Соглашение об именах copyNextSampleBuffer подразумевает, что вы являетесь владельцем возвращенного объекта, поэтому вы правильно его отпустите, но вы вызываете метод copyNextSampleBuffer несколько раз в цикле и перезаписываете предыдущую копию, не выпуская ее.
Когда вы наконец вызываете CFRelease, вы вызываете его для переменной, которую вы только что проверили, чтобы быть NULL. Согласно этому ответу StackOverflow , вызов CFRelease для NULL небезопасен, поэтому вы терпите крах:
Вместо этого вам нужно сделать вызов call внутри цикла while, прежде чем перезаписать переменную, например:
CMSampleBufferRef sample = [readerOutput copyNextSampleBuffer];
while( sample != NULL)
{
CFRelease(sample);
sample = [readerOutput copyNextSampleBuffer];
}
Если это не исправляет ваш сбой (и даже если это так), попробуйте запустить статический анализатор над вашим кодом (выберите «Анализ» в меню продукта в XCode) и посмотрите, сообщает ли он о возможных утечках или перевыпусках. Помните, что каждое желтое и синее предупреждение, которое вы получаете, является потенциальным сбоем, поэтому попробуйте исправить их все.
РЕДАКТИРОВАТЬ: Мне просто кажется, что ваш цикл не имеет особого смысла - почему вы читаете сэмплы снова и снова, а затем просто выбрасываете их? Возможно, вы ошиблись при проверке NULL в цикле while, и вы действительно хотели написать это вместо этого?
CMSampleBufferRef sample = [readerOutput copyNextSampleBuffer];
while( sample == NULL)
{
sample = [readerOutput copyNextSampleBuffer];
}
CFRelease(sample);
Это также должно подойти, так как в этом случае вы явно проверяете, что сэмпл не равен NULL перед его выпуском. Хотя вы все еще выбрасываете сэмпл перед тем, как что-то с ним делать, вы рискуете получить бесконечный цикл, если readerOutput не содержит сэмплов.