OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2013 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 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
162 congestion_controller_->GetBitrateController() | 162 congestion_controller_->GetBitrateController() |
163 ->CreateRtcpBandwidthObserver(), | 163 ->CreateRtcpBandwidthObserver(), |
164 congestion_controller_->GetTransportFeedbackObserver(), | 164 congestion_controller_->GetTransportFeedbackObserver(), |
165 nullptr, | 165 nullptr, |
166 call_stats_->rtcp_rtt_stats(), | 166 call_stats_->rtcp_rtt_stats(), |
167 congestion_controller_->pacer(), | 167 congestion_controller_->pacer(), |
168 congestion_controller_->packet_router(), | 168 congestion_controller_->packet_router(), |
169 config_.rtp.ssrcs.size(), | 169 config_.rtp.ssrcs.size(), |
170 true), | 170 true), |
171 vie_receiver_(vie_channel_.vie_receiver()), | 171 vie_receiver_(vie_channel_.vie_receiver()), |
172 rtp_rtcp_modules_(vie_channel_.rtp_rtcp()), | |
172 input_(&vie_encoder_, | 173 input_(&vie_encoder_, |
173 config_.local_renderer, | 174 config_.local_renderer, |
174 &stats_proxy_, | 175 &stats_proxy_, |
175 &overuse_detector_) { | 176 &overuse_detector_) { |
176 LOG(LS_INFO) << "VideoSendStream: " << config_.ToString(); | 177 LOG(LS_INFO) << "VideoSendStream: " << config_.ToString(); |
177 | 178 |
178 RTC_DCHECK(!config_.rtp.ssrcs.empty()); | 179 RTC_DCHECK(!config_.rtp.ssrcs.empty()); |
179 RTC_DCHECK(module_process_thread_); | 180 RTC_DCHECK(module_process_thread_); |
180 RTC_DCHECK(call_stats_); | 181 RTC_DCHECK(call_stats_); |
181 RTC_DCHECK(congestion_controller_); | 182 RTC_DCHECK(congestion_controller_); |
(...skipping 20 matching lines...) Expand all Loading... | |
202 RTC_CHECK_EQ(0, vie_channel_.SetSendAbsoluteSendTimeStatus(true, id)); | 203 RTC_CHECK_EQ(0, vie_channel_.SetSendAbsoluteSendTimeStatus(true, id)); |
203 } else if (extension == RtpExtension::kVideoRotation) { | 204 } else if (extension == RtpExtension::kVideoRotation) { |
204 RTC_CHECK_EQ(0, vie_channel_.SetSendVideoRotationStatus(true, id)); | 205 RTC_CHECK_EQ(0, vie_channel_.SetSendVideoRotationStatus(true, id)); |
205 } else if (extension == RtpExtension::kTransportSequenceNumber) { | 206 } else if (extension == RtpExtension::kTransportSequenceNumber) { |
206 RTC_CHECK_EQ(0, vie_channel_.SetSendTransportSequenceNumber(true, id)); | 207 RTC_CHECK_EQ(0, vie_channel_.SetSendTransportSequenceNumber(true, id)); |
207 } else { | 208 } else { |
208 RTC_NOTREACHED() << "Registering unsupported RTP extension."; | 209 RTC_NOTREACHED() << "Registering unsupported RTP extension."; |
209 } | 210 } |
210 } | 211 } |
211 | 212 |
212 RtpRtcp* rtp_module = vie_channel_.rtp_rtcp(); | 213 remb_->AddRembSender(rtp_rtcp_modules_[0]); |
213 remb_->AddRembSender(rtp_module); | 214 rtp_rtcp_modules_[0]->SetREMBStatus(true); |
214 rtp_module->SetREMBStatus(true); | |
215 | 215 |
216 // Enable NACK, FEC or both. | 216 // Enable NACK, FEC or both. |
217 const bool enable_protection_nack = config_.rtp.nack.rtp_history_ms > 0; | 217 const bool enable_protection_nack = config_.rtp.nack.rtp_history_ms > 0; |
218 const bool enable_protection_fec = config_.rtp.fec.red_payload_type != -1; | 218 const bool enable_protection_fec = config_.rtp.fec.red_payload_type != -1; |
219 // TODO(changbin): Should set RTX for RED mapping in RTP sender in future. | 219 // TODO(changbin): Should set RTX for RED mapping in RTP sender in future. |
220 vie_channel_.SetProtectionMode(enable_protection_nack, enable_protection_fec, | 220 vie_channel_.SetProtectionMode(enable_protection_nack, enable_protection_fec, |
221 config_.rtp.fec.red_payload_type, | 221 config_.rtp.fec.red_payload_type, |
222 config_.rtp.fec.ulpfec_payload_type); | 222 config_.rtp.fec.ulpfec_payload_type); |
223 vie_encoder_.SetProtectionMethod(enable_protection_nack, | 223 vie_encoder_.SetProtectionMethod(enable_protection_nack, |
224 enable_protection_fec); | 224 enable_protection_fec); |
225 | 225 |
226 ConfigureSsrcs(); | 226 ConfigureSsrcs(); |
227 | 227 |
228 vie_channel_.SetRTCPCName(config_.rtp.c_name.c_str()); | 228 // TODO(pbos): Should we set CNAME on all RTP modules? |
229 | 229 rtp_rtcp_modules_.front()->SetCNAME(config_.rtp.c_name.c_str()); |
230 // 28 to match packet overhead in ModuleRtpRtcpImpl. | 230 // 28 to match packet overhead in ModuleRtpRtcpImpl. |
231 RTC_DCHECK_LE(config_.rtp.max_packet_size, static_cast<size_t>(0xFFFF - 28)); | 231 RTC_DCHECK_LE(config_.rtp.max_packet_size, static_cast<size_t>(0xFFFF - 28)); |
232 vie_channel_.SetMTU(static_cast<uint16_t>(config_.rtp.max_packet_size + 28)); | 232 const uint16_t mtu = static_cast<uint16_t>(config_.rtp.max_packet_size + 28); |
stefan-webrtc
2016/02/22 13:11:52
Make 28 a named constant.
pbos-webrtc
2016/02/22 13:21:01
Done.
| |
233 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) { | |
234 rtp_rtcp->RegisterRtcpStatisticsCallback(&stats_proxy_); | |
235 rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(&stats_proxy_); | |
236 rtp_rtcp->SetMaxTransferUnit(mtu); | |
237 } | |
233 | 238 |
234 RTC_DCHECK(config.encoder_settings.encoder != nullptr); | 239 RTC_DCHECK(config.encoder_settings.encoder != nullptr); |
235 RTC_DCHECK_GE(config.encoder_settings.payload_type, 0); | 240 RTC_DCHECK_GE(config.encoder_settings.payload_type, 0); |
236 RTC_DCHECK_LE(config.encoder_settings.payload_type, 127); | 241 RTC_DCHECK_LE(config.encoder_settings.payload_type, 127); |
237 RTC_CHECK_EQ(0, vie_encoder_.RegisterExternalEncoder( | 242 RTC_CHECK_EQ(0, vie_encoder_.RegisterExternalEncoder( |
238 config.encoder_settings.encoder, | 243 config.encoder_settings.encoder, |
239 config.encoder_settings.payload_type, | 244 config.encoder_settings.payload_type, |
240 config.encoder_settings.internal_source)); | 245 config.encoder_settings.internal_source)); |
241 | 246 |
242 RTC_CHECK(ReconfigureVideoEncoder(encoder_config)); | 247 RTC_CHECK(ReconfigureVideoEncoder(encoder_config)); |
243 | 248 |
244 vie_channel_.RegisterSendSideDelayObserver(&stats_proxy_); | 249 vie_channel_.RegisterSendSideDelayObserver(&stats_proxy_); |
245 | 250 |
246 if (config_.post_encode_callback) | 251 if (config_.post_encode_callback) |
247 vie_encoder_.RegisterPostEncodeImageCallback(&encoded_frame_proxy_); | 252 vie_encoder_.RegisterPostEncodeImageCallback(&encoded_frame_proxy_); |
248 | 253 |
249 if (config_.suspend_below_min_bitrate) | 254 if (config_.suspend_below_min_bitrate) |
250 vie_encoder_.SuspendBelowMinBitrate(); | 255 vie_encoder_.SuspendBelowMinBitrate(); |
251 | 256 |
252 encoder_feedback_.AddEncoder(config_.rtp.ssrcs, &vie_encoder_); | 257 encoder_feedback_.AddEncoder(config_.rtp.ssrcs, &vie_encoder_); |
253 | 258 |
254 vie_channel_.RegisterSendChannelRtcpStatisticsCallback(&stats_proxy_); | |
255 vie_channel_.RegisterSendChannelRtpStatisticsCallback(&stats_proxy_); | |
256 vie_channel_.RegisterRtcpPacketTypeCounterObserver(&stats_proxy_); | 259 vie_channel_.RegisterRtcpPacketTypeCounterObserver(&stats_proxy_); |
257 vie_channel_.RegisterSendBitrateObserver(&stats_proxy_); | 260 vie_channel_.RegisterSendBitrateObserver(&stats_proxy_); |
258 vie_channel_.RegisterSendFrameCountObserver(&stats_proxy_); | 261 vie_channel_.RegisterSendFrameCountObserver(&stats_proxy_); |
259 | 262 |
260 module_process_thread_->RegisterModule(&overuse_detector_); | 263 module_process_thread_->RegisterModule(&overuse_detector_); |
261 } | 264 } |
262 | 265 |
263 VideoSendStream::~VideoSendStream() { | 266 VideoSendStream::~VideoSendStream() { |
264 LOG(LS_INFO) << "~VideoSendStream: " << config_.ToString(); | 267 LOG(LS_INFO) << "~VideoSendStream: " << config_.ToString(); |
265 Stop(); | 268 Stop(); |
266 | 269 |
267 module_process_thread_->DeRegisterModule(&overuse_detector_); | 270 module_process_thread_->DeRegisterModule(&overuse_detector_); |
268 // Remove vcm_protection_callback (part of vie_channel_) before destroying | 271 // Remove vcm_protection_callback (part of vie_channel_) before destroying |
269 // ViEChannel. vcm_ is owned by ViEEncoder and the registered callback does | 272 // ViEChannel. vcm_ is owned by ViEEncoder and the registered callback does |
270 // not outlive it. | 273 // not outlive it. |
271 vcm_->RegisterProtectionCallback(nullptr); | 274 vcm_->RegisterProtectionCallback(nullptr); |
272 vie_channel_.RegisterSendFrameCountObserver(nullptr); | 275 vie_channel_.RegisterSendFrameCountObserver(nullptr); |
273 vie_channel_.RegisterSendBitrateObserver(nullptr); | 276 vie_channel_.RegisterSendBitrateObserver(nullptr); |
274 vie_channel_.RegisterRtcpPacketTypeCounterObserver(nullptr); | 277 vie_channel_.RegisterRtcpPacketTypeCounterObserver(nullptr); |
275 vie_channel_.RegisterSendChannelRtpStatisticsCallback(nullptr); | |
276 vie_channel_.RegisterSendChannelRtcpStatisticsCallback(nullptr); | |
277 | 278 |
278 vie_encoder_.DeRegisterExternalEncoder( | 279 vie_encoder_.DeRegisterExternalEncoder(config_.encoder_settings.payload_type); |
279 config_.encoder_settings.payload_type); | |
280 | 280 |
281 call_stats_->DeregisterStatsObserver(vie_channel_.GetStatsObserver()); | 281 call_stats_->DeregisterStatsObserver(vie_channel_.GetStatsObserver()); |
282 | 282 rtp_rtcp_modules_[0]->SetREMBStatus(false); |
283 RtpRtcp* rtp_module = vie_channel_.rtp_rtcp(); | 283 remb_->RemoveRembSender(rtp_rtcp_modules_[0]); |
284 rtp_module->SetREMBStatus(false); | |
285 remb_->RemoveRembSender(rtp_module); | |
286 | 284 |
287 // Remove the feedback, stop all encoding threads and processing. This must be | 285 // Remove the feedback, stop all encoding threads and processing. This must be |
288 // done before deleting the channel. | 286 // done before deleting the channel. |
289 encoder_feedback_.RemoveEncoder(&vie_encoder_); | 287 encoder_feedback_.RemoveEncoder(&vie_encoder_); |
290 | 288 |
291 congestion_controller_->GetRemoteBitrateEstimator(false)->RemoveStream( | 289 congestion_controller_->GetRemoteBitrateEstimator(false)->RemoveStream( |
292 vie_receiver_->GetRemoteSsrc()); | 290 vie_receiver_->GetRemoteSsrc()); |
293 } | 291 } |
294 | 292 |
295 VideoCaptureInput* VideoSendStream::Input() { | 293 VideoCaptureInput* VideoSendStream::Input() { |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
478 if (config_.overuse_callback) | 476 if (config_.overuse_callback) |
479 config_.overuse_callback->OnLoadUpdate(LoadObserver::kOveruse); | 477 config_.overuse_callback->OnLoadUpdate(LoadObserver::kOveruse); |
480 } | 478 } |
481 | 479 |
482 void VideoSendStream::NormalUsage() { | 480 void VideoSendStream::NormalUsage() { |
483 if (config_.overuse_callback) | 481 if (config_.overuse_callback) |
484 config_.overuse_callback->OnLoadUpdate(LoadObserver::kUnderuse); | 482 config_.overuse_callback->OnLoadUpdate(LoadObserver::kUnderuse); |
485 } | 483 } |
486 | 484 |
487 void VideoSendStream::ConfigureSsrcs() { | 485 void VideoSendStream::ConfigureSsrcs() { |
488 vie_channel_.SetSSRC(config_.rtp.ssrcs.front(), kViEStreamTypeNormal, 0); | 486 // Configure regular SSRCs. |
489 for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) { | 487 for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) { |
490 uint32_t ssrc = config_.rtp.ssrcs[i]; | 488 uint32_t ssrc = config_.rtp.ssrcs[i]; |
491 vie_channel_.SetSSRC(ssrc, kViEStreamTypeNormal, | 489 RtpRtcp* const rtp_rtcp = rtp_rtcp_modules_[i]; |
492 static_cast<unsigned char>(i)); | 490 rtp_rtcp->SetSSRC(ssrc); |
491 | |
492 // Restore RTP state if previous existed. | |
493 RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc); | 493 RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc); |
494 if (it != suspended_ssrcs_.end()) | 494 if (it != suspended_ssrcs_.end()) |
495 vie_channel_.SetRtpStateForSsrc(ssrc, it->second); | 495 rtp_rtcp->SetRtpStateForSsrc(ssrc, it->second); |
496 } | 496 } |
497 | 497 |
498 if (config_.rtp.rtx.ssrcs.empty()) { | 498 // Set up RTX if available. |
499 if (config_.rtp.rtx.ssrcs.empty()) | |
499 return; | 500 return; |
500 } | |
501 | 501 |
502 // Set up RTX. | 502 // Configure RTX SSRCs. |
503 RTC_DCHECK_EQ(config_.rtp.rtx.ssrcs.size(), config_.rtp.ssrcs.size()); | 503 RTC_DCHECK_EQ(config_.rtp.rtx.ssrcs.size(), config_.rtp.ssrcs.size()); |
504 for (size_t i = 0; i < config_.rtp.rtx.ssrcs.size(); ++i) { | 504 for (size_t i = 0; i < config_.rtp.rtx.ssrcs.size(); ++i) { |
505 uint32_t ssrc = config_.rtp.rtx.ssrcs[i]; | 505 uint32_t ssrc = config_.rtp.rtx.ssrcs[i]; |
506 vie_channel_.SetSSRC(config_.rtp.rtx.ssrcs[i], kViEStreamTypeRtx, | 506 RtpRtcp* const rtp_rtcp = rtp_rtcp_modules_[i]; |
507 static_cast<unsigned char>(i)); | 507 rtp_rtcp->SetRtxSsrc(ssrc); |
508 RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc); | 508 RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc); |
509 if (it != suspended_ssrcs_.end()) | 509 if (it != suspended_ssrcs_.end()) |
510 vie_channel_.SetRtpStateForSsrc(ssrc, it->second); | 510 rtp_rtcp->SetRtpStateForSsrc(ssrc, it->second); |
511 } | 511 } |
512 | 512 |
513 // Configure RTX payload types. | |
513 RTC_DCHECK_GE(config_.rtp.rtx.payload_type, 0); | 514 RTC_DCHECK_GE(config_.rtp.rtx.payload_type, 0); |
514 vie_channel_.SetRtxSendPayloadType(config_.rtp.rtx.payload_type, | 515 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) { |
515 config_.encoder_settings.payload_type); | 516 rtp_rtcp->SetRtxSendPayloadType(config_.rtp.rtx.payload_type, |
517 config_.encoder_settings.payload_type); | |
518 } | |
516 if (config_.rtp.fec.red_payload_type != -1 && | 519 if (config_.rtp.fec.red_payload_type != -1 && |
517 config_.rtp.fec.red_rtx_payload_type != -1) { | 520 config_.rtp.fec.red_rtx_payload_type != -1) { |
518 vie_channel_.SetRtxSendPayloadType(config_.rtp.fec.red_rtx_payload_type, | 521 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) { |
519 config_.rtp.fec.red_payload_type); | 522 rtp_rtcp->SetRtxSendPayloadType(config_.rtp.fec.red_rtx_payload_type, |
523 config_.rtp.fec.red_payload_type); | |
524 } | |
520 } | 525 } |
526 // Enable RTX in RTP modules. | |
527 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) | |
528 rtp_rtcp->SetRtxSendStatus(kRtxRetransmitted | kRtxRedundantPayloads); | |
stefan-webrtc
2016/02/22 13:11:52
I think you can move this to line 524 or 517
pbos-webrtc
2016/02/22 13:21:01
Done.
| |
521 } | 529 } |
522 | 530 |
523 std::map<uint32_t, RtpState> VideoSendStream::GetRtpStates() const { | 531 std::map<uint32_t, RtpState> VideoSendStream::GetRtpStates() const { |
524 std::map<uint32_t, RtpState> rtp_states; | 532 std::map<uint32_t, RtpState> rtp_states; |
525 for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) { | 533 for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) { |
526 uint32_t ssrc = config_.rtp.ssrcs[i]; | 534 uint32_t ssrc = config_.rtp.ssrcs[i]; |
527 rtp_states[ssrc] = vie_channel_.GetRtpStateForSsrc(ssrc); | 535 rtp_states[ssrc] = vie_channel_.GetRtpStateForSsrc(ssrc); |
528 } | 536 } |
529 | 537 |
530 for (size_t i = 0; i < config_.rtp.rtx.ssrcs.size(); ++i) { | 538 for (size_t i = 0; i < config_.rtp.rtx.ssrcs.size(); ++i) { |
531 uint32_t ssrc = config_.rtp.rtx.ssrcs[i]; | 539 uint32_t ssrc = config_.rtp.rtx.ssrcs[i]; |
532 rtp_states[ssrc] = vie_channel_.GetRtpStateForSsrc(ssrc); | 540 rtp_states[ssrc] = vie_channel_.GetRtpStateForSsrc(ssrc); |
533 } | 541 } |
534 | 542 |
535 return rtp_states; | 543 return rtp_states; |
536 } | 544 } |
537 | 545 |
538 void VideoSendStream::SignalNetworkState(NetworkState state) { | 546 void VideoSendStream::SignalNetworkState(NetworkState state) { |
539 // When network goes up, enable RTCP status before setting transmission state. | 547 // When network goes up, enable RTCP status before setting transmission state. |
540 // When it goes down, disable RTCP afterwards. This ensures that any packets | 548 // When it goes down, disable RTCP afterwards. This ensures that any packets |
541 // sent due to the network state changed will not be dropped. | 549 // sent due to the network state changed will not be dropped. |
542 if (state == kNetworkUp) | 550 if (state == kNetworkUp) { |
543 vie_channel_.SetRTCPMode(config_.rtp.rtcp_mode); | 551 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) |
552 rtp_rtcp->SetRTCPStatus(config_.rtp.rtcp_mode); | |
553 } | |
544 vie_encoder_.SetNetworkTransmissionState(state == kNetworkUp); | 554 vie_encoder_.SetNetworkTransmissionState(state == kNetworkUp); |
545 if (state == kNetworkDown) | 555 if (state == kNetworkDown) { |
546 vie_channel_.SetRTCPMode(RtcpMode::kOff); | 556 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) |
557 rtp_rtcp->SetRTCPStatus(RtcpMode::kOff); | |
558 } | |
547 } | 559 } |
548 | 560 |
549 int64_t VideoSendStream::GetRtt() const { | 561 int64_t VideoSendStream::GetRtt() const { |
550 webrtc::RtcpStatistics rtcp_stats; | 562 webrtc::RtcpStatistics rtcp_stats; |
551 uint16_t frac_lost; | 563 uint16_t frac_lost; |
552 uint32_t cumulative_lost; | 564 uint32_t cumulative_lost; |
553 uint32_t extended_max_sequence_number; | 565 uint32_t extended_max_sequence_number; |
554 uint32_t jitter; | 566 uint32_t jitter; |
555 int64_t rtt_ms; | 567 int64_t rtt_ms; |
556 if (vie_channel_.GetSendRtcpStatistics(&frac_lost, &cumulative_lost, | 568 if (vie_channel_.GetSendRtcpStatistics(&frac_lost, &cumulative_lost, |
557 &extended_max_sequence_number, | 569 &extended_max_sequence_number, &jitter, |
558 &jitter, &rtt_ms) == 0) { | 570 &rtt_ms) == 0) { |
559 return rtt_ms; | 571 return rtt_ms; |
560 } | 572 } |
561 return -1; | 573 return -1; |
562 } | 574 } |
563 | 575 |
564 int VideoSendStream::GetPaddingNeededBps() const { | 576 int VideoSendStream::GetPaddingNeededBps() const { |
565 return vie_encoder_.GetPaddingNeededBps(); | 577 return vie_encoder_.GetPaddingNeededBps(); |
566 } | 578 } |
567 | 579 |
568 bool VideoSendStream::SetSendCodec(VideoCodec video_codec) { | 580 bool VideoSendStream::SetSendCodec(VideoCodec video_codec) { |
(...skipping 29 matching lines...) Expand all Loading... | |
598 used_ssrcs.resize(static_cast<size_t>(video_codec.numberOfSimulcastStreams)); | 610 used_ssrcs.resize(static_cast<size_t>(video_codec.numberOfSimulcastStreams)); |
599 vie_encoder_.SetSsrcs(used_ssrcs); | 611 vie_encoder_.SetSsrcs(used_ssrcs); |
600 | 612 |
601 // Restart the media flow | 613 // Restart the media flow |
602 vie_encoder_.Restart(); | 614 vie_encoder_.Restart(); |
603 | 615 |
604 return true; | 616 return true; |
605 } | 617 } |
606 } // namespace internal | 618 } // namespace internal |
607 } // namespace webrtc | 619 } // namespace webrtc |
OLD | NEW |