FFmepg 多线程解码历程 - 7:submit_packet

//在ff_thread_decode_frame中会调用submit_packet将码流交给对应的解码线程,来实现线程状态的改变,具体的流程图见下面图

static int submit_packet(PerThreadContext *p, AVPacket *avpkt)

{
    FrameThreadContext *fctx = p->parent;
    PerThreadContext *prev_thread = fctx->prev_thread;
    const AVCodec *codec = p->avctx->codec;

    if (!avpkt->size && !(codec->capabilities & CODEC_CAP_DELAY)) return 0;

    pthread_mutex_lock(&p->mutex);

    release_delayed_buffers(p);

    if (prev_thread) {
        int err;
        if (prev_thread->state == STATE_SETTING_UP) {
            pthread_mutex_lock(&prev_thread->progress_mutex);
            while (prev_thread->state == STATE_SETTING_UP)  //判断之前的线程状态为STATE_SETTING_UP的时候,进行线程的等待,
                pthread_cond_wait(&prev_thread->progress_cond, &prev_thread->progress_mutex);
            pthread_mutex_unlock(&prev_thread->progress_mutex);
        }

        err = update_context_from_thread(p->avctx, prev_thread->avctx, 0);//如果之前的线程状态变为STATE_SETUP_FINISHED,然后从线程中哦功能更新内容
        if (err) {
            pthread_mutex_unlock(&p->mutex);
            return err;
        }
    }

    av_buffer_unref(&p->avpkt.buf);
    p->avpkt = *avpkt;
    if (avpkt->buf)
        p->avpkt.buf = av_buffer_ref(avpkt->buf);
    else {
        av_fast_malloc(&p->buf, &p->allocated_buf_size, avpkt->size + FF_INPUT_BUFFER_PADDING_SIZE);
        p->avpkt.data = p->buf;
        memcpy(p->buf, avpkt->data, avpkt->size);
        memset(p->buf + avpkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
    }

    p->state = STATE_SETTING_UP;
    pthread_cond_signal(&p->input_cond);//发送码流输入准备好的信号给解码线程pthread_cond_waite(&p->input_cond),让解码线程
    pthread_mutex_unlock(&p->mutex);

    /*
     * If the client doesn't have a thread-safe get_buffer(),
     * then decoding threads call back to the main thread,
     * and it calls back to the client here.
     */

    if (!p->avctx->thread_safe_callbacks && (
#if FF_API_GET_BUFFER
         p->avctx->get_buffer ||
#endif
         p->avctx->get_buffer2 != avcodec_default_get_buffer2)) {
        while (p->state != STATE_SETUP_FINISHED && p->state != STATE_INPUT_READY) {
            pthread_mutex_lock(&p->progress_mutex);
            while (p->state == STATE_SETTING_UP)
                pthread_cond_wait(&p->progress_cond, &p->progress_mutex);

            if (p->state == STATE_GET_BUFFER) {
                p->result = ff_get_buffer(p->avctx, p->requested_frame, p->requested_flags);
                p->state  = STATE_SETTING_UP;
                pthread_cond_signal(&p->progress_cond);
            }
            pthread_mutex_unlock(&p->progress_mutex);
        }
    }

    fctx->prev_thread = p;
    fctx->next_decoding++;

    return 0;

}

主线程接收数据,准备完毕后发出pthread_cond_signal(&p->input_cond)信号,然后解码线程接收到以后,设置线程状态为finish_setup,发送广播p->process_cond,进行解码,

解码线程解完以后,发送p->progress_cond信号,主线程回调,从解码线程中获取get_buffer,解码之后的数据,然后发送p->progress_cond信号给解码线程,然后解码线程发出p->output_cond信号给主线程,主线程输出解码之后的frame给用户


注释1:

FFmepg 多线程解码历程 - 7:submit_packet_第1张图片


你可能感兴趣的:(FFmepg 多线程解码历程 - 7:submit_packet)