简体   繁体   English

MediaCodec 在一台设备上解码 h264 错误

[英]MediaCodec decoding h264 wrong on one device

I'm trying to decode h.264 stream using Android's MediaCodec interface.我正在尝试使用 Android 的 MediaCodec 接口解码 h.264 流。 Everything is working just fine on my test devices, but on one customer device that I dont' have access to (Samsung Tab S) there are strange issues.在我的测试设备上一切正常,但在我无法访问的一台客户设备(Samsung Tab S)上出现了奇怪的问题。

When I decode the stream I don't send any SPS/PPS NALs or an initial frame.当我解码流时,我不发送任何 SPS/PPS NAL 或初始帧。 I just start pushing the data from the live stream, chopped into blocks ending with a 0x09 NAL and the decoder will synchronize itself nicely without problems quite quickly.我刚开始从实时流中推送数据,将其切成以 0x09 NAL 结尾的块,解码器将很好地同步自身而不会很快出现问题。

The issue with at least this one device is that when I get a BufferInfo from the decoder it will claim it decoded 1413120 bytes of data, but the buffer size is only 1382400!至少这台设备的问题是,当我从解码器获取 BufferInfo 时,它会声称它解码了 1413120 字节的数据,但缓冲区大小仅为 1382400! So of course if I even try to get that much data out of the buffer it will crash.所以当然,如果我什至试图从缓冲区中获取那么多数据,它就会崩溃。

The video is 1280x720 and is decoded into NV12, so the buffer size is just fine.视频为 1280x720,解码为 NV12,所以缓冲区大小刚刚好。 The reported decoded output size isn't.报告的解码输出大小不是。 If I force the size as 1382400 and convert the NV12 into RGB I get almost correct picture.如果我将大小强制为 1382400 并将 NV12 转换为 RGB,我会得到几乎正确的图片。 The first 32 lines have a strong green color and the blue channel is shifted by quite a lot.前 32 条线具有强烈的绿色,蓝色通道偏移了很多。 This means that the UV block is decoded partially wrong on this device.这意味着 UV 块在此设备上部分解码错误。

Has anyone run into this kind of an issue before?有没有人遇到过这种问题? I have recorded the raw h264 stream from that specific device and it plays just fine with no green blocks or color shifts.我已经记录了来自该特定设备的原始 h264 流,它播放得很好,没有绿色块或颜色偏移。

Should I really set up SPS/PPS and an initial frame before starting the streaming?我真的应该在开始流式传输之前设置 SPS/PPS 和初始帧吗? The stream seems to contain everything needed since the decoder realizes the resolution to be correct, sets up buffers and decodes on every other device I've tested except this one.该流似乎包含所需的一切,因为解码器意识到分辨率是正确的,在我测试过的除此之外的所有其他设备上设置缓冲区和解码。 So I'm just wondering if Samsung has something special going on.所以我只是想知道三星是否有什么特别之处。

Another application decoding the same stream shows it without issues, but as far as I know they use ffmpeg internally, not MediaCodec.另一个解码相同流的应用程序显示它没有问题,但据我所知,他们在内部使用 ffmpeg,而不是 MediaCodec。 I would rather use built-in system codecs if possible.如果可能,我宁愿使用内置系统编解码器。

Here is an example of the result.这是结果的一个例子。 Don't have an image of just the stream, do note that the frame is rotated.不要只有流的图像,请注意框架已旋转。 The Y component in the green area is just fine and on the white block on the right you can clearly see the blue shift.绿色区域中的 Y 分量很好,在右侧的白色块上,您可以清楚地看到蓝移。

在此处输入图片说明

Edit: Even if I start the decoder with the SPS/PPS blocks in csd-0 the color problems persist.编辑:即使我使用 csd-0 中的 SPS/PPS 块启动解码器,颜色问题仍然存在。 So it isn't due to that.所以不是因为这个。

Also managed to test the exact stream with another device.还设法用另一台设备测试了确切的流。 No green bar, no color shifts.没有绿条,没有颜色变化。 So it's a problem with the codec in that particular device/model.因此,该特定设备/型号中的编解码器存在问题。

I had similar issues in the past (specifically on Samsung devices) and if I remember correctly it was due to the missing SPS/PPS data.我过去遇到过类似的问题(特别是在三星设备上),如果我没记错,那是由于缺少 SPS/PPS 数据。 You must feed in the SPS/PPS data if you want consistent results.如果您想要一致的结果,您必须输入 SPS/PPS 数据。

Not a direct solution to your issue but a possible workaround is to use an alternative decoder (if present) when running on that particular device.不是您问题的直接解决方案,但可能的解决方法是在该特定设备上运行时使用替代解码器(如果存在)。

I'm not sure how you are instantiating your decoder but often people use the mime type like so:我不确定你是如何实例化你的解码器的,但人们经常像这样使用 mime 类型:

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

The device will then choose the preferred decoder (probably hardware).然后设备将选择首选解码器(可能是硬件)。

You can alternatively instantiate a specific decoder like so:您也可以像这样实例化特定的解码器:

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

// OR

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

In my experience, most devices have at least 2 different H264 decoders available and you may find that an alternative decoder on this device performs without faults.根据我的经验,大多数设备至少有 2 种不同的 H264 解码器可用,您可能会发现该设备上的替代解码器可以正常运行。

You can list all the available codecs using the following code:您可以使用以下代码列出所有可用的编解码器:

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;
    }       
}

We faced a similar issue of Out of memory when trying to play on Amazon Fire stick (AFTMM) using h265 decoder at 480p and 1440p layer.在尝试使用 480p 和 1440p 层的 h265 解码器在 Amazon Fire Stick (AFTMM) 上播放时,我们遇到了类似的内存不足问题。 The issue was coming for both SDR and HDR playback. SDR 和 HDR 播放都出现了问题。 While this definitely is a device specific issue, there could be some workarounds like reducing the ref value while encoding and/or reducing CRF as well.虽然这绝对是设备特定的问题,但可能有一些解决方法,例如在编码和/或减少 CRF 时减少 ref 值。 This works for us.这对我们有用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM