• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2016 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 <cmath>
12 #include <memory>
13 #include <vector>
14 
15 #include "api/array_view.h"
16 #include "api/audio_codecs/builtin_audio_decoder_factory.h"
17 #include "modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.h"
18 #include "modules/audio_coding/neteq/tools/audio_checksum.h"
19 #include "modules/audio_coding/neteq/tools/encode_neteq_input.h"
20 #include "modules/audio_coding/neteq/tools/neteq_test.h"
21 #include "modules/rtp_rtcp/source/byte_io.h"
22 
23 namespace webrtc {
24 namespace test {
25 namespace {
26 constexpr int kPayloadType = 95;
27 
28 class SineGenerator : public EncodeNetEqInput::Generator {
29  public:
SineGenerator(int sample_rate_hz)30   explicit SineGenerator(int sample_rate_hz)
31       : sample_rate_hz_(sample_rate_hz) {}
32 
Generate(size_t num_samples)33   rtc::ArrayView<const int16_t> Generate(size_t num_samples) override {
34     if (samples_.size() < num_samples) {
35       samples_.resize(num_samples);
36     }
37 
38     rtc::ArrayView<int16_t> output(samples_.data(), num_samples);
39     for (auto& x : output) {
40       x = static_cast<int16_t>(2000.0 * std::sin(phase_));
41       phase_ += 2 * kPi * kFreqHz / sample_rate_hz_;
42     }
43     return output;
44   }
45 
46  private:
47   static constexpr int kFreqHz = 300;  // The sinewave frequency.
48   const int sample_rate_hz_;
49   const double kPi = std::acos(-1);
50   std::vector<int16_t> samples_;
51   double phase_ = 0.0;
52 };
53 
54 class FuzzRtpInput : public NetEqInput {
55  public:
FuzzRtpInput(rtc::ArrayView<const uint8_t> data)56   explicit FuzzRtpInput(rtc::ArrayView<const uint8_t> data) : data_(data) {
57     AudioEncoderPcm16B::Config config;
58     config.payload_type = kPayloadType;
59     config.sample_rate_hz = 32000;
60     std::unique_ptr<AudioEncoder> encoder(new AudioEncoderPcm16B(config));
61     std::unique_ptr<EncodeNetEqInput::Generator> generator(
62         new SineGenerator(config.sample_rate_hz));
63     input_.reset(new EncodeNetEqInput(std::move(generator), std::move(encoder),
64                                       std::numeric_limits<int64_t>::max()));
65     packet_ = input_->PopPacket();
66     FuzzHeader();
67   }
68 
NextPacketTime() const69   absl::optional<int64_t> NextPacketTime() const override {
70     return packet_->time_ms;
71   }
72 
NextOutputEventTime() const73   absl::optional<int64_t> NextOutputEventTime() const override {
74     return input_->NextOutputEventTime();
75   }
76 
PopPacket()77   std::unique_ptr<PacketData> PopPacket() override {
78     RTC_DCHECK(packet_);
79     std::unique_ptr<PacketData> packet_to_return = std::move(packet_);
80     packet_ = input_->PopPacket();
81     FuzzHeader();
82     return packet_to_return;
83   }
84 
AdvanceOutputEvent()85   void AdvanceOutputEvent() override { return input_->AdvanceOutputEvent(); }
86 
ended() const87   bool ended() const override { return ended_; }
88 
NextHeader() const89   absl::optional<RTPHeader> NextHeader() const override {
90     RTC_DCHECK(packet_);
91     return packet_->header;
92   }
93 
94  private:
FuzzHeader()95   void FuzzHeader() {
96     constexpr size_t kNumBytesToFuzz = 11;
97     if (data_ix_ + kNumBytesToFuzz > data_.size()) {
98       ended_ = true;
99       return;
100     }
101     RTC_DCHECK(packet_);
102     const size_t start_ix = data_ix_;
103     packet_->header.payloadType =
104         ByteReader<uint8_t>::ReadLittleEndian(&data_[data_ix_]);
105     packet_->header.payloadType &= 0x7F;
106     data_ix_ += sizeof(uint8_t);
107     packet_->header.sequenceNumber =
108         ByteReader<uint16_t>::ReadLittleEndian(&data_[data_ix_]);
109     data_ix_ += sizeof(uint16_t);
110     packet_->header.timestamp =
111         ByteReader<uint32_t>::ReadLittleEndian(&data_[data_ix_]);
112     data_ix_ += sizeof(uint32_t);
113     packet_->header.ssrc =
114         ByteReader<uint32_t>::ReadLittleEndian(&data_[data_ix_]);
115     data_ix_ += sizeof(uint32_t);
116     RTC_CHECK_EQ(data_ix_ - start_ix, kNumBytesToFuzz);
117   }
118 
119   bool ended_ = false;
120   rtc::ArrayView<const uint8_t> data_;
121   size_t data_ix_ = 0;
122   std::unique_ptr<EncodeNetEqInput> input_;
123   std::unique_ptr<PacketData> packet_;
124 };
125 }  // namespace
126 
FuzzOneInputTest(const uint8_t * data,size_t size)127 void FuzzOneInputTest(const uint8_t* data, size_t size) {
128   std::unique_ptr<FuzzRtpInput> input(
129       new FuzzRtpInput(rtc::ArrayView<const uint8_t>(data, size)));
130   std::unique_ptr<AudioChecksum> output(new AudioChecksum);
131   NetEqTest::Callbacks callbacks;
132   NetEq::Config config;
133   auto codecs = NetEqTest::StandardDecoderMap();
134   // kPayloadType is the payload type that will be used for encoding. Verify
135   // that it is included in the standard decoder map, and that it points to the
136   // expected decoder type.
137   const auto it = codecs.find(kPayloadType);
138   RTC_CHECK(it != codecs.end());
139   RTC_CHECK(it->second == SdpAudioFormat("L16", 32000, 1));
140 
141   NetEqTest test(config, CreateBuiltinAudioDecoderFactory(), codecs,
142                  /*text_log=*/nullptr, /*neteq_factory=*/nullptr,
143                  std::move(input), std::move(output), callbacks);
144   test.Run();
145 }
146 
147 }  // namespace test
148 
FuzzOneInput(const uint8_t * data,size_t size)149 void FuzzOneInput(const uint8_t* data, size_t size) {
150   if (size > 70000) {
151     return;
152   }
153   test::FuzzOneInputTest(data, size);
154 }
155 
156 }  // namespace webrtc
157