如何使用NDK有效地扩展视频帧

时间:2014-06-15 14:08:04

标签: android c++ video android-ndk multimedia

我正在做一个关于处理视频帧的Android项目,我需要在显示之前处理每一帧。该过程包括从1920x1080到2560x1440的分辨率放大帧,色彩空间转换和基于RGB的一些必要的图像处理,所有这些工作应在33ms~40ms内完成。

我已经用手臂霓虹灯优化了yuv-> rgb和其他处理,它们效果很好。但我必须首先将帧从1080p扩展到2k分辨率,它现在是性能的瓶颈。

我的问题是如何在20ms内有效地将图像从1080p扩展到2k分辨率,我对缩放算法没有太多经验,所以任何建议都是有帮助的。 我可以使用arm neon来优化现有的算法吗?

硬件环境:

  • CPU:Samsung Exynos 5420
  • 内存:3GB
  • 显示:2560X1600 px

更新

我将描述我的解码过程,我使用MediaCodec将普通视频(H.264)解码为YUV(NV12),默认解码器是硬件,它非常快。然后我使用arm neon将NV12转换为RGBW,然后将RGBW帧发送到surfaceflinger进行显示。我只使用普通的SurfaceView rahter而不是GLSurfaceView。

瓶颈是如何将YUV从1080p快速扩展到2K。

3 个答案:

答案 0 :(得分:1)

我发现这些示例效果很好,所以请允许我使用这个使用OpenGL着色器从YUV转换的示例程序 - > RGB:http://www.fourcc.org/source/YUV420P-OpenGL-GLSLang.c

我为您的计划设想的是:

  1. 硬件视频解码H.264流 - > YUV数组
  2. 将YUV数组作为纹理上传到OpenGL;实际上,你将上传3种不同的纹理--Y,U和V
  3. 运行片段着色器,将Y,U和V纹理转换为RGB(W)图像;这将在视频内存中产生新的纹理
  4. 针对上一步中生成的纹理运行新的片段着色器以缩放图像
  5. 这里可能涉及一些学习曲线,但考虑到你的问题描述,我认为它是可行的。一步一步:获得OpenGL框架,尝试仅上传Y纹理并编写一个简单的片段着色器,根据Y样本发出灰度像素,然后转到正确转换图像,然后得到一个非常天真的upsampler正在工作,然后将更复杂的上采样器投入使用。

答案 1 :(得分:0)

我也推荐opengl es,主要是因为我目前正在制作的项目,也在播放视频。对我来说,显示器是1920 x 1080,所以我使用的纹理是2048 x 1024.我在四核心臂7上得到大约35 fps。

使用GLSurfaceView和您自己的自定义渲染器。如果您正在使用ffmpeg,那么一旦您解码了视频帧,请使用sws_scale缩放您的帧,然后将其上传到opengl纹理中。纹理/显示越大,获得的fps就越少,因为每帧都需要花费很多时间将大图像上传到gpu。

根据您对解码视频输入的需求,您需要研究。对我来说,我必须为android编译ffmpeg并从那里开始。

答案 2 :(得分:0)

我很抱歉把它放在一个答案中。我没有足够的分数来发表评论。 我想补充一点,你可能会遇到OGL纹理限制。我试图使用OGL来解决相反的问题;实时缩小相机尺寸。问题是最大OGL纹理是2048x2048。不确定这是否适用于所有设备。这个限制适用于N72013和LG2等新型套件。最后,我不得不在没有OGL的情况下写入NDK,通过手动优化地狱。 祝你好运。