Wed Jan 8 2020 09:49:47

Asterisk developer's documentation


frame.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Mark Spencer <markster@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 Frame and codec manipulation routines
22  *
23  * \author Mark Spencer <markster@digium.com>
24  */
25 
26 /*** MODULEINFO
27  <support_level>core</support_level>
28  ***/
29 
30 #include "asterisk.h"
31 
32 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 413586 $")
33 
34 #include "asterisk/_private.h"
35 #include "asterisk/lock.h"
36 #include "asterisk/frame.h"
37 #include "asterisk/channel.h"
38 #include "asterisk/cli.h"
39 #include "asterisk/term.h"
40 #include "asterisk/utils.h"
41 #include "asterisk/threadstorage.h"
42 #include "asterisk/linkedlists.h"
43 #include "asterisk/translate.h"
44 #include "asterisk/dsp.h"
45 #include "asterisk/file.h"
46 
47 #if !defined(LOW_MEMORY)
48 static void frame_cache_cleanup(void *data);
49 
50 /*! \brief A per-thread cache of frame headers */
52 
53 /*!
54  * \brief Maximum ast_frame cache size
55  *
56  * In most cases where the frame header cache will be useful, the size
57  * of the cache will stay very small. However, it is not always the case that
58  * the same thread that allocates the frame will be the one freeing them, so
59  * sometimes a thread will never have any frames in its cache, or the cache
60  * will never be pulled from. For the latter case, we limit the maximum size.
61  */
62 #define FRAME_CACHE_MAX_SIZE 10
63 
64 /*! \brief This is just so ast_frames, a list head struct for holding a list of
65  * ast_frame structures, is defined. */
67 
69  struct ast_frames list;
70  size_t size;
71 };
72 #endif
73 
74 #define SMOOTHER_SIZE 8000
75 
76 enum frame_type {
77  TYPE_HIGH, /* 0x0 */
78  TYPE_LOW, /* 0x1 */
79  TYPE_SILENCE, /* 0x2 */
80  TYPE_DONTSEND /* 0x3 */
81 };
82 
83 #define TYPE_MASK 0x3
84 
85 struct ast_smoother {
86  int size;
88  int flags;
90  unsigned int opt_needs_swap:1;
91  struct ast_frame f;
92  struct timeval delivery;
95  struct ast_frame *opt;
96  int len;
97 };
98 
99 /*! \brief Definition of supported media formats (codecs) */
100 static const struct ast_format_list AST_FORMAT_LIST[] = {
101  { AST_FORMAT_G723_1 , "g723", 8000, "G.723.1", 20, 30, 300, 30, 30 }, /*!< G723.1 */
102  { AST_FORMAT_GSM, "gsm", 8000, "GSM", 33, 20, 300, 20, 20 }, /*!< codec_gsm.c */
103  { AST_FORMAT_ULAW, "ulaw", 8000, "G.711 u-law", 80, 10, 150, 10, 20 }, /*!< codec_ulaw.c */
104  { AST_FORMAT_ALAW, "alaw", 8000, "G.711 A-law", 80, 10, 150, 10, 20 }, /*!< codec_alaw.c */
105  { AST_FORMAT_G726, "g726", 8000, "G.726 RFC3551", 40, 10, 300, 10, 20 }, /*!< codec_g726.c */
106  { AST_FORMAT_ADPCM, "adpcm" , 8000, "ADPCM", 40, 10, 300, 10, 20 }, /*!< codec_adpcm.c */
107  { AST_FORMAT_SLINEAR, "slin", 8000, "16 bit Signed Linear PCM", 160, 10, 70, 10, 20, AST_SMOOTHER_FLAG_BE }, /*!< Signed linear */
108  { AST_FORMAT_LPC10, "lpc10", 8000, "LPC10", 7, 20, 20, 20, 20 }, /*!< codec_lpc10.c */
109  { AST_FORMAT_G729A, "g729", 8000, "G.729A", 10, 10, 230, 10, 20, AST_SMOOTHER_FLAG_G729 }, /*!< Binary commercial distribution */
110  { AST_FORMAT_SPEEX, "speex", 8000, "SpeeX", 10, 10, 60, 10, 20 }, /*!< codec_speex.c */
111  { AST_FORMAT_SPEEX16, "speex16", 16000, "SpeeX 16khz", 10, 10, 60, 10, 20 }, /*!< codec_speex.c */
112  { AST_FORMAT_ILBC, "ilbc", 8000, "iLBC", 50, 30, 30, 30, 30 }, /*!< codec_ilbc.c */ /* inc=30ms - workaround */
113  { AST_FORMAT_G726_AAL2, "g726aal2", 8000, "G.726 AAL2", 40, 10, 300, 10, 20 }, /*!< codec_g726.c */
114  { AST_FORMAT_G722, "g722", 16000, "G722", 80, 10, 150, 10, 20 }, /*!< codec_g722.c */
115  { AST_FORMAT_SLINEAR16, "slin16", 16000, "16 bit Signed Linear PCM (16kHz)", 320, 10, 70, 10, 20, AST_SMOOTHER_FLAG_BE }, /*!< Signed linear (16kHz) */
116  { AST_FORMAT_JPEG, "jpeg", 0, "JPEG image"}, /*!< See format_jpeg.c */
117  { AST_FORMAT_PNG, "png", 0, "PNG image"}, /*!< PNG Image format */
118  { AST_FORMAT_H261, "h261", 0, "H.261 Video" }, /*!< H.261 Video Passthrough */
119  { AST_FORMAT_H263, "h263", 0, "H.263 Video" }, /*!< H.263 Passthrough support, see format_h263.c */
120  { AST_FORMAT_H263_PLUS, "h263p", 0, "H.263+ Video" }, /*!< H.263plus passthrough support See format_h263.c */
121  { AST_FORMAT_H264, "h264", 0, "H.264 Video" }, /*!< Passthrough support, see format_h263.c */
122  { AST_FORMAT_MP4_VIDEO, "mpeg4", 0, "MPEG4 Video" }, /*!< Passthrough support for MPEG4 */
123  { AST_FORMAT_T140RED, "red", 1, "T.140 Realtime Text with redundancy"}, /*!< Redundant T.140 Realtime Text */
124  { AST_FORMAT_T140, "t140", 0, "Passthrough T.140 Realtime Text" }, /*!< Passthrough support for T.140 Realtime Text */
125  { AST_FORMAT_SIREN7, "siren7", 16000, "ITU G.722.1 (Siren7, licensed from Polycom)", 80, 20, 80, 20, 20 }, /*!< Binary commercial distribution */
126  { AST_FORMAT_SIREN14, "siren14", 32000, "ITU G.722.1 Annex C, (Siren14, licensed from Polycom)", 120, 20, 80, 20, 20 }, /*!< Binary commercial distribution */
127  { AST_FORMAT_TESTLAW, "testlaw", 8000, "G.711 test-law", 80, 10, 150, 10, 20 }, /*!< codec_ulaw.c */
128  { AST_FORMAT_G719, "g719", 48000, "ITU G.719", 160, 20, 80, 20, 20 },
129 };
130 
132 
133 static int smoother_frame_feed(struct ast_smoother *s, struct ast_frame *f, int swap)
134 {
135  if (s->flags & AST_SMOOTHER_FLAG_G729) {
136  if (s->len % 10) {
137  ast_log(LOG_NOTICE, "Dropping extra frame of G.729 since we already have a VAD frame at the end\n");
138  return 0;
139  }
140  }
141  if (swap) {
142  ast_swapcopy_samples(s->data + s->len, f->data.ptr, f->samples);
143  } else {
144  memcpy(s->data + s->len, f->data.ptr, f->datalen);
145  }
146  /* If either side is empty, reset the delivery time */
147  if (!s->len || ast_tvzero(f->delivery) || ast_tvzero(s->delivery)) { /* XXX really ? */
148  s->delivery = f->delivery;
149  }
150  s->len += f->datalen;
151 
152  return 0;
153 }
154 
155 void ast_smoother_reset(struct ast_smoother *s, int bytes)
156 {
157  memset(s, 0, sizeof(*s));
158  s->size = bytes;
159 }
160 
161 void ast_smoother_reconfigure(struct ast_smoother *s, int bytes)
162 {
163  /* if there is no change, then nothing to do */
164  if (s->size == bytes) {
165  return;
166  }
167  /* set the new desired output size */
168  s->size = bytes;
169  /* if there is no 'optimized' frame in the smoother,
170  * then there is nothing left to do
171  */
172  if (!s->opt) {
173  return;
174  }
175  /* there is an 'optimized' frame here at the old size,
176  * but it must now be put into the buffer so the data
177  * can be extracted at the new size
178  */
180  s->opt = NULL;
181 }
182 
184 {
185  struct ast_smoother *s;
186  if (size < 1)
187  return NULL;
188  if ((s = ast_malloc(sizeof(*s))))
189  ast_smoother_reset(s, size);
190  return s;
191 }
192 
194 {
195  return s->flags;
196 }
197 
199 {
200  s->flags = flags;
201 }
202 
203 int ast_smoother_test_flag(struct ast_smoother *s, int flag)
204 {
205  return (s->flags & flag);
206 }
207 
208 int __ast_smoother_feed(struct ast_smoother *s, struct ast_frame *f, int swap)
209 {
210  if (f->frametype != AST_FRAME_VOICE) {
211  ast_log(LOG_WARNING, "Huh? Can't smooth a non-voice frame!\n");
212  return -1;
213  }
214  if (!s->format) {
215  s->format = f->subclass.codec;
216  s->samplesperbyte = (float)f->samples / (float)f->datalen;
217  } else if (s->format != f->subclass.codec) {
218  ast_log(LOG_WARNING, "Smoother was working on %s format frames, now trying to feed %s?\n",
220  return -1;
221  }
222  if (s->len + f->datalen > SMOOTHER_SIZE) {
223  ast_log(LOG_WARNING, "Out of smoother space\n");
224  return -1;
225  }
226  if (((f->datalen == s->size) ||
227  ((f->datalen < 10) && (s->flags & AST_SMOOTHER_FLAG_G729))) &&
228  !s->opt &&
229  !s->len &&
230  (f->offset >= AST_MIN_OFFSET)) {
231  /* Optimize by sending the frame we just got
232  on the next read, thus eliminating the douple
233  copy */
234  if (swap)
236  s->opt = f;
237  s->opt_needs_swap = swap ? 1 : 0;
238  return 0;
239  }
240 
241  return smoother_frame_feed(s, f, swap);
242 }
243 
245 {
246  struct ast_frame *opt;
247  int len;
248 
249  /* IF we have an optimization frame, send it */
250  if (s->opt) {
251  if (s->opt->offset < AST_FRIENDLY_OFFSET)
252  ast_log(LOG_WARNING, "Returning a frame of inappropriate offset (%d).\n",
253  s->opt->offset);
254  opt = s->opt;
255  s->opt = NULL;
256  return opt;
257  }
258 
259  /* Make sure we have enough data */
260  if (s->len < s->size) {
261  /* Or, if this is a G.729 frame with VAD on it, send it immediately anyway */
262  if (!((s->flags & AST_SMOOTHER_FLAG_G729) && (s->len % 10)))
263  return NULL;
264  }
265  len = s->size;
266  if (len > s->len)
267  len = s->len;
268  /* Make frame */
270  s->f.subclass.codec = s->format;
273  s->f.datalen = len;
274  /* Samples will be improper given VAD, but with VAD the concept really doesn't even exist */
275  s->f.samples = len * s->samplesperbyte; /* XXX rounding */
276  s->f.delivery = s->delivery;
277  /* Fill Data */
278  memcpy(s->f.data.ptr, s->data, len);
279  s->len -= len;
280  /* Move remaining data to the front if applicable */
281  if (s->len) {
282  /* In principle this should all be fine because if we are sending
283  G.729 VAD, the next timestamp will take over anyawy */
284  memmove(s->data, s->data + len, s->len);
285  if (!ast_tvzero(s->delivery)) {
286  /* If we have delivery time, increment it, otherwise, leave it at 0 */
288  }
289  }
290  /* Return frame */
291  return &s->f;
292 }
293 
295 {
296  ast_free(s);
297 }
298 
299 static struct ast_frame *ast_frame_header_new(void)
300 {
301  struct ast_frame *f;
302 
303 #if !defined(LOW_MEMORY)
304  struct ast_frame_cache *frames;
305 
306  if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames)))) {
307  if ((f = AST_LIST_REMOVE_HEAD(&frames->list, frame_list))) {
308  size_t mallocd_len = f->mallocd_hdr_len;
309  memset(f, 0, sizeof(*f));
310  f->mallocd_hdr_len = mallocd_len;
312  frames->size--;
313  return f;
314  }
315  }
316  if (!(f = ast_calloc_cache(1, sizeof(*f))))
317  return NULL;
318 #else
319  if (!(f = ast_calloc(1, sizeof(*f))))
320  return NULL;
321 #endif
322 
323  f->mallocd_hdr_len = sizeof(*f);
324 
325  return f;
326 }
327 
328 #if !defined(LOW_MEMORY)
329 static void frame_cache_cleanup(void *data)
330 {
331  struct ast_frame_cache *frames = data;
332  struct ast_frame *f;
333 
334  while ((f = AST_LIST_REMOVE_HEAD(&frames->list, frame_list)))
335  ast_free(f);
336 
337  ast_free(frames);
338 }
339 #endif
340 
341 static void __frame_free(struct ast_frame *fr, int cache)
342 {
343  if (!fr->mallocd)
344  return;
345 
346 #if !defined(LOW_MEMORY)
347  if (cache && fr->mallocd == AST_MALLOCD_HDR) {
348  /* Cool, only the header is malloc'd, let's just cache those for now
349  * to keep things simple... */
350  struct ast_frame_cache *frames;
351 
352  if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames))) &&
353  (frames->size < FRAME_CACHE_MAX_SIZE)) {
354  AST_LIST_INSERT_HEAD(&frames->list, fr, frame_list);
355  frames->size++;
356  return;
357  }
358  }
359 #endif
360 
361  if (fr->mallocd & AST_MALLOCD_DATA) {
362  if (fr->data.ptr)
363  ast_free(fr->data.ptr - fr->offset);
364  }
365  if (fr->mallocd & AST_MALLOCD_SRC) {
366  if (fr->src)
367  ast_free((void *) fr->src);
368  }
369  if (fr->mallocd & AST_MALLOCD_HDR) {
370  ast_free(fr);
371  }
372 }
373 
374 
375 void ast_frame_free(struct ast_frame *frame, int cache)
376 {
377  struct ast_frame *next;
378 
379  for (next = AST_LIST_NEXT(frame, frame_list);
380  frame;
381  frame = next, next = frame ? AST_LIST_NEXT(frame, frame_list) : NULL) {
382  __frame_free(frame, cache);
383  }
384 }
385 
386 /*!
387  * \brief 'isolates' a frame by duplicating non-malloc'ed components
388  * (header, src, data).
389  * On return all components are malloc'ed
390  */
391 struct ast_frame *ast_frisolate(struct ast_frame *fr)
392 {
393  struct ast_frame *out;
394  void *newdata;
395 
396  /* if none of the existing frame is malloc'd, let ast_frdup() do it
397  since it is more efficient
398  */
399  if (fr->mallocd == 0) {
400  return ast_frdup(fr);
401  }
402 
403  /* if everything is already malloc'd, we are done */
406  return fr;
407  }
408 
409  if (!(fr->mallocd & AST_MALLOCD_HDR)) {
410  /* Allocate a new header if needed */
411  if (!(out = ast_frame_header_new())) {
412  return NULL;
413  }
414  out->frametype = fr->frametype;
415  out->subclass.codec = fr->subclass.codec;
416  out->datalen = fr->datalen;
417  out->samples = fr->samples;
418  out->offset = fr->offset;
419  /* Copy the timing data */
422  out->ts = fr->ts;
423  out->len = fr->len;
424  out->seqno = fr->seqno;
425  }
426  } else {
427  out = fr;
428  }
429 
430  if (!(fr->mallocd & AST_MALLOCD_SRC) && fr->src) {
431  if (!(out->src = ast_strdup(fr->src))) {
432  if (out != fr) {
433  ast_free(out);
434  }
435  return NULL;
436  }
437  } else {
438  out->src = fr->src;
439  fr->src = NULL;
440  fr->mallocd &= ~AST_MALLOCD_SRC;
441  }
442 
443  if (!(fr->mallocd & AST_MALLOCD_DATA)) {
444  if (!fr->datalen) {
445  out->data.uint32 = fr->data.uint32;
447  return out;
448  }
449  if (!(newdata = ast_malloc(fr->datalen + AST_FRIENDLY_OFFSET))) {
450  if (out->src != fr->src) {
451  ast_free((void *) out->src);
452  }
453  if (out != fr) {
454  ast_free(out);
455  }
456  return NULL;
457  }
458  newdata += AST_FRIENDLY_OFFSET;
460  out->datalen = fr->datalen;
461  memcpy(newdata, fr->data.ptr, fr->datalen);
462  out->data.ptr = newdata;
463  } else {
464  out->data = fr->data;
465  memset(&fr->data, 0, sizeof(fr->data));
466  fr->mallocd &= ~AST_MALLOCD_DATA;
467  }
468 
470 
471  return out;
472 }
473 
474 struct ast_frame *ast_frdup(const struct ast_frame *f)
475 {
476  struct ast_frame *out = NULL;
477  int len, srclen = 0;
478  void *buf = NULL;
479 
480 #if !defined(LOW_MEMORY)
481  struct ast_frame_cache *frames;
482 #endif
483 
484  /* Start with standard stuff */
485  len = sizeof(*out) + AST_FRIENDLY_OFFSET + f->datalen;
486  /* If we have a source, add space for it */
487  /*
488  * XXX Watch out here - if we receive a src which is not terminated
489  * properly, we can be easily attacked. Should limit the size we deal with.
490  */
491  if (f->src)
492  srclen = strlen(f->src);
493  if (srclen > 0)
494  len += srclen + 1;
495 
496 #if !defined(LOW_MEMORY)
497  if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames)))) {
499  if (out->mallocd_hdr_len >= len) {
500  size_t mallocd_len = out->mallocd_hdr_len;
501 
503  memset(out, 0, sizeof(*out));
504  out->mallocd_hdr_len = mallocd_len;
505  buf = out;
506  frames->size--;
507  break;
508  }
509  }
511  }
512 #endif
513 
514  if (!buf) {
515  if (!(buf = ast_calloc_cache(1, len)))
516  return NULL;
517  out = buf;
518  out->mallocd_hdr_len = len;
519  }
520 
521  out->frametype = f->frametype;
522  out->subclass.codec = f->subclass.codec;
523  out->datalen = f->datalen;
524  out->samples = f->samples;
525  out->delivery = f->delivery;
526  /* Even though this new frame was allocated from the heap, we can't mark it
527  * with AST_MALLOCD_HDR, AST_MALLOCD_DATA and AST_MALLOCD_SRC, because that
528  * would cause ast_frfree() to attempt to individually free each of those
529  * under the assumption that they were separately allocated. Since this frame
530  * was allocated in a single allocation, we'll only mark it as if the header
531  * was heap-allocated; this will result in the entire frame being properly freed.
532  */
533  out->mallocd = AST_MALLOCD_HDR;
535  if (out->datalen) {
536  out->data.ptr = buf + sizeof(*out) + AST_FRIENDLY_OFFSET;
537  memcpy(out->data.ptr, f->data.ptr, out->datalen);
538  } else {
539  out->data.uint32 = f->data.uint32;
540  }
541  if (srclen > 0) {
542  /* This may seem a little strange, but it's to avoid a gcc (4.2.4) compiler warning */
543  char *src;
544  out->src = buf + sizeof(*out) + AST_FRIENDLY_OFFSET + f->datalen;
545  src = (char *) out->src;
546  /* Must have space since we allocated for it */
547  strcpy(src, f->src);
548  }
550  out->ts = f->ts;
551  out->len = f->len;
552  out->seqno = f->seqno;
553  return out;
554 }
555 
556 void ast_swapcopy_samples(void *dst, const void *src, int samples)
557 {
558  int i;
559  unsigned short *dst_s = dst;
560  const unsigned short *src_s = src;
561 
562  for (i = 0; i < samples; i++)
563  dst_s[i] = (src_s[i]<<8) | (src_s[i]>>8);
564 }
565 
566 
568 {
569  return &AST_FORMAT_LIST[idx];
570 }
571 
572 const struct ast_format_list *ast_get_format_list(size_t *size)
573 {
574  *size = ARRAY_LEN(AST_FORMAT_LIST);
575  return AST_FORMAT_LIST;
576 }
577 
579 {
580  int x;
581  char *ret = "unknown";
582  for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
583  if (AST_FORMAT_LIST[x].bits == format) {
584  ret = AST_FORMAT_LIST[x].name;
585  break;
586  }
587  }
588  return ret;
589 }
590 
591 char *ast_getformatname_multiple(char *buf, size_t size, format_t format)
592 {
593  int x;
594  unsigned len;
595  char *start, *end = buf;
596 
597  if (!size)
598  return buf;
599  snprintf(end, size, "0x%llx (", (unsigned long long) format);
600  len = strlen(end);
601  end += len;
602  size -= len;
603  start = end;
604  for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
605  if (AST_FORMAT_LIST[x].bits & format) {
606  snprintf(end, size, "%s|", AST_FORMAT_LIST[x].name);
607  len = strlen(end);
608  end += len;
609  size -= len;
610  }
611  }
612  if (start == end)
613  ast_copy_string(start, "nothing)", size);
614  else if (size > 1)
615  *(end - 1) = ')';
616  return buf;
617 }
618 
619 static struct ast_codec_alias_table {
620  char *alias;
621  char *realname;
622 } ast_codec_alias_table[] = {
623  { "slinear", "slin"},
624  { "slinear16", "slin16"},
625  { "g723.1", "g723"},
626  { "g722.1", "siren7"},
627  { "g722.1c", "siren14"},
628 };
629 
630 static const char *ast_expand_codec_alias(const char *in)
631 {
632  int x;
633 
634  for (x = 0; x < ARRAY_LEN(ast_codec_alias_table); x++) {
635  if (!strcmp(in,ast_codec_alias_table[x].alias))
636  return ast_codec_alias_table[x].realname;
637  }
638  return in;
639 }
640 
642 {
643  int x, all;
644  format_t format = 0;
645 
646  all = strcasecmp(name, "all") ? 0 : 1;
647  for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
648  if (all ||
649  !strcasecmp(AST_FORMAT_LIST[x].name,name) ||
650  !strcasecmp(AST_FORMAT_LIST[x].name, ast_expand_codec_alias(name))) {
651  format |= AST_FORMAT_LIST[x].bits;
652  if (!all)
653  break;
654  }
655  }
656 
657  return format;
658 }
659 
661 {
662  int x;
663  char *ret = "unknown";
664  for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
665  if (AST_FORMAT_LIST[x].bits == codec) {
666  ret = AST_FORMAT_LIST[x].desc;
667  break;
668  }
669  }
670  return ret;
671 }
672 
673 static char *show_codecs(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
674 {
675  int i, found=0;
676  char hex[25];
677 
678  switch (cmd) {
679  case CLI_INIT:
680  e->command = "core show codecs [audio|video|image|text]";
681  e->usage =
682  "Usage: core show codecs [audio|video|image|text]\n"
683  " Displays codec mapping\n";
684  return NULL;
685  case CLI_GENERATE:
686  return NULL;
687  }
688 
689  if ((a->argc < 3) || (a->argc > 4))
690  return CLI_SHOWUSAGE;
691 
692  if (!ast_opt_dont_warn)
693  ast_cli(a->fd, "Disclaimer: this command is for informational purposes only.\n"
694  "\tIt does not indicate anything about your configuration.\n");
695 
696  ast_cli(a->fd, "%19s %9s %20s TYPE %8s %s\n","INT","BINARY","HEX","NAME","DESCRIPTION");
697  ast_cli(a->fd, "-----------------------------------------------------------------------------------\n");
698  for (i = 0; i < 63; i++) {
699 
700  if (a->argc == 4) {
701  if (!strcasecmp(a->argv[3], "audio")) {
702  if (!((1LL << i) & AST_FORMAT_AUDIO_MASK)) {
703  continue;
704  }
705  } else if (!strcasecmp(a->argv[3], "video")) {
706  if (!((1LL << i) & AST_FORMAT_VIDEO_MASK)) {
707  continue;
708  }
709  } else if (!strcasecmp(a->argv[3], "image")) {
710  if (i != 16 && i != 17) {
711  continue;
712  }
713  } else if (!strcasecmp(a->argv[3], "text")) {
714  if (!((1LL << i) & AST_FORMAT_TEXT_MASK)) {
715  continue;
716  }
717  } else {
718  continue;
719  }
720  }
721 
722  snprintf(hex, sizeof(hex), "(0x%llx)", 1ULL << i);
723  ast_cli(a->fd, "%19llu (1 << %2d) %20s %5s %8s (%s)\n", 1ULL << i, i, hex,
724  ((1LL << i) & AST_FORMAT_AUDIO_MASK) ? "audio" :
725  i == 16 || i == 17 ? "image" :
726  ((1LL << i) & AST_FORMAT_VIDEO_MASK) ? "video" :
727  ((1LL << i) & AST_FORMAT_TEXT_MASK) ? "text" :
728  "(unk)",
729  ast_getformatname(1LL << i), ast_codec2str(1LL << i));
730  found = 1;
731  }
732 
733  if (!found) {
734  return CLI_SHOWUSAGE;
735  } else {
736  return CLI_SUCCESS;
737  }
738 }
739 
740 static char *show_codec_n(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
741 {
742  format_t codec;
743  int i, found = 0;
744  long long type_punned_codec;
745 
746  switch (cmd) {
747  case CLI_INIT:
748  e->command = "core show codec";
749  e->usage =
750  "Usage: core show codec <number>\n"
751  " Displays codec mapping\n";
752  return NULL;
753  case CLI_GENERATE:
754  return NULL;
755  }
756 
757  if (a->argc != 4)
758  return CLI_SHOWUSAGE;
759 
760  if (sscanf(a->argv[3], "%30lld", &type_punned_codec) != 1) {
761  return CLI_SHOWUSAGE;
762  }
763  codec = type_punned_codec;
764 
765  for (i = 0; i < 63; i++)
766  if (codec & (1LL << i)) {
767  found = 1;
768  ast_cli(a->fd, "%11llu (1 << %2d) %s\n", 1ULL << i, i, ast_codec2str(1LL << i));
769  }
770 
771  if (!found)
772  ast_cli(a->fd, "Codec %lld not found\n", (long long) codec);
773 
774  return CLI_SUCCESS;
775 }
776 
777 /*! Dump a frame for debugging purposes */
778 void ast_frame_dump(const char *name, struct ast_frame *f, char *prefix)
779 {
780  const char noname[] = "unknown";
781  char ftype[40] = "Unknown Frametype";
782  char cft[80];
783  char subclass[40] = "Unknown Subclass";
784  char csub[80];
785  char moreinfo[40] = "";
786  char cn[60];
787  char cp[40];
788  char cmn[40];
789  const char *message = "Unknown";
790 
791  if (!name)
792  name = noname;
793 
794 
795  if (!f) {
796  ast_verbose("%s [ %s (NULL) ] [%s]\n",
797  term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
798  term_color(cft, "HANGUP", COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
799  term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
800  return;
801  }
802  /* XXX We should probably print one each of voice and video when the format changes XXX */
803  if (f->frametype == AST_FRAME_VOICE)
804  return;
805  if (f->frametype == AST_FRAME_VIDEO)
806  return;
807  switch(f->frametype) {
809  strcpy(ftype, "DTMF Begin");
810  subclass[0] = f->subclass.integer;
811  subclass[1] = '\0';
812  break;
813  case AST_FRAME_DTMF_END:
814  strcpy(ftype, "DTMF End");
815  subclass[0] = f->subclass.integer;
816  subclass[1] = '\0';
817  break;
818  case AST_FRAME_CONTROL:
819  strcpy(ftype, "Control");
820  switch (f->subclass.integer) {
821  case AST_CONTROL_HANGUP:
822  strcpy(subclass, "Hangup");
823  break;
824  case AST_CONTROL_RING:
825  strcpy(subclass, "Ring");
826  break;
827  case AST_CONTROL_RINGING:
828  strcpy(subclass, "Ringing");
829  break;
830  case AST_CONTROL_ANSWER:
831  strcpy(subclass, "Answer");
832  break;
833  case AST_CONTROL_BUSY:
834  strcpy(subclass, "Busy");
835  break;
837  strcpy(subclass, "Take Off Hook");
838  break;
839  case AST_CONTROL_OFFHOOK:
840  strcpy(subclass, "Line Off Hook");
841  break;
843  strcpy(subclass, "Congestion");
844  break;
845  case AST_CONTROL_FLASH:
846  strcpy(subclass, "Flash");
847  break;
848  case AST_CONTROL_WINK:
849  strcpy(subclass, "Wink");
850  break;
851  case AST_CONTROL_OPTION:
852  strcpy(subclass, "Option");
853  break;
855  strcpy(subclass, "Key Radio");
856  break;
858  strcpy(subclass, "Unkey Radio");
859  break;
860  case AST_CONTROL_HOLD:
861  strcpy(subclass, "Hold");
862  break;
863  case AST_CONTROL_UNHOLD:
864  strcpy(subclass, "Unhold");
865  break;
867  if (f->datalen != sizeof(struct ast_control_t38_parameters)) {
868  message = "Invalid";
869  } else {
870  struct ast_control_t38_parameters *parameters = f->data.ptr;
871  enum ast_control_t38 state = parameters->request_response;
872  if (state == AST_T38_REQUEST_NEGOTIATE)
873  message = "Negotiation Requested";
874  else if (state == AST_T38_REQUEST_TERMINATE)
875  message = "Negotiation Request Terminated";
876  else if (state == AST_T38_NEGOTIATED)
877  message = "Negotiated";
878  else if (state == AST_T38_TERMINATED)
879  message = "Terminated";
880  else if (state == AST_T38_REFUSED)
881  message = "Refused";
882  }
883  snprintf(subclass, sizeof(subclass), "T38_Parameters/%s", message);
884  break;
885  case -1:
886  strcpy(subclass, "Stop generators");
887  break;
888  default:
889  snprintf(subclass, sizeof(subclass), "Unknown control '%d'", f->subclass.integer);
890  }
891  break;
892  case AST_FRAME_NULL:
893  strcpy(ftype, "Null Frame");
894  strcpy(subclass, "N/A");
895  break;
896  case AST_FRAME_IAX:
897  /* Should never happen */
898  strcpy(ftype, "IAX Specific");
899  snprintf(subclass, sizeof(subclass), "IAX Frametype %d", f->subclass.integer);
900  break;
901  case AST_FRAME_TEXT:
902  strcpy(ftype, "Text");
903  strcpy(subclass, "N/A");
904  ast_copy_string(moreinfo, f->data.ptr, sizeof(moreinfo));
905  break;
906  case AST_FRAME_IMAGE:
907  strcpy(ftype, "Image");
908  snprintf(subclass, sizeof(subclass), "Image format %s\n", ast_getformatname(f->subclass.codec));
909  break;
910  case AST_FRAME_HTML:
911  strcpy(ftype, "HTML");
912  switch (f->subclass.integer) {
913  case AST_HTML_URL:
914  strcpy(subclass, "URL");
915  ast_copy_string(moreinfo, f->data.ptr, sizeof(moreinfo));
916  break;
917  case AST_HTML_DATA:
918  strcpy(subclass, "Data");
919  break;
920  case AST_HTML_BEGIN:
921  strcpy(subclass, "Begin");
922  break;
923  case AST_HTML_END:
924  strcpy(subclass, "End");
925  break;
926  case AST_HTML_LDCOMPLETE:
927  strcpy(subclass, "Load Complete");
928  break;
929  case AST_HTML_NOSUPPORT:
930  strcpy(subclass, "No Support");
931  break;
932  case AST_HTML_LINKURL:
933  strcpy(subclass, "Link URL");
934  ast_copy_string(moreinfo, f->data.ptr, sizeof(moreinfo));
935  break;
936  case AST_HTML_UNLINK:
937  strcpy(subclass, "Unlink");
938  break;
939  case AST_HTML_LINKREJECT:
940  strcpy(subclass, "Link Reject");
941  break;
942  default:
943  snprintf(subclass, sizeof(subclass), "Unknown HTML frame '%d'\n", f->subclass.integer);
944  break;
945  }
946  break;
947  case AST_FRAME_MODEM:
948  strcpy(ftype, "Modem");
949  switch (f->subclass.integer) {
950  case AST_MODEM_T38:
951  strcpy(subclass, "T.38");
952  break;
953  case AST_MODEM_V150:
954  strcpy(subclass, "V.150");
955  break;
956  default:
957  snprintf(subclass, sizeof(subclass), "Unknown MODEM frame '%d'\n", f->subclass.integer);
958  break;
959  }
960  break;
961  default:
962  snprintf(ftype, sizeof(ftype), "Unknown Frametype '%u'", f->frametype);
963  }
964  if (!ast_strlen_zero(moreinfo))
965  ast_verbose("%s [ TYPE: %s (%u) SUBCLASS: %s (%d) '%s' ] [%s]\n",
966  term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
967  term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
968  f->frametype,
969  term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
970  f->subclass.integer,
971  term_color(cmn, moreinfo, COLOR_BRGREEN, COLOR_BLACK, sizeof(cmn)),
972  term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
973  else
974  ast_verbose("%s [ TYPE: %s (%u) SUBCLASS: %s (%d) ] [%s]\n",
975  term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
976  term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
977  f->frametype,
978  term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
979  f->subclass.integer,
980  term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
981 }
982 
983 
984 /* Builtin Asterisk CLI-commands for debugging */
985 static struct ast_cli_entry my_clis[] = {
986  AST_CLI_DEFINE(show_codecs, "Displays a list of codecs"),
987  AST_CLI_DEFINE(show_codec_n, "Shows a specific codec"),
988 };
989 
990 static void framer_shutdown(void)
991 {
992  ast_cli_unregister_multiple(my_clis, ARRAY_LEN(my_clis));
993 }
994 
995 int init_framer(void)
996 {
997  ast_cli_register_multiple(my_clis, ARRAY_LEN(my_clis));
999  return 0;
1000 }
1001 
1002 void ast_codec_pref_convert(struct ast_codec_pref *pref, char *buf, size_t size, int right)
1003 {
1004  int x, differential = (int) 'A', mem;
1005  char *from, *to;
1006 
1007  if (right) {
1008  from = pref->order;
1009  to = buf;
1010  mem = size;
1011  } else {
1012  to = pref->order;
1013  from = buf;
1014  mem = sizeof(format_t) * 8;
1015  }
1016 
1017  memset(to, 0, mem);
1018  for (x = 0; x < sizeof(format_t) * 8; x++) {
1019  if (!from[x])
1020  break;
1021  to[x] = right ? (from[x] + differential) : (from[x] - differential);
1022  }
1023 }
1024 
1025 int ast_codec_pref_string(struct ast_codec_pref *pref, char *buf, size_t size)
1026 {
1027  int x;
1028  format_t codec;
1029  size_t total_len, slen;
1030  char *formatname;
1031 
1032  memset(buf, 0, size);
1033  total_len = size;
1034  buf[0] = '(';
1035  total_len--;
1036  for (x = 0; x < sizeof(format_t) * 8; x++) {
1037  if (total_len <= 0)
1038  break;
1039  if (!(codec = ast_codec_pref_index(pref,x)))
1040  break;
1041  if ((formatname = ast_getformatname(codec))) {
1042  slen = strlen(formatname);
1043  if (slen > total_len)
1044  break;
1045  strncat(buf, formatname, total_len - 1); /* safe */
1046  total_len -= slen;
1047  }
1048  if (total_len && x < sizeof(format_t) * 8 - 1 && ast_codec_pref_index(pref, x + 1)) {
1049  strncat(buf, "|", total_len - 1); /* safe */
1050  total_len--;
1051  }
1052  }
1053  if (total_len) {
1054  strncat(buf, ")", total_len - 1); /* safe */
1055  total_len--;
1056  }
1057 
1058  return size - total_len;
1059 }
1060 
1062 {
1063  int slot = 0;
1064 
1065  if ((idx >= 0) && (idx < sizeof(pref->order))) {
1066  slot = pref->order[idx];
1067  }
1068 
1069  return slot ? AST_FORMAT_LIST[slot - 1].bits : 0;
1070 }
1071 
1072 /*! \brief Remove codec from pref list */
1074 {
1075  struct ast_codec_pref oldorder;
1076  int x, y = 0;
1077  int slot;
1078  int size;
1079 
1080  if (!pref->order[0])
1081  return;
1082 
1083  memcpy(&oldorder, pref, sizeof(oldorder));
1084  memset(pref, 0, sizeof(*pref));
1085 
1086  for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
1087  slot = oldorder.order[x];
1088  size = oldorder.framing[x];
1089  if (! slot)
1090  break;
1091  if (AST_FORMAT_LIST[slot-1].bits != format) {
1092  pref->order[y] = slot;
1093  pref->framing[y++] = size;
1094  }
1095  }
1096 }
1097 
1098 /*! \brief Append codec to list */
1100 {
1101  int x, newindex = 0;
1102 
1103  ast_codec_pref_remove(pref, format);
1104 
1105  for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
1106  if (AST_FORMAT_LIST[x].bits == format) {
1107  newindex = x + 1;
1108  break;
1109  }
1110  }
1111 
1112  if (newindex) {
1113  for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
1114  if (!pref->order[x]) {
1115  pref->order[x] = newindex;
1116  break;
1117  }
1118  }
1119  }
1120 
1121  return x;
1122 }
1123 
1124 /*! \brief Prepend codec to list */
1125 void ast_codec_pref_prepend(struct ast_codec_pref *pref, format_t format, int only_if_existing)
1126 {
1127  int x, newindex = 0;
1128 
1129  /* First step is to get the codecs "index number" */
1130  for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
1131  if (AST_FORMAT_LIST[x].bits == format) {
1132  newindex = x + 1;
1133  break;
1134  }
1135  }
1136  /* Done if its unknown */
1137  if (!newindex)
1138  return;
1139 
1140  /* Now find any existing occurrence, or the end */
1141  for (x = 0; x < sizeof(format_t) * 8; x++) {
1142  if (!pref->order[x] || pref->order[x] == newindex)
1143  break;
1144  }
1145 
1146  /* If we failed to find any occurrence, set to the end */
1147  if (x == sizeof(format_t) * 8) {
1148  --x;
1149  }
1150 
1151  if (only_if_existing && !pref->order[x])
1152  return;
1153 
1154  /* Move down to make space to insert - either all the way to the end,
1155  or as far as the existing location (which will be overwritten) */
1156  for (; x > 0; x--) {
1157  pref->order[x] = pref->order[x - 1];
1158  pref->framing[x] = pref->framing[x - 1];
1159  }
1160 
1161  /* And insert the new entry */
1162  pref->order[0] = newindex;
1163  pref->framing[0] = 0; /* ? */
1164 }
1165 
1166 /*! \brief Set packet size for codec */
1167 int ast_codec_pref_setsize(struct ast_codec_pref *pref, format_t format, int framems)
1168 {
1169  int x, idx = -1;
1170 
1171  for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
1172  if (AST_FORMAT_LIST[x].bits == format) {
1173  idx = x;
1174  break;
1175  }
1176  }
1177 
1178  if (idx < 0)
1179  return -1;
1180 
1181  /* size validation */
1182  if (!framems)
1183  framems = AST_FORMAT_LIST[idx].def_ms;
1184 
1185  if (AST_FORMAT_LIST[idx].inc_ms && framems % AST_FORMAT_LIST[idx].inc_ms) /* avoid division by zero */
1186  framems -= framems % AST_FORMAT_LIST[idx].inc_ms;
1187 
1188  if (framems < AST_FORMAT_LIST[idx].min_ms)
1189  framems = AST_FORMAT_LIST[idx].min_ms;
1190 
1191  if (framems > AST_FORMAT_LIST[idx].max_ms)
1192  framems = AST_FORMAT_LIST[idx].max_ms;
1193 
1194  for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
1195  if (pref->order[x] == (idx + 1)) {
1196  pref->framing[x] = framems;
1197  break;
1198  }
1199  }
1200 
1201  return x;
1202 }
1203 
1204 /*! \brief Get packet size for codec */
1206 {
1207  int x, idx = -1, framems = 0;
1208  struct ast_format_list fmt = { 0, };
1209 
1210  for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
1211  if (AST_FORMAT_LIST[x].bits == format) {
1212  fmt = AST_FORMAT_LIST[x];
1213  idx = x;
1214  break;
1215  }
1216  }
1217 
1218  if (idx < 0) {
1219  ast_log(AST_LOG_WARNING, "Format %s unknown; unable to get preferred codec packet size\n", ast_getformatname(format));
1220  return fmt;
1221  }
1222 
1223  for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
1224  if (pref->order[x] == (idx + 1)) {
1225  framems = pref->framing[x];
1226  break;
1227  }
1228  }
1229 
1230  /* size validation */
1231  if (!framems)
1232  framems = AST_FORMAT_LIST[idx].def_ms;
1233 
1234  if (AST_FORMAT_LIST[idx].inc_ms && framems % AST_FORMAT_LIST[idx].inc_ms) /* avoid division by zero */
1235  framems -= framems % AST_FORMAT_LIST[idx].inc_ms;
1236 
1237  if (framems < AST_FORMAT_LIST[idx].min_ms)
1238  framems = AST_FORMAT_LIST[idx].min_ms;
1239 
1240  if (framems > AST_FORMAT_LIST[idx].max_ms)
1241  framems = AST_FORMAT_LIST[idx].max_ms;
1242 
1243  fmt.cur_ms = framems;
1244 
1245  return fmt;
1246 }
1247 
1248 /*! \brief Pick a codec */
1250 {
1251  int x, slot;
1252  format_t ret = 0;
1253 
1254  for (x = 0; x < ARRAY_LEN(AST_FORMAT_LIST); x++) {
1255  slot = pref->order[x];
1256 
1257  if (!slot)
1258  break;
1259  if (formats & AST_FORMAT_LIST[slot-1].bits) {
1260  ret = AST_FORMAT_LIST[slot-1].bits;
1261  break;
1262  }
1263  }
1264  if (ret & AST_FORMAT_AUDIO_MASK)
1265  return ret;
1266 
1267  ast_debug(4, "Could not find preferred codec - %s\n", find_best ? "Going for the best codec" : "Returning zero codec");
1268 
1269  return find_best ? ast_best_codec(formats) : 0;
1270 }
1271 
1272 int ast_parse_allow_disallow(struct ast_codec_pref *pref, format_t *mask, const char *list, int allowing)
1273 {
1274  int errors = 0, framems = 0;
1275  char *parse = NULL, *this = NULL, *psize = NULL;
1276  format_t format = 0;
1277 
1278  parse = ast_strdupa(list);
1279  while ((this = strsep(&parse, ","))) {
1280  framems = 0;
1281  if ((psize = strrchr(this, ':'))) {
1282  *psize++ = '\0';
1283  ast_debug(1, "Packetization for codec: %s is %s\n", this, psize);
1284  framems = atoi(psize);
1285  if (framems < 0) {
1286  framems = 0;
1287  errors++;
1288  ast_log(LOG_WARNING, "Bad packetization value for codec %s\n", this);
1289  }
1290  }
1291  if (!(format = ast_getformatbyname(this))) {
1292  ast_log(LOG_WARNING, "Cannot %s unknown format '%s'\n", allowing ? "allow" : "disallow", this);
1293  errors++;
1294  continue;
1295  }
1296 
1297  if (mask) {
1298  if (allowing)
1299  *mask |= format;
1300  else
1301  *mask &= ~format;
1302  }
1303 
1304  /* Set up a preference list for audio. Do not include video in preferences
1305  since we can not transcode video and have to use whatever is offered
1306  */
1307  if (pref && (format & AST_FORMAT_AUDIO_MASK)) {
1308  if (strcasecmp(this, "all")) {
1309  if (allowing) {
1310  ast_codec_pref_append(pref, format);
1311  ast_codec_pref_setsize(pref, format, framems);
1312  }
1313  else
1314  ast_codec_pref_remove(pref, format);
1315  } else if (!allowing) {
1316  memset(pref, 0, sizeof(*pref));
1317  }
1318  }
1319  }
1320  return errors;
1321 }
1322 
1323 static int g723_len(unsigned char buf)
1324 {
1325  enum frame_type type = buf & TYPE_MASK;
1326 
1327  switch(type) {
1328  case TYPE_DONTSEND:
1329  return 0;
1330  break;
1331  case TYPE_SILENCE:
1332  return 4;
1333  break;
1334  case TYPE_HIGH:
1335  return 24;
1336  break;
1337  case TYPE_LOW:
1338  return 20;
1339  break;
1340  default:
1341  ast_log(LOG_WARNING, "Badly encoded frame (%u)\n", type);
1342  }
1343  return -1;
1344 }
1345 
1346 static int g723_samples(unsigned char *buf, int maxlen)
1347 {
1348  int pos = 0;
1349  int samples = 0;
1350  int res;
1351  while(pos < maxlen) {
1352  res = g723_len(buf[pos]);
1353  if (res <= 0)
1354  break;
1355  samples += 240;
1356  pos += res;
1357  }
1358  return samples;
1359 }
1360 
1361 static unsigned char get_n_bits_at(unsigned char *data, int n, int bit)
1362 {
1363  int byte = bit / 8; /* byte containing first bit */
1364  int rem = 8 - (bit % 8); /* remaining bits in first byte */
1365  unsigned char ret = 0;
1366 
1367  if (n <= 0 || n > 8)
1368  return 0;
1369 
1370  if (rem < n) {
1371  ret = (data[byte] << (n - rem));
1372  ret |= (data[byte + 1] >> (8 - n + rem));
1373  } else {
1374  ret = (data[byte] >> (rem - n));
1375  }
1376 
1377  return (ret & (0xff >> (8 - n)));
1378 }
1379 
1380 static int speex_get_wb_sz_at(unsigned char *data, int len, int bit)
1381 {
1382  static const int SpeexWBSubModeSz[] = {
1383  4, 36, 112, 192,
1384  352, 0, 0, 0 };
1385  int off = bit;
1386  unsigned char c;
1387 
1388  /* skip up to two wideband frames */
1389  if (((len * 8 - off) >= 5) &&
1390  get_n_bits_at(data, 1, off)) {
1391  c = get_n_bits_at(data, 3, off + 1);
1392  off += SpeexWBSubModeSz[c];
1393 
1394  if (((len * 8 - off) >= 5) &&
1395  get_n_bits_at(data, 1, off)) {
1396  c = get_n_bits_at(data, 3, off + 1);
1397  off += SpeexWBSubModeSz[c];
1398 
1399  if (((len * 8 - off) >= 5) &&
1400  get_n_bits_at(data, 1, off)) {
1401  ast_log(LOG_WARNING, "Encountered corrupt speex frame; too many wideband frames in a row.\n");
1402  return -1;
1403  }
1404  }
1405 
1406  }
1407  return off - bit;
1408 }
1409 
1410 static int speex_samples(unsigned char *data, int len)
1411 {
1412  static const int SpeexSubModeSz[] = {
1413  5, 43, 119, 160,
1414  220, 300, 364, 492,
1415  79, 0, 0, 0,
1416  0, 0, 0, 0 };
1417  static const int SpeexInBandSz[] = {
1418  1, 1, 4, 4,
1419  4, 4, 4, 4,
1420  8, 8, 16, 16,
1421  32, 32, 64, 64 };
1422  int bit = 0;
1423  int cnt = 0;
1424  int off;
1425  unsigned char c;
1426 
1427  while ((len * 8 - bit) >= 5) {
1428  /* skip wideband frames */
1429  off = speex_get_wb_sz_at(data, len, bit);
1430  if (off < 0) {
1431  ast_log(LOG_WARNING, "Had error while reading wideband frames for speex samples\n");
1432  break;
1433  }
1434  bit += off;
1435 
1436  if ((len * 8 - bit) < 5)
1437  break;
1438 
1439  /* get control bits */
1440  c = get_n_bits_at(data, 5, bit);
1441  bit += 5;
1442 
1443  if (c == 15) {
1444  /* terminator */
1445  break;
1446  } else if (c == 14) {
1447  /* in-band signal; next 4 bits contain signal id */
1448  c = get_n_bits_at(data, 4, bit);
1449  bit += 4;
1450  bit += SpeexInBandSz[c];
1451  } else if (c == 13) {
1452  /* user in-band; next 4 bits contain msg len */
1453  c = get_n_bits_at(data, 4, bit);
1454  bit += 4;
1455  /* after which it's 5-bit signal id + c bytes of data */
1456  bit += 5 + c * 8;
1457  } else if (c > 8) {
1458  /* unknown */
1459  ast_log(LOG_WARNING, "Unknown speex control frame %d\n", c);
1460  break;
1461  } else {
1462  /* skip number bits for submode (less the 5 control bits) */
1463  bit += SpeexSubModeSz[c] - 5;
1464  cnt += 160; /* new frame */
1465  }
1466  }
1467  return cnt;
1468 }
1469 
1471 {
1472  int samples = 0;
1473  char tmp[64];
1474 
1475  switch (f->subclass.codec) {
1476  case AST_FORMAT_SPEEX:
1477  samples = speex_samples(f->data.ptr, f->datalen);
1478  break;
1479  case AST_FORMAT_SPEEX16:
1480  samples = 2 * speex_samples(f->data.ptr, f->datalen);
1481  break;
1482  case AST_FORMAT_G723_1:
1483  samples = g723_samples(f->data.ptr, f->datalen);
1484  break;
1485  case AST_FORMAT_ILBC:
1486  samples = 240 * (f->datalen / 50);
1487  break;
1488  case AST_FORMAT_GSM:
1489  samples = 160 * (f->datalen / 33);
1490  break;
1491  case AST_FORMAT_G729A:
1492  samples = f->datalen * 8;
1493  break;
1494  case AST_FORMAT_SLINEAR:
1495  case AST_FORMAT_SLINEAR16:
1496  samples = f->datalen / 2;
1497  break;
1498  case AST_FORMAT_LPC10:
1499  /* assumes that the RTP packet contains one LPC10 frame */
1500  samples = 22 * 8;
1501  samples += (((char *)(f->data.ptr))[7] & 0x1) * 8;
1502  break;
1503  case AST_FORMAT_ULAW:
1504  case AST_FORMAT_ALAW:
1505  case AST_FORMAT_TESTLAW:
1506  samples = f->datalen;
1507  break;
1508  case AST_FORMAT_G722:
1509  case AST_FORMAT_ADPCM:
1510  case AST_FORMAT_G726:
1511  case AST_FORMAT_G726_AAL2:
1512  samples = f->datalen * 2;
1513  break;
1514  case AST_FORMAT_SIREN7:
1515  /* 16,000 samples per second at 32kbps is 4,000 bytes per second */
1516  samples = f->datalen * (16000 / 4000);
1517  break;
1518  case AST_FORMAT_SIREN14:
1519  /* 32,000 samples per second at 48kbps is 6,000 bytes per second */
1520  samples = (int) f->datalen * ((float) 32000 / 6000);
1521  break;
1522  case AST_FORMAT_G719:
1523  /* 48,000 samples per second at 64kbps is 8,000 bytes per second */
1524  samples = (int) f->datalen * ((float) 48000 / 8000);
1525  break;
1526  default:
1527  ast_log(LOG_WARNING, "Unable to calculate samples for format %s\n", ast_getformatname_multiple(tmp, sizeof(tmp), f->subclass.codec));
1528  }
1529  return samples;
1530 }
1531 
1533 {
1534  int len = 0;
1535 
1536  /* XXX Still need speex, and lpc10 XXX */
1537  switch(format) {
1538  case AST_FORMAT_G723_1:
1539  len = (samples / 240) * 20;
1540  break;
1541  case AST_FORMAT_ILBC:
1542  len = (samples / 240) * 50;
1543  break;
1544  case AST_FORMAT_GSM:
1545  len = (samples / 160) * 33;
1546  break;
1547  case AST_FORMAT_G729A:
1548  len = samples / 8;
1549  break;
1550  case AST_FORMAT_SLINEAR:
1551  case AST_FORMAT_SLINEAR16:
1552  len = samples * 2;
1553  break;
1554  case AST_FORMAT_ULAW:
1555  case AST_FORMAT_ALAW:
1556  case AST_FORMAT_TESTLAW:
1557  len = samples;
1558  break;
1559  case AST_FORMAT_G722:
1560  case AST_FORMAT_ADPCM:
1561  case AST_FORMAT_G726:
1562  case AST_FORMAT_G726_AAL2:
1563  len = samples / 2;
1564  break;
1565  case AST_FORMAT_SIREN7:
1566  /* 16,000 samples per second at 32kbps is 4,000 bytes per second */
1567  len = samples / (16000 / 4000);
1568  break;
1569  case AST_FORMAT_SIREN14:
1570  /* 32,000 samples per second at 48kbps is 6,000 bytes per second */
1571  len = (int) samples / ((float) 32000 / 6000);
1572  break;
1573  case AST_FORMAT_G719:
1574  /* 48,000 samples per second at 64kbps is 8,000 bytes per second */
1575  len = (int) samples / ((float) 48000 / 8000);
1576  break;
1577  default:
1578  ast_log(LOG_WARNING, "Unable to calculate sample length for format %s\n", ast_getformatname(format));
1579  }
1580 
1581  return len;
1582 }
1583 
1584 int ast_frame_adjust_volume(struct ast_frame *f, int adjustment)
1585 {
1586  int count;
1587  short *fdata = f->data.ptr;
1588  short adjust_value = abs(adjustment);
1589 
1591  return -1;
1592 
1593  if (!adjustment)
1594  return 0;
1595 
1596  for (count = 0; count < f->samples; count++) {
1597  if (adjustment > 0) {
1598  ast_slinear_saturated_multiply(&fdata[count], &adjust_value);
1599  } else if (adjustment < 0) {
1600  ast_slinear_saturated_divide(&fdata[count], &adjust_value);
1601  }
1602  }
1603 
1604  return 0;
1605 }
1606 
1607 int ast_frame_slinear_sum(struct ast_frame *f1, struct ast_frame *f2)
1608 {
1609  int count;
1610  short *data1, *data2;
1611 
1612  if ((f1->frametype != AST_FRAME_VOICE) || (f1->subclass.codec != AST_FORMAT_SLINEAR))
1613  return -1;
1614 
1615  if ((f2->frametype != AST_FRAME_VOICE) || (f2->subclass.codec != AST_FORMAT_SLINEAR))
1616  return -1;
1617 
1618  if (f1->samples != f2->samples)
1619  return -1;
1620 
1621  for (count = 0, data1 = f1->data.ptr, data2 = f2->data.ptr;
1622  count < f1->samples;
1623  count++, data1++, data2++)
1624  ast_slinear_saturated_add(data1, data2);
1625 
1626  return 0;
1627 }
1628 
1629 int ast_frame_clear(struct ast_frame *frame)
1630 {
1631  struct ast_frame *next;
1632 
1633  for (next = AST_LIST_NEXT(frame, frame_list);
1634  frame;
1635  frame = next, next = frame ? AST_LIST_NEXT(frame, frame_list) : NULL) {
1636  memset(frame->data.ptr, 0, frame->datalen);
1637  }
1638  return 0;
1639 }
format_t format
Definition: frame.c:87
This is just so ast_frames, a list head struct for holding a list of ast_frame structures, is defined.
Definition: frame.c:66
void ast_frame_free(struct ast_frame *fr, int cache)
Requests a frame to be allocated.
Definition: frame.c:375
union ast_frame_subclass subclass
Definition: frame.h:146
struct ast_smoother * ast_smoother_new(int bytes)
Definition: frame.c:183
#define SMOOTHER_SIZE
Definition: frame.c:74
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:191
void ast_smoother_free(struct ast_smoother *s)
Definition: frame.c:294
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
int offset
Definition: frame.h:156
struct ast_frame ast_null_frame
Definition: frame.c:131
int ast_frame_clear(struct ast_frame *frame)
Clear all audio samples from an ast_frame. The frame must be AST_FRAME_VOICE and AST_FORMAT_SLINEAR.
Definition: frame.c:1629
void * ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size)
Retrieve thread storage.
char * strsep(char **str, const char *delims)
void ast_frame_dump(const char *name, struct ast_frame *f, char *prefix)
Definition: frame.c:778
#define FRAME_CACHE_MAX_SIZE
Maximum ast_frame cache size.
Definition: frame.c:62
int ast_codec_pref_string(struct ast_codec_pref *pref, char *buf, size_t size)
Dump audio codec preference list into a string.
Definition: frame.c:1025
int seqno
Definition: frame.h:172
#define ast_strdup(a)
Definition: astmm.h:109
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: cli.c:2177
#define AST_FORMAT_H261
Definition: frame.h:280
struct ast_frame * ast_smoother_read(struct ast_smoother *s)
Definition: frame.c:244
#define ast_test_flag(p, flag)
Definition: utils.h:63
Support for translation of data formats. translate.c.
char order[sizeof(format_t)*8]
Definition: frame.h:39
#define AST_FORMAT_G723_1
Definition: frame.h:242
void * ptr
Definition: frame.h:160
int ast_codec_pref_setsize(struct ast_codec_pref *pref, format_t format, int framems)
Set packet size for codec.
Definition: frame.c:1167
#define AST_HTML_BEGIN
Definition: frame.h:226
static char * show_codecs(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: frame.c:673
Convenient Signal Processing routines.
#define COLOR_YELLOW
Definition: term.h:54
void ast_smoother_set_flags(struct ast_smoother *smoother, int flags)
Definition: frame.c:198
descriptor for a cli entry.
Definition: cli.h:165
const int argc
Definition: cli.h:154
#define LOG_WARNING
Definition: logger.h:144
static void __frame_free(struct ast_frame *fr, int cache)
Definition: frame.c:341
void ast_verbose(const char *fmt,...)
Definition: logger.c:1568
static unsigned char get_n_bits_at(unsigned char *data, int n, int bit)
Definition: frame.c:1361
#define AST_LOG_WARNING
Definition: logger.h:149
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:100
format_t ast_codec_pref_index(struct ast_codec_pref *pref, int index)
Codec located at a particular place in the preference index.
Definition: frame.c:1061
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:438
enum ast_control_t38 request_response
Definition: frame.h:412
#define AST_FORMAT_H263_PLUS
Definition: frame.h:285
#define AST_MODEM_T38
Definition: frame.h:216
Definition: cli.h:146
#define AST_HTML_END
Definition: frame.h:228
static int g723_samples(unsigned char *buf, int maxlen)
Definition: frame.c:1346
long ts
Definition: frame.h:168
int __ast_smoother_feed(struct ast_smoother *s, struct ast_frame *f, int swap)
Definition: frame.c:208
struct ast_frames list
Definition: frame.c:69
void ast_smoother_reset(struct ast_smoother *s, int bytes)
Definition: frame.c:155
format_t ast_best_codec(format_t fmts)
Pick the best audio codec.
Definition: channel.c:1062
static force_inline int ast_format_rate(format_t format)
Get the sample rate for a given format.
Definition: frame.h:809
#define ast_copy_flags(dest, src, flagz)
Definition: utils.h:84
struct ast_frame * ast_frisolate(struct ast_frame *fr)
Makes a frame independent of any static storage.
Definition: frame.c:391
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
format_t codec
Definition: frame.h:137
struct ast_frame f
Definition: frame.c:91
struct ast_format_list * ast_get_format_list(size_t *size)
Definition: frame.c:572
Definitions to aid in the use of thread local storage.
frame_type
Definition: frame.c:76
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
#define TYPE_MASK
Definition: frame.c:83
#define AST_HTML_URL
Definition: frame.h:222
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:600
void ast_smoother_reconfigure(struct ast_smoother *s, int bytes)
Reconfigure an existing smoother to output a different number of bytes per frame. ...
Definition: frame.c:161
#define AST_FORMAT_G729A
Definition: frame.h:258
#define COLOR_BRCYAN
Definition: term.h:60
#define AST_FORMAT_LPC10
Definition: frame.h:256
static int frames
Definition: iax2-parser.c:49
Utility functions.
#define COLOR_BRRED
Definition: term.h:50
static void framer_shutdown(void)
Definition: frame.c:990
static struct ast_threadstorage frame_cache
Definition: frame.c:51
Definition of supported media formats (codecs)
Definition: frame.h:550
static struct ast_frame * ast_frame_header_new(void)
Definition: frame.c:299
int ast_codec_pref_append(struct ast_codec_pref *pref, format_t format)
Append a audio codec to a preference list, removing it first if it was already there.
Definition: frame.c:1099
#define ast_opt_dont_warn
Definition: options.h:121
#define AST_FORMAT_PNG
Definition: frame.h:278
struct ast_format_list ast_codec_pref_getsize(struct ast_codec_pref *pref, format_t format)
Get packet size for codec.
Definition: frame.c:1205
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
#define AST_SMOOTHER_FLAG_BE
Definition: frame.h:428
General Asterisk PBX channel definitions.
#define AST_FRIENDLY_OFFSET
Offset into a frame&#39;s data buffer.
Definition: frame.h:204
const char * src
Definition: frame.h:158
#define AST_HTML_DATA
Definition: frame.h:224
const int fd
Definition: cli.h:153
#define AST_FORMAT_ALAW
Definition: frame.h:248
#define AST_FORMAT_T140RED
Definition: frame.h:292
void ast_codec_pref_remove(struct ast_codec_pref *pref, format_t format)
Remove audio a codec from a preference list.
Definition: frame.c:1073
#define AST_FORMAT_SPEEX
Definition: frame.h:260
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
Asterisk internal frame definitions.
#define AST_FORMAT_TEXT_MASK
Definition: frame.h:297
int datalen
Definition: frame.h:148
static int smoother_frame_feed(struct ast_smoother *s, struct ast_frame *f, int swap)
Definition: frame.c:133
#define AST_FORMAT_G726
Definition: frame.h:264
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:554
#define AST_FORMAT_G726_AAL2
Definition: frame.h:250
#define AST_MALLOCD_SRC
Definition: frame.h:212
char * name
Definition: frame.h:552
int ast_register_atexit(void(*func)(void))
Register a function to be executed before Asterisk exits.
Definition: asterisk.c:998
static force_inline void ast_slinear_saturated_add(short *input, short *value)
Definition: utils.h:312
struct timeval ast_samp2tv(unsigned int _nsamp, unsigned int _rate)
Returns a timeval corresponding to the duration of n samples at rate r. Useful to convert samples to ...
Definition: time.h:191
#define COLOR_BRGREEN
Definition: term.h:52
static force_inline void ast_slinear_saturated_multiply(short *input, short *value)
Definition: utils.h:338
static struct callattempt * find_best(struct callattempt *outgoing)
find the entry with the best metric, or NULL
Definition: app_queue.c:3540
size_t mallocd_hdr_len
Definition: frame.h:154
A set of macros to manage forward-linked lists.
char * desc
Definition: frame.h:554
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:818
#define AST_FORMAT_H263
Definition: frame.h:283
char data[SMOOTHER_SIZE]
Definition: frame.c:93
#define AST_FORMAT_SLINEAR16
Definition: frame.h:272
char * term_color(char *outbuf, const char *inbuf, int fgcolor, int bgcolor, int maxout)
Definition: term.c:184
#define COLOR_BRMAGENTA
Definition: term.h:58
const char *const * argv
Definition: cli.h:155
static const char * ast_expand_codec_alias(const char *in)
Definition: frame.c:630
#define AST_LIST_HEAD_NOLOCK(name, type)
Defines a structure to be used to hold a list of specified type (with no lock).
Definition: linkedlists.h:224
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
format_t ast_getformatbyname(const char *name)
Gets a format from a name.
Definition: frame.c:641
#define COLOR_BLACK
Definition: term.h:47
int size
Definition: frame.c:86
char * ast_getformatname(format_t format)
Get the name of a format.
Definition: frame.c:578
#define AST_FORMAT_JPEG
Definition: frame.h:276
#define AST_FORMAT_SIREN7
Definition: frame.h:268
float samplesperbyte
Definition: frame.c:89
int len
Definition: frame.c:96
int64_t format_t
Definition: frame_defs.h:32
#define AST_HTML_LDCOMPLETE
Definition: frame.h:230
#define CLI_SHOWUSAGE
Definition: cli.h:44
#define AST_SMOOTHER_FLAG_G729
Definition: frame.h:427
#define AST_FORMAT_ULAW
Definition: frame.h:246
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
struct timeval delivery
Definition: frame.c:92
#define AST_FORMAT_TESTLAW
Definition: frame.h:303
Definition: file.c:65
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Definition: utils.c:1587
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
format_t ast_codec_choose(struct ast_codec_pref *pref, format_t formats, int find_best)
Select the best audio format according to preference list from supplied options. If &quot;find_best&quot; is no...
Definition: frame.c:1249
struct ast_frame * opt
Definition: frame.c:95
#define LOG_NOTICE
Definition: logger.h:133
#define AST_HTML_LINKURL
Definition: frame.h:234
int framing[64]
Definition: frame.h:40
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:696
#define AST_FORMAT_VIDEO_MASK
Definition: frame.h:290
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1858
static const char name[]
#define ast_free(a)
Definition: astmm.h:97
char * command
Definition: cli.h:180
#define AST_HTML_NOSUPPORT
Definition: frame.h:232
#define AST_FORMAT_AUDIO_MASK
Definition: frame.h:274
static force_inline void ast_slinear_saturated_divide(short *input, short *value)
Definition: utils.h:351
#define AST_FORMAT_SIREN14
Definition: frame.h:270
static int speex_samples(unsigned char *data, int len)
Definition: frame.c:1410
static struct ast_format f[]
Definition: format_g726.c:181
struct ast_format_list * ast_get_format_list_index(int index)
Definition: frame.c:567
int ast_smoother_test_flag(struct ast_smoother *s, int flag)
Definition: frame.c:203
#define AST_MALLOCD_HDR
Definition: frame.h:208
static const char type[]
Definition: chan_nbs.c:57
format_t bits
Definition: frame.h:551
struct timeval delivery
Definition: frame.h:162
int mallocd
Definition: frame.h:152
struct ao2_container * cache
Definition: pbx_realtime.c:78
const char * usage
Definition: cli.h:171
unsigned int opt_needs_swap
Definition: frame.c:90
#define AST_THREADSTORAGE_CUSTOM(a, b, c)
Define a thread storage variable, with custom initialization and cleanup.
#define CLI_SUCCESS
Definition: cli.h:43
int init_framer(void)
Definition: frame.c:995
#define AST_FORMAT_T140
Definition: frame.h:294
#define AST_FORMAT_SLINEAR
Definition: frame.h:254
#define AST_FORMAT_G719
Definition: frame.h:299
Standard Command Line Interface.
#define AST_MODEM_V150
Definition: frame.h:218
#define ast_calloc(a, b)
Definition: astmm.h:82
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
int ast_codec_get_samples(struct ast_frame *f)
Returns the number of samples contained in the frame.
Definition: frame.c:1470
int ast_cli_register_multiple(struct ast_cli_entry *e, int len)
Register multiple commands.
Definition: cli.c:2167
struct ast_frame * next
Definition: frame.h:164
int ast_smoother_get_flags(struct ast_smoother *smoother)
Definition: frame.c:193
static struct ast_cli_entry my_clis[]
Definition: frame.c:985
int ast_frame_adjust_volume(struct ast_frame *f, int adjustment)
Adjusts the volume of the audio samples contained in a frame.
Definition: frame.c:1584
#define AST_FORMAT_ADPCM
Definition: frame.h:252
char * ast_getformatname_multiple(char *buf, size_t size, format_t format)
Get the names of a set of formats.
Definition: frame.c:591
Data structure associated with a single frame of data.
Definition: frame.h:142
void ast_codec_pref_convert(struct ast_codec_pref *pref, char *buf, size_t size, int right)
Shift an audio codec preference list up or down 65 bytes so that it becomes an ASCII string...
Definition: frame.c:1002
static struct ast_format_list AST_FORMAT_LIST[]
Definition of supported media formats (codecs)
Definition: frame.c:100
#define AST_FORMAT_G722
Definition: frame.h:266
static int speex_get_wb_sz_at(unsigned char *data, int len, int bit)
Definition: frame.c:1380
char framedata[SMOOTHER_SIZE+AST_FRIENDLY_OFFSET]
Definition: frame.c:94
Handy terminal functions for vt* terms.
uint32_t uint32
Definition: frame.h:160
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
#define AST_HTML_UNLINK
Definition: frame.h:236
enum ast_frame_type frametype
Definition: frame.h:144
static int g723_len(unsigned char buf)
Definition: frame.c:1323
Definition: frame.c:78
size_t size
Definition: frame.c:70
#define AST_FORMAT_MP4_VIDEO
Definition: frame.h:289
#define AST_FORMAT_H264
Definition: frame.h:287
void ast_swapcopy_samples(void *dst, const void *src, int samples)
Definition: frame.c:556
int ast_frame_slinear_sum(struct ast_frame *f1, struct ast_frame *f2)
Sums two frames of audio samples.
Definition: frame.c:1607
#define AST_HTML_LINKREJECT
Definition: frame.h:238
static void frame_cache_cleanup(void *data)
Definition: frame.c:329
#define ast_malloc(a)
Definition: astmm.h:91
static snd_pcm_format_t format
Definition: chan_alsa.c:93
union ast_frame::@172 data
int ast_codec_get_len(format_t format, int samples)
Returns the number of bytes for the number of samples of the given format.
Definition: frame.c:1532
#define AST_FORMAT_ILBC
Definition: frame.h:262
int flags
Definition: frame.c:88
#define AST_FORMAT_GSM
Definition: frame.h:244
long len
Definition: frame.h:170
ast_control_t38
Definition: frame.h:384
struct ast_frame * ast_frdup(const struct ast_frame *fr)
Copies a frame.
Definition: frame.c:474
int ast_parse_allow_disallow(struct ast_codec_pref *pref, format_t *mask, const char *list, int allowing)
Parse an &quot;allow&quot; or &quot;deny&quot; line in a channel or device configuration and update the capabilities mask...
Definition: frame.c:1272
#define AST_MIN_OFFSET
Definition: frame.h:205
static char * show_codec_n(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: frame.c:740
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
Definition: asterisk.h:180
int samples
Definition: frame.h:150
#define ast_calloc_cache(a, b)
Definition: astmm.h:85
#define AST_MALLOCD_DATA
Definition: frame.h:210
void ast_codec_pref_prepend(struct ast_codec_pref *pref, format_t format, int only_if_existing)
Prepend an audio codec to a preference list, removing it first if it was already there.
Definition: frame.c:1125
static char prefix[MAX_PREFIX]
Definition: http.c:107
#define AST_FORMAT_SPEEX16
Definition: frame.h:301
char * ast_codec2str(format_t codec)
Get a name from a format Gets a name from a format.
Definition: frame.c:660