diff --git a/webrtc/common_types.h b/webrtc/common_types.h index aa6f319928..9cb56af82f 100644 --- a/webrtc/common_types.h +++ b/webrtc/common_types.h @@ -239,6 +239,15 @@ struct StreamDataCounters { retransmitted_packets(0), fec_packets(0) {} + void Add(const StreamDataCounters& other) { + bytes += other.bytes; + header_bytes += other.header_bytes; + padding_bytes += other.padding_bytes; + packets += other.packets; + retransmitted_packets += other.retransmitted_packets; + fec_packets += other.fec_packets; + } + // TODO(pbos): Rename bytes -> media_bytes. size_t bytes; // Payload bytes, excluding RTP headers and padding. size_t header_bytes; // Number of bytes used by RTP headers. diff --git a/webrtc/modules/rtp_rtcp/interface/receive_statistics.h b/webrtc/modules/rtp_rtcp/interface/receive_statistics.h index ae1fbb6776..8cbed804ac 100644 --- a/webrtc/modules/rtp_rtcp/interface/receive_statistics.h +++ b/webrtc/modules/rtp_rtcp/interface/receive_statistics.h @@ -28,6 +28,11 @@ class StreamStatistician { virtual bool GetStatistics(RtcpStatistics* statistics, bool reset) = 0; virtual void GetDataCounters(size_t* bytes_received, uint32_t* packets_received) const = 0; + + // Gets received stream data counters (includes reset counter values). + virtual void GetReceiveStreamDataCounters( + StreamDataCounters* data_counters) const = 0; + virtual uint32_t BitrateReceived() const = 0; // Resets all statistics. diff --git a/webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h b/webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h index bbdac6722c..f58eaead60 100644 --- a/webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h +++ b/webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h @@ -77,6 +77,8 @@ class RTPPayloadRegistry { void SetRtxSsrc(uint32_t ssrc); + bool GetRtxSsrc(uint32_t* ssrc) const; + void SetRtxPayloadType(int payload_type); bool IsRtx(const RTPHeader& header) const; diff --git a/webrtc/modules/rtp_rtcp/source/receive_statistics_impl.cc b/webrtc/modules/rtp_rtcp/source/receive_statistics_impl.cc index eeb6e3176d..8585e16af6 100644 --- a/webrtc/modules/rtp_rtcp/source/receive_statistics_impl.cc +++ b/webrtc/modules/rtp_rtcp/source/receive_statistics_impl.cc @@ -63,6 +63,7 @@ void StreamStatisticianImpl::ResetStatistics() { received_seq_wraps_ = 0; received_seq_max_ = 0; received_seq_first_ = 0; + stored_sum_receive_counters_.Add(receive_counters_); receive_counters_ = StreamDataCounters(); } @@ -314,6 +315,13 @@ void StreamStatisticianImpl::GetDataCounters( } } +void StreamStatisticianImpl::GetReceiveStreamDataCounters( + StreamDataCounters* data_counters) const { + CriticalSectionScoped cs(stream_lock_.get()); + *data_counters = receive_counters_; + data_counters->Add(stored_sum_receive_counters_); +} + uint32_t StreamStatisticianImpl::BitrateReceived() const { CriticalSectionScoped cs(stream_lock_.get()); return incoming_bitrate_.BitrateNow(); diff --git a/webrtc/modules/rtp_rtcp/source/receive_statistics_impl.h b/webrtc/modules/rtp_rtcp/source/receive_statistics_impl.h index bef856fa35..f3eaa580f1 100644 --- a/webrtc/modules/rtp_rtcp/source/receive_statistics_impl.h +++ b/webrtc/modules/rtp_rtcp/source/receive_statistics_impl.h @@ -33,6 +33,8 @@ class StreamStatisticianImpl : public StreamStatistician { virtual bool GetStatistics(RtcpStatistics* statistics, bool reset) OVERRIDE; virtual void GetDataCounters(size_t* bytes_received, uint32_t* packets_received) const OVERRIDE; + virtual void GetReceiveStreamDataCounters( + StreamDataCounters* data_counters) const OVERRIDE; virtual uint32_t BitrateReceived() const OVERRIDE; virtual void ResetStatistics() OVERRIDE; virtual bool IsRetransmitOfOldPacket(const RTPHeader& header, @@ -83,6 +85,9 @@ class StreamStatisticianImpl : public StreamStatistician { size_t received_packet_overhead_; StreamDataCounters receive_counters_; + // Stored counter values. Includes sum of reset counter values for the stream. + StreamDataCounters stored_sum_receive_counters_; + // Counter values when we sent the last report. uint32_t last_report_inorder_packets_; uint32_t last_report_old_packets_; diff --git a/webrtc/modules/rtp_rtcp/source/rtp_payload_registry.cc b/webrtc/modules/rtp_rtcp/source/rtp_payload_registry.cc index 6073016530..727a4d3aca 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_payload_registry.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_payload_registry.cc @@ -286,6 +286,12 @@ void RTPPayloadRegistry::SetRtxSsrc(uint32_t ssrc) { rtx_ = true; } +bool RTPPayloadRegistry::GetRtxSsrc(uint32_t* ssrc) const { + CriticalSectionScoped cs(crit_sect_.get()); + *ssrc = ssrc_rtx_; + return rtx_; +} + void RTPPayloadRegistry::SetRtxPayloadType(int payload_type) { CriticalSectionScoped cs(crit_sect_.get()); assert(payload_type >= 0); diff --git a/webrtc/video/video_send_stream_tests.cc b/webrtc/video/video_send_stream_tests.cc index 6fedaf7276..cec65f5067 100644 --- a/webrtc/video/video_send_stream_tests.cc +++ b/webrtc/video/video_send_stream_tests.cc @@ -252,6 +252,8 @@ class FakeReceiveStatistics : public NullReceiveStatistics { *bytes_received = 0; *packets_received = 0; } + virtual void GetReceiveStreamDataCounters( + StreamDataCounters* data_counters) const OVERRIDE {} virtual uint32_t BitrateReceived() const OVERRIDE { return 0; } virtual void ResetStatistics() OVERRIDE {} virtual bool IsRetransmitOfOldPacket(const RTPHeader& header, diff --git a/webrtc/video_engine/vie_channel.cc b/webrtc/video_engine/vie_channel.cc index 291831380f..8679c176a6 100644 --- a/webrtc/video_engine/vie_channel.cc +++ b/webrtc/video_engine/vie_channel.cc @@ -258,7 +258,7 @@ void ViEChannel::UpdateHistograms() { rtcp_received.fir_packets / elapsed_minutes); RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.PliPacketsReceivedPerMinute", rtcp_received.pli_packets / elapsed_minutes); - } else if (vie_receiver_.GetRemoteSsrc() > 0) { + } else if (vie_receiver_.GetRemoteSsrc() > 0) { // Get receive stats if we are receiving packets, i.e. there is a remote // ssrc. if (rtcp_sent.nack_requests > 0) { @@ -281,6 +281,26 @@ void ViEChannel::UpdateHistograms() { 0.5f)); } } + StreamDataCounters data; + StreamDataCounters rtx_data; + GetReceiveStreamDataCounters(&data, &rtx_data); + uint32_t media_bytes = data.bytes; + uint32_t rtx_bytes = + rtx_data.bytes + rtx_data.header_bytes + rtx_data.padding_bytes; + uint32_t total_bytes = data.bytes + data.header_bytes + data.padding_bytes; + total_bytes += rtx_bytes; + uint32_t padding_bytes = data.padding_bytes + rtx_data.padding_bytes; + RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.BitrateReceivedInKbps", + total_bytes * 8 / (elapsed_minutes * 60) / 1000); + RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.MediaBitrateReceivedInKbps", + media_bytes * 8 / (elapsed_minutes * 60) / 1000); + RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.PaddingBitrateReceivedInKbps", + padding_bytes * 8 / (elapsed_minutes * 60) / 1000); + uint32_t ssrc = 0; + if (vie_receiver_.GetRtxSsrc(&ssrc)) { + RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.RtxBitrateReceivedInKbps", + rtx_bytes * 8 / (elapsed_minutes * 60) / 1000); + } } } @@ -1164,6 +1184,24 @@ int32_t ViEChannel::GetRtpStatistics(size_t* bytes_sent, return 0; } +void ViEChannel::GetReceiveStreamDataCounters( + StreamDataCounters* data, + StreamDataCounters* rtx_data) const { + StreamStatistician* statistician = vie_receiver_.GetReceiveStatistics()-> + GetStatistician(vie_receiver_.GetRemoteSsrc()); + if (statistician) { + statistician->GetReceiveStreamDataCounters(data); + } + uint32_t rtx_ssrc = 0; + if (vie_receiver_.GetRtxSsrc(&rtx_ssrc)) { + StreamStatistician* statistician = + vie_receiver_.GetReceiveStatistics()->GetStatistician(rtx_ssrc); + if (statistician) { + statistician->GetReceiveStreamDataCounters(rtx_data); + } + } +} + void ViEChannel::RegisterSendChannelRtpStatisticsCallback( StreamDataCountersCallback* callback) { rtp_rtcp_->RegisterSendChannelRtpStatisticsCallback(callback); diff --git a/webrtc/video_engine/vie_channel.h b/webrtc/video_engine/vie_channel.h index 3f2621aab8..ffb754c376 100644 --- a/webrtc/video_engine/vie_channel.h +++ b/webrtc/video_engine/vie_channel.h @@ -194,6 +194,10 @@ class ViEChannel size_t* bytes_received, uint32_t* packets_received) const; + // Gets received stream data counters. + void GetReceiveStreamDataCounters(StreamDataCounters* data, + StreamDataCounters* rtx_data) const; + // Called on update of RTP statistics. void RegisterSendChannelRtpStatisticsCallback( StreamDataCountersCallback* callback); diff --git a/webrtc/video_engine/vie_receiver.cc b/webrtc/video_engine/vie_receiver.cc index 8f359bf7da..6dec985565 100644 --- a/webrtc/video_engine/vie_receiver.cc +++ b/webrtc/video_engine/vie_receiver.cc @@ -110,6 +110,10 @@ void ViEReceiver::SetRtxSsrc(uint32_t ssrc) { rtp_payload_registry_->SetRtxSsrc(ssrc); } +bool ViEReceiver::GetRtxSsrc(uint32_t* ssrc) const { + return rtp_payload_registry_->GetRtxSsrc(ssrc); +} + uint32_t ViEReceiver::GetRemoteSsrc() const { return rtp_receiver_->SSRC(); } diff --git a/webrtc/video_engine/vie_receiver.h b/webrtc/video_engine/vie_receiver.h index a7b238bf0d..39a85e4c2b 100644 --- a/webrtc/video_engine/vie_receiver.h +++ b/webrtc/video_engine/vie_receiver.h @@ -49,6 +49,7 @@ class ViEReceiver : public RtpData { void SetNackStatus(bool enable, int max_nack_reordering_threshold); void SetRtxPayloadType(int payload_type); void SetRtxSsrc(uint32_t ssrc); + bool GetRtxSsrc(uint32_t* ssrc) const; uint32_t GetRemoteSsrc() const; int GetCsrcs(uint32_t* csrcs) const;