blob: 52951819f594f71bd57792a8626653d839a1cb8f [file] [log] [blame]
Alex Loikoab20a602018-01-16 11:50:341/*
2 * Copyright (c) 2017 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
Sam Zackrisson790da372018-06-19 08:46:0411#include <bitset>
12#include <string>
13
Karl Wiberg918f50c2018-07-05 09:40:3314#include "absl/memory/memory.h"
Gustaf Ullberg0efa9412018-02-27 12:58:4515#include "api/audio/echo_canceller3_factory.h"
Alex Loikof344dbb2018-06-19 10:33:2016#include "modules/audio_processing/aec_dump/mock_aec_dump.h"
Alex Loikoab20a602018-01-16 11:50:3417#include "modules/audio_processing/include/audio_processing.h"
Sam Zackrisson790da372018-06-19 08:46:0418#include "rtc_base/arraysize.h"
Alex Loikoa05ee822018-02-20 14:58:3619#include "rtc_base/numerics/safe_minmax.h"
Sam Zackrisson790da372018-06-19 08:46:0420#include "system_wrappers/include/field_trial_default.h"
Alex Loikoab20a602018-01-16 11:50:3421#include "test/fuzzers/audio_processing_fuzzer_helper.h"
22#include "test/fuzzers/fuzz_data_helper.h"
23
24namespace webrtc {
25namespace {
Sam Zackrisson790da372018-06-19 08:46:0426
27const std::string kFieldTrialNames[] = {
28 "WebRTC-Aec3TransparentModeKillSwitch",
29 "WebRTC-Aec3StationaryRenderImprovementsKillSwitch",
30 "WebRTC-Aec3EnforceDelayAfterRealignmentKillSwitch",
31 "WebRTC-Aec3UseShortDelayEstimatorWindow",
32 "WebRTC-Aec3ReverbBasedOnRenderKillSwitch",
33 "WebRTC-Aec3ReverbModellingKillSwitch",
34 "WebRTC-Aec3FilterAnalyzerPreprocessorKillSwitch",
35 "WebRTC-Aec3TransparencyImprovementsKillSwitch",
36 "WebRTC-Aec3SoftTransparentModeKillSwitch",
37 "WebRTC-Aec3OverrideEchoPathGainKillSwitch",
38 "WebRTC-Aec3ZeroExternalDelayHeadroomKillSwitch",
39 "WebRTC-Aec3DownSamplingFactor8KillSwitch",
40 "WebRTC-Aec3EnforceSkewHysteresis1",
41 "WebRTC-Aec3EnforceSkewHysteresis2"};
42
43std::unique_ptr<AudioProcessing> CreateApm(test::FuzzDataHelper* fuzz_data,
44 std::string* field_trial_string) {
Alex Loikoab20a602018-01-16 11:50:3445 // Parse boolean values for optionally enabling different
46 // configurable public components of APM.
47 bool exp_agc = fuzz_data->ReadOrDefaultValue(true);
48 bool exp_ns = fuzz_data->ReadOrDefaultValue(true);
Sam Zackrisson44b98f92018-06-25 12:21:5349 static_cast<void>(fuzz_data->ReadOrDefaultValue(true));
Alex Loikoab20a602018-01-16 11:50:3450 bool ef = fuzz_data->ReadOrDefaultValue(true);
51 bool raf = fuzz_data->ReadOrDefaultValue(true);
Alex Loiko8a5edb22018-06-18 15:25:3252 static_cast<void>(fuzz_data->ReadOrDefaultValue(true));
Alex Loikoab20a602018-01-16 11:50:3453 bool ie = fuzz_data->ReadOrDefaultValue(true);
54 bool red = fuzz_data->ReadOrDefaultValue(true);
Alex Loikoab20a602018-01-16 11:50:3455 bool hpf = fuzz_data->ReadOrDefaultValue(true);
56 bool aec3 = fuzz_data->ReadOrDefaultValue(true);
57
58 bool use_aec = fuzz_data->ReadOrDefaultValue(true);
59 bool use_aecm = fuzz_data->ReadOrDefaultValue(true);
60 bool use_agc = fuzz_data->ReadOrDefaultValue(true);
61 bool use_ns = fuzz_data->ReadOrDefaultValue(true);
62 bool use_le = fuzz_data->ReadOrDefaultValue(true);
63 bool use_vad = fuzz_data->ReadOrDefaultValue(true);
64 bool use_agc_limiter = fuzz_data->ReadOrDefaultValue(true);
Alex Loikoa05ee822018-02-20 14:58:3665 bool use_agc2_limiter = fuzz_data->ReadOrDefaultValue(true);
Alex Loikoab20a602018-01-16 11:50:3466
Alex Loiko38c15d32018-03-02 12:53:0967 // Read an int8 value, but don't let it be too large or small.
68 const float gain_controller2_gain_db =
69 rtc::SafeClamp<int>(fuzz_data->ReadOrDefaultValue<int8_t>(0), -50, 50);
70
Sam Zackrisson790da372018-06-19 08:46:0471 constexpr size_t kNumFieldTrials = arraysize(kFieldTrialNames);
72 // This check ensures the uint16_t that is read has enough bits to cover all
73 // the field trials.
74 RTC_DCHECK_LE(kNumFieldTrials, 16);
75 std::bitset<kNumFieldTrials> field_trial_bitmask(
76 fuzz_data->ReadOrDefaultValue<uint16_t>(0));
77 for (size_t i = 0; i < kNumFieldTrials; ++i) {
78 if (field_trial_bitmask[i]) {
79 *field_trial_string += kFieldTrialNames[i] + "/Enabled/";
80 }
81 }
82 field_trial::InitFieldTrialsFromString(field_trial_string->c_str());
83
Alex Loiko38c15d32018-03-02 12:53:0984 // Ignore a few bytes. Bytes from this segment will be used for
85 // future config flag changes. We assume 40 bytes is enough for
86 // configuring the APM.
87 constexpr size_t kSizeOfConfigSegment = 40;
88 RTC_DCHECK(kSizeOfConfigSegment >= fuzz_data->BytesRead());
89 static_cast<void>(
90 fuzz_data->ReadByteArray(kSizeOfConfigSegment - fuzz_data->BytesRead()));
91
Alex Loikoab20a602018-01-16 11:50:3492 // Filter out incompatible settings that lead to CHECK failures.
93 if (use_aecm && use_aec) {
94 return nullptr;
95 }
96
97 // Components can be enabled through webrtc::Config and
98 // webrtc::AudioProcessingConfig.
99 Config config;
100
101 std::unique_ptr<EchoControlFactory> echo_control_factory;
102 if (aec3) {
103 echo_control_factory.reset(new EchoCanceller3Factory());
104 }
105
106 config.Set<ExperimentalAgc>(new ExperimentalAgc(exp_agc));
107 config.Set<ExperimentalNs>(new ExperimentalNs(exp_ns));
Alex Loikoab20a602018-01-16 11:50:34108 config.Set<ExtendedFilter>(new ExtendedFilter(ef));
109 config.Set<RefinedAdaptiveFilter>(new RefinedAdaptiveFilter(raf));
Alex Loiko8a5edb22018-06-18 15:25:32110 config.Set<DelayAgnostic>(new DelayAgnostic(true));
Alex Loikoab20a602018-01-16 11:50:34111 config.Set<Intelligibility>(new Intelligibility(ie));
112
113 std::unique_ptr<AudioProcessing> apm(
114 AudioProcessingBuilder()
115 .SetEchoControlFactory(std::move(echo_control_factory))
116 .Create(config));
117
Alex Loikof344dbb2018-06-19 10:33:20118 apm->AttachAecDump(
Karl Wiberg918f50c2018-07-05 09:40:33119 absl::make_unique<testing::NiceMock<webrtc::test::MockAecDump>>());
Alex Loikof344dbb2018-06-19 10:33:20120
Alex Loikoab20a602018-01-16 11:50:34121 webrtc::AudioProcessing::Config apm_config;
122 apm_config.residual_echo_detector.enabled = red;
Alex Loikoab20a602018-01-16 11:50:34123 apm_config.high_pass_filter.enabled = hpf;
Alex Loikoa05ee822018-02-20 14:58:36124 apm_config.gain_controller2.enabled = use_agc2_limiter;
125
Alex Loiko38c15d32018-03-02 12:53:09126 apm_config.gain_controller2.fixed_gain_db = gain_controller2_gain_db;
Alex Loikoab20a602018-01-16 11:50:34127
128 apm->ApplyConfig(apm_config);
129
130 apm->echo_cancellation()->Enable(use_aec);
131 apm->echo_control_mobile()->Enable(use_aecm);
132 apm->gain_control()->Enable(use_agc);
133 apm->noise_suppression()->Enable(use_ns);
134 apm->level_estimator()->Enable(use_le);
135 apm->voice_detection()->Enable(use_vad);
136 apm->gain_control()->enable_limiter(use_agc_limiter);
137
138 return apm;
139}
140} // namespace
141
142void FuzzOneInput(const uint8_t* data, size_t size) {
143 test::FuzzDataHelper fuzz_data(rtc::ArrayView<const uint8_t>(data, size));
Sam Zackrisson790da372018-06-19 08:46:04144 // This string must be in scope during execution, according to documentation
145 // for field_trial_default.h. Hence it's created here and not in CreateApm.
146 std::string field_trial_string = "";
147 auto apm = CreateApm(&fuzz_data, &field_trial_string);
Alex Loikoab20a602018-01-16 11:50:34148
149 if (apm) {
150 FuzzAudioProcessing(&fuzz_data, std::move(apm));
151 }
152}
153} // namespace webrtc