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 /* 12 * This file generates databases with information about all supported audio 13 * codecs. 14 */ 15 16 // TODO(tlegrand): Change constant input pointers in all functions to constant 17 // references, where appropriate. 18 #include "webrtc/modules/audio_coding/acm2/acm_codec_database.h" 19 20 #include <assert.h> 21 22 #include "webrtc/base/checks.h" 23 #include "webrtc/modules/audio_coding/acm2/acm_common_defs.h" 24 #include "webrtc/system_wrappers/include/trace.h" 25 26 namespace webrtc { 27 28 namespace acm2 { 29 30 namespace { 31 32 // Checks if the bitrate is valid for iSAC. 33 bool IsISACRateValid(int rate) { 34 return (rate == -1) || ((rate <= 56000) && (rate >= 10000)); 35 } 36 37 // Checks if the bitrate is valid for iLBC. 38 bool IsILBCRateValid(int rate, int frame_size_samples) { 39 if (((frame_size_samples == 240) || (frame_size_samples == 480)) && 40 (rate == 13300)) { 41 return true; 42 } else if (((frame_size_samples == 160) || (frame_size_samples == 320)) && 43 (rate == 15200)) { 44 return true; 45 } else { 46 return false; 47 } 48 } 49 50 // Checks if the bitrate is valid for Opus. 51 bool IsOpusRateValid(int rate) { 52 return (rate >= 6000) && (rate <= 510000); 53 } 54 55 } // namespace 56 57 // Not yet used payload-types. 58 // 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 59 // 67, 66, 65 60 61 const CodecInst ACMCodecDB::database_[] = { 62 #if (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)) 63 {103, "ISAC", 16000, kIsacPacSize480, 1, kIsacWbDefaultRate}, 64 # if (defined(WEBRTC_CODEC_ISAC)) 65 {104, "ISAC", 32000, kIsacPacSize960, 1, kIsacSwbDefaultRate}, 66 # endif 67 #endif 68 // Mono 69 {107, "L16", 8000, 80, 1, 128000}, 70 {108, "L16", 16000, 160, 1, 256000}, 71 {109, "L16", 32000, 320, 1, 512000}, 72 // Stereo 73 {111, "L16", 8000, 80, 2, 128000}, 74 {112, "L16", 16000, 160, 2, 256000}, 75 {113, "L16", 32000, 320, 2, 512000}, 76 // G.711, PCM mu-law and A-law. 77 // Mono 78 {0, "PCMU", 8000, 160, 1, 64000}, 79 {8, "PCMA", 8000, 160, 1, 64000}, 80 // Stereo 81 {110, "PCMU", 8000, 160, 2, 64000}, 82 {118, "PCMA", 8000, 160, 2, 64000}, 83 #ifdef WEBRTC_CODEC_ILBC 84 {102, "ILBC", 8000, 240, 1, 13300}, 85 #endif 86 #ifdef WEBRTC_CODEC_G722 87 // Mono 88 {9, "G722", 16000, 320, 1, 64000}, 89 // Stereo 90 {119, "G722", 16000, 320, 2, 64000}, 91 #endif 92 #ifdef WEBRTC_CODEC_OPUS 93 // Opus internally supports 48, 24, 16, 12, 8 kHz. 94 // Mono and stereo. 95 {120, "opus", 48000, 960, 2, 64000}, 96 #endif 97 // Comfort noise for four different sampling frequencies. 98 {13, "CN", 8000, 240, 1, 0}, 99 {98, "CN", 16000, 480, 1, 0}, 100 {99, "CN", 32000, 960, 1, 0}, 101 #ifdef ENABLE_48000_HZ 102 {100, "CN", 48000, 1440, 1, 0}, 103 #endif 104 {106, "telephone-event", 8000, 240, 1, 0}, 105 #ifdef WEBRTC_CODEC_RED 106 {127, "red", 8000, 0, 1, 0}, 107 #endif 108 // To prevent compile errors due to trailing commas. 109 {-1, "Null", -1, -1, 0, -1} 110 }; 111 112 // Create database with all codec settings at compile time. 113 // Each entry needs the following parameters in the given order: 114 // Number of allowed packet sizes, a vector with the allowed packet sizes, 115 // Basic block samples, max number of channels that are supported. 116 const ACMCodecDB::CodecSettings ACMCodecDB::codec_settings_[] = { 117 #if (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)) 118 {2, {kIsacPacSize480, kIsacPacSize960}, 0, 1}, 119 # if (defined(WEBRTC_CODEC_ISAC)) 120 {1, {kIsacPacSize960}, 0, 1}, 121 # endif 122 #endif 123 // Mono 124 {4, {80, 160, 240, 320}, 0, 2}, 125 {4, {160, 320, 480, 640}, 0, 2}, 126 {2, {320, 640}, 0, 2}, 127 // Stereo 128 {4, {80, 160, 240, 320}, 0, 2}, 129 {4, {160, 320, 480, 640}, 0, 2}, 130 {2, {320, 640}, 0, 2}, 131 // G.711, PCM mu-law and A-law. 132 // Mono 133 {6, {80, 160, 240, 320, 400, 480}, 0, 2}, 134 {6, {80, 160, 240, 320, 400, 480}, 0, 2}, 135 // Stereo 136 {6, {80, 160, 240, 320, 400, 480}, 0, 2}, 137 {6, {80, 160, 240, 320, 400, 480}, 0, 2}, 138 #ifdef WEBRTC_CODEC_ILBC 139 {4, {160, 240, 320, 480}, 0, 1}, 140 #endif 141 #ifdef WEBRTC_CODEC_G722 142 // Mono 143 {6, {160, 320, 480, 640, 800, 960}, 0, 2}, 144 // Stereo 145 {6, {160, 320, 480, 640, 800, 960}, 0, 2}, 146 #endif 147 #ifdef WEBRTC_CODEC_OPUS 148 // Opus supports frames shorter than 10ms, 149 // but it doesn't help us to use them. 150 // Mono and stereo. 151 {4, {480, 960, 1920, 2880}, 0, 2}, 152 #endif 153 // Comfort noise for three different sampling frequencies. 154 {1, {240}, 240, 1}, 155 {1, {480}, 480, 1}, 156 {1, {960}, 960, 1}, 157 #ifdef ENABLE_48000_HZ 158 {1, {1440}, 1440, 1}, 159 #endif 160 {1, {240}, 240, 1}, 161 #ifdef WEBRTC_CODEC_RED 162 {1, {0}, 0, 1}, 163 #endif 164 // To prevent compile errors due to trailing commas. 165 {-1, {-1}, -1, 0} 166 }; 167 168 // Create a database of all NetEQ decoders at compile time. 169 const NetEqDecoder ACMCodecDB::neteq_decoders_[] = { 170 #if (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)) 171 NetEqDecoder::kDecoderISAC, 172 # if (defined(WEBRTC_CODEC_ISAC)) 173 NetEqDecoder::kDecoderISACswb, 174 # endif 175 #endif 176 // Mono 177 NetEqDecoder::kDecoderPCM16B, NetEqDecoder::kDecoderPCM16Bwb, 178 NetEqDecoder::kDecoderPCM16Bswb32kHz, 179 // Stereo 180 NetEqDecoder::kDecoderPCM16B_2ch, NetEqDecoder::kDecoderPCM16Bwb_2ch, 181 NetEqDecoder::kDecoderPCM16Bswb32kHz_2ch, 182 // G.711, PCM mu-las and A-law. 183 // Mono 184 NetEqDecoder::kDecoderPCMu, NetEqDecoder::kDecoderPCMa, 185 // Stereo 186 NetEqDecoder::kDecoderPCMu_2ch, NetEqDecoder::kDecoderPCMa_2ch, 187 #ifdef WEBRTC_CODEC_ILBC 188 NetEqDecoder::kDecoderILBC, 189 #endif 190 #ifdef WEBRTC_CODEC_G722 191 // Mono 192 NetEqDecoder::kDecoderG722, 193 // Stereo 194 NetEqDecoder::kDecoderG722_2ch, 195 #endif 196 #ifdef WEBRTC_CODEC_OPUS 197 // Mono and stereo. 198 NetEqDecoder::kDecoderOpus, 199 #endif 200 // Comfort noise for three different sampling frequencies. 201 NetEqDecoder::kDecoderCNGnb, NetEqDecoder::kDecoderCNGwb, 202 NetEqDecoder::kDecoderCNGswb32kHz, 203 #ifdef ENABLE_48000_HZ 204 NetEqDecoder::kDecoderCNGswb48kHz, 205 #endif 206 NetEqDecoder::kDecoderAVT, 207 #ifdef WEBRTC_CODEC_RED 208 NetEqDecoder::kDecoderRED, 209 #endif 210 }; 211 212 // Enumerator for error codes when asking for codec database id. 213 enum { 214 kInvalidCodec = -10, 215 kInvalidPayloadtype = -30, 216 kInvalidPacketSize = -40, 217 kInvalidRate = -50 218 }; 219 220 // Gets the codec id number from the database. If there is some mismatch in 221 // the codec settings, the function will return an error code. 222 // NOTE! The first mismatch found will generate the return value. 223 int ACMCodecDB::CodecNumber(const CodecInst& codec_inst) { 224 // Look for a matching codec in the database. 225 int codec_id = CodecId(codec_inst); 226 227 // Checks if we found a matching codec. 228 if (codec_id == -1) { 229 return kInvalidCodec; 230 } 231 232 // Checks the validity of payload type 233 if (!RentACodec::IsPayloadTypeValid(codec_inst.pltype)) { 234 return kInvalidPayloadtype; 235 } 236 237 // Comfort Noise is special case, packet-size & rate is not checked. 238 if (STR_CASE_CMP(database_[codec_id].plname, "CN") == 0) { 239 return codec_id; 240 } 241 242 // RED is special case, packet-size & rate is not checked. 243 if (STR_CASE_CMP(database_[codec_id].plname, "red") == 0) { 244 return codec_id; 245 } 246 247 // Checks the validity of packet size. 248 if (codec_settings_[codec_id].num_packet_sizes > 0) { 249 bool packet_size_ok = false; 250 int i; 251 int packet_size_samples; 252 for (i = 0; i < codec_settings_[codec_id].num_packet_sizes; i++) { 253 packet_size_samples = 254 codec_settings_[codec_id].packet_sizes_samples[i]; 255 if (codec_inst.pacsize == packet_size_samples) { 256 packet_size_ok = true; 257 break; 258 } 259 } 260 261 if (!packet_size_ok) { 262 return kInvalidPacketSize; 263 } 264 } 265 266 if (codec_inst.pacsize < 1) { 267 return kInvalidPacketSize; 268 } 269 270 // Check the validity of rate. Codecs with multiple rates have their own 271 // function for this. 272 if (STR_CASE_CMP("isac", codec_inst.plname) == 0) { 273 return IsISACRateValid(codec_inst.rate) ? codec_id : kInvalidRate; 274 } else if (STR_CASE_CMP("ilbc", codec_inst.plname) == 0) { 275 return IsILBCRateValid(codec_inst.rate, codec_inst.pacsize) 276 ? codec_id : kInvalidRate; 277 } else if (STR_CASE_CMP("opus", codec_inst.plname) == 0) { 278 return IsOpusRateValid(codec_inst.rate) 279 ? codec_id : kInvalidRate; 280 } 281 282 return database_[codec_id].rate == codec_inst.rate ? codec_id : kInvalidRate; 283 } 284 285 // Looks for a matching payload name, frequency, and channels in the 286 // codec list. Need to check all three since some codecs have several codec 287 // entries with different frequencies and/or channels. 288 // Does not check other codec settings, such as payload type and packet size. 289 // Returns the id of the codec, or -1 if no match is found. 290 int ACMCodecDB::CodecId(const CodecInst& codec_inst) { 291 return (CodecId(codec_inst.plname, codec_inst.plfreq, 292 codec_inst.channels)); 293 } 294 295 int ACMCodecDB::CodecId(const char* payload_name, 296 int frequency, 297 size_t channels) { 298 for (const CodecInst& ci : RentACodec::Database()) { 299 bool name_match = false; 300 bool frequency_match = false; 301 bool channels_match = false; 302 303 // Payload name, sampling frequency and number of channels need to match. 304 // NOTE! If |frequency| is -1, the frequency is not applicable, and is 305 // always treated as true, like for RED. 306 name_match = (STR_CASE_CMP(ci.plname, payload_name) == 0); 307 frequency_match = (frequency == ci.plfreq) || (frequency == -1); 308 // The number of channels must match for all codecs but Opus. 309 if (STR_CASE_CMP(payload_name, "opus") != 0) { 310 channels_match = (channels == ci.channels); 311 } else { 312 // For opus we just check that number of channels is valid. 313 channels_match = (channels == 1 || channels == 2); 314 } 315 316 if (name_match && frequency_match && channels_match) { 317 // We have found a matching codec in the list. 318 return &ci - RentACodec::Database().data(); 319 } 320 } 321 322 // We didn't find a matching codec. 323 return -1; 324 } 325 // Gets codec id number from database for the receiver. 326 int ACMCodecDB::ReceiverCodecNumber(const CodecInst& codec_inst) { 327 // Look for a matching codec in the database. 328 return CodecId(codec_inst); 329 } 330 331 } // namespace acm2 332 333 } // namespace webrtc 334