OLD | NEW |
---|---|
(Empty) | |
1 /* | |
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 | |
11 #include "webrtc/test/fuzzers/audio_processing_fuzzer.h" | |
12 | |
13 #include <algorithm> | |
14 #include <array> | |
15 #include <cmath> | |
16 | |
17 #include "webrtc/base/checks.h" | |
18 #include "webrtc/modules/audio_processing/include/audio_processing.h" | |
19 #include "webrtc/modules/include/module_common_types.h" | |
20 | |
21 namespace webrtc { | |
22 namespace { | |
23 size_t ByteToNativeRate(uint8_t data) { | |
24 using Rate = AudioProcessing::NativeRate; | |
25 switch (data % 4) { | |
26 case 0: | |
27 // Breaks AEC3. | |
28 // return static_cast<size_t>(Rate::kSampleRate8kHz); | |
29 case 1: | |
30 return static_cast<size_t>(Rate::kSampleRate16kHz); | |
31 case 2: | |
32 return static_cast<size_t>(Rate::kSampleRate32kHz); | |
33 default: | |
34 return static_cast<size_t>(Rate::kSampleRate48kHz); | |
35 } | |
36 } | |
37 | |
38 template <class T> | |
39 bool ParseSequence(size_t size, | |
40 const uint8_t** data, | |
41 size_t* remaining_size, | |
42 T* result_data) { | |
43 const size_t data_size_bytes = sizeof(T) * size; | |
44 if (data_size_bytes > *remaining_size) { | |
45 return false; | |
46 } | |
47 | |
48 std::copy(*data, *data + data_size_bytes, | |
49 reinterpret_cast<uint8_t*>(result_data)); | |
50 | |
51 *data += data_size_bytes; | |
52 *remaining_size -= data_size_bytes; | |
53 return true; | |
54 } | |
55 | |
56 void FuzzAudioProcessing(const uint8_t* data, | |
57 size_t size, | |
58 bool is_float, | |
59 AudioProcessing* apm) { | |
60 AudioFrame fixed_frame; | |
61 std::array<float, 480> float_frame; | |
62 float* const first_channel = &float_frame[0]; | |
63 | |
64 while (size > 0) { | |
65 // Decide input/output rate for this iteration. | |
66 const auto input_rate_byte = ParseByte(&data, &size); | |
67 const auto output_rate_byte = ParseByte(&data, &size); | |
68 if (!input_rate_byte || !output_rate_byte) { | |
69 return; | |
70 } | |
71 const auto input_rate_hz = ByteToNativeRate(*input_rate_byte); | |
72 const auto output_rate_hz = ByteToNativeRate(*output_rate_byte); | |
73 | |
74 const size_t samples_per_input_channel = | |
75 rtc::CheckedDivExact(input_rate_hz, 100ul); | |
76 fixed_frame.samples_per_channel_ = samples_per_input_channel; | |
77 fixed_frame.sample_rate_hz_ = input_rate_hz; | |
78 | |
79 // Two channels breaks AEC3. | |
80 fixed_frame.num_channels_ = 1; | |
81 | |
82 // Fill the arrays with audio samples from the data. | |
83 if (is_float) { | |
84 if (!ParseSequence(samples_per_input_channel, &data, &size, | |
85 &float_frame[0])) { | |
86 return; | |
87 } | |
88 } else if (!ParseSequence(samples_per_input_channel, &data, &size, | |
89 fixed_frame.mutable_data())) { | |
90 return; | |
91 } | |
92 | |
93 // Filter obviously wrong values like inf/nan and values that will | |
94 // lead to inf/nan in calculations. 1e6 leads to DCHECKS failing. | |
95 for (auto& x : float_frame) { | |
96 if (!std::isnormal(x) || std::abs(x) > 1e5) { | |
97 x = 0; | |
98 } | |
99 } | |
100 | |
101 // Make the APM call depending on capture/render mode and float / | |
102 // fix interface. | |
103 const auto is_capture = ParseBool(&data, &size); | |
104 if (!is_capture) { | |
105 return; | |
106 } | |
107 if (*is_capture) { | |
108 auto apm_return_code = | |
109 is_float ? (apm->ProcessStream( | |
110 &first_channel, StreamConfig(input_rate_hz, 1), | |
111 StreamConfig(output_rate_hz, 1), &first_channel)) | |
112 : (apm->ProcessStream(&fixed_frame)); | |
113 RTC_DCHECK_EQ(apm_return_code, AudioProcessing::kNoError); | |
hlundin-webrtc
2017/06/20 09:32:58
Hmmm. Will the live fuzzer be run with dcheck_alwa
aleloi
2017/06/20 09:46:42
Done.
| |
114 } else { | |
115 auto apm_return_code = | |
116 is_float ? (apm->ProcessReverseStream( | |
117 &first_channel, StreamConfig(input_rate_hz, 1), | |
118 StreamConfig(output_rate_hz, 1), &first_channel)) | |
119 : (apm->ProcessReverseStream(&fixed_frame)); | |
120 RTC_DCHECK_EQ(apm_return_code, AudioProcessing::kNoError); | |
hlundin-webrtc
2017/06/20 09:32:58
Same here.
aleloi
2017/06/20 09:46:42
Done.
| |
121 } | |
122 } | |
123 } | |
124 | |
125 } // namespace | |
126 | |
127 rtc::Optional<bool> ParseBool(const uint8_t** data, size_t* remaining_size) { | |
128 if (1 > *remaining_size) { | |
129 return rtc::Optional<bool>(); | |
130 } | |
131 auto res = rtc::Optional<bool>((**data) % 2); | |
132 *data += 1; | |
133 *remaining_size -= 1; | |
134 return res; | |
135 } | |
136 | |
137 rtc::Optional<uint8_t> ParseByte(const uint8_t** data, size_t* remaining_size) { | |
138 if (1 > *remaining_size) { | |
139 return rtc::Optional<uint8_t>(); | |
140 } | |
141 auto res = rtc::Optional<uint8_t>((**data)); | |
142 *data += 1; | |
143 *remaining_size -= 1; | |
144 return res; | |
145 } | |
146 | |
147 void FuzzAudioProcessing(const uint8_t* data, | |
148 size_t size, | |
149 std::unique_ptr<AudioProcessing> apm) { | |
150 const auto is_float = ParseBool(&data, &size); | |
151 if (!is_float) { | |
152 return; | |
153 } | |
154 | |
155 FuzzAudioProcessing(data, size, *is_float, apm.get()); | |
156 } | |
157 } // namespace webrtc | |
OLD | NEW |