zoukankan      html  css  js  c++  java
  • ffmeg过滤器介绍[转]

      在ffmpeg中,进行反交错需要用到avfilter,即图像过滤器,ffmpeg中有很多过滤器,很强大,反交错的过滤器是yadif.

      基本的过滤器使用流程是:

             解码后的画面--->buffer过滤器---->其他过滤器---->buffersink过滤器--->处理完的画面

    所有的过滤器形成了过滤器链,一定要的两个过滤器是buffer过滤器和buffersink过滤器,前者的作用是将解码后的画面加载到过滤器链中,后者的作用是将处理好的画面从过滤器链中读取出来.那么进行反交错的过滤器链应该是这样的: buffer过滤器--->yadif过滤器--->buffersink过滤器

        过滤器相关的结构体:

        AVFilterGraph: 管理所有的过滤器图像

        AVFilterContext: 过滤器上下文

        AVFilter: 过滤器


    下面来看如何创建过滤器链:

        第一步,创建AVFilterGraph

            AVFilterGraph *filter_graph=avfilter_graph_alloc();

        第二步,获取要使用的过滤器:

            AVFilter *filter_buffer=avfilter_get_by_name("buffer");

            AVFilter *filter_yadif=avfilter_get_by_name("yadif");

            AVFilter *filter_buffersink=avfilter_get_by_name("buffersink");

        第三步,创建过滤器上下文,即AVFilterContext:

            int avfilter_graph_create_filter(AVFilterContext **filt_ctx, const AVFilter *filt,
                                     const char *name, const char *args, void *opaque,
                                     AVFilterGraph *graph_ctx);

        参数说明:filt_ctx用来保存创建好的过滤器上下文,filt是过滤器,name是过滤器名称(在过滤器链中应该唯一),args是传给过滤器的参 数(每个过滤器不同,可以在相应的过滤器代码找到),opaque在代码中没有被使用,graph_ctx是过滤器图像管理指针.例:

            AVFilterContext *filter_buffer_ctx,*filter_yadif_ctx,*filter_buffersink_ctx;

            //创建buffer过滤器

            snprintf(args, sizeof(args),
                "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
                dec_ctx->width, dec_ctx->height, dec_ctx->pix_fmt,
                dec_ctx->time_base.num, dec_ctx->time_base.den,
                dec_ctx->sample_aspect_ratio.num, dec_ctx->sample_aspect_ratio.den);
            avfilter_graph_create_filter(&filter_buffer_ctx, avfilter_get_by_name("buffer"), "in",
                                           args, NULL, filter_graph);

            //创建yadif过滤器

            avfilter_graph_create_filter(&filter_yadif_ctx, avfilter_get_by_name("yadif"), "yadif",
                                       "mode=send_frame:parity=auto:deint=interlaced", NULL, filter_graph);

            //创建buffersink过滤器

            enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE };

            avfilter_graph_create_filter(&filter_buffersink_ctx, avfilter_get_by_name("buffersink"), "out",
                                           NULL, NULL,filter_graph);

            av_opt_set_int_list(filter_buffersink_ctx, "pix_fmts", pix_fmts,
                                  AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN);

       

        第四步,连接过滤器

            avfilter_link(filter_buffer_ctx, 0, filter_yadif_ctx, 0);

            avfilter_link(filter_yadif_ctx, 0, filter_buffersink_ctx, 0);

        第五步,检查所有配置是否正确:

            if ((ret = avfilter_graph_config(player->filter_graph, NULL)) < 0){
                LOGE(0,"avfilter_graph_config:%d ",ret);
                goto end;
            }

        注意上面所有的函数都应该检查返回值,这里是略写,到这里如果没出错的话,过滤器链就创建好了.


        如何使用过滤器链进行过滤,主要是使用两个函数:

        //将解码后的frame推送给过滤器链

        int av_buffersrc_add_frame_flags(AVFilterContext *buffer_src,
                                     AVFrame *frame, int flags);

        //将处理完的frame拉取出来:

        int av_buffersink_get_frame(AVFilterContext *ctx, AVFrame *frame);
        例如:

        av_buffersrc_add_frame_flags(filter_buffer_ctx, orgin_frame, AV_BUFFERSRC_FLAG_KEEP_REF);

        while(1){

            ret = av_buffersink_get_frame(filter_buffersink_ctx, frame);
            if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF){
                break;
            }

            display(frame);

        };


        反交错前的图像和反交错后的图像对比:

       

       

        虽然比较模糊,但是横纹确实去掉了.

        找了一下,发现ffmpeg中还有一个反交错的过滤器kerndeint,是GPL授权,使用时要配置打开GPL

        传入参数thresh=0:map=0:order=1:sharp=0:twoway=0后,看来起比yadif要好一些,效果如下图:

       

        ffmpeg还有一些deinterlace的过滤器,测试发现在过滤时间和画面质量方面,比较好的是pp/lb过滤器。

  • 相关阅读:
    php动态拼接变量名,可变变量,动态变量,使用花括号,使用两个$符
    php取整的几种方式,四舍五入,舍去法取整,进一法取整
    分享一张有趣的图,当程序员愿天堂没有代码
    php中函数 isset(), empty(), is_null() 的区别,boolean类型和string类型的false判断
    Linux查看系统当前登录用户的命令,top命令看到users有多个用户登录
    python如何通过windows命令行运行一个python程序文件?
    不要成为积极的废人,重要和紧急的四方格法,成功的四个基本步骤
    php CI如何实现全站静态生成html,动态创建目录
    怎么进入bios设置界面,电脑如何进入BIOS进行设置,怎么进入BIOS的方法集合
    分享几个好用的聚合工具网站,一个网站,解决一堆问题
  • 原文地址:https://www.cnblogs.com/zxqstrong/p/4566495.html
Copyright © 2011-2022 走看看