d77d244a644d4239f10bb304c2470898ce734122
[asterisk/asterisk.git] / main / format.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2010, Digium, Inc.
5  *
6  * David Vossel <dvossel@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 /*!
20  * \file
21  * \brief Format API
22  *
23  * \author David Vossel <dvossel@digium.com>
24  */
25
26 #include "asterisk.h"
27
28 ASTERISK_FILE_VERSION(__FILE__, "$Revision$");
29
30 #include "asterisk/_private.h"
31 #include "asterisk/version.h"
32 #include "asterisk/format.h"
33 #include "asterisk/astobj2.h"
34 #include "asterisk/lock.h"
35
36 /*! This is the container for all the format attribute interfaces.
37  *  An ao2 container was chosen for fast lookup. */
38 static struct ao2_container *interfaces;
39
40 /*! This is the lock used to protect the interfaces container.  Yes, ao2_containers
41  * do have their own locking, but we need the capability of performing read/write
42  * locks on this specific container. */
43 static ast_rwlock_t ilock;
44
45 /*! a wrapper is used put interfaces into the ao2 container. */
46 struct interface_ao2_wrapper {
47         enum ast_format_id id;
48         const struct ast_format_attr_interface *interface;
49         /*! a read write lock must be used to protect the wrapper instead
50          * of the ao2 lock. */
51         ast_rwlock_t wraplock;
52 };
53
54 static int interface_cmp_cb(void *obj, void *arg, int flags)
55 {
56         struct interface_ao2_wrapper *wrapper1 = obj;
57         struct interface_ao2_wrapper *wrapper2 = arg;
58
59         return (wrapper2->id == wrapper1->id) ? CMP_MATCH | CMP_STOP : 0;
60 }
61
62 static int interface_hash_cb(const void *obj, const int flags)
63 {
64         const struct interface_ao2_wrapper *wrapper = obj;
65         return wrapper->id;
66 }
67
68 static void interface_destroy_cb(void *obj)
69 {
70         struct interface_ao2_wrapper *wrapper = obj;
71         ast_rwlock_destroy(&wrapper->wraplock);
72 }
73
74 void ast_format_copy(struct ast_format *dst, const struct ast_format *src)
75 {
76         memcpy(dst, src, sizeof(struct ast_format));
77 }
78
79 void ast_format_set_video_mark(struct ast_format *format)
80 {
81         format->fattr.rtp_marker_bit = 1;
82 }
83
84 int ast_format_get_video_mark(const struct ast_format *format)
85 {
86         return format->fattr.rtp_marker_bit;
87 }
88
89 static struct interface_ao2_wrapper *find_interface(const struct ast_format *format)
90 {
91         struct interface_ao2_wrapper *wrapper;
92         struct interface_ao2_wrapper tmp_wrapper = {
93                 .id = format->id,
94         };
95
96         ast_rwlock_rdlock(&ilock);
97         if (!(wrapper = ao2_find(interfaces, &tmp_wrapper, (OBJ_POINTER | OBJ_NOLOCK)))) {
98                 ast_rwlock_unlock(&ilock);
99                 return NULL;
100         }
101         ast_rwlock_unlock(&ilock);
102
103         return wrapper;
104 }
105
106 /*! \internal
107  * \brief set format attributes using an interface
108  */
109 static int format_set_helper(struct ast_format *format, va_list ap)
110 {
111         struct interface_ao2_wrapper *wrapper;
112
113         if (!(wrapper = find_interface(format))) {
114                 ast_log(LOG_WARNING, "Could not find format interface to set.\n");
115                 return -1;
116         }
117
118         ast_rwlock_rdlock(&wrapper->wraplock);
119         if (!wrapper->interface || !wrapper->interface->format_attr_set) {
120                 ast_rwlock_unlock(&wrapper->wraplock);
121                 ao2_ref(wrapper, -1);
122                 return -1;
123         }
124
125         wrapper->interface->format_attr_set(&format->fattr, ap);
126
127         ast_rwlock_unlock(&wrapper->wraplock);
128         ao2_ref(wrapper, -1);
129
130         return 0;
131 }
132
133 struct ast_format *ast_format_append(struct ast_format *format, ... )
134 {
135         va_list ap;
136         va_start(ap, format);
137         format_set_helper(format, ap);
138         va_end(ap);
139
140         return format;
141 }
142
143 struct ast_format *ast_format_set(struct ast_format *format, enum ast_format_id id, int set_attributes, ... )
144 {
145         /* initialize the structure before setting it. */
146         ast_format_clear(format);
147
148         format->id = id;
149
150         if (set_attributes) {
151                 va_list ap;
152                 va_start(ap, set_attributes);
153                 format_set_helper(format, ap);
154                 va_end(ap);
155         }
156
157         return format;
158 }
159
160 void ast_format_clear(struct ast_format *format)
161 {
162         format->id = 0;
163         memset(&format->fattr, 0, sizeof(format->fattr));
164 }
165
166 /*! \internal
167  * \brief determine if a list of attribute key value pairs are set on a format
168  */
169 static int format_isset_helper(struct ast_format *format, va_list ap)
170 {
171         int res;
172         struct interface_ao2_wrapper *wrapper;
173         struct ast_format tmp = {
174                 .id = format->id,
175                 .fattr = { { 0, }, },
176         };
177
178         if (!(wrapper = find_interface(format))) {
179                 return -1;
180         }
181
182         ast_rwlock_rdlock(&wrapper->wraplock);
183         if (!wrapper->interface ||
184                 !wrapper->interface->format_attr_set ||
185                 !wrapper->interface->format_attr_cmp) {
186
187                 ast_rwlock_unlock(&wrapper->wraplock);
188                 ao2_ref(wrapper, -1);
189                 return -1;
190         }
191
192         wrapper->interface->format_attr_set(&tmp.fattr, ap);
193
194         /* use our tmp structure to tell if the attributes are set or not */
195         res = wrapper->interface->format_attr_cmp(&tmp.fattr, &format->fattr);
196
197         ast_rwlock_unlock(&wrapper->wraplock);
198         ao2_ref(wrapper, -1);
199
200         return (res == AST_FORMAT_CMP_NOT_EQUAL) ? -1 : 0;
201 }
202
203 int ast_format_isset(struct ast_format *format, ... )
204 {
205         va_list ap;
206         int res;
207
208         va_start(ap, format);
209         res = format_isset_helper(format, ap);
210         va_end(ap);
211         return res;
212 }
213
214
215 /*! \internal
216  * \brief cmp format attributes using an interface
217  */
218 static enum ast_format_cmp_res format_cmp_helper(const struct ast_format *format1, const struct ast_format *format2)
219 {
220         enum ast_format_cmp_res res = AST_FORMAT_CMP_EQUAL;
221         struct interface_ao2_wrapper *wrapper;
222
223         if (!(wrapper = find_interface(format1))) {
224                 return res;
225         }
226
227         ast_rwlock_rdlock(&wrapper->wraplock);
228         if (!wrapper->interface || !wrapper->interface->format_attr_cmp) {
229                 ast_rwlock_unlock(&wrapper->wraplock);
230                 ao2_ref(wrapper, -1);
231                 return res;
232         }
233
234         res = wrapper->interface->format_attr_cmp(&format1->fattr, &format2->fattr);
235
236         ast_rwlock_unlock(&wrapper->wraplock);
237         ao2_ref(wrapper, -1);
238
239         return res;
240 }
241
242 enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
243 {
244         if (format1->id != format2->id) {
245                 return AST_FORMAT_CMP_NOT_EQUAL;
246         }
247
248         return format_cmp_helper(format1, format2);
249 }
250
251 /*! \internal
252  * \brief get joint format attributes using an interface
253  */
254 static int format_joint_helper(const struct ast_format *format1, const struct ast_format *format2, struct ast_format *result)
255 {
256         int res = 0;
257         struct interface_ao2_wrapper *wrapper;
258
259         if (!(wrapper = find_interface(format1))) {
260                 /* if no interface is present, we assume formats are joint by id alone */
261                 return res;
262         }
263
264         ast_rwlock_rdlock(&wrapper->wraplock);
265         if (wrapper->interface && wrapper->interface->format_attr_get_joint) {
266                 res = wrapper->interface->format_attr_get_joint(&format1->fattr, &format2->fattr, &result->fattr);
267         }
268         ast_rwlock_unlock(&wrapper->wraplock);
269
270         ao2_ref(wrapper, -1);
271
272         return res;
273 }
274
275 int ast_format_joint(const struct ast_format *format1, const struct ast_format *format2, struct ast_format *result)
276 {
277         if (format1->id != format2->id) {
278                 return -1;
279         }
280         result->id = format1->id;
281         return format_joint_helper(format1, format2, result);
282 }
283
284
285 uint64_t ast_format_id_to_old_bitfield(enum ast_format_id id)
286 {
287         switch (id) {
288         /*! G.723.1 compression */
289         case AST_FORMAT_G723_1:
290                 return (1ULL << 0);
291         /*! GSM compression */
292         case AST_FORMAT_GSM:
293                 return (1ULL << 1);
294         /*! Raw mu-law data (G.711) */
295         case AST_FORMAT_ULAW:
296                 return (1ULL << 2);
297         /*! Raw A-law data (G.711) */
298         case AST_FORMAT_ALAW:
299                 return (1ULL << 3);
300         /*! ADPCM (G.726, 32kbps, AAL2 codeword packing) */
301         case AST_FORMAT_G726_AAL2:
302                 return (1ULL << 4);
303         /*! ADPCM (IMA) */
304         case AST_FORMAT_ADPCM:
305                 return (1ULL << 5);
306         /*! Raw 16-bit Signed Linear (8000 Hz) PCM */
307         case AST_FORMAT_SLINEAR:
308                 return (1ULL << 6);
309         /*! LPC10, 180 samples/frame */
310         case AST_FORMAT_LPC10:
311                 return (1ULL << 7);
312         /*! G.729A audio */
313         case AST_FORMAT_G729A:
314                 return (1ULL << 8);
315         /*! SpeeX Free Compression */
316         case AST_FORMAT_SPEEX:
317                 return (1ULL << 9);
318         /*! iLBC Free Compression */
319         case AST_FORMAT_ILBC:
320                 return (1ULL << 10);
321         /*! ADPCM (G.726, 32kbps, RFC3551 codeword packing) */
322         case AST_FORMAT_G726:
323                 return (1ULL << 11);
324         /*! G.722 */
325         case AST_FORMAT_G722:
326                 return (1ULL << 12);
327         /*! G.722.1 (also known as Siren7, 32kbps assumed) */
328         case AST_FORMAT_SIREN7:
329                 return (1ULL << 13);
330         /*! G.722.1 Annex C (also known as Siren14, 48kbps assumed) */
331         case AST_FORMAT_SIREN14:
332                 return (1ULL << 14);
333         /*! Raw 16-bit Signed Linear (16000 Hz) PCM */
334         case AST_FORMAT_SLINEAR16:
335                 return (1ULL << 15);
336         /*! G.719 (64 kbps assumed) */
337         case AST_FORMAT_G719:
338                 return (1ULL << 32);
339         /*! SpeeX Wideband (16kHz) Free Compression */
340         case AST_FORMAT_SPEEX16:
341                 return (1ULL << 33);
342         /*! Raw mu-law data (G.711) */
343         case AST_FORMAT_TESTLAW:
344                 return (1ULL << 47);
345
346         /*! H.261 Video */
347         case AST_FORMAT_H261:
348                 return (1ULL << 18);
349         /*! H.263 Video */
350         case AST_FORMAT_H263:
351                 return (1ULL << 19);
352         /*! H.263+ Video */
353         case AST_FORMAT_H263_PLUS:
354                 return (1ULL << 20);
355         /*! H.264 Video */
356         case AST_FORMAT_H264:
357                 return (1ULL << 21);
358         /*! MPEG4 Video */
359         case AST_FORMAT_MP4_VIDEO:
360                 return (1ULL << 22);
361
362         /*! JPEG Images */
363         case AST_FORMAT_JPEG:
364                 return (1ULL << 16);
365         /*! PNG Images */
366         case AST_FORMAT_PNG:
367                 return (1ULL << 17);
368
369         /*! T.140 RED Text format RFC 4103 */
370         case AST_FORMAT_T140RED:
371                 return (1ULL << 26);
372         /*! T.140 Text format - ITU T.140, RFC 4103 */
373         case AST_FORMAT_T140:
374                 return (1ULL << 27);
375         }
376
377         return 0;
378
379 }
380 uint64_t ast_format_to_old_bitfield(const struct ast_format *format)
381 {
382         return ast_format_id_to_old_bitfield(format->id);
383 }
384
385 struct ast_format *ast_format_from_old_bitfield(struct ast_format *dst, uint64_t src)
386 {
387         switch (src) {
388         /*! G.723.1 compression */
389         case (1ULL << 0):
390                 return ast_format_set(dst, AST_FORMAT_G723_1, 0);
391         /*! GSM compression */
392         case (1ULL << 1):
393                 return ast_format_set(dst, AST_FORMAT_GSM, 0);
394         /*! Raw mu-law data (G.711) */
395         case (1ULL << 2):
396                 return ast_format_set(dst, AST_FORMAT_ULAW, 0);
397         /*! Raw A-law data (G.711) */
398         case (1ULL << 3):
399                 return ast_format_set(dst, AST_FORMAT_ALAW, 0);
400         /*! ADPCM (G.726, 32kbps, AAL2 codeword packing) */
401         case (1ULL << 4):
402                 return ast_format_set(dst, AST_FORMAT_G726_AAL2, 0);
403         /*! ADPCM (IMA) */
404         case (1ULL << 5):
405                 return ast_format_set(dst, AST_FORMAT_ADPCM, 0);
406         /*! Raw 16-bit Signed Linear (8000 Hz) PCM */
407         case (1ULL << 6):
408                 return ast_format_set(dst, AST_FORMAT_SLINEAR, 0);
409         /*! LPC10, 180 samples/frame */
410         case (1ULL << 7):
411                 return ast_format_set(dst, AST_FORMAT_LPC10, 0);
412         /*! G.729A audio */
413         case (1ULL << 8):
414                 return ast_format_set(dst, AST_FORMAT_G729A, 0);
415         /*! SpeeX Free Compression */
416         case (1ULL << 9):
417                 return ast_format_set(dst, AST_FORMAT_SPEEX, 0);
418         /*! iLBC Free Compression */
419         case (1ULL << 10):
420                 return ast_format_set(dst, AST_FORMAT_ILBC, 0);
421         /*! ADPCM (G.726, 32kbps, RFC3551 codeword packing) */
422         case (1ULL << 11):
423                 return ast_format_set(dst, AST_FORMAT_G726, 0);
424         /*! G.722 */
425         case (1ULL << 12):
426                 return ast_format_set(dst, AST_FORMAT_G722, 0);
427         /*! G.722.1 (also known as Siren7, 32kbps assumed) */
428         case (1ULL << 13):
429                 return ast_format_set(dst, AST_FORMAT_SIREN7, 0);
430         /*! G.722.1 Annex C (also known as Siren14, 48kbps assumed) */
431         case (1ULL << 14):
432                 return ast_format_set(dst, AST_FORMAT_SIREN14, 0);
433         /*! Raw 16-bit Signed Linear (16000 Hz) PCM */
434         case (1ULL << 15):
435                 return ast_format_set(dst, AST_FORMAT_SLINEAR16, 0);
436         /*! G.719 (64 kbps assumed) */
437         case (1ULL << 32):
438                 return ast_format_set(dst, AST_FORMAT_G719, 0);
439         /*! SpeeX Wideband (16kHz) Free Compression */
440         case (1ULL << 33):
441                 return ast_format_set(dst, AST_FORMAT_SPEEX16, 0);
442         /*! Raw mu-law data (G.711) */
443         case (1ULL << 47):
444                 return ast_format_set(dst, AST_FORMAT_TESTLAW, 0);
445
446         /*! H.261 Video */
447         case (1ULL << 18):
448                 return ast_format_set(dst, AST_FORMAT_H261, 0);
449         /*! H.263 Video */
450         case (1ULL << 19):
451                 return ast_format_set(dst, AST_FORMAT_H263, 0);
452         /*! H.263+ Video */
453         case (1ULL << 20):
454                 return ast_format_set(dst, AST_FORMAT_H263_PLUS, 0);
455         /*! H.264 Video */
456         case (1ULL << 21):
457                 return ast_format_set(dst, AST_FORMAT_H264, 0);
458         /*! MPEG4 Video */
459         case (1ULL << 22):
460                 return ast_format_set(dst, AST_FORMAT_MP4_VIDEO, 0);
461
462         /*! JPEG Images */
463         case (1ULL << 16):
464                 return ast_format_set(dst, AST_FORMAT_JPEG, 0);
465         /*! PNG Images */
466         case (1ULL << 17):
467                 return ast_format_set(dst, AST_FORMAT_PNG, 0);
468
469         /*! T.140 RED Text format RFC 4103 */
470         case (1ULL << 26):
471                 return ast_format_set(dst, AST_FORMAT_T140RED, 0);
472         /*! T.140 Text format - ITU T.140, RFC 4103 */
473         case (1ULL << 27):
474                 return ast_format_set(dst, AST_FORMAT_T140, 0);
475         }
476         ast_format_clear(dst);
477         return NULL;
478 }
479
480 enum ast_format_id ast_format_id_from_old_bitfield(uint64_t src)
481 {
482         struct ast_format dst;
483         if (ast_format_from_old_bitfield(&dst, src)) {
484                 return dst.id;
485         }
486         return 0;
487 }
488
489 int ast_format_attr_init()
490 {
491         if (ast_rwlock_init(&ilock)) {
492                 return -1;
493         }
494         if (!(interfaces = ao2_container_alloc(283, interface_hash_cb, interface_cmp_cb))) {
495                 ast_rwlock_destroy(&ilock);
496                 return -1;
497         }
498         return 0;
499 }
500
501 int ast_format_attr_reg_interface(const struct ast_format_attr_interface *interface)
502 {
503         struct interface_ao2_wrapper *wrapper;
504         struct interface_ao2_wrapper tmp_wrapper = {
505                 .id = interface->id,
506         };
507
508         /* check for duplicates first*/
509         ast_rwlock_wrlock(&ilock);
510         if ((wrapper = ao2_find(interfaces, &tmp_wrapper, (OBJ_POINTER | OBJ_NOLOCK)))) {
511                 ast_rwlock_unlock(&ilock);
512                 ast_log(LOG_WARNING, "Can not register attribute interface for format id %d, interface already exists.\n", interface->id);
513                 ao2_ref(wrapper, -1);
514                 return -1;
515         }
516         ast_rwlock_unlock(&ilock);
517
518         if (!(wrapper = ao2_alloc(sizeof(*wrapper), interface_destroy_cb))) {
519                 return -1;
520         }
521
522         wrapper->interface = interface;
523         wrapper->id = interface->id;
524         ast_rwlock_init(&wrapper->wraplock);
525
526         /* use the write lock whenever the interface container is modified */
527         ast_rwlock_wrlock(&ilock);
528         ao2_link(interfaces, wrapper);
529         ast_rwlock_unlock(&ilock);
530
531         ao2_ref(wrapper, -1);
532
533         return 0;
534 }
535
536 int ast_format_attr_unreg_interface(const struct ast_format_attr_interface *interface)
537 {
538         struct interface_ao2_wrapper *wrapper;
539         struct interface_ao2_wrapper tmp_wrapper = {
540                 .id = interface->id,
541         };
542
543         /* use the write lock whenever the interface container is modified */
544         ast_rwlock_wrlock(&ilock);
545         if (!(wrapper = ao2_find(interfaces, &tmp_wrapper, (OBJ_POINTER | OBJ_UNLINK | OBJ_NOLOCK)))) {
546                 ast_rwlock_unlock(&ilock);
547                 return -1;
548         }
549         ast_rwlock_unlock(&ilock);
550
551         ast_rwlock_wrlock(&wrapper->wraplock);
552         wrapper->interface = NULL;
553         ast_rwlock_unlock(&wrapper->wraplock);
554
555         ao2_ref(wrapper, -1);
556
557         return 0;
558 }