Skip to content

Commit

Permalink
Merge pull request TheWidlarzGroup#1627 from jenshandersson/posterfix
Browse files Browse the repository at this point in the history
Fixes bug where poster and video was displayed simultaneously

(rebased from commit 3a7be63)
  • Loading branch information
CHaNGeTe authored and Beau Ner committed Oct 10, 2019
1 parent 2283241 commit 25f34a9
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 28 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
* Change compileOnly to implementation on gradle (for newer gradle versions and react-native 0.59 support) [#1592](https://github.com/react-native-community/react-native-video/pull/1592)
* Replaced RCTBubblingEventBlock events by RCTDirectEventBlock to avoid event name collisions [#1625](https://github.com/react-native-community/react-native-video/pull/1625)
* Added `onPlaybackRateChange` to README [#1578](https://github.com/react-native-community/react-native-video/pull/1578)
* Added `onReadyForDisplay` to README [#1627](https://github.com/react-native-community/react-native-video/pull/1627)
* Improved handling of poster image. Fixes bug with displaying video and poster simultaneously. [#1627](https://github.com/react-native-community/react-native-video/pull/1627)
* Fix background audio stopping on iOS when using `controls` [#1614](https://github.com/react-native-community/react-native-video/pull/1614)

### Version 4.4.1
Expand Down
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ var styles = StyleSheet.create({
* [onFullscreenPlayerDidDismiss](#onfullscreenplayerdiddismiss)
* [onLoad](#onload)
* [onLoadStart](#onloadstart)
* [onReadyForDisplay](#onreadyfordisplay)
* [onPictureInPictureStatusChanged](#onpictureinpicturestatuschanged)
* [onPlaybackRateChange](#onplaybackratechange)
* [onProgress](#onprogress)
Expand Down Expand Up @@ -954,6 +955,17 @@ Example:

Platforms: all

#### onReadyForDisplay
Callback function that is called when the first video frame is ready for display. This is when the poster is removed.

Payload: none

* iOS: [readyForDisplay](https://developer.apple.com/documentation/avkit/avplayerviewcontroller/1615830-readyfordisplay?language=objc)
* Android: [MEDIA_INFO_VIDEO_RENDERING_START](https://developer.android.com/reference/android/media/MediaPlayer#MEDIA_INFO_VIDEO_RENDERING_START)
* Android ExoPlayer [STATE_READY](https://exoplayer.dev/doc/reference/com/google/android/exoplayer2/Player.html#STATE_READY)

Platforms: Android ExoPlayer, Android MediaPlayer, iOS, Web

#### onPictureInPictureStatusChanged
Callback function that is called when picture in picture becomes active or inactive.

Expand Down
40 changes: 22 additions & 18 deletions Video.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export default class Video extends Component {
super(props);

this.state = {
showPoster: true,
showPoster: !!props.poster
};
}

Expand Down Expand Up @@ -86,6 +86,12 @@ export default class Video extends Component {
this._root = component;
};

_hidePoster = () => {
if (this.state.showPoster) {
this.setState({showPoster: false});
}
}

_onLoadStart = (event) => {
if (this.props.onLoadStart) {
this.props.onLoadStart(event.nativeEvent);
Expand All @@ -100,6 +106,10 @@ export default class Video extends Component {
};

_onLoad = (event) => {
// Need to hide poster here for windows as onReadyForDisplay is not implemented
if (Platform.OS === 'windows') {
this._hidePoster();
}
if (this.props.onLoad) {
this.props.onLoad(event.nativeEvent);
}
Expand All @@ -124,10 +134,6 @@ export default class Video extends Component {
};

_onSeek = (event) => {
if (this.state.showPoster && !this.props.audioOnly) {
this.setState({showPoster: false});
}

if (this.props.onSeek) {
this.props.onSeek(event.nativeEvent);
}
Expand Down Expand Up @@ -170,6 +176,7 @@ export default class Video extends Component {
};

_onReadyForDisplay = (event) => {
this._hidePoster();
if (this.props.onReadyForDisplay) {
this.props.onReadyForDisplay(event.nativeEvent);
}
Expand All @@ -188,10 +195,6 @@ export default class Video extends Component {
};

_onPlaybackRateChange = (event) => {
if (this.state.showPoster && event.nativeEvent.playbackRate !== 0 && !this.props.audioOnly) {
this.setState({showPoster: false});
}

if (this.props.onPlaybackRateChange) {
this.props.onPlaybackRateChange(event.nativeEvent);
}
Expand Down Expand Up @@ -339,15 +342,16 @@ export default class Video extends Component {
};

return (
<React.Fragment>
<RCTVideo ref={this._assignRoot} {...nativeProps} />
{this.props.poster &&
this.state.showPoster && (
<View style={nativeProps.style}>
<Image style={posterStyle} source={{ uri: this.props.poster }} />
</View>
)}
</React.Fragment>
<View style={nativeProps.style}>
<RCTVideo
ref={this._assignRoot}
{...nativeProps}
style={StyleSheet.absoluteFill}
/>
{this.state.showPoster && (
<Image style={posterStyle} source={{ uri: this.props.poster }} />
)}
</View>
);
}
}
Expand Down
6 changes: 6 additions & 0 deletions dom/RCTVideo.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class RCTVideo extends RCTView {
this.videoElement = this.initializeVideoElement();
this.videoElement.addEventListener("ended", this.onEnd);
this.videoElement.addEventListener("loadeddata", this.onLoad);
this.videoElement.addEventListener("canplay", this.onReadyForDisplay);
this.videoElement.addEventListener("loadstart", this.onLoadStart);
this.videoElement.addEventListener("pause", this.onPause);
this.videoElement.addEventListener("play", this.onPlay);
Expand All @@ -51,6 +52,7 @@ class RCTVideo extends RCTView {
detachFromView(view: UIView) {
this.videoElement.removeEventListener("ended", this.onEnd);
this.videoElement.removeEventListener("loadeddata", this.onLoad);
this.videoElement.removeEventListener("canplay", this.onReadyForDisplay);
this.videoElement.removeEventListener("loadstart", this.onLoadStart);
this.videoElement.removeEventListener("pause", this.onPause);
this.videoElement.removeEventListener("play", this.onPlay);
Expand Down Expand Up @@ -203,6 +205,10 @@ class RCTVideo extends RCTView {
this.sendEvent("topVideoLoad", payload);
}

onReadyForDisplay = () => {
this.sendEvent("onReadyForDisplay");
}

onLoadStart = () => {
const src = this.videoElement.currentSrc;
const payload = {
Expand Down
20 changes: 10 additions & 10 deletions ios/Video/RCTVideo.m
Original file line number Diff line number Diff line change
Expand Up @@ -545,8 +545,6 @@ - (void)crankVideo2 {
[self setMaxBitRate:_maxBitRate];

[_player pause];
[_playerViewController.view removeFromSuperview];
_playerViewController = nil;

if (_playbackRateObserverRegistered) {
[_player removeObserver:self forKeyPath:playbackRate context:nil];
Expand Down Expand Up @@ -1048,7 +1046,10 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N
} else
return [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}

if([keyPath isEqualToString:readyForDisplayKeyPath] && [change objectForKey:NSKeyValueChangeNewKey] && self.onReadyForDisplay) {
self.onReadyForDisplay(@{@"target": self.reactTag});
return;
}
if (object == _playerItem) {
// When timeMetadata is read the event onTimedMetadata is triggered
if ([keyPath isEqualToString:timedMetadata]) {
Expand Down Expand Up @@ -1140,12 +1141,6 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N
_playerBufferEmpty = NO;
self.onVideoBuffer(@{@"isBuffering": @(NO), @"target": self.reactTag});
}
} else if (object == _playerLayer) {
if([keyPath isEqualToString:readyForDisplayKeyPath] && [change objectForKey:NSKeyValueChangeNewKey]) {
if([change objectForKey:NSKeyValueChangeNewKey] && self.onReadyForDisplay) {
self.onReadyForDisplay(@{@"target": self.reactTag});
}
}
} else if (object == _player) {
if([keyPath isEqualToString:playbackRate]) {
if(self.onPlaybackRateChange) {
Expand Down Expand Up @@ -1733,7 +1728,9 @@ - (void)usePlayerViewController
{
if( _player )
{
_playerViewController = [self createPlayerViewController:_player withPlayerItem:_playerItem];
if (!_playerViewController) {
_playerViewController = [self createPlayerViewController:_player withPlayerItem:_playerItem];
}
// to prevent video from being animated when resizeMode is 'cover'
// resize mode must be set before subview is added
[self setResizeMode:_resizeMode];
Expand All @@ -1743,6 +1740,8 @@ - (void)usePlayerViewController
[viewController addChildViewController:_playerViewController];
[self addSubview:_playerViewController.view];
}

[_playerViewController addObserver:self forKeyPath:readyForDisplayKeyPath options:NSKeyValueObservingOptionNew context:nil];

[_playerViewController.contentOverlayView addObserver:self forKeyPath:@"frame" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:NULL];
}
Expand Down Expand Up @@ -1943,6 +1942,7 @@ - (void)removeFromSuperview
[self removePlayerLayer];

[_playerViewController.contentOverlayView removeObserver:self forKeyPath:@"frame"];
[_playerViewController removeObserver:self forKeyPath:readyForDisplayKeyPath];
[_playerViewController.view removeFromSuperview];
_playerViewController = nil;

Expand Down

0 comments on commit 25f34a9

Please sign in to comment.