Pass initial timestamp offset to VideoFrameProcessor
For pause and resume feature we will remux the previously processed video in the first export and then in the second export we will resume processing remaining video. For the second export we will have to set initial timestamp offset so that video samples from the second export are in continuation to the previously muxed samples. PiperOrigin-RevId: 561689651
This commit is contained in:
parent
4c3ad641c0
commit
219b253731
@ -53,7 +53,8 @@ import java.util.concurrent.Executor;
|
|||||||
DebugViewProvider debugViewProvider,
|
DebugViewProvider debugViewProvider,
|
||||||
Listener listener,
|
Listener listener,
|
||||||
Executor listenerExecutor,
|
Executor listenerExecutor,
|
||||||
List<Effect> compositionEffects) {
|
List<Effect> compositionEffects,
|
||||||
|
long initialTimestampOffsetUs) {
|
||||||
@Nullable Presentation presentation = null;
|
@Nullable Presentation presentation = null;
|
||||||
for (int i = 0; i < compositionEffects.size(); i++) {
|
for (int i = 0; i < compositionEffects.size(); i++) {
|
||||||
Effect effect = compositionEffects.get(i);
|
Effect effect = compositionEffects.get(i);
|
||||||
@ -71,7 +72,8 @@ import java.util.concurrent.Executor;
|
|||||||
debugViewProvider,
|
debugViewProvider,
|
||||||
listenerExecutor,
|
listenerExecutor,
|
||||||
/* renderFramesAutomatically= */ true,
|
/* renderFramesAutomatically= */ true,
|
||||||
presentation);
|
presentation,
|
||||||
|
initialTimestampOffsetUs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,6 +86,7 @@ import java.util.concurrent.Executor;
|
|||||||
private final DebugViewProvider debugViewProvider;
|
private final DebugViewProvider debugViewProvider;
|
||||||
private final Executor listenerExecutor;
|
private final Executor listenerExecutor;
|
||||||
private final boolean renderFramesAutomatically;
|
private final boolean renderFramesAutomatically;
|
||||||
|
private final long initialTimestampOffsetUs;
|
||||||
@Nullable private final Presentation presentation;
|
@Nullable private final Presentation presentation;
|
||||||
|
|
||||||
@Nullable private VideoFrameProcessingWrapper videoFrameProcessingWrapper;
|
@Nullable private VideoFrameProcessingWrapper videoFrameProcessingWrapper;
|
||||||
@ -101,7 +104,8 @@ import java.util.concurrent.Executor;
|
|||||||
DebugViewProvider debugViewProvider,
|
DebugViewProvider debugViewProvider,
|
||||||
Executor listenerExecutor,
|
Executor listenerExecutor,
|
||||||
boolean renderFramesAutomatically,
|
boolean renderFramesAutomatically,
|
||||||
@Nullable Presentation presentation) {
|
@Nullable Presentation presentation,
|
||||||
|
long initialTimestampOffsetUs) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.videoFrameProcessorFactory = videoFrameProcessorFactory;
|
this.videoFrameProcessorFactory = videoFrameProcessorFactory;
|
||||||
this.inputColorInfo = inputColorInfo;
|
this.inputColorInfo = inputColorInfo;
|
||||||
@ -112,6 +116,7 @@ import java.util.concurrent.Executor;
|
|||||||
this.listenerExecutor = listenerExecutor;
|
this.listenerExecutor = listenerExecutor;
|
||||||
this.renderFramesAutomatically = renderFramesAutomatically;
|
this.renderFramesAutomatically = renderFramesAutomatically;
|
||||||
this.presentation = presentation;
|
this.presentation = presentation;
|
||||||
|
this.initialTimestampOffsetUs = initialTimestampOffsetUs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -168,7 +173,8 @@ import java.util.concurrent.Executor;
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
renderFramesAutomatically,
|
renderFramesAutomatically,
|
||||||
presentation);
|
presentation,
|
||||||
|
initialTimestampOffsetUs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the {@link GraphInput}. */
|
/** Returns the {@link GraphInput}. */
|
||||||
|
@ -1008,7 +1008,8 @@ public final class Transformer {
|
|||||||
fallbackListener,
|
fallbackListener,
|
||||||
applicationHandler,
|
applicationHandler,
|
||||||
debugViewProvider,
|
debugViewProvider,
|
||||||
clock);
|
clock,
|
||||||
|
/* videoSampleTimestampOffsetUs= */ 0);
|
||||||
transformerInternal.start();
|
transformerInternal.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,6 +105,13 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
private final Listener listener;
|
private final Listener listener;
|
||||||
private final HandlerWrapper applicationHandler;
|
private final HandlerWrapper applicationHandler;
|
||||||
private final Clock clock;
|
private final Clock clock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The presentation timestamp offset for all the video samples. It will be set when resuming video
|
||||||
|
* processing after remuxing previously processed samples.
|
||||||
|
*/
|
||||||
|
private final long videoSampleTimestampOffsetUs;
|
||||||
|
|
||||||
private final HandlerThread internalHandlerThread;
|
private final HandlerThread internalHandlerThread;
|
||||||
private final HandlerWrapper internalHandler;
|
private final HandlerWrapper internalHandler;
|
||||||
private final List<SequenceAssetLoader> sequenceAssetLoaders;
|
private final List<SequenceAssetLoader> sequenceAssetLoaders;
|
||||||
@ -142,13 +149,15 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
FallbackListener fallbackListener,
|
FallbackListener fallbackListener,
|
||||||
HandlerWrapper applicationHandler,
|
HandlerWrapper applicationHandler,
|
||||||
DebugViewProvider debugViewProvider,
|
DebugViewProvider debugViewProvider,
|
||||||
Clock clock) {
|
Clock clock,
|
||||||
|
long videoSampleTimestampOffsetUs) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.composition = composition;
|
this.composition = composition;
|
||||||
this.encoderFactory = new CapturingEncoderFactory(encoderFactory);
|
this.encoderFactory = new CapturingEncoderFactory(encoderFactory);
|
||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
this.applicationHandler = applicationHandler;
|
this.applicationHandler = applicationHandler;
|
||||||
this.clock = clock;
|
this.clock = clock;
|
||||||
|
this.videoSampleTimestampOffsetUs = videoSampleTimestampOffsetUs;
|
||||||
this.muxerWrapper = muxerWrapper;
|
this.muxerWrapper = muxerWrapper;
|
||||||
// It's safe to use "this" because we don't mux any data before exiting the constructor.
|
// It's safe to use "this" because we don't mux any data before exiting the constructor.
|
||||||
this.muxerWrapper.setListener(this);
|
this.muxerWrapper.setListener(this);
|
||||||
@ -601,7 +610,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
muxerWrapper,
|
muxerWrapper,
|
||||||
/* errorConsumer= */ this::onError,
|
/* errorConsumer= */ this::onError,
|
||||||
fallbackListener,
|
fallbackListener,
|
||||||
debugViewProvider));
|
debugViewProvider,
|
||||||
|
videoSampleTimestampOffsetUs));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,6 +48,7 @@ import java.util.concurrent.atomic.AtomicLong;
|
|||||||
private final VideoFrameProcessor videoFrameProcessor;
|
private final VideoFrameProcessor videoFrameProcessor;
|
||||||
private final AtomicLong mediaItemOffsetUs;
|
private final AtomicLong mediaItemOffsetUs;
|
||||||
private final ColorInfo inputColorInfo;
|
private final ColorInfo inputColorInfo;
|
||||||
|
private final long initialTimestampOffsetUs;
|
||||||
@Nullable final Presentation presentation;
|
@Nullable final Presentation presentation;
|
||||||
|
|
||||||
public VideoFrameProcessingWrapper(
|
public VideoFrameProcessingWrapper(
|
||||||
@ -59,10 +60,12 @@ import java.util.concurrent.atomic.AtomicLong;
|
|||||||
Executor listenerExecutor,
|
Executor listenerExecutor,
|
||||||
VideoFrameProcessor.Listener listener,
|
VideoFrameProcessor.Listener listener,
|
||||||
boolean renderFramesAutomatically,
|
boolean renderFramesAutomatically,
|
||||||
@Nullable Presentation presentation)
|
@Nullable Presentation presentation,
|
||||||
|
long initialTimestampOffsetUs)
|
||||||
throws VideoFrameProcessingException {
|
throws VideoFrameProcessingException {
|
||||||
this.mediaItemOffsetUs = new AtomicLong();
|
this.mediaItemOffsetUs = new AtomicLong();
|
||||||
this.inputColorInfo = inputColorInfo;
|
this.inputColorInfo = inputColorInfo;
|
||||||
|
this.initialTimestampOffsetUs = initialTimestampOffsetUs;
|
||||||
this.presentation = presentation;
|
this.presentation = presentation;
|
||||||
|
|
||||||
videoFrameProcessor =
|
videoFrameProcessor =
|
||||||
@ -89,7 +92,7 @@ import java.util.concurrent.atomic.AtomicLong;
|
|||||||
createEffectListWithPresentation(editedMediaItem.effects.videoEffects, presentation),
|
createEffectListWithPresentation(editedMediaItem.effects.videoEffects, presentation),
|
||||||
new FrameInfo.Builder(decodedSize.getWidth(), decodedSize.getHeight())
|
new FrameInfo.Builder(decodedSize.getWidth(), decodedSize.getHeight())
|
||||||
.setPixelWidthHeightRatio(trackFormat.pixelWidthHeightRatio)
|
.setPixelWidthHeightRatio(trackFormat.pixelWidthHeightRatio)
|
||||||
.setOffsetToAddUs(mediaItemOffsetUs.get())
|
.setOffsetToAddUs(initialTimestampOffsetUs + mediaItemOffsetUs.get())
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
mediaItemOffsetUs.addAndGet(durationUs);
|
mediaItemOffsetUs.addAndGet(durationUs);
|
||||||
|
@ -56,7 +56,8 @@ import java.util.concurrent.Executor;
|
|||||||
DebugViewProvider debugViewProvider,
|
DebugViewProvider debugViewProvider,
|
||||||
Listener listener,
|
Listener listener,
|
||||||
Executor listenerExecutor,
|
Executor listenerExecutor,
|
||||||
List<Effect> compositionEffects)
|
List<Effect> compositionEffects,
|
||||||
|
long initialTimestampOffsetUs)
|
||||||
throws VideoFrameProcessingException;
|
throws VideoFrameProcessingException;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,6 +63,7 @@ import org.checkerframework.dataflow.qual.Pure;
|
|||||||
private final VideoGraph videoGraph;
|
private final VideoGraph videoGraph;
|
||||||
private final EncoderWrapper encoderWrapper;
|
private final EncoderWrapper encoderWrapper;
|
||||||
private final DecoderInputBuffer encoderOutputBuffer;
|
private final DecoderInputBuffer encoderOutputBuffer;
|
||||||
|
private final long initialTimestampOffsetUs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The timestamp of the last buffer processed before {@linkplain
|
* The timestamp of the last buffer processed before {@linkplain
|
||||||
@ -82,11 +83,13 @@ import org.checkerframework.dataflow.qual.Pure;
|
|||||||
MuxerWrapper muxerWrapper,
|
MuxerWrapper muxerWrapper,
|
||||||
Consumer<ExportException> errorConsumer,
|
Consumer<ExportException> errorConsumer,
|
||||||
FallbackListener fallbackListener,
|
FallbackListener fallbackListener,
|
||||||
DebugViewProvider debugViewProvider)
|
DebugViewProvider debugViewProvider,
|
||||||
|
long initialTimestampOffsetUs)
|
||||||
throws ExportException {
|
throws ExportException {
|
||||||
// TODO(b/278259383) Consider delaying configuration of VideoSampleExporter to use the decoder
|
// TODO(b/278259383) Consider delaying configuration of VideoSampleExporter to use the decoder
|
||||||
// output format instead of the extractor output format, to match AudioSampleExporter behavior.
|
// output format instead of the extractor output format, to match AudioSampleExporter behavior.
|
||||||
super(firstInputFormat, muxerWrapper);
|
super(firstInputFormat, muxerWrapper);
|
||||||
|
this.initialTimestampOffsetUs = initialTimestampOffsetUs;
|
||||||
finalFramePresentationTimeUs = C.TIME_UNSET;
|
finalFramePresentationTimeUs = C.TIME_UNSET;
|
||||||
|
|
||||||
ColorInfo decoderInputColor;
|
ColorInfo decoderInputColor;
|
||||||
@ -488,7 +491,8 @@ import org.checkerframework.dataflow.qual.Pure;
|
|||||||
debugViewProvider,
|
debugViewProvider,
|
||||||
/* listener= */ thisRef,
|
/* listener= */ thisRef,
|
||||||
/* listenerExecutor= */ MoreExecutors.directExecutor(),
|
/* listenerExecutor= */ MoreExecutors.directExecutor(),
|
||||||
compositionEffects);
|
compositionEffects,
|
||||||
|
initialTimestampOffsetUs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
Loading…
x
Reference in New Issue
Block a user