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

Commit ed467b36 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "transcoding: add API for determininng transcoding format"

parents 7162831a 566b316d
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -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);
+8 −0
Original line number Diff line number Diff line
@@ -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);
+136 −0
Original line number Diff line number Diff line
@@ -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;
            }
        }
    }

    /**
+13 −2
Original line number Diff line number Diff line
@@ -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 -> {
+8 −0
Original line number Diff line number Diff line
@@ -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);