FFmpeg
scale.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2007 Bobby Bingham
3  *
4  * This file is part of FFmpeg.
5  *
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.
10  *
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.
15  *
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
19  */
20 
21 #include <stdint.h>
22 #include "scale.h"
23 #include "libavutil/eval.h"
24 #include "libavutil/mathematics.h"
25 #include "libavutil/pixdesc.h"
26 
27 static const char *const var_names[] = {
28  "PI",
29  "PHI",
30  "E",
31  "in_w", "iw",
32  "in_h", "ih",
33  "out_w", "ow",
34  "out_h", "oh",
35  "a",
36  "sar",
37  "dar",
38  "hsub",
39  "vsub",
40  "ohsub",
41  "ovsub",
42  NULL
43 };
44 
45 enum var_name {
61 };
62 
63 /**
64  * This must be kept in sync with var_names so that it is always a
65  * complete list of var_names with the scale2ref specific names
66  * appended. scale2ref values must appear in the order they appear
67  * in the var_name_scale2ref enum but also be below all of the
68  * non-scale2ref specific values.
69  */
70 static const char *const var_names_scale2ref[] = {
71  "PI",
72  "PHI",
73  "E",
74  "in_w", "iw",
75  "in_h", "ih",
76  "out_w", "ow",
77  "out_h", "oh",
78  "a",
79  "sar",
80  "dar",
81  "hsub",
82  "vsub",
83  "ohsub",
84  "ovsub",
85  "main_w",
86  "main_h",
87  "main_a",
88  "main_sar",
89  "main_dar", "mdar",
90  "main_hsub",
91  "main_vsub",
92  NULL
93 };
94 
104 };
105 
106 int ff_scale_eval_dimensions(void *log_ctx,
107  const char *w_expr, const char *h_expr,
108  AVFilterLink *inlink, AVFilterLink *outlink,
109  int *ret_w, int *ret_h)
110 {
112  const AVPixFmtDescriptor *out_desc = av_pix_fmt_desc_get(outlink->format);
113  const char *expr;
114  int eval_w, eval_h;
115  int ret;
116  const char scale2ref = outlink->src->nb_inputs == 2 && outlink->src->inputs[1] == inlink;
117  double var_values[VARS_NB + VARS_S2R_NB], res;
118  const AVPixFmtDescriptor *main_desc;
119  const AVFilterLink *main_link;
120  const char *const *names = scale2ref ? var_names_scale2ref : var_names;
121 
122  if (scale2ref) {
123  main_link = outlink->src->inputs[0];
124  main_desc = av_pix_fmt_desc_get(main_link->format);
125  }
126 
127  var_values[VAR_PI] = M_PI;
128  var_values[VAR_PHI] = M_PHI;
129  var_values[VAR_E] = M_E;
130  var_values[VAR_IN_W] = var_values[VAR_IW] = inlink->w;
131  var_values[VAR_IN_H] = var_values[VAR_IH] = inlink->h;
132  var_values[VAR_OUT_W] = var_values[VAR_OW] = NAN;
133  var_values[VAR_OUT_H] = var_values[VAR_OH] = NAN;
134  var_values[VAR_A] = (double) inlink->w / inlink->h;
135  var_values[VAR_SAR] = inlink->sample_aspect_ratio.num ?
136  (double) inlink->sample_aspect_ratio.num / inlink->sample_aspect_ratio.den : 1;
137  var_values[VAR_DAR] = var_values[VAR_A] * var_values[VAR_SAR];
138  var_values[VAR_HSUB] = 1 << desc->log2_chroma_w;
139  var_values[VAR_VSUB] = 1 << desc->log2_chroma_h;
140  var_values[VAR_OHSUB] = 1 << out_desc->log2_chroma_w;
141  var_values[VAR_OVSUB] = 1 << out_desc->log2_chroma_h;
142 
143  if (scale2ref) {
144  var_values[VARS_NB + VAR_S2R_MAIN_W] = main_link->w;
145  var_values[VARS_NB + VAR_S2R_MAIN_H] = main_link->h;
146  var_values[VARS_NB + VAR_S2R_MAIN_A] = (double) main_link->w / main_link->h;
147  var_values[VARS_NB + VAR_S2R_MAIN_SAR] = main_link->sample_aspect_ratio.num ?
148  (double) main_link->sample_aspect_ratio.num / main_link->sample_aspect_ratio.den : 1;
149  var_values[VARS_NB + VAR_S2R_MAIN_DAR] = var_values[VARS_NB + VAR_S2R_MDAR] =
150  var_values[VARS_NB + VAR_S2R_MAIN_A] * var_values[VARS_NB + VAR_S2R_MAIN_SAR];
151  var_values[VARS_NB + VAR_S2R_MAIN_HSUB] = 1 << main_desc->log2_chroma_w;
152  var_values[VARS_NB + VAR_S2R_MAIN_VSUB] = 1 << main_desc->log2_chroma_h;
153  }
154 
155  /* evaluate width and height */
156  av_expr_parse_and_eval(&res, (expr = w_expr),
157  names, var_values,
158  NULL, NULL, NULL, NULL, NULL, 0, log_ctx);
159  eval_w = var_values[VAR_OUT_W] = var_values[VAR_OW] = (int) res == 0 ? inlink->w : (int) res;
160 
161  if ((ret = av_expr_parse_and_eval(&res, (expr = h_expr),
162  names, var_values,
163  NULL, NULL, NULL, NULL, NULL, 0, log_ctx)) < 0)
164  goto fail;
165  eval_h = var_values[VAR_OUT_H] = var_values[VAR_OH] = (int) res == 0 ? inlink->h : (int) res;
166  /* evaluate again the width, as it may depend on the output height */
167  if ((ret = av_expr_parse_and_eval(&res, (expr = w_expr),
168  names, var_values,
169  NULL, NULL, NULL, NULL, NULL, 0, log_ctx)) < 0)
170  goto fail;
171  eval_w = (int) res == 0 ? inlink->w : (int) res;
172 
173  *ret_w = eval_w;
174  *ret_h = eval_h;
175 
176  return 0;
177 
178 fail:
179  av_log(log_ctx, AV_LOG_ERROR,
180  "Error when evaluating the expression '%s'.\n"
181  "Maybe the expression for out_w:'%s' or for out_h:'%s' is self-referencing.\n",
182  expr, w_expr, h_expr);
183  return ret;
184 }
185 
187  int *ret_w, int *ret_h,
188  int force_original_aspect_ratio, int force_divisible_by)
189 {
190  int w, h;
191  int factor_w, factor_h;
192 
193  w = *ret_w;
194  h = *ret_h;
195 
196  /* Check if it is requested that the result has to be divisible by some
197  * factor (w or h = -n with n being the factor). */
198  factor_w = 1;
199  factor_h = 1;
200  if (w < -1) {
201  factor_w = -w;
202  }
203  if (h < -1) {
204  factor_h = -h;
205  }
206 
207  if (w < 0 && h < 0) {
208  w = inlink->w;
209  h = inlink->h;
210  }
211 
212  /* Make sure that the result is divisible by the factor we determined
213  * earlier. If no factor was set, nothing will happen as the default
214  * factor is 1 */
215  if (w < 0)
216  w = av_rescale(h, inlink->w, inlink->h * factor_w) * factor_w;
217  if (h < 0)
218  h = av_rescale(w, inlink->h, inlink->w * factor_h) * factor_h;
219 
220  /* Note that force_original_aspect_ratio may overwrite the previous set
221  * dimensions so that it is not divisible by the set factors anymore
222  * unless force_divisible_by is defined as well */
223  if (force_original_aspect_ratio) {
224  int tmp_w = av_rescale(h, inlink->w, inlink->h);
225  int tmp_h = av_rescale(w, inlink->h, inlink->w);
226 
227  if (force_original_aspect_ratio == 1) {
228  w = FFMIN(tmp_w, w);
229  h = FFMIN(tmp_h, h);
230  if (force_divisible_by > 1) {
231  // round down
232  w = w / force_divisible_by * force_divisible_by;
233  h = h / force_divisible_by * force_divisible_by;
234  }
235  } else {
236  w = FFMAX(tmp_w, w);
237  h = FFMAX(tmp_h, h);
238  if (force_divisible_by > 1) {
239  // round up
240  w = (w + force_divisible_by - 1) / force_divisible_by * force_divisible_by;
241  h = (h + force_divisible_by - 1) / force_divisible_by * force_divisible_by;
242  }
243  }
244  }
245 
246  *ret_w = w;
247  *ret_h = h;
248 
249  return 0;
250 }
Definition: scale.c:50
#define NULL
Definition: coverity.c:32
int ff_scale_adjust_dimensions(AVFilterLink *inlink, int *ret_w, int *ret_h, int force_original_aspect_ratio, int force_divisible_by)
Transform evaluated width and height obtained from ff_scale_eval_dimensions into actual target width ...
Definition: scale.c:186
int ff_scale_eval_dimensions(void *log_ctx, const char *w_expr, const char *h_expr, AVFilterLink *inlink, AVFilterLink *outlink, int *ret_w, int *ret_h)
Parse and evaluate string expressions for width and height.
Definition: scale.c:106
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2522
const char * desc
Definition: nvenc.c:68
int num
Numerator.
Definition: rational.h:59
Definition: scale.c:54
uint8_t log2_chroma_w
Amount to shift the luma width right to find the chroma width.
Definition: pixdesc.h:92
Definition: scale.c:47
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:346
Definition: scale.c:50
#define av_log(a,...)
int av_expr_parse_and_eval(double *d, const char *s, const char *const *const_names, const double *const_values, const char *const *func1_names, double(*const *funcs1)(void *, double), const char *const *func2_names, double(*const *funcs2)(void *, double, double), void *opaque, int log_offset, void *log_ctx)
Parse and evaluate an expression.
Definition: eval.c:764
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
uint8_t log2_chroma_h
Amount to shift the luma height right to find the chroma height.
Definition: pixdesc.h:101
#define M_E
Definition: mathematics.h:37
Definition: scale.c:60
#define FFMAX(a, b)
Definition: common.h:94
#define fail()
Definition: checkasm.h:122
var_name
Definition: aeval.c:46
Definition: scale.c:56
unsigned nb_inputs
number of input pads
Definition: avfilter.h:347
int64_t av_rescale(int64_t a, int64_t b, int64_t c)
Rescale a 64-bit integer with rounding to nearest.
Definition: mathematics.c:129
#define NAN
Definition: mathematics.h:64
#define FFMIN(a, b)
Definition: common.h:96
Definition: scale.c:52
uint8_t w
Definition: llviddspenc.c:38
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:81
#define M_PHI
Definition: mathematics.h:49
The exact code depends on how similar the blocks are and how related they are to the and needs to apply these operations to the correct inlink or outlink if there are several Macros are available to factor that when no extra processing is inlink
static const char *const var_names[]
Definition: scale.c:27
Definition: scale.c:53
int
Definition: scale.c:51
int den
Denominator.
Definition: rational.h:60
Definition: scale.c:46
var_name_scale2ref
Definition: scale.c:95
Definition: scale.c:57
Definition: scale.c:48
static const char *const var_names_scale2ref[]
This must be kept in sync with var_names so that it is always a complete list of var_names with the s...
Definition: scale.c:70
#define M_PI
Definition: mathematics.h:52
Definition: scale.c:55
simple arithmetic expression evaluator
Definition: scale.c:49
Definition: scale.c:49