Experimental sticker compression

This commit is contained in:
Ali
2022-02-05 03:53:54 +04:00
parent 44ad75f857
commit ff07040ad6
17 changed files with 2630 additions and 26 deletions

View File

@@ -5,6 +5,7 @@ import Display
import AsyncDisplayKit
import YuvConversion
import MediaResources
import AnimationCompression
private let sharedQueue = Queue()
@@ -79,7 +80,6 @@ public final class AnimatedStickerFrame {
self.type = type
self.width = width
self.height = height
assert(bytesPerRow > 0)
self.bytesPerRow = bytesPerRow
self.index = index
self.isLastFrame = isLastFrame
@@ -171,6 +171,7 @@ public final class AnimatedStickerNode: ASDisplayNode {
private var directData: (Data, String, Int, Int, String?, EmojiFitzModifier?, Bool)?
private var cachedData: (Data, Bool, EmojiFitzModifier?)?
private let useMetalCache: Bool
private var renderer: (AnimationRenderer & ASDisplayNode)?
public var isPlaying: Bool = false
@@ -208,10 +209,12 @@ public final class AnimatedStickerNode: ASDisplayNode {
private var overlayColor: (UIColor?, Bool)? = nil
private var size: CGSize?
override public init() {
public init(useMetalCache: Bool = false) {
self.queue = sharedQueue
self.eventsNode = AnimatedStickerNodeDisplayEvents()
self.useMetalCache = useMetalCache
super.init()
self.eventsNode.updated = { [weak self] value in
@@ -233,12 +236,12 @@ public final class AnimatedStickerNode: ASDisplayNode {
override public func didLoad() {
super.didLoad()
#if targetEnvironment(simulator)
self.renderer = SoftwareAnimationRenderer()
#else
self.renderer = SoftwareAnimationRenderer()
//self.renderer = MetalAnimationRenderer()
#endif
if #available(iOS 10.0, *), self.useMetalCache {
self.renderer = CompressedAnimationRenderer()
} else {
self.renderer = SoftwareAnimationRenderer()
}
self.renderer?.frame = CGRect(origin: CGPoint(), size: self.size ?? self.bounds.size)
if let contents = self.nodeToCopyFrameFrom?.renderer?.contents {
self.renderer?.contents = contents
@@ -377,6 +380,7 @@ public final class AnimatedStickerNode: ASDisplayNode {
let queue = self.queue
let timerHolder = self.timer
let frameSourceHolder = self.frameSource
let useMetalCache = self.useMetalCache
self.queue.async { [weak self] in
var maybeFrameSource: AnimatedStickerFrameSource? = frameSourceHolder.with { $0 }?.syncWith { $0 }.value
if maybeFrameSource == nil {
@@ -385,7 +389,7 @@ public final class AnimatedStickerNode: ASDisplayNode {
if directData.6 {
maybeFrameSource = VideoStickerDirectFrameSource(queue: queue, path: directData.1, width: directData.2, height: directData.3, cachePathPrefix: directData.4)
} else {
maybeFrameSource = AnimatedStickerDirectFrameSource(queue: queue, data: directData.0, width: directData.2, height: directData.3, cachePathPrefix: directData.4, fitzModifier: directData.5)
maybeFrameSource = AnimatedStickerDirectFrameSource(queue: queue, data: directData.0, width: directData.2, height: directData.3, cachePathPrefix: directData.4, useMetalCache: useMetalCache, fitzModifier: directData.5)
}
} else if let (cachedData, cachedDataComplete, _) = cachedData {
if #available(iOS 9.0, *) {
@@ -482,6 +486,7 @@ public final class AnimatedStickerNode: ASDisplayNode {
let queue = self.queue
let timerHolder = self.timer
let frameSourceHolder = self.frameSource
let useMetalCache = self.useMetalCache
self.queue.async { [weak self] in
var maybeFrameSource: AnimatedStickerFrameSource?
let notifyUpdated: (() -> Void)? = nil
@@ -489,7 +494,7 @@ public final class AnimatedStickerNode: ASDisplayNode {
if directData.6 {
maybeFrameSource = VideoStickerDirectFrameSource(queue: queue, path: directData.1, width: directData.2, height: directData.3, cachePathPrefix: directData.4)
} else {
maybeFrameSource = AnimatedStickerDirectFrameSource(queue: queue, data: directData.0, width: directData.2, height: directData.3, cachePathPrefix: directData.4, fitzModifier: directData.5)
maybeFrameSource = AnimatedStickerDirectFrameSource(queue: queue, data: directData.0, width: directData.2, height: directData.3, cachePathPrefix: directData.4, useMetalCache: useMetalCache, fitzModifier: directData.5)
}
} else if let (cachedData, cachedDataComplete, _) = cachedData {
if #available(iOS 9.0, *) {
@@ -526,8 +531,6 @@ public final class AnimatedStickerNode: ASDisplayNode {
guard let strongSelf = self else {
return
}
assert(frame.bytesPerRow != 0)
strongSelf.renderer?.render(queue: strongSelf.queue, width: frame.width, height: frame.height, bytesPerRow: frame.bytesPerRow, data: frame.data, type: frame.type, mulAlpha: frame.multiplyAlpha, completion: {
guard let strongSelf = self else {
@@ -601,6 +604,7 @@ public final class AnimatedStickerNode: ASDisplayNode {
let queue = self.queue
let frameSourceHolder = self.frameSource
let timerHolder = self.timer
let useMetalCache = self.useMetalCache
self.queue.async { [weak self] in
var maybeFrameSource: AnimatedStickerFrameSource? = frameSourceHolder.with { $0 }?.syncWith { $0 }.value
if case .timestamp = position {
@@ -609,7 +613,7 @@ public final class AnimatedStickerNode: ASDisplayNode {
if directData.6 {
maybeFrameSource = VideoStickerDirectFrameSource(queue: queue, path: directData.1, width: directData.2, height: directData.3, cachePathPrefix: directData.4)
} else {
maybeFrameSource = AnimatedStickerDirectFrameSource(queue: queue, data: directData.0, width: directData.2, height: directData.3, cachePathPrefix: directData.4, fitzModifier: directData.5)
maybeFrameSource = AnimatedStickerDirectFrameSource(queue: queue, data: directData.0, width: directData.2, height: directData.3, cachePathPrefix: directData.4, useMetalCache: useMetalCache, fitzModifier: directData.5)
}
if case .end = position {
maybeFrameSource?.skipToEnd()