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