1 /*
2  *  Copyright (c) 2011 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 <stdio.h>
12 #include <string>
13 
14 #include "webrtc/call/rtc_event_log.h"
15 #include "webrtc/test/test_suite.h"
16 #include "webrtc/test/testsupport/fileutils.h"
17 #include "webrtc/voice_engine/test/auto_test/fixtures/after_streaming_fixture.h"
18 #include "webrtc/voice_engine/voice_engine_defines.h"
19 
20 class CodecTest : public AfterStreamingFixture {
21  protected:
SetUp()22   void SetUp() {
23     memset(&codec_instance_, 0, sizeof(codec_instance_));
24   }
25 
SetArbitrarySendCodec()26   void SetArbitrarySendCodec() {
27     // Just grab the first codec.
28     EXPECT_EQ(0, voe_codec_->GetCodec(0, codec_instance_));
29     EXPECT_EQ(0, voe_codec_->SetSendCodec(channel_, codec_instance_));
30   }
31 
32   webrtc::CodecInst codec_instance_;
33 };
34 
SetRateIfILBC(webrtc::CodecInst * codec_instance,int packet_size)35 static void SetRateIfILBC(webrtc::CodecInst* codec_instance, int packet_size) {
36   if (!_stricmp(codec_instance->plname, "ilbc")) {
37     if (packet_size == 160 || packet_size == 320) {
38       codec_instance->rate = 15200;
39     } else {
40       codec_instance->rate = 13300;
41     }
42   }
43 }
44 
IsNotViableSendCodec(const char * codec_name)45 static bool IsNotViableSendCodec(const char* codec_name) {
46   return !_stricmp(codec_name, "CN") ||
47          !_stricmp(codec_name, "telephone-event") ||
48          !_stricmp(codec_name, "red");
49 }
50 
TEST_F(CodecTest,PcmuIsDefaultCodecAndHasTheRightValues)51 TEST_F(CodecTest, PcmuIsDefaultCodecAndHasTheRightValues) {
52   EXPECT_EQ(0, voe_codec_->GetSendCodec(channel_, codec_instance_));
53   EXPECT_EQ(1u, codec_instance_.channels);
54   EXPECT_EQ(160, codec_instance_.pacsize);
55   EXPECT_EQ(8000, codec_instance_.plfreq);
56   EXPECT_EQ(0, codec_instance_.pltype);
57   EXPECT_EQ(64000, codec_instance_.rate);
58   EXPECT_STRCASEEQ("PCMU", codec_instance_.plname);
59 }
60 
TEST_F(CodecTest,VoiceActivityDetectionIsOffByDefault)61 TEST_F(CodecTest, VoiceActivityDetectionIsOffByDefault) {
62   bool vad_enabled = false;
63   bool dtx_disabled = false;
64   webrtc::VadModes vad_mode = webrtc::kVadAggressiveMid;
65 
66   voe_codec_->GetVADStatus(channel_, vad_enabled, vad_mode, dtx_disabled);
67 
68   EXPECT_FALSE(vad_enabled);
69   EXPECT_TRUE(dtx_disabled);
70   EXPECT_EQ(webrtc::kVadConventional, vad_mode);
71 }
72 
TEST_F(CodecTest,VoiceActivityDetectionCanBeEnabled)73 TEST_F(CodecTest, VoiceActivityDetectionCanBeEnabled) {
74   EXPECT_EQ(0, voe_codec_->SetVADStatus(channel_, true));
75 
76   bool vad_enabled = false;
77   bool dtx_disabled = false;
78   webrtc::VadModes vad_mode = webrtc::kVadAggressiveMid;
79 
80   voe_codec_->GetVADStatus(channel_, vad_enabled, vad_mode, dtx_disabled);
81 
82   EXPECT_TRUE(vad_enabled);
83   EXPECT_EQ(webrtc::kVadConventional, vad_mode);
84   EXPECT_FALSE(dtx_disabled);
85 }
86 
TEST_F(CodecTest,VoiceActivityDetectionTypeSettingsCanBeChanged)87 TEST_F(CodecTest, VoiceActivityDetectionTypeSettingsCanBeChanged) {
88   bool vad_enabled = false;
89   bool dtx_disabled = false;
90   webrtc::VadModes vad_mode = webrtc::kVadAggressiveMid;
91 
92   EXPECT_EQ(0, voe_codec_->SetVADStatus(
93       channel_, true, webrtc::kVadAggressiveLow, false));
94   EXPECT_EQ(0, voe_codec_->GetVADStatus(
95       channel_, vad_enabled, vad_mode, dtx_disabled));
96   EXPECT_EQ(vad_mode, webrtc::kVadAggressiveLow);
97   EXPECT_FALSE(dtx_disabled);
98 
99   EXPECT_EQ(0, voe_codec_->SetVADStatus(
100       channel_, true, webrtc::kVadAggressiveMid, false));
101   EXPECT_EQ(0, voe_codec_->GetVADStatus(
102       channel_, vad_enabled, vad_mode, dtx_disabled));
103   EXPECT_EQ(vad_mode, webrtc::kVadAggressiveMid);
104   EXPECT_FALSE(dtx_disabled);
105 
106   // The fourth argument is the DTX disable flag, which is always supposed to
107   // be false.
108   EXPECT_EQ(0, voe_codec_->SetVADStatus(channel_, true,
109                                         webrtc::kVadAggressiveHigh, false));
110   EXPECT_EQ(0, voe_codec_->GetVADStatus(
111       channel_, vad_enabled, vad_mode, dtx_disabled));
112   EXPECT_EQ(vad_mode, webrtc::kVadAggressiveHigh);
113   EXPECT_FALSE(dtx_disabled);
114 
115   EXPECT_EQ(0, voe_codec_->SetVADStatus(channel_, true,
116                                         webrtc::kVadConventional, false));
117   EXPECT_EQ(0, voe_codec_->GetVADStatus(
118       channel_, vad_enabled, vad_mode, dtx_disabled));
119   EXPECT_EQ(vad_mode, webrtc::kVadConventional);
120 }
121 
TEST_F(CodecTest,VoiceActivityDetectionCanBeTurnedOff)122 TEST_F(CodecTest, VoiceActivityDetectionCanBeTurnedOff) {
123   EXPECT_EQ(0, voe_codec_->SetVADStatus(channel_, true));
124 
125   // VAD is always on when DTX is on, so we need to turn off DTX too.
126   EXPECT_EQ(0, voe_codec_->SetVADStatus(
127       channel_, false, webrtc::kVadConventional, true));
128 
129   bool vad_enabled = false;
130   bool dtx_disabled = false;
131   webrtc::VadModes vad_mode = webrtc::kVadAggressiveMid;
132 
133   voe_codec_->GetVADStatus(channel_, vad_enabled, vad_mode, dtx_disabled);
134 
135   EXPECT_FALSE(vad_enabled);
136   EXPECT_TRUE(dtx_disabled);
137   EXPECT_EQ(webrtc::kVadConventional, vad_mode);
138 }
139 
TEST_F(CodecTest,OpusMaxPlaybackRateCanBeSet)140 TEST_F(CodecTest, OpusMaxPlaybackRateCanBeSet) {
141   for (int i = 0; i < voe_codec_->NumOfCodecs(); ++i) {
142     voe_codec_->GetCodec(i, codec_instance_);
143     if (_stricmp("opus", codec_instance_.plname)) {
144       continue;
145     }
146     voe_codec_->SetSendCodec(channel_, codec_instance_);
147     // SetOpusMaxPlaybackRate can handle any integer as the bandwidth. Following
148     // tests some most commonly used numbers.
149     EXPECT_EQ(0, voe_codec_->SetOpusMaxPlaybackRate(channel_, 48000));
150     EXPECT_EQ(0, voe_codec_->SetOpusMaxPlaybackRate(channel_, 32000));
151     EXPECT_EQ(0, voe_codec_->SetOpusMaxPlaybackRate(channel_, 16000));
152     EXPECT_EQ(0, voe_codec_->SetOpusMaxPlaybackRate(channel_, 8000));
153   }
154 }
155 
TEST_F(CodecTest,OpusDtxCanBeSetForOpus)156 TEST_F(CodecTest, OpusDtxCanBeSetForOpus) {
157   for (int i = 0; i < voe_codec_->NumOfCodecs(); ++i) {
158     voe_codec_->GetCodec(i, codec_instance_);
159     if (_stricmp("opus", codec_instance_.plname)) {
160       continue;
161     }
162     voe_codec_->SetSendCodec(channel_, codec_instance_);
163     EXPECT_EQ(0, voe_codec_->SetOpusDtx(channel_, false));
164     EXPECT_EQ(0, voe_codec_->SetOpusDtx(channel_, true));
165   }
166 }
167 
TEST_F(CodecTest,OpusDtxCannotBeSetForNonOpus)168 TEST_F(CodecTest, OpusDtxCannotBeSetForNonOpus) {
169   for (int i = 0; i < voe_codec_->NumOfCodecs(); ++i) {
170     voe_codec_->GetCodec(i, codec_instance_);
171     if (!_stricmp("opus", codec_instance_.plname)) {
172       continue;
173     }
174     voe_codec_->SetSendCodec(channel_, codec_instance_);
175     EXPECT_EQ(-1, voe_codec_->SetOpusDtx(channel_, true));
176   }
177 }
178 
179 #ifdef ENABLE_RTC_EVENT_LOG
TEST_F(CodecTest,RtcEventLogIntegrationTest)180 TEST_F(CodecTest, RtcEventLogIntegrationTest) {
181   webrtc::RtcEventLog* event_log = voe_codec_->GetEventLog();
182   ASSERT_TRUE(event_log);
183 
184   // Find the name of the current test, in order to use it as a temporary
185   // filename.
186   auto test_info = ::testing::UnitTest::GetInstance()->current_test_info();
187   const std::string temp_filename = webrtc::test::OutputPath() +
188                                     test_info->test_case_name() +
189                                     test_info->name();
190   // Create a log file.
191   event_log->StartLogging(temp_filename, 1000);
192   event_log->StopLogging();
193 
194   // Check if the file has been created.
195   FILE* event_file = fopen(temp_filename.c_str(), "r");
196   ASSERT_TRUE(event_file);
197   fclose(event_file);
198   // Remove the temporary file.
199   remove(temp_filename.c_str());
200 }
201 #endif  // ENABLE_RTC_EVENT_LOG
202 
203 // TODO(xians, phoglund): Re-enable when issue 372 is resolved.
TEST_F(CodecTest,DISABLED_ManualVerifySendCodecsForAllPacketSizes)204 TEST_F(CodecTest, DISABLED_ManualVerifySendCodecsForAllPacketSizes) {
205   for (int i = 0; i < voe_codec_->NumOfCodecs(); ++i) {
206     voe_codec_->GetCodec(i, codec_instance_);
207     if (IsNotViableSendCodec(codec_instance_.plname)) {
208       TEST_LOG("Skipping %s.\n", codec_instance_.plname);
209       continue;
210     }
211     EXPECT_NE(-1, codec_instance_.pltype) <<
212         "The codec database should suggest a payload type.";
213 
214     // Test with default packet size:
215     TEST_LOG("%s (pt=%d): default packet size(%d), accepts sizes ",
216              codec_instance_.plname, codec_instance_.pltype,
217              codec_instance_.pacsize);
218     voe_codec_->SetSendCodec(channel_, codec_instance_);
219     Sleep(CODEC_TEST_TIME);
220 
221     // Now test other reasonable packet sizes:
222     bool at_least_one_succeeded = false;
223     for (int packet_size = 80; packet_size < 1000; packet_size += 80) {
224       SetRateIfILBC(&codec_instance_, packet_size);
225       codec_instance_.pacsize = packet_size;
226 
227       if (voe_codec_->SetSendCodec(channel_, codec_instance_) != -1) {
228         // Note that it's fine for SetSendCodec to fail - what packet sizes
229         // it accepts depends on the codec. It should accept one at minimum.
230         TEST_LOG("%d ", packet_size);
231         TEST_LOG_FLUSH;
232         at_least_one_succeeded = true;
233         Sleep(CODEC_TEST_TIME);
234       }
235     }
236     TEST_LOG("\n");
237     EXPECT_TRUE(at_least_one_succeeded);
238   }
239 }
240