处理来自 Mediacodec 输出的帧并在 Android 上更新帧

Posted

技术标签:

【中文标题】处理来自 Mediacodec 输出的帧并在 Android 上更新帧【英文标题】:Processing Frames from Mediacodec Output and Update the Frames on Android 【发布时间】:2016-05-01 10:09:39 【问题描述】:

我正在做一个关于图像处理的项目。我实时接收原始 h264 视频流并使用 MediaCodec 对其进行解码。我已在 TextureView 或 SurfaceView 上成功显示解码的视频。现在我想处理每一帧,使用 OpenCV4android 对其进行处理,并在屏幕上显示更新的视频帧。我知道 OpenCV 有一个示例项目,它演示了如何处理来自手机摄像头的视频帧,但我想知道如果我有其他视频源该怎么做。

我还有一些关于 TextureView 的问题:

    SurfaceTextureListener 的 onSurfaceTextureUpdated() 有什么作用?如果我在这个函数中调用 getBitmap() ,那么这是否意味着我得到了视频的每一帧?那么 SurfaceTexture.onFrameAvailableListener 呢?

    是否可以使用隐藏的 TextureView 作为中间体,提取其帧进行处理并将其渲染回另一个表面,例如用于显示的 OpenGL ES 纹理?

【问题讨论】:

【参考方案1】:

Grafika 中使用相机作为输入的各种示例也可以处理来自视频流的输入。无论哪种方式,您都可以将视频帧发送到 Surface。

如果您想在软件中而不是在 GPU 上处理视频帧,事情就会变得更加困难。您必须在 Surface 上接收帧并将其复制到内存缓冲区,可能在此过程中执行 RGB 到 YUV 颜色转换,或者您必须从 MediaCodec 获取 YUV 缓冲区输出。后者比较棘手,因为可能有几种不同的格式,包括 Qualcomm 专有的平铺格式。

关于TextureView:

    onSurfaceTextureUpdated() 在 TextureView 接收到新帧时被调用。您可以使用getBitmap() 获取视频的每一帧,但您需要调整视频播放速度以匹配您的过滤器速度——如果您落后,TextureView 会丢帧。

    您可以通过将其他 View 元素放在其上来创建“隐藏的 TextureView”,但这很愚蠢。 TextureView 使用SurfaceTexture 将视频帧转换为 OpenGL ES 纹理,然后将它们渲染为绘制 View UI 的一部分。使用glReadPixels() 检索位图数据。您可以直接使用这些元素。 bigflake ExtractMpegFramesTest 证明了这一点。

【讨论】:

非常感谢先生。

以上是关于处理来自 Mediacodec 输出的帧并在 Android 上更新帧的主要内容,如果未能解决你的问题,请参考以下文章

制作一个 Mat 类型的对象数组。输出窗口显示相同的帧

android camera2 处理每一帧并显示其预览

是否可以使用 MediaProjection API 并在录制过程中处理每个录制的帧?

Java 多线程共享对象 - 需要设计模式

通过流获取帧并在屏幕上显示

spark中将每个组作为新数据帧并在循环中传递另一个函数的最佳方法是啥?