mirror of
https://github.com/androidx/media.git
synced 2025-05-18 04:59:54 +08:00
MergingMediaSource fixes
- Don't send a timeline to the listener until all children have reported their timelines. - Propagate a proper merge error if merging fails. - The PlayerActivity hack is necessary due to the way Andorid's MediaController widget attaches to the window :(. It'll go away once we get our own player controls. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=131958169
This commit is contained in:
parent
a964da7922
commit
d48bf94145
@ -562,8 +562,14 @@ public class PlayerActivity extends Activity implements OnKeyListener, OnTouchLi
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void showControls() {
|
private void showControls() {
|
||||||
mediaController.show(0);
|
|
||||||
debugRootView.setVisibility(View.VISIBLE);
|
debugRootView.setVisibility(View.VISIBLE);
|
||||||
|
// TODO: Remove this hack when transitioning to our own playback controls.
|
||||||
|
mainHandler.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
mediaController.show(0);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showToast(int messageId) {
|
private void showToast(int messageId) {
|
||||||
|
@ -22,7 +22,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.IdentityHashMap;
|
import java.util.IdentityHashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Merges multiple {@link MediaPeriod} instances.
|
* Merges multiple {@link MediaPeriod}s.
|
||||||
*/
|
*/
|
||||||
/* package */ final class MergingMediaPeriod implements MediaPeriod, MediaPeriod.Callback {
|
/* package */ final class MergingMediaPeriod implements MediaPeriod, MediaPeriod.Callback {
|
||||||
|
|
||||||
|
@ -20,45 +20,79 @@ import com.google.android.exoplayer2.source.MediaPeriod.Callback;
|
|||||||
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.Assertions;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Merges multiple {@link MediaPeriod} instances.
|
* Merges multiple {@link MediaSource}s.
|
||||||
* <p>
|
* <p>
|
||||||
* The {@link MediaSource}s being merged must have final windows and an equal number of periods.
|
* The {@link Timeline}s of the sources being merged must have the same number of periods, and must
|
||||||
|
* not have any dynamic windows.
|
||||||
*/
|
*/
|
||||||
public final class MergingMediaSource implements MediaSource {
|
public final class MergingMediaSource implements MediaSource {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thrown when a {@link MergingMediaSource} cannot merge its sources.
|
||||||
|
*/
|
||||||
|
public static final class IllegalMergeException extends IOException {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The merge failed because one of the sources being merged has a dynamic window.
|
||||||
|
*/
|
||||||
|
public static final int REASON_WINDOWS_ARE_DYNAMIC = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The merge failed because the sources have different period counts.
|
||||||
|
*/
|
||||||
|
public static final int REASON_PERIOD_COUNT_MISMATCH = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The reason the merge failed. One of {@link #REASON_WINDOWS_ARE_DYNAMIC} and
|
||||||
|
* {@link #REASON_PERIOD_COUNT_MISMATCH}.
|
||||||
|
*/
|
||||||
|
public final int reason;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param reason The reason the merge failed. One of {@link #REASON_WINDOWS_ARE_DYNAMIC} and
|
||||||
|
* {@link #REASON_PERIOD_COUNT_MISMATCH}.
|
||||||
|
*/
|
||||||
|
public IllegalMergeException(int reason) {
|
||||||
|
this.reason = reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private static final int PERIOD_COUNT_UNSET = -1;
|
private static final int PERIOD_COUNT_UNSET = -1;
|
||||||
|
|
||||||
private final MediaSource[] mediaSources;
|
private final MediaSource[] mediaSources;
|
||||||
|
private final ArrayList<MediaSource> pendingTimelineSources;
|
||||||
private final Timeline.Window window;
|
private final Timeline.Window window;
|
||||||
|
|
||||||
|
private Listener listener;
|
||||||
|
private Timeline primaryTimeline;
|
||||||
|
private Object primaryManifest;
|
||||||
private int periodCount;
|
private int periodCount;
|
||||||
|
private IllegalMergeException mergeError;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param mediaSources The {@link MediaSource}s to merge.
|
* @param mediaSources The {@link MediaSource}s to merge.
|
||||||
*/
|
*/
|
||||||
public MergingMediaSource(MediaSource... mediaSources) {
|
public MergingMediaSource(MediaSource... mediaSources) {
|
||||||
this.mediaSources = mediaSources;
|
this.mediaSources = mediaSources;
|
||||||
|
pendingTimelineSources = new ArrayList<>(Arrays.asList(mediaSources));
|
||||||
window = new Timeline.Window();
|
window = new Timeline.Window();
|
||||||
periodCount = PERIOD_COUNT_UNSET;
|
periodCount = PERIOD_COUNT_UNSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void prepareSource(final Listener listener) {
|
public void prepareSource(final Listener listener) {
|
||||||
mediaSources[0].prepareSource(new Listener() {
|
this.listener = listener;
|
||||||
@Override
|
for (int i = 0; i < mediaSources.length; i++) {
|
||||||
public void onSourceInfoRefreshed(Timeline timeline, Object manifest) {
|
final int sourceIndex = i;
|
||||||
checkConsistentTimeline(timeline);
|
mediaSources[sourceIndex].prepareSource(new Listener() {
|
||||||
// All source timelines must match.
|
|
||||||
listener.onSourceInfoRefreshed(timeline, manifest);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
for (int i = 1; i < mediaSources.length; i++) {
|
|
||||||
mediaSources[i].prepareSource(new Listener() {
|
|
||||||
@Override
|
@Override
|
||||||
public void onSourceInfoRefreshed(Timeline timeline, Object manifest) {
|
public void onSourceInfoRefreshed(Timeline timeline, Object manifest) {
|
||||||
checkConsistentTimeline(timeline);
|
handleSourceInfoRefreshed(sourceIndex, timeline, manifest);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -66,6 +100,9 @@ public final class MergingMediaSource implements MediaSource {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void maybeThrowSourceInfoRefreshError() throws IOException {
|
public void maybeThrowSourceInfoRefreshError() throws IOException {
|
||||||
|
if (mergeError != null) {
|
||||||
|
throw mergeError;
|
||||||
|
}
|
||||||
for (MediaSource mediaSource : mediaSources) {
|
for (MediaSource mediaSource : mediaSources) {
|
||||||
mediaSource.maybeThrowSourceInfoRefreshError();
|
mediaSource.maybeThrowSourceInfoRefreshError();
|
||||||
}
|
}
|
||||||
@ -99,17 +136,36 @@ public final class MergingMediaSource implements MediaSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkConsistentTimeline(Timeline timeline) {
|
private void handleSourceInfoRefreshed(int sourceIndex, Timeline timeline, Object manifest) {
|
||||||
int windowCount = timeline.getWindowCount();
|
if (mergeError == null) {
|
||||||
for (int i = 0; i < windowCount; i++) {
|
mergeError = checkTimelineMerges(timeline);
|
||||||
Assertions.checkArgument(!timeline.getWindow(i, window, false).isDynamic);
|
|
||||||
}
|
}
|
||||||
int periodCount = timeline.getPeriodCount();
|
if (mergeError != null) {
|
||||||
if (this.periodCount == PERIOD_COUNT_UNSET) {
|
return;
|
||||||
this.periodCount = periodCount;
|
}
|
||||||
} else {
|
pendingTimelineSources.remove(mediaSources[sourceIndex]);
|
||||||
Assertions.checkState(this.periodCount == periodCount);
|
if (sourceIndex == 0) {
|
||||||
|
primaryTimeline = timeline;
|
||||||
|
primaryManifest = manifest;
|
||||||
|
}
|
||||||
|
if (pendingTimelineSources.isEmpty()) {
|
||||||
|
listener.onSourceInfoRefreshed(primaryTimeline, primaryManifest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IllegalMergeException checkTimelineMerges(Timeline timeline) {
|
||||||
|
int windowCount = timeline.getWindowCount();
|
||||||
|
for (int i = 0; i < windowCount; i++) {
|
||||||
|
if (timeline.getWindow(i, window, false).isDynamic) {
|
||||||
|
return new IllegalMergeException(IllegalMergeException.REASON_WINDOWS_ARE_DYNAMIC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (periodCount == PERIOD_COUNT_UNSET) {
|
||||||
|
periodCount = timeline.getPeriodCount();
|
||||||
|
} else if (timeline.getPeriodCount() != periodCount) {
|
||||||
|
return new IllegalMergeException(IllegalMergeException.REASON_PERIOD_COUNT_MISMATCH);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user