内存拷贝渲染视频的研究

简介: 内存拷贝渲染视频这里说的视频渲染是指通过 CVPixelBufferRef 获取 CGImageRef 对象在 UI 上进行渲染的过程。大家都知道视频渲染是一个非常麻烦的过程,一般来说我们会通过将 CVPixelBufferRef 转换为 CIIm...

内存拷贝渲染视频

这里说的视频渲染是指通过 CVPixelBufferRef 获取 CGImageRef 对象在 UI 上进行渲染的过程。

大家都知道视频渲染是一个非常麻烦的过程,一般来说我们会通过将 CVPixelBufferRef 转换为 CIImage 再将 CIImage 对象转换为 CGImageRef 来完成视频的渲染,其中 CIImage 渲染到 CGImageRef 的过程将会需要到 CIContext- render:toBitmap:rowBytes:bounds:format:colorSpace: 方法来实现,但是在实际使用过程中发现,在 iOS 9.0 系统上,使用这个方法渲染视频时会出现内存泄漏的问题(长时间调试发现似乎是系统的问题)于是花了很多时间来找寻如何绕过 CIContext 来进行视频渲染,最终找到了直接内存拷贝进行视频渲染的方法,也是最为快速的方法。

代码解析

下面我们来直接看代码吧

+ (CGImageRef)createImageWithPixelBuffer:(CVPixelBufferRef)pixelBuffer {
    CGImageRef image = NULL;
    size_t width = CVPixelBufferGetWidth(pixelBuffer);
    size_t height = CVPixelBufferGetHeight(pixelBuffer);
    size_t bytePerRow = CVPixelBufferGetBytesPerRow(pixelBuffer);
    size_t bitPerCompoment = 8;
    size_t bitPerPixel = 4 * bitPerCompoment;
    size_t length = CVPixelBufferGetDataSize(pixelBuffer);
    CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
    CVPixelBufferLockBaseAddress(pixelBuffer, 0);
    void *baseAddress = CVPixelBufferGetBaseAddress(pixelBuffer);
    unsigned char *imageData = (unsigned char *)malloc(length);
    memcpy(imageData, baseAddress, length);
    CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
    [self.class convertBGRAtoRGBA:imageData withSize:length];
    CFDataRef data = CFDataCreate(NULL, imageData, length);
    free(imageData);
    CGDataProviderRef provider = CGDataProviderCreateWithCFData(data);
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    image = CGImageCreate(width, height, bitPerCompoment, bitPerPixel, bytePerRow, colorSpace, bitmapInfo, provider, NULL, NULL, kCGRenderingIntentDefault);
    CFRelease(data);
    CGColorSpaceRelease(colorSpace);
    CGDataProviderRelease(provider);
    return image;
}

不管是视频还是图片,每一帧的画面都是通过一个 RGBA 或是 BGRA 的位图来存储的,所以,实现 CVPixelBufferRefCGImageRef 的转换,也就是需要把他们所对应的内存里面保存的位图数据进行拷贝,来实现图像的渲染。

上面代码分为下面部分:

  • 根据 PixelBuffer 中的信息,以及一些我们已知的信息,获取创建 CGImageRef 对象的必要参数
    size_t width = CVPixelBufferGetWidth(pixelBuffer);
    size_t height = CVPixelBufferGetHeight(pixelBuffer);
    size_t bytePerRow = CVPixelBufferGetBytesPerRow(pixelBuffer);
    size_t bitPerCompoment = 8;
    size_t bitPerPixel = 4 * bitPerCompoment;
    size_t length = CVPixelBufferGetDataSize(pixelBuffer);
    CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
  • 从 PixelBuffer 中拷贝位图数据,并将位图数据拷贝到一个 CFDataRef 对象中

注意:[self.class convertBGRAtoRGBA:imageData withSize:length]; 这个方法的目的只是将位图中的第一位和第三位进行位置交换,因为 PixelBuffer 中的图像是 BGRA 的,而 CGImage 中的图像是 RGBA 的。

    CVPixelBufferLockBaseAddress(pixelBuffer, 0);
    void *baseAddress = CVPixelBufferGetBaseAddress(pixelBuffer);
    unsigned char *imageData = (unsigned char *)malloc(length);
    memcpy(imageData, baseAddress, length);
    CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
    [self.class convertBGRAtoRGBA:imageData withSize:length];
    CFDataRef data = CFDataCreate(NULL, imageData, length);
  • 通过 CFDataRef 创建 CGImageRef
    CGDataProviderRef provider = CGDataProviderCreateWithCFData(data);
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    image = CGImageCreate(width, height, bitPerCompoment, bitPerPixel, bytePerRow, colorSpace, bitmapInfo, provider, NULL, NULL, kCGRenderingIntentDefault);
    CFRelease(data);
    CGColorSpaceRelease(colorSpace);
    CGDataProviderRelease(provider);
    return image;

这样就实现了视频的渲染,获取到视频的图像就可以直接渲染到 UI 上了。

目录
相关文章
|
5月前
|
存储 监控 安全
内存卡数据恢复,3个方法帮你找回丢失的照片和视频
今天,针对内存卡数据恢复,本期做一个详细的归纳,分析常见的数据丢失原因、详细的数据恢复步骤、以及如何保护内存卡数据。
内存卡数据恢复,3个方法帮你找回丢失的照片和视频
|
5月前
|
监控 Java 图形学
【性能优化篇】U3D游戏卡顿大作战:内存与渲染效率的极致提升
【7月更文第12天】在Unity3D游戏开发领域,性能优化是决定玩家体验好坏的关键一环。游戏频繁卡顿,不仅破坏了沉浸式体验,还可能造成玩家流失。本文将深入探讨如何有效解决U3D游戏卡顿问题,特别聚焦于内存管理和渲染效率两大核心领域,助力开发者打造流畅丝滑的游戏世界。
446 0
|
7月前
|
存储 安全 程序员
C内存管理研究
C内存管理研究
41 2
|
7月前
|
存储 测试技术 C语言
C语言内存管理函数研究
C语言内存管理函数研究
51 0
|
存储 JavaScript 前端开发
手撕前端面试题【javascript~ 列表动态渲染、无重复数组、数组排序、新数组、创建数组、深浅拷贝、内存泄露等】
html页面的骨架,相当于人的骨头,只有骨头是不是看着有点瘆人,只有HTML也是如此。 css,相当于把骨架修饰起来,相当于人的皮肉。
81 0
|
机器学习/深度学习 人工智能 缓存
为内存塞不下Transformer犯愁?OpenAI应用AI研究负责人写了份指南(3)
为内存塞不下Transformer犯愁?OpenAI应用AI研究负责人写了份指南
329 0
|
机器学习/深度学习 人工智能 算法
为内存塞不下Transformer犯愁?OpenAI应用AI研究负责人写了份指南(2)
为内存塞不下Transformer犯愁?OpenAI应用AI研究负责人写了份指南
204 0
|
机器学习/深度学习 存储 人工智能
为内存塞不下Transformer犯愁?OpenAI应用AI研究负责人写了份指南(1)
为内存塞不下Transformer犯愁?OpenAI应用AI研究负责人写了份指南
204 0
|
Dart JavaScript 前端开发
从渲染原理出发探究Flutter内存泄漏
# 背景 众所周知,内存的高低是评判一款app的性能优劣的重要的指标之一。作为开发者而言,都会尽可能的减少内存的使用,清除无用的内存块,从而减少整个app的内存使用量。这也是历来开发者是追求的目标。然而,开发者难免时常因为语言用法或者写法的缘故,导致该释放而未释放的对象迟迟未释放,从而内存泄漏,消耗殆尽内存空间,从而导致系统崩溃的情况。 如何更简单的帮助开发者分析、暴露且解决内存泄漏问
从渲染原理出发探究Flutter内存泄漏