libavfilter/formats.c
Go to the documentation of this file.
00001 /*
00002  * Filter layer - format negotiation
00003  * Copyright (c) 2007 Bobby Bingham
00004  *
00005  * This file is part of FFmpeg.
00006  *
00007  * FFmpeg is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * FFmpeg is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with FFmpeg; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 
00022 #include "libavutil/eval.h"
00023 #include "libavutil/pixdesc.h"
00024 #include "libavutil/audioconvert.h"
00025 #include "avfilter.h"
00026 #include "internal.h"
00027 
00031 static void merge_ref(AVFilterFormats *ret, AVFilterFormats *a)
00032 {
00033     int i;
00034 
00035     for (i = 0; i < a->refcount; i++) {
00036         ret->refs[ret->refcount] = a->refs[i];
00037         *ret->refs[ret->refcount++] = ret;
00038     }
00039 
00040     av_free(a->refs);
00041     av_free(a->formats);
00042     av_free(a);
00043 }
00044 
00045 AVFilterFormats *avfilter_merge_formats(AVFilterFormats *a, AVFilterFormats *b)
00046 {
00047     AVFilterFormats *ret;
00048     unsigned i, j, k = 0;
00049 
00050     if (a == b) return a;
00051 
00052     ret = av_mallocz(sizeof(AVFilterFormats));
00053 
00054     /* merge list of formats */
00055     ret->formats = av_malloc(sizeof(*ret->formats) * FFMIN(a->format_count,
00056                                                            b->format_count));
00057     for (i = 0; i < a->format_count; i++)
00058         for (j = 0; j < b->format_count; j++)
00059             if (a->formats[i] == b->formats[j]){
00060                 if(k >= FFMIN(a->format_count, b->format_count)){
00061                     av_log(0, AV_LOG_ERROR, "Duplicate formats in avfilter_merge_formats() detected\n");
00062                     av_free(ret->formats);
00063                     av_free(ret);
00064                     return NULL;
00065                 }
00066                 ret->formats[k++] = a->formats[i];
00067             }
00068 
00069     ret->format_count = k;
00070     /* check that there was at least one common format */
00071     if (!ret->format_count) {
00072         av_free(ret->formats);
00073         av_free(ret);
00074         return NULL;
00075     }
00076 
00077     ret->refs = av_malloc(sizeof(AVFilterFormats**)*(a->refcount+b->refcount));
00078 
00079     merge_ref(ret, a);
00080     merge_ref(ret, b);
00081 
00082     return ret;
00083 }
00084 
00085 int ff_fmt_is_in(int fmt, const int *fmts)
00086 {
00087     const int *p;
00088 
00089     for (p = fmts; *p != -1; p++) {
00090         if (fmt == *p)
00091             return 1;
00092     }
00093     return 0;
00094 }
00095 
00096 #define COPY_INT_LIST(list_copy, list, type) {                          \
00097     int count = 0;                                                      \
00098     if (list)                                                           \
00099         for (count = 0; list[count] != -1; count++)                     \
00100             ;                                                           \
00101     list_copy = av_calloc(count+1, sizeof(type));                       \
00102     if (list_copy) {                                                    \
00103         memcpy(list_copy, list, sizeof(type) * count);                  \
00104         list_copy[count] = -1;                                          \
00105     }                                                                   \
00106 }
00107 
00108 int *ff_copy_int_list(const int * const list)
00109 {
00110     int *ret = NULL;
00111     COPY_INT_LIST(ret, list, int);
00112     return ret;
00113 }
00114 
00115 int64_t *ff_copy_int64_list(const int64_t * const list)
00116 {
00117     int64_t *ret = NULL;
00118     COPY_INT_LIST(ret, list, int64_t);
00119     return ret;
00120 }
00121 
00122 #define MAKE_FORMAT_LIST()                                              \
00123     AVFilterFormats *formats;                                           \
00124     int count = 0;                                                      \
00125     if (fmts)                                                           \
00126         for (count = 0; fmts[count] != -1; count++)                     \
00127             ;                                                           \
00128     formats = av_mallocz(sizeof(AVFilterFormats));                      \
00129     if (!formats) return NULL;                                          \
00130     formats->format_count = count;                                      \
00131     if (count) {                                                        \
00132         formats->formats = av_malloc(sizeof(*formats->formats)*count);  \
00133         if (!formats->formats) {                                        \
00134             av_free(formats);                                           \
00135             return NULL;                                                \
00136         }                                                               \
00137     }
00138 
00139 AVFilterFormats *avfilter_make_format_list(const int *fmts)
00140 {
00141     MAKE_FORMAT_LIST();
00142     while (count--)
00143         formats->formats[count] = fmts[count];
00144 
00145     return formats;
00146 }
00147 
00148 AVFilterFormats *avfilter_make_format64_list(const int64_t *fmts)
00149 {
00150     MAKE_FORMAT_LIST();
00151     if (count)
00152         memcpy(formats->formats, fmts, sizeof(*formats->formats) * count);
00153 
00154     return formats;
00155 }
00156 
00157 int avfilter_add_format(AVFilterFormats **avff, int64_t fmt)
00158 {
00159     int64_t *fmts;
00160 
00161     if (!(*avff) && !(*avff = av_mallocz(sizeof(AVFilterFormats))))
00162         return AVERROR(ENOMEM);
00163 
00164     fmts = av_realloc((*avff)->formats,
00165                       sizeof(*(*avff)->formats) * ((*avff)->format_count+1));
00166     if (!fmts)
00167         return AVERROR(ENOMEM);
00168 
00169     (*avff)->formats = fmts;
00170     (*avff)->formats[(*avff)->format_count++] = fmt;
00171     return 0;
00172 }
00173 
00174 #if FF_API_OLD_ALL_FORMATS_API
00175 AVFilterFormats *avfilter_all_formats(enum AVMediaType type)
00176 {
00177     return avfilter_make_all_formats(type);
00178 }
00179 #endif
00180 
00181 AVFilterFormats *avfilter_make_all_formats(enum AVMediaType type)
00182 {
00183     AVFilterFormats *ret = NULL;
00184     int fmt;
00185     int num_formats = type == AVMEDIA_TYPE_VIDEO ? PIX_FMT_NB    :
00186                       type == AVMEDIA_TYPE_AUDIO ? AV_SAMPLE_FMT_NB : 0;
00187 
00188     for (fmt = 0; fmt < num_formats; fmt++)
00189         if ((type != AVMEDIA_TYPE_VIDEO) ||
00190             (type == AVMEDIA_TYPE_VIDEO && !(av_pix_fmt_descriptors[fmt].flags & PIX_FMT_HWACCEL)))
00191             avfilter_add_format(&ret, fmt);
00192 
00193     return ret;
00194 }
00195 
00196 const int64_t avfilter_all_channel_layouts[] = {
00197 #include "all_channel_layouts.h"
00198     -1
00199 };
00200 
00201 AVFilterFormats *avfilter_make_all_channel_layouts(void)
00202 {
00203     return avfilter_make_format64_list(avfilter_all_channel_layouts);
00204 }
00205 
00206 AVFilterFormats *avfilter_make_all_packing_formats(void)
00207 {
00208     static const int packing[] = {
00209         AVFILTER_PACKED,
00210         AVFILTER_PLANAR,
00211         -1,
00212     };
00213 
00214     return avfilter_make_format_list(packing);
00215 }
00216 
00217 void avfilter_formats_ref(AVFilterFormats *f, AVFilterFormats **ref)
00218 {
00219     *ref = f;
00220     f->refs = av_realloc(f->refs, sizeof(AVFilterFormats**) * ++f->refcount);
00221     f->refs[f->refcount-1] = ref;
00222 }
00223 
00224 static int find_ref_index(AVFilterFormats **ref)
00225 {
00226     int i;
00227     for (i = 0; i < (*ref)->refcount; i++)
00228         if ((*ref)->refs[i] == ref)
00229             return i;
00230     return -1;
00231 }
00232 
00233 void avfilter_formats_unref(AVFilterFormats **ref)
00234 {
00235     int idx;
00236 
00237     if (!*ref)
00238         return;
00239 
00240     idx = find_ref_index(ref);
00241 
00242     if (idx >= 0)
00243         memmove((*ref)->refs + idx, (*ref)->refs + idx+1,
00244             sizeof(AVFilterFormats**) * ((*ref)->refcount-idx-1));
00245 
00246     if (!--(*ref)->refcount) {
00247         av_free((*ref)->formats);
00248         av_free((*ref)->refs);
00249         av_free(*ref);
00250     }
00251     *ref = NULL;
00252 }
00253 
00254 void avfilter_formats_changeref(AVFilterFormats **oldref,
00255                                 AVFilterFormats **newref)
00256 {
00257     int idx = find_ref_index(oldref);
00258 
00259     if (idx >= 0) {
00260         (*oldref)->refs[idx] = newref;
00261         *newref = *oldref;
00262         *oldref = NULL;
00263     }
00264 }
00265 
00266 /* internal functions for parsing audio format arguments */
00267 
00268 int ff_parse_pixel_format(enum PixelFormat *ret, const char *arg, void *log_ctx)
00269 {
00270     char *tail;
00271     int pix_fmt = av_get_pix_fmt(arg);
00272     if (pix_fmt == PIX_FMT_NONE) {
00273         pix_fmt = strtol(arg, &tail, 0);
00274         if (*tail || (unsigned)pix_fmt >= PIX_FMT_NB) {
00275             av_log(log_ctx, AV_LOG_ERROR, "Invalid pixel format '%s'\n", arg);
00276             return AVERROR(EINVAL);
00277         }
00278     }
00279     *ret = pix_fmt;
00280     return 0;
00281 }
00282 
00283 int ff_parse_sample_format(int *ret, const char *arg, void *log_ctx)
00284 {
00285     char *tail;
00286     int sfmt = av_get_sample_fmt(arg);
00287     if (sfmt == AV_SAMPLE_FMT_NONE) {
00288         sfmt = strtol(arg, &tail, 0);
00289         if (*tail || (unsigned)sfmt >= AV_SAMPLE_FMT_NB) {
00290             av_log(log_ctx, AV_LOG_ERROR, "Invalid sample format '%s'\n", arg);
00291             return AVERROR(EINVAL);
00292         }
00293     }
00294     *ret = sfmt;
00295     return 0;
00296 }
00297 
00298 int ff_parse_sample_rate(int *ret, const char *arg, void *log_ctx)
00299 {
00300     char *tail;
00301     double srate = av_strtod(arg, &tail);
00302     if (*tail || srate < 1 || (int)srate != srate || srate > INT_MAX) {
00303         av_log(log_ctx, AV_LOG_ERROR, "Invalid sample rate '%s'\n", arg);
00304         return AVERROR(EINVAL);
00305     }
00306     *ret = srate;
00307     return 0;
00308 }
00309 
00310 int ff_parse_channel_layout(int64_t *ret, const char *arg, void *log_ctx)
00311 {
00312     char *tail;
00313     int64_t chlayout = av_get_channel_layout(arg);
00314     if (chlayout == 0) {
00315         chlayout = strtol(arg, &tail, 10);
00316         if (*tail || chlayout == 0) {
00317             av_log(log_ctx, AV_LOG_ERROR, "Invalid channel layout '%s'\n", arg);
00318             return AVERROR(EINVAL);
00319         }
00320     }
00321     *ret = chlayout;
00322     return 0;
00323 }
00324 
00325 int ff_parse_packing_format(int *ret, const char *arg, void *log_ctx)
00326 {
00327     char *tail;
00328     int planar = strtol(arg, &tail, 10);
00329     if (*tail) {
00330         planar = !strcmp(arg, "packed") ? 0:
00331                  !strcmp(arg, "planar") ? 1: -1;
00332     }
00333 
00334     if (planar != 0 && planar != 1) {
00335         av_log(log_ctx, AV_LOG_ERROR, "Invalid packing format '%s'\n", arg);
00336         return AVERROR(EINVAL);
00337     }
00338     *ret = planar;
00339     return 0;
00340 }
00341 
00342 #ifdef TEST
00343 
00344 #undef printf
00345 
00346 int main(void)
00347 {
00348     const int64_t *cl;
00349     char buf[512];
00350 
00351     for (cl = avfilter_all_channel_layouts; *cl != -1; cl++) {
00352         av_get_channel_layout_string(buf, sizeof(buf), -1, *cl);
00353         printf("%s\n", buf);
00354     }
00355 
00356     return 0;
00357 }
00358 
00359 #endif