Foreword
GStreamer是一个非常强大的多功能型多媒体框架,它的许多优点都源自于模块化,如GStreamer可以无缝添加新的插件模块。但模块化同时也带来高复杂度的缺点,使得开发新的应用程序并不总是十分简便。
Introduction
本书是从应用开发者的视角来编写,它描述了如何使用GStreamer库和工具来开发新的应用。如需开发插件,建议阅读另一本手册《Plugin Writers Guide》。
正式开始阅读本书前,你至少需要对C语言基础有所了解。同时,由于GStreamer沿用了GObject的开发模型,因此需要预先阅读GObject和glib开发基础,特别是:
- GObject instantiation
- GObject properties(set/get)
- GObject casting
- GObject refercing/dereferencing
- glib memory management
- glib signals and callbacks
- glib main loop
为了便于对手册进行浏览,本书分为几大部分,每一部分各有侧重。具体分布如下:
- Part I 概述GStreamer的设计原则和基础
- Part II 覆盖了GStreamer应用开发基础,本篇结束时,你应该可以使用GStreamer来创建一个audio player
- Part III 切入GStreamer的优势,包括应用-pipeline使用动态参数和接口进行交互、线程和threaded pipelines、scheduling、时钟以及同步。这些主题大部分虽然只是简单介绍了相关API,但其实际目的是深入理解GStreamer如何处理应用开发中的问题,并理解相关概念
- Part IV GStreamer高阶API,你无须了解前述篇章的所有细节,但你必须了解其中包含的基础概念。该篇中,我们将讨论XML、playbin和autopluggers
- Part V 本篇中主要为GNOME、KDE、OS X 或Windows相关的内容,以及部分调试帮助和简化应用开发的建议
Part I. About GStreamer
Chapter 1. What is GStreamer?
GStreamer是一个流媒体应用开发框架,其设计灵感来源于Oregon Graduate Institute的video pipeline和DirectShow。
GStreamer开发框架使得开发任何类型的多媒体应用成为可能。该框架设计用于简化audio、video处理应用的开发流程,但它并不限定于audio和video,实际上可处理任何格式的数据流。pipeline基于已包含的filters进行再次抽象,这使得GStreamer在应对开发低延时的高阶audio应用时井然有序。
GStreamer最常见的应用之一就是用来创建多媒体播放器,其内部已经集成了大量用用于创建播放器的组件,它们支持各种各样的格式,包括Mp3、Ogg/Vorbis、MPEG-1/2、AVI、QuickTime、mod等等。然而GStreamer并不止于播放器的开发,它最大的优势就是可将pluggable组件有序组合为任意类型的pipelines,这样一来,即使是开发功能丰富的video/audio编辑应用也游刃有余。
该框架基于plugins,它们提供了丰富的codec和其他功能。plugins可被连接成为pipeline,pipeline对应特定的数据流。由于Pipelines可以通过GUI编辑器编辑并保存为XML文件,因此将库组合成pipeline只需要很小的工作量。
GStreamer核心功能是为插件、数据流、媒体类型协商/处理提供了框架。同时,它还提供了一套用于开发应用的API,具体如下:
- 多媒体应用程序框架
- plugin架构
- pipeline架构
- 媒体类型协商、处理机制
- 同步机制
- 超过250种插件提供了多于1000种elements
- 一系列工具
GStreamer 的plugins可分类为:
- 协议处理
- 源 : 用于audio和video(包括协议插件)
- 格式器:parsers, formaters, muxers, demuxers, metadata, subtitiles
- 编码器:coders 和 decoders
- filters : converters, mixers, effects
- sinks : 用于audio和video(包括协议插件)
GStreamer 打包为:
- gstreamer : 核心包
- gst-plugins-base : 关键的核心系列元素
- gst-plugins-good : 一些高质量的LGPL插件
- gst-plugins-ugly : 一些高质量的但可能潜在问题的插件
- gst-plugins-bad : 一些低质量插件
- gst-libav : 一些libav的包装器,用于编解码
- 一些其他包
Chapter 2. Design principles
2.1 Clean and powerful
GStreamer为如下人员供了简洁的接口:
- 需要构建media pipeline的应用开发者:开发者可直接使用大量强大的工具来创建media pipeline,而不用编写一行代码。这样一来,执行复杂的多媒体操作就变得十分简单
- 插件开发者:开发者可通过所提供的简洁API来创建独立的插件。GStreamer在集成了通用调试、跟踪机制的同事,还附带了大量实用插件作为范例
2.2 Object oriented
GStreamer沿用GObject、GLib2.0对象模型,熟悉GLib2.0或GTK+的开发者也会更适应GStreamer。GStreamer使用类GTK+的开发方法,这些体现在对象模型、对象所有权、引用计数等。
GStreamer使用了信号和对象属性机制。所有对象都支持运行时查询变量属性和功能。
2.3 Extensible
所有GStreamer对象通过GObject继承模型进行扩展。所有的插件均为动态加载,并支持独立扩展和升级。
2.4 Allow binary-only plugins
插件是运行时动态加载的共享库,由于插件所有的属性都可以通过GObject属性来设置,因此插件头文件也就没有加载的必要(也没有方法)。
为了让插件完全独立,所有插件相关的内容都必须支持运行时获取。
2.5 High performance
高性能表现通过如下部分达成:
- 使用GLib的GSlice分配器
- 轻量级插件间连接,数据可在相当小开销的条件下在pipeline中传输,实际上pipeline中的插件之间通常只传递指针
- 提供了直接操作目标内存的机制,如插件可以直接写X server的共享内存,Buffers也可以直接指向专用内存,如声卡内部集成的闪存
- 引用计数和写时复制机制降低了memcpy的使用率,Sub-buffers高效地将buffers切割成更便于管理的块
- 专用流媒体线程,该线程直接由内核进行调度
- 通过特殊插件支持硬件加速
- 支持插件通过规格注册,使得插件加载可延迟至实际使用前而非创建时
2.6 Clean core/plugins separation
GStreamer的核心本质上是媒体无关的,它只关注bytes和blocks,只包含基础elements。GStreamer核心功能足够全面,甚至可以直接实现类似cp的底层工具。
所有媒体处理部分的功能都是通过向核心扩展插件添加,这些插件告诉核心该如何处理特定的媒体类型。
2.7 Provide a framework for codec experimentation
GStreamer同样希望成为一个便于codec开发者实验不同算法的框架,并推动如Xiph.Org Foundation开发的开源多媒体codecs的发展。
Chapter 3. Foundations
本章介绍了GStreamer的基础概念,了解这些概念对阅读剩下的章节十分重要。
3.1 Elements
Element是GStreamer中最重要的一类对象,你常常会创建一些elements并连接成chain,然后让数据在链路中的每个elements间流动。每个element有其特定的功能,或是从文件中读取数据,或是解码数据,或是将数据输出到声卡(或其他文件)。通过连接几个这样的elements,你就创建了一个用于特定任务的pipeline,如媒体播放或采集。GStreamer自带了大量的elements,这使得各式各样多媒体应用程序的开发成为可能。如有必要,你也可以自己编写新的elements,详细内容可参考GStreamer Plugin Writer's Guide.
3.2 Pads
Pad是element的输入和输出,可与其他element相连接。GStreamer中,它们用于和其他elements协商连接,然后完成数据流动的职责。一个pad可视为element间连接时的挂载点或端口,数据可通过pad在elements间流动。Pad有特定的数据处理能力:一个pad可限制支持通过它的数据类型。只有当两个pads都支持该数据类型时,才可以完成连接。数据类型通过GstCaps描述,协商则是通过caps negotiation机制进行协商。
举个形象的例子,pad就像物理设备的插头或接口。想象一下,典型的家庭影院由功放、DVD播放器、投影仪组成。将DVD播放器连接到功放是可以的,因为两个设备都有音频插头;将投影仪和DVD播放器相连也是可行的,因为两者都有视频接口;但将投影仪和功放相连就无法做到了,因为他们接口不同。Pads在GStreamer中的功能正如插头在家庭影院系统中一样。
需要留意的是,GStreamer里一条链路中所有elements间数据流动方向是一致的。数据从element的source pads中流出,链路下游的element通过sink pads接收该数据。Source和Sink elements分别只有source和sink pads。数据通常代表buffers(通过GstBuffer
对象描述)和events(通过GstEvent
对象描述)。
3.3 Bins and pipelines
Bin是一组elements的容器。由于bins本身就是是elements的子类,所以你通常可以和操作element一样操作bin。这样就可以从程序的复杂度中抽象出来,如可以通过改变bin本身的状态达到改变其中所有的elements状态的目的。bin还负责转发其包含的elements发出的总线消息(如错误消息、tag消息或EOS消息)
pipeline是最高阶的bin,它向应用提供了一条总线,并维护内部所有组件的同步性。当你设置pipeline为PAUSED或PLAYING状态时,数据流会开始启动,媒体数据的处理也会即时生效。一旦启动,pipelines会在独立线程内运行直到手动停止或到达数据的末端。
3.4 Communication
GStreamer提供了几套用于应用和pipeline间通讯和数据交换的机制:
- buffers是用于在pipeline中的elements间传递流数据的对象,Buffers通常从sources往sinks端传递(downstream)
- events是在elements间或由应用发送给elements的对象,Events可以downstream或upstream。Downstream events可与数据流进行同步
- messages是elements post到pipeline消息总线上的对象,在总线上它们会被应用所采集。消息在被element的 streaming线程post出后可被同步拦截,但通常应用主线程会选择进行异步处理。消息常被element用于以线程安全的方式向应用传达如errors, tags, state changes, buffering state, redirects 等信息
- queries允许应用从pipeline中查询如duration或current playback position等信息。Queries通常是同步应答的,Elements同样也可以向同阶elements查询如文件大小或duration等信息。它们支持上下行查询,但通常上行查询使用较多