diff options
author | android-build-team Robot <android-build-team-robot@google.com> | 2017-06-06 07:32:29 +0000 |
---|---|---|
committer | android-build-team Robot <android-build-team-robot@google.com> | 2017-06-06 07:32:29 +0000 |
commit | 584a88badd26189ed3f110c48a17e77679b211a4 (patch) | |
tree | 724740ada0915e173e641258010aae501bef6206 | |
parent | 6141c624ec4876257b9fb7f286baba123fef6b2f (diff) | |
parent | 8cd04cc0169cfa392de5428c37f5657455d81f61 (diff) | |
download | fugu-584a88badd26189ed3f110c48a17e77679b211a4.tar.gz |
release-request-d6bf2db5-83c3-41cb-ba89-644c366c2525-for-git_oc-mr1-release-4070602 snap-temp-L56000000070867102
Change-Id: I111279b36fd6355a69ff4a717b97f80be6b06b37
-rw-r--r-- | libaudio/AudioStreamOut.cpp | 39 | ||||
-rw-r--r-- | libaudio/alsa_utils.cpp | 161 | ||||
-rw-r--r-- | libaudio/alsa_utils.h | 6 |
3 files changed, 133 insertions, 73 deletions
diff --git a/libaudio/AudioStreamOut.cpp b/libaudio/AudioStreamOut.cpp index 53a13ef..f1bdb92 100644 --- a/libaudio/AudioStreamOut.cpp +++ b/libaudio/AudioStreamOut.cpp @@ -265,9 +265,10 @@ void AudioStreamOut::finishedWriteOp(size_t framesWritten, } static const String8 keyRouting(AudioParameter::keyRouting); -static const String8 keySupSampleRates("sup_sampling_rates"); -static const String8 keySupFormats("sup_formats"); -static const String8 keySupChannels("sup_channels"); +static const String8 keyFormat(AudioParameter::keyFormat); +static const String8 keySupSampleRates(AudioParameter::keyStreamSupportedSamplingRates); +static const String8 keySupFormats(AudioParameter::keyStreamSupportedFormats); +static const String8 keySupChannels(AudioParameter::keyStreamSupportedChannels); status_t AudioStreamOut::setParameters(__unused struct audio_stream *stream, const char *kvpairs) { AudioParameter param = AudioParameter(String8(kvpairs)); @@ -291,36 +292,42 @@ status_t AudioStreamOut::setParameters(__unused struct audio_stream *stream, con char* AudioStreamOut::getParameters(const char* k) { AudioParameter param = AudioParameter(String8(k)); - String8 value; + String8 stringValue; + int intValue; - if (param.get(keyRouting, value) == NO_ERROR) { + if (param.get(keyRouting, stringValue) == NO_ERROR) { param.addInt(keyRouting, (int)mAudioFlingerTgtDevices); } HDMIAudioCaps& hdmiCaps = mOwnerHAL.getHDMIAudioCaps(); - if (param.get(keySupSampleRates, value) == NO_ERROR) { + if (param.get(keySupFormats, stringValue) == NO_ERROR) { if (mIsMCOutput) { - hdmiCaps.getRatesForAF(value); - param.add(keySupSampleRates, value); + hdmiCaps.getFmtsForAF(stringValue); + param.add(keySupFormats, stringValue); } else { - param.add(keySupSampleRates, String8("48000")); + param.add(keySupFormats, String8("AUDIO_FORMAT_PCM_16_BIT|AUDIO_FORMAT_PCM_8_24_BIT")); } } - if (param.get(keySupFormats, value) == NO_ERROR) { + audio_format_t format = AUDIO_FORMAT_INVALID; + if (param.getInt(keyFormat, intValue) == NO_ERROR) { + format = (audio_format_t)intValue; + } + + if (param.get(keySupSampleRates, stringValue) == NO_ERROR) { if (mIsMCOutput) { - hdmiCaps.getFmtsForAF(value); - param.add(keySupFormats, value); + hdmiCaps.getRatesForAF(stringValue, format); + param.add(keySupSampleRates, stringValue); } else { - param.add(keySupFormats, String8("AUDIO_FORMAT_PCM_16_BIT|AUDIO_FORMAT_PCM_8_24_BIT")); + param.add(keySupSampleRates, String8("48000")); } } - if (param.get(keySupChannels, value) == NO_ERROR) { + if (param.get(keySupChannels, stringValue) == NO_ERROR) { if (mIsMCOutput) { - hdmiCaps.getChannelMasksForAF(value); - param.add(keySupChannels, value); + hdmiCaps.getChannelMasksForAF(stringValue, format); + param.add(keySupChannels, stringValue); } else { param.add(keySupChannels, String8("AUDIO_CHANNEL_OUT_STEREO")); } diff --git a/libaudio/alsa_utils.cpp b/libaudio/alsa_utils.cpp index 2062cf6..0f50848 100644 --- a/libaudio/alsa_utils.cpp +++ b/libaudio/alsa_utils.cpp @@ -219,33 +219,6 @@ void HDMIAudioCaps::reset_l() { mModes.clear(); } -void HDMIAudioCaps::getRatesForAF(String8& rates) { - Mutex::Autolock _l(mLock); - rates.clear(); - - // If the sink does not support basic audio, then it supports no audio. - if (!mBasicAudioSupported) - return; - - // Basic audio always supports from 32k through 38k. - uint32_t tmp = kSR_32000 | kSR_44100 | kSR_48000; - - // To keep things simple, only report mode information for the PCM mode - // which supports the maximum number of channels. - ssize_t ndx = getMaxChModeNdx_l(); - if (ndx >= 0) - tmp |= mModes[ndx].sr_bitmask; - - bool first = true; - for (uint32_t i = 1; tmp; i <<= 1) { - if (i & tmp) { - rates.appendFormat(first ? "%d" : "|%d", srMaskToSR(i)); - first = false; - tmp &= ~i; - } - } -} - void HDMIAudioCaps::getFmtsForAF(String8& fmts) { Mutex::Autolock _l(mLock); fmts.clear(); @@ -316,29 +289,117 @@ void HDMIAudioCaps::getFmtsForAF(String8& fmts) { #endif /* ALSA_UTILS_PRINT_FORMATS */ } -void HDMIAudioCaps::getChannelMasksForAF(String8& masks) { +/* static */ +HDMIAudioCaps::AudFormat HDMIAudioCaps::alsaFormatFromAndroidFormat(audio_format_t format) +{ + AudFormat alsaFormat = kFmtInvalid; + switch (audio_get_main_format(format)) { + case AUDIO_FORMAT_PCM: alsaFormat = kFmtLPCM; break; + case AUDIO_FORMAT_AC3: alsaFormat = kFmtAC3; break; + case AUDIO_FORMAT_E_AC3: alsaFormat = kFmtAC3; break; // FIXME should this be kFmtEAC3? + case AUDIO_FORMAT_DTS: alsaFormat = kFmtDTS; break; + case AUDIO_FORMAT_DTS_HD: alsaFormat = kFmtDTSHD; break; + case AUDIO_FORMAT_IEC61937: alsaFormat = kFmtLPCM; break; + default: + ALOGE("supportsFormat() says format %#x not supported", format); + break; + } + return alsaFormat; +} + +const HDMIAudioCaps::Mode *HDMIAudioCaps::getModeForFormat(HDMIAudioCaps::AudFormat format) +{ + for (size_t i = 0; i < mModes.size(); ++i) { + if (mModes[i].fmt == format) { + return &mModes[i]; + } + } + return nullptr; +} + +void HDMIAudioCaps::getRatesForAF(String8& rates, audio_format_t format) { Mutex::Autolock _l(mLock); - masks.clear(); + rates.clear(); // If the sink does not support basic audio, then it supports no audio. if (!mBasicAudioSupported) return; - masks.append("AUDIO_CHANNEL_OUT_STEREO"); + uint32_t tmp = 0; + // No format provided: returns rates for format with max channels + if (format == AUDIO_FORMAT_INVALID) { + ssize_t ndx = getMaxChModeNdx_l(); + if (ndx >= 0) + tmp = mModes[ndx].sr_bitmask; + } else { + AudFormat alsaFormat = alsaFormatFromAndroidFormat(format); + if (alsaFormat == kFmtInvalid) { + return; + } + const Mode *mode = getModeForFormat(alsaFormat); + if (mode == nullptr) { + return; + } + tmp = mode->sr_bitmask; + } + bool first = true; + for (uint32_t i = 1; tmp; i <<= 1) { + if (i & tmp) { + rates.appendFormat(first ? "%d" : "|%d", srMaskToSR(i)); + first = false; + tmp &= ~i; + } + } +} + +void HDMIAudioCaps::getChannelMasksForAF(String8& masks, audio_format_t format) { + Mutex::Autolock _l(mLock); + masks.clear(); + const Mode *mode = nullptr; - // To keep things simple, only report mode information for the mode - // which supports the maximum number of channels. - ssize_t ndx = getMaxChModeNdx_l(); - if (ndx < 0) + // If the sink does not support basic audio, then it supports no audio. + if (!mBasicAudioSupported) return; - if (mModes[ndx].max_ch >= 6) { - if (masks.length()) - masks.append("|"); + if (format == AUDIO_FORMAT_INVALID) { + // To keep things simple, only report mode information for the mode + // which supports the maximum number of channels. + ssize_t ndx = getMaxChModeNdx_l(); + if (ndx < 0) + return; + mode = &mModes[ndx]; + } else { + AudFormat alsaFormat = alsaFormatFromAndroidFormat(format); + if (alsaFormat == kFmtInvalid) { + return; + } + mode = getModeForFormat(alsaFormat); + if (mode == nullptr) { + return; + } + } - masks.append((mModes[ndx].max_ch >= 8) - ? "AUDIO_CHANNEL_OUT_5POINT1|AUDIO_CHANNEL_OUT_7POINT1" - : "AUDIO_CHANNEL_OUT_5POINT1"); + if (mode != nullptr) { + // allow mono for non-pcm formats, e.g. AC3 + if (mode->max_ch >= 1 && mode->fmt != kFmtLPCM) { + masks.append("AUDIO_CHANNEL_OUT_MONO"); + } + if (mode->max_ch >= 2) { + if (masks.length()) masks.append("|"); + masks.append("AUDIO_CHANNEL_OUT_STEREO"); + } + if (mode->max_ch >= 4) { + if (masks.length()) masks.append("|"); + masks.append("AUDIO_CHANNEL_OUT_QUAD"); + } + if (mode->max_ch >= 6) { + if (masks.length()) masks.append("|"); + masks.append("AUDIO_CHANNEL_OUT_5POINT1"); + } + if (mode->max_ch >= 8) { + if (masks.length()) masks.append("|"); + masks.append("AUDIO_CHANNEL_OUT_7POINT1"); + } } } @@ -368,21 +429,11 @@ bool HDMIAudioCaps::supportsFormat(audio_format_t format, if (!mBasicAudioSupported) return false; - AudFormat alsaFormat; - switch (audio_get_main_format(format)) { - case AUDIO_FORMAT_PCM: alsaFormat = kFmtLPCM; break; - case AUDIO_FORMAT_AC3: alsaFormat = kFmtAC3; break; - case AUDIO_FORMAT_E_AC3: alsaFormat = kFmtAC3; break; // FIXME should this be kFmtEAC3? - case AUDIO_FORMAT_DTS: alsaFormat = kFmtDTS; break; - case AUDIO_FORMAT_DTS_HD: alsaFormat = kFmtDTSHD; break; - case AUDIO_FORMAT_IEC61937: - alsaFormat = kFmtLPCM; - isIec958NonAudio = true; - break; - default: - ALOGE("supportsFormat() says format %#x not supported", format); - return false; - } + AudFormat alsaFormat = alsaFormatFromAndroidFormat(format); + if (alsaFormat == kFmtInvalid) + return false; + + isIec958NonAudio |= (format == AUDIO_FORMAT_IEC61937); // EAC3 uses a PCM sample rate of 4X the base rate. // We try to detect that situation and allow 4X rate even if the diff --git a/libaudio/alsa_utils.h b/libaudio/alsa_utils.h index f0f1b21..d61fa5a 100644 --- a/libaudio/alsa_utils.h +++ b/libaudio/alsa_utils.h @@ -103,9 +103,9 @@ class HDMIAudioCaps { bool loadCaps(int ALSADeviceID); void reset(); - void getRatesForAF(String8& rates); + void getRatesForAF(String8& rates, audio_format_t format); void getFmtsForAF(String8& fmts); - void getChannelMasksForAF(String8& masks); + void getChannelMasksForAF(String8& masks, audio_format_t format); bool supportsFormat(audio_format_t format, uint32_t sampleRate, uint32_t channelCount, @@ -130,6 +130,8 @@ class HDMIAudioCaps { void reset_l(); ssize_t getMaxChModeNdx_l(); static bool sanityCheckMode(const Mode& m); + static AudFormat alsaFormatFromAndroidFormat(audio_format_t format); + const Mode *getModeForFormat(AudFormat format); }; } // namespace android #endif // __cplusplus |