From e4da5c97734862e6a3585d06088b7aed336166e8 Mon Sep 17 00:00:00 2001 From: benlime Date: Sun, 30 Apr 2017 13:43:01 +0200 Subject: [PATCH 01/57] adds resizeMode to poster image --- Video.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Video.js b/Video.js index 4d69b333..ed55b7fc 100644 --- a/Video.js +++ b/Video.js @@ -217,7 +217,6 @@ export default class Video extends Component { top: 0, right: 0, bottom: 0, - resizeMode: 'contain', }; return ( @@ -229,6 +228,7 @@ export default class Video extends Component { ); @@ -271,6 +271,7 @@ Video.propTypes = { ]), resizeMode: PropTypes.string, poster: PropTypes.string, + posterResizeMode: Image.propTypes.resizeMode, repeat: PropTypes.bool, paused: PropTypes.bool, muted: PropTypes.bool, From 435669a944430fa51b8bbd640c6bf66c7756a1ce Mon Sep 17 00:00:00 2001 From: Dan Hodos Date: Thu, 28 Sep 2017 21:37:26 -0400 Subject: [PATCH 02/57] Extract method to add observer for progress update --- ios/RCTVideo.m | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/ios/RCTVideo.m b/ios/RCTVideo.m index 9962c2bb..88f3a640 100644 --- a/ios/RCTVideo.m +++ b/ios/RCTVideo.m @@ -124,6 +124,16 @@ static NSString *const timedMetadata = @"timedMetadata"; return (kCMTimeRangeZero); } +-(void)addPlayerTimeObserver +{ + const Float64 progressUpdateIntervalMS = _progressUpdateInterval / 1000; + // @see endScrubbing in AVPlayerDemoPlaybackViewController.m of https://developer.apple.com/library/ios/samplecode/AVPlayerDemo/Introduction/Intro.html + __weak RCTVideo *weakSelf = self; + _timeObserver = [_player addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(progressUpdateIntervalMS, NSEC_PER_SEC) + queue:NULL + usingBlock:^(CMTime time) { [weakSelf sendProgressUpdate]; } + ]; +} /* Cancels the previously registered time observer. */ -(void)removePlayerTimeObserver @@ -283,13 +293,7 @@ static NSString *const timedMetadata = @"timedMetadata"; [_player addObserver:self forKeyPath:playbackRate options:0 context:nil]; _playbackRateObserverRegistered = YES; - const Float64 progressUpdateIntervalMS = _progressUpdateInterval / 1000; - // @see endScrubbing in AVPlayerDemoPlaybackViewController.m of https://developer.apple.com/library/ios/samplecode/AVPlayerDemo/Introduction/Intro.html - __weak RCTVideo *weakSelf = self; - _timeObserver = [_player addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(progressUpdateIntervalMS, NSEC_PER_SEC) - queue:NULL - usingBlock:^(CMTime time) { [weakSelf sendProgressUpdate]; } - ]; + [self addPlayerTimeObserver]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ //Perform on next run loop, otherwise onVideoLoadStart is nil From 10cba5ad5c545a1ea6a6e7d53020f834466aa72e Mon Sep 17 00:00:00 2001 From: Dan Hodos Date: Thu, 28 Sep 2017 21:37:52 -0400 Subject: [PATCH 03/57] Reset progress observer on update interval changes --- ios/RCTVideo.m | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ios/RCTVideo.m b/ios/RCTVideo.m index 88f3a640..68e52e31 100644 --- a/ios/RCTVideo.m +++ b/ios/RCTVideo.m @@ -725,6 +725,11 @@ static NSString *const timedMetadata = @"timedMetadata"; - (void)setProgressUpdateInterval:(float)progressUpdateInterval { _progressUpdateInterval = progressUpdateInterval; + + if (_timeObserver) { + [self removePlayerTimeObserver]; + [self addPlayerTimeObserver]; + } } - (void)removePlayerLayer From 2ae99bd484486f468932db7830b7db8b69ccc507 Mon Sep 17 00:00:00 2001 From: Jan Lievens Date: Tue, 24 Oct 2017 09:47:43 +0200 Subject: [PATCH 04/57] remove observers before adding thus preventing multiple observers for the same notification --- ios/RCTVideo.m | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ios/RCTVideo.m b/ios/RCTVideo.m index 9962c2bb..ab0927c6 100644 --- a/ios/RCTVideo.m +++ b/ios/RCTVideo.m @@ -454,10 +454,17 @@ static NSString *const timedMetadata = @"timedMetadata"; - (void)attachListeners { // listen for end of file + [[NSNotificationCenter defaultCenter] removeObserver:self + name:AVPlayerItemDidPlayToEndTimeNotification + object:[_player currentItem]]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playerItemDidReachEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:[_player currentItem]]; + + [[NSNotificationCenter defaultCenter] removeObserver:self + name:AVPlayerItemPlaybackStalledNotification + object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackStalled:) name:AVPlayerItemPlaybackStalledNotification From 5d274631c8d742a5faa49532bf0a967da760be2c Mon Sep 17 00:00:00 2001 From: Brandon Moon Date: Mon, 29 Jan 2018 13:25:58 -0700 Subject: [PATCH 05/57] Link up cookies so exoplayer can use them --- .../brentvatne/exoplayer/DataSourceUtil.java | 31 +++++++++++++------ .../exoplayer/ReactExoplayerView.java | 16 +++------- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/DataSourceUtil.java b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/DataSourceUtil.java index 0077c3b0..c486bf0b 100644 --- a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/DataSourceUtil.java +++ b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/DataSourceUtil.java @@ -1,7 +1,11 @@ package com.brentvatne.exoplayer; import android.content.Context; +import android.content.ContextWrapper; +import com.facebook.react.bridge.ReactContext; +import com.facebook.react.modules.network.CookieJarContainer; +import com.facebook.react.modules.network.ForwardingCookieHandler; import com.facebook.react.modules.network.OkHttpClientProvider; import com.google.android.exoplayer2.ext.okhttp.OkHttpDataSourceFactory; import com.google.android.exoplayer2.upstream.DataSource; @@ -10,6 +14,10 @@ import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; import com.google.android.exoplayer2.upstream.HttpDataSource; import com.google.android.exoplayer2.util.Util; +import okhttp3.Cookie; +import okhttp3.JavaNetCookieJar; +import okhttp3.OkHttpClient; + public class DataSourceUtil { private DataSourceUtil() { @@ -23,14 +31,14 @@ public class DataSourceUtil { DataSourceUtil.userAgent = userAgent; } - public static String getUserAgent(Context context) { + public static String getUserAgent(ReactContext context) { if (userAgent == null) { - userAgent = Util.getUserAgent(context.getApplicationContext(), "ReactNativeVideo"); + userAgent = Util.getUserAgent(context, "ReactNativeVideo"); } return userAgent; } - public static DataSource.Factory getRawDataSourceFactory(Context context) { + public static DataSource.Factory getRawDataSourceFactory(ReactContext context) { if (rawDataSourceFactory == null) { rawDataSourceFactory = buildRawDataSourceFactory(context); } @@ -41,7 +49,7 @@ public class DataSourceUtil { DataSourceUtil.rawDataSourceFactory = factory; } - public static DataSource.Factory getDefaultDataSourceFactory(Context context, DefaultBandwidthMeter bandwidthMeter) { + public static DataSource.Factory getDefaultDataSourceFactory(ReactContext context, DefaultBandwidthMeter bandwidthMeter) { if (defaultDataSourceFactory == null) { defaultDataSourceFactory = buildDataSourceFactory(context, bandwidthMeter); } @@ -52,17 +60,20 @@ public class DataSourceUtil { DataSourceUtil.defaultDataSourceFactory = factory; } - private static DataSource.Factory buildRawDataSourceFactory(Context context) { + private static DataSource.Factory buildRawDataSourceFactory(ReactContext context) { return new RawResourceDataSourceFactory(context.getApplicationContext()); } - private static DataSource.Factory buildDataSourceFactory(Context context, DefaultBandwidthMeter bandwidthMeter) { - Context appContext = context.getApplicationContext(); - return new DefaultDataSourceFactory(appContext, bandwidthMeter, - buildHttpDataSourceFactory(appContext, bandwidthMeter)); + private static DataSource.Factory buildDataSourceFactory(ReactContext context, DefaultBandwidthMeter bandwidthMeter) { + return new DefaultDataSourceFactory(context, bandwidthMeter, + buildHttpDataSourceFactory(context, bandwidthMeter)); } - private static HttpDataSource.Factory buildHttpDataSourceFactory(Context context, DefaultBandwidthMeter bandwidthMeter) { + private static HttpDataSource.Factory buildHttpDataSourceFactory(ReactContext context, DefaultBandwidthMeter bandwidthMeter) { + OkHttpClient client = OkHttpClientProvider.getOkHttpClient(); + CookieJarContainer container = (CookieJarContainer) client.cookieJar(); + ForwardingCookieHandler handler = new ForwardingCookieHandler(context); + container.setCookieJar(new JavaNetCookieJar(handler)); return new OkHttpDataSourceFactory(OkHttpClientProvider.getOkHttpClient(), getUserAgent(context), bandwidthMeter); } diff --git a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java index f24d94c2..074531af 100644 --- a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java +++ b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java @@ -124,14 +124,13 @@ class ReactExoplayerView extends FrameLayout implements public ReactExoplayerView(ThemedReactContext context) { super(context); + this.themedReactContext = context; createViews(); this.eventEmitter = new VideoEventEmitter(context); - this.themedReactContext = context; audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); themedReactContext.addLifecycleEventListener(this); audioBecomingNoisyReceiver = new AudioBecomingNoisyReceiver(themedReactContext); - initializePlayer(); } @@ -353,7 +352,7 @@ class ReactExoplayerView extends FrameLayout implements * @return A new DataSource factory. */ private DataSource.Factory buildDataSourceFactory(boolean useBandwidthMeter) { - return DataSourceUtil.getDefaultDataSourceFactory(getContext(), useBandwidthMeter ? BANDWIDTH_METER : null); + return DataSourceUtil.getDefaultDataSourceFactory(this.themedReactContext, useBandwidthMeter ? BANDWIDTH_METER : null); } // AudioManager.OnAudioFocusChangeListener implementation @@ -482,7 +481,6 @@ class ReactExoplayerView extends FrameLayout implements @Override public void onPlayerError(ExoPlaybackException e) { String errorString = null; - Exception ex = e; if (e.type == ExoPlaybackException.TYPE_RENDERER) { Exception cause = e.getRendererException(); if (cause instanceof MediaCodecRenderer.DecoderInitializationException) { @@ -505,12 +503,8 @@ class ReactExoplayerView extends FrameLayout implements } } } - else if (e.type == ExoPlaybackException.TYPE_SOURCE) { - ex = e.getSourceException(); - errorString = getResources().getString(R.string.unrecognized_media_format); - } if (errorString != null) { - eventEmitter.error(errorString, ex); + eventEmitter.error(errorString, e); } playerNeedsSource = true; if (isBehindLiveWindow(e)) { @@ -549,7 +543,7 @@ class ReactExoplayerView extends FrameLayout implements this.srcUri = uri; this.extension = extension; - this.mediaDataSourceFactory = DataSourceUtil.getDefaultDataSourceFactory(getContext(), BANDWIDTH_METER); + this.mediaDataSourceFactory = DataSourceUtil.getDefaultDataSourceFactory(this.themedReactContext, BANDWIDTH_METER); if (!isOriginalSourceNull && !isSourceEqual) { reloadSource(); @@ -568,7 +562,7 @@ class ReactExoplayerView extends FrameLayout implements this.srcUri = uri; this.extension = extension; - this.mediaDataSourceFactory = DataSourceUtil.getRawDataSourceFactory(getContext()); + this.mediaDataSourceFactory = DataSourceUtil.getRawDataSourceFactory(this.themedReactContext); if (!isOriginalSourceNull && !isSourceEqual) { reloadSource(); From f2e182addc70cb380b56db190b62cca56d3dcac4 Mon Sep 17 00:00:00 2001 From: Brandon Moon Date: Mon, 29 Jan 2018 13:32:31 -0700 Subject: [PATCH 06/57] Bring things up to date with master from copied code --- .../java/com/brentvatne/exoplayer/ReactExoplayerView.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java index 074531af..cf8ebc28 100644 --- a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java +++ b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java @@ -131,6 +131,7 @@ class ReactExoplayerView extends FrameLayout implements themedReactContext.addLifecycleEventListener(this); audioBecomingNoisyReceiver = new AudioBecomingNoisyReceiver(themedReactContext); + initializePlayer(); } @@ -481,6 +482,7 @@ class ReactExoplayerView extends FrameLayout implements @Override public void onPlayerError(ExoPlaybackException e) { String errorString = null; + Exception ex = e; if (e.type == ExoPlaybackException.TYPE_RENDERER) { Exception cause = e.getRendererException(); if (cause instanceof MediaCodecRenderer.DecoderInitializationException) { @@ -503,8 +505,12 @@ class ReactExoplayerView extends FrameLayout implements } } } + else if (e.type == ExoPlaybackException.TYPE_SOURCE) { + ex = e.getSourceException(); + errorString = getResources().getString(R.string.unrecognized_media_format); + } if (errorString != null) { - eventEmitter.error(errorString, e); + eventEmitter.error(errorString, ex); } playerNeedsSource = true; if (isBehindLiveWindow(e)) { From 28bae40c6c0d5b58bb30c2e56249b91fe7ae115d Mon Sep 17 00:00:00 2001 From: seansy Date: Mon, 19 Mar 2018 12:56:55 -0700 Subject: [PATCH 07/57] Fixes #963 Bug happens when uri is changed for a video. The fix: Remove player layer before addPlayerItemObservers so _playerItemObserversSet is still set to NO if observers have already been removed. --- ios/RCTVideo.m | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/ios/RCTVideo.m b/ios/RCTVideo.m index 0f1227b1..ab0d5879 100644 --- a/ios/RCTVideo.m +++ b/ios/RCTVideo.m @@ -140,8 +140,8 @@ static NSString *const timedMetadata = @"timedMetadata"; - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; - [self removePlayerItemObservers]; [self removePlayerLayer]; + [self removePlayerItemObservers]; [_player removeObserver:self forKeyPath:playbackRate context:nil]; } @@ -252,9 +252,6 @@ static NSString *const timedMetadata = @"timedMetadata"; * observer set */ - (void)removePlayerItemObservers { - if (_playerLayer) { - [_playerLayer removeObserver:self forKeyPath:readyForDisplayKeyPath]; - } if (_playerItemObserversSet) { [_playerItem removeObserver:self forKeyPath:statusKeyPath]; [_playerItem removeObserver:self forKeyPath:playbackBufferEmptyKeyPath]; @@ -268,13 +265,13 @@ static NSString *const timedMetadata = @"timedMetadata"; - (void)setSrc:(NSDictionary *)source { + [self removePlayerLayer]; [self removePlayerTimeObserver]; [self removePlayerItemObservers]; _playerItem = [self playerItemForSource:source]; [self addPlayerItemObservers]; [_player pause]; - [self removePlayerLayer]; [_playerViewController.view removeFromSuperview]; _playerViewController = nil; From c8d44448c79e01b506a104356057e3255c1725c3 Mon Sep 17 00:00:00 2001 From: Hampton Maxwell Date: Tue, 29 May 2018 15:25:29 -0700 Subject: [PATCH 08/57] Remove obsolete metadata code that shouldn't have been included --- .../java/com/brentvatne/exoplayer/ExoPlayerView.java | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ExoPlayerView.java b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ExoPlayerView.java index e4a7a57b..4eff8a6b 100644 --- a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ExoPlayerView.java +++ b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ExoPlayerView.java @@ -18,8 +18,6 @@ import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.PlaybackParameters; import com.google.android.exoplayer2.SimpleExoPlayer; import com.google.android.exoplayer2.Timeline; -import com.google.android.exoplayer2.metadata.Metadata; -import com.google.android.exoplayer2.metadata.MetadataRenderer; import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.text.Cue; import com.google.android.exoplayer2.text.TextRenderer; @@ -101,7 +99,6 @@ public final class ExoPlayerView extends FrameLayout { this.player.setVideoListener(null); this.player.removeListener(componentListener); this.player.setVideoSurface(null); - this.player.setMetadataOutput(componentListener); } this.player = player; shutterView.setVisibility(VISIBLE); @@ -114,7 +111,6 @@ public final class ExoPlayerView extends FrameLayout { player.setVideoListener(componentListener); player.addListener(componentListener); player.setTextOutput(componentListener); - player.setMetadataOutput(componentListener); } } @@ -168,7 +164,7 @@ public final class ExoPlayerView extends FrameLayout { } private final class ComponentListener implements SimpleExoPlayer.VideoListener, - TextRenderer.Output, ExoPlayer.EventListener, MetadataRenderer.Output { + TextRenderer.Output, ExoPlayer.EventListener { // TextRenderer.Output implementation @@ -232,11 +228,6 @@ public final class ExoPlayerView extends FrameLayout { // Do nothing } - @Override - public void onMetadata(Metadata metadata) { - Log.d("onMetadata", "onMetadata"); - } - @Override public void onSeekProcessed() { // Do nothing. From dc6eed21005df63a4b246f8ccde5e6f547c0182d Mon Sep 17 00:00:00 2001 From: Hampton Maxwell Date: Tue, 29 May 2018 16:12:51 -0700 Subject: [PATCH 09/57] Initial commit --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..b50bd3f3 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,5 @@ +## Changelog + +Upcoming release +* Remove ExoPlayer onMetadata that wasn't being used (https://github.com/react-native-community/react-native-video/pull/1040) +* Fix bug where setting the progress interval on iOS didn't work (https://github.com/react-native-community/react-native-video/pull/800) From e47e2a969de33de99952b33c25415b41132265d6 Mon Sep 17 00:00:00 2001 From: Hampton Maxwell Date: Tue, 29 May 2018 16:22:46 -0700 Subject: [PATCH 10/57] Maintain default poster resize mode Set contain as the default mode when not specified --- Video.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Video.js b/Video.js index ed55b7fc..a6c04ed5 100644 --- a/Video.js +++ b/Video.js @@ -217,6 +217,7 @@ export default class Video extends Component { top: 0, right: 0, bottom: 0, + resizeMode: this.props.posterResizeMode || 'contain' }; return ( @@ -228,7 +229,6 @@ export default class Video extends Component { ); From b4d1ee78acc0f832e9e29b1c8471db09af277332 Mon Sep 17 00:00:00 2001 From: Hampton Maxwell Date: Tue, 29 May 2018 16:24:47 -0700 Subject: [PATCH 11/57] Add note for poster resize mode --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b50bd3f3..21b4a04e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,3 +3,4 @@ Upcoming release * Remove ExoPlayer onMetadata that wasn't being used (https://github.com/react-native-community/react-native-video/pull/1040) * Fix bug where setting the progress interval on iOS didn't work (https://github.com/react-native-community/react-native-video/pull/800) +* Support setting the poster resize mode (https://github.com/react-native-community/react-native-video/pull/595) From cfc7da2a31d743c7fb65b4e7a03bf2e3a58de476 Mon Sep 17 00:00:00 2001 From: Hampton Maxwell Date: Tue, 29 May 2018 16:27:11 -0700 Subject: [PATCH 12/57] Add docs for posterResizeMode flag --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 0a3afb03..50435ae6 100644 --- a/README.md +++ b/README.md @@ -182,6 +182,7 @@ using System.Collections.Generic;