5

This has been asked before, but something must have changed in Swift since it was asked. I am trying to store CMSampleBuffer objects returned from an AVCaptureSession to be processed later. After some experimentation I discovered that AVCaptureSession must be reusing its CMSampleBuffer references. When I try to keep more than 15 the session hangs. So I thought I would make copies of the sample buffers. But I can't seem to get it to work. Here is what I have written:

var allocator: Unmanaged<CFAllocator>! = CFAllocatorGetDefault()
var bufferCopy: UnsafeMutablePointer<CMSampleBuffer?>
let err = CMSampleBufferCreateCopy(allocator.takeRetainedValue(), sampleBuffer, bufferCopy)
if err == noErr {
    bufferArray.append(bufferCopy.memory!)
} else {
    NSLog("Failed to copy buffer. Error: \(err)")
}

This won't compile because it says that Variable 'bufferCopy' used before being initialized. I've looked at many examples and they'll either compile and not work or they won't compile.

Anyone see what I'm doing wrong here?

Rob
  • 4,149
  • 5
  • 34
  • 48

2 Answers2

8

You can simply pass a CMSampleBuffer? variable (which, as an optional, is implicitly initialized with nil) as inout argument with &:

var bufferCopy : CMSampleBuffer?
let err = CMSampleBufferCreateCopy(kCFAllocatorDefault, buffer, &bufferCopy)
if err == noErr {
    // ...
}
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • 2
    Thank you. This answered the problem I had above for getting the code to compile. And when I test ran the code it turns out that it must be a shallow clone. The data that the new `CMSampleBuffer` held was in the same location as the previous. So when I ran the `AVCaptureSession` it sent 15 sample and locked again because I was holding the reference to the underlying data location. Any idea how I can create a deep clone so I can duplicate the data into a new location in memory? Thanks! – Rob Feb 20 '16 at 16:06
2

Literally you're attempting to use the variable bufferCopy before it is initialized.

You've declared a type for it, but haven't allocated the memory it's pointing to.

You should instead create CMSampleBuffers using the following call https://developer.apple.com/library/tvos/documentation/CoreMedia/Reference/CMSampleBuffer/index.html#//apple_ref/c/func/CMSampleBufferCreate

You should be able to copy the buffer into this then (as long as the format of the buffer matches the one you're copying from).

Tim Bull
  • 2,375
  • 21
  • 25
  • 1
    Thanks for the response Tim, this seems like it may be a good solution for a deep clone. But I'm not that familiar with the way the memory is used at this level. Do you know where I might find a decent example of how to create a deep clone of a `CMSampleBuffer` for both video and audio? Apple apparently holds a cache of 15 `CMSampleBuffer`s that it recycles when running the `AVCaptureSession`. I will evidently need to deep clone to store my own. – Rob Feb 20 '16 at 16:11
  • 1
    I finally figured out how to use this to create a deep clone. All the copy methods reused the data in the heap which kept would lock the `AVCaptureSession`. So I had to pull the data out into a `NSMutableData` object and then created a new sample buffer. Thanks – Rob Feb 24 '16 at 17:44
  • @Rob could you add your code for deep cloning. I have the same issue and am already searching for half a day. – ferdyyy Apr 20 '16 at 13:27
  • @Rob, your exact procedure has been asked about in a follow-up question: http://stackoverflow.com/questions/38335365/ Perhaps you'd like to post an answer there? – jscs Jul 12 '16 at 17:43
  • @Rob, Can you share please your solution – Neil Galiaskarov Oct 23 '17 at 05:03