gpt4 book ai didi

c++ - 将 AVPackets 混合到 mp4 文件中

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:39:56 25 4
gpt4 key购买 nike

我正在开发一种工具,它从网络接收 h.264 实时流(发送方是硬件编码器),缓冲最后 x 分钟并在触发时创建最后 x 分钟的视频文件。

我的工具能够接收实时流,还可以使用 boost::serialization 缓冲 AVPackets。此外,我能够加载缓冲的 AVPackets。

但是当我尝试使用加载的 AV 数据包创建/混合视频文件 (mp4) 时,mp4 文件或 mp4 header 中出现错误。我能够创建一个 mp4 文件,还可以使用 av_interleaved_write_frame() 将数据包写入该文件。 mp4 文件也有合理的大小。因此,AVPackets 似乎已写入文件。

但是当我尝试用像 vlc 这样的播放器打开 mp4 文件时,视频无法播放。播放器提供如下错误: header 不正确且不播放任何帧。但是我使用 writeHeader() 函数将 header 写入 AVFormatContext。

我猜是因为 AVFormatContext 没有正确初始化,但是以 ffmpeg/libav (muxing-examples) 为例,我无法解决问题。

有没有解决方案(示例代码)或其他示例如何正确初始化 AVFormatContext?

感谢您的帮助。奥尔根

    avcodec_init();
avcodec_register_all();
av_register_all();
av_log_set_level(AV_LOG_DEBUG);

char *outputFilename = "/tmp/output.mp4";

// define AVOutputFormat
AVOutputFormat *outputFormat = NULL;
outputFormat = av_guess_format("mp4", NULL, NULL);
if (!outputFormat) {
fprintf(stderr, "Could not find suitable output format\n");
return 1;
}

// define AVFormatContext
AVFormatContext *formatContext = NULL;
// lallocate the output media context
std::cout << "alloc" << std::endl;
formatContext = avformat_alloc_context();
// avformat_alloc_output_context(&formatContext, outputFormat, NULL, NULL);
if (!formatContext) {
fprintf(stderr, "Memory error\n");
return 1;
}
std::cout << "stream" << std::endl;
AVStream * video_st = av_new_stream(formatContext, 0);
AVCodec * codec = NULL;
avcodec_get_context_defaults3(video_st->codec, codec);
video_st->codec->coder_type = AVMEDIA_TYPE_VIDEO;

video_st->codec->flags = fc->streams[0]->codec->flags;
video_st->codec->sample_aspect_ratio = fc->streams[0]->codec->sample_aspect_ratio;
video_st->disposition = fc->streams[0]->disposition;
video_st->codec->codec_tag = fc->streams[0]->codec->codec_tag;
video_st->codec->bits_per_raw_sample = fc->streams[0]->codec->bits_per_raw_sample;
video_st->codec->chroma_sample_location = fc->streams[0]->codec->chroma_sample_location;
video_st->codec->codec_id = fc->streams[0]->codec->codec_id;
video_st->codec->codec_tag = fc->streams[0]->codec->codec_tag;
video_st->codec->time_base = fc->streams[0]->codec->time_base;
video_st->codec->extradata = fc->streams[0]->codec->extradata;
video_st->codec->extradata_size = fc->streams[0]->codec->extradata_size;
video_st->codec->pix_fmt = fc->streams[0]->codec->pix_fmt;
video_st->codec->width = fc->streams[0]->codec->width;
video_st->codec->height = fc->streams[0]->codec->height;
video_st->codec->sample_aspect_ratio = fc->streams[0]->codec->sample_aspect_ratio;


std::cout << "file" << std::endl;
avio_open(&formatContext->pb, outputFilename, AVIO_FLAG_WRITE);
std::cout << "header" << std::endl;
avformat_write_header(formatContext, NULL);
// av_write_header(formatContext);

// loop to write AVPackets with av_write_frame

程序在 avformat_write_header(formatContext, NULL) 之后崩溃并出现内存错误。我还尝试了 avformat_alloc_output_context() 而不是 avformat_alloc_output_context2() 但这两个函数都不起作用。所以我使用了 avformat_alloc_context() (见上文)

我认为存在分配问题,但为什么我不能使用 avformat_alloc_output_context2 或 avformat_alloc_output_context。有人可以解决我的问题吗?

最佳答案

这是一个通用方案,展示了如何从现有数据包中复用视频文件

AVOutputFormat * outFmt = av_guess_format("mp4", NULL, NULL);
AVFormatContext *outFmtCtx = NULL;
avformat_alloc_output_context2(&outFmtCtx, outFmt, NULL, NULL);
AVStream * outStrm = av_new_stream(outFmtCtx, 0);

AVCodec * codec = NULL;
avcodec_get_context_defaults3(outStrm->codec, codec);
outStrm->codec->coder_type = AVMEDIA_TYPE_VIDEO;

///....
/// set some required value, such as
/// outStrm->codec->flags
/// outStrm->codec->sample_aspect_ratio
/// outStrm->disposition
/// outStrm->codec->codec_tag
/// outStrm->codec->bits_per_raw_sample
/// outStrm->codec->chroma_sample_location
/// outStrm->codec->codec_id
/// outStrm->codec->codec_tag
/// outStrm->codec->time_base
/// outStrm->codec->extradata
/// outStrm->codec->extradata_size
/// outStrm->codec->pix_fmt
/// outStrm->codec->width
/// outStrm->codec->height
/// outStrm->codec->sample_aspect_ratio
/// see ffmpeg.c for details

avio_open(&outFmtCtx->pb, outputFileName, AVIO_FLAG_WRITE);

avformat_write_header(outFmtCtx, NULL);

for (...)
{
av_write_frame(outFmtCtx, &pkt);
}

av_write_trailer(outFmtCtx);
avio_close(outFmtCtx->pb);
avformat_free_context(outFmtCtx);

对于故障排除,设置详细的日志记录很有用:av_log_set_level(AV_LOG_DEBUG);

关于c++ - 将 AVPackets 混合到 mp4 文件中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19679833/

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