xref: /aosp_15_r20/external/webrtc/test/pc/e2e/analyzer/video/video_quality_metrics_reporter.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "test/pc/e2e/analyzer/video/video_quality_metrics_reporter.h"
12 
13 #include <map>
14 #include <string>
15 
16 #include "api/stats/rtc_stats.h"
17 #include "api/stats/rtcstats_objects.h"
18 #include "api/test/metrics/metric.h"
19 #include "api/units/data_rate.h"
20 #include "api/units/time_delta.h"
21 #include "api/units/timestamp.h"
22 #include "rtc_base/checks.h"
23 #include "test/pc/e2e/metric_metadata_keys.h"
24 
25 namespace webrtc {
26 namespace webrtc_pc_e2e {
27 namespace {
28 
29 using ::webrtc::test::ImprovementDirection;
30 using ::webrtc::test::Unit;
31 using ::webrtc::webrtc_pc_e2e::MetricMetadataKey;
32 
BytesPerSecondToKbps(const SamplesStatsCounter & counter)33 SamplesStatsCounter BytesPerSecondToKbps(const SamplesStatsCounter& counter) {
34   return counter * 0.008;
35 }
36 
37 }  // namespace
38 
VideoQualityMetricsReporter(Clock * const clock,test::MetricsLogger * const metrics_logger)39 VideoQualityMetricsReporter::VideoQualityMetricsReporter(
40     Clock* const clock,
41     test::MetricsLogger* const metrics_logger)
42     : clock_(clock), metrics_logger_(metrics_logger) {
43   RTC_CHECK(metrics_logger_);
44 }
45 
Start(absl::string_view test_case_name,const TrackIdStreamInfoMap *)46 void VideoQualityMetricsReporter::Start(
47     absl::string_view test_case_name,
48     const TrackIdStreamInfoMap* /*reporter_helper*/) {
49   test_case_name_ = std::string(test_case_name);
50   start_time_ = Now();
51 }
52 
OnStatsReports(absl::string_view pc_label,const rtc::scoped_refptr<const RTCStatsReport> & report)53 void VideoQualityMetricsReporter::OnStatsReports(
54     absl::string_view pc_label,
55     const rtc::scoped_refptr<const RTCStatsReport>& report) {
56   RTC_CHECK(start_time_)
57       << "Please invoke Start(...) method before calling OnStatsReports(...)";
58 
59   auto transport_stats = report->GetStatsOfType<RTCTransportStats>();
60   if (transport_stats.size() == 0u ||
61       !transport_stats[0]->selected_candidate_pair_id.is_defined()) {
62     return;
63   }
64   RTC_DCHECK_EQ(transport_stats.size(), 1);
65   std::string selected_ice_id =
66       transport_stats[0]->selected_candidate_pair_id.ValueToString();
67   // Use the selected ICE candidate pair ID to get the appropriate ICE stats.
68   const RTCIceCandidatePairStats ice_candidate_pair_stats =
69       report->Get(selected_ice_id)->cast_to<const RTCIceCandidatePairStats>();
70 
71   auto outbound_rtp_stats = report->GetStatsOfType<RTCOutboundRTPStreamStats>();
72   StatsSample sample;
73   for (auto& s : outbound_rtp_stats) {
74     if (!s->kind.is_defined()) {
75       continue;
76     }
77     if (!(*s->kind == RTCMediaStreamTrackKind::kVideo)) {
78       continue;
79     }
80     if (s->timestamp_us() > sample.sample_time.us()) {
81       sample.sample_time = Timestamp::Micros(s->timestamp_us());
82     }
83     sample.retransmitted_bytes_sent +=
84         DataSize::Bytes(s->retransmitted_bytes_sent.ValueOrDefault(0ul));
85     sample.bytes_sent += DataSize::Bytes(s->bytes_sent.ValueOrDefault(0ul));
86     sample.header_bytes_sent +=
87         DataSize::Bytes(s->header_bytes_sent.ValueOrDefault(0ul));
88   }
89 
90   MutexLock lock(&video_bwe_stats_lock_);
91   VideoBweStats& video_bwe_stats = video_bwe_stats_[std::string(pc_label)];
92   if (ice_candidate_pair_stats.available_outgoing_bitrate.is_defined()) {
93     video_bwe_stats.available_send_bandwidth.AddSample(
94         DataRate::BitsPerSec(
95             *ice_candidate_pair_stats.available_outgoing_bitrate)
96             .bytes_per_sec());
97   }
98 
99   StatsSample prev_sample = last_stats_sample_[std::string(pc_label)];
100   if (prev_sample.sample_time.IsZero()) {
101     prev_sample.sample_time = start_time_.value();
102   }
103   last_stats_sample_[std::string(pc_label)] = sample;
104 
105   TimeDelta time_between_samples = sample.sample_time - prev_sample.sample_time;
106   if (time_between_samples.IsZero()) {
107     return;
108   }
109 
110   DataRate retransmission_bitrate =
111       (sample.retransmitted_bytes_sent - prev_sample.retransmitted_bytes_sent) /
112       time_between_samples;
113   video_bwe_stats.retransmission_bitrate.AddSample(
114       retransmission_bitrate.bytes_per_sec());
115   DataRate transmission_bitrate =
116       (sample.bytes_sent + sample.header_bytes_sent - prev_sample.bytes_sent -
117        prev_sample.header_bytes_sent) /
118       time_between_samples;
119   video_bwe_stats.transmission_bitrate.AddSample(
120       transmission_bitrate.bytes_per_sec());
121 }
122 
StopAndReportResults()123 void VideoQualityMetricsReporter::StopAndReportResults() {
124   MutexLock video_bwemutex_(&video_bwe_stats_lock_);
125   for (const auto& item : video_bwe_stats_) {
126     ReportVideoBweResults(item.first, item.second);
127   }
128 }
129 
GetTestCaseName(const std::string & peer_name) const130 std::string VideoQualityMetricsReporter::GetTestCaseName(
131     const std::string& peer_name) const {
132   return test_case_name_ + "/" + peer_name;
133 }
134 
ReportVideoBweResults(const std::string & peer_name,const VideoBweStats & video_bwe_stats)135 void VideoQualityMetricsReporter::ReportVideoBweResults(
136     const std::string& peer_name,
137     const VideoBweStats& video_bwe_stats) {
138   std::string test_case_name = GetTestCaseName(peer_name);
139   std::map<std::string, std::string> metric_metadata{
140       {MetricMetadataKey::kPeerMetadataKey, peer_name}};
141 
142   metrics_logger_->LogMetric(
143       "available_send_bandwidth", test_case_name,
144       BytesPerSecondToKbps(video_bwe_stats.available_send_bandwidth),
145       Unit::kKilobitsPerSecond, ImprovementDirection::kNeitherIsBetter,
146       metric_metadata);
147   metrics_logger_->LogMetric(
148       "transmission_bitrate", test_case_name,
149       BytesPerSecondToKbps(video_bwe_stats.transmission_bitrate),
150       Unit::kKilobitsPerSecond, ImprovementDirection::kNeitherIsBetter,
151       metric_metadata);
152   metrics_logger_->LogMetric(
153       "retransmission_bitrate", test_case_name,
154       BytesPerSecondToKbps(video_bwe_stats.retransmission_bitrate),
155       Unit::kKilobitsPerSecond, ImprovementDirection::kNeitherIsBetter,
156       metric_metadata);
157 }
158 
159 }  // namespace webrtc_pc_e2e
160 }  // namespace webrtc
161