FFmpeg開發教程(1) --- 過濾器中涉及的主要函數說明

       本系列文章居於FFMpeg源碼4.1版本,因此,有些流程和老版本會有稍微差別(源碼我做了詳細註釋,有需要請在下方評論留言,寫明郵箱,我會統一發給你們)。       

       上一節說了過濾器涉及到的主要結構說明,這一節我們介紹下FFMpeg中過濾器涉及到的主要函數說明,把結構和函數講完後,後面會從過濾器整體的機構來講解,因此,這兩節如果看不明白,只需要看個大概就行,後面說整體流程時會繼續介紹其在整個流程中的位置和功能。

     1) ff_filter_alloc

       此函數通過傳入的AVFilter和對應的名稱生成AVFilterContext,ACFilterContext記錄了AVFilter的詳細信息,加入我們定義如下:
   AVFilter* filter;
   ACFilterContext* filterCtx;
       那麼filterCtx中的nb_inputs表示了filter中的inputs數組中元素個數,filterCtx中的input_pads就是filter裏的inputs;對應的ouputs也是這樣賦值的。
       這個函數最後會調用AVFilter的preinit函數來對過濾器做預初始化。
       注意:對於buffer過濾器,其priv_class被定義爲buffer_class,最後這個buffer過濾器的私有數據會賦值給AVFilterContext的priv屬性(大家可以看下buffersrc.c文件實現,因爲buffer是ffmpeg過濾器的第一個,就是source filter,用於緩存AVFrame)。
       下面是buffer過濾器的AVFilter定義:
AVFilter ff_vsrc_buffer = {
    .name      = "buffer",
    .description = NULL_IF_CONFIG_SMALL("Buffer video frames, and make them accessible to the filterchain."),
    .priv_size = sizeof(BufferSourceContext),
    .query_formats = query_formats,

    .init      = init_video,
    .uninit    = uninit,

    .inputs    = NULL,
    .outputs   = avfilter_vsrc_buffer_outputs,
    .priv_class = &buffer_class,
};
       從上面結構可以看到,buffer過濾器是沒有實現preinit函數的,而且其只有outputs,說明buffer過濾只能是源(source)。

     2) avfilter_graph_alloc_filter

       此函數首先通過ff_filter_alloc創建AVFilter對應的上下文結構AVFilterContext,然後把創建的AVFilterContext加入AVFilterGraph的列表filters的末尾,同時nb_filters的值加1(就是AVFilter的個數加1)。

    3)avfilter_graph_create_filter

       此函數通過傳入的AFFilter信息(過濾器結構、名稱、參數等)創建一個過濾器的上下結構對象AVFilterContext,並把AVFilterContext加入負責管理過濾器的AVFilterGraph中,並設置過濾器的屬性參數。

    4)avfilter_link

       這個函數主要就是創建AVFilterLink結構,來把兩個過濾器給串聯起來,其屬性src表示上一個AVFilterContext,dst表示下一個AVFilterContext,srcpad表示src中output_pads指定索引的AVFilterPad,dstpad表示dst中output_pads指定索引的AVFilterPad,其中type就是srcpad.type的值;format初始化爲-1。
       這個函數裏還有一個比較關鍵的點,那就是初始化AVFilterLink的fifo隊列,這個隊列被初始化爲ff_framequeue_init(&link->fifo, &src->graph->internal->frame_queues);
       創建的這個AVFilterLink結構其實就是當前AVFilter和下一個AVFilter的連接器,它被保存在當前AVFilter的outputs中和下一個AVFilter的inputs中,這表示當前AVFilter的輸出就是下一個AVFilter的輸入。
       因此這個AVFilterLink保存有當前AVFilter和下一個AVFilter的所有信息。

   5)ff_filter_frame

       這個函數在源AVFilter處理完幀後調用,然後把處理後的AVFrame放入AVFilterLink的fifo隊列,同時設置下一個AVFilter的ready優先級(必須大於0,這裏設置的是300、200等),當AVFilterGraph再次進行調度時會取出優先級最高的AVFilter來進行處理。

   6)avfilter_graph_alloc

       分配AVFilterGraph對象,此對象負責管理加入的所有過濾器。

   7)avfilter_graph_free

       是否過濾器管理對象。

   8)av_buffersrc_add_frame

       把需要處理的幀加入到buffer過濾器,注意,buffer過濾器是AVFilterGraph中第一個過濾器,其只有輸出沒有輸入。

   9)av_buffersink_get_frame_flags

       獲取從AVFilterGraph管理的過濾器對象處理的幀AVFrame,此過程會經過所有的過濾器處理,最終處理的結果放入buffersink過濾器裏的,因此這個buffersink過濾器是AVFilterGraph管理的過濾器中最後的一個過濾器,其只有輸入,沒有輸出。

   10)get_frame_internal

       由av_buffersink_get_frame_flags調用獲取最終處理好的AVFrame。

   11)ff_filter_graph_run_once

       這個函數主要是從AVFilterGraph中找到優先級最大的一個AVFilterContext過濾器,然後使用此過濾器處理幀。

   12)ff_filter_activate

       此函數一般由ff_filter_graph_run_once調用,因爲ff_filter_graph_run_once負責找到優先級最大的過濾器,然後傳給這個函數,然後此函數依次調用其輸入inputs的filter_frame對輸入的AVFrame進行處理,如果沒有輸入數據處理了,則調用其outputs的request_frame來把其處理後的幀交給下一個過濾器處理。

   13)ff_filter_activate_default

       如果我們沒有定義過濾器激活函數,則使用這個默認的激活函數來調用激活當前過濾器對數據進行處理。

   14)ff_filter_frame_to_filter ff_filter_frame_framed

       這個函數主要處理過濾器的輸入數據,如果過濾器實現了filter_frame,則調用filter_frame處理輸入的幀,否則直接把輸入的幀交給下一個過濾器(調用默認實現)。

   15)ff_request_frame_to_filter

       此函數主要處理過濾器的輸出數據(已經調用了ff_filter_frame_framed處理了輸入數據),其調用request_frame來做預處理,比如設置下一個過濾器的優先級(設置一個大於0的數,表示過濾器下一步需要激活),如果沒有實現request_frame,則調用默認實現函數ff_request_frame處理。

       本系列文章均爲原創,主要總結作者多年在軟件行業的一些經驗,和大家共同學習、進步,轉載請註明出處,謝謝!

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