public final class

TransformationRequest

extends java.lang.Object

 java.lang.Object

↳androidx.media3.transformer.TransformationRequest

Gradle dependencies

compile group: 'androidx.media3', name: 'media3-transformer', version: '1.0.0-alpha03'

  • groupId: androidx.media3
  • artifactId: media3-transformer
  • version: 1.0.0-alpha03

Artifact androidx.media3:media3-transformer:1.0.0-alpha03 it located at Google repository (https://maven.google.com/)

Overview

A media transformation request.

Summary

Fields
public final java.lang.StringaudioMimeType

The requested output audio sample MIME type, or null if inferred from the input.

public final booleanenableHdrEditing

Whether to attempt to process any input video stream as a high dynamic range (HDR) signal.

public final booleanflattenForSlowMotion

Whether the input should be flattened for media containing slow motion markers.

public final intoutputHeight

The requested height of the output video, or C.LENGTH_UNSET if inferred from the input.

public final MatrixtransformationMatrix

A to apply to video frames.

public final java.lang.StringvideoMimeType

The requested output video sample MIME type, or null if inferred from the input.

Methods
public TransformationRequest.BuilderbuildUpon()

Returns a new TransformationRequest.Builder initialized with the values of this instance.

public booleanequals(java.lang.Object o)

public inthashCode()

from java.lang.Objectclone, finalize, getClass, notify, notifyAll, toString, wait, wait, wait

Fields

public final Matrix transformationMatrix

A to apply to video frames.

See also: TransformationRequest.Builder.setTransformationMatrix(Matrix)

public final boolean flattenForSlowMotion

Whether the input should be flattened for media containing slow motion markers.

See also: TransformationRequest.Builder.setFlattenForSlowMotion(boolean)

public final int outputHeight

The requested height of the output video, or C.LENGTH_UNSET if inferred from the input.

See also: TransformationRequest.Builder.setResolution(int)

public final java.lang.String audioMimeType

The requested output audio sample MIME type, or null if inferred from the input.

See also: TransformationRequest.Builder.setAudioMimeType(String)

public final java.lang.String videoMimeType

The requested output video sample MIME type, or null if inferred from the input.

See also: TransformationRequest.Builder.setVideoMimeType(String)

public final boolean enableHdrEditing

Whether to attempt to process any input video stream as a high dynamic range (HDR) signal.

See also: TransformationRequest.Builder.experimental_setEnableHdrEditing(boolean)

Methods

public boolean equals(java.lang.Object o)

public int hashCode()

Returns a new TransformationRequest.Builder initialized with the values of this instance.

Source

/*
 * Copyright 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 androidx.media3.transformer;

import static androidx.media3.common.util.Assertions.checkArgument;

import android.graphics.Matrix;
import androidx.annotation.Nullable;
import androidx.media3.common.C;
import androidx.media3.common.MimeTypes;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.common.util.Util;
import androidx.media3.exoplayer.source.MediaSource;
import androidx.media3.extractor.mp4.Mp4Extractor;
import com.google.common.collect.ImmutableSet;

/** A media transformation request. */
@UnstableApi
public final class TransformationRequest {

  /** A builder for {@link TransformationRequest} instances. */
  public static final class Builder {

    private static final ImmutableSet<Integer> SUPPORTED_OUTPUT_HEIGHTS =
        ImmutableSet.of(144, 240, 360, 480, 720, 1080, 1440, 2160);

    private Matrix transformationMatrix;
    private boolean flattenForSlowMotion;
    private int outputHeight;
    @Nullable private String audioMimeType;
    @Nullable private String videoMimeType;
    private boolean enableHdrEditing;

    /**
     * Creates a new instance with default values.
     *
     * <p>Use {@link TransformationRequest#buildUpon()} to obtain a builder representing an existing
     * {@link TransformationRequest}.
     */
    public Builder() {
      transformationMatrix = new Matrix();
      outputHeight = C.LENGTH_UNSET;
    }

    private Builder(TransformationRequest transformationRequest) {
      this.transformationMatrix = new Matrix(transformationRequest.transformationMatrix);
      this.flattenForSlowMotion = transformationRequest.flattenForSlowMotion;
      this.outputHeight = transformationRequest.outputHeight;
      this.audioMimeType = transformationRequest.audioMimeType;
      this.videoMimeType = transformationRequest.videoMimeType;
      this.enableHdrEditing = transformationRequest.enableHdrEditing;
    }

    /**
     * Sets the transformation matrix. The default value is to apply no change.
     *
     * <p>This can be used to perform operations supported by {@link Matrix}, like scaling and
     * rotating the video.
     *
     * <p>The video dimensions will be on the x axis, from -aspectRatio to aspectRatio, and on the y
     * axis, from -1 to 1.
     *
     * <p>For now, resolution will not be affected by this method.
     *
     * @param transformationMatrix The transformation to apply to video frames.
     * @return This builder.
     */
    public Builder setTransformationMatrix(Matrix transformationMatrix) {
      // TODO(b/201293185): After {@link #setResolution} supports arbitrary resolutions,
      // allow transformations to change the resolution, by scaling to the appropriate min/max
      // values. This will also be required to create the VertexTransformation class, in order to
      // have aspect ratio helper methods (which require resolution to change).

      // TODO(b/213198690): Consider changing how transformationMatrix is applied, so that
      // dimensions will be from -1 to 1 on both x and y axes, but transformations will be applied
      // in a predictable manner.
      this.transformationMatrix = new Matrix(transformationMatrix);
      return this;
    }

    /**
     * Sets whether the input should be flattened for media containing slow motion markers. The
     * transformed output is obtained by removing the slow motion metadata and by actually slowing
     * down the parts of the video and audio streams defined in this metadata. The default value for
     * {@code flattenForSlowMotion} is {@code false}.
     *
     * <p>Only Samsung Extension Format (SEF) slow motion metadata type is supported. The
     * transformation has no effect if the input does not contain this metadata type.
     *
     * <p>For SEF slow motion media, the following assumptions are made on the input:
     *
     * <ul>
     *   <li>The input container format is (unfragmented) MP4.
     *   <li>The input contains an AVC video elementary stream with temporal SVC.
     *   <li>The recording frame rate of the video is 120 or 240 fps.
     * </ul>
     *
     * <p>If specifying a {@link MediaSource.Factory} using {@link
     * Transformer.Builder#setMediaSourceFactory(MediaSource.Factory)}, make sure that {@link
     * Mp4Extractor#FLAG_READ_SEF_DATA} is set on the {@link Mp4Extractor} used. Otherwise, the slow
     * motion metadata will be ignored and the input won't be flattened.
     *
     * @param flattenForSlowMotion Whether to flatten for slow motion.
     * @return This builder.
     */
    public Builder setFlattenForSlowMotion(boolean flattenForSlowMotion) {
      this.flattenForSlowMotion = flattenForSlowMotion;
      return this;
    }

    /**
     * Sets the output resolution using the output height. The default value {@link C#LENGTH_UNSET}
     * corresponds to using the same height as the input. Output width will scale to preserve the
     * input video's aspect ratio.
     *
     * <p>For now, only "popular" heights like 144, 240, 360, 480, 720, 1080, 1440, or 2160 are
     * supported, to ensure compatibility on different devices.
     *
     * <p>For example, a 1920x1440 video can be scaled to 640x480 by calling setResolution(480).
     *
     * @param outputHeight The output height in pixels.
     * @return This builder.
     * @throws IllegalArgumentException If the {@code outputHeight} is not supported.
     */
    public Builder setResolution(int outputHeight) {
      // TODO(b/209781577): Define outputHeight in the javadoc as height can be ambiguous for videos
      // where rotationDegrees is set in the Format.
      // TODO(b/201293185): Restructure to input a Presentation class.
      // TODO(b/201293185): Check encoder codec capabilities in order to allow arbitrary
      // resolutions and reasonable fallbacks.
      checkArgument(
          outputHeight == C.LENGTH_UNSET || SUPPORTED_OUTPUT_HEIGHTS.contains(outputHeight),
          "Unsupported outputHeight: " + outputHeight);
      this.outputHeight = outputHeight;
      return this;
    }

    /**
     * Sets the video MIME type of the output. The default value is {@code null} which corresponds
     * to using the same MIME type as the input. Supported MIME types are:
     *
     * <ul>
     *   <li>{@link MimeTypes#VIDEO_H263}
     *   <li>{@link MimeTypes#VIDEO_H264}
     *   <li>{@link MimeTypes#VIDEO_H265} from API level 24
     *   <li>{@link MimeTypes#VIDEO_MP4V}
     * </ul>
     *
     * @param videoMimeType The MIME type of the video samples in the output.
     * @return This builder.
     * @throws IllegalArgumentException If the {@code videoMimeType} is non-null but not a video
     *     {@link MimeTypes MIME type}.
     */
    public Builder setVideoMimeType(@Nullable String videoMimeType) {
      checkArgument(
          videoMimeType == null || MimeTypes.isVideo(videoMimeType),
          "Not a video MIME type: " + videoMimeType);
      this.videoMimeType = videoMimeType;
      return this;
    }

    /**
     * Sets the audio MIME type of the output. The default value is {@code null} which corresponds
     * to using the same MIME type as the input. Supported MIME types are:
     *
     * <ul>
     *   <li>{@link MimeTypes#AUDIO_AAC}
     *   <li>{@link MimeTypes#AUDIO_AMR_NB}
     *   <li>{@link MimeTypes#AUDIO_AMR_WB}
     * </ul>
     *
     * @param audioMimeType The MIME type of the audio samples in the output.
     * @return This builder.
     * @throws IllegalArgumentException If the {@code audioMimeType} is non-null but not an audio
     *     {@link MimeTypes MIME type}.
     */
    public Builder setAudioMimeType(@Nullable String audioMimeType) {
      checkArgument(
          audioMimeType == null || MimeTypes.isAudio(audioMimeType),
          "Not an audio MIME type: " + audioMimeType);
      this.audioMimeType = audioMimeType;
      return this;
    }

    /**
     * Sets whether to attempt to process any input video stream as a high dynamic range (HDR)
     * signal.
     *
     * <p>This method is experimental, and will be renamed or removed in a future release. The HDR
     * editing feature is under development and is intended for developing/testing HDR processing
     * and encoding support.
     *
     * @param enableHdrEditing Whether to attempt to process any input video stream as a high
     *     dynamic range (HDR) signal.
     * @return This builder.
     */
    public Builder experimental_setEnableHdrEditing(boolean enableHdrEditing) {
      this.enableHdrEditing = enableHdrEditing;
      return this;
    }

    /** Builds a {@link TransformationRequest} instance. */
    public TransformationRequest build() {
      return new TransformationRequest(
          transformationMatrix,
          flattenForSlowMotion,
          outputHeight,
          audioMimeType,
          videoMimeType,
          enableHdrEditing);
    }
  }

  /**
   * A {@link Matrix transformation matrix} to apply to video frames.
   *
   * @see Builder#setTransformationMatrix(Matrix)
   */
  public final Matrix transformationMatrix;
  /**
   * Whether the input should be flattened for media containing slow motion markers.
   *
   * @see Builder#setFlattenForSlowMotion(boolean)
   */
  public final boolean flattenForSlowMotion;
  /**
   * The requested height of the output video, or {@link C#LENGTH_UNSET} if inferred from the input.
   *
   * @see Builder#setResolution(int)
   */
  public final int outputHeight;
  /**
   * The requested output audio sample {@link MimeTypes MIME type}, or {@code null} if inferred from
   * the input.
   *
   * @see Builder#setAudioMimeType(String)
   */
  @Nullable public final String audioMimeType;
  /**
   * The requested output video sample {@link MimeTypes MIME type}, or {@code null} if inferred from
   * the input.
   *
   * @see Builder#setVideoMimeType(String)
   */
  @Nullable public final String videoMimeType;
  /**
   * Whether to attempt to process any input video stream as a high dynamic range (HDR) signal.
   *
   * @see Builder#experimental_setEnableHdrEditing(boolean)
   */
  public final boolean enableHdrEditing;

  private TransformationRequest(
      Matrix transformationMatrix,
      boolean flattenForSlowMotion,
      int outputHeight,
      @Nullable String audioMimeType,
      @Nullable String videoMimeType,
      boolean enableHdrEditing) {
    this.transformationMatrix = transformationMatrix;
    this.flattenForSlowMotion = flattenForSlowMotion;
    this.outputHeight = outputHeight;
    this.audioMimeType = audioMimeType;
    this.videoMimeType = videoMimeType;
    this.enableHdrEditing = enableHdrEditing;
  }

  @Override
  public boolean equals(@Nullable Object o) {
    if (this == o) {
      return true;
    }
    if (!(o instanceof TransformationRequest)) {
      return false;
    }
    TransformationRequest that = (TransformationRequest) o;
    return transformationMatrix.equals(that.transformationMatrix)
        && flattenForSlowMotion == that.flattenForSlowMotion
        && outputHeight == that.outputHeight
        && Util.areEqual(audioMimeType, that.audioMimeType)
        && Util.areEqual(videoMimeType, that.videoMimeType)
        && enableHdrEditing == that.enableHdrEditing;
  }

  @Override
  public int hashCode() {
    int result = transformationMatrix.hashCode();
    result = 31 * result + (flattenForSlowMotion ? 1 : 0);
    result = 31 * result + outputHeight;
    result = 31 * result + (audioMimeType != null ? audioMimeType.hashCode() : 0);
    result = 31 * result + (videoMimeType != null ? videoMimeType.hashCode() : 0);
    result = 31 * result + (enableHdrEditing ? 1 : 0);
    return result;
  }

  /**
   * Returns a new {@link TransformationRequest.Builder} initialized with the values of this
   * instance.
   */
  public Builder buildUpon() {
    return new Builder(this);
  }
}