Skip to content

Commit

Permalink
feat(ios): add onBandwidthUpdate event (#3331)
Browse files Browse the repository at this point in the history
* feat(ios): add onBandwidthUpdate event
  • Loading branch information
KrzysztofMoch authored Nov 8, 2023
1 parent 8fbdc28 commit 9054db3
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 30 deletions.
15 changes: 14 additions & 1 deletion docs/pages/component/events.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,24 @@ Payload:
Property | Type | Description
--- | --- | ---
bitrate | number | The estimated bitrate in bits/sec
width | number | The width of the video (android only)
height | number | The height of the video (android only)
trackId | string | The track ID of the video track (android only)

Example:
Example on iOS:
```javascript
{
bitrate: 1000000
}
```

Example on Android:
```javascript
{
bitrate: 1000000
width: 1920
height: 1080
trackId: 'some-track-id'
}
```

Expand Down
18 changes: 12 additions & 6 deletions ios/Video/Features/RCTPlayerObserver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ protocol RCTPlayerObserverHandlerObjc {
func handleDidFailToFinishPlaying(notification:NSNotification!)
func handlePlaybackStalled(notification:NSNotification!)
func handlePlayerItemDidReachEnd(notification:NSNotification!)
// unused
// func handleAVPlayerAccess(notification:NSNotification!)
func handleAVPlayerAccess(notification:NSNotification!)
}

protocol RCTPlayerObserverHandler: RCTPlayerObserverHandlerObjc {
Expand All @@ -25,7 +24,6 @@ protocol RCTPlayerObserverHandler: RCTPlayerObserverHandlerObjc {
}

class RCTPlayerObserver: NSObject {

weak var _handlers: RCTPlayerObserverHandler?

var player:AVPlayer? {
Expand Down Expand Up @@ -108,7 +106,6 @@ class RCTPlayerObserver: NSObject {

func addPlayerItemObservers() {
guard let playerItem = playerItem, let _handlers = _handlers else { return }

_playerItemStatusObserver = playerItem.observe(\.status, options: [.new, .old], changeHandler: _handlers.handlePlayerItemStatusChange)
_playerPlaybackBufferEmptyObserver = playerItem.observe(\.isPlaybackBufferEmpty, options: [.new, .old], changeHandler: _handlers.handlePlaybackBufferKeyEmpty)
_playerPlaybackLikelyToKeepUpObserver = playerItem.observe(\.isPlaybackLikelyToKeepUp, options: [.new, .old], changeHandler: _handlers.handlePlaybackLikelyToKeepUp)
Expand All @@ -121,7 +118,6 @@ class RCTPlayerObserver: NSObject {
_playerPlaybackLikelyToKeepUpObserver?.invalidate()
_playerTimedMetadataObserver?.invalidate()
}

func addPlayerViewControllerObservers() {
guard let playerViewController = playerViewController, let _handlers = _handlers else { return }

Expand Down Expand Up @@ -182,10 +178,10 @@ class RCTPlayerObserver: NSObject {

func attachPlayerEventListeners() {
guard let _handlers = _handlers else {return}

NotificationCenter.default.removeObserver(_handlers,
name:NSNotification.Name.AVPlayerItemDidPlayToEndTime,
object:player?.currentItem)

NotificationCenter.default.addObserver(_handlers,
selector:#selector(RCTPlayerObserverHandler.handlePlayerItemDidReachEnd(notification:)),
name:NSNotification.Name.AVPlayerItemDidPlayToEndTime,
Expand All @@ -194,17 +190,27 @@ class RCTPlayerObserver: NSObject {
NotificationCenter.default.removeObserver(_handlers,
name:NSNotification.Name.AVPlayerItemPlaybackStalled,
object:nil)

NotificationCenter.default.addObserver(_handlers,
selector:#selector(RCTPlayerObserverHandler.handlePlaybackStalled(notification:)),
name:NSNotification.Name.AVPlayerItemPlaybackStalled,
object:nil)

NotificationCenter.default.removeObserver(_handlers,
name: NSNotification.Name.AVPlayerItemFailedToPlayToEndTime,
object:nil)

NotificationCenter.default.addObserver(_handlers,
selector:#selector(RCTPlayerObserverHandler.handleDidFailToFinishPlaying(notification:)),
name: NSNotification.Name.AVPlayerItemFailedToPlayToEndTime,
object:nil)

NotificationCenter.default.removeObserver(_handlers, name: NSNotification.Name.AVPlayerItemNewAccessLogEntry, object: player?.currentItem)

NotificationCenter.default.addObserver(_handlers,
selector:#selector(RCTPlayerObserverHandlerObjc.handleAVPlayerAccess(notification:)),
name: NSNotification.Name.AVPlayerItemNewAccessLogEntry,
object: player?.currentItem)
}

func clearPlayer() {
Expand Down
21 changes: 8 additions & 13 deletions ios/Video/RCTVideo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
@objc var onVideoBuffer: RCTDirectEventBlock?
@objc var onVideoError: RCTDirectEventBlock?
@objc var onVideoProgress: RCTDirectEventBlock?
@objc var onBandwidthUpdate: RCTDirectEventBlock?
@objc var onVideoBandwidthUpdate: RCTDirectEventBlock?
@objc var onVideoSeek: RCTDirectEventBlock?
@objc var onVideoEnd: RCTDirectEventBlock?
@objc var onTimedMetadata: RCTDirectEventBlock?
Expand Down Expand Up @@ -1335,16 +1335,11 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
_playerObserver.removePlayerTimeObserver()
}
}

//unused
// @objc func handleAVPlayerAccess(notification:NSNotification!) {
// let accessLog:AVPlayerItemAccessLog! = (notification.object as! AVPlayerItem).accessLog()
// let lastEvent:AVPlayerItemAccessLogEvent! = accessLog.events.last
//
// /* TODO: get this working
// if (self.onBandwidthUpdate) {
// self.onBandwidthUpdate(@{@"bitrate": [NSNumber numberWithFloat:lastEvent.observedBitrate]});
// }
// */
// }

@objc func handleAVPlayerAccess(notification:NSNotification!) {
let accessLog:AVPlayerItemAccessLog! = (notification.object as! AVPlayerItem).accessLog()
let lastEvent:AVPlayerItemAccessLogEvent! = accessLog.events.last

onVideoBandwidthUpdate?(["bitrate": lastEvent.observedBitrate, "target": reactTag])
}
}
2 changes: 1 addition & 1 deletion ios/Video/RCTVideoManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ @interface RCT_EXTERN_MODULE(RCTVideoManager, RCTViewManager)
RCT_EXPORT_VIEW_PROPERTY(onVideoBuffer, RCTDirectEventBlock);
RCT_EXPORT_VIEW_PROPERTY(onVideoError, RCTDirectEventBlock);
RCT_EXPORT_VIEW_PROPERTY(onVideoProgress, RCTDirectEventBlock);
RCT_EXPORT_VIEW_PROPERTY(onBandwidthUpdate, RCTDirectEventBlock);
RCT_EXPORT_VIEW_PROPERTY(onVideoBandwidthUpdate, RCTDirectEventBlock);
RCT_EXPORT_VIEW_PROPERTY(onVideoSeek, RCTDirectEventBlock);
RCT_EXPORT_VIEW_PROPERTY(onVideoEnd, RCTDirectEventBlock);
RCT_EXPORT_VIEW_PROPERTY(onTimedMetadata, RCTDirectEventBlock);
Expand Down
6 changes: 3 additions & 3 deletions src/VideoNativeComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,9 +150,9 @@ export type OnProgressData = Readonly<{

export type OnBandwidthUpdateData = Readonly<{
bitrate: number;
width: number;
height: number;
trackId: number;
width?: number;
height?: number;
trackId?: number;
}>;

export type OnSeekData = Readonly<{
Expand Down
15 changes: 9 additions & 6 deletions src/types/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,12 +131,15 @@ export type OnAudioFocusChangedData = Readonly<{

export type OnBufferData = Readonly<{isBuffering: boolean}>;

export type OnBandwidthUpdateData = Readonly<{
bitrate: number;
width: number;
height: number;
trackId: number;
}>;
export type OnBandwidthUpdateData = Readonly<
| {
bitrate: number;
width: number;
height: number;
trackId: number;
}
| {bitrate: number}
>;

export interface ReactVideoEvents {
onAudioBecomingNoisy?: () => void; //Android, iOS
Expand Down

0 comments on commit 9054db3

Please sign in to comment.