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
33 #include "libavutil/avstring.h"
34 #include "libavutil/eval.h"
35 #include "libavutil/internal.h"
36 #include "libavutil/mathematics.h"
37 #include "libavutil/opt.h"
38 #include "libavutil/parseutils.h"
39 #include "libavutil/pixdesc.h"
40 #include "libavutil/imgutils.h"
41 #include "libavutil/avassert.h"
42 #include "libswscale/swscale.h"
44 static const char *const var_names
[] = {
74 typedef struct ScaleContext
{
76 struct SwsContext
*sws
; ///< software scaler context
77 struct SwsContext
*isws
[2]; ///< software scaler context for interlaced material
81 * New dimensions. Special values are:
82 * 0 = original width/height
83 * -1 = keep original aspect
84 * -N = try to keep aspect but make sure it is divisible by N
88 unsigned int flags
; ///sws flags
90 int hsub
, vsub
; ///< chroma subsampling
91 int slice_y
; ///< top of current output slice
92 int input_is_pal
; ///< set to 1 if the input format is paletted
93 int output_is_pal
; ///< set to 1 if the output format is paletted
96 char *w_expr
; ///< width expression string
97 char *h_expr
; ///< height expression string
100 char *in_color_matrix
;
101 char *out_color_matrix
;
111 int force_original_aspect_ratio
;
114 static av_cold
int init_dict(AVFilterContext
*ctx
, AVDictionary
**opts
)
116 ScaleContext
*scale
= ctx
->priv
;
119 if (scale
->size_str
&& (scale
->w_expr
|| scale
->h_expr
)) {
120 av_log(ctx
, AV_LOG_ERROR
,
121 "Size and width/height expressions cannot be set at the same time.\n");
122 return AVERROR(EINVAL
);
125 if (scale
->w_expr
&& !scale
->h_expr
)
126 FFSWAP(char *, scale
->w_expr
, scale
->size_str
);
128 if (scale
->size_str
) {
130 if ((ret
= av_parse_video_size(&scale
->w
, &scale
->h
, scale
->size_str
)) < 0) {
131 av_log(ctx
, AV_LOG_ERROR
,
132 "Invalid size '%s'\n", scale
->size_str
);
135 snprintf(buf
, sizeof(buf
)-1, "%d", scale
->w
);
136 av_opt_set(scale
, "w", buf
, 0);
137 snprintf(buf
, sizeof(buf
)-1, "%d", scale
->h
);
138 av_opt_set(scale
, "h", buf
, 0);
141 av_opt_set(scale
, "w", "iw", 0);
143 av_opt_set(scale
, "h", "ih", 0);
145 av_log(ctx
, AV_LOG_VERBOSE
, "w:%s h:%s flags:'%s' interl:%d\n",
146 scale
->w_expr
, scale
->h_expr
, (char *)av_x_if_null(scale
->flags_str
, ""), scale
->interlaced
);
150 if (scale
->flags_str
) {
151 const AVClass
*class = sws_get_class();
152 const AVOption
*o
= av_opt_find(&class, "sws_flags", NULL
, 0,
153 AV_OPT_SEARCH_FAKE_OBJ
);
154 int ret
= av_opt_eval_flags(&class, o
, scale
->flags_str
, &scale
->flags
);
164 static av_cold
void uninit(AVFilterContext
*ctx
)
166 ScaleContext
*scale
= ctx
->priv
;
167 sws_freeContext(scale
->sws
);
168 sws_freeContext(scale
->isws
[0]);
169 sws_freeContext(scale
->isws
[1]);
171 av_dict_free(&scale
->opts
);
174 static int query_formats(AVFilterContext
*ctx
)
176 AVFilterFormats
*formats
;
177 enum AVPixelFormat pix_fmt
;
180 if (ctx
->inputs
[0]) {
181 const AVPixFmtDescriptor
*desc
= NULL
;
183 while ((desc
= av_pix_fmt_desc_next(desc
))) {
184 pix_fmt
= av_pix_fmt_desc_get_id(desc
);
185 if ((sws_isSupportedInput(pix_fmt
) ||
186 sws_isSupportedEndiannessConversion(pix_fmt
))
187 && (ret
= ff_add_format(&formats
, pix_fmt
)) < 0) {
188 ff_formats_unref(&formats
);
192 ff_formats_ref(formats
, &ctx
->inputs
[0]->out_formats
);
194 if (ctx
->outputs
[0]) {
195 const AVPixFmtDescriptor
*desc
= NULL
;
197 while ((desc
= av_pix_fmt_desc_next(desc
))) {
198 pix_fmt
= av_pix_fmt_desc_get_id(desc
);
199 if ((sws_isSupportedOutput(pix_fmt
) || pix_fmt
== AV_PIX_FMT_PAL8
||
200 sws_isSupportedEndiannessConversion(pix_fmt
))
201 && (ret
= ff_add_format(&formats
, pix_fmt
)) < 0) {
202 ff_formats_unref(&formats
);
206 ff_formats_ref(formats
, &ctx
->outputs
[0]->in_formats
);
212 static const int *parse_yuv_type(const char *s
, enum AVColorSpace colorspace
)
217 if (s
&& strstr(s
, "bt709")) {
218 colorspace
= AVCOL_SPC_BT709
;
219 } else if (s
&& strstr(s
, "fcc")) {
220 colorspace
= AVCOL_SPC_FCC
;
221 } else if (s
&& strstr(s
, "smpte240m")) {
222 colorspace
= AVCOL_SPC_SMPTE240M
;
223 } else if (s
&& (strstr(s
, "bt601") || strstr(s
, "bt470") || strstr(s
, "smpte170m"))) {
224 colorspace
= AVCOL_SPC_BT470BG
;
227 if (colorspace
< 1 || colorspace
> 7) {
228 colorspace
= AVCOL_SPC_BT470BG
;
231 return sws_getCoefficients(colorspace
);
234 static int config_props(AVFilterLink
*outlink
)
236 AVFilterContext
*ctx
= outlink
->src
;
237 AVFilterLink
*inlink
= outlink
->src
->inputs
[0];
238 enum AVPixelFormat outfmt
= outlink
->format
;
239 ScaleContext
*scale
= ctx
->priv
;
240 const AVPixFmtDescriptor
*desc
= av_pix_fmt_desc_get(inlink
->format
);
241 const AVPixFmtDescriptor
*out_desc
= av_pix_fmt_desc_get(outlink
->format
);
243 double var_values
[VARS_NB
], res
;
246 int factor_w
, factor_h
;
248 var_values
[VAR_IN_W
] = var_values
[VAR_IW
] = inlink
->w
;
249 var_values
[VAR_IN_H
] = var_values
[VAR_IH
] = inlink
->h
;
250 var_values
[VAR_OUT_W
] = var_values
[VAR_OW
] = NAN
;
251 var_values
[VAR_OUT_H
] = var_values
[VAR_OH
] = NAN
;
252 var_values
[VAR_A
] = (double) inlink
->w
/ inlink
->h
;
253 var_values
[VAR_SAR
] = inlink
->sample_aspect_ratio
.num
?
254 (double) inlink
->sample_aspect_ratio
.num
/ inlink
->sample_aspect_ratio
.den
: 1;
255 var_values
[VAR_DAR
] = var_values
[VAR_A
] * var_values
[VAR_SAR
];
256 var_values
[VAR_HSUB
] = 1 << desc
->log2_chroma_w
;
257 var_values
[VAR_VSUB
] = 1 << desc
->log2_chroma_h
;
258 var_values
[VAR_OHSUB
] = 1 << out_desc
->log2_chroma_w
;
259 var_values
[VAR_OVSUB
] = 1 << out_desc
->log2_chroma_h
;
261 /* evaluate width and height */
262 av_expr_parse_and_eval(&res
, (expr
= scale
->w_expr
),
263 var_names
, var_values
,
264 NULL
, NULL
, NULL
, NULL
, NULL
, 0, ctx
);
265 scale
->w
= var_values
[VAR_OUT_W
] = var_values
[VAR_OW
] = res
;
266 if ((ret
= av_expr_parse_and_eval(&res
, (expr
= scale
->h_expr
),
267 var_names
, var_values
,
268 NULL
, NULL
, NULL
, NULL
, NULL
, 0, ctx
)) < 0)
270 scale
->h
= var_values
[VAR_OUT_H
] = var_values
[VAR_OH
] = res
;
271 /* evaluate again the width, as it may depend on the output height */
272 if ((ret
= av_expr_parse_and_eval(&res
, (expr
= scale
->w_expr
),
273 var_names
, var_values
,
274 NULL
, NULL
, NULL
, NULL
, NULL
, 0, ctx
)) < 0)
281 /* Check if it is requested that the result has to be divisible by a some
282 * factor (w or h = -n with n being the factor). */
293 scale
->w
= scale
->h
= 0;
300 /* Make sure that the result is divisible by the factor we determined
301 * earlier. If no factor was set, it is nothing will happen as the default
304 w
= av_rescale(h
, inlink
->w
, inlink
->h
* factor_w
) * factor_w
;
306 h
= av_rescale(w
, inlink
->h
, inlink
->w
* factor_h
) * factor_h
;
308 /* Note that force_original_aspect_ratio may overwrite the previous set
309 * dimensions so that it is not divisible by the set factors anymore. */
310 if (scale
->force_original_aspect_ratio
) {
311 int tmp_w
= av_rescale(h
, inlink
->w
, inlink
->h
);
312 int tmp_h
= av_rescale(w
, inlink
->h
, inlink
->w
);
314 if (scale
->force_original_aspect_ratio
== 1) {
323 if (w
> INT_MAX
|| h
> INT_MAX
||
324 (h
* inlink
->w
) > INT_MAX
||
325 (w
* inlink
->h
) > INT_MAX
)
326 av_log(ctx
, AV_LOG_ERROR
, "Rescaled value for width or height is too big.\n");
331 /* TODO: make algorithm configurable */
333 scale
->input_is_pal
= desc
->flags
& AV_PIX_FMT_FLAG_PAL
||
334 desc
->flags
& AV_PIX_FMT_FLAG_PSEUDOPAL
;
335 if (outfmt
== AV_PIX_FMT_PAL8
) outfmt
= AV_PIX_FMT_BGR8
;
336 scale
->output_is_pal
= av_pix_fmt_desc_get(outfmt
)->flags
& AV_PIX_FMT_FLAG_PAL
||
337 av_pix_fmt_desc_get(outfmt
)->flags
& AV_PIX_FMT_FLAG_PSEUDOPAL
;
340 sws_freeContext(scale
->sws
);
342 sws_freeContext(scale
->isws
[0]);
344 sws_freeContext(scale
->isws
[1]);
345 scale
->isws
[0] = scale
->isws
[1] = scale
->sws
= NULL
;
346 if (inlink
->w
== outlink
->w
&& inlink
->h
== outlink
->h
&&
347 inlink
->format
== outlink
->format
)
350 struct SwsContext
**swscs
[3] = {&scale
->sws
, &scale
->isws
[0], &scale
->isws
[1]};
353 for (i
= 0; i
< 3; i
++) {
354 struct SwsContext
**s
= swscs
[i
];
355 *s
= sws_alloc_context();
357 return AVERROR(ENOMEM
);
360 AVDictionaryEntry
*e
= NULL
;
362 while ((e
= av_dict_get(scale
->opts
, "", e
, AV_DICT_IGNORE_SUFFIX
))) {
363 if ((ret
= av_opt_set(*s
, e
->key
, e
->value
, 0)) < 0)
368 av_opt_set_int(*s
, "srcw", inlink
->w
, 0);
369 av_opt_set_int(*s
, "srch", inlink
->h
>> !!i
, 0);
370 av_opt_set_int(*s
, "src_format", inlink
->format
, 0);
371 av_opt_set_int(*s
, "dstw", outlink
->w
, 0);
372 av_opt_set_int(*s
, "dsth", outlink
->h
>> !!i
, 0);
373 av_opt_set_int(*s
, "dst_format", outfmt
, 0);
374 av_opt_set_int(*s
, "sws_flags", scale
->flags
, 0);
376 av_opt_set_int(*s
, "src_h_chr_pos", scale
->in_h_chr_pos
, 0);
377 av_opt_set_int(*s
, "src_v_chr_pos", scale
->in_v_chr_pos
, 0);
378 av_opt_set_int(*s
, "dst_h_chr_pos", scale
->out_h_chr_pos
, 0);
379 av_opt_set_int(*s
, "dst_v_chr_pos", scale
->out_v_chr_pos
, 0);
381 if ((ret
= sws_init_context(*s
, NULL
, NULL
)) < 0)
383 if (!scale
->interlaced
)
388 if (inlink
->sample_aspect_ratio
.num
){
389 outlink
->sample_aspect_ratio
= av_mul_q((AVRational
){outlink
->h
* inlink
->w
, outlink
->w
* inlink
->h
}, inlink
->sample_aspect_ratio
);
391 outlink
->sample_aspect_ratio
= inlink
->sample_aspect_ratio
;
393 av_log(ctx
, AV_LOG_VERBOSE
, "w:%d h:%d fmt:%s sar:%d/%d -> w:%d h:%d fmt:%s sar:%d/%d flags:0x%0x\n",
394 inlink
->w
, inlink
->h
, av_get_pix_fmt_name( inlink
->format
),
395 inlink
->sample_aspect_ratio
.num
, inlink
->sample_aspect_ratio
.den
,
396 outlink
->w
, outlink
->h
, av_get_pix_fmt_name(outlink
->format
),
397 outlink
->sample_aspect_ratio
.num
, outlink
->sample_aspect_ratio
.den
,
402 av_log(NULL
, AV_LOG_ERROR
,
403 "Error when evaluating the expression '%s'.\n"
404 "Maybe the expression for out_w:'%s' or for out_h:'%s' is self-referencing.\n",
405 expr
, scale
->w_expr
, scale
->h_expr
);
409 static int scale_slice(AVFilterLink
*link
, AVFrame
*out_buf
, AVFrame
*cur_pic
, struct SwsContext
*sws
, int y
, int h
, int mul
, int field
)
411 ScaleContext
*scale
= link
->dst
->priv
;
412 const uint8_t *in
[4];
414 int in_stride
[4],out_stride
[4];
418 int vsub
= ((i
+1)&2) ? scale
->vsub
: 0;
419 in_stride
[i
] = cur_pic
->linesize
[i
] * mul
;
420 out_stride
[i
] = out_buf
->linesize
[i
] * mul
;
421 in
[i
] = cur_pic
->data
[i
] + ((y
>>vsub
)+field
) * cur_pic
->linesize
[i
];
422 out
[i
] = out_buf
->data
[i
] + field
* out_buf
->linesize
[i
];
424 if(scale
->input_is_pal
)
425 in
[1] = cur_pic
->data
[1];
426 if(scale
->output_is_pal
)
427 out
[1] = out_buf
->data
[1];
429 return sws_scale(sws
, in
, in_stride
, y
/mul
, h
,
433 static int filter_frame(AVFilterLink
*link
, AVFrame
*in
)
435 ScaleContext
*scale
= link
->dst
->priv
;
436 AVFilterLink
*outlink
= link
->dst
->outputs
[0];
438 const AVPixFmtDescriptor
*desc
= av_pix_fmt_desc_get(link
->format
);
442 if( in
->width
!= link
->w
443 || in
->height
!= link
->h
444 || in
->format
!= link
->format
) {
446 snprintf(buf
, sizeof(buf
)-1, "%d", outlink
->w
);
447 av_opt_set(scale
, "w", buf
, 0);
448 snprintf(buf
, sizeof(buf
)-1, "%d", outlink
->h
);
449 av_opt_set(scale
, "h", buf
, 0);
451 link
->dst
->inputs
[0]->format
= in
->format
;
452 link
->dst
->inputs
[0]->w
= in
->width
;
453 link
->dst
->inputs
[0]->h
= in
->height
;
455 if ((ret
= config_props(outlink
)) < 0)
460 return ff_filter_frame(outlink
, in
);
462 scale
->hsub
= desc
->log2_chroma_w
;
463 scale
->vsub
= desc
->log2_chroma_h
;
465 out
= ff_get_video_buffer(outlink
, outlink
->w
, outlink
->h
);
468 return AVERROR(ENOMEM
);
471 av_frame_copy_props(out
, in
);
472 out
->width
= outlink
->w
;
473 out
->height
= outlink
->h
;
475 if(scale
->output_is_pal
)
476 avpriv_set_systematic_pal2((uint32_t*)out
->data
[1], outlink
->format
== AV_PIX_FMT_PAL8
? AV_PIX_FMT_BGR8
: outlink
->format
);
478 in_range
= av_frame_get_color_range(in
);
480 if ( scale
->in_color_matrix
481 || scale
->out_color_matrix
482 || scale
-> in_range
!= AVCOL_RANGE_UNSPECIFIED
483 || in_range
!= AVCOL_RANGE_UNSPECIFIED
484 || scale
->out_range
!= AVCOL_RANGE_UNSPECIFIED
) {
485 int in_full
, out_full
, brightness
, contrast
, saturation
;
486 const int *inv_table
, *table
;
488 sws_getColorspaceDetails(scale
->sws
, (int **)&inv_table
, &in_full
,
489 (int **)&table
, &out_full
,
490 &brightness
, &contrast
, &saturation
);
492 if (scale
->in_color_matrix
)
493 inv_table
= parse_yuv_type(scale
->in_color_matrix
, av_frame_get_colorspace(in
));
494 if (scale
->out_color_matrix
)
495 table
= parse_yuv_type(scale
->out_color_matrix
, AVCOL_SPC_UNSPECIFIED
);
497 if (scale
-> in_range
!= AVCOL_RANGE_UNSPECIFIED
)
498 in_full
= (scale
-> in_range
== AVCOL_RANGE_JPEG
);
499 else if (in_range
!= AVCOL_RANGE_UNSPECIFIED
)
500 in_full
= (in_range
== AVCOL_RANGE_JPEG
);
501 if (scale
->out_range
!= AVCOL_RANGE_UNSPECIFIED
)
502 out_full
= (scale
->out_range
== AVCOL_RANGE_JPEG
);
504 sws_setColorspaceDetails(scale
->sws
, inv_table
, in_full
,
506 brightness
, contrast
, saturation
);
508 sws_setColorspaceDetails(scale
->isws
[0], inv_table
, in_full
,
510 brightness
, contrast
, saturation
);
512 sws_setColorspaceDetails(scale
->isws
[1], inv_table
, in_full
,
514 brightness
, contrast
, saturation
);
517 av_reduce(&out
->sample_aspect_ratio
.num
, &out
->sample_aspect_ratio
.den
,
518 (int64_t)in
->sample_aspect_ratio
.num
* outlink
->h
* link
->w
,
519 (int64_t)in
->sample_aspect_ratio
.den
* outlink
->w
* link
->h
,
522 if(scale
->interlaced
>0 || (scale
->interlaced
<0 && in
->interlaced_frame
)){
523 scale_slice(link
, out
, in
, scale
->isws
[0], 0, (link
->h
+1)/2, 2, 0);
524 scale_slice(link
, out
, in
, scale
->isws
[1], 0, link
->h
/2, 2, 1);
526 scale_slice(link
, out
, in
, scale
->sws
, 0, link
->h
, 1, 0);
530 return ff_filter_frame(outlink
, out
);
533 static const AVClass
*child_class_next(const AVClass
*prev
)
535 return prev
? NULL
: sws_get_class();
538 #define OFFSET(x) offsetof(ScaleContext, x)
539 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
541 static const AVOption scale_options
[] = {
542 { "w", "Output video width", OFFSET(w_expr
), AV_OPT_TYPE_STRING
, .flags
= FLAGS
},
543 { "width", "Output video width", OFFSET(w_expr
), AV_OPT_TYPE_STRING
, .flags
= FLAGS
},
544 { "h", "Output video height", OFFSET(h_expr
), AV_OPT_TYPE_STRING
, .flags
= FLAGS
},
545 { "height","Output video height", OFFSET(h_expr
), AV_OPT_TYPE_STRING
, .flags
= FLAGS
},
546 { "flags", "Flags to pass to libswscale", OFFSET(flags_str
), AV_OPT_TYPE_STRING
, { .str
= "bilinear" }, .flags
= FLAGS
},
547 { "interl", "set interlacing", OFFSET(interlaced
), AV_OPT_TYPE_INT
, {.i64
= 0 }, -1, 1, FLAGS
},
548 { "size", "set video size", OFFSET(size_str
), AV_OPT_TYPE_STRING
, {.str
= NULL
}, 0, FLAGS
},
549 { "s", "set video size", OFFSET(size_str
), AV_OPT_TYPE_STRING
, {.str
= NULL
}, 0, FLAGS
},
550 { "in_color_matrix", "set input YCbCr type", OFFSET(in_color_matrix
), AV_OPT_TYPE_STRING
, { .str
= "auto" }, .flags
= FLAGS
},
551 { "out_color_matrix", "set output YCbCr type", OFFSET(out_color_matrix
), AV_OPT_TYPE_STRING
, { .str
= NULL
}, .flags
= FLAGS
},
552 { "in_range", "set input color range", OFFSET( in_range
), AV_OPT_TYPE_INT
, {.i64
= AVCOL_RANGE_UNSPECIFIED
}, 0, 2, FLAGS
, "range" },
553 { "out_range", "set output color range", OFFSET(out_range
), AV_OPT_TYPE_INT
, {.i64
= AVCOL_RANGE_UNSPECIFIED
}, 0, 2, FLAGS
, "range" },
554 { "auto", NULL
, 0, AV_OPT_TYPE_CONST
, {.i64
= AVCOL_RANGE_UNSPECIFIED
}, 0, 0, FLAGS
, "range" },
555 { "full", NULL
, 0, AV_OPT_TYPE_CONST
, {.i64
= AVCOL_RANGE_JPEG
}, 0, 0, FLAGS
, "range" },
556 { "jpeg", NULL
, 0, AV_OPT_TYPE_CONST
, {.i64
= AVCOL_RANGE_JPEG
}, 0, 0, FLAGS
, "range" },
557 { "mpeg", NULL
, 0, AV_OPT_TYPE_CONST
, {.i64
= AVCOL_RANGE_MPEG
}, 0, 0, FLAGS
, "range" },
558 { "tv", NULL
, 0, AV_OPT_TYPE_CONST
, {.i64
= AVCOL_RANGE_MPEG
}, 0, 0, FLAGS
, "range" },
559 { "pc", NULL
, 0, AV_OPT_TYPE_CONST
, {.i64
= AVCOL_RANGE_JPEG
}, 0, 0, FLAGS
, "range" },
560 { "in_v_chr_pos", "input vertical chroma position in luma grid/256" , OFFSET(in_v_chr_pos
), AV_OPT_TYPE_INT
, { .i64
= -513}, -513, 512, FLAGS
},
561 { "in_h_chr_pos", "input horizontal chroma position in luma grid/256", OFFSET(in_h_chr_pos
), AV_OPT_TYPE_INT
, { .i64
= -513}, -513, 512, FLAGS
},
562 { "out_v_chr_pos", "output vertical chroma position in luma grid/256" , OFFSET(out_v_chr_pos
), AV_OPT_TYPE_INT
, { .i64
= -513}, -513, 512, FLAGS
},
563 { "out_h_chr_pos", "output horizontal chroma position in luma grid/256", OFFSET(out_h_chr_pos
), AV_OPT_TYPE_INT
, { .i64
= -513}, -513, 512, FLAGS
},
564 { "force_original_aspect_ratio", "decrease or increase w/h if necessary to keep the original AR", OFFSET(force_original_aspect_ratio
), AV_OPT_TYPE_INT
, { .i64
= 0}, 0, 2, FLAGS
, "force_oar" },
565 { "disable", NULL
, 0, AV_OPT_TYPE_CONST
, {.i64
= 0 }, 0, 0, FLAGS
, "force_oar" },
566 { "decrease", NULL
, 0, AV_OPT_TYPE_CONST
, {.i64
= 1 }, 0, 0, FLAGS
, "force_oar" },
567 { "increase", NULL
, 0, AV_OPT_TYPE_CONST
, {.i64
= 2 }, 0, 0, FLAGS
, "force_oar" },
571 static const AVClass scale_class
= {
572 .class_name
= "scale",
573 .item_name
= av_default_item_name
,
574 .option
= scale_options
,
575 .version
= LIBAVUTIL_VERSION_INT
,
576 .category
= AV_CLASS_CATEGORY_FILTER
,
577 .child_class_next
= child_class_next
,
580 static const AVFilterPad avfilter_vf_scale_inputs
[] = {
583 .type
= AVMEDIA_TYPE_VIDEO
,
584 .filter_frame
= filter_frame
,
589 static const AVFilterPad avfilter_vf_scale_outputs
[] = {
592 .type
= AVMEDIA_TYPE_VIDEO
,
593 .config_props
= config_props
,
598 AVFilter ff_vf_scale
= {
600 .description
= NULL_IF_CONFIG_SMALL("Scale the input video size and/or convert the image format."),
601 .init_dict
= init_dict
,
603 .query_formats
= query_formats
,
604 .priv_size
= sizeof(ScaleContext
),
605 .priv_class
= &scale_class
,
606 .inputs
= avfilter_vf_scale_inputs
,
607 .outputs
= avfilter_vf_scale_outputs
,