Android 上的硬件加速 H.264/HEVC 视频解码到 OpenGL FBO 或纹理

Hardware accelerated H.264/HEVC video decode on Android to OpenGL FBO or texture

我想解码视频流并将解码后的帧写入 FBO opengl 纹理或其他内存表示,OpenGL 可以很容易地使用它来对其应用额外的过滤器或转换(通过着色器)。

使用 MediaCodec 是当前 Android 中的加速标准吗?我可以使用生成的表面作为 OpenGL 的输入吗?

通过在桌面开发中这样做,我知道有很多方法可以不必要地减慢这个过程(例如,使用 CPU 而不是专用芯片或 GPU 进行解码,在 GPU 中解码并转储结果到系统 ram,然后再次复制到 VRAM,等等)。我不确定这些问题在 Android 上是否重要。例如,java可用内存和opengl可用内存之间的复制成本是否也很高,或者可以忽略不计?

您必须使用 MediaCodec 来访问硬件解码器(这将通过 libstagefright 和 OpenMAX 完成 - 在后台)。

  • 如果要进行任何处理则需要获取解码后的图像 (通常是 YUV420p 类型)并执行 YUV2RGB 和任何其他所需的处理,所有这些都可以在将纹理传递给消费者之前作为 OGL texture/GLSL 等完成。但是,这意味着您必须进行所有音频和视频同步等。如果不需要,请避免。

  • 如果要确保它是版权和 DRM 内容,则必须 使用Surface和DRM接口,不能做任何处理。

  • 如果你只是想直接显示那么可以使用Surface,它可以 也做 YUV2RGB 或只使用 ExoPlayer。

我不知道你是否可以将 Surface 的纹理读入任何 OGL 纹理。我已经实现了上面的第一个选项。

是的,you can configure 一个带有输出表面的 MediaCodec 解码器,并使用 GLSurfaceView 通过着色器应用更改,这是最好的方法,因为您只使用必要的内存,尤其是对于颜色转换(您不能提前知道你的解码器使用什么颜色),以及用于 YUV2RGB 转换。

想做原生的可以看看here or here

一般来说,对于 OpenGL ES,您可以直接导入 YUV 视频表面,如果您将表面作为外部 EGL 图像导入,则可以本地访问它们(请参阅此处的扩展 https://www.khronos.org/registry/OpenGL/extensions/OES/OES_EGL_image_external.txt)。

图形驱动程序将以正确的颜色 space 处理从 YUV 到 RGB 的颜色转换(假设解码器无论如何报告正确的颜色 space ...),这全为零如果您想使用 OpenGL ES,-copy so 绝对是正确的方法,并且比滚动您自己的颜色转换着色器更有效。

在 Android 上,Java-land 中的外部表面导入功能是通过 SurfaceTexture class (https://developer.android.com/reference/android/graphics/SurfaceTexture).

提供的