This commit is contained in:
Nicolas Gonzalez 2018-12-13 21:38:32 -06:00
commit c2d9fb4301
9 changed files with 109 additions and 10 deletions

View File

@ -1,5 +1,17 @@
## Changelog ## Changelog
### 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)
* Support setting the maxBitRate [#1310](https://github.com/react-native-community/react-native-video/pull/1310)
* Fix useTextureView not defaulting to true [#1383](https://github.com/react-native-community/react-native-video/pull/1383)
* Fix crash on MediaPlayer w/ Android 4.4 & avoid memory leak [#1328](https://github.com/react-native-community/react-native-video/pull/1328)
### Version 4.1.0
* Generate onSeek on Android ExoPlayer & MediaPlayer after seek completes [#1351](https://github.com/react-native-community/react-native-video/pull/1351)
* Remove unneeded onVideoSaved event [#1350](https://github.com/react-native-community/react-native-video/pull/1350)
* Disable AirPlay if sidecar text tracks are enabled [#1304](https://github.com/react-native-community/react-native-video/pull/1304)
* Add possibility to remove black screen while video is loading in Exoplayer [#1355](https://github.com/react-native-community/react-native-video/pull/1355)
### Version 4.0.1 ### Version 4.0.1
* Add missing files to package.json [#1342](https://github.com/react-native-community/react-native-video/pull/1342) * Add missing files to package.json [#1342](https://github.com/react-native-community/react-native-video/pull/1342)

View File

@ -265,8 +265,10 @@ var styles = StyleSheet.create({
* [fullscreenAutorotate](#fullscreenautorotate) * [fullscreenAutorotate](#fullscreenautorotate)
* [fullscreenOrientation](#fullscreenorientation) * [fullscreenOrientation](#fullscreenorientation)
* [headers](#headers) * [headers](#headers)
* [hideShutterView](#hideshutterview)
* [id](#id) * [id](#id)
* [ignoreSilentSwitch](#ignoresilentswitch) * [ignoreSilentSwitch](#ignoresilentswitch)
* [maxBitRate](#maxbitrate)
* [muted](#muted) * [muted](#muted)
* [paused](#paused) * [paused](#paused)
* [playInBackground](#playinbackground) * [playInBackground](#playinbackground)
@ -427,6 +429,14 @@ headers={{
Platforms: Android ExoPlayer Platforms: Android ExoPlayer
#### hideShutterView
Controls whether the ExoPlayer shutter view (black screen while loading) is enabled.
* **false (default)** - Show shutter view
* **true** - Hide shutter view
Platforms: Android ExoPlayer
#### id #### id
Set the DOM id element so you can use document.getElementById on web platforms. Accepts string values. Set the DOM id element so you can use document.getElementById on web platforms. Accepts string values.
@ -445,6 +455,18 @@ Controls the iOS silent switch behavior
Platforms: iOS Platforms: iOS
#### maxBitRate
Sets the desired limit, in bits per second, of network bandwidth consumption when multiple video streams are available for a playlist.
Default: 0. Don't limit the maxBitRate.
Example:
```
maxBitRate={2000000} // 2 megabits
```
Platforms: Android ExoPlayer, iOS
#### muted #### muted
Controls whether the audio is muted Controls whether the audio is muted
* **false (default)** - Don't mute audio * **false (default)** - Don't mute audio
@ -594,6 +616,7 @@ Sets the media source. You can pass an asset loaded via require or an object wit
The docs for this prop are incomplete and will be updated as each option is investigated and tested. The docs for this prop are incomplete and will be updated as each option is investigated and tested.
##### Asset loaded via require ##### Asset loaded via require
Example: Example:
@ -666,6 +689,8 @@ uri | URL for the text track. Currently, only tracks hosted on a webserver are s
On iOS, sidecar text tracks are only supported for individual files, not HLS playlists. For HLS, you should include the text tracks as part of the playlist. On iOS, sidecar text tracks are only supported for individual files, not HLS playlists. For HLS, you should include the text tracks as part of the playlist.
Note: Due to iOS limitations, sidecar text tracks are not compatible with Airplay. If textTracks are specified, AirPlay support will be automatically disabled.
Example: Example:
``` ```
import { TextTrackType }, Video from 'react-native-video'; import { TextTrackType }, Video from 'react-native-video';

View File

@ -331,6 +331,7 @@ Video.propTypes = {
// Opaque type returned by require('./video.mp4') // Opaque type returned by require('./video.mp4')
PropTypes.number PropTypes.number
]), ]),
maxBitRate: PropTypes.number,
resizeMode: PropTypes.string, resizeMode: PropTypes.string,
poster: PropTypes.string, poster: PropTypes.string,
posterResizeMode: Image.propTypes.resizeMode, posterResizeMode: Image.propTypes.resizeMode,
@ -384,6 +385,7 @@ Video.propTypes = {
fullscreenOrientation: PropTypes.oneOf(['all','landscape','portrait']), fullscreenOrientation: PropTypes.oneOf(['all','landscape','portrait']),
progressUpdateInterval: PropTypes.number, progressUpdateInterval: PropTypes.number,
useTextureView: PropTypes.bool, useTextureView: PropTypes.bool,
hideShutterView: PropTypes.bool,
onLoadStart: PropTypes.func, onLoadStart: PropTypes.func,
onLoad: PropTypes.func, onLoad: PropTypes.func,
onBuffer: PropTypes.func, onBuffer: PropTypes.func,

View File

@ -38,7 +38,8 @@ public final class ExoPlayerView extends FrameLayout {
private Context context; private Context context;
private ViewGroup.LayoutParams layoutParams; private ViewGroup.LayoutParams layoutParams;
private boolean useTextureView = false; private boolean useTextureView = true;
private boolean hideShutterView = false;
public ExoPlayerView(Context context) { public ExoPlayerView(Context context) {
this(context, null); this(context, null);
@ -106,6 +107,10 @@ public final class ExoPlayerView extends FrameLayout {
} }
} }
private void updateShutterViewVisibility() {
shutterView.setVisibility(this.hideShutterView ? View.INVISIBLE : View.VISIBLE);
}
/** /**
* Set the {@link SimpleExoPlayer} to use. The {@link SimpleExoPlayer#setTextOutput} and * Set the {@link SimpleExoPlayer} to use. The {@link SimpleExoPlayer#setTextOutput} and
* {@link SimpleExoPlayer#setVideoListener} method of the player will be called and previous * {@link SimpleExoPlayer#setVideoListener} method of the player will be called and previous
@ -157,9 +162,16 @@ public final class ExoPlayerView extends FrameLayout {
} }
public void setUseTextureView(boolean useTextureView) { public void setUseTextureView(boolean useTextureView) {
if (useTextureView != this.useTextureView) {
this.useTextureView = useTextureView; this.useTextureView = useTextureView;
updateSurfaceView(); updateSurfaceView();
} }
}
public void setHideShutterView(boolean hideShutterView) {
this.hideShutterView = hideShutterView;
updateShutterViewVisibility();
}
private final Runnable measureAndLayout = new Runnable() { private final Runnable measureAndLayout = new Runnable() {
@Override @Override

View File

@ -110,6 +110,7 @@ class ReactExoplayerView extends FrameLayout implements
private boolean isBuffering; private boolean isBuffering;
private float rate = 1f; private float rate = 1f;
private float audioVolume = 1f; private float audioVolume = 1f;
private int maxBitRate = 0;
private long seekTime = C.TIME_UNSET; private long seekTime = C.TIME_UNSET;
private int minBufferMs = DefaultLoadControl.DEFAULT_MIN_BUFFER_MS; private int minBufferMs = DefaultLoadControl.DEFAULT_MIN_BUFFER_MS;
@ -130,7 +131,6 @@ class ReactExoplayerView extends FrameLayout implements
private boolean disableFocus; private boolean disableFocus;
private float mProgressUpdateInterval = 250.0f; private float mProgressUpdateInterval = 250.0f;
private boolean playInBackground = false; private boolean playInBackground = false;
private boolean useTextureView = false;
private Map<String, String> requestHeaders; private Map<String, String> requestHeaders;
// \ End props // \ End props
@ -245,6 +245,9 @@ class ReactExoplayerView extends FrameLayout implements
if (player == null) { if (player == null) {
TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(BANDWIDTH_METER); TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(BANDWIDTH_METER);
trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory); 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); DefaultAllocator allocator = new DefaultAllocator(true, C.DEFAULT_BUFFER_SEGMENT_SIZE);
DefaultLoadControl defaultLoadControl = new DefaultLoadControl(allocator, minBufferMs, maxBufferMs, bufferForPlaybackMs, bufferForPlaybackAfterRebufferMs, -1, true); DefaultLoadControl defaultLoadControl = new DefaultLoadControl(allocator, minBufferMs, maxBufferMs, bufferForPlaybackMs, bufferForPlaybackAfterRebufferMs, -1, true);
player = ExoPlayerFactory.newSimpleInstance(getContext(), trackSelector, defaultLoadControl); player = ExoPlayerFactory.newSimpleInstance(getContext(), trackSelector, defaultLoadControl);
@ -908,6 +911,14 @@ class ReactExoplayerView extends FrameLayout implements
} }
} }
public void setMaxBitRateModifier(int newMaxBitRate) {
maxBitRate = newMaxBitRate;
if (player != null) {
trackSelector.setParameters(trackSelector.buildUponParameters()
.setMaxVideoBitrate(maxBitRate == 0 ? Integer.MAX_VALUE : maxBitRate));
}
}
public void setPlayInBackground(boolean playInBackground) { public void setPlayInBackground(boolean playInBackground) {
this.playInBackground = playInBackground; this.playInBackground = playInBackground;
@ -954,6 +965,10 @@ class ReactExoplayerView extends FrameLayout implements
exoPlayerView.setUseTextureView(useTextureView); exoPlayerView.setUseTextureView(useTextureView);
} }
public void setHideShutterView(boolean hideShutterView) {
exoPlayerView.setHideShutterView(hideShutterView);
}
public void setBufferConfig(int newMinBufferMs, int newMaxBufferMs, int newBufferForPlaybackMs, int newBufferForPlaybackAfterRebufferMs) { public void setBufferConfig(int newMinBufferMs, int newMaxBufferMs, int newBufferForPlaybackMs, int newBufferForPlaybackAfterRebufferMs) {
minBufferMs = newMinBufferMs; minBufferMs = newMinBufferMs;
maxBufferMs = newMaxBufferMs; maxBufferMs = newMaxBufferMs;

View File

@ -47,10 +47,12 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
private static final String PROP_PROGRESS_UPDATE_INTERVAL = "progressUpdateInterval"; private static final String PROP_PROGRESS_UPDATE_INTERVAL = "progressUpdateInterval";
private static final String PROP_SEEK = "seek"; private static final String PROP_SEEK = "seek";
private static final String PROP_RATE = "rate"; private static final String PROP_RATE = "rate";
private static final String PROP_MAXIMUM_BIT_RATE = "maxBitRate";
private static final String PROP_PLAY_IN_BACKGROUND = "playInBackground"; private static final String PROP_PLAY_IN_BACKGROUND = "playInBackground";
private static final String PROP_DISABLE_FOCUS = "disableFocus"; private static final String PROP_DISABLE_FOCUS = "disableFocus";
private static final String PROP_FULLSCREEN = "fullscreen"; private static final String PROP_FULLSCREEN = "fullscreen";
private static final String PROP_USE_TEXTURE_VIEW = "useTextureView"; private static final String PROP_USE_TEXTURE_VIEW = "useTextureView";
private static final String PROP_HIDE_SHUTTER_VIEW = "hideShutterView";
@Override @Override
public String getName() { public String getName() {
@ -200,6 +202,11 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
videoView.setRateModifier(rate); videoView.setRateModifier(rate);
} }
@ReactProp(name = PROP_MAXIMUM_BIT_RATE)
public void setMaxBitRate(final ReactExoplayerView videoView, final int maxBitRate) {
videoView.setMaxBitRateModifier(maxBitRate);
}
@ReactProp(name = PROP_PLAY_IN_BACKGROUND, defaultBoolean = false) @ReactProp(name = PROP_PLAY_IN_BACKGROUND, defaultBoolean = false)
public void setPlayInBackground(final ReactExoplayerView videoView, final boolean playInBackground) { public void setPlayInBackground(final ReactExoplayerView videoView, final boolean playInBackground) {
videoView.setPlayInBackground(playInBackground); videoView.setPlayInBackground(playInBackground);
@ -220,6 +227,11 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
videoView.setUseTextureView(useTextureView); videoView.setUseTextureView(useTextureView);
} }
@ReactProp(name = PROP_HIDE_SHUTTER_VIEW, defaultBoolean = false)
public void setHideShutterView(final ReactExoplayerView videoView, final boolean hideShutterView) {
videoView.setHideShutterView(hideShutterView);
}
@ReactProp(name = PROP_BUFFER_CONFIG) @ReactProp(name = PROP_BUFFER_CONFIG)
public void setBufferConfig(final ReactExoplayerView videoView, @Nullable ReadableMap bufferConfig) { public void setBufferConfig(final ReactExoplayerView videoView, @Nullable ReadableMap bufferConfig) {
int minBufferMs = DefaultLoadControl.DEFAULT_MIN_BUFFER_MS; int minBufferMs = DefaultLoadControl.DEFAULT_MIN_BUFFER_MS;

View File

@ -235,12 +235,19 @@ public class ReactVideoView extends ScalableVideoView implements
mediaController.hide(); mediaController.hide();
} }
if ( mMediaPlayer != null ) { if ( mMediaPlayer != null ) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mMediaPlayer.setOnTimedMetaDataAvailableListener(null);
}
mMediaPlayerValid = false; mMediaPlayerValid = false;
release(); release();
} }
if (mIsFullscreen) { if (mIsFullscreen) {
setFullscreen(false); setFullscreen(false);
} }
if (mThemedReactContext != null) {
mThemedReactContext.removeLifecycleEventListener(this);
mThemedReactContext = null;
}
} }
public void setSrc(final String uriString, final String type, final boolean isNetwork, final boolean isAsset, final ReadableMap requestHeaders) { public void setSrc(final String uriString, final String type, final boolean isNetwork, final boolean isAsset, final ReadableMap requestHeaders) {
@ -567,8 +574,7 @@ public class ReactVideoView extends ScalableVideoView implements
}); });
} }
// Select track (so we can use it to listen to timed meta data updates) selectTimedMetadataTrack(mp);
mp.selectTrack(0);
} }
@Override @Override
@ -603,9 +609,7 @@ public class ReactVideoView extends ScalableVideoView implements
@Override @Override
public void onBufferingUpdate(MediaPlayer mp, int percent) { public void onBufferingUpdate(MediaPlayer mp, int percent) {
// Select track (so we can use it to listen to timed meta data updates) selectTimedMetadataTrack(mp);
mp.selectTrack(0);
mVideoBufferedDuration = (int) Math.round((double) (mVideoDuration * percent) / 100.0); mVideoBufferedDuration = (int) Math.round((double) (mVideoDuration * percent) / 100.0);
} }
@ -761,4 +765,20 @@ public class ReactVideoView extends ScalableVideoView implements
return result; return result;
} }
// Select track (so we can use it to listen to timed meta data updates)
private void selectTimedMetadataTrack(MediaPlayer mp) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return;
}
try { // It's possible this could throw an exception if the framework doesn't support getting track info
MediaPlayer.TrackInfo[] trackInfo = mp.getTrackInfo();
for (int i = 0; i < trackInfo.length; ++i) {
if (trackInfo[i].getTrackType() == MediaPlayer.TrackInfo.MEDIA_TRACK_TYPE_TIMEDTEXT) {
mp.selectTrack(i);
break;
}
}
} catch (Exception e) {}
}
} }

View File

@ -19,6 +19,7 @@ RCT_EXPORT_MODULE();
} }
RCT_EXPORT_VIEW_PROPERTY(src, NSDictionary); RCT_EXPORT_VIEW_PROPERTY(src, NSDictionary);
RCT_EXPORT_VIEW_PROPERTY(maxBitRate, float);
RCT_EXPORT_VIEW_PROPERTY(resizeMode, NSString); RCT_EXPORT_VIEW_PROPERTY(resizeMode, NSString);
RCT_EXPORT_VIEW_PROPERTY(repeat, BOOL); RCT_EXPORT_VIEW_PROPERTY(repeat, BOOL);
RCT_EXPORT_VIEW_PROPERTY(allowsExternalPlayback, BOOL); RCT_EXPORT_VIEW_PROPERTY(allowsExternalPlayback, BOOL);

View File

@ -1,6 +1,6 @@
{ {
"name": "react-native-video", "name": "react-native-video",
"version": "4.0.2", "version": "4.2.1",
"description": "A <Video /> element for react-native", "description": "A <Video /> element for react-native",
"main": "Video.js", "main": "Video.js",
"license": "MIT", "license": "MIT",