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