Ffmpeg 1.0 contact分析

2014 10 27

Ffmpeg 1.0 contact分析

ffmpeg -y -i test.3gp -i test1.3gp -filter_complex 'concat' -c:v libx264 -an -strict -2 merge.3gp

注:test.3gptest1.3gp的分辨率大小一樣,爲了簡單起見只處理視頻部分。

 

由於avf_concat.c文件的ConcatContext結構的nb_segments缺省值爲2,所以在這個文件的init函數會創建2input_padsctx->nb_inputs=2。在後續的graphparser.c文件的avfilter_graph_parse2函數裏調用link_filter_inouts時,link_filter_inouts函數會linker兩個inputopen_inputs.

 

avfilter_graph_parse2函數後面會調用

   for (cur = inputs, i = 0; cur; cur = cur->next, i++)

        if ((ret = configure_input_filter(fg, fg->inputs[i], cur)) < 0)

            return ret;

從而調用了2configure_input_video_filter,創建了2buffer filter,如下:

 

Buffer(1)---

                    |--->concat--->format--->sink

Buffer(2)---

 

av_buffersrc_add_ref--->buffersrc.c::request_frame()--->ff_end_frame--->avf_concat.c:: end_frame--->process_frame--->push_frame(),push_frame函數的主要用處是根據當前輸入的input_padindex(就是代碼中的in_no)來進行pts計算。

 

transcode_from_filter--->avfilter_graph_request_oldest--->ff_request_frame---> avf_concat.c:: request_frame,request_frame函數裏有如下處理:

while (1) {

        if (in_no >= ctx->nb_inputs)

            return AVERROR_EOF;

        if (!cat->in[in_no].eof) {

            ret = ff_request_frame(ctx->inputs[in_no]);

            if (ret != AVERROR_EOF)

                return ret;

            close_input(ctx, in_no);

        }

可見,即使第一個文件的ff_request_frame返回爲AVERROR_EOF,改函數只是調用close_input來關閉第一個,繼續獲取第二個,這時候會返回EAGAIN。從而在transcode_from_filter函數不會調用close_output_stream來關閉結束整個編碼。transcode_from_filter函數又有如下代碼來將*best_ist指向第二個輸入文件:

    for (i = 0; i < graph->nb_inputs; i++) {

        ifilter = graph->inputs[i];

        ist = ifilter->ist;

        if (input_files[ist->file_index]->eagain ||

            input_files[ist->file_index]->eof_reached)

        {

                    av_log(NULL, AV_LOG_INFO, "transcode_from_filter contine\n");

                 continue;

        }

        nb_requests = av_buffersrc_get_nb_failed_requests(ifilter->filter);

        if (nb_requests > nb_requests_max) {

            nb_requests_max = nb_requests;

            *best_ist = ist;

        }

}

由於input_files[0]->eof_reached已經結束,所以*best_ist會指向第二個輸入文件。

 

 

綜上,avf_concat.c的主要作用是:

1.              當第一個文件結束時,通過控制使avfilter_graph_request_oldest返回EAGAIN,從而繼續編碼第2個文件

2.              end_frame/push_frame計算正確的pts(累加第一個文件的pts)

3.              第一個文件結束時,確保將解碼緩衝區的buffer正確輸出(未完全看明白cur_idx/nb_in_active/queue/flush_segment/send_silence這些變量以及函數的意思)

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