使用 getInputImage 和 MediaCodec 进行编码

Using getInputImage with MediaCodec for encoding

背景:我进行视频文件解复用,解码视频轨道,对接收到的帧应用一些更改,再次解码和复用它们。

在 Android 中执行此操作的已知问题是供应商指定编码器/解码器颜色格式的数量。 Android 4.3 引入了表面以独立于设备,但我发现很难使用它们,因为我的框架更改例程需要 Canvas 才能写入。

自 Android 5.0 以来,灵活的 YUV420 颜色格式的使用大有可为。与用于解码的 getOutputImage 和用于编码的 getInputImage 一起,Image 对象可以用作从解码 MediaCodec 检索的格式。我使用 getOutputImage 进行解码工作,并且可以在 RGB 转换后可视化结果。对于编码 YUV 图像并将其排队到 MediaCodec(编码器)中,似乎缺少 link 但是:

从 MediaCodec 出列输入缓冲区后

int inputBufferId = encoder.dequeueInputBuffer (5000);

我可以访问

返回的正确图像
encoder.getInputImage (inputBufferId);

我填充了图像缓冲区 - 这也在工作,但我没有看到将输入缓冲区排队回编解码器进行编码的方法...只有

encoder.queueInputBuffer (inputBufferId, position, size, presentationUs, 0);

方法可用,但没有与图像匹配的方法。可以使用

检索调用所需的大小
ByteBuffer  byteBuffer = encoder.getInputBuffer (inputBufferId);

byteBuffer.remaining ();

但是除了调用 getInputImage() 之外,这似乎会搞砸编码器。

又遗漏了一份文档,还是我弄错了什么?

这确实有点问题-最简单的方法可能是计算Image中任何平面的起始指针到任何平面的最后一个字节之间的最大距离,但你需要本机代码这样做(为了获得直接字节缓冲区的实际指针值)。

第二种选择是如您所示使用 getInputBuffer,但有一个警告。首先调用 getInputBuffer 获取 ByteBuffer 并在其上调用 remaining()。 (或者 capacity() 效果更好?)。只有在这之后,调用 getInputImage。细节是当调用 getInputImage 时,getInputBuffer 返回的 ByteBuffer 无效,反之亦然。 (文档在 MediaCodec.getInputBuffer(int) 中说 "After calling this method any ByteBuffer or Image object previously returned for the same input index MUST no longer be used."。)