Merge "transcoding: add API for determininng transcoding format"

This commit is contained in:
TreeHugger Robot
2020-09-08 23:59:20 +00:00
committed by Android (Google) Code Review
5 changed files with 173 additions and 2 deletions

View File

@@ -4394,6 +4394,14 @@ package android.media {
method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.Builder setVideoTrackFormat(@NonNull android.media.MediaFormat);
}
public static class MediaTranscodeManager.TranscodingRequest.MediaFormatResolver {
ctor public MediaTranscodeManager.TranscodingRequest.MediaFormatResolver();
method @Nullable public android.media.MediaFormat resolveVideoFormat();
method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.MediaFormatResolver setSourceVideoFormatHint(@NonNull android.media.MediaFormat);
method public boolean shouldTranscode();
field public static final String CAPS_SUPPORTS_HEVC = "support-hevc";
}
public class PlayerProxy {
method public void pause();
method public void setPan(float);

View File

@@ -1870,6 +1870,14 @@ package android.media {
method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.Builder setVideoTrackFormat(@NonNull android.media.MediaFormat);
}
public static class MediaTranscodeManager.TranscodingRequest.MediaFormatResolver {
ctor public MediaTranscodeManager.TranscodingRequest.MediaFormatResolver();
method @Nullable public android.media.MediaFormat resolveVideoFormat();
method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.MediaFormatResolver setSourceVideoFormatHint(@NonNull android.media.MediaFormat);
method public boolean shouldTranscode();
field public static final String CAPS_SUPPORTS_HEVC = "support-hevc";
}
public final class PlaybackParams implements android.os.Parcelable {
method public int getAudioStretchMode();
method public android.media.PlaybackParams setAudioStretchMode(int);

View File

@@ -27,6 +27,7 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.net.Uri;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -814,6 +815,141 @@ public final class MediaTranscodeManager {
return new TranscodingRequest(this);
}
}
/**
* Helper class for deciding if transcoding is needed, and if so, the track
* formats to use.
*/
public static class MediaFormatResolver {
private static final int BIT_RATE = 20000000; // 20Mbps
private MediaFormat mSrcVideoFormatHint;
private MediaFormat mSrcAudioFormatHint;
private Bundle mClientCaps;
/**
* A key describing whether the client supports HEVC-encoded video.
*
* The value associated with this key is a boolean. If unspecified, it's up to
* the MediaFormatResolver to determine the default.
*
* @see #setClientCapabilities(Bundle)
*/
public static final String CAPS_SUPPORTS_HEVC = "support-hevc";
/**
* Sets the abilities of the client consuming the media. Must be called
* before {@link #shouldTranscode()} or {@link #resolveVideoFormat()}.
*
* @param clientCaps A Bundle object containing the client's capabilities, such as
* {@link #CAPS_SUPPORTS_HEVC}.
* @return the same VideoFormatResolver instance.
* @hide
*/
@NonNull
public MediaFormatResolver setClientCapabilities(@NonNull Bundle clientCaps) {
mClientCaps = clientCaps;
return this;
}
/**
* Sets the video format hint about the source. Must be called before
* {@link #shouldTranscode()} or {@link #resolveVideoFormat()}.
*
* @param format A MediaFormat object containing information about the source's
* video track format that could affect the transcoding decision.
* Such information could include video codec types, color spaces,
* whether special format info (eg. slow-motion markers) are present,
* etc.. If a particular information is not present, it will not be
* used to make the decision.
* @return the same MediaFormatResolver instance.
*/
@NonNull
public MediaFormatResolver setSourceVideoFormatHint(@NonNull MediaFormat format) {
mSrcVideoFormatHint = format;
return this;
}
/**
* Sets the audio format hint about the source.
*
* @param format A MediaFormat object containing information about the source's
* audio track format that could affect the transcoding decision.
* @return the same MediaFormatResolver instance.
* @hide
*/
@NonNull
public MediaFormatResolver setSourceAudioFormatHint(@NonNull MediaFormat format) {
mSrcAudioFormatHint = format;
return this;
}
/**
* Returns whether the source content should be transcoded.
*
* @return true if the source should be transcoded.
* @throws UnsupportedOperationException if {@link #setClientCapabilities(Bundle)}
* or {@link #setSourceVideoFormatHint(MediaFormat)} was not called.
*/
public boolean shouldTranscode() {
if (mClientCaps == null) {
throw new UnsupportedOperationException(
"Client caps must be set!");
}
// Video src hint must be provided, audio src hint is not used right now.
if (mSrcVideoFormatHint == null) {
throw new UnsupportedOperationException(
"Source video format hint must be set!");
}
boolean supportHevc = mClientCaps.getBoolean(CAPS_SUPPORTS_HEVC, false);
if (!supportHevc && MediaFormat.MIMETYPE_VIDEO_HEVC.equals(
mSrcVideoFormatHint.getString(MediaFormat.KEY_MIME))) {
return true;
}
// TODO: add more checks as needed below.
return false;
}
/**
* Retrieves the video track format to be used on
* {@link Builder#setVideoTrackFormat(MediaFormat)} for this configuration.
*
* @return the video track format to be used if transcoding should be performed,
* and null otherwise.
* @throws UnsupportedOperationException if {@link #setClientCapabilities(Bundle)}
* or {@link #setSourceVideoFormatHint(MediaFormat)} was not called.
*/
@Nullable
public MediaFormat resolveVideoFormat() {
if (!shouldTranscode()) {
return null;
}
// TODO(hkuang): Only modified the video codec type, and use fixed bitrate for now.
// May switch to transcoding profile when it's available.
MediaFormat videoTrackFormat = new MediaFormat(mSrcVideoFormatHint);
videoTrackFormat.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_VIDEO_AVC);
videoTrackFormat.setInteger(MediaFormat.KEY_BIT_RATE, BIT_RATE);
return videoTrackFormat;
}
/**
* Retrieves the audio track format to be used for transcoding.
*
* @return the audio track format to be used if transcoding should be performed, and
* null otherwise.
* @throws UnsupportedOperationException if {@link #setClientCapabilities(Bundle)}
* or {@link #setSourceVideoFormatHint(MediaFormat)} was not called.
* @hide
*/
@Nullable
public MediaFormat resolveAudioFormat() {
if (!shouldTranscode()) {
return null;
}
// Audio transcoding is not supported yet, always return null.
return null;
}
}
}
/**

View File

@@ -24,6 +24,7 @@ import android.media.MediaFormat;
import android.media.MediaTranscodeManager;
import android.media.MediaTranscodeManager.TranscodingJob;
import android.media.MediaTranscodeManager.TranscodingRequest;
import android.media.MediaTranscodeManager.TranscodingRequest.MediaFormatResolver;
import android.media.TranscodingTestConfig;
import android.net.Uri;
import android.os.Bundle;
@@ -414,17 +415,27 @@ public class MediaTranscodeManagerTest
Uri destinationUri = Uri.parse(ContentResolver.SCHEME_FILE + "://"
+ mContext.getCacheDir().getAbsolutePath() + "/HevcTranscode.mp4");
Bundle clientCaps = new Bundle();
clientCaps.putBoolean(MediaFormatResolver.CAPS_SUPPORTS_HEVC, false);
MediaFormatResolver resolver = new MediaFormatResolver()
.setSourceVideoFormatHint(MediaFormat.createVideoFormat(
MediaFormat.MIMETYPE_VIDEO_HEVC, WIDTH, HEIGHT))
.setClientCapabilities(clientCaps);
assertTrue(resolver.shouldTranscode());
MediaFormat videoTrackFormat = resolver.resolveVideoFormat();
assertNotNull(videoTrackFormat);
TranscodingRequest request =
new TranscodingRequest.Builder()
.setSourceUri(mSourceHEVCVideoUri)
.setDestinationUri(destinationUri)
.setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
.setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
.setVideoTrackFormat(createMediaFormat())
.setVideoTrackFormat(videoTrackFormat)
.build();
Executor listenerExecutor = Executors.newSingleThreadExecutor();
Log.i(TAG, "transcoding to " + createMediaFormat());
Log.i(TAG, "transcoding to " + videoTrackFormat);
TranscodingJob job = mMediaTranscodeManager.enqueueRequest(request, listenerExecutor,
transcodingJob -> {

View File

@@ -4334,6 +4334,14 @@ package android.media {
method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.Builder setVideoTrackFormat(@NonNull android.media.MediaFormat);
}
public static class MediaTranscodeManager.TranscodingRequest.MediaFormatResolver {
ctor public MediaTranscodeManager.TranscodingRequest.MediaFormatResolver();
method @Nullable public android.media.MediaFormat resolveVideoFormat();
method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.MediaFormatResolver setSourceVideoFormatHint(@NonNull android.media.MediaFormat);
method public boolean shouldTranscode();
field public static final String CAPS_SUPPORTS_HEVC = "support-hevc";
}
public class PlayerProxy {
method public void pause();
method public void setPan(float);