mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Clarify and fix SequenceAssetLoader threading
PiperOrigin-RevId: 520663415
This commit is contained in:
parent
766e7d7d35
commit
104cfc322c
1 changed files with 61 additions and 56 deletions
|
|
@ -40,7 +40,6 @@ import com.google.common.collect.ImmutableMap;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -88,8 +87,6 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||||
private boolean decodeAudio;
|
private boolean decodeAudio;
|
||||||
private boolean decodeVideo;
|
private boolean decodeVideo;
|
||||||
private long totalDurationUs;
|
private long totalDurationUs;
|
||||||
private long maxSequenceDurationUs;
|
|
||||||
private boolean isMaxSequenceDurationUsFinal;
|
|
||||||
private int sequenceLoopCount;
|
private int sequenceLoopCount;
|
||||||
private boolean audioLoopingEnded;
|
private boolean audioLoopingEnded;
|
||||||
private boolean videoLoopingEnded;
|
private boolean videoLoopingEnded;
|
||||||
|
|
@ -97,6 +94,8 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||||
private boolean released;
|
private boolean released;
|
||||||
|
|
||||||
private volatile long currentAssetDurationUs;
|
private volatile long currentAssetDurationUs;
|
||||||
|
private volatile long maxSequenceDurationUs;
|
||||||
|
private volatile boolean isMaxSequenceDurationUsFinal;
|
||||||
|
|
||||||
public SequenceAssetLoader(
|
public SequenceAssetLoader(
|
||||||
EditedMediaItemSequence sequence,
|
EditedMediaItemSequence sequence,
|
||||||
|
|
@ -112,7 +111,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||||
sequenceAssetLoaderListener = listener;
|
sequenceAssetLoaderListener = listener;
|
||||||
handler = clock.createHandler(looper, /* callback= */ null);
|
handler = clock.createHandler(looper, /* callback= */ null);
|
||||||
sampleConsumersByTrackType = new HashMap<>();
|
sampleConsumersByTrackType = new HashMap<>();
|
||||||
mediaItemChangedListenersByTrackType = new ConcurrentHashMap<>();
|
mediaItemChangedListenersByTrackType = new HashMap<>();
|
||||||
processedInputsBuilder = new ImmutableList.Builder<>();
|
processedInputsBuilder = new ImmutableList.Builder<>();
|
||||||
nonEndedTracks = new AtomicInteger();
|
nonEndedTracks = new AtomicInteger();
|
||||||
isCurrentAssetFirstAsset = true;
|
isCurrentAssetFirstAsset = true;
|
||||||
|
|
@ -124,6 +123,8 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||||
this.currentAssetLoader = currentAssetLoader;
|
this.currentAssetLoader = currentAssetLoader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Methods called from TransformerInternal thread.
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start() {
|
public void start() {
|
||||||
currentAssetLoader.start();
|
currentAssetLoader.start();
|
||||||
|
|
@ -172,12 +173,27 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addCurrentProcessedInput() {
|
||||||
|
if ((sequenceLoopCount * editedMediaItems.size() + currentMediaItemIndex)
|
||||||
|
>= processedInputsSize) {
|
||||||
|
MediaItem mediaItem = editedMediaItems.get(currentMediaItemIndex).mediaItem;
|
||||||
|
ImmutableMap<Integer, String> decoders = currentAssetLoader.getDecoderNames();
|
||||||
|
processedInputsBuilder.add(
|
||||||
|
new ExportResult.ProcessedInput(
|
||||||
|
mediaItem, decoders.get(C.TRACK_TYPE_AUDIO), decoders.get(C.TRACK_TYPE_VIDEO)));
|
||||||
|
processedInputsSize++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Methods called from AssetLoader threads.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds an {@link OnMediaItemChangedListener} for the given track type.
|
* Adds an {@link OnMediaItemChangedListener} for the given track type.
|
||||||
*
|
*
|
||||||
* <p>There can't be more than one {@link OnMediaItemChangedListener} for the same track type.
|
* <p>There can't be more than one {@link OnMediaItemChangedListener} for the same track type.
|
||||||
*
|
*
|
||||||
* <p>Must always be called from the same thread. This thread can be any thread.
|
* <p>Must be called from the thread used by the current {@link AssetLoader} to pass data to the
|
||||||
|
* {@link SampleConsumer}.
|
||||||
*
|
*
|
||||||
* @param onMediaItemChangedListener The {@link OnMediaItemChangedListener}.
|
* @param onMediaItemChangedListener The {@link OnMediaItemChangedListener}.
|
||||||
* @param trackType The {@link C.TrackType} for which to listen to {@link MediaItem} change
|
* @param trackType The {@link C.TrackType} for which to listen to {@link MediaItem} change
|
||||||
|
|
@ -190,43 +206,6 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||||
mediaItemChangedListenersByTrackType.put(trackType, onMediaItemChangedListener);
|
mediaItemChangedListenersByTrackType.put(trackType, onMediaItemChangedListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the maximum {@link EditedMediaItemSequence} duration in the {@link Composition}.
|
|
||||||
*
|
|
||||||
* <p>The duration passed is the current maximum duration. This method can be called multiple
|
|
||||||
* times as this duration increases. Indeed, a sequence duration will increase during an export
|
|
||||||
* when a new {@link MediaItem} is loaded, which can increase the maximum sequence duration.
|
|
||||||
*
|
|
||||||
* <p>Must be called from the thread used by the current {@link AssetLoader} to pass data to the
|
|
||||||
* {@link SampleConsumer}.
|
|
||||||
*
|
|
||||||
* @param maxSequenceDurationUs The current maximum sequence duration, in microseconds.
|
|
||||||
* @param isFinal Whether the duration passed is final. Setting this value to {@code true} means
|
|
||||||
* that the duration passed will not change anymore during the entire export.
|
|
||||||
*/
|
|
||||||
public void setMaxSequenceDurationUs(long maxSequenceDurationUs, boolean isFinal) {
|
|
||||||
this.maxSequenceDurationUs = maxSequenceDurationUs;
|
|
||||||
isMaxSequenceDurationUsFinal = isFinal;
|
|
||||||
}
|
|
||||||
|
|
||||||
// AssetLoader.Listener implementation.
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDurationUs(long durationUs) {
|
|
||||||
checkArgument(
|
|
||||||
durationUs != C.TIME_UNSET || currentMediaItemIndex == editedMediaItems.size() - 1,
|
|
||||||
"Could not retrieve required duration for EditedMediaItem " + currentMediaItemIndex);
|
|
||||||
currentAssetDurationUs = durationUs;
|
|
||||||
if (editedMediaItems.size() == 1 && !isLooping) {
|
|
||||||
sequenceAssetLoaderListener.onDurationUs(durationUs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onTrackCount(int trackCount) {
|
|
||||||
nonEndedTracks.set(trackCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onTrackAdded(
|
public boolean onTrackAdded(
|
||||||
Format inputFormat,
|
Format inputFormat,
|
||||||
|
|
@ -321,11 +300,6 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||||
return sampleConsumer;
|
return sampleConsumer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(ExportException exportException) {
|
|
||||||
sequenceAssetLoaderListener.onError(exportException);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onMediaItemChanged(int trackType, @Nullable Format format) {
|
private void onMediaItemChanged(int trackType, @Nullable Format format) {
|
||||||
@Nullable
|
@Nullable
|
||||||
OnMediaItemChangedListener onMediaItemChangedListener =
|
OnMediaItemChangedListener onMediaItemChangedListener =
|
||||||
|
|
@ -340,18 +314,49 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||||
/* isLast= */ currentMediaItemIndex == editedMediaItems.size() - 1);
|
/* isLast= */ currentMediaItemIndex == editedMediaItems.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addCurrentProcessedInput() {
|
// Methods called from any thread.
|
||||||
if ((sequenceLoopCount * editedMediaItems.size() + currentMediaItemIndex)
|
|
||||||
>= processedInputsSize) {
|
/**
|
||||||
MediaItem mediaItem = editedMediaItems.get(currentMediaItemIndex).mediaItem;
|
* Sets the maximum {@link EditedMediaItemSequence} duration in the {@link Composition}.
|
||||||
ImmutableMap<Integer, String> decoders = currentAssetLoader.getDecoderNames();
|
*
|
||||||
processedInputsBuilder.add(
|
* <p>The duration passed is the current maximum duration. This method can be called multiple
|
||||||
new ExportResult.ProcessedInput(
|
* times as this duration increases. Indeed, a sequence duration will increase during an export
|
||||||
mediaItem, decoders.get(C.TRACK_TYPE_AUDIO), decoders.get(C.TRACK_TYPE_VIDEO)));
|
* when a new {@link MediaItem} is loaded, which can increase the maximum sequence duration.
|
||||||
processedInputsSize++;
|
*
|
||||||
|
* <p>Can be called from any thread.
|
||||||
|
*
|
||||||
|
* @param maxSequenceDurationUs The current maximum sequence duration, in microseconds.
|
||||||
|
* @param isFinal Whether the duration passed is final. Setting this value to {@code true} means
|
||||||
|
* that the duration passed will not change anymore during the entire export.
|
||||||
|
*/
|
||||||
|
public void setMaxSequenceDurationUs(long maxSequenceDurationUs, boolean isFinal) {
|
||||||
|
this.maxSequenceDurationUs = maxSequenceDurationUs;
|
||||||
|
isMaxSequenceDurationUsFinal = isFinal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDurationUs(long durationUs) {
|
||||||
|
checkArgument(
|
||||||
|
durationUs != C.TIME_UNSET || currentMediaItemIndex == editedMediaItems.size() - 1,
|
||||||
|
"Could not retrieve required duration for EditedMediaItem " + currentMediaItemIndex);
|
||||||
|
currentAssetDurationUs = durationUs;
|
||||||
|
if (editedMediaItems.size() == 1 && !isLooping) {
|
||||||
|
sequenceAssetLoaderListener.onDurationUs(durationUs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTrackCount(int trackCount) {
|
||||||
|
nonEndedTracks.set(trackCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(ExportException exportException) {
|
||||||
|
sequenceAssetLoaderListener.onError(exportException);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Classes accessed from AssetLoader threads.
|
||||||
|
|
||||||
private final class SampleConsumerWrapper implements SampleConsumer {
|
private final class SampleConsumerWrapper implements SampleConsumer {
|
||||||
|
|
||||||
private final SampleConsumer sampleConsumer;
|
private final SampleConsumer sampleConsumer;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue