1 /* 2 * Copyright (C) 2012 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 package android.media; 18 19 import static android.media.audio.Flags.FLAG_IAMF_DEFINITIONS_API; 20 import static android.media.codec.Flags.FLAG_DYNAMIC_COLOR_ASPECTS; 21 import static android.media.codec.Flags.FLAG_HLG_EDITING; 22 import static android.media.codec.Flags.FLAG_IN_PROCESS_SW_AUDIO_CODEC; 23 import static android.media.codec.Flags.FLAG_NULL_OUTPUT_SURFACE; 24 import static android.media.codec.Flags.FLAG_REGION_OF_INTEREST; 25 import static android.media.codec.Flags.FLAG_APV_SUPPORT; 26 import static android.media.Utils.intersectSortedDistinctRanges; 27 import static android.media.Utils.sortDistinctRanges; 28 import static android.media.MediaCodec.GetFlag; 29 30 import android.annotation.FlaggedApi; 31 import android.annotation.IntDef; 32 import android.annotation.IntRange; 33 import android.annotation.NonNull; 34 import android.annotation.Nullable; 35 import android.annotation.SuppressLint; 36 import android.annotation.TestApi; 37 import android.compat.annotation.UnsupportedAppUsage; 38 import android.os.Build; 39 import android.os.Process; 40 import android.os.SystemProperties; 41 import android.sysprop.MediaProperties; 42 import android.util.Log; 43 import android.util.Pair; 44 import android.util.Range; 45 import android.util.Rational; 46 import android.util.Size; 47 48 import java.lang.annotation.Retention; 49 import java.lang.annotation.RetentionPolicy; 50 import java.util.ArrayList; 51 import java.util.Arrays; 52 import java.util.Collections; 53 import java.util.HashMap; 54 import java.util.List; 55 import java.util.Map; 56 import java.util.Set; 57 import java.util.Vector; 58 59 /** 60 * Provides information about a given media codec available on the device. You can 61 * iterate through all codecs available by querying {@link MediaCodecList}. For example, 62 * here's how to find an encoder that supports a given MIME type: 63 * <pre> 64 * private static MediaCodecInfo selectCodec(String mimeType) { 65 * int numCodecs = MediaCodecList.getCodecCount(); 66 * for (int i = 0; i < numCodecs; i++) { 67 * MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i); 68 * 69 * if (!codecInfo.isEncoder()) { 70 * continue; 71 * } 72 * 73 * String[] types = codecInfo.getSupportedTypes(); 74 * for (int j = 0; j < types.length; j++) { 75 * if (types[j].equalsIgnoreCase(mimeType)) { 76 * return codecInfo; 77 * } 78 * } 79 * } 80 * return null; 81 * }</pre> 82 * 83 */ 84 public final class MediaCodecInfo { 85 private static final String TAG = "MediaCodecInfo"; 86 87 private static final int FLAG_IS_ENCODER = (1 << 0); 88 private static final int FLAG_IS_VENDOR = (1 << 1); 89 private static final int FLAG_IS_SOFTWARE_ONLY = (1 << 2); 90 private static final int FLAG_IS_HARDWARE_ACCELERATED = (1 << 3); 91 92 private int mFlags; 93 private String mName; 94 private String mCanonicalName; 95 private Map<String, CodecCapabilities> mCaps; 96 MediaCodecInfo( String name, String canonicalName, int flags, CodecCapabilities[] caps)97 /* package private */ MediaCodecInfo( 98 String name, String canonicalName, int flags, CodecCapabilities[] caps) { 99 mName = name; 100 mCanonicalName = canonicalName; 101 mFlags = flags; 102 mCaps = new HashMap<String, CodecCapabilities>(); 103 104 for (CodecCapabilities c: caps) { 105 mCaps.put(c.getMimeType(), c); 106 } 107 } 108 109 /** 110 * Retrieve the codec name. 111 * 112 * <strong>Note:</strong> Implementations may provide multiple aliases (codec 113 * names) for the same underlying codec, any of which can be used to instantiate the same 114 * underlying codec in {@link MediaCodec#createByCodecName}. 115 * 116 * Applications targeting SDK < {@link android.os.Build.VERSION_CODES#Q}, cannot determine if 117 * the multiple codec names listed in MediaCodecList are in-fact for the same codec. 118 */ 119 @NonNull getName()120 public final String getName() { 121 return mName; 122 } 123 124 /** 125 * Retrieve the underlying codec name. 126 * 127 * Device implementations may provide multiple aliases (codec names) for the same underlying 128 * codec to maintain backward app compatibility. This method returns the name of the underlying 129 * codec name, which must not be another alias. For non-aliases this is always the name of the 130 * codec. 131 */ 132 @NonNull getCanonicalName()133 public final String getCanonicalName() { 134 return mCanonicalName; 135 } 136 137 /** 138 * Query if the codec is an alias for another underlying codec. 139 */ isAlias()140 public final boolean isAlias() { 141 return !mName.equals(mCanonicalName); 142 } 143 144 /** 145 * Query if the codec is an encoder. 146 */ isEncoder()147 public final boolean isEncoder() { 148 return (mFlags & FLAG_IS_ENCODER) != 0; 149 } 150 151 /** 152 * Query if the codec is provided by the Android platform (false) or the device manufacturer 153 * (true). 154 */ isVendor()155 public final boolean isVendor() { 156 return (mFlags & FLAG_IS_VENDOR) != 0; 157 } 158 159 /** 160 * Query if the codec is software only. Software-only codecs are more secure as they run in 161 * a tighter security sandbox. On the other hand, software-only codecs do not provide any 162 * performance guarantees. 163 */ isSoftwareOnly()164 public final boolean isSoftwareOnly() { 165 return (mFlags & FLAG_IS_SOFTWARE_ONLY) != 0; 166 } 167 168 /** 169 * Query if the codec is hardware accelerated. This attribute is provided by the device 170 * manufacturer. Note that it cannot be tested for correctness. 171 */ isHardwareAccelerated()172 public final boolean isHardwareAccelerated() { 173 return (mFlags & FLAG_IS_HARDWARE_ACCELERATED) != 0; 174 } 175 176 /** 177 * Query the media types supported by the codec. 178 */ getSupportedTypes()179 public final String[] getSupportedTypes() { 180 Set<String> typeSet = mCaps.keySet(); 181 String[] types = typeSet.toArray(new String[typeSet.size()]); 182 Arrays.sort(types); 183 return types; 184 } 185 checkPowerOfTwo(int value, String message)186 private static int checkPowerOfTwo(int value, String message) { 187 if ((value & (value - 1)) != 0) { 188 throw new IllegalArgumentException(message); 189 } 190 return value; 191 } 192 193 private static class Feature { 194 public String mName; 195 public int mValue; 196 public boolean mDefault; 197 public boolean mInternal; Feature(String name, int value, boolean def)198 public Feature(String name, int value, boolean def) { 199 this(name, value, def, false /* internal */); 200 } Feature(String name, int value, boolean def, boolean internal)201 public Feature(String name, int value, boolean def, boolean internal) { 202 mName = name; 203 mValue = value; 204 mDefault = def; 205 mInternal = internal; 206 } 207 } 208 209 // COMMON CONSTANTS 210 private static final Range<Integer> POSITIVE_INTEGERS = 211 Range.create(1, Integer.MAX_VALUE); 212 private static final Range<Long> POSITIVE_LONGS = 213 Range.create(1L, Long.MAX_VALUE); 214 private static final Range<Rational> POSITIVE_RATIONALS = 215 Range.create(new Rational(1, Integer.MAX_VALUE), 216 new Rational(Integer.MAX_VALUE, 1)); 217 private static final Range<Integer> FRAME_RATE_RANGE = Range.create(0, 960); 218 private static final Range<Integer> BITRATE_RANGE = Range.create(0, 500000000); 219 private static final int DEFAULT_MAX_SUPPORTED_INSTANCES = 32; 220 private static final int MAX_SUPPORTED_INSTANCES_LIMIT = 256; 221 222 private static Range<Integer> SIZE_RANGE; getSizeRange()223 private static synchronized Range<Integer> getSizeRange() { 224 if (SIZE_RANGE == null) { 225 SIZE_RANGE = Process.is64Bit() 226 ? Range.create(1, 32768) 227 : Range.create(1, MediaProperties.resolution_limit_32bit().orElse(4096)); 228 } 229 return SIZE_RANGE; 230 } 231 232 // found stuff that is not supported by framework (=> this should not happen) 233 private static final int ERROR_UNRECOGNIZED = (1 << 0); 234 // found profile/level for which we don't have capability estimates 235 private static final int ERROR_UNSUPPORTED = (1 << 1); 236 // have not found any profile/level for which we don't have capability estimate 237 private static final int ERROR_NONE_SUPPORTED = (1 << 2); 238 239 240 /** 241 * Encapsulates the capabilities of a given codec component. 242 * For example, what profile/level combinations it supports and what colorspaces 243 * it is capable of providing the decoded data in, as well as some 244 * codec-type specific capability flags. 245 * <p>You can get an instance for a given {@link MediaCodecInfo} object with 246 * {@link MediaCodecInfo#getCapabilitiesForType getCapabilitiesForType()}, passing a MIME type. 247 */ 248 public static final class CodecCapabilities { CodecCapabilities()249 public CodecCapabilities() { 250 } 251 252 // CLASSIFICATION 253 private String mMime; 254 private int mMaxSupportedInstances; 255 256 // LEGACY FIELDS 257 258 // Enumerates supported profile/level combinations as defined 259 // by the type of encoded data. These combinations impose restrictions 260 // on video resolution, bitrate... and limit the available encoder tools 261 // such as B-frame support, arithmetic coding... 262 public CodecProfileLevel[] profileLevels; // NOTE this array is modifiable by user 263 264 // from MediaCodecConstants 265 /** @deprecated Use {@link #COLOR_Format24bitBGR888}. */ 266 public static final int COLOR_FormatMonochrome = 1; 267 /** @deprecated Use {@link #COLOR_Format24bitBGR888}. */ 268 public static final int COLOR_Format8bitRGB332 = 2; 269 /** @deprecated Use {@link #COLOR_Format24bitBGR888}. */ 270 public static final int COLOR_Format12bitRGB444 = 3; 271 /** @deprecated Use {@link #COLOR_Format32bitABGR8888}. */ 272 public static final int COLOR_Format16bitARGB4444 = 4; 273 /** @deprecated Use {@link #COLOR_Format32bitABGR8888}. */ 274 public static final int COLOR_Format16bitARGB1555 = 5; 275 276 /** 277 * 16 bits per pixel RGB color format, with 5-bit red & blue and 6-bit green component. 278 * <p> 279 * Using 16-bit little-endian representation, colors stored as Red 15:11, Green 10:5, Blue 4:0. 280 * <pre> 281 * byte byte 282 * <--------- i --------> | <------ i + 1 ------> 283 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 284 * | BLUE | GREEN | RED | 285 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 286 * 0 4 5 7 0 2 3 7 287 * bit 288 * </pre> 289 * 290 * This format corresponds to {@link android.graphics.PixelFormat#RGB_565} and 291 * {@link android.graphics.ImageFormat#RGB_565}. 292 */ 293 public static final int COLOR_Format16bitRGB565 = 6; 294 /** @deprecated Use {@link #COLOR_Format16bitRGB565}. */ 295 public static final int COLOR_Format16bitBGR565 = 7; 296 /** @deprecated Use {@link #COLOR_Format24bitBGR888}. */ 297 public static final int COLOR_Format18bitRGB666 = 8; 298 /** @deprecated Use {@link #COLOR_Format32bitABGR8888}. */ 299 public static final int COLOR_Format18bitARGB1665 = 9; 300 /** @deprecated Use {@link #COLOR_Format32bitABGR8888}. */ 301 public static final int COLOR_Format19bitARGB1666 = 10; 302 303 /** @deprecated Use {@link #COLOR_Format24bitBGR888} or {@link #COLOR_FormatRGBFlexible}. */ 304 public static final int COLOR_Format24bitRGB888 = 11; 305 306 /** 307 * 24 bits per pixel RGB color format, with 8-bit red, green & blue components. 308 * <p> 309 * Using 24-bit little-endian representation, colors stored as Red 7:0, Green 15:8, Blue 23:16. 310 * <pre> 311 * byte byte byte 312 * <------ i -----> | <---- i+1 ----> | <---- i+2 -----> 313 * +-----------------+-----------------+-----------------+ 314 * | RED | GREEN | BLUE | 315 * +-----------------+-----------------+-----------------+ 316 * </pre> 317 * 318 * This format corresponds to {@link android.graphics.PixelFormat#RGB_888}, and can also be 319 * represented as a flexible format by {@link #COLOR_FormatRGBFlexible}. 320 */ 321 public static final int COLOR_Format24bitBGR888 = 12; 322 /** @deprecated Use {@link #COLOR_Format32bitABGR8888}. */ 323 public static final int COLOR_Format24bitARGB1887 = 13; 324 /** @deprecated Use {@link #COLOR_Format32bitABGR8888}. */ 325 public static final int COLOR_Format25bitARGB1888 = 14; 326 327 /** 328 * @deprecated Use {@link #COLOR_Format32bitABGR8888} Or {@link #COLOR_FormatRGBAFlexible}. 329 */ 330 public static final int COLOR_Format32bitBGRA8888 = 15; 331 /** 332 * @deprecated Use {@link #COLOR_Format32bitABGR8888} Or {@link #COLOR_FormatRGBAFlexible}. 333 */ 334 public static final int COLOR_Format32bitARGB8888 = 16; 335 /** @deprecated Use {@link #COLOR_FormatYUV420Flexible}. */ 336 public static final int COLOR_FormatYUV411Planar = 17; 337 /** @deprecated Use {@link #COLOR_FormatYUV420Flexible}. */ 338 public static final int COLOR_FormatYUV411PackedPlanar = 18; 339 /** @deprecated Use {@link #COLOR_FormatYUV420Flexible}. */ 340 public static final int COLOR_FormatYUV420Planar = 19; 341 /** @deprecated Use {@link #COLOR_FormatYUV420Flexible}. */ 342 public static final int COLOR_FormatYUV420PackedPlanar = 20; 343 /** @deprecated Use {@link #COLOR_FormatYUV420Flexible}. */ 344 public static final int COLOR_FormatYUV420SemiPlanar = 21; 345 346 /** @deprecated Use {@link #COLOR_FormatYUV422Flexible}. */ 347 public static final int COLOR_FormatYUV422Planar = 22; 348 /** @deprecated Use {@link #COLOR_FormatYUV422Flexible}. */ 349 public static final int COLOR_FormatYUV422PackedPlanar = 23; 350 /** @deprecated Use {@link #COLOR_FormatYUV422Flexible}. */ 351 public static final int COLOR_FormatYUV422SemiPlanar = 24; 352 353 /** @deprecated Use {@link #COLOR_FormatYUV422Flexible}. */ 354 public static final int COLOR_FormatYCbYCr = 25; 355 /** @deprecated Use {@link #COLOR_FormatYUV422Flexible}. */ 356 public static final int COLOR_FormatYCrYCb = 26; 357 /** @deprecated Use {@link #COLOR_FormatYUV422Flexible}. */ 358 public static final int COLOR_FormatCbYCrY = 27; 359 /** @deprecated Use {@link #COLOR_FormatYUV422Flexible}. */ 360 public static final int COLOR_FormatCrYCbY = 28; 361 362 /** @deprecated Use {@link #COLOR_FormatYUV444Flexible}. */ 363 public static final int COLOR_FormatYUV444Interleaved = 29; 364 365 /** 366 * SMIA 8-bit Bayer format. 367 * Each byte represents the top 8-bits of a 10-bit signal. 368 */ 369 public static final int COLOR_FormatRawBayer8bit = 30; 370 /** 371 * SMIA 10-bit Bayer format. 372 */ 373 public static final int COLOR_FormatRawBayer10bit = 31; 374 375 /** 376 * SMIA 8-bit compressed Bayer format. 377 * Each byte represents a sample from the 10-bit signal that is compressed into 8-bits 378 * using DPCM/PCM compression, as defined by the SMIA Functional Specification. 379 */ 380 public static final int COLOR_FormatRawBayer8bitcompressed = 32; 381 382 /** @deprecated Use {@link #COLOR_FormatL8}. */ 383 public static final int COLOR_FormatL2 = 33; 384 /** @deprecated Use {@link #COLOR_FormatL8}. */ 385 public static final int COLOR_FormatL4 = 34; 386 387 /** 388 * 8 bits per pixel Y color format. 389 * <p> 390 * Each byte contains a single pixel. 391 * This format corresponds to {@link android.graphics.PixelFormat#L_8}. 392 */ 393 public static final int COLOR_FormatL8 = 35; 394 395 /** 396 * 16 bits per pixel, little-endian Y color format. 397 * <p> 398 * <pre> 399 * byte byte 400 * <--------- i --------> | <------ i + 1 ------> 401 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 402 * | Y | 403 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 404 * 0 7 0 7 405 * bit 406 * </pre> 407 */ 408 public static final int COLOR_FormatL16 = 36; 409 /** @deprecated Use {@link #COLOR_FormatL16}. */ 410 public static final int COLOR_FormatL24 = 37; 411 412 /** 413 * 32 bits per pixel, little-endian Y color format. 414 * <p> 415 * <pre> 416 * byte byte byte byte 417 * <------ i -----> | <---- i+1 ----> | <---- i+2 ----> | <---- i+3 -----> 418 * +-----------------+-----------------+-----------------+-----------------+ 419 * | Y | 420 * +-----------------+-----------------+-----------------+-----------------+ 421 * 0 7 0 7 0 7 0 7 422 * bit 423 * </pre> 424 * 425 * @deprecated Use {@link #COLOR_FormatL16}. 426 */ 427 public static final int COLOR_FormatL32 = 38; 428 429 /** @deprecated Use {@link #COLOR_FormatYUV420Flexible}. */ 430 public static final int COLOR_FormatYUV420PackedSemiPlanar = 39; 431 /** @deprecated Use {@link #COLOR_FormatYUV422Flexible}. */ 432 public static final int COLOR_FormatYUV422PackedSemiPlanar = 40; 433 434 /** @deprecated Use {@link #COLOR_Format24bitBGR888}. */ 435 public static final int COLOR_Format18BitBGR666 = 41; 436 437 /** @deprecated Use {@link #COLOR_Format32bitABGR8888}. */ 438 public static final int COLOR_Format24BitARGB6666 = 42; 439 /** @deprecated Use {@link #COLOR_Format32bitABGR8888}. */ 440 public static final int COLOR_Format24BitABGR6666 = 43; 441 442 /** 443 * P010 is 10-bit-per component 4:2:0 YCbCr semiplanar format. 444 * <p> 445 * This format uses 24 allocated bits per pixel with 15 bits of 446 * data per pixel. Chroma planes are subsampled by 2 both 447 * horizontally and vertically. Each chroma and luma component 448 * has 16 allocated bits in little-endian configuration with 10 449 * MSB of actual data. 450 * 451 * <pre> 452 * byte byte 453 * <--------- i --------> | <------ i + 1 ------> 454 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 455 * | UNUSED | Y/Cb/Cr | 456 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 457 * 0 5 6 7 0 7 458 * bit 459 * </pre> 460 * 461 * Use this format with {@link Image}. This format corresponds 462 * to {@link android.graphics.ImageFormat#YCBCR_P010}. 463 * <p> 464 */ 465 @SuppressLint("AllUpper") 466 public static final int COLOR_FormatYUVP010 = 54; 467 468 /** 469 * P210 is 10-bit-per component 4:2:2 YCbCr semiplanar format. 470 * <p> 471 * This format uses 32 allocated bits per pixel with 20 bits of 472 * data per pixel. Chroma planes are subsampled by 2 both 473 * horizontally. Each chroma and luma component 474 * has 16 allocated bits in little-endian configuration with 10 475 * MSB of actual data. 476 * 477 * <pre> 478 * byte byte 479 * <--------- i --------> | <------ i + 1 ------> 480 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 481 * | UNUSED | Y/Cb/Cr | 482 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 483 * 0 5 6 7 0 7 484 * bit 485 * </pre> 486 * 487 * Use this format with {@link Image}. This format corresponds 488 * to {@link android.graphics.ImageFormat#YCBCR_P210}. 489 * <p> 490 */ 491 @SuppressLint("AllUpper") 492 @FlaggedApi(android.media.codec.Flags.FLAG_P210_FORMAT_SUPPORT) 493 public static final int COLOR_FormatYUVP210 = 60; 494 495 /** @deprecated Use {@link #COLOR_FormatYUV420Flexible}. */ 496 public static final int COLOR_TI_FormatYUV420PackedSemiPlanar = 0x7f000100; 497 // COLOR_FormatSurface indicates that the data will be a GraphicBuffer metadata reference. 498 // Note: in OMX this is called OMX_COLOR_FormatAndroidOpaque. 499 public static final int COLOR_FormatSurface = 0x7F000789; 500 501 /** 502 * 64 bits per pixel RGBA color format, with 16-bit signed 503 * floating point red, green, blue, and alpha components. 504 * <p> 505 * 506 * <pre> 507 * byte byte byte byte 508 * <-- i -->|<- i+1 ->|<- i+2 ->|<- i+3 ->|<- i+4 ->|<- i+5 ->|<- i+6 ->|<- i+7 -> 509 * +---------+---------+-------------------+---------+---------+---------+---------+ 510 * | RED | GREEN | BLUE | ALPHA | 511 * +---------+---------+-------------------+---------+---------+---------+---------+ 512 * 0 7 0 7 0 7 0 7 0 7 0 7 0 7 0 7 513 * </pre> 514 * 515 * This corresponds to {@link android.graphics.PixelFormat#RGBA_F16}. 516 */ 517 @SuppressLint("AllUpper") 518 public static final int COLOR_Format64bitABGRFloat = 0x7F000F16; 519 520 /** 521 * 32 bits per pixel RGBA color format, with 8-bit red, green, blue, and alpha components. 522 * <p> 523 * Using 32-bit little-endian representation, colors stored as Red 7:0, Green 15:8, 524 * Blue 23:16, and Alpha 31:24. 525 * <pre> 526 * byte byte byte byte 527 * <------ i -----> | <---- i+1 ----> | <---- i+2 ----> | <---- i+3 -----> 528 * +-----------------+-----------------+-----------------+-----------------+ 529 * | RED | GREEN | BLUE | ALPHA | 530 * +-----------------+-----------------+-----------------+-----------------+ 531 * </pre> 532 * 533 * This corresponds to {@link android.graphics.PixelFormat#RGBA_8888}. 534 */ 535 public static final int COLOR_Format32bitABGR8888 = 0x7F00A000; 536 537 /** 538 * 32 bits per pixel RGBA color format, with 10-bit red, green, 539 * blue, and 2-bit alpha components. 540 * <p> 541 * Using 32-bit little-endian representation, colors stored as 542 * Red 9:0, Green 19:10, Blue 29:20, and Alpha 31:30. 543 * <pre> 544 * byte byte byte byte 545 * <------ i -----> | <---- i+1 ----> | <---- i+2 ----> | <---- i+3 -----> 546 * +-----------------+---+-------------+-------+---------+-----------+-----+ 547 * | RED | GREEN | BLUE |ALPHA| 548 * +-----------------+---+-------------+-------+---------+-----------+-----+ 549 * 0 7 0 1 2 7 0 3 4 7 0 5 6 7 550 * </pre> 551 * 552 * This corresponds to {@link android.graphics.PixelFormat#RGBA_1010102}. 553 */ 554 @SuppressLint("AllUpper") 555 public static final int COLOR_Format32bitABGR2101010 = 0x7F00AAA2; 556 557 /** 558 * Flexible 12 bits per pixel, subsampled YUV color format with 8-bit chroma and luma 559 * components. 560 * <p> 561 * Chroma planes are subsampled by 2 both horizontally and vertically. 562 * Use this format with {@link Image}. 563 * This format corresponds to {@link android.graphics.ImageFormat#YUV_420_888}, 564 * and can represent the {@link #COLOR_FormatYUV411Planar}, 565 * {@link #COLOR_FormatYUV411PackedPlanar}, {@link #COLOR_FormatYUV420Planar}, 566 * {@link #COLOR_FormatYUV420PackedPlanar}, {@link #COLOR_FormatYUV420SemiPlanar} 567 * and {@link #COLOR_FormatYUV420PackedSemiPlanar} formats. 568 * 569 * @see Image#getFormat 570 */ 571 public static final int COLOR_FormatYUV420Flexible = 0x7F420888; 572 573 /** 574 * Flexible 16 bits per pixel, subsampled YUV color format with 8-bit chroma and luma 575 * components. 576 * <p> 577 * Chroma planes are horizontally subsampled by 2. Use this format with {@link Image}. 578 * This format corresponds to {@link android.graphics.ImageFormat#YUV_422_888}, 579 * and can represent the {@link #COLOR_FormatYCbYCr}, {@link #COLOR_FormatYCrYCb}, 580 * {@link #COLOR_FormatCbYCrY}, {@link #COLOR_FormatCrYCbY}, 581 * {@link #COLOR_FormatYUV422Planar}, {@link #COLOR_FormatYUV422PackedPlanar}, 582 * {@link #COLOR_FormatYUV422SemiPlanar} and {@link #COLOR_FormatYUV422PackedSemiPlanar} 583 * formats. 584 * 585 * @see Image#getFormat 586 */ 587 public static final int COLOR_FormatYUV422Flexible = 0x7F422888; 588 589 /** 590 * Flexible 24 bits per pixel YUV color format with 8-bit chroma and luma 591 * components. 592 * <p> 593 * Chroma planes are not subsampled. Use this format with {@link Image}. 594 * This format corresponds to {@link android.graphics.ImageFormat#YUV_444_888}, 595 * and can represent the {@link #COLOR_FormatYUV444Interleaved} format. 596 * @see Image#getFormat 597 */ 598 public static final int COLOR_FormatYUV444Flexible = 0x7F444888; 599 600 /** 601 * Flexible 24 bits per pixel RGB color format with 8-bit red, green and blue 602 * components. 603 * <p> 604 * Use this format with {@link Image}. This format corresponds to 605 * {@link android.graphics.ImageFormat#FLEX_RGB_888}, and can represent 606 * {@link #COLOR_Format24bitBGR888} and {@link #COLOR_Format24bitRGB888} formats. 607 * @see Image#getFormat() 608 */ 609 public static final int COLOR_FormatRGBFlexible = 0x7F36B888; 610 611 /** 612 * Flexible 32 bits per pixel RGBA color format with 8-bit red, green, blue, and alpha 613 * components. 614 * <p> 615 * Use this format with {@link Image}. This format corresponds to 616 * {@link android.graphics.ImageFormat#FLEX_RGBA_8888}, and can represent 617 * {@link #COLOR_Format32bitBGRA8888}, {@link #COLOR_Format32bitABGR8888} and 618 * {@link #COLOR_Format32bitARGB8888} formats. 619 * 620 * @see Image#getFormat() 621 */ 622 public static final int COLOR_FormatRGBAFlexible = 0x7F36A888; 623 624 /** @deprecated Use {@link #COLOR_FormatYUV420Flexible}. */ 625 public static final int COLOR_QCOM_FormatYUV420SemiPlanar = 0x7fa30c00; 626 627 /** 628 * The color format for the media. This is one of the color constants defined in this class. 629 */ 630 public int[] colorFormats; // NOTE this array is modifiable by user 631 632 // FEATURES 633 634 private int mFlagsSupported; 635 private int mFlagsRequired; 636 private int mFlagsVerified; 637 638 /** 639 * <b>video decoder only</b>: codec supports seamless resolution changes. 640 */ 641 public static final String FEATURE_AdaptivePlayback = "adaptive-playback"; 642 643 /** 644 * <b>video decoder only</b>: codec supports secure decryption. 645 */ 646 public static final String FEATURE_SecurePlayback = "secure-playback"; 647 648 /** 649 * <b>video or audio decoder only</b>: codec supports tunneled playback. 650 */ 651 public static final String FEATURE_TunneledPlayback = "tunneled-playback"; 652 653 /** 654 * If true, the timestamp of each output buffer is derived from the timestamp of the input 655 * buffer that produced the output. If false, the timestamp of each output buffer is 656 * derived from the timestamp of the first input buffer. 657 */ 658 public static final String FEATURE_DynamicTimestamp = "dynamic-timestamp"; 659 660 /** 661 * <b>decoder only</b>If true, the codec supports partial (including multiple) access units 662 * per input buffer. 663 */ 664 public static final String FEATURE_FrameParsing = "frame-parsing"; 665 666 /** 667 * If true, the codec supports multiple access units (for decoding, or to output for 668 * encoders). If false, the codec only supports single access units. Producing multiple 669 * access units for output is an optional feature. 670 */ 671 public static final String FEATURE_MultipleFrames = "multiple-frames"; 672 673 /** 674 * <b>video decoder only</b>: codec supports queuing partial frames. 675 */ 676 public static final String FEATURE_PartialFrame = "partial-frame"; 677 678 /** 679 * <b>video encoder only</b>: codec supports intra refresh. 680 */ 681 public static final String FEATURE_IntraRefresh = "intra-refresh"; 682 683 /** 684 * <b>decoder only</b>: codec supports low latency decoding. 685 * If supported, clients can enable the low latency mode for the decoder. 686 * When the mode is enabled, the decoder doesn't hold input and output data more than 687 * required by the codec standards. 688 */ 689 public static final String FEATURE_LowLatency = "low-latency"; 690 691 /** 692 * Do not include in REGULAR_CODECS list in MediaCodecList. 693 */ 694 private static final String FEATURE_SpecialCodec = "special-codec"; 695 696 /** 697 * <b>video encoder only</b>: codec supports quantization parameter bounds. 698 * @see MediaFormat#KEY_VIDEO_QP_MAX 699 * @see MediaFormat#KEY_VIDEO_QP_MIN 700 */ 701 @SuppressLint("AllUpper") 702 public static final String FEATURE_QpBounds = "qp-bounds"; 703 704 /** 705 * <b>video encoder only</b>: codec supports exporting encoding statistics. 706 * Encoders with this feature can provide the App clients with the encoding statistics 707 * information about the frame. 708 * The scope of encoding statistics is controlled by 709 * {@link MediaFormat#KEY_VIDEO_ENCODING_STATISTICS_LEVEL}. 710 * 711 * @see MediaFormat#KEY_VIDEO_ENCODING_STATISTICS_LEVEL 712 */ 713 @SuppressLint("AllUpper") // for consistency with other FEATURE_* constants 714 public static final String FEATURE_EncodingStatistics = "encoding-statistics"; 715 716 /** 717 * <b>video encoder only</b>: codec supports HDR editing. 718 * <p> 719 * HDR editing support means that the codec accepts 10-bit HDR 720 * input surface, and it is capable of generating any HDR 721 * metadata required from both YUV and RGB input when the 722 * metadata is not present. This feature is only meaningful when 723 * using an HDR capable profile (and 10-bit HDR input). 724 * <p> 725 * This feature implies that the codec is capable of encoding at 726 * least one HDR format, and that it supports RGBA_1010102 as 727 * well as P010, and optionally RGBA_FP16 input formats, and 728 * that the encoder can generate HDR metadata for all supported 729 * HDR input formats. 730 */ 731 @SuppressLint("AllUpper") 732 public static final String FEATURE_HdrEditing = "hdr-editing"; 733 734 /** 735 * <b>video encoder only</b>: codec supports HLG editing. 736 * <p> 737 * HLG editing support means that the codec accepts 10-bit HDR 738 * input surface in both YUV and RGB pixel format. This feature 739 * is only meaningful when using a 10-bit (HLG) profile and 740 * 10-bit input. 741 * <p> 742 * This feature implies that the codec is capable of encoding 743 * 10-bit format, and that it supports RGBA_1010102 as 744 * well as P010, and optionally RGBA_FP16 input formats. 745 * <p> 746 * The difference between this feature and {@link 747 * FEATURE_HdrEditing} is that HLG does not require the 748 * generation of HDR metadata and does not use an explicit HDR 749 * profile. 750 */ 751 @SuppressLint("AllUpper") 752 @FlaggedApi(FLAG_HLG_EDITING) 753 public static final String FEATURE_HlgEditing = "hlg-editing"; 754 755 /** 756 * <b>video decoder only</b>: codec supports dynamically 757 * changing color aspects. 758 * <p> 759 * If true, the codec can propagate color aspect changes during 760 * decoding. This is only meaningful at session boundaries, e.g. 761 * upon processing Picture Parameter Sets prior to a new IDR. 762 * The color aspects may come from the bitstream, or may be 763 * provided using {@link MediaCodec#setParameters} calls. 764 * <p> 765 * If the codec supports both 8-bit and 10-bit profiles, this 766 * feature means that the codec can dynamically switch between 8 767 * and 10-bit profiles, but this is restricted to Surface mode 768 * only. 769 * <p> 770 * If the device supports HDR transfer functions, switching 771 * between SDR and HDR transfer is also supported. Together with 772 * the previous clause this means that switching between SDR and 773 * HDR sessions are supported in Surface mode, as SDR is 774 * typically encoded at 8-bit and HDR at 10-bit. 775 */ 776 @SuppressLint("AllUpper") 777 @FlaggedApi(FLAG_DYNAMIC_COLOR_ASPECTS) 778 public static final String FEATURE_DynamicColorAspects = "dynamic-color-aspects"; 779 780 /** 781 * <b>video encoder only</b>: codec supports region of interest encoding. 782 * <p> 783 * RoI encoding support means the codec accepts information that specifies the relative 784 * importance of different portions of each video frame. This allows the encoder to 785 * separate a video frame into critical and non-critical regions, and use more bits 786 * (better quality) to represent the critical regions and de-prioritize non-critical 787 * regions. In other words, the encoder chooses a negative qp bias for the critical 788 * portions and a zero or positive qp bias for the non-critical portions. 789 * <p> 790 * At a basic level, if the encoder decides to encode each frame with a uniform 791 * quantization value 'qpFrame' and a 'qpBias' is chosen/suggested for an LCU of the 792 * frame, then the actual qp of the LCU will be 'qpFrame + qpBias', although this value 793 * can be clamped basing on the min-max configured qp bounds for the current encoding 794 * session. 795 * <p> 796 * In a shot, if a group of LCUs pan out quickly they can be marked as non-critical 797 * thereby enabling the encoder to reserve fewer bits during their encoding. Contrarily, 798 * LCUs that remain in shot for a prolonged duration can be encoded at better quality in 799 * one frame thereby setting-up an excellent long-term reference for all future frames. 800 * <p> 801 * Note that by offsetting the quantization of each LCU, the overall bit allocation will 802 * differ from the originally estimated bit allocation, and the encoder will adjust the 803 * frame quantization for subsequent frames to meet the bitrate target. An effective 804 * selection of critical regions can set-up a golden reference and this can compensate 805 * for the bit burden that was introduced due to encoding RoI's at better quality. 806 * On the other hand, an ineffective choice of critical regions might increase the 807 * quality of certain parts of the image but this can hamper quality in subsequent frames. 808 * <p> 809 * @see MediaCodec#PARAMETER_KEY_QP_OFFSET_MAP 810 * @see MediaCodec#PARAMETER_KEY_QP_OFFSET_RECTS 811 */ 812 @SuppressLint("AllUpper") 813 @FlaggedApi(FLAG_REGION_OF_INTEREST) 814 public static final String FEATURE_Roi = "region-of-interest"; 815 816 /** 817 * <b>video decoder only</b>: codec supports detaching the 818 * output surface when in Surface mode. 819 * <p> If true, the codec can be configured in Surface mode 820 * without an actual surface (in detached surface mode). 821 * @see MediaCodec#CONFIGURE_FLAG_DETACHED_SURFACE 822 */ 823 @SuppressLint("AllUpper") 824 @FlaggedApi(FLAG_NULL_OUTPUT_SURFACE) 825 public static final String FEATURE_DetachedSurface = "detached-surface"; 826 827 /** 828 * Query codec feature capabilities. 829 * <p> 830 * These features are supported to be used by the codec. These 831 * include optional features that can be turned on, as well as 832 * features that are always on. 833 */ isFeatureSupported(String name)834 public final boolean isFeatureSupported(String name) { 835 return checkFeature(name, mFlagsSupported); 836 } 837 838 /** 839 * Query codec feature requirements. 840 * <p> 841 * These features are required to be used by the codec, and as such, 842 * they are always turned on. 843 */ isFeatureRequired(String name)844 public final boolean isFeatureRequired(String name) { 845 return checkFeature(name, mFlagsRequired); 846 } 847 848 // Flags are used for feature list creation so separate this into a private 849 // static class to delay reading the flags only when constructing the list. 850 private static class FeatureList { getDecoderFeatures()851 private static Feature[] getDecoderFeatures() { 852 ArrayList<Feature> features = new ArrayList(); 853 features.add(new Feature(FEATURE_AdaptivePlayback, (1 << 0), true)); 854 features.add(new Feature(FEATURE_SecurePlayback, (1 << 1), false)); 855 features.add(new Feature(FEATURE_TunneledPlayback, (1 << 2), false)); 856 features.add(new Feature(FEATURE_PartialFrame, (1 << 3), false)); 857 features.add(new Feature(FEATURE_FrameParsing, (1 << 4), false)); 858 features.add(new Feature(FEATURE_MultipleFrames, (1 << 5), false)); 859 features.add(new Feature(FEATURE_DynamicTimestamp, (1 << 6), false)); 860 features.add(new Feature(FEATURE_LowLatency, (1 << 7), true)); 861 if (GetFlag(() -> android.media.codec.Flags.dynamicColorAspects())) { 862 features.add(new Feature(FEATURE_DynamicColorAspects, (1 << 8), true)); 863 } 864 if (GetFlag(() -> android.media.codec.Flags.nullOutputSurface())) { 865 features.add(new Feature(FEATURE_DetachedSurface, (1 << 9), true)); 866 } 867 868 // feature to exclude codec from REGULAR codec list 869 features.add(new Feature(FEATURE_SpecialCodec, (1 << 30), false, true)); 870 871 return features.toArray(new Feature[0]); 872 }; 873 874 private static Feature[] decoderFeatures = getDecoderFeatures(); 875 getEncoderFeatures()876 private static Feature[] getEncoderFeatures() { 877 ArrayList<Feature> features = new ArrayList(); 878 879 features.add(new Feature(FEATURE_IntraRefresh, (1 << 0), false)); 880 features.add(new Feature(FEATURE_MultipleFrames, (1 << 1), false)); 881 features.add(new Feature(FEATURE_DynamicTimestamp, (1 << 2), false)); 882 features.add(new Feature(FEATURE_QpBounds, (1 << 3), false)); 883 features.add(new Feature(FEATURE_EncodingStatistics, (1 << 4), false)); 884 features.add(new Feature(FEATURE_HdrEditing, (1 << 5), false)); 885 if (GetFlag(() -> android.media.codec.Flags.hlgEditing())) { 886 features.add(new Feature(FEATURE_HlgEditing, (1 << 6), true)); 887 } 888 if (GetFlag(() -> android.media.codec.Flags.regionOfInterest())) { 889 features.add(new Feature(FEATURE_Roi, (1 << 7), true)); 890 } 891 892 // feature to exclude codec from REGULAR codec list 893 features.add(new Feature(FEATURE_SpecialCodec, (1 << 30), false, true)); 894 895 return features.toArray(new Feature[0]); 896 }; 897 898 private static Feature[] encoderFeatures = getEncoderFeatures(); 899 getFeatures(boolean isEncoder)900 public static Feature[] getFeatures(boolean isEncoder) { 901 if (isEncoder) { 902 return encoderFeatures; 903 } else { 904 return decoderFeatures; 905 } 906 } 907 } 908 909 /** @hide */ validFeatures()910 public String[] validFeatures() { 911 Feature[] features = getValidFeatures(); 912 ArrayList<String> res = new ArrayList(); 913 for (int i = 0; i < features.length; i++) { 914 if (!features[i].mInternal) { 915 res.add(features[i].mName); 916 } 917 } 918 return res.toArray(new String[0]); 919 } 920 getValidFeatures()921 private Feature[] getValidFeatures() { 922 return FeatureList.getFeatures(isEncoder()); 923 } 924 checkFeature(String name, int flags)925 private boolean checkFeature(String name, int flags) { 926 for (Feature feat: getValidFeatures()) { 927 if (feat.mName.equals(name)) { 928 return (flags & feat.mValue) != 0; 929 } 930 } 931 return false; 932 } 933 934 /** @hide */ isRegular()935 public boolean isRegular() { 936 // regular codecs only require default features 937 for (Feature feat: getValidFeatures()) { 938 if (!feat.mDefault && isFeatureRequired(feat.mName)) { 939 return false; 940 } 941 } 942 return true; 943 } 944 945 /** 946 * Query whether codec supports a given {@link MediaFormat}. 947 * 948 * <p class=note> 949 * <strong>Note:</strong> On {@link android.os.Build.VERSION_CODES#LOLLIPOP}, 950 * {@code format} must not contain a {@linkplain MediaFormat#KEY_FRAME_RATE 951 * frame rate}. Use 952 * <code class=prettyprint>format.setString(MediaFormat.KEY_FRAME_RATE, null)</code> 953 * to clear any existing frame rate setting in the format. 954 * <p> 955 * 956 * The following table summarizes the format keys considered by this method. 957 * This is especially important to consider when targeting a higher SDK version than the 958 * minimum SDK version, as this method will disregard some keys on devices below the target 959 * SDK version. 960 * 961 * <table style="width: 0%"> 962 * <thead> 963 * <tr> 964 * <th rowspan=3>OS Version(s)</th> 965 * <td colspan=3>{@code MediaFormat} keys considered for</th> 966 * </tr><tr> 967 * <th>Audio Codecs</th> 968 * <th>Video Codecs</th> 969 * <th>Encoders</th> 970 * </tr> 971 * </thead> 972 * <tbody> 973 * <tr> 974 * <td>{@link android.os.Build.VERSION_CODES#LOLLIPOP}</td> 975 * <td rowspan=3>{@link MediaFormat#KEY_MIME}<sup>*</sup>,<br> 976 * {@link MediaFormat#KEY_SAMPLE_RATE},<br> 977 * {@link MediaFormat#KEY_CHANNEL_COUNT},</td> 978 * <td>{@link MediaFormat#KEY_MIME}<sup>*</sup>,<br> 979 * {@link CodecCapabilities#FEATURE_AdaptivePlayback}<sup>D</sup>,<br> 980 * {@link CodecCapabilities#FEATURE_SecurePlayback}<sup>D</sup>,<br> 981 * {@link CodecCapabilities#FEATURE_TunneledPlayback}<sup>D</sup>,<br> 982 * {@link MediaFormat#KEY_WIDTH},<br> 983 * {@link MediaFormat#KEY_HEIGHT},<br> 984 * <strong>no</strong> {@code KEY_FRAME_RATE}</td> 985 * <td rowspan=10>as to the left, plus<br> 986 * {@link MediaFormat#KEY_BITRATE_MODE},<br> 987 * {@link MediaFormat#KEY_PROFILE} 988 * (and/or {@link MediaFormat#KEY_AAC_PROFILE}<sup>~</sup>),<br> 989 * <!-- {link MediaFormat#KEY_QUALITY},<br> --> 990 * {@link MediaFormat#KEY_COMPLEXITY} 991 * (and/or {@link MediaFormat#KEY_FLAC_COMPRESSION_LEVEL}<sup>~</sup>)</td> 992 * </tr><tr> 993 * <td>{@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1}</td> 994 * <td rowspan=2>as above, plus<br> 995 * {@link MediaFormat#KEY_FRAME_RATE}</td> 996 * </tr><tr> 997 * <td>{@link android.os.Build.VERSION_CODES#M}</td> 998 * </tr><tr> 999 * <td>{@link android.os.Build.VERSION_CODES#N}</td> 1000 * <td rowspan=2>as above, plus<br> 1001 * {@link MediaFormat#KEY_PROFILE},<br> 1002 * <!-- {link MediaFormat#KEY_MAX_BIT_RATE},<br> --> 1003 * {@link MediaFormat#KEY_BIT_RATE}</td> 1004 * <td rowspan=2>as above, plus<br> 1005 * {@link MediaFormat#KEY_PROFILE},<br> 1006 * {@link MediaFormat#KEY_LEVEL}<sup>+</sup>,<br> 1007 * <!-- {link MediaFormat#KEY_MAX_BIT_RATE},<br> --> 1008 * {@link MediaFormat#KEY_BIT_RATE},<br> 1009 * {@link CodecCapabilities#FEATURE_IntraRefresh}<sup>E</sup></td> 1010 * </tr><tr> 1011 * <td>{@link android.os.Build.VERSION_CODES#N_MR1}</td> 1012 * </tr><tr> 1013 * <td>{@link android.os.Build.VERSION_CODES#O}</td> 1014 * <td rowspan=3 colspan=2>as above, plus<br> 1015 * {@link CodecCapabilities#FEATURE_PartialFrame}<sup>D</sup></td> 1016 * </tr><tr> 1017 * <td>{@link android.os.Build.VERSION_CODES#O_MR1}</td> 1018 * </tr><tr> 1019 * <td>{@link android.os.Build.VERSION_CODES#P}</td> 1020 * </tr><tr> 1021 * <td>{@link android.os.Build.VERSION_CODES#Q}</td> 1022 * <td colspan=2>as above, plus<br> 1023 * {@link CodecCapabilities#FEATURE_FrameParsing}<sup>D</sup>,<br> 1024 * {@link CodecCapabilities#FEATURE_MultipleFrames},<br> 1025 * {@link CodecCapabilities#FEATURE_DynamicTimestamp}</td> 1026 * </tr><tr> 1027 * <td>{@link android.os.Build.VERSION_CODES#R}</td> 1028 * <td colspan=2>as above, plus<br> 1029 * {@link CodecCapabilities#FEATURE_LowLatency}<sup>D</sup></td> 1030 * </tr> 1031 * <tr> 1032 * <td colspan=4> 1033 * <p class=note><strong>Notes:</strong><br> 1034 * *: must be specified; otherwise, method returns {@code false}.<br> 1035 * +: method does not verify that the format parameters are supported 1036 * by the specified level.<br> 1037 * D: decoders only<br> 1038 * E: encoders only<br> 1039 * ~: if both keys are provided values must match 1040 * </td> 1041 * </tr> 1042 * </tbody> 1043 * </table> 1044 * 1045 * @param format media format with optional feature directives. 1046 * @throws IllegalArgumentException if format is not a valid media format. 1047 * @return whether the codec capabilities support the given format 1048 * and feature requests. 1049 */ isFormatSupported(MediaFormat format)1050 public final boolean isFormatSupported(MediaFormat format) { 1051 final Map<String, Object> map = format.getMap(); 1052 final String mime = (String)map.get(MediaFormat.KEY_MIME); 1053 1054 // mime must match if present 1055 if (mime != null && !mMime.equalsIgnoreCase(mime)) { 1056 return false; 1057 } 1058 1059 // check feature support 1060 for (Feature feat: getValidFeatures()) { 1061 if (feat.mInternal) { 1062 continue; 1063 } 1064 1065 Integer yesNo = (Integer)map.get(MediaFormat.KEY_FEATURE_ + feat.mName); 1066 if (yesNo == null) { 1067 continue; 1068 } 1069 if ((yesNo == 1 && !isFeatureSupported(feat.mName)) || 1070 (yesNo == 0 && isFeatureRequired(feat.mName))) { 1071 return false; 1072 } 1073 } 1074 1075 Integer profile = (Integer)map.get(MediaFormat.KEY_PROFILE); 1076 Integer level = (Integer)map.get(MediaFormat.KEY_LEVEL); 1077 1078 if (profile != null) { 1079 if (!supportsProfileLevel(profile, level)) { 1080 return false; 1081 } 1082 1083 // If we recognize this profile, check that this format is supported by the 1084 // highest level supported by the codec for that profile. (Ignore specified 1085 // level beyond the above profile/level check as level is only used as a 1086 // guidance. E.g. AVC Level 1 CIF format is supported if codec supports level 1.1 1087 // even though max size for Level 1 is QCIF. However, MPEG2 Simple Profile 1088 // 1080p format is not supported even if codec supports Main Profile Level High, 1089 // as Simple Profile does not support 1080p. 1090 CodecCapabilities levelCaps = null; 1091 int maxLevel = 0; 1092 for (CodecProfileLevel pl : profileLevels) { 1093 if (pl.profile == profile && pl.level > maxLevel) { 1094 // H.263 levels are not completely ordered: 1095 // Level45 support only implies Level10 support 1096 if (!mMime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_H263) 1097 || pl.level != CodecProfileLevel.H263Level45 1098 || maxLevel == CodecProfileLevel.H263Level10) { 1099 maxLevel = pl.level; 1100 } 1101 } 1102 } 1103 levelCaps = createFromProfileLevel(mMime, profile, maxLevel); 1104 // We must remove the profile from this format otherwise levelCaps.isFormatSupported 1105 // will get into this same condition and loop forever. Furthermore, since levelCaps 1106 // does not contain features and bitrate specific keys, keep only keys relevant for 1107 // a level check. 1108 Map<String, Object> levelCriticalFormatMap = new HashMap<>(map); 1109 final Set<String> criticalKeys = 1110 isVideo() ? VideoCapabilities.VIDEO_LEVEL_CRITICAL_FORMAT_KEYS : 1111 isAudio() ? AudioCapabilities.AUDIO_LEVEL_CRITICAL_FORMAT_KEYS : 1112 null; 1113 1114 // critical keys will always contain KEY_MIME, but should also contain others to be 1115 // meaningful 1116 if (criticalKeys != null && criticalKeys.size() > 1 && levelCaps != null) { 1117 levelCriticalFormatMap.keySet().retainAll(criticalKeys); 1118 1119 MediaFormat levelCriticalFormat = new MediaFormat(levelCriticalFormatMap); 1120 if (!levelCaps.isFormatSupported(levelCriticalFormat)) { 1121 return false; 1122 } 1123 } 1124 } 1125 if (mAudioCaps != null && !mAudioCaps.supportsFormat(format)) { 1126 return false; 1127 } 1128 if (mVideoCaps != null && !mVideoCaps.supportsFormat(format)) { 1129 return false; 1130 } 1131 if (mEncoderCaps != null && !mEncoderCaps.supportsFormat(format)) { 1132 return false; 1133 } 1134 return true; 1135 } 1136 supportsBitrate( Range<Integer> bitrateRange, MediaFormat format)1137 private static boolean supportsBitrate( 1138 Range<Integer> bitrateRange, MediaFormat format) { 1139 Map<String, Object> map = format.getMap(); 1140 1141 // consider max bitrate over average bitrate for support 1142 Integer maxBitrate = (Integer)map.get(MediaFormat.KEY_MAX_BIT_RATE); 1143 Integer bitrate = (Integer)map.get(MediaFormat.KEY_BIT_RATE); 1144 if (bitrate == null) { 1145 bitrate = maxBitrate; 1146 } else if (maxBitrate != null) { 1147 bitrate = Math.max(bitrate, maxBitrate); 1148 } 1149 1150 if (bitrate != null && bitrate > 0) { 1151 return bitrateRange.contains(bitrate); 1152 } 1153 1154 return true; 1155 } 1156 supportsProfileLevel(int profile, Integer level)1157 private boolean supportsProfileLevel(int profile, Integer level) { 1158 for (CodecProfileLevel pl: profileLevels) { 1159 if (pl.profile != profile) { 1160 continue; 1161 } 1162 1163 // No specific level requested 1164 if (level == null) { 1165 return true; 1166 } 1167 1168 // AAC doesn't use levels 1169 if (mMime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AAC)) { 1170 return true; 1171 } 1172 1173 // DTS doesn't use levels 1174 if (mMime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_DTS) 1175 || mMime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_DTS_HD) 1176 || mMime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_DTS_UHD)) { 1177 return true; 1178 } 1179 1180 // H.263 levels are not completely ordered: 1181 // Level45 support only implies Level10 support 1182 if (mMime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_H263)) { 1183 if (pl.level != level && pl.level == CodecProfileLevel.H263Level45 1184 && level > CodecProfileLevel.H263Level10) { 1185 continue; 1186 } 1187 } 1188 1189 // MPEG4 levels are not completely ordered: 1190 // Level1 support only implies Level0 (and not Level0b) support 1191 if (mMime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_MPEG4)) { 1192 if (pl.level != level && pl.level == CodecProfileLevel.MPEG4Level1 1193 && level > CodecProfileLevel.MPEG4Level0) { 1194 continue; 1195 } 1196 } 1197 1198 // HEVC levels incorporate both tiers and levels. Verify tier support. 1199 if (mMime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_HEVC)) { 1200 boolean supportsHighTier = 1201 (pl.level & CodecProfileLevel.HEVCHighTierLevels) != 0; 1202 boolean checkingHighTier = (level & CodecProfileLevel.HEVCHighTierLevels) != 0; 1203 // high tier levels are only supported by other high tier levels 1204 if (checkingHighTier && !supportsHighTier) { 1205 continue; 1206 } 1207 } 1208 1209 if (pl.level >= level) { 1210 // if we recognize the listed profile/level, we must also recognize the 1211 // profile/level arguments. 1212 if (createFromProfileLevel(mMime, profile, pl.level) != null) { 1213 return createFromProfileLevel(mMime, profile, level) != null; 1214 } 1215 return true; 1216 } 1217 } 1218 return false; 1219 } 1220 1221 // errors while reading profile levels - accessed from sister capabilities 1222 int mError; 1223 1224 private static final String TAG = "CodecCapabilities"; 1225 1226 // NEW-STYLE CAPABILITIES 1227 // Capabilities for an audio codec. 1228 @Nullable 1229 private AudioCapabilities mAudioCaps; 1230 // Capabilities for a video codec. 1231 @Nullable 1232 private VideoCapabilities mVideoCaps; 1233 // Capabilities specific to an encoder (vs. a decoder). 1234 @Nullable 1235 private EncoderCapabilities mEncoderCaps; 1236 private MediaFormat mDefaultFormat; 1237 1238 /** 1239 * Returns a MediaFormat object with default values for configurations that have 1240 * defaults. 1241 */ getDefaultFormat()1242 public MediaFormat getDefaultFormat() { 1243 return mDefaultFormat; 1244 } 1245 1246 /** 1247 * Returns the mime type for which this codec-capability object was created. 1248 */ getMimeType()1249 public String getMimeType() { 1250 return mMime; 1251 } 1252 1253 /** 1254 * Returns the max number of the supported concurrent codec instances. 1255 * <p> 1256 * This is a hint for an upper bound. Applications should not expect to successfully 1257 * operate more instances than the returned value, but the actual number of 1258 * concurrently operable instances may be less as it depends on the available 1259 * resources at time of use. 1260 */ getMaxSupportedInstances()1261 public int getMaxSupportedInstances() { 1262 return mMaxSupportedInstances; 1263 } 1264 isAudio()1265 private boolean isAudio() { 1266 return mAudioCaps != null; 1267 } 1268 1269 /** 1270 * Returns the audio capabilities or {@code null} if this is not an audio codec. 1271 */ 1272 @Nullable getAudioCapabilities()1273 public AudioCapabilities getAudioCapabilities() { 1274 return mAudioCaps; 1275 } 1276 isEncoder()1277 private boolean isEncoder() { 1278 return mEncoderCaps != null; 1279 } 1280 1281 /** 1282 * Returns the encoding capabilities or {@code null} if this is not an encoder. 1283 */ 1284 @Nullable getEncoderCapabilities()1285 public EncoderCapabilities getEncoderCapabilities() { 1286 return mEncoderCaps; 1287 } 1288 isVideo()1289 private boolean isVideo() { 1290 return mVideoCaps != null; 1291 } 1292 1293 /** 1294 * Returns the video capabilities or {@code null} if this is not a video codec. 1295 */ 1296 @Nullable getVideoCapabilities()1297 public VideoCapabilities getVideoCapabilities() { 1298 return mVideoCaps; 1299 } 1300 1301 /** @hide */ dup()1302 public CodecCapabilities dup() { 1303 CodecCapabilities caps = new CodecCapabilities(); 1304 1305 // profileLevels and colorFormats may be modified by client. 1306 caps.profileLevels = Arrays.copyOf(profileLevels, profileLevels.length); 1307 caps.colorFormats = Arrays.copyOf(colorFormats, colorFormats.length); 1308 1309 caps.mMime = mMime; 1310 caps.mMaxSupportedInstances = mMaxSupportedInstances; 1311 caps.mFlagsRequired = mFlagsRequired; 1312 caps.mFlagsSupported = mFlagsSupported; 1313 caps.mFlagsVerified = mFlagsVerified; 1314 caps.mAudioCaps = mAudioCaps; 1315 caps.mVideoCaps = mVideoCaps; 1316 caps.mEncoderCaps = mEncoderCaps; 1317 caps.mDefaultFormat = mDefaultFormat; 1318 caps.mCapabilitiesInfo = mCapabilitiesInfo; 1319 1320 return caps; 1321 } 1322 1323 /** 1324 * Retrieve the codec capabilities for a certain {@code mime type}, {@code 1325 * profile} and {@code level}. If the type, or profile-level combination 1326 * is not understood by the framework, it returns null. 1327 * <p class=note> In {@link android.os.Build.VERSION_CODES#M}, calling this 1328 * method without calling any method of the {@link MediaCodecList} class beforehand 1329 * results in a {@link NullPointerException}.</p> 1330 */ createFromProfileLevel( String mime, int profile, int level)1331 public static CodecCapabilities createFromProfileLevel( 1332 String mime, int profile, int level) { 1333 CodecProfileLevel pl = new CodecProfileLevel(); 1334 pl.profile = profile; 1335 pl.level = level; 1336 MediaFormat defaultFormat = new MediaFormat(); 1337 defaultFormat.setString(MediaFormat.KEY_MIME, mime); 1338 1339 CodecCapabilities ret = new CodecCapabilities( 1340 new CodecProfileLevel[] { pl }, new int[0], true /* encoder */, 1341 defaultFormat, new MediaFormat() /* info */); 1342 if (ret.mError != 0) { 1343 return null; 1344 } 1345 return ret; 1346 } 1347 CodecCapabilities( CodecProfileLevel[] profLevs, int[] colFmts, boolean encoder, Map<String, Object>defaultFormatMap, Map<String, Object>capabilitiesMap)1348 /* package private */ CodecCapabilities( 1349 CodecProfileLevel[] profLevs, int[] colFmts, 1350 boolean encoder, 1351 Map<String, Object>defaultFormatMap, 1352 Map<String, Object>capabilitiesMap) { 1353 this(profLevs, colFmts, encoder, 1354 new MediaFormat(defaultFormatMap), 1355 new MediaFormat(capabilitiesMap)); 1356 } 1357 1358 private MediaFormat mCapabilitiesInfo; 1359 CodecCapabilities( CodecProfileLevel[] profLevs, int[] colFmts, boolean encoder, MediaFormat defaultFormat, MediaFormat info)1360 /* package private */ CodecCapabilities( 1361 CodecProfileLevel[] profLevs, int[] colFmts, boolean encoder, 1362 MediaFormat defaultFormat, MediaFormat info) { 1363 final Map<String, Object> map = info.getMap(); 1364 colorFormats = colFmts; 1365 mFlagsVerified = 0; // TODO: remove as it is unused 1366 mDefaultFormat = defaultFormat; 1367 mCapabilitiesInfo = info; 1368 mMime = mDefaultFormat.getString(MediaFormat.KEY_MIME); 1369 1370 /* VP9 introduced profiles around 2016, so some VP9 codecs may not advertise any 1371 supported profiles. Determine the level for them using the info they provide. */ 1372 if (profLevs.length == 0 && mMime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP9)) { 1373 CodecProfileLevel profLev = new CodecProfileLevel(); 1374 profLev.profile = CodecProfileLevel.VP9Profile0; 1375 profLev.level = VideoCapabilities.equivalentVP9Level(info); 1376 profLevs = new CodecProfileLevel[] { profLev }; 1377 } 1378 profileLevels = profLevs; 1379 1380 if (mMime.toLowerCase().startsWith("audio/")) { 1381 mAudioCaps = AudioCapabilities.create(info, this); 1382 mAudioCaps.getDefaultFormat(mDefaultFormat); 1383 } else if (mMime.toLowerCase().startsWith("video/") 1384 || mMime.equalsIgnoreCase(MediaFormat.MIMETYPE_IMAGE_ANDROID_HEIC)) { 1385 mVideoCaps = VideoCapabilities.create(info, this); 1386 } 1387 if (encoder) { 1388 mEncoderCaps = EncoderCapabilities.create(info, this); 1389 mEncoderCaps.getDefaultFormat(mDefaultFormat); 1390 } 1391 1392 final Map<String, Object> global = MediaCodecList.getGlobalSettings(); 1393 mMaxSupportedInstances = Utils.parseIntSafely( 1394 global.get("max-concurrent-instances"), DEFAULT_MAX_SUPPORTED_INSTANCES); 1395 1396 int maxInstances = Utils.parseIntSafely( 1397 map.get("max-concurrent-instances"), mMaxSupportedInstances); 1398 mMaxSupportedInstances = 1399 Range.create(1, MAX_SUPPORTED_INSTANCES_LIMIT).clamp(maxInstances); 1400 1401 for (Feature feat: getValidFeatures()) { 1402 String key = MediaFormat.KEY_FEATURE_ + feat.mName; 1403 Integer yesNo = (Integer)map.get(key); 1404 if (yesNo == null) { 1405 continue; 1406 } 1407 if (yesNo > 0) { 1408 mFlagsRequired |= feat.mValue; 1409 } 1410 mFlagsSupported |= feat.mValue; 1411 if (!feat.mInternal) { 1412 mDefaultFormat.setInteger(key, 1); 1413 } 1414 // TODO restrict features by mFlagsVerified once all codecs reliably verify them 1415 } 1416 } 1417 } 1418 1419 /** 1420 * A class that supports querying the audio capabilities of a codec. 1421 */ 1422 public static final class AudioCapabilities { 1423 private static final String TAG = "AudioCapabilities"; 1424 private CodecCapabilities mParent; 1425 private Range<Integer> mBitrateRange; 1426 1427 private int[] mSampleRates; 1428 private Range<Integer>[] mSampleRateRanges; 1429 private Range<Integer>[] mInputChannelRanges; 1430 1431 private static final int MAX_INPUT_CHANNEL_COUNT = 30; 1432 1433 /** 1434 * Returns the range of supported bitrates in bits/second. 1435 */ getBitrateRange()1436 public Range<Integer> getBitrateRange() { 1437 return mBitrateRange; 1438 } 1439 1440 /** 1441 * Returns the array of supported sample rates if the codec 1442 * supports only discrete values. Otherwise, it returns 1443 * {@code null}. The array is sorted in ascending order. 1444 */ getSupportedSampleRates()1445 public int[] getSupportedSampleRates() { 1446 return mSampleRates != null ? Arrays.copyOf(mSampleRates, mSampleRates.length) : null; 1447 } 1448 1449 /** 1450 * Returns the array of supported sample rate ranges. The 1451 * array is sorted in ascending order, and the ranges are 1452 * distinct. 1453 */ getSupportedSampleRateRanges()1454 public Range<Integer>[] getSupportedSampleRateRanges() { 1455 return Arrays.copyOf(mSampleRateRanges, mSampleRateRanges.length); 1456 } 1457 1458 /** 1459 * Returns the maximum number of input channels supported. 1460 * 1461 * Through {@link android.os.Build.VERSION_CODES#R}, this method indicated support 1462 * for any number of input channels between 1 and this maximum value. 1463 * 1464 * As of {@link android.os.Build.VERSION_CODES#S}, 1465 * the implied lower limit of 1 channel is no longer valid. 1466 * As of {@link android.os.Build.VERSION_CODES#S}, {@link #getMaxInputChannelCount} is 1467 * superseded by {@link #getInputChannelCountRanges}, 1468 * which returns an array of ranges of channels. 1469 * The {@link #getMaxInputChannelCount} method will return the highest value 1470 * in the ranges returned by {@link #getInputChannelCountRanges} 1471 * 1472 */ 1473 @IntRange(from = 1, to = 255) getMaxInputChannelCount()1474 public int getMaxInputChannelCount() { 1475 int overall_max = 0; 1476 for (int i = mInputChannelRanges.length - 1; i >= 0; i--) { 1477 int lmax = mInputChannelRanges[i].getUpper(); 1478 if (lmax > overall_max) { 1479 overall_max = lmax; 1480 } 1481 } 1482 return overall_max; 1483 } 1484 1485 /** 1486 * Returns the minimum number of input channels supported. 1487 * This is often 1, but does vary for certain mime types. 1488 * 1489 * This returns the lowest channel count in the ranges returned by 1490 * {@link #getInputChannelCountRanges}. 1491 */ 1492 @IntRange(from = 1, to = 255) getMinInputChannelCount()1493 public int getMinInputChannelCount() { 1494 int overall_min = MAX_INPUT_CHANNEL_COUNT; 1495 for (int i = mInputChannelRanges.length - 1; i >= 0; i--) { 1496 int lmin = mInputChannelRanges[i].getLower(); 1497 if (lmin < overall_min) { 1498 overall_min = lmin; 1499 } 1500 } 1501 return overall_min; 1502 } 1503 1504 /* 1505 * Returns an array of ranges representing the number of input channels supported. 1506 * The codec supports any number of input channels within this range. 1507 * 1508 * This supersedes the {@link #getMaxInputChannelCount} method. 1509 * 1510 * For many codecs, this will be a single range [1..N], for some N. 1511 */ 1512 @SuppressLint("ArrayReturn") 1513 @NonNull getInputChannelCountRanges()1514 public Range<Integer>[] getInputChannelCountRanges() { 1515 return Arrays.copyOf(mInputChannelRanges, mInputChannelRanges.length); 1516 } 1517 1518 /* no public constructor */ AudioCapabilities()1519 private AudioCapabilities() { } 1520 1521 /** @hide */ create( MediaFormat info, CodecCapabilities parent)1522 public static AudioCapabilities create( 1523 MediaFormat info, CodecCapabilities parent) { 1524 AudioCapabilities caps = new AudioCapabilities(); 1525 caps.init(info, parent); 1526 return caps; 1527 } 1528 init(MediaFormat info, CodecCapabilities parent)1529 private void init(MediaFormat info, CodecCapabilities parent) { 1530 mParent = parent; 1531 initWithPlatformLimits(); 1532 applyLevelLimits(); 1533 parseFromInfo(info); 1534 } 1535 initWithPlatformLimits()1536 private void initWithPlatformLimits() { 1537 mBitrateRange = Range.create(0, Integer.MAX_VALUE); 1538 mInputChannelRanges = new Range[] {Range.create(1, MAX_INPUT_CHANNEL_COUNT)}; 1539 // mBitrateRange = Range.create(1, 320000); 1540 final int minSampleRate = SystemProperties. 1541 getInt("ro.mediacodec.min_sample_rate", 7350); 1542 final int maxSampleRate = SystemProperties. 1543 getInt("ro.mediacodec.max_sample_rate", 192000); 1544 mSampleRateRanges = new Range[] { Range.create(minSampleRate, maxSampleRate) }; 1545 mSampleRates = null; 1546 } 1547 supports(Integer sampleRate, Integer inputChannels)1548 private boolean supports(Integer sampleRate, Integer inputChannels) { 1549 // channels and sample rates are checked orthogonally 1550 if (inputChannels != null) { 1551 int ix = Utils.binarySearchDistinctRanges( 1552 mInputChannelRanges, inputChannels); 1553 if (ix < 0) { 1554 return false; 1555 } 1556 } 1557 if (sampleRate != null) { 1558 int ix = Utils.binarySearchDistinctRanges( 1559 mSampleRateRanges, sampleRate); 1560 if (ix < 0) { 1561 return false; 1562 } 1563 } 1564 return true; 1565 } 1566 1567 /** 1568 * Query whether the sample rate is supported by the codec. 1569 */ isSampleRateSupported(int sampleRate)1570 public boolean isSampleRateSupported(int sampleRate) { 1571 return supports(sampleRate, null); 1572 } 1573 1574 /** modifies rates */ limitSampleRates(int[] rates)1575 private void limitSampleRates(int[] rates) { 1576 Arrays.sort(rates); 1577 ArrayList<Range<Integer>> ranges = new ArrayList<Range<Integer>>(); 1578 for (int rate: rates) { 1579 if (supports(rate, null /* channels */)) { 1580 ranges.add(Range.create(rate, rate)); 1581 } 1582 } 1583 mSampleRateRanges = ranges.toArray(new Range[ranges.size()]); 1584 createDiscreteSampleRates(); 1585 } 1586 createDiscreteSampleRates()1587 private void createDiscreteSampleRates() { 1588 mSampleRates = new int[mSampleRateRanges.length]; 1589 for (int i = 0; i < mSampleRateRanges.length; i++) { 1590 mSampleRates[i] = mSampleRateRanges[i].getLower(); 1591 } 1592 } 1593 1594 /** modifies rateRanges */ limitSampleRates(Range<Integer>[] rateRanges)1595 private void limitSampleRates(Range<Integer>[] rateRanges) { 1596 sortDistinctRanges(rateRanges); 1597 mSampleRateRanges = intersectSortedDistinctRanges(mSampleRateRanges, rateRanges); 1598 1599 // check if all values are discrete 1600 for (Range<Integer> range: mSampleRateRanges) { 1601 if (!range.getLower().equals(range.getUpper())) { 1602 mSampleRates = null; 1603 return; 1604 } 1605 } 1606 createDiscreteSampleRates(); 1607 } 1608 applyLevelLimits()1609 private void applyLevelLimits() { 1610 int[] sampleRates = null; 1611 Range<Integer> sampleRateRange = null, bitRates = null; 1612 int maxChannels = MAX_INPUT_CHANNEL_COUNT; 1613 CodecProfileLevel[] profileLevels = mParent.profileLevels; 1614 String mime = mParent.getMimeType(); 1615 1616 if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_MPEG)) { 1617 sampleRates = new int[] { 1618 8000, 11025, 12000, 1619 16000, 22050, 24000, 1620 32000, 44100, 48000 }; 1621 bitRates = Range.create(8000, 320000); 1622 maxChannels = 2; 1623 } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AMR_NB)) { 1624 sampleRates = new int[] { 8000 }; 1625 bitRates = Range.create(4750, 12200); 1626 maxChannels = 1; 1627 } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AMR_WB)) { 1628 sampleRates = new int[] { 16000 }; 1629 bitRates = Range.create(6600, 23850); 1630 maxChannels = 1; 1631 } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AAC)) { 1632 sampleRates = new int[] { 1633 7350, 8000, 1634 11025, 12000, 16000, 1635 22050, 24000, 32000, 1636 44100, 48000, 64000, 1637 88200, 96000 }; 1638 bitRates = Range.create(8000, 510000); 1639 maxChannels = 48; 1640 } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_VORBIS)) { 1641 bitRates = Range.create(32000, 500000); 1642 sampleRateRange = Range.create(8000, 192000); 1643 maxChannels = 255; 1644 } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_OPUS)) { 1645 bitRates = Range.create(6000, 510000); 1646 sampleRates = new int[] { 8000, 12000, 16000, 24000, 48000 }; 1647 maxChannels = 255; 1648 } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_RAW)) { 1649 sampleRateRange = Range.create(1, 192000); 1650 bitRates = Range.create(1, 10000000); 1651 maxChannels = AudioSystem.OUT_CHANNEL_COUNT_MAX; 1652 } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_FLAC)) { 1653 sampleRateRange = Range.create(1, 655350); 1654 // lossless codec, so bitrate is ignored 1655 maxChannels = 255; 1656 } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_G711_ALAW) 1657 || mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_G711_MLAW)) { 1658 sampleRates = new int[] { 8000 }; 1659 bitRates = Range.create(64000, 64000); 1660 // platform allows multiple channels for this format 1661 } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_MSGSM)) { 1662 sampleRates = new int[] { 8000 }; 1663 bitRates = Range.create(13000, 13000); 1664 maxChannels = 1; 1665 } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AC3)) { 1666 maxChannels = 6; 1667 } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_EAC3)) { 1668 maxChannels = 16; 1669 } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_EAC3_JOC)) { 1670 sampleRates = new int[] { 48000 }; 1671 bitRates = Range.create(32000, 6144000); 1672 maxChannels = 16; 1673 } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AC4)) { 1674 sampleRates = new int[] { 44100, 48000, 96000, 192000 }; 1675 bitRates = Range.create(16000, 2688000); 1676 maxChannels = 24; 1677 } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_DTS)) { 1678 sampleRates = new int[] { 44100, 48000 }; 1679 bitRates = Range.create(96000, 1524000); 1680 maxChannels = 6; 1681 } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_DTS_HD)) { 1682 for (CodecProfileLevel profileLevel: profileLevels) { 1683 switch (profileLevel.profile) { 1684 case CodecProfileLevel.DTS_HDProfileLBR: 1685 sampleRates = new int[]{ 22050, 24000, 44100, 48000 }; 1686 bitRates = Range.create(32000, 768000); 1687 break; 1688 case CodecProfileLevel.DTS_HDProfileHRA: 1689 case CodecProfileLevel.DTS_HDProfileMA: 1690 sampleRates = new int[]{ 44100, 48000, 88200, 96000, 176400, 192000 }; 1691 bitRates = Range.create(96000, 24500000); 1692 break; 1693 default: 1694 Log.w(TAG, "Unrecognized profile " 1695 + profileLevel.profile + " for " + mime); 1696 mParent.mError |= ERROR_UNRECOGNIZED; 1697 sampleRates = new int[]{ 44100, 48000, 88200, 96000, 176400, 192000 }; 1698 bitRates = Range.create(96000, 24500000); 1699 } 1700 } 1701 maxChannels = 8; 1702 } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_DTS_UHD)) { 1703 for (CodecProfileLevel profileLevel: profileLevels) { 1704 switch (profileLevel.profile) { 1705 case CodecProfileLevel.DTS_UHDProfileP2: 1706 sampleRates = new int[]{ 48000 }; 1707 bitRates = Range.create(96000, 768000); 1708 maxChannels = 10; 1709 break; 1710 case CodecProfileLevel.DTS_UHDProfileP1: 1711 sampleRates = new int[]{ 44100, 48000, 88200, 96000, 176400, 192000 }; 1712 bitRates = Range.create(96000, 24500000); 1713 maxChannels = 32; 1714 break; 1715 default: 1716 Log.w(TAG, "Unrecognized profile " 1717 + profileLevel.profile + " for " + mime); 1718 mParent.mError |= ERROR_UNRECOGNIZED; 1719 sampleRates = new int[]{ 44100, 48000, 88200, 96000, 176400, 192000 }; 1720 bitRates = Range.create(96000, 24500000); 1721 maxChannels = 32; 1722 } 1723 } 1724 } else { 1725 Log.w(TAG, "Unsupported mime " + mime); 1726 mParent.mError |= ERROR_UNSUPPORTED; 1727 } 1728 1729 // restrict ranges 1730 if (sampleRates != null) { 1731 limitSampleRates(sampleRates); 1732 } else if (sampleRateRange != null) { 1733 limitSampleRates(new Range[] { sampleRateRange }); 1734 } 1735 1736 Range<Integer> channelRange = Range.create(1, maxChannels); 1737 1738 applyLimits(new Range[] { channelRange }, bitRates); 1739 } 1740 applyLimits(Range<Integer>[] inputChannels, Range<Integer> bitRates)1741 private void applyLimits(Range<Integer>[] inputChannels, Range<Integer> bitRates) { 1742 1743 // clamp & make a local copy 1744 Range<Integer>[] myInputChannels = new Range[inputChannels.length]; 1745 for (int i = 0; i < inputChannels.length; i++) { 1746 int lower = inputChannels[i].clamp(1); 1747 int upper = inputChannels[i].clamp(MAX_INPUT_CHANNEL_COUNT); 1748 myInputChannels[i] = Range.create(lower, upper); 1749 } 1750 1751 // sort, intersect with existing, & save channel list 1752 sortDistinctRanges(myInputChannels); 1753 Range<Integer>[] joinedChannelList = 1754 intersectSortedDistinctRanges(myInputChannels, mInputChannelRanges); 1755 mInputChannelRanges = joinedChannelList; 1756 1757 if (bitRates != null) { 1758 mBitrateRange = mBitrateRange.intersect(bitRates); 1759 } 1760 } 1761 parseFromInfo(MediaFormat info)1762 private void parseFromInfo(MediaFormat info) { 1763 int maxInputChannels = MAX_INPUT_CHANNEL_COUNT; 1764 Range<Integer>[] channels = new Range[] { Range.create(1, maxInputChannels)}; 1765 Range<Integer> bitRates = POSITIVE_INTEGERS; 1766 1767 if (info.containsKey("sample-rate-ranges")) { 1768 String[] rateStrings = info.getString("sample-rate-ranges").split(","); 1769 Range<Integer>[] rateRanges = new Range[rateStrings.length]; 1770 for (int i = 0; i < rateStrings.length; i++) { 1771 rateRanges[i] = Utils.parseIntRange(rateStrings[i], null); 1772 } 1773 limitSampleRates(rateRanges); 1774 } 1775 1776 // we will prefer channel-ranges over max-channel-count 1777 if (info.containsKey("channel-ranges")) { 1778 String[] channelStrings = info.getString("channel-ranges").split(","); 1779 Range<Integer>[] channelRanges = new Range[channelStrings.length]; 1780 for (int i = 0; i < channelStrings.length; i++) { 1781 channelRanges[i] = Utils.parseIntRange(channelStrings[i], null); 1782 } 1783 channels = channelRanges; 1784 } else if (info.containsKey("channel-range")) { 1785 Range<Integer> oneRange = Utils.parseIntRange(info.getString("channel-range"), 1786 null); 1787 channels = new Range[] { oneRange }; 1788 } else if (info.containsKey("max-channel-count")) { 1789 maxInputChannels = Utils.parseIntSafely( 1790 info.getString("max-channel-count"), maxInputChannels); 1791 if (maxInputChannels == 0) { 1792 channels = new Range[] {Range.create(0, 0)}; 1793 } else { 1794 channels = new Range[] {Range.create(1, maxInputChannels)}; 1795 } 1796 } else if ((mParent.mError & ERROR_UNSUPPORTED) != 0) { 1797 maxInputChannels = 0; 1798 channels = new Range[] {Range.create(0, 0)}; 1799 } 1800 1801 if (info.containsKey("bitrate-range")) { 1802 bitRates = bitRates.intersect( 1803 Utils.parseIntRange(info.getString("bitrate-range"), bitRates)); 1804 } 1805 1806 applyLimits(channels, bitRates); 1807 } 1808 1809 /** @hide */ getDefaultFormat(MediaFormat format)1810 public void getDefaultFormat(MediaFormat format) { 1811 // report settings that have only a single choice 1812 if (mBitrateRange.getLower().equals(mBitrateRange.getUpper())) { 1813 format.setInteger(MediaFormat.KEY_BIT_RATE, mBitrateRange.getLower()); 1814 } 1815 if (getMaxInputChannelCount() == 1) { 1816 // mono-only format 1817 format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1); 1818 } 1819 if (mSampleRates != null && mSampleRates.length == 1) { 1820 format.setInteger(MediaFormat.KEY_SAMPLE_RATE, mSampleRates[0]); 1821 } 1822 } 1823 1824 /* package private */ 1825 // must not contain KEY_PROFILE 1826 static final Set<String> AUDIO_LEVEL_CRITICAL_FORMAT_KEYS = Set.of( 1827 // We don't set level-specific limits for audio codecs today. Key candidates would 1828 // be sample rate, bit rate or channel count. 1829 // MediaFormat.KEY_SAMPLE_RATE, 1830 // MediaFormat.KEY_CHANNEL_COUNT, 1831 // MediaFormat.KEY_BIT_RATE, 1832 MediaFormat.KEY_MIME); 1833 1834 /** @hide */ supportsFormat(MediaFormat format)1835 public boolean supportsFormat(MediaFormat format) { 1836 Map<String, Object> map = format.getMap(); 1837 Integer sampleRate = (Integer)map.get(MediaFormat.KEY_SAMPLE_RATE); 1838 Integer channels = (Integer)map.get(MediaFormat.KEY_CHANNEL_COUNT); 1839 1840 if (!supports(sampleRate, channels)) { 1841 return false; 1842 } 1843 1844 if (!CodecCapabilities.supportsBitrate(mBitrateRange, format)) { 1845 return false; 1846 } 1847 1848 // nothing to do for: 1849 // KEY_CHANNEL_MASK: codecs don't get this 1850 // KEY_IS_ADTS: required feature for all AAC decoders 1851 return true; 1852 } 1853 } 1854 1855 /** @hide */ 1856 @IntDef(prefix = {"SECURITY_MODEL_"}, value = { 1857 SECURITY_MODEL_SANDBOXED, 1858 SECURITY_MODEL_MEMORY_SAFE, 1859 SECURITY_MODEL_TRUSTED_CONTENT_ONLY, 1860 }) 1861 @Retention(RetentionPolicy.SOURCE) 1862 public @interface SecurityModel {} 1863 1864 /** 1865 * In this model the codec is running in a sandboxed process. Even if a 1866 * malicious content was fed to the codecs in this model, the impact will 1867 * be contained in the sandboxed process. 1868 */ 1869 @FlaggedApi(FLAG_IN_PROCESS_SW_AUDIO_CODEC) 1870 public static final int SECURITY_MODEL_SANDBOXED = 0; 1871 /** 1872 * In this model the codec is not running in a sandboxed process, but 1873 * written in a memory-safe way. It typically means that the software 1874 * implementation of the codec is written in a memory-safe language such 1875 * as Rust. 1876 */ 1877 @FlaggedApi(FLAG_IN_PROCESS_SW_AUDIO_CODEC) 1878 public static final int SECURITY_MODEL_MEMORY_SAFE = 1; 1879 /** 1880 * In this model the codec is suitable only for trusted content where 1881 * the input can be verified to be well-formed and no malicious actor 1882 * can alter it. For example, codecs in this model are not suitable 1883 * for arbitrary media downloaded from the internet or present in a user 1884 * directory. On the other hand, they could be suitable for media encoded 1885 * in the backend that the app developer wholly controls. 1886 * <p> 1887 * Codecs with this security model is not included in 1888 * {@link MediaCodecList#REGULAR_CODECS}, but included in 1889 * {@link MediaCodecList#ALL_CODECS}. 1890 * 1891 * @hide 1892 */ 1893 @FlaggedApi(FLAG_IN_PROCESS_SW_AUDIO_CODEC) 1894 public static final int SECURITY_MODEL_TRUSTED_CONTENT_ONLY = 2; 1895 1896 /** 1897 * Query the security model of the codec. 1898 */ 1899 @FlaggedApi(FLAG_IN_PROCESS_SW_AUDIO_CODEC) 1900 @SecurityModel getSecurityModel()1901 public int getSecurityModel() { 1902 // TODO b/297922713 --- detect security model of out-of-sandbox codecs 1903 return SECURITY_MODEL_SANDBOXED; 1904 } 1905 1906 /** 1907 * A class that supports querying the video capabilities of a codec. 1908 */ 1909 public static final class VideoCapabilities { 1910 private static final String TAG = "VideoCapabilities"; 1911 private CodecCapabilities mParent; 1912 private Range<Integer> mBitrateRange; 1913 1914 private Range<Integer> mHeightRange; 1915 private Range<Integer> mWidthRange; 1916 private Range<Integer> mBlockCountRange; 1917 private Range<Integer> mHorizontalBlockRange; 1918 private Range<Integer> mVerticalBlockRange; 1919 private Range<Rational> mAspectRatioRange; 1920 private Range<Rational> mBlockAspectRatioRange; 1921 private Range<Long> mBlocksPerSecondRange; 1922 private Map<Size, Range<Long>> mMeasuredFrameRates; 1923 private List<PerformancePoint> mPerformancePoints; 1924 private Range<Integer> mFrameRateRange; 1925 1926 private int mBlockWidth; 1927 private int mBlockHeight; 1928 private int mWidthAlignment; 1929 private int mHeightAlignment; 1930 private int mSmallerDimensionUpperLimit; 1931 1932 private boolean mAllowMbOverride; // allow XML to override calculated limits 1933 1934 /** 1935 * Returns the range of supported bitrates in bits/second. 1936 */ getBitrateRange()1937 public Range<Integer> getBitrateRange() { 1938 return mBitrateRange; 1939 } 1940 1941 /** 1942 * Returns the range of supported video widths. 1943 * <p class=note> 1944 * 32-bit processes will not support resolutions larger than 4096x4096 due to 1945 * the limited address space. 1946 */ getSupportedWidths()1947 public Range<Integer> getSupportedWidths() { 1948 return mWidthRange; 1949 } 1950 1951 /** 1952 * Returns the range of supported video heights. 1953 * <p class=note> 1954 * 32-bit processes will not support resolutions larger than 4096x4096 due to 1955 * the limited address space. 1956 */ getSupportedHeights()1957 public Range<Integer> getSupportedHeights() { 1958 return mHeightRange; 1959 } 1960 1961 /** 1962 * Returns the alignment requirement for video width (in pixels). 1963 * 1964 * This is a power-of-2 value that video width must be a 1965 * multiple of. 1966 */ getWidthAlignment()1967 public int getWidthAlignment() { 1968 return mWidthAlignment; 1969 } 1970 1971 /** 1972 * Returns the alignment requirement for video height (in pixels). 1973 * 1974 * This is a power-of-2 value that video height must be a 1975 * multiple of. 1976 */ getHeightAlignment()1977 public int getHeightAlignment() { 1978 return mHeightAlignment; 1979 } 1980 1981 /** 1982 * Return the upper limit on the smaller dimension of width or height. 1983 * <p></p> 1984 * Some codecs have a limit on the smaller dimension, whether it be 1985 * the width or the height. E.g. a codec may only be able to handle 1986 * up to 1920x1080 both in landscape and portrait mode (1080x1920). 1987 * In this case the maximum width and height are both 1920, but the 1988 * smaller dimension limit will be 1080. For other codecs, this is 1989 * {@code Math.min(getSupportedWidths().getUpper(), 1990 * getSupportedHeights().getUpper())}. 1991 * 1992 * @hide 1993 */ getSmallerDimensionUpperLimit()1994 public int getSmallerDimensionUpperLimit() { 1995 return mSmallerDimensionUpperLimit; 1996 } 1997 1998 /** 1999 * Returns the range of supported frame rates. 2000 * <p> 2001 * This is not a performance indicator. Rather, it expresses the 2002 * limits specified in the coding standard, based on the complexities 2003 * of encoding material for later playback at a certain frame rate, 2004 * or the decoding of such material in non-realtime. 2005 */ getSupportedFrameRates()2006 public Range<Integer> getSupportedFrameRates() { 2007 return mFrameRateRange; 2008 } 2009 2010 /** 2011 * Returns the range of supported video widths for a video height. 2012 * @param height the height of the video 2013 */ getSupportedWidthsFor(int height)2014 public Range<Integer> getSupportedWidthsFor(int height) { 2015 try { 2016 Range<Integer> range = mWidthRange; 2017 if (!mHeightRange.contains(height) 2018 || (height % mHeightAlignment) != 0) { 2019 throw new IllegalArgumentException("unsupported height"); 2020 } 2021 final int heightInBlocks = Utils.divUp(height, mBlockHeight); 2022 2023 // constrain by block count and by block aspect ratio 2024 final int minWidthInBlocks = Math.max( 2025 Utils.divUp(mBlockCountRange.getLower(), heightInBlocks), 2026 (int)Math.ceil(mBlockAspectRatioRange.getLower().doubleValue() 2027 * heightInBlocks)); 2028 final int maxWidthInBlocks = Math.min( 2029 mBlockCountRange.getUpper() / heightInBlocks, 2030 (int)(mBlockAspectRatioRange.getUpper().doubleValue() 2031 * heightInBlocks)); 2032 range = range.intersect( 2033 (minWidthInBlocks - 1) * mBlockWidth + mWidthAlignment, 2034 maxWidthInBlocks * mBlockWidth); 2035 2036 // constrain by smaller dimension limit 2037 if (height > mSmallerDimensionUpperLimit) { 2038 range = range.intersect(1, mSmallerDimensionUpperLimit); 2039 } 2040 2041 // constrain by aspect ratio 2042 range = range.intersect( 2043 (int)Math.ceil(mAspectRatioRange.getLower().doubleValue() 2044 * height), 2045 (int)(mAspectRatioRange.getUpper().doubleValue() * height)); 2046 return range; 2047 } catch (IllegalArgumentException e) { 2048 // height is not supported because there are no suitable widths 2049 Log.v(TAG, "could not get supported widths for " + height); 2050 throw new IllegalArgumentException("unsupported height"); 2051 } 2052 } 2053 2054 /** 2055 * Returns the range of supported video heights for a video width 2056 * @param width the width of the video 2057 */ getSupportedHeightsFor(int width)2058 public Range<Integer> getSupportedHeightsFor(int width) { 2059 try { 2060 Range<Integer> range = mHeightRange; 2061 if (!mWidthRange.contains(width) 2062 || (width % mWidthAlignment) != 0) { 2063 throw new IllegalArgumentException("unsupported width"); 2064 } 2065 final int widthInBlocks = Utils.divUp(width, mBlockWidth); 2066 2067 // constrain by block count and by block aspect ratio 2068 final int minHeightInBlocks = Math.max( 2069 Utils.divUp(mBlockCountRange.getLower(), widthInBlocks), 2070 (int)Math.ceil(widthInBlocks / 2071 mBlockAspectRatioRange.getUpper().doubleValue())); 2072 final int maxHeightInBlocks = Math.min( 2073 mBlockCountRange.getUpper() / widthInBlocks, 2074 (int)(widthInBlocks / 2075 mBlockAspectRatioRange.getLower().doubleValue())); 2076 range = range.intersect( 2077 (minHeightInBlocks - 1) * mBlockHeight + mHeightAlignment, 2078 maxHeightInBlocks * mBlockHeight); 2079 2080 // constrain by smaller dimension limit 2081 if (width > mSmallerDimensionUpperLimit) { 2082 range = range.intersect(1, mSmallerDimensionUpperLimit); 2083 } 2084 2085 // constrain by aspect ratio 2086 range = range.intersect( 2087 (int)Math.ceil(width / 2088 mAspectRatioRange.getUpper().doubleValue()), 2089 (int)(width / mAspectRatioRange.getLower().doubleValue())); 2090 return range; 2091 } catch (IllegalArgumentException e) { 2092 // width is not supported because there are no suitable heights 2093 Log.v(TAG, "could not get supported heights for " + width); 2094 throw new IllegalArgumentException("unsupported width"); 2095 } 2096 } 2097 2098 /** 2099 * Returns the range of supported video frame rates for a video size. 2100 * <p> 2101 * This is not a performance indicator. Rather, it expresses the limits specified in 2102 * the coding standard, based on the complexities of encoding material of a given 2103 * size for later playback at a certain frame rate, or the decoding of such material 2104 * in non-realtime. 2105 2106 * @param width the width of the video 2107 * @param height the height of the video 2108 */ getSupportedFrameRatesFor(int width, int height)2109 public Range<Double> getSupportedFrameRatesFor(int width, int height) { 2110 Range<Integer> range = mHeightRange; 2111 if (!supports(width, height, null)) { 2112 throw new IllegalArgumentException("unsupported size"); 2113 } 2114 final int blockCount = 2115 Utils.divUp(width, mBlockWidth) * Utils.divUp(height, mBlockHeight); 2116 2117 return Range.create( 2118 Math.max(mBlocksPerSecondRange.getLower() / (double) blockCount, 2119 (double) mFrameRateRange.getLower()), 2120 Math.min(mBlocksPerSecondRange.getUpper() / (double) blockCount, 2121 (double) mFrameRateRange.getUpper())); 2122 } 2123 getBlockCount(int width, int height)2124 private int getBlockCount(int width, int height) { 2125 return Utils.divUp(width, mBlockWidth) * Utils.divUp(height, mBlockHeight); 2126 } 2127 2128 @NonNull findClosestSize(int width, int height)2129 private Size findClosestSize(int width, int height) { 2130 int targetBlockCount = getBlockCount(width, height); 2131 Size closestSize = null; 2132 int minDiff = Integer.MAX_VALUE; 2133 for (Size size : mMeasuredFrameRates.keySet()) { 2134 int diff = Math.abs(targetBlockCount - 2135 getBlockCount(size.getWidth(), size.getHeight())); 2136 if (diff < minDiff) { 2137 minDiff = diff; 2138 closestSize = size; 2139 } 2140 } 2141 return closestSize; 2142 } 2143 estimateFrameRatesFor(int width, int height)2144 private Range<Double> estimateFrameRatesFor(int width, int height) { 2145 Size size = findClosestSize(width, height); 2146 Range<Long> range = mMeasuredFrameRates.get(size); 2147 Double ratio = getBlockCount(size.getWidth(), size.getHeight()) 2148 / (double)Math.max(getBlockCount(width, height), 1); 2149 return Range.create(range.getLower() * ratio, range.getUpper() * ratio); 2150 } 2151 2152 /** 2153 * Returns the range of achievable video frame rates for a video size. 2154 * May return {@code null}, if the codec did not publish any measurement 2155 * data. 2156 * <p> 2157 * This is a performance estimate provided by the device manufacturer based on statistical 2158 * sampling of full-speed decoding and encoding measurements in various configurations 2159 * of common video sizes supported by the codec. As such it should only be used to 2160 * compare individual codecs on the device. The value is not suitable for comparing 2161 * different devices or even different android releases for the same device. 2162 * <p> 2163 * <em>On {@link android.os.Build.VERSION_CODES#M} release</em> the returned range 2164 * corresponds to the fastest frame rates achieved in the tested configurations. As 2165 * such, it should not be used to gauge guaranteed or even average codec performance 2166 * on the device. 2167 * <p> 2168 * <em>On {@link android.os.Build.VERSION_CODES#N} release</em> the returned range 2169 * corresponds closer to sustained performance <em>in tested configurations</em>. 2170 * One can expect to achieve sustained performance higher than the lower limit more than 2171 * 50% of the time, and higher than half of the lower limit at least 90% of the time 2172 * <em>in tested configurations</em>. 2173 * Conversely, one can expect performance lower than twice the upper limit at least 2174 * 90% of the time. 2175 * <p class=note> 2176 * Tested configurations use a single active codec. For use cases where multiple 2177 * codecs are active, applications can expect lower and in most cases significantly lower 2178 * performance. 2179 * <p class=note> 2180 * The returned range value is interpolated from the nearest frame size(s) tested. 2181 * Codec performance is severely impacted by other activity on the device as well 2182 * as environmental factors (such as battery level, temperature or power source), and can 2183 * vary significantly even in a steady environment. 2184 * <p class=note> 2185 * Use this method in cases where only codec performance matters, e.g. to evaluate if 2186 * a codec has any chance of meeting a performance target. Codecs are listed 2187 * in {@link MediaCodecList} in the preferred order as defined by the device 2188 * manufacturer. As such, applications should use the first suitable codec in the 2189 * list to achieve the best balance between power use and performance. 2190 * 2191 * @param width the width of the video 2192 * @param height the height of the video 2193 * 2194 * @throws IllegalArgumentException if the video size is not supported. 2195 */ 2196 @Nullable getAchievableFrameRatesFor(int width, int height)2197 public Range<Double> getAchievableFrameRatesFor(int width, int height) { 2198 if (!supports(width, height, null)) { 2199 throw new IllegalArgumentException("unsupported size"); 2200 } 2201 2202 if (mMeasuredFrameRates == null || mMeasuredFrameRates.size() <= 0) { 2203 Log.w(TAG, "Codec did not publish any measurement data."); 2204 return null; 2205 } 2206 2207 return estimateFrameRatesFor(width, height); 2208 } 2209 2210 /** 2211 * Video performance points are a set of standard performance points defined by number of 2212 * pixels, pixel rate and frame rate. Performance point represents an upper bound. This 2213 * means that it covers all performance points with fewer pixels, pixel rate and frame 2214 * rate. 2215 */ 2216 public static final class PerformancePoint { 2217 private Size mBlockSize; // codec block size in macroblocks 2218 private int mWidth; // width in macroblocks 2219 private int mHeight; // height in macroblocks 2220 private int mMaxFrameRate; // max frames per second 2221 private long mMaxMacroBlockRate; // max macro block rate 2222 2223 /** 2224 * Maximum number of macroblocks in the frame. 2225 * 2226 * Video frames are conceptually divided into 16-by-16 pixel blocks called macroblocks. 2227 * Most coding standards operate on these 16-by-16 pixel blocks; thus, codec performance 2228 * is characterized using such blocks. 2229 * 2230 * @hide 2231 */ 2232 @TestApi getMaxMacroBlocks()2233 public int getMaxMacroBlocks() { 2234 return saturateLongToInt(mWidth * (long)mHeight); 2235 } 2236 2237 /** 2238 * Maximum frame rate in frames per second. 2239 * 2240 * @hide 2241 */ 2242 @TestApi getMaxFrameRate()2243 public int getMaxFrameRate() { 2244 return mMaxFrameRate; 2245 } 2246 2247 /** 2248 * Maximum number of macroblocks processed per second. 2249 * 2250 * @hide 2251 */ 2252 @TestApi getMaxMacroBlockRate()2253 public long getMaxMacroBlockRate() { 2254 return mMaxMacroBlockRate; 2255 } 2256 2257 /** Convert to a debug string */ toString()2258 public String toString() { 2259 int blockWidth = 16 * mBlockSize.getWidth(); 2260 int blockHeight = 16 * mBlockSize.getHeight(); 2261 int origRate = (int)Utils.divUp(mMaxMacroBlockRate, getMaxMacroBlocks()); 2262 String info = (mWidth * 16) + "x" + (mHeight * 16) + "@" + origRate; 2263 if (origRate < mMaxFrameRate) { 2264 info += ", max " + mMaxFrameRate + "fps"; 2265 } 2266 if (blockWidth > 16 || blockHeight > 16) { 2267 info += ", " + blockWidth + "x" + blockHeight + " blocks"; 2268 } 2269 return "PerformancePoint(" + info + ")"; 2270 } 2271 2272 @Override hashCode()2273 public int hashCode() { 2274 // only max frame rate must equal between performance points that equal to one 2275 // another 2276 return mMaxFrameRate; 2277 } 2278 2279 /** 2280 * Create a detailed performance point with custom max frame rate and macroblock size. 2281 * 2282 * @param width frame width in pixels 2283 * @param height frame height in pixels 2284 * @param frameRate frames per second for frame width and height 2285 * @param maxFrameRate maximum frames per second for any frame size 2286 * @param blockSize block size for codec implementation. Must be powers of two in both 2287 * width and height. 2288 * 2289 * @throws IllegalArgumentException if the blockSize dimensions are not powers of two. 2290 * 2291 * @hide 2292 */ 2293 @TestApi PerformancePoint( int width, int height, int frameRate, int maxFrameRate, @NonNull Size blockSize)2294 public PerformancePoint( 2295 int width, int height, int frameRate, int maxFrameRate, 2296 @NonNull Size blockSize) { 2297 checkPowerOfTwo(blockSize.getWidth(), "block width"); 2298 checkPowerOfTwo(blockSize.getHeight(), "block height"); 2299 2300 mBlockSize = new Size(Utils.divUp(blockSize.getWidth(), 16), 2301 Utils.divUp(blockSize.getHeight(), 16)); 2302 // these are guaranteed not to overflow as we decimate by 16 2303 mWidth = (int)(Utils.divUp(Math.max(1L, width), 2304 Math.max(blockSize.getWidth(), 16)) 2305 * mBlockSize.getWidth()); 2306 mHeight = (int)(Utils.divUp(Math.max(1L, height), 2307 Math.max(blockSize.getHeight(), 16)) 2308 * mBlockSize.getHeight()); 2309 mMaxFrameRate = Math.max(1, Math.max(frameRate, maxFrameRate)); 2310 mMaxMacroBlockRate = Math.max(1, frameRate) * getMaxMacroBlocks(); 2311 } 2312 2313 /** 2314 * Convert a performance point to a larger blocksize. 2315 * 2316 * @param pp performance point 2317 * @param blockSize block size for codec implementation 2318 * 2319 * @hide 2320 */ 2321 @TestApi PerformancePoint(@onNull PerformancePoint pp, @NonNull Size newBlockSize)2322 public PerformancePoint(@NonNull PerformancePoint pp, @NonNull Size newBlockSize) { 2323 this( 2324 pp.mWidth * 16, pp.mHeight * 16, 2325 // guaranteed not to overflow as these were multiplied at construction 2326 (int)Utils.divUp(pp.mMaxMacroBlockRate, pp.getMaxMacroBlocks()), 2327 pp.mMaxFrameRate, 2328 new Size(Math.max(newBlockSize.getWidth(), pp.mBlockSize.getWidth() * 16), 2329 Math.max(newBlockSize.getHeight(), pp.mBlockSize.getHeight() * 16)) 2330 ); 2331 } 2332 2333 /** 2334 * Create a performance point for a given frame size and frame rate. 2335 * 2336 * @param width width of the frame in pixels 2337 * @param height height of the frame in pixels 2338 * @param frameRate frame rate in frames per second 2339 */ PerformancePoint(int width, int height, int frameRate)2340 public PerformancePoint(int width, int height, int frameRate) { 2341 this(width, height, frameRate, frameRate /* maxFrameRate */, new Size(16, 16)); 2342 } 2343 2344 /** Saturates a long value to int */ saturateLongToInt(long value)2345 private int saturateLongToInt(long value) { 2346 if (value < Integer.MIN_VALUE) { 2347 return Integer.MIN_VALUE; 2348 } else if (value > Integer.MAX_VALUE) { 2349 return Integer.MAX_VALUE; 2350 } else { 2351 return (int)value; 2352 } 2353 } 2354 2355 /* This method may overflow */ align(int value, int alignment)2356 private int align(int value, int alignment) { 2357 return Utils.divUp(value, alignment) * alignment; 2358 } 2359 2360 /** Checks that value is a power of two. */ checkPowerOfTwo2(int value, @NonNull String description)2361 private void checkPowerOfTwo2(int value, @NonNull String description) { 2362 if (value == 0 || (value & (value - 1)) != 0) { 2363 throw new IllegalArgumentException( 2364 description + " (" + value + ") must be a power of 2"); 2365 } 2366 } 2367 2368 /** 2369 * Checks whether the performance point covers a media format. 2370 * 2371 * @param format Stream format considered 2372 * 2373 * @return {@code true} if the performance point covers the format. 2374 */ covers(@onNull MediaFormat format)2375 public boolean covers(@NonNull MediaFormat format) { 2376 PerformancePoint other = new PerformancePoint( 2377 format.getInteger(MediaFormat.KEY_WIDTH, 0), 2378 format.getInteger(MediaFormat.KEY_HEIGHT, 0), 2379 // safely convert ceil(double) to int through float cast and Math.round 2380 Math.round((float)( 2381 Math.ceil(format.getNumber(MediaFormat.KEY_FRAME_RATE, 0) 2382 .doubleValue())))); 2383 return covers(other); 2384 } 2385 2386 /** 2387 * Checks whether the performance point covers another performance point. Use this 2388 * method to determine if a performance point advertised by a codec covers the 2389 * performance point required. This method can also be used for loose ordering as this 2390 * method is transitive. 2391 * 2392 * @param other other performance point considered 2393 * 2394 * @return {@code true} if the performance point covers the other. 2395 */ covers(@onNull PerformancePoint other)2396 public boolean covers(@NonNull PerformancePoint other) { 2397 // convert performance points to common block size 2398 Size commonSize = getCommonBlockSize(other); 2399 PerformancePoint aligned = new PerformancePoint(this, commonSize); 2400 PerformancePoint otherAligned = new PerformancePoint(other, commonSize); 2401 2402 return (aligned.getMaxMacroBlocks() >= otherAligned.getMaxMacroBlocks() 2403 && aligned.mMaxFrameRate >= otherAligned.mMaxFrameRate 2404 && aligned.mMaxMacroBlockRate >= otherAligned.mMaxMacroBlockRate); 2405 } 2406 getCommonBlockSize(@onNull PerformancePoint other)2407 private @NonNull Size getCommonBlockSize(@NonNull PerformancePoint other) { 2408 return new Size( 2409 Math.max(mBlockSize.getWidth(), other.mBlockSize.getWidth()) * 16, 2410 Math.max(mBlockSize.getHeight(), other.mBlockSize.getHeight()) * 16); 2411 } 2412 2413 @Override equals(Object o)2414 public boolean equals(Object o) { 2415 if (o instanceof PerformancePoint) { 2416 // convert performance points to common block size 2417 PerformancePoint other = (PerformancePoint)o; 2418 Size commonSize = getCommonBlockSize(other); 2419 PerformancePoint aligned = new PerformancePoint(this, commonSize); 2420 PerformancePoint otherAligned = new PerformancePoint(other, commonSize); 2421 2422 return (aligned.getMaxMacroBlocks() == otherAligned.getMaxMacroBlocks() 2423 && aligned.mMaxFrameRate == otherAligned.mMaxFrameRate 2424 && aligned.mMaxMacroBlockRate == otherAligned.mMaxMacroBlockRate); 2425 } 2426 return false; 2427 } 2428 2429 /** 480p 24fps */ 2430 @NonNull 2431 public static final PerformancePoint SD_24 = new PerformancePoint(720, 480, 24); 2432 /** 576p 25fps */ 2433 @NonNull 2434 public static final PerformancePoint SD_25 = new PerformancePoint(720, 576, 25); 2435 /** 480p 30fps */ 2436 @NonNull 2437 public static final PerformancePoint SD_30 = new PerformancePoint(720, 480, 30); 2438 /** 480p 48fps */ 2439 @NonNull 2440 public static final PerformancePoint SD_48 = new PerformancePoint(720, 480, 48); 2441 /** 576p 50fps */ 2442 @NonNull 2443 public static final PerformancePoint SD_50 = new PerformancePoint(720, 576, 50); 2444 /** 480p 60fps */ 2445 @NonNull 2446 public static final PerformancePoint SD_60 = new PerformancePoint(720, 480, 60); 2447 2448 /** 720p 24fps */ 2449 @NonNull 2450 public static final PerformancePoint HD_24 = new PerformancePoint(1280, 720, 24); 2451 /** 720p 25fps */ 2452 @NonNull 2453 public static final PerformancePoint HD_25 = new PerformancePoint(1280, 720, 25); 2454 /** 720p 30fps */ 2455 @NonNull 2456 public static final PerformancePoint HD_30 = new PerformancePoint(1280, 720, 30); 2457 /** 720p 50fps */ 2458 @NonNull 2459 public static final PerformancePoint HD_50 = new PerformancePoint(1280, 720, 50); 2460 /** 720p 60fps */ 2461 @NonNull 2462 public static final PerformancePoint HD_60 = new PerformancePoint(1280, 720, 60); 2463 /** 720p 100fps */ 2464 @NonNull 2465 public static final PerformancePoint HD_100 = new PerformancePoint(1280, 720, 100); 2466 /** 720p 120fps */ 2467 @NonNull 2468 public static final PerformancePoint HD_120 = new PerformancePoint(1280, 720, 120); 2469 /** 720p 200fps */ 2470 @NonNull 2471 public static final PerformancePoint HD_200 = new PerformancePoint(1280, 720, 200); 2472 /** 720p 240fps */ 2473 @NonNull 2474 public static final PerformancePoint HD_240 = new PerformancePoint(1280, 720, 240); 2475 2476 /** 1080p 24fps */ 2477 @NonNull 2478 public static final PerformancePoint FHD_24 = new PerformancePoint(1920, 1080, 24); 2479 /** 1080p 25fps */ 2480 @NonNull 2481 public static final PerformancePoint FHD_25 = new PerformancePoint(1920, 1080, 25); 2482 /** 1080p 30fps */ 2483 @NonNull 2484 public static final PerformancePoint FHD_30 = new PerformancePoint(1920, 1080, 30); 2485 /** 1080p 50fps */ 2486 @NonNull 2487 public static final PerformancePoint FHD_50 = new PerformancePoint(1920, 1080, 50); 2488 /** 1080p 60fps */ 2489 @NonNull 2490 public static final PerformancePoint FHD_60 = new PerformancePoint(1920, 1080, 60); 2491 /** 1080p 100fps */ 2492 @NonNull 2493 public static final PerformancePoint FHD_100 = new PerformancePoint(1920, 1080, 100); 2494 /** 1080p 120fps */ 2495 @NonNull 2496 public static final PerformancePoint FHD_120 = new PerformancePoint(1920, 1080, 120); 2497 /** 1080p 200fps */ 2498 @NonNull 2499 public static final PerformancePoint FHD_200 = new PerformancePoint(1920, 1080, 200); 2500 /** 1080p 240fps */ 2501 @NonNull 2502 public static final PerformancePoint FHD_240 = new PerformancePoint(1920, 1080, 240); 2503 2504 /** 2160p 24fps */ 2505 @NonNull 2506 public static final PerformancePoint UHD_24 = new PerformancePoint(3840, 2160, 24); 2507 /** 2160p 25fps */ 2508 @NonNull 2509 public static final PerformancePoint UHD_25 = new PerformancePoint(3840, 2160, 25); 2510 /** 2160p 30fps */ 2511 @NonNull 2512 public static final PerformancePoint UHD_30 = new PerformancePoint(3840, 2160, 30); 2513 /** 2160p 50fps */ 2514 @NonNull 2515 public static final PerformancePoint UHD_50 = new PerformancePoint(3840, 2160, 50); 2516 /** 2160p 60fps */ 2517 @NonNull 2518 public static final PerformancePoint UHD_60 = new PerformancePoint(3840, 2160, 60); 2519 /** 2160p 100fps */ 2520 @NonNull 2521 public static final PerformancePoint UHD_100 = new PerformancePoint(3840, 2160, 100); 2522 /** 2160p 120fps */ 2523 @NonNull 2524 public static final PerformancePoint UHD_120 = new PerformancePoint(3840, 2160, 120); 2525 /** 2160p 200fps */ 2526 @NonNull 2527 public static final PerformancePoint UHD_200 = new PerformancePoint(3840, 2160, 200); 2528 /** 2160p 240fps */ 2529 @NonNull 2530 public static final PerformancePoint UHD_240 = new PerformancePoint(3840, 2160, 240); 2531 } 2532 2533 /** 2534 * Returns the supported performance points. May return {@code null} if the codec did not 2535 * publish any performance point information (e.g. the vendor codecs have not been updated 2536 * to the latest android release). May return an empty list if the codec published that 2537 * if does not guarantee any performance points. 2538 * <p> 2539 * This is a performance guarantee provided by the device manufacturer for hardware codecs 2540 * based on hardware capabilities of the device. 2541 * <p> 2542 * The returned list is sorted first by decreasing number of pixels, then by decreasing 2543 * width, and finally by decreasing frame rate. 2544 * Performance points assume a single active codec. For use cases where multiple 2545 * codecs are active, should use that highest pixel count, and add the frame rates of 2546 * each individual codec. 2547 * <p class=note> 2548 * 32-bit processes will not support resolutions larger than 4096x4096 due to 2549 * the limited address space, but performance points will be presented as is. 2550 * In other words, even though a component publishes a performance point for 2551 * a resolution higher than 4096x4096, it does not mean that the resolution is supported 2552 * for 32-bit processes. 2553 */ 2554 @Nullable getSupportedPerformancePoints()2555 public List<PerformancePoint> getSupportedPerformancePoints() { 2556 return mPerformancePoints; 2557 } 2558 2559 /** 2560 * Returns whether a given video size ({@code width} and 2561 * {@code height}) and {@code frameRate} combination is supported. 2562 */ areSizeAndRateSupported( int width, int height, double frameRate)2563 public boolean areSizeAndRateSupported( 2564 int width, int height, double frameRate) { 2565 return supports(width, height, frameRate); 2566 } 2567 2568 /** 2569 * Returns whether a given video size ({@code width} and 2570 * {@code height}) is supported. 2571 */ isSizeSupported(int width, int height)2572 public boolean isSizeSupported(int width, int height) { 2573 return supports(width, height, null); 2574 } 2575 supports(Integer width, Integer height, Number rate)2576 private boolean supports(Integer width, Integer height, Number rate) { 2577 boolean ok = true; 2578 2579 if (ok && width != null) { 2580 ok = mWidthRange.contains(width) 2581 && (width % mWidthAlignment == 0); 2582 } 2583 if (ok && height != null) { 2584 ok = mHeightRange.contains(height) 2585 && (height % mHeightAlignment == 0); 2586 } 2587 if (ok && rate != null) { 2588 ok = mFrameRateRange.contains(Utils.intRangeFor(rate.doubleValue())); 2589 } 2590 if (ok && height != null && width != null) { 2591 ok = Math.min(height, width) <= mSmallerDimensionUpperLimit; 2592 2593 final int widthInBlocks = Utils.divUp(width, mBlockWidth); 2594 final int heightInBlocks = Utils.divUp(height, mBlockHeight); 2595 final int blockCount = widthInBlocks * heightInBlocks; 2596 ok = ok && mBlockCountRange.contains(blockCount) 2597 && mBlockAspectRatioRange.contains( 2598 new Rational(widthInBlocks, heightInBlocks)) 2599 && mAspectRatioRange.contains(new Rational(width, height)); 2600 if (ok && rate != null) { 2601 double blocksPerSec = blockCount * rate.doubleValue(); 2602 ok = mBlocksPerSecondRange.contains( 2603 Utils.longRangeFor(blocksPerSec)); 2604 } 2605 } 2606 return ok; 2607 } 2608 2609 /* package private */ 2610 // must not contain KEY_PROFILE 2611 static final Set<String> VIDEO_LEVEL_CRITICAL_FORMAT_KEYS = Set.of( 2612 MediaFormat.KEY_WIDTH, 2613 MediaFormat.KEY_HEIGHT, 2614 MediaFormat.KEY_FRAME_RATE, 2615 MediaFormat.KEY_BIT_RATE, 2616 MediaFormat.KEY_MIME); 2617 2618 /** 2619 * @hide 2620 * @throws java.lang.ClassCastException */ supportsFormat(MediaFormat format)2621 public boolean supportsFormat(MediaFormat format) { 2622 final Map<String, Object> map = format.getMap(); 2623 Integer width = (Integer)map.get(MediaFormat.KEY_WIDTH); 2624 Integer height = (Integer)map.get(MediaFormat.KEY_HEIGHT); 2625 Number rate = (Number)map.get(MediaFormat.KEY_FRAME_RATE); 2626 2627 if (!supports(width, height, rate)) { 2628 return false; 2629 } 2630 2631 if (!CodecCapabilities.supportsBitrate(mBitrateRange, format)) { 2632 return false; 2633 } 2634 2635 // we ignore color-format for now as it is not reliably reported by codec 2636 return true; 2637 } 2638 2639 /* no public constructor */ VideoCapabilities()2640 private VideoCapabilities() { } 2641 2642 /** @hide */ 2643 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) create( MediaFormat info, CodecCapabilities parent)2644 public static VideoCapabilities create( 2645 MediaFormat info, CodecCapabilities parent) { 2646 VideoCapabilities caps = new VideoCapabilities(); 2647 caps.init(info, parent); 2648 return caps; 2649 } 2650 init(MediaFormat info, CodecCapabilities parent)2651 private void init(MediaFormat info, CodecCapabilities parent) { 2652 mParent = parent; 2653 initWithPlatformLimits(); 2654 applyLevelLimits(); 2655 parseFromInfo(info); 2656 updateLimits(); 2657 } 2658 2659 /** @hide */ getBlockSize()2660 public Size getBlockSize() { 2661 return new Size(mBlockWidth, mBlockHeight); 2662 } 2663 2664 /** @hide */ getBlockCountRange()2665 public Range<Integer> getBlockCountRange() { 2666 return mBlockCountRange; 2667 } 2668 2669 /** @hide */ getBlocksPerSecondRange()2670 public Range<Long> getBlocksPerSecondRange() { 2671 return mBlocksPerSecondRange; 2672 } 2673 2674 /** @hide */ getAspectRatioRange(boolean blocks)2675 public Range<Rational> getAspectRatioRange(boolean blocks) { 2676 return blocks ? mBlockAspectRatioRange : mAspectRatioRange; 2677 } 2678 initWithPlatformLimits()2679 private void initWithPlatformLimits() { 2680 mBitrateRange = BITRATE_RANGE; 2681 2682 mWidthRange = getSizeRange(); 2683 mHeightRange = getSizeRange(); 2684 mFrameRateRange = FRAME_RATE_RANGE; 2685 2686 mHorizontalBlockRange = getSizeRange(); 2687 mVerticalBlockRange = getSizeRange(); 2688 2689 // full positive ranges are supported as these get calculated 2690 mBlockCountRange = POSITIVE_INTEGERS; 2691 mBlocksPerSecondRange = POSITIVE_LONGS; 2692 2693 mBlockAspectRatioRange = POSITIVE_RATIONALS; 2694 mAspectRatioRange = POSITIVE_RATIONALS; 2695 2696 mWidthAlignment = 1; 2697 mHeightAlignment = 1; 2698 mBlockWidth = 1; 2699 mBlockHeight = 1; 2700 mSmallerDimensionUpperLimit = getSizeRange().getUpper(); 2701 } 2702 getPerformancePoints(Map<String, Object> map)2703 private @Nullable List<PerformancePoint> getPerformancePoints(Map<String, Object> map) { 2704 Vector<PerformancePoint> ret = new Vector<>(); 2705 final String prefix = "performance-point-"; 2706 Set<String> keys = map.keySet(); 2707 for (String key : keys) { 2708 // looking for: performance-point-WIDTHxHEIGHT-range 2709 if (!key.startsWith(prefix)) { 2710 continue; 2711 } 2712 String subKey = key.substring(prefix.length()); 2713 if (subKey.equals("none") && ret.size() == 0) { 2714 // This means that component knowingly did not publish performance points. 2715 // This is different from when the component forgot to publish performance 2716 // points. 2717 return Collections.unmodifiableList(ret); 2718 } 2719 String[] temp = key.split("-"); 2720 if (temp.length != 4) { 2721 continue; 2722 } 2723 String sizeStr = temp[2]; 2724 Size size = Utils.parseSize(sizeStr, null); 2725 if (size == null || size.getWidth() * size.getHeight() <= 0) { 2726 continue; 2727 } 2728 Range<Long> range = Utils.parseLongRange(map.get(key), null); 2729 if (range == null || range.getLower() < 0 || range.getUpper() < 0) { 2730 continue; 2731 } 2732 PerformancePoint given = new PerformancePoint( 2733 size.getWidth(), size.getHeight(), range.getLower().intValue(), 2734 range.getUpper().intValue(), new Size(mBlockWidth, mBlockHeight)); 2735 PerformancePoint rotated = new PerformancePoint( 2736 size.getHeight(), size.getWidth(), range.getLower().intValue(), 2737 range.getUpper().intValue(), new Size(mBlockWidth, mBlockHeight)); 2738 ret.add(given); 2739 if (!given.covers(rotated)) { 2740 ret.add(rotated); 2741 } 2742 } 2743 2744 // check if the component specified no performance point indication 2745 if (ret.size() == 0) { 2746 return null; 2747 } 2748 2749 // sort reversed by area first, then by frame rate 2750 ret.sort((a, b) -> 2751 -((a.getMaxMacroBlocks() != b.getMaxMacroBlocks()) ? 2752 (a.getMaxMacroBlocks() < b.getMaxMacroBlocks() ? -1 : 1) : 2753 (a.getMaxMacroBlockRate() != b.getMaxMacroBlockRate()) ? 2754 (a.getMaxMacroBlockRate() < b.getMaxMacroBlockRate() ? -1 : 1) : 2755 (a.getMaxFrameRate() != b.getMaxFrameRate()) ? 2756 (a.getMaxFrameRate() < b.getMaxFrameRate() ? -1 : 1) : 0)); 2757 2758 return Collections.unmodifiableList(ret); 2759 } 2760 2761 private Map<Size, Range<Long>> getMeasuredFrameRates(Map<String, Object> map) { 2762 Map<Size, Range<Long>> ret = new HashMap<Size, Range<Long>>(); 2763 final String prefix = "measured-frame-rate-"; 2764 Set<String> keys = map.keySet(); 2765 for (String key : keys) { 2766 // looking for: measured-frame-rate-WIDTHxHEIGHT-range 2767 if (!key.startsWith(prefix)) { 2768 continue; 2769 } 2770 String subKey = key.substring(prefix.length()); 2771 String[] temp = key.split("-"); 2772 if (temp.length != 5) { 2773 continue; 2774 } 2775 String sizeStr = temp[3]; 2776 Size size = Utils.parseSize(sizeStr, null); 2777 if (size == null || size.getWidth() * size.getHeight() <= 0) { 2778 continue; 2779 } 2780 Range<Long> range = Utils.parseLongRange(map.get(key), null); 2781 if (range == null || range.getLower() < 0 || range.getUpper() < 0) { 2782 continue; 2783 } 2784 ret.put(size, range); 2785 } 2786 return ret; 2787 } 2788 2789 private static Pair<Range<Integer>, Range<Integer>> parseWidthHeightRanges(Object o) { 2790 Pair<Size, Size> range = Utils.parseSizeRange(o); 2791 if (range != null) { 2792 try { 2793 return Pair.create( 2794 Range.create(range.first.getWidth(), range.second.getWidth()), 2795 Range.create(range.first.getHeight(), range.second.getHeight())); 2796 } catch (IllegalArgumentException e) { 2797 Log.w(TAG, "could not parse size range '" + o + "'"); 2798 } 2799 } 2800 return null; 2801 } 2802 2803 /** @hide */ 2804 public static int equivalentVP9Level(MediaFormat info) { 2805 final Map<String, Object> map = info.getMap(); 2806 2807 Size blockSize = Utils.parseSize(map.get("block-size"), new Size(8, 8)); 2808 int BS = blockSize.getWidth() * blockSize.getHeight(); 2809 2810 Range<Integer> counts = Utils.parseIntRange(map.get("block-count-range"), null); 2811 int FS = counts == null ? 0 : BS * counts.getUpper(); 2812 2813 Range<Long> blockRates = 2814 Utils.parseLongRange(map.get("blocks-per-second-range"), null); 2815 long SR = blockRates == null ? 0 : BS * blockRates.getUpper(); 2816 2817 Pair<Range<Integer>, Range<Integer>> dimensionRanges = 2818 parseWidthHeightRanges(map.get("size-range")); 2819 int D = dimensionRanges == null ? 0 : Math.max( 2820 dimensionRanges.first.getUpper(), dimensionRanges.second.getUpper()); 2821 2822 Range<Integer> bitRates = Utils.parseIntRange(map.get("bitrate-range"), null); 2823 int BR = bitRates == null ? 0 : Utils.divUp(bitRates.getUpper(), 1000); 2824 2825 if (SR <= 829440 && FS <= 36864 && BR <= 200 && D <= 512) 2826 return CodecProfileLevel.VP9Level1; 2827 if (SR <= 2764800 && FS <= 73728 && BR <= 800 && D <= 768) 2828 return CodecProfileLevel.VP9Level11; 2829 if (SR <= 4608000 && FS <= 122880 && BR <= 1800 && D <= 960) 2830 return CodecProfileLevel.VP9Level2; 2831 if (SR <= 9216000 && FS <= 245760 && BR <= 3600 && D <= 1344) 2832 return CodecProfileLevel.VP9Level21; 2833 if (SR <= 20736000 && FS <= 552960 && BR <= 7200 && D <= 2048) 2834 return CodecProfileLevel.VP9Level3; 2835 if (SR <= 36864000 && FS <= 983040 && BR <= 12000 && D <= 2752) 2836 return CodecProfileLevel.VP9Level31; 2837 if (SR <= 83558400 && FS <= 2228224 && BR <= 18000 && D <= 4160) 2838 return CodecProfileLevel.VP9Level4; 2839 if (SR <= 160432128 && FS <= 2228224 && BR <= 30000 && D <= 4160) 2840 return CodecProfileLevel.VP9Level41; 2841 if (SR <= 311951360 && FS <= 8912896 && BR <= 60000 && D <= 8384) 2842 return CodecProfileLevel.VP9Level5; 2843 if (SR <= 588251136 && FS <= 8912896 && BR <= 120000 && D <= 8384) 2844 return CodecProfileLevel.VP9Level51; 2845 if (SR <= 1176502272 && FS <= 8912896 && BR <= 180000 && D <= 8384) 2846 return CodecProfileLevel.VP9Level52; 2847 if (SR <= 1176502272 && FS <= 35651584 && BR <= 180000 && D <= 16832) 2848 return CodecProfileLevel.VP9Level6; 2849 if (SR <= 2353004544L && FS <= 35651584 && BR <= 240000 && D <= 16832) 2850 return CodecProfileLevel.VP9Level61; 2851 if (SR <= 4706009088L && FS <= 35651584 && BR <= 480000 && D <= 16832) 2852 return CodecProfileLevel.VP9Level62; 2853 // returning largest level 2854 return CodecProfileLevel.VP9Level62; 2855 } 2856 2857 private void parseFromInfo(MediaFormat info) { 2858 final Map<String, Object> map = info.getMap(); 2859 Size blockSize = new Size(mBlockWidth, mBlockHeight); 2860 Size alignment = new Size(mWidthAlignment, mHeightAlignment); 2861 Range<Integer> counts = null, widths = null, heights = null; 2862 Range<Integer> frameRates = null, bitRates = null; 2863 Range<Long> blockRates = null; 2864 Range<Rational> ratios = null, blockRatios = null; 2865 2866 blockSize = Utils.parseSize(map.get("block-size"), blockSize); 2867 alignment = Utils.parseSize(map.get("alignment"), alignment); 2868 counts = Utils.parseIntRange(map.get("block-count-range"), null); 2869 blockRates = 2870 Utils.parseLongRange(map.get("blocks-per-second-range"), null); 2871 mMeasuredFrameRates = getMeasuredFrameRates(map); 2872 mPerformancePoints = getPerformancePoints(map); 2873 Pair<Range<Integer>, Range<Integer>> sizeRanges = 2874 parseWidthHeightRanges(map.get("size-range")); 2875 if (sizeRanges != null) { 2876 widths = sizeRanges.first; 2877 heights = sizeRanges.second; 2878 } 2879 // for now this just means using the smaller max size as 2nd 2880 // upper limit. 2881 // for now we are keeping the profile specific "width/height 2882 // in macroblocks" limits. 2883 if (map.containsKey("feature-can-swap-width-height")) { 2884 if (widths != null) { 2885 mSmallerDimensionUpperLimit = 2886 Math.min(widths.getUpper(), heights.getUpper()); 2887 widths = heights = widths.extend(heights); 2888 } else { 2889 Log.w(TAG, "feature can-swap-width-height is best used with size-range"); 2890 mSmallerDimensionUpperLimit = 2891 Math.min(mWidthRange.getUpper(), mHeightRange.getUpper()); 2892 mWidthRange = mHeightRange = mWidthRange.extend(mHeightRange); 2893 } 2894 } 2895 2896 ratios = Utils.parseRationalRange( 2897 map.get("block-aspect-ratio-range"), null); 2898 blockRatios = Utils.parseRationalRange( 2899 map.get("pixel-aspect-ratio-range"), null); 2900 frameRates = Utils.parseIntRange(map.get("frame-rate-range"), null); 2901 if (frameRates != null) { 2902 try { 2903 frameRates = frameRates.intersect(FRAME_RATE_RANGE); 2904 } catch (IllegalArgumentException e) { 2905 Log.w(TAG, "frame rate range (" + frameRates 2906 + ") is out of limits: " + FRAME_RATE_RANGE); 2907 frameRates = null; 2908 } 2909 } 2910 bitRates = Utils.parseIntRange(map.get("bitrate-range"), null); 2911 if (bitRates != null) { 2912 try { 2913 bitRates = bitRates.intersect(BITRATE_RANGE); 2914 } catch (IllegalArgumentException e) { 2915 Log.w(TAG, "bitrate range (" + bitRates 2916 + ") is out of limits: " + BITRATE_RANGE); 2917 bitRates = null; 2918 } 2919 } 2920 2921 checkPowerOfTwo( 2922 blockSize.getWidth(), "block-size width must be power of two"); 2923 checkPowerOfTwo( 2924 blockSize.getHeight(), "block-size height must be power of two"); 2925 2926 checkPowerOfTwo( 2927 alignment.getWidth(), "alignment width must be power of two"); 2928 checkPowerOfTwo( 2929 alignment.getHeight(), "alignment height must be power of two"); 2930 2931 // update block-size and alignment 2932 applyMacroBlockLimits( 2933 Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, 2934 Long.MAX_VALUE, blockSize.getWidth(), blockSize.getHeight(), 2935 alignment.getWidth(), alignment.getHeight()); 2936 2937 if ((mParent.mError & ERROR_UNSUPPORTED) != 0 || mAllowMbOverride) { 2938 // codec supports profiles that we don't know. 2939 // Use supplied values clipped to platform limits 2940 if (widths != null) { 2941 mWidthRange = getSizeRange().intersect(widths); 2942 } 2943 if (heights != null) { 2944 mHeightRange = getSizeRange().intersect(heights); 2945 } 2946 if (counts != null) { 2947 mBlockCountRange = POSITIVE_INTEGERS.intersect( 2948 Utils.factorRange(counts, mBlockWidth * mBlockHeight 2949 / blockSize.getWidth() / blockSize.getHeight())); 2950 } 2951 if (blockRates != null) { 2952 mBlocksPerSecondRange = POSITIVE_LONGS.intersect( 2953 Utils.factorRange(blockRates, mBlockWidth * mBlockHeight 2954 / blockSize.getWidth() / blockSize.getHeight())); 2955 } 2956 if (blockRatios != null) { 2957 mBlockAspectRatioRange = POSITIVE_RATIONALS.intersect( 2958 Utils.scaleRange(blockRatios, 2959 mBlockHeight / blockSize.getHeight(), 2960 mBlockWidth / blockSize.getWidth())); 2961 } 2962 if (ratios != null) { 2963 mAspectRatioRange = POSITIVE_RATIONALS.intersect(ratios); 2964 } 2965 if (frameRates != null) { 2966 mFrameRateRange = FRAME_RATE_RANGE.intersect(frameRates); 2967 } 2968 if (bitRates != null) { 2969 // only allow bitrate override if unsupported profiles were encountered 2970 if ((mParent.mError & ERROR_UNSUPPORTED) != 0) { 2971 mBitrateRange = BITRATE_RANGE.intersect(bitRates); 2972 } else { 2973 mBitrateRange = mBitrateRange.intersect(bitRates); 2974 } 2975 } 2976 } else { 2977 // no unsupported profile/levels, so restrict values to known limits 2978 if (widths != null) { 2979 mWidthRange = mWidthRange.intersect(widths); 2980 } 2981 if (heights != null) { 2982 mHeightRange = mHeightRange.intersect(heights); 2983 } 2984 if (counts != null) { 2985 mBlockCountRange = mBlockCountRange.intersect( 2986 Utils.factorRange(counts, mBlockWidth * mBlockHeight 2987 / blockSize.getWidth() / blockSize.getHeight())); 2988 } 2989 if (blockRates != null) { 2990 mBlocksPerSecondRange = mBlocksPerSecondRange.intersect( 2991 Utils.factorRange(blockRates, mBlockWidth * mBlockHeight 2992 / blockSize.getWidth() / blockSize.getHeight())); 2993 } 2994 if (blockRatios != null) { 2995 mBlockAspectRatioRange = mBlockAspectRatioRange.intersect( 2996 Utils.scaleRange(blockRatios, 2997 mBlockHeight / blockSize.getHeight(), 2998 mBlockWidth / blockSize.getWidth())); 2999 } 3000 if (ratios != null) { 3001 mAspectRatioRange = mAspectRatioRange.intersect(ratios); 3002 } 3003 if (frameRates != null) { 3004 mFrameRateRange = mFrameRateRange.intersect(frameRates); 3005 } 3006 if (bitRates != null) { 3007 mBitrateRange = mBitrateRange.intersect(bitRates); 3008 } 3009 } 3010 updateLimits(); 3011 } 3012 3013 private void applyBlockLimits( 3014 int blockWidth, int blockHeight, 3015 Range<Integer> counts, Range<Long> rates, Range<Rational> ratios) { 3016 checkPowerOfTwo(blockWidth, "blockWidth must be a power of two"); 3017 checkPowerOfTwo(blockHeight, "blockHeight must be a power of two"); 3018 3019 final int newBlockWidth = Math.max(blockWidth, mBlockWidth); 3020 final int newBlockHeight = Math.max(blockHeight, mBlockHeight); 3021 3022 // factor will always be a power-of-2 3023 int factor = 3024 newBlockWidth * newBlockHeight / mBlockWidth / mBlockHeight; 3025 if (factor != 1) { 3026 mBlockCountRange = Utils.factorRange(mBlockCountRange, factor); 3027 mBlocksPerSecondRange = Utils.factorRange( 3028 mBlocksPerSecondRange, factor); 3029 mBlockAspectRatioRange = Utils.scaleRange( 3030 mBlockAspectRatioRange, 3031 newBlockHeight / mBlockHeight, 3032 newBlockWidth / mBlockWidth); 3033 mHorizontalBlockRange = Utils.factorRange( 3034 mHorizontalBlockRange, newBlockWidth / mBlockWidth); 3035 mVerticalBlockRange = Utils.factorRange( 3036 mVerticalBlockRange, newBlockHeight / mBlockHeight); 3037 } 3038 factor = newBlockWidth * newBlockHeight / blockWidth / blockHeight; 3039 if (factor != 1) { 3040 counts = Utils.factorRange(counts, factor); 3041 rates = Utils.factorRange(rates, factor); 3042 ratios = Utils.scaleRange( 3043 ratios, newBlockHeight / blockHeight, 3044 newBlockWidth / blockWidth); 3045 } 3046 mBlockCountRange = mBlockCountRange.intersect(counts); 3047 mBlocksPerSecondRange = mBlocksPerSecondRange.intersect(rates); 3048 mBlockAspectRatioRange = mBlockAspectRatioRange.intersect(ratios); 3049 mBlockWidth = newBlockWidth; 3050 mBlockHeight = newBlockHeight; 3051 } 3052 3053 private void applyAlignment(int widthAlignment, int heightAlignment) { 3054 checkPowerOfTwo(widthAlignment, "widthAlignment must be a power of two"); 3055 checkPowerOfTwo(heightAlignment, "heightAlignment must be a power of two"); 3056 3057 if (widthAlignment > mBlockWidth || heightAlignment > mBlockHeight) { 3058 // maintain assumption that 0 < alignment <= block-size 3059 applyBlockLimits( 3060 Math.max(widthAlignment, mBlockWidth), 3061 Math.max(heightAlignment, mBlockHeight), 3062 POSITIVE_INTEGERS, POSITIVE_LONGS, POSITIVE_RATIONALS); 3063 } 3064 3065 mWidthAlignment = Math.max(widthAlignment, mWidthAlignment); 3066 mHeightAlignment = Math.max(heightAlignment, mHeightAlignment); 3067 3068 mWidthRange = Utils.alignRange(mWidthRange, mWidthAlignment); 3069 mHeightRange = Utils.alignRange(mHeightRange, mHeightAlignment); 3070 } 3071 3072 private void updateLimits() { 3073 // pixels -> blocks <- counts 3074 mHorizontalBlockRange = mHorizontalBlockRange.intersect( 3075 Utils.factorRange(mWidthRange, mBlockWidth)); 3076 mHorizontalBlockRange = mHorizontalBlockRange.intersect( 3077 Range.create( 3078 mBlockCountRange.getLower() / mVerticalBlockRange.getUpper(), 3079 mBlockCountRange.getUpper() / mVerticalBlockRange.getLower())); 3080 mVerticalBlockRange = mVerticalBlockRange.intersect( 3081 Utils.factorRange(mHeightRange, mBlockHeight)); 3082 mVerticalBlockRange = mVerticalBlockRange.intersect( 3083 Range.create( 3084 mBlockCountRange.getLower() / mHorizontalBlockRange.getUpper(), 3085 mBlockCountRange.getUpper() / mHorizontalBlockRange.getLower())); 3086 mBlockCountRange = mBlockCountRange.intersect( 3087 Range.create( 3088 mHorizontalBlockRange.getLower() 3089 * mVerticalBlockRange.getLower(), 3090 mHorizontalBlockRange.getUpper() 3091 * mVerticalBlockRange.getUpper())); 3092 mBlockAspectRatioRange = mBlockAspectRatioRange.intersect( 3093 new Rational( 3094 mHorizontalBlockRange.getLower(), mVerticalBlockRange.getUpper()), 3095 new Rational( 3096 mHorizontalBlockRange.getUpper(), mVerticalBlockRange.getLower())); 3097 3098 // blocks -> pixels 3099 mWidthRange = mWidthRange.intersect( 3100 (mHorizontalBlockRange.getLower() - 1) * mBlockWidth + mWidthAlignment, 3101 mHorizontalBlockRange.getUpper() * mBlockWidth); 3102 mHeightRange = mHeightRange.intersect( 3103 (mVerticalBlockRange.getLower() - 1) * mBlockHeight + mHeightAlignment, 3104 mVerticalBlockRange.getUpper() * mBlockHeight); 3105 mAspectRatioRange = mAspectRatioRange.intersect( 3106 new Rational(mWidthRange.getLower(), mHeightRange.getUpper()), 3107 new Rational(mWidthRange.getUpper(), mHeightRange.getLower())); 3108 3109 mSmallerDimensionUpperLimit = Math.min( 3110 mSmallerDimensionUpperLimit, 3111 Math.min(mWidthRange.getUpper(), mHeightRange.getUpper())); 3112 3113 // blocks -> rate 3114 mBlocksPerSecondRange = mBlocksPerSecondRange.intersect( 3115 mBlockCountRange.getLower() * (long)mFrameRateRange.getLower(), 3116 mBlockCountRange.getUpper() * (long)mFrameRateRange.getUpper()); 3117 mFrameRateRange = mFrameRateRange.intersect( 3118 (int)(mBlocksPerSecondRange.getLower() 3119 / mBlockCountRange.getUpper()), 3120 (int)(mBlocksPerSecondRange.getUpper() 3121 / (double)mBlockCountRange.getLower())); 3122 } 3123 3124 private void applyMacroBlockLimits( 3125 int maxHorizontalBlocks, int maxVerticalBlocks, 3126 int maxBlocks, long maxBlocksPerSecond, 3127 int blockWidth, int blockHeight, 3128 int widthAlignment, int heightAlignment) { 3129 applyMacroBlockLimits( 3130 1 /* minHorizontalBlocks */, 1 /* minVerticalBlocks */, 3131 maxHorizontalBlocks, maxVerticalBlocks, 3132 maxBlocks, maxBlocksPerSecond, 3133 blockWidth, blockHeight, widthAlignment, heightAlignment); 3134 } 3135 3136 private void applyMacroBlockLimits( 3137 int minHorizontalBlocks, int minVerticalBlocks, 3138 int maxHorizontalBlocks, int maxVerticalBlocks, 3139 int maxBlocks, long maxBlocksPerSecond, 3140 int blockWidth, int blockHeight, 3141 int widthAlignment, int heightAlignment) { 3142 applyAlignment(widthAlignment, heightAlignment); 3143 applyBlockLimits( 3144 blockWidth, blockHeight, Range.create(1, maxBlocks), 3145 Range.create(1L, maxBlocksPerSecond), 3146 Range.create( 3147 new Rational(1, maxVerticalBlocks), 3148 new Rational(maxHorizontalBlocks, 1))); 3149 mHorizontalBlockRange = 3150 mHorizontalBlockRange.intersect( 3151 Utils.divUp(minHorizontalBlocks, (mBlockWidth / blockWidth)), 3152 maxHorizontalBlocks / (mBlockWidth / blockWidth)); 3153 mVerticalBlockRange = 3154 mVerticalBlockRange.intersect( 3155 Utils.divUp(minVerticalBlocks, (mBlockHeight / blockHeight)), 3156 maxVerticalBlocks / (mBlockHeight / blockHeight)); 3157 } 3158 3159 private void applyLevelLimits() { 3160 long maxBlocksPerSecond = 0; 3161 int maxBlocks = 0; 3162 int maxBps = 0; 3163 int maxDPBBlocks = 0; 3164 3165 int errors = ERROR_NONE_SUPPORTED; 3166 CodecProfileLevel[] profileLevels = mParent.profileLevels; 3167 String mime = mParent.getMimeType(); 3168 3169 if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_AVC)) { 3170 maxBlocks = 99; 3171 maxBlocksPerSecond = 1485; 3172 maxBps = 64000; 3173 maxDPBBlocks = 396; 3174 for (CodecProfileLevel profileLevel: profileLevels) { 3175 int MBPS = 0, FS = 0, BR = 0, DPB = 0; 3176 boolean supported = true; 3177 switch (profileLevel.level) { 3178 case CodecProfileLevel.AVCLevel1: 3179 MBPS = 1485; FS = 99; BR = 64; DPB = 396; break; 3180 case CodecProfileLevel.AVCLevel1b: 3181 MBPS = 1485; FS = 99; BR = 128; DPB = 396; break; 3182 case CodecProfileLevel.AVCLevel11: 3183 MBPS = 3000; FS = 396; BR = 192; DPB = 900; break; 3184 case CodecProfileLevel.AVCLevel12: 3185 MBPS = 6000; FS = 396; BR = 384; DPB = 2376; break; 3186 case CodecProfileLevel.AVCLevel13: 3187 MBPS = 11880; FS = 396; BR = 768; DPB = 2376; break; 3188 case CodecProfileLevel.AVCLevel2: 3189 MBPS = 11880; FS = 396; BR = 2000; DPB = 2376; break; 3190 case CodecProfileLevel.AVCLevel21: 3191 MBPS = 19800; FS = 792; BR = 4000; DPB = 4752; break; 3192 case CodecProfileLevel.AVCLevel22: 3193 MBPS = 20250; FS = 1620; BR = 4000; DPB = 8100; break; 3194 case CodecProfileLevel.AVCLevel3: 3195 MBPS = 40500; FS = 1620; BR = 10000; DPB = 8100; break; 3196 case CodecProfileLevel.AVCLevel31: 3197 MBPS = 108000; FS = 3600; BR = 14000; DPB = 18000; break; 3198 case CodecProfileLevel.AVCLevel32: 3199 MBPS = 216000; FS = 5120; BR = 20000; DPB = 20480; break; 3200 case CodecProfileLevel.AVCLevel4: 3201 MBPS = 245760; FS = 8192; BR = 20000; DPB = 32768; break; 3202 case CodecProfileLevel.AVCLevel41: 3203 MBPS = 245760; FS = 8192; BR = 50000; DPB = 32768; break; 3204 case CodecProfileLevel.AVCLevel42: 3205 MBPS = 522240; FS = 8704; BR = 50000; DPB = 34816; break; 3206 case CodecProfileLevel.AVCLevel5: 3207 MBPS = 589824; FS = 22080; BR = 135000; DPB = 110400; break; 3208 case CodecProfileLevel.AVCLevel51: 3209 MBPS = 983040; FS = 36864; BR = 240000; DPB = 184320; break; 3210 case CodecProfileLevel.AVCLevel52: 3211 MBPS = 2073600; FS = 36864; BR = 240000; DPB = 184320; break; 3212 case CodecProfileLevel.AVCLevel6: 3213 MBPS = 4177920; FS = 139264; BR = 240000; DPB = 696320; break; 3214 case CodecProfileLevel.AVCLevel61: 3215 MBPS = 8355840; FS = 139264; BR = 480000; DPB = 696320; break; 3216 case CodecProfileLevel.AVCLevel62: 3217 MBPS = 16711680; FS = 139264; BR = 800000; DPB = 696320; break; 3218 default: 3219 Log.w(TAG, "Unrecognized level " 3220 + profileLevel.level + " for " + mime); 3221 errors |= ERROR_UNRECOGNIZED; 3222 } 3223 switch (profileLevel.profile) { 3224 case CodecProfileLevel.AVCProfileConstrainedHigh: 3225 case CodecProfileLevel.AVCProfileHigh: 3226 BR *= 1250; break; 3227 case CodecProfileLevel.AVCProfileHigh10: 3228 BR *= 3000; break; 3229 case CodecProfileLevel.AVCProfileExtended: 3230 case CodecProfileLevel.AVCProfileHigh422: 3231 case CodecProfileLevel.AVCProfileHigh444: 3232 Log.w(TAG, "Unsupported profile " 3233 + profileLevel.profile + " for " + mime); 3234 errors |= ERROR_UNSUPPORTED; 3235 supported = false; 3236 // fall through - treat as base profile 3237 case CodecProfileLevel.AVCProfileConstrainedBaseline: 3238 case CodecProfileLevel.AVCProfileBaseline: 3239 case CodecProfileLevel.AVCProfileMain: 3240 BR *= 1000; break; 3241 default: 3242 Log.w(TAG, "Unrecognized profile " 3243 + profileLevel.profile + " for " + mime); 3244 errors |= ERROR_UNRECOGNIZED; 3245 BR *= 1000; 3246 } 3247 if (supported) { 3248 errors &= ~ERROR_NONE_SUPPORTED; 3249 } 3250 maxBlocksPerSecond = Math.max(MBPS, maxBlocksPerSecond); 3251 maxBlocks = Math.max(FS, maxBlocks); 3252 maxBps = Math.max(BR, maxBps); 3253 maxDPBBlocks = Math.max(maxDPBBlocks, DPB); 3254 } 3255 3256 int maxLengthInBlocks = (int)(Math.sqrt(maxBlocks * 8)); 3257 applyMacroBlockLimits( 3258 maxLengthInBlocks, maxLengthInBlocks, 3259 maxBlocks, maxBlocksPerSecond, 3260 16 /* blockWidth */, 16 /* blockHeight */, 3261 1 /* widthAlignment */, 1 /* heightAlignment */); 3262 } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_MPEG2)) { 3263 int maxWidth = 11, maxHeight = 9, maxRate = 15; 3264 maxBlocks = 99; 3265 maxBlocksPerSecond = 1485; 3266 maxBps = 64000; 3267 for (CodecProfileLevel profileLevel: profileLevels) { 3268 int MBPS = 0, FS = 0, BR = 0, FR = 0, W = 0, H = 0; 3269 boolean supported = true; 3270 switch (profileLevel.profile) { 3271 case CodecProfileLevel.MPEG2ProfileSimple: 3272 switch (profileLevel.level) { 3273 case CodecProfileLevel.MPEG2LevelML: 3274 FR = 30; W = 45; H = 36; MBPS = 40500; FS = 1620; BR = 15000; break; 3275 default: 3276 Log.w(TAG, "Unrecognized profile/level " 3277 + profileLevel.profile + "/" 3278 + profileLevel.level + " for " + mime); 3279 errors |= ERROR_UNRECOGNIZED; 3280 } 3281 break; 3282 case CodecProfileLevel.MPEG2ProfileMain: 3283 switch (profileLevel.level) { 3284 case CodecProfileLevel.MPEG2LevelLL: 3285 FR = 30; W = 22; H = 18; MBPS = 11880; FS = 396; BR = 4000; break; 3286 case CodecProfileLevel.MPEG2LevelML: 3287 FR = 30; W = 45; H = 36; MBPS = 40500; FS = 1620; BR = 15000; break; 3288 case CodecProfileLevel.MPEG2LevelH14: 3289 FR = 60; W = 90; H = 68; MBPS = 183600; FS = 6120; BR = 60000; break; 3290 case CodecProfileLevel.MPEG2LevelHL: 3291 FR = 60; W = 120; H = 68; MBPS = 244800; FS = 8160; BR = 80000; break; 3292 case CodecProfileLevel.MPEG2LevelHP: 3293 FR = 60; W = 120; H = 68; MBPS = 489600; FS = 8160; BR = 80000; break; 3294 default: 3295 Log.w(TAG, "Unrecognized profile/level " 3296 + profileLevel.profile + "/" 3297 + profileLevel.level + " for " + mime); 3298 errors |= ERROR_UNRECOGNIZED; 3299 } 3300 break; 3301 case CodecProfileLevel.MPEG2Profile422: 3302 case CodecProfileLevel.MPEG2ProfileSNR: 3303 case CodecProfileLevel.MPEG2ProfileSpatial: 3304 case CodecProfileLevel.MPEG2ProfileHigh: 3305 Log.i(TAG, "Unsupported profile " 3306 + profileLevel.profile + " for " + mime); 3307 errors |= ERROR_UNSUPPORTED; 3308 supported = false; 3309 break; 3310 default: 3311 Log.w(TAG, "Unrecognized profile " 3312 + profileLevel.profile + " for " + mime); 3313 errors |= ERROR_UNRECOGNIZED; 3314 } 3315 if (supported) { 3316 errors &= ~ERROR_NONE_SUPPORTED; 3317 } 3318 maxBlocksPerSecond = Math.max(MBPS, maxBlocksPerSecond); 3319 maxBlocks = Math.max(FS, maxBlocks); 3320 maxBps = Math.max(BR * 1000, maxBps); 3321 maxWidth = Math.max(W, maxWidth); 3322 maxHeight = Math.max(H, maxHeight); 3323 maxRate = Math.max(FR, maxRate); 3324 } 3325 applyMacroBlockLimits(maxWidth, maxHeight, 3326 maxBlocks, maxBlocksPerSecond, 3327 16 /* blockWidth */, 16 /* blockHeight */, 3328 1 /* widthAlignment */, 1 /* heightAlignment */); 3329 mFrameRateRange = mFrameRateRange.intersect(12, maxRate); 3330 } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_MPEG4)) { 3331 int maxWidth = 11, maxHeight = 9, maxRate = 15; 3332 maxBlocks = 99; 3333 maxBlocksPerSecond = 1485; 3334 maxBps = 64000; 3335 for (CodecProfileLevel profileLevel: profileLevels) { 3336 int MBPS = 0, FS = 0, BR = 0, FR = 0, W = 0, H = 0; 3337 boolean strict = false; // true: W, H and FR are individual max limits 3338 boolean supported = true; 3339 switch (profileLevel.profile) { 3340 case CodecProfileLevel.MPEG4ProfileSimple: 3341 switch (profileLevel.level) { 3342 case CodecProfileLevel.MPEG4Level0: 3343 strict = true; 3344 FR = 15; W = 11; H = 9; MBPS = 1485; FS = 99; BR = 64; break; 3345 case CodecProfileLevel.MPEG4Level1: 3346 FR = 30; W = 11; H = 9; MBPS = 1485; FS = 99; BR = 64; break; 3347 case CodecProfileLevel.MPEG4Level0b: 3348 strict = true; 3349 FR = 15; W = 11; H = 9; MBPS = 1485; FS = 99; BR = 128; break; 3350 case CodecProfileLevel.MPEG4Level2: 3351 FR = 30; W = 22; H = 18; MBPS = 5940; FS = 396; BR = 128; break; 3352 case CodecProfileLevel.MPEG4Level3: 3353 FR = 30; W = 22; H = 18; MBPS = 11880; FS = 396; BR = 384; break; 3354 case CodecProfileLevel.MPEG4Level4a: 3355 FR = 30; W = 40; H = 30; MBPS = 36000; FS = 1200; BR = 4000; break; 3356 case CodecProfileLevel.MPEG4Level5: 3357 FR = 30; W = 45; H = 36; MBPS = 40500; FS = 1620; BR = 8000; break; 3358 case CodecProfileLevel.MPEG4Level6: 3359 FR = 30; W = 80; H = 45; MBPS = 108000; FS = 3600; BR = 12000; break; 3360 default: 3361 Log.w(TAG, "Unrecognized profile/level " 3362 + profileLevel.profile + "/" 3363 + profileLevel.level + " for " + mime); 3364 errors |= ERROR_UNRECOGNIZED; 3365 } 3366 break; 3367 case CodecProfileLevel.MPEG4ProfileAdvancedSimple: 3368 switch (profileLevel.level) { 3369 case CodecProfileLevel.MPEG4Level0: 3370 case CodecProfileLevel.MPEG4Level1: 3371 FR = 30; W = 11; H = 9; MBPS = 2970; FS = 99; BR = 128; break; 3372 case CodecProfileLevel.MPEG4Level2: 3373 FR = 30; W = 22; H = 18; MBPS = 5940; FS = 396; BR = 384; break; 3374 case CodecProfileLevel.MPEG4Level3: 3375 FR = 30; W = 22; H = 18; MBPS = 11880; FS = 396; BR = 768; break; 3376 case CodecProfileLevel.MPEG4Level3b: 3377 FR = 30; W = 22; H = 18; MBPS = 11880; FS = 396; BR = 1500; break; 3378 case CodecProfileLevel.MPEG4Level4: 3379 FR = 30; W = 44; H = 36; MBPS = 23760; FS = 792; BR = 3000; break; 3380 case CodecProfileLevel.MPEG4Level5: 3381 FR = 30; W = 45; H = 36; MBPS = 48600; FS = 1620; BR = 8000; break; 3382 default: 3383 Log.w(TAG, "Unrecognized profile/level " 3384 + profileLevel.profile + "/" 3385 + profileLevel.level + " for " + mime); 3386 errors |= ERROR_UNRECOGNIZED; 3387 } 3388 break; 3389 case CodecProfileLevel.MPEG4ProfileMain: // 2-4 3390 case CodecProfileLevel.MPEG4ProfileNbit: // 2 3391 case CodecProfileLevel.MPEG4ProfileAdvancedRealTime: // 1-4 3392 case CodecProfileLevel.MPEG4ProfileCoreScalable: // 1-3 3393 case CodecProfileLevel.MPEG4ProfileAdvancedCoding: // 1-4 3394 case CodecProfileLevel.MPEG4ProfileCore: // 1-2 3395 case CodecProfileLevel.MPEG4ProfileAdvancedCore: // 1-4 3396 case CodecProfileLevel.MPEG4ProfileSimpleScalable: // 0-2 3397 case CodecProfileLevel.MPEG4ProfileHybrid: // 1-2 3398 3399 // Studio profiles are not supported by our codecs. 3400 3401 // Only profiles that can decode simple object types are considered. 3402 // The following profiles are not able to. 3403 case CodecProfileLevel.MPEG4ProfileBasicAnimated: // 1-2 3404 case CodecProfileLevel.MPEG4ProfileScalableTexture: // 1 3405 case CodecProfileLevel.MPEG4ProfileSimpleFace: // 1-2 3406 case CodecProfileLevel.MPEG4ProfileAdvancedScalable: // 1-3 3407 case CodecProfileLevel.MPEG4ProfileSimpleFBA: // 1-2 3408 Log.i(TAG, "Unsupported profile " 3409 + profileLevel.profile + " for " + mime); 3410 errors |= ERROR_UNSUPPORTED; 3411 supported = false; 3412 break; 3413 default: 3414 Log.w(TAG, "Unrecognized profile " 3415 + profileLevel.profile + " for " + mime); 3416 errors |= ERROR_UNRECOGNIZED; 3417 } 3418 if (supported) { 3419 errors &= ~ERROR_NONE_SUPPORTED; 3420 } 3421 maxBlocksPerSecond = Math.max(MBPS, maxBlocksPerSecond); 3422 maxBlocks = Math.max(FS, maxBlocks); 3423 maxBps = Math.max(BR * 1000, maxBps); 3424 if (strict) { 3425 maxWidth = Math.max(W, maxWidth); 3426 maxHeight = Math.max(H, maxHeight); 3427 maxRate = Math.max(FR, maxRate); 3428 } else { 3429 // assuming max 60 fps frame rate and 1:2 aspect ratio 3430 int maxDim = (int)Math.sqrt(FS * 2); 3431 maxWidth = Math.max(maxDim, maxWidth); 3432 maxHeight = Math.max(maxDim, maxHeight); 3433 maxRate = Math.max(Math.max(FR, 60), maxRate); 3434 } 3435 } 3436 applyMacroBlockLimits(maxWidth, maxHeight, 3437 maxBlocks, maxBlocksPerSecond, 3438 16 /* blockWidth */, 16 /* blockHeight */, 3439 1 /* widthAlignment */, 1 /* heightAlignment */); 3440 mFrameRateRange = mFrameRateRange.intersect(12, maxRate); 3441 } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_H263)) { 3442 int maxWidth = 11, maxHeight = 9, maxRate = 15; 3443 int minWidth = maxWidth, minHeight = maxHeight; 3444 int minAlignment = 16; 3445 maxBlocks = 99; 3446 maxBlocksPerSecond = 1485; 3447 maxBps = 64000; 3448 for (CodecProfileLevel profileLevel: profileLevels) { 3449 int MBPS = 0, BR = 0, FR = 0, W = 0, H = 0, minW = minWidth, minH = minHeight; 3450 boolean strict = false; // true: support only sQCIF, QCIF (maybe CIF) 3451 switch (profileLevel.level) { 3452 case CodecProfileLevel.H263Level10: 3453 strict = true; // only supports sQCIF & QCIF 3454 FR = 15; W = 11; H = 9; BR = 1; MBPS = W * H * FR; break; 3455 case CodecProfileLevel.H263Level20: 3456 strict = true; // only supports sQCIF, QCIF & CIF 3457 FR = 30; W = 22; H = 18; BR = 2; MBPS = W * H * 15; break; 3458 case CodecProfileLevel.H263Level30: 3459 strict = true; // only supports sQCIF, QCIF & CIF 3460 FR = 30; W = 22; H = 18; BR = 6; MBPS = W * H * FR; break; 3461 case CodecProfileLevel.H263Level40: 3462 strict = true; // only supports sQCIF, QCIF & CIF 3463 FR = 30; W = 22; H = 18; BR = 32; MBPS = W * H * FR; break; 3464 case CodecProfileLevel.H263Level45: 3465 // only implies level 10 support 3466 strict = profileLevel.profile == CodecProfileLevel.H263ProfileBaseline 3467 || profileLevel.profile == 3468 CodecProfileLevel.H263ProfileBackwardCompatible; 3469 if (!strict) { 3470 minW = 1; minH = 1; minAlignment = 4; 3471 } 3472 FR = 15; W = 11; H = 9; BR = 2; MBPS = W * H * FR; break; 3473 case CodecProfileLevel.H263Level50: 3474 // only supports 50fps for H > 15 3475 minW = 1; minH = 1; minAlignment = 4; 3476 FR = 60; W = 22; H = 18; BR = 64; MBPS = W * H * 50; break; 3477 case CodecProfileLevel.H263Level60: 3478 // only supports 50fps for H > 15 3479 minW = 1; minH = 1; minAlignment = 4; 3480 FR = 60; W = 45; H = 18; BR = 128; MBPS = W * H * 50; break; 3481 case CodecProfileLevel.H263Level70: 3482 // only supports 50fps for H > 30 3483 minW = 1; minH = 1; minAlignment = 4; 3484 FR = 60; W = 45; H = 36; BR = 256; MBPS = W * H * 50; break; 3485 default: 3486 Log.w(TAG, "Unrecognized profile/level " + profileLevel.profile 3487 + "/" + profileLevel.level + " for " + mime); 3488 errors |= ERROR_UNRECOGNIZED; 3489 } 3490 switch (profileLevel.profile) { 3491 case CodecProfileLevel.H263ProfileBackwardCompatible: 3492 case CodecProfileLevel.H263ProfileBaseline: 3493 case CodecProfileLevel.H263ProfileH320Coding: 3494 case CodecProfileLevel.H263ProfileHighCompression: 3495 case CodecProfileLevel.H263ProfileHighLatency: 3496 case CodecProfileLevel.H263ProfileInterlace: 3497 case CodecProfileLevel.H263ProfileInternet: 3498 case CodecProfileLevel.H263ProfileISWV2: 3499 case CodecProfileLevel.H263ProfileISWV3: 3500 break; 3501 default: 3502 Log.w(TAG, "Unrecognized profile " 3503 + profileLevel.profile + " for " + mime); 3504 errors |= ERROR_UNRECOGNIZED; 3505 } 3506 if (strict) { 3507 // Strict levels define sub-QCIF min size and enumerated sizes. We cannot 3508 // express support for "only sQCIF & QCIF (& CIF)" using VideoCapabilities 3509 // but we can express "only QCIF (& CIF)", so set minimume size at QCIF. 3510 // minW = 8; minH = 6; 3511 minW = 11; minH = 9; 3512 } else { 3513 // any support for non-strict levels (including unrecognized profiles or 3514 // levels) allow custom frame size support beyond supported limits 3515 // (other than bitrate) 3516 mAllowMbOverride = true; 3517 } 3518 errors &= ~ERROR_NONE_SUPPORTED; 3519 maxBlocksPerSecond = Math.max(MBPS, maxBlocksPerSecond); 3520 maxBlocks = Math.max(W * H, maxBlocks); 3521 maxBps = Math.max(BR * 64000, maxBps); 3522 maxWidth = Math.max(W, maxWidth); 3523 maxHeight = Math.max(H, maxHeight); 3524 maxRate = Math.max(FR, maxRate); 3525 minWidth = Math.min(minW, minWidth); 3526 minHeight = Math.min(minH, minHeight); 3527 } 3528 // unless we encountered custom frame size support, limit size to QCIF and CIF 3529 // using aspect ratio. 3530 if (!mAllowMbOverride) { 3531 mBlockAspectRatioRange = 3532 Range.create(new Rational(11, 9), new Rational(11, 9)); 3533 } 3534 applyMacroBlockLimits( 3535 minWidth, minHeight, 3536 maxWidth, maxHeight, 3537 maxBlocks, maxBlocksPerSecond, 3538 16 /* blockWidth */, 16 /* blockHeight */, 3539 minAlignment /* widthAlignment */, minAlignment /* heightAlignment */); 3540 mFrameRateRange = Range.create(1, maxRate); 3541 } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP8)) { 3542 maxBlocks = Integer.MAX_VALUE; 3543 maxBlocksPerSecond = Integer.MAX_VALUE; 3544 3545 // TODO: set to 100Mbps for now, need a number for VP8 3546 maxBps = 100000000; 3547 3548 // profile levels are not indicative for VPx, but verify 3549 // them nonetheless 3550 for (CodecProfileLevel profileLevel: profileLevels) { 3551 switch (profileLevel.level) { 3552 case CodecProfileLevel.VP8Level_Version0: 3553 case CodecProfileLevel.VP8Level_Version1: 3554 case CodecProfileLevel.VP8Level_Version2: 3555 case CodecProfileLevel.VP8Level_Version3: 3556 break; 3557 default: 3558 Log.w(TAG, "Unrecognized level " 3559 + profileLevel.level + " for " + mime); 3560 errors |= ERROR_UNRECOGNIZED; 3561 } 3562 switch (profileLevel.profile) { 3563 case CodecProfileLevel.VP8ProfileMain: 3564 break; 3565 default: 3566 Log.w(TAG, "Unrecognized profile " 3567 + profileLevel.profile + " for " + mime); 3568 errors |= ERROR_UNRECOGNIZED; 3569 } 3570 errors &= ~ERROR_NONE_SUPPORTED; 3571 } 3572 3573 final int blockSize = 16; 3574 applyMacroBlockLimits(Short.MAX_VALUE, Short.MAX_VALUE, 3575 maxBlocks, maxBlocksPerSecond, blockSize, blockSize, 3576 1 /* widthAlignment */, 1 /* heightAlignment */); 3577 } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP9)) { 3578 maxBlocksPerSecond = 829440; 3579 maxBlocks = 36864; 3580 maxBps = 200000; 3581 int maxDim = 512; 3582 3583 for (CodecProfileLevel profileLevel: profileLevels) { 3584 long SR = 0; // luma sample rate 3585 int FS = 0; // luma picture size 3586 int BR = 0; // bit rate kbps 3587 int D = 0; // luma dimension 3588 switch (profileLevel.level) { 3589 case CodecProfileLevel.VP9Level1: 3590 SR = 829440; FS = 36864; BR = 200; D = 512; break; 3591 case CodecProfileLevel.VP9Level11: 3592 SR = 2764800; FS = 73728; BR = 800; D = 768; break; 3593 case CodecProfileLevel.VP9Level2: 3594 SR = 4608000; FS = 122880; BR = 1800; D = 960; break; 3595 case CodecProfileLevel.VP9Level21: 3596 SR = 9216000; FS = 245760; BR = 3600; D = 1344; break; 3597 case CodecProfileLevel.VP9Level3: 3598 SR = 20736000; FS = 552960; BR = 7200; D = 2048; break; 3599 case CodecProfileLevel.VP9Level31: 3600 SR = 36864000; FS = 983040; BR = 12000; D = 2752; break; 3601 case CodecProfileLevel.VP9Level4: 3602 SR = 83558400; FS = 2228224; BR = 18000; D = 4160; break; 3603 case CodecProfileLevel.VP9Level41: 3604 SR = 160432128; FS = 2228224; BR = 30000; D = 4160; break; 3605 case CodecProfileLevel.VP9Level5: 3606 SR = 311951360; FS = 8912896; BR = 60000; D = 8384; break; 3607 case CodecProfileLevel.VP9Level51: 3608 SR = 588251136; FS = 8912896; BR = 120000; D = 8384; break; 3609 case CodecProfileLevel.VP9Level52: 3610 SR = 1176502272; FS = 8912896; BR = 180000; D = 8384; break; 3611 case CodecProfileLevel.VP9Level6: 3612 SR = 1176502272; FS = 35651584; BR = 180000; D = 16832; break; 3613 case CodecProfileLevel.VP9Level61: 3614 SR = 2353004544L; FS = 35651584; BR = 240000; D = 16832; break; 3615 case CodecProfileLevel.VP9Level62: 3616 SR = 4706009088L; FS = 35651584; BR = 480000; D = 16832; break; 3617 default: 3618 Log.w(TAG, "Unrecognized level " 3619 + profileLevel.level + " for " + mime); 3620 errors |= ERROR_UNRECOGNIZED; 3621 } 3622 switch (profileLevel.profile) { 3623 case CodecProfileLevel.VP9Profile0: 3624 case CodecProfileLevel.VP9Profile1: 3625 case CodecProfileLevel.VP9Profile2: 3626 case CodecProfileLevel.VP9Profile3: 3627 case CodecProfileLevel.VP9Profile2HDR: 3628 case CodecProfileLevel.VP9Profile3HDR: 3629 case CodecProfileLevel.VP9Profile2HDR10Plus: 3630 case CodecProfileLevel.VP9Profile3HDR10Plus: 3631 break; 3632 default: 3633 Log.w(TAG, "Unrecognized profile " 3634 + profileLevel.profile + " for " + mime); 3635 errors |= ERROR_UNRECOGNIZED; 3636 } 3637 errors &= ~ERROR_NONE_SUPPORTED; 3638 maxBlocksPerSecond = Math.max(SR, maxBlocksPerSecond); 3639 maxBlocks = Math.max(FS, maxBlocks); 3640 maxBps = Math.max(BR * 1000, maxBps); 3641 maxDim = Math.max(D, maxDim); 3642 } 3643 3644 final int blockSize = 8; 3645 int maxLengthInBlocks = Utils.divUp(maxDim, blockSize); 3646 maxBlocks = Utils.divUp(maxBlocks, blockSize * blockSize); 3647 maxBlocksPerSecond = Utils.divUp(maxBlocksPerSecond, blockSize * blockSize); 3648 3649 applyMacroBlockLimits( 3650 maxLengthInBlocks, maxLengthInBlocks, 3651 maxBlocks, maxBlocksPerSecond, 3652 blockSize, blockSize, 3653 1 /* widthAlignment */, 1 /* heightAlignment */); 3654 } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_HEVC)) { 3655 // CTBs are at least 8x8 so use 8x8 block size 3656 maxBlocks = 36864 >> 6; // 192x192 pixels == 576 8x8 blocks 3657 maxBlocksPerSecond = maxBlocks * 15; 3658 maxBps = 128000; 3659 for (CodecProfileLevel profileLevel: profileLevels) { 3660 double FR = 0; 3661 int FS = 0; 3662 int BR = 0; 3663 switch (profileLevel.level) { 3664 /* The HEVC spec talks only in a very convoluted manner about the 3665 existence of levels 1-3.1 for High tier, which could also be 3666 understood as 'decoders and encoders should treat these levels 3667 as if they were Main tier', so we do that. */ 3668 case CodecProfileLevel.HEVCMainTierLevel1: 3669 case CodecProfileLevel.HEVCHighTierLevel1: 3670 FR = 15; FS = 36864; BR = 128; break; 3671 case CodecProfileLevel.HEVCMainTierLevel2: 3672 case CodecProfileLevel.HEVCHighTierLevel2: 3673 FR = 30; FS = 122880; BR = 1500; break; 3674 case CodecProfileLevel.HEVCMainTierLevel21: 3675 case CodecProfileLevel.HEVCHighTierLevel21: 3676 FR = 30; FS = 245760; BR = 3000; break; 3677 case CodecProfileLevel.HEVCMainTierLevel3: 3678 case CodecProfileLevel.HEVCHighTierLevel3: 3679 FR = 30; FS = 552960; BR = 6000; break; 3680 case CodecProfileLevel.HEVCMainTierLevel31: 3681 case CodecProfileLevel.HEVCHighTierLevel31: 3682 FR = 33.75; FS = 983040; BR = 10000; break; 3683 case CodecProfileLevel.HEVCMainTierLevel4: 3684 FR = 30; FS = 2228224; BR = 12000; break; 3685 case CodecProfileLevel.HEVCHighTierLevel4: 3686 FR = 30; FS = 2228224; BR = 30000; break; 3687 case CodecProfileLevel.HEVCMainTierLevel41: 3688 FR = 60; FS = 2228224; BR = 20000; break; 3689 case CodecProfileLevel.HEVCHighTierLevel41: 3690 FR = 60; FS = 2228224; BR = 50000; break; 3691 case CodecProfileLevel.HEVCMainTierLevel5: 3692 FR = 30; FS = 8912896; BR = 25000; break; 3693 case CodecProfileLevel.HEVCHighTierLevel5: 3694 FR = 30; FS = 8912896; BR = 100000; break; 3695 case CodecProfileLevel.HEVCMainTierLevel51: 3696 FR = 60; FS = 8912896; BR = 40000; break; 3697 case CodecProfileLevel.HEVCHighTierLevel51: 3698 FR = 60; FS = 8912896; BR = 160000; break; 3699 case CodecProfileLevel.HEVCMainTierLevel52: 3700 FR = 120; FS = 8912896; BR = 60000; break; 3701 case CodecProfileLevel.HEVCHighTierLevel52: 3702 FR = 120; FS = 8912896; BR = 240000; break; 3703 case CodecProfileLevel.HEVCMainTierLevel6: 3704 FR = 30; FS = 35651584; BR = 60000; break; 3705 case CodecProfileLevel.HEVCHighTierLevel6: 3706 FR = 30; FS = 35651584; BR = 240000; break; 3707 case CodecProfileLevel.HEVCMainTierLevel61: 3708 FR = 60; FS = 35651584; BR = 120000; break; 3709 case CodecProfileLevel.HEVCHighTierLevel61: 3710 FR = 60; FS = 35651584; BR = 480000; break; 3711 case CodecProfileLevel.HEVCMainTierLevel62: 3712 FR = 120; FS = 35651584; BR = 240000; break; 3713 case CodecProfileLevel.HEVCHighTierLevel62: 3714 FR = 120; FS = 35651584; BR = 800000; break; 3715 default: 3716 Log.w(TAG, "Unrecognized level " 3717 + profileLevel.level + " for " + mime); 3718 errors |= ERROR_UNRECOGNIZED; 3719 } 3720 switch (profileLevel.profile) { 3721 case CodecProfileLevel.HEVCProfileMain: 3722 case CodecProfileLevel.HEVCProfileMain10: 3723 case CodecProfileLevel.HEVCProfileMainStill: 3724 case CodecProfileLevel.HEVCProfileMain10HDR10: 3725 case CodecProfileLevel.HEVCProfileMain10HDR10Plus: 3726 break; 3727 default: 3728 Log.w(TAG, "Unrecognized profile " 3729 + profileLevel.profile + " for " + mime); 3730 errors |= ERROR_UNRECOGNIZED; 3731 } 3732 3733 /* DPB logic: 3734 if (width * height <= FS / 4) DPB = 16; 3735 else if (width * height <= FS / 2) DPB = 12; 3736 else if (width * height <= FS * 0.75) DPB = 8; 3737 else DPB = 6; 3738 */ 3739 3740 FS >>= 6; // convert pixels to blocks 3741 errors &= ~ERROR_NONE_SUPPORTED; 3742 maxBlocksPerSecond = Math.max((int)(FR * FS), maxBlocksPerSecond); 3743 maxBlocks = Math.max(FS, maxBlocks); 3744 maxBps = Math.max(BR * 1000, maxBps); 3745 } 3746 3747 int maxLengthInBlocks = (int)(Math.sqrt(maxBlocks * 8)); 3748 applyMacroBlockLimits( 3749 maxLengthInBlocks, maxLengthInBlocks, 3750 maxBlocks, maxBlocksPerSecond, 3751 8 /* blockWidth */, 8 /* blockHeight */, 3752 1 /* widthAlignment */, 1 /* heightAlignment */); 3753 } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_AV1)) { 3754 maxBlocksPerSecond = 829440; 3755 maxBlocks = 36864; 3756 maxBps = 200000; 3757 int maxDim = 512; 3758 3759 // Sample rate, Picture Size, Bit rate and luma dimension for AV1 Codec, 3760 // corresponding to the definitions in 3761 // "AV1 Bitstream & Decoding Process Specification", Annex A 3762 // found at https://aomedia.org/av1-bitstream-and-decoding-process-specification/ 3763 for (CodecProfileLevel profileLevel: profileLevels) { 3764 long SR = 0; // luma sample rate 3765 int FS = 0; // luma picture size 3766 int BR = 0; // bit rate kbps 3767 int D = 0; // luma D 3768 switch (profileLevel.level) { 3769 case CodecProfileLevel.AV1Level2: 3770 SR = 5529600; FS = 147456; BR = 1500; D = 2048; break; 3771 case CodecProfileLevel.AV1Level21: 3772 case CodecProfileLevel.AV1Level22: 3773 case CodecProfileLevel.AV1Level23: 3774 SR = 10454400; FS = 278784; BR = 3000; D = 2816; break; 3775 3776 case CodecProfileLevel.AV1Level3: 3777 SR = 24969600; FS = 665856; BR = 6000; D = 4352; break; 3778 case CodecProfileLevel.AV1Level31: 3779 case CodecProfileLevel.AV1Level32: 3780 case CodecProfileLevel.AV1Level33: 3781 SR = 39938400; FS = 1065024; BR = 10000; D = 5504; break; 3782 3783 case CodecProfileLevel.AV1Level4: 3784 SR = 77856768; FS = 2359296; BR = 12000; D = 6144; break; 3785 case CodecProfileLevel.AV1Level41: 3786 case CodecProfileLevel.AV1Level42: 3787 case CodecProfileLevel.AV1Level43: 3788 SR = 155713536; FS = 2359296; BR = 20000; D = 6144; break; 3789 3790 case CodecProfileLevel.AV1Level5: 3791 SR = 273715200; FS = 8912896; BR = 30000; D = 8192; break; 3792 case CodecProfileLevel.AV1Level51: 3793 SR = 547430400; FS = 8912896; BR = 40000; D = 8192; break; 3794 case CodecProfileLevel.AV1Level52: 3795 SR = 1094860800; FS = 8912896; BR = 60000; D = 8192; break; 3796 case CodecProfileLevel.AV1Level53: 3797 SR = 1176502272; FS = 8912896; BR = 60000; D = 8192; break; 3798 3799 case CodecProfileLevel.AV1Level6: 3800 SR = 1176502272; FS = 35651584; BR = 60000; D = 16384; break; 3801 case CodecProfileLevel.AV1Level61: 3802 SR = 2189721600L; FS = 35651584; BR = 100000; D = 16384; break; 3803 case CodecProfileLevel.AV1Level62: 3804 SR = 4379443200L; FS = 35651584; BR = 160000; D = 16384; break; 3805 case CodecProfileLevel.AV1Level63: 3806 SR = 4706009088L; FS = 35651584; BR = 160000; D = 16384; break; 3807 3808 default: 3809 Log.w(TAG, "Unrecognized level " 3810 + profileLevel.level + " for " + mime); 3811 errors |= ERROR_UNRECOGNIZED; 3812 } 3813 switch (profileLevel.profile) { 3814 case CodecProfileLevel.AV1ProfileMain8: 3815 case CodecProfileLevel.AV1ProfileMain10: 3816 case CodecProfileLevel.AV1ProfileMain10HDR10: 3817 case CodecProfileLevel.AV1ProfileMain10HDR10Plus: 3818 break; 3819 default: 3820 Log.w(TAG, "Unrecognized profile " 3821 + profileLevel.profile + " for " + mime); 3822 errors |= ERROR_UNRECOGNIZED; 3823 } 3824 errors &= ~ERROR_NONE_SUPPORTED; 3825 maxBlocksPerSecond = Math.max(SR, maxBlocksPerSecond); 3826 maxBlocks = Math.max(FS, maxBlocks); 3827 maxBps = Math.max(BR * 1000, maxBps); 3828 maxDim = Math.max(D, maxDim); 3829 } 3830 3831 final int blockSize = 8; 3832 int maxLengthInBlocks = Utils.divUp(maxDim, blockSize); 3833 maxBlocks = Utils.divUp(maxBlocks, blockSize * blockSize); 3834 maxBlocksPerSecond = Utils.divUp(maxBlocksPerSecond, blockSize * blockSize); 3835 applyMacroBlockLimits( 3836 maxLengthInBlocks, maxLengthInBlocks, 3837 maxBlocks, maxBlocksPerSecond, 3838 blockSize, blockSize, 3839 1 /* widthAlignment */, 1 /* heightAlignment */); 3840 } else if (GetFlag(() -> android.media.codec.Flags.apvSupport()) 3841 && mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_APV)) { 3842 maxBlocksPerSecond = 11880; 3843 maxBps = 7000000; 3844 3845 // Sample rate, and Bit rate for APV Codec, 3846 // corresponding to the definitions in 3847 // "10.1.4. Levels and bands" 3848 // found at https://www.ietf.org/archive/id/draft-lim-apv-03.html 3849 for (CodecProfileLevel profileLevel: profileLevels) { 3850 long SR = 0; // luma sample rate 3851 int BR = 0; // bit rate bps 3852 switch (profileLevel.level) { 3853 case CodecProfileLevel.APVLevel1Band0: 3854 SR = 3041280; BR = 7000000; break; 3855 case CodecProfileLevel.APVLevel1Band1: 3856 SR = 3041280; BR = 11000000; break; 3857 case CodecProfileLevel.APVLevel1Band2: 3858 SR = 3041280; BR = 14000000; break; 3859 case CodecProfileLevel.APVLevel1Band3: 3860 SR = 3041280; BR = 21000000; break; 3861 case CodecProfileLevel.APVLevel11Band0: 3862 SR = 6082560; BR = 14000000; break; 3863 case CodecProfileLevel.APVLevel11Band1: 3864 SR = 6082560; BR = 21000000; break; 3865 case CodecProfileLevel.APVLevel11Band2: 3866 SR = 6082560; BR = 28000000; break; 3867 case CodecProfileLevel.APVLevel11Band3: 3868 SR = 6082560; BR = 42000000; break; 3869 case CodecProfileLevel.APVLevel2Band0: 3870 SR = 15667200; BR = 36000000; break; 3871 case CodecProfileLevel.APVLevel2Band1: 3872 SR = 15667200; BR = 53000000; break; 3873 case CodecProfileLevel.APVLevel2Band2: 3874 SR = 15667200; BR = 71000000; break; 3875 case CodecProfileLevel.APVLevel2Band3: 3876 SR = 15667200; BR = 106000000; break; 3877 case CodecProfileLevel.APVLevel21Band0: 3878 SR = 31334400; BR = 71000000; break; 3879 case CodecProfileLevel.APVLevel21Band1: 3880 SR = 31334400; BR = 106000000; break; 3881 case CodecProfileLevel.APVLevel21Band2: 3882 SR = 31334400; BR = 141000000; break; 3883 case CodecProfileLevel.APVLevel21Band3: 3884 SR = 31334400; BR = 212000000; break; 3885 case CodecProfileLevel.APVLevel3Band0: 3886 SR = 66846720; BR = 101000000; break; 3887 case CodecProfileLevel.APVLevel3Band1: 3888 SR = 66846720; BR = 151000000; break; 3889 case CodecProfileLevel.APVLevel3Band2: 3890 SR = 66846720; BR = 201000000; break; 3891 case CodecProfileLevel.APVLevel3Band3: 3892 SR = 66846720; BR = 301000000; break; 3893 case CodecProfileLevel.APVLevel31Band0: 3894 SR = 133693440; BR = 201000000; break; 3895 case CodecProfileLevel.APVLevel31Band1: 3896 SR = 133693440; BR = 301000000; break; 3897 case CodecProfileLevel.APVLevel31Band2: 3898 SR = 133693440; BR = 401000000; break; 3899 case CodecProfileLevel.APVLevel31Band3: 3900 SR = 133693440; BR = 602000000; break; 3901 case CodecProfileLevel.APVLevel4Band0: 3902 SR = 265420800; BR = 401000000; break; 3903 case CodecProfileLevel.APVLevel4Band1: 3904 SR = 265420800; BR = 602000000; break; 3905 case CodecProfileLevel.APVLevel4Band2: 3906 SR = 265420800; BR = 780000000; break; 3907 case CodecProfileLevel.APVLevel4Band3: 3908 SR = 265420800; BR = 1170000000; break; 3909 case CodecProfileLevel.APVLevel41Band0: 3910 SR = 530841600; BR = 780000000; break; 3911 case CodecProfileLevel.APVLevel41Band1: 3912 SR = 530841600; BR = 1170000000; break; 3913 case CodecProfileLevel.APVLevel41Band2: 3914 SR = 530841600; BR = 1560000000; break; 3915 case CodecProfileLevel.APVLevel41Band3: 3916 // Current API allows bitrates only up to Max Integer 3917 // Hence we are limiting internal limits to Integer.MAX_VALUE 3918 // even when actual Level/Band limits are higher 3919 SR = 530841600; BR = Integer.MAX_VALUE; break; 3920 case CodecProfileLevel.APVLevel5Band0: 3921 SR = 1061683200; BR = 1560000000; break; 3922 case CodecProfileLevel.APVLevel5Band1: 3923 SR = 1061683200; BR = Integer.MAX_VALUE; break; 3924 case CodecProfileLevel.APVLevel5Band2: 3925 SR = 1061683200; BR = Integer.MAX_VALUE; break; 3926 case CodecProfileLevel.APVLevel5Band3: 3927 SR = 1061683200; BR = Integer.MAX_VALUE; break; 3928 case CodecProfileLevel.APVLevel51Band0: 3929 case CodecProfileLevel.APVLevel51Band1: 3930 case CodecProfileLevel.APVLevel51Band2: 3931 case CodecProfileLevel.APVLevel51Band3: 3932 SR = 2123366400; BR = Integer.MAX_VALUE; break; 3933 case CodecProfileLevel.APVLevel6Band0: 3934 case CodecProfileLevel.APVLevel6Band1: 3935 case CodecProfileLevel.APVLevel6Band2: 3936 case CodecProfileLevel.APVLevel6Band3: 3937 SR = 4777574400L; BR = Integer.MAX_VALUE; break; 3938 case CodecProfileLevel.APVLevel61Band0: 3939 case CodecProfileLevel.APVLevel61Band1: 3940 case CodecProfileLevel.APVLevel61Band2: 3941 case CodecProfileLevel.APVLevel61Band3: 3942 SR = 8493465600L; BR = Integer.MAX_VALUE; break; 3943 case CodecProfileLevel.APVLevel7Band0: 3944 case CodecProfileLevel.APVLevel7Band1: 3945 case CodecProfileLevel.APVLevel7Band2: 3946 case CodecProfileLevel.APVLevel7Band3: 3947 SR = 16986931200L; BR = Integer.MAX_VALUE; break; 3948 case CodecProfileLevel.APVLevel71Band0: 3949 case CodecProfileLevel.APVLevel71Band1: 3950 case CodecProfileLevel.APVLevel71Band2: 3951 case CodecProfileLevel.APVLevel71Band3: 3952 SR = 33973862400L; BR = Integer.MAX_VALUE; break; 3953 default: 3954 Log.w(TAG, "Unrecognized level " 3955 + profileLevel.level + " for " + mime); 3956 errors |= ERROR_UNRECOGNIZED; 3957 } 3958 switch (profileLevel.profile) { 3959 case CodecProfileLevel.APVProfile422_10: 3960 case CodecProfileLevel.APVProfile422_10HDR10: 3961 case CodecProfileLevel.APVProfile422_10HDR10Plus: 3962 break; 3963 default: 3964 Log.w(TAG, "Unrecognized profile " 3965 + profileLevel.profile + " for " + mime); 3966 errors |= ERROR_UNRECOGNIZED; 3967 } 3968 errors &= ~ERROR_NONE_SUPPORTED; 3969 maxBlocksPerSecond = Math.max(SR, maxBlocksPerSecond); 3970 maxBps = Math.max(BR, maxBps); 3971 } 3972 3973 final int blockSize = 16; 3974 maxBlocks = Integer.MAX_VALUE; 3975 maxBlocksPerSecond = Utils.divUp(maxBlocksPerSecond, blockSize * blockSize); 3976 maxBlocks = (int) Math.min((long) maxBlocks, maxBlocksPerSecond); 3977 // Max frame size in APV is 2^24 3978 int maxLengthInBlocks = Utils.divUp((int) Math.pow(2, 24), blockSize); 3979 maxLengthInBlocks = Math.min(maxLengthInBlocks, maxBlocks); 3980 applyMacroBlockLimits( 3981 maxLengthInBlocks, maxLengthInBlocks, 3982 maxBlocks, maxBlocksPerSecond, 3983 blockSize, blockSize, 3984 2 /* widthAlignment */, 1 /* heightAlignment */); 3985 } else { 3986 Log.w(TAG, "Unsupported mime " + mime); 3987 // using minimal bitrate here. should be overriden by 3988 // info from media_codecs.xml 3989 maxBps = 64000; 3990 errors |= ERROR_UNSUPPORTED; 3991 } 3992 mBitrateRange = Range.create(1, maxBps); 3993 mParent.mError |= errors; 3994 } 3995 } 3996 3997 /** 3998 * A class that supports querying the encoding capabilities of a codec. 3999 */ 4000 public static final class EncoderCapabilities { 4001 /** 4002 * Returns the supported range of quality values. 4003 * 4004 * Quality is implementation-specific. As a general rule, a higher quality 4005 * setting results in a better image quality and a lower compression ratio. 4006 */ 4007 public Range<Integer> getQualityRange() { 4008 return mQualityRange; 4009 } 4010 4011 /** 4012 * Returns the supported range of encoder complexity values. 4013 * <p> 4014 * Some codecs may support multiple complexity levels, where higher 4015 * complexity values use more encoder tools (e.g. perform more 4016 * intensive calculations) to improve the quality or the compression 4017 * ratio. Use a lower value to save power and/or time. 4018 */ 4019 public Range<Integer> getComplexityRange() { 4020 return mComplexityRange; 4021 } 4022 4023 /** Constant quality mode */ 4024 public static final int BITRATE_MODE_CQ = 0; 4025 /** Variable bitrate mode */ 4026 public static final int BITRATE_MODE_VBR = 1; 4027 /** Constant bitrate mode */ 4028 public static final int BITRATE_MODE_CBR = 2; 4029 /** Constant bitrate mode with frame drops */ 4030 public static final int BITRATE_MODE_CBR_FD = 3; 4031 4032 private static final Feature[] bitrates = new Feature[] { 4033 new Feature("VBR", BITRATE_MODE_VBR, true), 4034 new Feature("CBR", BITRATE_MODE_CBR, false), 4035 new Feature("CQ", BITRATE_MODE_CQ, false), 4036 new Feature("CBR-FD", BITRATE_MODE_CBR_FD, false) 4037 }; 4038 4039 private static int parseBitrateMode(String mode) { 4040 for (Feature feat: bitrates) { 4041 if (feat.mName.equalsIgnoreCase(mode)) { 4042 return feat.mValue; 4043 } 4044 } 4045 return 0; 4046 } 4047 4048 /** 4049 * Query whether a bitrate mode is supported. 4050 */ 4051 public boolean isBitrateModeSupported(int mode) { 4052 for (Feature feat: bitrates) { 4053 if (mode == feat.mValue) { 4054 return (mBitControl & (1 << mode)) != 0; 4055 } 4056 } 4057 return false; 4058 } 4059 4060 private Range<Integer> mQualityRange; 4061 private Range<Integer> mComplexityRange; 4062 private CodecCapabilities mParent; 4063 4064 /* no public constructor */ 4065 private EncoderCapabilities() { } 4066 4067 /** @hide */ 4068 public static EncoderCapabilities create( 4069 MediaFormat info, CodecCapabilities parent) { 4070 EncoderCapabilities caps = new EncoderCapabilities(); 4071 caps.init(info, parent); 4072 return caps; 4073 } 4074 4075 private void init(MediaFormat info, CodecCapabilities parent) { 4076 // no support for complexity or quality yet 4077 mParent = parent; 4078 mComplexityRange = Range.create(0, 0); 4079 mQualityRange = Range.create(0, 0); 4080 mBitControl = (1 << BITRATE_MODE_VBR); 4081 4082 applyLevelLimits(); 4083 parseFromInfo(info); 4084 } 4085 4086 private void applyLevelLimits() { 4087 String mime = mParent.getMimeType(); 4088 if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_FLAC)) { 4089 mComplexityRange = Range.create(0, 8); 4090 mBitControl = (1 << BITRATE_MODE_CQ); 4091 } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AMR_NB) 4092 || mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AMR_WB) 4093 || mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_G711_ALAW) 4094 || mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_G711_MLAW) 4095 || mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_MSGSM)) { 4096 mBitControl = (1 << BITRATE_MODE_CBR); 4097 } 4098 } 4099 4100 private int mBitControl; 4101 private Integer mDefaultComplexity; 4102 private Integer mDefaultQuality; 4103 private String mQualityScale; 4104 4105 private void parseFromInfo(MediaFormat info) { 4106 Map<String, Object> map = info.getMap(); 4107 4108 if (info.containsKey("complexity-range")) { 4109 mComplexityRange = Utils 4110 .parseIntRange(info.getString("complexity-range"), mComplexityRange); 4111 // TODO should we limit this to level limits? 4112 } 4113 if (info.containsKey("quality-range")) { 4114 mQualityRange = Utils 4115 .parseIntRange(info.getString("quality-range"), mQualityRange); 4116 } 4117 if (info.containsKey("feature-bitrate-modes")) { 4118 mBitControl = 0; 4119 for (String mode: info.getString("feature-bitrate-modes").split(",")) { 4120 mBitControl |= (1 << parseBitrateMode(mode)); 4121 } 4122 } 4123 4124 try { 4125 mDefaultComplexity = Integer.parseInt((String)map.get("complexity-default")); 4126 } catch (NumberFormatException e) { } 4127 4128 try { 4129 mDefaultQuality = Integer.parseInt((String)map.get("quality-default")); 4130 } catch (NumberFormatException e) { } 4131 4132 mQualityScale = (String)map.get("quality-scale"); 4133 } 4134 4135 private boolean supports( 4136 Integer complexity, Integer quality, Integer profile) { 4137 boolean ok = true; 4138 if (ok && complexity != null) { 4139 ok = mComplexityRange.contains(complexity); 4140 } 4141 if (ok && quality != null) { 4142 ok = mQualityRange.contains(quality); 4143 } 4144 if (ok && profile != null) { 4145 for (CodecProfileLevel pl: mParent.profileLevels) { 4146 if (pl.profile == profile) { 4147 profile = null; 4148 break; 4149 } 4150 } 4151 ok = profile == null; 4152 } 4153 return ok; 4154 } 4155 4156 /** @hide */ 4157 public void getDefaultFormat(MediaFormat format) { 4158 // don't list trivial quality/complexity as default for now 4159 if (!mQualityRange.getUpper().equals(mQualityRange.getLower()) 4160 && mDefaultQuality != null) { 4161 format.setInteger(MediaFormat.KEY_QUALITY, mDefaultQuality); 4162 } 4163 if (!mComplexityRange.getUpper().equals(mComplexityRange.getLower()) 4164 && mDefaultComplexity != null) { 4165 format.setInteger(MediaFormat.KEY_COMPLEXITY, mDefaultComplexity); 4166 } 4167 // bitrates are listed in order of preference 4168 for (Feature feat: bitrates) { 4169 if ((mBitControl & (1 << feat.mValue)) != 0) { 4170 format.setInteger(MediaFormat.KEY_BITRATE_MODE, feat.mValue); 4171 break; 4172 } 4173 } 4174 } 4175 4176 /** @hide */ 4177 public boolean supportsFormat(MediaFormat format) { 4178 final Map<String, Object> map = format.getMap(); 4179 final String mime = mParent.getMimeType(); 4180 4181 Integer mode = (Integer)map.get(MediaFormat.KEY_BITRATE_MODE); 4182 if (mode != null && !isBitrateModeSupported(mode)) { 4183 return false; 4184 } 4185 4186 Integer complexity = (Integer)map.get(MediaFormat.KEY_COMPLEXITY); 4187 if (MediaFormat.MIMETYPE_AUDIO_FLAC.equalsIgnoreCase(mime)) { 4188 Integer flacComplexity = 4189 (Integer)map.get(MediaFormat.KEY_FLAC_COMPRESSION_LEVEL); 4190 if (complexity == null) { 4191 complexity = flacComplexity; 4192 } else if (flacComplexity != null && !complexity.equals(flacComplexity)) { 4193 throw new IllegalArgumentException( 4194 "conflicting values for complexity and " + 4195 "flac-compression-level"); 4196 } 4197 } 4198 4199 // other audio parameters 4200 Integer profile = (Integer)map.get(MediaFormat.KEY_PROFILE); 4201 if (MediaFormat.MIMETYPE_AUDIO_AAC.equalsIgnoreCase(mime)) { 4202 Integer aacProfile = (Integer)map.get(MediaFormat.KEY_AAC_PROFILE); 4203 if (profile == null) { 4204 profile = aacProfile; 4205 } else if (aacProfile != null && !aacProfile.equals(profile)) { 4206 throw new IllegalArgumentException( 4207 "conflicting values for profile and aac-profile"); 4208 } 4209 } 4210 4211 Integer quality = (Integer)map.get(MediaFormat.KEY_QUALITY); 4212 4213 return supports(complexity, quality, profile); 4214 } 4215 }; 4216 4217 /** 4218 * Encapsulates the profiles available for a codec component. 4219 * <p>You can get a set of {@link MediaCodecInfo.CodecProfileLevel} objects for a given 4220 * {@link MediaCodecInfo} object from the 4221 * {@link MediaCodecInfo.CodecCapabilities#profileLevels} field. 4222 */ 4223 public static final class CodecProfileLevel { 4224 // These constants were originally in-line with OMX values, but this 4225 // correspondence is no longer maintained. 4226 4227 // Profiles and levels for AVC Codec, corresponding to the definitions in 4228 // "SERIES H: AUDIOVISUAL AND MULTIMEDIA SYSTEMS, 4229 // Infrastructure of audiovisual services – Coding of moving video 4230 // Advanced video coding for generic audiovisual services" 4231 // found at 4232 // https://www.itu.int/rec/T-REC-H.264-201704-I 4233 4234 /** 4235 * AVC Baseline profile. 4236 * See definition in 4237 * <a href="https://www.itu.int/rec/T-REC-H.264-201704-I">H.264 recommendation</a>, 4238 * Annex A. 4239 */ 4240 public static final int AVCProfileBaseline = 0x01; 4241 4242 /** 4243 * AVC Main profile. 4244 * See definition in 4245 * <a href="https://www.itu.int/rec/T-REC-H.264-201704-I">H.264 recommendation</a>, 4246 * Annex A. 4247 */ 4248 public static final int AVCProfileMain = 0x02; 4249 4250 /** 4251 * AVC Extended profile. 4252 * See definition in 4253 * <a href="https://www.itu.int/rec/T-REC-H.264-201704-I">H.264 recommendation</a>, 4254 * Annex A. 4255 */ 4256 public static final int AVCProfileExtended = 0x04; 4257 4258 /** 4259 * AVC High profile. 4260 * See definition in 4261 * <a href="https://www.itu.int/rec/T-REC-H.264-201704-I">H.264 recommendation</a>, 4262 * Annex A. 4263 */ 4264 public static final int AVCProfileHigh = 0x08; 4265 4266 /** 4267 * AVC High 10 profile. 4268 * See definition in 4269 * <a href="https://www.itu.int/rec/T-REC-H.264-201704-I">H.264 recommendation</a>, 4270 * Annex A. 4271 */ 4272 public static final int AVCProfileHigh10 = 0x10; 4273 4274 /** 4275 * AVC High 4:2:2 profile. 4276 * See definition in 4277 * <a href="https://www.itu.int/rec/T-REC-H.264-201704-I">H.264 recommendation</a>, 4278 * Annex A. 4279 */ 4280 public static final int AVCProfileHigh422 = 0x20; 4281 4282 /** 4283 * AVC High 4:4:4 profile. 4284 * See definition in 4285 * <a href="https://www.itu.int/rec/T-REC-H.264-201704-I">H.264 recommendation</a>, 4286 * Annex A. 4287 */ 4288 public static final int AVCProfileHigh444 = 0x40; 4289 4290 /** 4291 * AVC Constrained Baseline profile. 4292 * See definition in 4293 * <a href="https://www.itu.int/rec/T-REC-H.264-201704-I">H.264 recommendation</a>, 4294 * Annex A. 4295 */ 4296 public static final int AVCProfileConstrainedBaseline = 0x10000; 4297 4298 /** 4299 * AVC Constrained High profile. 4300 * See definition in 4301 * <a href="https://www.itu.int/rec/T-REC-H.264-201704-I">H.264 recommendation</a>, 4302 * Annex A. 4303 */ 4304 public static final int AVCProfileConstrainedHigh = 0x80000; 4305 4306 public static final int AVCLevel1 = 0x01; 4307 public static final int AVCLevel1b = 0x02; 4308 public static final int AVCLevel11 = 0x04; 4309 public static final int AVCLevel12 = 0x08; 4310 public static final int AVCLevel13 = 0x10; 4311 public static final int AVCLevel2 = 0x20; 4312 public static final int AVCLevel21 = 0x40; 4313 public static final int AVCLevel22 = 0x80; 4314 public static final int AVCLevel3 = 0x100; 4315 public static final int AVCLevel31 = 0x200; 4316 public static final int AVCLevel32 = 0x400; 4317 public static final int AVCLevel4 = 0x800; 4318 public static final int AVCLevel41 = 0x1000; 4319 public static final int AVCLevel42 = 0x2000; 4320 public static final int AVCLevel5 = 0x4000; 4321 public static final int AVCLevel51 = 0x8000; 4322 public static final int AVCLevel52 = 0x10000; 4323 public static final int AVCLevel6 = 0x20000; 4324 public static final int AVCLevel61 = 0x40000; 4325 public static final int AVCLevel62 = 0x80000; 4326 4327 public static final int H263ProfileBaseline = 0x01; 4328 public static final int H263ProfileH320Coding = 0x02; 4329 public static final int H263ProfileBackwardCompatible = 0x04; 4330 public static final int H263ProfileISWV2 = 0x08; 4331 public static final int H263ProfileISWV3 = 0x10; 4332 public static final int H263ProfileHighCompression = 0x20; 4333 public static final int H263ProfileInternet = 0x40; 4334 public static final int H263ProfileInterlace = 0x80; 4335 public static final int H263ProfileHighLatency = 0x100; 4336 4337 public static final int H263Level10 = 0x01; 4338 public static final int H263Level20 = 0x02; 4339 public static final int H263Level30 = 0x04; 4340 public static final int H263Level40 = 0x08; 4341 public static final int H263Level45 = 0x10; 4342 public static final int H263Level50 = 0x20; 4343 public static final int H263Level60 = 0x40; 4344 public static final int H263Level70 = 0x80; 4345 4346 public static final int MPEG4ProfileSimple = 0x01; 4347 public static final int MPEG4ProfileSimpleScalable = 0x02; 4348 public static final int MPEG4ProfileCore = 0x04; 4349 public static final int MPEG4ProfileMain = 0x08; 4350 public static final int MPEG4ProfileNbit = 0x10; 4351 public static final int MPEG4ProfileScalableTexture = 0x20; 4352 public static final int MPEG4ProfileSimpleFace = 0x40; 4353 public static final int MPEG4ProfileSimpleFBA = 0x80; 4354 public static final int MPEG4ProfileBasicAnimated = 0x100; 4355 public static final int MPEG4ProfileHybrid = 0x200; 4356 public static final int MPEG4ProfileAdvancedRealTime = 0x400; 4357 public static final int MPEG4ProfileCoreScalable = 0x800; 4358 public static final int MPEG4ProfileAdvancedCoding = 0x1000; 4359 public static final int MPEG4ProfileAdvancedCore = 0x2000; 4360 public static final int MPEG4ProfileAdvancedScalable = 0x4000; 4361 public static final int MPEG4ProfileAdvancedSimple = 0x8000; 4362 4363 public static final int MPEG4Level0 = 0x01; 4364 public static final int MPEG4Level0b = 0x02; 4365 public static final int MPEG4Level1 = 0x04; 4366 public static final int MPEG4Level2 = 0x08; 4367 public static final int MPEG4Level3 = 0x10; 4368 public static final int MPEG4Level3b = 0x18; 4369 public static final int MPEG4Level4 = 0x20; 4370 public static final int MPEG4Level4a = 0x40; 4371 public static final int MPEG4Level5 = 0x80; 4372 public static final int MPEG4Level6 = 0x100; 4373 4374 public static final int MPEG2ProfileSimple = 0x00; 4375 public static final int MPEG2ProfileMain = 0x01; 4376 public static final int MPEG2Profile422 = 0x02; 4377 public static final int MPEG2ProfileSNR = 0x03; 4378 public static final int MPEG2ProfileSpatial = 0x04; 4379 public static final int MPEG2ProfileHigh = 0x05; 4380 4381 public static final int MPEG2LevelLL = 0x00; 4382 public static final int MPEG2LevelML = 0x01; 4383 public static final int MPEG2LevelH14 = 0x02; 4384 public static final int MPEG2LevelHL = 0x03; 4385 public static final int MPEG2LevelHP = 0x04; 4386 4387 public static final int AACObjectMain = 1; 4388 public static final int AACObjectLC = 2; 4389 public static final int AACObjectSSR = 3; 4390 public static final int AACObjectLTP = 4; 4391 public static final int AACObjectHE = 5; 4392 public static final int AACObjectScalable = 6; 4393 public static final int AACObjectERLC = 17; 4394 public static final int AACObjectERScalable = 20; 4395 public static final int AACObjectLD = 23; 4396 public static final int AACObjectHE_PS = 29; 4397 public static final int AACObjectELD = 39; 4398 /** xHE-AAC (includes USAC) */ 4399 public static final int AACObjectXHE = 42; 4400 4401 public static final int VP8Level_Version0 = 0x01; 4402 public static final int VP8Level_Version1 = 0x02; 4403 public static final int VP8Level_Version2 = 0x04; 4404 public static final int VP8Level_Version3 = 0x08; 4405 4406 public static final int VP8ProfileMain = 0x01; 4407 4408 /** VP9 Profile 0 4:2:0 8-bit */ 4409 public static final int VP9Profile0 = 0x01; 4410 4411 /** VP9 Profile 1 4:2:2 8-bit */ 4412 public static final int VP9Profile1 = 0x02; 4413 4414 /** VP9 Profile 2 4:2:0 10-bit */ 4415 public static final int VP9Profile2 = 0x04; 4416 4417 /** VP9 Profile 3 4:2:2 10-bit */ 4418 public static final int VP9Profile3 = 0x08; 4419 4420 // HDR profiles also support passing HDR metadata 4421 /** VP9 Profile 2 4:2:0 10-bit HDR */ 4422 public static final int VP9Profile2HDR = 0x1000; 4423 4424 /** VP9 Profile 3 4:2:2 10-bit HDR */ 4425 public static final int VP9Profile3HDR = 0x2000; 4426 4427 /** VP9 Profile 2 4:2:0 10-bit HDR10Plus */ 4428 public static final int VP9Profile2HDR10Plus = 0x4000; 4429 4430 /** VP9 Profile 3 4:2:2 10-bit HDR10Plus */ 4431 public static final int VP9Profile3HDR10Plus = 0x8000; 4432 4433 public static final int VP9Level1 = 0x1; 4434 public static final int VP9Level11 = 0x2; 4435 public static final int VP9Level2 = 0x4; 4436 public static final int VP9Level21 = 0x8; 4437 public static final int VP9Level3 = 0x10; 4438 public static final int VP9Level31 = 0x20; 4439 public static final int VP9Level4 = 0x40; 4440 public static final int VP9Level41 = 0x80; 4441 public static final int VP9Level5 = 0x100; 4442 public static final int VP9Level51 = 0x200; 4443 public static final int VP9Level52 = 0x400; 4444 public static final int VP9Level6 = 0x800; 4445 public static final int VP9Level61 = 0x1000; 4446 public static final int VP9Level62 = 0x2000; 4447 4448 public static final int HEVCProfileMain = 0x01; 4449 public static final int HEVCProfileMain10 = 0x02; 4450 public static final int HEVCProfileMainStill = 0x04; 4451 public static final int HEVCProfileMain10HDR10 = 0x1000; 4452 public static final int HEVCProfileMain10HDR10Plus = 0x2000; 4453 4454 public static final int HEVCMainTierLevel1 = 0x1; 4455 public static final int HEVCHighTierLevel1 = 0x2; 4456 public static final int HEVCMainTierLevel2 = 0x4; 4457 public static final int HEVCHighTierLevel2 = 0x8; 4458 public static final int HEVCMainTierLevel21 = 0x10; 4459 public static final int HEVCHighTierLevel21 = 0x20; 4460 public static final int HEVCMainTierLevel3 = 0x40; 4461 public static final int HEVCHighTierLevel3 = 0x80; 4462 public static final int HEVCMainTierLevel31 = 0x100; 4463 public static final int HEVCHighTierLevel31 = 0x200; 4464 public static final int HEVCMainTierLevel4 = 0x400; 4465 public static final int HEVCHighTierLevel4 = 0x800; 4466 public static final int HEVCMainTierLevel41 = 0x1000; 4467 public static final int HEVCHighTierLevel41 = 0x2000; 4468 public static final int HEVCMainTierLevel5 = 0x4000; 4469 public static final int HEVCHighTierLevel5 = 0x8000; 4470 public static final int HEVCMainTierLevel51 = 0x10000; 4471 public static final int HEVCHighTierLevel51 = 0x20000; 4472 public static final int HEVCMainTierLevel52 = 0x40000; 4473 public static final int HEVCHighTierLevel52 = 0x80000; 4474 public static final int HEVCMainTierLevel6 = 0x100000; 4475 public static final int HEVCHighTierLevel6 = 0x200000; 4476 public static final int HEVCMainTierLevel61 = 0x400000; 4477 public static final int HEVCHighTierLevel61 = 0x800000; 4478 public static final int HEVCMainTierLevel62 = 0x1000000; 4479 public static final int HEVCHighTierLevel62 = 0x2000000; 4480 4481 private static final int HEVCHighTierLevels = 4482 HEVCHighTierLevel1 | HEVCHighTierLevel2 | HEVCHighTierLevel21 | HEVCHighTierLevel3 | 4483 HEVCHighTierLevel31 | HEVCHighTierLevel4 | HEVCHighTierLevel41 | HEVCHighTierLevel5 | 4484 HEVCHighTierLevel51 | HEVCHighTierLevel52 | HEVCHighTierLevel6 | HEVCHighTierLevel61 | 4485 HEVCHighTierLevel62; 4486 4487 public static final int DolbyVisionProfileDvavPer = 0x1; 4488 public static final int DolbyVisionProfileDvavPen = 0x2; 4489 public static final int DolbyVisionProfileDvheDer = 0x4; 4490 public static final int DolbyVisionProfileDvheDen = 0x8; 4491 public static final int DolbyVisionProfileDvheDtr = 0x10; 4492 public static final int DolbyVisionProfileDvheStn = 0x20; 4493 public static final int DolbyVisionProfileDvheDth = 0x40; 4494 public static final int DolbyVisionProfileDvheDtb = 0x80; 4495 public static final int DolbyVisionProfileDvheSt = 0x100; 4496 public static final int DolbyVisionProfileDvavSe = 0x200; 4497 /** Dolby Vision AV1 profile */ 4498 @SuppressLint("AllUpper") 4499 public static final int DolbyVisionProfileDvav110 = 0x400; 4500 4501 public static final int DolbyVisionLevelHd24 = 0x1; 4502 public static final int DolbyVisionLevelHd30 = 0x2; 4503 public static final int DolbyVisionLevelFhd24 = 0x4; 4504 public static final int DolbyVisionLevelFhd30 = 0x8; 4505 public static final int DolbyVisionLevelFhd60 = 0x10; 4506 public static final int DolbyVisionLevelUhd24 = 0x20; 4507 public static final int DolbyVisionLevelUhd30 = 0x40; 4508 public static final int DolbyVisionLevelUhd48 = 0x80; 4509 public static final int DolbyVisionLevelUhd60 = 0x100; 4510 @SuppressLint("AllUpper") 4511 public static final int DolbyVisionLevelUhd120 = 0x200; 4512 @SuppressLint("AllUpper") 4513 public static final int DolbyVisionLevel8k30 = 0x400; 4514 @SuppressLint("AllUpper") 4515 public static final int DolbyVisionLevel8k60 = 0x800; 4516 4517 // Profiles and levels for AV1 Codec, corresponding to the definitions in 4518 // "AV1 Bitstream & Decoding Process Specification", Annex A 4519 // found at https://aomedia.org/av1-bitstream-and-decoding-process-specification/ 4520 4521 /** 4522 * AV1 Main profile 4:2:0 8-bit 4523 * 4524 * See definition in 4525 * <a href="https://aomedia.org/av1-bitstream-and-decoding-process-specification/">AV1 Specification</a> 4526 * Annex A. 4527 */ 4528 public static final int AV1ProfileMain8 = 0x1; 4529 4530 /** 4531 * AV1 Main profile 4:2:0 10-bit 4532 * 4533 * See definition in 4534 * <a href="https://aomedia.org/av1-bitstream-and-decoding-process-specification/">AV1 Specification</a> 4535 * Annex A. 4536 */ 4537 public static final int AV1ProfileMain10 = 0x2; 4538 4539 4540 /** AV1 Main profile 4:2:0 10-bit with HDR10. */ 4541 public static final int AV1ProfileMain10HDR10 = 0x1000; 4542 4543 /** AV1 Main profile 4:2:0 10-bit with HDR10Plus. */ 4544 public static final int AV1ProfileMain10HDR10Plus = 0x2000; 4545 4546 public static final int AV1Level2 = 0x1; 4547 public static final int AV1Level21 = 0x2; 4548 public static final int AV1Level22 = 0x4; 4549 public static final int AV1Level23 = 0x8; 4550 public static final int AV1Level3 = 0x10; 4551 public static final int AV1Level31 = 0x20; 4552 public static final int AV1Level32 = 0x40; 4553 public static final int AV1Level33 = 0x80; 4554 public static final int AV1Level4 = 0x100; 4555 public static final int AV1Level41 = 0x200; 4556 public static final int AV1Level42 = 0x400; 4557 public static final int AV1Level43 = 0x800; 4558 public static final int AV1Level5 = 0x1000; 4559 public static final int AV1Level51 = 0x2000; 4560 public static final int AV1Level52 = 0x4000; 4561 public static final int AV1Level53 = 0x8000; 4562 public static final int AV1Level6 = 0x10000; 4563 public static final int AV1Level61 = 0x20000; 4564 public static final int AV1Level62 = 0x40000; 4565 public static final int AV1Level63 = 0x80000; 4566 public static final int AV1Level7 = 0x100000; 4567 public static final int AV1Level71 = 0x200000; 4568 public static final int AV1Level72 = 0x400000; 4569 public static final int AV1Level73 = 0x800000; 4570 4571 /** DTS codec profile for DTS HRA. */ 4572 @SuppressLint("AllUpper") 4573 public static final int DTS_HDProfileHRA = 0x1; 4574 /** DTS codec profile for DTS Express. */ 4575 @SuppressLint("AllUpper") 4576 public static final int DTS_HDProfileLBR = 0x2; 4577 /** DTS codec profile for DTS-HD Master Audio */ 4578 @SuppressLint("AllUpper") 4579 public static final int DTS_HDProfileMA = 0x4; 4580 /** DTS codec profile for DTS:X Profile 1 */ 4581 @SuppressLint("AllUpper") 4582 public static final int DTS_UHDProfileP1 = 0x1; 4583 /** DTS codec profile for DTS:X Profile 2 */ 4584 @SuppressLint("AllUpper") 4585 public static final int DTS_UHDProfileP2 = 0x2; 4586 4587 // Profiles and levels for AC-4 Codec, corresponding to the definitions in 4588 // "The MIME codecs parameter", Annex E.13 4589 // found at https://www.etsi.org/deliver/etsi_ts/103100_103199/10319002/01.02.01_60/ts_10319002v010201p.pdf 4590 // profile = ((1 << bitstream_version) << 8) | (1 << presentation_version); 4591 // level = 1 << mdcompat; 4592 4593 @SuppressLint("AllUpper") 4594 private static final int AC4BitstreamVersion0 = 0x01; 4595 @SuppressLint("AllUpper") 4596 private static final int AC4BitstreamVersion1 = 0x02; 4597 @SuppressLint("AllUpper") 4598 private static final int AC4BitstreamVersion2 = 0x04; 4599 4600 @SuppressLint("AllUpper") 4601 private static final int AC4PresentationVersion0 = 0x01; 4602 @SuppressLint("AllUpper") 4603 private static final int AC4PresentationVersion1 = 0x02; 4604 @SuppressLint("AllUpper") 4605 private static final int AC4PresentationVersion2 = 0x04; 4606 4607 /** 4608 * AC-4 codec profile with bitstream_version 0 and presentation_version 0 4609 * as per ETSI TS 103 190-2 v1.2.1 4610 */ 4611 @SuppressLint("AllUpper") 4612 public static final int AC4Profile00 = AC4BitstreamVersion0 << 8 | AC4PresentationVersion0; 4613 4614 /** 4615 * AC-4 codec profile with bitstream_version 1 and presentation_version 0 4616 * as per ETSI TS 103 190-2 v1.2.1 4617 */ 4618 @SuppressLint("AllUpper") 4619 public static final int AC4Profile10 = AC4BitstreamVersion1 << 8 | AC4PresentationVersion0; 4620 4621 /** 4622 * AC-4 codec profile with bitstream_version 1 and presentation_version 1 4623 * as per ETSI TS 103 190-2 v1.2.1 4624 */ 4625 @SuppressLint("AllUpper") 4626 public static final int AC4Profile11 = AC4BitstreamVersion1 << 8 | AC4PresentationVersion1; 4627 4628 /** 4629 * AC-4 codec profile with bitstream_version 2 and presentation_version 1 4630 * as per ETSI TS 103 190-2 v1.2.1 4631 */ 4632 @SuppressLint("AllUpper") 4633 public static final int AC4Profile21 = AC4BitstreamVersion2 << 8 | AC4PresentationVersion1; 4634 4635 /** 4636 * AC-4 codec profile with bitstream_version 2 and presentation_version 2 4637 * as per ETSI TS 103 190-2 v1.2.1 4638 */ 4639 @SuppressLint("AllUpper") 4640 public static final int AC4Profile22 = AC4BitstreamVersion2 << 8 | AC4PresentationVersion2; 4641 4642 /** AC-4 codec level corresponding to mdcompat 0 as per ETSI TS 103 190-2 v1.2.1 */ 4643 @SuppressLint("AllUpper") 4644 public static final int AC4Level0 = 0x01; 4645 /** AC-4 codec level corresponding to mdcompat 1 as per ETSI TS 103 190-2 v1.2.1 */ 4646 @SuppressLint("AllUpper") 4647 public static final int AC4Level1 = 0x02; 4648 /** AC-4 codec level corresponding to mdcompat 2 as per ETSI TS 103 190-2 v1.2.1 */ 4649 @SuppressLint("AllUpper") 4650 public static final int AC4Level2 = 0x04; 4651 /** AC-4 codec level corresponding to mdcompat 3 as per ETSI TS 103 190-2 v1.2.1 */ 4652 @SuppressLint("AllUpper") 4653 public static final int AC4Level3 = 0x08; 4654 /** AC-4 codec level corresponding to mdcompat 4 as per ETSI TS 103 190-2 v1.2.1 */ 4655 @SuppressLint("AllUpper") 4656 public static final int AC4Level4 = 0x10; 4657 4658 // Profiles and levels/bands for APV Codec, corresponding to the definitions in 4659 // "Advanced Professional Video", 10.1.3 Profiles, 10.1.4 Levels and Bands 4660 // found at https://www.ietf.org/archive/id/draft-lim-apv-02.html 4661 4662 /** 4663 * APV codec profile 422-10 as per IETF lim-apv-02, 10.1.3.1.1 4664 */ 4665 @SuppressLint("AllUpper") 4666 @FlaggedApi(FLAG_APV_SUPPORT) 4667 public static final int APVProfile422_10 = 0x01; 4668 4669 /** 4670 * APV codec profile 422-10 as per IETF lim-apv-02, 10.1.3.1.1 4671 * with HDR10. 4672 */ 4673 @SuppressLint("AllUpper") 4674 @FlaggedApi(FLAG_APV_SUPPORT) 4675 public static final int APVProfile422_10HDR10 = 0x1000; 4676 4677 /** 4678 * APV codec profile 422-10 as per IETF lim-apv-02, 10.1.3.1.1 4679 * with HDR10Plus. 4680 */ 4681 @SuppressLint("AllUpper") 4682 @FlaggedApi(FLAG_APV_SUPPORT) 4683 public static final int APVProfile422_10HDR10Plus = 0x2000; 4684 4685 // For APV Levels, the numerical values are constructed as follows: 4686 // ((0x100 << (level_num - 1)) | (1 << band)) 4687 // where: 4688 // - "level_num" is the APV Level numbered consecutively 4689 // (i.e., Level 1 == 1, Level 1.1 == 2, etc.) 4690 // - "band" is the APV Band 4691 4692 /** APV Codec Level 1, Band 0 as per IETF lim-apv-02, 10.1.4 */ 4693 @SuppressLint("AllUpper") 4694 @FlaggedApi(FLAG_APV_SUPPORT) 4695 public static final int APVLevel1Band0 = 0x101; 4696 /** APV Codec Level 1, Band 1 as per IETF lim-apv-02, 10.1.4 */ 4697 @SuppressLint("AllUpper") 4698 @FlaggedApi(FLAG_APV_SUPPORT) 4699 public static final int APVLevel1Band1 = 0x102; 4700 /** APV Codec Level 1, Band 2 as per IETF lim-apv-02, 10.1.4 */ 4701 @SuppressLint("AllUpper") 4702 @FlaggedApi(FLAG_APV_SUPPORT) 4703 public static final int APVLevel1Band2 = 0x104; 4704 /** APV Codec Level 1, Band 3 as per IETF lim-apv-02, 10.1.4 */ 4705 @SuppressLint("AllUpper") 4706 @FlaggedApi(FLAG_APV_SUPPORT) 4707 public static final int APVLevel1Band3 = 0x108; 4708 /** APV Codec Level 1.1, Band 0 as per IETF lim-apv-02, 10.1.4 */ 4709 @SuppressLint("AllUpper") 4710 @FlaggedApi(FLAG_APV_SUPPORT) 4711 public static final int APVLevel11Band0 = 0x201; 4712 /** APV Codec Level 1.1, Band 1 as per IETF lim-apv-02, 10.1.4 */ 4713 @SuppressLint("AllUpper") 4714 @FlaggedApi(FLAG_APV_SUPPORT) 4715 public static final int APVLevel11Band1 = 0x202; 4716 /** APV Codec Level 1.1, Band 2 as per IETF lim-apv-02, 10.1.4 */ 4717 @SuppressLint("AllUpper") 4718 @FlaggedApi(FLAG_APV_SUPPORT) 4719 public static final int APVLevel11Band2 = 0x204; 4720 /** APV Codec Level 1.1, Band 3 as per IETF lim-apv-02, 10.1.4 */ 4721 @SuppressLint("AllUpper") 4722 @FlaggedApi(FLAG_APV_SUPPORT) 4723 public static final int APVLevel11Band3 = 0x208; 4724 /** APV Codec Level 2, Band 0 as per IETF lim-apv-02, 10.1.4 */ 4725 @SuppressLint("AllUpper") 4726 @FlaggedApi(FLAG_APV_SUPPORT) 4727 public static final int APVLevel2Band0 = 0x401; 4728 /** APV Codec Level 2, Band 1 as per IETF lim-apv-02, 10.1.4 */ 4729 @SuppressLint("AllUpper") 4730 @FlaggedApi(FLAG_APV_SUPPORT) 4731 public static final int APVLevel2Band1 = 0x402; 4732 /** APV Codec Level 2, Band 2 as per IETF lim-apv-02, 10.1.4 */ 4733 @SuppressLint("AllUpper") 4734 @FlaggedApi(FLAG_APV_SUPPORT) 4735 public static final int APVLevel2Band2 = 0x404; 4736 /** APV Codec Level 2, Band 3 as per IETF lim-apv-02, 10.1.4 */ 4737 @SuppressLint("AllUpper") 4738 @FlaggedApi(FLAG_APV_SUPPORT) 4739 public static final int APVLevel2Band3 = 0x408; 4740 /** APV Codec Level 2.1, Band 0 as per IETF lim-apv-02, 10.1.4 */ 4741 @SuppressLint("AllUpper") 4742 @FlaggedApi(FLAG_APV_SUPPORT) 4743 public static final int APVLevel21Band0 = 0x801; 4744 /** APV Codec Level 2.1, Band 1 as per IETF lim-apv-02, 10.1.4 */ 4745 @SuppressLint("AllUpper") 4746 @FlaggedApi(FLAG_APV_SUPPORT) 4747 public static final int APVLevel21Band1 = 0x802; 4748 /** APV Codec Level 2.1, Band 2 as per IETF lim-apv-02, 10.1.4 */ 4749 @SuppressLint("AllUpper") 4750 @FlaggedApi(FLAG_APV_SUPPORT) 4751 public static final int APVLevel21Band2 = 0x804; 4752 /** APV Codec Level 2.1, Band 3 as per IETF lim-apv-02, 10.1.4 */ 4753 @SuppressLint("AllUpper") 4754 @FlaggedApi(FLAG_APV_SUPPORT) 4755 public static final int APVLevel21Band3 = 0x808; 4756 /** APV Codec Level 3, Band 0 as per IETF lim-apv-02, 10.1.4 */ 4757 @SuppressLint("AllUpper") 4758 @FlaggedApi(FLAG_APV_SUPPORT) 4759 public static final int APVLevel3Band0 = 0x1001; 4760 /** APV Codec Level 3, Band 1 as per IETF lim-apv-02, 10.1.4 */ 4761 @SuppressLint("AllUpper") 4762 @FlaggedApi(FLAG_APV_SUPPORT) 4763 public static final int APVLevel3Band1 = 0x1002; 4764 /** APV Codec Level 3, Band 2 as per IETF lim-apv-02, 10.1.4 */ 4765 @SuppressLint("AllUpper") 4766 @FlaggedApi(FLAG_APV_SUPPORT) 4767 public static final int APVLevel3Band2 = 0x1004; 4768 /** APV Codec Level 3, Band 3 as per IETF lim-apv-02, 10.1.4 */ 4769 @SuppressLint("AllUpper") 4770 @FlaggedApi(FLAG_APV_SUPPORT) 4771 public static final int APVLevel3Band3 = 0x1008; 4772 /** APV Codec Level 3.1, Band 0 as per IETF lim-apv-02, 10.1.4 */ 4773 @SuppressLint("AllUpper") 4774 @FlaggedApi(FLAG_APV_SUPPORT) 4775 public static final int APVLevel31Band0 = 0x2001; 4776 /** APV Codec Level 3.1, Band 1 as per IETF lim-apv-02, 10.1.4 */ 4777 @SuppressLint("AllUpper") 4778 @FlaggedApi(FLAG_APV_SUPPORT) 4779 public static final int APVLevel31Band1 = 0x2002; 4780 /** APV Codec Level 3.1, Band 2 as per IETF lim-apv-02, 10.1.4 */ 4781 @SuppressLint("AllUpper") 4782 @FlaggedApi(FLAG_APV_SUPPORT) 4783 public static final int APVLevel31Band2 = 0x2004; 4784 /** APV Codec Level 3.1, Band 3 as per IETF lim-apv-02, 10.1.4 */ 4785 @SuppressLint("AllUpper") 4786 @FlaggedApi(FLAG_APV_SUPPORT) 4787 public static final int APVLevel31Band3 = 0x2008; 4788 /** APV Codec Level 4, Band 0 as per IETF lim-apv-02, 10.1.4 */ 4789 @SuppressLint("AllUpper") 4790 @FlaggedApi(FLAG_APV_SUPPORT) 4791 public static final int APVLevel4Band0 = 0x4001; 4792 /** APV Codec Level 4, Band 1 as per IETF lim-apv-02, 10.1.4 */ 4793 @SuppressLint("AllUpper") 4794 @FlaggedApi(FLAG_APV_SUPPORT) 4795 public static final int APVLevel4Band1 = 0x4002; 4796 /** APV Codec Level 4, Band 2 as per IETF lim-apv-02, 10.1.4 */ 4797 @SuppressLint("AllUpper") 4798 @FlaggedApi(FLAG_APV_SUPPORT) 4799 public static final int APVLevel4Band2 = 0x4004; 4800 /** APV Codec Level 4, Band 3 as per IETF lim-apv-02, 10.1.4 */ 4801 @SuppressLint("AllUpper") 4802 @FlaggedApi(FLAG_APV_SUPPORT) 4803 public static final int APVLevel4Band3 = 0x4008; 4804 /** APV Codec Level 4.1, Band 0 as per IETF lim-apv-02, 10.1.4 */ 4805 @SuppressLint("AllUpper") 4806 @FlaggedApi(FLAG_APV_SUPPORT) 4807 public static final int APVLevel41Band0 = 0x8001; 4808 /** APV Codec Level 4.1, Band 1 as per IETF lim-apv-02, 10.1.4 */ 4809 @SuppressLint("AllUpper") 4810 @FlaggedApi(FLAG_APV_SUPPORT) 4811 public static final int APVLevel41Band1 = 0x8002; 4812 /** APV Codec Level 4.1, Band 2 as per IETF lim-apv-02, 10.1.4 */ 4813 @SuppressLint("AllUpper") 4814 @FlaggedApi(FLAG_APV_SUPPORT) 4815 public static final int APVLevel41Band2 = 0x8004; 4816 /** APV Codec Level 4.1, Band 3 as per IETF lim-apv-02, 10.1.4 */ 4817 @SuppressLint("AllUpper") 4818 @FlaggedApi(FLAG_APV_SUPPORT) 4819 public static final int APVLevel41Band3 = 0x8008; 4820 /** APV Codec Level 5, Band 0 as per IETF lim-apv-02, 10.1.4 */ 4821 @SuppressLint("AllUpper") 4822 @FlaggedApi(FLAG_APV_SUPPORT) 4823 public static final int APVLevel5Band0 = 0x10001; 4824 /** APV Codec Level 5, Band 1 as per IETF lim-apv-02, 10.1.4 */ 4825 @SuppressLint("AllUpper") 4826 @FlaggedApi(FLAG_APV_SUPPORT) 4827 public static final int APVLevel5Band1 = 0x10002; 4828 /** APV Codec Level 5, Band 2 as per IETF lim-apv-02, 10.1.4 */ 4829 @SuppressLint("AllUpper") 4830 @FlaggedApi(FLAG_APV_SUPPORT) 4831 public static final int APVLevel5Band2 = 0x10004; 4832 /** APV Codec Level 5, Band 3 as per IETF lim-apv-02, 10.1.4 */ 4833 @SuppressLint("AllUpper") 4834 @FlaggedApi(FLAG_APV_SUPPORT) 4835 public static final int APVLevel5Band3 = 0x10008; 4836 /** APV Codec Level 5.1, Band 0 as per IETF lim-apv-02, 10.1.4 */ 4837 @SuppressLint("AllUpper") 4838 @FlaggedApi(FLAG_APV_SUPPORT) 4839 public static final int APVLevel51Band0 = 0x20001; 4840 /** APV Codec Level 5.1, Band 1 as per IETF lim-apv-02, 10.1.4 */ 4841 @SuppressLint("AllUpper") 4842 @FlaggedApi(FLAG_APV_SUPPORT) 4843 public static final int APVLevel51Band1 = 0x20002; 4844 /** APV Codec Level 5.1, Band 2 as per IETF lim-apv-02, 10.1.4 */ 4845 @SuppressLint("AllUpper") 4846 @FlaggedApi(FLAG_APV_SUPPORT) 4847 public static final int APVLevel51Band2 = 0x20004; 4848 /** APV Codec Level 5.1, Band 3 as per IETF lim-apv-02, 10.1.4 */ 4849 @SuppressLint("AllUpper") 4850 @FlaggedApi(FLAG_APV_SUPPORT) 4851 public static final int APVLevel51Band3 = 0x20008; 4852 /** APV Codec Level 6, Band 0 as per IETF lim-apv-02, 10.1.4 */ 4853 @SuppressLint("AllUpper") 4854 @FlaggedApi(FLAG_APV_SUPPORT) 4855 public static final int APVLevel6Band0 = 0x40001; 4856 /** APV Codec Level 6, Band 1 as per IETF lim-apv-02, 10.1.4 */ 4857 @SuppressLint("AllUpper") 4858 @FlaggedApi(FLAG_APV_SUPPORT) 4859 public static final int APVLevel6Band1 = 0x40002; 4860 /** APV Codec Level 6, Band 2 as per IETF lim-apv-02, 10.1.4 */ 4861 @SuppressLint("AllUpper") 4862 @FlaggedApi(FLAG_APV_SUPPORT) 4863 public static final int APVLevel6Band2 = 0x40004; 4864 /** APV Codec Level 6, Band 3 as per IETF lim-apv-02, 10.1.4 */ 4865 @SuppressLint("AllUpper") 4866 @FlaggedApi(FLAG_APV_SUPPORT) 4867 public static final int APVLevel6Band3 = 0x40008; 4868 /** APV Codec Level 6.1, Band 0 as per IETF lim-apv-02, 10.1.4 */ 4869 @SuppressLint("AllUpper") 4870 @FlaggedApi(FLAG_APV_SUPPORT) 4871 public static final int APVLevel61Band0 = 0x80001; 4872 /** APV Codec Level 6.1, Band 1 as per IETF lim-apv-02, 10.1.4 */ 4873 @SuppressLint("AllUpper") 4874 @FlaggedApi(FLAG_APV_SUPPORT) 4875 public static final int APVLevel61Band1 = 0x80002; 4876 /** APV Codec Level 6.1, Band 2 as per IETF lim-apv-02, 10.1.4 */ 4877 @SuppressLint("AllUpper") 4878 @FlaggedApi(FLAG_APV_SUPPORT) 4879 public static final int APVLevel61Band2 = 0x80004; 4880 /** APV Codec Level 6.1, Band 3 as per IETF lim-apv-02, 10.1.4 */ 4881 @SuppressLint("AllUpper") 4882 @FlaggedApi(FLAG_APV_SUPPORT) 4883 public static final int APVLevel61Band3 = 0x80008; 4884 /** APV Codec Level 7, Band 0 as per IETF lim-apv-02, 10.1.4 */ 4885 @SuppressLint("AllUpper") 4886 @FlaggedApi(FLAG_APV_SUPPORT) 4887 public static final int APVLevel7Band0 = 0x100001; 4888 /** APV Codec Level 7, Band 1 as per IETF lim-apv-02, 10.1.4 */ 4889 @SuppressLint("AllUpper") 4890 @FlaggedApi(FLAG_APV_SUPPORT) 4891 public static final int APVLevel7Band1 = 0x100002; 4892 /** APV Codec Level 7, Band 2 as per IETF lim-apv-02, 10.1.4 */ 4893 @SuppressLint("AllUpper") 4894 @FlaggedApi(FLAG_APV_SUPPORT) 4895 public static final int APVLevel7Band2 = 0x100004; 4896 /** APV Codec Level 7, Band 3 as per IETF lim-apv-02, 10.1.4 */ 4897 @SuppressLint("AllUpper") 4898 @FlaggedApi(FLAG_APV_SUPPORT) 4899 public static final int APVLevel7Band3 = 0x100008; 4900 /** APV Codec Level 7.1, Band 0 as per IETF lim-apv-02, 10.1.4 */ 4901 @SuppressLint("AllUpper") 4902 @FlaggedApi(FLAG_APV_SUPPORT) 4903 public static final int APVLevel71Band0 = 0x200001; 4904 /** APV Codec Level 7.1, Band 1 as per IETF lim-apv-02, 10.1.4 */ 4905 @SuppressLint("AllUpper") 4906 @FlaggedApi(FLAG_APV_SUPPORT) 4907 public static final int APVLevel71Band1 = 0x200002; 4908 /** APV Codec Level 7.1, Band 2 as per IETF lim-apv-02, 10.1.4 */ 4909 @SuppressLint("AllUpper") 4910 @FlaggedApi(FLAG_APV_SUPPORT) 4911 public static final int APVLevel71Band2 = 0x200004; 4912 /** APV Codec Level 7.1, Band 3 as per IETF lim-apv-02, 10.1.4 */ 4913 @SuppressLint("AllUpper") 4914 @FlaggedApi(FLAG_APV_SUPPORT) 4915 public static final int APVLevel71Band3 = 0x200008; 4916 4917 // IAMF profiles are defined as the combination of the (listed from LSB to MSB): 4918 // - audio codec (2 bytes) 4919 // - profile (1 byte, offset 16) 4920 // - specification version (1 byte, offset 24) 4921 private static final int IAMF_CODEC_OPUS = 0x1; 4922 private static final int IAMF_CODEC_AAC = 0x1 << 1; 4923 private static final int IAMF_CODEC_FLAC = 0x1 << 2; 4924 private static final int IAMF_CODEC_PCM = 0x1 << 3; 4925 private static final int IAMF_PROFILE_SIMPLE = 0x1 << 16; 4926 private static final int IAMF_PROFILE_BASE = 0x1 << 17; 4927 private static final int IAMF_PROFILE_BASE_ENHANCED = 0x1 << 18; 4928 private static final int IAMF_v1 = 0x1 << 24; 4929 /** 4930 * IAMF profile using the 4931 * <a href="https://aomediacodec.github.io/iamf/#profiles-simple">simple profile</a> 4932 * with audio streams <a href="https://aomediacodec.github.io/iamf/#codec_id">encoded</a> 4933 * in OPUS. 4934 */ 4935 @SuppressLint("AllUpper") 4936 @FlaggedApi(FLAG_IAMF_DEFINITIONS_API) 4937 public static final int IAMFProfileSimpleOpus = 4938 IAMF_v1 + IAMF_PROFILE_SIMPLE + IAMF_CODEC_OPUS; 4939 /** 4940 * IAMF profile using the 4941 * <a href="https://aomediacodec.github.io/iamf/#profiles-simple">simple profile</a> 4942 * with audio streams <a href="https://aomediacodec.github.io/iamf/#codec_id">encoded</a> 4943 * in AAC. 4944 */ 4945 @SuppressLint("AllUpper") 4946 @FlaggedApi(FLAG_IAMF_DEFINITIONS_API) 4947 public static final int IAMFProfileSimpleAac = 4948 IAMF_v1 + IAMF_PROFILE_SIMPLE + IAMF_CODEC_AAC; 4949 /** 4950 * IAMF profile using the 4951 * <a href="https://aomediacodec.github.io/iamf/#profiles-simple">simple profile</a> 4952 * with audio streams <a href="https://aomediacodec.github.io/iamf/#codec_id">encoded</a> 4953 * in FLAC. 4954 */ 4955 @SuppressLint("AllUpper") 4956 @FlaggedApi(FLAG_IAMF_DEFINITIONS_API) 4957 public static final int IAMFProfileSimpleFlac = 4958 IAMF_v1 + IAMF_PROFILE_SIMPLE + IAMF_CODEC_FLAC; 4959 /** 4960 * IAMF profile using the 4961 * <a href="https://aomediacodec.github.io/iamf/#profiles-simple">simple profile</a> 4962 * with audio streams <a href="https://aomediacodec.github.io/iamf/#codec_id">encoded</a> 4963 * in PCM. 4964 */ 4965 @SuppressLint("AllUpper") 4966 @FlaggedApi(FLAG_IAMF_DEFINITIONS_API) 4967 public static final int IAMFProfileSimplePcm = 4968 IAMF_v1 + IAMF_PROFILE_SIMPLE + IAMF_CODEC_PCM; 4969 /** 4970 * IAMF profile using the 4971 * <a href="https://aomediacodec.github.io/iamf/#profiles-base">base profile</a> 4972 * with audio streams <a href="https://aomediacodec.github.io/iamf/#codec_id">encoded</a> 4973 * in OPUS. 4974 */ 4975 @SuppressLint("AllUpper") 4976 @FlaggedApi(FLAG_IAMF_DEFINITIONS_API) 4977 public static final int IAMFProfileBaseOpus = 4978 IAMF_v1 + IAMF_PROFILE_BASE + IAMF_CODEC_OPUS; 4979 /** 4980 * IAMF profile using the 4981 * <a href="https://aomediacodec.github.io/iamf/#profiles-base">base profile</a> 4982 * with audio streams <a href="https://aomediacodec.github.io/iamf/#codec_id">encoded</a> 4983 * in AAC. 4984 */ 4985 @SuppressLint("AllUpper") 4986 @FlaggedApi(FLAG_IAMF_DEFINITIONS_API) 4987 public static final int IAMFProfileBaseAac = 4988 IAMF_v1 + IAMF_PROFILE_BASE + IAMF_CODEC_AAC; 4989 /** 4990 * IAMF profile using the 4991 * <a href="https://aomediacodec.github.io/iamf/#profiles-base">base profile</a> 4992 * with audio streams <a href="https://aomediacodec.github.io/iamf/#codec_id">encoded</a> 4993 * in FLAC. 4994 */ 4995 @SuppressLint("AllUpper") 4996 @FlaggedApi(FLAG_IAMF_DEFINITIONS_API) 4997 public static final int IAMFProfileBaseFlac = 4998 IAMF_v1 + IAMF_PROFILE_BASE + IAMF_CODEC_FLAC; 4999 /** 5000 * IAMF profile using the 5001 * <a href="https://aomediacodec.github.io/iamf/#profiles-base">base profile</a> 5002 * with audio streams <a href="https://aomediacodec.github.io/iamf/#codec_id">encoded</a> 5003 * in PCM. 5004 */ 5005 @SuppressLint("AllUpper") 5006 @FlaggedApi(FLAG_IAMF_DEFINITIONS_API) 5007 public static final int IAMFProfileBasePcm = 5008 IAMF_v1 + IAMF_PROFILE_BASE + IAMF_CODEC_PCM; 5009 /** 5010 * IAMF profile using the 5011 * <a href="https://aomediacodec.github.io/iamf/#profiles-base-enhanced">base-enhanced profile</a> 5012 * with audio streams <a href="https://aomediacodec.github.io/iamf/#codec_id">encoded</a> 5013 * in OPUS. 5014 */ 5015 @SuppressLint("AllUpper") 5016 @FlaggedApi(FLAG_IAMF_DEFINITIONS_API) 5017 public static final int IAMFProfileBaseEnhancedOpus = 5018 IAMF_v1 + IAMF_PROFILE_BASE_ENHANCED + IAMF_CODEC_OPUS; 5019 /** 5020 * IAMF profile using the 5021 * <a href="https://aomediacodec.github.io/iamf/#profiles-base-enhanced">base-enhanced profile</a> 5022 * with audio streams <a href="https://aomediacodec.github.io/iamf/#codec_id">encoded</a> 5023 * in AAC. 5024 */ 5025 @SuppressLint("AllUpper") 5026 @FlaggedApi(FLAG_IAMF_DEFINITIONS_API) 5027 public static final int IAMFProfileBaseEnhancedAac = 5028 IAMF_v1 + IAMF_PROFILE_BASE_ENHANCED + IAMF_CODEC_AAC; 5029 /** 5030 * IAMF profile using the 5031 * <a href="https://aomediacodec.github.io/iamf/#profiles-base-enhanced">base-enhanced profile</a> 5032 * with audio streams <a href="https://aomediacodec.github.io/iamf/#codec_id">encoded</a> 5033 * in FLAC. 5034 */ 5035 @SuppressLint("AllUpper") 5036 @FlaggedApi(FLAG_IAMF_DEFINITIONS_API) 5037 public static final int IAMFProfileBaseEnhancedFlac = 5038 IAMF_v1 + IAMF_PROFILE_BASE_ENHANCED + IAMF_CODEC_FLAC; 5039 /** 5040 * IAMF profile using the 5041 * <a href="https://aomediacodec.github.io/iamf/#profiles-base-enhanced">base-enhanced profile</a> 5042 * with audio streams <a href="https://aomediacodec.github.io/iamf/#codec_id">encoded</a> 5043 * in PCM. 5044 */ 5045 @SuppressLint("AllUpper") 5046 @FlaggedApi(FLAG_IAMF_DEFINITIONS_API) 5047 public static final int IAMFProfileBaseEnhancedPcm = 5048 IAMF_v1 + IAMF_PROFILE_BASE_ENHANCED + IAMF_CODEC_PCM; 5049 5050 /** 5051 * The profile of the media content. Depending on the type of media this can be 5052 * one of the profile values defined in this class. 5053 */ 5054 public int profile; 5055 5056 /** 5057 * The level of the media content. Depending on the type of media this can be 5058 * one of the level values defined in this class. 5059 * 5060 * Note that VP9 decoder on platforms before {@link android.os.Build.VERSION_CODES#N} may 5061 * not advertise a profile level support. For those VP9 decoders, please use 5062 * {@link VideoCapabilities} to determine the codec capabilities. 5063 */ 5064 public int level; 5065 5066 @Override 5067 public boolean equals(Object obj) { 5068 if (obj == null) { 5069 return false; 5070 } 5071 if (obj instanceof CodecProfileLevel) { 5072 CodecProfileLevel other = (CodecProfileLevel)obj; 5073 return other.profile == profile && other.level == level; 5074 } 5075 return false; 5076 } 5077 5078 @Override 5079 public int hashCode() { 5080 return Long.hashCode(((long)profile << Integer.SIZE) | level); 5081 } 5082 }; 5083 5084 /** 5085 * Enumerates the capabilities of the codec component. Since a single 5086 * component can support data of a variety of types, the type has to be 5087 * specified to yield a meaningful result. 5088 * @param type The MIME type to query 5089 */ 5090 public final CodecCapabilities getCapabilitiesForType( 5091 String type) { 5092 CodecCapabilities caps = mCaps.get(type); 5093 if (caps == null) { 5094 throw new IllegalArgumentException("codec does not support type"); 5095 } 5096 // clone writable object 5097 return caps.dup(); 5098 } 5099 5100 /** @hide */ 5101 public MediaCodecInfo makeRegular() { 5102 ArrayList<CodecCapabilities> caps = new ArrayList<CodecCapabilities>(); 5103 for (CodecCapabilities c: mCaps.values()) { 5104 if (c.isRegular()) { 5105 caps.add(c); 5106 } 5107 } 5108 if (caps.size() == 0) { 5109 return null; 5110 } else if (caps.size() == mCaps.size()) { 5111 return this; 5112 } 5113 5114 return new MediaCodecInfo( 5115 mName, mCanonicalName, mFlags, 5116 caps.toArray(new CodecCapabilities[caps.size()])); 5117 } 5118 } 5119