]> code.delx.au - pulseaudio/blob - src/pulse/format.c
add support for MPEG-2 AAC pass-through
[pulseaudio] / src / pulse / format.c
1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2011 Intel Corporation
5 Copyright 2011 Collabora Multimedia
6 Copyright 2011 Arun Raghavan <arun.raghavan@collabora.co.uk>
7
8 PulseAudio is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as published
10 by the Free Software Foundation; either version 2.1 of the License,
11 or (at your option) any later version.
12
13 PulseAudio is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with PulseAudio; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 USA.
22 ***/
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <json.h>
29
30 #include <pulse/internal.h>
31 #include <pulse/xmalloc.h>
32
33 #include <pulsecore/core-util.h>
34 #include <pulsecore/i18n.h>
35 #include <pulsecore/macro.h>
36
37 #include "format.h"
38
39 #define PA_JSON_MIN_KEY "min"
40 #define PA_JSON_MAX_KEY "max"
41
42 static int pa_format_info_prop_compatible(const char *one, const char *two);
43
44 static const char* const _encoding_str_table[]= {
45 [PA_ENCODING_PCM] = "pcm",
46 [PA_ENCODING_AC3_IEC61937] = "ac3-iec61937",
47 [PA_ENCODING_EAC3_IEC61937] = "eac3-iec61937",
48 [PA_ENCODING_MPEG_IEC61937] = "mpeg-iec61937",
49 [PA_ENCODING_DTS_IEC61937] = "dts-iec61937",
50 [PA_ENCODING_MPEG2_AAC_IEC61937] = "mpeg2-aac-iec61937",
51 [PA_ENCODING_ANY] = "any",
52 };
53
54 const char *pa_encoding_to_string(pa_encoding_t e) {
55 if (e < 0 || e >= PA_ENCODING_MAX)
56 return NULL;
57
58 return _encoding_str_table[e];
59 }
60
61 pa_encoding_t pa_encoding_from_string(const char *encoding) {
62 pa_encoding_t e;
63
64 for (e = PA_ENCODING_ANY; e < PA_ENCODING_MAX; e++)
65 if (pa_streq(_encoding_str_table[e], encoding))
66 return e;
67
68 return PA_ENCODING_INVALID;
69 }
70
71 pa_format_info* pa_format_info_new(void) {
72 pa_format_info *f = pa_xnew(pa_format_info, 1);
73
74 f->encoding = PA_ENCODING_INVALID;
75 f->plist = pa_proplist_new();
76
77 return f;
78 }
79
80 pa_format_info* pa_format_info_copy(const pa_format_info *src) {
81 pa_format_info *dest;
82
83 pa_assert(src);
84
85 dest = pa_xnew(pa_format_info, 1);
86
87 dest->encoding = src->encoding;
88
89 if (src->plist)
90 dest->plist = pa_proplist_copy(src->plist);
91 else
92 dest->plist = NULL;
93
94 return dest;
95 }
96
97 void pa_format_info_free(pa_format_info *f) {
98 pa_assert(f);
99
100 pa_proplist_free(f->plist);
101 pa_xfree(f);
102 }
103
104 int pa_format_info_valid(const pa_format_info *f) {
105 return (f->encoding >= 0 && f->encoding < PA_ENCODING_MAX && f->plist != NULL);
106 }
107
108 int pa_format_info_is_pcm(const pa_format_info *f) {
109 return f->encoding == PA_ENCODING_PCM;
110 }
111
112 char *pa_format_info_snprint(char *s, size_t l, const pa_format_info *f) {
113 char *tmp;
114
115 pa_assert(s);
116 pa_assert(l > 0);
117 pa_assert(f);
118
119 pa_init_i18n();
120
121 if (!pa_format_info_valid(f))
122 pa_snprintf(s, l, _("(invalid)"));
123 else {
124 tmp = pa_proplist_to_string_sep(f->plist, " ");
125 if (tmp[0])
126 pa_snprintf(s, l, "%s, %s", pa_encoding_to_string(f->encoding), tmp);
127 else
128 pa_snprintf(s, l, "%s", pa_encoding_to_string(f->encoding));
129 pa_xfree(tmp);
130 }
131
132 return s;
133 }
134
135 pa_format_info* pa_format_info_from_string(const char *str) {
136 pa_format_info *f = pa_format_info_new();
137 char *encoding = NULL, *properties = NULL;
138 size_t pos;
139
140 pos = strcspn(str, ",");
141
142 encoding = pa_xstrndup(str, pos);
143 f->encoding = pa_encoding_from_string(pa_strip(encoding));
144 if (f->encoding == PA_ENCODING_INVALID)
145 goto error;
146
147 if (pos != strlen(str)) {
148 pa_proplist *plist;
149
150 properties = pa_xstrdup(&str[pos+1]);
151 plist = pa_proplist_from_string(properties);
152
153 if (!plist)
154 goto error;
155
156 pa_proplist_free(f->plist);
157 f->plist = plist;
158 }
159
160 out:
161 if (encoding)
162 pa_xfree(encoding);
163 if (properties)
164 pa_xfree(properties);
165 return f;
166
167 error:
168 pa_format_info_free(f);
169 f = NULL;
170 goto out;
171 }
172
173 int pa_format_info_is_compatible(pa_format_info *first, pa_format_info *second) {
174 const char *key;
175 void *state = NULL;
176
177 pa_assert(first);
178 pa_assert(second);
179
180 if (first->encoding != second->encoding)
181 return FALSE;
182
183 while ((key = pa_proplist_iterate(first->plist, &state))) {
184 const char *value_one, *value_two;
185
186 value_one = pa_proplist_gets(first->plist, key);
187 value_two = pa_proplist_gets(second->plist, key);
188
189 if (!value_two || !pa_format_info_prop_compatible(value_one, value_two))
190 return FALSE;
191 }
192
193 return TRUE;
194 }
195
196 pa_format_info* pa_format_info_from_sample_spec(pa_sample_spec *ss, pa_channel_map *map) {
197 char cm[PA_CHANNEL_MAP_SNPRINT_MAX];
198 pa_format_info *f;
199
200 pa_assert(ss && pa_sample_spec_valid(ss));
201 pa_assert(!map || pa_channel_map_valid(map));
202
203 f = pa_format_info_new();
204 f->encoding = PA_ENCODING_PCM;
205
206 pa_format_info_set_sample_format(f, ss->format);
207 pa_format_info_set_rate(f, ss->rate);
208 pa_format_info_set_channels(f, ss->channels);
209
210 if (map) {
211 pa_channel_map_snprint(cm, sizeof(cm), map);
212 pa_format_info_set_prop_string(f, PA_PROP_FORMAT_CHANNEL_MAP, cm);
213 }
214
215 return f;
216 }
217
218 /* For compressed streams */
219 static int pa_format_info_to_sample_spec_fake(pa_format_info *f, pa_sample_spec *ss) {
220 int rate;
221
222 pa_assert(f);
223 pa_assert(ss);
224
225 /* Note: When we add support for non-IEC61937 encapsulated compressed
226 * formats, this function should return a non-zero values for these. */
227
228 ss->format = PA_SAMPLE_S16LE;
229 ss->channels = 2;
230
231 pa_return_val_if_fail(pa_format_info_get_prop_int(f, PA_PROP_FORMAT_RATE, &rate) == 0, -PA_ERR_INVALID);
232 ss->rate = (uint32_t) rate;
233
234 if (f->encoding == PA_ENCODING_EAC3_IEC61937)
235 ss->rate *= 4;
236
237 return 0;
238 }
239
240 /* For PCM streams */
241 int pa_format_info_to_sample_spec(pa_format_info *f, pa_sample_spec *ss, pa_channel_map *map) {
242 char *sf = NULL, *m = NULL;
243 int rate, channels;
244 int ret = -PA_ERR_INVALID;
245
246 pa_assert(f);
247 pa_assert(ss);
248
249 if (!pa_format_info_is_pcm(f))
250 return pa_format_info_to_sample_spec_fake(f, ss);
251
252 if (pa_format_info_get_prop_string(f, PA_PROP_FORMAT_SAMPLE_FORMAT, &sf))
253 goto out;
254 if (pa_format_info_get_prop_int(f, PA_PROP_FORMAT_RATE, &rate))
255 goto out;
256 if (pa_format_info_get_prop_int(f, PA_PROP_FORMAT_CHANNELS, &channels))
257 goto out;
258
259 if ((ss->format = pa_parse_sample_format(sf)) == PA_SAMPLE_INVALID)
260 goto out;
261
262 ss->rate = (uint32_t) rate;
263 ss->channels = (uint8_t) channels;
264
265 if (map) {
266 pa_channel_map_init(map);
267
268 if (pa_format_info_get_prop_string(f, PA_PROP_FORMAT_CHANNEL_MAP, &m) == 0)
269 if (pa_channel_map_parse(map, m) == NULL)
270 goto out;
271 }
272
273 ret = 0;
274
275 out:
276 if (sf)
277 pa_xfree(sf);
278 if (m)
279 pa_xfree(m);
280
281 return ret;
282 }
283
284 pa_prop_type_t pa_format_info_get_prop_type(pa_format_info *f, const char *key) {
285 const char *str;
286 json_object *o, *o1;
287 pa_prop_type_t type;
288
289 pa_assert(f);
290 pa_assert(key);
291
292 str = pa_proplist_gets(f->plist, key);
293 if (!str)
294 return PA_PROP_TYPE_INVALID;
295
296 o = json_tokener_parse(str);
297 if (is_error(o))
298 return PA_PROP_TYPE_INVALID;
299
300 switch (json_object_get_type(o)) {
301 case json_type_int:
302 type = PA_PROP_TYPE_INT;
303 break;
304
305 case json_type_string:
306 type = PA_PROP_TYPE_STRING;
307 break;
308
309 case json_type_array:
310 if (json_object_array_length(o) == 0) {
311 /* Unlikely, but let's account for this anyway. We need at
312 * least one element to figure out the array type. */
313 type = PA_PROP_TYPE_INVALID;
314 break;
315 }
316
317 o1 = json_object_array_get_idx(o, 1);
318
319 if (json_object_get_type(o1) == json_type_int)
320 type = PA_PROP_TYPE_INT_ARRAY;
321 else if (json_object_get_type(o1) == json_type_string)
322 type = PA_PROP_TYPE_STRING_ARRAY;
323 else
324 type = PA_PROP_TYPE_INVALID;
325
326 json_object_put(o1);
327 break;
328
329 case json_type_object:
330 /* We actually know at this point that it's a int range, but let's
331 * confirm. */
332 o1 = json_object_object_get(o, PA_JSON_MIN_KEY);
333 if (!o1) {
334 type = PA_PROP_TYPE_INVALID;
335 break;
336 }
337 json_object_put(o1);
338
339 o1 = json_object_object_get(o, PA_JSON_MAX_KEY);
340 if (!o1) {
341 type = PA_PROP_TYPE_INVALID;
342 break;
343 }
344 json_object_put(o1);
345
346 type = PA_PROP_TYPE_INT_RANGE;
347 break;
348
349 default:
350 type = PA_PROP_TYPE_INVALID;
351 break;
352 }
353
354 json_object_put(o);
355 return type;
356 }
357
358 int pa_format_info_get_prop_int(pa_format_info *f, const char *key, int *v) {
359 const char *str;
360 json_object *o;
361
362 pa_assert(f);
363 pa_assert(key);
364 pa_assert(v);
365
366 str = pa_proplist_gets(f->plist, key);
367 if (!str)
368 return -PA_ERR_NOENTITY;
369
370 o = json_tokener_parse(str);
371 if (is_error(o))
372 return -PA_ERR_INVALID;
373
374 if (json_object_get_type(o) != json_type_int) {
375 json_object_put(o);
376 return -PA_ERR_INVALID;
377 }
378
379 *v = json_object_get_int(o);
380 json_object_put(o);
381
382 return 0;
383 }
384
385 int pa_format_info_get_prop_int_range(pa_format_info *f, const char *key, int *min, int *max) {
386 const char *str;
387 json_object *o, *o1;
388 int ret = -PA_ERR_INVALID;
389
390 pa_assert(f);
391 pa_assert(key);
392 pa_assert(min);
393 pa_assert(max);
394
395 str = pa_proplist_gets(f->plist, key);
396 if (!str)
397 return -PA_ERR_NOENTITY;
398
399 o = json_tokener_parse(str);
400 if (is_error(o))
401 return -PA_ERR_INVALID;
402
403 if (json_object_get_type(o) != json_type_object)
404 goto out;
405
406 if (!(o1 = json_object_object_get(o, PA_JSON_MIN_KEY)))
407 goto out;
408
409 *min = json_object_get_int(o1);
410 json_object_put(o1);
411
412 if (!(o1 = json_object_object_get(o, PA_JSON_MAX_KEY)))
413 goto out;
414
415 *max = json_object_get_int(o1);
416 json_object_put(o1);
417
418 ret = 0;
419
420 out:
421 json_object_put(o);
422 return ret;
423 }
424
425 int pa_format_info_get_prop_int_array(pa_format_info *f, const char *key, int **values, int *n_values)
426 {
427 const char *str;
428 json_object *o, *o1;
429 int i, ret = -PA_ERR_INVALID;
430
431 pa_assert(f);
432 pa_assert(key);
433 pa_assert(values);
434 pa_assert(n_values);
435
436 str = pa_proplist_gets(f->plist, key);
437 if (!str)
438 return -PA_ERR_NOENTITY;
439
440 o = json_tokener_parse(str);
441 if (is_error(o))
442 return -PA_ERR_INVALID;
443
444 if (json_object_get_type(o) != json_type_array)
445 goto out;
446
447 *n_values = json_object_array_length(o);
448 *values = pa_xnew(int, *n_values);
449
450 for (i = 0; i < *n_values; i++) {
451 o1 = json_object_array_get_idx(o, i);
452
453 if (json_object_get_type(o1) != json_type_int) {
454 json_object_put(o1);
455 goto out;
456 }
457
458 (*values)[i] = json_object_get_int(o1);
459 json_object_put(o1);
460 }
461
462 ret = 0;
463
464 out:
465 json_object_put(o);
466 return ret;
467 }
468
469 int pa_format_info_get_prop_string(pa_format_info *f, const char *key, char **v) {
470 const char *str = NULL;
471 json_object *o;
472
473 pa_assert(f);
474 pa_assert(key);
475 pa_assert(v);
476
477 str = pa_proplist_gets(f->plist, key);
478 if (!str)
479 return -PA_ERR_NOENTITY;
480
481 o = json_tokener_parse(str);
482 if (is_error(o))
483 return -PA_ERR_INVALID;
484
485 if (json_object_get_type(o) != json_type_string) {
486 json_object_put(o);
487 return -PA_ERR_INVALID;
488 }
489
490 *v = pa_xstrdup(json_object_get_string(o));
491 json_object_put(o);
492
493 return 0;
494 }
495
496 int pa_format_info_get_prop_string_array(pa_format_info *f, const char *key, char ***values, int *n_values)
497 {
498 const char *str;
499 json_object *o, *o1;
500 int i, ret = -PA_ERR_INVALID;
501
502 pa_assert(f);
503 pa_assert(key);
504 pa_assert(values);
505 pa_assert(n_values);
506
507 str = pa_proplist_gets(f->plist, key);
508 if (!str)
509 return -PA_ERR_NOENTITY;
510
511 o = json_tokener_parse(str);
512 if (is_error(o))
513 return -PA_ERR_INVALID;
514
515 if (json_object_get_type(o) != json_type_array)
516 goto out;
517
518 *n_values = json_object_array_length(o);
519 *values = pa_xnew(char *, *n_values);
520
521 for (i = 0; i < *n_values; i++) {
522 o1 = json_object_array_get_idx(o, i);
523
524 if (json_object_get_type(o1) != json_type_string) {
525 json_object_put(o1);
526 goto out;
527 }
528
529 (*values)[i] = pa_xstrdup(json_object_get_string(o1));
530 json_object_put(o1);
531 }
532
533 ret = 0;
534
535 out:
536 json_object_put(o);
537 return ret;
538 }
539
540 void pa_format_info_free_string_array(char **values, int n_values) {
541 int i;
542
543 for (i = 0; i < n_values; i++)
544 pa_xfree(values[i]);
545
546 pa_xfree(values);
547 }
548
549 void pa_format_info_set_sample_format(pa_format_info *f, pa_sample_format_t sf) {
550 pa_format_info_set_prop_string(f, PA_PROP_FORMAT_SAMPLE_FORMAT, pa_sample_format_to_string(sf));
551 }
552
553 void pa_format_info_set_rate(pa_format_info *f, int rate) {
554 pa_format_info_set_prop_int(f, PA_PROP_FORMAT_RATE, rate);
555 }
556
557 void pa_format_info_set_channels(pa_format_info *f, int channels) {
558 pa_format_info_set_prop_int(f, PA_PROP_FORMAT_CHANNELS, channels);
559 }
560
561 void pa_format_info_set_channel_map(pa_format_info *f, const pa_channel_map *map) {
562 char map_str[PA_CHANNEL_MAP_SNPRINT_MAX];
563
564 pa_channel_map_snprint(map_str, sizeof(map_str), map);
565
566 pa_format_info_set_prop_string(f, PA_PROP_FORMAT_CHANNEL_MAP, map_str);
567 }
568
569 void pa_format_info_set_prop_int(pa_format_info *f, const char *key, int value) {
570 json_object *o;
571
572 pa_assert(f);
573 pa_assert(key);
574
575 o = json_object_new_int(value);
576
577 pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
578
579 json_object_put(o);
580 }
581
582 void pa_format_info_set_prop_int_array(pa_format_info *f, const char *key, const int *values, int n_values) {
583 json_object *o;
584 int i;
585
586 pa_assert(f);
587 pa_assert(key);
588
589 o = json_object_new_array();
590
591 for (i = 0; i < n_values; i++)
592 json_object_array_add(o, json_object_new_int(values[i]));
593
594 pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
595
596 json_object_put(o);
597 }
598
599 void pa_format_info_set_prop_int_range(pa_format_info *f, const char *key, int min, int max) {
600 json_object *o;
601
602 pa_assert(f);
603 pa_assert(key);
604
605 o = json_object_new_object();
606
607 json_object_object_add(o, PA_JSON_MIN_KEY, json_object_new_int(min));
608 json_object_object_add(o, PA_JSON_MAX_KEY, json_object_new_int(max));
609
610 pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
611
612 json_object_put(o);
613 }
614
615 void pa_format_info_set_prop_string(pa_format_info *f, const char *key, const char *value) {
616 json_object *o;
617
618 pa_assert(f);
619 pa_assert(key);
620
621 o = json_object_new_string(value);
622
623 pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
624
625 json_object_put(o);
626 }
627
628 void pa_format_info_set_prop_string_array(pa_format_info *f, const char *key, const char **values, int n_values) {
629 json_object *o;
630 int i;
631
632 pa_assert(f);
633 pa_assert(key);
634
635 o = json_object_new_array();
636
637 for (i = 0; i < n_values; i++)
638 json_object_array_add(o, json_object_new_string(values[i]));
639
640 pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
641
642 json_object_put(o);
643 }
644
645 static pa_bool_t pa_json_is_fixed_type(json_object *o)
646 {
647 switch(json_object_get_type(o)) {
648 case json_type_object:
649 case json_type_array:
650 return FALSE;
651
652 default:
653 return TRUE;
654 }
655 }
656
657 static int pa_json_value_equal(json_object *o1, json_object *o2) {
658 return (json_object_get_type(o1) == json_object_get_type(o2)) &&
659 pa_streq(json_object_to_json_string(o1), json_object_to_json_string(o2));
660 }
661
662 static int pa_format_info_prop_compatible(const char *one, const char *two) {
663 json_object *o1 = NULL, *o2 = NULL;
664 int i, ret = 0;
665
666 o1 = json_tokener_parse(one);
667 if (is_error(o1))
668 goto out;
669
670 o2 = json_tokener_parse(two);
671 if (is_error(o2))
672 goto out;
673
674 /* We don't deal with both values being non-fixed - just because there is no immediate need (FIXME) */
675 pa_return_val_if_fail(pa_json_is_fixed_type(o1) || pa_json_is_fixed_type(o2), FALSE);
676
677 if (pa_json_is_fixed_type(o1) && pa_json_is_fixed_type(o2)) {
678 ret = pa_json_value_equal(o1, o2);
679 goto out;
680 }
681
682 if (pa_json_is_fixed_type(o1)) {
683 json_object *tmp = o2;
684 o2 = o1;
685 o1 = tmp;
686 }
687
688 /* o2 is now a fixed type, and o1 is not */
689
690 if (json_object_get_type(o1) == json_type_array) {
691 for (i = 0; i < json_object_array_length(o1); i++) {
692 if (pa_json_value_equal(json_object_array_get_idx(o1, i), o2)) {
693 ret = 1;
694 break;
695 }
696 }
697 } else if (json_object_get_type(o1) == json_type_object) {
698 /* o1 should be a range type */
699 int min, max, v;
700 json_object *o_min = NULL, *o_max = NULL;
701
702 if (json_object_get_type(o2) != json_type_int) {
703 /* We don't support non-integer ranges */
704 goto out;
705 }
706
707 o_min = json_object_object_get(o1, PA_JSON_MIN_KEY);
708 if (!o_min || json_object_get_type(o_min) != json_type_int)
709 goto out;
710
711 o_max = json_object_object_get(o1, PA_JSON_MAX_KEY);
712 if (!o_max || json_object_get_type(o_max) != json_type_int)
713 goto out;
714
715 v = json_object_get_int(o2);
716 min = json_object_get_int(o_min);
717 max = json_object_get_int(o_max);
718
719 ret = v >= min && v <= max;
720 } else {
721 pa_log_warn("Got a format type that we don't support");
722 }
723
724 out:
725 if (o1)
726 json_object_put(o1);
727 if (o2)
728 json_object_put(o2);
729
730 return ret;
731 }