1 /*
2 * Copyright (c) 2021 James Almer
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 #include "libavutil/channel_layout.c"
22
23 #define CHANNEL_NAME(x) \
24 av_bprint_clear(&bp); \
25 av_channel_name_bprint(&bp, x);
26
27 #define CHANNEL_DESCRIPTION(x) \
28 av_bprint_clear(&bp); \
29 av_channel_description_bprint(&bp, x);
30
31 #define CHANNEL_LAYOUT_FROM_MASK(x) \
32 av_channel_layout_uninit(&layout); \
33 av_bprint_clear(&bp); \
34 if (!av_channel_layout_from_mask(&layout, x) && \
35 av_channel_layout_check(&layout)) \
36 av_channel_layout_describe_bprint(&layout, &bp); \
37 else \
38 av_bprintf(&bp, "fail");
39
40 #define CHANNEL_LAYOUT_FROM_STRING(x) \
41 av_channel_layout_uninit(&layout); \
42 av_bprint_clear(&bp); \
43 if (!av_channel_layout_from_string(&layout, x) && \
44 av_channel_layout_check(&layout)) \
45 av_channel_layout_describe_bprint(&layout, &bp); \
46 else \
47 av_bprintf(&bp, "fail");
48
49 #define CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(x) \
50 ret = av_channel_layout_channel_from_index(&layout, x); \
51 if (ret < 0) \
52 ret = -1
53
54 #define CHANNEL_LAYOUT_SUBSET(x) \
55 mask = av_channel_layout_subset(&layout, x)
56
57 #define CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(x) \
58 ret = av_channel_layout_index_from_channel(&layout, x); \
59 if (ret < 0) \
60 ret = -1
61
62 #define CHANNEL_LAYOUT_CHANNEL_FROM_STRING(x) \
63 ret = av_channel_layout_channel_from_string(&layout, x); \
64 if (ret < 0) \
65 ret = -1
66
67 #define CHANNEL_LAYOUT_INDEX_FROM_STRING(x) \
68 ret = av_channel_layout_index_from_string(&layout, x); \
69 if (ret < 0) \
70 ret = -1
71
main(void)72 int main(void)
73 {
74 const AVChannelLayout *playout;
75 AVChannelLayout layout = { 0 };
76 AVBPrint bp;
77 void *iter = NULL;
78 uint64_t mask;
79 int ret;
80
81 av_bprint_init(&bp, 64, AV_BPRINT_SIZE_AUTOMATIC);
82
83 printf("Testing av_channel_layout_standard\n");
84 while (playout = av_channel_layout_standard(&iter)) {
85 av_channel_layout_describe_bprint(playout, &bp);
86 printf("%-14s ", bp.str);
87 av_bprint_clear(&bp);
88 for (int i = 0; i < 63; i++) {
89 int idx = av_channel_layout_index_from_channel(playout, i);
90 if (idx >= 0) {
91 if (idx)
92 av_bprintf(&bp, "+");
93 av_channel_name_bprint(&bp, i);
94 }
95 }
96 printf("%s\n", bp.str);
97 av_bprint_clear(&bp);
98 }
99
100 printf("\nTesting av_channel_name\n");
101 CHANNEL_NAME(AV_CHAN_FRONT_LEFT);
102 printf("With AV_CHAN_FRONT_LEFT: %27s\n", bp.str);
103 CHANNEL_NAME(AV_CHAN_FRONT_RIGHT);
104 printf("With AV_CHAN_FRONT_RIGHT: %26s\n", bp.str);
105 CHANNEL_NAME(63);
106 printf("With 63: %43s\n", bp.str);
107 CHANNEL_NAME(AV_CHAN_AMBISONIC_BASE);
108 printf("With AV_CHAN_AMBISONIC_BASE: %23s\n", bp.str);
109 CHANNEL_NAME(AV_CHAN_AMBISONIC_END);
110 printf("With AV_CHAN_AMBISONIC_END: %24s\n", bp.str);
111
112 printf("Testing av_channel_description\n");
113 CHANNEL_DESCRIPTION(AV_CHAN_FRONT_LEFT);
114 printf("With AV_CHAN_FRONT_LEFT: %27s\n", bp.str);
115 CHANNEL_DESCRIPTION(AV_CHAN_FRONT_RIGHT);
116 printf("With AV_CHAN_FRONT_RIGHT: %26s\n", bp.str);
117 CHANNEL_DESCRIPTION(63);
118 printf("With 63: %43s\n", bp.str);
119 CHANNEL_DESCRIPTION(AV_CHAN_AMBISONIC_BASE);
120 printf("With AV_CHAN_AMBISONIC_BASE: %23s\n", bp.str);
121 CHANNEL_DESCRIPTION(AV_CHAN_AMBISONIC_END);
122 printf("With AV_CHAN_AMBISONIC_END: %24s\n", bp.str);
123
124 printf("\nTesting av_channel_from_string\n");
125 printf("With \"FL\": %41d\n", av_channel_from_string("FL"));
126 printf("With \"FR\": %41d\n", av_channel_from_string("FR"));
127 printf("With \"USR63\": %38d\n", av_channel_from_string("USR63"));
128 printf("With \"AMBI0\": %38d\n", av_channel_from_string("AMBI0"));
129 printf("With \"AMBI1023\": %35d\n", av_channel_from_string("AMBI1023"));
130
131 printf("\n==Native layouts==\n");
132
133 printf("\nTesting av_channel_layout_from_string\n");
134 CHANNEL_LAYOUT_FROM_STRING("0x3f");
135 printf("With \"0x3f\": %39s\n", bp.str);
136 CHANNEL_LAYOUT_FROM_STRING("63");
137 printf("With \"63\": %41s\n", bp.str);
138 CHANNEL_LAYOUT_FROM_STRING("6c");
139 printf("With \"6c\": %41s\n", bp.str);
140 CHANNEL_LAYOUT_FROM_STRING("6C");
141 printf("With \"6C\": %41s\n", bp.str);
142 CHANNEL_LAYOUT_FROM_STRING("6 channels");
143 printf("With \"6 channels\": %33s\n", bp.str);
144 CHANNEL_LAYOUT_FROM_STRING("6 channels (FL+FR+FC+LFE+BL+BR)");
145 printf("With \"6 channels (FL+FR+FC+LFE+BL+BR)\": %12s\n", bp.str);
146 CHANNEL_LAYOUT_FROM_STRING("FL+FR+FC+LFE+BL+BR");
147 printf("With \"FL+FR+FC+LFE+BL+BR\": %25s\n", bp.str);
148 CHANNEL_LAYOUT_FROM_STRING("5.1");
149 printf("With \"5.1\": %40s\n", bp.str);
150 CHANNEL_LAYOUT_FROM_STRING("FL+FR+USR63");
151 printf("With \"FL+FR+USR63\": %32s\n", bp.str);
152 CHANNEL_LAYOUT_FROM_STRING("FL+FR+FC+LFE+SL+SR");
153 printf("With \"FL+FR+FC+LFE+SL+SR\": %25s\n", bp.str);
154 CHANNEL_LAYOUT_FROM_STRING("5.1(side)");
155 printf("With \"5.1(side)\": %34s\n", bp.str);
156
157 printf("\nTesting av_channel_layout_from_mask\n");
158 CHANNEL_LAYOUT_FROM_MASK(AV_CH_LAYOUT_5POINT1);
159 printf("With AV_CH_LAYOUT_5POINT1: %25s\n", bp.str);
160
161 printf("\nTesting av_channel_layout_channel_from_index\n");
162 CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(0);
163 printf("On 5.1(side) layout with 0: %24d\n", ret);
164 CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(1);
165 printf("On 5.1(side) layout with 1: %24d\n", ret);
166 CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(2);
167 printf("On 5.1(side) layout with 2: %24d\n", ret);
168 CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(3);
169 printf("On 5.1(side) layout with 3: %24d\n", ret);
170 CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(4);
171 printf("On 5.1(side) layout with 4: %24d\n", ret);
172 CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(5);
173 printf("On 5.1(side) layout with 5: %24d\n", ret);
174 CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(6);
175 printf("On 5.1(side) layout with 6: %24d\n", ret);
176
177 printf("\nTesting av_channel_layout_index_from_channel\n");
178 CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(AV_CHAN_FRONT_LEFT);
179 printf("On 5.1(side) layout with AV_CHAN_FRONT_LEFT: %7d\n", ret);
180 CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(AV_CHAN_FRONT_RIGHT);
181 printf("On 5.1(side) layout with AV_CHAN_FRONT_RIGHT: %6d\n", ret);
182 CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(AV_CHAN_FRONT_CENTER);
183 printf("On 5.1(side) layout with AV_CHAN_FRONT_CENTER: %5d\n", ret);
184 CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(AV_CHAN_LOW_FREQUENCY);
185 printf("On 5.1(side) layout with AV_CHAN_LOW_FREQUENCY: %4d\n", ret);
186 CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(AV_CHAN_SIDE_LEFT);
187 printf("On 5.1(side) layout with AV_CHAN_SIDE_LEFT: %8d\n", ret);
188 CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(AV_CHAN_SIDE_RIGHT);
189 printf("On 5.1(side) layout with AV_CHAN_SIDE_RIGHT: %7d\n", ret);
190 CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(AV_CHAN_BACK_CENTER);
191 printf("On 5.1(side) layout with AV_CHAN_BACK_CENTER: %6d\n", ret);
192
193 printf("\nTesting av_channel_layout_channel_from_string\n");
194 CHANNEL_LAYOUT_CHANNEL_FROM_STRING("FL");
195 printf("On 5.1(side) layout with \"FL\": %21d\n", ret);
196 CHANNEL_LAYOUT_CHANNEL_FROM_STRING("FR");
197 printf("On 5.1(side) layout with \"FR\": %21d\n", ret);
198 CHANNEL_LAYOUT_CHANNEL_FROM_STRING("FC");
199 printf("On 5.1(side) layout with \"FC\": %21d\n", ret);
200 CHANNEL_LAYOUT_CHANNEL_FROM_STRING("LFE");
201 printf("On 5.1(side) layout with \"LFE\": %20d\n", ret);
202 CHANNEL_LAYOUT_CHANNEL_FROM_STRING("SL");
203 printf("On 5.1(side) layout with \"SL\": %21d\n", ret);
204 CHANNEL_LAYOUT_CHANNEL_FROM_STRING("SR");
205 printf("On 5.1(side) layout with \"SR\": %21d\n", ret);
206 CHANNEL_LAYOUT_CHANNEL_FROM_STRING("BC");
207 printf("On 5.1(side) layout with \"BC\": %21d\n", ret);
208
209 printf("\nTesting av_channel_layout_index_from_string\n");
210 CHANNEL_LAYOUT_INDEX_FROM_STRING("FL");
211 printf("On 5.1(side) layout with \"FL\": %21d\n", ret);
212 CHANNEL_LAYOUT_INDEX_FROM_STRING("FR");
213 printf("On 5.1(side) layout with \"FR\": %21d\n", ret);
214 CHANNEL_LAYOUT_INDEX_FROM_STRING("FC");
215 printf("On 5.1(side) layout with \"FC\": %21d\n", ret);
216 CHANNEL_LAYOUT_INDEX_FROM_STRING("LFE");
217 printf("On 5.1(side) layout with \"LFE\": %20d\n", ret);
218 CHANNEL_LAYOUT_INDEX_FROM_STRING("SL");
219 printf("On 5.1(side) layout with \"SL\": %21d\n", ret);
220 CHANNEL_LAYOUT_INDEX_FROM_STRING("SR");
221 printf("On 5.1(side) layout with \"SR\": %21d\n", ret);
222 CHANNEL_LAYOUT_INDEX_FROM_STRING("BC");
223 printf("On 5.1(side) layout with \"BC\": %21d\n", ret);
224
225 printf("\nTesting av_channel_layout_subset\n");
226 CHANNEL_LAYOUT_SUBSET(AV_CH_LAYOUT_STEREO);
227 printf("On 5.1(side) layout with AV_CH_LAYOUT_STEREO: 0x%"PRIx64"\n", mask);
228 CHANNEL_LAYOUT_SUBSET(AV_CH_LAYOUT_2POINT1);
229 printf("On 5.1(side) layout with AV_CH_LAYOUT_2POINT1: 0x%"PRIx64"\n", mask);
230 CHANNEL_LAYOUT_SUBSET(AV_CH_LAYOUT_4POINT1);
231 printf("On 5.1(side) layout with AV_CH_LAYOUT_4POINT1: 0x%"PRIx64"\n", mask);
232
233 printf("\n==Custom layouts==\n");
234
235 printf("\nTesting av_channel_layout_from_string\n");
236 CHANNEL_LAYOUT_FROM_STRING("FL+FR+FC+BL+BR+LFE");
237 printf("With \"FL+FR+FC+BL+BR+LFE\": %34s\n", bp.str);
238 CHANNEL_LAYOUT_FROM_STRING("2 channels (FR+FL)");
239 printf("With \"2 channels (FR+FL)\": %34s\n", bp.str);
240 CHANNEL_LAYOUT_FROM_STRING("ambisonic 1+FR+FL");
241 printf("With \"ambisonic 1+FR+FL\": %35s\n", bp.str);
242 CHANNEL_LAYOUT_FROM_STRING("ambisonic 2+FC@Foo");
243 printf("With \"ambisonic 2+FC@Foo\": %34s\n", bp.str);
244 CHANNEL_LAYOUT_FROM_STRING("FL@Foo+FR@Bar");
245 printf("With \"FL@Foo+FR@Bar\": %39s\n", bp.str);
246 CHANNEL_LAYOUT_FROM_STRING("FR+FL@Foo+USR63@Foo");
247 printf("With \"FR+FL@Foo+USR63@Foo\": %33s\n", bp.str);
248
249 printf("\nTesting av_channel_layout_index_from_string\n");
250 CHANNEL_LAYOUT_INDEX_FROM_STRING("FR");
251 printf("On \"FR+FL@Foo+USR63@Foo\" layout with \"FR\": %18d\n", ret);
252 CHANNEL_LAYOUT_INDEX_FROM_STRING("FL");
253 printf("On \"FR+FL@Foo+USR63@Foo\" layout with \"FL\": %18d\n", ret);
254 CHANNEL_LAYOUT_INDEX_FROM_STRING("USR63");
255 printf("On \"FR+FL@Foo+USR63@Foo\" layout with \"USR63\": %15d\n", ret);
256 CHANNEL_LAYOUT_INDEX_FROM_STRING("Foo");
257 printf("On \"FR+FL@Foo+USR63@Foo\" layout with \"Foo\": %17d\n", ret);
258 CHANNEL_LAYOUT_INDEX_FROM_STRING("@Foo");
259 printf("On \"FR+FL@Foo+USR63@Foo\" layout with \"@Foo\": %16d\n", ret);
260 CHANNEL_LAYOUT_INDEX_FROM_STRING("FR@Foo");
261 printf("On \"FR+FL@Foo+USR63@Foo\" layout with \"FR@Foo\": %14d\n", ret);
262 CHANNEL_LAYOUT_INDEX_FROM_STRING("FL@Foo");
263 printf("On \"FR+FL@Foo+USR63@Foo\" layout with \"FL@Foo\": %14d\n", ret);
264 CHANNEL_LAYOUT_INDEX_FROM_STRING("USR63@Foo");
265 printf("On \"FR+FL@Foo+USR63@Foo\" layout with \"USR63@Foo\": %11d\n", ret);
266 CHANNEL_LAYOUT_INDEX_FROM_STRING("BC");
267 printf("On \"FR+FL@Foo+USR63@Foo\" layout with \"BC\": %18d\n", ret);
268
269 printf("\nTesting av_channel_layout_channel_from_string\n");
270 CHANNEL_LAYOUT_CHANNEL_FROM_STRING("FR");
271 printf("On \"FR+FL@Foo+USR63@Foo\" layout with \"FR\": %18d\n", ret);
272 CHANNEL_LAYOUT_CHANNEL_FROM_STRING("FL");
273 printf("On \"FR+FL@Foo+USR63@Foo\" layout with \"FL\": %18d\n", ret);
274 CHANNEL_LAYOUT_CHANNEL_FROM_STRING("USR63");
275 printf("On \"FR+FL@Foo+USR63@Foo\" layout with \"USR63\": %15d\n", ret);
276 CHANNEL_LAYOUT_CHANNEL_FROM_STRING("Foo");
277 printf("On \"FR+FL@Foo+USR63@Foo\" layout with \"Foo\": %17d\n", ret);
278 CHANNEL_LAYOUT_CHANNEL_FROM_STRING("@Foo");
279 printf("On \"FR+FL@Foo+USR63@Foo\" layout with \"@Foo\": %16d\n", ret);
280 CHANNEL_LAYOUT_CHANNEL_FROM_STRING("FR@Foo");
281 printf("On \"FR+FL@Foo+USR63@Foo\" layout with \"FR@Foo\": %14d\n", ret);
282 CHANNEL_LAYOUT_CHANNEL_FROM_STRING("FL@Foo");
283 printf("On \"FR+FL@Foo+USR63@Foo\" layout with \"FL@Foo\": %14d\n", ret);
284 CHANNEL_LAYOUT_CHANNEL_FROM_STRING("USR63@Foo");
285 printf("On \"FR+FL@Foo+USR63@Foo\" layout with \"USR63@Foo\": %11d\n", ret);
286 CHANNEL_LAYOUT_CHANNEL_FROM_STRING("BC");
287 printf("On \"FR+FL@Foo+USR63@Foo\" layout with \"BC\": %18d\n", ret);
288
289 printf("\nTesting av_channel_layout_index_from_channel\n");
290 CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(AV_CHAN_FRONT_RIGHT);
291 printf("On \"FR+FL@Foo+USR63@Foo\" layout with AV_CHAN_FRONT_RIGHT: %3d\n", ret);
292 CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(AV_CHAN_FRONT_LEFT);
293 printf("On \"FR+FL@Foo+USR63@Foo\" layout with AV_CHAN_FRONT_LEFT: %4d\n", ret);
294 CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(63);
295 printf("On \"FR+FL@Foo+USR63@Foo\" layout with 63: %20d\n", ret);
296 CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(AV_CHAN_BACK_CENTER);
297 printf("On \"FR+FL@Foo+USR63@Foo\" layout with AV_CHAN_BACK_CENTER: %3d\n", ret);
298
299 printf("\nTesting av_channel_layout_channel_from_index\n");
300 CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(0);
301 printf("On \"FR+FL@Foo+USR63@Foo\" layout with 0: %21d\n", ret);
302 CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(1);
303 printf("On \"FR+FL@Foo+USR63@Foo\" layout with 1: %21d\n", ret);
304 CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(2);
305 printf("On \"FR+FL@Foo+USR63@Foo\" layout with 2: %21d\n", ret);
306 CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(3);
307 printf("On \"FR+FL@Foo+USR63@Foo\" layout with 3: %21d\n", ret);
308
309 printf("\nTesting av_channel_layout_subset\n");
310 CHANNEL_LAYOUT_SUBSET(AV_CH_LAYOUT_STEREO);
311 printf("On \"FR+FL@Foo+USR63@Foo\" layout with AV_CH_LAYOUT_STEREO: 0x%"PRIx64"\n", mask);
312 CHANNEL_LAYOUT_SUBSET(AV_CH_LAYOUT_QUAD);
313 printf("On \"FR+FL@Foo+USR63@Foo\" layout with AV_CH_LAYOUT_QUAD: 0x%"PRIx64"\n", mask);
314
315 printf("\n==Ambisonic layouts==\n");
316
317 printf("\nTesting av_channel_layout_from_string\n");
318 CHANNEL_LAYOUT_FROM_STRING("ambisonic 1");
319 printf("With \"ambisonic 1\": %41s\n", bp.str);
320 CHANNEL_LAYOUT_FROM_STRING("ambisonic 2+stereo");
321 printf("With \"ambisonic 2+stereo\": %34s\n", bp.str);
322
323 printf("\nTesting av_channel_layout_index_from_channel\n");
324 CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(AV_CHAN_AMBISONIC_BASE);
325 printf("On \"ambisonic 2+stereo\" layout with AV_CHAN_AMBISONIC_BASE: %d\n", ret);
326 CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(AV_CHAN_FRONT_LEFT);
327 printf("On \"ambisonic 2+stereo\" layout with AV_CHAN_FRONT_LEFT: %5d\n", ret);
328 CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(AV_CHAN_FRONT_RIGHT);
329 printf("On \"ambisonic 2+stereo\" layout with AV_CHAN_FRONT_RIGHT: %4d\n", ret);
330 CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(AV_CHAN_BACK_CENTER);
331 printf("On \"ambisonic 2+stereo\" layout with AV_CHAN_BACK_CENTER: %4d\n", ret);
332
333 printf("\nTesting av_channel_layout_channel_from_index\n");
334 CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(0);
335 printf("On \"ambisonic 2+stereo\" layout with 0: %22d\n", ret);
336 CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(9);
337 printf("On \"ambisonic 2+stereo\" layout with 9: %22d\n", ret);
338 CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(10);
339 printf("On \"ambisonic 2+stereo\" layout with 10: %21d\n", ret);
340 CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(11);
341 printf("On \"ambisonic 2+stereo\" layout with 11: %21d\n", ret);
342
343 printf("\nTesting av_channel_layout_subset\n");
344 CHANNEL_LAYOUT_SUBSET(AV_CH_LAYOUT_STEREO);
345 printf("On \"ambisonic 2+stereo\" layout with AV_CH_LAYOUT_STEREO: 0x%"PRIx64"\n", mask);
346 CHANNEL_LAYOUT_SUBSET(AV_CH_LAYOUT_QUAD);
347 printf("On \"ambisonic 2+stereo\" layout with AV_CH_LAYOUT_QUAD: 0x%"PRIx64"\n", mask);
348
349 av_channel_layout_uninit(&layout);
350 av_bprint_finalize(&bp, NULL);
351
352 return 0;
353 }
354