diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/spherical/ProjectionRenderer.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/spherical/ProjectionRenderer.java index 50dd89baea..28ecfc6b53 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/spherical/ProjectionRenderer.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/spherical/ProjectionRenderer.java @@ -24,6 +24,7 @@ import androidx.annotation.Nullable; import androidx.media3.common.C; import androidx.media3.common.util.GlUtil; import java.nio.FloatBuffer; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; /** * Utility class to render spherical meshes for video or images. Call {@link #init()} on the GL @@ -93,9 +94,9 @@ import java.nio.FloatBuffer; private int stereoMode; @Nullable private MeshData leftMeshData; @Nullable private MeshData rightMeshData; - @Nullable private GlUtil.Program program; + private GlUtil.@MonotonicNonNull Program program; - // Program related GL items. These are only valid if program is non-null. + // Program related GL items. These are only valid if Program is valid. private int mvpMatrixHandle; private int uTexMatrixHandle; private int positionHandle; @@ -195,11 +196,10 @@ import java.nio.FloatBuffer; GLES20.glDisableVertexAttribArray(texCoordsHandle); } - /** Cleans up the GL resources. */ + /** Cleans up GL resources. */ /* package */ void shutdown() { if (program != null) { program.delete(); - program = null; } } diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/spherical/SceneRenderer.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/spherical/SceneRenderer.java index bb8dc2fd5b..b31cfa98ab 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/spherical/SceneRenderer.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/spherical/SceneRenderer.java @@ -129,7 +129,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; projectionRenderer.draw(textureId, tempMatrix, rightEye); } - /** Cleans up the GL resources. */ + /** Cleans up GL resources. */ public void shutdown() { projectionRenderer.shutdown(); } diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/TranscodingTransformer.java b/libraries/transformer/src/main/java/androidx/media3/transformer/TranscodingTransformer.java index fb60d058ea..cef85c1266 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/TranscodingTransformer.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/TranscodingTransformer.java @@ -43,6 +43,7 @@ import androidx.media3.common.Player; import androidx.media3.common.Timeline; import androidx.media3.common.TracksInfo; import androidx.media3.common.util.Clock; +import androidx.media3.common.util.Log; import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.Util; import androidx.media3.exoplayer.DefaultLoadControl; @@ -93,12 +94,16 @@ public final class TranscodingTransformer { /** A builder for {@link TranscodingTransformer} instances. */ public static final class Builder { + // Mandatory field. private @MonotonicNonNull Context context; + + // Optional fields. private @MonotonicNonNull MediaSourceFactory mediaSourceFactory; private Muxer.Factory muxerFactory; private boolean removeAudio; private boolean removeVideo; private boolean flattenForSlowMotion; + private int outputHeight; private String outputMimeType; @Nullable private String audioMimeType; @Nullable private String videoMimeType; @@ -123,6 +128,7 @@ public final class TranscodingTransformer { this.removeAudio = transcodingTransformer.transformation.removeAudio; this.removeVideo = transcodingTransformer.transformation.removeVideo; this.flattenForSlowMotion = transcodingTransformer.transformation.flattenForSlowMotion; + this.outputHeight = transcodingTransformer.transformation.outputHeight; this.outputMimeType = transcodingTransformer.transformation.outputMimeType; this.audioMimeType = transcodingTransformer.transformation.audioMimeType; this.videoMimeType = transcodingTransformer.transformation.videoMimeType; @@ -215,6 +221,21 @@ public final class TranscodingTransformer { return this; } + /** + * Sets the output resolution for the video, using the output height. The default value is to + * use the same height as the input. Output width will scale to preserve the input video's + * aspect ratio. + * + *
For example, a 1920x1440 video can be scaled to 640x480 by calling setResolution(480). + * + * @param outputHeight The output height for the video, in pixels. + * @return This builder. + */ + public Builder setResolution(int outputHeight) { + this.outputHeight = outputHeight; + return this; + } + /** * Sets the MIME type of the output. The default value is {@link MimeTypes#VIDEO_MP4}. Supported * values are: @@ -358,6 +379,12 @@ public final class TranscodingTransformer { checkState( muxerFactory.supportsOutputMimeType(outputMimeType), "Unsupported output MIME type: " + outputMimeType); + // TODO(ME): Test with values of 10, 100, 1000). + Log.e("TranscodingTransformer", "outputHeight = " + outputHeight); + if (outputHeight == 0) { + // TODO(ME): get output height from input video. + outputHeight = 480; + } if (audioMimeType != null) { checkSampleMimeType(audioMimeType); } @@ -369,6 +396,7 @@ public final class TranscodingTransformer { removeAudio, removeVideo, flattenForSlowMotion, + outputHeight, outputMimeType, audioMimeType, videoMimeType); @@ -455,6 +483,7 @@ public final class TranscodingTransformer { checkState( !transformation.removeAudio || !transformation.removeVideo, "Audio and video cannot both be removed."); + checkState(!(transformation.removeVideo)); this.context = context; this.mediaSourceFactory = mediaSourceFactory; this.muxerFactory = muxerFactory; diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/Transformation.java b/libraries/transformer/src/main/java/androidx/media3/transformer/Transformation.java index 7b109478be..83413cc1a8 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/Transformation.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/Transformation.java @@ -24,6 +24,7 @@ import androidx.annotation.Nullable; public final boolean removeAudio; public final boolean removeVideo; public final boolean flattenForSlowMotion; + public final int outputHeight; public final String outputMimeType; @Nullable public final String audioMimeType; @Nullable public final String videoMimeType; @@ -32,12 +33,14 @@ import androidx.annotation.Nullable; boolean removeAudio, boolean removeVideo, boolean flattenForSlowMotion, + int outputHeight, String outputMimeType, @Nullable String audioMimeType, @Nullable String videoMimeType) { this.removeAudio = removeAudio; this.removeVideo = removeVideo; this.flattenForSlowMotion = flattenForSlowMotion; + this.outputHeight = outputHeight; this.outputMimeType = outputMimeType; this.audioMimeType = audioMimeType; this.videoMimeType = videoMimeType; diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/Transformer.java b/libraries/transformer/src/main/java/androidx/media3/transformer/Transformer.java index 85ff150e99..d587705a77 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/Transformer.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/Transformer.java @@ -299,11 +299,13 @@ public final class Transformer { checkState( muxerFactory.supportsOutputMimeType(outputMimeType), "Unsupported output MIME type: " + outputMimeType); + int outputHeight = 0; // TODO(ME): How do we get the input height here? Transformation transformation = new Transformation( removeAudio, removeVideo, flattenForSlowMotion, + outputHeight, outputMimeType, /* audioMimeType= */ null, /* videoMimeType= */ null);