X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fthird_party%2Fwebrtc%2Fmodules%2Frtp_rtcp%2Fsource%2Freceive_statistics_impl.cc;h=aa7c9c571568355c3fbd03a1f67e792d0700c2db;hb=ff3e2503a20db9193d323c1d19c38c68004dec4a;hp=cf189903d13cba89bca8f2a8e9ce8ce976f9c910;hpb=172ee7c03df346ff158858709f7f6494e695e0e4;p=platform%2Fframework%2Fweb%2Fcrosswalk.git diff --git a/src/third_party/webrtc/modules/rtp_rtcp/source/receive_statistics_impl.cc b/src/third_party/webrtc/modules/rtp_rtcp/source/receive_statistics_impl.cc index cf18990..aa7c9c5 100644 --- a/src/third_party/webrtc/modules/rtp_rtcp/source/receive_statistics_impl.cc +++ b/src/third_party/webrtc/modules/rtp_rtcp/source/receive_statistics_impl.cc @@ -24,14 +24,16 @@ const int kStatisticsProcessIntervalMs = 1000; StreamStatistician::~StreamStatistician() {} -StreamStatisticianImpl::StreamStatisticianImpl(Clock* clock) +StreamStatisticianImpl::StreamStatisticianImpl( + Clock* clock, + RtcpStatisticsCallback* rtcp_callback, + StreamDataCountersCallback* rtp_callback) : clock_(clock), - crit_sect_(CriticalSectionWrapper::CreateCriticalSection()), - incoming_bitrate_(clock), + stream_lock_(CriticalSectionWrapper::CreateCriticalSection()), + incoming_bitrate_(clock, NULL), ssrc_(0), max_reordering_threshold_(kDefaultMaxReorderingThreshold), jitter_q4_(0), - jitter_max_q4_(0), cumulative_loss_(0), jitter_q4_transmission_time_offset_(0), last_receive_time_ms_(0), @@ -42,53 +44,53 @@ StreamStatisticianImpl::StreamStatisticianImpl(Clock* clock) received_seq_first_(0), received_seq_max_(0), received_seq_wraps_(0), - first_packet_(true), received_packet_overhead_(12), - received_byte_count_(0), - received_retransmitted_packets_(0), - received_inorder_packet_count_(0), last_report_inorder_packets_(0), last_report_old_packets_(0), last_report_seq_max_(0), - last_reported_statistics_() {} + rtcp_callback_(rtcp_callback), + rtp_callback_(rtp_callback) {} void StreamStatisticianImpl::ResetStatistics() { - CriticalSectionScoped cs(crit_sect_.get()); + CriticalSectionScoped cs(stream_lock_.get()); last_report_inorder_packets_ = 0; last_report_old_packets_ = 0; last_report_seq_max_ = 0; - memset(&last_reported_statistics_, 0, sizeof(last_reported_statistics_)); + last_reported_statistics_ = RtcpStatistics(); jitter_q4_ = 0; - jitter_max_q4_ = 0; cumulative_loss_ = 0; jitter_q4_transmission_time_offset_ = 0; received_seq_wraps_ = 0; received_seq_max_ = 0; received_seq_first_ = 0; - received_byte_count_ = 0; - received_retransmitted_packets_ = 0; - received_inorder_packet_count_ = 0; - first_packet_ = true; + receive_counters_ = StreamDataCounters(); } void StreamStatisticianImpl::IncomingPacket(const RTPHeader& header, size_t bytes, bool retransmitted) { - CriticalSectionScoped cs(crit_sect_.get()); + UpdateCounters(header, bytes, retransmitted); + NotifyRtpCallback(); +} + +void StreamStatisticianImpl::UpdateCounters(const RTPHeader& header, + size_t bytes, + bool retransmitted) { + CriticalSectionScoped cs(stream_lock_.get()); bool in_order = InOrderPacketInternal(header.sequenceNumber); ssrc_ = header.ssrc; incoming_bitrate_.Update(bytes); - received_byte_count_ += bytes; + receive_counters_.bytes += + bytes - (header.paddingLength + header.headerLength); + receive_counters_.header_bytes += header.headerLength; + receive_counters_.padding_bytes += header.paddingLength; + ++receive_counters_.packets; + if (!in_order && retransmitted) { + ++receive_counters_.retransmitted_packets; + } - if (first_packet_) { - first_packet_ = false; - // This is the first received report. + if (receive_counters_.packets == 1) { received_seq_first_ = header.sequenceNumber; - received_seq_max_ = header.sequenceNumber; - received_inorder_packet_count_ = 1; - clock_->CurrentNtp(last_receive_time_secs_, last_receive_time_frac_); - last_receive_time_ms_ = clock_->TimeInMilliseconds(); - return; } // Count only the new packets received. That is, if packets 1, 2, 3, 5, 4, 6 @@ -98,66 +100,27 @@ void StreamStatisticianImpl::IncomingPacket(const RTPHeader& header, uint32_t receive_time_secs; uint32_t receive_time_frac; clock_->CurrentNtp(receive_time_secs, receive_time_frac); - received_inorder_packet_count_++; // Wrong if we use RetransmitOfOldPacket. - int32_t seq_diff = header.sequenceNumber - received_seq_max_; - if (seq_diff < 0) { + if (receive_counters_.packets > 1 && + received_seq_max_ > header.sequenceNumber) { // Wrap around detected. received_seq_wraps_++; } // New max. received_seq_max_ = header.sequenceNumber; + // If new time stamp and more than one in-order packet received, calculate + // new jitter statistics. if (header.timestamp != last_received_timestamp_ && - received_inorder_packet_count_ > 1) { - uint32_t receive_time_rtp = ModuleRTPUtility::ConvertNTPTimeToRTP( - receive_time_secs, receive_time_frac, header.payload_type_frequency); - uint32_t last_receive_time_rtp = ModuleRTPUtility::ConvertNTPTimeToRTP( - last_receive_time_secs_, last_receive_time_frac_, - header.payload_type_frequency); - int32_t time_diff_samples = (receive_time_rtp - last_receive_time_rtp) - - (header.timestamp - last_received_timestamp_); - - time_diff_samples = abs(time_diff_samples); - - // lib_jingle sometimes deliver crazy jumps in TS for the same stream. - // If this happens, don't update jitter value. Use 5 secs video frequency - // as the threshold. - if (time_diff_samples < 450000) { - // Note we calculate in Q4 to avoid using float. - int32_t jitter_diff_q4 = (time_diff_samples << 4) - jitter_q4_; - jitter_q4_ += ((jitter_diff_q4 + 8) >> 4); - } - - // Extended jitter report, RFC 5450. - // Actual network jitter, excluding the source-introduced jitter. - int32_t time_diff_samples_ext = - (receive_time_rtp - last_receive_time_rtp) - - ((header.timestamp + - header.extension.transmissionTimeOffset) - - (last_received_timestamp_ + - last_received_transmission_time_offset_)); - - time_diff_samples_ext = abs(time_diff_samples_ext); - - if (time_diff_samples_ext < 450000) { - int32_t jitter_diffQ4TransmissionTimeOffset = - (time_diff_samples_ext << 4) - jitter_q4_transmission_time_offset_; - jitter_q4_transmission_time_offset_ += - ((jitter_diffQ4TransmissionTimeOffset + 8) >> 4); - } + (receive_counters_.packets - receive_counters_.retransmitted_packets) > + 1) { + UpdateJitter(header, receive_time_secs, receive_time_frac); } last_received_timestamp_ = header.timestamp; last_receive_time_secs_ = receive_time_secs; last_receive_time_frac_ = receive_time_frac; last_receive_time_ms_ = clock_->TimeInMilliseconds(); - } else { - if (retransmitted) { - received_retransmitted_packets_++; - } else { - received_inorder_packet_count_++; - } } uint16_t packet_oh = header.headerLength + header.paddingLength; @@ -167,29 +130,113 @@ void StreamStatisticianImpl::IncomingPacket(const RTPHeader& header, received_packet_overhead_ = (15 * received_packet_overhead_ + packet_oh) >> 4; } +void StreamStatisticianImpl::UpdateJitter(const RTPHeader& header, + uint32_t receive_time_secs, + uint32_t receive_time_frac) { + uint32_t receive_time_rtp = ModuleRTPUtility::ConvertNTPTimeToRTP( + receive_time_secs, receive_time_frac, header.payload_type_frequency); + uint32_t last_receive_time_rtp = ModuleRTPUtility::ConvertNTPTimeToRTP( + last_receive_time_secs_, last_receive_time_frac_, + header.payload_type_frequency); + int32_t time_diff_samples = (receive_time_rtp - last_receive_time_rtp) - + (header.timestamp - last_received_timestamp_); + + time_diff_samples = abs(time_diff_samples); + + // lib_jingle sometimes deliver crazy jumps in TS for the same stream. + // If this happens, don't update jitter value. Use 5 secs video frequency + // as the threshold. + if (time_diff_samples < 450000) { + // Note we calculate in Q4 to avoid using float. + int32_t jitter_diff_q4 = (time_diff_samples << 4) - jitter_q4_; + jitter_q4_ += ((jitter_diff_q4 + 8) >> 4); + } + + // Extended jitter report, RFC 5450. + // Actual network jitter, excluding the source-introduced jitter. + int32_t time_diff_samples_ext = + (receive_time_rtp - last_receive_time_rtp) - + ((header.timestamp + + header.extension.transmissionTimeOffset) - + (last_received_timestamp_ + + last_received_transmission_time_offset_)); + + time_diff_samples_ext = abs(time_diff_samples_ext); + + if (time_diff_samples_ext < 450000) { + int32_t jitter_diffQ4TransmissionTimeOffset = + (time_diff_samples_ext << 4) - jitter_q4_transmission_time_offset_; + jitter_q4_transmission_time_offset_ += + ((jitter_diffQ4TransmissionTimeOffset + 8) >> 4); + } +} + +void StreamStatisticianImpl::NotifyRtpCallback() { + StreamDataCounters data; + uint32_t ssrc; + { + CriticalSectionScoped cs(stream_lock_.get()); + data = receive_counters_; + ssrc = ssrc_; + } + rtp_callback_->DataCountersUpdated(data, ssrc); +} + +void StreamStatisticianImpl::NotifyRtcpCallback() { + RtcpStatistics data; + uint32_t ssrc; + { + CriticalSectionScoped cs(stream_lock_.get()); + data = last_reported_statistics_; + ssrc = ssrc_; + } + rtcp_callback_->StatisticsUpdated(data, ssrc); +} + +void StreamStatisticianImpl::FecPacketReceived() { + { + CriticalSectionScoped cs(stream_lock_.get()); + ++receive_counters_.fec_packets; + } + NotifyRtpCallback(); +} + void StreamStatisticianImpl::SetMaxReorderingThreshold( int max_reordering_threshold) { - CriticalSectionScoped cs(crit_sect_.get()); + CriticalSectionScoped cs(stream_lock_.get()); max_reordering_threshold_ = max_reordering_threshold; } -bool StreamStatisticianImpl::GetStatistics(Statistics* statistics, bool reset) { - CriticalSectionScoped cs(crit_sect_.get()); - if (received_seq_first_ == 0 && received_byte_count_ == 0) { - // We have not received anything. - return false; - } - - if (!reset) { - if (last_report_inorder_packets_ == 0) { - // No report. +bool StreamStatisticianImpl::GetStatistics(RtcpStatistics* statistics, + bool reset) { + { + CriticalSectionScoped cs(stream_lock_.get()); + if (received_seq_first_ == 0 && receive_counters_.bytes == 0) { + // We have not received anything. return false; } - // Just get last report. - *statistics = last_reported_statistics_; - return true; + + if (!reset) { + if (last_report_inorder_packets_ == 0) { + // No report. + return false; + } + // Just get last report. + *statistics = last_reported_statistics_; + return true; + } + + *statistics = CalculateRtcpStatistics(); } + NotifyRtcpCallback(); + + return true; +} + +RtcpStatistics StreamStatisticianImpl::CalculateRtcpStatistics() { + RtcpStatistics stats; + if (last_report_inorder_packets_ == 0) { // First time we send a report. last_report_seq_max_ = received_seq_first_ - 1; @@ -206,7 +253,8 @@ bool StreamStatisticianImpl::GetStatistics(Statistics* statistics, bool reset) { // Number of received RTP packets since last report, counts all packets but // not re-transmissions. uint32_t rec_since_last = - received_inorder_packet_count_ - last_report_inorder_packets_; + (receive_counters_.packets - receive_counters_.retransmitted_packets) - + last_report_inorder_packets_; // With NACK we don't know the expected retransmissions during the last // second. We know how many "old" packets we have received. We just count @@ -218,7 +266,7 @@ bool StreamStatisticianImpl::GetStatistics(Statistics* statistics, bool reset) { // re-transmitted. We use RTT to decide if a packet is re-ordered or // re-transmitted. uint32_t retransmitted_packets = - received_retransmitted_packets_ - last_report_old_packets_; + receive_counters_.retransmitted_packets - last_report_old_packets_; rec_since_last += retransmitted_packets; int32_t missing = 0; @@ -231,64 +279,60 @@ bool StreamStatisticianImpl::GetStatistics(Statistics* statistics, bool reset) { local_fraction_lost = static_cast(255 * missing / exp_since_last); } - statistics->fraction_lost = local_fraction_lost; + stats.fraction_lost = local_fraction_lost; // We need a counter for cumulative loss too. cumulative_loss_ += missing; - - if (jitter_q4_ > jitter_max_q4_) { - jitter_max_q4_ = jitter_q4_; - } - statistics->cumulative_lost = cumulative_loss_; - statistics->extended_max_sequence_number = (received_seq_wraps_ << 16) + - received_seq_max_; + stats.cumulative_lost = cumulative_loss_; + stats.extended_max_sequence_number = + (received_seq_wraps_ << 16) + received_seq_max_; // Note: internal jitter value is in Q4 and needs to be scaled by 1/16. - statistics->jitter = jitter_q4_ >> 4; - statistics->max_jitter = jitter_max_q4_ >> 4; - if (reset) { - // Store this report. - last_reported_statistics_ = *statistics; - - // Only for report blocks in RTCP SR and RR. - last_report_inorder_packets_ = received_inorder_packet_count_; - last_report_old_packets_ = received_retransmitted_packets_; - last_report_seq_max_ = received_seq_max_; - } - return true; + stats.jitter = jitter_q4_ >> 4; + + // Store this report. + last_reported_statistics_ = stats; + + // Only for report blocks in RTCP SR and RR. + last_report_inorder_packets_ = + receive_counters_.packets - receive_counters_.retransmitted_packets; + last_report_old_packets_ = receive_counters_.retransmitted_packets; + last_report_seq_max_ = received_seq_max_; + + return stats; } void StreamStatisticianImpl::GetDataCounters( uint32_t* bytes_received, uint32_t* packets_received) const { - CriticalSectionScoped cs(crit_sect_.get()); + CriticalSectionScoped cs(stream_lock_.get()); if (bytes_received) { - *bytes_received = received_byte_count_; + *bytes_received = receive_counters_.bytes + receive_counters_.header_bytes + + receive_counters_.padding_bytes; } if (packets_received) { - *packets_received = - received_retransmitted_packets_ + received_inorder_packet_count_; + *packets_received = receive_counters_.packets; } } uint32_t StreamStatisticianImpl::BitrateReceived() const { - CriticalSectionScoped cs(crit_sect_.get()); + CriticalSectionScoped cs(stream_lock_.get()); return incoming_bitrate_.BitrateNow(); } void StreamStatisticianImpl::ProcessBitrate() { - CriticalSectionScoped cs(crit_sect_.get()); + CriticalSectionScoped cs(stream_lock_.get()); incoming_bitrate_.Process(); } void StreamStatisticianImpl::LastReceiveTimeNtp(uint32_t* secs, uint32_t* frac) const { - CriticalSectionScoped cs(crit_sect_.get()); + CriticalSectionScoped cs(stream_lock_.get()); *secs = last_receive_time_secs_; *frac = last_receive_time_frac_; } bool StreamStatisticianImpl::IsRetransmitOfOldPacket( const RTPHeader& header, int min_rtt) const { - CriticalSectionScoped cs(crit_sect_.get()); + CriticalSectionScoped cs(stream_lock_.get()); if (InOrderPacketInternal(header.sequenceNumber)) { return false; } @@ -323,7 +367,7 @@ bool StreamStatisticianImpl::IsRetransmitOfOldPacket( } bool StreamStatisticianImpl::IsPacketInOrder(uint16_t sequence_number) const { - CriticalSectionScoped cs(crit_sect_.get()); + CriticalSectionScoped cs(stream_lock_.get()); return InOrderPacketInternal(sequence_number); } @@ -348,8 +392,10 @@ ReceiveStatistics* ReceiveStatistics::Create(Clock* clock) { ReceiveStatisticsImpl::ReceiveStatisticsImpl(Clock* clock) : clock_(clock), - crit_sect_(CriticalSectionWrapper::CreateCriticalSection()), - last_rate_update_ms_(0) {} + receive_statistics_lock_(CriticalSectionWrapper::CreateCriticalSection()), + last_rate_update_ms_(0), + rtcp_stats_callback_(NULL), + rtp_stats_callback_(NULL) {} ReceiveStatisticsImpl::~ReceiveStatisticsImpl() { while (!statisticians_.empty()) { @@ -359,20 +405,31 @@ ReceiveStatisticsImpl::~ReceiveStatisticsImpl() { } void ReceiveStatisticsImpl::IncomingPacket(const RTPHeader& header, - size_t bytes, bool old_packet) { - CriticalSectionScoped cs(crit_sect_.get()); - StatisticianImplMap::iterator it = statisticians_.find(header.ssrc); - if (it == statisticians_.end()) { - std::pair insert_result = - statisticians_.insert(std::make_pair( - header.ssrc, new StreamStatisticianImpl(clock_))); - it = insert_result.first; + size_t bytes, + bool retransmitted) { + StatisticianImplMap::iterator it; + { + CriticalSectionScoped cs(receive_statistics_lock_.get()); + it = statisticians_.find(header.ssrc); + if (it == statisticians_.end()) { + std::pair insert_result = + statisticians_.insert(std::make_pair( + header.ssrc, new StreamStatisticianImpl(clock_, this, this))); + it = insert_result.first; + } } - statisticians_[header.ssrc]->IncomingPacket(header, bytes, old_packet); + it->second->IncomingPacket(header, bytes, retransmitted); +} + +void ReceiveStatisticsImpl::FecPacketReceived(uint32_t ssrc) { + CriticalSectionScoped cs(receive_statistics_lock_.get()); + StatisticianImplMap::iterator it = statisticians_.find(ssrc); + assert(it != statisticians_.end()); + it->second->FecPacketReceived(); } void ReceiveStatisticsImpl::ChangeSsrc(uint32_t from_ssrc, uint32_t to_ssrc) { - CriticalSectionScoped cs(crit_sect_.get()); + CriticalSectionScoped cs(receive_statistics_lock_.get()); StatisticianImplMap::iterator from_it = statisticians_.find(from_ssrc); if (from_it == statisticians_.end()) return; @@ -383,7 +440,7 @@ void ReceiveStatisticsImpl::ChangeSsrc(uint32_t from_ssrc, uint32_t to_ssrc) { } StatisticianMap ReceiveStatisticsImpl::GetActiveStatisticians() const { - CriticalSectionScoped cs(crit_sect_.get()); + CriticalSectionScoped cs(receive_statistics_lock_.get()); StatisticianMap active_statisticians; for (StatisticianImplMap::const_iterator it = statisticians_.begin(); it != statisticians_.end(); ++it) { @@ -400,7 +457,7 @@ StatisticianMap ReceiveStatisticsImpl::GetActiveStatisticians() const { StreamStatistician* ReceiveStatisticsImpl::GetStatistician( uint32_t ssrc) const { - CriticalSectionScoped cs(crit_sect_.get()); + CriticalSectionScoped cs(receive_statistics_lock_.get()); StatisticianImplMap::const_iterator it = statisticians_.find(ssrc); if (it == statisticians_.end()) return NULL; @@ -409,7 +466,7 @@ StreamStatistician* ReceiveStatisticsImpl::GetStatistician( void ReceiveStatisticsImpl::SetMaxReorderingThreshold( int max_reordering_threshold) { - CriticalSectionScoped cs(crit_sect_.get()); + CriticalSectionScoped cs(receive_statistics_lock_.get()); for (StatisticianImplMap::iterator it = statisticians_.begin(); it != statisticians_.end(); ++it) { it->second->SetMaxReorderingThreshold(max_reordering_threshold); @@ -417,7 +474,7 @@ void ReceiveStatisticsImpl::SetMaxReorderingThreshold( } int32_t ReceiveStatisticsImpl::Process() { - CriticalSectionScoped cs(crit_sect_.get()); + CriticalSectionScoped cs(receive_statistics_lock_.get()); for (StatisticianImplMap::iterator it = statisticians_.begin(); it != statisticians_.end(); ++it) { it->second->ProcessBitrate(); @@ -427,17 +484,50 @@ int32_t ReceiveStatisticsImpl::Process() { } int32_t ReceiveStatisticsImpl::TimeUntilNextProcess() { - CriticalSectionScoped cs(crit_sect_.get()); + CriticalSectionScoped cs(receive_statistics_lock_.get()); int time_since_last_update = clock_->TimeInMilliseconds() - last_rate_update_ms_; return std::max(kStatisticsProcessIntervalMs - time_since_last_update, 0); } +void ReceiveStatisticsImpl::RegisterRtcpStatisticsCallback( + RtcpStatisticsCallback* callback) { + CriticalSectionScoped cs(receive_statistics_lock_.get()); + if (callback != NULL) + assert(rtcp_stats_callback_ == NULL); + rtcp_stats_callback_ = callback; +} + +void ReceiveStatisticsImpl::StatisticsUpdated(const RtcpStatistics& statistics, + uint32_t ssrc) { + CriticalSectionScoped cs(receive_statistics_lock_.get()); + if (rtcp_stats_callback_) { + rtcp_stats_callback_->StatisticsUpdated(statistics, ssrc); + } +} + +void ReceiveStatisticsImpl::RegisterRtpStatisticsCallback( + StreamDataCountersCallback* callback) { + CriticalSectionScoped cs(receive_statistics_lock_.get()); + if (callback != NULL) + assert(rtp_stats_callback_ == NULL); + rtp_stats_callback_ = callback; +} + +void ReceiveStatisticsImpl::DataCountersUpdated(const StreamDataCounters& stats, + uint32_t ssrc) { + CriticalSectionScoped cs(receive_statistics_lock_.get()); + if (rtp_stats_callback_) { + rtp_stats_callback_->DataCountersUpdated(stats, ssrc); + } +} void NullReceiveStatistics::IncomingPacket(const RTPHeader& rtp_header, size_t bytes, bool retransmitted) {} +void NullReceiveStatistics::FecPacketReceived(uint32_t ssrc) {} + StatisticianMap NullReceiveStatistics::GetActiveStatisticians() const { return StatisticianMap(); } @@ -454,4 +544,10 @@ int32_t NullReceiveStatistics::TimeUntilNextProcess() { return 0; } int32_t NullReceiveStatistics::Process() { return 0; } +void NullReceiveStatistics::RegisterRtcpStatisticsCallback( + RtcpStatisticsCallback* callback) {} + +void NullReceiveStatistics::RegisterRtpStatisticsCallback( + StreamDataCountersCallback* callback) {} + } // namespace webrtc