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