Asterisk - The Open Source Telephony Project  21.4.1
codec_builtin.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2014, Digium, Inc.
5  *
6  * Joshua Colp <jcolp@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 /*! \file
20  *
21  * \brief Built-in supported codecs
22  *
23  * \author Joshua Colp <jcolp@digium.com>
24  */
25 
26 /*** MODULEINFO
27  <support_level>core</support_level>
28  ***/
29 
30 #include "asterisk.h"
31 
32 #include "asterisk/ilbc.h"
33 #include "asterisk/logger.h"
34 #include "asterisk/astobj2.h"
35 #include "asterisk/codec.h"
36 #include "asterisk/format.h"
37 #include "asterisk/format_cache.h"
38 #include "asterisk/frame.h"
39 #include "asterisk/smoother.h"
40 
41 int __ast_codec_register_with_format(struct ast_codec *codec, const char *format_name,
42  struct ast_module *mod);
43 
44 enum frame_type {
45  TYPE_HIGH, /* 0x0 */
46  TYPE_LOW, /* 0x1 */
47  TYPE_SILENCE, /* 0x2 */
48  TYPE_DONTSEND /* 0x3 */
49 };
50 
51 #define TYPE_MASK 0x3
52 
53 static int g723_len(unsigned char buf)
54 {
55  enum frame_type type = buf & TYPE_MASK;
56 
57  switch(type) {
58  case TYPE_DONTSEND:
59  return 0;
60  break;
61  case TYPE_SILENCE:
62  return 4;
63  break;
64  case TYPE_HIGH:
65  return 24;
66  break;
67  case TYPE_LOW:
68  return 20;
69  break;
70  default:
71  ast_log(LOG_WARNING, "Badly encoded frame (%u)\n", type);
72  }
73  return -1;
74 }
75 
76 static int g723_samples(struct ast_frame *frame)
77 {
78  unsigned char *buf = frame->data.ptr;
79  int pos = 0, samples = 0, res;
80 
81  while(pos < frame->datalen) {
82  res = g723_len(buf[pos]);
83  if (res <= 0)
84  break;
85  samples += 240;
86  pos += res;
87  }
88 
89  return samples;
90 }
91 
92 static int g723_length(unsigned int samples)
93 {
94  return (samples / 240) * 20;
95 }
96 
97 static struct ast_codec g723 = {
98  .name = "g723",
99  .description = "G.723.1",
100  .type = AST_MEDIA_TYPE_AUDIO,
101  .sample_rate = 8000,
102  .minimum_ms = 30,
103  .maximum_ms = 300,
104  .default_ms = 30,
105  .minimum_bytes = 20,
106  .samples_count = g723_samples,
107  .get_length = g723_length,
108  .quality = 20,
109 };
110 
111 static int codec2_samples(struct ast_frame *frame)
112 {
113  return 160 * (frame->datalen / 6);
114 }
115 
116 static int codec2_length(unsigned int samples)
117 {
118  return (samples / 160) * 6;
119 }
120 
121 static struct ast_codec codec2 = {
122  .name = "codec2",
123  .description = "Codec 2",
124  .type = AST_MEDIA_TYPE_AUDIO,
125  .sample_rate = 8000,
126  .minimum_ms = 20,
127  .maximum_ms = 300,
128  .default_ms = 20,
129  .minimum_bytes = 6,
130  .samples_count = codec2_samples,
131  .get_length = codec2_length,
132  .smooth = 1,
133 };
134 
135 static int none_samples(struct ast_frame *frame)
136 {
137  return frame->datalen;
138 }
139 
140 static int none_length(unsigned int samples) {
141  return samples;
142 }
143 
144 static struct ast_codec none = {
145  .name = "none",
146  .description = "<Null> codec",
147  .type = AST_MEDIA_TYPE_AUDIO,
148  .sample_rate = 8000, /* This must have some sample rate to prevent divide by 0 */
149  .minimum_ms = 10,
150  .maximum_ms = 140,
151  .default_ms = 20,
152  .minimum_bytes = 20,
153  .samples_count = none_samples,
154  .get_length = none_length,
155 };
156 
157 static int ulaw_samples(struct ast_frame *frame)
158 {
159  return frame->datalen;
160 }
161 
162 static int ulaw_length(unsigned int samples)
163 {
164  return samples;
165 }
166 
167 static struct ast_codec ulaw = {
168  .name = "ulaw",
169  .description = "G.711 u-law",
170  .type = AST_MEDIA_TYPE_AUDIO,
171  .sample_rate = 8000,
172  .minimum_ms = 10,
173  .maximum_ms = 140,
174  .default_ms = 20,
175  .minimum_bytes = 80,
176  .samples_count = ulaw_samples,
177  .get_length = ulaw_length,
178  .smooth = 1,
179  .quality = 100, /* We are the gold standard. */
180 };
181 
182 static struct ast_codec alaw = {
183  .name = "alaw",
184  .description = "G.711 a-law",
185  .type = AST_MEDIA_TYPE_AUDIO,
186  .sample_rate = 8000,
187  .minimum_ms = 10,
188  .maximum_ms = 140,
189  .default_ms = 20,
190  .minimum_bytes = 80,
191  .samples_count = ulaw_samples,
192  .get_length = ulaw_length,
193  .smooth = 1,
194  .quality = 100, /* Just as good as ulaw */
195 };
196 
197 static int gsm_samples(struct ast_frame *frame)
198 {
199  return 160 * (frame->datalen / 33);
200 }
201 
202 static int gsm_length(unsigned int samples)
203 {
204  return (samples / 160) * 33;
205 }
206 
207 static struct ast_codec gsm = {
208  .name = "gsm",
209  .description = "GSM",
210  .type = AST_MEDIA_TYPE_AUDIO,
211  .sample_rate = 8000,
212  .minimum_ms = 20,
213  .maximum_ms = 300,
214  .default_ms = 20,
215  .minimum_bytes = 33,
216  .samples_count = gsm_samples,
217  .get_length = gsm_length,
218  .smooth = 1,
219  .quality = 60,
220 };
221 
222 static int g726_samples(struct ast_frame *frame)
223 {
224  return frame->datalen * 2;
225 }
226 
227 static int g726_length(unsigned int samples)
228 {
229  return samples / 2;
230 }
231 
232 static struct ast_codec g726rfc3551 = {
233  .name = "g726",
234  .description = "G.726 RFC3551",
235  .type = AST_MEDIA_TYPE_AUDIO,
236  .sample_rate = 8000,
237  .minimum_ms = 10,
238  .maximum_ms = 300,
239  .default_ms = 20,
240  .minimum_bytes = 40,
241  .samples_count = g726_samples,
242  .get_length = g726_length,
243  .smooth = 1,
244  .quality = 85,
245 };
246 
247 static struct ast_codec g726aal2 = {
248  .name = "g726aal2",
249  .description = "G.726 AAL2",
250  .type = AST_MEDIA_TYPE_AUDIO,
251  .sample_rate = 8000,
252  .minimum_ms = 10,
253  .maximum_ms = 300,
254  .default_ms = 20,
255  .minimum_bytes = 40,
256  .samples_count = g726_samples,
257  .get_length = g726_length,
258  .smooth = 1,
259  .quality = 85,
260 };
261 
262 static struct ast_codec adpcm = {
263  .name = "adpcm",
264  .description = "Dialogic ADPCM",
265  .type = AST_MEDIA_TYPE_AUDIO,
266  .sample_rate = 8000,
267  .minimum_ms = 10,
268  .maximum_ms = 300,
269  .default_ms = 20,
270  .minimum_bytes = 40,
271  .samples_count = g726_samples,
272  .get_length = g726_length,
273  .smooth = 1,
274  .quality = 80,
275 };
276 
277 static int slin_samples(struct ast_frame *frame)
278 {
279  return frame->datalen / 2;
280 }
281 
282 static int slin_length(unsigned int samples)
283 {
284  return samples * 2;
285 }
286 
287 static struct ast_codec slin8 = {
288  .name = "slin",
289  .description = "16 bit Signed Linear PCM",
290  .type = AST_MEDIA_TYPE_AUDIO,
291  .sample_rate = 8000,
292  .minimum_ms = 10,
293  .maximum_ms = 60,
294  .default_ms = 20,
295  .minimum_bytes = 160,
296  .samples_count = slin_samples,
297  .get_length = slin_length,
298  .smooth = 1,
299  .smoother_flags = AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED,
300  .quality = 115, /* Better than ulaw */
301 };
302 
303 static struct ast_codec slin12 = {
304  .name = "slin",
305  .description = "16 bit Signed Linear PCM (12kHz)",
306  .type = AST_MEDIA_TYPE_AUDIO,
307  .sample_rate = 12000,
308  .minimum_ms = 10,
309  .maximum_ms = 60,
310  .default_ms = 20,
311  .minimum_bytes = 240,
312  .samples_count = slin_samples,
313  .get_length = slin_length,
314  .smooth = 1,
315  .smoother_flags = AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED,
316  .quality = 116,
317 };
318 
319 static struct ast_codec slin16 = {
320  .name = "slin",
321  .description = "16 bit Signed Linear PCM (16kHz)",
322  .type = AST_MEDIA_TYPE_AUDIO,
323  .sample_rate = 16000,
324  .minimum_ms = 10,
325  .maximum_ms = 60,
326  .default_ms = 20,
327  .minimum_bytes = 320,
328  .samples_count = slin_samples,
329  .get_length = slin_length,
330  .smooth = 1,
331  .smoother_flags = AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED,
332  .quality = 117,
333 };
334 
335 static struct ast_codec slin24 = {
336  .name = "slin",
337  .description = "16 bit Signed Linear PCM (24kHz)",
338  .type = AST_MEDIA_TYPE_AUDIO,
339  .sample_rate = 24000,
340  .minimum_ms = 10,
341  .maximum_ms = 60,
342  .default_ms = 20,
343  .minimum_bytes = 480,
344  .samples_count = slin_samples,
345  .get_length = slin_length,
346  .smooth = 1,
347  .smoother_flags = AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED,
348  .quality = 118,
349 };
350 
351 static struct ast_codec slin32 = {
352  .name = "slin",
353  .description = "16 bit Signed Linear PCM (32kHz)",
354  .type = AST_MEDIA_TYPE_AUDIO,
355  .sample_rate = 32000,
356  .minimum_ms = 10,
357  .maximum_ms = 60,
358  .default_ms = 20,
359  .minimum_bytes = 640,
360  .samples_count = slin_samples,
361  .get_length = slin_length,
362  .smooth = 1,
363  .smoother_flags = AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED,
364  .quality = 119,
365 };
366 
367 static struct ast_codec slin44 = {
368  .name = "slin",
369  .description = "16 bit Signed Linear PCM (44kHz)",
370  .type = AST_MEDIA_TYPE_AUDIO,
371  .sample_rate = 44100,
372  .minimum_ms = 10,
373  .maximum_ms = 60,
374  .default_ms = 20,
375  .minimum_bytes = 882,
376  .samples_count = slin_samples,
377  .get_length = slin_length,
378  .smooth = 1,
379  .smoother_flags = AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED,
380  .quality = 120,
381 };
382 
383 static struct ast_codec slin48 = {
384  .name = "slin",
385  .description = "16 bit Signed Linear PCM (48kHz)",
386  .type = AST_MEDIA_TYPE_AUDIO,
387  .sample_rate = 48000,
388  .minimum_ms = 10,
389  .maximum_ms = 60,
390  .default_ms = 20,
391  .minimum_bytes = 960,
392  .samples_count = slin_samples,
393  .get_length = slin_length,
394  .smooth = 1,
395  .smoother_flags = AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED,
396  .quality = 121,
397 };
398 
399 static struct ast_codec slin96 = {
400  .name = "slin",
401  .description = "16 bit Signed Linear PCM (96kHz)",
402  .type = AST_MEDIA_TYPE_AUDIO,
403  .sample_rate = 96000,
404  .minimum_ms = 10,
405  .maximum_ms = 60,
406  .default_ms = 20,
407  .minimum_bytes = 1920,
408  .samples_count = slin_samples,
409  .get_length = slin_length,
410  .smooth = 1,
411  .smoother_flags = AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED,
412  .quality = 122,
413 };
414 
415 static struct ast_codec slin192 = {
416  .name = "slin",
417  .description = "16 bit Signed Linear PCM (192kHz)",
418  .type = AST_MEDIA_TYPE_AUDIO,
419  .sample_rate = 192000,
420  .minimum_ms = 10,
421  .maximum_ms = 60,
422  .default_ms = 20,
423  .minimum_bytes = 3840,
424  .samples_count = slin_samples,
425  .get_length = slin_length,
426  .smooth = 1,
427  .smoother_flags = AST_SMOOTHER_FLAG_BE | AST_SMOOTHER_FLAG_FORCED,
428  .quality = 123,
429 };
430 
431 static int lpc10_samples(struct ast_frame *frame)
432 {
433  int samples = 22 * 8;
434 
435  /* assumes that the RTP packet contains one LPC10 frame */
436  samples += (((char *)(frame->data.ptr))[7] & 0x1) * 8;
437 
438  return samples;
439 }
440 
441 static struct ast_codec lpc10 = {
442  .name = "lpc10",
443  .description = "LPC10",
444  .type = AST_MEDIA_TYPE_AUDIO,
445  .sample_rate = 8000,
446  .minimum_ms = 20,
447  .maximum_ms = 20,
448  .default_ms = 20,
449  .minimum_bytes = 7,
450  .samples_count = lpc10_samples,
451  .smooth = 1,
452  .quality = 25,
453 };
454 
455 static int g729_samples(struct ast_frame *frame)
456 {
457  return frame->datalen * 8;
458 }
459 
460 static int g729_length(unsigned int samples)
461 {
462  return samples / 8;
463 }
464 
465 static struct ast_codec g729a = {
466  .name = "g729",
467  .description = "G.729A",
468  .type = AST_MEDIA_TYPE_AUDIO,
469  .sample_rate = 8000,
470  .minimum_ms = 10,
471  .maximum_ms = 220,
472  .default_ms = 20,
473  .minimum_bytes = 10,
474  .samples_count = g729_samples,
475  .get_length = g729_length,
476  .smooth = 1,
477  .smoother_flags = AST_SMOOTHER_FLAG_G729,
478  .quality = 20,
479 };
480 
481 static unsigned char get_n_bits_at(unsigned char *data, int n, int bit)
482 {
483  int byte = bit / 8; /* byte containing first bit */
484  int rem = 8 - (bit % 8); /* remaining bits in first byte */
485  unsigned char ret = 0;
486 
487  if (n <= 0 || n > 8)
488  return 0;
489 
490  if (rem < n) {
491  ret = (data[byte] << (n - rem));
492  ret |= (data[byte + 1] >> (8 - n + rem));
493  } else {
494  ret = (data[byte] >> (rem - n));
495  }
496 
497  return (ret & (0xff >> (8 - n)));
498 }
499 
500 static int speex_get_wb_sz_at(unsigned char *data, int len, int bit)
501 {
502  static const int SpeexWBSubModeSz[] = {
503  4, 36, 112, 192,
504  352, 0, 0, 0 };
505  int off = bit;
506  unsigned char c;
507 
508  /* skip up to two wideband frames */
509  if (((len * 8 - off) >= 5) &&
510  get_n_bits_at(data, 1, off)) {
511  c = get_n_bits_at(data, 3, off + 1);
512  off += SpeexWBSubModeSz[c];
513 
514  if (((len * 8 - off) >= 5) &&
515  get_n_bits_at(data, 1, off)) {
516  c = get_n_bits_at(data, 3, off + 1);
517  off += SpeexWBSubModeSz[c];
518 
519  if (((len * 8 - off) >= 5) &&
520  get_n_bits_at(data, 1, off)) {
521  ast_log(LOG_WARNING, "Encountered corrupt speex frame; too many wideband frames in a row.\n");
522  return -1;
523  }
524  }
525 
526  }
527  return off - bit;
528 }
529 
530 static int speex_samples(unsigned char *data, int len)
531 {
532  static const int SpeexSubModeSz[] = {
533  5, 43, 119, 160,
534  220, 300, 364, 492,
535  79, 0, 0, 0,
536  0, 0, 0, 0 };
537  static const int SpeexInBandSz[] = {
538  1, 1, 4, 4,
539  4, 4, 4, 4,
540  8, 8, 16, 16,
541  32, 32, 64, 64 };
542  int bit = 0;
543  int cnt = 0;
544  int off;
545  unsigned char c;
546 
547  while ((len * 8 - bit) >= 5) {
548  /* skip wideband frames */
549  off = speex_get_wb_sz_at(data, len, bit);
550  if (off < 0) {
551  ast_log(LOG_WARNING, "Had error while reading wideband frames for speex samples\n");
552  break;
553  }
554  bit += off;
555 
556  if ((len * 8 - bit) < 5)
557  break;
558 
559  /* get control bits */
560  c = get_n_bits_at(data, 5, bit);
561  bit += 5;
562 
563  if (c == 15) {
564  /* terminator */
565  break;
566  } else if (c == 14) {
567  /* in-band signal; next 4 bits contain signal id */
568  c = get_n_bits_at(data, 4, bit);
569  bit += 4;
570  bit += SpeexInBandSz[c];
571  } else if (c == 13) {
572  /* user in-band; next 4 bits contain msg len */
573  c = get_n_bits_at(data, 4, bit);
574  bit += 4;
575  /* after which it's 5-bit signal id + c bytes of data */
576  bit += 5 + c * 8;
577  } else if (c > 8) {
578  /* unknown */
579  ast_log(LOG_WARNING, "Unknown speex control frame %d\n", c);
580  break;
581  } else {
582  /* skip number bits for submode (less the 5 control bits) */
583  bit += SpeexSubModeSz[c] - 5;
584  cnt += 160; /* new frame */
585  }
586  }
587  return cnt;
588 }
589 
590 static int speex8_samples(struct ast_frame *frame)
591 {
592  return speex_samples(frame->data.ptr, frame->datalen);
593 }
594 
595 static struct ast_codec speex8 = {
596  .name = "speex",
597  .description = "SpeeX",
598  .type = AST_MEDIA_TYPE_AUDIO,
599  .sample_rate = 8000,
600  .minimum_ms = 10,
601  .maximum_ms = 60,
602  .default_ms = 20,
603  .minimum_bytes = 10,
604  .samples_count = speex8_samples,
605  .quality = 40,
606 };
607 
608 static int speex16_samples(struct ast_frame *frame)
609 {
610  return 2 * speex_samples(frame->data.ptr, frame->datalen);
611 }
612 
613 static struct ast_codec speex16 = {
614  .name = "speex",
615  .description = "SpeeX 16khz",
616  .type = AST_MEDIA_TYPE_AUDIO,
617  .sample_rate = 16000,
618  .minimum_ms = 10,
619  .maximum_ms = 60,
620  .default_ms = 20,
621  .minimum_bytes = 10,
622  .samples_count = speex16_samples,
623  .quality = 40,
624 };
625 
626 static int speex32_samples(struct ast_frame *frame)
627 {
628  return 4 * speex_samples(frame->data.ptr, frame->datalen);
629 }
630 
631 static struct ast_codec speex32 = {
632  .name = "speex",
633  .description = "SpeeX 32khz",
634  .type = AST_MEDIA_TYPE_AUDIO,
635  .sample_rate = 32000,
636  .minimum_ms = 10,
637  .maximum_ms = 60,
638  .default_ms = 20,
639  .minimum_bytes = 10,
640  .samples_count = speex32_samples,
641  .quality = 40,
642 };
643 
644 static int ilbc_samples(struct ast_frame *frame)
645 {
647  const unsigned int mode = attr ? attr->mode : 30;
648  const unsigned int samples_per_frame = mode * ast_format_get_sample_rate(frame->subclass.format) / 1000;
649  const unsigned int octets_per_frame = (mode == 20) ? 38 : 50;
650 
651  return samples_per_frame * frame->datalen / octets_per_frame;
652 }
653 
654 static struct ast_codec ilbc = {
655  .name = "ilbc",
656  .description = "iLBC",
657  .type = AST_MEDIA_TYPE_AUDIO,
658  .sample_rate = 8000,
659  .minimum_ms = 20,
660  .maximum_ms = 300,
661  .default_ms = 20,
662  .minimum_bytes = 38,
663  .samples_count = ilbc_samples,
664  .smooth = 0,
665  .quality = 45,
666 };
667 
668 static struct ast_codec g722 = {
669  .name = "g722",
670  .description = "G722",
671  .type = AST_MEDIA_TYPE_AUDIO,
672  .sample_rate = 16000,
673  .minimum_ms = 10,
674  .maximum_ms = 140,
675  .default_ms = 20,
676  .minimum_bytes = 80,
677  .samples_count = g726_samples,
678  .get_length = g726_length,
679  .smooth = 1,
680  .quality = 110, /* In theory, better than ulaw */
681 };
682 
683 static int siren7_samples(struct ast_frame *frame)
684 {
685  return frame->datalen * (16000 / 4000);
686 }
687 
688 static int siren7_length(unsigned int samples)
689 {
690  return samples / (16000 / 4000);
691 }
692 
693 static struct ast_codec siren7 = {
694  .name = "siren7",
695  .description = "ITU G.722.1 (Siren7, licensed from Polycom)",
696  .type = AST_MEDIA_TYPE_AUDIO,
697  .sample_rate = 16000,
698  .minimum_ms = 20,
699  .maximum_ms = 80,
700  .default_ms = 20,
701  .minimum_bytes = 80,
702  .samples_count = siren7_samples,
703  .get_length = siren7_length,
704  .quality = 85,
705 };
706 
707 static int siren14_samples(struct ast_frame *frame)
708 {
709  return (int) frame->datalen * ((float) 32000 / 6000);
710 }
711 
712 static int siren14_length(unsigned int samples)
713 {
714  return (int) samples / ((float) 32000 / 6000);;
715 }
716 
717 static struct ast_codec siren14 = {
718  .name = "siren14",
719  .description = "ITU G.722.1 Annex C, (Siren14, licensed from Polycom)",
720  .type = AST_MEDIA_TYPE_AUDIO,
721  .sample_rate = 32000,
722  .minimum_ms = 20,
723  .maximum_ms = 80,
724  .default_ms = 20,
725  .minimum_bytes = 120,
726  .samples_count = siren14_samples,
727  .get_length = siren14_length,
728  .quality = 90,
729 };
730 
731 static int g719_samples(struct ast_frame *frame)
732 {
733  return (int) frame->datalen * ((float) 48000 / 8000);
734 }
735 
736 static int g719_length(unsigned int samples)
737 {
738  return (int) samples / ((float) 48000 / 8000);
739 }
740 
741 static struct ast_codec g719 = {
742  .name = "g719",
743  .description = "ITU G.719",
744  .type = AST_MEDIA_TYPE_AUDIO,
745  .sample_rate = 48000,
746  .minimum_ms = 20,
747  .maximum_ms = 80,
748  .default_ms = 20,
749  .minimum_bytes = 160,
750  .samples_count = g719_samples,
751  .get_length = g719_length,
752  .quality = 95,
753 };
754 
755 static int opus_samples(struct ast_frame *frame)
756 {
757  /*
758  * XXX This is likely not at all what's intended from this
759  * callback. If you have codec_opus.so loaded then this
760  * function is overridden anyway. However, since opus is
761  * variable bit rate and I cannot extract the calculation code
762  * from the opus library, I am going to punt and assume 20ms
763  * worth of samples. In testing, this has worked just fine.
764  * Pass through support doesn't seem to care about the value
765  * returned anyway.
766  */
767  return ast_format_get_sample_rate(frame->subclass.format) / 50;
768 }
769 
770 static struct ast_codec opus = {
771  .name = "opus",
772  .description = "Opus Codec",
773  .type = AST_MEDIA_TYPE_AUDIO,
774  .sample_rate = 48000,
775  .minimum_ms = 20,
776  .maximum_ms = 60,
777  .default_ms = 20,
778  .samples_count = opus_samples,
779  .minimum_bytes = 10,
780  .quality = 50,
781 };
782 
783 static struct ast_codec jpeg = {
784  .name = "jpeg",
785  .description = "JPEG image",
786  .type = AST_MEDIA_TYPE_IMAGE,
787 };
788 
789 static struct ast_codec png = {
790  .name = "png",
791  .description = "PNG Image",
792  .type = AST_MEDIA_TYPE_IMAGE,
793 };
794 
795 static struct ast_codec h261 = {
796  .name = "h261",
797  .description = "H.261 video",
798  .type = AST_MEDIA_TYPE_VIDEO,
799  .sample_rate = 1000,
800 };
801 
802 static struct ast_codec h263 = {
803  .name = "h263",
804  .description = "H.263 video",
805  .type = AST_MEDIA_TYPE_VIDEO,
806  .sample_rate = 1000,
807 };
808 
809 static struct ast_codec h263p = {
810  .name = "h263p",
811  .description = "H.263+ video",
812  .type = AST_MEDIA_TYPE_VIDEO,
813  .sample_rate = 1000,
814 };
815 
816 static struct ast_codec h264 = {
817  .name = "h264",
818  .description = "H.264 video",
819  .type = AST_MEDIA_TYPE_VIDEO,
820  .sample_rate = 1000,
821 };
822 
823 static struct ast_codec h265 = {
824  .name = "h265",
825  .description = "H.265 video",
826  .type = AST_MEDIA_TYPE_VIDEO,
827  .sample_rate = 1000,
828 };
829 
830 static struct ast_codec mpeg4 = {
831  .name = "mpeg4",
832  .description = "MPEG4 video",
833  .type = AST_MEDIA_TYPE_VIDEO,
834  .sample_rate = 1000,
835 };
836 
837 static struct ast_codec vp8 = {
838  .name = "vp8",
839  .description = "VP8 video",
840  .type = AST_MEDIA_TYPE_VIDEO,
841  .sample_rate = 1000,
842 };
843 
844 static struct ast_codec vp9 = {
845  .name = "vp9",
846  .description = "VP9 video",
847  .type = AST_MEDIA_TYPE_VIDEO,
848  .sample_rate = 1000,
849 };
850 
851 static struct ast_codec t140red = {
852  .name = "red",
853  .description = "T.140 Realtime Text with redundancy",
854  .type = AST_MEDIA_TYPE_TEXT,
855 };
856 
857 static struct ast_codec t140 = {
858  .name = "t140",
859  .description = "Passthrough T.140 Realtime Text",
860  .type = AST_MEDIA_TYPE_TEXT,
861 };
862 
863 static struct ast_codec t38 = {
864  .name = "t38",
865  .description = "T.38 UDPTL Fax",
866  .type = AST_MEDIA_TYPE_IMAGE,
867 };
868 
869 static int silk_samples(struct ast_frame *frame)
870 {
871  /* XXX This is likely not at all what's intended from this callback. However,
872  * since SILK is variable bit rate, I have no idea how to take a frame of data
873  * and determine the number of samples present. Instead, we base this on the
874  * sample rate of the codec and the expected number of samples to receive in 20ms.
875  * In testing, this has worked just fine.
876  */
877  return ast_format_get_sample_rate(frame->subclass.format) / 50;
878 }
879 
880 static struct ast_codec silk8 = {
881  .name = "silk",
882  .description = "SILK Codec (8 KHz)",
883  .type = AST_MEDIA_TYPE_AUDIO,
884  .sample_rate = 8000,
885  .minimum_ms = 20,
886  .maximum_ms = 100,
887  .default_ms = 20,
888  .minimum_bytes = 160,
889  .samples_count = silk_samples,
890 };
891 
892 static struct ast_codec silk12 = {
893  .name = "silk",
894  .description = "SILK Codec (12 KHz)",
895  .type = AST_MEDIA_TYPE_AUDIO,
896  .sample_rate = 12000,
897  .minimum_ms = 20,
898  .maximum_ms = 100,
899  .default_ms = 20,
900  .minimum_bytes = 240,
901  .samples_count = silk_samples
902 };
903 
904 static struct ast_codec silk16 = {
905  .name = "silk",
906  .description = "SILK Codec (16 KHz)",
907  .type = AST_MEDIA_TYPE_AUDIO,
908  .sample_rate = 16000,
909  .minimum_ms = 20,
910  .maximum_ms = 100,
911  .default_ms = 20,
912  .minimum_bytes = 320,
913  .samples_count = silk_samples
914 };
915 
916 static struct ast_codec silk24 = {
917  .name = "silk",
918  .description = "SILK Codec (24 KHz)",
919  .type = AST_MEDIA_TYPE_AUDIO,
920  .sample_rate = 24000,
921  .minimum_ms = 20,
922  .maximum_ms = 100,
923  .default_ms = 20,
924  .minimum_bytes = 480,
925  .samples_count = silk_samples
926 };
927 
928 #define CODEC_REGISTER_AND_CACHE(codec) \
929  ({ \
930  int __res_ ## __LINE__ = 0; \
931  struct ast_format *__fmt_ ## __LINE__; \
932  struct ast_codec *__codec_ ## __LINE__; \
933  res |= __ast_codec_register_with_format(&(codec), (codec).name, NULL); \
934  __codec_ ## __LINE__ = ast_codec_get((codec).name, (codec).type, (codec).sample_rate); \
935  __fmt_ ## __LINE__ = __codec_ ## __LINE__ ? ast_format_create(__codec_ ## __LINE__) : NULL; \
936  res |= ast_format_cache_set(__fmt_ ## __LINE__); \
937  ao2_ref(__fmt_ ## __LINE__, -1); \
938  ao2_ref(__codec_ ## __LINE__, -1); \
939  __res_ ## __LINE__; \
940  })
941 
942 #define CODEC_REGISTER_AND_CACHE_NAMED(fmt_name, codec) \
943  ({ \
944  int __res_ ## __LINE__ = 0; \
945  struct ast_format *__fmt_ ## __LINE__; \
946  struct ast_codec *__codec_ ## __LINE__; \
947  res |= __ast_codec_register_with_format(&(codec), fmt_name, NULL); \
948  __codec_ ## __LINE__ = ast_codec_get((codec).name, (codec).type, (codec).sample_rate); \
949  __fmt_ ## __LINE__ = ast_format_create_named((fmt_name), __codec_ ## __LINE__); \
950  res |= ast_format_cache_set(__fmt_ ## __LINE__); \
951  ao2_ref(__fmt_ ## __LINE__, -1); \
952  ao2_ref(__codec_ ## __LINE__, -1); \
953  __res_ ## __LINE__; \
954  })
955 
957 {
958  int res = 0;
959 
960  res |= CODEC_REGISTER_AND_CACHE(codec2);
961  res |= CODEC_REGISTER_AND_CACHE(g723);
962  res |= CODEC_REGISTER_AND_CACHE(ulaw);
963  res |= CODEC_REGISTER_AND_CACHE(alaw);
964  res |= CODEC_REGISTER_AND_CACHE(gsm);
965  res |= CODEC_REGISTER_AND_CACHE(g726rfc3551);
966  res |= CODEC_REGISTER_AND_CACHE(g726aal2);
967  res |= CODEC_REGISTER_AND_CACHE(adpcm);
968  res |= CODEC_REGISTER_AND_CACHE(slin8);
969  res |= CODEC_REGISTER_AND_CACHE_NAMED("slin12", slin12);
970  res |= CODEC_REGISTER_AND_CACHE_NAMED("slin16", slin16);
971  res |= CODEC_REGISTER_AND_CACHE_NAMED("slin24", slin24);
972  res |= CODEC_REGISTER_AND_CACHE_NAMED("slin32", slin32);
973  res |= CODEC_REGISTER_AND_CACHE_NAMED("slin44", slin44);
974  res |= CODEC_REGISTER_AND_CACHE_NAMED("slin48", slin48);
975  res |= CODEC_REGISTER_AND_CACHE_NAMED("slin96", slin96);
976  res |= CODEC_REGISTER_AND_CACHE_NAMED("slin192", slin192);
977  res |= CODEC_REGISTER_AND_CACHE(lpc10);
978  res |= CODEC_REGISTER_AND_CACHE(g729a);
979  res |= CODEC_REGISTER_AND_CACHE(speex8);
980  res |= CODEC_REGISTER_AND_CACHE_NAMED("speex16", speex16);
981  res |= CODEC_REGISTER_AND_CACHE_NAMED("speex32", speex32);
982  res |= CODEC_REGISTER_AND_CACHE(ilbc);
983  res |= CODEC_REGISTER_AND_CACHE(g722);
984  res |= CODEC_REGISTER_AND_CACHE(siren7);
985  res |= CODEC_REGISTER_AND_CACHE(siren14);
986  res |= CODEC_REGISTER_AND_CACHE(g719);
987  res |= CODEC_REGISTER_AND_CACHE(opus);
988  res |= CODEC_REGISTER_AND_CACHE(jpeg);
989  res |= CODEC_REGISTER_AND_CACHE(png);
990  res |= CODEC_REGISTER_AND_CACHE(h261);
991  res |= CODEC_REGISTER_AND_CACHE(h263);
992  res |= CODEC_REGISTER_AND_CACHE(h263p);
993  res |= CODEC_REGISTER_AND_CACHE(h264);
994  res |= CODEC_REGISTER_AND_CACHE(h265);
995  res |= CODEC_REGISTER_AND_CACHE(mpeg4);
996  res |= CODEC_REGISTER_AND_CACHE(vp8);
997  res |= CODEC_REGISTER_AND_CACHE(vp9);
998  res |= CODEC_REGISTER_AND_CACHE(t140red);
999  res |= CODEC_REGISTER_AND_CACHE(t140);
1000  res |= CODEC_REGISTER_AND_CACHE(t38);
1001  res |= CODEC_REGISTER_AND_CACHE(none);
1002  res |= CODEC_REGISTER_AND_CACHE_NAMED("silk8", silk8);
1003  res |= CODEC_REGISTER_AND_CACHE_NAMED("silk12", silk12);
1004  res |= CODEC_REGISTER_AND_CACHE_NAMED("silk16", silk16);
1005  res |= CODEC_REGISTER_AND_CACHE_NAMED("silk24", silk24);
1006 
1007  return res;
1008 }
const char * name
Name for this codec.
Definition: codec.h:46
Asterisk main include file. File version handling, generic pbx functions.
Definition: ilbc.h:4
int ast_codec_builtin_init(void)
Initialize built-in codecs within the core.
Codec API.
void * ast_format_get_attribute_data(const struct ast_format *format)
Get the attribute data on a format.
Definition: format.c:125
Asterisk internal frame definitions.
struct ast_frame_subclass subclass
Media Format API.
Asterisk internal frame definitions.
union ast_frame::@224 data
Support for logging to various files, console and syslog Configuration in file logger.conf.
unsigned int ast_format_get_sample_rate(const struct ast_format *format)
Get the sample rate of a media format.
Definition: format.c:379
Data structure associated with a single frame of data.
struct ast_format * format
Represents a media codec within Asterisk.
Definition: codec.h:42
Media Format Cache API.