理想情况下,我想完成两个目标:
Camera
将MediaCodec
预览数据传递给Surface
编码器。我可以使用Surface
创建MediaCodec.createInputSurface()
,但Camera.setPreviewDisplay()
需要SurfaceHolder
,而不是Surface
。 Camera
预览数据传递给编码器之外,我还想在屏幕上显示预览(这样用户实际上可以看到他们编码的内容)。如果没有涉及编码器,那么我会使用SurfaceView
,但这似乎不适用于此方案,因为SurfaceView
创建了自己的Surface
,我认为我需要使用MediaCodec
创建的那个。我在线搜索了很多解决方案而没有找到解决方案。 bigflake.com上的一些示例似乎是朝着正确方向迈出的一步,但它们采用了一种方法,增加了一堆我想避免的EGL / SurfaceTexture开销。我希望有一个更简单的示例或解决方案,我可以让Camera
和MediaCodec
更直接地讨论,而不涉及EGL或纹理。
答案 0 :(得分:14)
从Android 4.3(API 18)开始,bigflake CameraToMpegTest方法是正确的方法。
EGL / SurfaceTexture开销目前是不可避免的,特别是对于你想在目标#2中做的事情。这个想法是:
SurfaceTexture
。这使得GLES的Camera输出可用作“外部纹理”。SurfaceTexture
呈现给Surface
返回的MediaCodec#createInputSurface()
。这为视频编码器提供了支持。SurfaceTexture
到GLSurfaceView
。这使它显示在实时预览上。发生的唯一数据复制是由GLES驱动程序执行的,因此您正在进行硬件加速的blits,这将很快。
唯一棘手的一点是你希望外部纹理可用于两个不同的EGL上下文(一个用于MediaCodec
,一个用于GLSurfaceView
)。您可以在bigflake上的“Android Breakout游戏录制器补丁”示例中看到创建共享上下文的示例 - 它将游戏渲染两次,一次渲染到屏幕,一次渲染到MediaCodec
编码器。
更新:这是在Grafika(“显示+捕捉相机”)中实现的。
更新:“show + capture camera”方法中的多上下文方法是somewhat flawed。 “连续捕获”活动使用普通的SurfaceView,并且能够使用单个EGL上下文进行屏幕渲染和视频录制。建议这样做。