Мое приложение вылетает с сообщением «Прервано из-за проблемы с памятью» при использовании AVPlayerLooper
для бесконечного зацикливания видео.Эта проблема возникает только на старых устройствах (это не происходит на iPhone 6S и новее) и с очень короткими циклами (короче 1 секунды).
Я пытался использовать AVPlayer и наблюдать AVPlayerItemDidPlayToEndTime
, а затемстремление начать вручную, но это решение вызывает короткий перерыв / сбой между каждым циклом, и это вызывает проблемы синхронизации для моей конкретной потребности.Приостановка перед вызовом seek(to: CMTime.zero)
не решает проблему.
Вот мой класс Looper:
class Looper: NSObject {
private var playerItem: AVPlayerItem!
private var player: AVQueuePlayer!
private let playerLayer = AVPlayerLayer()
private var playerLooper: AVPlayerLooper!
private var isPaused: Bool = false {
didSet {
isPaused ? player.pause() : player.play()
}
}
weak var delegate: LooperDelegate?
required init(videoURL: URL) {
super.init()
let asset = AVURLAsset(url: videoURL, options: ["AVURLAssetPreferPreciseDurationAndTimingKey" : true])
playerItem = AVPlayerItem(asset: asset)
player = AVQueuePlayer(playerItem: playerItem)
playerLayer.player = player
playerLooper = AVPlayerLooper(player: player, templateItem: playerItem)
player.addObserver(self, forKeyPath: #keyPath(AVPlayer.status), options: [.old, .new], context: nil)
player.addObserver(self, forKeyPath: #keyPath(AVPlayer.timeControlStatus), options: [.old, .new], context: nil)
playerLooper.addObserver(self, forKeyPath: #keyPath(AVPlayerLooper.status), options: [.old, .new], context: nil)
}
deinit {
player.removeObserver(self, forKeyPath: #keyPath(AVPlayer.status))
player.removeObserver(self, forKeyPath: #keyPath(AVPlayer.timeControlStatus))
playerLooper.removeObserver(self, forKeyPath: #keyPath(AVPlayerLooper.status))
}
func add(in parentLayer: CALayer) {
playerLayer.frame = parentLayer.bounds
parentLayer.addSublayer(playerLayer)
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if object as AnyObject? === self.player &&
keyPath == #keyPath(AVPlayer.status),
let statusNumber = change?[.newKey] as? NSNumber,
AVPlayer.Status(rawValue: statusNumber.intValue)! == .readyToPlay {
self.delegate?.isReadyToPlay(duration: playerItem.asset.duration.seconds)
print("Duration: \(playerItem.asset.duration.seconds)")
} else if object as AnyObject? === self.player &&
keyPath == #keyPath(AVPlayer.timeControlStatus),
let oldKey = change?[.oldKey] as? NSNumber,
let newKey = change?[.newKey] as? NSNumber,
oldKey != 2 && newKey == 2 {
self.delegate?.isLooping()
print("isLooping")
} else if object as AnyObject? === self.playerLooper &&
keyPath == #keyPath(AVPlayerLooper.status),
let statusNumber = change?[.newKey] as? NSNumber {
if AVPlayerLooper.Status(rawValue: statusNumber.intValue)! == .ready {
self.delegate?.isReadyForDisplay()
print("isReadyForDisplay")
}
}
}
}