diff --git a/api/current.txt b/api/current.txt index 344e93baedf03..6c8141031357d 100644 --- a/api/current.txt +++ b/api/current.txt @@ -24184,6 +24184,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 getSupportedHdrTypes(); + method @NonNull public java.util.List 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 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); @@ -26303,6 +26322,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); diff --git a/core/api/current.txt b/core/api/current.txt index 9562715b8cfff..e58e2ef8adbdb 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -24166,6 +24166,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 getSupportedHdrTypes(); + method @NonNull public java.util.List 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 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); @@ -26261,6 +26280,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); diff --git a/media/java/android/media/ApplicationMediaCapabilities.java b/media/java/android/media/ApplicationMediaCapabilities.java index 4b28553cce90d..792e85f5d8396 100644 --- a/media/java/android/media/ApplicationMediaCapabilities.java +++ b/media/java/android/media/ApplicationMediaCapabilities.java @@ -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 + *

Video Codec Support

+ * 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. * - * @hide + *

Capability of handling HDR(high dynamic range) video

+ * 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. + * + *

Capability of handling Slow Motion video

+ * 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 mSupportedVideoMimeTypes = new HashSet<>(); - /** Whether handling of slow-motion video is supported. */ - private final boolean mIsSlowMotionSupported; + /** List of supported hdr types. */ + private Set 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; + /** + * Query if an video codec is supported by the application. + */ + public boolean isVideoMimeTypeSupported( + @NonNull String videoMime) { + return mSupportedVideoMimeTypes.contains(videoMime); } - /** Whether handling of slow-motion video is supported. */ - public boolean isSlowMotionSupported() { - return mIsSlowMotionSupported; - } - - /** 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 CREATOR = + new Creator() { + 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 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 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 mSupportedVideoMimeTypes = new HashSet<>(); + + /** List of supported hdr types. */ + private Set 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 Builder. * @throws UnsupportedOperationException if the parameters set on the - * Builder were incompatible, or if they are not supported by the - * device. + * Builder 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; } - /** - * Sets whether supports high dynamic range video. - */ - @NonNull - public Builder setHdrSupported(boolean hdrSupported) { - mIsHdrSupported = hdrSupported; - return this; + private List getSupportedVideoMimeTypes() { + return new ArrayList<>(mSupportedVideoMimeTypes); } /** - * Sets whether supports slow-motion 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 addSupportedHdrType( + @NonNull @MediaFeature.MediaHdrType String hdrType) { + mSupportedHdrTypes.add(hdrType); + return this; + } + + private List getSupportedHdrTypes() { + return new ArrayList<>(mSupportedHdrTypes); + } + + /** + * 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) { diff --git a/media/java/android/media/MediaFeature.java b/media/java/android/media/MediaFeature.java new file mode 100644 index 0000000000000..0e461888a0e30 --- /dev/null +++ b/media/java/android/media/MediaFeature.java @@ -0,0 +1,63 @@ +/* + * 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 { + } +} diff --git a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/ApplicationMediaCapabilitiesTest.java b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/ApplicationMediaCapabilitiesTest.java index 8a668c670d1ef..3f3f49ae23181 100644 --- a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/ApplicationMediaCapabilitiesTest.java +++ b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/ApplicationMediaCapabilitiesTest.java @@ -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(); }); } }