blob: fdd1b24bd695ca64f0074516988b792e24a7a456 [file] [log] [blame]
henrik.lundine8a77e32016-06-22 06:34:03 -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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/audio_coding/neteq/tools/neteq_test.h"
henrik.lundine8a77e32016-06-22 06:34:03 -070012
13#include <iostream>
14
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020015#include "api/audio_codecs/builtin_audio_decoder_factory.h"
henrik.lundine8a77e32016-06-22 06:34:03 -070016
17namespace webrtc {
18namespace test {
Ivo Creusen55de08e2018-09-03 11:49:27 +020019namespace {
20
21absl::optional<Operations> ActionToOperations(
22 absl::optional<NetEqSimulator::Action> a) {
23 if (!a) {
24 return absl::nullopt;
25 }
26 switch (*a) {
27 case NetEqSimulator::Action::kAccelerate:
28 return absl::make_optional(kAccelerate);
29 case NetEqSimulator::Action::kExpand:
30 return absl::make_optional(kExpand);
31 case NetEqSimulator::Action::kNormal:
32 return absl::make_optional(kNormal);
33 case NetEqSimulator::Action::kPreemptiveExpand:
34 return absl::make_optional(kPreemptiveExpand);
35 }
36}
37
38} // namespace
henrik.lundine8a77e32016-06-22 06:34:03 -070039
40void DefaultNetEqTestErrorCallback::OnInsertPacketError(
henrik.lundine8a77e32016-06-22 06:34:03 -070041 const NetEqInput::PacketData& packet) {
Henrik Lundinc417d9e2017-06-14 12:29:03 +020042 std::cerr << "InsertPacket returned an error." << std::endl;
henrik.lundin7a38fd22017-04-28 01:35:53 -070043 std::cerr << "Packet data: " << packet.ToString() << std::endl;
henrik.lundine8a77e32016-06-22 06:34:03 -070044 FATAL();
45}
46
Henrik Lundinc417d9e2017-06-14 12:29:03 +020047void DefaultNetEqTestErrorCallback::OnGetAudioError() {
48 std::cerr << "GetAudio returned an error." << std::endl;
henrik.lundine8a77e32016-06-22 06:34:03 -070049 FATAL();
50}
51
52NetEqTest::NetEqTest(const NetEq::Config& config,
53 const DecoderMap& codecs,
54 const ExtDecoderMap& ext_codecs,
55 std::unique_ptr<NetEqInput> input,
56 std::unique_ptr<AudioSink> output,
henrik.lundin02739d92017-05-04 06:09:06 -070057 Callbacks callbacks)
henrik.lundine8a77e32016-06-22 06:34:03 -070058 : neteq_(NetEq::Create(config, CreateBuiltinAudioDecoderFactory())),
59 input_(std::move(input)),
60 output_(std::move(output)),
henrik.lundin02739d92017-05-04 06:09:06 -070061 callbacks_(callbacks),
henrik.lundine8a77e32016-06-22 06:34:03 -070062 sample_rate_hz_(config.sample_rate_hz) {
63 RTC_CHECK(!config.enable_muted_state)
64 << "The code does not handle enable_muted_state";
65 RegisterDecoders(codecs);
66 RegisterExternalDecoders(ext_codecs);
67}
68
Mirko Bonadei682aac52018-07-20 13:59:20 +020069NetEqTest::~NetEqTest() = default;
70
henrik.lundine8a77e32016-06-22 06:34:03 -070071int64_t NetEqTest::Run() {
Ivo Creusen55de08e2018-09-03 11:49:27 +020072 int64_t simulation_time = 0;
73 SimulationStepResult step_result;
74 do {
75 step_result = RunToNextGetAudio();
76 simulation_time += step_result.simulation_step_ms;
77 } while (!step_result.is_simulation_finished);
78 if (callbacks_.simulation_ended_callback) {
79 callbacks_.simulation_ended_callback->SimulationEnded(simulation_time);
80 }
81 return simulation_time;
82}
83
84NetEqTest::SimulationStepResult NetEqTest::RunToNextGetAudio() {
85 SimulationStepResult result;
henrik.lundine8a77e32016-06-22 06:34:03 -070086 const int64_t start_time_ms = *input_->NextEventTime();
87 int64_t time_now_ms = start_time_ms;
Ivo Creusen4384f532018-09-07 17:19:56 +020088 current_state_.packet_iat_ms.clear();
henrik.lundine8a77e32016-06-22 06:34:03 -070089
90 while (!input_->ended()) {
91 // Advance time to next event.
92 RTC_DCHECK(input_->NextEventTime());
93 time_now_ms = *input_->NextEventTime();
94 // Check if it is time to insert packet.
95 if (input_->NextPacketTime() && time_now_ms >= *input_->NextPacketTime()) {
96 std::unique_ptr<NetEqInput::PacketData> packet_data = input_->PopPacket();
97 RTC_CHECK(packet_data);
Minyue Li1a800182018-09-12 12:52:48 +020098 const size_t payload_data_length =
99 packet_data->payload.size() - packet_data->header.paddingLength;
100 if (payload_data_length != 0) {
101 int error = neteq_->InsertPacket(
102 packet_data->header,
103 rtc::ArrayView<const uint8_t>(packet_data->payload),
104 static_cast<uint32_t>(packet_data->time_ms * sample_rate_hz_ /
105 1000));
106 if (error != NetEq::kOK && callbacks_.error_callback) {
107 callbacks_.error_callback->OnInsertPacketError(*packet_data);
108 }
109 if (callbacks_.post_insert_packet) {
110 callbacks_.post_insert_packet->AfterInsertPacket(*packet_data,
111 neteq_.get());
112 }
113 } else {
114 neteq_->InsertEmptyPacket(packet_data->header);
henrik.lundine8a77e32016-06-22 06:34:03 -0700115 }
Ivo Creusen4384f532018-09-07 17:19:56 +0200116 if (last_packet_time_ms_) {
117 current_state_.packet_iat_ms.push_back(time_now_ms -
118 *last_packet_time_ms_);
119 }
120 last_packet_time_ms_ = absl::make_optional<int>(time_now_ms);
henrik.lundine8a77e32016-06-22 06:34:03 -0700121 }
122
123 // Check if it is time to get output audio.
124 if (input_->NextOutputEventTime() &&
125 time_now_ms >= *input_->NextOutputEventTime()) {
henrik.lundin02739d92017-05-04 06:09:06 -0700126 if (callbacks_.get_audio_callback) {
127 callbacks_.get_audio_callback->BeforeGetAudio(neteq_.get());
128 }
henrik.lundine8a77e32016-06-22 06:34:03 -0700129 AudioFrame out_frame;
130 bool muted;
Ivo Creusen55de08e2018-09-03 11:49:27 +0200131 int error = neteq_->GetAudio(&out_frame, &muted,
132 ActionToOperations(next_action_));
133 next_action_ = absl::nullopt;
henrik.lundine8a77e32016-06-22 06:34:03 -0700134 RTC_CHECK(!muted) << "The code does not handle enable_muted_state";
135 if (error != NetEq::kOK) {
henrik.lundin02739d92017-05-04 06:09:06 -0700136 if (callbacks_.error_callback) {
Henrik Lundinc417d9e2017-06-14 12:29:03 +0200137 callbacks_.error_callback->OnGetAudioError();
henrik.lundine8a77e32016-06-22 06:34:03 -0700138 }
139 } else {
140 sample_rate_hz_ = out_frame.sample_rate_hz_;
141 }
henrik.lundin02739d92017-05-04 06:09:06 -0700142 if (callbacks_.get_audio_callback) {
143 callbacks_.get_audio_callback->AfterGetAudio(time_now_ms, out_frame,
144 muted, neteq_.get());
145 }
henrik.lundine8a77e32016-06-22 06:34:03 -0700146
147 if (output_) {
148 RTC_CHECK(output_->WriteArray(
yujo36b1a5f2017-06-12 12:45:32 -0700149 out_frame.data(),
henrik.lundine8a77e32016-06-22 06:34:03 -0700150 out_frame.samples_per_channel_ * out_frame.num_channels_));
151 }
152
153 input_->AdvanceOutputEvent();
Henrik Lundin9be77452018-09-10 12:53:27 +0200154 result.simulation_step_ms =
155 input_->NextEventTime().value_or(time_now_ms) - start_time_ms;
Ivo Creusend1c2f782018-09-13 14:39:55 +0200156 const auto operations_state = neteq_->GetOperationsAndState();
157 current_state_.current_delay_ms = operations_state.current_buffer_size_ms;
158 // TODO(ivoc): Add more accurate reporting by tracking the origin of
159 // samples in the sync buffer.
160 result.action_times_ms[Action::kExpand] = 0;
161 result.action_times_ms[Action::kAccelerate] = 0;
162 result.action_times_ms[Action::kPreemptiveExpand] = 0;
163 result.action_times_ms[Action::kNormal] = 0;
164
165 if (out_frame.speech_type_ == AudioFrame::SpeechType::kPLC ||
166 out_frame.speech_type_ == AudioFrame::SpeechType::kPLCCNG) {
167 // Consider the whole frame to be the result of expansion.
168 result.action_times_ms[Action::kExpand] = 10;
169 } else if (operations_state.accelerate_samples -
170 prev_ops_state_.accelerate_samples >
171 0) {
172 // Consider the whole frame to be the result of acceleration.
173 result.action_times_ms[Action::kAccelerate] = 10;
174 } else if (operations_state.preemptive_samples -
175 prev_ops_state_.preemptive_samples >
176 0) {
177 // Consider the whole frame to be the result of preemptive expansion.
178 result.action_times_ms[Action::kPreemptiveExpand] = 10;
179 } else {
180 // Consider the whole frame to be the result of normal playout.
181 result.action_times_ms[Action::kNormal] = 10;
182 }
Ivo Creusen55de08e2018-09-03 11:49:27 +0200183 result.is_simulation_finished = input_->ended();
Ivo Creusend1c2f782018-09-13 14:39:55 +0200184 prev_ops_state_ = operations_state;
Ivo Creusen55de08e2018-09-03 11:49:27 +0200185 return result;
henrik.lundine8a77e32016-06-22 06:34:03 -0700186 }
187 }
Henrik Lundin9be77452018-09-10 12:53:27 +0200188 result.simulation_step_ms =
189 input_->NextEventTime().value_or(time_now_ms) - start_time_ms;
Ivo Creusen55de08e2018-09-03 11:49:27 +0200190 result.is_simulation_finished = true;
191 return result;
192}
193
194void NetEqTest::SetNextAction(NetEqTest::Action next_operation) {
195 next_action_ = absl::optional<Action>(next_operation);
196}
197
198NetEqTest::NetEqState NetEqTest::GetNetEqState() {
Ivo Creusen4384f532018-09-07 17:19:56 +0200199 return current_state_;
henrik.lundine8a77e32016-06-22 06:34:03 -0700200}
201
202NetEqNetworkStatistics NetEqTest::SimulationStats() {
203 NetEqNetworkStatistics stats;
204 RTC_CHECK_EQ(neteq_->NetworkStatistics(&stats), 0);
205 return stats;
206}
207
Alex Narest7ff6ca52018-02-07 18:46:33 +0100208NetEqLifetimeStatistics NetEqTest::LifetimeStats() const {
209 return neteq_->GetLifetimeStatistics();
210}
211
Henrik Lundin7687ad52018-07-02 10:14:46 +0200212NetEqTest::DecoderMap NetEqTest::StandardDecoderMap() {
213 DecoderMap codecs = {
214 {0, std::make_pair(NetEqDecoder::kDecoderPCMu, "pcmu")},
215 {8, std::make_pair(NetEqDecoder::kDecoderPCMa, "pcma")},
216#ifdef WEBRTC_CODEC_ILBC
217 {102, std::make_pair(NetEqDecoder::kDecoderILBC, "ilbc")},
218#endif
219 {103, std::make_pair(NetEqDecoder::kDecoderISAC, "isac")},
220#if !defined(WEBRTC_ANDROID)
221 {104, std::make_pair(NetEqDecoder::kDecoderISACswb, "isac-swb")},
222#endif
223#ifdef WEBRTC_CODEC_OPUS
224 {111, std::make_pair(NetEqDecoder::kDecoderOpus, "opus")},
225#endif
226 {93, std::make_pair(NetEqDecoder::kDecoderPCM16B, "pcm16-nb")},
227 {94, std::make_pair(NetEqDecoder::kDecoderPCM16Bwb, "pcm16-wb")},
228 {95, std::make_pair(NetEqDecoder::kDecoderPCM16Bswb32kHz, "pcm16-swb32")},
229 {96, std::make_pair(NetEqDecoder::kDecoderPCM16Bswb48kHz, "pcm16-swb48")},
230 {9, std::make_pair(NetEqDecoder::kDecoderG722, "g722")},
231 {106, std::make_pair(NetEqDecoder::kDecoderAVT, "avt")},
232 {114, std::make_pair(NetEqDecoder::kDecoderAVT16kHz, "avt-16")},
233 {115, std::make_pair(NetEqDecoder::kDecoderAVT32kHz, "avt-32")},
234 {116, std::make_pair(NetEqDecoder::kDecoderAVT48kHz, "avt-48")},
235 {117, std::make_pair(NetEqDecoder::kDecoderRED, "red")},
236 {13, std::make_pair(NetEqDecoder::kDecoderCNGnb, "cng-nb")},
237 {98, std::make_pair(NetEqDecoder::kDecoderCNGwb, "cng-wb")},
238 {99, std::make_pair(NetEqDecoder::kDecoderCNGswb32kHz, "cng-swb32")},
239 {100, std::make_pair(NetEqDecoder::kDecoderCNGswb48kHz, "cng-swb48")}
240 };
241 return codecs;
242}
243
henrik.lundine8a77e32016-06-22 06:34:03 -0700244void NetEqTest::RegisterDecoders(const DecoderMap& codecs) {
245 for (const auto& c : codecs) {
246 RTC_CHECK_EQ(
247 neteq_->RegisterPayloadType(c.second.first, c.second.second, c.first),
248 NetEq::kOK)
249 << "Cannot register " << c.second.second << " to payload type "
250 << c.first;
251 }
252}
253
254void NetEqTest::RegisterExternalDecoders(const ExtDecoderMap& codecs) {
255 for (const auto& c : codecs) {
256 RTC_CHECK_EQ(
257 neteq_->RegisterExternalDecoder(c.second.decoder, c.second.codec,
258 c.second.codec_name, c.first),
259 NetEq::kOK)
260 << "Cannot register " << c.second.codec_name << " to payload type "
261 << c.first;
262 }
263}
264
265} // namespace test
266} // namespace webrtc