GStreamer应用程序——元素

1 1,元素

对于程序员来说,GStreamer中最重要的对象是 的 GstElement 对象。元素是媒体管道的基本构建块。所有您将使用的不同高级组件源自 GstElement。每个解码器、编码器、解复用器、视频或音频输出都是事实上是一个GstElement

1.1,什么是元素?

对于应用程序程序员来说,元素最好被可视化为黑盒子。在一端,你可能会放入一些东西,元素对它进行处理,然后在另一端输出其他东西。例如,对于一个解码器元素,你可以输入编码后的数据,然后元素会输出解码后的数据。在下一章(参见Pads和功能),你将学习更多关于元素中数据输入和输出的知识,以及如何在应用程序中进行设置。

1.1.1,源元素

源元素生成用于管道的数据,例如从磁盘读取或从声卡读取。源元素的可视化显示了我们将如何可视化一个源元素。我们总是在元素的右侧绘制一个源pad。

源元素不接受数据,它们只生成数据。您可以通过图中只有一个源pad(在右侧)来看到这一点。一个源pad只能生成数据。

1.1.2,滤波器、转换器、解复用器、复用器和编解码器

过滤器和类似过滤器的元素具有输入和输出pad。它们对在其输入(sink)pad上接收到的数据进行操作,并在其输出(source)pad上提供数据。例如,音量元素(过滤器)、视频缩放器(转换器)、Ogg解复用器或Vorbis解码器等元素都属于此类。

类似过滤器的元素可以有任意数量的源或sink pad。例如,一个视频解复用器将有一个sink pad和一个包含在容器格式中的多个(1-N)源pad。另一方面,解码器只会有一个源pad和一个sink pad。

滤芯的可视化 展示了我们将如何可视化一个类似过滤器的元素。这个特定元素有一个源pad和一个sink pad。接收输入数据的sink pad在元素的左侧表示;源pad仍在右侧。

可视化一个具有多个输出pad的过滤器元素显示了另一个类似过滤器的元素,该元素具有多个输出(源)pad。例如,一个这样的元素可能是一个Ogg解复用器,用于包含音频和视频的Ogg流。一个源pad将包含基本的视频流,另一个将包含基本的声音流。解复用器通常会在创建新的pad时发出信号。应用程序程序员可以在信号处理程序中处理新的原始流。

1.1.3,Sink元素

Sink元素是媒体管道中的端点。它们接受数据但不产生任何内容。磁盘写入、声卡播放和视频输出都将由sink元素实现。可视化一个sink元素显示了一个sink元素。

1.2,创建GstElement 

创建一个简单的元素的方法就是使用gst_element_factory_make()函数。这个函数接收一个工厂名称和一个新创建的元素的名称。例如:元素的名称是以后在bin中查找元素时可以使用的。名称还将用于调试输出。你可以将NULL作为名称参数传递,以获得一个唯一的默认名称。

当你不再需要元素时,你需要使用gst_object_unref()来取消引用它。这将使元素的引用计数减少1。当元素被创建时,它的引用计数为1。当引用计数减少到0时,元素将被完全销毁。

以下示例[1]展示了如何从名为fakesrc的元素工厂创建一个名为source的元素。它检查创建是否成功。在检查后,它取消引用该元素。

#include <gst/gst.h>

int
main (int   argc,
      char *argv[])
{
  GstElement *element;

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

  /* create element */
  element = gst_element_factory_make ("fakesrc", "source");
  if (!element) {
    g_print ("Failed to create element of type 'fakesrc'\n");
    return -1;
  }

  gst_object_unref (GST_OBJECT (element));

  return 0;
}

gst_element_factory_make 实际上是两个函数的组合的简写。首先,通过工厂创建一个 GstElement 对象。要创建元素,您需要使用唯一的工厂名称获取对 GstElementFactory 对象的访问权限。这是通过 gst_element_factory_find() 完成的。

以下代码片段用于获取一个可以用于创建 fakesrc 元素的工厂,即一个假数据源。函数 gst_element_factory_create() 将使用元素工厂根据给定的名称创建一个元素。

#include <gst/gst.h>

int
main (int   argc,
      char *argv[])
{
  GstElementFactory *factory;
  GstElement * element;

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

  /* create element, method #2 */
  factory = gst_element_factory_find ("fakesrc");
  if (!factory) {
    g_print ("Failed to find factory of type 'fakesrc'\n");
    return -1;
  }
  element = gst_element_factory_create (factory, "source");
  if (!element) {
    g_print ("Failed to create element, even though its factory exists!\n");
    return -1;
  }

  gst_object_unref (GST_OBJECT (element));
  gst_object_unref (GST_OBJECT (factory));

  return 0;
}

1.3,使用元素作为GObject 

GstElement 可以具有多个属性,这些属性使用标准的 GObject 属性实现。因此支持通常的 GObject 方法来查询、设置和获取属性值和 GParamSpecs。

每个 GstElement 都从其父 GstObject 继承至少一个属性:即 "name" 属性。这是您提供给 gst_element_factory_make() 或 gst_element_factory_create() 函数的名称。您可以使用 gst_object_set_name 和 gst_object_get_name 函数获取和设置此属性,或者使用以下所示的 GObject 属性机制。

#include <gst/gst.h>

int
main (int   argc,
      char *argv[])
{
  GstElement *element;
  gchar *name;

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

  /* create element */
  element = gst_element_factory_make ("fakesrc", "source");

  /* get name */
  g_object_get (G_OBJECT (element), "name", &name, NULL);
  g_print ("The name of the element is '%s'.\n", name);
  g_free (name);

  gst_object_unref (GST_OBJECT (element));

  return 0;
}

大多数插件提供额外的属性以提供更多关于其配置的信息或配置元素。gst-inspect是一个查询特定元素属性的有用工具,它还会使用属性自省来简要解释属性的功能以及它支持的参数类型和范围。有关gst-inspect的详细信息,请参阅附录中的gst-inspect。

要了解更多关于GObject属性的信息,我们建议您阅读GObject手册和Glib对象系统的介绍。

GstElement还提供了各种GObject信号,可以用作灵活的回调机制。在这里,您也可以使用gst-inspect查看特定元素支持的信号。信号和属性是元素和应用程序交互的最基本方式。

1.4,更多关于元素工厂

在上一节中,我们简要介绍了GstElementFactory对象,它已经作为一种创建元素实例的方式。然而,元素工厂不仅仅是这样。元素工厂是从GStreamer注册表中检索的基本类型,它们描述了GStreamer可以创建的所有插件和元素。这意味着元素工厂对于自动化元素实例化非常有用,例如自动插接器所做的,以及用于创建可用元素列表。

1.4.1,使用工厂获取有关元素的信息

gst-inspect等工具可以提供关于元素的一些通用信息,例如编写插件的人、描述性名称(和简称)、等级和类别。类别可用于获取可以使用此元素工厂创建的元素类型。类别的示例包括Codec/Decoder/Video(视频解码器)、Codec/Encoder/Video(视频编码器)、Source/Video(视频生成器)、Sink/Video(视频输出),当然,这些也适用于音频。然后还有Codec/Demuxer和Codec/Muxer等等。gst-inspect将列出所有工厂,而gst-inspect 将列出上述所有信息以及更多信息。

#include <gst/gst.h>

int
main (int   argc,
      char *argv[])
{
  GstElementFactory *factory;

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

  /* get factory */
  factory = gst_element_factory_find ("fakesrc");
  if (!factory) {
    g_print ("You don't have the 'fakesrc' element installed!\n");
    return -1;
  }

  /* display information */
  g_print ("The '%s' element is a member of the category %s.\n"
           "Description: %s\n",
           gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)),
           gst_element_factory_get_metadata (factory, GST_ELEMENT_METADATA_KLASS),
           gst_element_factory_get_metadata (factory, GST_ELEMENT_METADATA_DESCRIPTION));

  gst_object_unref (GST_OBJECT (factory));

  return 0;
}

你可以用gst_registry_pool_feature_list (GST_TYPE_ELEMENT_FACTORY) 获取GStreamer知道的所有元素工厂的列表。

1.4.2,找出一个元素可以包含哪些pads

元素工厂最强大的功能可能是它们包含了元素可以生成的pad的完整描述,以及这些pad的能力(用外行的话来说:哪些类型的媒体可以在这些pad上流动),而实际上无需将这些插件加载到内存中。这可以用来为编码器提供编解码器选择列表,或者用于媒体播放器的自动插接目的。所有当前的基于GStreamer的媒体播放器和自动插接器都采用这种方式工作。我们将在下一章:Pads and capabilities中更深入地了解这些功能,届时我们将学习GstPad和GstCaps。

1.5,链接元素

通过将源元素与零个或多个类似过滤器的元素链接,最后是接收器元素,您可以设置媒体管道。数据将流经元素。这是GStreamer中媒体处理的基本概念。

通过链接这三个元素,我们创建了一个非常简单的元素链。其效果将是源元素的输出将用作类似过滤器元素的输入。类似过滤器的元素将对数据进行处理,并将结果发送到最终的接收器元素。

想象一下上面的图表作为一个简单的Ogg/Vorbis音频解码器。源是一个磁盘源,从磁盘读取文件。第二个元素是一个Ogg/Vorbis音频解码器。接收器元素是你的声卡,播放解码后的音频数据。我们将在本手册后面使用这个简单的图表来构建一个Ogg/Vorbis播放器。

在代码中,上述图表是这样写的:

#include <gst/gst.h>

int
main (int   argc,
      char *argv[])
{
  GstElement *pipeline;
  GstElement *source, *filter, *sink;

  /* init */
  gst_init (&argc, &argv);

  /* create pipeline */
  pipeline = gst_pipeline_new ("my-pipeline");

  /* create elements */
  source = gst_element_factory_make ("fakesrc", "source");
  filter = gst_element_factory_make ("identity", "filter");
  sink = gst_element_factory_make ("fakesink", "sink");

  /* must add elements to pipeline before linking them */
  gst_bin_add_many (GST_BIN (pipeline), source, filter, sink, NULL);

  /* link */
  if (!gst_element_link_many (source, filter, sink, NULL)) {
    g_warning ("Failed to link elements!");
  }

[..]

}

为了实现更具体的行为,还有gst_element_link()和gst_element_link_pads()函数。您还可以获得对单个pad的引用,并使用各种gst_pad_link_*()函数链接它们。有关更多详细信息,请参阅API参考。

重要提示:在链接元素之前,必须将元素添加到bin或pipeline中,因为将元素添加到bin中会断开任何已存在的链接。另外,您不能直接链接不在同一bin或pipeline中的元素;如果您想在不同层次结构级别链接元素或pad,将需要使用幽灵pad(稍后将详细介绍幽灵pad)。

1.6,元素状态

在被创建后,元素实际上还不会执行任何操作。您需要改变元素的状态以使其执行某些操作。GStreamer知道四种元素状态,每种状态都有非常特定的含义。这四种状态是:

  • GST_STATE_NULL:这是默认状态。在此状态下不会分配任何资源,因此,转换到该状态将释放所有资源。当元素的引用计数达到0并被释放时,元素必须处于此状态。

  • GST_STATE_READY:在就绪状态下,元素已分配其所有全局资源,即可以在流中保留的资源。您可以认为是打开设备、分配缓冲区等。然而,在此状态下流尚未打开,因此流位置自动为零。如果之前打开了流,应在该状态下关闭它,并且应重置位置、属性等。

  • GST_STATE_PAUSED:在此状态下,元素已打开流,但未积极处理它。元素被允许修改流的位置,读取和处理数据等,以便一旦状态更改为PAUSED就准备播放,但它不允许播放数据,这将使时钟运行。总之,PAUSED与PLAYING相同,但没有运行的时钟。

    进入PAUSED状态的元素应尽快准备好转移到PLAYING状态。例如,视频或音频输出会等待数据到达并将其排队,以便在状态更改后立即播放。同样,视频接收器已经可以播放第一帧(因为这还不会影响到时钟)。自动插接器可以使用相同的状态转换来预先连接管道。然而,大多数其他元素,如编解码器或过滤器,在此状态下不需要显式做任何事情。

  • GST_STATE_PLAYING:在PLAYING状态下,元素所做的与PAUSED状态完全相同,除了现在时钟正在运行。

您可以使用gst_element_set_state()函数更改元素的状态。如果您将元素设置为另一个状态,GStreamer将在内部遍历所有中间状态。因此,如果您将元素从NULL设置为PLAYING,GStreamer将在内部将元素设置为READY和PAUSED。

当移动到GST_STATE_PLAYING时,管道将自动处理数据。它们不需要以任何形式进行迭代。在内部,GStreamer将启动线程来承担这项任务。GStreamer还将通过使用GstBus来处理从管道线程到应用程序自己的线程的消息切换。有关详细信息,请参阅Bus。

当您将bin或管道设置为某个目标状态时,它通常会将状态更改自动传播到bin或管道内的所有元素,因此通常只需设置顶级管道的状态即可启动或关闭管道。但是,当动态向已运行的管道添加元素时,例如在“pad-added”信号回调中,您需要使用gst_element_set_state()或gst_element_sync_state_with_parent()自己将其设置为所需的目标状态。

  1. 此示例的代码会自动从文档中提取,并在GStreamer tarball中的tests/examples/manual下构建。
  • 8
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值