在iPhone GPU上解码视频帧



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

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

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

提前感谢!

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

该演示从内置相机捕获30 FPS的视频,并将每一帧作为纹理传递给OpenGL。然后,它使用OpenGL来处理帧,并选择性地将结果写入输出视频文件。

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

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

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

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

假设您可以使用iOS5,那么vImage似乎是合适的。每10帧似乎都在使用vImage这样的框架的范围内。然而,任何类型的实际实时处理几乎肯定都需要OpenGL。

假设您的应用程序的瓶颈在于将视频帧转换为可显示格式(如RGB)的代码,您可能会对我共享的一个代码感兴趣,该代码用于使用QtOpenGL将一个.mp4帧(编码为YV12)转换为RGB。该应用程序将帧上传到GPU,并激活GLSL片段着色器以进行从YV12到RGB的转换,因此它可以显示在QImage中。

static const char *p_s_fragment_shader =
    "#extension GL_ARB_texture_rectangle : enablen"
    "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);"
    "}"

最新更新