二十、GstEvent
1 GstEvent基本概念
-
事件GstEvent是在元素pad间传递,也可以通过应用程序传递给元素的pad.
-
事件在元素之间传递,与数据流并行进行。有些事件与缓冲区序列化,而其他事件则没有。有些事件只能向下游传递,而其他事件只能向上游传递。有些事件可以同时向上游和下游传递。
-
事件用于在数据流中发出特殊条件的信号,例如 EOS(流结束)或开始新的流段。事件还用于清除管道中的任何挂起数据。
-
大多数事件 API 在插件内部使用。应用程序通常只构造和使用寻址事件。为此,可以使用 gst_event_new_seek 来创建一个寻址事件,以指定寻址时间和模式。
GstEvent *event; gboolean result; ... // construct a seek event to play the media from second 2 to 5, flush // the pipeline to decrease latency. event = gst_event_new_seek (1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, 2 * GST_SECOND, GST_SEEK_TYPE_SET, 5 * GST_SECOND); ... result = gst_element_send_event (pipeline, event); if (!result) g_warning ("seek failed"); ...
1.1 事件的传递
-
上游元素(Upstream Elements):上游元素通常是管道中数据生成或输入的起点,它们负责生成或提供多媒体数据流,如音频、视频或其他数据。 上游元素通常是源(Source)元素,例如从文件、网络、摄像头或麦克风等获取数据的元素。
-
下游元素(Downstream Elements):下游元素通常是管道中数据处理或输出的终点。它们负责处理、呈现或传输多媒体数据流。下游元素通常是转码器、渲染器、显示器、存储器或网络输出元素。
-
上游事件(Upstream Events):上游事件是从下游元素传递到上游元素的事件。下游元素sink pad传到上游元素src pad。
-
通常,这些事件用于向上游元素发送信息、请求或控制命令,以影响数据流的生成或传递。
-
例如,一个下游元素可以发送一个上游事件,请求上游元素切换到不同的视频分辨率,或者请求上游元素更改音频编解码器。上游元素可以根据这些事件来调整其行为。
-
-
下游事件(Downstream Events):下游事件是从上游元素传递到下游元素的事件。上游元素src pad传到下游元素sink pad。
我们查看
GstEventTypeFlags
可以发现,GST_EVENT_TYPE_UPSTREAM
就是往上游传递,GST_EVENT_TYPE_DOWNSTREAM
是往下游传递。
注意:
-
下游事件只能 srcpad 调用
gst_pad_push_event (srcpad, event)
,然后sinkpad编写事件处理函数gst_pad_set_event_function (element->sinkpad, gst_my_filter_sink_event)
-
上游事件只能 sinkpad 调用
gst_pad_push_event (sink, event)
,然后srcpad编写事件处理函数gst_pad_set_event_function (element->srcpad, gst_my_filter_src_event)
2 事件类型
黏性事件全都是下游事件
3 GstPad处理事件函数
4 发送事件
我们一般都应该是,发送事件到管道pipeline元素。然后管道的bin中会找到所有的src元素或者sink元素,发送下游或者上游事件。
4.1 GstElement发送事件
/**
* @brief: GstBaseSrc 和 GstSinkSrc会实现 send_event 虚函数
* send_event虚函数,内部调用的是 gst_pad_push_event
*/
gboolean
gst_element_send_event (GstElement * element, GstEvent * event)
{
[...]
result = oclass->send_event (element, event);
[...]
}
4.2 GstPad发送事件
/**
* @pad: a #GstPad to push the event to.
* @event: (transfer full): the #GstEvent to send to the pad.
*
* @brief: 发送事件到@pad的对端pad(和另一个元素相连的pad)
* 这个函数主要是被 Pad处理事件函数调用
*
* @note: 如果@pad是srcpad,那么@event必须是下游事件
* 如果@pad是sinkpad,那么@event必须是上游游事件
* 最后由 gst_pad_send_event_unchecked 调用对端GstPad->eventfunc的事件处理函数
*
* 这个函数会获取event的所有权,所以执行之前需要 gst_event_ref()
*
* Returns: %TRUE if the event was handled.
*
* MT safe.
*/
gboolean
gst_pad_push_event (GstPad * pad, GstEvent * event);
/**
* @note: @event会发送到@pad元素内部的另一端所有的pad。比如@pad是sink pad,这将会调用 @parent的所有src pad进行 gst_pad_push_event
*
* 如果@event是下游事件@pad必须是sink_pad
* 如果@event是上游事件@pad必须是src_pad
*/
gboolean
gst_pad_event_default (GstPad * pad, GstObject * parent, GstEvent * event);
/**
* @pad: a #GstPad to send the event to.
* @event: (transfer full): the #GstEvent to send to the pad.
*
* @brief: 发送事件到@pad,该函数内部会调用该@pad的事件处理函数
*
* @note: 如果@pad是sinkpad,@event必须是下游事件
* 如果@pad是srcpad,@event必须是上游事件
*
* Returns: %TRUE if the event was handled.
*/
gboolean
gst_pad_send_event (GstPad * pad, GstEvent * event);
5 分析GST_EVENT_FLUSH_START事件函数调用过程
分析管道运行会有哪些事件及其作用
参考:https://gstreamer.freedesktop.org/documentation/additional/design/streams.html?gi-language=c
+-----+-------+ +-++-+ +-+ +---+
|START|SEGMENT| |B||B| ... |B| |EOS|
+-----+-------+ +-++-+ +-+ +---+
- segment事件
GstBaseSrc
GstBaseTransform
GstBaseSink
都会存储GstSegment