创建滤镜使用的是avfilter_graph_create_filter函数,函数里主要是调用了avfilter_graph_alloc_filter和avfilter_init_str
ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in", args, NULL, filter_graph);
int avfilter_graph_create_filter(AVFilterContext **filt_ctx, const AVFilter *filt,
const char *name, const char *args, void *opaque,
AVFilterGraph *graph_ctx)
{
int ret;
*filt_ctx = avfilter_graph_alloc_filter(graph_ctx, filt, name);
if (!*filt_ctx)
return AVERROR(ENOMEM);
//根据参数,初始化上下文
ret = avfilter_init_str(*filt_ctx, args);
if (ret < 0)
goto fail;
return 0;
fail:
if (*filt_ctx)
avfilter_free(*filt_ctx);
*filt_ctx = NULL;
return ret;
}
下面看看avfilter_graph_alloc_filter
AVFilterContext *avfilter_graph_alloc_filter(AVFilterGraph *graph,
const AVFilter *filter,
const char *name)
{
AVFilterContext **filters, *s;
//多线程??暂时不管
if (graph->thread_type && !graph->internal->thread_execute) {
if (graph->execute) {
graph->internal->thread_execute = graph->execute;
} else {
int ret = ff_graph_thread_init(graph);
if (ret < 0) {
av_log(graph, AV_LOG_ERROR, "Error initializing threading: %s.\n", av_err2str(ret));
return NULL;
}
}
}
//给滤镜初始化一个滤镜上下文
s = ff_filter_alloc(filter, name);
if (!s)
return NULL;
//申请滤镜上下文数组,realloc,再之前的基础上扩展申请
filters = av_realloc(graph->filters, sizeof(*filters) * (graph->nb_filters + 1));
if (!filters) {
avfilter_free(s);
return NULL;
}
//将滤镜上下文数组赋值到图表
graph->filters = filters;
//将当前滤镜上下文保存到数组对应的索引下
graph->filters[graph->nb_filters++] = s;
//同时,将图表保存到当前滤镜上下文
s->graph = graph;
return s;
}
该函数主要是:
1、申请了滤镜当前上下文
2、扩展了滤镜上下文数据长度
3、将上下文数据保存到图表
4、当前上下文保存到上下文数组中
5、将图表保存到当前滤镜上下文
其中,申请上下文函数s = ff_filter_alloc(filter, name);
AVFilterContext *ff_filter_alloc(const AVFilter *filter, const char *inst_name)
{
//当前滤镜上下文
AVFilterContext *ret;
int preinited = 0;
//滤镜为空,退出
if (!filter)
return NULL;
//给当前上下文申请内存
ret = av_mallocz(sizeof(AVFilterContext));
if (!ret)
return NULL;
ret->av_class = &avfilter_class;
//保存当前滤镜
ret->filter = filter;
//滤镜别名,如[in],[0:v]等
ret->name = inst_name ? av_strdup(inst_name) : NULL;
if (filter->priv_size) {
ret->priv = av_mallocz(filter->priv_size);
if (!ret->priv)
goto err;
}
if (filter->preinit) {
if (filter->preinit(ret) < 0)
goto err;
preinited = 1;
}
av_opt_set_defaults(ret);
//将filter中的priv_class赋值给了上下文的priv
if (filter->priv_class) {
*(const AVClass**)ret->priv = filter->priv_class;
av_opt_set_defaults(ret->priv);
}
ret->internal = av_mallocz(sizeof(*ret->internal));
if (!ret->internal)
goto err;
ret->internal->execute = default_execute;
//遍历filter->inputs,计算inputs的长度
ret->nb_inputs = avfilter_pad_count(filter->inputs);
//将filter->inputs拷贝到上下文的input_pads
if (ret->nb_inputs ) {
ret->input_pads = av_malloc_array(ret->nb_inputs, sizeof(AVFilterPad));
if (!ret->input_pads)
goto err;
memcpy(ret->input_pads, filter->inputs, sizeof(AVFilterPad) * ret->nb_inputs);
ret->inputs = av_mallocz_array(ret->nb_inputs, sizeof(AVFilterLink*));
if (!ret->inputs)
goto err;
}
//遍历filter->outputs,计算outputs的长度
ret->nb_outputs = avfilter_pad_count(filter->outputs);
//将filter->outputs拷贝到上下文的output_pads
if (ret->nb_outputs) {
ret->output_pads = av_malloc_array(ret->nb_outputs, sizeof(AVFilterPad));
if (!ret->output_pads)
goto err;
memcpy(ret->output_pads, filter->outputs, sizeof(AVFilterPad) * ret->nb_outputs);
ret->outputs = av_mallocz_array(ret->nb_outputs, sizeof(AVFilterLink*));
if (!ret->outputs)
goto err;
}
return ret;
err:
if (preinited)
filter->uninit(ret);
av_freep(&ret->inputs);
av_freep(&ret->input_pads);
ret->nb_inputs = 0;
av_freep(&ret->outputs);
av_freep(&ret->output_pads);
ret->nb_outputs = 0;
av_freep(&ret->priv);
av_freep(&ret->internal);
av_free(ret);
return NULL;
}
这个函数主要是:
1、申请上下文内存
2、存储当前滤镜到滤镜上下文
3、将filter中的priv_class赋值给了上下文的priv
4、将filter->inputs拷贝到上下文的input_pads
5、将filter->outputs拷贝到上下文的output_pads
总结下来,创建滤镜上下文的流程为:
1、申请了滤镜当前上下文
-
申请上下文内存
-
存储当前滤镜到滤镜上下文
-
将filter中的priv_class赋值给了上下文的priv
-
将filter->inputs拷贝到上下文的input_pads
-
将filter->outputs拷贝到上下文的output_pads
2、扩展了滤镜上下文数组长度
3、将上下文数组保存到图表
4、当前上下文保存到上下文数组中
5、将图表保存到当前滤镜上下文
申请滤镜当前上下文
filter_ctx->filter = filter
filter_ctx->priv = filter->priv_class
filter_ctx->input_pads = filter->inputs
filter_ctx->output_pads = filter->outputs
将上下文保存到图表
graph->filters[graph->nb_filters++] = filter_ctx
将图表保存到当前滤镜上下文
filter_ctx->graph = graph;
创建完上下文后,则开始对上下文进行初始化:ret = avfilter_init_str(*filt_ctx, args);该函数主要是调用了:process_options和avfilter_init_dict;process_options主要是设置参数到滤镜,
具体是设置到了滤镜的priv_class中和滤镜上下文中的class中;
avfilter_init_dict主要是调用filter的init,init_opaque,和init_dict函数
if (ctx->filter->priv_class) {
ret = av_opt_set_dict2(ctx->priv, options, AV_OPT_SEARCH_CHILDREN);
if (ret < 0) {
av_log(ctx, AV_LOG_ERROR, "Error applying options to the filter.\n");
return ret;
}
}
if (ctx->filter->init_opaque)
ret = ctx->filter->init_opaque(ctx, NULL);
else if (ctx->filter->init)
ret = ctx->filter->init(ctx);
else if (ctx->filter->init_dict)
ret = ctx->filter->init_dict(ctx, options);