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