1822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org/* 2822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. 3822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org * 4822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org * Use of this source code is governed by a BSD-style license 5822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org * that can be found in the LICENSE file in the root of the source 6822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org * tree. An additional intellectual property rights grant can be found 7822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org * in the file PATENTS. All contributing project authors may 8822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org * be found in the AUTHORS file in the root of the source tree. 9822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org */ 10822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org 11822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org#include "webrtc/modules/rtp_rtcp/source/receive_statistics_impl.h" 12822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org 137bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org#include <math.h> 147bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org 1500b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org#include "webrtc/base/scoped_ptr.h" 16822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org#include "webrtc/modules/rtp_rtcp/source/bitrate.h" 171227e8b3451b1a2f2a765bf6101cb0862f625568danilchap#include "webrtc/modules/rtp_rtcp/source/time_util.h" 1898f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/critical_section_wrapper.h" 19822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org 20822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.orgnamespace webrtc { 21822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org 22286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.orgconst int64_t kStatisticsTimeoutMs = 8000; 230b1534c52eab79372557a6d81aaf4dd9407f55d3pkasting@chromium.orgconst int64_t kStatisticsProcessIntervalMs = 1000; 24822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org 25286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.orgStreamStatistician::~StreamStatistician() {} 26822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org 2754ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.orgStreamStatisticianImpl::StreamStatisticianImpl( 2854ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org Clock* clock, 290e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org RtcpStatisticsCallback* rtcp_callback, 300e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org StreamDataCountersCallback* rtp_callback) 31286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org : clock_(clock), 327dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org stream_lock_(CriticalSectionWrapper::CreateCriticalSection()), 336811b6e308d16f160ba4c32650f195d5d3d9a2b1sprang@webrtc.org incoming_bitrate_(clock, NULL), 34822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org ssrc_(0), 357bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org max_reordering_threshold_(kDefaultMaxReorderingThreshold), 36822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org jitter_q4_(0), 37822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org cumulative_loss_(0), 38822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org jitter_q4_transmission_time_offset_(0), 397bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org last_receive_time_ms_(0), 40822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org last_received_timestamp_(0), 41822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org last_received_transmission_time_offset_(0), 42822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org received_seq_first_(0), 43822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org received_seq_max_(0), 44822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org received_seq_wraps_(0), 45822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org received_packet_overhead_(12), 46822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org last_report_inorder_packets_(0), 47822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org last_report_old_packets_(0), 48822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org last_report_seq_max_(0), 490e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org rtcp_callback_(rtcp_callback), 500e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org rtp_callback_(rtp_callback) {} 51822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org 52286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.orgvoid StreamStatisticianImpl::IncomingPacket(const RTPHeader& header, 5397d0489058ae7a983f7306f32cfd49a2356c6488asapersson@webrtc.org size_t packet_length, 547bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org bool retransmitted) { 5597d0489058ae7a983f7306f32cfd49a2356c6488asapersson@webrtc.org UpdateCounters(header, packet_length, retransmitted); 56a45cac0fb79782fd4bfe9c6ef1e1a74074a33aeesprang@webrtc.org NotifyRtpCallback(); 57a45cac0fb79782fd4bfe9c6ef1e1a74074a33aeesprang@webrtc.org} 58a45cac0fb79782fd4bfe9c6ef1e1a74074a33aeesprang@webrtc.org 59a45cac0fb79782fd4bfe9c6ef1e1a74074a33aeesprang@webrtc.orgvoid StreamStatisticianImpl::UpdateCounters(const RTPHeader& header, 6097d0489058ae7a983f7306f32cfd49a2356c6488asapersson@webrtc.org size_t packet_length, 61a45cac0fb79782fd4bfe9c6ef1e1a74074a33aeesprang@webrtc.org bool retransmitted) { 627dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org CriticalSectionScoped cs(stream_lock_.get()); 637bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org bool in_order = InOrderPacketInternal(header.sequenceNumber); 64822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org ssrc_ = header.ssrc; 6597d0489058ae7a983f7306f32cfd49a2356c6488asapersson@webrtc.org incoming_bitrate_.Update(packet_length); 664414939954fd908b6490ce1bb88271e161219aa3asapersson@webrtc.org receive_counters_.transmitted.AddPacket(packet_length, header); 670e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org if (!in_order && retransmitted) { 684414939954fd908b6490ce1bb88271e161219aa3asapersson@webrtc.org receive_counters_.retransmitted.AddPacket(packet_length, header); 690e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org } 70822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org 71cfd82dfc1156f6610388bec0ebbdeacaf47e9719asapersson@webrtc.org if (receive_counters_.transmitted.packets == 1) { 72822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org received_seq_first_ = header.sequenceNumber; 73d08d389ce836238030ec31e45c5f9a5535e0855fasapersson@webrtc.org receive_counters_.first_packet_time_ms = clock_->TimeInMilliseconds(); 74822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org } 75822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org 76822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org // Count only the new packets received. That is, if packets 1, 2, 3, 5, 4, 6 77822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org // are received, 4 will be ignored. 78822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org if (in_order) { 79822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org // Current time in samples. 801227e8b3451b1a2f2a765bf6101cb0862f625568danilchap NtpTime receive_time(*clock_); 81822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org 82822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org // Wrong if we use RetransmitOfOldPacket. 83cfd82dfc1156f6610388bec0ebbdeacaf47e9719asapersson@webrtc.org if (receive_counters_.transmitted.packets > 1 && 840e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org received_seq_max_ > header.sequenceNumber) { 85822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org // Wrap around detected. 86822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org received_seq_wraps_++; 87822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org } 88822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org // New max. 89822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org received_seq_max_ = header.sequenceNumber; 90822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org 910e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org // If new time stamp and more than one in-order packet received, calculate 920e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org // new jitter statistics. 93822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org if (header.timestamp != last_received_timestamp_ && 94cfd82dfc1156f6610388bec0ebbdeacaf47e9719asapersson@webrtc.org (receive_counters_.transmitted.packets - 95cfd82dfc1156f6610388bec0ebbdeacaf47e9719asapersson@webrtc.org receive_counters_.retransmitted.packets) > 1) { 961227e8b3451b1a2f2a765bf6101cb0862f625568danilchap UpdateJitter(header, receive_time); 97822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org } 98822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org last_received_timestamp_ = header.timestamp; 991227e8b3451b1a2f2a765bf6101cb0862f625568danilchap last_receive_time_ntp_ = receive_time; 1007bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org last_receive_time_ms_ = clock_->TimeInMilliseconds(); 101822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org } 102822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org 1034591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org size_t packet_oh = header.headerLength + header.paddingLength; 104822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org 105822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org // Our measured overhead. Filter from RFC 5104 4.2.1.2: 106822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org // avg_OH (new) = 15/16*avg_OH (old) + 1/16*pckt_OH, 107822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org received_packet_overhead_ = (15 * received_packet_overhead_ + packet_oh) >> 4; 1080e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org} 1090e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org 1100e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.orgvoid StreamStatisticianImpl::UpdateJitter(const RTPHeader& header, 1111227e8b3451b1a2f2a765bf6101cb0862f625568danilchap NtpTime receive_time) { 1121227e8b3451b1a2f2a765bf6101cb0862f625568danilchap uint32_t receive_time_rtp = 1131227e8b3451b1a2f2a765bf6101cb0862f625568danilchap NtpToRtp(receive_time, header.payload_type_frequency); 11462bafae6618fe3aefbd18657062abc98a40c3375pbos@webrtc.org uint32_t last_receive_time_rtp = 1151227e8b3451b1a2f2a765bf6101cb0862f625568danilchap NtpToRtp(last_receive_time_ntp_, header.payload_type_frequency); 1160e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org int32_t time_diff_samples = (receive_time_rtp - last_receive_time_rtp) - 1170e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org (header.timestamp - last_received_timestamp_); 1180e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org 1190e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org time_diff_samples = abs(time_diff_samples); 1200e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org 1210e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org // lib_jingle sometimes deliver crazy jumps in TS for the same stream. 1220e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org // If this happens, don't update jitter value. Use 5 secs video frequency 1230e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org // as the threshold. 1240e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org if (time_diff_samples < 450000) { 1250e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org // Note we calculate in Q4 to avoid using float. 1260e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org int32_t jitter_diff_q4 = (time_diff_samples << 4) - jitter_q4_; 1270e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org jitter_q4_ += ((jitter_diff_q4 + 8) >> 4); 1280e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org } 1290e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org 1300e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org // Extended jitter report, RFC 5450. 1310e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org // Actual network jitter, excluding the source-introduced jitter. 1320e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org int32_t time_diff_samples_ext = 1330e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org (receive_time_rtp - last_receive_time_rtp) - 1340e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org ((header.timestamp + 1350e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org header.extension.transmissionTimeOffset) - 1360e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org (last_received_timestamp_ + 1370e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org last_received_transmission_time_offset_)); 1380e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org 1390e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org time_diff_samples_ext = abs(time_diff_samples_ext); 1400e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org 1410e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org if (time_diff_samples_ext < 450000) { 1420e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org int32_t jitter_diffQ4TransmissionTimeOffset = 1430e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org (time_diff_samples_ext << 4) - jitter_q4_transmission_time_offset_; 1440e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org jitter_q4_transmission_time_offset_ += 1450e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org ((jitter_diffQ4TransmissionTimeOffset + 8) >> 4); 1460e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org } 1470e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org} 1480e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org 149a45cac0fb79782fd4bfe9c6ef1e1a74074a33aeesprang@webrtc.orgvoid StreamStatisticianImpl::NotifyRtpCallback() { 150a45cac0fb79782fd4bfe9c6ef1e1a74074a33aeesprang@webrtc.org StreamDataCounters data; 151a45cac0fb79782fd4bfe9c6ef1e1a74074a33aeesprang@webrtc.org uint32_t ssrc; 152a45cac0fb79782fd4bfe9c6ef1e1a74074a33aeesprang@webrtc.org { 153a45cac0fb79782fd4bfe9c6ef1e1a74074a33aeesprang@webrtc.org CriticalSectionScoped cs(stream_lock_.get()); 154a45cac0fb79782fd4bfe9c6ef1e1a74074a33aeesprang@webrtc.org data = receive_counters_; 155a45cac0fb79782fd4bfe9c6ef1e1a74074a33aeesprang@webrtc.org ssrc = ssrc_; 156a45cac0fb79782fd4bfe9c6ef1e1a74074a33aeesprang@webrtc.org } 157a45cac0fb79782fd4bfe9c6ef1e1a74074a33aeesprang@webrtc.org rtp_callback_->DataCountersUpdated(data, ssrc); 158a45cac0fb79782fd4bfe9c6ef1e1a74074a33aeesprang@webrtc.org} 159a45cac0fb79782fd4bfe9c6ef1e1a74074a33aeesprang@webrtc.org 160a45cac0fb79782fd4bfe9c6ef1e1a74074a33aeesprang@webrtc.orgvoid StreamStatisticianImpl::NotifyRtcpCallback() { 161a45cac0fb79782fd4bfe9c6ef1e1a74074a33aeesprang@webrtc.org RtcpStatistics data; 162a45cac0fb79782fd4bfe9c6ef1e1a74074a33aeesprang@webrtc.org uint32_t ssrc; 163a45cac0fb79782fd4bfe9c6ef1e1a74074a33aeesprang@webrtc.org { 164a45cac0fb79782fd4bfe9c6ef1e1a74074a33aeesprang@webrtc.org CriticalSectionScoped cs(stream_lock_.get()); 165a45cac0fb79782fd4bfe9c6ef1e1a74074a33aeesprang@webrtc.org data = last_reported_statistics_; 166a45cac0fb79782fd4bfe9c6ef1e1a74074a33aeesprang@webrtc.org ssrc = ssrc_; 167a45cac0fb79782fd4bfe9c6ef1e1a74074a33aeesprang@webrtc.org } 168a45cac0fb79782fd4bfe9c6ef1e1a74074a33aeesprang@webrtc.org rtcp_callback_->StatisticsUpdated(data, ssrc); 169a45cac0fb79782fd4bfe9c6ef1e1a74074a33aeesprang@webrtc.org} 170a45cac0fb79782fd4bfe9c6ef1e1a74074a33aeesprang@webrtc.org 171273fbbb921e61273c3d83eb494d0a68db7834d3dasapersson@webrtc.orgvoid StreamStatisticianImpl::FecPacketReceived(const RTPHeader& header, 172273fbbb921e61273c3d83eb494d0a68db7834d3dasapersson@webrtc.org size_t packet_length) { 173a45cac0fb79782fd4bfe9c6ef1e1a74074a33aeesprang@webrtc.org { 174a45cac0fb79782fd4bfe9c6ef1e1a74074a33aeesprang@webrtc.org CriticalSectionScoped cs(stream_lock_.get()); 1754414939954fd908b6490ce1bb88271e161219aa3asapersson@webrtc.org receive_counters_.fec.AddPacket(packet_length, header); 176a45cac0fb79782fd4bfe9c6ef1e1a74074a33aeesprang@webrtc.org } 177a45cac0fb79782fd4bfe9c6ef1e1a74074a33aeesprang@webrtc.org NotifyRtpCallback(); 178822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org} 179822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org 1807bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.orgvoid StreamStatisticianImpl::SetMaxReorderingThreshold( 1817bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org int max_reordering_threshold) { 1827dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org CriticalSectionScoped cs(stream_lock_.get()); 1837bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org max_reordering_threshold_ = max_reordering_threshold; 1847bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org} 1857bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org 18654ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.orgbool StreamStatisticianImpl::GetStatistics(RtcpStatistics* statistics, 18754ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org bool reset) { 1887dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org { 1897dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org CriticalSectionScoped cs(stream_lock_.get()); 190cfd82dfc1156f6610388bec0ebbdeacaf47e9719asapersson@webrtc.org if (received_seq_first_ == 0 && 191cfd82dfc1156f6610388bec0ebbdeacaf47e9719asapersson@webrtc.org receive_counters_.transmitted.payload_bytes == 0) { 1927dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org // We have not received anything. 193822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org return false; 194822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org } 1957dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org 1967dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org if (!reset) { 1977dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org if (last_report_inorder_packets_ == 0) { 1987dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org // No report. 1997dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org return false; 2007dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org } 2017dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org // Just get last report. 2027dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org *statistics = last_reported_statistics_; 2037dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org return true; 2047dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org } 2057dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org 206c00adbed7388c7c3a2e6214e6ab06242997e1825sprang@webrtc.org *statistics = CalculateRtcpStatistics(); 207822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org } 208822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org 209a45cac0fb79782fd4bfe9c6ef1e1a74074a33aeesprang@webrtc.org NotifyRtcpCallback(); 2100e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org 2117dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org return true; 2127dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org} 2137dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org 214c00adbed7388c7c3a2e6214e6ab06242997e1825sprang@webrtc.orgRtcpStatistics StreamStatisticianImpl::CalculateRtcpStatistics() { 2157dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org RtcpStatistics stats; 2167dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org 217822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org if (last_report_inorder_packets_ == 0) { 218822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org // First time we send a report. 219822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org last_report_seq_max_ = received_seq_first_ - 1; 220822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org } 221822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org 222822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org // Calculate fraction lost. 223822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org uint16_t exp_since_last = (received_seq_max_ - last_report_seq_max_); 224822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org 225822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org if (last_report_seq_max_ > received_seq_max_) { 226822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org // Can we assume that the seq_num can't go decrease over a full RTCP period? 227822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org exp_since_last = 0; 228822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org } 229822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org 230822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org // Number of received RTP packets since last report, counts all packets but 231822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org // not re-transmissions. 232822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org uint32_t rec_since_last = 233cfd82dfc1156f6610388bec0ebbdeacaf47e9719asapersson@webrtc.org (receive_counters_.transmitted.packets - 234cfd82dfc1156f6610388bec0ebbdeacaf47e9719asapersson@webrtc.org receive_counters_.retransmitted.packets) - last_report_inorder_packets_; 235822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org 236822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org // With NACK we don't know the expected retransmissions during the last 237822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org // second. We know how many "old" packets we have received. We just count 238822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org // the number of old received to estimate the loss, but it still does not 239822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org // guarantee an exact number since we run this based on time triggered by 240822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org // sending of an RTP packet. This should have a minimum effect. 241822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org 242822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org // With NACK we don't count old packets as received since they are 243822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org // re-transmitted. We use RTT to decide if a packet is re-ordered or 244822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org // re-transmitted. 245822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org uint32_t retransmitted_packets = 246cfd82dfc1156f6610388bec0ebbdeacaf47e9719asapersson@webrtc.org receive_counters_.retransmitted.packets - last_report_old_packets_; 247822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org rec_since_last += retransmitted_packets; 248822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org 249286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org int32_t missing = 0; 250822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org if (exp_since_last > rec_since_last) { 251286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org missing = (exp_since_last - rec_since_last); 252822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org } 253822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org uint8_t local_fraction_lost = 0; 254822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org if (exp_since_last) { 255822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org // Scale 0 to 255, where 255 is 100% loss. 256822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org local_fraction_lost = 257286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org static_cast<uint8_t>(255 * missing / exp_since_last); 258822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org } 2597dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org stats.fraction_lost = local_fraction_lost; 260822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org 261822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org // We need a counter for cumulative loss too. 262a72e7349d52366655076e609e9e32d456da7f5a2danilchap // TODO(danilchap): Ensure cumulative loss is below maximum value of 2^24. 263286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org cumulative_loss_ += missing; 2647dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org stats.cumulative_lost = cumulative_loss_; 2657dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org stats.extended_max_sequence_number = 2667dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org (received_seq_wraps_ << 16) + received_seq_max_; 267822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org // Note: internal jitter value is in Q4 and needs to be scaled by 1/16. 2687dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org stats.jitter = jitter_q4_ >> 4; 26954ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org 2707dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org // Store this report. 2717dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org last_reported_statistics_ = stats; 2727dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org 2737dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org // Only for report blocks in RTCP SR and RR. 2740e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org last_report_inorder_packets_ = 275cfd82dfc1156f6610388bec0ebbdeacaf47e9719asapersson@webrtc.org receive_counters_.transmitted.packets - 276cfd82dfc1156f6610388bec0ebbdeacaf47e9719asapersson@webrtc.org receive_counters_.retransmitted.packets; 277cfd82dfc1156f6610388bec0ebbdeacaf47e9719asapersson@webrtc.org last_report_old_packets_ = receive_counters_.retransmitted.packets; 2787dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org last_report_seq_max_ = received_seq_max_; 2797dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org 2807dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org return stats; 281822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org} 282822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org 283286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.orgvoid StreamStatisticianImpl::GetDataCounters( 2844591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org size_t* bytes_received, uint32_t* packets_received) const { 2857dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org CriticalSectionScoped cs(stream_lock_.get()); 286822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org if (bytes_received) { 287cfd82dfc1156f6610388bec0ebbdeacaf47e9719asapersson@webrtc.org *bytes_received = receive_counters_.transmitted.payload_bytes + 288cfd82dfc1156f6610388bec0ebbdeacaf47e9719asapersson@webrtc.org receive_counters_.transmitted.header_bytes + 289cfd82dfc1156f6610388bec0ebbdeacaf47e9719asapersson@webrtc.org receive_counters_.transmitted.padding_bytes; 290822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org } 291822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org if (packets_received) { 292cfd82dfc1156f6610388bec0ebbdeacaf47e9719asapersson@webrtc.org *packets_received = receive_counters_.transmitted.packets; 293822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org } 294822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org} 295822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org 296d952c40c7e31c1603988c1f09ebfba9f17c6a866asapersson@webrtc.orgvoid StreamStatisticianImpl::GetReceiveStreamDataCounters( 297d952c40c7e31c1603988c1f09ebfba9f17c6a866asapersson@webrtc.org StreamDataCounters* data_counters) const { 298d952c40c7e31c1603988c1f09ebfba9f17c6a866asapersson@webrtc.org CriticalSectionScoped cs(stream_lock_.get()); 299d952c40c7e31c1603988c1f09ebfba9f17c6a866asapersson@webrtc.org *data_counters = receive_counters_; 300d952c40c7e31c1603988c1f09ebfba9f17c6a866asapersson@webrtc.org} 301d952c40c7e31c1603988c1f09ebfba9f17c6a866asapersson@webrtc.org 302286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.orguint32_t StreamStatisticianImpl::BitrateReceived() const { 3037dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org CriticalSectionScoped cs(stream_lock_.get()); 304822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org return incoming_bitrate_.BitrateNow(); 305822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org} 306822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org 307286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.orgvoid StreamStatisticianImpl::ProcessBitrate() { 3087dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org CriticalSectionScoped cs(stream_lock_.get()); 309286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org incoming_bitrate_.Process(); 310286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org} 311286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org 312286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.orgvoid StreamStatisticianImpl::LastReceiveTimeNtp(uint32_t* secs, 313286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org uint32_t* frac) const { 3147dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org CriticalSectionScoped cs(stream_lock_.get()); 3151227e8b3451b1a2f2a765bf6101cb0862f625568danilchap *secs = last_receive_time_ntp_.seconds(); 3161227e8b3451b1a2f2a765bf6101cb0862f625568danilchap *frac = last_receive_time_ntp_.fractions(); 317286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org} 318286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org 3197bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.orgbool StreamStatisticianImpl::IsRetransmitOfOldPacket( 32016825b1a828bb4ff40f7682040e43a239b7b8ca3pkasting@chromium.org const RTPHeader& header, int64_t min_rtt) const { 3217dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org CriticalSectionScoped cs(stream_lock_.get()); 3227bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org if (InOrderPacketInternal(header.sequenceNumber)) { 3237bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org return false; 3247bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org } 3257bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org uint32_t frequency_khz = header.payload_type_frequency / 1000; 3267bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org assert(frequency_khz > 0); 3277bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org 3287bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org int64_t time_diff_ms = clock_->TimeInMilliseconds() - 3297bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org last_receive_time_ms_; 3307bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org 3317bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org // Diff in time stamp since last received in order. 3327bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org uint32_t timestamp_diff = header.timestamp - last_received_timestamp_; 33316825b1a828bb4ff40f7682040e43a239b7b8ca3pkasting@chromium.org uint32_t rtp_time_stamp_diff_ms = timestamp_diff / frequency_khz; 3347bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org 33516825b1a828bb4ff40f7682040e43a239b7b8ca3pkasting@chromium.org int64_t max_delay_ms = 0; 3367bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org if (min_rtt == 0) { 3377bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org // Jitter standard deviation in samples. 3387bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org float jitter_std = sqrt(static_cast<float>(jitter_q4_ >> 4)); 3397bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org 3407bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org // 2 times the standard deviation => 95% confidence. 3417bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org // And transform to milliseconds by dividing by the frequency in kHz. 34216825b1a828bb4ff40f7682040e43a239b7b8ca3pkasting@chromium.org max_delay_ms = static_cast<int64_t>((2 * jitter_std) / frequency_khz); 3437bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org 3447bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org // Min max_delay_ms is 1. 3457bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org if (max_delay_ms == 0) { 3467bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org max_delay_ms = 1; 3477bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org } 3487bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org } else { 3497bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org max_delay_ms = (min_rtt / 3) + 1; 3507bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org } 3517bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org return time_diff_ms > rtp_time_stamp_diff_ms + max_delay_ms; 3527bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org} 3537bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org 3547bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.orgbool StreamStatisticianImpl::IsPacketInOrder(uint16_t sequence_number) const { 3557dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org CriticalSectionScoped cs(stream_lock_.get()); 3567bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org return InOrderPacketInternal(sequence_number); 3577bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org} 3587bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org 3597bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.orgbool StreamStatisticianImpl::InOrderPacketInternal( 3607bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org uint16_t sequence_number) const { 3617bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org // First packet is always in order. 3627bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org if (last_receive_time_ms_ == 0) 3637bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org return true; 3647bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org 3657bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org if (IsNewerSequenceNumber(sequence_number, received_seq_max_)) { 3667bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org return true; 3677bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org } else { 3687bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org // If we have a restart of the remote side this packet is still in order. 3697bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org return !IsNewerSequenceNumber(sequence_number, received_seq_max_ - 3707bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org max_reordering_threshold_); 3717bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org } 3727bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org} 3737bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org 374286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.orgReceiveStatistics* ReceiveStatistics::Create(Clock* clock) { 375286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org return new ReceiveStatisticsImpl(clock); 376286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org} 377286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org 378286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.orgReceiveStatisticsImpl::ReceiveStatisticsImpl(Clock* clock) 379286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org : clock_(clock), 3807dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org receive_statistics_lock_(CriticalSectionWrapper::CreateCriticalSection()), 38154ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org last_rate_update_ms_(0), 3820e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org rtcp_stats_callback_(NULL), 3830e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org rtp_stats_callback_(NULL) {} 384286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org 385286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.orgReceiveStatisticsImpl::~ReceiveStatisticsImpl() { 386286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org while (!statisticians_.empty()) { 387286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org delete statisticians_.begin()->second; 388286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org statisticians_.erase(statisticians_.begin()); 389286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org } 390286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org} 391286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org 392286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.orgvoid ReceiveStatisticsImpl::IncomingPacket(const RTPHeader& header, 39397d0489058ae7a983f7306f32cfd49a2356c6488asapersson@webrtc.org size_t packet_length, 3940e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org bool retransmitted) { 395c30e9e230065ddde4cc439d9ba430273413e70d7sprang@webrtc.org StreamStatisticianImpl* impl; 3967dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org { 3977dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org CriticalSectionScoped cs(receive_statistics_lock_.get()); 398c30e9e230065ddde4cc439d9ba430273413e70d7sprang@webrtc.org StatisticianImplMap::iterator it = statisticians_.find(header.ssrc); 399c30e9e230065ddde4cc439d9ba430273413e70d7sprang@webrtc.org if (it != statisticians_.end()) { 400c30e9e230065ddde4cc439d9ba430273413e70d7sprang@webrtc.org impl = it->second; 401c30e9e230065ddde4cc439d9ba430273413e70d7sprang@webrtc.org } else { 402c30e9e230065ddde4cc439d9ba430273413e70d7sprang@webrtc.org impl = new StreamStatisticianImpl(clock_, this, this); 403c30e9e230065ddde4cc439d9ba430273413e70d7sprang@webrtc.org statisticians_[header.ssrc] = impl; 4047dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org } 405286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org } 406c30e9e230065ddde4cc439d9ba430273413e70d7sprang@webrtc.org // StreamStatisticianImpl instance is created once and only destroyed when 407c30e9e230065ddde4cc439d9ba430273413e70d7sprang@webrtc.org // this whole ReceiveStatisticsImpl is destroyed. StreamStatisticianImpl has 408c30e9e230065ddde4cc439d9ba430273413e70d7sprang@webrtc.org // it's own locking so don't hold receive_statistics_lock_ (potential 409c30e9e230065ddde4cc439d9ba430273413e70d7sprang@webrtc.org // deadlock). 41097d0489058ae7a983f7306f32cfd49a2356c6488asapersson@webrtc.org impl->IncomingPacket(header, packet_length, retransmitted); 4110e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org} 4120e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org 413273fbbb921e61273c3d83eb494d0a68db7834d3dasapersson@webrtc.orgvoid ReceiveStatisticsImpl::FecPacketReceived(const RTPHeader& header, 414273fbbb921e61273c3d83eb494d0a68db7834d3dasapersson@webrtc.org size_t packet_length) { 4150e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org CriticalSectionScoped cs(receive_statistics_lock_.get()); 416273fbbb921e61273c3d83eb494d0a68db7834d3dasapersson@webrtc.org StatisticianImplMap::iterator it = statisticians_.find(header.ssrc); 417c30e9e230065ddde4cc439d9ba430273413e70d7sprang@webrtc.org // Ignore FEC if it is the first packet. 418c30e9e230065ddde4cc439d9ba430273413e70d7sprang@webrtc.org if (it != statisticians_.end()) { 419273fbbb921e61273c3d83eb494d0a68db7834d3dasapersson@webrtc.org it->second->FecPacketReceived(header, packet_length); 420c30e9e230065ddde4cc439d9ba430273413e70d7sprang@webrtc.org } 421286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org} 422286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org 423286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.orgStatisticianMap ReceiveStatisticsImpl::GetActiveStatisticians() const { 4247dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org CriticalSectionScoped cs(receive_statistics_lock_.get()); 425286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org StatisticianMap active_statisticians; 426286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org for (StatisticianImplMap::const_iterator it = statisticians_.begin(); 427286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org it != statisticians_.end(); ++it) { 428286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org uint32_t secs; 429286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org uint32_t frac; 430286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org it->second->LastReceiveTimeNtp(&secs, &frac); 431286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org if (clock_->CurrentNtpInMilliseconds() - 432286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org Clock::NtpToMs(secs, frac) < kStatisticsTimeoutMs) { 433286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org active_statisticians[it->first] = it->second; 434286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org } 435286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org } 436286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org return active_statisticians; 437286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org} 438286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org 439286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.orgStreamStatistician* ReceiveStatisticsImpl::GetStatistician( 440286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org uint32_t ssrc) const { 4417dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org CriticalSectionScoped cs(receive_statistics_lock_.get()); 442286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org StatisticianImplMap::const_iterator it = statisticians_.find(ssrc); 443286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org if (it == statisticians_.end()) 444286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org return NULL; 445286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org return it->second; 4461a65d6c36b6a25f9f734176c697c684c3b43ac4bstefan@webrtc.org} 4471a65d6c36b6a25f9f734176c697c684c3b43ac4bstefan@webrtc.org 4487bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.orgvoid ReceiveStatisticsImpl::SetMaxReorderingThreshold( 4497bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org int max_reordering_threshold) { 4507dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org CriticalSectionScoped cs(receive_statistics_lock_.get()); 4517bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org for (StatisticianImplMap::iterator it = statisticians_.begin(); 4527bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org it != statisticians_.end(); ++it) { 4537bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org it->second->SetMaxReorderingThreshold(max_reordering_threshold); 4547bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org } 4557bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org} 4567bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org 457a0218a84d17a727111e2e24cf5af915b1b91c06ehenrike@webrtc.orgint32_t ReceiveStatisticsImpl::Process() { 4587dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org CriticalSectionScoped cs(receive_statistics_lock_.get()); 459286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org for (StatisticianImplMap::iterator it = statisticians_.begin(); 460286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org it != statisticians_.end(); ++it) { 461286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org it->second->ProcessBitrate(); 462286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org } 463286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org last_rate_update_ms_ = clock_->TimeInMilliseconds(); 464a0218a84d17a727111e2e24cf5af915b1b91c06ehenrike@webrtc.org return 0; 4651a65d6c36b6a25f9f734176c697c684c3b43ac4bstefan@webrtc.org} 4661a65d6c36b6a25f9f734176c697c684c3b43ac4bstefan@webrtc.org 4670b1534c52eab79372557a6d81aaf4dd9407f55d3pkasting@chromium.orgint64_t ReceiveStatisticsImpl::TimeUntilNextProcess() { 4687dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org CriticalSectionScoped cs(receive_statistics_lock_.get()); 4690b1534c52eab79372557a6d81aaf4dd9407f55d3pkasting@chromium.org int64_t time_since_last_update = clock_->TimeInMilliseconds() - 470286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org last_rate_update_ms_; 4710b1534c52eab79372557a6d81aaf4dd9407f55d3pkasting@chromium.org return std::max<int64_t>( 4720b1534c52eab79372557a6d81aaf4dd9407f55d3pkasting@chromium.org kStatisticsProcessIntervalMs - time_since_last_update, 0); 473286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org} 474286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org 47554ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.orgvoid ReceiveStatisticsImpl::RegisterRtcpStatisticsCallback( 47654ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org RtcpStatisticsCallback* callback) { 4777dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org CriticalSectionScoped cs(receive_statistics_lock_.get()); 47854ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org if (callback != NULL) 47954ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org assert(rtcp_stats_callback_ == NULL); 48054ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org rtcp_stats_callback_ = callback; 48154ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org} 48254ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org 48354ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.orgvoid ReceiveStatisticsImpl::StatisticsUpdated(const RtcpStatistics& statistics, 48454ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org uint32_t ssrc) { 4857dba27c740048c92692d4e1cf6fee1fee7827901sprang@webrtc.org CriticalSectionScoped cs(receive_statistics_lock_.get()); 486ce4e9a356200170abcdd44ff2af95f87a6781b8epbos@webrtc.org if (rtcp_stats_callback_) 48754ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org rtcp_stats_callback_->StatisticsUpdated(statistics, ssrc); 488ce4e9a356200170abcdd44ff2af95f87a6781b8epbos@webrtc.org} 489ce4e9a356200170abcdd44ff2af95f87a6781b8epbos@webrtc.org 490ce4e9a356200170abcdd44ff2af95f87a6781b8epbos@webrtc.orgvoid ReceiveStatisticsImpl::CNameChanged(const char* cname, uint32_t ssrc) { 491ce4e9a356200170abcdd44ff2af95f87a6781b8epbos@webrtc.org CriticalSectionScoped cs(receive_statistics_lock_.get()); 492ce4e9a356200170abcdd44ff2af95f87a6781b8epbos@webrtc.org if (rtcp_stats_callback_) 493ce4e9a356200170abcdd44ff2af95f87a6781b8epbos@webrtc.org rtcp_stats_callback_->CNameChanged(cname, ssrc); 49454ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org} 495286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org 4960e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.orgvoid ReceiveStatisticsImpl::RegisterRtpStatisticsCallback( 4970e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org StreamDataCountersCallback* callback) { 4980e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org CriticalSectionScoped cs(receive_statistics_lock_.get()); 4990e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org if (callback != NULL) 5000e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org assert(rtp_stats_callback_ == NULL); 5010e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org rtp_stats_callback_ = callback; 5020e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org} 5030e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org 5040e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.orgvoid ReceiveStatisticsImpl::DataCountersUpdated(const StreamDataCounters& stats, 5050e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org uint32_t ssrc) { 5060e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org CriticalSectionScoped cs(receive_statistics_lock_.get()); 5070e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org if (rtp_stats_callback_) { 5080e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org rtp_stats_callback_->DataCountersUpdated(stats, ssrc); 5090e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org } 5100e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org} 5110e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org 512286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.orgvoid NullReceiveStatistics::IncomingPacket(const RTPHeader& rtp_header, 51397d0489058ae7a983f7306f32cfd49a2356c6488asapersson@webrtc.org size_t packet_length, 5147bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org bool retransmitted) {} 515286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org 516273fbbb921e61273c3d83eb494d0a68db7834d3dasapersson@webrtc.orgvoid NullReceiveStatistics::FecPacketReceived(const RTPHeader& header, 517273fbbb921e61273c3d83eb494d0a68db7834d3dasapersson@webrtc.org size_t packet_length) {} 5180e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org 519286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.orgStatisticianMap NullReceiveStatistics::GetActiveStatisticians() const { 520286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org return StatisticianMap(); 521286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org} 522286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org 523286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.orgStreamStatistician* NullReceiveStatistics::GetStatistician( 524286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org uint32_t ssrc) const { 525286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org return NULL; 526286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org} 527286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org 5287bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.orgvoid NullReceiveStatistics::SetMaxReorderingThreshold( 5297bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org int max_reordering_threshold) {} 5307bb8f02274ecbfa1f7ef134d708369a369a78c83stefan@webrtc.org 5310b1534c52eab79372557a6d81aaf4dd9407f55d3pkasting@chromium.orgint64_t NullReceiveStatistics::TimeUntilNextProcess() { return 0; } 532286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org 533286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.orgint32_t NullReceiveStatistics::Process() { return 0; } 534286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org 53554ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.orgvoid NullReceiveStatistics::RegisterRtcpStatisticsCallback( 53654ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org RtcpStatisticsCallback* callback) {} 53754ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org 5380e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.orgvoid NullReceiveStatistics::RegisterRtpStatisticsCallback( 5390e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org StreamDataCountersCallback* callback) {} 5400e93257cee79c0d19ddaef1f14ba750bf469a084sprang@webrtc.org 541822fbd8b68ffdb481b9557e2950ae8d6657c8ce6wu@webrtc.org} // namespace webrtc 542