• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
ModifyAndUseThisCodec(CodecInst * codec_param)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
RemapPltypeAndUseThisCodec(const char * plname,int plfreq,size_t channels,int * pltype)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 
AcmReceiveTestOldApi(PacketSource * packet_source,AudioSink * audio_sink,int output_freq_hz,NumOutputChannels exptected_output_channels)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 
RegisterDefaultCodecs()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 
RegisterNetEqTestCodecs()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 
RegisterExternalReceiveCodec(int rtp_payload_type,AudioDecoder * external_decoder,int sample_rate_hz,int num_channels,const std::string & name)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 
Run()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 
AcmReceiveTestToggleOutputFreqOldApi(PacketSource * packet_source,AudioSink * audio_sink,int output_freq_hz_1,int output_freq_hz_2,int toggle_period_ms,NumOutputChannels exptected_output_channels)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 
AfterGetAudio()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