1 /*
2  *  Copyright (c) 2018 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 "modules/audio_processing/aec3/api_call_jitter_metrics.h"
12 
13 #include <algorithm>
14 #include <limits>
15 
16 #include "modules/audio_processing/aec3/aec3_common.h"
17 #include "system_wrappers/include/metrics.h"
18 
19 namespace webrtc {
20 namespace {
21 
TimeToReportMetrics(int frames_since_last_report)22 bool TimeToReportMetrics(int frames_since_last_report) {
23   constexpr int kNumFramesPerSecond = 100;
24   constexpr int kReportingIntervalFrames = 10 * kNumFramesPerSecond;
25   return frames_since_last_report == kReportingIntervalFrames;
26 }
27 
28 }  // namespace
29 
Jitter()30 ApiCallJitterMetrics::Jitter::Jitter()
31     : max_(0), min_(std::numeric_limits<int>::max()) {}
32 
Update(int num_api_calls_in_a_row)33 void ApiCallJitterMetrics::Jitter::Update(int num_api_calls_in_a_row) {
34   min_ = std::min(min_, num_api_calls_in_a_row);
35   max_ = std::max(max_, num_api_calls_in_a_row);
36 }
37 
Reset()38 void ApiCallJitterMetrics::Jitter::Reset() {
39   min_ = std::numeric_limits<int>::max();
40   max_ = 0;
41 }
42 
Reset()43 void ApiCallJitterMetrics::Reset() {
44   render_jitter_.Reset();
45   capture_jitter_.Reset();
46   num_api_calls_in_a_row_ = 0;
47   frames_since_last_report_ = 0;
48   last_call_was_render_ = false;
49   proper_call_observed_ = false;
50 }
51 
ReportRenderCall()52 void ApiCallJitterMetrics::ReportRenderCall() {
53   if (!last_call_was_render_) {
54     // If the previous call was a capture and a proper call has been observed
55     // (containing both render and capture data), storing the last number of
56     // capture calls into the metrics.
57     if (proper_call_observed_) {
58       capture_jitter_.Update(num_api_calls_in_a_row_);
59     }
60 
61     // Reset the call counter to start counting render calls.
62     num_api_calls_in_a_row_ = 0;
63   }
64   ++num_api_calls_in_a_row_;
65   last_call_was_render_ = true;
66 }
67 
ReportCaptureCall()68 void ApiCallJitterMetrics::ReportCaptureCall() {
69   if (last_call_was_render_) {
70     // If the previous call was a render and a proper call has been observed
71     // (containing both render and capture data), storing the last number of
72     // render calls into the metrics.
73     if (proper_call_observed_) {
74       render_jitter_.Update(num_api_calls_in_a_row_);
75     }
76     // Reset the call counter to start counting capture calls.
77     num_api_calls_in_a_row_ = 0;
78 
79     // If this statement is reached, at least one render and one capture call
80     // have been observed.
81     proper_call_observed_ = true;
82   }
83   ++num_api_calls_in_a_row_;
84   last_call_was_render_ = false;
85 
86   // Only report and update jitter metrics for when a proper call, containing
87   // both render and capture data, has been observed.
88   if (proper_call_observed_ &&
89       TimeToReportMetrics(++frames_since_last_report_)) {
90     // Report jitter, where the base basic unit is frames.
91     constexpr int kMaxJitterToReport = 50;
92 
93     // Report max and min jitter for render and capture, in units of 20 ms.
94     RTC_HISTOGRAM_COUNTS_LINEAR(
95         "WebRTC.Audio.EchoCanceller.MaxRenderJitter",
96         std::min(kMaxJitterToReport, render_jitter().max()), 1,
97         kMaxJitterToReport, kMaxJitterToReport);
98     RTC_HISTOGRAM_COUNTS_LINEAR(
99         "WebRTC.Audio.EchoCanceller.MinRenderJitter",
100         std::min(kMaxJitterToReport, render_jitter().min()), 1,
101         kMaxJitterToReport, kMaxJitterToReport);
102 
103     RTC_HISTOGRAM_COUNTS_LINEAR(
104         "WebRTC.Audio.EchoCanceller.MaxCaptureJitter",
105         std::min(kMaxJitterToReport, capture_jitter().max()), 1,
106         kMaxJitterToReport, kMaxJitterToReport);
107     RTC_HISTOGRAM_COUNTS_LINEAR(
108         "WebRTC.Audio.EchoCanceller.MinCaptureJitter",
109         std::min(kMaxJitterToReport, capture_jitter().min()), 1,
110         kMaxJitterToReport, kMaxJitterToReport);
111 
112     frames_since_last_report_ = 0;
113     Reset();
114   }
115 }
116 
WillReportMetricsAtNextCapture() const117 bool ApiCallJitterMetrics::WillReportMetricsAtNextCapture() const {
118   return TimeToReportMetrics(frames_since_last_report_ + 1);
119 }
120 
121 }  // namespace webrtc
122