00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
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
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 MAKE_FORMAT_LIST() \
00097 AVFilterFormats *formats; \
00098 int count = 0; \
00099 if (fmts) \
00100 for (count = 0; fmts[count] != -1; count++) \
00101 ; \
00102 formats = av_mallocz(sizeof(AVFilterFormats)); \
00103 if (!formats) return NULL; \
00104 formats->format_count = count; \
00105 if (count) { \
00106 formats->formats = av_malloc(sizeof(*formats->formats)*count); \
00107 if (!formats->formats) { \
00108 av_free(formats); \
00109 return NULL; \
00110 } \
00111 }
00112
00113 AVFilterFormats *avfilter_make_format_list(const int *fmts)
00114 {
00115 MAKE_FORMAT_LIST();
00116 while (count--)
00117 formats->formats[count] = fmts[count];
00118
00119 return formats;
00120 }
00121
00122 AVFilterFormats *avfilter_make_format64_list(const int64_t *fmts)
00123 {
00124 MAKE_FORMAT_LIST();
00125 if (count)
00126 memcpy(formats->formats, fmts, sizeof(*formats->formats) * count);
00127
00128 return formats;
00129 }
00130
00131 int avfilter_add_format(AVFilterFormats **avff, int64_t fmt)
00132 {
00133 int64_t *fmts;
00134
00135 if (!(*avff) && !(*avff = av_mallocz(sizeof(AVFilterFormats))))
00136 return AVERROR(ENOMEM);
00137
00138 fmts = av_realloc((*avff)->formats,
00139 sizeof(*(*avff)->formats) * ((*avff)->format_count+1));
00140 if (!fmts)
00141 return AVERROR(ENOMEM);
00142
00143 (*avff)->formats = fmts;
00144 (*avff)->formats[(*avff)->format_count++] = fmt;
00145 return 0;
00146 }
00147
00148 #if FF_API_OLD_ALL_FORMATS_API
00149 AVFilterFormats *avfilter_all_formats(enum AVMediaType type)
00150 {
00151 return avfilter_make_all_formats(type);
00152 }
00153 #endif
00154
00155 AVFilterFormats *avfilter_make_all_formats(enum AVMediaType type)
00156 {
00157 AVFilterFormats *ret = NULL;
00158 int fmt;
00159 int num_formats = type == AVMEDIA_TYPE_VIDEO ? PIX_FMT_NB :
00160 type == AVMEDIA_TYPE_AUDIO ? AV_SAMPLE_FMT_NB : 0;
00161
00162 for (fmt = 0; fmt < num_formats; fmt++)
00163 if ((type != AVMEDIA_TYPE_VIDEO) ||
00164 (type == AVMEDIA_TYPE_VIDEO && !(av_pix_fmt_descriptors[fmt].flags & PIX_FMT_HWACCEL)))
00165 avfilter_add_format(&ret, fmt);
00166
00167 return ret;
00168 }
00169
00170 const int64_t avfilter_all_channel_layouts[] = {
00171 #include "all_channel_layouts.h"
00172 -1
00173 };
00174
00175 AVFilterFormats *avfilter_make_all_channel_layouts(void)
00176 {
00177 return avfilter_make_format64_list(avfilter_all_channel_layouts);
00178 }
00179
00180 AVFilterFormats *avfilter_make_all_packing_formats(void)
00181 {
00182 static const int packing[] = {
00183 AVFILTER_PACKED,
00184 AVFILTER_PLANAR,
00185 -1,
00186 };
00187
00188 return avfilter_make_format_list(packing);
00189 }
00190
00191 void avfilter_formats_ref(AVFilterFormats *f, AVFilterFormats **ref)
00192 {
00193 *ref = f;
00194 f->refs = av_realloc(f->refs, sizeof(AVFilterFormats**) * ++f->refcount);
00195 f->refs[f->refcount-1] = ref;
00196 }
00197
00198 static int find_ref_index(AVFilterFormats **ref)
00199 {
00200 int i;
00201 for (i = 0; i < (*ref)->refcount; i++)
00202 if ((*ref)->refs[i] == ref)
00203 return i;
00204 return -1;
00205 }
00206
00207 void avfilter_formats_unref(AVFilterFormats **ref)
00208 {
00209 int idx;
00210
00211 if (!*ref)
00212 return;
00213
00214 idx = find_ref_index(ref);
00215
00216 if (idx >= 0)
00217 memmove((*ref)->refs + idx, (*ref)->refs + idx+1,
00218 sizeof(AVFilterFormats**) * ((*ref)->refcount-idx-1));
00219
00220 if (!--(*ref)->refcount) {
00221 av_free((*ref)->formats);
00222 av_free((*ref)->refs);
00223 av_free(*ref);
00224 }
00225 *ref = NULL;
00226 }
00227
00228 void avfilter_formats_changeref(AVFilterFormats **oldref,
00229 AVFilterFormats **newref)
00230 {
00231 int idx = find_ref_index(oldref);
00232
00233 if (idx >= 0) {
00234 (*oldref)->refs[idx] = newref;
00235 *newref = *oldref;
00236 *oldref = NULL;
00237 }
00238 }
00239
00240
00241
00242 int ff_parse_pixel_format(enum PixelFormat *ret, const char *arg, void *log_ctx)
00243 {
00244 char *tail;
00245 int pix_fmt = av_get_pix_fmt(arg);
00246 if (pix_fmt == PIX_FMT_NONE) {
00247 pix_fmt = strtol(arg, &tail, 0);
00248 if (*tail || (unsigned)pix_fmt >= PIX_FMT_NB) {
00249 av_log(log_ctx, AV_LOG_ERROR, "Invalid pixel format '%s'\n", arg);
00250 return AVERROR(EINVAL);
00251 }
00252 }
00253 *ret = pix_fmt;
00254 return 0;
00255 }
00256
00257 int ff_parse_sample_format(int *ret, const char *arg, void *log_ctx)
00258 {
00259 char *tail;
00260 int sfmt = av_get_sample_fmt(arg);
00261 if (sfmt == AV_SAMPLE_FMT_NONE) {
00262 sfmt = strtol(arg, &tail, 0);
00263 if (*tail || (unsigned)sfmt >= AV_SAMPLE_FMT_NB) {
00264 av_log(log_ctx, AV_LOG_ERROR, "Invalid sample format '%s'\n", arg);
00265 return AVERROR(EINVAL);
00266 }
00267 }
00268 *ret = sfmt;
00269 return 0;
00270 }
00271
00272 int ff_parse_sample_rate(int *ret, const char *arg, void *log_ctx)
00273 {
00274 char *tail;
00275 double srate = av_strtod(arg, &tail);
00276 if (*tail || srate < 1 || (int)srate != srate || srate > INT_MAX) {
00277 av_log(log_ctx, AV_LOG_ERROR, "Invalid sample rate '%s'\n", arg);
00278 return AVERROR(EINVAL);
00279 }
00280 *ret = srate;
00281 return 0;
00282 }
00283
00284 int ff_parse_channel_layout(int64_t *ret, const char *arg, void *log_ctx)
00285 {
00286 char *tail;
00287 int64_t chlayout = av_get_channel_layout(arg);
00288 if (chlayout == 0) {
00289 chlayout = strtol(arg, &tail, 10);
00290 if (*tail || chlayout == 0) {
00291 av_log(log_ctx, AV_LOG_ERROR, "Invalid channel layout '%s'\n", arg);
00292 return AVERROR(EINVAL);
00293 }
00294 }
00295 *ret = chlayout;
00296 return 0;
00297 }
00298
00299 int ff_parse_packing_format(int *ret, const char *arg, void *log_ctx)
00300 {
00301 char *tail;
00302 int planar = strtol(arg, &tail, 10);
00303 if (*tail) {
00304 planar = !strcmp(arg, "packed") ? 0:
00305 !strcmp(arg, "planar") ? 1: -1;
00306 }
00307
00308 if (planar != 0 && planar != 1) {
00309 av_log(log_ctx, AV_LOG_ERROR, "Invalid packing format '%s'\n", arg);
00310 return AVERROR(EINVAL);
00311 }
00312 *ret = planar;
00313 return 0;
00314 }
00315
00316 #ifdef TEST
00317
00318 #undef printf
00319
00320 int main(void)
00321 {
00322 const int64_t *cl;
00323 char buf[512];
00324
00325 for (cl = avfilter_all_channel_layouts; *cl != -1; cl++) {
00326 av_get_channel_layout_string(buf, sizeof(buf), -1, *cl);
00327 printf("%s\n", buf);
00328 }
00329
00330 return 0;
00331 }
00332
00333 #endif