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

}

阅读(4141) | 评论(1) | 转发(0) |

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐