Skip to content

Commit

Permalink
Fix(ios): fix real time issue when fast zapping (#3582)
Browse files Browse the repository at this point in the history
* fix(ios): fix real time issue when doing fast zapping

* fix(ios): fix delay implementation (timing was not applied correctly)

* chore: fix random crash in sample

* chore: fix linter
  • Loading branch information
freeboub authored Mar 14, 2024
1 parent f4cce2e commit 429fddf
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 10 deletions.
22 changes: 15 additions & 7 deletions examples/basic/src/VideoPlayer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -693,6 +693,9 @@ class VideoPlayer extends Component {
});
}}>
{this.state.audioTracks.map(track => {
if (!track) {
return;
}
return (
<Picker.Item
label={track.language}
Expand Down Expand Up @@ -720,13 +723,18 @@ class VideoPlayer extends Component {
});
}}>
<Picker.Item label={'none'} value={'none'} key={'none'} />
{this.state.textTracks.map(track => (
<Picker.Item
label={track.language}
value={track.language}
key={track.language}
/>
))}
{this.state.textTracks.map(track => {
if (!track) {
return;
}
return (
<Picker.Item
label={track.language}
value={track.language}
key={track.language}
/>
);
})}
</Picker>
)}
</View>
Expand Down
2 changes: 1 addition & 1 deletion ios/Video/Features/RCTVideoUtils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ enum RCTVideoUtils {

static func delay(seconds: Int = 0) -> Promise<Void> {
return Promise<Void>(on: .global()) { fulfill, _ in
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + Double(Int64(seconds)) / Double(NSEC_PER_SEC)) {
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(seconds)) {
fulfill(())
}
}
Expand Down
45 changes: 43 additions & 2 deletions ios/Video/RCTVideo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -300,14 +300,38 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
}
}

var isSetSourceOngoing = false
var nextSource: NSDictionary?

func applyNextSource() {
if self.nextSource != nil {
DebugLog("apply next source")
self.isSetSourceOngoing = false
let nextSrc = self.nextSource
self.nextSource = nil
self.setSrc(nextSrc)
}
}

// MARK: - Player and source

@objc
func setSrc(_ source: NSDictionary!) {
if self.isSetSourceOngoing || self.nextSource != nil {
DebugLog("setSrc buffer request")
self._player?.replaceCurrentItem(with: nil)
nextSource = source
return
}
self.isSetSourceOngoing = true

let dispatchClosure = {
self._source = VideoSource(source)
if self._source?.uri == nil || self._source?.uri == "" {
self._player?.replaceCurrentItem(with: nil)
self.isSetSourceOngoing = false
self.applyNextSource()
DebugLog("setSrc Stopping playback")
return
}
self.removePlayerLayer()
Expand All @@ -321,9 +345,13 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
guard let self else { throw NSError(domain: "", code: 0, userInfo: nil) }
guard let source = self._source else {
DebugLog("The source not exist")
self.isSetSourceOngoing = false
self.applyNextSource()
throw NSError(domain: "", code: 0, userInfo: nil)
}
if let uri = source.uri, uri.starts(with: "ph://") {
self.isSetSourceOngoing = false
self.applyNextSource()
return Promise {
RCTVideoUtils.preparePHAsset(uri: uri).then { asset in
return self.playerItemPrepareText(asset: asset, assetOptions: nil, uri: source.uri ?? "")
Expand All @@ -334,6 +362,8 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
let asset = assetResult.asset,
let assetOptions = assetResult.assetOptions else {
DebugLog("Could not find video URL in source '\(String(describing: self._source))'")
self.isSetSourceOngoing = false
self.applyNextSource()
throw NSError(domain: "", code: 0, userInfo: nil)
}

Expand Down Expand Up @@ -361,7 +391,10 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
return self.playerItemPrepareText(asset: asset, assetOptions: assetOptions, uri: source.uri ?? "")
}.then { [weak self] (playerItem: AVPlayerItem!) in
guard let self else { throw NSError(domain: "", code: 0, userInfo: nil) }

if !self.isSetSourceOngoing {
DebugLog("setSrc has been canceled last step")
return
}
self._player?.pause()
self._playerItem = playerItem
self._playerObserver.playerItem = self._playerItem
Expand Down Expand Up @@ -402,8 +435,16 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
"drm": self._drm?.json ?? NSNull(),
"target": self.reactTag,
])
}.catch { _ in }
self.isSetSourceOngoing = false
self.applyNextSource()
}.catch { error in
DebugLog("An error occurred: \(error.localizedDescription)")
self.onVideoError?(["error": error.localizedDescription])
self.isSetSourceOngoing = false
self.applyNextSource()
}
self._videoLoadStarted = true
self.applyNextSource()
}
DispatchQueue.global(qos: .default).async(execute: dispatchClosure)
}
Expand Down

0 comments on commit 429fddf

Please sign in to comment.