Wed Jan 8 2020 09:49:51

Asterisk developer's documentation


slinfactory.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2005, Anthony Minessale II.
5  *
6  * Anthony Minessale <anthmct@yahoo.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 A machine to gather up arbitrary frames and convert them
22  * to raw slinear on demand.
23  *
24  * \author Anthony Minessale <anthmct@yahoo.com>
25  */
26 
27 /*** MODULEINFO
28  <support_level>core</support_level>
29  ***/
30 
31 #include "asterisk.h"
32 
33 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 389895 $")
34 
35 #include "asterisk/frame.h"
36 #include "asterisk/slinfactory.h"
37 #include "asterisk/translate.h"
38 
40 {
41  memset(sf, 0, sizeof(*sf));
42  sf->offset = sf->hold;
44 }
45 
46 int ast_slinfactory_init_rate(struct ast_slinfactory *sf, unsigned int sample_rate)
47 {
48  memset(sf, 0, sizeof(*sf));
49  sf->offset = sf->hold;
50  switch (sample_rate) {
51  case 8000:
53  break;
54  case 16000:
56  break;
57  default:
58  return -1;
59  }
60 
61  return 0;
62 }
63 
65 {
66  struct ast_frame *f;
67 
68  if (sf->trans) {
70  sf->trans = NULL;
71  }
72 
73  while ((f = AST_LIST_REMOVE_HEAD(&sf->queue, frame_list)))
74  ast_frfree(f);
75 }
76 
78 {
79  struct ast_frame *begin_frame = f, *duped_frame = NULL, *frame_ptr;
80  unsigned int x = 0;
81 
82  /* In some cases, we can be passed a frame which has no data in it, but
83  * which has a positive number of samples defined. Once such situation is
84  * when a jitter buffer is in use and the jitter buffer interpolates a frame.
85  * The frame it produces has data set to NULL, datalen set to 0, and samples
86  * set to either 160 or 240.
87  */
88  if (!f->data.ptr) {
89  return 0;
90  }
91 
92  if (f->subclass.codec != sf->output_format) {
93  if (sf->trans && f->subclass.codec != sf->format) {
95  sf->trans = NULL;
96  }
97 
98  if (!sf->trans) {
100  ast_log(LOG_WARNING, "Cannot build a path from %s to %s\n", ast_getformatname(f->subclass.codec),
102  return 0;
103  }
104  sf->format = f->subclass.codec;
105  }
106 
107  if (!(begin_frame = ast_translate(sf->trans, f, 0))) {
108  return 0;
109  }
110 
111  if (!(duped_frame = ast_frisolate(begin_frame))) {
112  return 0;
113  }
114 
115  if (duped_frame != begin_frame) {
116  ast_frfree(begin_frame);
117  }
118  } else {
119  if (sf->trans) {
121  sf->trans = NULL;
122  }
123  if (!(duped_frame = ast_frdup(f)))
124  return 0;
125  }
126 
127  AST_LIST_TRAVERSE(&sf->queue, frame_ptr, frame_list) {
128  x++;
129  }
130 
131  /* if the frame was translated, the translator may have returned multiple
132  frames, so process each of them
133  */
134  for (begin_frame = duped_frame; begin_frame; begin_frame = AST_LIST_NEXT(begin_frame, frame_list)) {
135  AST_LIST_INSERT_TAIL(&sf->queue, begin_frame, frame_list);
136  sf->size += begin_frame->samples;
137  }
138 
139  return x;
140 }
141 
142 int ast_slinfactory_read(struct ast_slinfactory *sf, short *buf, size_t samples)
143 {
144  struct ast_frame *frame_ptr;
145  unsigned int sofar = 0, ineed, remain;
146  short *frame_data, *offset = buf;
147 
148  while (sofar < samples) {
149  ineed = samples - sofar;
150 
151  if (sf->holdlen) {
152  if (sf->holdlen <= ineed) {
153  memcpy(offset, sf->offset, sf->holdlen * sizeof(*offset));
154  sofar += sf->holdlen;
155  offset += sf->holdlen;
156  sf->holdlen = 0;
157  sf->offset = sf->hold;
158  } else {
159  remain = sf->holdlen - ineed;
160  memcpy(offset, sf->offset, ineed * sizeof(*offset));
161  sofar += ineed;
162  sf->offset += ineed;
163  sf->holdlen = remain;
164  }
165  continue;
166  }
167 
168  if ((frame_ptr = AST_LIST_REMOVE_HEAD(&sf->queue, frame_list))) {
169  frame_data = frame_ptr->data.ptr;
170 
171  if (frame_ptr->samples <= ineed) {
172  memcpy(offset, frame_data, frame_ptr->samples * sizeof(*offset));
173  sofar += frame_ptr->samples;
174  offset += frame_ptr->samples;
175  } else {
176  remain = frame_ptr->samples - ineed;
177  memcpy(offset, frame_data, ineed * sizeof(*offset));
178  sofar += ineed;
179  frame_data += ineed;
180  if (remain > (AST_SLINFACTORY_MAX_HOLD - sf->holdlen)) {
181  remain = AST_SLINFACTORY_MAX_HOLD - sf->holdlen;
182  }
183  memcpy(sf->hold, frame_data, remain * sizeof(*offset));
184  sf->holdlen = remain;
185  }
186  ast_frfree(frame_ptr);
187  } else {
188  break;
189  }
190  }
191 
192  sf->size -= sofar;
193  return sofar;
194 }
195 
196 unsigned int ast_slinfactory_available(const struct ast_slinfactory *sf)
197 {
198  return sf->size;
199 }
200 
202 {
203  struct ast_frame *fr = NULL;
204 
205  if (sf->trans) {
207  sf->trans = NULL;
208  }
209 
210  while ((fr = AST_LIST_REMOVE_HEAD(&sf->queue, frame_list)))
211  ast_frfree(fr);
212 
213  sf->size = sf->holdlen = 0;
214  sf->offset = sf->hold;
215 
216  return;
217 }
union ast_frame_subclass subclass
Definition: frame.h:146
Asterisk main include file. File version handling, generic pbx functions.
unsigned int size
Definition: slinfactory.h:39
int offset
Definition: frame.h:156
void ast_slinfactory_flush(struct ast_slinfactory *sf)
Flush the contents of a slinfactory.
Definition: slinfactory.c:201
Support for translation of data formats. translate.c.
void * ptr
Definition: frame.h:160
#define LOG_WARNING
Definition: logger.h:144
short hold[AST_SLINFACTORY_MAX_HOLD]
Definition: slinfactory.h:36
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:438
int ast_slinfactory_feed(struct ast_slinfactory *sf, struct ast_frame *f)
Feed audio into a slinfactory.
Definition: slinfactory.c:77
struct ast_frame * ast_translate(struct ast_trans_pvt *tr, struct ast_frame *f, int consume)
translates one or more frames Apply an input frame into the translator and receive zero or one output...
Definition: translate.c:328
struct ast_frame * ast_frisolate(struct ast_frame *fr)
Makes a frame independent of any static storage.
Definition: frame.c:391
format_t codec
Definition: frame.h:137
struct ast_trans_pvt * trans
Definition: slinfactory.h:35
unsigned int ast_slinfactory_available(const struct ast_slinfactory *sf)
Retrieve number of samples currently in a slinfactory.
Definition: slinfactory.c:196
struct ast_trans_pvt * ast_translator_build_path(format_t dest, format_t source)
Builds a translator path Build a path (possibly NULL) from source to dest.
Definition: translate.c:282
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:818
#define AST_FORMAT_SLINEAR16
Definition: frame.h:272
void ast_slinfactory_destroy(struct ast_slinfactory *sf)
Destroy the contents of a slinfactory.
Definition: slinfactory.c:64
int ast_slinfactory_init_rate(struct ast_slinfactory *sf, unsigned int sample_rate)
Initialize a slinfactory.
Definition: slinfactory.c:46
char * ast_getformatname(format_t format)
Get the name of a format.
Definition: frame.c:578
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:716
short * offset
Definition: slinfactory.h:37
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
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
A machine to gather up arbitrary frames and convert them to raw slinear on demand.
format_t output_format
Definition: slinfactory.h:41
static struct ast_format f[]
Definition: format_g726.c:181
void ast_slinfactory_init(struct ast_slinfactory *sf)
Initialize a slinfactory.
Definition: slinfactory.c:39
#define AST_SLINFACTORY_MAX_HOLD
Definition: slinfactory.h:31
format_t format
Definition: slinfactory.h:40
#define AST_FORMAT_SLINEAR
Definition: frame.h:254
Data structure associated with a single frame of data.
Definition: frame.h:142
int ast_slinfactory_read(struct ast_slinfactory *sf, short *buf, size_t samples)
Read samples from a slinfactory.
Definition: slinfactory.c:142
#define ast_frfree(fr)
Definition: frame.h:583
union ast_frame::@172 data
struct ast_frame * ast_frdup(const struct ast_frame *fr)
Copies a frame.
Definition: frame.c:474
void ast_translator_free_path(struct ast_trans_pvt *tr)
Frees a translator path Frees the given translator path structure.
Definition: translate.c:272
#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