3

我需要在实时视频上应用过滤器,我正在尝试在 Metal 中执行此操作。

但是在将过滤器编码为目标过滤器后,我遇到了将 MTLTexture 转换为 CVPixelBuffer 的问题。参考(https://github.com/oklyc/MetalCameraSample-master-2

这是我的代码。

if let pixelBuffer = pixelBuffer {
                CVPixelBufferLockBaseAddress(pixelBuffer, CVPixelBufferLockFlags.init(rawValue: 0))             
                let region = MTLRegionMake2D(0, 0, Int(currentDrawable.layer.drawableSize.width), Int(currentDrawable.layer.drawableSize.height))                    
                let bytesPerPixel = 4;
                let bytesPerRow = CGFloat(bytesPerPixel) * currentDrawable.layer.drawableSize.width

                let tempBuffer = CVPixelBufferGetBaseAddress(pixelBuffer)
                destinationTexture.getBytes(tempBuffer!, bytesPerRow: Int(bytesPerRow), from: region1, mipmapLevel: 0)

                let image = self.imageFromCVPixelBuffer(buffer: pixelBuffer)
                CVPixelBufferUnlockBaseAddress(pixelBuffer, CVPixelBufferLockFlags.init(rawValue: 0))

            }

方法 imageFromCVPixelBuffer 看起来像这样。

func imageFromCVPixelBuffer(buffer: CVPixelBuffer) -> UIImage {

    let ciimage = CIImage(cvPixelBuffer: buffer)
    let context = CIContext(options: nil)
    let cgimgage = context.createCGImage(ciimage, from: CGRect(x: 0, y: 0, width: CVPixelBufferGetWidth(buffer), height: CVPixelBufferGetHeight(buffer)))

    let uiimage = UIImage(cgImage: cgimgage!)

    return uiimage
}

这是通过金属渲染图像的屏幕截图

在此处输入图像描述

这是将 MTLTexture 转换为 CVPixelBuffer 的同一图像的屏幕截图。

在此处输入图像描述

需要将 MTLtexture 转换为 CVPixelBuffer 以写入 AVAssetWriter 然后将其保存到库中。

4

1 回答 1

7

不要那样计算bytesPerRow自己。它被传递给 Metal 以让 Metal 知道如何排列行。您希望 Metal 以CVPixelBuffer期望的方式排列它们。因此,您应该使用CVPixelBufferGetBytesPerRow()来确定该值。

于 2017-06-30T09:34:46.567 回答