Thanks for being a part of WWDC25!

How did we do? We’d love to know your thoughts on this year’s conference. Take the survey here

CVPixelBufferCreate EXC_BAD_ACCESS

I am doing something similar to this post

Within an AVCaptureDataOutputSynchronizerDelegate method, I create a pixelBuffer using CVPixelBufferCreate with the following attributes: kCVPixelBufferIOSurfacePropertiesKey as String: true, kCVPixelBufferIOSurfaceOpenGLESTextureCompatibilityKey as String: true

When I copy the data from the vImagePixelBuffer "rotatedImageBuffer", I get the following error:

Thread 10: EXC_BAD_ACCESS (code=1, address=0x14caa8000)

I get the same error with memcpy and data.copyBytes (not running them at the same time obviously).

If I use CVPixelBufferCreateWithBytes, I do not get this error. However, CVPixelBufferCreateWithBytes does not let you include attributes (see linked post above).

I am using vImage because I need the original CVPixelBuffer from the camera output and a rotated version with a different color scheme.

        // Copy to pixel buffer
        let attributes: NSDictionary = [
            true : kCVPixelBufferIOSurfacePropertiesKey,
            true : kCVPixelBufferIOSurfaceOpenGLESTextureCompatibilityKey,
        ]
        
        var colorBuffer: CVPixelBuffer?

        let status = CVPixelBufferCreate(kCFAllocatorDefault, Int(rotatedImageBuffer.width), Int(rotatedImageBuffer.height), kCVPixelFormatType_32BGRA, attributes, &colorBuffer)

        //let status = CVPixelBufferCreateWithBytes(kCFAllocatorDefault, Int(rotatedImageBuffer.width), Int(rotatedImageBuffer.height), kCVPixelFormatType_32BGRA, rotatedImageBuffer.data, rotatedImageBuffer.rowBytes, nil, nil, attributes as CFDictionary, &colorBuffer) // does NOT produce error, but also does not have attributes
        
        guard status == kCVReturnSuccess, let colorBuffer = colorBuffer else {
            print("Failed to create buffer")
            return
        }
        
        let lockFlags = CVPixelBufferLockFlags(rawValue: 0)
        
        guard kCVReturnSuccess == CVPixelBufferLockBaseAddress(colorBuffer, lockFlags) else {
            print("Failed to lock base address")
            return
        }
        
        let colorBufferMemory = CVPixelBufferGetBaseAddress(colorBuffer)!

        let data = Data(bytes: rotatedImageBuffer.data, count: rotatedImageBuffer.rowBytes * Int(rotatedImageBuffer.height))
        data.copyBytes(to: colorBufferMemory.assumingMemoryBound(to: UInt8.self), count: data.count) // Fails here

        //memcpy(colorBufferMemory, rotatedImageBuffer.data, rotatedImageBuffer.rowBytes * Int(rotatedImageBuffer.height)) // Also produces the same error

        CVPixelBufferUnlockBaseAddress(colorBuffer, lockFlags)
Accepted Answer

Found an answer - CVPixelBufferCreate isn't that efficient so it runs on a few frames and then crashes.

You can include attributes using a CVPixelBufferPool, which apparently is designed for streaming frames and managing the buffers in memory

Also realized the format for the attributes dictionary was wrong

    private var colorPixelBufferPool: CVPixelBufferPool!
    private var pixelBufferPool_isPrepared = false

...

// within delegate

        if !pixelBufferPool_isPrepared {
            
            var videoDescription: CMFormatDescription
            do {
                videoDescription = try CMVideoFormatDescription(imageBuffer: videoBuffer)
            } //videoBuffer is the original CVPixelBuffer
            catch {
                print("Failed video description")
                return
            }
            
            let inputDimensions = CMVideoFormatDescriptionGetDimensions(videoDescription)
            let outputPixelBufferAttributes: [String: Any] = [
                kCVPixelBufferPixelFormatTypeKey as String: kCVPixelFormatType_32BGRA,
                kCVPixelBufferWidthKey as String: Int(inputDimensions.height), // rotated 90 degrees
                kCVPixelBufferHeightKey as String: Int(inputDimensions.width), // rotated 90 degrees
                kCVPixelBufferIOSurfaceOpenGLESTextureCompatibilityKey as String: true,
                kCVPixelBufferIOSurfacePropertiesKey as String: [:]
            ]
            
            let poolAttributes = [kCVPixelBufferPoolMinimumBufferCountKey as String: 2]
            var cvPixelBufferPool: CVPixelBufferPool?
            // Create a pixel buffer pool with the same pixel attributes as the input format description
            CVPixelBufferPoolCreate(kCFAllocatorDefault, poolAttributes as NSDictionary?, outputPixelBufferAttributes as NSDictionary?, &cvPixelBufferPool)
            guard let pixelBufferPool = cvPixelBufferPool else {
                assertionFailure("Allocation failure: Could not create pixel buffer pool")
                return
            }
            
            colorPixelBufferPool = pixelBufferPool
            pixelBufferPool_isPrepared = true
        }

...

        // let status = CVPixelBufferCreate(kCFAllocatorDefault, Int(rotatedBuffer.width), Int(rotatedBuffer.height), kCVPixelFormatType_32BGRA, attributes, &colorBuffer) // throws error eventually, not efficient
        
        let status = CVPixelBufferPoolCreatePixelBuffer(kCFAllocatorDefault, colorPixelBufferPool!, &colorBuffer) // works!

CVPixelBufferCreate EXC_BAD_ACCESS
 
 
Q