图解Gstreamer(N):音频渲染

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);
        }
    }
}

  • 8
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FlightYe

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值