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

Commit c318d881 authored by Hangyu Kuang's avatar Hangyu Kuang Committed by Android (Google) Code Review
Browse files

Merge "transcoding: Unhide ApplicationMediaCapabilities"

parents 88a27c68 10acecb2
Loading
Loading
Loading
Loading
+30 −0
Original line number Diff line number Diff line
@@ -24192,6 +24192,25 @@ package android.location {
package android.media {
  public final class ApplicationMediaCapabilities implements android.os.Parcelable {
    method public int describeContents();
    method @NonNull public java.util.List<java.lang.String> getSupportedHdrTypes();
    method @NonNull public java.util.List<java.lang.String> getSupportedVideoMimeTypes();
    method public boolean isHdrTypeSupported(@NonNull String);
    method public boolean isSlowMotionSupported();
    method public boolean isVideoMimeTypeSupported(@NonNull String);
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.media.ApplicationMediaCapabilities> CREATOR;
  }
  public static final class ApplicationMediaCapabilities.Builder {
    ctor public ApplicationMediaCapabilities.Builder();
    method @NonNull public android.media.ApplicationMediaCapabilities.Builder addSupportedHdrType(@NonNull String);
    method @NonNull public android.media.ApplicationMediaCapabilities.Builder addSupportedVideoMimeType(@NonNull String);
    method @NonNull public android.media.ApplicationMediaCapabilities build();
    method @NonNull public android.media.ApplicationMediaCapabilities.Builder setSlowMotionSupported(boolean);
  }
  public class AsyncPlayer {
    ctor public AsyncPlayer(String);
    method @Deprecated public void play(android.content.Context, android.net.Uri, boolean, int);
@@ -26313,6 +26332,17 @@ package android.media {
    field public static final String TRACKS = "android.media.mediaextractor.ntrk";
  }
  public final class MediaFeature {
    ctor public MediaFeature();
  }
  public static final class MediaFeature.HdrType {
    field public static final String DOLBY_VISION = "android.media.feature.hdr.dolby_vision";
    field public static final String HDR10 = "android.media.feature.hdr.hdr10";
    field public static final String HDR10_PLUS = "android.media.feature.hdr.hdr10_plus";
    field public static final String HLG = "android.media.feature.hdr.hlg";
  }
  public final class MediaFormat {
    ctor public MediaFormat();
    ctor public MediaFormat(@NonNull android.media.MediaFormat);
+30 −0
Original line number Diff line number Diff line
@@ -24174,6 +24174,25 @@ package android.location {
package android.media {
  public final class ApplicationMediaCapabilities implements android.os.Parcelable {
    method public int describeContents();
    method @NonNull public java.util.List<java.lang.String> getSupportedHdrTypes();
    method @NonNull public java.util.List<java.lang.String> getSupportedVideoMimeTypes();
    method public boolean isHdrTypeSupported(@NonNull String);
    method public boolean isSlowMotionSupported();
    method public boolean isVideoMimeTypeSupported(@NonNull String);
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.media.ApplicationMediaCapabilities> CREATOR;
  }
  public static final class ApplicationMediaCapabilities.Builder {
    ctor public ApplicationMediaCapabilities.Builder();
    method @NonNull public android.media.ApplicationMediaCapabilities.Builder addSupportedHdrType(@NonNull String);
    method @NonNull public android.media.ApplicationMediaCapabilities.Builder addSupportedVideoMimeType(@NonNull String);
    method @NonNull public android.media.ApplicationMediaCapabilities build();
    method @NonNull public android.media.ApplicationMediaCapabilities.Builder setSlowMotionSupported(boolean);
  }
  public class AsyncPlayer {
    ctor public AsyncPlayer(String);
    method @Deprecated public void play(android.content.Context, android.net.Uri, boolean, int);
@@ -26271,6 +26290,17 @@ package android.media {
    field public static final String TRACKS = "android.media.mediaextractor.ntrk";
  }
  public final class MediaFeature {
    ctor public MediaFeature();
  }
  public static final class MediaFeature.HdrType {
    field public static final String DOLBY_VISION = "android.media.feature.hdr.dolby_vision";
    field public static final String HDR10 = "android.media.feature.hdr.hdr10";
    field public static final String HDR10_PLUS = "android.media.feature.hdr.hdr10_plus";
    field public static final String HLG = "android.media.feature.hdr.hlg";
  }
  public final class MediaFormat {
    ctor public MediaFormat();
    ctor public MediaFormat(@NonNull android.media.MediaFormat);
+161 −41
Original line number Diff line number Diff line
@@ -23,11 +23,16 @@ import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * ApplicationMediaCapabilities is an immutable class that encapsulates an application's
 * capabilities of handling advanced media formats.
 * capabilities for handling newer video codec format and media features.
 *
 * The ApplicationMediaCapabilities class is used by the platform to to represent an application's
 * The ApplicationMediaCapabilities class is used by the platform to represent an application's
 * media capabilities as defined in their manifest(TODO: Add link) in order to determine
 * whether modern media files need to be transcoded for that application (TODO: Add link).
 *
@@ -37,43 +42,55 @@ import android.os.Parcelable;
 * provided by applications at runtime like this override the default manifest capabilities for that
 * media access.
 *
 * TODO(huang): Correct openTypedAssetFileDescriptor with the new API after it is added.
 * TODO(hkuang): Add a link to seamless transcoding detail when it is published
 * TODO(hkuang): Add code sample on how to build a capability object with MediaCodecList
 * <h3> Video Codec Support</h3>
 * Newer video codes include HEVC, VP9 and AV1. Application only needs to indicate their support
 * for newer format with this class as they are assumed to support older format like h.264.
 *
 * <h4>Capability of handling HDR(high dynamic range) video</h4>
 * There are four types of HDR video(Dolby-Vision, HDR10, HDR10+, HLG) supported by the platform,
 * application will only need to specify individual types they supported.
 *
 * @hide
 * <h4>Capability of handling Slow Motion video</h4>
 * There is no standard format for slow motion yet. If an application indicates support for slow
 * motion, it is application's responsibility to parse the slow motion videos using their own parser
 * or using support library.
 */
// TODO(huang): Correct openTypedAssetFileDescriptor with the new API after it is added.
// TODO(hkuang): Add a link to seamless transcoding detail when it is published
// TODO(hkuang): Add code sample on how to build a capability object with MediaCodecList
// TODO(hkuang): Add the support library page on parsing slow motion video.
public final class ApplicationMediaCapabilities implements Parcelable {
    private static final String TAG = "ApplicationMediaCapabilities";

    /** Whether handling of HEVC video is supported. */
    private final boolean mIsHevcSupported;
    /** List of supported video codec mime types. */
    // TODO: init it with avc and mpeg4 as application is assuming to support them.
    private Set<String> mSupportedVideoMimeTypes = new HashSet<>();

    /** Whether handling of slow-motion video is supported. */
    private final boolean mIsSlowMotionSupported;
    /** List of supported hdr types. */
    private Set<String> mSupportedHdrTypes = new HashSet<>();

    /** Whether handling of high dynamic range video is supported. */
    private final boolean mIsHdrSupported;
    private boolean mIsSlowMotionSupported = false;

    private ApplicationMediaCapabilities(Builder b) {
        mIsHevcSupported = b.mIsHevcSupported;
        mIsHdrSupported = b.mIsHdrSupported;
        mSupportedVideoMimeTypes.addAll(b.getSupportedVideoMimeTypes());
        mSupportedHdrTypes.addAll(b.getSupportedHdrTypes());
        mIsSlowMotionSupported = b.mIsSlowMotionSupported;
    }

    /** Whether handling of HEVC video is supported. */
    public boolean isHevcSupported() {
        return mIsHevcSupported;
    }

    /** Whether handling of slow-motion video is supported. */
    public boolean isSlowMotionSupported() {
        return mIsSlowMotionSupported;
    /**
     * Query if an video codec is supported by the application.
     */
    public boolean isVideoMimeTypeSupported(
            @NonNull String videoMime) {
        return mSupportedVideoMimeTypes.contains(videoMime);
    }

    /** Whether handling of high dynamic range video is supported. */
    public boolean isHdrSupported() {
        return mIsHdrSupported;
    /**
     * Query if a hdr type is supported by the application.
     */
    public boolean isHdrTypeSupported(
            @NonNull @MediaFeature.MediaHdrType String hdrType) {
        return mSupportedHdrTypes.contains(hdrType);
    }

    @Override
@@ -82,12 +99,86 @@ public final class ApplicationMediaCapabilities implements Parcelable {
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeBoolean(mIsHevcSupported);
        dest.writeBoolean(mIsHdrSupported);
    public void writeToParcel(@NonNull Parcel dest, int flags) {
        // Write out the supported video mime types.
        dest.writeInt(mSupportedVideoMimeTypes.size());
        for (String cap : mSupportedVideoMimeTypes) {
            dest.writeString(cap);
        }
        // Write out the supported hdr types.
        dest.writeInt(mSupportedHdrTypes.size());
        for (String cap : mSupportedHdrTypes) {
            dest.writeString(cap);
        }
        // Write out the supported slow motion.
        dest.writeBoolean(mIsSlowMotionSupported);
    }

    @Override
    public String toString() {
        String caps = new String(
                "Supported Video MimeTypes: " + mSupportedVideoMimeTypes.toString());
        caps += "Supported HDR types: " + mSupportedHdrTypes.toString();
        caps += "Supported slow motion: " + mIsSlowMotionSupported;
        return caps;
    }

    @NonNull
    public static final Creator<ApplicationMediaCapabilities> CREATOR =
            new Creator<ApplicationMediaCapabilities>() {
                public ApplicationMediaCapabilities createFromParcel(Parcel in) {
                    ApplicationMediaCapabilities.Builder builder =
                            new ApplicationMediaCapabilities.Builder();

                    // Parse supported video codec mime types.
                    int count = in.readInt();
                    for (int readCount = 0; readCount < count; ++readCount) {
                        builder.addSupportedVideoMimeType(in.readString());
                    }
                    // Parse supported hdr types.
                    count = in.readInt();
                    for (int readCount = 0; readCount < count; ++readCount) {
                        builder.addSupportedHdrType(in.readString());
                    }

                    boolean supported = in.readBoolean();
                    builder.setSlowMotionSupported(supported);

                    return builder.build();
                }

                public ApplicationMediaCapabilities[] newArray(int size) {
                    return new ApplicationMediaCapabilities[size];
                }
            };

    /*
     * Returns a list that contains all the video codec mime types supported by the application.
     * The list will be empty if no codecs are supported by the application.
     * @return List of supported video codec mime types.
     */
    @NonNull
    public List<String> getSupportedVideoMimeTypes() {
        return new ArrayList<>(mSupportedVideoMimeTypes);
    }

    /*
     * Returns a list that contains all hdr types supported by the application.
     * The list will be empty if no hdr types are supported by the application.
     * @return List of supported hdr types.
     */
    @NonNull
    public List<String> getSupportedHdrTypes() {
        return new ArrayList<>(mSupportedHdrTypes);
    }

    /*
     * Whether handling of slow-motion video is supported
     */
    public boolean isSlowMotionSupported() {
        return mIsSlowMotionSupported;
    }

    /**
     * Builder class for {@link ApplicationMediaCapabilities} objects.
     * Use this class to configure and create an ApplicationMediaCapabilities instance. Builder
@@ -96,8 +187,12 @@ public final class ApplicationMediaCapabilities implements Parcelable {
     * //TODO(hkuang): Add xml parsing support to the builder.
     */
    public final static class Builder {
        private boolean mIsHevcSupported = false;
        private boolean mIsHdrSupported = false;
        /** List of supported video codec mime types. */
        private Set<String> mSupportedVideoMimeTypes = new HashSet<>();

        /** List of supported hdr types. */
        private Set<String> mSupportedHdrTypes = new HashSet<>();

        private boolean mIsSlowMotionSupported = false;

        /**
@@ -112,37 +207,62 @@ public final class ApplicationMediaCapabilities implements Parcelable {
         * @return a new {@link ApplicationMediaCapabilities} instance successfully initialized
         * with all the parameters set on this <code>Builder</code>.
         * @throws UnsupportedOperationException if the parameters set on the
         *         <code>Builder</code> were incompatible, or if they are not supported by the
         *                                       <code>Builder</code> were incompatible, or if they
         *                                       are not supported by the
         *                                       device.
         */
        @NonNull
        public ApplicationMediaCapabilities build() {
            if (mIsHdrSupported && !mIsHevcSupported) {
                throw new UnsupportedOperationException("Must also support HEVC if support HDR.");
            // If hdr is supported, application must also support hevc.
            if (!mSupportedHdrTypes.isEmpty() && !mSupportedVideoMimeTypes.contains(
                    MediaFormat.MIMETYPE_VIDEO_HEVC)) {
                throw new UnsupportedOperationException("Only support HEVC mime type");
            }
            return new ApplicationMediaCapabilities(this);
        }

        /**
         * Sets whether supports HEVC encoded video.
         * Adds a supported video codec mime type.
         *
         * @param codecMime Supported codec mime types. Must be one of the mime type defined
         *                  in {@link MediaFormat}.
         * @throws UnsupportedOperationException if the codec mime type is not supported.
         * @throws IllegalArgumentException      if mime type is not valid.
         */
        @NonNull
        public Builder setHevcSupported(boolean hevcSupported) {
            mIsHevcSupported = hevcSupported;
        public Builder addSupportedVideoMimeType(
                @NonNull String codecMime) {
            mSupportedVideoMimeTypes.add(codecMime);
            return this;
        }

        private List<String> getSupportedVideoMimeTypes() {
            return new ArrayList<>(mSupportedVideoMimeTypes);
        }

        /**
         * Sets whether supports high dynamic range video.
         * Adds a supported hdr type.
         *
         * @param hdrType Supported hdr types. Must be one of the String defined in
         *                {@link MediaFeature.HdrType}.
         * @throws IllegalArgumentException if hdrType is not valid.
         */
        @NonNull
        public Builder setHdrSupported(boolean hdrSupported) {
            mIsHdrSupported = hdrSupported;
        public Builder addSupportedHdrType(
                @NonNull @MediaFeature.MediaHdrType String hdrType) {
            mSupportedHdrTypes.add(hdrType);
            return this;
        }

        private List<String> getSupportedHdrTypes() {
            return new ArrayList<>(mSupportedHdrTypes);
        }

        /**
         * Sets whether supports slow-motion video.
         * Sets whether slow-motion video is supported.
         * If an application indicates support for slow-motion, it is application's responsibility
         * to parse the slow-motion videos using their own parser or using support library.
         * @see android.media.MediaFormat#KEY_SLOW_MOTION_MARKERS
         */
        @NonNull
        public Builder setSlowMotionSupported(boolean slowMotionSupported) {
+63 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.media;

import android.annotation.StringDef;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * MediaFeature defines various media features, e.g. hdr type.
 */
public final class MediaFeature {
     /**
     * Defines tye type of HDR(high dynamic range) video.
     */
    public static final class HdrType {
        private HdrType() {
        }

        /**
         * HDR type for dolby-vision.
         */
        public static final String DOLBY_VISION = "android.media.feature.hdr.dolby_vision";
        /**
         * HDR type for hdr10.
         */
        public static final String HDR10 = "android.media.feature.hdr.hdr10";
        /**
         * HDR type for hdr10+.
         */
        public static final String HDR10_PLUS = "android.media.feature.hdr.hdr10_plus";
        /**
         * HDR type for hlg.
         */
        public static final String HLG = "android.media.feature.hdr.hlg";
    }

    /** @hide */
    @StringDef({
            HdrType.DOLBY_VISION,
            HdrType.HDR10,
            HdrType.HDR10_PLUS,
            HdrType.HLG,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface MediaHdrType {
    }
}
+19 −15
Original line number Diff line number Diff line
@@ -34,6 +34,8 @@ package com.android.mediatranscodingtest;
import static org.testng.Assert.assertThrows;

import android.media.ApplicationMediaCapabilities;
import android.media.MediaFeature;
import android.media.MediaFormat;
import android.test.ActivityInstrumentationTestCase2;

import org.junit.Test;
@@ -49,37 +51,39 @@ public class ApplicationMediaCapabilitiesTest extends
    @Test
    public void testSetSupportHevc() throws Exception {
        ApplicationMediaCapabilities capability =
                new ApplicationMediaCapabilities.Builder().setHevcSupported(true).build();
        assertTrue(capability.isHevcSupported());
                new ApplicationMediaCapabilities.Builder().addSupportedVideoMimeType(
                        MediaFormat.MIMETYPE_VIDEO_HEVC).build();
        assertTrue(capability.isVideoMimeTypeSupported(MediaFormat.MIMETYPE_VIDEO_HEVC));

        ApplicationMediaCapabilities capability2 =
                new ApplicationMediaCapabilities.Builder().setHevcSupported(false).build();
        assertFalse(capability2.isHevcSupported());
                new ApplicationMediaCapabilities.Builder().build();
        assertFalse(capability2.isVideoMimeTypeSupported(MediaFormat.MIMETYPE_VIDEO_HEVC));
    }

    @Test
    public void testSetSupportHdr() throws Exception {
        ApplicationMediaCapabilities capability =
                new ApplicationMediaCapabilities.Builder().setHdrSupported(true).setHevcSupported(
                        true).build();
        assertEquals(true, capability.isHdrSupported());
                new ApplicationMediaCapabilities.Builder().addSupportedHdrType(
                        MediaFeature.HdrType.HDR10_PLUS).addSupportedVideoMimeType(
                        MediaFormat.MIMETYPE_VIDEO_HEVC).build();
        assertEquals(true, capability.isHdrTypeSupported(MediaFeature.HdrType.HDR10_PLUS));
    }

    @Test
    public void testSetSupportSlowMotion() throws Exception {
        ApplicationMediaCapabilities capability =
                new ApplicationMediaCapabilities.Builder().setSlowMotionSupported(
                        true).build();
                new ApplicationMediaCapabilities.Builder().setSlowMotionSupported(true).build();
        assertTrue(capability.isSlowMotionSupported());
    }

    @Test
    public void testBuilder() throws Exception {
        ApplicationMediaCapabilities capability =
                new ApplicationMediaCapabilities.Builder().setHdrSupported(
                        true).setHevcSupported(true).setSlowMotionSupported(true).build();
        assertTrue(capability.isHdrSupported());
        assertTrue(capability.isSlowMotionSupported());
                new ApplicationMediaCapabilities.Builder().addSupportedVideoMimeType(
                        MediaFormat.MIMETYPE_VIDEO_HEVC).addSupportedHdrType(
                        MediaFeature.HdrType.HDR10_PLUS).setSlowMotionSupported(true).build();
        assertTrue(capability.isVideoMimeTypeSupported(MediaFormat.MIMETYPE_VIDEO_HEVC));
        assertTrue(capability.isHdrTypeSupported(MediaFeature.HdrType.HDR10_PLUS));
        assertTrue(capability.isSlowMotionSupported());
    }

@@ -87,8 +91,8 @@ public class ApplicationMediaCapabilitiesTest extends
    public void testSupportHdrWithoutSupportHevc() throws Exception {
        assertThrows(UnsupportedOperationException.class, () -> {
            ApplicationMediaCapabilities capability =
                    new ApplicationMediaCapabilities.Builder().setHdrSupported(
                            true).setHevcSupported(false).build();
                    new ApplicationMediaCapabilities.Builder().addSupportedHdrType(
                            MediaFeature.HdrType.HDR10_PLUS).build();
        });
    }
}