• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "rtc_base/logging.h"
16 
17 namespace webrtc {
18 namespace webrtc_pc_e2e {
19 
Start(std::string test_case_name,TrackIdStreamInfoMap * analyzer_helper)20 void DefaultAudioQualityAnalyzer::Start(std::string test_case_name,
21                                         TrackIdStreamInfoMap* analyzer_helper) {
22   test_case_name_ = std::move(test_case_name);
23   analyzer_helper_ = analyzer_helper;
24 }
25 
OnStatsReports(absl::string_view pc_label,const rtc::scoped_refptr<const RTCStatsReport> & report)26 void DefaultAudioQualityAnalyzer::OnStatsReports(
27     absl::string_view pc_label,
28     const rtc::scoped_refptr<const RTCStatsReport>& report) {
29   // TODO(https://crbug.com/webrtc/11683): use "inbound-rtp" instead of "track"
30   // stats when required audio metrics moved there
31   auto stats = report->GetStatsOfType<RTCMediaStreamTrackStats>();
32 
33   for (auto& stat : stats) {
34     if (!stat->kind.is_defined() ||
35         !(*stat->kind == RTCMediaStreamTrackKind::kAudio) ||
36         !*stat->remote_source) {
37       continue;
38     }
39 
40     StatsSample sample;
41     sample.total_samples_received =
42         stat->total_samples_received.ValueOrDefault(0ul);
43     sample.concealed_samples = stat->concealed_samples.ValueOrDefault(0ul);
44     sample.removed_samples_for_acceleration =
45         stat->removed_samples_for_acceleration.ValueOrDefault(0ul);
46     sample.inserted_samples_for_deceleration =
47         stat->inserted_samples_for_deceleration.ValueOrDefault(0ul);
48     sample.silent_concealed_samples =
49         stat->silent_concealed_samples.ValueOrDefault(0ul);
50     sample.jitter_buffer_delay =
51         TimeDelta::Seconds(stat->jitter_buffer_delay.ValueOrDefault(0.));
52     sample.jitter_buffer_target_delay =
53         TimeDelta::Seconds(stat->jitter_buffer_target_delay.ValueOrDefault(0.));
54     sample.jitter_buffer_emitted_count =
55         stat->jitter_buffer_emitted_count.ValueOrDefault(0ul);
56 
57     const std::string stream_label = std::string(
58         analyzer_helper_->GetStreamLabelFromTrackId(*stat->track_identifier));
59 
60     MutexLock lock(&lock_);
61     StatsSample prev_sample = last_stats_sample_[stream_label];
62     RTC_CHECK_GE(sample.total_samples_received,
63                  prev_sample.total_samples_received);
64     double total_samples_diff = static_cast<double>(
65         sample.total_samples_received - prev_sample.total_samples_received);
66     if (total_samples_diff == 0) {
67       return;
68     }
69 
70     AudioStreamStats& audio_stream_stats = streams_stats_[stream_label];
71     audio_stream_stats.expand_rate.AddSample(
72         (sample.concealed_samples - prev_sample.concealed_samples) /
73         total_samples_diff);
74     audio_stream_stats.accelerate_rate.AddSample(
75         (sample.removed_samples_for_acceleration -
76          prev_sample.removed_samples_for_acceleration) /
77         total_samples_diff);
78     audio_stream_stats.preemptive_rate.AddSample(
79         (sample.inserted_samples_for_deceleration -
80          prev_sample.inserted_samples_for_deceleration) /
81         total_samples_diff);
82 
83     int64_t speech_concealed_samples =
84         sample.concealed_samples - sample.silent_concealed_samples;
85     int64_t prev_speech_concealed_samples =
86         prev_sample.concealed_samples - prev_sample.silent_concealed_samples;
87     audio_stream_stats.speech_expand_rate.AddSample(
88         (speech_concealed_samples - prev_speech_concealed_samples) /
89         total_samples_diff);
90 
91     int64_t jitter_buffer_emitted_count_diff =
92         sample.jitter_buffer_emitted_count -
93         prev_sample.jitter_buffer_emitted_count;
94     if (jitter_buffer_emitted_count_diff > 0) {
95       TimeDelta jitter_buffer_delay_diff =
96           sample.jitter_buffer_delay - prev_sample.jitter_buffer_delay;
97       TimeDelta jitter_buffer_target_delay_diff =
98           sample.jitter_buffer_target_delay -
99           prev_sample.jitter_buffer_target_delay;
100       audio_stream_stats.average_jitter_buffer_delay_ms.AddSample(
101           jitter_buffer_delay_diff.ms<double>() /
102           jitter_buffer_emitted_count_diff);
103       audio_stream_stats.preferred_buffer_size_ms.AddSample(
104           jitter_buffer_target_delay_diff.ms<double>() /
105           jitter_buffer_emitted_count_diff);
106     }
107 
108     last_stats_sample_[stream_label] = sample;
109   }
110 }
111 
GetTestCaseName(const std::string & stream_label) const112 std::string DefaultAudioQualityAnalyzer::GetTestCaseName(
113     const std::string& stream_label) const {
114   return test_case_name_ + "/" + stream_label;
115 }
116 
Stop()117 void DefaultAudioQualityAnalyzer::Stop() {
118   using ::webrtc::test::ImproveDirection;
119   MutexLock lock(&lock_);
120   for (auto& item : streams_stats_) {
121     ReportResult("expand_rate", item.first, item.second.expand_rate, "unitless",
122                  ImproveDirection::kSmallerIsBetter);
123     ReportResult("accelerate_rate", item.first, item.second.accelerate_rate,
124                  "unitless", ImproveDirection::kSmallerIsBetter);
125     ReportResult("preemptive_rate", item.first, item.second.preemptive_rate,
126                  "unitless", ImproveDirection::kSmallerIsBetter);
127     ReportResult("speech_expand_rate", item.first,
128                  item.second.speech_expand_rate, "unitless",
129                  ImproveDirection::kSmallerIsBetter);
130     ReportResult("average_jitter_buffer_delay_ms", item.first,
131                  item.second.average_jitter_buffer_delay_ms, "ms",
132                  ImproveDirection::kNone);
133     ReportResult("preferred_buffer_size_ms", item.first,
134                  item.second.preferred_buffer_size_ms, "ms",
135                  ImproveDirection::kNone);
136   }
137 }
138 
139 std::map<std::string, AudioStreamStats>
GetAudioStreamsStats() const140 DefaultAudioQualityAnalyzer::GetAudioStreamsStats() const {
141   MutexLock lock(&lock_);
142   return streams_stats_;
143 }
144 
ReportResult(const std::string & metric_name,const std::string & stream_label,const SamplesStatsCounter & counter,const std::string & unit,webrtc::test::ImproveDirection improve_direction) const145 void DefaultAudioQualityAnalyzer::ReportResult(
146     const std::string& metric_name,
147     const std::string& stream_label,
148     const SamplesStatsCounter& counter,
149     const std::string& unit,
150     webrtc::test::ImproveDirection improve_direction) const {
151   test::PrintResultMeanAndError(
152       metric_name, /*modifier=*/"", GetTestCaseName(stream_label),
153       counter.IsEmpty() ? 0 : counter.GetAverage(),
154       counter.IsEmpty() ? 0 : counter.GetStandardDeviation(), unit,
155       /*important=*/false, improve_direction);
156 }
157 
158 }  // namespace webrtc_pc_e2e
159 }  // namespace webrtc
160