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