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