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