| 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 11 matching lines...) Expand all Loading... |
| 22 #include "webrtc/system_wrappers/include/clock.h" | 22 #include "webrtc/system_wrappers/include/clock.h" |
| 23 | 23 |
| 24 namespace webrtc { | 24 namespace webrtc { |
| 25 | 25 |
| 26 const int64_t kStatisticsTimeoutMs = 8000; | 26 const int64_t kStatisticsTimeoutMs = 8000; |
| 27 const int64_t kStatisticsProcessIntervalMs = 1000; | 27 const int64_t kStatisticsProcessIntervalMs = 1000; |
| 28 | 28 |
| 29 StreamStatistician::~StreamStatistician() {} | 29 StreamStatistician::~StreamStatistician() {} |
| 30 | 30 |
| 31 StreamStatisticianImpl::StreamStatisticianImpl( | 31 StreamStatisticianImpl::StreamStatisticianImpl( |
| 32 uint32_t ssrc, |
| 32 Clock* clock, | 33 Clock* clock, |
| 33 RtcpStatisticsCallback* rtcp_callback, | 34 RtcpStatisticsCallback* rtcp_callback, |
| 34 StreamDataCountersCallback* rtp_callback) | 35 StreamDataCountersCallback* rtp_callback) |
| 35 : clock_(clock), | 36 : ssrc_(ssrc), |
| 37 clock_(clock), |
| 36 incoming_bitrate_(kStatisticsProcessIntervalMs, | 38 incoming_bitrate_(kStatisticsProcessIntervalMs, |
| 37 RateStatistics::kBpsScale), | 39 RateStatistics::kBpsScale), |
| 38 ssrc_(0), | |
| 39 max_reordering_threshold_(kDefaultMaxReorderingThreshold), | 40 max_reordering_threshold_(kDefaultMaxReorderingThreshold), |
| 40 jitter_q4_(0), | 41 jitter_q4_(0), |
| 41 cumulative_loss_(0), | 42 cumulative_loss_(0), |
| 42 jitter_q4_transmission_time_offset_(0), | 43 jitter_q4_transmission_time_offset_(0), |
| 43 last_receive_time_ms_(0), | 44 last_receive_time_ms_(0), |
| 44 last_received_timestamp_(0), | 45 last_received_timestamp_(0), |
| 45 last_received_transmission_time_offset_(0), | 46 last_received_transmission_time_offset_(0), |
| 46 received_seq_first_(0), | 47 received_seq_first_(0), |
| 47 received_seq_max_(0), | 48 received_seq_max_(0), |
| 48 received_seq_wraps_(0), | 49 received_seq_wraps_(0), |
| 49 received_packet_overhead_(12), | 50 received_packet_overhead_(12), |
| 50 last_report_inorder_packets_(0), | 51 last_report_inorder_packets_(0), |
| 51 last_report_old_packets_(0), | 52 last_report_old_packets_(0), |
| 52 last_report_seq_max_(0), | 53 last_report_seq_max_(0), |
| 53 rtcp_callback_(rtcp_callback), | 54 rtcp_callback_(rtcp_callback), |
| 54 rtp_callback_(rtp_callback) {} | 55 rtp_callback_(rtp_callback) {} |
| 55 | 56 |
| 56 void StreamStatisticianImpl::IncomingPacket(const RTPHeader& header, | 57 void StreamStatisticianImpl::IncomingPacket(const RTPHeader& header, |
| 57 size_t packet_length, | 58 size_t packet_length, |
| 58 bool retransmitted) { | 59 bool retransmitted) { |
| 59 UpdateCounters(header, packet_length, retransmitted); | 60 auto counters = UpdateCounters(header, packet_length, retransmitted); |
| 60 NotifyRtpCallback(); | 61 rtp_callback_->DataCountersUpdated(counters, ssrc_); |
| 61 } | 62 } |
| 62 | 63 |
| 63 void StreamStatisticianImpl::UpdateCounters(const RTPHeader& header, | 64 StreamDataCounters StreamStatisticianImpl::UpdateCounters( |
| 64 size_t packet_length, | 65 const RTPHeader& header, |
| 65 bool retransmitted) { | 66 size_t packet_length, |
| 67 bool retransmitted) { |
| 66 rtc::CritScope cs(&stream_lock_); | 68 rtc::CritScope cs(&stream_lock_); |
| 67 bool in_order = InOrderPacketInternal(header.sequenceNumber); | 69 bool in_order = InOrderPacketInternal(header.sequenceNumber); |
| 68 ssrc_ = header.ssrc; | 70 RTC_DCHECK_EQ(ssrc_, header.ssrc); |
| 69 incoming_bitrate_.Update(packet_length, clock_->TimeInMilliseconds()); | 71 incoming_bitrate_.Update(packet_length, clock_->TimeInMilliseconds()); |
| 70 receive_counters_.transmitted.AddPacket(packet_length, header); | 72 receive_counters_.transmitted.AddPacket(packet_length, header); |
| 71 if (!in_order && retransmitted) { | 73 if (!in_order && retransmitted) { |
| 72 receive_counters_.retransmitted.AddPacket(packet_length, header); | 74 receive_counters_.retransmitted.AddPacket(packet_length, header); |
| 73 } | 75 } |
| 74 | 76 |
| 75 if (receive_counters_.transmitted.packets == 1) { | 77 if (receive_counters_.transmitted.packets == 1) { |
| 76 received_seq_first_ = header.sequenceNumber; | 78 received_seq_first_ = header.sequenceNumber; |
| 77 receive_counters_.first_packet_time_ms = clock_->TimeInMilliseconds(); | 79 receive_counters_.first_packet_time_ms = clock_->TimeInMilliseconds(); |
| 78 } | 80 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 102 last_received_timestamp_ = header.timestamp; | 104 last_received_timestamp_ = header.timestamp; |
| 103 last_receive_time_ntp_ = receive_time; | 105 last_receive_time_ntp_ = receive_time; |
| 104 last_receive_time_ms_ = clock_->TimeInMilliseconds(); | 106 last_receive_time_ms_ = clock_->TimeInMilliseconds(); |
| 105 } | 107 } |
| 106 | 108 |
| 107 size_t packet_oh = header.headerLength + header.paddingLength; | 109 size_t packet_oh = header.headerLength + header.paddingLength; |
| 108 | 110 |
| 109 // Our measured overhead. Filter from RFC 5104 4.2.1.2: | 111 // Our measured overhead. Filter from RFC 5104 4.2.1.2: |
| 110 // avg_OH (new) = 15/16*avg_OH (old) + 1/16*pckt_OH, | 112 // avg_OH (new) = 15/16*avg_OH (old) + 1/16*pckt_OH, |
| 111 received_packet_overhead_ = (15 * received_packet_overhead_ + packet_oh) >> 4; | 113 received_packet_overhead_ = (15 * received_packet_overhead_ + packet_oh) >> 4; |
| 114 return receive_counters_; |
| 112 } | 115 } |
| 113 | 116 |
| 114 void StreamStatisticianImpl::UpdateJitter(const RTPHeader& header, | 117 void StreamStatisticianImpl::UpdateJitter(const RTPHeader& header, |
| 115 NtpTime receive_time) { | 118 NtpTime receive_time) { |
| 116 uint32_t receive_time_rtp = | 119 uint32_t receive_time_rtp = |
| 117 NtpToRtp(receive_time, header.payload_type_frequency); | 120 NtpToRtp(receive_time, header.payload_type_frequency); |
| 118 uint32_t last_receive_time_rtp = | 121 uint32_t last_receive_time_rtp = |
| 119 NtpToRtp(last_receive_time_ntp_, header.payload_type_frequency); | 122 NtpToRtp(last_receive_time_ntp_, header.payload_type_frequency); |
| 120 int32_t time_diff_samples = (receive_time_rtp - last_receive_time_rtp) - | 123 int32_t time_diff_samples = (receive_time_rtp - last_receive_time_rtp) - |
| 121 (header.timestamp - last_received_timestamp_); | 124 (header.timestamp - last_received_timestamp_); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 143 time_diff_samples_ext = std::abs(time_diff_samples_ext); | 146 time_diff_samples_ext = std::abs(time_diff_samples_ext); |
| 144 | 147 |
| 145 if (time_diff_samples_ext < 450000) { | 148 if (time_diff_samples_ext < 450000) { |
| 146 int32_t jitter_diffQ4TransmissionTimeOffset = | 149 int32_t jitter_diffQ4TransmissionTimeOffset = |
| 147 (time_diff_samples_ext << 4) - jitter_q4_transmission_time_offset_; | 150 (time_diff_samples_ext << 4) - jitter_q4_transmission_time_offset_; |
| 148 jitter_q4_transmission_time_offset_ += | 151 jitter_q4_transmission_time_offset_ += |
| 149 ((jitter_diffQ4TransmissionTimeOffset + 8) >> 4); | 152 ((jitter_diffQ4TransmissionTimeOffset + 8) >> 4); |
| 150 } | 153 } |
| 151 } | 154 } |
| 152 | 155 |
| 153 void StreamStatisticianImpl::NotifyRtpCallback() { | |
| 154 StreamDataCounters data; | |
| 155 uint32_t ssrc; | |
| 156 { | |
| 157 rtc::CritScope cs(&stream_lock_); | |
| 158 data = receive_counters_; | |
| 159 ssrc = ssrc_; | |
| 160 } | |
| 161 rtp_callback_->DataCountersUpdated(data, ssrc); | |
| 162 } | |
| 163 | |
| 164 void StreamStatisticianImpl::NotifyRtcpCallback() { | |
| 165 RtcpStatistics data; | |
| 166 uint32_t ssrc; | |
| 167 { | |
| 168 rtc::CritScope cs(&stream_lock_); | |
| 169 data = last_reported_statistics_; | |
| 170 ssrc = ssrc_; | |
| 171 } | |
| 172 rtcp_callback_->StatisticsUpdated(data, ssrc); | |
| 173 } | |
| 174 | |
| 175 void StreamStatisticianImpl::FecPacketReceived(const RTPHeader& header, | 156 void StreamStatisticianImpl::FecPacketReceived(const RTPHeader& header, |
| 176 size_t packet_length) { | 157 size_t packet_length) { |
| 158 StreamDataCounters counters; |
| 177 { | 159 { |
| 178 rtc::CritScope cs(&stream_lock_); | 160 rtc::CritScope cs(&stream_lock_); |
| 179 receive_counters_.fec.AddPacket(packet_length, header); | 161 receive_counters_.fec.AddPacket(packet_length, header); |
| 162 counters = receive_counters_; |
| 180 } | 163 } |
| 181 NotifyRtpCallback(); | 164 rtp_callback_->DataCountersUpdated(counters, ssrc_); |
| 182 } | 165 } |
| 183 | 166 |
| 184 void StreamStatisticianImpl::SetMaxReorderingThreshold( | 167 void StreamStatisticianImpl::SetMaxReorderingThreshold( |
| 185 int max_reordering_threshold) { | 168 int max_reordering_threshold) { |
| 186 rtc::CritScope cs(&stream_lock_); | 169 rtc::CritScope cs(&stream_lock_); |
| 187 max_reordering_threshold_ = max_reordering_threshold; | 170 max_reordering_threshold_ = max_reordering_threshold; |
| 188 } | 171 } |
| 189 | 172 |
| 190 bool StreamStatisticianImpl::GetStatistics(RtcpStatistics* statistics, | 173 bool StreamStatisticianImpl::GetStatistics(RtcpStatistics* statistics, |
| 191 bool reset) { | 174 bool reset) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 203 return false; | 186 return false; |
| 204 } | 187 } |
| 205 // Just get last report. | 188 // Just get last report. |
| 206 *statistics = last_reported_statistics_; | 189 *statistics = last_reported_statistics_; |
| 207 return true; | 190 return true; |
| 208 } | 191 } |
| 209 | 192 |
| 210 *statistics = CalculateRtcpStatistics(); | 193 *statistics = CalculateRtcpStatistics(); |
| 211 } | 194 } |
| 212 | 195 |
| 213 NotifyRtcpCallback(); | 196 rtcp_callback_->StatisticsUpdated(*statistics, ssrc_); |
| 214 | |
| 215 return true; | 197 return true; |
| 216 } | 198 } |
| 217 | 199 |
| 218 RtcpStatistics StreamStatisticianImpl::CalculateRtcpStatistics() { | 200 RtcpStatistics StreamStatisticianImpl::CalculateRtcpStatistics() { |
| 219 RtcpStatistics stats; | 201 RtcpStatistics stats; |
| 220 | 202 |
| 221 if (last_report_inorder_packets_ == 0) { | 203 if (last_report_inorder_packets_ == 0) { |
| 222 // First time we send a report. | 204 // First time we send a report. |
| 223 last_report_seq_max_ = received_seq_first_ - 1; | 205 last_report_seq_max_ = received_seq_first_ - 1; |
| 224 } | 206 } |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 395 void ReceiveStatisticsImpl::IncomingPacket(const RTPHeader& header, | 377 void ReceiveStatisticsImpl::IncomingPacket(const RTPHeader& header, |
| 396 size_t packet_length, | 378 size_t packet_length, |
| 397 bool retransmitted) { | 379 bool retransmitted) { |
| 398 StreamStatisticianImpl* impl; | 380 StreamStatisticianImpl* impl; |
| 399 { | 381 { |
| 400 rtc::CritScope cs(&receive_statistics_lock_); | 382 rtc::CritScope cs(&receive_statistics_lock_); |
| 401 StatisticianImplMap::iterator it = statisticians_.find(header.ssrc); | 383 StatisticianImplMap::iterator it = statisticians_.find(header.ssrc); |
| 402 if (it != statisticians_.end()) { | 384 if (it != statisticians_.end()) { |
| 403 impl = it->second; | 385 impl = it->second; |
| 404 } else { | 386 } else { |
| 405 impl = new StreamStatisticianImpl(clock_, this, this); | 387 impl = new StreamStatisticianImpl(header.ssrc, clock_, this, this); |
| 406 statisticians_[header.ssrc] = impl; | 388 statisticians_[header.ssrc] = impl; |
| 407 } | 389 } |
| 408 } | 390 } |
| 409 // StreamStatisticianImpl instance is created once and only destroyed when | 391 // StreamStatisticianImpl instance is created once and only destroyed when |
| 410 // this whole ReceiveStatisticsImpl is destroyed. StreamStatisticianImpl has | 392 // this whole ReceiveStatisticsImpl is destroyed. StreamStatisticianImpl has |
| 411 // it's own locking so don't hold receive_statistics_lock_ (potential | 393 // it's own locking so don't hold receive_statistics_lock_ (potential |
| 412 // deadlock). | 394 // deadlock). |
| 413 impl->IncomingPacket(header, packet_length, retransmitted); | 395 impl->IncomingPacket(header, packet_length, retransmitted); |
| 414 } | 396 } |
| 415 | 397 |
| 416 void ReceiveStatisticsImpl::FecPacketReceived(const RTPHeader& header, | 398 void ReceiveStatisticsImpl::FecPacketReceived(const RTPHeader& header, |
| 417 size_t packet_length) { | 399 size_t packet_length) { |
| 418 rtc::CritScope cs(&receive_statistics_lock_); | 400 StreamStatisticianImpl* impl; |
| 419 StatisticianImplMap::iterator it = statisticians_.find(header.ssrc); | 401 { |
| 420 // Ignore FEC if it is the first packet. | 402 rtc::CritScope cs(&receive_statistics_lock_); |
| 421 if (it != statisticians_.end()) { | 403 StatisticianImplMap::iterator it = statisticians_.find(header.ssrc); |
| 422 it->second->FecPacketReceived(header, packet_length); | 404 // Ignore FEC if it is the first packet. |
| 405 if (it == statisticians_.end()) |
| 406 return; |
| 407 impl = it->second; |
| 423 } | 408 } |
| 409 impl->FecPacketReceived(header, packet_length); |
| 424 } | 410 } |
| 425 | 411 |
| 426 StatisticianMap ReceiveStatisticsImpl::GetActiveStatisticians() const { | 412 StatisticianMap ReceiveStatisticsImpl::GetActiveStatisticians() const { |
| 427 StatisticianMap active_statisticians; | 413 StatisticianMap active_statisticians; |
| 428 rtc::CritScope cs(&receive_statistics_lock_); | 414 rtc::CritScope cs(&receive_statistics_lock_); |
| 429 for (StatisticianImplMap::const_iterator it = statisticians_.begin(); | 415 for (StatisticianImplMap::const_iterator it = statisticians_.begin(); |
| 430 it != statisticians_.end(); ++it) { | 416 it != statisticians_.end(); ++it) { |
| 431 uint32_t secs; | 417 uint32_t secs; |
| 432 uint32_t frac; | 418 uint32_t frac; |
| 433 it->second->LastReceiveTimeNtp(&secs, &frac); | 419 it->second->LastReceiveTimeNtp(&secs, &frac); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 519 result.pop_back(); | 505 result.pop_back(); |
| 520 continue; | 506 continue; |
| 521 } | 507 } |
| 522 block.SetExtHighestSeqNum(stats.extended_highest_sequence_number); | 508 block.SetExtHighestSeqNum(stats.extended_highest_sequence_number); |
| 523 block.SetJitter(stats.jitter); | 509 block.SetJitter(stats.jitter); |
| 524 } | 510 } |
| 525 return result; | 511 return result; |
| 526 } | 512 } |
| 527 | 513 |
| 528 } // namespace webrtc | 514 } // namespace webrtc |
| OLD | NEW |