Gstreamer之Clock时间机制

说到Gstreamer的时间,我想从时间的传递开始,这样我们才能了解Gstreamer时间机制的来龙去脉。
在Gstreamer中时间的传递主要有两个载体:
1. 随着GstBuffer在各个element中传递;
2. event事件;

对于第一种情况,因为不论你用的何种播放器都要有PTS然后音视频才能正常同步、播放,而这个GstBuffer中正是提供了这样一个成员timestamp来存储PTS。说到这也许要的童鞋们可能就要问了,既然有PTS那DTS在哪呢?很不幸的是Gstreamer0.10中的GstBuffer并不提供类似的成员,那这时你想说完蛋了,那我在有些特殊情况下必须要使用DTS怎么办呢?这个不是“坑人”吗?其实也不用担心的,你只需要通过GstBuffer中duration来存放delt(delt=PTS-DTS)。这样你知道了PTS还知道了delt,就可以在你后面的程序中反向计算出DTS来。

struct _GstBuffer {
  GstMiniObject          mini_object;

  /*< public >*/ /* with COW */
  /* pointer to data and its size */
  guint8                *data;
  guint                  size;

  /* timestamp */
  GstClockTime           timestamp;
  GstClockTime           duration;

  /* the media type of this buffer */
  GstCaps               *caps;

  /* media specific offset */
  guint64                offset;
  guint64                offset_end;

  guint8                *malloc_data;

  /* ABI Added */
  GFreeFunc              free_func;
  GstBuffer             *parent;

  /*< private >*/
  gpointer _gst_reserved[GST_PADDING - 2];
};
注:如果你现在用的是Gstreamer1.0,那你就可以偷着笑了,因为你就不用担心什么反向计算什么的了,新的GstBuffer提供存储DTS的字段,所以你就可以不用管了。


对于第二种情况,我们最常见的使用方式是在source-element中,当数据送达之前可以有其发送event,实例如下

gst_pad_push_event (sdi->videopad, gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, sdi->clock_base, -1, 0));
gst_pad_push_event (sdi->audiopad, gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, sdi->clock_base, -1, 0));
这时如果有兴趣的童鞋就又会问了,“哦,这个地方一定要发送吗?我不弄行不?”答案是在某些情况下也行。那这会你是不是又会说,你这不是“调戏我们吗?什么叫在某些情况下?”那我只能说莫急,这和Gstreamer的同步机制有点关系。如果设置不正确,有可能就会在某个sink-element中hung在gst_clock_id_wait()中了。


实际上前面push的那个event的主要意图是,通知其后的所有element更新自己的base_time。而这个base_time又和running_time的计算息息相关。


说到这大家开始晕了,什么又是base_time,什么又是running_time?
对此我对一些在Gstreamer中常用的时钟概念做一个大致的解释吧!
1、clock time(absolute_time): 管道维护的一个全局时钟,是一个以纳秒为单位单调递增的时钟时间。可以通过gst_clock_get_time()函数获取。如果管道中没有元素提供时钟,则使用该系统时钟。
2、base time: 媒体从0开始时全局的时间值。可以通过_get_time()函数获取。
3、Running time: 媒体处于PLAYING状态时流逝的时间。
4、stream time: 媒体播放的位置(在整个媒体流中)。
公式:
running_time = clock_time - base_time;


到此我想大家对Gstreamer的时间机制大致有个了解了,那接下来我就说说在Gstreamer中一些常用API函数,他到底在做些什么?

GstClockTime gst_clock_get_time (GstClock * clock);
这个函数大致是工具所提供的clock获取当前的系统时间

gint64 gst_segment_to_running_time (GstSegment * segment, GstFormat format, gint64 position);

其实就是running_time = position - base_time + accum;简单明了

guint64 gst_util_uint64_scale(val , num, den);
这里随便提一个函数,这个函数可以等价于 return (val*num/den);只不过里面做了防止溢出处理,所以不用担心溢出问题的。


最后列一下Gstreamer中常见的时间宏,注意Gstreamer中的时间单位是:纳秒
#define G_USEC_PER_SEC 1000000
#define GST_SECOND  (G_USEC_PER_SEC * G_GINT64_CONSTANT (1000))
#define GST_MSECOND (GST_SECOND / G_GINT64_CONSTANT (1000))
#define GST_USECOND (GST_SECOND / G_GINT64_CONSTANT (1000000))
#define GST_NSECOND (GST_SECOND / G_GINT64_CONSTANT (1000000000))

整理之后,等价表示
GST_SECOND  = 1000000000 ns
GST_MSECOND = 1000000 ns
GST_USECOND = 1000 ns
GST_NSECOND = 1 ns


-流媒体-

你可能感兴趣的:(Gstreamer)