2011-12-15 3 views
3

Я пытаюсь использовать структуру AVFoundation для захвата «серий» неподвижных изображений из AVCaptureStillImageOutput QUICKLY, как и пакетный режим в некоторых камерах. Я хочу использовать обработчик завершения,Сохранение CMSampleBufferRef для последующей обработки

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

Означает ли кто-нибудь, что я, возможно, делаю неправильно здесь? Есть ли лучший способ сделать это?

ответ

7

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

ИСТОЧНИК: CoreMedia.Framework CMSampleBuffer.h

0

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

Таким образом, в дополнение к манипулирование 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. Сохраните сжатый CMSampleBuffer, сжатый VT, только достаточно долго, чтобы выставить глубокую копию для последующей обработки.

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