Allow moving media source within DynamicConcatenatingMediaSource.

This option allows to move the currently playing media source to another position
and also to move other media source without creating a new MediaSource object.

Issue:#1706

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=161402022
This commit is contained in:
tonihei 2017-07-10 09:20:56 -07:00 committed by Oliver Woodman
parent 06b3b3ca8d
commit 45f94eab62
2 changed files with 63 additions and 2 deletions

View File

@ -85,6 +85,24 @@ public final class DynamicConcatenatingMediaSourceTest extends TestCase {
TimelineAsserts.assertPeriodCounts(timeline, 2, 4, 1, 5, 6, 7, 3);
TimelineAsserts.assertWindowIds(timeline, 222, 444, 111, 555, 666, 777, 333);
// Move sources.
mediaSource.moveMediaSource(2, 3);
waitForTimelineUpdate();
TimelineAsserts.assertPeriodCounts(timeline, 2, 4, 5, 1, 6, 7, 3);
TimelineAsserts.assertWindowIds(timeline, 222, 444, 555, 111, 666, 777, 333);
mediaSource.moveMediaSource(3, 2);
waitForTimelineUpdate();
TimelineAsserts.assertPeriodCounts(timeline, 2, 4, 1, 5, 6, 7, 3);
TimelineAsserts.assertWindowIds(timeline, 222, 444, 111, 555, 666, 777, 333);
mediaSource.moveMediaSource(0, 6);
waitForTimelineUpdate();
TimelineAsserts.assertPeriodCounts(timeline, 4, 1, 5, 6, 7, 3, 2);
TimelineAsserts.assertWindowIds(timeline, 444, 111, 555, 666, 777, 333, 222);
mediaSource.moveMediaSource(6, 0);
waitForTimelineUpdate();
TimelineAsserts.assertPeriodCounts(timeline, 2, 4, 1, 5, 6, 7, 3);
TimelineAsserts.assertWindowIds(timeline, 222, 444, 111, 555, 666, 777, 333);
// Remove in the middle.
mediaSource.removeMediaSource(3);
waitForTimelineUpdate();
@ -138,7 +156,9 @@ public final class DynamicConcatenatingMediaSourceTest extends TestCase {
mediaSource.addMediaSource(childSources[0]);
mediaSource.addMediaSource(childSources[1]);
mediaSource.addMediaSource(0, childSources[2]);
mediaSource.removeMediaSource(1);
mediaSource.moveMediaSource(0, 2);
mediaSource.removeMediaSource(0);
mediaSource.moveMediaSource(1, 0);
mediaSource.addMediaSource(1, childSources[3]);
assertNull(timeline);

View File

@ -44,6 +44,7 @@ public final class DynamicConcatenatingMediaSource implements MediaSource, ExoPl
private static final int MSG_ADD = 0;
private static final int MSG_ADD_MULTIPLE = 1;
private static final int MSG_REMOVE = 2;
private static final int MSG_MOVE = 3;
// Accessed on the app thread.
private final List<MediaSource> mediaSourcesPublic;
@ -126,7 +127,8 @@ public final class DynamicConcatenatingMediaSource implements MediaSource, ExoPl
/**
* Removes a {@link MediaSource} from the playlist.
*
* @param index The index at which the media source will be removed.
* @param index The index at which the media source will be removed. This index must be in the
* range of 0 <= index < {@link #getSize()}.
*/
public synchronized void removeMediaSource(int index) {
mediaSourcesPublic.remove(index);
@ -135,6 +137,25 @@ public final class DynamicConcatenatingMediaSource implements MediaSource, ExoPl
}
}
/**
* Moves an existing {@link MediaSource} within the playlist.
*
* @param currentIndex The current index of the media source in the playlist. This index must be
* in the range of 0 <= index < {@link #getSize()}.
* @param newIndex The target index of the media source in the playlist. This index must be in the
* range of 0 <= index < {@link #getSize()}.
*/
public synchronized void moveMediaSource(int currentIndex, int newIndex) {
if (currentIndex == newIndex) {
return;
}
mediaSourcesPublic.add(newIndex, mediaSourcesPublic.remove(currentIndex));
if (player != null) {
player.sendMessages(new ExoPlayerMessage(this, MSG_MOVE,
Pair.create(currentIndex, newIndex)));
}
}
/**
* Returns the number of media sources in the playlist.
*/
@ -225,6 +246,11 @@ public final class DynamicConcatenatingMediaSource implements MediaSource, ExoPl
removeMediaSourceInternal((Integer) message);
break;
}
case MSG_MOVE: {
Pair<Integer, Integer> messageData = (Pair<Integer, Integer>) message;
moveMediaSourceInternal(messageData.first, messageData.second);
break;
}
default: {
throw new IllegalStateException();
}
@ -304,6 +330,21 @@ public final class DynamicConcatenatingMediaSource implements MediaSource, ExoPl
holder.mediaSource.releaseSource();
}
private void moveMediaSourceInternal(int currentIndex, int newIndex) {
int startIndex = Math.min(currentIndex, newIndex);
int endIndex = Math.max(currentIndex, newIndex);
int windowOffset = mediaSourceHolders.get(startIndex).firstWindowIndexInChild;
int periodOffset = mediaSourceHolders.get(startIndex).firstPeriodIndexInChild;
mediaSourceHolders.add(newIndex, mediaSourceHolders.remove(currentIndex));
for (int i = startIndex; i <= endIndex; i++) {
MediaSourceHolder holder = mediaSourceHolders.get(i);
holder.firstWindowIndexInChild = windowOffset;
holder.firstPeriodIndexInChild = periodOffset;
windowOffset += holder.timeline.getWindowCount();
periodOffset += holder.timeline.getPeriodCount();
}
}
private void correctOffsets(int startIndex, int windowOffsetUpdate, int periodOffsetUpdate) {
windowCount += windowOffsetUpdate;
periodCount += periodOffsetUpdate;