'Replacing deprecated AVStream codec parameter in libav

A long time ago, I implemented a C++ class to create MP4 video files from an array of images. The code works pretty well, nevertheless, I discovered a deprecation warning that I want to rid off. The parameter "codec" from the AVStream structure has been deprecated and I want to replace it.

Here is my current working code:

AVOutputFormat *outputFormat = av_guess_format("ffh264", movieFile.toLocal8Bit().data(), nullptr);
if (!outputFormat)
    return false;

enum AVCodecID videoCodecID = outputFormat->video_codec;

AVCodec *videoCodec = avcodec_find_encoder(videoCodecID);
if (!videoCodec)
    return false;

AVStream *stream = avformat_new_stream(formatContext, videoCodec);
if (!stream)
    return false;

AVCodecContext *videoCodecContext = stream->codec; // <- codec is a deprecated parameter

videoCodecContext->width = videoW;
videoCodecContext->height = videoH;

Now, to replace the "codec" parameter, the libav developers team recommends using the parameter "codecpar" (AVCodecParameters) that was included in the AVStream structure. The example they use to share is this:

if (avcodec_parameters_to_context(videoCodecContext, stream->codecpar) < 0)
    return nullptr;

Note: codecpar (AVCodecParameters) is a data structure itself.

Unfortunately, when I try to use that code, I got this problem: usually, all the information stored in the codecpar parameter comes from the data structure from a previous video file that was opened previously. In other words, the information already exists. In my case, the situation is different because I am creating an MP4 file from scratch so there is no previous codecpar record to use, therefore I have to create a new instance of AVCodecParameters structure by myself, setting every variable manually.

As far, I was able to set all the variables from the codecpar structure, except for two:

uint8_t * extradata 
int       extradata_size

Note: currently I can create an MP4 file "successfully" without setting those variables, but the file is incomplete and when I try to play it using "mplayer" I got this error message:

[extract_extradata @ 0x55b5bb7e45c0] No start code is found.

I was researching these two fields, and it seems they store some kind of information related to the codec, which in my case is H264.

So, my specific question is: if I am setting a codecpar variable (AVCodecParameters) from scratch, how can I set values for the fields extradata and extradata_size in the right way for the codec H264?



Solution 1:[1]

Solution:

This is a basic list of steps I followed to replace the deprecated stream->codec data structure successfully:

  1. Initialize AVFormatContext, AVOutputFormat variables (using av_guess_format and avformat_alloc_output_context2)

  2. Open video codec (using avcodec_find_encoder)

  3. Add/Initialize AVStream variable (using avformat_new_stream)

  4. Initialize AVCodecContext variable (using avcodec_alloc_context3)

  5. Customize AVCodecContext parameters, only if you need to. (In example: width, height, bit_rate, etc)

  6. Add this piece of code:

    if (formatContext->oformat->flags & AVFMT_GLOBALHEADER)
        videoCodecContext->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
    
  7. Open AVCodecContext variable (using avcodec_open2)

  8. Copy AVCodecContext codecpar structure into AVStream codecpar (using avcodec_parameters_from_context)

From this point, you will be able to create and add frames to your output file.

PS: The example I used as a reference to code this implementation is available on doc/examples/muxing.c

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 xtingray