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