1 /*
2 * Copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 /**
22 * @file
23 * audio channel layout utility functions
24 */
25
26 #include <stdint.h>
27 #include <stdlib.h>
28 #include <string.h>
29
38
39 #define CHAN_IS_AMBI(x) ((x) >= AV_CHAN_AMBISONIC_BASE &&\
40 (x) <= AV_CHAN_AMBISONIC_END)
41
45 };
46
82 };
83
85 {
98 else
100 }
101
103 {
104 AVBPrint bp;
105
106 if (!buf && buf_size)
108
111
112 if (bp.len >= INT_MAX)
114 return bp.len + 1;
115 }
116
118 {
131 else
133 }
134
136 {
137 AVBPrint bp;
138
139 if (!buf && buf_size)
141
144
145 if (bp.len >= INT_MAX)
147 return bp.len + 1;
148 }
149
151 {
153 char *endptr = (char *)str;
155
156 if (!strncmp(str, "AMBI", 4)) {
157 i = strtol(str + 4,
NULL, 0);
161 }
162
166 }
167 if (!strcmp(str, "UNK"))
169 if (!strcmp(str, "UNSD"))
171
172 if (!strncmp(str, "USR", 3)) {
173 const char *p = str + 3;
174 id = strtol(p, &endptr, 0);
175 }
176 if (id >= 0 && !*endptr)
178
180 }
181
185 };
186
225 };
226
228 {
230
231 if (nb_channels <= 0)
233
237 for (
int i = 0;
i < nb_channels;
i++)
239
243
244 return 0;
245 }
246
249 {
252
256
257 return 0;
258 }
259
261 {
263 int nb_channels = 0;
266
267 while (*str) {
273 }
274 if (*str)
275 str++; // skip separator
279 }
287 }
288
292 }
293
294 if (!nb_channels)
296
300
303
304 return 0;
305 }
306
308 const char *str)
309 {
312 char *chlist, *end;
314
315 /* channel layout names */
319 return 0;
320 }
321 }
322
323 /* This function is a channel layout initializer, so we have to
324 * zero-initialize before we start setting fields individually. */
325 memset(channel_layout, 0, sizeof(*channel_layout));
326
327 /* ambisonic */
328 if (!strncmp(str, "ambisonic ", 10)) {
329 const char *p = str + 10;
330 char *endptr;
332 int order;
333
334 order = strtol(p, &endptr, 0);
335 if (order < 0 || order + 1 > INT_MAX / (order + 1) ||
336 (*endptr && *endptr != '+'))
338
340 channel_layout->
nb_channels = (order + 1) * (order + 1);
341
342 if (*endptr) {
349 }
350
353 } else {
355 channel_layout->
u.
map =
357 sizeof(*channel_layout->
u.
map));
358 if (!channel_layout->
u.
map) {
361 }
362
371 }
378 }
379 }
382 }
383
384 return 0;
385 }
386
388 if (!chlist)
390
391 /* channel names */
392 matches =
av_sscanf(str,
"%d channels (%[^)]", &nb_channels, chlist);
397
399 end = strchr(str, ')');
400 if (matches == 2 && (nb_channels != channel_layout->
nb_channels || !end || *++end)) {
403 }
404 return 0;
405 }
406
407 errno = 0;
408 mask = strtoull(str, &end, 0);
409
410 /* channel layout mask */
411 if (!errno && !*end && !strchr(str,
'-') &&
mask) {
413 return 0;
414 }
415
416 errno = 0;
418
419 /* number of channels */
420 if (!errno && !strcmp(end,
"c") &&
channels > 0) {
423 return 0;
424 }
425
426 /* number of unordered channels */
427 if (!errno && (!strcmp(end, "C") || !strcmp(end, " channels"))
431 return 0;
432 }
433
435 }
436
438 {
441 memset(channel_layout, 0, sizeof(*channel_layout));
442 }
443
445 {
452 memcpy(
dst->u.map,
src->u.map,
src->nb_channels *
sizeof(*
src->u.map));
453 }
454 return 0;
455 }
456
458 {
460 for (
int i = start_channel;
i < channel_layout->
nb_channels;
i++) {
462 if (ch >= 0 && ch < 63 &&
mask < (1ULL << ch))
463 mask |= (1ULL << ch);
464 else
466 }
468 }
469
471 {
473 return 0;
476 return 1;
477 return 0;
478 }
479
481 {
482 int i, highest_ambi, order;
483
487
488 highest_ambi = -1;
491 else {
494
497
498 /* ambisonic following non-ambisonic */
501
502 /* non-default ordering */
505
508 }
509 }
510 /* no ambisonic channels*/
511 if (highest_ambi < 0)
513
514 order =
floor(sqrt(highest_ambi));
515 /* incomplete order - some harmonics are missing */
516 if ((order + 1) * (order + 1) != highest_ambi + 1)
518
519 return order;
520 }
521
523 {
524 int has_known_channel = 0;
525 int order;
526
528 return channel_layout->
order;
529
532
533 for (
int i = 0;
i < channel_layout->
nb_channels && !has_known_channel;
i++)
535 has_known_channel = 1;
536 if (!has_known_channel)
538
541
545
547 }
548
549 /**
550 * If the custom layout is n-th order standard-order ambisonic, with optional
551 * extra non-diegetic channels at the end, write its string description in bp.
552 * Return a negative error code otherwise.
553 */
555 {
556 int nb_ambi_channels;
558 if (order < 0)
559 return order;
560
562
563 /* extra channels present */
564 nb_ambi_channels = (order + 1) * (order + 1);
565 if (nb_ambi_channels < channel_layout->nb_channels) {
567
572 } else {
579 } else {
582 extra.
u.
map = channel_layout->
u.
map + nb_ambi_channels;
583 }
584 }
585
588 /* Not calling uninit here on extra because we don't own the u.map pointer */
589 }
590
591 return 0;
592 }
593
595 AVBPrint *bp)
596 {
598
599 switch (channel_layout->
order) {
604 return 0;
605 }
606 // fall-through
611 if (res >= 0)
612 return 0;
619 }
620 }
625
632 }
635 return 0;
636 }
637 // fall-through
640 return 0;
643 default:
645 }
646 }
647
649 char *buf, size_t buf_size)
650 {
651 AVBPrint bp;
653
654 if (!buf && buf_size)
656
661
662 if (bp.len >= INT_MAX)
664 return bp.len + 1;
665 }
666
669 unsigned int idx)
670 {
672
675
676 switch (channel_layout->
order) {
678 return channel_layout->
u.
map[idx].
id;
681 if (idx < ambi_channels)
683 idx -= ambi_channels;
684 }
685 // fall-through
687 for (
i = 0;
i < 64;
i++) {
688 if ((1ULL <<
i) & channel_layout->
u.
mask && !idx--)
690 }
691 default:
693 }
694 }
695
698 const char *str)
699 {
701
704
706 }
707
710 {
712
715
716 switch (channel_layout->
order) {
731 }
736 }
737 default:
739 }
740 }
741
743 const char *str)
744 {
745 char *chname;
747
748 switch (channel_layout->
order) {
750 chname = strstr(str, "@");
751 if (chname) {
752 char buf[16];
753 chname++;
755 if (!*chname)
760 }
762 if (!strcmp(chname, channel_layout->
u.
map[
i].
name) &&
765 }
766 // fall-through
773 }
774
776 }
777
779 {
781 return 0;
782
783 switch (channel_layout->
order) {
787 if (!channel_layout->
u.
map)
788 return 0;
791 return 0;
792 }
793 return 1;
795 /* If non-diegetic channels are present, ensure they are taken into account */
798 return 1;
799 default:
800 return 0;
801 }
802 }
803
805 {
807
808 /* different channel counts -> not equal */
810 return 1;
811
812 /* if only one is unspecified -> not equal */
815 return 1;
816 /* both are unspecified -> equal */
818 return 0;
819
820 /* can compare masks directly */
825
826 /* compare channel by channel */
830 return 1;
831 return 0;
832 }
833
835 {
840 return;
841 }
842
845 }
846
848 {
849 uintptr_t
i = (uintptr_t)*opaque;
851
854 *opaque = (
void*)(
i + 1);
855 }
856
857 return ch_layout;
858 }
859
862 {
865
866 switch (channel_layout->
order) {
871 for (
i = 0;
i < 64;
i++)
874 break;
875 }
876
878 }
879
881 {
883 int lossy;
884
887
890
891 if (channel_layout->
order == order)
892 return 0;
893
894 switch (order) {
898 lossy = 0;
899 for (
int i = 0;
i < nb_channels;
i++) {
901 lossy = 1;
902 break;
903 }
904 }
905 } else {
906 lossy = 1;
907 }
908 if (!lossy || allow_lossy) {
909 void *opaque = channel_layout->
opaque;
913 channel_layout->
opaque = opaque;
914 return lossy;
915 }
917 }
924 if (!lossy || allow_lossy) {
925 void *opaque = channel_layout->
opaque;
928 channel_layout->
opaque = opaque;
929 return lossy;
930 }
931 }
936 void *opaque = channel_layout->
opaque;
943 *channel_layout = custom;
944 channel_layout->
opaque = opaque;
945 return 0;
946 }
952 if (order < 0)
958 if (!lossy || allow_lossy) {
959 void *opaque = channel_layout->
opaque;
964 channel_layout->
opaque = opaque;
965 return lossy;
966 }
967 }
969 default:
971 }
972 }