X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavfilter%2Fvf_drawtext.c;h=912a8547bbd14ea4aab2ee2d604c26ce28845195;hb=8e2bab5d4bddb4029503c0f90623854948ddb3c5;hp=a8d3517b99c30248e5aa55f1e7ef30bd0bc1b9ed;hpb=f884ef00de362a5460a9c58318d009bcae440cc8;p=ffmpeg diff --git a/libavfilter/vf_drawtext.c b/libavfilter/vf_drawtext.c index a8d3517b99c..912a8547bbd 100644 --- a/libavfilter/vf_drawtext.c +++ b/libavfilter/vf_drawtext.c @@ -22,7 +22,7 @@ /** * @file - * drawtext filter, based on the original FFmpeg vhook/drawtext.c + * drawtext filter, based on the original vhook/drawtext.c * filter by Gustavo Sverzut Barbieri */ @@ -30,12 +30,14 @@ #include #include "libavutil/colorspace.h" -#include "libavutil/eval.h" #include "libavutil/file.h" +#include "libavutil/eval.h" #include "libavutil/opt.h" +#include "libavutil/random_seed.h" #include "libavutil/parseutils.h" #include "libavutil/pixdesc.h" #include "libavutil/tree.h" +#include "libavutil/lfg.h" #include "avfilter.h" #include "drawutils.h" @@ -46,12 +48,9 @@ #include FT_FREETYPE_H #include FT_GLYPH_H -static const char *var_names[] = { - "E", - "PHI", - "PI", - "w", ///< width of the input video - "h", ///< height of the input video +static const char * const var_names[] = { + "main_w", "w", "W", ///< width of the input video + "main_h", "h", "H", ///< height of the input video "tw", "text_w", ///< width of the rendered text "th", "text_h", ///< height of the rendered text "max_glyph_w", ///< max glyph width @@ -70,12 +69,25 @@ static const char *var_names[] = { NULL }; +static const char *fun2_names[] = { + "rand", +}; + +static double drand(void *opaque, double min, double max) +{ + return min + (max-min) / UINT_MAX * av_lfg_get(opaque); +} + +typedef double (*eval_func2)(void *, double a, double b); + +static const eval_func2 fun2[] = { + drand, + NULL +}; + enum var_name { - VAR_E, - VAR_PHI, - VAR_PI, - VAR_W, - VAR_H, + VAR_MAIN_W, VAR_w, VAR_W, + VAR_MAIN_H, VAR_h, VAR_H, VAR_TW, VAR_TEXT_W, VAR_TH, VAR_TEXT_H, VAR_MAX_GLYPH_W, @@ -107,9 +119,6 @@ typedef struct { char *textfile; ///< file with text to be drawn int x; ///< x position to start drawing text int y; ///< y position to start drawing text - char *x_expr; ///< expression for x position - char *y_expr; ///< expression for y position - AVExpr *x_pexpr, *y_pexpr; ///< parsed expressions for x and y int max_glyph_w; ///< max glyph width int max_glyph_h; ///< max glyph heigth int shadowx, shadowy; @@ -136,8 +145,15 @@ typedef struct { int pixel_step[4]; ///< distance in bytes between the component of each pixel uint8_t rgba_map[4]; ///< map RGBA offsets to the positions in the packed RGBA format uint8_t *box_line[4]; ///< line used for filling the box background + char *x_expr; ///< expression for x position + char *y_expr; ///< expression for y position + AVExpr *x_pexpr, *y_pexpr; ///< parsed expressions for x and y int64_t basetime; ///< base pts time in the real world for display double var_values[VAR_VARS_NB]; + char *d_expr; + AVExpr *d_pexpr; + int draw; ///< set to zero to prevent drawing + AVLFG prng; ///< random } DrawTextContext; #define OFFSET(x) offsetof(DrawTextContext, x) @@ -157,7 +173,7 @@ static const AVOption drawtext_options[]= { {"shadowy", "set y", OFFSET(shadowy), AV_OPT_TYPE_INT, {.dbl=0}, INT_MIN, INT_MAX }, {"tabsize", "set tab size", OFFSET(tabsize), AV_OPT_TYPE_INT, {.dbl=4}, 0, INT_MAX }, {"basetime", "set base time", OFFSET(basetime), AV_OPT_TYPE_INT64, {.dbl=AV_NOPTS_VALUE}, INT64_MIN, INT64_MAX }, - +{"draw", "if false do not draw", OFFSET(d_expr), AV_OPT_TYPE_STRING, {.str="1"}, CHAR_MIN, CHAR_MAX }, /* FT_LOAD_* flags */ {"ft_load_flags", "set font loading flags for libfreetype", OFFSET(ft_load_flags), AV_OPT_TYPE_FLAGS, {.dbl=FT_LOAD_DEFAULT|FT_LOAD_RENDER}, 0, INT_MAX, 0, "ft_load_flags" }, @@ -365,7 +381,7 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) load_glyph(ctx, NULL, 0); /* set the tabsize in pixels */ - if ((err = load_glyph(ctx, &glyph, ' ') < 0)) { + if ((err = load_glyph(ctx, &glyph, ' ')) < 0) { av_log(ctx, AV_LOG_ERROR, "Could not set tabsize.\n"); return err; } @@ -429,10 +445,15 @@ static av_cold void uninit(AVFilterContext *ctx) } } +static inline int is_newline(uint32_t c) +{ + return (c == '\n' || c == '\r' || c == '\f' || c == '\v'); +} + static int config_input(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; - DrawTextContext *dtext = inlink->dst->priv; + DrawTextContext *dtext = ctx->priv; const AVPixFmtDescriptor *pix_desc = &av_pix_fmt_descriptors[inlink->format]; int ret; @@ -459,11 +480,8 @@ static int config_input(AVFilterLink *inlink) dtext->shadowcolor[3] = rgba[3]; } - dtext->var_values[VAR_E] = M_E; - dtext->var_values[VAR_PHI] = M_PHI; - dtext->var_values[VAR_PI] = M_PI; - dtext->var_values[VAR_W] = inlink->w; - dtext->var_values[VAR_H] = inlink->h; + dtext->var_values[VAR_w] = dtext->var_values[VAR_W] = dtext->var_values[VAR_MAIN_W] = inlink->w; + dtext->var_values[VAR_h] = dtext->var_values[VAR_H] = dtext->var_values[VAR_MAIN_H] = inlink->h; dtext->var_values[VAR_SAR] = inlink->sample_aspect_ratio.num ? av_q2d(inlink->sample_aspect_ratio) : 1; dtext->var_values[VAR_DAR] = (double)inlink->w / inlink->h * dtext->var_values[VAR_SAR]; dtext->var_values[VAR_HSUB] = 1<log2_chroma_w; @@ -474,10 +492,15 @@ static int config_input(AVFilterLink *inlink) dtext->var_values[VAR_N] = 0; dtext->var_values[VAR_T] = NAN; + av_lfg_init(&dtext->prng, av_get_random_seed()); + if ((ret = av_expr_parse(&dtext->x_pexpr, dtext->x_expr, var_names, - NULL, NULL, NULL, NULL, 0, ctx)) < 0 || + NULL, NULL, fun2_names, fun2, 0, ctx)) < 0 || (ret = av_expr_parse(&dtext->y_pexpr, dtext->y_expr, var_names, - NULL, NULL, NULL, NULL, 0, ctx)) < 0) + NULL, NULL, fun2_names, fun2, 0, ctx)) < 0 || + (ret = av_expr_parse(&dtext->d_pexpr, dtext->d_expr, var_names, + NULL, NULL, fun2_names, fun2, 0, ctx)) < 0) + return AVERROR(EINVAL); return 0; @@ -601,11 +624,6 @@ static inline void drawbox(AVFilterBufferRef *picref, int x, int y, } } -static inline int is_newline(uint32_t c) -{ - return (c == '\n' || c == '\r' || c == '\f' || c == '\v'); -} - static int draw_glyphs(DrawTextContext *dtext, AVFilterBufferRef *picref, int width, int height, const uint8_t rgbcolor[4], const uint8_t yuvcolor[4], int x, int y) { @@ -770,9 +788,13 @@ static int draw_text(AVFilterContext *ctx, AVFilterBufferRef *picref, dtext->var_values[VAR_LINE_H] = dtext->var_values[VAR_LH] = dtext->max_glyph_h; - dtext->x = dtext->var_values[VAR_X] = av_expr_eval(dtext->x_pexpr, dtext->var_values, NULL); - dtext->y = dtext->var_values[VAR_Y] = av_expr_eval(dtext->y_pexpr, dtext->var_values, NULL); - dtext->x = dtext->var_values[VAR_X] = av_expr_eval(dtext->x_pexpr, dtext->var_values, NULL); + dtext->x = dtext->var_values[VAR_X] = av_expr_eval(dtext->x_pexpr, dtext->var_values, &dtext->prng); + dtext->y = dtext->var_values[VAR_Y] = av_expr_eval(dtext->y_pexpr, dtext->var_values, &dtext->prng); + dtext->x = dtext->var_values[VAR_X] = av_expr_eval(dtext->x_pexpr, dtext->var_values, &dtext->prng); + dtext->draw = av_expr_eval(dtext->d_pexpr, dtext->var_values, &dtext->prng); + + if(!dtext->draw) + return 0; dtext->x &= ~((1 << dtext->hsub) - 1); dtext->y &= ~((1 << dtext->vsub) - 1); @@ -832,7 +854,7 @@ AVFilter avfilter_vf_drawtext = { .uninit = uninit, .query_formats = query_formats, - .inputs = (AVFilterPad[]) {{ .name = "default", + .inputs = (const AVFilterPad[]) {{ .name = "default", .type = AVMEDIA_TYPE_VIDEO, .get_video_buffer = avfilter_null_get_video_buffer, .start_frame = avfilter_null_start_frame, @@ -843,7 +865,7 @@ AVFilter avfilter_vf_drawtext = { AV_PERM_READ, .rej_perms = AV_PERM_PRESERVE }, { .name = NULL}}, - .outputs = (AVFilterPad[]) {{ .name = "default", + .outputs = (const AVFilterPad[]) {{ .name = "default", .type = AVMEDIA_TYPE_VIDEO, }, { .name = NULL}}, .process_command = command,