]> git.sesse.net Git - ffmpeg/blob - libavfilter/formats.c
Merge commit '3a16ec19d2426457419cb8a7304f97982699efda'
[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->nb_formats; i++)
112             for (j = 0; j < b->nb_formats; 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 & AV_PIX_FMT_FLAG_ALPHA;
116                 chroma2|= adesc->nb_components > 1 && bdesc->nb_components > 1;
117                 if (a->formats[i] == b->formats[j]) {
118                     alpha1 |= adesc->flags & AV_PIX_FMT_FLAG_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, nb_formats, 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->nb_formats && b->nb_formats) {
147         MERGE_FORMATS(ret, a, b, formats, nb_formats, AVFilterFormats, fail);
148     } else if (a->nb_formats) {
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             /* Not optimal: the unknown layouts of b may become known after
188                another merge. */
189             if (!j)
190                 return NULL;
191             b->nb_channel_layouts = j;
192         }
193         MERGE_REF(b, a, channel_layouts, AVFilterChannelLayouts, fail);
194         return b;
195     }
196
197     ret_max = a->nb_channel_layouts + b->nb_channel_layouts;
198     if (!(ret = av_mallocz(sizeof(*ret))) ||
199         !(ret->channel_layouts = av_malloc(sizeof(*ret->channel_layouts) *
200                                            ret_max)))
201         goto fail;
202
203     /* a[known] intersect b[known] */
204     for (i = 0; i < a->nb_channel_layouts; i++) {
205         if (!KNOWN(a->channel_layouts[i]))
206             continue;
207         for (j = 0; j < b->nb_channel_layouts; j++) {
208             if (a->channel_layouts[i] == b->channel_layouts[j]) {
209                 ret->channel_layouts[ret_nb++] = a->channel_layouts[i];
210                 a->channel_layouts[i] = b->channel_layouts[j] = 0;
211             }
212         }
213     }
214     /* 1st round: a[known] intersect b[generic]
215        2nd round: a[generic] intersect b[known] */
216     for (round = 0; round < 2; round++) {
217         for (i = 0; i < a->nb_channel_layouts; i++) {
218             uint64_t fmt = a->channel_layouts[i], bfmt;
219             if (!fmt || !KNOWN(fmt))
220                 continue;
221             bfmt = FF_COUNT2LAYOUT(av_get_channel_layout_nb_channels(fmt));
222             for (j = 0; j < b->nb_channel_layouts; j++)
223                 if (b->channel_layouts[j] == bfmt)
224                     ret->channel_layouts[ret_nb++] = a->channel_layouts[i];
225         }
226         /* 1st round: swap to prepare 2nd round; 2nd round: put it back */
227         FFSWAP(AVFilterChannelLayouts *, a, b);
228     }
229     /* a[generic] intersect b[generic] */
230     for (i = 0; i < a->nb_channel_layouts; i++) {
231         if (KNOWN(a->channel_layouts[i]))
232             continue;
233         for (j = 0; j < b->nb_channel_layouts; j++)
234             if (a->channel_layouts[i] == b->channel_layouts[j])
235                 ret->channel_layouts[ret_nb++] = a->channel_layouts[i];
236     }
237
238     ret->nb_channel_layouts = ret_nb;
239     if (!ret->nb_channel_layouts)
240         goto fail;
241     MERGE_REF(ret, a, channel_layouts, AVFilterChannelLayouts, fail);
242     MERGE_REF(ret, b, channel_layouts, AVFilterChannelLayouts, fail);
243     return ret;
244
245 fail:
246     if (ret) {
247         av_freep(&ret->refs);
248         av_freep(&ret->channel_layouts);
249     }
250     av_freep(&ret);
251     return NULL;
252 }
253
254 int ff_fmt_is_in(int fmt, const int *fmts)
255 {
256     const int *p;
257
258     for (p = fmts; *p != -1; p++) {
259         if (fmt == *p)
260             return 1;
261     }
262     return 0;
263 }
264
265 #define COPY_INT_LIST(list_copy, list, type) {                          \
266     int count = 0;                                                      \
267     if (list)                                                           \
268         for (count = 0; list[count] != -1; count++)                     \
269             ;                                                           \
270     list_copy = av_calloc(count+1, sizeof(type));                       \
271     if (list_copy) {                                                    \
272         memcpy(list_copy, list, sizeof(type) * count);                  \
273         list_copy[count] = -1;                                          \
274     }                                                                   \
275 }
276
277 #define MAKE_FORMAT_LIST(type, field, count_field)                      \
278     type *formats;                                                      \
279     int count = 0;                                                      \
280     if (fmts)                                                           \
281         for (count = 0; fmts[count] != -1; count++)                     \
282             ;                                                           \
283     formats = av_mallocz(sizeof(*formats));                             \
284     if (!formats) return NULL;                                          \
285     formats->count_field = count;                                       \
286     if (count) {                                                        \
287         formats->field = av_malloc(sizeof(*formats->field)*count);      \
288         if (!formats->field) {                                          \
289             av_free(formats);                                           \
290             return NULL;                                                \
291         }                                                               \
292     }
293
294 AVFilterFormats *ff_make_format_list(const int *fmts)
295 {
296     MAKE_FORMAT_LIST(AVFilterFormats, formats, nb_formats);
297     while (count--)
298         formats->formats[count] = fmts[count];
299
300     return formats;
301 }
302
303 AVFilterChannelLayouts *avfilter_make_format64_list(const int64_t *fmts)
304 {
305     MAKE_FORMAT_LIST(AVFilterChannelLayouts,
306                      channel_layouts, nb_channel_layouts);
307     if (count)
308         memcpy(formats->channel_layouts, fmts,
309                sizeof(*formats->channel_layouts) * count);
310
311     return formats;
312 }
313
314 #define ADD_FORMAT(f, fmt, type, list, nb)                  \
315 do {                                                        \
316     type *fmts;                                             \
317                                                             \
318     if (!(*f) && !(*f = av_mallocz(sizeof(**f))))           \
319         return AVERROR(ENOMEM);                             \
320                                                             \
321     fmts = av_realloc((*f)->list,                           \
322                       sizeof(*(*f)->list) * ((*f)->nb + 1));\
323     if (!fmts)                                              \
324         return AVERROR(ENOMEM);                             \
325                                                             \
326     (*f)->list = fmts;                                      \
327     (*f)->list[(*f)->nb++] = fmt;                           \
328 } while (0)
329
330 int ff_add_format(AVFilterFormats **avff, int64_t fmt)
331 {
332     ADD_FORMAT(avff, fmt, int, formats, nb_formats);
333     return 0;
334 }
335
336 int ff_add_channel_layout(AVFilterChannelLayouts **l, uint64_t channel_layout)
337 {
338     av_assert1(!(*l && (*l)->all_layouts));
339     ADD_FORMAT(l, channel_layout, uint64_t, channel_layouts, nb_channel_layouts);
340     return 0;
341 }
342
343 AVFilterFormats *ff_all_formats(enum AVMediaType type)
344 {
345     AVFilterFormats *ret = NULL;
346     int fmt;
347     int num_formats = type == AVMEDIA_TYPE_VIDEO ? AV_PIX_FMT_NB    :
348                       type == AVMEDIA_TYPE_AUDIO ? AV_SAMPLE_FMT_NB : 0;
349
350     for (fmt = 0; fmt < num_formats; fmt++) {
351         const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt);
352         if ((type != AVMEDIA_TYPE_VIDEO) ||
353             (type == AVMEDIA_TYPE_VIDEO && !(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)))
354             ff_add_format(&ret, fmt);
355     }
356
357     return ret;
358 }
359
360 const int64_t avfilter_all_channel_layouts[] = {
361 #include "all_channel_layouts.inc"
362     -1
363 };
364
365 // AVFilterFormats *avfilter_make_all_channel_layouts(void)
366 // {
367 //     return avfilter_make_format64_list(avfilter_all_channel_layouts);
368 // }
369
370 AVFilterFormats *ff_planar_sample_fmts(void)
371 {
372     AVFilterFormats *ret = NULL;
373     int fmt;
374
375     for (fmt = 0; fmt < AV_SAMPLE_FMT_NB; fmt++)
376         if (av_sample_fmt_is_planar(fmt))
377             ff_add_format(&ret, fmt);
378
379     return ret;
380 }
381
382 AVFilterFormats *ff_all_samplerates(void)
383 {
384     AVFilterFormats *ret = av_mallocz(sizeof(*ret));
385     return ret;
386 }
387
388 AVFilterChannelLayouts *ff_all_channel_layouts(void)
389 {
390     AVFilterChannelLayouts *ret = av_mallocz(sizeof(*ret));
391     if (!ret)
392         return NULL;
393     ret->all_layouts = 1;
394     return ret;
395 }
396
397 AVFilterChannelLayouts *ff_all_channel_counts(void)
398 {
399     AVFilterChannelLayouts *ret = av_mallocz(sizeof(*ret));
400     if (!ret)
401         return NULL;
402     ret->all_layouts = ret->all_counts = 1;
403     return ret;
404 }
405
406 #define FORMATS_REF(f, ref)                                          \
407 do {                                                                 \
408     *ref = f;                                                        \
409     f->refs = av_realloc(f->refs, sizeof(*f->refs) * ++f->refcount); \
410     f->refs[f->refcount-1] = ref;                                    \
411 } while (0)
412
413 void ff_channel_layouts_ref(AVFilterChannelLayouts *f, AVFilterChannelLayouts **ref)
414 {
415     FORMATS_REF(f, ref);
416 }
417
418 void ff_formats_ref(AVFilterFormats *f, AVFilterFormats **ref)
419 {
420     FORMATS_REF(f, ref);
421 }
422
423 #define FIND_REF_INDEX(ref, idx)            \
424 do {                                        \
425     int i;                                  \
426     for (i = 0; i < (*ref)->refcount; i ++) \
427         if((*ref)->refs[i] == ref) {        \
428             idx = i;                        \
429             break;                          \
430         }                                   \
431 } while (0)
432
433 #define FORMATS_UNREF(ref, list)                                   \
434 do {                                                               \
435     int idx = -1;                                                  \
436                                                                    \
437     if (!*ref)                                                     \
438         return;                                                    \
439                                                                    \
440     FIND_REF_INDEX(ref, idx);                                      \
441                                                                    \
442     if (idx >= 0)                                                  \
443         memmove((*ref)->refs + idx, (*ref)->refs + idx + 1,        \
444             sizeof(*(*ref)->refs) * ((*ref)->refcount - idx - 1)); \
445                                                                    \
446     if(!--(*ref)->refcount) {                                      \
447         av_free((*ref)->list);                                     \
448         av_free((*ref)->refs);                                     \
449         av_free(*ref);                                             \
450     }                                                              \
451     *ref = NULL;                                                   \
452 } while (0)
453
454 void ff_formats_unref(AVFilterFormats **ref)
455 {
456     FORMATS_UNREF(ref, formats);
457 }
458
459 void ff_channel_layouts_unref(AVFilterChannelLayouts **ref)
460 {
461     FORMATS_UNREF(ref, channel_layouts);
462 }
463
464 #define FORMATS_CHANGEREF(oldref, newref)       \
465 do {                                            \
466     int idx = -1;                               \
467                                                 \
468     FIND_REF_INDEX(oldref, idx);                \
469                                                 \
470     if (idx >= 0) {                             \
471         (*oldref)->refs[idx] = newref;          \
472         *newref = *oldref;                      \
473         *oldref = NULL;                         \
474     }                                           \
475 } while (0)
476
477 void ff_channel_layouts_changeref(AVFilterChannelLayouts **oldref,
478                                   AVFilterChannelLayouts **newref)
479 {
480     FORMATS_CHANGEREF(oldref, newref);
481 }
482
483 void ff_formats_changeref(AVFilterFormats **oldref, AVFilterFormats **newref)
484 {
485     FORMATS_CHANGEREF(oldref, newref);
486 }
487
488 #define SET_COMMON_FORMATS(ctx, fmts, in_fmts, out_fmts, ref, list) \
489 {                                                                   \
490     int count = 0, i;                                               \
491                                                                     \
492     for (i = 0; i < ctx->nb_inputs; i++) {                          \
493         if (ctx->inputs[i] && !ctx->inputs[i]->out_fmts) {          \
494             ref(fmts, &ctx->inputs[i]->out_fmts);                   \
495             count++;                                                \
496         }                                                           \
497     }                                                               \
498     for (i = 0; i < ctx->nb_outputs; i++) {                         \
499         if (ctx->outputs[i] && !ctx->outputs[i]->in_fmts) {         \
500             ref(fmts, &ctx->outputs[i]->in_fmts);                   \
501             count++;                                                \
502         }                                                           \
503     }                                                               \
504                                                                     \
505     if (!count) {                                                   \
506         av_freep(&fmts->list);                                      \
507         av_freep(&fmts->refs);                                      \
508         av_freep(&fmts);                                            \
509     }                                                               \
510 }
511
512 void ff_set_common_channel_layouts(AVFilterContext *ctx,
513                                    AVFilterChannelLayouts *layouts)
514 {
515     SET_COMMON_FORMATS(ctx, layouts, in_channel_layouts, out_channel_layouts,
516                        ff_channel_layouts_ref, channel_layouts);
517 }
518
519 void ff_set_common_samplerates(AVFilterContext *ctx,
520                                AVFilterFormats *samplerates)
521 {
522     SET_COMMON_FORMATS(ctx, samplerates, in_samplerates, out_samplerates,
523                        ff_formats_ref, formats);
524 }
525
526 /**
527  * A helper for query_formats() which sets all links to the same list of
528  * formats. If there are no links hooked to this filter, the list of formats is
529  * freed.
530  */
531 void ff_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats)
532 {
533     SET_COMMON_FORMATS(ctx, formats, in_formats, out_formats,
534                        ff_formats_ref, formats);
535 }
536
537 static int default_query_formats_common(AVFilterContext *ctx,
538                                         AVFilterChannelLayouts *(layouts)(void))
539 {
540     enum AVMediaType type = ctx->inputs  && ctx->inputs [0] ? ctx->inputs [0]->type :
541                             ctx->outputs && ctx->outputs[0] ? ctx->outputs[0]->type :
542                             AVMEDIA_TYPE_VIDEO;
543
544     ff_set_common_formats(ctx, ff_all_formats(type));
545     if (type == AVMEDIA_TYPE_AUDIO) {
546         ff_set_common_channel_layouts(ctx, layouts());
547         ff_set_common_samplerates(ctx, ff_all_samplerates());
548     }
549
550     return 0;
551 }
552
553 int ff_default_query_formats(AVFilterContext *ctx)
554 {
555     return default_query_formats_common(ctx, ff_all_channel_layouts);
556 }
557
558 int ff_query_formats_all(AVFilterContext *ctx)
559 {
560     return default_query_formats_common(ctx, ff_all_channel_counts);
561 }
562
563 /* internal functions for parsing audio format arguments */
564
565 int ff_parse_pixel_format(enum AVPixelFormat *ret, const char *arg, void *log_ctx)
566 {
567     char *tail;
568     int pix_fmt = av_get_pix_fmt(arg);
569     if (pix_fmt == AV_PIX_FMT_NONE) {
570         pix_fmt = strtol(arg, &tail, 0);
571         if (*tail || (unsigned)pix_fmt >= AV_PIX_FMT_NB) {
572             av_log(log_ctx, AV_LOG_ERROR, "Invalid pixel format '%s'\n", arg);
573             return AVERROR(EINVAL);
574         }
575     }
576     *ret = pix_fmt;
577     return 0;
578 }
579
580 int ff_parse_sample_format(int *ret, const char *arg, void *log_ctx)
581 {
582     char *tail;
583     int sfmt = av_get_sample_fmt(arg);
584     if (sfmt == AV_SAMPLE_FMT_NONE) {
585         sfmt = strtol(arg, &tail, 0);
586         if (*tail || (unsigned)sfmt >= AV_SAMPLE_FMT_NB) {
587             av_log(log_ctx, AV_LOG_ERROR, "Invalid sample format '%s'\n", arg);
588             return AVERROR(EINVAL);
589         }
590     }
591     *ret = sfmt;
592     return 0;
593 }
594
595 int ff_parse_time_base(AVRational *ret, const char *arg, void *log_ctx)
596 {
597     AVRational r;
598     if(av_parse_ratio(&r, arg, INT_MAX, 0, log_ctx) < 0 ||r.num<=0  ||r.den<=0) {
599         av_log(log_ctx, AV_LOG_ERROR, "Invalid time base '%s'\n", arg);
600         return AVERROR(EINVAL);
601     }
602     *ret = r;
603     return 0;
604 }
605
606 int ff_parse_sample_rate(int *ret, const char *arg, void *log_ctx)
607 {
608     char *tail;
609     double srate = av_strtod(arg, &tail);
610     if (*tail || srate < 1 || (int)srate != srate || srate > INT_MAX) {
611         av_log(log_ctx, AV_LOG_ERROR, "Invalid sample rate '%s'\n", arg);
612         return AVERROR(EINVAL);
613     }
614     *ret = srate;
615     return 0;
616 }
617
618 int ff_parse_channel_layout(int64_t *ret, int *nret, const char *arg,
619                             void *log_ctx)
620 {
621     char *tail;
622     int64_t chlayout, count;
623
624     if (nret) {
625         count = strtol(arg, &tail, 10);
626         if (*tail == 'c' && !tail[1] && count > 0 && count < 63) {
627             *nret = count;
628             *ret = 0;
629             return 0;
630         }
631     }
632     chlayout = av_get_channel_layout(arg);
633     if (chlayout == 0) {
634         chlayout = strtol(arg, &tail, 10);
635         if (*tail || chlayout == 0) {
636             av_log(log_ctx, AV_LOG_ERROR, "Invalid channel layout '%s'\n", arg);
637             return AVERROR(EINVAL);
638         }
639     }
640     *ret = chlayout;
641     if (nret)
642         *nret = av_get_channel_layout_nb_channels(chlayout);
643     return 0;
644 }
645
646 #ifdef TEST
647
648 #undef printf
649
650 int main(void)
651 {
652     const int64_t *cl;
653     char buf[512];
654
655     for (cl = avfilter_all_channel_layouts; *cl != -1; cl++) {
656         av_get_channel_layout_string(buf, sizeof(buf), -1, *cl);
657         printf("%s\n", buf);
658     }
659
660     return 0;
661 }
662
663 #endif
664