blob: be1dd418fc2e437ee1dd7f65311bc085d3b07aee [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
Ivo Creusen2db46b02018-12-14 16:49:12 +010013#include <iomanip>
henrik.lundine8a77e32016-06-22 06:34:03 -070014#include <iostream>
15
Ivo Creusen2db46b02018-12-14 16:49:12 +010016#include "modules/rtp_rtcp/source/byte_io.h"
henrik.lundine8a77e32016-06-22 06:34:03 -070017
18namespace webrtc {
19namespace test {
Ivo Creusen55de08e2018-09-03 11:49:27 +020020namespace {
21
22absl::optional<Operations> ActionToOperations(
23 absl::optional<NetEqSimulator::Action> a) {
24 if (!a) {
25 return absl::nullopt;
26 }
27 switch (*a) {
28 case NetEqSimulator::Action::kAccelerate:
29 return absl::make_optional(kAccelerate);
30 case NetEqSimulator::Action::kExpand:
31 return absl::make_optional(kExpand);
32 case NetEqSimulator::Action::kNormal:
33 return absl::make_optional(kNormal);
34 case NetEqSimulator::Action::kPreemptiveExpand:
35 return absl::make_optional(kPreemptiveExpand);
36 }
37}
38
39} // namespace
henrik.lundine8a77e32016-06-22 06:34:03 -070040
41void DefaultNetEqTestErrorCallback::OnInsertPacketError(
henrik.lundine8a77e32016-06-22 06:34:03 -070042 const NetEqInput::PacketData& packet) {
Henrik Lundinc417d9e2017-06-14 12:29:03 +020043 std::cerr << "InsertPacket returned an error." << std::endl;
henrik.lundin7a38fd22017-04-28 01:35:53 -070044 std::cerr << "Packet data: " << packet.ToString() << std::endl;
henrik.lundine8a77e32016-06-22 06:34:03 -070045 FATAL();
46}
47
Henrik Lundinc417d9e2017-06-14 12:29:03 +020048void DefaultNetEqTestErrorCallback::OnGetAudioError() {
49 std::cerr << "GetAudio returned an error." << std::endl;
henrik.lundine8a77e32016-06-22 06:34:03 -070050 FATAL();
51}
52
53NetEqTest::NetEqTest(const NetEq::Config& config,
Niels Möller3f651d82018-12-19 15:06:17 +010054 rtc::scoped_refptr<AudioDecoderFactory> decoder_factory,
henrik.lundine8a77e32016-06-22 06:34:03 -070055 const DecoderMap& codecs,
Ivo Creusen2db46b02018-12-14 16:49:12 +010056 std::unique_ptr<std::ofstream> text_log,
henrik.lundine8a77e32016-06-22 06:34:03 -070057 std::unique_ptr<NetEqInput> input,
58 std::unique_ptr<AudioSink> output,
henrik.lundin02739d92017-05-04 06:09:06 -070059 Callbacks callbacks)
Niels Möller3f651d82018-12-19 15:06:17 +010060 : neteq_(NetEq::Create(config, decoder_factory)),
henrik.lundine8a77e32016-06-22 06:34:03 -070061 input_(std::move(input)),
62 output_(std::move(output)),
henrik.lundin02739d92017-05-04 06:09:06 -070063 callbacks_(callbacks),
Ivo Creusen2db46b02018-12-14 16:49:12 +010064 sample_rate_hz_(config.sample_rate_hz),
65 text_log_(std::move(text_log)) {
henrik.lundine8a77e32016-06-22 06:34:03 -070066 RTC_CHECK(!config.enable_muted_state)
67 << "The code does not handle enable_muted_state";
68 RegisterDecoders(codecs);
henrik.lundine8a77e32016-06-22 06:34:03 -070069}
70
Mirko Bonadei682aac52018-07-20 13:59:20 +020071NetEqTest::~NetEqTest() = default;
72
henrik.lundine8a77e32016-06-22 06:34:03 -070073int64_t NetEqTest::Run() {
Ivo Creusen55de08e2018-09-03 11:49:27 +020074 int64_t simulation_time = 0;
75 SimulationStepResult step_result;
76 do {
77 step_result = RunToNextGetAudio();
78 simulation_time += step_result.simulation_step_ms;
79 } while (!step_result.is_simulation_finished);
80 if (callbacks_.simulation_ended_callback) {
81 callbacks_.simulation_ended_callback->SimulationEnded(simulation_time);
82 }
83 return simulation_time;
84}
85
86NetEqTest::SimulationStepResult NetEqTest::RunToNextGetAudio() {
87 SimulationStepResult result;
henrik.lundine8a77e32016-06-22 06:34:03 -070088 const int64_t start_time_ms = *input_->NextEventTime();
89 int64_t time_now_ms = start_time_ms;
Ivo Creusen4384f532018-09-07 17:19:56 +020090 current_state_.packet_iat_ms.clear();
henrik.lundine8a77e32016-06-22 06:34:03 -070091
92 while (!input_->ended()) {
93 // Advance time to next event.
94 RTC_DCHECK(input_->NextEventTime());
95 time_now_ms = *input_->NextEventTime();
96 // Check if it is time to insert packet.
97 if (input_->NextPacketTime() && time_now_ms >= *input_->NextPacketTime()) {
98 std::unique_ptr<NetEqInput::PacketData> packet_data = input_->PopPacket();
99 RTC_CHECK(packet_data);
Minyue Li1a800182018-09-12 12:52:48 +0200100 const size_t payload_data_length =
101 packet_data->payload.size() - packet_data->header.paddingLength;
102 if (payload_data_length != 0) {
103 int error = neteq_->InsertPacket(
104 packet_data->header,
105 rtc::ArrayView<const uint8_t>(packet_data->payload),
106 static_cast<uint32_t>(packet_data->time_ms * sample_rate_hz_ /
107 1000));
108 if (error != NetEq::kOK && callbacks_.error_callback) {
109 callbacks_.error_callback->OnInsertPacketError(*packet_data);
110 }
111 if (callbacks_.post_insert_packet) {
112 callbacks_.post_insert_packet->AfterInsertPacket(*packet_data,
113 neteq_.get());
114 }
115 } else {
116 neteq_->InsertEmptyPacket(packet_data->header);
henrik.lundine8a77e32016-06-22 06:34:03 -0700117 }
Ivo Creusen4384f532018-09-07 17:19:56 +0200118 if (last_packet_time_ms_) {
119 current_state_.packet_iat_ms.push_back(time_now_ms -
120 *last_packet_time_ms_);
121 }
Ivo Creusen2db46b02018-12-14 16:49:12 +0100122 if (text_log_) {
123 const auto ops_state = neteq_->GetOperationsAndState();
124 const auto delta_wallclock =
125 last_packet_time_ms_ ? (time_now_ms - *last_packet_time_ms_) : -1;
126 const auto delta_timestamp =
127 last_packet_timestamp_
128 ? (static_cast<int64_t>(packet_data->header.timestamp) -
129 *last_packet_timestamp_) *
130 1000 / sample_rate_hz_
131 : -1;
132 const auto packet_size_bytes =
133 packet_data->payload.size() == 12
134 ? ByteReader<uint32_t>::ReadLittleEndian(
135 &packet_data->payload[8])
136 : -1;
137 *text_log_ << "Packet - wallclock: " << std::setw(5) << time_now_ms
138 << ", delta wc: " << std::setw(4) << delta_wallclock
Jakob Ivarssone98954c2019-02-06 15:37:50 +0100139 << ", seq_no: " << packet_data->header.sequenceNumber
Ivo Creusen2db46b02018-12-14 16:49:12 +0100140 << ", timestamp: " << std::setw(10)
141 << packet_data->header.timestamp
142 << ", delta ts: " << std::setw(4) << delta_timestamp
143 << ", size: " << std::setw(5) << packet_size_bytes
144 << ", frame size: " << std::setw(3)
145 << ops_state.current_frame_size_ms
146 << ", buffer size: " << std::setw(4)
147 << ops_state.current_buffer_size_ms << std::endl;
148 }
Ivo Creusen4384f532018-09-07 17:19:56 +0200149 last_packet_time_ms_ = absl::make_optional<int>(time_now_ms);
Ivo Creusen2db46b02018-12-14 16:49:12 +0100150 last_packet_timestamp_ =
151 absl::make_optional<uint32_t>(packet_data->header.timestamp);
henrik.lundine8a77e32016-06-22 06:34:03 -0700152 }
153
154 // Check if it is time to get output audio.
155 if (input_->NextOutputEventTime() &&
156 time_now_ms >= *input_->NextOutputEventTime()) {
henrik.lundin02739d92017-05-04 06:09:06 -0700157 if (callbacks_.get_audio_callback) {
158 callbacks_.get_audio_callback->BeforeGetAudio(neteq_.get());
159 }
henrik.lundine8a77e32016-06-22 06:34:03 -0700160 AudioFrame out_frame;
161 bool muted;
Ivo Creusen55de08e2018-09-03 11:49:27 +0200162 int error = neteq_->GetAudio(&out_frame, &muted,
163 ActionToOperations(next_action_));
164 next_action_ = absl::nullopt;
henrik.lundine8a77e32016-06-22 06:34:03 -0700165 RTC_CHECK(!muted) << "The code does not handle enable_muted_state";
166 if (error != NetEq::kOK) {
henrik.lundin02739d92017-05-04 06:09:06 -0700167 if (callbacks_.error_callback) {
Henrik Lundinc417d9e2017-06-14 12:29:03 +0200168 callbacks_.error_callback->OnGetAudioError();
henrik.lundine8a77e32016-06-22 06:34:03 -0700169 }
170 } else {
171 sample_rate_hz_ = out_frame.sample_rate_hz_;
172 }
henrik.lundin02739d92017-05-04 06:09:06 -0700173 if (callbacks_.get_audio_callback) {
174 callbacks_.get_audio_callback->AfterGetAudio(time_now_ms, out_frame,
175 muted, neteq_.get());
176 }
henrik.lundine8a77e32016-06-22 06:34:03 -0700177
178 if (output_) {
179 RTC_CHECK(output_->WriteArray(
yujo36b1a5f2017-06-12 12:45:32 -0700180 out_frame.data(),
henrik.lundine8a77e32016-06-22 06:34:03 -0700181 out_frame.samples_per_channel_ * out_frame.num_channels_));
182 }
183
184 input_->AdvanceOutputEvent();
Henrik Lundin9be77452018-09-10 12:53:27 +0200185 result.simulation_step_ms =
186 input_->NextEventTime().value_or(time_now_ms) - start_time_ms;
Ivo Creusend1c2f782018-09-13 14:39:55 +0200187 const auto operations_state = neteq_->GetOperationsAndState();
188 current_state_.current_delay_ms = operations_state.current_buffer_size_ms;
Ivo Creusendc6d5532018-09-27 11:43:42 +0200189 current_state_.packet_size_ms = operations_state.current_frame_size_ms;
190 current_state_.next_packet_available =
191 operations_state.next_packet_available;
192 current_state_.packet_buffer_flushed =
193 operations_state.packet_buffer_flushes >
194 prev_ops_state_.packet_buffer_flushes;
Ivo Creusend1c2f782018-09-13 14:39:55 +0200195 // TODO(ivoc): Add more accurate reporting by tracking the origin of
196 // samples in the sync buffer.
197 result.action_times_ms[Action::kExpand] = 0;
198 result.action_times_ms[Action::kAccelerate] = 0;
199 result.action_times_ms[Action::kPreemptiveExpand] = 0;
200 result.action_times_ms[Action::kNormal] = 0;
201
202 if (out_frame.speech_type_ == AudioFrame::SpeechType::kPLC ||
203 out_frame.speech_type_ == AudioFrame::SpeechType::kPLCCNG) {
204 // Consider the whole frame to be the result of expansion.
205 result.action_times_ms[Action::kExpand] = 10;
206 } else if (operations_state.accelerate_samples -
207 prev_ops_state_.accelerate_samples >
208 0) {
209 // Consider the whole frame to be the result of acceleration.
210 result.action_times_ms[Action::kAccelerate] = 10;
211 } else if (operations_state.preemptive_samples -
212 prev_ops_state_.preemptive_samples >
213 0) {
214 // Consider the whole frame to be the result of preemptive expansion.
215 result.action_times_ms[Action::kPreemptiveExpand] = 10;
216 } else {
217 // Consider the whole frame to be the result of normal playout.
218 result.action_times_ms[Action::kNormal] = 10;
219 }
Ivo Creusen2db46b02018-12-14 16:49:12 +0100220 auto lifetime_stats = LifetimeStats();
221 if (text_log_) {
222 const bool plc =
223 (out_frame.speech_type_ == AudioFrame::SpeechType::kPLC) ||
224 (out_frame.speech_type_ == AudioFrame::SpeechType::kPLCCNG);
225 const bool cng = out_frame.speech_type_ == AudioFrame::SpeechType::kCNG;
226 const bool voice_concealed =
Ivo Creusenbf4a2212019-04-24 14:06:24 +0200227 (lifetime_stats.concealed_samples -
228 lifetime_stats.silent_concealed_samples) >
229 (prev_lifetime_stats_.concealed_samples -
230 prev_lifetime_stats_.silent_concealed_samples);
Ivo Creusen2db46b02018-12-14 16:49:12 +0100231 *text_log_ << "GetAudio - wallclock: " << std::setw(5) << time_now_ms
232 << ", delta wc: " << std::setw(4)
233 << (input_->NextEventTime().value_or(time_now_ms) -
234 start_time_ms)
235 << ", CNG: " << cng << ", PLC: " << plc
236 << ", voice concealed: " << voice_concealed
237 << ", buffer size: " << std::setw(4)
238 << current_state_.current_delay_ms << std::endl;
239 if (operations_state.discarded_primary_packets >
240 prev_ops_state_.discarded_primary_packets) {
241 *text_log_ << "Discarded "
242 << (operations_state.discarded_primary_packets -
243 prev_ops_state_.discarded_primary_packets)
244 << " primary packets." << std::endl;
245 }
246 if (operations_state.packet_buffer_flushes >
247 prev_ops_state_.packet_buffer_flushes) {
248 *text_log_ << "Flushed packet buffer "
249 << (operations_state.packet_buffer_flushes -
250 prev_ops_state_.packet_buffer_flushes)
251 << " times." << std::endl;
252 }
253 }
254 prev_lifetime_stats_ = lifetime_stats;
Jakob Ivarsson9ce451a2019-05-22 16:41:22 +0200255 const bool no_more_packets_to_decode =
256 !input_->NextPacketTime() && !operations_state.next_packet_available;
257 result.is_simulation_finished =
258 no_more_packets_to_decode || input_->ended();
Ivo Creusend1c2f782018-09-13 14:39:55 +0200259 prev_ops_state_ = operations_state;
Ivo Creusen55de08e2018-09-03 11:49:27 +0200260 return result;
henrik.lundine8a77e32016-06-22 06:34:03 -0700261 }
262 }
Henrik Lundin9be77452018-09-10 12:53:27 +0200263 result.simulation_step_ms =
264 input_->NextEventTime().value_or(time_now_ms) - start_time_ms;
Ivo Creusen55de08e2018-09-03 11:49:27 +0200265 result.is_simulation_finished = true;
266 return result;
267}
268
269void NetEqTest::SetNextAction(NetEqTest::Action next_operation) {
270 next_action_ = absl::optional<Action>(next_operation);
271}
272
273NetEqTest::NetEqState NetEqTest::GetNetEqState() {
Ivo Creusen4384f532018-09-07 17:19:56 +0200274 return current_state_;
henrik.lundine8a77e32016-06-22 06:34:03 -0700275}
276
277NetEqNetworkStatistics NetEqTest::SimulationStats() {
278 NetEqNetworkStatistics stats;
279 RTC_CHECK_EQ(neteq_->NetworkStatistics(&stats), 0);
280 return stats;
281}
282
Alex Narest7ff6ca52018-02-07 18:46:33 +0100283NetEqLifetimeStatistics NetEqTest::LifetimeStats() const {
284 return neteq_->GetLifetimeStatistics();
285}
286
Henrik Lundin7687ad52018-07-02 10:14:46 +0200287NetEqTest::DecoderMap NetEqTest::StandardDecoderMap() {
288 DecoderMap codecs = {
Niels Möller05543682019-01-10 16:55:06 +0100289 {0, SdpAudioFormat("pcmu", 8000, 1)},
290 {8, SdpAudioFormat("pcma", 8000, 1)},
Henrik Lundin7687ad52018-07-02 10:14:46 +0200291#ifdef WEBRTC_CODEC_ILBC
Niels Möller05543682019-01-10 16:55:06 +0100292 {102, SdpAudioFormat("ilbc", 8000, 1)},
Henrik Lundin7687ad52018-07-02 10:14:46 +0200293#endif
Niels Möller05543682019-01-10 16:55:06 +0100294 {103, SdpAudioFormat("isac", 16000, 1)},
Henrik Lundin7687ad52018-07-02 10:14:46 +0200295#if !defined(WEBRTC_ANDROID)
Niels Möller05543682019-01-10 16:55:06 +0100296 {104, SdpAudioFormat("isac", 32000, 1)},
Henrik Lundin7687ad52018-07-02 10:14:46 +0200297#endif
298#ifdef WEBRTC_CODEC_OPUS
Niels Möller05543682019-01-10 16:55:06 +0100299 {111, SdpAudioFormat("opus", 48000, 2)},
Henrik Lundin7687ad52018-07-02 10:14:46 +0200300#endif
Niels Möller05543682019-01-10 16:55:06 +0100301 {93, SdpAudioFormat("l16", 8000, 1)},
302 {94, SdpAudioFormat("l16", 16000, 1)},
303 {95, SdpAudioFormat("l16", 32000, 1)},
304 {96, SdpAudioFormat("l16", 48000, 1)},
305 {9, SdpAudioFormat("g722", 8000, 1)},
306 {106, SdpAudioFormat("telephone-event", 8000, 1)},
307 {114, SdpAudioFormat("telephone-event", 16000, 1)},
308 {115, SdpAudioFormat("telephone-event", 32000, 1)},
309 {116, SdpAudioFormat("telephone-event", 48000, 1)},
310 {117, SdpAudioFormat("red", 8000, 1)},
311 {13, SdpAudioFormat("cn", 8000, 1)},
312 {98, SdpAudioFormat("cn", 16000, 1)},
313 {99, SdpAudioFormat("cn", 32000, 1)},
314 {100, SdpAudioFormat("cn", 48000, 1)}
Henrik Lundin7687ad52018-07-02 10:14:46 +0200315 };
316 return codecs;
317}
318
henrik.lundine8a77e32016-06-22 06:34:03 -0700319void NetEqTest::RegisterDecoders(const DecoderMap& codecs) {
320 for (const auto& c : codecs) {
Niels Möller05543682019-01-10 16:55:06 +0100321 RTC_CHECK(neteq_->RegisterPayloadType(c.first, c.second))
322 << "Cannot register " << c.second.name << " to payload type "
henrik.lundine8a77e32016-06-22 06:34:03 -0700323 << c.first;
324 }
325}
326
henrik.lundine8a77e32016-06-22 06:34:03 -0700327} // namespace test
328} // namespace webrtc