Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b58dc313 authored by Lajos Molnar's avatar Lajos Molnar
Browse files

Extend MediaCodecInfo to describe usable codec limits and features

Bug: 11990470
Bug: 12065651
Bug: 16131974
Change-Id: I841b8507e823f1ddf14754e34029a9bed4f402d8
parent 71396450
Loading
Loading
Loading
Loading
+80 −0
Original line number Diff line number Diff line
@@ -14624,7 +14624,15 @@ package android.media {
  public static final class MediaCodecInfo.CodecCapabilities {
    ctor public MediaCodecInfo.CodecCapabilities();
    method public static final android.media.MediaCodecInfo.CodecCapabilities CreateFromProfileLevel(java.lang.String, int, int);
    method public final android.media.MediaCodecInfo.CodecCapabilities.AudioCapabilities getAudioCapabilities();
    method public final android.media.MediaFormat getDefaultFormat();
    method public final android.media.MediaCodecInfo.CodecCapabilities.EncoderCapabilities getEncoderCapabilities();
    method public final java.lang.String getMime();
    method public final android.media.MediaCodecInfo.CodecCapabilities.VideoCapabilities getVideoCapabilities();
    method public final boolean isFeatureRequired(java.lang.String);
    method public final boolean isFeatureSupported(java.lang.String);
    method public final boolean isFormatSupported(android.media.MediaFormat);
    field public static final int COLOR_Format12bitRGB444 = 3; // 0x3
    field public static final int COLOR_Format16bitARGB1555 = 5; // 0x5
    field public static final int COLOR_Format16bitARGB4444 = 4; // 0x4
@@ -14660,6 +14668,7 @@ package android.media {
    field public static final int COLOR_FormatYCrYCb = 26; // 0x1a
    field public static final int COLOR_FormatYUV411PackedPlanar = 18; // 0x12
    field public static final int COLOR_FormatYUV411Planar = 17; // 0x11
    field public static final int COLOR_FormatYUV420Flexible = 2135033992; // 0x7f420888
    field public static final int COLOR_FormatYUV420PackedPlanar = 20; // 0x14
    field public static final int COLOR_FormatYUV420PackedSemiPlanar = 39; // 0x27
    field public static final int COLOR_FormatYUV420Planar = 19; // 0x13
@@ -14672,10 +14681,45 @@ package android.media {
    field public static final int COLOR_QCOM_FormatYUV420SemiPlanar = 2141391872; // 0x7fa30c00
    field public static final int COLOR_TI_FormatYUV420PackedSemiPlanar = 2130706688; // 0x7f000100
    field public static final java.lang.String FEATURE_AdaptivePlayback = "adaptive-playback";
    field public static final java.lang.String FEATURE_SecurePlayback = "secure-playback";
    field public static final java.lang.String FEATURE_TunneledPlayback = "tunneled-playback";
    field public int[] colorFormats;
    field public android.media.MediaCodecInfo.CodecProfileLevel[] profileLevels;
  }
  public static final class MediaCodecInfo.CodecCapabilities.AudioCapabilities extends android.media.MediaCodecInfo.CodecCapabilities.BaseCapabilities {
    method public final int getMaxInputChannelCount();
    method public final android.util.Range<java.lang.Integer>[] getSupportedSampleRateRanges();
    method public final int[] getSupportedSampleRates();
    method public final boolean isSampleRateSupported(int);
  }
  public static class MediaCodecInfo.CodecCapabilities.BaseCapabilities {
    method public final android.util.Range<java.lang.Integer> getBitrateRange();
  }
  public static final class MediaCodecInfo.CodecCapabilities.EncoderCapabilities {
    method public final android.util.Range<java.lang.Integer> getComplexityRange();
    method public final android.util.Range<java.lang.Integer> getQualityRange();
    method public final boolean isBitrateModeSupported(int);
    field public static final int BITRATE_MODE_CBR = 2; // 0x2
    field public static final int BITRATE_MODE_CQ = 0; // 0x0
    field public static final int BITRATE_MODE_VBR = 1; // 0x1
  }
  public static final class MediaCodecInfo.CodecCapabilities.VideoCapabilities extends android.media.MediaCodecInfo.CodecCapabilities.BaseCapabilities {
    method public final boolean areSizeAndRateSupported(int, int, double);
    method public final int getHeightAlignment();
    method public final android.util.Range<java.lang.Integer> getSupportedFrameRates();
    method public final android.util.Range<java.lang.Double> getSupportedFrameRatesFor(int, int);
    method public final android.util.Range<java.lang.Integer> getSupportedHeights();
    method public final android.util.Range<java.lang.Integer> getSupportedHeightsFor(int);
    method public final android.util.Range<java.lang.Integer> getSupportedWidths();
    method public final android.util.Range<java.lang.Integer> getSupportedWidthsFor(int);
    method public final int getWidthAlignment();
    method public final boolean isSizeSupported(int, int);
  }
  public static final class MediaCodecInfo.CodecProfileLevel {
    ctor public MediaCodecInfo.CodecProfileLevel();
    field public static final int AACObjectELD = 39; // 0x27
@@ -14704,6 +14748,7 @@ package android.media {
    field public static final int AVCLevel42 = 8192; // 0x2000
    field public static final int AVCLevel5 = 16384; // 0x4000
    field public static final int AVCLevel51 = 32768; // 0x8000
    field public static final int AVCLevel52 = 65536; // 0x10000
    field public static final int AVCProfileBaseline = 1; // 0x1
    field public static final int AVCProfileExtended = 4; // 0x4
    field public static final int AVCProfileHigh = 8; // 0x8
@@ -14790,8 +14835,14 @@ package android.media {
  }
  public final class MediaCodecList {
    ctor public MediaCodecList(int);
    method public final java.lang.String findDecoderForFormat(android.media.MediaFormat);
    method public final java.lang.String findEncoderForFormat(android.media.MediaFormat);
    method public static final int getCodecCount();
    method public static final android.media.MediaCodecInfo getCodecInfoAt(int);
    method public final android.media.MediaCodecInfo[] getCodecInfos();
    field public static final int ALL_CODECS = 1; // 0x1
    field public static final int REGULAR_CODECS = 0; // 0x0
  }
  public final class MediaCrypto {
@@ -14917,11 +14968,14 @@ package android.media {
    method public final void setLong(java.lang.String, long);
    method public final void setString(java.lang.String, java.lang.String);
    field public static final java.lang.String KEY_AAC_PROFILE = "aac-profile";
    field public static final java.lang.String KEY_BITRATE_MODE = "bitrate-mode";
    field public static final java.lang.String KEY_BIT_RATE = "bitrate";
    field public static final java.lang.String KEY_CHANNEL_COUNT = "channel-count";
    field public static final java.lang.String KEY_CHANNEL_MASK = "channel-mask";
    field public static final java.lang.String KEY_COLOR_FORMAT = "color-format";
    field public static final java.lang.String KEY_COMPLEXITY = "complexity";
    field public static final java.lang.String KEY_DURATION = "durationUs";
    field public static final java.lang.String KEY_FEATURE_ = "feature-";
    field public static final java.lang.String KEY_FLAC_COMPRESSION_LEVEL = "flac-compression-level";
    field public static final java.lang.String KEY_FRAME_RATE = "frame-rate";
    field public static final java.lang.String KEY_HEIGHT = "height";
@@ -14935,10 +14989,36 @@ package android.media {
    field public static final java.lang.String KEY_MAX_INPUT_SIZE = "max-input-size";
    field public static final java.lang.String KEY_MAX_WIDTH = "max-width";
    field public static final java.lang.String KEY_MIME = "mime";
    field public static final java.lang.String KEY_PROFILE = "profile";
    field public static final java.lang.String KEY_PUSH_BLANK_BUFFERS_ON_STOP = "push-blank-buffers-on-shutdown";
    field public static final java.lang.String KEY_QUALITY = "quality";
    field public static final java.lang.String KEY_REFERENCE_CLOCK_ID = "reference-clock-id";
    field public static final java.lang.String KEY_REPEAT_PREVIOUS_FRAME_AFTER = "repeat-previous-frame-after";
    field public static final java.lang.String KEY_SAMPLE_RATE = "sample-rate";
    field public static final java.lang.String KEY_WIDTH = "width";
    field public static final java.lang.String MIMETYPE_AUDIO_AAC = "audio/mp4a-latm";
    field public static final java.lang.String MIMETYPE_AUDIO_AC3 = "audio/ac3";
    field public static final java.lang.String MIMETYPE_AUDIO_AMR_NB = "audio/3gpp";
    field public static final java.lang.String MIMETYPE_AUDIO_AMR_WB = "audio/amr-wb";
    field public static final java.lang.String MIMETYPE_AUDIO_FLAC = "audio/flac";
    field public static final java.lang.String MIMETYPE_AUDIO_G711_ALAW = "audio/g711-alaw";
    field public static final java.lang.String MIMETYPE_AUDIO_G711_MLAW = "audio/g711-mlaw";
    field public static final java.lang.String MIMETYPE_AUDIO_MPEG = "audio/mpeg";
    field public static final java.lang.String MIMETYPE_AUDIO_MSGSM = "audio/gsm";
    field public static final java.lang.String MIMETYPE_AUDIO_OPUS = "audio/opus";
    field public static final java.lang.String MIMETYPE_AUDIO_QCELP = "audio/qcelp";
    field public static final java.lang.String MIMETYPE_AUDIO_RAW = "audio/raw";
    field public static final java.lang.String MIMETYPE_AUDIO_VORBIS = "audio/vorbis";
    field public static final java.lang.String MIMETYPE_TEXT_CEA_608 = "text/cea-608";
    field public static final java.lang.String MIMETYPE_TEXT_VTT = "text/vtt";
    field public static final java.lang.String MIMETYPE_VIDEO_AVC = "video/avc";
    field public static final java.lang.String MIMETYPE_VIDEO_H263 = "video/3gpp";
    field public static final java.lang.String MIMETYPE_VIDEO_HEVC = "video/hevc";
    field public static final java.lang.String MIMETYPE_VIDEO_MPEG2 = "video/mpeg2";
    field public static final java.lang.String MIMETYPE_VIDEO_MPEG4 = "video/mp4v-es";
    field public static final java.lang.String MIMETYPE_VIDEO_RAW = "video/raw";
    field public static final java.lang.String MIMETYPE_VIDEO_VP8 = "video/x-vnd.on2.vp8";
    field public static final java.lang.String MIMETYPE_VIDEO_VP9 = "video/x-vnd.on2.vp9";
  }
  public final class MediaMetadata implements android.os.Parcelable {
+1808 −61

File changed.

Preview size limit exceeded, changes collapsed.

+153 −5
Original line number Diff line number Diff line
@@ -16,7 +16,13 @@

package android.media;

import android.util.Log;

import android.media.MediaCodecInfo;
import android.media.MediaCodecInfo.CodecCapabilities;

import java.util.ArrayList;
import java.util.Arrays;

/**
 * Allows you to enumerate available codecs, each specified as a {@link MediaCodecInfo} object,
@@ -25,17 +31,74 @@ import android.media.MediaCodecInfo;
 * <p>See {@link MediaCodecInfo} for sample usage.
 */
final public class MediaCodecList {
    private static final String TAG = "MediaCodecList";

    /**
     * Count the number of available codecs.
     * Count the number of available (regular) codecs.
     *
     * @see #REGULAR_CODECS
     */
    public static native final int getCodecCount();
    public static final int getCodecCount() {
        initCodecList();
        return sRegularCodecInfos.length;
    }

    private static native final int native_getCodecCount();

    /**
     * Return the {@link MediaCodecInfo} object for the codec at
     * the given {@code index} in the regular list.
     *
     * @see #REGULAR_CODECS
     */
    public static final MediaCodecInfo getCodecInfoAt(int index) {
        if (index < 0 || index > getCodecCount()) {
        initCodecList();
        if (index < 0 || index > sRegularCodecInfos.length) {
            throw new IllegalArgumentException();
        }
        return sRegularCodecInfos[index];
    }

    private static Object sInitLock = new Object();
    private static MediaCodecInfo[] sAllCodecInfos;
    private static MediaCodecInfo[] sRegularCodecInfos;

        return new MediaCodecInfo(index);
    private static final void initCodecList() {
        synchronized (sInitLock) {
            if (sRegularCodecInfos == null) {
                int count = native_getCodecCount();
                ArrayList<MediaCodecInfo> regulars = new ArrayList<MediaCodecInfo>();
                ArrayList<MediaCodecInfo> all = new ArrayList<MediaCodecInfo>();
                for (int index = 0; index < count; index++) {
                    try {
                        MediaCodecInfo info = getNewCodecInfoAt(index);
                        all.add(info);
                        info = info.makeRegular();
                        if (info != null) {
                            regulars.add(info);
                        }
                    } catch (Exception e) {
                        Log.e(TAG, "Could not get codec capabilities", e);
                    }
                }
                sRegularCodecInfos =
                    regulars.toArray(new MediaCodecInfo[regulars.size()]);
                sAllCodecInfos =
                    all.toArray(new MediaCodecInfo[all.size()]);
            }
        }
    }

    private static MediaCodecInfo getNewCodecInfoAt(int index) {
        String[] supportedTypes = getSupportedTypes(index);
        MediaCodecInfo.CodecCapabilities[] caps =
            new MediaCodecInfo.CodecCapabilities[supportedTypes.length];
        int typeIx = 0;
        for (String type: supportedTypes) {
            caps[typeIx] = getCodecCapabilities(index, type);
        }
        return new MediaCodecInfo(
                getCodecName(index), isEncoder(index), caps);
    }

    /* package private */ static native final String getCodecName(int index);
@@ -51,10 +114,95 @@ final public class MediaCodecList {

    private static native final void native_init();

    private MediaCodecList() {}
    /**
     * Use in {@link #MediaCodecList} to enumerate only codecs that are suitable
     * for normal playback and recording.
     */
    public static final int REGULAR_CODECS = 0;

    /**
     * Use in {@link #MediaCodecList} to enumerate all codecs, even ones that are
     * not suitable for normal playback or recording.
     */
    public static final int ALL_CODECS = 1;

    private MediaCodecList() {
        this(REGULAR_CODECS);
    }

    private MediaCodecInfo[] mCodecInfos;

    /**
     * Create a list of media-codecs of a specific kind.
     * @param kind Either {@code REGULAR_CODECS} or {@code ALL_CODECS}.
     */
    public MediaCodecList(int kind) {
        initCodecList();
        if (kind == REGULAR_CODECS) {
            mCodecInfos = sRegularCodecInfos;
        } else {
            mCodecInfos = sAllCodecInfos;
        }
    }

    /**
     * Returns the list of {@link MediaCodecInfo} objects for the list
     * of media-codecs.
     */
    public final MediaCodecInfo[] getCodecInfos() {
        return Arrays.copyOf(mCodecInfos, mCodecInfos.length);
    }

    static {
        System.loadLibrary("media_jni");
        native_init();

        // mediaserver is not yet alive here
    }

    /**
     * Find a decoder supporting a given {@link MediaFormat} in the list
     * of media-codecs.
     *
     * @param format A decoder media format with optional feature directives.
     * @throws IllegalArgumentException if format is not a valid media format.
     * @throws NullPointerException if format is null.
     * @return the name of a decoder that supports the given format and feature
     *         requests, or {@code null} if no such codec has been found.
     */
    public final String findDecoderForFormat(MediaFormat format) {
        return findCodecForFormat(false /* encoder */, format);
    }

    /**
     * Find an encoder supporting a given {@link MediaFormat} in the list
     * of media-codecs.
     *
     * @param format An encoder media format with optional feature directives.
     * @throws IllegalArgumentException if format is not a valid media format.
     * @throws NullPointerException if format is null.
     * @return the name of an encoder that supports the given format and feature
     *         requests, or {@code null} if no such codec has been found.
     */
    public final String findEncoderForFormat(MediaFormat format) {
        return findCodecForFormat(false /* encoder */, format);
    }

    private String findCodecForFormat(boolean encoder, MediaFormat format) {
        String mime = format.getString(MediaFormat.KEY_MIME);
        for (MediaCodecInfo info: mCodecInfos) {
            if (info.isEncoder() != encoder) {
                continue;
            }
            try {
                MediaCodecInfo.CodecCapabilities caps = info.getCapabilitiesForType(mime);
                if (caps != null && caps.isFormatSupported(format)) {
                    return info.getName();
                }
            } catch (IllegalArgumentException e) {
                // type is not supported
            }
        }
        return null;
    }
}
+91 −0
Original line number Diff line number Diff line
@@ -76,8 +76,54 @@ import java.util.Map;
 * </table>
 */
public final class MediaFormat {
    public static final String MIMETYPE_VIDEO_VP8 = "video/x-vnd.on2.vp8";
    public static final String MIMETYPE_VIDEO_VP9 = "video/x-vnd.on2.vp9";
    public static final String MIMETYPE_VIDEO_AVC = "video/avc";
    public static final String MIMETYPE_VIDEO_HEVC = "video/hevc";
    public static final String MIMETYPE_VIDEO_MPEG4 = "video/mp4v-es";
    public static final String MIMETYPE_VIDEO_H263 = "video/3gpp";
    public static final String MIMETYPE_VIDEO_MPEG2 = "video/mpeg2";
    public static final String MIMETYPE_VIDEO_RAW = "video/raw";

    public static final String MIMETYPE_AUDIO_AMR_NB = "audio/3gpp";
    public static final String MIMETYPE_AUDIO_AMR_WB = "audio/amr-wb";
    public static final String MIMETYPE_AUDIO_MPEG = "audio/mpeg";
    public static final String MIMETYPE_AUDIO_AAC = "audio/mp4a-latm";
    public static final String MIMETYPE_AUDIO_QCELP = "audio/qcelp";
    public static final String MIMETYPE_AUDIO_VORBIS = "audio/vorbis";
    public static final String MIMETYPE_AUDIO_OPUS = "audio/opus";
    public static final String MIMETYPE_AUDIO_G711_ALAW = "audio/g711-alaw";
    public static final String MIMETYPE_AUDIO_G711_MLAW = "audio/g711-mlaw";
    public static final String MIMETYPE_AUDIO_RAW = "audio/raw";
    public static final String MIMETYPE_AUDIO_FLAC = "audio/flac";
    public static final String MIMETYPE_AUDIO_MSGSM = "audio/gsm";
    public static final String MIMETYPE_AUDIO_AC3 = "audio/ac3";

    /**
     * MIME type for WebVTT subtitle data.
     */
    public static final String MIMETYPE_TEXT_VTT = "text/vtt";

    /**
     * MIME type for CEA-608 closed caption data.
     */
    public static final String MIMETYPE_TEXT_CEA_608 = "text/cea-608";

    private Map<String, Object> mMap;

    /**
     * A key prefix used together with a {@link MediaCodecInfo.CodecCapabilities}
     * feature name describing a required or optional feature for a codec capabilities
     * query.
     * The associated value is an integer, where non-0 value means the feature is
     * requested to be present, while 0 value means the feature is requested to be not
     * present.
     * @see MediaCodecList#findDecoderForFormat
     * @see MediaCodecList#findEncoderForFormat
     * @see MediaCodecInfo.CodecCapabilities#isFormatSupported
     */
    public static final String KEY_FEATURE_ = "feature-";

    /**
     * A key describing the mime type of the MediaFormat.
     * The associated value is a string.
@@ -221,6 +267,51 @@ public final class MediaFormat {
     */
    public static final String KEY_FLAC_COMPRESSION_LEVEL = "flac-compression-level";

    /**
     * A key describing the encoding complexity.
     * The associated value is an integer.  These values are device and codec specific,
     * but lower values generally result in faster and/or less power-hungry encoding.
     *
     * @see MediaCodecInfo.CodecCapabilities.EncoderCapabilities#getComplexityRange
     */
    public static final String KEY_COMPLEXITY = "complexity";

    /**
     * A key describing the desired encoding quality.
     * The associated value is an integer.  This key is only supported for encoders
     * that are configured in constant-quality mode.  These values are device and
     * codec specific, but lower values generally result in more efficient
     * (smaller-sized) encoding.
     *
     * @see MediaCodecInfo.CodecCapabilities.EncoderCapabilities#getQualityRange
     */
    public static final String KEY_QUALITY = "quality";

    /**
     * A key describing the desired profile to be used by an encoder.
     * Constants are declared in {@link MediaCodecInfo.CodecProfileLevel}.
     * This key is only supported for codecs that specify a profile.
     *
     * @see MediaCodecInfo.CodecCapabilities#profileLevels
     */
    public static final String KEY_PROFILE = "profile";

    /**
     * A key describing the desired bitrate mode to be used by an encoder.
     * Constants are declared in {@link MediaCodecInfo.CodecCapabilities}.
     *
     * @see MediaCodecInfo.CodecCapabilities.EncoderCapabilities#isBitrateModeSupported
     */
    public static final String KEY_BITRATE_MODE = "bitrate-mode";

    /**
     * A key describing the reference clock ID for a tunneled codec.
     * The associated value is an integer.
     *
     * @see MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback
     */
    public static final String KEY_REFERENCE_CLOCK_ID = "reference-clock-id";

    /**
     * A key for boolean AUTOSELECT behavior for the track. Tracks with AUTOSELECT=true
     * are considered when automatically selecting a track without specific user
+296 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading