Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose currentPlaybackTime when live stream video #1944

Merged
merged 57 commits into from
May 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
91fc169
added trackId to exoplayer onLoad callback
anubansal92 Jul 10, 2019
e14221f
added trackInfo to bandwidth callback
anubansal92 Jul 10, 2019
a102ce7
syntax fix
anubansal92 Jul 10, 2019
eb14d95
syntax fix
anubansal92 Jul 10, 2019
2ce2e34
version update
anubansal92 Sep 3, 2019
4611654
sending complete logcat for media playback exception ExoPlaybackExcep…
anubansal92 Sep 30, 2019
5cd86dd
Merge branch 'upstream-master' into v5x
sivakumar-cf Oct 29, 2019
6a36597
version bump
anubansal92 Nov 12, 2019
7462dd8
package publish changes
anubansal92 Nov 15, 2019
e45cb13
Live playback fix
parikshit-basu Nov 17, 2019
edb6fc2
Merge branch 'master' of https://github.com/curefit/react-native-video
parikshit-basu Nov 18, 2019
b9b8f89
Version bump
parikshit-basu Nov 18, 2019
1a12840
import fix
anubansal92 Nov 18, 2019
2effca3
Merge pull request #1 from curefit/pb/master/LivePlaybackFix
anubansal92 Nov 18, 2019
9f53c62
version bump
anubansal92 Nov 18, 2019
7600996
Merge branch 'master' of github.com:curefit/react-native-video
anubansal92 Nov 18, 2019
0b1fb14
Merge branch 'v5x' of github.com:curefit/react-native-video
anubansal92 Nov 29, 2019
2039e95
configurable preferredForwardBufferDuration
anubansal92 Dec 13, 2019
fc2c407
Merge pull request #3 from curefit/anu_dev
anubansal92 Dec 13, 2019
3303674
configurable preferredForwardBufferDuration
anubansal92 Dec 13, 2019
1acc1e2
version update
anubansal92 Dec 13, 2019
5526136
Exposing time
parikshit-basu Dec 9, 2019
b25e22a
exo player window current tsp
rishu-curefit Dec 17, 2019
86f6535
return type
rishu-curefit Dec 17, 2019
981368d
Current window timestamp in epoch
rishu-curefit Dec 17, 2019
389511f
iOS changes
rishu-curefit Dec 18, 2019
738f0d7
Merge branch 'anu_dev' of github.com:curefit/react-native-video
anubansal92 Jan 14, 2020
2fc7f7b
version update
anubansal92 Jan 14, 2020
eba58b2
Merge pull request #5 from curefit/anu_dev
anubansal92 Jan 14, 2020
691a6bf
Updated package.json
rishu-curefit Jan 20, 2020
d1539ce
updated version
rishu-curefit Jan 20, 2020
83afd5f
CurrentTime bug fix
rishu-curefit Jan 21, 2020
6a96902
Updated package.json
rishu-curefit Jan 21, 2020
5d4e91d
Updated currentPlaybackTime
rishu-curefit Jan 22, 2020
802abfc
Updated currentPlayback logic
rishu-curefit Jan 22, 2020
585832b
Updated package.json
rishu-curefit Jan 22, 2020
f9dfbdb
Bug fix
rishu-curefit Jan 22, 2020
ded7374
Resolved merge conflicts and updated version
rishu-curefit Feb 3, 2020
d31edf9
Merge pull request #6 from curefit/Release_7.85
anubansal92 Feb 3, 2020
4b31eb5
Added semicolon
rishu-curefit Feb 3, 2020
5d3bd05
Merge pull request #7 from curefit/Release_7.85
rishu-curefit Feb 3, 2020
f4d8167
updated package.json
rishu-curefit Feb 3, 2020
d68ca50
Merge pull request #8 from curefit/Release_7.85
anubansal92 Feb 3, 2020
ef7df20
Updated ReactVideoView
rishu-curefit Feb 3, 2020
877263e
updated verison
rishu-curefit Feb 3, 2020
34b7edf
Merge pull request #9 from curefit/Release_7.85
rishu-curefit Feb 3, 2020
559c8e3
Revert package.json changes
paramaggarwal Mar 11, 2020
f6004dc
Update ReactVideoView.java
paramaggarwal Mar 11, 2020
7997eea
Use standard log
paramaggarwal May 14, 2020
8860325
Document preferredForwardBufferDuration (iOS)
paramaggarwal May 14, 2020
e236807
Document currentPlaybackTime
paramaggarwal May 14, 2020
068fad6
Document trackId
paramaggarwal May 14, 2020
004990e
Update CHANGELOG.md
paramaggarwal May 14, 2020
c6f5b37
Update CHANGELOG.md
paramaggarwal May 14, 2020
325d27f
Update README.md
paramaggarwal May 14, 2020
9264182
Merge branch 'master' into upstream-pr
paramaggarwal May 14, 2020
d9adb31
Update CHANGELOG.md
paramaggarwal May 14, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
- 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)
- 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

Expand Down
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ var styles = StyleSheet.create({
* [automaticallyWaitsToMinimizeStalling](#automaticallyWaitsToMinimizeStalling)
* [bufferConfig](#bufferconfig)
* [controls](#controls)
* [currentPlaybackTime](#currentPlaybackTime)
* [disableFocus](#disableFocus)
* [filter](#filter)
* [filterEnabled](#filterEnabled)
Expand All @@ -297,6 +298,7 @@ var styles = StyleSheet.create({
* [playWhenInactive](#playwheninactive)
* [poster](#poster)
* [posterResizeMode](#posterresizemode)
* [preferredForwardBufferDuration](#preferredForwardBufferDuration)
* [progressUpdateInterval](#progressupdateinterval)
* [rate](#rate)
* [repeat](#repeat)
Expand All @@ -308,6 +310,7 @@ var styles = StyleSheet.create({
* [source](#source)
* [stereoPan](#stereopan)
* [textTracks](#texttracks)
* [trackId](#trackId)
* [useTextureView](#usetextureview)
* [volume](#volume)

Expand Down Expand Up @@ -386,6 +389,11 @@ bufferConfig={{

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
Determines whether to show player controls.
* ** false (default)** - Don't show player controls
Expand Down Expand Up @@ -596,6 +604,13 @@ Determines how to resize the poster image when the frame doesn't match the raw v

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
Delay in milliseconds between onProgress events in milliseconds.

Expand Down Expand Up @@ -831,6 +846,11 @@ textTracks={[

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
Controls whether to output to a TextureView or SurfaceView.

Expand Down
1 change: 1 addition & 0 deletions Video.js
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,7 @@ Video.propTypes = {
rate: PropTypes.number,
pictureInPicture: PropTypes.bool,
playInBackground: PropTypes.bool,
preferredForwardBufferDuration: PropTypes.number,
playWhenInactive: PropTypes.bool,
ignoreSilentSwitch: PropTypes.oneOf(['ignore', 'obey']),
reportBandwidth: PropTypes.bool,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DefaultAllocator;
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
import com.google.android.exoplayer2.upstream.HttpDataSource;
import com.google.android.exoplayer2.util.Util;

import java.net.CookieHandler;
Expand Down Expand Up @@ -161,14 +162,22 @@ public void handleMessage(Message msg) {
) {
long pos = player.getCurrentPosition();
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);
sendMessageDelayed(msg, Math.round(mProgressUpdateInterval));
}
break;
}
}
};

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) {
super(context);
Expand Down Expand Up @@ -257,7 +266,15 @@ public void cleanUpResources() {
@Override
public void onBandwidthSample(int elapsedMs, long bytes, long bitrate) {
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);
}
}
}

Expand Down Expand Up @@ -749,8 +766,9 @@ private void videoLoaded() {
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.load(player.getDuration(), player.getCurrentPosition(), width, height,
getAudioTrackInfo(), getTextTrackInfo(), getVideoTrackInfo());
getAudioTrackInfo(), getTextTrackInfo(), getVideoTrackInfo(), trackId);
}
}

Expand Down Expand Up @@ -889,7 +907,7 @@ public void onPlaybackParametersChanged(PlaybackParameters params) {

@Override
public void onPlayerError(ExoPlaybackException e) {
String errorString = null;
String errorString = "ExoPlaybackException type : " + e.type;
Exception ex = e;
if (e.type == ExoPlaybackException.TYPE_RENDERER) {
Exception cause = e.getRendererException();
Expand All @@ -914,12 +932,9 @@ public void onPlayerError(ExoPlaybackException e) {
}
}
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, ex);
playerNeedsSource = true;
if (isBehindLiveWindow(e)) {
clearResumePosition();
Expand All @@ -930,12 +945,14 @@ else if (e.type == ExoPlaybackException.TYPE_SOURCE) {
}

private static boolean isBehindLiveWindow(ExoPlaybackException e) {
Log.e("ExoPlayer Exception", e.toString());
if (e.type != ExoPlaybackException.TYPE_SOURCE) {
return false;
}
Throwable cause = e.getSourceException();
while (cause != null) {
if (cause instanceof BehindLiveWindowException) {
if (cause instanceof BehindLiveWindowException ||
cause instanceof HttpDataSource.HttpDataSourceException) {
return true;
}
cause = cause.getCause();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,10 @@ class VideoEventEmitter {
private static final String EVENT_PROP_PLAYABLE_DURATION = "playableDuration";
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_PLAYBACK_TIME = "currentPlaybackTime";
private static final String EVENT_PROP_SEEK_TIME = "seekTime";
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_HEIGHT = "height";
private static final String EVENT_PROP_ORIENTATION = "orientation";
Expand Down Expand Up @@ -137,7 +139,7 @@ void loadStart() {
}

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();
event.putDouble(EVENT_PROP_DURATION, duration / 1000D);
event.putDouble(EVENT_PROP_CURRENT_TIME, currentPosition / 1000D);
Expand All @@ -151,7 +153,7 @@ void load(double duration, double currentPosition, int videoWidth, int videoHeig
naturalSize.putString(EVENT_PROP_ORIENTATION, "portrait");
}
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_AUDIO_TRACKS, audioTracks);
event.putArray(EVENT_PROP_TEXT_TRACKS, textTracks);
Expand All @@ -168,17 +170,21 @@ void load(double duration, double currentPosition, int videoWidth, int videoHeig
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();
event.putDouble(EVENT_PROP_CURRENT_TIME, currentPosition / 1000D);
event.putDouble(EVENT_PROP_PLAYABLE_DURATION, bufferedDuration / 1000D);
event.putDouble(EVENT_PROP_SEEKABLE_DURATION, seekableDuration / 1000D);
event.putDouble(EVENT_PROP_CURRENT_PLAYBACK_TIME, currentPlaybackTime);
receiveEvent(EVENT_PROGRESS, event);
}

void bandwidthReport(double bitRateEstimate) {
void bandwidthReport(double bitRateEstimate, int height, int width, String id) {
WritableMap event = Arguments.createMap();
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);
}

Expand Down Expand Up @@ -226,7 +232,7 @@ void fullscreenDidDismiss() {
void error(String errorString, Exception exception) {
WritableMap error = Arguments.createMap();
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();
event.putMap(EVENT_PROP_ERROR, error);
receiveEvent(EVENT_ERROR, event);
Expand Down
11 changes: 11 additions & 0 deletions ios/Video/RCTVideo.m
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ @implementation RCTVideo
NSDictionary * _selectedAudioTrack;
BOOL _playbackStalled;
BOOL _playInBackground;
float _preferredForwardBufferDuration;
BOOL _playWhenInactive;
BOOL _pictureInPicture;
NSString * _ignoreSilentSwitch;
Expand Down Expand Up @@ -105,6 +106,7 @@ - (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
_controls = NO;
_playerBufferEmpty = YES;
_playInBackground = false;
_preferredForwardBufferDuration = 0.0f;
_allowsExternalPlayback = YES;
_playWhenInactive = false;
_pictureInPicture = false;
Expand Down Expand Up @@ -265,6 +267,7 @@ - (void)sendProgressUpdate
}

CMTime currentTime = _player.currentTime;
NSDate *currentPlaybackTime = _player.currentItem.currentDate;
const Float64 duration = CMTimeGetSeconds(playerDuration);
const Float64 currentTimeSecs = CMTimeGetSeconds(currentTime);

Expand All @@ -276,6 +279,7 @@ - (void)sendProgressUpdate
@"playableDuration": [self calculatePlayableDuration],
@"atValue": [NSNumber numberWithLongLong:currentTime.value],
@"atTimescale": [NSNumber numberWithInt:currentTime.timescale],
@"currentPlaybackTime": [NSNumber numberWithLongLong:[@(floor([currentPlaybackTime timeIntervalSince1970] * 1000)) longLongValue]],
@"target": self.reactTag,
@"seekableDuration": [self calculateSeekableDuration],
});
Expand Down Expand Up @@ -354,6 +358,7 @@ - (void)setSrc:(NSDictionary *)source
// perform on next run loop, otherwise other passed react-props may not be set
[self playerItemForSource:source withCallback:^(AVPlayerItem * playerItem) {
_playerItem = playerItem;
[self setPreferredForwardBufferDuration:_preferredForwardBufferDuration];
[self addPlayerItemObservers];
[self setFilter:_filterName];
[self setMaxBitRate:_maxBitRate];
Expand Down Expand Up @@ -995,6 +1000,12 @@ - (void)setMaxBitRate:(float) maxBitRate {
_playerItem.preferredPeakBitRate = maxBitRate;
}

- (void)setPreferredForwardBufferDuration:(float) preferredForwardBufferDuration
{
_preferredForwardBufferDuration = preferredForwardBufferDuration;
_playerItem.preferredForwardBufferDuration = preferredForwardBufferDuration;
}

- (void)setAutomaticallyWaitsToMinimizeStalling:(BOOL)waits
{
_automaticallyWaitsToMinimizeStalling = waits;
Expand Down
1 change: 1 addition & 0 deletions ios/Video/RCTVideoManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ - (dispatch_queue_t)methodQueue
RCT_EXPORT_VIEW_PROPERTY(controls, BOOL);
RCT_EXPORT_VIEW_PROPERTY(volume, float);
RCT_EXPORT_VIEW_PROPERTY(playInBackground, BOOL);
RCT_EXPORT_VIEW_PROPERTY(preferredForwardBufferDuration, float);
RCT_EXPORT_VIEW_PROPERTY(playWhenInactive, BOOL);
RCT_EXPORT_VIEW_PROPERTY(pictureInPicture, BOOL);
RCT_EXPORT_VIEW_PROPERTY(ignoreSilentSwitch, NSString);
Expand Down