繁体   English   中英

如何直接从Android Surface访问EGL图像以用于MediaCodec视频解码器?

[英]How to access EGL Image directly from Android Surface for use in MediaCodec video decoder?

我正在编写一个Android应用程序,我需要缓存视频帧,以便我可以轻松地来回转移,几乎没有延迟。

现在我通过向MediaCodec对象的Configure调用提供Surface并调用releaseOutputBuffer并将render标志设置为true来让android解码视频帧。

我发现访问解码表面数据的唯一方法(除了解码返回的bytebuffer,其格式似乎与设备有关)是调用链接到Surface的SurfaceTexture上的updateTeximage ,将其附加到GL_TEXTURE_EXTERNAL_OES目标并将其渲染到GL_TEXTURE2D我自己创建的目标纹理是为了缓存它。

我想优化这个缓存过程,并能够解码不同线程上的帧。 使用我当前的方法,这意味着我将不得不为视频解码器创建另一个EGL上下文,共享上下文等...

我的问题是: 是否可以在不调用 updateTexImage 情况下访问与Surface关联的EGL图像或本机缓冲区数据

这样我就可以缓存egl图像(根据EGL_ANDROID_image_native_buffer不需要EGL上下文)。 这也将以YUV格式缓存,这比我现在缓存的原始RGB纹理更具存储效率。

简答:不。

更长的答案: Surface封装了一个缓冲区队列 编辑: 此处详细解释了系统。)当您调用updateTexImage() ,如果有新的数据帧可用,则会丢弃头部的缓冲区,队列中的下一个缓冲区将变为当前状态。 调用updateTexImage()是查看连续帧所必需的; 没有机制可以检查不在头部的缓冲区。

一个SurfaceTexture包装的实例GLConsumer 该消费者要求制作者(视频解码器)以可以用作“硬件纹理”的格式生成数据,即设备的GL实现可以理解的东西。 它可能是也可能不是YUV。 更重要的是,消费者不要求缓冲区可用于“软件”,这意味着您不能假设您可以直接访问数据 - 您需要使用GLES。 (有关标志的完整列表,请参阅gralloc标头 。)

这里最好的是能够将缓冲区从BufferQueue的头部BufferQueue到单独的数据结构( BufferArrayList ?)而无需进行格式转换,但目前还没有类似的机制(Android 4.3)。 我不知道比你描述的更好的方式(共享EGL上下文等)。

更新:我的办公室伙伴提出了一个建议:使用着色器将缓冲区渲染为两个纹理,一个用于Y和用于CbCr(在GLES 3中,您可以使用RG纹理)。 这保留了GLES中的所有操作,而不会扩展为完整的RGB。 在内部,它会将MediaCodec输出转换为RGB并通过它进行两次研磨,但这可能比将其复制到用户空间并在CPU上自行完成更便宜。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM