前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ffmeg 反交错「建议收藏」

ffmeg 反交错「建议收藏」

作者头像
全栈程序员站长
发布2022-09-29 11:37:52
1.1K0
发布2022-09-29 11:37:52
举报
文章被收录于专栏:全栈程序员必看

大家好,又见面了,我是你们的朋友全栈君。

ffmeg 反交错

分类: 多媒体编程 2015-01-20 09:31 1037人阅读 评论(0) 收藏 举报

ffmpeg 反交错 avfilter 过滤器

昨天发现播放TS流(PAL 25FPS)时有横纹,查资料找到原因是解码出来的画面是用于隔行扫描显示的画面,需要进行反交错处理成逐行扫描显示画面.因为是帧内交错,所以不要IVTC(IVTC是match场操作,这里已经在同一帧了)。

在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过滤器。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/193498.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年9月15日 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • ffmeg 反交错
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档