| @@ -36,12 +36,6 @@ · 35 unmodified lines |
| 36 | #include "internal.h" | 36 | #include "internal.h" |
| 37 | #include "video.h" | 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 | #define SAT_MIN_VAL -10 | 39 | #define SAT_MIN_VAL -10 |
| 46 | #define SAT_MAX_VAL 10 | 40 | #define SAT_MAX_VAL 10 |
| 47 | | 41 | |
| @@ -78,7 +72,6 @@ typedef struct { · 30 unmodified lines |
| 78 | int vsub; | 72 | int vsub; |
| 79 | int32_t hue_sin; | 73 | int32_t hue_sin; |
| 80 | int32_t hue_cos; | 74 | int32_t hue_cos; |
| 81 | int flat_syntax; | | |
| 82 | double var_values[VAR_NB]; | 75 | double var_values[VAR_NB]; |
| 83 | } HueContext; | 76 | } HueContext; |
| 84 | | 77 | |
| @@ -87,9 +80,9 @@ typedef struct { · 2 unmodified lines |
| 87 | static const AVOption hue_options[] = { | 80 | static const AVOption hue_options[] = { |
| 88 | { "h", "set the hue angle degrees expression", OFFSET(hue_deg_expr), AV_OPT_TYPE_STRING, | 81 | { "h", "set the hue angle degrees expression", OFFSET(hue_deg_expr), AV_OPT_TYPE_STRING, |
| 89 | { .str = NULL }, .flags = FLAGS }, | 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 | { "s", "set the saturation expression", OFFSET(saturation_expr), AV_OPT_TYPE_STRING, | 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 | { .str = NULL }, .flags = FLAGS }, | 86 | { .str = NULL }, .flags = FLAGS }, |
| 94 | { NULL } | 87 | { NULL } |
| 95 | }; | 88 | }; |
| @@ -107,99 +100,62 @@ static inline void compute_sin_and_cos(HueContext *hue) · 11 unmodified lines |
| 107 | hue->hue_cos = rint(cos(hue->hue) * (1 << 16) * hue->saturation); | 100 | hue->hue_cos = rint(cos(hue->hue) * (1 << 16) * hue->saturation); |
| 108 | } | 101 | } |
| 109 | | 102 | |
| 110 | #define SET_EXPRESSION(attr, name) do { \ | 103 | static int set_expr(AVExpr **pexpr, const char *expr, const char *option, void *log_ctx) |
| 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) | | |
| 131 | { | 104 | { |
| 132 | HueContext *hue = ctx->priv; | | |
| 133 | int ret; | 105 | int ret; |
| 134 | char *old_hue_expr, *old_hue_deg_expr, *old_saturation_expr; | 106 | AVExpr *old = NULL; |
| 135 | AVExpr *old_hue_pexpr, *old_hue_deg_pexpr, *old_saturation_pexpr; | 107 | |
| 136 | static const char *shorthand[] = { "h", "s", NULL }; | 108 | if (*pexpr) |
| 137 | old_hue_expr = hue->hue_expr; | 109 | old = *pexpr; |
| 138 | old_hue_deg_expr = hue->hue_deg_expr; | 110 | ret = av_expr_parse(pexpr, expr, var_names, |
| 139 | old_saturation_expr = hue->saturation_expr; | 111 | NULL, NULL, NULL, NULL, 0, log_ctx); |
| 140 | | 112 | if (ret < 0) { |
| 141 | old_hue_pexpr = hue->hue_pexpr; | 113 | av_log(log_ctx, AV_LOG_ERROR, |
| 142 | old_hue_deg_pexpr = hue->hue_deg_pexpr; | 114 | "Error when evaluating the expression '%s' for %s\n", |
| 143 | old_saturation_pexpr = hue->saturation_pexpr; | 115 | expr, option); |
| 144 | | 116 | *pexpr = old; |
| 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) | | |
| 150 | return ret; | 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 | if (hue->hue_expr && hue->hue_deg_expr) { | 128 | if (hue->hue_expr && hue->hue_deg_expr) { |
| 152 | av_log(ctx, AV_LOG_ERROR, | 129 | av_log(ctx, AV_LOG_ERROR, |
| 153 | "H and h options are incompatible and cannot be specified " | 130 | "H and h options are incompatible and cannot be specified " |
| 154 | "at the same time\n"); | 131 | "at the same time\n"); |
| 155 | hue->hue_expr = old_hue_expr; | | |
| 156 | hue->hue_deg_expr = old_hue_deg_expr; | | |
| 157 | | | |
| 158 | return AVERROR(EINVAL); | 132 | return AVERROR(EINVAL); |
| 159 | } | 133 | } |
| 160 | | 134 | |
| 161 | SET_EXPRESSION(hue_deg, h); | 135 | #define SET_EXPR(expr, option) \ |
| 162 | SET_EXPRESSION(hue, H); | 136 | if (hue->expr##_expr) do { \ |
| 163 | SET_EXPRESSION(saturation, s); | 137 | ret = set_expr(&hue->expr##_pexpr, hue->expr##_expr, option, ctx); \ |
| 164 | | 138 | if (ret < 0) \ |
| 165 | hue->flat_syntax = 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 | av_log(ctx, AV_LOG_VERBOSE, | 145 | av_log(ctx, AV_LOG_VERBOSE, |
| 168 | "H_expr:%s h_deg_expr:%s s_expr:%s\n", | 146 | "H_expr:%s h_deg_expr:%s s_expr:%s\n", |
| 169 | hue->hue_expr, hue->hue_deg_expr, hue->saturation_expr); | 147 | hue->hue_expr, hue->hue_deg_expr, hue->saturation_expr); |
| 170 | | | |
| 171 | compute_sin_and_cos(hue); | 148 | compute_sin_and_cos(hue); |
| 172 | | 149 | |
| 173 | return 0; | 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 | static av_cold void uninit(AVFilterContext *ctx) | 153 | static av_cold void uninit(AVFilterContext *ctx) |
| 193 | { | 154 | { |
| 194 | HueContext *hue = ctx->priv; | 155 | HueContext *hue = ctx->priv; |
| 195 | | 156 | |
| 196 | av_opt_free(hue); | | |
| 197 | | | |
| 198 | av_free(hue->hue_deg_expr); | | |
| 199 | av_expr_free(hue->hue_deg_pexpr); | 157 | av_expr_free(hue->hue_deg_pexpr); |
| 200 | av_free(hue->hue_expr); | | |
| 201 | av_expr_free(hue->hue_pexpr); | 158 | av_expr_free(hue->hue_pexpr); |
| 202 | av_free(hue->saturation_expr); | | |
| 203 | av_expr_free(hue->saturation_pexpr); | 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 | av_frame_copy_props(outpic, inpic); | 251 | av_frame_copy_props(outpic, inpic); |
| 296 | } | 252 | } |
| 297 | | 253 | |
| 298 | if (!hue->flat_syntax) { | 254 | /* todo: reindent */ |
| 299 | hue->var_values[VAR_T] = TS2T(inpic->pts, inlink->time_base); | 255 | hue->var_values[VAR_T] = TS2T(inpic->pts, inlink->time_base); |
| 300 | hue->var_values[VAR_PTS] = TS2D(inpic->pts); | 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 | hue->var_values[VAR_T], (int)hue->var_values[VAR_N]); | 279 | hue->var_values[VAR_T], (int)hue->var_values[VAR_N]); |
| 324 | | 280 | |
| 325 | compute_sin_and_cos(hue); | 281 | compute_sin_and_cos(hue); |
| 326 | } | | |
| 327 | | 282 | |
| 328 | hue->var_values[VAR_N] += 1; | 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 | static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, | 300 | static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, |
| 346 | char *res, int res_len, int flags) | 301 | char *res, int res_len, int flags) |
| 347 | { | 302 | { |
| 348 | if (!strcmp(cmd, "reinit")) | 303 | HueContext *hue = ctx->priv; |
| 349 | return set_options(ctx, args); | 304 | |
| 350 | else | 305 | #define SET_CMD(expr, option) \ |
| 351 | return AVERROR(ENOSYS); | 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 | static const AVFilterPad hue_inputs[] = { | 316 | static const AVFilterPad hue_inputs[] = { |