mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Video Stickers Fixes
This commit is contained in:
parent
bbc082e991
commit
1e2695839a
@ -305,7 +305,7 @@ final class VideoStickerDirectFrameSource: AnimatedStickerFrameSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.source = SoftwareVideoSource(path: path, hintVP9: true)
|
self.source = SoftwareVideoSource(path: path, hintVP9: true)
|
||||||
self.frameRate = self.source.getFramerate()
|
self.frameRate = min(30, self.source.getFramerate())
|
||||||
|
|
||||||
self.frameCount = (self.cache?.frameCount).flatMap { Int($0) } ?? 0
|
self.frameCount = (self.cache?.frameCount).flatMap { Int($0) } ?? 0
|
||||||
}
|
}
|
||||||
|
@ -251,11 +251,7 @@ public final class FFMpegMediaVideoFrameDecoder: MediaTrackFrameDecoder {
|
|||||||
case .YUV:
|
case .YUV:
|
||||||
pixelFormat = kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange
|
pixelFormat = kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange
|
||||||
case .YUVA:
|
case .YUVA:
|
||||||
// if #available(iOS 13.0, *) {
|
|
||||||
// pixelFormat = kCVPixelFormatType_420YpCbCr8VideoRange_8A_TriPlanar
|
|
||||||
// } else {
|
|
||||||
pixelFormat = kCVPixelFormatType_32ARGB
|
pixelFormat = kCVPixelFormatType_32ARGB
|
||||||
// }
|
|
||||||
default:
|
default:
|
||||||
pixelFormat = kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange
|
pixelFormat = kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange
|
||||||
}
|
}
|
||||||
@ -286,6 +282,16 @@ public final class FFMpegMediaVideoFrameDecoder: MediaTrackFrameDecoder {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let status = CVPixelBufferLockBaseAddress(pixelBuffer, [])
|
||||||
|
if status != kCVReturnSuccess {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var base: UnsafeMutableRawPointer
|
||||||
|
if pixelFormat == kCVPixelFormatType_32ARGB {
|
||||||
|
let bytesPerRow = CVPixelBufferGetBytesPerRow(pixelBuffer)
|
||||||
|
decodeYUVAPlanesToRGBA(frame.data[0], Int32(frame.lineSize[0]), frame.data[1], Int32(frame.lineSize[1]), frame.data[2], Int32(frame.lineSize[2]), frame.data[3], CVPixelBufferGetBaseAddress(pixelBuffer)?.assumingMemoryBound(to: UInt8.self), Int32(frame.width), Int32(frame.height), Int32(bytesPerRow))
|
||||||
|
} else {
|
||||||
let srcPlaneSize = Int(frame.lineSize[1]) * Int(frame.height / 2)
|
let srcPlaneSize = Int(frame.lineSize[1]) * Int(frame.height / 2)
|
||||||
let uvPlaneSize = srcPlaneSize * 2
|
let uvPlaneSize = srcPlaneSize * 2
|
||||||
|
|
||||||
@ -302,16 +308,6 @@ public final class FFMpegMediaVideoFrameDecoder: MediaTrackFrameDecoder {
|
|||||||
|
|
||||||
fillDstPlane(uvPlane, frame.data[1]!, frame.data[2]!, srcPlaneSize)
|
fillDstPlane(uvPlane, frame.data[1]!, frame.data[2]!, srcPlaneSize)
|
||||||
|
|
||||||
let status = CVPixelBufferLockBaseAddress(pixelBuffer, [])
|
|
||||||
if status != kCVReturnSuccess {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var base: UnsafeMutableRawPointer
|
|
||||||
if pixelFormat == kCVPixelFormatType_32ARGB {
|
|
||||||
let bytesPerRow = CVPixelBufferGetBytesPerRow(pixelBuffer)
|
|
||||||
decodeYUVAPlanesToRGBA(frame.data[0], uvPlane, frame.data[3], CVPixelBufferGetBaseAddress(pixelBuffer)?.assumingMemoryBound(to: UInt8.self), Int32(frame.width), Int32(frame.height), Int32(bytesPerRow))
|
|
||||||
} else {
|
|
||||||
let bytesPerRowY = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 0)
|
let bytesPerRowY = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 0)
|
||||||
let bytesPerRowUV = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 1)
|
let bytesPerRowUV = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 1)
|
||||||
let bytesPerRowA = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 2)
|
let bytesPerRowA = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 2)
|
||||||
|
@ -301,7 +301,7 @@ public final class CachedVideoStickerRepresentation: CachedMediaResourceRepresen
|
|||||||
public let height: Int32
|
public let height: Int32
|
||||||
|
|
||||||
public var uniqueId: String {
|
public var uniqueId: String {
|
||||||
let version: Int = 0
|
let version: Int = 1
|
||||||
return "video-sticker-\(self.width)x\(self.height)-v\(version)"
|
return "video-sticker-\(self.width)x\(self.height)-v\(version)"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -288,7 +288,7 @@ public func cacheVideoStickerFrames(path: String, size: CGSize, cacheKey: String
|
|||||||
let _ = file.write(data, count: length)
|
let _ = file.write(data, count: length)
|
||||||
}
|
}
|
||||||
|
|
||||||
var fps: Int32 = Int32(source.getFramerate())
|
var fps: Int32 = Int32(min(30, source.getFramerate()))
|
||||||
var frameCount: Int32 = 0
|
var frameCount: Int32 = 0
|
||||||
writeData(&fps, length: 4)
|
writeData(&fps, length: 4)
|
||||||
writeData(&frameCount, length: 4)
|
writeData(&frameCount, length: 4)
|
||||||
|
@ -282,7 +282,7 @@ final class ChatMediaInputStickerGridItemNode: GridItemNode {
|
|||||||
let dimensions = item.stickerItem.file.dimensions ?? PixelDimensions(width: 512, height: 512)
|
let dimensions = item.stickerItem.file.dimensions ?? PixelDimensions(width: 512, height: 512)
|
||||||
let fittedSize = item.large ? CGSize(width: 384.0, height: 384.0) : CGSize(width: 160.0, height: 160.0)
|
let fittedSize = item.large ? CGSize(width: 384.0, height: 384.0) : CGSize(width: 160.0, height: 160.0)
|
||||||
if item.stickerItem.file.isVideoSticker {
|
if item.stickerItem.file.isVideoSticker {
|
||||||
self.imageNode.setSignal(chatMessageSticker(account: item.account, file: item.stickerItem.file, small: !item.large, synchronousLoad: synchronousLoads && isVisible))
|
self.imageNode.setSignal(chatMessageSticker(account: item.account, file: item.stickerItem.file, small: false, synchronousLoad: synchronousLoads && isVisible))
|
||||||
} else {
|
} else {
|
||||||
self.imageNode.setSignal(chatMessageAnimatedSticker(postbox: item.account.postbox, file: item.stickerItem.file, small: false, size: dimensions.cgSize.aspectFitted(fittedSize)))
|
self.imageNode.setSignal(chatMessageAnimatedSticker(postbox: item.account.postbox, file: item.stickerItem.file, small: false, size: dimensions.cgSize.aspectFitted(fittedSize)))
|
||||||
}
|
}
|
||||||
|
@ -214,7 +214,6 @@ final class ChatMediaInputStickerPackItemNode: ListViewItemNode {
|
|||||||
|
|
||||||
if self.currentThumbnailItem != thumbnailItem {
|
if self.currentThumbnailItem != thumbnailItem {
|
||||||
self.currentThumbnailItem = thumbnailItem
|
self.currentThumbnailItem = thumbnailItem
|
||||||
let thumbnailDimensions = PixelDimensions(width: 512, height: 512)
|
|
||||||
if let thumbnailItem = thumbnailItem {
|
if let thumbnailItem = thumbnailItem {
|
||||||
switch thumbnailItem {
|
switch thumbnailItem {
|
||||||
case let .still(representation):
|
case let .still(representation):
|
||||||
@ -236,6 +235,7 @@ final class ChatMediaInputStickerPackItemNode: ListViewItemNode {
|
|||||||
animatedStickerNode = AnimatedStickerNode()
|
animatedStickerNode = AnimatedStickerNode()
|
||||||
animatedStickerNode.started = { [weak self] in
|
animatedStickerNode.started = { [weak self] in
|
||||||
self?.imageNode.isHidden = true
|
self?.imageNode.isHidden = true
|
||||||
|
self?.removePlaceholder(animated: false)
|
||||||
}
|
}
|
||||||
self.animatedStickerNode = animatedStickerNode
|
self.animatedStickerNode = animatedStickerNode
|
||||||
if let placeholderNode = self.placeholderNode {
|
if let placeholderNode = self.placeholderNode {
|
||||||
@ -252,12 +252,22 @@ final class ChatMediaInputStickerPackItemNode: ListViewItemNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let placeholderNode = self.placeholderNode {
|
self.updateIsHighlighted()
|
||||||
let imageSize = boundingImageSize
|
|
||||||
placeholderNode.update(backgroundColor: nil, foregroundColor: theme.chat.inputMediaPanel.stickersSectionTextColor.blitOver(theme.chat.inputPanel.panelBackgroundColor, alpha: 0.4), shimmeringColor: theme.chat.inputMediaPanel.panelHighlightedIconBackgroundColor.withMultipliedAlpha(0.2), data: info.immediateThumbnailData, size: imageSize, imageSize: thumbnailDimensions.cgSize)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.updateIsHighlighted()
|
if let placeholderNode = self.placeholderNode {
|
||||||
|
var imageSize = PixelDimensions(width: 512, height: 512)
|
||||||
|
var immediateThumbnailData: Data?
|
||||||
|
if let data = info.immediateThumbnailData {
|
||||||
|
if info.flags.contains(.isVideo) {
|
||||||
|
imageSize = PixelDimensions(width: 100, height: 100)
|
||||||
|
}
|
||||||
|
immediateThumbnailData = data
|
||||||
|
} else if let data = item?.file.immediateThumbnailData {
|
||||||
|
immediateThumbnailData = data
|
||||||
|
}
|
||||||
|
|
||||||
|
placeholderNode.update(backgroundColor: nil, foregroundColor: theme.chat.inputMediaPanel.stickersSectionTextColor.blitOver(theme.chat.inputPanel.panelBackgroundColor, alpha: 0.4), shimmeringColor: theme.chat.inputMediaPanel.panelHighlightedIconBackgroundColor.withMultipliedAlpha(0.2), data: immediateThumbnailData, size: boundingImageSize, imageSize: imageSize.cgSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.containerNode.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: expandedBoundingSize)
|
self.containerNode.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: expandedBoundingSize)
|
||||||
|
@ -4,4 +4,4 @@ void encodeRGBAToYUVA(uint8_t *yuva, uint8_t const *argb, int width, int height,
|
|||||||
void resizeAndEncodeRGBAToYUVA(uint8_t *yuva, uint8_t const *argb, int width, int height, int bytesPerRow, int originalWidth, int originalHeight, int originalBytesPerRow);
|
void resizeAndEncodeRGBAToYUVA(uint8_t *yuva, uint8_t const *argb, int width, int height, int bytesPerRow, int originalWidth, int originalHeight, int originalBytesPerRow);
|
||||||
|
|
||||||
void decodeYUVAToRGBA(uint8_t const *yuva, uint8_t *argb, int width, int height, int bytesPerRow);
|
void decodeYUVAToRGBA(uint8_t const *yuva, uint8_t *argb, int width, int height, int bytesPerRow);
|
||||||
void decodeYUVAPlanesToRGBA(uint8_t const *yPlane, uint8_t const *uvPlane, uint8_t const *alphaPlane, uint8_t *argb, int width, int height, int bytesPerRow);
|
void decodeYUVAPlanesToRGBA(uint8_t const *srcYpData, int srcYpBytesPerRow, uint8_t const *srcCbData, int srcCbBytesPerRow, uint8_t const *srcCrData, int srcCrBytesPerRow, uint8_t const *alphaData, uint8_t *argb, int width, int height, int bytesPerRow);
|
||||||
|
@ -169,7 +169,7 @@ void decodeYUVAToRGBA(uint8_t const *yuva, uint8_t *argb, int width, int height,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void decodeYUVAPlanesToRGBA(uint8_t const *yPlane, uint8_t const *uvPlane, uint8_t const *alphaPlane, uint8_t *argb, int width, int height, int bytesPerRow) {
|
void decodeYUVAPlanesToRGBA(uint8_t const *srcYpData, int srcYpBytesPerRow, uint8_t const *srcCbData, int srcCbBytesPerRow, uint8_t const *srcCrData, int srcCrBytesPerRow, uint8_t const *alphaData, uint8_t *argb, int width, int height, int bytesPerRow) {
|
||||||
static vImage_YpCbCrToARGB info;
|
static vImage_YpCbCrToARGB info;
|
||||||
static dispatch_once_t onceToken;
|
static dispatch_once_t onceToken;
|
||||||
dispatch_once(&onceToken, ^{
|
dispatch_once(&onceToken, ^{
|
||||||
@ -180,31 +180,36 @@ void decodeYUVAPlanesToRGBA(uint8_t const *yPlane, uint8_t const *uvPlane, uint8
|
|||||||
vImage_Error error = kvImageNoError;
|
vImage_Error error = kvImageNoError;
|
||||||
|
|
||||||
vImage_Buffer srcYp;
|
vImage_Buffer srcYp;
|
||||||
srcYp.data = (void *)(yPlane + 0);
|
srcYp.data = (void *)(srcYpData);
|
||||||
srcYp.width = width;
|
srcYp.width = width;
|
||||||
srcYp.height = height;
|
srcYp.height = height;
|
||||||
srcYp.rowBytes = width * 1;
|
srcYp.rowBytes = srcYpBytesPerRow;
|
||||||
|
|
||||||
vImage_Buffer srcCbCr;
|
vImage_Buffer srcCb;
|
||||||
srcCbCr.data = (void *)(uvPlane);
|
srcCb.data = (void *)(srcCbData);
|
||||||
srcCbCr.width = width;
|
srcCb.width = width / 2;
|
||||||
srcCbCr.height = height;
|
srcCb.height = height;
|
||||||
srcCbCr.rowBytes = width * 1;
|
srcCb.rowBytes = srcCbBytesPerRow;
|
||||||
|
|
||||||
|
vImage_Buffer srcCr;
|
||||||
|
srcCr.data = (void *)(srcCrData);
|
||||||
|
srcCr.width = width / 2;
|
||||||
|
srcCr.height = height;
|
||||||
|
srcCr.rowBytes = srcCrBytesPerRow;
|
||||||
|
|
||||||
vImage_Buffer dest;
|
vImage_Buffer dest;
|
||||||
dest.data = (void *)argb;
|
dest.data = (void *)argb;
|
||||||
dest.width = width;
|
dest.width = width;
|
||||||
dest.height = height;
|
dest.height = height;
|
||||||
dest.rowBytes = bytesPerRow;
|
dest.rowBytes = bytesPerRow;
|
||||||
|
error = vImageConvert_420Yp8_Cb8_Cr8ToARGB8888(&srcYp, &srcCb, &srcCr, &dest, &info, NULL, 0xff, kvImageDoNotTile);
|
||||||
|
|
||||||
error = vImageConvert_420Yp8_CbCr8ToARGB8888(&srcYp, &srcCbCr, &dest, &info, NULL, 0xff, kvImageDoNotTile);
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
for (int y = 0; y < height; y += 1) {
|
for (int y = 0; y < height; y += 1) {
|
||||||
uint8_t *argbRow = argb + y * bytesPerRow;
|
uint8_t *argbRow = argb + y * bytesPerRow;
|
||||||
|
int alphaRow = y * srcYpBytesPerRow;
|
||||||
|
|
||||||
for (int x = 0; x < width; x += 1) {
|
for (int x = 0; x < width; x += 1) {
|
||||||
argbRow[x * 4] = alphaPlane[i];
|
argbRow[x * 4] = alphaData[alphaRow + x];
|
||||||
i += 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user