blob: cb63aea6cec84803e0a0e39ddc7c3493ef8e30af [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
tina.legrand@webrtc.orgdf697752012-02-08 10:22:21 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
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 * Implementation of the codec database.
13 */
14
15#include "codec_db.h"
16
17#include <string.h> /* to define NULL */
18
19#include "signal_processing_library.h"
20
21#include "neteq_error_codes.h"
22
23/*
24 * Resets the codec database.
25 */
26
27int WebRtcNetEQ_DbReset(CodecDbInst_t *inst)
28{
29 int i;
30
31 WebRtcSpl_MemSetW16((WebRtc_Word16*) inst, 0,
32 sizeof(CodecDbInst_t) / sizeof(WebRtc_Word16));
33
34 for (i = 0; i < NUM_TOTAL_CODECS; i++)
35 {
36 inst->position[i] = -1;
37 }
38
39 for (i = 0; i < NUM_CODECS; i++)
40 {
41 inst->payloadType[i] = -1;
42 }
43
44 for (i = 0; i < NUM_CNG_CODECS; i++)
45 {
46 inst->CNGpayloadType[i] = -1;
47 }
48
49 return 0;
50}
51
52/*
53 * Adds a new codec to the database.
54 */
55
56int WebRtcNetEQ_DbAdd(CodecDbInst_t *inst, enum WebRtcNetEQDecoder codec,
57 WebRtc_Word16 payloadType, FuncDecode funcDecode,
58 FuncDecode funcDecodeRCU, FuncDecodePLC funcDecodePLC,
59 FuncDecodeInit funcDecodeInit, FuncAddLatePkt funcAddLatePkt,
60 FuncGetMDinfo funcGetMDinfo, FuncGetPitchInfo funcGetPitch,
61 FuncUpdBWEst funcUpdBWEst, FuncGetErrorCode funcGetErrorCode,
62 void* codec_state, WebRtc_UWord16 codec_fs)
63{
64
65 int temp;
66 int insertCNGcodec = 0, overwriteCNGcodec = 0, CNGpos = -1;
67
68#ifndef NETEQ_RED_CODEC
69 if (codec == kDecoderRED)
70 {
71 return CODEC_DB_UNSUPPORTED_CODEC;
72 }
73#endif
74 if (((int) codec <= (int) kDecoderReservedStart) || ((int) codec
75 >= (int) kDecoderReservedEnd))
76 {
77 return CODEC_DB_UNSUPPORTED_CODEC;
78 }
79
80 if ((codec_fs != 8000)
81#ifdef NETEQ_WIDEBAND
82 &&(codec_fs!=16000)
83#endif
84#ifdef NETEQ_32KHZ_WIDEBAND
85 &&(codec_fs!=32000)
86#endif
87#ifdef NETEQ_48KHZ_WIDEBAND
88 &&(codec_fs!=48000)
89#endif
90 )
91 {
92 return CODEC_DB_UNSUPPORTED_FS;
93 }
94
95 /* Ensure that the codec type is supported */
96 switch (codec)
97 {
98#ifdef NETEQ_PCM16B_CODEC
99 case kDecoderPCM16B :
100#endif
101#ifdef NETEQ_G711_CODEC
102 case kDecoderPCMu :
103 case kDecoderPCMa :
104#endif
105#ifdef NETEQ_ILBC_CODEC
106 case kDecoderILBC :
107#endif
108#ifdef NETEQ_ISAC_CODEC
109 case kDecoderISAC :
110#endif
111#ifdef NETEQ_ISAC_SWB_CODEC
112 case kDecoderISACswb :
113#endif
114#ifdef NETEQ_G722_CODEC
115 case kDecoderG722 :
116#endif
117#ifdef NETEQ_WIDEBAND
118 case kDecoderPCM16Bwb :
119#endif
120#ifdef NETEQ_32KHZ_WIDEBAND
121 case kDecoderPCM16Bswb32kHz :
122#endif
123#ifdef NETEQ_CNG_CODEC
124 case kDecoderCNG :
125#endif
126#ifdef NETEQ_ATEVENT_DECODE
127 case kDecoderAVT :
128#endif
129#ifdef NETEQ_RED_CODEC
130 case kDecoderRED :
131#endif
132#ifdef NETEQ_48KHZ_WIDEBAND
133 case kDecoderPCM16Bswb48kHz :
134#endif
135#ifdef NETEQ_ARBITRARY_CODEC
136 case kDecoderArbitrary:
137#endif
138#ifdef NETEQ_G729_CODEC
139 case kDecoderG729:
140#endif
141#ifdef NETEQ_G729_1_CODEC
142 case kDecoderG729_1 :
143#endif
144#ifdef NETEQ_G726_CODEC
145 case kDecoderG726_16 :
146 case kDecoderG726_24 :
147 case kDecoderG726_32 :
148 case kDecoderG726_40 :
149#endif
150#ifdef NETEQ_G722_1_CODEC
151 case kDecoderG722_1_16 :
152 case kDecoderG722_1_24 :
153 case kDecoderG722_1_32 :
154#endif
155#ifdef NETEQ_G722_1C_CODEC
156 case kDecoderG722_1C_24 :
157 case kDecoderG722_1C_32 :
158 case kDecoderG722_1C_48 :
159#endif
160#ifdef NETEQ_SPEEX_CODEC
161 case kDecoderSPEEX_8 :
162 case kDecoderSPEEX_16 :
163#endif
tina.legrand@webrtc.orgdf697752012-02-08 10:22:21 +0000164#ifdef NETEQ_CELT_CODEC
165 case kDecoderCELT_32 :
166#endif
niklase@google.com470e71d2011-07-07 08:21:25 +0000167#ifdef NETEQ_GSMFR_CODEC
168 case kDecoderGSMFR :
169#endif
170#ifdef NETEQ_AMR_CODEC
171 case kDecoderAMR :
172#endif
173#ifdef NETEQ_AMRWB_CODEC
174 case kDecoderAMRWB :
175#endif
176 {
177 /* If we end up here, the inserted codec is supported => Do nothing */
178 break;
179 }
180 default:
181 {
182 /* If we get to this point, the inserted codec is not supported */
183 return CODEC_DB_UNSUPPORTED_CODEC;
184 }
185 }
186
187 /* Check to see if payload type is taken */
188 if (WebRtcNetEQ_DbGetCodec(inst, payloadType) > 0)
189 {
190 return CODEC_DB_PAYLOAD_TAKEN;
191 }
192
193 /* Special case for CNG codecs */
194 if (codec == kDecoderCNG)
195 {
196 /* check if this is first CNG codec to be registered */
197 if (WebRtcNetEQ_DbGetPayload(inst, codec) == CODEC_DB_NOT_EXIST2)
198 {
199 /* no other CNG codec found */
200 insertCNGcodec = 1;
201 }
202
203 /* find the appropriate insert position in CNG payload vector */
204 switch (codec_fs)
205 {
206#ifdef NETEQ_WIDEBAND
207 case 16000:
208 CNGpos = 1;
209 break;
210#endif
211#ifdef NETEQ_32KHZ_WIDEBAND
212 case 32000:
213 CNGpos = 2;
214 break;
215#endif
216#ifdef NETEQ_48KHZ_WIDEBAND
217 case 48000:
218 CNGpos = 3;
219 break;
220#endif
221 default: /* 8000 Hz case */
222 CNGpos = 0;
223 /*
224 * The 8 kHz CNG payload type is the one associated with the regular codec DB
225 * should override any other setting.
226 * Overwrite if this isn't the first CNG
227 */
228 overwriteCNGcodec = !insertCNGcodec;
229 break;
230 }
231
232 /* insert CNG payload type */
233 inst->CNGpayloadType[CNGpos] = payloadType;
234
235 }
236
237 if ((codec != kDecoderCNG) || (insertCNGcodec == 1) || (overwriteCNGcodec == 1))
238 {
239 /* Check if we have reached the maximum numbers of simultaneous codecs */
240 if (inst->nrOfCodecs == NUM_CODECS) return CODEC_DB_FULL;
241
242 /* Check that codec has not already been initialized to DB =>
243 remove it and reinitialize according to new spec */
244 if ((inst->position[codec] != -1) && (overwriteCNGcodec != 1))
245 { /* if registering multiple CNG codecs, don't remove, just overwrite */
246 WebRtcNetEQ_DbRemove(inst, codec);
247 }
248
249 if (overwriteCNGcodec == 1)
250 {
251 temp = inst->position[codec];
252 }
253 else
254 {
255 temp = inst->nrOfCodecs; /* Store this codecs position */
256 inst->position[codec] = temp;
257 inst->nrOfCodecs++;
258 }
259
260 inst->payloadType[temp] = payloadType;
261
262 /* Copy to database */
263 inst->codec_state[temp] = codec_state;
264 inst->funcDecode[temp] = funcDecode;
265 inst->funcDecodeRCU[temp] = funcDecodeRCU;
266 inst->funcAddLatePkt[temp] = funcAddLatePkt;
267 inst->funcDecodeInit[temp] = funcDecodeInit;
268 inst->funcDecodePLC[temp] = funcDecodePLC;
269 inst->funcGetMDinfo[temp] = funcGetMDinfo;
270 inst->funcGetPitch[temp] = funcGetPitch;
271 inst->funcUpdBWEst[temp] = funcUpdBWEst;
272 inst->funcGetErrorCode[temp] = funcGetErrorCode;
273 inst->codec_fs[temp] = codec_fs;
274
275 }
276
277 return 0;
278}
279
280/*
281 * Removes a codec from the database.
282 */
283
284int WebRtcNetEQ_DbRemove(CodecDbInst_t *inst, enum WebRtcNetEQDecoder codec)
285{
286 int i;
287 int pos = -1;
288
289#ifndef NETEQ_RED_CODEC
290 if (codec == kDecoderRED)
291 {
292 return CODEC_DB_UNSUPPORTED_CODEC;
293 }
294#endif
295 if (((int) codec <= (int) kDecoderReservedStart) || ((int) codec
296 >= (int) kDecoderReservedEnd))
297 {
298 return CODEC_DB_UNSUPPORTED_CODEC;
299 }
300
301 pos = inst->position[codec];
302 if (pos == -1)
303 {
304 return CODEC_DB_NOT_EXIST4;
305 }
306 else
307 {
308 /* Remove this codec */
309 inst->position[codec] = -1;
310 for (i = pos; i < (inst->nrOfCodecs - 1); i++)
311 {
312 inst->payloadType[i] = inst->payloadType[i + 1];
313 inst->codec_state[i] = inst->codec_state[i + 1];
314 inst->funcDecode[i] = inst->funcDecode[i + 1];
315 inst->funcDecodeRCU[i] = inst->funcDecodeRCU[i + 1];
316 inst->funcAddLatePkt[i] = inst->funcAddLatePkt[i + 1];
317 inst->funcDecodeInit[i] = inst->funcDecodeInit[i + 1];
318 inst->funcDecodePLC[i] = inst->funcDecodePLC[i + 1];
319 inst->funcGetMDinfo[i] = inst->funcGetMDinfo[i + 1];
320 inst->funcGetPitch[i] = inst->funcGetPitch[i + 1];
321 inst->funcUpdBWEst[i] = inst->funcUpdBWEst[i + 1];
322 inst->funcGetErrorCode[i] = inst->funcGetErrorCode[i + 1];
323 inst->codec_fs[i] = inst->codec_fs[i + 1];
324 }
325 inst->payloadType[i] = -1;
326 inst->codec_state[i] = NULL;
327 inst->funcDecode[i] = NULL;
328 inst->funcDecodeRCU[i] = NULL;
329 inst->funcAddLatePkt[i] = NULL;
330 inst->funcDecodeInit[i] = NULL;
331 inst->funcDecodePLC[i] = NULL;
332 inst->funcGetMDinfo[i] = NULL;
333 inst->funcGetPitch[i] = NULL;
334 inst->funcUpdBWEst[i] = NULL;
335 inst->funcGetErrorCode[i] = NULL;
336 inst->codec_fs[i] = 0;
337 /* Move down all the codecs above this one */
338 for (i = 0; i < NUM_TOTAL_CODECS; i++)
339 {
340 if (inst->position[i] >= pos)
341 {
342 inst->position[i] = inst->position[i] - 1;
343 }
344 }
345 inst->nrOfCodecs--;
346
347 if (codec == kDecoderCNG)
348 {
349 /* also remove all registered CNG payload types */
350 for (i = 0; i < NUM_CNG_CODECS; i++)
351 {
352 inst->CNGpayloadType[i] = -1;
353 }
354 }
355 }
356 return 0;
357}
358
359/*
360 * Get the decoder function pointers for a codec.
361 */
362
363int WebRtcNetEQ_DbGetPtrs(CodecDbInst_t *inst, enum WebRtcNetEQDecoder codec,
364 CodecFuncInst_t *ptr_inst)
365{
366
367 int pos = inst->position[codec];
368 if ((codec <= kDecoderReservedStart) || (codec >= kDecoderReservedEnd) || (codec
369 > NUM_TOTAL_CODECS))
370 {
371 /* ERROR */
372 pos = -1;
373 }
374 if (pos >= 0)
375 {
376 ptr_inst->codec_state = inst->codec_state[pos];
377 ptr_inst->funcAddLatePkt = inst->funcAddLatePkt[pos];
378 ptr_inst->funcDecode = inst->funcDecode[pos];
379 ptr_inst->funcDecodeRCU = inst->funcDecodeRCU[pos];
380 ptr_inst->funcDecodeInit = inst->funcDecodeInit[pos];
381 ptr_inst->funcDecodePLC = inst->funcDecodePLC[pos];
382 ptr_inst->funcGetMDinfo = inst->funcGetMDinfo[pos];
383 ptr_inst->funcUpdBWEst = inst->funcUpdBWEst[pos];
384 ptr_inst->funcGetErrorCode = inst->funcGetErrorCode[pos];
385 ptr_inst->codec_fs = inst->codec_fs[pos];
386 return 0;
387 }
388 else
389 {
390 WebRtcSpl_MemSetW16((WebRtc_Word16*) ptr_inst, 0,
391 sizeof(CodecFuncInst_t) / sizeof(WebRtc_Word16));
392 return CODEC_DB_NOT_EXIST1;
393 }
394}
395
396/*
397 * Returns payload number given a codec identifier.
398 */
399
400int WebRtcNetEQ_DbGetPayload(CodecDbInst_t *inst, enum WebRtcNetEQDecoder codecID)
401{
402 if (inst->position[codecID] == -1)
403 return CODEC_DB_NOT_EXIST2;
404 else
405 return (inst->payloadType[inst->position[codecID]]);
406
407}
408
409/*
410 * Returns codec identifier given a payload number.
411 * Returns -1 if the payload type does not exist.
412 */
413
414int WebRtcNetEQ_DbGetCodec(CodecDbInst_t *inst, int payloadType)
415{
416 int i, pos;
417
418 for (i = 0; i < NUM_TOTAL_CODECS; i++)
419 {
420 pos = inst->position[i];
421 if (pos != -1)
422 {
423 if (inst->payloadType[pos] == payloadType) return i;
424 }
425 }
426
427 /* did not find payload type */
428 /* check if it's a CNG codec */
429 if (WebRtcNetEQ_DbIsCNGPayload(inst, payloadType))
430 {
431 return kDecoderCNG;
432 }
433
434 /* found no match */
435 return CODEC_DB_NOT_EXIST3;
436}
437
438/*
439 * Extracts the Payload Split information of the codec with the specified payloadType.
440 */
441
442int WebRtcNetEQ_DbGetSplitInfo(SplitInfo_t *inst, enum WebRtcNetEQDecoder codecID,
443 int codedsize)
444{
445
446 switch (codecID)
447 {
448#ifdef NETEQ_ISAC_CODEC
449 case kDecoderISAC:
450#endif
451#ifdef NETEQ_ISAC_SWB_CODEC
452 case kDecoderISACswb:
453#endif
454#ifdef NETEQ_ARBITRARY_CODEC
455 case kDecoderArbitrary:
456#endif
457#ifdef NETEQ_AMR_CODEC
458 case kDecoderAMR:
459#endif
460#ifdef NETEQ_AMRWB_CODEC
461 case kDecoderAMRWB:
462#endif
463#ifdef NETEQ_G726_CODEC
464 /* Treat G726 as non-splittable to simplify the implementation */
465 case kDecoderG726_16:
466 case kDecoderG726_24:
467 case kDecoderG726_32:
468 case kDecoderG726_40:
469#endif
470#ifdef NETEQ_SPEEX_CODEC
471 case kDecoderSPEEX_8:
472 case kDecoderSPEEX_16:
473#endif
tina.legrand@webrtc.orgdf697752012-02-08 10:22:21 +0000474#ifdef NETEQ_CELT_CODEC
475 case kDecoderCELT_32 :
476#endif
niklase@google.com470e71d2011-07-07 08:21:25 +0000477#ifdef NETEQ_G729_1_CODEC
478 case kDecoderG729_1:
479#endif
480 {
481 /* These codecs' payloads are not splittable */
482 inst->deltaBytes = NO_SPLIT;
483 return 0;
484 }
485
486 /*
487 * Sample based coders are a special case.
488 * In this case, deltaTime signals the number of bytes per timestamp unit times 2
489 * in log2 domain.
490 */
491#if (defined NETEQ_G711_CODEC)
492 case kDecoderPCMu:
493 case kDecoderPCMa:
494 {
495 inst->deltaBytes = -12;
496 inst->deltaTime = 1;
497 return 0;
498 }
499#endif
500#if (defined NETEQ_G722_CODEC)
501 case kDecoderG722:
502 {
503 inst->deltaBytes = -14;
504 inst->deltaTime = 0;
505 return 0;
506 }
507#endif
508#if (defined NETEQ_PCM16B_CODEC)
509 case kDecoderPCM16B:
510 {
511 inst->deltaBytes = -12;
512 inst->deltaTime = 2;
513 return 0;
514 }
515#endif
516#if ((defined NETEQ_PCM16B_CODEC)&&(defined NETEQ_WIDEBAND))
517 case kDecoderPCM16Bwb:
518 {
519 inst->deltaBytes = -14;
520 inst->deltaTime = 2;
521 return 0;
522 }
523#endif
524#if ((defined NETEQ_PCM16B_CODEC)&&(defined NETEQ_32KHZ_WIDEBAND))
525 case kDecoderPCM16Bswb32kHz:
526 {
527 inst->deltaBytes = -18;
528 inst->deltaTime = 2;
529 return 0;
530 }
531#endif
532#if ((defined NETEQ_PCM16B_CODEC)&&(defined NETEQ_48KHZ_WIDEBAND))
533 case kDecoderPCM16Bswb48kHz:
534 {
535 inst->deltaBytes = -22;
536 inst->deltaTime = 2;
537 return 0;
538 }
539#endif
540
541 /* Splittable payloads */
542#ifdef NETEQ_G722_1_CODEC
543 case kDecoderG722_1_16:
544 {
545 inst->deltaBytes = 40;
546 inst->deltaTime = 320;
547 return 0;
548 }
549 case kDecoderG722_1_24:
550 {
551 inst->deltaBytes = 60;
552 inst->deltaTime = 320;
553 return 0;
554 }
555 case kDecoderG722_1_32:
556 {
557 inst->deltaBytes = 80;
558 inst->deltaTime = 320;
559 return 0;
560 }
561#endif
562#ifdef NETEQ_G722_1C_CODEC
563 case kDecoderG722_1C_24:
564 {
565 inst->deltaBytes = 60;
566 inst->deltaTime = 640;
567 return 0;
568 }
569 case kDecoderG722_1C_32:
570 {
571 inst->deltaBytes = 80;
572 inst->deltaTime = 640;
573 return 0;
574 }
575 case kDecoderG722_1C_48:
576 {
577 inst->deltaBytes = 120;
578 inst->deltaTime = 640;
579 return 0;
580 }
581#endif
582#ifdef NETEQ_G729_CODEC
583 case kDecoderG729:
584 {
585 inst->deltaBytes = 10;
586 inst->deltaTime = 80;
587 return 0;
588 }
589#endif
590#ifdef NETEQ_ILBC_CODEC
591 case kDecoderILBC:
592 {
593 /* Check for splitting of iLBC packets.
594 * If payload size is a multiple of 50 bytes it should be split into 30ms frames.
595 * If payload size is a multiple of 38 bytes it should be split into 20ms frames.
596 * Least common multiplier between 38 and 50 is 950, so the payload size must be less than
597 * 950 bytes in order to resolve the frames unambiguously.
598 * Currently max 12 frames in one bundle.
599 */
600 switch (codedsize)
601 {
602 case 50:
603 case 100:
604 case 150:
605 case 200:
606 case 250:
607 case 300:
608 case 350:
609 case 400:
610 case 450:
611 case 500:
612 case 550:
613 case 600:
614 {
615 inst->deltaBytes = 50;
616 inst->deltaTime = 240;
617 break;
618 }
619 case 38:
620 case 76:
621 case 114:
622 case 152:
623 case 190:
624 case 228:
625 case 266:
626 case 304:
627 case 342:
628 case 380:
629 case 418:
630 case 456:
631 {
632 inst->deltaBytes = 38;
633 inst->deltaTime = 160;
634 break;
635 }
636 default:
637 {
638 return AMBIGUOUS_ILBC_FRAME_SIZE; /* Something not supported... */
639 }
640 }
641 return 0;
642 }
643#endif
644#ifdef NETEQ_GSMFR_CODEC
645 case kDecoderGSMFR:
646 {
647 inst->deltaBytes = 33;
648 inst->deltaTime = 160;
649 return 0;
650 }
651#endif
652 default:
653 { /*Unknown codec */
654 inst->deltaBytes = NO_SPLIT;
655 return CODEC_DB_UNKNOWN_CODEC;
656 }
657 } /* end of switch */
658}
659
660/*
661 * Returns 1 if codec is multiple description, 0 otherwise.
662 * NOTE: This function is a stub, since there currently are no MD codecs.
663 */
664int WebRtcNetEQ_DbIsMDCodec(enum WebRtcNetEQDecoder codecID)
665{
666 if (0) /* Add test for MD codecs here */
667 return 1;
668 else
669 return 0;
670}
671
672/*
673 * Returns 1 if payload type is registered as a CNG codec, 0 otherwise
674 */
675int WebRtcNetEQ_DbIsCNGPayload(CodecDbInst_t *inst, int payloadType)
676{
677#ifdef NETEQ_CNG_CODEC
678 int i;
679
680 for(i=0; i<NUM_CNG_CODECS; i++)
681 {
682 if( (inst->CNGpayloadType[i] != -1) && (inst->CNGpayloadType[i] == payloadType) )
683 {
684 return 1;
685 }
686 }
687#endif
688
689 return 0;
690
691}
692
693/*
694 * Return the sample rate for the codec with the given payload type, 0 if error
695 */
696WebRtc_UWord16 WebRtcNetEQ_DbGetSampleRate(CodecDbInst_t *inst, int payloadType)
697{
698 int i;
699 CodecFuncInst_t codecInst;
700
701 /* Sanity */
702 if (inst == NULL)
703 {
704 /* return 0 Hz */
705 return 0;
706 }
707
708 /* Check among CNG payloads */
709 for (i = 0; i < NUM_CNG_CODECS; i++)
710 {
711 if ((inst->CNGpayloadType[i] != -1) && (inst->CNGpayloadType[i] == payloadType))
712 {
713 switch (i)
714 {
715 case 1:
716 return 16000;
717 case 2:
718 return 32000;
719 case 3:
720 return 48000;
721 default:
722 return 8000;
723 }
724 }
725 }
726
727 /* Not a CNG payload, check the other payloads */
728 i = WebRtcNetEQ_DbGetCodec(inst, payloadType);
729 if (i >= 0)
730 {
731 if (WebRtcNetEQ_DbGetPtrs(inst, (enum WebRtcNetEQDecoder) i, &codecInst) != 0)
732 {
733 /* Unexpected error, return 0 Hz */
734 return 0;
735 }
736 return codecInst.codec_fs;
737 }
738
739 /* If we end up here, we got an error, return 0 Hz */
740 return 0;
741
742}
743