GStreamer基础教程01 - Hello World
摘要
在面对一个新的软件库时,第一步通常实现一个“hello world”程序,来了解库的用法。对于GStreamer,我们可以实现一个极简的播放器,来了解GStreamer的使用。
环境配置
为了快速掌握Gstreamer相关的知识,我们优先选择Ubuntu作为我们的开发环境,其他平台的开发会在后续文章单独介绍。如果还没有Ubuntu虚拟机,可以在OSBoxes中直接下载Ubuntu 18.04的VirtualBox或VMware镜像文件,节省安装时间。
安装编译工具及库
我们在基本介绍中提到,gstreamer的框架及插件位于不同的源码包中,所以我们需要安装多个软件包:
- $ sudo apt-get install gcc build-essential libgstreamer1.- gstreamer1.-plugins-base gstreamer1.-plugins-good \
gstreamer1.-plugins-bad gstreamer1.-plugins-ugly gstreamer1.-libav gstreamer1.-doc gstreamer1.-tools \
gstreamer1.-x gstreamer1.-alsa gstreamer1.-gl gstreamer1.-qt5 gstreamer1.-pulseaudio
Hello World
我们首先使用官方的HelloWorld作为我们的第一个应用:basic-tutorial-1.c
- #include <gst/gst.h>
- int main (int argc, char *argv[])
- {
- GstElement *pipeline;
- GstBus *bus;
- GstMessage *msg;
- /* Initialize GStreamer */
- gst_init (&argc, &argv);
- /* Build the pipeline */
- pipeline = gst_parse_launch ("playbin uri=https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm", NULL);
- /* Start playing */
- gst_element_set_state (pipeline, GST_STATE_PLAYING);
- /* Wait until error or EOS */
- bus = gst_element_get_bus (pipeline);
- msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE,
- GST_MESSAGE_ERROR | GST_MESSAGE_EOS);
- /* Free resources */
- if (msg != NULL)
- gst_message_unref (msg);
- gst_object_unref (bus);
- gst_element_set_state (pipeline, GST_STATE_NULL);
- gst_object_unref (pipeline);
- return ;
- }
通过下面的命令编译得到可执行程序
- $ gcc basic-tutorial-.c -o basic-tutorial- `pkg-config --cflags --libs gstreamer-1.0`
编译成功后,我们可以得到可执行文件,执行 basic-tutorial-1,会在弹出的窗口中,自动读取服务器上的sintel_trailer-480p.webm视频文件并播放。如果网络环境不理想,在播放的过程中会经常处理缓冲状态,造成播放卡顿。也可以先下载媒体文件,将uri的http路径替换为本地uri(例如: uri=file:///home/john/sintel_trailer-480p.webm)避免网络的影响。
源码分析
通过上面的代码,我们达到了播放一个视频文件的目的,接下来通过分析这个简短的程序来了解gstreamer应用是如何工作的。
GStreamer初始化
- /* Initialize GStreamer */
- gst_init (&argc, &argv);
首先我们调用了gstreamer的初始化函数,该初始化函数必须在其他gstreamer接口之前被调用,gst_init会负责以下资源的初始化:
- 初始化GStreamer库
- 注册内部element
- 加载插件列表,扫描列表中及相应路径下的插件
- 解析并执行命令行参数
在不需要gst_init处理命令行参数时,我们可以讲NULL作为其参数,例如:gst_init(NULL, NULL);
创建Pipeline
- /* Build the pipeline */
- pipeline = gst_parse_launch ("playbin uri=https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm", NULL);
这一行是示例中的核心逻辑,展示了如何通过gst_parse_launch 创建一个playbin的pipeline,并设置播放文件的uri。
gst_parse_launch
在基本介绍中我们了解了Pipeline的概念,在pipeline中,首先通过“source” element获取媒体数据,然后通过一个或多个element对编码数据进行解码,最后通过“sink” element输出声音和画面。通常在创建较复杂的pipeline时,我们需要通过gst_element_factory_make来创建element,然后将其加入到GStreamer Bin中,并连接起来。当pipeline比较简单并且我们不需要对pipeline中的element进行过多的控制时,我们可以采用gst_parse_launch 来简化pipeline的创建。
这个函数能够巧妙的将pipeline的文本描述转化为pipeline对象,我们也经常需要通过文本方式构建pipeline来查看GStreamer是否支持相应的功能,因此GStreamer提供了gst-launch-1.0命令行工具,极大的方便了pipeline的测试。
playbin
我们知道pipeline中需要添加特定的element以实现相应的功能,在本例中,我们通过gst_parse_launch创建了只包含一个element的Pipeline。
我们刚提到pipeline需要有“source”、“sink” element,为什么这里只需要一个playbin就够了呢?是因为playbin element内部会根据文件的类型自动去查找所需要的“source”,“decoder”,”sink”并将它们连接起来,同时提供了部分接口用于控制pipeline中相应的element。
在playbin后,我们跟了一个uri参数,指定了我们想要播放的媒体文件地址,playbin会根据uri所使用的协议(“https://”,“ftp://”,“file://”等)自动选择合适的source element(此例中通过https方式)获取数据。
设置播放状态
- /* Start playing */
- gst_element_set_state (pipeline, GST_STATE_PLAYING);
这一行代码引入了一个新的概念“状态”(state)。每个GStreamer element都有相应都状态,我们目前可以简单的把状态与播放器的播放/暂停按钮联系起来,只有当状态处于PLAYING时,pipeline才会播放/处理数据。
这里gst_element_set_state通过pipeline,将playbin的状态设置为PLAYING,使playbin开始播放视频文件。
等待播放结束
- /* Wait until error or EOS */
- bus = gst_element_get_bus (pipeline);
- msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS);
这几行会等待pipeline播放结束或者播放出错。我们知道GStreamer框架会通过bus,将所发生的事件通知到应用程序,因此,这里首先取得pipeline的bus对象,通过gst_bus_timed_pop_filtered 以同步的方式等待bus上的ERROR或EOS(End of Stream)消息,该函数收到消息后才会返回。
我们会在下一篇文章中继续介绍消息相关的内容。
到目前为止,GStreamer会处理视频播放的所有工作(数据获取,解码,音视频同步,输出)。当到达文件末端(EOS)或出错(直接关闭播放窗口,断开网络)时,播放会自动停止。我们也可以在终端通过ctrl+c中断程序的执行。
释放资源
- /* Free resources */
- if (msg != NULL)
- gst_message_unref (msg);
- gst_object_unref (bus);
- gst_element_set_state (pipeline, GST_STATE_NULL);
- gst_object_unref (pipeline);
这里我们将不再使用的msg,bus对象进行销毁,并将pipeline状态设置为NULL(在NULL状态时GStreamer会释放为pipeline分配的所有资源),最后销毁pipeline对象。由于GStreamer是继承自GObject,所以需要通过gst_object_unref 来减少引用计数,当对象的引用计数为0时,函数内部会自动释放为其分配的内存。
不同接口会对返回的对象进行不同的处理,我们需要详细的阅读API文档,来决定我们是否需要对返回的对象进行释放。
总结
在本教程中,我们掌握了:
- 如何中Ubuntu下搭建GStreamer的开发环境。
- 如何通过gst_init()初始化GStreamer。
- 如何通过gst_parse_launch()快速构建一个pipeline。
- 如何使用playbin自动播放文件。
- 如何使用gst_element_set_state()来控制pipeline开始播放。
- 如何通过bus等待播放结束。
在下一篇文章中,我们将继续介绍GStreamer的基本概念,以及pipeline的另一种构造方式。
引用
https://gstreamer.freedesktop.org/documentation/tutorials/basic/hello-world.html
https://gstreamer.freedesktop.org/documentation/installing/on-linux.html
GStreamer基础教程01 - Hello World的更多相关文章
- 【GStreamer开发】GStreamer基础教程01——Hello World
目标 对于一个软件库来说,没有比在屏幕上打印出Hello World更近直观的第一印象了.因为我们是在和一个多媒体的framework打交道,所以我们准备播放一段视频来代替Hello World.不要 ...
- GStreamer基础教程02 - 基本概念
摘要 在 Gstreamer基础教程01 - Hello World中,我们介绍了如何快速的通过一个字符串创建一个简单的pipeline.为了能够更好的控制pipline中的element,我们需要单 ...
- 【GStreamer开发】GStreamer基础教程10——GStreamer工具
目标 GStreamer提供了一系列方便使用的工具.这篇教程里不牵涉任何代码,但还是会讲一些有用的内容: 如何在命令行下建立一个pipeline--完全不使用C 如何找出一个element的Capab ...
- 【GStreamer开发】GStreamer基础教程05——集成GUI工具
目标 本教程展示了如何在GStreamer集成一个GUI(比如:GTK+).最基本的原则是GStreamer处理多媒体的播放而GUI处理和用户的交互. 在这个教程里面,我们可以学到: 如何告诉GStr ...
- GStreamer基础教程09 - Appsrc及Appsink
摘要 在我们前面的文章中,我们的Pipline都是使用GStreamer自带的插件去产生/消费数据.在实际的情况中,我们的数据源可能没有相应的gstreamer插件,但我们又需要将数据发送到GStre ...
- GStreamer基础教程12 - 常用命令工具
摘要 GStreamer提供了不同的命令行工具用于快速的查看信息以及验证Pipeline的是否能够正确运行,在平时的开发过程中,我们也优先使用GStreamer的命令行工具验证,再将Pipeline集 ...
- 【GStreamer开发】GStreamer基础教程13——播放速度
目标 快进,倒放和慢放是trick模式的共同技巧,它们有一个共同点就是它们都修改了播放的速度.本教程会展示如何来获得这些效果和如何进行逐帧的跳跃.主要内容是: 如何来变换播放的速度,变快或者变慢,前进 ...
- 【GStreamer开发】GStreamer基础教程14——常用的element
目标 本教程给出了一系列开发中常用的element.它们包括大杂烩般的eleemnt(比如playbin2)以及一些调试时很有用的element. 简单来说,下面用gst-launch这个工具给出一个 ...
- 【GStreamer开发】GStreamer基础教程08——pipeline的快捷访问
目标 GStreamer建立的pipeline不需要完全关闭.有多种方法可以让数据在任何时候送到pipeline中或者从pipeline中取出.本教程会展示: 如何把外部数据送到pipeline中 如 ...
随机推荐
- 简单的UIButton按钮动画效果iOS源码
这个是简单的UIButton按钮动画效果案例,源码,简单的UIButton按钮动画,可以自定义button属性. 效果图: <ignore_js_op> 使用方法: 使用时把ButtonA ...
- I2C controller core之Bit controller(01)
FPGA proven, AISC proven, I2C controller core from OpenCores http://opencores.org/project,i2c Bit-co ...
- 读书笔记「Python编程:从入门到实践」_4.操作列表
4.1 遍历整个列表 4.1.1 深入地研究循环 4.1.2 在for循环中执行更多的操作 4.1.3 在for循环结束后执行一些操作 例 magicians = ['alice', ' ...
- C# 遍历文本框
#region 文本框指定位置加入回车符 private void button1_Click(object sender, EventArgs e) { #region // 查询首字母位置 //s ...
- mysql安装包下载地址
1.打开mysql官网 :https://dev.mysql.com/ 2.选择 downlad-->windows-->MySQL Installer -->滑动至页面底部,选择第 ...
- Hadoop-2.2.0集群部署时live nodes数目不对的问题
关于防火墙,hadoop本身配置都确定没任何问题,集群启动不报错,但打开50070页面,始终live nodes数目不对,于是我尝试/etc/hosts文件配置是否存在逻辑的错误: 127.0.0.1 ...
- matlab学习checkbox使用
添加radiobutton1和checkbox2控件以及两个edittextbox控件 %得到控件的值var=get(handles.kj2,'value');%将数值显示到文本框中,将得到的数值转换 ...
- js中的数组遍历
js中的数组遍历是项目中经常用到的,在这里将几种方法做个对比. ! for循环:使用评率最高,也是最基本的一种遍历方式. let arr = ['a','b','c','d','e']; for (l ...
- Oracle开发常用函数 max 最大数 自动加 1
max 最大数 自动加 1 create or replace function fun_getmaxlot( vend in varchar2 , domain IN VARCHAR2, tag i ...
- Monkey基本常用命令整理
adb shell monkey -v 500 >F:/monkeylog2018.txt -P表示包名 -V表示输出日志的详细级别 一个-V表示一级 递增 >输出日志 ...