diff --git a/modules/rtp_rtcp/include/receive_statistics.h b/modules/rtp_rtcp/include/receive_statistics.h index 65a78a26db..669a087066 100644 --- a/modules/rtp_rtcp/include/receive_statistics.h +++ b/modules/rtp_rtcp/include/receive_statistics.h @@ -57,10 +57,9 @@ class ReceiveStatistics : public ReceiveStatisticsProvider, public: ~ReceiveStatistics() override = default; - static std::unique_ptr Create(Clock* clock) { - return Create(clock, nullptr); - } + static std::unique_ptr Create(Clock* clock); + RTC_DEPRECATED static std::unique_ptr Create( Clock* clock, StreamDataCountersCallback* rtp_callback); diff --git a/modules/rtp_rtcp/source/receive_statistics_impl.cc b/modules/rtp_rtcp/source/receive_statistics_impl.cc index 99566b7e19..e61719728e 100644 --- a/modules/rtp_rtcp/source/receive_statistics_impl.cc +++ b/modules/rtp_rtcp/source/receive_statistics_impl.cc @@ -30,11 +30,9 @@ const int64_t kStatisticsProcessIntervalMs = 1000; StreamStatistician::~StreamStatistician() {} -StreamStatisticianImpl::StreamStatisticianImpl( - uint32_t ssrc, - Clock* clock, - int max_reordering_threshold, - StreamDataCountersCallback* rtp_callback) +StreamStatisticianImpl::StreamStatisticianImpl(uint32_t ssrc, + Clock* clock, + int max_reordering_threshold) : ssrc_(ssrc), clock_(clock), incoming_bitrate_(kStatisticsProcessIntervalMs, @@ -49,15 +47,12 @@ StreamStatisticianImpl::StreamStatisticianImpl( received_seq_max_(-1), last_report_inorder_packets_(0), last_report_old_packets_(0), - last_report_seq_max_(-1), - rtp_callback_(rtp_callback) {} + last_report_seq_max_(-1) {} StreamStatisticianImpl::~StreamStatisticianImpl() = default; void StreamStatisticianImpl::OnRtpPacket(const RtpPacketReceived& packet) { - StreamDataCounters counters = UpdateCounters(packet); - if (rtp_callback_) - rtp_callback_->DataCountersUpdated(counters, ssrc_); + UpdateCounters(packet); } bool StreamStatisticianImpl::UpdateOutOfOrder(const RtpPacketReceived& packet, @@ -156,14 +151,8 @@ void StreamStatisticianImpl::UpdateJitter(const RtpPacketReceived& packet, void StreamStatisticianImpl::FecPacketReceived( const RtpPacketReceived& packet) { - StreamDataCounters counters; - { - rtc::CritScope cs(&stream_lock_); - receive_counters_.fec.AddPacket(packet); - counters = receive_counters_; - } - if (rtp_callback_) - rtp_callback_->DataCountersUpdated(counters, ssrc_); + rtc::CritScope cs(&stream_lock_); + receive_counters_.fec.AddPacket(packet); } void StreamStatisticianImpl::SetMaxReorderingThreshold( @@ -332,10 +321,15 @@ bool StreamStatisticianImpl::IsRetransmitOfOldPacket( return time_diff_ms > rtp_time_stamp_diff_ms + max_delay_ms; } +std::unique_ptr ReceiveStatistics::Create(Clock* clock) { + return absl::make_unique(clock); +} + std::unique_ptr ReceiveStatistics::Create( Clock* clock, StreamDataCountersCallback* rtp_callback) { - return absl::make_unique(clock, rtp_callback); + RTC_CHECK(rtp_callback == nullptr); + return Create(clock); } std::unique_ptr ReceiveStatistics::Create( @@ -343,16 +337,14 @@ std::unique_ptr ReceiveStatistics::Create( RtcpStatisticsCallback* rtcp_callback, StreamDataCountersCallback* rtp_callback) { RTC_CHECK(rtcp_callback == nullptr); - return Create(clock, rtp_callback); + RTC_CHECK(rtp_callback == nullptr); + return Create(clock); } -ReceiveStatisticsImpl::ReceiveStatisticsImpl( - Clock* clock, - StreamDataCountersCallback* rtp_callback) +ReceiveStatisticsImpl::ReceiveStatisticsImpl(Clock* clock) : clock_(clock), last_returned_ssrc_(0), - max_reordering_threshold_(kDefaultMaxReorderingThreshold), - rtp_stats_callback_(rtp_callback) {} + max_reordering_threshold_(kDefaultMaxReorderingThreshold) {} ReceiveStatisticsImpl::~ReceiveStatisticsImpl() { while (!statisticians_.empty()) { @@ -391,8 +383,7 @@ StreamStatisticianImpl* ReceiveStatisticsImpl::GetOrCreateStatistician( rtc::CritScope cs(&receive_statistics_lock_); StreamStatisticianImpl*& impl = statisticians_[ssrc]; if (impl == nullptr) { // new element - impl = new StreamStatisticianImpl(ssrc, clock_, max_reordering_threshold_, - rtp_stats_callback_); + impl = new StreamStatisticianImpl(ssrc, clock_, max_reordering_threshold_); } return impl; } diff --git a/modules/rtp_rtcp/source/receive_statistics_impl.h b/modules/rtp_rtcp/source/receive_statistics_impl.h index c49fd11979..04030d4a85 100644 --- a/modules/rtp_rtcp/source/receive_statistics_impl.h +++ b/modules/rtp_rtcp/source/receive_statistics_impl.h @@ -29,8 +29,7 @@ class StreamStatisticianImpl : public StreamStatistician, public: StreamStatisticianImpl(uint32_t ssrc, Clock* clock, - int max_reordering_threshold, - StreamDataCountersCallback* rtp_callback); + int max_reordering_threshold); ~StreamStatisticianImpl() override; // |reset| here and in next method restarts calculation of fraction_lost stat. @@ -98,15 +97,11 @@ class StreamStatisticianImpl : public StreamStatistician, uint32_t last_report_old_packets_ RTC_GUARDED_BY(&stream_lock_); int64_t last_report_seq_max_ RTC_GUARDED_BY(&stream_lock_); RtcpStatistics last_reported_statistics_ RTC_GUARDED_BY(&stream_lock_); - - // stream_lock_ shouldn't be held when calling callbacks. - StreamDataCountersCallback* const rtp_callback_; }; class ReceiveStatisticsImpl : public ReceiveStatistics { public: - ReceiveStatisticsImpl(Clock* clock, - StreamDataCountersCallback* rtp_callback); + explicit ReceiveStatisticsImpl(Clock* clock); ~ReceiveStatisticsImpl() override; @@ -134,8 +129,6 @@ class ReceiveStatisticsImpl : public ReceiveStatistics { int max_reordering_threshold_ RTC_GUARDED_BY(receive_statistics_lock_); std::map statisticians_ RTC_GUARDED_BY(receive_statistics_lock_); - - StreamDataCountersCallback* const rtp_stats_callback_; }; } // namespace webrtc #endif // MODULES_RTP_RTCP_SOURCE_RECEIVE_STATISTICS_IMPL_H_ diff --git a/modules/rtp_rtcp/source/receive_statistics_unittest.cc b/modules/rtp_rtcp/source/receive_statistics_unittest.cc index 8b08ce40da..44e53cf8c1 100644 --- a/modules/rtp_rtcp/source/receive_statistics_unittest.cc +++ b/modules/rtp_rtcp/source/receive_statistics_unittest.cc @@ -68,8 +68,7 @@ void IncrementSequenceNumber(RtpPacketReceived* packet) { class ReceiveStatisticsTest : public ::testing::Test { public: ReceiveStatisticsTest() - : clock_(0), - receive_statistics_(ReceiveStatistics::Create(&clock_, nullptr)) { + : clock_(0), receive_statistics_(ReceiveStatistics::Create(&clock_)) { packet1_ = CreateRtpPacket(kSsrc1, kPacketSize1); packet2_ = CreateRtpPacket(kSsrc2, kPacketSize2); } @@ -460,45 +459,8 @@ TEST_F(ReceiveStatisticsTest, WrapsAroundExtendedHighestSequenceNumber) { EXPECT_EQ(0x20001u, statistics.extended_highest_sequence_number); } -class RtpTestCallback : public StreamDataCountersCallback { - public: - RtpTestCallback() - : StreamDataCountersCallback(), num_calls_(0), ssrc_(0), stats_() {} - ~RtpTestCallback() override = default; - - void DataCountersUpdated(const StreamDataCounters& counters, - uint32_t ssrc) override { - ssrc_ = ssrc; - stats_ = counters; - ++num_calls_; - } - - void MatchPacketCounter(const RtpPacketCounter& expected, - const RtpPacketCounter& actual) { - EXPECT_EQ(expected.payload_bytes, actual.payload_bytes); - EXPECT_EQ(expected.header_bytes, actual.header_bytes); - EXPECT_EQ(expected.padding_bytes, actual.padding_bytes); - EXPECT_EQ(expected.packets, actual.packets); - } - - void Matches(uint32_t num_calls, - uint32_t ssrc, - const StreamDataCounters& expected) { - EXPECT_EQ(num_calls, num_calls_); - EXPECT_EQ(ssrc, ssrc_); - MatchPacketCounter(expected.transmitted, stats_.transmitted); - MatchPacketCounter(expected.retransmitted, stats_.retransmitted); - MatchPacketCounter(expected.fec, stats_.fec); - } - - uint32_t num_calls_; - uint32_t ssrc_; - StreamDataCounters stats_; -}; - -TEST_F(ReceiveStatisticsTest, RtpCallbacks) { - RtpTestCallback callback; - receive_statistics_ = ReceiveStatistics::Create(&clock_, &callback); +TEST_F(ReceiveStatisticsTest, StreamDataCounters) { + receive_statistics_ = ReceiveStatistics::Create(&clock_); receive_statistics_->EnableRetransmitDetection(kSsrc1, true); const size_t kHeaderLength = 20; @@ -508,17 +470,17 @@ TEST_F(ReceiveStatisticsTest, RtpCallbacks) { RtpPacketReceived packet1 = CreateRtpPacket(kSsrc1, kHeaderLength, kPacketSize1, 0); receive_statistics_->OnRtpPacket(packet1); - StreamDataCounters expected; - expected.transmitted.payload_bytes = kPacketSize1; - expected.transmitted.header_bytes = kHeaderLength; - expected.transmitted.padding_bytes = 0; - expected.transmitted.packets = 1; - expected.retransmitted.payload_bytes = 0; - expected.retransmitted.header_bytes = 0; - expected.retransmitted.padding_bytes = 0; - expected.retransmitted.packets = 0; - expected.fec.packets = 0; - callback.Matches(1, kSsrc1, expected); + StreamDataCounters counters = receive_statistics_->GetStatistician(kSsrc1) + ->GetReceiveStreamDataCounters(); + EXPECT_EQ(counters.transmitted.payload_bytes, kPacketSize1); + EXPECT_EQ(counters.transmitted.header_bytes, kHeaderLength); + EXPECT_EQ(counters.transmitted.padding_bytes, 0u); + EXPECT_EQ(counters.transmitted.packets, 1u); + EXPECT_EQ(counters.retransmitted.payload_bytes, 0u); + EXPECT_EQ(counters.retransmitted.header_bytes, 0u); + EXPECT_EQ(counters.retransmitted.padding_bytes, 0u); + EXPECT_EQ(counters.retransmitted.packets, 0u); + EXPECT_EQ(counters.fec.packets, 0u); // Another packet of size kPacketSize1 with 9 bytes padding. RtpPacketReceived packet2 = @@ -526,77 +488,89 @@ TEST_F(ReceiveStatisticsTest, RtpCallbacks) { packet2.SetSequenceNumber(packet1.SequenceNumber() + 1); clock_.AdvanceTimeMilliseconds(5); receive_statistics_->OnRtpPacket(packet2); - expected.transmitted.payload_bytes = kPacketSize1 * 2; - expected.transmitted.header_bytes = kHeaderLength * 2; - expected.transmitted.padding_bytes = kPaddingLength; - expected.transmitted.packets = 2; - callback.Matches(2, kSsrc1, expected); + counters = receive_statistics_->GetStatistician(kSsrc1) + ->GetReceiveStreamDataCounters(); + EXPECT_EQ(counters.transmitted.payload_bytes, kPacketSize1 * 2); + EXPECT_EQ(counters.transmitted.header_bytes, kHeaderLength * 2); + EXPECT_EQ(counters.transmitted.padding_bytes, kPaddingLength); + EXPECT_EQ(counters.transmitted.packets, 2u); clock_.AdvanceTimeMilliseconds(5); // Retransmit last packet. receive_statistics_->OnRtpPacket(packet2); - expected.transmitted.payload_bytes = kPacketSize1 * 3; - expected.transmitted.header_bytes = kHeaderLength * 3; - expected.transmitted.padding_bytes = kPaddingLength * 2; - expected.transmitted.packets = 3; - expected.retransmitted.payload_bytes = kPacketSize1; - expected.retransmitted.header_bytes = kHeaderLength; - expected.retransmitted.padding_bytes = kPaddingLength; - expected.retransmitted.packets = 1; - callback.Matches(3, kSsrc1, expected); + counters = receive_statistics_->GetStatistician(kSsrc1) + ->GetReceiveStreamDataCounters(); + EXPECT_EQ(counters.transmitted.payload_bytes, kPacketSize1 * 3); + EXPECT_EQ(counters.transmitted.header_bytes, kHeaderLength * 3); + EXPECT_EQ(counters.transmitted.padding_bytes, kPaddingLength * 2); + EXPECT_EQ(counters.transmitted.packets, 3u); + EXPECT_EQ(counters.retransmitted.payload_bytes, kPacketSize1); + EXPECT_EQ(counters.retransmitted.header_bytes, kHeaderLength); + EXPECT_EQ(counters.retransmitted.padding_bytes, kPaddingLength); + EXPECT_EQ(counters.retransmitted.packets, 1u); // One FEC packet. packet1.SetSequenceNumber(packet2.SequenceNumber() + 1); clock_.AdvanceTimeMilliseconds(5); receive_statistics_->OnRtpPacket(packet1); receive_statistics_->FecPacketReceived(packet1); - expected.transmitted.payload_bytes = kPacketSize1 * 4; - expected.transmitted.header_bytes = kHeaderLength * 4; - expected.transmitted.packets = 4; - expected.fec.payload_bytes = kPacketSize1; - expected.fec.header_bytes = kHeaderLength; - expected.fec.packets = 1; - callback.Matches(5, kSsrc1, expected); + counters = receive_statistics_->GetStatistician(kSsrc1) + ->GetReceiveStreamDataCounters(); + EXPECT_EQ(counters.transmitted.payload_bytes, kPacketSize1 * 4); + EXPECT_EQ(counters.transmitted.header_bytes, kHeaderLength * 4); + EXPECT_EQ(counters.transmitted.packets, 4u); + EXPECT_EQ(counters.fec.payload_bytes, kPacketSize1); + EXPECT_EQ(counters.fec.header_bytes, kHeaderLength); + EXPECT_EQ(counters.fec.packets, 1u); } TEST_F(ReceiveStatisticsTest, LastPacketReceivedTimestamp) { - RtpTestCallback callback; - receive_statistics_ = ReceiveStatistics::Create(&clock_, &callback); + receive_statistics_ = ReceiveStatistics::Create(&clock_); clock_.AdvanceTimeMilliseconds(42); receive_statistics_->OnRtpPacket(packet1_); - EXPECT_EQ(42, callback.stats_.last_packet_received_timestamp_ms); + StreamDataCounters counters = receive_statistics_->GetStatistician(kSsrc1) + ->GetReceiveStreamDataCounters(); + + EXPECT_EQ(42, counters.last_packet_received_timestamp_ms); clock_.AdvanceTimeMilliseconds(3); receive_statistics_->OnRtpPacket(packet1_); - EXPECT_EQ(45, callback.stats_.last_packet_received_timestamp_ms); + counters = receive_statistics_->GetStatistician(kSsrc1) + ->GetReceiveStreamDataCounters(); + EXPECT_EQ(45, counters.last_packet_received_timestamp_ms); } -TEST_F(ReceiveStatisticsTest, RtpCallbacksFecFirst) { - RtpTestCallback callback; - receive_statistics_ = ReceiveStatistics::Create(&clock_, &callback); +TEST_F(ReceiveStatisticsTest, FecFirst) { + receive_statistics_ = ReceiveStatistics::Create(&clock_); const uint32_t kHeaderLength = 20; RtpPacketReceived packet = CreateRtpPacket(kSsrc1, kHeaderLength, kPacketSize1, 0); // If first packet is FEC, ignore it. receive_statistics_->FecPacketReceived(packet); - EXPECT_EQ(0u, callback.num_calls_); + + EXPECT_EQ(receive_statistics_->GetStatistician(kSsrc1), nullptr); receive_statistics_->OnRtpPacket(packet); - StreamDataCounters expected; - expected.transmitted.payload_bytes = kPacketSize1; - expected.transmitted.header_bytes = kHeaderLength; - expected.transmitted.padding_bytes = 0; - expected.transmitted.packets = 1; - expected.fec.packets = 0; - callback.Matches(1, kSsrc1, expected); + StreamDataCounters counters = receive_statistics_->GetStatistician(kSsrc1) + ->GetReceiveStreamDataCounters(); + EXPECT_EQ(counters.transmitted.payload_bytes, kPacketSize1); + EXPECT_EQ(counters.transmitted.header_bytes, kHeaderLength); + EXPECT_EQ(counters.transmitted.padding_bytes, 0u); + EXPECT_EQ(counters.transmitted.packets, 1u); + EXPECT_EQ(counters.fec.packets, 0u); receive_statistics_->FecPacketReceived(packet); - expected.fec.payload_bytes = kPacketSize1; - expected.fec.header_bytes = kHeaderLength; - expected.fec.packets = 1; - callback.Matches(2, kSsrc1, expected); + counters = receive_statistics_->GetStatistician(kSsrc1) + ->GetReceiveStreamDataCounters(); + EXPECT_EQ(counters.transmitted.payload_bytes, kPacketSize1); + EXPECT_EQ(counters.transmitted.header_bytes, kHeaderLength); + EXPECT_EQ(counters.transmitted.padding_bytes, 0u); + EXPECT_EQ(counters.transmitted.packets, 1u); + EXPECT_EQ(counters.fec.payload_bytes, kPacketSize1); + EXPECT_EQ(counters.fec.header_bytes, kHeaderLength); + EXPECT_EQ(counters.fec.packets, 1u); } } // namespace diff --git a/video/receive_statistics_proxy.cc b/video/receive_statistics_proxy.cc index aaeed1b5c8..4359b5d197 100644 --- a/video/receive_statistics_proxy.cc +++ b/video/receive_statistics_proxy.cc @@ -118,15 +118,12 @@ ReceiveStatisticsProxy::ReceiveStatisticsProxy( decode_thread_.Detach(); network_thread_.Detach(); stats_.ssrc = config_.rtp.remote_ssrc; - // TODO(brandtr): Replace |rtx_stats_| with a single instance of - // StreamDataCounters. - if (config_.rtp.rtx_ssrc) { - rtx_stats_[config_.rtp.rtx_ssrc] = StreamDataCounters(); - } } void ReceiveStatisticsProxy::UpdateHistograms( - absl::optional fraction_lost) { + absl::optional fraction_lost, + const StreamDataCounters& rtp_stats, + const StreamDataCounters* rtx_stats) { // Not actually running on the decoder thread, but must be called after // DecoderThreadStopped, which detaches the thread checker. It is therefore // safe to access |qp_counters_|, which were updated on the decode thread @@ -404,42 +401,42 @@ void ReceiveStatisticsProxy::UpdateHistograms( } } - StreamDataCounters rtp = stats_.rtp_stats; - StreamDataCounters rtx; - for (auto it : rtx_stats_) - rtx.Add(it.second); - StreamDataCounters rtp_rtx = rtp; - rtp_rtx.Add(rtx); + StreamDataCounters rtp_rtx_stats = rtp_stats; + if (rtx_stats) + rtp_rtx_stats.Add(*rtx_stats); int64_t elapsed_sec = - rtp_rtx.TimeSinceFirstPacketInMs(clock_->TimeInMilliseconds()) / 1000; + rtp_rtx_stats.TimeSinceFirstPacketInMs(clock_->TimeInMilliseconds()) / + 1000; if (elapsed_sec >= metrics::kMinRunTimeInSeconds) { RTC_HISTOGRAM_COUNTS_10000( "WebRTC.Video.BitrateReceivedInKbps", - static_cast(rtp_rtx.transmitted.TotalBytes() * 8 / elapsed_sec / - 1000)); - int media_bitrate_kbs = - static_cast(rtp.MediaPayloadBytes() * 8 / elapsed_sec / 1000); + static_cast(rtp_rtx_stats.transmitted.TotalBytes() * 8 / + elapsed_sec / 1000)); + int media_bitrate_kbs = static_cast(rtp_stats.MediaPayloadBytes() * 8 / + elapsed_sec / 1000); RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.MediaBitrateReceivedInKbps", media_bitrate_kbs); log_stream << "WebRTC.Video.MediaBitrateReceivedInKbps " << media_bitrate_kbs << '\n'; RTC_HISTOGRAM_COUNTS_10000( "WebRTC.Video.PaddingBitrateReceivedInKbps", - static_cast(rtp_rtx.transmitted.padding_bytes * 8 / elapsed_sec / - 1000)); + static_cast(rtp_rtx_stats.transmitted.padding_bytes * 8 / + elapsed_sec / 1000)); RTC_HISTOGRAM_COUNTS_10000( "WebRTC.Video.RetransmittedBitrateReceivedInKbps", - static_cast(rtp_rtx.retransmitted.TotalBytes() * 8 / elapsed_sec / - 1000)); - if (!rtx_stats_.empty()) { - RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.RtxBitrateReceivedInKbps", - static_cast(rtx.transmitted.TotalBytes() * - 8 / elapsed_sec / 1000)); + static_cast(rtp_rtx_stats.retransmitted.TotalBytes() * 8 / + elapsed_sec / 1000)); + if (rtx_stats) { + RTC_HISTOGRAM_COUNTS_10000( + "WebRTC.Video.RtxBitrateReceivedInKbps", + static_cast(rtx_stats->transmitted.TotalBytes() * 8 / + elapsed_sec / 1000)); } if (config_.rtp.ulpfec_payload_type != -1) { RTC_HISTOGRAM_COUNTS_10000( "WebRTC.Video.FecBitrateReceivedInKbps", - static_cast(rtp_rtx.fec.TotalBytes() * 8 / elapsed_sec / 1000)); + static_cast(rtp_rtx_stats.fec.TotalBytes() * 8 / elapsed_sec / + 1000)); } const RtcpPacketTypeCounter& counters = stats_.rtcp_packet_type_counts; RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.NackPacketsSentPerMinute", @@ -667,22 +664,6 @@ void ReceiveStatisticsProxy::OnCname(uint32_t ssrc, absl::string_view cname) { stats_.c_name = std::string(cname); } -void ReceiveStatisticsProxy::DataCountersUpdated( - const webrtc::StreamDataCounters& counters, - uint32_t ssrc) { - rtc::CritScope lock(&crit_); - if (ssrc == stats_.ssrc) { - stats_.rtp_stats = counters; - } else { - auto it = rtx_stats_.find(ssrc); - if (it != rtx_stats_.end()) { - it->second = counters; - } else { - RTC_NOTREACHED() << "Unexpected stream ssrc: " << ssrc; - } - } -} - void ReceiveStatisticsProxy::OnDecodedFrame(const VideoFrame& frame, absl::optional qp, int32_t decode_time_ms, diff --git a/video/receive_statistics_proxy.h b/video/receive_statistics_proxy.h index fe93030a7b..f1a9f1ec7a 100644 --- a/video/receive_statistics_proxy.h +++ b/video/receive_statistics_proxy.h @@ -39,7 +39,6 @@ struct CodecSpecificInfo; class ReceiveStatisticsProxy : public VCMReceiveStatisticsCallback, public RtcpCnameCallback, public RtcpPacketTypeCounterObserver, - public StreamDataCountersCallback, public CallStatsObserver { public: ReceiveStatisticsProxy(const VideoReceiveStream::Config* config, @@ -84,9 +83,6 @@ class ReceiveStatisticsProxy : public VCMReceiveStatisticsCallback, void RtcpPacketTypesCounterUpdated( uint32_t ssrc, const RtcpPacketTypeCounter& packet_counter) override; - // Overrides StreamDataCountersCallback. - void DataCountersUpdated(const webrtc::StreamDataCounters& counters, - uint32_t ssrc) override; // Implements CallStatsObserver. void OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) override; @@ -98,7 +94,9 @@ class ReceiveStatisticsProxy : public VCMReceiveStatisticsCallback, // Produce histograms. Must be called after DecoderThreadStopped(), typically // at the end of the call. - void UpdateHistograms(absl::optional fraction_lost); + void UpdateHistograms(absl::optional fraction_lost, + const StreamDataCounters& rtp_stats, + const StreamDataCounters* rtx_stats); private: struct QpCounters { @@ -147,6 +145,7 @@ class ReceiveStatisticsProxy : public VCMReceiveStatisticsCallback, rtc::SampleCounter qp_sample_ RTC_GUARDED_BY(crit_); int num_bad_states_ RTC_GUARDED_BY(crit_); int num_certain_states_ RTC_GUARDED_BY(crit_); + // Note: The |stats_.rtp_stats| member is not used or populated by this class. mutable VideoReceiveStream::Stats stats_ RTC_GUARDED_BY(crit_); RateStatistics decode_fps_estimator_ RTC_GUARDED_BY(crit_); RateStatistics renders_fps_estimator_ RTC_GUARDED_BY(crit_); @@ -166,7 +165,6 @@ class ReceiveStatisticsProxy : public VCMReceiveStatisticsCallback, RTC_GUARDED_BY(crit_); MaxCounter freq_offset_counter_ RTC_GUARDED_BY(crit_); QpCounters qp_counters_ RTC_GUARDED_BY(decode_thread_); - std::map rtx_stats_ RTC_GUARDED_BY(crit_); int64_t avg_rtt_ms_ RTC_GUARDED_BY(crit_); mutable std::map frame_window_ RTC_GUARDED_BY(&crit_); VideoContentType last_content_type_ RTC_GUARDED_BY(&crit_); diff --git a/video/receive_statistics_proxy_unittest.cc b/video/receive_statistics_proxy_unittest.cc index 5a6a0ef903..9834b3e143 100644 --- a/video/receive_statistics_proxy_unittest.cc +++ b/video/receive_statistics_proxy_unittest.cc @@ -53,12 +53,6 @@ class ReceiveStatisticsProxyTest : public ::testing::Test { return config; } - void InsertFirstRtpPacket(uint32_t ssrc) { - StreamDataCounters counters; - counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds(); - statistics_proxy_->DataCountersUpdated(counters, ssrc); - } - VideoFrame CreateFrame(int width, int height) { return CreateVideoFrame(width, height, 0); } @@ -103,7 +97,8 @@ TEST_F(ReceiveStatisticsProxyTest, DecodedFpsIsReported) { VideoContentType::UNSPECIFIED); fake_clock_.AdvanceTimeMilliseconds(1000 / kFps); } - statistics_proxy_->UpdateHistograms(absl::nullopt); + statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(), + nullptr); EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond")); EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DecodedFramesPerSecond", kFps)); } @@ -117,7 +112,8 @@ TEST_F(ReceiveStatisticsProxyTest, DecodedFpsIsNotReportedForTooFewSamples) { VideoContentType::UNSPECIFIED); fake_clock_.AdvanceTimeMilliseconds(1000 / kFps); } - statistics_proxy_->UpdateHistograms(absl::nullopt); + statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(), + nullptr); EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond")); } @@ -525,7 +521,8 @@ TEST_F(ReceiveStatisticsProxyTest, LifetimeHistogramIsUpdated) { fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000); // Need at least one frame to report stream lifetime. statistics_proxy_->OnCompleteFrame(true, 1000, VideoContentType::UNSPECIFIED); - statistics_proxy_->UpdateHistograms(absl::nullopt); + statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(), + nullptr); EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds")); EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceiveStreamLifetimeInSeconds", @@ -537,7 +534,8 @@ TEST_F(ReceiveStatisticsProxyTest, const int64_t kTimeSec = 3; fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000); // No frames received. - statistics_proxy_->UpdateHistograms(absl::nullopt); + statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(), + nullptr); EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds")); } @@ -552,7 +550,6 @@ TEST_F(ReceiveStatisticsProxyTest, BadCallHistogramsAreUpdated) { StreamDataCounters counters; counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds(); - statistics_proxy_->DataCountersUpdated(counters, config_.rtp.remote_ssrc); webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight); @@ -560,7 +557,7 @@ TEST_F(ReceiveStatisticsProxyTest, BadCallHistogramsAreUpdated) { fake_clock_.AdvanceTimeMilliseconds(kBadFameIntervalMs); statistics_proxy_->OnRenderedFrame(frame); } - statistics_proxy_->UpdateHistograms(absl::nullopt); + statistics_proxy_->UpdateHistograms(absl::nullopt, counters, nullptr); EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BadCall.Any")); EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.BadCall.Any", 100)); @@ -573,7 +570,7 @@ TEST_F(ReceiveStatisticsProxyTest, BadCallHistogramsAreUpdated) { } TEST_F(ReceiveStatisticsProxyTest, PacketLossHistogramIsUpdated) { - statistics_proxy_->UpdateHistograms(10); + statistics_proxy_->UpdateHistograms(10, StreamDataCounters(), nullptr); EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent")); @@ -582,7 +579,7 @@ TEST_F(ReceiveStatisticsProxyTest, PacketLossHistogramIsUpdated) { // Min run time has passed. fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000); - statistics_proxy_->UpdateHistograms(10); + statistics_proxy_->UpdateHistograms(10, StreamDataCounters(), nullptr); EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent")); EXPECT_EQ( @@ -603,7 +600,8 @@ TEST_F(ReceiveStatisticsProxyTest, AvSyncOffsetHistogramIsUpdated) { const double kFreqKhz = 90.0; for (int i = 0; i < kMinRequiredSamples; ++i) statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz); - statistics_proxy_->UpdateHistograms(absl::nullopt); + statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(), + nullptr); EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AVSyncOffsetInMs")); EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AVSyncOffsetInMs", kSyncOffsetMs)); @@ -622,7 +620,8 @@ TEST_F(ReceiveStatisticsProxyTest, RtpToNtpFrequencyOffsetHistogramIsUpdated) { fake_clock_.AdvanceTimeMilliseconds(kFreqOffsetProcessIntervalInMs); // Process interval passed, max diff: 4. statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz); - statistics_proxy_->UpdateHistograms(absl::nullopt); + statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(), + nullptr); // Average reported: (2 + 4) / 2 = 3. EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtpToNtpFreqOffsetInKhz")); EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtpToNtpFreqOffsetInKhz", 3)); @@ -634,7 +633,8 @@ TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsUpdated) { for (int i = 0; i < kMinRequiredSamples; ++i) statistics_proxy_->OnPreDecode(kVideoCodecVP8, kQp); - statistics_proxy_->UpdateHistograms(absl::nullopt); + statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(), + nullptr); EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp")); EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.Decoded.Vp8.Qp", kQp)); } @@ -645,7 +645,8 @@ TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsNotUpdatedForTooFewSamples) { for (int i = 0; i < kMinRequiredSamples - 1; ++i) statistics_proxy_->OnPreDecode(kVideoCodecVP8, kQp); - statistics_proxy_->UpdateHistograms(absl::nullopt); + statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(), + nullptr); EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp")); } @@ -653,7 +654,8 @@ TEST_F(ReceiveStatisticsProxyTest, Vp8QpHistogramIsNotUpdatedIfNoQpValue) { for (int i = 0; i < kMinRequiredSamples; ++i) statistics_proxy_->OnPreDecode(kVideoCodecVP8, -1); - statistics_proxy_->UpdateHistograms(absl::nullopt); + statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(), + nullptr); EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.Decoded.Vp8.Qp")); } @@ -670,7 +672,8 @@ TEST_F(ReceiveStatisticsProxyTest, EXPECT_EQ(kMinRequiredSamples - 1, statistics_proxy_->GetStats().frame_counts.delta_frames); - statistics_proxy_->UpdateHistograms(absl::nullopt); + statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(), + nullptr); EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille")); } @@ -687,7 +690,8 @@ TEST_F(ReceiveStatisticsProxyTest, EXPECT_EQ(kMinRequiredSamples, statistics_proxy_->GetStats().frame_counts.delta_frames); - statistics_proxy_->UpdateHistograms(absl::nullopt); + statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(), + nullptr); EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille")); EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.KeyFramesReceivedInPermille", 0)); @@ -709,7 +713,8 @@ TEST_F(ReceiveStatisticsProxyTest, KeyFrameHistogramIsUpdated) { EXPECT_EQ(kMinRequiredSamples, statistics_proxy_->GetStats().frame_counts.delta_frames); - statistics_proxy_->UpdateHistograms(absl::nullopt); + statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(), + nullptr); EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille")); EXPECT_EQ( 1, metrics::NumEvents("WebRTC.Video.KeyFramesReceivedInPermille", 500)); @@ -729,7 +734,8 @@ TEST_F(ReceiveStatisticsProxyTest, TimingHistogramsNotUpdatedForTooFewSamples) { kMinPlayoutDelayMs, kRenderDelayMs); } - statistics_proxy_->UpdateHistograms(absl::nullopt); + statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(), + nullptr); EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs")); EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs")); EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.TargetDelayInMs")); @@ -751,7 +757,8 @@ TEST_F(ReceiveStatisticsProxyTest, TimingHistogramsAreUpdated) { kMinPlayoutDelayMs, kRenderDelayMs); } - statistics_proxy_->UpdateHistograms(absl::nullopt); + statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(), + nullptr); EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs")); EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.TargetDelayInMs")); EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs")); @@ -807,7 +814,8 @@ TEST_F(ReceiveStatisticsProxyTest, for (int i = 0; i < kMinRequiredSamples - 1; ++i) statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight)); - statistics_proxy_->UpdateHistograms(absl::nullopt); + statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(), + nullptr); EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels")); EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels")); EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond")); @@ -818,7 +826,8 @@ TEST_F(ReceiveStatisticsProxyTest, ReceivedFrameHistogramsAreUpdated) { for (int i = 0; i < kMinRequiredSamples; ++i) statistics_proxy_->OnRenderedFrame(CreateFrame(kWidth, kHeight)); - statistics_proxy_->UpdateHistograms(absl::nullopt); + statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(), + nullptr); EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedWidthInPixels")); EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.ReceivedHeightInPixels")); EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond")); @@ -840,7 +849,8 @@ TEST_F(ReceiveStatisticsProxyTest, ZeroDelayReportedIfFrameNotDelayed) { // Min run time has passed. fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000)); - statistics_proxy_->UpdateHistograms(absl::nullopt); + statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(), + nullptr); EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer")); EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 0)); EXPECT_EQ(0, metrics::NumSamples( @@ -860,7 +870,8 @@ TEST_F(ReceiveStatisticsProxyTest, // Min run time has not passed. fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000) - 1); - statistics_proxy_->UpdateHistograms(absl::nullopt); + statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(), + nullptr); EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer")); EXPECT_EQ(0, metrics::NumSamples( "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs")); @@ -874,7 +885,8 @@ TEST_F(ReceiveStatisticsProxyTest, // Min run time has passed. No rendered frames. fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000)); - statistics_proxy_->UpdateHistograms(absl::nullopt); + statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(), + nullptr); EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer")); EXPECT_EQ(0, metrics::NumSamples( "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs")); @@ -891,7 +903,8 @@ TEST_F(ReceiveStatisticsProxyTest, DelayReportedIfFrameIsDelayed) { // Min run time has passed. fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000)); - statistics_proxy_->UpdateHistograms(absl::nullopt); + statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(), + nullptr); EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer")); EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 100)); EXPECT_EQ(1, metrics::NumSamples( @@ -914,7 +927,8 @@ TEST_F(ReceiveStatisticsProxyTest, AverageDelayOfDelayedFramesIsReported) { // Min run time has passed. fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000)); - statistics_proxy_->UpdateHistograms(absl::nullopt); + statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(), + nullptr); EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer")); EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DelayedFramesToRenderer", 50)); EXPECT_EQ(1, metrics::NumSamples( @@ -925,21 +939,24 @@ TEST_F(ReceiveStatisticsProxyTest, AverageDelayOfDelayedFramesIsReported) { TEST_F(ReceiveStatisticsProxyTest, RtcpHistogramsNotUpdatedIfMinRuntimeHasNotPassed) { - InsertFirstRtpPacket(kRemoteSsrc); + StreamDataCounters data_counters; + data_counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds(); + fake_clock_.AdvanceTimeMilliseconds((metrics::kMinRunTimeInSeconds * 1000) - 1); RtcpPacketTypeCounter counter; statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter); - statistics_proxy_->UpdateHistograms(absl::nullopt); + statistics_proxy_->UpdateHistograms(absl::nullopt, data_counters, nullptr); EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute")); EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute")); EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute")); } TEST_F(ReceiveStatisticsProxyTest, RtcpHistogramsAreUpdated) { - InsertFirstRtpPacket(kRemoteSsrc); + StreamDataCounters data_counters; + data_counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds(); fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000); const uint32_t kFirPackets = 100; @@ -952,7 +969,7 @@ TEST_F(ReceiveStatisticsProxyTest, RtcpHistogramsAreUpdated) { counter.nack_packets = kNackPackets; statistics_proxy_->RtcpPacketTypesCounterUpdated(kRemoteSsrc, counter); - statistics_proxy_->UpdateHistograms(absl::nullopt); + statistics_proxy_->UpdateHistograms(absl::nullopt, data_counters, nullptr); EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute")); EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute")); EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute")); @@ -1044,7 +1061,8 @@ TEST_P(ReceiveStatisticsProxyTestWithContent, InterFrameDelaysAreReported) { fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs); statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_); - statistics_proxy_->UpdateHistograms(absl::nullopt); + statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(), + nullptr); const int kExpectedInterFrame = (kInterFrameDelayMs * (kMinRequiredSamples - 1) + kInterFrameDelayMs * 2) / @@ -1083,7 +1101,8 @@ TEST_P(ReceiveStatisticsProxyTestWithContent, fake_clock_.AdvanceTimeMilliseconds(10 * kInterFrameDelayMs); statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_); - statistics_proxy_->UpdateHistograms(absl::nullopt); + statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(), + nullptr); const int kExpectedInterFrame = kInterFrameDelayMs * 2; if (videocontenttypehelpers::IsScreenshare(content_type_)) { EXPECT_EQ(kExpectedInterFrame, @@ -1108,7 +1127,8 @@ TEST_P(ReceiveStatisticsProxyTestWithContent, // |kMinRequiredSamples| samples, and thereby intervals, is required. That // means we're one frame short of having a valid data set. - statistics_proxy_->UpdateHistograms(absl::nullopt); + statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(), + nullptr); EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.InterframeDelayInMs")); EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.InterframeDelayMaxInMs")); EXPECT_EQ( @@ -1137,7 +1157,8 @@ TEST_P(ReceiveStatisticsProxyTestWithContent, MaxInterFrameDelayOnlyWithPause) { fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs); statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_); - statistics_proxy_->UpdateHistograms(absl::nullopt); + statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(), + nullptr); if (videocontenttypehelpers::IsScreenshare(content_type_)) { EXPECT_EQ( 1, metrics::NumSamples("WebRTC.Video.Screenshare.InterframeDelayInMs")); @@ -1176,7 +1197,8 @@ TEST_P(ReceiveStatisticsProxyTestWithContent, FreezesAreReported) { statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_); statistics_proxy_->OnRenderedFrame(frame); - statistics_proxy_->UpdateHistograms(absl::nullopt); + statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(), + nullptr); const int kExpectedTimeBetweenFreezes = kInterFrameDelayMs * (kMinRequiredSamples - 1); const int kExpectedNumberFreezesPerMinute = 60 * 1000 / kCallDurationMs; @@ -1226,7 +1248,8 @@ TEST_P(ReceiveStatisticsProxyTestWithContent, HarmonicFrameRateIsReported) { statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_); statistics_proxy_->OnRenderedFrame(frame); - statistics_proxy_->UpdateHistograms(absl::nullopt); + statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(), + nullptr); double kSumSquaredFrameDurationSecs = (kMinRequiredSamples - 1) * (kFrameDurationMs / 1000.0 * kFrameDurationMs / 1000.0); @@ -1266,7 +1289,8 @@ TEST_P(ReceiveStatisticsProxyTestWithContent, PausesAreIgnored) { fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs); } - statistics_proxy_->UpdateHistograms(absl::nullopt); + statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(), + nullptr); // Average of two playback intervals. const int kExpectedTimeBetweenFreezes = kInterFrameDelayMs * kMinRequiredSamples * 2; @@ -1299,7 +1323,8 @@ TEST_P(ReceiveStatisticsProxyTestWithContent, ManyPausesAtTheBeginning) { fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs); } - statistics_proxy_->UpdateHistograms(absl::nullopt); + statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(), + nullptr); // No freezes should be detected, as all long inter-frame delays were pauses. if (videocontenttypehelpers::IsScreenshare(content_type_)) { EXPECT_EQ(-1, metrics::MinSample( @@ -1331,7 +1356,8 @@ TEST_P(ReceiveStatisticsProxyTestWithContent, TimeInHdReported) { // Extra last frame. statistics_proxy_->OnRenderedFrame(frame_sd); - statistics_proxy_->UpdateHistograms(absl::nullopt); + statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(), + nullptr); const int kExpectedTimeInHdPercents = 33; if (videocontenttypehelpers::IsScreenshare(content_type_)) { EXPECT_EQ( @@ -1365,7 +1391,8 @@ TEST_P(ReceiveStatisticsProxyTestWithContent, TimeInBlockyVideoReported) { statistics_proxy_->OnDecodedFrame(frame, kHighQp, 0, content_type_); statistics_proxy_->OnRenderedFrame(frame); - statistics_proxy_->UpdateHistograms(absl::nullopt); + statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(), + nullptr); const int kExpectedTimeInHdPercents = 66; if (videocontenttypehelpers::IsScreenshare(content_type_)) { EXPECT_EQ(kExpectedTimeInHdPercents, @@ -1398,7 +1425,8 @@ TEST_P(ReceiveStatisticsProxyTestWithContent, DownscalesReported) { statistics_proxy_->OnRenderedFrame(frame_ld); fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs); - statistics_proxy_->UpdateHistograms(absl::nullopt); + statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(), + nullptr); const int kExpectedDownscales = 30; // 2 per 4 seconds = 30 per minute. if (videocontenttypehelpers::IsScreenshare(content_type_)) { EXPECT_EQ( @@ -1423,7 +1451,8 @@ TEST_P(ReceiveStatisticsProxyTestWithContent, DecodeTimeReported) { statistics_proxy_->OnDecodedFrame(frame, kLowQp, kDecodeMs, content_type_); fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs); } - statistics_proxy_->UpdateHistograms(absl::nullopt); + statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(), + nullptr); EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.DecodeTimeInMs", kDecodeMs)); } @@ -1447,7 +1476,8 @@ TEST_P(ReceiveStatisticsProxyTestWithContent, fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs2); statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type); } - statistics_proxy_->UpdateHistograms(absl::nullopt); + statistics_proxy_->UpdateHistograms(absl::nullopt, StreamDataCounters(), + nullptr); if (videocontenttypehelpers::IsScreenshare(content_type)) { EXPECT_EQ( diff --git a/video/video_receive_stream.cc b/video/video_receive_stream.cc index 3a50bc9134..ef1ac85842 100644 --- a/video/video_receive_stream.cc +++ b/video/video_receive_stream.cc @@ -193,7 +193,7 @@ VideoReceiveStream::VideoReceiveStream( call_stats_(call_stats), source_tracker_(clock_), stats_proxy_(&config_, clock_), - rtp_receive_statistics_(ReceiveStatistics::Create(clock_, &stats_proxy_)), + rtp_receive_statistics_(ReceiveStatistics::Create(clock_)), timing_(timing), video_receiver_(clock_, timing_.get()), rtp_video_stream_receiver_(clock_, @@ -464,6 +464,7 @@ VideoReceiveStream::Stats VideoReceiveStream::GetStats() const { rtp_receive_statistics_->GetStatistician(stats.ssrc); if (statistician) { statistician->GetStatistics(&stats.rtcp_stats, /*reset=*/false); + stats.rtp_stats = statistician->GetReceiveStreamDataCounters(); stats.total_bitrate_bps = statistician->BitrateReceived(); } if (config_.rtp.rtx_ssrc) { @@ -477,12 +478,24 @@ VideoReceiveStream::Stats VideoReceiveStream::GetStats() const { void VideoReceiveStream::UpdateHistograms() { absl::optional fraction_lost; + StreamDataCounters rtp_stats; StreamStatistician* statistician = rtp_receive_statistics_->GetStatistician(config_.rtp.remote_ssrc); if (statistician) { fraction_lost = statistician->GetFractionLostInPercent(); + rtp_stats = statistician->GetReceiveStreamDataCounters(); } - stats_proxy_.UpdateHistograms(fraction_lost); + if (config_.rtp.rtx_ssrc) { + StreamStatistician* rtx_statistician = + rtp_receive_statistics_->GetStatistician(config_.rtp.rtx_ssrc); + if (rtx_statistician) { + StreamDataCounters rtx_stats = + rtx_statistician->GetReceiveStreamDataCounters(); + stats_proxy_.UpdateHistograms(fraction_lost, rtp_stats, &rtx_stats); + return; + } + } + stats_proxy_.UpdateHistograms(fraction_lost, rtp_stats, nullptr); } void VideoReceiveStream::AddSecondarySink(RtpPacketSinkInterface* sink) {