/** * 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); }
@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 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 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)); }
buffer.flip(); onQueueInputBuffer(buffer);
return false; inputBuffer.flip(); onQueueInputBuffer(inputBuffer); decoder.queueInputBuffer(inputBuffer);