Android range playback.

This commit is contained in:
Radin Gospodinov 2023-02-09 09:38:05 +02:00
parent 029542721e
commit 6ca0ab3834
2 changed files with 48 additions and 11 deletions

View File

@ -93,6 +93,7 @@ import com.google.android.exoplayer2.source.dash.manifest.Representation;
import com.google.android.exoplayer2.ext.ima.ImaAdsLoader; import com.google.android.exoplayer2.ext.ima.ImaAdsLoader;
import com.google.android.exoplayer2.source.ads.AdsMediaSource; import com.google.android.exoplayer2.source.ads.AdsMediaSource;
import com.google.android.exoplayer2.source.DefaultMediaSourceFactory; import com.google.android.exoplayer2.source.DefaultMediaSourceFactory;
import com.google.android.exoplayer2.source.ClippingMediaSource;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import java.net.CookieHandler; import java.net.CookieHandler;
@ -181,6 +182,10 @@ class ReactExoplayerView extends FrameLayout implements
// Props from React // Props from React
private int backBufferDurationMs = DefaultLoadControl.DEFAULT_BACK_BUFFER_DURATION_MS; private int backBufferDurationMs = DefaultLoadControl.DEFAULT_BACK_BUFFER_DURATION_MS;
private Uri srcUri; private Uri srcUri;
private long startTimeMs = -1;
private long endTimeMs = -1;
private String extension; private String extension;
private boolean repeat; private boolean repeat;
private String audioTrackType; private String audioTrackType;
@ -669,7 +674,7 @@ class ReactExoplayerView extends FrameLayout implements
private void initializePlayerSource(ReactExoplayerView self, DrmSessionManager drmSessionManager) { private void initializePlayerSource(ReactExoplayerView self, DrmSessionManager drmSessionManager) {
ArrayList<MediaSource> mediaSourceList = buildTextSources(); ArrayList<MediaSource> mediaSourceList = buildTextSources();
MediaSource videoSource = buildMediaSource(self.srcUri, self.extension, drmSessionManager); MediaSource videoSource = buildMediaSource(self.srcUri, self.extension, drmSessionManager, startTimeMs, endTimeMs);
MediaSource mediaSourceWithAds = null; MediaSource mediaSourceWithAds = null;
if (adTagUrl != null) { if (adTagUrl != null) {
MediaSource.Factory mediaSourceFactory = new DefaultMediaSourceFactory(mediaDataSourceFactory) MediaSource.Factory mediaSourceFactory = new DefaultMediaSourceFactory(mediaDataSourceFactory)
@ -764,7 +769,13 @@ class ReactExoplayerView extends FrameLayout implements
} }
} }
private MediaSource buildMediaSource(Uri uri, String overrideExtension, DrmSessionManager drmSessionManager) { private MediaSource buildMediaSource(
Uri uri,
String overrideExtension,
DrmSessionManager drmSessionManager,
long startTimeMs,
long endTimeMs) {
if (uri == null) { if (uri == null) {
throw new IllegalStateException("Invalid video uri"); throw new IllegalStateException("Invalid video uri");
} }
@ -781,7 +792,7 @@ class ReactExoplayerView extends FrameLayout implements
} }
MediaItem mediaItem = mediaItemBuilder.build(); MediaItem mediaItem = mediaItemBuilder.build();
MediaSource mediaSource = null;
DrmSessionManagerProvider drmProvider = null; DrmSessionManagerProvider drmProvider = null;
if (drmSessionManager != null) { if (drmSessionManager != null) {
drmProvider = new DrmSessionManagerProvider() { drmProvider = new DrmSessionManagerProvider() {
@ -795,39 +806,50 @@ class ReactExoplayerView extends FrameLayout implements
} }
switch (type) { switch (type) {
case CONTENT_TYPE_SS: case CONTENT_TYPE_SS:
return new SsMediaSource.Factory( mediaSource = SsMediaSource.Factory(
new DefaultSsChunkSource.Factory(mediaDataSourceFactory), new DefaultSsChunkSource.Factory(mediaDataSourceFactory),
buildDataSourceFactory(false) buildDataSourceFactory(false)
).setDrmSessionManagerProvider(drmProvider) ).setDrmSessionManagerProvider(drmProvider)
.setLoadErrorHandlingPolicy( .setLoadErrorHandlingPolicy(
config.buildLoadErrorHandlingPolicy(minLoadRetryCount) config.buildLoadErrorHandlingPolicy(minLoadRetryCount)
).createMediaSource(mediaItem); ).createMediaSource(mediaItem);
break;
case CONTENT_TYPE_DASH: case CONTENT_TYPE_DASH:
return new DashMediaSource.Factory( mediaSource = DashMediaSource.Factory(
new DefaultDashChunkSource.Factory(mediaDataSourceFactory), new DefaultDashChunkSource.Factory(mediaDataSourceFactory),
buildDataSourceFactory(false) buildDataSourceFactory(false)
).setDrmSessionManagerProvider(drmProvider) ).setDrmSessionManagerProvider(drmProvider)
.setLoadErrorHandlingPolicy( .setLoadErrorHandlingPolicy(
config.buildLoadErrorHandlingPolicy(minLoadRetryCount) config.buildLoadErrorHandlingPolicy(minLoadRetryCount)
).createMediaSource(mediaItem); ).createMediaSource(mediaItem);
break;
case CONTENT_TYPE_HLS: case CONTENT_TYPE_HLS:
return new HlsMediaSource.Factory( mediaSource = HlsMediaSource.Factory(
mediaDataSourceFactory mediaDataSourceFactory
).setDrmSessionManagerProvider(drmProvider) ).setDrmSessionManagerProvider(drmProvider)
.setLoadErrorHandlingPolicy( .setLoadErrorHandlingPolicy(
config.buildLoadErrorHandlingPolicy(minLoadRetryCount) config.buildLoadErrorHandlingPolicy(minLoadRetryCount)
).createMediaSource(mediaItem); ).createMediaSource(mediaItem);
break;
case CONTENT_TYPE_OTHER: case CONTENT_TYPE_OTHER:
return new ProgressiveMediaSource.Factory( mediaSource = ProgressiveMediaSource.Factory(
mediaDataSourceFactory mediaDataSourceFactory
).setDrmSessionManagerProvider(drmProvider) ).setDrmSessionManagerProvider(drmProvider)
.setLoadErrorHandlingPolicy( .setLoadErrorHandlingPolicy(
config.buildLoadErrorHandlingPolicy(minLoadRetryCount) config.buildLoadErrorHandlingPolicy(minLoadRetryCount)
).createMediaSource(mediaItem); ).createMediaSource(mediaItem);
break;
default: { default: {
throw new IllegalStateException("Unsupported type: " + type); throw new IllegalStateException("Unsupported type: " + type);
} }
} }
if(startTimeMs >= 0 && endTimeMs >= 0)
{
return new ClippingMediaSource(mediaSource, startTimeMs * 1000, endTimeMs * 1000);
}
return mediaSource;
} }
private ArrayList<MediaSource> buildTextSources() { private ArrayList<MediaSource> buildTextSources() {
@ -1465,11 +1487,19 @@ class ReactExoplayerView extends FrameLayout implements
// ReactExoplayerViewManager public api // ReactExoplayerViewManager public api
public void setSrc(final Uri uri, final String extension, Map<String, String> headers) { public void setSrc(
final Uri uri,
final long startTimeMs,
final long endTimeMs,
final String extension,
Map<String, String> headers) {
if (uri != null) { if (uri != null) {
boolean isSourceEqual = uri.equals(srcUri); boolean isSourceEqual = uri.equals(srcUri) && startTimeMs == this.startTimeMs && endTimeMs == this.endTimeMs;
hasDrmFailed = false; hasDrmFailed = false;
this.srcUri = uri; this.srcUri = uri;
this.startTimeMs = startTimeMs;
this.endTimeMs = endTimeMs;
this.extension = extension; this.extension = extension;
this.requestHeaders = headers; this.requestHeaders = headers;
this.mediaDataSourceFactory = this.mediaDataSourceFactory =
@ -1487,6 +1517,8 @@ class ReactExoplayerView extends FrameLayout implements
player.stop(); player.stop();
player.clearMediaItems(); player.clearMediaItems();
this.srcUri = null; this.srcUri = null;
this.startTimeMs = -1;
this.endTimeMs = -1;
this.extension = null; this.extension = null;
this.requestHeaders = null; this.requestHeaders = null;
this.mediaDataSourceFactory = null; this.mediaDataSourceFactory = null;

View File

@ -28,9 +28,12 @@ import javax.annotation.Nullable;
public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerView> { public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerView> {
private static final String REACT_CLASS = "RCTVideo"; private static final String REACT_CLASS = "RCTVideo";
private static final String PROP_SRC = "src"; private static final String PROP_SRC = "src";
private static final String PROP_SRC_URI = "uri"; private static final String PROP_SRC_URI = "uri";
private static final String PROP_SRC_START_TIME = "startTime";
private static final String PROP_SRC_END_TIME = "endTime";
private static final String PROP_AD_TAG_URL = "adTagUrl"; private static final String PROP_AD_TAG_URL = "adTagUrl";
private static final String PROP_SRC_TYPE = "type"; private static final String PROP_SRC_TYPE = "type";
private static final String PROP_DRM = "drm"; private static final String PROP_DRM = "drm";
@ -152,6 +155,8 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
public void setSrc(final ReactExoplayerView videoView, @Nullable ReadableMap src) { public void setSrc(final ReactExoplayerView videoView, @Nullable ReadableMap src) {
Context context = videoView.getContext().getApplicationContext(); Context context = videoView.getContext().getApplicationContext();
String uriString = src.hasKey(PROP_SRC_URI) ? src.getString(PROP_SRC_URI) : null; String uriString = src.hasKey(PROP_SRC_URI) ? src.getString(PROP_SRC_URI) : null;
int startTimeMs = src.hasKey(PROP_SRC_START_TIME) ? src.getInt(PROP_SRC_START_TIME) : -1;
int endTimeMs = src.hasKey(PROP_SRC_END_TIME) ? src.getInt(PROP_SRC_END_TIME) : -1;
String extension = src.hasKey(PROP_SRC_TYPE) ? src.getString(PROP_SRC_TYPE) : null; String extension = src.hasKey(PROP_SRC_TYPE) ? src.getString(PROP_SRC_TYPE) : null;
Map<String, String> headers = src.hasKey(PROP_SRC_HEADERS) ? toStringMap(src.getMap(PROP_SRC_HEADERS)) : null; Map<String, String> headers = src.hasKey(PROP_SRC_HEADERS) ? toStringMap(src.getMap(PROP_SRC_HEADERS)) : null;
@ -164,7 +169,7 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
Uri srcUri = Uri.parse(uriString); Uri srcUri = Uri.parse(uriString);
if (srcUri != null) { if (srcUri != null) {
videoView.setSrc(srcUri, extension, headers); videoView.setSrc(srcUri, startTimeMs, endTimeMs, extension, headers);
} }
} else { } else {
int identifier = context.getResources().getIdentifier( int identifier = context.getResources().getIdentifier(