亚欧色一区w666天堂,色情一区二区三区免费看,少妇特黄A片一区二区三区,亚洲人成网站999久久久综合,国产av熟女一区二区三区

  • 發布文章
  • 消息中心
點贊
收藏
評論
分享
原創

ffmpeg濾鏡流程解析--創建濾鏡上下文

2023-09-27 12:18:37
37
0
創建濾鏡使用的是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);
0條評論
作者已關閉評論
y****n
4文章數
0粉絲數
y****n
4 文章 | 0 粉絲
原創

ffmpeg濾鏡流程解析--創建濾鏡上下文

2023-09-27 12:18:37
37
0
創建濾鏡使用的是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);
文章來自個人專欄
文章 | 訂閱
0條評論
作者已關閉評論
作者已關閉評論
0
0