Chromium Code Reviews| 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 15 matching lines...) Expand all Loading... | |
| 26 #include "webrtc/call/congestion_controller.h" | 26 #include "webrtc/call/congestion_controller.h" |
| 27 #include "webrtc/call/rtc_event_log.h" | 27 #include "webrtc/call/rtc_event_log.h" |
| 28 #include "webrtc/common.h" | 28 #include "webrtc/common.h" |
| 29 #include "webrtc/config.h" | 29 #include "webrtc/config.h" |
| 30 #include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h" | 30 #include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h" |
| 31 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" | 31 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" |
| 32 #include "webrtc/modules/utility/include/process_thread.h" | 32 #include "webrtc/modules/utility/include/process_thread.h" |
| 33 #include "webrtc/system_wrappers/include/cpu_info.h" | 33 #include "webrtc/system_wrappers/include/cpu_info.h" |
| 34 #include "webrtc/system_wrappers/include/critical_section_wrapper.h" | 34 #include "webrtc/system_wrappers/include/critical_section_wrapper.h" |
| 35 #include "webrtc/system_wrappers/include/logging.h" | 35 #include "webrtc/system_wrappers/include/logging.h" |
| 36 #include "webrtc/system_wrappers/include/metrics.h" | |
| 36 #include "webrtc/system_wrappers/include/rw_lock_wrapper.h" | 37 #include "webrtc/system_wrappers/include/rw_lock_wrapper.h" |
| 37 #include "webrtc/system_wrappers/include/trace.h" | 38 #include "webrtc/system_wrappers/include/trace.h" |
| 38 #include "webrtc/video/video_receive_stream.h" | 39 #include "webrtc/video/video_receive_stream.h" |
| 39 #include "webrtc/video/video_send_stream.h" | 40 #include "webrtc/video/video_send_stream.h" |
| 40 #include "webrtc/video_engine/call_stats.h" | 41 #include "webrtc/video_engine/call_stats.h" |
| 41 #include "webrtc/voice_engine/include/voe_codec.h" | 42 #include "webrtc/voice_engine/include/voe_codec.h" |
| 42 | 43 |
| 43 namespace webrtc { | 44 namespace webrtc { |
| 44 | 45 |
| 45 const int Call::Config::kDefaultStartBitrateBps = 300000; | 46 const int Call::Config::kDefaultStartBitrateBps = 300000; |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 98 | 99 |
| 99 VoiceEngine* voice_engine() { | 100 VoiceEngine* voice_engine() { |
| 100 internal::AudioState* audio_state = | 101 internal::AudioState* audio_state = |
| 101 static_cast<internal::AudioState*>(config_.audio_state.get()); | 102 static_cast<internal::AudioState*>(config_.audio_state.get()); |
| 102 if (audio_state) | 103 if (audio_state) |
| 103 return audio_state->voice_engine(); | 104 return audio_state->voice_engine(); |
| 104 else | 105 else |
| 105 return nullptr; | 106 return nullptr; |
| 106 } | 107 } |
| 107 | 108 |
| 109 void UpdateHistograms(); | |
| 110 | |
| 111 const Clock* const clock_; | |
| 112 | |
| 108 const int num_cpu_cores_; | 113 const int num_cpu_cores_; |
| 109 const rtc::scoped_ptr<ProcessThread> module_process_thread_; | 114 const rtc::scoped_ptr<ProcessThread> module_process_thread_; |
| 110 const rtc::scoped_ptr<CallStats> call_stats_; | 115 const rtc::scoped_ptr<CallStats> call_stats_; |
| 111 const rtc::scoped_ptr<CongestionController> congestion_controller_; | 116 const rtc::scoped_ptr<CongestionController> congestion_controller_; |
| 112 Call::Config config_; | 117 Call::Config config_; |
| 113 rtc::ThreadChecker configuration_thread_checker_; | 118 rtc::ThreadChecker configuration_thread_checker_; |
| 114 | 119 |
| 115 bool network_enabled_; | 120 bool network_enabled_; |
| 116 | 121 |
| 117 rtc::scoped_ptr<RWLockWrapper> receive_crit_; | 122 rtc::scoped_ptr<RWLockWrapper> receive_crit_; |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 128 rtc::scoped_ptr<RWLockWrapper> send_crit_; | 133 rtc::scoped_ptr<RWLockWrapper> send_crit_; |
| 129 // Audio and Video send streams are owned by the client that creates them. | 134 // Audio and Video send streams are owned by the client that creates them. |
| 130 std::map<uint32_t, AudioSendStream*> audio_send_ssrcs_ GUARDED_BY(send_crit_); | 135 std::map<uint32_t, AudioSendStream*> audio_send_ssrcs_ GUARDED_BY(send_crit_); |
| 131 std::map<uint32_t, VideoSendStream*> video_send_ssrcs_ GUARDED_BY(send_crit_); | 136 std::map<uint32_t, VideoSendStream*> video_send_ssrcs_ GUARDED_BY(send_crit_); |
| 132 std::set<VideoSendStream*> video_send_streams_ GUARDED_BY(send_crit_); | 137 std::set<VideoSendStream*> video_send_streams_ GUARDED_BY(send_crit_); |
| 133 | 138 |
| 134 VideoSendStream::RtpStateMap suspended_video_send_ssrcs_; | 139 VideoSendStream::RtpStateMap suspended_video_send_ssrcs_; |
| 135 | 140 |
| 136 RtcEventLog* event_log_ = nullptr; | 141 RtcEventLog* event_log_ = nullptr; |
| 137 | 142 |
| 143 // The RateTrackers are only accessed (exclusively) from DeliverRtp or | |
| 144 // DeliverRtcp, and from the destructor, and therefore doesn't need any | |
| 145 // explicit synchronization. | |
| 146 rtc::RateTracker received_video_bytes_per_sec_; | |
| 147 rtc::RateTracker received_audio_bytes_per_sec_; | |
| 148 rtc::RateTracker received_rtcp_bytes_per_sec_; | |
| 149 int64_t first_rtp_packet_received_ms_; | |
|
pbos-webrtc
2015/11/11 16:24:29
(I assume the corner case where RTCP arrives first
stefan-webrtc
2015/11/11 18:15:22
Its a very slim corner case. If rtcp arrives first
| |
| 150 | |
| 138 RTC_DISALLOW_COPY_AND_ASSIGN(Call); | 151 RTC_DISALLOW_COPY_AND_ASSIGN(Call); |
| 139 }; | 152 }; |
| 140 } // namespace internal | 153 } // namespace internal |
| 141 | 154 |
| 142 Call* Call::Create(const Call::Config& config) { | 155 Call* Call::Create(const Call::Config& config) { |
| 143 return new internal::Call(config); | 156 return new internal::Call(config); |
| 144 } | 157 } |
| 145 | 158 |
| 146 namespace internal { | 159 namespace internal { |
| 147 | 160 |
| 148 Call::Call(const Call::Config& config) | 161 Call::Call(const Call::Config& config) |
| 149 : num_cpu_cores_(CpuInfo::DetectNumberOfCores()), | 162 : clock_(Clock::GetRealTimeClock()), |
| 163 num_cpu_cores_(CpuInfo::DetectNumberOfCores()), | |
| 150 module_process_thread_(ProcessThread::Create("ModuleProcessThread")), | 164 module_process_thread_(ProcessThread::Create("ModuleProcessThread")), |
| 151 call_stats_(new CallStats()), | 165 call_stats_(new CallStats()), |
| 152 congestion_controller_(new CongestionController( | 166 congestion_controller_( |
| 153 module_process_thread_.get(), call_stats_.get())), | 167 new CongestionController(module_process_thread_.get(), |
| 168 call_stats_.get())), | |
| 154 config_(config), | 169 config_(config), |
| 155 network_enabled_(true), | 170 network_enabled_(true), |
| 156 receive_crit_(RWLockWrapper::CreateRWLock()), | 171 receive_crit_(RWLockWrapper::CreateRWLock()), |
| 157 send_crit_(RWLockWrapper::CreateRWLock()) { | 172 send_crit_(RWLockWrapper::CreateRWLock()), |
| 173 received_video_bytes_per_sec_(1000, 1), | |
| 174 received_audio_bytes_per_sec_(1000, 1), | |
| 175 received_rtcp_bytes_per_sec_(1000, 1), | |
| 176 first_rtp_packet_received_ms_(-1) { | |
| 158 RTC_DCHECK_GE(config.bitrate_config.min_bitrate_bps, 0); | 177 RTC_DCHECK_GE(config.bitrate_config.min_bitrate_bps, 0); |
| 159 RTC_DCHECK_GE(config.bitrate_config.start_bitrate_bps, | 178 RTC_DCHECK_GE(config.bitrate_config.start_bitrate_bps, |
| 160 config.bitrate_config.min_bitrate_bps); | 179 config.bitrate_config.min_bitrate_bps); |
| 161 if (config.bitrate_config.max_bitrate_bps != -1) { | 180 if (config.bitrate_config.max_bitrate_bps != -1) { |
| 162 RTC_DCHECK_GE(config.bitrate_config.max_bitrate_bps, | 181 RTC_DCHECK_GE(config.bitrate_config.max_bitrate_bps, |
| 163 config.bitrate_config.start_bitrate_bps); | 182 config.bitrate_config.start_bitrate_bps); |
| 164 } | 183 } |
| 165 if (config.audio_state.get()) { | 184 if (config.audio_state.get()) { |
| 166 ScopedVoEInterface<VoECodec> voe_codec(voice_engine()); | 185 ScopedVoEInterface<VoECodec> voe_codec(voice_engine()); |
| 167 event_log_ = voe_codec->GetEventLog(); | 186 event_log_ = voe_codec->GetEventLog(); |
| 168 } | 187 } |
| 169 | 188 |
| 170 Trace::CreateTrace(); | 189 Trace::CreateTrace(); |
| 171 module_process_thread_->Start(); | 190 module_process_thread_->Start(); |
| 172 module_process_thread_->RegisterModule(call_stats_.get()); | 191 module_process_thread_->RegisterModule(call_stats_.get()); |
| 173 | 192 |
| 174 congestion_controller_->SetBweBitrates( | 193 congestion_controller_->SetBweBitrates( |
| 175 config_.bitrate_config.min_bitrate_bps, | 194 config_.bitrate_config.min_bitrate_bps, |
| 176 config_.bitrate_config.start_bitrate_bps, | 195 config_.bitrate_config.start_bitrate_bps, |
| 177 config_.bitrate_config.max_bitrate_bps); | 196 config_.bitrate_config.max_bitrate_bps); |
| 178 | 197 |
| 179 congestion_controller_->GetBitrateController()->SetEventLog(event_log_); | 198 congestion_controller_->GetBitrateController()->SetEventLog(event_log_); |
| 180 } | 199 } |
| 181 | 200 |
| 182 Call::~Call() { | 201 Call::~Call() { |
| 202 UpdateHistograms(); | |
| 183 RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread()); | 203 RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread()); |
| 184 RTC_CHECK(audio_send_ssrcs_.empty()); | 204 RTC_CHECK(audio_send_ssrcs_.empty()); |
| 185 RTC_CHECK(video_send_ssrcs_.empty()); | 205 RTC_CHECK(video_send_ssrcs_.empty()); |
| 186 RTC_CHECK(video_send_streams_.empty()); | 206 RTC_CHECK(video_send_streams_.empty()); |
| 187 RTC_CHECK(audio_receive_ssrcs_.empty()); | 207 RTC_CHECK(audio_receive_ssrcs_.empty()); |
| 188 RTC_CHECK(video_receive_ssrcs_.empty()); | 208 RTC_CHECK(video_receive_ssrcs_.empty()); |
| 189 RTC_CHECK(video_receive_streams_.empty()); | 209 RTC_CHECK(video_receive_streams_.empty()); |
| 190 | 210 |
| 191 module_process_thread_->DeRegisterModule(call_stats_.get()); | 211 module_process_thread_->DeRegisterModule(call_stats_.get()); |
| 192 module_process_thread_->Stop(); | 212 module_process_thread_->Stop(); |
| 193 Trace::ReturnTrace(); | 213 Trace::ReturnTrace(); |
| 194 } | 214 } |
| 195 | 215 |
| 216 void Call::UpdateHistograms() { | |
| 217 if (first_rtp_packet_received_ms_ == -1) | |
| 218 return; | |
| 219 int64_t elapsed_sec = | |
| 220 (clock_->TimeInMilliseconds() - first_rtp_packet_received_ms_) / 1000; | |
| 221 if (elapsed_sec < metrics::kMinRunTimeInSeconds) | |
| 222 return; | |
| 223 int audio_bitrate_kbps = | |
| 224 received_audio_bytes_per_sec_.ComputeTotalRate() * 8 / 1000; | |
| 225 int video_bitrate_kbps = | |
| 226 received_video_bytes_per_sec_.ComputeTotalRate() * 8 / 1000; | |
| 227 int rtcp_bitrate_bps = received_rtcp_bytes_per_sec_.ComputeTotalRate() * 8; | |
| 228 if (video_bitrate_kbps > 0) { | |
| 229 RTC_HISTOGRAM_COUNTS_100000("WebRTC.Call.VideoBitrateReceivedInKbps", | |
| 230 video_bitrate_kbps); | |
| 231 } | |
| 232 if (audio_bitrate_kbps > 0) { | |
| 233 RTC_HISTOGRAM_COUNTS_100000("WebRTC.Call.AudioBitrateReceivedInKbps", | |
| 234 audio_bitrate_kbps); | |
| 235 } | |
| 236 if (rtcp_bitrate_bps > 0) { | |
| 237 RTC_HISTOGRAM_COUNTS_100000("WebRTC.Call.RtcpBitrateReceivedInBps", | |
| 238 rtcp_bitrate_bps); | |
| 239 } | |
| 240 RTC_HISTOGRAM_COUNTS_100000( | |
| 241 "WebRTC.Call.BitrateReceivedInKbps", | |
| 242 audio_bitrate_kbps + video_bitrate_kbps + rtcp_bitrate_bps / 1000); | |
| 243 } | |
| 244 | |
| 196 PacketReceiver* Call::Receiver() { | 245 PacketReceiver* Call::Receiver() { |
| 197 // TODO(solenberg): Some test cases in EndToEndTest use this from a different | 246 // TODO(solenberg): Some test cases in EndToEndTest use this from a different |
| 198 // thread. Re-enable once that is fixed. | 247 // thread. Re-enable once that is fixed. |
| 199 // RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread()); | 248 // RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread()); |
| 200 return this; | 249 return this; |
| 201 } | 250 } |
| 202 | 251 |
| 203 webrtc::AudioSendStream* Call::CreateAudioSendStream( | 252 webrtc::AudioSendStream* Call::CreateAudioSendStream( |
| 204 const webrtc::AudioSendStream::Config& config) { | 253 const webrtc::AudioSendStream::Config& config) { |
| 205 TRACE_EVENT0("webrtc", "Call::CreateAudioSendStream"); | 254 TRACE_EVENT0("webrtc", "Call::CreateAudioSendStream"); |
| (...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 520 } | 569 } |
| 521 } | 570 } |
| 522 | 571 |
| 523 PacketReceiver::DeliveryStatus Call::DeliverRtcp(MediaType media_type, | 572 PacketReceiver::DeliveryStatus Call::DeliverRtcp(MediaType media_type, |
| 524 const uint8_t* packet, | 573 const uint8_t* packet, |
| 525 size_t length) { | 574 size_t length) { |
| 526 // TODO(pbos): Figure out what channel needs it actually. | 575 // TODO(pbos): Figure out what channel needs it actually. |
| 527 // Do NOT broadcast! Also make sure it's a valid packet. | 576 // Do NOT broadcast! Also make sure it's a valid packet. |
| 528 // Return DELIVERY_UNKNOWN_SSRC if it can be determined that | 577 // Return DELIVERY_UNKNOWN_SSRC if it can be determined that |
| 529 // there's no receiver of the packet. | 578 // there's no receiver of the packet. |
| 579 received_rtcp_bytes_per_sec_.AddSamples(length); | |
| 530 bool rtcp_delivered = false; | 580 bool rtcp_delivered = false; |
| 531 if (media_type == MediaType::ANY || media_type == MediaType::VIDEO) { | 581 if (media_type == MediaType::ANY || media_type == MediaType::VIDEO) { |
| 532 ReadLockScoped read_lock(*receive_crit_); | 582 ReadLockScoped read_lock(*receive_crit_); |
| 533 for (VideoReceiveStream* stream : video_receive_streams_) { | 583 for (VideoReceiveStream* stream : video_receive_streams_) { |
| 534 if (stream->DeliverRtcp(packet, length)) { | 584 if (stream->DeliverRtcp(packet, length)) { |
| 535 rtcp_delivered = true; | 585 rtcp_delivered = true; |
| 536 if (event_log_) | 586 if (event_log_) |
| 537 event_log_->LogRtcpPacket(true, media_type, packet, length); | 587 event_log_->LogRtcpPacket(true, media_type, packet, length); |
| 538 } | 588 } |
| 539 } | 589 } |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 552 } | 602 } |
| 553 | 603 |
| 554 PacketReceiver::DeliveryStatus Call::DeliverRtp(MediaType media_type, | 604 PacketReceiver::DeliveryStatus Call::DeliverRtp(MediaType media_type, |
| 555 const uint8_t* packet, | 605 const uint8_t* packet, |
| 556 size_t length, | 606 size_t length, |
| 557 const PacketTime& packet_time) { | 607 const PacketTime& packet_time) { |
| 558 // Minimum RTP header size. | 608 // Minimum RTP header size. |
| 559 if (length < 12) | 609 if (length < 12) |
| 560 return DELIVERY_PACKET_ERROR; | 610 return DELIVERY_PACKET_ERROR; |
| 561 | 611 |
| 612 if (first_rtp_packet_received_ms_ == -1) | |
| 613 first_rtp_packet_received_ms_ = clock_->TimeInMilliseconds(); | |
| 614 | |
| 562 uint32_t ssrc = ByteReader<uint32_t>::ReadBigEndian(&packet[8]); | 615 uint32_t ssrc = ByteReader<uint32_t>::ReadBigEndian(&packet[8]); |
| 563 | |
| 564 ReadLockScoped read_lock(*receive_crit_); | 616 ReadLockScoped read_lock(*receive_crit_); |
| 565 if (media_type == MediaType::ANY || media_type == MediaType::AUDIO) { | 617 if (media_type == MediaType::ANY || media_type == MediaType::AUDIO) { |
| 566 auto it = audio_receive_ssrcs_.find(ssrc); | 618 auto it = audio_receive_ssrcs_.find(ssrc); |
| 567 if (it != audio_receive_ssrcs_.end()) { | 619 if (it != audio_receive_ssrcs_.end()) { |
| 620 received_audio_bytes_per_sec_.AddSamples(length); | |
| 568 auto status = it->second->DeliverRtp(packet, length, packet_time) | 621 auto status = it->second->DeliverRtp(packet, length, packet_time) |
| 569 ? DELIVERY_OK | 622 ? DELIVERY_OK |
| 570 : DELIVERY_PACKET_ERROR; | 623 : DELIVERY_PACKET_ERROR; |
| 571 if (status == DELIVERY_OK && event_log_) | 624 if (status == DELIVERY_OK && event_log_) |
| 572 event_log_->LogRtpHeader(true, media_type, packet, length); | 625 event_log_->LogRtpHeader(true, media_type, packet, length); |
| 573 return status; | 626 return status; |
| 574 } | 627 } |
| 575 } | 628 } |
| 576 if (media_type == MediaType::ANY || media_type == MediaType::VIDEO) { | 629 if (media_type == MediaType::ANY || media_type == MediaType::VIDEO) { |
| 577 auto it = video_receive_ssrcs_.find(ssrc); | 630 auto it = video_receive_ssrcs_.find(ssrc); |
| 578 if (it != video_receive_ssrcs_.end()) { | 631 if (it != video_receive_ssrcs_.end()) { |
| 632 received_video_bytes_per_sec_.AddSamples(length); | |
| 579 auto status = it->second->DeliverRtp(packet, length, packet_time) | 633 auto status = it->second->DeliverRtp(packet, length, packet_time) |
| 580 ? DELIVERY_OK | 634 ? DELIVERY_OK |
| 581 : DELIVERY_PACKET_ERROR; | 635 : DELIVERY_PACKET_ERROR; |
| 582 if (status == DELIVERY_OK && event_log_) | 636 if (status == DELIVERY_OK && event_log_) |
| 583 event_log_->LogRtpHeader(true, media_type, packet, length); | 637 event_log_->LogRtpHeader(true, media_type, packet, length); |
| 584 return status; | 638 return status; |
| 585 } | 639 } |
| 586 } | 640 } |
| 587 return DELIVERY_UNKNOWN_SSRC; | 641 return DELIVERY_UNKNOWN_SSRC; |
|
pbos-webrtc
2015/11/11 16:24:29
Do you wanna track unknown bitrate as well?
stefan-webrtc
2015/11/11 18:15:22
We can add that later if we see a need.
| |
| 588 } | 642 } |
| 589 | 643 |
| 590 PacketReceiver::DeliveryStatus Call::DeliverPacket( | 644 PacketReceiver::DeliveryStatus Call::DeliverPacket( |
| 591 MediaType media_type, | 645 MediaType media_type, |
| 592 const uint8_t* packet, | 646 const uint8_t* packet, |
| 593 size_t length, | 647 size_t length, |
| 594 const PacketTime& packet_time) { | 648 const PacketTime& packet_time) { |
| 595 // TODO(solenberg): Tests call this function on a network thread, libjingle | 649 // TODO(solenberg): Tests call this function on a network thread, libjingle |
| 596 // calls on the worker thread. We should move towards always using a network | 650 // calls on the worker thread. We should move towards always using a network |
| 597 // thread. Then this check can be enabled. | 651 // thread. Then this check can be enabled. |
| 598 // RTC_DCHECK(!configuration_thread_checker_.CalledOnValidThread()); | 652 // RTC_DCHECK(!configuration_thread_checker_.CalledOnValidThread()); |
| 599 if (RtpHeaderParser::IsRtcp(packet, length)) | 653 if (RtpHeaderParser::IsRtcp(packet, length)) |
| 600 return DeliverRtcp(media_type, packet, length); | 654 return DeliverRtcp(media_type, packet, length); |
| 601 | 655 |
| 602 return DeliverRtp(media_type, packet, length, packet_time); | 656 return DeliverRtp(media_type, packet, length, packet_time); |
| 603 } | 657 } |
| 604 | 658 |
| 605 } // namespace internal | 659 } // namespace internal |
| 606 } // namespace webrtc | 660 } // namespace webrtc |
| OLD | NEW |