Это было довольно интересно после того, как я возился с образцом. Проблема здесь заключается в функции CVOpenGLESTextureCacheCreateTextureFromImage()
. Если вы посмотрите на консоль, когда получите зеленую текстуру, вы увидите что-то похожее на следующее:
Ошибка при CVOpenGLESTextureCacheCreateTextureFromImage -6661
-6661, согласно заголовкам (единственное место, где я мог найти документацию по этим новым функциям), это ошибка kCVReturnInvalidArgument
. Что-то явно не так с одним из аргументов этой функции.
Оказывается, это проблема CVImageBufferRef
. Похоже, что это освобождается или иным образом изменяется, пока происходит блок, который обрабатывает это обновление кэша текстуры.
Я попробовал несколько способов решения этой проблемы и в итоге использовал очередь отправки и семафор отправки, как я описал в этом ответе , когда делегат по-прежнему перезванивал в главном потоке и внутри делегата. сделать что-то вроде следующего:
- (void)captureOutput:(AVCaptureOutput *)captureOutput
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
fromConnection:(AVCaptureConnection *)connection
{
if (dispatch_semaphore_wait(frameRenderingSemaphore, DISPATCH_TIME_NOW) != 0)
{
return;
}
CVImageBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
CVPixelBufferLockBaseAddress(pixelBuffer, 0);
CFRetain(pixelBuffer);
dispatch_async(openGLESContextQueue, ^{
[EAGLContext setCurrentContext:_context];
// Rest of your processing
CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
CFRelease(pixelBuffer);
dispatch_semaphore_signal(frameRenderingSemaphore);
});
}
Создавая CVImageBufferRef в главном потоке, блокируя байты, на которые он указывает, и сохраняя его, затем передавая его асинхронному блоку, который, похоже, исправляет эту ошибку. Полный проект, демонстрирующий эту модификацию, можно загрузить с здесь .
Я должен сказать здесь одну вещь: это, похоже, ничего вам не даст. Если вы посмотрите, как настроен пример GLCameraRipple, самая тяжелая операция в приложении, вычисление эффекта ряби, уже отправлена в фоновую очередь. При этом также используется новый путь быстрой загрузки для предоставления данных камеры в OpenGL ES, так что это не является узким местом при запуске в главном потоке.
В своем профилировании инструментов на двухъядерном iPhone 4S я не вижу существенной разницы в скорости рендеринга или использовании процессора между стандартной версией этого примера приложения и моей модифицированной, которая выполняет загрузку кадров в фоновой очереди. Тем не менее, это была интересная проблема для диагностики.