201410 22
Ffmpeg1.0 Filter format流程分析
Ffmpeg –y – i vga.3gp –vcodec libx264 –an –strict -2 merge.3gp
Filter为: buffer->null->format->ffbuffersink
第三行的 query_formats位于avfilter\avfiltergraph.c文件里,主要代码如下:
static intquery_formats(AVFilterGraph *graph, AVClass *log_ctx)
{
AVFilterFormats* a,*b;
int i, j,ret;
charfilt_args[128];
AVFilterFormats *formats;
AVFilterChannelLayouts *chlayouts;
AVFilterFormats *samplerates;
intscaler_count = 0, resampler_count = 0;
//下面这个奇怪的循环是一个临时解决方案,目的是让buffer filter(souce) 的query_formats函数先被调用。Filter链: buffer->null->format->ffbuffersink,但是在内存里却是:graph->filters[0]=null, graph->filters[1]=buffer,graph->filters[2]= ffbuffersink, graph->filters[3]= format.
for (j = 0; j< 2; j++) {
/* ask all thesub-filters for their supported media formats */
for (i = 0;i < graph->filter_count; i++) {
/* Callquery_formats on sources first.
This is a temporary workaround foramerge,
until format renegociation isimplemented. */
if(!graph->filters[i]->nb_inputs == j)
continue;
if(graph->filters[i]->filter->query_formats)
ret =filter_query_formats(graph->filters[i]); //会调用avfiltergraph.c文件的filter_query_formats函数
else
ret =ff_default_query_formats(graph->filters[i]);//会调用ff_set_common_formats(ctx, ff_all_formats(type)),将所有formt都设置到in_formats或者out_formats,如果有的话
if (ret< 0)
returnret;
}
}
/* go through andmerge as many format lists as possible */
for (i = 0;i < graph->filter_count; i++) {
AVFilterContext *filter =graph->filters[i];
for (j= 0; j < filter->nb_inputs; j++) {
AVFilterLink *link = filter->inputs[j];
intconvert_needed = 0;
if(!link)
continue;
if(link->in_formats != link->out_formats &&
!ff_merge_formats(link->in_formats,
link->out_formats)) //合并filter,见下面具体函数
convert_needed = 1;
if(link->type == AVMEDIA_TYPE_AUDIO) {
if(link->in_channel_layouts != link->out_channel_layouts &&
!ff_merge_channel_layouts(link->in_channel_layouts,
link->out_channel_layouts))
convert_needed = 1;
if(link->in_samplerates != link->out_samplerates &&
!ff_merge_samplerates(link->in_samplerates,
link->out_samplerates))
convert_needed = 1;
}
if(convert_needed) {//格式需要转换,插入新的filter