Audio and video project—Audio and video player analysis based on FFmpeg and SDL (8)

introduce

In this series, I plan to spend a lot of time explaining my gitee project audio and video player. In this project, you can learn audio and video decapsulation, decoding, and SDL rendering related knowledge. If you are interested in the source code, please check out the audio and video player based on FFmpeg and SDL

If you don’t understand this article, you can refer to my previous article Audio and Video Project— Audio and Video Player Analysis Based on FFmpeg and SDL (7)

parse

There is one function that has not yet been analyzed above. This article will discuss the Run function of decodethread. This function is responsible for the running of the decode thread, so it is very important, so I will talk about it last.

void DecodeThread::Run(){
    AVFrame* frame = av_frame_alloc();
    while (abort != 1)
    {
        if(frame_queue->Size() > 10){
            this_thread::sleep_for(chrono::milliseconds(10));
            continue;
        }
        AVPacket* pack = packet_queue->Pop(10);
        if(pack){
            int ret = avcodec_send_packet(codec_ctx, pack);
            av_packet_free(&pack);
            if(ret < 0){
                break;
            }

            while (true) {
                ret = avcodec_receive_frame(codec_ctx, frame);
                if(ret == 0){
                    frame_queue->Push(frame);
                    continue;
                }else if (AVERROR(EAGAIN) == ret) {
                    break;
                }else {
                    abort = 1;
                    break;
                }
            }
            
        }else {
            perror("not got packet");
        }
    }
}

First of all, we need to understand the purpose of decoding, which is to extract the frame data from the packet (Packet) and put it into the corresponding queue.

So, we first declare a local variable AVFrame and use av_frame_alloc to allocate memory without further explanation.

Then, there is a while loop. When the flag abort is not equal to 1, the code is continuously run in a loop.

Then we continue to look at this code:

if(frame_queue->Size() > 10){
   this_thread::sleep_for(chrono::milliseconds(10));
   continue;
}

This code means that if the length of the frame queue exceeds 10, the thread will stop for 10 milliseconds. As for why this is so, I am not sure yet. I hope there are experts who can give me some guidance.

Then extract the packet data:

AVPacket* pack = packet_queue->Pop(10);

This Pop is customized, and its function is to delete the head of the queue and return it, so the AVPacket variable pack obtains the head of the queue, and the queue also deletes the head.

Then there is a conditional judgment. If the data in pack is not empty, execution will continue, otherwise the program will stop.

This is the logic when pack is not empty

int ret = avcodec_send_packet(codec_ctx, pack);
av_packet_free(&pack);
if(ret < 0){
   break;
}

Send pack to context via avcodec_send_packet, abort if error occurs.

Then there is an infinite loop:

while (true) {
       ret = avcodec_receive_frame(codec_ctx, frame);
       if(ret == 0){
          frame_queue->Push(frame);
          continue;
       }else if (AVERROR(EAGAIN) == ret) {
                 break;
       }else {
           abort = 1;
           break;
       }
}

Through the decoder context that just received the packet data, use avcodec_receive_frame to receive the decoded frame (Frame).

Then start the conditional judgment. If the frame is successfully received, it will be placed in the frame queue and continue running. Otherwise, the infinite loop is terminated.

Okay, we have finished talking about the last function Run of decodethread. This is more important and contains more content. You can understand it slowly.

In the next article, we will explain Queue.

If you want to know what happened next, please listen to the breakdown next time.

Guess you like

Origin blog.csdn.net/weixin_60701731/article/details/134450171