首先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 查看评论

更多相关文章

  1. Android(安卓)学习记录-零散知识点
  2. Android完全退出App的一些问题
  3. android Window和ViewRootImpl
  4. ActivityManagerService启动学习
  5. Android9.0 Activity启动流程分析(一)
  6. [android] Activity 的生命周期 以及 横屏竖屏切换时 Activity
  7. Android(安卓)display架构分析四-msm_fb.c 函数和数据结构介绍
  8. android不公开的面试题偶!!!
  9. ffmpeg入门教程之Android使用FFmpeg so(封装格式转换)

随机推荐

  1. Android开发心得(一)
  2. Android软键盘弹出时布局的调整问题
  3. Android神技之 使用SVG以及自定义IconFon
  4. Material Design(六)
  5. Android中图表AChartEngine学习使用与例
  6. Android开发者的福音-良心之选
  7. Android通过WebView实现原生Java与JS交互
  8. Android(安卓)低功耗(BLE)蓝牙(三)
  9. H5跟ios、android数据对接
  10. Android--控件Button的详细用法介绍(适合