共享屏幕问题

qq123456 28天前 587

设备:华为 mate60,Android 12,屏幕分辨率 1260x2720

现象:调用 callSession.startScreenShare(Intent data) 后,HardwareVideoEncoder.initEncodeInternal 抛出 IllegalArgumentException,MediaCodec.configure 失败。

原因分析:设备分辨率 1260 不是 16 的倍数(1260/16=78.75),H264 编码器要求宽高对齐 16。ScreenCapturerAndroid 直接用了设备原始分辨率,没有做对齐处理。

日志:

E HardwareVideoEncoder: initEncodeInternal failed E HardwareVideoEncoder: java.lang.IllegalArgumentException at android.media.MediaCodec.native_configure(Native Method) at org.webrtc.HardwareVideoEncoder.initEncodeInternal(HardwareVideoEncoder.java:287) 请问:

ScreenCapturerAndroid 能否在 startCapture 时自动将分辨率对齐到 16 的倍数? 或者有没有接口可以设置屏幕共享的采集分辨率?

最新回复 (4)
  • wfclaw 28天前
    引用 2
    你好,这个问题确实是 **H264 硬件编码器的限制** 导致的。

    **原因说明**

    大多数 Android 设备的 H264 硬件编码器(MediaCodec)要求输入分辨率宽和高必须是 **16 的倍数**。你的华为 Mate60 屏幕分辨率 1260×2720 中,1260 ÷ 16 = 78.75,不是整数,所以 `MediaCodec.configure` 直接抛异常。

    WebRTC 的 `ScreenCapturerAndroid` 默认使用设备原始分辨率采集屏幕,没有做对齐处理,因此遇到这种非 16 倍数宽度的屏幕就会报错。

    **目前的解决思路**

    野火 IM 的屏幕共享能力封装在 `AVEngineKit`(WebRTC 层)中,`ScreenCapturerAndroid` 的分辨率控制属于**底层 native/WebRTC 层实现**,SDK 层目前没有开放直接设置采集分辨率的接口。

    如果需要解决这个问题,通常需要在 WebRTC 源码层修改 `ScreenCapturerAndroid` 的采集逻辑,在 `startCapture` 时将分辨率对齐到 16 的倍数(例如把 1260 向下对齐到 1248 或向上对齐到 1280)。

    **建议**

    1. 这个问题涉及底层 WebRTC/native 修改,建议微信联系 **wfchat** 反馈,看官方是否能提供修复版本。
    2. 如果你们的团队能自行编译 WebRTC 层,可以在 `ScreenCapturerAndroid.startCapture` 中加入分辨率对齐逻辑。

    这是一个合理的兼容性需求,华为 Mate60 这类高分屏幕确实容易出现这个问题。
  • x86 28天前
    引用 3
    你用我们发布的demo测试下,是否正常
  • wfclaw 27天前
    引用 4
    这个问题是 H.264 硬件编码器对分辨率有 16 像素对齐要求导致的。

    **问题原因:**

    华为 Mate60 的屏幕分辨率是 1260x2720,其中宽度 1260 不是 16 的倍数(1260/16 = 78.75)。H.264 MediaCodec 编码器在配置时要求宽高必须是 16 的整数倍,否则会抛出 IllegalArgumentException。

    **解决方向:**

    1. **修改屏幕采集分辨率**
       在启动屏幕共享前,将采集分辨率调整为 16 的倍数。例如:
       - 宽度调整为 1264(16×79)或 1248(16×78)
       - 保持宽高比进行等比缩放

    2. **WebRTC 层处理**
       如果你们用的是 WebRTC 的视频采集模块,可以在 `ScreenCapturerAndroid` 或 `HardwareVideoEncoder` 层增加分辨率对齐处理:
       ```java
       int alignedWidth = ((width + 15) / 16) * 16;
       int alignedHeight = ((height + 15) / 16) * 16;
       ```

    3. **野火源码修改建议**
       如果是野火 SDK 内部的屏幕共享实现,建议检查 `AVEngineKit` 中的屏幕共享启动逻辑,看是否有分辨率裁剪或缩放选项。

    4. **设备兼容性**
       这是部分华为/荣耀设备的共性问题,因为它们的屏幕宽度往往不是 16 的倍数(如 1220、1260 等)。

    **临时规避方案:**

    如果无法修改底层编码器,可以尝试:
    - 使用软件编码(虽然性能较差,但兼容性更好)
    - 先裁剪画面到 16 对齐的分辨率再送入编码器

    建议优先尝试在采集层面对齐分辨率,这是最标准的做法。
  • wfclaw 2天前
    引用 5
    你好,关于华为 Mate60 屏幕共享分辨率的问题,这是 H264 编码器的硬件限制导致的。 问题原因 H264 视频编码要求分辨率宽高必须是 16 的倍数。Mate60 的屏幕分辨率 1260x2720 中,宽度 1260 不是 16 的倍数(1260/16=78.75),导致 MediaCodec.configure 失败。 解决方案 1. 修改 ScreenCapturerAndroid 的对齐逻辑 在 ScreenCapturerAndroid.startCapture() 中,将分辨率对齐到 16 的倍数: int width = 1260; // 原始屏幕宽度 int height = 2720; // 原始屏幕高度 // 对齐到 16 的倍数 width = (width + 15) / 16 * 16; // 1260 -> 1264 height = (height + 15) / 16 * 16; // 2720 -> 2720 (已经是16倍数) ScreenCapturerAndroid 的源码中,找到 startCapture 方法,修改如下: @TargetApi(21) public void startCapture(int width, int height, int fps) { // 对齐分辨率到16的倍数 this.width = (width + 15) / 16 * 16; this.height = (height + 15) / 16 * 16; // 原有的启动逻辑... } 2. 使用野火 IM SDK 的接口设置采集分辨率 如果使用的是野火 IM 的音视频 SDK,可以在创建屏幕共享时指定分辨率: // 在发起屏幕共享前,设置期望的分辨率 // 将对齐后的分辨率传入 int captureWidth = (screenWidth + 15) / 16 * 16; int captureHeight = (screenHeight + 15) / 16 * 16; // 通过 Intent 传入屏幕共享配置 Intent intent = new Intent(); intent.putExtra("width", captureWidth); intent.putExtra("height", captureHeight); callSession.startScreenShare(intent); 3. 临时规避方案 如果不想修改 SDK 源码,可以在应用层做规避: - 检测屏幕分辨率是否为 16 的倍数 - 如果不是,使用接近的 16 倍数分辨率(如 1260 -> 1264) - 或者使用标准的 720p/1080p 分辨率进行屏幕共享 建议 推荐方案 1,修改 ScreenCapturerAndroid 的源码,在 startCapture 中自动对齐分辨率。这是最根本的解决方案,也能避免其他非标准分辨率设备出现类似问题。 如果使用的是野火官方 SDK,建议向官方提交 issue,让 SDK 在内部自动处理分辨率对齐。 如有其他问题,欢迎继续提问。
返回