GStreamer流媒体知识介绍
GStreamer框架
1、GStreamer是什么?
众所周知,Microsoft's Windows和Apple's MacOS对多媒体设备、多媒体创作、播放和实时处理等方面都有很好的支持,而Linux对多媒体应用一直略显不足,所以为了解决Linux上对多媒体方面的支持,才引进GStreamer。
GStreamer是一个通用的跨平台的流媒体应用程序框架,基于GObject,以C语言写成。 GStreamer并不受限于音频和视频处理,它能够处理任意类型的数据流,因此任意一种流媒体应用都可以支持,如:MeidaPlayer、A/V Editor、VOIP、RTSP、A/V Coder等等。 GStreamer框架是基于插件(plugin)和管道(pipeline)的体系结构,框架中所有功能模块都是可插拔的组件,可随意安装到任意管道上,因此造就了大量的GStreamer的共享库。
2、 pipeline是什么?
这是个典型的MeidaPlayer的模型。
source —— 数据来源,可能是file、http、rtp等。
demux —— 负责把容器里的音视频数据剥离出来,然后分别送给audio/video decoder。
decoder —— 解码,然后把解完后的数据(pcm/yuv)送给audio/video output输出。
output —— 负责将decoder过来的数据呈现出来。
如果把数据想象成流水的话,每个模块功能虽然不同,但基本都是接收上个模块过来的数据,然后加工,把加工后的数据送到下一个模块,这些模块通过某种方式连接起来,就形成了一个流水线(pipeline),这个流水线就是一个MediaPlayer。 GStreamer 把每个模块都看做是一个元件(element),然后构建连接和操作这些element的方法,用户可以通过自己的需求把不同的elements排列组合,形成不同的pipeline。
3. element是什么?
element是一个对多媒体流进行处理的object,也是一个具体的功能模块,是pipeline的最小组成部分。
element分类:source(只提供数据源),sink(如播放设备),transform,demuxer,muxer element的输入为sink pad,输出为source pad,通过pad把element连接起来构成pipeline 图中downstream为顺流方向,upstream为逆流方向
4. pad是什么?
element的衬垫(pad)对应输入和输出接口,对于输入衬垫为sink pad,对于输出衬垫为source pad element之间都是通过pad来链接的,顺序流向不能错,也基于pad类型进行分类
pad有处理特殊数据的能力,一个pad能够限制数据流类型(GstCaps)的通过。 链接成功的条件是:只有在两个衬垫(pads)允许通过的数据类型一致的时候才被建立,通过caps negotiation方法。 衬垫有三种类型的时效性: 永久型(always)、随机型(sometimes)、请求型(on request)。 永久型的衬垫一直会存在,随机型的衬垫只在某种特定的条件下才存在(会随机消失的衬垫也属于随机型), 请求型的衬垫只在应用程序明确发出请求时才出现。
5. 四种状态
element有四种可能的状态,分别是NULL,READY,PAUSED,PLAYING。
GST_STATE_NULL 默认状态,该状态将会回收所有被元件占用的资源。
GST_STATE_READY 准备状态,该状态会得到所需的全局资源,但数据流并未处理。
GST_STATE_PAUSED 暂停状态,元件已经对流开始处理,一旦状态变为 PLAYING,可以重放数据流, 与PLAYING 状态的区别是:时钟是禁止运行的,主要对数据进行preroll。
GST_STATE_PLAYING 与 PAUSED 状态一模一样,但可以运行时钟,对数据进行处理。
通过函数gst_element_set_state()可以改变一个元件的状态,但状态变换不能跳变,比如不能从READY状态 直接变换到PLAYING状态,必须经过中间的PAUSE状态。
6. element流程
element create
gstreamer加载时,扫描/usr/lib/gstreamer-1.0目录下的库,识别其中的feature,并记录相关信息。当使用时,检查gstreamer core是否支持该功能,如果有,则加载相应库,获取信息,创建相应的element实例。
element link
element创建后,会添加到pipeline,在link时会通过gst_pad_query_caps(pad, NULL)查询pad template caps。因为此时尚未打开设备、初始化等,所以不知道element真正支持的caps,但只要查询的caps有交集即可link成功。
NULL->READY
该状态下,会初始化设备,根据相应的class调用start()或open()等函数初始化相应的硬件设备,初始化class的结构参数等。
READY->PAUSED
进一步申请资源,确定相应的参数设置,同时会激活pad。然后数据预滚(preroll),当数据到达时,检查数据时间戳是否在segment内,进行数据同步,最后就是commit,进入PAUSED。
PAUSED->PLAYING
在这个过程,设置clock时钟运行,接收到数据时,检查时间有效性,进行数据同步、处理,push到下游,发送QOS事件到上游,完成一个循环。
7. bin是什么?
箱柜(bin)是由多个element构成的容器,同时bin本身也是一种element,所以能够像操作普通element一样操作一个bin,改变bin的状态可以改变bin内部所有elements的状态。
bin可以发送总线消息给它的子集elements ,包括:错误消息(error messages),标签消息(tag messages),EOS消息(EOS messages)。
管道(pipeline)是一个特殊的bin,当设定管道暂停或播放状态的时候,数据流将开始流动,并且媒体数据处理也开始处理。一旦开始,pipeline将在一个单独的线程中运行,直到被停止或者数据流播放完毕。
data flow:数据流在pads之间传送,封装在Buffer里,Buffer包含指向数据的指针和一些metadata。
event flow:事件流与数据量不同,既有downstream方向,也有upstream,可以捕捉事件信号,进行回调处理
pipeline构建过程
gst_pipeline_new()函数:创建一个pipeline
gst_bin_add()函数:向pipeline中添加elements
gst_bin_remove()函数:从pipeline中移除element
gst_element_link()函数:链接pipeline中的elements
8. 缓冲区
缓冲区是指管道里的数据流,通常一个源元件会创建一个新的缓冲区,同时元件还将会把缓冲区的数据传递给下一个元件。使用GStreamer创建管道,不需要自己来处理缓冲区,元件将会自动处理这些缓冲区。
一个缓冲区主要组成:
指向某块内存的指针
内存的大小
缓冲区的时间戳
一个引用计数,指出了缓冲区所使用的元件数。没有元件可引用的时候,这个引用将用于销毁缓冲区
9. message/event/signal
Bus message —— 用于gstreamer和app之间交互的,比如当一个文件播放结束的时候,gstreamer会发一个EOS的message到GstBus上,如果app有去侦听(函数gst_bus_add_watch),那么在处理消息的callback函数中就可以收到这个消息。
event —— 用于gstreamer内部element之间(或pad之间)传递事件的,比如source element数据已经结束,会发出一个EOS event,顺着pipeline依次向downstream方向传递,elements得到通知,做一些cleanup工作,当所有sink element都收到并处理之后,gstreamer内部产生一条GSTMessage,并post至GstBus,如果APP有监听,就能知道当前播放已经结束。
signal —— 属于GObject体系,用于app和GObject之间交互的一种机制。在gstreamer中,element本身也是gobject,所以通过signal,就可以将app和element联系起来。 当element发生了一些事情相让app知道时,就可以用signal的方式来通知app,比如动态创建了一个Pad。
10. 初步总结
需要包含头文件gst/gst.h来访问库函数。
使用gst_init初始化GStreamer库和一些必要的参数。
使用gst_element_factory_make创建元件,参数为工厂对象名和新元件名,在bin中可查询该元件。
使用gst_object_unref释放元件,元件引用记数减1,任一元件创建时,引用记数为1,当引用记数为0时,元件会被销毁。
使用gst_bin_new或gst_pipeline_new创建箱柜。
使用gst_bin_add/remove添加/移除元件,元件所属箱柜,销毁箱柜,则箱柜中的元件同样被销毁,元件移除则自动销毁。
使用gst_element_link链接元件
每个管道默认包含一个总线,应用程序不需要再创建总线,只需在总线上设置一个消息处理器,总线会轮询消息处理器是否有新的消息,当采集到消息后,总线将呼叫相应的回调函数来处理。使用gst_bus_add_watch或gst_bus_add_signal_watch侦听回调,或使用gst_bus_peek/poll主动轮询消息。
11. 编译说明
比如之前的helloworld程序
编译: gcc -Wall helloworld.c -o helloworld $(pkg-config --cflags --libs gstreamer-0.10)
编译时借助了pkg-config命令,用于获得某一个库/模块的所有编译相关的信息。
pkg-config --cflags --libs gstreamer-0.10 会把gstreamer-0.10编译所依赖的库路径和头文件路径全部找出来,不用再依次写出,这条命令参数相当于: -pthread -I/usr/include/glib-2.0 -I/usr/lib/i386-linux-gnu/glib-2.0/include -I/usr/include/gstreamer-0.10 -I/usr/include/libxml2 -pthread -L/usr/lib/i386-linux-gnu -lgstreamer-0.10 -lgobject-2.0 -lgmodule-2.0 -lxml2 -lgthread-2.0 -lrt -lglib-2.0)
GStreamer流媒体知识介绍的更多相关文章
- [推荐]dubbo分布式服务框架知识介绍
[推荐]dubbo分布式服务框架知识介绍 CentOS+Jdk+Jboss+dubbo+zookeeper集群配置教程 http://wenku.baidu.com/view/20e8f36bf ...
- [推荐]Zookeeper大型分布式系统的可靠协调系统知识介绍
[推荐]Zookeeper大型分布式系统的可靠协调系统知识介绍 基于Zookeeper的锁开发手册 http://wenku.baidu.com/view/acbb8fc6102de2bd960588 ...
- [推荐]DDOS攻击与防范知识介绍
[推荐]DDOS攻击与防范知识介绍 DDOS攻防体系建设v0.2(淘宝-林晓曦) http://wenku.baidu.com/view/39549a11a8114431b90dd866.ht ...
- [推荐]WebService开发知识介绍
[推荐]WebService开发知识介绍 WebService开发手册 http://wenku.baidu.com/view/df3992ce050876323112128a.html WebSe ...
- [转] - Linux网络编程 -- 网络知识介绍
(一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍客户端和服务端 网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户 ...
- [转]流媒体协议介绍(rtp/rtcp/rtsp/rtmp/mms/hls)
[转]流媒体协议介绍(rtp/rtcp/rtsp/rtmp/mms/hls) http://blog.csdn.net/tttyd/article/details/12032357 RTP ...
- (转)Linxu磁盘体系知识介绍及磁盘介绍
Linxu磁盘体系知识介绍及磁盘介绍 系统管理 / 2017-01-14 / 0 条评论 / 浴春风 Linu磁盘设备基础知识指南磁盘速度快具备的条件: 1)主轴的转速5400/7200/10000/ ...
- linux字符设备驱动--基本知识介绍
一.设备驱动的分类 1.字符设备 字符设备是指那些能一个字节一个字节读取数据的设备,如LED灯.键盘.鼠标等.字符设备一般需要在驱动层实现open().close().read().write().i ...
- PySpark SQL 相关知识介绍
title: PySpark SQL 相关知识介绍 summary: 关键词:大数据 Hadoop Hive Pig Kafka Spark PySpark SQL 集群管理器 PostgreSQL ...
随机推荐
- SHELL 中条件语句的运用 if for 条件测试语句
if条件测试语句可以让脚本根据实际情况自动执行相应的命令.从技术角度来讲,if语句分为单分支结构.双分支结构.多分支结构:其复杂度随着灵活度一起逐级上升. if条件语句的单分支结构由if.then.f ...
- 使用CocoaPods创建自己的私有库-iOS组件化第一步
目前iOS组件化常用的解决方案是Pod+路由+持续集成,通常架构设计完成后第一步就是将原来工程里的模块按照架构图分解为一个个独立的pod工程(组件),今天我们就来看看如何创建一个Pod私有库. 新建: ...
- [apue] 测试管道容量的一些疑问
所谓管道的容量,指不消费(读)的情况下,最大能写入的数据量.有两种方式来测试一个管道的容量: 1)使用阻塞写,每次写一个字节,并打印写入的总字节数,最后写入阻塞时,上次打印的就是管道的容量: 2)使用 ...
- PyCharm2018 汉化&激活
一.汉化 将下载好的resources_cn_PyCharm_2018.1_r2.jar 放入pycharm 的lib 目录中,启动app即可 下载链接: https://pan.baidu.com/ ...
- 100天搞定机器学习|Day7 K-NN
最近事情无比之多,换了工作.组队参加了一个比赛.和朋友搞了一些小项目,公号荒废许久.坚持是多么重要,又是多么艰难,目前事情都告一段落,我们继续100天搞定机器学习系列.想要继续做这个是因为,一方面在具 ...
- 获取当前时间的MySql时间函数
mysql> select current_timestamp(); +---------------------+ | current_timestamp() | +------------- ...
- SQL Server 2016 + AlwaysOn 无域集群
目录 AlwaysOn 搭建 WSFC 配置计算机的 DNS 后缀 安装故障转移集群 验证集群 创建集群 创建文件共享见证 配置 AlwaysOn 新建可用性组 创建侦听器 可读副本的负载均衡 主角色 ...
- 【深入浅出-JVM】(5):Java 虚拟机结构
Java 虚拟机基本结构 Java 堆 新生代.老年代划分 栈帧 感谢您的耐心阅读,如果您发现文章中有一些没表述清楚的,或者是不对的地方,请给我留言,您的鼓励是作者写作最大的动力. 作 者 : @mo ...
- 满足高密度设备存储需求 一颗ICMAXLPDDR4X 8GB就行
通讯技术在当代无疑更新越来越快速,随着5G时代即将到来,对通讯的设备的要求也将提出更高的要求.具备AI功能的硬件设备将普及化,其智能化程度也将越来越高,同时对手机等智能移动设备的内存容量和带宽也提出了 ...
- Java 源码学习系列(三)——Integer
Integer 类在对象中包装了一个基本类型 int 的值.Integer 类型的对象包含一个 int 类型的字段. 此外,该类提供了多个方法,能在 int 类型和 String 类型之间互相转换,还 ...