Add more Audio Mixer and Fixed Gain Controller metrics.
We want to know how the AudioMixer is used and how FixedGainController behaves. The WebRTC.Audio.Agc2.FixedDigitalGainCurveRegion.* metrics measures how often the input level hits different regions of the Fixed Gain Controller gain curve (when the limiter is enabled). They also measure how long the metrics stay in different regions. They are related to WebRTC.Audio.ApmCaptureOutputLevelPeakRms, but the new metrics measure the level before any processing done in APM. The AudioMixer mixes incoming audio streams. Their number should be mostly constant, and often some of them could be muted. The metrics WebRTC.Audio.AudioMixer.NumIncomingStreams, WebRTC.Audio.AudioMixer.NumIncomingActiveStreams log the number of incoming stream and how many are not muted. We currently don't have any stats related to that. The metric WebRTC.Audio.AudioMixer.MixingRate logs the rate selected for mixing. The rate can sometimes be inferred from WebRTC.Audio.Encoder.CodecType. But that metric measures encoding and not decoding, and codecs don't always map to rates. See also accompanying Chromium CL https://chromium-review.googlesource.com/c/chromium/src/+/939473 Bug: webrtc:8925 Change-Id: Ib1405877fc1b39e5d2f0ceccba04434813f20b0d Reviewed-on: https://webrtc-review.googlesource.com/57740 Reviewed-by: Alessio Bazzica <alessiob@webrtc.org> Commit-Queue: Alex Loiko <aleloi@webrtc.org> Cr-Commit-Position: refs/heads/master@{#22443}
This commit is contained in:
parent
aaa882cea5
commit
6f2fcb4962
@ -47,6 +47,7 @@ rtc_static_library("audio_mixer_impl") {
|
||||
"../../rtc_base:rtc_base_approved",
|
||||
"../../system_wrappers",
|
||||
"../../system_wrappers:field_trial_api",
|
||||
"../../system_wrappers:metrics_api",
|
||||
"../audio_processing",
|
||||
"../audio_processing:apm_logging",
|
||||
"../audio_processing:audio_frame_view",
|
||||
|
||||
@ -20,8 +20,10 @@
|
||||
#include "modules/audio_mixer/audio_frame_manipulator.h"
|
||||
#include "modules/audio_mixer/audio_mixer_impl.h"
|
||||
#include "modules/audio_processing/logging/apm_data_dumper.h"
|
||||
#include "rtc_base/arraysize.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/logging.h"
|
||||
#include "system_wrappers/include/metrics.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
@ -253,6 +255,36 @@ void FrameCombiner::Combine(const std::vector<AudioFrame*>& mix_list,
|
||||
}
|
||||
|
||||
InterleaveToAudioFrame(mixing_buffer_view, audio_frame_for_mixing);
|
||||
|
||||
LogMixingStats(mix_list, sample_rate, number_of_streams);
|
||||
}
|
||||
|
||||
void FrameCombiner::LogMixingStats(const std::vector<AudioFrame*>& mix_list,
|
||||
int sample_rate,
|
||||
size_t number_of_streams) const {
|
||||
// Log every second.
|
||||
uma_logging_counter_++;
|
||||
if (uma_logging_counter_ > 1000 / AudioMixerImpl::kFrameDurationInMs) {
|
||||
uma_logging_counter_ = 0;
|
||||
RTC_HISTOGRAM_COUNTS_100("WebRTC.Audio.AudioMixer.NumIncomingStreams",
|
||||
static_cast<int>(number_of_streams));
|
||||
RTC_HISTOGRAM_ENUMERATION(
|
||||
"WebRTC.Audio.AudioMixer.NumIncomingActiveStreams",
|
||||
static_cast<int>(mix_list.size()),
|
||||
AudioMixerImpl::kMaximumAmountOfMixedAudioSources);
|
||||
|
||||
using NativeRate = AudioProcessing::NativeRate;
|
||||
static constexpr NativeRate native_rates[] = {
|
||||
NativeRate::kSampleRate8kHz, NativeRate::kSampleRate16kHz,
|
||||
NativeRate::kSampleRate32kHz, NativeRate::kSampleRate48kHz};
|
||||
const auto* rate_position = std::lower_bound(
|
||||
std::begin(native_rates), std::end(native_rates), sample_rate);
|
||||
|
||||
RTC_HISTOGRAM_ENUMERATION(
|
||||
"WebRTC.Audio.AudioMixer.MixingRate",
|
||||
std::distance(std::begin(native_rates), rate_position),
|
||||
arraysize(native_rates));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -44,10 +44,15 @@ class FrameCombiner {
|
||||
AudioFrame* audio_frame_for_mixing);
|
||||
|
||||
private:
|
||||
void LogMixingStats(const std::vector<AudioFrame*>& mix_list,
|
||||
int sample_rate,
|
||||
size_t number_of_streams) const;
|
||||
|
||||
LimiterType limiter_type_;
|
||||
std::unique_ptr<AudioProcessing> apm_agc_limiter_;
|
||||
std::unique_ptr<ApmDataDumper> data_dumper_;
|
||||
FixedGainController apm_agc2_limiter_;
|
||||
mutable int uma_logging_counter_ = 0;
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
|
||||
@ -32,6 +32,7 @@ rtc_source_set("agc2") {
|
||||
"../../../rtc_base:gtest_prod",
|
||||
"../../../rtc_base:rtc_base_approved",
|
||||
"../../../rtc_base:safe_minmax",
|
||||
"../../../system_wrappers:metrics_api",
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@ -14,8 +14,27 @@
|
||||
#include "modules/audio_processing/logging/apm_data_dumper.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/logging.h"
|
||||
#include "system_wrappers/include/metrics.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
void LogRegionStats(const InterpolatedGainCurve::Stats& stats) {
|
||||
using Region = InterpolatedGainCurve::GainCurveRegion;
|
||||
|
||||
std::string histogram_name = "WebRTC.Audio.AGC2.FixedDigitalGainCurveRegion.";
|
||||
if (stats.region == Region::kIdentity) {
|
||||
histogram_name += "Identity";
|
||||
} else if (stats.region == Region::kKnee) {
|
||||
histogram_name += "Knee";
|
||||
} else if (stats.region == Region::kLimiter) {
|
||||
histogram_name += "Limiter";
|
||||
} else {
|
||||
histogram_name += "Saturation";
|
||||
}
|
||||
RTC_HISTOGRAM_COUNTS_10000(histogram_name,
|
||||
stats.region_duration_frames / 100);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
constexpr std::array<float, kInterpolatedGainCurveTotalPoints>
|
||||
InterpolatedGainCurve::approximation_params_x_;
|
||||
@ -31,7 +50,6 @@ InterpolatedGainCurve::InterpolatedGainCurve(ApmDataDumper* apm_data_dumper)
|
||||
|
||||
InterpolatedGainCurve::~InterpolatedGainCurve() {
|
||||
if (stats_.available) {
|
||||
// TODO(alessiob): We might want to add these stats as RTC metrics.
|
||||
RTC_DCHECK(apm_data_dumper_);
|
||||
apm_data_dumper_->DumpRaw("agc2_interp_gain_curve_lookups_identity",
|
||||
stats_.look_ups_identity_region);
|
||||
@ -41,21 +59,37 @@ InterpolatedGainCurve::~InterpolatedGainCurve() {
|
||||
stats_.look_ups_limiter_region);
|
||||
apm_data_dumper_->DumpRaw("agc2_interp_gain_curve_lookups_saturation",
|
||||
stats_.look_ups_saturation_region);
|
||||
LogRegionStats(stats_);
|
||||
}
|
||||
}
|
||||
|
||||
void InterpolatedGainCurve::UpdateStats(float input_level) const {
|
||||
stats_.available = true;
|
||||
|
||||
GainCurveRegion region;
|
||||
|
||||
if (input_level < approximation_params_x_[0]) {
|
||||
stats_.look_ups_identity_region++;
|
||||
region = GainCurveRegion::kIdentity;
|
||||
} else if (input_level <
|
||||
approximation_params_x_[kInterpolatedGainCurveKneePoints - 1]) {
|
||||
stats_.look_ups_knee_region++;
|
||||
region = GainCurveRegion::kKnee;
|
||||
} else if (input_level < kMaxInputLevelLinear) {
|
||||
stats_.look_ups_limiter_region++;
|
||||
region = GainCurveRegion::kLimiter;
|
||||
} else {
|
||||
stats_.look_ups_saturation_region++;
|
||||
region = GainCurveRegion::kSaturation;
|
||||
}
|
||||
|
||||
if (region == stats_.region) {
|
||||
++stats_.region_duration_frames;
|
||||
} else {
|
||||
LogRegionStats(stats_);
|
||||
|
||||
stats_.region_duration_frames = 0;
|
||||
stats_.region = region;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -33,6 +33,13 @@ constexpr float kMaxInputLevelLinear = static_cast<float>(36766.300710566735);
|
||||
// estimates of the gain to apply given an estimated input level.
|
||||
class InterpolatedGainCurve {
|
||||
public:
|
||||
enum class GainCurveRegion {
|
||||
kIdentity = 0,
|
||||
kKnee = 1,
|
||||
kLimiter = 2,
|
||||
kSaturation = 3
|
||||
};
|
||||
|
||||
struct Stats {
|
||||
// Region in which the output level equals the input one.
|
||||
size_t look_ups_identity_region = 0;
|
||||
@ -45,6 +52,11 @@ class InterpolatedGainCurve {
|
||||
size_t look_ups_saturation_region = 0;
|
||||
// True if stats have been populated.
|
||||
bool available = false;
|
||||
|
||||
// The current region, and for how many frames the level has been
|
||||
// in that region.
|
||||
GainCurveRegion region = GainCurveRegion::kIdentity;
|
||||
int64_t region_duration_frames = 0;
|
||||
};
|
||||
|
||||
// InterpolatedGainCurve(InterpolatedGainCurve&&);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user