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