解码器的输出表面如何传递到编码器的输入表面?

Posted

技术标签:

【中文标题】解码器的输出表面如何传递到编码器的输入表面?【英文标题】:How does an output surface of a Decoder is passed to an input surface of an Encoder? 【发布时间】:2016-06-07 18:00:45 【问题描述】:

我正在尝试了解表面对表面方法如何与 MediaCodec 配合使用。在仅 ByteBuffer 的方法中,解码的数据放置在 OutputBuffers 中。可以手动处理这些未编码的数据,然后将其传递给 Encoder 的 InputBuffers。

如果我们看一个来自 android MediaCodec CTS 的示例,它使用表面到表面的方法在解码器和编码器之间传递数据,我们将解码器配置为将解码后的数据输出到名为 outputSurface 的表面上,我们配置用于在称为 inputSurface 的 Surface 上接收数据的编码器。

在文档中,在Encoder的配置中createInputSurface和这个surface的使用是这样描述的:

createInputSurface():请求 Surface 用作编码器的输入,代替输入缓冲区。

换句话说,这在 CTS 示例中的 ByteBuffers 声明中可见:编码器没有 InputBuffers。你有:

DecoderInputBuffers(从 MediaExtractor 接收视频轨道样本) DecoderOutputBuffers(输出拉取解码的 yuv 帧) 什么都没有。 (嗯...输入表面。) EncoderOutputBuffers(输出以拉取重新编码的内容以传递给复用器)

您无需在 Encoder InputBuffers 中排队数据,而是使用以下代码行:

outputSurface.awaitNewImage();
outputSurface.drawImage();
inputSurface.setPresentationTime(videoDecoderOutputBufferInfo.presentationTimeUs * 1000);
inputSurface.swapBuffers();

Decoder 的 ouputSurface 内容是如何传递给 Encoder 的 inputSurface 的?幕后具体发生了什么?

【问题讨论】:

从这里开始:source.android.com/devices/graphics/architecture.html 【参考方案1】:

解码器/编码器的输出/输入Surface分别是一个特殊配置物理上连续保留等)一块内存哪些专用硬件(例如,GPUs、硬件(加速)编解码器)或软件模块可以以最适合性能需求的方式使用(通过使用硬件加速、DMA 等功能)。

更具体地说,例如,在当前上下文中,解码器的输出 Surface 由 SurfaceTexture 支持,因此它可以在 OpenGL environment 中用作 external 纹理在渲染到 Surface 之前进行任何类型的处理,编码器可以从中读取和编码以创建最终视频帧。

并非巧合,OpenGL 只能渲染到这样的Surface

所以解码器充当原始视频帧的提供者表面(纹理)载体 , OpenGL medium 将其渲染到 Encoder 的 input Surface 这是 destination 用于(待编码的)视频帧。

为了进一步满足您的好奇心,请查看Editing frames and encoding with MediaCodec了解更多详情。

[编辑]

您可以查看grafikaContinuous Camera 或Show + capture camera 中的子项目,它们当前将相机帧(馈送到 SurfaceTexture)渲染到视频(和显示)。所以本质上,唯一的变化是 MediaCodec 将帧馈送到 SurfaceTexture 而不是相机。

Google CTS DecodeEditEncodeTest 做的完全一样,可以作为参考,让学习曲线更平滑。

正如fadden指出的那样,从最基本的开始使用Android graphics tutorials

【讨论】:

哇,谢谢!但是输入表面到底在哪里连接到解码器表面?通过 EglContext? 您需要做什么?可以渲染解码为 Surface 纹理的帧(如果需要通过 OpenGL 以任何方式进行操作。请检查更新的答案 其实,我并不是想有所成就。我浏览了大部分现有文档和测试,并开发了一个相当丰富的视频编辑器(在 Xamarin.Android 中)。但我想要的是能够“解释”它为什么起作用。为什么两个表面都可以通信。不过,Fadden 的链接似乎正是我需要阅读的内容。 是的,它是 Fadden 自己编写的关于图形子系统架构的唯一正确(更不用说,写得非常好)的文档。 :) 嗨!我正在尝试实现类似的东西(使用 MediaProjection 来获取屏幕录制只需要记录用户选择的区域)。我的理解是我必须对 SurfaceTexture 应用转换。但是我应该在哪里以及如何为编码器创建表面。我需要将这个输入表面提供给 VirtualDisplay 以获取帧。我按照 grafika 示例录制屏幕。我现在正在尝试一个星期。能否请你帮忙。谢谢!

以上是关于解码器的输出表面如何传递到编码器的输入表面?的主要内容,如果未能解决你的问题,请参考以下文章

ffmpeg hwaccel 没有剩下的解码器表面

Android:如何将解码器集成到多媒体框架

是否可以共享 DXVA 表面?

自编码器

视频解码器 使用 MediaCodec 配置

将 CNN 编码器的输出传递给 convLSTM 层。 (火炬)