160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber/*
260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * Copyright (C) 2012 The Android Open Source Project
360d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber *
460d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
560d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * you may not use this file except in compliance with the License.
660d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * You may obtain a copy of the License at
760d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber *
860d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
960d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber *
1060d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * Unless required by applicable law or agreed to in writing, software
1160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
1260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1360d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * See the License for the specific language governing permissions and
1460d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber * limitations under the License.
1560d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber */
1660d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber
1760d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huberpackage android.media;
1860d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber
1975c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wuimport android.annotation.NonNull;
2075c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wuimport android.annotation.Nullable;
21b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnarimport android.util.Log;
22b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnarimport android.util.Pair;
23b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnarimport android.util.Range;
24b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnarimport android.util.Rational;
25b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnarimport android.util.Size;
26b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
27b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnarimport java.util.ArrayList;
28b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnarimport java.util.Arrays;
29b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnarimport java.util.HashMap;
30b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnarimport java.util.Map;
31b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnarimport java.util.Set;
32b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
33b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnarimport static android.media.Utils.intersectSortedDistinctRanges;
34b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnarimport static android.media.Utils.sortDistinctRanges;
35b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
36c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main/**
37c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main * Provides information about a given media codec available on the device. You can
38c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main * iterate through all codecs available by querying {@link MediaCodecList}. For example,
39c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main * here's how to find an encoder that supports a given MIME type:
40c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main * <pre>
41c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main * private static MediaCodecInfo selectCodec(String mimeType) {
42c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main *     int numCodecs = MediaCodecList.getCodecCount();
43c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main *     for (int i = 0; i &lt; numCodecs; i++) {
44c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main *         MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
45c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main *
46c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main *         if (!codecInfo.isEncoder()) {
47c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main *             continue;
48c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main *         }
49c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main *
50c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main *         String[] types = codecInfo.getSupportedTypes();
51c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main *         for (int j = 0; j &lt; types.length; j++) {
52c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main *             if (types[j].equalsIgnoreCase(mimeType)) {
53c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main *                 return codecInfo;
54c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main *             }
55c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main *         }
56c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main *     }
57c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main *     return null;
58c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main * }</pre>
59c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main *
60c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main */
6160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huberpublic final class MediaCodecInfo {
62b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    private boolean mIsEncoder;
63b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    private String mName;
64b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    private Map<String, CodecCapabilities> mCaps;
6560d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber
66b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    /* package private */ MediaCodecInfo(
67b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            String name, boolean isEncoder, CodecCapabilities[] caps) {
68b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        mName = name;
69b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        mIsEncoder = isEncoder;
70b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        mCaps = new HashMap<String, CodecCapabilities>();
71b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        for (CodecCapabilities c: caps) {
72217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mCaps.put(c.getMimeType(), c);
73b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
7460d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber    }
7560d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber
7660d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber    /**
7760d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber     * Retrieve the codec name.
7860d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber     */
7960d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber    public final String getName() {
80b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        return mName;
8160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber    }
8260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber
8360d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber    /**
8460d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber     * Query if the codec is an encoder.
8560d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber     */
8660d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber    public final boolean isEncoder() {
87b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        return mIsEncoder;
8860d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber    }
8960d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber
9060d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber    /**
9160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber     * Query the media types supported by the codec.
9260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber     */
9360d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber    public final String[] getSupportedTypes() {
94b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        Set<String> typeSet = mCaps.keySet();
95b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        String[] types = typeSet.toArray(new String[typeSet.size()]);
96b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        Arrays.sort(types);
97b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        return types;
9860d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber    }
9960d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber
100217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    private static int checkPowerOfTwo(int value, String message) {
101217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        if ((value & (value - 1)) != 0) {
102217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            throw new IllegalArgumentException(message);
103217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
104217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        return value;
105217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    }
106217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
107217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    private static class Feature {
108217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public String mName;
109217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public int mValue;
110217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public boolean mDefault;
111217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public Feature(String name, int value, boolean def) {
112217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mName = name;
113217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mValue = value;
114217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mDefault = def;
115217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
116217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    }
117217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
118217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    // COMMON CONSTANTS
119217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    private static final Range<Integer> POSITIVE_INTEGERS =
120217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        Range.create(1, Integer.MAX_VALUE);
121217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    private static final Range<Long> POSITIVE_LONGS =
122217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        Range.create(1l, Long.MAX_VALUE);
123217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    private static final Range<Rational> POSITIVE_RATIONALS =
124217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        Range.create(new Rational(1, Integer.MAX_VALUE),
125217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                     new Rational(Integer.MAX_VALUE, 1));
126217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    private static final Range<Integer> SIZE_RANGE = Range.create(1, 32768);
127217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    private static final Range<Integer> FRAME_RATE_RANGE = Range.create(0, 960);
128216e11dcbb4d56699c1740c801489be0d57b16c4Chong Zhang    private static final Range<Integer> BITRATE_RANGE = Range.create(0, 500000000);
129ee2997577db8d9e3e52593b9ca454386f703d710Ronghua Wu    private static final int DEFAULT_MAX_SUPPORTED_INSTANCES = 32;
130ee2997577db8d9e3e52593b9ca454386f703d710Ronghua Wu    private static final int MAX_SUPPORTED_INSTANCES_LIMIT = 256;
131217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
132217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    // found stuff that is not supported by framework (=> this should not happen)
133217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    private static final int ERROR_UNRECOGNIZED   = (1 << 0);
134217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    // found profile/level for which we don't have capability estimates
135217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    private static final int ERROR_UNSUPPORTED    = (1 << 1);
136217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    // have not found any profile/level for which we don't have capability estimate
137217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    private static final int ERROR_NONE_SUPPORTED = (1 << 2);
138217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
139217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
140ba9269a5855b6d9d581af09077caafbd45180b41Andreas Huber    /**
141c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main     * Encapsulates the capabilities of a given codec component.
142c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main     * For example, what profile/level combinations it supports and what colorspaces
14380c4437ebfe3e679267a64e4c9d7bdd585b7afceLajos Molnar     * it is capable of providing the decoded data in, as well as some
14480c4437ebfe3e679267a64e4c9d7bdd585b7afceLajos Molnar     * codec-type specific capability flags.
145c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main     * <p>You can get an instance for a given {@link MediaCodecInfo} object with
146c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main     * {@link MediaCodecInfo#getCapabilitiesForType getCapabilitiesForType()}, passing a MIME type.
147ba9269a5855b6d9d581af09077caafbd45180b41Andreas Huber     */
14860d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber    public static final class CodecCapabilities {
149b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public CodecCapabilities() {
150b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
151b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
152b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        // CLASSIFICATION
153b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        private String mMime;
154ee2997577db8d9e3e52593b9ca454386f703d710Ronghua Wu        private int mMaxSupportedInstances;
155b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
156b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        // LEGACY FIELDS
157b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
158ba9269a5855b6d9d581af09077caafbd45180b41Andreas Huber        // Enumerates supported profile/level combinations as defined
159ba9269a5855b6d9d581af09077caafbd45180b41Andreas Huber        // by the type of encoded data. These combinations impose restrictions
160ba9269a5855b6d9d581af09077caafbd45180b41Andreas Huber        // on video resolution, bitrate... and limit the available encoder tools
161ba9269a5855b6d9d581af09077caafbd45180b41Andreas Huber        // such as B-frame support, arithmetic coding...
162b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public CodecProfileLevel[] profileLevels;  // NOTE this array is modifiable by user
16360d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber
16460d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        // from OMX_COLOR_FORMATTYPE
165e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar        /** @deprecated Use {@link #COLOR_Format24bitBGR888}. */
166b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatMonochrome              = 1;
167e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar        /** @deprecated Use {@link #COLOR_Format24bitBGR888}. */
168b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_Format8bitRGB332              = 2;
169e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar        /** @deprecated Use {@link #COLOR_Format24bitBGR888}. */
170b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_Format12bitRGB444             = 3;
171e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar        /** @deprecated Use {@link #COLOR_Format32bitABGR8888}. */
172b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_Format16bitARGB4444           = 4;
173e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar        /** @deprecated Use {@link #COLOR_Format32bitABGR8888}. */
174b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_Format16bitARGB1555           = 5;
175b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar
176b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar        /**
177b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         * 16 bits per pixel RGB color format, with 5-bit red & blue and 6-bit green component.
178b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         * <p>
179e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * Using 16-bit little-endian representation, colors stored as Red 15:11, Green 10:5, Blue 4:0.
180b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         * <pre>
181b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         *            byte                   byte
182b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         *  <--------- i --------> | <------ i + 1 ------>
183b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
184b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         * |     BLUE     |      GREEN      |     RED      |
185b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
186b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         *  0           4  5     7   0     2  3           7
187b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         * bit
188b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         * </pre>
189e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         *
190e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * This format corresponds to {@link android.graphics.PixelFormat#RGB_565} and
191e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * {@link android.graphics.ImageFormat#RGB_565}.
192b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         */
193b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_Format16bitRGB565             = 6;
194b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar        /** @deprecated Use {@link #COLOR_Format16bitRGB565}. */
195b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_Format16bitBGR565             = 7;
196e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar        /** @deprecated Use {@link #COLOR_Format24bitBGR888}. */
197b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_Format18bitRGB666             = 8;
198e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar        /** @deprecated Use {@link #COLOR_Format32bitABGR8888}. */
199b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_Format18bitARGB1665           = 9;
200e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar        /** @deprecated Use {@link #COLOR_Format32bitABGR8888}. */
201b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_Format19bitARGB1666           = 10;
202b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar
203e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar        /** @deprecated Use {@link #COLOR_Format24bitBGR888} or {@link #COLOR_FormatRGBFlexible}. */
204e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar        public static final int COLOR_Format24bitRGB888             = 11;
205e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar
206b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar        /**
207b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         * 24 bits per pixel RGB color format, with 8-bit red, green & blue components.
208b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         * <p>
209e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * Using 24-bit little-endian representation, colors stored as Red 7:0, Green 15:8, Blue 23:16.
210b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         * <pre>
211b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         *         byte              byte             byte
212b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         *  <------ i -----> | <---- i+1 ----> | <---- i+2 ----->
213b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         * +-----------------+-----------------+-----------------+
214e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * |       RED       |      GREEN      |       BLUE      |
215b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         * +-----------------+-----------------+-----------------+
216b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         * </pre>
217e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         *
218e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * This format corresponds to {@link android.graphics.PixelFormat#RGB_888}, and can also be
219e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * represented as a flexible format by {@link #COLOR_FormatRGBFlexible}.
220b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         */
221b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_Format24bitBGR888             = 12;
222e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar        /** @deprecated Use {@link #COLOR_Format32bitABGR8888}. */
223b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_Format24bitARGB1887           = 13;
224e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar        /** @deprecated Use {@link #COLOR_Format32bitABGR8888}. */
225b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_Format25bitARGB1888           = 14;
226b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar
227b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar        /**
228e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * @deprecated Use {@link #COLOR_Format32bitABGR8888} Or {@link #COLOR_FormatRGBAFlexible}.
229b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         */
230b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_Format32bitBGRA8888           = 15;
231b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar        /**
232e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * @deprecated Use {@link #COLOR_Format32bitABGR8888} Or {@link #COLOR_FormatRGBAFlexible}.
233b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         */
234b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_Format32bitARGB8888           = 16;
235b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar        /** @deprecated Use {@link #COLOR_FormatYUV420Flexible}. */
236b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatYUV411Planar            = 17;
237b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar        /** @deprecated Use {@link #COLOR_FormatYUV420Flexible}. */
238b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatYUV411PackedPlanar      = 18;
239b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar        /** @deprecated Use {@link #COLOR_FormatYUV420Flexible}. */
240b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatYUV420Planar            = 19;
241b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar        /** @deprecated Use {@link #COLOR_FormatYUV420Flexible}. */
242b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatYUV420PackedPlanar      = 20;
243b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar        /** @deprecated Use {@link #COLOR_FormatYUV420Flexible}. */
244b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatYUV420SemiPlanar        = 21;
245b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar
246b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar        /** @deprecated Use {@link #COLOR_FormatYUV422Flexible}. */
247b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatYUV422Planar            = 22;
248b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar        /** @deprecated Use {@link #COLOR_FormatYUV422Flexible}. */
249b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatYUV422PackedPlanar      = 23;
250b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar        /** @deprecated Use {@link #COLOR_FormatYUV422Flexible}. */
251b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatYUV422SemiPlanar        = 24;
252b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar
253b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar        /** @deprecated Use {@link #COLOR_FormatYUV422Flexible}. */
254b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatYCbYCr                  = 25;
255b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar        /** @deprecated Use {@link #COLOR_FormatYUV422Flexible}. */
256b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatYCrYCb                  = 26;
257b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar        /** @deprecated Use {@link #COLOR_FormatYUV422Flexible}. */
258b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatCbYCrY                  = 27;
259b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar        /** @deprecated Use {@link #COLOR_FormatYUV422Flexible}. */
260b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatCrYCbY                  = 28;
261b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar
262e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar        /** @deprecated Use {@link #COLOR_FormatYUV444Flexible}. */
263b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatYUV444Interleaved       = 29;
264b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar
265e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar        /**
266e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * SMIA 8-bit Bayer format.
267e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * Each byte represents the top 8-bits of a 10-bit signal.
268e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         */
269b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatRawBayer8bit            = 30;
270e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar        /**
271e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * SMIA 10-bit Bayer format.
272e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         */
273b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatRawBayer10bit           = 31;
274e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar
275e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar        /**
276e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * SMIA 8-bit compressed Bayer format.
277e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * Each byte represents a sample from the 10-bit signal that is compressed into 8-bits
278e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * using DPCM/PCM compression, as defined by the SMIA Functional Specification.
279e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         */
280b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatRawBayer8bitcompressed  = 32;
281b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar
282b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar        /** @deprecated Use {@link #COLOR_FormatL8}. */
283b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatL2                      = 33;
284b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar        /** @deprecated Use {@link #COLOR_FormatL8}. */
285b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatL4                      = 34;
286b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar
287b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar        /**
288b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         * 8 bits per pixel Y color format.
289b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         * <p>
290b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         * Each byte contains a single pixel.
291e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * This format corresponds to {@link android.graphics.PixelFormat#L_8}.
292b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         */
293b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatL8                      = 35;
294b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar
295b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar        /**
296b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         * 16 bits per pixel, little-endian Y color format.
297b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         * <p>
298b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         * <pre>
299b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         *            byte                   byte
300b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         *  <--------- i --------> | <------ i + 1 ------>
301b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
302b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         * |                       Y                       |
303b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
304b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         *  0                    7   0                    7
305b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         * bit
306b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         * </pre>
307b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         */
308b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatL16                     = 36;
309e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar        /** @deprecated Use {@link #COLOR_FormatL16}. */
310b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatL24                     = 37;
311b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar
312b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar        /**
313b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         * 32 bits per pixel, little-endian Y color format.
314b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         * <p>
315b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         * <pre>
316b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         *         byte              byte             byte              byte
317b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         *  <------ i -----> | <---- i+1 ----> | <---- i+2 ----> | <---- i+3 ----->
318b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         * +-----------------+-----------------+-----------------+-----------------+
319b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         * |                                   Y                                   |
320b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         * +-----------------+-----------------+-----------------+-----------------+
321b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         *  0               7 0               7 0               7 0               7
322b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         * bit
323b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         * </pre>
324e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         *
325e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * @deprecated Use {@link #COLOR_FormatL16}.
326b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         */
327b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatL32                     = 38;
328b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar
329b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar        /** @deprecated Use {@link #COLOR_FormatYUV420Flexible}. */
330b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatYUV420PackedSemiPlanar  = 39;
331b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar        /** @deprecated Use {@link #COLOR_FormatYUV422Flexible}. */
332b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatYUV422PackedSemiPlanar  = 40;
333b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar
334e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar        /** @deprecated Use {@link #COLOR_Format24bitBGR888}. */
335b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_Format18BitBGR666             = 41;
336b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar
337e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar        /** @deprecated Use {@link #COLOR_Format32bitABGR8888}. */
338b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_Format24BitARGB6666           = 42;
339e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar        /** @deprecated Use {@link #COLOR_Format32bitABGR8888}. */
340b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_Format24BitABGR6666           = 43;
341b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
342b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar        /** @deprecated Use {@link #COLOR_FormatYUV420Flexible}. */
343b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_TI_FormatYUV420PackedSemiPlanar = 0x7f000100;
34434f17dd1f615c6285f4f344eb700923e2432e48eAndy McFadden        // COLOR_FormatSurface indicates that the data will be a GraphicBuffer metadata reference.
34534f17dd1f615c6285f4f344eb700923e2432e48eAndy McFadden        // In OMX this is called OMX_COLOR_FormatAndroidOpaque.
346b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatSurface                   = 0x7F000789;
347b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar
348e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar        /**
349e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * 32 bits per pixel RGBA color format, with 8-bit red, green, blue, and alpha components.
350e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * <p>
351e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * Using 32-bit little-endian representation, colors stored as Red 7:0, Green 15:8,
352e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * Blue 23:16, and Alpha 31:24.
353e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * <pre>
354e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         *         byte              byte             byte              byte
355e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         *  <------ i -----> | <---- i+1 ----> | <---- i+2 ----> | <---- i+3 ----->
356e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * +-----------------+-----------------+-----------------+-----------------+
357e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * |       RED       |      GREEN      |       BLUE      |      ALPHA      |
358e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * +-----------------+-----------------+-----------------+-----------------+
359e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * </pre>
360e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         *
361e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * This corresponds to {@link android.graphics.PixelFormat#RGBA_8888}.
362e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         */
363e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar        public static final int COLOR_Format32bitABGR8888             = 0x7F00A000;
364b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar
365b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar        /**
366b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         * Flexible 12 bits per pixel, subsampled YUV color format with 8-bit chroma and luma
367b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         * components.
368b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         * <p>
369b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         * Chroma planes are subsampled by 2 both horizontally and vertically.
370b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         * Use this format with {@link Image}.
371e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * This format corresponds to {@link android.graphics.ImageFormat#YUV_420_888},
372e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * and can represent the {@link #COLOR_FormatYUV411Planar},
373e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * {@link #COLOR_FormatYUV411PackedPlanar}, {@link #COLOR_FormatYUV420Planar},
374e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * {@link #COLOR_FormatYUV420PackedPlanar}, {@link #COLOR_FormatYUV420SemiPlanar}
375e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * and {@link #COLOR_FormatYUV420PackedSemiPlanar} formats.
376b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         *
377b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         * @see Image#getFormat
378b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         */
379b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatYUV420Flexible            = 0x7F420888;
380b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar
381b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar        /**
382b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         * Flexible 16 bits per pixel, subsampled YUV color format with 8-bit chroma and luma
383b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         * components.
384b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         * <p>
385e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * Chroma planes are horizontally subsampled by 2. Use this format with {@link Image}.
386e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * This format corresponds to {@link android.graphics.ImageFormat#YUV_422_888},
387e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * and can represent the {@link #COLOR_FormatYCbYCr}, {@link #COLOR_FormatYCrYCb},
388e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * {@link #COLOR_FormatCbYCrY}, {@link #COLOR_FormatCrYCbY},
389e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * {@link #COLOR_FormatYUV422Planar}, {@link #COLOR_FormatYUV422PackedPlanar},
390e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * {@link #COLOR_FormatYUV422SemiPlanar} and {@link #COLOR_FormatYUV422PackedSemiPlanar}
391e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * formats.
392b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         *
393b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         * @see Image#getFormat
394b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar         */
395b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar        public static final int COLOR_FormatYUV422Flexible            = 0x7F422888;
396b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar
397e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar        /**
398e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * Flexible 24 bits per pixel YUV color format with 8-bit chroma and luma
399e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * components.
400e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * <p>
401e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * Chroma planes are not subsampled. Use this format with {@link Image}.
402e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * This format corresponds to {@link android.graphics.ImageFormat#YUV_444_888},
403e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * and can represent the {@link #COLOR_FormatYUV444Interleaved} format.
404e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * @see Image#getFormat
405e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         */
406e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar        public static final int COLOR_FormatYUV444Flexible            = 0x7F444888;
407e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar
408e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar        /**
409e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * Flexible 24 bits per pixel RGB color format with 8-bit red, green and blue
410e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * components.
411e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * <p>
412e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * Use this format with {@link Image}. This format corresponds to
413e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * {@link android.graphics.ImageFormat#FLEX_RGB_888}, and can represent
414e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * {@link #COLOR_Format24bitBGR888} and {@link #COLOR_Format24bitRGB888} formats.
415e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * @see Image#getFormat.
416e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         */
417e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar        public static final int COLOR_FormatRGBFlexible               = 0x7F36B888;
418e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar
419e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar        /**
420e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * Flexible 32 bits per pixel RGBA color format with 8-bit red, green, blue, and alpha
421e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * components.
422e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * <p>
423e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * Use this format with {@link Image}. This format corresponds to
424e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * {@link android.graphics.ImageFormat#FLEX_RGBA_8888}, and can represent
425e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * {@link #COLOR_Format32bitBGRA8888}, {@link #COLOR_Format32bitABGR8888} and
426e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * {@link #COLOR_Format32bitARGB8888} formats.
427e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         *
428e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         * @see Image#getFormat
429e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar         */
430e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar        public static final int COLOR_FormatRGBAFlexible              = 0x7F36A888;
431e7f12bfdf69d2f9c5827e385390e12dfdeec3140Lajos Molnar
432b1fa78c132ae97efa8f03c18893c036b8278286cLajos Molnar        /** @deprecated Use {@link #COLOR_FormatYUV420Flexible}. */
433b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_QCOM_FormatYUV420SemiPlanar     = 0x7fa30c00;
43460d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber
43560d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        /**
43660d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber         * Defined in the OpenMAX IL specs, color format values are drawn from
43760d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber         * OMX_COLOR_FORMATTYPE.
43860d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber         */
439b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public int[] colorFormats; // NOTE this array is modifiable by user
44080c4437ebfe3e679267a64e4c9d7bdd585b7afceLajos Molnar
441b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        // FEATURES
442b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
443b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        private int mFlagsSupported;
444b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        private int mFlagsRequired;
445b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        private int mFlagsVerified;
44680c4437ebfe3e679267a64e4c9d7bdd585b7afceLajos Molnar
44780c4437ebfe3e679267a64e4c9d7bdd585b7afceLajos Molnar        /**
44880c4437ebfe3e679267a64e4c9d7bdd585b7afceLajos Molnar         * <b>video decoder only</b>: codec supports seamless resolution changes.
44980c4437ebfe3e679267a64e4c9d7bdd585b7afceLajos Molnar         */
450b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final String FEATURE_AdaptivePlayback       = "adaptive-playback";
451b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
452b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        /**
453b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         * <b>video decoder only</b>: codec supports secure decryption.
454b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         */
455b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final String FEATURE_SecurePlayback         = "secure-playback";
456b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
457b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        /**
458b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         * <b>video or audio decoder only</b>: codec supports tunneled playback.
459b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         */
460b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final String FEATURE_TunneledPlayback       = "tunneled-playback";
46180c4437ebfe3e679267a64e4c9d7bdd585b7afceLajos Molnar
46280c4437ebfe3e679267a64e4c9d7bdd585b7afceLajos Molnar        /**
463d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang         * <b>video decoder only</b>: codec supports queuing partial frames.
464d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang         */
465d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang        public static final String FEATURE_PartialFrame = "partial-frame";
466d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang
467d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang        /**
468e9618e810a61fee9b0126fe5dd9741743f6fb332Hangyu Kuang         * <b>video encoder only</b>: codec supports intra refresh.
469e9618e810a61fee9b0126fe5dd9741743f6fb332Hangyu Kuang         */
470e9618e810a61fee9b0126fe5dd9741743f6fb332Hangyu Kuang        public static final String FEATURE_IntraRefresh = "intra-refresh";
471e9618e810a61fee9b0126fe5dd9741743f6fb332Hangyu Kuang
472e9618e810a61fee9b0126fe5dd9741743f6fb332Hangyu Kuang        /**
47380c4437ebfe3e679267a64e4c9d7bdd585b7afceLajos Molnar         * Query codec feature capabilities.
474b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         * <p>
475b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         * These features are supported to be used by the codec.  These
476b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         * include optional features that can be turned on, as well as
477b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         * features that are always on.
47880c4437ebfe3e679267a64e4c9d7bdd585b7afceLajos Molnar         */
47980c4437ebfe3e679267a64e4c9d7bdd585b7afceLajos Molnar        public final boolean isFeatureSupported(String name) {
480b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            return checkFeature(name, mFlagsSupported);
481b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
482b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
483b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        /**
484b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         * Query codec feature requirements.
485b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         * <p>
486b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         * These features are required to be used by the codec, and as such,
487b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         * they are always turned on.
488b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         */
489b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public final boolean isFeatureRequired(String name) {
490b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            return checkFeature(name, mFlagsRequired);
491b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
492b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
493b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        private static final Feature[] decoderFeatures = {
494b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            new Feature(FEATURE_AdaptivePlayback, (1 << 0), true),
495b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            new Feature(FEATURE_SecurePlayback,   (1 << 1), false),
496b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            new Feature(FEATURE_TunneledPlayback, (1 << 2), false),
497d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang            new Feature(FEATURE_PartialFrame,     (1 << 3), false),
498b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        };
499b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
500e9618e810a61fee9b0126fe5dd9741743f6fb332Hangyu Kuang        private static final Feature[] encoderFeatures = {
501e9618e810a61fee9b0126fe5dd9741743f6fb332Hangyu Kuang            new Feature(FEATURE_IntraRefresh, (1 << 0), false),
502e9618e810a61fee9b0126fe5dd9741743f6fb332Hangyu Kuang        };
503e9618e810a61fee9b0126fe5dd9741743f6fb332Hangyu Kuang
504b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        /** @hide */
505b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public String[] validFeatures() {
506b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            Feature[] features = getValidFeatures();
507b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            String[] res = new String[features.length];
508b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            for (int i = 0; i < res.length; i++) {
509b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                res[i] = features[i].mName;
510b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
511b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            return res;
512b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
513b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
514b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        private Feature[] getValidFeatures() {
515b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            if (!isEncoder()) {
516b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                return decoderFeatures;
517b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
518e9618e810a61fee9b0126fe5dd9741743f6fb332Hangyu Kuang            return encoderFeatures;
519b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
520b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
521b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        private boolean checkFeature(String name, int flags) {
522b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            for (Feature feat: getValidFeatures()) {
523b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                if (feat.mName.equals(name)) {
524b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                    return (flags & feat.mValue) != 0;
525b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                }
52680c4437ebfe3e679267a64e4c9d7bdd585b7afceLajos Molnar            }
52780c4437ebfe3e679267a64e4c9d7bdd585b7afceLajos Molnar            return false;
52880c4437ebfe3e679267a64e4c9d7bdd585b7afceLajos Molnar        }
529b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
530b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        /** @hide */
531b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public boolean isRegular() {
532b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            // regular codecs only require default features
533b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            for (Feature feat: getValidFeatures()) {
534b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                if (!feat.mDefault && isFeatureRequired(feat.mName)) {
535b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                    return false;
536b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                }
537b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
538b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            return true;
539b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
540b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
541b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        /**
542b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         * Query whether codec supports a given {@link MediaFormat}.
543afa6ceb5a0d809b630db43564d3ce7f7b821129cLajos Molnar         *
544afa6ceb5a0d809b630db43564d3ce7f7b821129cLajos Molnar         * <p class=note>
545afa6ceb5a0d809b630db43564d3ce7f7b821129cLajos Molnar         * <strong>Note:</strong> On {@link android.os.Build.VERSION_CODES#LOLLIPOP},
546afa6ceb5a0d809b630db43564d3ce7f7b821129cLajos Molnar         * {@code format} must not contain a {@linkplain MediaFormat#KEY_FRAME_RATE
547afa6ceb5a0d809b630db43564d3ce7f7b821129cLajos Molnar         * frame rate}. Use
548afa6ceb5a0d809b630db43564d3ce7f7b821129cLajos Molnar         * <code class=prettyprint>format.setString(MediaFormat.KEY_FRAME_RATE, null)</code>
549afa6ceb5a0d809b630db43564d3ce7f7b821129cLajos Molnar         * to clear any existing frame rate setting in the format.
550db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         * <p>
551db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *
552db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         * The following table summarizes the format keys considered by this method.
553db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *
554db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         * <table style="width: 0%">
555db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *  <thead>
556db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *   <tr>
557db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *    <th rowspan=3>OS Version(s)</th>
558db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *    <td colspan=3>{@code MediaFormat} keys considered for</th>
559db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *   </tr><tr>
560db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *    <th>Audio Codecs</th>
561db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *    <th>Video Codecs</th>
562db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *    <th>Encoders</th>
563db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *   </tr>
564db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *  </thead>
565db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *  <tbody>
566db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *   <tr>
567db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *    <td>{@link android.os.Build.VERSION_CODES#LOLLIPOP}</th>
568db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *    <td rowspan=3>{@link MediaFormat#KEY_MIME}<sup>*</sup>,<br>
569db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *        {@link MediaFormat#KEY_SAMPLE_RATE},<br>
570db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *        {@link MediaFormat#KEY_CHANNEL_COUNT},</td>
571db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *    <td>{@link MediaFormat#KEY_MIME}<sup>*</sup>,<br>
572db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *        {@link CodecCapabilities#FEATURE_AdaptivePlayback}<sup>D</sup>,<br>
573db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *        {@link CodecCapabilities#FEATURE_SecurePlayback}<sup>D</sup>,<br>
574db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *        {@link CodecCapabilities#FEATURE_TunneledPlayback}<sup>D</sup>,<br>
575db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *        {@link MediaFormat#KEY_WIDTH},<br>
576db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *        {@link MediaFormat#KEY_HEIGHT},<br>
577db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *        <strong>no</strong> {@code KEY_FRAME_RATE}</td>
578db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *    <td rowspan=4>{@link MediaFormat#KEY_BITRATE_MODE},<br>
579db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *        {@link MediaFormat#KEY_PROFILE}
580db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *        (and/or {@link MediaFormat#KEY_AAC_PROFILE}<sup>~</sup>),<br>
581db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *        <!-- {link MediaFormat#KEY_QUALITY},<br> -->
582db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *        {@link MediaFormat#KEY_COMPLEXITY}
583db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *        (and/or {@link MediaFormat#KEY_FLAC_COMPRESSION_LEVEL}<sup>~</sup>)</td>
584db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *   </tr><tr>
585db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *    <td>{@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1}</th>
586db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *    <td rowspan=2>as above, plus<br>
587db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *        {@link MediaFormat#KEY_FRAME_RATE}</td>
588db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *   </tr><tr>
589db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *    <td>{@link android.os.Build.VERSION_CODES#M}</th>
590db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *   </tr><tr>
591db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *    <td>{@link android.os.Build.VERSION_CODES#N}</th>
592db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *    <td>as above, plus<br>
593db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *        {@link MediaFormat#KEY_PROFILE},<br>
594db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *        <!-- {link MediaFormat#KEY_MAX_BIT_RATE},<br> -->
595db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *        {@link MediaFormat#KEY_BIT_RATE}</td>
596db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *    <td>as above, plus<br>
597db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *        {@link MediaFormat#KEY_PROFILE},<br>
598db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *        {@link MediaFormat#KEY_LEVEL}<sup>+</sup>,<br>
599db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *        <!-- {link MediaFormat#KEY_MAX_BIT_RATE},<br> -->
600db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *        {@link MediaFormat#KEY_BIT_RATE},<br>
601db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *        {@link CodecCapabilities#FEATURE_IntraRefresh}<sup>E</sup></td>
602db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *   </tr>
603db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *   <tr>
604db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *    <td colspan=4>
605db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *     <p class=note><strong>Notes:</strong><br>
606db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *      *: must be specified; otherwise, method returns {@code false}.<br>
607db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *      +: method does not verify that the format parameters are supported
608db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *      by the specified level.<br>
609db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *      D: decoders only<br>
610db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *      E: encoders only<br>
611db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *      ~: if both keys are provided values must match
612db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *    </td>
613db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *   </tr>
614db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         *  </tbody>
615db56549ff24df1f5fc3ff7a816274a69e3fe4c3eLajos Molnar         * </table>
616afa6ceb5a0d809b630db43564d3ce7f7b821129cLajos Molnar         *
617b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         * @param format media format with optional feature directives.
618b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         * @throws IllegalArgumentException if format is not a valid media format.
619b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         * @return whether the codec capabilities support the given format
620b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         *         and feature requests.
621b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         */
622b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public final boolean isFormatSupported(MediaFormat format) {
623b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            final Map<String, Object> map = format.getMap();
624b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            final String mime = (String)map.get(MediaFormat.KEY_MIME);
625b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
626b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            // mime must match if present
627b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            if (mime != null && !mMime.equalsIgnoreCase(mime)) {
628b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                return false;
629b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
630b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
631b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            // check feature support
632b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            for (Feature feat: getValidFeatures()) {
633b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                Integer yesNo = (Integer)map.get(MediaFormat.KEY_FEATURE_ + feat.mName);
634dbf1552d526e62859e7a40cfea8e68b614a7d413Lajos Molnar                if (yesNo == null) {
635dbf1552d526e62859e7a40cfea8e68b614a7d413Lajos Molnar                    continue;
636dbf1552d526e62859e7a40cfea8e68b614a7d413Lajos Molnar                }
637b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                if ((yesNo == 1 && !isFeatureSupported(feat.mName)) ||
638b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                        (yesNo == 0 && isFeatureRequired(feat.mName))) {
639b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                    return false;
640b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                }
641b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
6420581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar
6430581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar            Integer profile = (Integer)map.get(MediaFormat.KEY_PROFILE);
6440581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar            Integer level = (Integer)map.get(MediaFormat.KEY_LEVEL);
6450581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar
6460581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar            if (profile != null) {
6470581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                if (!supportsProfileLevel(profile, level)) {
6480581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                    return false;
6490581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                }
6500581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar
6510581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                // If we recognize this profile, check that this format is supported by the
6520581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                // highest level supported by the codec for that profile. (Ignore specified
6530581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                // level beyond the above profile/level check as level is only used as a
6540581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                // guidance. E.g. AVC Level 1 CIF format is supported if codec supports level 1.1
6550581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                // even though max size for Level 1 is QCIF. However, MPEG2 Simple Profile
6560581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                // 1080p format is not supported even if codec supports Main Profile Level High,
6570581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                // as Simple Profile does not support 1080p.
6580581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                CodecCapabilities levelCaps = null;
6590581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                int maxLevel = 0;
6600581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                for (CodecProfileLevel pl : profileLevels) {
6610581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                    if (pl.profile == profile && pl.level > maxLevel) {
6620581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                        maxLevel = pl.level;
6630581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                    }
6640581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                }
6650581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                levelCaps = createFromProfileLevel(mMime, profile, maxLevel);
66687436bb67fb56e7efa8c475d56a0cc8f97cf79daLajos Molnar                // remove profile from this format otherwise levelCaps.isFormatSupported will
66787436bb67fb56e7efa8c475d56a0cc8f97cf79daLajos Molnar                // get into this same conditon and loop forever.
66887436bb67fb56e7efa8c475d56a0cc8f97cf79daLajos Molnar                Map<String, Object> mapWithoutProfile = new HashMap<>(map);
66987436bb67fb56e7efa8c475d56a0cc8f97cf79daLajos Molnar                mapWithoutProfile.remove(MediaFormat.KEY_PROFILE);
67087436bb67fb56e7efa8c475d56a0cc8f97cf79daLajos Molnar                MediaFormat formatWithoutProfile = new MediaFormat(mapWithoutProfile);
67187436bb67fb56e7efa8c475d56a0cc8f97cf79daLajos Molnar                if (levelCaps != null && !levelCaps.isFormatSupported(formatWithoutProfile)) {
6720581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                    return false;
6730581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                }
6740581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar            }
675b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            if (mAudioCaps != null && !mAudioCaps.supportsFormat(format)) {
676b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                return false;
677b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
678b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            if (mVideoCaps != null && !mVideoCaps.supportsFormat(format)) {
679b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                return false;
680b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
681b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            if (mEncoderCaps != null && !mEncoderCaps.supportsFormat(format)) {
682b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                return false;
683b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
684b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            return true;
685b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
686b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
6870581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar        private static boolean supportsBitrate(
6880581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                Range<Integer> bitrateRange, MediaFormat format) {
6890581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar            Map<String, Object> map = format.getMap();
6900581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar
6910581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar            // consider max bitrate over average bitrate for support
6920581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar            Integer maxBitrate = (Integer)map.get(MediaFormat.KEY_MAX_BIT_RATE);
6930581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar            Integer bitrate = (Integer)map.get(MediaFormat.KEY_BIT_RATE);
6940581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar            if (bitrate == null) {
6950581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                bitrate = maxBitrate;
6960581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar            } else if (maxBitrate != null) {
6970581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                bitrate = Math.max(bitrate, maxBitrate);
6980581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar            }
6990581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar
7000581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar            if (bitrate != null && bitrate > 0) {
7010581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                return bitrateRange.contains(bitrate);
7020581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar            }
7030581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar
7040581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar            return true;
7050581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar        }
7060581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar
7070581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar        private boolean supportsProfileLevel(int profile, Integer level) {
7080581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar            for (CodecProfileLevel pl: profileLevels) {
7090581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                if (pl.profile != profile) {
7100581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                    continue;
7110581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                }
7120581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar
7130581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                // AAC does not use levels
7140581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                if (level == null || mMime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AAC)) {
7150581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                    return true;
7160581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                }
7170581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar
7180581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                // H.263 levels are not completely ordered:
7190581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                // Level45 support only implies Level10 support
7200581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                if (mMime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_H263)) {
7210581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                    if (pl.level != level && pl.level == CodecProfileLevel.H263Level45
7220581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                            && level > CodecProfileLevel.H263Level10) {
7230581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                        continue;
7240581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                    }
7250581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                }
7262fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar
7272fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                // MPEG4 levels are not completely ordered:
7282fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                // Level1 support only implies Level0 (and not Level0b) support
7292fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                if (mMime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_MPEG4)) {
7302fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                    if (pl.level != level && pl.level == CodecProfileLevel.MPEG4Level1
7312fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                            && level > CodecProfileLevel.MPEG4Level0) {
7322fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                        continue;
7332fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                    }
7342fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                }
7352fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar
7362fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                // HEVC levels incorporate both tiers and levels. Verify tier support.
7372fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                if (mMime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_HEVC)) {
7382fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                    boolean supportsHighTier =
7392fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                        (pl.level & CodecProfileLevel.HEVCHighTierLevels) != 0;
7402fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                    boolean checkingHighTier = (level & CodecProfileLevel.HEVCHighTierLevels) != 0;
7412fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                    // high tier levels are only supported by other high tier levels
7422fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                    if (checkingHighTier && !supportsHighTier) {
7432fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                        continue;
7442fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                    }
7452fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                }
7462fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar
7470581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                if (pl.level >= level) {
7480581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                    // if we recognize the listed profile/level, we must also recognize the
7490581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                    // profile/level arguments.
7500581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                    if (createFromProfileLevel(mMime, profile, pl.level) != null) {
7510581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                        return createFromProfileLevel(mMime, profile, level) != null;
7520581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                    }
7530581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                    return true;
7540581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                }
7550581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar            }
7560581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar            return false;
7570581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar        }
7580581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar
759217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        // errors while reading profile levels - accessed from sister capabilities
760217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        int mError;
761b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
762b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        private static final String TAG = "CodecCapabilities";
763b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
764b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        // NEW-STYLE CAPABILITIES
765217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private AudioCapabilities mAudioCaps;
766217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private VideoCapabilities mVideoCaps;
767217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private EncoderCapabilities mEncoderCaps;
768217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private MediaFormat mDefaultFormat;
769b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
770b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        /**
771b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         * Returns a MediaFormat object with default values for configurations that have
772b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         * defaults.
773b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         */
774217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public MediaFormat getDefaultFormat() {
775b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            return mDefaultFormat;
776b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
777b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
778b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        /**
779b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         * Returns the mime type for which this codec-capability object was created.
780b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         */
781217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public String getMimeType() {
782b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            return mMime;
783b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
784b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
785ee2997577db8d9e3e52593b9ca454386f703d710Ronghua Wu        /**
786ee2997577db8d9e3e52593b9ca454386f703d710Ronghua Wu         * Returns the max number of the supported concurrent codec instances.
787ee2997577db8d9e3e52593b9ca454386f703d710Ronghua Wu         * <p>
788ee2997577db8d9e3e52593b9ca454386f703d710Ronghua Wu         * This is a hint for an upper bound. Applications should not expect to successfully
789ee2997577db8d9e3e52593b9ca454386f703d710Ronghua Wu         * operate more instances than the returned value, but the actual number of
790ee2997577db8d9e3e52593b9ca454386f703d710Ronghua Wu         * concurrently operable instances may be less as it depends on the available
791ee2997577db8d9e3e52593b9ca454386f703d710Ronghua Wu         * resources at time of use.
792ee2997577db8d9e3e52593b9ca454386f703d710Ronghua Wu         */
793ee2997577db8d9e3e52593b9ca454386f703d710Ronghua Wu        public int getMaxSupportedInstances() {
794ee2997577db8d9e3e52593b9ca454386f703d710Ronghua Wu            return mMaxSupportedInstances;
795ee2997577db8d9e3e52593b9ca454386f703d710Ronghua Wu        }
796ee2997577db8d9e3e52593b9ca454386f703d710Ronghua Wu
797217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private boolean isAudio() {
798217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return mAudioCaps != null;
799217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
800217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
801b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        /**
802217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Returns the audio capabilities or {@code null} if this is not an audio codec.
803b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         */
804217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public AudioCapabilities getAudioCapabilities() {
805217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return mAudioCaps;
806b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
807b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
808b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        private boolean isEncoder() {
809b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            return mEncoderCaps != null;
810b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
811b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
812b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        /**
813217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Returns the encoding capabilities or {@code null} if this is not an encoder.
814b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         */
815217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public EncoderCapabilities getEncoderCapabilities() {
816217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return mEncoderCaps;
817b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
818b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
819b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        private boolean isVideo() {
820b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            return mVideoCaps != null;
821b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
822b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
823b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        /**
824b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         * Returns the video capabilities or {@code null} if this is not a video codec.
825b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         */
826217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public VideoCapabilities getVideoCapabilities() {
827b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            return mVideoCaps;
828b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
829b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
830217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /** @hide */
831217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public CodecCapabilities dup() {
832217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return new CodecCapabilities(
833217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                // clone writable arrays
834217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                Arrays.copyOf(profileLevels, profileLevels.length),
835217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                Arrays.copyOf(colorFormats, colorFormats.length),
836217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                isEncoder(),
837217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                mFlagsVerified,
838217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                mDefaultFormat,
839217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                mCapabilitiesInfo);
840217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
841217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
842b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        /**
843b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         * Retrieve the codec capabilities for a certain {@code mime type}, {@code
844b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         * profile} and {@code level}.  If the type, or profile-level combination
845b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         * is not understood by the framework, it returns null.
8460d8337c3143867f51a52814830b0dd48535338b7Lajos Molnar         * <p class=note> In {@link android.os.Build.VERSION_CODES#M}, calling this
8470d8337c3143867f51a52814830b0dd48535338b7Lajos Molnar         * method without calling any method of the {@link MediaCodecList} class beforehand
8480d8337c3143867f51a52814830b0dd48535338b7Lajos Molnar         * results in a {@link NullPointerException}.</p>
849b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         */
850a18b69f5907ef27b9954dfcbe8f60d29fcec2be7Lajos Molnar        public static CodecCapabilities createFromProfileLevel(
851b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                String mime, int profile, int level) {
852b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            CodecProfileLevel pl = new CodecProfileLevel();
853b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            pl.profile = profile;
854b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            pl.level = level;
855b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            MediaFormat defaultFormat = new MediaFormat();
856b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            defaultFormat.setString(MediaFormat.KEY_MIME, mime);
857b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
858b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            CodecCapabilities ret = new CodecCapabilities(
859b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                new CodecProfileLevel[] { pl }, new int[0], true /* encoder */,
860b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                0 /* flags */, defaultFormat, new MediaFormat() /* info */);
861b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            if (ret.mError != 0) {
862b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                return null;
863b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
864b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            return ret;
865b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
866b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
867b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        /* package private */ CodecCapabilities(
868b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                CodecProfileLevel[] profLevs, int[] colFmts,
869b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                boolean encoder, int flags,
870b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                Map<String, Object>defaultFormatMap,
871b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                Map<String, Object>capabilitiesMap) {
872b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            this(profLevs, colFmts, encoder, flags,
873b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                    new MediaFormat(defaultFormatMap),
874b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                    new MediaFormat(capabilitiesMap));
875b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
876b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
877b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        private MediaFormat mCapabilitiesInfo;
878b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
879b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        /* package private */ CodecCapabilities(
880b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                CodecProfileLevel[] profLevs, int[] colFmts, boolean encoder, int flags,
881b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                MediaFormat defaultFormat, MediaFormat info) {
882b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            final Map<String, Object> map = info.getMap();
883b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            colorFormats = colFmts;
884b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            mFlagsVerified = flags;
885b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            mDefaultFormat = defaultFormat;
886b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            mCapabilitiesInfo = info;
887b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            mMime = mDefaultFormat.getString(MediaFormat.KEY_MIME);
888b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
8898acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar            /* VP9 introduced profiles around 2016, so some VP9 codecs may not advertise any
8908acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar               supported profiles. Determine the level for them using the info they provide. */
8918acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar            if (profLevs.length == 0 && mMime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP9)) {
8928acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                CodecProfileLevel profLev = new CodecProfileLevel();
8938acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                profLev.profile = CodecProfileLevel.VP9Profile0;
8948acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                profLev.level = VideoCapabilities.equivalentVP9Level(info);
8958acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                profLevs = new CodecProfileLevel[] { profLev };
8968acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar            }
8978acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar            profileLevels = profLevs;
8988acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar
899b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            if (mMime.toLowerCase().startsWith("audio/")) {
900b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                mAudioCaps = AudioCapabilities.create(info, this);
901981c344ee7a4472e2a331d66819c132267a681c6Lajos Molnar                mAudioCaps.setDefaultFormat(mDefaultFormat);
902b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            } else if (mMime.toLowerCase().startsWith("video/")) {
903b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                mVideoCaps = VideoCapabilities.create(info, this);
904b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
905b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            if (encoder) {
906b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                mEncoderCaps = EncoderCapabilities.create(info, this);
907981c344ee7a4472e2a331d66819c132267a681c6Lajos Molnar                mEncoderCaps.setDefaultFormat(mDefaultFormat);
908b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
909b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
910ee2997577db8d9e3e52593b9ca454386f703d710Ronghua Wu            final Map<String, Object> global = MediaCodecList.getGlobalSettings();
911ee2997577db8d9e3e52593b9ca454386f703d710Ronghua Wu            mMaxSupportedInstances = Utils.parseIntSafely(
91271b5a5866d8ba0eaf45972741b8f1dece36b5d03Ronghua Wu                    global.get("max-concurrent-instances"), DEFAULT_MAX_SUPPORTED_INSTANCES);
913ee2997577db8d9e3e52593b9ca454386f703d710Ronghua Wu
914ee2997577db8d9e3e52593b9ca454386f703d710Ronghua Wu            int maxInstances = Utils.parseIntSafely(
91571b5a5866d8ba0eaf45972741b8f1dece36b5d03Ronghua Wu                    map.get("max-concurrent-instances"), mMaxSupportedInstances);
916ee2997577db8d9e3e52593b9ca454386f703d710Ronghua Wu            mMaxSupportedInstances =
917ee2997577db8d9e3e52593b9ca454386f703d710Ronghua Wu                    Range.create(1, MAX_SUPPORTED_INSTANCES_LIMIT).clamp(maxInstances);
918ee2997577db8d9e3e52593b9ca454386f703d710Ronghua Wu
919b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            for (Feature feat: getValidFeatures()) {
920981c344ee7a4472e2a331d66819c132267a681c6Lajos Molnar                String key = MediaFormat.KEY_FEATURE_ + feat.mName;
921981c344ee7a4472e2a331d66819c132267a681c6Lajos Molnar                Integer yesNo = (Integer)map.get(key);
922b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                if (yesNo == null) {
923b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                    continue;
924dbf1552d526e62859e7a40cfea8e68b614a7d413Lajos Molnar                }
925dbf1552d526e62859e7a40cfea8e68b614a7d413Lajos Molnar                if (yesNo > 0) {
926b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                    mFlagsRequired |= feat.mValue;
927b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                }
928dbf1552d526e62859e7a40cfea8e68b614a7d413Lajos Molnar                mFlagsSupported |= feat.mValue;
929dbf1552d526e62859e7a40cfea8e68b614a7d413Lajos Molnar                mDefaultFormat.setInteger(key, 1);
930b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                // TODO restrict features by mFlagsVerified once all codecs reliably verify them
931b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
932b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
933217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    }
934b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
935217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    /**
936217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar     * A class that supports querying the audio capabilities of a codec.
937217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar     */
938217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    public static final class AudioCapabilities {
939217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private static final String TAG = "AudioCapabilities";
940217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private CodecCapabilities mParent;
941217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private Range<Integer> mBitrateRange;
942217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
943217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private int[] mSampleRates;
944217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private Range<Integer>[] mSampleRateRanges;
945217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private int mMaxInputChannelCount;
946217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
947217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private static final int MAX_INPUT_CHANNEL_COUNT = 30;
948217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
949217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /**
950217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Returns the range of supported bitrates in bits/second.
951217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         */
952217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public Range<Integer> getBitrateRange() {
953217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return mBitrateRange;
954217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
955217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
956217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /**
957217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Returns the array of supported sample rates if the codec
958217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * supports only discrete values.  Otherwise, it returns
959217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * {@code null}.  The array is sorted in ascending order.
960217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         */
961217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public int[] getSupportedSampleRates() {
962217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return Arrays.copyOf(mSampleRates, mSampleRates.length);
963217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
964217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
965217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /**
966217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Returns the array of supported sample rate ranges.  The
967217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * array is sorted in ascending order, and the ranges are
968217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * distinct.
969217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         */
970217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public Range<Integer>[] getSupportedSampleRateRanges() {
971217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return Arrays.copyOf(mSampleRateRanges, mSampleRateRanges.length);
972217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
973217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
974217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /**
975217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Returns the maximum number of input channels supported.  The codec
976217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * supports any number of channels between 1 and this maximum value.
977217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         */
978217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public int getMaxInputChannelCount() {
979217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return mMaxInputChannelCount;
980217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
981b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
982217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /* no public constructor */
983217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private AudioCapabilities() { }
984217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
985217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /** @hide */
986217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public static AudioCapabilities create(
987217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                MediaFormat info, CodecCapabilities parent) {
988217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            AudioCapabilities caps = new AudioCapabilities();
989217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            caps.init(info, parent);
990217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return caps;
991217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
992217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
993217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /** @hide */
994217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public void init(MediaFormat info, CodecCapabilities parent) {
995217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mParent = parent;
996217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            initWithPlatformLimits();
997217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            applyLevelLimits();
998217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            parseFromInfo(info);
999217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1000217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1001217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private void initWithPlatformLimits() {
1002217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mBitrateRange = Range.create(0, Integer.MAX_VALUE);
1003217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mMaxInputChannelCount = MAX_INPUT_CHANNEL_COUNT;
1004217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // mBitrateRange = Range.create(1, 320000);
1005217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mSampleRateRanges = new Range[] { Range.create(8000, 96000) };
1006217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mSampleRates = null;
1007217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1008217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1009217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private boolean supports(Integer sampleRate, Integer inputChannels) {
1010217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // channels and sample rates are checked orthogonally
1011217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (inputChannels != null &&
1012217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    (inputChannels < 1 || inputChannels > mMaxInputChannelCount)) {
1013217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                return false;
1014b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
1015217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (sampleRate != null) {
1016217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                int ix = Utils.binarySearchDistinctRanges(
1017217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        mSampleRateRanges, sampleRate);
1018217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (ix < 0) {
1019217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    return false;
1020217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
1021217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
1022217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return true;
1023217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1024b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
1025217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /**
1026217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Query whether the sample rate is supported by the codec.
1027217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         */
1028217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public boolean isSampleRateSupported(int sampleRate) {
1029217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return supports(sampleRate, null);
1030217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1031217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1032217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /** modifies rates */
1033217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private void limitSampleRates(int[] rates) {
1034217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            Arrays.sort(rates);
1035217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            ArrayList<Range<Integer>> ranges = new ArrayList<Range<Integer>>();
1036217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            for (int rate: rates) {
1037217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (supports(rate, null /* channels */)) {
1038217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    ranges.add(Range.create(rate, rate));
1039217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
1040b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
1041217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mSampleRateRanges = ranges.toArray(new Range[ranges.size()]);
1042217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            createDiscreteSampleRates();
1043217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1044b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
1045217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private void createDiscreteSampleRates() {
1046217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mSampleRates = new int[mSampleRateRanges.length];
1047217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            for (int i = 0; i < mSampleRateRanges.length; i++) {
1048217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                mSampleRates[i] = mSampleRateRanges[i].getLower();
1049217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
1050217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1051b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
1052217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /** modifies rateRanges */
1053217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private void limitSampleRates(Range<Integer>[] rateRanges) {
1054217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            sortDistinctRanges(rateRanges);
1055217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mSampleRateRanges = intersectSortedDistinctRanges(mSampleRateRanges, rateRanges);
1056217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1057217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // check if all values are discrete
1058217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            for (Range<Integer> range: mSampleRateRanges) {
1059217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (!range.getLower().equals(range.getUpper())) {
1060217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mSampleRates = null;
1061217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    return;
1062217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
1063b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
1064217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            createDiscreteSampleRates();
1065217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1066217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1067217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private void applyLevelLimits() {
1068217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            int[] sampleRates = null;
1069217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            Range<Integer> sampleRateRange = null, bitRates = null;
1070f31d11341e689ff5a630350cb48d30ff0ec21e70Robert Shih            int maxChannels = MAX_INPUT_CHANNEL_COUNT;
1071217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            String mime = mParent.getMimeType();
1072217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1073217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_MPEG)) {
1074217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                sampleRates = new int[] {
1075217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        8000, 11025, 12000,
1076217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        16000, 22050, 24000,
1077217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        32000, 44100, 48000 };
1078217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                bitRates = Range.create(8000, 320000);
1079217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxChannels = 2;
1080217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AMR_NB)) {
1081217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                sampleRates = new int[] { 8000 };
1082217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                bitRates = Range.create(4750, 12200);
1083217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxChannels = 1;
1084217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AMR_WB)) {
1085217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                sampleRates = new int[] { 16000 };
1086217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                bitRates = Range.create(6600, 23850);
1087217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxChannels = 1;
1088217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AAC)) {
1089217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                sampleRates = new int[] {
1090217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        7350, 8000,
1091217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        11025, 12000, 16000,
1092217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        22050, 24000, 32000,
1093217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        44100, 48000, 64000,
1094217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        88200, 96000 };
1095217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                bitRates = Range.create(8000, 510000);
1096217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxChannels = 48;
1097217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_VORBIS)) {
1098217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                bitRates = Range.create(32000, 500000);
1099610e288de6727d9be3277777e6c5abca4b18aa86Lajos Molnar                sampleRateRange = Range.create(8000, 192000);
1100217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxChannels = 255;
1101217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_OPUS)) {
1102217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                bitRates = Range.create(6000, 510000);
1103217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                sampleRates = new int[] { 8000, 12000, 16000, 24000, 48000 };
1104217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxChannels = 255;
1105217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_RAW)) {
1106217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                sampleRateRange = Range.create(1, 96000);
1107217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                bitRates = Range.create(1, 10000000);
1108bd2c3d65d6b62b5a359268246e7ebe96904bd851Glenn Kasten                maxChannels = AudioTrack.CHANNEL_COUNT_MAX;
1109217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_FLAC)) {
1110217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                sampleRateRange = Range.create(1, 655350);
1111217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                // lossless codec, so bitrate is ignored
1112217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxChannels = 255;
1113217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_G711_ALAW)
1114217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    || mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_G711_MLAW)) {
1115217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                sampleRates = new int[] { 8000 };
1116217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                bitRates = Range.create(64000, 64000);
1117217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                // platform allows multiple channels for this format
1118217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_MSGSM)) {
1119217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                sampleRates = new int[] { 8000 };
1120217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                bitRates = Range.create(13000, 13000);
1121217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxChannels = 1;
1122b95d7b5af42107d022d4f450d96563134895cf87ZhiWei Chen            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AC3)) {
1123b95d7b5af42107d022d4f450d96563134895cf87ZhiWei Chen                maxChannels = 6;
1124b95d7b5af42107d022d4f450d96563134895cf87ZhiWei Chen            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_EAC3)) {
1125b95d7b5af42107d022d4f450d96563134895cf87ZhiWei Chen                maxChannels = 16;
1126217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            } else {
1127217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                Log.w(TAG, "Unsupported mime " + mime);
1128217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                mParent.mError |= ERROR_UNSUPPORTED;
1129217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
1130217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1131217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // restrict ranges
1132217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (sampleRates != null) {
1133217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                limitSampleRates(sampleRates);
1134217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            } else if (sampleRateRange != null) {
1135217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                limitSampleRates(new Range[] { sampleRateRange });
1136217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
1137217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            applyLimits(maxChannels, bitRates);
1138217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1139b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
1140217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private void applyLimits(int maxInputChannels, Range<Integer> bitRates) {
1141217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mMaxInputChannelCount = Range.create(1, mMaxInputChannelCount)
1142217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    .clamp(maxInputChannels);
1143217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (bitRates != null) {
1144217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                mBitrateRange = mBitrateRange.intersect(bitRates);
1145b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
1146217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1147217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1148217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private void parseFromInfo(MediaFormat info) {
1149217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            int maxInputChannels = MAX_INPUT_CHANNEL_COUNT;
1150217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            Range<Integer> bitRates = POSITIVE_INTEGERS;
1151b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
1152217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (info.containsKey("sample-rate-ranges")) {
1153217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                String[] rateStrings = info.getString("sample-rate-ranges").split(",");
1154217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                Range<Integer>[] rateRanges = new Range[rateStrings.length];
1155217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                for (int i = 0; i < rateStrings.length; i++) {
1156217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    rateRanges[i] = Utils.parseIntRange(rateStrings[i], null);
1157217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
1158217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                limitSampleRates(rateRanges);
1159217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
1160217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (info.containsKey("max-channel-count")) {
1161217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxInputChannels = Utils.parseIntSafely(
1162217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        info.getString("max-channel-count"), maxInputChannels);
1163f31d11341e689ff5a630350cb48d30ff0ec21e70Robert Shih            } else if ((mParent.mError & ERROR_UNSUPPORTED) != 0) {
1164f31d11341e689ff5a630350cb48d30ff0ec21e70Robert Shih                maxInputChannels = 0;
1165217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
1166217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (info.containsKey("bitrate-range")) {
1167217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                bitRates = bitRates.intersect(
1168216e11dcbb4d56699c1740c801489be0d57b16c4Chong Zhang                        Utils.parseIntRange(info.getString("bitrate-range"), bitRates));
1169b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
1170217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            applyLimits(maxInputChannels, bitRates);
1171217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1172b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
1173217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /** @hide */
1174217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public void setDefaultFormat(MediaFormat format) {
1175217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // report settings that have only a single choice
1176217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (mBitrateRange.getLower().equals(mBitrateRange.getUpper())) {
1177217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                format.setInteger(MediaFormat.KEY_BIT_RATE, mBitrateRange.getLower());
1178217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
1179217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (mMaxInputChannelCount == 1) {
1180217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                // mono-only format
1181217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
1182217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
1183217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (mSampleRates != null && mSampleRates.length == 1) {
1184217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                format.setInteger(MediaFormat.KEY_SAMPLE_RATE, mSampleRates[0]);
1185217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
1186217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1187217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1188217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /** @hide */
1189217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public boolean supportsFormat(MediaFormat format) {
1190217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            Map<String, Object> map = format.getMap();
1191217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            Integer sampleRate = (Integer)map.get(MediaFormat.KEY_SAMPLE_RATE);
1192217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            Integer channels = (Integer)map.get(MediaFormat.KEY_CHANNEL_COUNT);
11930581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar
1194217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (!supports(sampleRate, channels)) {
1195217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                return false;
1196217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
1197217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
11980581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar            if (!CodecCapabilities.supportsBitrate(mBitrateRange, format)) {
11990581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                return false;
12000581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar            }
12010581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar
1202217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // nothing to do for:
1203217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // KEY_CHANNEL_MASK: codecs don't get this
1204217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // KEY_IS_ADTS:      required feature for all AAC decoders
1205217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return true;
1206217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1207217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    }
1208217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1209217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    /**
1210217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar     * A class that supports querying the video capabilities of a codec.
1211217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar     */
1212217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    public static final class VideoCapabilities {
1213217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private static final String TAG = "VideoCapabilities";
1214217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private CodecCapabilities mParent;
1215217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private Range<Integer> mBitrateRange;
1216217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1217217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private Range<Integer> mHeightRange;
1218217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private Range<Integer> mWidthRange;
1219217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private Range<Integer> mBlockCountRange;
1220217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private Range<Integer> mHorizontalBlockRange;
1221217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private Range<Integer> mVerticalBlockRange;
1222217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private Range<Rational> mAspectRatioRange;
1223217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private Range<Rational> mBlockAspectRatioRange;
1224217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private Range<Long> mBlocksPerSecondRange;
122575c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu        private Map<Size, Range<Long>> mMeasuredFrameRates;
1226217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private Range<Integer> mFrameRateRange;
1227217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1228217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private int mBlockWidth;
1229217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private int mBlockHeight;
1230217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private int mWidthAlignment;
1231217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private int mHeightAlignment;
1232217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private int mSmallerDimensionUpperLimit;
1233217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
12342fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar        private boolean mAllowMbOverride; // allow XML to override calculated limits
12352fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar
1236217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /**
1237217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Returns the range of supported bitrates in bits/second.
1238217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         */
1239217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public Range<Integer> getBitrateRange() {
1240217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return mBitrateRange;
1241217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1242217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1243217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /**
1244217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Returns the range of supported video widths.
1245217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         */
1246217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public Range<Integer> getSupportedWidths() {
1247217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return mWidthRange;
1248217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1249217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1250217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /**
1251217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Returns the range of supported video heights.
1252217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         */
1253217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public Range<Integer> getSupportedHeights() {
1254217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return mHeightRange;
1255217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1256217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1257217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /**
1258217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Returns the alignment requirement for video width (in pixels).
1259217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         *
1260217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * This is a power-of-2 value that video width must be a
1261217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * multiple of.
1262217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         */
1263217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public int getWidthAlignment() {
1264217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return mWidthAlignment;
1265217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1266217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1267217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /**
1268217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Returns the alignment requirement for video height (in pixels).
1269217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         *
1270217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * This is a power-of-2 value that video height must be a
1271217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * multiple of.
1272217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         */
1273217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public int getHeightAlignment() {
1274217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return mHeightAlignment;
1275217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1276217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1277217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /**
1278217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Return the upper limit on the smaller dimension of width or height.
1279217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * <p></p>
1280217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Some codecs have a limit on the smaller dimension, whether it be
1281217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * the width or the height.  E.g. a codec may only be able to handle
1282217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * up to 1920x1080 both in landscape and portrait mode (1080x1920).
1283217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * In this case the maximum width and height are both 1920, but the
1284217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * smaller dimension limit will be 1080. For other codecs, this is
1285217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * {@code Math.min(getSupportedWidths().getUpper(),
1286217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * getSupportedHeights().getUpper())}.
1287217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         *
1288217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * @hide
1289217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         */
1290217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public int getSmallerDimensionUpperLimit() {
1291217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return mSmallerDimensionUpperLimit;
1292217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1293217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1294217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /**
1295217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Returns the range of supported frame rates.
1296217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * <p>
1297217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * This is not a performance indicator.  Rather, it expresses the
1298217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * limits specified in the coding standard, based on the complexities
1299217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * of encoding material for later playback at a certain frame rate,
1300217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * or the decoding of such material in non-realtime.
1301217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         */
1302217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public Range<Integer> getSupportedFrameRates() {
1303217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return mFrameRateRange;
1304217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1305217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1306217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /**
1307217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Returns the range of supported video widths for a video height.
1308217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * @param height the height of the video
1309217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         */
1310217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public Range<Integer> getSupportedWidthsFor(int height) {
1311217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            try {
1312217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                Range<Integer> range = mWidthRange;
1313217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (!mHeightRange.contains(height)
1314217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        || (height % mHeightAlignment) != 0) {
1315217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    throw new IllegalArgumentException("unsupported height");
1316b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                }
1317217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                final int heightInBlocks = Utils.divUp(height, mBlockHeight);
1318217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1319217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                // constrain by block count and by block aspect ratio
1320217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                final int minWidthInBlocks = Math.max(
1321217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        Utils.divUp(mBlockCountRange.getLower(), heightInBlocks),
1322217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        (int)Math.ceil(mBlockAspectRatioRange.getLower().doubleValue()
1323217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                * heightInBlocks));
1324217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                final int maxWidthInBlocks = Math.min(
1325217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        mBlockCountRange.getUpper() / heightInBlocks,
1326217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        (int)(mBlockAspectRatioRange.getUpper().doubleValue()
1327217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                * heightInBlocks));
1328217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                range = range.intersect(
1329217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        (minWidthInBlocks - 1) * mBlockWidth + mWidthAlignment,
1330217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        maxWidthInBlocks * mBlockWidth);
1331217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1332217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                // constrain by smaller dimension limit
1333217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (height > mSmallerDimensionUpperLimit) {
1334217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    range = range.intersect(1, mSmallerDimensionUpperLimit);
1335b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                }
1336b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
1337217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                // constrain by aspect ratio
1338217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                range = range.intersect(
1339217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        (int)Math.ceil(mAspectRatioRange.getLower().doubleValue()
1340217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                * height),
1341217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        (int)(mAspectRatioRange.getUpper().doubleValue() * height));
1342217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                return range;
1343217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            } catch (IllegalArgumentException e) {
13446c9833b9674197eb3ef3d1617584787600f5e7dfLajos Molnar                // height is not supported because there are no suitable widths
13456c9833b9674197eb3ef3d1617584787600f5e7dfLajos Molnar                Log.v(TAG, "could not get supported widths for " + height);
1346217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                throw new IllegalArgumentException("unsupported height");
1347b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
1348217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1349b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
1350217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /**
1351217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Returns the range of supported video heights for a video width
1352217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * @param width the width of the video
1353217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         */
1354217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public Range<Integer> getSupportedHeightsFor(int width) {
1355217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            try {
1356217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                Range<Integer> range = mHeightRange;
1357217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (!mWidthRange.contains(width)
1358217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        || (width % mWidthAlignment) != 0) {
1359217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    throw new IllegalArgumentException("unsupported width");
1360b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                }
1361217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                final int widthInBlocks = Utils.divUp(width, mBlockWidth);
1362217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1363217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                // constrain by block count and by block aspect ratio
1364217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                final int minHeightInBlocks = Math.max(
1365217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        Utils.divUp(mBlockCountRange.getLower(), widthInBlocks),
1366217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        (int)Math.ceil(widthInBlocks /
1367217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                mBlockAspectRatioRange.getUpper().doubleValue()));
1368217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                final int maxHeightInBlocks = Math.min(
1369217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        mBlockCountRange.getUpper() / widthInBlocks,
1370217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        (int)(widthInBlocks /
1371217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                mBlockAspectRatioRange.getLower().doubleValue()));
1372217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                range = range.intersect(
1373217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        (minHeightInBlocks - 1) * mBlockHeight + mHeightAlignment,
1374217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        maxHeightInBlocks * mBlockHeight);
1375217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1376217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                // constrain by smaller dimension limit
1377217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (width > mSmallerDimensionUpperLimit) {
1378217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    range = range.intersect(1, mSmallerDimensionUpperLimit);
1379217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
1380217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1381217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                // constrain by aspect ratio
1382217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                range = range.intersect(
1383217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        (int)Math.ceil(width /
1384217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                mAspectRatioRange.getUpper().doubleValue()),
1385217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        (int)(width / mAspectRatioRange.getLower().doubleValue()));
1386217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                return range;
1387217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            } catch (IllegalArgumentException e) {
13886c9833b9674197eb3ef3d1617584787600f5e7dfLajos Molnar                // width is not supported because there are no suitable heights
13896c9833b9674197eb3ef3d1617584787600f5e7dfLajos Molnar                Log.v(TAG, "could not get supported heights for " + width);
1390217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                throw new IllegalArgumentException("unsupported width");
1391217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
1392217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1393217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1394217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /**
1395217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Returns the range of supported video frame rates for a video size.
1396217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * <p>
1397217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * This is not a performance indicator.  Rather, it expresses the limits specified in
1398217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * the coding standard, based on the complexities of encoding material of a given
1399217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * size for later playback at a certain frame rate, or the decoding of such material
1400217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * in non-realtime.
1401217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1402217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * @param width the width of the video
1403217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * @param height the height of the video
1404217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         */
1405217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public Range<Double> getSupportedFrameRatesFor(int width, int height) {
1406217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            Range<Integer> range = mHeightRange;
1407217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (!supports(width, height, null)) {
1408217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                throw new IllegalArgumentException("unsupported size");
1409217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
1410217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            final int blockCount =
1411217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                Utils.divUp(width, mBlockWidth) * Utils.divUp(height, mBlockHeight);
1412217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1413217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return Range.create(
1414217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    Math.max(mBlocksPerSecondRange.getLower() / (double) blockCount,
1415217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            (double) mFrameRateRange.getLower()),
1416217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    Math.min(mBlocksPerSecondRange.getUpper() / (double) blockCount,
1417217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            (double) mFrameRateRange.getUpper()));
1418217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1419217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1420e595268e98ee609899c71c4114fc098daa2ee1f4Ronghua Wu        private int getBlockCount(int width, int height) {
1421e595268e98ee609899c71c4114fc098daa2ee1f4Ronghua Wu            return Utils.divUp(width, mBlockWidth) * Utils.divUp(height, mBlockHeight);
1422e595268e98ee609899c71c4114fc098daa2ee1f4Ronghua Wu        }
1423e595268e98ee609899c71c4114fc098daa2ee1f4Ronghua Wu
142475c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu        @NonNull
142575c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu        private Size findClosestSize(int width, int height) {
1426e595268e98ee609899c71c4114fc098daa2ee1f4Ronghua Wu            int targetBlockCount = getBlockCount(width, height);
142775c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu            Size closestSize = null;
1428e595268e98ee609899c71c4114fc098daa2ee1f4Ronghua Wu            int minDiff = Integer.MAX_VALUE;
142975c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu            for (Size size : mMeasuredFrameRates.keySet()) {
1430e595268e98ee609899c71c4114fc098daa2ee1f4Ronghua Wu                int diff = Math.abs(targetBlockCount -
1431e595268e98ee609899c71c4114fc098daa2ee1f4Ronghua Wu                        getBlockCount(size.getWidth(), size.getHeight()));
1432e595268e98ee609899c71c4114fc098daa2ee1f4Ronghua Wu                if (diff < minDiff) {
1433e595268e98ee609899c71c4114fc098daa2ee1f4Ronghua Wu                    minDiff = diff;
143475c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu                    closestSize = size;
143575c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu                }
143675c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu            }
143775c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu            return closestSize;
143875c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu        }
143975c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu
144075c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu        private Range<Double> estimateFrameRatesFor(int width, int height) {
144175c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu            Size size = findClosestSize(width, height);
144275c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu            Range<Long> range = mMeasuredFrameRates.get(size);
14437a2ab16b65f7ae252a7b127a7286f6ecde87bdf0Lajos Molnar            Double ratio = getBlockCount(size.getWidth(), size.getHeight())
14447a2ab16b65f7ae252a7b127a7286f6ecde87bdf0Lajos Molnar                    / (double)Math.max(getBlockCount(width, height), 1);
144575c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu            return Range.create(range.getLower() * ratio, range.getUpper() * ratio);
144675c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu        }
144775c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu
1448217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /**
144938a296a65f89b0b16a717fe29f583db21e5c46dfLajos Molnar         * Returns the range of achievable video frame rates for a video size.
145038a296a65f89b0b16a717fe29f583db21e5c46dfLajos Molnar         * May return {@code null}, if the codec did not publish any measurement
145138a296a65f89b0b16a717fe29f583db21e5c46dfLajos Molnar         * data.
145238a296a65f89b0b16a717fe29f583db21e5c46dfLajos Molnar         * <p>
1453b28b99a4257f2ef6d747cc8dc4d60a23cc69e0ebLajos Molnar         * This is a performance estimate provided by the device manufacturer based on statistical
1454b28b99a4257f2ef6d747cc8dc4d60a23cc69e0ebLajos Molnar         * sampling of full-speed decoding and encoding measurements in various configurations
1455afa6ceb5a0d809b630db43564d3ce7f7b821129cLajos Molnar         * of common video sizes supported by the codec. As such it should only be used to
1456afa6ceb5a0d809b630db43564d3ce7f7b821129cLajos Molnar         * compare individual codecs on the device. The value is not suitable for comparing
1457afa6ceb5a0d809b630db43564d3ce7f7b821129cLajos Molnar         * different devices or even different android releases for the same device.
1458afa6ceb5a0d809b630db43564d3ce7f7b821129cLajos Molnar         * <p>
1459b28b99a4257f2ef6d747cc8dc4d60a23cc69e0ebLajos Molnar         * <em>On {@link android.os.Build.VERSION_CODES#M} release</em> the returned range
1460b28b99a4257f2ef6d747cc8dc4d60a23cc69e0ebLajos Molnar         * corresponds to the fastest frame rates achieved in the tested configurations. As
1461b28b99a4257f2ef6d747cc8dc4d60a23cc69e0ebLajos Molnar         * such, it should not be used to gauge guaranteed or even average codec performance
1462b28b99a4257f2ef6d747cc8dc4d60a23cc69e0ebLajos Molnar         * on the device.
1463b28b99a4257f2ef6d747cc8dc4d60a23cc69e0ebLajos Molnar         * <p>
1464b28b99a4257f2ef6d747cc8dc4d60a23cc69e0ebLajos Molnar         * <em>On {@link android.os.Build.VERSION_CODES#N} release</em> the returned range
1465b28b99a4257f2ef6d747cc8dc4d60a23cc69e0ebLajos Molnar         * corresponds closer to sustained performance <em>in tested configurations</em>.
1466b28b99a4257f2ef6d747cc8dc4d60a23cc69e0ebLajos Molnar         * One can expect to achieve sustained performance higher than the lower limit more than
1467b28b99a4257f2ef6d747cc8dc4d60a23cc69e0ebLajos Molnar         * 50% of the time, and higher than half of the lower limit at least 90% of the time
1468b28b99a4257f2ef6d747cc8dc4d60a23cc69e0ebLajos Molnar         * <em>in tested configurations</em>.
1469b28b99a4257f2ef6d747cc8dc4d60a23cc69e0ebLajos Molnar         * Conversely, one can expect performance lower than twice the upper limit at least
1470b28b99a4257f2ef6d747cc8dc4d60a23cc69e0ebLajos Molnar         * 90% of the time.
1471b28b99a4257f2ef6d747cc8dc4d60a23cc69e0ebLajos Molnar         * <p class=note>
1472b28b99a4257f2ef6d747cc8dc4d60a23cc69e0ebLajos Molnar         * Tested configurations use a single active codec. For use cases where multiple
1473b28b99a4257f2ef6d747cc8dc4d60a23cc69e0ebLajos Molnar         * codecs are active, applications can expect lower and in most cases significantly lower
1474b28b99a4257f2ef6d747cc8dc4d60a23cc69e0ebLajos Molnar         * performance.
1475b28b99a4257f2ef6d747cc8dc4d60a23cc69e0ebLajos Molnar         * <p class=note>
1476b28b99a4257f2ef6d747cc8dc4d60a23cc69e0ebLajos Molnar         * The returned range value is interpolated from the nearest frame size(s) tested.
1477b28b99a4257f2ef6d747cc8dc4d60a23cc69e0ebLajos Molnar         * Codec performance is severely impacted by other activity on the device as well
1478b28b99a4257f2ef6d747cc8dc4d60a23cc69e0ebLajos Molnar         * as environmental factors (such as battery level, temperature or power source), and can
1479b28b99a4257f2ef6d747cc8dc4d60a23cc69e0ebLajos Molnar         * vary significantly even in a steady environment.
1480afa6ceb5a0d809b630db43564d3ce7f7b821129cLajos Molnar         * <p class=note>
1481afa6ceb5a0d809b630db43564d3ce7f7b821129cLajos Molnar         * Use this method in cases where only codec performance matters, e.g. to evaluate if
1482afa6ceb5a0d809b630db43564d3ce7f7b821129cLajos Molnar         * a codec has any chance of meeting a performance target. Codecs are listed
1483afa6ceb5a0d809b630db43564d3ce7f7b821129cLajos Molnar         * in {@link MediaCodecList} in the preferred order as defined by the device
1484afa6ceb5a0d809b630db43564d3ce7f7b821129cLajos Molnar         * manufacturer. As such, applications should use the first suitable codec in the
1485afa6ceb5a0d809b630db43564d3ce7f7b821129cLajos Molnar         * list to achieve the best balance between power use and performance.
148638a296a65f89b0b16a717fe29f583db21e5c46dfLajos Molnar         *
148738a296a65f89b0b16a717fe29f583db21e5c46dfLajos Molnar         * @param width the width of the video
148838a296a65f89b0b16a717fe29f583db21e5c46dfLajos Molnar         * @param height the height of the video
148938a296a65f89b0b16a717fe29f583db21e5c46dfLajos Molnar         *
149038a296a65f89b0b16a717fe29f583db21e5c46dfLajos Molnar         * @throws IllegalArgumentException if the video size is not supported.
149138a296a65f89b0b16a717fe29f583db21e5c46dfLajos Molnar         */
149275c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu        @Nullable
149338a296a65f89b0b16a717fe29f583db21e5c46dfLajos Molnar        public Range<Double> getAchievableFrameRatesFor(int width, int height) {
149438a296a65f89b0b16a717fe29f583db21e5c46dfLajos Molnar            if (!supports(width, height, null)) {
149538a296a65f89b0b16a717fe29f583db21e5c46dfLajos Molnar                throw new IllegalArgumentException("unsupported size");
149638a296a65f89b0b16a717fe29f583db21e5c46dfLajos Molnar            }
149775c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu
149875c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu            if (mMeasuredFrameRates == null || mMeasuredFrameRates.size() <= 0) {
149975c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu                Log.w(TAG, "Codec did not publish any measurement data.");
150075c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu                return null;
150175c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu            }
150275c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu
150375c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu            return estimateFrameRatesFor(width, height);
150438a296a65f89b0b16a717fe29f583db21e5c46dfLajos Molnar        }
150538a296a65f89b0b16a717fe29f583db21e5c46dfLajos Molnar
150638a296a65f89b0b16a717fe29f583db21e5c46dfLajos Molnar        /**
1507217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Returns whether a given video size ({@code width} and
1508217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * {@code height}) and {@code frameRate} combination is supported.
1509217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         */
1510217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public boolean areSizeAndRateSupported(
1511217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                int width, int height, double frameRate) {
1512217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return supports(width, height, frameRate);
1513217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1514217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1515217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /**
1516217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Returns whether a given video size ({@code width} and
1517217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * {@code height}) is supported.
1518217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         */
1519217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public boolean isSizeSupported(int width, int height) {
1520217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return supports(width, height, null);
1521217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1522217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
15230581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar        private boolean supports(Integer width, Integer height, Number rate) {
1524217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            boolean ok = true;
1525217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1526217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (ok && width != null) {
1527217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                ok = mWidthRange.contains(width)
1528217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        && (width % mWidthAlignment == 0);
1529217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
1530217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (ok && height != null) {
1531217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                ok = mHeightRange.contains(height)
1532217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        && (height % mHeightAlignment == 0);
1533b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
1534217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (ok && rate != null) {
1535a4fcb62a224eca99d53b1692d1cc5ae5ff2d2127Lajos Molnar                ok = mFrameRateRange.contains(Utils.intRangeFor(rate.doubleValue()));
1536217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
1537217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (ok && height != null && width != null) {
1538217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                ok = Math.min(height, width) <= mSmallerDimensionUpperLimit;
1539b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
1540217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                final int widthInBlocks = Utils.divUp(width, mBlockWidth);
1541217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                final int heightInBlocks = Utils.divUp(height, mBlockHeight);
1542217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                final int blockCount = widthInBlocks * heightInBlocks;
1543217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                ok = ok && mBlockCountRange.contains(blockCount)
1544217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        && mBlockAspectRatioRange.contains(
1545217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                new Rational(widthInBlocks, heightInBlocks))
1546217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        && mAspectRatioRange.contains(new Rational(width, height));
1547217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (ok && rate != null) {
1548a4fcb62a224eca99d53b1692d1cc5ae5ff2d2127Lajos Molnar                    double blocksPerSec = blockCount * rate.doubleValue();
1549217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    ok = mBlocksPerSecondRange.contains(
1550217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            Utils.longRangeFor(blocksPerSec));
1551b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                }
1552b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
1553217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return ok;
1554217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1555b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
1556217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /**
1557217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * @hide
1558217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * @throws java.lang.ClassCastException */
1559217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public boolean supportsFormat(MediaFormat format) {
1560217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            final Map<String, Object> map = format.getMap();
1561217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            Integer width = (Integer)map.get(MediaFormat.KEY_WIDTH);
1562217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            Integer height = (Integer)map.get(MediaFormat.KEY_HEIGHT);
1563a4fcb62a224eca99d53b1692d1cc5ae5ff2d2127Lajos Molnar            Number rate = (Number)map.get(MediaFormat.KEY_FRAME_RATE);
1564217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
15650581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar            if (!supports(width, height, rate)) {
15660581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                return false;
15670581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar            }
1568217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
15690581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar            if (!CodecCapabilities.supportsBitrate(mBitrateRange, format)) {
15700581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar                return false;
15710581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar            }
15720581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar
15730581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar            // we ignore color-format for now as it is not reliably reported by codec
15740581ee49719fba54fc37071ffa357f4518cf1583Lajos Molnar            return true;
1575217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1576217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1577217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /* no public constructor */
1578217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private VideoCapabilities() { }
1579217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1580217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /** @hide */
1581217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public static VideoCapabilities create(
1582217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                MediaFormat info, CodecCapabilities parent) {
1583217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            VideoCapabilities caps = new VideoCapabilities();
1584217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            caps.init(info, parent);
1585217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return caps;
1586217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1587217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1588217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /** @hide */
1589217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public void init(MediaFormat info, CodecCapabilities parent) {
1590217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mParent = parent;
1591217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            initWithPlatformLimits();
1592217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            applyLevelLimits();
1593217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            parseFromInfo(info);
1594217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            updateLimits();
1595217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1596217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1597217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /** @hide */
1598217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public Size getBlockSize() {
1599217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return new Size(mBlockWidth, mBlockHeight);
1600217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1601217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1602217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /** @hide */
1603217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public Range<Integer> getBlockCountRange() {
1604217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return mBlockCountRange;
1605217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1606217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1607217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /** @hide */
1608217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public Range<Long> getBlocksPerSecondRange() {
1609217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return mBlocksPerSecondRange;
1610217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1611b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
1612217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /** @hide */
1613217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public Range<Rational> getAspectRatioRange(boolean blocks) {
1614217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return blocks ? mBlockAspectRatioRange : mAspectRatioRange;
1615217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1616217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1617217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private void initWithPlatformLimits() {
1618216e11dcbb4d56699c1740c801489be0d57b16c4Chong Zhang            mBitrateRange = BITRATE_RANGE;
1619217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1620217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mWidthRange  = SIZE_RANGE;
1621217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mHeightRange = SIZE_RANGE;
1622217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mFrameRateRange = FRAME_RATE_RANGE;
1623217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1624217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mHorizontalBlockRange = SIZE_RANGE;
1625217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mVerticalBlockRange   = SIZE_RANGE;
1626217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1627217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // full positive ranges are supported as these get calculated
1628217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mBlockCountRange      = POSITIVE_INTEGERS;
1629217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mBlocksPerSecondRange = POSITIVE_LONGS;
1630217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1631217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mBlockAspectRatioRange = POSITIVE_RATIONALS;
1632217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mAspectRatioRange      = POSITIVE_RATIONALS;
1633217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1634217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // YUV 4:2:0 requires 2:2 alignment
1635217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mWidthAlignment = 2;
1636217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mHeightAlignment = 2;
1637217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mBlockWidth = 2;
1638217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mBlockHeight = 2;
1639217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mSmallerDimensionUpperLimit = SIZE_RANGE.getUpper();
1640217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1641217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
164275c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu        private Map<Size, Range<Long>> getMeasuredFrameRates(Map<String, Object> map) {
164375c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu            Map<Size, Range<Long>> ret = new HashMap<Size, Range<Long>>();
164475c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu            final String prefix = "measured-frame-rate-";
164575c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu            Set<String> keys = map.keySet();
164675c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu            for (String key : keys) {
164775c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu                // looking for: measured-frame-rate-WIDTHxHEIGHT-range
164875c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu                if (!key.startsWith(prefix)) {
164975c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu                    continue;
165075c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu                }
165175c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu                String subKey = key.substring(prefix.length());
165275c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu                String[] temp = key.split("-");
165375c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu                if (temp.length != 5) {
165475c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu                    continue;
165575c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu                }
165675c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu                String sizeStr = temp[3];
165775c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu                Size size = Utils.parseSize(sizeStr, null);
165875c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu                if (size == null || size.getWidth() * size.getHeight() <= 0) {
165975c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu                    continue;
166075c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu                }
166175c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu                Range<Long> range = Utils.parseLongRange(map.get(key), null);
166275c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu                if (range == null || range.getLower() < 0 || range.getUpper() < 0) {
166375c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu                    continue;
166475c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu                }
166575c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu                ret.put(size, range);
166675c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu            }
166775c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu            return ret;
166875c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu        }
166975c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu
16708acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar        private static Pair<Range<Integer>, Range<Integer>> parseWidthHeightRanges(Object o) {
16718acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar            Pair<Size, Size> range = Utils.parseSizeRange(o);
16728acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar            if (range != null) {
16738acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                try {
16748acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                    return Pair.create(
16758acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                            Range.create(range.first.getWidth(), range.second.getWidth()),
16768acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                            Range.create(range.first.getHeight(), range.second.getHeight()));
16778acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                } catch (IllegalArgumentException e) {
16788acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                    Log.w(TAG, "could not parse size range '" + o + "'");
16798acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                }
16808acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar            }
16818acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar            return null;
16828acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar        }
16838acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar
16848acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar        /** @hide */
16858acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar        public static int equivalentVP9Level(MediaFormat info) {
16868acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar            final Map<String, Object> map = info.getMap();
16878acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar
16888acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar            Size blockSize = Utils.parseSize(map.get("block-size"), new Size(8, 8));
16898acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar            int BS = blockSize.getWidth() * blockSize.getHeight();
16908acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar
16918acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar            Range<Integer> counts = Utils.parseIntRange(map.get("block-count-range"), null);
16928acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar            int FS = counts == null ? 0 : BS * counts.getUpper();
16938acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar
16948acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar            Range<Long> blockRates =
16958acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                Utils.parseLongRange(map.get("blocks-per-second-range"), null);
16968acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar            long SR = blockRates == null ? 0 : BS * blockRates.getUpper();
16978acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar
16988acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar            Pair<Range<Integer>, Range<Integer>> dimensionRanges =
16998acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                parseWidthHeightRanges(map.get("size-range"));
17008acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar            int D = dimensionRanges == null ? 0 : Math.max(
17018acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                    dimensionRanges.first.getUpper(), dimensionRanges.second.getUpper());
17028acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar
17038acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar            Range<Integer> bitRates = Utils.parseIntRange(map.get("bitrate-range"), null);
17048acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar            int BR = bitRates == null ? 0 : Utils.divUp(bitRates.getUpper(), 1000);
17058acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar
17068acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar            if (SR <=      829440 && FS <=    36864 && BR <=    200 && D <=   512)
17078acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                return CodecProfileLevel.VP9Level1;
17088acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar            if (SR <=     2764800 && FS <=    73728 && BR <=    800 && D <=   768)
17098acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                return CodecProfileLevel.VP9Level11;
17108acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar            if (SR <=     4608000 && FS <=   122880 && BR <=   1800 && D <=   960)
17118acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                return CodecProfileLevel.VP9Level2;
17128acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar            if (SR <=     9216000 && FS <=   245760 && BR <=   3600 && D <=  1344)
17138acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                return CodecProfileLevel.VP9Level21;
17148acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar            if (SR <=    20736000 && FS <=   552960 && BR <=   7200 && D <=  2048)
17158acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                return CodecProfileLevel.VP9Level3;
17168acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar            if (SR <=    36864000 && FS <=   983040 && BR <=  12000 && D <=  2752)
17178acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                return CodecProfileLevel.VP9Level31;
17188acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar            if (SR <=    83558400 && FS <=  2228224 && BR <=  18000 && D <=  4160)
17198acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                return CodecProfileLevel.VP9Level4;
17208acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar            if (SR <=   160432128 && FS <=  2228224 && BR <=  30000 && D <=  4160)
17218acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                return CodecProfileLevel.VP9Level41;
17228acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar            if (SR <=   311951360 && FS <=  8912896 && BR <=  60000 && D <=  8384)
17238acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                return CodecProfileLevel.VP9Level5;
17248acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar            if (SR <=   588251136 && FS <=  8912896 && BR <= 120000 && D <=  8384)
17258acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                return CodecProfileLevel.VP9Level51;
17268acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar            if (SR <=  1176502272 && FS <=  8912896 && BR <= 180000 && D <=  8384)
17278acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                return CodecProfileLevel.VP9Level52;
17288acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar            if (SR <=  1176502272 && FS <= 35651584 && BR <= 180000 && D <= 16832)
17298acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                return CodecProfileLevel.VP9Level6;
17308acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar            if (SR <= 2353004544L && FS <= 35651584 && BR <= 240000 && D <= 16832)
17318acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                return CodecProfileLevel.VP9Level61;
17328acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar            if (SR <= 4706009088L && FS <= 35651584 && BR <= 480000 && D <= 16832)
17338acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                return CodecProfileLevel.VP9Level62;
17348acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar            // returning largest level
17358acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar            return CodecProfileLevel.VP9Level62;
17368acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar        }
17378acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar
1738217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private void parseFromInfo(MediaFormat info) {
1739217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            final Map<String, Object> map = info.getMap();
1740217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            Size blockSize = new Size(mBlockWidth, mBlockHeight);
1741217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            Size alignment = new Size(mWidthAlignment, mHeightAlignment);
1742217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            Range<Integer> counts = null, widths = null, heights = null;
1743216e11dcbb4d56699c1740c801489be0d57b16c4Chong Zhang            Range<Integer> frameRates = null, bitRates = null;
1744217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            Range<Long> blockRates = null;
1745217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            Range<Rational> ratios = null, blockRatios = null;
1746217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1747217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            blockSize = Utils.parseSize(map.get("block-size"), blockSize);
1748217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            alignment = Utils.parseSize(map.get("alignment"), alignment);
1749217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            counts = Utils.parseIntRange(map.get("block-count-range"), null);
1750217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            blockRates =
1751217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                Utils.parseLongRange(map.get("blocks-per-second-range"), null);
175275c4824bf6efd996956edb4436f2d85bad4ac473Ronghua Wu            mMeasuredFrameRates = getMeasuredFrameRates(map);
17538acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar            Pair<Range<Integer>, Range<Integer>> sizeRanges =
17548acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                parseWidthHeightRanges(map.get("size-range"));
17558acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar            if (sizeRanges != null) {
17568acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                widths = sizeRanges.first;
17578acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                heights = sizeRanges.second;
1758b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
1759217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // for now this just means using the smaller max size as 2nd
1760217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // upper limit.
1761217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // for now we are keeping the profile specific "width/height
1762217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // in macroblocks" limits.
17631c436bd911373810b2ac14088dd16762daf94191Lajos Molnar            if (map.containsKey("feature-can-swap-width-height")) {
1764217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (widths != null) {
1765217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mSmallerDimensionUpperLimit =
1766217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        Math.min(widths.getUpper(), heights.getUpper());
1767217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    widths = heights = widths.extend(heights);
1768981c344ee7a4472e2a331d66819c132267a681c6Lajos Molnar                } else {
1769217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    Log.w(TAG, "feature can-swap-width-height is best used with size-range");
1770217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mSmallerDimensionUpperLimit =
1771217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        Math.min(mWidthRange.getUpper(), mHeightRange.getUpper());
1772217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mWidthRange = mHeightRange = mWidthRange.extend(mHeightRange);
1773b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                }
1774b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
1775b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
1776217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            ratios = Utils.parseRationalRange(
1777217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    map.get("block-aspect-ratio-range"), null);
1778217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            blockRatios = Utils.parseRationalRange(
1779217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    map.get("pixel-aspect-ratio-range"), null);
1780217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            frameRates = Utils.parseIntRange(map.get("frame-rate-range"), null);
1781217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (frameRates != null) {
1782217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                try {
1783217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    frameRates = frameRates.intersect(FRAME_RATE_RANGE);
1784217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                } catch (IllegalArgumentException e) {
1785217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    Log.w(TAG, "frame rate range (" + frameRates
1786217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            + ") is out of limits: " + FRAME_RATE_RANGE);
1787217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    frameRates = null;
1788b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                }
1789b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
1790216e11dcbb4d56699c1740c801489be0d57b16c4Chong Zhang            bitRates = Utils.parseIntRange(map.get("bitrate-range"), null);
1791216e11dcbb4d56699c1740c801489be0d57b16c4Chong Zhang            if (bitRates != null) {
1792216e11dcbb4d56699c1740c801489be0d57b16c4Chong Zhang                try {
1793216e11dcbb4d56699c1740c801489be0d57b16c4Chong Zhang                    bitRates = bitRates.intersect(BITRATE_RANGE);
1794216e11dcbb4d56699c1740c801489be0d57b16c4Chong Zhang                } catch (IllegalArgumentException e) {
1795216e11dcbb4d56699c1740c801489be0d57b16c4Chong Zhang                    Log.w(TAG,  "bitrate range (" + bitRates
1796216e11dcbb4d56699c1740c801489be0d57b16c4Chong Zhang                            + ") is out of limits: " + BITRATE_RANGE);
1797216e11dcbb4d56699c1740c801489be0d57b16c4Chong Zhang                    bitRates = null;
1798216e11dcbb4d56699c1740c801489be0d57b16c4Chong Zhang                }
1799216e11dcbb4d56699c1740c801489be0d57b16c4Chong Zhang            }
1800b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
1801217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            checkPowerOfTwo(
1802217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    blockSize.getWidth(), "block-size width must be power of two");
1803217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            checkPowerOfTwo(
1804217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    blockSize.getHeight(), "block-size height must be power of two");
1805b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
1806217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            checkPowerOfTwo(
1807217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    alignment.getWidth(), "alignment width must be power of two");
1808217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            checkPowerOfTwo(
1809217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    alignment.getHeight(), "alignment height must be power of two");
1810217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1811217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // update block-size and alignment
1812217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            applyMacroBlockLimits(
1813217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE,
1814217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    Long.MAX_VALUE, blockSize.getWidth(), blockSize.getHeight(),
1815217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    alignment.getWidth(), alignment.getHeight());
1816217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
18172fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar            if ((mParent.mError & ERROR_UNSUPPORTED) != 0 || mAllowMbOverride) {
1818217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                // codec supports profiles that we don't know.
1819217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                // Use supplied values clipped to platform limits
1820217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (widths != null) {
1821217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mWidthRange = SIZE_RANGE.intersect(widths);
1822217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
1823217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (heights != null) {
1824217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mHeightRange = SIZE_RANGE.intersect(heights);
1825217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
1826217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (counts != null) {
1827217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mBlockCountRange = POSITIVE_INTEGERS.intersect(
1828217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            Utils.factorRange(counts, mBlockWidth * mBlockHeight
1829217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    / blockSize.getWidth() / blockSize.getHeight()));
1830217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
1831217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (blockRates != null) {
1832217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mBlocksPerSecondRange = POSITIVE_LONGS.intersect(
1833217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            Utils.factorRange(blockRates, mBlockWidth * mBlockHeight
1834217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    / blockSize.getWidth() / blockSize.getHeight()));
1835217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
1836217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (blockRatios != null) {
1837217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mBlockAspectRatioRange = POSITIVE_RATIONALS.intersect(
1838217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            Utils.scaleRange(blockRatios,
1839217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    mBlockHeight / blockSize.getHeight(),
1840217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    mBlockWidth / blockSize.getWidth()));
1841217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
1842217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (ratios != null) {
1843217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mAspectRatioRange = POSITIVE_RATIONALS.intersect(ratios);
1844217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
1845217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (frameRates != null) {
1846217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mFrameRateRange = FRAME_RATE_RANGE.intersect(frameRates);
1847217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
1848216e11dcbb4d56699c1740c801489be0d57b16c4Chong Zhang                if (bitRates != null) {
18492fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                    // only allow bitrate override if unsupported profiles were encountered
18502fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                    if ((mParent.mError & ERROR_UNSUPPORTED) != 0) {
18512fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                        mBitrateRange = BITRATE_RANGE.intersect(bitRates);
18522fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                    } else {
18532fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                        mBitrateRange = mBitrateRange.intersect(bitRates);
18542fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                    }
1855216e11dcbb4d56699c1740c801489be0d57b16c4Chong Zhang                }
1856217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            } else {
1857217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                // no unsupported profile/levels, so restrict values to known limits
1858217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (widths != null) {
1859217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mWidthRange = mWidthRange.intersect(widths);
1860217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
1861217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (heights != null) {
1862217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mHeightRange = mHeightRange.intersect(heights);
1863b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                }
1864217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (counts != null) {
1865217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mBlockCountRange = mBlockCountRange.intersect(
1866217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            Utils.factorRange(counts, mBlockWidth * mBlockHeight
1867217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    / blockSize.getWidth() / blockSize.getHeight()));
1868b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                }
1869217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (blockRates != null) {
1870217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mBlocksPerSecondRange = mBlocksPerSecondRange.intersect(
1871217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            Utils.factorRange(blockRates, mBlockWidth * mBlockHeight
1872217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    / blockSize.getWidth() / blockSize.getHeight()));
1873b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                }
1874217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (blockRatios != null) {
1875217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mBlockAspectRatioRange = mBlockAspectRatioRange.intersect(
1876217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            Utils.scaleRange(blockRatios,
1877217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    mBlockHeight / blockSize.getHeight(),
1878217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    mBlockWidth / blockSize.getWidth()));
1879217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
1880217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (ratios != null) {
1881217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mAspectRatioRange = mAspectRatioRange.intersect(ratios);
1882217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
1883217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (frameRates != null) {
1884217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mFrameRateRange = mFrameRateRange.intersect(frameRates);
1885217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
1886216e11dcbb4d56699c1740c801489be0d57b16c4Chong Zhang                if (bitRates != null) {
1887216e11dcbb4d56699c1740c801489be0d57b16c4Chong Zhang                    mBitrateRange = mBitrateRange.intersect(bitRates);
1888216e11dcbb4d56699c1740c801489be0d57b16c4Chong Zhang                }
1889217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
1890217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            updateLimits();
1891217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1892217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1893217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private void applyBlockLimits(
1894217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                int blockWidth, int blockHeight,
1895217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                Range<Integer> counts, Range<Long> rates, Range<Rational> ratios) {
1896217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            checkPowerOfTwo(blockWidth, "blockWidth must be a power of two");
1897217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            checkPowerOfTwo(blockHeight, "blockHeight must be a power of two");
1898217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1899217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            final int newBlockWidth = Math.max(blockWidth, mBlockWidth);
1900217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            final int newBlockHeight = Math.max(blockHeight, mBlockHeight);
1901217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1902217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // factor will always be a power-of-2
1903217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            int factor =
1904217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                newBlockWidth * newBlockHeight / mBlockWidth / mBlockHeight;
1905217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (factor != 1) {
1906217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                mBlockCountRange = Utils.factorRange(mBlockCountRange, factor);
1907217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                mBlocksPerSecondRange = Utils.factorRange(
1908217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        mBlocksPerSecondRange, factor);
1909217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                mBlockAspectRatioRange = Utils.scaleRange(
1910217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        mBlockAspectRatioRange,
1911217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        newBlockHeight / mBlockHeight,
1912217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        newBlockWidth / mBlockWidth);
1913217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                mHorizontalBlockRange = Utils.factorRange(
1914217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        mHorizontalBlockRange, newBlockWidth / mBlockWidth);
1915217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                mVerticalBlockRange = Utils.factorRange(
1916217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        mVerticalBlockRange, newBlockHeight / mBlockHeight);
1917217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
1918217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            factor = newBlockWidth * newBlockHeight / blockWidth / blockHeight;
1919217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (factor != 1) {
1920217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                counts = Utils.factorRange(counts, factor);
1921217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                rates = Utils.factorRange(rates, factor);
1922217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                ratios = Utils.scaleRange(
1923217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        ratios, newBlockHeight / blockHeight,
1924217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        newBlockWidth / blockWidth);
1925217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
1926217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mBlockCountRange = mBlockCountRange.intersect(counts);
1927217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mBlocksPerSecondRange = mBlocksPerSecondRange.intersect(rates);
1928217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mBlockAspectRatioRange = mBlockAspectRatioRange.intersect(ratios);
1929217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mBlockWidth = newBlockWidth;
1930217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mBlockHeight = newBlockHeight;
1931217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1932217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1933217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private void applyAlignment(int widthAlignment, int heightAlignment) {
1934217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            checkPowerOfTwo(widthAlignment, "widthAlignment must be a power of two");
1935217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            checkPowerOfTwo(heightAlignment, "heightAlignment must be a power of two");
1936217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1937217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (widthAlignment > mBlockWidth || heightAlignment > mBlockHeight) {
1938217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                // maintain assumption that 0 < alignment <= block-size
1939217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                applyBlockLimits(
1940217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        Math.max(widthAlignment, mBlockWidth),
1941217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        Math.max(heightAlignment, mBlockHeight),
1942217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        POSITIVE_INTEGERS, POSITIVE_LONGS, POSITIVE_RATIONALS);
1943b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
1944b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
1945217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mWidthAlignment = Math.max(widthAlignment, mWidthAlignment);
1946217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mHeightAlignment = Math.max(heightAlignment, mHeightAlignment);
1947217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1948217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mWidthRange = Utils.alignRange(mWidthRange, mWidthAlignment);
1949217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mHeightRange = Utils.alignRange(mHeightRange, mHeightAlignment);
1950217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1951217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1952217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private void updateLimits() {
1953217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // pixels -> blocks <- counts
1954217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mHorizontalBlockRange = mHorizontalBlockRange.intersect(
1955217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    Utils.factorRange(mWidthRange, mBlockWidth));
1956217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mHorizontalBlockRange = mHorizontalBlockRange.intersect(
1957217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    Range.create(
1958217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            mBlockCountRange.getLower() / mVerticalBlockRange.getUpper(),
1959217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            mBlockCountRange.getUpper() / mVerticalBlockRange.getLower()));
1960217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mVerticalBlockRange = mVerticalBlockRange.intersect(
1961217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    Utils.factorRange(mHeightRange, mBlockHeight));
1962217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mVerticalBlockRange = mVerticalBlockRange.intersect(
1963217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    Range.create(
1964217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            mBlockCountRange.getLower() / mHorizontalBlockRange.getUpper(),
1965217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            mBlockCountRange.getUpper() / mHorizontalBlockRange.getLower()));
1966217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mBlockCountRange = mBlockCountRange.intersect(
1967217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    Range.create(
1968217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            mHorizontalBlockRange.getLower()
1969217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    * mVerticalBlockRange.getLower(),
1970217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            mHorizontalBlockRange.getUpper()
1971217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    * mVerticalBlockRange.getUpper()));
1972217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mBlockAspectRatioRange = mBlockAspectRatioRange.intersect(
1973217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    new Rational(
1974217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            mHorizontalBlockRange.getLower(), mVerticalBlockRange.getUpper()),
1975217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    new Rational(
1976217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            mHorizontalBlockRange.getUpper(), mVerticalBlockRange.getLower()));
1977217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1978217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // blocks -> pixels
1979217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mWidthRange = mWidthRange.intersect(
1980217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    (mHorizontalBlockRange.getLower() - 1) * mBlockWidth + mWidthAlignment,
1981217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mHorizontalBlockRange.getUpper() * mBlockWidth);
1982217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mHeightRange = mHeightRange.intersect(
1983217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    (mVerticalBlockRange.getLower() - 1) * mBlockHeight + mHeightAlignment,
1984217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mVerticalBlockRange.getUpper() * mBlockHeight);
1985217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mAspectRatioRange = mAspectRatioRange.intersect(
1986217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    new Rational(mWidthRange.getLower(), mHeightRange.getUpper()),
1987217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    new Rational(mWidthRange.getUpper(), mHeightRange.getLower()));
1988217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1989217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mSmallerDimensionUpperLimit = Math.min(
1990217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mSmallerDimensionUpperLimit,
1991217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    Math.min(mWidthRange.getUpper(), mHeightRange.getUpper()));
1992217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1993217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // blocks -> rate
1994217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mBlocksPerSecondRange = mBlocksPerSecondRange.intersect(
1995217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mBlockCountRange.getLower() * (long)mFrameRateRange.getLower(),
1996217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mBlockCountRange.getUpper() * (long)mFrameRateRange.getUpper());
1997217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mFrameRateRange = mFrameRateRange.intersect(
1998217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    (int)(mBlocksPerSecondRange.getLower()
1999217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            / mBlockCountRange.getUpper()),
2000217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    (int)(mBlocksPerSecondRange.getUpper()
2001217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            / (double)mBlockCountRange.getLower()));
2002217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
2003217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
2004217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private void applyMacroBlockLimits(
2005217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                int maxHorizontalBlocks, int maxVerticalBlocks,
2006217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                int maxBlocks, long maxBlocksPerSecond,
2007217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                int blockWidth, int blockHeight,
2008217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                int widthAlignment, int heightAlignment) {
20092fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar            applyMacroBlockLimits(
20102fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                    1 /* minHorizontalBlocks */, 1 /* minVerticalBlocks */,
20112fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                    maxHorizontalBlocks, maxVerticalBlocks,
20122fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                    maxBlocks, maxBlocksPerSecond,
20132fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                    blockWidth, blockHeight, widthAlignment, heightAlignment);
20142fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar        }
20152fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar
20162fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar        private void applyMacroBlockLimits(
20172fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                int minHorizontalBlocks, int minVerticalBlocks,
20182fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                int maxHorizontalBlocks, int maxVerticalBlocks,
20192fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                int maxBlocks, long maxBlocksPerSecond,
20202fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                int blockWidth, int blockHeight,
20212fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                int widthAlignment, int heightAlignment) {
2022217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            applyAlignment(widthAlignment, heightAlignment);
2023217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            applyBlockLimits(
2024217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    blockWidth, blockHeight, Range.create(1, maxBlocks),
2025217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    Range.create(1L, maxBlocksPerSecond),
2026217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    Range.create(
2027217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            new Rational(1, maxVerticalBlocks),
2028217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            new Rational(maxHorizontalBlocks, 1)));
2029217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mHorizontalBlockRange =
2030217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mHorizontalBlockRange.intersect(
20312fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                            Utils.divUp(minHorizontalBlocks, (mBlockWidth / blockWidth)),
20322fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                            maxHorizontalBlocks / (mBlockWidth / blockWidth));
2033217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mVerticalBlockRange =
2034217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mVerticalBlockRange.intersect(
20352fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                            Utils.divUp(minVerticalBlocks, (mBlockHeight / blockHeight)),
20362fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                            maxVerticalBlocks / (mBlockHeight / blockHeight));
2037217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
2038217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
2039217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private void applyLevelLimits() {
2040f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu            long maxBlocksPerSecond = 0;
2041217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            int maxBlocks = 0;
2042217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            int maxBps = 0;
2043217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            int maxDPBBlocks = 0;
2044217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
2045217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            int errors = ERROR_NONE_SUPPORTED;
2046217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            CodecProfileLevel[] profileLevels = mParent.profileLevels;
2047217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            String mime = mParent.getMimeType();
2048217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
20495755817422700f6f5e8380921d1f5a728b677dd2Ronghua Wu            if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_AVC)) {
2050217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxBlocks = 99;
2051217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxBlocksPerSecond = 1485;
2052217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxBps = 64000;
2053217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxDPBBlocks = 396;
2054217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                for (CodecProfileLevel profileLevel: profileLevels) {
2055217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    int MBPS = 0, FS = 0, BR = 0, DPB = 0;
2056217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    boolean supported = true;
2057217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    switch (profileLevel.level) {
2058217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCLevel1:
2059217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            MBPS =    1485; FS =    99; BR =     64; DPB =    396; break;
2060217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCLevel1b:
2061217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            MBPS =    1485; FS =    99; BR =    128; DPB =    396; break;
2062217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCLevel11:
2063217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            MBPS =    3000; FS =   396; BR =    192; DPB =    900; break;
2064217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCLevel12:
2065217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            MBPS =    6000; FS =   396; BR =    384; DPB =   2376; break;
2066217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCLevel13:
2067217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            MBPS =   11880; FS =   396; BR =    768; DPB =   2376; break;
2068217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCLevel2:
2069217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            MBPS =   11880; FS =   396; BR =   2000; DPB =   2376; break;
2070217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCLevel21:
2071217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            MBPS =   19800; FS =   792; BR =   4000; DPB =   4752; break;
2072217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCLevel22:
2073217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            MBPS =   20250; FS =  1620; BR =   4000; DPB =   8100; break;
2074217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCLevel3:
2075217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            MBPS =   40500; FS =  1620; BR =  10000; DPB =   8100; break;
2076217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCLevel31:
2077217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            MBPS =  108000; FS =  3600; BR =  14000; DPB =  18000; break;
2078217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCLevel32:
2079217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            MBPS =  216000; FS =  5120; BR =  20000; DPB =  20480; break;
2080217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCLevel4:
2081217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            MBPS =  245760; FS =  8192; BR =  20000; DPB =  32768; break;
2082217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCLevel41:
2083217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            MBPS =  245760; FS =  8192; BR =  50000; DPB =  32768; break;
2084217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCLevel42:
2085217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            MBPS =  522240; FS =  8704; BR =  50000; DPB =  34816; break;
2086217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCLevel5:
2087217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            MBPS =  589824; FS = 22080; BR = 135000; DPB = 110400; break;
2088217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCLevel51:
2089217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            MBPS =  983040; FS = 36864; BR = 240000; DPB = 184320; break;
2090217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCLevel52:
2091217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            MBPS = 2073600; FS = 36864; BR = 240000; DPB = 184320; break;
2092217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        default:
2093217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            Log.w(TAG, "Unrecognized level "
2094217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    + profileLevel.level + " for " + mime);
2095217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            errors |= ERROR_UNRECOGNIZED;
2096217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    }
2097217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    switch (profileLevel.profile) {
2098217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCProfileHigh:
2099217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            BR *= 1250; break;
2100217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCProfileHigh10:
2101217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            BR *= 3000; break;
2102217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCProfileExtended:
2103217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCProfileHigh422:
2104217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCProfileHigh444:
2105217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            Log.w(TAG, "Unsupported profile "
2106217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    + profileLevel.profile + " for " + mime);
2107217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            errors |= ERROR_UNSUPPORTED;
2108217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            supported = false;
2109217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            // fall through - treat as base profile
2110217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCProfileBaseline:
2111217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCProfileMain:
2112217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            BR *= 1000; break;
2113217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        default:
2114217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            Log.w(TAG, "Unrecognized profile "
2115217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    + profileLevel.profile + " for " + mime);
2116217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            errors |= ERROR_UNRECOGNIZED;
2117217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            BR *= 1000;
2118217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    }
2119217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    if (supported) {
2120217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        errors &= ~ERROR_NONE_SUPPORTED;
2121217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    }
2122217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    maxBlocksPerSecond = Math.max(MBPS, maxBlocksPerSecond);
2123217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    maxBlocks = Math.max(FS, maxBlocks);
2124217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    maxBps = Math.max(BR, maxBps);
2125217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    maxDPBBlocks = Math.max(maxDPBBlocks, DPB);
2126981c344ee7a4472e2a331d66819c132267a681c6Lajos Molnar                }
2127217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
2128217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                int maxLengthInBlocks = (int)(Math.sqrt(maxBlocks * 8));
2129217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                applyMacroBlockLimits(
2130217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        maxLengthInBlocks, maxLengthInBlocks,
2131217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        maxBlocks, maxBlocksPerSecond,
2132217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        16 /* blockWidth */, 16 /* blockHeight */,
2133217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        1 /* widthAlignment */, 1 /* heightAlignment */);
213434265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_MPEG2)) {
213534265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                int maxWidth = 11, maxHeight = 9, maxRate = 15;
213634265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                maxBlocks = 99;
213734265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                maxBlocksPerSecond = 1485;
213834265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                maxBps = 64000;
213934265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                for (CodecProfileLevel profileLevel: profileLevels) {
214034265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                    int MBPS = 0, FS = 0, BR = 0, FR = 0, W = 0, H = 0;
214134265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                    boolean supported = true;
214234265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                    switch (profileLevel.profile) {
214334265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                        case CodecProfileLevel.MPEG2ProfileSimple:
214434265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                            switch (profileLevel.level) {
214534265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                                case CodecProfileLevel.MPEG2LevelML:
21462fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                                    FR = 30; W = 45; H =  36; MBPS =  40500; FS =  1620; BR =  15000; break;
214734265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                                default:
214834265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                                    Log.w(TAG, "Unrecognized profile/level "
214934265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                                            + profileLevel.profile + "/"
215034265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                                            + profileLevel.level + " for " + mime);
215134265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                                    errors |= ERROR_UNRECOGNIZED;
215234265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                            }
215334265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                            break;
215434265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                        case CodecProfileLevel.MPEG2ProfileMain:
215534265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                            switch (profileLevel.level) {
215634265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                                case CodecProfileLevel.MPEG2LevelLL:
21572a4001ee62f3374d7fffed72d71f77c5a833c331Lajos Molnar                                    FR = 30; W = 22; H =  18; MBPS =  11880; FS =   396; BR =  4000; break;
215834265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                                case CodecProfileLevel.MPEG2LevelML:
21592fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                                    FR = 30; W = 45; H =  36; MBPS =  40500; FS =  1620; BR = 15000; break;
216034265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                                case CodecProfileLevel.MPEG2LevelH14:
21612a4001ee62f3374d7fffed72d71f77c5a833c331Lajos Molnar                                    FR = 60; W = 90; H =  68; MBPS = 183600; FS =  6120; BR = 60000; break;
216234265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                                case CodecProfileLevel.MPEG2LevelHL:
21632a4001ee62f3374d7fffed72d71f77c5a833c331Lajos Molnar                                    FR = 60; W = 120; H = 68; MBPS = 244800; FS =  8160; BR = 80000; break;
21642a4001ee62f3374d7fffed72d71f77c5a833c331Lajos Molnar                                case CodecProfileLevel.MPEG2LevelHP:
21652a4001ee62f3374d7fffed72d71f77c5a833c331Lajos Molnar                                    FR = 60; W = 120; H = 68; MBPS = 489600; FS =  8160; BR = 80000; break;
216634265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                                default:
216734265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                                    Log.w(TAG, "Unrecognized profile/level "
216834265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                                            + profileLevel.profile + "/"
216934265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                                            + profileLevel.level + " for " + mime);
217034265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                                    errors |= ERROR_UNRECOGNIZED;
217134265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                            }
217234265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                            break;
217334265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                        case CodecProfileLevel.MPEG2Profile422:
217434265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                        case CodecProfileLevel.MPEG2ProfileSNR:
217534265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                        case CodecProfileLevel.MPEG2ProfileSpatial:
217634265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                        case CodecProfileLevel.MPEG2ProfileHigh:
217734265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                            Log.i(TAG, "Unsupported profile "
217834265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                                    + profileLevel.profile + " for " + mime);
217934265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                            errors |= ERROR_UNSUPPORTED;
218034265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                            supported = false;
218134265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                            break;
218234265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                        default:
218334265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                            Log.w(TAG, "Unrecognized profile "
218434265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                                    + profileLevel.profile + " for " + mime);
218534265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                            errors |= ERROR_UNRECOGNIZED;
218634265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                    }
218734265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                    if (supported) {
218834265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                        errors &= ~ERROR_NONE_SUPPORTED;
218934265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                    }
219034265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                    maxBlocksPerSecond = Math.max(MBPS, maxBlocksPerSecond);
219134265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                    maxBlocks = Math.max(FS, maxBlocks);
219234265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                    maxBps = Math.max(BR * 1000, maxBps);
219334265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                    maxWidth = Math.max(W, maxWidth);
219434265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                    maxHeight = Math.max(H, maxHeight);
219534265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                    maxRate = Math.max(FR, maxRate);
219634265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                }
219734265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                applyMacroBlockLimits(maxWidth, maxHeight,
219834265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                        maxBlocks, maxBlocksPerSecond,
219934265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                        16 /* blockWidth */, 16 /* blockHeight */,
220034265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                        1 /* widthAlignment */, 1 /* heightAlignment */);
220134265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar                mFrameRateRange = mFrameRateRange.intersect(12, maxRate);
2202217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_MPEG4)) {
2203217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                int maxWidth = 11, maxHeight = 9, maxRate = 15;
2204217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxBlocks = 99;
2205217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxBlocksPerSecond = 1485;
2206217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxBps = 64000;
2207217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                for (CodecProfileLevel profileLevel: profileLevels) {
2208217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    int MBPS = 0, FS = 0, BR = 0, FR = 0, W = 0, H = 0;
22092fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                    boolean strict = false; // true: W, H and FR are individual max limits
2210217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    boolean supported = true;
2211217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    switch (profileLevel.profile) {
2212217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.MPEG4ProfileSimple:
2213217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            switch (profileLevel.level) {
2214217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                case CodecProfileLevel.MPEG4Level0:
22152fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                                    strict = true;
2216217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    FR = 15; W = 11; H =  9; MBPS =  1485; FS =  99; BR =  64; break;
2217217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                case CodecProfileLevel.MPEG4Level1:
2218217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    FR = 30; W = 11; H =  9; MBPS =  1485; FS =  99; BR =  64; break;
2219217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                case CodecProfileLevel.MPEG4Level0b:
22202fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                                    strict = true;
22212fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                                    FR = 15; W = 11; H =  9; MBPS =  1485; FS =  99; BR = 128; break;
2222217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                case CodecProfileLevel.MPEG4Level2:
2223217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    FR = 30; W = 22; H = 18; MBPS =  5940; FS = 396; BR = 128; break;
2224217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                case CodecProfileLevel.MPEG4Level3:
2225217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    FR = 30; W = 22; H = 18; MBPS = 11880; FS = 396; BR = 384; break;
2226217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                case CodecProfileLevel.MPEG4Level4a:
22272a4001ee62f3374d7fffed72d71f77c5a833c331Lajos Molnar                                    FR = 30; W = 40; H = 30; MBPS = 36000; FS = 1200; BR = 4000; break;
2228217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                case CodecProfileLevel.MPEG4Level5:
22292a4001ee62f3374d7fffed72d71f77c5a833c331Lajos Molnar                                    FR = 30; W = 45; H = 36; MBPS = 40500; FS = 1620; BR = 8000; break;
22302a4001ee62f3374d7fffed72d71f77c5a833c331Lajos Molnar                                case CodecProfileLevel.MPEG4Level6:
22312a4001ee62f3374d7fffed72d71f77c5a833c331Lajos Molnar                                    FR = 30; W = 80; H = 45; MBPS = 108000; FS = 3600; BR = 12000; break;
2232217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                default:
2233217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    Log.w(TAG, "Unrecognized profile/level "
2234217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                            + profileLevel.profile + "/"
2235217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                            + profileLevel.level + " for " + mime);
2236217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    errors |= ERROR_UNRECOGNIZED;
2237217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            }
2238217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            break;
2239217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.MPEG4ProfileAdvancedSimple:
2240217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            switch (profileLevel.level) {
2241217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                case CodecProfileLevel.MPEG4Level0:
2242217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                case CodecProfileLevel.MPEG4Level1:
2243217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    FR = 30; W = 11; H =  9; MBPS =  2970; FS =   99; BR =  128; break;
2244217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                case CodecProfileLevel.MPEG4Level2:
2245217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    FR = 30; W = 22; H = 18; MBPS =  5940; FS =  396; BR =  384; break;
2246217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                case CodecProfileLevel.MPEG4Level3:
2247217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    FR = 30; W = 22; H = 18; MBPS = 11880; FS =  396; BR =  768; break;
22482a4001ee62f3374d7fffed72d71f77c5a833c331Lajos Molnar                                case CodecProfileLevel.MPEG4Level3b:
22492a4001ee62f3374d7fffed72d71f77c5a833c331Lajos Molnar                                    FR = 30; W = 22; H = 18; MBPS = 11880; FS =  396; BR = 1500; break;
2250217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                case CodecProfileLevel.MPEG4Level4:
2251217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    FR = 30; W = 44; H = 36; MBPS = 23760; FS =  792; BR = 3000; break;
2252217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                case CodecProfileLevel.MPEG4Level5:
2253217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    FR = 30; W = 45; H = 36; MBPS = 48600; FS = 1620; BR = 8000; break;
2254217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                default:
2255217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    Log.w(TAG, "Unrecognized profile/level "
2256217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                            + profileLevel.profile + "/"
2257217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                            + profileLevel.level + " for " + mime);
2258217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    errors |= ERROR_UNRECOGNIZED;
2259217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            }
2260217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            break;
2261217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.MPEG4ProfileMain:             // 2-4
2262217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.MPEG4ProfileNbit:             // 2
2263217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.MPEG4ProfileAdvancedRealTime: // 1-4
2264217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.MPEG4ProfileCoreScalable:     // 1-3
2265217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.MPEG4ProfileAdvancedCoding:   // 1-4
2266217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.MPEG4ProfileCore:             // 1-2
2267217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.MPEG4ProfileAdvancedCore:     // 1-4
2268217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.MPEG4ProfileSimpleScalable:   // 0-2
2269217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.MPEG4ProfileHybrid:           // 1-2
22702fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar
22712fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                        // Studio profiles are not supported by our codecs.
22722fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar
22732fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                        // Only profiles that can decode simple object types are considered.
22742fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                        // The following profiles are not able to.
2275217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.MPEG4ProfileBasicAnimated:    // 1-2
2276217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.MPEG4ProfileScalableTexture:  // 1
2277217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.MPEG4ProfileSimpleFace:       // 1-2
22782fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                        case CodecProfileLevel.MPEG4ProfileAdvancedScalable: // 1-3
2279217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.MPEG4ProfileSimpleFBA:        // 1-2
2280217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            Log.i(TAG, "Unsupported profile "
2281217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    + profileLevel.profile + " for " + mime);
2282217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            errors |= ERROR_UNSUPPORTED;
2283217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            supported = false;
2284217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            break;
2285217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        default:
2286217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            Log.w(TAG, "Unrecognized profile "
2287217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    + profileLevel.profile + " for " + mime);
2288217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            errors |= ERROR_UNRECOGNIZED;
2289217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    }
2290217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    if (supported) {
2291217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        errors &= ~ERROR_NONE_SUPPORTED;
2292217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    }
2293217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    maxBlocksPerSecond = Math.max(MBPS, maxBlocksPerSecond);
2294217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    maxBlocks = Math.max(FS, maxBlocks);
2295217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    maxBps = Math.max(BR * 1000, maxBps);
22962fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                    if (strict) {
22972fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                        maxWidth = Math.max(W, maxWidth);
22982fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                        maxHeight = Math.max(H, maxHeight);
22992fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                        maxRate = Math.max(FR, maxRate);
23002fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                    } else {
23012fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                        // assuming max 60 fps frame rate and 1:2 aspect ratio
23022fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                        int maxDim = (int)Math.sqrt(FS * 2);
23032fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                        maxWidth = Math.max(maxDim, maxWidth);
23042fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                        maxHeight = Math.max(maxDim, maxHeight);
23052fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                        maxRate = Math.max(Math.max(FR, 60), maxRate);
23062fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                    }
2307981c344ee7a4472e2a331d66819c132267a681c6Lajos Molnar                }
2308217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                applyMacroBlockLimits(maxWidth, maxHeight,
2309217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        maxBlocks, maxBlocksPerSecond,
2310217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        16 /* blockWidth */, 16 /* blockHeight */,
2311217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        1 /* widthAlignment */, 1 /* heightAlignment */);
2312217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                mFrameRateRange = mFrameRateRange.intersect(12, maxRate);
2313217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_H263)) {
2314217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                int maxWidth = 11, maxHeight = 9, maxRate = 15;
23152fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                int minWidth = maxWidth, minHeight = maxHeight;
23162fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                int minAlignment = 16;
2317217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxBlocks = 99;
2318217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxBlocksPerSecond = 1485;
2319217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxBps = 64000;
2320217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                for (CodecProfileLevel profileLevel: profileLevels) {
23212fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                    int MBPS = 0, BR = 0, FR = 0, W = 0, H = 0, minW = minWidth, minH = minHeight;
23222fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                    boolean strict = false; // true: support only sQCIF, QCIF (maybe CIF)
2323217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    switch (profileLevel.level) {
2324217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.H263Level10:
23252fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                            strict = true; // only supports sQCIF & QCIF
2326217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR = 15; W = 11; H =  9; BR =   1; MBPS =  W * H * FR; break;
2327217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.H263Level20:
23282fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                            strict = true; // only supports sQCIF, QCIF & CIF
23292fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                            FR = 30; W = 22; H = 18; BR =   2; MBPS =  W * H * 15; break;
2330217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.H263Level30:
23312fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                            strict = true; // only supports sQCIF, QCIF & CIF
2332217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR = 30; W = 22; H = 18; BR =   6; MBPS =  W * H * FR; break;
2333217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.H263Level40:
23342fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                            strict = true; // only supports sQCIF, QCIF & CIF
2335217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR = 30; W = 22; H = 18; BR =  32; MBPS =  W * H * FR; break;
2336217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.H263Level45:
2337217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            // only implies level 10 support
23382fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                            strict = profileLevel.profile == CodecProfileLevel.H263ProfileBaseline
23392fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                                    || profileLevel.profile ==
23402fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                                            CodecProfileLevel.H263ProfileBackwardCompatible;
23412fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                            if (!strict) {
23422fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                                minW = 1; minH = 1; minAlignment = 4;
23432fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                            }
23442fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                            FR = 15; W = 11; H =  9; BR =   2; MBPS =  W * H * FR; break;
2345217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.H263Level50:
2346217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            // only supports 50fps for H > 15
23472fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                            minW = 1; minH = 1; minAlignment = 4;
2348217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR = 60; W = 22; H = 18; BR =  64; MBPS =  W * H * 50; break;
2349217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.H263Level60:
2350217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            // only supports 50fps for H > 15
23512fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                            minW = 1; minH = 1; minAlignment = 4;
2352217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR = 60; W = 45; H = 18; BR = 128; MBPS =  W * H * 50; break;
2353217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.H263Level70:
2354217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            // only supports 50fps for H > 30
23552fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                            minW = 1; minH = 1; minAlignment = 4;
2356217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR = 60; W = 45; H = 36; BR = 256; MBPS =  W * H * 50; break;
2357217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        default:
2358217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            Log.w(TAG, "Unrecognized profile/level " + profileLevel.profile
2359217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    + "/" + profileLevel.level + " for " + mime);
2360217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            errors |= ERROR_UNRECOGNIZED;
2361217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    }
2362217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    switch (profileLevel.profile) {
2363217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.H263ProfileBackwardCompatible:
2364217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.H263ProfileBaseline:
2365217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.H263ProfileH320Coding:
2366217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.H263ProfileHighCompression:
2367217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.H263ProfileHighLatency:
2368217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.H263ProfileInterlace:
2369217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.H263ProfileInternet:
2370217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.H263ProfileISWV2:
2371217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.H263ProfileISWV3:
2372217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            break;
2373217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        default:
2374217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            Log.w(TAG, "Unrecognized profile "
2375217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    + profileLevel.profile + " for " + mime);
2376217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            errors |= ERROR_UNRECOGNIZED;
2377217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    }
23782fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                    if (strict) {
23792fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                        // Strict levels define sub-QCIF min size and enumerated sizes. We cannot
23802fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                        // express support for "only sQCIF & QCIF (& CIF)" using VideoCapabilities
23812fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                        // but we can express "only QCIF (& CIF)", so set minimume size at QCIF.
23822fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                        // minW = 8; minH = 6;
23832fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                        minW = 11; minH = 9;
23842fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                    } else {
23852fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                        // any support for non-strict levels (including unrecognized profiles or
23862fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                        // levels) allow custom frame size support beyond supported limits
23872fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                        // (other than bitrate)
23882fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                        mAllowMbOverride = true;
23892fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                    }
2390217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    errors &= ~ERROR_NONE_SUPPORTED;
2391217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    maxBlocksPerSecond = Math.max(MBPS, maxBlocksPerSecond);
2392217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    maxBlocks = Math.max(W * H, maxBlocks);
2393217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    maxBps = Math.max(BR * 64000, maxBps);
2394217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    maxWidth = Math.max(W, maxWidth);
2395217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    maxHeight = Math.max(H, maxHeight);
2396217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    maxRate = Math.max(FR, maxRate);
23972fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                    minWidth = Math.min(minW, minWidth);
23982fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                    minHeight = Math.min(minH, minHeight);
2399217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
24002fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                // unless we encountered custom frame size support, limit size to QCIF and CIF
24012fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                // using aspect ratio.
24022fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                if (!mAllowMbOverride) {
24032fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                    mBlockAspectRatioRange =
24042fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                        Range.create(new Rational(11, 9), new Rational(11, 9));
24052fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                }
24062fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                applyMacroBlockLimits(
24072fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                        minWidth, minHeight,
24082fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                        maxWidth, maxHeight,
2409217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        maxBlocks, maxBlocksPerSecond,
2410217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        16 /* blockWidth */, 16 /* blockHeight */,
24112fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                        minAlignment /* widthAlignment */, minAlignment /* heightAlignment */);
2412217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                mFrameRateRange = Range.create(1, maxRate);
2413f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP8)) {
2414f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                maxBlocks = Integer.MAX_VALUE;
2415f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                maxBlocksPerSecond = Integer.MAX_VALUE;
2416217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
2417f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                // TODO: set to 100Mbps for now, need a number for VP8
2418217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxBps = 100000000;
2419217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
2420217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                // profile levels are not indicative for VPx, but verify
2421217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                // them nonetheless
2422217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                for (CodecProfileLevel profileLevel: profileLevels) {
2423217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    switch (profileLevel.level) {
2424217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.VP8Level_Version0:
2425217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.VP8Level_Version1:
2426217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.VP8Level_Version2:
2427217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.VP8Level_Version3:
2428217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            break;
2429217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        default:
2430217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            Log.w(TAG, "Unrecognized level "
2431217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    + profileLevel.level + " for " + mime);
2432217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            errors |= ERROR_UNRECOGNIZED;
2433217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    }
2434217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    switch (profileLevel.profile) {
2435217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.VP8ProfileMain:
2436217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            break;
2437217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        default:
2438217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            Log.w(TAG, "Unrecognized profile "
2439217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    + profileLevel.profile + " for " + mime);
2440217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            errors |= ERROR_UNRECOGNIZED;
2441217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    }
2442217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    errors &= ~ERROR_NONE_SUPPORTED;
2443981c344ee7a4472e2a331d66819c132267a681c6Lajos Molnar                }
2444981c344ee7a4472e2a331d66819c132267a681c6Lajos Molnar
2445f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                final int blockSize = 16;
2446217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                applyMacroBlockLimits(Short.MAX_VALUE, Short.MAX_VALUE,
2447217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        maxBlocks, maxBlocksPerSecond, blockSize, blockSize,
2448217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        1 /* widthAlignment */, 1 /* heightAlignment */);
2449f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP9)) {
2450f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                maxBlocksPerSecond = 829440;
2451f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                maxBlocks = 36864;
2452f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                maxBps = 200000;
24538acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                int maxDim = 512;
2454f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu
2455f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                for (CodecProfileLevel profileLevel: profileLevels) {
24568acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                    long SR = 0; // luma sample rate
24578acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                    int FS = 0;  // luma picture size
24588acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                    int BR = 0;  // bit rate kbps
24598acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                    int D = 0;   // luma dimension
2460f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                    switch (profileLevel.level) {
2461f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                        case CodecProfileLevel.VP9Level1:
24628acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                            SR =      829440; FS =    36864; BR =    200; D =   512; break;
2463f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                        case CodecProfileLevel.VP9Level11:
24648acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                            SR =     2764800; FS =    73728; BR =    800; D =   768; break;
2465f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                        case CodecProfileLevel.VP9Level2:
24668acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                            SR =     4608000; FS =   122880; BR =   1800; D =   960; break;
2467f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                        case CodecProfileLevel.VP9Level21:
24688acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                            SR =     9216000; FS =   245760; BR =   3600; D =  1344; break;
2469f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                        case CodecProfileLevel.VP9Level3:
24708acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                            SR =    20736000; FS =   552960; BR =   7200; D =  2048; break;
2471f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                        case CodecProfileLevel.VP9Level31:
24728acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                            SR =    36864000; FS =   983040; BR =  12000; D =  2752; break;
2473f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                        case CodecProfileLevel.VP9Level4:
24748acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                            SR =    83558400; FS =  2228224; BR =  18000; D =  4160; break;
2475f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                        case CodecProfileLevel.VP9Level41:
24768acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                            SR =   160432128; FS =  2228224; BR =  30000; D =  4160; break;
2477f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                        case CodecProfileLevel.VP9Level5:
24788acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                            SR =   311951360; FS =  8912896; BR =  60000; D =  8384; break;
2479f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                        case CodecProfileLevel.VP9Level51:
24808acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                            SR =   588251136; FS =  8912896; BR = 120000; D =  8384; break;
2481f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                        case CodecProfileLevel.VP9Level52:
24828acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                            SR =  1176502272; FS =  8912896; BR = 180000; D =  8384; break;
2483f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                        case CodecProfileLevel.VP9Level6:
24848acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                            SR =  1176502272; FS = 35651584; BR = 180000; D = 16832; break;
2485f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                        case CodecProfileLevel.VP9Level61:
24868acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                            SR = 2353004544L; FS = 35651584; BR = 240000; D = 16832; break;
2487f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                        case CodecProfileLevel.VP9Level62:
24888acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                            SR = 4706009088L; FS = 35651584; BR = 480000; D = 16832; break;
2489f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                        default:
2490f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                            Log.w(TAG, "Unrecognized level "
2491f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                                    + profileLevel.level + " for " + mime);
2492f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                            errors |= ERROR_UNRECOGNIZED;
2493f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                    }
2494f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                    switch (profileLevel.profile) {
2495f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                        case CodecProfileLevel.VP9Profile0:
2496f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                        case CodecProfileLevel.VP9Profile1:
2497f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                        case CodecProfileLevel.VP9Profile2:
2498f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                        case CodecProfileLevel.VP9Profile3:
24992fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                        case CodecProfileLevel.VP9Profile2HDR:
25002fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                        case CodecProfileLevel.VP9Profile3HDR:
2501f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                            break;
2502f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                        default:
2503f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                            Log.w(TAG, "Unrecognized profile "
2504f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                                    + profileLevel.profile + " for " + mime);
2505f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                            errors |= ERROR_UNRECOGNIZED;
2506f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                    }
2507f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                    errors &= ~ERROR_NONE_SUPPORTED;
2508f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                    maxBlocksPerSecond = Math.max(SR, maxBlocksPerSecond);
2509f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                    maxBlocks = Math.max(FS, maxBlocks);
2510f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                    maxBps = Math.max(BR * 1000, maxBps);
25118acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                    maxDim = Math.max(D, maxDim);
2512f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                }
2513f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu
2514f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                final int blockSize = 8;
25158acc16473873053342f7a033ad08c4421dfb3cafLajos Molnar                int maxLengthInBlocks = Utils.divUp(maxDim, blockSize);
2516f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                maxBlocks = Utils.divUp(maxBlocks, blockSize * blockSize);
2517f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                maxBlocksPerSecond = Utils.divUp(maxBlocksPerSecond, blockSize * blockSize);
2518f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu
2519f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                applyMacroBlockLimits(
2520f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                        maxLengthInBlocks, maxLengthInBlocks,
2521f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                        maxBlocks, maxBlocksPerSecond,
2522f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                        blockSize, blockSize,
2523f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu                        1 /* widthAlignment */, 1 /* heightAlignment */);
25245755817422700f6f5e8380921d1f5a728b677dd2Ronghua Wu            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_HEVC)) {
25252fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                // CTBs are at least 8x8 so use 8x8 block size
25262fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                maxBlocks = 36864 >> 6; // 192x192 pixels == 576 8x8 blocks
2527217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxBlocksPerSecond = maxBlocks * 15;
2528217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxBps = 128000;
2529217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                for (CodecProfileLevel profileLevel: profileLevels) {
2530217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    double FR = 0;
2531217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    int FS = 0;
2532217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    int BR = 0;
2533217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    switch (profileLevel.level) {
25342fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                        /* The HEVC spec talks only in a very convoluted manner about the
25352fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                           existence of levels 1-3.1 for High tier, which could also be
25362fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                           understood as 'decoders and encoders should treat these levels
25372fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                           as if they were Main tier', so we do that. */
2538217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCMainTierLevel1:
2539217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCHighTierLevel1:
2540217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR =    15; FS =    36864; BR =    128; break;
2541217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCMainTierLevel2:
2542217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCHighTierLevel2:
2543217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR =    30; FS =   122880; BR =   1500; break;
2544217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCMainTierLevel21:
2545217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCHighTierLevel21:
2546217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR =    30; FS =   245760; BR =   3000; break;
2547217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCMainTierLevel3:
2548217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCHighTierLevel3:
2549217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR =    30; FS =   552960; BR =   6000; break;
2550217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCMainTierLevel31:
2551217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCHighTierLevel31:
2552217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR = 33.75; FS =   983040; BR =  10000; break;
2553217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCMainTierLevel4:
2554217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR =    30; FS =  2228224; BR =  12000; break;
2555217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCHighTierLevel4:
2556217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR =    30; FS =  2228224; BR =  30000; break;
2557217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCMainTierLevel41:
2558217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR =    60; FS =  2228224; BR =  20000; break;
2559217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCHighTierLevel41:
2560217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR =    60; FS =  2228224; BR =  50000; break;
2561217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCMainTierLevel5:
2562217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR =    30; FS =  8912896; BR =  25000; break;
2563217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCHighTierLevel5:
2564217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR =    30; FS =  8912896; BR = 100000; break;
2565217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCMainTierLevel51:
2566217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR =    60; FS =  8912896; BR =  40000; break;
2567217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCHighTierLevel51:
2568217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR =    60; FS =  8912896; BR = 160000; break;
2569217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCMainTierLevel52:
2570217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR =   120; FS =  8912896; BR =  60000; break;
2571217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCHighTierLevel52:
2572217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR =   120; FS =  8912896; BR = 240000; break;
2573217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCMainTierLevel6:
2574217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR =    30; FS = 35651584; BR =  60000; break;
2575217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCHighTierLevel6:
2576217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR =    30; FS = 35651584; BR = 240000; break;
2577217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCMainTierLevel61:
2578217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR =    60; FS = 35651584; BR = 120000; break;
2579217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCHighTierLevel61:
2580217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR =    60; FS = 35651584; BR = 480000; break;
2581217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCMainTierLevel62:
2582217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR =   120; FS = 35651584; BR = 240000; break;
2583217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCHighTierLevel62:
2584217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR =   120; FS = 35651584; BR = 800000; break;
2585217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        default:
2586217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            Log.w(TAG, "Unrecognized level "
2587217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    + profileLevel.level + " for " + mime);
2588217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            errors |= ERROR_UNRECOGNIZED;
2589217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    }
2590217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    switch (profileLevel.profile) {
2591217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCProfileMain:
2592217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCProfileMain10:
2593f2615b8b339b812ad6b309d5ec116eb0add320f3Ronghua Wu                        case CodecProfileLevel.HEVCProfileMain10HDR10:
2594217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            break;
2595217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        default:
2596217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            Log.w(TAG, "Unrecognized profile "
2597217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    + profileLevel.profile + " for " + mime);
2598217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            errors |= ERROR_UNRECOGNIZED;
2599217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    }
2600217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
2601217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    /* DPB logic:
2602217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    if      (width * height <= FS / 4)    DPB = 16;
2603217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    else if (width * height <= FS / 2)    DPB = 12;
2604217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    else if (width * height <= FS * 0.75) DPB = 8;
2605217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    else                                  DPB = 6;
2606217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    */
2607217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
26082fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar                    FS >>= 6; // convert pixels to blocks
2609217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    errors &= ~ERROR_NONE_SUPPORTED;
2610217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    maxBlocksPerSecond = Math.max((int)(FR * FS), maxBlocksPerSecond);
2611217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    maxBlocks = Math.max(FS, maxBlocks);
2612217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    maxBps = Math.max(BR * 1000, maxBps);
2613b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                }
2614b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
2615217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                int maxLengthInBlocks = (int)(Math.sqrt(maxBlocks * 8));
2616217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                applyMacroBlockLimits(
2617217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        maxLengthInBlocks, maxLengthInBlocks,
2618217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        maxBlocks, maxBlocksPerSecond,
2619217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        8 /* blockWidth */, 8 /* blockHeight */,
2620217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        1 /* widthAlignment */, 1 /* heightAlignment */);
2621217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            } else {
2622217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                Log.w(TAG, "Unsupported mime " + mime);
2623217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                // using minimal bitrate here.  should be overriden by
2624217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                // info from media_codecs.xml
2625217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxBps = 64000;
2626217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                errors |= ERROR_UNSUPPORTED;
2627217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
2628217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mBitrateRange = Range.create(1, maxBps);
2629217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mParent.mError |= errors;
2630217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
2631217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    }
2632217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
2633217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    /**
2634217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar     * A class that supports querying the encoding capabilities of a codec.
2635217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar     */
2636217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    public static final class EncoderCapabilities {
2637217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /**
2638217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Returns the supported range of quality values.
2639217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         *
2640217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * @hide
2641217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         */
2642217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public Range<Integer> getQualityRange() {
2643217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return mQualityRange;
2644217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
2645217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
2646217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /**
2647217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Returns the supported range of encoder complexity values.
2648217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * <p>
2649217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Some codecs may support multiple complexity levels, where higher
2650217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * complexity values use more encoder tools (e.g. perform more
2651217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * intensive calculations) to improve the quality or the compression
2652217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * ratio.  Use a lower value to save power and/or time.
2653217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         */
2654217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public Range<Integer> getComplexityRange() {
2655217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return mComplexityRange;
2656217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
2657217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
2658217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /** Constant quality mode */
2659217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public static final int BITRATE_MODE_CQ = 0;
2660217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /** Variable bitrate mode */
2661217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public static final int BITRATE_MODE_VBR = 1;
2662217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /** Constant bitrate mode */
2663217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public static final int BITRATE_MODE_CBR = 2;
2664217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
2665217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private static final Feature[] bitrates = new Feature[] {
2666217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            new Feature("VBR", BITRATE_MODE_VBR, true),
2667217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            new Feature("CBR", BITRATE_MODE_CBR, false),
2668217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            new Feature("CQ",  BITRATE_MODE_CQ,  false)
2669b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        };
2670b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
2671217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private static int parseBitrateMode(String mode) {
2672217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            for (Feature feat: bitrates) {
2673217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (feat.mName.equalsIgnoreCase(mode)) {
2674217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    return feat.mValue;
2675217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
2676217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
2677217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return 0;
2678b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
2679b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
2680b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        /**
2681217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Query whether a bitrate mode is supported.
2682b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         */
2683217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public boolean isBitrateModeSupported(int mode) {
2684217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            for (Feature feat: bitrates) {
2685217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (mode == feat.mValue) {
2686217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    return (mBitControl & (1 << mode)) != 0;
2687217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
2688217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
2689217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return false;
2690b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
2691b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
2692217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private Range<Integer> mQualityRange;
2693217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private Range<Integer> mComplexityRange;
2694217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private CodecCapabilities mParent;
2695217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
2696217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /* no public constructor */
2697217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private EncoderCapabilities() { }
2698217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
2699b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        /** @hide */
2700217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public static EncoderCapabilities create(
2701217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                MediaFormat info, CodecCapabilities parent) {
2702217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            EncoderCapabilities caps = new EncoderCapabilities();
2703217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            caps.init(info, parent);
2704217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return caps;
2705217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
2706217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
2707217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /** @hide */
2708217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public void init(MediaFormat info, CodecCapabilities parent) {
2709217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // no support for complexity or quality yet
2710217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mParent = parent;
2711217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mComplexityRange = Range.create(0, 0);
2712217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mQualityRange = Range.create(0, 0);
2713217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mBitControl = (1 << BITRATE_MODE_VBR);
2714217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
2715217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            applyLevelLimits();
2716217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            parseFromInfo(info);
2717217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
2718217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
2719217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private void applyLevelLimits() {
2720217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            String mime = mParent.getMimeType();
2721217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_FLAC)) {
2722217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                mComplexityRange = Range.create(0, 8);
2723217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                mBitControl = (1 << BITRATE_MODE_CQ);
2724217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AMR_NB)
2725217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    || mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AMR_WB)
2726217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    || mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_G711_ALAW)
2727217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    || mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_G711_MLAW)
2728217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    || mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_MSGSM)) {
2729217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                mBitControl = (1 << BITRATE_MODE_CBR);
2730217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
2731217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
2732217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
2733217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private int mBitControl;
2734217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private Integer mDefaultComplexity;
2735217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private Integer mDefaultQuality;
2736217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private String mQualityScale;
2737217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
2738217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private void parseFromInfo(MediaFormat info) {
2739217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            Map<String, Object> map = info.getMap();
2740217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
2741217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (info.containsKey("complexity-range")) {
2742217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                mComplexityRange = Utils
2743217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        .parseIntRange(info.getString("complexity-range"), mComplexityRange);
2744217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                // TODO should we limit this to level limits?
2745217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
2746217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (info.containsKey("quality-range")) {
2747217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                mQualityRange = Utils
2748217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        .parseIntRange(info.getString("quality-range"), mQualityRange);
2749217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
2750217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (info.containsKey("feature-bitrate-control")) {
2751217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                for (String mode: info.getString("feature-bitrate-control").split(",")) {
2752217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mBitControl |= parseBitrateMode(mode);
2753217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
2754217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
2755217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
2756217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            try {
2757217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                mDefaultComplexity = Integer.parseInt((String)map.get("complexity-default"));
2758217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            } catch (NumberFormatException e) { }
2759217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
2760217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            try {
2761217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                mDefaultQuality = Integer.parseInt((String)map.get("quality-default"));
2762217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            } catch (NumberFormatException e) { }
2763217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
2764217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mQualityScale = (String)map.get("quality-scale");
2765217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
2766217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
2767217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private boolean supports(
2768217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                Integer complexity, Integer quality, Integer profile) {
2769217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            boolean ok = true;
2770217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (ok && complexity != null) {
2771217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                ok = mComplexityRange.contains(complexity);
2772217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
2773217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (ok && quality != null) {
2774217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                ok = mQualityRange.contains(quality);
2775217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
2776217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (ok && profile != null) {
2777217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                for (CodecProfileLevel pl: mParent.profileLevels) {
2778217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    if (pl.profile == profile) {
2779217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        profile = null;
2780217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        break;
2781217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    }
2782217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
2783217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                ok = profile == null;
2784217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
2785217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return ok;
2786217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
2787217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
2788217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /** @hide */
2789217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public void setDefaultFormat(MediaFormat format) {
2790217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // don't list trivial quality/complexity as default for now
2791217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (!mQualityRange.getUpper().equals(mQualityRange.getLower())
2792217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    && mDefaultQuality != null) {
2793217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                format.setInteger(MediaFormat.KEY_QUALITY, mDefaultQuality);
2794217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
2795217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (!mComplexityRange.getUpper().equals(mComplexityRange.getLower())
2796217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    && mDefaultComplexity != null) {
2797217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                format.setInteger(MediaFormat.KEY_COMPLEXITY, mDefaultComplexity);
2798217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
2799217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // bitrates are listed in order of preference
2800217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            for (Feature feat: bitrates) {
2801217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if ((mBitControl & (1 << feat.mValue)) != 0) {
2802217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    format.setInteger(MediaFormat.KEY_BITRATE_MODE, feat.mValue);
2803217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    break;
2804217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
2805217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
2806217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
2807217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
2808217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /** @hide */
2809217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public boolean supportsFormat(MediaFormat format) {
2810217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            final Map<String, Object> map = format.getMap();
2811217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            final String mime = mParent.getMimeType();
2812217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
2813217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            Integer mode = (Integer)map.get(MediaFormat.KEY_BITRATE_MODE);
2814217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (mode != null && !isBitrateModeSupported(mode)) {
2815217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                return false;
2816217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
2817217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
2818217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            Integer complexity = (Integer)map.get(MediaFormat.KEY_COMPLEXITY);
2819217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (MediaFormat.MIMETYPE_AUDIO_FLAC.equalsIgnoreCase(mime)) {
2820217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                Integer flacComplexity =
2821217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    (Integer)map.get(MediaFormat.KEY_FLAC_COMPRESSION_LEVEL);
2822217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (complexity == null) {
2823217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    complexity = flacComplexity;
28245c5978985a3457539d1f3b611f23d26b77484536Andreas Gampe                } else if (flacComplexity != null && !complexity.equals(flacComplexity)) {
2825217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    throw new IllegalArgumentException(
2826217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            "conflicting values for complexity and " +
2827217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            "flac-compression-level");
2828217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
2829217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
2830217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
2831217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // other audio parameters
2832217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            Integer profile = (Integer)map.get(MediaFormat.KEY_PROFILE);
2833217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (MediaFormat.MIMETYPE_AUDIO_AAC.equalsIgnoreCase(mime)) {
2834217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                Integer aacProfile = (Integer)map.get(MediaFormat.KEY_AAC_PROFILE);
2835217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (profile == null) {
2836217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    profile = aacProfile;
28375c5978985a3457539d1f3b611f23d26b77484536Andreas Gampe                } else if (aacProfile != null && !aacProfile.equals(profile)) {
2838217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    throw new IllegalArgumentException(
2839217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            "conflicting values for profile and aac-profile");
2840217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
2841217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
2842217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
2843217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            Integer quality = (Integer)map.get(MediaFormat.KEY_QUALITY);
2844217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
2845217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return supports(complexity, quality, profile);
2846b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
284760d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber    };
284860d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber
2849c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main    /**
2850c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main     * Encapsulates the profiles available for a codec component.
2851c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main     * <p>You can get a set of {@link MediaCodecInfo.CodecProfileLevel} objects for a given
2852c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main     * {@link MediaCodecInfo} object from the
2853c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main     * {@link MediaCodecInfo.CodecCapabilities#profileLevels} field.
2854c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main     */
285560d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber    public static final class CodecProfileLevel {
285660d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        // from OMX_VIDEO_AVCPROFILETYPE
285760d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCProfileBaseline = 0x01;
285860d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCProfileMain     = 0x02;
285960d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCProfileExtended = 0x04;
286060d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCProfileHigh     = 0x08;
286160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCProfileHigh10   = 0x10;
286260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCProfileHigh422  = 0x20;
286360d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCProfileHigh444  = 0x40;
286460d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber
286560d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        // from OMX_VIDEO_AVCLEVELTYPE
286660d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCLevel1       = 0x01;
286760d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCLevel1b      = 0x02;
286860d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCLevel11      = 0x04;
286960d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCLevel12      = 0x08;
287060d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCLevel13      = 0x10;
287160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCLevel2       = 0x20;
287260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCLevel21      = 0x40;
287360d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCLevel22      = 0x80;
287460d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCLevel3       = 0x100;
287560d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCLevel31      = 0x200;
287660d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCLevel32      = 0x400;
287760d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCLevel4       = 0x800;
287860d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCLevel41      = 0x1000;
287960d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCLevel42      = 0x2000;
288060d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCLevel5       = 0x4000;
288160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCLevel51      = 0x8000;
2882b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int AVCLevel52      = 0x10000;
288360d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber
288460d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        // from OMX_VIDEO_H263PROFILETYPE
288560d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int H263ProfileBaseline             = 0x01;
288660d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int H263ProfileH320Coding           = 0x02;
288760d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int H263ProfileBackwardCompatible   = 0x04;
288860d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int H263ProfileISWV2                = 0x08;
288960d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int H263ProfileISWV3                = 0x10;
289060d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int H263ProfileHighCompression      = 0x20;
289160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int H263ProfileInternet             = 0x40;
289260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int H263ProfileInterlace            = 0x80;
289360d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int H263ProfileHighLatency          = 0x100;
289460d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber
289560d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        // from OMX_VIDEO_H263LEVELTYPE
289660d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int H263Level10      = 0x01;
289760d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int H263Level20      = 0x02;
289860d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int H263Level30      = 0x04;
289960d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int H263Level40      = 0x08;
290060d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int H263Level45      = 0x10;
290160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int H263Level50      = 0x20;
290260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int H263Level60      = 0x40;
290360d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int H263Level70      = 0x80;
290460d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber
290560d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        // from OMX_VIDEO_MPEG4PROFILETYPE
290660d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4ProfileSimple              = 0x01;
290760d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4ProfileSimpleScalable      = 0x02;
290860d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4ProfileCore                = 0x04;
290960d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4ProfileMain                = 0x08;
291060d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4ProfileNbit                = 0x10;
291160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4ProfileScalableTexture     = 0x20;
291260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4ProfileSimpleFace          = 0x40;
291360d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4ProfileSimpleFBA           = 0x80;
291460d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4ProfileBasicAnimated       = 0x100;
291560d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4ProfileHybrid              = 0x200;
291660d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4ProfileAdvancedRealTime    = 0x400;
291760d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4ProfileCoreScalable        = 0x800;
291860d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4ProfileAdvancedCoding      = 0x1000;
291960d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4ProfileAdvancedCore        = 0x2000;
292060d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4ProfileAdvancedScalable    = 0x4000;
292160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4ProfileAdvancedSimple      = 0x8000;
292260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber
292360d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        // from OMX_VIDEO_MPEG4LEVELTYPE
292460d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4Level0      = 0x01;
292560d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4Level0b     = 0x02;
292660d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4Level1      = 0x04;
292760d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4Level2      = 0x08;
292860d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4Level3      = 0x10;
29292a4001ee62f3374d7fffed72d71f77c5a833c331Lajos Molnar        public static final int MPEG4Level3b     = 0x18;
293060d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4Level4      = 0x20;
293160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4Level4a     = 0x40;
293260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4Level5      = 0x80;
29332a4001ee62f3374d7fffed72d71f77c5a833c331Lajos Molnar        public static final int MPEG4Level6      = 0x100;
293460d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber
293534265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar        // from OMX_VIDEO_MPEG2PROFILETYPE
293634265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar        public static final int MPEG2ProfileSimple              = 0x00;
293734265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar        public static final int MPEG2ProfileMain                = 0x01;
293834265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar        public static final int MPEG2Profile422                 = 0x02;
293934265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar        public static final int MPEG2ProfileSNR                 = 0x03;
294034265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar        public static final int MPEG2ProfileSpatial             = 0x04;
294134265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar        public static final int MPEG2ProfileHigh                = 0x05;
294234265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar
294334265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar        // from OMX_VIDEO_MPEG2LEVELTYPE
294434265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar        public static final int MPEG2LevelLL     = 0x00;
294534265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar        public static final int MPEG2LevelML     = 0x01;
294634265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar        public static final int MPEG2LevelH14    = 0x02;
294734265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar        public static final int MPEG2LevelHL     = 0x03;
29482a4001ee62f3374d7fffed72d71f77c5a833c331Lajos Molnar        public static final int MPEG2LevelHP     = 0x04;
294934265cd94f76cc18648c310e4f120d280bf3a0a4Harish Mahendrakar
295060d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        // from OMX_AUDIO_AACPROFILETYPE
295160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AACObjectMain       = 1;
295260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AACObjectLC         = 2;
295360d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AACObjectSSR        = 3;
295460d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AACObjectLTP        = 4;
295560d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AACObjectHE         = 5;
295660d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AACObjectScalable   = 6;
295760d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AACObjectERLC       = 17;
29587c1cb0d5a5420823e63d59daf140844921407e29Jean-Michel Trivi        public static final int AACObjectERScalable = 20;
295960d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AACObjectLD         = 23;
296060d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AACObjectHE_PS      = 29;
296160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AACObjectELD        = 39;
296260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber
2963e72409fe779f620382c5bd0b82f4a32ac91d9fe4Kunter Gultekin        // from OMX_VIDEO_VP8LEVELTYPE
2964e72409fe779f620382c5bd0b82f4a32ac91d9fe4Kunter Gultekin        public static final int VP8Level_Version0 = 0x01;
2965e72409fe779f620382c5bd0b82f4a32ac91d9fe4Kunter Gultekin        public static final int VP8Level_Version1 = 0x02;
2966e72409fe779f620382c5bd0b82f4a32ac91d9fe4Kunter Gultekin        public static final int VP8Level_Version2 = 0x04;
2967e72409fe779f620382c5bd0b82f4a32ac91d9fe4Kunter Gultekin        public static final int VP8Level_Version3 = 0x08;
2968e72409fe779f620382c5bd0b82f4a32ac91d9fe4Kunter Gultekin
2969e72409fe779f620382c5bd0b82f4a32ac91d9fe4Kunter Gultekin        // from OMX_VIDEO_VP8PROFILETYPE
2970e72409fe779f620382c5bd0b82f4a32ac91d9fe4Kunter Gultekin        public static final int VP8ProfileMain = 0x01;
2971e72409fe779f620382c5bd0b82f4a32ac91d9fe4Kunter Gultekin
2972f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu        // from OMX_VIDEO_VP9PROFILETYPE
2973f0ef572fd0dfb8304db391e5643cd53b7625fd0aHangyu Kuang        public static final int VP9Profile0 = 0x01;
2974f0ef572fd0dfb8304db391e5643cd53b7625fd0aHangyu Kuang        public static final int VP9Profile1 = 0x02;
2975f0ef572fd0dfb8304db391e5643cd53b7625fd0aHangyu Kuang        public static final int VP9Profile2 = 0x04;
2976f0ef572fd0dfb8304db391e5643cd53b7625fd0aHangyu Kuang        public static final int VP9Profile3 = 0x08;
2977f0ef572fd0dfb8304db391e5643cd53b7625fd0aHangyu Kuang        // HDR profiles also support passing HDR metadata
2978f0ef572fd0dfb8304db391e5643cd53b7625fd0aHangyu Kuang        public static final int VP9Profile2HDR = 0x1000;
2979f0ef572fd0dfb8304db391e5643cd53b7625fd0aHangyu Kuang        public static final int VP9Profile3HDR = 0x2000;
2980f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu
2981f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu        // from OMX_VIDEO_VP9LEVELTYPE
29829186c38fceedd4e517d764216b4f71561f3baf97Hangyu Kuang        public static final int VP9Level1  = 0x1;
29839186c38fceedd4e517d764216b4f71561f3baf97Hangyu Kuang        public static final int VP9Level11 = 0x2;
29849186c38fceedd4e517d764216b4f71561f3baf97Hangyu Kuang        public static final int VP9Level2  = 0x4;
29859186c38fceedd4e517d764216b4f71561f3baf97Hangyu Kuang        public static final int VP9Level21 = 0x8;
29869186c38fceedd4e517d764216b4f71561f3baf97Hangyu Kuang        public static final int VP9Level3  = 0x10;
29879186c38fceedd4e517d764216b4f71561f3baf97Hangyu Kuang        public static final int VP9Level31 = 0x20;
29889186c38fceedd4e517d764216b4f71561f3baf97Hangyu Kuang        public static final int VP9Level4  = 0x40;
29899186c38fceedd4e517d764216b4f71561f3baf97Hangyu Kuang        public static final int VP9Level41 = 0x80;
29909186c38fceedd4e517d764216b4f71561f3baf97Hangyu Kuang        public static final int VP9Level5  = 0x100;
29919186c38fceedd4e517d764216b4f71561f3baf97Hangyu Kuang        public static final int VP9Level51 = 0x200;
29929186c38fceedd4e517d764216b4f71561f3baf97Hangyu Kuang        public static final int VP9Level52 = 0x400;
29939186c38fceedd4e517d764216b4f71561f3baf97Hangyu Kuang        public static final int VP9Level6  = 0x800;
29949186c38fceedd4e517d764216b4f71561f3baf97Hangyu Kuang        public static final int VP9Level61 = 0x1000;
29959186c38fceedd4e517d764216b4f71561f3baf97Hangyu Kuang        public static final int VP9Level62 = 0x2000;
2996f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu
2997aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        // from OMX_VIDEO_HEVCPROFILETYPE
2998f2615b8b339b812ad6b309d5ec116eb0add320f3Ronghua Wu        public static final int HEVCProfileMain        = 0x01;
2999f2615b8b339b812ad6b309d5ec116eb0add320f3Ronghua Wu        public static final int HEVCProfileMain10      = 0x02;
3000f2615b8b339b812ad6b309d5ec116eb0add320f3Ronghua Wu        public static final int HEVCProfileMain10HDR10 = 0x1000;
3001aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad
3002aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        // from OMX_VIDEO_HEVCLEVELTYPE
3003aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCMainTierLevel1  = 0x1;
3004aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCHighTierLevel1  = 0x2;
3005aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCMainTierLevel2  = 0x4;
3006aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCHighTierLevel2  = 0x8;
3007aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCMainTierLevel21 = 0x10;
3008aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCHighTierLevel21 = 0x20;
3009aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCMainTierLevel3  = 0x40;
3010aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCHighTierLevel3  = 0x80;
3011aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCMainTierLevel31 = 0x100;
3012aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCHighTierLevel31 = 0x200;
3013aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCMainTierLevel4  = 0x400;
3014aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCHighTierLevel4  = 0x800;
3015aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCMainTierLevel41 = 0x1000;
3016aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCHighTierLevel41 = 0x2000;
3017aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCMainTierLevel5  = 0x4000;
3018aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCHighTierLevel5  = 0x8000;
3019aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCMainTierLevel51 = 0x10000;
3020aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCHighTierLevel51 = 0x20000;
3021aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCMainTierLevel52 = 0x40000;
3022aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCHighTierLevel52 = 0x80000;
3023aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCMainTierLevel6  = 0x100000;
3024aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCHighTierLevel6  = 0x200000;
3025aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCMainTierLevel61 = 0x400000;
3026aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCHighTierLevel61 = 0x800000;
3027aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCMainTierLevel62 = 0x1000000;
3028aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCHighTierLevel62 = 0x2000000;
3029e72409fe779f620382c5bd0b82f4a32ac91d9fe4Kunter Gultekin
30302fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar        private static final int HEVCHighTierLevels =
30312fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar            HEVCHighTierLevel1 | HEVCHighTierLevel2 | HEVCHighTierLevel21 | HEVCHighTierLevel3 |
30322fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar            HEVCHighTierLevel31 | HEVCHighTierLevel4 | HEVCHighTierLevel41 | HEVCHighTierLevel5 |
30332fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar            HEVCHighTierLevel51 | HEVCHighTierLevel52 | HEVCHighTierLevel6 | HEVCHighTierLevel61 |
30342fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar            HEVCHighTierLevel62;
30352fc9c6925a51b18452e8080d5ac2d50babd0c866Lajos Molnar
3036d6c2a76dcf8160e56846be1e82893f0c89527582Ronghua Wu        // from OMX_VIDEO_DOLBYVISIONPROFILETYPE
303732e537c610b66ca975e6d9e4cf5dadb4a7cb62d3Ronghua Wu        public static final int DolbyVisionProfileDvavPer = 0x1;
303832e537c610b66ca975e6d9e4cf5dadb4a7cb62d3Ronghua Wu        public static final int DolbyVisionProfileDvavPen = 0x2;
303932e537c610b66ca975e6d9e4cf5dadb4a7cb62d3Ronghua Wu        public static final int DolbyVisionProfileDvheDer = 0x4;
304032e537c610b66ca975e6d9e4cf5dadb4a7cb62d3Ronghua Wu        public static final int DolbyVisionProfileDvheDen = 0x8;
304132e537c610b66ca975e6d9e4cf5dadb4a7cb62d3Ronghua Wu        public static final int DolbyVisionProfileDvheDtr = 0x10;
304232e537c610b66ca975e6d9e4cf5dadb4a7cb62d3Ronghua Wu        public static final int DolbyVisionProfileDvheStn = 0x20;
304332e537c610b66ca975e6d9e4cf5dadb4a7cb62d3Ronghua Wu        public static final int DolbyVisionProfileDvheDth = 0x40;
3044f939e4adf1b3c6f9d7d26def48503654801f700dHangyu Kuang        public static final int DolbyVisionProfileDvheDtb = 0x80;
3045d6c2a76dcf8160e56846be1e82893f0c89527582Ronghua Wu
3046d6c2a76dcf8160e56846be1e82893f0c89527582Ronghua Wu        // from OMX_VIDEO_DOLBYVISIONLEVELTYPE
3047d6c2a76dcf8160e56846be1e82893f0c89527582Ronghua Wu        public static final int DolbyVisionLevelHd24    = 0x1;
3048d6c2a76dcf8160e56846be1e82893f0c89527582Ronghua Wu        public static final int DolbyVisionLevelHd30    = 0x2;
3049d6c2a76dcf8160e56846be1e82893f0c89527582Ronghua Wu        public static final int DolbyVisionLevelFhd24   = 0x4;
3050d6c2a76dcf8160e56846be1e82893f0c89527582Ronghua Wu        public static final int DolbyVisionLevelFhd30   = 0x8;
3051d6c2a76dcf8160e56846be1e82893f0c89527582Ronghua Wu        public static final int DolbyVisionLevelFhd60   = 0x10;
3052d6c2a76dcf8160e56846be1e82893f0c89527582Ronghua Wu        public static final int DolbyVisionLevelUhd24   = 0x20;
3053d6c2a76dcf8160e56846be1e82893f0c89527582Ronghua Wu        public static final int DolbyVisionLevelUhd30   = 0x40;
3054d6c2a76dcf8160e56846be1e82893f0c89527582Ronghua Wu        public static final int DolbyVisionLevelUhd48   = 0x80;
3055d6c2a76dcf8160e56846be1e82893f0c89527582Ronghua Wu        public static final int DolbyVisionLevelUhd60   = 0x100;
3056d6c2a76dcf8160e56846be1e82893f0c89527582Ronghua Wu
305760d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        /**
305860d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber         * Defined in the OpenMAX IL specs, depending on the type of media
305960d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber         * this can be OMX_VIDEO_AVCPROFILETYPE, OMX_VIDEO_H263PROFILETYPE,
3060f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu         * OMX_VIDEO_MPEG4PROFILETYPE, OMX_VIDEO_VP8PROFILETYPE or OMX_VIDEO_VP9PROFILETYPE.
306160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber         */
306260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public int profile;
306360d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber
306460d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        /**
306560d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber         * Defined in the OpenMAX IL specs, depending on the type of media
306660d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber         * this can be OMX_VIDEO_AVCLEVELTYPE, OMX_VIDEO_H263LEVELTYPE
3067f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu         * OMX_VIDEO_MPEG4LEVELTYPE, OMX_VIDEO_VP8LEVELTYPE or OMX_VIDEO_VP9LEVELTYPE.
3068f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu         *
3069f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu         * Note that VP9 decoder on platforms before {@link android.os.Build.VERSION_CODES#N} may
3070f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu         * not advertise a profile level support. For those VP9 decoders, please use
3071f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu         * {@link VideoCapabilities} to determine the codec capabilities.
307260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber         */
307360d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public int level;
307460d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber    };
307560d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber
3076ba9269a5855b6d9d581af09077caafbd45180b41Andreas Huber    /**
3077ba9269a5855b6d9d581af09077caafbd45180b41Andreas Huber     * Enumerates the capabilities of the codec component. Since a single
3078ba9269a5855b6d9d581af09077caafbd45180b41Andreas Huber     * component can support data of a variety of types, the type has to be
3079ba9269a5855b6d9d581af09077caafbd45180b41Andreas Huber     * specified to yield a meaningful result.
3080c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main     * @param type The MIME type to query
3081ba9269a5855b6d9d581af09077caafbd45180b41Andreas Huber     */
308260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber    public final CodecCapabilities getCapabilitiesForType(
308360d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber            String type) {
3084b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        CodecCapabilities caps = mCaps.get(type);
3085b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        if (caps == null) {
3086b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            throw new IllegalArgumentException("codec does not support type");
3087b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
3088b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        // clone writable object
3089b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        return caps.dup();
3090b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    }
3091b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
3092b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    /** @hide */
3093b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    public MediaCodecInfo makeRegular() {
3094b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        ArrayList<CodecCapabilities> caps = new ArrayList<CodecCapabilities>();
3095b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        for (CodecCapabilities c: mCaps.values()) {
3096b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            if (c.isRegular()) {
3097b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                caps.add(c);
3098b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
3099b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
3100b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        if (caps.size() == 0) {
3101b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            return null;
3102b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        } else if (caps.size() == mCaps.size()) {
3103b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            return this;
3104b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
3105b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
3106b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        return new MediaCodecInfo(
3107b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                mName, mIsEncoder,
3108b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                caps.toArray(new CodecCapabilities[caps.size()]));
310960d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber    }
311060d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber}
3111