GStreamer 基础教程学习 4 - 时间管理 (Basic tutorial 4: Time management)

https://gstreamer.freedesktop.org/documentation/tutorials/basic/time-management.html?gi-language=c

本节介绍和时间相关的内容,主要有两点: 

  • How to query the pipeline for information like stream position or duration.
  • How to seek (jump) to a different position (time) inside the stream.

如何从管道获取流的信息,例如位置和长度;

如何在流中不同的位置(时间)进行跳转。

GstQuery is a mechanism that allows asking an element or pad for a piece of information. In this example we ask the pipeline if seeking is allowed (some sources, like live streams, do not allow seeking). If it is allowed, then, once the movie has been running for ten seconds, we skip to a different position using a seek.

GstQuery用来从一个元素element或pad获取信息。本节中的例子,询问管道是否支持Seeking(因为有些不支持该功能),如果支持的话,使用Seeking跳转到不同的位置。

之前的几节,在管道进入播放状态后,使用了一个阻塞函数等待管道的错误信息或者流结束信号EOS。这一节会周期性的调用查询函数获取当前流的位置。

msg = gst_bus_timed_pop_filtered (bus, 100 * GST_MSECOND,
    GST_MESSAGE_STATE_CHANGED | GST_MESSAGE_ERROR | GST_MESSAGE_EOS | GST_MESSAGE_DURATION);

在之前几节,这个函数是一个阻塞函数,本节设置了timeout为100ms。那么可以知道,在管道正常播放状态下,如果没有错误发生同时也没有结束的情况下, 100ms内是没有信息从管道发出的,那么这个函数就会超时。在超时的分支下,就可以进行其他的判断和操作。 

查询流信息可以通过GstQuery来进行,由于本节的流位置和长度信息是非常常用的流信息。所以有专门的函数来获取他们:

/* Query the current position of the stream */
if (!gst_element_query_position (data.pipeline, GST_FORMAT_TIME, &current)) {
  g_printerr ("Could not query current position.\n");
}

gst_element_query_position() hides the management of the query object and directly provides us with the result.

/* If we didn't know it yet, query the stream duration */
if (!GST_CLOCK_TIME_IS_VALID (data.duration)) {
  if (!gst_element_query_duration (data.pipeline, GST_FORMAT_TIME, &data.duration)) {
     g_printerr ("Could not query current duration.\n");
  }
}

Now is a good moment to know the length of the stream, with another GstElement helper function: gst_element_query_duration()

关于Seeking

if (data->playing) {
  /* We just moved to PLAYING. Check if seeking is possible */
  GstQuery *query;
  gint64 start, end;
  query = gst_query_new_seeking (GST_FORMAT_TIME);
  if (gst_element_query (data->pipeline, query)) {
    gst_query_parse_seeking (query, NULL, &data->seek_enabled, &start, &end);
    if (data->seek_enabled) {
      g_print ("Seeking is ENABLED from %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT "\n",
          GST_TIME_ARGS (start), GST_TIME_ARGS (end));
    } else {
      g_print ("Seeking is DISABLED for this stream.\n");
    }
  }
  else {
    g_printerr ("Seeking query failed.");
  }
  gst_query_unref (query);
}

gst_query_new_seeking() creates a new query object of the "seeking" type, with GST_FORMAT_TIME format. This indicates that we are interested in seeking by specifying the new time to which we want to move. We could also ask for GST_FORMAT_BYTES, and then seek to a particular byte position inside the source file, but this is normally less useful.

This query object is then passed to the pipeline with gst_element_query(). The result is stored in the same query, and can be easily retrieved with gst_query_parse_seeking(). It extracts a boolean indicating if seeking is allowed, and the range in which seeking is possible.

Don't forget to unref the query object when you are done with it.

如果管道支持Seeking

/* If seeking is enabled, we have not done it yet, and the time is right, seek */
if (data.seek_enabled && !data.seek_done && current > 10 * GST_SECOND) {
  g_print ("\nReached 10s, performing seek...\n");
  gst_element_seek_simple (data.pipeline, GST_FORMAT_TIME,
      GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT, 30 * GST_SECOND);
  data.seek_done = TRUE;
}

Now we perform the seek, “simply” by calling gst_element_seek_simple() on the pipeline. A lot of the intricacies of seeking are hidden in this method, which is a good thing!

Seeking的具体属性: 

Let's review the parameters:

GST_FORMAT_TIME indicates that we are specifying the destination in time units. Other seek-formats use different units.

Then come the GstSeekFlags, let's review the most common:

GST_SEEK_FLAG_FLUSH: This discards all data currently in the pipeline before doing the seek. Might pause a bit while the pipeline is refilled and the new data starts to show up, but greatly increases the “responsiveness” of the application. If this flag is not provided, “stale” data might be shown for a while until the new position appears at the end of the pipeline.

GST_SEEK_FLAG_KEY_UNIT: With most encoded video streams, seeking to arbitrary positions is not possible but only to certain frames called Key Frames. When this flag is used, the seek will actually move to the closest key frame and start producing data straight away. If this flag is not used, the pipeline will move internally to the closest key frame (it has no other alternative) but data will not be shown until it reaches the requested position. This last alternative is more accurate, but might take longer.

GST_SEEK_FLAG_ACCURATE: Some media clips do not provide enough indexing information, meaning that seeking to arbitrary positions is time-consuming. In these cases, GStreamer usually estimates the position to seek to, and usually works just fine. If this precision is not good enough for your case (you see seeks not going to the exact time you asked for), then provide this flag. Be warned that it might take longer to calculate the seeking position (very long, on some files).

Finally, we provide the position to seek to. Since we asked for GST_FORMAT_TIME, the value must be in nanoseconds so we express the time in seconds, for simplicity, and then multiply by GST_SECOND.

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值