Line data Source code
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 "webrtc/modules/rtp_rtcp/include/flexfec_sender.h"
12 :
13 : #include <utility>
14 :
15 : #include "webrtc/base/logging.h"
16 : #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
17 : #include "webrtc/modules/rtp_rtcp/source/forward_error_correction.h"
18 : #include "webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h"
19 :
20 : namespace webrtc {
21 :
22 : namespace {
23 :
24 : // Let first sequence number be in the first half of the interval.
25 : constexpr uint16_t kMaxInitRtpSeqNumber = 0x7fff;
26 :
27 : // See breakdown in flexfec_header_reader_writer.cc.
28 : constexpr 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.
36 : const int kMsToRtpTimestamp = kVideoPayloadTypeFrequency / 1000;
37 :
38 : // How often to log the generated FEC packets to the text log.
39 : constexpr int64_t kPacketLogIntervalMs = 10000;
40 :
41 0 : RtpHeaderExtensionMap RegisterBweExtensions(
42 : const std::vector<RtpExtension>& rtp_header_extensions) {
43 0 : RtpHeaderExtensionMap map;
44 0 : for (const auto& extension : rtp_header_extensions) {
45 0 : if (extension.uri == TransportSequenceNumber::kUri) {
46 0 : map.Register<TransportSequenceNumber>(extension.id);
47 0 : } else if (extension.uri == AbsoluteSendTime::kUri) {
48 0 : map.Register<AbsoluteSendTime>(extension.id);
49 0 : } else if (extension.uri == TransmissionOffset::kUri) {
50 0 : map.Register<TransmissionOffset>(extension.id);
51 : } else {
52 0 : LOG(LS_INFO) << "FlexfecSender only supports RTP header extensions for "
53 0 : << "BWE, so the extension " << extension.ToString()
54 0 : << " will not be used.";
55 : }
56 : }
57 0 : return map;
58 : }
59 :
60 : } // namespace
61 :
62 0 : FlexfecSender::FlexfecSender(
63 : int payload_type,
64 : uint32_t ssrc,
65 : uint32_t protected_media_ssrc,
66 : const std::vector<RtpExtension>& rtp_header_extensions,
67 0 : Clock* clock)
68 : : clock_(clock),
69 0 : random_(clock_->TimeInMicroseconds()),
70 : last_generated_packet_ms_(-1),
71 : payload_type_(payload_type),
72 : // Initialize the timestamp offset and RTP sequence numbers randomly.
73 : // (This is not intended to be cryptographically strong.)
74 0 : timestamp_offset_(random_.Rand<uint32_t>()),
75 : ssrc_(ssrc),
76 : protected_media_ssrc_(protected_media_ssrc),
77 0 : seq_num_(random_.Rand(1, kMaxInitRtpSeqNumber)),
78 0 : ulpfec_generator_(ForwardErrorCorrection::CreateFlexfec()),
79 0 : rtp_header_extension_map_(RegisterBweExtensions(rtp_header_extensions)) {
80 : // This object should not have been instantiated if FlexFEC is disabled.
81 0 : RTC_DCHECK_GE(payload_type, 0);
82 0 : RTC_DCHECK_LE(payload_type, 127);
83 0 : }
84 :
85 : FlexfecSender::~FlexfecSender() = default;
86 :
87 : // We are reusing the implementation from UlpfecGenerator for SetFecParameters,
88 : // AddRtpPacketAndGenerateFec, and FecAvailable.
89 0 : void FlexfecSender::SetFecParameters(const FecProtectionParams& params) {
90 0 : ulpfec_generator_.SetFecParameters(params);
91 0 : }
92 :
93 0 : bool FlexfecSender::AddRtpPacketAndGenerateFec(const RtpPacketToSend& packet) {
94 : // TODO(brandtr): Generalize this SSRC check when we support multistream
95 : // protection.
96 0 : RTC_DCHECK_EQ(packet.Ssrc(), protected_media_ssrc_);
97 0 : return ulpfec_generator_.AddRtpPacketAndGenerateFec(
98 0 : packet.data(), packet.payload_size(), packet.headers_size()) == 0;
99 : }
100 :
101 0 : bool FlexfecSender::FecAvailable() const {
102 0 : return ulpfec_generator_.FecAvailable();
103 : }
104 :
105 0 : std::vector<std::unique_ptr<RtpPacketToSend>> FlexfecSender::GetFecPackets() {
106 0 : std::vector<std::unique_ptr<RtpPacketToSend>> fec_packets_to_send;
107 0 : fec_packets_to_send.reserve(ulpfec_generator_.generated_fec_packets_.size());
108 0 : for (const auto& fec_packet : ulpfec_generator_.generated_fec_packets_) {
109 : std::unique_ptr<RtpPacketToSend> fec_packet_to_send(
110 0 : new RtpPacketToSend(&rtp_header_extension_map_));
111 :
112 : // RTP header.
113 0 : fec_packet_to_send->SetMarker(false);
114 0 : fec_packet_to_send->SetPayloadType(payload_type_);
115 0 : fec_packet_to_send->SetSequenceNumber(seq_num_++);
116 0 : fec_packet_to_send->SetTimestamp(
117 0 : timestamp_offset_ +
118 : static_cast<uint32_t>(kMsToRtpTimestamp *
119 0 : clock_->TimeInMilliseconds()));
120 : // Set "capture time" so that the TransmissionOffset header extension
121 : // can be set by the RTPSender.
122 0 : fec_packet_to_send->set_capture_time_ms(clock_->TimeInMilliseconds());
123 0 : fec_packet_to_send->SetSsrc(ssrc_);
124 : // Reserve extensions, if registered. These will be set by the RTPSender.
125 0 : fec_packet_to_send->ReserveExtension<AbsoluteSendTime>();
126 0 : fec_packet_to_send->ReserveExtension<TransmissionOffset>();
127 0 : fec_packet_to_send->ReserveExtension<TransportSequenceNumber>();
128 :
129 : // RTP payload.
130 0 : uint8_t* payload = fec_packet_to_send->AllocatePayload(fec_packet->length);
131 0 : memcpy(payload, fec_packet->data, fec_packet->length);
132 :
133 0 : fec_packets_to_send.push_back(std::move(fec_packet_to_send));
134 : }
135 0 : ulpfec_generator_.ResetState();
136 :
137 0 : int64_t now_ms = clock_->TimeInMilliseconds();
138 0 : if (!fec_packets_to_send.empty() &&
139 0 : now_ms - last_generated_packet_ms_ > kPacketLogIntervalMs) {
140 0 : LOG(LS_VERBOSE) << "Generated " << fec_packets_to_send.size()
141 0 : << " FlexFEC packets with payload type: " << payload_type_
142 0 : << " and SSRC: " << ssrc_ << ".";
143 0 : last_generated_packet_ms_ = now_ms;
144 : }
145 :
146 0 : return fec_packets_to_send;
147 : }
148 :
149 : // The overhead is BWE RTP header extensions and FlexFEC header.
150 0 : size_t FlexfecSender::MaxPacketOverhead() const {
151 0 : return rtp_header_extension_map_.GetTotalLengthInBytes() +
152 0 : kFlexfecMaxHeaderSize;
153 : }
154 :
155 : } // namespace webrtc
|