blob: dbce10026852b82354a0f41b20f370a1c2fa77e1 [file] [log] [blame]
henrik.lundin58466f62016-10-05 02:27:42 -07001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020015#include "api/array_view.h"
Niels Möller3f651d82018-12-19 15:06:17 +010016#include "api/audio_codecs/builtin_audio_decoder_factory.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#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"
henrik.lundin58466f62016-10-05 02:27:42 -070022
23namespace webrtc {
24namespace test {
25namespace {
26constexpr int kPayloadType = 95;
27
28class SineGenerator : public EncodeNetEqInput::Generator {
29 public:
30 explicit SineGenerator(int sample_rate_hz)
31 : sample_rate_hz_(sample_rate_hz) {}
32
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
54class FuzzRtpInput : public NetEqInput {
55 public:
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
Danil Chapovalov431abd92018-06-18 12:54:17 +020069 absl::optional<int64_t> NextPacketTime() const override {
Oskar Sundbomdf0822b2017-11-16 14:02:13 +010070 return packet_->time_ms;
henrik.lundin58466f62016-10-05 02:27:42 -070071 }
72
Danil Chapovalov431abd92018-06-18 12:54:17 +020073 absl::optional<int64_t> NextOutputEventTime() const override {
henrik.lundin58466f62016-10-05 02:27:42 -070074 return input_->NextOutputEventTime();
75 }
76
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
85 void AdvanceOutputEvent() override { return input_->AdvanceOutputEvent(); }
86
87 bool ended() const override { return ended_; }
88
Danil Chapovalov431abd92018-06-18 12:54:17 +020089 absl::optional<RTPHeader> NextHeader() const override {
henrik.lundin58466f62016-10-05 02:27:42 -070090 RTC_DCHECK(packet_);
Oskar Sundbomdf0822b2017-11-16 14:02:13 +010091 return packet_->header;
henrik.lundin58466f62016-10-05 02:27:42 -070092 }
93
94 private:
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_;
henrik.lundin246ef3e2017-04-24 09:14:32 -0700103 packet_->header.payloadType =
henrik.lundin58466f62016-10-05 02:27:42 -0700104 ByteReader<uint8_t>::ReadLittleEndian(&data_[data_ix_]);
henrik.lundin246ef3e2017-04-24 09:14:32 -0700105 packet_->header.payloadType &= 0x7F;
henrik.lundin58466f62016-10-05 02:27:42 -0700106 data_ix_ += sizeof(uint8_t);
henrik.lundin246ef3e2017-04-24 09:14:32 -0700107 packet_->header.sequenceNumber =
henrik.lundin58466f62016-10-05 02:27:42 -0700108 ByteReader<uint16_t>::ReadLittleEndian(&data_[data_ix_]);
109 data_ix_ += sizeof(uint16_t);
henrik.lundin246ef3e2017-04-24 09:14:32 -0700110 packet_->header.timestamp =
henrik.lundin58466f62016-10-05 02:27:42 -0700111 ByteReader<uint32_t>::ReadLittleEndian(&data_[data_ix_]);
112 data_ix_ += sizeof(uint32_t);
henrik.lundin246ef3e2017-04-24 09:14:32 -0700113 packet_->header.ssrc =
henrik.lundin58466f62016-10-05 02:27:42 -0700114 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
127void 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);
henrik.lundin02739d92017-05-04 06:09:06 -0700131 NetEqTest::Callbacks callbacks;
henrik.lundin58466f62016-10-05 02:27:42 -0700132 NetEq::Config config;
Henrik Lundin7687ad52018-07-02 10:14:46 +0200133 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.
Niels Möller05543682019-01-10 16:55:06 +0100137 const auto it = codecs.find(kPayloadType);
138 RTC_CHECK(it != codecs.end());
Niels Möller5d7cf3d2019-01-14 12:51:19 +0100139 RTC_CHECK(it->second == SdpAudioFormat("L16", 32000, 1));
Henrik Lundin7687ad52018-07-02 10:14:46 +0200140
Niels Möllerbd6dee82019-01-02 09:39:47 +0100141 NetEqTest test(config, CreateBuiltinAudioDecoderFactory(), codecs, nullptr,
142 std::move(input), std::move(output), callbacks);
henrik.lundin58466f62016-10-05 02:27:42 -0700143 test.Run();
144}
145
146} // namespace test
147
148void FuzzOneInput(const uint8_t* data, size_t size) {
Henrik Lundine17339b2019-03-27 15:18:15 +0100149 if (size > 70000) {
Sam Zackrisson26204702018-10-25 13:46:26 +0200150 return;
151 }
henrik.lundin58466f62016-10-05 02:27:42 -0700152 test::FuzzOneInputTest(data, size);
153}
154
155} // namespace webrtc