創建濾鏡使用的是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);