Asterisk - The Open Source Telephony Project GIT-master-7e7a603
codec.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 <jcolp@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 Codecs API
22 *
23 * \author Joshua Colp <jcolp@digium.com>
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/frame.h"
36#include "asterisk/astobj2.h"
37#include "asterisk/strings.h"
38#include "asterisk/module.h"
39#include "asterisk/cli.h"
40
41/*! \brief Number of buckets to use for codecs (should be prime for performance reasons) */
42#define CODEC_BUCKETS 53
43
44/*! \brief Current identifier value for newly registered codec */
45static int codec_id = 1;
46
47/*! \brief Registered codecs */
48static struct ao2_container *codecs;
49
50/*!
51 * \internal
52 * \brief Internal codec structure
53 *
54 * External codecs won't know about the format_name field so the public
55 * ast_codec structure has to leave it out. This structure will be used
56 * for the internal codecs.
57 *
58 */
60 /*! \brief Public codec structure. Must remain first. */
62 /*! \brief A format name for a default sane format using this codec */
63 const char *format_name;
64};
65
66/*!
67 * \internal
68 * \brief Internal function for registration with format name
69 *
70 * This function is only used by codec.c and codec_builtin.c and
71 * will be removed in Asterisk 14
72 */
73int __ast_codec_register_with_format(struct ast_codec *codec, const char *format_name,
74 struct ast_module *mod);
75
77
78static int codec_cmp(void *obj, void *arg, int flags)
79{
80 const struct ast_codec *left = obj;
81 const struct ast_codec *right = arg;
82 const char *right_key = arg;
83 int cmp;
84
85 switch (flags & OBJ_SEARCH_MASK) {
87 right_key = right->name;
88 cmp = strcmp(left->name, right_key);
89
90 if (right->type != AST_MEDIA_TYPE_UNKNOWN) {
91 cmp |= (right->type != left->type);
92 }
93
94 /* BUGBUG: this will allow a match on a codec by name only.
95 * This is particularly useful when executed by the CLI; if
96 * that is not needed in translate.c, this can be removed.
97 */
98 if (right->sample_rate) {
99 cmp |= (right->sample_rate != left->sample_rate);
100 }
101 break;
102 case OBJ_SEARCH_KEY:
103 cmp = strcmp(left->name, right_key);
104 break;
106 cmp = strncmp(left->name, right_key, strlen(right_key));
107 break;
108 default:
109 ast_assert(0);
110 cmp = 0;
111 break;
112 }
113 if (cmp) {
114 return 0;
115 }
116
117 return CMP_MATCH;
118}
119
120static char *show_codecs(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
121{
122 struct ao2_iterator i;
123 struct internal_ast_codec *codec;
124
125 switch (cmd) {
126 case CLI_INIT:
127 e->command = "core show codecs [audio|video|image|text]";
128 e->usage =
129 "Usage: core show codecs [audio|video|image|text]\n"
130 " Displays codec mapping\n";
131 return NULL;
132 case CLI_GENERATE:
133 return NULL;
134 }
135
136 if ((a->argc < 3) || (a->argc > 4)) {
137 return CLI_SHOWUSAGE;
138 }
139
140 if (!ast_opt_dont_warn) {
141 ast_cli(a->fd, "Disclaimer: this command is for informational purposes only.\n"
142 "\tIt does not indicate anything about your configuration.\n");
143 }
144
145 ast_cli(a->fd, "%8s %-5s %-12s %-16s %7s %s\n","ID","TYPE","NAME","FORMAT","QUALITY", "DESCRIPTION");
146 ast_cli(a->fd, "------------------------------------------------------------------------------------------------\n");
147
150
151 for (; (codec = ao2_iterator_next(&i)); ao2_ref(codec, -1)) {
152 if (a->argc == 4) {
153 if (!strcasecmp(a->argv[3], "audio")) {
154 if (codec->external.type != AST_MEDIA_TYPE_AUDIO) {
155 continue;
156 }
157 } else if (!strcasecmp(a->argv[3], "video")) {
158 if (codec->external.type != AST_MEDIA_TYPE_VIDEO) {
159 continue;
160 }
161 } else if (!strcasecmp(a->argv[3], "image")) {
162 if (codec->external.type != AST_MEDIA_TYPE_IMAGE) {
163 continue;
164 }
165 } else if (!strcasecmp(a->argv[3], "text")) {
166 if (codec->external.type != AST_MEDIA_TYPE_TEXT) {
167 continue;
168 }
169 } else {
170 continue;
171 }
172 }
173
174 ast_cli(a->fd, "%8u %-5s %-12s %-16s %7d (%s)\n",
175 codec->external.id,
177 codec->external.name,
178 S_OR(codec->format_name, "no cached format"),
179 codec->external.quality,
180 codec->external.description);
181 }
182
185
186 return CLI_SUCCESS;
187}
188
189/*! \brief Callback function for getting a codec based on unique identifier */
190static int codec_id_cmp(void *obj, void *arg, int flags)
191{
192 struct ast_codec *codec = obj;
193 int *id = arg;
194
195 return (codec->id == *id) ? CMP_MATCH | CMP_STOP : 0;
196}
197
198static char *show_codec(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
199{
200 int type_punned_codec;
201 struct internal_ast_codec *codec;
202
203 switch (cmd) {
204 case CLI_INIT:
205 e->command = "core show codec";
206 e->usage =
207 "Usage: core show codec <number>\n"
208 " Displays codec mapping\n";
209 return NULL;
210 case CLI_GENERATE:
211 return NULL;
212 }
213
214 if (a->argc != 4) {
215 return CLI_SHOWUSAGE;
216 }
217
218 if (sscanf(a->argv[3], "%30d", &type_punned_codec) != 1) {
219 return CLI_SHOWUSAGE;
220 }
221
222 codec = ao2_callback(codecs, 0, codec_id_cmp, &type_punned_codec);
223 if (!codec) {
224 ast_cli(a->fd, "Codec %d not found\n", type_punned_codec);
225 return CLI_SUCCESS;
226 }
227
228 ast_cli(a->fd, "%11u %s (%s)\n", (unsigned int) codec->external.id, codec->external.description,
229 S_OR(codec->format_name, "no format"));
230
231 ao2_ref(codec, -1);
232
233 return CLI_SUCCESS;
234}
235
236/* Builtin Asterisk CLI-commands for debugging */
237static struct ast_cli_entry codec_cli[] = {
238 AST_CLI_DEFINE(show_codecs, "Displays a list of registered codecs"),
239 AST_CLI_DEFINE(show_codec, "Shows a specific codec"),
240};
241
242/*! \brief Function called when the process is shutting down */
243static void codec_shutdown(void)
244{
247 codecs = NULL;
248}
249
251{
253 ast_codec_hash_fn, NULL, codec_cmp);
254 if (!codecs) {
255 return -1;
256 }
257
260
261 return 0;
262}
263
264static void codec_dtor(void *obj)
265{
266 struct ast_codec *codec;
267
268 codec = obj;
269
270 ast_module_unref(codec->mod);
271}
272
273int __ast_codec_register(struct ast_codec *codec, struct ast_module *mod)
274{
276}
277
278int __ast_codec_register_with_format(struct ast_codec *codec, const char *format_name, struct ast_module *mod)
279{
281 struct internal_ast_codec *codec_new;
282
283 /* Some types have specific requirements */
284 if (codec->type == AST_MEDIA_TYPE_UNKNOWN) {
285 ast_log(LOG_ERROR, "A media type must be specified for codec '%s'\n", codec->name);
286 return -1;
287 } else if (codec->type == AST_MEDIA_TYPE_AUDIO) {
288 if (!codec->sample_rate) {
289 ast_log(LOG_ERROR, "A sample rate must be specified for codec '%s' of type '%s'\n",
290 codec->name, ast_codec_media_type2str(codec->type));
291 return -1;
292 }
293 }
294
295 codec_new = ao2_find(codecs, codec, OBJ_SEARCH_OBJECT | OBJ_NOLOCK);
296 if (codec_new) {
297 ast_log(LOG_ERROR, "A codec with name '%s' of type '%s' and sample rate '%u' is already registered\n",
298 codec->name, ast_codec_media_type2str(codec->type), codec->sample_rate);
299 ao2_ref(codec_new, -1);
300 return -1;
301 }
302
303 codec_new = ao2_t_alloc_options(sizeof(*codec_new), codec_dtor,
305 if (!codec_new) {
306 ast_log(LOG_ERROR, "Could not allocate a codec with name '%s' of type '%s' and sample rate '%u'\n",
307 codec->name, ast_codec_media_type2str(codec->type), codec->sample_rate);
308 return -1;
309 }
310 codec_new->external = *codec;
311 codec_new->format_name = format_name;
312 codec_new->external.id = codec_id++;
313
314 ao2_link_flags(codecs, codec_new, OBJ_NOLOCK);
315
316 /* Once registered a codec can not be unregistered, and the module must persist until shutdown */
318
319 ast_verb(5, "Registered '%s' codec '%s' at sample rate '%u' with id '%u'\n",
320 ast_codec_media_type2str(codec->type), codec->name, codec->sample_rate, codec_new->external.id);
321
322 ao2_ref(codec_new, -1);
323
324 return 0;
325}
326
327struct ast_codec *ast_codec_get(const char *name, enum ast_media_type type, unsigned int sample_rate)
328{
329 struct ast_codec codec = {
330 .name = name,
331 .type = type,
332 .sample_rate = sample_rate,
333 };
334
335 return ao2_find(codecs, &codec, OBJ_SEARCH_OBJECT);
336}
337
339{
340 return ao2_callback(codecs, 0, codec_id_cmp, &id);
341}
342
344{
345 return codec_id;
346}
347
349{
350 switch (type) {
352 return "audio";
354 return "video";
356 return "image";
358 return "text";
359 default:
360 return "<unknown>";
361 }
362}
363
364enum ast_media_type ast_media_type_from_str(const char *media_type_str)
365{
366 if (!strcasecmp(media_type_str, "audio")) {
368 } else if (!strcasecmp(media_type_str, "video")) {
370 } else if (!strcasecmp(media_type_str, "image")) {
372 } else if (!strcasecmp(media_type_str, "text")) {
373 return AST_MEDIA_TYPE_TEXT;
374 } else {
376 }
377}
378
379unsigned int ast_codec_samples_count(struct ast_frame *frame)
380{
381 struct ast_codec *codec;
382 unsigned int samples = 0;
383
384 if ((frame->frametype != AST_FRAME_VOICE) &&
385 (frame->frametype != AST_FRAME_VIDEO) &&
386 (frame->frametype != AST_FRAME_IMAGE)) {
387 return 0;
388 }
389
390 codec = ast_format_get_codec(frame->subclass.format);
391
392 if (codec->samples_count) {
393 samples = codec->samples_count(frame);
394 if ((int) samples < 0) {
395 ast_log(LOG_WARNING, "Codec %s returned invalid number of samples.\n",
397 samples = 0;
398 }
399 } else {
400 ast_log(LOG_WARNING, "Unable to calculate samples for codec %s\n",
402 }
403
404 ao2_ref(codec, -1);
405 return samples;
406}
407
408unsigned int ast_codec_determine_length(const struct ast_codec *codec, unsigned int samples)
409{
410 if (!codec->get_length) {
411 return 0;
412 }
413
414 return codec->get_length(samples);
415}
ast_mutex_t lock
Definition: app_sla.c:331
Asterisk main include file. File version handling, generic pbx functions.
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19
#define ast_log
Definition: astobj2.c:42
#define ao2_iterator_next(iter)
Definition: astobj2.h:1911
@ CMP_MATCH
Definition: astobj2.h:1027
@ CMP_STOP
Definition: astobj2.h:1028
#define ao2_rdlock(a)
Definition: astobj2.h:718
@ AO2_ALLOC_OPT_LOCK_NOLOCK
Definition: astobj2.h:367
@ AO2_ALLOC_OPT_LOCK_RWLOCK
Definition: astobj2.h:365
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
Definition: astobj2.h:1693
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
@ AO2_ITERATOR_DONTLOCK
Assume that the ao2_container is already locked.
Definition: astobj2.h:1852
#define ao2_link_flags(container, obj, flags)
Add an object to a container.
Definition: astobj2.h:1554
#define ao2_t_alloc_options(data_size, destructor_fn, options, debug_msg)
Allocate and initialize an object.
Definition: astobj2.h:402
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1736
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ao2_unlock(a)
Definition: astobj2.h:729
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define AO2_STRING_FIELD_HASH_FN(stype, field)
Creates a hash function for a structure string field.
Definition: astobj2.h:2032
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
@ OBJ_SEARCH_PARTIAL_KEY
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
Definition: astobj2.h:1116
@ OBJ_SEARCH_OBJECT
The arg parameter is an object of the same type.
Definition: astobj2.h:1087
@ OBJ_NOLOCK
Assume that the ao2_container is already locked.
Definition: astobj2.h:1063
@ OBJ_SEARCH_MASK
Search option field mask.
Definition: astobj2.h:1072
@ OBJ_SEARCH_KEY
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1101
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
Definition: astobj2.h:1303
static const char type[]
Definition: chan_ooh323.c:109
Standard Command Line Interface.
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_SUCCESS
Definition: cli.h:44
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
static void codec_shutdown(void)
Function called when the process is shutting down.
Definition: codec.c:243
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:408
int __ast_codec_register(struct ast_codec *codec, struct ast_module *mod)
This function is used to register a codec with the Asterisk core. Registering allows it to be passed ...
Definition: codec.c:273
static int codec_id_cmp(void *obj, void *arg, int flags)
Callback function for getting a codec based on unique identifier.
Definition: codec.c:190
enum ast_media_type ast_media_type_from_str(const char *media_type_str)
Conversion function to take a media string and convert it to a media type.
Definition: codec.c:364
static int codec_id
Current identifier value for newly registered codec.
Definition: codec.c:45
static struct ao2_container * codecs
Registered codecs.
Definition: codec.c:48
static char * show_codec(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: codec.c:198
int ast_codec_init(void)
Initialize codec support within the core.
Definition: codec.c:250
int __ast_codec_register_with_format(struct ast_codec *codec, const char *format_name, struct ast_module *mod)
Definition: codec.c:278
struct ast_codec * ast_codec_get(const char *name, enum ast_media_type type, unsigned int sample_rate)
Retrieve a codec given a name, type, and sample rate.
Definition: codec.c:327
#define CODEC_BUCKETS
Number of buckets to use for codecs (should be prime for performance reasons)
Definition: codec.c:42
unsigned int ast_codec_samples_count(struct ast_frame *frame)
Get the number of samples contained within a frame.
Definition: codec.c:379
struct ast_codec * ast_codec_get_by_id(int id)
Retrieve a codec given the unique identifier.
Definition: codec.c:338
const char * ast_codec_media_type2str(enum ast_media_type type)
Conversion function to take a media type and turn it into a string.
Definition: codec.c:348
static char * show_codecs(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: codec.c:120
static int codec_cmp(void *obj, void *arg, int flags)
Definition: codec.c:78
static void codec_dtor(void *obj)
Definition: codec.c:264
int ast_codec_get_max(void)
Retrieve the current maximum identifier for codec iteration.
Definition: codec.c:343
static struct ast_cli_entry codec_cli[]
Definition: codec.c:237
Codec API.
ast_media_type
Types of media.
Definition: codec.h:30
@ AST_MEDIA_TYPE_AUDIO
Definition: codec.h:32
@ AST_MEDIA_TYPE_UNKNOWN
Definition: codec.h:31
@ AST_MEDIA_TYPE_VIDEO
Definition: codec.h:33
@ AST_MEDIA_TYPE_IMAGE
Definition: codec.h:34
@ AST_MEDIA_TYPE_TEXT
Definition: codec.h:35
Media Format API.
struct ast_codec * ast_format_get_codec(const struct ast_format *format)
Get the codec associated with a format.
Definition: format.c:324
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
static const char name[]
Definition: format_mp3.c:68
Asterisk internal frame definitions.
@ AST_FRAME_VIDEO
@ AST_FRAME_IMAGE
@ AST_FRAME_VOICE
Support for logging to various files, console and syslog Configuration in file logger....
#define LOG_ERROR
#define ast_verb(level,...)
#define LOG_WARNING
#define SCOPED_AO2WRLOCK(varname, obj)
scoped lock specialization for ao2 write locks.
Definition: lock.h:614
Asterisk module definitions.
#define ast_module_unref(mod)
Release a reference to the module.
Definition: module.h:469
#define ast_module_shutdown_ref(mod)
Prevent unload of the module before shutdown.
Definition: module.h:464
#define ast_opt_dont_warn
Definition: options.h:125
#define NULL
Definition: resample.c:96
String manipulation functions.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
Generic container type.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
descriptor for a cli entry.
Definition: cli.h:171
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
Represents a media codec within Asterisk.
Definition: codec.h:42
unsigned int sample_rate
Sample rate (number of samples carried in a second)
Definition: codec.h:52
int(* samples_count)(struct ast_frame *frame)
Retrieve the number of samples in a frame.
Definition: codec.h:68
enum ast_media_type type
Type of media this codec contains.
Definition: codec.h:50
int(* get_length)(unsigned int samples)
Retrieve the length of media from number of samples.
Definition: codec.h:76
const char * description
Brief description.
Definition: codec.h:48
unsigned int quality
Format quality, on scale from 0 to 150 (100 is ulaw, the reference). This allows better format to be ...
Definition: codec.h:82
struct ast_module * mod
The module that registered this codec.
Definition: codec.h:84
const char * name
Name for this codec.
Definition: codec.h:46
unsigned int id
Internal unique identifier for this codec, set at registration time (starts at 1)
Definition: codec.h:44
struct ast_format * format
Data structure associated with a single frame of data.
struct ast_frame_subclass subclass
enum ast_frame_type frametype
const char * format_name
A format name for a default sane format using this codec.
Definition: codec.c:63
struct ast_codec external
Public codec structure. Must remain first.
Definition: codec.c:61
static struct test_val a
#define ast_assert(a)
Definition: utils.h:739
#define ARRAY_LEN(a)
Definition: utils.h:666