【问题标题】:The returned color format by selectColorFormat method is not correctselectColorFormat 方法返回的颜色格式不正确
【发布时间】:2015-02-18 13:36:33
【问题描述】:

我正在使用 bigflake 的 selectColorFormat 方法来获取 MediaCodec 编码器支持的输入颜色格式。它在除华为 Mate7 之外的一些测试设备上运行良好。返回的颜色格式是COLOR_FormatYUV420Planar。所以我把它配置为输入格式。但是编码时我发现输入缓冲区的容量不正确,应该是3*width*height/2。但是它比那个小。所以当queueInputBuffer调用时发生了错误。然后我观察了capabilities.colorFormats列表,它有十多种颜色格式。但是在普通设备上,该列表大约有2或3种颜色格式。然后我将颜色格式选择为COLOR_FormatYUV420SemiPlanar,它在Mate7上也很好用。

所以我怀疑这是Mate7版本的bug还是selectColorFormat方法的bug?

我发现 FAQ Q5 的答案有:

#20 COLOR_FormatYUV420PackedPlanar (also I420)
#39 COLOR_FormatYUV420PackedSemiPlanar (also NV12)
#0x7f000100 COLOR_TI_FormatYUV420PackedSemiPlanar (also also NV12) 

also I420 和 NV12 是什么意思?是说布局和 I420 或 NV12 都一样吗?因为我测试过 I420 和 NV12,但没有遇到过这三色设备。

selectColorFormat方法如下:

private MediaCodecInfo selectCodec(String mimeType) {
    int numCodecs = MediaCodecList.getCodecCount();
    for (int i = 0; i < numCodecs; i++) {
        MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
        if (!codecInfo.isEncoder()) {
            continue;
        }
        String[] types = codecInfo.getSupportedTypes();
        for (int j = 0; j < types.length; j++) {
            if (types[j].equalsIgnoreCase(mimeType)) {
                return codecInfo;
            }
        }
    }
    return null;
}

private int selectColorFormat(String mimeType) {
    MediaCodecInfo codecInfo = selectCodec(mimeType);
    int colorFormat = 0;
    MediaCodecInfo.CodecCapabilities capabilities =  codecInfo.getCapabilitiesForType(mimeType);
    for (int i = 0; i < capabilities.colorFormats.length; i++) {

        if (isRecognizedFormat(capabilities.colorFormats[i])) {
            colorFormat = capabilities.colorFormats[i];
            break;
        }
    }

    return colorFormat; 
}

private boolean isRecognizedFormat(int colorFormat) {
    switch (colorFormat) {
    // these are the formats we know how to handle for this test
    case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar:
    case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedPlanar:
    case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar:
    case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedSemiPlanar:
    case MediaCodecInfo.CodecCapabilities.COLOR_TI_FormatYUV420PackedSemiPlanar:
    return true;
    default:
    return false;
    }
}

【问题讨论】:

    标签: android yuv android-mediacodec


    【解决方案1】:

    所有运行 Android 4.3 (API 18) 或更高版本的设备都支持 I420 or NV12 formats 中的 YUV 输入。我可以自信地说出这一点,因为它们是所有“官方”Android 设备都必须通过的 CTS 测试的一部分。

    编解码器返回的颜色常量有多个映射到 I420 或 NV12 的值。您可以在 bigflake 示例代码中看到这是如何处理的(例如,EncodeDecodeTest 中的 generateFrame())。

    输入缓冲区容量应等于或略大于width * height * 3 / 2。如果您遇到缓冲区溢出异常,请在将数据复制到其中之前确保您是clearing the buffer

    【讨论】:

    • 感谢您的回复,fadden。但我确实在放入数据之前调用了缓冲区清除。
    • 并且调试时观察到的容量小于width*height*3/2。而在Android 4.3之前是什么情况?有没有颜色格式列表不包含I420或者NV12的情况?如果返回其他三种颜色格式,我是不是应该简单配置编码器对应的I420或者NV12,还是使用返回的格式进行配置,但向编码器提供 I420 或 NV12 格式的 YUV 数据?
    • Pre-Android 4.3,这不能保证有效,因为直到那时才添加 CTS 测试。您在哪个版本的 Android 上看到此行为?你能提供宽度/高度/格式/缓冲容量的例子吗? (记录 MediaFormat 对象并将输出包含在您的问题中。)
    • 是的,我稍后会发布,因为手机现在不在手边。但是我发现编解码器返回的颜色常数既有I420又有NV12,这正常吗?然后 I420 格式不好用,但 NV12 好用。
    • CTS 测试本质上要求设备支持 I420 格式或 NV12 格式,并且列表中的第一个可以正常工作。 CTS 测试不会详尽地使用宣传的颜色格式。我不知道设备宣传多种颜色格式有多普遍。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-28
    • 2021-12-14
    • 2020-01-24
    • 2021-08-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多