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/main/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/main/interface/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 // iSAC fullband = 124 51 // AVT/DTMF = 106 52 // RED = 117 53 // PCM16b 8 kHz = 93 54 // PCM16b 16 kHz = 94 55 // PCM16b 32 kHz = 95 56 // G.722 = 94 57 bool RemapPltypeAndUseThisCodec(const char* plname, 58 int plfreq, 59 int channels, 60 int* pltype) { 61 if (channels != 1) 62 return false; // Don't use non-mono codecs. 63 64 // Re-map pltypes to those used in the NetEq test files. 65 if (STR_CASE_CMP(plname, "PCMU") == 0 && plfreq == 8000) { 66 *pltype = 0; 67 } else if (STR_CASE_CMP(plname, "PCMA") == 0 && plfreq == 8000) { 68 *pltype = 8; 69 } else if (STR_CASE_CMP(plname, "CN") == 0 && plfreq == 8000) { 70 *pltype = 13; 71 } else if (STR_CASE_CMP(plname, "CN") == 0 && plfreq == 16000) { 72 *pltype = 98; 73 } else if (STR_CASE_CMP(plname, "CN") == 0 && plfreq == 32000) { 74 *pltype = 99; 75 } else if (STR_CASE_CMP(plname, "ILBC") == 0) { 76 *pltype = 102; 77 } else if (STR_CASE_CMP(plname, "ISAC") == 0 && plfreq == 16000) { 78 *pltype = 103; 79 } else if (STR_CASE_CMP(plname, "ISAC") == 0 && plfreq == 32000) { 80 *pltype = 104; 81 } else if (STR_CASE_CMP(plname, "ISAC") == 0 && plfreq == 48000) { 82 *pltype = 124; 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 } // namespace 102 103 AcmReceiveTestOldApi::AcmReceiveTestOldApi( 104 PacketSource* packet_source, 105 AudioSink* audio_sink, 106 int output_freq_hz, 107 NumOutputChannels exptected_output_channels) 108 : clock_(0), 109 acm_(webrtc::AudioCodingModule::Create(0, &clock_)), 110 packet_source_(packet_source), 111 audio_sink_(audio_sink), 112 output_freq_hz_(output_freq_hz), 113 exptected_output_channels_(exptected_output_channels) { 114 } 115 116 void AcmReceiveTestOldApi::RegisterDefaultCodecs() { 117 CodecInst my_codec_param; 118 for (int n = 0; n < acm_->NumberOfCodecs(); n++) { 119 ASSERT_EQ(0, acm_->Codec(n, &my_codec_param)) << "Failed to get codec."; 120 if (ModifyAndUseThisCodec(&my_codec_param)) { 121 ASSERT_EQ(0, acm_->RegisterReceiveCodec(my_codec_param)) 122 << "Couldn't register receive codec.\n"; 123 } 124 } 125 } 126 127 void AcmReceiveTestOldApi::RegisterNetEqTestCodecs() { 128 CodecInst my_codec_param; 129 for (int n = 0; n < acm_->NumberOfCodecs(); n++) { 130 ASSERT_EQ(0, acm_->Codec(n, &my_codec_param)) << "Failed to get codec."; 131 if (!ModifyAndUseThisCodec(&my_codec_param)) { 132 // Skip this codec. 133 continue; 134 } 135 136 if (RemapPltypeAndUseThisCodec(my_codec_param.plname, 137 my_codec_param.plfreq, 138 my_codec_param.channels, 139 &my_codec_param.pltype)) { 140 ASSERT_EQ(0, acm_->RegisterReceiveCodec(my_codec_param)) 141 << "Couldn't register receive codec.\n"; 142 } 143 } 144 } 145 146 void AcmReceiveTestOldApi::Run() { 147 for (scoped_ptr<Packet> packet(packet_source_->NextPacket()); packet; 148 packet.reset(packet_source_->NextPacket())) { 149 // Pull audio until time to insert packet. 150 while (clock_.TimeInMilliseconds() < packet->time_ms()) { 151 AudioFrame output_frame; 152 EXPECT_EQ(0, acm_->PlayoutData10Ms(output_freq_hz_, &output_frame)); 153 EXPECT_EQ(output_freq_hz_, output_frame.sample_rate_hz_); 154 const int samples_per_block = output_freq_hz_ * 10 / 1000; 155 EXPECT_EQ(samples_per_block, output_frame.samples_per_channel_); 156 if (exptected_output_channels_ != kArbitraryChannels) { 157 if (output_frame.speech_type_ == webrtc::AudioFrame::kPLC) { 158 // Don't check number of channels for PLC output, since each test run 159 // usually starts with a short period of mono PLC before decoding the 160 // first packet. 161 } else { 162 EXPECT_EQ(exptected_output_channels_, output_frame.num_channels_); 163 } 164 } 165 ASSERT_TRUE(audio_sink_->WriteAudioFrame(output_frame)); 166 clock_.AdvanceTimeMilliseconds(10); 167 } 168 169 // Insert packet after converting from RTPHeader to WebRtcRTPHeader. 170 WebRtcRTPHeader header; 171 header.header = packet->header(); 172 header.frameType = kAudioFrameSpeech; 173 memset(&header.type.Audio, 0, sizeof(RTPAudioHeader)); 174 EXPECT_EQ(0, 175 acm_->IncomingPacket( 176 packet->payload(), 177 static_cast<int32_t>(packet->payload_length_bytes()), 178 header)) 179 << "Failure when inserting packet:" << std::endl 180 << " PT = " << static_cast<int>(header.header.payloadType) << std::endl 181 << " TS = " << header.header.timestamp << std::endl 182 << " SN = " << header.header.sequenceNumber; 183 } 184 } 185 186 } // namespace test 187 } // namespace webrtc 188