From 9d947a56f837cd7698c59b229baca9860bb61172 Mon Sep 17 00:00:00 2001 From: eguven Date: Wed, 31 Oct 2018 07:57:14 -0700 Subject: [PATCH] Add MediaChunkListIterator ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=219472988 --- .../source/chunk/BaseMediaChunkIterator.java | 4 +- .../source/chunk/MediaChunkListIterator.java | 61 +++++++++++++++ .../chunk/MediaChunkListIteratorTest.java | 76 +++++++++++++++++++ .../AdaptiveTrackSelectionTest.java | 38 +--------- .../exoplayer2/testutil/FakeMediaChunk.java | 58 ++++++++++++++ 5 files changed, 198 insertions(+), 39 deletions(-) create mode 100644 library/core/src/main/java/com/google/android/exoplayer2/source/chunk/MediaChunkListIterator.java create mode 100644 library/core/src/test/java/com/google/android/exoplayer2/source/chunk/MediaChunkListIteratorTest.java create mode 100644 testutils_robolectric/src/main/java/com/google/android/exoplayer2/testutil/FakeMediaChunk.java diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/BaseMediaChunkIterator.java b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/BaseMediaChunkIterator.java index 4c1462babf..e506cac675 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/BaseMediaChunkIterator.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/BaseMediaChunkIterator.java @@ -56,14 +56,14 @@ public abstract class BaseMediaChunkIterator implements MediaChunkIterator { * * @throws NoSuchElementException If the iterator does not point to a valid element. */ - protected void checkInBounds() { + protected final void checkInBounds() { if (currentIndex < fromIndex || currentIndex > toIndex) { throw new NoSuchElementException(); } } /** Returns the current index this iterator is pointing to. */ - protected long getCurrentIndex() { + protected final long getCurrentIndex() { return currentIndex; } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/MediaChunkListIterator.java b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/MediaChunkListIterator.java new file mode 100644 index 0000000000..ca64e1affd --- /dev/null +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/MediaChunkListIterator.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2018 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.chunk; + +import com.google.android.exoplayer2.upstream.DataSpec; +import java.util.List; + +/** A {@link MediaChunkIterator} which iterates over a {@link List} of {@link MediaChunk}s. */ +public final class MediaChunkListIterator extends BaseMediaChunkIterator { + + private final List chunks; + private final boolean reverseOrder; + + /** + * Creates iterator. + * + * @param chunks The list of chunks to iterate over. + * @param reverseOrder Whether to iterate in reverse order. + */ + public MediaChunkListIterator(List chunks, boolean reverseOrder) { + super(0, chunks.size() - 1); + this.chunks = chunks; + this.reverseOrder = reverseOrder; + } + + @Override + public DataSpec getDataSpec() { + return getCurrentChunk().dataSpec; + } + + @Override + public long getChunkStartTimeUs() { + return getCurrentChunk().startTimeUs; + } + + @Override + public long getChunkEndTimeUs() { + return getCurrentChunk().endTimeUs; + } + + private MediaChunk getCurrentChunk() { + int index = (int) super.getCurrentIndex(); + if (reverseOrder) { + index = chunks.size() - 1 - index; + } + return chunks.get(index); + } +} diff --git a/library/core/src/test/java/com/google/android/exoplayer2/source/chunk/MediaChunkListIteratorTest.java b/library/core/src/test/java/com/google/android/exoplayer2/source/chunk/MediaChunkListIteratorTest.java new file mode 100644 index 0000000000..590c06f3d5 --- /dev/null +++ b/library/core/src/test/java/com/google/android/exoplayer2/source/chunk/MediaChunkListIteratorTest.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2018 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.chunk; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.android.exoplayer2.Format; +import com.google.android.exoplayer2.testutil.FakeMediaChunk; +import java.util.Arrays; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; + +/** Tests for {@link MediaChunkListIterator}. */ +@RunWith(RobolectricTestRunner.class) +public class MediaChunkListIteratorTest { + + private static final Format TEST_FORMAT = Format.createSampleFormat(null, null, 0); + + private FakeMediaChunk testChunk1; + private FakeMediaChunk testChunk2; + + @Before + public void setUp() { + testChunk1 = new FakeMediaChunk(TEST_FORMAT, 0, 10); + testChunk2 = new FakeMediaChunk(TEST_FORMAT, 10, 20); + } + + @Test + public void iterator_reverseOrderFalse_returnsItemsInNormalOrder() { + MediaChunkListIterator iterator = + new MediaChunkListIterator( + Arrays.asList(testChunk1, testChunk2), /* reverseOrder= */ false); + assertThat(iterator.isEnded()).isFalse(); + assertThat(iterator.next()).isTrue(); + assertEqual(iterator, testChunk1); + assertThat(iterator.next()).isTrue(); + assertEqual(iterator, testChunk2); + assertThat(iterator.next()).isFalse(); + assertThat(iterator.isEnded()).isTrue(); + } + + @Test + public void iterator_reverseOrderTrue_returnsItemsInReverseOrder() { + MediaChunkListIterator iterator = + new MediaChunkListIterator( + Arrays.asList(testChunk1, testChunk2), /* reverseOrder= */ true); + assertThat(iterator.isEnded()).isFalse(); + assertThat(iterator.next()).isTrue(); + assertEqual(iterator, testChunk2); + assertThat(iterator.next()).isTrue(); + assertEqual(iterator, testChunk1); + assertThat(iterator.next()).isFalse(); + assertThat(iterator.isEnded()).isTrue(); + } + + private static void assertEqual(MediaChunkListIterator iterator, FakeMediaChunk chunk) { + assertThat(iterator.getChunkStartTimeUs()).isEqualTo(chunk.startTimeUs); + assertThat(iterator.getChunkEndTimeUs()).isEqualTo(chunk.endTimeUs); + assertThat(iterator.getDataSpec()).isEqualTo(chunk.dataSpec); + } +} diff --git a/library/core/src/test/java/com/google/android/exoplayer2/trackselection/AdaptiveTrackSelectionTest.java b/library/core/src/test/java/com/google/android/exoplayer2/trackselection/AdaptiveTrackSelectionTest.java index 3ddc809ca4..dcad02fef1 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/trackselection/AdaptiveTrackSelectionTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/trackselection/AdaptiveTrackSelectionTest.java @@ -23,19 +23,14 @@ import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.initMocks; -import android.net.Uri; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.source.TrackGroup; -import com.google.android.exoplayer2.source.chunk.MediaChunk; import com.google.android.exoplayer2.source.chunk.MediaChunkIterator; import com.google.android.exoplayer2.testutil.FakeClock; +import com.google.android.exoplayer2.testutil.FakeMediaChunk; import com.google.android.exoplayer2.upstream.BandwidthMeter; -import com.google.android.exoplayer2.upstream.DataSource; -import com.google.android.exoplayer2.upstream.DataSpec; -import com.google.android.exoplayer2.upstream.DefaultHttpDataSource; import com.google.android.exoplayer2.util.MimeTypes; -import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -409,35 +404,4 @@ public final class AdaptiveTrackSelectionTest { /* drmInitData= */ null); } - private static final class FakeMediaChunk extends MediaChunk { - - private static final DataSource DATA_SOURCE = new DefaultHttpDataSource("TEST_AGENT", null); - - public FakeMediaChunk(Format trackFormat, long startTimeUs, long endTimeUs) { - super( - DATA_SOURCE, - new DataSpec(Uri.EMPTY), - trackFormat, - C.SELECTION_REASON_ADAPTIVE, - null, - startTimeUs, - endTimeUs, - 0); - } - - @Override - public void cancelLoad() { - // Do nothing. - } - - @Override - public void load() throws IOException, InterruptedException { - // Do nothing. - } - - @Override - public boolean isLoadCompleted() { - return true; - } - } } diff --git a/testutils_robolectric/src/main/java/com/google/android/exoplayer2/testutil/FakeMediaChunk.java b/testutils_robolectric/src/main/java/com/google/android/exoplayer2/testutil/FakeMediaChunk.java new file mode 100644 index 0000000000..8740e3e57f --- /dev/null +++ b/testutils_robolectric/src/main/java/com/google/android/exoplayer2/testutil/FakeMediaChunk.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2018 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.testutil; + +import android.net.Uri; +import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.Format; +import com.google.android.exoplayer2.source.chunk.MediaChunk; +import com.google.android.exoplayer2.upstream.DataSource; +import com.google.android.exoplayer2.upstream.DataSpec; +import com.google.android.exoplayer2.upstream.DefaultHttpDataSource; +import java.io.IOException; + +/** Fake {@link MediaChunk}. */ +public final class FakeMediaChunk extends MediaChunk { + + private static final DataSource DATA_SOURCE = new DefaultHttpDataSource("TEST_AGENT", null); + + public FakeMediaChunk(Format trackFormat, long startTimeUs, long endTimeUs) { + super( + DATA_SOURCE, + new DataSpec(Uri.EMPTY), + trackFormat, + C.SELECTION_REASON_ADAPTIVE, + /* trackSelectionData= */ null, + startTimeUs, + endTimeUs, + /* chunkIndex= */ 0); + } + + @Override + public void cancelLoad() { + // Do nothing. + } + + @Override + public void load() throws IOException, InterruptedException { + // Do nothing. + } + + @Override + public boolean isLoadCompleted() { + return true; + } +}