/** * Creates a new instance for which {@link #isFlagsOnly()} will return true. * * @return A new flags only input buffer. */ public static DecoderInputBuffer newFlagsOnlyInstance() { return new DecoderInputBuffer(BUFFER_REPLACEMENT_MODE_DISABLED); }
private void releaseInputBufferInternal(I inputBuffer) { inputBuffer.clear(); availableInputBuffers[availableInputBufferCount++] = inputBuffer; }
@Override public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer, boolean formatRequired) { if (eventDispatcher != null && !notifiedDownstreamFormat) { eventDispatcher.downstreamFormatChanged( C.TRACK_TYPE_UNKNOWN, format, C.SELECTION_REASON_UNKNOWN, /* trackSelectionData= */ null, /* mediaTimeUs= */ 0); notifiedDownstreamFormat = true; } if (formatRequired || !readFormat) { formatHolder.format = format; readFormat = true; return C.RESULT_FORMAT_READ; } else if (!readSample) { buffer.timeUs = 0; buffer.ensureSpaceForWrite(1); buffer.data.put((byte) 0); buffer.flip(); readSample = true; return C.RESULT_BUFFER_READ; } else { buffer.setFlags(C.BUFFER_FLAG_END_OF_STREAM); return C.RESULT_BUFFER_READ; } }
@Override public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer, boolean requireFormat) { maybeNotifyDownstreamFormat(); if (streamState == STREAM_STATE_END_OF_STREAM) { buffer.addFlag(C.BUFFER_FLAG_END_OF_STREAM); return C.RESULT_BUFFER_READ; } else if (requireFormat || streamState == STREAM_STATE_SEND_FORMAT) { formatHolder.format = format; streamState = STREAM_STATE_SEND_SAMPLE; return C.RESULT_FORMAT_READ; } else if (loadingFinished) { if (loadingSucceeded) { buffer.timeUs = 0; buffer.addFlag(C.BUFFER_FLAG_KEY_FRAME); buffer.ensureSpaceForWrite(sampleSize); buffer.data.put(sampleData, 0, sampleSize); } else { buffer.addFlag(C.BUFFER_FLAG_END_OF_STREAM); } streamState = STREAM_STATE_END_OF_STREAM; return C.RESULT_BUFFER_READ; } return C.RESULT_NOTHING_READ; }
@Override public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer, boolean formatRequired) { if (formatRequired || !isFormatSentDownstream) { formatHolder.format = upstreamFormat; isFormatSentDownstream = true; return C.RESULT_FORMAT_READ; } if (currentIndex == eventTimesUs.length) { if (!eventStreamAppendable) { buffer.setFlags(C.BUFFER_FLAG_END_OF_STREAM); return C.RESULT_BUFFER_READ; } else { return C.RESULT_NOTHING_READ; } } int sampleIndex = currentIndex++; byte[] serializedEvent = eventMessageEncoder.encode(eventStream.events[sampleIndex], eventStream.timescale); if (serializedEvent != null) { buffer.ensureSpaceForWrite(serializedEvent.length); buffer.setFlags(C.BUFFER_FLAG_KEY_FRAME); buffer.data.put(serializedEvent); buffer.timeUs = eventTimesUs[sampleIndex]; return C.RESULT_BUFFER_READ; } else { return C.RESULT_NOTHING_READ; } }
buffer.clear(); buffer.clear(); codecReconfigurationState = RECONFIGURATION_STATE_WRITE_PENDING; if (buffer.isEndOfStream()) { if (codecReconfigurationState == RECONFIGURATION_STATE_QUEUE_PENDING) { buffer.clear(); codecReconfigurationState = RECONFIGURATION_STATE_WRITE_PENDING; if (waitingForFirstSyncFrame && !buffer.isKeyFrame()) { buffer.clear(); if (codecReconfigurationState == RECONFIGURATION_STATE_QUEUE_PENDING) { boolean bufferEncrypted = buffer.isEncrypted(); waitingForKeys = shouldWaitForKeys(bufferEncrypted); if (waitingForKeys) { if (buffer.isDecodeOnly()) { decodeOnlyPresentationTimestamps.add(presentationTimeUs); buffer.flip(); onQueueInputBuffer(buffer);
@Override public void render(long positionUs, long elapsedRealtimeUs) throws ExoPlaybackException { if (isEnded) { return; } playbackPositionUs = positionUs; while (lastSamplePositionUs < positionUs + SOURCE_READAHEAD_US) { formatHolder.format = null; buffer.clear(); int result = readSource(formatHolder, buffer, false); if (result == C.RESULT_FORMAT_READ) { formatReadCount++; assertThat(expectedFormats).contains(formatHolder.format); onFormatChanged(formatHolder.format); } else if (result == C.RESULT_BUFFER_READ) { if (buffer.isEndOfStream()) { isEnded = true; return; } lastSamplePositionUs = buffer.timeUs; sampleBufferReadCount++; onBufferRead(); } else { Assertions.checkState(result == C.RESULT_NOTHING_READ); return; } } }
inputBuffer.setFlags(C.BUFFER_FLAG_END_OF_STREAM); decoder.queueInputBuffer(inputBuffer); inputBuffer = null; return true; if (inputBuffer.isEndOfStream()) { inputStreamEnded = true; decoder.queueInputBuffer(inputBuffer); return false; boolean bufferEncrypted = inputBuffer.isEncrypted(); waitingForKeys = shouldWaitForKeys(bufferEncrypted); if (waitingForKeys) { return false; inputBuffer.flip(); onQueueInputBuffer(inputBuffer); decoder.queueInputBuffer(inputBuffer);
return C.RESULT_FORMAT_READ; case C.RESULT_BUFFER_READ: if (!buffer.isEndOfStream()) { if (buffer.timeUs < decodeOnlyUntilUs) { buffer.addFlag(C.BUFFER_FLAG_DECODE_ONLY); if (buffer.isEncrypted()) { readEncryptionData(buffer, extrasHolder); buffer.ensureSpaceForWrite(extrasHolder.size); readData(extrasHolder.offset, buffer.data, extrasHolder.size);
private void assertInputBufferHasNoDefaultFlagsSet() { assertThat(inputBuffer.isEndOfStream()).isFalse(); assertThat(inputBuffer.isDecodeOnly()).isFalse(); assertThat(inputBuffer.isEncrypted()).isFalse(); }
@Override public void render(long positionUs, long elapsedRealtimeUs) throws ExoPlaybackException { // 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(); int result = readSource(formatHolder, buffer, /* formatRequired= */ false); if (result != C.RESULT_BUFFER_READ || buffer.isEndOfStream()) { return; } buffer.flip(); lastTimestampUs = buffer.timeUs; if (listener != null) { float[] rotation = parseMetadata(buffer.data); if (rotation != null) { Util.castNonNull(listener).onCameraMotion(lastTimestampUs - offsetUs, rotation); } } } }
/** * Asserts {@link SampleQueue#read} returns {@link C#RESULT_BUFFER_READ} and that the buffer is * filled with the specified sample data. * * @param timeUs The expected buffer timestamp. * @param isKeyframe The expected keyframe flag. * @param sampleData An array containing the expected sample data. * @param offset The offset in {@code sampleData} of the expected sample data. * @param length The length of the expected sample data. */ private void assertReadSample( long timeUs, boolean isKeyframe, byte[] sampleData, int offset, int length) { clearFormatHolderAndInputBuffer(); int result = sampleQueue.read(formatHolder, inputBuffer, false, false, 0); assertThat(result).isEqualTo(RESULT_BUFFER_READ); // formatHolder should not be populated. assertThat(formatHolder.format).isNull(); // inputBuffer should be populated. assertThat(inputBuffer.timeUs).isEqualTo(timeUs); assertThat(inputBuffer.isKeyFrame()).isEqualTo(isKeyframe); assertThat(inputBuffer.isDecodeOnly()).isFalse(); assertThat(inputBuffer.isEncrypted()).isFalse(); inputBuffer.flip(); assertThat(inputBuffer.data.limit()).isEqualTo(length); byte[] readData = new byte[length]; inputBuffer.data.get(readData); assertThat(readData).isEqualTo(copyOfRange(sampleData, offset, offset + length)); }
this.playClearSamplesWithoutKeys = playClearSamplesWithoutKeys; this.assumedMinimumCodecOperatingRate = assumedMinimumCodecOperatingRate; buffer = new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_DISABLED); flagsOnlyBuffer = DecoderInputBuffer.newFlagsOnlyInstance(); formatHolder = new FormatHolder(); formatQueue = new TimedValueQueue<>();
if (inputBuffer.isEndOfStream()) { outputBuffer.addFlag(C.BUFFER_FLAG_END_OF_STREAM); } else { if (inputBuffer.isDecodeOnly()) { outputBuffer.addFlag(C.BUFFER_FLAG_DECODE_ONLY);
if (!hasNextSample()) { if (loadingFinished || isLastSampleQueued) { buffer.setFlags(C.BUFFER_FLAG_END_OF_STREAM); return C.RESULT_BUFFER_READ; } else if (upstreamFormat != null if (buffer.isFlagsOnly()) { return C.RESULT_NOTHING_READ; buffer.setFlags(flags[relativeReadIndex]); extrasHolder.size = sizes[relativeReadIndex]; extrasHolder.offset = offsets[relativeReadIndex];
@Override protected AudioDecoderException decode(DecoderInputBuffer inputBuffer, SimpleOutputBuffer outputBuffer, boolean reset) { if (inputBuffer.isEndOfStream()) { outputBuffer.setFlags(C.BUFFER_FLAG_END_OF_STREAM); } return null; }
@Override public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer, boolean formatRequired) { buffer.setFlags(C.BUFFER_FLAG_END_OF_STREAM); return C.RESULT_BUFFER_READ; }
/** * Sets the initial size of each input buffer. * <p> * This method should only be called before the decoder is used (i.e. before the first call to * {@link #dequeueInputBuffer()}. * * @param size The required input buffer size. */ protected final void setInitialInputBufferSize(int size) { Assertions.checkState(availableInputBufferCount == availableInputBuffers.length); for (I inputBuffer : availableInputBuffers) { inputBuffer.ensureSpaceForWrite(size); } }
/** * Asserts {@code inputBuffer} does not contain any sample data. */ private void assertInputBufferContainsNoSampleData() { if (inputBuffer.data == null) { return; } inputBuffer.flip(); assertThat(inputBuffer.data.limit()).isEqualTo(0); }