使用 GPU 清除 CVPixelBufferRef

wfb*_*ale 5 avfoundation core-video core-media ios

我正在使用 编写一些视频处理代码AVComposition。仅提供必要的背景详细信息,我收到CVPixelBuffer来自我无法控制的苹果 API 的信息。这个 CVPixel 缓冲区包含之前渲染的视频帧,因为它们显然是由我无法控制的 Apple API 回收的。所以我的目标是将 CVPixelBufferRef 中的所有像素设置为 [0, 0, 0, 0] (在 RGBA 颜色空间中)。我可以通过以下函数在 CPU 上执行此操作:

- (void)processPixelBuffer: (CVImageBufferRef)pixelBuffer
{
    CVPixelBufferLockBaseAddress( pixelBuffer, 0 );

    int bufferWidth = CVPixelBufferGetWidth(pixelBuffer);
    int bufferHeight = CVPixelBufferGetHeight(pixelBuffer);
    unsigned char *pixel = (unsigned char *)CVPixelBufferGetBaseAddress(pixelBuffer);

    for( int row = 0; row < bufferHeight; row++ ) {
        for( int column = 0; column < bufferWidth; column++ ) {
            pixel[0] = 0;
            pixel[1] = 0;
            pixel[2] = 0;
            pixel[3] = 0;
            pixel += 4;
        }
    }
    CVPixelBufferUnlockBaseAddress( pixelBuffer, 0 );
}
Run Code Online (Sandbox Code Playgroud)

有什么方法可以使用 GPU 完成同样的事情吗?另外,是否可以通过 CoreImage 来做到这一点?因为我不了解 openGL 并且它的设置似乎相当复杂。

Ian*_*hek 6

您可以使用AcceleratevImageBufferFill来完成此操作(但不是 GPU)。这在 Swift 4 中用黑色填充 BGRA:

let width: Int = 3
let height: Int = 3

var pixelBuffer: CVPixelBuffer?
var imageBuffer: vImage_Buffer
var date: Date
let iterations: Int = 10000

let pixelBufferAttributes: [CFString: Any] = [kCVPixelBufferCGImageCompatibilityKey: true, kCVPixelBufferCGBitmapContextCompatibilityKey: true]
if CVPixelBufferCreate(kCFAllocatorDefault, width, height, kCVPixelFormatType_32BGRA, pixelBufferAttributes as CFDictionary, &pixelBuffer) != kCVReturnSuccess || pixelBuffer == nil { fatalError("Cannot create pixel buffer.") }
if CVPixelBufferLockBaseAddress(pixelBuffer!, []) != kCVReturnSuccess { fatalError("Cannot lock pixel buffer base address.") }
imageBuffer = vImage_Buffer(data: CVPixelBufferGetBaseAddress(pixelBuffer!), height: UInt(height), width: UInt(width), rowBytes: CVPixelBufferGetBytesPerRow(pixelBuffer!))
vImageBufferFill_ARGB8888(&imageBuffer, [0, 0, 0, 0xFF], UInt32(kvImageNoFlags))
if CVPixelBufferUnlockBaseAddress(pixelBuffer!, []) != kCVReturnSuccess { fatalError("Cannot unlock pixel buffer base address.") }
Run Code Online (Sandbox Code Playgroud)

在 Playground 中,测试普通 memset 以在 10000 次迭代中用零填充小缓冲区要快得多。在使用真实数据的发布版本中,结果可能不会有太大差异。

  • 加速: 1629.0
  • 内存集: 314.0

在此输入图像描述


use*_*321 2

这个页面看来,您可以CVImageBufferRef通过以下方式直接访问 OpenGL 纹理:

glBindTexture( CVOpenGLTextureGetTarget( image ), CVOpenGLTextureGetName( image ) );
Run Code Online (Sandbox Code Playgroud)

一旦将其作为纹理,您就可以将其用作 FBO 的绘制缓冲区并简单地调用glClear(GL_COLOR_BUFFER_BIT);它。