Asterisk - The Open Source Telephony Project  18.5.0
format.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2014, Digium, Inc.
5  *
6  * Joshua Colp <[email protected]>
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 Media Format API
22  *
23  * \author Joshua Colp <[email protected]>
24  */
25 
26 /*** MODULEINFO
27  <support_level>core</support_level>
28  ***/
29 
30 #include "asterisk.h"
31 
32 #include "asterisk/logger.h"
33 #include "asterisk/codec.h"
34 #include "asterisk/format.h"
35 #include "asterisk/astobj2.h"
36 #include "asterisk/strings.h"
37 #include "asterisk/module.h"
38 
39 /*! \brief Number of buckets to use for format interfaces (should be prime for performance reasons) */
40 #define FORMAT_INTERFACE_BUCKETS 53
41 
42 /*! \brief Definition of a media format */
43 struct ast_format {
44  /*! Name of the format */
45  const char *name;
46  /*! \brief Pointer to the codec in use for this format */
47  struct ast_codec *codec;
48  /*! \brief Attribute specific data, implementation specific */
50  /*! \brief Pointer to the optional format interface */
52  /*! \brief The number if audio channels used, if more than one an interleaved format is required */
53  unsigned int channel_count;
54 };
55 
56 /*! \brief Structure used when registering a format interface */
58  /*! \brief Pointer to the format interface itself */
60  /*! \brief Name of the codec the interface is for */
61  char codec[0];
62 };
63 
64 /*! \brief Container for registered format interfaces */
65 static struct ao2_container *interfaces;
66 
69 
70 /*! \brief Function called when the process is shutting down */
71 static void format_shutdown(void)
72 {
73  ao2_cleanup(interfaces);
74  interfaces = NULL;
75 }
76 
77 int ast_format_init(void)
78 {
80  FORMAT_INTERFACE_BUCKETS, format_interface_hash_fn, NULL, format_interface_cmp_fn);
81  if (!interfaces) {
82  return -1;
83  }
84 
86 
87  return 0;
88 }
89 
91 {
92  SCOPED_AO2WRLOCK(lock, interfaces);
94 
95  if (!interface->format_clone || !interface->format_destroy) {
96  ast_log(LOG_ERROR, "Format interface for codec '%s' does not implement required callbacks\n", codec);
97  return -1;
98  }
99 
100  format_interface = ao2_find(interfaces, codec, OBJ_SEARCH_KEY | OBJ_NOLOCK);
101  if (format_interface) {
102  ast_log(LOG_ERROR, "A format interface is already present for codec '%s'\n", codec);
103  ao2_ref(format_interface, -1);
104  return -1;
105  }
106 
107  format_interface = ao2_alloc_options(sizeof(*format_interface) + strlen(codec) + 1,
109  if (!format_interface) {
110  return -1;
111  }
112  format_interface->interface = interface;
113  strcpy(format_interface->codec, codec); /* Safe */
114 
115  /* Once registered a format interface cannot be unregistered. */
117  ao2_link_flags(interfaces, format_interface, OBJ_NOLOCK);
118  ao2_ref(format_interface, -1);
119 
120  ast_verb(2, "Registered format interface for codec '%s'\n", codec);
121 
122  return 0;
123 }
124 
126 {
127  return format->attribute_data;
128 }
129 
131 {
132  format->attribute_data = attribute_data;
133 }
134 
135 unsigned int ast_format_get_channel_count(const struct ast_format *format)
136 {
137  return format->channel_count;
138 }
139 
141 {
142  format->channel_count = channel_count;
143 }
144 
145 /*! \brief Destructor for media formats */
146 static void format_destroy(void *obj)
147 {
148  struct ast_format *format = obj;
149 
150  if (format->interface) {
151  format->interface->format_destroy(format);
152  }
153 
154  ao2_cleanup(format->codec);
155 }
156 
157 struct ast_format *ast_format_create_named(const char *format_name, struct ast_codec *codec)
158 {
159  struct ast_format *format;
161 
162  format = ao2_t_alloc_options(sizeof(*format), format_destroy,
164  if (!format) {
165  return NULL;
166  }
167  format->name = format_name;
168  format->codec = ao2_bump(codec);
169  format->channel_count = 1;
170 
171  format_interface = ao2_find(interfaces, codec->name, OBJ_SEARCH_KEY);
172  if (format_interface) {
173  format->interface = format_interface->interface;
174  ao2_ref(format_interface, -1);
175  }
176 
177  return format;
178 }
179 
181 {
182  struct ast_format *cloned = ast_format_create_named(format->name, format->codec);
183 
184  if (!cloned) {
185  return NULL;
186  }
187 
188  if (cloned->interface && cloned->interface->format_clone(format, cloned)) {
189  ao2_ref(cloned, -1);
190  return NULL;
191  }
192 
193  return cloned;
194 }
195 
197 {
198  return ast_format_create_named(codec->name, codec);
199 }
200 
201 enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
202 {
203  const struct ast_format_interface *interface;
204 
205  if (format1 == NULL || format2 == NULL) {
207  }
208 
209  if (format1 == format2) {
210  return AST_FORMAT_CMP_EQUAL;
211  }
212 
213  if (format1->codec != format2->codec) {
215  }
216 
217  interface = format1->interface ? format1->interface : format2->interface;
218 
219  if (interface && interface->format_cmp) {
220  return interface->format_cmp(format1, format2);
221  }
222 
223  return AST_FORMAT_CMP_EQUAL;
224 }
225 
226 struct ast_format *ast_format_joint(const struct ast_format *format1, const struct ast_format *format2)
227 {
228  const struct ast_format_interface *interface;
229 
230  if (format1->codec != format2->codec) {
231  return NULL;
232  }
233 
234  /* If the two formats are the same structure OR if the codec is the same and no attributes
235  * exist we can immediately return a format with reference count bumped up, since they are
236  * the same.
237  */
238  if ((ast_format_cmp(format1, format2) == AST_FORMAT_CMP_EQUAL && !format1->attribute_data && !format2->attribute_data)) {
239  return ao2_bump((struct ast_format*)format1);
240  }
241 
242  interface = format1->interface ? format1->interface : format2->interface;
243 
244  /* If there is attribute data on either there has to be an interface */
245  return interface->format_get_joint(format1, format2);
246 }
247 
248 struct ast_format *ast_format_attribute_set(const struct ast_format *format, const char *name, const char *value)
249 {
250  const struct ast_format_interface *interface = format->interface;
251 
252  if (!interface) {
253  struct format_interface *format_interface = ao2_find(interfaces, format->codec->name, OBJ_SEARCH_KEY);
254  if (format_interface) {
255  interface = format_interface->interface;
256  ao2_ref(format_interface, -1);
257  }
258  }
259 
260  if (!interface || !interface->format_attribute_set) {
261  return ao2_bump((struct ast_format*)format);
262  }
263 
264  return interface->format_attribute_set(format, name, value);
265 }
266 
267 const void *ast_format_attribute_get(const struct ast_format *format, const char *name)
268 {
269  const struct ast_format_interface *interface = format->interface;
270 
271  if (!interface) {
272  struct format_interface *format_interface = ao2_find(interfaces, format->codec->name, OBJ_SEARCH_KEY);
273  if (format_interface) {
274  interface = format_interface->interface;
275  ao2_ref(format_interface, -1);
276  }
277  }
278 
279  if (!interface || !interface->format_attribute_get) {
280  return NULL;
281  }
282 
283  return interface->format_attribute_get(format, name);
284 }
285 
286 struct ast_format *ast_format_parse_sdp_fmtp(const struct ast_format *format, const char *attributes)
287 {
288  const struct ast_format_interface *interface = format->interface;
289 
290  if (!interface) {
291  struct format_interface *format_interface = ao2_find(interfaces, format->codec->name, OBJ_SEARCH_KEY);
292  if (format_interface) {
293  interface = format_interface->interface;
294  ao2_ref(format_interface, -1);
295  }
296  }
297 
298  if (!interface || !interface->format_parse_sdp_fmtp) {
299  return ao2_bump((struct ast_format*)format);
300  }
301 
302  return interface->format_parse_sdp_fmtp(format, attributes);
303 }
304 
305 void ast_format_generate_sdp_fmtp(const struct ast_format *format, unsigned int payload, struct ast_str **str)
306 {
307  const struct ast_format_interface *interface = format->interface;
308 
309  if (!interface) {
310  struct format_interface *format_interface = ao2_find(interfaces, format->codec->name, OBJ_SEARCH_KEY);
311  if (format_interface) {
312  interface = format_interface->interface;
313  ao2_ref(format_interface, -1);
314  }
315  }
316 
317  if (!interface || !interface->format_generate_sdp_fmtp) {
318  return;
319  }
320 
321  interface->format_generate_sdp_fmtp(format, payload, str);
322 }
323 
325 {
326  return ao2_bump(format->codec);
327 }
328 
329 unsigned int ast_format_get_codec_id(const struct ast_format *format)
330 {
331  return format->codec->id;
332 }
333 
334 const char *ast_format_get_name(const struct ast_format *format)
335 {
336  return format->name;
337 }
338 
339 const char *ast_format_get_codec_name(const struct ast_format *format)
340 {
341  return format->codec->name;
342 }
343 
345 {
346  return format->codec->smooth;
347 }
348 
350 {
351  return format->codec->smoother_flags;
352 }
353 
355 {
356  return format->codec->type;
357 }
358 
359 unsigned int ast_format_get_default_ms(const struct ast_format *format)
360 {
361  return format->codec->default_ms;
362 }
363 
364 unsigned int ast_format_get_minimum_ms(const struct ast_format *format)
365 {
366  return format->codec->minimum_ms;
367 }
368 
369 unsigned int ast_format_get_maximum_ms(const struct ast_format *format)
370 {
371  return format->codec->maximum_ms;
372 }
373 
374 unsigned int ast_format_get_minimum_bytes(const struct ast_format *format)
375 {
376  return format->codec->minimum_bytes;
377 }
378 
379 unsigned int ast_format_get_sample_rate(const struct ast_format *format)
380 {
381  return format->codec->sample_rate ?: 8000;
382 }
383 
384 unsigned int ast_format_determine_length(const struct ast_format *format, unsigned int samples)
385 {
386  return ast_codec_determine_length(format->codec, samples);
387 }
enum ast_media_type ast_format_get_type(const struct ast_format *format)
Get the media type of a format.
Definition: format.c:354
unsigned int smoother_flags
Flags to be passed to the smoother.
Definition: codec.h:80
int ast_format_init(void)
Initialize media format support.
Definition: format.c:77
unsigned int minimum_bytes
Length in bytes of the data payload of a minimum_ms frame.
Definition: codec.h:60
const char * name
Name for this codec.
Definition: codec.h:46
Asterisk main include file. File version handling, generic pbx functions.
void ast_format_generate_sdp_fmtp(const struct ast_format *format, unsigned int payload, struct ast_str **str)
This function is used to produce an fmtp SDP line for an Asterisk format. The attributes present on t...
Definition: format.c:305
const void * ast_format_attribute_get(const struct ast_format *format, const char *name)
Definition: format.c:267
const char * name
Definition: format.c:45
Optional format interface to extend format operations.
Definition: format.h:44
String manipulation functions.
unsigned int ast_format_get_default_ms(const struct ast_format *format)
Get the default framing size (in milliseconds) for a format.
Definition: format.c:359
#define AO2_STRING_FIELD_HASH_FN(stype, field)
Creates a hash function for a structure string field.
Definition: astobj2.h:2055
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
int ast_format_get_smoother_flags(const struct ast_format *format)
Get smoother flags for this format.
Definition: format.c:349
unsigned int id
Internal unique identifier for this codec, set at registration time (starts at 1) ...
Definition: codec.h:44
struct ast_format * ast_format_create(struct ast_codec *codec)
Create a new media format.
Definition: format.c:196
const struct ast_format_interface * interface
Pointer to the format interface itself.
Definition: format.c:59
int(*const format_clone)(const struct ast_format *src, struct ast_format *dst)
Callback for when the format is cloned, used to clone attributes.
Definition: format.h:61
Assume that the ao2_container is already locked.
Definition: astobj2.h:1067
if(!yyg->yy_init)
Definition: ast_expr2f.c:868
unsigned int ast_format_get_sample_rate(const struct ast_format *format)
Get the sample rate of a media format.
Definition: format.c:379
Codec API.
Definition of a media format.
Definition: format.c:43
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:406
#define ao2_link_flags(container, obj, flags)
Definition: astobj2.h:1572
#define ao2_t_alloc_options(data_size, destructor_fn, options, debug_msg)
Allocate and initialize an object.
Definition: astobj2.h:404
const char * str
Definition: app_jack.c:147
#define NULL
Definition: resample.c:96
struct ast_codec * ast_format_get_codec(const struct ast_format *format)
Get the codec associated with a format.
Definition: format.c:324
int value
Definition: syslog.c:37
char codec[0]
Name of the codec the interface is for.
Definition: format.c:61
#define ast_verb(level,...)
Definition: logger.h:463
unsigned int default_ms
Default length of media carried (in milliseconds) in a frame.
Definition: codec.h:58
void ast_format_set_channel_count(struct ast_format *format, unsigned int channel_count)
Set the channel count on a format.
Definition: format.c:140
#define SCOPED_AO2WRLOCK(varname, obj)
scoped lock specialization for ao2 write locks.
Definition: lock.h:612
Media Format API.
static struct ao2_container * interfaces
Container for registered format interfaces.
Definition: format.c:65
const char * ast_format_get_codec_name(const struct ast_format *format)
Get the codec name associated with a format.
Definition: format.c:339
unsigned int maximum_ms
Maximum length of media that can be carried (in milliseconds) in a frame.
Definition: codec.h:56
#define ao2_bump(obj)
Definition: astobj2.h:491
#define ast_log
Definition: astobj2.c:42
unsigned int ast_format_get_maximum_ms(const struct ast_format *format)
Get the maximum amount of media carried in this format.
Definition: format.c:369
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19
static void format_destroy(void *obj)
Destructor for media formats.
Definition: format.c:146
ast_mutex_t lock
Definition: app_meetme.c:1091
void(*const format_destroy)(struct ast_format *format)
Callback for when the format is destroyed, used to release attribute resources.
Definition: format.h:50
unsigned int ast_format_get_channel_count(const struct ast_format *format)
Get the channel count on a format.
Definition: format.c:135
#define ao2_ref(o, delta)
Definition: astobj2.h:464
ast_format_cmp_res
Format comparison results.
Definition: format.h:34
void * attribute_data
Attribute specific data, implementation specific.
Definition: format.c:49
unsigned int ast_format_get_minimum_bytes(const struct ast_format *format)
Get the minimum number of bytes expected in a frame for this format.
Definition: format.c:374
unsigned int ast_format_determine_length(const struct ast_format *format, unsigned int samples)
Get the length (in milliseconds) for the format with a given number of samples.
Definition: format.c:384
#define FORMAT_INTERFACE_BUCKETS
Number of buckets to use for format interfaces (should be prime for performance reasons) ...
Definition: format.c:40
#define LOG_ERROR
Definition: logger.h:285
int ast_format_can_be_smoothed(const struct ast_format *format)
Get whether or not the format can be smoothed.
Definition: format.c:344
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Definition: astobj2.h:1310
const char * description
Brief description.
Definition: codec.h:48
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
#define ast_module_shutdown_ref(mod)
Prevent unload of the module before shutdown.
Definition: module.h:464
struct ast_codec * codec
Pointer to the codec in use for this format.
Definition: format.c:47
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
void * ast_format_get_attribute_data(const struct ast_format *format)
Get the attribute data on a format.
Definition: format.c:125
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
unsigned int sample_rate
Sample rate (number of samples carried in a second)
Definition: codec.h:52
void ast_format_set_attribute_data(struct ast_format *format, void *attribute_data)
Set the attribute data on a format.
Definition: format.c:130
Support for logging to various files, console and syslog Configuration in file logger.conf.
static void format_shutdown(void)
Function called when the process is shutting down.
Definition: format.c:71
Structure used when registering a format interface.
Definition: format.c:57
const struct ast_format_interface * interface
Pointer to the optional format interface.
Definition: format.c:51
int __ast_format_interface_register(const char *codec, const struct ast_format_interface *interface, struct ast_module *mod)
Register a format interface for use with the provided codec.
Definition: format.c:90
#define AO2_STRING_FIELD_CMP_FN(stype, field)
Creates a compare function for a structure string field.
Definition: astobj2.h:2071
unsigned int channel_count
The number if audio channels used, if more than one an interleaved format is required.
Definition: format.c:53
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct ast_format * ast_format_clone(const struct ast_format *format)
Clone an existing media format so it can be modified.
Definition: format.c:180
struct ast_format * ast_format_joint(const struct ast_format *format1, const struct ast_format *format2)
Get a common joint capability between two formats.
Definition: format.c:226
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
struct ast_format * ast_format_parse_sdp_fmtp(const struct ast_format *format, const char *attributes)
This function is used to have a media format aware module parse and interpret SDP attribute informati...
Definition: format.c:286
enum ast_media_type type
Type of media this codec contains.
Definition: codec.h:50
unsigned int smooth
Whether the media can be smoothed or not.
Definition: codec.h:78
unsigned int ast_format_get_minimum_ms(const struct ast_format *format)
Get the minimum amount of media carried in this format.
Definition: format.c:364
ast_media_type
Types of media.
Definition: codec.h:30
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
Generic container type.
Asterisk module definitions.
static snd_pcm_format_t format
Definition: chan_alsa.c:102
struct ast_format * ast_format_attribute_set(const struct ast_format *format, const char *name, const char *value)
Set an attribute on a format to a specific value.
Definition: format.c:248
unsigned int minimum_ms
Minimum length of media that can be carried (in milliseconds) in a frame.
Definition: codec.h:54
Represents a media codec within Asterisk.
Definition: codec.h:42
struct ast_format * ast_format_create_named(const char *format_name, struct ast_codec *codec)
Create a new media format with a specific name.
Definition: format.c:157
unsigned int ast_codec_determine_length(const struct ast_codec *codec, unsigned int samples)
Get the length of media (in milliseconds) given a number of samples.
Definition: codec.c:407
unsigned int ast_format_get_codec_id(const struct ast_format *format)
Get the codec identifier associated with a format.
Definition: format.c:329