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 w, h;
115  int factor_w, factor_h;
116  int eval_w, eval_h;
117  int ret;
118  const char scale2ref = outlink->src->nb_inputs == 2 && outlink->src->inputs[1] == inlink;
119  double var_values[VARS_NB + VARS_S2R_NB], res;
120  const AVPixFmtDescriptor *main_desc;
121  const AVFilterLink *main_link;
122  const char *const *names = scale2ref ? var_names_scale2ref : var_names;
123 
124  if (scale2ref) {
125  main_link = outlink->src->inputs[0];
126  main_desc = av_pix_fmt_desc_get(main_link->format);
127  }
128 
129  var_values[VAR_PI] = M_PI;
130  var_values[VAR_PHI] = M_PHI;
131  var_values[VAR_E] = M_E;
132  var_values[VAR_IN_W] = var_values[VAR_IW] = inlink->w;
133  var_values[VAR_IN_H] = var_values[VAR_IH] = inlink->h;
134  var_values[VAR_OUT_W] = var_values[VAR_OW] = NAN;
135  var_values[VAR_OUT_H] = var_values[VAR_OH] = NAN;
136  var_values[VAR_A] = (double) inlink->w / inlink->h;
137  var_values[VAR_SAR] = inlink->sample_aspect_ratio.num ?
138  (double) inlink->sample_aspect_ratio.num / inlink->sample_aspect_ratio.den : 1;
139  var_values[VAR_DAR] = var_values[VAR_A] * var_values[VAR_SAR];
140  var_values[VAR_HSUB] = 1 << desc->log2_chroma_w;
141  var_values[VAR_VSUB] = 1 << desc->log2_chroma_h;
142  var_values[VAR_OHSUB] = 1 << out_desc->log2_chroma_w;
143  var_values[VAR_OVSUB] = 1 << out_desc->log2_chroma_h;
144 
145  if (scale2ref) {
146  var_values[VARS_NB + VAR_S2R_MAIN_W] = main_link->w;
147  var_values[VARS_NB + VAR_S2R_MAIN_H] = main_link->h;
148  var_values[VARS_NB + VAR_S2R_MAIN_A] = (double) main_link->w / main_link->h;
149  var_values[VARS_NB + VAR_S2R_MAIN_SAR] = main_link->sample_aspect_ratio.num ?
150  (double) main_link->sample_aspect_ratio.num / main_link->sample_aspect_ratio.den : 1;
151  var_values[VARS_NB + VAR_S2R_MAIN_DAR] = var_values[VARS_NB + VAR_S2R_MDAR] =
152  var_values[VARS_NB + VAR_S2R_MAIN_A] * var_values[VARS_NB + VAR_S2R_MAIN_SAR];
153  var_values[VARS_NB + VAR_S2R_MAIN_HSUB] = 1 << main_desc->log2_chroma_w;
154  var_values[VARS_NB + VAR_S2R_MAIN_VSUB] = 1 << main_desc->log2_chroma_h;
155  }
156 
157  /* evaluate width and height */
158  av_expr_parse_and_eval(&res, (expr = w_expr),
159  names, var_values,
160  NULL, NULL, NULL, NULL, NULL, 0, log_ctx);
161  eval_w = var_values[VAR_OUT_W] = var_values[VAR_OW] = (int) res == 0 ? inlink->w : (int) res;
162 
163  if ((ret = av_expr_parse_and_eval(&res, (expr = h_expr),
164  names, var_values,
165  NULL, NULL, NULL, NULL, NULL, 0, log_ctx)) < 0)
166  goto fail;
167  eval_h = var_values[VAR_OUT_H] = var_values[VAR_OH] = (int) res == 0 ? inlink->h : (int) res;
168  /* evaluate again the width, as it may depend on the output height */
169  if ((ret = av_expr_parse_and_eval(&res, (expr = w_expr),
170  names, var_values,
171  NULL, NULL, NULL, NULL, NULL, 0, log_ctx)) < 0)
172  goto fail;
173  eval_w = (int) res == 0 ? inlink->w : (int) res;
174 
175  w = eval_w;
176  h = eval_h;
177 
178  /* Check if it is requested that the result has to be divisible by a some
179  * factor (w or h = -n with n being the factor). */
180  factor_w = 1;
181  factor_h = 1;
182  if (w < -1) {
183  factor_w = -w;
184  }
185  if (h < -1) {
186  factor_h = -h;
187  }
188 
189  if (w < 0 && h < 0) {
190  w = inlink->w;
191  h = inlink->h;
192  }
193 
194  /* Make sure that the result is divisible by the factor we determined
195  * earlier. If no factor was set, it is nothing will happen as the default
196  * factor is 1 */
197  if (w < 0)
198  w = av_rescale(h, inlink->w, inlink->h * factor_w) * factor_w;
199  if (h < 0)
200  h = av_rescale(w, inlink->h, inlink->w * factor_h) * factor_h;
201 
202  *ret_w = w;
203  *ret_h = h;
204 
205  return 0;
206 
207 fail:
208  av_log(log_ctx, AV_LOG_ERROR,
209  "Error when evaluating the expression '%s'.\n"
210  "Maybe the expression for out_w:'%s' or for out_h:'%s' is self-referencing.\n",
211  expr, w_expr, h_expr);
212  return ret;
213 }
Definition: scale.c:50
#define NULL
Definition: coverity.c:32
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)
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:744
#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 fail()
Definition: checkasm.h:120
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
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