xref: /aosp_15_r20/frameworks/av/media/libmedia/CodecCapabilities.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 "CodecCapabilities"
19*ec779b8eSAndroid Build Coastguard Worker 
20*ec779b8eSAndroid Build Coastguard Worker #include <android-base/strings.h>
21*ec779b8eSAndroid Build Coastguard Worker #include <utils/Log.h>
22*ec779b8eSAndroid Build Coastguard Worker #include <media/CodecCapabilities.h>
23*ec779b8eSAndroid Build Coastguard Worker #include <media/CodecCapabilitiesUtils.h>
24*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/ADebug.h>
25*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/AMessage.h>
26*ec779b8eSAndroid Build Coastguard Worker 
27*ec779b8eSAndroid Build Coastguard Worker namespace android {
28*ec779b8eSAndroid Build Coastguard Worker 
29*ec779b8eSAndroid Build Coastguard Worker static const int32_t HEVCHighTierLevels =
30*ec779b8eSAndroid Build Coastguard Worker         HEVCHighTierLevel1 | HEVCHighTierLevel2 | HEVCHighTierLevel21 | HEVCHighTierLevel3 |
31*ec779b8eSAndroid Build Coastguard Worker         HEVCHighTierLevel31 | HEVCHighTierLevel4 | HEVCHighTierLevel41 | HEVCHighTierLevel5 |
32*ec779b8eSAndroid Build Coastguard Worker         HEVCHighTierLevel51 | HEVCHighTierLevel52 | HEVCHighTierLevel6 | HEVCHighTierLevel61 |
33*ec779b8eSAndroid Build Coastguard Worker         HEVCHighTierLevel62;
34*ec779b8eSAndroid Build Coastguard Worker 
35*ec779b8eSAndroid Build Coastguard Worker static const int32_t DEFAULT_MAX_SUPPORTED_INSTANCES = 32;
36*ec779b8eSAndroid Build Coastguard Worker static const int32_t MAX_SUPPORTED_INSTANCES_LIMIT = 256;
37*ec779b8eSAndroid Build Coastguard Worker 
38*ec779b8eSAndroid Build Coastguard Worker // must not contain KEY_PROFILE
39*ec779b8eSAndroid Build Coastguard Worker static const std::set<std::pair<std::string, AMessage::Type>> AUDIO_LEVEL_CRITICAL_FORMAT_KEYS = {
40*ec779b8eSAndroid Build Coastguard Worker     // We don't set level-specific limits for audio codecs today. Key candidates would
41*ec779b8eSAndroid Build Coastguard Worker     // be sample rate, bit rate or channel count.
42*ec779b8eSAndroid Build Coastguard Worker     // MediaFormat.KEY_SAMPLE_RATE,
43*ec779b8eSAndroid Build Coastguard Worker     // MediaFormat.KEY_CHANNEL_COUNT,
44*ec779b8eSAndroid Build Coastguard Worker     // MediaFormat.KEY_BIT_RATE,
45*ec779b8eSAndroid Build Coastguard Worker     { KEY_MIME, AMessage::kTypeString }
46*ec779b8eSAndroid Build Coastguard Worker };
47*ec779b8eSAndroid Build Coastguard Worker 
48*ec779b8eSAndroid Build Coastguard Worker // CodecCapabilities Features
49*ec779b8eSAndroid Build Coastguard Worker static const std::vector<Feature> DECODER_FEATURES = {
50*ec779b8eSAndroid Build Coastguard Worker     Feature(FEATURE_AdaptivePlayback, (1 << 0), true),
51*ec779b8eSAndroid Build Coastguard Worker     Feature(FEATURE_SecurePlayback,   (1 << 1), false),
52*ec779b8eSAndroid Build Coastguard Worker     Feature(FEATURE_TunneledPlayback, (1 << 2), false),
53*ec779b8eSAndroid Build Coastguard Worker     Feature(FEATURE_PartialFrame,     (1 << 3), false),
54*ec779b8eSAndroid Build Coastguard Worker     Feature(FEATURE_FrameParsing,     (1 << 4), false),
55*ec779b8eSAndroid Build Coastguard Worker     Feature(FEATURE_MultipleFrames,   (1 << 5), false),
56*ec779b8eSAndroid Build Coastguard Worker     Feature(FEATURE_DynamicTimestamp, (1 << 6), false),
57*ec779b8eSAndroid Build Coastguard Worker     Feature(FEATURE_LowLatency,       (1 << 7), true),
58*ec779b8eSAndroid Build Coastguard Worker     // feature to exclude codec from REGULAR codec list
59*ec779b8eSAndroid Build Coastguard Worker     Feature(FEATURE_SpecialCodec,     (1 << 30), false, true),
60*ec779b8eSAndroid Build Coastguard Worker };
61*ec779b8eSAndroid Build Coastguard Worker static const std::vector<Feature> ENCODER_FEATURES = {
62*ec779b8eSAndroid Build Coastguard Worker     Feature(FEATURE_IntraRefresh, (1 << 0), false),
63*ec779b8eSAndroid Build Coastguard Worker     Feature(FEATURE_MultipleFrames, (1 << 1), false),
64*ec779b8eSAndroid Build Coastguard Worker     Feature(FEATURE_DynamicTimestamp, (1 << 2), false),
65*ec779b8eSAndroid Build Coastguard Worker     Feature(FEATURE_QpBounds, (1 << 3), false),
66*ec779b8eSAndroid Build Coastguard Worker     Feature(FEATURE_EncodingStatistics, (1 << 4), false),
67*ec779b8eSAndroid Build Coastguard Worker     Feature(FEATURE_HdrEditing, (1 << 5), false),
68*ec779b8eSAndroid Build Coastguard Worker     // feature to exclude codec from REGULAR codec list
69*ec779b8eSAndroid Build Coastguard Worker     Feature(FEATURE_SpecialCodec,     (1 << 30), false, true),
70*ec779b8eSAndroid Build Coastguard Worker };
71*ec779b8eSAndroid Build Coastguard Worker 
72*ec779b8eSAndroid Build Coastguard Worker // must not contain KEY_PROFILE
73*ec779b8eSAndroid Build Coastguard Worker static const std::set<std::pair<std::string, AMessage::Type>> VIDEO_LEVEL_CRITICAL_FORMAT_KEYS = {
74*ec779b8eSAndroid Build Coastguard Worker     { KEY_WIDTH, AMessage::kTypeInt32 },
75*ec779b8eSAndroid Build Coastguard Worker     { KEY_HEIGHT, AMessage::kTypeInt32 },
76*ec779b8eSAndroid Build Coastguard Worker     { KEY_FRAME_RATE, AMessage::kTypeInt32 },
77*ec779b8eSAndroid Build Coastguard Worker     { KEY_BIT_RATE, AMessage::kTypeInt32 },
78*ec779b8eSAndroid Build Coastguard Worker     { KEY_MIME, AMessage::kTypeString }
79*ec779b8eSAndroid Build Coastguard Worker };
80*ec779b8eSAndroid Build Coastguard Worker 
SupportsBitrate(Range<int32_t> bitrateRange,const sp<AMessage> & format)81*ec779b8eSAndroid Build Coastguard Worker bool CodecCapabilities::SupportsBitrate(Range<int32_t> bitrateRange,
82*ec779b8eSAndroid Build Coastguard Worker         const sp<AMessage> &format) {
83*ec779b8eSAndroid Build Coastguard Worker     // consider max bitrate over average bitrate for support
84*ec779b8eSAndroid Build Coastguard Worker     int32_t maxBitrate = 0;
85*ec779b8eSAndroid Build Coastguard Worker     format->findInt32(KEY_MAX_BIT_RATE, &maxBitrate);
86*ec779b8eSAndroid Build Coastguard Worker     int32_t bitrate = 0;
87*ec779b8eSAndroid Build Coastguard Worker     format->findInt32(KEY_BIT_RATE, &bitrate);
88*ec779b8eSAndroid Build Coastguard Worker 
89*ec779b8eSAndroid Build Coastguard Worker     if (bitrate == 0) {
90*ec779b8eSAndroid Build Coastguard Worker         bitrate = maxBitrate;
91*ec779b8eSAndroid Build Coastguard Worker     } else if (maxBitrate != 0) {
92*ec779b8eSAndroid Build Coastguard Worker         bitrate = std::max(bitrate, maxBitrate);
93*ec779b8eSAndroid Build Coastguard Worker     }
94*ec779b8eSAndroid Build Coastguard Worker 
95*ec779b8eSAndroid Build Coastguard Worker     if (bitrate > 0) {
96*ec779b8eSAndroid Build Coastguard Worker         return bitrateRange.contains(bitrate);
97*ec779b8eSAndroid Build Coastguard Worker     }
98*ec779b8eSAndroid Build Coastguard Worker 
99*ec779b8eSAndroid Build Coastguard Worker     return true;
100*ec779b8eSAndroid Build Coastguard Worker }
101*ec779b8eSAndroid Build Coastguard Worker 
isFeatureSupported(const std::string & name) const102*ec779b8eSAndroid Build Coastguard Worker bool CodecCapabilities::isFeatureSupported(const std::string &name) const {
103*ec779b8eSAndroid Build Coastguard Worker     return mFeaturesSupported.contains(name);
104*ec779b8eSAndroid Build Coastguard Worker }
105*ec779b8eSAndroid Build Coastguard Worker 
isFeatureRequired(const std::string & name) const106*ec779b8eSAndroid Build Coastguard Worker bool CodecCapabilities::isFeatureRequired(const std::string &name) const {
107*ec779b8eSAndroid Build Coastguard Worker     return mFeaturesRequired.contains(name);
108*ec779b8eSAndroid Build Coastguard Worker }
109*ec779b8eSAndroid Build Coastguard Worker 
validFeatures() const110*ec779b8eSAndroid Build Coastguard Worker std::vector<std::string> CodecCapabilities::validFeatures() const {
111*ec779b8eSAndroid Build Coastguard Worker     std::vector<std::string> res;
112*ec779b8eSAndroid Build Coastguard Worker     for (const Feature& feature : getValidFeatures()) {
113*ec779b8eSAndroid Build Coastguard Worker         if (!feature.mInternal) {
114*ec779b8eSAndroid Build Coastguard Worker             res.push_back(feature.mName);
115*ec779b8eSAndroid Build Coastguard Worker         }
116*ec779b8eSAndroid Build Coastguard Worker     }
117*ec779b8eSAndroid Build Coastguard Worker     return res;
118*ec779b8eSAndroid Build Coastguard Worker }
119*ec779b8eSAndroid Build Coastguard Worker 
getValidFeatures() const120*ec779b8eSAndroid Build Coastguard Worker std::vector<Feature> CodecCapabilities::getValidFeatures() const {
121*ec779b8eSAndroid Build Coastguard Worker     if (isEncoder()) {
122*ec779b8eSAndroid Build Coastguard Worker         return ENCODER_FEATURES;
123*ec779b8eSAndroid Build Coastguard Worker     } else {
124*ec779b8eSAndroid Build Coastguard Worker         return DECODER_FEATURES;
125*ec779b8eSAndroid Build Coastguard Worker     }
126*ec779b8eSAndroid Build Coastguard Worker }
127*ec779b8eSAndroid Build Coastguard Worker 
isRegular() const128*ec779b8eSAndroid Build Coastguard Worker bool CodecCapabilities::isRegular() const {
129*ec779b8eSAndroid Build Coastguard Worker     // regular codecs only require default features
130*ec779b8eSAndroid Build Coastguard Worker     std::vector<Feature> features = getValidFeatures();
131*ec779b8eSAndroid Build Coastguard Worker     return std::all_of(features.begin(), features.end(),
132*ec779b8eSAndroid Build Coastguard Worker             [this](Feature feat){ return (feat.mDefault || !isFeatureRequired(feat.mName)); });
133*ec779b8eSAndroid Build Coastguard Worker }
134*ec779b8eSAndroid Build Coastguard Worker 
isFormatSupported(const sp<AMessage> & format) const135*ec779b8eSAndroid Build Coastguard Worker bool CodecCapabilities::isFormatSupported(const sp<AMessage> &format) const {
136*ec779b8eSAndroid Build Coastguard Worker     AString mediaType;
137*ec779b8eSAndroid Build Coastguard Worker     format->findString(KEY_MIME, &mediaType);
138*ec779b8eSAndroid Build Coastguard Worker     // mediaType must match if present
139*ec779b8eSAndroid Build Coastguard Worker     if (!base::EqualsIgnoreCase(mMediaType, mediaType.c_str())) {
140*ec779b8eSAndroid Build Coastguard Worker         return false;
141*ec779b8eSAndroid Build Coastguard Worker     }
142*ec779b8eSAndroid Build Coastguard Worker 
143*ec779b8eSAndroid Build Coastguard Worker     // check feature support
144*ec779b8eSAndroid Build Coastguard Worker     for (Feature feat: getValidFeatures()) {
145*ec779b8eSAndroid Build Coastguard Worker         if (feat.mInternal) {
146*ec779b8eSAndroid Build Coastguard Worker             continue;
147*ec779b8eSAndroid Build Coastguard Worker         }
148*ec779b8eSAndroid Build Coastguard Worker 
149*ec779b8eSAndroid Build Coastguard Worker         int32_t yesNo;
150*ec779b8eSAndroid Build Coastguard Worker         std::string key = KEY_FEATURE_;
151*ec779b8eSAndroid Build Coastguard Worker         key = key + feat.mName;
152*ec779b8eSAndroid Build Coastguard Worker         if (format->findInt32(key.c_str(), &yesNo)) {
153*ec779b8eSAndroid Build Coastguard Worker             continue;
154*ec779b8eSAndroid Build Coastguard Worker         }
155*ec779b8eSAndroid Build Coastguard Worker         if ((yesNo == 1 && !isFeatureSupported(feat.mName)) ||
156*ec779b8eSAndroid Build Coastguard Worker                 (yesNo == 0 && isFeatureRequired(feat.mName))) {
157*ec779b8eSAndroid Build Coastguard Worker             return false;
158*ec779b8eSAndroid Build Coastguard Worker         }
159*ec779b8eSAndroid Build Coastguard Worker     }
160*ec779b8eSAndroid Build Coastguard Worker 
161*ec779b8eSAndroid Build Coastguard Worker     int32_t profile;
162*ec779b8eSAndroid Build Coastguard Worker     if (format->findInt32(KEY_PROFILE, &profile)) {
163*ec779b8eSAndroid Build Coastguard Worker         int32_t level = -1;
164*ec779b8eSAndroid Build Coastguard Worker         format->findInt32(KEY_LEVEL, &level);
165*ec779b8eSAndroid Build Coastguard Worker         if (!supportsProfileLevel(profile, level)) {
166*ec779b8eSAndroid Build Coastguard Worker             return false;
167*ec779b8eSAndroid Build Coastguard Worker         }
168*ec779b8eSAndroid Build Coastguard Worker 
169*ec779b8eSAndroid Build Coastguard Worker         // If we recognize this profile, check that this format is supported by the
170*ec779b8eSAndroid Build Coastguard Worker         // highest level supported by the codec for that profile. (Ignore specified
171*ec779b8eSAndroid Build Coastguard Worker         // level beyond the above profile/level check as level is only used as a
172*ec779b8eSAndroid Build Coastguard Worker         // guidance. E.g. AVC Level 1 CIF format is supported if codec supports level 1.1
173*ec779b8eSAndroid Build Coastguard Worker         // even though max size for Level 1 is QCIF. However, MPEG2 Simple Profile
174*ec779b8eSAndroid Build Coastguard Worker         // 1080p format is not supported even if codec supports Main Profile Level High,
175*ec779b8eSAndroid Build Coastguard Worker         // as Simple Profile does not support 1080p.
176*ec779b8eSAndroid Build Coastguard Worker         int32_t maxLevel = 0;
177*ec779b8eSAndroid Build Coastguard Worker         for (ProfileLevel pl : mProfileLevels) {
178*ec779b8eSAndroid Build Coastguard Worker             if (pl.mProfile == profile && pl.mLevel > maxLevel) {
179*ec779b8eSAndroid Build Coastguard Worker                 // H.263 levels are not completely ordered:
180*ec779b8eSAndroid Build Coastguard Worker                 // Level45 support only implies Level10 support
181*ec779b8eSAndroid Build Coastguard Worker                 if (!base::EqualsIgnoreCase(mMediaType, MIMETYPE_VIDEO_H263)
182*ec779b8eSAndroid Build Coastguard Worker                         || pl.mLevel != H263Level45
183*ec779b8eSAndroid Build Coastguard Worker                         || maxLevel == H263Level10) {
184*ec779b8eSAndroid Build Coastguard Worker                     maxLevel = pl.mLevel;
185*ec779b8eSAndroid Build Coastguard Worker                 }
186*ec779b8eSAndroid Build Coastguard Worker             }
187*ec779b8eSAndroid Build Coastguard Worker         }
188*ec779b8eSAndroid Build Coastguard Worker         std::shared_ptr<CodecCapabilities> levelCaps
189*ec779b8eSAndroid Build Coastguard Worker                 = CreateFromProfileLevel(mMediaType, profile, maxLevel);
190*ec779b8eSAndroid Build Coastguard Worker         // We must remove the profile from this format otherwise levelCaps.isFormatSupported
191*ec779b8eSAndroid Build Coastguard Worker         // will get into this same condition and loop forever. Furthermore, since levelCaps
192*ec779b8eSAndroid Build Coastguard Worker         // does not contain features and bitrate specific keys, keep only keys relevant for
193*ec779b8eSAndroid Build Coastguard Worker         // a level check.
194*ec779b8eSAndroid Build Coastguard Worker         sp<AMessage> levelCriticalFormat = new AMessage;
195*ec779b8eSAndroid Build Coastguard Worker 
196*ec779b8eSAndroid Build Coastguard Worker         // critical keys will always contain KEY_MIME, but should also contain others to be
197*ec779b8eSAndroid Build Coastguard Worker         // meaningful
198*ec779b8eSAndroid Build Coastguard Worker         if ((isVideo() || isAudio()) && levelCaps != nullptr) {
199*ec779b8eSAndroid Build Coastguard Worker             const std::set<std::pair<std::string, AMessage::Type>> criticalKeys =
200*ec779b8eSAndroid Build Coastguard Worker                 isVideo() ? VIDEO_LEVEL_CRITICAL_FORMAT_KEYS : AUDIO_LEVEL_CRITICAL_FORMAT_KEYS;
201*ec779b8eSAndroid Build Coastguard Worker             for (std::pair<std::string, AMessage::Type> key : criticalKeys) {
202*ec779b8eSAndroid Build Coastguard Worker                 if (format->contains(key.first.c_str())) {
203*ec779b8eSAndroid Build Coastguard Worker                     // AMessage::ItemData value = format->findItem(key.c_str());
204*ec779b8eSAndroid Build Coastguard Worker                     // levelCriticalFormat->setItem(key.c_str(), value);
205*ec779b8eSAndroid Build Coastguard Worker                     switch (key.second) {
206*ec779b8eSAndroid Build Coastguard Worker                         case AMessage::kTypeInt32: {
207*ec779b8eSAndroid Build Coastguard Worker                             int32_t value;
208*ec779b8eSAndroid Build Coastguard Worker                             format->findInt32(key.first.c_str(), &value);
209*ec779b8eSAndroid Build Coastguard Worker                             levelCriticalFormat->setInt32(key.first.c_str(), value);
210*ec779b8eSAndroid Build Coastguard Worker                             break;
211*ec779b8eSAndroid Build Coastguard Worker                         }
212*ec779b8eSAndroid Build Coastguard Worker                         case AMessage::kTypeString: {
213*ec779b8eSAndroid Build Coastguard Worker                             AString value;
214*ec779b8eSAndroid Build Coastguard Worker                             format->findString(key.first.c_str(), &value);
215*ec779b8eSAndroid Build Coastguard Worker                             levelCriticalFormat->setString(key.first.c_str(), value);
216*ec779b8eSAndroid Build Coastguard Worker                             break;
217*ec779b8eSAndroid Build Coastguard Worker                         }
218*ec779b8eSAndroid Build Coastguard Worker                         default:
219*ec779b8eSAndroid Build Coastguard Worker                             ALOGE("Unsupported type");
220*ec779b8eSAndroid Build Coastguard Worker                     }
221*ec779b8eSAndroid Build Coastguard Worker                 }
222*ec779b8eSAndroid Build Coastguard Worker             }
223*ec779b8eSAndroid Build Coastguard Worker             if (!levelCaps->isFormatSupported(levelCriticalFormat)) {
224*ec779b8eSAndroid Build Coastguard Worker                 return false;
225*ec779b8eSAndroid Build Coastguard Worker             }
226*ec779b8eSAndroid Build Coastguard Worker         }
227*ec779b8eSAndroid Build Coastguard Worker     }
228*ec779b8eSAndroid Build Coastguard Worker     if (mAudioCaps && !mAudioCaps->supportsFormat(format)) {
229*ec779b8eSAndroid Build Coastguard Worker         return false;
230*ec779b8eSAndroid Build Coastguard Worker     }
231*ec779b8eSAndroid Build Coastguard Worker     if (mVideoCaps && !mVideoCaps->supportsFormat(format)) {
232*ec779b8eSAndroid Build Coastguard Worker         return false;
233*ec779b8eSAndroid Build Coastguard Worker     }
234*ec779b8eSAndroid Build Coastguard Worker     if (mEncoderCaps && !mEncoderCaps->supportsFormat(format)) {
235*ec779b8eSAndroid Build Coastguard Worker         return false;
236*ec779b8eSAndroid Build Coastguard Worker     }
237*ec779b8eSAndroid Build Coastguard Worker     return true;
238*ec779b8eSAndroid Build Coastguard Worker }
239*ec779b8eSAndroid Build Coastguard Worker 
supportsProfileLevel(int32_t profile,int32_t level) const240*ec779b8eSAndroid Build Coastguard Worker bool CodecCapabilities::supportsProfileLevel(int32_t profile, int32_t level) const {
241*ec779b8eSAndroid Build Coastguard Worker     for (ProfileLevel pl: mProfileLevels) {
242*ec779b8eSAndroid Build Coastguard Worker         if (pl.mProfile != profile) {
243*ec779b8eSAndroid Build Coastguard Worker             continue;
244*ec779b8eSAndroid Build Coastguard Worker         }
245*ec779b8eSAndroid Build Coastguard Worker 
246*ec779b8eSAndroid Build Coastguard Worker         // No specific level requested
247*ec779b8eSAndroid Build Coastguard Worker         if (level == -1) {
248*ec779b8eSAndroid Build Coastguard Worker             return true;
249*ec779b8eSAndroid Build Coastguard Worker         }
250*ec779b8eSAndroid Build Coastguard Worker 
251*ec779b8eSAndroid Build Coastguard Worker         // AAC doesn't use levels
252*ec779b8eSAndroid Build Coastguard Worker         if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_AAC)) {
253*ec779b8eSAndroid Build Coastguard Worker             return true;
254*ec779b8eSAndroid Build Coastguard Worker         }
255*ec779b8eSAndroid Build Coastguard Worker 
256*ec779b8eSAndroid Build Coastguard Worker         // DTS doesn't use levels
257*ec779b8eSAndroid Build Coastguard Worker         if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_DTS)
258*ec779b8eSAndroid Build Coastguard Worker                 || base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_DTS_HD)
259*ec779b8eSAndroid Build Coastguard Worker                 || base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_DTS_UHD)) {
260*ec779b8eSAndroid Build Coastguard Worker             return true;
261*ec779b8eSAndroid Build Coastguard Worker         }
262*ec779b8eSAndroid Build Coastguard Worker 
263*ec779b8eSAndroid Build Coastguard Worker         // H.263 levels are not completely ordered:
264*ec779b8eSAndroid Build Coastguard Worker         // Level45 support only implies Level10 support
265*ec779b8eSAndroid Build Coastguard Worker         if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_VIDEO_H263)) {
266*ec779b8eSAndroid Build Coastguard Worker             if (pl.mLevel != level && pl.mLevel == H263Level45
267*ec779b8eSAndroid Build Coastguard Worker                     && level > H263Level10) {
268*ec779b8eSAndroid Build Coastguard Worker                 continue;
269*ec779b8eSAndroid Build Coastguard Worker             }
270*ec779b8eSAndroid Build Coastguard Worker         }
271*ec779b8eSAndroid Build Coastguard Worker 
272*ec779b8eSAndroid Build Coastguard Worker         // MPEG4 levels are not completely ordered:
273*ec779b8eSAndroid Build Coastguard Worker         // Level1 support only implies Level0 (and not Level0b) support
274*ec779b8eSAndroid Build Coastguard Worker         if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_VIDEO_MPEG4)) {
275*ec779b8eSAndroid Build Coastguard Worker             if (pl.mLevel != level && pl.mLevel == MPEG4Level1
276*ec779b8eSAndroid Build Coastguard Worker                     && level > MPEG4Level0) {
277*ec779b8eSAndroid Build Coastguard Worker                 continue;
278*ec779b8eSAndroid Build Coastguard Worker             }
279*ec779b8eSAndroid Build Coastguard Worker         }
280*ec779b8eSAndroid Build Coastguard Worker 
281*ec779b8eSAndroid Build Coastguard Worker         // HEVC levels incorporate both tiers and levels. Verify tier support.
282*ec779b8eSAndroid Build Coastguard Worker         if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_VIDEO_HEVC)) {
283*ec779b8eSAndroid Build Coastguard Worker             bool supportsHighTier =
284*ec779b8eSAndroid Build Coastguard Worker                 (pl.mLevel & HEVCHighTierLevels) != 0;
285*ec779b8eSAndroid Build Coastguard Worker             bool checkingHighTier = (level & HEVCHighTierLevels) != 0;
286*ec779b8eSAndroid Build Coastguard Worker             // high tier levels are only supported by other high tier levels
287*ec779b8eSAndroid Build Coastguard Worker             if (checkingHighTier && !supportsHighTier) {
288*ec779b8eSAndroid Build Coastguard Worker                 continue;
289*ec779b8eSAndroid Build Coastguard Worker             }
290*ec779b8eSAndroid Build Coastguard Worker         }
291*ec779b8eSAndroid Build Coastguard Worker 
292*ec779b8eSAndroid Build Coastguard Worker         if (pl.mLevel >= level) {
293*ec779b8eSAndroid Build Coastguard Worker             // if we recognize the listed profile/level, we must also recognize the
294*ec779b8eSAndroid Build Coastguard Worker             // profile/level arguments.
295*ec779b8eSAndroid Build Coastguard Worker             if (CreateFromProfileLevel(mMediaType, profile, pl.mLevel) != nullptr) {
296*ec779b8eSAndroid Build Coastguard Worker                 return CreateFromProfileLevel(mMediaType, profile, level) != nullptr;
297*ec779b8eSAndroid Build Coastguard Worker             }
298*ec779b8eSAndroid Build Coastguard Worker             return true;
299*ec779b8eSAndroid Build Coastguard Worker         }
300*ec779b8eSAndroid Build Coastguard Worker     }
301*ec779b8eSAndroid Build Coastguard Worker     return false;
302*ec779b8eSAndroid Build Coastguard Worker }
303*ec779b8eSAndroid Build Coastguard Worker 
getDefaultFormat() const304*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> CodecCapabilities::getDefaultFormat() const {
305*ec779b8eSAndroid Build Coastguard Worker     return mDefaultFormat;
306*ec779b8eSAndroid Build Coastguard Worker }
307*ec779b8eSAndroid Build Coastguard Worker 
getMediaType()308*ec779b8eSAndroid Build Coastguard Worker const std::string& CodecCapabilities::getMediaType() {
309*ec779b8eSAndroid Build Coastguard Worker     return mMediaType;
310*ec779b8eSAndroid Build Coastguard Worker }
311*ec779b8eSAndroid Build Coastguard Worker 
getProfileLevels()312*ec779b8eSAndroid Build Coastguard Worker const std::vector<ProfileLevel>& CodecCapabilities::getProfileLevels() {
313*ec779b8eSAndroid Build Coastguard Worker     return mProfileLevels;
314*ec779b8eSAndroid Build Coastguard Worker }
315*ec779b8eSAndroid Build Coastguard Worker 
getColorFormats() const316*ec779b8eSAndroid Build Coastguard Worker std::vector<uint32_t> CodecCapabilities::getColorFormats() const {
317*ec779b8eSAndroid Build Coastguard Worker     return mColorFormats;
318*ec779b8eSAndroid Build Coastguard Worker }
319*ec779b8eSAndroid Build Coastguard Worker 
getMaxSupportedInstances() const320*ec779b8eSAndroid Build Coastguard Worker int32_t CodecCapabilities::getMaxSupportedInstances() const {
321*ec779b8eSAndroid Build Coastguard Worker     return mMaxSupportedInstances;
322*ec779b8eSAndroid Build Coastguard Worker }
323*ec779b8eSAndroid Build Coastguard Worker 
isAudio() const324*ec779b8eSAndroid Build Coastguard Worker bool CodecCapabilities::isAudio() const {
325*ec779b8eSAndroid Build Coastguard Worker     return mAudioCaps != nullptr;
326*ec779b8eSAndroid Build Coastguard Worker }
327*ec779b8eSAndroid Build Coastguard Worker 
328*ec779b8eSAndroid Build Coastguard Worker std::shared_ptr<AudioCapabilities>
getAudioCapabilities() const329*ec779b8eSAndroid Build Coastguard Worker         CodecCapabilities::getAudioCapabilities() const {
330*ec779b8eSAndroid Build Coastguard Worker     return mAudioCaps;
331*ec779b8eSAndroid Build Coastguard Worker }
332*ec779b8eSAndroid Build Coastguard Worker 
isEncoder() const333*ec779b8eSAndroid Build Coastguard Worker bool CodecCapabilities::isEncoder() const {
334*ec779b8eSAndroid Build Coastguard Worker     return mEncoderCaps != nullptr;
335*ec779b8eSAndroid Build Coastguard Worker }
336*ec779b8eSAndroid Build Coastguard Worker 
337*ec779b8eSAndroid Build Coastguard Worker std::shared_ptr<EncoderCapabilities>
getEncoderCapabilities() const338*ec779b8eSAndroid Build Coastguard Worker         CodecCapabilities::getEncoderCapabilities() const {
339*ec779b8eSAndroid Build Coastguard Worker     return mEncoderCaps;
340*ec779b8eSAndroid Build Coastguard Worker }
341*ec779b8eSAndroid Build Coastguard Worker 
isVideo() const342*ec779b8eSAndroid Build Coastguard Worker bool CodecCapabilities::isVideo() const {
343*ec779b8eSAndroid Build Coastguard Worker     return mVideoCaps != nullptr;
344*ec779b8eSAndroid Build Coastguard Worker }
345*ec779b8eSAndroid Build Coastguard Worker 
getVideoCapabilities() const346*ec779b8eSAndroid Build Coastguard Worker std::shared_ptr<VideoCapabilities> CodecCapabilities::getVideoCapabilities() const {
347*ec779b8eSAndroid Build Coastguard Worker     return mVideoCaps;
348*ec779b8eSAndroid Build Coastguard Worker }
349*ec779b8eSAndroid Build Coastguard Worker 
350*ec779b8eSAndroid Build Coastguard Worker // static
CreateFromProfileLevel(std::string mediaType,int32_t profile,int32_t level,int32_t maxConcurrentInstances)351*ec779b8eSAndroid Build Coastguard Worker std::shared_ptr<CodecCapabilities> CodecCapabilities::CreateFromProfileLevel(
352*ec779b8eSAndroid Build Coastguard Worker         std::string mediaType, int32_t profile, int32_t level, int32_t maxConcurrentInstances) {
353*ec779b8eSAndroid Build Coastguard Worker     ProfileLevel pl;
354*ec779b8eSAndroid Build Coastguard Worker     pl.mProfile = profile;
355*ec779b8eSAndroid Build Coastguard Worker     pl.mLevel = level;
356*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> defaultFormat = new AMessage;
357*ec779b8eSAndroid Build Coastguard Worker     defaultFormat->setString(KEY_MIME, mediaType.c_str());
358*ec779b8eSAndroid Build Coastguard Worker 
359*ec779b8eSAndroid Build Coastguard Worker     std::vector<ProfileLevel> pls;
360*ec779b8eSAndroid Build Coastguard Worker     pls.push_back(pl);
361*ec779b8eSAndroid Build Coastguard Worker     std::vector<uint32_t> colFmts;
362*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> capabilitiesInfo = new AMessage;
363*ec779b8eSAndroid Build Coastguard Worker     std::shared_ptr<CodecCapabilities> ret(new CodecCapabilities());
364*ec779b8eSAndroid Build Coastguard Worker     ret->init(pls, colFmts, true /* encoder */, defaultFormat, capabilitiesInfo,
365*ec779b8eSAndroid Build Coastguard Worker             maxConcurrentInstances);
366*ec779b8eSAndroid Build Coastguard Worker     if (ret->getErrors() != 0) {
367*ec779b8eSAndroid Build Coastguard Worker         return nullptr;
368*ec779b8eSAndroid Build Coastguard Worker     }
369*ec779b8eSAndroid Build Coastguard Worker     return ret;
370*ec779b8eSAndroid Build Coastguard Worker }
371*ec779b8eSAndroid Build Coastguard Worker 
init(std::vector<ProfileLevel> profLevs,std::vector<uint32_t> colFmts,bool encoder,sp<AMessage> & defaultFormat,sp<AMessage> & capabilitiesInfo,int32_t maxConcurrentInstances)372*ec779b8eSAndroid Build Coastguard Worker void CodecCapabilities::init(std::vector<ProfileLevel> profLevs, std::vector<uint32_t> colFmts,
373*ec779b8eSAndroid Build Coastguard Worker         bool encoder, sp<AMessage> &defaultFormat, sp<AMessage> &capabilitiesInfo,
374*ec779b8eSAndroid Build Coastguard Worker         int32_t maxConcurrentInstances) {
375*ec779b8eSAndroid Build Coastguard Worker     mColorFormats = colFmts;
376*ec779b8eSAndroid Build Coastguard Worker     mDefaultFormat = defaultFormat;
377*ec779b8eSAndroid Build Coastguard Worker     mCapabilitiesInfo = capabilitiesInfo;
378*ec779b8eSAndroid Build Coastguard Worker 
379*ec779b8eSAndroid Build Coastguard Worker     AString mediaTypeAStr;
380*ec779b8eSAndroid Build Coastguard Worker     mDefaultFormat->findString(KEY_MIME, &mediaTypeAStr);
381*ec779b8eSAndroid Build Coastguard Worker     mMediaType = mediaTypeAStr.c_str();
382*ec779b8eSAndroid Build Coastguard Worker 
383*ec779b8eSAndroid Build Coastguard Worker     /* VP9 introduced profiles around 2016, so some VP9 codecs may not advertise any
384*ec779b8eSAndroid Build Coastguard Worker        supported profiles. Determine the level for them using the info they provide. */
385*ec779b8eSAndroid Build Coastguard Worker     if (profLevs.size() == 0 && mMediaType == MIMETYPE_VIDEO_VP9) {
386*ec779b8eSAndroid Build Coastguard Worker         ProfileLevel profLev;
387*ec779b8eSAndroid Build Coastguard Worker         profLev.mProfile = VP9Profile0;
388*ec779b8eSAndroid Build Coastguard Worker         profLev.mLevel = VideoCapabilities::EquivalentVP9Level(capabilitiesInfo);
389*ec779b8eSAndroid Build Coastguard Worker         profLevs.push_back(profLev);
390*ec779b8eSAndroid Build Coastguard Worker     }
391*ec779b8eSAndroid Build Coastguard Worker     mProfileLevels = profLevs;
392*ec779b8eSAndroid Build Coastguard Worker 
393*ec779b8eSAndroid Build Coastguard Worker     if (mediaTypeAStr.startsWithIgnoreCase("audio/")) {
394*ec779b8eSAndroid Build Coastguard Worker         mAudioCaps = AudioCapabilities::Create(mMediaType, profLevs, capabilitiesInfo);
395*ec779b8eSAndroid Build Coastguard Worker         mAudioCaps->getDefaultFormat(mDefaultFormat);
396*ec779b8eSAndroid Build Coastguard Worker     } else if (mediaTypeAStr.startsWithIgnoreCase("video/")
397*ec779b8eSAndroid Build Coastguard Worker             || mediaTypeAStr.equalsIgnoreCase(MIMETYPE_IMAGE_ANDROID_HEIC)) {
398*ec779b8eSAndroid Build Coastguard Worker         mVideoCaps = VideoCapabilities::Create(mMediaType, profLevs, capabilitiesInfo);
399*ec779b8eSAndroid Build Coastguard Worker     }
400*ec779b8eSAndroid Build Coastguard Worker 
401*ec779b8eSAndroid Build Coastguard Worker     if (encoder) {
402*ec779b8eSAndroid Build Coastguard Worker         mEncoderCaps = EncoderCapabilities::Create(mMediaType, profLevs, capabilitiesInfo);
403*ec779b8eSAndroid Build Coastguard Worker         mEncoderCaps->getDefaultFormat(mDefaultFormat);
404*ec779b8eSAndroid Build Coastguard Worker     }
405*ec779b8eSAndroid Build Coastguard Worker 
406*ec779b8eSAndroid Build Coastguard Worker     mMaxSupportedInstances = maxConcurrentInstances > 0
407*ec779b8eSAndroid Build Coastguard Worker             ? maxConcurrentInstances : DEFAULT_MAX_SUPPORTED_INSTANCES;
408*ec779b8eSAndroid Build Coastguard Worker 
409*ec779b8eSAndroid Build Coastguard Worker     int32_t maxInstances = mMaxSupportedInstances;
410*ec779b8eSAndroid Build Coastguard Worker     capabilitiesInfo->findInt32("max-concurrent-instances", &maxInstances);
411*ec779b8eSAndroid Build Coastguard Worker     mMaxSupportedInstances =
412*ec779b8eSAndroid Build Coastguard Worker             Range(1, MAX_SUPPORTED_INSTANCES_LIMIT).clamp(maxInstances);
413*ec779b8eSAndroid Build Coastguard Worker 
414*ec779b8eSAndroid Build Coastguard Worker     mFeaturesRequired.clear();
415*ec779b8eSAndroid Build Coastguard Worker     mFeaturesSupported.clear();
416*ec779b8eSAndroid Build Coastguard Worker     for (Feature feat: getValidFeatures()) {
417*ec779b8eSAndroid Build Coastguard Worker         std::string key = KEY_FEATURE_;
418*ec779b8eSAndroid Build Coastguard Worker         key = key + feat.mName;
419*ec779b8eSAndroid Build Coastguard Worker         int yesNo = -1;
420*ec779b8eSAndroid Build Coastguard Worker         if (!capabilitiesInfo->findInt32(key.c_str(), &yesNo)) {
421*ec779b8eSAndroid Build Coastguard Worker             continue;
422*ec779b8eSAndroid Build Coastguard Worker         }
423*ec779b8eSAndroid Build Coastguard Worker         if (yesNo > 0) {
424*ec779b8eSAndroid Build Coastguard Worker             mFeaturesRequired.insert(feat.mName);
425*ec779b8eSAndroid Build Coastguard Worker         }
426*ec779b8eSAndroid Build Coastguard Worker         mFeaturesSupported.insert(feat.mName);
427*ec779b8eSAndroid Build Coastguard Worker         if (!feat.mInternal) {
428*ec779b8eSAndroid Build Coastguard Worker             mDefaultFormat->setInt32(key.c_str(), 1);
429*ec779b8eSAndroid Build Coastguard Worker         }
430*ec779b8eSAndroid Build Coastguard Worker     }
431*ec779b8eSAndroid Build Coastguard Worker }
432*ec779b8eSAndroid Build Coastguard Worker 
getErrors() const433*ec779b8eSAndroid Build Coastguard Worker int32_t CodecCapabilities::getErrors() const {
434*ec779b8eSAndroid Build Coastguard Worker     if (mAudioCaps) {
435*ec779b8eSAndroid Build Coastguard Worker         return mAudioCaps->mError;
436*ec779b8eSAndroid Build Coastguard Worker     } else if (mVideoCaps) {
437*ec779b8eSAndroid Build Coastguard Worker         return mVideoCaps->mError;
438*ec779b8eSAndroid Build Coastguard Worker     }
439*ec779b8eSAndroid Build Coastguard Worker     return 0;
440*ec779b8eSAndroid Build Coastguard Worker }
441*ec779b8eSAndroid Build Coastguard Worker 
442*ec779b8eSAndroid Build Coastguard Worker }  // namespace android