Home | History | Annotate | Download | only in media
      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 &lt; 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 &lt; 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