Commit 890700fa by aquilescanta Committed by Oliver Woodman

Push formatHolder up to the BaseRenderer class

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