didDropSampleBuffer вызывается очень часто в iOS

#ios #objective-c #tensorflow

#iOS #objective-c #tensorflow

Вопрос:

Я снимаю видео и выполняю некоторые анализы в captureOutput:(AVCaptureOutput *)output didOutputSampleBuffer delegate. но через короткое время этот метод не вызывается. затем вызывается captureOutput:(AVCaptureOutput *)output didDropSampleBuffer делегат.

Когда я ничего не делаю в didOutputSampleBuffer, все в порядке.
Я запускаю модель тензорного потока в этом делегате. И это вызывает проблему.

Проблема:
Проблема в том, что при didDropSampleBuffer вызове didOutputSampleBuffer больше не вызывается.

Мое решение:
Моим решением была остановка и запуск AVCaptureSession. но это привело к дополнительному использованию памяти! Что в конечном итоге привело к сбою моего приложения.

  - (void)captureOutput:(AVCaptureOutput *)output didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
    {
        // ******  do heavy work in this delegate *********
        graph = [TensorflowGraph new];
        predictions = [graph runModelOnPixelBuffer:pixelBuffer orientation: UIDeviceOrientationPortrait CardRect: _vwRect];
    }

    - (void)captureOutput:(AVCaptureOutput *)output didDropSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
    {
                CFTypeRef droppedFrameReason = CMGetAttachment(sampleBuffer, kCMSampleBufferAttachmentKey_DroppedFrameReason, NULL);
                NSLog(@"dropped frame, reason: %@", droppedFrameReason);
    }
  

—-> отброшенный кадр, причина: OutOfBuffers

Согласно [https://developer.apple.com/library/archive/technotes/tn2445/_index.html ]:

Это условие обычно вызывается тем, что клиент слишком долго удерживает буферы, и его можно устранить, вернув буферы поставщику.

Как я могу вернуть буфер поставщику?

Отредактировано

После выполнения 11 раз этой CGImageRef cgImage = [context createCGImage:resized fromRect:resized.extent]; строки вызывается didDropSampleBuffer . комментирование CFRelease(pixelBuffer) не имеет никакого значения в результате. Означает ли это, что PixelBuffer не выпущен?

 CFRetain(pixelBuffer);
CVPixelBufferLockBaseAddress(pixelBuffer, kCVPixelBufferLock_ReadOnly);

CIImage* ciImage = [[CIImage alloc] initWithCVPixelBuffer:pixelBuffer];
ciImage = [ciImage imageByCroppingToRect:cropRect];

CGAffineTransform transform = CGAffineTransformIdentity;
CGFloat angle = 0.0;

transform = CGAffineTransformRotate(transform, angle);
CIImage* resized = [ciImage imageByApplyingTransform:transform];

CIContext *context = [CIContext contextWithOptions:nil];

CGImageRef cgImage = [context createCGImage:resized fromRect:resized.extent]; // *********************************

UIImage* _res = [[UIImage alloc] initWithCGImage:cgImage];


CFRelease(pixelBuffer);
  

1

Комментарии:

1. Это может показаться излишним вопросом, но что вы ожидаете, что произойдет? С моей точки зрения, это то, что произойдет, если метод didOutputSampleBuffer не сможет поддерживать частоту кадров камеры.

2. Скорее всего, вы CFRetain включаете sampleBuffer что-то, что вы делаете, но не выпускаете это. Когда в конвейере захвата заканчиваются буферы, потому что все они сохранены, он прекращает вывод. Это утечка памяти. Но вам, вероятно, потребуется показать больше кода, чтобы определить проблему и убедиться, что ваши существующие фрагменты кода точны.

3. @allenh Спасибо. Я обновил вопрос.

4. Вы можете проверить количество сохранений вашего пиксельного буфера с помощью CFGetRetainCount . При возврате вашего делегата должно быть 1. [CIImage initWithCVPixelBuffer: на самом деле сохраняется пиксельный буфер, поэтому, если вы храните изображение где угодно, это может вызвать проблемы. Кроме того, я понятия не имею, что [TensorflowGraph runModelOnPixelBuffer:orientation:CardRect:] происходит с пиксельным буфером. Вы также должны вызывать CVPixelBufferUnlockBaseAddress перед CFRelease .

5. @allenh Спасибо. Это был действительно хороший комментарий. После [ciimage initWithCvPixelBuffer] как я должен освободить пиксельный буфер? Должен ли я что-то сделать, или это будет выпущено автоматически?