Gstreamer的音视频同步
来源:互联网 发布:风驰网络加速器 官网 编辑:程序博客网 时间:2024/04/29 05:17
一 概述
Gstreamer的音频视频同步,概括起来是一个比较大的问题,因为在网上可以看到很多音视频同步的办法。这里我们只看最普通的一种。以音频时钟做为参考时钟(要求参考时钟上的时间是线性递增的);生成数据流时依据参考时钟上的时间给每个数据块都打上时间戳(一般包括开始时间和结束时间);在播放时,读取数据上的时间戳,同时参考当前参考时钟上的时间来安排播放(如果数据块上的时间大于参考时钟的时间,则不急于播放,直到参考时钟达到数据块的开始时间;如果数据块上的时间小于参考时钟的时间,则应"尽快"播放或者干脆"丢弃"该数据块,以使得播放赶上播放进度。)
Gstreamer的因视频分离器如下图:
demux element将音频,视频分离后,给各自的解码器进行解码播放。
+-----------+ | Audio | +--| | / +-----------+ +----------+ / | demux |/ | |\ +----------+ \ \ +-----------+ +--| Video | | | +-----------+
二 提供时钟
默认情况下,是有AudioSink来提供参考时钟的。下面开始代码之旅。
/* gst-plugins-base-0.10.32/gst-libs/gst/audio/gstbaseaudiosink.c *//*默认的情况下是由这个element来提供clock的。*/#define DEFAULT_PROVIDE_CLOCK TRUEstatic voidgst_base_audio_sink_init (GstBaseAudioSink * baseaudiosink, GstBaseAudioSinkClass * g_class){ baseaudiosink->provide_clock = DEFAULT_PROVIDE_CLOCK /* 这里在clock类里面新建了一个时钟 */ baseaudiosink->provided_clock = gst_audio_clock_new ("GstAudioSinkClock", (GstAudioClockGetTimeFunc) gst_base_audio_sink_get_time, baseaudiosink);}/* * 查询是否 @sink 将提供 clock */gbooleangst_base_audio_sink_get_provide_clock (GstBaseAudioSink * sink){ gboolean result; result = sink->provide_clock; return result;}/* 查询clock的时间 * 如果将这里的返回结果变慢,那么视频播放就会变慢。当然视频很音频就不同步了。 */static GstClockTimegst_base_audio_sink_get_time (GstClock * clock, GstBaseAudioSink * sink){ result = gst_util_uint64_scale_int (samples, GST_SECOND, sink->ringbuffer->spec.rate); return result;}
三 视频如何同步?
以我实验的视频为例,视频使用的是xvimagesink element它的继承关系如下
GObject +----GstObject +----GstElement +----GstBaseSink +----GstVideoSink +----GstXvImageSink从element的chain func开始(PS: 为什么从chain开始,参考[Gstreamer初见]).
/* * gst-plugins-base/sys/xvimage/xvimagesink.c * gst-plugins-base/gst-libs/gst/video/gstvideosink.c * 这两个文件里都没有chain函数. * 在gstreamer-0.10.32/libs/gst/base/gstbasesink.c中 chain函数为 */static GstFlowReturngst_base_sink_chain (GstPad * pad, GstBuffer * buf){ basesink = GST_BASE_SINK (GST_OBJECT_PARENT (pad)); return gst_base_sink_chain_main (basesink, pad, _PR_IS_BUFFER, buf);}static GstFlowReturngst_base_sink_chain_main (GstBaseSink * basesink, GstPad * pad, guint8 obj_type, gpointer obj){ result = gst_base_sink_chain_unlocked (basesink, pad, obj_type, obj);}static GstFlowReturngst_base_sink_chain_unlocked (GstBaseSink * basesink, GstPad * pad, guint8 obj_type, gpointer obj){ result = gst_base_sink_queue_object_unlocked (basesink, pad, obj_type, obj, TRUE);}static GstFlowReturngst_base_sink_queue_object_unlocked (GstBaseSink * basesink, GstPad * pad, guint8 obj_type, gpointer obj, gboolean prerollable) { while (G_UNLIKELY (!g_queue_is_empty (q))) { ret = gst_base_sink_render_object (basesink, pad, ot, o); }}/* gstreamer-0.10.32/libs/gst/base/gstbasesink.c */static GstFlowReturngst_base_sink_render_object (GstBaseSink * basesink, GstPad * pad, guint8 obj_type, gpointer obj){ /* 这里开始做同步,同步成功后,才开始播放 */ ret = gst_base_sink_do_sync (basesink, pad, sync_obj, &late, &step_end, obj_type); if (G_UNLIKELY (ret != GST_FLOW_OK)) goto sync_failed; if (!OBJ_IS_BUFFERLIST (obj_type)) { ret = bclass->render (basesink, buf); } else { ret = bclass->render_list (basesink, buflist); }}static GstFlowReturngst_base_sink_do_sync (GstBaseSink * basesink, GstPad * pad, GstMiniObject * obj, gboolean * late, gboolean * step_end, guint8 obj_type){ status = gst_base_sink_wait_clock (basesink, stime, &jitter); return GST_FLOW_OK;}/* * @time: the running_time to be reached * @jitter: (out) (allow-none): the jitter to be filled with time diff, or NULL * * This function will block until @time is reached. It is usually called by * subclasses that use their own internal synchronisation. */GstClockReturngst_base_sink_wait_clock (GstBaseSink * sink, GstClockTime time, GstClockTimeDiff * jitter){ if (G_UNLIKELY ((clock = GST_ELEMENT_CLOCK (sink)) == NULL)) goto no_clock; base_time = GST_ELEMENT_CAST (sink)->base_time; sink->priv->cached_clock_id = gst_clock_new_single_shot_id (clock, time); /* 这里一直等待到时间 */ ret = gst_clock_id_wait (sink->priv->cached_clock_id, jitter); return ret;}
这里同步完成,其实这里还有最后一个小问题,那么就是AudioClock是以什么为时钟的呢。其实就是以声卡的时钟为时钟的。因为声卡有时钟同步功能。所以我们计算一同播放了多少个sample,就可以计算出当前播放了多长的时间。 So.
END
- Gstreamer的音视频同步
- Gstreamer的音视频同步 .
- Gstreamer的音视频同步
- Gstreamer的同步机制
- GStreamer下的音视频播放
- GStreamer下的音视频播放
- 【miscellaneous】GStreamer下的音视频播放
- 基于gstreamer的视频转发
- 基于DM3730平台的gstreamer音视频传输调试
- ubuntu下 gstreamer 的配置及播放音视频例子
- 用gstreamer抓取视频的缩略图
- Gstreamer/Core: Gstreamer 同步机制
- gstreamer 学习笔记 -- 音视频播放
- 关于音视频的同步
- 音视频的同步原理
- 音视频的同步原理
- 音视频的同步原理
- ubuntu下 gstreamer 的配置及播放音视频例子(已经验证)
- oracle exchange特性做sql优化测试
- 精通top,ps命令
- interpolating between 2D slices
- 在fedora下使用google yum源来安装chrome
- ios 内存使用陷阱
- Gstreamer的音视频同步
- daemon tools lite安装完成后,“无法添加适配器,设备错误12” 解决方法
- SQL GROUP BY 语句
- Android RoboGuice2 使用指南(4): 综合示例Astroboy
- PMBOK(第4版)--第5章 项目项目范围管理(概述、输入、工具与技术、输出、数据流向图)
- Oracle 11G Client 客户端安装步骤(图文详解)
- android数据存储
- setlogmask() linux
- 企业信息化实施风险