avfilter: Error out from avfilter_merge_formats() when there are duplicates
[ffmpeg.git] / 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/eval.h"
23 #include "libavutil/pixdesc.h"
24 #include "libavutil/audioconvert.h"
25 #include "avfilter.h"
26 #include "internal.h"
27
28 /**
29  * Add all refs from a to ret and destroy a.
30  */
31 static void merge_ref(AVFilterFormats *ret, AVFilterFormats *a)
32 {
33     int i;
34
35     for (i = 0; i < a->refcount; i++) {
36         ret->refs[ret->refcount] = a->refs[i];
37         *ret->refs[ret->refcount++] = ret;
38     }
39
40     av_free(a->refs);
41     av_free(a->formats);
42     av_free(a);
43 }
44
45 AVFilterFormats *avfilter_merge_formats(AVFilterFormats *a, AVFilterFormats *b)
46 {
47     AVFilterFormats *ret;
48     unsigned i, j, k = 0;
49
50     if (a == b) return a;
51
52     ret = av_mallocz(sizeof(AVFilterFormats));
53
54     /* merge list of formats */
55     ret->formats = av_malloc(sizeof(*ret->formats) * FFMIN(a->format_count,
56                                                            b->format_count));
57     for (i = 0; i < a->format_count; i++)
58         for (j = 0; j < b->format_count; j++)
59             if (a->formats[i] == b->formats[j]){
60                 if(k >= FFMIN(a->format_count, b->format_count)){
61                     av_log(0, AV_LOG_ERROR, "Duplicate formats in avfilter_merge_formats() detected\n");
62                     av_free(ret->formats);
63                     av_free(ret);
64                     return NULL;
65                 }
66                 ret->formats[k++] = a->formats[i];
67             }
68
69     ret->format_count = k;
70     /* check that there was at least one common format */
71     if (!ret->format_count) {
72         av_free(ret->formats);
73         av_free(ret);
74         return NULL;
75     }
76
77     ret->refs = av_malloc(sizeof(AVFilterFormats**)*(a->refcount+b->refcount));
78
79     merge_ref(ret, a);
80     merge_ref(ret, b);
81
82     return ret;
83 }
84
85 int ff_fmt_is_in(int fmt, const int *fmts)
86 {
87     const int *p;
88
89     for (p = fmts; *p != -1; p++) {
90         if (fmt == *p)
91             return 1;
92     }
93     return 0;
94 }
95
96 #define MAKE_FORMAT_LIST()                                              \
97     AVFilterFormats *formats;                                           \
98     int count = 0;                                                      \
99     if (fmts)                                                           \
100         for (count = 0; fmts[count] != -1; count++)                     \
101             ;                                                           \
102     formats = av_mallocz(sizeof(AVFilterFormats));                      \
103     if (!formats) return NULL;                                          \
104     formats->format_count = count;                                      \
105     if (count) {                                                        \
106         formats->formats = av_malloc(sizeof(*formats->formats)*count);  \
107         if (!formats->formats) {                                        \
108             av_free(formats);                                           \
109             return NULL;                                                \
110         }                                                               \
111     }
112
113 AVFilterFormats *avfilter_make_format_list(const int *fmts)
114 {
115     MAKE_FORMAT_LIST();
116     while (count--)
117         formats->formats[count] = fmts[count];
118
119     return formats;
120 }
121
122 AVFilterFormats *avfilter_make_format64_list(const int64_t *fmts)
123 {
124     MAKE_FORMAT_LIST();
125     if (count)
126         memcpy(formats->formats, fmts, sizeof(*formats->formats) * count);
127
128     return formats;
129 }
130
131 int avfilter_add_format(AVFilterFormats **avff, int64_t fmt)
132 {
133     int64_t *fmts;
134
135     if (!(*avff) && !(*avff = av_mallocz(sizeof(AVFilterFormats))))
136         return AVERROR(ENOMEM);
137
138     fmts = av_realloc((*avff)->formats,
139                       sizeof(*(*avff)->formats) * ((*avff)->format_count+1));
140     if (!fmts)
141         return AVERROR(ENOMEM);
142
143     (*avff)->formats = fmts;
144     (*avff)->formats[(*avff)->format_count++] = fmt;
145     return 0;
146 }
147
148 #if FF_API_OLD_ALL_FORMATS_API
149 AVFilterFormats *avfilter_all_formats(enum AVMediaType type)
150 {
151     return avfilter_make_all_formats(type);
152 }
153 #endif
154
155 AVFilterFormats *avfilter_make_all_formats(enum AVMediaType type)
156 {
157     AVFilterFormats *ret = NULL;
158     int fmt;
159     int num_formats = type == AVMEDIA_TYPE_VIDEO ? PIX_FMT_NB    :
160                       type == AVMEDIA_TYPE_AUDIO ? AV_SAMPLE_FMT_NB : 0;
161
162     for (fmt = 0; fmt < num_formats; fmt++)
163         if ((type != AVMEDIA_TYPE_VIDEO) ||
164             (type == AVMEDIA_TYPE_VIDEO && !(av_pix_fmt_descriptors[fmt].flags & PIX_FMT_HWACCEL)))
165             avfilter_add_format(&ret, fmt);
166
167     return ret;
168 }
169
170 const int64_t avfilter_all_channel_layouts[] = {
171 #include "all_channel_layouts.h"
172     -1
173 };
174
175 AVFilterFormats *avfilter_make_all_channel_layouts(void)
176 {
177     return avfilter_make_format64_list(avfilter_all_channel_layouts);
178 }
179
180 AVFilterFormats *avfilter_make_all_packing_formats(void)
181 {
182     static const int packing[] = {
183         AVFILTER_PACKED,
184         AVFILTER_PLANAR,
185         -1,
186     };
187
188     return avfilter_make_format_list(packing);
189 }
190
191 void avfilter_formats_ref(AVFilterFormats *f, AVFilterFormats **ref)
192 {
193     *ref = f;
194     f->refs = av_realloc(f->refs, sizeof(AVFilterFormats**) * ++f->refcount);
195     f->refs[f->refcount-1] = ref;
196 }
197
198 static int find_ref_index(AVFilterFormats **ref)
199 {
200     int i;
201     for (i = 0; i < (*ref)->refcount; i++)
202         if ((*ref)->refs[i] == ref)
203             return i;
204     return -1;
205 }
206
207 void avfilter_formats_unref(AVFilterFormats **ref)
208 {
209     int idx;
210
211     if (!*ref)
212         return;
213
214     idx = find_ref_index(ref);
215
216     if (idx >= 0)
217         memmove((*ref)->refs + idx, (*ref)->refs + idx+1,
218             sizeof(AVFilterFormats**) * ((*ref)->refcount-idx-1));
219
220     if (!--(*ref)->refcount) {
221         av_free((*ref)->formats);
222         av_free((*ref)->refs);
223         av_free(*ref);
224     }
225     *ref = NULL;
226 }
227
228 void avfilter_formats_changeref(AVFilterFormats **oldref,
229                                 AVFilterFormats **newref)
230 {
231     int idx = find_ref_index(oldref);
232
233     if (idx >= 0) {
234         (*oldref)->refs[idx] = newref;
235         *newref = *oldref;
236         *oldref = NULL;
237     }
238 }
239
240 /* internal functions for parsing audio format arguments */
241
242 int ff_parse_pixel_format(enum PixelFormat *ret, const char *arg, void *log_ctx)
243 {
244     char *tail;
245     int pix_fmt = av_get_pix_fmt(arg);
246     if (pix_fmt == PIX_FMT_NONE) {
247         pix_fmt = strtol(arg, &tail, 0);
248         if (*tail || (unsigned)pix_fmt >= PIX_FMT_NB) {
249             av_log(log_ctx, AV_LOG_ERROR, "Invalid pixel format '%s'\n", arg);
250             return AVERROR(EINVAL);
251         }
252     }
253     *ret = pix_fmt;
254     return 0;
255 }
256
257 int ff_parse_sample_format(int *ret, const char *arg, void *log_ctx)
258 {
259     char *tail;
260     int sfmt = av_get_sample_fmt(arg);
261     if (sfmt == AV_SAMPLE_FMT_NONE) {
262         sfmt = strtol(arg, &tail, 0);
263         if (*tail || (unsigned)sfmt >= AV_SAMPLE_FMT_NB) {
264             av_log(log_ctx, AV_LOG_ERROR, "Invalid sample format '%s'\n", arg);
265             return AVERROR(EINVAL);
266         }
267     }
268     *ret = sfmt;
269     return 0;
270 }
271
272 int ff_parse_sample_rate(int *ret, const char *arg, void *log_ctx)
273 {
274     char *tail;
275     double srate = av_strtod(arg, &tail);
276     if (*tail || srate < 1 || (int)srate != srate || srate > INT_MAX) {
277         av_log(log_ctx, AV_LOG_ERROR, "Invalid sample rate '%s'\n", arg);
278         return AVERROR(EINVAL);
279     }
280     *ret = srate;
281     return 0;
282 }
283
284 int ff_parse_channel_layout(int64_t *ret, const char *arg, void *log_ctx)
285 {
286     char *tail;
287     int64_t chlayout = av_get_channel_layout(arg);
288     if (chlayout == 0) {
289         chlayout = strtol(arg, &tail, 10);
290         if (*tail || chlayout == 0) {
291             av_log(log_ctx, AV_LOG_ERROR, "Invalid channel layout '%s'\n", arg);
292             return AVERROR(EINVAL);
293         }
294     }
295     *ret = chlayout;
296     return 0;
297 }
298
299 int ff_parse_packing_format(int *ret, const char *arg, void *log_ctx)
300 {
301     char *tail;
302     int planar = strtol(arg, &tail, 10);
303     if (*tail) {
304         planar = !strcmp(arg, "packed") ? 0:
305                  !strcmp(arg, "planar") ? 1: -1;
306     }
307
308     if (planar != 0 && planar != 1) {
309         av_log(log_ctx, AV_LOG_ERROR, "Invalid packing format '%s'\n", arg);
310         return AVERROR(EINVAL);
311     }
312     *ret = planar;
313     return 0;
314 }
315
316 #ifdef TEST
317
318 #undef printf
319
320 int main(void)
321 {
322     const int64_t *cl;
323     char buf[512];
324
325     for (cl = avfilter_all_channel_layouts; *cl != -1; cl++) {
326         av_get_channel_layout_string(buf, sizeof(buf), -1, *cl);
327         printf("%s\n", buf);
328     }
329
330     return 0;
331 }
332
333 #endif