Asterisk - The Open Source Telephony Project  GIT-master-b91fb3c
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 #include "asterisk/frame.h"
34 #include "asterisk/format_cache.h"
35 #include "asterisk/slinfactory.h"
36 #include "asterisk/translate.h"
37 #include "asterisk/astobj2.h"
38 
40 {
41  memset(sf, 0, sizeof(*sf));
42  sf->offset = sf->hold;
44 }
45 
47 {
48  memset(sf, 0, sizeof(*sf));
49  sf->offset = sf->hold;
50  if (!ast_format_cache_is_slinear(slin_out)) {
51  return -1;
52  }
53  sf->output_format = ao2_bump(slin_out);
54 
55  return 0;
56 }
57 
59 {
60  struct ast_frame *f;
61 
62  if (sf->trans) {
64  sf->trans = NULL;
65  }
66 
67  while ((f = AST_LIST_REMOVE_HEAD(&sf->queue, frame_list))) {
68  ast_frfree(f);
69  }
70 
72  sf->output_format = NULL;
73  ao2_cleanup(sf->format);
74  sf->format = NULL;
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 
95  sf->trans = NULL;
96  }
97 
98  if (!sf->trans) {
100  ast_log(LOG_WARNING, "Cannot build a path from %s (%u)to %s (%u)\n",
105  return 0;
106  }
108  }
109 
110  if (!(begin_frame = ast_translate(sf->trans, f, 0))) {
111  return 0;
112  }
113 
114  if (!(duped_frame = ast_frisolate(begin_frame))) {
115  return 0;
116  }
117 
118  if (duped_frame != begin_frame) {
119  ast_frfree(begin_frame);
120  }
121  } else {
122  if (sf->trans) {
124  sf->trans = NULL;
125  }
126  if (!(duped_frame = ast_frdup(f)))
127  return 0;
128  }
129 
130  AST_LIST_TRAVERSE(&sf->queue, frame_ptr, frame_list) {
131  x++;
132  }
133 
134  /* if the frame was translated, the translator may have returned multiple
135  frames, so process each of them
136  */
137  for (begin_frame = duped_frame; begin_frame; begin_frame = AST_LIST_NEXT(begin_frame, frame_list)) {
138  AST_LIST_INSERT_TAIL(&sf->queue, begin_frame, frame_list);
139  sf->size += begin_frame->samples;
140  }
141 
142  return x;
143 }
144 
145 int ast_slinfactory_read(struct ast_slinfactory *sf, short *buf, size_t samples)
146 {
147  struct ast_frame *frame_ptr;
148  unsigned int sofar = 0, ineed, remain;
149  short *frame_data, *offset = buf;
150 
151  while (sofar < samples) {
152  ineed = samples - sofar;
153 
154  if (sf->holdlen) {
155  if (sf->holdlen <= ineed) {
156  memcpy(offset, sf->offset, sf->holdlen * sizeof(*offset));
157  sofar += sf->holdlen;
158  offset += sf->holdlen;
159  sf->holdlen = 0;
160  sf->offset = sf->hold;
161  } else {
162  remain = sf->holdlen - ineed;
163  memcpy(offset, sf->offset, ineed * sizeof(*offset));
164  sofar += ineed;
165  sf->offset += ineed;
166  sf->holdlen = remain;
167  }
168  continue;
169  }
170 
171  if ((frame_ptr = AST_LIST_REMOVE_HEAD(&sf->queue, frame_list))) {
172  frame_data = frame_ptr->data.ptr;
173 
174  if (frame_ptr->samples <= ineed) {
175  memcpy(offset, frame_data, frame_ptr->samples * sizeof(*offset));
176  sofar += frame_ptr->samples;
177  offset += frame_ptr->samples;
178  } else {
179  remain = frame_ptr->samples - ineed;
180  memcpy(offset, frame_data, ineed * sizeof(*offset));
181  sofar += ineed;
182  frame_data += ineed;
183  if (remain > (AST_SLINFACTORY_MAX_HOLD - sf->holdlen)) {
184  remain = AST_SLINFACTORY_MAX_HOLD - sf->holdlen;
185  }
186  memcpy(sf->hold, frame_data, remain * sizeof(*offset));
187  sf->holdlen = remain;
188  }
189  ast_frfree(frame_ptr);
190  } else {
191  break;
192  }
193  }
194 
195  sf->size -= sofar;
196  return sofar;
197 }
198 
199 unsigned int ast_slinfactory_available(const struct ast_slinfactory *sf)
200 {
201  return sf->size;
202 }
203 
205 {
206  struct ast_frame *fr = NULL;
207 
208  if (sf->trans) {
210  sf->trans = NULL;
211  }
212 
213  while ((fr = AST_LIST_REMOVE_HEAD(&sf->queue, frame_list)))
214  ast_frfree(fr);
215 
216  sf->size = sf->holdlen = 0;
217  sf->offset = sf->hold;
218 
219  return;
220 }
#define ast_frdup(fr)
Copies a frame.
void ast_slinfactory_flush(struct ast_slinfactory *sf)
Flush the contents of a slinfactory.
Definition: slinfactory.c:204
Asterisk main include file. File version handling, generic pbx functions.
unsigned int size
Definition: slinfactory.h:41
Support for translation of data formats. translate.c.
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define LOG_WARNING
Definition: logger.h:274
short hold[AST_SLINFACTORY_MAX_HOLD]
Definition: slinfactory.h:38
union ast_frame::@257 data
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:438
Definition of a media format.
Definition: format.c:43
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:559
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
#define NULL
Definition: resample.c:96
struct ast_trans_pvt * trans
Definition: slinfactory.h:37
struct ast_format * format
Definition: slinfactory.h:42
int ast_slinfactory_read(struct ast_slinfactory *sf, short *buf, size_t samples)
Read samples from a slinfactory.
Definition: slinfactory.c:145
struct ast_frame_subclass subclass
#define ao2_bump(obj)
Definition: astobj2.h:491
#define ast_log
Definition: astobj2.c:42
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
struct ast_trans_pvt * ast_translator_build_path(struct ast_format *dest, struct ast_format *source)
Builds a translator path Build a path (possibly NULL) from source to dest.
Definition: translate.c:479
int ast_slinfactory_init_with_format(struct ast_slinfactory *sf, struct ast_format *slin_out)
Initialize a slinfactory.
Definition: slinfactory.c:46
Asterisk internal frame definitions.
void ast_slinfactory_destroy(struct ast_slinfactory *sf)
Destroy the contents of a slinfactory.
Definition: slinfactory.c:58
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
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
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
short * offset
Definition: slinfactory.h:39
void ast_slinfactory_init(struct ast_slinfactory *sf)
Initialize a slinfactory.
Definition: slinfactory.c:39
#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.
#define AST_SLINFACTORY_MAX_HOLD
Definition: slinfactory.h:33
#define ast_frisolate(fr)
Makes a frame independent of any static storage.
int ast_slinfactory_feed(struct ast_slinfactory *sf, struct ast_frame *f)
Feed audio into a slinfactory.
Definition: slinfactory.c:77
#define ao2_replace(dst, src)
Definition: astobj2.h:517
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
#define ast_frfree(fr)
Data structure associated with a single frame of data.
unsigned int ast_slinfactory_available(const struct ast_slinfactory *sf)
Retrieve number of samples currently in a slinfactory.
Definition: slinfactory.c:199
struct ast_format * format
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
Definition: format_cache.c:41
unsigned int ast_format_get_codec_id(const struct ast_format *format)
Get the codec identifier associated with a format.
Definition: format.c:329
void ast_translator_free_path(struct ast_trans_pvt *tr)
Frees a translator path Frees the given translator path structure.
Definition: translate.c:469
Media Format Cache API.
struct ast_format * output_format
Definition: slinfactory.h:43