最近一段时间接到不少android客户反馈,看到对方的视频是绿屏,还有一些反馈对方看不到自己的视频,由于我们使用的是h264硬编解码,首先想到的是编解码这块出现了问题。
先看绿屏的问题,收集了下反馈机型,主要集中在cpu为联发科MT6735至MT6755的机器上,使用的硬件编解码器是OMX.MTK.**,随便在云真机测试平台找了台机器-华为畅享5(TIT-AL00)测试,果然是绿屏。打开webrtc全日志
Logging.enableTracing(
"logcat:",
EnumSet.of(Logging.TraceLevel.TRACE_ALL))
Logging.enableLogToDebugOutput(Logging.Severity.LS_SENSITIVE)
再编译个版本在华为畅享5上跑,日志下载下来,逐条分析,有一段日志很奇怪:
04-12 15:58:45.440 W/hwcomposer( 260): [BLT] Not support color range(0), use default BT601
04-12 15:58:45.440 W/hwcomposer( 260): [BLT] Not support color range(0), use default BT601
hwcomposer是android4.0后推出的新特性,它定义了一套HAL接口,然后各大厂商需要根据自己硬件特性去实现,其实就是一些图层处理功能,这里报了color不支持。下面我们追踪一下源码,看看webrtc 解码中使用了哪些color
private static @Nullable DecoderProperties findDecoder(
String mime, String[] supportedCodecPrefixes) {
...
// Check if codec supports either yuv420 or nv12.
CodecCapabilities capabilities;
try {
capabilities = info.getCapabilitiesForType(mime);
} catch (IllegalArgumentException e) {
Logging.e(TAG, "Cannot retrieve decoder capabilities", e);
continue;
}
for (int colorFormat : capabilities.colorFormats) {
Logging.v(TAG, " Color: 0x" + Integer.toHexString(colorFormat));
}
for (int supportedColorFormat : supportedColorList) {
for (int codecColorFormat : capabilities.colorFormats) {
if (codecColorFormat == supportedColorFormat) {
// Found supported HW decoder.
Logging.d(TAG, "Found target decoder " + name + ". Color: 0x"
+ Integer.toHexString(codecColorFormat));
return new DecoderProperties(name, codecColorFormat);
}
}
}
}
...
}
这里会遍历解码器支持的所有colorFormat,然后看支持的格式是否在supportedColorList列表中,直到匹配上,supportedColorList是以白名单的形式存在的,如下:
private static final List supportedColorList = Arrays.asList(
CodecCapabilities.COLOR_FormatYUV420Planar, CodecCapabilities.COLOR_FormatYUV420SemiPlanar,
CodecCapabilities.COLOR_QCOM_FormatYUV420SemiPlanar,
COLOR_QCOM_FORMATYVU420PackedSemiPlanar32m4ka, COLOR_QCOM_FORMATYVU420PackedSemiPlanar16m4ka,
COLOR_QCOM_FORMATYVU420PackedSemiPlanar64x32Tile2m8ka,
COLOR_QCOM_FORMATYUV420PackedSemiPlanar32m);
遍历的是硬件支持的colorFormat,看上去没有任何问题。再回头看看运行日志,看看使用了哪个colorFormat
04-12 15:58:27.286 I/MediaCodecVideoDecoder( 2452): MediaCodecVideoDecoder: Java initDecode: VIDEO_CODEC_H264 : 320 x 240. Color: 0x13. Use Surface: true
日志显示使用了0x13的Color,对应supportedColorList里面的CodecCapabilities.COLOR_FormatYUV420Planar,也就是第一个,先把这个colorFormate屏蔽掉试试
private static @Nullable DecoderProperties findDecoder(
String mime, String[] supportedCodecPrefixes) {
...
// Check if codec supports either yuv420 or nv12.
CodecCapabilities capabilities;
try {
capabilities = info.getCapabilitiesForType(mime);
} catch (IllegalArgumentException e) {
Logging.e(TAG, "Cannot retrieve decoder capabilities", e);
continue;
}
for (int colorFormat : capabilities.colorFormats) {
Logging.v(TAG, " Color: 0x" + Integer.toHexString(colorFormat));
}
for (int supportedColorFormat : supportedColorList) {
for (int codecColorFormat : capabilities.colorFormats) {
//屏蔽掉解码器为OMX.MTK并且颜色格式为CodecCapabilities.COLOR_FormatYUV420Planar
if (codecColorFormat == supportedColorFormat && (!name.startsWith("OMX.MTK") ||
supportedColorFormat != CodecCapabilities.COLOR_FormatYUV420Planar)) {
// Found supported HW decoder.
Logging.d(TAG, "Found target decoder " + name + ". Color: 0x"
+ Integer.toHexString(codecColorFormat));
return new DecoderProperties(name, codecColorFormat);
}
}
}
}
...
}
编译好再在华为畅享5(TIT-AL00)测试,一切正常了,可以看到对方图像了。
受到启发,再来看看对方看不到我的情况,会不会也是跟绿屏的情况一样,是编码颜色格式的问题呢,先收集一下出问题的机型,主要集中在cpu为:华为kirin930 华为kirin935,对应编码器为OMX.IMG.TOPAZ,测试机器:华为p8,通过查看运行日志使用的colorFormate也是0x13,也就是supportedColorList里面的CodecCapabilities.COLOR_FormatYUV420Planar,对编码部分做同样的处理,即:屏蔽掉编码器为OMX.IMG.TOPAZ并且颜色格式为CodecCapabilities.COLOR_FormatYUV420Planar的情况,代码跟绿屏完全类似,这里就不贴出来了,编译好,再在p8上跑,正常了,对方能看到我的视频了。
至此,两种问题都解决了,但是原因呢,明明api支持这种颜色格式啊,实际确不支持,这不坑爹吗,也许只有手机厂商自己能解释清楚了。
欢迎关注公众号:
或者微信搜索公众号:webrtc home