flutter-webrtc / flutter-webrtc

WebRTC plugin for Flutter Mobile/Desktop/Web
MIT License
4.15k stars 1.13k forks source link

0.9.11版本iOS broadcast兼容性问题 #1151

Open JiaoLiu opened 2 years ago

JiaoLiu commented 2 years ago

Describe the bug iOS broadcast分享屏幕到mac端,无法显示。 To Reproduce 一台iphone 一台Mac 分别运行flutter_webrtc 0.9.11版本,iOS配置上broadcast, 比如: { 'audio': userScreen ? false : true, 'video': { 'deviceId': 'broadcast', 'width': {'min': '480', 'ideal': '720', 'max': '1080'}, 'height': {'min': '640', 'ideal': '1280', 'max': '1920'}, 'mandatory': { 'minFrameRate': '15', }, } }, iOS和Mac通话,分享屏幕后,Mac端无法显示。
Expected behavior Mac 端能显示iOS屏幕 Platform information

[✓] Xcode - develop for iOS and macOS (Xcode 13.0) [✓] Chrome - develop for the web [!] Android Studio (not installed) [✓] VS Code (version 1.69.2) [✓] Connected device (3 available)

JiaoLiu commented 2 years ago
image image
cloudwebrtc commented 2 years ago

你可以试试这个补丁,修改一下ios 和macOS 端的sdp https://github.com/flutter-webrtc/flutter-webrtc-demo/commit/48b6c64be4a560e6ea84e0a62c6f5ef93cd898e6

JiaoLiu commented 2 years ago

你可以试试这个补丁,修改一下ios 和macOS 端的sdp flutter-webrtc/flutter-webrtc-demo@48b6c64

修改SDP 可行,是否后续版本会在底层修复这个问题?上层不用replace

cloudwebrtc commented 2 years ago

此问题属于iOS 硬编,不同porfile-level-id 对应对应不用HW 编解码设置设置,最好还是在上层修改

JiaoLiu commented 2 years ago

此问题属于iOS 硬编,不同porfile-level-id 对应对应不用HW 编解码设置设置,最好还是在上层修改

上层修改是否需要区分操作系统,只对iOS、MAC 发起替换?能否在setLocalDescription 内部函数内进行替换,感觉设置 profile-level-id=42e032 这种对应用层不友好。

cloudwebrtc commented 2 years ago

实际操作由这些代码行 https://github.com/webrtc-sdk/webrtc/blob/m104_release/sdk/objc/components/video_codec/RTCVideoEncoderH264.mm#L176-L313

通过协商后的level 对HW Encoder 的kVTProfileLevelxxxx 参数设置,此设置与iOS 设备的硬件性能有关,因此实际修改会比较复杂。

// Extract VideoToolbox profile out of the webrtc::SdpVideoFormat. If there is no specific VideoToolbox profile for the 
// specified level, AutoLevel will be returned. The user must initialize the encoder with a resolution and framerate conforming 
// to the selected H264 level regardless.

这是代码里的注释,也就是从sdp 中获取的profile-level-id 需要对应视频Track的分辨率和帧率码率,我认为最简单的方式是在知道自己的分辨率码率情况下修改 profile-level 然后 setLocalDescription.

另外,强制使用vp8 不会有这样问题

上层修改是否需要区分操作系统,只对iOS、MAC 发起替换?

仅需要对iOS/macOS 进行设置

JiaoLiu commented 2 years ago

实际操作由这些代码行 https://github.com/webrtc-sdk/webrtc/blob/m104_release/sdk/objc/components/video_codec/RTCVideoEncoderH264.mm#L176-L313

通过协商后的level 对HW Encoder 的kVTProfileLevelxxxx 参数设置,此设置与iOS 设备的硬件性能有关,因此实际修改会比较复杂。

// Extract VideoToolbox profile out of the webrtc::SdpVideoFormat. If there is no specific VideoToolbox profile for the 
// specified level, AutoLevel will be returned. The user must initialize the encoder with a resolution and framerate conforming 
// to the selected H264 level regardless.

这是代码里的注释,也就是从sdp 中获取的profile-level-id 需要对应视频Track的分辨率和帧率码率,我认为最简单的方式是在知道自己的分辨率码率情况下修改 profile-level 然后 setLocalDescription.

另外,强制使用vp8 不会有这样问题

上层修改是否需要区分操作系统,只对iOS、MAC 发起替换?

仅需要对iOS/macOS 进行设置

怎么强制使用VP8? 好像没有接口参数可以选择编码方式。以前就遇到过通话质量不好,想尝试切换编码而不行。

cloudwebrtc commented 2 years ago

你可以尝试使用此工具类来修改sdp https://github.com/ionorg/ion-sdk-flutter/blob/master/lib/src/utils.dart

  void setPreferredCodec(RTCSessionDescription description) {
    var capSel = CodecCapabilitySelector(description.sdp!);
    var acaps = capSel.getCapabilities('audio');
    if (acaps != null) {
      acaps.codecs = acaps.codecs
          .where((e) => (e['codec'] as String).toLowerCase() == 'opus')
          .toList();
      acaps.setCodecPreferences('audio', acaps.codecs);
      capSel.setCapabilities(acaps);
    }

    var vcaps = capSel.getCapabilities('video');
    if (vcaps != null) {
      vcaps.codecs = vcaps.codecs
          .where((e) => (e['codec'] as String).toLowerCase() == 'vp8')
          .toList();
      vcaps.setCodecPreferences('video', vcaps.codecs);
      capSel.setCapabilities(vcaps);
    }
    description.sdp = capSel.sdp();
  }
JiaoLiu commented 2 years ago

你可以尝试使用此工具类来修改sdp https://github.com/ionorg/ion-sdk-flutter/blob/master/lib/src/utils.dart

  void setPreferredCodec(RTCSessionDescription description) {
    var capSel = CodecCapabilitySelector(description.sdp!);
    var acaps = capSel.getCapabilities('audio');
    if (acaps != null) {
      acaps.codecs = acaps.codecs
          .where((e) => (e['codec'] as String).toLowerCase() == 'opus')
          .toList();
      acaps.setCodecPreferences('audio', acaps.codecs);
      capSel.setCapabilities(acaps);
    }

    var vcaps = capSel.getCapabilities('video');
    if (vcaps != null) {
      vcaps.codecs = vcaps.codecs
          .where((e) => (e['codec'] as String).toLowerCase() == 'vp8')
          .toList();
      vcaps.setCodecPreferences('video', vcaps.codecs);
      capSel.setCapabilities(vcaps);
    }
    description.sdp = capSel.sdp();
  }

iOS相关设备都是优先使用的H264吗?按理说优先使用的VP8的话就不会有问题吧