xref: /aosp_15_r20/frameworks/av/media/libmedia/AudioCapabilities.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker  * Copyright 2024, The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker  *
4*ec779b8eSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker  *
8*ec779b8eSAndroid Build Coastguard Worker  *     http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker  *
10*ec779b8eSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker  * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker  */
16*ec779b8eSAndroid Build Coastguard Worker 
17*ec779b8eSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
18*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "AudioCapabilities"
19*ec779b8eSAndroid Build Coastguard Worker 
20*ec779b8eSAndroid Build Coastguard Worker #include <android-base/strings.h>
21*ec779b8eSAndroid Build Coastguard Worker #include <android-base/properties.h>
22*ec779b8eSAndroid Build Coastguard Worker 
23*ec779b8eSAndroid Build Coastguard Worker #include <media/AudioCapabilities.h>
24*ec779b8eSAndroid Build Coastguard Worker #include <media/CodecCapabilities.h>
25*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/MediaCodecConstants.h>
26*ec779b8eSAndroid Build Coastguard Worker 
27*ec779b8eSAndroid Build Coastguard Worker namespace android {
28*ec779b8eSAndroid Build Coastguard Worker 
getBitrateRange() const29*ec779b8eSAndroid Build Coastguard Worker const Range<int32_t>& AudioCapabilities::getBitrateRange() const {
30*ec779b8eSAndroid Build Coastguard Worker     return mBitrateRange;
31*ec779b8eSAndroid Build Coastguard Worker }
32*ec779b8eSAndroid Build Coastguard Worker 
getSupportedSampleRates() const33*ec779b8eSAndroid Build Coastguard Worker const std::vector<int32_t>& AudioCapabilities::getSupportedSampleRates() const {
34*ec779b8eSAndroid Build Coastguard Worker     return mSampleRates;
35*ec779b8eSAndroid Build Coastguard Worker }
36*ec779b8eSAndroid Build Coastguard Worker 
37*ec779b8eSAndroid Build Coastguard Worker const std::vector<Range<int32_t>>&
getSupportedSampleRateRanges() const38*ec779b8eSAndroid Build Coastguard Worker         AudioCapabilities::getSupportedSampleRateRanges() const {
39*ec779b8eSAndroid Build Coastguard Worker     return mSampleRateRanges;
40*ec779b8eSAndroid Build Coastguard Worker }
41*ec779b8eSAndroid Build Coastguard Worker 
getMaxInputChannelCount() const42*ec779b8eSAndroid Build Coastguard Worker int32_t AudioCapabilities::getMaxInputChannelCount() const {
43*ec779b8eSAndroid Build Coastguard Worker     int32_t overallMax = 0;
44*ec779b8eSAndroid Build Coastguard Worker     for (int i = mInputChannelRanges.size() - 1; i >= 0; i--) {
45*ec779b8eSAndroid Build Coastguard Worker         int32_t lmax = mInputChannelRanges[i].upper();
46*ec779b8eSAndroid Build Coastguard Worker         if (lmax > overallMax) {
47*ec779b8eSAndroid Build Coastguard Worker             overallMax = lmax;
48*ec779b8eSAndroid Build Coastguard Worker         }
49*ec779b8eSAndroid Build Coastguard Worker     }
50*ec779b8eSAndroid Build Coastguard Worker     return overallMax;
51*ec779b8eSAndroid Build Coastguard Worker }
52*ec779b8eSAndroid Build Coastguard Worker 
getMinInputChannelCount() const53*ec779b8eSAndroid Build Coastguard Worker int32_t AudioCapabilities::getMinInputChannelCount() const {
54*ec779b8eSAndroid Build Coastguard Worker     int32_t overallMin = MAX_INPUT_CHANNEL_COUNT;
55*ec779b8eSAndroid Build Coastguard Worker     for (int i = mInputChannelRanges.size() - 1; i >= 0; i--) {
56*ec779b8eSAndroid Build Coastguard Worker         int32_t lmin = mInputChannelRanges[i].lower();
57*ec779b8eSAndroid Build Coastguard Worker         if (lmin < overallMin) {
58*ec779b8eSAndroid Build Coastguard Worker             overallMin = lmin;
59*ec779b8eSAndroid Build Coastguard Worker         }
60*ec779b8eSAndroid Build Coastguard Worker     }
61*ec779b8eSAndroid Build Coastguard Worker     return overallMin;
62*ec779b8eSAndroid Build Coastguard Worker }
63*ec779b8eSAndroid Build Coastguard Worker 
64*ec779b8eSAndroid Build Coastguard Worker const std::vector<Range<int32_t>>&
getInputChannelCountRanges() const65*ec779b8eSAndroid Build Coastguard Worker         AudioCapabilities::getInputChannelCountRanges() const {
66*ec779b8eSAndroid Build Coastguard Worker     return mInputChannelRanges;
67*ec779b8eSAndroid Build Coastguard Worker }
68*ec779b8eSAndroid Build Coastguard Worker 
69*ec779b8eSAndroid Build Coastguard Worker // static
Create(std::string mediaType,std::vector<ProfileLevel> profLevs,const sp<AMessage> & format)70*ec779b8eSAndroid Build Coastguard Worker std::shared_ptr<AudioCapabilities> AudioCapabilities::Create(std::string mediaType,
71*ec779b8eSAndroid Build Coastguard Worker         std::vector<ProfileLevel> profLevs, const sp<AMessage> &format) {
72*ec779b8eSAndroid Build Coastguard Worker     std::shared_ptr<AudioCapabilities> caps(new AudioCapabilities());
73*ec779b8eSAndroid Build Coastguard Worker     caps->init(mediaType, profLevs, format);
74*ec779b8eSAndroid Build Coastguard Worker     return caps;
75*ec779b8eSAndroid Build Coastguard Worker }
76*ec779b8eSAndroid Build Coastguard Worker 
init(std::string mediaType,std::vector<ProfileLevel> profLevs,const sp<AMessage> & format)77*ec779b8eSAndroid Build Coastguard Worker void AudioCapabilities::init(std::string mediaType, std::vector<ProfileLevel> profLevs,
78*ec779b8eSAndroid Build Coastguard Worker         const sp<AMessage> &format) {
79*ec779b8eSAndroid Build Coastguard Worker     mMediaType = mediaType;
80*ec779b8eSAndroid Build Coastguard Worker     mProfileLevels = profLevs;
81*ec779b8eSAndroid Build Coastguard Worker     mError = 0;
82*ec779b8eSAndroid Build Coastguard Worker 
83*ec779b8eSAndroid Build Coastguard Worker     initWithPlatformLimits();
84*ec779b8eSAndroid Build Coastguard Worker     applyLevelLimits();
85*ec779b8eSAndroid Build Coastguard Worker     parseFromInfo(format);
86*ec779b8eSAndroid Build Coastguard Worker }
87*ec779b8eSAndroid Build Coastguard Worker 
initWithPlatformLimits()88*ec779b8eSAndroid Build Coastguard Worker void AudioCapabilities::initWithPlatformLimits() {
89*ec779b8eSAndroid Build Coastguard Worker     mBitrateRange = Range<int32_t>(0, INT32_MAX);
90*ec779b8eSAndroid Build Coastguard Worker     mInputChannelRanges.push_back(Range<int32_t>(1, MAX_INPUT_CHANNEL_COUNT));
91*ec779b8eSAndroid Build Coastguard Worker 
92*ec779b8eSAndroid Build Coastguard Worker     const int32_t minSampleRate = base::GetIntProperty("ro.mediacodec.min_sample_rate", 7350);
93*ec779b8eSAndroid Build Coastguard Worker     const int32_t maxSampleRate = base::GetIntProperty("ro.mediacodec.max_sample_rate", 192000);
94*ec779b8eSAndroid Build Coastguard Worker     mSampleRateRanges.push_back(Range<int32_t>(minSampleRate, maxSampleRate));
95*ec779b8eSAndroid Build Coastguard Worker }
96*ec779b8eSAndroid Build Coastguard Worker 
supports(std::optional<int32_t> sampleRate,std::optional<int32_t> inputChannels)97*ec779b8eSAndroid Build Coastguard Worker bool AudioCapabilities::supports(std::optional<int32_t> sampleRate,
98*ec779b8eSAndroid Build Coastguard Worker         std::optional<int32_t> inputChannels) {
99*ec779b8eSAndroid Build Coastguard Worker     // channels and sample rates are checked orthogonally
100*ec779b8eSAndroid Build Coastguard Worker     if (inputChannels
101*ec779b8eSAndroid Build Coastguard Worker             && !std::any_of(mInputChannelRanges.begin(), mInputChannelRanges.end(),
102*ec779b8eSAndroid Build Coastguard Worker             [inputChannels](const Range<int32_t> &a) {
103*ec779b8eSAndroid Build Coastguard Worker                     return a.contains(inputChannels.value()); })) {
104*ec779b8eSAndroid Build Coastguard Worker         return false;
105*ec779b8eSAndroid Build Coastguard Worker     }
106*ec779b8eSAndroid Build Coastguard Worker     if (sampleRate
107*ec779b8eSAndroid Build Coastguard Worker             && !std::any_of(mSampleRateRanges.begin(), mSampleRateRanges.end(),
108*ec779b8eSAndroid Build Coastguard Worker             [sampleRate](const Range<int32_t> &a) { return a.contains(sampleRate.value()); })) {
109*ec779b8eSAndroid Build Coastguard Worker         return false;
110*ec779b8eSAndroid Build Coastguard Worker     }
111*ec779b8eSAndroid Build Coastguard Worker     return true;
112*ec779b8eSAndroid Build Coastguard Worker }
113*ec779b8eSAndroid Build Coastguard Worker 
isSampleRateSupported(int32_t sampleRate)114*ec779b8eSAndroid Build Coastguard Worker bool AudioCapabilities::isSampleRateSupported(int32_t sampleRate) {
115*ec779b8eSAndroid Build Coastguard Worker     return supports(std::make_optional<int32_t>(sampleRate), std::nullopt);
116*ec779b8eSAndroid Build Coastguard Worker }
117*ec779b8eSAndroid Build Coastguard Worker 
limitSampleRates(std::vector<int32_t> rates)118*ec779b8eSAndroid Build Coastguard Worker void AudioCapabilities::limitSampleRates(std::vector<int32_t> rates) {
119*ec779b8eSAndroid Build Coastguard Worker     std::vector<Range<int32_t>> sampleRateRanges;
120*ec779b8eSAndroid Build Coastguard Worker     std::sort(rates.begin(), rates.end());
121*ec779b8eSAndroid Build Coastguard Worker     for (int32_t rate : rates) {
122*ec779b8eSAndroid Build Coastguard Worker         if (supports(std::make_optional<int32_t>(rate), std::nullopt /* channels */)) {
123*ec779b8eSAndroid Build Coastguard Worker             sampleRateRanges.push_back(Range<int32_t>(rate, rate));
124*ec779b8eSAndroid Build Coastguard Worker         }
125*ec779b8eSAndroid Build Coastguard Worker     }
126*ec779b8eSAndroid Build Coastguard Worker     mSampleRateRanges = intersectSortedDistinctRanges(mSampleRateRanges, sampleRateRanges);
127*ec779b8eSAndroid Build Coastguard Worker     createDiscreteSampleRates();
128*ec779b8eSAndroid Build Coastguard Worker }
129*ec779b8eSAndroid Build Coastguard Worker 
createDiscreteSampleRates()130*ec779b8eSAndroid Build Coastguard Worker void AudioCapabilities::createDiscreteSampleRates() {
131*ec779b8eSAndroid Build Coastguard Worker     mSampleRates.clear();
132*ec779b8eSAndroid Build Coastguard Worker     for (int i = 0; i < mSampleRateRanges.size(); i++) {
133*ec779b8eSAndroid Build Coastguard Worker         mSampleRates.push_back(mSampleRateRanges[i].lower());
134*ec779b8eSAndroid Build Coastguard Worker     }
135*ec779b8eSAndroid Build Coastguard Worker }
136*ec779b8eSAndroid Build Coastguard Worker 
limitSampleRates(std::vector<Range<int32_t>> rateRanges)137*ec779b8eSAndroid Build Coastguard Worker void AudioCapabilities::limitSampleRates(std::vector<Range<int32_t>> rateRanges) {
138*ec779b8eSAndroid Build Coastguard Worker     sortDistinctRanges(&rateRanges);
139*ec779b8eSAndroid Build Coastguard Worker     mSampleRateRanges = intersectSortedDistinctRanges(mSampleRateRanges, rateRanges);
140*ec779b8eSAndroid Build Coastguard Worker     // check if all values are discrete
141*ec779b8eSAndroid Build Coastguard Worker     for (Range<int32_t> range: mSampleRateRanges) {
142*ec779b8eSAndroid Build Coastguard Worker         if (range.lower() != range.upper()) {
143*ec779b8eSAndroid Build Coastguard Worker             mSampleRates.clear();
144*ec779b8eSAndroid Build Coastguard Worker             return;
145*ec779b8eSAndroid Build Coastguard Worker         }
146*ec779b8eSAndroid Build Coastguard Worker     }
147*ec779b8eSAndroid Build Coastguard Worker     createDiscreteSampleRates();
148*ec779b8eSAndroid Build Coastguard Worker }
149*ec779b8eSAndroid Build Coastguard Worker 
applyLevelLimits()150*ec779b8eSAndroid Build Coastguard Worker void AudioCapabilities::applyLevelLimits() {
151*ec779b8eSAndroid Build Coastguard Worker     std::vector<int32_t> sampleRates;
152*ec779b8eSAndroid Build Coastguard Worker     std::optional<Range<int32_t>> sampleRateRange;
153*ec779b8eSAndroid Build Coastguard Worker     std::optional<Range<int32_t>> bitRates;
154*ec779b8eSAndroid Build Coastguard Worker     int32_t maxChannels = MAX_INPUT_CHANNEL_COUNT;
155*ec779b8eSAndroid Build Coastguard Worker 
156*ec779b8eSAndroid Build Coastguard Worker     // const char *mediaType = mMediaType.c_str();
157*ec779b8eSAndroid Build Coastguard Worker     if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_MPEG)) {
158*ec779b8eSAndroid Build Coastguard Worker         sampleRates = {
159*ec779b8eSAndroid Build Coastguard Worker                 8000, 11025, 12000,
160*ec779b8eSAndroid Build Coastguard Worker                 16000, 22050, 24000,
161*ec779b8eSAndroid Build Coastguard Worker                 32000, 44100, 48000 };
162*ec779b8eSAndroid Build Coastguard Worker         bitRates = Range<int32_t>(8000, 320000);
163*ec779b8eSAndroid Build Coastguard Worker         maxChannels = 2;
164*ec779b8eSAndroid Build Coastguard Worker     } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_AMR_NB)) {
165*ec779b8eSAndroid Build Coastguard Worker         sampleRates = { 8000 };
166*ec779b8eSAndroid Build Coastguard Worker         bitRates = Range<int32_t>(4750, 12200);
167*ec779b8eSAndroid Build Coastguard Worker         maxChannels = 1;
168*ec779b8eSAndroid Build Coastguard Worker     } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_AMR_WB)) {
169*ec779b8eSAndroid Build Coastguard Worker         sampleRates = { 16000 };
170*ec779b8eSAndroid Build Coastguard Worker         bitRates = Range<int32_t>(6600, 23850);
171*ec779b8eSAndroid Build Coastguard Worker         maxChannels = 1;
172*ec779b8eSAndroid Build Coastguard Worker     } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_AAC)) {
173*ec779b8eSAndroid Build Coastguard Worker         sampleRates = {
174*ec779b8eSAndroid Build Coastguard Worker                 7350, 8000,
175*ec779b8eSAndroid Build Coastguard Worker                 11025, 12000, 16000,
176*ec779b8eSAndroid Build Coastguard Worker                 22050, 24000, 32000,
177*ec779b8eSAndroid Build Coastguard Worker                 44100, 48000, 64000,
178*ec779b8eSAndroid Build Coastguard Worker                 88200, 96000 };
179*ec779b8eSAndroid Build Coastguard Worker         bitRates = Range<int32_t>(8000, 510000);
180*ec779b8eSAndroid Build Coastguard Worker         maxChannels = 48;
181*ec779b8eSAndroid Build Coastguard Worker     } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_VORBIS)) {
182*ec779b8eSAndroid Build Coastguard Worker         bitRates = Range<int32_t>(32000, 500000);
183*ec779b8eSAndroid Build Coastguard Worker         sampleRateRange = Range<int32_t>(8000, 192000);
184*ec779b8eSAndroid Build Coastguard Worker         maxChannels = 255;
185*ec779b8eSAndroid Build Coastguard Worker     } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_OPUS)) {
186*ec779b8eSAndroid Build Coastguard Worker         bitRates = Range<int32_t>(6000, 510000);
187*ec779b8eSAndroid Build Coastguard Worker         sampleRates = { 8000, 12000, 16000, 24000, 48000 };
188*ec779b8eSAndroid Build Coastguard Worker         maxChannels = 255;
189*ec779b8eSAndroid Build Coastguard Worker     } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_RAW)) {
190*ec779b8eSAndroid Build Coastguard Worker         sampleRateRange = Range<int32_t>(1, 192000);
191*ec779b8eSAndroid Build Coastguard Worker         bitRates = Range<int32_t>(1, 10000000);
192*ec779b8eSAndroid Build Coastguard Worker         maxChannels = MAX_NUM_CHANNELS;
193*ec779b8eSAndroid Build Coastguard Worker     } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_FLAC)) {
194*ec779b8eSAndroid Build Coastguard Worker         sampleRateRange = Range<int32_t>(1, 655350);
195*ec779b8eSAndroid Build Coastguard Worker         // lossless codec, so bitrate is ignored
196*ec779b8eSAndroid Build Coastguard Worker         maxChannels = 255;
197*ec779b8eSAndroid Build Coastguard Worker     } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_G711_ALAW)
198*ec779b8eSAndroid Build Coastguard Worker             || base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_G711_MLAW)) {
199*ec779b8eSAndroid Build Coastguard Worker         sampleRates = { 8000 };
200*ec779b8eSAndroid Build Coastguard Worker         bitRates = Range<int32_t>(64000, 64000);
201*ec779b8eSAndroid Build Coastguard Worker         // platform allows multiple channels for this format
202*ec779b8eSAndroid Build Coastguard Worker     } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_MSGSM)) {
203*ec779b8eSAndroid Build Coastguard Worker         sampleRates = { 8000 };
204*ec779b8eSAndroid Build Coastguard Worker         bitRates = Range<int32_t>(13000, 13000);
205*ec779b8eSAndroid Build Coastguard Worker         maxChannels = 1;
206*ec779b8eSAndroid Build Coastguard Worker     } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_AC3)) {
207*ec779b8eSAndroid Build Coastguard Worker         maxChannels = 6;
208*ec779b8eSAndroid Build Coastguard Worker     } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_EAC3)) {
209*ec779b8eSAndroid Build Coastguard Worker         maxChannels = 16;
210*ec779b8eSAndroid Build Coastguard Worker     } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_EAC3_JOC)) {
211*ec779b8eSAndroid Build Coastguard Worker         sampleRates = { 48000 };
212*ec779b8eSAndroid Build Coastguard Worker         bitRates = Range<int32_t>(32000, 6144000);
213*ec779b8eSAndroid Build Coastguard Worker         maxChannels = 16;
214*ec779b8eSAndroid Build Coastguard Worker     } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_AC4)) {
215*ec779b8eSAndroid Build Coastguard Worker         sampleRates = { 44100, 48000, 96000, 192000 };
216*ec779b8eSAndroid Build Coastguard Worker         bitRates = Range<int32_t>(16000, 2688000);
217*ec779b8eSAndroid Build Coastguard Worker         maxChannels = 24;
218*ec779b8eSAndroid Build Coastguard Worker     } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_DTS)) {
219*ec779b8eSAndroid Build Coastguard Worker         sampleRates = { 44100, 48000 };
220*ec779b8eSAndroid Build Coastguard Worker         bitRates = Range<int32_t>(96000, 1524000);
221*ec779b8eSAndroid Build Coastguard Worker         maxChannels = 6;
222*ec779b8eSAndroid Build Coastguard Worker     } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_DTS_HD)) {
223*ec779b8eSAndroid Build Coastguard Worker         for (ProfileLevel profileLevel: mProfileLevels) {
224*ec779b8eSAndroid Build Coastguard Worker             switch (profileLevel.mProfile) {
225*ec779b8eSAndroid Build Coastguard Worker                 case DTS_HDProfileLBR:
226*ec779b8eSAndroid Build Coastguard Worker                     sampleRates = { 22050, 24000, 44100, 48000 };
227*ec779b8eSAndroid Build Coastguard Worker                     bitRates = Range<int32_t>(32000, 768000);
228*ec779b8eSAndroid Build Coastguard Worker                     break;
229*ec779b8eSAndroid Build Coastguard Worker                 case DTS_HDProfileHRA:
230*ec779b8eSAndroid Build Coastguard Worker                 case DTS_HDProfileMA:
231*ec779b8eSAndroid Build Coastguard Worker                     sampleRates = { 44100, 48000, 88200, 96000, 176400, 192000 };
232*ec779b8eSAndroid Build Coastguard Worker                     bitRates = Range<int32_t>(96000, 24500000);
233*ec779b8eSAndroid Build Coastguard Worker                     break;
234*ec779b8eSAndroid Build Coastguard Worker                 default:
235*ec779b8eSAndroid Build Coastguard Worker                     ALOGW("Unrecognized profile %d for %s", profileLevel.mProfile,
236*ec779b8eSAndroid Build Coastguard Worker                             mMediaType.c_str());
237*ec779b8eSAndroid Build Coastguard Worker                     mError |= ERROR_CAPABILITIES_UNRECOGNIZED;
238*ec779b8eSAndroid Build Coastguard Worker                     sampleRates = { 44100, 48000, 88200, 96000, 176400, 192000 };
239*ec779b8eSAndroid Build Coastguard Worker                     bitRates = Range<int32_t>(96000, 24500000);
240*ec779b8eSAndroid Build Coastguard Worker             }
241*ec779b8eSAndroid Build Coastguard Worker         }
242*ec779b8eSAndroid Build Coastguard Worker         maxChannels = 8;
243*ec779b8eSAndroid Build Coastguard Worker     } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_DTS_UHD)) {
244*ec779b8eSAndroid Build Coastguard Worker         for (ProfileLevel profileLevel: mProfileLevels) {
245*ec779b8eSAndroid Build Coastguard Worker             switch (profileLevel.mProfile) {
246*ec779b8eSAndroid Build Coastguard Worker                 case DTS_UHDProfileP2:
247*ec779b8eSAndroid Build Coastguard Worker                     sampleRates = { 48000 };
248*ec779b8eSAndroid Build Coastguard Worker                     bitRates = Range<int32_t>(96000, 768000);
249*ec779b8eSAndroid Build Coastguard Worker                     maxChannels = 10;
250*ec779b8eSAndroid Build Coastguard Worker                     break;
251*ec779b8eSAndroid Build Coastguard Worker                 case DTS_UHDProfileP1:
252*ec779b8eSAndroid Build Coastguard Worker                     sampleRates = { 44100, 48000, 88200, 96000, 176400, 192000 };
253*ec779b8eSAndroid Build Coastguard Worker                     bitRates = Range<int32_t>(96000, 24500000);
254*ec779b8eSAndroid Build Coastguard Worker                     maxChannels = 32;
255*ec779b8eSAndroid Build Coastguard Worker                     break;
256*ec779b8eSAndroid Build Coastguard Worker                 default:
257*ec779b8eSAndroid Build Coastguard Worker                     ALOGW("Unrecognized profile %d for %s", profileLevel.mProfile,
258*ec779b8eSAndroid Build Coastguard Worker                             mMediaType.c_str());
259*ec779b8eSAndroid Build Coastguard Worker                     mError |= ERROR_CAPABILITIES_UNRECOGNIZED;
260*ec779b8eSAndroid Build Coastguard Worker                     sampleRates = { 44100, 48000, 88200, 96000, 176400, 192000 };
261*ec779b8eSAndroid Build Coastguard Worker                     bitRates = Range<int32_t>(96000, 24500000);
262*ec779b8eSAndroid Build Coastguard Worker                     maxChannels = 32;
263*ec779b8eSAndroid Build Coastguard Worker             }
264*ec779b8eSAndroid Build Coastguard Worker         }
265*ec779b8eSAndroid Build Coastguard Worker     } else {
266*ec779b8eSAndroid Build Coastguard Worker         ALOGW("Unsupported mediaType %s", mMediaType.c_str());
267*ec779b8eSAndroid Build Coastguard Worker         mError |= ERROR_CAPABILITIES_UNSUPPORTED;
268*ec779b8eSAndroid Build Coastguard Worker     }
269*ec779b8eSAndroid Build Coastguard Worker 
270*ec779b8eSAndroid Build Coastguard Worker     // restrict ranges
271*ec779b8eSAndroid Build Coastguard Worker     if (!sampleRates.empty()) {
272*ec779b8eSAndroid Build Coastguard Worker         limitSampleRates(sampleRates);
273*ec779b8eSAndroid Build Coastguard Worker     } else if (sampleRateRange) {
274*ec779b8eSAndroid Build Coastguard Worker         std::vector<Range<int32_t>> rateRanges = { sampleRateRange.value() };
275*ec779b8eSAndroid Build Coastguard Worker         limitSampleRates(rateRanges);
276*ec779b8eSAndroid Build Coastguard Worker     }
277*ec779b8eSAndroid Build Coastguard Worker 
278*ec779b8eSAndroid Build Coastguard Worker     Range<int32_t> channelRange = Range<int32_t>(1, maxChannels);
279*ec779b8eSAndroid Build Coastguard Worker     std::vector<Range<int32_t>> inputChannels = { channelRange };
280*ec779b8eSAndroid Build Coastguard Worker     applyLimits(inputChannels, bitRates);
281*ec779b8eSAndroid Build Coastguard Worker }
282*ec779b8eSAndroid Build Coastguard Worker 
applyLimits(const std::vector<Range<int32_t>> & inputChannels,const std::optional<Range<int32_t>> & bitRates)283*ec779b8eSAndroid Build Coastguard Worker void AudioCapabilities::applyLimits(
284*ec779b8eSAndroid Build Coastguard Worker         const std::vector<Range<int32_t>> &inputChannels,
285*ec779b8eSAndroid Build Coastguard Worker         const std::optional<Range<int32_t>> &bitRates) {
286*ec779b8eSAndroid Build Coastguard Worker     // clamp & make a local copy
287*ec779b8eSAndroid Build Coastguard Worker     std::vector<Range<int32_t>> inputChannelsCopy(inputChannels.size());
288*ec779b8eSAndroid Build Coastguard Worker     for (int i = 0; i < inputChannels.size(); i++) {
289*ec779b8eSAndroid Build Coastguard Worker         int32_t lower = inputChannels[i].clamp(1);
290*ec779b8eSAndroid Build Coastguard Worker         int32_t upper = inputChannels[i].clamp(MAX_INPUT_CHANNEL_COUNT);
291*ec779b8eSAndroid Build Coastguard Worker         inputChannelsCopy[i] = Range<int32_t>(lower, upper);
292*ec779b8eSAndroid Build Coastguard Worker     }
293*ec779b8eSAndroid Build Coastguard Worker 
294*ec779b8eSAndroid Build Coastguard Worker     // sort, intersect with existing, & save channel list
295*ec779b8eSAndroid Build Coastguard Worker     sortDistinctRanges(&inputChannelsCopy);
296*ec779b8eSAndroid Build Coastguard Worker     mInputChannelRanges = intersectSortedDistinctRanges(inputChannelsCopy, mInputChannelRanges);
297*ec779b8eSAndroid Build Coastguard Worker 
298*ec779b8eSAndroid Build Coastguard Worker     if (bitRates) {
299*ec779b8eSAndroid Build Coastguard Worker         mBitrateRange = mBitrateRange.intersect(bitRates.value());
300*ec779b8eSAndroid Build Coastguard Worker     }
301*ec779b8eSAndroid Build Coastguard Worker }
302*ec779b8eSAndroid Build Coastguard Worker 
parseFromInfo(const sp<AMessage> & format)303*ec779b8eSAndroid Build Coastguard Worker void AudioCapabilities::parseFromInfo(const sp<AMessage> &format) {
304*ec779b8eSAndroid Build Coastguard Worker     int32_t maxInputChannels = MAX_INPUT_CHANNEL_COUNT;
305*ec779b8eSAndroid Build Coastguard Worker     std::vector<Range<int32_t>> channels = { Range<int32_t>(1, maxInputChannels) };
306*ec779b8eSAndroid Build Coastguard Worker     std::optional<Range<int32_t>> bitRates = POSITIVE_INT32;
307*ec779b8eSAndroid Build Coastguard Worker 
308*ec779b8eSAndroid Build Coastguard Worker     AString rateAString;
309*ec779b8eSAndroid Build Coastguard Worker     if (format->findString("sample-rate-ranges", &rateAString)) {
310*ec779b8eSAndroid Build Coastguard Worker         std::vector<std::string> rateStrings = base::Split(std::string(rateAString.c_str()), ",");
311*ec779b8eSAndroid Build Coastguard Worker         std::vector<Range<int32_t>> rateRanges;
312*ec779b8eSAndroid Build Coastguard Worker         for (std::string rateString : rateStrings) {
313*ec779b8eSAndroid Build Coastguard Worker             std::optional<Range<int32_t>> rateRange = Range<int32_t>::Parse(rateString);
314*ec779b8eSAndroid Build Coastguard Worker             if (!rateRange) {
315*ec779b8eSAndroid Build Coastguard Worker                 continue;
316*ec779b8eSAndroid Build Coastguard Worker             }
317*ec779b8eSAndroid Build Coastguard Worker             rateRanges.push_back(rateRange.value());
318*ec779b8eSAndroid Build Coastguard Worker         }
319*ec779b8eSAndroid Build Coastguard Worker         limitSampleRates(rateRanges);
320*ec779b8eSAndroid Build Coastguard Worker     }
321*ec779b8eSAndroid Build Coastguard Worker 
322*ec779b8eSAndroid Build Coastguard Worker     // we will prefer channel-ranges over max-channel-count
323*ec779b8eSAndroid Build Coastguard Worker     AString valueStr;
324*ec779b8eSAndroid Build Coastguard Worker     if (format->findString("channel-ranges", &valueStr)) {
325*ec779b8eSAndroid Build Coastguard Worker         std::vector<std::string> channelStrings = base::Split(std::string(valueStr.c_str()), ",");
326*ec779b8eSAndroid Build Coastguard Worker         std::vector<Range<int32_t>> channelRanges;
327*ec779b8eSAndroid Build Coastguard Worker         for (std::string channelString : channelStrings) {
328*ec779b8eSAndroid Build Coastguard Worker             std::optional<Range<int32_t>> channelRange = Range<int32_t>::Parse(channelString);
329*ec779b8eSAndroid Build Coastguard Worker             if (!channelRange) {
330*ec779b8eSAndroid Build Coastguard Worker                 continue;
331*ec779b8eSAndroid Build Coastguard Worker             }
332*ec779b8eSAndroid Build Coastguard Worker             channelRanges.push_back(channelRange.value());
333*ec779b8eSAndroid Build Coastguard Worker         }
334*ec779b8eSAndroid Build Coastguard Worker         channels = channelRanges;
335*ec779b8eSAndroid Build Coastguard Worker     } else if (format->findString("channel-range", &valueStr)) {
336*ec779b8eSAndroid Build Coastguard Worker         std::optional<Range<int32_t>> oneRange
337*ec779b8eSAndroid Build Coastguard Worker                 = Range<int32_t>::Parse(std::string(valueStr.c_str()));
338*ec779b8eSAndroid Build Coastguard Worker         if (oneRange) {
339*ec779b8eSAndroid Build Coastguard Worker             channels = { oneRange.value() };
340*ec779b8eSAndroid Build Coastguard Worker         }
341*ec779b8eSAndroid Build Coastguard Worker     } else if (format->findString("max-channel-count", &valueStr)) {
342*ec779b8eSAndroid Build Coastguard Worker         maxInputChannels = std::atoi(valueStr.c_str());
343*ec779b8eSAndroid Build Coastguard Worker         if (maxInputChannels == 0) {
344*ec779b8eSAndroid Build Coastguard Worker             channels = { Range<int32_t>(0, 0) };
345*ec779b8eSAndroid Build Coastguard Worker         } else {
346*ec779b8eSAndroid Build Coastguard Worker             channels = { Range<int32_t>(1, maxInputChannels) };
347*ec779b8eSAndroid Build Coastguard Worker         }
348*ec779b8eSAndroid Build Coastguard Worker     } else if ((mError & ERROR_CAPABILITIES_UNSUPPORTED) != 0) {
349*ec779b8eSAndroid Build Coastguard Worker         maxInputChannels = 0;
350*ec779b8eSAndroid Build Coastguard Worker         channels = { Range<int32_t>(0, 0) };
351*ec779b8eSAndroid Build Coastguard Worker     }
352*ec779b8eSAndroid Build Coastguard Worker 
353*ec779b8eSAndroid Build Coastguard Worker     if (format->findString("bitrate-range", &valueStr)) {
354*ec779b8eSAndroid Build Coastguard Worker         std::optional<Range<int32_t>> parsedBitrate = Range<int32_t>::Parse(valueStr.c_str());
355*ec779b8eSAndroid Build Coastguard Worker         if (parsedBitrate) {
356*ec779b8eSAndroid Build Coastguard Worker             bitRates = bitRates.value().intersect(parsedBitrate.value());
357*ec779b8eSAndroid Build Coastguard Worker         }
358*ec779b8eSAndroid Build Coastguard Worker     }
359*ec779b8eSAndroid Build Coastguard Worker 
360*ec779b8eSAndroid Build Coastguard Worker     applyLimits(channels, bitRates);
361*ec779b8eSAndroid Build Coastguard Worker }
362*ec779b8eSAndroid Build Coastguard Worker 
getDefaultFormat(sp<AMessage> & format)363*ec779b8eSAndroid Build Coastguard Worker void AudioCapabilities::getDefaultFormat(sp<AMessage> &format) {
364*ec779b8eSAndroid Build Coastguard Worker     // report settings that have only a single choice
365*ec779b8eSAndroid Build Coastguard Worker     if (mBitrateRange.lower() == mBitrateRange.upper()) {
366*ec779b8eSAndroid Build Coastguard Worker         format->setInt32(KEY_BIT_RATE, mBitrateRange.lower());
367*ec779b8eSAndroid Build Coastguard Worker     }
368*ec779b8eSAndroid Build Coastguard Worker     if (getMaxInputChannelCount() == 1) {
369*ec779b8eSAndroid Build Coastguard Worker         // mono-only format
370*ec779b8eSAndroid Build Coastguard Worker         format->setInt32(KEY_CHANNEL_COUNT, 1);
371*ec779b8eSAndroid Build Coastguard Worker     }
372*ec779b8eSAndroid Build Coastguard Worker     if (!mSampleRates.empty() && mSampleRates.size() == 1) {
373*ec779b8eSAndroid Build Coastguard Worker         format->setInt32(KEY_SAMPLE_RATE, mSampleRates[0]);
374*ec779b8eSAndroid Build Coastguard Worker     }
375*ec779b8eSAndroid Build Coastguard Worker }
376*ec779b8eSAndroid Build Coastguard Worker 
supportsFormat(const sp<AMessage> & format)377*ec779b8eSAndroid Build Coastguard Worker bool AudioCapabilities::supportsFormat(const sp<AMessage> &format) {
378*ec779b8eSAndroid Build Coastguard Worker     int32_t sampleRateValue;
379*ec779b8eSAndroid Build Coastguard Worker     std::optional<int32_t> sampleRate = format->findInt32(KEY_SAMPLE_RATE, &sampleRateValue)
380*ec779b8eSAndroid Build Coastguard Worker             ? std::make_optional<int32_t>(sampleRateValue) : std::nullopt;
381*ec779b8eSAndroid Build Coastguard Worker     int32_t channelsValue;
382*ec779b8eSAndroid Build Coastguard Worker     std::optional<int32_t> channels = format->findInt32(KEY_CHANNEL_COUNT, &channelsValue)
383*ec779b8eSAndroid Build Coastguard Worker             ? std::make_optional<int32_t>(channelsValue) : std::nullopt;
384*ec779b8eSAndroid Build Coastguard Worker 
385*ec779b8eSAndroid Build Coastguard Worker     if (!supports(sampleRate, channels)) {
386*ec779b8eSAndroid Build Coastguard Worker         return false;
387*ec779b8eSAndroid Build Coastguard Worker     }
388*ec779b8eSAndroid Build Coastguard Worker 
389*ec779b8eSAndroid Build Coastguard Worker     if (!CodecCapabilities::SupportsBitrate(mBitrateRange, format)) {
390*ec779b8eSAndroid Build Coastguard Worker         return false;
391*ec779b8eSAndroid Build Coastguard Worker     }
392*ec779b8eSAndroid Build Coastguard Worker 
393*ec779b8eSAndroid Build Coastguard Worker     // nothing to do for:
394*ec779b8eSAndroid Build Coastguard Worker     // KEY_CHANNEL_MASK: codecs don't get this
395*ec779b8eSAndroid Build Coastguard Worker     // KEY_IS_ADTS:      required feature for all AAC decoders
396*ec779b8eSAndroid Build Coastguard Worker     return true;
397*ec779b8eSAndroid Build Coastguard Worker }
398*ec779b8eSAndroid Build Coastguard Worker 
399*ec779b8eSAndroid Build Coastguard Worker }  // namespace android