diff options
author | Eric Laurent <elaurent@google.com> | 2015-05-18 15:40:16 -0700 |
---|---|---|
committer | Eric Laurent <elaurent@google.com> | 2015-05-19 16:42:42 -0700 |
commit | 861a628adbcbe7c3baa6eab1b765b87b480ff4a2 (patch) | |
tree | 8d1e10f24987535156df45df180c366b97f19b31 /services | |
parent | 4a95e69406aa2e9896d865962d6d947ebbdac6fc (diff) | |
download | frameworks_av-861a628adbcbe7c3baa6eab1b765b87b480ff4a2.zip frameworks_av-861a628adbcbe7c3baa6eab1b765b87b480ff4a2.tar.gz frameworks_av-861a628adbcbe7c3baa6eab1b765b87b480ff4a2.tar.bz2 |
audio policy: fix direct output profile selection
Fix logic in AudioPolicyManager::getProfileForDirectOutput()
to select the direct output with most matching flags and not just
the first compatible one.
Also fixes issue 17783395 which was fixed by commit f7bc29b02
in lmp-tv-dev branch only but in a way that caused a regression
for HW A/V sync (issue 19384172).
Also removed duplicated code lines in getOutputForDevice()
Bug: 20819715.
Bug: 17783395.
Bug: 19384172.
Change-Id: I7fc793b37f9b53fabd92cab6b884ef85cfdafee4
Diffstat (limited to 'services')
-rw-r--r-- | services/audiopolicy/managerdefault/AudioPolicyManager.cpp | 56 |
1 files changed, 44 insertions, 12 deletions
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp index d1ee400..17060e9 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp @@ -579,24 +579,43 @@ sp<IOProfile> AudioPolicyManager::getProfileForDirectOutput( audio_channel_mask_t channelMask, audio_output_flags_t flags) { + // only retain flags that will drive the direct output profile selection + // if explicitly requested + static const uint32_t kRelevantFlags = + (AUDIO_OUTPUT_FLAG_HW_AV_SYNC | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD); + flags = + (audio_output_flags_t)((flags & kRelevantFlags) | AUDIO_OUTPUT_FLAG_DIRECT); + + sp<IOProfile> profile; + for (size_t i = 0; i < mHwModules.size(); i++) { if (mHwModules[i]->mHandle == 0) { continue; } for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++) { - sp<IOProfile> profile = mHwModules[i]->mOutputProfiles[j]; - bool found = profile->isCompatibleProfile(device, String8(""), + sp<IOProfile> curProfile = mHwModules[i]->mOutputProfiles[j]; + if (!curProfile->isCompatibleProfile(device, String8(""), samplingRate, NULL /*updatedSamplingRate*/, format, NULL /*updatedFormat*/, channelMask, NULL /*updatedChannelMask*/, - flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ? - AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD : AUDIO_OUTPUT_FLAG_DIRECT); - if (found && (mAvailableOutputDevices.types() & profile->mSupportedDevices.types())) { - return profile; + flags)) { + continue; + } + // reject profiles not corresponding to a device currently available + if ((mAvailableOutputDevices.types() & curProfile->mSupportedDevices.types()) == 0) { + continue; + } + // if several profiles are compatible, give priority to one with offload capability + if (profile != 0 && ((curProfile->mFlags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0)) { + continue; + } + profile = curProfile; + if ((profile->mFlags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) { + break; } } } - return 0; + return profile; } audio_io_handle_t AudioPolicyManager::getOutput(audio_stream_type_t stream, @@ -819,10 +838,27 @@ audio_io_handle_t AudioPolicyManager::getOutputForDevice( if (outputDesc != NULL) { closeOutput(outputDesc->mIoHandle); } + + // if the selected profile is offloaded and no offload info was specified, + // create a default one + audio_offload_info_t defaultOffloadInfo = AUDIO_INFO_INITIALIZER; + if ((profile->mFlags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) && !offloadInfo) { + flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD); + defaultOffloadInfo.sample_rate = samplingRate; + defaultOffloadInfo.channel_mask = channelMask; + defaultOffloadInfo.format = format; + defaultOffloadInfo.stream_type = stream; + defaultOffloadInfo.bit_rate = 0; + defaultOffloadInfo.duration_us = -1; + defaultOffloadInfo.has_video = true; // conservative + defaultOffloadInfo.is_streaming = true; // likely + offloadInfo = &defaultOffloadInfo; + } + outputDesc = new SwAudioOutputDescriptor(profile, mpClientInterface); outputDesc->mDevice = device; outputDesc->mLatency = 0; - outputDesc->mFlags =(audio_output_flags_t) (outputDesc->mFlags | flags); + outputDesc->mFlags = (audio_output_flags_t)(outputDesc->mFlags | flags); audio_config_t config = AUDIO_CONFIG_INITIALIZER; config.sample_rate = samplingRate; config.channel_mask = channelMask; @@ -854,10 +890,6 @@ audio_io_handle_t AudioPolicyManager::getOutputForDevice( if (audio_is_linear_pcm(format) && samplingRate <= MAX_MIXER_SAMPLING_RATE) { goto non_direct_output; } - // fall back to mixer output if possible when the direct output could not be open - if (audio_is_linear_pcm(format) && samplingRate <= MAX_MIXER_SAMPLING_RATE) { - goto non_direct_output; - } return AUDIO_IO_HANDLE_NONE; } outputDesc->mSamplingRate = config.sample_rate; |