• 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.0-0 gstreamer1.0-plugins-base gstreamer1.0-plugins-good \
    gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-doc gstreamer1.0-tools \
    gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-qt5 gstreamer1.0-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 0;
    }

    通过下面的命令编译得到可执行程序

    $ gcc basic-tutorial-1.c -o basic-tutorial-1 `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

    作者:John.Leng
    本文版权归作者所有,欢迎转载。商业转载请联系作者获得授权,非商业转载请在文章页面明显位置给出原文连接.
  • 相关阅读:
    回车代码兼容火狐浏览器
    js区分浏览器类型
    阶段总结(2014-07-23)
    Spring学习笔记 2014-7-9
    Maven学习笔记
    QQ协议的研究
    模仿微信打飞机做的程序
    滚动字幕
    13年8月15日阿里云服务器网络故障事件
    [转]程序员自己写的神器 MonoDevelop 4 (Xamarin Studio) Debugging for Unity
  • 原文地址:https://www.cnblogs.com/xleng/p/11008239.html
Copyright © 2020-2023  润新知