-
Notifications
You must be signed in to change notification settings - Fork 391
avcodec_decode_video2 and got_picture_ptr #7
Description
Regarding frameFinished in https://github.com/mpenkov/ffmpeg-tutorial/blob/master/tutorial01.c#L150
It is worth noting here that frameFinished might result in missed frames. Consider the following frame format:
F1 F2 F3 F4
II BB BB PP
01 02 03 04 PTS (Presentation Time Stamp)
01 04 02 03 DTS (Decode Time Stamp)
In the above example, avcodec_decode_video2 would return got_frame with nonzero for the first frame, but what happens with the Bi-Predictive frame for frame 02? A Bi-Predictive frame requires both the previous frame and a frame somewhere after it. In this case, the frame it needs is in frame 04. So avcodec_decode_video2 will return got_frame with zero for frame 02 and 03, buffering the frames until it can properly decode them. At the point that it hits frame 04, it is now able to decode frame 02 and 03, and will return got_picture with a non-zero value.
01 02 03 04 05 06 Calls to avcodec_decode_video2
++ -- -- ++ ?? ?? got_picture_ptr returns zero on -- frames
01 -- -- 02 03 04 Order of returned frames
What does all this mean? By the time we reach the end of the file, although we have presented every frame we can decode in correct order, we will have ended up skipping a given number of frames for every B frame. The presentation will stop after decoding every frame, but not after processing every frame by our application!
As discussed, those frames are buffered internally. This means that at the end of the primary loop, every frame has been processed, and all of the information needed to process every B frame is now complete. For every time that got_picture returned zero, our buffer still grew by a frame, but avcodec_decode_video2 couldn't return it as it would be out of Presentation Time Stamp order. So where are those frames by the time we reach the end of this primary loop?
They are simply sitting buffered. To display all of the frames in the file, we must continue to call avcodec_decode_video2 after the primary loop until got_frame returns zero. This should be the number of times that got_picture returned zero.