How to deep copy CMSampleBuffer

Hi all,

Does anyone know how I can make a deep copy of CMSampleBuffer?

I currently have the following extension on CVPixelBuffer:

func copy() -> CVPixelBuffer {
    precondition(CFGetTypeID(self) == CVPixelBufferGetTypeID(), "copy() cannot be called on a non-CVPixelBuffer")
    
    var _copy : CVPixelBuffer?
    CVPixelBufferCreate(
      nil,
      CVPixelBufferGetWidth(self),
      CVPixelBufferGetHeight(self),
      CVPixelBufferGetPixelFormatType(self),
      CVBufferGetAttachments(self, CVAttachmentMode.shouldPropagate),
      &_copy
    )
    
    guard let copy = _copy else { fatalError() }
    
    CVPixelBufferLockBaseAddress(self, .readOnly)
    CVPixelBufferLockBaseAddress(copy, CVPixelBufferLockFlags(rawValue: 0))
    
    for plane in 0..<CVPixelBufferGetPlaneCount(self) {
      let dest = CVPixelBufferGetBaseAddressOfPlane(copy, plane)
      let source = CVPixelBufferGetBaseAddressOfPlane(self, plane)
      let height = CVPixelBufferGetHeightOfPlane(self, plane)
      let bytesPerRow = CVPixelBufferGetBytesPerRowOfPlane(self, plane)
      
      memcpy(dest, source, height * bytesPerRow)
    }
    
    CVPixelBufferUnlockBaseAddress(copy, CVPixelBufferLockFlags(rawValue: 0))
    CVPixelBufferUnlockBaseAddress(self, .readOnly)
    
    return copy
  }

I use this in AVCaptureVideoDataOutputSampleBufferDelegate so that it doesn’t lock up:

extension SampleViewController: AVCaptureVideoDataOutputSampleBufferDelegate {
  func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!) {
    guard let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { return }
    
    let copy = pixelBuffer.copy()
    pixelBuffers.append(copy)
    print("PixelBuffers: \(pixelBuffers.count)")
  }
}

I can see that the pixelBuffers Array does contain all the CVPixelBuffers, but when I loop through the array and convert the CVPIxelBuffer to UIImage, the image is not displayed:

private func imageFromPixelBuffer(_ pixelBuffer: CVPixelBuffer) -> UIImage? {
    let ciImage = CIImage(cvPixelBuffer: pixelBuffer)
    let context = CIContext()
    
    let imageRect = CGRect(x: 0, y: 0, width: CVPixelBufferGetWidth(pixelBuffer), height: CVPixelBufferGetHeight(pixelBuffer))
    
    if let cgImage = context.createCGImage(ciImage, from: imageRect) {
      return UIImage(cgImage: cgImage, scale: UIScreen.main.scale, orientation: .right)
    }
    
    return nil
}

Could anyone assist with this problem?

@martinjbt. Thanks very much for your question! I personally would recommend for such complex programming questions to post them on www.stackoverflow.com .
I can almost guarantee you that you would get a decent solution within 24 hours :slight_smile:

I hope this helps!

All the best!