2 * Copyright (c) 2007 Bobby Bingham
4 * This file is part of FFmpeg.
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 * format and noformat video filters
26 #include "config_components.h"
30 #include "libavutil/internal.h"
31 #include "libavutil/mem.h"
32 #include "libavutil/pixdesc.h"
33 #include "libavutil/opt.h"
40 typedef struct FormatContext
{
46 AVFilterFormats
*formats
; ///< parsed from `pix_fmts`
47 AVFilterFormats
*color_spaces
; ///< parsed from `csps`
48 AVFilterFormats
*color_ranges
; ///< parsed from `ranges`
51 static av_cold
void uninit(AVFilterContext
*ctx
)
53 FormatContext
*s
= ctx
->priv
;
54 ff_formats_unref(&s
->formats
);
55 ff_formats_unref(&s
->color_spaces
);
56 ff_formats_unref(&s
->color_ranges
);
59 static av_cold
int invert_formats(AVFilterFormats
**fmts
,
60 AVFilterFormats
*allfmts
)
63 return AVERROR(ENOMEM
);
65 /* empty fmt list means no restriction, regardless of filter type */
66 ff_formats_unref(&allfmts
);
70 for (int i
= 0; i
< allfmts
->nb_formats
; i
++) {
71 for (int j
= 0; j
< (*fmts
)->nb_formats
; j
++) {
72 if (allfmts
->formats
[i
] == (*fmts
)->formats
[j
]) {
73 /* format is forbidden, remove it from allfmts list */
74 memmove(&allfmts
->formats
[i
], &allfmts
->formats
[i
+1],
75 (allfmts
->nb_formats
- (i
+1)) * sizeof(*allfmts
->formats
));
76 allfmts
->nb_formats
--;
77 i
--; /* repeat loop with same idx */
83 ff_formats_unref(fmts
);
88 static int parse_pixel_format(enum AVPixelFormat
*ret
, const char *arg
, void *log_ctx
)
91 int pix_fmt
= av_get_pix_fmt(arg
);
92 if (pix_fmt
== AV_PIX_FMT_NONE
) {
93 pix_fmt
= strtol(arg
, &tail
, 0);
94 if (*tail
|| !av_pix_fmt_desc_get(pix_fmt
)) {
95 av_log(log_ctx
, AV_LOG_ERROR
, "Invalid pixel format '%s'\n", arg
);
96 return AVERROR(EINVAL
);
103 static av_cold
int init(AVFilterContext
*ctx
)
105 FormatContext
*s
= ctx
->priv
;
106 enum AVPixelFormat pix_fmt
;
109 for (char *sep
, *cur
= s
->pix_fmts
; cur
; cur
= sep
) {
110 sep
= strchr(cur
, '|');
113 if ((ret
= parse_pixel_format(&pix_fmt
, cur
, ctx
)) < 0 ||
114 (ret
= ff_add_format(&s
->formats
, pix_fmt
)) < 0)
118 for (char *sep
, *cur
= s
->csps
; cur
; cur
= sep
) {
119 sep
= strchr(cur
, '|');
122 if ((ret
= av_color_space_from_name(cur
)) < 0 ||
123 (ret
= ff_add_format(&s
->color_spaces
, ret
)) < 0)
127 for (char *sep
, *cur
= s
->ranges
; cur
; cur
= sep
) {
128 sep
= strchr(cur
, '|');
131 if ((ret
= av_color_range_from_name(cur
)) < 0 ||
132 (ret
= ff_add_format(&s
->color_ranges
, ret
)) < 0)
136 if (!strcmp(ctx
->filter
->name
, "noformat")) {
137 if ((ret
= invert_formats(&s
->formats
, ff_all_formats(AVMEDIA_TYPE_VIDEO
))) < 0 ||
138 (ret
= invert_formats(&s
->color_spaces
, ff_all_color_spaces())) < 0 ||
139 (ret
= invert_formats(&s
->color_ranges
, ff_all_color_ranges())) < 0)
143 /* hold on to a ref for the lifetime of the filter */
144 if (s
->formats
&& (ret
= ff_formats_ref(s
->formats
, &s
->formats
)) < 0 ||
145 s
->color_spaces
&& (ret
= ff_formats_ref(s
->color_spaces
, &s
->color_spaces
)) < 0 ||
146 s
->color_ranges
&& (ret
= ff_formats_ref(s
->color_ranges
, &s
->color_ranges
)) < 0)
152 static int query_formats(const AVFilterContext
*ctx
,
153 AVFilterFormatsConfig
**cfg_in
,
154 AVFilterFormatsConfig
**cfg_out
)
156 FormatContext
*s
= ctx
->priv
;
159 if (s
->formats
&& (ret
= ff_set_common_formats2 (ctx
, cfg_in
, cfg_out
, s
->formats
)) < 0 ||
160 s
->color_spaces
&& (ret
= ff_set_common_color_spaces2(ctx
, cfg_in
, cfg_out
, s
->color_spaces
)) < 0 ||
161 s
->color_ranges
&& (ret
= ff_set_common_color_ranges2(ctx
, cfg_in
, cfg_out
, s
->color_ranges
)) < 0)
168 #define OFFSET(x) offsetof(FormatContext, x)
169 static const AVOption options
[] = {
170 { "pix_fmts", "A '|'-separated list of pixel formats", OFFSET(pix_fmts
), AV_OPT_TYPE_STRING
, .flags
= AV_OPT_FLAG_VIDEO_PARAM
| AV_OPT_FLAG_FILTERING_PARAM
},
171 { "color_spaces", "A '|'-separated list of color spaces", OFFSET(csps
), AV_OPT_TYPE_STRING
, .flags
= AV_OPT_FLAG_VIDEO_PARAM
| AV_OPT_FLAG_FILTERING_PARAM
},
172 { "color_ranges", "A '|'-separated list of color ranges", OFFSET(ranges
), AV_OPT_TYPE_STRING
, .flags
= AV_OPT_FLAG_VIDEO_PARAM
| AV_OPT_FLAG_FILTERING_PARAM
},
176 AVFILTER_DEFINE_CLASS_EXT(format
, "(no)format", options
);
178 static const AVFilterPad inputs
[] = {
181 .type
= AVMEDIA_TYPE_VIDEO
,
182 .get_buffer
.video
= ff_null_get_video_buffer
,
186 #if CONFIG_FORMAT_FILTER
187 const FFFilter ff_vf_format
= {
189 .p
.description
= NULL_IF_CONFIG_SMALL("Convert the input video to one of the specified pixel formats."),
190 .p
.priv_class
= &format_class
,
192 .p
.flags
= AVFILTER_FLAG_METADATA_ONLY
,
197 .priv_size
= sizeof(FormatContext
),
199 FILTER_INPUTS(inputs
),
200 FILTER_OUTPUTS(ff_video_default_filterpad
),
202 FILTER_QUERY_FUNC2(query_formats
),
204 #endif /* CONFIG_FORMAT_FILTER */
206 #if CONFIG_NOFORMAT_FILTER
207 const FFFilter ff_vf_noformat
= {
208 .p
.name
= "noformat",
209 .p
.description
= NULL_IF_CONFIG_SMALL("Force libavfilter not to use any of the specified pixel formats for the input to the next filter."),
210 .p
.priv_class
= &format_class
,
212 .p
.flags
= AVFILTER_FLAG_METADATA_ONLY
,
217 .priv_size
= sizeof(FormatContext
),
219 FILTER_INPUTS(inputs
),
220 FILTER_OUTPUTS(ff_video_default_filterpad
),
222 FILTER_QUERY_FUNC2(query_formats
),
224 #endif /* CONFIG_NOFORMAT_FILTER */