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