]> git.sesse.net Git - ffmpeg/blob - libavfilter/formats.c
mpegts: use seek_back() for all seek backs
[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 int *ff_copy_int_list(const int * const list)
278 {
279     int *ret = NULL;
280     COPY_INT_LIST(ret, list, int);
281     return ret;
282 }
283
284 int64_t *ff_copy_int64_list(const int64_t * const list)
285 {
286     int64_t *ret = NULL;
287     COPY_INT_LIST(ret, list, int64_t);
288     return ret;
289 }
290
291 #define MAKE_FORMAT_LIST(type, field, count_field)                      \
292     type *formats;                                                      \
293     int count = 0;                                                      \
294     if (fmts)                                                           \
295         for (count = 0; fmts[count] != -1; count++)                     \
296             ;                                                           \
297     formats = av_mallocz(sizeof(*formats));                             \
298     if (!formats) return NULL;                                          \
299     formats->count_field = count;                                       \
300     if (count) {                                                        \
301         formats->field = av_malloc(sizeof(*formats->field)*count);      \
302         if (!formats->field) {                                          \
303             av_free(formats);                                           \
304             return NULL;                                                \
305         }                                                               \
306     }
307
308 AVFilterFormats *ff_make_format_list(const int *fmts)
309 {
310     MAKE_FORMAT_LIST(AVFilterFormats, formats, nb_formats);
311     while (count--)
312         formats->formats[count] = fmts[count];
313
314     return formats;
315 }
316
317 AVFilterChannelLayouts *avfilter_make_format64_list(const int64_t *fmts)
318 {
319     MAKE_FORMAT_LIST(AVFilterChannelLayouts,
320                      channel_layouts, nb_channel_layouts);
321     if (count)
322         memcpy(formats->channel_layouts, fmts,
323                sizeof(*formats->channel_layouts) * count);
324
325     return formats;
326 }
327
328 #define ADD_FORMAT(f, fmt, type, list, nb)                  \
329 do {                                                        \
330     type *fmts;                                             \
331                                                             \
332     if (!(*f) && !(*f = av_mallocz(sizeof(**f))))           \
333         return AVERROR(ENOMEM);                             \
334                                                             \
335     fmts = av_realloc((*f)->list,                           \
336                       sizeof(*(*f)->list) * ((*f)->nb + 1));\
337     if (!fmts)                                              \
338         return AVERROR(ENOMEM);                             \
339                                                             \
340     (*f)->list = fmts;                                      \
341     (*f)->list[(*f)->nb++] = fmt;                           \
342 } while (0)
343
344 int ff_add_format(AVFilterFormats **avff, int64_t fmt)
345 {
346     ADD_FORMAT(avff, fmt, int, formats, nb_formats);
347     return 0;
348 }
349
350 int ff_add_channel_layout(AVFilterChannelLayouts **l, uint64_t channel_layout)
351 {
352     av_assert1(!(*l && (*l)->all_layouts));
353     ADD_FORMAT(l, channel_layout, uint64_t, channel_layouts, nb_channel_layouts);
354     return 0;
355 }
356
357 AVFilterFormats *ff_all_formats(enum AVMediaType type)
358 {
359     AVFilterFormats *ret = NULL;
360     int fmt;
361     int num_formats = type == AVMEDIA_TYPE_VIDEO ? AV_PIX_FMT_NB    :
362                       type == AVMEDIA_TYPE_AUDIO ? AV_SAMPLE_FMT_NB : 0;
363
364     for (fmt = 0; fmt < num_formats; fmt++) {
365         const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt);
366         if ((type != AVMEDIA_TYPE_VIDEO) ||
367             (type == AVMEDIA_TYPE_VIDEO && !(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)))
368             ff_add_format(&ret, fmt);
369     }
370
371     return ret;
372 }
373
374 const int64_t avfilter_all_channel_layouts[] = {
375 #include "all_channel_layouts.inc"
376     -1
377 };
378
379 // AVFilterFormats *avfilter_make_all_channel_layouts(void)
380 // {
381 //     return avfilter_make_format64_list(avfilter_all_channel_layouts);
382 // }
383
384 AVFilterFormats *ff_planar_sample_fmts(void)
385 {
386     AVFilterFormats *ret = NULL;
387     int fmt;
388
389     for (fmt = 0; fmt < AV_SAMPLE_FMT_NB; fmt++)
390         if (av_sample_fmt_is_planar(fmt))
391             ff_add_format(&ret, fmt);
392
393     return ret;
394 }
395
396 AVFilterFormats *ff_all_samplerates(void)
397 {
398     AVFilterFormats *ret = av_mallocz(sizeof(*ret));
399     return ret;
400 }
401
402 AVFilterChannelLayouts *ff_all_channel_layouts(void)
403 {
404     AVFilterChannelLayouts *ret = av_mallocz(sizeof(*ret));
405     if (!ret)
406         return NULL;
407     ret->all_layouts = 1;
408     return ret;
409 }
410
411 AVFilterChannelLayouts *ff_all_channel_counts(void)
412 {
413     AVFilterChannelLayouts *ret = av_mallocz(sizeof(*ret));
414     if (!ret)
415         return NULL;
416     ret->all_layouts = ret->all_counts = 1;
417     return ret;
418 }
419
420 #define FORMATS_REF(f, ref)                                          \
421 do {                                                                 \
422     *ref = f;                                                        \
423     f->refs = av_realloc(f->refs, sizeof(*f->refs) * ++f->refcount); \
424     f->refs[f->refcount-1] = ref;                                    \
425 } while (0)
426
427 void ff_channel_layouts_ref(AVFilterChannelLayouts *f, AVFilterChannelLayouts **ref)
428 {
429     FORMATS_REF(f, ref);
430 }
431
432 void ff_formats_ref(AVFilterFormats *f, AVFilterFormats **ref)
433 {
434     FORMATS_REF(f, ref);
435 }
436
437 #define FIND_REF_INDEX(ref, idx)            \
438 do {                                        \
439     int i;                                  \
440     for (i = 0; i < (*ref)->refcount; i ++) \
441         if((*ref)->refs[i] == ref) {        \
442             idx = i;                        \
443             break;                          \
444         }                                   \
445 } while (0)
446
447 #define FORMATS_UNREF(ref, list)                                   \
448 do {                                                               \
449     int idx = -1;                                                  \
450                                                                    \
451     if (!*ref)                                                     \
452         return;                                                    \
453                                                                    \
454     FIND_REF_INDEX(ref, idx);                                      \
455                                                                    \
456     if (idx >= 0)                                                  \
457         memmove((*ref)->refs + idx, (*ref)->refs + idx + 1,        \
458             sizeof(*(*ref)->refs) * ((*ref)->refcount - idx - 1)); \
459                                                                    \
460     if(!--(*ref)->refcount) {                                      \
461         av_free((*ref)->list);                                     \
462         av_free((*ref)->refs);                                     \
463         av_free(*ref);                                             \
464     }                                                              \
465     *ref = NULL;                                                   \
466 } while (0)
467
468 void ff_formats_unref(AVFilterFormats **ref)
469 {
470     FORMATS_UNREF(ref, formats);
471 }
472
473 void ff_channel_layouts_unref(AVFilterChannelLayouts **ref)
474 {
475     FORMATS_UNREF(ref, channel_layouts);
476 }
477
478 #define FORMATS_CHANGEREF(oldref, newref)       \
479 do {                                            \
480     int idx = -1;                               \
481                                                 \
482     FIND_REF_INDEX(oldref, idx);                \
483                                                 \
484     if (idx >= 0) {                             \
485         (*oldref)->refs[idx] = newref;          \
486         *newref = *oldref;                      \
487         *oldref = NULL;                         \
488     }                                           \
489 } while (0)
490
491 void ff_channel_layouts_changeref(AVFilterChannelLayouts **oldref,
492                                   AVFilterChannelLayouts **newref)
493 {
494     FORMATS_CHANGEREF(oldref, newref);
495 }
496
497 void ff_formats_changeref(AVFilterFormats **oldref, AVFilterFormats **newref)
498 {
499     FORMATS_CHANGEREF(oldref, newref);
500 }
501
502 #define SET_COMMON_FORMATS(ctx, fmts, in_fmts, out_fmts, ref, list) \
503 {                                                                   \
504     int count = 0, i;                                               \
505                                                                     \
506     for (i = 0; i < ctx->nb_inputs; i++) {                          \
507         if (ctx->inputs[i] && !ctx->inputs[i]->out_fmts) {          \
508             ref(fmts, &ctx->inputs[i]->out_fmts);                   \
509             count++;                                                \
510         }                                                           \
511     }                                                               \
512     for (i = 0; i < ctx->nb_outputs; i++) {                         \
513         if (ctx->outputs[i] && !ctx->outputs[i]->in_fmts) {         \
514             ref(fmts, &ctx->outputs[i]->in_fmts);                   \
515             count++;                                                \
516         }                                                           \
517     }                                                               \
518                                                                     \
519     if (!count) {                                                   \
520         av_freep(&fmts->list);                                      \
521         av_freep(&fmts->refs);                                      \
522         av_freep(&fmts);                                            \
523     }                                                               \
524 }
525
526 void ff_set_common_channel_layouts(AVFilterContext *ctx,
527                                    AVFilterChannelLayouts *layouts)
528 {
529     SET_COMMON_FORMATS(ctx, layouts, in_channel_layouts, out_channel_layouts,
530                        ff_channel_layouts_ref, channel_layouts);
531 }
532
533 void ff_set_common_samplerates(AVFilterContext *ctx,
534                                AVFilterFormats *samplerates)
535 {
536     SET_COMMON_FORMATS(ctx, samplerates, in_samplerates, out_samplerates,
537                        ff_formats_ref, formats);
538 }
539
540 /**
541  * A helper for query_formats() which sets all links to the same list of
542  * formats. If there are no links hooked to this filter, the list of formats is
543  * freed.
544  */
545 void ff_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats)
546 {
547     SET_COMMON_FORMATS(ctx, formats, in_formats, out_formats,
548                        ff_formats_ref, formats);
549 }
550
551 static int default_query_formats_common(AVFilterContext *ctx,
552                                         AVFilterChannelLayouts *(layouts)(void))
553 {
554     enum AVMediaType type = ctx->inputs  && ctx->inputs [0] ? ctx->inputs [0]->type :
555                             ctx->outputs && ctx->outputs[0] ? ctx->outputs[0]->type :
556                             AVMEDIA_TYPE_VIDEO;
557
558     ff_set_common_formats(ctx, ff_all_formats(type));
559     if (type == AVMEDIA_TYPE_AUDIO) {
560         ff_set_common_channel_layouts(ctx, layouts());
561         ff_set_common_samplerates(ctx, ff_all_samplerates());
562     }
563
564     return 0;
565 }
566
567 int ff_default_query_formats(AVFilterContext *ctx)
568 {
569     return default_query_formats_common(ctx, ff_all_channel_layouts);
570 }
571
572 int ff_query_formats_all(AVFilterContext *ctx)
573 {
574     return default_query_formats_common(ctx, ff_all_channel_counts);
575 }
576
577 /* internal functions for parsing audio format arguments */
578
579 int ff_parse_pixel_format(enum AVPixelFormat *ret, const char *arg, void *log_ctx)
580 {
581     char *tail;
582     int pix_fmt = av_get_pix_fmt(arg);
583     if (pix_fmt == AV_PIX_FMT_NONE) {
584         pix_fmt = strtol(arg, &tail, 0);
585         if (*tail || (unsigned)pix_fmt >= AV_PIX_FMT_NB) {
586             av_log(log_ctx, AV_LOG_ERROR, "Invalid pixel format '%s'\n", arg);
587             return AVERROR(EINVAL);
588         }
589     }
590     *ret = pix_fmt;
591     return 0;
592 }
593
594 int ff_parse_sample_format(int *ret, const char *arg, void *log_ctx)
595 {
596     char *tail;
597     int sfmt = av_get_sample_fmt(arg);
598     if (sfmt == AV_SAMPLE_FMT_NONE) {
599         sfmt = strtol(arg, &tail, 0);
600         if (*tail || (unsigned)sfmt >= AV_SAMPLE_FMT_NB) {
601             av_log(log_ctx, AV_LOG_ERROR, "Invalid sample format '%s'\n", arg);
602             return AVERROR(EINVAL);
603         }
604     }
605     *ret = sfmt;
606     return 0;
607 }
608
609 int ff_parse_time_base(AVRational *ret, const char *arg, void *log_ctx)
610 {
611     AVRational r;
612     if(av_parse_ratio(&r, arg, INT_MAX, 0, log_ctx) < 0 ||r.num<=0  ||r.den<=0) {
613         av_log(log_ctx, AV_LOG_ERROR, "Invalid time base '%s'\n", arg);
614         return AVERROR(EINVAL);
615     }
616     *ret = r;
617     return 0;
618 }
619
620 int ff_parse_sample_rate(int *ret, const char *arg, void *log_ctx)
621 {
622     char *tail;
623     double srate = av_strtod(arg, &tail);
624     if (*tail || srate < 1 || (int)srate != srate || srate > INT_MAX) {
625         av_log(log_ctx, AV_LOG_ERROR, "Invalid sample rate '%s'\n", arg);
626         return AVERROR(EINVAL);
627     }
628     *ret = srate;
629     return 0;
630 }
631
632 int ff_parse_channel_layout(int64_t *ret, const char *arg, void *log_ctx)
633 {
634     char *tail;
635     int64_t chlayout = av_get_channel_layout(arg);
636     if (chlayout == 0) {
637         chlayout = strtol(arg, &tail, 10);
638         if (*tail || chlayout == 0) {
639             av_log(log_ctx, AV_LOG_ERROR, "Invalid channel layout '%s'\n", arg);
640             return AVERROR(EINVAL);
641         }
642     }
643     *ret = chlayout;
644     return 0;
645 }
646
647 #ifdef TEST
648
649 #undef printf
650
651 int main(void)
652 {
653     const int64_t *cl;
654     char buf[512];
655
656     for (cl = avfilter_all_channel_layouts; *cl != -1; cl++) {
657         av_get_channel_layout_string(buf, sizeof(buf), -1, *cl);
658         printf("%s\n", buf);
659     }
660
661     return 0;
662 }
663
664 #endif
665