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