Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

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