mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-23 06:35:51 +00:00
Temp
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import Postbox
|
||||
import TelegramCore
|
||||
import SyncCore
|
||||
import SwiftSignalKit
|
||||
import CoreMedia
|
||||
import UniversalMediaPlayer
|
||||
|
||||
private let applyQueue = Queue()
|
||||
private let workers = ThreadPool(threadCount: 2, threadPriority: 0.09)
|
||||
private var nextWorker = 0
|
||||
|
||||
final class SoftwareVideoLayerFrameManager {
|
||||
private let fetchDisposable: Disposable
|
||||
private var dataDisposable = MetaDisposable()
|
||||
private let source = Atomic<SoftwareVideoSource?>(value: nil)
|
||||
|
||||
private var baseTimestamp: Double?
|
||||
private var frames: [MediaTrackFrame] = []
|
||||
private var minPts: CMTime?
|
||||
private var maxPts: CMTime?
|
||||
|
||||
private let account: Account
|
||||
private let resource: MediaResource
|
||||
private let queue: ThreadPoolQueue
|
||||
private let layerHolder: SampleBufferLayer
|
||||
|
||||
private var rotationAngle: CGFloat = 0.0
|
||||
private var aspect: CGFloat = 1.0
|
||||
|
||||
private var layerRotationAngleAndAspect: (CGFloat, CGFloat)?
|
||||
|
||||
init(account: Account, fileReference: FileMediaReference, resource: MediaResource, layerHolder: SampleBufferLayer) {
|
||||
nextWorker += 1
|
||||
self.account = account
|
||||
self.resource = resource
|
||||
self.queue = ThreadPoolQueue(threadPool: workers)
|
||||
self.layerHolder = layerHolder
|
||||
layerHolder.layer.videoGravity = .resizeAspectFill
|
||||
layerHolder.layer.masksToBounds = true
|
||||
self.fetchDisposable = fetchedMediaResource(mediaBox: account.postbox.mediaBox, reference: fileReference.resourceReference(resource)).start()
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.fetchDisposable.dispose()
|
||||
self.dataDisposable.dispose()
|
||||
}
|
||||
|
||||
func start() {
|
||||
self.dataDisposable.set((self.account.postbox.mediaBox.resourceData(self.resource, option: .complete(waitUntilFetchStatus: false)) |> deliverOn(applyQueue)).start(next: { [weak self] data in
|
||||
if let strongSelf = self, data.complete {
|
||||
let _ = strongSelf.source.swap(SoftwareVideoSource(path: data.path))
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
func tick(timestamp: Double) {
|
||||
applyQueue.async {
|
||||
if self.baseTimestamp == nil && !self.frames.isEmpty {
|
||||
self.baseTimestamp = timestamp
|
||||
}
|
||||
|
||||
if let baseTimestamp = self.baseTimestamp {
|
||||
var index = 0
|
||||
var latestFrameIndex: Int?
|
||||
while index < self.frames.count {
|
||||
if baseTimestamp + self.frames[index].position.seconds + self.frames[index].duration.seconds <= timestamp {
|
||||
latestFrameIndex = index
|
||||
}
|
||||
index += 1
|
||||
}
|
||||
if let latestFrameIndex = latestFrameIndex {
|
||||
let frame = self.frames[latestFrameIndex]
|
||||
for i in (0 ... latestFrameIndex).reversed() {
|
||||
self.frames.remove(at: i)
|
||||
}
|
||||
if self.layerHolder.layer.status == .failed {
|
||||
self.layerHolder.layer.flush()
|
||||
}
|
||||
/*if self.layerRotationAngleAndAspect?.0 != self.rotationAngle || self.layerRotationAngleAndAspect?.1 != self.aspect {
|
||||
self.layerRotationAngleAndAspect = (self.rotationAngle, self.aspect)
|
||||
var transform = CGAffineTransform(rotationAngle: CGFloat(self.rotationAngle))
|
||||
if !self.rotationAngle.isZero {
|
||||
transform = transform.scaledBy(x: CGFloat(self.aspect), y: CGFloat(1.0 / self.aspect))
|
||||
}
|
||||
self.layerHolder.layer.setAffineTransform(transform)
|
||||
}*/
|
||||
self.layerHolder.layer.enqueue(frame.sampleBuffer)
|
||||
}
|
||||
}
|
||||
|
||||
self.poll()
|
||||
}
|
||||
}
|
||||
|
||||
private var polling = false
|
||||
|
||||
private func poll() {
|
||||
if self.frames.count < 3 && !self.polling {
|
||||
self.polling = true
|
||||
let maxPts = self.maxPts
|
||||
self.queue.addTask(ThreadPoolTask { [weak self] state in
|
||||
if state.cancelled.with({ $0 }) {
|
||||
return
|
||||
}
|
||||
if let strongSelf = self {
|
||||
let frameAndLoop = (strongSelf.source.with { $0 })?.readFrame(maxPts: maxPts)
|
||||
|
||||
applyQueue.async {
|
||||
if let strongSelf = self {
|
||||
strongSelf.polling = false
|
||||
if let (_, rotationAngle, aspect, _) = frameAndLoop {
|
||||
strongSelf.rotationAngle = rotationAngle
|
||||
strongSelf.aspect = aspect
|
||||
}
|
||||
if let frame = frameAndLoop?.0 {
|
||||
if strongSelf.minPts == nil || CMTimeCompare(strongSelf.minPts!, frame.position) < 0 {
|
||||
strongSelf.minPts = frame.position
|
||||
}
|
||||
strongSelf.frames.append(frame)
|
||||
}
|
||||
if let loop = frameAndLoop?.3, loop {
|
||||
strongSelf.maxPts = strongSelf.minPts
|
||||
strongSelf.minPts = nil
|
||||
}
|
||||
strongSelf.poll()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user