1/*
2 *  Copyright (c) 2012 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/voice_engine/include/voe_codec.h"
12
13#include "testing/gtest/include/gtest/gtest.h"
14#include "webrtc/modules/audio_device/include/fake_audio_device.h"
15#include "webrtc/system_wrappers/interface/scoped_ptr.h"
16#include "webrtc/test/testsupport/gtest_disable.h"
17#include "webrtc/voice_engine/include/voe_base.h"
18#include "webrtc/voice_engine/include/voe_hardware.h"
19#include "webrtc/voice_engine/voice_engine_defines.h"
20
21namespace webrtc {
22namespace voe {
23namespace {
24
25class VoECodecTest : public ::testing::Test {
26 protected:
27  VoECodecTest()
28      : voe_(VoiceEngine::Create()),
29        base_(VoEBase::GetInterface(voe_)),
30        voe_codec_(VoECodec::GetInterface(voe_)),
31        channel_(-1),
32        adm_(new FakeAudioDeviceModule),
33        red_payload_type_(-1) {
34  }
35
36  ~VoECodecTest() {}
37
38  void TearDown() {
39    base_->DeleteChannel(channel_);
40    base_->Terminate();
41    base_->Release();
42    voe_codec_->Release();
43    VoiceEngine::Delete(voe_);
44  }
45
46  void SetUp() {
47    // Check if all components are valid.
48    ASSERT_TRUE(voe_ != NULL);
49    ASSERT_TRUE(base_ != NULL);
50    ASSERT_TRUE(voe_codec_ != NULL);
51    ASSERT_TRUE(adm_.get() != NULL);
52    ASSERT_EQ(0, base_->Init(adm_.get()));
53    channel_ = base_->CreateChannel();
54    ASSERT_NE(-1, channel_);
55
56    CodecInst my_codec;
57
58    bool primary_found = false;
59    bool valid_secondary_found = false;
60    bool invalid_secondary_found = false;
61
62    // Find primary and secondary codecs.
63    int num_codecs = voe_codec_->NumOfCodecs();
64    int n = 0;
65    while (n < num_codecs && (!primary_found || !valid_secondary_found ||
66        !invalid_secondary_found || red_payload_type_ < 0)) {
67      EXPECT_EQ(0, voe_codec_->GetCodec(n, my_codec));
68      if (!STR_CASE_CMP(my_codec.plname, "isac") && my_codec.plfreq == 16000) {
69        memcpy(&valid_secondary_, &my_codec, sizeof(my_codec));
70        valid_secondary_found = true;
71      } else if (!STR_CASE_CMP(my_codec.plname, "isac") &&
72          my_codec.plfreq == 32000) {
73        memcpy(&invalid_secondary_, &my_codec, sizeof(my_codec));
74        invalid_secondary_found = true;
75      } else if (!STR_CASE_CMP(my_codec.plname, "L16") &&
76          my_codec.plfreq == 16000) {
77        memcpy(&primary_, &my_codec, sizeof(my_codec));
78        primary_found = true;
79      } else if (!STR_CASE_CMP(my_codec.plname, "RED")) {
80        red_payload_type_ = my_codec.pltype;
81      }
82      n++;
83    }
84
85    EXPECT_TRUE(primary_found);
86    EXPECT_TRUE(valid_secondary_found);
87    EXPECT_TRUE(invalid_secondary_found);
88    EXPECT_NE(-1, red_payload_type_);
89  }
90
91  VoiceEngine* voe_;
92  VoEBase* base_;
93  VoECodec* voe_codec_;
94  int channel_;
95  CodecInst primary_;
96  CodecInst valid_secondary_;
97  scoped_ptr<FakeAudioDeviceModule> adm_;
98
99  // A codec which is not valid to be registered as secondary codec.
100  CodecInst invalid_secondary_;
101  int red_payload_type_;
102};
103
104
105TEST_F(VoECodecTest,
106       DISABLED_ON_ANDROID(DualStreamSetSecondaryBeforePrimaryFails)) {
107  // Setting secondary before a primary is registered should fail.
108  EXPECT_EQ(-1, voe_codec_->SetSecondarySendCodec(channel_, valid_secondary_,
109                                                  red_payload_type_));
110  red_payload_type_ = 1;
111}
112
113TEST_F(VoECodecTest,
114       DISABLED_ON_ANDROID(DualStreamRegisterWithWrongInputsFails)) {
115  // Register primary codec.
116  EXPECT_EQ(0, voe_codec_->SetSendCodec(channel_, primary_));
117
118  // Wrong secondary.
119  EXPECT_EQ(-1, voe_codec_->SetSecondarySendCodec(channel_, invalid_secondary_,
120                                                  red_payload_type_));
121
122  // Wrong payload.
123  EXPECT_EQ(-1, voe_codec_->SetSecondarySendCodec(channel_, valid_secondary_,
124                                                  -1));
125  // Wrong channel.
126  EXPECT_EQ(-1, voe_codec_->SetSecondarySendCodec(channel_ + 1,
127                                                  valid_secondary_,
128                                                  red_payload_type_));
129}
130
131TEST_F(VoECodecTest, DISABLED_ON_ANDROID(DualStreamGetSecodaryEncoder)) {
132  // Register primary codec.
133  EXPECT_EQ(0, voe_codec_->SetSendCodec(channel_, primary_));
134
135  // Register a valid codec.
136  EXPECT_EQ(0, voe_codec_->SetSecondarySendCodec(channel_, valid_secondary_,
137                                                 red_payload_type_));
138  CodecInst my_codec;
139
140  // Get secondary codec from wrong channel.
141  EXPECT_EQ(-1, voe_codec_->GetSecondarySendCodec(channel_ + 1, my_codec));
142
143  // Get secondary and compare.
144  memset(&my_codec, 0, sizeof(my_codec));
145  EXPECT_EQ(0, voe_codec_->GetSecondarySendCodec(channel_, my_codec));
146
147  EXPECT_EQ(valid_secondary_.plfreq, my_codec.plfreq);
148  EXPECT_EQ(valid_secondary_.channels, my_codec.channels);
149  EXPECT_EQ(valid_secondary_.pacsize, my_codec.pacsize);
150  EXPECT_EQ(valid_secondary_.rate, my_codec.rate);
151  EXPECT_EQ(valid_secondary_.pltype, my_codec.pltype);
152  EXPECT_EQ(0, STR_CASE_CMP(valid_secondary_.plname, my_codec.plname));
153}
154
155TEST_F(VoECodecTest, DISABLED_ON_ANDROID(DualStreamRemoveSecondaryCodec)) {
156  // Register primary codec.
157  EXPECT_EQ(0, voe_codec_->SetSendCodec(channel_, primary_));
158
159  // Register a valid codec.
160  EXPECT_EQ(0, voe_codec_->SetSecondarySendCodec(channel_, valid_secondary_,
161                                                 red_payload_type_));
162  // Remove from wrong channel.
163  EXPECT_EQ(-1, voe_codec_->RemoveSecondarySendCodec(channel_ + 1));
164  EXPECT_EQ(0, voe_codec_->RemoveSecondarySendCodec(channel_));
165
166  CodecInst my_codec;
167
168  // Get should fail, if secondary is removed.
169  EXPECT_EQ(-1, voe_codec_->GetSecondarySendCodec(channel_, my_codec));
170}
171
172TEST(VoECodecInst, TestCompareCodecInstances) {
173  CodecInst codec1, codec2;
174  memset(&codec1, 0, sizeof(CodecInst));
175  memset(&codec2, 0, sizeof(CodecInst));
176
177  codec1.pltype = 101;
178  strncpy(codec1.plname, "isac", 4);
179  codec1.plfreq = 8000;
180  codec1.pacsize = 110;
181  codec1.channels = 1;
182  codec1.rate = 8000;
183  memcpy(&codec2, &codec1, sizeof(CodecInst));
184  // Compare two codecs now.
185  EXPECT_TRUE(codec1 == codec2);
186  EXPECT_FALSE(codec1 != codec2);
187
188  // Changing pltype.
189  codec2.pltype = 102;
190  EXPECT_FALSE(codec1 == codec2);
191  EXPECT_TRUE(codec1 != codec2);
192
193  // Reset to codec2 to codec1 state.
194  memcpy(&codec2, &codec1, sizeof(CodecInst));
195  // payload name should be case insensitive.
196  strncpy(codec2.plname, "ISAC", 4);
197  EXPECT_TRUE(codec1 == codec2);
198
199  // Test modifying the |plfreq|
200  codec2.plfreq = 16000;
201  EXPECT_FALSE(codec1 == codec2);
202
203  // Reset to codec2 to codec1 state.
204  memcpy(&codec2, &codec1, sizeof(CodecInst));
205  // Test modifying the |pacsize|.
206  codec2.pacsize = 440;
207  EXPECT_FALSE(codec1 == codec2);
208
209  // Reset to codec2 to codec1 state.
210  memcpy(&codec2, &codec1, sizeof(CodecInst));
211  // Test modifying the |channels|.
212  codec2.channels = 2;
213  EXPECT_FALSE(codec1 == codec2);
214
215  // Reset to codec2 to codec1 state.
216  memcpy(&codec2, &codec1, sizeof(CodecInst));
217  // Test modifying the |rate|.
218  codec2.rate = 0;
219  EXPECT_FALSE(codec1 == codec2);
220}
221
222}  // namespace
223}  // namespace voe
224}  // namespace webrtc
225