| @@ -36,12 +36,6 @@ · 35 unmodified lines |
| 36 | 36 | #include "internal.h" |
| 37 | 37 | #include "video.h" |
| 38 | 38 | |
| 39 | | −#define HUE_DEFAULT_VAL 0 |
| 40 | | −#define SAT_DEFAULT_VAL 1 |
| 41 | | − |
| 42 | | −#define HUE_DEFAULT_VAL_STRING AV_STRINGIFY(HUE_DEFAULT_VAL) |
| 43 | | −#define SAT_DEFAULT_VAL_STRING AV_STRINGIFY(SAT_DEFAULT_VAL) |
| 44 | | − |
| 45 | 39 | #define SAT_MIN_VAL -10 |
| 46 | 40 | #define SAT_MAX_VAL 10 |
| 47 | 41 | |
| @@ -78,7 +72,6 @@ typedef struct { · 30 unmodified lines |
| 78 | 72 | int vsub; |
| 79 | 73 | int32_t hue_sin; |
| 80 | 74 | int32_t hue_cos; |
| 81 | | − int flat_syntax; |
| 82 | 75 | double var_values[VAR_NB]; |
| 83 | 76 | } HueContext; |
| 84 | 77 | |
| @@ -87,9 +80,9 @@ typedef struct { · 2 unmodified lines |
| 87 | 80 | static const AVOption hue_options[] = { |
| 88 | 81 | { "h", "set the hue angle degrees expression", OFFSET(hue_deg_expr), AV_OPT_TYPE_STRING, |
| 89 | 82 | { .str = NULL }, .flags = FLAGS }, |
| 90 | | − { "H", "set the hue angle radians expression", OFFSET(hue_expr), AV_OPT_TYPE_STRING, |
| 91 | | − { .str = NULL }, .flags = FLAGS }, |
| 92 | 83 | { "s", "set the saturation expression", OFFSET(saturation_expr), AV_OPT_TYPE_STRING, |
| 84 | + { .str = "1" }, .flags = FLAGS }, |
| 85 | + { "H", "set the hue angle radians expression", OFFSET(hue_expr), AV_OPT_TYPE_STRING, |
| 93 | 86 | { .str = NULL }, .flags = FLAGS }, |
| 94 | 87 | { NULL } |
| 95 | 88 | }; |
| @@ -107,99 +100,62 @@ static inline void compute_sin_and_cos(HueContext *hue) · 11 unmodified lines |
| 107 | 100 | hue->hue_cos = rint(cos(hue->hue) * (1 << 16) * hue->saturation); |
| 108 | 101 | } |
| 109 | 102 | |
| 110 | | −#define SET_EXPRESSION(attr, name) do { \ |
| 111 | | − if (hue->attr##_expr) { \ |
| 112 | | − if ((ret = av_expr_parse(&hue->attr##_pexpr, hue->attr##_expr, var_names, \ |
| 113 | | − NULL, NULL, NULL, NULL, 0, ctx)) < 0) { \ |
| 114 | | − av_log(ctx, AV_LOG_ERROR, \ |
| 115 | | − "Parsing failed for expression " #name "='%s'", \ |
| 116 | | − hue->attr##_expr); \ |
| 117 | | − hue->attr##_expr = old_##attr##_expr; \ |
| 118 | | − hue->attr##_pexpr = old_##attr##_pexpr; \ |
| 119 | | − return AVERROR(EINVAL); \ |
| 120 | | − } else if (old_##attr##_pexpr) { \ |
| 121 | | − av_freep(&old_##attr##_expr); \ |
| 122 | | − av_expr_free(old_##attr##_pexpr); \ |
| 123 | | − old_##attr##_pexpr = NULL; \ |
| 124 | | − } \ |
| 125 | | − } else { \ |
| 126 | | − hue->attr##_expr = old_##attr##_expr; \ |
| 127 | | − } \ |
| 128 | | −} while (0) |
| 129 | | − |
| 130 | | −static inline int set_options(AVFilterContext *ctx, const char *args) |
| 103 | +static int set_expr(AVExpr **pexpr, const char *expr, const char *option, void *log_ctx) |
| 131 | 104 | { |
| 132 | | − HueContext *hue = ctx->priv; |
| 133 | 105 | int ret; |
| 134 | | − char *old_hue_expr, *old_hue_deg_expr, *old_saturation_expr; |
| 135 | | − AVExpr *old_hue_pexpr, *old_hue_deg_pexpr, *old_saturation_pexpr; |
| 136 | | − static const char *shorthand[] = { "h", "s", NULL }; |
| 137 | | − old_hue_expr = hue->hue_expr; |
| 138 | | − old_hue_deg_expr = hue->hue_deg_expr; |
| 139 | | − old_saturation_expr = hue->saturation_expr; |
| 140 | | − |
| 141 | | − old_hue_pexpr = hue->hue_pexpr; |
| 142 | | − old_hue_deg_pexpr = hue->hue_deg_pexpr; |
| 143 | | − old_saturation_pexpr = hue->saturation_pexpr; |
| 144 | | − |
| 145 | | − hue->hue_expr = NULL; |
| 146 | | − hue->hue_deg_expr = NULL; |
| 147 | | − hue->saturation_expr = NULL; |
| 148 | | − |
| 149 | | − if ((ret = av_opt_set_from_string(hue, args, shorthand, "=", ":")) < 0) |
| 106 | + AVExpr *old = NULL; |
| 107 | + |
| 108 | + if (*pexpr) |
| 109 | + old = *pexpr; |
| 110 | + ret = av_expr_parse(pexpr, expr, var_names, |
| 111 | + NULL, NULL, NULL, NULL, 0, log_ctx); |
| 112 | + if (ret < 0) { |
| 113 | + av_log(log_ctx, AV_LOG_ERROR, |
| 114 | + "Error when evaluating the expression '%s' for %s\n", |
| 115 | + expr, option); |
| 116 | + *pexpr = old; |
| 150 | 117 | return ret; |
| 118 | + } |
| 119 | + av_expr_free(old); |
| 120 | + return 0; |
| 121 | +} |
| 122 | + |
| 123 | +static av_cold int init(AVFilterContext *ctx, const char *args) |
| 124 | +{ |
| 125 | + HueContext *hue = ctx->priv; |
| 126 | + int ret; |
| 127 | + |
| 151 | 128 | if (hue->hue_expr && hue->hue_deg_expr) { |
| 152 | 129 | av_log(ctx, AV_LOG_ERROR, |
| 153 | 130 | "H and h options are incompatible and cannot be specified " |
| 154 | 131 | "at the same time\n"); |
| 155 | | − hue->hue_expr = old_hue_expr; |
| 156 | | − hue->hue_deg_expr = old_hue_deg_expr; |
| 157 | | − |
| 158 | 132 | return AVERROR(EINVAL); |
| 159 | 133 | } |
| 160 | 134 | |
| 161 | | − SET_EXPRESSION(hue_deg, h); |
| 162 | | − SET_EXPRESSION(hue, H); |
| 163 | | − SET_EXPRESSION(saturation, s); |
| 164 | | − |
| 165 | | − hue->flat_syntax = 0; |
| 135 | +#define SET_EXPR(expr, option) \ |
| 136 | + if (hue->expr##_expr) do { \ |
| 137 | + ret = set_expr(&hue->expr##_pexpr, hue->expr##_expr, option, ctx); \ |
| 138 | + if (ret < 0) \ |
| 139 | + return ret; \ |
| 140 | + } while (0) |
| 141 | + SET_EXPR(saturation, "s"); |
| 142 | + SET_EXPR(hue_deg, "h"); |
| 143 | + SET_EXPR(hue, "H"); |
| 166 | 144 | |
| 167 | 145 | av_log(ctx, AV_LOG_VERBOSE, |
| 168 | 146 | "H_expr:%s h_deg_expr:%s s_expr:%s\n", |
| 169 | 147 | hue->hue_expr, hue->hue_deg_expr, hue->saturation_expr); |
| 170 | | − |
| 171 | 148 | compute_sin_and_cos(hue); |
| 172 | 149 | |
| 173 | 150 | return 0; |
| 174 | 151 | } |
| 175 | 152 | |
| 176 | | −static av_cold int init(AVFilterContext *ctx, const char *args) |
| 177 | | −{ |
| 178 | | − HueContext *hue = ctx->priv; |
| 179 | | − |
| 180 | | − hue->class = &hue_class; |
| 181 | | − av_opt_set_defaults(hue); |
| 182 | | − |
| 183 | | − hue->saturation = SAT_DEFAULT_VAL; |
| 184 | | − hue->hue = HUE_DEFAULT_VAL; |
| 185 | | − hue->hue_deg_pexpr = NULL; |
| 186 | | − hue->hue_pexpr = NULL; |
| 187 | | − hue->flat_syntax = 1; |
| 188 | | − |
| 189 | | − return set_options(ctx, args); |
| 190 | | −} |
| 191 | | − |
| 192 | 153 | static av_cold void uninit(AVFilterContext *ctx) |
| 193 | 154 | { |
| 194 | 155 | HueContext *hue = ctx->priv; |
| 195 | 156 | |
| 196 | | − av_opt_free(hue); |
| 197 | | − |
| 198 | | − av_free(hue->hue_deg_expr); |
| 199 | 157 | av_expr_free(hue->hue_deg_pexpr); |
| 200 | | − av_free(hue->hue_expr); |
| 201 | 158 | av_expr_free(hue->hue_pexpr); |
| 202 | | − av_free(hue->saturation_expr); |
| 203 | 159 | av_expr_free(hue->saturation_pexpr); |
| 204 | 160 | } |
| 205 | 161 | |
| @@ -295,7 +251,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpic) · 89 unmodified lines |
| 295 | 251 | av_frame_copy_props(outpic, inpic); |
| 296 | 252 | } |
| 297 | 253 | |
| 298 | | − if (!hue->flat_syntax) { |
| 254 | + /* todo: reindent */ |
| 299 | 255 | hue->var_values[VAR_T] = TS2T(inpic->pts, inlink->time_base); |
| 300 | 256 | hue->var_values[VAR_PTS] = TS2D(inpic->pts); |
| 301 | 257 | |
| @@ -323,7 +279,6 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpic) · 21 unmodified lines |
| 323 | 279 | hue->var_values[VAR_T], (int)hue->var_values[VAR_N]); |
| 324 | 280 | |
| 325 | 281 | compute_sin_and_cos(hue); |
| 326 | | − } |
| 327 | 282 | |
| 328 | 283 | hue->var_values[VAR_N] += 1; |
| 329 | 284 | |
| @@ -345,10 +300,17 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpic) · 15 unmodified lines |
| 345 | 300 | static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, |
| 346 | 301 | char *res, int res_len, int flags) |
| 347 | 302 | { |
| 348 | | − if (!strcmp(cmd, "reinit")) |
| 349 | | − return set_options(ctx, args); |
| 350 | | − else |
| 351 | | − return AVERROR(ENOSYS); |
| 303 | + HueContext *hue = ctx->priv; |
| 304 | + |
| 305 | +#define SET_CMD(expr, option) \ |
| 306 | + if (!strcmp(cmd, option)) do { \ |
| 307 | + return set_expr(&hue->expr##_pexpr, args, cmd, ctx); \ |
| 308 | + } while (0) |
| 309 | + SET_CMD(hue_deg, "h"); |
| 310 | + SET_CMD(hue, "H"); |
| 311 | + SET_CMD(saturation, "s"); |
| 312 | + |
| 313 | + return AVERROR(ENOSYS); |
| 352 | 314 | } |
| 353 | 315 | |
| 354 | 316 | static const AVFilterPad hue_inputs[] = { |