Asterisk - The Open Source Telephony Project  GIT-master-0190e70
main/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 #include "asterisk/_private.h"
33 #include "asterisk/lock.h"
34 #include "asterisk/frame.h"
35 #include "asterisk/format_cache.h"
36 #include "asterisk/channel.h"
37 #include "asterisk/cli.h"
38 #include "asterisk/term.h"
39 #include "asterisk/utils.h"
40 #include "asterisk/threadstorage.h"
41 #include "asterisk/linkedlists.h"
42 #include "asterisk/translate.h"
43 #include "asterisk/dsp.h"
44 #include "asterisk/file.h"
45 
46 #include <math.h>
47 
48 #if (defined(LOW_MEMORY) || defined(MALLOC_DEBUG)) && !defined(NO_FRAME_CACHE)
49 #define NO_FRAME_CACHE
50 #endif
51 
52 #if !defined(NO_FRAME_CACHE)
53 static void frame_cache_cleanup(void *data);
54 
55 /*! \brief A per-thread cache of frame headers */
57 
58 /*!
59  * \brief Maximum ast_frame cache size
60  *
61  * In most cases where the frame header cache will be useful, the size
62  * of the cache will stay very small. However, it is not always the case that
63  * the same thread that allocates the frame will be the one freeing them, so
64  * sometimes a thread will never have any frames in its cache, or the cache
65  * will never be pulled from. For the latter case, we limit the maximum size.
66  */
67 #define FRAME_CACHE_MAX_SIZE 10
68 
69 /*! \brief This is just so ast_frames, a list head struct for holding a list of
70  * ast_frame structures, is defined. */
72 
74  struct ast_frames list;
75  size_t size;
76 };
77 #endif
78 
80 
81 static struct ast_frame *ast_frame_header_new(const char *file, int line, const char *func)
82 {
83  struct ast_frame *f;
84 
85 #if !defined(NO_FRAME_CACHE)
86  struct ast_frame_cache *frames;
87 
88  if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames)))) {
89  if ((f = AST_LIST_REMOVE_HEAD(&frames->list, frame_list))) {
90  size_t mallocd_len = f->mallocd_hdr_len;
91 
92  memset(f, 0, sizeof(*f));
93  f->mallocd_hdr_len = mallocd_len;
94  frames->size--;
95  return f;
96  }
97  }
98 #endif
99 
100  if (!(f = __ast_calloc(1, sizeof(*f), file, line, func))) {
101  return NULL;
102  }
103 
104  f->mallocd_hdr_len = sizeof(*f);
105 
106  return f;
107 }
108 
109 #if !defined(NO_FRAME_CACHE)
110 static void frame_cache_cleanup(void *data)
111 {
112  struct ast_frame_cache *frames = data;
113  struct ast_frame *f;
114 
115  while ((f = AST_LIST_REMOVE_HEAD(&frames->list, frame_list)))
116  ast_free(f);
117 
118  ast_free(frames);
119 }
120 #endif
121 
122 static void __frame_free(struct ast_frame *fr, int cache)
123 {
124  if (!fr->mallocd)
125  return;
126 
127 #if !defined(NO_FRAME_CACHE)
128  if (fr->mallocd == AST_MALLOCD_HDR
129  && cache
131  /* Cool, only the header is malloc'd, let's just cache those for now
132  * to keep things simple... */
133  struct ast_frame_cache *frames;
134 
135  frames = ast_threadstorage_get(&frame_cache, sizeof(*frames));
136  if (frames && frames->size < FRAME_CACHE_MAX_SIZE) {
137  if (fr->frametype == AST_FRAME_VOICE
138  || fr->frametype == AST_FRAME_VIDEO
139  || fr->frametype == AST_FRAME_IMAGE) {
141  } else if (fr->frametype == AST_FRAME_CONTROL && fr->subclass.integer == AST_CONTROL_ANSWER) {
143  }
144 
145  AST_LIST_INSERT_HEAD(&frames->list, fr, frame_list);
146  frames->size++;
147  return;
148  }
149  }
150 #endif
151 
152  if (fr->mallocd & AST_MALLOCD_DATA) {
153  if (fr->data.ptr) {
154  ast_free(fr->data.ptr - fr->offset);
155  }
156  }
157  if (fr->mallocd & AST_MALLOCD_SRC) {
158  ast_free((void *) fr->src);
159  }
160  if (fr->mallocd & AST_MALLOCD_HDR) {
161  if (fr->frametype == AST_FRAME_VOICE
162  || fr->frametype == AST_FRAME_VIDEO
163  || fr->frametype == AST_FRAME_IMAGE) {
165  } else if (fr->frametype == AST_FRAME_CONTROL && fr->subclass.integer == AST_CONTROL_ANSWER) {
167  }
168 
169  ast_free(fr);
170  } else {
171  fr->mallocd = 0;
172  }
173 }
174 
175 
176 void ast_frame_free(struct ast_frame *frame, int cache)
177 {
178  struct ast_frame *next;
179 
180  while (frame) {
181  next = AST_LIST_NEXT(frame, frame_list);
182  __frame_free(frame, cache);
183  frame = next;
184  }
185 }
186 
187 void ast_frame_dtor(struct ast_frame *f)
188 {
189  ast_frfree(f);
190 }
191 
192 /*!
193  * \brief 'isolates' a frame by duplicating non-malloc'ed components
194  * (header, src, data).
195  * On return all components are malloc'ed
196  */
197 struct ast_frame *__ast_frisolate(struct ast_frame *fr, const char *file, int line, const char *func)
198 {
199  struct ast_frame *out;
200  void *newdata;
201 
202  /* if none of the existing frame is malloc'd, let ast_frdup() do it
203  since it is more efficient
204  */
205  if (fr->mallocd == 0) {
206  return __ast_frdup(fr, file, line, func);
207  }
208 
209  /* if everything is already malloc'd, we are done */
212  return fr;
213  }
214 
215  if (!(fr->mallocd & AST_MALLOCD_HDR)) {
216  /* Allocate a new header if needed */
217  if (!(out = ast_frame_header_new(file, line, func))) {
218  return NULL;
219  }
220  out->frametype = fr->frametype;
221  out->subclass = fr->subclass;
222  if ((fr->frametype == AST_FRAME_VOICE) || (fr->frametype == AST_FRAME_VIDEO) ||
223  (fr->frametype == AST_FRAME_IMAGE)) {
224  ao2_bump(out->subclass.format);
225  } else if (fr->frametype == AST_FRAME_VOICE && fr->subclass.integer == AST_CONTROL_ANSWER) {
226  ao2_bump(out->subclass.topology);
227  }
228  out->datalen = fr->datalen;
229  out->samples = fr->samples;
230  out->mallocd = AST_MALLOCD_HDR;
231  out->offset = fr->offset;
232  /* Copy the timing data */
233  ast_copy_flags(out, fr, AST_FLAGS_ALL);
235  out->ts = fr->ts;
236  out->len = fr->len;
237  out->seqno = fr->seqno;
238  }
239  out->stream_num = fr->stream_num;
240  } else {
241  out = fr;
242  }
243 
244  if (fr->src) {
245  /* The original frame has a source string */
246  if (!(fr->mallocd & AST_MALLOCD_SRC)) {
247  /*
248  * The original frame has a non-malloced source string.
249  *
250  * Duplicate the string and put it into the isolated frame
251  * which may also be the original frame.
252  */
253  newdata = ast_strdup(fr->src);
254  if (!newdata) {
255  if (out != fr) {
256  ast_frame_free(out, 0);
257  }
258  return NULL;
259  }
260  out->src = newdata;
261  out->mallocd |= AST_MALLOCD_SRC;
262  } else if (out != fr) {
263  /* Steal the source string from the original frame. */
264  out->src = fr->src;
265  fr->src = NULL;
266  fr->mallocd &= ~AST_MALLOCD_SRC;
267  out->mallocd |= AST_MALLOCD_SRC;
268  }
269  }
270 
271  if (!(fr->mallocd & AST_MALLOCD_DATA)) {
272  /* The original frame has a non-malloced data buffer. */
273  if (!fr->datalen && fr->frametype != AST_FRAME_TEXT) {
274  /* Actually it's just an int so we can simply copy it. */
275  out->data.uint32 = fr->data.uint32;
276  return out;
277  }
278  /*
279  * Duplicate the data buffer and put it into the isolated frame
280  * which may also be the original frame.
281  */
282  newdata = ast_malloc(fr->datalen + AST_FRIENDLY_OFFSET);
283  if (!newdata) {
284  if (out != fr) {
285  ast_frame_free(out, 0);
286  }
287  return NULL;
288  }
289  newdata += AST_FRIENDLY_OFFSET;
291  memcpy(newdata, fr->data.ptr, fr->datalen);
292  out->data.ptr = newdata;
293  out->mallocd |= AST_MALLOCD_DATA;
294  } else if (out != fr) {
295  /* Steal the data buffer from the original frame. */
296  out->data = fr->data;
297  memset(&fr->data, 0, sizeof(fr->data));
298  fr->mallocd &= ~AST_MALLOCD_DATA;
299  out->mallocd |= AST_MALLOCD_DATA;
300  }
301 
302  return out;
303 }
304 
305 struct ast_frame *__ast_frdup(const struct ast_frame *f, const char *file, int line, const char *func)
306 {
307  struct ast_frame *out = NULL;
308  int len, srclen = 0;
309  void *buf = NULL;
310 
311 #if !defined(NO_FRAME_CACHE)
312  struct ast_frame_cache *frames;
313 #endif
314 
315  /* Start with standard stuff */
316  len = sizeof(*out) + AST_FRIENDLY_OFFSET + f->datalen;
317  /* If we have a source, add space for it */
318  /*
319  * XXX Watch out here - if we receive a src which is not terminated
320  * properly, we can be easily attacked. Should limit the size we deal with.
321  */
322  if (f->src)
323  srclen = strlen(f->src);
324  if (srclen > 0)
325  len += srclen + 1;
326 
327 #if !defined(NO_FRAME_CACHE)
328  if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames)))) {
330  if (out->mallocd_hdr_len >= len) {
331  size_t mallocd_len = out->mallocd_hdr_len;
332 
334  memset(out, 0, sizeof(*out));
335  out->mallocd_hdr_len = mallocd_len;
336  buf = out;
337  frames->size--;
338  break;
339  }
340  }
342  }
343 #endif
344 
345  if (!buf) {
346  if (!(buf = __ast_calloc(1, len, file, line, func)))
347  return NULL;
348  out = buf;
349  out->mallocd_hdr_len = len;
350  }
351 
352  out->frametype = f->frametype;
353  out->subclass = f->subclass;
354  if ((f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_VIDEO) ||
355  (f->frametype == AST_FRAME_IMAGE)) {
356  ao2_bump(out->subclass.format);
357  } else if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_ANSWER) {
358  ao2_bump(out->subclass.topology);
359  }
360 
361  out->datalen = f->datalen;
362  out->samples = f->samples;
363  out->delivery = f->delivery;
364  /* Even though this new frame was allocated from the heap, we can't mark it
365  * with AST_MALLOCD_HDR, AST_MALLOCD_DATA and AST_MALLOCD_SRC, because that
366  * would cause ast_frfree() to attempt to individually free each of those
367  * under the assumption that they were separately allocated. Since this frame
368  * was allocated in a single allocation, we'll only mark it as if the header
369  * was heap-allocated; this will result in the entire frame being properly freed.
370  */
371  out->mallocd = AST_MALLOCD_HDR;
373  /* Make sure that empty text frames have a valid data.ptr */
374  if (out->datalen || f->frametype == AST_FRAME_TEXT) {
375  out->data.ptr = buf + sizeof(*out) + AST_FRIENDLY_OFFSET;
376  memcpy(out->data.ptr, f->data.ptr, out->datalen);
377  } else {
378  out->data.uint32 = f->data.uint32;
379  }
380  if (srclen > 0) {
381  /* This may seem a little strange, but it's to avoid a gcc (4.2.4) compiler warning */
382  char *src;
383  out->src = buf + sizeof(*out) + AST_FRIENDLY_OFFSET + f->datalen;
384  src = (char *) out->src;
385  /* Must have space since we allocated for it */
386  strcpy(src, f->src);
387  }
388  ast_copy_flags(out, f, AST_FLAGS_ALL);
389  out->ts = f->ts;
390  out->len = f->len;
391  out->seqno = f->seqno;
392  out->stream_num = f->stream_num;
393  return out;
394 }
395 
396 void ast_swapcopy_samples(void *dst, const void *src, int samples)
397 {
398  int i;
399  unsigned short *dst_s = dst;
400  const unsigned short *src_s = src;
401 
402  for (i = 0; i < samples; i++)
403  dst_s[i] = (src_s[i]<<8) | (src_s[i]>>8);
404 }
405 
406 char *ast_frame_subclass2str(struct ast_frame *f, char *subclass, size_t slen, char *moreinfo, size_t mlen)
407 {
408  switch(f->frametype) {
410  if (slen > 1) {
411  subclass[0] = f->subclass.integer;
412  subclass[1] = '\0';
413  }
414  break;
415  case AST_FRAME_DTMF_END:
416  if (slen > 1) {
417  subclass[0] = f->subclass.integer;
418  subclass[1] = '\0';
419  }
420  break;
421  case AST_FRAME_CONTROL:
422  switch (f->subclass.integer) {
423  case AST_CONTROL_HANGUP:
424  ast_copy_string(subclass, "Hangup", slen);
425  break;
426  case AST_CONTROL_RING:
427  ast_copy_string(subclass, "Ring", slen);
428  break;
429  case AST_CONTROL_RINGING:
430  ast_copy_string(subclass, "Ringing", slen);
431  break;
432  case AST_CONTROL_ANSWER:
433  ast_copy_string(subclass, "Answer", slen);
434  break;
435  case AST_CONTROL_BUSY:
436  ast_copy_string(subclass, "Busy", slen);
437  break;
439  ast_copy_string(subclass, "Take Off Hook", slen);
440  break;
441  case AST_CONTROL_OFFHOOK:
442  ast_copy_string(subclass, "Line Off Hook", slen);
443  break;
445  ast_copy_string(subclass, "Congestion", slen);
446  break;
447  case AST_CONTROL_FLASH:
448  ast_copy_string(subclass, "Flash", slen);
449  break;
450  case AST_CONTROL_WINK:
451  ast_copy_string(subclass, "Wink", slen);
452  break;
453  case AST_CONTROL_OPTION:
454  ast_copy_string(subclass, "Option", slen);
455  break;
457  ast_copy_string(subclass, "Key Radio", slen);
458  break;
460  ast_copy_string(subclass, "Unkey Radio", slen);
461  break;
462  case AST_CONTROL_HOLD:
463  ast_copy_string(subclass, "Hold", slen);
464  break;
465  case AST_CONTROL_UNHOLD:
466  ast_copy_string(subclass, "Unhold", slen);
467  break;
469  char *message = "Unknown";
470  if (f->datalen != sizeof(struct ast_control_t38_parameters)) {
471  message = "Invalid";
472  } else {
473  struct ast_control_t38_parameters *parameters = f->data.ptr;
474  enum ast_control_t38 state = parameters->request_response;
475  if (state == AST_T38_REQUEST_NEGOTIATE)
476  message = "Negotiation Requested";
477  else if (state == AST_T38_REQUEST_TERMINATE)
478  message = "Negotiation Request Terminated";
479  else if (state == AST_T38_NEGOTIATED)
480  message = "Negotiated";
481  else if (state == AST_T38_TERMINATED)
482  message = "Terminated";
483  else if (state == AST_T38_REFUSED)
484  message = "Refused";
485  }
486  snprintf(subclass, slen, "T38_Parameters/%s", message);
487  break;
488  }
489 
491  ast_copy_string(subclass, "Stop stream", slen);
492  break;
494  ast_copy_string(subclass, "Suspend stream", slen);
495  break;
497  ast_copy_string(subclass, "Restart stream", slen);
498  break;
500  ast_copy_string(subclass, "Reverse stream", slen);
501  break;
503  ast_copy_string(subclass, "Forward stream", slen);
504  break;
506  ast_copy_string(subclass, "Cancel stream", slen);
507  break;
509  ast_copy_string(subclass, "Record stop", slen);
510  break;
512  ast_copy_string(subclass, "Record suspend", slen);
513  break;
515  ast_copy_string(subclass, "Record mute", slen);
516  break;
518  ast_copy_string(subclass, "Media source update", slen);
519  break;
521  ast_copy_string(subclass, "Transfer", slen);
522  break;
524  ast_copy_string(subclass, "Connected line update", slen);
525  break;
527  ast_copy_string(subclass, "Redirect", slen);
528  break;
529  case AST_CONTROL_CC:
530  ast_copy_string(subclass, "CC", slen);
531  break;
533  ast_copy_string(subclass, "Media SSRC change", slen);
534  break;
536  ast_copy_string(subclass, "Read action", slen);
537  break;
538  case AST_CONTROL_AOC:
539  ast_copy_string(subclass, "AOC", slen);
540  break;
542  ast_copy_string(subclass, "Endof Q", slen);
543  break;
545  ast_copy_string(subclass, "Incomplete", slen);
546  break;
547  case AST_CONTROL_MCID:
548  ast_copy_string(subclass, "MCID", slen);
549  break;
551  ast_copy_string(subclass, "Update RTP peer", slen);
552  break;
554  ast_copy_string(subclass, "Private Cause Code", slen);
555  break;
557  ast_copy_string(subclass, "Masquerade notify", slen);
558  break;
560  ast_copy_string(subclass, "Stream topology request change", slen);
561  break;
563  ast_copy_string(subclass, "Stream topology changed", slen);
564  break;
566  ast_copy_string(subclass, "Stream topology source changed", slen);
567  break;
568  case -1:
569  ast_copy_string(subclass, "Stop generators", slen);
570  break;
571  default:
572  snprintf(subclass, slen, "Unknown control '%d'", f->subclass.integer);
573  }
574  break;
575  case AST_FRAME_NULL:
576  ast_copy_string(subclass, "N/A", slen);
577  break;
578  case AST_FRAME_IAX:
579  /* Should never happen */
580  snprintf(subclass, slen, "IAX Frametype %d", f->subclass.integer);
581  break;
583  /* Should never happen */
584  snprintf(subclass, slen, "Bridge Frametype %d", f->subclass.integer);
585  break;
587  /* Should never happen */
588  snprintf(subclass, slen, "Synchronous Bridge Frametype %d", f->subclass.integer);
589  break;
590  case AST_FRAME_TEXT:
591  ast_copy_string(subclass, "N/A", slen);
592  if (moreinfo) {
593  ast_copy_string(moreinfo, f->data.ptr, mlen);
594  }
595  break;
596  case AST_FRAME_IMAGE:
597  snprintf(subclass, slen, "Image format %s\n", ast_format_get_name(f->subclass.format));
598  break;
599  case AST_FRAME_HTML:
600  switch (f->subclass.integer) {
601  case AST_HTML_URL:
602  ast_copy_string(subclass, "URL", slen);
603  if (moreinfo) {
604  ast_copy_string(moreinfo, f->data.ptr, mlen);
605  }
606  break;
607  case AST_HTML_DATA:
608  ast_copy_string(subclass, "Data", slen);
609  break;
610  case AST_HTML_BEGIN:
611  ast_copy_string(subclass, "Begin", slen);
612  break;
613  case AST_HTML_END:
614  ast_copy_string(subclass, "End", slen);
615  break;
616  case AST_HTML_LDCOMPLETE:
617  ast_copy_string(subclass, "Load Complete", slen);
618  break;
619  case AST_HTML_NOSUPPORT:
620  ast_copy_string(subclass, "No Support", slen);
621  break;
622  case AST_HTML_LINKURL:
623  ast_copy_string(subclass, "Link URL", slen);
624  if (moreinfo) {
625  ast_copy_string(moreinfo, f->data.ptr, mlen);
626  }
627  break;
628  case AST_HTML_UNLINK:
629  ast_copy_string(subclass, "Unlink", slen);
630  break;
631  case AST_HTML_LINKREJECT:
632  ast_copy_string(subclass, "Link Reject", slen);
633  break;
634  default:
635  snprintf(subclass, slen, "Unknown HTML frame '%d'\n", f->subclass.integer);
636  break;
637  }
638  break;
639  case AST_FRAME_MODEM:
640  switch (f->subclass.integer) {
641  case AST_MODEM_T38:
642  ast_copy_string(subclass, "T.38", slen);
643  break;
644  case AST_MODEM_V150:
645  ast_copy_string(subclass, "V.150", slen);
646  break;
647  default:
648  snprintf(subclass, slen, "Unknown MODEM frame '%d'\n", f->subclass.integer);
649  break;
650  }
651  break;
652  case AST_FRAME_RTCP:
653  ast_copy_string(subclass, "RTCP", slen);
654  default:
655  ast_copy_string(subclass, "Unknown Subclass", slen);
656  break;
657  }
658 
659  return subclass;
660 }
661 
662 char *ast_frame_type2str(enum ast_frame_type frame_type, char *ftype, size_t len)
663 {
664  switch (frame_type) {
666  ast_copy_string(ftype, "DTMF Begin", len);
667  break;
668  case AST_FRAME_DTMF_END:
669  ast_copy_string(ftype, "DTMF End", len);
670  break;
671  case AST_FRAME_CONTROL:
672  ast_copy_string(ftype, "Control", len);
673  break;
674  case AST_FRAME_NULL:
675  ast_copy_string(ftype, "Null Frame", len);
676  break;
677  case AST_FRAME_IAX:
678  /* Should never happen */
679  ast_copy_string(ftype, "IAX Specific", len);
680  break;
682  /* Should never happen */
683  ast_copy_string(ftype, "Bridge Specific", len);
684  break;
686  /* Should never happen */
687  ast_copy_string(ftype, "Bridge Specific", len);
688  break;
689  case AST_FRAME_TEXT:
690  ast_copy_string(ftype, "Text", len);
691  break;
692  case AST_FRAME_TEXT_DATA:
693  ast_copy_string(ftype, "Text Data", len);
694  break;
695  case AST_FRAME_IMAGE:
696  ast_copy_string(ftype, "Image", len);
697  break;
698  case AST_FRAME_HTML:
699  ast_copy_string(ftype, "HTML", len);
700  break;
701  case AST_FRAME_MODEM:
702  ast_copy_string(ftype, "Modem", len);
703  break;
704  case AST_FRAME_VOICE:
705  ast_copy_string(ftype, "Voice", len);
706  break;
707  case AST_FRAME_VIDEO:
708  ast_copy_string(ftype, "Video", len);
709  break;
710  case AST_FRAME_RTCP:
711  ast_copy_string(ftype, "RTCP", len);
712  break;
713  default:
714  snprintf(ftype, len, "Unknown Frametype '%u'", frame_type);
715  break;
716  }
717 
718  return ftype;
719 }
720 
721 /*! Dump a frame for debugging purposes */
722 void ast_frame_dump(const char *name, struct ast_frame *f, char *prefix)
723 {
724  const char noname[] = "unknown";
725  char ftype[40] = "Unknown Frametype";
726  char cft[80];
727  char subclass[40] = "Unknown Subclass";
728  char csub[80];
729  char moreinfo[40] = "";
730  char cn[60];
731  char cp[40];
732  char cmn[40];
733 
734  if (!name) {
735  name = noname;
736  }
737 
738  if (!f) {
739  ast_verb(-1, "%s [ %s (NULL) ] [%s]\n",
740  term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
741  term_color(cft, "HANGUP", COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
742  term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
743  return;
744  }
745  /* XXX We should probably print one each of voice and video when the format changes XXX */
746  if (f->frametype == AST_FRAME_VOICE) {
747  return;
748  }
749  if (f->frametype == AST_FRAME_VIDEO) {
750  return;
751  }
752  if (f->frametype == AST_FRAME_RTCP) {
753  return;
754  }
755 
756  ast_frame_type2str(f->frametype, ftype, sizeof(ftype));
757  ast_frame_subclass2str(f, subclass, sizeof(subclass), moreinfo, sizeof(moreinfo));
758 
759  if (!ast_strlen_zero(moreinfo))
760  ast_verb(-1, "%s [ TYPE: %s (%u) SUBCLASS: %s (%d) '%s' ] [%s]\n",
761  term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
762  term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
763  f->frametype,
764  term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
765  f->subclass.integer,
766  term_color(cmn, moreinfo, COLOR_BRGREEN, COLOR_BLACK, sizeof(cmn)),
767  term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
768  else
769  ast_verb(-1, "%s [ TYPE: %s (%u) SUBCLASS: %s (%d) ] [%s]\n",
770  term_color(cp, prefix, COLOR_BRMAGENTA, COLOR_BLACK, sizeof(cp)),
771  term_color(cft, ftype, COLOR_BRRED, COLOR_BLACK, sizeof(cft)),
772  f->frametype,
773  term_color(csub, subclass, COLOR_BRCYAN, COLOR_BLACK, sizeof(csub)),
774  f->subclass.integer,
775  term_color(cn, name, COLOR_YELLOW, COLOR_BLACK, sizeof(cn)));
776 }
777 
778 int ast_frame_adjust_volume(struct ast_frame *f, int adjustment)
779 {
780  int count;
781  short *fdata = f->data.ptr;
782  short adjust_value = abs(adjustment);
783 
785  return -1;
786  }
787 
788  if (!adjustment) {
789  return 0;
790  }
791 
792  for (count = 0; count < f->samples; count++) {
793  if (adjustment > 0) {
794  ast_slinear_saturated_multiply(&fdata[count], &adjust_value);
795  } else if (adjustment < 0) {
796  ast_slinear_saturated_divide(&fdata[count], &adjust_value);
797  }
798  }
799 
800  return 0;
801 }
802 
803 int ast_frame_adjust_volume_float(struct ast_frame *f, float adjustment)
804 {
805  int count;
806  short *fdata = f->data.ptr;
807  float adjust_value = fabs(adjustment);
808 
810  return -1;
811  }
812 
813  if (!adjustment) {
814  return 0;
815  }
816 
817  for (count = 0; count < f->samples; count++) {
818  if (adjustment > 0) {
819  ast_slinear_saturated_multiply_float(&fdata[count], &adjust_value);
820  } else if (adjustment < 0) {
821  ast_slinear_saturated_divide_float(&fdata[count], &adjust_value);
822  }
823  }
824 
825  return 0;
826 }
827 
828 int ast_frame_slinear_sum(struct ast_frame *f1, struct ast_frame *f2)
829 {
830  int count;
831  short *data1, *data2;
832 
834  return -1;
835 
837  return -1;
838 
839  if (f1->samples != f2->samples)
840  return -1;
841 
842  for (count = 0, data1 = f1->data.ptr, data2 = f2->data.ptr;
843  count < f1->samples;
844  count++, data1++, data2++)
845  ast_slinear_saturated_add(data1, data2);
846 
847  return 0;
848 }
849 
850 int ast_frame_clear(struct ast_frame *frame)
851 {
852  struct ast_frame *next;
853 
854  for (next = AST_LIST_NEXT(frame, frame_list);
855  frame;
856  frame = next, next = frame ? AST_LIST_NEXT(frame, frame_list) : NULL) {
857  memset(frame->data.ptr, 0, frame->datalen);
858  }
859  return 0;
860 }
This is just so ast_frames, a list head struct for holding a list of ast_frame structures, is defined.
Definition: main/frame.c:71
void ast_swapcopy_samples(void *dst, const void *src, int samples)
Definition: main/frame.c:396
#define AST_HTML_LINKURL
void * __ast_calloc(size_t nmemb, size_t size, const char *file, int lineno, const char *func) attribute_malloc
Definition: astmm.c:1635
struct ast_frame * __ast_frisolate(struct ast_frame *fr, const char *file, int line, const char *func)
&#39;isolates&#39; a frame by duplicating non-malloc&#39;ed components (header, src, data). On return all compone...
Definition: main/frame.c:197
#define AST_MODEM_V150
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
void * ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size)
Retrieve thread storage.
void ast_frame_free(struct ast_frame *frame, int cache)
Requests a frame to be allocated.
Definition: main/frame.c:176
struct ast_frame * __ast_frdup(const struct ast_frame *f, const char *file, int line, const char *func)
Definition: main/frame.c:305
#define AST_HTML_NOSUPPORT
char * ast_frame_type2str(enum ast_frame_type frame_type, char *ftype, size_t len)
Copy the discription of a frame type into the provided string.
Definition: main/frame.c:662
#define ast_test_flag(p, flag)
Definition: utils.h:63
Support for translation of data formats. translate.c.
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define AST_HTML_LDCOMPLETE
Convenient Signal Processing routines.
#define COLOR_YELLOW
Definition: term.h:54
#define AST_MALLOCD_DATA
union ast_frame::@257 data
#define AST_HTML_LINKREJECT
#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
char * ast_frame_subclass2str(struct ast_frame *f, char *subclass, size_t slen, char *moreinfo, size_t mlen)
Copy the discription of a frame&#39;s subclass into the provided string.
Definition: main/frame.c:406
void ast_frame_dtor(struct ast_frame *f)
NULL-safe wrapper for ast_frfree, good for RAII_VAR.
Definition: main/frame.c:187
struct ast_frames list
Definition: main/frame.c:74
#define ast_copy_flags(dest, src, flagz)
Definition: utils.h:84
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
#define NULL
Definition: resample.c:96
Definitions to aid in the use of thread local storage.
void ast_frame_dump(const char *name, struct ast_frame *f, char *prefix)
Definition: main/frame.c:722
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:614
static void __frame_free(struct ast_frame *fr, int cache)
Definition: main/frame.c:122
#define ast_verb(level,...)
Definition: logger.h:455
#define COLOR_BRCYAN
Definition: term.h:60
#define AST_HTML_DATA
struct ast_frame_subclass subclass
Utility functions.
#define COLOR_BRRED
Definition: term.h:50
#define ao2_bump(obj)
Definition: astobj2.h:491
#define AST_HTML_UNLINK
#define AST_MALLOCD_HDR
enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
Compare two formats.
Definition: format.c:201
General Asterisk PBX channel definitions.
#define AST_FRIENDLY_OFFSET
Offset into a frame&#39;s data buffer.
const char * src
#define ast_opt_cache_media_frames
Definition: options.h:121
static int frames
Definition: parser.c:51
#define FRAME_CACHE_MAX_SIZE
Maximum ast_frame cache size.
Definition: main/frame.c:67
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:556
Asterisk internal frame definitions.
static force_inline void ast_slinear_saturated_add(short *input, short *value)
Definition: utils.h:365
#define COLOR_BRGREEN
Definition: term.h:52
static force_inline void ast_slinear_saturated_multiply(short *input, short *value)
Definition: utils.h:391
A set of macros to manage forward-linked lists.
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
AST_LIST_HEAD_NOLOCK(contactliststruct, contact)
int ast_frame_slinear_sum(struct ast_frame *f1, struct ast_frame *f2)
Sums two frames of audio samples.
Definition: main/frame.c:828
#define AST_HTML_BEGIN
int ast_format_cache_is_slinear(struct ast_format *format)
Determines if a format is one of the cached slin formats.
Definition: format_cache.c:542
static struct ast_frame * ast_frame_header_new(const char *file, int line, const char *func)
Definition: main/frame.c:81
static force_inline void ast_slinear_saturated_divide_float(short *input, float *value)
Definition: utils.h:422
char * term_color(char *outbuf, const char *inbuf, int fgcolor, int bgcolor, int maxout)
Colorize a specified string by adding terminal color codes.
Definition: term.c:184
#define COLOR_BRMAGENTA
Definition: term.h:58
ast_frame_type
Frame types.
#define COLOR_BLACK
Definition: term.h:47
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
frame_type
Definition: codec_builtin.c:44
#define ast_strlen_zero(a)
Definition: muted.c:73
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:710
static const char name[]
Definition: cdr_mysql.c:74
#define ast_free(a)
Definition: astmm.h:182
#define AST_FLAGS_ALL
Definition: utils.h:196
static force_inline void ast_slinear_saturated_divide(short *input, short *value)
Definition: utils.h:417
Prototypes for public functions only of internal interest,.
#define AST_HTML_URL
#define AST_HTML_END
struct timeval delivery
struct ao2_container * cache
Definition: pbx_realtime.c:77
struct ast_frame ast_null_frame
Definition: main/frame.c:79
#define AST_THREADSTORAGE_CUSTOM(a, b, c)
Define a thread storage variable, with custom initialization and cleanup.
int ast_frame_adjust_volume_float(struct ast_frame *f, float adjustment)
Adjusts the volume of the audio samples contained in a frame.
Definition: main/frame.c:803
FILE * out
Definition: utils/frame.c:33
#define abs(x)
Definition: f2c.h:195
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
Standard Command Line Interface.
static void frame_cache_cleanup(void *data)
Definition: main/frame.c:110
static force_inline void ast_slinear_saturated_multiply_float(short *input, float *value)
Definition: utils.h:404
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
struct ast_frame * next
#define ast_frfree(fr)
#define AST_MODEM_T38
Data structure associated with a single frame of data.
Handy terminal functions for vt* terms.
int ast_frame_adjust_volume(struct ast_frame *f, int adjustment)
Adjusts the volume of the audio samples contained in a frame.
Definition: main/frame.c:778
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
enum ast_frame_type frametype
#define AST_MALLOCD_SRC
struct ast_format * format
static struct ast_threadstorage frame_cache
Definition: main/frame.c:56
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
Definition: format_cache.c:41
struct ast_stream_topology * topology
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: main/frame.c:850
Media Format Cache API.
static char prefix[MAX_PREFIX]
Definition: http.c:141