Add ability to sideload text tracks and report them in onLoad
This commit is contained in:
		| @@ -16,8 +16,13 @@ import android.widget.FrameLayout; | ||||
| import com.brentvatne.react.R; | ||||
| import com.brentvatne.receiver.AudioBecomingNoisyReceiver; | ||||
| import com.brentvatne.receiver.BecomingNoisyListener; | ||||
| import com.facebook.react.bridge.Arguments; | ||||
| import com.facebook.react.bridge.Dynamic; | ||||
| import com.facebook.react.bridge.LifecycleEventListener; | ||||
| import com.facebook.react.bridge.ReadableArray; | ||||
| import com.facebook.react.bridge.ReadableMap; | ||||
| import com.facebook.react.bridge.WritableArray; | ||||
| import com.facebook.react.bridge.WritableMap; | ||||
| import com.facebook.react.uimanager.ThemedReactContext; | ||||
| import com.google.android.exoplayer2.C; | ||||
| import com.google.android.exoplayer2.DefaultLoadControl; | ||||
| @@ -62,7 +67,6 @@ import java.net.CookiePolicy; | ||||
| import java.lang.Math; | ||||
| import java.lang.Object; | ||||
| import java.util.ArrayList; | ||||
| import java.util.Arrays; | ||||
|  | ||||
| @SuppressLint("ViewConstructor") | ||||
| class ReactExoplayerView extends FrameLayout implements | ||||
| @@ -108,6 +112,7 @@ class ReactExoplayerView extends FrameLayout implements | ||||
|     private boolean repeat; | ||||
|     private String textTrackType; | ||||
|     private Dynamic textTrackValue; | ||||
|     private ReadableArray textTracks; | ||||
|     private boolean disableFocus; | ||||
|     private float mProgressUpdateInterval = 250.0f; | ||||
|     private boolean playInBackground = false; | ||||
| @@ -234,25 +239,17 @@ class ReactExoplayerView extends FrameLayout implements | ||||
|             player.setPlaybackParameters(params); | ||||
|         } | ||||
|         if (playerNeedsSource && srcUri != null) { | ||||
|             ArrayList<MediaSource> mediaSources = new ArrayList<>(); | ||||
|             mediaSources.add(buildMediaSource(srcUri, extension)); // video source | ||||
|             MediaSource text0 = buildTextSource( | ||||
|                     "ES VTT", | ||||
|                     Uri.parse("https://bitdash-a.akamaihd.net/content/sintel/subtitles/subtitles_es.vtt"), | ||||
|                     "vtt", | ||||
|                     "es" | ||||
|             ); | ||||
|             if (text0 != null) { | ||||
|                 mediaSources.add(text0); | ||||
|             } | ||||
|             ArrayList<MediaSource> mediaSourceList = buildTextSources(); | ||||
|             MediaSource videoSource = buildMediaSource(srcUri, extension); | ||||
|             MediaSource mediaSource; | ||||
|             if (mediaSources.size() > 1) { | ||||
|                 MediaSource[] textSourceArray = mediaSources.toArray( | ||||
|                         new MediaSource[mediaSources.size()] | ||||
|             if (mediaSourceList.size() == 0) { | ||||
|                 mediaSource = videoSource; | ||||
|             } else { | ||||
|                 mediaSourceList.add(0, videoSource); | ||||
|                 MediaSource[] textSourceArray = mediaSourceList.toArray( | ||||
|                         new MediaSource[mediaSourceList.size()] | ||||
|                 ); | ||||
|                 mediaSource = new MergingMediaSource(textSourceArray); | ||||
|             } else { | ||||
|                 mediaSource = mediaSources.get(0); | ||||
|             } | ||||
|  | ||||
|             boolean haveResumePosition = resumeWindow != C.INDEX_UNSET; | ||||
| @@ -288,6 +285,27 @@ class ReactExoplayerView extends FrameLayout implements | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private ArrayList<MediaSource> buildTextSources() { | ||||
|         ArrayList<MediaSource> textSources = new ArrayList<>(); | ||||
|         if (textTracks == null) { | ||||
|             return textSources; | ||||
|         } | ||||
|  | ||||
|         for (int i = 0; i < textTracks.size(); ++i) { | ||||
|             ReadableMap textTrack = textTracks.getMap(i); | ||||
|             String language = textTrack.getString("language"); | ||||
|             String title = textTrack.hasKey("title") | ||||
|                     ? textTrack.getString("title") : language + " " + i; | ||||
|             Uri uri = Uri.parse(textTrack.getString("uri")); | ||||
|             MediaSource textSource = buildTextSource(title, uri, textTrack.getString("type"), | ||||
|                     language); | ||||
|             if (textSource != null) { | ||||
|                 textSources.add(textSource); | ||||
|             } | ||||
|         } | ||||
|         return textSources; | ||||
|     } | ||||
|  | ||||
|     private MediaSource buildTextSource(String title, Uri uri, String mimeType, String language) { | ||||
|         String sampleType; | ||||
|         switch (mimeType) { | ||||
| @@ -494,10 +512,33 @@ class ReactExoplayerView extends FrameLayout implements | ||||
|             Format videoFormat = player.getVideoFormat(); | ||||
|             int width = videoFormat != null ? videoFormat.width : 0; | ||||
|             int height = videoFormat != null ? videoFormat.height : 0; | ||||
|             eventEmitter.load(player.getDuration(), player.getCurrentPosition(), width, height); | ||||
|             eventEmitter.load(player.getDuration(), player.getCurrentPosition(), width, height, | ||||
|                     getTextTrackInfo()); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private WritableArray getTextTrackInfo() { | ||||
|         WritableArray textTracks = Arguments.createArray(); | ||||
|  | ||||
|         MappingTrackSelector.MappedTrackInfo info = trackSelector.getCurrentMappedTrackInfo(); | ||||
|         int index = getTextTrackRendererIndex(); | ||||
|         if (info == null || index == C.INDEX_UNSET) { | ||||
|             return textTracks; | ||||
|         } | ||||
|  | ||||
|         TrackGroupArray groups = info.getTrackGroups(index); | ||||
|         for (int i = 0; i < groups.length; ++i) { | ||||
|              Format format = groups.get(i).getFormat(0); | ||||
|              WritableMap textTrack = Arguments.createMap(); | ||||
|              textTrack.putInt("index", i); | ||||
|              textTrack.putString("title", format.id); | ||||
|              textTrack.putString("type", format.sampleMimeType); | ||||
|              textTrack.putString("language", format.language); | ||||
|              textTracks.pushMap(textTrack); | ||||
|         } | ||||
|         return textTracks; | ||||
|     } | ||||
|  | ||||
|     private void onBuffering(boolean buffering) { | ||||
|         if (isBuffering == buffering) { | ||||
|             return; | ||||
| @@ -664,6 +705,11 @@ class ReactExoplayerView extends FrameLayout implements | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public void setTextTracks(ReadableArray textTracks) { | ||||
|         this.textTracks = textTracks; | ||||
|         reloadSource(); | ||||
|     } | ||||
|  | ||||
|     private void reloadSource() { | ||||
|         playerNeedsSource = true; | ||||
|         initializePlayer(); | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import android.net.Uri; | ||||
| import android.text.TextUtils; | ||||
|  | ||||
| import com.facebook.react.bridge.Dynamic; | ||||
| import com.facebook.react.bridge.ReadableArray; | ||||
| import com.facebook.react.bridge.ReadableMap; | ||||
| import com.facebook.react.common.MapBuilder; | ||||
| import com.facebook.react.uimanager.ThemedReactContext; | ||||
| @@ -28,6 +29,7 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi | ||||
|     private static final String PROP_SELECTED_TEXT_TRACK = "selectedTextTrack"; | ||||
|     private static final String PROP_SELECTED_TEXT_TRACK_TYPE = "type"; | ||||
|     private static final String PROP_SELECTED_TEXT_TRACK_VALUE = "value"; | ||||
|     private static final String PROP_TEXT_TRACKS = "textTracks"; | ||||
|     private static final String PROP_PAUSED = "paused"; | ||||
|     private static final String PROP_MUTED = "muted"; | ||||
|     private static final String PROP_VOLUME = "volume"; | ||||
| @@ -131,6 +133,12 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi | ||||
|         videoView.setSelectedTextTrack(typeString, value); | ||||
|     } | ||||
|  | ||||
|     @ReactProp(name = PROP_TEXT_TRACKS) | ||||
|     public void setPropTextTracks(final ReactExoplayerView videoView, | ||||
|                                   @Nullable ReadableArray textTracks) { | ||||
|         videoView.setTextTracks(textTracks); | ||||
|     } | ||||
|  | ||||
|     @ReactProp(name = PROP_PAUSED, defaultBoolean = false) | ||||
|     public void setPaused(final ReactExoplayerView videoView, final boolean paused) { | ||||
|         videoView.setPausedModifier(paused); | ||||
|   | ||||
| @@ -109,6 +109,7 @@ class VideoEventEmitter { | ||||
|     private static final String EVENT_PROP_WIDTH = "width"; | ||||
|     private static final String EVENT_PROP_HEIGHT = "height"; | ||||
|     private static final String EVENT_PROP_ORIENTATION = "orientation"; | ||||
|     private static final String EVENT_PROP_TEXT_TRACKS = "textTracks"; | ||||
|     private static final String EVENT_PROP_HAS_AUDIO_FOCUS = "hasAudioFocus"; | ||||
|     private static final String EVENT_PROP_IS_BUFFERING = "isBuffering"; | ||||
|     private static final String EVENT_PROP_PLAYBACK_RATE = "playbackRate"; | ||||
| @@ -128,7 +129,8 @@ class VideoEventEmitter { | ||||
|         receiveEvent(EVENT_LOAD_START, null); | ||||
|     } | ||||
|  | ||||
|     void load(double duration, double currentPosition, int videoWidth, int videoHeight) { | ||||
|     void load(double duration, double currentPosition, int videoWidth, int videoHeight, | ||||
|               WritableArray textTracks) { | ||||
|         WritableMap event = Arguments.createMap(); | ||||
|         event.putDouble(EVENT_PROP_DURATION, duration / 1000D); | ||||
|         event.putDouble(EVENT_PROP_CURRENT_TIME, currentPosition / 1000D); | ||||
| @@ -143,6 +145,8 @@ class VideoEventEmitter { | ||||
|         } | ||||
|         event.putMap(EVENT_PROP_NATURAL_SIZE, naturalSize); | ||||
|  | ||||
|         event.putArray(EVENT_PROP_TEXT_TRACKS, textTracks); | ||||
|  | ||||
|         // TODO: Actually check if you can. | ||||
|         event.putBoolean(EVENT_PROP_FAST_FORWARD, true); | ||||
|         event.putBoolean(EVENT_PROP_SLOW_FORWARD, true); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user