summaryrefslogtreecommitdiff
path: root/tree/library/core/src/test/java/com/google/android/exoplayer2/source/SampleQueueTest.java
diff options
context:
space:
mode:
Diffstat (limited to 'tree/library/core/src/test/java/com/google/android/exoplayer2/source/SampleQueueTest.java')
-rw-r--r--tree/library/core/src/test/java/com/google/android/exoplayer2/source/SampleQueueTest.java1385
1 files changed, 0 insertions, 1385 deletions
diff --git a/tree/library/core/src/test/java/com/google/android/exoplayer2/source/SampleQueueTest.java b/tree/library/core/src/test/java/com/google/android/exoplayer2/source/SampleQueueTest.java
deleted file mode 100644
index 41b953a0..00000000
--- a/tree/library/core/src/test/java/com/google/android/exoplayer2/source/SampleQueueTest.java
+++ /dev/null
@@ -1,1385 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.google.android.exoplayer2.source;
-
-import static com.google.android.exoplayer2.C.BUFFER_FLAG_ENCRYPTED;
-import static com.google.android.exoplayer2.C.BUFFER_FLAG_KEY_FRAME;
-import static com.google.android.exoplayer2.C.RESULT_BUFFER_READ;
-import static com.google.android.exoplayer2.C.RESULT_FORMAT_READ;
-import static com.google.android.exoplayer2.C.RESULT_NOTHING_READ;
-import static com.google.common.truth.Truth.assertThat;
-import static java.lang.Long.MIN_VALUE;
-import static java.util.Arrays.copyOfRange;
-import static org.junit.Assert.assertArrayEquals;
-import static org.mockito.Mockito.when;
-
-import android.os.Looper;
-import androidx.annotation.Nullable;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import com.google.android.exoplayer2.C;
-import com.google.android.exoplayer2.Format;
-import com.google.android.exoplayer2.FormatHolder;
-import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
-import com.google.android.exoplayer2.drm.DrmInitData;
-import com.google.android.exoplayer2.drm.DrmSession;
-import com.google.android.exoplayer2.drm.DrmSessionManager;
-import com.google.android.exoplayer2.extractor.TrackOutput;
-import com.google.android.exoplayer2.testutil.TestUtil;
-import com.google.android.exoplayer2.upstream.Allocator;
-import com.google.android.exoplayer2.upstream.DefaultAllocator;
-import com.google.android.exoplayer2.util.Assertions;
-import com.google.android.exoplayer2.util.MediaSourceEventDispatcher;
-import com.google.android.exoplayer2.util.ParsableByteArray;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.concurrent.atomic.AtomicReference;
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentMatchers;
-import org.mockito.Mockito;
-
-/** Test for {@link SampleQueue}. */
-@RunWith(AndroidJUnit4.class)
-public final class SampleQueueTest {
-
- private static final int ALLOCATION_SIZE = 16;
-
- private static final Format FORMAT_1 = buildFormat(/* id= */ "1");
- private static final Format FORMAT_2 = buildFormat(/* id= */ "2");
- private static final Format FORMAT_1_COPY = buildFormat(/* id= */ "1");
- private static final Format FORMAT_SPLICED = buildFormat(/* id= */ "spliced");
- private static final Format FORMAT_ENCRYPTED =
- new Format.Builder().setId(/* id= */ "encrypted").setDrmInitData(new DrmInitData()).build();
- private static final byte[] DATA = TestUtil.buildTestData(ALLOCATION_SIZE * 10);
-
- /*
- * SAMPLE_SIZES and SAMPLE_OFFSETS are intended to test various boundary cases (with
- * respect to the allocation size). SAMPLE_OFFSETS values are defined as the backward offsets
- * (as expected by SampleQueue.sampleMetadata) assuming that DATA has been written to the
- * sampleQueue in full. The allocations are filled as follows, where | indicates a boundary
- * between allocations and x indicates a byte that doesn't belong to a sample:
- *
- * x<s1>|x<s2>x|x<s3>|<s4>x|<s5>|<s6|s6>|x<s7|s7>x|<s8>
- */
- private static final int[] SAMPLE_SIZES =
- new int[] {
- ALLOCATION_SIZE - 1,
- ALLOCATION_SIZE - 2,
- ALLOCATION_SIZE - 1,
- ALLOCATION_SIZE - 1,
- ALLOCATION_SIZE,
- ALLOCATION_SIZE * 2,
- ALLOCATION_SIZE * 2 - 2,
- ALLOCATION_SIZE
- };
- private static final int[] SAMPLE_OFFSETS =
- new int[] {
- ALLOCATION_SIZE * 9,
- ALLOCATION_SIZE * 8 + 1,
- ALLOCATION_SIZE * 7,
- ALLOCATION_SIZE * 6 + 1,
- ALLOCATION_SIZE * 5,
- ALLOCATION_SIZE * 3,
- ALLOCATION_SIZE + 1,
- 0
- };
- private static final long[] SAMPLE_TIMESTAMPS =
- new long[] {0, 1000, 2000, 3000, 4000, 5000, 6000, 7000};
- private static final long LAST_SAMPLE_TIMESTAMP = SAMPLE_TIMESTAMPS[SAMPLE_TIMESTAMPS.length - 1];
- private static final int[] SAMPLE_FLAGS =
- new int[] {C.BUFFER_FLAG_KEY_FRAME, 0, 0, 0, C.BUFFER_FLAG_KEY_FRAME, 0, 0, 0};
- private static final Format[] SAMPLE_FORMATS =
- new Format[] {FORMAT_1, FORMAT_1, FORMAT_1, FORMAT_1, FORMAT_2, FORMAT_2, FORMAT_2, FORMAT_2};
- private static final int DATA_SECOND_KEYFRAME_INDEX = 4;
-
- private static final int[] ENCRYPTED_SAMPLES_FLAGS =
- new int[] {
- C.BUFFER_FLAG_KEY_FRAME, C.BUFFER_FLAG_ENCRYPTED, 0, C.BUFFER_FLAG_ENCRYPTED,
- };
- private static final long[] ENCRYPTED_SAMPLE_TIMESTAMPS = new long[] {0, 1000, 2000, 3000};
- private static final Format[] ENCRYPTED_SAMPLE_FORMATS =
- new Format[] {FORMAT_ENCRYPTED, FORMAT_ENCRYPTED, FORMAT_1, FORMAT_ENCRYPTED};
- /** Encrypted samples require the encryption preamble. */
- private static final int[] ENCRYPTED_SAMPLE_SIZES = new int[] {1, 3, 1, 3};
-
- private static final int[] ENCRYPTED_SAMPLE_OFFSETS = new int[] {7, 4, 3, 0};
- private static final byte[] ENCRYPTED_SAMPLE_DATA = new byte[] {1, 1, 1, 1, 1, 1, 1, 1};
-
- private static final TrackOutput.CryptoData DUMMY_CRYPTO_DATA =
- new TrackOutput.CryptoData(C.CRYPTO_MODE_AES_CTR, new byte[16], 0, 0);
-
- private Allocator allocator;
- private DrmSessionManager mockDrmSessionManager;
- private DrmSession mockDrmSession;
- private MediaSourceEventDispatcher eventDispatcher;
- private SampleQueue sampleQueue;
- private FormatHolder formatHolder;
- private DecoderInputBuffer inputBuffer;
-
- @Before
- public void setUp() {
- allocator = new DefaultAllocator(false, ALLOCATION_SIZE);
- mockDrmSessionManager = Mockito.mock(DrmSessionManager.class);
- mockDrmSession = Mockito.mock(DrmSession.class);
- when(mockDrmSessionManager.acquireSession(
- ArgumentMatchers.any(), ArgumentMatchers.any(), ArgumentMatchers.any()))
- .thenReturn(mockDrmSession);
- eventDispatcher = new MediaSourceEventDispatcher();
- sampleQueue =
- new SampleQueue(
- allocator,
- /* playbackLooper= */ Assertions.checkNotNull(Looper.myLooper()),
- mockDrmSessionManager,
- eventDispatcher);
- formatHolder = new FormatHolder();
- inputBuffer = new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_NORMAL);
- }
-
- @After
- public void tearDown() {
- allocator = null;
- sampleQueue = null;
- formatHolder = null;
- inputBuffer = null;
- }
-
- @Test
- public void capacityIncreases() {
- int numberOfSamplesToInput = 3 * SampleQueue.SAMPLE_CAPACITY_INCREMENT + 1;
- sampleQueue.format(FORMAT_1);
- sampleQueue.sampleData(
- new ParsableByteArray(numberOfSamplesToInput), /* length= */ numberOfSamplesToInput);
- for (int i = 0; i < numberOfSamplesToInput; i++) {
- sampleQueue.sampleMetadata(
- /* timeUs= */ i * 1000,
- /* flags= */ C.BUFFER_FLAG_KEY_FRAME,
- /* size= */ 1,
- /* offset= */ numberOfSamplesToInput - i - 1,
- /* cryptoData= */ null);
- }
-
- assertReadFormat(/* formatRequired= */ false, FORMAT_1);
- for (int i = 0; i < numberOfSamplesToInput; i++) {
- assertReadSample(
- /* timeUs= */ i * 1000,
- /* isKeyFrame= */ true,
- /* isEncrypted= */ false,
- /* sampleData= */ new byte[1],
- /* offset= */ 0,
- /* length= */ 1);
- }
- assertReadNothing(/* formatRequired= */ false);
- }
-
- @Test
- public void resetReleasesAllocations() {
- writeTestData();
- assertAllocationCount(10);
- sampleQueue.reset();
- assertAllocationCount(0);
- }
-
- @Test
- public void readWithoutWrite() {
- assertNoSamplesToRead(null);
- }
-
- @Test
- public void equalFormatsDeduplicated() {
- sampleQueue.format(FORMAT_1);
- assertReadFormat(false, FORMAT_1);
- // If the same format is written then it should not cause a format change on the read side.
- sampleQueue.format(FORMAT_1);
- assertNoSamplesToRead(FORMAT_1);
- // The same applies for a format that's equal (but a different object).
- sampleQueue.format(FORMAT_1_COPY);
- assertNoSamplesToRead(FORMAT_1);
- }
-
- @Test
- public void multipleFormatsDeduplicated() {
- sampleQueue.format(FORMAT_1);
- sampleQueue.sampleData(new ParsableByteArray(DATA), ALLOCATION_SIZE);
- sampleQueue.sampleMetadata(0, C.BUFFER_FLAG_KEY_FRAME, ALLOCATION_SIZE, 0, null);
- // Writing multiple formats should not cause a format change on the read side, provided the last
- // format to be written is equal to the format of the previous sample.
- sampleQueue.format(FORMAT_2);
- sampleQueue.format(FORMAT_1_COPY);
- sampleQueue.sampleData(new ParsableByteArray(DATA), ALLOCATION_SIZE);
- sampleQueue.sampleMetadata(1000, C.BUFFER_FLAG_KEY_FRAME, ALLOCATION_SIZE, 0, null);
-
- assertReadFormat(false, FORMAT_1);
- assertReadSample(0, true, /* isEncrypted= */ false, DATA, 0, ALLOCATION_SIZE);
- // Assert the second sample is read without a format change.
- assertReadSample(1000, true, /* isEncrypted= */ false, DATA, 0, ALLOCATION_SIZE);
-
- // The same applies if the queue is empty when the formats are written.
- sampleQueue.format(FORMAT_2);
- sampleQueue.format(FORMAT_1);
- sampleQueue.sampleData(new ParsableByteArray(DATA), ALLOCATION_SIZE);
- sampleQueue.sampleMetadata(2000, C.BUFFER_FLAG_KEY_FRAME, ALLOCATION_SIZE, 0, null);
-
- // Assert the third sample is read without a format change.
- assertReadSample(2000, true, /* isEncrypted= */ false, DATA, 0, ALLOCATION_SIZE);
- }
-
- @Test
- public void readSingleSamples() {
- sampleQueue.sampleData(new ParsableByteArray(DATA), ALLOCATION_SIZE);
-
- assertAllocationCount(1);
- // Nothing to read.
- assertNoSamplesToRead(null);
-
- sampleQueue.format(FORMAT_1);
-
- // Read the format.
- assertReadFormat(false, FORMAT_1);
- // Nothing to read.
- assertNoSamplesToRead(FORMAT_1);
-
- sampleQueue.sampleMetadata(1000, C.BUFFER_FLAG_KEY_FRAME, ALLOCATION_SIZE, 0, null);
-
- // If formatRequired, should read the format rather than the sample.
- assertReadFormat(true, FORMAT_1);
- // Otherwise should read the sample.
- assertReadSample(1000, true, /* isEncrypted= */ false, DATA, 0, ALLOCATION_SIZE);
- // Allocation should still be held.
- assertAllocationCount(1);
- sampleQueue.discardToRead();
- // The allocation should have been released.
- assertAllocationCount(0);
-
- // Nothing to read.
- assertNoSamplesToRead(FORMAT_1);
-
- // Write a second sample followed by one byte that does not belong to it.
- sampleQueue.sampleData(new ParsableByteArray(DATA), ALLOCATION_SIZE);
- sampleQueue.sampleMetadata(2000, 0, ALLOCATION_SIZE - 1, 1, null);
-
- // If formatRequired, should read the format rather than the sample.
- assertReadFormat(true, FORMAT_1);
- // Read the sample.
- assertReadSample(2000, false, /* isEncrypted= */ false, DATA, 0, ALLOCATION_SIZE - 1);
- // Allocation should still be held.
- assertAllocationCount(1);
- sampleQueue.discardToRead();
- // The last byte written to the sample queue may belong to a sample whose metadata has yet to be
- // written, so an allocation should still be held.
- assertAllocationCount(1);
-
- // Write metadata for a third sample containing the remaining byte.
- sampleQueue.sampleMetadata(3000, 0, 1, 0, null);
-
- // If formatRequired, should read the format rather than the sample.
- assertReadFormat(true, FORMAT_1);
- // Read the sample.
- assertReadSample(3000, false, /* isEncrypted= */ false, DATA, ALLOCATION_SIZE - 1, 1);
- // Allocation should still be held.
- assertAllocationCount(1);
- sampleQueue.discardToRead();
- // The allocation should have been released.
- assertAllocationCount(0);
- }
-
- @Test
- public void readMultiSamples() {
- writeTestData();
- assertThat(sampleQueue.getLargestQueuedTimestampUs()).isEqualTo(LAST_SAMPLE_TIMESTAMP);
- assertAllocationCount(10);
- assertReadTestData();
- assertAllocationCount(10);
- sampleQueue.discardToRead();
- assertAllocationCount(0);
- }
-
- @Test
- public void readMultiSamplesTwice() {
- writeTestData();
- writeTestData();
- assertAllocationCount(20);
- assertReadTestData(FORMAT_2);
- assertReadTestData(FORMAT_2);
- assertAllocationCount(20);
- sampleQueue.discardToRead();
- assertAllocationCount(0);
- }
-
- @Test
- public void readMultiWithSeek() {
- writeTestData();
- assertReadTestData();
- assertThat(sampleQueue.getFirstIndex()).isEqualTo(0);
- assertThat(sampleQueue.getReadIndex()).isEqualTo(8);
- assertAllocationCount(10);
-
- sampleQueue.seekTo(0);
- assertAllocationCount(10);
- // Read again.
- assertThat(sampleQueue.getFirstIndex()).isEqualTo(0);
- assertThat(sampleQueue.getReadIndex()).isEqualTo(0);
- assertReadTestData();
- }
-
- @Test
- public void emptyQueueReturnsLoadingFinished() {
- sampleQueue.sampleData(new ParsableByteArray(DATA), DATA.length);
- assertThat(sampleQueue.isReady(/* loadingFinished= */ false)).isFalse();
- assertThat(sampleQueue.isReady(/* loadingFinished= */ true)).isTrue();
- }
-
- @Test
- public void isReadyWithUpstreamFormatOnlyReturnsTrue() {
- sampleQueue.format(FORMAT_ENCRYPTED);
- assertThat(sampleQueue.isReady(/* loadingFinished= */ false)).isTrue();
- }
-
- @Test
- public void isReadyReturnsTrueForValidDrmSession() {
- writeTestDataWithEncryptedSections();
- assertReadFormat(/* formatRequired= */ false, FORMAT_ENCRYPTED);
- assertThat(sampleQueue.isReady(/* loadingFinished= */ false)).isFalse();
- when(mockDrmSession.getState()).thenReturn(DrmSession.STATE_OPENED_WITH_KEYS);
- assertThat(sampleQueue.isReady(/* loadingFinished= */ false)).isTrue();
- }
-
- @Test
- public void isReadyReturnsTrueForClearSampleAndPlayClearSamplesWithoutKeysIsTrue() {
- when(mockDrmSession.playClearSamplesWithoutKeys()).thenReturn(true);
- // We recreate the queue to ensure the mock DRM session manager flags are taken into account.
- sampleQueue =
- new SampleQueue(
- allocator,
- /* playbackLooper= */ Assertions.checkNotNull(Looper.myLooper()),
- mockDrmSessionManager,
- eventDispatcher);
- writeTestDataWithEncryptedSections();
- assertThat(sampleQueue.isReady(/* loadingFinished= */ false)).isTrue();
- }
-
- @Test
- public void readEncryptedSectionsWaitsForKeys() {
- when(mockDrmSession.getState()).thenReturn(DrmSession.STATE_OPENED);
- writeTestDataWithEncryptedSections();
-
- assertReadFormat(/* formatRequired= */ false, FORMAT_ENCRYPTED);
- assertReadNothing(/* formatRequired= */ false);
- assertThat(inputBuffer.waitingForKeys).isTrue();
- when(mockDrmSession.getState()).thenReturn(DrmSession.STATE_OPENED_WITH_KEYS);
- assertReadEncryptedSample(/* sampleIndex= */ 0);
- assertThat(inputBuffer.waitingForKeys).isFalse();
- }
-
- @Test
- public void readEncryptedSectionsPopulatesDrmSession() {
- when(mockDrmSession.getState()).thenReturn(DrmSession.STATE_OPENED_WITH_KEYS);
- writeTestDataWithEncryptedSections();
-
- int result =
- sampleQueue.read(
- formatHolder,
- inputBuffer,
- /* formatRequired= */ false,
- /* loadingFinished= */ false,
- /* decodeOnlyUntilUs= */ 0);
- assertThat(result).isEqualTo(RESULT_FORMAT_READ);
- assertThat(formatHolder.drmSession).isSameInstanceAs(mockDrmSession);
- assertReadEncryptedSample(/* sampleIndex= */ 0);
- assertReadEncryptedSample(/* sampleIndex= */ 1);
- formatHolder.clear();
- assertThat(formatHolder.drmSession).isNull();
- result =
- sampleQueue.read(
- formatHolder,
- inputBuffer,
- /* formatRequired= */ false,
- /* loadingFinished= */ false,
- /* decodeOnlyUntilUs= */ 0);
- assertThat(result).isEqualTo(RESULT_FORMAT_READ);
- assertThat(formatHolder.drmSession).isNull();
- assertReadEncryptedSample(/* sampleIndex= */ 2);
- result =
- sampleQueue.read(
- formatHolder,
- inputBuffer,
- /* formatRequired= */ false,
- /* loadingFinished= */ false,
- /* decodeOnlyUntilUs= */ 0);
- assertThat(result).isEqualTo(RESULT_FORMAT_READ);
- assertThat(formatHolder.drmSession).isSameInstanceAs(mockDrmSession);
- }
-
- @Test
- public void allowPlaceholderSessionPopulatesDrmSession() {
- when(mockDrmSession.getState()).thenReturn(DrmSession.STATE_OPENED_WITH_KEYS);
- DrmSession mockPlaceholderDrmSession = Mockito.mock(DrmSession.class);
- when(mockPlaceholderDrmSession.getState()).thenReturn(DrmSession.STATE_OPENED_WITH_KEYS);
- when(mockDrmSessionManager.acquirePlaceholderSession(
- ArgumentMatchers.any(), ArgumentMatchers.anyInt()))
- .thenReturn(mockPlaceholderDrmSession);
- writeTestDataWithEncryptedSections();
-
- int result =
- sampleQueue.read(
- formatHolder,
- inputBuffer,
- /* formatRequired= */ false,
- /* loadingFinished= */ false,
- /* decodeOnlyUntilUs= */ 0);
- assertThat(result).isEqualTo(RESULT_FORMAT_READ);
- assertThat(formatHolder.drmSession).isSameInstanceAs(mockDrmSession);
- assertReadEncryptedSample(/* sampleIndex= */ 0);
- assertReadEncryptedSample(/* sampleIndex= */ 1);
- formatHolder.clear();
- assertThat(formatHolder.drmSession).isNull();
- result =
- sampleQueue.read(
- formatHolder,
- inputBuffer,
- /* formatRequired= */ false,
- /* loadingFinished= */ false,
- /* decodeOnlyUntilUs= */ 0);
- assertThat(result).isEqualTo(RESULT_FORMAT_READ);
- assertThat(formatHolder.drmSession).isSameInstanceAs(mockPlaceholderDrmSession);
- assertReadEncryptedSample(/* sampleIndex= */ 2);
- result =
- sampleQueue.read(
- formatHolder,
- inputBuffer,
- /* formatRequired= */ false,
- /* loadingFinished= */ false,
- /* decodeOnlyUntilUs= */ 0);
- assertThat(result).isEqualTo(RESULT_FORMAT_READ);
- assertThat(formatHolder.drmSession).isSameInstanceAs(mockDrmSession);
- assertReadEncryptedSample(/* sampleIndex= */ 3);
- }
-
- @Test
- public void trailingCryptoInfoInitializationVectorBytesZeroed() {
- when(mockDrmSession.getState()).thenReturn(DrmSession.STATE_OPENED_WITH_KEYS);
- DrmSession mockPlaceholderDrmSession = Mockito.mock(DrmSession.class);
- when(mockPlaceholderDrmSession.getState()).thenReturn(DrmSession.STATE_OPENED_WITH_KEYS);
- when(mockDrmSessionManager.acquirePlaceholderSession(
- ArgumentMatchers.any(), ArgumentMatchers.anyInt()))
- .thenReturn(mockPlaceholderDrmSession);
-
- writeFormat(ENCRYPTED_SAMPLE_FORMATS[0]);
- byte[] sampleData = new byte[] {0, 1, 2};
- byte[] initializationVector = new byte[] {7, 6, 5, 4, 3, 2, 1, 0};
- byte[] encryptedSampleData =
- TestUtil.joinByteArrays(
- new byte[] {
- 0x08, // subsampleEncryption = false (1 bit), ivSize = 8 (7 bits).
- },
- initializationVector,
- sampleData);
- writeSample(
- encryptedSampleData, /* timestampUs= */ 0, BUFFER_FLAG_KEY_FRAME | BUFFER_FLAG_ENCRYPTED);
-
- int result =
- sampleQueue.read(
- formatHolder,
- inputBuffer,
- /* formatRequired= */ false,
- /* loadingFinished= */ false,
- /* decodeOnlyUntilUs= */ 0);
- assertThat(result).isEqualTo(RESULT_FORMAT_READ);
-
- // Fill cryptoInfo.iv with non-zero data. When the 8 byte initialization vector is written into
- // it, we expect the trailing 8 bytes to be zeroed.
- inputBuffer.cryptoInfo.iv = new byte[16];
- Arrays.fill(inputBuffer.cryptoInfo.iv, (byte) 1);
-
- result =
- sampleQueue.read(
- formatHolder,
- inputBuffer,
- /* formatRequired= */ false,
- /* loadingFinished= */ false,
- /* decodeOnlyUntilUs= */ 0);
- assertThat(result).isEqualTo(RESULT_BUFFER_READ);
-
- // Assert cryptoInfo.iv contains the 8-byte initialization vector and that the trailing 8 bytes
- // have been zeroed.
- byte[] expectedInitializationVector = Arrays.copyOf(initializationVector, 16);
- assertArrayEquals(expectedInitializationVector, inputBuffer.cryptoInfo.iv);
- }
-
- @Test
- public void readWithErrorSessionReadsNothingAndThrows() throws IOException {
- when(mockDrmSession.getState()).thenReturn(DrmSession.STATE_OPENED);
- writeTestDataWithEncryptedSections();
-
- assertReadFormat(/* formatRequired= */ false, FORMAT_ENCRYPTED);
- assertReadNothing(/* formatRequired= */ false);
- sampleQueue.maybeThrowError();
- when(mockDrmSession.getState()).thenReturn(DrmSession.STATE_ERROR);
- when(mockDrmSession.getError()).thenReturn(new DrmSession.DrmSessionException(new Exception()));
- assertReadNothing(/* formatRequired= */ false);
- try {
- sampleQueue.maybeThrowError();
- Assert.fail();
- } catch (IOException e) {
- // Expected.
- }
- when(mockDrmSession.getState()).thenReturn(DrmSession.STATE_OPENED_WITH_KEYS);
- assertReadEncryptedSample(/* sampleIndex= */ 0);
- }
-
- @Test
- public void allowPlayClearSamplesWithoutKeysReadsClearSamples() {
- when(mockDrmSession.playClearSamplesWithoutKeys()).thenReturn(true);
- // We recreate the queue to ensure the mock DRM session manager flags are taken into account.
- sampleQueue =
- new SampleQueue(
- allocator,
- /* playbackLooper= */ Assertions.checkNotNull(Looper.myLooper()),
- mockDrmSessionManager,
- eventDispatcher);
- when(mockDrmSession.getState()).thenReturn(DrmSession.STATE_OPENED);
- writeTestDataWithEncryptedSections();
-
- assertReadFormat(/* formatRequired= */ false, FORMAT_ENCRYPTED);
- assertReadEncryptedSample(/* sampleIndex= */ 0);
- }
-
- @Test
- public void seekAfterDiscard() {
- writeTestData();
- assertReadTestData();
- sampleQueue.discardToRead();
- assertThat(sampleQueue.getFirstIndex()).isEqualTo(8);
- assertThat(sampleQueue.getReadIndex()).isEqualTo(8);
- assertAllocationCount(0);
-
- sampleQueue.seekTo(0);
- assertAllocationCount(0);
- // Can't read again.
- assertThat(sampleQueue.getFirstIndex()).isEqualTo(8);
- assertThat(sampleQueue.getReadIndex()).isEqualTo(8);
- assertReadEndOfStream(false);
- }
-
- @Test
- public void advanceToEnd() {
- writeTestData();
- sampleQueue.advanceToEnd();
- assertAllocationCount(10);
- sampleQueue.discardToRead();
- assertAllocationCount(0);
- // Despite skipping all samples, we should still read the last format, since this is the
- // expected format for a subsequent sample.
- assertReadFormat(false, FORMAT_2);
- // Once the format has been read, there's nothing else to read.
- assertNoSamplesToRead(FORMAT_2);
- }
-
- @Test
- public void advanceToEndRetainsUnassignedData() {
- sampleQueue.format(FORMAT_1);
- sampleQueue.sampleData(new ParsableByteArray(DATA), ALLOCATION_SIZE);
- sampleQueue.advanceToEnd();
- assertAllocationCount(1);
- sampleQueue.discardToRead();
- // Skipping shouldn't discard data that may belong to a sample whose metadata has yet to be
- // written.
- assertAllocationCount(1);
- // We should be able to read the format.
- assertReadFormat(false, FORMAT_1);
- // Once the format has been read, there's nothing else to read.
- assertNoSamplesToRead(FORMAT_1);
-
- sampleQueue.sampleMetadata(0, C.BUFFER_FLAG_KEY_FRAME, ALLOCATION_SIZE, 0, null);
- // Once the metadata has been written, check the sample can be read as expected.
- assertReadSample(0, true, /* isEncrypted= */ false, DATA, 0, ALLOCATION_SIZE);
- assertNoSamplesToRead(FORMAT_1);
- assertAllocationCount(1);
- sampleQueue.discardToRead();
- assertAllocationCount(0);
- }
-
- @Test
- public void advanceToBeforeBuffer() {
- writeTestData();
- int skipCount = sampleQueue.advanceTo(SAMPLE_TIMESTAMPS[0] - 1);
- // Should have no effect (we're already at the first frame).
- assertThat(skipCount).isEqualTo(0);
- assertReadTestData();
- assertNoSamplesToRead(FORMAT_2);
- }
-
- @Test
- public void advanceToStartOfBuffer() {
- writeTestData();
- int skipCount = sampleQueue.advanceTo(SAMPLE_TIMESTAMPS[0]);
- // Should have no effect (we're already at the first frame).
- assertThat(skipCount).isEqualTo(0);
- assertReadTestData();
- assertNoSamplesToRead(FORMAT_2);
- }
-
- @Test
- public void advanceToEndOfBuffer() {
- writeTestData();
- int skipCount = sampleQueue.advanceTo(LAST_SAMPLE_TIMESTAMP);
- // Should advance to 2nd keyframe (the 4th frame).
- assertThat(skipCount).isEqualTo(4);
- assertReadTestData(null, DATA_SECOND_KEYFRAME_INDEX);
- assertNoSamplesToRead(FORMAT_2);
- }
-
- @Test
- public void advanceToAfterBuffer() {
- writeTestData();
- int skipCount = sampleQueue.advanceTo(LAST_SAMPLE_TIMESTAMP + 1);
- // Should advance to 2nd keyframe (the 4th frame).
- assertThat(skipCount).isEqualTo(4);
- assertReadTestData(null, DATA_SECOND_KEYFRAME_INDEX);
- assertNoSamplesToRead(FORMAT_2);
- }
-
- @Test
- public void seekToBeforeBuffer() {
- writeTestData();
- boolean success = sampleQueue.seekTo(SAMPLE_TIMESTAMPS[0] - 1, false);
- assertThat(success).isFalse();
- assertThat(sampleQueue.getReadIndex()).isEqualTo(0);
- assertReadTestData();
- assertNoSamplesToRead(FORMAT_2);
- }
-
- @Test
- public void seekToStartOfBuffer() {
- writeTestData();
- boolean success = sampleQueue.seekTo(SAMPLE_TIMESTAMPS[0], false);
- assertThat(success).isTrue();
- assertThat(sampleQueue.getReadIndex()).isEqualTo(0);
- assertReadTestData();
- assertNoSamplesToRead(FORMAT_2);
- }
-
- @Test
- public void seekToEndOfBuffer() {
- writeTestData();
- boolean success = sampleQueue.seekTo(LAST_SAMPLE_TIMESTAMP, false);
- assertThat(success).isTrue();
- assertThat(sampleQueue.getReadIndex()).isEqualTo(4);
- assertReadTestData(null, DATA_SECOND_KEYFRAME_INDEX);
- assertNoSamplesToRead(FORMAT_2);
- }
-
- @Test
- public void seekToAfterBuffer() {
- writeTestData();
- boolean success = sampleQueue.seekTo(LAST_SAMPLE_TIMESTAMP + 1, false);
- assertThat(success).isFalse();
- assertThat(sampleQueue.getReadIndex()).isEqualTo(0);
- assertReadTestData();
- assertNoSamplesToRead(FORMAT_2);
- }
-
- @Test
- public void seekToAfterBufferAllowed() {
- writeTestData();
- boolean success = sampleQueue.seekTo(LAST_SAMPLE_TIMESTAMP + 1, true);
- assertThat(success).isTrue();
- assertThat(sampleQueue.getReadIndex()).isEqualTo(4);
- assertReadTestData(null, DATA_SECOND_KEYFRAME_INDEX);
- assertNoSamplesToRead(FORMAT_2);
- }
-
- @Test
- public void seekToEndAndBackToStart() {
- writeTestData();
- boolean success = sampleQueue.seekTo(LAST_SAMPLE_TIMESTAMP, false);
- assertThat(success).isTrue();
- assertThat(sampleQueue.getReadIndex()).isEqualTo(4);
- assertReadTestData(null, DATA_SECOND_KEYFRAME_INDEX);
- assertNoSamplesToRead(FORMAT_2);
- // Seek back to the start.
- success = sampleQueue.seekTo(SAMPLE_TIMESTAMPS[0], false);
- assertThat(success).isTrue();
- assertThat(sampleQueue.getReadIndex()).isEqualTo(0);
- assertReadTestData();
- assertNoSamplesToRead(FORMAT_2);
- }
-
- @Test
- public void discardToEnd() {
- writeTestData();
- // Should discard everything.
- sampleQueue.discardToEnd();
- assertThat(sampleQueue.getFirstIndex()).isEqualTo(8);
- assertThat(sampleQueue.getReadIndex()).isEqualTo(8);
- assertAllocationCount(0);
- // We should still be able to read the upstream format.
- assertReadFormat(false, FORMAT_2);
- // We should be able to write and read subsequent samples.
- writeTestData();
- assertReadTestData(FORMAT_2);
- }
-
- @Test
- public void discardToStopAtReadPosition() {
- writeTestData();
- // Shouldn't discard anything.
- sampleQueue.discardTo(LAST_SAMPLE_TIMESTAMP, false, true);
- assertThat(sampleQueue.getFirstIndex()).isEqualTo(0);
- assertThat(sampleQueue.getReadIndex()).isEqualTo(0);
- assertAllocationCount(10);
- // Read the first sample.
- assertReadTestData(null, 0, 1);
- // Shouldn't discard anything.
- sampleQueue.discardTo(SAMPLE_TIMESTAMPS[1] - 1, false, true);
- assertThat(sampleQueue.getFirstIndex()).isEqualTo(0);
- assertThat(sampleQueue.getReadIndex()).isEqualTo(1);
- assertAllocationCount(10);
- // Should discard the read sample.
- sampleQueue.discardTo(SAMPLE_TIMESTAMPS[1], false, true);
- assertThat(sampleQueue.getFirstIndex()).isEqualTo(1);
- assertThat(sampleQueue.getReadIndex()).isEqualTo(1);
- assertAllocationCount(9);
- // Shouldn't discard anything.
- sampleQueue.discardTo(LAST_SAMPLE_TIMESTAMP, false, true);
- assertThat(sampleQueue.getFirstIndex()).isEqualTo(1);
- assertThat(sampleQueue.getReadIndex()).isEqualTo(1);
- assertAllocationCount(9);
- // Should be able to read the remaining samples.
- assertReadTestData(FORMAT_1, 1, 7);
- assertThat(sampleQueue.getFirstIndex()).isEqualTo(1);
- assertThat(sampleQueue.getReadIndex()).isEqualTo(8);
- // Should discard up to the second last sample
- sampleQueue.discardTo(LAST_SAMPLE_TIMESTAMP - 1, false, true);
- assertThat(sampleQueue.getFirstIndex()).isEqualTo(6);
- assertThat(sampleQueue.getReadIndex()).isEqualTo(8);
- assertAllocationCount(3);
- // Should discard up the last sample
- sampleQueue.discardTo(LAST_SAMPLE_TIMESTAMP, false, true);
- assertThat(sampleQueue.getFirstIndex()).isEqualTo(7);
- assertThat(sampleQueue.getReadIndex()).isEqualTo(8);
- assertAllocationCount(1);
- }
-
- @Test
- public void discardToDontStopAtReadPosition() {
- writeTestData();
- // Shouldn't discard anything.
- sampleQueue.discardTo(SAMPLE_TIMESTAMPS[1] - 1, false, false);
- assertThat(sampleQueue.getFirstIndex()).isEqualTo(0);
- assertThat(sampleQueue.getReadIndex()).isEqualTo(0);
- assertAllocationCount(10);
- // Should discard the first sample.
- sampleQueue.discardTo(SAMPLE_TIMESTAMPS[1], false, false);
- assertThat(sampleQueue.getFirstIndex()).isEqualTo(1);
- assertThat(sampleQueue.getReadIndex()).isEqualTo(1);
- assertAllocationCount(9);
- // Should be able to read the remaining samples.
- assertReadTestData(FORMAT_1, 1, 7);
- }
-
- @Test
- public void discardUpstream() {
- writeTestData();
- sampleQueue.discardUpstreamSamples(8);
- assertAllocationCount(10);
- sampleQueue.discardUpstreamSamples(7);
- assertAllocationCount(9);
- sampleQueue.discardUpstreamSamples(6);
- assertAllocationCount(7);
- sampleQueue.discardUpstreamSamples(5);
- assertAllocationCount(5);
- sampleQueue.discardUpstreamSamples(4);
- assertAllocationCount(4);
- sampleQueue.discardUpstreamSamples(3);
- assertAllocationCount(3);
- sampleQueue.discardUpstreamSamples(2);
- assertAllocationCount(2);
- sampleQueue.discardUpstreamSamples(1);
- assertAllocationCount(1);
- sampleQueue.discardUpstreamSamples(0);
- assertAllocationCount(0);
- assertReadFormat(false, FORMAT_2);
- assertNoSamplesToRead(FORMAT_2);
- }
-
- @Test
- public void discardUpstreamMulti() {
- writeTestData();
- sampleQueue.discardUpstreamSamples(4);
- assertAllocationCount(4);
- sampleQueue.discardUpstreamSamples(0);
- assertAllocationCount(0);
- assertReadFormat(false, FORMAT_2);
- assertNoSamplesToRead(FORMAT_2);
- }
-
- @Test
- public void discardUpstreamBeforeRead() {
- writeTestData();
- sampleQueue.discardUpstreamSamples(4);
- assertAllocationCount(4);
- assertReadTestData(null, 0, 4);
- assertReadFormat(false, FORMAT_2);
- assertNoSamplesToRead(FORMAT_2);
- }
-
- @Test
- public void discardUpstreamAfterRead() {
- writeTestData();
- assertReadTestData(null, 0, 3);
- sampleQueue.discardUpstreamSamples(8);
- assertAllocationCount(10);
- sampleQueue.discardToRead();
- assertAllocationCount(7);
- sampleQueue.discardUpstreamSamples(7);
- assertAllocationCount(6);
- sampleQueue.discardUpstreamSamples(6);
- assertAllocationCount(4);
- sampleQueue.discardUpstreamSamples(5);
- assertAllocationCount(2);
- sampleQueue.discardUpstreamSamples(4);
- assertAllocationCount(1);
- sampleQueue.discardUpstreamSamples(3);
- assertAllocationCount(0);
- assertReadFormat(false, FORMAT_2);
- assertNoSamplesToRead(FORMAT_2);
- }
-
- @Test
- public void largestQueuedTimestampWithDiscardUpstream() {
- writeTestData();
- assertThat(sampleQueue.getLargestQueuedTimestampUs()).isEqualTo(LAST_SAMPLE_TIMESTAMP);
- sampleQueue.discardUpstreamSamples(SAMPLE_TIMESTAMPS.length - 1);
- // Discarding from upstream should reduce the largest timestamp.
- assertThat(sampleQueue.getLargestQueuedTimestampUs())
- .isEqualTo(SAMPLE_TIMESTAMPS[SAMPLE_TIMESTAMPS.length - 2]);
- sampleQueue.discardUpstreamSamples(0);
- // Discarding everything from upstream without reading should unset the largest timestamp.
- assertThat(sampleQueue.getLargestQueuedTimestampUs()).isEqualTo(MIN_VALUE);
- }
-
- @Test
- public void largestQueuedTimestampWithDiscardUpstreamDecodeOrder() {
- long[] decodeOrderTimestamps = new long[] {0, 3000, 2000, 1000, 4000, 7000, 6000, 5000};
- writeTestData(
- DATA, SAMPLE_SIZES, SAMPLE_OFFSETS, decodeOrderTimestamps, SAMPLE_FORMATS, SAMPLE_FLAGS);
- assertThat(sampleQueue.getLargestQueuedTimestampUs()).isEqualTo(7000);
- sampleQueue.discardUpstreamSamples(SAMPLE_TIMESTAMPS.length - 2);
- // Discarding the last two samples should not change the largest timestamp, due to the decode
- // ordering of the timestamps.
- assertThat(sampleQueue.getLargestQueuedTimestampUs()).isEqualTo(7000);
- sampleQueue.discardUpstreamSamples(SAMPLE_TIMESTAMPS.length - 3);
- // Once a third sample is discarded, the largest timestamp should have changed.
- assertThat(sampleQueue.getLargestQueuedTimestampUs()).isEqualTo(4000);
- sampleQueue.discardUpstreamSamples(0);
- // Discarding everything from upstream without reading should unset the largest timestamp.
- assertThat(sampleQueue.getLargestQueuedTimestampUs()).isEqualTo(MIN_VALUE);
- }
-
- @Test
- public void largestQueuedTimestampWithRead() {
- writeTestData();
- assertThat(sampleQueue.getLargestQueuedTimestampUs()).isEqualTo(LAST_SAMPLE_TIMESTAMP);
- assertReadTestData();
- // Reading everything should not reduce the largest timestamp.
- assertThat(sampleQueue.getLargestQueuedTimestampUs()).isEqualTo(LAST_SAMPLE_TIMESTAMP);
- }
-
- @Test
- public void setSampleOffsetBeforeData() {
- long sampleOffsetUs = 1000;
- sampleQueue.setSampleOffsetUs(sampleOffsetUs);
- writeTestData();
- assertReadTestData(
- /* startFormat= */ null, /* firstSampleIndex= */ 0, /* sampleCount= */ 8, sampleOffsetUs);
- assertReadEndOfStream(/* formatRequired= */ false);
- }
-
- @Test
- public void setSampleOffsetBetweenSamples() {
- writeTestData();
- long sampleOffsetUs = 1000;
- sampleQueue.setSampleOffsetUs(sampleOffsetUs);
-
- // Write a final sample now the offset is set.
- long unadjustedTimestampUs = LAST_SAMPLE_TIMESTAMP + 1234;
- writeSample(DATA, unadjustedTimestampUs, /* sampleFlags= */ 0);
-
- assertReadTestData();
- // We expect to read the format adjusted to account for the sample offset, followed by the final
- // sample and then the end of stream.
- assertReadFormat(
- /* formatRequired= */ false,
- FORMAT_2.buildUpon().setSubsampleOffsetUs(sampleOffsetUs).build());
- assertReadSample(
- unadjustedTimestampUs + sampleOffsetUs,
- /* isKeyFrame= */ false,
- /* isEncrypted= */ false,
- DATA,
- /* offset= */ 0,
- DATA.length);
- assertReadEndOfStream(/* formatRequired= */ false);
- }
-
- @Test
- public void adjustUpstreamFormat() {
- String label = "label";
- sampleQueue =
- new SampleQueue(
- allocator,
- /* playbackLooper= */ Assertions.checkNotNull(Looper.myLooper()),
- mockDrmSessionManager,
- eventDispatcher) {
- @Override
- public Format getAdjustedUpstreamFormat(Format format) {
- return super.getAdjustedUpstreamFormat(copyWithLabel(format, label));
- }
- };
-
- writeFormat(FORMAT_1);
- assertReadFormat(/* formatRequired= */ false, copyWithLabel(FORMAT_1, label));
- assertReadEndOfStream(/* formatRequired= */ false);
- }
-
- @Test
- public void invalidateUpstreamFormatAdjustment() {
- AtomicReference<String> label = new AtomicReference<>("label1");
- sampleQueue =
- new SampleQueue(
- allocator,
- /* playbackLooper= */ Assertions.checkNotNull(Looper.myLooper()),
- mockDrmSessionManager,
- eventDispatcher) {
- @Override
- public Format getAdjustedUpstreamFormat(Format format) {
- return super.getAdjustedUpstreamFormat(copyWithLabel(format, label.get()));
- }
- };
-
- writeFormat(FORMAT_1);
- writeSample(DATA, /* timestampUs= */ 0, BUFFER_FLAG_KEY_FRAME);
-
- // Make a change that'll affect the SampleQueue's format adjustment, and invalidate it.
- label.set("label2");
- sampleQueue.invalidateUpstreamFormatAdjustment();
-
- writeSample(DATA, /* timestampUs= */ 1, /* sampleFlags= */ 0);
-
- assertReadFormat(/* formatRequired= */ false, copyWithLabel(FORMAT_1, "label1"));
- assertReadSample(
- /* timeUs= */ 0,
- /* isKeyFrame= */ true,
- /* isEncrypted= */ false,
- DATA,
- /* offset= */ 0,
- DATA.length);
- assertReadFormat(/* formatRequired= */ false, copyWithLabel(FORMAT_1, "label2"));
- assertReadSample(
- /* timeUs= */ 1,
- /* isKeyFrame= */ false,
- /* isEncrypted= */ false,
- DATA,
- /* offset= */ 0,
- DATA.length);
- assertReadEndOfStream(/* formatRequired= */ false);
- }
-
- @Test
- public void splice() {
- writeTestData();
- sampleQueue.splice();
- // Splice should succeed, replacing the last 4 samples with the sample being written.
- long spliceSampleTimeUs = SAMPLE_TIMESTAMPS[4];
- writeFormat(FORMAT_SPLICED);
- writeSample(DATA, spliceSampleTimeUs, C.BUFFER_FLAG_KEY_FRAME);
- assertReadTestData(null, 0, 4);
- assertReadFormat(false, FORMAT_SPLICED);
- assertReadSample(spliceSampleTimeUs, true, /* isEncrypted= */ false, DATA, 0, DATA.length);
- assertReadEndOfStream(false);
- }
-
- @Test
- public void spliceAfterRead() {
- writeTestData();
- assertReadTestData(null, 0, 4);
- sampleQueue.splice();
- // Splice should fail, leaving the last 4 samples unchanged.
- long spliceSampleTimeUs = SAMPLE_TIMESTAMPS[3];
- writeFormat(FORMAT_SPLICED);
- writeSample(DATA, spliceSampleTimeUs, C.BUFFER_FLAG_KEY_FRAME);
- assertReadTestData(SAMPLE_FORMATS[3], 4, 4);
- assertReadEndOfStream(false);
-
- sampleQueue.seekTo(0);
- assertReadTestData(null, 0, 4);
- sampleQueue.splice();
- // Splice should succeed, replacing the last 4 samples with the sample being written
- spliceSampleTimeUs = SAMPLE_TIMESTAMPS[3] + 1;
- writeFormat(FORMAT_SPLICED);
- writeSample(DATA, spliceSampleTimeUs, C.BUFFER_FLAG_KEY_FRAME);
- assertReadFormat(false, FORMAT_SPLICED);
- assertReadSample(spliceSampleTimeUs, true, /* isEncrypted= */ false, DATA, 0, DATA.length);
- assertReadEndOfStream(false);
- }
-
- @Test
- public void spliceWithSampleOffset() {
- long sampleOffsetUs = 30000;
- sampleQueue.setSampleOffsetUs(sampleOffsetUs);
- writeTestData();
- sampleQueue.splice();
- // Splice should succeed, replacing the last 4 samples with the sample being written.
- long spliceSampleTimeUs = SAMPLE_TIMESTAMPS[4];
- writeFormat(FORMAT_SPLICED);
- writeSample(DATA, spliceSampleTimeUs, C.BUFFER_FLAG_KEY_FRAME);
- assertReadTestData(null, 0, 4, sampleOffsetUs);
- assertReadFormat(
- false, FORMAT_SPLICED.buildUpon().setSubsampleOffsetUs(sampleOffsetUs).build());
- assertReadSample(
- spliceSampleTimeUs + sampleOffsetUs, true, /* isEncrypted= */ false, DATA, 0, DATA.length);
- assertReadEndOfStream(false);
- }
-
- // Internal methods.
-
- /**
- * Writes standard test data to {@code sampleQueue}.
- */
- private void writeTestData() {
- writeTestData(
- DATA, SAMPLE_SIZES, SAMPLE_OFFSETS, SAMPLE_TIMESTAMPS, SAMPLE_FORMATS, SAMPLE_FLAGS);
- }
-
- private void writeTestDataWithEncryptedSections() {
- writeTestData(
- ENCRYPTED_SAMPLE_DATA,
- ENCRYPTED_SAMPLE_SIZES,
- ENCRYPTED_SAMPLE_OFFSETS,
- ENCRYPTED_SAMPLE_TIMESTAMPS,
- ENCRYPTED_SAMPLE_FORMATS,
- ENCRYPTED_SAMPLES_FLAGS);
- }
-
- /**
- * Writes the specified test data to {@code sampleQueue}.
- */
- @SuppressWarnings("ReferenceEquality")
- private void writeTestData(byte[] data, int[] sampleSizes, int[] sampleOffsets,
- long[] sampleTimestamps, Format[] sampleFormats, int[] sampleFlags) {
- sampleQueue.sampleData(new ParsableByteArray(data), data.length);
- Format format = null;
- for (int i = 0; i < sampleTimestamps.length; i++) {
- if (sampleFormats[i] != format) {
- sampleQueue.format(sampleFormats[i]);
- format = sampleFormats[i];
- }
- sampleQueue.sampleMetadata(
- sampleTimestamps[i],
- sampleFlags[i],
- sampleSizes[i],
- sampleOffsets[i],
- (sampleFlags[i] & C.BUFFER_FLAG_ENCRYPTED) != 0 ? DUMMY_CRYPTO_DATA : null);
- }
- }
-
- /** Writes a {@link Format} to the {@code sampleQueue}. */
- private void writeFormat(Format format) {
- sampleQueue.format(format);
- }
-
- /** Writes a single sample to {@code sampleQueue}. */
- private void writeSample(byte[] data, long timestampUs, int sampleFlags) {
- sampleQueue.sampleData(new ParsableByteArray(data), data.length);
- sampleQueue.sampleMetadata(
- timestampUs,
- sampleFlags,
- data.length,
- /* offset= */ 0,
- (sampleFlags & C.BUFFER_FLAG_ENCRYPTED) != 0 ? DUMMY_CRYPTO_DATA : null);
- }
-
- /**
- * Asserts correct reading of standard test data from {@code sampleQueue}.
- */
- private void assertReadTestData() {
- assertReadTestData(null, 0);
- }
-
- /**
- * Asserts correct reading of standard test data from {@code sampleQueue}.
- *
- * @param startFormat The format of the last sample previously read from {@code sampleQueue}.
- */
- private void assertReadTestData(Format startFormat) {
- assertReadTestData(startFormat, 0);
- }
-
- /**
- * Asserts correct reading of standard test data from {@code sampleQueue}.
- *
- * @param startFormat The format of the last sample previously read from {@code sampleQueue}.
- * @param firstSampleIndex The index of the first sample that's expected to be read.
- */
- private void assertReadTestData(Format startFormat, int firstSampleIndex) {
- assertReadTestData(startFormat, firstSampleIndex, SAMPLE_TIMESTAMPS.length - firstSampleIndex);
- }
-
- /**
- * Asserts correct reading of standard test data from {@code sampleQueue}.
- *
- * @param startFormat The format of the last sample previously read from {@code sampleQueue}.
- * @param firstSampleIndex The index of the first sample that's expected to be read.
- * @param sampleCount The number of samples to read.
- */
- private void assertReadTestData(Format startFormat, int firstSampleIndex, int sampleCount) {
- assertReadTestData(startFormat, firstSampleIndex, sampleCount, 0);
- }
-
- /**
- * Asserts correct reading of standard test data from {@code sampleQueue}.
- *
- * @param startFormat The format of the last sample previously read from {@code sampleQueue}.
- * @param firstSampleIndex The index of the first sample that's expected to be read.
- * @param sampleCount The number of samples to read.
- * @param sampleOffsetUs The expected sample offset.
- */
- private void assertReadTestData(
- Format startFormat, int firstSampleIndex, int sampleCount, long sampleOffsetUs) {
- Format format = adjustFormat(startFormat, sampleOffsetUs);
- for (int i = firstSampleIndex; i < firstSampleIndex + sampleCount; i++) {
- // Use equals() on the read side despite using referential equality on the write side, since
- // sampleQueue de-duplicates written formats using equals().
- Format testSampleFormat = adjustFormat(SAMPLE_FORMATS[i], sampleOffsetUs);
- if (!testSampleFormat.equals(format)) {
- // If the format has changed, we should read it.
- assertReadFormat(false, testSampleFormat);
- format = testSampleFormat;
- }
- // If we require the format, we should always read it.
- assertReadFormat(true, testSampleFormat);
- // Assert the sample is as expected.
- assertReadSample(
- SAMPLE_TIMESTAMPS[i] + sampleOffsetUs,
- (SAMPLE_FLAGS[i] & C.BUFFER_FLAG_KEY_FRAME) != 0,
- /* isEncrypted= */ false,
- DATA,
- DATA.length - SAMPLE_OFFSETS[i] - SAMPLE_SIZES[i],
- SAMPLE_SIZES[i]);
- }
- }
-
- /**
- * Asserts {@link SampleQueue#read} is behaving correctly, given there are no samples to read and
- * the last format to be written to the sample queue is {@code endFormat}.
- *
- * @param endFormat The last format to be written to the sample queue, or null of no format has
- * been written.
- */
- private void assertNoSamplesToRead(Format endFormat) {
- // If not formatRequired or loadingFinished, should read nothing.
- assertReadNothing(false);
- // If formatRequired, should read the end format if set, else read nothing.
- if (endFormat == null) {
- assertReadNothing(true);
- } else {
- assertReadFormat(true, endFormat);
- }
- // If loadingFinished, should read end of stream.
- assertReadEndOfStream(false);
- assertReadEndOfStream(true);
- // Having read end of stream should not affect other cases.
- assertReadNothing(false);
- if (endFormat == null) {
- assertReadNothing(true);
- } else {
- assertReadFormat(true, endFormat);
- }
- }
-
- /**
- * Asserts {@link SampleQueue#read} returns {@link C#RESULT_NOTHING_READ}.
- *
- * @param formatRequired The value of {@code formatRequired} passed to {@link SampleQueue#read}.
- */
- private void assertReadNothing(boolean formatRequired) {
- clearFormatHolderAndInputBuffer();
- int result =
- sampleQueue.read(
- formatHolder,
- inputBuffer,
- formatRequired,
- /* loadingFinished= */ false,
- /* decodeOnlyUntilUs= */ 0);
- assertThat(result).isEqualTo(RESULT_NOTHING_READ);
- // formatHolder should not be populated.
- assertThat(formatHolder.format).isNull();
- // inputBuffer should not be populated.
- assertInputBufferContainsNoSampleData();
- assertInputBufferHasNoDefaultFlagsSet();
- }
-
- /**
- * Asserts {@link SampleQueue#read} returns {@link C#RESULT_BUFFER_READ} and that the {@link
- * DecoderInputBuffer#isEndOfStream()} is set.
- *
- * @param formatRequired The value of {@code formatRequired} passed to {@link SampleQueue#read}.
- */
- private void assertReadEndOfStream(boolean formatRequired) {
- clearFormatHolderAndInputBuffer();
- int result =
- sampleQueue.read(
- formatHolder,
- inputBuffer,
- formatRequired,
- /* loadingFinished= */ true,
- /* decodeOnlyUntilUs= */ 0);
- assertThat(result).isEqualTo(RESULT_BUFFER_READ);
- // formatHolder should not be populated.
- assertThat(formatHolder.format).isNull();
- // inputBuffer should not contain sample data, but end of stream flag should be set.
- assertInputBufferContainsNoSampleData();
- assertThat(inputBuffer.isEndOfStream()).isTrue();
- assertThat(inputBuffer.isDecodeOnly()).isFalse();
- assertThat(inputBuffer.isEncrypted()).isFalse();
- }
-
- /**
- * Asserts {@link SampleQueue#read} returns {@link C#RESULT_FORMAT_READ} and that the format
- * holder is filled with a {@link Format} that equals {@code format}.
- *
- * @param formatRequired The value of {@code formatRequired} passed to {@link SampleQueue#read}.
- * @param format The expected format.
- */
- private void assertReadFormat(boolean formatRequired, Format format) {
- clearFormatHolderAndInputBuffer();
- int result =
- sampleQueue.read(
- formatHolder,
- inputBuffer,
- formatRequired,
- /* loadingFinished= */ false,
- /* decodeOnlyUntilUs= */ 0);
- assertThat(result).isEqualTo(RESULT_FORMAT_READ);
- // formatHolder should be populated.
- assertThat(formatHolder.format).isEqualTo(format);
- // inputBuffer should not be populated.
- assertInputBufferContainsNoSampleData();
- assertInputBufferHasNoDefaultFlagsSet();
- }
-
- private void assertReadEncryptedSample(int sampleIndex) {
- byte[] sampleData = new byte[ENCRYPTED_SAMPLE_SIZES[sampleIndex]];
- Arrays.fill(sampleData, (byte) 1);
- boolean isKeyFrame = (ENCRYPTED_SAMPLES_FLAGS[sampleIndex] & C.BUFFER_FLAG_KEY_FRAME) != 0;
- boolean isEncrypted = (ENCRYPTED_SAMPLES_FLAGS[sampleIndex] & C.BUFFER_FLAG_ENCRYPTED) != 0;
- assertReadSample(
- ENCRYPTED_SAMPLE_TIMESTAMPS[sampleIndex],
- isKeyFrame,
- isEncrypted,
- sampleData,
- /* offset= */ 0,
- ENCRYPTED_SAMPLE_SIZES[sampleIndex] - (isEncrypted ? 2 : 0));
- }
-
- /**
- * 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 isEncrypted The expected encrypted 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,
- boolean isEncrypted,
- byte[] sampleData,
- int offset,
- int length) {
- clearFormatHolderAndInputBuffer();
- int result =
- sampleQueue.read(
- formatHolder,
- inputBuffer,
- /* formatRequired= */ false,
- /* loadingFinished= */ false,
- /* decodeOnlyUntilUs= */ 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()).isEqualTo(isEncrypted);
- 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));
- }
-
- /**
- * Asserts the number of allocations currently in use by {@code sampleQueue}.
- *
- * @param count The expected number of allocations.
- */
- private void assertAllocationCount(int count) {
- assertThat(allocator.getTotalBytesAllocated()).isEqualTo(ALLOCATION_SIZE * count);
- }
-
- /**
- * 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);
- }
-
- private void assertInputBufferHasNoDefaultFlagsSet() {
- assertThat(inputBuffer.isEndOfStream()).isFalse();
- assertThat(inputBuffer.isDecodeOnly()).isFalse();
- assertThat(inputBuffer.isEncrypted()).isFalse();
- }
-
- private void clearFormatHolderAndInputBuffer() {
- formatHolder.format = null;
- inputBuffer.clear();
- }
-
- private static Format adjustFormat(@Nullable Format format, long sampleOffsetUs) {
- return format == null || sampleOffsetUs == 0
- ? format
- : format.buildUpon().setSubsampleOffsetUs(sampleOffsetUs).build();
- }
-
- private static Format buildFormat(String id) {
- return new Format.Builder().setId(id).setSubsampleOffsetUs(0).build();
- }
-
- private static Format copyWithLabel(Format format, String label) {
- return format.buildUpon().setLabel(label).build();
- }
-}