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