diff --git a/library/core/src/main/java/com/google/android/exoplayer2/BaseRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/BaseRenderer.java index f4e51a38a0..6c323deca4 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/BaseRenderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/BaseRenderer.java @@ -34,6 +34,7 @@ import java.io.IOException; public abstract class BaseRenderer implements Renderer, RendererCapabilities { private final int trackType; + private final FormatHolder formatHolder; private RendererConfiguration configuration; private int index; @@ -50,6 +51,7 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities { */ public BaseRenderer(int trackType) { this.trackType = trackType; + formatHolder = new FormatHolder(); readingPositionUs = C.TIME_END_OF_SOURCE; } @@ -157,6 +159,7 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities { @Override public final void disable() { Assertions.checkState(state == STATE_ENABLED); + formatHolder.clear(); state = STATE_DISABLED; stream = null; streamFormats = null; @@ -167,6 +170,7 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities { @Override public final void reset() { Assertions.checkState(state == STATE_DISABLED); + formatHolder.clear(); onReset(); } @@ -275,6 +279,12 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities { // Methods to be called by subclasses. + /** Returns a clear {@link FormatHolder}. */ + protected final FormatHolder getFormatHolder() { + formatHolder.clear(); + return formatHolder; + } + /** Returns the formats of the currently enabled stream. */ protected final Format[] getStreamFormats() { return streamFormats; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/SimpleDecoderAudioRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/SimpleDecoderAudioRenderer.java index e92f1d63db..32516e7dcd 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/audio/SimpleDecoderAudioRenderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/SimpleDecoderAudioRenderer.java @@ -94,7 +94,6 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements private final boolean playClearSamplesWithoutKeys; private final EventDispatcher eventDispatcher; private final AudioSink audioSink; - private final FormatHolder formatHolder; private final DecoderInputBuffer flagsOnlyBuffer; private DecoderCounters decoderCounters; @@ -212,7 +211,6 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements eventDispatcher = new EventDispatcher(eventHandler, eventListener); this.audioSink = audioSink; audioSink.setListener(new AudioSinkListener()); - formatHolder = new FormatHolder(); flagsOnlyBuffer = DecoderInputBuffer.newFlagsOnlyInstance(); decoderReinitializationState = REINITIALIZATION_STATE_NONE; audioTrackNeedsConfigure = true; @@ -270,12 +268,11 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements // Try and read a format if we don't have one already. if (inputFormat == null) { // We don't have a format yet, so try and read one. - formatHolder.clear(); + FormatHolder formatHolder = getFormatHolder(); flagsOnlyBuffer.clear(); int result = readSource(formatHolder, flagsOnlyBuffer, true); if (result == C.RESULT_FORMAT_READ) { onInputFormatChanged(formatHolder); - formatHolder.clear(); } else if (result == C.RESULT_BUFFER_READ) { // End of stream read having not read a format. Assertions.checkState(flagsOnlyBuffer.isEndOfStream()); @@ -440,11 +437,11 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements } int result; + FormatHolder formatHolder = getFormatHolder(); if (waitingForKeys) { // We've already read an encrypted sample into buffer, and are waiting for keys. result = C.RESULT_BUFFER_READ; } else { - formatHolder.clear(); result = readSource(formatHolder, inputBuffer, false); } @@ -453,7 +450,6 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements } if (result == C.RESULT_FORMAT_READ) { onInputFormatChanged(formatHolder); - formatHolder.clear(); return true; } if (inputBuffer.isEndOfStream()) { diff --git a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java index f853339474..f43b1461f8 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java @@ -319,7 +319,6 @@ public abstract class MediaCodecRenderer extends BaseRenderer { private final float assumedMinimumCodecOperatingRate; private final DecoderInputBuffer buffer; private final DecoderInputBuffer flagsOnlyBuffer; - private final FormatHolder formatHolder; private final TimedValueQueue formatQueue; private final ArrayList decodeOnlyPresentationTimestamps; private final MediaCodec.BufferInfo outputBufferInfo; @@ -405,7 +404,6 @@ public abstract class MediaCodecRenderer extends BaseRenderer { this.assumedMinimumCodecOperatingRate = assumedMinimumCodecOperatingRate; buffer = new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_DISABLED); flagsOnlyBuffer = DecoderInputBuffer.newFlagsOnlyInstance(); - formatHolder = new FormatHolder(); formatQueue = new TimedValueQueue<>(); decodeOnlyPresentationTimestamps = new ArrayList<>(); outputBufferInfo = new MediaCodec.BufferInfo(); @@ -769,12 +767,11 @@ public abstract class MediaCodecRenderer extends BaseRenderer { /** Reads into {@link #flagsOnlyBuffer} and returns whether a format was read. */ private boolean readToFlagsOnlyBuffer(boolean requireFormat) throws ExoPlaybackException { - formatHolder.clear(); + FormatHolder formatHolder = getFormatHolder(); flagsOnlyBuffer.clear(); int result = readSource(formatHolder, flagsOnlyBuffer, requireFormat); if (result == C.RESULT_FORMAT_READ) { onInputFormatChanged(formatHolder); - formatHolder.clear(); return true; } else if (result == C.RESULT_BUFFER_READ && flagsOnlyBuffer.isEndOfStream()) { inputStreamEnded = true; @@ -1042,6 +1039,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { } int result; + FormatHolder formatHolder = getFormatHolder(); int adaptiveReconfigurationBytes = 0; if (waitingForKeys) { // We've already read an encrypted sample into buffer, and are waiting for keys. @@ -1057,7 +1055,6 @@ public abstract class MediaCodecRenderer extends BaseRenderer { codecReconfigurationState = RECONFIGURATION_STATE_QUEUE_PENDING; } adaptiveReconfigurationBytes = buffer.data.position(); - formatHolder.clear(); result = readSource(formatHolder, buffer, false); } @@ -1077,7 +1074,6 @@ public abstract class MediaCodecRenderer extends BaseRenderer { codecReconfigurationState = RECONFIGURATION_STATE_WRITE_PENDING; } onInputFormatChanged(formatHolder); - formatHolder.clear(); return true; } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/metadata/MetadataRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/metadata/MetadataRenderer.java index d162164f79..d738a8662e 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/metadata/MetadataRenderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/metadata/MetadataRenderer.java @@ -45,7 +45,6 @@ public final class MetadataRenderer extends BaseRenderer implements Callback { private final MetadataDecoderFactory decoderFactory; private final MetadataOutput output; @Nullable private final Handler outputHandler; - private final FormatHolder formatHolder; private final MetadataInputBuffer buffer; private final Metadata[] pendingMetadata; private final long[] pendingMetadataTimestamps; @@ -84,7 +83,6 @@ public final class MetadataRenderer extends BaseRenderer implements Callback { this.outputHandler = outputLooper == null ? null : Util.createHandler(outputLooper, /* callback= */ this); this.decoderFactory = Assertions.checkNotNull(decoderFactory); - formatHolder = new FormatHolder(); buffer = new MetadataInputBuffer(); pendingMetadata = new Metadata[MAX_PENDING_METADATA_COUNT]; pendingMetadataTimestamps = new long[MAX_PENDING_METADATA_COUNT]; @@ -114,7 +112,7 @@ public final class MetadataRenderer extends BaseRenderer implements Callback { public void render(long positionUs, long elapsedRealtimeUs) throws ExoPlaybackException { if (!inputStreamEnded && pendingMetadataCount < MAX_PENDING_METADATA_COUNT) { buffer.clear(); - formatHolder.clear(); + FormatHolder formatHolder = getFormatHolder(); int result = readSource(formatHolder, buffer, false); if (result == C.RESULT_BUFFER_READ) { if (buffer.isEndOfStream()) { @@ -142,7 +140,6 @@ public final class MetadataRenderer extends BaseRenderer implements Callback { } } else if (result == C.RESULT_FORMAT_READ) { subsampleOffsetUs = formatHolder.format.subsampleOffsetUs; - formatHolder.clear(); } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/video/SimpleDecoderVideoRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/video/SimpleDecoderVideoRenderer.java index 048f9cbf0f..e8d63dd617 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/video/SimpleDecoderVideoRenderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/video/SimpleDecoderVideoRenderer.java @@ -73,7 +73,6 @@ public abstract class SimpleDecoderVideoRenderer extends BaseRenderer { private final int maxDroppedFramesToNotify; private final boolean playClearSamplesWithoutKeys; private final EventDispatcher eventDispatcher; - private final FormatHolder formatHolder; private final TimedValueQueue formatQueue; private final DecoderInputBuffer flagsOnlyBuffer; private final DrmSessionManager drmSessionManager; @@ -144,7 +143,6 @@ public abstract class SimpleDecoderVideoRenderer extends BaseRenderer { this.playClearSamplesWithoutKeys = playClearSamplesWithoutKeys; joiningDeadlineMs = C.TIME_UNSET; clearReportedVideoSize(); - formatHolder = new FormatHolder(); formatQueue = new TimedValueQueue<>(); flagsOnlyBuffer = DecoderInputBuffer.newFlagsOnlyInstance(); eventDispatcher = new EventDispatcher(eventHandler, eventListener); @@ -166,12 +164,11 @@ public abstract class SimpleDecoderVideoRenderer extends BaseRenderer { if (inputFormat == null) { // We don't have a format yet, so try and read one. - formatHolder.clear(); + FormatHolder formatHolder = getFormatHolder(); flagsOnlyBuffer.clear(); int result = readSource(formatHolder, flagsOnlyBuffer, true); if (result == C.RESULT_FORMAT_READ) { onInputFormatChanged(formatHolder); - formatHolder.clear(); } else if (result == C.RESULT_BUFFER_READ) { // End of stream read having not read a format. Assertions.checkState(flagsOnlyBuffer.isEndOfStream()); @@ -680,11 +677,11 @@ public abstract class SimpleDecoderVideoRenderer extends BaseRenderer { } int result; + FormatHolder formatHolder = getFormatHolder(); if (waitingForKeys) { // We've already read an encrypted sample into buffer, and are waiting for keys. result = C.RESULT_BUFFER_READ; } else { - formatHolder.clear(); result = readSource(formatHolder, inputBuffer, false); } @@ -693,7 +690,6 @@ public abstract class SimpleDecoderVideoRenderer extends BaseRenderer { } if (result == C.RESULT_FORMAT_READ) { onInputFormatChanged(formatHolder); - formatHolder.clear(); return true; } if (inputBuffer.isEndOfStream()) { diff --git a/library/core/src/main/java/com/google/android/exoplayer2/video/spherical/CameraMotionRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/video/spherical/CameraMotionRenderer.java index 9384d32a6f..d1cf0abc56 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/video/spherical/CameraMotionRenderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/video/spherical/CameraMotionRenderer.java @@ -34,7 +34,6 @@ public class CameraMotionRenderer extends BaseRenderer { // The amount of time to read samples ahead of the current time. private static final int SAMPLE_WINDOW_DURATION_US = 100000; - private final FormatHolder formatHolder; private final DecoderInputBuffer buffer; private final ParsableByteArray scratch; @@ -44,7 +43,6 @@ public class CameraMotionRenderer extends BaseRenderer { public CameraMotionRenderer() { super(C.TRACK_TYPE_CAMERA_MOTION); - formatHolder = new FormatHolder(); buffer = new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_NORMAL); scratch = new ParsableByteArray(); } @@ -85,10 +83,9 @@ public class CameraMotionRenderer extends BaseRenderer { // Keep reading available samples as long as the sample time is not too far into the future. while (!hasReadStreamToEnd() && lastTimestampUs < positionUs + SAMPLE_WINDOW_DURATION_US) { buffer.clear(); - formatHolder.clear(); + FormatHolder formatHolder = getFormatHolder(); int result = readSource(formatHolder, buffer, /* formatRequired= */ false); if (result != C.RESULT_BUFFER_READ || buffer.isEndOfStream()) { - formatHolder.clear(); return; } diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeRenderer.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeRenderer.java index 499aa1ec9e..39d3d8f7f4 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeRenderer.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeRenderer.java @@ -45,7 +45,6 @@ public class FakeRenderer extends BaseRenderer { private final List expectedFormats; private final DecoderInputBuffer buffer; - private final FormatHolder formatHolder; private long playbackPositionUs; private long lastSamplePositionUs; @@ -60,7 +59,6 @@ public class FakeRenderer extends BaseRenderer { : MimeTypes.getTrackType(expectedFormats[0].sampleMimeType)); this.expectedFormats = Collections.unmodifiableList(Arrays.asList(expectedFormats)); buffer = new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_NORMAL); - formatHolder = new FormatHolder(); lastSamplePositionUs = Long.MIN_VALUE; } @@ -79,14 +77,13 @@ public class FakeRenderer extends BaseRenderer { } playbackPositionUs = positionUs; while (lastSamplePositionUs < positionUs + SOURCE_READAHEAD_US) { - formatHolder.clear(); + FormatHolder formatHolder = getFormatHolder(); buffer.clear(); int result = readSource(formatHolder, buffer, false); if (result == C.RESULT_FORMAT_READ) { formatReadCount++; assertThat(expectedFormats).contains(formatHolder.format); onFormatChanged(formatHolder.format); - formatHolder.clear(); } else if (result == C.RESULT_BUFFER_READ) { if (buffer.isEndOfStream()) { isEnded = true;