mtk android 4.4 audio framework 代码分析(未完成)
2015-07-29 23:07
645 查看
mtk android 4.4 audio framework 代码分析(未完成),有需要的朋友可以参考下。
mtk android 4.4 audio framework 代码分析(未完成)
2/28/2015 3:01:24 PM
关于 audio_policy.conf 文件
这个文件 mediatek/config/$project 下, 在 audiomtkpolicymanager.cpp 中解析,
解析出如下信息:
对应类定义中的 mDefaultOutputDevice
对应类定义中的 mAvailableInputDevices
3)
最重要的解析出 mHwModules,而这个变量的定义在audiomtkpolicymanager.h 中,Vector
APS构造函数分析:
上面关于文件解析的东西其实也属于本节的内容,不过还是单独出去了。
上面已经分析了,解析配置文件。
-》mHwModules[i]->mHandle = mpClientInterface->loadHwModule(mHwModules[i]->mName);
mHandle 是 audio_module_handle_t类型,实际上是 AF中成员变量DefaultKeyedVector
AudioMTKPolicyManager::setOutputDevice 分析
原型:
uint32_t AudioMTKPolicyManager::setOutputDevice(audio_io_handle_t output,
audio_devices_t device,
bool force,
int delayMs)
-》
-》
-》
-》
-》
-》
-》 // update stream volumes according to new device
设备路由:
mOutput 是AudioStreamOut 类型:
-》 out->stream.common.set_parameters = out_set_parameters; HAL层
-》 status_t
AudioMTKStreamOut::setParameters(const String8 &keyValuePairs)
-》 AudioMTKStreamOut::dokeyRouting(uint32_t new_device)
-》 mAudioResourceManager->SelectOutputDevice(new_device);
-》 AudioResourceManager::SelectOutputDevice(uint32_t new_device)
-》 StopOutputDevice(); // 关掉 mDlOutputDevice,
-》 mDlOutputDevice = new_device; 设置NEW device。
-》 AudioResourceManager::StartOutputDevice()
AudioResourceManager::StartOutputDevice() 分析
定义:
-》 AudioResourceManager::TurnonAudioDevice(unsigned int mDlOutputDevice)
-》 mAudioAnalogInstance->AnalogOpen(AudioAnalogType::DEVICE_OUT_EARPIECER,
AudioAnalogType::DEVICE_PLATFORM_MACHINE); 打开对应的设备。
-》 AudioAnalogControl::AnalogOpen
定义:
音量调节 AudioMTKPolicyManager::applyStreamVolumes 分析
-》
for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {
checkAndSetVolume(stream,
mStreams[stream].getVolumeIndex(device),
output,
device,
delayMs,
force);
}
-》传入的参数 StreamDescriptor mStreams[AudioSystem::NUM_STREAM_TYPES]; // stream descriptors for volume control 定义, 实际上类似于一个二维数组,STREAM是第一维, DEVICE是第二维。 上述代码实际上是取出音量的index(int).
checkAndSetVolume 分析
AudioMTKPolicyManager::checkAndSetVolume
定义:
-》
-》
-》
-》
-》
-》
-》
-》
-》
-》
-》
-》
-》
-》
-》
-》
-》
-》
-》
-》
插入耳机路由切换过程 WiredAccessoryManager ###
构造函数中
-》
mObserver = new WiredAccessoryObserver();
-》
init 中 public String getSwitchStatePath() {
return String.format(“/sys/class/switch/%s/state”, mDevName);
}
-》
mAudioManager.setWiredDeviceConnectionState(device, state, headsetName);
-》
AudioService中 public void setWiredDeviceConnectionState(int device, int state, String name) {
synchronized (mConnectedDevices) {
int delay = checkSendBecomingNoisyIntent(device, state);
queueMsgUnderWakeLock(mAudioHandler,
MSG_SET_WIRED_DEVICE_CONNECTION_STATE,
device,
state,
name,
delay);
}
}
-》
checkSendBecomingNoisyIntent 中
sendMsg(mAudioHandler , MSG_BROADCAST_AUDIO_BECOMING_NOISY,
SENDMSG_REPLACE,
0,
0,
null,
0);
delay = 1000;
Senmsg在handler中处理
-》
i.setAction(MediaPlaybackService.SERVICECMD);
i.putExtra(MediaPlaybackService.CMDNAME, MediaPlaybackService.CMDPAUSE);
context.startService(i);
-》
在 mediaplayerservice 中处理
else if (CMDPAUSE.equals(cmd) || PAUSE_ACTION.equals(action)
|| AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(action)) {
pause();
mPausedByTransientLossOfFocus = false;
}
-》 audioservice 中
-》
private void onSetWiredDeviceConnectionState(int device, int state, String name)
{
synchronized (mConnectedDevices) {
Log.d(TAG,”onSetWiredDeviceConnectionState:” + “device:” + device + “,state:” + state);
if ((state == 0) && ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) ||(device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE))) { // 耳机
/// M: Change for sound output from device
when a2dp conneted @ {
//setBluetoothA2dpOnInt(true); AudioSystem.setForceUse(AudioSystem.FOR_MEDIA,AudioSystem.FORCE_NONE);
///@}
}
boolean isUsb = ((device & AudioSystem.DEVICE_OUT_ALL_USB) != 0);
handleDeviceConnection((state == 1), device, (isUsb ? name : “”));
if (state != 0) {
if ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) ||
(device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE)) {
setBluetoothA2dpOnInt(false);
}
if ((device & mSafeMediaVolumeDevices) != 0) {
sendMsg(mAudioHandler,
MSG_CHECK_MUSIC_ACTIVE,
SENDMSG_REPLACE,
0,
0,
null,
MUSIC_ACTIVE_POLL_PERIOD_MS);
}
}
if (!isUsb) {
sendDeviceConnectionIntent(device, state, name);
}
}
}
AudioSystem.setForceUse 分析 handleDeviceConnection(audioservice) 分析
boolean isUsb = ((device & AudioSystem.DEVICE_OUT_ALL_USB) != 0);
handleDeviceConnection((state == 1), device, (isUsb ? name : “”));
下面是定义:
-》
-》
-》
-》
-》
-》
-》
-》
-》
-》
-》
-》
-》
-》
-》
-》
-》
-》
Audioservice中重要变量:
AudioTrack 跟踪
-》
int initResult = native_setup(new WeakReference(this),
mStreamType, mSampleRate, mChannels, mAudioFormat,
mNativeBufferSizeInBytes, mDataLoadMode, session);
-》
-》
->
->
status =
hwDevHal->open_output_stream(hwDevHal,
id,
*pDevices,
(audio_output_flags_t)flags,
&config,
&outStream);
outStream 是在HAL层分配的,然后返回到AF中。
-》
->
-》
-》
-》
-》
-》
-》
uint32_t actual = AudioSystem::getStrategyForStream(t->streamType());
track = new Track(this, client, streamType, sampleRate, format,
channelMask, frameCount, sharedBuffer, sessionId, uid, *flags);
-》
AudioFlinger::PlaybackThread::Track::Track
-》
AudioTrackServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
size_t frameSize, bool clientInServer = false)
: ServerProxy(cblk, buffers, frameCount, frameSize, true /isOut/, clientInServer) { }
-》
然后根据这个 streamout 和ID, NEW threads. 然后ADD 到 AF中的 mPlaybackThreads。
-》hwDevHal->set_mode(hwDevHal, mMode); // 大概是 设置MODE, NORMAL , CALL MODE? 条件是 (mPrimaryHardwareDev == NULL) ,只有第一次AudioFlinger::openOutput 时会设置模式。
HAL 层open_output_stream
Audio_hw_hal.cpp 中关于
legacy_adev_open 中将
ladev->device.open_output_stream = adev_open_output_stream;
-》 adev_open_output_stream
-》
static int adev_open_output_stream(struct
audio_hw_device *dev,
audio_io_handle_t handle,
audio_devices_t devices,
audio_output_flags_t flags,
struct audio_config *config,
struct audio_stream_out **stream_out)
{
struct legacy_audio_device *ladev = to_ladev(dev);
status_t
status;
struct legacy_stream_out *out;
int ret;
-》AudioHardwareALSA::openOutputStream
-》
/*==============================================================================
* Implementations
============================================================================/
-》
android_audio_legacy::AudioStreamOut *AudioALSAStreamManager::openOutputStream(
uint32_t devices,
int *format,
uint32_t *channels,
uint32_t *sampleRate,
status_t
*status)
{
ALOGD(“+%s()”, FUNCTION);
AudioAutoTimeoutLock streamVectorAutoTimeoutLock(mStreamVectorLock);
AudioAutoTimeoutLock _l(mLock);
-》audioAStreamManager::openOutputStream
-》audioALSAStreamOut::open
-》audioALSAStreamOut::open()
-》playbackHandler = mStreamManager->createPlaybackHandler(&mStreamAttributeSource);
-> // open codec
driver
mHardwareResourceManager->startOutputDevice(mStreamAttributeSource->output_devices, mStreamAttributeTarget.sample_rate);
mtk android 4.4 audio framework 代码分析(未完成)
2/28/2015 3:01:24 PM
关于 audio_policy.conf 文件
这个文件 mediatek/config/$project 下, 在 audiomtkpolicymanager.cpp 中解析,
解析出如下信息:
1) ATTACHED_OUTPUT_DEVICES_TAG "attached_output_devices" ,对应 类定义中的变量 mAttachedOutputDevices 2 ) #define DEFAULT_OUTPUT_DEVICE_TAG "default_output_device"
对应类定义中的 mDefaultOutputDevice
#define ATTACHED_INPUT_DEVICES_TAG "attached_input_devices"
对应类定义中的 mAvailableInputDevices
mHasA2dp = true; 根据文件解析出是否有此MODULE。 mHasUsb = true; 根据文件接触出是否有此MODULE。 mHasRemoteSubmix = true; 根据文件接触出是否有此MODULE。
3)
最重要的解析出 mHwModules,而这个变量的定义在audiomtkpolicymanager.h 中,Vector
APS构造函数分析:
上面关于文件解析的东西其实也属于本节的内容,不过还是单独出去了。
-》mpClientInterface = clientInterface; 就是APS -》 AudioMTKPolicyManager::LoadCustomVolume -》GetVolumeVer1ParamFromNV 从NVRAM里读取参数,这个暂且不表。 -》initializeVolumeCurves(); // 初始化VOLUME曲线,SETVOLUME时会用到,以后分析。 -》if (loadAudioPolicyConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE) != NO_ERROR)
上面已经分析了,解析配置文件。
-》mHwModules[i]->mHandle = mpClientInterface->loadHwModule(mHwModules[i]->mName);
mHandle 是 audio_module_handle_t类型,实际上是 AF中成员变量DefaultKeyedVector
AudioMTKPolicyManager::setOutputDevice 分析
原型:
uint32_t AudioMTKPolicyManager::setOutputDevice(audio_io_handle_t output,
audio_devices_t device,
bool force,
int delayMs)
-》
AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output); 根据传入参数取得 outputDesc
-》
if (outputDesc->isDuplicated()) { // 蓝牙,暂且不分析 muteWaitMs = setOutputDevice(outputDesc->mOutput1->mId, device, force, delayMs); muteWaitMs += setOutputDevice(outputDesc->mOutput2->mId, device, force, delayMs); return muteWaitMs; }
-》
if (device != AUDIO_DEVICE_NONE) { outputDesc->mDevice = device; } // 设置 outputDesc route to 传入的 device. 软件层面上的。
-》
muteWaitMs = checkDeviceMuteStrategies(outputDesc, prevDevice, delayMs);
-》
param.addInt(String8(AudioParameter::keyRouting), (int)device); 设置keyroute 的PARA,
-》
mpClientInterface->setParameters(output, param.toString(), delayMs); APS cmd thread 切换。
-》 // update stream volumes according to new device
applyStreamVolumes(output, device, delayMs); 分析见下面。
设备路由:
mpClientInterface->setParameters(output, param.toString(), delayMs); APS cmd thread 切换。定义 void AudioPolicyService::setParameters(audio_io_handle_t ioHandle,
const char *keyValuePairs,
int delayMs)
{
mAudioCommandThread->parametersCommand(ioHandle, keyValuePairs,
delayMs);
}
-》 AudioCommand *command = new AudioCommand();-》 insertCommand_l(command, delayMs);-》 AudioCommandThread::threadLoop()
-》case SET_PARAMETERS: AudioSystem::setParameters
-》 af->setParameters
-》 thread = checkPlaybackThread_l(ioHandle); 找到 相应的 thread
-》 thread->setParameters(keyValuePairs);
-》 ThreadBase::setParameters(const String8& keyValuePairs)
-》 mNewParameters.add(keyValuePairs);
Vector<String8> mNewParameters 是 ThreadBase的成员变量。
-》 PlaybackThread::threadLoop()
-》 status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
keyValuePair.string());
mOutput 是AudioStreamOut 类型:
struct AudioStreamOut { AudioHwDevice* const audioHwDev; audio_stream_out_t* const stream; audio_hw_device_t* hwDev() const { return audioHwDev->hwDevice(); } AudioStreamOut(AudioHwDevice *dev, audio_stream_out_t *out) : audioHwDev(dev), stream(out) {} };
-》 out->stream.common.set_parameters = out_set_parameters; HAL层
-》 status_t
AudioMTKStreamOut::setParameters(const String8 &keyValuePairs)
{ AudioParameter param = AudioParameter(keyValuePairs); String8 keyRouting = String8(AudioParameter::keyRouting); status_t status = NO_ERROR; int devices = 0; ALOGD("setParameters() %s", keyValuePairs.string()); if (param.getInt(keyRouting, devices) == NO_ERROR) { param.remove(keyRouting); dokeyRouting(devices); mAudioResourceManager->doSetMode(); } if (param.size()) { status = BAD_VALUE; } return status; }
-》 AudioMTKStreamOut::dokeyRouting(uint32_t new_device)
-》 mAudioResourceManager->SelectOutputDevice(new_device);
-》 AudioResourceManager::SelectOutputDevice(uint32_t new_device)
AudioResourceManager::SelectOutputDevice 分析 pre_device = mDlOutputDevice;
-》 StopOutputDevice(); // 关掉 mDlOutputDevice,
-》 mDlOutputDevice = new_device; 设置NEW device。
-》 AudioResourceManager::StartOutputDevice()
AudioResourceManager::StartOutputDevice() 分析
定义:
switch (mAudioMode) { case AUDIO_MODE_NORMAL: case AUDIO_MODE_RINGTONE: { TurnonAudioDevice(mDlOutputDevice); break; } case AUDIO_MODE_IN_CALL: case AUDIO_MODE_IN_CALL_2: { TurnonAudioDeviceIncall(mDlOutputDevice); break; } case AUDIO_MODE_IN_COMMUNICATION: { TurnonAudioDevice(mDlOutputDevice); break; } }
-》 AudioResourceManager::TurnonAudioDevice(unsigned int mDlOutputDevice)
-》 mAudioAnalogInstance->AnalogOpen(AudioAnalogType::DEVICE_OUT_EARPIECER,
AudioAnalogType::DEVICE_PLATFORM_MACHINE); 打开对应的设备。
-》 AudioAnalogControl::AnalogOpen
定义:
// analog open power , need to open by mux setting status_t AudioAnalogControl::AnalogOpen(AudioAnalogType::DEVICE_TYPE DeviceType, AudioAnalogType::DEVICE_TYPE_SETTING Type_setting) { ALOGD("AnalogOpen DeviceType = %s", kAudioAnalogDeviceTypeName[DeviceType]); CheckDevicePolicy((uint32*)&DeviceType,AudioAnalogType::AUDIOANALOG_DEVICE); mBlockAttribute[DeviceType].mEnable = true; mAudioPlatformDevice->AnalogOpen(DeviceType); 直接操作KERNEL 接口,寄存器。 mAudioMachineDevice->AnalogOpen(DeviceType); return NO_ERROR; }
音量调节 AudioMTKPolicyManager::applyStreamVolumes 分析
void applyStreamVolumes(audio_io_handle_t output, audio_devices_t device, int delayMs = 0, bool force = false); // 注意调用此传入的参数。
-》
for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {
checkAndSetVolume(stream,
mStreams[stream].getVolumeIndex(device),
output,
device,
delayMs,
force);
}
-》传入的参数 StreamDescriptor mStreams[AudioSystem::NUM_STREAM_TYPES]; // stream descriptors for volume control 定义, 实际上类似于一个二维数组,STREAM是第一维, DEVICE是第二维。 上述代码实际上是取出音量的index(int).
class StreamDescriptor { public: StreamDescriptor(); int getVolumeIndex(audio_devices_t device); void dump(int fd); int mIndexMin; // min volume index int mIndexMax; // max volume index KeyedVector<audio_devices_t, int> mIndexCur; // current volume index per device bool mCanBeMuted; // true is the stream can be muted const VolumeCurvePoint *mVolumeCurve[DEVICE_CATEGORY_CNT]; #ifdef MTK_AUDIO float mIndexRange; #endif };
checkAndSetVolume 分析
AudioMTKPolicyManager::checkAndSetVolume
定义:
status_t checkAndSetVolume(int stream, int index, audio_io_handle_t output, audio_devices_t device, int delayMs = 0, bool force = false); // 注意 后面2个参数。
-》
if (mOutputs.valueFor(output)->mMuteCount[stream] != 0) { ALOGV("checkAndSetVolume() stream %d muted count %d", stream, mOutputs.valueFor(output)->mMuteCount[stream]); return NO_ERROR; } do not change actual stream volume if the stream is muted
-》
// do not change in call volume if bluetooth is connected and vice versa if ((stream == AudioSystem::VOICE_CALL && mForceUse[AudioSystem::FOR_COMMUNICATION] == AudioSystem::FORCE_BT_SCO) || (stream == AudioSystem::BLUETOOTH_SCO && mForceUse[AudioSystem::FOR_COMMUNICATION] != AudioSystem::FORCE_BT_SCO)) { ALOGD("checkAndSetVolume() cannot set stream %d volume with force use = %d for comm", stream, mForceUse[AudioSystem::FOR_COMMUNICATION]); return INVALID_OPERATION; }
-》
float volume = computeVolume(stream, index, output, device); // 计算音量。 后面详细分析、
-》
//for VT notify tone when incoming call. it's volume will be adusted in hardware. if((stream == AudioSystem::VOICE_CALL ||stream == AudioSystem::BLUETOOTH_SCO) && mOutputs.valueFor(output)->mRefCount[stream]!=0 && mPhoneState==AudioSystem::MODE_IN_CALL) { volume =1.0; } 处理特列 MODE_IN_CALL
-》
// ALPS00554824 KH: If notifiaction is exist, FM should be mute if ((stream == AudioSystem::FM) && (mOutputs.valueFor(output)->mRefCount[AudioSystem::NOTIFICATION] || mOutputs.valueFor(output)->mRefCount[AudioSystem::RING] || mOutputs.valueFor(output)->mRefCount[AudioSystem::ALARM])) { volume =0.0; }
-》
if (volume != mOutputs.valueFor(output)->mCurVolume[stream] || force) the float value returned by computeVolume() changed // - the force flag is set ,两者有一个条件满足则可以 调节音量。
-》
mOutputs.valueFor(output)->mCurVolume[stream] = volume; float mCurVolume[AudioSystem::NUM_STREAM_TYPES]; // current stream volume,更新软件音量。
-》
mpClientInterface->setStreamVolume((AudioSystem::stream_type)stream, volume, output, delayMs); //aps set volume
-》
int AudioPolicyService::setStreamVolume(audio_stream_type_t stream, float volume, audio_io_handle_t output, int delayMs) { return (int)mAudioCommandThread->volumeCommand(stream, volume, output, delayMs); }
-》
AudioCommandThread::volumeCommand
-》
AudioCommand *command = new AudioCommand();
-》
insertCommand_l(command, delayMs);
-》
mAudioCommands.insertAt(command, i + 1); 加入到mAudioCommands的 CMD容器中。
-》
AudioCommandThread::threadLoop while (!mAudioCommands.isEmpty()) { nsecs_t curTime = systemTime(); // commands are sorted by increasing time stamp: execute them from index 0 and up if (mAudioCommands[0]->mTime <= curTime) { // 当mAudioCommands 不为空,时间来到,
-》
CASE SET_VOLUME: { VolumeData *data = (VolumeData *)command->mParam; ALOGV("AudioCommandThread() processing set volume stream %d, \ volume %f, output %d", data->mStream, data->mVolume, data->mIO); command->mStatus = AudioSystem::setStreamVolume(data->mStream, data->mVolume,data->mIO); //
-》
af->setStreamVolume(stream, value, output); 下面分析 ### AudioFlinger::setStreamVolume 分析 ### status_t AudioFlinger::setStreamVolume(audio_stream_type_t stream, float value, audio_io_handle_t output) 定义
-》
thread = checkPlaybackThread_l(output);
-》
mStreamTypes[stream].volume = value; 设置软件音量 stream_type_t mStreamTypes[AUDIO_STREAM_CNT + 1]; AF中音量表示方法。
-》
thread->setStreamVolume(stream, value); 后面分析
-》
if(stream == AUDIO_STREAM_FM) { MTK_ALOG_D("setStreamVolume FM value = %f",value); #if defined(MT5192_FM) || defined(MT5193_FM) int FmVolume = (AudioSystem::logToLinear(value)); char Volume[30]; sprintf(Volume,"SetFmVolume=%d",FmVolume); String8 Key = String8(Volume); #else int FmVolume = (AudioSystem::logToLinear(value)>>4); char Volume[30]; sprintf(Volume,"SetFmVolume=%d",FmVolume); String8 Key = String8(Volume); #endif audio_hw_device_t *dev = mPrimaryHardwareDev->hwDevice(); dev->set_parameters (dev,Key); } 如果是stream 是FM, 则直接dev->set_parameters (dev,Key); 设置硬件VOLUME. ### PlaybackThread::setStreamVolume 分析 ### struct stream_type_t { stream_type_t() : volume(1.0f), mute(false) { } float volume; bool mute; }; // AF中 和 PLAYBACKTHREAD 中都有个这样的。 定义 void AudioFlinger::PlaybackThread::setStreamVolume(audio_stream_type_t stream, float value) { Mutex::Autolock _l(mLock); mStreamTypes[stream].volume = value; }
插入耳机路由切换过程 WiredAccessoryManager ###
构造函数中
mAudioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
-》
mObserver = new WiredAccessoryObserver();
-》
init 中 public String getSwitchStatePath() {
return String.format(“/sys/class/switch/%s/state”, mDevName);
}
-》
mAudioManager.setWiredDeviceConnectionState(device, state, headsetName);
-》
AudioService中 public void setWiredDeviceConnectionState(int device, int state, String name) {
synchronized (mConnectedDevices) {
int delay = checkSendBecomingNoisyIntent(device, state);
queueMsgUnderWakeLock(mAudioHandler,
MSG_SET_WIRED_DEVICE_CONNECTION_STATE,
device,
state,
name,
delay);
}
}
-》
checkSendBecomingNoisyIntent 中
sendMsg(mAudioHandler , MSG_BROADCAST_AUDIO_BECOMING_NOISY,
SENDMSG_REPLACE,
0,
0,
null,
0);
delay = 1000;
Senmsg在handler中处理
sendBroadcastToAll(new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY)); 这个广播哪些地方有处理,举例子:MUSIC应用中 public void onReceive(Context context, Intent intent) { String intentAction = intent.getAction(); MusicLogUtils.d("MediaButtonIntentReceiver", "intentAction " + intentAction); if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(intentAction)) {
-》
i.setAction(MediaPlaybackService.SERVICECMD);
i.putExtra(MediaPlaybackService.CMDNAME, MediaPlaybackService.CMDPAUSE);
context.startService(i);
-》
在 mediaplayerservice 中处理
else if (CMDPAUSE.equals(cmd) || PAUSE_ACTION.equals(action)
|| AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(action)) {
pause();
mPausedByTransientLossOfFocus = false;
}
-》 audioservice 中
case MSG_SET_WIRED_DEVICE_CONNECTION_STATE: onSetWiredDeviceConnectionState(msg.arg1, msg.arg2, (String)msg.obj);
-》
private void onSetWiredDeviceConnectionState(int device, int state, String name)
{
synchronized (mConnectedDevices) {
Log.d(TAG,”onSetWiredDeviceConnectionState:” + “device:” + device + “,state:” + state);
if ((state == 0) && ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) ||(device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE))) { // 耳机
/// M: Change for sound output from device
when a2dp conneted @ {
//setBluetoothA2dpOnInt(true); AudioSystem.setForceUse(AudioSystem.FOR_MEDIA,AudioSystem.FORCE_NONE);
///@}
}
boolean isUsb = ((device & AudioSystem.DEVICE_OUT_ALL_USB) != 0);
handleDeviceConnection((state == 1), device, (isUsb ? name : “”));
if (state != 0) {
if ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) ||
(device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE)) {
setBluetoothA2dpOnInt(false);
}
if ((device & mSafeMediaVolumeDevices) != 0) {
sendMsg(mAudioHandler,
MSG_CHECK_MUSIC_ACTIVE,
SENDMSG_REPLACE,
0,
0,
null,
MUSIC_ACTIVE_POLL_PERIOD_MS);
}
}
if (!isUsb) {
sendDeviceConnectionIntent(device, state, name);
}
}
}
AudioSystem.setForceUse 分析 handleDeviceConnection(audioservice) 分析
boolean isUsb = ((device & AudioSystem.DEVICE_OUT_ALL_USB) != 0);
handleDeviceConnection((state == 1), device, (isUsb ? name : “”));
下面是定义:
private boolean handleDeviceConnection(boolean connected, int device, String params) { synchronized (mConnectedDevices) { boolean isConnected = (mConnectedDevices.containsKey(device) && (params.isEmpty() || mConnectedDevices.get(device).equals(params))); Log.d(TAG,"handleDeviceConnection:isConnected" + isConnected); if (isConnected && !connected) { 、、 拔出 AudioSystem.setDeviceConnectionState(device, 设置状态 AudioSystem.DEVICE_STATE_UNAVAILABLE, mConnectedDevices.get(device)); Log.d(TAG,"handleDeviceConnection remove:" + "connected:" + connected + ",device:" + device); mConnectedDevices.remove(device); 移除设备。 return true; } else if (!isConnected && connected) { AudioSystem.setDeviceConnectionState(device, AudioSystem.DEVICE_STATE_AVAILABLE, params); Log.d(TAG,"handleDeviceConnection connect:" + "connected:" + connected + ",device:" + device); mConnectedDevices.put(new Integer(device), params); return true; } } return false; }
-》
AudioSystem::setDeviceConnectionState
-》
aps->setDeviceConnectionState(
-》
AudioMTKPolicyManager::setDeviceConnectionState(audio_devices_t device, AudioSystem::device_connection_state state,const char *device_address)
-》
case AudioSystem::DEVICE_STATE_AVAILABLE: if (checkOutputsForDevice(device, state, outputs) != NO_ERROR) { return INVALID_OPERATION; } ALOGD("setDeviceConnectionState() checkOutputsForDevice() returned %d outputs", outputs.size()); // register new device as available mAvailableOutputDevices = (audio_devices_t)(mAvailableOutputDevices | device); 输出设备。 checkOutputForAllStrategies(); 更新strategy if ((state == AudioSystem::DEVICE_STATE_UNAVAILABLE) || (mOutputs.valueFor(outputs[i])->mFlags & AUDIO_OUTPUT_FLAG_DIRECT)) { closeOutput(outputs[i]); 关掉 output } updateDevicesAndOutputs(); for (size_t i = 0; i < mOutputs.size(); i++) { // do not force device change on duplicated output because if device is 0, it will // also force a device 0 for the two outputs it is duplicated to which may override // a valid device selection on those outputs. setOutputDevice(mOutputs.keyAt(i), getNewDevice(mOutputs.keyAt(i), true /*fromCache*/), !mOutputs.valueAt(i)->isDuplicated(), 0); } ### AudioMTKPolicyManager::checkOutputForAllStrategies() 分析 ###
-》
调用 AudioMTKPolicyManager::checkOutputForStrategy(routing_strategy strategy)
-》
audio_devices_t oldDevice = getDeviceForStrategy(strategy, true /*fromCache*/); audio_devices_t newDevice = getDeviceForStrategy(strategy, false /*fromCache*/); SortedVector<audio_io_handle_t> srcOutputs = getOutputsForDevice(oldDevice, mPreviousOutputs); SortedVector<audio_io_handle_t> dstOutputs = getOutputsForDevice(newDevice, mOutputs);
-》
if (desc->strategyRefCount(strategy) != 0) { // #ifdef MTK_AUDIO //ALPS00446176 .ex: Speaker->Speaker,Don't move track and mute. Only change to dstOutputs[0] if(dstOutputs[0]!=srcOutputs[i]) 如果现在的dstOutputs不在 srcOutputs中 { setStrategyMute(strategy, true, srcOutputs[i]); // 立即MUTE setStrategyMute(strategy, false, srcOutputs[i], MUTE_TIME_MS, newDevice); // 2秒后unmute newDevice } #else setStrategyMute(strategy, true, srcOutputs[i]); setStrategyMute(strategy, false, srcOutputs[i], MUTE_TIME_MS, newDevice); #endif }
-》
AudioMTKPolicyManager::setStrategyMute
-》
setStreamMute(stream, on, output, delayMs, device);
-》
AudioMTKPolicyManager::setStreamMute(int stream, bool on, audio_io_handle_t output, int delayMs, audio_devices_t device)
-》
if (on) { // mute on if (outputDesc->mMuteCount[stream] == 0) { if (streamDesc.mCanBeMuted && ((stream != AudioSystem::ENFORCED_AUDIBLE) || (mForceUse[AudioSystem::FOR_SYSTEM] == AudioSystem::FORCE_NONE))) { checkAndSetVolume(stream, 0, output, device, delayMs); } } // increment mMuteCount after calling checkAndSetVolume() so that volume change is not ignored outputDesc->mMuteCount[stream]++; } checkAndSetVolume // 上面已经分析过了,最后会设置音量到 af对应的threads 接上面函数继续分析
-》
// Move tracks associated to this strategy from previous output to new output for (int i = 0; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) { if (getStrategy((AudioSystem::stream_type)i) == strategy) { //FIXME see fixme on name change mpClientInterface->setStreamOutput((AudioSystem::stream_type)i, dstOutputs[0] /* ignored */); } }
-》
status_t AudioPolicyCompatClient::setStreamOutput(AudioSystem::stream_type stream, audio_io_handle_t output) { return mServiceOps->set_stream_output(mService, (audio_stream_type_t)stream, output); }
-》
aps: set_stream_output
-》
af->setStreamOutput
-》
status_t AudioFlinger::setStreamOutput(audio_stream_type_t stream, audio_io_handle_t output) { Mutex::Autolock _l(mLock); ALOGV("setStreamOutput() stream %d to output %d", stream, output); for (size_t i = 0; i < mPlaybackThreads.size(); i++) { PlaybackThread *thread = mPlaybackThreads.valueAt(i).get(); thread->invalidateTracks(stream); } return NO_ERROR; }
-》
PlaybackThread::cacheParameters_l()
-》
PlaybackThread: t->mCblk->cv.signal(); 发信号, 哪里在等还没找到。 uint32_t mRefCount[AudioSystem::NUM_STREAM_TYPES]; // number of streams of each type using this output DefaultKeyedVector<audio_io_handle_t, AudioOutputDescriptor *> mPreviousOutputs;
Audioservice中重要变量:
private final HashMap <Integer, String> mConnectedDevices = new HashMap <Integer, String>();
AudioTrack 跟踪
AudioTrack.java blic AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat, int bufferSizeInBytes, int mode, int sessionId)
-》
int initResult = native_setup(new WeakReference(this),
mStreamType, mSampleRate, mChannels, mAudioFormat,
mNativeBufferSizeInBytes, mDataLoadMode, session);
-》
android_media_AudioTrack_native_setup(JNIEnv *env, jobject thiz, jobject weak_this, jint streamType, jint sampleRateInHertz, jint javaChannelMask, jint audioFormat, jint buffSizeInBytes, jint memoryMode, jintArray jSession) sp<AudioTrack> lpTrack = new AudioTrack();
-》
## AudioFlinger::openOutput 分析 ## DefaultKeyedVector< audio_io_handle_t, sp<PlaybackThread> > mPlaybackThreads; 在 AudioFlinger::openOutput 中 返回的就是这个audio_io_handle_t KEY值。 AudioFlinger::openOutput
->
outHwDev = findSuitableHwDev_l(module, *pDevices); // 找到 AudioHwDevice, 对应HAL 下的一个设备。
->
status =
hwDevHal->open_output_stream(hwDevHal,
id,
*pDevices,
(audio_output_flags_t)flags,
&config,
&outStream);
outStream 是在HAL层分配的,然后返回到AF中。
-》
AudioStreamOut *output = new AudioStreamOut(outHwDev, outStream); // 用上述2个NEW一个 AudioStreamOut。
->
if ((flags & AUDIO_OUTPUT_FLAG_DIRECT) || (config.format != AUDIO_FORMAT_PCM_16_BIT) || (config.channel_mask != AUDIO_CHANNEL_OUT_STEREO)) { thread = new DirectOutputThread(this, output, id, *pDevices); ALOGV("openOutput() created direct output: ID %d thread %p", id, thread); } else { thread = new MixerThread(this, output, id, *pDevices); ALOGV("openOutput() created mixer output: ID %d thread %p", id, thread); 附录LOG:(开机过程中) Line 2397: 01-01 03:59:20.971207 211 211 D AudioFlinger: openOutput(), module 1 Device 2, SamplingRate 44100, Format 0x000003, Channels 3, flags 2 Line 2398: 01-01 03:59:20.971246 211 211 D AudioFlinger: openOutput(), offloadInfo 0x0 version 0xffffffff Line 2399: 01-01 03:59:20.971291 211 211 D AudioALSAStreamManager: +openOutputStream() Line 2888: 01-01 03:59:21.028671 211 211 D AudioALSAStreamManager: -openOutputStream(), out = 0xb7ba8250, status = 0x0, mStreamOutVector.size() = 1 Line 2889: 01-01 03:59:21.028791 211 211 D AudioFlinger: openOutput() openOutputStream returned output 0xb7ba81e0, SamplingRate 44100, Format 0x000003, Channels 3, status 0, flags 2 Line 2889: 01-01 03:59:21.028791 211 211 D AudioFlinger: openOutput() openOutputStream returned output 0xb7ba81e0, SamplingRate 44100, Format 0x000003, Channels 3, status 0, flags 2 Line 2905: 01-01 03:59:21.048650 211 211 D AudioFlinger: openOutput() created mixer output: ID 2 thread 0xb4b26008 (在 AudioFlinger 构造函数中初始化了 mNextUniqueId(1) )
-》
AudioTrack::AudioTrack( audio_stream_type_t streamType, uint32_t sampleRate, audio_format_t format, audio_channel_mask_t channelMask, int frameCount, audio_output_flags_t flags, callback_t cbf, void* user, int notificationFrames, int sessionId, transfer_type transferType, const audio_offload_info_t *offloadInfo, int uid) : mStatus(NO_INIT), mIsTimed(false), mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT), mPausedPosition(0) { mStatus = set(streamType, sampleRate, format, channelMask, frameCount, flags, cbf, user, notificationFrames, 0 /*sharedBuffer*/, false /*threadCanCallJava*/, sessionId, transferType, offloadInfo, uid); } } mPlaybackThreads.add(id, thread);
-》
audio_io_handle_t output = AudioSystem::getOutput( streamType, sampleRate, format, channelMask, flags, offloadInfo); if (cbf != NULL) { mAudioTrackThread = new AudioTrackThread(*this, threadCanCallJava); mAudioTrackThread->run("AudioTrack", ANDROID_PRIORITY_AUDIO, 0 /*stack*/); } // create the IAudioTrack status_t status = createTrack_l(streamType, sampleRate, format, frameCount, flags, sharedBuffer, output, 0 /*epoch*/);
-》
sp<IAudioTrack> track = audioFlinger->createTrack(streamType, sampleRate, // AudioFlinger only sees 16-bit PCM format == AUDIO_FORMAT_PCM_8_BIT ? AUDIO_FORMAT_PCM_16_BIT : format, mChannelMask, frameCount, &trackFlags, sharedBuffer, output, tid, &mSessionId, mName, mClientUid, &status);
-》
track = thread->createTrack_l(client, streamType, sampleRate, format, channelMask, frameCount, sharedBuffer, lSessionId, flags, tid, clientUid, &lStatus);
-》
// PlaybackThread::createTrack_l() must be called with AudioFlinger::mLock held sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrack_l( const sp<AudioFlinger::Client>& client, audio_stream_type_t streamType, uint32_t sampleRate, audio_format_t format, audio_channel_mask_t channelMask, size_t frameCount, const sp<IMemory>& sharedBuffer, int sessionId, IAudioFlinger::track_flags_t *flags, pid_t tid, int uid, status_t *status) { sp<Track> track; status_t lStatus; bool isTimed = (*flags & IAudioFlinger::TRACK_TIMED) != 0; // client expresses a preference for FAST, but we get the final say if (*flags & IAudioFlinger::TRACK_FAST) { if ( // not timed (!isTimed) && // either of these use cases: ( // use case 1: shared buffer with any frame count ( (sharedBuffer != 0) ) || // use case 2: callback handler and frame count is default or at least as large as HAL ( (tid != -1) && ((frameCount == 0) || (frameCount >= mFrameCount)) ) ) && // PCM data audio_is_linear_pcm(format) && // mono or stereo ( (channelMask == AUDIO_CHANNEL_OUT_MONO) || (channelMask == AUDIO_CHANNEL_OUT_STEREO) ) && #ifndef FAST_TRACKS_AT_NON_NATIVE_SAMPLE_RATE // hardware sample rate (sampleRate == mSampleRate) && #endif // normal mixer has an associated fast mixer hasFastMixer() && // there are sufficient fast track slots available (mFastTrackAvailMask != 0) // FIXME test that MixerThread for this fast track has a capable output HAL // FIXME add a permission test also? ) { // if frameCount not specified, then it defaults to fast mixer (HAL) frame count if (frameCount == 0) { frameCount = mFrameCount * kFastTrackMultiplier; } ALOGV("AUDIO_OUTPUT_FLAG_FAST accepted: frameCount=%d mFrameCount=%d", frameCount, mFrameCount); } else { ALOGV("AUDIO_OUTPUT_FLAG_FAST denied: isTimed=%d sharedBuffer=%p frameCount=%d " "mFrameCount=%d format=%d isLinear=%d channelMask=%#x sampleRate=%u mSampleRate=%u " "hasFastMixer=%d tid=%d fastTrackAvailMask=%#x", isTimed, sharedBuffer.get(), frameCount, mFrameCount, format, audio_is_linear_pcm(format), channelMask, sampleRate, mSampleRate, hasFastMixer(), tid, mFastTrackAvailMask); *flags &= ~IAudioFlinger::TRACK_FAST; // For compatibility with AudioTrack calculation, buffer depth is forced // to be at least 2 x the normal mixer frame count and cover audio hardware latency. // This is probably too conservative, but legacy application code may depend on it. // If you change this calculation, also review the start threshold which is related. uint32_t latencyMs = mOutput->stream->get_latency(mOutput->stream); uint32_t minBufCount = latencyMs / ((1000 * mNormalFrameCount) / mSampleRate); if (minBufCount < 2) { minBufCount = 2; } #ifdef MTK_AUDIO size_t minFrameCount = (mFrameCount*sampleRate*minBufCount)/mSampleRate; #else size_t minFrameCount = mNormalFrameCount * minBufCount; #endif if (frameCount < minFrameCount) { frameCount = minFrameCount; } } } if (mType == DIRECT) { if ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM) { if (sampleRate != mSampleRate || format != mFormat || channelMask != mChannelMask) { ALOGE("createTrack_l() Bad parameter: sampleRate %u format %d, channelMask 0x%08x " "for output %p with format %d", sampleRate, format, channelMask, mOutput, mFormat); lStatus = BAD_VALUE; goto Exit; } } } else if (mType == OFFLOAD) { if (sampleRate != mSampleRate || format != mFormat || channelMask != mChannelMask) { ALOGE("createTrack_l() Bad parameter: sampleRate %d format %d, channelMask 0x%08x \"" "for output %p with format %d", sampleRate, format, channelMask, mOutput, mFormat); lStatus = BAD_VALUE; goto Exit; } } else { if ((format & AUDIO_FORMAT_MAIN_MASK) != AUDIO_FORMAT_PCM) { ALOGE("createTrack_l() Bad parameter: format %d \"" "for output %p with format %d", format, mOutput, mFormat); lStatus = BAD_VALUE; goto Exit; } // Resampler implementation limits input sampling rate to 2 x output sampling rate. if (sampleRate > mSampleRate*2) { ALOGE("Sample rate out of range: %u mSampleRate %u", sampleRate, mSampleRate); #ifndef MTK_AUDIO lStatus = BAD_VALUE; goto Exit; #endif } } lStatus = initCheck(); if (lStatus != NO_ERROR) { ALOGE("Audio driver not initialized."); goto Exit; } { // scope for mLock Mutex::Autolock _l(mLock); // all tracks in same audio session must share the same routing strategy otherwise // conflicts will happen when tracks are moved from one output to another by audio policy // manager uint32_t strategy = AudioSystem::getStrategyForStream(streamType); for (size_t i = 0; i < mTracks.size(); ++i) { sp<Track> t = mTracks[i]; if (t != 0 && !t->isOutputTrack()) { uint32_t actual = AudioSystem::getStrategyForStream(t->streamType()); if (sessionId == t->sessionId() && strategy != actual) { ALOGE("createTrack_l() mismatched strategy; expected %u but found %u", strategy, actual); lStatus = BAD_VALUE; goto Exit; } } } if (!isTimed) { track = new Track(this, client, streamType, sampleRate, format, channelMask, frameCount, sharedBuffer, sessionId, uid, *flags); } else { track = TimedTrack::create(this, client, streamType, sampleRate, format, channelMask, frameCount, sharedBuffer, sessionId, uid); } if (track == 0 || track->getCblk() == NULL || track->name() < 0) { lStatus = NO_MEMORY; // track must be cleared from the caller as the caller has the AF lock goto Exit; } mTracks.add(track); ALOGD("%s, mTracks.add(), track 0x%x, this 0x%x", __FUNCTION__, track.get(), this); sp<EffectChain> chain = getEffectChain_l(sessionId); if (chain != 0) { ALOGV("createTrack_l() setting main buffer %p", chain->inBuffer()); track->setMainBuffer(chain->inBuffer()); chain->setStrategy(AudioSystem::getStrategyForStream(track->streamType())); chain->incTrackCnt(); } if ((*flags & IAudioFlinger::TRACK_FAST) && (tid != -1)) { pid_t callingPid = IPCThreadState::self()->getCallingPid(); // we don't have CAP_SYS_NICE, nor do we want to have it as it's too powerful, // so ask activity manager to do this on our behalf sendPrioConfigEvent_l(callingPid, tid, kPriorityAudioApp); } } lStatus = NO_ERROR; Exit: if (status) { *status = lStatus; } return track; }
-》
uint32_t actual = AudioSystem::getStrategyForStream(t->streamType());
track = new Track(this, client, streamType, sampleRate, format,
channelMask, frameCount, sharedBuffer, sessionId, uid, *flags);
-》
AudioFlinger::PlaybackThread::Track::Track
-》
AudioTrackServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
size_t frameSize, bool clientInServer = false)
: ServerProxy(cblk, buffers, frameCount, frameSize, true /isOut/, clientInServer) { }
-》
ServerProxy::ServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize, bool isOut, bool clientInServer) : Proxy(cblk, buffers, frameCount, frameSize, isOut, clientInServer), mAvailToClient(0), mFlush(0) { }
然后根据这个 streamout 和ID, NEW threads. 然后ADD 到 AF中的 mPlaybackThreads。
-》hwDevHal->set_mode(hwDevHal, mMode); // 大概是 设置MODE, NORMAL , CALL MODE? 条件是 (mPrimaryHardwareDev == NULL) ,只有第一次AudioFlinger::openOutput 时会设置模式。
HAL 层open_output_stream
Audio_hw_hal.cpp 中关于
legacy_adev_open 中将
ladev->device.open_output_stream = adev_open_output_stream;
-》 adev_open_output_stream
-》
static int adev_open_output_stream(struct
audio_hw_device *dev,
audio_io_handle_t handle,
audio_devices_t devices,
audio_output_flags_t flags,
struct audio_config *config,
struct audio_stream_out **stream_out)
{
struct legacy_audio_device *ladev = to_ladev(dev);
status_t
status;
struct legacy_stream_out *out;
int ret;
out = (struct legacy_stream_out *)calloc(1, sizeof(*out)); 分配内存,然后由下面设备填充。 if (!out) return -ENOMEM; // 打开设备,填充 out->legacy_out = ladev->hwif->openOutputStreamWithFlag(devices, (int *) &config->format, &config->channel_mask, &config->sample_rate, &status, flags); if (!out->legacy_out) { ret = status; goto err_open; } out->stream.common.get_sample_rate = out_get_sample_rate; out->stream.common.set_sample_rate = out_set_sample_rate; out->stream.common.get_buffer_size = out_get_buffer_size; out->stream.common.get_channels = out_get_channels; out->stream.common.get_format = out_get_format; out->stream.common.set_format = out_set_format; out->stream.common.standby = out_standby; out->stream.common.dump = out_dump; out->stream.common.set_parameters = out_set_parameters; out->stream.common.get_parameters = out_get_parameters; out->stream.common.add_audio_effect = out_add_audio_effect; out->stream.common.remove_audio_effect = out_remove_audio_effect; out->stream.get_latency = out_get_latency; out->stream.set_volume = out_set_volume; out->stream.write = out_write; out->stream.get_render_position = out_get_render_position; out->stream.get_next_write_timestamp = out_get_next_write_timestamp; out->stream.set_callback = out_set_callback; out->stream.get_presentation_position = out_get_presentation_position; *stream_out = &out->stream; return 0; err_open: free(out); *stream_out = NULL; return ret; }
-》AudioHardwareALSA::openOutputStream
-》
android_audio_legacy::AudioStreamOut *AudioALSAHardware::openOutputStream( uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status) { return mStreamManager->openOutputStream(devices, format, channels, sampleRate, status); }
/*==============================================================================
* Implementations
============================================================================/
-》
android_audio_legacy::AudioStreamOut *AudioALSAStreamManager::openOutputStream(
uint32_t devices,
int *format,
uint32_t *channels,
uint32_t *sampleRate,
status_t
*status)
{
ALOGD(“+%s()”, FUNCTION);
AudioAutoTimeoutLock streamVectorAutoTimeoutLock(mStreamVectorLock);
AudioAutoTimeoutLock _l(mLock);
if (format == NULL || channels == NULL || sampleRate == NULL || status == NULL) { ALOGE("%s(), NULL pointer!! format = %p, channels = %p, sampleRate = %p, status = %p", __FUNCTION__, format, channels, sampleRate, status); if (status != NULL) { *status = INVALID_OPERATION; } return NULL; } // stream out flags const uint32_t flags = (uint32_t)(*status); // create stream out AudioALSAStreamOut *pAudioALSAStreamOut = new AudioALSAStreamOut(); pAudioALSAStreamOut->set(devices, format, channels, sampleRate, status, flags); if (*status != NO_ERROR) { ALOGE("-%s(), set fail, return NULL", __FUNCTION__); delete pAudioALSAStreamOut; pAudioALSAStreamOut = NULL; return NULL; } // save stream out object in vector pAudioALSAStreamOut->setIdentity(mStreamOutIndex); mStreamOutVector.add(mStreamOutIndex, pAudioALSAStreamOut); // 加入到streammanager 容器中。 mStreamOutIndex++; // setup Filter for ACF/HCF/AudEnh/VibSPK // TODO Check return status of pAudioALSAStreamOut->set AudioMTKFilterManager *pAudioFilterManagerHandler = new AudioMTKFilterManager(*sampleRate, android_audio_legacy::AudioSystem::popCount(*channels), *format, pAudioALSAStreamOut->bufferSize()); mFilterManagerVector.add(mFilterManagerNumber, pAudioFilterManagerHandler); mFilterManagerNumber++; ALOGD("-%s(), out = %p, status = 0x%x, mStreamOutVector.size() = %d", __FUNCTION__, pAudioALSAStreamOut, *status, mStreamOutVector.size()); return pAudioALSAStreamOut; }
-》audioAStreamManager::openOutputStream
-》audioALSAStreamOut::open
-》audioALSAStreamOut::open()
-》playbackHandler = mStreamManager->createPlaybackHandler(&mStreamAttributeSource);
-> // open codec
driver
mHardwareResourceManager->startOutputDevice(mStreamAttributeSource->output_devices, mStreamAttributeTarget.sample_rate);
相关文章推荐
- 网络资料备忘录
- HD Audio总线驱动加载失败彻底解决!
- WAVEFORMATEX 格式说明
- stagefright MKV/WebM parser
- 主板上常见英文标识的解释
- DirectX.Capture
- eDonkey协议
- maillist of Hacking USB@LINUX
- 电子网站导航 (zz http://blog.163.com/huanghuairen@126/blog/static/19577851200710192333382/)
- 流媒体学习(一)
- 在WinCE6.0下编译DirectShow相关应用时出现题图中的错误链接的解决方法
- iPhone 应用开发:音频播放
- What Is an MXF File?
- 数字音乐各种高保真音乐格式
- (转载+修改)FFMPEG解复用流程
- FFMPEG解复用、解码测试,音频保存WAV文件,视频保存为PPM图像
- All things considered
- APE
- MPEGLAYER3WAVEFORMAT Structure
- ANDROID4.0音频系统HAL初探