如何使用libavformat而不使用其他libav库? [英] How can libavformat be used without using other libav libraries?

查看:842
本文介绍了如何使用libavformat而不使用其他libav库?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要一个使用libavformat到mux视频的简单工作示例。有很好的例子( doc / examples / muxing.c ),显示编码使用libavcodec,使用libavformat进行复制,并使用libavio保存数据。然而,没有一个例子,我知道它使用libavformat本身,喂入缓冲区中的编码数据,并在缓冲区中获取多路复用数据。



fold:一个,添加一个流 avformat_new_stream(AVFormatContext * s,const AVCodec * c)需要引用编解码器;和两个,muxing的输出被传递给 AVFormatContext-> pb 这是一个 AVIOContext * 。因此,似乎没有(显而易见的)从其他libav库中提取libavformat的方法。



另请参见:此问题提到了一种不使用libavio的方法:从libavformat获取TS数据包到缓冲区

解决方案

您可以避免对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;

//填写编解码器上下文所需的属性。
// *从文档:
// *用户设置编解码器信息,muxer将其写入输出。
// * AVCodecContext
// *文件中指定的必填字段必须设置,即使AVCodecContext是
// *实际上不用于编码。
my_tune_codec(strmCodec);

if(oFmtCtx-> oformat-> flags& AVFMT_NOFILE)
{
:: avio_open2(& oFmtCtx-> pb,fileName,AVIO_FLAG_WRITE,NULL,空值);
}
:: avformat_write_header(oFmtCtx,NULL);
// .....
//写循环
// .....
:: av_write_trailer(oFmtCtx);
:: avio_close(oFmtCtx-> pb);
:: avformat_free_context(oFmtCtx);

要获得输出,您必须使用 AVIOContext 。您可以避免使用内置协议。为此,您需要创建自己的 AVIOContext :: avio_alloc_context )。



UPD
要创建您自己的 AVIOContext ,您必须执行此操作

  #include< stdio.h> 
externC{
#include #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)

//使用lseeki64而不是fseek
return fseek(h-> f_,static_cast< long>(offset),whichce);
}
:: 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();

///使用ctx

fclose(f);
return 0;
}


I would like a simple working example of using just libavformat to mux video. There are nice examples (doc/examples/muxing.c) that show encoding with libavcodec, muxing with libavformat and saving the data with libavio. However, there is no example I know of that uses libavformat by itself, feeding in encoded data in a buffer and getting muxed data in a buffer.

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

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

解决方案

You can avoid dependencies on libavcodec library, but you need the header files (for example, 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 output, you always have to use the concept of AVIOContext. You can avoid using the built-in protocols. To do this you need to create your own AVIOContext (::avio_alloc_context).

UPD To create your own AVIOContext, you have 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;
}

这篇关于如何使用libavformat而不使用其他libav库?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆