From 6eb30e40af3ae5977b176012debcff01e8627764 Mon Sep 17 00:00:00 2001 From: Artem Titov Date: Fri, 27 Aug 2021 22:29:03 +0200 Subject: [PATCH] [DVQA] Tolerate receiving frames which were considerer as dropped before It can happen that SFU will resend the frame which was before considered as dropped during stream switching. Bug: b/197740434 Change-Id: I95a67e6e637f6005a24df15875b50133a6e8eaaf Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/230423 Commit-Queue: Artem Titov Reviewed-by: Mirko Bonadei Cr-Commit-Position: refs/heads/main@{#34865} --- .../video/default_video_quality_analyzer.cc | 37 ++++++++++++++++--- .../video/default_video_quality_analyzer.h | 1 + 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/test/pc/e2e/analyzer/video/default_video_quality_analyzer.cc b/test/pc/e2e/analyzer/video/default_video_quality_analyzer.cc index b8c8a67ee8..da4a81a1fe 100644 --- a/test/pc/e2e/analyzer/video/default_video_quality_analyzer.cc +++ b/test/pc/e2e/analyzer/video/default_video_quality_analyzer.cc @@ -33,6 +33,10 @@ namespace { constexpr int kMicrosPerSecond = 1000000; constexpr int kBitsInByte = 8; +constexpr absl::string_view kSkipRenderedFrameReasonProcessed = "processed"; +constexpr absl::string_view kSkipRenderedFrameReasonRendered = "rendered"; +constexpr absl::string_view kSkipRenderedFrameReasonDropped = + "considered dropped"; void LogFrameCounters(const std::string& name, const FrameCounters& counters) { RTC_LOG(INFO) << "[" << name << "] Captured : " << counters.captured; @@ -387,12 +391,25 @@ void DefaultVideoQualityAnalyzer::OnFrameRendered( auto frame_it = captured_frames_in_flight_.find(frame.id()); if (frame_it == captured_frames_in_flight_.end() || - frame_it->second.HasRenderedTime(peer_index)) { - // It means this frame was rendered before, so we can skip it. It may happen - // when we have multiple simulcast streams in one track and received - // the same picture from two different streams because SFU can't reliably - // correlate two simulcast streams and started relaying the second stream - // from the same frame it has relayed right before for the first stream. + frame_it->second.HasRenderedTime(peer_index) || + frame_it->second.IsDropped(peer_index)) { + // It means this frame was rendered or dropped before, so we can skip it. + // It may happen when we have multiple simulcast streams in one track and + // received the same frame from two different streams because SFU can't + // reliably correlate two simulcast streams and started relaying the second + // stream from the same frame it has relayed right before for the first + // stream. + absl::string_view reason = kSkipRenderedFrameReasonProcessed; + if (frame_it != captured_frames_in_flight_.end()) { + if (frame_it->second.HasRenderedTime(peer_index)) { + reason = kSkipRenderedFrameReasonRendered; + } else if (frame_it->second.IsDropped(peer_index)) { + reason = kSkipRenderedFrameReasonDropped; + } + } + RTC_LOG(WARNING) << "Peer " << peer_name + << "; Received frame out of order: received frame with id " + << frame.id() << " which was " << reason << " before"; return; } @@ -1030,6 +1047,14 @@ bool DefaultVideoQualityAnalyzer::FrameInFlight::HasRenderedTime( return it->second.rendered_time.IsFinite(); } +bool DefaultVideoQualityAnalyzer::FrameInFlight::IsDropped(size_t peer) const { + auto it = receiver_stats_.find(peer); + if (it == receiver_stats_.end()) { + return false; + } + return it->second.dropped; +} + FrameStats DefaultVideoQualityAnalyzer::FrameInFlight::GetStatsForPeer( size_t peer) const { FrameStats stats(captured_time_); diff --git a/test/pc/e2e/analyzer/video/default_video_quality_analyzer.h b/test/pc/e2e/analyzer/video/default_video_quality_analyzer.h index 2091edf9ff..d7365cbfd0 100644 --- a/test/pc/e2e/analyzer/video/default_video_quality_analyzer.h +++ b/test/pc/e2e/analyzer/video/default_video_quality_analyzer.h @@ -243,6 +243,7 @@ class DefaultVideoQualityAnalyzer : public VideoQualityAnalyzerInterface { } void MarkDropped(size_t peer) { receiver_stats_[peer].dropped = true; } + bool IsDropped(size_t peer) const; void SetPrevFrameRenderedTime(size_t peer, webrtc::Timestamp time) { receiver_stats_[peer].prev_frame_rendered_time = time;