Я снимаю экран моей системы с помощью AVCaptureSession
, а затем создаю видеофайл из захваченных буферов изображений. Он отлично работает.
Теперь я хочу масштабировать буферы изображений, поддерживая соотношение сторон для размера видеофайла. Я использовал следующий код для масштабирования изображений.
- (void)captureOutput:(AVCaptureOutput *)output didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {
CVImageBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
if (pixelBuffer == NULL) { return; }
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
size_t finalWidth = 1080;
size_t finalHeight = 720;
size_t sourceWidth = CVPixelBufferGetWidth(imageBuffer);
size_t sourceHeight = CVPixelBufferGetHeight(imageBuffer);
CGRect aspectRect = AVMakeRectWithAspectRatioInsideRect(CGSizeMake(sourceWidth, sourceHeight), CGRectMake(0, 0, finalWidth, finalHeight));
size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
size_t startY = aspectRect.origin.y;
size_t yOffSet = (finalWidth*startY*4);
CVPixelBufferLockBaseAddress(imageBuffer, 0);
void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer);
void* destData = malloc(finalHeight * finalWidth * 4);
vImage_Buffer srcBuffer = { (void *)baseAddress, sourceHeight, sourceWidth, bytesPerRow};
vImage_Buffer destBuffer = { (void *)destData+yOffSet, aspectRect.size.height, aspectRect.size.width, aspectRect.size.width * 4};
vImage_Error err = vImageScale_ARGB8888(&srcBuffer, &destBuffer, NULL, 0);
CVPixelBufferUnlockBaseAddress(imageBuffer, 0);
OSType pixelFormat = CVPixelBufferGetPixelFormatType(imageBuffer);
CVImageBufferRef pixelBuffer1 = NULL;
CVReturn result = CVPixelBufferCreateWithBytes(NULL, finalWidth, finalHeight, pixelFormat, destData, finalWidth * 4, NULL, NULL, NULL, &pixelBuffer1);
}
Я могу масштабировать изображение с помощью приведенного выше кода, но окончательное изображение кажется размытым по сравнению с изменением размера изображения с помощью приложения предварительного просмотра. Из-за этого видео нечеткое.
Это нормально работает, если я изменяю формат выходных пикселей на RGB с помощью кода ниже.
output.videoSettings = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA], (id)kCVPixelBufferPixelFormatTypeKey, nil];
Но мне нужны буферы изображений в формате YUV ( формат по умолчанию для AVCaptureVideoDataOutput
), поскольку это уменьшит размер буфера при передаче по сети.
Изображение после масштабирования:
Image resized with Preview application:
введите описание изображения здесь
Я пробовал использовать vImageScale_CbCr8
вместо vImageScale_ARGB8888
, но полученное изображение не содержало правильных значений RGB.
Я также заметил, что есть функция для преобразования формата изображения : vImageConvert_422YpCbYpCr8ToARGB8888(const vImage_Buffer *src, const vImage_Buffer *dest, const vImage_YpCbCrToARGB *info, const uint8_t permuteMap[4], const uint8_t alpha, vImage_Flags flags);
Но я не знаю, какими должны быть значения для vImage_YpCbCrToARGB и permuteMap, так как я ничего не знаю об обработке изображений.
Ожидаемое решение:
Как преобразовать буферы пикселей YUV в буферы RGB и обратно в YUV (или) Как масштабировать буферы пикселей YUV, не влияя на значения RGB.