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