ffmpeg的新东东:AVFilter

http://blog.csdn.net/niu_gao/article/details/7219641

 

 

 

利用ffmpeg做图像的pixel format转换你还在用libswscale吗?嘿嘿,过时啦!
ffmpeg中有了新东西:libavfilter.使用它,可以完全代替libswscale,并且可以自动完成一些复杂的转换操作呢.libavfilter啊,用了都说好!但就是太复杂...
如果你仅仅是做图像的pixel format处理,用libswscale是相当简单,可以看看最新的ffplay.c中的代码,被#if CONFIG_AVFILTER #endif包围的代码量非常大,而且让人一上来看得一头雾水,但为了赶潮流,我们还是得学习它啊...
先弄清楚avfilter中的几个相关的概念(注意:如果没有directShow基础的同学看不懂以下解释,请先学DirectShow的基本概念):
1 AVFilterGraph:几乎完全等同与directShow中的fitlerGraph,代表一串连接起来的filter们.
AVFilter:代表一个filter.
AVFilterPad:代表一个filter的输入或输出口,等同于DShow中的Pin.只有输出pad的filter叫source,只有输入pad的tilter叫sink.
AVFilterLink:代表两个连接的fitler之间的粘合物.
其实总体看起来,libavfitler跟DShow几乎一样了.

下面看一下AVFilter是如何被使用的,我们以ffplay.c为例吧,分析一下其中AVFilter相关的代码.
1 产生graph:
AVFilterGraph *graph = avfilter_graph_alloc();
2 创建source
AVFilterContext *filt_src;
avfilter_graph_create_filter(&filt_src, &input_filter, "src",NULL, is, graph);
第一个参数是生成的filter(是一个source),第二个参数是一个AVFilter结构的实例,第三个参数是要创建的fitler的名字,第四个 参数是不知道什么用,第五个参数是user data(调用者的私有数据),第六个参数是graph的指针.其中第二个参数的实例必须由调用者自己实现,才能将帧送到graph中.
3 创建sink
AVFilterContext *filt_out;
ret = avfilter_graph_create_filter(&filt_out, avfilter_get_by_name("buffersink"), "out", NULL, pix_fmts, graph);
参数同上,不解释.所创建的这个sink是一个buffersink,可参考libavfitler的源码文件sink_buffer.c看看它是个什么 玩意.sink_buffer其实是一个能通过buffer输出帧的sink,当然它的输出不是通过pad,因为它后面没有fitler了.用它做 sink,可以让使用这个graph的代码轻松取得graph处理后的帧.
4 连接source和sink
avfilter_link(filt_src, 0, filt_out, 0);
第一个参数是接在前面的filter,第二个参数是前fitler的要连接的pad的序号,第三个参数是后面的filter,第四个参数是后filter的要连接的pad.
4 对graph做最后的检查
avfilter_graph_config(graph, NULL);
我们是从sink中取出处理完成的帧,所以最好把sink的引用保存下来,比如:
AVFilterContext *out_video_filter=filt_out;
6实现input_filter

由于input_filter是个source,所以只为它分配output pad,并且只有一个pad.

[cpp] view plaincopy
  1. static AVFilter input_filter =  
  2. {  
  3.     .name      = "ffplay_input",  
  4.   
  5.     .priv_size = sizeof(FilterPriv),  
  6.   
  7.     .init      = input_init,  
  8.     .uninit    = input_uninit,  
  9.   
  10.     .query_formats = input_query_formats,  
  11.   
  12.     .inputs    = (AVFilterPad[]) {{ .name = NULL }},  
  13.     .outputs   = (AVFilterPad[]) {{ .name = "default",  
  14.                                     .type = AVMEDIA_TYPE_VIDEO,  
  15.                                     .request_frame = input_request_frame,  
  16.                                     .config_props  = input_config_props, },  
  17.                                   { .name = NULL }},  
  18. };  

再实现AVFilter的回调函数们:init()和uninit()--用于初始化/销毁所用到的资源.
看一下ffplay.c中的实现:

[cpp] view plaincopy
  1. static int input_init(AVFilterContext *ctx, const char *args, void *opaque)  
  2. {  
  3.     FilterPriv *priv = ctx->priv;  
  4.     AVCodecContext *codec;  
  5.     if(!opaque) return -1;  
  6.   
  7.     priv->is = opaque;  
  8.     codec    = priv->is->video_st->codec;  
  9.     codec->opaque = ctx;  
  10.     if((codec->codec->capabilities & CODEC_CAP_DR1)) {  
  11.         av_assert0(codec->flags & CODEC_FLAG_EMU_EDGE);  
  12.         priv->use_dr1 = 1;  
  13.         codec->get_buffer     = input_get_buffer;  
  14.         codec->release_buffer = input_release_buffer;  
  15.         codec->reget_buffer   = input_reget_buffer;  
  16.         codec->thread_safe_callbacks = 1;  
  17.     }  
  18.   
  19.     priv->frame = avcodec_alloc_frame();  
  20.   
  21.     return 0;  
  22. }  

FilterPriv是ffplay实现的filter(也就是input_filter)的私有数据结构.主要的工作是分配了一个AVFrame,用于保存从设备取得的帧.uninit()更简单,就不用看了.
还需实现output pad的request_frame(),才能使input_filter后面的filter获取到帧

[cpp] view plaincopy
  1. static int input_request_frame(AVFilterLink *link)  
  2. {  
  3.     FilterPriv *priv = link->src->priv;  
  4.     AVFilterBufferRef *picref;  
  5.     int64_t pts = 0;  
  6.     AVPacket pkt;  
  7.     int ret;  
  8.   
  9.     while (!(ret = get_video_frame(priv->is, priv->frame, &pts, &pkt)))  
  10.         av_free_packet(&pkt);  
  11.     if (ret < 0)  
  12.         return -1;  
  13.   
  14.     if(priv->use_dr1 && priv->frame->opaque) {  
  15.         picref = avfilter_ref_buffer(priv->frame->opaque, ~0);  
  16.     } else {  
  17.         picref = avfilter_get_video_buffer(link, AV_PERM_WRITE, link->w, link->h);  
  18.         av_image_copy(picref->data, picref->linesize,  
  19.                       priv->frame->data, priv->frame->linesize,  
  20.                       picref->format, link->w, link->h);  
  21.     }  
  22.     av_free_packet(&pkt);  
  23.   
  24.     avfilter_copy_frame_props(picref, priv->frame);  
  25.     picref->pts = pts;  
  26.   
  27.     avfilter_start_frame(link, picref);  
  28.     avfilter_draw_slice(link, 0, link->h, 1);  
  29.     avfilter_end_frame(link);  
  30.   
  31.     return 0;  
  32. }  

调用者从sink中获取处理后的帧:
av_buffersink_get_buffer_ref(filt_out, &picref, 0);
获取后的帧保存在picref中.这个函数会引起graph中的filter从后向前依次调用上一个filter的outpad的 request_frame(),最后调用到source的request_frame(),也就是 input_request_frame(),input_request_frame()调用get_video_frame()(见 ffplay.c)从设备获取一帧(可能需要解码),然后将这帧数据复制到picref中,filter们处理的帧是用 AVFilterBufferRef表示的.然后将帧的一些属性也复制到picref中,最后调用avfilter_start_frame(link, picref);avfilter_draw_slice(link, 0, link->h, 1);avfilter_end_frame(link);来处理这一帧.这三个函数对应着pad上的三个函数指 针:start_frame,draw_slice,end_frame.以start_frame为例,其调用过程是这样的:首先是source的 start_frame被调用,做一些必要的处理后,再调用连接到source之后的filter的start_frame.每个filter的 output pad都负责在这个函数中向下传递这个调用.当sink调用完start_frame()时再一层层返回到source的output pad.当这三个函数都被source的output pad调用完成后,这一帧的最终结果就出来了.于是可以用sink上获得.
与DShow比较起来,avfilter没有那些推模式,拉模式的概念,没有在source的output pad上实现线程,整个graph的运转都是由调用者驱动.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/264868.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

https网络编程——HTTPS中SSL具体通信过程

参考:HTTPS中SSL是如何进行通信的? 地址:https://qingmu.blog.csdn.net/article/details/108277887?spm=1001.2014.3001.5502 目录 1、https中SSL通讯的前置准备工作2、openssl库相关函数介绍2.1、重要参数讲解3、SSL框架图4、demo4.1、sslserver.c4.2、sslclient.c1、http…

想跟着微软赛跑会累死你

当微软在推出ASP.NET1.1时,就发布了ASP.NET2.0测试版,当微软发布ASP.NET2.0时,又发布了ASP.NET AJAX测试版,当然也有不少人都知道,微软又有准备推出ASP.NET3.0版本的打算. 每一个版本比上一个版本都会有许多应用上的提升,一个重要的问题是:我们需要不需要和微软赛跑? 微软…

2019.2.4 nfs原理和安装实验

NFS 访问一个本地文件还是NFS共享文件对于客户端而言都是透明的&#xff0c;当文件打开的瞬间&#xff0c;内核会作出一个决定&#xff0c;如果是本地文件内核会将本地NFS共享文件内核会将NFS共享文件的所有引用传递给——》NFS客户端枢中 NFS客户端是通过TCP/IP协议及模块向NF…

基本 XAML 语法指南

我们介绍了 XAML 语法规则&#xff0c;以及用于描述 XAML 语法中存在的限制或选项的术语。当出现以下情况时你会发现本主题很有用&#xff1a;不熟悉 XAML 语言的使用&#xff0c;希望加强对术语或某些语法部分的理解&#xff0c;或者对 XAML 语言的工作原理感兴趣&#xff0c;…

https网络编程——如何做web的访问控制机制(ACL)

参考&#xff1a;如何做web的访问控制机制&#xff08;ACL&#xff09;&#xff1f; 地址&#xff1a;https://qingmu.blog.csdn.net/article/details/108286660?spm1001.2014.3001.5502 目录ACL含义例子具体实现ACL含义 对于一个服务器来说&#xff0c;我们不能让随随便便一…

形容人的内核是什么意思_成语雪泥鸿爪是形容什么的?雪泥鸿爪什么意思?蚂蚁庄园2020年12月10日答案...

斑马线和斑马什么关系&#xff1f;大家都知道斑马和斑马线&#xff0c;但是两者之间有什么关系&#xff1f;蚂蚁庄园12月10日提到了这个问题&#xff0c;我们一起来看看正确答案吧。问题&#xff1a;斑马线和斑马有什么关系&#xff1f;答案&#xff1a;横线酷似斑马纹答案解析…

.Net 2.0里有一个有用的新功能:迭代器

下面内容节选至MSDN2005。迭代器&#xff08;C# 编程指南&#xff09; 迭代器是 C# 2.0 中的新功能。迭代器是方法、get 访问器或运算符&#xff0c;它使您能够在类或结构中支持 foreach 迭代&#xff0c;而不必实现整个 IEnumerable 接口。您只需提供一个迭代器&#xff0c;即…

js操作indexedDB增删改查示例

js操作indexedDB增删改查示例 if (indexedDB in window) {// 如果数据库不存在则创建&#xff0c;如果存在但是version更大&#xff0c;会自动升级不会复制原来的版本var req indexedDB.open("TestDB", 1);req.onupgradeneeded function(e) {var db req.result;//…

MySQL 服务器变量 数据操作DML-视图

原文:MySQL 服务器变量 数据操作DML-视图SQL语言的组成部分 常见分类&#xff1a; DDL&#xff1a;数据定义语言 DCL&#xff1a;数据控制语言&#xff0c;如授权 DML&#xff1a;数据操作语言 其它分类&#xff1a; 完整性定义语言&#xff1a;DDL的一部分功能约束约束&#x…

kafka内存不断增加_为什么 Kafka 能这么快的 6 个原因

无论 kafka 作为 MQ 也好&#xff0c;作为存储层也罢&#xff0c;无非就是两个功能(好简单的样子)&#xff0c;一是 Producer 生产的数据存到 broker&#xff0c;二是 Consumer 从 broker 读取数据。那 Kafka 的快也就体现在读写两个方面了&#xff0c;下面我们就聊聊 Kafka 快…

https网络编程——DNS域名解析获取IP地址

参考&#xff1a;DNS域名解析 地址&#xff1a;https://qingmu.blog.csdn.net/article/details/115825036?spm1001.2014.3001.5502 1、原理 我在在通过域名解析获取IP的过程中一般使用的是DNS域名解析。 DNS协议是一种应用层协议&#xff0c;他是基于UDP来实现的。 2、代码…

C#桌面时钟

使用C&#xff03;制作的桌面时钟&#xff0c;提供闹钟功能&#xff08;虽然很简陋&#xff09;、万年历功能&#xff08;包含农历&#xff09;源码&#xff1a;http://www.cnblogs.com/Files/shiweifu/MyClock.rar截图&#xff1a;适合初学者研究 转载于:https://www.cnblogs.…

小a与黄金街道(欧拉函数)/**模运算规则总结*/

链接&#xff1a;https://ac.nowcoder.com/acm/contest/317/D 来源&#xff1a;牛客网 题目描述 小a和小b来到了一条布满了黄金的街道上。它们想要带几块黄金回去&#xff0c;然而这里的城管担心他们拿走的太多&#xff0c;于是要求小a和小b通过做一个游戏来决定最后得到的黄金…

使用cvs或svn从sourceforge上获取开源项目的方法[转载]

著名开源软件网站&#xff08;www.sourceforge.net)上面的开源项目&#xff0c;大部分使用的管理工具为cvs或svn。这两种软件的代表客户端程序是wincvs和tortoiseSVN。1.cvsCVS (Concurrent Versions System) is a tool used by many software developers to manage changes wi…

堆栈认知——逆向IDA工具的基本使用

参考&#xff1a;逆向-IDA工具的基本使用 地址&#xff1a;https://qingmu.blog.csdn.net/article/details/118862881 目录1、文件的打开与关闭2、窗口介绍&#xff1a;图形 文本 其他窗口2.1、图形界面&#xff1a;2.2、文本界面&#xff1a;2.3、反汇编窗口2.4、 十六进制窗口…

jmeter中timeout值怎么设置_jMeter解决failed to respond Connection reset

通过以上可总结三种情况错误的情况如下&#xff1a;(以2000并发为例)----1&#xff1a;ideltimeout不设置&#xff0c;只设置connectionTimeout20s----一批接口中第一个接口肯定不会出现&#xff0c;因为他都是新建的tcp连接。----第二个接口容易出现RST&#xff0c;因为第一个…

DevIL真是好用得想哭

昨天整一个tiny的渲染中间层&#xff0c;涉及到image格式读取的问题先是整HBITMAP这一套函数&#xff0c;搞得人头大&#xff0c;搞来搞去发现只有是从::CreateDC("DISPLAY", 0, 0, 0) compatible 过来的DC才是支持color bitmap的&#xff0c;晕然后用DevIL来读取多种…

[Computation]集合、关系、语言

写了半天发现啥都没写 相当于自查表 集合、关系和语言 集合 *太简单辽&#xff0c;自己翻书*集合&#xff1a;对象的汇集。空集、单元集子集、真子集集合的运算&#xff1a;交 并 差 幂等律 交换律 结合律 分配律 吸收律 De Morgan律幂集 划分*太简单辽&#xff0c;自己翻书*笛…

JOSSO在JBOSS中安装与配置

JOSSO在JBOSS中安装与配置 1、JOSSO单点登录网关1.1进入josso/bin目录&#xff0c;执行josso-gsh命令1.2 安装JOSSO的核心Gateway,执行命令gateway install --target <JBOSS_HOME> --jboss-instance default - platform jb42此命令实际上执行了如下操作&#xff1a;1.2.…

堆栈认知——栈溢出实例(ret2text)

参考&#xff1a;栈溢出实例–笔记一&#xff08;ret2text&#xff09; 地址&#xff1a;https://qingmu.blog.csdn.net/article/details/119295954 目录1、什么是栈溢出&#xff1f;2、栈结构3、栈溢出需要解决的问题3.1、解决如何跳转的问题3.2、跳转到哪里去&#xff1f;4、…