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

    技术2026-01-16  9

    首先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;}

    最新回复(0)