From 66d7d0d38b97fe608473c5e898dfb2dd0b2f7e9e Mon Sep 17 00:00:00 2001 From: hkuang Date: Thu, 14 Jan 2021 11:59:31 -0800 Subject: [PATCH] trasncoding: handle unspecified format correctly. ApplicationMediaCapabilities need to differentiate between unspecified format and unsupported format Change to throw NameNotFoundException for unspecified case. Bug: 176993974 Test: atest CtsMediaTranscodingTestCases:ApplicationMediaCapabilitiesTest Change-Id: I2cd3f921f7855f9891726568d0e36f59bbadc6e3 --- apex/media/framework/api/current.txt | 12 +- .../media/ApplicationMediaCapabilities.java | 197 ++++++++++++++++-- .../android/media/MediaTranscodeManager.java | 11 +- 3 files changed, 199 insertions(+), 21 deletions(-) diff --git a/apex/media/framework/api/current.txt b/apex/media/framework/api/current.txt index ce3bcbede4c79..103bb47fca23e 100644 --- a/apex/media/framework/api/current.txt +++ b/apex/media/framework/api/current.txt @@ -6,9 +6,11 @@ package android.media { 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 @NonNull public java.util.List getUnsupportedHdrTypes(); + method @NonNull public java.util.List getUnsupportedVideoMimeTypes(); + method public boolean isHdrTypeSupported(@NonNull String) throws android.media.ApplicationMediaCapabilities.FormatNotFoundException; method public boolean isSlowMotionSupported(); - method public boolean isVideoMimeTypeSupported(@NonNull String); + method public boolean isVideoMimeTypeSupported(@NonNull String) throws android.media.ApplicationMediaCapabilities.FormatNotFoundException; method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator CREATOR; } @@ -17,10 +19,16 @@ package android.media { 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.Builder addUnsupportedHdrType(@NonNull String); + method @NonNull public android.media.ApplicationMediaCapabilities.Builder addUnsupportedVideoMimeType(@NonNull String); method @NonNull public android.media.ApplicationMediaCapabilities build(); method @NonNull public android.media.ApplicationMediaCapabilities.Builder setSlowMotionSupported(boolean); } + public static class ApplicationMediaCapabilities.FormatNotFoundException extends android.util.AndroidException { + ctor public ApplicationMediaCapabilities.FormatNotFoundException(@NonNull String); + } + public class MediaController2 implements java.lang.AutoCloseable { method public void cancelSessionCommand(@NonNull Object); method public void close(); diff --git a/apex/media/framework/java/android/media/ApplicationMediaCapabilities.java b/apex/media/framework/java/android/media/ApplicationMediaCapabilities.java index 36f6b94b16ade..25ccec2930f1d 100644 --- a/apex/media/framework/java/android/media/ApplicationMediaCapabilities.java +++ b/apex/media/framework/java/android/media/ApplicationMediaCapabilities.java @@ -22,6 +22,7 @@ import android.net.Uri; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; +import android.util.AndroidException; import android.util.Log; import org.xmlpull.v1.XmlPullParser; @@ -68,35 +69,73 @@ import java.util.Set; public final class ApplicationMediaCapabilities implements Parcelable { private static final String TAG = "ApplicationMediaCapabilities"; + /** + * This exception is thrown when a given format is not specified in the media capabilities. + */ + public static class FormatNotFoundException extends AndroidException { + public FormatNotFoundException(@NonNull String format) { + super(format); + } + } + /** 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<>(); + /** List of unsupported video codec mime types. */ + private Set mUnsupportedVideoMimeTypes = new HashSet<>(); + /** List of supported hdr types. */ private Set mSupportedHdrTypes = new HashSet<>(); + /** List of unsupported hdr types. */ + private Set mUnsupportedHdrTypes = new HashSet<>(); + private boolean mIsSlowMotionSupported = false; private ApplicationMediaCapabilities(Builder b) { mSupportedVideoMimeTypes.addAll(b.getSupportedVideoMimeTypes()); + mUnsupportedVideoMimeTypes.addAll(b.getUnsupportedVideoMimeTypes()); mSupportedHdrTypes.addAll(b.getSupportedHdrTypes()); + mUnsupportedHdrTypes.addAll(b.getUnsupportedHdrTypes()); mIsSlowMotionSupported = b.mIsSlowMotionSupported; } /** - * Query if an video codec is supported by the application. + * Query if a video codec format is supported by the application. + * @param videoMime The mime type of the video codec format. Must be the one used in + * {@link MediaFormat#KEY_MIME}. + * @return true if application supports the video codec format, false otherwise. + * @throws FormatNotFoundException if the application did not specify the codec either in the + * supported or unsupported formats. */ public boolean isVideoMimeTypeSupported( - @NonNull String videoMime) { - return mSupportedVideoMimeTypes.contains(videoMime); + @NonNull String videoMime) throws FormatNotFoundException { + if (mUnsupportedVideoMimeTypes.contains(videoMime)) { + return false; + } else if (mSupportedVideoMimeTypes.contains(videoMime)) { + return true; + } else { + throw new FormatNotFoundException(videoMime); + } } /** - * Query if a hdr type is supported by the application. + * Query if a HDR type is supported by the application. + * @param hdrType The type of the HDR format. + * @return true if application supports the HDR format, false otherwise. + * @throws FormatNotFoundException if the application did not specify the format either in the + * supported or unsupported formats. */ public boolean isHdrTypeSupported( - @NonNull @MediaFeature.MediaHdrType String hdrType) { - return mSupportedHdrTypes.contains(hdrType); + @NonNull @MediaFeature.MediaHdrType String hdrType) throws FormatNotFoundException { + if (mUnsupportedHdrTypes.contains(hdrType)) { + return false; + } else if (mSupportedHdrTypes.contains(hdrType)) { + return true; + } else { + throw new FormatNotFoundException(hdrType); + } } @Override @@ -111,11 +150,21 @@ public final class ApplicationMediaCapabilities implements Parcelable { for (String cap : mSupportedVideoMimeTypes) { dest.writeString(cap); } + // Write out the unsupported video mime types. + dest.writeInt(mUnsupportedVideoMimeTypes.size()); + for (String cap : mUnsupportedVideoMimeTypes) { + dest.writeString(cap); + } // Write out the supported hdr types. dest.writeInt(mSupportedHdrTypes.size()); for (String cap : mSupportedHdrTypes) { dest.writeString(cap); } + // Write out the unsupported hdr types. + dest.writeInt(mUnsupportedHdrTypes.size()); + for (String cap : mUnsupportedHdrTypes) { + dest.writeString(cap); + } // Write out the supported slow motion. dest.writeBoolean(mIsSlowMotionSupported); } @@ -124,7 +173,9 @@ public final class ApplicationMediaCapabilities implements Parcelable { public String toString() { String caps = new String( "Supported Video MimeTypes: " + mSupportedVideoMimeTypes.toString()); + caps += "Unsupported Video MimeTypes: " + mUnsupportedVideoMimeTypes.toString(); caps += "Supported HDR types: " + mSupportedHdrTypes.toString(); + caps += "Unsupported HDR types: " + mUnsupportedHdrTypes.toString(); caps += "Supported slow motion: " + mIsSlowMotionSupported; return caps; } @@ -159,9 +210,8 @@ public final class ApplicationMediaCapabilities implements Parcelable { }; /* - * 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. + * Query the video codec mime types supported by the application. + * @return List of supported video codec mime types. The list will be empty if there are none. */ @NonNull public List getSupportedVideoMimeTypes() { @@ -169,15 +219,32 @@ public final class ApplicationMediaCapabilities implements Parcelable { } /* - * 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. + * Query the video codec mime types that are not supported by the application. + * @return List of unsupported video codec mime types. The list will be empty if there are none. + */ + @NonNull + public List getUnsupportedVideoMimeTypes() { + return new ArrayList<>(mSupportedVideoMimeTypes); + } + + /* + * Query all hdr types that are supported by the application. + * @return List of supported hdr types. The list will be empty if there are none. */ @NonNull public List getSupportedHdrTypes() { return new ArrayList<>(mSupportedHdrTypes); } + /* + * Query all hdr types that are not supported by the application. + * @return List of unsupported hdr types. The list will be empty if there are none. + */ + @NonNull + public List getUnsupportedHdrTypes() { + return new ArrayList<>(mUnsupportedHdrTypes); + } + /* * Whether handling of slow-motion video is supported */ @@ -213,6 +280,12 @@ public final class ApplicationMediaCapabilities implements Parcelable { /** List of supported hdr types. */ private Set mSupportedHdrTypes = new HashSet<>(); + /** List of unsupported video codec mime types. */ + private Set mUnsupportedVideoMimeTypes = new HashSet<>(); + + /** List of unsupported hdr types. */ + private Set mUnsupportedHdrTypes = new HashSet<>(); + private boolean mIsSlowMotionSupported = false; /* Map to save the format read from the xml. */ @@ -299,26 +372,50 @@ public final class ApplicationMediaCapabilities implements Parcelable { case "HEVC": if (isSupported) { mSupportedVideoMimeTypes.add(MediaFormat.MIMETYPE_VIDEO_HEVC); + } else { + mUnsupportedVideoMimeTypes.add(MediaFormat.MIMETYPE_VIDEO_HEVC); + } + break; + case "VP9": + if (isSupported) { + mSupportedVideoMimeTypes.add(MediaFormat.MIMETYPE_VIDEO_VP9); + } else { + mUnsupportedVideoMimeTypes.add(MediaFormat.MIMETYPE_VIDEO_VP9); + } + break; + case "AV1": + if (isSupported) { + mSupportedVideoMimeTypes.add(MediaFormat.MIMETYPE_VIDEO_AV1); + } else { + mUnsupportedVideoMimeTypes.add(MediaFormat.MIMETYPE_VIDEO_AV1); } break; case "HDR10": if (isSupported) { mSupportedHdrTypes.add(MediaFeature.HdrType.HDR10); + } else { + mUnsupportedHdrTypes.add(MediaFeature.HdrType.HDR10); } break; case "HDR10Plus": if (isSupported) { mSupportedHdrTypes.add(MediaFeature.HdrType.HDR10_PLUS); + } else { + mUnsupportedHdrTypes.add(MediaFeature.HdrType.HDR10_PLUS); } break; case "Dolby-Vision": if (isSupported) { mSupportedHdrTypes.add(MediaFeature.HdrType.DOLBY_VISION); + } else { + mUnsupportedHdrTypes.add(MediaFeature.HdrType.DOLBY_VISION); } break; case "HLG": if (isSupported) { mSupportedHdrTypes.add(MediaFeature.HdrType.HLG); + } else { + mUnsupportedHdrTypes.add(MediaFeature.HdrType.HLG); } break; case "SlowMotion": @@ -348,8 +445,11 @@ public final class ApplicationMediaCapabilities implements Parcelable { @NonNull public ApplicationMediaCapabilities build() { Log.d(TAG, - "Building ApplicationMediaCapabilities with: " + mSupportedHdrTypes.toString() - + " " + mSupportedVideoMimeTypes.toString() + " " + "Building ApplicationMediaCapabilities with: (Supported HDR: " + + mSupportedHdrTypes.toString() + " Unsupported HDR: " + + mUnsupportedHdrTypes.toString() + ") (Supported Codec: " + + " " + mSupportedVideoMimeTypes.toString() + " Unsupported Codec:" + + mUnsupportedVideoMimeTypes.toString() + ") " + mIsSlowMotionSupported); // If hdr is supported, application must also support hevc. @@ -365,8 +465,7 @@ public final class ApplicationMediaCapabilities implements Parcelable { * * @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. + * @throws IllegalArgumentException if mime type is not valid. */ @NonNull public Builder addSupportedVideoMimeType( @@ -379,16 +478,49 @@ public final class ApplicationMediaCapabilities implements Parcelable { return new ArrayList<>(mSupportedVideoMimeTypes); } + private boolean isValidVideoCodecMimeType(@NonNull String codecMime) { + if (!codecMime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_HEVC) + && !codecMime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP9) + && !codecMime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_AV1)) { + return false; + } + return true; + } + + /** + * Adds an unsupported video codec mime type. + * + * @param codecMime Unsupported codec mime type. Must be one of the mime type defined + * in {@link MediaFormat}. + * @throws IllegalArgumentException if mime type is not valid. + */ + @NonNull + public Builder addUnsupportedVideoMimeType( + @NonNull String codecMime) { + if (!isValidVideoCodecMimeType(codecMime)) { + throw new IllegalArgumentException("Invalid codec mime type: " + codecMime); + } + mUnsupportedVideoMimeTypes.add(codecMime); + return this; + } + + private List getUnsupportedVideoMimeTypes() { + return new ArrayList<>(mUnsupportedVideoMimeTypes); + } + /** * Adds a supported hdr type. * - * @param hdrType Supported hdr types. Must be one of the String defined in + * @param hdrType Supported hdr type. 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) { + if (!isValidVideoCodecHdrType(hdrType)) { + throw new IllegalArgumentException("Invalid hdr type: " + hdrType); + } mSupportedHdrTypes.add(hdrType); return this; } @@ -397,6 +529,37 @@ public final class ApplicationMediaCapabilities implements Parcelable { return new ArrayList<>(mSupportedHdrTypes); } + private boolean isValidVideoCodecHdrType(@NonNull String hdrType) { + if (!hdrType.equals(MediaFeature.HdrType.DOLBY_VISION) + && !hdrType.equals(MediaFeature.HdrType.HDR10) + && !hdrType.equals(MediaFeature.HdrType.HDR10_PLUS) + && !hdrType.equals(MediaFeature.HdrType.HLG)) { + return false; + } + return true; + } + + /** + * Adds an unsupported hdr type. + * + * @param hdrType Unsupported hdr type. Must be one of the String defined in + * {@link MediaFeature.HdrType}. + * @throws IllegalArgumentException if hdrType is not valid. + */ + @NonNull + public Builder addUnsupportedHdrType( + @NonNull @MediaFeature.MediaHdrType String hdrType) { + if (!isValidVideoCodecHdrType(hdrType)) { + throw new IllegalArgumentException("Invalid hdr type: " + hdrType); + } + mUnsupportedHdrTypes.add(hdrType); + return this; + } + + private List getUnsupportedHdrTypes() { + return new ArrayList<>(mUnsupportedHdrTypes); + } + /** * Sets whether slow-motion video is supported. * If an application indicates support for slow-motion, it is application's responsibility diff --git a/apex/media/framework/java/android/media/MediaTranscodeManager.java b/apex/media/framework/java/android/media/MediaTranscodeManager.java index 3d706e40bc0b2..5d212b8e4745a 100644 --- a/apex/media/framework/java/android/media/MediaTranscodeManager.java +++ b/apex/media/framework/java/android/media/MediaTranscodeManager.java @@ -980,8 +980,15 @@ public final class MediaTranscodeManager { throw new UnsupportedOperationException( "Source video format hint must be set!"); } - boolean supportHevc = mClientCaps.isVideoMimeTypeSupported( - MediaFormat.MIMETYPE_VIDEO_HEVC); + + boolean supportHevc = false; + try { + supportHevc = mClientCaps.isVideoMimeTypeSupported( + MediaFormat.MIMETYPE_VIDEO_HEVC); + } catch (ApplicationMediaCapabilities.FormatNotFoundException ex) { + // Set to false if application did not specify. + supportHevc = false; + } if (!supportHevc && MediaFormat.MIMETYPE_VIDEO_HEVC.equals( mSrcVideoFormatHint.getString(MediaFormat.KEY_MIME))) { return true;