Expose currentPlaybackTime when live stream video (#1944)
* added trackId to exoplayer onLoad callback * added trackInfo to bandwidth callback * syntax fix * syntax fix * version update * sending complete logcat for media playback exception ExoPlaybackException * version bump * package publish changes * Live playback fix * Version bump * import fix * version bump * configurable preferredForwardBufferDuration * configurable preferredForwardBufferDuration * version update * Exposing time * exo player window current tsp * return type * Current window timestamp in epoch * iOS changes * version update * Updated package.json * updated version * CurrentTime bug fix * Updated package.json * Updated currentPlaybackTime * Updated currentPlayback logic * Updated package.json * Bug fix * Added semicolon * updated package.json * Updated ReactVideoView * updated verison * Revert package.json changes * Update ReactVideoView.java * Use standard log * Document preferredForwardBufferDuration (iOS) * Document currentPlaybackTime * Document trackId * Update CHANGELOG.md * Update CHANGELOG.md * Update README.md * Update CHANGELOG.md Co-authored-by: anubansal <anu.bansal@curefit.com> Co-authored-by: Sivakumar J <sivakumar@curefit.com> Co-authored-by: parikshit <parikshit@curefit.com> Co-authored-by: anubansal92 <40559524+anubansal92@users.noreply.github.com> Co-authored-by: Rishu Agrawal <rishu.agrawal@v.curefit.com> Co-authored-by: rishu-curefit <54575330+rishu-curefit@users.noreply.github.com>
This commit is contained in:
parent
e3009c60e1
commit
0b914ef2b9
@ -6,6 +6,9 @@
|
|||||||
- Fix video dimensions being undefined when playing HLS in ios. [#1992](https://github.com/react-native-community/react-native-video/pull/1992)
|
- Fix video dimensions being undefined when playing HLS in ios. [#1992](https://github.com/react-native-community/react-native-video/pull/1992)
|
||||||
- Add support for audio mix with other apps for iOS. [#1978](https://github.com/react-native-community/react-native-video/pull/1978)
|
- Add support for audio mix with other apps for iOS. [#1978](https://github.com/react-native-community/react-native-video/pull/1978)
|
||||||
- Properly implement pending seek for iOS. [#1994](https://github.com/react-native-community/react-native-video/pull/1994)
|
- Properly implement pending seek for iOS. [#1994](https://github.com/react-native-community/react-native-video/pull/1994)
|
||||||
|
- Added `preferredForwardBufferDuration` (iOS) - the duration the player should buffer media from the network ahead of the playhead to guard against playback disruption. (#1944)
|
||||||
|
- Added `currentPlaybackTime` (Android ExoPlayer, iOS) - when playing an HLS live stream with a `EXT-X-PROGRAM-DATE-TIME` tag configured, then this property will contain the epoch value in msec. (#1944)
|
||||||
|
- Added `trackId` (Android ExoPlayer) - Configure an identifier for the video stream to link the playback context to the events emitted. (#1944)
|
||||||
|
|
||||||
### Version 5.1.0-alpha5
|
### Version 5.1.0-alpha5
|
||||||
|
|
||||||
|
20
README.md
20
README.md
@ -277,6 +277,7 @@ var styles = StyleSheet.create({
|
|||||||
* [automaticallyWaitsToMinimizeStalling](#automaticallyWaitsToMinimizeStalling)
|
* [automaticallyWaitsToMinimizeStalling](#automaticallyWaitsToMinimizeStalling)
|
||||||
* [bufferConfig](#bufferconfig)
|
* [bufferConfig](#bufferconfig)
|
||||||
* [controls](#controls)
|
* [controls](#controls)
|
||||||
|
* [currentPlaybackTime](#currentPlaybackTime)
|
||||||
* [disableFocus](#disableFocus)
|
* [disableFocus](#disableFocus)
|
||||||
* [filter](#filter)
|
* [filter](#filter)
|
||||||
* [filterEnabled](#filterEnabled)
|
* [filterEnabled](#filterEnabled)
|
||||||
@ -297,6 +298,7 @@ var styles = StyleSheet.create({
|
|||||||
* [playWhenInactive](#playwheninactive)
|
* [playWhenInactive](#playwheninactive)
|
||||||
* [poster](#poster)
|
* [poster](#poster)
|
||||||
* [posterResizeMode](#posterresizemode)
|
* [posterResizeMode](#posterresizemode)
|
||||||
|
* [preferredForwardBufferDuration](#preferredForwardBufferDuration)
|
||||||
* [progressUpdateInterval](#progressupdateinterval)
|
* [progressUpdateInterval](#progressupdateinterval)
|
||||||
* [rate](#rate)
|
* [rate](#rate)
|
||||||
* [repeat](#repeat)
|
* [repeat](#repeat)
|
||||||
@ -308,6 +310,7 @@ var styles = StyleSheet.create({
|
|||||||
* [source](#source)
|
* [source](#source)
|
||||||
* [stereoPan](#stereopan)
|
* [stereoPan](#stereopan)
|
||||||
* [textTracks](#texttracks)
|
* [textTracks](#texttracks)
|
||||||
|
* [trackId](#trackId)
|
||||||
* [useTextureView](#usetextureview)
|
* [useTextureView](#usetextureview)
|
||||||
* [volume](#volume)
|
* [volume](#volume)
|
||||||
|
|
||||||
@ -386,6 +389,11 @@ bufferConfig={{
|
|||||||
|
|
||||||
Platforms: Android ExoPlayer
|
Platforms: Android ExoPlayer
|
||||||
|
|
||||||
|
#### currentPlaybackTime
|
||||||
|
When playing an HLS live stream with a `EXT-X-PROGRAM-DATE-TIME` tag configured, then this property will contain the epoch value in msec.
|
||||||
|
|
||||||
|
Platforms: Android ExoPlayer, iOS
|
||||||
|
|
||||||
#### controls
|
#### controls
|
||||||
Determines whether to show player controls.
|
Determines whether to show player controls.
|
||||||
* ** false (default)** - Don't show player controls
|
* ** false (default)** - Don't show player controls
|
||||||
@ -596,6 +604,13 @@ Determines how to resize the poster image when the frame doesn't match the raw v
|
|||||||
|
|
||||||
Platforms: all
|
Platforms: all
|
||||||
|
|
||||||
|
#### preferredForwardBufferDuration
|
||||||
|
The duration the player should buffer media from the network ahead of the playhead to guard against playback disruption. Sets the [preferredForwardBufferDuration](https://developer.apple.com/documentation/avfoundation/avplayeritem/1643630-preferredforwardbufferduration) instance property on AVPlayerItem.
|
||||||
|
|
||||||
|
Default: 0
|
||||||
|
|
||||||
|
Platforms: iOS
|
||||||
|
|
||||||
#### progressUpdateInterval
|
#### progressUpdateInterval
|
||||||
Delay in milliseconds between onProgress events in milliseconds.
|
Delay in milliseconds between onProgress events in milliseconds.
|
||||||
|
|
||||||
@ -831,6 +846,11 @@ textTracks={[
|
|||||||
|
|
||||||
Platforms: Android ExoPlayer, iOS
|
Platforms: Android ExoPlayer, iOS
|
||||||
|
|
||||||
|
#### trackId
|
||||||
|
Configure an identifier for the video stream to link the playback context to the events emitted.
|
||||||
|
|
||||||
|
Platforms: Android ExoPlayer
|
||||||
|
|
||||||
#### useTextureView
|
#### useTextureView
|
||||||
Controls whether to output to a TextureView or SurfaceView.
|
Controls whether to output to a TextureView or SurfaceView.
|
||||||
|
|
||||||
|
1
Video.js
1
Video.js
@ -479,6 +479,7 @@ Video.propTypes = {
|
|||||||
rate: PropTypes.number,
|
rate: PropTypes.number,
|
||||||
pictureInPicture: PropTypes.bool,
|
pictureInPicture: PropTypes.bool,
|
||||||
playInBackground: PropTypes.bool,
|
playInBackground: PropTypes.bool,
|
||||||
|
preferredForwardBufferDuration: PropTypes.number,
|
||||||
playWhenInactive: PropTypes.bool,
|
playWhenInactive: PropTypes.bool,
|
||||||
ignoreSilentSwitch: PropTypes.oneOf(['ignore', 'obey']),
|
ignoreSilentSwitch: PropTypes.oneOf(['ignore', 'obey']),
|
||||||
reportBandwidth: PropTypes.bool,
|
reportBandwidth: PropTypes.bool,
|
||||||
|
@ -64,6 +64,7 @@ import com.google.android.exoplayer2.upstream.BandwidthMeter;
|
|||||||
import com.google.android.exoplayer2.upstream.DataSource;
|
import com.google.android.exoplayer2.upstream.DataSource;
|
||||||
import com.google.android.exoplayer2.upstream.DefaultAllocator;
|
import com.google.android.exoplayer2.upstream.DefaultAllocator;
|
||||||
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
|
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
|
||||||
|
import com.google.android.exoplayer2.upstream.HttpDataSource;
|
||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
|
|
||||||
import java.net.CookieHandler;
|
import java.net.CookieHandler;
|
||||||
@ -161,7 +162,7 @@ class ReactExoplayerView extends FrameLayout implements
|
|||||||
) {
|
) {
|
||||||
long pos = player.getCurrentPosition();
|
long pos = player.getCurrentPosition();
|
||||||
long bufferedDuration = player.getBufferedPercentage() * player.getDuration() / 100;
|
long bufferedDuration = player.getBufferedPercentage() * player.getDuration() / 100;
|
||||||
eventEmitter.progressChanged(pos, bufferedDuration, player.getDuration());
|
eventEmitter.progressChanged(pos, bufferedDuration, player.getDuration(), getPositionInFirstPeriodMsForCurrentWindow(pos));
|
||||||
msg = obtainMessage(SHOW_PROGRESS);
|
msg = obtainMessage(SHOW_PROGRESS);
|
||||||
sendMessageDelayed(msg, Math.round(mProgressUpdateInterval));
|
sendMessageDelayed(msg, Math.round(mProgressUpdateInterval));
|
||||||
}
|
}
|
||||||
@ -169,6 +170,14 @@ class ReactExoplayerView extends FrameLayout implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public double getPositionInFirstPeriodMsForCurrentWindow(long currentPosition) {
|
||||||
|
Timeline.Window window = new Timeline.Window();
|
||||||
|
if(!player.getCurrentTimeline().isEmpty()) {
|
||||||
|
player.getCurrentTimeline().getWindow(player.getCurrentWindowIndex(), window);
|
||||||
|
}
|
||||||
|
return window.windowStartTimeMs + currentPosition;
|
||||||
|
}
|
||||||
|
|
||||||
public ReactExoplayerView(ThemedReactContext context, ReactExoplayerConfig config) {
|
public ReactExoplayerView(ThemedReactContext context, ReactExoplayerConfig config) {
|
||||||
super(context);
|
super(context);
|
||||||
@ -257,7 +266,15 @@ class ReactExoplayerView extends FrameLayout implements
|
|||||||
@Override
|
@Override
|
||||||
public void onBandwidthSample(int elapsedMs, long bytes, long bitrate) {
|
public void onBandwidthSample(int elapsedMs, long bytes, long bitrate) {
|
||||||
if (mReportBandwidth) {
|
if (mReportBandwidth) {
|
||||||
eventEmitter.bandwidthReport(bitrate);
|
if (player == null) {
|
||||||
|
eventEmitter.bandwidthReport(bitrate, 0, 0, "-1");
|
||||||
|
} else {
|
||||||
|
Format videoFormat = player.getVideoFormat();
|
||||||
|
int width = videoFormat != null ? videoFormat.width : 0;
|
||||||
|
int height = videoFormat != null ? videoFormat.height : 0;
|
||||||
|
String trackId = videoFormat != null ? videoFormat.id : "-1";
|
||||||
|
eventEmitter.bandwidthReport(bitrate, height, width, trackId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -749,8 +766,9 @@ class ReactExoplayerView extends FrameLayout implements
|
|||||||
Format videoFormat = player.getVideoFormat();
|
Format videoFormat = player.getVideoFormat();
|
||||||
int width = videoFormat != null ? videoFormat.width : 0;
|
int width = videoFormat != null ? videoFormat.width : 0;
|
||||||
int height = videoFormat != null ? videoFormat.height : 0;
|
int height = videoFormat != null ? videoFormat.height : 0;
|
||||||
|
String trackId = videoFormat != null ? videoFormat.id : "-1";
|
||||||
eventEmitter.load(player.getDuration(), player.getCurrentPosition(), width, height,
|
eventEmitter.load(player.getDuration(), player.getCurrentPosition(), width, height,
|
||||||
getAudioTrackInfo(), getTextTrackInfo(), getVideoTrackInfo());
|
getAudioTrackInfo(), getTextTrackInfo(), getVideoTrackInfo(), trackId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -889,7 +907,7 @@ class ReactExoplayerView extends FrameLayout implements
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPlayerError(ExoPlaybackException e) {
|
public void onPlayerError(ExoPlaybackException e) {
|
||||||
String errorString = null;
|
String errorString = "ExoPlaybackException type : " + e.type;
|
||||||
Exception ex = e;
|
Exception ex = e;
|
||||||
if (e.type == ExoPlaybackException.TYPE_RENDERER) {
|
if (e.type == ExoPlaybackException.TYPE_RENDERER) {
|
||||||
Exception cause = e.getRendererException();
|
Exception cause = e.getRendererException();
|
||||||
@ -914,12 +932,9 @@ class ReactExoplayerView extends FrameLayout implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (e.type == ExoPlaybackException.TYPE_SOURCE) {
|
else if (e.type == ExoPlaybackException.TYPE_SOURCE) {
|
||||||
ex = e.getSourceException();
|
|
||||||
errorString = getResources().getString(R.string.unrecognized_media_format);
|
errorString = getResources().getString(R.string.unrecognized_media_format);
|
||||||
}
|
}
|
||||||
if (errorString != null) {
|
eventEmitter.error(errorString, ex);
|
||||||
eventEmitter.error(errorString, ex);
|
|
||||||
}
|
|
||||||
playerNeedsSource = true;
|
playerNeedsSource = true;
|
||||||
if (isBehindLiveWindow(e)) {
|
if (isBehindLiveWindow(e)) {
|
||||||
clearResumePosition();
|
clearResumePosition();
|
||||||
@ -930,12 +945,14 @@ class ReactExoplayerView extends FrameLayout implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isBehindLiveWindow(ExoPlaybackException e) {
|
private static boolean isBehindLiveWindow(ExoPlaybackException e) {
|
||||||
|
Log.e("ExoPlayer Exception", e.toString());
|
||||||
if (e.type != ExoPlaybackException.TYPE_SOURCE) {
|
if (e.type != ExoPlaybackException.TYPE_SOURCE) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Throwable cause = e.getSourceException();
|
Throwable cause = e.getSourceException();
|
||||||
while (cause != null) {
|
while (cause != null) {
|
||||||
if (cause instanceof BehindLiveWindowException) {
|
if (cause instanceof BehindLiveWindowException ||
|
||||||
|
cause instanceof HttpDataSource.HttpDataSourceException) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
cause = cause.getCause();
|
cause = cause.getCause();
|
||||||
|
@ -107,8 +107,10 @@ class VideoEventEmitter {
|
|||||||
private static final String EVENT_PROP_PLAYABLE_DURATION = "playableDuration";
|
private static final String EVENT_PROP_PLAYABLE_DURATION = "playableDuration";
|
||||||
private static final String EVENT_PROP_SEEKABLE_DURATION = "seekableDuration";
|
private static final String EVENT_PROP_SEEKABLE_DURATION = "seekableDuration";
|
||||||
private static final String EVENT_PROP_CURRENT_TIME = "currentTime";
|
private static final String EVENT_PROP_CURRENT_TIME = "currentTime";
|
||||||
|
private static final String EVENT_PROP_CURRENT_PLAYBACK_TIME = "currentPlaybackTime";
|
||||||
private static final String EVENT_PROP_SEEK_TIME = "seekTime";
|
private static final String EVENT_PROP_SEEK_TIME = "seekTime";
|
||||||
private static final String EVENT_PROP_NATURAL_SIZE = "naturalSize";
|
private static final String EVENT_PROP_NATURAL_SIZE = "naturalSize";
|
||||||
|
private static final String EVENT_PROP_TRACK_ID = "trackId";
|
||||||
private static final String EVENT_PROP_WIDTH = "width";
|
private static final String EVENT_PROP_WIDTH = "width";
|
||||||
private static final String EVENT_PROP_HEIGHT = "height";
|
private static final String EVENT_PROP_HEIGHT = "height";
|
||||||
private static final String EVENT_PROP_ORIENTATION = "orientation";
|
private static final String EVENT_PROP_ORIENTATION = "orientation";
|
||||||
@ -137,7 +139,7 @@ class VideoEventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void load(double duration, double currentPosition, int videoWidth, int videoHeight,
|
void load(double duration, double currentPosition, int videoWidth, int videoHeight,
|
||||||
WritableArray audioTracks, WritableArray textTracks, WritableArray videoTracks) {
|
WritableArray audioTracks, WritableArray textTracks, WritableArray videoTracks, String trackId) {
|
||||||
WritableMap event = Arguments.createMap();
|
WritableMap event = Arguments.createMap();
|
||||||
event.putDouble(EVENT_PROP_DURATION, duration / 1000D);
|
event.putDouble(EVENT_PROP_DURATION, duration / 1000D);
|
||||||
event.putDouble(EVENT_PROP_CURRENT_TIME, currentPosition / 1000D);
|
event.putDouble(EVENT_PROP_CURRENT_TIME, currentPosition / 1000D);
|
||||||
@ -151,7 +153,7 @@ class VideoEventEmitter {
|
|||||||
naturalSize.putString(EVENT_PROP_ORIENTATION, "portrait");
|
naturalSize.putString(EVENT_PROP_ORIENTATION, "portrait");
|
||||||
}
|
}
|
||||||
event.putMap(EVENT_PROP_NATURAL_SIZE, naturalSize);
|
event.putMap(EVENT_PROP_NATURAL_SIZE, naturalSize);
|
||||||
|
event.putString(EVENT_PROP_TRACK_ID, trackId);
|
||||||
event.putArray(EVENT_PROP_VIDEO_TRACKS, videoTracks);
|
event.putArray(EVENT_PROP_VIDEO_TRACKS, videoTracks);
|
||||||
event.putArray(EVENT_PROP_AUDIO_TRACKS, audioTracks);
|
event.putArray(EVENT_PROP_AUDIO_TRACKS, audioTracks);
|
||||||
event.putArray(EVENT_PROP_TEXT_TRACKS, textTracks);
|
event.putArray(EVENT_PROP_TEXT_TRACKS, textTracks);
|
||||||
@ -168,17 +170,21 @@ class VideoEventEmitter {
|
|||||||
receiveEvent(EVENT_LOAD, event);
|
receiveEvent(EVENT_LOAD, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void progressChanged(double currentPosition, double bufferedDuration, double seekableDuration) {
|
void progressChanged(double currentPosition, double bufferedDuration, double seekableDuration, double currentPlaybackTime) {
|
||||||
WritableMap event = Arguments.createMap();
|
WritableMap event = Arguments.createMap();
|
||||||
event.putDouble(EVENT_PROP_CURRENT_TIME, currentPosition / 1000D);
|
event.putDouble(EVENT_PROP_CURRENT_TIME, currentPosition / 1000D);
|
||||||
event.putDouble(EVENT_PROP_PLAYABLE_DURATION, bufferedDuration / 1000D);
|
event.putDouble(EVENT_PROP_PLAYABLE_DURATION, bufferedDuration / 1000D);
|
||||||
event.putDouble(EVENT_PROP_SEEKABLE_DURATION, seekableDuration / 1000D);
|
event.putDouble(EVENT_PROP_SEEKABLE_DURATION, seekableDuration / 1000D);
|
||||||
|
event.putDouble(EVENT_PROP_CURRENT_PLAYBACK_TIME, currentPlaybackTime);
|
||||||
receiveEvent(EVENT_PROGRESS, event);
|
receiveEvent(EVENT_PROGRESS, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bandwidthReport(double bitRateEstimate) {
|
void bandwidthReport(double bitRateEstimate, int height, int width, String id) {
|
||||||
WritableMap event = Arguments.createMap();
|
WritableMap event = Arguments.createMap();
|
||||||
event.putDouble(EVENT_PROP_BITRATE, bitRateEstimate);
|
event.putDouble(EVENT_PROP_BITRATE, bitRateEstimate);
|
||||||
|
event.putInt(EVENT_PROP_WIDTH, width);
|
||||||
|
event.putInt(EVENT_PROP_HEIGHT, height);
|
||||||
|
event.putString(EVENT_PROP_TRACK_ID, id);
|
||||||
receiveEvent(EVENT_BANDWIDTH, event);
|
receiveEvent(EVENT_BANDWIDTH, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -226,7 +232,7 @@ class VideoEventEmitter {
|
|||||||
void error(String errorString, Exception exception) {
|
void error(String errorString, Exception exception) {
|
||||||
WritableMap error = Arguments.createMap();
|
WritableMap error = Arguments.createMap();
|
||||||
error.putString(EVENT_PROP_ERROR_STRING, errorString);
|
error.putString(EVENT_PROP_ERROR_STRING, errorString);
|
||||||
error.putString(EVENT_PROP_ERROR_EXCEPTION, exception.getMessage());
|
error.putString(EVENT_PROP_ERROR_EXCEPTION, exception.toString());
|
||||||
WritableMap event = Arguments.createMap();
|
WritableMap event = Arguments.createMap();
|
||||||
event.putMap(EVENT_PROP_ERROR, error);
|
event.putMap(EVENT_PROP_ERROR, error);
|
||||||
receiveEvent(EVENT_ERROR, event);
|
receiveEvent(EVENT_ERROR, event);
|
||||||
|
@ -64,6 +64,7 @@ static int const RCTVideoUnset = -1;
|
|||||||
NSDictionary * _selectedAudioTrack;
|
NSDictionary * _selectedAudioTrack;
|
||||||
BOOL _playbackStalled;
|
BOOL _playbackStalled;
|
||||||
BOOL _playInBackground;
|
BOOL _playInBackground;
|
||||||
|
float _preferredForwardBufferDuration;
|
||||||
BOOL _playWhenInactive;
|
BOOL _playWhenInactive;
|
||||||
BOOL _pictureInPicture;
|
BOOL _pictureInPicture;
|
||||||
NSString * _ignoreSilentSwitch;
|
NSString * _ignoreSilentSwitch;
|
||||||
@ -105,6 +106,7 @@ static int const RCTVideoUnset = -1;
|
|||||||
_controls = NO;
|
_controls = NO;
|
||||||
_playerBufferEmpty = YES;
|
_playerBufferEmpty = YES;
|
||||||
_playInBackground = false;
|
_playInBackground = false;
|
||||||
|
_preferredForwardBufferDuration = 0.0f;
|
||||||
_allowsExternalPlayback = YES;
|
_allowsExternalPlayback = YES;
|
||||||
_playWhenInactive = false;
|
_playWhenInactive = false;
|
||||||
_pictureInPicture = false;
|
_pictureInPicture = false;
|
||||||
@ -265,6 +267,7 @@ static int const RCTVideoUnset = -1;
|
|||||||
}
|
}
|
||||||
|
|
||||||
CMTime currentTime = _player.currentTime;
|
CMTime currentTime = _player.currentTime;
|
||||||
|
NSDate *currentPlaybackTime = _player.currentItem.currentDate;
|
||||||
const Float64 duration = CMTimeGetSeconds(playerDuration);
|
const Float64 duration = CMTimeGetSeconds(playerDuration);
|
||||||
const Float64 currentTimeSecs = CMTimeGetSeconds(currentTime);
|
const Float64 currentTimeSecs = CMTimeGetSeconds(currentTime);
|
||||||
|
|
||||||
@ -276,6 +279,7 @@ static int const RCTVideoUnset = -1;
|
|||||||
@"playableDuration": [self calculatePlayableDuration],
|
@"playableDuration": [self calculatePlayableDuration],
|
||||||
@"atValue": [NSNumber numberWithLongLong:currentTime.value],
|
@"atValue": [NSNumber numberWithLongLong:currentTime.value],
|
||||||
@"atTimescale": [NSNumber numberWithInt:currentTime.timescale],
|
@"atTimescale": [NSNumber numberWithInt:currentTime.timescale],
|
||||||
|
@"currentPlaybackTime": [NSNumber numberWithLongLong:[@(floor([currentPlaybackTime timeIntervalSince1970] * 1000)) longLongValue]],
|
||||||
@"target": self.reactTag,
|
@"target": self.reactTag,
|
||||||
@"seekableDuration": [self calculateSeekableDuration],
|
@"seekableDuration": [self calculateSeekableDuration],
|
||||||
});
|
});
|
||||||
@ -354,6 +358,7 @@ static int const RCTVideoUnset = -1;
|
|||||||
// perform on next run loop, otherwise other passed react-props may not be set
|
// perform on next run loop, otherwise other passed react-props may not be set
|
||||||
[self playerItemForSource:source withCallback:^(AVPlayerItem * playerItem) {
|
[self playerItemForSource:source withCallback:^(AVPlayerItem * playerItem) {
|
||||||
_playerItem = playerItem;
|
_playerItem = playerItem;
|
||||||
|
[self setPreferredForwardBufferDuration:_preferredForwardBufferDuration];
|
||||||
[self addPlayerItemObservers];
|
[self addPlayerItemObservers];
|
||||||
[self setFilter:_filterName];
|
[self setFilter:_filterName];
|
||||||
[self setMaxBitRate:_maxBitRate];
|
[self setMaxBitRate:_maxBitRate];
|
||||||
@ -995,6 +1000,12 @@ static int const RCTVideoUnset = -1;
|
|||||||
_playerItem.preferredPeakBitRate = maxBitRate;
|
_playerItem.preferredPeakBitRate = maxBitRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setPreferredForwardBufferDuration:(float) preferredForwardBufferDuration
|
||||||
|
{
|
||||||
|
_preferredForwardBufferDuration = preferredForwardBufferDuration;
|
||||||
|
_playerItem.preferredForwardBufferDuration = preferredForwardBufferDuration;
|
||||||
|
}
|
||||||
|
|
||||||
- (void)setAutomaticallyWaitsToMinimizeStalling:(BOOL)waits
|
- (void)setAutomaticallyWaitsToMinimizeStalling:(BOOL)waits
|
||||||
{
|
{
|
||||||
_automaticallyWaitsToMinimizeStalling = waits;
|
_automaticallyWaitsToMinimizeStalling = waits;
|
||||||
|
@ -32,6 +32,7 @@ RCT_EXPORT_VIEW_PROPERTY(muted, BOOL);
|
|||||||
RCT_EXPORT_VIEW_PROPERTY(controls, BOOL);
|
RCT_EXPORT_VIEW_PROPERTY(controls, BOOL);
|
||||||
RCT_EXPORT_VIEW_PROPERTY(volume, float);
|
RCT_EXPORT_VIEW_PROPERTY(volume, float);
|
||||||
RCT_EXPORT_VIEW_PROPERTY(playInBackground, BOOL);
|
RCT_EXPORT_VIEW_PROPERTY(playInBackground, BOOL);
|
||||||
|
RCT_EXPORT_VIEW_PROPERTY(preferredForwardBufferDuration, float);
|
||||||
RCT_EXPORT_VIEW_PROPERTY(playWhenInactive, BOOL);
|
RCT_EXPORT_VIEW_PROPERTY(playWhenInactive, BOOL);
|
||||||
RCT_EXPORT_VIEW_PROPERTY(pictureInPicture, BOOL);
|
RCT_EXPORT_VIEW_PROPERTY(pictureInPicture, BOOL);
|
||||||
RCT_EXPORT_VIEW_PROPERTY(ignoreSilentSwitch, NSString);
|
RCT_EXPORT_VIEW_PROPERTY(ignoreSilentSwitch, NSString);
|
||||||
|
Loading…
Reference in New Issue
Block a user