Commit 28697799 by tonihei Committed by Oliver Woodman

Fix bug in DynamicConcatenatingMediaSource at dynamic changes of empty timelines.

When the dynamic media source contains multiple empty timelines in a row and some
of them dynamically change to a non-empty timeline, the window and period indices
are not updated correctly because the index of the changed child source is wrong.

To fix this bug, the child index is added to the media period holder to have direct
access on the current child index to prevent ambiguity.

Furthermore, the uid is changed to be the hash code of the MediaSourceHolder not the
MediaSource itself to allow adding the same MediaSource twice without violating the
unique uid policy.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=183973462
parent e7ba2caf
...@@ -344,6 +344,32 @@ public final class DynamicConcatenatingMediaSourceTest extends TestCase { ...@@ -344,6 +344,32 @@ public final class DynamicConcatenatingMediaSourceTest extends TestCase {
testRunner.assertPrepareAndReleaseAllPeriods(); testRunner.assertPrepareAndReleaseAllPeriods();
} }
public void testDynamicChangeOfEmptyTimelines() throws IOException {
FakeMediaSource[] childSources =
new FakeMediaSource[] {
new FakeMediaSource(Timeline.EMPTY, /* manifest= */ null),
new FakeMediaSource(Timeline.EMPTY, /* manifest= */ null),
new FakeMediaSource(Timeline.EMPTY, /* manifest= */ null),
};
Timeline nonEmptyTimeline = new FakeTimeline(/* windowCount = */ 1);
mediaSource.addMediaSources(Arrays.<MediaSource>asList(childSources));
Timeline timeline = testRunner.prepareSource();
TimelineAsserts.assertEmpty(timeline);
childSources[0].setNewSourceInfo(nonEmptyTimeline, /* newManifest== */ null);
timeline = testRunner.assertTimelineChangeBlocking();
TimelineAsserts.assertPeriodCounts(timeline, 1);
childSources[2].setNewSourceInfo(nonEmptyTimeline, /* newManifest== */ null);
timeline = testRunner.assertTimelineChangeBlocking();
TimelineAsserts.assertPeriodCounts(timeline, 1, 1);
childSources[1].setNewSourceInfo(nonEmptyTimeline, /* newManifest== */ null);
timeline = testRunner.assertTimelineChangeBlocking();
TimelineAsserts.assertPeriodCounts(timeline, 1, 1, 1);
}
public void testIllegalArguments() { public void testIllegalArguments() {
MediaSource validSource = new FakeMediaSource(createFakeTimeline(1), null); MediaSource validSource = new FakeMediaSource(createFakeTimeline(1), null);
......
...@@ -453,18 +453,24 @@ public final class DynamicConcatenatingMediaSource extends CompositeMediaSource< ...@@ -453,18 +453,24 @@ public final class DynamicConcatenatingMediaSource extends CompositeMediaSource<
private void addMediaSourceInternal(int newIndex, MediaSource newMediaSource) { private void addMediaSourceInternal(int newIndex, MediaSource newMediaSource) {
final MediaSourceHolder newMediaSourceHolder; final MediaSourceHolder newMediaSourceHolder;
Object newUid = System.identityHashCode(newMediaSource);
DeferredTimeline newTimeline = new DeferredTimeline(); DeferredTimeline newTimeline = new DeferredTimeline();
if (newIndex > 0) { if (newIndex > 0) {
MediaSourceHolder previousHolder = mediaSourceHolders.get(newIndex - 1); MediaSourceHolder previousHolder = mediaSourceHolders.get(newIndex - 1);
newMediaSourceHolder = new MediaSourceHolder(newMediaSource, newTimeline, newMediaSourceHolder =
new MediaSourceHolder(
newMediaSource,
newTimeline,
newIndex,
previousHolder.firstWindowIndexInChild + previousHolder.timeline.getWindowCount(), previousHolder.firstWindowIndexInChild + previousHolder.timeline.getWindowCount(),
previousHolder.firstPeriodIndexInChild + previousHolder.timeline.getPeriodCount(), previousHolder.firstPeriodIndexInChild + previousHolder.timeline.getPeriodCount());
newUid);
} else { } else {
newMediaSourceHolder = new MediaSourceHolder(newMediaSource, newTimeline, 0, 0, newUid); newMediaSourceHolder = new MediaSourceHolder(newMediaSource, newTimeline, 0, 0, 0);
} }
correctOffsets(newIndex, newTimeline.getWindowCount(), newTimeline.getPeriodCount()); correctOffsets(
newIndex,
/* childIndexUpdate= */ 1,
newTimeline.getWindowCount(),
newTimeline.getPeriodCount());
mediaSourceHolders.add(newIndex, newMediaSourceHolder); mediaSourceHolders.add(newIndex, newMediaSourceHolder);
prepareChildSource(newMediaSourceHolder, newMediaSourceHolder.mediaSource); prepareChildSource(newMediaSourceHolder, newMediaSourceHolder.mediaSource);
} }
...@@ -486,8 +492,11 @@ public final class DynamicConcatenatingMediaSource extends CompositeMediaSource< ...@@ -486,8 +492,11 @@ public final class DynamicConcatenatingMediaSource extends CompositeMediaSource<
int windowOffsetUpdate = timeline.getWindowCount() - deferredTimeline.getWindowCount(); int windowOffsetUpdate = timeline.getWindowCount() - deferredTimeline.getWindowCount();
int periodOffsetUpdate = timeline.getPeriodCount() - deferredTimeline.getPeriodCount(); int periodOffsetUpdate = timeline.getPeriodCount() - deferredTimeline.getPeriodCount();
if (windowOffsetUpdate != 0 || periodOffsetUpdate != 0) { if (windowOffsetUpdate != 0 || periodOffsetUpdate != 0) {
int index = findMediaSourceHolderByPeriodIndex(mediaSourceHolder.firstPeriodIndexInChild); correctOffsets(
correctOffsets(index + 1, windowOffsetUpdate, periodOffsetUpdate); mediaSourceHolder.childIndex + 1,
/* childIndexUpdate= */ 0,
windowOffsetUpdate,
periodOffsetUpdate);
} }
mediaSourceHolder.timeline = deferredTimeline.cloneWithNewTimeline(timeline); mediaSourceHolder.timeline = deferredTimeline.cloneWithNewTimeline(timeline);
if (!mediaSourceHolder.isPrepared) { if (!mediaSourceHolder.isPrepared) {
...@@ -506,7 +515,11 @@ public final class DynamicConcatenatingMediaSource extends CompositeMediaSource< ...@@ -506,7 +515,11 @@ public final class DynamicConcatenatingMediaSource extends CompositeMediaSource<
MediaSourceHolder holder = mediaSourceHolders.get(index); MediaSourceHolder holder = mediaSourceHolders.get(index);
mediaSourceHolders.remove(index); mediaSourceHolders.remove(index);
Timeline oldTimeline = holder.timeline; Timeline oldTimeline = holder.timeline;
correctOffsets(index, -oldTimeline.getWindowCount(), -oldTimeline.getPeriodCount()); correctOffsets(
index,
/* childIndexUpdate= */ -1,
-oldTimeline.getWindowCount(),
-oldTimeline.getPeriodCount());
releaseChildSource(holder); releaseChildSource(holder);
} }
...@@ -525,10 +538,12 @@ public final class DynamicConcatenatingMediaSource extends CompositeMediaSource< ...@@ -525,10 +538,12 @@ public final class DynamicConcatenatingMediaSource extends CompositeMediaSource<
} }
} }
private void correctOffsets(int startIndex, int windowOffsetUpdate, int periodOffsetUpdate) { private void correctOffsets(
int startIndex, int childIndexUpdate, int windowOffsetUpdate, int periodOffsetUpdate) {
windowCount += windowOffsetUpdate; windowCount += windowOffsetUpdate;
periodCount += periodOffsetUpdate; periodCount += periodOffsetUpdate;
for (int i = startIndex; i < mediaSourceHolders.size(); i++) { for (int i = startIndex; i < mediaSourceHolders.size(); i++) {
mediaSourceHolders.get(i).childIndex += childIndexUpdate;
mediaSourceHolders.get(i).firstWindowIndexInChild += windowOffsetUpdate; mediaSourceHolders.get(i).firstWindowIndexInChild += windowOffsetUpdate;
mediaSourceHolders.get(i).firstPeriodIndexInChild += periodOffsetUpdate; mediaSourceHolders.get(i).firstPeriodIndexInChild += periodOffsetUpdate;
} }
...@@ -551,20 +566,26 @@ public final class DynamicConcatenatingMediaSource extends CompositeMediaSource< ...@@ -551,20 +566,26 @@ public final class DynamicConcatenatingMediaSource extends CompositeMediaSource<
/* package */ static final class MediaSourceHolder implements Comparable<MediaSourceHolder> { /* package */ static final class MediaSourceHolder implements Comparable<MediaSourceHolder> {
public final MediaSource mediaSource; public final MediaSource mediaSource;
public final Object uid; public final int uid;
public DeferredTimeline timeline; public DeferredTimeline timeline;
public int childIndex;
public int firstWindowIndexInChild; public int firstWindowIndexInChild;
public int firstPeriodIndexInChild; public int firstPeriodIndexInChild;
public boolean isPrepared; public boolean isPrepared;
public MediaSourceHolder(MediaSource mediaSource, DeferredTimeline timeline, int window, public MediaSourceHolder(
int period, Object uid) { MediaSource mediaSource,
DeferredTimeline timeline,
int childIndex,
int window,
int period) {
this.mediaSource = mediaSource; this.mediaSource = mediaSource;
this.timeline = timeline; this.timeline = timeline;
this.childIndex = childIndex;
this.firstWindowIndexInChild = window; this.firstWindowIndexInChild = window;
this.firstPeriodIndexInChild = period; this.firstPeriodIndexInChild = period;
this.uid = uid; this.uid = System.identityHashCode(this);
} }
@Override @Override
...@@ -638,7 +659,7 @@ public final class DynamicConcatenatingMediaSource extends CompositeMediaSource< ...@@ -638,7 +659,7 @@ public final class DynamicConcatenatingMediaSource extends CompositeMediaSource<
timelines[index] = mediaSourceHolder.timeline; timelines[index] = mediaSourceHolder.timeline;
firstPeriodInChildIndices[index] = mediaSourceHolder.firstPeriodIndexInChild; firstPeriodInChildIndices[index] = mediaSourceHolder.firstPeriodIndexInChild;
firstWindowInChildIndices[index] = mediaSourceHolder.firstWindowIndexInChild; firstWindowInChildIndices[index] = mediaSourceHolder.firstWindowIndexInChild;
uids[index] = (int) mediaSourceHolder.uid; uids[index] = mediaSourceHolder.uid;
childIndexByUid.put(uids[index], index++); childIndexByUid.put(uids[index], index++);
} }
} }
......
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