Search code examples
c++ffmpeg

avcodec_open2 returns Invalid Argument (errnum -22)


I am trying to encode a vector of AVFrames to an MP4 file using the h264 codec.

Everything seems to work fine until the avcodec_open2 function, which returns an "Invalid Argument" (-22) error.

*The stream parameter is a pointer to AVStream.

Here is the code that sets the stream parameters:

    stream->codecpar->codec_id = AV_CODEC_ID_H264;
    stream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
    stream->codecpar->width = settings.resolution[0]; // 270
    stream->codecpar->height = settings.resolution[1]; // 480
    stream->codecpar->format = AV_PIX_FMT_YUV420P;
    stream->codecpar->bit_rate = 400000;
    AVRational framerate = { 1, 30};
    stream->time_base = av_inv_q(framerate);

And here is the code that opens the codec context:

    // Open the codec context
    AVCodecContext* codec_ctx = avcodec_alloc_context3(codec);
    if (!codec_ctx) {
        std::cout << "Error allocating codec context" << std::endl;
        avformat_free_context(format_ctx);
        return;
    }

    ret = avcodec_parameters_to_context(codec_ctx, stream->codecpar);
    if (ret < 0) {
        std::cout << "Error setting codec context parameters: " << av_err2str(ret) << std::endl;
        avcodec_free_context(&codec_ctx);
        avformat_free_context(format_ctx);
        return;
    }

    ret = avcodec_open2(codec_ctx, codec, nullptr);
    if (ret < 0) {
        wxMessageBox("Error opening codec: ");
        wxMessageBox(av_err2str(ret));
        avcodec_free_context(&codec_ctx);
        avformat_free_context(format_ctx);
        return;
    }

I tried the solution that @philipp suggested in ffmpeg-avcodec-open2-returns-invalid-argument but it didn't resolve my error.

I don't know what's causing this error in my code, can someone please help me?


Solution

  • It looks like codec_ctx->time_base is uninitialized.

    Before executing ret = avcodec_open2(codec_ctx, codec, nullptr);, add the following line of code:

    codec_ctx->time_base = stream->time_base;
    

    The default value of codec_ctx->time_base is {0, 0}, and that causes avcodec_open2 to return an error status.

    Note that executing avcodec_parameters_to_context(codec_ctx, stream->codecpar) doesn't copy the time_base, because time_base is not part of stream->codecpar.