mirror of
https://github.com/androidx/media.git
synced 2025-05-03 21:57:46 +08:00
Support duplicate entries in ConcatenatingMediaSource
People will inevitably try and do it, and it's pretty easy to handle properly, so why not... ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=132047019
This commit is contained in:
parent
d48bf94145
commit
bd76ec8b13
@ -43,7 +43,6 @@ import com.google.android.exoplayer2.ExoPlayerFactory;
|
|||||||
import com.google.android.exoplayer2.SimpleExoPlayer;
|
import com.google.android.exoplayer2.SimpleExoPlayer;
|
||||||
import com.google.android.exoplayer2.Timeline;
|
import com.google.android.exoplayer2.Timeline;
|
||||||
import com.google.android.exoplayer2.drm.DrmSessionManager;
|
import com.google.android.exoplayer2.drm.DrmSessionManager;
|
||||||
import com.google.android.exoplayer2.drm.FrameworkMediaCrypto;
|
|
||||||
import com.google.android.exoplayer2.drm.FrameworkMediaDrm;
|
import com.google.android.exoplayer2.drm.FrameworkMediaDrm;
|
||||||
import com.google.android.exoplayer2.drm.HttpMediaDrmCallback;
|
import com.google.android.exoplayer2.drm.HttpMediaDrmCallback;
|
||||||
import com.google.android.exoplayer2.drm.StreamingDrmSessionManager;
|
import com.google.android.exoplayer2.drm.StreamingDrmSessionManager;
|
||||||
@ -364,7 +363,7 @@ public class PlayerActivity extends Activity implements OnKeyListener, OnTouchLi
|
|||||||
}
|
}
|
||||||
HttpMediaDrmCallback drmCallback = new HttpMediaDrmCallback(licenseUrl,
|
HttpMediaDrmCallback drmCallback = new HttpMediaDrmCallback(licenseUrl,
|
||||||
buildHttpDataSourceFactory(false));
|
buildHttpDataSourceFactory(false));
|
||||||
return new StreamingDrmSessionManager<FrameworkMediaCrypto>(uuid,
|
return new StreamingDrmSessionManager<>(uuid,
|
||||||
FrameworkMediaDrm.newInstance(uuid), drmCallback, null, mainHandler, eventLogger);
|
FrameworkMediaDrm.newInstance(uuid), drmCallback, null, mainHandler, eventLogger);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -404,7 +403,9 @@ public class PlayerActivity extends Activity implements OnKeyListener, OnTouchLi
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Build a HttpDataSource factory.
|
* Build a HttpDataSource factory.
|
||||||
* @param useBandwidthMeter
|
*
|
||||||
|
* @param useBandwidthMeter Whether to set {@link #BANDWIDTH_METER} as a listener to the new
|
||||||
|
* DataSource factory.
|
||||||
*/
|
*/
|
||||||
private HttpDataSource.Factory buildHttpDataSourceFactory(boolean useBandwidthMeter) {
|
private HttpDataSource.Factory buildHttpDataSourceFactory(boolean useBandwidthMeter) {
|
||||||
return new DefaultHttpDataSourceFactory(userAgent, useBandwidthMeter ? BANDWIDTH_METER : null);
|
return new DefaultHttpDataSourceFactory(userAgent, useBandwidthMeter ? BANDWIDTH_METER : null);
|
||||||
|
@ -23,10 +23,12 @@ import com.google.android.exoplayer2.upstream.Allocator;
|
|||||||
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;
|
||||||
|
import java.util.IdentityHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Concatenates multiple {@link MediaSource}s.
|
* Concatenates multiple {@link MediaSource}s. It is valid for the same {@link MediaSource} instance
|
||||||
|
* to be present more than once in the concatenation.
|
||||||
*/
|
*/
|
||||||
public final class ConcatenatingMediaSource implements MediaSource {
|
public final class ConcatenatingMediaSource implements MediaSource {
|
||||||
|
|
||||||
@ -34,47 +36,45 @@ public final class ConcatenatingMediaSource implements MediaSource {
|
|||||||
private final Timeline[] timelines;
|
private final Timeline[] timelines;
|
||||||
private final Object[] manifests;
|
private final Object[] manifests;
|
||||||
private final Map<MediaPeriod, Integer> sourceIndexByMediaPeriod;
|
private final Map<MediaPeriod, Integer> sourceIndexByMediaPeriod;
|
||||||
|
private final boolean[] duplicateFlags;
|
||||||
|
|
||||||
|
private Listener listener;
|
||||||
private ConcatenatedTimeline timeline;
|
private ConcatenatedTimeline timeline;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param mediaSources The {@link MediaSource}s to concatenate.
|
* @param mediaSources The {@link MediaSource}s to concatenate. It is valid for the same
|
||||||
|
* {@link MediaSource} instance to be present more than once in the array.
|
||||||
*/
|
*/
|
||||||
public ConcatenatingMediaSource(MediaSource... mediaSources) {
|
public ConcatenatingMediaSource(MediaSource... mediaSources) {
|
||||||
this.mediaSources = mediaSources;
|
this.mediaSources = mediaSources;
|
||||||
timelines = new Timeline[mediaSources.length];
|
timelines = new Timeline[mediaSources.length];
|
||||||
manifests = new Object[mediaSources.length];
|
manifests = new Object[mediaSources.length];
|
||||||
sourceIndexByMediaPeriod = new HashMap<>();
|
sourceIndexByMediaPeriod = new HashMap<>();
|
||||||
|
duplicateFlags = buildDuplicateFlags(mediaSources);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void prepareSource(final Listener listener) {
|
public void prepareSource(Listener listener) {
|
||||||
|
this.listener = listener;
|
||||||
for (int i = 0; i < mediaSources.length; i++) {
|
for (int i = 0; i < mediaSources.length; i++) {
|
||||||
final int index = i;
|
if (!duplicateFlags[i]) {
|
||||||
mediaSources[i].prepareSource(new Listener() {
|
final int index = i;
|
||||||
|
mediaSources[i].prepareSource(new Listener() {
|
||||||
@Override
|
@Override
|
||||||
public void onSourceInfoRefreshed(Timeline sourceTimeline, Object manifest) {
|
public void onSourceInfoRefreshed(Timeline timeline, Object manifest) {
|
||||||
timelines[index] = sourceTimeline;
|
handleSourceInfoRefreshed(index, timeline, manifest);
|
||||||
manifests[index] = manifest;
|
|
||||||
for (Timeline timeline : timelines) {
|
|
||||||
if (timeline == null) {
|
|
||||||
// Don't invoke the listener until all sources have timelines.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
timeline = new ConcatenatedTimeline(timelines.clone());
|
});
|
||||||
listener.onSourceInfoRefreshed(timeline, manifests.clone());
|
}
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void maybeThrowSourceInfoRefreshError() throws IOException {
|
public void maybeThrowSourceInfoRefreshError() throws IOException {
|
||||||
for (MediaSource mediaSource : mediaSources) {
|
for (int i = 0; i < mediaSources.length; i++) {
|
||||||
mediaSource.maybeThrowSourceInfoRefreshError();
|
if (!duplicateFlags[i]) {
|
||||||
|
mediaSources[i].maybeThrowSourceInfoRefreshError();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,11 +98,49 @@ public final class ConcatenatingMediaSource implements MediaSource {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void releaseSource() {
|
public void releaseSource() {
|
||||||
for (MediaSource mediaSource : mediaSources) {
|
for (int i = 0; i < mediaSources.length; i++) {
|
||||||
mediaSource.releaseSource();
|
if (!duplicateFlags[i]) {
|
||||||
|
mediaSources[i].releaseSource();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void handleSourceInfoRefreshed(int sourceFirstIndex, Timeline sourceTimeline,
|
||||||
|
Object sourceManifest) {
|
||||||
|
// Set the timeline and manifest.
|
||||||
|
timelines[sourceFirstIndex] = sourceTimeline;
|
||||||
|
manifests[sourceFirstIndex] = sourceManifest;
|
||||||
|
// Also set the timeline and manifest for any duplicate entries of the same source.
|
||||||
|
for (int i = sourceFirstIndex + 1; i < mediaSources.length; i++) {
|
||||||
|
if (mediaSources[i] == mediaSources[sourceFirstIndex]) {
|
||||||
|
timelines[i] = sourceTimeline;
|
||||||
|
manifests[i] = sourceManifest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (Timeline timeline : timelines) {
|
||||||
|
if (timeline == null) {
|
||||||
|
// Don't invoke the listener until all sources have timelines.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
timeline = new ConcatenatedTimeline(timelines.clone());
|
||||||
|
listener.onSourceInfoRefreshed(timeline, manifests.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean[] buildDuplicateFlags(MediaSource[] mediaSources) {
|
||||||
|
boolean[] duplicateFlags = new boolean[mediaSources.length];
|
||||||
|
IdentityHashMap<MediaSource, Void> sources = new IdentityHashMap<>(mediaSources.length);
|
||||||
|
for (int i = 0; i < mediaSources.length; i++) {
|
||||||
|
MediaSource source = mediaSources[i];
|
||||||
|
if (!sources.containsKey(source)) {
|
||||||
|
sources.put(source, null);
|
||||||
|
} else {
|
||||||
|
duplicateFlags[i] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return duplicateFlags;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link Timeline} that is the concatenation of one or more {@link Timeline}s.
|
* A {@link Timeline} that is the concatenation of one or more {@link Timeline}s.
|
||||||
*/
|
*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user