WebRTC android h264 编解码适配(二)

最近一段时间接到不少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

你可能感兴趣的:(Webrtc,android)