解码iPhone GPU上的视频帧

时间:2012-02-17 17:33:21

标签: iphone ios opengl-es video-processing gpgpu

我正在寻找解码iPhone上本地mpeg-4视频帧的最快方法。我只是对每10帧中像素的亮度值感兴趣。我不需要在任何地方呈现视频。

我尝试过ffmpeg,AVAssetReader,ImageAssetGenerator,OpenCV和MPMoviePlayer,但它们都太慢了。我能得到的最快速度是2倍(一分钟内扫描2分钟)。我想要更接近10倍的东西。

假设我上面的尝试没有使用GPU,有没有办法用GPU上运行的东西来实现我的目标? OpenGL似乎主要用于渲染输出,但我已经看到它用作传入视频的过滤器。也许这是一个选择?

提前致谢!

3 个答案:

答案 0 :(得分:3)

如果您愿意使用仅限iOS 5的解决方案,请查看AVCaputureSession上2011 WWDC会话中的示例应用程序ChromaKey。

该演示从内置摄像头捕获30 FPS的视频,并将每个帧作为纹理传递给OpenGL。然后,它使用OpenGL来操作帧,并可选择将结果写入输出视频文件。

该代码使用一些严重的低级魔法将Core视频像素缓冲区从AVCaptureSession绑定到OpenGL,以便它们在图形硬件中共享内存。

将AVCaptureSession更改为使用电影文件作为输入而非摄像机输入应该相当简单。

您可以将会话设置为以Y / UV形式而不是RGB传送帧,其中Y分量是亮度。如果做不到这一点,编写一个将每个像素的RGB值转换为亮度值的着色器将是一件非常简单的事情。

你应该能够在所有帧上完成所有这些,而不仅仅是每10帧。

答案 1 :(得分:0)

假设您可以使用iOS 5,看似vImage可能是合适的。每10帧似乎都在使用像vImage这样的框架。但是,任何类型的实际实时处理几乎肯定都需要OpenGL。

答案 2 :(得分:0)

假设您的应用程序的瓶颈在将视频帧转换为可显示格式(如RGB)的代码中,您可能会对我共享的用于convert one .mp4 frame (encoded as YV12) to RGB using Qt and OpenGL的代码感兴趣。此应用程序将帧上传到GPU并激活GLSL fragment shader以执行从YV12到RGB的转换,因此它可以显示在QImage

static const char *p_s_fragment_shader =
    "#extension GL_ARB_texture_rectangle : enable\n"
    "uniform sampler2DRect tex;"
    "uniform float ImgHeight, chromaHeight_Half, chromaWidth;"
    "void main()"
    "{"
    "    vec2 t = gl_TexCoord[0].xy;" // get texcoord from fixed-function pipeline
    "    float CbY = ImgHeight + floor(t.y / 4.0);"
    "    float CrY = ImgHeight + chromaHeight_Half + floor(t.y / 4.0);"
    "    float CbCrX = floor(t.x / 2.0) + chromaWidth * floor(mod(t.y, 2.0));"
    "    float Cb = texture2DRect(tex, vec2(CbCrX, CbY)).x - .5;"
    "    float Cr = texture2DRect(tex, vec2(CbCrX, CrY)).x - .5;"
    "    float y = texture2DRect(tex, t).x;" // redundant texture read optimized away by texture cache
    "    float r = y + 1.28033 * Cr;"
    "    float g = y - .21482 * Cb - .38059 * Cr;"
    "    float b = y + 2.12798 * Cb;"
    "    gl_FragColor = vec4(r, g, b, 1.0);"
    "}"