GStreamer-Event-处理

187 阅读4分钟

事件 GstEvent

有许多不同的事件类型,但它们在管道中的传输方式只有两种:下游或上游。

了解这两种方法的工作原理非常重要,因为如果管道中的一个元素没有正确处理它们,管道的整个事件系统就会被破坏。

下游事件 Downstream event

下游事件通过接收 pad sink pad 的事件处理程序接收,在创建 pad 时使用 gst_pad_set_event_function() 设置。

下游事件可以通过两种方式传输:它们可以是带内 in-band(与缓冲区流串行化)或带外 out-of-band(立即通过管道传输,可能不在与处理缓冲区的流线程相同的线程中, 跳过正在处理或在管道中排队的缓冲区)。 最常见的下游事件(SEGMENT、CAPS、TAG、EOS)均通过缓冲流进行序列化。

这是一个典型的事件函数:


static gboolean
gst_my_filter_sink_event (GstPad  *pad, GstObject * parent, GstEvent * event)
{
  GstMyFilter *filter;
  gboolean ret;

  filter = GST_MY_FILTER (parent);
  ...

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_SEGMENT:
      /* maybe save and/or update the current segment (e.g. for output
       * clipping) or convert the event into one in a different format
       * (e.g. BYTES to TIME) or drop it and set a flag to send a segment
       * event in a different format later */
      ret = gst_pad_push_event (filter->src_pad, event);
      break;
    case GST_EVENT_EOS:
      /* end-of-stream, we should close down all stream leftovers here */
      gst_my_filter_stop_processing (filter);
      ret = gst_pad_push_event (filter->src_pad, event);
      break;
    case GST_EVENT_FLUSH_STOP:
      gst_my_filter_clear_temporary_buffers (filter);
      ret = gst_pad_push_event (filter->src_pad, event);
      break;
    default:
      ret = gst_pad_event_default (pad, parent, event);
      break;
  }

  ...
  return ret;
}

如果你的元件是基于链的 chain-based,你几乎总是必须实现接收器事件函数,因为这是收到有关段 segment、能力 caps 和流结束 end-of-stream 的通知的方式。

如果你的元素完全基于循环,你可能需要也可能不需要接收器事件函数(因为该元素正在驱动管道,它将提前知道流的长度或通过 gst_pad_pull_range() 的流返回值通知。 在某些情况下,即使基于循环的元素也可能从上游接收事件(例如,前面有 id3demux 或 apedemux 元素的音频解码器,或者从源提供输入的解复用器demuxers ,这些源在自定义事件中发送有关流的附加信息, 就像 DVD 源那样)。

上游事件 Upstream Event

上游事件由管道下游某处的元素生成(例如:视频接收器可能生成通知上游元素有关鼠标指针当前位置的导航事件 navigation event)。 这也可能根据应用程序的请求间接发生,例如,当应用程序在管道上执行查找时,该查找请求将被传递到 sink element,该 sink element 随后将生成上游查找事件 seek event。

最常见的上游事件是查找事件 sink event, 服务质量 (QoS) 和重新配置事件 reconfigure event.

可以使用 gst_pad_send_event 函数发送上游事件。 该函数只是调用该 pad 的默认事件处理程序。 pad 的默认事件处理程序是 gst_pad_event_default,它基本上将事件发送到内部链接的 pad 的对等点。 因此,上游事件始终到达元素的 src pad,并由默认事件处理程序处理,除非您重写该处理程序来自己处理它。 在某些特定情况下您必须这样做:

  • 如果您的元件中有多个sink pads。 在这种情况下,您将必须决定将事件发送到哪一个 sink pad(如果不是全部)。
  • 如果您需要在本地处理该事件。 例如,您想要在向上游发送之前转换的导航事件 navigation event,或者您想要处理的 QoS event。

您将在该事件处理程序中执行的处理并不重要,但您必须绝对遵守一些重要规则,因为一个损坏的元素事件处理程序正在破坏整个管道事件处理。 这些规则如下:

  • 始终使用默认的 gst_pad_event_default 方法处理您不会处理的事件。 此方法将根据事件转发事件或删除事件。
  • 如果您要根据收到的事件生成一些新事件,请不要忘记 gst_event_unref 您收到的事件。
  • 事件处理函数应该返回 TRUE 或 FALSE,指示事件是否已被处理。 永远不要简单地在该处理程序中返回 TRUE/FALSE ,除非您确实知道您已经处理了该事件。
  • 请记住,事件处理程序可能是从与流线程不同的线程调用的,因此请确保在所有地方都使用适当的锁定。