本文给出了Gstreamer的总体设计。通过阅读本文可以了解Gstreamer的内部工作原理。本文编译自gstreamer源码中的文档,原文在源码中的位置是/gstreamer/docs/design/part-overview.txt。

概述

Gstreamer是一个libraries和plugins的集合,用于帮助实现各种类型的多媒体应用程序,比如播放器,转码工具,多媒体服务器等。

利用Gstreamer编写多媒体应用程序,就是利用elements构建一个pipeline。element是一个对多媒体流进行处理的object,比如如下的处理:

  • 读取文件。
  • 不同格式的编解码。
  • 从硬件采集设备上采集数据。
  • 在硬件设备上播放多媒体。
  • 多个流的复用。

elements的输入叫做sink pads,输出叫做source pads。应用程序通过pad把element连接起来构成pipeline,如下图所示,其中顺着流的方向为downstream,相反方向是upstream。



应用程序会收到来自pipeline的消息和通知,比如EOS等。

总体设计

Gstreamer的设计目标如下:

  • 快速处理大规模数据。
  • 对多线程处理的完全支持。
  • 能处理各种格式的流媒体。
  • 不同数据流的同步。
  • 处理多种设备的能力。

基于Gstreamer的应用程序能够具备的处理能力依赖于系统中安装的不同种类功能的elements的数量。

Gstreamer核心不具备处理具体的media的功能,但是element处理media时需要具备的特性很多是由Gstreamer的核心提供的。

elements

element是pipeline的最小组成部分。element提供了多个pads,或者为sink,或者为source。一个element有四种可能的状态,分别是NULL,READY,PAUSED,PLAYING。NULL和READY状态下,element不对数据做任何处理,PLAYING状态对数据进行处理,PAUSE状态介于两者之间,对数据进行preroll。应用程序通过函数调用控制pipeline在不同状态之间进行转换。

element的状态变换不能跳过中间状态,比如不能从READY状态直接变换到PLAYING状态,必须经过中间的PAUSE状态。

element的状态转换成PAUSE会激活element的pad。首先是source pad被激活,然后是sink pad。pad被激活后会调用activate函数,有一些pad会启动一个Task。

PAUSE状态下,pipeline会进行数据的preroll,目的是为后续的PLAYING状态准备好数据,使得PLAYING启动的速度更快。一些element需接收到足够的数据才能完成向PAUSE状态的转变,sink
pad只有在接收到第一个数据才能实现向PAUSE的状态转变。

通常情况下,element的状态转变需要协调一致。

可对element进行如下分类:

  • source,只提供数据源。
  • sink,比如播放设备。
  • transform
  • demuxer
  • muxer

Bin

bin是由多个element构成的特殊的element,用图来说明:



Pipeline

pipeline是具备如下特性的特殊的bin:

  • 选择并管理一个全局的时钟。
  • 基于选定的时钟管理running_time。running_time用于同步,指的是pipeline在PLAYING状态下花费的时间。
  • 管理pipeline的延迟。
  • 通过GstBus提供element与应用程序间的通讯方式。
  • 管理elements的全局状态,比如EOS,Error等。

Dataflow and buffers

Gstreamer支持两种类型的数据流,分别是push模式和pull模式。在push模式下,upstream的element通过调用downstream的sink
pads的函数实现数据的传送。在pull模式下,downstream的element通过调用upstream的sourcepads的函数实现对数据的请求。

push模式是常用的模式,pull模式一般用于demuxer或者低延迟的音频应用等。

在pads之间传送的数据封装在Buffer里,Buffer中有一个指向实际数据的指针以及一些metadata。metadata的内容包括:

  • timestamp
  • offset
  • duration
  • media type
  • 其它

在push模式下,element通过调用gst_pad_push()函数把buffer传送给对应的pad。在pull模式下,element通过调用gst_pad_pull_range()函数把pull过来。

element在push buffer之前需要确认对应的element具备处理buffer中的数据类型的能力。在传说红之前首先查询对应的element能够处理的格式的种类,并从中选择合适的格式,通过gst_buffer_set_caps()函数对buffer进行设置,然后才传送数据。

收到一个buffer后,element要首先对buffer进行检查以确认是否能够处理。

可以调用gst_buffer_new()函数创建一个新的buffer,也可以调用gst_pad_alloc_buffer()函数申请一个可用的buffer。采用第二种方法接收数据的buffer可以设定接收其它类型的数据,这是通过对buffer的caps进行设定来实现的。

选择媒体类型并对buffer进行设定的处理过程叫做caps negotianation。

Caps

Caps,也就是媒体类型,采用key/value对的列表来描述。key是一个字符串类型,value的类型可能是int/float/string类型的single/list/range。

Data flow and events

除了数据流,还有events流。与数据流不同,events的传送方向既有downstream的,也有upstream的。

events用于传递EOS,flushing,seeking等消息。

有的events必须和data flow一起进行serialized。serialized的events比如TAG,非serialized的events比如FLUSH。

Pipeline construction

gst_pipeline_create()函数用于创建一个pipeline,gst_bin_add()函数用于向pipeline中添加element,gst_bin_remove()函数用于从pipeline中移除element。gst_element_get_pad()函数用于检索pipeline中的element。gst_pad_link()函数用于把pads连接在一起。

有的element会在数据流开始传送的时候创建新的pads,通过调用函数g_signal_connect()函数,能在新的pads被创建的时候接收到消息。

由于处理的数据互相不兼容,有的elements是不能被连接到一起的。gst_pad_get_caps()函数查询element能够处理的数据类型。

Pipeline clock

Pipeline的一个重要功能是为pipeline中的所有elements选择一个全局时钟。

时钟的作用是提供一个每秒为GST_SECOND的单调递增的时钟,单位是纳秒。element利用这个时钟时间来播放数据。

在pipeline被设为PLAYING之前,pipeline查询每一个element是否能提供clock,并按照如下次序来选择clock:

  • 应用程序选择了一个clock。
  • 如果source element提供了clock。
  • 其它任何提供了clock的element。
  • 选择一个默认的系统clock。

也有特殊的情况,比如存在音频sink提供了clock,那么就选择其提供的clock。

Pipeline states

完成了pads的链接和signals的链接,就可以设定pipeline为PAUSED状态启动数据流的处理。当bin(这里指的是pipeline)进行状态转换的时候要转换所有的children的状态,转换的次序是从sink element开始到source element结束,这样做的目的是为了确保upstream element提供数据的时候,downstream element已经准备好。

Pipeline status

Pipeline会通过bus向应用程序通报发生的events。bus是由pipeline提供的一个object,可以通过gst_pipeline_get_bus()函数取得。

bus分布到加入pipeline的每一个element。element利用bus来发布messages。有各种不同类型的messages,比如ERRORS,WARNINGS,EOS,STATE_CHANGED等。

pipeline以特殊的方式处理接收到的EOS message,只有当所有的sink element发送了EOS message的时候,pipeline才会把EOS发送给应用程序。

也可以通过gst_element_query()函数获取pipeline status,比如获取当前的位置或者播放的时间。

Pipeline EOS

当source filter遇上了流结束,会沿着downstream的方向向下一个element发送一个EOS的event,这个event依次传送给每一个element,接收到EOS event的element不再接收数据。

启动了线程的element发送了EOS event后就不再发送数据。

EOS event最终会到达sink element。sink element会发送一个EOS消息,通告流结束。pipeline在接收到EOS消息以后,把消息发送给应用程序。只有在PLAYING状态下会把EOS的消息传送给应用程序。

发送了EOS以后,pipeline保持PLAYING状态,等待应用程序把pipeline的状态置为PAUSE或者READY。应用程序也可以进行seek操作。

【miscellaneous】理解Gstreamer架构的更多相关文章

  1. 理解RESTful架构

    越来越多的人开始意识到,网站即软件,而且是一种新型的软件. 这种"互联网软件"采用客户端/服务器模式,建立在分布式体系上,通过互联网通信,具有高延时(high latency).高 ...

  2. [转]理解RESTful架构

    原文地址:http://www.ruanyifeng.com/blog/2011/09/restful 越来越多的人开始意识到,网站即软件,而且是一种新型的软件. 这种"互联网软件" ...

  3. 理解RESTful架构(转载)

    本文转载自:http://www.ruanyifeng.com/blog/2011/09/restful.html 越来越多的人开始意识到,网站即软件,而且是一种新型的软件. 这种"互联网软 ...

  4. [转载] 理解RESTful架构

    原文: http://www.ruanyifeng.com/blog/2011/09/restful.html 理解RESTful架构   作者: 阮一峰 日期: 2011年9月12日 越来越多的人开 ...

  5. fw:理解RESTful架构

    理解RESTful架构   作者: 阮一峰 日期: 2011年9月12日 越来越多的人开始意识到,网站即软件,而且是一种新型的软件. 这种"互联网软件"采用客户端/服务器模式,建立 ...

  6. 理解RESTful架构(转)

    理解RESTful架构   作者: 阮一峰 http://www.ruanyifeng.com/blog/2011/09/restful 越来越多的人开始意识到,网站即软件,而且是一种新型的软件. 这 ...

  7. 【转】理解RESTful架构

    [转]理解RESTful架构 越来越多的人开始意识到,网站即软件,而且是一种新型的软件. 这种"互联网软件"采用客户端/服务器模式,建立在分布式体系上,通过互联网通信,具有高延时( ...

  8. 理解RESTful架构(转)

    越来越多的人开始意识到,网站即软件,而且是一种新型的软件. 这种"互联网软件"采用客户端/服务器模式,建立在分布式体系上,通过互联网通信,具有高延时(high latency).高 ...

  9. 通过例子理解 k8s 架构 - 每天5分钟玩转 Docker 容器技术(122)

    为了帮助大家更好地理解 Kubernetes 架构,我们部署一个应用来演示各个组件之间是如何协作的. 执行命令 kubectl run httpd-app --image=httpd --replic ...

随机推荐

  1. LeetCode 282. Expression Add Operators

    原题链接在这里:https://leetcode.com/problems/expression-add-operators/ 题目: Given a string that contains onl ...

  2. 012——C#打开ecxel修改数据(附教程)

    (一)参考文献:[C#]将数据写入已存在的excel文件 C# 导入excel数据,解决关闭excel后不能释放资源的问题 (二)视频教程:https://v.qq.com/x/page/p30063 ...

  3. sql server 将某一列的值拼成一个字符串 赋值到一个字段内

    DECLARE @refCodeitems VARCHAR(800),   SELECT @refCodeitems=ISNULL(@refCodeitems,'')+refCodeitem +'/' ...

  4. Linux 内核参数说明

    转载自: https://www.cnblogs.com/tolimit/p/5065761.html 因个人能力有限,不能保证所有描述都正确,还请大家集思广益,有错误的地方欢迎大家留言指正,同时也欢 ...

  5. NetworkX系列教程(2)-graph生成器

    小书匠Graph图论 本节主要讲解如何快速使用内置的方法生成graph,官方的文档在这里,里面包含了networkX的所有graph生成器,下面的内容只是我节选的内容,并将graph画出来而已. 声明 ...

  6. nestjs中typeorm进行事物操作

    https://typeorm.io/#/transactions 两种方法

  7. OS创建页目录和页

    ;开始创建页目录项(PDE) .create_pde: ; 创建Page Directory Entry mov eax, PAGE_DIR_TABLE_POS ; PAGE_DIR_TABLE_PO ...

  8. [vsftpd] ubuntu14.04 ansible剧本安装vsftpd流程及报错排查

    需求: 在ubuntu14.04机器上搭建ftp服务,ftp账号通过winscp软件登录后,仅可增删改/data/wwwroot目录. 一.安装步骤 1.apt 安装vsftpd apt-get in ...

  9. css3 perspective与translateZ变换

    css3中的坐标系,rotateX就是绕着x轴旋转,rotateY就是绕着Y轴旋转,rotateZ就是绕着z轴旋转(也就是xy平面的旋转). perspective属性用来设置视点,在css3的模型中 ...

  10. postgresql数据的入门教程

    postgreSQL数据库简介 PostgreSQL 是一个免费的对象-关系数据库服务器(ORDBMS),在灵活的BSD许可证下发行. PostgreSQL 开发者把它念作 post-gress-Q- ...