diff --git a/CHANGELOG.md b/CHANGELOG.md index ce3a0d4cfd..24a19ba40c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,11 @@ ## Changelog -### Next Version +### Version 4.3.0 * Fix iOS video not displaying after switching source [#1395](https://github.com/react-native-community/react-native-video/pull/1395) * Add the filterEnabled flag, fixes iOS video start time regression [#1384](https://github.com/react-native-community/react-native-video/pull/1384) * Fix text not appearing in release builds of Android apps [#1373](https://github.com/react-native-community/react-native-video/pull/1373) * Update to ExoPlayer 2.9.3 [#1406](https://github.com/react-native-community/react-native-video/pull/1406) +* Add video track selection & onBandwidthUpdate [#1199](https://github.com/react-native-community/react-native-video/pull/1199) ### Version 4.2.0 * Don't initialize filters on iOS unless a filter is set. This was causing a startup performance regression [#1360](https://github.com/react-native-community/react-native-video/pull/1360) diff --git a/README.md b/README.md index d5dcaf7375..05337141f5 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Version 3.x requires react-native >= 0.40.0 ### Version 4.0.0 breaking changes Version 4.0.0 changes some behaviors and may require updates to your Gradle files. See [Updating](#updating) for details. -Version 4.0.0 now requires Android SDK 26+ and Gradle 3 plugin in order to support ExoPlayer 2.9.0. Google is dropping support for apps using SDKs older than 26 as of October 2018 and Gradle 2 as of January 2019. React Native 0.57 defaults to Gradle 3 & SDK 27. +Version 4.0.0 now requires Android target SDK 26+ and Gradle 3 plugin in order to support ExoPlayer 2.9.0. Google is dropping support for apps using target SDKs older than 26 as of October 2018 and Gradle 2 as of January 2019. React Native 0.57 defaults to Gradle 3 & SDK 27. If you need to support an older React Native version, you should use react-native-video 3.2.1. @@ -278,9 +278,11 @@ var styles = StyleSheet.create({ * [progressUpdateInterval](#progressupdateinterval) * [rate](#rate) * [repeat](#repeat) +* [reportBandwidth](#reportbandwidth) * [resizeMode](#resizemode) * [selectedAudioTrack](#selectedaudiotrack) * [selectedTextTrack](#selectedtexttrack) +* [selectedVideoTrack](#selectedvideotrack) * [source](#source) * [stereoPan](#stereopan) * [textTracks](#texttracks) @@ -289,6 +291,7 @@ var styles = StyleSheet.create({ ### Event props * [onAudioBecomingNoisy](#onaudiobecomingnoisy) +* [onBandwidthUpdate](#onbandwidthupdate) * [onEnd](#onend) * [onExternalPlaybackChange](#onexternalplaybackchange) * [onFullscreenPlayerWillPresent](#onfullscreenplayerwillpresent) @@ -417,15 +420,18 @@ Platforms: iOS Platforms: iOS #### headers -Pass headers to the HTTP client. Can be used for authorization. +Pass headers to the HTTP client. Can be used for authorization. Headers must be a part of the source object. To enable this on iOS, you will need to manually edit RCTVideo.m and uncomment the header code in the playerItemForSource function. This is because the code used a private API and may cause your app to be rejected by the App Store. Use at your own risk. Example: ``` -headers={{ - Authorization: 'bearer some-token-value', - 'X-Custom-Header': 'some value' +source={{ + uri: "https://www.example.com/video.mp4", + headers: { + Authorization: 'bearer some-token-value', + 'X-Custom-Header': 'some value' + } }} ``` @@ -542,6 +548,14 @@ Determine whether to repeat the video when the end is reached Platforms: all +#### reportBandwidth +Determine whether to generate onBandwidthUpdate events. This is needed due to the high frequency of these events on ExoPlayer. + +* **false (default)** - Generate onBandwidthUpdate events +* **true** - Don't generate onBandwidthUpdate events + +Platforms: Android ExoPlayer + #### resizeMode Determines how to resize the video when the frame doesn't match the raw video dimensions. * **"none" (default)** - Don't apply resize @@ -613,6 +627,35 @@ If a track matching the specified Type (and Value if appropriate) is unavailable Platforms: Android ExoPlayer, iOS +#### selectedVideoTrack +Configure which video track should be played. By default, the player uses Adaptive Bitrate Streaming to automatically select the stream it thinks will perform best based on available bandwidth. + +``` +selectedVideoTrack={{ + type: Type, + value: Value +}} +``` + +Example: +``` +selectedVideoTrack={{ + type: "resolution", + value: 480 +}} +``` + +Type | Value | Description +--- | --- | --- +"auto" (default) | N/A | Let the player determine which track to play using ABR +"disabled" | N/A | Turn off video +"resolution" | number | Play the video track with the height specified, e.g. 480 for the 480p stream +"index" | number | Play the video track with the index specified as the value, e.g. 0 + +If a track matching the specified Type (and Value if appropriate) is unavailable, ABR will be used. + +Platforms: Android ExoPlayer + #### source Sets the media source. You can pass an asset loaded via require or an object with a uri. @@ -748,6 +791,26 @@ Payload: none Platforms: Android ExoPlayer, iOS +#### onBandwidthUpdate +Callback function that is called when the available bandwidth changes. + +Payload: + +Property | Type | Description +--- | --- | --- +bitrate | number | The estimated bitrate in bits/sec + +Example: +``` +{ + bitrate: 1000000 +} +``` + +Note: On Android ExoPlayer, you must set the [reportBandwidth](#reportbandwidth) prop to enable this event. This is due to the high volume of events generated. + +Platforms: Android ExoPlayer + #### onEnd Callback function that is called when the player reaches the end of the media. @@ -1110,8 +1173,8 @@ To enable audio to play in background on iOS the audio session needs to be set t ### Version 4.0.0 -#### Gradle 3 and SDK 26 requirement -In order to support ExoPlayer 2.9.0, you must use version 3 or higher of the Gradle plugin. This is included by default in React Native 0.57. ExoPlayer +#### Gradle 3 and target SDK 26 requirement +In order to support ExoPlayer 2.9.0, you must use version 3 or higher of the Gradle plugin. This is included by default in React Native 0.57. #### ExoPlayer 2.9.0 Java 1.8 requirement ExoPlayer 2.9.0 uses some Java 1.8 features, so you may need to enable support for Java 1.8 in your app/build.gradle file. If you get an error, compiling with ExoPlayer like: @@ -1146,7 +1209,7 @@ Previously, on Android MediaPlayer if you setup an AppState event when the app w Note, Windows does not have a concept of an app going into the background, so this doesn't apply there. -#### Use Android SDK 27 by default +#### Use Android target SDK 27 by default Version 3.0 updates the Android build tools and SDK to version 27. React Native is in the process of [switchting over](https://github.com/facebook/react-native/issues/18095#issuecomment-395596130) to SDK 27 in preparation for Google's requirement that new Android apps [use SDK 26](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html) by August 2018. You will either need to install the version 27 SDK and version 27.0.3 buildtools or modify your build.gradle file to configure react-native-video to use the same build settings as the rest of your app as described below. diff --git a/android-exoplayer/build.gradle b/android-exoplayer/build.gradle index 614d010cd0..a532956d85 100644 --- a/android-exoplayer/build.gradle +++ b/android-exoplayer/build.gradle @@ -21,12 +21,6 @@ dependencies { implementation('com.google.android.exoplayer:exoplayer:2.9.3') { exclude group: 'com.android.support' } - implementation project(':exoplayer-library-core') - implementation project(':exoplayer-library-dash') - implementation project(':exoplayer-library-ui') - implementation project(':exoplayer-library-smoothstreaming') - implementation project(':exoplayer-library-hls') - implementation project(':exoplayer-extension-okhttp') // All support libs must use the same version implementation "com.android.support:support-annotations:${safeExtGet('supportLibVersion', '+')}" 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 27aaf3b7e2..64c8a4043f 100644 --- a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java +++ b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java @@ -889,11 +889,13 @@ public void setSelectedTrack(int trackType, String type, Dynamic value) { } if (groupIndex == C.INDEX_UNSET && trackType == C.TRACK_TYPE_VIDEO) { // Video auto - TrackGroup group = groups.get(0); - tracks = new int[group.length]; - groupIndex = 0; - for (int j = 0; j < group.length; j++) { - tracks[j] = j; + if (groups.length != 0) { + TrackGroup group = groups.get(0); + tracks = new int[group.length]; + groupIndex = 0; + for (int j = 0; j < group.length; j++) { + tracks[j] = j; + } } } else if (groupIndex == C.INDEX_UNSET) { trackSelector.setParameters(disableParameters); diff --git a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/VideoEventEmitter.java b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/VideoEventEmitter.java index b46b66d6d4..00f51c94cd 100644 --- a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/VideoEventEmitter.java +++ b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/VideoEventEmitter.java @@ -178,7 +178,7 @@ void progressChanged(double currentPosition, double bufferedDuration, double see void bandwidthReport(double bitRateEstimate) { WritableMap event = Arguments.createMap(); - event.putDouble(EVENT_PROP_BITRATE, bitRate); + event.putDouble(EVENT_PROP_BITRATE, bitRateEstimate); receiveEvent(EVENT_BANDWIDTH, event); } diff --git a/ios/Video/RCTVideo.m b/ios/Video/RCTVideo.m index b71bbf2853..52b0342a6b 100644 --- a/ios/Video/RCTVideo.m +++ b/ios/Video/RCTVideo.m @@ -719,9 +719,11 @@ - (void)handleAVPlayerAccess:(NSNotification *)notification { AVPlayerItemAccessLog *accessLog = [((AVPlayerItem *)notification.object) accessLog]; AVPlayerItemAccessLogEvent *lastEvent = accessLog.events.lastObject; + /* TODO: get this working if (self.onBandwidthUpdate) { self.onBandwidthUpdate(@{@"bitrate": [NSNumber numberWithFloat:lastEvent.observedBitrate]}); } + */ } - (void)playbackStalled:(NSNotification *)notification diff --git a/package.json b/package.json index 0c690a04f4..8e5e3ddc06 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-video", - "version": "4.2.1", + "version": "4.3.1", "description": "A