2、ffplay FrameQueue源碼分析

ffplay FrameQueue 源碼分析

一、FrameQueue結構

typedef struct FrameQueue {
    Frame queue[FRAME_QUEUE_SIZE];
    int rindex;//隊頭索引
    int windex;//隊尾索引
    int size;//隊列元素個數
    int max_size;//隊列最大容量
    int keep_last;//保留最後一幀數據
    int rindex_shown;
    SDL_mutex *mutex;
    SDL_cond *cond;
    PacketQueue *pktq;
} FrameQueue;

原理示意圖
framequeue原理示意圖

二、操作函數

包含如圖所示的方法
FrameQueue方法

主要分析隊列添加和移除元素功能

1、添加元素到隊列

  • 調用frame_queue_peek_writable(…)獲取隊列中的可用的Frame
  • 調用frame_queue_push(…)將隊尾索引++,元素個數++
static Frame *frame_queue_peek_writable(FrameQueue *f)
{
    /* wait until we have space to put a new frame */
    SDL_LockMutex(f->mutex);
    while (f->size >= f->max_size &&
           !f->pktq->abort_request) {// !f->pktq->abort_request條件讓隊列可被終止添加數據
        SDL_CondWait(f->cond, f->mutex);//渲染線程取走數據後,負責喚醒
    }
    SDL_UnlockMutex(f->mutex);

    if (f->pktq->abort_request)
        return NULL;

    return &f->queue[f->windex];
}

static void frame_queue_push(FrameQueue *f)
{
    if (++f->windex == f->max_size)
        f->windex = 0;//隊列尾索引大於等於max_size時重新回到0
    SDL_LockMutex(f->mutex);
    f->size++;//隊列中元素個數++,解碼線程和渲染線程均會操作,加鎖保護
    SDL_CondSignal(f->cond);//通知因隊列空而阻塞的渲染線程,隊列中有數據了
    SDL_UnlockMutex(f->mutex);
}

2、獲取隊列中的元素

  • 調用frame_queue_peek_readable(…)獲取當前隊頭的元素,隊列爲空將阻塞
  • frame_queue_next(…)將隊頭索引++,隊列元素個數–
static Frame *frame_queue_peek_readable(FrameQueue *f)
{
    /* wait until we have a readable a new frame */
    SDL_LockMutex(f->mutex);
    while (f->size - f->rindex_shown <= 0 &&
           !f->pktq->abort_request) {
        SDL_CondWait(f->cond, f->mutex);
    }
    SDL_UnlockMutex(f->mutex);

    if (f->pktq->abort_request)
        return NULL;

    return &f->queue[(f->rindex + f->rindex_shown) % f->max_size];
}

static void frame_queue_next(FrameQueue *f)
{
    if (f->keep_last && !f->rindex_shown) {
        f->rindex_shown = 1;
        return;
    }
    frame_queue_unref_item(&f->queue[f->rindex]);
    if (++f->rindex == f->max_size)
        f->rindex = 0;
    SDL_LockMutex(f->mutex);
    f->size--;//解碼線程和渲染線程均會操作,加鎖保護
    SDL_CondSignal(f->cond);//通知因隊列滿而阻塞的解碼線程,隊列有空間了
    SDL_UnlockMutex(f->mutex);
}

線程均會操作,加鎖保護
    SDL_CondSignal(f->cond);//通知因隊列滿而阻塞的解碼線程,隊列有空間了
    SDL_UnlockMutex(f->mutex);
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章