【问题标题】:Duplicate / Copy CVPixelBufferRef with CVPixelBufferCreate使用 CVPixelBufferCreate 复制/复制 CVPixelBufferRef
【发布时间】:2016-09-21 23:00:45
【问题描述】:

我需要创建CVPixelBufferRef 的副本,以便能够使用副本中的值以逐位方式操作原始像素缓冲区。我似乎无法通过CVPixelBufferCreateCVPixelBufferCreateWithBytes 实现这一目标。

根据this question,也可以使用 memcpy() 来完成。但是,没有说明如何实现这一点,以及无论如何都需要调用哪些 Core Video 库。

【问题讨论】:

  • 你不能把数据 memcpy 放在别的地方吗?
  • 这实际上正是我想到的“更简单的方法”,但是我没有找到任何关于如何做到这一点的示例,而且我对 C 编程非常陌生。我可以定义一个新的像素缓冲区CVPixelBufferRef newPixelBuffer = NULL 然后使用 memcpy() 吗?
  • 不,您只想复制像素数据,而不是复制 CVPixelBufferRef 具有的任何内部结构。请参阅 CVPixelBufferGetBaseAddress 的文档。
  • 我知道如何获取基地址,但我仍然不明白如何使用memcpy() 或者,确切地说,我不知道如何定义目标地址
  • 各位,感谢您将我的问题标记为重复。但是,上一个问题没有为我提供任何有关如何解决我的问题的有用信息。 @jtbandes 如果您知道如何使用memcpy() 解决问题,如果您能提供另一个问题的答案,我将不胜感激。否则我们基本上只是在浪费彼此的时间。

标签: ios objective-c cvpixelbuffer


【解决方案1】:

这似乎有效:

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {

    CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);

    // Get pixel buffer info
    const int kBytesPerPixel = 4;
    CVPixelBufferLockBaseAddress(pixelBuffer, 0);
    int bufferWidth = (int)CVPixelBufferGetWidth(pixelBuffer);
    int bufferHeight = (int)CVPixelBufferGetHeight(pixelBuffer);
    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(pixelBuffer); 
    uint8_t *baseAddress = CVPixelBufferGetBaseAddress(pixelBuffer);

    // Copy the pixel buffer
    CVPixelBufferRef pixelBufferCopy = NULL;
    CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, bufferWidth, bufferHeight, kCVPixelFormatType_32BGRA, NULL, &pixelBufferCopy);
    CVPixelBufferLockBaseAddress(pixelBufferCopy, 0);
    uint8_t *copyBaseAddress = CVPixelBufferGetBaseAddress(pixelBufferCopy);
    memcpy(copyBaseAddress, baseAddress, bufferHeight * bytesPerRow);

    // Do what needs to be done with the 2 pixel buffers

}

【讨论】:

  • kBytesPerPixel 未使用且不必要
【解决方案2】:

ooOlly 的代码在所有情况下都不适用于 YUV 像素缓冲区(底部的绿线和 memcpy 中的 sig 陷阱),因此这对于来自相机的 YUV 像素缓冲区非常有效:

var copyOut: CVPixelBuffer?
let status = CVPixelBufferCreate(kCFAllocatorDefault, CVPixelBufferGetWidth(pixelBuffer), CVPixelBufferGetHeight(pixelBuffer), CVPixelBufferGetPixelFormatType(pixelBuffer), nil, &copyOut)
let copy = copyOut!

CVPixelBufferLockBaseAddress(copy, [])
CVPixelBufferLockBaseAddress(pixelBuffer, [])

let ydestPlane = CVPixelBufferGetBaseAddressOfPlane(copy, 0)
let ysrcPlane = CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 0)
memcpy(ydestPlane, ysrcPlane, CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 0) * CVPixelBufferGetHeightOfPlane(pixelBuffer, 0))

let uvdestPlane = CVPixelBufferGetBaseAddressOfPlane(copy, 1)
let uvsrcPlane = CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 1)
memcpy(uvdestPlane, uvsrcPlane, CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 1) * CVPixelBufferGetHeightOfPlane(pixelBuffer, 1))

CVPixelBufferUnlockBaseAddress(copy, [])
CVPixelBufferUnlockBaseAddress(pixelBuffer, [])

当然,强烈建议比强制展开更好的错误处理。

【讨论】:

  • 那么现在如何缩放它,例如0.5?
【解决方案3】:

Maxi Mus 的代码仅适用于 RGB/BGR 缓冲区。 所以对于 YUV 缓冲区下面的代码应该可以工作。

// Copy the pixel buffer
    CVPixelBufferRef pixelBufferCopy = NULL;
    CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, bufferWidth, bufferHeight, pixelFormat, NULL, &pixelBufferCopy);
    CVPixelBufferLockBaseAddress(pixelBufferCopy, 0);
    //BGR
//    uint8_t *copyBaseAddress = CVPixelBufferGetBaseAddress(pixelBufferCopy);
//    memcpy(copyBaseAddress, baseAddress, bufferHeight * bytesPerRow);
    uint8_t *yDestPlane = CVPixelBufferGetBaseAddressOfPlane(pixelBufferCopy, 0);
    //YUV
    uint8_t *yPlane = CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 0);
    memcpy(yDestPlane, yPlane, bufferWidth * bufferHeight);
    uint8_t *uvDestPlane = CVPixelBufferGetBaseAddressOfPlane(pixelBufferCopy, 1);
    uint8_t *uvPlane = CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 1);
    memcpy(uvDestPlane, uvPlane, bufferWidth * bufferHeight/2);
    CVPixelBufferUnlockBaseAddress(pixelBufferCopy, 0);

【讨论】:

    猜你喜欢
    • 2013-05-18
    • 2019-01-24
    • 2010-09-06
    • 1970-01-01
    • 2013-10-19
    • 2013-05-27
    • 1970-01-01
    • 2011-10-05
    • 1970-01-01
    相关资源
    最近更新 更多