我正在尝试从相机捕捉视频。我已经获得captureOutput:didOutputSampleBuffer:
回调来触发它,它给了我一个样本缓冲区,然后我转换为CVImageBufferRef
。然后我尝试将该图像转换为UIImage
,然后我可以在我的应用中查看。
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
/*Lock the image buffer*/
CVPixelBufferLockBaseAddress(imageBuffer,0);
/*Get information about the image*/
uint8_t *baseAddress = (uint8_t *)CVPixelBufferGetBaseAddress(imageBuffer);
size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
size_t width = CVPixelBufferGetWidth(imageBuffer);
size_t height = CVPixelBufferGetHeight(imageBuffer);
/*We unlock the image buffer*/
CVPixelBufferUnlockBaseAddress(imageBuffer,0);
/*Create a CGImageRef from the CVImageBufferRef*/
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef newContext = CGBitmapContextCreate(baseAddress, width, height, 8, bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
CGImageRef newImage = CGBitmapContextCreateImage(newContext);
/*We release some components*/
CGContextRelease(newContext);
CGColorSpaceRelease(colorSpace);
/*We display the result on the custom layer*/
/*self.customLayer.contents = (id) newImage;*/
/*We display the result on the image view (We need to change the orientation of the image so that the video is displayed correctly)*/
UIImage *image= [UIImage imageWithCGImage:newImage scale:1.0 orientation:UIImageOrientationRight];
self.capturedView.image = image;
/*We relase the CGImageRef*/
CGImageRelease(newImage);
}
在调用CGBitmapContextCreate
之前,代码似乎工作正常。它总是返回一个NULL
指针。因此,该函数的其余部分都不起作用。无论我似乎传递它,该函数返回null。我不明白为什么。
答案 0 :(得分:20)
传递baseAddress的方式假设图像数据的格式为
ACCC
(其中C是一些颜色成分,R || G || B)。
如果您已将AVCaptureSession设置为以原始格式捕获视频帧,则很可能您将视频数据恢复为平面YUV420格式。 (参见:link text)为了做你在这里尝试做的事情,最简单的事情可能是指定你想要在kCVPixelFormatType_32RGBA中捕获的视频帧。如果您以非平面格式捕获视频帧,Apple建议您以kCVPixelFormatType_32BGRA捕获视频帧,其原因尚未说明,但我可以合理地假设是出于性能考虑。
警告:我没有这样做,并且假设访问像这样的CVPixelBufferRef内容是构建图像的合理方法。我无法保证这实际上有效,但我/可以/告诉你,由于您(可能)捕获视频帧的像素格式,您现在可靠地执行操作的方式将无法正常工作。
答案 1 :(得分:13)
如果你只需要将CVImageBufferRef转换为UIImage,那么它似乎要比应该的要困难得多。基本上你需要转换为CIImage,然后转换为CGImage,然后转换为UIImage。我希望我能告诉你为什么。谁知道呢。
-(void) screenshotOfVideoStream:(CVImageBufferRef)imageBuffer
{
CIImage *ciImage = [CIImage imageWithCVPixelBuffer:imageBuffer];
CIContext *temporaryContext = [CIContext contextWithOptions:nil];
CGImageRef videoImage = [temporaryContext
createCGImage:ciImage
fromRect:CGRectMake(0, 0,
CVPixelBufferGetWidth(imageBuffer),
CVPixelBufferGetHeight(imageBuffer))];
UIImage *image = [[UIImage alloc] initWithCGImage:videoImage];
[self doSomethingWithOurUIImage:image];
CGImageRelease(videoImage);
}
当我使用VTDecompressionSession回调转换H.264视频以获取CVImageBufferRef时,这种特殊方法对我有用(但它适用于任何CVImageBufferRef)。我使用的是iOS 8.1,XCode 6.2。
答案 2 :(得分:4)
您可以直接致电:
self.yourImageView.image=[[UIImage alloc] initWithCIImage:[CIImage imageWithCVPixelBuffer:imageBuffer]];
答案 3 :(得分:2)
Benjamin Loulier在考虑速度的情况下,通过多种方法撰写了一篇关于输出CVImageBufferRef的非常好的帖子。
您还可以在github上找到一个有效的例子;)
时光倒流怎么样? ;) 在这里:http://web.archive.org/web/20140426162537/http://www.benjaminloulier.com/posts/ios4-and-direct-access-to-the-camera