1、本图的基本作用:引导阅读源码,但更重要的是要自己去理解;
2、本图的最大价值:久之,皆已遗忘;顾之,皆已忆起。
一、总览
二、类图与设计
模块功能设计
三、时序图
1、状态NULL_TO_READY
主要完成环形缓冲区的创建,最终设备的open()。
核心代码:
static GstStateChangeReturn gst_audio_base_sink_change_state (GstElement * element,
GstStateChange transition) {
switch (transition) {
case GST_STATE_CHANGE_NULL_TO_READY:{
GstAudioRingBuffer *rb;
gst_audio_clock_reset (GST_AUDIO_CLOCK (sink->provided_clock), 0);
// 创建环形缓冲区
rb = gst_audio_base_sink_create_ringbuffer (sink);
if (rb == NULL)
goto create_failed;
GST_OBJECT_LOCK (sink);
sink->ringbuffer = rb;
GST_OBJECT_UNLOCK (sink);
// 打开输出设备
if (!gst_audio_ring_buffer_open_device (sink->ringbuffer)) {
GST_OBJECT_LOCK (sink);
gst_object_unparent (GST_OBJECT_CAST (sink->ringbuffer));
sink->ringbuffer = NULL;
GST_OBJECT_UNLOCK (sink);
goto open_failed;
}
break;
}
}
2、消息GST_EVENT_CAPS
主要是收到解码器的音频参数,设置到输出设备prepare(),并且创建读环形缓冲器的线程audioringbuffer_thread_func()。
核心代码:
static gboolean gst_audio_base_sink_setcaps (GstBaseSink * bsink, GstCaps * caps)
{
// rclass->acquire()->gst_audio_sink_ring_buffer_acquire()->csink->prepare, eg: gst_alsasink_prepare()
if (!gst_audio_ring_buffer_acquire (sink->ringbuffer, spec))
goto acquire_error;
// 创建线程audioringbuffer_thread_func(), 读取ring_buffer中的数据, 送去渲染.
if (bsink->pad_mode == GST_PAD_MODE_PUSH) {
GST_DEBUG_OBJECT (sink, "activate ringbuffer");
gst_audio_ring_buffer_activate (sink->ringbuffer, TRUE);
}
}
static gboolean gst_audio_sink_ring_buffer_activate (GstAudioRingBuffer * buf, gboolean active)
{
if (active) {
abuf->running = TRUE;
GST_DEBUG_OBJECT (sink, "starting thread");
// 创建读线程
sink->thread = g_thread_try_new ("audiosink-ringbuffer",
(GThreadFunc) audioringbuffer_thread_func, buf, &error);
}
}
3、pad的数据链(push)
完成音视频同步以及将pcm数据写入环形缓冲区。
核心代码:
static GstFlowReturn gst_base_sink_chain_unlocked (GstBaseSink * basesink, GstPad * pad, gpointer obj, gboolean is_list)
{
// 做同步
ret = gst_base_sink_do_sync (basesink, GST_MINI_OBJECT_CAST (sync_buf),
&late, &step_end);
// 送pcm数据到缓冲区
if (bclass->render)
ret = bclass->render (basesink, GST_BUFFER_CAST (obj));
}
static guint default_commit (GstAudioRingBuffer * buf, guint64 * sample,
guint8 * data, gint in_samples, gint out_samples, gint * accum) {
// 将数据写入循环缓冲区
data = data_end + bpf;
}
4、缓冲区读取
完成将pcm数据从环形缓冲区读出来,写入播放设备。
核心代码:
static void audioringbuffer_thread_func (GstAudioRingBuffer * buf) {
while (TRUE) {
gint left, len;
guint8 *readptr;
gint readseg;
// 从ring_buffer中取数据.
if (gst_audio_ring_buffer_prepare_read (buf, &readseg, &readptr, &len)) {
gint written;
left = len;
do {
// eg: gst_alsasink_write(), 将pcm写入数据设备
written = writefunc (sink, readptr, left);
}
}
}