xref: /aosp_15_r20/external/webrtc/test/pc/e2e/analyzer/audio/default_audio_quality_analyzer.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2019 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/audio/default_audio_quality_analyzer.h"
12 
13 #include "api/stats/rtc_stats.h"
14 #include "api/stats/rtcstats_objects.h"
15 #include "api/test/metrics/metric.h"
16 #include "api/test/track_id_stream_info_map.h"
17 #include "rtc_base/checks.h"
18 #include "rtc_base/logging.h"
19 #include "test/pc/e2e/metric_metadata_keys.h"
20 
21 namespace webrtc {
22 namespace webrtc_pc_e2e {
23 
24 using ::webrtc::test::ImprovementDirection;
25 using ::webrtc::test::Unit;
26 
DefaultAudioQualityAnalyzer(test::MetricsLogger * const metrics_logger)27 DefaultAudioQualityAnalyzer::DefaultAudioQualityAnalyzer(
28     test::MetricsLogger* const metrics_logger)
29     : metrics_logger_(metrics_logger) {
30   RTC_CHECK(metrics_logger_);
31 }
32 
Start(std::string test_case_name,TrackIdStreamInfoMap * analyzer_helper)33 void DefaultAudioQualityAnalyzer::Start(std::string test_case_name,
34                                         TrackIdStreamInfoMap* analyzer_helper) {
35   test_case_name_ = std::move(test_case_name);
36   analyzer_helper_ = analyzer_helper;
37 }
38 
OnStatsReports(absl::string_view pc_label,const rtc::scoped_refptr<const RTCStatsReport> & report)39 void DefaultAudioQualityAnalyzer::OnStatsReports(
40     absl::string_view pc_label,
41     const rtc::scoped_refptr<const RTCStatsReport>& report) {
42   auto stats = report->GetStatsOfType<RTCInboundRTPStreamStats>();
43 
44   for (auto& stat : stats) {
45     if (!stat->kind.is_defined() ||
46         !(*stat->kind == RTCMediaStreamTrackKind::kAudio)) {
47       continue;
48     }
49 
50     StatsSample sample;
51     sample.total_samples_received =
52         stat->total_samples_received.ValueOrDefault(0ul);
53     sample.concealed_samples = stat->concealed_samples.ValueOrDefault(0ul);
54     sample.removed_samples_for_acceleration =
55         stat->removed_samples_for_acceleration.ValueOrDefault(0ul);
56     sample.inserted_samples_for_deceleration =
57         stat->inserted_samples_for_deceleration.ValueOrDefault(0ul);
58     sample.silent_concealed_samples =
59         stat->silent_concealed_samples.ValueOrDefault(0ul);
60     sample.jitter_buffer_delay =
61         TimeDelta::Seconds(stat->jitter_buffer_delay.ValueOrDefault(0.));
62     sample.jitter_buffer_target_delay =
63         TimeDelta::Seconds(stat->jitter_buffer_target_delay.ValueOrDefault(0.));
64     sample.jitter_buffer_emitted_count =
65         stat->jitter_buffer_emitted_count.ValueOrDefault(0ul);
66 
67     TrackIdStreamInfoMap::StreamInfo stream_info =
68         analyzer_helper_->GetStreamInfoFromTrackId(*stat->track_identifier);
69 
70     MutexLock lock(&lock_);
71     stream_info_.emplace(stream_info.stream_label, stream_info);
72     StatsSample prev_sample = last_stats_sample_[stream_info.stream_label];
73     RTC_CHECK_GE(sample.total_samples_received,
74                  prev_sample.total_samples_received);
75     double total_samples_diff = static_cast<double>(
76         sample.total_samples_received - prev_sample.total_samples_received);
77     if (total_samples_diff == 0) {
78       return;
79     }
80 
81     AudioStreamStats& audio_stream_stats =
82         streams_stats_[stream_info.stream_label];
83     audio_stream_stats.expand_rate.AddSample(
84         (sample.concealed_samples - prev_sample.concealed_samples) /
85         total_samples_diff);
86     audio_stream_stats.accelerate_rate.AddSample(
87         (sample.removed_samples_for_acceleration -
88          prev_sample.removed_samples_for_acceleration) /
89         total_samples_diff);
90     audio_stream_stats.preemptive_rate.AddSample(
91         (sample.inserted_samples_for_deceleration -
92          prev_sample.inserted_samples_for_deceleration) /
93         total_samples_diff);
94 
95     int64_t speech_concealed_samples =
96         sample.concealed_samples - sample.silent_concealed_samples;
97     int64_t prev_speech_concealed_samples =
98         prev_sample.concealed_samples - prev_sample.silent_concealed_samples;
99     audio_stream_stats.speech_expand_rate.AddSample(
100         (speech_concealed_samples - prev_speech_concealed_samples) /
101         total_samples_diff);
102 
103     int64_t jitter_buffer_emitted_count_diff =
104         sample.jitter_buffer_emitted_count -
105         prev_sample.jitter_buffer_emitted_count;
106     if (jitter_buffer_emitted_count_diff > 0) {
107       TimeDelta jitter_buffer_delay_diff =
108           sample.jitter_buffer_delay - prev_sample.jitter_buffer_delay;
109       TimeDelta jitter_buffer_target_delay_diff =
110           sample.jitter_buffer_target_delay -
111           prev_sample.jitter_buffer_target_delay;
112       audio_stream_stats.average_jitter_buffer_delay_ms.AddSample(
113           jitter_buffer_delay_diff.ms<double>() /
114           jitter_buffer_emitted_count_diff);
115       audio_stream_stats.preferred_buffer_size_ms.AddSample(
116           jitter_buffer_target_delay_diff.ms<double>() /
117           jitter_buffer_emitted_count_diff);
118     }
119 
120     last_stats_sample_[stream_info.stream_label] = sample;
121   }
122 }
123 
GetTestCaseName(const std::string & stream_label) const124 std::string DefaultAudioQualityAnalyzer::GetTestCaseName(
125     const std::string& stream_label) const {
126   return test_case_name_ + "/" + stream_label;
127 }
128 
Stop()129 void DefaultAudioQualityAnalyzer::Stop() {
130   MutexLock lock(&lock_);
131   for (auto& item : streams_stats_) {
132     const TrackIdStreamInfoMap::StreamInfo& stream_info =
133         stream_info_[item.first];
134     std::map<std::string, std::string> metric_metadata{
135         {MetricMetadataKey::kAudioStreamMetadataKey, item.first},
136         {MetricMetadataKey::kPeerMetadataKey, stream_info.receiver_peer},
137         {MetricMetadataKey::kReceiverMetadataKey, stream_info.receiver_peer}};
138 
139     metrics_logger_->LogMetric("expand_rate", GetTestCaseName(item.first),
140                                item.second.expand_rate, Unit::kUnitless,
141                                ImprovementDirection::kSmallerIsBetter,
142                                metric_metadata);
143     metrics_logger_->LogMetric("accelerate_rate", GetTestCaseName(item.first),
144                                item.second.accelerate_rate, Unit::kUnitless,
145                                ImprovementDirection::kSmallerIsBetter,
146                                metric_metadata);
147     metrics_logger_->LogMetric("preemptive_rate", GetTestCaseName(item.first),
148                                item.second.preemptive_rate, Unit::kUnitless,
149                                ImprovementDirection::kSmallerIsBetter,
150                                metric_metadata);
151     metrics_logger_->LogMetric(
152         "speech_expand_rate", GetTestCaseName(item.first),
153         item.second.speech_expand_rate, Unit::kUnitless,
154         ImprovementDirection::kSmallerIsBetter, metric_metadata);
155     metrics_logger_->LogMetric(
156         "average_jitter_buffer_delay_ms", GetTestCaseName(item.first),
157         item.second.average_jitter_buffer_delay_ms, Unit::kMilliseconds,
158         ImprovementDirection::kNeitherIsBetter, metric_metadata);
159     metrics_logger_->LogMetric(
160         "preferred_buffer_size_ms", GetTestCaseName(item.first),
161         item.second.preferred_buffer_size_ms, Unit::kMilliseconds,
162         ImprovementDirection::kNeitherIsBetter, metric_metadata);
163   }
164 }
165 
166 std::map<std::string, AudioStreamStats>
GetAudioStreamsStats() const167 DefaultAudioQualityAnalyzer::GetAudioStreamsStats() const {
168   MutexLock lock(&lock_);
169   return streams_stats_;
170 }
171 
172 }  // namespace webrtc_pc_e2e
173 }  // namespace webrtc
174