Android上的WebRTC——多设备如何启用硬件编码?(二)

可以看到,Android仅对Qualcomm和Exynos芯片组启用了硬件编码支持。那么为什么标准的WebRTC实现不支持其他芯片组呢?最有可能是因为不同制造商的硬件编解码器实现方式不尽相同,因为并非总能找到具体设备,所以这种不同通常到了生产阶段才能发现。

所有编解码器描述都存储在media_codecs.xml文件中,例如Pixel XLHUAWEI P8 lite。当我们使用MediaCodecList对象中的getCodecInfos()方法接收编解码器列表时,该文件经过解析后,会返回已存储的编解码器。MediaCodecListTest在CTS中介绍了此过程以及制造商填写此文件的准确性,其SLOC计数已从Android 4.3中的160增加到Android 10中的740。

在Badoo中,我们更改了isHardwareSupportedInCurrentSdkH264方法代码,并将编解码器的允许列表替换为WebRTC中列出的软件编解码器前缀的黑名单

static final String[] SOFTWARE_IMPLEMENTATION_PREFIXES = {“OMX.google.”, “OMX.SEC.”};

但我们确实需要考虑制造特性,才有可能实现对所有编解码器的支持。从专用于Android上硬件编码的describe-webrtc主题名称中,我们可以明显看出此过程中肯定会出错,大多数情况下都是编解码器配置阶段出问题。

编解码器配置参数

用于编码的编解码器初始化是这样的:

MediaCodec mediaCodec = createByCodecName(codecName);
MediaFormat format = MediaFormat.createVideoFormat(mime, width, height);
format.setInteger(MediaFormat.KEY_BIT_RATE, targetBitrateBps);
format.setInteger(MediaFormat.KEY_BITRATE_MODE, VIDEO_ControlRateConstant);
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, colorFormat);
format.setInteger(MediaFormat.KEY_FRAME_RATE, targetFps);
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, keyFrameIntervalSec);
mediaCodec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);

其中某些参数容易出错,这会导致编解码器配置过程中出现异常,从而破坏了应用程序的功能。因为编解码器本身无法正确执行,我们可能还需要根据不同的原因调整比特率。在WebRTC中,调整任务由BaseBitrateAdjuster执行,它具有两个子类:

  1. DynamicBitrateAdjuster :根据数据量调整比特率。
  2. FramerateBitrateAdjuster:根据帧速率调整比特率。

因此我们要为每个编解码器选择不同的比特率调整方法。接下来让我们看看怎么设置硬件编解码器初始化参数。

流分辨率

在收到每个编解码器的MediaCodecInfo对象后,我们可以在CodecCapabilities类中获取该功能的信息,来更详细地了解编解码器。通过这种方式,我们可以确定该编解码器是否支持选定的分辨率和帧速率。如果它确实支持这些参数,我们就可以安全地进行设置。

但在某些情况下,此规则并不适用。我们发现,当流分辨率不是4:3时,带有“ OMX.MARVELL”前缀的编解码器在某些情况下会出现编码错误,导致屏幕边缘出现绿条,而该编解码器本身声称支持选定的分辨率和帧速率。

比特率模式

所有视频编解码器的标准模式是恒定比特率。但是有时我们必须使用可变比特率:

format.setInteger(MediaFormat.KEY_BITRATE_MODE, VIDEO_ControlRateVariable);

需要使用可变比特率的情况是搭载展讯(现在称为Unisoc)芯片组的联想A1000设备上,该芯片组以“ OMX.sprd”开头。通过网络搜索,我们找到了一份六年前发布的研究Firefox OS的文章,该作者在文章中阐述了问题和解决方案。

色彩模式

在字节缓冲模式下使用编解码器时,我们需要选择适当的格式。通常是在以下功能的帮助下执行的:

@Nullable
static Integer selectColorFormat(int[] supportedColorFormats, CodecCapabilities capabilities) {
  for (int supportedColorFormat : supportedColorFormats) {
    for (int codecColorFormat : capabilities.colorFormats) {
      if (codecColorFormat == supportedColorFormat) {
        return codecColorFormat;
      }
    }
  }
  return null;
}

一般来说我们应该始终选择支持的第一种颜色格式。

但是该格式并不适用于以“ OMX.IMG.TOPAZ。”、“ OMX.hisi”或“OMX.k3.”开头的HUAWEI编解码器。经过一段时间的搜索,某中文论坛上的一篇帖子帮我们解决了这个问题——无论这些编解码器返回的格式如何,使用COLOR_FormatYUV420SemiPlanar格式就可以了。

文章地址:https://badootech.badoo.com/webrtc-on-android-how-to-enable-hardware-encoding-on-multiple-devices-5bd819c0ce5

原文作者:Ivan Dyatlov

填写常用邮箱,接收社区更新

WebRTC 中文社区由

运营