Сохранение CMSampleBufferRef для последующей обработки - PullRequest
4 голосов
/ 15 декабря 2011

Я пытаюсь использовать платформу AVFoundation для захвата «серии» неподвижных изображений из AVCaptureStillImageOutput БЫСТРО, как режим серийной съемки в некоторых камерах. Я хочу использовать обработчик завершения,

    [stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection 
                                              completionHandler: ^(CMSampleBufferRef imageSampleBuffer, NSError *error) { 

и передайте imageSampleBuffer объекту NSOperation для дальнейшей обработки. Однако я не могу найти способ сохранить буфер в классе NSOperation.

    [stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection 
                                              completionHandler: ^(CMSampleBufferRef imageSampleBuffer, NSError *error) { 

    //Add to queue
    SaveImageDataOperation *saveOperation = [[SaveImageDataOperation alloc] initWithImageBuffer:imageSampleBuffer];
    [_saveDataQueue addOperation:saveOperation];
    [saveOperation release];

    //Continue
    [self captureCompleted];
}];

Кто-нибудь знает, что я тут не так делаю? Есть ли лучший подход для этого?

Ответы [ 2 ]

8 голосов
/ 24 июня 2012

"ВАЖНО. Клиенты CMSampleBuffer должны явно управлять счетом сохранения, вызывая CFRetain и CFRelease, даже в процессах, использующих сборку мусора."

2 голосов
/ 03 июля 2017

В последнее время я много работал с объектами CMSampleBuffer и узнал, что большинство медиа-буферов, получаемых ОС во время операций в реальном времени, выделяются из пулов. Если AVFoundation (или CoreVideo / CoreMedia) исчерпывает буферы в пуле (т. Е. Вы CFRetain буфер в течение «длительного» времени), аспект процесса в реальном времени будет страдать или блокироваться, пока вы не CFRelease буфер обратно в бассейн.

Таким образом, в дополнение к манипулированию счетчиком CFRetain / CFRelease в CMSampleBuffer, вы должны хранить буфер только достаточно долго для распаковки (глубокого копирования битов) в CMBlockBuffer / CMFormat и создания нового CMSampleBuffer для передачи в ваш NSOperationQueue или dispatch_queue_t для последующей обработки.

В моей ситуации я хотел передать сжатые CMSampleBuffers из VideoToolbox по сети. По сути, я создал глубокую копию CMSampleBuffer, и мое приложение полностью контролировало распределение памяти и время жизни. Оттуда я помещаю скопированный CMSampleBuffer в очередь для сетевого ввода-вывода.

Если данные образца сжаты, глубокое копирование должно быть относительно быстрым. В моем приложении я использовал NSKeyedArchiver для создания объекта NSData из соответствующих частей исходного CMSampleBuffer. Для видеоданных H.264 это означало содержимое CMBlockBuffer, байты заголовка SPS / PPS, а также SampleTimingInfo. Сериализовав эти элементы, я смог восстановить CMSampleBuffer на другом конце сети, который вел себя так же, как тот, который мне дал VideoToolbox. В частности, AVSampleBufferLayer смог отобразить их так, как если бы они были получены из компьютера.

Для вашего приложения я бы рекомендовал следующее:

  1. Возьмите исходный CMSampleBuffer и сожмите данные пикселей. если ты можно использовать аппаратный кодировщик в VideoToolbox для создания только I-кадра Изображения H.264, которые будут очень высокого качества. Кодировщик VT по-видимому, очень хорошо для автономной работы, вероятно, много лучше, чем JPEG, если у них нет аппаратного кодека JPEG на система также.
  2. Глубокое копирование сжатого вывода CMSampleBuffer с помощью VideoToolbox, VT будет CFRelease оригинальный CMSampleBuffer обратно в пул, используемый подсистемой захвата.
  3. Сохраняйте сжатый VT CMSampleBuffer только достаточно долго, чтобы поставить глубокую копию в очередь для последующей обработки.

Поскольку видеомагнитофон AVFoundation может выполнять шаги № 1 и № 2 в режиме реального времени без исчерпания буферов, вы должны иметь возможность глубокого копирования и постановки в очередь данных в dispatch_queue без исчерпания буферных пулов, используемых компонентом захвата видео и компоненты VideoToolbox.

...