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/modules/audio_coding/neteq/decoder_database.h"
12 
13 #include <assert.h>
14 #include <stdlib.h>
15 
16 #include <string>
17 
18 #include "testing/gmock/include/gmock/gmock.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20 
21 #include "webrtc/modules/audio_coding/neteq/mock/mock_audio_decoder.h"
22 #include "webrtc/test/testsupport/gtest_disable.h"
23 
24 namespace webrtc {
25 
TEST(DecoderDatabase,CreateAndDestroy)26 TEST(DecoderDatabase, CreateAndDestroy) {
27   DecoderDatabase db;
28   EXPECT_EQ(0, db.Size());
29   EXPECT_TRUE(db.Empty());
30 }
31 
TEST(DecoderDatabase,InsertAndRemove)32 TEST(DecoderDatabase, InsertAndRemove) {
33   DecoderDatabase db;
34   const uint8_t kPayloadType = 0;
35   EXPECT_EQ(DecoderDatabase::kOK,
36             db.RegisterPayload(kPayloadType, NetEqDecoder::kDecoderPCMu));
37   EXPECT_EQ(1, db.Size());
38   EXPECT_FALSE(db.Empty());
39   EXPECT_EQ(DecoderDatabase::kOK, db.Remove(kPayloadType));
40   EXPECT_EQ(0, db.Size());
41   EXPECT_TRUE(db.Empty());
42 }
43 
TEST(DecoderDatabase,GetDecoderInfo)44 TEST(DecoderDatabase, GetDecoderInfo) {
45   DecoderDatabase db;
46   const uint8_t kPayloadType = 0;
47   EXPECT_EQ(DecoderDatabase::kOK,
48             db.RegisterPayload(kPayloadType, NetEqDecoder::kDecoderPCMu));
49   const DecoderDatabase::DecoderInfo* info;
50   info = db.GetDecoderInfo(kPayloadType);
51   ASSERT_TRUE(info != NULL);
52   EXPECT_EQ(NetEqDecoder::kDecoderPCMu, info->codec_type);
53   EXPECT_EQ(NULL, info->decoder);
54   EXPECT_EQ(8000, info->fs_hz);
55   EXPECT_FALSE(info->external);
56   info = db.GetDecoderInfo(kPayloadType + 1);  // Other payload type.
57   EXPECT_TRUE(info == NULL);  // Should not be found.
58 }
59 
TEST(DecoderDatabase,GetRtpPayloadType)60 TEST(DecoderDatabase, GetRtpPayloadType) {
61   DecoderDatabase db;
62   const uint8_t kPayloadType = 0;
63   EXPECT_EQ(DecoderDatabase::kOK,
64             db.RegisterPayload(kPayloadType, NetEqDecoder::kDecoderPCMu));
65   EXPECT_EQ(kPayloadType, db.GetRtpPayloadType(NetEqDecoder::kDecoderPCMu));
66   const uint8_t expected_value = DecoderDatabase::kRtpPayloadTypeError;
67   EXPECT_EQ(expected_value,
68             db.GetRtpPayloadType(
69                 NetEqDecoder::kDecoderISAC));  // iSAC is not registered.
70 }
71 
TEST(DecoderDatabase,GetDecoder)72 TEST(DecoderDatabase, GetDecoder) {
73   DecoderDatabase db;
74   const uint8_t kPayloadType = 0;
75   EXPECT_EQ(DecoderDatabase::kOK,
76             db.RegisterPayload(kPayloadType, NetEqDecoder::kDecoderPCM16B));
77   AudioDecoder* dec = db.GetDecoder(kPayloadType);
78   ASSERT_TRUE(dec != NULL);
79 }
80 
TEST(DecoderDatabase,TypeTests)81 TEST(DecoderDatabase, TypeTests) {
82   DecoderDatabase db;
83   const uint8_t kPayloadTypePcmU = 0;
84   const uint8_t kPayloadTypeCng = 13;
85   const uint8_t kPayloadTypeDtmf = 100;
86   const uint8_t kPayloadTypeRed = 101;
87   const uint8_t kPayloadNotUsed = 102;
88   // Load into database.
89   EXPECT_EQ(DecoderDatabase::kOK,
90             db.RegisterPayload(kPayloadTypePcmU, NetEqDecoder::kDecoderPCMu));
91   EXPECT_EQ(DecoderDatabase::kOK,
92             db.RegisterPayload(kPayloadTypeCng, NetEqDecoder::kDecoderCNGnb));
93   EXPECT_EQ(DecoderDatabase::kOK,
94             db.RegisterPayload(kPayloadTypeDtmf, NetEqDecoder::kDecoderAVT));
95   EXPECT_EQ(DecoderDatabase::kOK,
96             db.RegisterPayload(kPayloadTypeRed, NetEqDecoder::kDecoderRED));
97   EXPECT_EQ(4, db.Size());
98   // Test.
99   EXPECT_FALSE(db.IsComfortNoise(kPayloadNotUsed));
100   EXPECT_FALSE(db.IsDtmf(kPayloadNotUsed));
101   EXPECT_FALSE(db.IsRed(kPayloadNotUsed));
102   EXPECT_FALSE(db.IsComfortNoise(kPayloadTypePcmU));
103   EXPECT_FALSE(db.IsDtmf(kPayloadTypePcmU));
104   EXPECT_FALSE(db.IsRed(kPayloadTypePcmU));
105   EXPECT_FALSE(db.IsType(kPayloadTypePcmU, NetEqDecoder::kDecoderISAC));
106   EXPECT_TRUE(db.IsType(kPayloadTypePcmU, NetEqDecoder::kDecoderPCMu));
107   EXPECT_TRUE(db.IsComfortNoise(kPayloadTypeCng));
108   EXPECT_TRUE(db.IsDtmf(kPayloadTypeDtmf));
109   EXPECT_TRUE(db.IsRed(kPayloadTypeRed));
110 }
111 
TEST(DecoderDatabase,ExternalDecoder)112 TEST(DecoderDatabase, ExternalDecoder) {
113   DecoderDatabase db;
114   const uint8_t kPayloadType = 0;
115   MockAudioDecoder decoder;
116   // Load into database.
117   EXPECT_EQ(DecoderDatabase::kOK,
118             db.InsertExternal(kPayloadType, NetEqDecoder::kDecoderPCMu, 8000,
119                               &decoder));
120   EXPECT_EQ(1, db.Size());
121   // Get decoder and make sure we get the external one.
122   EXPECT_EQ(&decoder, db.GetDecoder(kPayloadType));
123   // Get the decoder info struct and check it too.
124   const DecoderDatabase::DecoderInfo* info;
125   info = db.GetDecoderInfo(kPayloadType);
126   ASSERT_TRUE(info != NULL);
127   EXPECT_EQ(NetEqDecoder::kDecoderPCMu, info->codec_type);
128   EXPECT_EQ(&decoder, info->decoder);
129   EXPECT_EQ(8000, info->fs_hz);
130   EXPECT_TRUE(info->external);
131   // Expect not to delete the decoder when removing it from the database, since
132   // it was declared externally.
133   EXPECT_CALL(decoder, Die()).Times(0);
134   EXPECT_EQ(DecoderDatabase::kOK, db.Remove(kPayloadType));
135   EXPECT_TRUE(db.Empty());
136 
137   EXPECT_CALL(decoder, Die()).Times(1);  // Will be called when |db| is deleted.
138 }
139 
TEST(DecoderDatabase,CheckPayloadTypes)140 TEST(DecoderDatabase, CheckPayloadTypes) {
141   DecoderDatabase db;
142   // Load a number of payloads into the database. Payload types are 0, 1, ...,
143   // while the decoder type is the same for all payload types (this does not
144   // matter for the test).
145   const int kNumPayloads = 10;
146   for (uint8_t payload_type = 0; payload_type < kNumPayloads; ++payload_type) {
147     EXPECT_EQ(
148         DecoderDatabase::kOK,
149         db.RegisterPayload(payload_type, NetEqDecoder::kDecoderArbitrary));
150   }
151   PacketList packet_list;
152   for (int i = 0; i < kNumPayloads + 1; ++i) {
153     // Create packet with payload type |i|. The last packet will have a payload
154     // type that is not registered in the decoder database.
155     Packet* packet = new Packet;
156     packet->header.payloadType = i;
157     packet_list.push_back(packet);
158   }
159 
160   // Expect to return false, since the last packet is of an unknown type.
161   EXPECT_EQ(DecoderDatabase::kDecoderNotFound,
162             db.CheckPayloadTypes(packet_list));
163 
164   delete packet_list.back();
165   packet_list.pop_back();  // Remove the unknown one.
166 
167   EXPECT_EQ(DecoderDatabase::kOK, db.CheckPayloadTypes(packet_list));
168 
169   // Delete all packets.
170   PacketList::iterator it = packet_list.begin();
171   while (it != packet_list.end()) {
172     delete packet_list.front();
173     it = packet_list.erase(it);
174   }
175 }
176 
177 #if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)
178 #define IF_ISAC(x) x
179 #else
180 #define IF_ISAC(x) DISABLED_##x
181 #endif
182 
183 // Test the methods for setting and getting active speech and CNG decoders.
TEST(DecoderDatabase,IF_ISAC (ActiveDecoders))184 TEST(DecoderDatabase, IF_ISAC(ActiveDecoders)) {
185   DecoderDatabase db;
186   // Load payload types.
187   ASSERT_EQ(DecoderDatabase::kOK,
188             db.RegisterPayload(0, NetEqDecoder::kDecoderPCMu));
189   ASSERT_EQ(DecoderDatabase::kOK,
190             db.RegisterPayload(103, NetEqDecoder::kDecoderISAC));
191   ASSERT_EQ(DecoderDatabase::kOK,
192             db.RegisterPayload(13, NetEqDecoder::kDecoderCNGnb));
193   // Verify that no decoders are active from the start.
194   EXPECT_EQ(NULL, db.GetActiveDecoder());
195   EXPECT_EQ(NULL, db.GetActiveCngDecoder());
196 
197   // Set active speech codec.
198   bool changed;  // Should be true when the active decoder changed.
199   EXPECT_EQ(DecoderDatabase::kOK, db.SetActiveDecoder(0, &changed));
200   EXPECT_TRUE(changed);
201   AudioDecoder* decoder = db.GetActiveDecoder();
202   ASSERT_FALSE(decoder == NULL);  // Should get a decoder here.
203 
204   // Set the same again. Expect no change.
205   EXPECT_EQ(DecoderDatabase::kOK, db.SetActiveDecoder(0, &changed));
206   EXPECT_FALSE(changed);
207   decoder = db.GetActiveDecoder();
208   ASSERT_FALSE(decoder == NULL);  // Should get a decoder here.
209 
210   // Change active decoder.
211   EXPECT_EQ(DecoderDatabase::kOK, db.SetActiveDecoder(103, &changed));
212   EXPECT_TRUE(changed);
213   decoder = db.GetActiveDecoder();
214   ASSERT_FALSE(decoder == NULL);  // Should get a decoder here.
215 
216   // Remove the active decoder, and verify that the active becomes NULL.
217   EXPECT_EQ(DecoderDatabase::kOK, db.Remove(103));
218   EXPECT_EQ(NULL, db.GetActiveDecoder());
219 
220   // Set active CNG codec.
221   EXPECT_EQ(DecoderDatabase::kOK, db.SetActiveCngDecoder(13));
222   decoder = db.GetActiveCngDecoder();
223   ASSERT_FALSE(decoder == NULL);  // Should get a decoder here.
224 
225   // Remove the active CNG decoder, and verify that the active becomes NULL.
226   EXPECT_EQ(DecoderDatabase::kOK, db.Remove(13));
227   EXPECT_EQ(NULL, db.GetActiveCngDecoder());
228 
229   // Try to set non-existing codecs as active.
230   EXPECT_EQ(DecoderDatabase::kDecoderNotFound,
231             db.SetActiveDecoder(17, &changed));
232   EXPECT_EQ(DecoderDatabase::kDecoderNotFound,
233             db.SetActiveCngDecoder(17));
234 }
235 }  // namespace webrtc
236