从SCNView录制视频的最快方式

时间:2018-05-07 17:01:08

标签: ios scenekit metal avassetwriter cvpixelbuffer

我的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,因为它太慢了。

P.S。我以前的浏览器是在OpenGL ES(GLKView)上使用this technique成功完成的(使用.screenshot方法开销1ms而不是30ms)

0 个答案:

没有答案