blob: d35f4d6eed4edf01aa1495ea6a379f55ae4ac15e [file] [log] [blame]
brandtrc295e002016-11-03 09:22:33 -07001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/rtp_rtcp/include/flexfec_sender.h"
brandtrc295e002016-11-03 09:22:33 -070012
Yves Gerey988cc082018-10-23 12:03:01 +020013#include <string.h>
Jonas Olssona4d87372019-07-05 19:08:33 +020014
Yves Gerey988cc082018-10-23 12:03:01 +020015#include <list>
brandtrc295e002016-11-03 09:22:33 -070016#include <utility>
17
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#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"
Yves Gerey988cc082018-10-23 12:03:01 +020021#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
22#include "rtc_base/checks.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020023#include "rtc_base/logging.h"
brandtrc295e002016-11-03 09:22:33 -070024
25namespace webrtc {
26
27namespace {
28
29// Let first sequence number be in the first half of the interval.
30constexpr uint16_t kMaxInitRtpSeqNumber = 0x7fff;
31
32// See breakdown in flexfec_header_reader_writer.cc.
33constexpr 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.
41const int kMsToRtpTimestamp = kVideoPayloadTypeFrequency / 1000;
42
43// How often to log the generated FEC packets to the text log.
44constexpr int64_t kPacketLogIntervalMs = 10000;
45
Steve Antonf0482ea2018-04-09 13:33:52 -070046RtpHeaderExtensionMap RegisterSupportedExtensions(
brandtr131bc492016-11-10 05:01:11 -080047 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);
Steve Antonf0482ea2018-04-09 13:33:52 -070056 } else if (extension.uri == RtpMid::kUri) {
57 map.Register<RtpMid>(extension.id);
brandtr131bc492016-11-10 05:01:11 -080058 } else {
Mirko Bonadei675513b2017-11-09 11:09:25 +010059 RTC_LOG(LS_INFO)
60 << "FlexfecSender only supports RTP header extensions for "
Steve Antonf0482ea2018-04-09 13:33:52 -070061 << "BWE and MID, so the extension " << extension.ToString()
Mirko Bonadei675513b2017-11-09 11:09:25 +010062 << " will not be used.";
brandtr131bc492016-11-10 05:01:11 -080063 }
64 }
65 return map;
66}
67
brandtrc295e002016-11-03 09:22:33 -070068} // namespace
69
70FlexfecSender::FlexfecSender(
71 int payload_type,
72 uint32_t ssrc,
73 uint32_t protected_media_ssrc,
Steve Antonf0482ea2018-04-09 13:33:52 -070074 const std::string& mid,
brandtrc295e002016-11-03 09:22:33 -070075 const std::vector<RtpExtension>& rtp_header_extensions,
erikvarga27883732017-05-17 05:08:38 -070076 rtc::ArrayView<const RtpExtensionSize> extension_sizes,
brandtr48d21a22017-05-30 02:32:12 -070077 const RtpState* rtp_state,
brandtrc295e002016-11-03 09:22:33 -070078 Clock* clock)
79 : clock_(clock),
80 random_(clock_->TimeInMicroseconds()),
81 last_generated_packet_ms_(-1),
82 payload_type_(payload_type),
brandtr48d21a22017-05-30 02:32:12 -070083 // 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>()),
brandtrc295e002016-11-03 09:22:33 -070088 ssrc_(ssrc),
89 protected_media_ssrc_(protected_media_ssrc),
Steve Antonf0482ea2018-04-09 13:33:52 -070090 mid_(mid),
brandtr48d21a22017-05-30 02:32:12 -070091 seq_num_(rtp_state ? rtp_state->sequence_number
92 : random_.Rand(1, kMaxInitRtpSeqNumber)),
brandtrd726a3f2017-06-29 02:45:35 -070093 ulpfec_generator_(
94 ForwardErrorCorrection::CreateFlexfec(ssrc, protected_media_ssrc)),
Steve Antonf0482ea2018-04-09 13:33:52 -070095 rtp_header_extension_map_(
96 RegisterSupportedExtensions(rtp_header_extensions)),
erikvarga27883732017-05-17 05:08:38 -070097 header_extensions_size_(
Danil Chapovalov7b189922018-10-03 10:15:36 +020098 RtpHeaderExtensionSize(extension_sizes, rtp_header_extension_map_)) {
brandtrc295e002016-11-03 09:22:33 -070099 // This object should not have been instantiated if FlexFEC is disabled.
100 RTC_DCHECK_GE(payload_type, 0);
101 RTC_DCHECK_LE(payload_type, 127);
brandtrc295e002016-11-03 09:22:33 -0700102}
103
104FlexfecSender::~FlexfecSender() = default;
105
106// We are reusing the implementation from UlpfecGenerator for SetFecParameters,
107// AddRtpPacketAndGenerateFec, and FecAvailable.
108void FlexfecSender::SetFecParameters(const FecProtectionParams& params) {
brandtr1743a192016-11-07 03:36:05 -0800109 ulpfec_generator_.SetFecParameters(params);
brandtrc295e002016-11-03 09:22:33 -0700110}
111
brandtrfe793eb2016-12-12 07:13:56 -0800112bool FlexfecSender::AddRtpPacketAndGenerateFec(const RtpPacketToSend& packet) {
brandtrc295e002016-11-03 09:22:33 -0700113 // TODO(brandtr): Generalize this SSRC check when we support multistream
114 // protection.
115 RTC_DCHECK_EQ(packet.Ssrc(), protected_media_ssrc_);
116 return ulpfec_generator_.AddRtpPacketAndGenerateFec(
Ilya Nikolaevskiya5d952f2019-09-03 11:07:37 +0200117 packet.Buffer(), packet.headers_size()) == 0;
brandtrc295e002016-11-03 09:22:33 -0700118}
119
120bool FlexfecSender::FecAvailable() const {
brandtrc295e002016-11-03 09:22:33 -0700121 return ulpfec_generator_.FecAvailable();
122}
123
brandtrfe793eb2016-12-12 07:13:56 -0800124std::vector<std::unique_ptr<RtpPacketToSend>> FlexfecSender::GetFecPackets() {
brandtrc295e002016-11-03 09:22:33 -0700125 std::vector<std::unique_ptr<RtpPacketToSend>> fec_packets_to_send;
126 fec_packets_to_send.reserve(ulpfec_generator_.generated_fec_packets_.size());
Danil Chapovalov2a5ce2b2018-02-07 09:38:31 +0100127 for (const auto* fec_packet : ulpfec_generator_.generated_fec_packets_) {
brandtrc295e002016-11-03 09:22:33 -0700128 std::unique_ptr<RtpPacketToSend> fec_packet_to_send(
129 new RtpPacketToSend(&rtp_header_extension_map_));
Erik Språngf53cfa92019-06-12 13:58:17 +0200130 fec_packet_to_send->set_packet_type(
131 RtpPacketToSend::Type::kForwardErrorCorrection);
brandtrc295e002016-11-03 09:22:33 -0700132
133 // RTP header.
134 fec_packet_to_send->SetMarker(false);
135 fec_packet_to_send->SetPayloadType(payload_type_);
136 fec_packet_to_send->SetSequenceNumber(seq_num_++);
137 fec_packet_to_send->SetTimestamp(
138 timestamp_offset_ +
139 static_cast<uint32_t>(kMsToRtpTimestamp *
140 clock_->TimeInMilliseconds()));
141 // Set "capture time" so that the TransmissionOffset header extension
142 // can be set by the RTPSender.
143 fec_packet_to_send->set_capture_time_ms(clock_->TimeInMilliseconds());
144 fec_packet_to_send->SetSsrc(ssrc_);
145 // Reserve extensions, if registered. These will be set by the RTPSender.
146 fec_packet_to_send->ReserveExtension<AbsoluteSendTime>();
147 fec_packet_to_send->ReserveExtension<TransmissionOffset>();
148 fec_packet_to_send->ReserveExtension<TransportSequenceNumber>();
Steve Antonf0482ea2018-04-09 13:33:52 -0700149 // Possibly include the MID header extension.
150 if (!mid_.empty()) {
151 // This is a no-op if the MID header extension is not registered.
152 fec_packet_to_send->SetExtension<RtpMid>(mid_);
153 }
brandtrc295e002016-11-03 09:22:33 -0700154
155 // RTP payload.
Ilya Nikolaevskiya5d952f2019-09-03 11:07:37 +0200156 uint8_t* payload =
157 fec_packet_to_send->AllocatePayload(fec_packet->data.size());
158 memcpy(payload, fec_packet->data.cdata(), fec_packet->data.size());
brandtrc295e002016-11-03 09:22:33 -0700159
160 fec_packets_to_send.push_back(std::move(fec_packet_to_send));
161 }
162 ulpfec_generator_.ResetState();
163
brandtrc295e002016-11-03 09:22:33 -0700164 int64_t now_ms = clock_->TimeInMilliseconds();
165 if (!fec_packets_to_send.empty() &&
166 now_ms - last_generated_packet_ms_ > kPacketLogIntervalMs) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100167 RTC_LOG(LS_VERBOSE) << "Generated " << fec_packets_to_send.size()
168 << " FlexFEC packets with payload type: "
169 << payload_type_ << " and SSRC: " << ssrc_ << ".";
brandtrc295e002016-11-03 09:22:33 -0700170 last_generated_packet_ms_ = now_ms;
171 }
172
173 return fec_packets_to_send;
174}
175
brandtr131bc492016-11-10 05:01:11 -0800176// The overhead is BWE RTP header extensions and FlexFEC header.
brandtrc295e002016-11-03 09:22:33 -0700177size_t FlexfecSender::MaxPacketOverhead() const {
erikvarga27883732017-05-17 05:08:38 -0700178 return header_extensions_size_ + kFlexfecMaxHeaderSize;
brandtrc295e002016-11-03 09:22:33 -0700179}
180
brandtr48d21a22017-05-30 02:32:12 -0700181RtpState FlexfecSender::GetRtpState() {
182 RtpState rtp_state;
183 rtp_state.sequence_number = seq_num_;
184 rtp_state.start_timestamp = timestamp_offset_;
185 return rtp_state;
186}
187
brandtrc295e002016-11-03 09:22:33 -0700188} // namespace webrtc