]> git.sesse.net Git - ffmpeg/blob - libavfilter/formats.c
Merge commit 'c24469e812501903a46a06eff9722a82e136e841'
[ffmpeg] / libavfilter / formats.c
1 /*
2  * Filter layer - format negotiation
3  * Copyright (c) 2007 Bobby Bingham
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21
22 #include "libavutil/avassert.h"
23 #include "libavutil/channel_layout.h"
24 #include "libavutil/common.h"
25 #include "libavutil/eval.h"
26 #include "libavutil/pixdesc.h"
27 #include "libavutil/parseutils.h"
28 #include "avfilter.h"
29 #include "internal.h"
30 #include "formats.h"
31
32 #define KNOWN(l) (!FF_LAYOUT2COUNT(l)) /* for readability */
33
34 /**
35  * Add all refs from a to ret and destroy a.
36  */
37 #define MERGE_REF(ret, a, fmts, type, fail)                                \
38 do {                                                                       \
39     type ***tmp;                                                           \
40     int i;                                                                 \
41                                                                            \
42     if (!(tmp = av_realloc(ret->refs,                                      \
43                            sizeof(*tmp) * (ret->refcount + a->refcount)))) \
44         goto fail;                                                         \
45     ret->refs = tmp;                                                       \
46                                                                            \
47     for (i = 0; i < a->refcount; i ++) {                                   \
48         ret->refs[ret->refcount] = a->refs[i];                             \
49         *ret->refs[ret->refcount++] = ret;                                 \
50     }                                                                      \
51                                                                            \
52     av_freep(&a->refs);                                                    \
53     av_freep(&a->fmts);                                                    \
54     av_freep(&a);                                                          \
55 } while (0)
56
57 /**
58  * Add all formats common for a and b to ret, copy the refs and destroy
59  * a and b.
60  */
61 #define MERGE_FORMATS(ret, a, b, fmts, nb, type, fail)                          \
62 do {                                                                            \
63     int i, j, k = 0, count = FFMIN(a->nb, b->nb);                               \
64                                                                                 \
65     if (!(ret = av_mallocz(sizeof(*ret))))                                      \
66         goto fail;                                                              \
67                                                                                 \
68     if (count) {                                                                \
69         if (!(ret->fmts = av_malloc(sizeof(*ret->fmts) * count)))               \
70             goto fail;                                                          \
71         for (i = 0; i < a->nb; i++)                                             \
72             for (j = 0; j < b->nb; j++)                                         \
73                 if (a->fmts[i] == b->fmts[j]) {                                 \
74                     if(k >= FFMIN(a->nb, b->nb)){                               \
75                         av_log(NULL, AV_LOG_ERROR, "Duplicate formats in avfilter_merge_formats() detected\n"); \
76                         av_free(ret->fmts);                                     \
77                         av_free(ret);                                           \
78                         return NULL;                                            \
79                     }                                                           \
80                     ret->fmts[k++] = a->fmts[i];                                \
81                 }                                                               \
82     }                                                                           \
83     ret->nb = k;                                                                \
84     /* check that there was at least one common format */                       \
85     if (!ret->nb)                                                               \
86         goto fail;                                                              \
87                                                                                 \
88     MERGE_REF(ret, a, fmts, type, fail);                                        \
89     MERGE_REF(ret, b, fmts, type, fail);                                        \
90 } while (0)
91
92 AVFilterFormats *ff_merge_formats(AVFilterFormats *a, AVFilterFormats *b,
93                                   enum AVMediaType type)
94 {
95     AVFilterFormats *ret = NULL;
96     int i, j;
97     int alpha1=0, alpha2=0;
98     int chroma1=0, chroma2=0;
99
100     if (a == b)
101         return a;
102
103     /* Do not lose chroma or alpha in merging.
104        It happens if both lists have formats with chroma (resp. alpha), but
105        the only formats in common do not have it (e.g. YUV+gray vs.
106        RGB+gray): in that case, the merging would select the gray format,
107        possibly causing a lossy conversion elsewhere in the graph.
108        To avoid that, pretend that there are no common formats to force the
109        insertion of a conversion filter. */
110     if (type == AVMEDIA_TYPE_VIDEO)
111         for (i = 0; i < a->format_count; i++)
112             for (j = 0; j < b->format_count; j++) {
113                 const AVPixFmtDescriptor *adesc = av_pix_fmt_desc_get(a->formats[i]);
114                 const AVPixFmtDescriptor *bdesc = av_pix_fmt_desc_get(b->formats[j]);
115                 alpha2 |= adesc->flags & bdesc->flags & PIX_FMT_ALPHA;
116                 chroma2|= adesc->nb_components > 1 && bdesc->nb_components > 1;
117                 if (a->formats[i] == b->formats[j]) {
118                     alpha1 |= adesc->flags & PIX_FMT_ALPHA;
119                     chroma1|= adesc->nb_components > 1;
120                 }
121             }
122
123     // If chroma or alpha can be lost through merging then do not merge
124     if (alpha2 > alpha1 || chroma2 > chroma1)
125         return NULL;
126
127     MERGE_FORMATS(ret, a, b, formats, format_count, AVFilterFormats, fail);
128
129     return ret;
130 fail:
131     if (ret) {
132         av_freep(&ret->refs);
133         av_freep(&ret->formats);
134     }
135     av_freep(&ret);
136     return NULL;
137 }
138
139 AVFilterFormats *ff_merge_samplerates(AVFilterFormats *a,
140                                       AVFilterFormats *b)
141 {
142     AVFilterFormats *ret = NULL;
143
144     if (a == b) return a;
145
146     if (a->format_count && b->format_count) {
147         MERGE_FORMATS(ret, a, b, formats, format_count, AVFilterFormats, fail);
148     } else if (a->format_count) {
149         MERGE_REF(a, b, formats, AVFilterFormats, fail);
150         ret = a;
151     } else {
152         MERGE_REF(b, a, formats, AVFilterFormats, fail);
153         ret = b;
154     }
155
156     return ret;
157 fail:
158     if (ret) {
159         av_freep(&ret->refs);
160         av_freep(&ret->formats);
161     }
162     av_freep(&ret);
163     return NULL;
164 }
165
166 AVFilterChannelLayouts *ff_merge_channel_layouts(AVFilterChannelLayouts *a,
167                                                  AVFilterChannelLayouts *b)
168 {
169     AVFilterChannelLayouts *ret = NULL;
170     unsigned a_all = a->all_layouts + a->all_counts;
171     unsigned b_all = b->all_layouts + b->all_counts;
172     int ret_max, ret_nb = 0, i, j, round;
173
174     if (a == b) return a;
175
176     /* Put the most generic set in a, to avoid doing everything twice */
177     if (a_all < b_all) {
178         FFSWAP(AVFilterChannelLayouts *, a, b);
179         FFSWAP(unsigned, a_all, b_all);
180     }
181     if (a_all) {
182         if (a_all == 1 && !b_all) {
183             /* keep only known layouts in b; works also for b_all = 1 */
184             for (i = j = 0; i < b->nb_channel_layouts; i++)
185                 if (KNOWN(b->channel_layouts[i]))
186                     b->channel_layouts[j++] = b->channel_layouts[i];
187             b->nb_channel_layouts = j;
188         }
189         MERGE_REF(b, a, channel_layouts, AVFilterChannelLayouts, fail);
190         return b;
191     }
192
193     ret_max = a->nb_channel_layouts + b->nb_channel_layouts;
194     if (!(ret = av_mallocz(sizeof(*ret))) ||
195         !(ret->channel_layouts = av_malloc(sizeof(*ret->channel_layouts) *
196                                            ret_max)))
197         goto fail;
198
199     /* a[known] intersect b[known] */
200     for (i = 0; i < a->nb_channel_layouts; i++) {
201         if (!KNOWN(a->channel_layouts[i]))
202             continue;
203         for (j = 0; j < b->nb_channel_layouts; j++) {
204             if (a->channel_layouts[i] == b->channel_layouts[j]) {
205                 ret->channel_layouts[ret_nb++] = a->channel_layouts[i];
206                 a->channel_layouts[i] = b->channel_layouts[j] = 0;
207             }
208         }
209     }
210     /* 1st round: a[known] intersect b[generic]
211        2nd round: a[generic] intersect b[known] */
212     for (round = 0; round < 2; round++) {
213         for (i = 0; i < a->nb_channel_layouts; i++) {
214             uint64_t fmt = a->channel_layouts[i], bfmt;
215             if (!fmt || !KNOWN(fmt))
216                 continue;
217             bfmt = FF_COUNT2LAYOUT(av_get_channel_layout_nb_channels(fmt));
218             for (j = 0; j < b->nb_channel_layouts; j++)
219                 if (b->channel_layouts[j] == bfmt)
220                     ret->channel_layouts[ret_nb++] = a->channel_layouts[i];
221         }
222         /* 1st round: swap to prepare 2nd round; 2nd round: put it back */
223         FFSWAP(AVFilterChannelLayouts *, a, b);
224     }
225     /* a[generic] intersect b[generic] */
226     for (i = 0; i < a->nb_channel_layouts; i++) {
227         if (KNOWN(a->channel_layouts[i]))
228             continue;
229         for (j = 0; j < b->nb_channel_layouts; j++)
230             if (a->channel_layouts[i] == b->channel_layouts[j])
231                 ret->channel_layouts[ret_nb++] = a->channel_layouts[i];
232     }
233
234     ret->nb_channel_layouts = ret_nb;
235     if (!ret->nb_channel_layouts)
236         goto fail;
237     MERGE_REF(ret, a, channel_layouts, AVFilterChannelLayouts, fail);
238     MERGE_REF(ret, b, channel_layouts, AVFilterChannelLayouts, fail);
239     return ret;
240
241 fail:
242     if (ret) {
243         av_freep(&ret->refs);
244         av_freep(&ret->channel_layouts);
245     }
246     av_freep(&ret);
247     return NULL;
248 }
249
250 int ff_fmt_is_in(int fmt, const int *fmts)
251 {
252     const int *p;
253
254     for (p = fmts; *p != -1; p++) {
255         if (fmt == *p)
256             return 1;
257     }
258     return 0;
259 }
260
261 #define COPY_INT_LIST(list_copy, list, type) {                          \
262     int count = 0;                                                      \
263     if (list)                                                           \
264         for (count = 0; list[count] != -1; count++)                     \
265             ;                                                           \
266     list_copy = av_calloc(count+1, sizeof(type));                       \
267     if (list_copy) {                                                    \
268         memcpy(list_copy, list, sizeof(type) * count);                  \
269         list_copy[count] = -1;                                          \
270     }                                                                   \
271 }
272
273 int *ff_copy_int_list(const int * const list)
274 {
275     int *ret = NULL;
276     COPY_INT_LIST(ret, list, int);
277     return ret;
278 }
279
280 int64_t *ff_copy_int64_list(const int64_t * const list)
281 {
282     int64_t *ret = NULL;
283     COPY_INT_LIST(ret, list, int64_t);
284     return ret;
285 }
286
287 #define MAKE_FORMAT_LIST(type, field, count_field)                      \
288     type *formats;                                                      \
289     int count = 0;                                                      \
290     if (fmts)                                                           \
291         for (count = 0; fmts[count] != -1; count++)                     \
292             ;                                                           \
293     formats = av_mallocz(sizeof(*formats));                             \
294     if (!formats) return NULL;                                          \
295     formats->count_field = count;                                       \
296     if (count) {                                                        \
297         formats->field = av_malloc(sizeof(*formats->field)*count);      \
298         if (!formats->field) {                                          \
299             av_free(formats);                                           \
300             return NULL;                                                \
301         }                                                               \
302     }
303
304 AVFilterFormats *ff_make_format_list(const int *fmts)
305 {
306     MAKE_FORMAT_LIST(AVFilterFormats, formats, format_count);
307     while (count--)
308         formats->formats[count] = fmts[count];
309
310     return formats;
311 }
312
313 AVFilterChannelLayouts *avfilter_make_format64_list(const int64_t *fmts)
314 {
315     MAKE_FORMAT_LIST(AVFilterChannelLayouts,
316                      channel_layouts, nb_channel_layouts);
317     if (count)
318         memcpy(formats->channel_layouts, fmts,
319                sizeof(*formats->channel_layouts) * count);
320
321     return formats;
322 }
323
324 #define ADD_FORMAT(f, fmt, type, list, nb)                  \
325 do {                                                        \
326     type *fmts;                                             \
327                                                             \
328     if (!(*f) && !(*f = av_mallocz(sizeof(**f))))           \
329         return AVERROR(ENOMEM);                             \
330                                                             \
331     fmts = av_realloc((*f)->list,                           \
332                       sizeof(*(*f)->list) * ((*f)->nb + 1));\
333     if (!fmts)                                              \
334         return AVERROR(ENOMEM);                             \
335                                                             \
336     (*f)->list = fmts;                                      \
337     (*f)->list[(*f)->nb++] = fmt;                           \
338 } while (0)
339
340 int ff_add_format(AVFilterFormats **avff, int64_t fmt)
341 {
342     ADD_FORMAT(avff, fmt, int, formats, format_count);
343     return 0;
344 }
345
346 int ff_add_channel_layout(AVFilterChannelLayouts **l, uint64_t channel_layout)
347 {
348     av_assert1(!(*l && (*l)->all_layouts));
349     ADD_FORMAT(l, channel_layout, uint64_t, channel_layouts, nb_channel_layouts);
350     return 0;
351 }
352
353 AVFilterFormats *ff_all_formats(enum AVMediaType type)
354 {
355     AVFilterFormats *ret = NULL;
356     int fmt;
357     int num_formats = type == AVMEDIA_TYPE_VIDEO ? AV_PIX_FMT_NB    :
358                       type == AVMEDIA_TYPE_AUDIO ? AV_SAMPLE_FMT_NB : 0;
359
360     for (fmt = 0; fmt < num_formats; fmt++) {
361         const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt);
362         if ((type != AVMEDIA_TYPE_VIDEO) ||
363             (type == AVMEDIA_TYPE_VIDEO && !(desc->flags & PIX_FMT_HWACCEL)))
364             ff_add_format(&ret, fmt);
365     }
366
367     return ret;
368 }
369
370 const int64_t avfilter_all_channel_layouts[] = {
371 #include "all_channel_layouts.inc"
372     -1
373 };
374
375 // AVFilterFormats *avfilter_make_all_channel_layouts(void)
376 // {
377 //     return avfilter_make_format64_list(avfilter_all_channel_layouts);
378 // }
379
380 AVFilterFormats *ff_planar_sample_fmts(void)
381 {
382     AVFilterFormats *ret = NULL;
383     int fmt;
384
385     for (fmt = 0; fmt < AV_SAMPLE_FMT_NB; fmt++)
386         if (av_sample_fmt_is_planar(fmt))
387             ff_add_format(&ret, fmt);
388
389     return ret;
390 }
391
392 AVFilterFormats *ff_all_samplerates(void)
393 {
394     AVFilterFormats *ret = av_mallocz(sizeof(*ret));
395     return ret;
396 }
397
398 AVFilterChannelLayouts *ff_all_channel_layouts(void)
399 {
400     AVFilterChannelLayouts *ret = av_mallocz(sizeof(*ret));
401     if (!ret)
402         return NULL;
403     ret->all_layouts = 1;
404     return ret;
405 }
406
407 AVFilterChannelLayouts *ff_all_channel_counts(void)
408 {
409     AVFilterChannelLayouts *ret = av_mallocz(sizeof(*ret));
410     if (!ret)
411         return NULL;
412     ret->all_layouts = ret->all_counts = 1;
413     return ret;
414 }
415
416 #define FORMATS_REF(f, ref)                                          \
417 do {                                                                 \
418     *ref = f;                                                        \
419     f->refs = av_realloc(f->refs, sizeof(*f->refs) * ++f->refcount); \
420     f->refs[f->refcount-1] = ref;                                    \
421 } while (0)
422
423 void ff_channel_layouts_ref(AVFilterChannelLayouts *f, AVFilterChannelLayouts **ref)
424 {
425     FORMATS_REF(f, ref);
426 }
427
428 void ff_formats_ref(AVFilterFormats *f, AVFilterFormats **ref)
429 {
430     FORMATS_REF(f, ref);
431 }
432
433 #define FIND_REF_INDEX(ref, idx)            \
434 do {                                        \
435     int i;                                  \
436     for (i = 0; i < (*ref)->refcount; i ++) \
437         if((*ref)->refs[i] == ref) {        \
438             idx = i;                        \
439             break;                          \
440         }                                   \
441 } while (0)
442
443 #define FORMATS_UNREF(ref, list)                                   \
444 do {                                                               \
445     int idx = -1;                                                  \
446                                                                    \
447     if (!*ref)                                                     \
448         return;                                                    \
449                                                                    \
450     FIND_REF_INDEX(ref, idx);                                      \
451                                                                    \
452     if (idx >= 0)                                                  \
453         memmove((*ref)->refs + idx, (*ref)->refs + idx + 1,        \
454             sizeof(*(*ref)->refs) * ((*ref)->refcount - idx - 1)); \
455                                                                    \
456     if(!--(*ref)->refcount) {                                      \
457         av_free((*ref)->list);                                     \
458         av_free((*ref)->refs);                                     \
459         av_free(*ref);                                             \
460     }                                                              \
461     *ref = NULL;                                                   \
462 } while (0)
463
464 void ff_formats_unref(AVFilterFormats **ref)
465 {
466     FORMATS_UNREF(ref, formats);
467 }
468
469 void ff_channel_layouts_unref(AVFilterChannelLayouts **ref)
470 {
471     FORMATS_UNREF(ref, channel_layouts);
472 }
473
474 #define FORMATS_CHANGEREF(oldref, newref)       \
475 do {                                            \
476     int idx = -1;                               \
477                                                 \
478     FIND_REF_INDEX(oldref, idx);                \
479                                                 \
480     if (idx >= 0) {                             \
481         (*oldref)->refs[idx] = newref;          \
482         *newref = *oldref;                      \
483         *oldref = NULL;                         \
484     }                                           \
485 } while (0)
486
487 void ff_channel_layouts_changeref(AVFilterChannelLayouts **oldref,
488                                   AVFilterChannelLayouts **newref)
489 {
490     FORMATS_CHANGEREF(oldref, newref);
491 }
492
493 void ff_formats_changeref(AVFilterFormats **oldref, AVFilterFormats **newref)
494 {
495     FORMATS_CHANGEREF(oldref, newref);
496 }
497
498 #define SET_COMMON_FORMATS(ctx, fmts, in_fmts, out_fmts, ref, list) \
499 {                                                                   \
500     int count = 0, i;                                               \
501                                                                     \
502     for (i = 0; i < ctx->nb_inputs; i++) {                          \
503         if (ctx->inputs[i] && !ctx->inputs[i]->out_fmts) {          \
504             ref(fmts, &ctx->inputs[i]->out_fmts);                   \
505             count++;                                                \
506         }                                                           \
507     }                                                               \
508     for (i = 0; i < ctx->nb_outputs; i++) {                         \
509         if (ctx->outputs[i] && !ctx->outputs[i]->in_fmts) {         \
510             ref(fmts, &ctx->outputs[i]->in_fmts);                   \
511             count++;                                                \
512         }                                                           \
513     }                                                               \
514                                                                     \
515     if (!count) {                                                   \
516         av_freep(&fmts->list);                                      \
517         av_freep(&fmts->refs);                                      \
518         av_freep(&fmts);                                            \
519     }                                                               \
520 }
521
522 void ff_set_common_channel_layouts(AVFilterContext *ctx,
523                                    AVFilterChannelLayouts *layouts)
524 {
525     SET_COMMON_FORMATS(ctx, layouts, in_channel_layouts, out_channel_layouts,
526                        ff_channel_layouts_ref, channel_layouts);
527 }
528
529 void ff_set_common_samplerates(AVFilterContext *ctx,
530                                AVFilterFormats *samplerates)
531 {
532     SET_COMMON_FORMATS(ctx, samplerates, in_samplerates, out_samplerates,
533                        ff_formats_ref, formats);
534 }
535
536 /**
537  * A helper for query_formats() which sets all links to the same list of
538  * formats. If there are no links hooked to this filter, the list of formats is
539  * freed.
540  */
541 void ff_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats)
542 {
543     SET_COMMON_FORMATS(ctx, formats, in_formats, out_formats,
544                        ff_formats_ref, formats);
545 }
546
547 static int default_query_formats_common(AVFilterContext *ctx,
548                                         AVFilterChannelLayouts *(layouts)(void))
549 {
550     enum AVMediaType type = ctx->inputs  && ctx->inputs [0] ? ctx->inputs [0]->type :
551                             ctx->outputs && ctx->outputs[0] ? ctx->outputs[0]->type :
552                             AVMEDIA_TYPE_VIDEO;
553
554     ff_set_common_formats(ctx, ff_all_formats(type));
555     if (type == AVMEDIA_TYPE_AUDIO) {
556         ff_set_common_channel_layouts(ctx, layouts());
557         ff_set_common_samplerates(ctx, ff_all_samplerates());
558     }
559
560     return 0;
561 }
562
563 int ff_default_query_formats(AVFilterContext *ctx)
564 {
565     return default_query_formats_common(ctx, ff_all_channel_layouts);
566 }
567
568 int ff_query_formats_all(AVFilterContext *ctx)
569 {
570     return default_query_formats_common(ctx, ff_all_channel_counts);
571 }
572
573 /* internal functions for parsing audio format arguments */
574
575 int ff_parse_pixel_format(enum AVPixelFormat *ret, const char *arg, void *log_ctx)
576 {
577     char *tail;
578     int pix_fmt = av_get_pix_fmt(arg);
579     if (pix_fmt == AV_PIX_FMT_NONE) {
580         pix_fmt = strtol(arg, &tail, 0);
581         if (*tail || (unsigned)pix_fmt >= AV_PIX_FMT_NB) {
582             av_log(log_ctx, AV_LOG_ERROR, "Invalid pixel format '%s'\n", arg);
583             return AVERROR(EINVAL);
584         }
585     }
586     *ret = pix_fmt;
587     return 0;
588 }
589
590 int ff_parse_sample_format(int *ret, const char *arg, void *log_ctx)
591 {
592     char *tail;
593     int sfmt = av_get_sample_fmt(arg);
594     if (sfmt == AV_SAMPLE_FMT_NONE) {
595         sfmt = strtol(arg, &tail, 0);
596         if (*tail || (unsigned)sfmt >= AV_SAMPLE_FMT_NB) {
597             av_log(log_ctx, AV_LOG_ERROR, "Invalid sample format '%s'\n", arg);
598             return AVERROR(EINVAL);
599         }
600     }
601     *ret = sfmt;
602     return 0;
603 }
604
605 int ff_parse_time_base(AVRational *ret, const char *arg, void *log_ctx)
606 {
607     AVRational r;
608     if(av_parse_ratio(&r, arg, INT_MAX, 0, log_ctx) < 0 ||r.num<=0  ||r.den<=0) {
609         av_log(log_ctx, AV_LOG_ERROR, "Invalid time base '%s'\n", arg);
610         return AVERROR(EINVAL);
611     }
612     *ret = r;
613     return 0;
614 }
615
616 int ff_parse_sample_rate(int *ret, const char *arg, void *log_ctx)
617 {
618     char *tail;
619     double srate = av_strtod(arg, &tail);
620     if (*tail || srate < 1 || (int)srate != srate || srate > INT_MAX) {
621         av_log(log_ctx, AV_LOG_ERROR, "Invalid sample rate '%s'\n", arg);
622         return AVERROR(EINVAL);
623     }
624     *ret = srate;
625     return 0;
626 }
627
628 int ff_parse_channel_layout(int64_t *ret, const char *arg, void *log_ctx)
629 {
630     char *tail;
631     int64_t chlayout = av_get_channel_layout(arg);
632     if (chlayout == 0) {
633         chlayout = strtol(arg, &tail, 10);
634         if (*tail || chlayout == 0) {
635             av_log(log_ctx, AV_LOG_ERROR, "Invalid channel layout '%s'\n", arg);
636             return AVERROR(EINVAL);
637         }
638     }
639     *ret = chlayout;
640     return 0;
641 }
642
643 #ifdef TEST
644
645 #undef printf
646
647 int main(void)
648 {
649     const int64_t *cl;
650     char buf[512];
651
652     for (cl = avfilter_all_channel_layouts; *cl != -1; cl++) {
653         av_get_channel_layout_string(buf, sizeof(buf), -1, *cl);
654         printf("%s\n", buf);
655     }
656
657     return 0;
658 }
659
660 #endif
661