美文网首页程序员
WebRTC android h264 编解码适配(二)

WebRTC android h264 编解码适配(二)

作者: 还我漂漂拳哒哒哒 | 来源:发表于2019-04-18 13:43 被阅读3次

    最近一段时间接到不少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<Integer> 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 h264 编解码适配(二)

        本文链接:https://www.haomeiwen.com/subject/denzwqtx.html