Internal-only change

PiperOrigin-RevId: 743468059
This commit is contained in:
dancho 2025-04-03 02:03:54 -07:00 committed by Copybara-Service
parent bd14b753ee
commit 769aca2e32
5 changed files with 44 additions and 19 deletions

View File

@ -501,6 +501,8 @@ public class TransformerEndToEndTest {
.build()
.run(testId, editedMediaItem);
Format format = retrieveTrackFormat(context, result.filePath, C.TRACK_TYPE_VIDEO);
assertThat(format.rotationDegrees).isEqualTo(90);
assertThat(result.exportResult.width).isEqualTo(outputFormat.width);
}
@ -527,6 +529,8 @@ public class TransformerEndToEndTest {
.build()
.run(testId, editedMediaItem);
Format format = retrieveTrackFormat(context, result.filePath, C.TRACK_TYPE_VIDEO);
assertThat(format.rotationDegrees).isEqualTo(0);
assertThat(result.exportResult.width).isEqualTo(inputFormat.width);
}

View File

@ -97,6 +97,9 @@ public final class Transformer {
/** A builder for {@link Transformer} instances. */
public static final class Builder {
private static final ImmutableList<Integer> ALL_ROTATION_DEGREES =
ImmutableList.of(0, 90, 180, 270);
// Mandatory field.
private final Context context;
@ -109,7 +112,7 @@ public final class Transformer {
private boolean removeAudio;
private boolean removeVideo;
private boolean trimOptimizationEnabled;
private boolean portraitEncodingEnabled;
private ImmutableList<Integer> allowedEncodingRotationDegrees;
private boolean fileStartsOnVideoFrameEnabled;
private boolean usePlatformDiagnostics;
private long maxDelayBetweenMuxerSamplesMs;
@ -150,6 +153,7 @@ public final class Transformer {
metricsReporterFactory =
new EditingMetricsCollector.DefaultMetricsReporter.Factory(context);
}
allowedEncodingRotationDegrees = ALL_ROTATION_DEGREES;
}
/** Creates a builder with the values of the provided {@link Transformer}. */
@ -163,7 +167,7 @@ public final class Transformer {
this.removeAudio = transformer.removeAudio;
this.removeVideo = transformer.removeVideo;
this.trimOptimizationEnabled = transformer.trimOptimizationEnabled;
this.portraitEncodingEnabled = transformer.portraitEncodingEnabled;
this.allowedEncodingRotationDegrees = transformer.allowedEncodingRotationDegrees;
this.fileStartsOnVideoFrameEnabled = transformer.fileStartsOnVideoFrameEnabled;
this.usePlatformDiagnostics = transformer.usePlatformDiagnostics;
this.maxDelayBetweenMuxerSamplesMs = transformer.maxDelayBetweenMuxerSamplesMs;
@ -286,7 +290,7 @@ public final class Transformer {
*/
@CanIgnoreReturnValue
public Builder setPortraitEncodingEnabled(boolean enabled) {
portraitEncodingEnabled = enabled;
allowedEncodingRotationDegrees = enabled ? ImmutableList.of(0) : ALL_ROTATION_DEGREES;
return this;
}
@ -597,7 +601,7 @@ public final class Transformer {
removeAudio,
removeVideo,
trimOptimizationEnabled,
portraitEncodingEnabled,
allowedEncodingRotationDegrees,
fileStartsOnVideoFrameEnabled,
usePlatformDiagnostics,
maxDelayBetweenMuxerSamplesMs,
@ -783,7 +787,7 @@ public final class Transformer {
private final boolean removeAudio;
private final boolean removeVideo;
private final boolean trimOptimizationEnabled;
private final boolean portraitEncodingEnabled;
private final ImmutableList<Integer> allowedEncodingRotationDegrees;
private final boolean fileStartsOnVideoFrameEnabled;
private final boolean usePlatformDiagnostics;
private final long maxDelayBetweenMuxerSamplesMs;
@ -825,7 +829,7 @@ public final class Transformer {
boolean removeAudio,
boolean removeVideo,
boolean trimOptimizationEnabled,
boolean portraitEncodingEnabled,
ImmutableList<Integer> allowedEncodingRotationDegrees,
boolean fileStartsOnVideoFrameEnabled,
boolean usePlatformDiagnostics,
long maxDelayBetweenMuxerSamplesMs,
@ -848,7 +852,7 @@ public final class Transformer {
this.removeAudio = removeAudio;
this.removeVideo = removeVideo;
this.trimOptimizationEnabled = trimOptimizationEnabled;
this.portraitEncodingEnabled = portraitEncodingEnabled;
this.allowedEncodingRotationDegrees = allowedEncodingRotationDegrees;
this.fileStartsOnVideoFrameEnabled = fileStartsOnVideoFrameEnabled;
this.usePlatformDiagnostics = usePlatformDiagnostics;
this.maxDelayBetweenMuxerSamplesMs = maxDelayBetweenMuxerSamplesMs;
@ -1639,7 +1643,7 @@ public final class Transformer {
audioMixerFactory,
videoFrameProcessorFactory,
encoderFactory,
portraitEncodingEnabled,
allowedEncodingRotationDegrees,
maxFramesInEncoder,
muxerWrapper,
componentListener,

View File

@ -148,7 +148,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
private final Object setMaxSequenceDurationUsLock;
private final Object progressLock;
private final ProgressHolder internalProgressHolder;
private final boolean portraitEncodingEnabled;
private final ImmutableList<Integer> allowedEncodingRotationDegrees;
private final int maxFramesInEncoder;
private boolean isDrainingExporters;
@ -194,7 +194,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
AudioMixer.Factory audioMixerFactory,
VideoFrameProcessor.Factory videoFrameProcessorFactory,
Codec.EncoderFactory encoderFactory,
boolean portraitEncodingEnabled,
ImmutableList<Integer> allowedEncodingRotationDegrees,
int maxFramesInEncoder,
MuxerWrapper muxerWrapper,
Listener listener,
@ -207,7 +207,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
this.context = context;
this.composition = composition;
this.encoderFactory = new CapturingEncoderFactory(encoderFactory);
this.portraitEncodingEnabled = portraitEncodingEnabled;
this.allowedEncodingRotationDegrees = allowedEncodingRotationDegrees;
this.maxFramesInEncoder = maxFramesInEncoder;
this.listener = listener;
this.applicationHandler = applicationHandler;
@ -746,7 +746,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
debugViewProvider,
videoSampleTimestampOffsetUs,
/* hasMultipleInputs= */ assetLoaderInputTracker.hasMultipleConcurrentVideoTracks(),
portraitEncodingEnabled,
allowedEncodingRotationDegrees,
maxFramesInEncoder,
logSessionId));
}

View File

@ -60,6 +60,7 @@ import androidx.media3.common.util.TimestampIterator;
import androidx.media3.decoder.DecoderInputBuffer;
import androidx.media3.effect.MultipleInputVideoGraph;
import androidx.media3.effect.SingleInputVideoGraph;
import com.google.common.collect.ImmutableList;
import java.nio.ByteBuffer;
import java.util.List;
import java.util.Objects;
@ -99,7 +100,7 @@ import org.checkerframework.dataflow.qual.Pure;
DebugViewProvider debugViewProvider,
long initialTimestampOffsetUs,
boolean hasMultipleInputs,
boolean portraitEncodingEnabled,
ImmutableList<Integer> allowedEncodingRotationDegrees,
int maxFramesInEncoder,
@Nullable LogSessionId logSessionId)
throws ExportException {
@ -136,7 +137,7 @@ import org.checkerframework.dataflow.qual.Pure;
new EncoderWrapper(
encoderFactory,
firstInputFormat.buildUpon().setColorInfo(videoGraphOutputColor).build(),
portraitEncodingEnabled,
allowedEncodingRotationDegrees,
muxerWrapper.getSupportedSampleMimeTypes(C.TRACK_TYPE_VIDEO),
transformationRequest,
fallbackListener,
@ -249,7 +250,7 @@ import org.checkerframework.dataflow.qual.Pure;
private final Codec.EncoderFactory encoderFactory;
private final Format inputFormat;
private final boolean portraitEncodingEnabled;
private final ImmutableList<Integer> allowedEncodingRotationDegrees;
private final List<String> muxerSupportedMimeTypes;
private final TransformationRequest transformationRequest;
private final FallbackListener fallbackListener;
@ -266,7 +267,7 @@ import org.checkerframework.dataflow.qual.Pure;
public EncoderWrapper(
Codec.EncoderFactory encoderFactory,
Format inputFormat,
boolean portraitEncodingEnabled,
ImmutableList<Integer> allowedEncodingRotationDegrees,
List<String> muxerSupportedMimeTypes,
TransformationRequest transformationRequest,
FallbackListener fallbackListener,
@ -274,7 +275,7 @@ import org.checkerframework.dataflow.qual.Pure;
checkArgument(inputFormat.colorInfo != null);
this.encoderFactory = encoderFactory;
this.inputFormat = inputFormat;
this.portraitEncodingEnabled = portraitEncodingEnabled;
this.allowedEncodingRotationDegrees = allowedEncodingRotationDegrees;
this.muxerSupportedMimeTypes = muxerSupportedMimeTypes;
this.transformationRequest = transformationRequest;
this.fallbackListener = fallbackListener;
@ -319,7 +320,7 @@ import org.checkerframework.dataflow.qual.Pure;
// frame before encoding, so the encoded frame's width >= height. In this case, the VideoGraph
// rotates the decoded video frames counter-clockwise, and the muxer adds a clockwise rotation
// to the metadata.
if (requestedWidth < requestedHeight && !portraitEncodingEnabled) {
if (requestedWidth < requestedHeight) {
int temp = requestedWidth;
requestedWidth = requestedHeight;
requestedHeight = temp;
@ -333,6 +334,22 @@ import org.checkerframework.dataflow.qual.Pure;
outputRotationDegrees = inputFormat.rotationDegrees;
}
if (!allowedEncodingRotationDegrees.contains(outputRotationDegrees)) {
int alternativeOutputRotationDegreesWithSameWidthAndHeight =
(outputRotationDegrees + 180) % 360;
if (allowedEncodingRotationDegrees.contains(
alternativeOutputRotationDegreesWithSameWidthAndHeight)) {
outputRotationDegrees = alternativeOutputRotationDegreesWithSameWidthAndHeight;
} else {
// No allowed rotation of the same orientation. Swap width and height, and use any allowed
// orientation.
int temp = requestedWidth;
requestedWidth = requestedHeight;
requestedHeight = temp;
outputRotationDegrees = allowedEncodingRotationDegrees.get(0);
}
}
// Rotation is handled by this class. The encoder must see a video with zero degrees rotation.
Format requestedEncoderFormat =
new Format.Builder()

View File

@ -73,7 +73,7 @@ public final class VideoEncoderWrapperTest {
.setSampleMimeType(MimeTypes.VIDEO_H264)
.setColorInfo(ColorInfo.SDR_BT709_LIMITED)
.build(),
/* portraitEncodingEnabled= */ false,
/* allowedEncodingRotationDegrees= */ ImmutableList.of(0, 90, 180, 270),
/* muxerSupportedMimeTypes= */ ImmutableList.of(MimeTypes.VIDEO_H264),
emptyTransformationRequest,
fallbackListener,