ios - iOS 7+ 上从 BGRA 字节获取 CVPixelBufferRef 的最快方法

标签 ios video textures

iOS 7+ 上转换 BGRA/UIImage 原始字节的最快方法是什么?数据到 CVPixelBufferRef ?字节是 BGRA 顺序中每个像素 4 个字节。

是否有机会在这里直接转换与将数据复制到辅助存储中?

我考虑过CVPixelBufferCreateWithBytes但我有预感它正在复制内存......

最佳答案

您必须使用 CVPixelBufferCreate因为CVPixelBufferCreateWithBytes不允许使用 Core Video 纹理缓存快速转换为 OpenGL 纹理。我不确定为什么会这样,但至少从 iOS 8 开始就是这样。我用分析器测试了这个,CVPixelBufferCreateWithBytes每次从缓存中访问 Core Video 纹理时都会调用 texSubImage2D。
CVPixelBufferCreate如果宽度不是 16 的倍数,会做一些有趣的事情,所以如果你打算在 CVPixelBufferGetBaseAddress 上进行 CPU 操作,并且您希望它的布局像 CGImageCGBitmapContext ,您需要将宽度加高直到它是 16 的倍数,或者确保使用 CVPixelBufferGetRowBytes 并将其传递给任何 CGBitmapContext你创造。

我测试了从 16 到 2048 的所有宽度和高度尺寸组合,只要将它们填充到下一个最高的 16 倍数,内存布局就正确了。

+ (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) } };
}

有趣的是,如果您从 Core Video 缓存中请求尺寸小于填充尺寸的纹理,它将立即返回一个纹理。不知何故,它下面能够引用原始纹理,但宽度和高度较小。

总而言之,您不能用 CVPixelBufferRef 包装现有内存。使用 CVPixelBufferCreateWithBytes并有效地使用 Core Video 纹理缓存。您必须使用 CVPixelBufferCreate并使用 CVPixelBufferGetBaseAddress .

关于ios - iOS 7+ 上从 BGRA 字节获取 CVPixelBufferRef 的最快方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28102358/

相关文章:

ios - 在 collectionViewCell 中使用 UIPageViewController

iphone - 将 iphone 应用程序转换为 iPad、iOS?

MATLAB:合并目录中的所有视频

opengl - 如何在 PyOpenGL 中将纹理复制到 pbo 中?

ios - AccessibilityTraits StartsMedia 不起作用

ios - 检查节点是否为 SKShapeNodes

android - 更改 ACTION_VIDEO_CAPTURE 的格式

video - ffmpeg concat 产生 DTS 乱序错误

java - OpenGL-GLSL纹理()调用: 1282 Invalid Operation

c++ - uvec2 片段着色器输出的哪种组合