【问题标题】:MediaCodec decoding h264 wrong on one deviceMediaCodec 在一台设备上解码 h264 错误
【发布时间】:2016-05-17 18:39:04
【问题描述】:

我正在尝试使用 Android 的 MediaCodec 接口解码 h.264 流。在我的测试设备上一切正常,但在我无法访问的一台客户设备(Samsung Tab S)上出现奇怪的问题。

当我解码流时,我不发送任何 SPS/PPS NAL 或初始帧。我刚开始从实时流中推送数据,切成以 0x09 NAL 结尾的块,解码器会很快很好地同步自身而不会出现问题。

至少这个设备的问题是,当我从解码器获得 BufferInfo 时,它会声称它解码了 1413120 字节的数据,但缓冲区大小仅为 1382400!所以当然,如果我什至尝试从缓冲区中取出这么多数据,它就会崩溃。

视频是 1280x720 并被解码为 NV12,所以缓冲区大小刚刚好。报告的解码输出大小不是。如果我将大小强制为 1382400 并将 NV12 转换为 RGB,我会得到几乎正确的图片。前 32 行具有强烈的绿色,蓝色通道偏移了很多。这意味着 UV 块在此设备上部分解码错误。

以前有人遇到过这种问题吗?我已经记录了来自该特定设备的原始 h264 流,它播放得很好,没有绿色块或颜色偏移。

我真的应该在开始流式传输之前设置 SPS/PPS 和初始帧吗?该流似乎包含所需的一切,因为解码器意识到分辨率是正确的,在我测试过的所有其他设备上设置缓冲区和解码,除了这个。所以我只是想知道三星是否有什么特别的事情发生。

解码相同流的另一个应用程序显示它没有问题,但据我所知,他们在内部使用 ffmpeg,而不是 MediaCodec。如果可能,我宁愿使用内置的系统编解码器。

这是一个结果示例。不要只有流的图像,请注意框架是旋转的。绿色区域的 Y 分量很好,在右边的白色块上可以清楚地看到蓝移。

编辑:即使我使用 csd-0 中的 SPS/PPS 块启动解码器,颜色问题仍然存在。所以不是因为这个。

还设法用另一台设备测试了确切的流。没有绿条,没有颜色变化。因此,该特定设备/型号中的编解码器存在问题。

【问题讨论】:

  • 尝试设置 sps/pps,因为我们不能期望在所有设备上都有相同的行为。设置并检查,它可能会有所帮助。
  • 嗯,所以要澄清MediaCodec.BufferInfo.size 是1413120 但ByteBuffer 的容量只有1382400?输出MediaFormat 包含什么?
  • 是的,它们在访问 NAL 的方式/时间方面有所不同(例如,您可以仅通过 csd-0csd-0csd-1 通过 @ 传递 SPS/PPS 987654330@,或作为带有CODEC_CONFIG 标志的普通输入缓冲区)。此外,如果传输没有清楚地指示帧边界,如何处理多个 NAL 当然也是一个问题。但无论如何,我认为它们都是与格式错误的像素数据布局完全正交的问题,就像您看到的问题(以及 CTS 测试试图处理的问题) - 我怀疑这样的事情会相关。
  • 无法访问该设备确实让事情变得更加困难,对不起,我忘记了你有这种情况。 (我还检查了developer.samsung.com 没有任何 Galaxy Tab S,只有 Tab S2,可用于远程测试,否则这是一个选项。)
  • 是的,SPS/PPS 不应与此相关。如果您有任何类型的可见解码器输出,则解码器已经以某种方式接收到 SPS/PPS(并且改变它的传递方式并不重要) - 没有这个,根本不可能获得任何合理的解码输出。

标签: android video h.264 android-mediacodec


【解决方案1】:

我过去也遇到过类似的问题(特别是在三星设备上),如果我没记错的话,那是因为缺少 SPS/PPS 数据。如果您想要一致的结果,您必须输入 SPS/PPS 数据。

不是直接解决您的问题,但可能的解决方法是在该特定设备上运行时使用替代解码器(如果存在)。

我不确定你是如何实例化你的解码器的,但人们经常像这样使用 mime 类型:

decoder = MediaCodec.createDecoderByType("video/avc");

然后设备将选择首选解码器(可能是硬件)。

您也可以像这样实例化特定的解码器:

decoder = MediaCodec.createByCodecName("OMX.google.h264.decoder");

// OR

decoder = MediaCodec.createByCodecName("OMX.qcom.video.decoder.avc");

根据我的经验,大多数设备至少有 2 个不同的 H264 解码器可用,您可能会发现此设备上的替代解码器可以正常运行。

您可以使用以下代码列出所有可用的编解码器:

static MediaCodecInfo[] getCodecs() {

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        MediaCodecList mediaCodecList = new MediaCodecList(MediaCodecList.ALL_CODECS);
        return mediaCodecList.getCodecInfos();
    } else {
        int numCodecs = MediaCodecList.getCodecCount();
        MediaCodecInfo[] mediaCodecInfo = new MediaCodecInfo[numCodecs];

        for (int i = 0; i < numCodecs; i++) {
            MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
            mediaCodecInfo[i] = codecInfo;
        }

        return mediaCodecInfo;
    }       
}

【讨论】:

    【解决方案2】:

    在尝试使用 h265 解码器在 480p 和 1440p 层上播放 Amazon Fire Stick (AFTMM) 时,我们遇到了类似的内存不足问题。 SDR 和 HDR 播放都出现了问题。虽然这绝对是一个特定于设备的问题,但可能有一些解决方法,例如在编码和/或减少 CRF 时减少 ref 值。这对我们有用。

    【讨论】:

      猜你喜欢
      • 2018-10-17
      • 1970-01-01
      • 2013-12-26
      • 2014-02-06
      • 2013-04-25
      • 1970-01-01
      • 2021-08-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多