4

ビデオを多重化するためにlibavformatのみを使用する簡単な実例が欲しいです。libavcodec でのエンコード、libavformat での多重化、libavio でのデータの保存を示す素敵な例 ( doc/examples/muxing.c ) があります。ただし、libavformat を単独で使用し、バッファ内のエンコードされたデータをフィードし、バッファ内の多重化されたデータを取得する例は私が知っているものはありません。

難しさは 2 つあります。1 つは、ストリームを追加するavformat_new_stream(AVFormatContext *s, const AVCodec *c)にはコーデックへの参照が必要です。2 つ目は、多重化からの出力が に渡されAVFormatContext->pbますAVIOContext*。したがって、libavformat を他の libav ライブラリから解放する (明白な) 方法はないようです。

参照: この質問では、libavio を使用しない方法について言及しています: Get TS packet into buffer from libavformat

4

1 に答える 1

7

libavcodec ライブラリへの依存を回避できますが、ヘッダー ファイル (avcodec.h など) が必要です。

スキームは次のとおりです。

AVOutputFormat * oFmt= ::av_guess_format("mp4", NULL, NULL);
AVFormatContext *oFmtCtx = NULL;
::avformat_alloc_output_context2(&oFmtCtx, oFmt, NULL, NULL);
AVStream * oStrm = ::avformat_new_stream(oFmtCtx, NULL);
AVCodecContext * strmCodec = oFmtCtx->streams[0]->codec;

// Fill the required properties for codec context.
// *from the documentation:
// *The user sets codec information, the muxer writes it to the output.
// *Mandatory fields as specified in AVCodecContext
// *documentation must be set even if this AVCodecContext is
// *not actually used for encoding.
my_tune_codec(strmCodec); 

if (oFmtCtx->oformat->flags & AVFMT_NOFILE)
{
  ::avio_open2(&oFmtCtx->pb, fileName, AVIO_FLAG_WRITE, NULL, NULL);
}
::avformat_write_header(oFmtCtx, NULL);
// .....
// writing loop
// .....
::av_write_trailer(oFmtCtx);
::avio_close(oFmtCtx->pb);
::avformat_free_context(oFmtCtx);

出力を得るには、常に の概念を使用する必要がありAVIOContextます。組み込みプロトコルの使用を避けることができます。これを行うには、独自のAVIOContext( ::avio_alloc_context) を作成する必要があります。

UPD 独自の を作成するには、次のAVIOContextようにする必要があります

#include <stdio.h>
extern "C" {
#include <libavformat/avio.h>
#include <libavformat/avformat.h>
}

static const int kBufferSize = 32768;

class my_iocontext_private
{
public:
    my_iocontext_private(FILE * f) : buffer_size_(kBufferSize),
        buffer_(static_cast<unsigned char*>(::av_malloc(buffer_size_))), f_(f) {
        ctx_ = ::avio_alloc_context(buffer_, buffer_size_, AVIO_FLAG_WRITE, this, 
            &my_iocontext_private::read, &my_iocontext_private::write, &my_iocontext_private::seek);
    }

    ~my_iocontext_private()    { av_free(buffer_); }

    static int read(void *opaque, unsigned char *buf, int buf_size) {
        my_iocontext_private* h = static_cast<my_iocontext_private*>(opaque);
        return fread(buf, 1, buf_size, h->f_);
    }

    static int write(void *opaque, unsigned char *buf, int buf_size) {
        my_iocontext_private* h = static_cast<my_iocontext_private*>(opaque);
        return fwrite(buf, 1, buf_size, h->f_);
    }

    static int64_t seek(void *opaque, int64_t offset, int whence) {
        my_iocontext_private* h = static_cast<my_iocontext_private*>(opaque);

        // use lseeki64 instead of fseek
        return fseek(h->f_, static_cast<long>(offset), whence);        
    }
    ::AVIOContext *get_avio() { return ctx_; }

private:
    int buffer_size_;
    unsigned char * buffer_;  
    FILE * f_;
    ::AVIOContext * ctx_;
};

int main(int argc, char* argv[])
{
    FILE * f = fopen("myfile.dmp", "wb");    
    my_iocontext_private priv_ctx(f); 

    AVFormatContext * ctx = ::avformat_alloc_context();
    ctx->pb = priv_ctx.get_avio();

    /// using ctx

    fclose(f); 
    return 0;
}
于 2012-11-30T09:36:04.360 に答える