Nic*_*lis 9 video android caching egl mediacodec
我正在编写一个Android应用程序,我需要缓存视频帧,以便我可以轻松地来回转移,几乎没有延迟.
现在我让android解码视频帧,方法是在MediaCodec对象的Configure调用中提供一个Surface 并调用releaseOutputBufferrender flag设置为true.
的唯一方法,我发现访问解码表面数据(除了解码所返回的字节缓冲区,其格式似乎是依赖于设备的)是调用updateTeximage在SurfaceTexture链接到表面,附接这对GL_TEXTURE_EXTERNAL_OES目标和它渲染到GL_TEXTURE2D目标纹理我创建我自己为了缓存它.
我想优化这个缓存过程,并能够解码不同线程上的帧.使用我当前的方法,这意味着我将不得不为视频解码器创建另一个EGL上下文,共享上下文等...
我的问题是:是否可以在不调用的情况下访问与Surface关联的EGL图像或本机缓冲区数据 updateTexImage?
这样我就可以缓存egl图像(根据不需要EGL上下文EGL_ANDROID_image_native_buffer).这也将以YUV格式缓存,这比我现在缓存的原始RGB纹理更具存储效率.
简短的回答:没有。
更长的答案:Surface封装了一个缓冲区队列。(编辑:现在在此处详细解释了系统。)当您调用 时updateTexImage(),如果有新的数据帧可用,则头部的缓冲区将被丢弃,队列中的下一个缓冲区变为当前。需要调用updateTexImage()才能看到连续的帧;没有用于检查不在头部的缓冲区的机制。
ASurfaceTexture包装了一个GLConsumer实例。这个消费者要求生产者(视频解码器)以一种可以用作“硬件纹理”的格式生成数据,即设备的 GL 实现可以理解的东西。它可能是也可能不是 YUV。更重要的是,消费者不要求缓冲区可用于“软件”,这意味着您不能假设您可以直接访问数据——您需要使用 GLES。(有关标志的完整列表,请参阅gralloc 标头。)
这里的好处是能够将缓冲区从头部复制BufferQueue到单独的数据结构(BufferArrayList?)而不进行格式转换,但目前还没有这样的机制(Android 4.3)。我不知道比您描述的更好的方法(共享 EGL 上下文等)。
更新:我的同事有一个建议:使用着色器将缓冲区渲染成两个纹理,一个用于 Y 和 CbCr(在 GLES 3 中,您可以使用 RG 纹理)。这将所有操作保留在 GLES 中,而无需扩展到完整的 RGB。在内部,它会将MediaCodec输出转换为 RGB 并对其进行两次研磨,但这可能比将其复制到用户空间并在 CPU 上自己执行要便宜。
| 归档时间: |
|
| 查看次数: |
3823 次 |
| 最近记录: |