blob: c149ec1b0bc21defe9ad30cc8fb7138ee6d438e5 [file] [log] [blame]
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +00001/*
2 * Copyright (c) 2014 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/acm2/acm_receive_test.h"
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000012
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000013#include <stdio.h>
14
kwiberg16c5a962016-02-15 02:27:22 -080015#include <memory>
16
Niels Möller2edab4c2018-10-22 09:48:08 +020017#include "absl/strings/match.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "api/audio_codecs/builtin_audio_decoder_factory.h"
19#include "modules/audio_coding/codecs/audio_format_conversion.h"
20#include "modules/audio_coding/include/audio_coding_module.h"
21#include "modules/audio_coding/neteq/tools/audio_sink.h"
22#include "modules/audio_coding/neteq/tools/packet.h"
23#include "modules/audio_coding/neteq/tools/packet_source.h"
Fredrik Solenbergbbf21a32018-04-12 22:44:09 +020024#include "modules/include/module_common_types.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020025#include "test/gtest.h"
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000026
27namespace webrtc {
28namespace test {
29
30namespace {
31// Returns true if the codec should be registered, otherwise false. Changes
32// the number of channels for the Opus codec to always be 1.
33bool ModifyAndUseThisCodec(CodecInst* codec_param) {
Niels Möller2edab4c2018-10-22 09:48:08 +020034 if (absl::EqualsIgnoreCase(codec_param->plname, "CN") &&
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000035 codec_param->plfreq == 48000)
36 return false; // Skip 48 kHz comfort noise.
37
Niels Möller2edab4c2018-10-22 09:48:08 +020038 if (absl::EqualsIgnoreCase(codec_param->plname, "telephone-event"))
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000039 return false; // Skip DTFM.
40
41 return true;
42}
43
44// Remaps payload types from ACM's default to those used in the resource file
45// neteq_universal_new.rtp. Returns true if the codec should be registered,
46// otherwise false. The payload types are set as follows (all are mono codecs):
47// PCMu = 0;
48// PCMa = 8;
49// Comfort noise 8 kHz = 13
50// Comfort noise 16 kHz = 98
51// Comfort noise 32 kHz = 99
52// iLBC = 102
53// iSAC wideband = 103
54// iSAC super-wideband = 104
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000055// AVT/DTMF = 106
56// RED = 117
57// PCM16b 8 kHz = 93
58// PCM16b 16 kHz = 94
59// PCM16b 32 kHz = 95
60// G.722 = 94
61bool RemapPltypeAndUseThisCodec(const char* plname,
62 int plfreq,
Peter Kasting69558702016-01-12 16:26:35 -080063 size_t channels,
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000064 int* pltype) {
65 if (channels != 1)
66 return false; // Don't use non-mono codecs.
67
68 // Re-map pltypes to those used in the NetEq test files.
Niels Möller2edab4c2018-10-22 09:48:08 +020069 if (absl::EqualsIgnoreCase(plname, "PCMU") && plfreq == 8000) {
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000070 *pltype = 0;
Niels Möller2edab4c2018-10-22 09:48:08 +020071 } else if (absl::EqualsIgnoreCase(plname, "PCMA") && plfreq == 8000) {
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000072 *pltype = 8;
Niels Möller2edab4c2018-10-22 09:48:08 +020073 } else if (absl::EqualsIgnoreCase(plname, "CN") && plfreq == 8000) {
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000074 *pltype = 13;
Niels Möller2edab4c2018-10-22 09:48:08 +020075 } else if (absl::EqualsIgnoreCase(plname, "CN") && plfreq == 16000) {
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000076 *pltype = 98;
Niels Möller2edab4c2018-10-22 09:48:08 +020077 } else if (absl::EqualsIgnoreCase(plname, "CN") && plfreq == 32000) {
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000078 *pltype = 99;
Niels Möller2edab4c2018-10-22 09:48:08 +020079 } else if (absl::EqualsIgnoreCase(plname, "ILBC")) {
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000080 *pltype = 102;
Niels Möller2edab4c2018-10-22 09:48:08 +020081 } else if (absl::EqualsIgnoreCase(plname, "ISAC") && plfreq == 16000) {
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000082 *pltype = 103;
Niels Möller2edab4c2018-10-22 09:48:08 +020083 } else if (absl::EqualsIgnoreCase(plname, "ISAC") && plfreq == 32000) {
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000084 *pltype = 104;
Niels Möller2edab4c2018-10-22 09:48:08 +020085 } else if (absl::EqualsIgnoreCase(plname, "telephone-event") &&
86 plfreq == 8000) {
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000087 *pltype = 106;
Niels Möller2edab4c2018-10-22 09:48:08 +020088 } else if (absl::EqualsIgnoreCase(plname, "telephone-event") &&
89 plfreq == 16000) {
solenberg2779bab2016-11-17 04:45:19 -080090 *pltype = 114;
Niels Möller2edab4c2018-10-22 09:48:08 +020091 } else if (absl::EqualsIgnoreCase(plname, "telephone-event") &&
92 plfreq == 32000) {
solenberg2779bab2016-11-17 04:45:19 -080093 *pltype = 115;
Niels Möller2edab4c2018-10-22 09:48:08 +020094 } else if (absl::EqualsIgnoreCase(plname, "telephone-event") &&
95 plfreq == 48000) {
solenberg2779bab2016-11-17 04:45:19 -080096 *pltype = 116;
Niels Möller2edab4c2018-10-22 09:48:08 +020097 } else if (absl::EqualsIgnoreCase(plname, "red")) {
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000098 *pltype = 117;
Niels Möller2edab4c2018-10-22 09:48:08 +020099 } else if (absl::EqualsIgnoreCase(plname, "L16") && plfreq == 8000) {
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000100 *pltype = 93;
Niels Möller2edab4c2018-10-22 09:48:08 +0200101 } else if (absl::EqualsIgnoreCase(plname, "L16") && plfreq == 16000) {
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000102 *pltype = 94;
Niels Möller2edab4c2018-10-22 09:48:08 +0200103 } else if (absl::EqualsIgnoreCase(plname, "L16") && plfreq == 32000) {
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000104 *pltype = 95;
Niels Möller2edab4c2018-10-22 09:48:08 +0200105 } else if (absl::EqualsIgnoreCase(plname, "G722")) {
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000106 *pltype = 9;
107 } else {
108 // Don't use any other codecs.
109 return false;
110 }
111 return true;
112}
kwiberg5adaf732016-10-04 09:33:27 -0700113
114AudioCodingModule::Config MakeAcmConfig(
115 Clock* clock,
116 rtc::scoped_refptr<AudioDecoderFactory> decoder_factory) {
117 AudioCodingModule::Config config;
kwiberg5adaf732016-10-04 09:33:27 -0700118 config.clock = clock;
119 config.decoder_factory = std::move(decoder_factory);
120 return config;
121}
122
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000123} // namespace
124
125AcmReceiveTestOldApi::AcmReceiveTestOldApi(
126 PacketSource* packet_source,
127 AudioSink* audio_sink,
128 int output_freq_hz,
kwiberg5adaf732016-10-04 09:33:27 -0700129 NumOutputChannels exptected_output_channels,
130 rtc::scoped_refptr<AudioDecoderFactory> decoder_factory)
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000131 : clock_(0),
kwiberg5adaf732016-10-04 09:33:27 -0700132 acm_(webrtc::AudioCodingModule::Create(
133 MakeAcmConfig(&clock_, std::move(decoder_factory)))),
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000134 packet_source_(packet_source),
135 audio_sink_(audio_sink),
136 output_freq_hz_(output_freq_hz),
kwiberg5adaf732016-10-04 09:33:27 -0700137 exptected_output_channels_(exptected_output_channels) {}
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000138
kwibergb8e56ee2016-08-29 06:37:33 -0700139AcmReceiveTestOldApi::~AcmReceiveTestOldApi() = default;
140
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000141void AcmReceiveTestOldApi::RegisterDefaultCodecs() {
142 CodecInst my_codec_param;
143 for (int n = 0; n < acm_->NumberOfCodecs(); n++) {
144 ASSERT_EQ(0, acm_->Codec(n, &my_codec_param)) << "Failed to get codec.";
145 if (ModifyAndUseThisCodec(&my_codec_param)) {
kwibergda2bf4e2016-10-24 13:47:09 -0700146 ASSERT_EQ(true,
147 acm_->RegisterReceiveCodec(my_codec_param.pltype,
148 CodecInstToSdp(my_codec_param)))
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000149 << "Couldn't register receive codec.\n";
150 }
151 }
152}
153
154void AcmReceiveTestOldApi::RegisterNetEqTestCodecs() {
155 CodecInst my_codec_param;
156 for (int n = 0; n < acm_->NumberOfCodecs(); n++) {
157 ASSERT_EQ(0, acm_->Codec(n, &my_codec_param)) << "Failed to get codec.";
158 if (!ModifyAndUseThisCodec(&my_codec_param)) {
159 // Skip this codec.
160 continue;
161 }
162
Yves Gerey665174f2018-06-19 15:03:05 +0200163 if (RemapPltypeAndUseThisCodec(my_codec_param.plname, my_codec_param.plfreq,
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000164 my_codec_param.channels,
165 &my_codec_param.pltype)) {
kwibergda2bf4e2016-10-24 13:47:09 -0700166 ASSERT_EQ(true,
167 acm_->RegisterReceiveCodec(my_codec_param.pltype,
168 CodecInstToSdp(my_codec_param)))
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000169 << "Couldn't register receive codec.\n";
170 }
171 }
172}
173
174void AcmReceiveTestOldApi::Run() {
kwiberg16c5a962016-02-15 02:27:22 -0800175 for (std::unique_ptr<Packet> packet(packet_source_->NextPacket()); packet;
henrik.lundin46ba49c2016-05-24 22:50:47 -0700176 packet = packet_source_->NextPacket()) {
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000177 // Pull audio until time to insert packet.
178 while (clock_.TimeInMilliseconds() < packet->time_ms()) {
179 AudioFrame output_frame;
henrik.lundin834a6ea2016-05-13 03:45:24 -0700180 bool muted;
181 EXPECT_EQ(0,
182 acm_->PlayoutData10Ms(output_freq_hz_, &output_frame, &muted));
henrik.lundin6d8e0112016-03-04 10:34:21 -0800183 ASSERT_EQ(output_freq_hz_, output_frame.sample_rate_hz_);
henrik.lundin834a6ea2016-05-13 03:45:24 -0700184 ASSERT_FALSE(muted);
Peter Kastingdce40cf2015-08-24 14:52:23 -0700185 const size_t samples_per_block =
186 static_cast<size_t>(output_freq_hz_ * 10 / 1000);
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000187 EXPECT_EQ(samples_per_block, output_frame.samples_per_channel_);
188 if (exptected_output_channels_ != kArbitraryChannels) {
189 if (output_frame.speech_type_ == webrtc::AudioFrame::kPLC) {
190 // Don't check number of channels for PLC output, since each test run
191 // usually starts with a short period of mono PLC before decoding the
192 // first packet.
193 } else {
194 EXPECT_EQ(exptected_output_channels_, output_frame.num_channels_);
195 }
196 }
197 ASSERT_TRUE(audio_sink_->WriteAudioFrame(output_frame));
198 clock_.AdvanceTimeMilliseconds(10);
henrik.lundin@webrtc.org81a78932014-10-14 10:49:58 +0000199 AfterGetAudio();
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000200 }
201
202 // Insert packet after converting from RTPHeader to WebRtcRTPHeader.
203 WebRtcRTPHeader header;
204 header.header = packet->header();
205 header.frameType = kAudioFrameSpeech;
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000206 EXPECT_EQ(0,
207 acm_->IncomingPacket(
208 packet->payload(),
Yves Gerey665174f2018-06-19 15:03:05 +0200209 static_cast<int32_t>(packet->payload_length_bytes()), header))
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000210 << "Failure when inserting packet:" << std::endl
211 << " PT = " << static_cast<int>(header.header.payloadType) << std::endl
212 << " TS = " << header.header.timestamp << std::endl
213 << " SN = " << header.header.sequenceNumber;
214 }
215}
216
henrik.lundin@webrtc.org81a78932014-10-14 10:49:58 +0000217AcmReceiveTestToggleOutputFreqOldApi::AcmReceiveTestToggleOutputFreqOldApi(
218 PacketSource* packet_source,
219 AudioSink* audio_sink,
220 int output_freq_hz_1,
221 int output_freq_hz_2,
222 int toggle_period_ms,
223 NumOutputChannels exptected_output_channels)
224 : AcmReceiveTestOldApi(packet_source,
225 audio_sink,
226 output_freq_hz_1,
kwiberg5adaf732016-10-04 09:33:27 -0700227 exptected_output_channels,
228 CreateBuiltinAudioDecoderFactory()),
henrik.lundin@webrtc.org81a78932014-10-14 10:49:58 +0000229 output_freq_hz_1_(output_freq_hz_1),
230 output_freq_hz_2_(output_freq_hz_2),
231 toggle_period_ms_(toggle_period_ms),
kwiberg5adaf732016-10-04 09:33:27 -0700232 last_toggle_time_ms_(clock_.TimeInMilliseconds()) {}
henrik.lundin@webrtc.org81a78932014-10-14 10:49:58 +0000233
234void AcmReceiveTestToggleOutputFreqOldApi::AfterGetAudio() {
235 if (clock_.TimeInMilliseconds() >= last_toggle_time_ms_ + toggle_period_ms_) {
236 output_freq_hz_ = (output_freq_hz_ == output_freq_hz_1_)
237 ? output_freq_hz_2_
238 : output_freq_hz_1_;
239 last_toggle_time_ms_ = clock_.TimeInMilliseconds();
240 }
241}
242
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000243} // namespace test
244} // namespace webrtc