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