Commit 1506b6d2 by olly Committed by Oliver Woodman

Pragmatic fix for Concat(source1, Looping(source2))

Issue: #2680

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=153827243
parent 3280dc87
...@@ -20,6 +20,7 @@ import com.google.android.exoplayer2.C; ...@@ -20,6 +20,7 @@ import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
...@@ -152,12 +153,14 @@ public final class ConcatenatingMediaSource implements MediaSource { ...@@ -152,12 +153,14 @@ public final class ConcatenatingMediaSource implements MediaSource {
public ConcatenatedTimeline(Timeline[] timelines) { public ConcatenatedTimeline(Timeline[] timelines) {
int[] sourcePeriodOffsets = new int[timelines.length]; int[] sourcePeriodOffsets = new int[timelines.length];
int[] sourceWindowOffsets = new int[timelines.length]; int[] sourceWindowOffsets = new int[timelines.length];
int periodCount = 0; long periodCount = 0;
int windowCount = 0; int windowCount = 0;
for (int i = 0; i < timelines.length; i++) { for (int i = 0; i < timelines.length; i++) {
Timeline timeline = timelines[i]; Timeline timeline = timelines[i];
periodCount += timeline.getPeriodCount(); periodCount += timeline.getPeriodCount();
sourcePeriodOffsets[i] = periodCount; Assertions.checkState(periodCount <= Integer.MAX_VALUE,
"ConcatenatingMediaSource children contain too many periods");
sourcePeriodOffsets[i] = (int) periodCount;
windowCount += timeline.getWindowCount(); windowCount += timeline.getWindowCount();
sourceWindowOffsets[i] = windowCount; sourceWindowOffsets[i] = windowCount;
} }
......
...@@ -29,6 +29,13 @@ import java.io.IOException; ...@@ -29,6 +29,13 @@ import java.io.IOException;
*/ */
public final class LoopingMediaSource implements MediaSource { public final class LoopingMediaSource implements MediaSource {
/**
* The maximum number of periods that can be exposed by the source. The value of this constant is
* large enough to cause indefinite looping in practice (the total duration of the looping source
* will be approximately five years if the duration of each period is one second).
*/
public static final int MAX_EXPOSED_PERIODS = 157680000;
private static final String TAG = "LoopingMediaSource"; private static final String TAG = "LoopingMediaSource";
private final MediaSource childSource; private final MediaSource childSource;
...@@ -50,8 +57,8 @@ public final class LoopingMediaSource implements MediaSource { ...@@ -50,8 +57,8 @@ public final class LoopingMediaSource implements MediaSource {
* *
* @param childSource The {@link MediaSource} to loop. * @param childSource The {@link MediaSource} to loop.
* @param loopCount The desired number of loops. Must be strictly positive. The actual number of * @param loopCount The desired number of loops. Must be strictly positive. The actual number of
* loops will be capped at the maximum value that can achieved without causing the number of * loops will be capped at the maximum that can achieved without causing the number of
* periods exposed by the source to exceed {@link Integer#MAX_VALUE}. * periods exposed by the source to exceed {@link #MAX_EXPOSED_PERIODS}.
*/ */
public LoopingMediaSource(MediaSource childSource, int loopCount) { public LoopingMediaSource(MediaSource childSource, int loopCount) {
Assertions.checkArgument(loopCount > 0); Assertions.checkArgument(loopCount > 0);
...@@ -101,8 +108,9 @@ public final class LoopingMediaSource implements MediaSource { ...@@ -101,8 +108,9 @@ public final class LoopingMediaSource implements MediaSource {
this.childTimeline = childTimeline; this.childTimeline = childTimeline;
childPeriodCount = childTimeline.getPeriodCount(); childPeriodCount = childTimeline.getPeriodCount();
childWindowCount = childTimeline.getWindowCount(); childWindowCount = childTimeline.getWindowCount();
// This is the maximum number of loops that can be performed without overflow. // This is the maximum number of loops that can be performed without exceeding
int maxLoopCount = Integer.MAX_VALUE / childPeriodCount; // MAX_EXPOSED_PERIODS periods.
int maxLoopCount = MAX_EXPOSED_PERIODS / childPeriodCount;
if (loopCount > maxLoopCount) { if (loopCount > maxLoopCount) {
if (loopCount != Integer.MAX_VALUE) { if (loopCount != Integer.MAX_VALUE) {
Log.w(TAG, "Capped loops to avoid overflow: " + loopCount + " -> " + maxLoopCount); Log.w(TAG, "Capped loops to avoid overflow: " + loopCount + " -> " + maxLoopCount);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment