dpcasady
dpcasady

Reputation: 1846

When to release CMBlockBufferRef?

I'm reading LPCM samples from a track in the iPod library, by means of the export functionality of AV Foundation. Most of my code is borrowed from Chris Adamson's example here.

I'm setting up a new CMBlockBufferRef and retaining it with CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer. According to the apple CFType reference, I need to use CFRelease on any object I explicitly retain.

The problem is that I can't seem to figure out where exactly to release the CMBlockBufferRef object. If I don't release it at all, I get a large memory leak. If I try to release it anywhere inside my loop, the app crashes with a EXC_BAD_ACCESS error in my GrabAudioData method. If I try to initiate and release it outside of the loop, the memory leak is still there. I've tried testing to see if the blockBuffer is NULL, before releasing but that doesn't work. Please help!

while (assetReader.status != AVAssetReaderStatusCompleted)
{
    if (assetReader.status == AVAssetReaderStatusReading)
    {
        CMSampleBufferRef nextBuffer = [readerOutput copyNextSampleBuffer];

        if (nextBuffer)
        {
            AudioBufferList bufferList;
            CMBlockBufferRef blockBuffer;
            CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(nextBuffer, NULL, &bufferList, sizeof(bufferList), NULL, NULL, kCMSampleBufferFlag_AudioBufferList_Assure16ByteAlignment, &blockBuffer);

            // Using the AudioBufferList
            bufferManager->GrabAudioData(&bufferList); 

            CMSampleBufferInvalidate(nextBuffer);
            CFRelease(nextBuffer);

            // Releasing here causes a crash
            // CFRelease(blockBuffer);
        }
        else
        {
            break;
        }
    }    
}

Upvotes: 1

Views: 1754

Answers (2)

user503821
user503821

Reputation: 653

In addition to @sinn246's answer, you must also check the return of CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer:

OSStatus err = CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(nextBuffer, NULL, &bufferList, sizeof(bufferList), NULL, NULL, kCMSampleBufferFlag_AudioBufferList_Assure16ByteAlignment, &blockBuffer);

if (!err && blockBuffer && bufferList.mBuffers[0].mData && (bufferList.mBuffers[0].mDataByteSize > 0))
{
    // Using the AudioBufferList
    bufferManager->GrabAudioData(&bufferList);
}

if (blockBuffer) // Double check that what you are releasing actually exists!
{
    CFRelease(blockBuffer);
}

CMSampleBufferInvalidate(nextBuffer);
CFRelease(nextBuffer);

Upvotes: 1

sinn246
sinn246

Reputation: 21

blockBuffer is retained from nextBuffer, so it should be released BEFORE nextBuffer.

Upvotes: 2

Related Questions