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

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

Issue 2490523002: Wire up FlexfecSender in RTPSenderVideo. (Closed)
Patch Set: Created 4 years, 1 month 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
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
45 } // namespace 45 } // namespace
46 46
47 RTPSenderVideo::RTPSenderVideo(Clock* clock, RTPSender* rtp_sender) 47 RTPSenderVideo::RTPSenderVideo(Clock* clock, RTPSender* rtp_sender)
48 : rtp_sender_(rtp_sender), 48 : rtp_sender_(rtp_sender),
49 clock_(clock), 49 clock_(clock),
50 video_type_(kRtpVideoGeneric), 50 video_type_(kRtpVideoGeneric),
51 retransmission_settings_(kRetransmitBaseLayer), 51 retransmission_settings_(kRetransmitBaseLayer),
52 last_rotation_(kVideoRotation_0), 52 last_rotation_(kVideoRotation_0),
53 red_payload_type_(-1), 53 red_payload_type_(-1),
54 ulpfec_payload_type_(-1), 54 ulpfec_payload_type_(-1),
55 flexfec_sender_(nullptr), // TODO(brandtr): Wire up in future CL.
55 delta_fec_params_{0, 1, kFecMaskRandom}, 56 delta_fec_params_{0, 1, kFecMaskRandom},
56 key_fec_params_{0, 1, kFecMaskRandom}, 57 key_fec_params_{0, 1, kFecMaskRandom},
57 fec_bitrate_(1000, RateStatistics::kBpsScale), 58 fec_bitrate_(1000, RateStatistics::kBpsScale),
58 video_bitrate_(1000, RateStatistics::kBpsScale) { 59 video_bitrate_(1000, RateStatistics::kBpsScale) {
59 encoder_checker_.Detach(); 60 encoder_checker_.Detach();
60 } 61 }
61 62
62 RTPSenderVideo::~RTPSenderVideo() {} 63 RTPSenderVideo::~RTPSenderVideo() {}
63 64
64 void RTPSenderVideo::SetVideoCodecType(RtpVideoCodecTypes video_type) { 65 void RTPSenderVideo::SetVideoCodecType(RtpVideoCodecTypes video_type) {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
107 rtc::CritScope cs(&stats_crit_); 108 rtc::CritScope cs(&stats_crit_);
108 video_bitrate_.Update(packet_size, clock_->TimeInMilliseconds()); 109 video_bitrate_.Update(packet_size, clock_->TimeInMilliseconds());
109 TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), 110 TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
110 "Video::PacketNormal", "timestamp", rtp_timestamp, 111 "Video::PacketNormal", "timestamp", rtp_timestamp,
111 "seqnum", seq_num); 112 "seqnum", seq_num);
112 } 113 }
113 114
114 void RTPSenderVideo::SendVideoPacketAsRed( 115 void RTPSenderVideo::SendVideoPacketAsRed(
115 std::unique_ptr<RtpPacketToSend> media_packet, 116 std::unique_ptr<RtpPacketToSend> media_packet,
116 StorageType media_packet_storage, 117 StorageType media_packet_storage,
117 bool protect) { 118 bool protect_packet) {
118 uint32_t rtp_timestamp = media_packet->Timestamp(); 119 uint32_t rtp_timestamp = media_packet->Timestamp();
119 uint16_t media_seq_num = media_packet->SequenceNumber(); 120 uint16_t media_seq_num = media_packet->SequenceNumber();
120 121
121 std::unique_ptr<RtpPacketToSend> red_packet( 122 std::unique_ptr<RtpPacketToSend> red_packet(
122 new RtpPacketToSend(*media_packet)); 123 new RtpPacketToSend(*media_packet));
123 BuildRedPayload(*media_packet, red_packet.get()); 124 BuildRedPayload(*media_packet, red_packet.get());
124 125
125 std::vector<std::unique_ptr<RedPacket>> fec_packets; 126 std::vector<std::unique_ptr<RedPacket>> fec_packets;
126 StorageType fec_storage = kDontRetransmit; 127 StorageType fec_storage = kDontRetransmit;
127 { 128 {
128 // Only protect while creating RED and FEC packets, not when sending. 129 // Only protect while creating RED and FEC packets, not when sending.
129 rtc::CritScope cs(&crit_); 130 rtc::CritScope cs(&crit_);
130 red_packet->SetPayloadType(red_payload_type_); 131 red_packet->SetPayloadType(red_payload_type_);
131 if (protect) { 132 if (ulpfec_enabled() && protect_packet) {
132 ulpfec_generator_.AddRtpPacketAndGenerateFec( 133 ulpfec_generator_.AddRtpPacketAndGenerateFec(
133 media_packet->data(), media_packet->payload_size(), 134 media_packet->data(), media_packet->payload_size(),
134 media_packet->headers_size()); 135 media_packet->headers_size());
135 } 136 }
136 uint16_t num_fec_packets = ulpfec_generator_.NumAvailableFecPackets(); 137 uint16_t num_fec_packets = ulpfec_generator_.NumAvailableFecPackets();
danilchap 2016/11/08 11:45:08 probably cleaner to hide this statement (and thus
brandtr 2016/11/09 10:40:00 Makes sense. Done.
137 if (num_fec_packets > 0) { 138 if (num_fec_packets > 0) {
138 uint16_t first_fec_sequence_number = 139 uint16_t first_fec_sequence_number =
139 rtp_sender_->AllocateSequenceNumber(num_fec_packets); 140 rtp_sender_->AllocateSequenceNumber(num_fec_packets);
140 fec_packets = ulpfec_generator_.GetUlpfecPacketsAsRed( 141 fec_packets = ulpfec_generator_.GetUlpfecPacketsAsRed(
141 red_payload_type_, ulpfec_payload_type_, first_fec_sequence_number, 142 red_payload_type_, ulpfec_payload_type_, first_fec_sequence_number,
142 media_packet->headers_size()); 143 media_packet->headers_size());
143 RTC_DCHECK_EQ(num_fec_packets, fec_packets.size()); 144 RTC_DCHECK_EQ(num_fec_packets, fec_packets.size());
144 if (retransmission_settings_ & kRetransmitFECPackets) 145 if (retransmission_settings_ & kRetransmitFECPackets)
145 fec_storage = kAllowRetransmission; 146 fec_storage = kAllowRetransmission;
146 } 147 }
(...skipping 16 matching lines...) Expand all
163 std::unique_ptr<RtpPacketToSend> rtp_packet( 164 std::unique_ptr<RtpPacketToSend> rtp_packet(
164 new RtpPacketToSend(*media_packet)); 165 new RtpPacketToSend(*media_packet));
165 RTC_CHECK(rtp_packet->Parse(fec_packet->data(), fec_packet->length())); 166 RTC_CHECK(rtp_packet->Parse(fec_packet->data(), fec_packet->length()));
166 rtp_packet->set_capture_time_ms(media_packet->capture_time_ms()); 167 rtp_packet->set_capture_time_ms(media_packet->capture_time_ms());
167 uint16_t fec_sequence_number = rtp_packet->SequenceNumber(); 168 uint16_t fec_sequence_number = rtp_packet->SequenceNumber();
168 if (rtp_sender_->SendToNetwork(std::move(rtp_packet), fec_storage, 169 if (rtp_sender_->SendToNetwork(std::move(rtp_packet), fec_storage,
169 RtpPacketSender::kLowPriority)) { 170 RtpPacketSender::kLowPriority)) {
170 rtc::CritScope cs(&stats_crit_); 171 rtc::CritScope cs(&stats_crit_);
171 fec_bitrate_.Update(fec_packet->length(), clock_->TimeInMilliseconds()); 172 fec_bitrate_.Update(fec_packet->length(), clock_->TimeInMilliseconds());
172 TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), 173 TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
173 "Video::PacketFec", "timestamp", rtp_timestamp, 174 "Video::PacketUlpfec", "timestamp", rtp_timestamp,
174 "seqnum", fec_sequence_number); 175 "seqnum", fec_sequence_number);
175 } else { 176 } else {
176 LOG(LS_WARNING) << "Failed to send FEC packet " << fec_sequence_number; 177 LOG(LS_WARNING) << "Failed to send FEC packet " << fec_sequence_number;
177 } 178 }
178 } 179 }
179 } 180 }
180 181
182 std::vector<std::unique_ptr<RtpPacketToSend>> RTPSenderVideo::GetFlexfecPackets(
danilchap 2016/11/08 11:45:08 try to order functions same as in header file, i.e
brandtr 2016/11/09 10:40:00 I changed the .h file instead :) Now at least Sen
183 const RtpPacketToSend& media_packet) {
184 RTC_DCHECK(flexfec_sender_);
185
186 std::vector<std::unique_ptr<RtpPacketToSend>> fec_packets;
187 if (!flexfec_sender_->AddRtpPacketAndGenerateFec(media_packet)) {
188 return fec_packets;
189 }
190 if (flexfec_sender_->FecAvailable()) {
191 fec_packets = flexfec_sender_->GetFecPackets();
192 }
193
194 return fec_packets;
195 }
196
197 void RTPSenderVideo::SendFlexfecPackets(
198 std::vector<std::unique_ptr<RtpPacketToSend>>* fec_packets) {
199 for (auto& fec_packet : *fec_packets) {
200 uint32_t timestamp = fec_packet->Timestamp();
201 uint16_t seq_num = fec_packet->SequenceNumber();
202 // We do not support retransmitting lost FlexFEC packets.
203 constexpr StorageType kFecStorage = kDontRetransmit;
danilchap 2016/11/08 11:45:08 the enums values probably self-explained already,
brandtr 2016/11/09 10:40:00 Removed.
204 constexpr RtpPacketSender::Priority kFecPriority =
205 RtpPacketSender::kLowPriority;
206 if (rtp_sender_->SendToNetwork(std::move(fec_packet), kFecStorage,
207 kFecPriority)) {
208 // TODO(brandtr): Wire up stats here.
danilchap 2016/11/08 11:45:08 may be resolve this TODO right away? or is it more
brandtr 2016/11/09 10:40:00 Yes, it's more complicated, since I want to do a c
209 TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
210 "Video::PacketFlexfec", "timestamp", timestamp,
211 "seqnum", seq_num);
212 } else {
213 LOG(LS_WARNING) << "Failed to send FlexFEC packet " << seq_num;
214 }
215 }
216 fec_packets->clear();
217 }
218
181 void RTPSenderVideo::SetUlpfecConfig(int red_payload_type, 219 void RTPSenderVideo::SetUlpfecConfig(int red_payload_type,
182 int ulpfec_payload_type) { 220 int ulpfec_payload_type) {
183 // Sanity check. Per the definition of UlpfecConfig (see config.h), 221 // Sanity check. Per the definition of UlpfecConfig (see config.h),
184 // a payload type of -1 means that the corresponding feature is 222 // a payload type of -1 means that the corresponding feature is
185 // turned off. 223 // turned off.
186 RTC_DCHECK_GE(red_payload_type, -1); 224 RTC_DCHECK_GE(red_payload_type, -1);
187 RTC_DCHECK_LE(red_payload_type, 127); 225 RTC_DCHECK_LE(red_payload_type, 127);
188 RTC_DCHECK_GE(ulpfec_payload_type, -1); 226 RTC_DCHECK_GE(ulpfec_payload_type, -1);
189 RTC_DCHECK_LE(ulpfec_payload_type, 127); 227 RTC_DCHECK_LE(ulpfec_payload_type, 127);
190 228
191 rtc::CritScope cs(&crit_); 229 rtc::CritScope cs(&crit_);
192 red_payload_type_ = red_payload_type; 230 red_payload_type_ = red_payload_type;
193 ulpfec_payload_type_ = ulpfec_payload_type; 231 ulpfec_payload_type_ = ulpfec_payload_type;
194 232
195 // Must not enable ULPFEC without RED. 233 // Must not enable ULPFEC without RED.
196 // TODO(brandtr): We currently support enabling RED without ULPFEC. Change 234 // TODO(brandtr): We currently support enabling RED without ULPFEC. Change
197 // this when we have removed the RED/RTX send-side workaround, so that we 235 // this when we have removed the RED/RTX send-side workaround, so that we
198 // ensure that RED and ULPFEC are only enabled together. 236 // ensure that RED and ULPFEC are only enabled together.
199 RTC_DCHECK(red_enabled() || !ulpfec_enabled()); 237 RTC_DCHECK(red_enabled() || !ulpfec_enabled());
200 238
201 // Reset FEC rates. 239 // Reset FEC parameters.
202 delta_fec_params_ = FecProtectionParams{0, 1, kFecMaskRandom}; 240 delta_fec_params_ = FecProtectionParams{0, 1, kFecMaskRandom};
203 key_fec_params_ = FecProtectionParams{0, 1, kFecMaskRandom}; 241 key_fec_params_ = FecProtectionParams{0, 1, kFecMaskRandom};
204 } 242 }
205 243
206 void RTPSenderVideo::GetUlpfecConfig(int* red_payload_type, 244 void RTPSenderVideo::GetUlpfecConfig(int* red_payload_type,
207 int* ulpfec_payload_type) const { 245 int* ulpfec_payload_type) const {
208 rtc::CritScope cs(&crit_); 246 rtc::CritScope cs(&crit_);
209 *red_payload_type = red_payload_type_; 247 *red_payload_type = red_payload_type_;
210 *ulpfec_payload_type = ulpfec_payload_type_; 248 *ulpfec_payload_type = ulpfec_payload_type_;
211 } 249 }
212 250
213 size_t RTPSenderVideo::FecPacketOverhead() const { 251 size_t RTPSenderVideo::FecPacketOverhead() const {
252 // Overhead is FEC headers plus RED for FEC header plus anything in RTP
253 // header beyond the 12 bytes base header (CSRC list, extensions...)
254 // This reason for the header extensions to be included here is that
255 // from an FEC viewpoint, they are part of the payload to be protected.
256 // (The base RTP header is already protected by the FEC header.)
257
258 if (flexfec_enabled()) {
259 return flexfec_sender_->MaxPacketOverhead() +
260 (rtp_sender_->RtpHeaderLength() - kRtpHeaderSize);
261 }
262
214 rtc::CritScope cs(&crit_); 263 rtc::CritScope cs(&crit_);
215 size_t overhead = 0; 264 size_t overhead = 0;
216 if (red_enabled()) { 265 if (red_enabled()) {
217 // Overhead is FEC headers plus RED for FEC header plus anything in RTP 266 overhead += kRedForFecHeaderLength;
218 // header beyond the 12 bytes base header (CSRC list, extensions...)
219 // This reason for the header extensions to be included here is that
220 // from an FEC viewpoint, they are part of the payload to be protected.
221 // (The base RTP header is already protected by the FEC header.)
222 return ulpfec_generator_.MaxPacketOverhead() + kRedForFecHeaderLength +
223 (rtp_sender_->RtpHeaderLength() - kRtpHeaderSize);
224 } 267 }
225 if (ulpfec_enabled()) 268 if (ulpfec_enabled()) {
226 overhead += ulpfec_generator_.MaxPacketOverhead(); 269 overhead += ulpfec_generator_.MaxPacketOverhead() +
270 (rtp_sender_->RtpHeaderLength() - kRtpHeaderSize);
271 }
227 return overhead; 272 return overhead;
228 } 273 }
229 274
230 void RTPSenderVideo::SetFecParameters(const FecProtectionParams& delta_params, 275 void RTPSenderVideo::SetFecParameters(const FecProtectionParams& delta_params,
231 const FecProtectionParams& key_params) { 276 const FecProtectionParams& key_params) {
232 rtc::CritScope cs(&crit_); 277 rtc::CritScope cs(&crit_);
233 if (ulpfec_enabled()) { 278 delta_fec_params_ = delta_params;
234 delta_fec_params_ = delta_params; 279 key_fec_params_ = key_params;
235 key_fec_params_ = key_params;
236 }
237 } 280 }
238 281
239 bool RTPSenderVideo::SendVideo(RtpVideoCodecTypes video_type, 282 bool RTPSenderVideo::SendVideo(RtpVideoCodecTypes video_type,
240 FrameType frame_type, 283 FrameType frame_type,
241 int8_t payload_type, 284 int8_t payload_type,
242 uint32_t rtp_timestamp, 285 uint32_t rtp_timestamp,
243 int64_t capture_time_ms, 286 int64_t capture_time_ms,
244 const uint8_t* payload_data, 287 const uint8_t* payload_data,
245 size_t payload_size, 288 size_t payload_size,
246 const RTPFragmentationHeader* fragmentation, 289 const RTPFragmentationHeader* fragmentation,
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 326
284 std::unique_ptr<RtpPacketizer> packetizer(RtpPacketizer::Create( 327 std::unique_ptr<RtpPacketizer> packetizer(RtpPacketizer::Create(
285 video_type, max_data_payload_length, 328 video_type, max_data_payload_length,
286 video_header ? &(video_header->codecHeader) : nullptr, frame_type)); 329 video_header ? &(video_header->codecHeader) : nullptr, frame_type));
287 330
288 StorageType storage; 331 StorageType storage;
289 bool red_enabled; 332 bool red_enabled;
290 bool first_frame = first_frame_sent_(); 333 bool first_frame = first_frame_sent_();
291 { 334 {
292 rtc::CritScope cs(&crit_); 335 rtc::CritScope cs(&crit_);
336
337 // Media packet storage.
338 storage = packetizer->GetStorageType(retransmission_settings_);
339
340 // FEC settings.
293 const FecProtectionParams& fec_params = 341 const FecProtectionParams& fec_params =
294 frame_type == kVideoFrameKey ? key_fec_params_ : delta_fec_params_; 342 frame_type == kVideoFrameKey ? key_fec_params_ : delta_fec_params_;
295 ulpfec_generator_.SetFecParameters(fec_params);
296 storage = packetizer->GetStorageType(retransmission_settings_);
297 red_enabled = this->red_enabled(); 343 red_enabled = this->red_enabled();
344 if (flexfec_enabled()) {
danilchap 2016/11/08 11:45:08 in this file it is more common to omit {} for one-
brandtr 2016/11/09 10:40:00 Yep, removed.
345 flexfec_sender_->SetFecParameters(fec_params);
346 }
347 if (ulpfec_enabled()) {
348 ulpfec_generator_.SetFecParameters(fec_params);
349 }
298 } 350 }
299 351
300 // TODO(changbin): we currently don't support to configure the codec to 352 // TODO(changbin): we currently don't support to configure the codec to
301 // output multiple partitions for VP8. Should remove below check after the 353 // output multiple partitions for VP8. Should remove below check after the
302 // issue is fixed. 354 // issue is fixed.
303 const RTPFragmentationHeader* frag = 355 const RTPFragmentationHeader* frag =
304 (video_type == kRtpVideoVp8) ? NULL : fragmentation; 356 (video_type == kRtpVideoVp8) ? NULL : fragmentation;
305 357
306 packetizer->SetPayloadData(payload_data, payload_size, frag); 358 packetizer->SetPayloadData(payload_data, payload_size, frag);
307 359
308 bool first = true; 360 bool first = true;
309 bool last = false; 361 bool last = false;
310 while (!last) { 362 while (!last) {
311 std::unique_ptr<RtpPacketToSend> packet(new RtpPacketToSend(*rtp_header)); 363 std::unique_ptr<RtpPacketToSend> packet(new RtpPacketToSend(*rtp_header));
312 uint8_t* payload = packet->AllocatePayload(max_data_payload_length); 364 uint8_t* payload = packet->AllocatePayload(max_data_payload_length);
313 RTC_DCHECK(payload); 365 RTC_DCHECK(payload);
314 366
315 size_t payload_bytes_in_packet = 0; 367 size_t payload_bytes_in_packet = 0;
316 if (!packetizer->NextPacket(payload, &payload_bytes_in_packet, &last)) 368 if (!packetizer->NextPacket(payload, &payload_bytes_in_packet, &last))
317 return false; 369 return false;
318 370
319 packet->SetPayloadSize(payload_bytes_in_packet); 371 packet->SetPayloadSize(payload_bytes_in_packet);
320 packet->SetMarker(last); 372 packet->SetMarker(last);
321 if (!rtp_sender_->AssignSequenceNumber(packet.get())) 373 if (!rtp_sender_->AssignSequenceNumber(packet.get()))
322 return false; 374 return false;
323 375
324 if (red_enabled) { 376 const bool protect_packet =
325 SendVideoPacketAsRed(std::move(packet), storage, 377 (packetizer->GetProtectionType() == kProtectedPacket);
326 packetizer->GetProtectionType() == kProtectedPacket); 378 // Note that we either send non-encapsulated media packets with FlexFEC
danilchap 2016/11/08 11:45:08 this comments feels like repeating (not explaining
brandtr 2016/11/09 10:40:00 Agree that the comment is a bit superfluous. I hav
379 // packets, or RED-encapsulated media packets with our without ULPFEC,
380 // packets, or non-encapsulated media packets without any FEC packets.
381 // If both FlexFEC and RED+ULPFEC are enabled, FlexFEC takes priority.
382 // TODO(brandtr): Remove this FlexFEC code path, when FlexfecSender
383 // is wired up to PacedSender instead.
384 if (flexfec_enabled()) {
385 std::vector<std::unique_ptr<RtpPacketToSend>> fec_packets;
386 if (protect_packet)
387 fec_packets = GetFlexfecPackets(*packet);
388 // Send media packet as usual.
389 SendVideoPacket(std::move(packet), storage);
390 // Send available FlexFEC packets after main media packet is sent.
391 if (!fec_packets.empty())
392 SendFlexfecPackets(&fec_packets);
danilchap 2016/11/08 11:45:08 may be cleaner to change SendFlexfecPackets to tak
brandtr 2016/11/09 10:40:00 Yes, that would have been nicer. Now that function
393 } else if (red_enabled) {
394 SendVideoPacketAsRed(std::move(packet), storage, protect_packet);
327 } else { 395 } else {
328 SendVideoPacket(std::move(packet), storage); 396 SendVideoPacket(std::move(packet), storage);
329 } 397 }
330 398
331 if (first_frame) { 399 if (first_frame) {
332 if (first) { 400 if (first) {
333 LOG(LS_INFO) 401 LOG(LS_INFO)
334 << "Sent first RTP packet of the first video frame (pre-pacer)"; 402 << "Sent first RTP packet of the first video frame (pre-pacer)";
335 } 403 }
336 if (last) { 404 if (last) {
(...skipping 23 matching lines...) Expand all
360 rtc::CritScope cs(&crit_); 428 rtc::CritScope cs(&crit_);
361 return retransmission_settings_; 429 return retransmission_settings_;
362 } 430 }
363 431
364 void RTPSenderVideo::SetSelectiveRetransmissions(uint8_t settings) { 432 void RTPSenderVideo::SetSelectiveRetransmissions(uint8_t settings) {
365 rtc::CritScope cs(&crit_); 433 rtc::CritScope cs(&crit_);
366 retransmission_settings_ = settings; 434 retransmission_settings_ = settings;
367 } 435 }
368 436
369 } // namespace webrtc 437 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698