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这些变量以及函数的意思)

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