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 |