iOS 7+上将BGRA / UIImage
数据的原始字节转换为CVPixelBufferRef
的最快方法是什么? BGRA顺序中每个像素的字节数为4个字节。
有没有机会直接投射,而不是将数据复制到二级存储中?
我考虑过CVPixelBufferCreateWithBytes
,但我有预感它正在复制记忆......
答案 0 :(得分:4)
您必须使用CVPixelBufferCreate
因为CVPixelBufferCreateWithBytes
不允许使用Core Video纹理缓存快速转换为OpenGL纹理。我不确定为什么会出现这种情况,但至少就像iOS 8那样。我用探查器测试了这个,CVPixelBufferCreateWithBytes
导致每次核心视频纹理都要进行texSubImage2D调用从缓存中访问。
CVPixelBufferCreate
会做有趣的事情,所以如果你打算在CVPixelBufferGetBaseAddress
上进行CPU操作,你希望它像{{1}那样布局或者CGImage
,您需要将宽度填充到16的倍数,或者确保使用CVPixelBufferGetRowBytes并将其传递给您创建的任何CGBitmapContext
。
我测试了宽度和高度尺寸从16到2048的所有组合,只要它们被填充到16的下一个最高倍数,就会正确布局。
CGBitmapContext
有趣的是,如果您要求Core Video缓存中的纹理尺寸小于填充尺寸,它将立即返回纹理。不知何故,它下面能够引用原始纹理,但宽度和高度较小。
总而言之,您无法使用+ (NSInteger) alignmentForPixelBufferDimension:(NSInteger)dim
{
static const NSInteger modValue = 16;
NSInteger mod = dim % modValue;
return (mod == 0 ? dim : (dim + (modValue - mod)));
}
+ (NSDictionary*) pixelBufferSurfaceAttributesOfSize:(CGSize)size
{
return @{ (NSString*)kCVPixelBufferPixelFormatTypeKey: @(kCVPixelFormatType_32BGRA),
(NSString*)kCVPixelBufferWidthKey: @(size.width),
(NSString*)kCVPixelBufferHeightKey: @(size.height),
(NSString*)kCVPixelBufferBytesPerRowAlignmentKey: @(size.width * 4),
(NSString*)kCVPixelBufferExtendedPixelsLeftKey: @(0),
(NSString*)kCVPixelBufferExtendedPixelsRightKey: @(0),
(NSString*)kCVPixelBufferExtendedPixelsTopKey: @(0),
(NSString*)kCVPixelBufferExtendedPixelsBottomKey: @(0),
(NSString*)kCVPixelBufferPlaneAlignmentKey: @(0),
(NSString*)kCVPixelBufferCGImageCompatibilityKey: @(YES),
(NSString*)kCVPixelBufferCGBitmapContextCompatibilityKey: @(YES),
(NSString*)kCVPixelBufferOpenGLESCompatibilityKey: @(YES),
(NSString*)kCVPixelBufferIOSurfacePropertiesKey: @{ @"IOSurfaceCGBitmapContextCompatibility": @(YES), @"IOSurfaceOpenGLESFBOCompatibility": @(YES), @"IOSurfaceOpenGLESTextureCompatibility": @(YES) } };
}
使用CVPixelBufferRef
包装现有内存并有效使用Core Video纹理缓存。您必须使用CVPixelBufferCreateWithBytes
并使用CVPixelBufferCreate
。