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 2886fa89c0..a2fbdbe899 100644 --- a/test/pc/e2e/analyzer/video/default_video_quality_analyzer.cc +++ b/test/pc/e2e/analyzer/video/default_video_quality_analyzer.cc @@ -45,9 +45,28 @@ void LogFrameCounters(const std::string& name, const FrameCounters& counters) { RTC_LOG(INFO) << "[" << name << "] Dropped : " << counters.dropped; } +absl::string_view ToString(FrameDropPhase phase) { + switch (phase) { + case FrameDropPhase::kBeforeEncoder: + return "kBeforeEncoder"; + case FrameDropPhase::kByEncoder: + return "kByEncoder"; + case FrameDropPhase::kTransport: + return "kTransport"; + case FrameDropPhase::kAfterDecoder: + return "kAfterDecoder"; + case FrameDropPhase::kLastValue: + RTC_CHECK(false) << "FrameDropPhase::kLastValue mustn't be used"; + } +} + void LogStreamInternalStats(const std::string& name, const StreamStats& stats, Timestamp start_time) { + for (const auto& entry : stats.dropped_by_phase) { + RTC_LOG(INFO) << "[" << name << "] Dropped at " << ToString(entry.first) + << ": " << entry.second; + } RTC_LOG(INFO) << "[" << name << "] Dropped by encoder : " << stats.dropped_by_encoder; RTC_LOG(INFO) << "[" << name << "] Dropped before encoder : " diff --git a/test/pc/e2e/analyzer/video/default_video_quality_analyzer_frames_comparator.cc b/test/pc/e2e/analyzer/video/default_video_quality_analyzer_frames_comparator.cc index b4aac71a88..ceabf09650 100644 --- a/test/pc/e2e/analyzer/video/default_video_quality_analyzer_frames_comparator.cc +++ b/test/pc/e2e/analyzer/video/default_video_quality_analyzer_frames_comparator.cc @@ -405,6 +405,21 @@ void DefaultVideoQualityAnalyzerFramesComparator::ProcessComparison( stats->ssim.AddSample(StatsSample(ssim, frame_stats.received_time)); } + // Compute dropped phase for dropped frame + if (comparison.type == FrameComparisonType::kDroppedFrame) { + webrtc_pc_e2e::FrameDropPhase dropped_phase; + if (frame_stats.decode_end_time.IsFinite()) { + dropped_phase = webrtc_pc_e2e::FrameDropPhase::kAfterDecoder; + } else if (frame_stats.encoded_time.IsFinite()) { + dropped_phase = webrtc_pc_e2e::FrameDropPhase::kTransport; + } else if (frame_stats.pre_encode_time.IsFinite()) { + dropped_phase = webrtc_pc_e2e::FrameDropPhase::kByEncoder; + } else { + dropped_phase = webrtc_pc_e2e::FrameDropPhase::kBeforeEncoder; + } + stats->dropped_by_phase[dropped_phase]++; + } + if (frame_stats.encoded_time.IsFinite()) { stats->encode_time_ms.AddSample(StatsSample( (frame_stats.encoded_time - frame_stats.pre_encode_time).ms(), diff --git a/test/pc/e2e/analyzer/video/default_video_quality_analyzer_shared_objects.cc b/test/pc/e2e/analyzer/video/default_video_quality_analyzer_shared_objects.cc index 1149ac1fdc..f40f5e0407 100644 --- a/test/pc/e2e/analyzer/video/default_video_quality_analyzer_shared_objects.cc +++ b/test/pc/e2e/analyzer/video/default_video_quality_analyzer_shared_objects.cc @@ -38,6 +38,14 @@ double RateCounter::GetEventsPerSecond() const { (event_last_time_ - event_first_time_).us() * kMicrosPerSecond; } +StreamStats::StreamStats(Timestamp stream_started_time) + : stream_started_time(stream_started_time) { + for (int i = static_cast(FrameDropPhase::kBeforeEncoder); + i < static_cast(FrameDropPhase::kLastValue); ++i) { + dropped_by_phase.emplace(static_cast(i), 0); + } +} + std::string StatsKey::ToString() const { rtc::StringBuilder out; out << stream_label << "_" << sender << "_" << receiver; diff --git a/test/pc/e2e/analyzer/video/default_video_quality_analyzer_shared_objects.h b/test/pc/e2e/analyzer/video/default_video_quality_analyzer_shared_objects.h index 4c90961a6f..278c9babca 100644 --- a/test/pc/e2e/analyzer/video/default_video_quality_analyzer_shared_objects.h +++ b/test/pc/e2e/analyzer/video/default_video_quality_analyzer_shared_objects.h @@ -11,6 +11,7 @@ #ifndef TEST_PC_E2E_ANALYZER_VIDEO_DEFAULT_VIDEO_QUALITY_ANALYZER_SHARED_OBJECTS_H_ #define TEST_PC_E2E_ANALYZER_VIDEO_DEFAULT_VIDEO_QUALITY_ANALYZER_SHARED_OBJECTS_H_ +#include #include #include #include @@ -78,9 +79,19 @@ struct StreamCodecInfo { Timestamp switched_from_at = Timestamp::PlusInfinity(); }; +// Represents phases where video frame can be dropped and such drop will be +// detected by analyzer. +enum class FrameDropPhase : int { + kBeforeEncoder, + kByEncoder, + kTransport, + kAfterDecoder, + // kLastValue must be the last value in this enumeration. + kLastValue +}; + struct StreamStats { - explicit StreamStats(Timestamp stream_started_time) - : stream_started_time(stream_started_time) {} + explicit StreamStats(Timestamp stream_started_time); // The time when the first frame of this stream was captured. Timestamp stream_started_time; @@ -117,6 +128,8 @@ struct StreamStats { int64_t total_encoded_images_payload = 0; int64_t dropped_by_encoder = 0; int64_t dropped_before_encoder = 0; + // Counters on which phase how many frames were dropped. + std::map dropped_by_phase; // Vector of encoders used for this stream by sending client. std::vector encoders;