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处理。

       本系列文章均为原创,主要总结作者多年在软件行业的一些经验,和大家共同学习、进步,转载请注明出处,谢谢!

猜你喜欢

转载自blog.csdn.net/china0851/article/details/88363488