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
19b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnarimport android.util.Log;
20b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnarimport android.util.Pair;
21b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnarimport android.util.Range;
22b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnarimport android.util.Rational;
23b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnarimport android.util.Size;
24b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
25b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnarimport java.util.ArrayList;
26b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnarimport java.util.Arrays;
27b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnarimport java.util.Comparator;
28b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnarimport java.util.HashMap;
29b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnarimport java.util.Map;
30b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnarimport java.util.Set;
31b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
32b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnarimport static android.media.Utils.intersectSortedDistinctRanges;
33b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnarimport static android.media.Utils.sortDistinctRanges;
34b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnarimport static com.android.internal.util.Preconditions.checkArgumentPositive;
35b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnarimport static com.android.internal.util.Preconditions.checkNotNull;
36b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
37c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main/**
38c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main * Provides information about a given media codec available on the device. You can
39c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main * iterate through all codecs available by querying {@link MediaCodecList}. For example,
40c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main * here's how to find an encoder that supports a given MIME type:
41c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main * <pre>
42c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main * private static MediaCodecInfo selectCodec(String mimeType) {
43c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main *     int numCodecs = MediaCodecList.getCodecCount();
44c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main *     for (int i = 0; i &lt; numCodecs; i++) {
45c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main *         MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
46c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main *
47c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main *         if (!codecInfo.isEncoder()) {
48c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main *             continue;
49c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main *         }
50c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main *
51c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main *         String[] types = codecInfo.getSupportedTypes();
52c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main *         for (int j = 0; j &lt; types.length; j++) {
53c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main *             if (types[j].equalsIgnoreCase(mimeType)) {
54c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main *                 return codecInfo;
55c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main *             }
56c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main *         }
57c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main *     }
58c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main *     return null;
59c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main * }</pre>
60c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main *
61c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main */
6260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huberpublic final class MediaCodecInfo {
63b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    private boolean mIsEncoder;
64b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    private String mName;
65b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    private Map<String, CodecCapabilities> mCaps;
6660d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber
67b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    /* package private */ MediaCodecInfo(
68b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            String name, boolean isEncoder, CodecCapabilities[] caps) {
69b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        mName = name;
70b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        mIsEncoder = isEncoder;
71b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        mCaps = new HashMap<String, CodecCapabilities>();
72b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        for (CodecCapabilities c: caps) {
73217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mCaps.put(c.getMimeType(), c);
74b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
7560d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber    }
7660d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber
7760d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber    /**
7860d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber     * Retrieve the codec name.
7960d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber     */
8060d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber    public final String getName() {
81b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        return mName;
8260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber    }
8360d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber
8460d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber    /**
8560d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber     * Query if the codec is an encoder.
8660d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber     */
8760d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber    public final boolean isEncoder() {
88b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        return mIsEncoder;
8960d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber    }
9060d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber
9160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber    /**
9260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber     * Query the media types supported by the codec.
9360d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber     */
9460d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber    public final String[] getSupportedTypes() {
95b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        Set<String> typeSet = mCaps.keySet();
96b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        String[] types = typeSet.toArray(new String[typeSet.size()]);
97b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        Arrays.sort(types);
98b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        return types;
9960d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber    }
10060d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber
101217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    private static int checkPowerOfTwo(int value, String message) {
102217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        if ((value & (value - 1)) != 0) {
103217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            throw new IllegalArgumentException(message);
104217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
105217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        return value;
106217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    }
107217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
108217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    private static class Feature {
109217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public String mName;
110217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public int mValue;
111217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public boolean mDefault;
112217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public Feature(String name, int value, boolean def) {
113217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mName = name;
114217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mValue = value;
115217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mDefault = def;
116217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
117217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    }
118217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
119217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    // COMMON CONSTANTS
120217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    private static final Range<Integer> POSITIVE_INTEGERS =
121217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        Range.create(1, Integer.MAX_VALUE);
122217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    private static final Range<Long> POSITIVE_LONGS =
123217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        Range.create(1l, Long.MAX_VALUE);
124217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    private static final Range<Rational> POSITIVE_RATIONALS =
125217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        Range.create(new Rational(1, Integer.MAX_VALUE),
126217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                     new Rational(Integer.MAX_VALUE, 1));
127217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    private static final Range<Integer> SIZE_RANGE = Range.create(1, 32768);
128217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    private static final Range<Integer> FRAME_RATE_RANGE = Range.create(0, 960);
129216e11dcbb4d56699c1740c801489be0d57b16c4Chong Zhang    private static final Range<Integer> BITRATE_RANGE = Range.create(0, 500000000);
130217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
131217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    // found stuff that is not supported by framework (=> this should not happen)
132217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    private static final int ERROR_UNRECOGNIZED   = (1 << 0);
133217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    // found profile/level for which we don't have capability estimates
134217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    private static final int ERROR_UNSUPPORTED    = (1 << 1);
135217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    // have not found any profile/level for which we don't have capability estimate
136217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    private static final int ERROR_NONE_SUPPORTED = (1 << 2);
137217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
138217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
139ba9269a5855b6d9d581af09077caafbd45180b41Andreas Huber    /**
140c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main     * Encapsulates the capabilities of a given codec component.
141c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main     * For example, what profile/level combinations it supports and what colorspaces
14280c4437ebfe3e679267a64e4c9d7bdd585b7afceLajos Molnar     * it is capable of providing the decoded data in, as well as some
14380c4437ebfe3e679267a64e4c9d7bdd585b7afceLajos Molnar     * codec-type specific capability flags.
144c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main     * <p>You can get an instance for a given {@link MediaCodecInfo} object with
145c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main     * {@link MediaCodecInfo#getCapabilitiesForType getCapabilitiesForType()}, passing a MIME type.
146ba9269a5855b6d9d581af09077caafbd45180b41Andreas Huber     */
14760d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber    public static final class CodecCapabilities {
148b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public CodecCapabilities() {
149b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
150b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
151b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        // CLASSIFICATION
152b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        private String mMime;
153b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
154b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        // LEGACY FIELDS
155b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
156ba9269a5855b6d9d581af09077caafbd45180b41Andreas Huber        // Enumerates supported profile/level combinations as defined
157ba9269a5855b6d9d581af09077caafbd45180b41Andreas Huber        // by the type of encoded data. These combinations impose restrictions
158ba9269a5855b6d9d581af09077caafbd45180b41Andreas Huber        // on video resolution, bitrate... and limit the available encoder tools
159ba9269a5855b6d9d581af09077caafbd45180b41Andreas Huber        // such as B-frame support, arithmetic coding...
160b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public CodecProfileLevel[] profileLevels;  // NOTE this array is modifiable by user
16160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber
16260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        // from OMX_COLOR_FORMATTYPE
163b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatMonochrome              = 1;
164b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_Format8bitRGB332              = 2;
165b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_Format12bitRGB444             = 3;
166b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_Format16bitARGB4444           = 4;
167b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_Format16bitARGB1555           = 5;
168b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_Format16bitRGB565             = 6;
169b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_Format16bitBGR565             = 7;
170b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_Format18bitRGB666             = 8;
171b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_Format18bitARGB1665           = 9;
172b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_Format19bitARGB1666           = 10;
173b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_Format24bitRGB888             = 11;
174b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_Format24bitBGR888             = 12;
175b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_Format24bitARGB1887           = 13;
176b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_Format25bitARGB1888           = 14;
177b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_Format32bitBGRA8888           = 15;
178b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_Format32bitARGB8888           = 16;
179b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatYUV411Planar            = 17;
180b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatYUV411PackedPlanar      = 18;
181b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatYUV420Planar            = 19;
182b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatYUV420PackedPlanar      = 20;
183b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatYUV420SemiPlanar        = 21;
184b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatYUV422Planar            = 22;
185b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatYUV422PackedPlanar      = 23;
186b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatYUV422SemiPlanar        = 24;
187b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatYCbYCr                  = 25;
188b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatYCrYCb                  = 26;
189b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatCbYCrY                  = 27;
190b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatCrYCbY                  = 28;
191b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatYUV444Interleaved       = 29;
192b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatRawBayer8bit            = 30;
193b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatRawBayer10bit           = 31;
194b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatRawBayer8bitcompressed  = 32;
195b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatL2                      = 33;
196b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatL4                      = 34;
197b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatL8                      = 35;
198b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatL16                     = 36;
199b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatL24                     = 37;
200b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatL32                     = 38;
201b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatYUV420PackedSemiPlanar  = 39;
202b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatYUV422PackedSemiPlanar  = 40;
203b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_Format18BitBGR666             = 41;
204b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_Format24BitARGB6666           = 42;
205b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_Format24BitABGR6666           = 43;
206b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
207b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_TI_FormatYUV420PackedSemiPlanar = 0x7f000100;
20834f17dd1f615c6285f4f344eb700923e2432e48eAndy McFadden        // COLOR_FormatSurface indicates that the data will be a GraphicBuffer metadata reference.
20934f17dd1f615c6285f4f344eb700923e2432e48eAndy McFadden        // In OMX this is called OMX_COLOR_FormatAndroidOpaque.
210b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatSurface                   = 0x7F000789;
211b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        // This corresponds to YUV_420_888 format
212b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_FormatYUV420Flexible            = 0x7F420888;
213b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int COLOR_QCOM_FormatYUV420SemiPlanar     = 0x7fa30c00;
21460d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber
21560d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        /**
21660d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber         * Defined in the OpenMAX IL specs, color format values are drawn from
21760d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber         * OMX_COLOR_FORMATTYPE.
21860d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber         */
219b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public int[] colorFormats; // NOTE this array is modifiable by user
22080c4437ebfe3e679267a64e4c9d7bdd585b7afceLajos Molnar
221b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        // FEATURES
222b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
223b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        private int mFlagsSupported;
224b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        private int mFlagsRequired;
225b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        private int mFlagsVerified;
22680c4437ebfe3e679267a64e4c9d7bdd585b7afceLajos Molnar
22780c4437ebfe3e679267a64e4c9d7bdd585b7afceLajos Molnar        /**
22880c4437ebfe3e679267a64e4c9d7bdd585b7afceLajos Molnar         * <b>video decoder only</b>: codec supports seamless resolution changes.
22980c4437ebfe3e679267a64e4c9d7bdd585b7afceLajos Molnar         */
230b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final String FEATURE_AdaptivePlayback       = "adaptive-playback";
231b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
232b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        /**
233b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         * <b>video decoder only</b>: codec supports secure decryption.
234b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         */
235b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final String FEATURE_SecurePlayback         = "secure-playback";
236b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
237b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        /**
238b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         * <b>video or audio decoder only</b>: codec supports tunneled playback.
239b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         */
240b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final String FEATURE_TunneledPlayback       = "tunneled-playback";
24180c4437ebfe3e679267a64e4c9d7bdd585b7afceLajos Molnar
24280c4437ebfe3e679267a64e4c9d7bdd585b7afceLajos Molnar        /**
24380c4437ebfe3e679267a64e4c9d7bdd585b7afceLajos Molnar         * Query codec feature capabilities.
244b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         * <p>
245b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         * These features are supported to be used by the codec.  These
246b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         * include optional features that can be turned on, as well as
247b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         * features that are always on.
24880c4437ebfe3e679267a64e4c9d7bdd585b7afceLajos Molnar         */
24980c4437ebfe3e679267a64e4c9d7bdd585b7afceLajos Molnar        public final boolean isFeatureSupported(String name) {
250b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            return checkFeature(name, mFlagsSupported);
251b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
252b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
253b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        /**
254b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         * Query codec feature requirements.
255b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         * <p>
256b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         * These features are required to be used by the codec, and as such,
257b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         * they are always turned on.
258b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         */
259b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public final boolean isFeatureRequired(String name) {
260b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            return checkFeature(name, mFlagsRequired);
261b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
262b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
263b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        private static final Feature[] decoderFeatures = {
264b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            new Feature(FEATURE_AdaptivePlayback, (1 << 0), true),
265b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            new Feature(FEATURE_SecurePlayback,   (1 << 1), false),
266b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            new Feature(FEATURE_TunneledPlayback, (1 << 2), false),
267b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        };
268b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
269b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        /** @hide */
270b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public String[] validFeatures() {
271b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            Feature[] features = getValidFeatures();
272b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            String[] res = new String[features.length];
273b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            for (int i = 0; i < res.length; i++) {
274b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                res[i] = features[i].mName;
275b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
276b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            return res;
277b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
278b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
279b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        private Feature[] getValidFeatures() {
280b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            if (!isEncoder()) {
281b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                return decoderFeatures;
282b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
283b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            return new Feature[] {};
284b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
285b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
286b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        private boolean checkFeature(String name, int flags) {
287b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            for (Feature feat: getValidFeatures()) {
288b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                if (feat.mName.equals(name)) {
289b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                    return (flags & feat.mValue) != 0;
290b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                }
29180c4437ebfe3e679267a64e4c9d7bdd585b7afceLajos Molnar            }
29280c4437ebfe3e679267a64e4c9d7bdd585b7afceLajos Molnar            return false;
29380c4437ebfe3e679267a64e4c9d7bdd585b7afceLajos Molnar        }
294b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
295b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        /** @hide */
296b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public boolean isRegular() {
297b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            // regular codecs only require default features
298b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            for (Feature feat: getValidFeatures()) {
299b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                if (!feat.mDefault && isFeatureRequired(feat.mName)) {
300b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                    return false;
301b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                }
302b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
303b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            return true;
304b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
305b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
306b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        /**
307b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         * Query whether codec supports a given {@link MediaFormat}.
308b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         * @param format media format with optional feature directives.
309b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         * @throws IllegalArgumentException if format is not a valid media format.
310b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         * @return whether the codec capabilities support the given format
311b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         *         and feature requests.
312b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         */
313b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public final boolean isFormatSupported(MediaFormat format) {
314b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            final Map<String, Object> map = format.getMap();
315b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            final String mime = (String)map.get(MediaFormat.KEY_MIME);
316b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
317b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            // mime must match if present
318b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            if (mime != null && !mMime.equalsIgnoreCase(mime)) {
319b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                return false;
320b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
321b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
322b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            // check feature support
323b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            for (Feature feat: getValidFeatures()) {
324b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                Integer yesNo = (Integer)map.get(MediaFormat.KEY_FEATURE_ + feat.mName);
325dbf1552d526e62859e7a40cfea8e68b614a7d413Lajos Molnar                if (yesNo == null) {
326dbf1552d526e62859e7a40cfea8e68b614a7d413Lajos Molnar                    continue;
327dbf1552d526e62859e7a40cfea8e68b614a7d413Lajos Molnar                }
328b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                if ((yesNo == 1 && !isFeatureSupported(feat.mName)) ||
329b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                        (yesNo == 0 && isFeatureRequired(feat.mName))) {
330b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                    return false;
331b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                }
332b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
333b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            if (mAudioCaps != null && !mAudioCaps.supportsFormat(format)) {
334b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                return false;
335b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
336b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            if (mVideoCaps != null && !mVideoCaps.supportsFormat(format)) {
337b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                return false;
338b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
339b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            if (mEncoderCaps != null && !mEncoderCaps.supportsFormat(format)) {
340b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                return false;
341b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
342b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            return true;
343b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
344b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
345217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        // errors while reading profile levels - accessed from sister capabilities
346217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        int mError;
347b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
348b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        private static final String TAG = "CodecCapabilities";
349b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
350b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        // NEW-STYLE CAPABILITIES
351217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private AudioCapabilities mAudioCaps;
352217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private VideoCapabilities mVideoCaps;
353217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private EncoderCapabilities mEncoderCaps;
354217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private MediaFormat mDefaultFormat;
355b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
356b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        /**
357b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         * Returns a MediaFormat object with default values for configurations that have
358b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         * defaults.
359b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         */
360217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public MediaFormat getDefaultFormat() {
361b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            return mDefaultFormat;
362b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
363b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
364b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        /**
365b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         * Returns the mime type for which this codec-capability object was created.
366b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         */
367217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public String getMimeType() {
368b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            return mMime;
369b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
370b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
371217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private boolean isAudio() {
372217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return mAudioCaps != null;
373217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
374217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
375b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        /**
376217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Returns the audio capabilities or {@code null} if this is not an audio codec.
377b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         */
378217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public AudioCapabilities getAudioCapabilities() {
379217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return mAudioCaps;
380b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
381b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
382b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        private boolean isEncoder() {
383b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            return mEncoderCaps != null;
384b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
385b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
386b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        /**
387217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Returns the encoding capabilities or {@code null} if this is not an encoder.
388b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         */
389217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public EncoderCapabilities getEncoderCapabilities() {
390217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return mEncoderCaps;
391b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
392b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
393b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        private boolean isVideo() {
394b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            return mVideoCaps != null;
395b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
396b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
397b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        /**
398b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         * Returns the video capabilities or {@code null} if this is not a video codec.
399b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         */
400217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public VideoCapabilities getVideoCapabilities() {
401b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            return mVideoCaps;
402b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
403b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
404217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /** @hide */
405217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public CodecCapabilities dup() {
406217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return new CodecCapabilities(
407217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                // clone writable arrays
408217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                Arrays.copyOf(profileLevels, profileLevels.length),
409217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                Arrays.copyOf(colorFormats, colorFormats.length),
410217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                isEncoder(),
411217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                mFlagsVerified,
412217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                mDefaultFormat,
413217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                mCapabilitiesInfo);
414217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
415217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
416b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        /**
417b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         * Retrieve the codec capabilities for a certain {@code mime type}, {@code
418b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         * profile} and {@code level}.  If the type, or profile-level combination
419b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         * is not understood by the framework, it returns null.
420b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         */
421a18b69f5907ef27b9954dfcbe8f60d29fcec2be7Lajos Molnar        public static CodecCapabilities createFromProfileLevel(
422b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                String mime, int profile, int level) {
423b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            CodecProfileLevel pl = new CodecProfileLevel();
424b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            pl.profile = profile;
425b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            pl.level = level;
426b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            MediaFormat defaultFormat = new MediaFormat();
427b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            defaultFormat.setString(MediaFormat.KEY_MIME, mime);
428b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
429b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            CodecCapabilities ret = new CodecCapabilities(
430b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                new CodecProfileLevel[] { pl }, new int[0], true /* encoder */,
431b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                0 /* flags */, defaultFormat, new MediaFormat() /* info */);
432b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            if (ret.mError != 0) {
433b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                return null;
434b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
435b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            return ret;
436b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
437b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
438b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        /* package private */ CodecCapabilities(
439b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                CodecProfileLevel[] profLevs, int[] colFmts,
440b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                boolean encoder, int flags,
441b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                Map<String, Object>defaultFormatMap,
442b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                Map<String, Object>capabilitiesMap) {
443b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            this(profLevs, colFmts, encoder, flags,
444b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                    new MediaFormat(defaultFormatMap),
445b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                    new MediaFormat(capabilitiesMap));
446b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
447b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
448b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        private MediaFormat mCapabilitiesInfo;
449b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
450b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        /* package private */ CodecCapabilities(
451b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                CodecProfileLevel[] profLevs, int[] colFmts, boolean encoder, int flags,
452b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                MediaFormat defaultFormat, MediaFormat info) {
453b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            final Map<String, Object> map = info.getMap();
454b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            profileLevels = profLevs;
455b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            colorFormats = colFmts;
456b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            mFlagsVerified = flags;
457b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            mDefaultFormat = defaultFormat;
458b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            mCapabilitiesInfo = info;
459b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            mMime = mDefaultFormat.getString(MediaFormat.KEY_MIME);
460b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
461b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            if (mMime.toLowerCase().startsWith("audio/")) {
462b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                mAudioCaps = AudioCapabilities.create(info, this);
463981c344ee7a4472e2a331d66819c132267a681c6Lajos Molnar                mAudioCaps.setDefaultFormat(mDefaultFormat);
464b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            } else if (mMime.toLowerCase().startsWith("video/")) {
465b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                mVideoCaps = VideoCapabilities.create(info, this);
466b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
467b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            if (encoder) {
468b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                mEncoderCaps = EncoderCapabilities.create(info, this);
469981c344ee7a4472e2a331d66819c132267a681c6Lajos Molnar                mEncoderCaps.setDefaultFormat(mDefaultFormat);
470b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
471b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
472b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            for (Feature feat: getValidFeatures()) {
473981c344ee7a4472e2a331d66819c132267a681c6Lajos Molnar                String key = MediaFormat.KEY_FEATURE_ + feat.mName;
474981c344ee7a4472e2a331d66819c132267a681c6Lajos Molnar                Integer yesNo = (Integer)map.get(key);
475b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                if (yesNo == null) {
476b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                    continue;
477dbf1552d526e62859e7a40cfea8e68b614a7d413Lajos Molnar                }
478dbf1552d526e62859e7a40cfea8e68b614a7d413Lajos Molnar                if (yesNo > 0) {
479b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                    mFlagsRequired |= feat.mValue;
480b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                }
481dbf1552d526e62859e7a40cfea8e68b614a7d413Lajos Molnar                mFlagsSupported |= feat.mValue;
482dbf1552d526e62859e7a40cfea8e68b614a7d413Lajos Molnar                mDefaultFormat.setInteger(key, 1);
483b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                // TODO restrict features by mFlagsVerified once all codecs reliably verify them
484b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
485b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
486217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    }
487b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
488217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    /**
489217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar     * A class that supports querying the audio capabilities of a codec.
490217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar     */
491217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    public static final class AudioCapabilities {
492217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private static final String TAG = "AudioCapabilities";
493217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private CodecCapabilities mParent;
494217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private Range<Integer> mBitrateRange;
495217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
496217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private int[] mSampleRates;
497217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private Range<Integer>[] mSampleRateRanges;
498217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private int mMaxInputChannelCount;
499217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
500217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private static final int MAX_INPUT_CHANNEL_COUNT = 30;
501217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
502217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /**
503217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Returns the range of supported bitrates in bits/second.
504217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         */
505217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public Range<Integer> getBitrateRange() {
506217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return mBitrateRange;
507217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
508217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
509217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /**
510217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Returns the array of supported sample rates if the codec
511217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * supports only discrete values.  Otherwise, it returns
512217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * {@code null}.  The array is sorted in ascending order.
513217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         */
514217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public int[] getSupportedSampleRates() {
515217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return Arrays.copyOf(mSampleRates, mSampleRates.length);
516217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
517217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
518217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /**
519217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Returns the array of supported sample rate ranges.  The
520217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * array is sorted in ascending order, and the ranges are
521217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * distinct.
522217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         */
523217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public Range<Integer>[] getSupportedSampleRateRanges() {
524217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return Arrays.copyOf(mSampleRateRanges, mSampleRateRanges.length);
525217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
526217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
527217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /**
528217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Returns the maximum number of input channels supported.  The codec
529217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * supports any number of channels between 1 and this maximum value.
530217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         */
531217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public int getMaxInputChannelCount() {
532217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return mMaxInputChannelCount;
533217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
534b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
535217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /* no public constructor */
536217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private AudioCapabilities() { }
537217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
538217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /** @hide */
539217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public static AudioCapabilities create(
540217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                MediaFormat info, CodecCapabilities parent) {
541217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            AudioCapabilities caps = new AudioCapabilities();
542217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            caps.init(info, parent);
543217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return caps;
544217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
545217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
546217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /** @hide */
547217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public void init(MediaFormat info, CodecCapabilities parent) {
548217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mParent = parent;
549217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            initWithPlatformLimits();
550217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            applyLevelLimits();
551217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            parseFromInfo(info);
552217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
553217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
554217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private void initWithPlatformLimits() {
555217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mBitrateRange = Range.create(0, Integer.MAX_VALUE);
556217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mMaxInputChannelCount = MAX_INPUT_CHANNEL_COUNT;
557217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // mBitrateRange = Range.create(1, 320000);
558217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mSampleRateRanges = new Range[] { Range.create(8000, 96000) };
559217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mSampleRates = null;
560217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
561217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
562217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private boolean supports(Integer sampleRate, Integer inputChannels) {
563217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // channels and sample rates are checked orthogonally
564217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (inputChannels != null &&
565217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    (inputChannels < 1 || inputChannels > mMaxInputChannelCount)) {
566217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                return false;
567b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
568217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (sampleRate != null) {
569217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                int ix = Utils.binarySearchDistinctRanges(
570217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        mSampleRateRanges, sampleRate);
571217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (ix < 0) {
572217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    return false;
573217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
574217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
575217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return true;
576217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
577b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
578217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /**
579217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Query whether the sample rate is supported by the codec.
580217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         */
581217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public boolean isSampleRateSupported(int sampleRate) {
582217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return supports(sampleRate, null);
583217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
584217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
585217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /** modifies rates */
586217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private void limitSampleRates(int[] rates) {
587217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            Arrays.sort(rates);
588217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            ArrayList<Range<Integer>> ranges = new ArrayList<Range<Integer>>();
589217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            for (int rate: rates) {
590217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (supports(rate, null /* channels */)) {
591217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    ranges.add(Range.create(rate, rate));
592217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
593b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
594217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mSampleRateRanges = ranges.toArray(new Range[ranges.size()]);
595217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            createDiscreteSampleRates();
596217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
597b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
598217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private void createDiscreteSampleRates() {
599217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mSampleRates = new int[mSampleRateRanges.length];
600217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            for (int i = 0; i < mSampleRateRanges.length; i++) {
601217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                mSampleRates[i] = mSampleRateRanges[i].getLower();
602217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
603217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
604b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
605217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /** modifies rateRanges */
606217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private void limitSampleRates(Range<Integer>[] rateRanges) {
607217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            sortDistinctRanges(rateRanges);
608217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mSampleRateRanges = intersectSortedDistinctRanges(mSampleRateRanges, rateRanges);
609217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
610217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // check if all values are discrete
611217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            for (Range<Integer> range: mSampleRateRanges) {
612217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (!range.getLower().equals(range.getUpper())) {
613217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mSampleRates = null;
614217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    return;
615217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
616b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
617217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            createDiscreteSampleRates();
618217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
619217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
620217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private void applyLevelLimits() {
621217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            int[] sampleRates = null;
622217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            Range<Integer> sampleRateRange = null, bitRates = null;
623217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            int maxChannels = 0;
624217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            String mime = mParent.getMimeType();
625217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
626217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_MPEG)) {
627217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                sampleRates = new int[] {
628217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        8000, 11025, 12000,
629217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        16000, 22050, 24000,
630217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        32000, 44100, 48000 };
631217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                bitRates = Range.create(8000, 320000);
632217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxChannels = 2;
633217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AMR_NB)) {
634217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                sampleRates = new int[] { 8000 };
635217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                bitRates = Range.create(4750, 12200);
636217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxChannels = 1;
637217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AMR_WB)) {
638217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                sampleRates = new int[] { 16000 };
639217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                bitRates = Range.create(6600, 23850);
640217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxChannels = 1;
641217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AAC)) {
642217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                sampleRates = new int[] {
643217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        7350, 8000,
644217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        11025, 12000, 16000,
645217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        22050, 24000, 32000,
646217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        44100, 48000, 64000,
647217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        88200, 96000 };
648217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                bitRates = Range.create(8000, 510000);
649217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxChannels = 48;
650217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_VORBIS)) {
651217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                bitRates = Range.create(32000, 500000);
652610e288de6727d9be3277777e6c5abca4b18aa86Lajos Molnar                sampleRateRange = Range.create(8000, 192000);
653217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxChannels = 255;
654217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_OPUS)) {
655217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                bitRates = Range.create(6000, 510000);
656217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                sampleRates = new int[] { 8000, 12000, 16000, 24000, 48000 };
657217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxChannels = 255;
658217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_RAW)) {
659217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                sampleRateRange = Range.create(1, 96000);
660217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                bitRates = Range.create(1, 10000000);
661217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxChannels = 8;
662217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_FLAC)) {
663217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                sampleRateRange = Range.create(1, 655350);
664217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                // lossless codec, so bitrate is ignored
665217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxChannels = 255;
666217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_G711_ALAW)
667217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    || mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_G711_MLAW)) {
668217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                sampleRates = new int[] { 8000 };
669217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                bitRates = Range.create(64000, 64000);
670217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                // platform allows multiple channels for this format
671217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_MSGSM)) {
672217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                sampleRates = new int[] { 8000 };
673217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                bitRates = Range.create(13000, 13000);
674217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxChannels = 1;
675217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            } else {
676217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                Log.w(TAG, "Unsupported mime " + mime);
677217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                mParent.mError |= ERROR_UNSUPPORTED;
678217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
679217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
680217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // restrict ranges
681217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (sampleRates != null) {
682217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                limitSampleRates(sampleRates);
683217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            } else if (sampleRateRange != null) {
684217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                limitSampleRates(new Range[] { sampleRateRange });
685217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
686217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            applyLimits(maxChannels, bitRates);
687217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
688b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
689217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private void applyLimits(int maxInputChannels, Range<Integer> bitRates) {
690217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mMaxInputChannelCount = Range.create(1, mMaxInputChannelCount)
691217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    .clamp(maxInputChannels);
692217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (bitRates != null) {
693217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                mBitrateRange = mBitrateRange.intersect(bitRates);
694b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
695217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
696217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
697217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private void parseFromInfo(MediaFormat info) {
698217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            int maxInputChannels = MAX_INPUT_CHANNEL_COUNT;
699217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            Range<Integer> bitRates = POSITIVE_INTEGERS;
700b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
701217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (info.containsKey("sample-rate-ranges")) {
702217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                String[] rateStrings = info.getString("sample-rate-ranges").split(",");
703217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                Range<Integer>[] rateRanges = new Range[rateStrings.length];
704217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                for (int i = 0; i < rateStrings.length; i++) {
705217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    rateRanges[i] = Utils.parseIntRange(rateStrings[i], null);
706217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
707217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                limitSampleRates(rateRanges);
708217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
709217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (info.containsKey("max-channel-count")) {
710217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxInputChannels = Utils.parseIntSafely(
711217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        info.getString("max-channel-count"), maxInputChannels);
712217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
713217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (info.containsKey("bitrate-range")) {
714217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                bitRates = bitRates.intersect(
715216e11dcbb4d56699c1740c801489be0d57b16c4Chong Zhang                        Utils.parseIntRange(info.getString("bitrate-range"), bitRates));
716b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
717217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            applyLimits(maxInputChannels, bitRates);
718217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
719b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
720217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /** @hide */
721217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public void setDefaultFormat(MediaFormat format) {
722217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // report settings that have only a single choice
723217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (mBitrateRange.getLower().equals(mBitrateRange.getUpper())) {
724217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                format.setInteger(MediaFormat.KEY_BIT_RATE, mBitrateRange.getLower());
725217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
726217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (mMaxInputChannelCount == 1) {
727217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                // mono-only format
728217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
729217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
730217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (mSampleRates != null && mSampleRates.length == 1) {
731217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                format.setInteger(MediaFormat.KEY_SAMPLE_RATE, mSampleRates[0]);
732217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
733217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
734217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
735217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /** @hide */
736217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public boolean supportsFormat(MediaFormat format) {
737217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            Map<String, Object> map = format.getMap();
738217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            Integer sampleRate = (Integer)map.get(MediaFormat.KEY_SAMPLE_RATE);
739217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            Integer channels = (Integer)map.get(MediaFormat.KEY_CHANNEL_COUNT);
740217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (!supports(sampleRate, channels)) {
741217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                return false;
742217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
743217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
744217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // nothing to do for:
745217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // KEY_CHANNEL_MASK: codecs don't get this
746217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // KEY_IS_ADTS:      required feature for all AAC decoders
747217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return true;
748217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
749217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    }
750217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
751217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    /**
752217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar     * A class that supports querying the video capabilities of a codec.
753217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar     */
754217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    public static final class VideoCapabilities {
755217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private static final String TAG = "VideoCapabilities";
756217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private CodecCapabilities mParent;
757217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private Range<Integer> mBitrateRange;
758217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
759217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private Range<Integer> mHeightRange;
760217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private Range<Integer> mWidthRange;
761217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private Range<Integer> mBlockCountRange;
762217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private Range<Integer> mHorizontalBlockRange;
763217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private Range<Integer> mVerticalBlockRange;
764217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private Range<Rational> mAspectRatioRange;
765217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private Range<Rational> mBlockAspectRatioRange;
766217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private Range<Long> mBlocksPerSecondRange;
767217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private Range<Integer> mFrameRateRange;
768217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
769217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private int mBlockWidth;
770217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private int mBlockHeight;
771217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private int mWidthAlignment;
772217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private int mHeightAlignment;
773217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private int mSmallerDimensionUpperLimit;
774217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
775217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /**
776217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Returns the range of supported bitrates in bits/second.
777217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         */
778217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public Range<Integer> getBitrateRange() {
779217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return mBitrateRange;
780217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
781217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
782217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /**
783217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Returns the range of supported video widths.
784217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         */
785217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public Range<Integer> getSupportedWidths() {
786217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return mWidthRange;
787217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
788217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
789217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /**
790217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Returns the range of supported video heights.
791217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         */
792217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public Range<Integer> getSupportedHeights() {
793217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return mHeightRange;
794217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
795217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
796217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /**
797217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Returns the alignment requirement for video width (in pixels).
798217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         *
799217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * This is a power-of-2 value that video width must be a
800217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * multiple of.
801217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         */
802217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public int getWidthAlignment() {
803217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return mWidthAlignment;
804217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
805217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
806217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /**
807217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Returns the alignment requirement for video height (in pixels).
808217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         *
809217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * This is a power-of-2 value that video height must be a
810217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * multiple of.
811217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         */
812217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public int getHeightAlignment() {
813217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return mHeightAlignment;
814217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
815217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
816217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /**
817217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Return the upper limit on the smaller dimension of width or height.
818217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * <p></p>
819217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Some codecs have a limit on the smaller dimension, whether it be
820217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * the width or the height.  E.g. a codec may only be able to handle
821217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * up to 1920x1080 both in landscape and portrait mode (1080x1920).
822217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * In this case the maximum width and height are both 1920, but the
823217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * smaller dimension limit will be 1080. For other codecs, this is
824217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * {@code Math.min(getSupportedWidths().getUpper(),
825217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * getSupportedHeights().getUpper())}.
826217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         *
827217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * @hide
828217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         */
829217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public int getSmallerDimensionUpperLimit() {
830217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return mSmallerDimensionUpperLimit;
831217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
832217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
833217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /**
834217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Returns the range of supported frame rates.
835217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * <p>
836217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * This is not a performance indicator.  Rather, it expresses the
837217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * limits specified in the coding standard, based on the complexities
838217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * of encoding material for later playback at a certain frame rate,
839217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * or the decoding of such material in non-realtime.
840217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         */
841217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public Range<Integer> getSupportedFrameRates() {
842217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return mFrameRateRange;
843217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
844217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
845217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /**
846217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Returns the range of supported video widths for a video height.
847217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * @param height the height of the video
848217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         */
849217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public Range<Integer> getSupportedWidthsFor(int height) {
850217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            try {
851217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                Range<Integer> range = mWidthRange;
852217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (!mHeightRange.contains(height)
853217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        || (height % mHeightAlignment) != 0) {
854217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    throw new IllegalArgumentException("unsupported height");
855b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                }
856217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                final int heightInBlocks = Utils.divUp(height, mBlockHeight);
857217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
858217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                // constrain by block count and by block aspect ratio
859217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                final int minWidthInBlocks = Math.max(
860217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        Utils.divUp(mBlockCountRange.getLower(), heightInBlocks),
861217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        (int)Math.ceil(mBlockAspectRatioRange.getLower().doubleValue()
862217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                * heightInBlocks));
863217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                final int maxWidthInBlocks = Math.min(
864217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        mBlockCountRange.getUpper() / heightInBlocks,
865217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        (int)(mBlockAspectRatioRange.getUpper().doubleValue()
866217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                * heightInBlocks));
867217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                range = range.intersect(
868217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        (minWidthInBlocks - 1) * mBlockWidth + mWidthAlignment,
869217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        maxWidthInBlocks * mBlockWidth);
870217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
871217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                // constrain by smaller dimension limit
872217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (height > mSmallerDimensionUpperLimit) {
873217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    range = range.intersect(1, mSmallerDimensionUpperLimit);
874b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                }
875b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
876217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                // constrain by aspect ratio
877217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                range = range.intersect(
878217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        (int)Math.ceil(mAspectRatioRange.getLower().doubleValue()
879217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                * height),
880217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        (int)(mAspectRatioRange.getUpper().doubleValue() * height));
881217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                return range;
882217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            } catch (IllegalArgumentException e) {
883217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                // should not be here
884217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                Log.w(TAG, "could not get supported widths for " + height , e);
885217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                throw new IllegalArgumentException("unsupported height");
886b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
887217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
888b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
889217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /**
890217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Returns the range of supported video heights for a video width
891217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * @param width the width of the video
892217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         */
893217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public Range<Integer> getSupportedHeightsFor(int width) {
894217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            try {
895217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                Range<Integer> range = mHeightRange;
896217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (!mWidthRange.contains(width)
897217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        || (width % mWidthAlignment) != 0) {
898217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    throw new IllegalArgumentException("unsupported width");
899b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                }
900217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                final int widthInBlocks = Utils.divUp(width, mBlockWidth);
901217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
902217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                // constrain by block count and by block aspect ratio
903217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                final int minHeightInBlocks = Math.max(
904217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        Utils.divUp(mBlockCountRange.getLower(), widthInBlocks),
905217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        (int)Math.ceil(widthInBlocks /
906217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                mBlockAspectRatioRange.getUpper().doubleValue()));
907217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                final int maxHeightInBlocks = Math.min(
908217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        mBlockCountRange.getUpper() / widthInBlocks,
909217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        (int)(widthInBlocks /
910217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                mBlockAspectRatioRange.getLower().doubleValue()));
911217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                range = range.intersect(
912217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        (minHeightInBlocks - 1) * mBlockHeight + mHeightAlignment,
913217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        maxHeightInBlocks * mBlockHeight);
914217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
915217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                // constrain by smaller dimension limit
916217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (width > mSmallerDimensionUpperLimit) {
917217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    range = range.intersect(1, mSmallerDimensionUpperLimit);
918217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
919217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
920217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                // constrain by aspect ratio
921217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                range = range.intersect(
922217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        (int)Math.ceil(width /
923217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                mAspectRatioRange.getUpper().doubleValue()),
924217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        (int)(width / mAspectRatioRange.getLower().doubleValue()));
925217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                return range;
926217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            } catch (IllegalArgumentException e) {
927217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                // should not be here
928217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                Log.w(TAG, "could not get supported heights for " + width , e);
929217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                throw new IllegalArgumentException("unsupported width");
930217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
931217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
932217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
933217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /**
934217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Returns the range of supported video frame rates for a video size.
935217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * <p>
936217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * This is not a performance indicator.  Rather, it expresses the limits specified in
937217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * the coding standard, based on the complexities of encoding material of a given
938217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * size for later playback at a certain frame rate, or the decoding of such material
939217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * in non-realtime.
940217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
941217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * @param width the width of the video
942217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * @param height the height of the video
943217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         */
944217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public Range<Double> getSupportedFrameRatesFor(int width, int height) {
945217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            Range<Integer> range = mHeightRange;
946217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (!supports(width, height, null)) {
947217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                throw new IllegalArgumentException("unsupported size");
948217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
949217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            final int blockCount =
950217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                Utils.divUp(width, mBlockWidth) * Utils.divUp(height, mBlockHeight);
951217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
952217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return Range.create(
953217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    Math.max(mBlocksPerSecondRange.getLower() / (double) blockCount,
954217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            (double) mFrameRateRange.getLower()),
955217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    Math.min(mBlocksPerSecondRange.getUpper() / (double) blockCount,
956217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            (double) mFrameRateRange.getUpper()));
957217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
958217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
959217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /**
960217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Returns whether a given video size ({@code width} and
961217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * {@code height}) and {@code frameRate} combination is supported.
962217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         */
963217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public boolean areSizeAndRateSupported(
964217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                int width, int height, double frameRate) {
965217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return supports(width, height, frameRate);
966217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
967217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
968217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /**
969217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Returns whether a given video size ({@code width} and
970217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * {@code height}) is supported.
971217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         */
972217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public boolean isSizeSupported(int width, int height) {
973217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return supports(width, height, null);
974217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
975217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
976217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private boolean supports(
977a4fcb62a224eca99d53b1692d1cc5ae5ff2d2127Lajos Molnar                Integer width, Integer height, Number rate) {
978217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            boolean ok = true;
979217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
980217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (ok && width != null) {
981217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                ok = mWidthRange.contains(width)
982217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        && (width % mWidthAlignment == 0);
983217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
984217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (ok && height != null) {
985217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                ok = mHeightRange.contains(height)
986217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        && (height % mHeightAlignment == 0);
987b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
988217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (ok && rate != null) {
989a4fcb62a224eca99d53b1692d1cc5ae5ff2d2127Lajos Molnar                ok = mFrameRateRange.contains(Utils.intRangeFor(rate.doubleValue()));
990217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
991217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (ok && height != null && width != null) {
992217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                ok = Math.min(height, width) <= mSmallerDimensionUpperLimit;
993b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
994217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                final int widthInBlocks = Utils.divUp(width, mBlockWidth);
995217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                final int heightInBlocks = Utils.divUp(height, mBlockHeight);
996217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                final int blockCount = widthInBlocks * heightInBlocks;
997217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                ok = ok && mBlockCountRange.contains(blockCount)
998217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        && mBlockAspectRatioRange.contains(
999217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                new Rational(widthInBlocks, heightInBlocks))
1000217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        && mAspectRatioRange.contains(new Rational(width, height));
1001217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (ok && rate != null) {
1002a4fcb62a224eca99d53b1692d1cc5ae5ff2d2127Lajos Molnar                    double blocksPerSec = blockCount * rate.doubleValue();
1003217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    ok = mBlocksPerSecondRange.contains(
1004217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            Utils.longRangeFor(blocksPerSec));
1005b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                }
1006b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
1007217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return ok;
1008217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1009b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
1010217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /**
1011217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * @hide
1012217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * @throws java.lang.ClassCastException */
1013217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public boolean supportsFormat(MediaFormat format) {
1014217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            final Map<String, Object> map = format.getMap();
1015217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            Integer width = (Integer)map.get(MediaFormat.KEY_WIDTH);
1016217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            Integer height = (Integer)map.get(MediaFormat.KEY_HEIGHT);
1017a4fcb62a224eca99d53b1692d1cc5ae5ff2d2127Lajos Molnar            Number rate = (Number)map.get(MediaFormat.KEY_FRAME_RATE);
1018217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1019217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // we ignore color-format for now as it is not reliably reported by codec
1020217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1021217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return supports(width, height, rate);
1022217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1023217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1024217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /* no public constructor */
1025217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private VideoCapabilities() { }
1026217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1027217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /** @hide */
1028217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public static VideoCapabilities create(
1029217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                MediaFormat info, CodecCapabilities parent) {
1030217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            VideoCapabilities caps = new VideoCapabilities();
1031217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            caps.init(info, parent);
1032217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return caps;
1033217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1034217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1035217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /** @hide */
1036217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public void init(MediaFormat info, CodecCapabilities parent) {
1037217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mParent = parent;
1038217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            initWithPlatformLimits();
1039217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            applyLevelLimits();
1040217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            parseFromInfo(info);
1041217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            updateLimits();
1042217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1043217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1044217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /** @hide */
1045217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public Size getBlockSize() {
1046217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return new Size(mBlockWidth, mBlockHeight);
1047217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1048217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1049217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /** @hide */
1050217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public Range<Integer> getBlockCountRange() {
1051217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return mBlockCountRange;
1052217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1053217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1054217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /** @hide */
1055217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public Range<Long> getBlocksPerSecondRange() {
1056217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return mBlocksPerSecondRange;
1057217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1058b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
1059217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /** @hide */
1060217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public Range<Rational> getAspectRatioRange(boolean blocks) {
1061217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return blocks ? mBlockAspectRatioRange : mAspectRatioRange;
1062217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1063217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1064217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private void initWithPlatformLimits() {
1065216e11dcbb4d56699c1740c801489be0d57b16c4Chong Zhang            mBitrateRange = BITRATE_RANGE;
1066217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1067217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mWidthRange  = SIZE_RANGE;
1068217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mHeightRange = SIZE_RANGE;
1069217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mFrameRateRange = FRAME_RATE_RANGE;
1070217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1071217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mHorizontalBlockRange = SIZE_RANGE;
1072217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mVerticalBlockRange   = SIZE_RANGE;
1073217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1074217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // full positive ranges are supported as these get calculated
1075217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mBlockCountRange      = POSITIVE_INTEGERS;
1076217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mBlocksPerSecondRange = POSITIVE_LONGS;
1077217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1078217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mBlockAspectRatioRange = POSITIVE_RATIONALS;
1079217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mAspectRatioRange      = POSITIVE_RATIONALS;
1080217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1081217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // YUV 4:2:0 requires 2:2 alignment
1082217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mWidthAlignment = 2;
1083217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mHeightAlignment = 2;
1084217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mBlockWidth = 2;
1085217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mBlockHeight = 2;
1086217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mSmallerDimensionUpperLimit = SIZE_RANGE.getUpper();
1087217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1088217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1089217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private void parseFromInfo(MediaFormat info) {
1090217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            final Map<String, Object> map = info.getMap();
1091217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            Size blockSize = new Size(mBlockWidth, mBlockHeight);
1092217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            Size alignment = new Size(mWidthAlignment, mHeightAlignment);
1093217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            Range<Integer> counts = null, widths = null, heights = null;
1094216e11dcbb4d56699c1740c801489be0d57b16c4Chong Zhang            Range<Integer> frameRates = null, bitRates = null;
1095217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            Range<Long> blockRates = null;
1096217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            Range<Rational> ratios = null, blockRatios = null;
1097217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1098217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            blockSize = Utils.parseSize(map.get("block-size"), blockSize);
1099217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            alignment = Utils.parseSize(map.get("alignment"), alignment);
1100217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            counts = Utils.parseIntRange(map.get("block-count-range"), null);
1101217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            blockRates =
1102217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                Utils.parseLongRange(map.get("blocks-per-second-range"), null);
1103217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            {
1104217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                Object o = map.get("size-range");
1105217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                Pair<Size, Size> sizeRange = Utils.parseSizeRange(o);
1106217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (sizeRange != null) {
1107217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    try {
1108217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        widths = Range.create(
1109217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                sizeRange.first.getWidth(),
1110217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                sizeRange.second.getWidth());
1111217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        heights = Range.create(
1112217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                sizeRange.first.getHeight(),
1113217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                sizeRange.second.getHeight());
1114217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    } catch (IllegalArgumentException e) {
1115217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        Log.w(TAG, "could not parse size range '" + o + "'");
1116217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        widths = null;
1117217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        heights = null;
1118b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                    }
1119b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                }
1120b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
1121217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // for now this just means using the smaller max size as 2nd
1122217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // upper limit.
1123217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // for now we are keeping the profile specific "width/height
1124217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // in macroblocks" limits.
1125217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (Integer.valueOf(1).equals(map.get("feature-can-swap-width-height"))) {
1126217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (widths != null) {
1127217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mSmallerDimensionUpperLimit =
1128217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        Math.min(widths.getUpper(), heights.getUpper());
1129217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    widths = heights = widths.extend(heights);
1130981c344ee7a4472e2a331d66819c132267a681c6Lajos Molnar                } else {
1131217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    Log.w(TAG, "feature can-swap-width-height is best used with size-range");
1132217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mSmallerDimensionUpperLimit =
1133217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        Math.min(mWidthRange.getUpper(), mHeightRange.getUpper());
1134217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mWidthRange = mHeightRange = mWidthRange.extend(mHeightRange);
1135b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                }
1136b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
1137b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
1138217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            ratios = Utils.parseRationalRange(
1139217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    map.get("block-aspect-ratio-range"), null);
1140217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            blockRatios = Utils.parseRationalRange(
1141217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    map.get("pixel-aspect-ratio-range"), null);
1142217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            frameRates = Utils.parseIntRange(map.get("frame-rate-range"), null);
1143217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (frameRates != null) {
1144217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                try {
1145217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    frameRates = frameRates.intersect(FRAME_RATE_RANGE);
1146217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                } catch (IllegalArgumentException e) {
1147217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    Log.w(TAG, "frame rate range (" + frameRates
1148217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            + ") is out of limits: " + FRAME_RATE_RANGE);
1149217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    frameRates = null;
1150b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                }
1151b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
1152216e11dcbb4d56699c1740c801489be0d57b16c4Chong Zhang            bitRates = Utils.parseIntRange(map.get("bitrate-range"), null);
1153216e11dcbb4d56699c1740c801489be0d57b16c4Chong Zhang            if (bitRates != null) {
1154216e11dcbb4d56699c1740c801489be0d57b16c4Chong Zhang                try {
1155216e11dcbb4d56699c1740c801489be0d57b16c4Chong Zhang                    bitRates = bitRates.intersect(BITRATE_RANGE);
1156216e11dcbb4d56699c1740c801489be0d57b16c4Chong Zhang                } catch (IllegalArgumentException e) {
1157216e11dcbb4d56699c1740c801489be0d57b16c4Chong Zhang                    Log.w(TAG,  "bitrate range (" + bitRates
1158216e11dcbb4d56699c1740c801489be0d57b16c4Chong Zhang                            + ") is out of limits: " + BITRATE_RANGE);
1159216e11dcbb4d56699c1740c801489be0d57b16c4Chong Zhang                    bitRates = null;
1160216e11dcbb4d56699c1740c801489be0d57b16c4Chong Zhang                }
1161216e11dcbb4d56699c1740c801489be0d57b16c4Chong Zhang            }
1162b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
1163217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            checkPowerOfTwo(
1164217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    blockSize.getWidth(), "block-size width must be power of two");
1165217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            checkPowerOfTwo(
1166217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    blockSize.getHeight(), "block-size height must be power of two");
1167b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
1168217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            checkPowerOfTwo(
1169217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    alignment.getWidth(), "alignment width must be power of two");
1170217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            checkPowerOfTwo(
1171217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    alignment.getHeight(), "alignment height must be power of two");
1172217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1173217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // update block-size and alignment
1174217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            applyMacroBlockLimits(
1175217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE,
1176217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    Long.MAX_VALUE, blockSize.getWidth(), blockSize.getHeight(),
1177217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    alignment.getWidth(), alignment.getHeight());
1178217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1179217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if ((mParent.mError & ERROR_UNSUPPORTED) != 0) {
1180217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                // codec supports profiles that we don't know.
1181217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                // Use supplied values clipped to platform limits
1182217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (widths != null) {
1183217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mWidthRange = SIZE_RANGE.intersect(widths);
1184217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
1185217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (heights != null) {
1186217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mHeightRange = SIZE_RANGE.intersect(heights);
1187217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
1188217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (counts != null) {
1189217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mBlockCountRange = POSITIVE_INTEGERS.intersect(
1190217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            Utils.factorRange(counts, mBlockWidth * mBlockHeight
1191217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    / blockSize.getWidth() / blockSize.getHeight()));
1192217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
1193217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (blockRates != null) {
1194217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mBlocksPerSecondRange = POSITIVE_LONGS.intersect(
1195217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            Utils.factorRange(blockRates, mBlockWidth * mBlockHeight
1196217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    / blockSize.getWidth() / blockSize.getHeight()));
1197217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
1198217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (blockRatios != null) {
1199217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mBlockAspectRatioRange = POSITIVE_RATIONALS.intersect(
1200217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            Utils.scaleRange(blockRatios,
1201217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    mBlockHeight / blockSize.getHeight(),
1202217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    mBlockWidth / blockSize.getWidth()));
1203217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
1204217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (ratios != null) {
1205217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mAspectRatioRange = POSITIVE_RATIONALS.intersect(ratios);
1206217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
1207217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (frameRates != null) {
1208217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mFrameRateRange = FRAME_RATE_RANGE.intersect(frameRates);
1209217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
1210216e11dcbb4d56699c1740c801489be0d57b16c4Chong Zhang                if (bitRates != null) {
1211216e11dcbb4d56699c1740c801489be0d57b16c4Chong Zhang                    mBitrateRange = BITRATE_RANGE.intersect(bitRates);
1212216e11dcbb4d56699c1740c801489be0d57b16c4Chong Zhang                }
1213217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            } else {
1214217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                // no unsupported profile/levels, so restrict values to known limits
1215217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (widths != null) {
1216217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mWidthRange = mWidthRange.intersect(widths);
1217217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
1218217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (heights != null) {
1219217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mHeightRange = mHeightRange.intersect(heights);
1220b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                }
1221217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (counts != null) {
1222217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mBlockCountRange = mBlockCountRange.intersect(
1223217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            Utils.factorRange(counts, mBlockWidth * mBlockHeight
1224217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    / blockSize.getWidth() / blockSize.getHeight()));
1225b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                }
1226217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (blockRates != null) {
1227217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mBlocksPerSecondRange = mBlocksPerSecondRange.intersect(
1228217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            Utils.factorRange(blockRates, mBlockWidth * mBlockHeight
1229217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    / blockSize.getWidth() / blockSize.getHeight()));
1230b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                }
1231217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (blockRatios != null) {
1232217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mBlockAspectRatioRange = mBlockAspectRatioRange.intersect(
1233217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            Utils.scaleRange(blockRatios,
1234217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    mBlockHeight / blockSize.getHeight(),
1235217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    mBlockWidth / blockSize.getWidth()));
1236217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
1237217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (ratios != null) {
1238217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mAspectRatioRange = mAspectRatioRange.intersect(ratios);
1239217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
1240217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (frameRates != null) {
1241217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mFrameRateRange = mFrameRateRange.intersect(frameRates);
1242217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
1243216e11dcbb4d56699c1740c801489be0d57b16c4Chong Zhang                if (bitRates != null) {
1244216e11dcbb4d56699c1740c801489be0d57b16c4Chong Zhang                    mBitrateRange = mBitrateRange.intersect(bitRates);
1245216e11dcbb4d56699c1740c801489be0d57b16c4Chong Zhang                }
1246217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
1247217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            updateLimits();
1248217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1249217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1250217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private void applyBlockLimits(
1251217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                int blockWidth, int blockHeight,
1252217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                Range<Integer> counts, Range<Long> rates, Range<Rational> ratios) {
1253217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            checkPowerOfTwo(blockWidth, "blockWidth must be a power of two");
1254217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            checkPowerOfTwo(blockHeight, "blockHeight must be a power of two");
1255217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1256217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            final int newBlockWidth = Math.max(blockWidth, mBlockWidth);
1257217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            final int newBlockHeight = Math.max(blockHeight, mBlockHeight);
1258217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1259217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // factor will always be a power-of-2
1260217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            int factor =
1261217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                newBlockWidth * newBlockHeight / mBlockWidth / mBlockHeight;
1262217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (factor != 1) {
1263217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                mBlockCountRange = Utils.factorRange(mBlockCountRange, factor);
1264217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                mBlocksPerSecondRange = Utils.factorRange(
1265217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        mBlocksPerSecondRange, factor);
1266217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                mBlockAspectRatioRange = Utils.scaleRange(
1267217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        mBlockAspectRatioRange,
1268217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        newBlockHeight / mBlockHeight,
1269217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        newBlockWidth / mBlockWidth);
1270217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                mHorizontalBlockRange = Utils.factorRange(
1271217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        mHorizontalBlockRange, newBlockWidth / mBlockWidth);
1272217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                mVerticalBlockRange = Utils.factorRange(
1273217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        mVerticalBlockRange, newBlockHeight / mBlockHeight);
1274217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
1275217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            factor = newBlockWidth * newBlockHeight / blockWidth / blockHeight;
1276217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (factor != 1) {
1277217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                counts = Utils.factorRange(counts, factor);
1278217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                rates = Utils.factorRange(rates, factor);
1279217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                ratios = Utils.scaleRange(
1280217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        ratios, newBlockHeight / blockHeight,
1281217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        newBlockWidth / blockWidth);
1282217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
1283217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mBlockCountRange = mBlockCountRange.intersect(counts);
1284217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mBlocksPerSecondRange = mBlocksPerSecondRange.intersect(rates);
1285217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mBlockAspectRatioRange = mBlockAspectRatioRange.intersect(ratios);
1286217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mBlockWidth = newBlockWidth;
1287217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mBlockHeight = newBlockHeight;
1288217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1289217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1290217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private void applyAlignment(int widthAlignment, int heightAlignment) {
1291217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            checkPowerOfTwo(widthAlignment, "widthAlignment must be a power of two");
1292217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            checkPowerOfTwo(heightAlignment, "heightAlignment must be a power of two");
1293217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1294217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (widthAlignment > mBlockWidth || heightAlignment > mBlockHeight) {
1295217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                // maintain assumption that 0 < alignment <= block-size
1296217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                applyBlockLimits(
1297217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        Math.max(widthAlignment, mBlockWidth),
1298217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        Math.max(heightAlignment, mBlockHeight),
1299217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        POSITIVE_INTEGERS, POSITIVE_LONGS, POSITIVE_RATIONALS);
1300b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
1301b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
1302217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mWidthAlignment = Math.max(widthAlignment, mWidthAlignment);
1303217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mHeightAlignment = Math.max(heightAlignment, mHeightAlignment);
1304217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1305217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mWidthRange = Utils.alignRange(mWidthRange, mWidthAlignment);
1306217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mHeightRange = Utils.alignRange(mHeightRange, mHeightAlignment);
1307217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1308217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1309217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private void updateLimits() {
1310217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // pixels -> blocks <- counts
1311217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mHorizontalBlockRange = mHorizontalBlockRange.intersect(
1312217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    Utils.factorRange(mWidthRange, mBlockWidth));
1313217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mHorizontalBlockRange = mHorizontalBlockRange.intersect(
1314217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    Range.create(
1315217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            mBlockCountRange.getLower() / mVerticalBlockRange.getUpper(),
1316217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            mBlockCountRange.getUpper() / mVerticalBlockRange.getLower()));
1317217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mVerticalBlockRange = mVerticalBlockRange.intersect(
1318217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    Utils.factorRange(mHeightRange, mBlockHeight));
1319217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mVerticalBlockRange = mVerticalBlockRange.intersect(
1320217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    Range.create(
1321217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            mBlockCountRange.getLower() / mHorizontalBlockRange.getUpper(),
1322217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            mBlockCountRange.getUpper() / mHorizontalBlockRange.getLower()));
1323217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mBlockCountRange = mBlockCountRange.intersect(
1324217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    Range.create(
1325217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            mHorizontalBlockRange.getLower()
1326217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    * mVerticalBlockRange.getLower(),
1327217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            mHorizontalBlockRange.getUpper()
1328217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    * mVerticalBlockRange.getUpper()));
1329217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mBlockAspectRatioRange = mBlockAspectRatioRange.intersect(
1330217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    new Rational(
1331217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            mHorizontalBlockRange.getLower(), mVerticalBlockRange.getUpper()),
1332217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    new Rational(
1333217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            mHorizontalBlockRange.getUpper(), mVerticalBlockRange.getLower()));
1334217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1335217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // blocks -> pixels
1336217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mWidthRange = mWidthRange.intersect(
1337217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    (mHorizontalBlockRange.getLower() - 1) * mBlockWidth + mWidthAlignment,
1338217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mHorizontalBlockRange.getUpper() * mBlockWidth);
1339217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mHeightRange = mHeightRange.intersect(
1340217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    (mVerticalBlockRange.getLower() - 1) * mBlockHeight + mHeightAlignment,
1341217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mVerticalBlockRange.getUpper() * mBlockHeight);
1342217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mAspectRatioRange = mAspectRatioRange.intersect(
1343217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    new Rational(mWidthRange.getLower(), mHeightRange.getUpper()),
1344217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    new Rational(mWidthRange.getUpper(), mHeightRange.getLower()));
1345217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1346217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mSmallerDimensionUpperLimit = Math.min(
1347217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mSmallerDimensionUpperLimit,
1348217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    Math.min(mWidthRange.getUpper(), mHeightRange.getUpper()));
1349217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1350217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // blocks -> rate
1351217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mBlocksPerSecondRange = mBlocksPerSecondRange.intersect(
1352217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mBlockCountRange.getLower() * (long)mFrameRateRange.getLower(),
1353217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mBlockCountRange.getUpper() * (long)mFrameRateRange.getUpper());
1354217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mFrameRateRange = mFrameRateRange.intersect(
1355217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    (int)(mBlocksPerSecondRange.getLower()
1356217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            / mBlockCountRange.getUpper()),
1357217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    (int)(mBlocksPerSecondRange.getUpper()
1358217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            / (double)mBlockCountRange.getLower()));
1359217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1360217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1361217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private void applyMacroBlockLimits(
1362217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                int maxHorizontalBlocks, int maxVerticalBlocks,
1363217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                int maxBlocks, long maxBlocksPerSecond,
1364217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                int blockWidth, int blockHeight,
1365217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                int widthAlignment, int heightAlignment) {
1366217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            applyAlignment(widthAlignment, heightAlignment);
1367217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            applyBlockLimits(
1368217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    blockWidth, blockHeight, Range.create(1, maxBlocks),
1369217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    Range.create(1L, maxBlocksPerSecond),
1370217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    Range.create(
1371217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            new Rational(1, maxVerticalBlocks),
1372217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            new Rational(maxHorizontalBlocks, 1)));
1373217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mHorizontalBlockRange =
1374217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mHorizontalBlockRange.intersect(
1375217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            1, maxHorizontalBlocks / (mBlockWidth / blockWidth));
1376217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mVerticalBlockRange =
1377217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mVerticalBlockRange.intersect(
1378217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            1, maxVerticalBlocks / (mBlockHeight / blockHeight));
1379217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1380217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1381217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private void applyLevelLimits() {
1382217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            int maxBlocksPerSecond = 0;
1383217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            int maxBlocks = 0;
1384217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            int maxBps = 0;
1385217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            int maxDPBBlocks = 0;
1386217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1387217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            int errors = ERROR_NONE_SUPPORTED;
1388217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            CodecProfileLevel[] profileLevels = mParent.profileLevels;
1389217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            String mime = mParent.getMimeType();
1390217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1391217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_AVC)) {
1392217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxBlocks = 99;
1393217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxBlocksPerSecond = 1485;
1394217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxBps = 64000;
1395217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxDPBBlocks = 396;
1396217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                for (CodecProfileLevel profileLevel: profileLevels) {
1397217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    int MBPS = 0, FS = 0, BR = 0, DPB = 0;
1398217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    boolean supported = true;
1399217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    switch (profileLevel.level) {
1400217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCLevel1:
1401217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            MBPS =    1485; FS =    99; BR =     64; DPB =    396; break;
1402217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCLevel1b:
1403217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            MBPS =    1485; FS =    99; BR =    128; DPB =    396; break;
1404217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCLevel11:
1405217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            MBPS =    3000; FS =   396; BR =    192; DPB =    900; break;
1406217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCLevel12:
1407217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            MBPS =    6000; FS =   396; BR =    384; DPB =   2376; break;
1408217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCLevel13:
1409217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            MBPS =   11880; FS =   396; BR =    768; DPB =   2376; break;
1410217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCLevel2:
1411217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            MBPS =   11880; FS =   396; BR =   2000; DPB =   2376; break;
1412217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCLevel21:
1413217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            MBPS =   19800; FS =   792; BR =   4000; DPB =   4752; break;
1414217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCLevel22:
1415217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            MBPS =   20250; FS =  1620; BR =   4000; DPB =   8100; break;
1416217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCLevel3:
1417217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            MBPS =   40500; FS =  1620; BR =  10000; DPB =   8100; break;
1418217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCLevel31:
1419217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            MBPS =  108000; FS =  3600; BR =  14000; DPB =  18000; break;
1420217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCLevel32:
1421217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            MBPS =  216000; FS =  5120; BR =  20000; DPB =  20480; break;
1422217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCLevel4:
1423217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            MBPS =  245760; FS =  8192; BR =  20000; DPB =  32768; break;
1424217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCLevel41:
1425217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            MBPS =  245760; FS =  8192; BR =  50000; DPB =  32768; break;
1426217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCLevel42:
1427217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            MBPS =  522240; FS =  8704; BR =  50000; DPB =  34816; break;
1428217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCLevel5:
1429217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            MBPS =  589824; FS = 22080; BR = 135000; DPB = 110400; break;
1430217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCLevel51:
1431217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            MBPS =  983040; FS = 36864; BR = 240000; DPB = 184320; break;
1432217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCLevel52:
1433217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            MBPS = 2073600; FS = 36864; BR = 240000; DPB = 184320; break;
1434217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        default:
1435217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            Log.w(TAG, "Unrecognized level "
1436217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    + profileLevel.level + " for " + mime);
1437217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            errors |= ERROR_UNRECOGNIZED;
1438217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    }
1439217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    switch (profileLevel.profile) {
1440217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCProfileHigh:
1441217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            BR *= 1250; break;
1442217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCProfileHigh10:
1443217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            BR *= 3000; break;
1444217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCProfileExtended:
1445217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCProfileHigh422:
1446217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCProfileHigh444:
1447217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            Log.w(TAG, "Unsupported profile "
1448217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    + profileLevel.profile + " for " + mime);
1449217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            errors |= ERROR_UNSUPPORTED;
1450217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            supported = false;
1451217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            // fall through - treat as base profile
1452217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCProfileBaseline:
1453217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.AVCProfileMain:
1454217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            BR *= 1000; break;
1455217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        default:
1456217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            Log.w(TAG, "Unrecognized profile "
1457217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    + profileLevel.profile + " for " + mime);
1458217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            errors |= ERROR_UNRECOGNIZED;
1459217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            BR *= 1000;
1460217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    }
1461217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    if (supported) {
1462217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        errors &= ~ERROR_NONE_SUPPORTED;
1463217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    }
1464217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    maxBlocksPerSecond = Math.max(MBPS, maxBlocksPerSecond);
1465217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    maxBlocks = Math.max(FS, maxBlocks);
1466217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    maxBps = Math.max(BR, maxBps);
1467217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    maxDPBBlocks = Math.max(maxDPBBlocks, DPB);
1468981c344ee7a4472e2a331d66819c132267a681c6Lajos Molnar                }
1469217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1470217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                int maxLengthInBlocks = (int)(Math.sqrt(maxBlocks * 8));
1471217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                applyMacroBlockLimits(
1472217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        maxLengthInBlocks, maxLengthInBlocks,
1473217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        maxBlocks, maxBlocksPerSecond,
1474217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        16 /* blockWidth */, 16 /* blockHeight */,
1475217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        1 /* widthAlignment */, 1 /* heightAlignment */);
1476217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_MPEG4)) {
1477217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                int maxWidth = 11, maxHeight = 9, maxRate = 15;
1478217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxBlocks = 99;
1479217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxBlocksPerSecond = 1485;
1480217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxBps = 64000;
1481217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                for (CodecProfileLevel profileLevel: profileLevels) {
1482217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    int MBPS = 0, FS = 0, BR = 0, FR = 0, W = 0, H = 0;
1483217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    boolean supported = true;
1484217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    switch (profileLevel.profile) {
1485217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.MPEG4ProfileSimple:
1486217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            switch (profileLevel.level) {
1487217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                case CodecProfileLevel.MPEG4Level0:
1488217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    FR = 15; W = 11; H =  9; MBPS =  1485; FS =  99; BR =  64; break;
1489217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                case CodecProfileLevel.MPEG4Level1:
1490217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    FR = 30; W = 11; H =  9; MBPS =  1485; FS =  99; BR =  64; break;
1491217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                case CodecProfileLevel.MPEG4Level0b:
1492217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    FR = 30; W = 11; H =  9; MBPS =  1485; FS =  99; BR = 128; break;
1493217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                case CodecProfileLevel.MPEG4Level2:
1494217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    FR = 30; W = 22; H = 18; MBPS =  5940; FS = 396; BR = 128; break;
1495217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                case CodecProfileLevel.MPEG4Level3:
1496217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    FR = 30; W = 22; H = 18; MBPS = 11880; FS = 396; BR = 384; break;
1497217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                case CodecProfileLevel.MPEG4Level4:
1498217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                case CodecProfileLevel.MPEG4Level4a:
1499217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                case CodecProfileLevel.MPEG4Level5:
1500217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    // While MPEG4 SP does not have level 4 or 5, some vendors
1501217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    // report it. Use the same limits as level 3, but mark as
1502217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    // unsupported.
1503217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    FR = 30; W = 22; H = 18; MBPS = 11880; FS = 396; BR = 384;
1504217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    supported = false;
1505217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    break;
1506217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                default:
1507217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    Log.w(TAG, "Unrecognized profile/level "
1508217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                            + profileLevel.profile + "/"
1509217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                            + profileLevel.level + " for " + mime);
1510217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    errors |= ERROR_UNRECOGNIZED;
1511217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            }
1512217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            break;
1513217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.MPEG4ProfileAdvancedSimple:
1514217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            switch (profileLevel.level) {
1515217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                case CodecProfileLevel.MPEG4Level0:
1516217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                case CodecProfileLevel.MPEG4Level1:
1517217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    FR = 30; W = 11; H =  9; MBPS =  2970; FS =   99; BR =  128; break;
1518217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                case CodecProfileLevel.MPEG4Level2:
1519217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    FR = 30; W = 22; H = 18; MBPS =  5940; FS =  396; BR =  384; break;
1520217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                case CodecProfileLevel.MPEG4Level3:
1521217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    FR = 30; W = 22; H = 18; MBPS = 11880; FS =  396; BR =  768; break;
1522217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                // case CodecProfileLevel.MPEG4Level3b:
1523217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                // TODO: MPEG4 level 3b is not defined in OMX
1524217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                //  MBPS = 11880; FS =  396; BR = 1500; break;
1525217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                case CodecProfileLevel.MPEG4Level4:
1526217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                case CodecProfileLevel.MPEG4Level4a:
1527217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    // TODO: MPEG4 level 4a is not defined in spec
1528217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    FR = 30; W = 44; H = 36; MBPS = 23760; FS =  792; BR = 3000; break;
1529217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                case CodecProfileLevel.MPEG4Level5:
1530217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    FR = 30; W = 45; H = 36; MBPS = 48600; FS = 1620; BR = 8000; break;
1531217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                default:
1532217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    Log.w(TAG, "Unrecognized profile/level "
1533217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                            + profileLevel.profile + "/"
1534217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                            + profileLevel.level + " for " + mime);
1535217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    errors |= ERROR_UNRECOGNIZED;
1536217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            }
1537217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            break;
1538217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.MPEG4ProfileMain:             // 2-4
1539217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.MPEG4ProfileNbit:             // 2
1540217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.MPEG4ProfileAdvancedRealTime: // 1-4
1541217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.MPEG4ProfileCoreScalable:     // 1-3
1542217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.MPEG4ProfileAdvancedCoding:   // 1-4
1543217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.MPEG4ProfileCore:             // 1-2
1544217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.MPEG4ProfileAdvancedCore:     // 1-4
1545217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.MPEG4ProfileSimpleScalable:   // 0-2
1546217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.MPEG4ProfileAdvancedScalable: // 1-3
1547217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.MPEG4ProfileHybrid:           // 1-2
1548217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.MPEG4ProfileBasicAnimated:    // 1-2
1549217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.MPEG4ProfileScalableTexture:  // 1
1550217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.MPEG4ProfileSimpleFace:       // 1-2
1551217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.MPEG4ProfileSimpleFBA:        // 1-2
1552217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            Log.i(TAG, "Unsupported profile "
1553217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    + profileLevel.profile + " for " + mime);
1554217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            errors |= ERROR_UNSUPPORTED;
1555217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            supported = false;
1556217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            break;
1557217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        default:
1558217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            Log.w(TAG, "Unrecognized profile "
1559217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    + profileLevel.profile + " for " + mime);
1560217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            errors |= ERROR_UNRECOGNIZED;
1561217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    }
1562217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    if (supported) {
1563217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        errors &= ~ERROR_NONE_SUPPORTED;
1564217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    }
1565217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    maxBlocksPerSecond = Math.max(MBPS, maxBlocksPerSecond);
1566217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    maxBlocks = Math.max(FS, maxBlocks);
1567217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    maxBps = Math.max(BR * 1000, maxBps);
1568217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    maxWidth = Math.max(W, maxWidth);
1569217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    maxHeight = Math.max(H, maxHeight);
1570217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    maxRate = Math.max(FR, maxRate);
1571981c344ee7a4472e2a331d66819c132267a681c6Lajos Molnar                }
1572217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                applyMacroBlockLimits(maxWidth, maxHeight,
1573217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        maxBlocks, maxBlocksPerSecond,
1574217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        16 /* blockWidth */, 16 /* blockHeight */,
1575217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        1 /* widthAlignment */, 1 /* heightAlignment */);
1576217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                mFrameRateRange = mFrameRateRange.intersect(12, maxRate);
1577217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_H263)) {
1578217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                int maxWidth = 11, maxHeight = 9, maxRate = 15;
1579217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxBlocks = 99;
1580217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxBlocksPerSecond = 1485;
1581217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxBps = 64000;
1582217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                for (CodecProfileLevel profileLevel: profileLevels) {
1583217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    int MBPS = 0, BR = 0, FR = 0, W = 0, H = 0;
1584217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    switch (profileLevel.level) {
1585217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.H263Level10:
1586217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR = 15; W = 11; H =  9; BR =   1; MBPS =  W * H * FR; break;
1587217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.H263Level20:
1588217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            // only supports CIF, 0..QCIF
1589217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR = 30; W = 22; H = 18; BR =   2; MBPS =  W * H * FR; break;
1590217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.H263Level30:
1591217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            // only supports CIF, 0..QCIF
1592217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR = 30; W = 22; H = 18; BR =   6; MBPS =  W * H * FR; break;
1593217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.H263Level40:
1594217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            // only supports CIF, 0..QCIF
1595217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR = 30; W = 22; H = 18; BR =  32; MBPS =  W * H * FR; break;
1596217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.H263Level45:
1597217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            // only implies level 10 support
1598217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR = 30; W = 11; H =  9; BR =   2; MBPS =  W * H * FR; break;
1599217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.H263Level50:
1600217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            // only supports 50fps for H > 15
1601217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR = 60; W = 22; H = 18; BR =  64; MBPS =  W * H * 50; break;
1602217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.H263Level60:
1603217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            // only supports 50fps for H > 15
1604217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR = 60; W = 45; H = 18; BR = 128; MBPS =  W * H * 50; break;
1605217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.H263Level70:
1606217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            // only supports 50fps for H > 30
1607217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR = 60; W = 45; H = 36; BR = 256; MBPS =  W * H * 50; break;
1608217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        default:
1609217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            Log.w(TAG, "Unrecognized profile/level " + profileLevel.profile
1610217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    + "/" + profileLevel.level + " for " + mime);
1611217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            errors |= ERROR_UNRECOGNIZED;
1612217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    }
1613217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    switch (profileLevel.profile) {
1614217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.H263ProfileBackwardCompatible:
1615217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.H263ProfileBaseline:
1616217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.H263ProfileH320Coding:
1617217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.H263ProfileHighCompression:
1618217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.H263ProfileHighLatency:
1619217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.H263ProfileInterlace:
1620217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.H263ProfileInternet:
1621217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.H263ProfileISWV2:
1622217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.H263ProfileISWV3:
1623217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            break;
1624217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        default:
1625217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            Log.w(TAG, "Unrecognized profile "
1626217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    + profileLevel.profile + " for " + mime);
1627217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            errors |= ERROR_UNRECOGNIZED;
1628217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    }
1629217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    errors &= ~ERROR_NONE_SUPPORTED;
1630217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    maxBlocksPerSecond = Math.max(MBPS, maxBlocksPerSecond);
1631217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    maxBlocks = Math.max(W * H, maxBlocks);
1632217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    maxBps = Math.max(BR * 64000, maxBps);
1633217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    maxWidth = Math.max(W, maxWidth);
1634217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    maxHeight = Math.max(H, maxHeight);
1635217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    maxRate = Math.max(FR, maxRate);
1636217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
1637217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                applyMacroBlockLimits(maxWidth, maxHeight,
1638217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        maxBlocks, maxBlocksPerSecond,
1639217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        16 /* blockWidth */, 16 /* blockHeight */,
1640217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        1 /* widthAlignment */, 1 /* heightAlignment */);
1641217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                mFrameRateRange = Range.create(1, maxRate);
1642217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP8) ||
1643217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP9)) {
1644217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxBlocks = maxBlocksPerSecond = Integer.MAX_VALUE;
1645217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1646217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                // TODO: set to 100Mbps for now, need a number for VPX
1647217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxBps = 100000000;
1648217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1649217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                // profile levels are not indicative for VPx, but verify
1650217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                // them nonetheless
1651217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                for (CodecProfileLevel profileLevel: profileLevels) {
1652217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    switch (profileLevel.level) {
1653217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.VP8Level_Version0:
1654217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.VP8Level_Version1:
1655217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.VP8Level_Version2:
1656217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.VP8Level_Version3:
1657217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            break;
1658217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        default:
1659217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            Log.w(TAG, "Unrecognized level "
1660217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    + profileLevel.level + " for " + mime);
1661217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            errors |= ERROR_UNRECOGNIZED;
1662217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    }
1663217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    switch (profileLevel.profile) {
1664217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.VP8ProfileMain:
1665217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            break;
1666217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        default:
1667217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            Log.w(TAG, "Unrecognized profile "
1668217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    + profileLevel.profile + " for " + mime);
1669217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            errors |= ERROR_UNRECOGNIZED;
1670217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    }
1671217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    errors &= ~ERROR_NONE_SUPPORTED;
1672981c344ee7a4472e2a331d66819c132267a681c6Lajos Molnar                }
1673981c344ee7a4472e2a331d66819c132267a681c6Lajos Molnar
1674217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                final int blockSize =
1675217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP8) ? 16 : 8;
1676217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                applyMacroBlockLimits(Short.MAX_VALUE, Short.MAX_VALUE,
1677217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        maxBlocks, maxBlocksPerSecond, blockSize, blockSize,
1678217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        1 /* widthAlignment */, 1 /* heightAlignment */);
1679217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_HEVC)) {
1680217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxBlocks = 36864;
1681217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxBlocksPerSecond = maxBlocks * 15;
1682217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxBps = 128000;
1683217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                for (CodecProfileLevel profileLevel: profileLevels) {
1684217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    double FR = 0;
1685217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    int FS = 0;
1686217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    int BR = 0;
1687217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    switch (profileLevel.level) {
1688217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCMainTierLevel1:
1689217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCHighTierLevel1:
1690217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR =    15; FS =    36864; BR =    128; break;
1691217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCMainTierLevel2:
1692217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCHighTierLevel2:
1693217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR =    30; FS =   122880; BR =   1500; break;
1694217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCMainTierLevel21:
1695217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCHighTierLevel21:
1696217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR =    30; FS =   245760; BR =   3000; break;
1697217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCMainTierLevel3:
1698217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCHighTierLevel3:
1699217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR =    30; FS =   552960; BR =   6000; break;
1700217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCMainTierLevel31:
1701217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCHighTierLevel31:
1702217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR = 33.75; FS =   983040; BR =  10000; break;
1703217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCMainTierLevel4:
1704217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR =    30; FS =  2228224; BR =  12000; break;
1705217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCHighTierLevel4:
1706217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR =    30; FS =  2228224; BR =  30000; break;
1707217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCMainTierLevel41:
1708217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR =    60; FS =  2228224; BR =  20000; break;
1709217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCHighTierLevel41:
1710217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR =    60; FS =  2228224; BR =  50000; break;
1711217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCMainTierLevel5:
1712217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR =    30; FS =  8912896; BR =  25000; break;
1713217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCHighTierLevel5:
1714217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR =    30; FS =  8912896; BR = 100000; break;
1715217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCMainTierLevel51:
1716217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR =    60; FS =  8912896; BR =  40000; break;
1717217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCHighTierLevel51:
1718217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR =    60; FS =  8912896; BR = 160000; break;
1719217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCMainTierLevel52:
1720217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR =   120; FS =  8912896; BR =  60000; break;
1721217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCHighTierLevel52:
1722217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR =   120; FS =  8912896; BR = 240000; break;
1723217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCMainTierLevel6:
1724217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR =    30; FS = 35651584; BR =  60000; break;
1725217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCHighTierLevel6:
1726217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR =    30; FS = 35651584; BR = 240000; break;
1727217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCMainTierLevel61:
1728217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR =    60; FS = 35651584; BR = 120000; break;
1729217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCHighTierLevel61:
1730217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR =    60; FS = 35651584; BR = 480000; break;
1731217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCMainTierLevel62:
1732217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR =   120; FS = 35651584; BR = 240000; break;
1733217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCHighTierLevel62:
1734217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            FR =   120; FS = 35651584; BR = 800000; break;
1735217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        default:
1736217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            Log.w(TAG, "Unrecognized level "
1737217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    + profileLevel.level + " for " + mime);
1738217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            errors |= ERROR_UNRECOGNIZED;
1739217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    }
1740217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    switch (profileLevel.profile) {
1741217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCProfileMain:
1742217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        case CodecProfileLevel.HEVCProfileMain10:
1743217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            break;
1744217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        default:
1745217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            Log.w(TAG, "Unrecognized profile "
1746217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                                    + profileLevel.profile + " for " + mime);
1747217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            errors |= ERROR_UNRECOGNIZED;
1748217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    }
1749217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1750217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    /* DPB logic:
1751217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    if      (width * height <= FS / 4)    DPB = 16;
1752217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    else if (width * height <= FS / 2)    DPB = 12;
1753217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    else if (width * height <= FS * 0.75) DPB = 8;
1754217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    else                                  DPB = 6;
1755217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    */
1756217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1757217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    errors &= ~ERROR_NONE_SUPPORTED;
1758217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    maxBlocksPerSecond = Math.max((int)(FR * FS), maxBlocksPerSecond);
1759217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    maxBlocks = Math.max(FS, maxBlocks);
1760217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    maxBps = Math.max(BR * 1000, maxBps);
1761b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                }
1762b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
1763217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                int maxLengthInBlocks = (int)(Math.sqrt(maxBlocks * 8));
1764217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                // CTBs are at least 8x8
1765217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxBlocks = Utils.divUp(maxBlocks, 8 * 8);
1766217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxBlocksPerSecond = Utils.divUp(maxBlocksPerSecond, 8 * 8);
1767217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxLengthInBlocks = Utils.divUp(maxLengthInBlocks, 8);
1768217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1769217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                applyMacroBlockLimits(
1770217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        maxLengthInBlocks, maxLengthInBlocks,
1771217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        maxBlocks, maxBlocksPerSecond,
1772217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        8 /* blockWidth */, 8 /* blockHeight */,
1773217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        1 /* widthAlignment */, 1 /* heightAlignment */);
1774217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            } else {
1775217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                Log.w(TAG, "Unsupported mime " + mime);
1776217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                // using minimal bitrate here.  should be overriden by
1777217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                // info from media_codecs.xml
1778217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                maxBps = 64000;
1779217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                errors |= ERROR_UNSUPPORTED;
1780217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
1781217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mBitrateRange = Range.create(1, maxBps);
1782217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mParent.mError |= errors;
1783217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1784217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    }
1785217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1786217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    /**
1787217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar     * A class that supports querying the encoding capabilities of a codec.
1788217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar     */
1789217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar    public static final class EncoderCapabilities {
1790217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /**
1791217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Returns the supported range of quality values.
1792217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         *
1793217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * @hide
1794217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         */
1795217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public Range<Integer> getQualityRange() {
1796217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return mQualityRange;
1797217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1798217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1799217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /**
1800217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Returns the supported range of encoder complexity values.
1801217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * <p>
1802217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Some codecs may support multiple complexity levels, where higher
1803217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * complexity values use more encoder tools (e.g. perform more
1804217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * intensive calculations) to improve the quality or the compression
1805217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * ratio.  Use a lower value to save power and/or time.
1806217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         */
1807217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public Range<Integer> getComplexityRange() {
1808217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return mComplexityRange;
1809217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1810217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1811217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /** Constant quality mode */
1812217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public static final int BITRATE_MODE_CQ = 0;
1813217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /** Variable bitrate mode */
1814217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public static final int BITRATE_MODE_VBR = 1;
1815217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /** Constant bitrate mode */
1816217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public static final int BITRATE_MODE_CBR = 2;
1817217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1818217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private static final Feature[] bitrates = new Feature[] {
1819217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            new Feature("VBR", BITRATE_MODE_VBR, true),
1820217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            new Feature("CBR", BITRATE_MODE_CBR, false),
1821217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            new Feature("CQ",  BITRATE_MODE_CQ,  false)
1822b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        };
1823b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
1824217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private static int parseBitrateMode(String mode) {
1825217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            for (Feature feat: bitrates) {
1826217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (feat.mName.equalsIgnoreCase(mode)) {
1827217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    return feat.mValue;
1828217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
1829217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
1830217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return 0;
1831b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
1832b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
1833b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        /**
1834217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar         * Query whether a bitrate mode is supported.
1835b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar         */
1836217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public boolean isBitrateModeSupported(int mode) {
1837217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            for (Feature feat: bitrates) {
1838217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (mode == feat.mValue) {
1839217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    return (mBitControl & (1 << mode)) != 0;
1840217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
1841217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
1842217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return false;
1843b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
1844b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
1845217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private Range<Integer> mQualityRange;
1846217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private Range<Integer> mComplexityRange;
1847217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private CodecCapabilities mParent;
1848217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1849217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /* no public constructor */
1850217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private EncoderCapabilities() { }
1851217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1852b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        /** @hide */
1853217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public static EncoderCapabilities create(
1854217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                MediaFormat info, CodecCapabilities parent) {
1855217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            EncoderCapabilities caps = new EncoderCapabilities();
1856217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            caps.init(info, parent);
1857217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return caps;
1858217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1859217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1860217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /** @hide */
1861217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public void init(MediaFormat info, CodecCapabilities parent) {
1862217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // no support for complexity or quality yet
1863217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mParent = parent;
1864217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mComplexityRange = Range.create(0, 0);
1865217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mQualityRange = Range.create(0, 0);
1866217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mBitControl = (1 << BITRATE_MODE_VBR);
1867217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1868217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            applyLevelLimits();
1869217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            parseFromInfo(info);
1870217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1871217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1872217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private void applyLevelLimits() {
1873217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            String mime = mParent.getMimeType();
1874217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_FLAC)) {
1875217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                mComplexityRange = Range.create(0, 8);
1876217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                mBitControl = (1 << BITRATE_MODE_CQ);
1877217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AMR_NB)
1878217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    || mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AMR_WB)
1879217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    || mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_G711_ALAW)
1880217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    || mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_G711_MLAW)
1881217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    || mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_MSGSM)) {
1882217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                mBitControl = (1 << BITRATE_MODE_CBR);
1883217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
1884217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1885217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1886217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private int mBitControl;
1887217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private Integer mDefaultComplexity;
1888217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private Integer mDefaultQuality;
1889217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private String mQualityScale;
1890217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1891217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private void parseFromInfo(MediaFormat info) {
1892217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            Map<String, Object> map = info.getMap();
1893217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1894217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (info.containsKey("complexity-range")) {
1895217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                mComplexityRange = Utils
1896217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        .parseIntRange(info.getString("complexity-range"), mComplexityRange);
1897217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                // TODO should we limit this to level limits?
1898217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
1899217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (info.containsKey("quality-range")) {
1900217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                mQualityRange = Utils
1901217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        .parseIntRange(info.getString("quality-range"), mQualityRange);
1902217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
1903217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (info.containsKey("feature-bitrate-control")) {
1904217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                for (String mode: info.getString("feature-bitrate-control").split(",")) {
1905217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    mBitControl |= parseBitrateMode(mode);
1906217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
1907217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
1908217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1909217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            try {
1910217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                mDefaultComplexity = Integer.parseInt((String)map.get("complexity-default"));
1911217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            } catch (NumberFormatException e) { }
1912217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1913217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            try {
1914217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                mDefaultQuality = Integer.parseInt((String)map.get("quality-default"));
1915217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            } catch (NumberFormatException e) { }
1916217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1917217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            mQualityScale = (String)map.get("quality-scale");
1918217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1919217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1920217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        private boolean supports(
1921217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                Integer complexity, Integer quality, Integer profile) {
1922217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            boolean ok = true;
1923217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (ok && complexity != null) {
1924217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                ok = mComplexityRange.contains(complexity);
1925217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
1926217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (ok && quality != null) {
1927217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                ok = mQualityRange.contains(quality);
1928217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
1929217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (ok && profile != null) {
1930217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                for (CodecProfileLevel pl: mParent.profileLevels) {
1931217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    if (pl.profile == profile) {
1932217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        profile = null;
1933217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                        break;
1934217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    }
1935217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
1936217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                ok = profile == null;
1937217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
1938217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return ok;
1939217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1940217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1941217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /** @hide */
1942217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public void setDefaultFormat(MediaFormat format) {
1943217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // don't list trivial quality/complexity as default for now
1944217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (!mQualityRange.getUpper().equals(mQualityRange.getLower())
1945217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    && mDefaultQuality != null) {
1946217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                format.setInteger(MediaFormat.KEY_QUALITY, mDefaultQuality);
1947217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
1948217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (!mComplexityRange.getUpper().equals(mComplexityRange.getLower())
1949217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    && mDefaultComplexity != null) {
1950217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                format.setInteger(MediaFormat.KEY_COMPLEXITY, mDefaultComplexity);
1951217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
1952217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // bitrates are listed in order of preference
1953217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            for (Feature feat: bitrates) {
1954217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if ((mBitControl & (1 << feat.mValue)) != 0) {
1955217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    format.setInteger(MediaFormat.KEY_BITRATE_MODE, feat.mValue);
1956217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    break;
1957217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
1958217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
1959217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        }
1960217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1961217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        /** @hide */
1962217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar        public boolean supportsFormat(MediaFormat format) {
1963217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            final Map<String, Object> map = format.getMap();
1964217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            final String mime = mParent.getMimeType();
1965217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1966217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            Integer mode = (Integer)map.get(MediaFormat.KEY_BITRATE_MODE);
1967217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (mode != null && !isBitrateModeSupported(mode)) {
1968217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                return false;
1969217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
1970217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1971217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            Integer complexity = (Integer)map.get(MediaFormat.KEY_COMPLEXITY);
1972217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (MediaFormat.MIMETYPE_AUDIO_FLAC.equalsIgnoreCase(mime)) {
1973217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                Integer flacComplexity =
1974217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    (Integer)map.get(MediaFormat.KEY_FLAC_COMPRESSION_LEVEL);
1975217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (complexity == null) {
1976217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    complexity = flacComplexity;
1977217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                } else if (flacComplexity != null && complexity != flacComplexity) {
1978217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    throw new IllegalArgumentException(
1979217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            "conflicting values for complexity and " +
1980217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            "flac-compression-level");
1981217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
1982217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
1983217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1984217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            // other audio parameters
1985217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            Integer profile = (Integer)map.get(MediaFormat.KEY_PROFILE);
1986217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            if (MediaFormat.MIMETYPE_AUDIO_AAC.equalsIgnoreCase(mime)) {
1987217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                Integer aacProfile = (Integer)map.get(MediaFormat.KEY_AAC_PROFILE);
1988217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                if (profile == null) {
1989217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    profile = aacProfile;
1990217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                } else if (aacProfile != null && aacProfile != profile) {
1991217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                    throw new IllegalArgumentException(
1992217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                            "conflicting values for profile and aac-profile");
1993217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar                }
1994217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            }
1995217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1996217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            Integer quality = (Integer)map.get(MediaFormat.KEY_QUALITY);
1997217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar
1998217474682ab9c551f331a598cf99d4e8d50f2a8dLajos Molnar            return supports(complexity, quality, profile);
1999b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
200060d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber    };
200160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber
2002c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main    /**
2003c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main     * Encapsulates the profiles available for a codec component.
2004c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main     * <p>You can get a set of {@link MediaCodecInfo.CodecProfileLevel} objects for a given
2005c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main     * {@link MediaCodecInfo} object from the
2006c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main     * {@link MediaCodecInfo.CodecCapabilities#profileLevels} field.
2007c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main     */
200860d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber    public static final class CodecProfileLevel {
200960d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        // from OMX_VIDEO_AVCPROFILETYPE
201060d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCProfileBaseline = 0x01;
201160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCProfileMain     = 0x02;
201260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCProfileExtended = 0x04;
201360d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCProfileHigh     = 0x08;
201460d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCProfileHigh10   = 0x10;
201560d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCProfileHigh422  = 0x20;
201660d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCProfileHigh444  = 0x40;
201760d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber
201860d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        // from OMX_VIDEO_AVCLEVELTYPE
201960d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCLevel1       = 0x01;
202060d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCLevel1b      = 0x02;
202160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCLevel11      = 0x04;
202260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCLevel12      = 0x08;
202360d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCLevel13      = 0x10;
202460d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCLevel2       = 0x20;
202560d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCLevel21      = 0x40;
202660d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCLevel22      = 0x80;
202760d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCLevel3       = 0x100;
202860d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCLevel31      = 0x200;
202960d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCLevel32      = 0x400;
203060d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCLevel4       = 0x800;
203160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCLevel41      = 0x1000;
203260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCLevel42      = 0x2000;
203360d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCLevel5       = 0x4000;
203460d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AVCLevel51      = 0x8000;
2035b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        public static final int AVCLevel52      = 0x10000;
203660d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber
203760d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        // from OMX_VIDEO_H263PROFILETYPE
203860d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int H263ProfileBaseline             = 0x01;
203960d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int H263ProfileH320Coding           = 0x02;
204060d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int H263ProfileBackwardCompatible   = 0x04;
204160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int H263ProfileISWV2                = 0x08;
204260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int H263ProfileISWV3                = 0x10;
204360d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int H263ProfileHighCompression      = 0x20;
204460d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int H263ProfileInternet             = 0x40;
204560d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int H263ProfileInterlace            = 0x80;
204660d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int H263ProfileHighLatency          = 0x100;
204760d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber
204860d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        // from OMX_VIDEO_H263LEVELTYPE
204960d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int H263Level10      = 0x01;
205060d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int H263Level20      = 0x02;
205160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int H263Level30      = 0x04;
205260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int H263Level40      = 0x08;
205360d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int H263Level45      = 0x10;
205460d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int H263Level50      = 0x20;
205560d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int H263Level60      = 0x40;
205660d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int H263Level70      = 0x80;
205760d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber
205860d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        // from OMX_VIDEO_MPEG4PROFILETYPE
205960d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4ProfileSimple              = 0x01;
206060d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4ProfileSimpleScalable      = 0x02;
206160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4ProfileCore                = 0x04;
206260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4ProfileMain                = 0x08;
206360d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4ProfileNbit                = 0x10;
206460d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4ProfileScalableTexture     = 0x20;
206560d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4ProfileSimpleFace          = 0x40;
206660d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4ProfileSimpleFBA           = 0x80;
206760d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4ProfileBasicAnimated       = 0x100;
206860d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4ProfileHybrid              = 0x200;
206960d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4ProfileAdvancedRealTime    = 0x400;
207060d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4ProfileCoreScalable        = 0x800;
207160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4ProfileAdvancedCoding      = 0x1000;
207260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4ProfileAdvancedCore        = 0x2000;
207360d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4ProfileAdvancedScalable    = 0x4000;
207460d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4ProfileAdvancedSimple      = 0x8000;
207560d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber
207660d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        // from OMX_VIDEO_MPEG4LEVELTYPE
207760d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4Level0      = 0x01;
207860d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4Level0b     = 0x02;
207960d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4Level1      = 0x04;
208060d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4Level2      = 0x08;
208160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4Level3      = 0x10;
208260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4Level4      = 0x20;
208360d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4Level4a     = 0x40;
208460d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int MPEG4Level5      = 0x80;
208560d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber
208660d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        // from OMX_AUDIO_AACPROFILETYPE
208760d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AACObjectMain       = 1;
208860d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AACObjectLC         = 2;
208960d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AACObjectSSR        = 3;
209060d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AACObjectLTP        = 4;
209160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AACObjectHE         = 5;
209260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AACObjectScalable   = 6;
209360d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AACObjectERLC       = 17;
209460d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AACObjectLD         = 23;
209560d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AACObjectHE_PS      = 29;
209660d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public static final int AACObjectELD        = 39;
209760d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber
2098e72409fe779f620382c5bd0b82f4a32ac91d9fe4Kunter Gultekin        // from OMX_VIDEO_VP8LEVELTYPE
2099e72409fe779f620382c5bd0b82f4a32ac91d9fe4Kunter Gultekin        public static final int VP8Level_Version0 = 0x01;
2100e72409fe779f620382c5bd0b82f4a32ac91d9fe4Kunter Gultekin        public static final int VP8Level_Version1 = 0x02;
2101e72409fe779f620382c5bd0b82f4a32ac91d9fe4Kunter Gultekin        public static final int VP8Level_Version2 = 0x04;
2102e72409fe779f620382c5bd0b82f4a32ac91d9fe4Kunter Gultekin        public static final int VP8Level_Version3 = 0x08;
2103e72409fe779f620382c5bd0b82f4a32ac91d9fe4Kunter Gultekin
2104e72409fe779f620382c5bd0b82f4a32ac91d9fe4Kunter Gultekin        // from OMX_VIDEO_VP8PROFILETYPE
2105e72409fe779f620382c5bd0b82f4a32ac91d9fe4Kunter Gultekin        public static final int VP8ProfileMain = 0x01;
2106e72409fe779f620382c5bd0b82f4a32ac91d9fe4Kunter Gultekin
2107aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        // from OMX_VIDEO_HEVCPROFILETYPE
2108aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCProfileMain   = 0x01;
2109aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCProfileMain10 = 0x02;
2110aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad
2111aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        // from OMX_VIDEO_HEVCLEVELTYPE
2112aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCMainTierLevel1  = 0x1;
2113aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCHighTierLevel1  = 0x2;
2114aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCMainTierLevel2  = 0x4;
2115aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCHighTierLevel2  = 0x8;
2116aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCMainTierLevel21 = 0x10;
2117aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCHighTierLevel21 = 0x20;
2118aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCMainTierLevel3  = 0x40;
2119aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCHighTierLevel3  = 0x80;
2120aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCMainTierLevel31 = 0x100;
2121aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCHighTierLevel31 = 0x200;
2122aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCMainTierLevel4  = 0x400;
2123aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCHighTierLevel4  = 0x800;
2124aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCMainTierLevel41 = 0x1000;
2125aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCHighTierLevel41 = 0x2000;
2126aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCMainTierLevel5  = 0x4000;
2127aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCHighTierLevel5  = 0x8000;
2128aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCMainTierLevel51 = 0x10000;
2129aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCHighTierLevel51 = 0x20000;
2130aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCMainTierLevel52 = 0x40000;
2131aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCHighTierLevel52 = 0x80000;
2132aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCMainTierLevel6  = 0x100000;
2133aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCHighTierLevel6  = 0x200000;
2134aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCMainTierLevel61 = 0x400000;
2135aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCHighTierLevel61 = 0x800000;
2136aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCMainTierLevel62 = 0x1000000;
2137aca5de7ca13b0a92e64379913aee6c20e7e2e08eRachad        public static final int HEVCHighTierLevel62 = 0x2000000;
2138e72409fe779f620382c5bd0b82f4a32ac91d9fe4Kunter Gultekin
213960d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        /**
214060d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber         * Defined in the OpenMAX IL specs, depending on the type of media
214160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber         * this can be OMX_VIDEO_AVCPROFILETYPE, OMX_VIDEO_H263PROFILETYPE,
2142e72409fe779f620382c5bd0b82f4a32ac91d9fe4Kunter Gultekin         * OMX_VIDEO_MPEG4PROFILETYPE or OMX_VIDEO_VP8PROFILETYPE.
214360d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber         */
214460d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public int profile;
214560d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber
214660d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        /**
214760d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber         * Defined in the OpenMAX IL specs, depending on the type of media
214860d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber         * this can be OMX_VIDEO_AVCLEVELTYPE, OMX_VIDEO_H263LEVELTYPE
2149e72409fe779f620382c5bd0b82f4a32ac91d9fe4Kunter Gultekin         * OMX_VIDEO_MPEG4LEVELTYPE or OMX_VIDEO_VP8LEVELTYPE.
215060d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber         */
215160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        public int level;
215260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber    };
215360d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber
2154ba9269a5855b6d9d581af09077caafbd45180b41Andreas Huber    /**
2155ba9269a5855b6d9d581af09077caafbd45180b41Andreas Huber     * Enumerates the capabilities of the codec component. Since a single
2156ba9269a5855b6d9d581af09077caafbd45180b41Andreas Huber     * component can support data of a variety of types, the type has to be
2157ba9269a5855b6d9d581af09077caafbd45180b41Andreas Huber     * specified to yield a meaningful result.
2158c06bb7f5b9c6be9d121e3f5b4ee7cd31c99f6879Scott Main     * @param type The MIME type to query
2159ba9269a5855b6d9d581af09077caafbd45180b41Andreas Huber     */
216060d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber    public final CodecCapabilities getCapabilitiesForType(
216160d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber            String type) {
2162b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        CodecCapabilities caps = mCaps.get(type);
2163b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        if (caps == null) {
2164b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            throw new IllegalArgumentException("codec does not support type");
2165b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
2166b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        // clone writable object
2167b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        return caps.dup();
2168b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    }
2169b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
2170b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    /** @hide */
2171b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    public MediaCodecInfo makeRegular() {
2172b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        ArrayList<CodecCapabilities> caps = new ArrayList<CodecCapabilities>();
2173b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        for (CodecCapabilities c: mCaps.values()) {
2174b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            if (c.isRegular()) {
2175b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                caps.add(c);
2176b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
2177b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
2178b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        if (caps.size() == 0) {
2179b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            return null;
2180b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        } else if (caps.size() == mCaps.size()) {
2181b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            return this;
2182b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
2183b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
2184b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        return new MediaCodecInfo(
2185b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                mName, mIsEncoder,
2186b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                caps.toArray(new CodecCapabilities[caps.size()]));
218760d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber    }
218860d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber}
2189