|  |  |  | @@ -27,26 +27,25 @@ import com.facebook.react.bridge.WritableMap; | 
		
	
		
			
				|  |  |  |  | import com.facebook.react.uimanager.ThemedReactContext; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.C; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.DefaultLoadControl; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.DefaultRenderersFactory; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.ExoPlaybackException; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.ExoPlayer; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.ExoPlayerFactory; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.Format; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.PlaybackParameters; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.Player; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.SimpleExoPlayer; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.Timeline; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.mediacodec.MediaCodecRenderer; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.mediacodec.MediaCodecUtil; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.metadata.Metadata; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.metadata.MetadataRenderer; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.metadata.MetadataOutput; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.source.BehindLiveWindowException; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.source.ExtractorMediaSource; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.source.MediaSource; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.source.MergingMediaSource; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.source.ProgressiveMediaSource; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.source.SingleSampleMediaSource; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.source.TrackGroupArray; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.source.TrackGroup; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.source.TrackGroupArray; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.source.dash.DashMediaSource; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.source.dash.DefaultDashChunkSource; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.source.hls.HlsMediaSource; | 
		
	
	
		
			
				
					
					|  |  |  | @@ -54,42 +53,36 @@ import com.google.android.exoplayer2.source.smoothstreaming.DefaultSsChunkSource | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.trackselection.FixedTrackSelection; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.trackselection.MappingTrackSelector; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.trackselection.TrackSelection; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.trackselection.TrackSelectionArray; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.ui.PlayerControlView; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.upstream.BandwidthMeter; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.upstream.DataSource; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.upstream.DefaultAllocator; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.upstream.BandwidthMeter; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.util.MimeTypes; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.util.Util; | 
		
	
		
			
				|  |  |  |  | import com.google.android.exoplayer2.ui.PlayerControlView; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | import java.net.CookieHandler; | 
		
	
		
			
				|  |  |  |  | import java.net.CookieManager; | 
		
	
		
			
				|  |  |  |  | import java.net.CookiePolicy; | 
		
	
		
			
				|  |  |  |  | import java.lang.Math; | 
		
	
		
			
				|  |  |  |  | import java.util.Map; | 
		
	
		
			
				|  |  |  |  | import java.lang.Object; | 
		
	
		
			
				|  |  |  |  | import java.util.ArrayList; | 
		
	
		
			
				|  |  |  |  | import java.util.Locale; | 
		
	
		
			
				|  |  |  |  | import java.util.Map; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | @SuppressLint("ViewConstructor") | 
		
	
		
			
				|  |  |  |  | class ReactExoplayerView extends FrameLayout implements | 
		
	
		
			
				|  |  |  |  |         LifecycleEventListener, | 
		
	
		
			
				|  |  |  |  |         ExoPlayer.EventListener, | 
		
	
		
			
				|  |  |  |  |         Player.EventListener, | 
		
	
		
			
				|  |  |  |  |         BandwidthMeter.EventListener, | 
		
	
		
			
				|  |  |  |  |         BecomingNoisyListener, | 
		
	
		
			
				|  |  |  |  |         AudioManager.OnAudioFocusChangeListener, | 
		
	
		
			
				|  |  |  |  |         MetadataRenderer.Output { | 
		
	
		
			
				|  |  |  |  |         MetadataOutput { | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     private static final String TAG = "ReactExoplayerView"; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     private static final DefaultBandwidthMeter BANDWIDTH_METER = new DefaultBandwidthMeter(); | 
		
	
		
			
				|  |  |  |  |     private static final CookieManager DEFAULT_COOKIE_MANAGER; | 
		
	
		
			
				|  |  |  |  |     private static final int SHOW_PROGRESS = 1; | 
		
	
		
			
				|  |  |  |  |     private static final int REPORT_BANDWIDTH = 1; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     static { | 
		
	
		
			
				|  |  |  |  |         DEFAULT_COOKIE_MANAGER = new CookieManager(); | 
		
	
	
		
			
				
					
					|  |  |  | @@ -97,11 +90,12 @@ class ReactExoplayerView extends FrameLayout implements | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     private final VideoEventEmitter eventEmitter; | 
		
	
		
			
				|  |  |  |  |     private final ReactExoplayerConfig config; | 
		
	
		
			
				|  |  |  |  |     private final DefaultBandwidthMeter bandwidthMeter; | 
		
	
		
			
				|  |  |  |  |     private PlayerControlView playerControlView; | 
		
	
		
			
				|  |  |  |  |     private View playPauseControlContainer; | 
		
	
		
			
				|  |  |  |  |     private Player.EventListener eventListener; | 
		
	
		
			
				|  |  |  |  |      | 
		
	
		
			
				|  |  |  |  |     private Handler mainHandler; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     private ExoPlayerView exoPlayerView; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     private DataSource.Factory mediaDataSourceFactory; | 
		
	
	
		
			
				
					
					|  |  |  | @@ -135,8 +129,7 @@ class ReactExoplayerView extends FrameLayout implements | 
		
	
		
			
				|  |  |  |  |     private String audioTrackType; | 
		
	
		
			
				|  |  |  |  |     private Dynamic audioTrackValue; | 
		
	
		
			
				|  |  |  |  |     private String videoTrackType; | 
		
	
		
			
				|  |  |  |  |     private Dynamic videoTrackValue;     | 
		
	
		
			
				|  |  |  |  |     private ReadableArray audioTracks; | 
		
	
		
			
				|  |  |  |  |     private Dynamic videoTrackValue; | 
		
	
		
			
				|  |  |  |  |     private String textTrackType; | 
		
	
		
			
				|  |  |  |  |     private Dynamic textTrackValue; | 
		
	
		
			
				|  |  |  |  |     private ReadableArray textTracks; | 
		
	
	
		
			
				
					
					|  |  |  | @@ -159,7 +152,7 @@ class ReactExoplayerView extends FrameLayout implements | 
		
	
		
			
				|  |  |  |  |             switch (msg.what) { | 
		
	
		
			
				|  |  |  |  |                 case SHOW_PROGRESS: | 
		
	
		
			
				|  |  |  |  |                     if (player != null | 
		
	
		
			
				|  |  |  |  |                             && player.getPlaybackState() == ExoPlayer.STATE_READY | 
		
	
		
			
				|  |  |  |  |                             && player.getPlaybackState() == Player.STATE_READY | 
		
	
		
			
				|  |  |  |  |                             && player.getPlayWhenReady() | 
		
	
		
			
				|  |  |  |  |                             ) { | 
		
	
		
			
				|  |  |  |  |                         long pos = player.getCurrentPosition(); | 
		
	
	
		
			
				
					
					|  |  |  | @@ -173,14 +166,15 @@ class ReactExoplayerView extends FrameLayout implements | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |     }; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     public ReactExoplayerView(ThemedReactContext context) { | 
		
	
		
			
				|  |  |  |  |     public ReactExoplayerView(ThemedReactContext context, ReactExoplayerConfig config) { | 
		
	
		
			
				|  |  |  |  |         super(context); | 
		
	
		
			
				|  |  |  |  |         this.themedReactContext = context; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |         this.eventEmitter = new VideoEventEmitter(context); | 
		
	
		
			
				|  |  |  |  |         this.config = config; | 
		
	
		
			
				|  |  |  |  |         this.bandwidthMeter = config.getBandwidthMeter(); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |         createViews(); | 
		
	
		
			
				|  |  |  |  |          | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |         audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); | 
		
	
		
			
				|  |  |  |  |         themedReactContext.addLifecycleEventListener(this); | 
		
	
		
			
				|  |  |  |  |         audioBecomingNoisyReceiver = new AudioBecomingNoisyReceiver(themedReactContext); | 
		
	
	
		
			
				
					
					|  |  |  | @@ -198,7 +192,6 @@ class ReactExoplayerView extends FrameLayout implements | 
		
	
		
			
				|  |  |  |  |     private void createViews() { | 
		
	
		
			
				|  |  |  |  |         clearResumePosition(); | 
		
	
		
			
				|  |  |  |  |         mediaDataSourceFactory = buildDataSourceFactory(true); | 
		
	
		
			
				|  |  |  |  |         mainHandler = new Handler(); | 
		
	
		
			
				|  |  |  |  |         if (CookieHandler.getDefault() != DEFAULT_COOKIE_MANAGER) { | 
		
	
		
			
				|  |  |  |  |             CookieHandler.setDefault(DEFAULT_COOKIE_MANAGER); | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
	
		
			
				
					
					|  |  |  | @@ -266,7 +259,7 @@ class ReactExoplayerView extends FrameLayout implements | 
		
	
		
			
				|  |  |  |  |     // Internal methods | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     /** | 
		
	
		
			
				|  |  |  |  |      * Toggling the visibility of the player control view  | 
		
	
		
			
				|  |  |  |  |      * Toggling the visibility of the player control view | 
		
	
		
			
				|  |  |  |  |      */ | 
		
	
		
			
				|  |  |  |  |     private void togglePlayerControlVisibility() { | 
		
	
		
			
				|  |  |  |  |         if(player == null) return; | 
		
	
	
		
			
				
					
					|  |  |  | @@ -342,24 +335,34 @@ class ReactExoplayerView extends FrameLayout implements | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     private void initializePlayer() { | 
		
	
		
			
				|  |  |  |  |         ReactExoplayerView self = this; | 
		
	
		
			
				|  |  |  |  |         // This ensures all props have been setted, to avoid async racing conditions. | 
		
	
		
			
				|  |  |  |  |         // This ensures all props have been settled, to avoid async racing conditions. | 
		
	
		
			
				|  |  |  |  |         new Handler().postDelayed(new Runnable() { | 
		
	
		
			
				|  |  |  |  |             @Override | 
		
	
		
			
				|  |  |  |  |             public void run() { | 
		
	
		
			
				|  |  |  |  |                 if (player == null) { | 
		
	
		
			
				|  |  |  |  |                     TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(BANDWIDTH_METER); | 
		
	
		
			
				|  |  |  |  |                     TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(); | 
		
	
		
			
				|  |  |  |  |                     trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory); | 
		
	
		
			
				|  |  |  |  |                     trackSelector.setParameters(trackSelector.buildUponParameters() | 
		
	
		
			
				|  |  |  |  |                             .setMaxVideoBitrate(maxBitRate == 0 ? Integer.MAX_VALUE : maxBitRate)); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |                     DefaultAllocator allocator = new DefaultAllocator(true, C.DEFAULT_BUFFER_SEGMENT_SIZE); | 
		
	
		
			
				|  |  |  |  |                     DefaultLoadControl defaultLoadControl = new DefaultLoadControl(allocator, minBufferMs, maxBufferMs, bufferForPlaybackMs, bufferForPlaybackAfterRebufferMs, -1, true); | 
		
	
		
			
				|  |  |  |  |                     player = ExoPlayerFactory.newSimpleInstance(getContext(), trackSelector, defaultLoadControl); | 
		
	
		
			
				|  |  |  |  |                     DefaultLoadControl.Builder defaultLoadControlBuilder = new DefaultLoadControl.Builder(); | 
		
	
		
			
				|  |  |  |  |                     defaultLoadControlBuilder.setAllocator(allocator); | 
		
	
		
			
				|  |  |  |  |                     defaultLoadControlBuilder.setBufferDurationsMs(minBufferMs, maxBufferMs, bufferForPlaybackMs, bufferForPlaybackAfterRebufferMs); | 
		
	
		
			
				|  |  |  |  |                     defaultLoadControlBuilder.setTargetBufferBytes(-1); | 
		
	
		
			
				|  |  |  |  |                     defaultLoadControlBuilder.setPrioritizeTimeOverSizeThresholds(true); | 
		
	
		
			
				|  |  |  |  |                     DefaultLoadControl defaultLoadControl = defaultLoadControlBuilder.createDefaultLoadControl(); | 
		
	
		
			
				|  |  |  |  |                     DefaultRenderersFactory renderersFactory = | 
		
	
		
			
				|  |  |  |  |                             new DefaultRenderersFactory(getContext()) | 
		
	
		
			
				|  |  |  |  |                                     .setExtensionRendererMode(DefaultRenderersFactory.EXTENSION_RENDERER_MODE_OFF); | 
		
	
		
			
				|  |  |  |  |                     // TODO: Add drmSessionManager to 5th param from: https://github.com/react-native-community/react-native-video/pull/1445 | 
		
	
		
			
				|  |  |  |  |                     player = ExoPlayerFactory.newSimpleInstance(getContext(), renderersFactory, | 
		
	
		
			
				|  |  |  |  |                             trackSelector, defaultLoadControl, null, bandwidthMeter); | 
		
	
		
			
				|  |  |  |  |                     player.addListener(self); | 
		
	
		
			
				|  |  |  |  |                     player.setMetadataOutput(self); | 
		
	
		
			
				|  |  |  |  |                     player.addMetadataOutput(self); | 
		
	
		
			
				|  |  |  |  |                     exoPlayerView.setPlayer(player); | 
		
	
		
			
				|  |  |  |  |                     audioBecomingNoisyReceiver.setListener(self); | 
		
	
		
			
				|  |  |  |  |                     BANDWIDTH_METER.addEventListener(new Handler(), self); | 
		
	
		
			
				|  |  |  |  |                     bandwidthMeter.addEventListener(new Handler(), self); | 
		
	
		
			
				|  |  |  |  |                     setPlayWhenReady(!isPaused); | 
		
	
		
			
				|  |  |  |  |                     playerNeedsSource = true; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
	
		
			
				
					
					|  |  |  | @@ -404,21 +407,31 @@ class ReactExoplayerView extends FrameLayout implements | 
		
	
		
			
				|  |  |  |  |                 : uri.getLastPathSegment()); | 
		
	
		
			
				|  |  |  |  |         switch (type) { | 
		
	
		
			
				|  |  |  |  |             case C.TYPE_SS: | 
		
	
		
			
				|  |  |  |  |                 return new SsMediaSource(uri, buildDataSourceFactory(false), | 
		
	
		
			
				|  |  |  |  |                         new DefaultSsChunkSource.Factory(mediaDataSourceFactory),  | 
		
	
		
			
				|  |  |  |  |                         minLoadRetryCount, SsMediaSource.DEFAULT_LIVE_PRESENTATION_DELAY_MS,  | 
		
	
		
			
				|  |  |  |  |                         mainHandler, null); | 
		
	
		
			
				|  |  |  |  |                 return new SsMediaSource.Factory( | 
		
	
		
			
				|  |  |  |  |                         new DefaultSsChunkSource.Factory(mediaDataSourceFactory), | 
		
	
		
			
				|  |  |  |  |                         buildDataSourceFactory(false) | 
		
	
		
			
				|  |  |  |  |                 ).setLoadErrorHandlingPolicy( | 
		
	
		
			
				|  |  |  |  |                         config.buildLoadErrorHandlingPolicy(minLoadRetryCount) | 
		
	
		
			
				|  |  |  |  |                 ).createMediaSource(uri); | 
		
	
		
			
				|  |  |  |  |             case C.TYPE_DASH: | 
		
	
		
			
				|  |  |  |  |                 return new DashMediaSource(uri, buildDataSourceFactory(false), | 
		
	
		
			
				|  |  |  |  |                         new DefaultDashChunkSource.Factory(mediaDataSourceFactory),  | 
		
	
		
			
				|  |  |  |  |                         minLoadRetryCount, DashMediaSource.DEFAULT_LIVE_PRESENTATION_DELAY_MS, | 
		
	
		
			
				|  |  |  |  |                         mainHandler, null); | 
		
	
		
			
				|  |  |  |  |                 return new DashMediaSource.Factory( | 
		
	
		
			
				|  |  |  |  |                         new DefaultDashChunkSource.Factory(mediaDataSourceFactory), | 
		
	
		
			
				|  |  |  |  |                         buildDataSourceFactory(false) | 
		
	
		
			
				|  |  |  |  |                 ).setLoadErrorHandlingPolicy( | 
		
	
		
			
				|  |  |  |  |                         config.buildLoadErrorHandlingPolicy(minLoadRetryCount) | 
		
	
		
			
				|  |  |  |  |                 ).createMediaSource(uri); | 
		
	
		
			
				|  |  |  |  |             case C.TYPE_HLS: | 
		
	
		
			
				|  |  |  |  |                 return new HlsMediaSource(uri, mediaDataSourceFactory,  | 
		
	
		
			
				|  |  |  |  |                         minLoadRetryCount, mainHandler, null); | 
		
	
		
			
				|  |  |  |  |                 return new HlsMediaSource.Factory( | 
		
	
		
			
				|  |  |  |  |                         mediaDataSourceFactory | 
		
	
		
			
				|  |  |  |  |                 ).setLoadErrorHandlingPolicy( | 
		
	
		
			
				|  |  |  |  |                         config.buildLoadErrorHandlingPolicy(minLoadRetryCount) | 
		
	
		
			
				|  |  |  |  |                 ).createMediaSource(uri); | 
		
	
		
			
				|  |  |  |  |             case C.TYPE_OTHER: | 
		
	
		
			
				|  |  |  |  |                 return new ExtractorMediaSource(uri, mediaDataSourceFactory, new DefaultExtractorsFactory(), | 
		
	
		
			
				|  |  |  |  |                         mainHandler, null); | 
		
	
		
			
				|  |  |  |  |                 return new ProgressiveMediaSource.Factory( | 
		
	
		
			
				|  |  |  |  |                         mediaDataSourceFactory | 
		
	
		
			
				|  |  |  |  |                 ).setLoadErrorHandlingPolicy( | 
		
	
		
			
				|  |  |  |  |                         config.buildLoadErrorHandlingPolicy(minLoadRetryCount) | 
		
	
		
			
				|  |  |  |  |                 ).createMediaSource(uri); | 
		
	
		
			
				|  |  |  |  |             default: { | 
		
	
		
			
				|  |  |  |  |                 throw new IllegalStateException("Unsupported type: " + type); | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
	
		
			
				
					
					|  |  |  | @@ -448,21 +461,22 @@ class ReactExoplayerView extends FrameLayout implements | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     private MediaSource buildTextSource(String title, Uri uri, String mimeType, String language) { | 
		
	
		
			
				|  |  |  |  |         Format textFormat = Format.createTextSampleFormat(title, mimeType, Format.NO_VALUE, language); | 
		
	
		
			
				|  |  |  |  |         return new SingleSampleMediaSource(uri, mediaDataSourceFactory, textFormat, C.TIME_UNSET); | 
		
	
		
			
				|  |  |  |  |         return new SingleSampleMediaSource.Factory(mediaDataSourceFactory) | 
		
	
		
			
				|  |  |  |  |                 .createMediaSource(uri, textFormat, C.TIME_UNSET); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     private void releasePlayer() { | 
		
	
		
			
				|  |  |  |  |         if (player != null) { | 
		
	
		
			
				|  |  |  |  |             updateResumePosition(); | 
		
	
		
			
				|  |  |  |  |             player.release(); | 
		
	
		
			
				|  |  |  |  |             player.setMetadataOutput(null); | 
		
	
		
			
				|  |  |  |  |             player.removeMetadataOutput(this); | 
		
	
		
			
				|  |  |  |  |             trackSelector = null; | 
		
	
		
			
				|  |  |  |  |             player = null; | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |         progressHandler.removeMessages(SHOW_PROGRESS); | 
		
	
		
			
				|  |  |  |  |         themedReactContext.removeLifecycleEventListener(this); | 
		
	
		
			
				|  |  |  |  |         audioBecomingNoisyReceiver.removeListener(); | 
		
	
		
			
				|  |  |  |  |         BANDWIDTH_METER.removeEventListener(this); | 
		
	
		
			
				|  |  |  |  |         bandwidthMeter.removeEventListener(this); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     private boolean requestAudioFocus() { | 
		
	
	
		
			
				
					
					|  |  |  | @@ -493,12 +507,12 @@ class ReactExoplayerView extends FrameLayout implements | 
		
	
		
			
				|  |  |  |  |     private void startPlayback() { | 
		
	
		
			
				|  |  |  |  |         if (player != null) { | 
		
	
		
			
				|  |  |  |  |             switch (player.getPlaybackState()) { | 
		
	
		
			
				|  |  |  |  |                 case ExoPlayer.STATE_IDLE: | 
		
	
		
			
				|  |  |  |  |                 case ExoPlayer.STATE_ENDED: | 
		
	
		
			
				|  |  |  |  |                 case Player.STATE_IDLE: | 
		
	
		
			
				|  |  |  |  |                 case Player.STATE_ENDED: | 
		
	
		
			
				|  |  |  |  |                     initializePlayer(); | 
		
	
		
			
				|  |  |  |  |                     break; | 
		
	
		
			
				|  |  |  |  |                 case ExoPlayer.STATE_BUFFERING: | 
		
	
		
			
				|  |  |  |  |                 case ExoPlayer.STATE_READY: | 
		
	
		
			
				|  |  |  |  |                 case Player.STATE_BUFFERING: | 
		
	
		
			
				|  |  |  |  |                 case Player.STATE_READY: | 
		
	
		
			
				|  |  |  |  |                     if (!player.getPlayWhenReady()) { | 
		
	
		
			
				|  |  |  |  |                         setPlayWhenReady(true); | 
		
	
		
			
				|  |  |  |  |                     } | 
		
	
	
		
			
				
					
					|  |  |  | @@ -551,12 +565,13 @@ class ReactExoplayerView extends FrameLayout implements | 
		
	
		
			
				|  |  |  |  |     /** | 
		
	
		
			
				|  |  |  |  |      * Returns a new DataSource factory. | 
		
	
		
			
				|  |  |  |  |      * | 
		
	
		
			
				|  |  |  |  |      * @param useBandwidthMeter Whether to set {@link #BANDWIDTH_METER} as a listener to the new | 
		
	
		
			
				|  |  |  |  |      * @param useBandwidthMeter Whether to set {@link #bandwidthMeter} as a listener to the new | 
		
	
		
			
				|  |  |  |  |      *                          DataSource factory. | 
		
	
		
			
				|  |  |  |  |      * @return A new DataSource factory. | 
		
	
		
			
				|  |  |  |  |      */ | 
		
	
		
			
				|  |  |  |  |     private DataSource.Factory buildDataSourceFactory(boolean useBandwidthMeter) { | 
		
	
		
			
				|  |  |  |  |         return DataSourceUtil.getDefaultDataSourceFactory(this.themedReactContext, useBandwidthMeter ? BANDWIDTH_METER : null, requestHeaders); | 
		
	
		
			
				|  |  |  |  |         return DataSourceUtil.getDefaultDataSourceFactory(this.themedReactContext, | 
		
	
		
			
				|  |  |  |  |                 useBandwidthMeter ? bandwidthMeter : null, requestHeaders); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     // AudioManager.OnAudioFocusChangeListener implementation | 
		
	
	
		
			
				
					
					|  |  |  | @@ -596,7 +611,7 @@ class ReactExoplayerView extends FrameLayout implements | 
		
	
		
			
				|  |  |  |  |         eventEmitter.audioBecomingNoisy(); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     // ExoPlayer.EventListener implementation | 
		
	
		
			
				|  |  |  |  |     // Player.EventListener implementation | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     @Override | 
		
	
		
			
				|  |  |  |  |     public void onLoadingChanged(boolean isLoading) { | 
		
	
	
		
			
				
					
					|  |  |  | @@ -607,26 +622,26 @@ class ReactExoplayerView extends FrameLayout implements | 
		
	
		
			
				|  |  |  |  |     public void onPlayerStateChanged(boolean playWhenReady, int playbackState) { | 
		
	
		
			
				|  |  |  |  |         String text = "onStateChanged: playWhenReady=" + playWhenReady + ", playbackState="; | 
		
	
		
			
				|  |  |  |  |         switch (playbackState) { | 
		
	
		
			
				|  |  |  |  |             case ExoPlayer.STATE_IDLE: | 
		
	
		
			
				|  |  |  |  |             case Player.STATE_IDLE: | 
		
	
		
			
				|  |  |  |  |                 text += "idle"; | 
		
	
		
			
				|  |  |  |  |                 eventEmitter.idle(); | 
		
	
		
			
				|  |  |  |  |                 break; | 
		
	
		
			
				|  |  |  |  |             case ExoPlayer.STATE_BUFFERING: | 
		
	
		
			
				|  |  |  |  |             case Player.STATE_BUFFERING: | 
		
	
		
			
				|  |  |  |  |                 text += "buffering"; | 
		
	
		
			
				|  |  |  |  |                 onBuffering(true); | 
		
	
		
			
				|  |  |  |  |                 break; | 
		
	
		
			
				|  |  |  |  |             case ExoPlayer.STATE_READY: | 
		
	
		
			
				|  |  |  |  |             case Player.STATE_READY: | 
		
	
		
			
				|  |  |  |  |                 text += "ready"; | 
		
	
		
			
				|  |  |  |  |                 eventEmitter.ready(); | 
		
	
		
			
				|  |  |  |  |                 onBuffering(false); | 
		
	
		
			
				|  |  |  |  |                 startProgressHandler(); | 
		
	
		
			
				|  |  |  |  |                 videoLoaded(); | 
		
	
		
			
				|  |  |  |  |                 //Setting the visibility for the playerControlView | 
		
	
		
			
				|  |  |  |  |                 if(playerControlView != null) { | 
		
	
		
			
				|  |  |  |  |                 if (playerControlView != null) { | 
		
	
		
			
				|  |  |  |  |                     playerControlView.show(); | 
		
	
		
			
				|  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |                 break; | 
		
	
		
			
				|  |  |  |  |             case ExoPlayer.STATE_ENDED: | 
		
	
		
			
				|  |  |  |  |             case Player.STATE_ENDED: | 
		
	
		
			
				|  |  |  |  |                 text += "ended"; | 
		
	
		
			
				|  |  |  |  |                 eventEmitter.end(); | 
		
	
		
			
				|  |  |  |  |                 onStopPlayback(); | 
		
	
	
		
			
				
					
					|  |  |  | @@ -752,7 +767,7 @@ class ReactExoplayerView extends FrameLayout implements | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |         // When repeat is turned on, reaching the end of the video will not cause a state change | 
		
	
		
			
				|  |  |  |  |         // so we need to explicitly detect it. | 
		
	
		
			
				|  |  |  |  |         if (reason == ExoPlayer.DISCONTINUITY_REASON_PERIOD_TRANSITION | 
		
	
		
			
				|  |  |  |  |         if (reason == Player.DISCONTINUITY_REASON_PERIOD_TRANSITION | 
		
	
		
			
				|  |  |  |  |                 && player.getRepeatMode() == Player.REPEAT_MODE_ONE) { | 
		
	
		
			
				|  |  |  |  |             eventEmitter.end(); | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
	
		
			
				
					
					|  |  |  | @@ -870,7 +885,9 @@ class ReactExoplayerView extends FrameLayout implements | 
		
	
		
			
				|  |  |  |  |             this.srcUri = uri; | 
		
	
		
			
				|  |  |  |  |             this.extension = extension; | 
		
	
		
			
				|  |  |  |  |             this.requestHeaders = headers; | 
		
	
		
			
				|  |  |  |  |             this.mediaDataSourceFactory = DataSourceUtil.getDefaultDataSourceFactory(this.themedReactContext, BANDWIDTH_METER, this.requestHeaders); | 
		
	
		
			
				|  |  |  |  |             this.mediaDataSourceFactory = | 
		
	
		
			
				|  |  |  |  |                     DataSourceUtil.getDefaultDataSourceFactory(this.themedReactContext, bandwidthMeter, | 
		
	
		
			
				|  |  |  |  |                             this.requestHeaders); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |             if (!isOriginalSourceNull && !isSourceEqual) { | 
		
	
		
			
				|  |  |  |  |                 reloadSource(); | 
		
	
	
		
			
				
					
					|  |  |  | @@ -884,7 +901,7 @@ class ReactExoplayerView extends FrameLayout implements | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     public void setReportBandwidth(boolean reportBandwidth) { | 
		
	
		
			
				|  |  |  |  |         mReportBandwidth = reportBandwidth; | 
		
	
		
			
				|  |  |  |  |     }    | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     public void setRawSrc(final Uri uri, final String extension) { | 
		
	
		
			
				|  |  |  |  |         if (uri != null) { | 
		
	
	
		
			
				
					
					|  |  |  | @@ -1010,7 +1027,7 @@ class ReactExoplayerView extends FrameLayout implements | 
		
	
		
			
				|  |  |  |  |             for (int j = 0; j < group.length; j++) { | 
		
	
		
			
				|  |  |  |  |                 tracks[j] = j; | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |         }  | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |         if (groupIndex == C.INDEX_UNSET) { | 
		
	
		
			
				|  |  |  |  |             trackSelector.setParameters(disableParameters); | 
		
	
	
		
			
				
					
					|  |  |  | @@ -1180,7 +1197,7 @@ class ReactExoplayerView extends FrameLayout implements | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     /** | 
		
	
		
			
				|  |  |  |  |      * Handling controls prop | 
		
	
		
			
				|  |  |  |  |      *  | 
		
	
		
			
				|  |  |  |  |      * | 
		
	
		
			
				|  |  |  |  |      * @param controls  Controls prop, if true enable controls, if false disable them | 
		
	
		
			
				|  |  |  |  |      */ | 
		
	
		
			
				|  |  |  |  |     public void setControls(boolean controls) { | 
		
	
	
		
			
				
					
					|  |  |  |   |