gpt4 book ai didi

video - 不使用其他libav库如何使用libavformat?

转载 作者:行者123 更新时间:2023-11-28 21:41:11 34 4
gpt4 key购买 nike

我想要一个仅使用 libavformat 来混合视频的简单工作示例。有很好的示例 ( doc/examples/muxing.c ) 显示了使用 libavcodec 进行编码、使用 libavformat 进行多路复用以及使用 libavio 保存数据。但是,据我所知,没有一个例子单独使用 libavformat,在缓冲区中输入编码数据并在缓冲区中获取混合数据。

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

另见:这个问题提到了一种不使用 libavio 的方法:Get TS packets into buffer from libavformat

最佳答案

您可以避免依赖 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 的概念。您可以避免使用内置协议(protocol)。为此,您需要创建自己的 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;
}

关于video - 不使用其他libav库如何使用libavformat?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13634539/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com