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 android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.util.Log; 22 import android.util.Pair; 23 import android.util.Range; 24 import android.util.Rational; 25 import android.util.Size; 26 27 import java.util.ArrayList; 28 import java.util.Arrays; 29 import java.util.HashMap; 30 import java.util.Map; 31 import java.util.Set; 32 33 import static android.media.Utils.intersectSortedDistinctRanges; 34 import static android.media.Utils.sortDistinctRanges; 35 36 /** 37 * Provides information about a given media codec available on the device. You can 38 * iterate through all codecs available by querying {@link MediaCodecList}. For example, 39 * here's how to find an encoder that supports a given MIME type: 40 * <pre> 41 * private static MediaCodecInfo selectCodec(String mimeType) { 42 * int numCodecs = MediaCodecList.getCodecCount(); 43 * for (int i = 0; i < numCodecs; i++) { 44 * MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i); 45 * 46 * if (!codecInfo.isEncoder()) { 47 * continue; 48 * } 49 * 50 * String[] types = codecInfo.getSupportedTypes(); 51 * for (int j = 0; j < types.length; j++) { 52 * if (types[j].equalsIgnoreCase(mimeType)) { 53 * return codecInfo; 54 * } 55 * } 56 * } 57 * return null; 58 * }</pre> 59 * 60 */ 61 public final class MediaCodecInfo { 62 private boolean mIsEncoder; 63 private String mName; 64 private Map<String, CodecCapabilities> mCaps; 65 MediaCodecInfo( String name, boolean isEncoder, CodecCapabilities[] caps)66 /* package private */ MediaCodecInfo( 67 String name, boolean isEncoder, CodecCapabilities[] caps) { 68 mName = name; 69 mIsEncoder = isEncoder; 70 mCaps = new HashMap<String, CodecCapabilities>(); 71 for (CodecCapabilities c: caps) { 72 mCaps.put(c.getMimeType(), c); 73 } 74 } 75 76 /** 77 * Retrieve the codec name. 78 */ getName()79 public final String getName() { 80 return mName; 81 } 82 83 /** 84 * Query if the codec is an encoder. 85 */ isEncoder()86 public final boolean isEncoder() { 87 return mIsEncoder; 88 } 89 90 /** 91 * Query the media types supported by the codec. 92 */ getSupportedTypes()93 public final String[] getSupportedTypes() { 94 Set<String> typeSet = mCaps.keySet(); 95 String[] types = typeSet.toArray(new String[typeSet.size()]); 96 Arrays.sort(types); 97 return types; 98 } 99 checkPowerOfTwo(int value, String message)100 private static int checkPowerOfTwo(int value, String message) { 101 if ((value & (value - 1)) != 0) { 102 throw new IllegalArgumentException(message); 103 } 104 return value; 105 } 106 107 private static class Feature { 108 public String mName; 109 public int mValue; 110 public boolean mDefault; Feature(String name, int value, boolean def)111 public Feature(String name, int value, boolean def) { 112 mName = name; 113 mValue = value; 114 mDefault = def; 115 } 116 } 117 118 // COMMON CONSTANTS 119 private static final Range<Integer> POSITIVE_INTEGERS = 120 Range.create(1, Integer.MAX_VALUE); 121 private static final Range<Long> POSITIVE_LONGS = 122 Range.create(1l, Long.MAX_VALUE); 123 private static final Range<Rational> POSITIVE_RATIONALS = 124 Range.create(new Rational(1, Integer.MAX_VALUE), 125 new Rational(Integer.MAX_VALUE, 1)); 126 private static final Range<Integer> SIZE_RANGE = Range.create(1, 32768); 127 private static final Range<Integer> FRAME_RATE_RANGE = Range.create(0, 960); 128 private static final Range<Integer> BITRATE_RANGE = Range.create(0, 500000000); 129 private static final int DEFAULT_MAX_SUPPORTED_INSTANCES = 32; 130 private static final int MAX_SUPPORTED_INSTANCES_LIMIT = 256; 131 132 // found stuff that is not supported by framework (=> this should not happen) 133 private static final int ERROR_UNRECOGNIZED = (1 << 0); 134 // found profile/level for which we don't have capability estimates 135 private static final int ERROR_UNSUPPORTED = (1 << 1); 136 // have not found any profile/level for which we don't have capability estimate 137 private static final int ERROR_NONE_SUPPORTED = (1 << 2); 138 139 140 /** 141 * Encapsulates the capabilities of a given codec component. 142 * For example, what profile/level combinations it supports and what colorspaces 143 * it is capable of providing the decoded data in, as well as some 144 * codec-type specific capability flags. 145 * <p>You can get an instance for a given {@link MediaCodecInfo} object with 146 * {@link MediaCodecInfo#getCapabilitiesForType getCapabilitiesForType()}, passing a MIME type. 147 */ 148 public static final class CodecCapabilities { CodecCapabilities()149 public CodecCapabilities() { 150 } 151 152 // CLASSIFICATION 153 private String mMime; 154 private int mMaxSupportedInstances; 155 156 // LEGACY FIELDS 157 158 // Enumerates supported profile/level combinations as defined 159 // by the type of encoded data. These combinations impose restrictions 160 // on video resolution, bitrate... and limit the available encoder tools 161 // such as B-frame support, arithmetic coding... 162 public CodecProfileLevel[] profileLevels; // NOTE this array is modifiable by user 163 164 // from OMX_COLOR_FORMATTYPE 165 /** @deprecated Use {@link #COLOR_Format24bitBGR888}. */ 166 public static final int COLOR_FormatMonochrome = 1; 167 /** @deprecated Use {@link #COLOR_Format24bitBGR888}. */ 168 public static final int COLOR_Format8bitRGB332 = 2; 169 /** @deprecated Use {@link #COLOR_Format24bitBGR888}. */ 170 public static final int COLOR_Format12bitRGB444 = 3; 171 /** @deprecated Use {@link #COLOR_Format32bitABGR8888}. */ 172 public static final int COLOR_Format16bitARGB4444 = 4; 173 /** @deprecated Use {@link #COLOR_Format32bitABGR8888}. */ 174 public static final int COLOR_Format16bitARGB1555 = 5; 175 176 /** 177 * 16 bits per pixel RGB color format, with 5-bit red & blue and 6-bit green component. 178 * <p> 179 * Using 16-bit little-endian representation, colors stored as Red 15:11, Green 10:5, Blue 4:0. 180 * <pre> 181 * byte byte 182 * <--------- i --------> | <------ i + 1 ------> 183 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 184 * | BLUE | GREEN | RED | 185 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 186 * 0 4 5 7 0 2 3 7 187 * bit 188 * </pre> 189 * 190 * This format corresponds to {@link android.graphics.PixelFormat#RGB_565} and 191 * {@link android.graphics.ImageFormat#RGB_565}. 192 */ 193 public static final int COLOR_Format16bitRGB565 = 6; 194 /** @deprecated Use {@link #COLOR_Format16bitRGB565}. */ 195 public static final int COLOR_Format16bitBGR565 = 7; 196 /** @deprecated Use {@link #COLOR_Format24bitBGR888}. */ 197 public static final int COLOR_Format18bitRGB666 = 8; 198 /** @deprecated Use {@link #COLOR_Format32bitABGR8888}. */ 199 public static final int COLOR_Format18bitARGB1665 = 9; 200 /** @deprecated Use {@link #COLOR_Format32bitABGR8888}. */ 201 public static final int COLOR_Format19bitARGB1666 = 10; 202 203 /** @deprecated Use {@link #COLOR_Format24bitBGR888} or {@link #COLOR_FormatRGBFlexible}. */ 204 public static final int COLOR_Format24bitRGB888 = 11; 205 206 /** 207 * 24 bits per pixel RGB color format, with 8-bit red, green & blue components. 208 * <p> 209 * Using 24-bit little-endian representation, colors stored as Red 7:0, Green 15:8, Blue 23:16. 210 * <pre> 211 * byte byte byte 212 * <------ i -----> | <---- i+1 ----> | <---- i+2 -----> 213 * +-----------------+-----------------+-----------------+ 214 * | RED | GREEN | BLUE | 215 * +-----------------+-----------------+-----------------+ 216 * </pre> 217 * 218 * This format corresponds to {@link android.graphics.PixelFormat#RGB_888}, and can also be 219 * represented as a flexible format by {@link #COLOR_FormatRGBFlexible}. 220 */ 221 public static final int COLOR_Format24bitBGR888 = 12; 222 /** @deprecated Use {@link #COLOR_Format32bitABGR8888}. */ 223 public static final int COLOR_Format24bitARGB1887 = 13; 224 /** @deprecated Use {@link #COLOR_Format32bitABGR8888}. */ 225 public static final int COLOR_Format25bitARGB1888 = 14; 226 227 /** 228 * @deprecated Use {@link #COLOR_Format32bitABGR8888} Or {@link #COLOR_FormatRGBAFlexible}. 229 */ 230 public static final int COLOR_Format32bitBGRA8888 = 15; 231 /** 232 * @deprecated Use {@link #COLOR_Format32bitABGR8888} Or {@link #COLOR_FormatRGBAFlexible}. 233 */ 234 public static final int COLOR_Format32bitARGB8888 = 16; 235 /** @deprecated Use {@link #COLOR_FormatYUV420Flexible}. */ 236 public static final int COLOR_FormatYUV411Planar = 17; 237 /** @deprecated Use {@link #COLOR_FormatYUV420Flexible}. */ 238 public static final int COLOR_FormatYUV411PackedPlanar = 18; 239 /** @deprecated Use {@link #COLOR_FormatYUV420Flexible}. */ 240 public static final int COLOR_FormatYUV420Planar = 19; 241 /** @deprecated Use {@link #COLOR_FormatYUV420Flexible}. */ 242 public static final int COLOR_FormatYUV420PackedPlanar = 20; 243 /** @deprecated Use {@link #COLOR_FormatYUV420Flexible}. */ 244 public static final int COLOR_FormatYUV420SemiPlanar = 21; 245 246 /** @deprecated Use {@link #COLOR_FormatYUV422Flexible}. */ 247 public static final int COLOR_FormatYUV422Planar = 22; 248 /** @deprecated Use {@link #COLOR_FormatYUV422Flexible}. */ 249 public static final int COLOR_FormatYUV422PackedPlanar = 23; 250 /** @deprecated Use {@link #COLOR_FormatYUV422Flexible}. */ 251 public static final int COLOR_FormatYUV422SemiPlanar = 24; 252 253 /** @deprecated Use {@link #COLOR_FormatYUV422Flexible}. */ 254 public static final int COLOR_FormatYCbYCr = 25; 255 /** @deprecated Use {@link #COLOR_FormatYUV422Flexible}. */ 256 public static final int COLOR_FormatYCrYCb = 26; 257 /** @deprecated Use {@link #COLOR_FormatYUV422Flexible}. */ 258 public static final int COLOR_FormatCbYCrY = 27; 259 /** @deprecated Use {@link #COLOR_FormatYUV422Flexible}. */ 260 public static final int COLOR_FormatCrYCbY = 28; 261 262 /** @deprecated Use {@link #COLOR_FormatYUV444Flexible}. */ 263 public static final int COLOR_FormatYUV444Interleaved = 29; 264 265 /** 266 * SMIA 8-bit Bayer format. 267 * Each byte represents the top 8-bits of a 10-bit signal. 268 */ 269 public static final int COLOR_FormatRawBayer8bit = 30; 270 /** 271 * SMIA 10-bit Bayer format. 272 */ 273 public static final int COLOR_FormatRawBayer10bit = 31; 274 275 /** 276 * SMIA 8-bit compressed Bayer format. 277 * Each byte represents a sample from the 10-bit signal that is compressed into 8-bits 278 * using DPCM/PCM compression, as defined by the SMIA Functional Specification. 279 */ 280 public static final int COLOR_FormatRawBayer8bitcompressed = 32; 281 282 /** @deprecated Use {@link #COLOR_FormatL8}. */ 283 public static final int COLOR_FormatL2 = 33; 284 /** @deprecated Use {@link #COLOR_FormatL8}. */ 285 public static final int COLOR_FormatL4 = 34; 286 287 /** 288 * 8 bits per pixel Y color format. 289 * <p> 290 * Each byte contains a single pixel. 291 * This format corresponds to {@link android.graphics.PixelFormat#L_8}. 292 */ 293 public static final int COLOR_FormatL8 = 35; 294 295 /** 296 * 16 bits per pixel, little-endian Y color format. 297 * <p> 298 * <pre> 299 * byte byte 300 * <--------- i --------> | <------ i + 1 ------> 301 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 302 * | Y | 303 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 304 * 0 7 0 7 305 * bit 306 * </pre> 307 */ 308 public static final int COLOR_FormatL16 = 36; 309 /** @deprecated Use {@link #COLOR_FormatL16}. */ 310 public static final int COLOR_FormatL24 = 37; 311 312 /** 313 * 32 bits per pixel, little-endian Y color format. 314 * <p> 315 * <pre> 316 * byte byte byte byte 317 * <------ i -----> | <---- i+1 ----> | <---- i+2 ----> | <---- i+3 -----> 318 * +-----------------+-----------------+-----------------+-----------------+ 319 * | Y | 320 * +-----------------+-----------------+-----------------+-----------------+ 321 * 0 7 0 7 0 7 0 7 322 * bit 323 * </pre> 324 * 325 * @deprecated Use {@link #COLOR_FormatL16}. 326 */ 327 public static final int COLOR_FormatL32 = 38; 328 329 /** @deprecated Use {@link #COLOR_FormatYUV420Flexible}. */ 330 public static final int COLOR_FormatYUV420PackedSemiPlanar = 39; 331 /** @deprecated Use {@link #COLOR_FormatYUV422Flexible}. */ 332 public static final int COLOR_FormatYUV422PackedSemiPlanar = 40; 333 334 /** @deprecated Use {@link #COLOR_Format24bitBGR888}. */ 335 public static final int COLOR_Format18BitBGR666 = 41; 336 337 /** @deprecated Use {@link #COLOR_Format32bitABGR8888}. */ 338 public static final int COLOR_Format24BitARGB6666 = 42; 339 /** @deprecated Use {@link #COLOR_Format32bitABGR8888}. */ 340 public static final int COLOR_Format24BitABGR6666 = 43; 341 342 /** @deprecated Use {@link #COLOR_FormatYUV420Flexible}. */ 343 public static final int COLOR_TI_FormatYUV420PackedSemiPlanar = 0x7f000100; 344 // COLOR_FormatSurface indicates that the data will be a GraphicBuffer metadata reference. 345 // In OMX this is called OMX_COLOR_FormatAndroidOpaque. 346 public static final int COLOR_FormatSurface = 0x7F000789; 347 348 /** 349 * 32 bits per pixel RGBA color format, with 8-bit red, green, blue, and alpha components. 350 * <p> 351 * Using 32-bit little-endian representation, colors stored as Red 7:0, Green 15:8, 352 * Blue 23:16, and Alpha 31:24. 353 * <pre> 354 * byte byte byte byte 355 * <------ i -----> | <---- i+1 ----> | <---- i+2 ----> | <---- i+3 -----> 356 * +-----------------+-----------------+-----------------+-----------------+ 357 * | RED | GREEN | BLUE | ALPHA | 358 * +-----------------+-----------------+-----------------+-----------------+ 359 * </pre> 360 * 361 * This corresponds to {@link android.graphics.PixelFormat#RGBA_8888}. 362 */ 363 public static final int COLOR_Format32bitABGR8888 = 0x7F00A000; 364 365 /** 366 * Flexible 12 bits per pixel, subsampled YUV color format with 8-bit chroma and luma 367 * components. 368 * <p> 369 * Chroma planes are subsampled by 2 both horizontally and vertically. 370 * Use this format with {@link Image}. 371 * This format corresponds to {@link android.graphics.ImageFormat#YUV_420_888}, 372 * and can represent the {@link #COLOR_FormatYUV411Planar}, 373 * {@link #COLOR_FormatYUV411PackedPlanar}, {@link #COLOR_FormatYUV420Planar}, 374 * {@link #COLOR_FormatYUV420PackedPlanar}, {@link #COLOR_FormatYUV420SemiPlanar} 375 * and {@link #COLOR_FormatYUV420PackedSemiPlanar} formats. 376 * 377 * @see Image#getFormat 378 */ 379 public static final int COLOR_FormatYUV420Flexible = 0x7F420888; 380 381 /** 382 * Flexible 16 bits per pixel, subsampled YUV color format with 8-bit chroma and luma 383 * components. 384 * <p> 385 * Chroma planes are horizontally subsampled by 2. Use this format with {@link Image}. 386 * This format corresponds to {@link android.graphics.ImageFormat#YUV_422_888}, 387 * and can represent the {@link #COLOR_FormatYCbYCr}, {@link #COLOR_FormatYCrYCb}, 388 * {@link #COLOR_FormatCbYCrY}, {@link #COLOR_FormatCrYCbY}, 389 * {@link #COLOR_FormatYUV422Planar}, {@link #COLOR_FormatYUV422PackedPlanar}, 390 * {@link #COLOR_FormatYUV422SemiPlanar} and {@link #COLOR_FormatYUV422PackedSemiPlanar} 391 * formats. 392 * 393 * @see Image#getFormat 394 */ 395 public static final int COLOR_FormatYUV422Flexible = 0x7F422888; 396 397 /** 398 * Flexible 24 bits per pixel YUV color format with 8-bit chroma and luma 399 * components. 400 * <p> 401 * Chroma planes are not subsampled. Use this format with {@link Image}. 402 * This format corresponds to {@link android.graphics.ImageFormat#YUV_444_888}, 403 * and can represent the {@link #COLOR_FormatYUV444Interleaved} format. 404 * @see Image#getFormat 405 */ 406 public static final int COLOR_FormatYUV444Flexible = 0x7F444888; 407 408 /** 409 * Flexible 24 bits per pixel RGB color format with 8-bit red, green and blue 410 * components. 411 * <p> 412 * Use this format with {@link Image}. This format corresponds to 413 * {@link android.graphics.ImageFormat#FLEX_RGB_888}, and can represent 414 * {@link #COLOR_Format24bitBGR888} and {@link #COLOR_Format24bitRGB888} formats. 415 * @see Image#getFormat. 416 */ 417 public static final int COLOR_FormatRGBFlexible = 0x7F36B888; 418 419 /** 420 * Flexible 32 bits per pixel RGBA color format with 8-bit red, green, blue, and alpha 421 * components. 422 * <p> 423 * Use this format with {@link Image}. This format corresponds to 424 * {@link android.graphics.ImageFormat#FLEX_RGBA_8888}, and can represent 425 * {@link #COLOR_Format32bitBGRA8888}, {@link #COLOR_Format32bitABGR8888} and 426 * {@link #COLOR_Format32bitARGB8888} formats. 427 * 428 * @see Image#getFormat 429 */ 430 public static final int COLOR_FormatRGBAFlexible = 0x7F36A888; 431 432 /** @deprecated Use {@link #COLOR_FormatYUV420Flexible}. */ 433 public static final int COLOR_QCOM_FormatYUV420SemiPlanar = 0x7fa30c00; 434 435 /** 436 * Defined in the OpenMAX IL specs, color format values are drawn from 437 * OMX_COLOR_FORMATTYPE. 438 */ 439 public int[] colorFormats; // NOTE this array is modifiable by user 440 441 // FEATURES 442 443 private int mFlagsSupported; 444 private int mFlagsRequired; 445 private int mFlagsVerified; 446 447 /** 448 * <b>video decoder only</b>: codec supports seamless resolution changes. 449 */ 450 public static final String FEATURE_AdaptivePlayback = "adaptive-playback"; 451 452 /** 453 * <b>video decoder only</b>: codec supports secure decryption. 454 */ 455 public static final String FEATURE_SecurePlayback = "secure-playback"; 456 457 /** 458 * <b>video or audio decoder only</b>: codec supports tunneled playback. 459 */ 460 public static final String FEATURE_TunneledPlayback = "tunneled-playback"; 461 462 /** 463 * <b>video decoder only</b>: codec supports queuing partial frames. 464 */ 465 public static final String FEATURE_PartialFrame = "partial-frame"; 466 467 /** 468 * <b>video encoder only</b>: codec supports intra refresh. 469 */ 470 public static final String FEATURE_IntraRefresh = "intra-refresh"; 471 472 /** 473 * Query codec feature capabilities. 474 * <p> 475 * These features are supported to be used by the codec. These 476 * include optional features that can be turned on, as well as 477 * features that are always on. 478 */ isFeatureSupported(String name)479 public final boolean isFeatureSupported(String name) { 480 return checkFeature(name, mFlagsSupported); 481 } 482 483 /** 484 * Query codec feature requirements. 485 * <p> 486 * These features are required to be used by the codec, and as such, 487 * they are always turned on. 488 */ isFeatureRequired(String name)489 public final boolean isFeatureRequired(String name) { 490 return checkFeature(name, mFlagsRequired); 491 } 492 493 private static final Feature[] decoderFeatures = { 494 new Feature(FEATURE_AdaptivePlayback, (1 << 0), true), 495 new Feature(FEATURE_SecurePlayback, (1 << 1), false), 496 new Feature(FEATURE_TunneledPlayback, (1 << 2), false), 497 new Feature(FEATURE_PartialFrame, (1 << 3), false), 498 }; 499 500 private static final Feature[] encoderFeatures = { 501 new Feature(FEATURE_IntraRefresh, (1 << 0), false), 502 }; 503 504 /** @hide */ validFeatures()505 public String[] validFeatures() { 506 Feature[] features = getValidFeatures(); 507 String[] res = new String[features.length]; 508 for (int i = 0; i < res.length; i++) { 509 res[i] = features[i].mName; 510 } 511 return res; 512 } 513 getValidFeatures()514 private Feature[] getValidFeatures() { 515 if (!isEncoder()) { 516 return decoderFeatures; 517 } 518 return encoderFeatures; 519 } 520 checkFeature(String name, int flags)521 private boolean checkFeature(String name, int flags) { 522 for (Feature feat: getValidFeatures()) { 523 if (feat.mName.equals(name)) { 524 return (flags & feat.mValue) != 0; 525 } 526 } 527 return false; 528 } 529 530 /** @hide */ isRegular()531 public boolean isRegular() { 532 // regular codecs only require default features 533 for (Feature feat: getValidFeatures()) { 534 if (!feat.mDefault && isFeatureRequired(feat.mName)) { 535 return false; 536 } 537 } 538 return true; 539 } 540 541 /** 542 * Query whether codec supports a given {@link MediaFormat}. 543 * 544 * <p class=note> 545 * <strong>Note:</strong> On {@link android.os.Build.VERSION_CODES#LOLLIPOP}, 546 * {@code format} must not contain a {@linkplain MediaFormat#KEY_FRAME_RATE 547 * frame rate}. Use 548 * <code class=prettyprint>format.setString(MediaFormat.KEY_FRAME_RATE, null)</code> 549 * to clear any existing frame rate setting in the format. 550 * <p> 551 * 552 * The following table summarizes the format keys considered by this method. 553 * 554 * <table style="width: 0%"> 555 * <thead> 556 * <tr> 557 * <th rowspan=3>OS Version(s)</th> 558 * <td colspan=3>{@code MediaFormat} keys considered for</th> 559 * </tr><tr> 560 * <th>Audio Codecs</th> 561 * <th>Video Codecs</th> 562 * <th>Encoders</th> 563 * </tr> 564 * </thead> 565 * <tbody> 566 * <tr> 567 * <td>{@link android.os.Build.VERSION_CODES#LOLLIPOP}</th> 568 * <td rowspan=3>{@link MediaFormat#KEY_MIME}<sup>*</sup>,<br> 569 * {@link MediaFormat#KEY_SAMPLE_RATE},<br> 570 * {@link MediaFormat#KEY_CHANNEL_COUNT},</td> 571 * <td>{@link MediaFormat#KEY_MIME}<sup>*</sup>,<br> 572 * {@link CodecCapabilities#FEATURE_AdaptivePlayback}<sup>D</sup>,<br> 573 * {@link CodecCapabilities#FEATURE_SecurePlayback}<sup>D</sup>,<br> 574 * {@link CodecCapabilities#FEATURE_TunneledPlayback}<sup>D</sup>,<br> 575 * {@link MediaFormat#KEY_WIDTH},<br> 576 * {@link MediaFormat#KEY_HEIGHT},<br> 577 * <strong>no</strong> {@code KEY_FRAME_RATE}</td> 578 * <td rowspan=4>{@link MediaFormat#KEY_BITRATE_MODE},<br> 579 * {@link MediaFormat#KEY_PROFILE} 580 * (and/or {@link MediaFormat#KEY_AAC_PROFILE}<sup>~</sup>),<br> 581 * <!-- {link MediaFormat#KEY_QUALITY},<br> --> 582 * {@link MediaFormat#KEY_COMPLEXITY} 583 * (and/or {@link MediaFormat#KEY_FLAC_COMPRESSION_LEVEL}<sup>~</sup>)</td> 584 * </tr><tr> 585 * <td>{@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1}</th> 586 * <td rowspan=2>as above, plus<br> 587 * {@link MediaFormat#KEY_FRAME_RATE}</td> 588 * </tr><tr> 589 * <td>{@link android.os.Build.VERSION_CODES#M}</th> 590 * </tr><tr> 591 * <td>{@link android.os.Build.VERSION_CODES#N}</th> 592 * <td>as above, plus<br> 593 * {@link MediaFormat#KEY_PROFILE},<br> 594 * <!-- {link MediaFormat#KEY_MAX_BIT_RATE},<br> --> 595 * {@link MediaFormat#KEY_BIT_RATE}</td> 596 * <td>as above, plus<br> 597 * {@link MediaFormat#KEY_PROFILE},<br> 598 * {@link MediaFormat#KEY_LEVEL}<sup>+</sup>,<br> 599 * <!-- {link MediaFormat#KEY_MAX_BIT_RATE},<br> --> 600 * {@link MediaFormat#KEY_BIT_RATE},<br> 601 * {@link CodecCapabilities#FEATURE_IntraRefresh}<sup>E</sup></td> 602 * </tr> 603 * <tr> 604 * <td colspan=4> 605 * <p class=note><strong>Notes:</strong><br> 606 * *: must be specified; otherwise, method returns {@code false}.<br> 607 * +: method does not verify that the format parameters are supported 608 * by the specified level.<br> 609 * D: decoders only<br> 610 * E: encoders only<br> 611 * ~: if both keys are provided values must match 612 * </td> 613 * </tr> 614 * </tbody> 615 * </table> 616 * 617 * @param format media format with optional feature directives. 618 * @throws IllegalArgumentException if format is not a valid media format. 619 * @return whether the codec capabilities support the given format 620 * and feature requests. 621 */ isFormatSupported(MediaFormat format)622 public final boolean isFormatSupported(MediaFormat format) { 623 final Map<String, Object> map = format.getMap(); 624 final String mime = (String)map.get(MediaFormat.KEY_MIME); 625 626 // mime must match if present 627 if (mime != null && !mMime.equalsIgnoreCase(mime)) { 628 return false; 629 } 630 631 // check feature support 632 for (Feature feat: getValidFeatures()) { 633 Integer yesNo = (Integer)map.get(MediaFormat.KEY_FEATURE_ + feat.mName); 634 if (yesNo == null) { 635 continue; 636 } 637 if ((yesNo == 1 && !isFeatureSupported(feat.mName)) || 638 (yesNo == 0 && isFeatureRequired(feat.mName))) { 639 return false; 640 } 641 } 642 643 Integer profile = (Integer)map.get(MediaFormat.KEY_PROFILE); 644 Integer level = (Integer)map.get(MediaFormat.KEY_LEVEL); 645 646 if (profile != null) { 647 if (!supportsProfileLevel(profile, level)) { 648 return false; 649 } 650 651 // If we recognize this profile, check that this format is supported by the 652 // highest level supported by the codec for that profile. (Ignore specified 653 // level beyond the above profile/level check as level is only used as a 654 // guidance. E.g. AVC Level 1 CIF format is supported if codec supports level 1.1 655 // even though max size for Level 1 is QCIF. However, MPEG2 Simple Profile 656 // 1080p format is not supported even if codec supports Main Profile Level High, 657 // as Simple Profile does not support 1080p. 658 CodecCapabilities levelCaps = null; 659 int maxLevel = 0; 660 for (CodecProfileLevel pl : profileLevels) { 661 if (pl.profile == profile && pl.level > maxLevel) { 662 maxLevel = pl.level; 663 } 664 } 665 levelCaps = createFromProfileLevel(mMime, profile, maxLevel); 666 // remove profile from this format otherwise levelCaps.isFormatSupported will 667 // get into this same conditon and loop forever. 668 Map<String, Object> mapWithoutProfile = new HashMap<>(map); 669 mapWithoutProfile.remove(MediaFormat.KEY_PROFILE); 670 MediaFormat formatWithoutProfile = new MediaFormat(mapWithoutProfile); 671 if (levelCaps != null && !levelCaps.isFormatSupported(formatWithoutProfile)) { 672 return false; 673 } 674 } 675 if (mAudioCaps != null && !mAudioCaps.supportsFormat(format)) { 676 return false; 677 } 678 if (mVideoCaps != null && !mVideoCaps.supportsFormat(format)) { 679 return false; 680 } 681 if (mEncoderCaps != null && !mEncoderCaps.supportsFormat(format)) { 682 return false; 683 } 684 return true; 685 } 686 supportsBitrate( Range<Integer> bitrateRange, MediaFormat format)687 private static boolean supportsBitrate( 688 Range<Integer> bitrateRange, MediaFormat format) { 689 Map<String, Object> map = format.getMap(); 690 691 // consider max bitrate over average bitrate for support 692 Integer maxBitrate = (Integer)map.get(MediaFormat.KEY_MAX_BIT_RATE); 693 Integer bitrate = (Integer)map.get(MediaFormat.KEY_BIT_RATE); 694 if (bitrate == null) { 695 bitrate = maxBitrate; 696 } else if (maxBitrate != null) { 697 bitrate = Math.max(bitrate, maxBitrate); 698 } 699 700 if (bitrate != null && bitrate > 0) { 701 return bitrateRange.contains(bitrate); 702 } 703 704 return true; 705 } 706 supportsProfileLevel(int profile, Integer level)707 private boolean supportsProfileLevel(int profile, Integer level) { 708 for (CodecProfileLevel pl: profileLevels) { 709 if (pl.profile != profile) { 710 continue; 711 } 712 713 // AAC does not use levels 714 if (level == null || mMime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AAC)) { 715 return true; 716 } 717 718 // H.263 levels are not completely ordered: 719 // Level45 support only implies Level10 support 720 if (mMime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_H263)) { 721 if (pl.level != level && pl.level == CodecProfileLevel.H263Level45 722 && level > CodecProfileLevel.H263Level10) { 723 continue; 724 } 725 } 726 727 // MPEG4 levels are not completely ordered: 728 // Level1 support only implies Level0 (and not Level0b) support 729 if (mMime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_MPEG4)) { 730 if (pl.level != level && pl.level == CodecProfileLevel.MPEG4Level1 731 && level > CodecProfileLevel.MPEG4Level0) { 732 continue; 733 } 734 } 735 736 // HEVC levels incorporate both tiers and levels. Verify tier support. 737 if (mMime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_HEVC)) { 738 boolean supportsHighTier = 739 (pl.level & CodecProfileLevel.HEVCHighTierLevels) != 0; 740 boolean checkingHighTier = (level & CodecProfileLevel.HEVCHighTierLevels) != 0; 741 // high tier levels are only supported by other high tier levels 742 if (checkingHighTier && !supportsHighTier) { 743 continue; 744 } 745 } 746 747 if (pl.level >= level) { 748 // if we recognize the listed profile/level, we must also recognize the 749 // profile/level arguments. 750 if (createFromProfileLevel(mMime, profile, pl.level) != null) { 751 return createFromProfileLevel(mMime, profile, level) != null; 752 } 753 return true; 754 } 755 } 756 return false; 757 } 758 759 // errors while reading profile levels - accessed from sister capabilities 760 int mError; 761 762 private static final String TAG = "CodecCapabilities"; 763 764 // NEW-STYLE CAPABILITIES 765 private AudioCapabilities mAudioCaps; 766 private VideoCapabilities mVideoCaps; 767 private EncoderCapabilities mEncoderCaps; 768 private MediaFormat mDefaultFormat; 769 770 /** 771 * Returns a MediaFormat object with default values for configurations that have 772 * defaults. 773 */ getDefaultFormat()774 public MediaFormat getDefaultFormat() { 775 return mDefaultFormat; 776 } 777 778 /** 779 * Returns the mime type for which this codec-capability object was created. 780 */ getMimeType()781 public String getMimeType() { 782 return mMime; 783 } 784 785 /** 786 * Returns the max number of the supported concurrent codec instances. 787 * <p> 788 * This is a hint for an upper bound. Applications should not expect to successfully 789 * operate more instances than the returned value, but the actual number of 790 * concurrently operable instances may be less as it depends on the available 791 * resources at time of use. 792 */ getMaxSupportedInstances()793 public int getMaxSupportedInstances() { 794 return mMaxSupportedInstances; 795 } 796 isAudio()797 private boolean isAudio() { 798 return mAudioCaps != null; 799 } 800 801 /** 802 * Returns the audio capabilities or {@code null} if this is not an audio codec. 803 */ getAudioCapabilities()804 public AudioCapabilities getAudioCapabilities() { 805 return mAudioCaps; 806 } 807 isEncoder()808 private boolean isEncoder() { 809 return mEncoderCaps != null; 810 } 811 812 /** 813 * Returns the encoding capabilities or {@code null} if this is not an encoder. 814 */ getEncoderCapabilities()815 public EncoderCapabilities getEncoderCapabilities() { 816 return mEncoderCaps; 817 } 818 isVideo()819 private boolean isVideo() { 820 return mVideoCaps != null; 821 } 822 823 /** 824 * Returns the video capabilities or {@code null} if this is not a video codec. 825 */ getVideoCapabilities()826 public VideoCapabilities getVideoCapabilities() { 827 return mVideoCaps; 828 } 829 830 /** @hide */ dup()831 public CodecCapabilities dup() { 832 return new CodecCapabilities( 833 // clone writable arrays 834 Arrays.copyOf(profileLevels, profileLevels.length), 835 Arrays.copyOf(colorFormats, colorFormats.length), 836 isEncoder(), 837 mFlagsVerified, 838 mDefaultFormat, 839 mCapabilitiesInfo); 840 } 841 842 /** 843 * Retrieve the codec capabilities for a certain {@code mime type}, {@code 844 * profile} and {@code level}. If the type, or profile-level combination 845 * is not understood by the framework, it returns null. 846 * <p class=note> In {@link android.os.Build.VERSION_CODES#M}, calling this 847 * method without calling any method of the {@link MediaCodecList} class beforehand 848 * results in a {@link NullPointerException}.</p> 849 */ createFromProfileLevel( String mime, int profile, int level)850 public static CodecCapabilities createFromProfileLevel( 851 String mime, int profile, int level) { 852 CodecProfileLevel pl = new CodecProfileLevel(); 853 pl.profile = profile; 854 pl.level = level; 855 MediaFormat defaultFormat = new MediaFormat(); 856 defaultFormat.setString(MediaFormat.KEY_MIME, mime); 857 858 CodecCapabilities ret = new CodecCapabilities( 859 new CodecProfileLevel[] { pl }, new int[0], true /* encoder */, 860 0 /* flags */, defaultFormat, new MediaFormat() /* info */); 861 if (ret.mError != 0) { 862 return null; 863 } 864 return ret; 865 } 866 CodecCapabilities( CodecProfileLevel[] profLevs, int[] colFmts, boolean encoder, int flags, Map<String, Object>defaultFormatMap, Map<String, Object>capabilitiesMap)867 /* package private */ CodecCapabilities( 868 CodecProfileLevel[] profLevs, int[] colFmts, 869 boolean encoder, int flags, 870 Map<String, Object>defaultFormatMap, 871 Map<String, Object>capabilitiesMap) { 872 this(profLevs, colFmts, encoder, flags, 873 new MediaFormat(defaultFormatMap), 874 new MediaFormat(capabilitiesMap)); 875 } 876 877 private MediaFormat mCapabilitiesInfo; 878 CodecCapabilities( CodecProfileLevel[] profLevs, int[] colFmts, boolean encoder, int flags, MediaFormat defaultFormat, MediaFormat info)879 /* package private */ CodecCapabilities( 880 CodecProfileLevel[] profLevs, int[] colFmts, boolean encoder, int flags, 881 MediaFormat defaultFormat, MediaFormat info) { 882 final Map<String, Object> map = info.getMap(); 883 colorFormats = colFmts; 884 mFlagsVerified = flags; 885 mDefaultFormat = defaultFormat; 886 mCapabilitiesInfo = info; 887 mMime = mDefaultFormat.getString(MediaFormat.KEY_MIME); 888 889 /* VP9 introduced profiles around 2016, so some VP9 codecs may not advertise any 890 supported profiles. Determine the level for them using the info they provide. */ 891 if (profLevs.length == 0 && mMime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP9)) { 892 CodecProfileLevel profLev = new CodecProfileLevel(); 893 profLev.profile = CodecProfileLevel.VP9Profile0; 894 profLev.level = VideoCapabilities.equivalentVP9Level(info); 895 profLevs = new CodecProfileLevel[] { profLev }; 896 } 897 profileLevels = profLevs; 898 899 if (mMime.toLowerCase().startsWith("audio/")) { 900 mAudioCaps = AudioCapabilities.create(info, this); 901 mAudioCaps.setDefaultFormat(mDefaultFormat); 902 } else if (mMime.toLowerCase().startsWith("video/")) { 903 mVideoCaps = VideoCapabilities.create(info, this); 904 } 905 if (encoder) { 906 mEncoderCaps = EncoderCapabilities.create(info, this); 907 mEncoderCaps.setDefaultFormat(mDefaultFormat); 908 } 909 910 final Map<String, Object> global = MediaCodecList.getGlobalSettings(); 911 mMaxSupportedInstances = Utils.parseIntSafely( 912 global.get("max-concurrent-instances"), DEFAULT_MAX_SUPPORTED_INSTANCES); 913 914 int maxInstances = Utils.parseIntSafely( 915 map.get("max-concurrent-instances"), mMaxSupportedInstances); 916 mMaxSupportedInstances = 917 Range.create(1, MAX_SUPPORTED_INSTANCES_LIMIT).clamp(maxInstances); 918 919 for (Feature feat: getValidFeatures()) { 920 String key = MediaFormat.KEY_FEATURE_ + feat.mName; 921 Integer yesNo = (Integer)map.get(key); 922 if (yesNo == null) { 923 continue; 924 } 925 if (yesNo > 0) { 926 mFlagsRequired |= feat.mValue; 927 } 928 mFlagsSupported |= feat.mValue; 929 mDefaultFormat.setInteger(key, 1); 930 // TODO restrict features by mFlagsVerified once all codecs reliably verify them 931 } 932 } 933 } 934 935 /** 936 * A class that supports querying the audio capabilities of a codec. 937 */ 938 public static final class AudioCapabilities { 939 private static final String TAG = "AudioCapabilities"; 940 private CodecCapabilities mParent; 941 private Range<Integer> mBitrateRange; 942 943 private int[] mSampleRates; 944 private Range<Integer>[] mSampleRateRanges; 945 private int mMaxInputChannelCount; 946 947 private static final int MAX_INPUT_CHANNEL_COUNT = 30; 948 949 /** 950 * Returns the range of supported bitrates in bits/second. 951 */ getBitrateRange()952 public Range<Integer> getBitrateRange() { 953 return mBitrateRange; 954 } 955 956 /** 957 * Returns the array of supported sample rates if the codec 958 * supports only discrete values. Otherwise, it returns 959 * {@code null}. The array is sorted in ascending order. 960 */ getSupportedSampleRates()961 public int[] getSupportedSampleRates() { 962 return Arrays.copyOf(mSampleRates, mSampleRates.length); 963 } 964 965 /** 966 * Returns the array of supported sample rate ranges. The 967 * array is sorted in ascending order, and the ranges are 968 * distinct. 969 */ getSupportedSampleRateRanges()970 public Range<Integer>[] getSupportedSampleRateRanges() { 971 return Arrays.copyOf(mSampleRateRanges, mSampleRateRanges.length); 972 } 973 974 /** 975 * Returns the maximum number of input channels supported. The codec 976 * supports any number of channels between 1 and this maximum value. 977 */ getMaxInputChannelCount()978 public int getMaxInputChannelCount() { 979 return mMaxInputChannelCount; 980 } 981 982 /* no public constructor */ AudioCapabilities()983 private AudioCapabilities() { } 984 985 /** @hide */ create( MediaFormat info, CodecCapabilities parent)986 public static AudioCapabilities create( 987 MediaFormat info, CodecCapabilities parent) { 988 AudioCapabilities caps = new AudioCapabilities(); 989 caps.init(info, parent); 990 return caps; 991 } 992 993 /** @hide */ init(MediaFormat info, CodecCapabilities parent)994 public void init(MediaFormat info, CodecCapabilities parent) { 995 mParent = parent; 996 initWithPlatformLimits(); 997 applyLevelLimits(); 998 parseFromInfo(info); 999 } 1000 initWithPlatformLimits()1001 private void initWithPlatformLimits() { 1002 mBitrateRange = Range.create(0, Integer.MAX_VALUE); 1003 mMaxInputChannelCount = MAX_INPUT_CHANNEL_COUNT; 1004 // mBitrateRange = Range.create(1, 320000); 1005 mSampleRateRanges = new Range[] { Range.create(8000, 96000) }; 1006 mSampleRates = null; 1007 } 1008 supports(Integer sampleRate, Integer inputChannels)1009 private boolean supports(Integer sampleRate, Integer inputChannels) { 1010 // channels and sample rates are checked orthogonally 1011 if (inputChannels != null && 1012 (inputChannels < 1 || inputChannels > mMaxInputChannelCount)) { 1013 return false; 1014 } 1015 if (sampleRate != null) { 1016 int ix = Utils.binarySearchDistinctRanges( 1017 mSampleRateRanges, sampleRate); 1018 if (ix < 0) { 1019 return false; 1020 } 1021 } 1022 return true; 1023 } 1024 1025 /** 1026 * Query whether the sample rate is supported by the codec. 1027 */ isSampleRateSupported(int sampleRate)1028 public boolean isSampleRateSupported(int sampleRate) { 1029 return supports(sampleRate, null); 1030 } 1031 1032 /** modifies rates */ limitSampleRates(int[] rates)1033 private void limitSampleRates(int[] rates) { 1034 Arrays.sort(rates); 1035 ArrayList<Range<Integer>> ranges = new ArrayList<Range<Integer>>(); 1036 for (int rate: rates) { 1037 if (supports(rate, null /* channels */)) { 1038 ranges.add(Range.create(rate, rate)); 1039 } 1040 } 1041 mSampleRateRanges = ranges.toArray(new Range[ranges.size()]); 1042 createDiscreteSampleRates(); 1043 } 1044 createDiscreteSampleRates()1045 private void createDiscreteSampleRates() { 1046 mSampleRates = new int[mSampleRateRanges.length]; 1047 for (int i = 0; i < mSampleRateRanges.length; i++) { 1048 mSampleRates[i] = mSampleRateRanges[i].getLower(); 1049 } 1050 } 1051 1052 /** modifies rateRanges */ limitSampleRates(Range<Integer>[] rateRanges)1053 private void limitSampleRates(Range<Integer>[] rateRanges) { 1054 sortDistinctRanges(rateRanges); 1055 mSampleRateRanges = intersectSortedDistinctRanges(mSampleRateRanges, rateRanges); 1056 1057 // check if all values are discrete 1058 for (Range<Integer> range: mSampleRateRanges) { 1059 if (!range.getLower().equals(range.getUpper())) { 1060 mSampleRates = null; 1061 return; 1062 } 1063 } 1064 createDiscreteSampleRates(); 1065 } 1066 applyLevelLimits()1067 private void applyLevelLimits() { 1068 int[] sampleRates = null; 1069 Range<Integer> sampleRateRange = null, bitRates = null; 1070 int maxChannels = MAX_INPUT_CHANNEL_COUNT; 1071 String mime = mParent.getMimeType(); 1072 1073 if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_MPEG)) { 1074 sampleRates = new int[] { 1075 8000, 11025, 12000, 1076 16000, 22050, 24000, 1077 32000, 44100, 48000 }; 1078 bitRates = Range.create(8000, 320000); 1079 maxChannels = 2; 1080 } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AMR_NB)) { 1081 sampleRates = new int[] { 8000 }; 1082 bitRates = Range.create(4750, 12200); 1083 maxChannels = 1; 1084 } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AMR_WB)) { 1085 sampleRates = new int[] { 16000 }; 1086 bitRates = Range.create(6600, 23850); 1087 maxChannels = 1; 1088 } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AAC)) { 1089 sampleRates = new int[] { 1090 7350, 8000, 1091 11025, 12000, 16000, 1092 22050, 24000, 32000, 1093 44100, 48000, 64000, 1094 88200, 96000 }; 1095 bitRates = Range.create(8000, 510000); 1096 maxChannels = 48; 1097 } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_VORBIS)) { 1098 bitRates = Range.create(32000, 500000); 1099 sampleRateRange = Range.create(8000, 192000); 1100 maxChannels = 255; 1101 } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_OPUS)) { 1102 bitRates = Range.create(6000, 510000); 1103 sampleRates = new int[] { 8000, 12000, 16000, 24000, 48000 }; 1104 maxChannels = 255; 1105 } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_RAW)) { 1106 sampleRateRange = Range.create(1, 96000); 1107 bitRates = Range.create(1, 10000000); 1108 maxChannels = AudioTrack.CHANNEL_COUNT_MAX; 1109 } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_FLAC)) { 1110 sampleRateRange = Range.create(1, 655350); 1111 // lossless codec, so bitrate is ignored 1112 maxChannels = 255; 1113 } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_G711_ALAW) 1114 || mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_G711_MLAW)) { 1115 sampleRates = new int[] { 8000 }; 1116 bitRates = Range.create(64000, 64000); 1117 // platform allows multiple channels for this format 1118 } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_MSGSM)) { 1119 sampleRates = new int[] { 8000 }; 1120 bitRates = Range.create(13000, 13000); 1121 maxChannels = 1; 1122 } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AC3)) { 1123 maxChannels = 6; 1124 } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_EAC3)) { 1125 maxChannels = 16; 1126 } else { 1127 Log.w(TAG, "Unsupported mime " + mime); 1128 mParent.mError |= ERROR_UNSUPPORTED; 1129 } 1130 1131 // restrict ranges 1132 if (sampleRates != null) { 1133 limitSampleRates(sampleRates); 1134 } else if (sampleRateRange != null) { 1135 limitSampleRates(new Range[] { sampleRateRange }); 1136 } 1137 applyLimits(maxChannels, bitRates); 1138 } 1139 applyLimits(int maxInputChannels, Range<Integer> bitRates)1140 private void applyLimits(int maxInputChannels, Range<Integer> bitRates) { 1141 mMaxInputChannelCount = Range.create(1, mMaxInputChannelCount) 1142 .clamp(maxInputChannels); 1143 if (bitRates != null) { 1144 mBitrateRange = mBitrateRange.intersect(bitRates); 1145 } 1146 } 1147 parseFromInfo(MediaFormat info)1148 private void parseFromInfo(MediaFormat info) { 1149 int maxInputChannels = MAX_INPUT_CHANNEL_COUNT; 1150 Range<Integer> bitRates = POSITIVE_INTEGERS; 1151 1152 if (info.containsKey("sample-rate-ranges")) { 1153 String[] rateStrings = info.getString("sample-rate-ranges").split(","); 1154 Range<Integer>[] rateRanges = new Range[rateStrings.length]; 1155 for (int i = 0; i < rateStrings.length; i++) { 1156 rateRanges[i] = Utils.parseIntRange(rateStrings[i], null); 1157 } 1158 limitSampleRates(rateRanges); 1159 } 1160 if (info.containsKey("max-channel-count")) { 1161 maxInputChannels = Utils.parseIntSafely( 1162 info.getString("max-channel-count"), maxInputChannels); 1163 } else if ((mParent.mError & ERROR_UNSUPPORTED) != 0) { 1164 maxInputChannels = 0; 1165 } 1166 if (info.containsKey("bitrate-range")) { 1167 bitRates = bitRates.intersect( 1168 Utils.parseIntRange(info.getString("bitrate-range"), bitRates)); 1169 } 1170 applyLimits(maxInputChannels, bitRates); 1171 } 1172 1173 /** @hide */ setDefaultFormat(MediaFormat format)1174 public void setDefaultFormat(MediaFormat format) { 1175 // report settings that have only a single choice 1176 if (mBitrateRange.getLower().equals(mBitrateRange.getUpper())) { 1177 format.setInteger(MediaFormat.KEY_BIT_RATE, mBitrateRange.getLower()); 1178 } 1179 if (mMaxInputChannelCount == 1) { 1180 // mono-only format 1181 format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1); 1182 } 1183 if (mSampleRates != null && mSampleRates.length == 1) { 1184 format.setInteger(MediaFormat.KEY_SAMPLE_RATE, mSampleRates[0]); 1185 } 1186 } 1187 1188 /** @hide */ supportsFormat(MediaFormat format)1189 public boolean supportsFormat(MediaFormat format) { 1190 Map<String, Object> map = format.getMap(); 1191 Integer sampleRate = (Integer)map.get(MediaFormat.KEY_SAMPLE_RATE); 1192 Integer channels = (Integer)map.get(MediaFormat.KEY_CHANNEL_COUNT); 1193 1194 if (!supports(sampleRate, channels)) { 1195 return false; 1196 } 1197 1198 if (!CodecCapabilities.supportsBitrate(mBitrateRange, format)) { 1199 return false; 1200 } 1201 1202 // nothing to do for: 1203 // KEY_CHANNEL_MASK: codecs don't get this 1204 // KEY_IS_ADTS: required feature for all AAC decoders 1205 return true; 1206 } 1207 } 1208 1209 /** 1210 * A class that supports querying the video capabilities of a codec. 1211 */ 1212 public static final class VideoCapabilities { 1213 private static final String TAG = "VideoCapabilities"; 1214 private CodecCapabilities mParent; 1215 private Range<Integer> mBitrateRange; 1216 1217 private Range<Integer> mHeightRange; 1218 private Range<Integer> mWidthRange; 1219 private Range<Integer> mBlockCountRange; 1220 private Range<Integer> mHorizontalBlockRange; 1221 private Range<Integer> mVerticalBlockRange; 1222 private Range<Rational> mAspectRatioRange; 1223 private Range<Rational> mBlockAspectRatioRange; 1224 private Range<Long> mBlocksPerSecondRange; 1225 private Map<Size, Range<Long>> mMeasuredFrameRates; 1226 private Range<Integer> mFrameRateRange; 1227 1228 private int mBlockWidth; 1229 private int mBlockHeight; 1230 private int mWidthAlignment; 1231 private int mHeightAlignment; 1232 private int mSmallerDimensionUpperLimit; 1233 1234 private boolean mAllowMbOverride; // allow XML to override calculated limits 1235 1236 /** 1237 * Returns the range of supported bitrates in bits/second. 1238 */ getBitrateRange()1239 public Range<Integer> getBitrateRange() { 1240 return mBitrateRange; 1241 } 1242 1243 /** 1244 * Returns the range of supported video widths. 1245 */ getSupportedWidths()1246 public Range<Integer> getSupportedWidths() { 1247 return mWidthRange; 1248 } 1249 1250 /** 1251 * Returns the range of supported video heights. 1252 */ getSupportedHeights()1253 public Range<Integer> getSupportedHeights() { 1254 return mHeightRange; 1255 } 1256 1257 /** 1258 * Returns the alignment requirement for video width (in pixels). 1259 * 1260 * This is a power-of-2 value that video width must be a 1261 * multiple of. 1262 */ getWidthAlignment()1263 public int getWidthAlignment() { 1264 return mWidthAlignment; 1265 } 1266 1267 /** 1268 * Returns the alignment requirement for video height (in pixels). 1269 * 1270 * This is a power-of-2 value that video height must be a 1271 * multiple of. 1272 */ getHeightAlignment()1273 public int getHeightAlignment() { 1274 return mHeightAlignment; 1275 } 1276 1277 /** 1278 * Return the upper limit on the smaller dimension of width or height. 1279 * <p></p> 1280 * Some codecs have a limit on the smaller dimension, whether it be 1281 * the width or the height. E.g. a codec may only be able to handle 1282 * up to 1920x1080 both in landscape and portrait mode (1080x1920). 1283 * In this case the maximum width and height are both 1920, but the 1284 * smaller dimension limit will be 1080. For other codecs, this is 1285 * {@code Math.min(getSupportedWidths().getUpper(), 1286 * getSupportedHeights().getUpper())}. 1287 * 1288 * @hide 1289 */ getSmallerDimensionUpperLimit()1290 public int getSmallerDimensionUpperLimit() { 1291 return mSmallerDimensionUpperLimit; 1292 } 1293 1294 /** 1295 * Returns the range of supported frame rates. 1296 * <p> 1297 * This is not a performance indicator. Rather, it expresses the 1298 * limits specified in the coding standard, based on the complexities 1299 * of encoding material for later playback at a certain frame rate, 1300 * or the decoding of such material in non-realtime. 1301 */ getSupportedFrameRates()1302 public Range<Integer> getSupportedFrameRates() { 1303 return mFrameRateRange; 1304 } 1305 1306 /** 1307 * Returns the range of supported video widths for a video height. 1308 * @param height the height of the video 1309 */ getSupportedWidthsFor(int height)1310 public Range<Integer> getSupportedWidthsFor(int height) { 1311 try { 1312 Range<Integer> range = mWidthRange; 1313 if (!mHeightRange.contains(height) 1314 || (height % mHeightAlignment) != 0) { 1315 throw new IllegalArgumentException("unsupported height"); 1316 } 1317 final int heightInBlocks = Utils.divUp(height, mBlockHeight); 1318 1319 // constrain by block count and by block aspect ratio 1320 final int minWidthInBlocks = Math.max( 1321 Utils.divUp(mBlockCountRange.getLower(), heightInBlocks), 1322 (int)Math.ceil(mBlockAspectRatioRange.getLower().doubleValue() 1323 * heightInBlocks)); 1324 final int maxWidthInBlocks = Math.min( 1325 mBlockCountRange.getUpper() / heightInBlocks, 1326 (int)(mBlockAspectRatioRange.getUpper().doubleValue() 1327 * heightInBlocks)); 1328 range = range.intersect( 1329 (minWidthInBlocks - 1) * mBlockWidth + mWidthAlignment, 1330 maxWidthInBlocks * mBlockWidth); 1331 1332 // constrain by smaller dimension limit 1333 if (height > mSmallerDimensionUpperLimit) { 1334 range = range.intersect(1, mSmallerDimensionUpperLimit); 1335 } 1336 1337 // constrain by aspect ratio 1338 range = range.intersect( 1339 (int)Math.ceil(mAspectRatioRange.getLower().doubleValue() 1340 * height), 1341 (int)(mAspectRatioRange.getUpper().doubleValue() * height)); 1342 return range; 1343 } catch (IllegalArgumentException e) { 1344 // height is not supported because there are no suitable widths 1345 Log.v(TAG, "could not get supported widths for " + height); 1346 throw new IllegalArgumentException("unsupported height"); 1347 } 1348 } 1349 1350 /** 1351 * Returns the range of supported video heights for a video width 1352 * @param width the width of the video 1353 */ getSupportedHeightsFor(int width)1354 public Range<Integer> getSupportedHeightsFor(int width) { 1355 try { 1356 Range<Integer> range = mHeightRange; 1357 if (!mWidthRange.contains(width) 1358 || (width % mWidthAlignment) != 0) { 1359 throw new IllegalArgumentException("unsupported width"); 1360 } 1361 final int widthInBlocks = Utils.divUp(width, mBlockWidth); 1362 1363 // constrain by block count and by block aspect ratio 1364 final int minHeightInBlocks = Math.max( 1365 Utils.divUp(mBlockCountRange.getLower(), widthInBlocks), 1366 (int)Math.ceil(widthInBlocks / 1367 mBlockAspectRatioRange.getUpper().doubleValue())); 1368 final int maxHeightInBlocks = Math.min( 1369 mBlockCountRange.getUpper() / widthInBlocks, 1370 (int)(widthInBlocks / 1371 mBlockAspectRatioRange.getLower().doubleValue())); 1372 range = range.intersect( 1373 (minHeightInBlocks - 1) * mBlockHeight + mHeightAlignment, 1374 maxHeightInBlocks * mBlockHeight); 1375 1376 // constrain by smaller dimension limit 1377 if (width > mSmallerDimensionUpperLimit) { 1378 range = range.intersect(1, mSmallerDimensionUpperLimit); 1379 } 1380 1381 // constrain by aspect ratio 1382 range = range.intersect( 1383 (int)Math.ceil(width / 1384 mAspectRatioRange.getUpper().doubleValue()), 1385 (int)(width / mAspectRatioRange.getLower().doubleValue())); 1386 return range; 1387 } catch (IllegalArgumentException e) { 1388 // width is not supported because there are no suitable heights 1389 Log.v(TAG, "could not get supported heights for " + width); 1390 throw new IllegalArgumentException("unsupported width"); 1391 } 1392 } 1393 1394 /** 1395 * Returns the range of supported video frame rates for a video size. 1396 * <p> 1397 * This is not a performance indicator. Rather, it expresses the limits specified in 1398 * the coding standard, based on the complexities of encoding material of a given 1399 * size for later playback at a certain frame rate, or the decoding of such material 1400 * in non-realtime. 1401 1402 * @param width the width of the video 1403 * @param height the height of the video 1404 */ getSupportedFrameRatesFor(int width, int height)1405 public Range<Double> getSupportedFrameRatesFor(int width, int height) { 1406 Range<Integer> range = mHeightRange; 1407 if (!supports(width, height, null)) { 1408 throw new IllegalArgumentException("unsupported size"); 1409 } 1410 final int blockCount = 1411 Utils.divUp(width, mBlockWidth) * Utils.divUp(height, mBlockHeight); 1412 1413 return Range.create( 1414 Math.max(mBlocksPerSecondRange.getLower() / (double) blockCount, 1415 (double) mFrameRateRange.getLower()), 1416 Math.min(mBlocksPerSecondRange.getUpper() / (double) blockCount, 1417 (double) mFrameRateRange.getUpper())); 1418 } 1419 getBlockCount(int width, int height)1420 private int getBlockCount(int width, int height) { 1421 return Utils.divUp(width, mBlockWidth) * Utils.divUp(height, mBlockHeight); 1422 } 1423 1424 @NonNull findClosestSize(int width, int height)1425 private Size findClosestSize(int width, int height) { 1426 int targetBlockCount = getBlockCount(width, height); 1427 Size closestSize = null; 1428 int minDiff = Integer.MAX_VALUE; 1429 for (Size size : mMeasuredFrameRates.keySet()) { 1430 int diff = Math.abs(targetBlockCount - 1431 getBlockCount(size.getWidth(), size.getHeight())); 1432 if (diff < minDiff) { 1433 minDiff = diff; 1434 closestSize = size; 1435 } 1436 } 1437 return closestSize; 1438 } 1439 estimateFrameRatesFor(int width, int height)1440 private Range<Double> estimateFrameRatesFor(int width, int height) { 1441 Size size = findClosestSize(width, height); 1442 Range<Long> range = mMeasuredFrameRates.get(size); 1443 Double ratio = getBlockCount(size.getWidth(), size.getHeight()) 1444 / (double)Math.max(getBlockCount(width, height), 1); 1445 return Range.create(range.getLower() * ratio, range.getUpper() * ratio); 1446 } 1447 1448 /** 1449 * Returns the range of achievable video frame rates for a video size. 1450 * May return {@code null}, if the codec did not publish any measurement 1451 * data. 1452 * <p> 1453 * This is a performance estimate provided by the device manufacturer based on statistical 1454 * sampling of full-speed decoding and encoding measurements in various configurations 1455 * of common video sizes supported by the codec. As such it should only be used to 1456 * compare individual codecs on the device. The value is not suitable for comparing 1457 * different devices or even different android releases for the same device. 1458 * <p> 1459 * <em>On {@link android.os.Build.VERSION_CODES#M} release</em> the returned range 1460 * corresponds to the fastest frame rates achieved in the tested configurations. As 1461 * such, it should not be used to gauge guaranteed or even average codec performance 1462 * on the device. 1463 * <p> 1464 * <em>On {@link android.os.Build.VERSION_CODES#N} release</em> the returned range 1465 * corresponds closer to sustained performance <em>in tested configurations</em>. 1466 * One can expect to achieve sustained performance higher than the lower limit more than 1467 * 50% of the time, and higher than half of the lower limit at least 90% of the time 1468 * <em>in tested configurations</em>. 1469 * Conversely, one can expect performance lower than twice the upper limit at least 1470 * 90% of the time. 1471 * <p class=note> 1472 * Tested configurations use a single active codec. For use cases where multiple 1473 * codecs are active, applications can expect lower and in most cases significantly lower 1474 * performance. 1475 * <p class=note> 1476 * The returned range value is interpolated from the nearest frame size(s) tested. 1477 * Codec performance is severely impacted by other activity on the device as well 1478 * as environmental factors (such as battery level, temperature or power source), and can 1479 * vary significantly even in a steady environment. 1480 * <p class=note> 1481 * Use this method in cases where only codec performance matters, e.g. to evaluate if 1482 * a codec has any chance of meeting a performance target. Codecs are listed 1483 * in {@link MediaCodecList} in the preferred order as defined by the device 1484 * manufacturer. As such, applications should use the first suitable codec in the 1485 * list to achieve the best balance between power use and performance. 1486 * 1487 * @param width the width of the video 1488 * @param height the height of the video 1489 * 1490 * @throws IllegalArgumentException if the video size is not supported. 1491 */ 1492 @Nullable getAchievableFrameRatesFor(int width, int height)1493 public Range<Double> getAchievableFrameRatesFor(int width, int height) { 1494 if (!supports(width, height, null)) { 1495 throw new IllegalArgumentException("unsupported size"); 1496 } 1497 1498 if (mMeasuredFrameRates == null || mMeasuredFrameRates.size() <= 0) { 1499 Log.w(TAG, "Codec did not publish any measurement data."); 1500 return null; 1501 } 1502 1503 return estimateFrameRatesFor(width, height); 1504 } 1505 1506 /** 1507 * Returns whether a given video size ({@code width} and 1508 * {@code height}) and {@code frameRate} combination is supported. 1509 */ areSizeAndRateSupported( int width, int height, double frameRate)1510 public boolean areSizeAndRateSupported( 1511 int width, int height, double frameRate) { 1512 return supports(width, height, frameRate); 1513 } 1514 1515 /** 1516 * Returns whether a given video size ({@code width} and 1517 * {@code height}) is supported. 1518 */ isSizeSupported(int width, int height)1519 public boolean isSizeSupported(int width, int height) { 1520 return supports(width, height, null); 1521 } 1522 supports(Integer width, Integer height, Number rate)1523 private boolean supports(Integer width, Integer height, Number rate) { 1524 boolean ok = true; 1525 1526 if (ok && width != null) { 1527 ok = mWidthRange.contains(width) 1528 && (width % mWidthAlignment == 0); 1529 } 1530 if (ok && height != null) { 1531 ok = mHeightRange.contains(height) 1532 && (height % mHeightAlignment == 0); 1533 } 1534 if (ok && rate != null) { 1535 ok = mFrameRateRange.contains(Utils.intRangeFor(rate.doubleValue())); 1536 } 1537 if (ok && height != null && width != null) { 1538 ok = Math.min(height, width) <= mSmallerDimensionUpperLimit; 1539 1540 final int widthInBlocks = Utils.divUp(width, mBlockWidth); 1541 final int heightInBlocks = Utils.divUp(height, mBlockHeight); 1542 final int blockCount = widthInBlocks * heightInBlocks; 1543 ok = ok && mBlockCountRange.contains(blockCount) 1544 && mBlockAspectRatioRange.contains( 1545 new Rational(widthInBlocks, heightInBlocks)) 1546 && mAspectRatioRange.contains(new Rational(width, height)); 1547 if (ok && rate != null) { 1548 double blocksPerSec = blockCount * rate.doubleValue(); 1549 ok = mBlocksPerSecondRange.contains( 1550 Utils.longRangeFor(blocksPerSec)); 1551 } 1552 } 1553 return ok; 1554 } 1555 1556 /** 1557 * @hide 1558 * @throws java.lang.ClassCastException */ supportsFormat(MediaFormat format)1559 public boolean supportsFormat(MediaFormat format) { 1560 final Map<String, Object> map = format.getMap(); 1561 Integer width = (Integer)map.get(MediaFormat.KEY_WIDTH); 1562 Integer height = (Integer)map.get(MediaFormat.KEY_HEIGHT); 1563 Number rate = (Number)map.get(MediaFormat.KEY_FRAME_RATE); 1564 1565 if (!supports(width, height, rate)) { 1566 return false; 1567 } 1568 1569 if (!CodecCapabilities.supportsBitrate(mBitrateRange, format)) { 1570 return false; 1571 } 1572 1573 // we ignore color-format for now as it is not reliably reported by codec 1574 return true; 1575 } 1576 1577 /* no public constructor */ VideoCapabilities()1578 private VideoCapabilities() { } 1579 1580 /** @hide */ create( MediaFormat info, CodecCapabilities parent)1581 public static VideoCapabilities create( 1582 MediaFormat info, CodecCapabilities parent) { 1583 VideoCapabilities caps = new VideoCapabilities(); 1584 caps.init(info, parent); 1585 return caps; 1586 } 1587 1588 /** @hide */ init(MediaFormat info, CodecCapabilities parent)1589 public void init(MediaFormat info, CodecCapabilities parent) { 1590 mParent = parent; 1591 initWithPlatformLimits(); 1592 applyLevelLimits(); 1593 parseFromInfo(info); 1594 updateLimits(); 1595 } 1596 1597 /** @hide */ getBlockSize()1598 public Size getBlockSize() { 1599 return new Size(mBlockWidth, mBlockHeight); 1600 } 1601 1602 /** @hide */ getBlockCountRange()1603 public Range<Integer> getBlockCountRange() { 1604 return mBlockCountRange; 1605 } 1606 1607 /** @hide */ getBlocksPerSecondRange()1608 public Range<Long> getBlocksPerSecondRange() { 1609 return mBlocksPerSecondRange; 1610 } 1611 1612 /** @hide */ getAspectRatioRange(boolean blocks)1613 public Range<Rational> getAspectRatioRange(boolean blocks) { 1614 return blocks ? mBlockAspectRatioRange : mAspectRatioRange; 1615 } 1616 initWithPlatformLimits()1617 private void initWithPlatformLimits() { 1618 mBitrateRange = BITRATE_RANGE; 1619 1620 mWidthRange = SIZE_RANGE; 1621 mHeightRange = SIZE_RANGE; 1622 mFrameRateRange = FRAME_RATE_RANGE; 1623 1624 mHorizontalBlockRange = SIZE_RANGE; 1625 mVerticalBlockRange = SIZE_RANGE; 1626 1627 // full positive ranges are supported as these get calculated 1628 mBlockCountRange = POSITIVE_INTEGERS; 1629 mBlocksPerSecondRange = POSITIVE_LONGS; 1630 1631 mBlockAspectRatioRange = POSITIVE_RATIONALS; 1632 mAspectRatioRange = POSITIVE_RATIONALS; 1633 1634 // YUV 4:2:0 requires 2:2 alignment 1635 mWidthAlignment = 2; 1636 mHeightAlignment = 2; 1637 mBlockWidth = 2; 1638 mBlockHeight = 2; 1639 mSmallerDimensionUpperLimit = SIZE_RANGE.getUpper(); 1640 } 1641 getMeasuredFrameRates(Map<String, Object> map)1642 private Map<Size, Range<Long>> getMeasuredFrameRates(Map<String, Object> map) { 1643 Map<Size, Range<Long>> ret = new HashMap<Size, Range<Long>>(); 1644 final String prefix = "measured-frame-rate-"; 1645 Set<String> keys = map.keySet(); 1646 for (String key : keys) { 1647 // looking for: measured-frame-rate-WIDTHxHEIGHT-range 1648 if (!key.startsWith(prefix)) { 1649 continue; 1650 } 1651 String subKey = key.substring(prefix.length()); 1652 String[] temp = key.split("-"); 1653 if (temp.length != 5) { 1654 continue; 1655 } 1656 String sizeStr = temp[3]; 1657 Size size = Utils.parseSize(sizeStr, null); 1658 if (size == null || size.getWidth() * size.getHeight() <= 0) { 1659 continue; 1660 } 1661 Range<Long> range = Utils.parseLongRange(map.get(key), null); 1662 if (range == null || range.getLower() < 0 || range.getUpper() < 0) { 1663 continue; 1664 } 1665 ret.put(size, range); 1666 } 1667 return ret; 1668 } 1669 parseWidthHeightRanges(Object o)1670 private static Pair<Range<Integer>, Range<Integer>> parseWidthHeightRanges(Object o) { 1671 Pair<Size, Size> range = Utils.parseSizeRange(o); 1672 if (range != null) { 1673 try { 1674 return Pair.create( 1675 Range.create(range.first.getWidth(), range.second.getWidth()), 1676 Range.create(range.first.getHeight(), range.second.getHeight())); 1677 } catch (IllegalArgumentException e) { 1678 Log.w(TAG, "could not parse size range '" + o + "'"); 1679 } 1680 } 1681 return null; 1682 } 1683 1684 /** @hide */ equivalentVP9Level(MediaFormat info)1685 public static int equivalentVP9Level(MediaFormat info) { 1686 final Map<String, Object> map = info.getMap(); 1687 1688 Size blockSize = Utils.parseSize(map.get("block-size"), new Size(8, 8)); 1689 int BS = blockSize.getWidth() * blockSize.getHeight(); 1690 1691 Range<Integer> counts = Utils.parseIntRange(map.get("block-count-range"), null); 1692 int FS = counts == null ? 0 : BS * counts.getUpper(); 1693 1694 Range<Long> blockRates = 1695 Utils.parseLongRange(map.get("blocks-per-second-range"), null); 1696 long SR = blockRates == null ? 0 : BS * blockRates.getUpper(); 1697 1698 Pair<Range<Integer>, Range<Integer>> dimensionRanges = 1699 parseWidthHeightRanges(map.get("size-range")); 1700 int D = dimensionRanges == null ? 0 : Math.max( 1701 dimensionRanges.first.getUpper(), dimensionRanges.second.getUpper()); 1702 1703 Range<Integer> bitRates = Utils.parseIntRange(map.get("bitrate-range"), null); 1704 int BR = bitRates == null ? 0 : Utils.divUp(bitRates.getUpper(), 1000); 1705 1706 if (SR <= 829440 && FS <= 36864 && BR <= 200 && D <= 512) 1707 return CodecProfileLevel.VP9Level1; 1708 if (SR <= 2764800 && FS <= 73728 && BR <= 800 && D <= 768) 1709 return CodecProfileLevel.VP9Level11; 1710 if (SR <= 4608000 && FS <= 122880 && BR <= 1800 && D <= 960) 1711 return CodecProfileLevel.VP9Level2; 1712 if (SR <= 9216000 && FS <= 245760 && BR <= 3600 && D <= 1344) 1713 return CodecProfileLevel.VP9Level21; 1714 if (SR <= 20736000 && FS <= 552960 && BR <= 7200 && D <= 2048) 1715 return CodecProfileLevel.VP9Level3; 1716 if (SR <= 36864000 && FS <= 983040 && BR <= 12000 && D <= 2752) 1717 return CodecProfileLevel.VP9Level31; 1718 if (SR <= 83558400 && FS <= 2228224 && BR <= 18000 && D <= 4160) 1719 return CodecProfileLevel.VP9Level4; 1720 if (SR <= 160432128 && FS <= 2228224 && BR <= 30000 && D <= 4160) 1721 return CodecProfileLevel.VP9Level41; 1722 if (SR <= 311951360 && FS <= 8912896 && BR <= 60000 && D <= 8384) 1723 return CodecProfileLevel.VP9Level5; 1724 if (SR <= 588251136 && FS <= 8912896 && BR <= 120000 && D <= 8384) 1725 return CodecProfileLevel.VP9Level51; 1726 if (SR <= 1176502272 && FS <= 8912896 && BR <= 180000 && D <= 8384) 1727 return CodecProfileLevel.VP9Level52; 1728 if (SR <= 1176502272 && FS <= 35651584 && BR <= 180000 && D <= 16832) 1729 return CodecProfileLevel.VP9Level6; 1730 if (SR <= 2353004544L && FS <= 35651584 && BR <= 240000 && D <= 16832) 1731 return CodecProfileLevel.VP9Level61; 1732 if (SR <= 4706009088L && FS <= 35651584 && BR <= 480000 && D <= 16832) 1733 return CodecProfileLevel.VP9Level62; 1734 // returning largest level 1735 return CodecProfileLevel.VP9Level62; 1736 } 1737 parseFromInfo(MediaFormat info)1738 private void parseFromInfo(MediaFormat info) { 1739 final Map<String, Object> map = info.getMap(); 1740 Size blockSize = new Size(mBlockWidth, mBlockHeight); 1741 Size alignment = new Size(mWidthAlignment, mHeightAlignment); 1742 Range<Integer> counts = null, widths = null, heights = null; 1743 Range<Integer> frameRates = null, bitRates = null; 1744 Range<Long> blockRates = null; 1745 Range<Rational> ratios = null, blockRatios = null; 1746 1747 blockSize = Utils.parseSize(map.get("block-size"), blockSize); 1748 alignment = Utils.parseSize(map.get("alignment"), alignment); 1749 counts = Utils.parseIntRange(map.get("block-count-range"), null); 1750 blockRates = 1751 Utils.parseLongRange(map.get("blocks-per-second-range"), null); 1752 mMeasuredFrameRates = getMeasuredFrameRates(map); 1753 Pair<Range<Integer>, Range<Integer>> sizeRanges = 1754 parseWidthHeightRanges(map.get("size-range")); 1755 if (sizeRanges != null) { 1756 widths = sizeRanges.first; 1757 heights = sizeRanges.second; 1758 } 1759 // for now this just means using the smaller max size as 2nd 1760 // upper limit. 1761 // for now we are keeping the profile specific "width/height 1762 // in macroblocks" limits. 1763 if (map.containsKey("feature-can-swap-width-height")) { 1764 if (widths != null) { 1765 mSmallerDimensionUpperLimit = 1766 Math.min(widths.getUpper(), heights.getUpper()); 1767 widths = heights = widths.extend(heights); 1768 } else { 1769 Log.w(TAG, "feature can-swap-width-height is best used with size-range"); 1770 mSmallerDimensionUpperLimit = 1771 Math.min(mWidthRange.getUpper(), mHeightRange.getUpper()); 1772 mWidthRange = mHeightRange = mWidthRange.extend(mHeightRange); 1773 } 1774 } 1775 1776 ratios = Utils.parseRationalRange( 1777 map.get("block-aspect-ratio-range"), null); 1778 blockRatios = Utils.parseRationalRange( 1779 map.get("pixel-aspect-ratio-range"), null); 1780 frameRates = Utils.parseIntRange(map.get("frame-rate-range"), null); 1781 if (frameRates != null) { 1782 try { 1783 frameRates = frameRates.intersect(FRAME_RATE_RANGE); 1784 } catch (IllegalArgumentException e) { 1785 Log.w(TAG, "frame rate range (" + frameRates 1786 + ") is out of limits: " + FRAME_RATE_RANGE); 1787 frameRates = null; 1788 } 1789 } 1790 bitRates = Utils.parseIntRange(map.get("bitrate-range"), null); 1791 if (bitRates != null) { 1792 try { 1793 bitRates = bitRates.intersect(BITRATE_RANGE); 1794 } catch (IllegalArgumentException e) { 1795 Log.w(TAG, "bitrate range (" + bitRates 1796 + ") is out of limits: " + BITRATE_RANGE); 1797 bitRates = null; 1798 } 1799 } 1800 1801 checkPowerOfTwo( 1802 blockSize.getWidth(), "block-size width must be power of two"); 1803 checkPowerOfTwo( 1804 blockSize.getHeight(), "block-size height must be power of two"); 1805 1806 checkPowerOfTwo( 1807 alignment.getWidth(), "alignment width must be power of two"); 1808 checkPowerOfTwo( 1809 alignment.getHeight(), "alignment height must be power of two"); 1810 1811 // update block-size and alignment 1812 applyMacroBlockLimits( 1813 Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, 1814 Long.MAX_VALUE, blockSize.getWidth(), blockSize.getHeight(), 1815 alignment.getWidth(), alignment.getHeight()); 1816 1817 if ((mParent.mError & ERROR_UNSUPPORTED) != 0 || mAllowMbOverride) { 1818 // codec supports profiles that we don't know. 1819 // Use supplied values clipped to platform limits 1820 if (widths != null) { 1821 mWidthRange = SIZE_RANGE.intersect(widths); 1822 } 1823 if (heights != null) { 1824 mHeightRange = SIZE_RANGE.intersect(heights); 1825 } 1826 if (counts != null) { 1827 mBlockCountRange = POSITIVE_INTEGERS.intersect( 1828 Utils.factorRange(counts, mBlockWidth * mBlockHeight 1829 / blockSize.getWidth() / blockSize.getHeight())); 1830 } 1831 if (blockRates != null) { 1832 mBlocksPerSecondRange = POSITIVE_LONGS.intersect( 1833 Utils.factorRange(blockRates, mBlockWidth * mBlockHeight 1834 / blockSize.getWidth() / blockSize.getHeight())); 1835 } 1836 if (blockRatios != null) { 1837 mBlockAspectRatioRange = POSITIVE_RATIONALS.intersect( 1838 Utils.scaleRange(blockRatios, 1839 mBlockHeight / blockSize.getHeight(), 1840 mBlockWidth / blockSize.getWidth())); 1841 } 1842 if (ratios != null) { 1843 mAspectRatioRange = POSITIVE_RATIONALS.intersect(ratios); 1844 } 1845 if (frameRates != null) { 1846 mFrameRateRange = FRAME_RATE_RANGE.intersect(frameRates); 1847 } 1848 if (bitRates != null) { 1849 // only allow bitrate override if unsupported profiles were encountered 1850 if ((mParent.mError & ERROR_UNSUPPORTED) != 0) { 1851 mBitrateRange = BITRATE_RANGE.intersect(bitRates); 1852 } else { 1853 mBitrateRange = mBitrateRange.intersect(bitRates); 1854 } 1855 } 1856 } else { 1857 // no unsupported profile/levels, so restrict values to known limits 1858 if (widths != null) { 1859 mWidthRange = mWidthRange.intersect(widths); 1860 } 1861 if (heights != null) { 1862 mHeightRange = mHeightRange.intersect(heights); 1863 } 1864 if (counts != null) { 1865 mBlockCountRange = mBlockCountRange.intersect( 1866 Utils.factorRange(counts, mBlockWidth * mBlockHeight 1867 / blockSize.getWidth() / blockSize.getHeight())); 1868 } 1869 if (blockRates != null) { 1870 mBlocksPerSecondRange = mBlocksPerSecondRange.intersect( 1871 Utils.factorRange(blockRates, mBlockWidth * mBlockHeight 1872 / blockSize.getWidth() / blockSize.getHeight())); 1873 } 1874 if (blockRatios != null) { 1875 mBlockAspectRatioRange = mBlockAspectRatioRange.intersect( 1876 Utils.scaleRange(blockRatios, 1877 mBlockHeight / blockSize.getHeight(), 1878 mBlockWidth / blockSize.getWidth())); 1879 } 1880 if (ratios != null) { 1881 mAspectRatioRange = mAspectRatioRange.intersect(ratios); 1882 } 1883 if (frameRates != null) { 1884 mFrameRateRange = mFrameRateRange.intersect(frameRates); 1885 } 1886 if (bitRates != null) { 1887 mBitrateRange = mBitrateRange.intersect(bitRates); 1888 } 1889 } 1890 updateLimits(); 1891 } 1892 applyBlockLimits( int blockWidth, int blockHeight, Range<Integer> counts, Range<Long> rates, Range<Rational> ratios)1893 private void applyBlockLimits( 1894 int blockWidth, int blockHeight, 1895 Range<Integer> counts, Range<Long> rates, Range<Rational> ratios) { 1896 checkPowerOfTwo(blockWidth, "blockWidth must be a power of two"); 1897 checkPowerOfTwo(blockHeight, "blockHeight must be a power of two"); 1898 1899 final int newBlockWidth = Math.max(blockWidth, mBlockWidth); 1900 final int newBlockHeight = Math.max(blockHeight, mBlockHeight); 1901 1902 // factor will always be a power-of-2 1903 int factor = 1904 newBlockWidth * newBlockHeight / mBlockWidth / mBlockHeight; 1905 if (factor != 1) { 1906 mBlockCountRange = Utils.factorRange(mBlockCountRange, factor); 1907 mBlocksPerSecondRange = Utils.factorRange( 1908 mBlocksPerSecondRange, factor); 1909 mBlockAspectRatioRange = Utils.scaleRange( 1910 mBlockAspectRatioRange, 1911 newBlockHeight / mBlockHeight, 1912 newBlockWidth / mBlockWidth); 1913 mHorizontalBlockRange = Utils.factorRange( 1914 mHorizontalBlockRange, newBlockWidth / mBlockWidth); 1915 mVerticalBlockRange = Utils.factorRange( 1916 mVerticalBlockRange, newBlockHeight / mBlockHeight); 1917 } 1918 factor = newBlockWidth * newBlockHeight / blockWidth / blockHeight; 1919 if (factor != 1) { 1920 counts = Utils.factorRange(counts, factor); 1921 rates = Utils.factorRange(rates, factor); 1922 ratios = Utils.scaleRange( 1923 ratios, newBlockHeight / blockHeight, 1924 newBlockWidth / blockWidth); 1925 } 1926 mBlockCountRange = mBlockCountRange.intersect(counts); 1927 mBlocksPerSecondRange = mBlocksPerSecondRange.intersect(rates); 1928 mBlockAspectRatioRange = mBlockAspectRatioRange.intersect(ratios); 1929 mBlockWidth = newBlockWidth; 1930 mBlockHeight = newBlockHeight; 1931 } 1932 applyAlignment(int widthAlignment, int heightAlignment)1933 private void applyAlignment(int widthAlignment, int heightAlignment) { 1934 checkPowerOfTwo(widthAlignment, "widthAlignment must be a power of two"); 1935 checkPowerOfTwo(heightAlignment, "heightAlignment must be a power of two"); 1936 1937 if (widthAlignment > mBlockWidth || heightAlignment > mBlockHeight) { 1938 // maintain assumption that 0 < alignment <= block-size 1939 applyBlockLimits( 1940 Math.max(widthAlignment, mBlockWidth), 1941 Math.max(heightAlignment, mBlockHeight), 1942 POSITIVE_INTEGERS, POSITIVE_LONGS, POSITIVE_RATIONALS); 1943 } 1944 1945 mWidthAlignment = Math.max(widthAlignment, mWidthAlignment); 1946 mHeightAlignment = Math.max(heightAlignment, mHeightAlignment); 1947 1948 mWidthRange = Utils.alignRange(mWidthRange, mWidthAlignment); 1949 mHeightRange = Utils.alignRange(mHeightRange, mHeightAlignment); 1950 } 1951 updateLimits()1952 private void updateLimits() { 1953 // pixels -> blocks <- counts 1954 mHorizontalBlockRange = mHorizontalBlockRange.intersect( 1955 Utils.factorRange(mWidthRange, mBlockWidth)); 1956 mHorizontalBlockRange = mHorizontalBlockRange.intersect( 1957 Range.create( 1958 mBlockCountRange.getLower() / mVerticalBlockRange.getUpper(), 1959 mBlockCountRange.getUpper() / mVerticalBlockRange.getLower())); 1960 mVerticalBlockRange = mVerticalBlockRange.intersect( 1961 Utils.factorRange(mHeightRange, mBlockHeight)); 1962 mVerticalBlockRange = mVerticalBlockRange.intersect( 1963 Range.create( 1964 mBlockCountRange.getLower() / mHorizontalBlockRange.getUpper(), 1965 mBlockCountRange.getUpper() / mHorizontalBlockRange.getLower())); 1966 mBlockCountRange = mBlockCountRange.intersect( 1967 Range.create( 1968 mHorizontalBlockRange.getLower() 1969 * mVerticalBlockRange.getLower(), 1970 mHorizontalBlockRange.getUpper() 1971 * mVerticalBlockRange.getUpper())); 1972 mBlockAspectRatioRange = mBlockAspectRatioRange.intersect( 1973 new Rational( 1974 mHorizontalBlockRange.getLower(), mVerticalBlockRange.getUpper()), 1975 new Rational( 1976 mHorizontalBlockRange.getUpper(), mVerticalBlockRange.getLower())); 1977 1978 // blocks -> pixels 1979 mWidthRange = mWidthRange.intersect( 1980 (mHorizontalBlockRange.getLower() - 1) * mBlockWidth + mWidthAlignment, 1981 mHorizontalBlockRange.getUpper() * mBlockWidth); 1982 mHeightRange = mHeightRange.intersect( 1983 (mVerticalBlockRange.getLower() - 1) * mBlockHeight + mHeightAlignment, 1984 mVerticalBlockRange.getUpper() * mBlockHeight); 1985 mAspectRatioRange = mAspectRatioRange.intersect( 1986 new Rational(mWidthRange.getLower(), mHeightRange.getUpper()), 1987 new Rational(mWidthRange.getUpper(), mHeightRange.getLower())); 1988 1989 mSmallerDimensionUpperLimit = Math.min( 1990 mSmallerDimensionUpperLimit, 1991 Math.min(mWidthRange.getUpper(), mHeightRange.getUpper())); 1992 1993 // blocks -> rate 1994 mBlocksPerSecondRange = mBlocksPerSecondRange.intersect( 1995 mBlockCountRange.getLower() * (long)mFrameRateRange.getLower(), 1996 mBlockCountRange.getUpper() * (long)mFrameRateRange.getUpper()); 1997 mFrameRateRange = mFrameRateRange.intersect( 1998 (int)(mBlocksPerSecondRange.getLower() 1999 / mBlockCountRange.getUpper()), 2000 (int)(mBlocksPerSecondRange.getUpper() 2001 / (double)mBlockCountRange.getLower())); 2002 } 2003 applyMacroBlockLimits( int maxHorizontalBlocks, int maxVerticalBlocks, int maxBlocks, long maxBlocksPerSecond, int blockWidth, int blockHeight, int widthAlignment, int heightAlignment)2004 private void applyMacroBlockLimits( 2005 int maxHorizontalBlocks, int maxVerticalBlocks, 2006 int maxBlocks, long maxBlocksPerSecond, 2007 int blockWidth, int blockHeight, 2008 int widthAlignment, int heightAlignment) { 2009 applyMacroBlockLimits( 2010 1 /* minHorizontalBlocks */, 1 /* minVerticalBlocks */, 2011 maxHorizontalBlocks, maxVerticalBlocks, 2012 maxBlocks, maxBlocksPerSecond, 2013 blockWidth, blockHeight, widthAlignment, heightAlignment); 2014 } 2015 applyMacroBlockLimits( int minHorizontalBlocks, int minVerticalBlocks, int maxHorizontalBlocks, int maxVerticalBlocks, int maxBlocks, long maxBlocksPerSecond, int blockWidth, int blockHeight, int widthAlignment, int heightAlignment)2016 private void applyMacroBlockLimits( 2017 int minHorizontalBlocks, int minVerticalBlocks, 2018 int maxHorizontalBlocks, int maxVerticalBlocks, 2019 int maxBlocks, long maxBlocksPerSecond, 2020 int blockWidth, int blockHeight, 2021 int widthAlignment, int heightAlignment) { 2022 applyAlignment(widthAlignment, heightAlignment); 2023 applyBlockLimits( 2024 blockWidth, blockHeight, Range.create(1, maxBlocks), 2025 Range.create(1L, maxBlocksPerSecond), 2026 Range.create( 2027 new Rational(1, maxVerticalBlocks), 2028 new Rational(maxHorizontalBlocks, 1))); 2029 mHorizontalBlockRange = 2030 mHorizontalBlockRange.intersect( 2031 Utils.divUp(minHorizontalBlocks, (mBlockWidth / blockWidth)), 2032 maxHorizontalBlocks / (mBlockWidth / blockWidth)); 2033 mVerticalBlockRange = 2034 mVerticalBlockRange.intersect( 2035 Utils.divUp(minVerticalBlocks, (mBlockHeight / blockHeight)), 2036 maxVerticalBlocks / (mBlockHeight / blockHeight)); 2037 } 2038 applyLevelLimits()2039 private void applyLevelLimits() { 2040 long maxBlocksPerSecond = 0; 2041 int maxBlocks = 0; 2042 int maxBps = 0; 2043 int maxDPBBlocks = 0; 2044 2045 int errors = ERROR_NONE_SUPPORTED; 2046 CodecProfileLevel[] profileLevels = mParent.profileLevels; 2047 String mime = mParent.getMimeType(); 2048 2049 if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_AVC)) { 2050 maxBlocks = 99; 2051 maxBlocksPerSecond = 1485; 2052 maxBps = 64000; 2053 maxDPBBlocks = 396; 2054 for (CodecProfileLevel profileLevel: profileLevels) { 2055 int MBPS = 0, FS = 0, BR = 0, DPB = 0; 2056 boolean supported = true; 2057 switch (profileLevel.level) { 2058 case CodecProfileLevel.AVCLevel1: 2059 MBPS = 1485; FS = 99; BR = 64; DPB = 396; break; 2060 case CodecProfileLevel.AVCLevel1b: 2061 MBPS = 1485; FS = 99; BR = 128; DPB = 396; break; 2062 case CodecProfileLevel.AVCLevel11: 2063 MBPS = 3000; FS = 396; BR = 192; DPB = 900; break; 2064 case CodecProfileLevel.AVCLevel12: 2065 MBPS = 6000; FS = 396; BR = 384; DPB = 2376; break; 2066 case CodecProfileLevel.AVCLevel13: 2067 MBPS = 11880; FS = 396; BR = 768; DPB = 2376; break; 2068 case CodecProfileLevel.AVCLevel2: 2069 MBPS = 11880; FS = 396; BR = 2000; DPB = 2376; break; 2070 case CodecProfileLevel.AVCLevel21: 2071 MBPS = 19800; FS = 792; BR = 4000; DPB = 4752; break; 2072 case CodecProfileLevel.AVCLevel22: 2073 MBPS = 20250; FS = 1620; BR = 4000; DPB = 8100; break; 2074 case CodecProfileLevel.AVCLevel3: 2075 MBPS = 40500; FS = 1620; BR = 10000; DPB = 8100; break; 2076 case CodecProfileLevel.AVCLevel31: 2077 MBPS = 108000; FS = 3600; BR = 14000; DPB = 18000; break; 2078 case CodecProfileLevel.AVCLevel32: 2079 MBPS = 216000; FS = 5120; BR = 20000; DPB = 20480; break; 2080 case CodecProfileLevel.AVCLevel4: 2081 MBPS = 245760; FS = 8192; BR = 20000; DPB = 32768; break; 2082 case CodecProfileLevel.AVCLevel41: 2083 MBPS = 245760; FS = 8192; BR = 50000; DPB = 32768; break; 2084 case CodecProfileLevel.AVCLevel42: 2085 MBPS = 522240; FS = 8704; BR = 50000; DPB = 34816; break; 2086 case CodecProfileLevel.AVCLevel5: 2087 MBPS = 589824; FS = 22080; BR = 135000; DPB = 110400; break; 2088 case CodecProfileLevel.AVCLevel51: 2089 MBPS = 983040; FS = 36864; BR = 240000; DPB = 184320; break; 2090 case CodecProfileLevel.AVCLevel52: 2091 MBPS = 2073600; FS = 36864; BR = 240000; DPB = 184320; break; 2092 default: 2093 Log.w(TAG, "Unrecognized level " 2094 + profileLevel.level + " for " + mime); 2095 errors |= ERROR_UNRECOGNIZED; 2096 } 2097 switch (profileLevel.profile) { 2098 case CodecProfileLevel.AVCProfileConstrainedHigh: 2099 case CodecProfileLevel.AVCProfileHigh: 2100 BR *= 1250; break; 2101 case CodecProfileLevel.AVCProfileHigh10: 2102 BR *= 3000; break; 2103 case CodecProfileLevel.AVCProfileExtended: 2104 case CodecProfileLevel.AVCProfileHigh422: 2105 case CodecProfileLevel.AVCProfileHigh444: 2106 Log.w(TAG, "Unsupported profile " 2107 + profileLevel.profile + " for " + mime); 2108 errors |= ERROR_UNSUPPORTED; 2109 supported = false; 2110 // fall through - treat as base profile 2111 case CodecProfileLevel.AVCProfileConstrainedBaseline: 2112 case CodecProfileLevel.AVCProfileBaseline: 2113 case CodecProfileLevel.AVCProfileMain: 2114 BR *= 1000; break; 2115 default: 2116 Log.w(TAG, "Unrecognized profile " 2117 + profileLevel.profile + " for " + mime); 2118 errors |= ERROR_UNRECOGNIZED; 2119 BR *= 1000; 2120 } 2121 if (supported) { 2122 errors &= ~ERROR_NONE_SUPPORTED; 2123 } 2124 maxBlocksPerSecond = Math.max(MBPS, maxBlocksPerSecond); 2125 maxBlocks = Math.max(FS, maxBlocks); 2126 maxBps = Math.max(BR, maxBps); 2127 maxDPBBlocks = Math.max(maxDPBBlocks, DPB); 2128 } 2129 2130 int maxLengthInBlocks = (int)(Math.sqrt(maxBlocks * 8)); 2131 applyMacroBlockLimits( 2132 maxLengthInBlocks, maxLengthInBlocks, 2133 maxBlocks, maxBlocksPerSecond, 2134 16 /* blockWidth */, 16 /* blockHeight */, 2135 1 /* widthAlignment */, 1 /* heightAlignment */); 2136 } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_MPEG2)) { 2137 int maxWidth = 11, maxHeight = 9, maxRate = 15; 2138 maxBlocks = 99; 2139 maxBlocksPerSecond = 1485; 2140 maxBps = 64000; 2141 for (CodecProfileLevel profileLevel: profileLevels) { 2142 int MBPS = 0, FS = 0, BR = 0, FR = 0, W = 0, H = 0; 2143 boolean supported = true; 2144 switch (profileLevel.profile) { 2145 case CodecProfileLevel.MPEG2ProfileSimple: 2146 switch (profileLevel.level) { 2147 case CodecProfileLevel.MPEG2LevelML: 2148 FR = 30; W = 45; H = 36; MBPS = 40500; FS = 1620; BR = 15000; break; 2149 default: 2150 Log.w(TAG, "Unrecognized profile/level " 2151 + profileLevel.profile + "/" 2152 + profileLevel.level + " for " + mime); 2153 errors |= ERROR_UNRECOGNIZED; 2154 } 2155 break; 2156 case CodecProfileLevel.MPEG2ProfileMain: 2157 switch (profileLevel.level) { 2158 case CodecProfileLevel.MPEG2LevelLL: 2159 FR = 30; W = 22; H = 18; MBPS = 11880; FS = 396; BR = 4000; break; 2160 case CodecProfileLevel.MPEG2LevelML: 2161 FR = 30; W = 45; H = 36; MBPS = 40500; FS = 1620; BR = 15000; break; 2162 case CodecProfileLevel.MPEG2LevelH14: 2163 FR = 60; W = 90; H = 68; MBPS = 183600; FS = 6120; BR = 60000; break; 2164 case CodecProfileLevel.MPEG2LevelHL: 2165 FR = 60; W = 120; H = 68; MBPS = 244800; FS = 8160; BR = 80000; break; 2166 case CodecProfileLevel.MPEG2LevelHP: 2167 FR = 60; W = 120; H = 68; MBPS = 489600; FS = 8160; BR = 80000; break; 2168 default: 2169 Log.w(TAG, "Unrecognized profile/level " 2170 + profileLevel.profile + "/" 2171 + profileLevel.level + " for " + mime); 2172 errors |= ERROR_UNRECOGNIZED; 2173 } 2174 break; 2175 case CodecProfileLevel.MPEG2Profile422: 2176 case CodecProfileLevel.MPEG2ProfileSNR: 2177 case CodecProfileLevel.MPEG2ProfileSpatial: 2178 case CodecProfileLevel.MPEG2ProfileHigh: 2179 Log.i(TAG, "Unsupported profile " 2180 + profileLevel.profile + " for " + mime); 2181 errors |= ERROR_UNSUPPORTED; 2182 supported = false; 2183 break; 2184 default: 2185 Log.w(TAG, "Unrecognized profile " 2186 + profileLevel.profile + " for " + mime); 2187 errors |= ERROR_UNRECOGNIZED; 2188 } 2189 if (supported) { 2190 errors &= ~ERROR_NONE_SUPPORTED; 2191 } 2192 maxBlocksPerSecond = Math.max(MBPS, maxBlocksPerSecond); 2193 maxBlocks = Math.max(FS, maxBlocks); 2194 maxBps = Math.max(BR * 1000, maxBps); 2195 maxWidth = Math.max(W, maxWidth); 2196 maxHeight = Math.max(H, maxHeight); 2197 maxRate = Math.max(FR, maxRate); 2198 } 2199 applyMacroBlockLimits(maxWidth, maxHeight, 2200 maxBlocks, maxBlocksPerSecond, 2201 16 /* blockWidth */, 16 /* blockHeight */, 2202 1 /* widthAlignment */, 1 /* heightAlignment */); 2203 mFrameRateRange = mFrameRateRange.intersect(12, maxRate); 2204 } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_MPEG4)) { 2205 int maxWidth = 11, maxHeight = 9, maxRate = 15; 2206 maxBlocks = 99; 2207 maxBlocksPerSecond = 1485; 2208 maxBps = 64000; 2209 for (CodecProfileLevel profileLevel: profileLevels) { 2210 int MBPS = 0, FS = 0, BR = 0, FR = 0, W = 0, H = 0; 2211 boolean strict = false; // true: W, H and FR are individual max limits 2212 boolean supported = true; 2213 switch (profileLevel.profile) { 2214 case CodecProfileLevel.MPEG4ProfileSimple: 2215 switch (profileLevel.level) { 2216 case CodecProfileLevel.MPEG4Level0: 2217 strict = true; 2218 FR = 15; W = 11; H = 9; MBPS = 1485; FS = 99; BR = 64; break; 2219 case CodecProfileLevel.MPEG4Level1: 2220 FR = 30; W = 11; H = 9; MBPS = 1485; FS = 99; BR = 64; break; 2221 case CodecProfileLevel.MPEG4Level0b: 2222 strict = true; 2223 FR = 15; W = 11; H = 9; MBPS = 1485; FS = 99; BR = 128; break; 2224 case CodecProfileLevel.MPEG4Level2: 2225 FR = 30; W = 22; H = 18; MBPS = 5940; FS = 396; BR = 128; break; 2226 case CodecProfileLevel.MPEG4Level3: 2227 FR = 30; W = 22; H = 18; MBPS = 11880; FS = 396; BR = 384; break; 2228 case CodecProfileLevel.MPEG4Level4a: 2229 FR = 30; W = 40; H = 30; MBPS = 36000; FS = 1200; BR = 4000; break; 2230 case CodecProfileLevel.MPEG4Level5: 2231 FR = 30; W = 45; H = 36; MBPS = 40500; FS = 1620; BR = 8000; break; 2232 case CodecProfileLevel.MPEG4Level6: 2233 FR = 30; W = 80; H = 45; MBPS = 108000; FS = 3600; BR = 12000; break; 2234 default: 2235 Log.w(TAG, "Unrecognized profile/level " 2236 + profileLevel.profile + "/" 2237 + profileLevel.level + " for " + mime); 2238 errors |= ERROR_UNRECOGNIZED; 2239 } 2240 break; 2241 case CodecProfileLevel.MPEG4ProfileAdvancedSimple: 2242 switch (profileLevel.level) { 2243 case CodecProfileLevel.MPEG4Level0: 2244 case CodecProfileLevel.MPEG4Level1: 2245 FR = 30; W = 11; H = 9; MBPS = 2970; FS = 99; BR = 128; break; 2246 case CodecProfileLevel.MPEG4Level2: 2247 FR = 30; W = 22; H = 18; MBPS = 5940; FS = 396; BR = 384; break; 2248 case CodecProfileLevel.MPEG4Level3: 2249 FR = 30; W = 22; H = 18; MBPS = 11880; FS = 396; BR = 768; break; 2250 case CodecProfileLevel.MPEG4Level3b: 2251 FR = 30; W = 22; H = 18; MBPS = 11880; FS = 396; BR = 1500; break; 2252 case CodecProfileLevel.MPEG4Level4: 2253 FR = 30; W = 44; H = 36; MBPS = 23760; FS = 792; BR = 3000; break; 2254 case CodecProfileLevel.MPEG4Level5: 2255 FR = 30; W = 45; H = 36; MBPS = 48600; FS = 1620; BR = 8000; break; 2256 default: 2257 Log.w(TAG, "Unrecognized profile/level " 2258 + profileLevel.profile + "/" 2259 + profileLevel.level + " for " + mime); 2260 errors |= ERROR_UNRECOGNIZED; 2261 } 2262 break; 2263 case CodecProfileLevel.MPEG4ProfileMain: // 2-4 2264 case CodecProfileLevel.MPEG4ProfileNbit: // 2 2265 case CodecProfileLevel.MPEG4ProfileAdvancedRealTime: // 1-4 2266 case CodecProfileLevel.MPEG4ProfileCoreScalable: // 1-3 2267 case CodecProfileLevel.MPEG4ProfileAdvancedCoding: // 1-4 2268 case CodecProfileLevel.MPEG4ProfileCore: // 1-2 2269 case CodecProfileLevel.MPEG4ProfileAdvancedCore: // 1-4 2270 case CodecProfileLevel.MPEG4ProfileSimpleScalable: // 0-2 2271 case CodecProfileLevel.MPEG4ProfileHybrid: // 1-2 2272 2273 // Studio profiles are not supported by our codecs. 2274 2275 // Only profiles that can decode simple object types are considered. 2276 // The following profiles are not able to. 2277 case CodecProfileLevel.MPEG4ProfileBasicAnimated: // 1-2 2278 case CodecProfileLevel.MPEG4ProfileScalableTexture: // 1 2279 case CodecProfileLevel.MPEG4ProfileSimpleFace: // 1-2 2280 case CodecProfileLevel.MPEG4ProfileAdvancedScalable: // 1-3 2281 case CodecProfileLevel.MPEG4ProfileSimpleFBA: // 1-2 2282 Log.i(TAG, "Unsupported profile " 2283 + profileLevel.profile + " for " + mime); 2284 errors |= ERROR_UNSUPPORTED; 2285 supported = false; 2286 break; 2287 default: 2288 Log.w(TAG, "Unrecognized profile " 2289 + profileLevel.profile + " for " + mime); 2290 errors |= ERROR_UNRECOGNIZED; 2291 } 2292 if (supported) { 2293 errors &= ~ERROR_NONE_SUPPORTED; 2294 } 2295 maxBlocksPerSecond = Math.max(MBPS, maxBlocksPerSecond); 2296 maxBlocks = Math.max(FS, maxBlocks); 2297 maxBps = Math.max(BR * 1000, maxBps); 2298 if (strict) { 2299 maxWidth = Math.max(W, maxWidth); 2300 maxHeight = Math.max(H, maxHeight); 2301 maxRate = Math.max(FR, maxRate); 2302 } else { 2303 // assuming max 60 fps frame rate and 1:2 aspect ratio 2304 int maxDim = (int)Math.sqrt(FS * 2); 2305 maxWidth = Math.max(maxDim, maxWidth); 2306 maxHeight = Math.max(maxDim, maxHeight); 2307 maxRate = Math.max(Math.max(FR, 60), maxRate); 2308 } 2309 } 2310 applyMacroBlockLimits(maxWidth, maxHeight, 2311 maxBlocks, maxBlocksPerSecond, 2312 16 /* blockWidth */, 16 /* blockHeight */, 2313 1 /* widthAlignment */, 1 /* heightAlignment */); 2314 mFrameRateRange = mFrameRateRange.intersect(12, maxRate); 2315 } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_H263)) { 2316 int maxWidth = 11, maxHeight = 9, maxRate = 15; 2317 int minWidth = maxWidth, minHeight = maxHeight; 2318 int minAlignment = 16; 2319 maxBlocks = 99; 2320 maxBlocksPerSecond = 1485; 2321 maxBps = 64000; 2322 for (CodecProfileLevel profileLevel: profileLevels) { 2323 int MBPS = 0, BR = 0, FR = 0, W = 0, H = 0, minW = minWidth, minH = minHeight; 2324 boolean strict = false; // true: support only sQCIF, QCIF (maybe CIF) 2325 switch (profileLevel.level) { 2326 case CodecProfileLevel.H263Level10: 2327 strict = true; // only supports sQCIF & QCIF 2328 FR = 15; W = 11; H = 9; BR = 1; MBPS = W * H * FR; break; 2329 case CodecProfileLevel.H263Level20: 2330 strict = true; // only supports sQCIF, QCIF & CIF 2331 FR = 30; W = 22; H = 18; BR = 2; MBPS = W * H * 15; break; 2332 case CodecProfileLevel.H263Level30: 2333 strict = true; // only supports sQCIF, QCIF & CIF 2334 FR = 30; W = 22; H = 18; BR = 6; MBPS = W * H * FR; break; 2335 case CodecProfileLevel.H263Level40: 2336 strict = true; // only supports sQCIF, QCIF & CIF 2337 FR = 30; W = 22; H = 18; BR = 32; MBPS = W * H * FR; break; 2338 case CodecProfileLevel.H263Level45: 2339 // only implies level 10 support 2340 strict = profileLevel.profile == CodecProfileLevel.H263ProfileBaseline 2341 || profileLevel.profile == 2342 CodecProfileLevel.H263ProfileBackwardCompatible; 2343 if (!strict) { 2344 minW = 1; minH = 1; minAlignment = 4; 2345 } 2346 FR = 15; W = 11; H = 9; BR = 2; MBPS = W * H * FR; break; 2347 case CodecProfileLevel.H263Level50: 2348 // only supports 50fps for H > 15 2349 minW = 1; minH = 1; minAlignment = 4; 2350 FR = 60; W = 22; H = 18; BR = 64; MBPS = W * H * 50; break; 2351 case CodecProfileLevel.H263Level60: 2352 // only supports 50fps for H > 15 2353 minW = 1; minH = 1; minAlignment = 4; 2354 FR = 60; W = 45; H = 18; BR = 128; MBPS = W * H * 50; break; 2355 case CodecProfileLevel.H263Level70: 2356 // only supports 50fps for H > 30 2357 minW = 1; minH = 1; minAlignment = 4; 2358 FR = 60; W = 45; H = 36; BR = 256; MBPS = W * H * 50; break; 2359 default: 2360 Log.w(TAG, "Unrecognized profile/level " + profileLevel.profile 2361 + "/" + profileLevel.level + " for " + mime); 2362 errors |= ERROR_UNRECOGNIZED; 2363 } 2364 switch (profileLevel.profile) { 2365 case CodecProfileLevel.H263ProfileBackwardCompatible: 2366 case CodecProfileLevel.H263ProfileBaseline: 2367 case CodecProfileLevel.H263ProfileH320Coding: 2368 case CodecProfileLevel.H263ProfileHighCompression: 2369 case CodecProfileLevel.H263ProfileHighLatency: 2370 case CodecProfileLevel.H263ProfileInterlace: 2371 case CodecProfileLevel.H263ProfileInternet: 2372 case CodecProfileLevel.H263ProfileISWV2: 2373 case CodecProfileLevel.H263ProfileISWV3: 2374 break; 2375 default: 2376 Log.w(TAG, "Unrecognized profile " 2377 + profileLevel.profile + " for " + mime); 2378 errors |= ERROR_UNRECOGNIZED; 2379 } 2380 if (strict) { 2381 // Strict levels define sub-QCIF min size and enumerated sizes. We cannot 2382 // express support for "only sQCIF & QCIF (& CIF)" using VideoCapabilities 2383 // but we can express "only QCIF (& CIF)", so set minimume size at QCIF. 2384 // minW = 8; minH = 6; 2385 minW = 11; minH = 9; 2386 } else { 2387 // any support for non-strict levels (including unrecognized profiles or 2388 // levels) allow custom frame size support beyond supported limits 2389 // (other than bitrate) 2390 mAllowMbOverride = true; 2391 } 2392 errors &= ~ERROR_NONE_SUPPORTED; 2393 maxBlocksPerSecond = Math.max(MBPS, maxBlocksPerSecond); 2394 maxBlocks = Math.max(W * H, maxBlocks); 2395 maxBps = Math.max(BR * 64000, maxBps); 2396 maxWidth = Math.max(W, maxWidth); 2397 maxHeight = Math.max(H, maxHeight); 2398 maxRate = Math.max(FR, maxRate); 2399 minWidth = Math.min(minW, minWidth); 2400 minHeight = Math.min(minH, minHeight); 2401 } 2402 // unless we encountered custom frame size support, limit size to QCIF and CIF 2403 // using aspect ratio. 2404 if (!mAllowMbOverride) { 2405 mBlockAspectRatioRange = 2406 Range.create(new Rational(11, 9), new Rational(11, 9)); 2407 } 2408 applyMacroBlockLimits( 2409 minWidth, minHeight, 2410 maxWidth, maxHeight, 2411 maxBlocks, maxBlocksPerSecond, 2412 16 /* blockWidth */, 16 /* blockHeight */, 2413 minAlignment /* widthAlignment */, minAlignment /* heightAlignment */); 2414 mFrameRateRange = Range.create(1, maxRate); 2415 } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP8)) { 2416 maxBlocks = Integer.MAX_VALUE; 2417 maxBlocksPerSecond = Integer.MAX_VALUE; 2418 2419 // TODO: set to 100Mbps for now, need a number for VP8 2420 maxBps = 100000000; 2421 2422 // profile levels are not indicative for VPx, but verify 2423 // them nonetheless 2424 for (CodecProfileLevel profileLevel: profileLevels) { 2425 switch (profileLevel.level) { 2426 case CodecProfileLevel.VP8Level_Version0: 2427 case CodecProfileLevel.VP8Level_Version1: 2428 case CodecProfileLevel.VP8Level_Version2: 2429 case CodecProfileLevel.VP8Level_Version3: 2430 break; 2431 default: 2432 Log.w(TAG, "Unrecognized level " 2433 + profileLevel.level + " for " + mime); 2434 errors |= ERROR_UNRECOGNIZED; 2435 } 2436 switch (profileLevel.profile) { 2437 case CodecProfileLevel.VP8ProfileMain: 2438 break; 2439 default: 2440 Log.w(TAG, "Unrecognized profile " 2441 + profileLevel.profile + " for " + mime); 2442 errors |= ERROR_UNRECOGNIZED; 2443 } 2444 errors &= ~ERROR_NONE_SUPPORTED; 2445 } 2446 2447 final int blockSize = 16; 2448 applyMacroBlockLimits(Short.MAX_VALUE, Short.MAX_VALUE, 2449 maxBlocks, maxBlocksPerSecond, blockSize, blockSize, 2450 1 /* widthAlignment */, 1 /* heightAlignment */); 2451 } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP9)) { 2452 maxBlocksPerSecond = 829440; 2453 maxBlocks = 36864; 2454 maxBps = 200000; 2455 int maxDim = 512; 2456 2457 for (CodecProfileLevel profileLevel: profileLevels) { 2458 long SR = 0; // luma sample rate 2459 int FS = 0; // luma picture size 2460 int BR = 0; // bit rate kbps 2461 int D = 0; // luma dimension 2462 switch (profileLevel.level) { 2463 case CodecProfileLevel.VP9Level1: 2464 SR = 829440; FS = 36864; BR = 200; D = 512; break; 2465 case CodecProfileLevel.VP9Level11: 2466 SR = 2764800; FS = 73728; BR = 800; D = 768; break; 2467 case CodecProfileLevel.VP9Level2: 2468 SR = 4608000; FS = 122880; BR = 1800; D = 960; break; 2469 case CodecProfileLevel.VP9Level21: 2470 SR = 9216000; FS = 245760; BR = 3600; D = 1344; break; 2471 case CodecProfileLevel.VP9Level3: 2472 SR = 20736000; FS = 552960; BR = 7200; D = 2048; break; 2473 case CodecProfileLevel.VP9Level31: 2474 SR = 36864000; FS = 983040; BR = 12000; D = 2752; break; 2475 case CodecProfileLevel.VP9Level4: 2476 SR = 83558400; FS = 2228224; BR = 18000; D = 4160; break; 2477 case CodecProfileLevel.VP9Level41: 2478 SR = 160432128; FS = 2228224; BR = 30000; D = 4160; break; 2479 case CodecProfileLevel.VP9Level5: 2480 SR = 311951360; FS = 8912896; BR = 60000; D = 8384; break; 2481 case CodecProfileLevel.VP9Level51: 2482 SR = 588251136; FS = 8912896; BR = 120000; D = 8384; break; 2483 case CodecProfileLevel.VP9Level52: 2484 SR = 1176502272; FS = 8912896; BR = 180000; D = 8384; break; 2485 case CodecProfileLevel.VP9Level6: 2486 SR = 1176502272; FS = 35651584; BR = 180000; D = 16832; break; 2487 case CodecProfileLevel.VP9Level61: 2488 SR = 2353004544L; FS = 35651584; BR = 240000; D = 16832; break; 2489 case CodecProfileLevel.VP9Level62: 2490 SR = 4706009088L; FS = 35651584; BR = 480000; D = 16832; break; 2491 default: 2492 Log.w(TAG, "Unrecognized level " 2493 + profileLevel.level + " for " + mime); 2494 errors |= ERROR_UNRECOGNIZED; 2495 } 2496 switch (profileLevel.profile) { 2497 case CodecProfileLevel.VP9Profile0: 2498 case CodecProfileLevel.VP9Profile1: 2499 case CodecProfileLevel.VP9Profile2: 2500 case CodecProfileLevel.VP9Profile3: 2501 case CodecProfileLevel.VP9Profile2HDR: 2502 case CodecProfileLevel.VP9Profile3HDR: 2503 break; 2504 default: 2505 Log.w(TAG, "Unrecognized profile " 2506 + profileLevel.profile + " for " + mime); 2507 errors |= ERROR_UNRECOGNIZED; 2508 } 2509 errors &= ~ERROR_NONE_SUPPORTED; 2510 maxBlocksPerSecond = Math.max(SR, maxBlocksPerSecond); 2511 maxBlocks = Math.max(FS, maxBlocks); 2512 maxBps = Math.max(BR * 1000, maxBps); 2513 maxDim = Math.max(D, maxDim); 2514 } 2515 2516 final int blockSize = 8; 2517 int maxLengthInBlocks = Utils.divUp(maxDim, blockSize); 2518 maxBlocks = Utils.divUp(maxBlocks, blockSize * blockSize); 2519 maxBlocksPerSecond = Utils.divUp(maxBlocksPerSecond, blockSize * blockSize); 2520 2521 applyMacroBlockLimits( 2522 maxLengthInBlocks, maxLengthInBlocks, 2523 maxBlocks, maxBlocksPerSecond, 2524 blockSize, blockSize, 2525 1 /* widthAlignment */, 1 /* heightAlignment */); 2526 } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_HEVC)) { 2527 // CTBs are at least 8x8 so use 8x8 block size 2528 maxBlocks = 36864 >> 6; // 192x192 pixels == 576 8x8 blocks 2529 maxBlocksPerSecond = maxBlocks * 15; 2530 maxBps = 128000; 2531 for (CodecProfileLevel profileLevel: profileLevels) { 2532 double FR = 0; 2533 int FS = 0; 2534 int BR = 0; 2535 switch (profileLevel.level) { 2536 /* The HEVC spec talks only in a very convoluted manner about the 2537 existence of levels 1-3.1 for High tier, which could also be 2538 understood as 'decoders and encoders should treat these levels 2539 as if they were Main tier', so we do that. */ 2540 case CodecProfileLevel.HEVCMainTierLevel1: 2541 case CodecProfileLevel.HEVCHighTierLevel1: 2542 FR = 15; FS = 36864; BR = 128; break; 2543 case CodecProfileLevel.HEVCMainTierLevel2: 2544 case CodecProfileLevel.HEVCHighTierLevel2: 2545 FR = 30; FS = 122880; BR = 1500; break; 2546 case CodecProfileLevel.HEVCMainTierLevel21: 2547 case CodecProfileLevel.HEVCHighTierLevel21: 2548 FR = 30; FS = 245760; BR = 3000; break; 2549 case CodecProfileLevel.HEVCMainTierLevel3: 2550 case CodecProfileLevel.HEVCHighTierLevel3: 2551 FR = 30; FS = 552960; BR = 6000; break; 2552 case CodecProfileLevel.HEVCMainTierLevel31: 2553 case CodecProfileLevel.HEVCHighTierLevel31: 2554 FR = 33.75; FS = 983040; BR = 10000; break; 2555 case CodecProfileLevel.HEVCMainTierLevel4: 2556 FR = 30; FS = 2228224; BR = 12000; break; 2557 case CodecProfileLevel.HEVCHighTierLevel4: 2558 FR = 30; FS = 2228224; BR = 30000; break; 2559 case CodecProfileLevel.HEVCMainTierLevel41: 2560 FR = 60; FS = 2228224; BR = 20000; break; 2561 case CodecProfileLevel.HEVCHighTierLevel41: 2562 FR = 60; FS = 2228224; BR = 50000; break; 2563 case CodecProfileLevel.HEVCMainTierLevel5: 2564 FR = 30; FS = 8912896; BR = 25000; break; 2565 case CodecProfileLevel.HEVCHighTierLevel5: 2566 FR = 30; FS = 8912896; BR = 100000; break; 2567 case CodecProfileLevel.HEVCMainTierLevel51: 2568 FR = 60; FS = 8912896; BR = 40000; break; 2569 case CodecProfileLevel.HEVCHighTierLevel51: 2570 FR = 60; FS = 8912896; BR = 160000; break; 2571 case CodecProfileLevel.HEVCMainTierLevel52: 2572 FR = 120; FS = 8912896; BR = 60000; break; 2573 case CodecProfileLevel.HEVCHighTierLevel52: 2574 FR = 120; FS = 8912896; BR = 240000; break; 2575 case CodecProfileLevel.HEVCMainTierLevel6: 2576 FR = 30; FS = 35651584; BR = 60000; break; 2577 case CodecProfileLevel.HEVCHighTierLevel6: 2578 FR = 30; FS = 35651584; BR = 240000; break; 2579 case CodecProfileLevel.HEVCMainTierLevel61: 2580 FR = 60; FS = 35651584; BR = 120000; break; 2581 case CodecProfileLevel.HEVCHighTierLevel61: 2582 FR = 60; FS = 35651584; BR = 480000; break; 2583 case CodecProfileLevel.HEVCMainTierLevel62: 2584 FR = 120; FS = 35651584; BR = 240000; break; 2585 case CodecProfileLevel.HEVCHighTierLevel62: 2586 FR = 120; FS = 35651584; BR = 800000; break; 2587 default: 2588 Log.w(TAG, "Unrecognized level " 2589 + profileLevel.level + " for " + mime); 2590 errors |= ERROR_UNRECOGNIZED; 2591 } 2592 switch (profileLevel.profile) { 2593 case CodecProfileLevel.HEVCProfileMain: 2594 case CodecProfileLevel.HEVCProfileMain10: 2595 case CodecProfileLevel.HEVCProfileMain10HDR10: 2596 break; 2597 default: 2598 Log.w(TAG, "Unrecognized profile " 2599 + profileLevel.profile + " for " + mime); 2600 errors |= ERROR_UNRECOGNIZED; 2601 } 2602 2603 /* DPB logic: 2604 if (width * height <= FS / 4) DPB = 16; 2605 else if (width * height <= FS / 2) DPB = 12; 2606 else if (width * height <= FS * 0.75) DPB = 8; 2607 else DPB = 6; 2608 */ 2609 2610 FS >>= 6; // convert pixels to blocks 2611 errors &= ~ERROR_NONE_SUPPORTED; 2612 maxBlocksPerSecond = Math.max((int)(FR * FS), maxBlocksPerSecond); 2613 maxBlocks = Math.max(FS, maxBlocks); 2614 maxBps = Math.max(BR * 1000, maxBps); 2615 } 2616 2617 int maxLengthInBlocks = (int)(Math.sqrt(maxBlocks * 8)); 2618 applyMacroBlockLimits( 2619 maxLengthInBlocks, maxLengthInBlocks, 2620 maxBlocks, maxBlocksPerSecond, 2621 8 /* blockWidth */, 8 /* blockHeight */, 2622 1 /* widthAlignment */, 1 /* heightAlignment */); 2623 } else { 2624 Log.w(TAG, "Unsupported mime " + mime); 2625 // using minimal bitrate here. should be overriden by 2626 // info from media_codecs.xml 2627 maxBps = 64000; 2628 errors |= ERROR_UNSUPPORTED; 2629 } 2630 mBitrateRange = Range.create(1, maxBps); 2631 mParent.mError |= errors; 2632 } 2633 } 2634 2635 /** 2636 * A class that supports querying the encoding capabilities of a codec. 2637 */ 2638 public static final class EncoderCapabilities { 2639 /** 2640 * Returns the supported range of quality values. 2641 * 2642 * @hide 2643 */ getQualityRange()2644 public Range<Integer> getQualityRange() { 2645 return mQualityRange; 2646 } 2647 2648 /** 2649 * Returns the supported range of encoder complexity values. 2650 * <p> 2651 * Some codecs may support multiple complexity levels, where higher 2652 * complexity values use more encoder tools (e.g. perform more 2653 * intensive calculations) to improve the quality or the compression 2654 * ratio. Use a lower value to save power and/or time. 2655 */ getComplexityRange()2656 public Range<Integer> getComplexityRange() { 2657 return mComplexityRange; 2658 } 2659 2660 /** Constant quality mode */ 2661 public static final int BITRATE_MODE_CQ = 0; 2662 /** Variable bitrate mode */ 2663 public static final int BITRATE_MODE_VBR = 1; 2664 /** Constant bitrate mode */ 2665 public static final int BITRATE_MODE_CBR = 2; 2666 2667 private static final Feature[] bitrates = new Feature[] { 2668 new Feature("VBR", BITRATE_MODE_VBR, true), 2669 new Feature("CBR", BITRATE_MODE_CBR, false), 2670 new Feature("CQ", BITRATE_MODE_CQ, false) 2671 }; 2672 parseBitrateMode(String mode)2673 private static int parseBitrateMode(String mode) { 2674 for (Feature feat: bitrates) { 2675 if (feat.mName.equalsIgnoreCase(mode)) { 2676 return feat.mValue; 2677 } 2678 } 2679 return 0; 2680 } 2681 2682 /** 2683 * Query whether a bitrate mode is supported. 2684 */ isBitrateModeSupported(int mode)2685 public boolean isBitrateModeSupported(int mode) { 2686 for (Feature feat: bitrates) { 2687 if (mode == feat.mValue) { 2688 return (mBitControl & (1 << mode)) != 0; 2689 } 2690 } 2691 return false; 2692 } 2693 2694 private Range<Integer> mQualityRange; 2695 private Range<Integer> mComplexityRange; 2696 private CodecCapabilities mParent; 2697 2698 /* no public constructor */ EncoderCapabilities()2699 private EncoderCapabilities() { } 2700 2701 /** @hide */ create( MediaFormat info, CodecCapabilities parent)2702 public static EncoderCapabilities create( 2703 MediaFormat info, CodecCapabilities parent) { 2704 EncoderCapabilities caps = new EncoderCapabilities(); 2705 caps.init(info, parent); 2706 return caps; 2707 } 2708 2709 /** @hide */ init(MediaFormat info, CodecCapabilities parent)2710 public void init(MediaFormat info, CodecCapabilities parent) { 2711 // no support for complexity or quality yet 2712 mParent = parent; 2713 mComplexityRange = Range.create(0, 0); 2714 mQualityRange = Range.create(0, 0); 2715 mBitControl = (1 << BITRATE_MODE_VBR); 2716 2717 applyLevelLimits(); 2718 parseFromInfo(info); 2719 } 2720 applyLevelLimits()2721 private void applyLevelLimits() { 2722 String mime = mParent.getMimeType(); 2723 if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_FLAC)) { 2724 mComplexityRange = Range.create(0, 8); 2725 mBitControl = (1 << BITRATE_MODE_CQ); 2726 } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AMR_NB) 2727 || mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AMR_WB) 2728 || mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_G711_ALAW) 2729 || mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_G711_MLAW) 2730 || mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_MSGSM)) { 2731 mBitControl = (1 << BITRATE_MODE_CBR); 2732 } 2733 } 2734 2735 private int mBitControl; 2736 private Integer mDefaultComplexity; 2737 private Integer mDefaultQuality; 2738 private String mQualityScale; 2739 parseFromInfo(MediaFormat info)2740 private void parseFromInfo(MediaFormat info) { 2741 Map<String, Object> map = info.getMap(); 2742 2743 if (info.containsKey("complexity-range")) { 2744 mComplexityRange = Utils 2745 .parseIntRange(info.getString("complexity-range"), mComplexityRange); 2746 // TODO should we limit this to level limits? 2747 } 2748 if (info.containsKey("quality-range")) { 2749 mQualityRange = Utils 2750 .parseIntRange(info.getString("quality-range"), mQualityRange); 2751 } 2752 if (info.containsKey("feature-bitrate-modes")) { 2753 for (String mode: info.getString("feature-bitrate-modes").split(",")) { 2754 mBitControl |= parseBitrateMode(mode); 2755 } 2756 } 2757 2758 try { 2759 mDefaultComplexity = Integer.parseInt((String)map.get("complexity-default")); 2760 } catch (NumberFormatException e) { } 2761 2762 try { 2763 mDefaultQuality = Integer.parseInt((String)map.get("quality-default")); 2764 } catch (NumberFormatException e) { } 2765 2766 mQualityScale = (String)map.get("quality-scale"); 2767 } 2768 supports( Integer complexity, Integer quality, Integer profile)2769 private boolean supports( 2770 Integer complexity, Integer quality, Integer profile) { 2771 boolean ok = true; 2772 if (ok && complexity != null) { 2773 ok = mComplexityRange.contains(complexity); 2774 } 2775 if (ok && quality != null) { 2776 ok = mQualityRange.contains(quality); 2777 } 2778 if (ok && profile != null) { 2779 for (CodecProfileLevel pl: mParent.profileLevels) { 2780 if (pl.profile == profile) { 2781 profile = null; 2782 break; 2783 } 2784 } 2785 ok = profile == null; 2786 } 2787 return ok; 2788 } 2789 2790 /** @hide */ setDefaultFormat(MediaFormat format)2791 public void setDefaultFormat(MediaFormat format) { 2792 // don't list trivial quality/complexity as default for now 2793 if (!mQualityRange.getUpper().equals(mQualityRange.getLower()) 2794 && mDefaultQuality != null) { 2795 format.setInteger(MediaFormat.KEY_QUALITY, mDefaultQuality); 2796 } 2797 if (!mComplexityRange.getUpper().equals(mComplexityRange.getLower()) 2798 && mDefaultComplexity != null) { 2799 format.setInteger(MediaFormat.KEY_COMPLEXITY, mDefaultComplexity); 2800 } 2801 // bitrates are listed in order of preference 2802 for (Feature feat: bitrates) { 2803 if ((mBitControl & (1 << feat.mValue)) != 0) { 2804 format.setInteger(MediaFormat.KEY_BITRATE_MODE, feat.mValue); 2805 break; 2806 } 2807 } 2808 } 2809 2810 /** @hide */ supportsFormat(MediaFormat format)2811 public boolean supportsFormat(MediaFormat format) { 2812 final Map<String, Object> map = format.getMap(); 2813 final String mime = mParent.getMimeType(); 2814 2815 Integer mode = (Integer)map.get(MediaFormat.KEY_BITRATE_MODE); 2816 if (mode != null && !isBitrateModeSupported(mode)) { 2817 return false; 2818 } 2819 2820 Integer complexity = (Integer)map.get(MediaFormat.KEY_COMPLEXITY); 2821 if (MediaFormat.MIMETYPE_AUDIO_FLAC.equalsIgnoreCase(mime)) { 2822 Integer flacComplexity = 2823 (Integer)map.get(MediaFormat.KEY_FLAC_COMPRESSION_LEVEL); 2824 if (complexity == null) { 2825 complexity = flacComplexity; 2826 } else if (flacComplexity != null && !complexity.equals(flacComplexity)) { 2827 throw new IllegalArgumentException( 2828 "conflicting values for complexity and " + 2829 "flac-compression-level"); 2830 } 2831 } 2832 2833 // other audio parameters 2834 Integer profile = (Integer)map.get(MediaFormat.KEY_PROFILE); 2835 if (MediaFormat.MIMETYPE_AUDIO_AAC.equalsIgnoreCase(mime)) { 2836 Integer aacProfile = (Integer)map.get(MediaFormat.KEY_AAC_PROFILE); 2837 if (profile == null) { 2838 profile = aacProfile; 2839 } else if (aacProfile != null && !aacProfile.equals(profile)) { 2840 throw new IllegalArgumentException( 2841 "conflicting values for profile and aac-profile"); 2842 } 2843 } 2844 2845 Integer quality = (Integer)map.get(MediaFormat.KEY_QUALITY); 2846 2847 return supports(complexity, quality, profile); 2848 } 2849 }; 2850 2851 /** 2852 * Encapsulates the profiles available for a codec component. 2853 * <p>You can get a set of {@link MediaCodecInfo.CodecProfileLevel} objects for a given 2854 * {@link MediaCodecInfo} object from the 2855 * {@link MediaCodecInfo.CodecCapabilities#profileLevels} field. 2856 */ 2857 public static final class CodecProfileLevel { 2858 // from OMX_VIDEO_AVCPROFILETYPE 2859 public static final int AVCProfileBaseline = 0x01; 2860 public static final int AVCProfileMain = 0x02; 2861 public static final int AVCProfileExtended = 0x04; 2862 public static final int AVCProfileHigh = 0x08; 2863 public static final int AVCProfileHigh10 = 0x10; 2864 public static final int AVCProfileHigh422 = 0x20; 2865 public static final int AVCProfileHigh444 = 0x40; 2866 public static final int AVCProfileConstrainedBaseline = 0x10000; 2867 public static final int AVCProfileConstrainedHigh = 0x80000; 2868 2869 // from OMX_VIDEO_AVCLEVELTYPE 2870 public static final int AVCLevel1 = 0x01; 2871 public static final int AVCLevel1b = 0x02; 2872 public static final int AVCLevel11 = 0x04; 2873 public static final int AVCLevel12 = 0x08; 2874 public static final int AVCLevel13 = 0x10; 2875 public static final int AVCLevel2 = 0x20; 2876 public static final int AVCLevel21 = 0x40; 2877 public static final int AVCLevel22 = 0x80; 2878 public static final int AVCLevel3 = 0x100; 2879 public static final int AVCLevel31 = 0x200; 2880 public static final int AVCLevel32 = 0x400; 2881 public static final int AVCLevel4 = 0x800; 2882 public static final int AVCLevel41 = 0x1000; 2883 public static final int AVCLevel42 = 0x2000; 2884 public static final int AVCLevel5 = 0x4000; 2885 public static final int AVCLevel51 = 0x8000; 2886 public static final int AVCLevel52 = 0x10000; 2887 2888 // from OMX_VIDEO_H263PROFILETYPE 2889 public static final int H263ProfileBaseline = 0x01; 2890 public static final int H263ProfileH320Coding = 0x02; 2891 public static final int H263ProfileBackwardCompatible = 0x04; 2892 public static final int H263ProfileISWV2 = 0x08; 2893 public static final int H263ProfileISWV3 = 0x10; 2894 public static final int H263ProfileHighCompression = 0x20; 2895 public static final int H263ProfileInternet = 0x40; 2896 public static final int H263ProfileInterlace = 0x80; 2897 public static final int H263ProfileHighLatency = 0x100; 2898 2899 // from OMX_VIDEO_H263LEVELTYPE 2900 public static final int H263Level10 = 0x01; 2901 public static final int H263Level20 = 0x02; 2902 public static final int H263Level30 = 0x04; 2903 public static final int H263Level40 = 0x08; 2904 public static final int H263Level45 = 0x10; 2905 public static final int H263Level50 = 0x20; 2906 public static final int H263Level60 = 0x40; 2907 public static final int H263Level70 = 0x80; 2908 2909 // from OMX_VIDEO_MPEG4PROFILETYPE 2910 public static final int MPEG4ProfileSimple = 0x01; 2911 public static final int MPEG4ProfileSimpleScalable = 0x02; 2912 public static final int MPEG4ProfileCore = 0x04; 2913 public static final int MPEG4ProfileMain = 0x08; 2914 public static final int MPEG4ProfileNbit = 0x10; 2915 public static final int MPEG4ProfileScalableTexture = 0x20; 2916 public static final int MPEG4ProfileSimpleFace = 0x40; 2917 public static final int MPEG4ProfileSimpleFBA = 0x80; 2918 public static final int MPEG4ProfileBasicAnimated = 0x100; 2919 public static final int MPEG4ProfileHybrid = 0x200; 2920 public static final int MPEG4ProfileAdvancedRealTime = 0x400; 2921 public static final int MPEG4ProfileCoreScalable = 0x800; 2922 public static final int MPEG4ProfileAdvancedCoding = 0x1000; 2923 public static final int MPEG4ProfileAdvancedCore = 0x2000; 2924 public static final int MPEG4ProfileAdvancedScalable = 0x4000; 2925 public static final int MPEG4ProfileAdvancedSimple = 0x8000; 2926 2927 // from OMX_VIDEO_MPEG4LEVELTYPE 2928 public static final int MPEG4Level0 = 0x01; 2929 public static final int MPEG4Level0b = 0x02; 2930 public static final int MPEG4Level1 = 0x04; 2931 public static final int MPEG4Level2 = 0x08; 2932 public static final int MPEG4Level3 = 0x10; 2933 public static final int MPEG4Level3b = 0x18; 2934 public static final int MPEG4Level4 = 0x20; 2935 public static final int MPEG4Level4a = 0x40; 2936 public static final int MPEG4Level5 = 0x80; 2937 public static final int MPEG4Level6 = 0x100; 2938 2939 // from OMX_VIDEO_MPEG2PROFILETYPE 2940 public static final int MPEG2ProfileSimple = 0x00; 2941 public static final int MPEG2ProfileMain = 0x01; 2942 public static final int MPEG2Profile422 = 0x02; 2943 public static final int MPEG2ProfileSNR = 0x03; 2944 public static final int MPEG2ProfileSpatial = 0x04; 2945 public static final int MPEG2ProfileHigh = 0x05; 2946 2947 // from OMX_VIDEO_MPEG2LEVELTYPE 2948 public static final int MPEG2LevelLL = 0x00; 2949 public static final int MPEG2LevelML = 0x01; 2950 public static final int MPEG2LevelH14 = 0x02; 2951 public static final int MPEG2LevelHL = 0x03; 2952 public static final int MPEG2LevelHP = 0x04; 2953 2954 // from OMX_AUDIO_AACPROFILETYPE 2955 public static final int AACObjectMain = 1; 2956 public static final int AACObjectLC = 2; 2957 public static final int AACObjectSSR = 3; 2958 public static final int AACObjectLTP = 4; 2959 public static final int AACObjectHE = 5; 2960 public static final int AACObjectScalable = 6; 2961 public static final int AACObjectERLC = 17; 2962 public static final int AACObjectERScalable = 20; 2963 public static final int AACObjectLD = 23; 2964 public static final int AACObjectHE_PS = 29; 2965 public static final int AACObjectELD = 39; 2966 2967 // from OMX_VIDEO_VP8LEVELTYPE 2968 public static final int VP8Level_Version0 = 0x01; 2969 public static final int VP8Level_Version1 = 0x02; 2970 public static final int VP8Level_Version2 = 0x04; 2971 public static final int VP8Level_Version3 = 0x08; 2972 2973 // from OMX_VIDEO_VP8PROFILETYPE 2974 public static final int VP8ProfileMain = 0x01; 2975 2976 // from OMX_VIDEO_VP9PROFILETYPE 2977 public static final int VP9Profile0 = 0x01; 2978 public static final int VP9Profile1 = 0x02; 2979 public static final int VP9Profile2 = 0x04; 2980 public static final int VP9Profile3 = 0x08; 2981 // HDR profiles also support passing HDR metadata 2982 public static final int VP9Profile2HDR = 0x1000; 2983 public static final int VP9Profile3HDR = 0x2000; 2984 2985 // from OMX_VIDEO_VP9LEVELTYPE 2986 public static final int VP9Level1 = 0x1; 2987 public static final int VP9Level11 = 0x2; 2988 public static final int VP9Level2 = 0x4; 2989 public static final int VP9Level21 = 0x8; 2990 public static final int VP9Level3 = 0x10; 2991 public static final int VP9Level31 = 0x20; 2992 public static final int VP9Level4 = 0x40; 2993 public static final int VP9Level41 = 0x80; 2994 public static final int VP9Level5 = 0x100; 2995 public static final int VP9Level51 = 0x200; 2996 public static final int VP9Level52 = 0x400; 2997 public static final int VP9Level6 = 0x800; 2998 public static final int VP9Level61 = 0x1000; 2999 public static final int VP9Level62 = 0x2000; 3000 3001 // from OMX_VIDEO_HEVCPROFILETYPE 3002 public static final int HEVCProfileMain = 0x01; 3003 public static final int HEVCProfileMain10 = 0x02; 3004 public static final int HEVCProfileMain10HDR10 = 0x1000; 3005 3006 // from OMX_VIDEO_HEVCLEVELTYPE 3007 public static final int HEVCMainTierLevel1 = 0x1; 3008 public static final int HEVCHighTierLevel1 = 0x2; 3009 public static final int HEVCMainTierLevel2 = 0x4; 3010 public static final int HEVCHighTierLevel2 = 0x8; 3011 public static final int HEVCMainTierLevel21 = 0x10; 3012 public static final int HEVCHighTierLevel21 = 0x20; 3013 public static final int HEVCMainTierLevel3 = 0x40; 3014 public static final int HEVCHighTierLevel3 = 0x80; 3015 public static final int HEVCMainTierLevel31 = 0x100; 3016 public static final int HEVCHighTierLevel31 = 0x200; 3017 public static final int HEVCMainTierLevel4 = 0x400; 3018 public static final int HEVCHighTierLevel4 = 0x800; 3019 public static final int HEVCMainTierLevel41 = 0x1000; 3020 public static final int HEVCHighTierLevel41 = 0x2000; 3021 public static final int HEVCMainTierLevel5 = 0x4000; 3022 public static final int HEVCHighTierLevel5 = 0x8000; 3023 public static final int HEVCMainTierLevel51 = 0x10000; 3024 public static final int HEVCHighTierLevel51 = 0x20000; 3025 public static final int HEVCMainTierLevel52 = 0x40000; 3026 public static final int HEVCHighTierLevel52 = 0x80000; 3027 public static final int HEVCMainTierLevel6 = 0x100000; 3028 public static final int HEVCHighTierLevel6 = 0x200000; 3029 public static final int HEVCMainTierLevel61 = 0x400000; 3030 public static final int HEVCHighTierLevel61 = 0x800000; 3031 public static final int HEVCMainTierLevel62 = 0x1000000; 3032 public static final int HEVCHighTierLevel62 = 0x2000000; 3033 3034 private static final int HEVCHighTierLevels = 3035 HEVCHighTierLevel1 | HEVCHighTierLevel2 | HEVCHighTierLevel21 | HEVCHighTierLevel3 | 3036 HEVCHighTierLevel31 | HEVCHighTierLevel4 | HEVCHighTierLevel41 | HEVCHighTierLevel5 | 3037 HEVCHighTierLevel51 | HEVCHighTierLevel52 | HEVCHighTierLevel6 | HEVCHighTierLevel61 | 3038 HEVCHighTierLevel62; 3039 3040 // from OMX_VIDEO_DOLBYVISIONPROFILETYPE 3041 public static final int DolbyVisionProfileDvavPer = 0x1; 3042 public static final int DolbyVisionProfileDvavPen = 0x2; 3043 public static final int DolbyVisionProfileDvheDer = 0x4; 3044 public static final int DolbyVisionProfileDvheDen = 0x8; 3045 public static final int DolbyVisionProfileDvheDtr = 0x10; 3046 public static final int DolbyVisionProfileDvheStn = 0x20; 3047 public static final int DolbyVisionProfileDvheDth = 0x40; 3048 public static final int DolbyVisionProfileDvheDtb = 0x80; 3049 public static final int DolbyVisionProfileDvheSt = 0x100; 3050 public static final int DolbyVisionProfileDvavSe = 0x200; 3051 3052 // from OMX_VIDEO_DOLBYVISIONLEVELTYPE 3053 public static final int DolbyVisionLevelHd24 = 0x1; 3054 public static final int DolbyVisionLevelHd30 = 0x2; 3055 public static final int DolbyVisionLevelFhd24 = 0x4; 3056 public static final int DolbyVisionLevelFhd30 = 0x8; 3057 public static final int DolbyVisionLevelFhd60 = 0x10; 3058 public static final int DolbyVisionLevelUhd24 = 0x20; 3059 public static final int DolbyVisionLevelUhd30 = 0x40; 3060 public static final int DolbyVisionLevelUhd48 = 0x80; 3061 public static final int DolbyVisionLevelUhd60 = 0x100; 3062 3063 /** 3064 * Defined in the OpenMAX IL specs, depending on the type of media 3065 * this can be OMX_VIDEO_AVCPROFILETYPE, OMX_VIDEO_H263PROFILETYPE, 3066 * OMX_VIDEO_MPEG4PROFILETYPE, OMX_VIDEO_VP8PROFILETYPE or OMX_VIDEO_VP9PROFILETYPE. 3067 */ 3068 public int profile; 3069 3070 /** 3071 * Defined in the OpenMAX IL specs, depending on the type of media 3072 * this can be OMX_VIDEO_AVCLEVELTYPE, OMX_VIDEO_H263LEVELTYPE 3073 * OMX_VIDEO_MPEG4LEVELTYPE, OMX_VIDEO_VP8LEVELTYPE or OMX_VIDEO_VP9LEVELTYPE. 3074 * 3075 * Note that VP9 decoder on platforms before {@link android.os.Build.VERSION_CODES#N} may 3076 * not advertise a profile level support. For those VP9 decoders, please use 3077 * {@link VideoCapabilities} to determine the codec capabilities. 3078 */ 3079 public int level; 3080 }; 3081 3082 /** 3083 * Enumerates the capabilities of the codec component. Since a single 3084 * component can support data of a variety of types, the type has to be 3085 * specified to yield a meaningful result. 3086 * @param type The MIME type to query 3087 */ getCapabilitiesForType( String type)3088 public final CodecCapabilities getCapabilitiesForType( 3089 String type) { 3090 CodecCapabilities caps = mCaps.get(type); 3091 if (caps == null) { 3092 throw new IllegalArgumentException("codec does not support type"); 3093 } 3094 // clone writable object 3095 return caps.dup(); 3096 } 3097 3098 /** @hide */ makeRegular()3099 public MediaCodecInfo makeRegular() { 3100 ArrayList<CodecCapabilities> caps = new ArrayList<CodecCapabilities>(); 3101 for (CodecCapabilities c: mCaps.values()) { 3102 if (c.isRegular()) { 3103 caps.add(c); 3104 } 3105 } 3106 if (caps.size() == 0) { 3107 return null; 3108 } else if (caps.size() == mCaps.size()) { 3109 return this; 3110 } 3111 3112 return new MediaCodecInfo( 3113 mName, mIsEncoder, 3114 caps.toArray(new CodecCapabilities[caps.size()])); 3115 } 3116 } 3117