问题
I need to create a copy of a CVPixelBufferRef
in order to be able to manipulate the original pixel buffer in a bit-wise fashion using the values from the copy. I cannot seem to achieve this with CVPixelBufferCreate
, or with CVPixelBufferCreateWithBytes
.
According to this question, it could possibly also be done with memcpy(). However, there is no explanation on how this would be achieved, and which Core Video library calls would be needed regardless.
回答1:
This seems to work:
- (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
}
回答2:
ooOlly's code was not working for me with YUV pixel buffers in all cases (green line at bottom and sig trap in memcpy), so this works in swift for YUV pixel buffers from the camera:
var copyOut: CVPixelBuffer?
let status = CVPixelBufferCreate(kCFAllocatorDefault, CVPixelBufferGetWidth(pixelBuffer), CVPixelBufferGetHeight(pixelBuffer), CVPixelBufferGetPixelFormatType(pixelBuffer), nil, ©Out)
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, [])
better error handling than the force unwrap is strongly suggested of course.
回答3:
Maxi Mus's code only due with RGB/BGR buffer. so for YUV buffer below code should work.
// 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);
来源:https://stackoverflow.com/questions/37418517/duplicate-copy-cvpixelbufferref-with-cvpixelbuffercreate