Throw when the video track disappears during export
Throw when the output has a video track but the current MediaItem in the sequence doesn't have any video. PiperOrigin-RevId: 512004463
This commit is contained in:
parent
672d7494f2
commit
c2fd7339e1
@ -17,6 +17,7 @@ package androidx.media3.transformer;
|
|||||||
|
|
||||||
import static androidx.media3.common.util.Assertions.checkArgument;
|
import static androidx.media3.common.util.Assertions.checkArgument;
|
||||||
import static androidx.media3.common.util.Assertions.checkNotNull;
|
import static androidx.media3.common.util.Assertions.checkNotNull;
|
||||||
|
import static androidx.media3.common.util.Assertions.checkState;
|
||||||
import static androidx.media3.common.util.Assertions.checkStateNotNull;
|
import static androidx.media3.common.util.Assertions.checkStateNotNull;
|
||||||
import static androidx.media3.transformer.Transformer.PROGRESS_STATE_AVAILABLE;
|
import static androidx.media3.transformer.Transformer.PROGRESS_STATE_AVAILABLE;
|
||||||
import static androidx.media3.transformer.Transformer.PROGRESS_STATE_NOT_STARTED;
|
import static androidx.media3.transformer.Transformer.PROGRESS_STATE_NOT_STARTED;
|
||||||
@ -52,8 +53,21 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
private final AssetLoader.Factory assetLoaderFactory;
|
private final AssetLoader.Factory assetLoaderFactory;
|
||||||
private final HandlerWrapper handler;
|
private final HandlerWrapper handler;
|
||||||
private final Listener compositeAssetLoaderListener;
|
private final Listener compositeAssetLoaderListener;
|
||||||
|
/**
|
||||||
|
* A mapping from track types to {@link SampleConsumer} instances.
|
||||||
|
*
|
||||||
|
* <p>This map never contains more than 2 entries, as the only track types allowed are audio and
|
||||||
|
* video.
|
||||||
|
*/
|
||||||
private final Map<Integer, SampleConsumer> sampleConsumersByTrackType;
|
private final Map<Integer, SampleConsumer> sampleConsumersByTrackType;
|
||||||
|
/**
|
||||||
|
* A mapping from track types to {@link OnMediaItemChangedListener} instances.
|
||||||
|
*
|
||||||
|
* <p>This map never contains more than 2 entries, as the only track types allowed are audio and
|
||||||
|
* video.
|
||||||
|
*/
|
||||||
private final Map<Integer, OnMediaItemChangedListener> mediaItemChangedListenersByTrackType;
|
private final Map<Integer, OnMediaItemChangedListener> mediaItemChangedListenersByTrackType;
|
||||||
|
|
||||||
private final ImmutableList.Builder<ExportResult.ProcessedInput> processedInputsBuilder;
|
private final ImmutableList.Builder<ExportResult.ProcessedInput> processedInputsBuilder;
|
||||||
private final AtomicInteger nonEndedTracks;
|
private final AtomicInteger nonEndedTracks;
|
||||||
|
|
||||||
@ -133,10 +147,11 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
*
|
*
|
||||||
* @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
|
||||||
* events.
|
* events. Must be {@link C#TRACK_TYPE_AUDIO} or {@link C#TRACK_TYPE_VIDEO}.
|
||||||
*/
|
*/
|
||||||
public void addOnMediaItemChangedListener(
|
public void addOnMediaItemChangedListener(
|
||||||
OnMediaItemChangedListener onMediaItemChangedListener, @C.TrackType int trackType) {
|
OnMediaItemChangedListener onMediaItemChangedListener, @C.TrackType int trackType) {
|
||||||
|
checkArgument(trackType == C.TRACK_TYPE_AUDIO || trackType == C.TRACK_TYPE_VIDEO);
|
||||||
checkArgument(mediaItemChangedListenersByTrackType.get(trackType) == null);
|
checkArgument(mediaItemChangedListenersByTrackType.get(trackType) == null);
|
||||||
mediaItemChangedListenersByTrackType.put(trackType, onMediaItemChangedListener);
|
mediaItemChangedListenersByTrackType.put(trackType, onMediaItemChangedListener);
|
||||||
}
|
}
|
||||||
@ -172,19 +187,21 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
long streamStartPositionUs,
|
long streamStartPositionUs,
|
||||||
long streamOffsetUs)
|
long streamOffsetUs)
|
||||||
throws ExportException {
|
throws ExportException {
|
||||||
int trackType = MimeTypes.getTrackType(format.sampleMimeType);
|
// Consider image as video because image inputs are fed to the VideoSamplePipeline.
|
||||||
|
int trackType =
|
||||||
|
MimeTypes.isAudio(format.sampleMimeType) ? C.TRACK_TYPE_AUDIO : C.TRACK_TYPE_VIDEO;
|
||||||
SampleConsumer sampleConsumer;
|
SampleConsumer sampleConsumer;
|
||||||
if (currentMediaItemIndex.get() == 0) {
|
if (currentMediaItemIndex.get() == 0) {
|
||||||
boolean addAudioTrack =
|
boolean addForcedAudioTrack =
|
||||||
forceAudioTrack && nonEndedTracks.get() == 1 && trackType == C.TRACK_TYPE_VIDEO;
|
forceAudioTrack && nonEndedTracks.get() == 1 && trackType == C.TRACK_TYPE_VIDEO;
|
||||||
int trackCount = nonEndedTracks.get() + (addAudioTrack ? 1 : 0);
|
int trackCount = nonEndedTracks.get() + (addForcedAudioTrack ? 1 : 0);
|
||||||
compositeAssetLoaderListener.onTrackCount(trackCount);
|
compositeAssetLoaderListener.onTrackCount(trackCount);
|
||||||
sampleConsumer =
|
sampleConsumer =
|
||||||
new SampleConsumerWrapper(
|
new SampleConsumerWrapper(
|
||||||
compositeAssetLoaderListener.onTrackAdded(
|
compositeAssetLoaderListener.onTrackAdded(
|
||||||
format, supportedOutputTypes, streamStartPositionUs, streamOffsetUs));
|
format, supportedOutputTypes, streamStartPositionUs, streamOffsetUs));
|
||||||
sampleConsumersByTrackType.put(trackType, sampleConsumer);
|
sampleConsumersByTrackType.put(trackType, sampleConsumer);
|
||||||
if (addAudioTrack) {
|
if (addForcedAudioTrack) {
|
||||||
Format firstAudioFormat =
|
Format firstAudioFormat =
|
||||||
new Format.Builder()
|
new Format.Builder()
|
||||||
.setSampleMimeType(MimeTypes.AUDIO_AAC)
|
.setSampleMimeType(MimeTypes.AUDIO_AAC)
|
||||||
@ -201,6 +218,14 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
sampleConsumersByTrackType.put(C.TRACK_TYPE_AUDIO, audioSampleConsumer);
|
sampleConsumersByTrackType.put(C.TRACK_TYPE_AUDIO, audioSampleConsumer);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// TODO(b/270533049): Remove the check below when implementing blank video frames generation.
|
||||||
|
boolean videoTrackDisappeared =
|
||||||
|
nonEndedTracks.get() == 1
|
||||||
|
&& trackType == C.TRACK_TYPE_AUDIO
|
||||||
|
&& sampleConsumersByTrackType.size() == 2;
|
||||||
|
checkState(
|
||||||
|
!videoTrackDisappeared,
|
||||||
|
"Inputs with no video track are not supported when the output contains a video track");
|
||||||
sampleConsumer =
|
sampleConsumer =
|
||||||
checkStateNotNull(
|
checkStateNotNull(
|
||||||
sampleConsumersByTrackType.get(trackType),
|
sampleConsumersByTrackType.get(trackType),
|
||||||
|
@ -367,7 +367,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
long streamStartPositionUs,
|
long streamStartPositionUs,
|
||||||
long streamOffsetUs)
|
long streamOffsetUs)
|
||||||
throws ExportException {
|
throws ExportException {
|
||||||
int trackType = MimeTypes.getTrackType(firstInputFormat.sampleMimeType);
|
|
||||||
if (!trackAdded) {
|
if (!trackAdded) {
|
||||||
// Call setTrackCount() methods here so that they are called from the same thread as the
|
// Call setTrackCount() methods here so that they are called from the same thread as the
|
||||||
// MuxerWrapper and FallbackListener methods called when building the sample pipelines.
|
// MuxerWrapper and FallbackListener methods called when building the sample pipelines.
|
||||||
@ -383,6 +382,11 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
firstInputFormat, supportedOutputTypes, streamStartPositionUs, streamOffsetUs),
|
firstInputFormat, supportedOutputTypes, streamStartPositionUs, streamOffsetUs),
|
||||||
streamStartPositionUs,
|
streamStartPositionUs,
|
||||||
streamOffsetUs);
|
streamOffsetUs);
|
||||||
|
// Consider image as video because image inputs are fed to the VideoSamplePipeline.
|
||||||
|
int trackType =
|
||||||
|
MimeTypes.isAudio(firstInputFormat.sampleMimeType)
|
||||||
|
? C.TRACK_TYPE_AUDIO
|
||||||
|
: C.TRACK_TYPE_VIDEO;
|
||||||
compositeAssetLoader.addOnMediaItemChangedListener(samplePipeline, trackType);
|
compositeAssetLoader.addOnMediaItemChangedListener(samplePipeline, trackType);
|
||||||
internalHandler.obtainMessage(MSG_REGISTER_SAMPLE_PIPELINE, samplePipeline).sendToTarget();
|
internalHandler.obtainMessage(MSG_REGISTER_SAMPLE_PIPELINE, samplePipeline).sendToTarget();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user