Как перейти от vImage_Buffer к CVPixelBufferRef
Я записываю живое видео в своем приложении для iOS. На другой странице Stackru ( ссылка) я обнаружил, что вы можете использовать vImage_Buffer для работы с моими фреймами.
Проблема в том, что я понятия не имею, как вернуться к CVPixelBufferRef из выведенного vImage_buffer.
Вот код, который приведен в другой статье:
NSInteger cropX0 = 100,
cropY0 = 100,
cropHeight = 100,
cropWidth = 100,
outWidth = 480,
outHeight = 480;
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
CVPixelBufferLockBaseAddress(imageBuffer,0);
void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer);
size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
vImage_Buffer inBuff;
inBuff.height = cropHeight;
inBuff.width = cropWidth;
inBuff.rowBytes = bytesPerRow;
int startpos = cropY0*bytesPerRow+4*cropX0;
inBuff.data = baseAddress+startpos;
unsigned char *outImg= (unsigned char*)malloc(4*outWidth*outHeight);
vImage_Buffer outBuff = {outImg, outHeight, outWidth, 4*outWidth};
vImage_Error err = vImageScale_ARGB8888(&inBuff, &outBuff, NULL, 0);
if (err != kvImageNoError) NSLog(@" error %ld", err);
И теперь мне нужно конвертировать outBuff
в CVPixelBufferRef.
Я предполагаю, что мне нужно использовать vImageBuffer_CopyToCVPixelBuffer
но я не уверен как.
Мои первые попытки провалились с EXC_BAD_ACCESS:
CVPixelBufferUnlockBaseAddress (imageBuffer, 0);
CVPixelBufferRef pixelBuffer;
CVPixelBufferCreate(kCFAllocatorSystemDefault, 480, 480, kCVPixelFormatType_32BGRA, NULL, &pixelBuffer);
CVPixelBufferLockBaseAddress( pixelBuffer, 0 );
vImage_CGImageFormat format = {
.bitsPerComponent = 8,
.bitsPerPixel = 32,
.bitmapInfo = kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst, //BGRX8888
.colorSpace = NULL, //sRGB
};
vImageBuffer_CopyToCVPixelBuffer(&outBuff,
&format,
pixelBuffer,
NULL,
NULL,
kvImageNoFlags); // Here is the crash!
CVPixelBufferUnlockBaseAddress( pixelBuffer, 0 );
Любая идея?
1 ответ
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool : YES], kCVPixelBufferCGImageCompatibilityKey,
[NSNumber numberWithBool : YES], kCVPixelBufferCGBitmapContextCompatibilityKey,
[NSNumber numberWithInt : 480], kCVPixelBufferWidthKey,
[NSNumber numberWithInt : 480], kCVPixelBufferHeightKey,
nil];
status = CVPixelBufferCreateWithBytes(kCFAllocatorDefault, 480, 480, kCVPixelFormatType_32BGRA, outImg, bytesPerRow, NULL, NULL, (__bridge CFDictionaryRef)options, &pixbuffer);
Вы должны сгенерировать новый pixelBuffer как выше.
- На всякий случай... если вы хотите, чтобы поток видео в реальном времени CROPPED в ваш интерфейс, используйте AVPlayerLayer,AVCaptureVideoPreviewLayer и / или другие подклассы CALayer, используйте границы слоя, кадр и положение для вашей области 100x100 пикселей до области 480x480.
Примечания к vImage для ВАШЕГО вопроса (разные обстоятельства могут отличаться)
CVPixelBufferCreateWithBytes не будет работать с vImageBuffer_CopyToCVPixelBuffer(), потому что вам нужно скопировать данные vImage_Buffer в "чистый" или "пустой" CVPixelBuffer.
Нет необходимости блокировать / разблокировать - убедитесь, что вы знаете, когда блокировать, а когда не блокировать буферы пикселей.
Ваш inBuff vImage_Buffer просто необходимо инициализировать из данных пиксельного буфера, а не вручную (если вы не знаете, как использовать CGContexts и т. Д. Для инициализации пиксельной сетки)
используйте vImageBuffer_InitWithCVPixelBuffer()
vImageScale_ARGB8888 масштабирует все данные CVPixel до меньшего / большего прямоугольника. Он не будет МАСШТАБИРОВАТЬ часть / область обрезки буфера для другого буфера.
Когда вы используете vImageBuffer_CopyToCVPixelBuffer(), vImageCVImageFormatRef и vImage_CGImageFormat должны быть заполнены правильно.
CGColorSpaceRef dstColorSpace = CGColorSpaceCreateWithName(kCGColorSpaceITUR_709);
vImage_CGImageFormat format = { .bitsPerComponent = 16, .bitsPerPixel = 64, .bitmapInfo = (CGBitmapInfo)kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder16Big , .colorSpace = dstColorSpace }; vImageCVImageFormatRef vformat = vImageCVImageFormat_Create(kCVPixelFormatType_4444AYpCbCr16, kvImage_ARGBToYpCbCrMatrix_ITU_R_709_2, kCVImageBufferChromaLocation_Center, format.colorSpace, 0); CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, 480, 480, kCVPixelFormatType_4444AYpCbCr16, NULL, &destBuffer); NSParameterAssert(status == kCVReturnSuccess && destBuffer != NULL); err = vImageBuffer_CopyToCVPixelBuffer(&sourceBuffer, &format, destBuffer, vformat, 0, kvImagePrintDiagnosticsToConsole);
(ПРИМЕЧАНИЕ - это настройки для 64-битного ProRes с Alpha - настройте для 32-битного)