mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-26 16:08:30 +00:00
Various improvements
This commit is contained in:
@@ -273,8 +273,8 @@ private final class VideoStickerFrameSourceCache {
|
||||
|
||||
private let useCache = true
|
||||
|
||||
public func makeVideoStickerDirectFrameSource(queue: Queue, path: String, width: Int, height: Int, cachePathPrefix: String?, unpremultiplyAlpha: Bool) -> AnimatedStickerFrameSource? {
|
||||
return VideoStickerDirectFrameSource(queue: queue, path: path, width: width, height: height, cachePathPrefix: cachePathPrefix, unpremultiplyAlpha: unpremultiplyAlpha)
|
||||
public func makeVideoStickerDirectFrameSource(queue: Queue, path: String, hintVP9: Bool, width: Int, height: Int, cachePathPrefix: String?, unpremultiplyAlpha: Bool) -> AnimatedStickerFrameSource? {
|
||||
return VideoStickerDirectFrameSource(queue: queue, path: path, isVP9: hintVP9, width: width, height: height, cachePathPrefix: cachePathPrefix, unpremultiplyAlpha: unpremultiplyAlpha)
|
||||
}
|
||||
|
||||
public final class VideoStickerDirectFrameSource: AnimatedStickerFrameSource {
|
||||
@@ -290,7 +290,7 @@ public final class VideoStickerDirectFrameSource: AnimatedStickerFrameSource {
|
||||
public var duration: Double
|
||||
fileprivate var currentFrame: Int
|
||||
|
||||
private let source: SoftwareVideoSource?
|
||||
private var source: FFMpegFileReader?
|
||||
|
||||
public var frameIndex: Int {
|
||||
if self.frameCount == 0 {
|
||||
@@ -300,7 +300,7 @@ public final class VideoStickerDirectFrameSource: AnimatedStickerFrameSource {
|
||||
}
|
||||
}
|
||||
|
||||
public init?(queue: Queue, path: String, width: Int, height: Int, cachePathPrefix: String?, unpremultiplyAlpha: Bool = true) {
|
||||
public init?(queue: Queue, path: String, isVP9: Bool = true, width: Int, height: Int, cachePathPrefix: String?, unpremultiplyAlpha: Bool = true) {
|
||||
self.queue = queue
|
||||
self.path = path
|
||||
self.width = width
|
||||
@@ -329,12 +329,25 @@ public final class VideoStickerDirectFrameSource: AnimatedStickerFrameSource {
|
||||
self.frameCount = 1
|
||||
self.duration = 0.0
|
||||
} else {
|
||||
let source = SoftwareVideoSource(path: path, hintVP9: true, unpremultiplyAlpha: unpremultiplyAlpha)
|
||||
self.source = source
|
||||
let source = FFMpegFileReader(
|
||||
source: .file(path),
|
||||
passthroughDecoder: false,
|
||||
useHardwareAcceleration: false,
|
||||
selectedStream: .mediaType(.video),
|
||||
seek: nil,
|
||||
maxReadablePts: nil
|
||||
)
|
||||
if let source {
|
||||
self.source = source
|
||||
self.frameRate = min(30, source.frameRate())
|
||||
self.duration = source.duration().seconds
|
||||
} else {
|
||||
self.source = nil
|
||||
self.frameRate = 30
|
||||
self.duration = 0.0
|
||||
}
|
||||
self.image = nil
|
||||
self.frameRate = min(30, source.getFramerate())
|
||||
self.frameCount = 0
|
||||
self.duration = source.reportedDuration.seconds
|
||||
}
|
||||
}
|
||||
|
||||
@@ -365,56 +378,66 @@ public final class VideoStickerDirectFrameSource: AnimatedStickerFrameSource {
|
||||
} else if useCache, let cache = self.cache, let yuvData = cache.readUncompressedYuvaFrame(index: frameIndex) {
|
||||
return AnimatedStickerFrame(data: yuvData, type: .yuva, width: self.width, height: self.height, bytesPerRow: self.width * 2, index: frameIndex, isLastFrame: frameIndex == self.frameCount - 1, totalFrames: self.frameCount)
|
||||
} else if let source = self.source {
|
||||
let frameAndLoop = source.readFrame(maxPts: nil)
|
||||
if frameAndLoop.0 == nil {
|
||||
if frameAndLoop.3 {
|
||||
if self.frameCount == 0 {
|
||||
if let cache = self.cache {
|
||||
if cache.storedFrames == frameIndex {
|
||||
self.frameCount = frameIndex
|
||||
cache.storeFrameRateAndCount(frameRate: self.frameRate, frameCount: self.frameCount)
|
||||
} else {
|
||||
Logger.shared.log("VideoSticker", "Missed a frame? \(frameIndex) \(cache.storedFrames)")
|
||||
}
|
||||
} else {
|
||||
self.frameCount = frameIndex
|
||||
}
|
||||
let frameAndLoop = source.readFrame(argb: true)
|
||||
switch frameAndLoop {
|
||||
case let .frame(frame):
|
||||
var frameData = Data(count: self.bytesPerRow * self.height)
|
||||
frameData.withUnsafeMutableBytes { buffer -> Void in
|
||||
guard let bytes = buffer.baseAddress?.assumingMemoryBound(to: UInt8.self) else {
|
||||
return
|
||||
}
|
||||
self.currentFrame = 0
|
||||
} else {
|
||||
Logger.shared.log("VideoSticker", "Skipped a frame?")
|
||||
|
||||
let imageBuffer = CMSampleBufferGetImageBuffer(frame.sampleBuffer)
|
||||
CVPixelBufferLockBaseAddress(imageBuffer!, CVPixelBufferLockFlags(rawValue: 0))
|
||||
let bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer!)
|
||||
let width = CVPixelBufferGetWidth(imageBuffer!)
|
||||
let height = CVPixelBufferGetHeight(imageBuffer!)
|
||||
let srcData = CVPixelBufferGetBaseAddress(imageBuffer!)
|
||||
|
||||
var sourceBuffer = vImage_Buffer(data: srcData, height: vImagePixelCount(height), width: vImagePixelCount(width), rowBytes: bytesPerRow)
|
||||
var destBuffer = vImage_Buffer(data: bytes, height: vImagePixelCount(self.height), width: vImagePixelCount(self.width), rowBytes: self.bytesPerRow)
|
||||
|
||||
let _ = vImageScale_ARGB8888(&sourceBuffer, &destBuffer, nil, vImage_Flags(kvImageDoNotTile))
|
||||
|
||||
CVPixelBufferUnlockBaseAddress(imageBuffer!, CVPixelBufferLockFlags(rawValue: 0))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
guard let frame = frameAndLoop.0 else {
|
||||
return nil
|
||||
}
|
||||
|
||||
var frameData = Data(count: self.bytesPerRow * self.height)
|
||||
frameData.withUnsafeMutableBytes { buffer -> Void in
|
||||
guard let bytes = buffer.baseAddress?.assumingMemoryBound(to: UInt8.self) else {
|
||||
return
|
||||
}
|
||||
|
||||
let imageBuffer = CMSampleBufferGetImageBuffer(frame.sampleBuffer)
|
||||
CVPixelBufferLockBaseAddress(imageBuffer!, CVPixelBufferLockFlags(rawValue: 0))
|
||||
let bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer!)
|
||||
let width = CVPixelBufferGetWidth(imageBuffer!)
|
||||
let height = CVPixelBufferGetHeight(imageBuffer!)
|
||||
let srcData = CVPixelBufferGetBaseAddress(imageBuffer!)
|
||||
|
||||
var sourceBuffer = vImage_Buffer(data: srcData, height: vImagePixelCount(height), width: vImagePixelCount(width), rowBytes: bytesPerRow)
|
||||
var destBuffer = vImage_Buffer(data: bytes, height: vImagePixelCount(self.height), width: vImagePixelCount(self.width), rowBytes: self.bytesPerRow)
|
||||
|
||||
let _ = vImageScale_ARGB8888(&sourceBuffer, &destBuffer, nil, vImage_Flags(kvImageDoNotTile))
|
||||
|
||||
CVPixelBufferUnlockBaseAddress(imageBuffer!, CVPixelBufferLockFlags(rawValue: 0))
|
||||
}
|
||||
|
||||
self.cache?.storeUncompressedRgbFrame(index: frameIndex, rgbData: frameData)
|
||||
|
||||
return AnimatedStickerFrame(data: frameData, type: .argb, width: self.width, height: self.height, bytesPerRow: self.bytesPerRow, index: frameIndex, isLastFrame: frameIndex == self.frameCount - 1, totalFrames: self.frameCount, multiplyAlpha: true)
|
||||
self.cache?.storeUncompressedRgbFrame(index: frameIndex, rgbData: frameData)
|
||||
|
||||
return AnimatedStickerFrame(data: frameData, type: .argb, width: self.width, height: self.height, bytesPerRow: self.bytesPerRow, index: frameIndex, isLastFrame: frameIndex == self.frameCount - 1, totalFrames: self.frameCount, multiplyAlpha: true)
|
||||
case .endOfStream:
|
||||
if self.frameCount == 0 {
|
||||
if let cache = self.cache {
|
||||
if cache.storedFrames == frameIndex {
|
||||
self.frameCount = frameIndex
|
||||
cache.storeFrameRateAndCount(frameRate: self.frameRate, frameCount: self.frameCount)
|
||||
} else {
|
||||
Logger.shared.log("VideoSticker", "Missed a frame? \(frameIndex) \(cache.storedFrames)")
|
||||
}
|
||||
} else {
|
||||
self.frameCount = frameIndex
|
||||
}
|
||||
}
|
||||
self.currentFrame = 0
|
||||
self.source = FFMpegFileReader(
|
||||
source: .file(self.path),
|
||||
passthroughDecoder: false,
|
||||
useHardwareAcceleration: false,
|
||||
selectedStream: .mediaType(.video),
|
||||
seek: nil,
|
||||
maxReadablePts: nil
|
||||
)
|
||||
|
||||
if let cache = self.cache {
|
||||
if let yuvData = cache.readUncompressedYuvaFrame(index: self.currentFrame) {
|
||||
return AnimatedStickerFrame(data: yuvData, type: .yuva, width: self.width, height: self.height, bytesPerRow: self.width * 2, index: frameIndex, isLastFrame: frameIndex == self.frameCount - 1, totalFrames: self.frameCount)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
case .waitingForMoreData, .error:
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user