summaryrefslogtreecommitdiffstats
path: root/services/audiopolicy/common
diff options
context:
space:
mode:
authorAndy Hung <hunga@google.com>2015-04-19 22:35:08 -0700
committerAndy Hung <hunga@google.com>2015-04-22 12:41:57 -0700
commitf27e2fbfc3284c00a60fa68edc51d436f75b1e32 (patch)
tree46d089a6f5e37a3ee692679216b351299cc94bc4 /services/audiopolicy/common
parent04f07fd61022dac46ddda9c815d65bc3d3278b84 (diff)
downloadframeworks_av-f27e2fbfc3284c00a60fa68edc51d436f75b1e32.zip
frameworks_av-f27e2fbfc3284c00a60fa68edc51d436f75b1e32.tar.gz
frameworks_av-f27e2fbfc3284c00a60fa68edc51d436f75b1e32.tar.bz2
Add channel index record to AudioPolicyManager
Change-Id: Ic534bee084108a68c7818600df6e1c9dc9258a0d
Diffstat (limited to 'services/audiopolicy/common')
-rw-r--r--services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h14
-rw-r--r--services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp85
2 files changed, 87 insertions, 12 deletions
diff --git a/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h b/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h
index f8c4d08..0b08430 100644
--- a/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h
+++ b/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h
@@ -38,7 +38,8 @@ struct StringToEnum {
uint32_t value;
};
-#define STRING_TO_ENUM(string) { #string, string }
+// TODO: move to a separate file. Should be in sync with audio.h.
+#define STRING_TO_ENUM(string) { #string, (uint32_t)string } // uint32_t cast removes warning
#define NAME_TO_ENUM(name, value) { name, value }
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
@@ -204,6 +205,17 @@ const StringToEnum sInChannelsNameToEnumTable[] = {
STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
};
+const StringToEnum sIndexChannelsNameToEnumTable[] = {
+ STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
+ STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
+ STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
+ STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
+ STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
+ STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
+ STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
+ STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
+};
+
const StringToEnum sGainModeNameToEnumTable[] = {
STRING_TO_ENUM(AUDIO_GAIN_MODE_JOINT),
STRING_TO_ENUM(AUDIO_GAIN_MODE_CHANNELS),
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
index f3978ec..647550c 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
@@ -235,8 +235,14 @@ void AudioPort::loadInChannels(char *name)
(audio_channel_mask_t)ConfigParsingUtils::stringToEnum(sInChannelsNameToEnumTable,
ARRAY_SIZE(sInChannelsNameToEnumTable),
str);
+ if (channelMask == 0) { // if not found, check the channel index table
+ channelMask = (audio_channel_mask_t)
+ ConfigParsingUtils::stringToEnum(sIndexChannelsNameToEnumTable,
+ ARRAY_SIZE(sIndexChannelsNameToEnumTable),
+ str);
+ }
if (channelMask != 0) {
- ALOGV("loadInChannels() adding channelMask %04x", channelMask);
+ ALOGV("loadInChannels() adding channelMask %#x", channelMask);
mChannelMasks.add(channelMask);
}
str = strtok(NULL, "|");
@@ -441,30 +447,87 @@ status_t AudioPort::checkCompatibleChannelMask(audio_channel_mask_t channelMask,
}
const bool isRecordThread = mType == AUDIO_PORT_TYPE_MIX && mRole == AUDIO_PORT_ROLE_SINK;
+ const bool isIndex = audio_channel_mask_get_representation(channelMask)
+ == AUDIO_CHANNEL_REPRESENTATION_INDEX;
+ int bestMatch = 0;
for (size_t i = 0; i < mChannelMasks.size(); i ++) {
- // FIXME Does not handle multi-channel automatic conversions yet
audio_channel_mask_t supported = mChannelMasks[i];
if (supported == channelMask) {
+ // Exact matches always taken.
if (updatedChannelMask != NULL) {
*updatedChannelMask = channelMask;
}
return NO_ERROR;
}
- if (isRecordThread) {
- // This uses hard-coded knowledge that AudioFlinger can silently down-mix and up-mix.
- // FIXME Abstract this out to a table.
- if (((supported == AUDIO_CHANNEL_IN_FRONT_BACK || supported == AUDIO_CHANNEL_IN_STEREO)
- && channelMask == AUDIO_CHANNEL_IN_MONO) ||
- (supported == AUDIO_CHANNEL_IN_MONO && (channelMask == AUDIO_CHANNEL_IN_FRONT_BACK
- || channelMask == AUDIO_CHANNEL_IN_STEREO))) {
+
+ // AUDIO_CHANNEL_NONE (value: 0) is used for dynamic channel support
+ if (isRecordThread && supported != AUDIO_CHANNEL_NONE) {
+ // Approximate (best) match:
+ // The match score measures how well the supported channel mask matches the
+ // desired mask, where increasing-is-better.
+ //
+ // TODO: Some tweaks may be needed.
+ // Should be a static function of the data processing library.
+ //
+ // In priority:
+ // match score = 1000 if legacy channel conversion equivalent (always prefer this)
+ // OR
+ // match score += 100 if the channel mask representations match
+ // match score += number of channels matched.
+ //
+ // If there are no matched channels, the mask may still be accepted
+ // but the playback or record will be silent.
+ const bool isSupportedIndex = (audio_channel_mask_get_representation(supported)
+ == AUDIO_CHANNEL_REPRESENTATION_INDEX);
+ int match;
+ if (isIndex && isSupportedIndex) {
+ // index equivalence
+ match = 100 + __builtin_popcount(
+ audio_channel_mask_get_bits(channelMask)
+ & audio_channel_mask_get_bits(supported));
+ } else if (isIndex && !isSupportedIndex) {
+ const uint32_t equivalentBits =
+ (1 << audio_channel_count_from_in_mask(supported)) - 1 ;
+ match = __builtin_popcount(
+ audio_channel_mask_get_bits(channelMask) & equivalentBits);
+ } else if (!isIndex && isSupportedIndex) {
+ const uint32_t equivalentBits =
+ (1 << audio_channel_count_from_in_mask(channelMask)) - 1;
+ match = __builtin_popcount(
+ equivalentBits & audio_channel_mask_get_bits(supported));
+ } else {
+ // positional equivalence
+ match = 100 + __builtin_popcount(
+ audio_channel_mask_get_bits(channelMask)
+ & audio_channel_mask_get_bits(supported));
+ switch (supported) {
+ case AUDIO_CHANNEL_IN_FRONT_BACK:
+ case AUDIO_CHANNEL_IN_STEREO:
+ if (channelMask == AUDIO_CHANNEL_IN_MONO) {
+ match = 1000;
+ }
+ break;
+ case AUDIO_CHANNEL_IN_MONO:
+ if (channelMask == AUDIO_CHANNEL_IN_FRONT_BACK
+ || channelMask == AUDIO_CHANNEL_IN_STEREO) {
+ match = 1000;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ if (match > bestMatch) {
+ bestMatch = match;
if (updatedChannelMask != NULL) {
*updatedChannelMask = supported;
+ } else {
+ return NO_ERROR; // any match will do in this case.
}
- return NO_ERROR;
}
}
}
- return BAD_VALUE;
+ return bestMatch > 0 ? NO_ERROR : BAD_VALUE;
}
status_t AudioPort::checkExactFormat(audio_format_t format) const