blob: 598ffd76f3add81acc3e266f56abb38005e11ff3 [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
11#include "webrtc/modules/audio_coding/neteq/tools/neteq_test.h"
12
13#include <iostream>
14
kwiberg087bd342017-02-10 08:15:44 -080015#include "webrtc/api/audio_codecs/builtin_audio_decoder_factory.h"
henrik.lundine8a77e32016-06-22 06:34:03 -070016
17namespace webrtc {
18namespace test {
19
20void DefaultNetEqTestErrorCallback::OnInsertPacketError(
henrik.lundine8a77e32016-06-22 06:34:03 -070021 const NetEqInput::PacketData& packet) {
Henrik Lundinc417d9e2017-06-14 12:29:03 +020022 std::cerr << "InsertPacket returned an error." << std::endl;
henrik.lundin7a38fd22017-04-28 01:35:53 -070023 std::cerr << "Packet data: " << packet.ToString() << std::endl;
henrik.lundine8a77e32016-06-22 06:34:03 -070024 FATAL();
25}
26
Henrik Lundinc417d9e2017-06-14 12:29:03 +020027void DefaultNetEqTestErrorCallback::OnGetAudioError() {
28 std::cerr << "GetAudio returned an error." << std::endl;
henrik.lundine8a77e32016-06-22 06:34:03 -070029 FATAL();
30}
31
32NetEqTest::NetEqTest(const NetEq::Config& config,
33 const DecoderMap& codecs,
34 const ExtDecoderMap& ext_codecs,
35 std::unique_ptr<NetEqInput> input,
36 std::unique_ptr<AudioSink> output,
henrik.lundin02739d92017-05-04 06:09:06 -070037 Callbacks callbacks)
henrik.lundine8a77e32016-06-22 06:34:03 -070038 : neteq_(NetEq::Create(config, CreateBuiltinAudioDecoderFactory())),
39 input_(std::move(input)),
40 output_(std::move(output)),
henrik.lundin02739d92017-05-04 06:09:06 -070041 callbacks_(callbacks),
henrik.lundine8a77e32016-06-22 06:34:03 -070042 sample_rate_hz_(config.sample_rate_hz) {
43 RTC_CHECK(!config.enable_muted_state)
44 << "The code does not handle enable_muted_state";
45 RegisterDecoders(codecs);
46 RegisterExternalDecoders(ext_codecs);
47}
48
49int64_t NetEqTest::Run() {
50 const int64_t start_time_ms = *input_->NextEventTime();
51 int64_t time_now_ms = start_time_ms;
52
53 while (!input_->ended()) {
54 // Advance time to next event.
55 RTC_DCHECK(input_->NextEventTime());
56 time_now_ms = *input_->NextEventTime();
57 // Check if it is time to insert packet.
58 if (input_->NextPacketTime() && time_now_ms >= *input_->NextPacketTime()) {
59 std::unique_ptr<NetEqInput::PacketData> packet_data = input_->PopPacket();
60 RTC_CHECK(packet_data);
61 int error = neteq_->InsertPacket(
henrik.lundin246ef3e2017-04-24 09:14:32 -070062 packet_data->header,
henrik.lundine8a77e32016-06-22 06:34:03 -070063 rtc::ArrayView<const uint8_t>(packet_data->payload),
64 static_cast<uint32_t>(packet_data->time_ms * sample_rate_hz_ / 1000));
henrik.lundin02739d92017-05-04 06:09:06 -070065 if (error != NetEq::kOK && callbacks_.error_callback) {
Henrik Lundinc417d9e2017-06-14 12:29:03 +020066 callbacks_.error_callback->OnInsertPacketError(*packet_data);
henrik.lundin02739d92017-05-04 06:09:06 -070067 }
68 if (callbacks_.post_insert_packet) {
69 callbacks_.post_insert_packet->AfterInsertPacket(*packet_data,
70 neteq_.get());
henrik.lundine8a77e32016-06-22 06:34:03 -070071 }
72 }
73
74 // Check if it is time to get output audio.
75 if (input_->NextOutputEventTime() &&
76 time_now_ms >= *input_->NextOutputEventTime()) {
henrik.lundin02739d92017-05-04 06:09:06 -070077 if (callbacks_.get_audio_callback) {
78 callbacks_.get_audio_callback->BeforeGetAudio(neteq_.get());
79 }
henrik.lundine8a77e32016-06-22 06:34:03 -070080 AudioFrame out_frame;
81 bool muted;
82 int error = neteq_->GetAudio(&out_frame, &muted);
83 RTC_CHECK(!muted) << "The code does not handle enable_muted_state";
84 if (error != NetEq::kOK) {
henrik.lundin02739d92017-05-04 06:09:06 -070085 if (callbacks_.error_callback) {
Henrik Lundinc417d9e2017-06-14 12:29:03 +020086 callbacks_.error_callback->OnGetAudioError();
henrik.lundine8a77e32016-06-22 06:34:03 -070087 }
88 } else {
89 sample_rate_hz_ = out_frame.sample_rate_hz_;
90 }
henrik.lundin02739d92017-05-04 06:09:06 -070091 if (callbacks_.get_audio_callback) {
92 callbacks_.get_audio_callback->AfterGetAudio(time_now_ms, out_frame,
93 muted, neteq_.get());
94 }
henrik.lundine8a77e32016-06-22 06:34:03 -070095
96 if (output_) {
97 RTC_CHECK(output_->WriteArray(
yujo36b1a5f2017-06-12 12:45:32 -070098 out_frame.data(),
henrik.lundine8a77e32016-06-22 06:34:03 -070099 out_frame.samples_per_channel_ * out_frame.num_channels_));
100 }
101
102 input_->AdvanceOutputEvent();
103 }
104 }
105 return time_now_ms - start_time_ms;
106}
107
108NetEqNetworkStatistics NetEqTest::SimulationStats() {
109 NetEqNetworkStatistics stats;
110 RTC_CHECK_EQ(neteq_->NetworkStatistics(&stats), 0);
111 return stats;
112}
113
114void NetEqTest::RegisterDecoders(const DecoderMap& codecs) {
115 for (const auto& c : codecs) {
116 RTC_CHECK_EQ(
117 neteq_->RegisterPayloadType(c.second.first, c.second.second, c.first),
118 NetEq::kOK)
119 << "Cannot register " << c.second.second << " to payload type "
120 << c.first;
121 }
122}
123
124void NetEqTest::RegisterExternalDecoders(const ExtDecoderMap& codecs) {
125 for (const auto& c : codecs) {
126 RTC_CHECK_EQ(
127 neteq_->RegisterExternalDecoder(c.second.decoder, c.second.codec,
128 c.second.codec_name, c.first),
129 NetEq::kOK)
130 << "Cannot register " << c.second.codec_name << " to payload type "
131 << c.first;
132 }
133}
134
135} // namespace test
136} // namespace webrtc