Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(416)

Side by Side Diff: webrtc/modules/rtp_rtcp/source/producer_fec.cc

Issue 2260803002: Generalize FEC header formatting. (pt. 4) (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/modules/rtp_rtcp/source/producer_fec.h" 11 #include "webrtc/modules/rtp_rtcp/source/producer_fec.h"
12 12
13 #include <memory> 13 #include <memory>
14 #include <utility> 14 #include <utility>
15 15
16 #include "webrtc/base/basictypes.h" 16 #include "webrtc/base/basictypes.h"
17 #include "webrtc/base/checks.h" 17 #include "webrtc/base/checks.h"
18 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" 18 #include "webrtc/modules/rtp_rtcp/source/byte_io.h"
19 #include "webrtc/modules/rtp_rtcp/source/forward_error_correction.h" 19 #include "webrtc/modules/rtp_rtcp/source/forward_error_correction.h"
20 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" 20 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
21 21
22 namespace webrtc { 22 namespace webrtc {
23 23
24 constexpr size_t kRedForFecHeaderLength = 1; 24 constexpr size_t kRedForFecHeaderLength = 1;
25 25
26 // This controls the maximum amount of excess overhead (actual - target) 26 // This controls the maximum amount of excess overhead (actual - target)
27 // allowed in order to trigger GenerateFec(), before |params_.max_fec_frames| 27 // allowed in order to trigger EncodeFec(), before |params_.max_fec_frames|
28 // is reached. Overhead here is defined as relative to number of media packets. 28 // is reached. Overhead here is defined as relative to number of media packets.
29 constexpr int kMaxExcessOverhead = 50; // Q8. 29 constexpr int kMaxExcessOverhead = 50; // Q8.
30 30
31 // This is the minimum number of media packets required (above some protection 31 // This is the minimum number of media packets required (above some protection
32 // level) in order to trigger GenerateFec(), before |params_.max_fec_frames| is 32 // level) in order to trigger EncodeFec(), before |params_.max_fec_frames| is
33 // reached. 33 // reached.
34 constexpr size_t kMinMediaPackets = 4; 34 constexpr size_t kMinMediaPackets = 4;
35 35
36 // Threshold on the received FEC protection level, above which we enforce at 36 // Threshold on the received FEC protection level, above which we enforce at
37 // least |kMinMediaPackets| packets for the FEC code. Below this 37 // least |kMinMediaPackets| packets for the FEC code. Below this
38 // threshold |kMinMediaPackets| is set to default value of 1. 38 // threshold |kMinMediaPackets| is set to default value of 1.
39 // 39 //
40 // The range is between 0 and 255, where 255 corresponds to 100% overhead 40 // The range is between 0 and 255, where 255 corresponds to 100% overhead
41 // (relative to the number of protected media packets). 41 // (relative to the number of protected media packets).
42 constexpr uint8_t kHighProtectionThreshold = 80; 42 constexpr uint8_t kHighProtectionThreshold = 80;
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
85 } 85 }
86 86
87 uint8_t* RedPacket::data() const { 87 uint8_t* RedPacket::data() const {
88 return data_.get(); 88 return data_.get();
89 } 89 }
90 90
91 size_t RedPacket::length() const { 91 size_t RedPacket::length() const {
92 return length_; 92 return length_;
93 } 93 }
94 94
95 ProducerFec::ProducerFec(ForwardErrorCorrection* fec) 95 ProducerFec::ProducerFec()
96 : fec_(fec), 96 : fec_(ForwardErrorCorrection::CreateUlpfec()),
97 media_packets_(), 97 media_packets_(),
98 generated_fec_packets_(), 98 generated_fec_packets_(),
99 num_protected_frames_(0), 99 num_protected_frames_(0),
100 num_important_packets_(0), 100 num_important_packets_(0),
101 min_num_media_packets_(1), 101 min_num_media_packets_(1),
102 params_(), 102 params_(),
103 new_params_() { 103 new_params_() {
104 memset(&params_, 0, sizeof(params_)); 104 memset(&params_, 0, sizeof(params_));
105 memset(&new_params_, 0, sizeof(new_params_)); 105 memset(&new_params_, 0, sizeof(new_params_));
106 } 106 }
(...skipping 15 matching lines...) Expand all
122 red_packet->AssignPayload(data_buffer + rtp_header_length, payload_length); 122 red_packet->AssignPayload(data_buffer + rtp_header_length, payload_length);
123 return red_packet; 123 return red_packet;
124 } 124 }
125 125
126 void ProducerFec::SetFecParameters(const FecProtectionParams* params, 126 void ProducerFec::SetFecParameters(const FecProtectionParams* params,
127 int num_important_packets) { 127 int num_important_packets) {
128 // Number of important packets (i.e. number of packets receiving additional 128 // Number of important packets (i.e. number of packets receiving additional
129 // protection in 'unequal protection mode') cannot exceed kMaxMediaPackets. 129 // protection in 'unequal protection mode') cannot exceed kMaxMediaPackets.
130 RTC_DCHECK_GE(params->fec_rate, 0); 130 RTC_DCHECK_GE(params->fec_rate, 0);
131 RTC_DCHECK_LE(params->fec_rate, 255); 131 RTC_DCHECK_LE(params->fec_rate, 255);
132 if (num_important_packets > 132 if (num_important_packets > static_cast<int>(kUlpfecMaxMediaPackets)) {
133 static_cast<int>(ForwardErrorCorrection::kMaxMediaPackets)) { 133 num_important_packets = kUlpfecMaxMediaPackets;
134 num_important_packets = ForwardErrorCorrection::kMaxMediaPackets;
135 } 134 }
136 // Store the new params and apply them for the next set of FEC packets being 135 // Store the new params and apply them for the next set of FEC packets being
137 // produced. 136 // produced.
138 new_params_ = *params; 137 new_params_ = *params;
139 num_important_packets_ = num_important_packets; 138 num_important_packets_ = num_important_packets;
140 if (params->fec_rate > kHighProtectionThreshold) { 139 if (params->fec_rate > kHighProtectionThreshold) {
141 min_num_media_packets_ = kMinMediaPackets; 140 min_num_media_packets_ = kMinMediaPackets;
142 } else { 141 } else {
143 min_num_media_packets_ = 1; 142 min_num_media_packets_ = 1;
144 } 143 }
145 } 144 }
146 145
147 int ProducerFec::AddRtpPacketAndGenerateFec(const uint8_t* data_buffer, 146 int ProducerFec::AddRtpPacketAndGenerateFec(const uint8_t* data_buffer,
148 size_t payload_length, 147 size_t payload_length,
149 size_t rtp_header_length) { 148 size_t rtp_header_length) {
150 RTC_DCHECK(generated_fec_packets_.empty()); 149 RTC_DCHECK(generated_fec_packets_.empty());
151 if (media_packets_.empty()) { 150 if (media_packets_.empty()) {
152 params_ = new_params_; 151 params_ = new_params_;
153 } 152 }
154 bool complete_frame = false; 153 bool complete_frame = false;
155 const bool marker_bit = (data_buffer[1] & kRtpMarkerBitMask) ? true : false; 154 const bool marker_bit = (data_buffer[1] & kRtpMarkerBitMask) ? true : false;
156 if (media_packets_.size() < ForwardErrorCorrection::kMaxMediaPackets) { 155 if (media_packets_.size() < kUlpfecMaxMediaPackets) {
157 // Generic FEC can only protect up to |kMaxMediaPackets| packets. 156 // Generic FEC can only protect up to kMaxMediaPackets packets.
158 std::unique_ptr<ForwardErrorCorrection::Packet> packet( 157 std::unique_ptr<ForwardErrorCorrection::Packet> packet(
159 new ForwardErrorCorrection::Packet()); 158 new ForwardErrorCorrection::Packet());
160 packet->length = payload_length + rtp_header_length; 159 packet->length = payload_length + rtp_header_length;
161 memcpy(packet->data, data_buffer, packet->length); 160 memcpy(packet->data, data_buffer, packet->length);
162 media_packets_.push_back(std::move(packet)); 161 media_packets_.push_back(std::move(packet));
163 } 162 }
164 if (marker_bit) { 163 if (marker_bit) {
165 ++num_protected_frames_; 164 ++num_protected_frames_;
166 complete_frame = true; 165 complete_frame = true;
167 } 166 }
168 // Produce FEC over at most |params_.max_fec_frames| frames, or as soon as: 167 // Produce FEC over at most |params_.max_fec_frames| frames, or as soon as:
169 // (1) the excess overhead (actual overhead - requested/target overhead) is 168 // (1) the excess overhead (actual overhead - requested/target overhead) is
170 // less than |kMaxExcessOverhead|, and 169 // less than |kMaxExcessOverhead|, and
171 // (2) at least |min_num_media_packets_| media packets is reached. 170 // (2) at least |min_num_media_packets_| media packets is reached.
172 if (complete_frame && 171 if (complete_frame &&
173 (num_protected_frames_ == params_.max_fec_frames || 172 (num_protected_frames_ == params_.max_fec_frames ||
174 (ExcessOverheadBelowMax() && MinimumMediaPacketsReached()))) { 173 (ExcessOverheadBelowMax() && MinimumMediaPacketsReached()))) {
175 RTC_DCHECK_LE(num_important_packets_, 174 RTC_DCHECK_LE(num_important_packets_,
176 static_cast<int>(ForwardErrorCorrection::kMaxMediaPackets)); 175 static_cast<int>(kUlpfecMaxMediaPackets));
177 // TODO(pbos): Consider whether unequal protection should be enabled or not, 176 // TODO(pbos): Consider whether unequal protection should be enabled or not,
178 // it is currently always disabled. 177 // it is currently always disabled.
179 // 178 //
180 // Since unequal protection is disabled, the value of 179 // Since unequal protection is disabled, the value of
181 // |num_important_packets_| has no importance when calling GenerateFec(). 180 // |num_important_packets_| has no importance when calling GenerateFec().
182 constexpr bool kUseUnequalProtection = false; 181 constexpr bool kUseUnequalProtection = false;
183 int ret = fec_->GenerateFec(media_packets_, params_.fec_rate, 182 int ret = fec_.EncodeFec(media_packets_, params_.fec_rate,
184 num_important_packets_, kUseUnequalProtection, 183 num_important_packets_, kUseUnequalProtection,
185 params_.fec_mask_type, &generated_fec_packets_); 184 params_.fec_mask_type, &generated_fec_packets_);
186 if (generated_fec_packets_.empty()) { 185 if (generated_fec_packets_.empty()) {
187 num_protected_frames_ = 0; 186 num_protected_frames_ = 0;
188 DeleteMediaPackets(); 187 DeleteMediaPackets();
189 } 188 }
190 return ret; 189 return ret;
191 } 190 }
192 return 0; 191 return 0;
193 } 192 }
194 193
195 bool ProducerFec::ExcessOverheadBelowMax() const { 194 bool ProducerFec::ExcessOverheadBelowMax() const {
(...skipping 14 matching lines...) Expand all
210 } 209 }
211 210
212 bool ProducerFec::FecAvailable() const { 211 bool ProducerFec::FecAvailable() const {
213 return !generated_fec_packets_.empty(); 212 return !generated_fec_packets_.empty();
214 } 213 }
215 214
216 size_t ProducerFec::NumAvailableFecPackets() const { 215 size_t ProducerFec::NumAvailableFecPackets() const {
217 return generated_fec_packets_.size(); 216 return generated_fec_packets_.size();
218 } 217 }
219 218
219 size_t ProducerFec::MaxPacketOverhead() const {
220 return fec_.MaxPacketOverhead();
221 }
222
220 std::vector<std::unique_ptr<RedPacket>> ProducerFec::GetFecPacketsAsRed( 223 std::vector<std::unique_ptr<RedPacket>> ProducerFec::GetFecPacketsAsRed(
221 int red_payload_type, 224 int red_payload_type,
222 int ulpfec_payload_type, 225 int ulpfec_payload_type,
223 uint16_t first_seq_num, 226 uint16_t first_seq_num,
224 size_t rtp_header_length) { 227 size_t rtp_header_length) {
225 std::vector<std::unique_ptr<RedPacket>> red_packets; 228 std::vector<std::unique_ptr<RedPacket>> red_packets;
226 red_packets.reserve(generated_fec_packets_.size()); 229 red_packets.reserve(generated_fec_packets_.size());
227 RTC_DCHECK(!media_packets_.empty()); 230 RTC_DCHECK(!media_packets_.empty());
228 ForwardErrorCorrection::Packet* last_media_packet = 231 ForwardErrorCorrection::Packet* last_media_packet =
229 media_packets_.back().get(); 232 media_packets_.back().get();
230 uint16_t seq_num = first_seq_num; 233 uint16_t seq_num = first_seq_num;
231 for (const auto& fec_packet : generated_fec_packets_) { 234 for (const auto& fec_packet : generated_fec_packets_) {
232 // Wrap FEC packet (including FEC headers) in a RED packet. Since the 235 // Wrap FEC packet (including FEC headers) in a RED packet. Since the
233 // FEC packets in |generated_fec_packets_| don't have RTP headers, we 236 // FEC packets in |generated_fec_packets_| don't have RTP headers, we
234 // reuse the header from the last media packet. 237 // reuse the header from the last media packet.
235 std::unique_ptr<RedPacket> red_packet(new RedPacket( 238 std::unique_ptr<RedPacket> red_packet(new RedPacket(
236 fec_packet->length + kRedForFecHeaderLength + rtp_header_length)); 239 fec_packet->length + kRedForFecHeaderLength + rtp_header_length));
237 red_packet->CreateHeader(last_media_packet->data, rtp_header_length, 240 red_packet->CreateHeader(last_media_packet->data, rtp_header_length,
238 red_payload_type, ulpfec_payload_type); 241 red_payload_type, ulpfec_payload_type);
239 red_packet->SetSeqNum(seq_num++); 242 red_packet->SetSeqNum(seq_num++);
240 red_packet->ClearMarkerBit(); 243 red_packet->ClearMarkerBit();
241 red_packet->AssignPayload(fec_packet->data, fec_packet->length); 244 red_packet->AssignPayload(fec_packet->data, fec_packet->length);
242
243 red_packets.push_back(std::move(red_packet)); 245 red_packets.push_back(std::move(red_packet));
244 } 246 }
245
246 // Reset state. 247 // Reset state.
247 DeleteMediaPackets(); 248 DeleteMediaPackets();
248 generated_fec_packets_.clear(); 249 generated_fec_packets_.clear();
249 num_protected_frames_ = 0; 250 num_protected_frames_ = 0;
250
251 return red_packets; 251 return red_packets;
252 } 252 }
253 253
254 int ProducerFec::Overhead() const { 254 int ProducerFec::Overhead() const {
255 // Overhead is defined as relative to the number of media packets, and not 255 // Overhead is defined as relative to the number of media packets, and not
256 // relative to total number of packets. This definition is inherited from the 256 // relative to total number of packets. This definition is inherited from the
257 // protection factor produced by video_coding module and how the FEC 257 // protection factor produced by video_coding module and how the FEC
258 // generation is implemented. 258 // generation is implemented.
259 RTC_DCHECK(!media_packets_.empty()); 259 RTC_DCHECK(!media_packets_.empty());
260 int num_fec_packets = 260 int num_fec_packets =
261 fec_->GetNumberOfFecPackets(media_packets_.size(), params_.fec_rate); 261 fec_.NumFecPackets(media_packets_.size(), params_.fec_rate);
262 // Return the overhead in Q8. 262 // Return the overhead in Q8.
263 return (num_fec_packets << 8) / media_packets_.size(); 263 return (num_fec_packets << 8) / media_packets_.size();
264 } 264 }
265 265
266 void ProducerFec::DeleteMediaPackets() { 266 void ProducerFec::DeleteMediaPackets() {
267 media_packets_.clear(); 267 media_packets_.clear();
268 } 268 }
269 269
270 } // namespace webrtc 270 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698