如何获取用于MediaCodec编码器的步幅和Y平面对齐值

5
有关此主题的一些相关问题和讨论: 我正在将相机预览帧(NV21转换为NV12)提供给MediaCodec编码器(NV12又称COLOR_FormatYUV420SemiPlanar)。在一些运行Android版本低于4.3的使用QualComm编码器的设备上,看起来我必须进行一些输入帧处理,以便获得正确颜色的帧。
在运行Android 4.2.2的Sony Xperia ZR上,我必须添加Y平面对齐,以使其在几乎所有分辨率上正常工作。上面的代码添加了1024字节宽度不能被32整除和2048字节对齐的其他分辨率。这使得MediaCodec可以为所有可以被16整除的分辨率正确编码帧(除了176x144之外,其中UV平面看起来错位)。
int getYPadding() {
    if (mediaCodecInfo.getName().contains("OMX.qcom") && android.os.Build.VERSION.SDK_INT < 18) {
        if ((getWidth() % 32) != 0) {
            return (getWidth()*getHeight()) % 1024;
        } else {
            return (getWidth()*getHeight()) % 2048;
        }
    }
    return 0;
}

我尝试在运行相同的 Android 4.2.2 并使用 QualComm 编码器的 LG G2 上测试这个对齐方式,但似乎它不能正确工作。 UV 平面未对齐(帧底部有一个绿色条纹)。我无法计算适用于两种手机的填充。

我还可以访问运行 Android 4.3Sony Xperia Z1,采用了 QualComm 芯片组,看起来它没有这样的问题。每个分辨率的视频都很好,Y 平面无需任何对齐。

我知道这与硬件有关,可能很复杂,但由于我必须支持运行 Android 版本低于 4.3 的用户,所以我有一个问题。是否有可能通过程序确定编码器针对给定颜色格式期望的 Y 平面对齐和垂直/水平步幅值?

1个回答

8
问题简述:在 Android 4.3(API 18)之前,视频编码没有 CTS tests,导致 MediaCodec 在不同设备上的行为不一致,并且一些错误未被注意。EncodeDecodeTest测试可以对你所询问的功能进行测试,因此您可以可靠地向 4.3+ 设备提供 YUV 数据(尽管您仍然必须运行时检测它是否需要平面或半平面)。
针对您的具体问题,在旧的高通设备上,Y 平面需要在 2K 边界处对齐,这并不完全是您的代码正在执行的操作。对于 720p 视频,这自然发生(720*1280 == 450 * 2048),对于 176x144,则需通过增加 1280 来调整,以便从 25344 开始 UV 平面而不是 26624。您需要在缓冲区内设置绝对对齐方式,而不是固定量的填充--使用 uvoffset = (width*height + 2047) & ~2047
你需要检测编解码器供应商和Android软件版本,如果是Qualcomm且低于4.3版本,则需要进行调整。如果你的要求改变,并且可以针对API 18+,则这些问题将消失。(并且你可以使用Surface输入到MediaCodec,避免U/V交换问题,但根据你的需求可能并不有用。)

感谢您的回答,@fadden。您真是太棒了! :) 通过正确的对齐方式,我终于能够让它在Sony Xperia ZR的所有分辨率上正常工作了。在LG G2上仍然有一些问题,但我想我会将其整理成一个单独的问题,并附上一些截图。 - Andrey Chernih
1
此外,更有可能您希望将Y平面和UV平面对齐到2K边界。例如,对于一个480x480的RGB视频分辨率,传递给MediaCodec的yuv420Buffer应该是这个大小:YUVBufferSize + yOffset + uvOffset,即:(480 * 480 * 1.5)+(2048-((480 * 480)%2048))+(2048-((480 * 480 / 2)%2048))。我不知道LG_G2使用哪种编码器,如果是qcom-encoder,则可以尝试此逻辑。希望这可以帮助到您。 - Gagan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接