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