|
|
@@ -36,12 +36,6 @@ |
|
|
|
#include "internal.h" |
|
|
|
#include "video.h" |
|
|
|
|
|
|
|
#define HUE_DEFAULT_VAL 0 |
|
|
|
#define SAT_DEFAULT_VAL 1 |
|
|
|
|
|
|
|
#define HUE_DEFAULT_VAL_STRING AV_STRINGIFY(HUE_DEFAULT_VAL) |
|
|
|
#define SAT_DEFAULT_VAL_STRING AV_STRINGIFY(SAT_DEFAULT_VAL) |
|
|
|
|
|
|
|
#define SAT_MIN_VAL -10 |
|
|
|
#define SAT_MAX_VAL 10 |
|
|
|
|
|
|
@@ -78,7 +72,6 @@ typedef struct { |
|
|
|
int vsub; |
|
|
|
int32_t hue_sin; |
|
|
|
int32_t hue_cos; |
|
|
|
int flat_syntax; |
|
|
|
double var_values[VAR_NB]; |
|
|
|
} HueContext; |
|
|
|
|
|
|
@@ -87,9 +80,9 @@ typedef struct { |
|
|
|
static const AVOption hue_options[] = { |
|
|
|
{ "h", "set the hue angle degrees expression", OFFSET(hue_deg_expr), AV_OPT_TYPE_STRING, |
|
|
|
{ .str = NULL }, .flags = FLAGS }, |
|
|
|
{ "H", "set the hue angle radians expression", OFFSET(hue_expr), AV_OPT_TYPE_STRING, |
|
|
|
{ .str = NULL }, .flags = FLAGS }, |
|
|
|
{ "s", "set the saturation expression", OFFSET(saturation_expr), AV_OPT_TYPE_STRING, |
|
|
|
{ .str = "1" }, .flags = FLAGS }, |
|
|
|
{ "H", "set the hue angle radians expression", OFFSET(hue_expr), AV_OPT_TYPE_STRING, |
|
|
|
{ .str = NULL }, .flags = FLAGS }, |
|
|
|
{ NULL } |
|
|
|
}; |
|
|
@@ -107,99 +100,62 @@ static inline void compute_sin_and_cos(HueContext *hue) |
|
|
|
hue->hue_cos = rint(cos(hue->hue) * (1 << 16) * hue->saturation); |
|
|
|
} |
|
|
|
|
|
|
|
#define SET_EXPRESSION(attr, name) do { \ |
|
|
|
if (hue->attr##_expr) { \ |
|
|
|
if ((ret = av_expr_parse(&hue->attr##_pexpr, hue->attr##_expr, var_names, \ |
|
|
|
NULL, NULL, NULL, NULL, 0, ctx)) < 0) { \ |
|
|
|
av_log(ctx, AV_LOG_ERROR, \ |
|
|
|
"Parsing failed for expression " #name "='%s'", \ |
|
|
|
hue->attr##_expr); \ |
|
|
|
hue->attr##_expr = old_##attr##_expr; \ |
|
|
|
hue->attr##_pexpr = old_##attr##_pexpr; \ |
|
|
|
return AVERROR(EINVAL); \ |
|
|
|
} else if (old_##attr##_pexpr) { \ |
|
|
|
av_freep(&old_##attr##_expr); \ |
|
|
|
av_expr_free(old_##attr##_pexpr); \ |
|
|
|
old_##attr##_pexpr = NULL; \ |
|
|
|
} \ |
|
|
|
} else { \ |
|
|
|
hue->attr##_expr = old_##attr##_expr; \ |
|
|
|
} \ |
|
|
|
} while (0) |
|
|
|
|
|
|
|
static inline int set_options(AVFilterContext *ctx, const char *args) |
|
|
|
static int set_expr(AVExpr **pexpr, const char *expr, const char *option, void *log_ctx) |
|
|
|
{ |
|
|
|
HueContext *hue = ctx->priv; |
|
|
|
int ret; |
|
|
|
char *old_hue_expr, *old_hue_deg_expr, *old_saturation_expr; |
|
|
|
AVExpr *old_hue_pexpr, *old_hue_deg_pexpr, *old_saturation_pexpr; |
|
|
|
static const char *shorthand[] = { "h", "s", NULL }; |
|
|
|
old_hue_expr = hue->hue_expr; |
|
|
|
old_hue_deg_expr = hue->hue_deg_expr; |
|
|
|
old_saturation_expr = hue->saturation_expr; |
|
|
|
|
|
|
|
old_hue_pexpr = hue->hue_pexpr; |
|
|
|
old_hue_deg_pexpr = hue->hue_deg_pexpr; |
|
|
|
old_saturation_pexpr = hue->saturation_pexpr; |
|
|
|
|
|
|
|
hue->hue_expr = NULL; |
|
|
|
hue->hue_deg_expr = NULL; |
|
|
|
hue->saturation_expr = NULL; |
|
|
|
|
|
|
|
if ((ret = av_opt_set_from_string(hue, args, shorthand, "=", ":")) < 0) |
|
|
|
AVExpr *old = NULL; |
|
|
|
|
|
|
|
if (*pexpr) |
|
|
|
old = *pexpr; |
|
|
|
ret = av_expr_parse(pexpr, expr, var_names, |
|
|
|
NULL, NULL, NULL, NULL, 0, log_ctx); |
|
|
|
if (ret < 0) { |
|
|
|
av_log(log_ctx, AV_LOG_ERROR, |
|
|
|
"Error when evaluating the expression '%s' for %s\n", |
|
|
|
expr, option); |
|
|
|
*pexpr = old; |
|
|
|
return ret; |
|
|
|
} |
|
|
|
av_expr_free(old); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static av_cold int init(AVFilterContext *ctx, const char *args) |
|
|
|
{ |
|
|
|
HueContext *hue = ctx->priv; |
|
|
|
int ret; |
|
|
|
|
|
|
|
if (hue->hue_expr && hue->hue_deg_expr) { |
|
|
|
av_log(ctx, AV_LOG_ERROR, |
|
|
|
"H and h options are incompatible and cannot be specified " |
|
|
|
"at the same time\n"); |
|
|
|
hue->hue_expr = old_hue_expr; |
|
|
|
hue->hue_deg_expr = old_hue_deg_expr; |
|
|
|
|
|
|
|
return AVERROR(EINVAL); |
|
|
|
} |
|
|
|
|
|
|
|
SET_EXPRESSION(hue_deg, h); |
|
|
|
SET_EXPRESSION(hue, H); |
|
|
|
SET_EXPRESSION(saturation, s); |
|
|
|
|
|
|
|
hue->flat_syntax = 0; |
|
|
|
#define SET_EXPR(expr, option) \ |
|
|
|
if (hue->expr##_expr) do { \ |
|
|
|
ret = set_expr(&hue->expr##_pexpr, hue->expr##_expr, option, ctx); \ |
|
|
|
if (ret < 0) \ |
|
|
|
return ret; \ |
|
|
|
} while (0) |
|
|
|
SET_EXPR(saturation, "s"); |
|
|
|
SET_EXPR(hue_deg, "h"); |
|
|
|
SET_EXPR(hue, "H"); |
|
|
|
|
|
|
|
av_log(ctx, AV_LOG_VERBOSE, |
|
|
|
"H_expr:%s h_deg_expr:%s s_expr:%s\n", |
|
|
|
hue->hue_expr, hue->hue_deg_expr, hue->saturation_expr); |
|
|
|
|
|
|
|
compute_sin_and_cos(hue); |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static av_cold int init(AVFilterContext *ctx, const char *args) |
|
|
|
{ |
|
|
|
HueContext *hue = ctx->priv; |
|
|
|
|
|
|
|
hue->class = &hue_class; |
|
|
|
av_opt_set_defaults(hue); |
|
|
|
|
|
|
|
hue->saturation = SAT_DEFAULT_VAL; |
|
|
|
hue->hue = HUE_DEFAULT_VAL; |
|
|
|
hue->hue_deg_pexpr = NULL; |
|
|
|
hue->hue_pexpr = NULL; |
|
|
|
hue->flat_syntax = 1; |
|
|
|
|
|
|
|
return set_options(ctx, args); |
|
|
|
} |
|
|
|
|
|
|
|
static av_cold void uninit(AVFilterContext *ctx) |
|
|
|
{ |
|
|
|
HueContext *hue = ctx->priv; |
|
|
|
|
|
|
|
av_opt_free(hue); |
|
|
|
|
|
|
|
av_free(hue->hue_deg_expr); |
|
|
|
av_expr_free(hue->hue_deg_pexpr); |
|
|
|
av_free(hue->hue_expr); |
|
|
|
av_expr_free(hue->hue_pexpr); |
|
|
|
av_free(hue->saturation_expr); |
|
|
|
av_expr_free(hue->saturation_pexpr); |
|
|
|
} |
|
|
|
|
|
|
@@ -295,7 +251,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpic) |
|
|
|
av_frame_copy_props(outpic, inpic); |
|
|
|
} |
|
|
|
|
|
|
|
if (!hue->flat_syntax) { |
|
|
|
/* todo: reindent */ |
|
|
|
hue->var_values[VAR_T] = TS2T(inpic->pts, inlink->time_base); |
|
|
|
hue->var_values[VAR_PTS] = TS2D(inpic->pts); |
|
|
|
|
|
|
@@ -323,7 +279,6 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpic) |
|
|
|
hue->var_values[VAR_T], (int)hue->var_values[VAR_N]); |
|
|
|
|
|
|
|
compute_sin_and_cos(hue); |
|
|
|
} |
|
|
|
|
|
|
|
hue->var_values[VAR_N] += 1; |
|
|
|
|
|
|
@@ -345,10 +300,17 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpic) |
|
|
|
static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, |
|
|
|
char *res, int res_len, int flags) |
|
|
|
{ |
|
|
|
if (!strcmp(cmd, "reinit")) |
|
|
|
return set_options(ctx, args); |
|
|
|
else |
|
|
|
return AVERROR(ENOSYS); |
|
|
|
HueContext *hue = ctx->priv; |
|
|
|
|
|
|
|
#define SET_CMD(expr, option) \ |
|
|
|
if (!strcmp(cmd, option)) do { \ |
|
|
|
return set_expr(&hue->expr##_pexpr, args, cmd, ctx); \ |
|
|
|
} while (0) |
|
|
|
SET_CMD(hue_deg, "h"); |
|
|
|
SET_CMD(hue, "H"); |
|
|
|
SET_CMD(saturation, "s"); |
|
|
|
|
|
|
|
return AVERROR(ENOSYS); |
|
|
|
} |
|
|
|
|
|
|
|
static const AVFilterPad hue_inputs[] = { |
|
|
|