GStreamer——教程——基础教程2:GStreamer concepts

基本教程2:GStreamer概念

1,目标

之前的教程展示了如何自动构建管道。现在我们将手动构建一条pipeline:初始化每一个element并将它们连接起来。在此过程中,我们将学习:

  • 什么是GStreamer元素以及如何创建一个。

  • 如何将elements相互连接。

  • 如何自定义element的行为(属性)。

  • 如何监视bus的错误条件并从GStreamer messages 中提取信息。

2,自制 Hello World

将此代码复制到名为basic-tutorial-2.c文本文件中(或找到它 在您的GStreamer安装中)。

基础教程

#include <gst/gst.h>

#ifdef __APPLE__
#include <TargetConditionals.h>
#endif

int
tutorial_main (int argc, char *argv[])
{
  GstElement *pipeline, *source, *sink;
  GstBus *bus;
  GstMessage *msg;
  GstStateChangeReturn ret;

  /* Initialize GStreamer */
  gst_init (&argc, &argv);

  /* Create the elements */
  source = gst_element_factory_make ("videotestsrc", "source");
  sink = gst_element_factory_make ("autovideosink", "sink");

  /* Create the empty pipeline */
  pipeline = gst_pipeline_new ("test-pipeline");

  if (!pipeline || !source || !sink) {
    g_printerr ("Not all elements could be created.\n");
    return -1;
  }

  /* Build the pipeline */
  gst_bin_add_many (GST_BIN (pipeline), source, sink, NULL);
  if (gst_element_link (source, sink) != TRUE) {
    g_printerr ("Elements could not be linked.\n");
    gst_object_unref (pipeline);
    return -1;
  }

  /* Modify the source's properties */
  g_object_set (source, "pattern", 0, NULL);

  /* Start playing */
  ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
  if (ret == GST_STATE_CHANGE_FAILURE) {
    g_printerr ("Unable to set the pipeline to the playing state.\n");
    gst_object_unref (pipeline);
    return -1;
  }

  /* 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);

  /* Parse message */
  if (msg != NULL) {
    GError *err;
    gchar *debug_info;

    switch (GST_MESSAGE_TYPE (msg)) {
      case GST_MESSAGE_ERROR:
        gst_message_parse_error (msg, &err, &debug_info);
        g_printerr ("Error received from element %s: %s\n",
            GST_OBJECT_NAME (msg->src), err->message);
        g_printerr ("Debugging information: %s\n",
            debug_info ? debug_info : "none");
        g_clear_error (&err);
        g_free (debug_info);
        break;
      case GST_MESSAGE_EOS:
        g_print ("End-Of-Stream reached.\n");
        break;
      default:
        /* We should not reach here because we only asked for ERRORs and EOS */
        g_printerr ("Unexpected message received.\n");
        break;
    }
    gst_message_unref (msg);
  }

  /* Free resources */
  gst_object_unref (bus);
  gst_element_set_state (pipeline, GST_STATE_NULL);
  gst_object_unref (pipeline);
  return 0;
}

int
main (int argc, char *argv[])
{
#if defined(__APPLE__) && TARGET_OS_MAC && !TARGET_OS_IPHONE
  return gst_macos_main ((GstMainFunc) tutorial_main, argc, argv, NULL);
#else
  return tutorial_main (argc, argv);
#endif
}

需要帮忙吗?

如果您需要帮助来编译此代码,请参阅为您的平台构建教程部分:LinuxMac OS XWindows,或在Linux上使用此特定命令:

gcc basic-tutorial-2.c -o basic-tutorial-2 `pkg-config --cflags --libs gstreamer-1.0`

如果您需要帮助来运行此代码,请参阅您平台的运行教程部分:LinuxMac OS X[2]或Windows

本教程打开一个窗口并显示一个测试模式,没有音频

所需库:gstreamer-1.0

3,工作流

这些 element 是GStreamer的基本构造单位。它们处理从source element(数据生产者)通过filter element流向sink element(数据消费者)的数据。

图1.示例管道

3.1,创建 element

我们将跳过GStreamer初始化,因为它与之前的教程相同:

  /* Create the elements */
  source = gst_element_factory_make ("videotestsrc", "source");
  sink = gst_element_factory_make ("autovideosink", "sink");

如本代码所示,如何使用gst_element_factory_make()新建一个element 。

第一个参数是要创建的element名,即插件名(基本教程14:方便的元素显示了一个 一些常见类型和基本教程10:GStreamer工具展示了如何 获取所有可用类型的列表)。

第二个参数是给这个特殊实例起的名称,在同一条pipeline中,必须是唯一的名称。如果你没有保留指针,给 element名可以方便你在以后检索它们(并且可以得到更有意义的调试输出)。但是,假如你传递NULL作为实例名,GStreamer也会自动为它初始化一个唯一的名称。

3.2,创建 pipeline

对于本教程,我们创建两个元素:videotestsrc autovideosink。中间没有filter element,所以整个pipeline看起来就如下图:

图2.本教程中构建的管道

Videotestsrc是一个按照制定pattern生成测试视频source element(它将生产数据),这个插件在测试和教程中很好用,但通常并不会出现在真实的应用中。

autovideosink是一个在窗口中播放它接收到的图像的sink element(它将消费数据),GStreamer包含有很多视频sink element,具体取决于操作系统,它们能够处理不同的图像格式,autovideosink将自动选择其中一个并实例话化,所以用户不需要担心平台兼容性问题。

  /* Create the empty pipeline */
  pipeline = gst_pipeline_new ("test-pipeline");

gst_pipeline_new()创建 pipeline,GStreamer中的所有元素在使用之前通常必须包含在一条pipeline 中,pipeline将负责一些时钟和消息功能。

  /* Build the pipeline */
  gst_bin_add_many (GST_BIN (pipeline), source, sink, NULL);
  if (gst_element_link (source, sink) != TRUE) {
    g_printerr ("Elements could not be linked.\n");
    gst_object_unref (pipeline);
    return -1;
  }

一条pipeline也是一个特殊的 bin,它是用于 包含其他elements。因此,适用于bin的所有方法也适用于pipeline。

在我们的例子中,我们调用gst_bin_add_many()来将elements添加到pipeline中(注意映射)。此函数接受一个要被添加到pipeline中的element列表,因为不确定列表长度所以需要以NULL结尾。添加单个element可以使gst_bin_add()。

然而,这些元素还没有相互联系。为此, 我们需要使用gst_element_link()。它的第一个参数是source, 第二个是destination。顺序很重要,因为链接必须按照数据流建立(即,从source elemnt到sink element)。请记住,只有 element 驻留在同一个bin中可以链接在一起,所以记得在之前将它们添加到pipeline中试图链接它们!

3.3,属性

GStreamer元素都是一种特殊的GObject,它是提供属性设施的实体。

大多数GStreamer元素都具有可自定义的属性:可以修改的命名属性以更改元素的行为(可写属性)或查询以了解元素的内部状态(可读属性)。

属性从g_object_get()中读取并写入用g_object_set()。

g_object_set()可以接受一个以NULL结束的属性名-属性值键值对列表,所以可以一次性设置多个属性。

这就是为什么属性处理方法具有g_前缀的原因。

回到上面的例子中,

  /* Modify the source's properties */
  g_object_set (source, "pattern", 0, NULL);

上面的代码行改变了videotestsrc的“pattern”属性, 它控制元素输出的测试视频类型。尝试不同的 值!

element 公开的所有属性的名称和可能值可以使用基本教程10:GStreamer工具或该元素的文档中描述的gst-inspect-1.0工具找到 (这里指的是videotestsrc)。

3.4,Error 监听

至此,我们已经构建和设置了整个管道,教程的其余部分与上一个非常相似,但我们将添加更多错误检查:

  /* Start playing */
  ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
  if (ret == GST_STATE_CHANGE_FAILURE) {
    g_printerr ("Unable to set the pipeline to the playing state.\n");
    gst_object_unref (pipeline);
    return -1;
  }

我们调用gst_element_set_state(),但是这次将检查状态改变的返回值。假如状态修改失败,将返回一个error值并进行相关退出处理,还有更多详细信息在基础教程3:动态管道中给出。

  /* 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);

  /* Parse message */
  if (msg != NULL) {
    GError *err;
    gchar *debug_info;

    switch (GST_MESSAGE_TYPE (msg)) {
      case GST_MESSAGE_ERROR:
        gst_message_parse_error (msg, &err, &debug_info);
        g_printerr ("Error received from element %s: %s\n",
            GST_OBJECT_NAME (msg->src), err->message);
        g_printerr ("Debugging information: %s\n",
            debug_info ? debug_info : "none");
        g_clear_error (&err);
        g_free (debug_info);
        break;
      case GST_MESSAGE_EOS:
        g_print ("End-Of-Stream reached.\n");
        break;
      default:
        /* We should not reach here because we only asked for ERRORs and EOS */
        g_printerr ("Unexpected message received.\n");
        break;
    }
    gst_message_unref (msg);
  }

gst_bus_timed_pop_filtered() 等待执行结束并返回带有我们之前忽略的GstMessage。我们要求gst_bus_timed_pop_filtered() 返回时GStreamer 遇到错误条件或EOS,所以我们需要检查发生了哪一个,并在屏幕上打印一条消息(您的应用程序将可能想采取更复杂的行动)。

GstMessage是一个非常通用的结构,它可以传递几乎任何类型的信息。幸运的是,GStreamer提供了一系列消息的解析函数。

在这种情况下,一旦我们知道消息包含错误(通过使用 GST_MESSAGE_TYPE() 宏),我们可以使用 gst_message_parse_error() 返回GLib的GError结构和对调试有用的字符串。检查代码以了解如何这些被使用并在之后释放。

3.5,GStreamer bus

在这一点上,值得更正式地介绍一下GStreamer bus 。GStreamer bus它是负责将element生成的GstMessages 按顺序交付给应用程序和应用程序线程(这点很重要,因此GStreamer实际是在其他的线程中处理媒体流)的对象。

消息可以通过 gst_bus_timed_pop_filtered()及其相关函数同步地从总线中提取,或者通过信号异步地提取(如在下一个教程中所示)。你的应用程序应该始终关注总线,以便被通知错误和其他与播放相关的问题。

其余的代码是清理序列,与基础教程1: Hello world!中的相同。

4,练习

如果您想练习,请尝试此练习:尝试在这条example pipeline的source和sink之间添加视频filter element,例如vertigotv,你需要创建它,将它加入pipeline,并将它和pipeline中的其他元素连接起来。

根据您的平台和可用插件,您可能会得到一个 “negotiation”错误,因为sink element 正在生产什么(更多关于基本教程6:媒体格式和Pad功能的协商)。在这种情况下你需要在filter 之后添加videoconvert(即构建一个4个元素的管道。更多关于 videoconvert在基本教程14:Handy elements)。

5,总结

本教程展示了:

### GStreamer on Linux Installation and Usage Documentation #### Overview of Resources Available for Learning GStreamer For those seeking a deeper understanding or beginning with GStreamer, the official resources provide comprehensive guidance. The assumption is that individuals have familiarity with basic working principles of GStreamer[^1]. For beginners who wish to understand programming concepts within this framework better, starting points include the _GStreamer Application Development Manual_. Additional documents are available through the GStreamer website which can serve as valuable references. #### Guidance Specifics for Developers Interested in Plugin Creation The development guide specifically caters towards developers interested not just in using existing plugins but also creating new ones. It clarifies that users only looking to leverage current functionalities should refer elsewhere such as application-specific manuals or other introductory materials aimed at end-users rather than plugin creators[^2]. #### Tutorial Focus Areas Related to Time Management Features One specific area covered by tutorials includes managing timing aspects effectively within applications built upon GStreamer. These guides aim to demonstrate practical implementations concerning temporal elements ensuring efficient handling of multimedia streams over time[^3]. #### Common Compilation Issues During Setup Process When setting up environments involving cross-compilation setups like Yocto Project-based systems targeting ARM architectures, encountering linker errors related to missing libraries (such as `-liberty`) may occur during compilation stages after configuring build configurations properly via `CFLAGS`. Such issues often stem from incomplete toolchain installations where certain auxiliary packages required by GCC aren't present in target root filesystem images generated by embedded Linux distribution builders[^4]. ```bash sudo apt-get install libiberty-dev ``` This command installs the necessary package containing the library needed for resolving the mentioned linking error when encountered outside specialized embedded SDK contexts. --related questions-- 1. What topics does the GStreamer Application Development Manual cover? 2. How do I resolve dependency issues while compiling custom-built binaries against GStreamer APIs? 3. Can you recommend any online courses focusing on advanced features offered by GStreamer? 4. Where can one find detailed explanations about each element provided by default in GStreamer pipelines?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值