Gstreamer- 元素(Elements)

Elements

GStreamer 中对于程序员开发者来说最重要的对象是 GstElement 。Elements 是多媒体 pipeline 的基本构建块。您使用的所有不同的高级组件都源自 GstElement。每个解码器、编码器、解复用器、视频或音频输出实际上都是一个 GstElement

什么是elements?

对于程序员开发者来说,elements 最好被可视化为黑盒。一方面,你可能向其输入一些东西,elements 用它做一些事情,从另一边会输出其他东西。例如,对于解码器element,您输入编码数据,该element将输出解码的数据。在下一章中(参见pad和capabilities),您将了解有关element中数据输入和输出的更多信息,以及如何在应用程序中进行设置。

Source elements

Source elements生成供pipeline使用的数据,例如从磁盘或声卡读取。Source element的可视化展示了如何可视化一个source element。我们总是在element的右侧绘制一个source pad。
在这里插入图片描述

Source elements不接受数据,它们只生成数据。 您可以在图中看到这一点,因为它只有一个source pad(在右侧)。 source pad只能生成数据。

Filters, convertors, demuxers, muxers and codecs

Filters(过滤器)和filter-like(类过滤器)的 elements 都有输入和输出pads。 它们对在输入(sink)pads上接收到的数据进行操作,并在其输出(source)pads上供给数据。 此类element 的示例是音量element (filter)、视频缩放器(convertor)、Ogg 解复用器或 Vorbis 解码器。

Filter-like 的elements 可以有任意数量的source 或 sink pads。 例如,video demuxer将有一个sink pad 和几个 (1-N) 个source pads,每个source pad对应容器格式中包含的每个基本流。 另一方面,Decoders只有一个source 和sink pads。
在这里插入图片描述

Filter element的可视化展示了如何可视化一个filter-like element。 这个特定的element有一个source pad 和一个sink pad。 接收输入数据的 sink pads位于element的左侧; source pads仍然在右侧。
在这里插入图片描述
具有多个输出pads的filter element的可视化显示了另一种filter-like element,该element具有多个输出(source)pad。 例如,一个此类element的示例可以是包含音频和视频的 Ogg 流的 Ogg demuxer 。 其中一个source pad将包含基本视频流,另一个将包含基本音频流。Demuxers 通常会在创建新的pad时发出信号。 然后程序开发者可以在信号处理程序中处理新的基本流。

Sink elements

Sink elements是 media pipeline中的终点。 他们接受数据但不产生任何东西。 磁盘写入、声卡播放和视频输出都将由sink elements实现。 sink elements的可视化显示了sink elements。
Visualisation of a sink element

创建 GstElement

创建element 最简单的方法是使用gst_element_factory_make()。 此这个函数接受新创建element的工厂名称和element名称。 例如,element的名称可以用于以后在bin中查找该名称的element。 该名称也将在调试输出中使用。 您可以将NULL作为name参数传递,以获得唯一的、默认的名称。

当您不再需要该element 时,您需要使用 gst_object_unref () 取消引用它。 这会将element 的引用计数减少 1。一个element 在创建时的引用计数为 1。 当引用计数减少到 0 时,element 将被完全销毁。

以下示例 [1] 显示了如何从名为 fakesrc 的element 工厂创建名为 source 的element 。 它检查创建是否成功。 检查后,它取消引用element 。

#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 对象是从工厂创建的。 要创建element ,您必须使用唯一的工厂名称访问 GstElementFactory 对象。 这是通过 gst_element_factory_find () 完成的。

以下代码片段用于获取可用于创建 fakesrc element的工厂。 函数 gst_element_factory_create () 将使用element工厂创建具有给定名称的element。

#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;
}
使用element作为 GObject

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

每个 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;
}

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

有关 GObject 属性的更多信息,我们建议您阅读 GObject 手册和 Glib 对象系统简介。

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

更多关于element factories

在上一节中,我们已经简要介绍了 GstElementFactory 对象作为创建element实例的一种方式。然而,element factories远不止这些。Element factories是从 GStreamer 注册表中检索到的基本类型,它们描述了 GStreamer 可以创建的所有plugins 和elements 。这意味着element factories对于element自动实例化非常有用,例如自动插件的作用,以及创建可用的element列表。

使用工厂获取有关element的信息

诸如 gst-inspect 之类的工具将提供有关element的一些通用信息,例如编写插件的人、描述性名称(和简称)、等级和类别。类别可用于获取可以使用此element factory创建的element的类型。类别的示例包括 Codec/Decoder/Video(视频解码器)、Codec/Encoder/Video(视频编码器)、Source/Video(视频生成器)、Sink/Video(视频输出),所有这些也适用于音频, 当然。然后,还有 Codec/Demuxer 和 Codec/Muxer 等等。 gst-inspect 将给出所有 factory的列表,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 知道的所有element factory的列表。

找出element可以包含哪些 pads

也许element factories最强大的功能是它们包含element可以生成的pads的完整描述,以及这些pads的功能(通俗地说:哪些类型的媒体可以流过这些pads),而实际上不必将这些插件加载到内存中。这可用于为编码器提供编解码器选择列表,也可用于媒体播放器的自动插件目的。当前所有基于 GStreamer 的媒体播放器和自动插件都以这种方式工作。当我们在下一章中了解 GstPad 和 GstCaps 时,我们将更仔细地研究这些功能:Pads 和 capabilities

链接Element

通过将source element与零个或多个filter-like elements以及最终的sink element链接起来,您就可以设置媒体pipeline。数据将流经这些elements。这是 GStreamer 中媒体处理的基本概念。
Visualisation of three linked elements

通过链接这三个element,我们创建了一个非常简单的element链。 这样做的效果是 source element(“element1”)的输出将用作 filter-like element(“element2”)的输入。 filter-like element会对数据做一些事情,并将结果发送到最终的 sink element(“element3”)。

将上图想象成一个简单的 Ogg/Vorbis 音频解码器。 数据源是从磁盘读取文件的磁盘源。 第二个element是 Ogg/Vorbis 音频解码器。 sink element 是你的声卡,播放解码后的音频数据。 我们将在本手册的后面使用这个简单的图形来构建一个 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 ()。您还可以使用各种 gst_pad_link_* () 函数获取对单个焊盘的引用并链接它们。有关更多详细信息,请参阅 API 参考。

重要提示:您必须在链接之前将element添加到 bin 或 pipeline,因为将element添加到 bin 会断开任何现有的链接。此外,您不能直接链接不在同一个 bin 或pipeline中的element;如果您想链接不同层次级别的element或pads,则需要使用ghost pad(稍后将详细介绍ghost pad)。

Element状态

创建后,element 实际上还不会执行任何操作。您需要更改element 的状态以使其执行某些操作。 GStreamer 能够理解四种element 状态,每种状态都有非常特定的含义。这四种状态是:

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

  • GST_STATE_READY:在就绪状态下,一个element已经分配了它所有的全局资源,即可以保留在流中的资源。您可以考虑打开设备、分配缓冲区等。但是,在此状态下未打开流,因此流位置自动为零。如果之前打开了一个流,它应该在这种状态下关闭,并且应该重置位置、属性等。

  • GST_STATE_PAUSED:在这种状态下,一个element已经打开了流,但没有主动处理它。允许element修改流的位置、读取和处理数据等,以便在状态更改为 PLAYING 后立即准备播放,但不允许播放会使时钟运行的数据。总之,PAUSED 与 PLAYING 相同,但没有运行时钟。

    进入 PAUSED 状态的element应该准备好尽快转移到 PLAYING 状态。例如,视频或音频输出将等待数据到达并将其排队,以便在状态更改后立即播放。此外,视频接收器已经可以播放第一帧(因为这还不会影响时钟)。 Autopluggers 可以使用相同的状态转换来将pipeline连接在一起。但是,大多数其他element(例如编解码器或过滤器)在此状态下不需要显式执行任何操作。

  • GST_STATE_PLAYING:在 PLAYING 状态下,element的行为与 PAUSED 状态下的完全相同,除了时钟现在运行。

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值