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\n",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過濾器。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM