对于第一种情况,因为不论你用的何种播放器都要有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()中了。
其实就是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