AEC-m and AEC-2 fuzzing.
Going through the coverage of audio_processing_fuzzer, it was noticed that it didn't cover AEC-m and AEC-2 code. Therefore this CL adds 2 fuzzer targets that only fuzz the previous generation echo cancellers. To avoid code duplication, the APM running code was broken out in a new GN target. We have also changed all fuzzing code to use the FuzzDataHelper class to avoid manual pointer arithmetic. Bug: webrtc:7820 Change-Id: Ifea3266e396b487952a736945577fccea15d0e01 Reviewed-on: https://webrtc-review.googlesource.com/36500 Reviewed-by: Henrik Lundin <henrik.lundin@webrtc.org> Reviewed-by: Sam Zackrisson <saza@webrtc.org> Commit-Queue: Alex Loiko <aleloi@webrtc.org> Cr-Commit-Position: refs/heads/master@{#21638}
This commit is contained in:
@ -421,14 +421,13 @@ webrtc_fuzzer_test("transport_feedback_packet_loss_tracker_fuzzer") {
|
|||||||
"../../voice_engine",
|
"../../voice_engine",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
rtc_static_library("audio_processing_fuzzer_helper") {
|
||||||
webrtc_fuzzer_test("audio_processing_fuzzer") {
|
|
||||||
sources = [
|
sources = [
|
||||||
"audio_processing_fuzzer.cc",
|
"audio_processing_fuzzer_helper.cc",
|
||||||
"audio_processing_fuzzer.h",
|
"audio_processing_fuzzer_helper.h",
|
||||||
"audio_processing_fuzzer_configs.cc",
|
|
||||||
]
|
]
|
||||||
deps = [
|
deps = [
|
||||||
|
":fuzz_data_helper",
|
||||||
"../../api:optional",
|
"../../api:optional",
|
||||||
"../../modules:module_api",
|
"../../modules:module_api",
|
||||||
"../../modules/audio_processing",
|
"../../modules/audio_processing",
|
||||||
@ -437,6 +436,17 @@ webrtc_fuzzer_test("audio_processing_fuzzer") {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
webrtc_fuzzer_test("audio_processing_fuzzer") {
|
||||||
|
sources = [
|
||||||
|
"audio_processing_configs_fuzzer.cc",
|
||||||
|
]
|
||||||
|
deps = [
|
||||||
|
":audio_processing_fuzzer_helper",
|
||||||
|
":fuzz_data_helper",
|
||||||
|
"../../modules/audio_processing",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
webrtc_fuzzer_test("comfort_noise_decoder_fuzzer") {
|
webrtc_fuzzer_test("comfort_noise_decoder_fuzzer") {
|
||||||
sources = [
|
sources = [
|
||||||
"comfort_noise_decoder_fuzzer.cc",
|
"comfort_noise_decoder_fuzzer.cc",
|
||||||
|
|||||||
96
test/fuzzers/audio_processing_configs_fuzzer.cc
Normal file
96
test/fuzzers/audio_processing_configs_fuzzer.cc
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license
|
||||||
|
* that can be found in the LICENSE file in the root of the source
|
||||||
|
* tree. An additional intellectual property rights grant can be found
|
||||||
|
* in the file PATENTS. All contributing project authors may
|
||||||
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "modules/audio_processing/include/audio_processing.h"
|
||||||
|
#include "test/fuzzers/audio_processing_fuzzer_helper.h"
|
||||||
|
#include "test/fuzzers/fuzz_data_helper.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
namespace {
|
||||||
|
std::unique_ptr<AudioProcessing> CreateApm(test::FuzzDataHelper* fuzz_data) {
|
||||||
|
// Parse boolean values for optionally enabling different
|
||||||
|
// configurable public components of APM.
|
||||||
|
bool exp_agc = fuzz_data->ReadOrDefaultValue(true);
|
||||||
|
bool exp_ns = fuzz_data->ReadOrDefaultValue(true);
|
||||||
|
bool bf = fuzz_data->ReadOrDefaultValue(true);
|
||||||
|
bool ef = fuzz_data->ReadOrDefaultValue(true);
|
||||||
|
bool raf = fuzz_data->ReadOrDefaultValue(true);
|
||||||
|
bool da = fuzz_data->ReadOrDefaultValue(true);
|
||||||
|
bool ie = fuzz_data->ReadOrDefaultValue(true);
|
||||||
|
bool red = fuzz_data->ReadOrDefaultValue(true);
|
||||||
|
bool lc = fuzz_data->ReadOrDefaultValue(true);
|
||||||
|
bool hpf = fuzz_data->ReadOrDefaultValue(true);
|
||||||
|
bool aec3 = fuzz_data->ReadOrDefaultValue(true);
|
||||||
|
|
||||||
|
bool use_aec = fuzz_data->ReadOrDefaultValue(true);
|
||||||
|
bool use_aecm = fuzz_data->ReadOrDefaultValue(true);
|
||||||
|
bool use_agc = fuzz_data->ReadOrDefaultValue(true);
|
||||||
|
bool use_ns = fuzz_data->ReadOrDefaultValue(true);
|
||||||
|
bool use_le = fuzz_data->ReadOrDefaultValue(true);
|
||||||
|
bool use_vad = fuzz_data->ReadOrDefaultValue(true);
|
||||||
|
bool use_agc_limiter = fuzz_data->ReadOrDefaultValue(true);
|
||||||
|
|
||||||
|
// Filter out incompatible settings that lead to CHECK failures.
|
||||||
|
if (use_aecm && use_aec) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Components can be enabled through webrtc::Config and
|
||||||
|
// webrtc::AudioProcessingConfig.
|
||||||
|
Config config;
|
||||||
|
|
||||||
|
std::unique_ptr<EchoControlFactory> echo_control_factory;
|
||||||
|
if (aec3) {
|
||||||
|
echo_control_factory.reset(new EchoCanceller3Factory());
|
||||||
|
}
|
||||||
|
|
||||||
|
config.Set<ExperimentalAgc>(new ExperimentalAgc(exp_agc));
|
||||||
|
config.Set<ExperimentalNs>(new ExperimentalNs(exp_ns));
|
||||||
|
if (bf) {
|
||||||
|
config.Set<Beamforming>(new Beamforming());
|
||||||
|
}
|
||||||
|
config.Set<ExtendedFilter>(new ExtendedFilter(ef));
|
||||||
|
config.Set<RefinedAdaptiveFilter>(new RefinedAdaptiveFilter(raf));
|
||||||
|
config.Set<DelayAgnostic>(new DelayAgnostic(da));
|
||||||
|
config.Set<Intelligibility>(new Intelligibility(ie));
|
||||||
|
|
||||||
|
std::unique_ptr<AudioProcessing> apm(
|
||||||
|
AudioProcessingBuilder()
|
||||||
|
.SetEchoControlFactory(std::move(echo_control_factory))
|
||||||
|
.Create(config));
|
||||||
|
|
||||||
|
webrtc::AudioProcessing::Config apm_config;
|
||||||
|
apm_config.residual_echo_detector.enabled = red;
|
||||||
|
apm_config.level_controller.enabled = lc;
|
||||||
|
apm_config.high_pass_filter.enabled = hpf;
|
||||||
|
|
||||||
|
apm->ApplyConfig(apm_config);
|
||||||
|
|
||||||
|
apm->echo_cancellation()->Enable(use_aec);
|
||||||
|
apm->echo_control_mobile()->Enable(use_aecm);
|
||||||
|
apm->gain_control()->Enable(use_agc);
|
||||||
|
apm->noise_suppression()->Enable(use_ns);
|
||||||
|
apm->level_estimator()->Enable(use_le);
|
||||||
|
apm->voice_detection()->Enable(use_vad);
|
||||||
|
apm->gain_control()->enable_limiter(use_agc_limiter);
|
||||||
|
|
||||||
|
return apm;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void FuzzOneInput(const uint8_t* data, size_t size) {
|
||||||
|
test::FuzzDataHelper fuzz_data(rtc::ArrayView<const uint8_t>(data, size));
|
||||||
|
auto apm = CreateApm(&fuzz_data);
|
||||||
|
|
||||||
|
if (apm) {
|
||||||
|
FuzzAudioProcessing(&fuzz_data, std::move(apm));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace webrtc
|
||||||
@ -1,156 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by a BSD-style license
|
|
||||||
* that can be found in the LICENSE file in the root of the source
|
|
||||||
* tree. An additional intellectual property rights grant can be found
|
|
||||||
* in the file PATENTS. All contributing project authors may
|
|
||||||
* be found in the AUTHORS file in the root of the source tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "test/fuzzers/audio_processing_fuzzer.h"
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <array>
|
|
||||||
#include <cmath>
|
|
||||||
|
|
||||||
#include "modules/audio_processing/include/audio_processing.h"
|
|
||||||
#include "modules/include/module_common_types.h"
|
|
||||||
#include "rtc_base/checks.h"
|
|
||||||
|
|
||||||
namespace webrtc {
|
|
||||||
namespace {
|
|
||||||
size_t ByteToNativeRate(uint8_t data) {
|
|
||||||
using Rate = AudioProcessing::NativeRate;
|
|
||||||
switch (data % 4) {
|
|
||||||
case 0:
|
|
||||||
return static_cast<size_t>(Rate::kSampleRate8kHz);
|
|
||||||
case 1:
|
|
||||||
return static_cast<size_t>(Rate::kSampleRate16kHz);
|
|
||||||
case 2:
|
|
||||||
return static_cast<size_t>(Rate::kSampleRate32kHz);
|
|
||||||
default:
|
|
||||||
return static_cast<size_t>(Rate::kSampleRate48kHz);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
bool ParseSequence(size_t size,
|
|
||||||
const uint8_t** data,
|
|
||||||
size_t* remaining_size,
|
|
||||||
T* result_data) {
|
|
||||||
const size_t data_size_bytes = sizeof(T) * size;
|
|
||||||
if (data_size_bytes > *remaining_size) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::copy(*data, *data + data_size_bytes,
|
|
||||||
reinterpret_cast<uint8_t*>(result_data));
|
|
||||||
|
|
||||||
*data += data_size_bytes;
|
|
||||||
*remaining_size -= data_size_bytes;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FuzzAudioProcessing(const uint8_t* data,
|
|
||||||
size_t size,
|
|
||||||
bool is_float,
|
|
||||||
AudioProcessing* apm) {
|
|
||||||
AudioFrame fixed_frame;
|
|
||||||
std::array<float, 480> float_frame{};
|
|
||||||
float* const first_channel = &float_frame[0];
|
|
||||||
|
|
||||||
while (size > 0) {
|
|
||||||
// Decide input/output rate for this iteration.
|
|
||||||
const auto input_rate_byte = ParseByte(&data, &size);
|
|
||||||
const auto output_rate_byte = ParseByte(&data, &size);
|
|
||||||
if (!input_rate_byte || !output_rate_byte) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const auto input_rate_hz = ByteToNativeRate(*input_rate_byte);
|
|
||||||
const auto output_rate_hz = ByteToNativeRate(*output_rate_byte);
|
|
||||||
|
|
||||||
const size_t samples_per_input_channel =
|
|
||||||
rtc::CheckedDivExact(input_rate_hz, 100ul);
|
|
||||||
fixed_frame.samples_per_channel_ = samples_per_input_channel;
|
|
||||||
fixed_frame.sample_rate_hz_ = input_rate_hz;
|
|
||||||
|
|
||||||
// Two channels breaks AEC3.
|
|
||||||
fixed_frame.num_channels_ = 1;
|
|
||||||
|
|
||||||
// Fill the arrays with audio samples from the data.
|
|
||||||
if (is_float) {
|
|
||||||
if (!ParseSequence(samples_per_input_channel, &data, &size,
|
|
||||||
&float_frame[0])) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if (!ParseSequence(samples_per_input_channel, &data, &size,
|
|
||||||
fixed_frame.mutable_data())) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter obviously wrong values like inf/nan and values that will
|
|
||||||
// lead to inf/nan in calculations. 1e6 leads to DCHECKS failing.
|
|
||||||
for (auto& x : float_frame) {
|
|
||||||
if (!std::isnormal(x) || std::abs(x) > 1e5) {
|
|
||||||
x = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make the APM call depending on capture/render mode and float /
|
|
||||||
// fix interface.
|
|
||||||
const auto is_capture = ParseBool(&data, &size);
|
|
||||||
if (!is_capture) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (*is_capture) {
|
|
||||||
auto apm_return_code =
|
|
||||||
is_float ? (apm->ProcessStream(
|
|
||||||
&first_channel, StreamConfig(input_rate_hz, 1),
|
|
||||||
StreamConfig(output_rate_hz, 1), &first_channel))
|
|
||||||
: (apm->ProcessStream(&fixed_frame));
|
|
||||||
RTC_DCHECK_NE(apm_return_code, AudioProcessing::kBadDataLengthError);
|
|
||||||
} else {
|
|
||||||
auto apm_return_code =
|
|
||||||
is_float ? (apm->ProcessReverseStream(
|
|
||||||
&first_channel, StreamConfig(input_rate_hz, 1),
|
|
||||||
StreamConfig(output_rate_hz, 1), &first_channel))
|
|
||||||
: (apm->ProcessReverseStream(&fixed_frame));
|
|
||||||
RTC_DCHECK_NE(apm_return_code, AudioProcessing::kBadDataLengthError);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
rtc::Optional<bool> ParseBool(const uint8_t** data, size_t* remaining_size) {
|
|
||||||
if (1 > *remaining_size) {
|
|
||||||
return rtc::nullopt;
|
|
||||||
}
|
|
||||||
auto res = (**data) % 2;
|
|
||||||
*data += 1;
|
|
||||||
*remaining_size -= 1;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
rtc::Optional<uint8_t> ParseByte(const uint8_t** data, size_t* remaining_size) {
|
|
||||||
if (1 > *remaining_size) {
|
|
||||||
return rtc::nullopt;
|
|
||||||
}
|
|
||||||
auto res = **data;
|
|
||||||
*data += 1;
|
|
||||||
*remaining_size -= 1;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FuzzAudioProcessing(const uint8_t* data,
|
|
||||||
size_t size,
|
|
||||||
std::unique_ptr<AudioProcessing> apm) {
|
|
||||||
const auto is_float = ParseBool(&data, &size);
|
|
||||||
if (!is_float) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
FuzzAudioProcessing(data, size, *is_float, apm.get());
|
|
||||||
}
|
|
||||||
} // namespace webrtc
|
|
||||||
@ -1,101 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by a BSD-style license
|
|
||||||
* that can be found in the LICENSE file in the root of the source
|
|
||||||
* tree. An additional intellectual property rights grant can be found
|
|
||||||
* in the file PATENTS. All contributing project authors may
|
|
||||||
* be found in the AUTHORS file in the root of the source tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "modules/audio_processing/include/audio_processing.h"
|
|
||||||
#include "test/fuzzers/audio_processing_fuzzer.h"
|
|
||||||
|
|
||||||
#include "api/optional.h"
|
|
||||||
|
|
||||||
namespace webrtc {
|
|
||||||
|
|
||||||
std::unique_ptr<AudioProcessing> CreateAPM(const uint8_t** data,
|
|
||||||
size_t* remaining_size) {
|
|
||||||
// Parse boolean values for optionally enabling different
|
|
||||||
// configurable public components of APM.
|
|
||||||
auto exp_agc = ParseBool(data, remaining_size);
|
|
||||||
auto exp_ns = ParseBool(data, remaining_size);
|
|
||||||
auto bf = ParseBool(data, remaining_size);
|
|
||||||
auto ef = ParseBool(data, remaining_size);
|
|
||||||
auto raf = ParseBool(data, remaining_size);
|
|
||||||
auto da = ParseBool(data, remaining_size);
|
|
||||||
auto ie = ParseBool(data, remaining_size);
|
|
||||||
auto red = ParseBool(data, remaining_size);
|
|
||||||
auto lc = ParseBool(data, remaining_size);
|
|
||||||
auto hpf = ParseBool(data, remaining_size);
|
|
||||||
auto aec3 = ParseBool(data, remaining_size);
|
|
||||||
|
|
||||||
auto use_aec = ParseBool(data, remaining_size);
|
|
||||||
auto use_aecm = ParseBool(data, remaining_size);
|
|
||||||
auto use_agc = ParseBool(data, remaining_size);
|
|
||||||
auto use_ns = ParseBool(data, remaining_size);
|
|
||||||
auto use_le = ParseBool(data, remaining_size);
|
|
||||||
auto use_vad = ParseBool(data, remaining_size);
|
|
||||||
auto use_agc_limiter = ParseBool(data, remaining_size);
|
|
||||||
|
|
||||||
if (!(exp_agc && exp_ns && bf && ef && raf && da && ie && red && lc && hpf &&
|
|
||||||
aec3 && use_aec && use_aecm && use_agc && use_ns && use_le && use_vad &&
|
|
||||||
use_agc_limiter)) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter out incompatible settings that lead to CHECK failures.
|
|
||||||
if (*use_aecm && *use_aec) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Components can be enabled through webrtc::Config and
|
|
||||||
// webrtc::AudioProcessingConfig.
|
|
||||||
Config config;
|
|
||||||
|
|
||||||
std::unique_ptr<EchoControlFactory> echo_control_factory;
|
|
||||||
if (*aec3) {
|
|
||||||
echo_control_factory.reset(new EchoCanceller3Factory());
|
|
||||||
}
|
|
||||||
|
|
||||||
config.Set<ExperimentalAgc>(new ExperimentalAgc(*exp_agc));
|
|
||||||
config.Set<ExperimentalNs>(new ExperimentalNs(*exp_ns));
|
|
||||||
if (*bf) {
|
|
||||||
config.Set<Beamforming>(new Beamforming());
|
|
||||||
}
|
|
||||||
config.Set<ExtendedFilter>(new ExtendedFilter(*ef));
|
|
||||||
config.Set<RefinedAdaptiveFilter>(new RefinedAdaptiveFilter(*raf));
|
|
||||||
config.Set<DelayAgnostic>(new DelayAgnostic(*da));
|
|
||||||
config.Set<Intelligibility>(new Intelligibility(*ie));
|
|
||||||
|
|
||||||
std::unique_ptr<AudioProcessing> apm(
|
|
||||||
AudioProcessingBuilder()
|
|
||||||
.SetEchoControlFactory(std::move(echo_control_factory))
|
|
||||||
.Create(config));
|
|
||||||
|
|
||||||
webrtc::AudioProcessing::Config apm_config;
|
|
||||||
apm_config.residual_echo_detector.enabled = *red;
|
|
||||||
apm_config.level_controller.enabled = *lc;
|
|
||||||
apm_config.high_pass_filter.enabled = *hpf;
|
|
||||||
|
|
||||||
apm->ApplyConfig(apm_config);
|
|
||||||
|
|
||||||
apm->echo_cancellation()->Enable(*use_aec);
|
|
||||||
apm->echo_control_mobile()->Enable(*use_aecm);
|
|
||||||
apm->gain_control()->Enable(*use_agc);
|
|
||||||
apm->noise_suppression()->Enable(*use_ns);
|
|
||||||
apm->level_estimator()->Enable(*use_le);
|
|
||||||
apm->voice_detection()->Enable(*use_vad);
|
|
||||||
apm->gain_control()->enable_limiter(*use_agc_limiter);
|
|
||||||
|
|
||||||
return apm;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FuzzOneInput(const uint8_t* data, size_t size) {
|
|
||||||
auto apm = CreateAPM(&data, &size);
|
|
||||||
if (apm) {
|
|
||||||
FuzzAudioProcessing(data, size, std::move(apm));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // namespace webrtc
|
|
||||||
120
test/fuzzers/audio_processing_fuzzer_helper.cc
Normal file
120
test/fuzzers/audio_processing_fuzzer_helper.cc
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license
|
||||||
|
* that can be found in the LICENSE file in the root of the source
|
||||||
|
* tree. An additional intellectual property rights grant can be found
|
||||||
|
* in the file PATENTS. All contributing project authors may
|
||||||
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "test/fuzzers/audio_processing_fuzzer_helper.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <array>
|
||||||
|
#include <cmath>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
#include "modules/audio_processing/include/audio_processing.h"
|
||||||
|
#include "modules/include/module_common_types.h"
|
||||||
|
#include "rtc_base/checks.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
namespace {
|
||||||
|
void GenerateFloatFrame(test::FuzzDataHelper* fuzz_data,
|
||||||
|
size_t input_rate,
|
||||||
|
size_t num_channels,
|
||||||
|
float* const* float_frames) {
|
||||||
|
const size_t samples_per_input_channel =
|
||||||
|
rtc::CheckedDivExact(input_rate, 100ul);
|
||||||
|
RTC_DCHECK_LE(samples_per_input_channel, 480);
|
||||||
|
for (size_t i = 0; i < num_channels; ++i) {
|
||||||
|
for (size_t j = 0; j < samples_per_input_channel; ++j) {
|
||||||
|
float_frames[i][j] =
|
||||||
|
static_cast<float>(fuzz_data->ReadOrDefaultValue<int16_t>(0)) /
|
||||||
|
static_cast<float>(std::numeric_limits<int16_t>::max());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GenerateFixedFrame(test::FuzzDataHelper* fuzz_data,
|
||||||
|
size_t input_rate,
|
||||||
|
size_t num_channels,
|
||||||
|
AudioFrame* fixed_frame) {
|
||||||
|
const size_t samples_per_input_channel =
|
||||||
|
rtc::CheckedDivExact(input_rate, 100ul);
|
||||||
|
fixed_frame->samples_per_channel_ = samples_per_input_channel;
|
||||||
|
fixed_frame->sample_rate_hz_ = input_rate;
|
||||||
|
fixed_frame->num_channels_ = num_channels;
|
||||||
|
|
||||||
|
RTC_DCHECK_LE(samples_per_input_channel * num_channels,
|
||||||
|
AudioFrame::kMaxDataSizeSamples);
|
||||||
|
for (size_t i = 0; i < samples_per_input_channel * num_channels; ++i) {
|
||||||
|
fixed_frame->mutable_data()[i] = fuzz_data->ReadOrDefaultValue(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void FuzzAudioProcessing(test::FuzzDataHelper* fuzz_data,
|
||||||
|
std::unique_ptr<AudioProcessing> apm) {
|
||||||
|
AudioFrame fixed_frame;
|
||||||
|
std::array<float, 480> float_frame1;
|
||||||
|
std::array<float, 480> float_frame2;
|
||||||
|
std::array<float* const, 2> float_frame_ptrs = {
|
||||||
|
&float_frame1[0], &float_frame2[0],
|
||||||
|
};
|
||||||
|
float* const* ptr_to_float_frames = &float_frame_ptrs[0];
|
||||||
|
|
||||||
|
using Rate = AudioProcessing::NativeRate;
|
||||||
|
const Rate rate_kinds[] = {Rate::kSampleRate8kHz, Rate::kSampleRate16kHz,
|
||||||
|
Rate::kSampleRate32kHz, Rate::kSampleRate48kHz};
|
||||||
|
|
||||||
|
// We may run out of fuzz data in the middle of a loop iteration. In
|
||||||
|
// that case, default values will be used for the rest of that
|
||||||
|
// iteration.
|
||||||
|
while (fuzz_data->CanReadBytes(1)) {
|
||||||
|
const bool is_float = fuzz_data->ReadOrDefaultValue(true);
|
||||||
|
// Decide input/output rate for this iteration.
|
||||||
|
const auto input_rate =
|
||||||
|
static_cast<size_t>(fuzz_data->SelectOneOf(rate_kinds));
|
||||||
|
const auto output_rate =
|
||||||
|
static_cast<size_t>(fuzz_data->SelectOneOf(rate_kinds));
|
||||||
|
|
||||||
|
const bool num_channels = fuzz_data->ReadOrDefaultValue(true) ? 2 : 1;
|
||||||
|
const uint8_t stream_delay = fuzz_data->ReadOrDefaultValue(0);
|
||||||
|
|
||||||
|
// API call needed for AEC-2 and AEC-m to run.
|
||||||
|
apm->set_stream_delay_ms(stream_delay);
|
||||||
|
|
||||||
|
// Make the APM call depending on capture/render mode and float /
|
||||||
|
// fix interface.
|
||||||
|
const bool is_capture = fuzz_data->ReadOrDefaultValue(true);
|
||||||
|
|
||||||
|
// Fill the arrays with audio samples from the data.
|
||||||
|
int apm_return_code = AudioProcessing::Error::kNoError;
|
||||||
|
if (is_float) {
|
||||||
|
GenerateFloatFrame(fuzz_data, input_rate, num_channels,
|
||||||
|
ptr_to_float_frames);
|
||||||
|
if (is_capture) {
|
||||||
|
apm_return_code = apm->ProcessStream(
|
||||||
|
ptr_to_float_frames, StreamConfig(input_rate, num_channels),
|
||||||
|
StreamConfig(output_rate, num_channels), ptr_to_float_frames);
|
||||||
|
} else {
|
||||||
|
apm_return_code = apm->ProcessReverseStream(
|
||||||
|
ptr_to_float_frames, StreamConfig(input_rate, 1),
|
||||||
|
StreamConfig(output_rate, 1), ptr_to_float_frames);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
GenerateFixedFrame(fuzz_data, input_rate, num_channels, &fixed_frame);
|
||||||
|
|
||||||
|
if (is_capture) {
|
||||||
|
apm_return_code = apm->ProcessStream(&fixed_frame);
|
||||||
|
} else {
|
||||||
|
apm_return_code = apm->ProcessReverseStream(&fixed_frame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RTC_DCHECK_NE(apm_return_code, AudioProcessing::kBadDataLengthError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace webrtc
|
||||||
@ -8,20 +8,18 @@
|
|||||||
* be found in the AUTHORS file in the root of the source tree.
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef TEST_FUZZERS_AUDIO_PROCESSING_FUZZER_H_
|
#ifndef TEST_FUZZERS_AUDIO_PROCESSING_FUZZER_HELPER_H_
|
||||||
#define TEST_FUZZERS_AUDIO_PROCESSING_FUZZER_H_
|
#define TEST_FUZZERS_AUDIO_PROCESSING_FUZZER_HELPER_H_
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "modules/audio_processing/include/audio_processing.h"
|
#include "modules/audio_processing/include/audio_processing.h"
|
||||||
|
#include "test/fuzzers/fuzz_data_helper.h"
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
rtc::Optional<bool> ParseBool(const uint8_t** data, size_t* remaining_size);
|
void FuzzAudioProcessing(test::FuzzDataHelper* fuzz_data,
|
||||||
rtc::Optional<uint8_t> ParseByte(const uint8_t** data, size_t* remaining_size);
|
|
||||||
|
|
||||||
void FuzzAudioProcessing(const uint8_t* data,
|
|
||||||
size_t size,
|
|
||||||
std::unique_ptr<AudioProcessing> apm);
|
std::unique_ptr<AudioProcessing> apm);
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|
||||||
#endif // TEST_FUZZERS_AUDIO_PROCESSING_FUZZER_H_
|
#endif // TEST_FUZZERS_AUDIO_PROCESSING_FUZZER_HELPER_H_
|
||||||
Reference in New Issue
Block a user