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