return formats;
}
-#if LIBAVFILTER_VERSION_MAJOR < 8
-AVFilterChannelLayouts *avfilter_make_format64_list(const int64_t *fmts)
-{
- return ff_make_format64_list(fmts);
-}
-#endif
-
#define ADD_FORMAT(f, fmt, unref_fn, type, list, nb) \
do { \
type *fmts; \
- void *oldf = *f; \
\
if (!(*f) && !(*f = av_mallocz(sizeof(**f)))) { \
return AVERROR(ENOMEM); \
sizeof(*(*f)->list)); \
if (!fmts) { \
unref_fn(f); \
- if (!oldf) \
- av_freep(f); \
return AVERROR(ENOMEM); \
} \
\
#define FORMATS_REF(f, ref, unref_fn) \
void *tmp; \
\
- if (!f || !ref) \
+ if (!f) \
return AVERROR(ENOMEM); \
\
tmp = av_realloc_array(f->refs, sizeof(*f->refs), f->refcount + 1); \
do { \
int idx = -1; \
\
- if (!ref || !*ref || !(*ref)->refs) \
+ if (!*ref) \
return; \
\
FIND_REF_INDEX(ref, idx); \
\
- if (idx >= 0) \
+ if (idx >= 0) { \
memmove((*ref)->refs + idx, (*ref)->refs + idx + 1, \
sizeof(*(*ref)->refs) * ((*ref)->refcount - idx - 1)); \
- \
- if(!--(*ref)->refcount) { \
+ --(*ref)->refcount; \
+ } \
+ if (!(*ref)->refcount) { \
av_free((*ref)->list); \
av_free((*ref)->refs); \
av_free(*ref); \
FORMATS_CHANGEREF(oldref, newref);
}
-#define SET_COMMON_FORMATS(ctx, fmts, in_fmts, out_fmts, ref_fn, unref_fn, list) \
+#define SET_COMMON_FORMATS(ctx, fmts, ref_fn, unref_fn) \
int count = 0, i; \
\
if (!fmts) \
return AVERROR(ENOMEM); \
\
for (i = 0; i < ctx->nb_inputs; i++) { \
- if (ctx->inputs[i] && !ctx->inputs[i]->out_fmts) { \
- int ret = ref_fn(fmts, &ctx->inputs[i]->out_fmts); \
+ if (ctx->inputs[i] && !ctx->inputs[i]->outcfg.fmts) { \
+ int ret = ref_fn(fmts, &ctx->inputs[i]->outcfg.fmts); \
if (ret < 0) { \
- unref_fn(&fmts); \
- if (fmts) \
- av_freep(&fmts->list); \
- av_freep(&fmts); \
return ret; \
} \
count++; \
} \
} \
for (i = 0; i < ctx->nb_outputs; i++) { \
- if (ctx->outputs[i] && !ctx->outputs[i]->in_fmts) { \
- int ret = ref_fn(fmts, &ctx->outputs[i]->in_fmts); \
+ if (ctx->outputs[i] && !ctx->outputs[i]->incfg.fmts) { \
+ int ret = ref_fn(fmts, &ctx->outputs[i]->incfg.fmts); \
if (ret < 0) { \
- unref_fn(&fmts); \
- if (fmts) \
- av_freep(&fmts->list); \
- av_freep(&fmts); \
return ret; \
} \
count++; \
} \
\
if (!count) { \
- av_freep(&fmts->list); \
- av_freep(&fmts->refs); \
- av_freep(&fmts); \
+ unref_fn(&fmts); \
} \
\
return 0;
int ff_set_common_channel_layouts(AVFilterContext *ctx,
- AVFilterChannelLayouts *layouts)
+ AVFilterChannelLayouts *channel_layouts)
{
- SET_COMMON_FORMATS(ctx, layouts, in_channel_layouts, out_channel_layouts,
- ff_channel_layouts_ref, ff_channel_layouts_unref, channel_layouts);
+ SET_COMMON_FORMATS(ctx, channel_layouts,
+ ff_channel_layouts_ref, ff_channel_layouts_unref);
}
int ff_set_common_samplerates(AVFilterContext *ctx,
AVFilterFormats *samplerates)
{
- SET_COMMON_FORMATS(ctx, samplerates, in_samplerates, out_samplerates,
- ff_formats_ref, ff_formats_unref, formats);
+ SET_COMMON_FORMATS(ctx, samplerates,
+ ff_formats_ref, ff_formats_unref);
}
/**
*/
int ff_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats)
{
- SET_COMMON_FORMATS(ctx, formats, in_formats, out_formats,
- ff_formats_ref, ff_formats_unref, formats);
+ SET_COMMON_FORMATS(ctx, formats,
+ ff_formats_ref, ff_formats_unref);
}
int ff_default_query_formats(AVFilterContext *ctx)
{
int ret;
- enum AVMediaType type = ctx->inputs && ctx->inputs [0] ? ctx->inputs [0]->type :
- ctx->outputs && ctx->outputs[0] ? ctx->outputs[0]->type :
+ enum AVMediaType type = ctx->nb_inputs ? ctx->inputs [0]->type :
+ ctx->nb_outputs ? ctx->outputs[0]->type :
AVMEDIA_TYPE_VIDEO;
ret = ff_set_common_formats(ctx, ff_all_formats(type));
return 0;
}
+
+static int check_list(void *log, const char *name, const AVFilterFormats *fmts)
+{
+ unsigned i, j;
+
+ if (!fmts)
+ return 0;
+ if (!fmts->nb_formats) {
+ av_log(log, AV_LOG_ERROR, "Empty %s list\n", name);
+ return AVERROR(EINVAL);
+ }
+ for (i = 0; i < fmts->nb_formats; i++) {
+ for (j = i + 1; j < fmts->nb_formats; j++) {
+ if (fmts->formats[i] == fmts->formats[j]) {
+ av_log(log, AV_LOG_ERROR, "Duplicated %s\n", name);
+ return AVERROR(EINVAL);
+ }
+ }
+ }
+ return 0;
+}
+
+int ff_formats_check_pixel_formats(void *log, const AVFilterFormats *fmts)
+{
+ return check_list(log, "pixel format", fmts);
+}
+
+int ff_formats_check_sample_formats(void *log, const AVFilterFormats *fmts)
+{
+ return check_list(log, "sample format", fmts);
+}
+
+int ff_formats_check_sample_rates(void *log, const AVFilterFormats *fmts)
+{
+ if (!fmts || !fmts->nb_formats)
+ return 0;
+ return check_list(log, "sample rate", fmts);
+}
+
+static int layouts_compatible(uint64_t a, uint64_t b)
+{
+ return a == b ||
+ (KNOWN(a) && !KNOWN(b) && av_get_channel_layout_nb_channels(a) == FF_LAYOUT2COUNT(b)) ||
+ (KNOWN(b) && !KNOWN(a) && av_get_channel_layout_nb_channels(b) == FF_LAYOUT2COUNT(a));
+}
+
+int ff_formats_check_channel_layouts(void *log, const AVFilterChannelLayouts *fmts)
+{
+ unsigned i, j;
+
+ if (!fmts)
+ return 0;
+ if (fmts->all_layouts < fmts->all_counts) {
+ av_log(log, AV_LOG_ERROR, "Inconsistent generic list\n");
+ return AVERROR(EINVAL);
+ }
+ if (!fmts->all_layouts && !fmts->nb_channel_layouts) {
+ av_log(log, AV_LOG_ERROR, "Empty channel layout list\n");
+ return AVERROR(EINVAL);
+ }
+ for (i = 0; i < fmts->nb_channel_layouts; i++) {
+ for (j = i + 1; j < fmts->nb_channel_layouts; j++) {
+ if (layouts_compatible(fmts->channel_layouts[i], fmts->channel_layouts[j])) {
+ av_log(log, AV_LOG_ERROR, "Duplicated or redundant channel layout\n");
+ return AVERROR(EINVAL);
+ }
+ }
+ }
+ return 0;
+}