mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
127 lines
3.7 KiB
Swift
127 lines
3.7 KiB
Swift
import Foundation
|
|
import AVFoundation
|
|
import AsyncDisplayKit
|
|
import Display
|
|
import SwiftSignalKit
|
|
import TelegramCore
|
|
|
|
private class VideoStickerNodeDisplayEvents: ASDisplayNode {
|
|
private var value: Bool = false
|
|
var updated: ((Bool) -> Void)?
|
|
|
|
override init() {
|
|
super.init()
|
|
|
|
self.isLayerBacked = true
|
|
}
|
|
|
|
override func didEnterHierarchy() {
|
|
super.didEnterHierarchy()
|
|
|
|
if !self.value {
|
|
self.value = true
|
|
self.updated?(true)
|
|
}
|
|
}
|
|
|
|
override func didExitHierarchy() {
|
|
super.didExitHierarchy()
|
|
|
|
DispatchQueue.main.async { [weak self] in
|
|
guard let strongSelf = self else {
|
|
return
|
|
}
|
|
if !strongSelf.isInHierarchy {
|
|
if strongSelf.value {
|
|
strongSelf.value = false
|
|
strongSelf.updated?(false)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public class VideoStickerNode: ASDisplayNode {
|
|
private let eventsNode: VideoStickerNodeDisplayEvents
|
|
|
|
private var layerHolder: SampleBufferLayer?
|
|
private var manager: SoftwareVideoLayerFrameManager?
|
|
|
|
private var displayLink: ConstantDisplayLinkAnimator?
|
|
private var displayLinkTimestamp: Double = 0.0
|
|
|
|
public var started: () -> Void = {}
|
|
|
|
private var validLayout: CGSize?
|
|
|
|
private var isDisplaying: Bool = false {
|
|
didSet {
|
|
self.updateIsPlaying()
|
|
}
|
|
}
|
|
private var isPlaying: Bool = false
|
|
|
|
public override init() {
|
|
self.eventsNode = VideoStickerNodeDisplayEvents()
|
|
|
|
super.init()
|
|
|
|
self.eventsNode.updated = { [weak self] value in
|
|
guard let strongSelf = self else {
|
|
return
|
|
}
|
|
strongSelf.isDisplaying = value
|
|
}
|
|
self.addSubnode(self.eventsNode)
|
|
}
|
|
|
|
private func updateIsPlaying() {
|
|
let isPlaying = self.isPlaying && self.isDisplaying
|
|
if isPlaying {
|
|
let displayLink: ConstantDisplayLinkAnimator
|
|
if let current = self.displayLink {
|
|
displayLink = current
|
|
} else {
|
|
displayLink = ConstantDisplayLinkAnimator { [weak self] in
|
|
guard let strongSelf = self else {
|
|
return
|
|
}
|
|
strongSelf.manager?.tick(timestamp: strongSelf.displayLinkTimestamp)
|
|
strongSelf.displayLinkTimestamp += 1.0 / 30.0
|
|
}
|
|
displayLink.frameInterval = 2
|
|
self.displayLink = displayLink
|
|
}
|
|
displayLink.isPaused = !isPlaying
|
|
} else {
|
|
self.displayLink?.isPaused = true
|
|
}
|
|
}
|
|
|
|
public func update(isPlaying: Bool) {
|
|
self.isPlaying = isPlaying
|
|
self.updateIsPlaying()
|
|
}
|
|
|
|
public func update(account: Account, fileReference: FileMediaReference) {
|
|
let layerHolder = takeSampleBufferLayer()
|
|
layerHolder.layer.videoGravity = AVLayerVideoGravity.resizeAspectFill
|
|
if let size = self.validLayout {
|
|
layerHolder.layer.frame = CGRect(origin: CGPoint(), size: size)
|
|
}
|
|
self.layer.addSublayer(layerHolder.layer)
|
|
self.layerHolder = layerHolder
|
|
|
|
let manager = SoftwareVideoLayerFrameManager(account: account, fileReference: fileReference, layerHolder: layerHolder, hintVP9: true)
|
|
manager.started = self.started
|
|
self.manager = manager
|
|
manager.start()
|
|
}
|
|
|
|
public func updateLayout(size: CGSize) {
|
|
self.validLayout = size
|
|
|
|
self.layerHolder?.layer.frame = CGRect(origin: CGPoint(), size: size)
|
|
}
|
|
}
|