何时发布CMBlockBufferRef?

时间:2012-06-21 17:17:30

标签: objective-c ios avfoundation

我正在通过AV Foundation的导出功能从iPod库中的轨道读取LPCM样本。我的大多数代码都是从Chris Adamson's example here借来的。

我正在设置一个新的CMBlockBufferRef并将其保留为CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer。根据apple CFType reference,我需要对我明确保留的任何对象使用CFRelease

问题是我似乎无法确定释放CMBlockBufferRef对象的确切位置。如果我根本不释放它,我会收到大量内存泄漏。如果我尝试在循环内的任何位置释放它,应用程序会在我的GrabAudioData方法中因EXC_BAD_ACCESS错误而崩溃。如果我尝试在循环之外启动并释放它,则内存泄漏仍然存在。我已经尝试过测试,看看blockBuffer是否NULL,然后才发布,但这不起作用。请帮忙!

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;
        }
    }    
}

2 个答案:

答案 0 :(得分:2)

blockBuffer是从nextBuffer中保留的,所以它应该在nextBuffer之前释放。

答案 1 :(得分:1)

除了@ sinn246的答案,你还必须检查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);