mirror of
https://github.com/samsonjs/media.git
synced 2026-04-15 12:55:46 +00:00
Pass MuxerWrapper to the TransformerInternal
For pause/resume feature, same MuxerWrapper needs to be used across intermediate exports. So pass the MuxerWrapper from Transformer.java More specifically, when resume() is called 1. Create a MuxerWrapper and remux the previous video samples (Export 1). 2. User the same MuxerWrapper and start processing remaining video samples (Export 2). PiperOrigin-RevId: 561325867
This commit is contained in:
parent
cf3fd1f4dd
commit
b37e37aa3c
3 changed files with 29 additions and 21 deletions
|
|
@ -71,7 +71,6 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||
|
||||
private final String outputPath;
|
||||
private final Muxer.Factory muxerFactory;
|
||||
private final Listener listener;
|
||||
private final SparseArray<TrackInfo> trackTypeToInfo;
|
||||
private final ScheduledExecutorService abortScheduledExecutorService;
|
||||
|
||||
|
|
@ -80,6 +79,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||
private @C.TrackType int previousTrackType;
|
||||
private long minTrackTimeUs;
|
||||
private long maxEndedTrackTimeUs;
|
||||
private @MonotonicNonNull Listener listener;
|
||||
private @MonotonicNonNull ScheduledFuture<?> abortScheduledFuture;
|
||||
private boolean isAborted;
|
||||
private @MonotonicNonNull Muxer muxer;
|
||||
|
|
@ -87,16 +87,25 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||
private volatile int additionalRotationDegrees;
|
||||
private volatile int trackCount;
|
||||
|
||||
public MuxerWrapper(String outputPath, Muxer.Factory muxerFactory, Listener listener) {
|
||||
/** Creates an instance. */
|
||||
public MuxerWrapper(String outputPath, Muxer.Factory muxerFactory) {
|
||||
this.outputPath = outputPath;
|
||||
this.muxerFactory = muxerFactory;
|
||||
this.listener = listener;
|
||||
|
||||
trackTypeToInfo = new SparseArray<>();
|
||||
previousTrackType = C.TRACK_TYPE_NONE;
|
||||
abortScheduledExecutorService = Util.newSingleThreadScheduledExecutor(TIMER_THREAD_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a {@link MuxerWrapper.Listener}.
|
||||
*
|
||||
* <p>The {@link MuxerWrapper.Listener} must be set before calling any other methods.
|
||||
*/
|
||||
public void setListener(Listener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the clockwise rotation to add to the {@linkplain #addTrackFormat(Format) video track's}
|
||||
* rotation, in degrees.
|
||||
|
|
@ -266,9 +275,9 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||
|
||||
TrackInfo trackInfo = trackTypeToInfo.get(trackType);
|
||||
maxEndedTrackTimeUs = max(maxEndedTrackTimeUs, trackInfo.timeUs);
|
||||
Listener listener = checkNotNull(this.listener);
|
||||
listener.onTrackEnded(
|
||||
trackType, trackInfo.format, trackInfo.getAverageBitrate(), trackInfo.sampleCount);
|
||||
|
||||
if (trackType == C.TRACK_TYPE_VIDEO) {
|
||||
DebugTraceUtil.logEvent(DebugTraceUtil.EVENT_MUXER_TRACK_ENDED_VIDEO, trackInfo.timeUs);
|
||||
} else if (trackType == C.TRACK_TYPE_AUDIO) {
|
||||
|
|
@ -345,14 +354,15 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||
return;
|
||||
}
|
||||
isAborted = true;
|
||||
listener.onError(
|
||||
ExportException.createForMuxer(
|
||||
new IllegalStateException(
|
||||
Util.formatInvariant(
|
||||
MUXER_TIMEOUT_ERROR_FORMAT_STRING,
|
||||
maxDelayBetweenSamplesMs,
|
||||
DebugTraceUtil.generateTraceSummary())),
|
||||
ExportException.ERROR_CODE_MUXING_TIMEOUT));
|
||||
checkNotNull(listener)
|
||||
.onError(
|
||||
ExportException.createForMuxer(
|
||||
new IllegalStateException(
|
||||
Util.formatInvariant(
|
||||
MUXER_TIMEOUT_ERROR_FORMAT_STRING,
|
||||
maxDelayBetweenSamplesMs,
|
||||
DebugTraceUtil.generateTraceSummary())),
|
||||
ExportException.ERROR_CODE_MUXING_TIMEOUT));
|
||||
},
|
||||
maxDelayBetweenSamplesMs,
|
||||
MILLISECONDS);
|
||||
|
|
|
|||
|
|
@ -837,6 +837,7 @@ public final class Transformer {
|
|||
verifyApplicationThread();
|
||||
checkState(transformerInternal == null, "There is already an export in progress.");
|
||||
|
||||
MuxerWrapper muxerWrapper = new MuxerWrapper(path, muxerFactory);
|
||||
TransformerInternalListener transformerInternalListener =
|
||||
new TransformerInternalListener(composition);
|
||||
HandlerWrapper applicationHandler = clock.createHandler(looper, /* callback= */ null);
|
||||
|
|
@ -862,13 +863,12 @@ public final class Transformer {
|
|||
new TransformerInternal(
|
||||
context,
|
||||
composition,
|
||||
path,
|
||||
transformationRequest,
|
||||
assetLoaderFactory,
|
||||
audioMixerFactory,
|
||||
videoFrameProcessorFactory,
|
||||
encoderFactory,
|
||||
muxerFactory,
|
||||
muxerWrapper,
|
||||
transformerInternalListener,
|
||||
fallbackListener,
|
||||
applicationHandler,
|
||||
|
|
|
|||
|
|
@ -128,17 +128,16 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||
private volatile boolean released;
|
||||
|
||||
// Warning suppression is needed to assign the MuxerWrapper with "this" as listener.
|
||||
@SuppressWarnings("assignment.type.incompatible")
|
||||
@SuppressWarnings({"argument.type.incompatible"})
|
||||
public TransformerInternal(
|
||||
Context context,
|
||||
Composition composition,
|
||||
String outputPath,
|
||||
TransformationRequest transformationRequest,
|
||||
AssetLoader.Factory assetLoaderFactory,
|
||||
AudioMixer.Factory audioMixerFactory,
|
||||
VideoFrameProcessor.Factory videoFrameProcessorFactory,
|
||||
Codec.EncoderFactory encoderFactory,
|
||||
Muxer.Factory muxerFactory,
|
||||
MuxerWrapper muxerWrapper,
|
||||
Listener listener,
|
||||
FallbackListener fallbackListener,
|
||||
HandlerWrapper applicationHandler,
|
||||
|
|
@ -150,6 +149,9 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||
this.listener = listener;
|
||||
this.applicationHandler = applicationHandler;
|
||||
this.clock = clock;
|
||||
this.muxerWrapper = muxerWrapper;
|
||||
// It's safe to use "this" because we don't mux any data before exiting the constructor.
|
||||
this.muxerWrapper.setListener(this);
|
||||
internalHandlerThread = new HandlerThread("Transformer:Internal");
|
||||
internalHandlerThread.start();
|
||||
sequenceAssetLoaders = new ArrayList<>();
|
||||
|
|
@ -192,10 +194,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||
HandlerWrapper internalHandler =
|
||||
clock.createHandler(internalLooper, /* callback= */ this::handleMessage);
|
||||
this.internalHandler = internalHandler;
|
||||
// It's safe to use "this" because we don't mux any data before exiting the constructor.
|
||||
@SuppressWarnings("nullness:argument.type.incompatible")
|
||||
MuxerWrapper muxerWrapper = new MuxerWrapper(outputPath, muxerFactory, /* listener= */ this);
|
||||
this.muxerWrapper = muxerWrapper;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
|
|
|
|||
Loading…
Reference in a new issue