音频场景切换与设置路由
·
1.修改音频场景,会另起一个线程,异步的修改音频场景。以下是几种常规场景。
enum AudioScene : int32_t {
/**
* Invalid
*/
AUDIO_SCENE_INVALID = -1,
/**
* Default audio scene
*/
AUDIO_SCENE_DEFAULT,//媒体场景
/**
* Ringing audio scene
* Only available for system api.
*/
AUDIO_SCENE_RINGING,
/**
* Phone call audio scene
* Only available for system api.
*/
AUDIO_SCENE_PHONE_CALL,//通话场景
/**
* Voice chat audio scene
*/
AUDIO_SCENE_PHONE_CHAT,
/**
* AvSession set call start flag
*/
AUDIO_SCENE_CALL_START,
/**
* AvSession set call end flag
*/
AUDIO_SCENE_CALL_END,
/**
* Voice ringing audio scene
* Only available for system api.
*/
AUDIO_SCENE_VOICE_RINGING,
/**
* Max
*/
AUDIO_SCENE_MAX,
};
void AudioInterruptService::UpdateAudioSceneFromInterrupt(const AudioScene audioScene,
AudioInterruptChangeType changeType)
{
...
std::thread setAudioSceneThread([this, audioScene] {
this->policyServer_->SetAudioSceneInternal(audioScene);
});
setAudioSceneThread.detach();
}
2.进入AudioServer::SetAudioScene,这里会同时修改render的音频场景,和capture的音频场景,并且对通话场景额外对pcm设备做停止和开启操作。
int32_t AudioServer::SetAudioScene(AudioScene audioScene, std::vector<DeviceType> &activeOutputDevices,
DeviceType activeInputDevice, BluetoothOffloadState a2dpOffloadFlag)
{
...
if (audioScene != audioScene_ && (audioScene == AUDIO_SCENE_PHONE_CALL || audioScene_ == AUDIO_SCENE_PHONE_CALL)) {
if (audioCapturerSourceInstance == nullptr || !audioCapturerSourceInstance->IsInited()) {
AUDIO_WARNING_LOG("Capturer is not initialized.");
} else {
audioCapturerSourceInstance->Stop();
}
if (audioRendererSinkInstance == nullptr || !audioRendererSinkInstance->IsInited()) {
AUDIO_WARNING_LOG("Renderer is not initialized.");
} else {
audioRendererSinkInstance->Stop();
}
}
if (audioCapturerSourceInstance != nullptr) {
if (!audioCapturerSourceInstance->IsInited()) {
AUDIO_WARNING_LOG("Capturer is not initialized.");
}
audioCapturerSourceInstance->SetAudioScene(audioScene, activeInputDevice);
}
if (audioRendererSinkInstance == nullptr || !audioRendererSinkInstance->IsInited()) {
AUDIO_WARNING_LOG("Renderer is not initialized.");
} else {
if (activeOutputDevice == DEVICE_TYPE_BLUETOOTH_A2DP && a2dpOffloadFlag != A2DP_OFFLOAD) {
activeOutputDevices[0] = DEVICE_TYPE_NONE;
}
audioRendererSinkInstance->SetAudioScene(audioScene, activeOutputDevices);
}
if ((audioScene == AUDIO_SCENE_PHONE_CALL || audioScene_ == AUDIO_SCENE_PHONE_CALL) ||
(audioScene == AUDIO_SCENE_RINGING && audioScene_ != AUDIO_SCENE_RINGING)) {
if (audioCapturerSourceInstance == nullptr || !audioCapturerSourceInstance->IsInited()) {
AUDIO_WARNING_LOG("Capturer is not initialized.");
} else {
AUDIO_WARNING_LOG("Capturer audioCapturerSourceInstance->Start");
audioCapturerSourceInstance->Start();
}
if (audioRendererSinkInstance == nullptr || !audioRendererSinkInstance->IsInited()) {
AUDIO_WARNING_LOG("Renderer is not initialized.");
} else {
AUDIO_WARNING_LOG("Renderer audioRendererSinkInstance->Start");
audioRendererSinkInstance->Start();
}
}
audioScene_ = audioScene;
return SUCCESS;
}
3.AudioCapturerSourceInner::SetAudioScene是对capture的场景的修改,并且修改路由。
int32_t AudioCapturerSourceInner::SetAudioScene(AudioScene audioScene, DeviceType activeDevice)
{
...
if (openMic_) {
AudioPortPin audioSceneInPort = PIN_IN_MIC;
if (halName_ == "usb") {
audioSceneInPort = PIN_IN_USB_HEADSET;
}
int32_t ret = SUCCESS;
std::lock_guard<std::mutex> lock(sourceAttrMutex_);
ret = SetInputRoute(activeDevice, audioSceneInPort, static_cast<SourceType>(attr_.sourceTy
if (ret < 0) {
AUDIO_WARNING_LOG("Update route FAILED: %{public}d", ret);
}
struct AudioSceneDescriptor scene;
scene.scene.id = GetAudioCategory(audioScene);
scene.desc.pins = audioSceneInPort;
scene.desc.desc = const_cast<char *>("");
ret = audioCapture_->SelectScene(audioCapture_, &scene);
CHECK_AND_RETURN_RET_LOG(ret >= 0, ERR_OPERATION_FAILED,
"Select scene FAILED: %{public}d", ret);
currentAudioScene_ = audioScene;
}
AUDIO_DEBUG_LOG("Select audio scene SUCCESS: %{public}d", audioScene);
return SUCCESS;
}
4.进入HDF层,CaptureSelectSceneImpl中,如果需要进行场景切换,则会调用ReOpenPcmAndSetParams来切换对应的场景并重新打开pcm设备。
static int32_t CaptureSelectSceneImpl(struct AlsaCapture *captureIns, const struct AudioHwCaptureParam *handleData)
{
CHECK_NULL_PTR_RETURN_DEFAULT(handleData);
CHECK_NULL_PTR_RETURN_DEFAULT(captureIns);
int32_t ret = HDF_SUCCESS;
AUDIO_FUNC_LOGI("CaptureSelectSceneImpl enter");
captureIns->descPins = handleData->captureMode.hwInfo.deviceDescript.pins;
enum AudioCategory scene = handleData->frameCaptureMode.attrs.type;
// 实现通话录音场景时切换pcm设备流程,设置对应路由信息
if (CheckSceneIsChange(scene)) {
AUDIO_FUNC_LOGI("CaptureSelectSceneImpl change scene");
if (g_currentScene == AUDIO_MMAP_NOIRQ) {
AUDIO_FUNC_LOGI("CaptureSelectSceneImpl scene is AUDIO_MMAP_NOIRQ");
ret = UpdateAudioCaptureRoute(captureIns, handleData);
if (ret < 0) {
AUDIO_FUNC_LOGE("capture UpdateAudioCaptureRoute fail");
return HDF_FAILURE;
}
g_currentScene = scene;
} else {
AUDIO_FUNC_LOGI("CaptureSelectSceneImpl scene is not AUDIO_MMAP_NOIRQ scene: %{public}d", scene);
if (captureIns->soundCard.pcmHandle != NULL) {
snd_pcm_drop(captureIns->soundCard.pcmHandle);
}
PcmCloseHandle(&captureIns->soundCard);
if (!SndisBusy(&captureIns->soundCard)) {
AUDIO_FUNC_LOGI("CaptureSelectSceneImpl pcm is NULL");
g_currentScene = scene;
if (scene == AUDIO_IN_CALL) {
ret = ReOpenPcmAndSetParams(captureIns, handleData);
if (ret < 0) {
AUDIO_FUNC_LOGE("ReOpenPcmAndSetParams fail");
return HDF_FAILURE;
}
}
}
}
} else {
g_currentScene = scene;
if (scene == AUDIO_IN_CALL) {
AUDIO_FUNC_LOGI("CaptureSelectSceneImpl change device");
ret = UpdateAudioCaptureRoute(captureIns, handleData);
if (ret < 0) {
AUDIO_FUNC_LOGE("capture UpdateAudioCaptureRoute fail");
return HDF_FAILURE;
}
}
}
AUDIO_FUNC_LOGI("CaptureSelectSceneImpl end");
return HDF_SUCCESS;
}
5.HDF层,RenderSelectSceneImpl是进行对render的场景切换。*在这里启动render的pcm设备和capture的pcm设备**。
static int32_t RenderSelectSceneImpl(struct AlsaRender *renderIns, const struct AudioHwRenderParam *handleData)
{
CHECK_NULL_PTR_RETURN_DEFAULT(handleData);
CHECK_NULL_PTR_RETURN_DEFAULT(renderIns);
int32_t ret = HDF_SUCCESS;
renderIns->descPins = handleData->renderMode.hwInfo.deviceDescript.pins;
enum AudioCategory scene = handleData->frameRenderMode.attrs.type;
AUDIO_FUNC_LOGI("RenderSelectSceneImpl enter scene: %{public}d, device: %{public}d", scene, renderIns->descPins
if (CheckSceneIsChange(scene)) {
AUDIO_FUNC_LOGI("RenderSelectSceneImpl change scene");
if (g_currentScene == AUDIO_MMAP_NOIRQ) {
AUDIO_FUNC_LOGI("RenderSelectSceneImpl scene is AUDIO_MMAP_NOIRQ");
ret = UpdateAudioRenderRoute(renderIns, handleData);
if (ret < 0) {
AUDIO_FUNC_LOGE("render UpdateAudioRenderRoute fail");
return HDF_FAILURE;
}
g_currentScene = scene;
} else {
if (ChangeScene(renderIns, handleData, scene) < 0) {
AUDIO_FUNC_LOGE("ChangeScene fail");
return HDF_FAILURE;
}
}
} else {
g_currentScene = scene;
AUDIO_FUNC_LOGI("RenderSelectSceneImpl not need change scene");
if (scene == AUDIO_IN_CALL) {
// change device
AUDIO_FUNC_LOGI("RenderSelectSceneImpl change device");
ret = UpdateAudioRenderRoute(renderIns, handleData);
if (ret < 0) {
AUDIO_FUNC_LOGE("render UpdateAudioRenderRoute fail");
return HDF_FAILURE;
}
if (!g_dlHandle) {
AUDIO_FUNC_LOGE("open libsprd_mock_effect_lib.z.so failed!");
return HDF_FAILURE;
}
UpdateFunc updateDevice = (UpdateFunc)dlsym(g_dlHandle, "update_device");
if (updateDevice == NULL) {
AUDIO_FUNC_LOGE("update_device not defined or exported!");
return HDF_FAILURE;
}
ret = updateDevice(handleData->renderMode.hwInfo.deviceDescript.pins);
if (ret < 0) {
AUDIO_FUNC_LOGE("render update_device failed");
return HDF_FAILURE;
}
}
ret = UpdateAudioRenderRoute(renderIns, handleData);
if (ret < 0) {
AUDIO_FUNC_LOGE("render UpdateAudioRenderRoute fail");
return HDF_FAILURE;
}
}
AUDIO_FUNC_LOGI("RenderSelectSceneImpl end");
return HDF_SUCCESS;
}
更多推荐

所有评论(0)