blob: 9704096ff7d7b3702b4452f017e92305d72c9e9d [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
13#include <utility>
14
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020015#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
16#include "modules/rtp_rtcp/source/forward_error_correction.h"
17#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
18#include "rtc_base/logging.h"
brandtrc295e002016-11-03 09:22:33 -070019
20namespace webrtc {
21
22namespace {
23
24// Let first sequence number be in the first half of the interval.
25constexpr uint16_t kMaxInitRtpSeqNumber = 0x7fff;
26
27// See breakdown in flexfec_header_reader_writer.cc.
28constexpr size_t kFlexfecMaxHeaderSize = 32;
29
30// Since we will mainly use FlexFEC to protect video streams, we use a 90 kHz
31// clock for the RTP timestamps. (This is according to the RFC, which states
32// that it is RECOMMENDED to use the same clock frequency for FlexFEC as for
33// the protected media stream.)
34// The constant converts from clock millisecond timestamps to the 90 kHz
35// RTP timestamp.
36const int kMsToRtpTimestamp = kVideoPayloadTypeFrequency / 1000;
37
38// How often to log the generated FEC packets to the text log.
39constexpr int64_t kPacketLogIntervalMs = 10000;
40
Steve Antonf0482ea2018-04-09 13:33:52 -070041RtpHeaderExtensionMap RegisterSupportedExtensions(
brandtr131bc492016-11-10 05:01:11 -080042 const std::vector<RtpExtension>& rtp_header_extensions) {
43 RtpHeaderExtensionMap map;
44 for (const auto& extension : rtp_header_extensions) {
45 if (extension.uri == TransportSequenceNumber::kUri) {
46 map.Register<TransportSequenceNumber>(extension.id);
47 } else if (extension.uri == AbsoluteSendTime::kUri) {
48 map.Register<AbsoluteSendTime>(extension.id);
49 } else if (extension.uri == TransmissionOffset::kUri) {
50 map.Register<TransmissionOffset>(extension.id);
Steve Antonf0482ea2018-04-09 13:33:52 -070051 } else if (extension.uri == RtpMid::kUri) {
52 map.Register<RtpMid>(extension.id);
brandtr131bc492016-11-10 05:01:11 -080053 } else {
Mirko Bonadei675513b2017-11-09 11:09:25 +010054 RTC_LOG(LS_INFO)
55 << "FlexfecSender only supports RTP header extensions for "
Steve Antonf0482ea2018-04-09 13:33:52 -070056 << "BWE and MID, so the extension " << extension.ToString()
Mirko Bonadei675513b2017-11-09 11:09:25 +010057 << " will not be used.";
brandtr131bc492016-11-10 05:01:11 -080058 }
59 }
60 return map;
61}
62
brandtrc295e002016-11-03 09:22:33 -070063} // namespace
64
65FlexfecSender::FlexfecSender(
66 int payload_type,
67 uint32_t ssrc,
68 uint32_t protected_media_ssrc,
Steve Antonf0482ea2018-04-09 13:33:52 -070069 const std::string& mid,
brandtrc295e002016-11-03 09:22:33 -070070 const std::vector<RtpExtension>& rtp_header_extensions,
erikvarga27883732017-05-17 05:08:38 -070071 rtc::ArrayView<const RtpExtensionSize> extension_sizes,
brandtr48d21a22017-05-30 02:32:12 -070072 const RtpState* rtp_state,
brandtrc295e002016-11-03 09:22:33 -070073 Clock* clock)
74 : clock_(clock),
75 random_(clock_->TimeInMicroseconds()),
76 last_generated_packet_ms_(-1),
77 payload_type_(payload_type),
brandtr48d21a22017-05-30 02:32:12 -070078 // Reset RTP state if this is not the first time we are operating.
79 // Otherwise, randomize the initial timestamp offset and RTP sequence
80 // numbers. (This is not intended to be cryptographically strong.)
81 timestamp_offset_(rtp_state ? rtp_state->start_timestamp
82 : random_.Rand<uint32_t>()),
brandtrc295e002016-11-03 09:22:33 -070083 ssrc_(ssrc),
84 protected_media_ssrc_(protected_media_ssrc),
Steve Antonf0482ea2018-04-09 13:33:52 -070085 mid_(mid),
brandtr48d21a22017-05-30 02:32:12 -070086 seq_num_(rtp_state ? rtp_state->sequence_number
87 : random_.Rand(1, kMaxInitRtpSeqNumber)),
brandtrd726a3f2017-06-29 02:45:35 -070088 ulpfec_generator_(
89 ForwardErrorCorrection::CreateFlexfec(ssrc, protected_media_ssrc)),
Steve Antonf0482ea2018-04-09 13:33:52 -070090 rtp_header_extension_map_(
91 RegisterSupportedExtensions(rtp_header_extensions)),
erikvarga27883732017-05-17 05:08:38 -070092 header_extensions_size_(
93 rtp_header_extension_map_.GetTotalLengthInBytes(extension_sizes)) {
brandtrc295e002016-11-03 09:22:33 -070094 // This object should not have been instantiated if FlexFEC is disabled.
95 RTC_DCHECK_GE(payload_type, 0);
96 RTC_DCHECK_LE(payload_type, 127);
brandtrc295e002016-11-03 09:22:33 -070097}
98
99FlexfecSender::~FlexfecSender() = default;
100
101// We are reusing the implementation from UlpfecGenerator for SetFecParameters,
102// AddRtpPacketAndGenerateFec, and FecAvailable.
103void FlexfecSender::SetFecParameters(const FecProtectionParams& params) {
brandtr1743a192016-11-07 03:36:05 -0800104 ulpfec_generator_.SetFecParameters(params);
brandtrc295e002016-11-03 09:22:33 -0700105}
106
brandtrfe793eb2016-12-12 07:13:56 -0800107bool FlexfecSender::AddRtpPacketAndGenerateFec(const RtpPacketToSend& packet) {
brandtrc295e002016-11-03 09:22:33 -0700108 // TODO(brandtr): Generalize this SSRC check when we support multistream
109 // protection.
110 RTC_DCHECK_EQ(packet.Ssrc(), protected_media_ssrc_);
111 return ulpfec_generator_.AddRtpPacketAndGenerateFec(
112 packet.data(), packet.payload_size(), packet.headers_size()) == 0;
113}
114
115bool FlexfecSender::FecAvailable() const {
brandtrc295e002016-11-03 09:22:33 -0700116 return ulpfec_generator_.FecAvailable();
117}
118
brandtrfe793eb2016-12-12 07:13:56 -0800119std::vector<std::unique_ptr<RtpPacketToSend>> FlexfecSender::GetFecPackets() {
brandtrc295e002016-11-03 09:22:33 -0700120 std::vector<std::unique_ptr<RtpPacketToSend>> fec_packets_to_send;
121 fec_packets_to_send.reserve(ulpfec_generator_.generated_fec_packets_.size());
Danil Chapovalov2a5ce2b2018-02-07 09:38:31 +0100122 for (const auto* fec_packet : ulpfec_generator_.generated_fec_packets_) {
brandtrc295e002016-11-03 09:22:33 -0700123 std::unique_ptr<RtpPacketToSend> fec_packet_to_send(
124 new RtpPacketToSend(&rtp_header_extension_map_));
125
126 // RTP header.
127 fec_packet_to_send->SetMarker(false);
128 fec_packet_to_send->SetPayloadType(payload_type_);
129 fec_packet_to_send->SetSequenceNumber(seq_num_++);
130 fec_packet_to_send->SetTimestamp(
131 timestamp_offset_ +
132 static_cast<uint32_t>(kMsToRtpTimestamp *
133 clock_->TimeInMilliseconds()));
134 // Set "capture time" so that the TransmissionOffset header extension
135 // can be set by the RTPSender.
136 fec_packet_to_send->set_capture_time_ms(clock_->TimeInMilliseconds());
137 fec_packet_to_send->SetSsrc(ssrc_);
138 // Reserve extensions, if registered. These will be set by the RTPSender.
139 fec_packet_to_send->ReserveExtension<AbsoluteSendTime>();
140 fec_packet_to_send->ReserveExtension<TransmissionOffset>();
141 fec_packet_to_send->ReserveExtension<TransportSequenceNumber>();
Steve Antonf0482ea2018-04-09 13:33:52 -0700142 // Possibly include the MID header extension.
143 if (!mid_.empty()) {
144 // This is a no-op if the MID header extension is not registered.
145 fec_packet_to_send->SetExtension<RtpMid>(mid_);
146 }
brandtrc295e002016-11-03 09:22:33 -0700147
148 // RTP payload.
149 uint8_t* payload = fec_packet_to_send->AllocatePayload(fec_packet->length);
150 memcpy(payload, fec_packet->data, fec_packet->length);
151
152 fec_packets_to_send.push_back(std::move(fec_packet_to_send));
153 }
154 ulpfec_generator_.ResetState();
155
brandtrc295e002016-11-03 09:22:33 -0700156 int64_t now_ms = clock_->TimeInMilliseconds();
157 if (!fec_packets_to_send.empty() &&
158 now_ms - last_generated_packet_ms_ > kPacketLogIntervalMs) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100159 RTC_LOG(LS_VERBOSE) << "Generated " << fec_packets_to_send.size()
160 << " FlexFEC packets with payload type: "
161 << payload_type_ << " and SSRC: " << ssrc_ << ".";
brandtrc295e002016-11-03 09:22:33 -0700162 last_generated_packet_ms_ = now_ms;
163 }
164
165 return fec_packets_to_send;
166}
167
brandtr131bc492016-11-10 05:01:11 -0800168// The overhead is BWE RTP header extensions and FlexFEC header.
brandtrc295e002016-11-03 09:22:33 -0700169size_t FlexfecSender::MaxPacketOverhead() const {
erikvarga27883732017-05-17 05:08:38 -0700170 return header_extensions_size_ + kFlexfecMaxHeaderSize;
brandtrc295e002016-11-03 09:22:33 -0700171}
172
brandtr48d21a22017-05-30 02:32:12 -0700173RtpState FlexfecSender::GetRtpState() {
174 RtpState rtp_state;
175 rtp_state.sequence_number = seq_num_;
176 rtp_state.start_timestamp = timestamp_offset_;
177 return rtp_state;
178}
179
brandtrc295e002016-11-03 09:22:33 -0700180} // namespace webrtc