mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-22 14:20:20 +00:00
Support i420
This commit is contained in:
@@ -815,14 +815,53 @@ private final class AdaptedCallVideoSource: VideoSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final class PixelBufferPool {
|
||||||
|
let width: Int
|
||||||
|
let height: Int
|
||||||
|
let pool: CVPixelBufferPool
|
||||||
|
|
||||||
|
init?(width: Int, height: Int) {
|
||||||
|
self.width = width
|
||||||
|
self.height = height
|
||||||
|
|
||||||
|
let bufferOptions: [String: Any] = [
|
||||||
|
kCVPixelBufferPoolMinimumBufferCountKey as String: 4 as NSNumber
|
||||||
|
]
|
||||||
|
let pixelBufferOptions: [String: Any] = [
|
||||||
|
kCVPixelBufferPixelFormatTypeKey as String: kCVPixelFormatType_420YpCbCr8BiPlanarFullRange as NSNumber,
|
||||||
|
kCVPixelBufferWidthKey as String: width as NSNumber,
|
||||||
|
kCVPixelBufferHeightKey as String: height as NSNumber,
|
||||||
|
kCVPixelBufferIOSurfacePropertiesKey as String: [:] as NSDictionary
|
||||||
|
]
|
||||||
|
|
||||||
|
var pool: CVPixelBufferPool?
|
||||||
|
CVPixelBufferPoolCreate(nil, bufferOptions as CFDictionary, pixelBufferOptions as CFDictionary, &pool)
|
||||||
|
guard let pool else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
self.pool = pool
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final class PixelBufferPoolState {
|
||||||
|
var pool: PixelBufferPool?
|
||||||
|
}
|
||||||
|
|
||||||
private static let queue = Queue(name: "AdaptedCallVideoSource")
|
private static let queue = Queue(name: "AdaptedCallVideoSource")
|
||||||
private var onUpdatedListeners = Bag<() -> Void>()
|
private var onUpdatedListeners = Bag<() -> Void>()
|
||||||
private(set) var currentOutput: Output?
|
private(set) var currentOutput: Output?
|
||||||
|
|
||||||
private var textureCache: CVMetalTextureCache?
|
private var textureCache: CVMetalTextureCache?
|
||||||
|
private var pixelBufferPoolState: QueueLocalObject<PixelBufferPoolState>
|
||||||
|
|
||||||
private var videoFrameDisposable: Disposable?
|
private var videoFrameDisposable: Disposable?
|
||||||
|
|
||||||
init(videoStreamSignal: Signal<OngoingGroupCallContext.VideoFrameData, NoError>) {
|
init(videoStreamSignal: Signal<OngoingGroupCallContext.VideoFrameData, NoError>) {
|
||||||
|
let pixelBufferPoolState = QueueLocalObject(queue: AdaptedCallVideoSource.queue, generate: {
|
||||||
|
return PixelBufferPoolState()
|
||||||
|
})
|
||||||
|
self.pixelBufferPoolState = pixelBufferPoolState
|
||||||
|
|
||||||
CVMetalTextureCacheCreate(nil, nil, MetalEngine.shared.device, nil, &self.textureCache)
|
CVMetalTextureCacheCreate(nil, nil, MetalEngine.shared.device, nil, &self.textureCache)
|
||||||
|
|
||||||
self.videoFrameDisposable = (videoStreamSignal
|
self.videoFrameDisposable = (videoStreamSignal
|
||||||
@@ -917,47 +956,62 @@ private final class AdaptedCallVideoSource: VideoSource {
|
|||||||
sourceId: sourceId
|
sourceId: sourceId
|
||||||
)
|
)
|
||||||
case let .i420(i420Buffer):
|
case let .i420(i420Buffer):
|
||||||
|
guard let pixelBufferPoolState = pixelBufferPoolState.unsafeGet() else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
let width = i420Buffer.width
|
let width = i420Buffer.width
|
||||||
let height = i420Buffer.height
|
let height = i420Buffer.height
|
||||||
|
|
||||||
/*output = Output(
|
let pool: PixelBufferPool?
|
||||||
resolution: CGSize(width: CGFloat(width), height: CGFloat(height)),
|
if let current = pixelBufferPoolState.pool, current.width == width, current.height == height {
|
||||||
textureLayout: .triPlanar(Output.TriPlanarTextureLayout(
|
pool = current
|
||||||
y: yTexture,
|
} else {
|
||||||
uv: uvTexture
|
pool = PixelBufferPool(width: width, height: height)
|
||||||
)),
|
pixelBufferPoolState.pool = pool
|
||||||
dataBuffer: Output.NativeDataBuffer(pixelBuffer: nativeBuffer.pixelBuffer),
|
}
|
||||||
rotationAngle: rotationAngle,
|
guard let pool else {
|
||||||
followsDeviceOrientation: followsDeviceOrientation,
|
|
||||||
mirrorDirection: mirrorDirection,
|
|
||||||
sourceId: sourceId
|
|
||||||
)*/
|
|
||||||
|
|
||||||
let _ = width
|
|
||||||
let _ = height
|
|
||||||
return
|
return
|
||||||
|
}
|
||||||
|
|
||||||
/*var cvMetalTextureY: CVMetalTexture?
|
let auxAttributes: [String: Any] = [kCVPixelBufferPoolAllocationThresholdKey as String: 5 as NSNumber]
|
||||||
var status = CVMetalTextureCacheCreateTextureFromImage(nil, textureCache, nativeBuffer.pixelBuffer, nil, .r8Unorm, width, height, 0, &cvMetalTextureY)
|
var pixelBuffer: CVPixelBuffer?
|
||||||
|
let result = CVPixelBufferPoolCreatePixelBufferWithAuxAttributes(kCFAllocatorDefault, pool.pool, auxAttributes as CFDictionary, &pixelBuffer)
|
||||||
|
if result == kCVReturnWouldExceedAllocationThreshold {
|
||||||
|
print("kCVReturnWouldExceedAllocationThreshold, dropping frame")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
guard let pixelBuffer else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !copyI420BufferToNV12Buffer(buffer: i420Buffer, pixelBuffer: pixelBuffer) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var cvMetalTextureY: CVMetalTexture?
|
||||||
|
var status = CVMetalTextureCacheCreateTextureFromImage(nil, textureCache, pixelBuffer, nil, .r8Unorm, width, height, 0, &cvMetalTextureY)
|
||||||
guard status == kCVReturnSuccess, let yTexture = CVMetalTextureGetTexture(cvMetalTextureY!) else {
|
guard status == kCVReturnSuccess, let yTexture = CVMetalTextureGetTexture(cvMetalTextureY!) else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var cvMetalTextureUV: CVMetalTexture?
|
var cvMetalTextureUV: CVMetalTexture?
|
||||||
status = CVMetalTextureCacheCreateTextureFromImage(nil, textureCache, nativeBuffer.pixelBuffer, nil, .rg8Unorm, width / 2, height / 2, 1, &cvMetalTextureUV)
|
status = CVMetalTextureCacheCreateTextureFromImage(nil, textureCache, pixelBuffer, nil, .rg8Unorm, width / 2, height / 2, 1, &cvMetalTextureUV)
|
||||||
guard status == kCVReturnSuccess, let uvTexture = CVMetalTextureGetTexture(cvMetalTextureUV!) else {
|
guard status == kCVReturnSuccess, let uvTexture = CVMetalTextureGetTexture(cvMetalTextureUV!) else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
output = Output(
|
output = Output(
|
||||||
resolution: CGSize(width: CGFloat(yTexture.width), height: CGFloat(yTexture.height)),
|
resolution: CGSize(width: CGFloat(yTexture.width), height: CGFloat(yTexture.height)),
|
||||||
|
textureLayout: .biPlanar(Output.BiPlanarTextureLayout(
|
||||||
y: yTexture,
|
y: yTexture,
|
||||||
uv: uvTexture,
|
uv: uvTexture
|
||||||
dataBuffer: Output.NativeDataBuffer(pixelBuffer: nativeBuffer.pixelBuffer),
|
)),
|
||||||
|
dataBuffer: Output.NativeDataBuffer(pixelBuffer: pixelBuffer),
|
||||||
rotationAngle: rotationAngle,
|
rotationAngle: rotationAngle,
|
||||||
followsDeviceOrientation: followsDeviceOrientation,
|
followsDeviceOrientation: followsDeviceOrientation,
|
||||||
mirrorDirection: mirrorDirection,
|
mirrorDirection: mirrorDirection,
|
||||||
sourceId: sourceId
|
sourceId: sourceId
|
||||||
)*/
|
)
|
||||||
default:
|
default:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user