mirror of
https://github.com/androidx/media.git
synced 2025-05-07 23:50:44 +08:00
Use CompositeAssetLoader in Transformer
PiperOrigin-RevId: 506863538
This commit is contained in:
parent
4528ea3005
commit
23a544025d
@ -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();
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -761,7 +761,7 @@ public final class Transformer {
|
|||||||
transformerInternal =
|
transformerInternal =
|
||||||
new TransformerInternal(
|
new TransformerInternal(
|
||||||
context,
|
context,
|
||||||
editedMediaItem,
|
composition,
|
||||||
path,
|
path,
|
||||||
transformationRequest,
|
transformationRequest,
|
||||||
generateSilentAudio,
|
generateSilentAudio,
|
||||||
|
@ -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.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user