xref: /aosp_15_r20/external/webrtc/test/fuzzers/neteq_rtp_fuzzer.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker 
11*d9f75844SAndroid Build Coastguard Worker #include <algorithm>
12*d9f75844SAndroid Build Coastguard Worker #include <cmath>
13*d9f75844SAndroid Build Coastguard Worker #include <cstring>
14*d9f75844SAndroid Build Coastguard Worker #include <memory>
15*d9f75844SAndroid Build Coastguard Worker #include <vector>
16*d9f75844SAndroid Build Coastguard Worker 
17*d9f75844SAndroid Build Coastguard Worker #include "api/array_view.h"
18*d9f75844SAndroid Build Coastguard Worker #include "api/audio_codecs/builtin_audio_decoder_factory.h"
19*d9f75844SAndroid Build Coastguard Worker #include "modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.h"
20*d9f75844SAndroid Build Coastguard Worker #include "modules/audio_coding/neteq/tools/audio_checksum.h"
21*d9f75844SAndroid Build Coastguard Worker #include "modules/audio_coding/neteq/tools/encode_neteq_input.h"
22*d9f75844SAndroid Build Coastguard Worker #include "modules/audio_coding/neteq/tools/neteq_test.h"
23*d9f75844SAndroid Build Coastguard Worker #include "modules/rtp_rtcp/source/byte_io.h"
24*d9f75844SAndroid Build Coastguard Worker 
25*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
26*d9f75844SAndroid Build Coastguard Worker namespace test {
27*d9f75844SAndroid Build Coastguard Worker namespace {
28*d9f75844SAndroid Build Coastguard Worker constexpr int kPayloadType = 95;
29*d9f75844SAndroid Build Coastguard Worker 
30*d9f75844SAndroid Build Coastguard Worker class SineGenerator : public EncodeNetEqInput::Generator {
31*d9f75844SAndroid Build Coastguard Worker  public:
SineGenerator(int sample_rate_hz)32*d9f75844SAndroid Build Coastguard Worker   explicit SineGenerator(int sample_rate_hz)
33*d9f75844SAndroid Build Coastguard Worker       : sample_rate_hz_(sample_rate_hz) {}
34*d9f75844SAndroid Build Coastguard Worker 
Generate(size_t num_samples)35*d9f75844SAndroid Build Coastguard Worker   rtc::ArrayView<const int16_t> Generate(size_t num_samples) override {
36*d9f75844SAndroid Build Coastguard Worker     if (samples_.size() < num_samples) {
37*d9f75844SAndroid Build Coastguard Worker       samples_.resize(num_samples);
38*d9f75844SAndroid Build Coastguard Worker     }
39*d9f75844SAndroid Build Coastguard Worker 
40*d9f75844SAndroid Build Coastguard Worker     rtc::ArrayView<int16_t> output(samples_.data(), num_samples);
41*d9f75844SAndroid Build Coastguard Worker     for (auto& x : output) {
42*d9f75844SAndroid Build Coastguard Worker       x = static_cast<int16_t>(2000.0 * std::sin(phase_));
43*d9f75844SAndroid Build Coastguard Worker       phase_ += 2 * kPi * kFreqHz / sample_rate_hz_;
44*d9f75844SAndroid Build Coastguard Worker     }
45*d9f75844SAndroid Build Coastguard Worker     return output;
46*d9f75844SAndroid Build Coastguard Worker   }
47*d9f75844SAndroid Build Coastguard Worker 
48*d9f75844SAndroid Build Coastguard Worker  private:
49*d9f75844SAndroid Build Coastguard Worker   static constexpr int kFreqHz = 300;  // The sinewave frequency.
50*d9f75844SAndroid Build Coastguard Worker   const int sample_rate_hz_;
51*d9f75844SAndroid Build Coastguard Worker   const double kPi = std::acos(-1);
52*d9f75844SAndroid Build Coastguard Worker   std::vector<int16_t> samples_;
53*d9f75844SAndroid Build Coastguard Worker   double phase_ = 0.0;
54*d9f75844SAndroid Build Coastguard Worker };
55*d9f75844SAndroid Build Coastguard Worker 
56*d9f75844SAndroid Build Coastguard Worker class FuzzRtpInput : public NetEqInput {
57*d9f75844SAndroid Build Coastguard Worker  public:
FuzzRtpInput(rtc::ArrayView<const uint8_t> data)58*d9f75844SAndroid Build Coastguard Worker   explicit FuzzRtpInput(rtc::ArrayView<const uint8_t> data) : data_(data) {
59*d9f75844SAndroid Build Coastguard Worker     AudioEncoderPcm16B::Config config;
60*d9f75844SAndroid Build Coastguard Worker     config.payload_type = kPayloadType;
61*d9f75844SAndroid Build Coastguard Worker     config.sample_rate_hz = 32000;
62*d9f75844SAndroid Build Coastguard Worker     std::unique_ptr<AudioEncoder> encoder(new AudioEncoderPcm16B(config));
63*d9f75844SAndroid Build Coastguard Worker     std::unique_ptr<EncodeNetEqInput::Generator> generator(
64*d9f75844SAndroid Build Coastguard Worker         new SineGenerator(config.sample_rate_hz));
65*d9f75844SAndroid Build Coastguard Worker     input_.reset(new EncodeNetEqInput(std::move(generator), std::move(encoder),
66*d9f75844SAndroid Build Coastguard Worker                                       std::numeric_limits<int64_t>::max()));
67*d9f75844SAndroid Build Coastguard Worker     packet_ = input_->PopPacket();
68*d9f75844SAndroid Build Coastguard Worker     FuzzHeader();
69*d9f75844SAndroid Build Coastguard Worker     MaybeFuzzPayload();
70*d9f75844SAndroid Build Coastguard Worker   }
71*d9f75844SAndroid Build Coastguard Worker 
NextPacketTime() const72*d9f75844SAndroid Build Coastguard Worker   absl::optional<int64_t> NextPacketTime() const override {
73*d9f75844SAndroid Build Coastguard Worker     return packet_->time_ms;
74*d9f75844SAndroid Build Coastguard Worker   }
75*d9f75844SAndroid Build Coastguard Worker 
NextOutputEventTime() const76*d9f75844SAndroid Build Coastguard Worker   absl::optional<int64_t> NextOutputEventTime() const override {
77*d9f75844SAndroid Build Coastguard Worker     return input_->NextOutputEventTime();
78*d9f75844SAndroid Build Coastguard Worker   }
79*d9f75844SAndroid Build Coastguard Worker 
PopPacket()80*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<PacketData> PopPacket() override {
81*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(packet_);
82*d9f75844SAndroid Build Coastguard Worker     std::unique_ptr<PacketData> packet_to_return = std::move(packet_);
83*d9f75844SAndroid Build Coastguard Worker     packet_ = input_->PopPacket();
84*d9f75844SAndroid Build Coastguard Worker     FuzzHeader();
85*d9f75844SAndroid Build Coastguard Worker     MaybeFuzzPayload();
86*d9f75844SAndroid Build Coastguard Worker     return packet_to_return;
87*d9f75844SAndroid Build Coastguard Worker   }
88*d9f75844SAndroid Build Coastguard Worker 
AdvanceOutputEvent()89*d9f75844SAndroid Build Coastguard Worker   void AdvanceOutputEvent() override { return input_->AdvanceOutputEvent(); }
90*d9f75844SAndroid Build Coastguard Worker 
ended() const91*d9f75844SAndroid Build Coastguard Worker   bool ended() const override { return ended_; }
92*d9f75844SAndroid Build Coastguard Worker 
NextHeader() const93*d9f75844SAndroid Build Coastguard Worker   absl::optional<RTPHeader> NextHeader() const override {
94*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(packet_);
95*d9f75844SAndroid Build Coastguard Worker     return packet_->header;
96*d9f75844SAndroid Build Coastguard Worker   }
97*d9f75844SAndroid Build Coastguard Worker 
98*d9f75844SAndroid Build Coastguard Worker  private:
FuzzHeader()99*d9f75844SAndroid Build Coastguard Worker   void FuzzHeader() {
100*d9f75844SAndroid Build Coastguard Worker     constexpr size_t kNumBytesToFuzz = 11;
101*d9f75844SAndroid Build Coastguard Worker     if (data_ix_ + kNumBytesToFuzz > data_.size()) {
102*d9f75844SAndroid Build Coastguard Worker       ended_ = true;
103*d9f75844SAndroid Build Coastguard Worker       return;
104*d9f75844SAndroid Build Coastguard Worker     }
105*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(packet_);
106*d9f75844SAndroid Build Coastguard Worker     const size_t start_ix = data_ix_;
107*d9f75844SAndroid Build Coastguard Worker     packet_->header.payloadType =
108*d9f75844SAndroid Build Coastguard Worker         ByteReader<uint8_t>::ReadLittleEndian(&data_[data_ix_]);
109*d9f75844SAndroid Build Coastguard Worker     packet_->header.payloadType &= 0x7F;
110*d9f75844SAndroid Build Coastguard Worker     data_ix_ += sizeof(uint8_t);
111*d9f75844SAndroid Build Coastguard Worker     packet_->header.sequenceNumber =
112*d9f75844SAndroid Build Coastguard Worker         ByteReader<uint16_t>::ReadLittleEndian(&data_[data_ix_]);
113*d9f75844SAndroid Build Coastguard Worker     data_ix_ += sizeof(uint16_t);
114*d9f75844SAndroid Build Coastguard Worker     packet_->header.timestamp =
115*d9f75844SAndroid Build Coastguard Worker         ByteReader<uint32_t>::ReadLittleEndian(&data_[data_ix_]);
116*d9f75844SAndroid Build Coastguard Worker     data_ix_ += sizeof(uint32_t);
117*d9f75844SAndroid Build Coastguard Worker     packet_->header.ssrc =
118*d9f75844SAndroid Build Coastguard Worker         ByteReader<uint32_t>::ReadLittleEndian(&data_[data_ix_]);
119*d9f75844SAndroid Build Coastguard Worker     data_ix_ += sizeof(uint32_t);
120*d9f75844SAndroid Build Coastguard Worker     RTC_CHECK_EQ(data_ix_ - start_ix, kNumBytesToFuzz);
121*d9f75844SAndroid Build Coastguard Worker   }
122*d9f75844SAndroid Build Coastguard Worker 
MaybeFuzzPayload()123*d9f75844SAndroid Build Coastguard Worker   void MaybeFuzzPayload() {
124*d9f75844SAndroid Build Coastguard Worker     // Read one byte of fuzz data to determine how many payload bytes to fuzz.
125*d9f75844SAndroid Build Coastguard Worker     if (data_ix_ + 1 > data_.size()) {
126*d9f75844SAndroid Build Coastguard Worker       ended_ = true;
127*d9f75844SAndroid Build Coastguard Worker       return;
128*d9f75844SAndroid Build Coastguard Worker     }
129*d9f75844SAndroid Build Coastguard Worker     size_t bytes_to_fuzz = data_[data_ix_++];
130*d9f75844SAndroid Build Coastguard Worker 
131*d9f75844SAndroid Build Coastguard Worker     // Restrict number of bytes to fuzz to 16; a reasonably low number enough to
132*d9f75844SAndroid Build Coastguard Worker     // cover a few RED headers. Also don't write outside the payload length.
133*d9f75844SAndroid Build Coastguard Worker     bytes_to_fuzz = std::min(bytes_to_fuzz % 16, packet_->payload.size());
134*d9f75844SAndroid Build Coastguard Worker 
135*d9f75844SAndroid Build Coastguard Worker     if (bytes_to_fuzz == 0)
136*d9f75844SAndroid Build Coastguard Worker       return;
137*d9f75844SAndroid Build Coastguard Worker 
138*d9f75844SAndroid Build Coastguard Worker     if (data_ix_ + bytes_to_fuzz > data_.size()) {
139*d9f75844SAndroid Build Coastguard Worker       ended_ = true;
140*d9f75844SAndroid Build Coastguard Worker       return;
141*d9f75844SAndroid Build Coastguard Worker     }
142*d9f75844SAndroid Build Coastguard Worker 
143*d9f75844SAndroid Build Coastguard Worker     std::memcpy(packet_->payload.data(), &data_[data_ix_], bytes_to_fuzz);
144*d9f75844SAndroid Build Coastguard Worker     data_ix_ += bytes_to_fuzz;
145*d9f75844SAndroid Build Coastguard Worker   }
146*d9f75844SAndroid Build Coastguard Worker 
147*d9f75844SAndroid Build Coastguard Worker   bool ended_ = false;
148*d9f75844SAndroid Build Coastguard Worker   rtc::ArrayView<const uint8_t> data_;
149*d9f75844SAndroid Build Coastguard Worker   size_t data_ix_ = 0;
150*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<EncodeNetEqInput> input_;
151*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<PacketData> packet_;
152*d9f75844SAndroid Build Coastguard Worker };
153*d9f75844SAndroid Build Coastguard Worker }  // namespace
154*d9f75844SAndroid Build Coastguard Worker 
FuzzOneInputTest(const uint8_t * data,size_t size)155*d9f75844SAndroid Build Coastguard Worker void FuzzOneInputTest(const uint8_t* data, size_t size) {
156*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<FuzzRtpInput> input(
157*d9f75844SAndroid Build Coastguard Worker       new FuzzRtpInput(rtc::ArrayView<const uint8_t>(data, size)));
158*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<AudioChecksum> output(new AudioChecksum);
159*d9f75844SAndroid Build Coastguard Worker   NetEqTest::Callbacks callbacks;
160*d9f75844SAndroid Build Coastguard Worker   NetEq::Config config;
161*d9f75844SAndroid Build Coastguard Worker   auto codecs = NetEqTest::StandardDecoderMap();
162*d9f75844SAndroid Build Coastguard Worker   // kPayloadType is the payload type that will be used for encoding. Verify
163*d9f75844SAndroid Build Coastguard Worker   // that it is included in the standard decoder map, and that it points to the
164*d9f75844SAndroid Build Coastguard Worker   // expected decoder type.
165*d9f75844SAndroid Build Coastguard Worker   const auto it = codecs.find(kPayloadType);
166*d9f75844SAndroid Build Coastguard Worker   RTC_CHECK(it != codecs.end());
167*d9f75844SAndroid Build Coastguard Worker   RTC_CHECK(it->second == SdpAudioFormat("L16", 32000, 1));
168*d9f75844SAndroid Build Coastguard Worker 
169*d9f75844SAndroid Build Coastguard Worker   NetEqTest test(config, CreateBuiltinAudioDecoderFactory(), codecs,
170*d9f75844SAndroid Build Coastguard Worker                  /*text_log=*/nullptr, /*neteq_factory=*/nullptr,
171*d9f75844SAndroid Build Coastguard Worker                  std::move(input), std::move(output), callbacks);
172*d9f75844SAndroid Build Coastguard Worker   test.Run();
173*d9f75844SAndroid Build Coastguard Worker }
174*d9f75844SAndroid Build Coastguard Worker 
175*d9f75844SAndroid Build Coastguard Worker }  // namespace test
176*d9f75844SAndroid Build Coastguard Worker 
FuzzOneInput(const uint8_t * data,size_t size)177*d9f75844SAndroid Build Coastguard Worker void FuzzOneInput(const uint8_t* data, size_t size) {
178*d9f75844SAndroid Build Coastguard Worker   if (size > 70000) {
179*d9f75844SAndroid Build Coastguard Worker     return;
180*d9f75844SAndroid Build Coastguard Worker   }
181*d9f75844SAndroid Build Coastguard Worker   test::FuzzOneInputTest(data, size);
182*d9f75844SAndroid Build Coastguard Worker }
183*d9f75844SAndroid Build Coastguard Worker 
184*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
185