OLD | NEW |
| (Empty) |
1 /* | |
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 | |
11 #include "webrtc/modules/audio_coding/acm2/acm_receive_test_oldapi.h" | |
12 | |
13 #include <assert.h> | |
14 #include <stdio.h> | |
15 | |
16 #include <memory> | |
17 | |
18 #include "webrtc/modules/audio_coding/codecs/builtin_audio_decoder_factory.h" | |
19 #include "webrtc/modules/audio_coding/include/audio_coding_module.h" | |
20 #include "webrtc/modules/audio_coding/neteq/tools/audio_sink.h" | |
21 #include "webrtc/modules/audio_coding/neteq/tools/packet.h" | |
22 #include "webrtc/modules/audio_coding/neteq/tools/packet_source.h" | |
23 #include "webrtc/test/gtest.h" | |
24 | |
25 namespace webrtc { | |
26 namespace test { | |
27 | |
28 namespace { | |
29 // Returns true if the codec should be registered, otherwise false. Changes | |
30 // the number of channels for the Opus codec to always be 1. | |
31 bool ModifyAndUseThisCodec(CodecInst* codec_param) { | |
32 if (STR_CASE_CMP(codec_param->plname, "CN") == 0 && | |
33 codec_param->plfreq == 48000) | |
34 return false; // Skip 48 kHz comfort noise. | |
35 | |
36 if (STR_CASE_CMP(codec_param->plname, "telephone-event") == 0) | |
37 return false; // Skip DTFM. | |
38 | |
39 return true; | |
40 } | |
41 | |
42 // Remaps payload types from ACM's default to those used in the resource file | |
43 // neteq_universal_new.rtp. Returns true if the codec should be registered, | |
44 // otherwise false. The payload types are set as follows (all are mono codecs): | |
45 // PCMu = 0; | |
46 // PCMa = 8; | |
47 // Comfort noise 8 kHz = 13 | |
48 // Comfort noise 16 kHz = 98 | |
49 // Comfort noise 32 kHz = 99 | |
50 // iLBC = 102 | |
51 // iSAC wideband = 103 | |
52 // iSAC super-wideband = 104 | |
53 // AVT/DTMF = 106 | |
54 // RED = 117 | |
55 // PCM16b 8 kHz = 93 | |
56 // PCM16b 16 kHz = 94 | |
57 // PCM16b 32 kHz = 95 | |
58 // G.722 = 94 | |
59 bool RemapPltypeAndUseThisCodec(const char* plname, | |
60 int plfreq, | |
61 size_t channels, | |
62 int* pltype) { | |
63 if (channels != 1) | |
64 return false; // Don't use non-mono codecs. | |
65 | |
66 // Re-map pltypes to those used in the NetEq test files. | |
67 if (STR_CASE_CMP(plname, "PCMU") == 0 && plfreq == 8000) { | |
68 *pltype = 0; | |
69 } else if (STR_CASE_CMP(plname, "PCMA") == 0 && plfreq == 8000) { | |
70 *pltype = 8; | |
71 } else if (STR_CASE_CMP(plname, "CN") == 0 && plfreq == 8000) { | |
72 *pltype = 13; | |
73 } else if (STR_CASE_CMP(plname, "CN") == 0 && plfreq == 16000) { | |
74 *pltype = 98; | |
75 } else if (STR_CASE_CMP(plname, "CN") == 0 && plfreq == 32000) { | |
76 *pltype = 99; | |
77 } else if (STR_CASE_CMP(plname, "ILBC") == 0) { | |
78 *pltype = 102; | |
79 } else if (STR_CASE_CMP(plname, "ISAC") == 0 && plfreq == 16000) { | |
80 *pltype = 103; | |
81 } else if (STR_CASE_CMP(plname, "ISAC") == 0 && plfreq == 32000) { | |
82 *pltype = 104; | |
83 } else if (STR_CASE_CMP(plname, "telephone-event") == 0) { | |
84 *pltype = 106; | |
85 } else if (STR_CASE_CMP(plname, "red") == 0) { | |
86 *pltype = 117; | |
87 } else if (STR_CASE_CMP(plname, "L16") == 0 && plfreq == 8000) { | |
88 *pltype = 93; | |
89 } else if (STR_CASE_CMP(plname, "L16") == 0 && plfreq == 16000) { | |
90 *pltype = 94; | |
91 } else if (STR_CASE_CMP(plname, "L16") == 0 && plfreq == 32000) { | |
92 *pltype = 95; | |
93 } else if (STR_CASE_CMP(plname, "G722") == 0) { | |
94 *pltype = 9; | |
95 } else { | |
96 // Don't use any other codecs. | |
97 return false; | |
98 } | |
99 return true; | |
100 } | |
101 | |
102 AudioCodingModule::Config MakeAcmConfig( | |
103 Clock* clock, | |
104 rtc::scoped_refptr<AudioDecoderFactory> decoder_factory) { | |
105 AudioCodingModule::Config config; | |
106 config.id = 0; | |
107 config.clock = clock; | |
108 config.decoder_factory = std::move(decoder_factory); | |
109 return config; | |
110 } | |
111 | |
112 } // namespace | |
113 | |
114 AcmReceiveTestOldApi::AcmReceiveTestOldApi( | |
115 PacketSource* packet_source, | |
116 AudioSink* audio_sink, | |
117 int output_freq_hz, | |
118 NumOutputChannels exptected_output_channels, | |
119 rtc::scoped_refptr<AudioDecoderFactory> decoder_factory) | |
120 : clock_(0), | |
121 acm_(webrtc::AudioCodingModule::Create( | |
122 MakeAcmConfig(&clock_, std::move(decoder_factory)))), | |
123 packet_source_(packet_source), | |
124 audio_sink_(audio_sink), | |
125 output_freq_hz_(output_freq_hz), | |
126 exptected_output_channels_(exptected_output_channels) {} | |
127 | |
128 AcmReceiveTestOldApi::~AcmReceiveTestOldApi() = default; | |
129 | |
130 void AcmReceiveTestOldApi::RegisterDefaultCodecs() { | |
131 CodecInst my_codec_param; | |
132 for (int n = 0; n < acm_->NumberOfCodecs(); n++) { | |
133 ASSERT_EQ(0, acm_->Codec(n, &my_codec_param)) << "Failed to get codec."; | |
134 if (ModifyAndUseThisCodec(&my_codec_param)) { | |
135 ASSERT_EQ(0, acm_->RegisterReceiveCodec(my_codec_param)) | |
136 << "Couldn't register receive codec.\n"; | |
137 } | |
138 } | |
139 } | |
140 | |
141 void AcmReceiveTestOldApi::RegisterNetEqTestCodecs() { | |
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)) { | |
146 // Skip this codec. | |
147 continue; | |
148 } | |
149 | |
150 if (RemapPltypeAndUseThisCodec(my_codec_param.plname, | |
151 my_codec_param.plfreq, | |
152 my_codec_param.channels, | |
153 &my_codec_param.pltype)) { | |
154 ASSERT_EQ(0, acm_->RegisterReceiveCodec(my_codec_param)) | |
155 << "Couldn't register receive codec.\n"; | |
156 } | |
157 } | |
158 } | |
159 | |
160 int AcmReceiveTestOldApi::RegisterExternalReceiveCodec( | |
161 int rtp_payload_type, | |
162 AudioDecoder* external_decoder, | |
163 int sample_rate_hz, | |
164 int num_channels, | |
165 const std::string& name) { | |
166 return acm_->RegisterExternalReceiveCodec(rtp_payload_type, external_decoder, | |
167 sample_rate_hz, num_channels, name); | |
168 } | |
169 | |
170 void AcmReceiveTestOldApi::Run() { | |
171 for (std::unique_ptr<Packet> packet(packet_source_->NextPacket()); packet; | |
172 packet = packet_source_->NextPacket()) { | |
173 // Pull audio until time to insert packet. | |
174 while (clock_.TimeInMilliseconds() < packet->time_ms()) { | |
175 AudioFrame output_frame; | |
176 bool muted; | |
177 EXPECT_EQ(0, | |
178 acm_->PlayoutData10Ms(output_freq_hz_, &output_frame, &muted)); | |
179 ASSERT_EQ(output_freq_hz_, output_frame.sample_rate_hz_); | |
180 ASSERT_FALSE(muted); | |
181 const size_t samples_per_block = | |
182 static_cast<size_t>(output_freq_hz_ * 10 / 1000); | |
183 EXPECT_EQ(samples_per_block, output_frame.samples_per_channel_); | |
184 if (exptected_output_channels_ != kArbitraryChannels) { | |
185 if (output_frame.speech_type_ == webrtc::AudioFrame::kPLC) { | |
186 // Don't check number of channels for PLC output, since each test run | |
187 // usually starts with a short period of mono PLC before decoding the | |
188 // first packet. | |
189 } else { | |
190 EXPECT_EQ(exptected_output_channels_, output_frame.num_channels_); | |
191 } | |
192 } | |
193 ASSERT_TRUE(audio_sink_->WriteAudioFrame(output_frame)); | |
194 clock_.AdvanceTimeMilliseconds(10); | |
195 AfterGetAudio(); | |
196 } | |
197 | |
198 // Insert packet after converting from RTPHeader to WebRtcRTPHeader. | |
199 WebRtcRTPHeader header; | |
200 header.header = packet->header(); | |
201 header.frameType = kAudioFrameSpeech; | |
202 memset(&header.type.Audio, 0, sizeof(RTPAudioHeader)); | |
203 EXPECT_EQ(0, | |
204 acm_->IncomingPacket( | |
205 packet->payload(), | |
206 static_cast<int32_t>(packet->payload_length_bytes()), | |
207 header)) | |
208 << "Failure when inserting packet:" << std::endl | |
209 << " PT = " << static_cast<int>(header.header.payloadType) << std::endl | |
210 << " TS = " << header.header.timestamp << std::endl | |
211 << " SN = " << header.header.sequenceNumber; | |
212 } | |
213 } | |
214 | |
215 AcmReceiveTestToggleOutputFreqOldApi::AcmReceiveTestToggleOutputFreqOldApi( | |
216 PacketSource* packet_source, | |
217 AudioSink* audio_sink, | |
218 int output_freq_hz_1, | |
219 int output_freq_hz_2, | |
220 int toggle_period_ms, | |
221 NumOutputChannels exptected_output_channels) | |
222 : AcmReceiveTestOldApi(packet_source, | |
223 audio_sink, | |
224 output_freq_hz_1, | |
225 exptected_output_channels, | |
226 CreateBuiltinAudioDecoderFactory()), | |
227 output_freq_hz_1_(output_freq_hz_1), | |
228 output_freq_hz_2_(output_freq_hz_2), | |
229 toggle_period_ms_(toggle_period_ms), | |
230 last_toggle_time_ms_(clock_.TimeInMilliseconds()) {} | |
231 | |
232 void AcmReceiveTestToggleOutputFreqOldApi::AfterGetAudio() { | |
233 if (clock_.TimeInMilliseconds() >= last_toggle_time_ms_ + toggle_period_ms_) { | |
234 output_freq_hz_ = (output_freq_hz_ == output_freq_hz_1_) | |
235 ? output_freq_hz_2_ | |
236 : output_freq_hz_1_; | |
237 last_toggle_time_ms_ = clock_.TimeInMilliseconds(); | |
238 } | |
239 } | |
240 | |
241 } // namespace test | |
242 } // namespace webrtc | |
OLD | NEW |