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