[FFmpeg-devel] [PATCH 2/2] drawtext: introduce fontcolor argument expansion
Andrey Utkin
andrey.krieger.utkin at gmail.com
Sun Jun 22 16:31:10 CEST 2014
---
libavfilter/vf_drawtext.c | 68 +++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 63 insertions(+), 5 deletions(-)
diff --git a/libavfilter/vf_drawtext.c b/libavfilter/vf_drawtext.c
index adc587e..4ac7ab9 100644
--- a/libavfilter/vf_drawtext.c
+++ b/libavfilter/vf_drawtext.c
@@ -35,6 +35,7 @@
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
+#include <fenv.h>
#if CONFIG_LIBFONTCONFIG
#include <fontconfig/fontconfig.h>
@@ -136,6 +137,8 @@ typedef struct DrawTextContext {
uint8_t *fontfile; ///< font to be used
uint8_t *text; ///< text to be drawn
AVBPrint expanded_text; ///< used to contain the expanded text
+ uint8_t *fontcolor_expr; ///< fontcolor expression to evaluate
+ AVBPrint expanded_fontcolor; ///< used to contain the expanded fontcolor spec
int ft_load_flags; ///< flags used for loading fonts, see FT_LOAD_*
FT_Vector *positions; ///< positions for each element in the text
size_t nb_positions; ///< number of elements of positions array
@@ -191,6 +194,7 @@ static const AVOption drawtext_options[]= {
{"text", "set text", OFFSET(text), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS},
{"textfile", "set text file", OFFSET(textfile), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS},
{"fontcolor", "set foreground color", OFFSET(fontcolor.rgba), AV_OPT_TYPE_COLOR, {.str="black"}, CHAR_MIN, CHAR_MAX, FLAGS},
+ {"fontcolor_expr", "set foreground color expression to evaluate", OFFSET(fontcolor_expr), AV_OPT_TYPE_STRING, {.str=""}, CHAR_MIN, CHAR_MAX, FLAGS},
{"boxcolor", "set box color", OFFSET(boxcolor.rgba), AV_OPT_TYPE_COLOR, {.str="white"}, CHAR_MIN, CHAR_MAX, FLAGS},
{"bordercolor", "set border color", OFFSET(bordercolor.rgba), AV_OPT_TYPE_COLOR, {.str="black"}, CHAR_MIN, CHAR_MAX, FLAGS},
{"shadowcolor", "set shadow color", OFFSET(shadowcolor.rgba), AV_OPT_TYPE_COLOR, {.str="black"}, CHAR_MIN, CHAR_MAX, FLAGS},
@@ -198,6 +202,7 @@ static const AVOption drawtext_options[]= {
{"fontsize", "set font size", OFFSET(fontsize), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX , FLAGS},
{"x", "set x expression", OFFSET(x_expr), AV_OPT_TYPE_STRING, {.str="0"}, CHAR_MIN, CHAR_MAX, FLAGS},
{"y", "set y expression", OFFSET(y_expr), AV_OPT_TYPE_STRING, {.str="0"}, CHAR_MIN, CHAR_MAX, FLAGS},
+ {"fontcolor_expr", "set fontcolor expression", OFFSET(fontcolor_expr), AV_OPT_TYPE_STRING, {.str=""}, CHAR_MIN, CHAR_MAX, FLAGS},
{"shadowx", "set x", OFFSET(shadowx), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX , FLAGS},
{"shadowy", "set y", OFFSET(shadowy), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX , FLAGS},
{"borderw", "set border width", OFFSET(borderw), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX , FLAGS},
@@ -569,6 +574,7 @@ static av_cold int init(AVFilterContext *ctx)
av_log(ctx, AV_LOG_WARNING, "expansion=strftime is deprecated.\n");
av_bprint_init(&s->expanded_text, 0, AV_BPRINT_SIZE_UNLIMITED);
+ av_bprint_init(&s->expanded_fontcolor, 0, AV_BPRINT_SIZE_UNLIMITED);
return 0;
}
@@ -612,6 +618,7 @@ static av_cold void uninit(AVFilterContext *ctx)
FT_Done_FreeType(s->library);
av_bprint_finalize(&s->expanded_text, NULL);
+ av_bprint_finalize(&s->expanded_fontcolor, NULL);
}
static inline int is_newline(uint32_t c)
@@ -800,6 +807,44 @@ static int func_eval_expr(AVFilterContext *ctx, AVBPrint *bp,
return ret;
}
+static int func_eval_expr_int_format(AVFilterContext *ctx, AVBPrint *bp,
+ char *fct, unsigned argc, char **argv, int tag)
+{
+ DrawTextContext *s = ctx->priv;
+ double res;
+ int intval;
+ int ret;
+
+ /* Check that argv[0] (format) contains exactly one output specifier */
+ const char *percent_sign = strchr(argv[0], '%');
+ if (!percent_sign || strchr(percent_sign + 1, '%')) {
+ av_log(ctx, AV_LOG_ERROR, "Format must contain exactly one output "
+ "specifier, but '%s' is supplied\n", argv[0]);
+ return AVERROR(EINVAL);
+ }
+ ret = av_expr_parse_and_eval(&res, argv[1], var_names, s->var_values,
+ NULL, NULL, fun2_names, fun2,
+ &s->prng, 0, ctx);
+ if (ret < 0)
+ av_log(ctx, AV_LOG_ERROR,
+ "Expression '%s' for the expr text expansion function is not valid\n",
+ argv[1]);
+ else
+ {
+ av_log(ctx, AV_LOG_DEBUG, "Formatting value %f (expr '%s') with spec '%s'\n",
+ res, argv[1], argv[0]);
+ feclearexcept(FE_ALL_EXCEPT);
+ intval = res;
+ if ((ret = fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW))) {
+ av_log(ctx, AV_LOG_ERROR, "Conversion of floating-point result to int failed. Control register: 0x%08x. Conversion result: %d\n", ret, intval);
+ return AVERROR(EINVAL);
+ }
+ av_bprintf(bp, argv[0], intval);
+ }
+
+ return ret;
+}
+
static const struct drawtext_function {
const char *name;
unsigned argc_min, argc_max;
@@ -808,6 +853,7 @@ static const struct drawtext_function {
} functions[] = {
{ "expr", 1, 1, 0, func_eval_expr },
{ "e", 1, 1, 0, func_eval_expr },
+ { "eif", 2, 2, 0, func_eval_expr_int_format },
{ "pict_type", 0, 0, 0, func_pict_type },
{ "pts", 0, 2, 0, func_pts },
{ "gmtime", 0, 1, 'G', func_strftime },
@@ -884,11 +930,8 @@ end:
return ret;
}
-static int expand_text(AVFilterContext *ctx)
+static int expand_text(AVFilterContext *ctx, char *text, AVBPrint *bp)
{
- DrawTextContext *s = ctx->priv;
- char *text = s->text;
- AVBPrint *bp = &s->expanded_text;
int ret;
av_bprint_clear(bp);
@@ -984,7 +1027,7 @@ static int draw_text(AVFilterContext *ctx, AVFrame *frame,
av_bprintf(bp, "%s", s->text);
break;
case EXP_NORMAL:
- if ((ret = expand_text(ctx)) < 0)
+ if ((ret = expand_text(ctx, s->text, &s->expanded_text)) < 0)
return ret;
break;
case EXP_STRFTIME:
@@ -1010,6 +1053,21 @@ static int draw_text(AVFilterContext *ctx, AVFrame *frame,
s->nb_positions = len;
}
+ if (s->fontcolor_expr[0]) {
+ /* If expression is set, evaluate and repace statically set */
+ av_bprint_clear(&s->expanded_fontcolor);
+ if ((ret = expand_text(ctx, s->fontcolor_expr, &s->expanded_fontcolor)) < 0)
+ return ret;
+ if (!av_bprint_is_complete(&s->expanded_fontcolor))
+ return AVERROR(ENOMEM);
+ av_log(s, AV_LOG_DEBUG, "Evaluated fontcolor is '%s'\n", s->expanded_fontcolor.str);
+ ret = av_parse_color(s->fontcolor.rgba, s->expanded_fontcolor.str, -1, s);
+ if (ret)
+ return ret;
+ ff_draw_color(&s->dc, &s->fontcolor, s->fontcolor.rgba);
+ }
+
+
x = 0;
y = 0;
--
1.8.3.2
More information about the ffmpeg-devel
mailing list