/* * 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.NonNull; import android.content.ContentResolver; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; import android.util.Log; import com.android.modules.annotation.MinSdk; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; /** ApplicationMediaCapabilities is an immutable class that encapsulates an application's capabilities for handling newer video codec format and media features.
Android 12 introduces Compatible media transcoding feature. See Compatible media transcoding. By default, Android assumes apps can support playback of all media formats. Apps that would like to request that media be transcoded into a more compatible format should declare their media capabilities in a media_capabilities.xml resource file and add it as a property tag in the AndroidManifest.xml file. Here is a example:
{@codeThe ApplicationMediaCapabilities class is generated from this xml and used by the platform to represent an application's media capabilities in order to determine whether modern media files need to be transcoded for that application.}
ApplicationMediaCapabilities objects can also be built by applications at runtime for use with {@link ContentResolver#openTypedAssetFileDescriptor(Uri, String, Bundle)} to provide more control over the transcoding that is built into the platform. ApplicationMediaCapabilities provided by applications at runtime like this override the default manifest capabilities for that media access.The object could be build either through {@link #createFromXml(XmlPullParser)} or through the builder class {@link ApplicationMediaCapabilities.Builder}
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.
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.
*/
@MinSdk(Build.VERSION_CODES.S)
public final class ApplicationMediaCapabilities implements Parcelable {
private static final String TAG = "ApplicationMediaCapabilities";
/** List of supported video codec mime types. */
private Set
* If the application has not specified supporting the format or not, this will return false.
* Use {@link #isFormatSpecified(String)} to query if a format is specified or not.
*
* @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.
*/
public boolean isVideoMimeTypeSupported(
@NonNull String videoMime) {
if (mSupportedVideoMimeTypes.contains(videoMime.toLowerCase())) {
return true;
}
return false;
}
/**
* Query if a HDR type is supported by the application.
*
* If the application has not specified supporting the format or not, this will return false.
* Use {@link #isFormatSpecified(String)} to query if a format is specified or not.
*
* @param hdrType The type of the HDR format.
* @return true if application supports the HDR format, false otherwise.
*/
public boolean isHdrTypeSupported(
@NonNull @MediaFeature.MediaHdrType String hdrType) {
if (mSupportedHdrTypes.contains(hdrType)) {
return true;
}
return false;
}
/**
* Query if a format is specified by the application.
*
* The format could be either the video format or the hdr format.
*
* @param format The name of the format.
* @return true if application specifies the format, false otherwise.
*/
public boolean isFormatSpecified(@NonNull String format) {
if (mSupportedVideoMimeTypes.contains(format) || mUnsupportedVideoMimeTypes.contains(format)
|| mSupportedHdrTypes.contains(format) || mUnsupportedHdrTypes.contains(format)) {
return true;
}
return false;
}
@Override
public int describeContents() {
return 0;
}
@Override
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 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);
}
@Override
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;
}
@NonNull
public static final Creator Here is an example:
*
*
*
* @param xmlParser The underlying {@link XmlPullParser} that will read the xml.
* @return An ApplicationMediaCapabilities object.
* @throws UnsupportedOperationException if the capabilities in xml config are invalid or
* incompatible.
*/
// TODO: Add developer.android.com link for the format of the xml.
@NonNull
public static ApplicationMediaCapabilities createFromXml(@NonNull XmlPullParser xmlParser) {
ApplicationMediaCapabilities.Builder builder = new ApplicationMediaCapabilities.Builder();
builder.parseXml(xmlParser);
return builder.build();
}
/**
* Builder class for {@link ApplicationMediaCapabilities} objects.
* Use this class to configure and create an ApplicationMediaCapabilities instance. Builder
* could be created from an existing ApplicationMediaCapabilities object, from a xml file or
* MediaCodecList.
* //TODO(hkuang): Add xml parsing support to the builder.
*/
public final static class Builder {
/** List of supported video codec mime types. */
private Set
* {@code
*
* Builder
.
* @throws UnsupportedOperationException if the parameters set on the
* Builder
were incompatible, or if they
* are not supported by the
* device.
*/
@NonNull
public ApplicationMediaCapabilities build() {
Log.d(TAG,
"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.
if (!mSupportedHdrTypes.isEmpty() && !mSupportedVideoMimeTypes.contains(
MediaFormat.MIMETYPE_VIDEO_HEVC)) {
throw new UnsupportedOperationException("Only support HEVC mime type");
}
return new ApplicationMediaCapabilities(this);
}
/**
* 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 IllegalArgumentException if mime type is not valid.
*/
@NonNull
public Builder addSupportedVideoMimeType(
@NonNull String codecMime) {
mSupportedVideoMimeTypes.add(codecMime);
return this;
}
private List