在iOS中将RGB像素数据高性能复制到屏幕

时间:2012-07-11 00:19:36

标签: ios opengl-es core-graphics core-video

我们的产品包含一种软件图像解码器,它基本上可以生成全帧像素数据,需要快速复制到屏幕上(我们在iOS上运行)。

目前我们正在使用CGBitmapContextCreate,我们直接访问内存缓冲区,然后为每个帧调用CGBitmapContextCreateImage,然后将该位图绘制到屏幕上。对于iPad的视网膜显示器上的全屏刷新来说,这是太慢了,但帧速度不错(但对于非Retina设备来说还可以)。

我们已经尝试了各种基于OpenGL ES的方法,包括使用glTexImage2D和glTexSubImage2D(基本上渲染到纹理),但CPU使用率仍然很高,我们不能超过~30 FPS满iPad上的屏幕刷新3.问题是,对于30 FPS,CPU使用率几乎为100%,只是为了将像素复制到屏幕上,这意味着我们没有太多工作用于在CPU上自己渲染

我们愿意使用OpenGL或任何能够带来最佳性能的iOS API。像素数据被格式化为每像素32位RGBA数据,但我们在那里有一些灵活性......

有什么建议吗?

4 个答案:

答案 0 :(得分:2)

所以,坏消息是你遇到了一个非常棘手的问题。我一直在这个特定的领域进行了大量的研究,目前唯一能够实现2倍全屏大小的帧缓冲的方法就是使用h.264解码器。一旦将图像数据解码到实际内存中,就可以使用OpenGL完成一些不错的技巧(看看GPUImage)。但是,最大的问题不在于如何将像素从实时内存移动到屏幕上。真正的问题是如何将像素从磁盘上的编码形式移动到实时内存中。可以使用文件映射内存来保存磁盘上的像素,但IO子系统的速度不够快,无法交换足够的页面,从而可以从映射内存中流式传输2x全屏大小的图像。过去常常使用1x全屏尺寸,但现在2倍大小的屏幕实际上是内存量的4倍,硬件无法跟上。您还可以尝试以更加压缩的格式(如PNG)在磁盘上存储帧。但是,然后解码压缩格式会将问题从IO绑定到CPU绑定,并且您仍然卡住了。请查看我的博文opengl_write_texture_cache,了解我在该方法中找到的完整源代码和时序结果。如果您有一个非常特定的格式,您可以将输入图像数据限制为(如8位表),那么您可以使用GPU通过着色器将8位数据作为32BPP像素进行blit,如此示例xcode project { {3}}。但是,我的建议是看看你如何使用h.264解码器,因为它实际上能够在硬件中解码那么多数据,没有其他方法可能会给你那种你想要的结果。

答案 1 :(得分:1)

经过几年,以及我遇到这种需求的几种不同情况,我决定实施一个基本的" pixel viewer"适用于iOS的视图。它支持多种格式的像素缓冲器的高度优化显示,包括32-bpp RGBA,24-bpp RGB和多种YpCbCr格式。

它还支持所有UIViewContentMode *用于智能缩放,缩放以适合/填充等。

代码经过高度优化(使用OpenGL),即使是较旧的iOS设备(如iPhone 5或原装iPad Air)也能实现出色的性能。在这些设备上,它可以在所有像素格式上实现60FPS,除了24bpp格式,它达到大约30-50fps(我通常通过在设备的原始分辨率上显示像素缓冲区进行基准测试,所以显然iPad必须推动更多像素比iPhone 5)。

请查看EEPixelViewer

答案 2 :(得分:1)

CoreVideo很可能是您应该关注的框架。使用OpenGL和CoreGraphics方法,您很难将位图数据从主存储器移动到GPU内存上。这个成本也存在于台式机上,但在iPhone上尤其令人痛苦。

在这种情况下,OpenGL不会对CoreGraphics的速度提升很大,因为瓶颈是纹理数据副本。 OpenGL将为您提供更高效的渲染管道,但纹理副本已经完成了损坏。

所以CoreVideo是要走的路。据我了解框架,它可以解决您遇到的问题。

答案 3 :(得分:0)

然后可以将pbuffer或FBO用作纹理贴图,以便OpenGL ES进一步渲染。这称为Render to Texture或RTT。它在EGL中更快速的搜索pbuffer或FBO