出处:https://www.cnblogs.com/zxqstrong/p/4566495.html在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))            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过滤器。
10-03 17:51