How can libavformat be used without using other libav libraries?

I need a simple working example of using only libavformat for a multiplexer. There are good examples ( doc / examples / muxing.c ) that show encoding with libavcodec, muxing with libavformat, and saving data with libavio. However, there is no example that I know that uses libavformat on its own, feeding encoded data to the buffer and receiving multiplexed data in the buffer.

The difficulty is twofold: one, adding a stream with avformat_new_stream(AVFormatContext *s, const AVCodec *c) requires a link to the codec; and two, the output from muxing is passed to AVFormatContext->pb , which is AVIOContext* . Thus, there seems to be no (obvious) way to extract libavformat from other libav libraries.

See also: This question mentions a way not to use libavio: Get TS packets to buffer from libavformat

+3
source share
1 answer

You can avoid libavcodec library dependencies, but you need header files (e.g. avcodec.h).

The scheme is as follows:

 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); 

To get the result, you should always use the concept of AVIOContext . You can avoid using built-in protocols. To do this, you need to create your own AVIOContext ( ::avio_alloc_context ).

UPD To create your own AVIOContext , you need to do something like this

 #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; } 
+6
source

All Articles