decoder_database_unittest.cc (9033B)
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 "modules/audio_coding/neteq/decoder_database.h" 12 13 #include <cstdint> 14 #include <cstdlib> 15 #include <optional> 16 #include <string> 17 #include <utility> 18 19 #include "absl/memory/memory.h" 20 #include "api/audio_codecs/audio_decoder.h" 21 #include "api/audio_codecs/audio_format.h" 22 #include "api/audio_codecs/builtin_audio_decoder_factory.h" 23 #include "api/environment/environment_factory.h" 24 #include "api/make_ref_counted.h" 25 #include "modules/audio_coding/codecs/cng/webrtc_cng.h" 26 #include "modules/audio_coding/neteq/packet.h" 27 #include "test/gmock.h" 28 #include "test/gtest.h" 29 #include "test/mock_audio_decoder.h" 30 #include "test/mock_audio_decoder_factory.h" 31 32 namespace webrtc { 33 34 using ::testing::WithArg; 35 36 TEST(DecoderDatabase, CreateAndDestroy) { 37 DecoderDatabase db(CreateEnvironment(), 38 make_ref_counted<MockAudioDecoderFactory>(), std::nullopt); 39 EXPECT_EQ(0, db.Size()); 40 EXPECT_TRUE(db.Empty()); 41 } 42 43 TEST(DecoderDatabase, InsertAndRemove) { 44 DecoderDatabase db(CreateEnvironment(), 45 make_ref_counted<MockAudioDecoderFactory>(), std::nullopt); 46 const uint8_t kPayloadType = 0; 47 const std::string kCodecName = "Robert\'); DROP TABLE Students;"; 48 EXPECT_EQ( 49 DecoderDatabase::kOK, 50 db.RegisterPayload(kPayloadType, SdpAudioFormat(kCodecName, 8000, 1))); 51 EXPECT_EQ(1, db.Size()); 52 EXPECT_FALSE(db.Empty()); 53 EXPECT_EQ(DecoderDatabase::kOK, db.Remove(kPayloadType)); 54 EXPECT_EQ(0, db.Size()); 55 EXPECT_TRUE(db.Empty()); 56 } 57 58 TEST(DecoderDatabase, InsertAndRemoveAll) { 59 DecoderDatabase db(CreateEnvironment(), 60 make_ref_counted<MockAudioDecoderFactory>(), std::nullopt); 61 const std::string kCodecName1 = "Robert\'); DROP TABLE Students;"; 62 const std::string kCodecName2 = "https://xkcd.com/327/"; 63 EXPECT_EQ(DecoderDatabase::kOK, 64 db.RegisterPayload(0, SdpAudioFormat(kCodecName1, 8000, 1))); 65 EXPECT_EQ(DecoderDatabase::kOK, 66 db.RegisterPayload(1, SdpAudioFormat(kCodecName2, 8000, 1))); 67 EXPECT_EQ(2, db.Size()); 68 EXPECT_FALSE(db.Empty()); 69 db.RemoveAll(); 70 EXPECT_EQ(0, db.Size()); 71 EXPECT_TRUE(db.Empty()); 72 } 73 74 TEST(DecoderDatabase, GetDecoderInfo) { 75 auto factory = make_ref_counted<MockAudioDecoderFactory>(); 76 auto* decoder = new MockAudioDecoder; 77 EXPECT_CALL(*factory, Create) 78 .WillOnce(WithArg<1>([decoder](const SdpAudioFormat& format) { 79 EXPECT_EQ("pcmu", format.name); 80 return absl::WrapUnique(decoder); 81 })); 82 DecoderDatabase db(CreateEnvironment(), std::move(factory), std::nullopt); 83 const uint8_t kPayloadType = 0; 84 const std::string kCodecName = "pcmu"; 85 EXPECT_EQ( 86 DecoderDatabase::kOK, 87 db.RegisterPayload(kPayloadType, SdpAudioFormat(kCodecName, 8000, 1))); 88 const DecoderDatabase::DecoderInfo* info; 89 info = db.GetDecoderInfo(kPayloadType); 90 ASSERT_TRUE(info != nullptr); 91 EXPECT_TRUE(info->IsType("pcmu")); 92 EXPECT_EQ(kCodecName, info->get_name()); 93 EXPECT_EQ(decoder, db.GetDecoder(kPayloadType)); 94 info = db.GetDecoderInfo(kPayloadType + 1); // Other payload type. 95 EXPECT_TRUE(info == nullptr); // Should not be found. 96 } 97 98 TEST(DecoderDatabase, GetDecoder) { 99 DecoderDatabase db(CreateEnvironment(), CreateBuiltinAudioDecoderFactory(), 100 std::nullopt); 101 const uint8_t kPayloadType = 0; 102 EXPECT_EQ(DecoderDatabase::kOK, 103 db.RegisterPayload(kPayloadType, SdpAudioFormat("l16", 8000, 1))); 104 AudioDecoder* dec = db.GetDecoder(kPayloadType); 105 ASSERT_TRUE(dec != nullptr); 106 } 107 108 TEST(DecoderDatabase, TypeTests) { 109 DecoderDatabase db(CreateEnvironment(), 110 make_ref_counted<MockAudioDecoderFactory>(), std::nullopt); 111 const uint8_t kPayloadTypePcmU = 0; 112 const uint8_t kPayloadTypeCng = 13; 113 const uint8_t kPayloadTypeDtmf = 100; 114 const uint8_t kPayloadTypeRed = 101; 115 const uint8_t kPayloadNotUsed = 102; 116 // Load into database. 117 EXPECT_EQ( 118 DecoderDatabase::kOK, 119 db.RegisterPayload(kPayloadTypePcmU, SdpAudioFormat("pcmu", 8000, 1))); 120 EXPECT_EQ(DecoderDatabase::kOK, 121 db.RegisterPayload(kPayloadTypeCng, SdpAudioFormat("cn", 8000, 1))); 122 EXPECT_EQ(DecoderDatabase::kOK, 123 db.RegisterPayload(kPayloadTypeDtmf, 124 SdpAudioFormat("telephone-event", 8000, 1))); 125 EXPECT_EQ( 126 DecoderDatabase::kOK, 127 db.RegisterPayload(kPayloadTypeRed, SdpAudioFormat("red", 8000, 1))); 128 EXPECT_EQ(4, db.Size()); 129 // Test. 130 EXPECT_FALSE(db.IsComfortNoise(kPayloadNotUsed)); 131 EXPECT_FALSE(db.IsDtmf(kPayloadNotUsed)); 132 EXPECT_FALSE(db.IsRed(kPayloadNotUsed)); 133 EXPECT_FALSE(db.IsComfortNoise(kPayloadTypePcmU)); 134 EXPECT_FALSE(db.IsDtmf(kPayloadTypePcmU)); 135 EXPECT_FALSE(db.IsRed(kPayloadTypePcmU)); 136 EXPECT_TRUE(db.IsComfortNoise(kPayloadTypeCng)); 137 EXPECT_TRUE(db.IsDtmf(kPayloadTypeDtmf)); 138 EXPECT_TRUE(db.IsRed(kPayloadTypeRed)); 139 } 140 141 TEST(DecoderDatabase, CheckPayloadTypes) { 142 constexpr int kNumPayloads = 10; 143 DecoderDatabase db(CreateEnvironment(), 144 make_ref_counted<MockAudioDecoderFactory>(), std::nullopt); 145 // Load a number of payloads into the database. Payload types are 0, 1, ..., 146 // while the decoder type is the same for all payload types (this does not 147 // matter for the test). 148 for (uint8_t payload_type = 0; payload_type < kNumPayloads; ++payload_type) { 149 EXPECT_EQ( 150 DecoderDatabase::kOK, 151 db.RegisterPayload(payload_type, SdpAudioFormat("pcmu", 8000, 1))); 152 } 153 PacketList packet_list; 154 for (int i = 0; i < kNumPayloads + 1; ++i) { 155 // Create packet with payload type `i`. The last packet will have a payload 156 // type that is not registered in the decoder database. 157 Packet packet; 158 packet.payload_type = i; 159 packet_list.push_back(std::move(packet)); 160 } 161 162 // Expect to return false, since the last packet is of an unknown type. 163 EXPECT_EQ(DecoderDatabase::kDecoderNotFound, 164 db.CheckPayloadTypes(packet_list)); 165 166 packet_list.pop_back(); // Remove the unknown one. 167 168 EXPECT_EQ(DecoderDatabase::kOK, db.CheckPayloadTypes(packet_list)); 169 170 // Delete all packets. 171 PacketList::iterator it = packet_list.begin(); 172 while (it != packet_list.end()) { 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. 184 TEST(DecoderDatabase, IF_ISAC(ActiveDecoders)) { 185 DecoderDatabase db(CreateEnvironment(), CreateBuiltinAudioDecoderFactory(), 186 std::nullopt); 187 // Load payload types. 188 ASSERT_EQ(DecoderDatabase::kOK, 189 db.RegisterPayload(0, SdpAudioFormat("pcmu", 8000, 1))); 190 ASSERT_EQ(DecoderDatabase::kOK, 191 db.RegisterPayload(103, SdpAudioFormat("isac", 16000, 1))); 192 ASSERT_EQ(DecoderDatabase::kOK, 193 db.RegisterPayload(13, SdpAudioFormat("cn", 8000, 1))); 194 // Verify that no decoders are active from the start. 195 EXPECT_EQ(nullptr, db.GetActiveDecoder()); 196 EXPECT_EQ(nullptr, db.GetActiveCngDecoder()); 197 198 // Set active speech codec. 199 bool changed; // Should be true when the active decoder changed. 200 EXPECT_EQ(DecoderDatabase::kOK, db.SetActiveDecoder(0, &changed)); 201 EXPECT_TRUE(changed); 202 AudioDecoder* decoder = db.GetActiveDecoder(); 203 ASSERT_FALSE(decoder == nullptr); // Should get a decoder here. 204 205 // Set the same again. Expect no change. 206 EXPECT_EQ(DecoderDatabase::kOK, db.SetActiveDecoder(0, &changed)); 207 EXPECT_FALSE(changed); 208 decoder = db.GetActiveDecoder(); 209 ASSERT_FALSE(decoder == nullptr); // Should get a decoder here. 210 211 // Change active decoder. 212 EXPECT_EQ(DecoderDatabase::kOK, db.SetActiveDecoder(103, &changed)); 213 EXPECT_TRUE(changed); 214 decoder = db.GetActiveDecoder(); 215 ASSERT_FALSE(decoder == nullptr); // Should get a decoder here. 216 217 // Remove the active decoder, and verify that the active becomes NULL. 218 EXPECT_EQ(DecoderDatabase::kOK, db.Remove(103)); 219 EXPECT_EQ(nullptr, db.GetActiveDecoder()); 220 221 // Set active CNG codec. 222 EXPECT_EQ(DecoderDatabase::kOK, db.SetActiveCngDecoder(13)); 223 ComfortNoiseDecoder* cng = db.GetActiveCngDecoder(); 224 ASSERT_FALSE(cng == nullptr); // Should get a decoder here. 225 226 // Remove the active CNG decoder, and verify that the active becomes NULL. 227 EXPECT_EQ(DecoderDatabase::kOK, db.Remove(13)); 228 EXPECT_EQ(nullptr, db.GetActiveCngDecoder()); 229 230 // Try to set non-existing codecs as active. 231 EXPECT_EQ(DecoderDatabase::kDecoderNotFound, 232 db.SetActiveDecoder(17, &changed)); 233 EXPECT_EQ(DecoderDatabase::kDecoderNotFound, db.SetActiveCngDecoder(17)); 234 } 235 } // namespace webrtc