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