[FFmpeg combat] FFplay serial number analysis

Author: Loken1 Link: https://juejin.cn/post/7155351642731855909

The serial number is mainly prepared for the fast forward and rewind functions. If you can't fast forward or rewind, you don't actually need a serial number. As long as the demultiplexing thread continues to read the AVPacket and puts it into the PacketQueue queue, the decoding thread continues to fetch data from the PacketQueue to decode and put it into the FrameQueue, and finally there is a playback thread to fetch the data from the FrameQueue for playback.

The overall flow chart is as follows:

img

PacketQueue and FrameQueue are both cache queues, which first extract the data that is ready for use. But just because the fast forward and rewind functions are added, once the playback jumps to another time point, will the previously prepared data become unusable?

Therefore, a serial number is needed to determine whether the previously cached data is the latest, so the serial number can be regarded as the same thing as the version number .

FFplay player mainly has 4 serial number fields, which are as follows:

1. Serial of struct PackeQueue, which is the serial number of the queue itself. It can be regarded as the value of the latest serial number.

2. The serial of struct MyAVPacketList is the serial number of the AVPacket in the queue.

3. pkt_serial of struct Decoder records the serial number of the AVPacket used by the decoder last time to decode.

4. The serial of struct Frame, the serial number of AVFrame in the queue.

First, the serial source of MyAVPacketList and the serial of PackeQueue can be seen in the packet_queue_put_private() function:

img

Frame's serial is derived from Decoder's pkt_serial, as follows:

img

And where does the pkt_serial in the Decoder structure come from?

Answer: The value is assigned in decoder_decode_frame(). What is recorded is the serial number of the most recent AVPacket input to the decoder, as follows:

img

Therefore, it can be said that Frame's serial is indirectly derived from AVPacket's serial.

Now that we have understood the places where the four serial numbers are assigned, what codes are these four serial number fields used in?

Answer: As long as the logic related to caching is concerned, the serial number will be determined.

Because the serial number is prepared for the fast forward and rewind functions, let’s briefly explain the logic of fast forward and rewind. For a more detailed analysis, please see " FFplay Jump Time Point Playback ".

When you press one of the up, down, left, or right keys, a seek operation will occur, which is implemented by calling the stream_seek() function, as follows:

img

The code of the stream_seek() function is as follows:

/* seek in the stream */
static void stream_seek(VideoState *is, int64_t pos, int64_t rel, int seek_by_bytes)
{
    if (!is->seek_req) {
        is->seek_pos = pos;
        is->seek_rel = rel;
        is->seek_flags &= ~AVSEEK_FLAG_BYTE;
        if (seek_by_bytes)
            is->seek_flags |= AVSEEK_FLAG_BYTE;
        is->seek_req = 1;
        SDL_CondSignal(is->continue_read_thread);
    }
}

The focus of the above code is to set the is->seek_req tag and where to jump to play. Then the read_thread() thread will be woken up. When the read_thread() thread sees the is->seek_req mark, it will start the seek operation. as follows:

Therefore, the real place where the seek operation is performed is in the read_thread() demultiplexing thread, not the main thread.

img

As can be seen from the above figure, after using avformat_seek_file() to perform a seek operation, the packet_queue_flush() function will be called to refresh the sequence number to achieve the effect of discarding the previous invalid cache.

packet_queue_flush() is a very important function, the code is as follows:

img

As you can see, the data in the PacketQueue queue is cleared at the beginning, and then the sequence number is +1.

I personally have a question. Since the data has been cleared before +1, the decoding thread does not need to determine the sequence number at all when fetching data from PakcetQueue. Because it has been cleared, the decoding thread cannot get the old AVPacket.

Ignore this for now, anyway, the serial number of PacketQueue has been refreshed.

The serial sequence number of the PacketQueue queue itself is refreshed by +1, which will cause a series of chain reactions .

First of all, the serial of MyAVPacketList added to the PacketQueue queue by the subsequent demultiplexing thread will also be the latest. However, the pkt_serial in the decoding manager (struct Decoder) is still the old value.

As mentioned before, the pkt_serial of struct Decoder records the serial number of the last decoded AVPacket.

This will lead to directly abandoning the cache in the decoder and using the new AVPacket for decoding, as follows:

img

It will also cause the decoder's cache to be flushed, as follows:

img

The logic of the above figure is that as long as the serial number of the AVPacket decoded this time is different from the serial number of the AVPacket used last time, the decoder cache will be refreshed immediately .

Another area affected by chaining is the logic of reading FrameQueue. FrameQueue is different from PakcetQueue. FrameQueue itself does not have a serial number, but the struct Frame in its queue has a serial number, so it will also be affected, as follows:

img

It can be seen that when the audio playback thread fetches data, it will determine whether the serial number of the Frame is the latest, and if not, it will be discarded immediately.

There is another application scenario for serial numbers, and that is clock, as follows:

typedef struct Clock {
       ...
    int serial;           /* clock is based on a packet with this serial */
    ...
    int *queue_serial;    /* pointer to the current packet queue serial, used for obsolete clock detection */
} Clock;

This scenario is used when synchronizing audio and video, which is a bit complicated. When we explain audio and video synchronization later, we will analyze the serial number in Clock.

  >>> 音视频开发 视频教程: https://ke.qq.com/course/3202131?flowToken=1031864 
  >>> 音视频开发学习资料、教学视频,免费分享有需要的可以自行添加学习交流群 739729163 领取

Guess you like

Origin blog.csdn.net/weixin_52622200/article/details/131684966