/* * Copyright 2024, The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ //#define LOG_NDEBUG 0 #define LOG_TAG "AudioCapabilities" #include #include #include #include #include namespace android { const Range& AudioCapabilities::getBitrateRange() const { return mBitrateRange; } const std::vector& AudioCapabilities::getSupportedSampleRates() const { return mSampleRates; } const std::vector>& AudioCapabilities::getSupportedSampleRateRanges() const { return mSampleRateRanges; } int32_t AudioCapabilities::getMaxInputChannelCount() const { int32_t overallMax = 0; for (int i = mInputChannelRanges.size() - 1; i >= 0; i--) { int32_t lmax = mInputChannelRanges[i].upper(); if (lmax > overallMax) { overallMax = lmax; } } return overallMax; } int32_t AudioCapabilities::getMinInputChannelCount() const { int32_t overallMin = MAX_INPUT_CHANNEL_COUNT; for (int i = mInputChannelRanges.size() - 1; i >= 0; i--) { int32_t lmin = mInputChannelRanges[i].lower(); if (lmin < overallMin) { overallMin = lmin; } } return overallMin; } const std::vector>& AudioCapabilities::getInputChannelCountRanges() const { return mInputChannelRanges; } // static std::shared_ptr AudioCapabilities::Create(std::string mediaType, std::vector profLevs, const sp &format) { std::shared_ptr caps(new AudioCapabilities()); caps->init(mediaType, profLevs, format); return caps; } void AudioCapabilities::init(std::string mediaType, std::vector profLevs, const sp &format) { mMediaType = mediaType; mProfileLevels = profLevs; mError = 0; initWithPlatformLimits(); applyLevelLimits(); parseFromInfo(format); } void AudioCapabilities::initWithPlatformLimits() { mBitrateRange = Range(0, INT32_MAX); mInputChannelRanges.push_back(Range(1, MAX_INPUT_CHANNEL_COUNT)); const int32_t minSampleRate = base::GetIntProperty("ro.mediacodec.min_sample_rate", 7350); const int32_t maxSampleRate = base::GetIntProperty("ro.mediacodec.max_sample_rate", 192000); mSampleRateRanges.push_back(Range(minSampleRate, maxSampleRate)); } bool AudioCapabilities::supports(std::optional sampleRate, std::optional inputChannels) { // channels and sample rates are checked orthogonally if (inputChannels && !std::any_of(mInputChannelRanges.begin(), mInputChannelRanges.end(), [inputChannels](const Range &a) { return a.contains(inputChannels.value()); })) { return false; } if (sampleRate && !std::any_of(mSampleRateRanges.begin(), mSampleRateRanges.end(), [sampleRate](const Range &a) { return a.contains(sampleRate.value()); })) { return false; } return true; } bool AudioCapabilities::isSampleRateSupported(int32_t sampleRate) { return supports(std::make_optional(sampleRate), std::nullopt); } void AudioCapabilities::limitSampleRates(std::vector rates) { std::vector> sampleRateRanges; std::sort(rates.begin(), rates.end()); for (int32_t rate : rates) { if (supports(std::make_optional(rate), std::nullopt /* channels */)) { sampleRateRanges.push_back(Range(rate, rate)); } } mSampleRateRanges = intersectSortedDistinctRanges(mSampleRateRanges, sampleRateRanges); createDiscreteSampleRates(); } void AudioCapabilities::createDiscreteSampleRates() { mSampleRates.clear(); for (int i = 0; i < mSampleRateRanges.size(); i++) { mSampleRates.push_back(mSampleRateRanges[i].lower()); } } void AudioCapabilities::limitSampleRates(std::vector> rateRanges) { sortDistinctRanges(&rateRanges); mSampleRateRanges = intersectSortedDistinctRanges(mSampleRateRanges, rateRanges); // check if all values are discrete for (Range range: mSampleRateRanges) { if (range.lower() != range.upper()) { mSampleRates.clear(); return; } } createDiscreteSampleRates(); } void AudioCapabilities::applyLevelLimits() { std::vector sampleRates; std::optional> sampleRateRange; std::optional> bitRates; int32_t maxChannels = MAX_INPUT_CHANNEL_COUNT; // const char *mediaType = mMediaType.c_str(); if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_MPEG)) { sampleRates = { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 }; bitRates = Range(8000, 320000); maxChannels = 2; } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_AMR_NB)) { sampleRates = { 8000 }; bitRates = Range(4750, 12200); maxChannels = 1; } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_AMR_WB)) { sampleRates = { 16000 }; bitRates = Range(6600, 23850); maxChannels = 1; } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_AAC)) { sampleRates = { 7350, 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000 }; bitRates = Range(8000, 510000); maxChannels = 48; } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_VORBIS)) { bitRates = Range(32000, 500000); sampleRateRange = Range(8000, 192000); maxChannels = 255; } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_OPUS)) { bitRates = Range(6000, 510000); sampleRates = { 8000, 12000, 16000, 24000, 48000 }; maxChannels = 255; } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_RAW)) { sampleRateRange = Range(1, 192000); bitRates = Range(1, 10000000); maxChannels = MAX_NUM_CHANNELS; } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_FLAC)) { sampleRateRange = Range(1, 655350); // lossless codec, so bitrate is ignored maxChannels = 255; } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_G711_ALAW) || base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_G711_MLAW)) { sampleRates = { 8000 }; bitRates = Range(64000, 64000); // platform allows multiple channels for this format } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_MSGSM)) { sampleRates = { 8000 }; bitRates = Range(13000, 13000); maxChannels = 1; } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_AC3)) { maxChannels = 6; } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_EAC3)) { maxChannels = 16; } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_EAC3_JOC)) { sampleRates = { 48000 }; bitRates = Range(32000, 6144000); maxChannels = 16; } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_AC4)) { sampleRates = { 44100, 48000, 96000, 192000 }; bitRates = Range(16000, 2688000); maxChannels = 24; } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_DTS)) { sampleRates = { 44100, 48000 }; bitRates = Range(96000, 1524000); maxChannels = 6; } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_DTS_HD)) { for (ProfileLevel profileLevel: mProfileLevels) { switch (profileLevel.mProfile) { case DTS_HDProfileLBR: sampleRates = { 22050, 24000, 44100, 48000 }; bitRates = Range(32000, 768000); break; case DTS_HDProfileHRA: case DTS_HDProfileMA: sampleRates = { 44100, 48000, 88200, 96000, 176400, 192000 }; bitRates = Range(96000, 24500000); break; default: ALOGW("Unrecognized profile %d for %s", profileLevel.mProfile, mMediaType.c_str()); mError |= ERROR_CAPABILITIES_UNRECOGNIZED; sampleRates = { 44100, 48000, 88200, 96000, 176400, 192000 }; bitRates = Range(96000, 24500000); } } maxChannels = 8; } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_DTS_UHD)) { for (ProfileLevel profileLevel: mProfileLevels) { switch (profileLevel.mProfile) { case DTS_UHDProfileP2: sampleRates = { 48000 }; bitRates = Range(96000, 768000); maxChannels = 10; break; case DTS_UHDProfileP1: sampleRates = { 44100, 48000, 88200, 96000, 176400, 192000 }; bitRates = Range(96000, 24500000); maxChannels = 32; break; default: ALOGW("Unrecognized profile %d for %s", profileLevel.mProfile, mMediaType.c_str()); mError |= ERROR_CAPABILITIES_UNRECOGNIZED; sampleRates = { 44100, 48000, 88200, 96000, 176400, 192000 }; bitRates = Range(96000, 24500000); maxChannels = 32; } } } else { ALOGW("Unsupported mediaType %s", mMediaType.c_str()); mError |= ERROR_CAPABILITIES_UNSUPPORTED; } // restrict ranges if (!sampleRates.empty()) { limitSampleRates(sampleRates); } else if (sampleRateRange) { std::vector> rateRanges = { sampleRateRange.value() }; limitSampleRates(rateRanges); } Range channelRange = Range(1, maxChannels); std::vector> inputChannels = { channelRange }; applyLimits(inputChannels, bitRates); } void AudioCapabilities::applyLimits( const std::vector> &inputChannels, const std::optional> &bitRates) { // clamp & make a local copy std::vector> inputChannelsCopy(inputChannels.size()); for (int i = 0; i < inputChannels.size(); i++) { int32_t lower = inputChannels[i].clamp(1); int32_t upper = inputChannels[i].clamp(MAX_INPUT_CHANNEL_COUNT); inputChannelsCopy[i] = Range(lower, upper); } // sort, intersect with existing, & save channel list sortDistinctRanges(&inputChannelsCopy); mInputChannelRanges = intersectSortedDistinctRanges(inputChannelsCopy, mInputChannelRanges); if (bitRates) { mBitrateRange = mBitrateRange.intersect(bitRates.value()); } } void AudioCapabilities::parseFromInfo(const sp &format) { int32_t maxInputChannels = MAX_INPUT_CHANNEL_COUNT; std::vector> channels = { Range(1, maxInputChannels) }; std::optional> bitRates = POSITIVE_INT32; AString rateAString; if (format->findString("sample-rate-ranges", &rateAString)) { std::vector rateStrings = base::Split(std::string(rateAString.c_str()), ","); std::vector> rateRanges; for (std::string rateString : rateStrings) { std::optional> rateRange = Range::Parse(rateString); if (!rateRange) { continue; } rateRanges.push_back(rateRange.value()); } limitSampleRates(rateRanges); } // we will prefer channel-ranges over max-channel-count AString valueStr; if (format->findString("channel-ranges", &valueStr)) { std::vector channelStrings = base::Split(std::string(valueStr.c_str()), ","); std::vector> channelRanges; for (std::string channelString : channelStrings) { std::optional> channelRange = Range::Parse(channelString); if (!channelRange) { continue; } channelRanges.push_back(channelRange.value()); } channels = channelRanges; } else if (format->findString("channel-range", &valueStr)) { std::optional> oneRange = Range::Parse(std::string(valueStr.c_str())); if (oneRange) { channels = { oneRange.value() }; } } else if (format->findString("max-channel-count", &valueStr)) { maxInputChannels = std::atoi(valueStr.c_str()); if (maxInputChannels == 0) { channels = { Range(0, 0) }; } else { channels = { Range(1, maxInputChannels) }; } } else if ((mError & ERROR_CAPABILITIES_UNSUPPORTED) != 0) { maxInputChannels = 0; channels = { Range(0, 0) }; } if (format->findString("bitrate-range", &valueStr)) { std::optional> parsedBitrate = Range::Parse(valueStr.c_str()); if (parsedBitrate) { bitRates = bitRates.value().intersect(parsedBitrate.value()); } } applyLimits(channels, bitRates); } void AudioCapabilities::getDefaultFormat(sp &format) { // report settings that have only a single choice if (mBitrateRange.lower() == mBitrateRange.upper()) { format->setInt32(KEY_BIT_RATE, mBitrateRange.lower()); } if (getMaxInputChannelCount() == 1) { // mono-only format format->setInt32(KEY_CHANNEL_COUNT, 1); } if (!mSampleRates.empty() && mSampleRates.size() == 1) { format->setInt32(KEY_SAMPLE_RATE, mSampleRates[0]); } } bool AudioCapabilities::supportsFormat(const sp &format) { int32_t sampleRateValue; std::optional sampleRate = format->findInt32(KEY_SAMPLE_RATE, &sampleRateValue) ? std::make_optional(sampleRateValue) : std::nullopt; int32_t channelsValue; std::optional channels = format->findInt32(KEY_CHANNEL_COUNT, &channelsValue) ? std::make_optional(channelsValue) : std::nullopt; if (!supports(sampleRate, channels)) { return false; } if (!CodecCapabilities::SupportsBitrate(mBitrateRange, format)) { return false; } // nothing to do for: // KEY_CHANNEL_MASK: codecs don't get this // KEY_IS_ADTS: required feature for all AAC decoders return true; } } // namespace android