【问题标题】:Initializing an output file for muxing mkv with FFmpeg使用 FFmpeg 初始化 mkv 的输出文件
【发布时间】:2019-10-30 09:17:56
【问题描述】:

我是第一次使用 ffmpeg,但在初始化 mkv 多路复用的输出文件时遇到了麻烦。 我按照on the middle of this page 的描述进行操作,但它不起作用。

当我调用 avformat_write_header() 函数时,它返回错误代码 -1094995529,这意味着:处理输入时发现无效数据。

当我将输出上下文分配为 mp4 格式(在这两种情况下我都使用 avformat_alloc_output_context2)时,我没有收到此错误,并且它成功写入了标题。 我试图分析the code of this example ,但我无法弄清楚问题是什么(我也尝试了不同的功能,但没有结果)。

这是我的代码:

const char *filename = "c:\\Users\\MPM\\Desktop\\test.mkv";
AVFormatContext *mkvVideo = NULL;

int ret = 0;
ret = avformat_alloc_output_context2(&mkvVideo, av_guess_format("matroska", "c:\\Users\\MPM\\Desktop\\test.mkv", NULL), "mkv", filename);

std::cout << "\n avformat_alloc_output_context2: " << ret<<"\n";

AVStream* video_stream = avformat_new_stream(mkvVideo, NULL);

video_stream->time_base.den = 25;
video_stream->time_base.num = 1;
video_stream->id = mkvVideo->nb_streams - 1;

video_stream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
video_stream->codecpar->codec_id = AV_CODEC_ID_H264;
video_stream->codecpar->bit_rate = 40000;
video_stream->codecpar->width = 1920;
video_stream->codecpar->height = 1080;
video_stream->codecpar->format = 0;

// AVCodec *video_codec = avcodec_find_encoder(AV_CODEC_ID_H264);
// AVCodecContext *codecCTx = NULL;

// codecCTx = avcodec_alloc_context3(video_codec);
// avcodec_get_context_defaults3(codecCTx, video_codec);

// ret = avcodec_parameters_to_context(codecCTx, video_stream->codecpar);
// std::cout << "\n avcodec_parameters_to_context: " << ret;

// codecCTx->framerate = { 25, 1 };
// codecCTx->gop_size = 12; 
// codecCTx->pix_fmt = AV_PIX_FMT_YUV420;
// codecCTx->max_b_frames = 1;
// codecCTx->codec_tag = 1;
// codecCTx->codec_type = AVMEDIA_TYPE_VIDEO;

std::cout << std::endl;
av_dump_format(mkvVideo, 0, filename, 1);

ret = avio_open(&mkvVideo->pb, "c:\\Users\\MPM\\Desktop\\test.mp4", AVIO_FLAG_READ_WRITE);
std::cout << "\n avio open: " << ret;

ret = avformat_write_header(mkvVideo, NULL);
std::cout << "\n ret: " << ret;

if (ret < 0)
    {
        char buffer[50];
        size_t bufsize = 50;
        av_strerror(ret, buffer, bufsize);
        std::cout << "\n error message: ";
        for (int i = 0; i < bufsize; i++) std::cout << buffer[i];
        exit(1);
    }

关于输出格式的打印输出数据(通过av_dump_format)如下:

Output #0, matroska, to 'c:\Users\\MPM\\Desktop\\test.mkv':
Stream #0:0: Video: h264, yuv420p, 1920x1080, q=2-31, 40 kb/s, 25 tbn

我认为它不起作用可能有两个原因:

  1. AVStream 缺少一些参数

  2. mkv 输出格式需要以不同方式初始化

那么谁能告诉我我做错了什么?

【问题讨论】:

    标签: c++ video ffmpeg libavformat mkv


    【解决方案1】:

    结果证明问题确实出在 H264 编解码器初始化上。 videostream->codecpar->extradata 字段必须分配并填充NAL units,它们是流参数。这样做是other complicated problem

    因为我的项目不需要流式传输,所以我只是用 avmalloc() 为 extradata 字段分配了一些空间,然后我就能够初始化输出文件了。

    【讨论】:

    • 尝试做 HLS -> MKV,请你给个提示,如何处理那里的额外数据?
    猜你喜欢
    • 1970-01-01
    • 2021-02-07
    • 1970-01-01
    • 2018-07-05
    • 2021-06-15
    • 1970-01-01
    • 2016-07-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多