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