关于android下audioflinger+alsa+a2dp+pcm+bluez+sbc编码理解

首先audioflinger创建音频hw类-比如alsa类,如果打开了with_a2dp编译选项,那么随后a2dpaudiointerface类将
作为audioflinger最终使用的hw类,[luther.gliethttp]
如果打开一个device,将调用a2dpaudiointerface::openoutputstream,如果该device不是a2dp设备,那么
a2dpaudiointerface类将直接调用alsa类提供的函数openoutputstream打开实际的alsa设备,
可见android系统a2dp功能根本就用不到alsa的任何东西,即便audio驱动没有完成a2dp仍然可独立使用[luther.gliethttp].


对于media等音频的发送,首先是由audioflinger将通过借助binder采用ashmem共享文件方式推入数据的各个track
进行mixer,所有mixer后的最终pcm数据将被推入moutput->write(curbuf, mixbuffersize);也就是
a2dpaudiointerface::a2dpaudiostreamout::write(const void* buffer, size_t bytes);
随后这些裸pcm数据将被送入bluez的a2dp_write(mdata, buffer, remaining);进行sbc_encode即sbc编码,
透过socket或者rfcomm送到bluetooth chip芯片最后发送到air等待a2dp设备接收.[luther.gliethttp]

audiohardwareinterface* audiohardwareinterface::create()
{
    ......
    hw = createaudiohardware(); // 调用alsa_sound/audiohardwarealsa.cpp构造函数
    ......
#ifdef with_a2dp
    hw = new a2dpaudiointerface(hw); // 使用a2dp作为默认hw,这样a2dp这个hw类发现device不是a2dp时
#endif                               // 它会调用alsa的hw打开设备,否则将自己打开该a2dp device[luther.gliethttp]
    ......
    return hw;
}

audiostreamout* a2dpaudiointerface::openoutputstream(
        uint32_t devices, int *format, uint32_t *channels, uint32_t *samplerate, status_t *status)
{
    if (!audiosystem::isa2dpdevice((audiosystem::audio_devices)devices)) {
        logv("a2dpaudiointerface::openoutputstream() open hw device: %x", devices);
        return mhardwareinterface->openoutputstream(devices, format, channels, samplerate, status);
    }

    status_t err = 0;

    // only one output stream allowed
    if (moutput) {
        if (status)
            *status = -1;
        return null;
    }

    // create new output stream
    a2dpaudiostreamout* out = new a2dpaudiostreamout();
    if ((err = out->set(devices, format, channels, samplerate)) == no_error) {
        moutput = out;
        moutput->setbluetoothenabled(mbluetoothenabled);
        moutput->setsuspended(msuspended);
    } else {
        delete out;
    }

    if (status)
        *status = err;
    return moutput;
}

frameworks/base/libs/audioflinger/a2dpaudiointerface.cpp
==> a2dpaudiointerface::a2dpaudiostreamout::init
==> 调用external/bluetooth/bluez/audio/liba2dp.c中的
==> a2dp_init(44100, 2, &mdata);

ssize_t a2dpaudiointerface::a2dpaudiostreamout::write(const void* buffer, size_t bytes)
{
    mutex::autolock lock(mlock);

    size_t remaining = bytes;
    status_t status = -1;

    if (!mbluetoothenabled || mclosing || msuspended) {
        logv("a2dpaudiostreamout::write(), but bluetooth disabled /
               mbluetoothenabled %d, mclosing %d, msuspended %d",
                mbluetoothenabled, mclosing, msuspended);
        goto error;
    }

    status = init();
    if (status < 0)
        goto error;

    while (remaining > 0) {
        status = a2dp_write(mdata, buffer, remaining);
        if (status <= 0) {
            loge("a2dp_write failed err: %d/n", status);
            goto error;
        }
        remaining -= status;
        buffer = ((char *)buffer) + status;
    }

    mstandby = false;

    return bytes;

error:
    // simulate audio output timing in case of error
    usleep(((bytes * 1000 )/ framesize() / samplerate()) * 1000);

    return status;
}

int a2dp_write(a2dpdata d, const void* buffer, int count)
{
    struct bluetooth_data* data = (struct bluetooth_data*)d;
    uint8_t* src = (uint8_t *)buffer;
    int codesize;
    int err, ret = 0;
    long frames_left = count;
    int encoded;
    unsigned int written;
    const char *buff;
    int did_configure = 0;
#ifdef enable_timing
    uint64_t begin, end;
    dbg("********** a2dp_write **********");
    begin = get_microseconds();
#endif

    err = wait_for_start(data, write_timeout);
    if (err < 0)
        return err;

    codesize = data->codesize;

    while (frames_left >= codesize) {
        /* enough data to encode (sbc wants 512 byte blocks) */
        encoded = sbc_encode(&(data->sbc), src, codesize,
                    data->buffer + data->count,
                    sizeof(data->buffer) - data->count,
                    &written);
        if (encoded <= 0) {
            err("encoding error %d", encoded);
            goto done;
        }
        vdbg("sbc_encode returned %d, codesize: %d, written: %d/n",
            encoded, codesize, written);

        src += encoded;
        data->count += written;
        data->frame_count++;
        data->samples += encoded;
        data->nsamples += encoded;

        /* no space left for another frame then send */
        if ((data->count + written >= data->link_mtu) ||
                (data->count + written >= buffer_size)) {
            vdbg("sending packet %d, count %d, link_mtu %u",
                    data->seq_num, data->count,
                    data->link_mtu);
            err = avdtp_write(data);
            if (err < 0)
                return err;
        }

        ret += encoded;
        frames_left -= encoded;
    }

    if (frames_left > 0)
        err("%ld bytes left at end of a2dp_write/n", frames_left);

done:
#ifdef enable_timing
    end = get_microseconds();
    print_time("a2dp_write total", begin, end);
#endif
    return ret;
}

作者:Siobhan 发表于2011-2-17 17:46:00 原文链接
阅读:472 评论:0 查看评论
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值