处理来自 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 上更新帧的主要内容,如果未能解决你的问题,请参考以下文章