CVPixelBufferLockBaseAddress почему? Захват неподвижного изображения с помощью AVFoundation - PullRequest
7 голосов
/ 24 июня 2011

Я пишу приложение для iPhone, которое создает неподвижные изображения с камеры с помощью AVFoundation.Читая руководство по программированию, я нашел код, который мне почти необходим, поэтому я пытаюсь «реверсировать» и понять его.Я нашел некоторые трудности, чтобы понять ту часть, которая конвертирует CMSampleBuffer в изображение.Так вот, что я понял, а позже код.CMSampleBuffer представляет буфер в памяти, где хранится изображение с дополнительными данными.Позже я вызываю функцию CMSampleBufferGetImageBuffer (), чтобы получить CVImageBuffer с данными изображения.Теперь есть функция, которую я не понимал, и я могу только представить ее функцию: CVPixelBufferLockBaseAddress (imageBuffer, 0);Я не могу понять, является ли это «блокировкой потока», чтобы избежать многократной операции над ним, или блокировкой адреса буфера, чтобы избежать изменений во время работы (и почему это должно измениться?в другом месте?).Остальная часть кода мне понятна.Пытался искать в Google, но все равно ничего не нашел полезного.Кто-нибудь может принести немного света?

-(UIImage*) getUIImageFromBuffer:(CMSampleBufferRef) sampleBuffer{

// Get a CMSampleBuffer's Core Video image buffer for the media data
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 

// Lock the base address of the pixel buffer 
CVPixelBufferLockBaseAddress(imageBuffer, 0); 

void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer); 

// Get the number of bytes per row for the pixel buffer
size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer); 
// Get the pixel buffer width and height
size_t width = CVPixelBufferGetWidth(imageBuffer); 
size_t height = CVPixelBufferGetHeight(imageBuffer); 

// Create a device-dependent RGB color space
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 

// Create a bitmap graphics context with the sample buffer data
CGContextRef context = CGBitmapContextCreate(baseAddress, width, height, 8, 
bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst); 
// Create a Quartz image from the pixel data in the bitmap graphics context
CGImageRef quartzImage = CGBitmapContextCreateImage(context); 
// Unlock the pixel buffer
CVPixelBufferUnlockBaseAddress(imageBuffer,0);

// Free up the context and color space
CGContextRelease(context); 
CGColorSpaceRelease(colorSpace);

// Create an image object from the Quartz image
UIImage *image = [UIImage imageWithCGImage:quartzImage];

// Release the Quartz image
CGImageRelease(quartzImage);

return (image);
}

Спасибо, Андреа

Ответы [ 2 ]

3 голосов
/ 25 июня 2011

Файл заголовка говорит, что CVPixelBufferLockBaseAddress делает память «доступной». Я не уверен, что именно это означает, но если вы этого не сделаете, CVPixelBufferGetBaseAddress завершится ошибкой, поэтому вам лучше это сделать.

EDIT

Просто сделай это короткий ответ. Почему следует учитывать, что изображение может не храниться в основной памяти, оно может находиться где-то в текстуре на каком-то графическом процессоре (CoreVideo работает и на Mac) или даже в другом формате, чем вы ожидаете, поэтому пиксели, которые вы получаете, на самом деле копия. Без блокировки / разблокировки или какой-либо пары «начало / конец» реализация не сможет узнать, когда вы закончили с дублирующимися пикселями, чтобы они эффективно просочились. CVPixelBufferLockBaseAddress просто предоставляет информацию о области действия CoreVideo, я бы не стал зацикливаться на этом.

Да, они могли бы просто вернуть пиксели из CVPixelBufferGetBaseAddress и полностью исключить CVPixelBufferLockBaseAddress. Я не знаю, почему они этого не сделали.

0 голосов
/ 21 октября 2013

Я хотел бы дать больше советов об этой функции, я провел несколько тестов и могу вам это сказать.
Когда вы получаете базовый адрес, вы, вероятно, получаете адрес какого-то ресурса общей памяти. Это становится понятным, если вы печатаете адрес базового адреса, делая так, чтобы вы могли видеть, что базовые адреса повторяются при получении видеокадров.
В моем приложении я беру кадры через определенные интервалы и передаю CVImageBufferRef в * 1004. * Подкласс, который преобразует буфер в изображение и сохраняет его на телефоне. Я не блокирую пиксельный буфер до тех пор, пока операция не начнет преобразовывать CVImageBufferRef, даже если нажатие на более высокой частоте кадров приводит к тому, что базовый адрес пикселя и адрес буфера CVImageBufferRef равны до создания NSOperation и внутри него. , Я просто сохраняю CVImageBufferRef. Я ожидал увидеть несопоставимые ссылки, и даже если я его не увидел, я думаю, что лучшим описанием будет то, что CVPixelBufferLockBaseAddress блокирует часть памяти, где расположен буфер, делая его недоступным из других ресурсов, поэтому он будет сохранять те же данные До тех пор, пока вы не разблокируете его.

...