我有 SCNView,屏幕中间有一些对象,用户可以旋转它,缩放等。
我想在视频中记录所有这些动作并实时添加一些声音。另外,我只想记录 SCNView 的中间部分(例如 SCNView 框架是 375x812,但我只想要中间 375x375,没有顶部和底部边框)。我还想在视频捕获的同时在屏幕上显示它。
我当前的变体是:
func renderer(_ renderer: SCNSceneRenderer, didRenderScene scene: SCNScene, atTime time: TimeInterval) {
DispatchQueue.main.async {
if let metalLayer = self.sceneView.layer as? CAMetalLayer, let texture = metalLayer.currentSceneDrawable?.texture, let pixelBufferPool = self.pixelBufferPool {
//1
var maybePixelBuffer: CVPixelBuffer? = nil
let status = CVPixelBufferPoolCreatePixelBuffer(nil, pixelBufferPool, &maybePixelBuffer)
guard let pixelBuffer = maybePixelBuffer else { return }
CVPixelBufferLockBaseAddress(pixelBuffer, [])
let bytesPerRow = CVPixelBufferGetBytesPerRow(pixelBuffer)
let region = MTLRegionMake2D(Int(self.fieldOfView.origin.x * UIScreen.main.scale),
Int(self.fieldOfView.origin.y * UIScreen.main.scale),
Int(self.fieldOfView.width * UIScreen.main.scale),
Int(self.fieldOfView.height * UIScreen.main.scale))
let pixelBufferBytes = CVPixelBufferGetBaseAddress(pixelBuffer)!
texture.getBytes(pixelBufferBytes, bytesPerRow: bytesPerRow, from: region, mipmapLevel: 0)
let uiImage = self.image(from: pixelBuffer)
CVPixelBufferUnlockBaseAddress(pixelBuffer, [])
//2
if #available(iOS 11.0, *) {
var pixelBuffer: Unmanaged<CVPixelBuffer>? = nil
CVPixelBufferCreateWithIOSurface(kCFAllocatorDefault, texture.iosurface!, nil, UnsafeMutablePointer<Unmanaged<CVPixelBuffer>?>(&pixelBuffer))
let imageBuffer = pixelBuffer!.takeUnretainedValue()
} else {
// Fallback on earlier versions
}
//3
var pb: CVPixelBuffer? = nil
let result = CVPixelBufferCreate(kCFAllocatorDefault, texture.width, texture.height, kCVPixelFormatType_32BGRA, nil, &pb)
print(result)
let ciImage = CIImage(mtlTexture: texture, options: nil)
let context = CIContext()
context.render(ciImage!, to: pb!)
}
}
}
获得的CVPixelBuffer将被添加到AVAssetWriter中。
但是所有这些方法都有一些缺陷。
1)MTLTexture具有colorPixelFormat == 555(bgra10_XR_sRGB,如果我没记错的话),我不知道如何将其转换为BGR(将其附加到aseetWriter),也不知道如何更改该colorPixelFormat,也不知道如何将bgra10_XR_sRGB添加到aseetWriter .
2)iOS10版本如何实现?
2,3)裁剪图像最快的方法是什么?使用这种方法,我只能抓取完整图像,而不是裁剪后的图像。而且我不想将其转换为 UIImage,因为它太慢了。
附注我之前的查看器是在 OpenGL ES(GLKView) 上,我使用此技术成功完成了它(开销 1 毫秒,而不是使用 .screenshot 方法的 30 毫秒)
使用 CIContext 将 bgra10_xr_srgb 转换为 BGRA8
if let ciImage = CIImage(mtlTexture: texture) {
self?.context?.render(ciImage, toBitmap: storge, rowBytes: bytesPerRow, bounds: CGRectMake(0, 0, CGFloat(tW), CGFloat(tH)), format: .BGRA8, colorSpace: CGColorSpaceCreateDeviceRGB())
}