diff --git a/test/pc/e2e/analyzer/video/BUILD.gn b/test/pc/e2e/analyzer/video/BUILD.gn index 47a3721ea2..cbb4c078f3 100644 --- a/test/pc/e2e/analyzer/video/BUILD.gn +++ b/test/pc/e2e/analyzer/video/BUILD.gn @@ -231,6 +231,7 @@ rtc_library("default_video_quality_analyzer_internal") { "../..:metric_metadata_keys", "../../../../../api:array_view", "../../../../../api:scoped_refptr", + "../../../../../api/numerics", "../../../../../api/units:data_size", "../../../../../api/units:timestamp", "../../../../../api/video:video_frame", diff --git a/test/pc/e2e/analyzer/video/default_video_quality_analyzer_frame_in_flight.cc b/test/pc/e2e/analyzer/video/default_video_quality_analyzer_frame_in_flight.cc index 5f08b452fc..24f829e089 100644 --- a/test/pc/e2e/analyzer/video/default_video_quality_analyzer_frame_in_flight.cc +++ b/test/pc/e2e/analyzer/video/default_video_quality_analyzer_frame_in_flight.cc @@ -94,7 +94,8 @@ void FrameInFlight::OnFrameEncoded(webrtc::Timestamp time, frame_type_ = frame_type; encoded_image_size_ = encoded_image_size; target_encode_bitrate_ += target_encode_bitrate; - qp_values_.push_back(qp); + qp_values_.AddSample(SamplesStatsCounter::StatsSample{ + .value = static_cast(qp), .time = time}); // Update used encoder info. If simulcast/SVC is used, this method can // be called multiple times, in such case we should preserve the value // of `used_encoder_.switched_on_at` from the first invocation as the @@ -184,8 +185,7 @@ FrameStats FrameInFlight::GetStatsForPeer(size_t peer) const { stats.encoded_frame_type = frame_type_; stats.encoded_image_size = encoded_image_size_; stats.used_encoder = used_encoder_; - stats.qp_values.insert(stats.qp_values.begin(), qp_values_.begin(), - qp_values_.end()); + stats.qp_values = qp_values_; absl::optional receiver_stats = MaybeGetValue(receiver_stats_, peer); diff --git a/test/pc/e2e/analyzer/video/default_video_quality_analyzer_frame_in_flight.h b/test/pc/e2e/analyzer/video/default_video_quality_analyzer_frame_in_flight.h index 26785bdc97..7ee910effe 100644 --- a/test/pc/e2e/analyzer/video/default_video_quality_analyzer_frame_in_flight.h +++ b/test/pc/e2e/analyzer/video/default_video_quality_analyzer_frame_in_flight.h @@ -17,6 +17,7 @@ #include #include "absl/types/optional.h" +#include "api/numerics/samples_stats_counter.h" #include "api/units/data_size.h" #include "api/units/timestamp.h" #include "api/video/video_frame.h" @@ -153,7 +154,7 @@ class FrameInFlight { VideoFrameType frame_type_ = VideoFrameType::kEmptyFrame; DataSize encoded_image_size_ = DataSize::Bytes(0); uint32_t target_encode_bitrate_ = 0; - std::vector qp_values_; + SamplesStatsCounter qp_values_; // Can be not set if frame was dropped by encoder. absl::optional used_encoder_ = absl::nullopt; // Map from the receiver peer's index to frame stats for that peer. 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 400309653a..77418b7e5d 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 @@ -459,8 +459,10 @@ void DefaultVideoQualityAnalyzerFramesComparator::ProcessComparison( frame_stats.encoded_image_size.bytes(); stats->target_encode_bitrate.AddSample(StatsSample( frame_stats.target_encode_bitrate, frame_stats.encoded_time, metadata)); - for (const int qp : frame_stats.qp_values) { - stats->qp.AddSample(StatsSample(qp, frame_stats.encoded_time, metadata)); + for (SamplesStatsCounter::StatsSample qp : + frame_stats.qp_values.GetTimedSamples()) { + qp.metadata = metadata; + stats->qp.AddSample(std::move(qp)); } // Stats sliced on encoded frame type. diff --git a/test/pc/e2e/analyzer/video/default_video_quality_analyzer_frames_comparator_test.cc b/test/pc/e2e/analyzer/video/default_video_quality_analyzer_frames_comparator_test.cc index 519eee6d07..2cfb0c3d79 100644 --- a/test/pc/e2e/analyzer/video/default_video_quality_analyzer_frames_comparator_test.cc +++ b/test/pc/e2e/analyzer/video/default_video_quality_analyzer_frames_comparator_test.cc @@ -108,6 +108,16 @@ FrameStats ShiftStatsOn(const FrameStats& stats, TimeDelta delta) { return frame_stats; } +SamplesStatsCounter StatsCounter( + const std::vector>& samples) { + SamplesStatsCounter counter; + for (const std::pair& sample : samples) { + counter.AddSample(SamplesStatsCounter::StatsSample{.value = sample.first, + .time = sample.second}); + } + return counter; +} + double GetFirstOrDie(const SamplesStatsCounter& counter) { EXPECT_FALSE(counter.IsEmpty()) << "Counter has to be not empty"; return counter.GetSamples()[0]; @@ -478,7 +488,8 @@ TEST(DefaultVideoQualityAnalyzerFramesComparatorTest, frame_stats.encoded_frame_type = VideoFrameType::kVideoFrameKey; frame_stats.encoded_image_size = DataSize::Bytes(1000); frame_stats.target_encode_bitrate = 2000; - frame_stats.qp_values = {5, 5}; + frame_stats.qp_values = StatsCounter( + /*samples=*/{{5, Timestamp::Seconds(1)}, {5, Timestamp::Seconds(2)}}); comparator.Start(/*max_threads_count=*/1); comparator.EnsureStatsForStream(stream, sender, /*peers_count=*/2, @@ -548,7 +559,8 @@ TEST(DefaultVideoQualityAnalyzerFramesComparatorTest, frame_stats.encoded_frame_type = VideoFrameType::kVideoFrameDelta; frame_stats.encoded_image_size = DataSize::Bytes(1000); frame_stats.target_encode_bitrate = 2000; - frame_stats.qp_values = {5, 5}; + frame_stats.qp_values = StatsCounter( + /*samples=*/{{5, Timestamp::Seconds(1)}, {5, Timestamp::Seconds(2)}}); comparator.Start(/*max_threads_count=*/1); comparator.EnsureStatsForStream(stream, sender, /*peers_count=*/2, @@ -618,7 +630,8 @@ TEST(DefaultVideoQualityAnalyzerFramesComparatorTest, frame_stats.encoded_frame_type = VideoFrameType::kVideoFrameKey; frame_stats.encoded_image_size = DataSize::Bytes(1000); frame_stats.target_encode_bitrate = 2000; - frame_stats.qp_values = {5, 5}; + frame_stats.qp_values = StatsCounter( + /*samples=*/{{5, Timestamp::Seconds(1)}, {5, Timestamp::Seconds(2)}}); // Frame pre decoded frame_stats.pre_decoded_frame_type = VideoFrameType::kVideoFrameKey; frame_stats.pre_decoded_image_size = DataSize::Bytes(500); @@ -693,7 +706,8 @@ TEST(DefaultVideoQualityAnalyzerFramesComparatorTest, frame_stats.encoded_frame_type = VideoFrameType::kVideoFrameKey; frame_stats.encoded_image_size = DataSize::Bytes(1000); frame_stats.target_encode_bitrate = 2000; - frame_stats.qp_values = {5, 5}; + frame_stats.qp_values = StatsCounter( + /*samples=*/{{5, Timestamp::Seconds(1)}, {5, Timestamp::Seconds(2)}}); // Frame pre decoded frame_stats.pre_decoded_frame_type = VideoFrameType::kVideoFrameKey; frame_stats.pre_decoded_image_size = DataSize::Bytes(500); @@ -776,7 +790,8 @@ TEST(DefaultVideoQualityAnalyzerFramesComparatorTest, frame_stats.encoded_frame_type = VideoFrameType::kVideoFrameKey; frame_stats.encoded_image_size = DataSize::Bytes(1000); frame_stats.target_encode_bitrate = 2000; - frame_stats.qp_values = {5, 5}; + frame_stats.qp_values = StatsCounter( + /*samples=*/{{5, Timestamp::Seconds(1)}, {5, Timestamp::Seconds(2)}}); // Frame pre decoded frame_stats.pre_decoded_frame_type = VideoFrameType::kVideoFrameKey; frame_stats.pre_decoded_image_size = DataSize::Bytes(500); @@ -977,7 +992,8 @@ TEST(DefaultVideoQualityAnalyzerFramesComparatorTest, frame_stats.encoded_frame_type = VideoFrameType::kVideoFrameKey; frame_stats.encoded_image_size = DataSize::Bytes(1000); frame_stats.target_encode_bitrate = 2000; - frame_stats.qp_values = {5, 5}; + frame_stats.qp_values = StatsCounter( + /*samples=*/{{5, Timestamp::Seconds(1)}, {5, Timestamp::Seconds(2)}}); comparator.Start(/*max_threads_count=*/1); comparator.EnsureStatsForStream(stream, sender, /*peers_count=*/2, @@ -1047,7 +1063,8 @@ TEST(DefaultVideoQualityAnalyzerFramesComparatorTest, frame_stats.encoded_frame_type = VideoFrameType::kVideoFrameDelta; frame_stats.encoded_image_size = DataSize::Bytes(1000); frame_stats.target_encode_bitrate = 2000; - frame_stats.qp_values = {5, 5}; + frame_stats.qp_values = StatsCounter( + /*samples=*/{{5, Timestamp::Seconds(1)}, {5, Timestamp::Seconds(2)}}); comparator.Start(/*max_threads_count=*/1); comparator.EnsureStatsForStream(stream, sender, /*peers_count=*/2, @@ -1193,7 +1210,8 @@ TEST(DefaultVideoQualityAnalyzerFramesComparatorTest, frame_stats.encoded_frame_type = VideoFrameType::kVideoFrameKey; frame_stats.encoded_image_size = DataSize::Bytes(1000); frame_stats.target_encode_bitrate = 2000; - frame_stats.qp_values = {5, 5}; + frame_stats.qp_values = StatsCounter( + /*samples=*/{{5, Timestamp::Seconds(1)}, {5, Timestamp::Seconds(2)}}); // Frame pre decoded frame_stats.pre_decoded_frame_type = VideoFrameType::kVideoFrameKey; frame_stats.pre_decoded_image_size = DataSize::Bytes(500); @@ -1275,7 +1293,8 @@ TEST(DefaultVideoQualityAnalyzerFramesComparatorTest, frame_stats.encoded_frame_type = VideoFrameType::kVideoFrameKey; frame_stats.encoded_image_size = DataSize::Bytes(1000); frame_stats.target_encode_bitrate = 2000; - frame_stats.qp_values = {5, 5}; + frame_stats.qp_values = StatsCounter( + /*samples=*/{{5, Timestamp::Seconds(1)}, {5, Timestamp::Seconds(2)}}); // Frame pre decoded frame_stats.pre_decoded_frame_type = VideoFrameType::kVideoFrameKey; frame_stats.pre_decoded_image_size = DataSize::Bytes(500); @@ -1359,7 +1378,8 @@ TEST(DefaultVideoQualityAnalyzerFramesComparatorTest, frame_stats.encoded_frame_type = VideoFrameType::kVideoFrameKey; frame_stats.encoded_image_size = DataSize::Bytes(1000); frame_stats.target_encode_bitrate = 2000; - frame_stats.qp_values = {5, 5}; + frame_stats.qp_values = StatsCounter( + /*samples=*/{{5, Timestamp::Seconds(1)}, {5, Timestamp::Seconds(2)}}); // Frame pre decoded frame_stats.pre_decoded_frame_type = VideoFrameType::kVideoFrameKey; frame_stats.pre_decoded_image_size = DataSize::Bytes(500); @@ -1444,7 +1464,8 @@ TEST(DefaultVideoQualityAnalyzerFramesComparatorTest, AllStatsHaveMetadataSet) { frame_stats.encoded_frame_type = VideoFrameType::kVideoFrameKey; frame_stats.encoded_image_size = DataSize::Bytes(1000); frame_stats.target_encode_bitrate = 2000; - frame_stats.qp_values = {5, 5}; + frame_stats.qp_values = StatsCounter( + /*samples=*/{{5, Timestamp::Seconds(1)}, {5, Timestamp::Seconds(2)}}); // Frame pre decoded frame_stats.pre_decoded_frame_type = VideoFrameType::kVideoFrameKey; frame_stats.pre_decoded_image_size = DataSize::Bytes(500); diff --git a/test/pc/e2e/analyzer/video/default_video_quality_analyzer_internal_shared_objects.h b/test/pc/e2e/analyzer/video/default_video_quality_analyzer_internal_shared_objects.h index 0b2ad2078b..3e65e2b888 100644 --- a/test/pc/e2e/analyzer/video/default_video_quality_analyzer_internal_shared_objects.h +++ b/test/pc/e2e/analyzer/video/default_video_quality_analyzer_internal_shared_objects.h @@ -17,6 +17,7 @@ #include #include "absl/types/optional.h" +#include "api/numerics/samples_stats_counter.h" #include "api/units/data_size.h" #include "api/units/timestamp.h" #include "api/video/video_frame.h" @@ -66,7 +67,7 @@ struct FrameStats { // There can be multiple qp values for single video frame when simulcast // or SVC is used. In such case multiple EncodedImage's are created by encoder // and each of it will have its own qp value. - std::vector qp_values; + SamplesStatsCounter qp_values; absl::optional decoded_frame_width = absl::nullopt; absl::optional decoded_frame_height = absl::nullopt;