使用MediaCodec和Surface

时间:2015-09-07 13:31:34

标签: android surfaceview mediacodec encoder decoder

我一直在通过MediaCodec将视频直接渲染到我的UI中从SurfaceView获取的Surface。这很有效。

我现在正尝试将MediaCodec用作编码器。作为测试,我想渲染到Surface(如上所述)并通过配置为编码器的MediaCodec的不同实例进行环回。

我看到了编码器的createInputSurface()方法。我想我希望编码器创建这个表面然后让解码器MediaCodec使用它作为要绘制的表面。首先,这可能吗?

其次,我不确定如何从编码器创建的Surface创建SurfaceView。我只从SurfaceView中提取了一个Surface,而我从文档中看不到如何反向执行。

1 个答案:

答案 0 :(得分:7)

表面是"生产者"生产者 - 消费者安排的一面。一般来说,API以消费者为中心,创建两端,然后将生产者界面(Surface)交给您。

因此,对于SurfaceView或MediaCodec编码器,您可以创建对象,并获取其Surface。然后使用Canvas,OpenGL ES或MediaCodec解码器向它们发送图形数据缓冲区。

无法使用编码器的输入Surface并将其用作SurfaceView的显示器Surface - 它们是两个不同的管道。 SurfaceView的消费者在系统合成器(SurfaceFlinger)中,这就是为什么你必须等待"表面创建"回击起火。 MediaCodec编码器的消费者处于mediaserver过程中,尽管隐藏了异步性。

将MediaCodec解码器输出发送到SurfaceView非常简单,将输出发送到MediaCodec编码器也是如此。如您所推测的那样,只需将编码器的输入Surface传递给解码器即可。生活变得有趣的地方就是你想要同时做这两件事。

Surface下面的代码(称为BufferQueue)应该能够(从Lollipop开始)进行多路复用,但我不知道Lollipop中的API会向应用程序公开该功能。这意味着你很难坚持做事。

困难的方法是创建一个SurfaceTexture(a / k / a GLConsumer),它是管道的消费者端。从那里你可以使用sole constructor创建一个Surface。你把它交给MediaCodec解码器。现在,每个出来的帧都将被SurfaceTexture转换为GLES纹理。您可以将它们渲染到SurfaceView和编码器的输入Surface。

您可以在Grafika中找到各种示例,并在graphics architecture doc中找到有关机制的更长解释。