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

And*_*ell 15 camera android encoder surfaceview mediacodec

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

  1. 通过Camera预览将预览数据传递给MediaCodec编码器Surface.我可以创建Surface使用MediaCodec.createInputSurface()但是Camera.setPreviewDisplay()需要a SurfaceHolder,而不是a Surface.
  2. 除了将Camera预览数据传递给编码器之外,我还想在屏幕上显示预览(这样用户实际上可以看到他们编码的内容).如果编码器没有参与,那么我会使用a SurfaceView,但这似乎不适用于这种情况,因为SurfaceView创建了自己的编码器Surface,我认为我需要使用创建的编码器MediaCodec.

我在网上搜索了很多解决方案,但没有找到解决方案.bigflake.com上的一些例子似乎是朝着正确方向迈出的一步,但他们采取了一种方法,增加了一堆我想避免的EGL/SurfaceTexture开销.我希望有一个简单的例子或解决方案,我能得到Camera并且MediaCodec不涉及EGL或纹理更直接交谈.

fad*_*den 14

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

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

  • 配置相机将输出发送到SurfaceTexture.这使得GLES的Camera输出可用作"外部纹理".
  • 渲染SurfaceTextureSurface返回的MediaCodec#createInputSurface().这为视频编码器提供了动力
  • 再渲染SurfaceTexture一次GLSurfaceView.这使它在显示屏上进行实时预览.

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

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

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

更新: "show + capture camera"方法中的多上下文方法存在一些缺陷."连续捕获"活动使用普通的SurfaceView,并且能够使用单个EGL上下文进行屏幕渲染和视频录制.这是推荐的.