tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

flexfec_sender.cc (8299B)


      1 /*
      2 *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
      3 *
      4 *  Use of this source code is governed by a BSD-style license
      5 *  that can be found in the LICENSE file in the root of the source
      6 *  tree. An additional intellectual property rights grant can be found
      7 *  in the file PATENTS.  All contributing project authors may
      8 *  be found in the AUTHORS file in the root of the source tree.
      9 */
     10 
     11 #include "modules/rtp_rtcp/include/flexfec_sender.h"
     12 
     13 #include <cstdint>
     14 #include <cstring>
     15 #include <list>
     16 #include <memory>
     17 #include <optional>
     18 #include <utility>
     19 #include <vector>
     20 
     21 #include "absl/strings/string_view.h"
     22 #include "api/array_view.h"
     23 #include "api/environment/environment.h"
     24 #include "api/rtp_parameters.h"
     25 #include "api/units/data_rate.h"
     26 #include "api/units/time_delta.h"
     27 #include "api/units/timestamp.h"
     28 #include "modules/include/module_fec_types.h"
     29 #include "modules/rtp_rtcp/include/rtp_header_extension_map.h"
     30 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
     31 #include "modules/rtp_rtcp/source/forward_error_correction.h"
     32 #include "modules/rtp_rtcp/source/rtp_header_extension_size.h"
     33 #include "modules/rtp_rtcp/source/rtp_header_extensions.h"
     34 #include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
     35 #include "rtc_base/checks.h"
     36 #include "rtc_base/logging.h"
     37 #include "rtc_base/race_checker.h"
     38 #include "rtc_base/synchronization/mutex.h"
     39 
     40 namespace webrtc {
     41 
     42 namespace {
     43 
     44 // Let first sequence number be in the first half of the interval.
     45 constexpr uint16_t kMaxInitRtpSeqNumber = 0x7fff;
     46 
     47 // See breakdown in flexfec_header_reader_writer.cc.
     48 constexpr size_t kFlexfecMaxHeaderSize = 32;
     49 
     50 // Since we will mainly use FlexFEC to protect video streams, we use a 90 kHz
     51 // clock for the RTP timestamps. (This is according to the RFC, which states
     52 // that it is RECOMMENDED to use the same clock frequency for FlexFEC as for
     53 // the protected media stream.)
     54 // The constant converts from clock millisecond timestamps to the 90 kHz
     55 // RTP timestamp.
     56 const int kMsToRtpTimestamp = kVideoPayloadTypeFrequency / 1000;
     57 
     58 // How often to log the generated FEC packets to the text log.
     59 constexpr TimeDelta kPacketLogInterval = TimeDelta::Seconds(10);
     60 
     61 RtpHeaderExtensionMap RegisterSupportedExtensions(
     62    const std::vector<RtpExtension>& rtp_header_extensions) {
     63  RtpHeaderExtensionMap map;
     64  for (const auto& extension : rtp_header_extensions) {
     65    if (extension.uri == TransportSequenceNumber::Uri()) {
     66      map.Register<TransportSequenceNumber>(extension.id);
     67    } else if (extension.uri == AbsoluteSendTime::Uri()) {
     68      map.Register<AbsoluteSendTime>(extension.id);
     69    } else if (extension.uri == TransmissionOffset::Uri()) {
     70      map.Register<TransmissionOffset>(extension.id);
     71    } else if (extension.uri == RtpMid::Uri()) {
     72      map.Register<RtpMid>(extension.id);
     73    } else {
     74      RTC_LOG(LS_INFO)
     75          << "FlexfecSender only supports RTP header extensions for "
     76             "BWE and MID, so the extension "
     77          << extension.ToString() << " will not be used.";
     78    }
     79  }
     80  return map;
     81 }
     82 
     83 }  // namespace
     84 
     85 FlexfecSender::FlexfecSender(
     86    const Environment& env,
     87    int payload_type,
     88    uint32_t ssrc,
     89    uint32_t protected_media_ssrc,
     90    absl::string_view mid,
     91    const std::vector<RtpExtension>& rtp_header_extensions,
     92    ArrayView<const RtpExtensionSize> extension_sizes,
     93    const RtpState* rtp_state)
     94    : env_(env),
     95      random_(env_.clock().TimeInMicroseconds()),
     96      payload_type_(payload_type),
     97      // Reset RTP state if this is not the first time we are operating.
     98      // Otherwise, randomize the initial timestamp offset and RTP sequence
     99      // numbers. (This is not intended to be cryptographically strong.)
    100      timestamp_offset_(rtp_state ? rtp_state->start_timestamp
    101                                  : random_.Rand<uint32_t>()),
    102      ssrc_(ssrc),
    103      protected_media_ssrc_(protected_media_ssrc),
    104      mid_(mid),
    105      seq_num_(rtp_state ? rtp_state->sequence_number
    106                         : random_.Rand(1, kMaxInitRtpSeqNumber)),
    107      ulpfec_generator_(
    108          env_,
    109          ForwardErrorCorrection::CreateFlexfec(ssrc, protected_media_ssrc)),
    110      rtp_header_extension_map_(
    111          RegisterSupportedExtensions(rtp_header_extensions)),
    112      header_extensions_size_(
    113          RtpHeaderExtensionSize(extension_sizes, rtp_header_extension_map_)),
    114      fec_bitrate_(/*max_window_size=*/TimeDelta::Seconds(1)) {
    115  // This object should not have been instantiated if FlexFEC is disabled.
    116  RTC_DCHECK_GE(payload_type, 0);
    117  RTC_DCHECK_LE(payload_type, 127);
    118 }
    119 
    120 FlexfecSender::~FlexfecSender() = default;
    121 
    122 // We are reusing the implementation from UlpfecGenerator for SetFecParameters,
    123 // AddRtpPacketAndGenerateFec, and FecAvailable.
    124 void FlexfecSender::SetProtectionParameters(
    125    const FecProtectionParams& delta_params,
    126    const FecProtectionParams& key_params) {
    127  ulpfec_generator_.SetProtectionParameters(delta_params, key_params);
    128 }
    129 
    130 void FlexfecSender::AddPacketAndGenerateFec(const RtpPacketToSend& packet) {
    131  // TODO(brandtr): Generalize this SSRC check when we support multistream
    132  // protection.
    133  RTC_DCHECK_EQ(packet.Ssrc(), protected_media_ssrc_);
    134  ulpfec_generator_.AddPacketAndGenerateFec(packet);
    135 }
    136 
    137 std::vector<std::unique_ptr<RtpPacketToSend>> FlexfecSender::GetFecPackets() {
    138  RTC_CHECK_RUNS_SERIALIZED(&ulpfec_generator_.race_checker_);
    139  std::vector<std::unique_ptr<RtpPacketToSend>> fec_packets_to_send;
    140  fec_packets_to_send.reserve(ulpfec_generator_.generated_fec_packets_.size());
    141  size_t total_fec_data_bytes = 0;
    142  for (const auto* fec_packet : ulpfec_generator_.generated_fec_packets_) {
    143    std::unique_ptr<RtpPacketToSend> fec_packet_to_send(
    144        new RtpPacketToSend(&rtp_header_extension_map_));
    145    fec_packet_to_send->set_packet_type(
    146        RtpPacketMediaType::kForwardErrorCorrection);
    147    fec_packet_to_send->set_allow_retransmission(false);
    148 
    149    // RTP header.
    150    fec_packet_to_send->SetMarker(false);
    151    fec_packet_to_send->SetPayloadType(payload_type_);
    152    fec_packet_to_send->SetSequenceNumber(seq_num_++);
    153    fec_packet_to_send->SetTimestamp(
    154        timestamp_offset_ +
    155        static_cast<uint32_t>(kMsToRtpTimestamp *
    156                              env_.clock().TimeInMilliseconds()));
    157    // Set "capture time" so that the TransmissionOffset header extension
    158    // can be set by the RTPSender.
    159    fec_packet_to_send->set_capture_time(env_.clock().CurrentTime());
    160    fec_packet_to_send->SetSsrc(ssrc_);
    161    // Reserve extensions, if registered. These will be set by the RTPSender.
    162    fec_packet_to_send->ReserveExtension<AbsoluteSendTime>();
    163    fec_packet_to_send->ReserveExtension<TransmissionOffset>();
    164    fec_packet_to_send->ReserveExtension<TransportSequenceNumber>();
    165    // Possibly include the MID header extension.
    166    if (!mid_.empty()) {
    167      // This is a no-op if the MID header extension is not registered.
    168      fec_packet_to_send->SetExtension<RtpMid>(mid_);
    169    }
    170 
    171    // RTP payload.
    172    fec_packet_to_send->SetPayload(fec_packet->data);
    173 
    174    total_fec_data_bytes += fec_packet_to_send->size();
    175    fec_packets_to_send.push_back(std::move(fec_packet_to_send));
    176  }
    177 
    178  if (!fec_packets_to_send.empty()) {
    179    ulpfec_generator_.ResetState();
    180  }
    181 
    182  Timestamp now = env_.clock().CurrentTime();
    183  if (!fec_packets_to_send.empty() &&
    184      now - last_generated_packet_ > kPacketLogInterval) {
    185    RTC_LOG(LS_VERBOSE) << "Generated " << fec_packets_to_send.size()
    186                        << " FlexFEC packets with payload type: "
    187                        << payload_type_ << " and SSRC: " << ssrc_ << ".";
    188    last_generated_packet_ = now;
    189  }
    190 
    191  MutexLock lock(&mutex_);
    192  fec_bitrate_.Update(total_fec_data_bytes, now);
    193 
    194  return fec_packets_to_send;
    195 }
    196 
    197 // The overhead is BWE RTP header extensions and FlexFEC header.
    198 size_t FlexfecSender::MaxPacketOverhead() const {
    199  return header_extensions_size_ + kFlexfecMaxHeaderSize;
    200 }
    201 
    202 DataRate FlexfecSender::CurrentFecRate() const {
    203  MutexLock lock(&mutex_);
    204  return fec_bitrate_.Rate(env_.clock().CurrentTime())
    205      .value_or(DataRate::Zero());
    206 }
    207 
    208 std::optional<RtpState> FlexfecSender::GetRtpState() {
    209  RtpState rtp_state;
    210  rtp_state.sequence_number = seq_num_;
    211  rtp_state.start_timestamp = timestamp_offset_;
    212  return rtp_state;
    213 }
    214 
    215 }  // namespace webrtc