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