Skip to content

Commit

Permalink
Add TransformerInternal
Browse files Browse the repository at this point in the history
The player is still driving the transformation at this point. The
transformer thread will be added in another CL.

PiperOrigin-RevId: 487479148
  • Loading branch information
kim-vde authored and microkatz committed Nov 10, 2022
1 parent 14e23d3 commit ef568d2
Show file tree
Hide file tree
Showing 8 changed files with 345 additions and 447 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.DefaultLoadControl;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.PlaybackException;
import com.google.android.exoplayer2.Player;
Expand All @@ -47,33 +48,28 @@
import com.google.android.exoplayer2.text.TextOutput;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.util.Clock;
import com.google.android.exoplayer2.util.DebugViewProvider;
import com.google.android.exoplayer2.util.Effect;
import com.google.android.exoplayer2.util.FrameProcessor;
import com.google.android.exoplayer2.video.VideoRendererEventListener;
import com.google.common.collect.ImmutableList;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;

/* package */ final class ExoPlayerAssetLoader {

public interface Listener {

void onTrackRegistered();

SamplePipeline onTrackAdded(Format format, long streamStartPositionUs, long streamOffsetUs)
throws TransformationException;

void onEnded();

void onError(Exception e);
}

private final Context context;
private final TransformationRequest transformationRequest;
private final ImmutableList<Effect> videoEffects;
private final boolean removeAudio;
private final boolean removeVideo;
private final MediaSource.Factory mediaSourceFactory;
private final Codec.DecoderFactory decoderFactory;
private final Codec.EncoderFactory encoderFactory;
private final FrameProcessor.Factory frameProcessorFactory;
private final Looper looper;
private final DebugViewProvider debugViewProvider;
private final Clock clock;

private @MonotonicNonNull MuxerWrapper muxerWrapper;
Expand All @@ -82,28 +78,16 @@ public interface Listener {

public ExoPlayerAssetLoader(
Context context,
TransformationRequest transformationRequest,
ImmutableList<Effect> videoEffects,
boolean removeAudio,
boolean removeVideo,
MediaSource.Factory mediaSourceFactory,
Codec.DecoderFactory decoderFactory,
Codec.EncoderFactory encoderFactory,
FrameProcessor.Factory frameProcessorFactory,
Looper looper,
DebugViewProvider debugViewProvider,
Clock clock) {
this.context = context;
this.transformationRequest = transformationRequest;
this.videoEffects = videoEffects;
this.removeAudio = removeAudio;
this.removeVideo = removeVideo;
this.mediaSourceFactory = mediaSourceFactory;
this.decoderFactory = decoderFactory;
this.encoderFactory = encoderFactory;
this.frameProcessorFactory = frameProcessorFactory;
this.looper = looper;
this.debugViewProvider = debugViewProvider;
this.clock = clock;
progressState = PROGRESS_STATE_NO_TRANSFORMATION;
}
Expand All @@ -112,7 +96,6 @@ public void start(
MediaItem mediaItem,
MuxerWrapper muxerWrapper,
Listener listener,
FallbackListener fallbackListener,
Transformer.AsyncErrorListener asyncErrorListener) {
this.muxerWrapper = muxerWrapper;

Expand All @@ -134,20 +117,7 @@ public void start(
ExoPlayer.Builder playerBuilder =
new ExoPlayer.Builder(
context,
new RenderersFactoryImpl(
context,
muxerWrapper,
removeAudio,
removeVideo,
transformationRequest,
mediaItem.clippingConfiguration.startsAtKeyFrame,
videoEffects,
frameProcessorFactory,
encoderFactory,
decoderFactory,
fallbackListener,
asyncErrorListener,
debugViewProvider))
new RenderersFactoryImpl(removeAudio, removeVideo, listener, asyncErrorListener))
.setMediaSourceFactory(mediaSourceFactory)
.setTrackSelector(trackSelector)
.setLoadControl(loadControl)
Expand Down Expand Up @@ -187,48 +157,21 @@ public void release() {

private static final class RenderersFactoryImpl implements RenderersFactory {

private final Context context;
private final MuxerWrapper muxerWrapper;
private final TransformerMediaClock mediaClock;
private final boolean removeAudio;
private final boolean removeVideo;
private final TransformationRequest transformationRequest;
private final boolean clippingStartsAtKeyFrame;
private final ImmutableList<Effect> videoEffects;
private final FrameProcessor.Factory frameProcessorFactory;
private final Codec.EncoderFactory encoderFactory;
private final Codec.DecoderFactory decoderFactory;
private final FallbackListener fallbackListener;
private final ExoPlayerAssetLoader.Listener assetLoaderListener;
private final Transformer.AsyncErrorListener asyncErrorListener;
private final DebugViewProvider debugViewProvider;

public RenderersFactoryImpl(
Context context,
MuxerWrapper muxerWrapper,
boolean removeAudio,
boolean removeVideo,
TransformationRequest transformationRequest,
boolean clippingStartsAtKeyFrame,
ImmutableList<Effect> videoEffects,
FrameProcessor.Factory frameProcessorFactory,
Codec.EncoderFactory encoderFactory,
Codec.DecoderFactory decoderFactory,
FallbackListener fallbackListener,
Transformer.AsyncErrorListener asyncErrorListener,
DebugViewProvider debugViewProvider) {
this.context = context;
this.muxerWrapper = muxerWrapper;
ExoPlayerAssetLoader.Listener assetLoaderListener,
Transformer.AsyncErrorListener asyncErrorListener) {
this.removeAudio = removeAudio;
this.removeVideo = removeVideo;
this.transformationRequest = transformationRequest;
this.clippingStartsAtKeyFrame = clippingStartsAtKeyFrame;
this.videoEffects = videoEffects;
this.frameProcessorFactory = frameProcessorFactory;
this.encoderFactory = encoderFactory;
this.decoderFactory = decoderFactory;
this.fallbackListener = fallbackListener;
this.assetLoaderListener = assetLoaderListener;
this.asyncErrorListener = asyncErrorListener;
this.debugViewProvider = debugViewProvider;
mediaClock = new TransformerMediaClock();
}

Expand All @@ -244,31 +187,14 @@ public Renderer[] createRenderers(
int index = 0;
if (!removeAudio) {
renderers[index] =
new TransformerAudioRenderer(
muxerWrapper,
mediaClock,
transformationRequest,
encoderFactory,
decoderFactory,
asyncErrorListener,
fallbackListener);
new ExoPlayerAssetLoaderRenderer(
C.TRACK_TYPE_AUDIO, mediaClock, assetLoaderListener, asyncErrorListener);
index++;
}
if (!removeVideo) {
renderers[index] =
new TransformerVideoRenderer(
context,
muxerWrapper,
mediaClock,
transformationRequest,
clippingStartsAtKeyFrame,
videoEffects,
frameProcessorFactory,
encoderFactory,
decoderFactory,
asyncErrorListener,
fallbackListener,
debugViewProvider);
new ExoPlayerAssetLoaderRenderer(
C.TRACK_TYPE_VIDEO, mediaClock, assetLoaderListener, asyncErrorListener);
index++;
}
return renderers;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,46 +16,53 @@

package com.google.android.exoplayer2.transformer;

import static com.google.android.exoplayer2.decoder.DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_DISABLED;
import static com.google.android.exoplayer2.source.SampleStream.FLAG_REQUIRE_FORMAT;
import static com.google.android.exoplayer2.util.Assertions.checkNotNull;

import androidx.annotation.Nullable;
import com.google.android.exoplayer2.BaseRenderer;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.FormatHolder;
import com.google.android.exoplayer2.RendererCapabilities;
import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
import com.google.android.exoplayer2.source.SampleStream.ReadDataResult;
import com.google.android.exoplayer2.util.MediaClock;
import com.google.android.exoplayer2.util.MimeTypes;
import com.google.errorprone.annotations.ForOverride;
import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.checkerframework.checker.nullness.qual.RequiresNonNull;

/* package */ abstract class TransformerBaseRenderer extends BaseRenderer {
/* package */ final class ExoPlayerAssetLoaderRenderer extends BaseRenderer {

private static final String TAG = "ExoPlayerAssetLoaderRenderer";

protected final MuxerWrapper muxerWrapper;
protected final TransformerMediaClock mediaClock;
protected final TransformationRequest transformationRequest;
protected final Transformer.AsyncErrorListener asyncErrorListener;
protected final FallbackListener fallbackListener;
private final TransformerMediaClock mediaClock;
private final ExoPlayerAssetLoader.Listener assetLoaderListener;
private final Transformer.AsyncErrorListener asyncErrorListener;
private final DecoderInputBuffer decoderInputBuffer;

private boolean isTransformationRunning;
protected long streamOffsetUs;
protected long streamStartPositionUs;
protected @MonotonicNonNull SamplePipeline samplePipeline;
private long streamOffsetUs;
private long streamStartPositionUs;
private @MonotonicNonNull SamplePipeline samplePipeline;

public TransformerBaseRenderer(
public ExoPlayerAssetLoaderRenderer(
int trackType,
MuxerWrapper muxerWrapper,
TransformerMediaClock mediaClock,
TransformationRequest transformationRequest,
Transformer.AsyncErrorListener asyncErrorListener,
FallbackListener fallbackListener) {
ExoPlayerAssetLoader.Listener assetLoaderListener,
Transformer.AsyncErrorListener asyncErrorListener) {
super(trackType);
this.muxerWrapper = muxerWrapper;
this.mediaClock = mediaClock;
this.transformationRequest = transformationRequest;
this.assetLoaderListener = assetLoaderListener;
this.asyncErrorListener = asyncErrorListener;
this.fallbackListener = fallbackListener;
decoderInputBuffer = new DecoderInputBuffer(BUFFER_REPLACEMENT_MODE_DISABLED);
}

@Override
public String getName() {
return TAG;
}

/**
Expand All @@ -65,30 +72,30 @@ public TransformerBaseRenderer(
* @return The {@link Capabilities} for this format.
*/
@Override
public final @Capabilities int supportsFormat(Format format) {
public @Capabilities int supportsFormat(Format format) {
return RendererCapabilities.create(
MimeTypes.getTrackType(format.sampleMimeType) == getTrackType()
? C.FORMAT_HANDLED
: C.FORMAT_UNSUPPORTED_TYPE);
}

@Override
public final MediaClock getMediaClock() {
public MediaClock getMediaClock() {
return mediaClock;
}

@Override
public final boolean isReady() {
public boolean isReady() {
return isSourceReady();
}

@Override
public final boolean isEnded() {
public boolean isEnded() {
return samplePipeline != null && samplePipeline.isEnded();
}

@Override
public final void render(long positionUs, long elapsedRealtimeUs) {
public void render(long positionUs, long elapsedRealtimeUs) {
try {
if (!isTransformationRunning || isEnded() || !ensureConfigured()) {
return;
Expand All @@ -97,43 +104,56 @@ public final void render(long positionUs, long elapsedRealtimeUs) {
while (samplePipeline.processData() || feedPipelineFromInput()) {}
} catch (TransformationException e) {
isTransformationRunning = false;
asyncErrorListener.onTransformationException(e);
asyncErrorListener.onTransformationError(e);
}
}

@Override
protected final void onStreamChanged(Format[] formats, long startPositionUs, long offsetUs) {
protected void onStreamChanged(Format[] formats, long startPositionUs, long offsetUs) {
this.streamOffsetUs = offsetUs;
this.streamStartPositionUs = startPositionUs;
}

@Override
protected final void onEnabled(boolean joining, boolean mayRenderStartOfStream) {
muxerWrapper.registerTrack();
fallbackListener.registerTrack();
protected void onEnabled(boolean joining, boolean mayRenderStartOfStream) {
assetLoaderListener.onTrackRegistered();
mediaClock.updateTimeForTrackType(getTrackType(), 0L);
}

@Override
protected final void onStarted() {
protected void onStarted() {
isTransformationRunning = true;
}

@Override
protected final void onStopped() {
protected void onStopped() {
isTransformationRunning = false;
}

@Override
protected final void onReset() {
protected void onReset() {
if (samplePipeline != null) {
samplePipeline.release();
}
}

@ForOverride
@EnsuresNonNullIf(expression = "samplePipeline", result = true)
protected abstract boolean ensureConfigured() throws TransformationException;
private boolean ensureConfigured() throws TransformationException {
if (samplePipeline != null) {
return true;
}

FormatHolder formatHolder = getFormatHolder();
@ReadDataResult
int result = readSource(formatHolder, decoderInputBuffer, /* readFlags= */ FLAG_REQUIRE_FORMAT);
if (result != C.RESULT_FORMAT_READ) {
return false;
}
Format inputFormat = checkNotNull(formatHolder.format);
samplePipeline =
assetLoaderListener.onTrackAdded(inputFormat, streamStartPositionUs, streamOffsetUs);
return true;
}

/**
* Attempts to read input data and pass the input data to the sample pipeline.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ private void resetAbortTimer() {
return;
}
isAborted = true;
asyncErrorListener.onTransformationException(
asyncErrorListener.onTransformationError(
TransformationException.createForMuxer(
new IllegalStateException(
"No output sample written in the last "
Expand Down
Loading

0 comments on commit ef568d2

Please sign in to comment.