]> git.sesse.net Git - ffmpeg/blob - libavfilter/formats.c
avfilter/formats: Remove avfilter_make_format64_list()
[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 "avfilter.h"
28 #include "internal.h"
29 #include "formats.h"
30
31 #define KNOWN(l) (!FF_LAYOUT2COUNT(l)) /* for readability */
32
33 /**
34  * Add all refs from a to ret and destroy a.
35  */
36 #define MERGE_REF(ret, a, fmts, type, fail_statement)                      \
37 do {                                                                       \
38     type ***tmp;                                                           \
39     int i;                                                                 \
40                                                                            \
41     if (!(tmp = av_realloc_array(ret->refs, ret->refcount + a->refcount,   \
42                                  sizeof(*tmp))))                           \
43         { fail_statement }                                                 \
44     ret->refs = tmp;                                                       \
45                                                                            \
46     for (i = 0; i < a->refcount; i ++) {                                   \
47         ret->refs[ret->refcount] = a->refs[i];                             \
48         *ret->refs[ret->refcount++] = ret;                                 \
49     }                                                                      \
50                                                                            \
51     av_freep(&a->refs);                                                    \
52     av_freep(&a->fmts);                                                    \
53     av_freep(&a);                                                          \
54 } while (0)
55
56 /**
57  * Add all formats common to a and b to a, add b's refs to a and destroy b.
58  * If check is set, nothing is modified and it is only checked whether
59  * the formats are compatible.
60  * If empty_allowed is set and one of a,b->nb is zero, the lists are
61  * merged; otherwise, it is treated as error.
62  */
63 #define MERGE_FORMATS(a, b, fmts, nb, type, check, empty_allowed)          \
64 do {                                                                       \
65     int i, j, k = 0, skip = 0;                                             \
66                                                                            \
67     if (empty_allowed) {                                                   \
68         if (!a->nb || !b->nb) {                                            \
69             if (check)                                                     \
70                 return 1;                                                  \
71             if (!a->nb)                                                    \
72                 FFSWAP(type *, a, b);                                      \
73             skip = 1;                                                      \
74         }                                                                  \
75     }                                                                      \
76     if (!skip) {                                                           \
77         for (i = 0; i < a->nb; i++)                                        \
78             for (j = 0; j < b->nb; j++)                                    \
79                 if (a->fmts[i] == b->fmts[j]) {                            \
80                     if (check)                                             \
81                         return 1;                                          \
82                     a->fmts[k++] = a->fmts[i];                             \
83                     break;                                                 \
84                 }                                                          \
85         /* Check that there was at least one common format.                \
86          * Notice that both a and b are unchanged if not. */               \
87         if (!k)                                                            \
88             return 0;                                                      \
89         av_assert2(!check);                                                \
90         a->nb = k;                                                         \
91     }                                                                      \
92                                                                            \
93     MERGE_REF(a, b, fmts, type, return AVERROR(ENOMEM););                  \
94 } while (0)
95
96 static int merge_formats_internal(AVFilterFormats *a, AVFilterFormats *b,
97                                   enum AVMediaType type, int check)
98 {
99     int i, j;
100     int alpha1=0, alpha2=0;
101     int chroma1=0, chroma2=0;
102
103     if (a == b)
104         return 1;
105
106     /* Do not lose chroma or alpha in merging.
107        It happens if both lists have formats with chroma (resp. alpha), but
108        the only formats in common do not have it (e.g. YUV+gray vs.
109        RGB+gray): in that case, the merging would select the gray format,
110        possibly causing a lossy conversion elsewhere in the graph.
111        To avoid that, pretend that there are no common formats to force the
112        insertion of a conversion filter. */
113     if (type == AVMEDIA_TYPE_VIDEO)
114         for (i = 0; i < a->nb_formats; i++)
115             for (j = 0; j < b->nb_formats; j++) {
116                 const AVPixFmtDescriptor *adesc = av_pix_fmt_desc_get(a->formats[i]);
117                 const AVPixFmtDescriptor *bdesc = av_pix_fmt_desc_get(b->formats[j]);
118                 alpha2 |= adesc->flags & bdesc->flags & AV_PIX_FMT_FLAG_ALPHA;
119                 chroma2|= adesc->nb_components > 1 && bdesc->nb_components > 1;
120                 if (a->formats[i] == b->formats[j]) {
121                     alpha1 |= adesc->flags & AV_PIX_FMT_FLAG_ALPHA;
122                     chroma1|= adesc->nb_components > 1;
123                 }
124             }
125
126     // If chroma or alpha can be lost through merging then do not merge
127     if (alpha2 > alpha1 || chroma2 > chroma1)
128         return 0;
129
130     MERGE_FORMATS(a, b, formats, nb_formats, AVFilterFormats, check, 0);
131
132     return 1;
133 }
134
135 int ff_can_merge_formats(const AVFilterFormats *a, const AVFilterFormats *b,
136                          enum AVMediaType type)
137 {
138     return merge_formats_internal((AVFilterFormats *)a,
139                                   (AVFilterFormats *)b, type, 1);
140 }
141
142 int ff_merge_formats(AVFilterFormats *a, AVFilterFormats *b,
143                      enum AVMediaType type)
144 {
145     av_assert2(a->refcount && b->refcount);
146     return merge_formats_internal(a, b, type, 0);
147 }
148
149 static int merge_samplerates_internal(AVFilterFormats *a,
150                                       AVFilterFormats *b, int check)
151 {
152     if (a == b) return 1;
153
154     MERGE_FORMATS(a, b, formats, nb_formats, AVFilterFormats, check, 1);
155     return 1;
156 }
157
158 int ff_can_merge_samplerates(const AVFilterFormats *a, const AVFilterFormats *b)
159 {
160     return merge_samplerates_internal((AVFilterFormats *)a, (AVFilterFormats *)b, 1);
161 }
162
163 int ff_merge_samplerates(AVFilterFormats *a, AVFilterFormats *b)
164 {
165     av_assert2(a->refcount && b->refcount);
166     return merge_samplerates_internal(a, b, 0);
167 }
168
169 int ff_merge_channel_layouts(AVFilterChannelLayouts *a,
170                              AVFilterChannelLayouts *b)
171 {
172     uint64_t *channel_layouts;
173     unsigned a_all = a->all_layouts + a->all_counts;
174     unsigned b_all = b->all_layouts + b->all_counts;
175     int ret_max, ret_nb = 0, i, j, round;
176
177     av_assert2(a->refcount && b->refcount);
178
179     if (a == b) return 1;
180
181     /* Put the most generic set in a, to avoid doing everything twice */
182     if (a_all < b_all) {
183         FFSWAP(AVFilterChannelLayouts *, a, b);
184         FFSWAP(unsigned, a_all, b_all);
185     }
186     if (a_all) {
187         if (a_all == 1 && !b_all) {
188             /* keep only known layouts in b; works also for b_all = 1 */
189             for (i = j = 0; i < b->nb_channel_layouts; i++)
190                 if (KNOWN(b->channel_layouts[i]))
191                     b->channel_layouts[j++] = b->channel_layouts[i];
192             /* Not optimal: the unknown layouts of b may become known after
193                another merge. */
194             if (!j)
195                 return 0;
196             b->nb_channel_layouts = j;
197         }
198         MERGE_REF(b, a, channel_layouts, AVFilterChannelLayouts, return AVERROR(ENOMEM););
199         return 1;
200     }
201
202     ret_max = a->nb_channel_layouts + b->nb_channel_layouts;
203     if (!(channel_layouts = av_malloc_array(ret_max, sizeof(*channel_layouts))))
204         return AVERROR(ENOMEM);
205
206     /* a[known] intersect b[known] */
207     for (i = 0; i < a->nb_channel_layouts; i++) {
208         if (!KNOWN(a->channel_layouts[i]))
209             continue;
210         for (j = 0; j < b->nb_channel_layouts; j++) {
211             if (a->channel_layouts[i] == b->channel_layouts[j]) {
212                 channel_layouts[ret_nb++] = a->channel_layouts[i];
213                 a->channel_layouts[i] = b->channel_layouts[j] = 0;
214                 break;
215             }
216         }
217     }
218     /* 1st round: a[known] intersect b[generic]
219        2nd round: a[generic] intersect b[known] */
220     for (round = 0; round < 2; round++) {
221         for (i = 0; i < a->nb_channel_layouts; i++) {
222             uint64_t fmt = a->channel_layouts[i], bfmt;
223             if (!fmt || !KNOWN(fmt))
224                 continue;
225             bfmt = FF_COUNT2LAYOUT(av_get_channel_layout_nb_channels(fmt));
226             for (j = 0; j < b->nb_channel_layouts; j++)
227                 if (b->channel_layouts[j] == bfmt)
228                     channel_layouts[ret_nb++] = a->channel_layouts[i];
229         }
230         /* 1st round: swap to prepare 2nd round; 2nd round: put it back */
231         FFSWAP(AVFilterChannelLayouts *, a, b);
232     }
233     /* a[generic] intersect b[generic] */
234     for (i = 0; i < a->nb_channel_layouts; i++) {
235         if (KNOWN(a->channel_layouts[i]))
236             continue;
237         for (j = 0; j < b->nb_channel_layouts; j++)
238             if (a->channel_layouts[i] == b->channel_layouts[j])
239                 channel_layouts[ret_nb++] = a->channel_layouts[i];
240     }
241
242     if (!ret_nb) {
243         av_free(channel_layouts);
244         return 0;
245     }
246
247     if (a->refcount > b->refcount)
248         FFSWAP(AVFilterChannelLayouts *, a, b);
249
250     MERGE_REF(b, a, channel_layouts, AVFilterChannelLayouts,
251               { av_free(channel_layouts); return AVERROR(ENOMEM); });
252     av_freep(&b->channel_layouts);
253     b->channel_layouts    = channel_layouts;
254     b->nb_channel_layouts = ret_nb;
255     return 1;
256 }
257
258 int ff_fmt_is_in(int fmt, const int *fmts)
259 {
260     const int *p;
261
262     for (p = fmts; *p != -1; p++) {
263         if (fmt == *p)
264             return 1;
265     }
266     return 0;
267 }
268
269 #define MAKE_FORMAT_LIST(type, field, count_field)                      \
270     type *formats;                                                      \
271     int count = 0;                                                      \
272     if (fmts)                                                           \
273         for (count = 0; fmts[count] != -1; count++)                     \
274             ;                                                           \
275     formats = av_mallocz(sizeof(*formats));                             \
276     if (!formats)                                                       \
277         return NULL;                                                    \
278     formats->count_field = count;                                       \
279     if (count) {                                                        \
280         formats->field = av_malloc_array(count, sizeof(*formats->field));      \
281         if (!formats->field) {                                          \
282             av_freep(&formats);                                         \
283             return NULL;                                                \
284         }                                                               \
285     }
286
287 AVFilterFormats *ff_make_format_list(const int *fmts)
288 {
289     MAKE_FORMAT_LIST(AVFilterFormats, formats, nb_formats);
290     while (count--)
291         formats->formats[count] = fmts[count];
292
293     return formats;
294 }
295
296 AVFilterChannelLayouts *ff_make_format64_list(const int64_t *fmts)
297 {
298     MAKE_FORMAT_LIST(AVFilterChannelLayouts,
299                      channel_layouts, nb_channel_layouts);
300     if (count)
301         memcpy(formats->channel_layouts, fmts,
302                sizeof(*formats->channel_layouts) * count);
303
304     return formats;
305 }
306
307 #define ADD_FORMAT(f, fmt, unref_fn, type, list, nb)        \
308 do {                                                        \
309     type *fmts;                                             \
310                                                             \
311     if (!(*f) && !(*f = av_mallocz(sizeof(**f)))) {         \
312         return AVERROR(ENOMEM);                             \
313     }                                                       \
314                                                             \
315     fmts = av_realloc_array((*f)->list, (*f)->nb + 1,       \
316                             sizeof(*(*f)->list));           \
317     if (!fmts) {                                            \
318         unref_fn(f);                                        \
319         return AVERROR(ENOMEM);                             \
320     }                                                       \
321                                                             \
322     (*f)->list = fmts;                                      \
323     (*f)->list[(*f)->nb++] = fmt;                           \
324 } while (0)
325
326 int ff_add_format(AVFilterFormats **avff, int64_t fmt)
327 {
328     ADD_FORMAT(avff, fmt, ff_formats_unref, int, formats, nb_formats);
329     return 0;
330 }
331
332 int ff_add_channel_layout(AVFilterChannelLayouts **l, uint64_t channel_layout)
333 {
334     av_assert1(!(*l && (*l)->all_layouts));
335     ADD_FORMAT(l, channel_layout, ff_channel_layouts_unref, uint64_t, channel_layouts, nb_channel_layouts);
336     return 0;
337 }
338
339 AVFilterFormats *ff_all_formats(enum AVMediaType type)
340 {
341     AVFilterFormats *ret = NULL;
342
343     if (type == AVMEDIA_TYPE_VIDEO) {
344         const AVPixFmtDescriptor *desc = NULL;
345         while ((desc = av_pix_fmt_desc_next(desc))) {
346             if (ff_add_format(&ret, av_pix_fmt_desc_get_id(desc)) < 0)
347                 return NULL;
348         }
349     } else if (type == AVMEDIA_TYPE_AUDIO) {
350         enum AVSampleFormat fmt = 0;
351         while (av_get_sample_fmt_name(fmt)) {
352             if (ff_add_format(&ret, fmt) < 0)
353                 return NULL;
354             fmt++;
355         }
356     }
357
358     return ret;
359 }
360
361 int ff_formats_pixdesc_filter(AVFilterFormats **rfmts, unsigned want, unsigned rej)
362 {
363     unsigned nb_formats, fmt, flags;
364     AVFilterFormats *formats = NULL;
365
366     while (1) {
367         nb_formats = 0;
368         for (fmt = 0;; fmt++) {
369             const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt);
370             if (!desc)
371                 break;
372             flags = desc->flags;
373             if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL) &&
374                 !(desc->flags & AV_PIX_FMT_FLAG_PLANAR) &&
375                 (desc->log2_chroma_w || desc->log2_chroma_h))
376                 flags |= FF_PIX_FMT_FLAG_SW_FLAT_SUB;
377             if ((flags & (want | rej)) != want)
378                 continue;
379             if (formats)
380                 formats->formats[nb_formats] = fmt;
381             nb_formats++;
382         }
383         if (formats) {
384             av_assert0(formats->nb_formats == nb_formats);
385             *rfmts = formats;
386             return 0;
387         }
388         formats = av_mallocz(sizeof(*formats));
389         if (!formats)
390             return AVERROR(ENOMEM);
391         formats->nb_formats = nb_formats;
392         if (nb_formats) {
393             formats->formats = av_malloc_array(nb_formats, sizeof(*formats->formats));
394             if (!formats->formats) {
395                 av_freep(&formats);
396                 return AVERROR(ENOMEM);
397             }
398         }
399     }
400 }
401
402 AVFilterFormats *ff_planar_sample_fmts(void)
403 {
404     AVFilterFormats *ret = NULL;
405     int fmt;
406
407     for (fmt = 0; av_get_bytes_per_sample(fmt)>0; fmt++)
408         if (av_sample_fmt_is_planar(fmt))
409             if (ff_add_format(&ret, fmt) < 0)
410                 return NULL;
411
412     return ret;
413 }
414
415 AVFilterFormats *ff_all_samplerates(void)
416 {
417     AVFilterFormats *ret = av_mallocz(sizeof(*ret));
418     return ret;
419 }
420
421 AVFilterChannelLayouts *ff_all_channel_layouts(void)
422 {
423     AVFilterChannelLayouts *ret = av_mallocz(sizeof(*ret));
424     if (!ret)
425         return NULL;
426     ret->all_layouts = 1;
427     return ret;
428 }
429
430 AVFilterChannelLayouts *ff_all_channel_counts(void)
431 {
432     AVFilterChannelLayouts *ret = av_mallocz(sizeof(*ret));
433     if (!ret)
434         return NULL;
435     ret->all_layouts = ret->all_counts = 1;
436     return ret;
437 }
438
439 #define FORMATS_REF(f, ref, unref_fn)                                           \
440     void *tmp;                                                                  \
441                                                                                 \
442     if (!f)                                                                     \
443         return AVERROR(ENOMEM);                                                 \
444                                                                                 \
445     tmp = av_realloc_array(f->refs, sizeof(*f->refs), f->refcount + 1);         \
446     if (!tmp) {                                                                 \
447         unref_fn(&f);                                                           \
448         return AVERROR(ENOMEM);                                                 \
449     }                                                                           \
450     f->refs = tmp;                                                              \
451     f->refs[f->refcount++] = ref;                                               \
452     *ref = f;                                                                   \
453     return 0
454
455 int ff_channel_layouts_ref(AVFilterChannelLayouts *f, AVFilterChannelLayouts **ref)
456 {
457     FORMATS_REF(f, ref, ff_channel_layouts_unref);
458 }
459
460 int ff_formats_ref(AVFilterFormats *f, AVFilterFormats **ref)
461 {
462     FORMATS_REF(f, ref, ff_formats_unref);
463 }
464
465 #define FIND_REF_INDEX(ref, idx)            \
466 do {                                        \
467     int i;                                  \
468     for (i = 0; i < (*ref)->refcount; i ++) \
469         if((*ref)->refs[i] == ref) {        \
470             idx = i;                        \
471             break;                          \
472         }                                   \
473 } while (0)
474
475 #define FORMATS_UNREF(ref, list)                                   \
476 do {                                                               \
477     int idx = -1;                                                  \
478                                                                    \
479     if (!*ref)                                                     \
480         return;                                                    \
481                                                                    \
482     FIND_REF_INDEX(ref, idx);                                      \
483                                                                    \
484     if (idx >= 0) {                                                \
485         memmove((*ref)->refs + idx, (*ref)->refs + idx + 1,        \
486             sizeof(*(*ref)->refs) * ((*ref)->refcount - idx - 1)); \
487         --(*ref)->refcount;                                        \
488     }                                                              \
489     if (!(*ref)->refcount) {                                       \
490         av_free((*ref)->list);                                     \
491         av_free((*ref)->refs);                                     \
492         av_free(*ref);                                             \
493     }                                                              \
494     *ref = NULL;                                                   \
495 } while (0)
496
497 void ff_formats_unref(AVFilterFormats **ref)
498 {
499     FORMATS_UNREF(ref, formats);
500 }
501
502 void ff_channel_layouts_unref(AVFilterChannelLayouts **ref)
503 {
504     FORMATS_UNREF(ref, channel_layouts);
505 }
506
507 #define FORMATS_CHANGEREF(oldref, newref)       \
508 do {                                            \
509     int idx = -1;                               \
510                                                 \
511     FIND_REF_INDEX(oldref, idx);                \
512                                                 \
513     if (idx >= 0) {                             \
514         (*oldref)->refs[idx] = newref;          \
515         *newref = *oldref;                      \
516         *oldref = NULL;                         \
517     }                                           \
518 } while (0)
519
520 void ff_channel_layouts_changeref(AVFilterChannelLayouts **oldref,
521                                   AVFilterChannelLayouts **newref)
522 {
523     FORMATS_CHANGEREF(oldref, newref);
524 }
525
526 void ff_formats_changeref(AVFilterFormats **oldref, AVFilterFormats **newref)
527 {
528     FORMATS_CHANGEREF(oldref, newref);
529 }
530
531 #define SET_COMMON_FORMATS(ctx, fmts, ref_fn, unref_fn)             \
532     int count = 0, i;                                               \
533                                                                     \
534     if (!fmts)                                                      \
535         return AVERROR(ENOMEM);                                     \
536                                                                     \
537     for (i = 0; i < ctx->nb_inputs; i++) {                          \
538         if (ctx->inputs[i] && !ctx->inputs[i]->outcfg.fmts) {       \
539             int ret = ref_fn(fmts, &ctx->inputs[i]->outcfg.fmts);   \
540             if (ret < 0) {                                          \
541                 return ret;                                         \
542             }                                                       \
543             count++;                                                \
544         }                                                           \
545     }                                                               \
546     for (i = 0; i < ctx->nb_outputs; i++) {                         \
547         if (ctx->outputs[i] && !ctx->outputs[i]->incfg.fmts) {      \
548             int ret = ref_fn(fmts, &ctx->outputs[i]->incfg.fmts);   \
549             if (ret < 0) {                                          \
550                 return ret;                                         \
551             }                                                       \
552             count++;                                                \
553         }                                                           \
554     }                                                               \
555                                                                     \
556     if (!count) {                                                   \
557         unref_fn(&fmts);                                            \
558     }                                                               \
559                                                                     \
560     return 0;
561
562 int ff_set_common_channel_layouts(AVFilterContext *ctx,
563                                   AVFilterChannelLayouts *channel_layouts)
564 {
565     SET_COMMON_FORMATS(ctx, channel_layouts,
566                        ff_channel_layouts_ref, ff_channel_layouts_unref);
567 }
568
569 int ff_set_common_samplerates(AVFilterContext *ctx,
570                               AVFilterFormats *samplerates)
571 {
572     SET_COMMON_FORMATS(ctx, samplerates,
573                        ff_formats_ref, ff_formats_unref);
574 }
575
576 /**
577  * A helper for query_formats() which sets all links to the same list of
578  * formats. If there are no links hooked to this filter, the list of formats is
579  * freed.
580  */
581 int ff_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats)
582 {
583     SET_COMMON_FORMATS(ctx, formats,
584                        ff_formats_ref, ff_formats_unref);
585 }
586
587 int ff_default_query_formats(AVFilterContext *ctx)
588 {
589     int ret;
590     enum AVMediaType type = ctx->nb_inputs  ? ctx->inputs [0]->type :
591                             ctx->nb_outputs ? ctx->outputs[0]->type :
592                             AVMEDIA_TYPE_VIDEO;
593
594     ret = ff_set_common_formats(ctx, ff_all_formats(type));
595     if (ret < 0)
596         return ret;
597     if (type == AVMEDIA_TYPE_AUDIO) {
598         ret = ff_set_common_channel_layouts(ctx, ff_all_channel_counts());
599         if (ret < 0)
600             return ret;
601         ret = ff_set_common_samplerates(ctx, ff_all_samplerates());
602         if (ret < 0)
603             return ret;
604     }
605
606     return 0;
607 }
608
609 /* internal functions for parsing audio format arguments */
610
611 int ff_parse_pixel_format(enum AVPixelFormat *ret, const char *arg, void *log_ctx)
612 {
613     char *tail;
614     int pix_fmt = av_get_pix_fmt(arg);
615     if (pix_fmt == AV_PIX_FMT_NONE) {
616         pix_fmt = strtol(arg, &tail, 0);
617         if (*tail || !av_pix_fmt_desc_get(pix_fmt)) {
618             av_log(log_ctx, AV_LOG_ERROR, "Invalid pixel format '%s'\n", arg);
619             return AVERROR(EINVAL);
620         }
621     }
622     *ret = pix_fmt;
623     return 0;
624 }
625
626 int ff_parse_sample_rate(int *ret, const char *arg, void *log_ctx)
627 {
628     char *tail;
629     double srate = av_strtod(arg, &tail);
630     if (*tail || srate < 1 || (int)srate != srate || srate > INT_MAX) {
631         av_log(log_ctx, AV_LOG_ERROR, "Invalid sample rate '%s'\n", arg);
632         return AVERROR(EINVAL);
633     }
634     *ret = srate;
635     return 0;
636 }
637
638 int ff_parse_channel_layout(int64_t *ret, int *nret, const char *arg,
639                             void *log_ctx)
640 {
641     int64_t chlayout;
642     int nb_channels;
643
644     if (av_get_extended_channel_layout(arg, &chlayout, &nb_channels) < 0) {
645         av_log(log_ctx, AV_LOG_ERROR, "Invalid channel layout '%s'\n", arg);
646         return AVERROR(EINVAL);
647     }
648     if (!chlayout && !nret) {
649         av_log(log_ctx, AV_LOG_ERROR, "Unknown channel layout '%s' is not supported.\n", arg);
650         return AVERROR(EINVAL);
651     }
652     *ret = chlayout;
653     if (nret)
654         *nret = nb_channels;
655
656     return 0;
657 }
658
659 static int check_list(void *log, const char *name, const AVFilterFormats *fmts)
660 {
661     unsigned i, j;
662
663     if (!fmts)
664         return 0;
665     if (!fmts->nb_formats) {
666         av_log(log, AV_LOG_ERROR, "Empty %s list\n", name);
667         return AVERROR(EINVAL);
668     }
669     for (i = 0; i < fmts->nb_formats; i++) {
670         for (j = i + 1; j < fmts->nb_formats; j++) {
671             if (fmts->formats[i] == fmts->formats[j]) {
672                 av_log(log, AV_LOG_ERROR, "Duplicated %s\n", name);
673                 return AVERROR(EINVAL);
674             }
675         }
676     }
677     return 0;
678 }
679
680 int ff_formats_check_pixel_formats(void *log, const AVFilterFormats *fmts)
681 {
682     return check_list(log, "pixel format", fmts);
683 }
684
685 int ff_formats_check_sample_formats(void *log, const AVFilterFormats *fmts)
686 {
687     return check_list(log, "sample format", fmts);
688 }
689
690 int ff_formats_check_sample_rates(void *log, const AVFilterFormats *fmts)
691 {
692     if (!fmts || !fmts->nb_formats)
693         return 0;
694     return check_list(log, "sample rate", fmts);
695 }
696
697 static int layouts_compatible(uint64_t a, uint64_t b)
698 {
699     return a == b ||
700            (KNOWN(a) && !KNOWN(b) && av_get_channel_layout_nb_channels(a) == FF_LAYOUT2COUNT(b)) ||
701            (KNOWN(b) && !KNOWN(a) && av_get_channel_layout_nb_channels(b) == FF_LAYOUT2COUNT(a));
702 }
703
704 int ff_formats_check_channel_layouts(void *log, const AVFilterChannelLayouts *fmts)
705 {
706     unsigned i, j;
707
708     if (!fmts)
709         return 0;
710     if (fmts->all_layouts < fmts->all_counts) {
711         av_log(log, AV_LOG_ERROR, "Inconsistent generic list\n");
712         return AVERROR(EINVAL);
713     }
714     if (!fmts->all_layouts && !fmts->nb_channel_layouts) {
715         av_log(log, AV_LOG_ERROR, "Empty channel layout list\n");
716         return AVERROR(EINVAL);
717     }
718     for (i = 0; i < fmts->nb_channel_layouts; i++) {
719         for (j = i + 1; j < fmts->nb_channel_layouts; j++) {
720             if (layouts_compatible(fmts->channel_layouts[i], fmts->channel_layouts[j])) {
721                 av_log(log, AV_LOG_ERROR, "Duplicated or redundant channel layout\n");
722                 return AVERROR(EINVAL);
723             }
724         }
725     }
726     return 0;
727 }