//在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: