事件
事件是与缓冲区数据流并行传递的对象,以通知element各种事件。
使用事件函数在pad上接收事件。一些事件应该与数据流交错,因此它们需要采用 STREAM_LOCK,而另一些则不需要。
存在不同类型的事件来实现各种功能。
- GST_EVENT_FLUSH_START:数据将被丢弃
- GST_EVENT_FLUSH_STOP:再次允许数据
- GST_EVENT_CAPS:关于随后的缓冲区的格式信息
- GST_EVENT_SEGMENT:关于随后的缓冲区的时序信息
- GST_EVENT_TAG:关于流的元数据信息。
- GST_EVENT_BUFFERSIZE:缓冲区大小要求。目前还没有使用。
- GST_EVENT_SINK_MESSAGE:事件被接sink转化为消息
- GST_EVENT_EOS:pad上不会出现更多数据。
- GST_EVENT_QOS:流服务质量的通知
- GST_EVENT_SEEK:应该定位到流的新位置
- GST_EVENT_NAVIGATION:导航事件。
- GST_EVENT_LATENCY:配置pipeline的延迟
- GST_EVENT_STEP:步进事件
- GST_EVENT_RECONFIGURE:流重新配置事件
源垫(source pad)
srcpad 上的 gst_pad_push_event() 将首先将粘性事件存储在粘性数组中,然后再将事件发送到peer pad。如果没有peer pad并且事件没有存储在粘性数组中,则返回 FALSE。
Flushing pads将拒绝事件并且不会存储粘性事件。
接收垫(sink pad)
在sinkpad 上调用 gst_pad_send_event() 将调用 pad 上的事件函数。如果事件函数返回成功,则粘滞事件存储在粘滞事件数组中,并将该事件标记为更新。
当pad 冲洗时,gst_pad_send_event() 函数立即返回 FALSE。
当下一个数据项被推送时,挂起的事件被首先推送。
这确保了永远不会为flushing pads调用事件函数,并且粘性数组仅包含事件函数返回成功的事件。
垫链接(pad link)
链接 pads 时,srcpad 粘性事件在与 sinkpad 事件不同时被标记为更新。下一次缓冲区推送会将事件推送到sink。
FLUSH_START/STOP
向下游和上游发送flush事件以清除pipeline中的任何挂起数据。当正常数据流被例如seek事件中断时,这可能需要使图像更具响应性。
Flushing 发生在两个阶段。
-
source element将 FLUSH_START 事件发送到下游peer element。下游element开始拒绝来自上游element的缓冲区。它向下游进一步发送flush 事件,并尽快丢弃它持有的任何缓冲区并从链函数返回。这确保所有上游element都被取消阻塞。此事件与 STREAM_LOCK 不保持同步,可以在应用程序线程中完成。
-
source element发送 FLUSH_STOP 事件以指示下游element可以再次接收缓冲区。下游element将flush 事件发送到其peer element。在此步骤之后,数据流继续。 FLUSH_STOP 调用与 STREAM_LOCK 保持同步,因此如果需要,链函数使用的任何数据都可以在这里安全地释放。任何未决的EOS事件也应该被丢弃。
flush 完成第二阶段后,数据再次在pipeline中流动,并且所有缓冲区都比刷新之前的缓冲区更新。
对于使用 pullrange 函数的element,它们以相同的方式将两个flush 事件发送到上游 pads,以确保 pullrange 函数解锁并清除上游element中的任何挂起缓冲区。
FLUSH_START 可以指示pipeline将新的 base_time 分配给element,以便将 running_time 重置为 0。(参见时钟和同步)。
流结束(EOS)
EOS 事件只能在sink上发送。它通常在source element完成发送数据时发出。此事件主要在流线程中发送,但也可以从应用程序线程中发送。
下游element应将 EOS 事件转发到其下游peer element。这样,事件最终将到达sink,然后sink应在PLAYING状态时在总线上发布 EOS 消息。
在向下游转发 EOS 事件之前,element可能希望flush其内部排队的数据。这种flush可以在与处理 EOS 事件的线程相同的线程中完成。
对于具有多个sinkpad的element,可能在转发事件之前等待所有pad上的EOS。
EOS 事件应始终与数据流交错,因此 GStreamer core将采用 STREAM_LOCK。
有时 EOS 事件是由另一个element而不是source element生成的,例如,demuxer element可以在source element之前生成 EOS 事件。这不是问题,demuxer 不会向上游element发送 EOS 事件,而是返回 GST_FLOW_EOS,导致source element停止发送数据。
在pad上发送 EOS 的element应停止在该pad上发送数据。为此,source element通常会 pause() 其任务。
默认情况下,GstBin在将EOS消息发送给它的父对象之前,会从它所有的sink中收集所有的EOS消息。
EOS 仅由处于 PLAYING 状态的sink element发布到总线上。如果在 PAUSED 状态下接收到 EOS 事件,它会进入等候队列直到element进入 PLAYING状态。
element上的 FLUSH_STOP 事件会刷新 EOS 状态和所有挂起(pending) EOS 消息。
段(SEGMENT)
segment 事件由element向下游发送,以指示以下缓冲区组在指定位置开始和结束。newsegment 事件还包含流的播放速度和使用的速率(the applied rate of the stream)。
由于流时间总是在start和seek之后被设置为0,所有下一个缓冲区的时间戳的0点必须使用SEGMENT事件通过pipeline传播。
在发送缓冲区之前,element必须发送 SEGMENT 事件。如果缓冲区之前没有 SEGMENT 事件,则element可以自由的拒绝缓冲区。
与时钟同步的element应存储 SEGMENT 开始和结束值,并在将其与流时间进行比较之前从缓冲区时间戳中减去开始值(请参阅时钟)。
允许element发送已经从时间戳中减去 SEGMENT 开始时间的缓冲区。如果它这样做,它需要向下游发送一个校正的SEGMENT ,即起始时间为0的segment。
SEGMENT 事件应在pipeline中尽快生成,通常由demuxer 或source生成。该事件在推送第一个缓冲区之前和seek之后,就在推送新缓冲区之前生成。
SEGMENT 事件应该从流线程发送并且应该与缓冲区序列化。
缓冲区应该在由newsegment 事件开始和停止值指示的范围内裁剪。sink必须丢弃时间戳超出指定段范围的缓冲区。
标签(tag)
当element在媒体文件中发现元数据tag时,tag事件被发送到下游。编码器可以使用此事件来调整其tagging 系统。tag与缓冲区序列化。
缓冲大小(BUFFERSIZE)
注意 此事件尚未实现。
element可以提议下游element的缓冲区大小。这通常由在多个source pad上生成数据的element完成,例如demuxers。
服务质量(QOS)
QOS或quality of service消息在element中生成以向上游element报告关于当前流的实时性能的质量。这通常由sink完成测量丢帧量。 (见qos)
(定位)seek
应用程序发出seek事件以配置流的播放范围。它从应用程序线程中调用并向上游传输。
seek事件包含执行seek后播放的新开始和停止位置。可以选择将停止位置保留为 -1 以继续播放到流的末尾。 seek 事件还包含流的新播放速率,1.0 是正常播放,2.0 倍速和负值表示向后播放。
seek通常会刷新图像以最小化查找后的延迟。此行为是通过在seek事件上使用 SEEK_FLUSH 标志来触发的。
seek事件通常从sink element开始,并从element到element向上游传播,直到到达可以执行seek的element。不允许任何中间element假设会发生对该位置的seek。如果需要,允许修改开始和停止时间。这种典型的情况是seek请求的是一个非时间的位置。
实际的seek是在应用程序线程中执行的,因此可以将成功或失败报告为seek事件的返回值。因此,在执行seek之前,element获取STREAM_LOCK,以便流线程和seek被序列化,这一点很重要。
使用 FLUSH 执行seek的一般流程如下:
-
解除阻塞流线程,它们可以在链函数中被阻塞。这是通过在所有 srcpad 上发送 FLUSH_START 或暂停流任务来完成的,具体取决于seek 的 FLUSH 标志。flush 将确保所有下游element解锁,并且该控制将返回到此element的chain/loop函数。在执行此操作之前我们不能锁定 STREAM_LOCK,因为它可能会导致死锁。
-
获取 STREAM_LOCK。这是没有问题的,因为 chain/loop 函数在步骤 1) 中被unlocked/paused。
-
执行seek。由于持有STREAM_LOCK,流线程将等待seek完成。最可能的情况是,流线程将暂停,因为peer element正在刷新。
-
向所有peer element发送 FLUSH_STOP 事件以再次允许流传输。
-
创建一个 SEGMENT 事件来通知新的缓冲区时间戳基准时间。此事件必须排队等待以便由流线程发送。
-
启动停止的任务并解锁 STREAM_LOCK,数据流将从新位置继续。
有关不同seek类型的更多信息可以在seek中找到。
导航 (NAVIGATION)
导航事件由sink element生成,以向导航事件的element发出信号,例如鼠标移动或按钮单击。导航事件向上游传播。
延迟(LATENCY)
延迟事件用于配置pipeline中的特定延迟。它包含具有所需延迟的单个 GstClockTime。延迟值由pipeline计算并在设置为 PLAYING 之前分配给所有sink element。sink 会将配置的延迟值添加到缓冲区的时间戳中,以延迟它们的渲染。 (另见延迟)。