0

I am trying to encode a mpeg2video stream and a signed PCM 32 bit audio stream to a .mov file using ffmpeg's avcodec and avformat libraries.

My video stream is set up in almost the exact same way as is described here with my audio stream being set up in a very similar way.

My time_base for both audio and video is set to 1/fps.

Here is the overview output from setting up the encoder:

Output #0, mov, to '~/Recordings/SDI_Video.mov':
Metadata:
encoder : Lavf59.27.100
Stream #0:0: Video: mpeg2video (m2v1 / 0x3176326D), yuv420p, 1920x1080, q=2-31, 207360 kb/s, 90k tbn
Stream #0:1: Audio: pcm_s32be (in32 / 0x32336E69), 48000 Hz, stereo, s32, 3072 kb/s

As I understand it my pts should be when the frame is presented while dts should be when the frame is decoded. This means that audio and video frame pts should be the same whereas dts should be incremental between them.

Essentially meaning interleaved audio and video frames should be in the following pts and dts order:

pts 112233 dts 123456

I am using this format to set my pts and dts:

videoFrame->pts = frameCounter;
    
if(avcodec_send_frame(videoContext, videoFrame) < 0)
{
    std::cout << "Failed to send video frame " << frameCounter << std::endl;
    return;
}
    
AVPacket videoPkt;
av_init_packet(&videoPkt);
videoPkt.data = nullptr;
videoPkt.size = 0;
videoPkt.flags |= AV_PKT_FLAG_KEY;
videoPkt.stream_index = 0;
videoPkt.dts = frameCounter * 2;
    
if(avcodec_receive_packet(videoContext, &videoPkt) == 0)
{
    av_interleaved_write_frame(outputFormatContext, &videoPkt);
    av_packet_unref(&videoPkt);
}

With audio the same except:

audioPkt.stream_index = 1;
audioPkt.dts = frameCounter * 2 + 1;

However, I still get problems with my dts setting shown in this output:

[mov @ 0x7fc1b3667480] Application provided invalid, non monotonically increasing dts to muxer in stream 0: 1 >= 0
[mov @ 0x7fc1b3667480] Application provided invalid, non monotonically increasing dts to muxer in stream 0: 2 >= 1
[mov @ 0x7fc1b3667480] Application provided invalid, non monotonically increasing dts to muxer in stream 0: 3 >= 2

I would like to fix this issue.

WalleyM
  • 172
  • 7

1 Answers1

0

I have since found out there are a couple of problems with this code.

Firstly DTS and PTS should be set independent of other streams in the AVFormatContext. This means we can set independent time_bases where video time_base is 1/fps and audio is 1/samplerate. We then increase DTS and PTS by the same amount for each stream. The values must increase by number of samples for audio and by a specific value dependant on fps for video. These values can be found here.

The second problem, and the one that was causing the pts/dts error message, is that avcodec_receive_packet() resets the stream_index parameter of the packet that is passed in. This meant that the audio packets were attempting to be written to the video stream due to the stream_index being set to 0. Since the DTS values were not increasing with every packet in that stream as expected, the write function was throwing the error.

The way to get around this is to initialise the stream_index parameter directly before calling av_interleaved_write_frame() rather than before the if statement.

WalleyM
  • 172
  • 7