mirror of
https://github.com/androidx/media.git
synced 2025-05-09 16:40:55 +08:00
Deduplicate transformer audio and video renderer implementations.
This change moves methods that are the same in `TransformerAudioRenderer` and `TransformerVideoRenderer` to `TransformerBaseRenderer`. PiperOrigin-RevId: 411758928
This commit is contained in:
parent
736ea9a148
commit
551a47e1fc
@ -150,6 +150,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
encoderOutputBuffer.data = encoder.getOutputBuffer();
|
encoderOutputBuffer.data = encoder.getOutputBuffer();
|
||||||
if (encoderOutputBuffer.data != null) {
|
if (encoderOutputBuffer.data != null) {
|
||||||
encoderOutputBuffer.timeUs = checkNotNull(encoder.getOutputBufferInfo()).presentationTimeUs;
|
encoderOutputBuffer.timeUs = checkNotNull(encoder.getOutputBufferInfo()).presentationTimeUs;
|
||||||
|
encoderOutputBuffer.setFlags(C.BUFFER_FLAG_KEY_FRAME);
|
||||||
return encoderOutputBuffer;
|
return encoderOutputBuffer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,10 +17,8 @@
|
|||||||
package androidx.media3.transformer;
|
package androidx.media3.transformer;
|
||||||
|
|
||||||
import static androidx.media3.common.util.Assertions.checkNotNull;
|
import static androidx.media3.common.util.Assertions.checkNotNull;
|
||||||
import static androidx.media3.common.util.Assertions.checkStateNotNull;
|
|
||||||
import static androidx.media3.exoplayer.source.SampleStream.FLAG_REQUIRE_FORMAT;
|
import static androidx.media3.exoplayer.source.SampleStream.FLAG_REQUIRE_FORMAT;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.annotation.RequiresApi;
|
import androidx.annotation.RequiresApi;
|
||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
import androidx.media3.common.Format;
|
import androidx.media3.common.Format;
|
||||||
@ -28,9 +26,6 @@ import androidx.media3.decoder.DecoderInputBuffer;
|
|||||||
import androidx.media3.exoplayer.ExoPlaybackException;
|
import androidx.media3.exoplayer.ExoPlaybackException;
|
||||||
import androidx.media3.exoplayer.FormatHolder;
|
import androidx.media3.exoplayer.FormatHolder;
|
||||||
import androidx.media3.exoplayer.source.SampleStream.ReadDataResult;
|
import androidx.media3.exoplayer.source.SampleStream.ReadDataResult;
|
||||||
import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf;
|
|
||||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|
||||||
import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|
||||||
|
|
||||||
@RequiresApi(18)
|
@RequiresApi(18)
|
||||||
/* package */ final class TransformerAudioRenderer extends TransformerBaseRenderer {
|
/* package */ final class TransformerAudioRenderer extends TransformerBaseRenderer {
|
||||||
@ -39,10 +34,6 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
|
|
||||||
private final DecoderInputBuffer decoderInputBuffer;
|
private final DecoderInputBuffer decoderInputBuffer;
|
||||||
|
|
||||||
private @MonotonicNonNull SamplePipeline samplePipeline;
|
|
||||||
private boolean muxerWrapperTrackAdded;
|
|
||||||
private boolean muxerWrapperTrackEnded;
|
|
||||||
|
|
||||||
public TransformerAudioRenderer(
|
public TransformerAudioRenderer(
|
||||||
MuxerWrapper muxerWrapper, TransformerMediaClock mediaClock, Transformation transformation) {
|
MuxerWrapper muxerWrapper, TransformerMediaClock mediaClock, Transformation transformation) {
|
||||||
super(C.TRACK_TYPE_AUDIO, muxerWrapper, mediaClock, transformation);
|
super(C.TRACK_TYPE_AUDIO, muxerWrapper, mediaClock, transformation);
|
||||||
@ -55,32 +46,9 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
return TAG;
|
return TAG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Attempts to read the input format and to initialize the sample or passthrough pipeline. */
|
||||||
@Override
|
@Override
|
||||||
public boolean isEnded() {
|
protected boolean ensureConfigured() throws ExoPlaybackException {
|
||||||
return muxerWrapperTrackEnded;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onReset() {
|
|
||||||
if (samplePipeline != null) {
|
|
||||||
samplePipeline.release();
|
|
||||||
}
|
|
||||||
muxerWrapperTrackAdded = false;
|
|
||||||
muxerWrapperTrackEnded = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void render(long positionUs, long elapsedRealtimeUs) throws ExoPlaybackException {
|
|
||||||
if (!isRendererStarted || isEnded() || !ensureRendererConfigured()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (feedMuxerFromPipeline() || samplePipeline.processData() || feedPipelineFromInput()) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Attempts to read the input format and to initialize the sample pipeline. */
|
|
||||||
@EnsuresNonNullIf(expression = "samplePipeline", result = true)
|
|
||||||
private boolean ensureRendererConfigured() throws ExoPlaybackException {
|
|
||||||
if (samplePipeline != null) {
|
if (samplePipeline != null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -100,73 +68,4 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Attempts to write sample pipeline output data to the muxer.
|
|
||||||
*
|
|
||||||
* @return Whether it may be possible to write more data immediately by calling this method again.
|
|
||||||
*/
|
|
||||||
@RequiresNonNull("samplePipeline")
|
|
||||||
private boolean feedMuxerFromPipeline() {
|
|
||||||
if (!muxerWrapperTrackAdded) {
|
|
||||||
@Nullable Format samplePipelineOutputFormat = samplePipeline.getOutputFormat();
|
|
||||||
if (samplePipelineOutputFormat == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
muxerWrapperTrackAdded = true;
|
|
||||||
muxerWrapper.addTrackFormat(samplePipelineOutputFormat);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (samplePipeline.isEnded()) {
|
|
||||||
muxerWrapper.endTrack(getTrackType());
|
|
||||||
muxerWrapperTrackEnded = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
@Nullable DecoderInputBuffer samplePipelineOutputBuffer = samplePipeline.getOutputBuffer();
|
|
||||||
if (samplePipelineOutputBuffer == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!muxerWrapper.writeSample(
|
|
||||||
getTrackType(),
|
|
||||||
checkStateNotNull(samplePipelineOutputBuffer.data),
|
|
||||||
/* isKeyFrame= */ true,
|
|
||||||
samplePipelineOutputBuffer.timeUs)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
samplePipeline.releaseOutputBuffer();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attempts to pass input data to the sample pipeline.
|
|
||||||
*
|
|
||||||
* @return Whether it may be possible to pass more data immediately by calling this method again.
|
|
||||||
*/
|
|
||||||
@RequiresNonNull("samplePipeline")
|
|
||||||
private boolean feedPipelineFromInput() {
|
|
||||||
@Nullable DecoderInputBuffer samplePipelineInputBuffer = samplePipeline.dequeueInputBuffer();
|
|
||||||
if (samplePipelineInputBuffer == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ReadDataResult
|
|
||||||
int result = readSource(getFormatHolder(), samplePipelineInputBuffer, /* readFlags= */ 0);
|
|
||||||
switch (result) {
|
|
||||||
case C.RESULT_BUFFER_READ:
|
|
||||||
if (samplePipelineInputBuffer.isEndOfStream()) {
|
|
||||||
samplePipeline.queueInputBuffer();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
mediaClock.updateTimeForTrackType(getTrackType(), samplePipelineInputBuffer.timeUs);
|
|
||||||
samplePipelineInputBuffer.timeUs -= streamOffsetUs;
|
|
||||||
samplePipelineInputBuffer.flip();
|
|
||||||
samplePipeline.queueInputBuffer();
|
|
||||||
return true;
|
|
||||||
case C.RESULT_FORMAT_READ:
|
|
||||||
throw new IllegalStateException("Format changes are not supported.");
|
|
||||||
case C.RESULT_NOTHING_READ:
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -16,15 +16,23 @@
|
|||||||
|
|
||||||
package androidx.media3.transformer;
|
package androidx.media3.transformer;
|
||||||
|
|
||||||
|
import static androidx.media3.common.util.Assertions.checkStateNotNull;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.RequiresApi;
|
import androidx.annotation.RequiresApi;
|
||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
import androidx.media3.common.Format;
|
import androidx.media3.common.Format;
|
||||||
import androidx.media3.common.MimeTypes;
|
import androidx.media3.common.MimeTypes;
|
||||||
|
import androidx.media3.decoder.DecoderInputBuffer;
|
||||||
import androidx.media3.exoplayer.BaseRenderer;
|
import androidx.media3.exoplayer.BaseRenderer;
|
||||||
import androidx.media3.exoplayer.ExoPlaybackException;
|
import androidx.media3.exoplayer.ExoPlaybackException;
|
||||||
import androidx.media3.exoplayer.MediaClock;
|
import androidx.media3.exoplayer.MediaClock;
|
||||||
import androidx.media3.exoplayer.RendererCapabilities;
|
import androidx.media3.exoplayer.RendererCapabilities;
|
||||||
|
import androidx.media3.exoplayer.source.SampleStream.ReadDataResult;
|
||||||
|
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;
|
||||||
|
|
||||||
@RequiresApi(18)
|
@RequiresApi(18)
|
||||||
/* package */ abstract class TransformerBaseRenderer extends BaseRenderer {
|
/* package */ abstract class TransformerBaseRenderer extends BaseRenderer {
|
||||||
@ -34,7 +42,10 @@ import androidx.media3.exoplayer.RendererCapabilities;
|
|||||||
protected final Transformation transformation;
|
protected final Transformation transformation;
|
||||||
|
|
||||||
protected boolean isRendererStarted;
|
protected boolean isRendererStarted;
|
||||||
|
protected boolean muxerWrapperTrackAdded;
|
||||||
|
protected boolean muxerWrapperTrackEnded;
|
||||||
protected long streamOffsetUs;
|
protected long streamOffsetUs;
|
||||||
|
protected @MonotonicNonNull SamplePipeline samplePipeline;
|
||||||
|
|
||||||
public TransformerBaseRenderer(
|
public TransformerBaseRenderer(
|
||||||
int trackType,
|
int trackType,
|
||||||
@ -47,11 +58,6 @@ import androidx.media3.exoplayer.RendererCapabilities;
|
|||||||
this.transformation = transformation;
|
this.transformation = transformation;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onStreamChanged(Format[] formats, long startPositionUs, long offsetUs) {
|
|
||||||
this.streamOffsetUs = offsetUs;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@C.FormatSupport
|
@C.FormatSupport
|
||||||
public final int supportsFormat(Format format) {
|
public final int supportsFormat(Format format) {
|
||||||
@ -84,6 +90,34 @@ import androidx.media3.exoplayer.RendererCapabilities;
|
|||||||
return mediaClock;
|
return mediaClock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final boolean isEnded() {
|
||||||
|
return muxerWrapperTrackEnded;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void render(long positionUs, long elapsedRealtimeUs) throws ExoPlaybackException {
|
||||||
|
if (!isRendererStarted || isEnded() || !ensureConfigured()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (feedMuxerFromPipeline() || samplePipeline.processData() || feedPipelineFromInput()) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected final void onStreamChanged(Format[] formats, long startPositionUs, long offsetUs) {
|
||||||
|
this.streamOffsetUs = offsetUs;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected final void onReset() {
|
||||||
|
if (samplePipeline != null) {
|
||||||
|
samplePipeline.release();
|
||||||
|
}
|
||||||
|
muxerWrapperTrackAdded = false;
|
||||||
|
muxerWrapperTrackEnded = false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected final void onEnabled(boolean joining, boolean mayRenderStartOfStream) {
|
protected final void onEnabled(boolean joining, boolean mayRenderStartOfStream) {
|
||||||
muxerWrapper.registerTrack();
|
muxerWrapper.registerTrack();
|
||||||
@ -91,7 +125,7 @@ import androidx.media3.exoplayer.RendererCapabilities;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onStarted() throws ExoPlaybackException {
|
protected final void onStarted() {
|
||||||
isRendererStarted = true;
|
isRendererStarted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,4 +133,85 @@ import androidx.media3.exoplayer.RendererCapabilities;
|
|||||||
protected final void onStopped() {
|
protected final void onStopped() {
|
||||||
isRendererStarted = false;
|
isRendererStarted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ForOverride
|
||||||
|
@EnsuresNonNullIf(expression = "samplePipeline", result = true)
|
||||||
|
protected abstract boolean ensureConfigured() throws ExoPlaybackException;
|
||||||
|
|
||||||
|
@RequiresNonNull({"samplePipeline", "#1.data"})
|
||||||
|
protected void maybeQueueSampleToPipeline(DecoderInputBuffer inputBuffer) {
|
||||||
|
samplePipeline.queueInputBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to write sample pipeline output data to the muxer.
|
||||||
|
*
|
||||||
|
* @return Whether it may be possible to write more data immediately by calling this method again.
|
||||||
|
*/
|
||||||
|
@RequiresNonNull("samplePipeline")
|
||||||
|
private boolean feedMuxerFromPipeline() {
|
||||||
|
if (!muxerWrapperTrackAdded) {
|
||||||
|
@Nullable Format samplePipelineOutputFormat = samplePipeline.getOutputFormat();
|
||||||
|
if (samplePipelineOutputFormat == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
muxerWrapperTrackAdded = true;
|
||||||
|
muxerWrapper.addTrackFormat(samplePipelineOutputFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (samplePipeline.isEnded()) {
|
||||||
|
muxerWrapper.endTrack(getTrackType());
|
||||||
|
muxerWrapperTrackEnded = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable DecoderInputBuffer samplePipelineOutputBuffer = samplePipeline.getOutputBuffer();
|
||||||
|
if (samplePipelineOutputBuffer == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!muxerWrapper.writeSample(
|
||||||
|
getTrackType(),
|
||||||
|
checkStateNotNull(samplePipelineOutputBuffer.data),
|
||||||
|
samplePipelineOutputBuffer.isKeyFrame(),
|
||||||
|
samplePipelineOutputBuffer.timeUs)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
samplePipeline.releaseOutputBuffer();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to read input data and pass the input data to the sample pipeline.
|
||||||
|
*
|
||||||
|
* @return Whether it may be possible to read more data immediately by calling this method again.
|
||||||
|
*/
|
||||||
|
@RequiresNonNull("samplePipeline")
|
||||||
|
private boolean feedPipelineFromInput() {
|
||||||
|
@Nullable DecoderInputBuffer samplePipelineInputBuffer = samplePipeline.dequeueInputBuffer();
|
||||||
|
if (samplePipelineInputBuffer == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ReadDataResult
|
||||||
|
int result = readSource(getFormatHolder(), samplePipelineInputBuffer, /* readFlags= */ 0);
|
||||||
|
switch (result) {
|
||||||
|
case C.RESULT_BUFFER_READ:
|
||||||
|
if (samplePipelineInputBuffer.isEndOfStream()) {
|
||||||
|
samplePipeline.queueInputBuffer();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
mediaClock.updateTimeForTrackType(getTrackType(), samplePipelineInputBuffer.timeUs);
|
||||||
|
samplePipelineInputBuffer.timeUs -= streamOffsetUs;
|
||||||
|
samplePipelineInputBuffer.flip();
|
||||||
|
checkStateNotNull(samplePipelineInputBuffer.data);
|
||||||
|
maybeQueueSampleToPipeline(samplePipelineInputBuffer);
|
||||||
|
return true;
|
||||||
|
case C.RESULT_FORMAT_READ:
|
||||||
|
throw new IllegalStateException("Format changes are not supported.");
|
||||||
|
case C.RESULT_NOTHING_READ:
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,11 +17,9 @@
|
|||||||
package androidx.media3.transformer;
|
package androidx.media3.transformer;
|
||||||
|
|
||||||
import static androidx.media3.common.util.Assertions.checkNotNull;
|
import static androidx.media3.common.util.Assertions.checkNotNull;
|
||||||
import static androidx.media3.common.util.Assertions.checkStateNotNull;
|
|
||||||
import static androidx.media3.exoplayer.source.SampleStream.FLAG_REQUIRE_FORMAT;
|
import static androidx.media3.exoplayer.source.SampleStream.FLAG_REQUIRE_FORMAT;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.annotation.RequiresApi;
|
import androidx.annotation.RequiresApi;
|
||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
import androidx.media3.common.Format;
|
import androidx.media3.common.Format;
|
||||||
@ -30,7 +28,6 @@ import androidx.media3.exoplayer.ExoPlaybackException;
|
|||||||
import androidx.media3.exoplayer.FormatHolder;
|
import androidx.media3.exoplayer.FormatHolder;
|
||||||
import androidx.media3.exoplayer.source.SampleStream.ReadDataResult;
|
import androidx.media3.exoplayer.source.SampleStream.ReadDataResult;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf;
|
|
||||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||||
import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||||
|
|
||||||
@ -43,9 +40,6 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
private final DecoderInputBuffer decoderInputBuffer;
|
private final DecoderInputBuffer decoderInputBuffer;
|
||||||
|
|
||||||
private @MonotonicNonNull SefSlowMotionFlattener sefSlowMotionFlattener;
|
private @MonotonicNonNull SefSlowMotionFlattener sefSlowMotionFlattener;
|
||||||
private @MonotonicNonNull SamplePipeline samplePipeline;
|
|
||||||
private boolean muxerWrapperTrackAdded;
|
|
||||||
private boolean muxerWrapperTrackEnded;
|
|
||||||
|
|
||||||
public TransformerVideoRenderer(
|
public TransformerVideoRenderer(
|
||||||
Context context,
|
Context context,
|
||||||
@ -63,32 +57,9 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
return TAG;
|
return TAG;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isEnded() {
|
|
||||||
return muxerWrapperTrackEnded;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onReset() {
|
|
||||||
if (samplePipeline != null) {
|
|
||||||
samplePipeline.release();
|
|
||||||
}
|
|
||||||
muxerWrapperTrackAdded = false;
|
|
||||||
muxerWrapperTrackEnded = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void render(long positionUs, long elapsedRealtimeUs) throws ExoPlaybackException {
|
|
||||||
if (!isRendererStarted || isEnded() || !ensureRendererConfigured()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (feedMuxerFromPipeline() || samplePipeline.processData() || feedPipelineFromInput()) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Attempts to read the input format and to initialize the sample or passthrough pipeline. */
|
/** Attempts to read the input format and to initialize the sample or passthrough pipeline. */
|
||||||
@EnsuresNonNullIf(expression = "samplePipeline", result = true)
|
@Override
|
||||||
private boolean ensureRendererConfigured() throws ExoPlaybackException {
|
protected boolean ensureConfigured() throws ExoPlaybackException {
|
||||||
if (samplePipeline != null) {
|
if (samplePipeline != null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -115,88 +86,19 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempts to write sample pipeline output data to the muxer.
|
* Queues the input buffer to the sample pipeline unless it should be dropped because of slow
|
||||||
*
|
* motion flattening.
|
||||||
* @return Whether it may be possible to write more data immediately by calling this method again.
|
|
||||||
*/
|
*/
|
||||||
@RequiresNonNull("samplePipeline")
|
@Override
|
||||||
private boolean feedMuxerFromPipeline() {
|
@RequiresNonNull({"samplePipeline", "#1.data"})
|
||||||
if (!muxerWrapperTrackAdded) {
|
protected void maybeQueueSampleToPipeline(DecoderInputBuffer inputBuffer) {
|
||||||
@Nullable Format samplePipelineOutputFormat = samplePipeline.getOutputFormat();
|
ByteBuffer data = inputBuffer.data;
|
||||||
if (samplePipelineOutputFormat == null) {
|
boolean shouldDropSample =
|
||||||
return false;
|
sefSlowMotionFlattener != null && sefSlowMotionFlattener.dropOrTransformSample(inputBuffer);
|
||||||
}
|
if (shouldDropSample) {
|
||||||
muxerWrapperTrackAdded = true;
|
data.clear();
|
||||||
muxerWrapper.addTrackFormat(samplePipelineOutputFormat);
|
} else {
|
||||||
}
|
samplePipeline.queueInputBuffer();
|
||||||
|
|
||||||
if (samplePipeline.isEnded()) {
|
|
||||||
muxerWrapper.endTrack(getTrackType());
|
|
||||||
muxerWrapperTrackEnded = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable DecoderInputBuffer samplePipelineOutputBuffer = samplePipeline.getOutputBuffer();
|
|
||||||
if (samplePipelineOutputBuffer == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!muxerWrapper.writeSample(
|
|
||||||
getTrackType(),
|
|
||||||
checkStateNotNull(samplePipelineOutputBuffer.data),
|
|
||||||
samplePipelineOutputBuffer.isKeyFrame(),
|
|
||||||
samplePipelineOutputBuffer.timeUs)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
samplePipeline.releaseOutputBuffer();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attempts to:
|
|
||||||
*
|
|
||||||
* <ol>
|
|
||||||
* <li>read input data,
|
|
||||||
* <li>optionally, apply slow motion flattening, and
|
|
||||||
* <li>pass input data to the sample pipeline.
|
|
||||||
* </ol>
|
|
||||||
*
|
|
||||||
* @return Whether it may be possible to read more data immediately by calling this method again.
|
|
||||||
*/
|
|
||||||
@RequiresNonNull("samplePipeline")
|
|
||||||
private boolean feedPipelineFromInput() {
|
|
||||||
@Nullable DecoderInputBuffer samplePipelineInputBuffer = samplePipeline.dequeueInputBuffer();
|
|
||||||
if (samplePipelineInputBuffer == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ReadDataResult
|
|
||||||
int result = readSource(getFormatHolder(), samplePipelineInputBuffer, /* readFlags= */ 0);
|
|
||||||
switch (result) {
|
|
||||||
case C.RESULT_BUFFER_READ:
|
|
||||||
if (samplePipelineInputBuffer.isEndOfStream()) {
|
|
||||||
samplePipeline.queueInputBuffer();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
mediaClock.updateTimeForTrackType(getTrackType(), samplePipelineInputBuffer.timeUs);
|
|
||||||
samplePipelineInputBuffer.timeUs -= streamOffsetUs;
|
|
||||||
samplePipelineInputBuffer.flip();
|
|
||||||
if (sefSlowMotionFlattener != null) {
|
|
||||||
ByteBuffer data = checkStateNotNull(samplePipelineInputBuffer.data);
|
|
||||||
boolean shouldDropSample =
|
|
||||||
sefSlowMotionFlattener.dropOrTransformSample(samplePipelineInputBuffer);
|
|
||||||
if (shouldDropSample) {
|
|
||||||
data.clear();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
samplePipeline.queueInputBuffer();
|
|
||||||
return true;
|
|
||||||
case C.RESULT_FORMAT_READ:
|
|
||||||
throw new IllegalStateException("Format changes are not supported.");
|
|
||||||
case C.RESULT_NOTHING_READ:
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user