C语言多媒体框架GStreamer如何使用


这篇文章主要介绍了C语言多媒体框架GStreamer如何使用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C语言多媒体框架GStreamer如何使用文章都会有所收获,下面我们一起来看看吧。GStreamer是GNOME桌面环境下用来创建流媒体应用的多媒体框架,其基本设计思想来自于俄勒冈(Oregon)研究生学院有关视频管道的创意,同时也借鉴了DirectShow的设计思想。GStreamer是用c语言实现的,使用了面向对象的思维。GStreamer框架是基于插件和管道的,所有的插件都能够被链接到任意的已经定义的数据流管道中,数据通过管道机制进行统一交换。GStreamer的很多优点来源于其框架的模块化,使得新的插件能够无缝合并。GStreamer能够处理任意类型的数据流,其目标是要简化音/视频应用程序的开发,其最显著的用途是在构建音视频播放器、编辑音视频文件、音视频格式转换和流媒体服务上,GStreamer已经能够被用来处理像 MP3、Ogg、MPEG1、MPEG2、AVI、Quicktime 等多种格式的多媒体数据。GStreamer核心库函数是一个处理插件、数据流和媒体操作的框架。另外,其还提供了一套API,用于程序员使用其它插件来编写他所需要的应用程序时使用。但是,由于追求模块化和高效率,使得GStreamer在整个框架上变的复杂,也同时因为复杂度的提高,使得开发一个新的应用程序显得不是那么的简单。元件是GStreamer的核心,是具有一定功能的基本单元,可将其描述为一个具有特定属性的黑盒子。其在代码里面的类型是GstElement,可以理解为Gstreamer里面的基类。Gstreamer默认安装了很多有用的元件,按照功能上的差异,element分为以下几类:(1)source element 数据源元件,只有输出端,用来产生供管道消费的数据,例如,音频捕捉单元,它从声卡读取原始音频数据,供其它模块用;(2)filter(/filter-like) element 中间元件,包括过滤器、转换器、复用器、解复用器、编解码器等,其既有输入端又有输出端,从输入端获得相应数据,经过处理之后传递给输出端,有的element可能有一个source pad多个sink pads(demux),有的可能有多个source pads一个sink pad(mux),有的有一个source pad一个sink pad,例如,音频编码单元,它从外界获得音频数据之后,根据压缩算法编码后,给其它模块使用;(3)sink elements 接收器元件,只有输入端,仅有消费数据的能力,是整条媒体管道的终端,例如,音频回放单元,负责将接收到的数据写到声卡上;由多个基本单元组成的一个高级的功能单元,是装载元件的容器,可以通过改变一个Bin的状态来改变其内部所有元件的状态,Bin可以发送总线消息(bus message)给其子集元件。Bin和pipeline的区别就是pipeline肯定是bin,但bin不一定是pipeline,bin就像一个盒子,里面放了什么东西,功能具体是怎么实现的,用户可以不关心,bin是元件的集合,而pipeline更强调应用的可执行性。最高等级的Bin,是一种允许对所包含的元件进行安排(scheduling)的普通容器。顶层(toplevel)箱柜必须为一个管道,因此每个GStreamer应用程序都至少需要一个管道。当应用程序启动后,管道会自动运行在后台线程中,下面是一个典型的pipeline示例:不同Elements之间的链接点,数据流在元件之间流动就是依靠Pads。Pads有处理特殊数据的能力,也就是其支持特定媒体类型的能力,一个Pads能够限制数据流类型的通过,链接成功的条件是,两个Pads允许通过的数据类型一致时才能建立(数据类型协商)。Pads按照数据导向,可分为source pads(element的输出),sink pads(element 的输入),按照时效性可分为,永久型(always)、随机型(sometimes)、请求型(on request),三种时效性的意义顾名思义: 永久型的衬垫一直会存在,随机型的衬垫只在某种特定的条件下才存在(会随机消失的衬垫也属于随机型),请求型的衬垫只在应用程序免费云主机域名明确发出请求时才出现。Pads通过GstCaps对象进行描述,一个GstCaps对象包括一个或者多个GstStructure对象,一个GstStructure描述一种媒体类型,其结构中只包含功能集中规定的固定值。Pad的属性描述,例如: SRC template: ‘src’
Availability: Always
Capabilities:
audio/x-raw-float
rate: [ 8000, 50000 ]
channels: [ 1, 2 ]
endianness: 1234
width: 32
buffer-frames: 0
SINK template: ‘sink’
Availability: Always
Capabilities:
audio/x-vorbisbin本身没有pad,所以就没有办法把两个bin链接起来。但可以用bin中的一个元件的pad构造一个代理pad,这样bin就有一个代理pad了。这个pad实际指向被代理的那个单元的pad,示例如下:Bus采用自己的线程机制,负责pipeline线程和应用程序程序之间的通信。每个pipeline缺省创建一个Bus,应用程序在总线上设置一个类似于对象的信号处理的消息处理器,当主循环运行的时候,总线将会轮询这个消息处理器是否有新的消息,当消息被采集到后,总线将呼叫相应的回调函数来完成相关操作。应用程序有两种方法使用Bus,第一种是使用 GLib/Gtk+ main loop及gst_bus_add_watch () or gst_bus_add_signal_watch()事件回调函数机制,第二种是程序通过gst_bus_peek () /gst_bus_poll ()主动检查Bus中的消息;管道的数据流由一组缓冲区和事件组成,缓冲区包括实际的管道数据,事件包括控制信息,如寻找信息和流的终止信号。所有这些数据流在运行的时候自动的流过管道。缓冲区包含了你创建的管道里的数据流,通常一个源元件会创建一个新的缓冲区,同时元件还将会把缓冲区的数据传递给下一个元件。一个缓冲区主要由以下一个组成:(1)指向某块内存的指针;(2)内存的大小;(3)缓冲区的时间戳;(4)一个引用计数,指出了缓冲区所使用的元件数。没有元件可引用的时候,这个引用将用于销毁缓冲区。buffer的创建有2种方式,一种是由当前的element自己创建,然后把这个buffer传递给下一个element;另外一种方式就是dwonstream-allocated buffers,就是由下一个element来创建要求大小的buffer,并提供buffer操作函数,当前element通过调用buffer操作函数将数据写入这个buffer中完成buffer数据传递。其区别在于buffer的创建是在数据传输的源端element创建还是在数据接收端element来创建。元件必须封装在插件中才能被使用,一个插件是一块可以加载的代码,通常被称为共享对象文件(shared object file)或动态链接库(dynamically linked library),一个插件中可以包含一个或若干element。GStreamer core、Plugins以及依赖的第三方开源库的架构关系,如下图所示,Gstreamer的组成结构如下图所示:Gstreamer的通信机制示意图及解释如下:pipeline用来主动向外报告自己的运行状态。这些Message被发送到一个消息队列,也就是pipeline的Bus,应用程序可以从Bus中获取Message,并作出自定义的反应。Message是GST提供的,属于异步操作;pipeline中插件之间进行通信的机制,分为下行事件,上行事件和双向事件。也可以由应用程序直接向某一个插件发送事件,但起作用的前提是:该插件定义了该事件的响应操作。 通过事件可以控制整个pipeline的运行状态。下行事件是由source插件向sink插件方向传输,例如,GST_EVENT_EOS (流的终止信号)GST_EVENT_NEWSEGMENT上行事件是由sink插件向source插件方向传输,用于改变管道中数据流的状态,例如:GST_EVENT_QOSGST_EVENT_SEEK(查找)双向事件,例如:GST_EVENT_FLUSH_STARTGST_EVENT_FLUSH_STOP应用程序控制某一插件的运行状态,signal可以看做Glib对象的一个属性,是由Gobject系统提供的,属于同步操作,与linux中的系统信号有差别。通过信号可以让某个插件做一些对插件本身变量的操作,比如增加或者删除一些维护信息等等。应用程序可以通过探针Probe来探测某个插件的pad中流过的数据,比如:在audioconert 插件的src pad 加一个探针,每当有buf到达时,就调用callback_have_data(),这里这个函数只是打印一下buf的大小,统计一下buf流过的个数;应用程序可以查询pipline当前的运行状态,比如:以下代码用来查询当前播放的位置,和总的播放时间。一个元件在被创建后,它不会执行任何操作,通过改变元件的状态,才能使它做某些事情。元件有四种状态,每种状态都有其特定的意义,具体如下:GST_STATE_NULL 默认状态:没有分配任何资源,没有载入插件,不能处理数据;GST_STATE_READY 预备状态:分配或载入所有与流无关的资源(非硬件资源),所有数据流的位置信息应该自动置0,如果数据流先前被打开过,它应该被关闭,并且其位置信息、特性信息应该被重新置为初始状态;GST_STATE_PAUSED 暂停状态:准备好全部资源,接受数据流,只是sink element暂停,收到数据不处理,只是block;GST_STATE_PLAYING 播放状态:准备好全部资源,接受并处理数据流;其实这个状态除了当前运行时钟外,其它与PAUSED状态一样,可以通过gst_element_set_state()来改变一个元件的状态,当元件处于GST_STATE_PLAYING状态,管道会开始自动处理数据。元件通过caps来描述其能处理的媒体格式,元件之间交互数据流通过caps协商,caps是一个mime类型或者一些特性集的组合。一个加载进系统的元件必须提供其源衬垫和接收衬垫支持的mime类型。通过Gstreamer注册中心可以知道目前注册的不同的元件,以及他们所期望得到的与他们能够产生的媒体类型,下图显示了管道中每个Pads所处理的MIME类型。通常当加载一个新的媒体流时,媒体的类型并不明了。这意味着选择一条管道来对媒体流进行解码之前,首先需要检测媒体流的类型。 GStreamer 使用了类型检测 (typefinding) 来达到此目的。类型检测是构建管道所必经的步骤。首先它会一直读取数据流,在此期间,它会把数据提供给所有的实现了类型检测器 (typefinder) 的插件,当其中任何一个类型检测器识别出数据流,这个类型检测器元件将会发送一个信号,并开始像一个关卡 (passthrough)模块一样工作。如果数据流的类型没有被任何类型检测器识别出来,管道会发送一个错误信息,并终止所有正在处理该数据流的动作。一旦类型检测元件找到一个类型,应用程序将会使用该元件作为管道的一部分来解码媒体流。探测是衬垫监听器的形象比喻,从技术上,探针仅仅是一个可以依附于衬垫的回调信号。这些信号默认是没有被发射(fired)的(不然的话会降低性能),但是可以通过附加探针调用gst_pad_add_data_probe() 或类似的函数被激活,这些函数附加了信号处理器,并激活实际信号的发射。同样地,你可以用 gst_pad_remove_data_probe () 或相关函数来删除信号处理器,也可以只是监听时间或缓冲区。 探针在管道的线程context运行,所以回调不应该阻塞,而且通常不能有异常的阻塞,否则会降低管道的性能,如果出现这样的缺陷,会导致死锁甚至崩溃。如下图所示,基于插件的程序,其工作原理本质上都是通过读取动态库实现的,只需要每个动态库中实现某一个特定的接口就可以了,比如XX_init等,这里就是plugin_init。里面会有个像注册表一样的数据结构会存储所有的插件的信息。利用GStreamer框架提供的组件,来实现一个简单的MP3播放器。数据源元件负责从磁盘上读取数据,过滤器元件负责对数据进行解码,而接受器元件则负责将解码后的数据写入声卡,示例代码和注释如下:编译运行gcc-Wall$(pkg-config–cflags–libsgstreamer-0.10)-gtest2.c-otest2./test2/home/phinecos/test.mp3关于“C语言多媒体框架GStreamer如何使用”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“C语言多媒体框架GStreamer如何使用”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注百云主机行业资讯频道。

相关推荐: 修饰符v-model与.sync有哪些区别

这篇文章主要讲解了“修饰符v-model与.sync有哪些区别”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“修饰符v-model与.sync有哪些区别”吧!1. 作用相信过使用过vue框架的朋友对这个指令不会感…

免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。

(0)
打赏 微信扫一扫 微信扫一扫
上一篇 03/21 20:06
下一篇 03/21 20:06

相关推荐