Samples that were discarded by calling {@link #discardUpstreamSamples(int)} are not
+ * considered as having been queued. Samples that were dequeued from the front of the queue are
+ * considered as having been queued.
+ */
+ public synchronized boolean isLastSampleQueued() {
+ return isLastSampleQueued;
+ }
+
/** Returns the timestamp of the first sample, or {@link Long#MIN_VALUE} if the queue is empty. */
public synchronized long getFirstTimestampUs() {
return length == 0 ? Long.MIN_VALUE : timesUs[relativeFirstIndex];
@@ -224,7 +240,7 @@ import com.google.android.exoplayer2.util.Util;
boolean formatRequired, boolean loadingFinished, Format downstreamFormat,
SampleExtrasHolder extrasHolder) {
if (!hasNextSample()) {
- if (loadingFinished) {
+ if (loadingFinished || isLastSampleQueued) {
buffer.setFlags(C.BUFFER_FLAG_END_OF_STREAM);
return C.RESULT_BUFFER_READ;
} else if (upstreamFormat != null
@@ -388,7 +404,9 @@ import com.google.android.exoplayer2.util.Util;
upstreamKeyframeRequired = false;
}
Assertions.checkState(!upstreamFormatRequired);
- commitSampleTimestamp(timeUs);
+
+ isLastSampleQueued = (sampleFlags & C.BUFFER_FLAG_LAST_SAMPLE) != 0;
+ largestQueuedTimestampUs = Math.max(largestQueuedTimestampUs, timeUs);
int relativeEndIndex = getRelativeIndex(length);
timesUs[relativeEndIndex] = timeUs;
@@ -439,10 +457,6 @@ import com.google.android.exoplayer2.util.Util;
}
}
- public synchronized void commitSampleTimestamp(long timeUs) {
- largestQueuedTimestampUs = Math.max(largestQueuedTimestampUs, timeUs);
- }
-
/**
* Attempts to discard samples from the end of the queue to allow samples starting from the
* specified timestamp to be spliced in. Samples will not be discarded prior to the read position.
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/SampleQueue.java b/library/core/src/main/java/com/google/android/exoplayer2/source/SampleQueue.java
index ecc720c656..0886e79d21 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/source/SampleQueue.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/source/SampleQueue.java
@@ -224,6 +224,15 @@ public class SampleQueue implements TrackOutput {
return metadataQueue.getLargestQueuedTimestampUs();
}
+ /**
+ * Returns whether the last sample of the stream has knowingly been queued. A return value of
+ * {@code false} means that the last sample had not been queued or that it's unknown whether the
+ * last sample has been queued.
+ */
+ public boolean isLastSampleQueued() {
+ return metadataQueue.isLastSampleQueued();
+ }
+
/** Returns the timestamp of the first sample, or {@link Long#MIN_VALUE} if the queue is empty. */
public long getFirstTimestampUs() {
return metadataQueue.getFirstTimestampUs();
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaSource.java b/library/core/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaSource.java
index 66097970c7..046672bb77 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaSource.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaSource.java
@@ -318,7 +318,7 @@ public final class SingleSampleMediaSource extends BaseMediaSource {
}
@Override
- public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator) {
+ public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long startPositionUs) {
return new SingleSampleMediaPeriod(
dataSpec,
dataSourceFactory,
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ads/AdsMediaSource.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ads/AdsMediaSource.java
index 19ddbd2c54..4bf661ddc0 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/source/ads/AdsMediaSource.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ads/AdsMediaSource.java
@@ -341,7 +341,7 @@ public final class AdsMediaSource extends CompositeMediaSource
- * If {@code length} is zero then 0 is returned. Otherwise, if no data is available because the
- * end of the opened range has been reached, then {@link C#RESULT_END_OF_INPUT} is returned.
+ *
+ * If {@code readLength} is zero then 0 is returned. Otherwise, if no data is available because
+ * the end of the opened range has been reached, then {@link C#RESULT_END_OF_INPUT} is returned.
* Otherwise, the call will block until at least one byte of data has been read and the number of
* bytes read is returned.
*
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSink.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSink.java
index 8d310015f8..63bc47504b 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSink.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSink.java
@@ -43,8 +43,8 @@ public final class CacheDataSink implements DataSink {
private final Cache cache;
private final long maxCacheFileSize;
private final int bufferSize;
- private final boolean syncFileDescriptor;
+ private boolean syncFileDescriptor;
private DataSpec dataSpec;
private File file;
private OutputStream outputStream;
@@ -64,18 +64,6 @@ public final class CacheDataSink implements DataSink {
}
- /**
- * Constructs a CacheDataSink using the {@link #DEFAULT_BUFFER_SIZE}.
- *
- * @param cache The cache into which data should be written.
- * @param maxCacheFileSize The maximum size of a cache file, in bytes. If the sink is opened for
- * a {@link DataSpec} whose size exceeds this value, then the data will be fragmented into
- * multiple cache files.
- */
- public CacheDataSink(Cache cache, long maxCacheFileSize) {
- this(cache, maxCacheFileSize, DEFAULT_BUFFER_SIZE, true);
- }
-
/**
* Constructs a CacheDataSink using the {@link #DEFAULT_BUFFER_SIZE}.
*
@@ -83,10 +71,9 @@ public final class CacheDataSink implements DataSink {
* @param maxCacheFileSize The maximum size of a cache file, in bytes. If the sink is opened for a
* {@link DataSpec} whose size exceeds this value, then the data will be fragmented into
* multiple cache files.
- * @param syncFileDescriptor Whether file descriptors are sync'd when closing output streams.
*/
- public CacheDataSink(Cache cache, long maxCacheFileSize, boolean syncFileDescriptor) {
- this(cache, maxCacheFileSize, DEFAULT_BUFFER_SIZE, syncFileDescriptor);
+ public CacheDataSink(Cache cache, long maxCacheFileSize) {
+ this(cache, maxCacheFileSize, DEFAULT_BUFFER_SIZE);
}
/**
@@ -98,23 +85,21 @@ public final class CacheDataSink implements DataSink {
* value disables buffering.
*/
public CacheDataSink(Cache cache, long maxCacheFileSize, int bufferSize) {
- this(cache, maxCacheFileSize, bufferSize, true);
- }
-
- /**
- * @param cache The cache into which data should be written.
- * @param maxCacheFileSize The maximum size of a cache file, in bytes. If the sink is opened for a
- * {@link DataSpec} whose size exceeds this value, then the data will be fragmented into
- * multiple cache files.
- * @param bufferSize The buffer size in bytes for writing to a cache file. A zero or negative
- * value disables buffering.
- * @param syncFileDescriptor Whether file descriptors are sync'd when closing output streams.
- */
- public CacheDataSink(
- Cache cache, long maxCacheFileSize, int bufferSize, boolean syncFileDescriptor) {
this.cache = Assertions.checkNotNull(cache);
this.maxCacheFileSize = maxCacheFileSize;
this.bufferSize = bufferSize;
+ syncFileDescriptor = true;
+ }
+
+ /**
+ * Sets whether file descriptors are synced when closing output streams.
+ *
+ * This method is experimental, and will be renamed or removed in a future release. It should
+ * only be called before the renderer is used.
+ *
+ * @param syncFileDescriptor Whether file descriptors are synced when closing output streams.
+ */
+ public void experimental_setSyncFileDescriptor(boolean syncFileDescriptor) {
this.syncFileDescriptor = syncFileDescriptor;
}
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/util/AtomicFile.java b/library/core/src/main/java/com/google/android/exoplayer2/util/AtomicFile.java
index 4bdee5ceea..2466d5a049 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/util/AtomicFile.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/util/AtomicFile.java
@@ -29,7 +29,7 @@ import java.io.OutputStream;
* has successfully completed.
*
* Atomic file guarantees file integrity by ensuring that a file has been completely written and
- * sync'd to disk before removing its backup. As long as the backup file exists, the original file
+ * synced to disk before removing its backup. As long as the backup file exists, the original file
* is considered to be invalid (left over from a previous attempt to write the file).
*
* Atomic file does not confer any file locking semantics. Do not use this class when the file
diff --git a/library/core/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java
index 40b25c2b2e..388aa29ce9 100644
--- a/library/core/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java
+++ b/library/core/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java
@@ -1087,6 +1087,10 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
throws DecoderQueryException {
int maxWidth = format.width;
int maxHeight = format.height;
+ if (codecNeedsMaxVideoSizeResetWorkaround(codecInfo.name)) {
+ maxWidth = Math.max(maxWidth, 1920);
+ maxHeight = Math.max(maxHeight, 1089);
+ }
int maxInputSize = getMaxInputSize(codecInfo, format);
if (streamFormats.length == 1) {
// The single entry in streamFormats must correspond to the format for which the codec is
@@ -1274,6 +1278,18 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
return "NVIDIA".equals(Util.MANUFACTURER);
}
+ /**
+ * Returns whether the codec is known to have problems with the configuration for interlaced
+ * content and needs minimum values for the maximum video size to force reset the configuration.
+ *
+ * See https://github.com/google/ExoPlayer/issues/5003.
+ *
+ * @param name The name of the codec.
+ */
+ private static boolean codecNeedsMaxVideoSizeResetWorkaround(String name) {
+ return "OMX.amlogic.avc.decoder.awesome".equals(name) && Util.SDK_INT <= 25;
+ }
+
/*
* TODO:
*
@@ -1322,7 +1338,8 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
// https://github.com/google/ExoPlayer/issues/4315,
// https://github.com/google/ExoPlayer/issues/4419,
// https://github.com/google/ExoPlayer/issues/4460,
- // https://github.com/google/ExoPlayer/issues/4468.
+ // https://github.com/google/ExoPlayer/issues/4468,
+ // https://github.com/google/ExoPlayer/issues/5312.
switch (Util.DEVICE) {
case "1601":
case "1713":
@@ -1378,6 +1395,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
case "HWBLN-H":
case "HWCAM-H":
case "HWVNS-H":
+ case "HWWAS-H":
case "i9031":
case "iball8735_9806":
case "Infinix-X572":
diff --git a/library/core/src/test/assets/mp4/sample.mp4.0.dump b/library/core/src/test/assets/mp4/sample.mp4.0.dump
index efc804d48b..b05d8250ab 100644
--- a/library/core/src/test/assets/mp4/sample.mp4.0.dump
+++ b/library/core/src/test/assets/mp4/sample.mp4.0.dump
@@ -147,7 +147,7 @@ track 0:
data = length 530, hash C98BC6A8
sample 29:
time = 934266
- flags = 0
+ flags = 536870912
data = length 568, hash 4FE5C8EA
track 1:
format:
@@ -352,6 +352,6 @@ track 1:
data = length 229, hash FFF98DF0
sample 44:
time = 1065678
- flags = 1
+ flags = 536870913
data = length 6, hash 31B22286
tracksEnded = true
diff --git a/library/core/src/test/assets/mp4/sample.mp4.1.dump b/library/core/src/test/assets/mp4/sample.mp4.1.dump
index 10104b5e81..84d86f8ccf 100644
--- a/library/core/src/test/assets/mp4/sample.mp4.1.dump
+++ b/library/core/src/test/assets/mp4/sample.mp4.1.dump
@@ -147,7 +147,7 @@ track 0:
data = length 530, hash C98BC6A8
sample 29:
time = 934266
- flags = 0
+ flags = 536870912
data = length 568, hash 4FE5C8EA
track 1:
format:
@@ -304,6 +304,6 @@ track 1:
data = length 229, hash FFF98DF0
sample 32:
time = 1065678
- flags = 1
+ flags = 536870913
data = length 6, hash 31B22286
tracksEnded = true
diff --git a/library/core/src/test/assets/mp4/sample.mp4.2.dump b/library/core/src/test/assets/mp4/sample.mp4.2.dump
index 8af96be673..9bbe8caa01 100644
--- a/library/core/src/test/assets/mp4/sample.mp4.2.dump
+++ b/library/core/src/test/assets/mp4/sample.mp4.2.dump
@@ -147,7 +147,7 @@ track 0:
data = length 530, hash C98BC6A8
sample 29:
time = 934266
- flags = 0
+ flags = 536870912
data = length 568, hash 4FE5C8EA
track 1:
format:
@@ -244,6 +244,6 @@ track 1:
data = length 229, hash FFF98DF0
sample 17:
time = 1065678
- flags = 1
+ flags = 536870913
data = length 6, hash 31B22286
tracksEnded = true
diff --git a/library/core/src/test/assets/mp4/sample.mp4.3.dump b/library/core/src/test/assets/mp4/sample.mp4.3.dump
index f1259661ed..f210f277b3 100644
--- a/library/core/src/test/assets/mp4/sample.mp4.3.dump
+++ b/library/core/src/test/assets/mp4/sample.mp4.3.dump
@@ -147,7 +147,7 @@ track 0:
data = length 530, hash C98BC6A8
sample 29:
time = 934266
- flags = 0
+ flags = 536870912
data = length 568, hash 4FE5C8EA
track 1:
format:
@@ -184,6 +184,6 @@ track 1:
data = length 229, hash FFF98DF0
sample 2:
time = 1065678
- flags = 1
+ flags = 536870913
data = length 6, hash 31B22286
tracksEnded = true
diff --git a/library/core/src/test/java/com/google/android/exoplayer2/extractor/mp4/MdtaMetadataEntryTest.java b/library/core/src/test/java/com/google/android/exoplayer2/extractor/mp4/MdtaMetadataEntryTest.java
new file mode 100644
index 0000000000..2f81836540
--- /dev/null
+++ b/library/core/src/test/java/com/google/android/exoplayer2/extractor/mp4/MdtaMetadataEntryTest.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2019 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.extractor.mp4;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.os.Parcel;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+/** Test for {@link MdtaMetadataEntry}. */
+@RunWith(RobolectricTestRunner.class)
+public final class MdtaMetadataEntryTest {
+
+ @Test
+ public void testParcelable() {
+ MdtaMetadataEntry mdtaMetadataEntryToParcel =
+ new MdtaMetadataEntry("test", new byte[] {1, 2}, 3, 4);
+
+ Parcel parcel = Parcel.obtain();
+ mdtaMetadataEntryToParcel.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+
+ MdtaMetadataEntry mdtaMetadataEntryFromParcel =
+ MdtaMetadataEntry.CREATOR.createFromParcel(parcel);
+ assertThat(mdtaMetadataEntryFromParcel).isEqualTo(mdtaMetadataEntryToParcel);
+
+ parcel.recycle();
+ }
+}
diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaPeriod.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaPeriod.java
index 5c9a933508..ea5193eae1 100644
--- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaPeriod.java
+++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaPeriod.java
@@ -46,6 +46,7 @@ import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy;
import com.google.android.exoplayer2.upstream.LoaderErrorThrower;
import com.google.android.exoplayer2.upstream.TransferListener;
import com.google.android.exoplayer2.util.MimeTypes;
+import com.google.android.exoplayer2.util.Util;
import java.io.IOException;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
@@ -452,13 +453,22 @@ import java.util.List;
if (adaptationSetSwitchingProperty == null) {
groupedAdaptationSetIndices[groupCount++] = new int[] {i};
} else {
- String[] extraAdaptationSetIds = adaptationSetSwitchingProperty.value.split(",");
+ String[] extraAdaptationSetIds = Util.split(adaptationSetSwitchingProperty.value, ",");
int[] adaptationSetIndices = new int[1 + extraAdaptationSetIds.length];
adaptationSetIndices[0] = i;
+ int outputIndex = 1;
for (int j = 0; j < extraAdaptationSetIds.length; j++) {
- int extraIndex = idToIndexMap.get(Integer.parseInt(extraAdaptationSetIds[j]));
- adaptationSetUsedFlags[extraIndex] = true;
- adaptationSetIndices[1 + j] = extraIndex;
+ int extraIndex =
+ idToIndexMap.get(
+ Integer.parseInt(extraAdaptationSetIds[j]), /* valueIfKeyNotFound= */ -1);
+ if (extraIndex != -1) {
+ adaptationSetUsedFlags[extraIndex] = true;
+ adaptationSetIndices[outputIndex] = extraIndex;
+ outputIndex++;
+ }
+ }
+ if (outputIndex < adaptationSetIndices.length) {
+ adaptationSetIndices = Arrays.copyOf(adaptationSetIndices, outputIndex);
}
groupedAdaptationSetIndices[groupCount++] = adaptationSetIndices;
}
diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaSource.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaSource.java
index c8de8f02b1..c65bfceb39 100644
--- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaSource.java
+++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaSource.java
@@ -635,7 +635,8 @@ public final class DashMediaSource extends BaseMediaSource {
}
@Override
- public MediaPeriod createPeriod(MediaPeriodId periodId, Allocator allocator) {
+ public MediaPeriod createPeriod(
+ MediaPeriodId periodId, Allocator allocator, long startPositionUs) {
int periodIndex = (Integer) periodId.periodUid - firstPeriodId;
EventDispatcher periodEventDispatcher =
createEventDispatcher(periodId, manifest.getPeriod(periodIndex).startMs);
diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DefaultDashChunkSource.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DefaultDashChunkSource.java
index 5e20fb769c..3e51009f20 100644
--- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DefaultDashChunkSource.java
+++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DefaultDashChunkSource.java
@@ -457,10 +457,10 @@ public class DefaultDashChunkSource implements DashChunkSource {
}
private ArrayList See {@link NotificationCompat.Builder#setSubText(CharSequence)}.
+ *
+ * @param player The {@link Player} for which a notification is being built.
+ */
+ @Nullable
+ default String getCurrentSubText(Player player) {
+ return null;
+ }
+
/**
* Gets the large icon for the current media item.
*
@@ -832,6 +844,7 @@ public class PlayerNotificationManager {
// Set media specific notification properties from MediaDescriptionAdapter.
builder.setContentTitle(mediaDescriptionAdapter.getCurrentContentTitle(player));
builder.setContentText(mediaDescriptionAdapter.getCurrentContentText(player));
+ builder.setSubText(mediaDescriptionAdapter.getCurrentSubText(player));
if (largeIcon == null) {
largeIcon =
mediaDescriptionAdapter.getCurrentLargeIcon(
diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerView.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerView.java
index 88eabfed07..83f5b70cbb 100644
--- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerView.java
+++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerView.java
@@ -679,8 +679,9 @@ public class PlayerView extends FrameLayout {
/**
* Sets whether the currently displayed video frame or media artwork is kept visible when the
* player is reset. A player reset is defined to mean the player being re-prepared with different
- * media, {@link Player#stop(boolean)} being called with {@code reset=true}, or the player being
- * replaced or cleared by calling {@link #setPlayer(Player)}.
+ * media, the player transitioning to unprepared media, {@link Player#stop(boolean)} being called
+ * with {@code reset=true}, or the player being replaced or cleared by calling {@link
+ * #setPlayer(Player)}.
*
* If enabled, the currently displayed video frame or media artwork will be kept visible until
* the player set on the view has been successfully prepared with new media and loaded enough of
diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeMediaSource.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeMediaSource.java
index 1f0c0c1a40..999372b90a 100644
--- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeMediaSource.java
+++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeMediaSource.java
@@ -116,7 +116,7 @@ public class FakeMediaSource extends BaseMediaSource {
}
@Override
- public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator) {
+ public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long startPositionUs) {
assertThat(preparedSource).isTrue();
assertThat(releasedSource).isFalse();
int periodIndex = timeline.getIndexOfPeriod(id.periodUid);
diff --git a/testutils_robolectric/src/main/java/com/google/android/exoplayer2/testutil/MediaSourceTestRunner.java b/testutils_robolectric/src/main/java/com/google/android/exoplayer2/testutil/MediaSourceTestRunner.java
index 70e7669dfb..e6fb5bc5f3 100644
--- a/testutils_robolectric/src/main/java/com/google/android/exoplayer2/testutil/MediaSourceTestRunner.java
+++ b/testutils_robolectric/src/main/java/com/google/android/exoplayer2/testutil/MediaSourceTestRunner.java
@@ -142,15 +142,28 @@ public class MediaSourceTestRunner {
}
/**
- * Calls {@link MediaSource#createPeriod(MediaSource.MediaPeriodId, Allocator)} on the playback
- * thread, asserting that a non-null {@link MediaPeriod} is returned.
+ * Calls {@link MediaSource#createPeriod(MediaSource.MediaPeriodId, Allocator, long)} with a zero
+ * start position on the playback thread, asserting that a non-null {@link MediaPeriod} is
+ * returned.
*
* @param periodId The id of the period to create.
* @return The created {@link MediaPeriod}.
*/
public MediaPeriod createPeriod(final MediaPeriodId periodId) {
+ return createPeriod(periodId, /* startPositionUs= */ 0);
+ }
+
+ /**
+ * Calls {@link MediaSource#createPeriod(MediaSource.MediaPeriodId, Allocator, long)} on the
+ * playback thread, asserting that a non-null {@link MediaPeriod} is returned.
+ *
+ * @param periodId The id of the period to create.
+ * @return The created {@link MediaPeriod}.
+ */
+ public MediaPeriod createPeriod(final MediaPeriodId periodId, long startPositionUs) {
final MediaPeriod[] holder = new MediaPeriod[1];
- runOnPlaybackThread(() -> holder[0] = mediaSource.createPeriod(periodId, allocator));
+ runOnPlaybackThread(
+ () -> holder[0] = mediaSource.createPeriod(periodId, allocator, startPositionUs));
assertThat(holder[0]).isNotNull();
return holder[0];
}