• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.media;
18 
19 import static android.media.audio.Flags.FLAG_IAMF_DEFINITIONS_API;
20 import static android.media.codec.Flags.FLAG_DYNAMIC_COLOR_ASPECTS;
21 import static android.media.codec.Flags.FLAG_HLG_EDITING;
22 import static android.media.codec.Flags.FLAG_IN_PROCESS_SW_AUDIO_CODEC;
23 import static android.media.codec.Flags.FLAG_NULL_OUTPUT_SURFACE;
24 import static android.media.codec.Flags.FLAG_REGION_OF_INTEREST;
25 import static android.media.codec.Flags.FLAG_APV_SUPPORT;
26 import static android.media.Utils.intersectSortedDistinctRanges;
27 import static android.media.Utils.sortDistinctRanges;
28 import static android.media.MediaCodec.GetFlag;
29 
30 import android.annotation.FlaggedApi;
31 import android.annotation.IntDef;
32 import android.annotation.IntRange;
33 import android.annotation.NonNull;
34 import android.annotation.Nullable;
35 import android.annotation.SuppressLint;
36 import android.annotation.TestApi;
37 import android.compat.annotation.UnsupportedAppUsage;
38 import android.os.Build;
39 import android.os.Process;
40 import android.os.SystemProperties;
41 import android.sysprop.MediaProperties;
42 import android.util.Log;
43 import android.util.Pair;
44 import android.util.Range;
45 import android.util.Rational;
46 import android.util.Size;
47 
48 import java.lang.annotation.Retention;
49 import java.lang.annotation.RetentionPolicy;
50 import java.util.ArrayList;
51 import java.util.Arrays;
52 import java.util.Collections;
53 import java.util.HashMap;
54 import java.util.List;
55 import java.util.Map;
56 import java.util.Set;
57 import java.util.Vector;
58 
59 /**
60  * Provides information about a given media codec available on the device. You can
61  * iterate through all codecs available by querying {@link MediaCodecList}. For example,
62  * here's how to find an encoder that supports a given MIME type:
63  * <pre>
64  * private static MediaCodecInfo selectCodec(String mimeType) {
65  *     int numCodecs = MediaCodecList.getCodecCount();
66  *     for (int i = 0; i &lt; numCodecs; i++) {
67  *         MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
68  *
69  *         if (!codecInfo.isEncoder()) {
70  *             continue;
71  *         }
72  *
73  *         String[] types = codecInfo.getSupportedTypes();
74  *         for (int j = 0; j &lt; types.length; j++) {
75  *             if (types[j].equalsIgnoreCase(mimeType)) {
76  *                 return codecInfo;
77  *             }
78  *         }
79  *     }
80  *     return null;
81  * }</pre>
82  *
83  */
84 public final class MediaCodecInfo {
85     private static final String TAG = "MediaCodecInfo";
86 
87     private static final int FLAG_IS_ENCODER = (1 << 0);
88     private static final int FLAG_IS_VENDOR = (1 << 1);
89     private static final int FLAG_IS_SOFTWARE_ONLY = (1 << 2);
90     private static final int FLAG_IS_HARDWARE_ACCELERATED = (1 << 3);
91 
92     private int mFlags;
93     private String mName;
94     private String mCanonicalName;
95     private Map<String, CodecCapabilities> mCaps;
96 
MediaCodecInfo( String name, String canonicalName, int flags, CodecCapabilities[] caps)97     /* package private */ MediaCodecInfo(
98             String name, String canonicalName, int flags, CodecCapabilities[] caps) {
99         mName = name;
100         mCanonicalName = canonicalName;
101         mFlags = flags;
102         mCaps = new HashMap<String, CodecCapabilities>();
103 
104         for (CodecCapabilities c: caps) {
105             mCaps.put(c.getMimeType(), c);
106         }
107     }
108 
109     /**
110      * Retrieve the codec name.
111      *
112      * <strong>Note:</strong> Implementations may provide multiple aliases (codec
113      * names) for the same underlying codec, any of which can be used to instantiate the same
114      * underlying codec in {@link MediaCodec#createByCodecName}.
115      *
116      * Applications targeting SDK < {@link android.os.Build.VERSION_CODES#Q}, cannot determine if
117      * the multiple codec names listed in MediaCodecList are in-fact for the same codec.
118      */
119     @NonNull
getName()120     public final String getName() {
121         return mName;
122     }
123 
124     /**
125      * Retrieve the underlying codec name.
126      *
127      * Device implementations may provide multiple aliases (codec names) for the same underlying
128      * codec to maintain backward app compatibility. This method returns the name of the underlying
129      * codec name, which must not be another alias. For non-aliases this is always the name of the
130      * codec.
131      */
132     @NonNull
getCanonicalName()133     public final String getCanonicalName() {
134         return mCanonicalName;
135     }
136 
137     /**
138      * Query if the codec is an alias for another underlying codec.
139      */
isAlias()140     public final boolean isAlias() {
141         return !mName.equals(mCanonicalName);
142     }
143 
144     /**
145      * Query if the codec is an encoder.
146      */
isEncoder()147     public final boolean isEncoder() {
148         return (mFlags & FLAG_IS_ENCODER) != 0;
149     }
150 
151     /**
152      * Query if the codec is provided by the Android platform (false) or the device manufacturer
153      * (true).
154      */
isVendor()155     public final boolean isVendor() {
156         return (mFlags & FLAG_IS_VENDOR) != 0;
157     }
158 
159     /**
160      * Query if the codec is software only. Software-only codecs are more secure as they run in
161      * a tighter security sandbox. On the other hand, software-only codecs do not provide any
162      * performance guarantees.
163      */
isSoftwareOnly()164     public final boolean isSoftwareOnly() {
165         return (mFlags & FLAG_IS_SOFTWARE_ONLY) != 0;
166     }
167 
168     /**
169      * Query if the codec is hardware accelerated. This attribute is provided by the device
170      * manufacturer. Note that it cannot be tested for correctness.
171      */
isHardwareAccelerated()172     public final boolean isHardwareAccelerated() {
173         return (mFlags & FLAG_IS_HARDWARE_ACCELERATED) != 0;
174     }
175 
176     /**
177      * Query the media types supported by the codec.
178      */
getSupportedTypes()179     public final String[] getSupportedTypes() {
180         Set<String> typeSet = mCaps.keySet();
181         String[] types = typeSet.toArray(new String[typeSet.size()]);
182         Arrays.sort(types);
183         return types;
184     }
185 
checkPowerOfTwo(int value, String message)186     private static int checkPowerOfTwo(int value, String message) {
187         if ((value & (value - 1)) != 0) {
188             throw new IllegalArgumentException(message);
189         }
190         return value;
191     }
192 
193     private static class Feature {
194         public String mName;
195         public int mValue;
196         public boolean mDefault;
197         public boolean mInternal;
Feature(String name, int value, boolean def)198         public Feature(String name, int value, boolean def) {
199             this(name, value, def, false /* internal */);
200         }
Feature(String name, int value, boolean def, boolean internal)201         public Feature(String name, int value, boolean def, boolean internal) {
202             mName = name;
203             mValue = value;
204             mDefault = def;
205             mInternal = internal;
206         }
207     }
208 
209     // COMMON CONSTANTS
210     private static final Range<Integer> POSITIVE_INTEGERS =
211             Range.create(1, Integer.MAX_VALUE);
212     private static final Range<Long> POSITIVE_LONGS =
213             Range.create(1L, Long.MAX_VALUE);
214     private static final Range<Rational> POSITIVE_RATIONALS =
215             Range.create(new Rational(1, Integer.MAX_VALUE),
216                          new Rational(Integer.MAX_VALUE, 1));
217     private static final Range<Integer> FRAME_RATE_RANGE = Range.create(0, 960);
218     private static final Range<Integer> BITRATE_RANGE = Range.create(0, 500000000);
219     private static final int DEFAULT_MAX_SUPPORTED_INSTANCES = 32;
220     private static final int MAX_SUPPORTED_INSTANCES_LIMIT = 256;
221 
222     private static Range<Integer> SIZE_RANGE;
getSizeRange()223     private static synchronized Range<Integer> getSizeRange() {
224         if (SIZE_RANGE == null) {
225             SIZE_RANGE = Process.is64Bit()
226                     ? Range.create(1, 32768)
227                     : Range.create(1, MediaProperties.resolution_limit_32bit().orElse(4096));
228         }
229         return SIZE_RANGE;
230     }
231 
232     // found stuff that is not supported by framework (=> this should not happen)
233     private static final int ERROR_UNRECOGNIZED   = (1 << 0);
234     // found profile/level for which we don't have capability estimates
235     private static final int ERROR_UNSUPPORTED    = (1 << 1);
236     // have not found any profile/level for which we don't have capability estimate
237     private static final int ERROR_NONE_SUPPORTED = (1 << 2);
238 
239 
240     /**
241      * Encapsulates the capabilities of a given codec component.
242      * For example, what profile/level combinations it supports and what colorspaces
243      * it is capable of providing the decoded data in, as well as some
244      * codec-type specific capability flags.
245      * <p>You can get an instance for a given {@link MediaCodecInfo} object with
246      * {@link MediaCodecInfo#getCapabilitiesForType getCapabilitiesForType()}, passing a MIME type.
247      */
248     public static final class CodecCapabilities {
CodecCapabilities()249         public CodecCapabilities() {
250         }
251 
252         // CLASSIFICATION
253         private String mMime;
254         private int mMaxSupportedInstances;
255 
256         // LEGACY FIELDS
257 
258         // Enumerates supported profile/level combinations as defined
259         // by the type of encoded data. These combinations impose restrictions
260         // on video resolution, bitrate... and limit the available encoder tools
261         // such as B-frame support, arithmetic coding...
262         public CodecProfileLevel[] profileLevels;  // NOTE this array is modifiable by user
263 
264         // from MediaCodecConstants
265         /** @deprecated Use {@link #COLOR_Format24bitBGR888}. */
266         public static final int COLOR_FormatMonochrome              = 1;
267         /** @deprecated Use {@link #COLOR_Format24bitBGR888}. */
268         public static final int COLOR_Format8bitRGB332              = 2;
269         /** @deprecated Use {@link #COLOR_Format24bitBGR888}. */
270         public static final int COLOR_Format12bitRGB444             = 3;
271         /** @deprecated Use {@link #COLOR_Format32bitABGR8888}. */
272         public static final int COLOR_Format16bitARGB4444           = 4;
273         /** @deprecated Use {@link #COLOR_Format32bitABGR8888}. */
274         public static final int COLOR_Format16bitARGB1555           = 5;
275 
276         /**
277          * 16 bits per pixel RGB color format, with 5-bit red & blue and 6-bit green component.
278          * <p>
279          * Using 16-bit little-endian representation, colors stored as Red 15:11, Green 10:5, Blue 4:0.
280          * <pre>
281          *            byte                   byte
282          *  <--------- i --------> | <------ i + 1 ------>
283          * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
284          * |     BLUE     |      GREEN      |     RED      |
285          * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
286          *  0           4  5     7   0     2  3           7
287          * bit
288          * </pre>
289          *
290          * This format corresponds to {@link android.graphics.PixelFormat#RGB_565} and
291          * {@link android.graphics.ImageFormat#RGB_565}.
292          */
293         public static final int COLOR_Format16bitRGB565             = 6;
294         /** @deprecated Use {@link #COLOR_Format16bitRGB565}. */
295         public static final int COLOR_Format16bitBGR565             = 7;
296         /** @deprecated Use {@link #COLOR_Format24bitBGR888}. */
297         public static final int COLOR_Format18bitRGB666             = 8;
298         /** @deprecated Use {@link #COLOR_Format32bitABGR8888}. */
299         public static final int COLOR_Format18bitARGB1665           = 9;
300         /** @deprecated Use {@link #COLOR_Format32bitABGR8888}. */
301         public static final int COLOR_Format19bitARGB1666           = 10;
302 
303         /** @deprecated Use {@link #COLOR_Format24bitBGR888} or {@link #COLOR_FormatRGBFlexible}. */
304         public static final int COLOR_Format24bitRGB888             = 11;
305 
306         /**
307          * 24 bits per pixel RGB color format, with 8-bit red, green & blue components.
308          * <p>
309          * Using 24-bit little-endian representation, colors stored as Red 7:0, Green 15:8, Blue 23:16.
310          * <pre>
311          *         byte              byte             byte
312          *  <------ i -----> | <---- i+1 ----> | <---- i+2 ----->
313          * +-----------------+-----------------+-----------------+
314          * |       RED       |      GREEN      |       BLUE      |
315          * +-----------------+-----------------+-----------------+
316          * </pre>
317          *
318          * This format corresponds to {@link android.graphics.PixelFormat#RGB_888}, and can also be
319          * represented as a flexible format by {@link #COLOR_FormatRGBFlexible}.
320          */
321         public static final int COLOR_Format24bitBGR888             = 12;
322         /** @deprecated Use {@link #COLOR_Format32bitABGR8888}. */
323         public static final int COLOR_Format24bitARGB1887           = 13;
324         /** @deprecated Use {@link #COLOR_Format32bitABGR8888}. */
325         public static final int COLOR_Format25bitARGB1888           = 14;
326 
327         /**
328          * @deprecated Use {@link #COLOR_Format32bitABGR8888} Or {@link #COLOR_FormatRGBAFlexible}.
329          */
330         public static final int COLOR_Format32bitBGRA8888           = 15;
331         /**
332          * @deprecated Use {@link #COLOR_Format32bitABGR8888} Or {@link #COLOR_FormatRGBAFlexible}.
333          */
334         public static final int COLOR_Format32bitARGB8888           = 16;
335         /** @deprecated Use {@link #COLOR_FormatYUV420Flexible}. */
336         public static final int COLOR_FormatYUV411Planar            = 17;
337         /** @deprecated Use {@link #COLOR_FormatYUV420Flexible}. */
338         public static final int COLOR_FormatYUV411PackedPlanar      = 18;
339         /** @deprecated Use {@link #COLOR_FormatYUV420Flexible}. */
340         public static final int COLOR_FormatYUV420Planar            = 19;
341         /** @deprecated Use {@link #COLOR_FormatYUV420Flexible}. */
342         public static final int COLOR_FormatYUV420PackedPlanar      = 20;
343         /** @deprecated Use {@link #COLOR_FormatYUV420Flexible}. */
344         public static final int COLOR_FormatYUV420SemiPlanar        = 21;
345 
346         /** @deprecated Use {@link #COLOR_FormatYUV422Flexible}. */
347         public static final int COLOR_FormatYUV422Planar            = 22;
348         /** @deprecated Use {@link #COLOR_FormatYUV422Flexible}. */
349         public static final int COLOR_FormatYUV422PackedPlanar      = 23;
350         /** @deprecated Use {@link #COLOR_FormatYUV422Flexible}. */
351         public static final int COLOR_FormatYUV422SemiPlanar        = 24;
352 
353         /** @deprecated Use {@link #COLOR_FormatYUV422Flexible}. */
354         public static final int COLOR_FormatYCbYCr                  = 25;
355         /** @deprecated Use {@link #COLOR_FormatYUV422Flexible}. */
356         public static final int COLOR_FormatYCrYCb                  = 26;
357         /** @deprecated Use {@link #COLOR_FormatYUV422Flexible}. */
358         public static final int COLOR_FormatCbYCrY                  = 27;
359         /** @deprecated Use {@link #COLOR_FormatYUV422Flexible}. */
360         public static final int COLOR_FormatCrYCbY                  = 28;
361 
362         /** @deprecated Use {@link #COLOR_FormatYUV444Flexible}. */
363         public static final int COLOR_FormatYUV444Interleaved       = 29;
364 
365         /**
366          * SMIA 8-bit Bayer format.
367          * Each byte represents the top 8-bits of a 10-bit signal.
368          */
369         public static final int COLOR_FormatRawBayer8bit            = 30;
370         /**
371          * SMIA 10-bit Bayer format.
372          */
373         public static final int COLOR_FormatRawBayer10bit           = 31;
374 
375         /**
376          * SMIA 8-bit compressed Bayer format.
377          * Each byte represents a sample from the 10-bit signal that is compressed into 8-bits
378          * using DPCM/PCM compression, as defined by the SMIA Functional Specification.
379          */
380         public static final int COLOR_FormatRawBayer8bitcompressed  = 32;
381 
382         /** @deprecated Use {@link #COLOR_FormatL8}. */
383         public static final int COLOR_FormatL2                      = 33;
384         /** @deprecated Use {@link #COLOR_FormatL8}. */
385         public static final int COLOR_FormatL4                      = 34;
386 
387         /**
388          * 8 bits per pixel Y color format.
389          * <p>
390          * Each byte contains a single pixel.
391          * This format corresponds to {@link android.graphics.PixelFormat#L_8}.
392          */
393         public static final int COLOR_FormatL8                      = 35;
394 
395         /**
396          * 16 bits per pixel, little-endian Y color format.
397          * <p>
398          * <pre>
399          *            byte                   byte
400          *  <--------- i --------> | <------ i + 1 ------>
401          * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
402          * |                       Y                       |
403          * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
404          *  0                    7   0                    7
405          * bit
406          * </pre>
407          */
408         public static final int COLOR_FormatL16                     = 36;
409         /** @deprecated Use {@link #COLOR_FormatL16}. */
410         public static final int COLOR_FormatL24                     = 37;
411 
412         /**
413          * 32 bits per pixel, little-endian Y color format.
414          * <p>
415          * <pre>
416          *         byte              byte             byte              byte
417          *  <------ i -----> | <---- i+1 ----> | <---- i+2 ----> | <---- i+3 ----->
418          * +-----------------+-----------------+-----------------+-----------------+
419          * |                                   Y                                   |
420          * +-----------------+-----------------+-----------------+-----------------+
421          *  0               7 0               7 0               7 0               7
422          * bit
423          * </pre>
424          *
425          * @deprecated Use {@link #COLOR_FormatL16}.
426          */
427         public static final int COLOR_FormatL32                     = 38;
428 
429         /** @deprecated Use {@link #COLOR_FormatYUV420Flexible}. */
430         public static final int COLOR_FormatYUV420PackedSemiPlanar  = 39;
431         /** @deprecated Use {@link #COLOR_FormatYUV422Flexible}. */
432         public static final int COLOR_FormatYUV422PackedSemiPlanar  = 40;
433 
434         /** @deprecated Use {@link #COLOR_Format24bitBGR888}. */
435         public static final int COLOR_Format18BitBGR666             = 41;
436 
437         /** @deprecated Use {@link #COLOR_Format32bitABGR8888}. */
438         public static final int COLOR_Format24BitARGB6666           = 42;
439         /** @deprecated Use {@link #COLOR_Format32bitABGR8888}. */
440         public static final int COLOR_Format24BitABGR6666           = 43;
441 
442         /**
443          * P010 is 10-bit-per component 4:2:0 YCbCr semiplanar format.
444          * <p>
445          * This format uses 24 allocated bits per pixel with 15 bits of
446          * data per pixel. Chroma planes are subsampled by 2 both
447          * horizontally and vertically. Each chroma and luma component
448          * has 16 allocated bits in little-endian configuration with 10
449          * MSB of actual data.
450          *
451          * <pre>
452          *            byte                   byte
453          *  <--------- i --------> | <------ i + 1 ------>
454          * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
455          * |     UNUSED      |      Y/Cb/Cr                |
456          * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
457          *  0               5 6   7 0                    7
458          * bit
459          * </pre>
460          *
461          * Use this format with {@link Image}. This format corresponds
462          * to {@link android.graphics.ImageFormat#YCBCR_P010}.
463          * <p>
464          */
465         @SuppressLint("AllUpper")
466         public static final int COLOR_FormatYUVP010                 = 54;
467 
468         /**
469          * P210 is 10-bit-per component 4:2:2 YCbCr semiplanar format.
470          * <p>
471          * This format uses 32 allocated bits per pixel with 20 bits of
472          * data per pixel. Chroma planes are subsampled by 2 both
473          * horizontally. Each chroma and luma component
474          * has 16 allocated bits in little-endian configuration with 10
475          * MSB of actual data.
476          *
477          * <pre>
478          *            byte                   byte
479          *  <--------- i --------> | <------ i + 1 ------>
480          * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
481          * |     UNUSED      |      Y/Cb/Cr                |
482          * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
483          *  0               5 6   7 0                    7
484          * bit
485          * </pre>
486          *
487          * Use this format with {@link Image}. This format corresponds
488          * to {@link android.graphics.ImageFormat#YCBCR_P210}.
489          * <p>
490          */
491         @SuppressLint("AllUpper")
492         @FlaggedApi(android.media.codec.Flags.FLAG_P210_FORMAT_SUPPORT)
493         public static final int COLOR_FormatYUVP210                 = 60;
494 
495         /** @deprecated Use {@link #COLOR_FormatYUV420Flexible}. */
496         public static final int COLOR_TI_FormatYUV420PackedSemiPlanar = 0x7f000100;
497         // COLOR_FormatSurface indicates that the data will be a GraphicBuffer metadata reference.
498         // Note: in OMX this is called OMX_COLOR_FormatAndroidOpaque.
499         public static final int COLOR_FormatSurface                   = 0x7F000789;
500 
501         /**
502          * 64 bits per pixel RGBA color format, with 16-bit signed
503          * floating point red, green, blue, and alpha components.
504          * <p>
505          *
506          * <pre>
507          *         byte              byte             byte              byte
508          *  <-- i -->|<- i+1 ->|<- i+2 ->|<- i+3 ->|<- i+4 ->|<- i+5 ->|<- i+6 ->|<- i+7 ->
509          * +---------+---------+-------------------+---------+---------+---------+---------+
510          * |        RED        |       GREEN       |       BLUE        |       ALPHA       |
511          * +---------+---------+-------------------+---------+---------+---------+---------+
512          *  0       7 0       7 0       7 0       7 0       7 0       7 0       7 0       7
513          * </pre>
514          *
515          * This corresponds to {@link android.graphics.PixelFormat#RGBA_F16}.
516          */
517         @SuppressLint("AllUpper")
518         public static final int COLOR_Format64bitABGRFloat            = 0x7F000F16;
519 
520         /**
521          * 32 bits per pixel RGBA color format, with 8-bit red, green, blue, and alpha components.
522          * <p>
523          * Using 32-bit little-endian representation, colors stored as Red 7:0, Green 15:8,
524          * Blue 23:16, and Alpha 31:24.
525          * <pre>
526          *         byte              byte             byte              byte
527          *  <------ i -----> | <---- i+1 ----> | <---- i+2 ----> | <---- i+3 ----->
528          * +-----------------+-----------------+-----------------+-----------------+
529          * |       RED       |      GREEN      |       BLUE      |      ALPHA      |
530          * +-----------------+-----------------+-----------------+-----------------+
531          * </pre>
532          *
533          * This corresponds to {@link android.graphics.PixelFormat#RGBA_8888}.
534          */
535         public static final int COLOR_Format32bitABGR8888             = 0x7F00A000;
536 
537         /**
538          * 32 bits per pixel RGBA color format, with 10-bit red, green,
539          * blue, and 2-bit alpha components.
540          * <p>
541          * Using 32-bit little-endian representation, colors stored as
542          * Red 9:0, Green 19:10, Blue 29:20, and Alpha 31:30.
543          * <pre>
544          *         byte              byte             byte              byte
545          *  <------ i -----> | <---- i+1 ----> | <---- i+2 ----> | <---- i+3 ----->
546          * +-----------------+---+-------------+-------+---------+-----------+-----+
547          * |       RED           |      GREEN          |       BLUE          |ALPHA|
548          * +-----------------+---+-------------+-------+---------+-----------+-----+
549          *  0               7 0 1 2           7 0     3 4       7 0         5 6   7
550          * </pre>
551          *
552          * This corresponds to {@link android.graphics.PixelFormat#RGBA_1010102}.
553          */
554         @SuppressLint("AllUpper")
555         public static final int COLOR_Format32bitABGR2101010          = 0x7F00AAA2;
556 
557         /**
558          * Flexible 12 bits per pixel, subsampled YUV color format with 8-bit chroma and luma
559          * components.
560          * <p>
561          * Chroma planes are subsampled by 2 both horizontally and vertically.
562          * Use this format with {@link Image}.
563          * This format corresponds to {@link android.graphics.ImageFormat#YUV_420_888},
564          * and can represent the {@link #COLOR_FormatYUV411Planar},
565          * {@link #COLOR_FormatYUV411PackedPlanar}, {@link #COLOR_FormatYUV420Planar},
566          * {@link #COLOR_FormatYUV420PackedPlanar}, {@link #COLOR_FormatYUV420SemiPlanar}
567          * and {@link #COLOR_FormatYUV420PackedSemiPlanar} formats.
568          *
569          * @see Image#getFormat
570          */
571         public static final int COLOR_FormatYUV420Flexible            = 0x7F420888;
572 
573         /**
574          * Flexible 16 bits per pixel, subsampled YUV color format with 8-bit chroma and luma
575          * components.
576          * <p>
577          * Chroma planes are horizontally subsampled by 2. Use this format with {@link Image}.
578          * This format corresponds to {@link android.graphics.ImageFormat#YUV_422_888},
579          * and can represent the {@link #COLOR_FormatYCbYCr}, {@link #COLOR_FormatYCrYCb},
580          * {@link #COLOR_FormatCbYCrY}, {@link #COLOR_FormatCrYCbY},
581          * {@link #COLOR_FormatYUV422Planar}, {@link #COLOR_FormatYUV422PackedPlanar},
582          * {@link #COLOR_FormatYUV422SemiPlanar} and {@link #COLOR_FormatYUV422PackedSemiPlanar}
583          * formats.
584          *
585          * @see Image#getFormat
586          */
587         public static final int COLOR_FormatYUV422Flexible            = 0x7F422888;
588 
589         /**
590          * Flexible 24 bits per pixel YUV color format with 8-bit chroma and luma
591          * components.
592          * <p>
593          * Chroma planes are not subsampled. Use this format with {@link Image}.
594          * This format corresponds to {@link android.graphics.ImageFormat#YUV_444_888},
595          * and can represent the {@link #COLOR_FormatYUV444Interleaved} format.
596          * @see Image#getFormat
597          */
598         public static final int COLOR_FormatYUV444Flexible            = 0x7F444888;
599 
600         /**
601          * Flexible 24 bits per pixel RGB color format with 8-bit red, green and blue
602          * components.
603          * <p>
604          * Use this format with {@link Image}. This format corresponds to
605          * {@link android.graphics.ImageFormat#FLEX_RGB_888}, and can represent
606          * {@link #COLOR_Format24bitBGR888} and {@link #COLOR_Format24bitRGB888} formats.
607          * @see Image#getFormat()
608          */
609         public static final int COLOR_FormatRGBFlexible               = 0x7F36B888;
610 
611         /**
612          * Flexible 32 bits per pixel RGBA color format with 8-bit red, green, blue, and alpha
613          * components.
614          * <p>
615          * Use this format with {@link Image}. This format corresponds to
616          * {@link android.graphics.ImageFormat#FLEX_RGBA_8888}, and can represent
617          * {@link #COLOR_Format32bitBGRA8888}, {@link #COLOR_Format32bitABGR8888} and
618          * {@link #COLOR_Format32bitARGB8888} formats.
619          *
620          * @see Image#getFormat()
621          */
622         public static final int COLOR_FormatRGBAFlexible              = 0x7F36A888;
623 
624         /** @deprecated Use {@link #COLOR_FormatYUV420Flexible}. */
625         public static final int COLOR_QCOM_FormatYUV420SemiPlanar     = 0x7fa30c00;
626 
627         /**
628          * The color format for the media. This is one of the color constants defined in this class.
629          */
630         public int[] colorFormats; // NOTE this array is modifiable by user
631 
632         // FEATURES
633 
634         private int mFlagsSupported;
635         private int mFlagsRequired;
636         private int mFlagsVerified;
637 
638         /**
639          * <b>video decoder only</b>: codec supports seamless resolution changes.
640          */
641         public static final String FEATURE_AdaptivePlayback       = "adaptive-playback";
642 
643         /**
644          * <b>video decoder only</b>: codec supports secure decryption.
645          */
646         public static final String FEATURE_SecurePlayback         = "secure-playback";
647 
648         /**
649          * <b>video or audio decoder only</b>: codec supports tunneled playback.
650          */
651         public static final String FEATURE_TunneledPlayback       = "tunneled-playback";
652 
653         /**
654          * If true, the timestamp of each output buffer is derived from the timestamp of the input
655          * buffer that produced the output. If false, the timestamp of each output buffer is
656          * derived from the timestamp of the first input buffer.
657          */
658         public static final String FEATURE_DynamicTimestamp = "dynamic-timestamp";
659 
660         /**
661          * <b>decoder only</b>If true, the codec supports partial (including multiple) access units
662          * per input buffer.
663          */
664         public static final String FEATURE_FrameParsing = "frame-parsing";
665 
666         /**
667          * If true, the codec supports multiple access units (for decoding, or to output for
668          * encoders). If false, the codec only supports single access units. Producing multiple
669          * access units for output is an optional feature.
670          */
671         public static final String FEATURE_MultipleFrames = "multiple-frames";
672 
673         /**
674          * <b>video decoder only</b>: codec supports queuing partial frames.
675          */
676         public static final String FEATURE_PartialFrame = "partial-frame";
677 
678         /**
679          * <b>video encoder only</b>: codec supports intra refresh.
680          */
681         public static final String FEATURE_IntraRefresh = "intra-refresh";
682 
683         /**
684          * <b>decoder only</b>: codec supports low latency decoding.
685          * If supported, clients can enable the low latency mode for the decoder.
686          * When the mode is enabled, the decoder doesn't hold input and output data more than
687          * required by the codec standards.
688          */
689         public static final String FEATURE_LowLatency = "low-latency";
690 
691         /**
692          * Do not include in REGULAR_CODECS list in MediaCodecList.
693          */
694         private static final String FEATURE_SpecialCodec = "special-codec";
695 
696         /**
697          * <b>video encoder only</b>: codec supports quantization parameter bounds.
698          * @see MediaFormat#KEY_VIDEO_QP_MAX
699          * @see MediaFormat#KEY_VIDEO_QP_MIN
700          */
701         @SuppressLint("AllUpper")
702         public static final String FEATURE_QpBounds = "qp-bounds";
703 
704         /**
705          * <b>video encoder only</b>: codec supports exporting encoding statistics.
706          * Encoders with this feature can provide the App clients with the encoding statistics
707          * information about the frame.
708          * The scope of encoding statistics is controlled by
709          * {@link MediaFormat#KEY_VIDEO_ENCODING_STATISTICS_LEVEL}.
710          *
711          * @see MediaFormat#KEY_VIDEO_ENCODING_STATISTICS_LEVEL
712          */
713         @SuppressLint("AllUpper") // for consistency with other FEATURE_* constants
714         public static final String FEATURE_EncodingStatistics = "encoding-statistics";
715 
716         /**
717          * <b>video encoder only</b>: codec supports HDR editing.
718          * <p>
719          * HDR editing support means that the codec accepts 10-bit HDR
720          * input surface, and it is capable of generating any HDR
721          * metadata required from both YUV and RGB input when the
722          * metadata is not present. This feature is only meaningful when
723          * using an HDR capable profile (and 10-bit HDR input).
724          * <p>
725          * This feature implies that the codec is capable of encoding at
726          * least one HDR format, and that it supports RGBA_1010102 as
727          * well as P010, and optionally RGBA_FP16 input formats, and
728          * that the encoder can generate HDR metadata for all supported
729          * HDR input formats.
730          */
731         @SuppressLint("AllUpper")
732         public static final String FEATURE_HdrEditing = "hdr-editing";
733 
734         /**
735          * <b>video encoder only</b>: codec supports HLG editing.
736          * <p>
737          * HLG editing support means that the codec accepts 10-bit HDR
738          * input surface in both YUV and RGB pixel format. This feature
739          * is only meaningful when using a 10-bit (HLG) profile and
740          * 10-bit input.
741          * <p>
742          * This feature implies that the codec is capable of encoding
743          * 10-bit format, and that it supports RGBA_1010102 as
744          * well as P010, and optionally RGBA_FP16 input formats.
745          * <p>
746          * The difference between this feature and {@link
747          * FEATURE_HdrEditing} is that HLG does not require the
748          * generation of HDR metadata and does not use an explicit HDR
749          * profile.
750          */
751         @SuppressLint("AllUpper")
752         @FlaggedApi(FLAG_HLG_EDITING)
753         public static final String FEATURE_HlgEditing = "hlg-editing";
754 
755         /**
756          * <b>video decoder only</b>: codec supports dynamically
757          * changing color aspects.
758          * <p>
759          * If true, the codec can propagate color aspect changes during
760          * decoding. This is only meaningful at session boundaries, e.g.
761          * upon processing Picture Parameter Sets prior to a new IDR.
762          * The color aspects may come from the bitstream, or may be
763          * provided using {@link MediaCodec#setParameters} calls.
764          * <p>
765          * If the codec supports both 8-bit and 10-bit profiles, this
766          * feature means that the codec can dynamically switch between 8
767          * and 10-bit profiles, but this is restricted to Surface mode
768          * only.
769          * <p>
770          * If the device supports HDR transfer functions, switching
771          * between SDR and HDR transfer is also supported. Together with
772          * the previous clause this means that switching between SDR and
773          * HDR sessions are supported in Surface mode, as SDR is
774          * typically encoded at 8-bit and HDR at 10-bit.
775          */
776         @SuppressLint("AllUpper")
777         @FlaggedApi(FLAG_DYNAMIC_COLOR_ASPECTS)
778         public static final String FEATURE_DynamicColorAspects = "dynamic-color-aspects";
779 
780         /**
781          * <b>video encoder only</b>: codec supports region of interest encoding.
782          * <p>
783          * RoI encoding support means the codec accepts information that specifies the relative
784          * importance of different portions of each video frame. This allows the encoder to
785          * separate a video frame into critical and non-critical regions, and use more bits
786          * (better quality) to represent the critical regions and de-prioritize non-critical
787          * regions. In other words, the encoder chooses a negative qp bias for the critical
788          * portions and a zero or positive qp bias for the non-critical portions.
789          * <p>
790          * At a basic level, if the encoder decides to encode each frame with a uniform
791          * quantization value 'qpFrame' and a 'qpBias' is chosen/suggested for an LCU of the
792          * frame, then the actual qp of the LCU will be 'qpFrame + qpBias', although this value
793          * can be clamped basing on the min-max configured qp bounds for the current encoding
794          * session.
795          * <p>
796          * In a shot, if a group of LCUs pan out quickly they can be marked as non-critical
797          * thereby enabling the encoder to reserve fewer bits during their encoding. Contrarily,
798          * LCUs that remain in shot for a prolonged duration can be encoded at better quality in
799          * one frame thereby setting-up an excellent long-term reference for all future frames.
800          * <p>
801          * Note that by offsetting the quantization of each LCU, the overall bit allocation will
802          * differ from the originally estimated bit allocation, and the encoder will adjust the
803          * frame quantization for subsequent frames to meet the bitrate target. An effective
804          * selection of critical regions can set-up a golden reference and this can compensate
805          * for the bit burden that was introduced due to encoding RoI's at better quality.
806          * On the other hand, an ineffective choice of critical regions might increase the
807          * quality of certain parts of the image but this can hamper quality in subsequent frames.
808          * <p>
809          * @see MediaCodec#PARAMETER_KEY_QP_OFFSET_MAP
810          * @see MediaCodec#PARAMETER_KEY_QP_OFFSET_RECTS
811          */
812         @SuppressLint("AllUpper")
813         @FlaggedApi(FLAG_REGION_OF_INTEREST)
814         public static final String FEATURE_Roi = "region-of-interest";
815 
816         /**
817          * <b>video decoder only</b>: codec supports detaching the
818          * output surface when in Surface mode.
819          * <p> If true, the codec can be configured in Surface mode
820          * without an actual surface (in detached surface mode).
821          * @see MediaCodec#CONFIGURE_FLAG_DETACHED_SURFACE
822          */
823         @SuppressLint("AllUpper")
824         @FlaggedApi(FLAG_NULL_OUTPUT_SURFACE)
825         public static final String FEATURE_DetachedSurface = "detached-surface";
826 
827         /**
828          * Query codec feature capabilities.
829          * <p>
830          * These features are supported to be used by the codec.  These
831          * include optional features that can be turned on, as well as
832          * features that are always on.
833          */
isFeatureSupported(String name)834         public final boolean isFeatureSupported(String name) {
835             return checkFeature(name, mFlagsSupported);
836         }
837 
838         /**
839          * Query codec feature requirements.
840          * <p>
841          * These features are required to be used by the codec, and as such,
842          * they are always turned on.
843          */
isFeatureRequired(String name)844         public final boolean isFeatureRequired(String name) {
845             return checkFeature(name, mFlagsRequired);
846         }
847 
848         // Flags are used for feature list creation so separate this into a private
849         // static class to delay reading the flags only when constructing the list.
850         private static class FeatureList {
getDecoderFeatures()851             private static Feature[] getDecoderFeatures() {
852                 ArrayList<Feature> features = new ArrayList();
853                 features.add(new Feature(FEATURE_AdaptivePlayback, (1 << 0), true));
854                 features.add(new Feature(FEATURE_SecurePlayback,   (1 << 1), false));
855                 features.add(new Feature(FEATURE_TunneledPlayback, (1 << 2), false));
856                 features.add(new Feature(FEATURE_PartialFrame,     (1 << 3), false));
857                 features.add(new Feature(FEATURE_FrameParsing,     (1 << 4), false));
858                 features.add(new Feature(FEATURE_MultipleFrames,   (1 << 5), false));
859                 features.add(new Feature(FEATURE_DynamicTimestamp, (1 << 6), false));
860                 features.add(new Feature(FEATURE_LowLatency,       (1 << 7), true));
861                 if (GetFlag(() -> android.media.codec.Flags.dynamicColorAspects())) {
862                     features.add(new Feature(FEATURE_DynamicColorAspects, (1 << 8), true));
863                 }
864                 if (GetFlag(() -> android.media.codec.Flags.nullOutputSurface())) {
865                     features.add(new Feature(FEATURE_DetachedSurface,     (1 << 9), true));
866                 }
867 
868                 // feature to exclude codec from REGULAR codec list
869                 features.add(new Feature(FEATURE_SpecialCodec,     (1 << 30), false, true));
870 
871                 return features.toArray(new Feature[0]);
872             };
873 
874             private static Feature[] decoderFeatures = getDecoderFeatures();
875 
getEncoderFeatures()876             private static Feature[] getEncoderFeatures() {
877                 ArrayList<Feature> features = new ArrayList();
878 
879                 features.add(new Feature(FEATURE_IntraRefresh, (1 << 0), false));
880                 features.add(new Feature(FEATURE_MultipleFrames, (1 << 1), false));
881                 features.add(new Feature(FEATURE_DynamicTimestamp, (1 << 2), false));
882                 features.add(new Feature(FEATURE_QpBounds, (1 << 3), false));
883                 features.add(new Feature(FEATURE_EncodingStatistics, (1 << 4), false));
884                 features.add(new Feature(FEATURE_HdrEditing, (1 << 5), false));
885                 if (GetFlag(() -> android.media.codec.Flags.hlgEditing())) {
886                     features.add(new Feature(FEATURE_HlgEditing, (1 << 6), true));
887                 }
888                 if (GetFlag(() -> android.media.codec.Flags.regionOfInterest())) {
889                     features.add(new Feature(FEATURE_Roi, (1 << 7), true));
890                 }
891 
892                 // feature to exclude codec from REGULAR codec list
893                 features.add(new Feature(FEATURE_SpecialCodec,     (1 << 30), false, true));
894 
895                 return features.toArray(new Feature[0]);
896             };
897 
898             private static Feature[] encoderFeatures = getEncoderFeatures();
899 
getFeatures(boolean isEncoder)900             public static Feature[] getFeatures(boolean isEncoder) {
901                 if (isEncoder) {
902                     return encoderFeatures;
903                 } else {
904                     return decoderFeatures;
905                 }
906             }
907         }
908 
909         /** @hide */
validFeatures()910         public String[] validFeatures() {
911             Feature[] features = getValidFeatures();
912             ArrayList<String> res = new ArrayList();
913             for (int i = 0; i < features.length; i++) {
914                 if (!features[i].mInternal) {
915                     res.add(features[i].mName);
916                 }
917             }
918             return res.toArray(new String[0]);
919         }
920 
getValidFeatures()921         private Feature[] getValidFeatures() {
922             return FeatureList.getFeatures(isEncoder());
923         }
924 
checkFeature(String name, int flags)925         private boolean checkFeature(String name, int flags) {
926             for (Feature feat: getValidFeatures()) {
927                 if (feat.mName.equals(name)) {
928                     return (flags & feat.mValue) != 0;
929                 }
930             }
931             return false;
932         }
933 
934         /** @hide */
isRegular()935         public boolean isRegular() {
936             // regular codecs only require default features
937             for (Feature feat: getValidFeatures()) {
938                 if (!feat.mDefault && isFeatureRequired(feat.mName)) {
939                     return false;
940                 }
941             }
942             return true;
943         }
944 
945         /**
946          * Query whether codec supports a given {@link MediaFormat}.
947          *
948          * <p class=note>
949          * <strong>Note:</strong> On {@link android.os.Build.VERSION_CODES#LOLLIPOP},
950          * {@code format} must not contain a {@linkplain MediaFormat#KEY_FRAME_RATE
951          * frame rate}. Use
952          * <code class=prettyprint>format.setString(MediaFormat.KEY_FRAME_RATE, null)</code>
953          * to clear any existing frame rate setting in the format.
954          * <p>
955          *
956          * The following table summarizes the format keys considered by this method.
957          * This is especially important to consider when targeting a higher SDK version than the
958          * minimum SDK version, as this method will disregard some keys on devices below the target
959          * SDK version.
960          *
961          * <table style="width: 0%">
962          *  <thead>
963          *   <tr>
964          *    <th rowspan=3>OS Version(s)</th>
965          *    <td colspan=3>{@code MediaFormat} keys considered for</th>
966          *   </tr><tr>
967          *    <th>Audio Codecs</th>
968          *    <th>Video Codecs</th>
969          *    <th>Encoders</th>
970          *   </tr>
971          *  </thead>
972          *  <tbody>
973          *   <tr>
974          *    <td>{@link android.os.Build.VERSION_CODES#LOLLIPOP}</td>
975          *    <td rowspan=3>{@link MediaFormat#KEY_MIME}<sup>*</sup>,<br>
976          *        {@link MediaFormat#KEY_SAMPLE_RATE},<br>
977          *        {@link MediaFormat#KEY_CHANNEL_COUNT},</td>
978          *    <td>{@link MediaFormat#KEY_MIME}<sup>*</sup>,<br>
979          *        {@link CodecCapabilities#FEATURE_AdaptivePlayback}<sup>D</sup>,<br>
980          *        {@link CodecCapabilities#FEATURE_SecurePlayback}<sup>D</sup>,<br>
981          *        {@link CodecCapabilities#FEATURE_TunneledPlayback}<sup>D</sup>,<br>
982          *        {@link MediaFormat#KEY_WIDTH},<br>
983          *        {@link MediaFormat#KEY_HEIGHT},<br>
984          *        <strong>no</strong> {@code KEY_FRAME_RATE}</td>
985          *    <td rowspan=10>as to the left, plus<br>
986          *        {@link MediaFormat#KEY_BITRATE_MODE},<br>
987          *        {@link MediaFormat#KEY_PROFILE}
988          *        (and/or {@link MediaFormat#KEY_AAC_PROFILE}<sup>~</sup>),<br>
989          *        <!-- {link MediaFormat#KEY_QUALITY},<br> -->
990          *        {@link MediaFormat#KEY_COMPLEXITY}
991          *        (and/or {@link MediaFormat#KEY_FLAC_COMPRESSION_LEVEL}<sup>~</sup>)</td>
992          *   </tr><tr>
993          *    <td>{@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1}</td>
994          *    <td rowspan=2>as above, plus<br>
995          *        {@link MediaFormat#KEY_FRAME_RATE}</td>
996          *   </tr><tr>
997          *    <td>{@link android.os.Build.VERSION_CODES#M}</td>
998          *   </tr><tr>
999          *    <td>{@link android.os.Build.VERSION_CODES#N}</td>
1000          *    <td rowspan=2>as above, plus<br>
1001          *        {@link MediaFormat#KEY_PROFILE},<br>
1002          *        <!-- {link MediaFormat#KEY_MAX_BIT_RATE},<br> -->
1003          *        {@link MediaFormat#KEY_BIT_RATE}</td>
1004          *    <td rowspan=2>as above, plus<br>
1005          *        {@link MediaFormat#KEY_PROFILE},<br>
1006          *        {@link MediaFormat#KEY_LEVEL}<sup>+</sup>,<br>
1007          *        <!-- {link MediaFormat#KEY_MAX_BIT_RATE},<br> -->
1008          *        {@link MediaFormat#KEY_BIT_RATE},<br>
1009          *        {@link CodecCapabilities#FEATURE_IntraRefresh}<sup>E</sup></td>
1010          *   </tr><tr>
1011          *    <td>{@link android.os.Build.VERSION_CODES#N_MR1}</td>
1012          *   </tr><tr>
1013          *    <td>{@link android.os.Build.VERSION_CODES#O}</td>
1014          *    <td rowspan=3 colspan=2>as above, plus<br>
1015          *        {@link CodecCapabilities#FEATURE_PartialFrame}<sup>D</sup></td>
1016          *   </tr><tr>
1017          *    <td>{@link android.os.Build.VERSION_CODES#O_MR1}</td>
1018          *   </tr><tr>
1019          *    <td>{@link android.os.Build.VERSION_CODES#P}</td>
1020          *   </tr><tr>
1021          *    <td>{@link android.os.Build.VERSION_CODES#Q}</td>
1022          *    <td colspan=2>as above, plus<br>
1023          *        {@link CodecCapabilities#FEATURE_FrameParsing}<sup>D</sup>,<br>
1024          *        {@link CodecCapabilities#FEATURE_MultipleFrames},<br>
1025          *        {@link CodecCapabilities#FEATURE_DynamicTimestamp}</td>
1026          *   </tr><tr>
1027          *    <td>{@link android.os.Build.VERSION_CODES#R}</td>
1028          *    <td colspan=2>as above, plus<br>
1029          *        {@link CodecCapabilities#FEATURE_LowLatency}<sup>D</sup></td>
1030          *   </tr>
1031          *   <tr>
1032          *    <td colspan=4>
1033          *     <p class=note><strong>Notes:</strong><br>
1034          *      *: must be specified; otherwise, method returns {@code false}.<br>
1035          *      +: method does not verify that the format parameters are supported
1036          *      by the specified level.<br>
1037          *      D: decoders only<br>
1038          *      E: encoders only<br>
1039          *      ~: if both keys are provided values must match
1040          *    </td>
1041          *   </tr>
1042          *  </tbody>
1043          * </table>
1044          *
1045          * @param format media format with optional feature directives.
1046          * @throws IllegalArgumentException if format is not a valid media format.
1047          * @return whether the codec capabilities support the given format
1048          *         and feature requests.
1049          */
isFormatSupported(MediaFormat format)1050         public final boolean isFormatSupported(MediaFormat format) {
1051             final Map<String, Object> map = format.getMap();
1052             final String mime = (String)map.get(MediaFormat.KEY_MIME);
1053 
1054             // mime must match if present
1055             if (mime != null && !mMime.equalsIgnoreCase(mime)) {
1056                 return false;
1057             }
1058 
1059             // check feature support
1060             for (Feature feat: getValidFeatures()) {
1061                 if (feat.mInternal) {
1062                     continue;
1063                 }
1064 
1065                 Integer yesNo = (Integer)map.get(MediaFormat.KEY_FEATURE_ + feat.mName);
1066                 if (yesNo == null) {
1067                     continue;
1068                 }
1069                 if ((yesNo == 1 && !isFeatureSupported(feat.mName)) ||
1070                         (yesNo == 0 && isFeatureRequired(feat.mName))) {
1071                     return false;
1072                 }
1073             }
1074 
1075             Integer profile = (Integer)map.get(MediaFormat.KEY_PROFILE);
1076             Integer level = (Integer)map.get(MediaFormat.KEY_LEVEL);
1077 
1078             if (profile != null) {
1079                 if (!supportsProfileLevel(profile, level)) {
1080                     return false;
1081                 }
1082 
1083                 // If we recognize this profile, check that this format is supported by the
1084                 // highest level supported by the codec for that profile. (Ignore specified
1085                 // level beyond the above profile/level check as level is only used as a
1086                 // guidance. E.g. AVC Level 1 CIF format is supported if codec supports level 1.1
1087                 // even though max size for Level 1 is QCIF. However, MPEG2 Simple Profile
1088                 // 1080p format is not supported even if codec supports Main Profile Level High,
1089                 // as Simple Profile does not support 1080p.
1090                 CodecCapabilities levelCaps = null;
1091                 int maxLevel = 0;
1092                 for (CodecProfileLevel pl : profileLevels) {
1093                     if (pl.profile == profile && pl.level > maxLevel) {
1094                         // H.263 levels are not completely ordered:
1095                         // Level45 support only implies Level10 support
1096                         if (!mMime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_H263)
1097                                 || pl.level != CodecProfileLevel.H263Level45
1098                                 || maxLevel == CodecProfileLevel.H263Level10) {
1099                             maxLevel = pl.level;
1100                         }
1101                     }
1102                 }
1103                 levelCaps = createFromProfileLevel(mMime, profile, maxLevel);
1104                 // We must remove the profile from this format otherwise levelCaps.isFormatSupported
1105                 // will get into this same condition and loop forever. Furthermore, since levelCaps
1106                 // does not contain features and bitrate specific keys, keep only keys relevant for
1107                 // a level check.
1108                 Map<String, Object> levelCriticalFormatMap = new HashMap<>(map);
1109                 final Set<String> criticalKeys =
1110                     isVideo() ? VideoCapabilities.VIDEO_LEVEL_CRITICAL_FORMAT_KEYS :
1111                     isAudio() ? AudioCapabilities.AUDIO_LEVEL_CRITICAL_FORMAT_KEYS :
1112                     null;
1113 
1114                 // critical keys will always contain KEY_MIME, but should also contain others to be
1115                 // meaningful
1116                 if (criticalKeys != null && criticalKeys.size() > 1 && levelCaps != null) {
1117                     levelCriticalFormatMap.keySet().retainAll(criticalKeys);
1118 
1119                     MediaFormat levelCriticalFormat = new MediaFormat(levelCriticalFormatMap);
1120                     if (!levelCaps.isFormatSupported(levelCriticalFormat)) {
1121                         return false;
1122                     }
1123                 }
1124             }
1125             if (mAudioCaps != null && !mAudioCaps.supportsFormat(format)) {
1126                 return false;
1127             }
1128             if (mVideoCaps != null && !mVideoCaps.supportsFormat(format)) {
1129                 return false;
1130             }
1131             if (mEncoderCaps != null && !mEncoderCaps.supportsFormat(format)) {
1132                 return false;
1133             }
1134             return true;
1135         }
1136 
supportsBitrate( Range<Integer> bitrateRange, MediaFormat format)1137         private static boolean supportsBitrate(
1138                 Range<Integer> bitrateRange, MediaFormat format) {
1139             Map<String, Object> map = format.getMap();
1140 
1141             // consider max bitrate over average bitrate for support
1142             Integer maxBitrate = (Integer)map.get(MediaFormat.KEY_MAX_BIT_RATE);
1143             Integer bitrate = (Integer)map.get(MediaFormat.KEY_BIT_RATE);
1144             if (bitrate == null) {
1145                 bitrate = maxBitrate;
1146             } else if (maxBitrate != null) {
1147                 bitrate = Math.max(bitrate, maxBitrate);
1148             }
1149 
1150             if (bitrate != null && bitrate > 0) {
1151                 return bitrateRange.contains(bitrate);
1152             }
1153 
1154             return true;
1155         }
1156 
supportsProfileLevel(int profile, Integer level)1157         private boolean supportsProfileLevel(int profile, Integer level) {
1158             for (CodecProfileLevel pl: profileLevels) {
1159                 if (pl.profile != profile) {
1160                     continue;
1161                 }
1162 
1163                 // No specific level requested
1164                 if (level == null) {
1165                     return true;
1166                 }
1167 
1168                 // AAC doesn't use levels
1169                 if (mMime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AAC)) {
1170                     return true;
1171                 }
1172 
1173                 // DTS doesn't use levels
1174                 if (mMime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_DTS)
1175                         || mMime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_DTS_HD)
1176                         || mMime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_DTS_UHD)) {
1177                     return true;
1178                 }
1179 
1180                 // H.263 levels are not completely ordered:
1181                 // Level45 support only implies Level10 support
1182                 if (mMime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_H263)) {
1183                     if (pl.level != level && pl.level == CodecProfileLevel.H263Level45
1184                             && level > CodecProfileLevel.H263Level10) {
1185                         continue;
1186                     }
1187                 }
1188 
1189                 // MPEG4 levels are not completely ordered:
1190                 // Level1 support only implies Level0 (and not Level0b) support
1191                 if (mMime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_MPEG4)) {
1192                     if (pl.level != level && pl.level == CodecProfileLevel.MPEG4Level1
1193                             && level > CodecProfileLevel.MPEG4Level0) {
1194                         continue;
1195                     }
1196                 }
1197 
1198                 // HEVC levels incorporate both tiers and levels. Verify tier support.
1199                 if (mMime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_HEVC)) {
1200                     boolean supportsHighTier =
1201                         (pl.level & CodecProfileLevel.HEVCHighTierLevels) != 0;
1202                     boolean checkingHighTier = (level & CodecProfileLevel.HEVCHighTierLevels) != 0;
1203                     // high tier levels are only supported by other high tier levels
1204                     if (checkingHighTier && !supportsHighTier) {
1205                         continue;
1206                     }
1207                 }
1208 
1209                 if (pl.level >= level) {
1210                     // if we recognize the listed profile/level, we must also recognize the
1211                     // profile/level arguments.
1212                     if (createFromProfileLevel(mMime, profile, pl.level) != null) {
1213                         return createFromProfileLevel(mMime, profile, level) != null;
1214                     }
1215                     return true;
1216                 }
1217             }
1218             return false;
1219         }
1220 
1221         // errors while reading profile levels - accessed from sister capabilities
1222         int mError;
1223 
1224         private static final String TAG = "CodecCapabilities";
1225 
1226         // NEW-STYLE CAPABILITIES
1227         // Capabilities for an audio codec.
1228         @Nullable
1229         private AudioCapabilities mAudioCaps;
1230         // Capabilities for a video codec.
1231         @Nullable
1232         private VideoCapabilities mVideoCaps;
1233         // Capabilities specific to an encoder (vs. a decoder).
1234         @Nullable
1235         private EncoderCapabilities mEncoderCaps;
1236         private MediaFormat mDefaultFormat;
1237 
1238         /**
1239          * Returns a MediaFormat object with default values for configurations that have
1240          * defaults.
1241          */
getDefaultFormat()1242         public MediaFormat getDefaultFormat() {
1243             return mDefaultFormat;
1244         }
1245 
1246         /**
1247          * Returns the mime type for which this codec-capability object was created.
1248          */
getMimeType()1249         public String getMimeType() {
1250             return mMime;
1251         }
1252 
1253         /**
1254          * Returns the max number of the supported concurrent codec instances.
1255          * <p>
1256          * This is a hint for an upper bound. Applications should not expect to successfully
1257          * operate more instances than the returned value, but the actual number of
1258          * concurrently operable instances may be less as it depends on the available
1259          * resources at time of use.
1260          */
getMaxSupportedInstances()1261         public int getMaxSupportedInstances() {
1262             return mMaxSupportedInstances;
1263         }
1264 
isAudio()1265         private boolean isAudio() {
1266             return mAudioCaps != null;
1267         }
1268 
1269         /**
1270          * Returns the audio capabilities or {@code null} if this is not an audio codec.
1271          */
1272         @Nullable
getAudioCapabilities()1273         public AudioCapabilities getAudioCapabilities() {
1274             return mAudioCaps;
1275         }
1276 
isEncoder()1277         private boolean isEncoder() {
1278             return mEncoderCaps != null;
1279         }
1280 
1281         /**
1282          * Returns the encoding capabilities or {@code null} if this is not an encoder.
1283          */
1284         @Nullable
getEncoderCapabilities()1285         public EncoderCapabilities getEncoderCapabilities() {
1286             return mEncoderCaps;
1287         }
1288 
isVideo()1289         private boolean isVideo() {
1290             return mVideoCaps != null;
1291         }
1292 
1293         /**
1294          * Returns the video capabilities or {@code null} if this is not a video codec.
1295          */
1296         @Nullable
getVideoCapabilities()1297         public VideoCapabilities getVideoCapabilities() {
1298             return mVideoCaps;
1299         }
1300 
1301         /** @hide */
dup()1302         public CodecCapabilities dup() {
1303             CodecCapabilities caps = new CodecCapabilities();
1304 
1305             // profileLevels and colorFormats may be modified by client.
1306             caps.profileLevels = Arrays.copyOf(profileLevels, profileLevels.length);
1307             caps.colorFormats = Arrays.copyOf(colorFormats, colorFormats.length);
1308 
1309             caps.mMime = mMime;
1310             caps.mMaxSupportedInstances = mMaxSupportedInstances;
1311             caps.mFlagsRequired = mFlagsRequired;
1312             caps.mFlagsSupported = mFlagsSupported;
1313             caps.mFlagsVerified = mFlagsVerified;
1314             caps.mAudioCaps = mAudioCaps;
1315             caps.mVideoCaps = mVideoCaps;
1316             caps.mEncoderCaps = mEncoderCaps;
1317             caps.mDefaultFormat = mDefaultFormat;
1318             caps.mCapabilitiesInfo = mCapabilitiesInfo;
1319 
1320             return caps;
1321         }
1322 
1323         /**
1324          * Retrieve the codec capabilities for a certain {@code mime type}, {@code
1325          * profile} and {@code level}.  If the type, or profile-level combination
1326          * is not understood by the framework, it returns null.
1327          * <p class=note> In {@link android.os.Build.VERSION_CODES#M}, calling this
1328          * method without calling any method of the {@link MediaCodecList} class beforehand
1329          * results in a {@link NullPointerException}.</p>
1330          */
createFromProfileLevel( String mime, int profile, int level)1331         public static CodecCapabilities createFromProfileLevel(
1332                 String mime, int profile, int level) {
1333             CodecProfileLevel pl = new CodecProfileLevel();
1334             pl.profile = profile;
1335             pl.level = level;
1336             MediaFormat defaultFormat = new MediaFormat();
1337             defaultFormat.setString(MediaFormat.KEY_MIME, mime);
1338 
1339             CodecCapabilities ret = new CodecCapabilities(
1340                 new CodecProfileLevel[] { pl }, new int[0], true /* encoder */,
1341                 defaultFormat, new MediaFormat() /* info */);
1342             if (ret.mError != 0) {
1343                 return null;
1344             }
1345             return ret;
1346         }
1347 
CodecCapabilities( CodecProfileLevel[] profLevs, int[] colFmts, boolean encoder, Map<String, Object>defaultFormatMap, Map<String, Object>capabilitiesMap)1348         /* package private */ CodecCapabilities(
1349                 CodecProfileLevel[] profLevs, int[] colFmts,
1350                 boolean encoder,
1351                 Map<String, Object>defaultFormatMap,
1352                 Map<String, Object>capabilitiesMap) {
1353             this(profLevs, colFmts, encoder,
1354                     new MediaFormat(defaultFormatMap),
1355                     new MediaFormat(capabilitiesMap));
1356         }
1357 
1358         private MediaFormat mCapabilitiesInfo;
1359 
CodecCapabilities( CodecProfileLevel[] profLevs, int[] colFmts, boolean encoder, MediaFormat defaultFormat, MediaFormat info)1360         /* package private */ CodecCapabilities(
1361                 CodecProfileLevel[] profLevs, int[] colFmts, boolean encoder,
1362                 MediaFormat defaultFormat, MediaFormat info) {
1363             final Map<String, Object> map = info.getMap();
1364             colorFormats = colFmts;
1365             mFlagsVerified = 0; // TODO: remove as it is unused
1366             mDefaultFormat = defaultFormat;
1367             mCapabilitiesInfo = info;
1368             mMime = mDefaultFormat.getString(MediaFormat.KEY_MIME);
1369 
1370             /* VP9 introduced profiles around 2016, so some VP9 codecs may not advertise any
1371                supported profiles. Determine the level for them using the info they provide. */
1372             if (profLevs.length == 0 && mMime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP9)) {
1373                 CodecProfileLevel profLev = new CodecProfileLevel();
1374                 profLev.profile = CodecProfileLevel.VP9Profile0;
1375                 profLev.level = VideoCapabilities.equivalentVP9Level(info);
1376                 profLevs = new CodecProfileLevel[] { profLev };
1377             }
1378             profileLevels = profLevs;
1379 
1380             if (mMime.toLowerCase().startsWith("audio/")) {
1381                 mAudioCaps = AudioCapabilities.create(info, this);
1382                 mAudioCaps.getDefaultFormat(mDefaultFormat);
1383             } else if (mMime.toLowerCase().startsWith("video/")
1384                     || mMime.equalsIgnoreCase(MediaFormat.MIMETYPE_IMAGE_ANDROID_HEIC)) {
1385                 mVideoCaps = VideoCapabilities.create(info, this);
1386             }
1387             if (encoder) {
1388                 mEncoderCaps = EncoderCapabilities.create(info, this);
1389                 mEncoderCaps.getDefaultFormat(mDefaultFormat);
1390             }
1391 
1392             final Map<String, Object> global = MediaCodecList.getGlobalSettings();
1393             mMaxSupportedInstances = Utils.parseIntSafely(
1394                     global.get("max-concurrent-instances"), DEFAULT_MAX_SUPPORTED_INSTANCES);
1395 
1396             int maxInstances = Utils.parseIntSafely(
1397                     map.get("max-concurrent-instances"), mMaxSupportedInstances);
1398             mMaxSupportedInstances =
1399                     Range.create(1, MAX_SUPPORTED_INSTANCES_LIMIT).clamp(maxInstances);
1400 
1401             for (Feature feat: getValidFeatures()) {
1402                 String key = MediaFormat.KEY_FEATURE_ + feat.mName;
1403                 Integer yesNo = (Integer)map.get(key);
1404                 if (yesNo == null) {
1405                     continue;
1406                 }
1407                 if (yesNo > 0) {
1408                     mFlagsRequired |= feat.mValue;
1409                 }
1410                 mFlagsSupported |= feat.mValue;
1411                 if (!feat.mInternal) {
1412                     mDefaultFormat.setInteger(key, 1);
1413                 }
1414                 // TODO restrict features by mFlagsVerified once all codecs reliably verify them
1415             }
1416         }
1417     }
1418 
1419     /**
1420      * A class that supports querying the audio capabilities of a codec.
1421      */
1422     public static final class AudioCapabilities {
1423         private static final String TAG = "AudioCapabilities";
1424         private CodecCapabilities mParent;
1425         private Range<Integer> mBitrateRange;
1426 
1427         private int[] mSampleRates;
1428         private Range<Integer>[] mSampleRateRanges;
1429         private Range<Integer>[] mInputChannelRanges;
1430 
1431         private static final int MAX_INPUT_CHANNEL_COUNT = 30;
1432 
1433         /**
1434          * Returns the range of supported bitrates in bits/second.
1435          */
getBitrateRange()1436         public Range<Integer> getBitrateRange() {
1437             return mBitrateRange;
1438         }
1439 
1440         /**
1441          * Returns the array of supported sample rates if the codec
1442          * supports only discrete values.  Otherwise, it returns
1443          * {@code null}.  The array is sorted in ascending order.
1444          */
getSupportedSampleRates()1445         public int[] getSupportedSampleRates() {
1446             return mSampleRates != null ? Arrays.copyOf(mSampleRates, mSampleRates.length) : null;
1447         }
1448 
1449         /**
1450          * Returns the array of supported sample rate ranges.  The
1451          * array is sorted in ascending order, and the ranges are
1452          * distinct.
1453          */
getSupportedSampleRateRanges()1454         public Range<Integer>[] getSupportedSampleRateRanges() {
1455             return Arrays.copyOf(mSampleRateRanges, mSampleRateRanges.length);
1456         }
1457 
1458         /**
1459          * Returns the maximum number of input channels supported.
1460          *
1461          * Through {@link android.os.Build.VERSION_CODES#R}, this method indicated support
1462          * for any number of input channels between 1 and this maximum value.
1463          *
1464          * As of {@link android.os.Build.VERSION_CODES#S},
1465          * the implied lower limit of 1 channel is no longer valid.
1466          * As of {@link android.os.Build.VERSION_CODES#S}, {@link #getMaxInputChannelCount} is
1467          * superseded by {@link #getInputChannelCountRanges},
1468          * which returns an array of ranges of channels.
1469          * The {@link #getMaxInputChannelCount} method will return the highest value
1470          * in the ranges returned by {@link #getInputChannelCountRanges}
1471          *
1472          */
1473         @IntRange(from = 1, to = 255)
getMaxInputChannelCount()1474         public int getMaxInputChannelCount() {
1475             int overall_max = 0;
1476             for (int i = mInputChannelRanges.length - 1; i >= 0; i--) {
1477                 int lmax = mInputChannelRanges[i].getUpper();
1478                 if (lmax > overall_max) {
1479                     overall_max = lmax;
1480                 }
1481             }
1482             return overall_max;
1483         }
1484 
1485         /**
1486          * Returns the minimum number of input channels supported.
1487          * This is often 1, but does vary for certain mime types.
1488          *
1489          * This returns the lowest channel count in the ranges returned by
1490          * {@link #getInputChannelCountRanges}.
1491          */
1492         @IntRange(from = 1, to = 255)
getMinInputChannelCount()1493         public int getMinInputChannelCount() {
1494             int overall_min = MAX_INPUT_CHANNEL_COUNT;
1495             for (int i = mInputChannelRanges.length - 1; i >= 0; i--) {
1496                 int lmin = mInputChannelRanges[i].getLower();
1497                 if (lmin < overall_min) {
1498                     overall_min = lmin;
1499                 }
1500             }
1501             return overall_min;
1502         }
1503 
1504         /*
1505          * Returns an array of ranges representing the number of input channels supported.
1506          * The codec supports any number of input channels within this range.
1507          *
1508          * This supersedes the {@link #getMaxInputChannelCount} method.
1509          *
1510          * For many codecs, this will be a single range [1..N], for some N.
1511          */
1512         @SuppressLint("ArrayReturn")
1513         @NonNull
getInputChannelCountRanges()1514         public Range<Integer>[] getInputChannelCountRanges() {
1515             return Arrays.copyOf(mInputChannelRanges, mInputChannelRanges.length);
1516         }
1517 
1518         /* no public constructor */
AudioCapabilities()1519         private AudioCapabilities() { }
1520 
1521         /** @hide */
create( MediaFormat info, CodecCapabilities parent)1522         public static AudioCapabilities create(
1523                 MediaFormat info, CodecCapabilities parent) {
1524             AudioCapabilities caps = new AudioCapabilities();
1525             caps.init(info, parent);
1526             return caps;
1527         }
1528 
init(MediaFormat info, CodecCapabilities parent)1529         private void init(MediaFormat info, CodecCapabilities parent) {
1530             mParent = parent;
1531             initWithPlatformLimits();
1532             applyLevelLimits();
1533             parseFromInfo(info);
1534         }
1535 
initWithPlatformLimits()1536         private void initWithPlatformLimits() {
1537             mBitrateRange = Range.create(0, Integer.MAX_VALUE);
1538             mInputChannelRanges = new Range[] {Range.create(1, MAX_INPUT_CHANNEL_COUNT)};
1539             // mBitrateRange = Range.create(1, 320000);
1540             final int minSampleRate = SystemProperties.
1541                 getInt("ro.mediacodec.min_sample_rate", 7350);
1542             final int maxSampleRate = SystemProperties.
1543                 getInt("ro.mediacodec.max_sample_rate", 192000);
1544             mSampleRateRanges = new Range[] { Range.create(minSampleRate, maxSampleRate) };
1545             mSampleRates = null;
1546         }
1547 
supports(Integer sampleRate, Integer inputChannels)1548         private boolean supports(Integer sampleRate, Integer inputChannels) {
1549             // channels and sample rates are checked orthogonally
1550             if (inputChannels != null) {
1551                 int ix = Utils.binarySearchDistinctRanges(
1552                         mInputChannelRanges, inputChannels);
1553                 if (ix < 0) {
1554                     return false;
1555                 }
1556             }
1557             if (sampleRate != null) {
1558                 int ix = Utils.binarySearchDistinctRanges(
1559                         mSampleRateRanges, sampleRate);
1560                 if (ix < 0) {
1561                     return false;
1562                 }
1563             }
1564             return true;
1565         }
1566 
1567         /**
1568          * Query whether the sample rate is supported by the codec.
1569          */
isSampleRateSupported(int sampleRate)1570         public boolean isSampleRateSupported(int sampleRate) {
1571             return supports(sampleRate, null);
1572         }
1573 
1574         /** modifies rates */
limitSampleRates(int[] rates)1575         private void limitSampleRates(int[] rates) {
1576             Arrays.sort(rates);
1577             ArrayList<Range<Integer>> ranges = new ArrayList<Range<Integer>>();
1578             for (int rate: rates) {
1579                 if (supports(rate, null /* channels */)) {
1580                     ranges.add(Range.create(rate, rate));
1581                 }
1582             }
1583             mSampleRateRanges = ranges.toArray(new Range[ranges.size()]);
1584             createDiscreteSampleRates();
1585         }
1586 
createDiscreteSampleRates()1587         private void createDiscreteSampleRates() {
1588             mSampleRates = new int[mSampleRateRanges.length];
1589             for (int i = 0; i < mSampleRateRanges.length; i++) {
1590                 mSampleRates[i] = mSampleRateRanges[i].getLower();
1591             }
1592         }
1593 
1594         /** modifies rateRanges */
limitSampleRates(Range<Integer>[] rateRanges)1595         private void limitSampleRates(Range<Integer>[] rateRanges) {
1596             sortDistinctRanges(rateRanges);
1597             mSampleRateRanges = intersectSortedDistinctRanges(mSampleRateRanges, rateRanges);
1598 
1599             // check if all values are discrete
1600             for (Range<Integer> range: mSampleRateRanges) {
1601                 if (!range.getLower().equals(range.getUpper())) {
1602                     mSampleRates = null;
1603                     return;
1604                 }
1605             }
1606             createDiscreteSampleRates();
1607         }
1608 
applyLevelLimits()1609         private void applyLevelLimits() {
1610             int[] sampleRates = null;
1611             Range<Integer> sampleRateRange = null, bitRates = null;
1612             int maxChannels = MAX_INPUT_CHANNEL_COUNT;
1613             CodecProfileLevel[] profileLevels = mParent.profileLevels;
1614             String mime = mParent.getMimeType();
1615 
1616             if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_MPEG)) {
1617                 sampleRates = new int[] {
1618                         8000, 11025, 12000,
1619                         16000, 22050, 24000,
1620                         32000, 44100, 48000 };
1621                 bitRates = Range.create(8000, 320000);
1622                 maxChannels = 2;
1623             } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AMR_NB)) {
1624                 sampleRates = new int[] { 8000 };
1625                 bitRates = Range.create(4750, 12200);
1626                 maxChannels = 1;
1627             } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AMR_WB)) {
1628                 sampleRates = new int[] { 16000 };
1629                 bitRates = Range.create(6600, 23850);
1630                 maxChannels = 1;
1631             } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AAC)) {
1632                 sampleRates = new int[] {
1633                         7350, 8000,
1634                         11025, 12000, 16000,
1635                         22050, 24000, 32000,
1636                         44100, 48000, 64000,
1637                         88200, 96000 };
1638                 bitRates = Range.create(8000, 510000);
1639                 maxChannels = 48;
1640             } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_VORBIS)) {
1641                 bitRates = Range.create(32000, 500000);
1642                 sampleRateRange = Range.create(8000, 192000);
1643                 maxChannels = 255;
1644             } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_OPUS)) {
1645                 bitRates = Range.create(6000, 510000);
1646                 sampleRates = new int[] { 8000, 12000, 16000, 24000, 48000 };
1647                 maxChannels = 255;
1648             } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_RAW)) {
1649                 sampleRateRange = Range.create(1, 192000);
1650                 bitRates = Range.create(1, 10000000);
1651                 maxChannels = AudioSystem.OUT_CHANNEL_COUNT_MAX;
1652             } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_FLAC)) {
1653                 sampleRateRange = Range.create(1, 655350);
1654                 // lossless codec, so bitrate is ignored
1655                 maxChannels = 255;
1656             } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_G711_ALAW)
1657                     || mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_G711_MLAW)) {
1658                 sampleRates = new int[] { 8000 };
1659                 bitRates = Range.create(64000, 64000);
1660                 // platform allows multiple channels for this format
1661             } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_MSGSM)) {
1662                 sampleRates = new int[] { 8000 };
1663                 bitRates = Range.create(13000, 13000);
1664                 maxChannels = 1;
1665             } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AC3)) {
1666                 maxChannels = 6;
1667             } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_EAC3)) {
1668                 maxChannels = 16;
1669             } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_EAC3_JOC)) {
1670                 sampleRates = new int[] { 48000 };
1671                 bitRates = Range.create(32000, 6144000);
1672                 maxChannels = 16;
1673             } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AC4)) {
1674                 sampleRates = new int[] { 44100, 48000, 96000, 192000 };
1675                 bitRates = Range.create(16000, 2688000);
1676                 maxChannels = 24;
1677             } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_DTS)) {
1678                 sampleRates = new int[] { 44100, 48000 };
1679                 bitRates = Range.create(96000, 1524000);
1680                 maxChannels = 6;
1681             } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_DTS_HD)) {
1682                 for (CodecProfileLevel profileLevel: profileLevels) {
1683                     switch (profileLevel.profile) {
1684                         case CodecProfileLevel.DTS_HDProfileLBR:
1685                             sampleRates = new int[]{ 22050, 24000, 44100, 48000 };
1686                             bitRates = Range.create(32000, 768000);
1687                             break;
1688                         case CodecProfileLevel.DTS_HDProfileHRA:
1689                         case CodecProfileLevel.DTS_HDProfileMA:
1690                             sampleRates = new int[]{ 44100, 48000, 88200, 96000, 176400, 192000 };
1691                             bitRates = Range.create(96000, 24500000);
1692                             break;
1693                         default:
1694                             Log.w(TAG, "Unrecognized profile "
1695                                     + profileLevel.profile + " for " + mime);
1696                             mParent.mError |= ERROR_UNRECOGNIZED;
1697                             sampleRates = new int[]{ 44100, 48000, 88200, 96000, 176400, 192000 };
1698                             bitRates = Range.create(96000, 24500000);
1699                     }
1700                 }
1701                 maxChannels = 8;
1702             } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_DTS_UHD)) {
1703                 for (CodecProfileLevel profileLevel: profileLevels) {
1704                     switch (profileLevel.profile) {
1705                         case CodecProfileLevel.DTS_UHDProfileP2:
1706                             sampleRates = new int[]{ 48000 };
1707                             bitRates = Range.create(96000, 768000);
1708                             maxChannels = 10;
1709                             break;
1710                         case CodecProfileLevel.DTS_UHDProfileP1:
1711                             sampleRates = new int[]{ 44100, 48000, 88200, 96000, 176400, 192000 };
1712                             bitRates = Range.create(96000, 24500000);
1713                             maxChannels = 32;
1714                             break;
1715                         default:
1716                             Log.w(TAG, "Unrecognized profile "
1717                                     + profileLevel.profile + " for " + mime);
1718                             mParent.mError |= ERROR_UNRECOGNIZED;
1719                             sampleRates = new int[]{ 44100, 48000, 88200, 96000, 176400, 192000 };
1720                             bitRates = Range.create(96000, 24500000);
1721                             maxChannels = 32;
1722                     }
1723                 }
1724             } else {
1725                 Log.w(TAG, "Unsupported mime " + mime);
1726                 mParent.mError |= ERROR_UNSUPPORTED;
1727             }
1728 
1729             // restrict ranges
1730             if (sampleRates != null) {
1731                 limitSampleRates(sampleRates);
1732             } else if (sampleRateRange != null) {
1733                 limitSampleRates(new Range[] { sampleRateRange });
1734             }
1735 
1736             Range<Integer> channelRange = Range.create(1, maxChannels);
1737 
1738             applyLimits(new Range[] { channelRange }, bitRates);
1739         }
1740 
applyLimits(Range<Integer>[] inputChannels, Range<Integer> bitRates)1741         private void applyLimits(Range<Integer>[] inputChannels, Range<Integer> bitRates) {
1742 
1743             // clamp & make a local copy
1744             Range<Integer>[] myInputChannels = new Range[inputChannels.length];
1745             for (int i = 0; i < inputChannels.length; i++) {
1746                 int lower = inputChannels[i].clamp(1);
1747                 int upper = inputChannels[i].clamp(MAX_INPUT_CHANNEL_COUNT);
1748                 myInputChannels[i] = Range.create(lower, upper);
1749             }
1750 
1751             // sort, intersect with existing, & save channel list
1752             sortDistinctRanges(myInputChannels);
1753             Range<Integer>[] joinedChannelList =
1754                             intersectSortedDistinctRanges(myInputChannels, mInputChannelRanges);
1755             mInputChannelRanges = joinedChannelList;
1756 
1757             if (bitRates != null) {
1758                 mBitrateRange = mBitrateRange.intersect(bitRates);
1759             }
1760         }
1761 
parseFromInfo(MediaFormat info)1762         private void parseFromInfo(MediaFormat info) {
1763             int maxInputChannels = MAX_INPUT_CHANNEL_COUNT;
1764             Range<Integer>[] channels = new Range[] { Range.create(1, maxInputChannels)};
1765             Range<Integer> bitRates = POSITIVE_INTEGERS;
1766 
1767             if (info.containsKey("sample-rate-ranges")) {
1768                 String[] rateStrings = info.getString("sample-rate-ranges").split(",");
1769                 Range<Integer>[] rateRanges = new Range[rateStrings.length];
1770                 for (int i = 0; i < rateStrings.length; i++) {
1771                     rateRanges[i] = Utils.parseIntRange(rateStrings[i], null);
1772                 }
1773                 limitSampleRates(rateRanges);
1774             }
1775 
1776             // we will prefer channel-ranges over max-channel-count
1777             if (info.containsKey("channel-ranges")) {
1778                 String[] channelStrings = info.getString("channel-ranges").split(",");
1779                 Range<Integer>[] channelRanges = new Range[channelStrings.length];
1780                 for (int i = 0; i < channelStrings.length; i++) {
1781                     channelRanges[i] = Utils.parseIntRange(channelStrings[i], null);
1782                 }
1783                 channels = channelRanges;
1784             } else if (info.containsKey("channel-range")) {
1785                 Range<Integer> oneRange = Utils.parseIntRange(info.getString("channel-range"),
1786                                                               null);
1787                 channels = new Range[] { oneRange };
1788             } else if (info.containsKey("max-channel-count")) {
1789                 maxInputChannels = Utils.parseIntSafely(
1790                         info.getString("max-channel-count"), maxInputChannels);
1791                 if (maxInputChannels == 0) {
1792                     channels = new Range[] {Range.create(0, 0)};
1793                 } else {
1794                     channels = new Range[] {Range.create(1, maxInputChannels)};
1795                 }
1796             } else if ((mParent.mError & ERROR_UNSUPPORTED) != 0) {
1797                 maxInputChannels = 0;
1798                 channels = new Range[] {Range.create(0, 0)};
1799             }
1800 
1801             if (info.containsKey("bitrate-range")) {
1802                 bitRates = bitRates.intersect(
1803                         Utils.parseIntRange(info.getString("bitrate-range"), bitRates));
1804             }
1805 
1806             applyLimits(channels, bitRates);
1807         }
1808 
1809         /** @hide */
getDefaultFormat(MediaFormat format)1810         public void getDefaultFormat(MediaFormat format) {
1811             // report settings that have only a single choice
1812             if (mBitrateRange.getLower().equals(mBitrateRange.getUpper())) {
1813                 format.setInteger(MediaFormat.KEY_BIT_RATE, mBitrateRange.getLower());
1814             }
1815             if (getMaxInputChannelCount() == 1) {
1816                 // mono-only format
1817                 format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
1818             }
1819             if (mSampleRates != null && mSampleRates.length == 1) {
1820                 format.setInteger(MediaFormat.KEY_SAMPLE_RATE, mSampleRates[0]);
1821             }
1822         }
1823 
1824         /* package private */
1825         // must not contain KEY_PROFILE
1826         static final Set<String> AUDIO_LEVEL_CRITICAL_FORMAT_KEYS = Set.of(
1827                 // We don't set level-specific limits for audio codecs today. Key candidates would
1828                 // be sample rate, bit rate or channel count.
1829                 // MediaFormat.KEY_SAMPLE_RATE,
1830                 // MediaFormat.KEY_CHANNEL_COUNT,
1831                 // MediaFormat.KEY_BIT_RATE,
1832                 MediaFormat.KEY_MIME);
1833 
1834         /** @hide */
supportsFormat(MediaFormat format)1835         public boolean supportsFormat(MediaFormat format) {
1836             Map<String, Object> map = format.getMap();
1837             Integer sampleRate = (Integer)map.get(MediaFormat.KEY_SAMPLE_RATE);
1838             Integer channels = (Integer)map.get(MediaFormat.KEY_CHANNEL_COUNT);
1839 
1840             if (!supports(sampleRate, channels)) {
1841                 return false;
1842             }
1843 
1844             if (!CodecCapabilities.supportsBitrate(mBitrateRange, format)) {
1845                 return false;
1846             }
1847 
1848             // nothing to do for:
1849             // KEY_CHANNEL_MASK: codecs don't get this
1850             // KEY_IS_ADTS:      required feature for all AAC decoders
1851             return true;
1852         }
1853     }
1854 
1855     /** @hide */
1856     @IntDef(prefix = {"SECURITY_MODEL_"}, value = {
1857         SECURITY_MODEL_SANDBOXED,
1858         SECURITY_MODEL_MEMORY_SAFE,
1859         SECURITY_MODEL_TRUSTED_CONTENT_ONLY,
1860     })
1861     @Retention(RetentionPolicy.SOURCE)
1862     public @interface SecurityModel {}
1863 
1864     /**
1865      * In this model the codec is running in a sandboxed process. Even if a
1866      * malicious content was fed to the codecs in this model, the impact will
1867      * be contained in the sandboxed process.
1868      */
1869     @FlaggedApi(FLAG_IN_PROCESS_SW_AUDIO_CODEC)
1870     public static final int SECURITY_MODEL_SANDBOXED = 0;
1871     /**
1872      * In this model the codec is not running in a sandboxed process, but
1873      * written in a memory-safe way. It typically means that the software
1874      * implementation of the codec is written in a memory-safe language such
1875      * as Rust.
1876      */
1877     @FlaggedApi(FLAG_IN_PROCESS_SW_AUDIO_CODEC)
1878     public static final int SECURITY_MODEL_MEMORY_SAFE = 1;
1879     /**
1880      * In this model the codec is suitable only for trusted content where
1881      * the input can be verified to be well-formed and no malicious actor
1882      * can alter it. For example, codecs in this model are not suitable
1883      * for arbitrary media downloaded from the internet or present in a user
1884      * directory. On the other hand, they could be suitable for media encoded
1885      * in the backend that the app developer wholly controls.
1886      * <p>
1887      * Codecs with this security model is not included in
1888      * {@link MediaCodecList#REGULAR_CODECS}, but included in
1889      * {@link MediaCodecList#ALL_CODECS}.
1890      *
1891      * @hide
1892      */
1893     @FlaggedApi(FLAG_IN_PROCESS_SW_AUDIO_CODEC)
1894     public static final int SECURITY_MODEL_TRUSTED_CONTENT_ONLY = 2;
1895 
1896     /**
1897      * Query the security model of the codec.
1898      */
1899     @FlaggedApi(FLAG_IN_PROCESS_SW_AUDIO_CODEC)
1900     @SecurityModel
getSecurityModel()1901     public int getSecurityModel() {
1902         // TODO b/297922713 --- detect security model of out-of-sandbox codecs
1903         return SECURITY_MODEL_SANDBOXED;
1904     }
1905 
1906     /**
1907      * A class that supports querying the video capabilities of a codec.
1908      */
1909     public static final class VideoCapabilities {
1910         private static final String TAG = "VideoCapabilities";
1911         private CodecCapabilities mParent;
1912         private Range<Integer> mBitrateRange;
1913 
1914         private Range<Integer> mHeightRange;
1915         private Range<Integer> mWidthRange;
1916         private Range<Integer> mBlockCountRange;
1917         private Range<Integer> mHorizontalBlockRange;
1918         private Range<Integer> mVerticalBlockRange;
1919         private Range<Rational> mAspectRatioRange;
1920         private Range<Rational> mBlockAspectRatioRange;
1921         private Range<Long> mBlocksPerSecondRange;
1922         private Map<Size, Range<Long>> mMeasuredFrameRates;
1923         private List<PerformancePoint> mPerformancePoints;
1924         private Range<Integer> mFrameRateRange;
1925 
1926         private int mBlockWidth;
1927         private int mBlockHeight;
1928         private int mWidthAlignment;
1929         private int mHeightAlignment;
1930         private int mSmallerDimensionUpperLimit;
1931 
1932         private boolean mAllowMbOverride; // allow XML to override calculated limits
1933 
1934         /**
1935          * Returns the range of supported bitrates in bits/second.
1936          */
getBitrateRange()1937         public Range<Integer> getBitrateRange() {
1938             return mBitrateRange;
1939         }
1940 
1941         /**
1942          * Returns the range of supported video widths.
1943          * <p class=note>
1944          * 32-bit processes will not support resolutions larger than 4096x4096 due to
1945          * the limited address space.
1946          */
getSupportedWidths()1947         public Range<Integer> getSupportedWidths() {
1948             return mWidthRange;
1949         }
1950 
1951         /**
1952          * Returns the range of supported video heights.
1953          * <p class=note>
1954          * 32-bit processes will not support resolutions larger than 4096x4096 due to
1955          * the limited address space.
1956          */
getSupportedHeights()1957         public Range<Integer> getSupportedHeights() {
1958             return mHeightRange;
1959         }
1960 
1961         /**
1962          * Returns the alignment requirement for video width (in pixels).
1963          *
1964          * This is a power-of-2 value that video width must be a
1965          * multiple of.
1966          */
getWidthAlignment()1967         public int getWidthAlignment() {
1968             return mWidthAlignment;
1969         }
1970 
1971         /**
1972          * Returns the alignment requirement for video height (in pixels).
1973          *
1974          * This is a power-of-2 value that video height must be a
1975          * multiple of.
1976          */
getHeightAlignment()1977         public int getHeightAlignment() {
1978             return mHeightAlignment;
1979         }
1980 
1981         /**
1982          * Return the upper limit on the smaller dimension of width or height.
1983          * <p></p>
1984          * Some codecs have a limit on the smaller dimension, whether it be
1985          * the width or the height.  E.g. a codec may only be able to handle
1986          * up to 1920x1080 both in landscape and portrait mode (1080x1920).
1987          * In this case the maximum width and height are both 1920, but the
1988          * smaller dimension limit will be 1080. For other codecs, this is
1989          * {@code Math.min(getSupportedWidths().getUpper(),
1990          * getSupportedHeights().getUpper())}.
1991          *
1992          * @hide
1993          */
getSmallerDimensionUpperLimit()1994         public int getSmallerDimensionUpperLimit() {
1995             return mSmallerDimensionUpperLimit;
1996         }
1997 
1998         /**
1999          * Returns the range of supported frame rates.
2000          * <p>
2001          * This is not a performance indicator.  Rather, it expresses the
2002          * limits specified in the coding standard, based on the complexities
2003          * of encoding material for later playback at a certain frame rate,
2004          * or the decoding of such material in non-realtime.
2005          */
getSupportedFrameRates()2006         public Range<Integer> getSupportedFrameRates() {
2007             return mFrameRateRange;
2008         }
2009 
2010         /**
2011          * Returns the range of supported video widths for a video height.
2012          * @param height the height of the video
2013          */
getSupportedWidthsFor(int height)2014         public Range<Integer> getSupportedWidthsFor(int height) {
2015             try {
2016                 Range<Integer> range = mWidthRange;
2017                 if (!mHeightRange.contains(height)
2018                         || (height % mHeightAlignment) != 0) {
2019                     throw new IllegalArgumentException("unsupported height");
2020                 }
2021                 final int heightInBlocks = Utils.divUp(height, mBlockHeight);
2022 
2023                 // constrain by block count and by block aspect ratio
2024                 final int minWidthInBlocks = Math.max(
2025                         Utils.divUp(mBlockCountRange.getLower(), heightInBlocks),
2026                         (int)Math.ceil(mBlockAspectRatioRange.getLower().doubleValue()
2027                                 * heightInBlocks));
2028                 final int maxWidthInBlocks = Math.min(
2029                         mBlockCountRange.getUpper() / heightInBlocks,
2030                         (int)(mBlockAspectRatioRange.getUpper().doubleValue()
2031                                 * heightInBlocks));
2032                 range = range.intersect(
2033                         (minWidthInBlocks - 1) * mBlockWidth + mWidthAlignment,
2034                         maxWidthInBlocks * mBlockWidth);
2035 
2036                 // constrain by smaller dimension limit
2037                 if (height > mSmallerDimensionUpperLimit) {
2038                     range = range.intersect(1, mSmallerDimensionUpperLimit);
2039                 }
2040 
2041                 // constrain by aspect ratio
2042                 range = range.intersect(
2043                         (int)Math.ceil(mAspectRatioRange.getLower().doubleValue()
2044                                 * height),
2045                         (int)(mAspectRatioRange.getUpper().doubleValue() * height));
2046                 return range;
2047             } catch (IllegalArgumentException e) {
2048                 // height is not supported because there are no suitable widths
2049                 Log.v(TAG, "could not get supported widths for " + height);
2050                 throw new IllegalArgumentException("unsupported height");
2051             }
2052         }
2053 
2054         /**
2055          * Returns the range of supported video heights for a video width
2056          * @param width the width of the video
2057          */
getSupportedHeightsFor(int width)2058         public Range<Integer> getSupportedHeightsFor(int width) {
2059             try {
2060                 Range<Integer> range = mHeightRange;
2061                 if (!mWidthRange.contains(width)
2062                         || (width % mWidthAlignment) != 0) {
2063                     throw new IllegalArgumentException("unsupported width");
2064                 }
2065                 final int widthInBlocks = Utils.divUp(width, mBlockWidth);
2066 
2067                 // constrain by block count and by block aspect ratio
2068                 final int minHeightInBlocks = Math.max(
2069                         Utils.divUp(mBlockCountRange.getLower(), widthInBlocks),
2070                         (int)Math.ceil(widthInBlocks /
2071                                 mBlockAspectRatioRange.getUpper().doubleValue()));
2072                 final int maxHeightInBlocks = Math.min(
2073                         mBlockCountRange.getUpper() / widthInBlocks,
2074                         (int)(widthInBlocks /
2075                                 mBlockAspectRatioRange.getLower().doubleValue()));
2076                 range = range.intersect(
2077                         (minHeightInBlocks - 1) * mBlockHeight + mHeightAlignment,
2078                         maxHeightInBlocks * mBlockHeight);
2079 
2080                 // constrain by smaller dimension limit
2081                 if (width > mSmallerDimensionUpperLimit) {
2082                     range = range.intersect(1, mSmallerDimensionUpperLimit);
2083                 }
2084 
2085                 // constrain by aspect ratio
2086                 range = range.intersect(
2087                         (int)Math.ceil(width /
2088                                 mAspectRatioRange.getUpper().doubleValue()),
2089                         (int)(width / mAspectRatioRange.getLower().doubleValue()));
2090                 return range;
2091             } catch (IllegalArgumentException e) {
2092                 // width is not supported because there are no suitable heights
2093                 Log.v(TAG, "could not get supported heights for " + width);
2094                 throw new IllegalArgumentException("unsupported width");
2095             }
2096         }
2097 
2098         /**
2099          * Returns the range of supported video frame rates for a video size.
2100          * <p>
2101          * This is not a performance indicator.  Rather, it expresses the limits specified in
2102          * the coding standard, based on the complexities of encoding material of a given
2103          * size for later playback at a certain frame rate, or the decoding of such material
2104          * in non-realtime.
2105 
2106          * @param width the width of the video
2107          * @param height the height of the video
2108          */
getSupportedFrameRatesFor(int width, int height)2109         public Range<Double> getSupportedFrameRatesFor(int width, int height) {
2110             Range<Integer> range = mHeightRange;
2111             if (!supports(width, height, null)) {
2112                 throw new IllegalArgumentException("unsupported size");
2113             }
2114             final int blockCount =
2115                 Utils.divUp(width, mBlockWidth) * Utils.divUp(height, mBlockHeight);
2116 
2117             return Range.create(
2118                     Math.max(mBlocksPerSecondRange.getLower() / (double) blockCount,
2119                             (double) mFrameRateRange.getLower()),
2120                     Math.min(mBlocksPerSecondRange.getUpper() / (double) blockCount,
2121                             (double) mFrameRateRange.getUpper()));
2122         }
2123 
getBlockCount(int width, int height)2124         private int getBlockCount(int width, int height) {
2125             return Utils.divUp(width, mBlockWidth) * Utils.divUp(height, mBlockHeight);
2126         }
2127 
2128         @NonNull
findClosestSize(int width, int height)2129         private Size findClosestSize(int width, int height) {
2130             int targetBlockCount = getBlockCount(width, height);
2131             Size closestSize = null;
2132             int minDiff = Integer.MAX_VALUE;
2133             for (Size size : mMeasuredFrameRates.keySet()) {
2134                 int diff = Math.abs(targetBlockCount -
2135                         getBlockCount(size.getWidth(), size.getHeight()));
2136                 if (diff < minDiff) {
2137                     minDiff = diff;
2138                     closestSize = size;
2139                 }
2140             }
2141             return closestSize;
2142         }
2143 
estimateFrameRatesFor(int width, int height)2144         private Range<Double> estimateFrameRatesFor(int width, int height) {
2145             Size size = findClosestSize(width, height);
2146             Range<Long> range = mMeasuredFrameRates.get(size);
2147             Double ratio = getBlockCount(size.getWidth(), size.getHeight())
2148                     / (double)Math.max(getBlockCount(width, height), 1);
2149             return Range.create(range.getLower() * ratio, range.getUpper() * ratio);
2150         }
2151 
2152         /**
2153          * Returns the range of achievable video frame rates for a video size.
2154          * May return {@code null}, if the codec did not publish any measurement
2155          * data.
2156          * <p>
2157          * This is a performance estimate provided by the device manufacturer based on statistical
2158          * sampling of full-speed decoding and encoding measurements in various configurations
2159          * of common video sizes supported by the codec. As such it should only be used to
2160          * compare individual codecs on the device. The value is not suitable for comparing
2161          * different devices or even different android releases for the same device.
2162          * <p>
2163          * <em>On {@link android.os.Build.VERSION_CODES#M} release</em> the returned range
2164          * corresponds to the fastest frame rates achieved in the tested configurations. As
2165          * such, it should not be used to gauge guaranteed or even average codec performance
2166          * on the device.
2167          * <p>
2168          * <em>On {@link android.os.Build.VERSION_CODES#N} release</em> the returned range
2169          * corresponds closer to sustained performance <em>in tested configurations</em>.
2170          * One can expect to achieve sustained performance higher than the lower limit more than
2171          * 50% of the time, and higher than half of the lower limit at least 90% of the time
2172          * <em>in tested configurations</em>.
2173          * Conversely, one can expect performance lower than twice the upper limit at least
2174          * 90% of the time.
2175          * <p class=note>
2176          * Tested configurations use a single active codec. For use cases where multiple
2177          * codecs are active, applications can expect lower and in most cases significantly lower
2178          * performance.
2179          * <p class=note>
2180          * The returned range value is interpolated from the nearest frame size(s) tested.
2181          * Codec performance is severely impacted by other activity on the device as well
2182          * as environmental factors (such as battery level, temperature or power source), and can
2183          * vary significantly even in a steady environment.
2184          * <p class=note>
2185          * Use this method in cases where only codec performance matters, e.g. to evaluate if
2186          * a codec has any chance of meeting a performance target. Codecs are listed
2187          * in {@link MediaCodecList} in the preferred order as defined by the device
2188          * manufacturer. As such, applications should use the first suitable codec in the
2189          * list to achieve the best balance between power use and performance.
2190          *
2191          * @param width the width of the video
2192          * @param height the height of the video
2193          *
2194          * @throws IllegalArgumentException if the video size is not supported.
2195          */
2196         @Nullable
getAchievableFrameRatesFor(int width, int height)2197         public Range<Double> getAchievableFrameRatesFor(int width, int height) {
2198             if (!supports(width, height, null)) {
2199                 throw new IllegalArgumentException("unsupported size");
2200             }
2201 
2202             if (mMeasuredFrameRates == null || mMeasuredFrameRates.size() <= 0) {
2203                 Log.w(TAG, "Codec did not publish any measurement data.");
2204                 return null;
2205             }
2206 
2207             return estimateFrameRatesFor(width, height);
2208         }
2209 
2210         /**
2211          * Video performance points are a set of standard performance points defined by number of
2212          * pixels, pixel rate and frame rate. Performance point represents an upper bound. This
2213          * means that it covers all performance points with fewer pixels, pixel rate and frame
2214          * rate.
2215          */
2216         public static final class PerformancePoint {
2217             private Size mBlockSize; // codec block size in macroblocks
2218             private int mWidth; // width in macroblocks
2219             private int mHeight; // height in macroblocks
2220             private int mMaxFrameRate; // max frames per second
2221             private long mMaxMacroBlockRate; // max macro block rate
2222 
2223             /**
2224              * Maximum number of macroblocks in the frame.
2225              *
2226              * Video frames are conceptually divided into 16-by-16 pixel blocks called macroblocks.
2227              * Most coding standards operate on these 16-by-16 pixel blocks; thus, codec performance
2228              * is characterized using such blocks.
2229              *
2230              * @hide
2231              */
2232             @TestApi
getMaxMacroBlocks()2233             public int getMaxMacroBlocks() {
2234                 return saturateLongToInt(mWidth * (long)mHeight);
2235             }
2236 
2237             /**
2238              * Maximum frame rate in frames per second.
2239              *
2240              * @hide
2241              */
2242             @TestApi
getMaxFrameRate()2243             public int getMaxFrameRate() {
2244                 return mMaxFrameRate;
2245             }
2246 
2247             /**
2248              * Maximum number of macroblocks processed per second.
2249              *
2250              * @hide
2251              */
2252             @TestApi
getMaxMacroBlockRate()2253             public long getMaxMacroBlockRate() {
2254                 return mMaxMacroBlockRate;
2255             }
2256 
2257             /** Convert to a debug string */
toString()2258             public String toString() {
2259                 int blockWidth = 16 * mBlockSize.getWidth();
2260                 int blockHeight = 16 * mBlockSize.getHeight();
2261                 int origRate = (int)Utils.divUp(mMaxMacroBlockRate, getMaxMacroBlocks());
2262                 String info = (mWidth * 16) + "x" + (mHeight * 16) + "@" + origRate;
2263                 if (origRate < mMaxFrameRate) {
2264                     info += ", max " + mMaxFrameRate + "fps";
2265                 }
2266                 if (blockWidth > 16 || blockHeight > 16) {
2267                     info += ", " + blockWidth + "x" + blockHeight + " blocks";
2268                 }
2269                 return "PerformancePoint(" + info + ")";
2270             }
2271 
2272             @Override
hashCode()2273             public int hashCode() {
2274                 // only max frame rate must equal between performance points that equal to one
2275                 // another
2276                 return mMaxFrameRate;
2277             }
2278 
2279             /**
2280              * Create a detailed performance point with custom max frame rate and macroblock size.
2281              *
2282              * @param width  frame width in pixels
2283              * @param height frame height in pixels
2284              * @param frameRate frames per second for frame width and height
2285              * @param maxFrameRate maximum frames per second for any frame size
2286              * @param blockSize block size for codec implementation. Must be powers of two in both
2287              *        width and height.
2288              *
2289              * @throws IllegalArgumentException if the blockSize dimensions are not powers of two.
2290              *
2291              * @hide
2292              */
2293             @TestApi
PerformancePoint( int width, int height, int frameRate, int maxFrameRate, @NonNull Size blockSize)2294             public PerformancePoint(
2295                     int width, int height, int frameRate, int maxFrameRate,
2296                     @NonNull Size blockSize) {
2297                 checkPowerOfTwo(blockSize.getWidth(), "block width");
2298                 checkPowerOfTwo(blockSize.getHeight(), "block height");
2299 
2300                 mBlockSize = new Size(Utils.divUp(blockSize.getWidth(), 16),
2301                                       Utils.divUp(blockSize.getHeight(), 16));
2302                 // these are guaranteed not to overflow as we decimate by 16
2303                 mWidth = (int)(Utils.divUp(Math.max(1L, width),
2304                                            Math.max(blockSize.getWidth(), 16))
2305                                * mBlockSize.getWidth());
2306                 mHeight = (int)(Utils.divUp(Math.max(1L, height),
2307                                             Math.max(blockSize.getHeight(), 16))
2308                                 * mBlockSize.getHeight());
2309                 mMaxFrameRate = Math.max(1, Math.max(frameRate, maxFrameRate));
2310                 mMaxMacroBlockRate = Math.max(1, frameRate) * getMaxMacroBlocks();
2311             }
2312 
2313             /**
2314              * Convert a performance point to a larger blocksize.
2315              *
2316              * @param pp performance point
2317              * @param blockSize block size for codec implementation
2318              *
2319              * @hide
2320              */
2321             @TestApi
PerformancePoint(@onNull PerformancePoint pp, @NonNull Size newBlockSize)2322             public PerformancePoint(@NonNull PerformancePoint pp, @NonNull Size newBlockSize) {
2323                 this(
2324                         pp.mWidth * 16, pp.mHeight * 16,
2325                         // guaranteed not to overflow as these were multiplied at construction
2326                         (int)Utils.divUp(pp.mMaxMacroBlockRate, pp.getMaxMacroBlocks()),
2327                         pp.mMaxFrameRate,
2328                         new Size(Math.max(newBlockSize.getWidth(), pp.mBlockSize.getWidth() * 16),
2329                                  Math.max(newBlockSize.getHeight(), pp.mBlockSize.getHeight() * 16))
2330                 );
2331             }
2332 
2333             /**
2334              * Create a performance point for a given frame size and frame rate.
2335              *
2336              * @param width width of the frame in pixels
2337              * @param height height of the frame in pixels
2338              * @param frameRate frame rate in frames per second
2339              */
PerformancePoint(int width, int height, int frameRate)2340             public PerformancePoint(int width, int height, int frameRate) {
2341                 this(width, height, frameRate, frameRate /* maxFrameRate */, new Size(16, 16));
2342             }
2343 
2344             /** Saturates a long value to int */
saturateLongToInt(long value)2345             private int saturateLongToInt(long value) {
2346                 if (value < Integer.MIN_VALUE) {
2347                     return Integer.MIN_VALUE;
2348                 } else if (value > Integer.MAX_VALUE) {
2349                     return Integer.MAX_VALUE;
2350                 } else {
2351                     return (int)value;
2352                 }
2353             }
2354 
2355             /* This method may overflow */
align(int value, int alignment)2356             private int align(int value, int alignment) {
2357                 return Utils.divUp(value, alignment) * alignment;
2358             }
2359 
2360             /** Checks that value is a power of two. */
checkPowerOfTwo2(int value, @NonNull String description)2361             private void checkPowerOfTwo2(int value, @NonNull String description) {
2362                 if (value == 0 || (value & (value - 1)) != 0) {
2363                     throw new IllegalArgumentException(
2364                             description + " (" + value + ") must be a power of 2");
2365                 }
2366             }
2367 
2368             /**
2369              * Checks whether the performance point covers a media format.
2370              *
2371              * @param format Stream format considered
2372              *
2373              * @return {@code true} if the performance point covers the format.
2374              */
covers(@onNull MediaFormat format)2375             public boolean covers(@NonNull MediaFormat format) {
2376                 PerformancePoint other = new PerformancePoint(
2377                         format.getInteger(MediaFormat.KEY_WIDTH, 0),
2378                         format.getInteger(MediaFormat.KEY_HEIGHT, 0),
2379                         // safely convert ceil(double) to int through float cast and Math.round
2380                         Math.round((float)(
2381                                 Math.ceil(format.getNumber(MediaFormat.KEY_FRAME_RATE, 0)
2382                                         .doubleValue()))));
2383                 return covers(other);
2384             }
2385 
2386             /**
2387              * Checks whether the performance point covers another performance point. Use this
2388              * method to determine if a performance point advertised by a codec covers the
2389              * performance point required. This method can also be used for loose ordering as this
2390              * method is transitive.
2391              *
2392              * @param other other performance point considered
2393              *
2394              * @return {@code true} if the performance point covers the other.
2395              */
covers(@onNull PerformancePoint other)2396             public boolean covers(@NonNull PerformancePoint other) {
2397                 // convert performance points to common block size
2398                 Size commonSize = getCommonBlockSize(other);
2399                 PerformancePoint aligned = new PerformancePoint(this, commonSize);
2400                 PerformancePoint otherAligned = new PerformancePoint(other, commonSize);
2401 
2402                 return (aligned.getMaxMacroBlocks() >= otherAligned.getMaxMacroBlocks()
2403                         && aligned.mMaxFrameRate >= otherAligned.mMaxFrameRate
2404                         && aligned.mMaxMacroBlockRate >= otherAligned.mMaxMacroBlockRate);
2405             }
2406 
getCommonBlockSize(@onNull PerformancePoint other)2407             private @NonNull Size getCommonBlockSize(@NonNull PerformancePoint other) {
2408                 return new Size(
2409                         Math.max(mBlockSize.getWidth(), other.mBlockSize.getWidth()) * 16,
2410                         Math.max(mBlockSize.getHeight(), other.mBlockSize.getHeight()) * 16);
2411             }
2412 
2413             @Override
equals(Object o)2414             public boolean equals(Object o) {
2415                 if (o instanceof PerformancePoint) {
2416                     // convert performance points to common block size
2417                     PerformancePoint other = (PerformancePoint)o;
2418                     Size commonSize = getCommonBlockSize(other);
2419                     PerformancePoint aligned = new PerformancePoint(this, commonSize);
2420                     PerformancePoint otherAligned = new PerformancePoint(other, commonSize);
2421 
2422                     return (aligned.getMaxMacroBlocks() == otherAligned.getMaxMacroBlocks()
2423                             && aligned.mMaxFrameRate == otherAligned.mMaxFrameRate
2424                             && aligned.mMaxMacroBlockRate == otherAligned.mMaxMacroBlockRate);
2425                 }
2426                 return false;
2427             }
2428 
2429             /** 480p 24fps */
2430             @NonNull
2431             public static final PerformancePoint SD_24 = new PerformancePoint(720, 480, 24);
2432             /** 576p 25fps */
2433             @NonNull
2434             public static final PerformancePoint SD_25 = new PerformancePoint(720, 576, 25);
2435             /** 480p 30fps */
2436             @NonNull
2437             public static final PerformancePoint SD_30 = new PerformancePoint(720, 480, 30);
2438             /** 480p 48fps */
2439             @NonNull
2440             public static final PerformancePoint SD_48 = new PerformancePoint(720, 480, 48);
2441             /** 576p 50fps */
2442             @NonNull
2443             public static final PerformancePoint SD_50 = new PerformancePoint(720, 576, 50);
2444             /** 480p 60fps */
2445             @NonNull
2446             public static final PerformancePoint SD_60 = new PerformancePoint(720, 480, 60);
2447 
2448             /** 720p 24fps */
2449             @NonNull
2450             public static final PerformancePoint HD_24 = new PerformancePoint(1280, 720, 24);
2451             /** 720p 25fps */
2452             @NonNull
2453             public static final PerformancePoint HD_25 = new PerformancePoint(1280, 720, 25);
2454             /** 720p 30fps */
2455             @NonNull
2456             public static final PerformancePoint HD_30 = new PerformancePoint(1280, 720, 30);
2457             /** 720p 50fps */
2458             @NonNull
2459             public static final PerformancePoint HD_50 = new PerformancePoint(1280, 720, 50);
2460             /** 720p 60fps */
2461             @NonNull
2462             public static final PerformancePoint HD_60 = new PerformancePoint(1280, 720, 60);
2463             /** 720p 100fps */
2464             @NonNull
2465             public static final PerformancePoint HD_100 = new PerformancePoint(1280, 720, 100);
2466             /** 720p 120fps */
2467             @NonNull
2468             public static final PerformancePoint HD_120 = new PerformancePoint(1280, 720, 120);
2469             /** 720p 200fps */
2470             @NonNull
2471             public static final PerformancePoint HD_200 = new PerformancePoint(1280, 720, 200);
2472             /** 720p 240fps */
2473             @NonNull
2474             public static final PerformancePoint HD_240 = new PerformancePoint(1280, 720, 240);
2475 
2476             /** 1080p 24fps */
2477             @NonNull
2478             public static final PerformancePoint FHD_24 = new PerformancePoint(1920, 1080, 24);
2479             /** 1080p 25fps */
2480             @NonNull
2481             public static final PerformancePoint FHD_25 = new PerformancePoint(1920, 1080, 25);
2482             /** 1080p 30fps */
2483             @NonNull
2484             public static final PerformancePoint FHD_30 = new PerformancePoint(1920, 1080, 30);
2485             /** 1080p 50fps */
2486             @NonNull
2487             public static final PerformancePoint FHD_50 = new PerformancePoint(1920, 1080, 50);
2488             /** 1080p 60fps */
2489             @NonNull
2490             public static final PerformancePoint FHD_60 = new PerformancePoint(1920, 1080, 60);
2491             /** 1080p 100fps */
2492             @NonNull
2493             public static final PerformancePoint FHD_100 = new PerformancePoint(1920, 1080, 100);
2494             /** 1080p 120fps */
2495             @NonNull
2496             public static final PerformancePoint FHD_120 = new PerformancePoint(1920, 1080, 120);
2497             /** 1080p 200fps */
2498             @NonNull
2499             public static final PerformancePoint FHD_200 = new PerformancePoint(1920, 1080, 200);
2500             /** 1080p 240fps */
2501             @NonNull
2502             public static final PerformancePoint FHD_240 = new PerformancePoint(1920, 1080, 240);
2503 
2504             /** 2160p 24fps */
2505             @NonNull
2506             public static final PerformancePoint UHD_24 = new PerformancePoint(3840, 2160, 24);
2507             /** 2160p 25fps */
2508             @NonNull
2509             public static final PerformancePoint UHD_25 = new PerformancePoint(3840, 2160, 25);
2510             /** 2160p 30fps */
2511             @NonNull
2512             public static final PerformancePoint UHD_30 = new PerformancePoint(3840, 2160, 30);
2513             /** 2160p 50fps */
2514             @NonNull
2515             public static final PerformancePoint UHD_50 = new PerformancePoint(3840, 2160, 50);
2516             /** 2160p 60fps */
2517             @NonNull
2518             public static final PerformancePoint UHD_60 = new PerformancePoint(3840, 2160, 60);
2519             /** 2160p 100fps */
2520             @NonNull
2521             public static final PerformancePoint UHD_100 = new PerformancePoint(3840, 2160, 100);
2522             /** 2160p 120fps */
2523             @NonNull
2524             public static final PerformancePoint UHD_120 = new PerformancePoint(3840, 2160, 120);
2525             /** 2160p 200fps */
2526             @NonNull
2527             public static final PerformancePoint UHD_200 = new PerformancePoint(3840, 2160, 200);
2528             /** 2160p 240fps */
2529             @NonNull
2530             public static final PerformancePoint UHD_240 = new PerformancePoint(3840, 2160, 240);
2531         }
2532 
2533         /**
2534          * Returns the supported performance points. May return {@code null} if the codec did not
2535          * publish any performance point information (e.g. the vendor codecs have not been updated
2536          * to the latest android release). May return an empty list if the codec published that
2537          * if does not guarantee any performance points.
2538          * <p>
2539          * This is a performance guarantee provided by the device manufacturer for hardware codecs
2540          * based on hardware capabilities of the device.
2541          * <p>
2542          * The returned list is sorted first by decreasing number of pixels, then by decreasing
2543          * width, and finally by decreasing frame rate.
2544          * Performance points assume a single active codec. For use cases where multiple
2545          * codecs are active, should use that highest pixel count, and add the frame rates of
2546          * each individual codec.
2547          * <p class=note>
2548          * 32-bit processes will not support resolutions larger than 4096x4096 due to
2549          * the limited address space, but performance points will be presented as is.
2550          * In other words, even though a component publishes a performance point for
2551          * a resolution higher than 4096x4096, it does not mean that the resolution is supported
2552          * for 32-bit processes.
2553          */
2554         @Nullable
getSupportedPerformancePoints()2555         public List<PerformancePoint> getSupportedPerformancePoints() {
2556             return mPerformancePoints;
2557         }
2558 
2559         /**
2560          * Returns whether a given video size ({@code width} and
2561          * {@code height}) and {@code frameRate} combination is supported.
2562          */
areSizeAndRateSupported( int width, int height, double frameRate)2563         public boolean areSizeAndRateSupported(
2564                 int width, int height, double frameRate) {
2565             return supports(width, height, frameRate);
2566         }
2567 
2568         /**
2569          * Returns whether a given video size ({@code width} and
2570          * {@code height}) is supported.
2571          */
isSizeSupported(int width, int height)2572         public boolean isSizeSupported(int width, int height) {
2573             return supports(width, height, null);
2574         }
2575 
supports(Integer width, Integer height, Number rate)2576         private boolean supports(Integer width, Integer height, Number rate) {
2577             boolean ok = true;
2578 
2579             if (ok && width != null) {
2580                 ok = mWidthRange.contains(width)
2581                         && (width % mWidthAlignment == 0);
2582             }
2583             if (ok && height != null) {
2584                 ok = mHeightRange.contains(height)
2585                         && (height % mHeightAlignment == 0);
2586             }
2587             if (ok && rate != null) {
2588                 ok = mFrameRateRange.contains(Utils.intRangeFor(rate.doubleValue()));
2589             }
2590             if (ok && height != null && width != null) {
2591                 ok = Math.min(height, width) <= mSmallerDimensionUpperLimit;
2592 
2593                 final int widthInBlocks = Utils.divUp(width, mBlockWidth);
2594                 final int heightInBlocks = Utils.divUp(height, mBlockHeight);
2595                 final int blockCount = widthInBlocks * heightInBlocks;
2596                 ok = ok && mBlockCountRange.contains(blockCount)
2597                         && mBlockAspectRatioRange.contains(
2598                                 new Rational(widthInBlocks, heightInBlocks))
2599                         && mAspectRatioRange.contains(new Rational(width, height));
2600                 if (ok && rate != null) {
2601                     double blocksPerSec = blockCount * rate.doubleValue();
2602                     ok = mBlocksPerSecondRange.contains(
2603                             Utils.longRangeFor(blocksPerSec));
2604                 }
2605             }
2606             return ok;
2607         }
2608 
2609         /* package private */
2610         // must not contain KEY_PROFILE
2611         static final Set<String> VIDEO_LEVEL_CRITICAL_FORMAT_KEYS = Set.of(
2612                 MediaFormat.KEY_WIDTH,
2613                 MediaFormat.KEY_HEIGHT,
2614                 MediaFormat.KEY_FRAME_RATE,
2615                 MediaFormat.KEY_BIT_RATE,
2616                 MediaFormat.KEY_MIME);
2617 
2618         /**
2619          * @hide
2620          * @throws java.lang.ClassCastException */
supportsFormat(MediaFormat format)2621         public boolean supportsFormat(MediaFormat format) {
2622             final Map<String, Object> map = format.getMap();
2623             Integer width = (Integer)map.get(MediaFormat.KEY_WIDTH);
2624             Integer height = (Integer)map.get(MediaFormat.KEY_HEIGHT);
2625             Number rate = (Number)map.get(MediaFormat.KEY_FRAME_RATE);
2626 
2627             if (!supports(width, height, rate)) {
2628                 return false;
2629             }
2630 
2631             if (!CodecCapabilities.supportsBitrate(mBitrateRange, format)) {
2632                 return false;
2633             }
2634 
2635             // we ignore color-format for now as it is not reliably reported by codec
2636             return true;
2637         }
2638 
2639         /* no public constructor */
VideoCapabilities()2640         private VideoCapabilities() { }
2641 
2642         /** @hide */
2643         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
create( MediaFormat info, CodecCapabilities parent)2644         public static VideoCapabilities create(
2645                 MediaFormat info, CodecCapabilities parent) {
2646             VideoCapabilities caps = new VideoCapabilities();
2647             caps.init(info, parent);
2648             return caps;
2649         }
2650 
init(MediaFormat info, CodecCapabilities parent)2651         private void init(MediaFormat info, CodecCapabilities parent) {
2652             mParent = parent;
2653             initWithPlatformLimits();
2654             applyLevelLimits();
2655             parseFromInfo(info);
2656             updateLimits();
2657         }
2658 
2659         /** @hide */
getBlockSize()2660         public Size getBlockSize() {
2661             return new Size(mBlockWidth, mBlockHeight);
2662         }
2663 
2664         /** @hide */
getBlockCountRange()2665         public Range<Integer> getBlockCountRange() {
2666             return mBlockCountRange;
2667         }
2668 
2669         /** @hide */
getBlocksPerSecondRange()2670         public Range<Long> getBlocksPerSecondRange() {
2671             return mBlocksPerSecondRange;
2672         }
2673 
2674         /** @hide */
getAspectRatioRange(boolean blocks)2675         public Range<Rational> getAspectRatioRange(boolean blocks) {
2676             return blocks ? mBlockAspectRatioRange : mAspectRatioRange;
2677         }
2678 
initWithPlatformLimits()2679         private void initWithPlatformLimits() {
2680             mBitrateRange = BITRATE_RANGE;
2681 
2682             mWidthRange  = getSizeRange();
2683             mHeightRange = getSizeRange();
2684             mFrameRateRange = FRAME_RATE_RANGE;
2685 
2686             mHorizontalBlockRange = getSizeRange();
2687             mVerticalBlockRange   = getSizeRange();
2688 
2689             // full positive ranges are supported as these get calculated
2690             mBlockCountRange      = POSITIVE_INTEGERS;
2691             mBlocksPerSecondRange = POSITIVE_LONGS;
2692 
2693             mBlockAspectRatioRange = POSITIVE_RATIONALS;
2694             mAspectRatioRange      = POSITIVE_RATIONALS;
2695 
2696             mWidthAlignment = 1;
2697             mHeightAlignment = 1;
2698             mBlockWidth = 1;
2699             mBlockHeight = 1;
2700             mSmallerDimensionUpperLimit = getSizeRange().getUpper();
2701         }
2702 
getPerformancePoints(Map<String, Object> map)2703         private @Nullable List<PerformancePoint> getPerformancePoints(Map<String, Object> map) {
2704             Vector<PerformancePoint> ret = new Vector<>();
2705             final String prefix = "performance-point-";
2706             Set<String> keys = map.keySet();
2707             for (String key : keys) {
2708                 // looking for: performance-point-WIDTHxHEIGHT-range
2709                 if (!key.startsWith(prefix)) {
2710                     continue;
2711                 }
2712                 String subKey = key.substring(prefix.length());
2713                 if (subKey.equals("none") && ret.size() == 0) {
2714                     // This means that component knowingly did not publish performance points.
2715                     // This is different from when the component forgot to publish performance
2716                     // points.
2717                     return Collections.unmodifiableList(ret);
2718                 }
2719                 String[] temp = key.split("-");
2720                 if (temp.length != 4) {
2721                     continue;
2722                 }
2723                 String sizeStr = temp[2];
2724                 Size size = Utils.parseSize(sizeStr, null);
2725                 if (size == null || size.getWidth() * size.getHeight() <= 0) {
2726                     continue;
2727                 }
2728                 Range<Long> range = Utils.parseLongRange(map.get(key), null);
2729                 if (range == null || range.getLower() < 0 || range.getUpper() < 0) {
2730                     continue;
2731                 }
2732                 PerformancePoint given = new PerformancePoint(
2733                         size.getWidth(), size.getHeight(), range.getLower().intValue(),
2734                         range.getUpper().intValue(), new Size(mBlockWidth, mBlockHeight));
2735                 PerformancePoint rotated = new PerformancePoint(
2736                         size.getHeight(), size.getWidth(), range.getLower().intValue(),
2737                         range.getUpper().intValue(), new Size(mBlockWidth, mBlockHeight));
2738                 ret.add(given);
2739                 if (!given.covers(rotated)) {
2740                     ret.add(rotated);
2741                 }
2742             }
2743 
2744             // check if the component specified no performance point indication
2745             if (ret.size() == 0) {
2746                 return null;
2747             }
2748 
2749             // sort reversed by area first, then by frame rate
2750             ret.sort((a, b) ->
2751                      -((a.getMaxMacroBlocks() != b.getMaxMacroBlocks()) ?
2752                                (a.getMaxMacroBlocks() < b.getMaxMacroBlocks() ? -1 : 1) :
2753                        (a.getMaxMacroBlockRate() != b.getMaxMacroBlockRate()) ?
2754                                (a.getMaxMacroBlockRate() < b.getMaxMacroBlockRate() ? -1 : 1) :
2755                        (a.getMaxFrameRate() != b.getMaxFrameRate()) ?
2756                                (a.getMaxFrameRate() < b.getMaxFrameRate() ? -1 : 1) : 0));
2757 
2758             return Collections.unmodifiableList(ret);
2759         }
2760 
2761         private Map<Size, Range<Long>> getMeasuredFrameRates(Map<String, Object> map) {
2762             Map<Size, Range<Long>> ret = new HashMap<Size, Range<Long>>();
2763             final String prefix = "measured-frame-rate-";
2764             Set<String> keys = map.keySet();
2765             for (String key : keys) {
2766                 // looking for: measured-frame-rate-WIDTHxHEIGHT-range
2767                 if (!key.startsWith(prefix)) {
2768                     continue;
2769                 }
2770                 String subKey = key.substring(prefix.length());
2771                 String[] temp = key.split("-");
2772                 if (temp.length != 5) {
2773                     continue;
2774                 }
2775                 String sizeStr = temp[3];
2776                 Size size = Utils.parseSize(sizeStr, null);
2777                 if (size == null || size.getWidth() * size.getHeight() <= 0) {
2778                     continue;
2779                 }
2780                 Range<Long> range = Utils.parseLongRange(map.get(key), null);
2781                 if (range == null || range.getLower() < 0 || range.getUpper() < 0) {
2782                     continue;
2783                 }
2784                 ret.put(size, range);
2785             }
2786             return ret;
2787         }
2788 
2789         private static Pair<Range<Integer>, Range<Integer>> parseWidthHeightRanges(Object o) {
2790             Pair<Size, Size> range = Utils.parseSizeRange(o);
2791             if (range != null) {
2792                 try {
2793                     return Pair.create(
2794                             Range.create(range.first.getWidth(), range.second.getWidth()),
2795                             Range.create(range.first.getHeight(), range.second.getHeight()));
2796                 } catch (IllegalArgumentException e) {
2797                     Log.w(TAG, "could not parse size range '" + o + "'");
2798                 }
2799             }
2800             return null;
2801         }
2802 
2803         /** @hide */
2804         public static int equivalentVP9Level(MediaFormat info) {
2805             final Map<String, Object> map = info.getMap();
2806 
2807             Size blockSize = Utils.parseSize(map.get("block-size"), new Size(8, 8));
2808             int BS = blockSize.getWidth() * blockSize.getHeight();
2809 
2810             Range<Integer> counts = Utils.parseIntRange(map.get("block-count-range"), null);
2811             int FS = counts == null ? 0 : BS * counts.getUpper();
2812 
2813             Range<Long> blockRates =
2814                 Utils.parseLongRange(map.get("blocks-per-second-range"), null);
2815             long SR = blockRates == null ? 0 : BS * blockRates.getUpper();
2816 
2817             Pair<Range<Integer>, Range<Integer>> dimensionRanges =
2818                 parseWidthHeightRanges(map.get("size-range"));
2819             int D = dimensionRanges == null ? 0 : Math.max(
2820                     dimensionRanges.first.getUpper(), dimensionRanges.second.getUpper());
2821 
2822             Range<Integer> bitRates = Utils.parseIntRange(map.get("bitrate-range"), null);
2823             int BR = bitRates == null ? 0 : Utils.divUp(bitRates.getUpper(), 1000);
2824 
2825             if (SR <=      829440 && FS <=    36864 && BR <=    200 && D <=   512)
2826                 return CodecProfileLevel.VP9Level1;
2827             if (SR <=     2764800 && FS <=    73728 && BR <=    800 && D <=   768)
2828                 return CodecProfileLevel.VP9Level11;
2829             if (SR <=     4608000 && FS <=   122880 && BR <=   1800 && D <=   960)
2830                 return CodecProfileLevel.VP9Level2;
2831             if (SR <=     9216000 && FS <=   245760 && BR <=   3600 && D <=  1344)
2832                 return CodecProfileLevel.VP9Level21;
2833             if (SR <=    20736000 && FS <=   552960 && BR <=   7200 && D <=  2048)
2834                 return CodecProfileLevel.VP9Level3;
2835             if (SR <=    36864000 && FS <=   983040 && BR <=  12000 && D <=  2752)
2836                 return CodecProfileLevel.VP9Level31;
2837             if (SR <=    83558400 && FS <=  2228224 && BR <=  18000 && D <=  4160)
2838                 return CodecProfileLevel.VP9Level4;
2839             if (SR <=   160432128 && FS <=  2228224 && BR <=  30000 && D <=  4160)
2840                 return CodecProfileLevel.VP9Level41;
2841             if (SR <=   311951360 && FS <=  8912896 && BR <=  60000 && D <=  8384)
2842                 return CodecProfileLevel.VP9Level5;
2843             if (SR <=   588251136 && FS <=  8912896 && BR <= 120000 && D <=  8384)
2844                 return CodecProfileLevel.VP9Level51;
2845             if (SR <=  1176502272 && FS <=  8912896 && BR <= 180000 && D <=  8384)
2846                 return CodecProfileLevel.VP9Level52;
2847             if (SR <=  1176502272 && FS <= 35651584 && BR <= 180000 && D <= 16832)
2848                 return CodecProfileLevel.VP9Level6;
2849             if (SR <= 2353004544L && FS <= 35651584 && BR <= 240000 && D <= 16832)
2850                 return CodecProfileLevel.VP9Level61;
2851             if (SR <= 4706009088L && FS <= 35651584 && BR <= 480000 && D <= 16832)
2852                 return CodecProfileLevel.VP9Level62;
2853             // returning largest level
2854             return CodecProfileLevel.VP9Level62;
2855         }
2856 
2857         private void parseFromInfo(MediaFormat info) {
2858             final Map<String, Object> map = info.getMap();
2859             Size blockSize = new Size(mBlockWidth, mBlockHeight);
2860             Size alignment = new Size(mWidthAlignment, mHeightAlignment);
2861             Range<Integer> counts = null, widths = null, heights = null;
2862             Range<Integer> frameRates = null, bitRates = null;
2863             Range<Long> blockRates = null;
2864             Range<Rational> ratios = null, blockRatios = null;
2865 
2866             blockSize = Utils.parseSize(map.get("block-size"), blockSize);
2867             alignment = Utils.parseSize(map.get("alignment"), alignment);
2868             counts = Utils.parseIntRange(map.get("block-count-range"), null);
2869             blockRates =
2870                 Utils.parseLongRange(map.get("blocks-per-second-range"), null);
2871             mMeasuredFrameRates = getMeasuredFrameRates(map);
2872             mPerformancePoints = getPerformancePoints(map);
2873             Pair<Range<Integer>, Range<Integer>> sizeRanges =
2874                 parseWidthHeightRanges(map.get("size-range"));
2875             if (sizeRanges != null) {
2876                 widths = sizeRanges.first;
2877                 heights = sizeRanges.second;
2878             }
2879             // for now this just means using the smaller max size as 2nd
2880             // upper limit.
2881             // for now we are keeping the profile specific "width/height
2882             // in macroblocks" limits.
2883             if (map.containsKey("feature-can-swap-width-height")) {
2884                 if (widths != null) {
2885                     mSmallerDimensionUpperLimit =
2886                         Math.min(widths.getUpper(), heights.getUpper());
2887                     widths = heights = widths.extend(heights);
2888                 } else {
2889                     Log.w(TAG, "feature can-swap-width-height is best used with size-range");
2890                     mSmallerDimensionUpperLimit =
2891                         Math.min(mWidthRange.getUpper(), mHeightRange.getUpper());
2892                     mWidthRange = mHeightRange = mWidthRange.extend(mHeightRange);
2893                 }
2894             }
2895 
2896             ratios = Utils.parseRationalRange(
2897                     map.get("block-aspect-ratio-range"), null);
2898             blockRatios = Utils.parseRationalRange(
2899                     map.get("pixel-aspect-ratio-range"), null);
2900             frameRates = Utils.parseIntRange(map.get("frame-rate-range"), null);
2901             if (frameRates != null) {
2902                 try {
2903                     frameRates = frameRates.intersect(FRAME_RATE_RANGE);
2904                 } catch (IllegalArgumentException e) {
2905                     Log.w(TAG, "frame rate range (" + frameRates
2906                             + ") is out of limits: " + FRAME_RATE_RANGE);
2907                     frameRates = null;
2908                 }
2909             }
2910             bitRates = Utils.parseIntRange(map.get("bitrate-range"), null);
2911             if (bitRates != null) {
2912                 try {
2913                     bitRates = bitRates.intersect(BITRATE_RANGE);
2914                 } catch (IllegalArgumentException e) {
2915                     Log.w(TAG,  "bitrate range (" + bitRates
2916                             + ") is out of limits: " + BITRATE_RANGE);
2917                     bitRates = null;
2918                 }
2919             }
2920 
2921             checkPowerOfTwo(
2922                     blockSize.getWidth(), "block-size width must be power of two");
2923             checkPowerOfTwo(
2924                     blockSize.getHeight(), "block-size height must be power of two");
2925 
2926             checkPowerOfTwo(
2927                     alignment.getWidth(), "alignment width must be power of two");
2928             checkPowerOfTwo(
2929                     alignment.getHeight(), "alignment height must be power of two");
2930 
2931             // update block-size and alignment
2932             applyMacroBlockLimits(
2933                     Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE,
2934                     Long.MAX_VALUE, blockSize.getWidth(), blockSize.getHeight(),
2935                     alignment.getWidth(), alignment.getHeight());
2936 
2937             if ((mParent.mError & ERROR_UNSUPPORTED) != 0 || mAllowMbOverride) {
2938                 // codec supports profiles that we don't know.
2939                 // Use supplied values clipped to platform limits
2940                 if (widths != null) {
2941                     mWidthRange = getSizeRange().intersect(widths);
2942                 }
2943                 if (heights != null) {
2944                     mHeightRange = getSizeRange().intersect(heights);
2945                 }
2946                 if (counts != null) {
2947                     mBlockCountRange = POSITIVE_INTEGERS.intersect(
2948                             Utils.factorRange(counts, mBlockWidth * mBlockHeight
2949                                     / blockSize.getWidth() / blockSize.getHeight()));
2950                 }
2951                 if (blockRates != null) {
2952                     mBlocksPerSecondRange = POSITIVE_LONGS.intersect(
2953                             Utils.factorRange(blockRates, mBlockWidth * mBlockHeight
2954                                     / blockSize.getWidth() / blockSize.getHeight()));
2955                 }
2956                 if (blockRatios != null) {
2957                     mBlockAspectRatioRange = POSITIVE_RATIONALS.intersect(
2958                             Utils.scaleRange(blockRatios,
2959                                     mBlockHeight / blockSize.getHeight(),
2960                                     mBlockWidth / blockSize.getWidth()));
2961                 }
2962                 if (ratios != null) {
2963                     mAspectRatioRange = POSITIVE_RATIONALS.intersect(ratios);
2964                 }
2965                 if (frameRates != null) {
2966                     mFrameRateRange = FRAME_RATE_RANGE.intersect(frameRates);
2967                 }
2968                 if (bitRates != null) {
2969                     // only allow bitrate override if unsupported profiles were encountered
2970                     if ((mParent.mError & ERROR_UNSUPPORTED) != 0) {
2971                         mBitrateRange = BITRATE_RANGE.intersect(bitRates);
2972                     } else {
2973                         mBitrateRange = mBitrateRange.intersect(bitRates);
2974                     }
2975                 }
2976             } else {
2977                 // no unsupported profile/levels, so restrict values to known limits
2978                 if (widths != null) {
2979                     mWidthRange = mWidthRange.intersect(widths);
2980                 }
2981                 if (heights != null) {
2982                     mHeightRange = mHeightRange.intersect(heights);
2983                 }
2984                 if (counts != null) {
2985                     mBlockCountRange = mBlockCountRange.intersect(
2986                             Utils.factorRange(counts, mBlockWidth * mBlockHeight
2987                                     / blockSize.getWidth() / blockSize.getHeight()));
2988                 }
2989                 if (blockRates != null) {
2990                     mBlocksPerSecondRange = mBlocksPerSecondRange.intersect(
2991                             Utils.factorRange(blockRates, mBlockWidth * mBlockHeight
2992                                     / blockSize.getWidth() / blockSize.getHeight()));
2993                 }
2994                 if (blockRatios != null) {
2995                     mBlockAspectRatioRange = mBlockAspectRatioRange.intersect(
2996                             Utils.scaleRange(blockRatios,
2997                                     mBlockHeight / blockSize.getHeight(),
2998                                     mBlockWidth / blockSize.getWidth()));
2999                 }
3000                 if (ratios != null) {
3001                     mAspectRatioRange = mAspectRatioRange.intersect(ratios);
3002                 }
3003                 if (frameRates != null) {
3004                     mFrameRateRange = mFrameRateRange.intersect(frameRates);
3005                 }
3006                 if (bitRates != null) {
3007                     mBitrateRange = mBitrateRange.intersect(bitRates);
3008                 }
3009             }
3010             updateLimits();
3011         }
3012 
3013         private void applyBlockLimits(
3014                 int blockWidth, int blockHeight,
3015                 Range<Integer> counts, Range<Long> rates, Range<Rational> ratios) {
3016             checkPowerOfTwo(blockWidth, "blockWidth must be a power of two");
3017             checkPowerOfTwo(blockHeight, "blockHeight must be a power of two");
3018 
3019             final int newBlockWidth = Math.max(blockWidth, mBlockWidth);
3020             final int newBlockHeight = Math.max(blockHeight, mBlockHeight);
3021 
3022             // factor will always be a power-of-2
3023             int factor =
3024                 newBlockWidth * newBlockHeight / mBlockWidth / mBlockHeight;
3025             if (factor != 1) {
3026                 mBlockCountRange = Utils.factorRange(mBlockCountRange, factor);
3027                 mBlocksPerSecondRange = Utils.factorRange(
3028                         mBlocksPerSecondRange, factor);
3029                 mBlockAspectRatioRange = Utils.scaleRange(
3030                         mBlockAspectRatioRange,
3031                         newBlockHeight / mBlockHeight,
3032                         newBlockWidth / mBlockWidth);
3033                 mHorizontalBlockRange = Utils.factorRange(
3034                         mHorizontalBlockRange, newBlockWidth / mBlockWidth);
3035                 mVerticalBlockRange = Utils.factorRange(
3036                         mVerticalBlockRange, newBlockHeight / mBlockHeight);
3037             }
3038             factor = newBlockWidth * newBlockHeight / blockWidth / blockHeight;
3039             if (factor != 1) {
3040                 counts = Utils.factorRange(counts, factor);
3041                 rates = Utils.factorRange(rates, factor);
3042                 ratios = Utils.scaleRange(
3043                         ratios, newBlockHeight / blockHeight,
3044                         newBlockWidth / blockWidth);
3045             }
3046             mBlockCountRange = mBlockCountRange.intersect(counts);
3047             mBlocksPerSecondRange = mBlocksPerSecondRange.intersect(rates);
3048             mBlockAspectRatioRange = mBlockAspectRatioRange.intersect(ratios);
3049             mBlockWidth = newBlockWidth;
3050             mBlockHeight = newBlockHeight;
3051         }
3052 
3053         private void applyAlignment(int widthAlignment, int heightAlignment) {
3054             checkPowerOfTwo(widthAlignment, "widthAlignment must be a power of two");
3055             checkPowerOfTwo(heightAlignment, "heightAlignment must be a power of two");
3056 
3057             if (widthAlignment > mBlockWidth || heightAlignment > mBlockHeight) {
3058                 // maintain assumption that 0 < alignment <= block-size
3059                 applyBlockLimits(
3060                         Math.max(widthAlignment, mBlockWidth),
3061                         Math.max(heightAlignment, mBlockHeight),
3062                         POSITIVE_INTEGERS, POSITIVE_LONGS, POSITIVE_RATIONALS);
3063             }
3064 
3065             mWidthAlignment = Math.max(widthAlignment, mWidthAlignment);
3066             mHeightAlignment = Math.max(heightAlignment, mHeightAlignment);
3067 
3068             mWidthRange = Utils.alignRange(mWidthRange, mWidthAlignment);
3069             mHeightRange = Utils.alignRange(mHeightRange, mHeightAlignment);
3070         }
3071 
3072         private void updateLimits() {
3073             // pixels -> blocks <- counts
3074             mHorizontalBlockRange = mHorizontalBlockRange.intersect(
3075                     Utils.factorRange(mWidthRange, mBlockWidth));
3076             mHorizontalBlockRange = mHorizontalBlockRange.intersect(
3077                     Range.create(
3078                             mBlockCountRange.getLower() / mVerticalBlockRange.getUpper(),
3079                             mBlockCountRange.getUpper() / mVerticalBlockRange.getLower()));
3080             mVerticalBlockRange = mVerticalBlockRange.intersect(
3081                     Utils.factorRange(mHeightRange, mBlockHeight));
3082             mVerticalBlockRange = mVerticalBlockRange.intersect(
3083                     Range.create(
3084                             mBlockCountRange.getLower() / mHorizontalBlockRange.getUpper(),
3085                             mBlockCountRange.getUpper() / mHorizontalBlockRange.getLower()));
3086             mBlockCountRange = mBlockCountRange.intersect(
3087                     Range.create(
3088                             mHorizontalBlockRange.getLower()
3089                                     * mVerticalBlockRange.getLower(),
3090                             mHorizontalBlockRange.getUpper()
3091                                     * mVerticalBlockRange.getUpper()));
3092             mBlockAspectRatioRange = mBlockAspectRatioRange.intersect(
3093                     new Rational(
3094                             mHorizontalBlockRange.getLower(), mVerticalBlockRange.getUpper()),
3095                     new Rational(
3096                             mHorizontalBlockRange.getUpper(), mVerticalBlockRange.getLower()));
3097 
3098             // blocks -> pixels
3099             mWidthRange = mWidthRange.intersect(
3100                     (mHorizontalBlockRange.getLower() - 1) * mBlockWidth + mWidthAlignment,
3101                     mHorizontalBlockRange.getUpper() * mBlockWidth);
3102             mHeightRange = mHeightRange.intersect(
3103                     (mVerticalBlockRange.getLower() - 1) * mBlockHeight + mHeightAlignment,
3104                     mVerticalBlockRange.getUpper() * mBlockHeight);
3105             mAspectRatioRange = mAspectRatioRange.intersect(
3106                     new Rational(mWidthRange.getLower(), mHeightRange.getUpper()),
3107                     new Rational(mWidthRange.getUpper(), mHeightRange.getLower()));
3108 
3109             mSmallerDimensionUpperLimit = Math.min(
3110                     mSmallerDimensionUpperLimit,
3111                     Math.min(mWidthRange.getUpper(), mHeightRange.getUpper()));
3112 
3113             // blocks -> rate
3114             mBlocksPerSecondRange = mBlocksPerSecondRange.intersect(
3115                     mBlockCountRange.getLower() * (long)mFrameRateRange.getLower(),
3116                     mBlockCountRange.getUpper() * (long)mFrameRateRange.getUpper());
3117             mFrameRateRange = mFrameRateRange.intersect(
3118                     (int)(mBlocksPerSecondRange.getLower()
3119                             / mBlockCountRange.getUpper()),
3120                     (int)(mBlocksPerSecondRange.getUpper()
3121                             / (double)mBlockCountRange.getLower()));
3122         }
3123 
3124         private void applyMacroBlockLimits(
3125                 int maxHorizontalBlocks, int maxVerticalBlocks,
3126                 int maxBlocks, long maxBlocksPerSecond,
3127                 int blockWidth, int blockHeight,
3128                 int widthAlignment, int heightAlignment) {
3129             applyMacroBlockLimits(
3130                     1 /* minHorizontalBlocks */, 1 /* minVerticalBlocks */,
3131                     maxHorizontalBlocks, maxVerticalBlocks,
3132                     maxBlocks, maxBlocksPerSecond,
3133                     blockWidth, blockHeight, widthAlignment, heightAlignment);
3134         }
3135 
3136         private void applyMacroBlockLimits(
3137                 int minHorizontalBlocks, int minVerticalBlocks,
3138                 int maxHorizontalBlocks, int maxVerticalBlocks,
3139                 int maxBlocks, long maxBlocksPerSecond,
3140                 int blockWidth, int blockHeight,
3141                 int widthAlignment, int heightAlignment) {
3142             applyAlignment(widthAlignment, heightAlignment);
3143             applyBlockLimits(
3144                     blockWidth, blockHeight, Range.create(1, maxBlocks),
3145                     Range.create(1L, maxBlocksPerSecond),
3146                     Range.create(
3147                             new Rational(1, maxVerticalBlocks),
3148                             new Rational(maxHorizontalBlocks, 1)));
3149             mHorizontalBlockRange =
3150                     mHorizontalBlockRange.intersect(
3151                             Utils.divUp(minHorizontalBlocks, (mBlockWidth / blockWidth)),
3152                             maxHorizontalBlocks / (mBlockWidth / blockWidth));
3153             mVerticalBlockRange =
3154                     mVerticalBlockRange.intersect(
3155                             Utils.divUp(minVerticalBlocks, (mBlockHeight / blockHeight)),
3156                             maxVerticalBlocks / (mBlockHeight / blockHeight));
3157         }
3158 
3159         private void applyLevelLimits() {
3160             long maxBlocksPerSecond = 0;
3161             int maxBlocks = 0;
3162             int maxBps = 0;
3163             int maxDPBBlocks = 0;
3164 
3165             int errors = ERROR_NONE_SUPPORTED;
3166             CodecProfileLevel[] profileLevels = mParent.profileLevels;
3167             String mime = mParent.getMimeType();
3168 
3169             if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_AVC)) {
3170                 maxBlocks = 99;
3171                 maxBlocksPerSecond = 1485;
3172                 maxBps = 64000;
3173                 maxDPBBlocks = 396;
3174                 for (CodecProfileLevel profileLevel: profileLevels) {
3175                     int MBPS = 0, FS = 0, BR = 0, DPB = 0;
3176                     boolean supported = true;
3177                     switch (profileLevel.level) {
3178                         case CodecProfileLevel.AVCLevel1:
3179                             MBPS =     1485; FS =     99; BR =     64; DPB =    396; break;
3180                         case CodecProfileLevel.AVCLevel1b:
3181                             MBPS =     1485; FS =     99; BR =    128; DPB =    396; break;
3182                         case CodecProfileLevel.AVCLevel11:
3183                             MBPS =     3000; FS =    396; BR =    192; DPB =    900; break;
3184                         case CodecProfileLevel.AVCLevel12:
3185                             MBPS =     6000; FS =    396; BR =    384; DPB =   2376; break;
3186                         case CodecProfileLevel.AVCLevel13:
3187                             MBPS =    11880; FS =    396; BR =    768; DPB =   2376; break;
3188                         case CodecProfileLevel.AVCLevel2:
3189                             MBPS =    11880; FS =    396; BR =   2000; DPB =   2376; break;
3190                         case CodecProfileLevel.AVCLevel21:
3191                             MBPS =    19800; FS =    792; BR =   4000; DPB =   4752; break;
3192                         case CodecProfileLevel.AVCLevel22:
3193                             MBPS =    20250; FS =   1620; BR =   4000; DPB =   8100; break;
3194                         case CodecProfileLevel.AVCLevel3:
3195                             MBPS =    40500; FS =   1620; BR =  10000; DPB =   8100; break;
3196                         case CodecProfileLevel.AVCLevel31:
3197                             MBPS =   108000; FS =   3600; BR =  14000; DPB =  18000; break;
3198                         case CodecProfileLevel.AVCLevel32:
3199                             MBPS =   216000; FS =   5120; BR =  20000; DPB =  20480; break;
3200                         case CodecProfileLevel.AVCLevel4:
3201                             MBPS =   245760; FS =   8192; BR =  20000; DPB =  32768; break;
3202                         case CodecProfileLevel.AVCLevel41:
3203                             MBPS =   245760; FS =   8192; BR =  50000; DPB =  32768; break;
3204                         case CodecProfileLevel.AVCLevel42:
3205                             MBPS =   522240; FS =   8704; BR =  50000; DPB =  34816; break;
3206                         case CodecProfileLevel.AVCLevel5:
3207                             MBPS =   589824; FS =  22080; BR = 135000; DPB = 110400; break;
3208                         case CodecProfileLevel.AVCLevel51:
3209                             MBPS =   983040; FS =  36864; BR = 240000; DPB = 184320; break;
3210                         case CodecProfileLevel.AVCLevel52:
3211                             MBPS =  2073600; FS =  36864; BR = 240000; DPB = 184320; break;
3212                         case CodecProfileLevel.AVCLevel6:
3213                             MBPS =  4177920; FS = 139264; BR = 240000; DPB = 696320; break;
3214                         case CodecProfileLevel.AVCLevel61:
3215                             MBPS =  8355840; FS = 139264; BR = 480000; DPB = 696320; break;
3216                         case CodecProfileLevel.AVCLevel62:
3217                             MBPS = 16711680; FS = 139264; BR = 800000; DPB = 696320; break;
3218                         default:
3219                             Log.w(TAG, "Unrecognized level "
3220                                     + profileLevel.level + " for " + mime);
3221                             errors |= ERROR_UNRECOGNIZED;
3222                     }
3223                     switch (profileLevel.profile) {
3224                         case CodecProfileLevel.AVCProfileConstrainedHigh:
3225                         case CodecProfileLevel.AVCProfileHigh:
3226                             BR *= 1250; break;
3227                         case CodecProfileLevel.AVCProfileHigh10:
3228                             BR *= 3000; break;
3229                         case CodecProfileLevel.AVCProfileExtended:
3230                         case CodecProfileLevel.AVCProfileHigh422:
3231                         case CodecProfileLevel.AVCProfileHigh444:
3232                             Log.w(TAG, "Unsupported profile "
3233                                     + profileLevel.profile + " for " + mime);
3234                             errors |= ERROR_UNSUPPORTED;
3235                             supported = false;
3236                             // fall through - treat as base profile
3237                         case CodecProfileLevel.AVCProfileConstrainedBaseline:
3238                         case CodecProfileLevel.AVCProfileBaseline:
3239                         case CodecProfileLevel.AVCProfileMain:
3240                             BR *= 1000; break;
3241                         default:
3242                             Log.w(TAG, "Unrecognized profile "
3243                                     + profileLevel.profile + " for " + mime);
3244                             errors |= ERROR_UNRECOGNIZED;
3245                             BR *= 1000;
3246                     }
3247                     if (supported) {
3248                         errors &= ~ERROR_NONE_SUPPORTED;
3249                     }
3250                     maxBlocksPerSecond = Math.max(MBPS, maxBlocksPerSecond);
3251                     maxBlocks = Math.max(FS, maxBlocks);
3252                     maxBps = Math.max(BR, maxBps);
3253                     maxDPBBlocks = Math.max(maxDPBBlocks, DPB);
3254                 }
3255 
3256                 int maxLengthInBlocks = (int)(Math.sqrt(maxBlocks * 8));
3257                 applyMacroBlockLimits(
3258                         maxLengthInBlocks, maxLengthInBlocks,
3259                         maxBlocks, maxBlocksPerSecond,
3260                         16 /* blockWidth */, 16 /* blockHeight */,
3261                         1 /* widthAlignment */, 1 /* heightAlignment */);
3262             } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_MPEG2)) {
3263                 int maxWidth = 11, maxHeight = 9, maxRate = 15;
3264                 maxBlocks = 99;
3265                 maxBlocksPerSecond = 1485;
3266                 maxBps = 64000;
3267                 for (CodecProfileLevel profileLevel: profileLevels) {
3268                     int MBPS = 0, FS = 0, BR = 0, FR = 0, W = 0, H = 0;
3269                     boolean supported = true;
3270                     switch (profileLevel.profile) {
3271                         case CodecProfileLevel.MPEG2ProfileSimple:
3272                             switch (profileLevel.level) {
3273                                 case CodecProfileLevel.MPEG2LevelML:
3274                                     FR = 30; W = 45; H =  36; MBPS =  40500; FS =  1620; BR =  15000; break;
3275                                 default:
3276                                     Log.w(TAG, "Unrecognized profile/level "
3277                                             + profileLevel.profile + "/"
3278                                             + profileLevel.level + " for " + mime);
3279                                     errors |= ERROR_UNRECOGNIZED;
3280                             }
3281                             break;
3282                         case CodecProfileLevel.MPEG2ProfileMain:
3283                             switch (profileLevel.level) {
3284                                 case CodecProfileLevel.MPEG2LevelLL:
3285                                     FR = 30; W = 22; H =  18; MBPS =  11880; FS =   396; BR =  4000; break;
3286                                 case CodecProfileLevel.MPEG2LevelML:
3287                                     FR = 30; W = 45; H =  36; MBPS =  40500; FS =  1620; BR = 15000; break;
3288                                 case CodecProfileLevel.MPEG2LevelH14:
3289                                     FR = 60; W = 90; H =  68; MBPS = 183600; FS =  6120; BR = 60000; break;
3290                                 case CodecProfileLevel.MPEG2LevelHL:
3291                                     FR = 60; W = 120; H = 68; MBPS = 244800; FS =  8160; BR = 80000; break;
3292                                 case CodecProfileLevel.MPEG2LevelHP:
3293                                     FR = 60; W = 120; H = 68; MBPS = 489600; FS =  8160; BR = 80000; break;
3294                                 default:
3295                                     Log.w(TAG, "Unrecognized profile/level "
3296                                             + profileLevel.profile + "/"
3297                                             + profileLevel.level + " for " + mime);
3298                                     errors |= ERROR_UNRECOGNIZED;
3299                             }
3300                             break;
3301                         case CodecProfileLevel.MPEG2Profile422:
3302                         case CodecProfileLevel.MPEG2ProfileSNR:
3303                         case CodecProfileLevel.MPEG2ProfileSpatial:
3304                         case CodecProfileLevel.MPEG2ProfileHigh:
3305                             Log.i(TAG, "Unsupported profile "
3306                                     + profileLevel.profile + " for " + mime);
3307                             errors |= ERROR_UNSUPPORTED;
3308                             supported = false;
3309                             break;
3310                         default:
3311                             Log.w(TAG, "Unrecognized profile "
3312                                     + profileLevel.profile + " for " + mime);
3313                             errors |= ERROR_UNRECOGNIZED;
3314                     }
3315                     if (supported) {
3316                         errors &= ~ERROR_NONE_SUPPORTED;
3317                     }
3318                     maxBlocksPerSecond = Math.max(MBPS, maxBlocksPerSecond);
3319                     maxBlocks = Math.max(FS, maxBlocks);
3320                     maxBps = Math.max(BR * 1000, maxBps);
3321                     maxWidth = Math.max(W, maxWidth);
3322                     maxHeight = Math.max(H, maxHeight);
3323                     maxRate = Math.max(FR, maxRate);
3324                 }
3325                 applyMacroBlockLimits(maxWidth, maxHeight,
3326                         maxBlocks, maxBlocksPerSecond,
3327                         16 /* blockWidth */, 16 /* blockHeight */,
3328                         1 /* widthAlignment */, 1 /* heightAlignment */);
3329                 mFrameRateRange = mFrameRateRange.intersect(12, maxRate);
3330             } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_MPEG4)) {
3331                 int maxWidth = 11, maxHeight = 9, maxRate = 15;
3332                 maxBlocks = 99;
3333                 maxBlocksPerSecond = 1485;
3334                 maxBps = 64000;
3335                 for (CodecProfileLevel profileLevel: profileLevels) {
3336                     int MBPS = 0, FS = 0, BR = 0, FR = 0, W = 0, H = 0;
3337                     boolean strict = false; // true: W, H and FR are individual max limits
3338                     boolean supported = true;
3339                     switch (profileLevel.profile) {
3340                         case CodecProfileLevel.MPEG4ProfileSimple:
3341                             switch (profileLevel.level) {
3342                                 case CodecProfileLevel.MPEG4Level0:
3343                                     strict = true;
3344                                     FR = 15; W = 11; H =  9; MBPS =  1485; FS =  99; BR =  64; break;
3345                                 case CodecProfileLevel.MPEG4Level1:
3346                                     FR = 30; W = 11; H =  9; MBPS =  1485; FS =  99; BR =  64; break;
3347                                 case CodecProfileLevel.MPEG4Level0b:
3348                                     strict = true;
3349                                     FR = 15; W = 11; H =  9; MBPS =  1485; FS =  99; BR = 128; break;
3350                                 case CodecProfileLevel.MPEG4Level2:
3351                                     FR = 30; W = 22; H = 18; MBPS =  5940; FS = 396; BR = 128; break;
3352                                 case CodecProfileLevel.MPEG4Level3:
3353                                     FR = 30; W = 22; H = 18; MBPS = 11880; FS = 396; BR = 384; break;
3354                                 case CodecProfileLevel.MPEG4Level4a:
3355                                     FR = 30; W = 40; H = 30; MBPS = 36000; FS = 1200; BR = 4000; break;
3356                                 case CodecProfileLevel.MPEG4Level5:
3357                                     FR = 30; W = 45; H = 36; MBPS = 40500; FS = 1620; BR = 8000; break;
3358                                 case CodecProfileLevel.MPEG4Level6:
3359                                     FR = 30; W = 80; H = 45; MBPS = 108000; FS = 3600; BR = 12000; break;
3360                                 default:
3361                                     Log.w(TAG, "Unrecognized profile/level "
3362                                             + profileLevel.profile + "/"
3363                                             + profileLevel.level + " for " + mime);
3364                                     errors |= ERROR_UNRECOGNIZED;
3365                             }
3366                             break;
3367                         case CodecProfileLevel.MPEG4ProfileAdvancedSimple:
3368                             switch (profileLevel.level) {
3369                                 case CodecProfileLevel.MPEG4Level0:
3370                                 case CodecProfileLevel.MPEG4Level1:
3371                                     FR = 30; W = 11; H =  9; MBPS =  2970; FS =   99; BR =  128; break;
3372                                 case CodecProfileLevel.MPEG4Level2:
3373                                     FR = 30; W = 22; H = 18; MBPS =  5940; FS =  396; BR =  384; break;
3374                                 case CodecProfileLevel.MPEG4Level3:
3375                                     FR = 30; W = 22; H = 18; MBPS = 11880; FS =  396; BR =  768; break;
3376                                 case CodecProfileLevel.MPEG4Level3b:
3377                                     FR = 30; W = 22; H = 18; MBPS = 11880; FS =  396; BR = 1500; break;
3378                                 case CodecProfileLevel.MPEG4Level4:
3379                                     FR = 30; W = 44; H = 36; MBPS = 23760; FS =  792; BR = 3000; break;
3380                                 case CodecProfileLevel.MPEG4Level5:
3381                                     FR = 30; W = 45; H = 36; MBPS = 48600; FS = 1620; BR = 8000; break;
3382                                 default:
3383                                     Log.w(TAG, "Unrecognized profile/level "
3384                                             + profileLevel.profile + "/"
3385                                             + profileLevel.level + " for " + mime);
3386                                     errors |= ERROR_UNRECOGNIZED;
3387                             }
3388                             break;
3389                         case CodecProfileLevel.MPEG4ProfileMain:             // 2-4
3390                         case CodecProfileLevel.MPEG4ProfileNbit:             // 2
3391                         case CodecProfileLevel.MPEG4ProfileAdvancedRealTime: // 1-4
3392                         case CodecProfileLevel.MPEG4ProfileCoreScalable:     // 1-3
3393                         case CodecProfileLevel.MPEG4ProfileAdvancedCoding:   // 1-4
3394                         case CodecProfileLevel.MPEG4ProfileCore:             // 1-2
3395                         case CodecProfileLevel.MPEG4ProfileAdvancedCore:     // 1-4
3396                         case CodecProfileLevel.MPEG4ProfileSimpleScalable:   // 0-2
3397                         case CodecProfileLevel.MPEG4ProfileHybrid:           // 1-2
3398 
3399                         // Studio profiles are not supported by our codecs.
3400 
3401                         // Only profiles that can decode simple object types are considered.
3402                         // The following profiles are not able to.
3403                         case CodecProfileLevel.MPEG4ProfileBasicAnimated:    // 1-2
3404                         case CodecProfileLevel.MPEG4ProfileScalableTexture:  // 1
3405                         case CodecProfileLevel.MPEG4ProfileSimpleFace:       // 1-2
3406                         case CodecProfileLevel.MPEG4ProfileAdvancedScalable: // 1-3
3407                         case CodecProfileLevel.MPEG4ProfileSimpleFBA:        // 1-2
3408                             Log.i(TAG, "Unsupported profile "
3409                                     + profileLevel.profile + " for " + mime);
3410                             errors |= ERROR_UNSUPPORTED;
3411                             supported = false;
3412                             break;
3413                         default:
3414                             Log.w(TAG, "Unrecognized profile "
3415                                     + profileLevel.profile + " for " + mime);
3416                             errors |= ERROR_UNRECOGNIZED;
3417                     }
3418                     if (supported) {
3419                         errors &= ~ERROR_NONE_SUPPORTED;
3420                     }
3421                     maxBlocksPerSecond = Math.max(MBPS, maxBlocksPerSecond);
3422                     maxBlocks = Math.max(FS, maxBlocks);
3423                     maxBps = Math.max(BR * 1000, maxBps);
3424                     if (strict) {
3425                         maxWidth = Math.max(W, maxWidth);
3426                         maxHeight = Math.max(H, maxHeight);
3427                         maxRate = Math.max(FR, maxRate);
3428                     } else {
3429                         // assuming max 60 fps frame rate and 1:2 aspect ratio
3430                         int maxDim = (int)Math.sqrt(FS * 2);
3431                         maxWidth = Math.max(maxDim, maxWidth);
3432                         maxHeight = Math.max(maxDim, maxHeight);
3433                         maxRate = Math.max(Math.max(FR, 60), maxRate);
3434                     }
3435                 }
3436                 applyMacroBlockLimits(maxWidth, maxHeight,
3437                         maxBlocks, maxBlocksPerSecond,
3438                         16 /* blockWidth */, 16 /* blockHeight */,
3439                         1 /* widthAlignment */, 1 /* heightAlignment */);
3440                 mFrameRateRange = mFrameRateRange.intersect(12, maxRate);
3441             } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_H263)) {
3442                 int maxWidth = 11, maxHeight = 9, maxRate = 15;
3443                 int minWidth = maxWidth, minHeight = maxHeight;
3444                 int minAlignment = 16;
3445                 maxBlocks = 99;
3446                 maxBlocksPerSecond = 1485;
3447                 maxBps = 64000;
3448                 for (CodecProfileLevel profileLevel: profileLevels) {
3449                     int MBPS = 0, BR = 0, FR = 0, W = 0, H = 0, minW = minWidth, minH = minHeight;
3450                     boolean strict = false; // true: support only sQCIF, QCIF (maybe CIF)
3451                     switch (profileLevel.level) {
3452                         case CodecProfileLevel.H263Level10:
3453                             strict = true; // only supports sQCIF & QCIF
3454                             FR = 15; W = 11; H =  9; BR =   1; MBPS =  W * H * FR; break;
3455                         case CodecProfileLevel.H263Level20:
3456                             strict = true; // only supports sQCIF, QCIF & CIF
3457                             FR = 30; W = 22; H = 18; BR =   2; MBPS =  W * H * 15; break;
3458                         case CodecProfileLevel.H263Level30:
3459                             strict = true; // only supports sQCIF, QCIF & CIF
3460                             FR = 30; W = 22; H = 18; BR =   6; MBPS =  W * H * FR; break;
3461                         case CodecProfileLevel.H263Level40:
3462                             strict = true; // only supports sQCIF, QCIF & CIF
3463                             FR = 30; W = 22; H = 18; BR =  32; MBPS =  W * H * FR; break;
3464                         case CodecProfileLevel.H263Level45:
3465                             // only implies level 10 support
3466                             strict = profileLevel.profile == CodecProfileLevel.H263ProfileBaseline
3467                                     || profileLevel.profile ==
3468                                             CodecProfileLevel.H263ProfileBackwardCompatible;
3469                             if (!strict) {
3470                                 minW = 1; minH = 1; minAlignment = 4;
3471                             }
3472                             FR = 15; W = 11; H =  9; BR =   2; MBPS =  W * H * FR; break;
3473                         case CodecProfileLevel.H263Level50:
3474                             // only supports 50fps for H > 15
3475                             minW = 1; minH = 1; minAlignment = 4;
3476                             FR = 60; W = 22; H = 18; BR =  64; MBPS =  W * H * 50; break;
3477                         case CodecProfileLevel.H263Level60:
3478                             // only supports 50fps for H > 15
3479                             minW = 1; minH = 1; minAlignment = 4;
3480                             FR = 60; W = 45; H = 18; BR = 128; MBPS =  W * H * 50; break;
3481                         case CodecProfileLevel.H263Level70:
3482                             // only supports 50fps for H > 30
3483                             minW = 1; minH = 1; minAlignment = 4;
3484                             FR = 60; W = 45; H = 36; BR = 256; MBPS =  W * H * 50; break;
3485                         default:
3486                             Log.w(TAG, "Unrecognized profile/level " + profileLevel.profile
3487                                     + "/" + profileLevel.level + " for " + mime);
3488                             errors |= ERROR_UNRECOGNIZED;
3489                     }
3490                     switch (profileLevel.profile) {
3491                         case CodecProfileLevel.H263ProfileBackwardCompatible:
3492                         case CodecProfileLevel.H263ProfileBaseline:
3493                         case CodecProfileLevel.H263ProfileH320Coding:
3494                         case CodecProfileLevel.H263ProfileHighCompression:
3495                         case CodecProfileLevel.H263ProfileHighLatency:
3496                         case CodecProfileLevel.H263ProfileInterlace:
3497                         case CodecProfileLevel.H263ProfileInternet:
3498                         case CodecProfileLevel.H263ProfileISWV2:
3499                         case CodecProfileLevel.H263ProfileISWV3:
3500                             break;
3501                         default:
3502                             Log.w(TAG, "Unrecognized profile "
3503                                     + profileLevel.profile + " for " + mime);
3504                             errors |= ERROR_UNRECOGNIZED;
3505                     }
3506                     if (strict) {
3507                         // Strict levels define sub-QCIF min size and enumerated sizes. We cannot
3508                         // express support for "only sQCIF & QCIF (& CIF)" using VideoCapabilities
3509                         // but we can express "only QCIF (& CIF)", so set minimume size at QCIF.
3510                         // minW = 8; minH = 6;
3511                         minW = 11; minH = 9;
3512                     } else {
3513                         // any support for non-strict levels (including unrecognized profiles or
3514                         // levels) allow custom frame size support beyond supported limits
3515                         // (other than bitrate)
3516                         mAllowMbOverride = true;
3517                     }
3518                     errors &= ~ERROR_NONE_SUPPORTED;
3519                     maxBlocksPerSecond = Math.max(MBPS, maxBlocksPerSecond);
3520                     maxBlocks = Math.max(W * H, maxBlocks);
3521                     maxBps = Math.max(BR * 64000, maxBps);
3522                     maxWidth = Math.max(W, maxWidth);
3523                     maxHeight = Math.max(H, maxHeight);
3524                     maxRate = Math.max(FR, maxRate);
3525                     minWidth = Math.min(minW, minWidth);
3526                     minHeight = Math.min(minH, minHeight);
3527                 }
3528                 // unless we encountered custom frame size support, limit size to QCIF and CIF
3529                 // using aspect ratio.
3530                 if (!mAllowMbOverride) {
3531                     mBlockAspectRatioRange =
3532                         Range.create(new Rational(11, 9), new Rational(11, 9));
3533                 }
3534                 applyMacroBlockLimits(
3535                         minWidth, minHeight,
3536                         maxWidth, maxHeight,
3537                         maxBlocks, maxBlocksPerSecond,
3538                         16 /* blockWidth */, 16 /* blockHeight */,
3539                         minAlignment /* widthAlignment */, minAlignment /* heightAlignment */);
3540                 mFrameRateRange = Range.create(1, maxRate);
3541             } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP8)) {
3542                 maxBlocks = Integer.MAX_VALUE;
3543                 maxBlocksPerSecond = Integer.MAX_VALUE;
3544 
3545                 // TODO: set to 100Mbps for now, need a number for VP8
3546                 maxBps = 100000000;
3547 
3548                 // profile levels are not indicative for VPx, but verify
3549                 // them nonetheless
3550                 for (CodecProfileLevel profileLevel: profileLevels) {
3551                     switch (profileLevel.level) {
3552                         case CodecProfileLevel.VP8Level_Version0:
3553                         case CodecProfileLevel.VP8Level_Version1:
3554                         case CodecProfileLevel.VP8Level_Version2:
3555                         case CodecProfileLevel.VP8Level_Version3:
3556                             break;
3557                         default:
3558                             Log.w(TAG, "Unrecognized level "
3559                                     + profileLevel.level + " for " + mime);
3560                             errors |= ERROR_UNRECOGNIZED;
3561                     }
3562                     switch (profileLevel.profile) {
3563                         case CodecProfileLevel.VP8ProfileMain:
3564                             break;
3565                         default:
3566                             Log.w(TAG, "Unrecognized profile "
3567                                     + profileLevel.profile + " for " + mime);
3568                             errors |= ERROR_UNRECOGNIZED;
3569                     }
3570                     errors &= ~ERROR_NONE_SUPPORTED;
3571                 }
3572 
3573                 final int blockSize = 16;
3574                 applyMacroBlockLimits(Short.MAX_VALUE, Short.MAX_VALUE,
3575                         maxBlocks, maxBlocksPerSecond, blockSize, blockSize,
3576                         1 /* widthAlignment */, 1 /* heightAlignment */);
3577             } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP9)) {
3578                 maxBlocksPerSecond = 829440;
3579                 maxBlocks = 36864;
3580                 maxBps = 200000;
3581                 int maxDim = 512;
3582 
3583                 for (CodecProfileLevel profileLevel: profileLevels) {
3584                     long SR = 0; // luma sample rate
3585                     int FS = 0;  // luma picture size
3586                     int BR = 0;  // bit rate kbps
3587                     int D = 0;   // luma dimension
3588                     switch (profileLevel.level) {
3589                         case CodecProfileLevel.VP9Level1:
3590                             SR =      829440; FS =    36864; BR =    200; D =   512; break;
3591                         case CodecProfileLevel.VP9Level11:
3592                             SR =     2764800; FS =    73728; BR =    800; D =   768; break;
3593                         case CodecProfileLevel.VP9Level2:
3594                             SR =     4608000; FS =   122880; BR =   1800; D =   960; break;
3595                         case CodecProfileLevel.VP9Level21:
3596                             SR =     9216000; FS =   245760; BR =   3600; D =  1344; break;
3597                         case CodecProfileLevel.VP9Level3:
3598                             SR =    20736000; FS =   552960; BR =   7200; D =  2048; break;
3599                         case CodecProfileLevel.VP9Level31:
3600                             SR =    36864000; FS =   983040; BR =  12000; D =  2752; break;
3601                         case CodecProfileLevel.VP9Level4:
3602                             SR =    83558400; FS =  2228224; BR =  18000; D =  4160; break;
3603                         case CodecProfileLevel.VP9Level41:
3604                             SR =   160432128; FS =  2228224; BR =  30000; D =  4160; break;
3605                         case CodecProfileLevel.VP9Level5:
3606                             SR =   311951360; FS =  8912896; BR =  60000; D =  8384; break;
3607                         case CodecProfileLevel.VP9Level51:
3608                             SR =   588251136; FS =  8912896; BR = 120000; D =  8384; break;
3609                         case CodecProfileLevel.VP9Level52:
3610                             SR =  1176502272; FS =  8912896; BR = 180000; D =  8384; break;
3611                         case CodecProfileLevel.VP9Level6:
3612                             SR =  1176502272; FS = 35651584; BR = 180000; D = 16832; break;
3613                         case CodecProfileLevel.VP9Level61:
3614                             SR = 2353004544L; FS = 35651584; BR = 240000; D = 16832; break;
3615                         case CodecProfileLevel.VP9Level62:
3616                             SR = 4706009088L; FS = 35651584; BR = 480000; D = 16832; break;
3617                         default:
3618                             Log.w(TAG, "Unrecognized level "
3619                                     + profileLevel.level + " for " + mime);
3620                             errors |= ERROR_UNRECOGNIZED;
3621                     }
3622                     switch (profileLevel.profile) {
3623                         case CodecProfileLevel.VP9Profile0:
3624                         case CodecProfileLevel.VP9Profile1:
3625                         case CodecProfileLevel.VP9Profile2:
3626                         case CodecProfileLevel.VP9Profile3:
3627                         case CodecProfileLevel.VP9Profile2HDR:
3628                         case CodecProfileLevel.VP9Profile3HDR:
3629                         case CodecProfileLevel.VP9Profile2HDR10Plus:
3630                         case CodecProfileLevel.VP9Profile3HDR10Plus:
3631                             break;
3632                         default:
3633                             Log.w(TAG, "Unrecognized profile "
3634                                     + profileLevel.profile + " for " + mime);
3635                             errors |= ERROR_UNRECOGNIZED;
3636                     }
3637                     errors &= ~ERROR_NONE_SUPPORTED;
3638                     maxBlocksPerSecond = Math.max(SR, maxBlocksPerSecond);
3639                     maxBlocks = Math.max(FS, maxBlocks);
3640                     maxBps = Math.max(BR * 1000, maxBps);
3641                     maxDim = Math.max(D, maxDim);
3642                 }
3643 
3644                 final int blockSize = 8;
3645                 int maxLengthInBlocks = Utils.divUp(maxDim, blockSize);
3646                 maxBlocks = Utils.divUp(maxBlocks, blockSize * blockSize);
3647                 maxBlocksPerSecond = Utils.divUp(maxBlocksPerSecond, blockSize * blockSize);
3648 
3649                 applyMacroBlockLimits(
3650                         maxLengthInBlocks, maxLengthInBlocks,
3651                         maxBlocks, maxBlocksPerSecond,
3652                         blockSize, blockSize,
3653                         1 /* widthAlignment */, 1 /* heightAlignment */);
3654             } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_HEVC)) {
3655                 // CTBs are at least 8x8 so use 8x8 block size
3656                 maxBlocks = 36864 >> 6; // 192x192 pixels == 576 8x8 blocks
3657                 maxBlocksPerSecond = maxBlocks * 15;
3658                 maxBps = 128000;
3659                 for (CodecProfileLevel profileLevel: profileLevels) {
3660                     double FR = 0;
3661                     int FS = 0;
3662                     int BR = 0;
3663                     switch (profileLevel.level) {
3664                         /* The HEVC spec talks only in a very convoluted manner about the
3665                            existence of levels 1-3.1 for High tier, which could also be
3666                            understood as 'decoders and encoders should treat these levels
3667                            as if they were Main tier', so we do that. */
3668                         case CodecProfileLevel.HEVCMainTierLevel1:
3669                         case CodecProfileLevel.HEVCHighTierLevel1:
3670                             FR =    15; FS =    36864; BR =    128; break;
3671                         case CodecProfileLevel.HEVCMainTierLevel2:
3672                         case CodecProfileLevel.HEVCHighTierLevel2:
3673                             FR =    30; FS =   122880; BR =   1500; break;
3674                         case CodecProfileLevel.HEVCMainTierLevel21:
3675                         case CodecProfileLevel.HEVCHighTierLevel21:
3676                             FR =    30; FS =   245760; BR =   3000; break;
3677                         case CodecProfileLevel.HEVCMainTierLevel3:
3678                         case CodecProfileLevel.HEVCHighTierLevel3:
3679                             FR =    30; FS =   552960; BR =   6000; break;
3680                         case CodecProfileLevel.HEVCMainTierLevel31:
3681                         case CodecProfileLevel.HEVCHighTierLevel31:
3682                             FR = 33.75; FS =   983040; BR =  10000; break;
3683                         case CodecProfileLevel.HEVCMainTierLevel4:
3684                             FR =    30; FS =  2228224; BR =  12000; break;
3685                         case CodecProfileLevel.HEVCHighTierLevel4:
3686                             FR =    30; FS =  2228224; BR =  30000; break;
3687                         case CodecProfileLevel.HEVCMainTierLevel41:
3688                             FR =    60; FS =  2228224; BR =  20000; break;
3689                         case CodecProfileLevel.HEVCHighTierLevel41:
3690                             FR =    60; FS =  2228224; BR =  50000; break;
3691                         case CodecProfileLevel.HEVCMainTierLevel5:
3692                             FR =    30; FS =  8912896; BR =  25000; break;
3693                         case CodecProfileLevel.HEVCHighTierLevel5:
3694                             FR =    30; FS =  8912896; BR = 100000; break;
3695                         case CodecProfileLevel.HEVCMainTierLevel51:
3696                             FR =    60; FS =  8912896; BR =  40000; break;
3697                         case CodecProfileLevel.HEVCHighTierLevel51:
3698                             FR =    60; FS =  8912896; BR = 160000; break;
3699                         case CodecProfileLevel.HEVCMainTierLevel52:
3700                             FR =   120; FS =  8912896; BR =  60000; break;
3701                         case CodecProfileLevel.HEVCHighTierLevel52:
3702                             FR =   120; FS =  8912896; BR = 240000; break;
3703                         case CodecProfileLevel.HEVCMainTierLevel6:
3704                             FR =    30; FS = 35651584; BR =  60000; break;
3705                         case CodecProfileLevel.HEVCHighTierLevel6:
3706                             FR =    30; FS = 35651584; BR = 240000; break;
3707                         case CodecProfileLevel.HEVCMainTierLevel61:
3708                             FR =    60; FS = 35651584; BR = 120000; break;
3709                         case CodecProfileLevel.HEVCHighTierLevel61:
3710                             FR =    60; FS = 35651584; BR = 480000; break;
3711                         case CodecProfileLevel.HEVCMainTierLevel62:
3712                             FR =   120; FS = 35651584; BR = 240000; break;
3713                         case CodecProfileLevel.HEVCHighTierLevel62:
3714                             FR =   120; FS = 35651584; BR = 800000; break;
3715                         default:
3716                             Log.w(TAG, "Unrecognized level "
3717                                     + profileLevel.level + " for " + mime);
3718                             errors |= ERROR_UNRECOGNIZED;
3719                     }
3720                     switch (profileLevel.profile) {
3721                         case CodecProfileLevel.HEVCProfileMain:
3722                         case CodecProfileLevel.HEVCProfileMain10:
3723                         case CodecProfileLevel.HEVCProfileMainStill:
3724                         case CodecProfileLevel.HEVCProfileMain10HDR10:
3725                         case CodecProfileLevel.HEVCProfileMain10HDR10Plus:
3726                             break;
3727                         default:
3728                             Log.w(TAG, "Unrecognized profile "
3729                                     + profileLevel.profile + " for " + mime);
3730                             errors |= ERROR_UNRECOGNIZED;
3731                     }
3732 
3733                     /* DPB logic:
3734                     if      (width * height <= FS / 4)    DPB = 16;
3735                     else if (width * height <= FS / 2)    DPB = 12;
3736                     else if (width * height <= FS * 0.75) DPB = 8;
3737                     else                                  DPB = 6;
3738                     */
3739 
3740                     FS >>= 6; // convert pixels to blocks
3741                     errors &= ~ERROR_NONE_SUPPORTED;
3742                     maxBlocksPerSecond = Math.max((int)(FR * FS), maxBlocksPerSecond);
3743                     maxBlocks = Math.max(FS, maxBlocks);
3744                     maxBps = Math.max(BR * 1000, maxBps);
3745                 }
3746 
3747                 int maxLengthInBlocks = (int)(Math.sqrt(maxBlocks * 8));
3748                 applyMacroBlockLimits(
3749                         maxLengthInBlocks, maxLengthInBlocks,
3750                         maxBlocks, maxBlocksPerSecond,
3751                         8 /* blockWidth */, 8 /* blockHeight */,
3752                         1 /* widthAlignment */, 1 /* heightAlignment */);
3753             } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_AV1)) {
3754                 maxBlocksPerSecond = 829440;
3755                 maxBlocks = 36864;
3756                 maxBps = 200000;
3757                 int maxDim = 512;
3758 
3759                 // Sample rate, Picture Size, Bit rate and luma dimension for AV1 Codec,
3760                 // corresponding to the definitions in
3761                 // "AV1 Bitstream & Decoding Process Specification", Annex A
3762                 // found at https://aomedia.org/av1-bitstream-and-decoding-process-specification/
3763                 for (CodecProfileLevel profileLevel: profileLevels) {
3764                     long SR = 0; // luma sample rate
3765                     int FS = 0;  // luma picture size
3766                     int BR = 0;  // bit rate kbps
3767                     int D = 0;   // luma D
3768                     switch (profileLevel.level) {
3769                         case CodecProfileLevel.AV1Level2:
3770                             SR =     5529600; FS =   147456; BR =   1500; D =  2048; break;
3771                         case CodecProfileLevel.AV1Level21:
3772                         case CodecProfileLevel.AV1Level22:
3773                         case CodecProfileLevel.AV1Level23:
3774                             SR =    10454400; FS =   278784; BR =   3000; D =  2816; break;
3775 
3776                         case CodecProfileLevel.AV1Level3:
3777                             SR =    24969600; FS =   665856; BR =   6000; D =  4352; break;
3778                         case CodecProfileLevel.AV1Level31:
3779                         case CodecProfileLevel.AV1Level32:
3780                         case CodecProfileLevel.AV1Level33:
3781                             SR =    39938400; FS =  1065024; BR =  10000; D =  5504; break;
3782 
3783                         case CodecProfileLevel.AV1Level4:
3784                             SR =    77856768; FS =  2359296; BR =  12000; D =  6144; break;
3785                         case CodecProfileLevel.AV1Level41:
3786                         case CodecProfileLevel.AV1Level42:
3787                         case CodecProfileLevel.AV1Level43:
3788                             SR =   155713536; FS =  2359296; BR =  20000; D =  6144; break;
3789 
3790                         case CodecProfileLevel.AV1Level5:
3791                             SR =   273715200; FS =  8912896; BR =  30000; D =  8192; break;
3792                         case CodecProfileLevel.AV1Level51:
3793                             SR =   547430400; FS =  8912896; BR =  40000; D =  8192; break;
3794                         case CodecProfileLevel.AV1Level52:
3795                             SR =  1094860800; FS =  8912896; BR =  60000; D =  8192; break;
3796                         case CodecProfileLevel.AV1Level53:
3797                             SR =  1176502272; FS =  8912896; BR =  60000; D =  8192; break;
3798 
3799                         case CodecProfileLevel.AV1Level6:
3800                             SR =  1176502272; FS = 35651584; BR =  60000; D = 16384; break;
3801                         case CodecProfileLevel.AV1Level61:
3802                             SR = 2189721600L; FS = 35651584; BR = 100000; D = 16384; break;
3803                         case CodecProfileLevel.AV1Level62:
3804                             SR = 4379443200L; FS = 35651584; BR = 160000; D = 16384; break;
3805                         case CodecProfileLevel.AV1Level63:
3806                             SR = 4706009088L; FS = 35651584; BR = 160000; D = 16384; break;
3807 
3808                         default:
3809                             Log.w(TAG, "Unrecognized level "
3810                                     + profileLevel.level + " for " + mime);
3811                             errors |= ERROR_UNRECOGNIZED;
3812                     }
3813                     switch (profileLevel.profile) {
3814                         case CodecProfileLevel.AV1ProfileMain8:
3815                         case CodecProfileLevel.AV1ProfileMain10:
3816                         case CodecProfileLevel.AV1ProfileMain10HDR10:
3817                         case CodecProfileLevel.AV1ProfileMain10HDR10Plus:
3818                             break;
3819                         default:
3820                             Log.w(TAG, "Unrecognized profile "
3821                                     + profileLevel.profile + " for " + mime);
3822                             errors |= ERROR_UNRECOGNIZED;
3823                     }
3824                     errors &= ~ERROR_NONE_SUPPORTED;
3825                     maxBlocksPerSecond = Math.max(SR, maxBlocksPerSecond);
3826                     maxBlocks = Math.max(FS, maxBlocks);
3827                     maxBps = Math.max(BR * 1000, maxBps);
3828                     maxDim = Math.max(D, maxDim);
3829                 }
3830 
3831                 final int blockSize = 8;
3832                 int maxLengthInBlocks = Utils.divUp(maxDim, blockSize);
3833                 maxBlocks = Utils.divUp(maxBlocks, blockSize * blockSize);
3834                 maxBlocksPerSecond = Utils.divUp(maxBlocksPerSecond, blockSize * blockSize);
3835                 applyMacroBlockLimits(
3836                         maxLengthInBlocks, maxLengthInBlocks,
3837                         maxBlocks, maxBlocksPerSecond,
3838                         blockSize, blockSize,
3839                         1 /* widthAlignment */, 1 /* heightAlignment */);
3840             } else if (GetFlag(() -> android.media.codec.Flags.apvSupport())
3841                         && mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_APV)) {
3842                 maxBlocksPerSecond = 11880;
3843                 maxBps = 7000000;
3844 
3845                 // Sample rate, and Bit rate for APV Codec,
3846                 // corresponding to the definitions in
3847                 // "10.1.4. Levels and bands"
3848                 // found at https://www.ietf.org/archive/id/draft-lim-apv-03.html
3849                 for (CodecProfileLevel profileLevel: profileLevels) {
3850                     long SR = 0; // luma sample rate
3851                     int BR = 0;  // bit rate bps
3852                     switch (profileLevel.level) {
3853                         case CodecProfileLevel.APVLevel1Band0:
3854                             SR =      3041280; BR =    7000000; break;
3855                         case CodecProfileLevel.APVLevel1Band1:
3856                             SR =      3041280; BR =   11000000; break;
3857                         case CodecProfileLevel.APVLevel1Band2:
3858                             SR =      3041280; BR =   14000000; break;
3859                         case CodecProfileLevel.APVLevel1Band3:
3860                             SR =      3041280; BR =   21000000; break;
3861                         case CodecProfileLevel.APVLevel11Band0:
3862                             SR =      6082560; BR =   14000000; break;
3863                         case CodecProfileLevel.APVLevel11Band1:
3864                             SR =      6082560; BR =   21000000; break;
3865                         case CodecProfileLevel.APVLevel11Band2:
3866                             SR =      6082560; BR =   28000000; break;
3867                         case CodecProfileLevel.APVLevel11Band3:
3868                             SR =      6082560; BR =   42000000; break;
3869                         case CodecProfileLevel.APVLevel2Band0:
3870                             SR =     15667200; BR =   36000000; break;
3871                         case CodecProfileLevel.APVLevel2Band1:
3872                             SR =     15667200; BR =   53000000; break;
3873                         case CodecProfileLevel.APVLevel2Band2:
3874                             SR =     15667200; BR =   71000000; break;
3875                         case CodecProfileLevel.APVLevel2Band3:
3876                             SR =     15667200; BR =  106000000; break;
3877                         case CodecProfileLevel.APVLevel21Band0:
3878                             SR =     31334400; BR =   71000000; break;
3879                         case CodecProfileLevel.APVLevel21Band1:
3880                             SR =     31334400; BR =  106000000; break;
3881                         case CodecProfileLevel.APVLevel21Band2:
3882                             SR =     31334400; BR =  141000000; break;
3883                         case CodecProfileLevel.APVLevel21Band3:
3884                             SR =     31334400; BR =  212000000; break;
3885                         case CodecProfileLevel.APVLevel3Band0:
3886                             SR =     66846720; BR =  101000000; break;
3887                         case CodecProfileLevel.APVLevel3Band1:
3888                             SR =     66846720; BR =  151000000; break;
3889                         case CodecProfileLevel.APVLevel3Band2:
3890                             SR =     66846720; BR =  201000000; break;
3891                         case CodecProfileLevel.APVLevel3Band3:
3892                             SR =     66846720; BR =  301000000; break;
3893                         case CodecProfileLevel.APVLevel31Band0:
3894                             SR =    133693440; BR =  201000000; break;
3895                         case CodecProfileLevel.APVLevel31Band1:
3896                             SR =    133693440; BR =  301000000; break;
3897                         case CodecProfileLevel.APVLevel31Band2:
3898                             SR =    133693440; BR =  401000000; break;
3899                         case CodecProfileLevel.APVLevel31Band3:
3900                             SR =    133693440; BR =  602000000; break;
3901                         case CodecProfileLevel.APVLevel4Band0:
3902                             SR =    265420800; BR =  401000000; break;
3903                         case CodecProfileLevel.APVLevel4Band1:
3904                             SR =    265420800; BR =  602000000; break;
3905                         case CodecProfileLevel.APVLevel4Band2:
3906                             SR =    265420800; BR =  780000000; break;
3907                         case CodecProfileLevel.APVLevel4Band3:
3908                             SR =    265420800; BR = 1170000000; break;
3909                         case CodecProfileLevel.APVLevel41Band0:
3910                             SR =    530841600; BR =  780000000; break;
3911                         case CodecProfileLevel.APVLevel41Band1:
3912                             SR =    530841600; BR = 1170000000; break;
3913                         case CodecProfileLevel.APVLevel41Band2:
3914                             SR =    530841600; BR = 1560000000; break;
3915                         case CodecProfileLevel.APVLevel41Band3:
3916                             // Current API allows bitrates only up to Max Integer
3917                             // Hence we are limiting internal limits to Integer.MAX_VALUE
3918                             // even when actual Level/Band limits are higher
3919                             SR =    530841600; BR = Integer.MAX_VALUE; break;
3920                         case CodecProfileLevel.APVLevel5Band0:
3921                             SR =   1061683200; BR = 1560000000; break;
3922                         case CodecProfileLevel.APVLevel5Band1:
3923                             SR =   1061683200; BR = Integer.MAX_VALUE; break;
3924                         case CodecProfileLevel.APVLevel5Band2:
3925                             SR =   1061683200; BR = Integer.MAX_VALUE; break;
3926                         case CodecProfileLevel.APVLevel5Band3:
3927                             SR =   1061683200; BR = Integer.MAX_VALUE; break;
3928                         case CodecProfileLevel.APVLevel51Band0:
3929                         case CodecProfileLevel.APVLevel51Band1:
3930                         case CodecProfileLevel.APVLevel51Band2:
3931                         case CodecProfileLevel.APVLevel51Band3:
3932                             SR =   2123366400; BR = Integer.MAX_VALUE; break;
3933                         case CodecProfileLevel.APVLevel6Band0:
3934                         case CodecProfileLevel.APVLevel6Band1:
3935                         case CodecProfileLevel.APVLevel6Band2:
3936                         case CodecProfileLevel.APVLevel6Band3:
3937                             SR =  4777574400L; BR = Integer.MAX_VALUE; break;
3938                         case CodecProfileLevel.APVLevel61Band0:
3939                         case CodecProfileLevel.APVLevel61Band1:
3940                         case CodecProfileLevel.APVLevel61Band2:
3941                         case CodecProfileLevel.APVLevel61Band3:
3942                             SR =  8493465600L; BR = Integer.MAX_VALUE; break;
3943                         case CodecProfileLevel.APVLevel7Band0:
3944                         case CodecProfileLevel.APVLevel7Band1:
3945                         case CodecProfileLevel.APVLevel7Band2:
3946                         case CodecProfileLevel.APVLevel7Band3:
3947                             SR = 16986931200L; BR = Integer.MAX_VALUE; break;
3948                         case CodecProfileLevel.APVLevel71Band0:
3949                         case CodecProfileLevel.APVLevel71Band1:
3950                         case CodecProfileLevel.APVLevel71Band2:
3951                         case CodecProfileLevel.APVLevel71Band3:
3952                             SR = 33973862400L; BR = Integer.MAX_VALUE; break;
3953                         default:
3954                             Log.w(TAG, "Unrecognized level "
3955                                     + profileLevel.level + " for " + mime);
3956                             errors |= ERROR_UNRECOGNIZED;
3957                     }
3958                     switch (profileLevel.profile) {
3959                         case CodecProfileLevel.APVProfile422_10:
3960                         case CodecProfileLevel.APVProfile422_10HDR10:
3961                         case CodecProfileLevel.APVProfile422_10HDR10Plus:
3962                             break;
3963                         default:
3964                             Log.w(TAG, "Unrecognized profile "
3965                                     + profileLevel.profile + " for " + mime);
3966                             errors |= ERROR_UNRECOGNIZED;
3967                     }
3968                     errors &= ~ERROR_NONE_SUPPORTED;
3969                     maxBlocksPerSecond = Math.max(SR, maxBlocksPerSecond);
3970                     maxBps = Math.max(BR, maxBps);
3971                 }
3972 
3973                 final int blockSize = 16;
3974                 maxBlocks = Integer.MAX_VALUE;
3975                 maxBlocksPerSecond = Utils.divUp(maxBlocksPerSecond, blockSize * blockSize);
3976                 maxBlocks = (int) Math.min((long) maxBlocks, maxBlocksPerSecond);
3977                 // Max frame size in APV is 2^24
3978                 int maxLengthInBlocks = Utils.divUp((int) Math.pow(2, 24), blockSize);
3979                 maxLengthInBlocks = Math.min(maxLengthInBlocks, maxBlocks);
3980                 applyMacroBlockLimits(
3981                         maxLengthInBlocks, maxLengthInBlocks,
3982                         maxBlocks, maxBlocksPerSecond,
3983                         blockSize, blockSize,
3984                         2 /* widthAlignment */, 1 /* heightAlignment */);
3985             } else {
3986                 Log.w(TAG, "Unsupported mime " + mime);
3987                 // using minimal bitrate here.  should be overriden by
3988                 // info from media_codecs.xml
3989                 maxBps = 64000;
3990                 errors |= ERROR_UNSUPPORTED;
3991             }
3992             mBitrateRange = Range.create(1, maxBps);
3993             mParent.mError |= errors;
3994         }
3995     }
3996 
3997     /**
3998      * A class that supports querying the encoding capabilities of a codec.
3999      */
4000     public static final class EncoderCapabilities {
4001         /**
4002          * Returns the supported range of quality values.
4003          *
4004          * Quality is implementation-specific. As a general rule, a higher quality
4005          * setting results in a better image quality and a lower compression ratio.
4006          */
4007         public Range<Integer> getQualityRange() {
4008             return mQualityRange;
4009         }
4010 
4011         /**
4012          * Returns the supported range of encoder complexity values.
4013          * <p>
4014          * Some codecs may support multiple complexity levels, where higher
4015          * complexity values use more encoder tools (e.g. perform more
4016          * intensive calculations) to improve the quality or the compression
4017          * ratio.  Use a lower value to save power and/or time.
4018          */
4019         public Range<Integer> getComplexityRange() {
4020             return mComplexityRange;
4021         }
4022 
4023         /** Constant quality mode */
4024         public static final int BITRATE_MODE_CQ = 0;
4025         /** Variable bitrate mode */
4026         public static final int BITRATE_MODE_VBR = 1;
4027         /** Constant bitrate mode */
4028         public static final int BITRATE_MODE_CBR = 2;
4029         /** Constant bitrate mode with frame drops */
4030         public static final int BITRATE_MODE_CBR_FD =  3;
4031 
4032         private static final Feature[] bitrates = new Feature[] {
4033             new Feature("VBR", BITRATE_MODE_VBR, true),
4034             new Feature("CBR", BITRATE_MODE_CBR, false),
4035             new Feature("CQ",  BITRATE_MODE_CQ,  false),
4036             new Feature("CBR-FD", BITRATE_MODE_CBR_FD, false)
4037         };
4038 
4039         private static int parseBitrateMode(String mode) {
4040             for (Feature feat: bitrates) {
4041                 if (feat.mName.equalsIgnoreCase(mode)) {
4042                     return feat.mValue;
4043                 }
4044             }
4045             return 0;
4046         }
4047 
4048         /**
4049          * Query whether a bitrate mode is supported.
4050          */
4051         public boolean isBitrateModeSupported(int mode) {
4052             for (Feature feat: bitrates) {
4053                 if (mode == feat.mValue) {
4054                     return (mBitControl & (1 << mode)) != 0;
4055                 }
4056             }
4057             return false;
4058         }
4059 
4060         private Range<Integer> mQualityRange;
4061         private Range<Integer> mComplexityRange;
4062         private CodecCapabilities mParent;
4063 
4064         /* no public constructor */
4065         private EncoderCapabilities() { }
4066 
4067         /** @hide */
4068         public static EncoderCapabilities create(
4069                 MediaFormat info, CodecCapabilities parent) {
4070             EncoderCapabilities caps = new EncoderCapabilities();
4071             caps.init(info, parent);
4072             return caps;
4073         }
4074 
4075         private void init(MediaFormat info, CodecCapabilities parent) {
4076             // no support for complexity or quality yet
4077             mParent = parent;
4078             mComplexityRange = Range.create(0, 0);
4079             mQualityRange = Range.create(0, 0);
4080             mBitControl = (1 << BITRATE_MODE_VBR);
4081 
4082             applyLevelLimits();
4083             parseFromInfo(info);
4084         }
4085 
4086         private void applyLevelLimits() {
4087             String mime = mParent.getMimeType();
4088             if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_FLAC)) {
4089                 mComplexityRange = Range.create(0, 8);
4090                 mBitControl = (1 << BITRATE_MODE_CQ);
4091             } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AMR_NB)
4092                     || mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AMR_WB)
4093                     || mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_G711_ALAW)
4094                     || mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_G711_MLAW)
4095                     || mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_MSGSM)) {
4096                 mBitControl = (1 << BITRATE_MODE_CBR);
4097             }
4098         }
4099 
4100         private int mBitControl;
4101         private Integer mDefaultComplexity;
4102         private Integer mDefaultQuality;
4103         private String mQualityScale;
4104 
4105         private void parseFromInfo(MediaFormat info) {
4106             Map<String, Object> map = info.getMap();
4107 
4108             if (info.containsKey("complexity-range")) {
4109                 mComplexityRange = Utils
4110                         .parseIntRange(info.getString("complexity-range"), mComplexityRange);
4111                 // TODO should we limit this to level limits?
4112             }
4113             if (info.containsKey("quality-range")) {
4114                 mQualityRange = Utils
4115                         .parseIntRange(info.getString("quality-range"), mQualityRange);
4116             }
4117             if (info.containsKey("feature-bitrate-modes")) {
4118                 mBitControl = 0;
4119                 for (String mode: info.getString("feature-bitrate-modes").split(",")) {
4120                     mBitControl |= (1 << parseBitrateMode(mode));
4121                 }
4122             }
4123 
4124             try {
4125                 mDefaultComplexity = Integer.parseInt((String)map.get("complexity-default"));
4126             } catch (NumberFormatException e) { }
4127 
4128             try {
4129                 mDefaultQuality = Integer.parseInt((String)map.get("quality-default"));
4130             } catch (NumberFormatException e) { }
4131 
4132             mQualityScale = (String)map.get("quality-scale");
4133         }
4134 
4135         private boolean supports(
4136                 Integer complexity, Integer quality, Integer profile) {
4137             boolean ok = true;
4138             if (ok && complexity != null) {
4139                 ok = mComplexityRange.contains(complexity);
4140             }
4141             if (ok && quality != null) {
4142                 ok = mQualityRange.contains(quality);
4143             }
4144             if (ok && profile != null) {
4145                 for (CodecProfileLevel pl: mParent.profileLevels) {
4146                     if (pl.profile == profile) {
4147                         profile = null;
4148                         break;
4149                     }
4150                 }
4151                 ok = profile == null;
4152             }
4153             return ok;
4154         }
4155 
4156         /** @hide */
4157         public void getDefaultFormat(MediaFormat format) {
4158             // don't list trivial quality/complexity as default for now
4159             if (!mQualityRange.getUpper().equals(mQualityRange.getLower())
4160                     && mDefaultQuality != null) {
4161                 format.setInteger(MediaFormat.KEY_QUALITY, mDefaultQuality);
4162             }
4163             if (!mComplexityRange.getUpper().equals(mComplexityRange.getLower())
4164                     && mDefaultComplexity != null) {
4165                 format.setInteger(MediaFormat.KEY_COMPLEXITY, mDefaultComplexity);
4166             }
4167             // bitrates are listed in order of preference
4168             for (Feature feat: bitrates) {
4169                 if ((mBitControl & (1 << feat.mValue)) != 0) {
4170                     format.setInteger(MediaFormat.KEY_BITRATE_MODE, feat.mValue);
4171                     break;
4172                 }
4173             }
4174         }
4175 
4176         /** @hide */
4177         public boolean supportsFormat(MediaFormat format) {
4178             final Map<String, Object> map = format.getMap();
4179             final String mime = mParent.getMimeType();
4180 
4181             Integer mode = (Integer)map.get(MediaFormat.KEY_BITRATE_MODE);
4182             if (mode != null && !isBitrateModeSupported(mode)) {
4183                 return false;
4184             }
4185 
4186             Integer complexity = (Integer)map.get(MediaFormat.KEY_COMPLEXITY);
4187             if (MediaFormat.MIMETYPE_AUDIO_FLAC.equalsIgnoreCase(mime)) {
4188                 Integer flacComplexity =
4189                     (Integer)map.get(MediaFormat.KEY_FLAC_COMPRESSION_LEVEL);
4190                 if (complexity == null) {
4191                     complexity = flacComplexity;
4192                 } else if (flacComplexity != null && !complexity.equals(flacComplexity)) {
4193                     throw new IllegalArgumentException(
4194                             "conflicting values for complexity and " +
4195                             "flac-compression-level");
4196                 }
4197             }
4198 
4199             // other audio parameters
4200             Integer profile = (Integer)map.get(MediaFormat.KEY_PROFILE);
4201             if (MediaFormat.MIMETYPE_AUDIO_AAC.equalsIgnoreCase(mime)) {
4202                 Integer aacProfile = (Integer)map.get(MediaFormat.KEY_AAC_PROFILE);
4203                 if (profile == null) {
4204                     profile = aacProfile;
4205                 } else if (aacProfile != null && !aacProfile.equals(profile)) {
4206                     throw new IllegalArgumentException(
4207                             "conflicting values for profile and aac-profile");
4208                 }
4209             }
4210 
4211             Integer quality = (Integer)map.get(MediaFormat.KEY_QUALITY);
4212 
4213             return supports(complexity, quality, profile);
4214         }
4215     };
4216 
4217     /**
4218      * Encapsulates the profiles available for a codec component.
4219      * <p>You can get a set of {@link MediaCodecInfo.CodecProfileLevel} objects for a given
4220      * {@link MediaCodecInfo} object from the
4221      * {@link MediaCodecInfo.CodecCapabilities#profileLevels} field.
4222      */
4223     public static final class CodecProfileLevel {
4224         // These constants were originally in-line with OMX values, but this
4225         // correspondence is no longer maintained.
4226 
4227         // Profiles and levels for AVC Codec, corresponding to the definitions in
4228         // "SERIES H: AUDIOVISUAL AND MULTIMEDIA SYSTEMS,
4229         // Infrastructure of audiovisual services – Coding of moving video
4230         // Advanced video coding for generic audiovisual services"
4231         // found at
4232         // https://www.itu.int/rec/T-REC-H.264-201704-I
4233 
4234         /**
4235          * AVC Baseline profile.
4236          * See definition in
4237          * <a href="https://www.itu.int/rec/T-REC-H.264-201704-I">H.264 recommendation</a>,
4238          * Annex A.
4239          */
4240         public static final int AVCProfileBaseline = 0x01;
4241 
4242         /**
4243          * AVC Main profile.
4244          * See definition in
4245          * <a href="https://www.itu.int/rec/T-REC-H.264-201704-I">H.264 recommendation</a>,
4246          * Annex A.
4247          */
4248         public static final int AVCProfileMain     = 0x02;
4249 
4250         /**
4251          * AVC Extended profile.
4252          * See definition in
4253          * <a href="https://www.itu.int/rec/T-REC-H.264-201704-I">H.264 recommendation</a>,
4254          * Annex A.
4255          */
4256         public static final int AVCProfileExtended = 0x04;
4257 
4258         /**
4259          * AVC High profile.
4260          * See definition in
4261          * <a href="https://www.itu.int/rec/T-REC-H.264-201704-I">H.264 recommendation</a>,
4262          * Annex A.
4263          */
4264         public static final int AVCProfileHigh     = 0x08;
4265 
4266         /**
4267          * AVC High 10 profile.
4268          * See definition in
4269          * <a href="https://www.itu.int/rec/T-REC-H.264-201704-I">H.264 recommendation</a>,
4270          * Annex A.
4271          */
4272         public static final int AVCProfileHigh10   = 0x10;
4273 
4274         /**
4275          * AVC High 4:2:2 profile.
4276          * See definition in
4277          * <a href="https://www.itu.int/rec/T-REC-H.264-201704-I">H.264 recommendation</a>,
4278          * Annex A.
4279          */
4280         public static final int AVCProfileHigh422  = 0x20;
4281 
4282         /**
4283          * AVC High 4:4:4 profile.
4284          * See definition in
4285          * <a href="https://www.itu.int/rec/T-REC-H.264-201704-I">H.264 recommendation</a>,
4286          * Annex A.
4287          */
4288         public static final int AVCProfileHigh444  = 0x40;
4289 
4290         /**
4291          * AVC Constrained Baseline profile.
4292          * See definition in
4293          * <a href="https://www.itu.int/rec/T-REC-H.264-201704-I">H.264 recommendation</a>,
4294          * Annex A.
4295          */
4296         public static final int AVCProfileConstrainedBaseline = 0x10000;
4297 
4298         /**
4299          * AVC Constrained High profile.
4300          * See definition in
4301          * <a href="https://www.itu.int/rec/T-REC-H.264-201704-I">H.264 recommendation</a>,
4302          * Annex A.
4303          */
4304         public static final int AVCProfileConstrainedHigh     = 0x80000;
4305 
4306         public static final int AVCLevel1       = 0x01;
4307         public static final int AVCLevel1b      = 0x02;
4308         public static final int AVCLevel11      = 0x04;
4309         public static final int AVCLevel12      = 0x08;
4310         public static final int AVCLevel13      = 0x10;
4311         public static final int AVCLevel2       = 0x20;
4312         public static final int AVCLevel21      = 0x40;
4313         public static final int AVCLevel22      = 0x80;
4314         public static final int AVCLevel3       = 0x100;
4315         public static final int AVCLevel31      = 0x200;
4316         public static final int AVCLevel32      = 0x400;
4317         public static final int AVCLevel4       = 0x800;
4318         public static final int AVCLevel41      = 0x1000;
4319         public static final int AVCLevel42      = 0x2000;
4320         public static final int AVCLevel5       = 0x4000;
4321         public static final int AVCLevel51      = 0x8000;
4322         public static final int AVCLevel52      = 0x10000;
4323         public static final int AVCLevel6       = 0x20000;
4324         public static final int AVCLevel61      = 0x40000;
4325         public static final int AVCLevel62      = 0x80000;
4326 
4327         public static final int H263ProfileBaseline             = 0x01;
4328         public static final int H263ProfileH320Coding           = 0x02;
4329         public static final int H263ProfileBackwardCompatible   = 0x04;
4330         public static final int H263ProfileISWV2                = 0x08;
4331         public static final int H263ProfileISWV3                = 0x10;
4332         public static final int H263ProfileHighCompression      = 0x20;
4333         public static final int H263ProfileInternet             = 0x40;
4334         public static final int H263ProfileInterlace            = 0x80;
4335         public static final int H263ProfileHighLatency          = 0x100;
4336 
4337         public static final int H263Level10      = 0x01;
4338         public static final int H263Level20      = 0x02;
4339         public static final int H263Level30      = 0x04;
4340         public static final int H263Level40      = 0x08;
4341         public static final int H263Level45      = 0x10;
4342         public static final int H263Level50      = 0x20;
4343         public static final int H263Level60      = 0x40;
4344         public static final int H263Level70      = 0x80;
4345 
4346         public static final int MPEG4ProfileSimple              = 0x01;
4347         public static final int MPEG4ProfileSimpleScalable      = 0x02;
4348         public static final int MPEG4ProfileCore                = 0x04;
4349         public static final int MPEG4ProfileMain                = 0x08;
4350         public static final int MPEG4ProfileNbit                = 0x10;
4351         public static final int MPEG4ProfileScalableTexture     = 0x20;
4352         public static final int MPEG4ProfileSimpleFace          = 0x40;
4353         public static final int MPEG4ProfileSimpleFBA           = 0x80;
4354         public static final int MPEG4ProfileBasicAnimated       = 0x100;
4355         public static final int MPEG4ProfileHybrid              = 0x200;
4356         public static final int MPEG4ProfileAdvancedRealTime    = 0x400;
4357         public static final int MPEG4ProfileCoreScalable        = 0x800;
4358         public static final int MPEG4ProfileAdvancedCoding      = 0x1000;
4359         public static final int MPEG4ProfileAdvancedCore        = 0x2000;
4360         public static final int MPEG4ProfileAdvancedScalable    = 0x4000;
4361         public static final int MPEG4ProfileAdvancedSimple      = 0x8000;
4362 
4363         public static final int MPEG4Level0      = 0x01;
4364         public static final int MPEG4Level0b     = 0x02;
4365         public static final int MPEG4Level1      = 0x04;
4366         public static final int MPEG4Level2      = 0x08;
4367         public static final int MPEG4Level3      = 0x10;
4368         public static final int MPEG4Level3b     = 0x18;
4369         public static final int MPEG4Level4      = 0x20;
4370         public static final int MPEG4Level4a     = 0x40;
4371         public static final int MPEG4Level5      = 0x80;
4372         public static final int MPEG4Level6      = 0x100;
4373 
4374         public static final int MPEG2ProfileSimple              = 0x00;
4375         public static final int MPEG2ProfileMain                = 0x01;
4376         public static final int MPEG2Profile422                 = 0x02;
4377         public static final int MPEG2ProfileSNR                 = 0x03;
4378         public static final int MPEG2ProfileSpatial             = 0x04;
4379         public static final int MPEG2ProfileHigh                = 0x05;
4380 
4381         public static final int MPEG2LevelLL     = 0x00;
4382         public static final int MPEG2LevelML     = 0x01;
4383         public static final int MPEG2LevelH14    = 0x02;
4384         public static final int MPEG2LevelHL     = 0x03;
4385         public static final int MPEG2LevelHP     = 0x04;
4386 
4387         public static final int AACObjectMain       = 1;
4388         public static final int AACObjectLC         = 2;
4389         public static final int AACObjectSSR        = 3;
4390         public static final int AACObjectLTP        = 4;
4391         public static final int AACObjectHE         = 5;
4392         public static final int AACObjectScalable   = 6;
4393         public static final int AACObjectERLC       = 17;
4394         public static final int AACObjectERScalable = 20;
4395         public static final int AACObjectLD         = 23;
4396         public static final int AACObjectHE_PS      = 29;
4397         public static final int AACObjectELD        = 39;
4398         /** xHE-AAC (includes USAC) */
4399         public static final int AACObjectXHE        = 42;
4400 
4401         public static final int VP8Level_Version0 = 0x01;
4402         public static final int VP8Level_Version1 = 0x02;
4403         public static final int VP8Level_Version2 = 0x04;
4404         public static final int VP8Level_Version3 = 0x08;
4405 
4406         public static final int VP8ProfileMain = 0x01;
4407 
4408         /** VP9 Profile 0 4:2:0 8-bit */
4409         public static final int VP9Profile0 = 0x01;
4410 
4411         /** VP9 Profile 1 4:2:2 8-bit */
4412         public static final int VP9Profile1 = 0x02;
4413 
4414         /** VP9 Profile 2 4:2:0 10-bit */
4415         public static final int VP9Profile2 = 0x04;
4416 
4417         /** VP9 Profile 3 4:2:2 10-bit */
4418         public static final int VP9Profile3 = 0x08;
4419 
4420         // HDR profiles also support passing HDR metadata
4421         /** VP9 Profile 2 4:2:0 10-bit HDR */
4422         public static final int VP9Profile2HDR = 0x1000;
4423 
4424         /** VP9 Profile 3 4:2:2 10-bit HDR */
4425         public static final int VP9Profile3HDR = 0x2000;
4426 
4427         /** VP9 Profile 2 4:2:0 10-bit HDR10Plus */
4428         public static final int VP9Profile2HDR10Plus = 0x4000;
4429 
4430         /** VP9 Profile 3 4:2:2 10-bit HDR10Plus */
4431         public static final int VP9Profile3HDR10Plus = 0x8000;
4432 
4433         public static final int VP9Level1  = 0x1;
4434         public static final int VP9Level11 = 0x2;
4435         public static final int VP9Level2  = 0x4;
4436         public static final int VP9Level21 = 0x8;
4437         public static final int VP9Level3  = 0x10;
4438         public static final int VP9Level31 = 0x20;
4439         public static final int VP9Level4  = 0x40;
4440         public static final int VP9Level41 = 0x80;
4441         public static final int VP9Level5  = 0x100;
4442         public static final int VP9Level51 = 0x200;
4443         public static final int VP9Level52 = 0x400;
4444         public static final int VP9Level6  = 0x800;
4445         public static final int VP9Level61 = 0x1000;
4446         public static final int VP9Level62 = 0x2000;
4447 
4448         public static final int HEVCProfileMain        = 0x01;
4449         public static final int HEVCProfileMain10      = 0x02;
4450         public static final int HEVCProfileMainStill   = 0x04;
4451         public static final int HEVCProfileMain10HDR10 = 0x1000;
4452         public static final int HEVCProfileMain10HDR10Plus = 0x2000;
4453 
4454         public static final int HEVCMainTierLevel1  = 0x1;
4455         public static final int HEVCHighTierLevel1  = 0x2;
4456         public static final int HEVCMainTierLevel2  = 0x4;
4457         public static final int HEVCHighTierLevel2  = 0x8;
4458         public static final int HEVCMainTierLevel21 = 0x10;
4459         public static final int HEVCHighTierLevel21 = 0x20;
4460         public static final int HEVCMainTierLevel3  = 0x40;
4461         public static final int HEVCHighTierLevel3  = 0x80;
4462         public static final int HEVCMainTierLevel31 = 0x100;
4463         public static final int HEVCHighTierLevel31 = 0x200;
4464         public static final int HEVCMainTierLevel4  = 0x400;
4465         public static final int HEVCHighTierLevel4  = 0x800;
4466         public static final int HEVCMainTierLevel41 = 0x1000;
4467         public static final int HEVCHighTierLevel41 = 0x2000;
4468         public static final int HEVCMainTierLevel5  = 0x4000;
4469         public static final int HEVCHighTierLevel5  = 0x8000;
4470         public static final int HEVCMainTierLevel51 = 0x10000;
4471         public static final int HEVCHighTierLevel51 = 0x20000;
4472         public static final int HEVCMainTierLevel52 = 0x40000;
4473         public static final int HEVCHighTierLevel52 = 0x80000;
4474         public static final int HEVCMainTierLevel6  = 0x100000;
4475         public static final int HEVCHighTierLevel6  = 0x200000;
4476         public static final int HEVCMainTierLevel61 = 0x400000;
4477         public static final int HEVCHighTierLevel61 = 0x800000;
4478         public static final int HEVCMainTierLevel62 = 0x1000000;
4479         public static final int HEVCHighTierLevel62 = 0x2000000;
4480 
4481         private static final int HEVCHighTierLevels =
4482             HEVCHighTierLevel1 | HEVCHighTierLevel2 | HEVCHighTierLevel21 | HEVCHighTierLevel3 |
4483             HEVCHighTierLevel31 | HEVCHighTierLevel4 | HEVCHighTierLevel41 | HEVCHighTierLevel5 |
4484             HEVCHighTierLevel51 | HEVCHighTierLevel52 | HEVCHighTierLevel6 | HEVCHighTierLevel61 |
4485             HEVCHighTierLevel62;
4486 
4487         public static final int DolbyVisionProfileDvavPer = 0x1;
4488         public static final int DolbyVisionProfileDvavPen = 0x2;
4489         public static final int DolbyVisionProfileDvheDer = 0x4;
4490         public static final int DolbyVisionProfileDvheDen = 0x8;
4491         public static final int DolbyVisionProfileDvheDtr = 0x10;
4492         public static final int DolbyVisionProfileDvheStn = 0x20;
4493         public static final int DolbyVisionProfileDvheDth = 0x40;
4494         public static final int DolbyVisionProfileDvheDtb = 0x80;
4495         public static final int DolbyVisionProfileDvheSt  = 0x100;
4496         public static final int DolbyVisionProfileDvavSe  = 0x200;
4497         /** Dolby Vision AV1 profile */
4498         @SuppressLint("AllUpper")
4499         public static final int DolbyVisionProfileDvav110 = 0x400;
4500 
4501         public static final int DolbyVisionLevelHd24    = 0x1;
4502         public static final int DolbyVisionLevelHd30    = 0x2;
4503         public static final int DolbyVisionLevelFhd24   = 0x4;
4504         public static final int DolbyVisionLevelFhd30   = 0x8;
4505         public static final int DolbyVisionLevelFhd60   = 0x10;
4506         public static final int DolbyVisionLevelUhd24   = 0x20;
4507         public static final int DolbyVisionLevelUhd30   = 0x40;
4508         public static final int DolbyVisionLevelUhd48   = 0x80;
4509         public static final int DolbyVisionLevelUhd60   = 0x100;
4510         @SuppressLint("AllUpper")
4511         public static final int DolbyVisionLevelUhd120  = 0x200;
4512         @SuppressLint("AllUpper")
4513         public static final int DolbyVisionLevel8k30    = 0x400;
4514         @SuppressLint("AllUpper")
4515         public static final int DolbyVisionLevel8k60    = 0x800;
4516 
4517         // Profiles and levels for AV1 Codec, corresponding to the definitions in
4518         // "AV1 Bitstream & Decoding Process Specification", Annex A
4519         // found at https://aomedia.org/av1-bitstream-and-decoding-process-specification/
4520 
4521         /**
4522          * AV1 Main profile 4:2:0 8-bit
4523          *
4524          * See definition in
4525          * <a href="https://aomedia.org/av1-bitstream-and-decoding-process-specification/">AV1 Specification</a>
4526          * Annex A.
4527          */
4528         public static final int AV1ProfileMain8   = 0x1;
4529 
4530         /**
4531          * AV1 Main profile 4:2:0 10-bit
4532          *
4533          * See definition in
4534          * <a href="https://aomedia.org/av1-bitstream-and-decoding-process-specification/">AV1 Specification</a>
4535          * Annex A.
4536          */
4537         public static final int AV1ProfileMain10  = 0x2;
4538 
4539 
4540         /** AV1 Main profile 4:2:0 10-bit with HDR10. */
4541         public static final int AV1ProfileMain10HDR10 = 0x1000;
4542 
4543         /** AV1 Main profile 4:2:0 10-bit with HDR10Plus. */
4544         public static final int AV1ProfileMain10HDR10Plus = 0x2000;
4545 
4546         public static final int AV1Level2       = 0x1;
4547         public static final int AV1Level21      = 0x2;
4548         public static final int AV1Level22      = 0x4;
4549         public static final int AV1Level23      = 0x8;
4550         public static final int AV1Level3       = 0x10;
4551         public static final int AV1Level31      = 0x20;
4552         public static final int AV1Level32      = 0x40;
4553         public static final int AV1Level33      = 0x80;
4554         public static final int AV1Level4       = 0x100;
4555         public static final int AV1Level41      = 0x200;
4556         public static final int AV1Level42      = 0x400;
4557         public static final int AV1Level43      = 0x800;
4558         public static final int AV1Level5       = 0x1000;
4559         public static final int AV1Level51      = 0x2000;
4560         public static final int AV1Level52      = 0x4000;
4561         public static final int AV1Level53      = 0x8000;
4562         public static final int AV1Level6       = 0x10000;
4563         public static final int AV1Level61      = 0x20000;
4564         public static final int AV1Level62      = 0x40000;
4565         public static final int AV1Level63      = 0x80000;
4566         public static final int AV1Level7       = 0x100000;
4567         public static final int AV1Level71      = 0x200000;
4568         public static final int AV1Level72      = 0x400000;
4569         public static final int AV1Level73      = 0x800000;
4570 
4571         /** DTS codec profile for DTS HRA. */
4572         @SuppressLint("AllUpper")
4573         public static final int DTS_HDProfileHRA = 0x1;
4574         /** DTS codec profile for DTS Express. */
4575         @SuppressLint("AllUpper")
4576         public static final int DTS_HDProfileLBR = 0x2;
4577         /** DTS codec profile for DTS-HD Master Audio */
4578         @SuppressLint("AllUpper")
4579         public static final int DTS_HDProfileMA = 0x4;
4580         /** DTS codec profile for DTS:X Profile 1 */
4581         @SuppressLint("AllUpper")
4582         public static final int DTS_UHDProfileP1 = 0x1;
4583         /** DTS codec profile for DTS:X Profile 2 */
4584         @SuppressLint("AllUpper")
4585         public static final int DTS_UHDProfileP2 = 0x2;
4586 
4587         // Profiles and levels for AC-4 Codec, corresponding to the definitions in
4588         // "The MIME codecs parameter", Annex E.13
4589         // found at https://www.etsi.org/deliver/etsi_ts/103100_103199/10319002/01.02.01_60/ts_10319002v010201p.pdf
4590         // profile = ((1 << bitstream_version) << 8) | (1 << presentation_version);
4591         // level = 1 << mdcompat;
4592 
4593         @SuppressLint("AllUpper")
4594         private static final int AC4BitstreamVersion0 = 0x01;
4595         @SuppressLint("AllUpper")
4596         private static final int AC4BitstreamVersion1 = 0x02;
4597         @SuppressLint("AllUpper")
4598         private static final int AC4BitstreamVersion2 = 0x04;
4599 
4600         @SuppressLint("AllUpper")
4601         private static final int AC4PresentationVersion0 = 0x01;
4602         @SuppressLint("AllUpper")
4603         private static final int AC4PresentationVersion1 = 0x02;
4604         @SuppressLint("AllUpper")
4605         private static final int AC4PresentationVersion2 = 0x04;
4606 
4607         /**
4608          * AC-4 codec profile with bitstream_version 0 and presentation_version 0
4609          * as per ETSI TS 103 190-2 v1.2.1
4610          */
4611         @SuppressLint("AllUpper")
4612         public static final int AC4Profile00 = AC4BitstreamVersion0 << 8 | AC4PresentationVersion0;
4613 
4614         /**
4615          * AC-4 codec profile with bitstream_version 1 and presentation_version 0
4616          * as per ETSI TS 103 190-2 v1.2.1
4617          */
4618         @SuppressLint("AllUpper")
4619         public static final int AC4Profile10 = AC4BitstreamVersion1 << 8 | AC4PresentationVersion0;
4620 
4621         /**
4622          * AC-4 codec profile with bitstream_version 1 and presentation_version 1
4623          * as per ETSI TS 103 190-2 v1.2.1
4624          */
4625         @SuppressLint("AllUpper")
4626         public static final int AC4Profile11 = AC4BitstreamVersion1 << 8 | AC4PresentationVersion1;
4627 
4628         /**
4629          * AC-4 codec profile with bitstream_version 2 and presentation_version 1
4630          * as per ETSI TS 103 190-2 v1.2.1
4631          */
4632         @SuppressLint("AllUpper")
4633         public static final int AC4Profile21 = AC4BitstreamVersion2 << 8 | AC4PresentationVersion1;
4634 
4635         /**
4636          * AC-4 codec profile with bitstream_version 2 and presentation_version 2
4637          * as per ETSI TS 103 190-2 v1.2.1
4638          */
4639         @SuppressLint("AllUpper")
4640         public static final int AC4Profile22 = AC4BitstreamVersion2 << 8 | AC4PresentationVersion2;
4641 
4642         /** AC-4 codec level corresponding to mdcompat 0 as per ETSI TS 103 190-2 v1.2.1 */
4643         @SuppressLint("AllUpper")
4644         public static final int AC4Level0       = 0x01;
4645         /** AC-4 codec level corresponding to mdcompat 1 as per ETSI TS 103 190-2 v1.2.1 */
4646         @SuppressLint("AllUpper")
4647         public static final int AC4Level1       = 0x02;
4648         /** AC-4 codec level corresponding to mdcompat 2 as per ETSI TS 103 190-2 v1.2.1 */
4649         @SuppressLint("AllUpper")
4650         public static final int AC4Level2       = 0x04;
4651         /** AC-4 codec level corresponding to mdcompat 3 as per ETSI TS 103 190-2 v1.2.1 */
4652         @SuppressLint("AllUpper")
4653         public static final int AC4Level3       = 0x08;
4654         /** AC-4 codec level corresponding to mdcompat 4 as per ETSI TS 103 190-2 v1.2.1 */
4655         @SuppressLint("AllUpper")
4656         public static final int AC4Level4       = 0x10;
4657 
4658         // Profiles and levels/bands for APV Codec, corresponding to the definitions in
4659         // "Advanced Professional Video", 10.1.3 Profiles, 10.1.4 Levels and Bands
4660         // found at https://www.ietf.org/archive/id/draft-lim-apv-02.html
4661 
4662         /**
4663          * APV codec profile 422-10 as per IETF lim-apv-02, 10.1.3.1.1
4664          */
4665         @SuppressLint("AllUpper")
4666         @FlaggedApi(FLAG_APV_SUPPORT)
4667         public static final int APVProfile422_10 =  0x01;
4668 
4669         /**
4670          * APV codec profile 422-10 as per IETF lim-apv-02, 10.1.3.1.1
4671          * with HDR10.
4672          */
4673         @SuppressLint("AllUpper")
4674         @FlaggedApi(FLAG_APV_SUPPORT)
4675         public static final int APVProfile422_10HDR10 =  0x1000;
4676 
4677         /**
4678          * APV codec profile 422-10 as per IETF lim-apv-02, 10.1.3.1.1
4679          * with HDR10Plus.
4680          */
4681         @SuppressLint("AllUpper")
4682         @FlaggedApi(FLAG_APV_SUPPORT)
4683         public static final int APVProfile422_10HDR10Plus =  0x2000;
4684 
4685         // For APV Levels, the numerical values are constructed as follows:
4686         //   ((0x100 << (level_num - 1)) | (1 << band))
4687         // where:
4688         //   - "level_num" is the APV Level numbered consecutively
4689         //     (i.e., Level 1 == 1, Level 1.1 == 2, etc.)
4690         //   - "band" is the APV Band
4691 
4692         /** APV Codec Level 1, Band 0 as per IETF lim-apv-02, 10.1.4 */
4693         @SuppressLint("AllUpper")
4694         @FlaggedApi(FLAG_APV_SUPPORT)
4695         public static final int APVLevel1Band0 =  0x101;
4696         /** APV Codec Level 1, Band 1 as per IETF lim-apv-02, 10.1.4 */
4697         @SuppressLint("AllUpper")
4698         @FlaggedApi(FLAG_APV_SUPPORT)
4699         public static final int APVLevel1Band1 =  0x102;
4700         /** APV Codec Level 1, Band 2 as per IETF lim-apv-02, 10.1.4 */
4701         @SuppressLint("AllUpper")
4702         @FlaggedApi(FLAG_APV_SUPPORT)
4703         public static final int APVLevel1Band2 =  0x104;
4704         /** APV Codec Level 1, Band 3 as per IETF lim-apv-02, 10.1.4 */
4705         @SuppressLint("AllUpper")
4706         @FlaggedApi(FLAG_APV_SUPPORT)
4707         public static final int APVLevel1Band3 =  0x108;
4708         /** APV Codec Level 1.1, Band 0 as per IETF lim-apv-02, 10.1.4 */
4709         @SuppressLint("AllUpper")
4710         @FlaggedApi(FLAG_APV_SUPPORT)
4711         public static final int APVLevel11Band0 = 0x201;
4712         /** APV Codec Level 1.1, Band 1 as per IETF lim-apv-02, 10.1.4 */
4713         @SuppressLint("AllUpper")
4714         @FlaggedApi(FLAG_APV_SUPPORT)
4715         public static final int APVLevel11Band1 = 0x202;
4716         /** APV Codec Level 1.1, Band 2 as per IETF lim-apv-02, 10.1.4 */
4717         @SuppressLint("AllUpper")
4718         @FlaggedApi(FLAG_APV_SUPPORT)
4719         public static final int APVLevel11Band2 = 0x204;
4720         /** APV Codec Level 1.1, Band 3 as per IETF lim-apv-02, 10.1.4 */
4721         @SuppressLint("AllUpper")
4722         @FlaggedApi(FLAG_APV_SUPPORT)
4723         public static final int APVLevel11Band3 = 0x208;
4724         /** APV Codec Level 2, Band 0 as per IETF lim-apv-02, 10.1.4 */
4725         @SuppressLint("AllUpper")
4726         @FlaggedApi(FLAG_APV_SUPPORT)
4727         public static final int APVLevel2Band0 =  0x401;
4728         /** APV Codec Level 2, Band 1 as per IETF lim-apv-02, 10.1.4 */
4729         @SuppressLint("AllUpper")
4730         @FlaggedApi(FLAG_APV_SUPPORT)
4731         public static final int APVLevel2Band1 =  0x402;
4732         /** APV Codec Level 2, Band 2 as per IETF lim-apv-02, 10.1.4 */
4733         @SuppressLint("AllUpper")
4734         @FlaggedApi(FLAG_APV_SUPPORT)
4735         public static final int APVLevel2Band2 =  0x404;
4736         /** APV Codec Level 2, Band 3 as per IETF lim-apv-02, 10.1.4 */
4737         @SuppressLint("AllUpper")
4738         @FlaggedApi(FLAG_APV_SUPPORT)
4739         public static final int APVLevel2Band3 =  0x408;
4740         /** APV Codec Level 2.1, Band 0 as per IETF lim-apv-02, 10.1.4 */
4741         @SuppressLint("AllUpper")
4742         @FlaggedApi(FLAG_APV_SUPPORT)
4743         public static final int APVLevel21Band0 = 0x801;
4744         /** APV Codec Level 2.1, Band 1 as per IETF lim-apv-02, 10.1.4 */
4745         @SuppressLint("AllUpper")
4746         @FlaggedApi(FLAG_APV_SUPPORT)
4747         public static final int APVLevel21Band1 = 0x802;
4748         /** APV Codec Level 2.1, Band 2 as per IETF lim-apv-02, 10.1.4 */
4749         @SuppressLint("AllUpper")
4750         @FlaggedApi(FLAG_APV_SUPPORT)
4751         public static final int APVLevel21Band2 = 0x804;
4752         /** APV Codec Level 2.1, Band 3 as per IETF lim-apv-02, 10.1.4 */
4753         @SuppressLint("AllUpper")
4754         @FlaggedApi(FLAG_APV_SUPPORT)
4755         public static final int APVLevel21Band3 = 0x808;
4756         /** APV Codec Level 3, Band 0 as per IETF lim-apv-02, 10.1.4 */
4757         @SuppressLint("AllUpper")
4758         @FlaggedApi(FLAG_APV_SUPPORT)
4759         public static final int APVLevel3Band0 =  0x1001;
4760         /** APV Codec Level 3, Band 1 as per IETF lim-apv-02, 10.1.4 */
4761         @SuppressLint("AllUpper")
4762         @FlaggedApi(FLAG_APV_SUPPORT)
4763         public static final int APVLevel3Band1 =  0x1002;
4764         /** APV Codec Level 3, Band 2 as per IETF lim-apv-02, 10.1.4 */
4765         @SuppressLint("AllUpper")
4766         @FlaggedApi(FLAG_APV_SUPPORT)
4767         public static final int APVLevel3Band2 =  0x1004;
4768         /** APV Codec Level 3, Band 3 as per IETF lim-apv-02, 10.1.4 */
4769         @SuppressLint("AllUpper")
4770         @FlaggedApi(FLAG_APV_SUPPORT)
4771         public static final int APVLevel3Band3 =  0x1008;
4772         /** APV Codec Level 3.1, Band 0 as per IETF lim-apv-02, 10.1.4 */
4773         @SuppressLint("AllUpper")
4774         @FlaggedApi(FLAG_APV_SUPPORT)
4775         public static final int APVLevel31Band0 = 0x2001;
4776         /** APV Codec Level 3.1, Band 1 as per IETF lim-apv-02, 10.1.4 */
4777         @SuppressLint("AllUpper")
4778         @FlaggedApi(FLAG_APV_SUPPORT)
4779         public static final int APVLevel31Band1 = 0x2002;
4780         /** APV Codec Level 3.1, Band 2 as per IETF lim-apv-02, 10.1.4 */
4781         @SuppressLint("AllUpper")
4782         @FlaggedApi(FLAG_APV_SUPPORT)
4783         public static final int APVLevel31Band2 = 0x2004;
4784         /** APV Codec Level 3.1, Band 3 as per IETF lim-apv-02, 10.1.4 */
4785         @SuppressLint("AllUpper")
4786         @FlaggedApi(FLAG_APV_SUPPORT)
4787         public static final int APVLevel31Band3 = 0x2008;
4788         /** APV Codec Level 4, Band 0 as per IETF lim-apv-02, 10.1.4 */
4789         @SuppressLint("AllUpper")
4790         @FlaggedApi(FLAG_APV_SUPPORT)
4791         public static final int APVLevel4Band0 =  0x4001;
4792         /** APV Codec Level 4, Band 1 as per IETF lim-apv-02, 10.1.4 */
4793         @SuppressLint("AllUpper")
4794         @FlaggedApi(FLAG_APV_SUPPORT)
4795         public static final int APVLevel4Band1 =  0x4002;
4796         /** APV Codec Level 4, Band 2 as per IETF lim-apv-02, 10.1.4 */
4797         @SuppressLint("AllUpper")
4798         @FlaggedApi(FLAG_APV_SUPPORT)
4799         public static final int APVLevel4Band2 =  0x4004;
4800         /** APV Codec Level 4, Band 3 as per IETF lim-apv-02, 10.1.4 */
4801         @SuppressLint("AllUpper")
4802         @FlaggedApi(FLAG_APV_SUPPORT)
4803         public static final int APVLevel4Band3 =  0x4008;
4804         /** APV Codec Level 4.1, Band 0 as per IETF lim-apv-02, 10.1.4 */
4805         @SuppressLint("AllUpper")
4806         @FlaggedApi(FLAG_APV_SUPPORT)
4807         public static final int APVLevel41Band0 = 0x8001;
4808         /** APV Codec Level 4.1, Band 1 as per IETF lim-apv-02, 10.1.4 */
4809         @SuppressLint("AllUpper")
4810         @FlaggedApi(FLAG_APV_SUPPORT)
4811         public static final int APVLevel41Band1 = 0x8002;
4812         /** APV Codec Level 4.1, Band 2 as per IETF lim-apv-02, 10.1.4 */
4813         @SuppressLint("AllUpper")
4814         @FlaggedApi(FLAG_APV_SUPPORT)
4815         public static final int APVLevel41Band2 = 0x8004;
4816         /** APV Codec Level 4.1, Band 3 as per IETF lim-apv-02, 10.1.4 */
4817         @SuppressLint("AllUpper")
4818         @FlaggedApi(FLAG_APV_SUPPORT)
4819         public static final int APVLevel41Band3 = 0x8008;
4820         /** APV Codec Level 5, Band 0 as per IETF lim-apv-02, 10.1.4 */
4821         @SuppressLint("AllUpper")
4822         @FlaggedApi(FLAG_APV_SUPPORT)
4823         public static final int APVLevel5Band0 =  0x10001;
4824         /** APV Codec Level 5, Band 1 as per IETF lim-apv-02, 10.1.4 */
4825         @SuppressLint("AllUpper")
4826         @FlaggedApi(FLAG_APV_SUPPORT)
4827         public static final int APVLevel5Band1 =  0x10002;
4828         /** APV Codec Level 5, Band 2 as per IETF lim-apv-02, 10.1.4 */
4829         @SuppressLint("AllUpper")
4830         @FlaggedApi(FLAG_APV_SUPPORT)
4831         public static final int APVLevel5Band2 =  0x10004;
4832         /** APV Codec Level 5, Band 3 as per IETF lim-apv-02, 10.1.4 */
4833         @SuppressLint("AllUpper")
4834         @FlaggedApi(FLAG_APV_SUPPORT)
4835         public static final int APVLevel5Band3 =  0x10008;
4836         /** APV Codec Level 5.1, Band 0 as per IETF lim-apv-02, 10.1.4 */
4837         @SuppressLint("AllUpper")
4838         @FlaggedApi(FLAG_APV_SUPPORT)
4839         public static final int APVLevel51Band0 = 0x20001;
4840         /** APV Codec Level 5.1, Band 1 as per IETF lim-apv-02, 10.1.4 */
4841         @SuppressLint("AllUpper")
4842         @FlaggedApi(FLAG_APV_SUPPORT)
4843         public static final int APVLevel51Band1 = 0x20002;
4844         /** APV Codec Level 5.1, Band 2 as per IETF lim-apv-02, 10.1.4 */
4845         @SuppressLint("AllUpper")
4846         @FlaggedApi(FLAG_APV_SUPPORT)
4847         public static final int APVLevel51Band2 = 0x20004;
4848         /** APV Codec Level 5.1, Band 3 as per IETF lim-apv-02, 10.1.4 */
4849         @SuppressLint("AllUpper")
4850         @FlaggedApi(FLAG_APV_SUPPORT)
4851         public static final int APVLevel51Band3 = 0x20008;
4852         /** APV Codec Level 6, Band 0 as per IETF lim-apv-02, 10.1.4 */
4853         @SuppressLint("AllUpper")
4854         @FlaggedApi(FLAG_APV_SUPPORT)
4855         public static final int APVLevel6Band0 =  0x40001;
4856         /** APV Codec Level 6, Band 1 as per IETF lim-apv-02, 10.1.4 */
4857         @SuppressLint("AllUpper")
4858         @FlaggedApi(FLAG_APV_SUPPORT)
4859         public static final int APVLevel6Band1 =  0x40002;
4860         /** APV Codec Level 6, Band 2 as per IETF lim-apv-02, 10.1.4 */
4861         @SuppressLint("AllUpper")
4862         @FlaggedApi(FLAG_APV_SUPPORT)
4863         public static final int APVLevel6Band2 =  0x40004;
4864         /** APV Codec Level 6, Band 3 as per IETF lim-apv-02, 10.1.4 */
4865         @SuppressLint("AllUpper")
4866         @FlaggedApi(FLAG_APV_SUPPORT)
4867         public static final int APVLevel6Band3 =  0x40008;
4868         /** APV Codec Level 6.1, Band 0 as per IETF lim-apv-02, 10.1.4 */
4869         @SuppressLint("AllUpper")
4870         @FlaggedApi(FLAG_APV_SUPPORT)
4871         public static final int APVLevel61Band0 = 0x80001;
4872         /** APV Codec Level 6.1, Band 1 as per IETF lim-apv-02, 10.1.4 */
4873         @SuppressLint("AllUpper")
4874         @FlaggedApi(FLAG_APV_SUPPORT)
4875         public static final int APVLevel61Band1 = 0x80002;
4876         /** APV Codec Level 6.1, Band 2 as per IETF lim-apv-02, 10.1.4 */
4877         @SuppressLint("AllUpper")
4878         @FlaggedApi(FLAG_APV_SUPPORT)
4879         public static final int APVLevel61Band2 = 0x80004;
4880         /** APV Codec Level 6.1, Band 3 as per IETF lim-apv-02, 10.1.4 */
4881         @SuppressLint("AllUpper")
4882         @FlaggedApi(FLAG_APV_SUPPORT)
4883         public static final int APVLevel61Band3 = 0x80008;
4884         /** APV Codec Level 7, Band 0 as per IETF lim-apv-02, 10.1.4 */
4885         @SuppressLint("AllUpper")
4886         @FlaggedApi(FLAG_APV_SUPPORT)
4887         public static final int APVLevel7Band0 =  0x100001;
4888         /** APV Codec Level 7, Band 1 as per IETF lim-apv-02, 10.1.4 */
4889         @SuppressLint("AllUpper")
4890         @FlaggedApi(FLAG_APV_SUPPORT)
4891         public static final int APVLevel7Band1 =  0x100002;
4892         /** APV Codec Level 7, Band 2 as per IETF lim-apv-02, 10.1.4 */
4893         @SuppressLint("AllUpper")
4894         @FlaggedApi(FLAG_APV_SUPPORT)
4895         public static final int APVLevel7Band2 =  0x100004;
4896         /** APV Codec Level 7, Band 3 as per IETF lim-apv-02, 10.1.4 */
4897         @SuppressLint("AllUpper")
4898         @FlaggedApi(FLAG_APV_SUPPORT)
4899         public static final int APVLevel7Band3 =  0x100008;
4900         /** APV Codec Level 7.1, Band 0 as per IETF lim-apv-02, 10.1.4 */
4901         @SuppressLint("AllUpper")
4902         @FlaggedApi(FLAG_APV_SUPPORT)
4903         public static final int APVLevel71Band0 = 0x200001;
4904         /** APV Codec Level 7.1, Band 1 as per IETF lim-apv-02, 10.1.4 */
4905         @SuppressLint("AllUpper")
4906         @FlaggedApi(FLAG_APV_SUPPORT)
4907         public static final int APVLevel71Band1 = 0x200002;
4908         /** APV Codec Level 7.1, Band 2 as per IETF lim-apv-02, 10.1.4 */
4909         @SuppressLint("AllUpper")
4910         @FlaggedApi(FLAG_APV_SUPPORT)
4911         public static final int APVLevel71Band2 = 0x200004;
4912         /** APV Codec Level 7.1, Band 3 as per IETF lim-apv-02, 10.1.4 */
4913         @SuppressLint("AllUpper")
4914         @FlaggedApi(FLAG_APV_SUPPORT)
4915         public static final int APVLevel71Band3 = 0x200008;
4916 
4917         // IAMF profiles are defined as the combination of the (listed from LSB to MSB):
4918         //  - audio codec (2 bytes)
4919         //  - profile (1 byte, offset 16)
4920         //  - specification version (1 byte, offset 24)
4921         private static final int IAMF_CODEC_OPUS = 0x1;
4922         private static final int IAMF_CODEC_AAC  = 0x1 << 1;
4923         private static final int IAMF_CODEC_FLAC = 0x1 << 2;
4924         private static final int IAMF_CODEC_PCM  = 0x1 << 3;
4925         private static final int IAMF_PROFILE_SIMPLE        = 0x1 << 16;
4926         private static final int IAMF_PROFILE_BASE          = 0x1 << 17;
4927         private static final int IAMF_PROFILE_BASE_ENHANCED = 0x1 << 18;
4928         private static final int IAMF_v1 = 0x1 << 24;
4929         /**
4930          * IAMF profile using the
4931          * <a href="https://aomediacodec.github.io/iamf/#profiles-simple">simple profile</a>
4932          * with audio streams <a href="https://aomediacodec.github.io/iamf/#codec_id">encoded</a>
4933          * in OPUS.
4934          */
4935         @SuppressLint("AllUpper")
4936         @FlaggedApi(FLAG_IAMF_DEFINITIONS_API)
4937         public static final int IAMFProfileSimpleOpus =
4938                 IAMF_v1 + IAMF_PROFILE_SIMPLE + IAMF_CODEC_OPUS;
4939         /**
4940          * IAMF profile using the
4941          * <a href="https://aomediacodec.github.io/iamf/#profiles-simple">simple profile</a>
4942          * with audio streams <a href="https://aomediacodec.github.io/iamf/#codec_id">encoded</a>
4943          * in AAC.
4944          */
4945         @SuppressLint("AllUpper")
4946         @FlaggedApi(FLAG_IAMF_DEFINITIONS_API)
4947         public static final int IAMFProfileSimpleAac =
4948                 IAMF_v1 + IAMF_PROFILE_SIMPLE + IAMF_CODEC_AAC;
4949         /**
4950          * IAMF profile using the
4951          * <a href="https://aomediacodec.github.io/iamf/#profiles-simple">simple profile</a>
4952          * with audio streams <a href="https://aomediacodec.github.io/iamf/#codec_id">encoded</a>
4953          * in FLAC.
4954          */
4955         @SuppressLint("AllUpper")
4956         @FlaggedApi(FLAG_IAMF_DEFINITIONS_API)
4957         public static final int IAMFProfileSimpleFlac =
4958                 IAMF_v1 + IAMF_PROFILE_SIMPLE + IAMF_CODEC_FLAC;
4959         /**
4960          * IAMF profile using the
4961          * <a href="https://aomediacodec.github.io/iamf/#profiles-simple">simple profile</a>
4962          * with audio streams <a href="https://aomediacodec.github.io/iamf/#codec_id">encoded</a>
4963          * in PCM.
4964          */
4965         @SuppressLint("AllUpper")
4966         @FlaggedApi(FLAG_IAMF_DEFINITIONS_API)
4967         public static final int IAMFProfileSimplePcm =
4968                 IAMF_v1 + IAMF_PROFILE_SIMPLE + IAMF_CODEC_PCM;
4969         /**
4970          * IAMF profile using the
4971          * <a href="https://aomediacodec.github.io/iamf/#profiles-base">base profile</a>
4972          * with audio streams <a href="https://aomediacodec.github.io/iamf/#codec_id">encoded</a>
4973          * in OPUS.
4974          */
4975         @SuppressLint("AllUpper")
4976         @FlaggedApi(FLAG_IAMF_DEFINITIONS_API)
4977         public static final int IAMFProfileBaseOpus =
4978                 IAMF_v1 + IAMF_PROFILE_BASE + IAMF_CODEC_OPUS;
4979         /**
4980          * IAMF profile using the
4981          * <a href="https://aomediacodec.github.io/iamf/#profiles-base">base profile</a>
4982          * with audio streams <a href="https://aomediacodec.github.io/iamf/#codec_id">encoded</a>
4983          * in AAC.
4984          */
4985         @SuppressLint("AllUpper")
4986         @FlaggedApi(FLAG_IAMF_DEFINITIONS_API)
4987         public static final int IAMFProfileBaseAac =
4988                 IAMF_v1 + IAMF_PROFILE_BASE + IAMF_CODEC_AAC;
4989         /**
4990          * IAMF profile using the
4991          * <a href="https://aomediacodec.github.io/iamf/#profiles-base">base profile</a>
4992          * with audio streams <a href="https://aomediacodec.github.io/iamf/#codec_id">encoded</a>
4993          * in FLAC.
4994          */
4995         @SuppressLint("AllUpper")
4996         @FlaggedApi(FLAG_IAMF_DEFINITIONS_API)
4997         public static final int IAMFProfileBaseFlac =
4998                 IAMF_v1 + IAMF_PROFILE_BASE + IAMF_CODEC_FLAC;
4999         /**
5000          * IAMF profile using the
5001          * <a href="https://aomediacodec.github.io/iamf/#profiles-base">base profile</a>
5002          * with audio streams <a href="https://aomediacodec.github.io/iamf/#codec_id">encoded</a>
5003          * in PCM.
5004          */
5005         @SuppressLint("AllUpper")
5006         @FlaggedApi(FLAG_IAMF_DEFINITIONS_API)
5007         public static final int IAMFProfileBasePcm =
5008                 IAMF_v1 + IAMF_PROFILE_BASE + IAMF_CODEC_PCM;
5009         /**
5010          * IAMF profile using the
5011          * <a href="https://aomediacodec.github.io/iamf/#profiles-base-enhanced">base-enhanced profile</a>
5012          * with audio streams <a href="https://aomediacodec.github.io/iamf/#codec_id">encoded</a>
5013          * in OPUS.
5014          */
5015         @SuppressLint("AllUpper")
5016         @FlaggedApi(FLAG_IAMF_DEFINITIONS_API)
5017         public static final int IAMFProfileBaseEnhancedOpus =
5018                 IAMF_v1 + IAMF_PROFILE_BASE_ENHANCED + IAMF_CODEC_OPUS;
5019         /**
5020          * IAMF profile using the
5021          * <a href="https://aomediacodec.github.io/iamf/#profiles-base-enhanced">base-enhanced profile</a>
5022          * with audio streams <a href="https://aomediacodec.github.io/iamf/#codec_id">encoded</a>
5023          * in AAC.
5024          */
5025         @SuppressLint("AllUpper")
5026         @FlaggedApi(FLAG_IAMF_DEFINITIONS_API)
5027         public static final int IAMFProfileBaseEnhancedAac =
5028                 IAMF_v1 + IAMF_PROFILE_BASE_ENHANCED + IAMF_CODEC_AAC;
5029         /**
5030          * IAMF profile using the
5031          * <a href="https://aomediacodec.github.io/iamf/#profiles-base-enhanced">base-enhanced profile</a>
5032          * with audio streams <a href="https://aomediacodec.github.io/iamf/#codec_id">encoded</a>
5033          * in FLAC.
5034          */
5035         @SuppressLint("AllUpper")
5036         @FlaggedApi(FLAG_IAMF_DEFINITIONS_API)
5037         public static final int IAMFProfileBaseEnhancedFlac =
5038                 IAMF_v1 + IAMF_PROFILE_BASE_ENHANCED + IAMF_CODEC_FLAC;
5039         /**
5040          * IAMF profile using the
5041          * <a href="https://aomediacodec.github.io/iamf/#profiles-base-enhanced">base-enhanced profile</a>
5042          * with audio streams <a href="https://aomediacodec.github.io/iamf/#codec_id">encoded</a>
5043          * in PCM.
5044          */
5045         @SuppressLint("AllUpper")
5046         @FlaggedApi(FLAG_IAMF_DEFINITIONS_API)
5047         public static final int IAMFProfileBaseEnhancedPcm =
5048                 IAMF_v1 + IAMF_PROFILE_BASE_ENHANCED + IAMF_CODEC_PCM;
5049 
5050         /**
5051          * The profile of the media content. Depending on the type of media this can be
5052          * one of the profile values defined in this class.
5053          */
5054         public int profile;
5055 
5056         /**
5057          * The level of the media content. Depending on the type of media this can be
5058          * one of the level values defined in this class.
5059          *
5060          * Note that VP9 decoder on platforms before {@link android.os.Build.VERSION_CODES#N} may
5061          * not advertise a profile level support. For those VP9 decoders, please use
5062          * {@link VideoCapabilities} to determine the codec capabilities.
5063          */
5064         public int level;
5065 
5066         @Override
5067         public boolean equals(Object obj) {
5068             if (obj == null) {
5069                 return false;
5070             }
5071             if (obj instanceof CodecProfileLevel) {
5072                 CodecProfileLevel other = (CodecProfileLevel)obj;
5073                 return other.profile == profile && other.level == level;
5074             }
5075             return false;
5076         }
5077 
5078         @Override
5079         public int hashCode() {
5080             return Long.hashCode(((long)profile << Integer.SIZE) | level);
5081         }
5082     };
5083 
5084     /**
5085      * Enumerates the capabilities of the codec component. Since a single
5086      * component can support data of a variety of types, the type has to be
5087      * specified to yield a meaningful result.
5088      * @param type The MIME type to query
5089      */
5090     public final CodecCapabilities getCapabilitiesForType(
5091             String type) {
5092         CodecCapabilities caps = mCaps.get(type);
5093         if (caps == null) {
5094             throw new IllegalArgumentException("codec does not support type");
5095         }
5096         // clone writable object
5097         return caps.dup();
5098     }
5099 
5100     /** @hide */
5101     public MediaCodecInfo makeRegular() {
5102         ArrayList<CodecCapabilities> caps = new ArrayList<CodecCapabilities>();
5103         for (CodecCapabilities c: mCaps.values()) {
5104             if (c.isRegular()) {
5105                 caps.add(c);
5106             }
5107         }
5108         if (caps.size() == 0) {
5109             return null;
5110         } else if (caps.size() == mCaps.size()) {
5111             return this;
5112         }
5113 
5114         return new MediaCodecInfo(
5115                 mName, mCanonicalName, mFlags,
5116                 caps.toArray(new CodecCapabilities[caps.size()]));
5117     }
5118 }
5119