美文网首页WebRTC
WebRTC 发送端无法获取丢包率的解决办法,以及如何获取 RT

WebRTC 发送端无法获取丢包率的解决办法,以及如何获取 RT

作者: Gobert | 来源:发表于2019-05-07 18:04 被阅读1次

    WebRTC 自 M68 版本推出新的重载方法 GetStats 以后,使用新的接口便再也获取不到发送端的丢包率了(包括所有的 Native 端和 Web 端),原因是在 void OnStatsDelivered(const rtc::scoped_refptr<const RTCStatsReport>& report) 回调中返回的结构体 RTCStatsReport 中没有 packets_lost 的定义,只有 packets_sentframes_encoded 等信息,默认只能获取到发送的码率、帧率,而得不到丢包率、rtt 等判断网络质量的关键信息。不过 WebRTC 底层其实已经将丢包信息、rtt 等关键信息实时统计上来了,只是 PeerConnectionInterface 在获取 Statistics 时,没有将相关信息打包进 RTCStatsReport 结构体中,那么解决办法就是:在 RTCStatsReport 结构体中新增定义 packets_lostrtt_ms 字段,并为其赋值即可,下面为 Native 源码中需要修改的相关代码。

    增加 RTCOutboundRTPStreamStats 导出结构体字段定义

    数据发送方数据的统计记录在 Outbound 的结构中,即:RTCOutboundRTPStreamStats,为其在末尾新增两个字段:

    文件为: api/stats/rtcstats_objects.h

    class RTCOutboundRTPStreamStats final : public RTCRTPStreamStats {
     public:
      WEBRTC_RTCSTATS_DECL();
    
      RTCOutboundRTPStreamStats(const std::string& id, int64_t timestamp_us);
      RTCOutboundRTPStreamStats(std::string&& id, int64_t timestamp_us);
      RTCOutboundRTPStreamStats(const RTCOutboundRTPStreamStats& other);
      ~RTCOutboundRTPStreamStats() override;
    
      RTCStatsMember<uint32_t> packets_sent;
      RTCStatsMember<uint64_t> bytes_sent;
      // TODO(hbos): Collect and populate this value. https://bugs.webrtc.org/7066
      RTCStatsMember<double> target_bitrate;
      RTCStatsMember<uint32_t> frames_encoded;
        // 新增字段
      RTCStatsMember<int32_t> packets_lost;
      RTCStatsMember<int32_t> rtt_ms;
    };
    

    初始化新字段

    文件为:stats/rtcstats_objects.cc

    • 构造函数的初始化列表增加 RTCStatsMember 键值对的初始化
    RTCOutboundRTPStreamStats::RTCOutboundRTPStreamStats(
        std::string&& id, int64_t timestamp_us)
        : RTCRTPStreamStats(std::move(id), timestamp_us),
          packets_sent("packetsSent"),
          bytes_sent("bytesSent"),
          target_bitrate("targetBitrate"),
          frames_encoded("framesEncoded"),
          packets_lost("packetsLost"),
          rtt_ms("rttMs") {
    }
    
    • 拷贝构造函数初始化
    RTCOutboundRTPStreamStats::RTCOutboundRTPStreamStats(
        const RTCOutboundRTPStreamStats& other)
        : RTCRTPStreamStats(other),
          packets_sent(other.packets_sent),
          bytes_sent(other.bytes_sent),
          target_bitrate(other.target_bitrate),
          frames_encoded(other.frames_encoded),
          packets_lost(other.packets_lost),
          rtt_ms(other.rtt_ms) {
    }
    
    • outbound-rtp 中增加 Json 导出字段

    如果不增加,在上层 ToJoin 时是没有 packetLostrttMs 字段的。

    // clang-format off
    WEBRTC_RTCSTATS_IMPL(
        RTCOutboundRTPStreamStats, RTCRTPStreamStats, "outbound-rtp",
        &packets_sent,
        &bytes_sent,
        &target_bitrate,
        &frames_encoded,
        &packets_lost,
        &rtt_ms);
    // clang-format on
    

    为新字段赋值

    // Provides the media independent counters (both audio and video).
    void SetOutboundRTPStreamStatsFromMediaSenderInfo(
        const cricket::MediaSenderInfo& media_sender_info,
        RTCOutboundRTPStreamStats* outbound_stats) {
      RTC_DCHECK(outbound_stats);
      outbound_stats->ssrc = media_sender_info.ssrc();
      // TODO(hbos): Support the remote case. https://crbug.com/657856
      outbound_stats->is_remote = false;
      outbound_stats->packets_sent =
          static_cast<uint32_t>(media_sender_info.packets_sent);
      outbound_stats->bytes_sent =
          static_cast<uint64_t>(media_sender_info.bytes_sent);
      
      // 为新字段赋值
      outbound_stats->packets_lost =
          static_cast<int32_t>(media_sender_info.packets_lost);
      outbound_stats->rtt_ms =
          static_cast<int32_t>(media_sender_info.rtt_ms);
    }
    

    验证

    通过 PeerConnectionInterfaceGetStats 获取到的 RTCStatsReport 结构体 转换为 Json 字符串后,可以发现 outbound-rtp 节点中已经有了以上我们新增的 packetsLostrttMs 两个字段。

    [
        ..... 其它节点请忽略,这里只展示 outbound-rtp
        {
            "type": "outbound-rtp",
            "id": "RTCOutboundRTPAudioStream_856432637",
            "timestamp": 1557220118008000,
            "ssrc": 856432637,
            "isRemote": false,
            "mediaType": "audio",
            "trackId": "RTCMediaStreamTrack_sender_2",
            "transportId": "RTCTransport_audio_1",
            "codecId": "RTCCodec_audio_Outbound_111",
            "packetsSent": 484,
            "bytesSent": 81000,
            "packetsLost": 0,
            "rttMs": 13
        },
        {
            "type": "outbound-rtp",
            "id": "RTCOutboundRTPVideoStream_4038037569",
            "timestamp": 1557220118008000,
            "ssrc": 4038037569,
            "isRemote": false,
            "mediaType": "video",
            "trackId": "RTCMediaStreamTrack_sender_1",
            "transportId": "RTCTransport_audio_1",
            "codecId": "RTCCodec_video_Outbound_100",
            "firCount": 0,
            "pliCount": 1,
            "nackCount": 0,
            "qpSum": 2883,
            "packetsSent": 559,
            "bytesSent": 579220,
            "framesEncoded": 145,
            "packetsLost": 0,
            "rttMs": 13
        }
    ]
    

    解析 Json 字符串获取 packetsLost 前后两次的差值,除以时间差便可以获取到此时间段内的丢包率了。

    相关文章

      网友评论

        本文标题:WebRTC 发送端无法获取丢包率的解决办法,以及如何获取 RT

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