WebRTC RTX

Table of Contents

在 WebRTC 中常用的 QoS 策略有

  1. 反馈:例如 PLI , NACK
  2. 冗余, 例如 FEC, RTX
  3. 调整:例如码率,分辨率及帧率的调整
  4. 缓存: 例如 Receive Adaptive Jitter Buffer, Send Buffer

这些措施的采用需要基于拥塞控制(congestion control) 及带宽估计(bandwidth estimation)技术, 不同的网络条件下需要采用不同的措施。

Webrtc 默认是开启 RTX (重传),它一般采用不同的 SSRC 进行传输

RTX 包的 Payload 在 RFC4588 中有详细描述,一般 NACK 和 Bandwidth Probe 也可能走 RTX 通道。

FEC 用作丢包恢复需要占用更多的带宽,即使 5% 的丢包需要几乎一倍的带宽,在带宽有限的情况下可能会使情况更糟。

RTX 不会占用太多的带宽,接收方发送 NACK 指明哪些包丢失了,发送方通过单独的 RTP 流(不同的 SSRC)来重传丢失的包,但是 RTX 至少需要一个 RTT 来修复丢失的包。

音频流对于延迟很敏感,而且占用带宽不多,所以用 FEC 更好。
视频流对于延迟没那么敏感,而且占用带宽很多,所以用 RTX 更好。

RTX packet 的处理

void RtxReceiveStream::SetAssociatedPayloadTypes(
    std::map<int, int> associated_payload_types) {
  RTC_DCHECK_RUN_ON(&packet_checker_);
  associated_payload_types_ = std::move(associated_payload_types);
}

void RtxReceiveStream::OnRtpPacket(const RtpPacketReceived& rtx_packet) {
  RTC_DCHECK_RUN_ON(&packet_checker_);
  if (rtp_receive_statistics_) {
    rtp_receive_statistics_->OnRtpPacket(rtx_packet);
  }
  rtc::ArrayView<const uint8_t> payload = rtx_packet.payload();

  if (payload.size() < kRtxHeaderSize) {
    return;
  }

  auto it = associated_payload_types_.find(rtx_packet.PayloadType());
  if (it == associated_payload_types_.end()) {
    RTC_DLOG(LS_VERBOSE) << "Unknown payload type "
                         << static_cast<int>(rtx_packet.PayloadType())
                         << " on rtx ssrc " << rtx_packet.Ssrc();
    return;
  }
  RtpPacketReceived media_packet;
  media_packet.CopyHeaderFrom(rtx_packet);

  media_packet.SetSsrc(media_ssrc_);
  media_packet.SetSequenceNumber((payload[0] << 8) + payload[1]);
  media_packet.SetPayloadType(it->second);
  media_packet.set_recovered(true);
  media_packet.set_arrival_time(rtx_packet.arrival_time());

  // Skip the RTX header.
  rtc::ArrayView<const uint8_t> rtx_payload = payload.subview(kRtxHeaderSize);

  uint8_t* media_payload = media_packet.AllocatePayload(rtx_payload.size());
  RTC_DCHECK(media_payload != nullptr);

  memcpy(media_payload, rtx_payload.data(), rtx_payload.size());

  media_sink_->OnRtpPacket(media_packet);
}

Reference

Comments |0|

Legend *) Required fields are marked
**) You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>
Category: Uncategorized