Skip to content

Commit

Permalink
code cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
mihailapuste committed Oct 6, 2023
1 parent e976f78 commit c15a742
Showing 1 changed file with 87 additions and 67 deletions.
154 changes: 87 additions & 67 deletions ios/Video/RCTVideo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
NotificationCenter.default.removeObserver(self)
self.removePlayerLayer()
_playerObserver.clearPlayer()
_playerLooper?.invalidate()
}

// MARK: - App lifecycle handlers
Expand Down Expand Up @@ -266,110 +267,129 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH

// MARK: - Player and source
@objc
func setUpPlayer(_ playerItem:AVPlayerItem!) {
_playerObserver.player = nil
_playerObserver.playerItem = nil
func setUpPlayer(_ playerItem: AVPlayerItem?) {

if #available(iOS 10.0, *) {
self._playerItem = playerItem
// Ensure playerItem is not nil before proceeding
guard let playerItem = playerItem else {
return
}

self._player = self._player ?? AVQueuePlayer()
// Reset player observer attributes
_playerObserver.player = nil
_playerObserver.playerItem = nil

self.setUpPlayerItemIos10()
// Check if _player is already initialized, if not, create appropriate player instance
if _player == nil {
if #available(iOS 10.0, *) {
_player = AVQueuePlayer()
} else {
_player = AVPlayer()
_player?.actionAtItemEnd = .none
}
}

self._playerObserver.player = self._player
// Configure the player based on iOS version
if #available(iOS 10.0, *) {
_playerItem = playerItem
setUpPlayerItemIos10()
} else {
self._playerItem = playerItem

self._player = self._player ?? AVPlayer()
self._player?.actionAtItemEnd = .none
DispatchQueue.global(qos: .default).async {
self._player?.replaceCurrentItem(with: playerItem)
// For iOS versions below 10, ensure player operations happen on the main thread
DispatchQueue.main.async { [weak self] in
self?._player?.replaceCurrentItem(with: playerItem)
}

self._playerObserver.playerItem = self._playerItem
self._playerObserver.player = self._player
}

// Set player observer attributes
_playerObserver.player = _player
_playerObserver.playerItem = playerItem
}

func includePlayerItems(replicas: Int) {
// Delaying execution to the next run loop to ensure other React props are set.
RCTVideoUtils.delay().then { [weak self] in
guard
let self = self,
let player = (self._player as? AVQueuePlayer)
else { return }
// Capture a strong reference to self.
guard let strongSelf = self, let player = (strongSelf._player as? AVQueuePlayer) else {
DebugLog("Self or player is nil.")
return
}

let missingReplicas = replicas - player.items().count

if (missingReplicas < 1) {
// If there are enough replicas already, just return.
if missingReplicas <= 0 {
return
}

print("RCTVideo includePlayerItems adding \(missingReplicas) playerItems")

for _ in 1...missingReplicas {
guard
let source = self._source,
let assetResult = RCTVideoUtils.prepareAsset(source: source),
let asset = assetResult.asset,
let assetOptions = assetResult.assetOptions
else {
DebugLog("Could not find video URL in source '\(self._source)'")
// Check if source is available.
guard let source = strongSelf._source else {
DebugLog("Source is nil.")
return
}

// Prepare the asset. Note: Consider performance if this is a heavy operation.
guard let assetResult = RCTVideoUtils.prepareAsset(source: source),
let asset = assetResult.asset,
let assetOptions = assetResult.assetOptions else {
DebugLog("Failed to prepare asset from source '\(source)'.")
return
}

let item = self.playerItemPrepareText(
asset: asset,
assetOptions: assetOptions
)
let item = strongSelf.playerItemPrepareText(asset: asset, assetOptions: assetOptions)

player.insert(
item,
after: player.items().last
)
player.insert(item, after: player.items().last)
}
}
}

func setUpPlayerItemIos10() {
if #available(iOS 10.0, *) {
guard
let playerItem = _playerItem,
let player = (_player as? AVQueuePlayer)
else { return }

player.removeAllItems()
player.actionAtItemEnd = self._repeat ? .advance : .none

if !self._repeat {
DispatchQueue.global(qos: .default).async {
player.replaceCurrentItem(with: playerItem)
}
guard #available(iOS 10.0, *),
let playerItem = _playerItem,
let player = (_player as? AVQueuePlayer)
else { return }

_playerObserver.playerItem = playerItem
// Configure player
player.removeAllItems()
player.actionAtItemEnd = _repeat ? .advance : .none

return
// Non-repeat configuration
if !_repeat {
DispatchQueue.global(qos: .default).async {
player.replaceCurrentItem(with: playerItem)
}
_playerObserver.playerItem = playerItem
return
}

_playerLooper?.invalidate()
_playerLooper = nil

let replicas = 5

self._playerLooper = player.observe(\.currentItem) { [weak self] player, _ in
guard let self = self else { return }

print("RCTVideo _playerLooper")

self._playerObserver.playerItem = player.currentItem
// Invalidate any existing looper
_playerLooper?.invalidate()
_playerLooper = nil

if player.items().count <= replicas {
self.includePlayerItems(replicas: replicas)
}
// Determine number of replicas based on content length
let contentLength = CMTimeGetSeconds(playerItem.duration)
let replicas: Int

switch contentLength {
case 0..<5:
replicas = 7
case 5..<10:
replicas = 5
case 10..<20:
replicas = 3
default:
replicas = 3
}

self.includePlayerItems(replicas: replicas)
_playerLooper = player.observe(\.currentItem) { [weak self] player, _ in
guard let strongSelf = self else { return }
if player.items().count <= replicas {
strongSelf.includePlayerItems(replicas: replicas)
}
}

includePlayerItems(replicas: replicas)
}

@objc
Expand Down

0 comments on commit c15a742

Please sign in to comment.