mirror of
https://github.com/androidx/media.git
synced 2025-04-29 22:36:54 +08:00
Compare commits
2 Commits
bd14b753ee
...
96222478cd
Author | SHA1 | Date | |
---|---|---|---|
![]() |
96222478cd | ||
![]() |
769aca2e32 |
@ -1409,9 +1409,7 @@ public class MediaControllerCompatCallbackWithMediaSessionTest {
|
||||
assertThat(controllerCompat.getPlaybackState().getPosition()).isEqualTo(testPosition);
|
||||
assertThat(playbackStateRef.get().getActiveQueueItemId()).isEqualTo(testItemIndex);
|
||||
assertThat(controllerCompat.getPlaybackState().getActiveQueueItemId()).isEqualTo(testItemIndex);
|
||||
assertThat(callbackOrder)
|
||||
.containsExactly("onMetadataChanged", "onPlaybackStateChanged")
|
||||
.inOrder();
|
||||
assertThat(callbackOrder).containsExactly("onMetadataChanged", "onPlaybackStateChanged");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user