Use CompositeAssetLoader in Transformer

PiperOrigin-RevId: 506863538
This commit is contained in:
kimvde 2023-02-03 11:58:57 +00:00 committed by microkatz
parent 4528ea3005
commit 23a544025d
5 changed files with 34 additions and 19 deletions

View File

@ -57,12 +57,12 @@ import java.util.concurrent.atomic.AtomicLong;
private volatile long currentDurationUs; private volatile long currentDurationUs;
public CompositeAssetLoader( public CompositeAssetLoader(
List<EditedMediaItem> editedMediaItems, EditedMediaItemSequence sequence,
AssetLoader.Factory assetLoaderFactory, AssetLoader.Factory assetLoaderFactory,
Looper looper, Looper looper,
Listener listener, Listener listener,
Clock clock) { Clock clock) {
this.editedMediaItems = editedMediaItems; this.editedMediaItems = sequence.editedMediaItems;
this.assetLoaderFactory = assetLoaderFactory; this.assetLoaderFactory = assetLoaderFactory;
compositeAssetLoaderListener = listener; compositeAssetLoaderListener = listener;
currentMediaItemIndex = new AtomicInteger(); currentMediaItemIndex = new AtomicInteger();

View File

@ -15,6 +15,8 @@
*/ */
package com.google.android.exoplayer2.transformer; package com.google.android.exoplayer2.transformer;
import static com.google.android.exoplayer2.util.Assertions.checkArgument;
import com.google.android.exoplayer2.MediaItem; import com.google.android.exoplayer2.MediaItem;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
@ -29,6 +31,8 @@ public final class Composition {
/** /**
* The {@link EditedMediaItemSequence} instances to compose. {@link MediaItem} instances from * The {@link EditedMediaItemSequence} instances to compose. {@link MediaItem} instances from
* different sequences that are overlapping in time will be mixed in the output. * different sequences that are overlapping in time will be mixed in the output.
*
* <p>This list must not be empty.
*/ */
public final ImmutableList<EditedMediaItemSequence> sequences; public final ImmutableList<EditedMediaItemSequence> sequences;
/** The {@link Effects} to apply to the composition. */ /** The {@link Effects} to apply to the composition. */
@ -41,6 +45,7 @@ public final class Composition {
* @param effects The {@link #effects}. * @param effects The {@link #effects}.
*/ */
public Composition(ImmutableList<EditedMediaItemSequence> sequences, Effects effects) { public Composition(ImmutableList<EditedMediaItemSequence> sequences, Effects effects) {
checkArgument(!sequences.isEmpty());
this.sequences = sequences; this.sequences = sequences;
this.effects = effects; this.effects = effects;
} }

View File

@ -15,6 +15,8 @@
*/ */
package com.google.android.exoplayer2.transformer; package com.google.android.exoplayer2.transformer;
import static com.google.android.exoplayer2.util.Assertions.checkArgument;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
/** /**
@ -24,7 +26,11 @@ import com.google.common.collect.ImmutableList;
*/ */
public final class EditedMediaItemSequence { public final class EditedMediaItemSequence {
/** The {@link EditedMediaItem} instances in the sequence. */ /**
* The {@link EditedMediaItem} instances in the sequence.
*
* <p>This list must not be empty.
*/
public final ImmutableList<EditedMediaItem> editedMediaItems; public final ImmutableList<EditedMediaItem> editedMediaItems;
/** /**
@ -33,6 +39,7 @@ public final class EditedMediaItemSequence {
* @param editedMediaItems The {@link #editedMediaItems}. * @param editedMediaItems The {@link #editedMediaItems}.
*/ */
public EditedMediaItemSequence(ImmutableList<EditedMediaItem> editedMediaItems) { public EditedMediaItemSequence(ImmutableList<EditedMediaItem> editedMediaItems) {
checkArgument(!editedMediaItems.isEmpty());
this.editedMediaItems = editedMediaItems; this.editedMediaItems = editedMediaItems;
} }
} }

View File

@ -761,7 +761,7 @@ public final class Transformer {
transformerInternal = transformerInternal =
new TransformerInternal( new TransformerInternal(
context, context,
editedMediaItem, composition,
path, path,
transformationRequest, transformationRequest,
generateSilentAudio, generateSilentAudio,

View File

@ -111,7 +111,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
public TransformerInternal( public TransformerInternal(
Context context, Context context,
EditedMediaItem editedMediaItem, Composition composition,
String outputPath, String outputPath,
TransformationRequest transformationRequest, TransformationRequest transformationRequest,
boolean generateSilentAudio, boolean generateSilentAudio,
@ -134,9 +134,11 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
internalHandlerThread = new HandlerThread("Transformer:Internal"); internalHandlerThread = new HandlerThread("Transformer:Internal");
internalHandlerThread.start(); internalHandlerThread.start();
Looper internalLooper = internalHandlerThread.getLooper(); Looper internalLooper = internalHandlerThread.getLooper();
ComponentListener componentListener = new ComponentListener(editedMediaItem, fallbackListener); EditedMediaItemSequence sequence = composition.sequences.get(0);
ComponentListener componentListener = new ComponentListener(sequence, fallbackListener);
assetLoader = assetLoader =
assetLoaderFactory.createAssetLoader(editedMediaItem, internalLooper, componentListener); new CompositeAssetLoader(
sequence, assetLoaderFactory, internalLooper, componentListener, clock);
samplePipelines = new ArrayList<>(); samplePipelines = new ArrayList<>();
muxerWrapper = new MuxerWrapper(outputPath, muxerFactory, componentListener); muxerWrapper = new MuxerWrapper(outputPath, muxerFactory, componentListener);
transformerConditionVariable = new ConditionVariable(); transformerConditionVariable = new ConditionVariable();
@ -313,7 +315,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
private class ComponentListener implements AssetLoader.Listener, MuxerWrapper.Listener { private class ComponentListener implements AssetLoader.Listener, MuxerWrapper.Listener {
private final EditedMediaItem editedMediaItem; // The first EditedMediaItem in the sequence determines which SamplePipeline to use.
private final EditedMediaItem firstEditedMediaItem;
private final FallbackListener fallbackListener; private final FallbackListener fallbackListener;
private final AtomicInteger trackCount; private final AtomicInteger trackCount;
@ -321,8 +324,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
private volatile long durationUs; private volatile long durationUs;
public ComponentListener(EditedMediaItem editedMediaItem, FallbackListener fallbackListener) { public ComponentListener(EditedMediaItemSequence sequence, FallbackListener fallbackListener) {
this.editedMediaItem = editedMediaItem; firstEditedMediaItem = sequence.editedMediaItems.get(0);
this.fallbackListener = fallbackListener; this.fallbackListener = fallbackListener;
trackCount = new AtomicInteger(); trackCount = new AtomicInteger();
durationUs = C.TIME_UNSET; durationUs = C.TIME_UNSET;
@ -468,8 +471,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
streamStartPositionUs, streamStartPositionUs,
streamOffsetUs, streamOffsetUs,
transformationRequest, transformationRequest,
editedMediaItem.flattenForSlowMotion, firstEditedMediaItem.flattenForSlowMotion,
editedMediaItem.effects.audioProcessors, firstEditedMediaItem.effects.audioProcessors,
generateSilentAudio ? durationUs : C.TIME_UNSET, generateSilentAudio ? durationUs : C.TIME_UNSET,
encoderFactory, encoderFactory,
muxerWrapper, muxerWrapper,
@ -481,8 +484,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
streamStartPositionUs, streamStartPositionUs,
streamOffsetUs, streamOffsetUs,
transformationRequest, transformationRequest,
editedMediaItem.effects.videoEffects, firstEditedMediaItem.effects.videoEffects,
editedMediaItem.effects.frameProcessorFactory, firstEditedMediaItem.effects.frameProcessorFactory,
encoderFactory, encoderFactory,
muxerWrapper, muxerWrapper,
/* errorConsumer= */ this::onTransformationError, /* errorConsumer= */ this::onTransformationError,
@ -510,10 +513,10 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
&& !muxerWrapper.supportsSampleMimeType(inputFormat.sampleMimeType)) { && !muxerWrapper.supportsSampleMimeType(inputFormat.sampleMimeType)) {
return true; return true;
} }
if (editedMediaItem.flattenForSlowMotion && isSlowMotion(inputFormat)) { if (firstEditedMediaItem.flattenForSlowMotion && isSlowMotion(inputFormat)) {
return true; return true;
} }
if (!editedMediaItem.effects.audioProcessors.isEmpty()) { if (!firstEditedMediaItem.effects.audioProcessors.isEmpty()) {
return true; return true;
} }
if (generateSilentAudio) { if (generateSilentAudio) {
@ -539,7 +542,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
private boolean shouldTranscodeVideo( private boolean shouldTranscodeVideo(
Format inputFormat, long streamStartPositionUs, long streamOffsetUs) { Format inputFormat, long streamStartPositionUs, long streamOffsetUs) {
if ((streamStartPositionUs - streamOffsetUs) != 0 if ((streamStartPositionUs - streamOffsetUs) != 0
&& !editedMediaItem.mediaItem.clippingConfiguration.startsAtKeyFrame) { && !firstEditedMediaItem.mediaItem.clippingConfiguration.startsAtKeyFrame) {
return true; return true;
} }
if (encoderFactory.videoNeedsEncoding()) { if (encoderFactory.videoNeedsEncoding()) {
@ -561,8 +564,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
} }
// TODO(b/265927935): consider generalizing this logic. // TODO(b/265927935): consider generalizing this logic.
for (int i = 0; i < editedMediaItem.effects.videoEffects.size(); i++) { for (int i = 0; i < firstEditedMediaItem.effects.videoEffects.size(); i++) {
Effect videoEffect = editedMediaItem.effects.videoEffects.get(i); Effect videoEffect = firstEditedMediaItem.effects.videoEffects.get(i);
if (videoEffect instanceof Presentation) { if (videoEffect instanceof Presentation) {
Presentation presentation = (Presentation) videoEffect; Presentation presentation = (Presentation) videoEffect;
// The decoder rotates encoded frames for display by inputFormat.rotationDegrees. // The decoder rotates encoded frames for display by inputFormat.rotationDegrees.