如何将Camera预览传递给MediaCodec.createInputSurface()创建的Surface?

时间:2013-10-28 19:06:09

标签: android camera surfaceview encoder mediacodec

理想情况下,我想完成两个目标:

  1. 通过CameraMediaCodec预览数据传递给Surface编码器。我可以使用Surface创建MediaCodec.createInputSurface(),但Camera.setPreviewDisplay()需要SurfaceHolder,而不是Surface
  2. 除了将Camera预览数据传递给编码器之外,我还想在屏幕上显示预览(这样用户实际上可以看到他们编码的内容)。如果没有涉及编码器,那么我会使用SurfaceView,但这似乎不适用于此方案,因为SurfaceView创建了自己的Surface,我认为我需要使用MediaCodec创建的那个。
  3. 我在线搜索了很多解决方案而没有找到解决方案。 bigflake.com上的一些示例似乎是朝着正确方向迈出的一步,但它们采用了一种方法,增加了一堆我想避免的EGL / SurfaceTexture开销。我希望有一个更简单的示例或解决方案,我可以让CameraMediaCodec更直接地讨论,而不涉及EGL或纹理。

1 个答案:

答案 0 :(得分:14)

从Android 4.3(API 18)开始,bigflake CameraToMpegTest方法是正确的方法。

EGL / SurfaceTexture开销目前是不可避免的,特别是对于你想在目标#2中做的事情。这个想法是:

  • 配置相机以将输出发送到SurfaceTexture。这使得GLES的Camera输出可用作“外部纹理”。
  • SurfaceTexture呈现给Surface返回的MediaCodec#createInputSurface()。这为视频编码器提供了支持。
  • 第二次渲染SurfaceTextureGLSurfaceView。这使它显示在实时预览上。

发生的唯一数据复制是由GLES驱动程序执行的,因此您正在进行硬件加速的blits,这将很快。

唯一棘手的一点是你希望外部纹理可用于两个不同的EGL上下文(一个用于MediaCodec,一个用于GLSurfaceView)。您可以在bigflake上的“Android Breakout游戏录制器补丁”示例中看到创建共享上下文的示例 - 它将游戏渲染两次,一次渲染到屏幕,一次渲染到MediaCodec编码器。

更新:这是在Grafika(“显示+捕捉相机”)中实现的。

更新:“show + capture camera”方法中的多上下文方法是somewhat flawed。 “连续捕获”活动使用普通的SurfaceView,并且能够使用单个EGL上下文进行屏幕渲染和视频录制。建议这样做。