Fix potential media source release before media period release.

This could happen when a media source is removed from a
DynamicConcatenatingMediaSource and one of its media periods is still active.
This media period is only removed by the player after the player received
a timeline update and thus we shouldn't release the removed child source
as long as it has active media periods.

Issue:#3796

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=184522836
This commit is contained in:
tonihei 2018-02-05 06:48:48 -08:00 committed by Oliver Woodman
parent 7b19de2e99
commit fe98477045
2 changed files with 27 additions and 6 deletions

View File

@ -627,6 +627,18 @@ public final class DynamicConcatenatingMediaSourceTest extends TestCase {
mediaSourceWithAds.assertMediaPeriodCreated(new MediaPeriodId(1, 0, 0)); mediaSourceWithAds.assertMediaPeriodCreated(new MediaPeriodId(1, 0, 0));
} }
public void testRemoveChildSourceWithActiveMediaPeriod() throws IOException {
FakeMediaSource childSource = createFakeMediaSource();
mediaSource.addMediaSource(childSource);
testRunner.prepareSource();
MediaPeriod mediaPeriod = testRunner.createPeriod(new MediaPeriodId(/* periodIndex= */ 0));
mediaSource.removeMediaSource(/* index= */ 0);
testRunner.assertTimelineChangeBlocking();
testRunner.releasePeriod(mediaPeriod);
childSource.assertReleased();
testRunner.releaseSource();
}
private static FakeMediaSource[] createMediaSources(int count) { private static FakeMediaSource[] createMediaSources(int count) {
FakeMediaSource[] sources = new FakeMediaSource[count]; FakeMediaSource[] sources = new FakeMediaSource[count];
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {

View File

@ -56,7 +56,7 @@ public final class DynamicConcatenatingMediaSource extends CompositeMediaSource<
// Accessed on the playback thread. // Accessed on the playback thread.
private final List<MediaSourceHolder> mediaSourceHolders; private final List<MediaSourceHolder> mediaSourceHolders;
private final MediaSourceHolder query; private final MediaSourceHolder query;
private final Map<MediaPeriod, MediaSource> mediaSourceByMediaPeriod; private final Map<MediaPeriod, MediaSourceHolder> mediaSourceByMediaPeriod;
private final List<DeferredMediaPeriod> deferredMediaPeriods; private final List<DeferredMediaPeriod> deferredMediaPeriods;
private ExoPlayer player; private ExoPlayer player;
@ -355,19 +355,23 @@ public final class DynamicConcatenatingMediaSource extends CompositeMediaSource<
} else { } else {
mediaPeriod = holder.mediaSource.createPeriod(idInSource, allocator); mediaPeriod = holder.mediaSource.createPeriod(idInSource, allocator);
} }
mediaSourceByMediaPeriod.put(mediaPeriod, holder.mediaSource); mediaSourceByMediaPeriod.put(mediaPeriod, holder);
holder.activeMediaPeriods++;
return mediaPeriod; return mediaPeriod;
} }
@Override @Override
public void releasePeriod(MediaPeriod mediaPeriod) { public void releasePeriod(MediaPeriod mediaPeriod) {
MediaSource mediaSource = mediaSourceByMediaPeriod.get(mediaPeriod); MediaSourceHolder holder = mediaSourceByMediaPeriod.remove(mediaPeriod);
mediaSourceByMediaPeriod.remove(mediaPeriod);
if (mediaPeriod instanceof DeferredMediaPeriod) { if (mediaPeriod instanceof DeferredMediaPeriod) {
deferredMediaPeriods.remove(mediaPeriod); deferredMediaPeriods.remove(mediaPeriod);
((DeferredMediaPeriod) mediaPeriod).releasePeriod(); ((DeferredMediaPeriod) mediaPeriod).releasePeriod();
} else { } else {
mediaSource.releasePeriod(mediaPeriod); holder.mediaSource.releasePeriod(mediaPeriod);
}
holder.activeMediaPeriods--;
if (holder.activeMediaPeriods == 0 && holder.isRemoved) {
releaseChildSource(holder);
} }
} }
@ -520,8 +524,11 @@ public final class DynamicConcatenatingMediaSource extends CompositeMediaSource<
/* childIndexUpdate= */ -1, /* childIndexUpdate= */ -1,
-oldTimeline.getWindowCount(), -oldTimeline.getWindowCount(),
-oldTimeline.getPeriodCount()); -oldTimeline.getPeriodCount());
holder.isRemoved = true;
if (holder.activeMediaPeriods == 0) {
releaseChildSource(holder); releaseChildSource(holder);
} }
}
private void moveMediaSourceInternal(int currentIndex, int newIndex) { private void moveMediaSourceInternal(int currentIndex, int newIndex) {
int startIndex = Math.min(currentIndex, newIndex); int startIndex = Math.min(currentIndex, newIndex);
@ -573,6 +580,8 @@ public final class DynamicConcatenatingMediaSource extends CompositeMediaSource<
public int firstWindowIndexInChild; public int firstWindowIndexInChild;
public int firstPeriodIndexInChild; public int firstPeriodIndexInChild;
public boolean isPrepared; public boolean isPrepared;
public boolean isRemoved;
public int activeMediaPeriods;
public MediaSourceHolder( public MediaSourceHolder(
MediaSource mediaSource, MediaSource mediaSource,