首先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;
}
阅读(4859) | 评论(1) | 转发(0) |