FFmpeg
vf_drawtext.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011 Stefano Sabatini
3  * Copyright (c) 2010 S.N. Hemanth Meenakshisundaram
4  * Copyright (c) 2003 Gustavo Sverzut Barbieri <gsbarbieri@yahoo.com.br>
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with FFmpeg; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 /**
24  * @file
25  * drawtext filter, based on the original vhook/drawtext.c
26  * filter by Gustavo Sverzut Barbieri
27  */
28 
29 #include "config.h"
30 
31 #if HAVE_SYS_TIME_H
32 #include <sys/time.h>
33 #endif
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <time.h>
37 #if HAVE_UNISTD_H
38 #include <unistd.h>
39 #endif
40 #include <fenv.h>
41 
42 #if CONFIG_LIBFONTCONFIG
43 #include <fontconfig/fontconfig.h>
44 #endif
45 
46 #include "libavutil/avstring.h"
47 #include "libavutil/bprint.h"
48 #include "libavutil/common.h"
49 #include "libavutil/file.h"
50 #include "libavutil/eval.h"
51 #include "libavutil/opt.h"
52 #include "libavutil/random_seed.h"
53 #include "libavutil/parseutils.h"
54 #include "libavutil/timecode.h"
56 #include "libavutil/tree.h"
57 #include "libavutil/lfg.h"
58 #include "avfilter.h"
59 #include "drawutils.h"
60 #include "formats.h"
61 #include "internal.h"
62 #include "video.h"
63 
64 #if CONFIG_LIBFRIBIDI
65 #include <fribidi.h>
66 #endif
67 
68 #include <ft2build.h>
69 #include FT_FREETYPE_H
70 #include FT_GLYPH_H
71 #include FT_STROKER_H
72 
73 static const char *const var_names[] = {
74  "dar",
75  "hsub", "vsub",
76  "line_h", "lh", ///< line height, same as max_glyph_h
77  "main_h", "h", "H", ///< height of the input video
78  "main_w", "w", "W", ///< width of the input video
79  "max_glyph_a", "ascent", ///< max glyph ascent
80  "max_glyph_d", "descent", ///< min glyph descent
81  "max_glyph_h", ///< max glyph height
82  "max_glyph_w", ///< max glyph width
83  "n", ///< number of frame
84  "sar",
85  "t", ///< timestamp expressed in seconds
86  "text_h", "th", ///< height of the rendered text
87  "text_w", "tw", ///< width of the rendered text
88  "x",
89  "y",
90  "pict_type",
91  NULL
92 };
93 
94 static const char *const fun2_names[] = {
95  "rand"
96 };
97 
98 static double drand(void *opaque, double min, double max)
99 {
100  return min + (max-min) / UINT_MAX * av_lfg_get(opaque);
101 }
102 
103 typedef double (*eval_func2)(void *, double a, double b);
104 
105 static const eval_func2 fun2[] = {
106  drand,
107  NULL
108 };
109 
110 enum var_name {
129 };
130 
135 };
136 
137 typedef struct DrawTextContext {
138  const AVClass *class;
139  int exp_mode; ///< expansion mode to use for the text
140  int reinit; ///< tells if the filter is being reinited
141 #if CONFIG_LIBFONTCONFIG
142  uint8_t *font; ///< font to be used
143 #endif
144  uint8_t *fontfile; ///< font to be used
145  uint8_t *text; ///< text to be drawn
146  AVBPrint expanded_text; ///< used to contain the expanded text
147  uint8_t *fontcolor_expr; ///< fontcolor expression to evaluate
148  AVBPrint expanded_fontcolor; ///< used to contain the expanded fontcolor spec
149  int ft_load_flags; ///< flags used for loading fonts, see FT_LOAD_*
150  FT_Vector *positions; ///< positions for each element in the text
151  size_t nb_positions; ///< number of elements of positions array
152  char *textfile; ///< file with text to be drawn
153  int x; ///< x position to start drawing text
154  int y; ///< y position to start drawing text
155  int max_glyph_w; ///< max glyph width
156  int max_glyph_h; ///< max glyph height
158  int borderw; ///< border width
159  char *fontsize_expr; ///< expression for fontsize
160  AVExpr *fontsize_pexpr; ///< parsed expressions for fontsize
161  unsigned int fontsize; ///< font size to use
162  unsigned int default_fontsize; ///< default font size to use
163 
164  int line_spacing; ///< lines spacing in pixels
165  short int draw_box; ///< draw box around text - true or false
166  int boxborderw; ///< box border width
167  int use_kerning; ///< font kerning is used - true/false
168  int tabsize; ///< tab size
169  int fix_bounds; ///< do we let it go out of frame bounds - t/f
170 
172  FFDrawColor fontcolor; ///< foreground color
173  FFDrawColor shadowcolor; ///< shadow color
174  FFDrawColor bordercolor; ///< border color
175  FFDrawColor boxcolor; ///< background color
176 
177  FT_Library library; ///< freetype font library handle
178  FT_Face face; ///< freetype font face handle
179  FT_Stroker stroker; ///< freetype stroker handle
180  struct AVTreeNode *glyphs; ///< rendered glyphs, stored using the UTF-32 char code
181  char *x_expr; ///< expression for x position
182  char *y_expr; ///< expression for y position
183  AVExpr *x_pexpr, *y_pexpr; ///< parsed expressions for x and y
184  int64_t basetime; ///< base pts time in the real world for display
186  char *a_expr;
188  int alpha;
189  AVLFG prng; ///< random
190  char *tc_opt_string; ///< specified timecode option string
191  AVRational tc_rate; ///< frame rate for timecode
192  AVTimecode tc; ///< timecode context
193  int tc24hmax; ///< 1 if timecode is wrapped to 24 hours, 0 otherwise
194  int reload; ///< reload text file for each frame
195  int start_number; ///< starting frame number for n/frame_num var
196 #if CONFIG_LIBFRIBIDI
197  int text_shaping; ///< 1 to shape the text before drawing it
198 #endif
201 
202 #define OFFSET(x) offsetof(DrawTextContext, x)
203 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
204 
205 static const AVOption drawtext_options[]= {
206  {"fontfile", "set font file", OFFSET(fontfile), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS},
207  {"text", "set text", OFFSET(text), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS},
208  {"textfile", "set text file", OFFSET(textfile), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS},
209  {"fontcolor", "set foreground color", OFFSET(fontcolor.rgba), AV_OPT_TYPE_COLOR, {.str="black"}, CHAR_MIN, CHAR_MAX, FLAGS},
210  {"fontcolor_expr", "set foreground color expression", OFFSET(fontcolor_expr), AV_OPT_TYPE_STRING, {.str=""}, CHAR_MIN, CHAR_MAX, FLAGS},
211  {"boxcolor", "set box color", OFFSET(boxcolor.rgba), AV_OPT_TYPE_COLOR, {.str="white"}, CHAR_MIN, CHAR_MAX, FLAGS},
212  {"bordercolor", "set border color", OFFSET(bordercolor.rgba), AV_OPT_TYPE_COLOR, {.str="black"}, CHAR_MIN, CHAR_MAX, FLAGS},
213  {"shadowcolor", "set shadow color", OFFSET(shadowcolor.rgba), AV_OPT_TYPE_COLOR, {.str="black"}, CHAR_MIN, CHAR_MAX, FLAGS},
214  {"box", "set box", OFFSET(draw_box), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 , FLAGS},
215  {"boxborderw", "set box border width", OFFSET(boxborderw), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX , FLAGS},
216  {"line_spacing", "set line spacing in pixels", OFFSET(line_spacing), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX,FLAGS},
217  {"fontsize", "set font size", OFFSET(fontsize_expr), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX , FLAGS},
218  {"x", "set x expression", OFFSET(x_expr), AV_OPT_TYPE_STRING, {.str="0"}, CHAR_MIN, CHAR_MAX, FLAGS},
219  {"y", "set y expression", OFFSET(y_expr), AV_OPT_TYPE_STRING, {.str="0"}, CHAR_MIN, CHAR_MAX, FLAGS},
220  {"shadowx", "set shadow x offset", OFFSET(shadowx), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX , FLAGS},
221  {"shadowy", "set shadow y offset", OFFSET(shadowy), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX , FLAGS},
222  {"borderw", "set border width", OFFSET(borderw), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX , FLAGS},
223  {"tabsize", "set tab size", OFFSET(tabsize), AV_OPT_TYPE_INT, {.i64=4}, 0, INT_MAX , FLAGS},
224  {"basetime", "set base time", OFFSET(basetime), AV_OPT_TYPE_INT64, {.i64=AV_NOPTS_VALUE}, INT64_MIN, INT64_MAX , FLAGS},
225 #if CONFIG_LIBFONTCONFIG
226  { "font", "Font name", OFFSET(font), AV_OPT_TYPE_STRING, { .str = "Sans" }, .flags = FLAGS },
227 #endif
228 
229  {"expansion", "set the expansion mode", OFFSET(exp_mode), AV_OPT_TYPE_INT, {.i64=EXP_NORMAL}, 0, 2, FLAGS, "expansion"},
230  {"none", "set no expansion", OFFSET(exp_mode), AV_OPT_TYPE_CONST, {.i64=EXP_NONE}, 0, 0, FLAGS, "expansion"},
231  {"normal", "set normal expansion", OFFSET(exp_mode), AV_OPT_TYPE_CONST, {.i64=EXP_NORMAL}, 0, 0, FLAGS, "expansion"},
232  {"strftime", "set strftime expansion (deprecated)", OFFSET(exp_mode), AV_OPT_TYPE_CONST, {.i64=EXP_STRFTIME}, 0, 0, FLAGS, "expansion"},
233 
234  {"timecode", "set initial timecode", OFFSET(tc_opt_string), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS},
235  {"tc24hmax", "set 24 hours max (timecode only)", OFFSET(tc24hmax), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
236  {"timecode_rate", "set rate (timecode only)", OFFSET(tc_rate), AV_OPT_TYPE_RATIONAL, {.dbl=0}, 0, INT_MAX, FLAGS},
237  {"r", "set rate (timecode only)", OFFSET(tc_rate), AV_OPT_TYPE_RATIONAL, {.dbl=0}, 0, INT_MAX, FLAGS},
238  {"rate", "set rate (timecode only)", OFFSET(tc_rate), AV_OPT_TYPE_RATIONAL, {.dbl=0}, 0, INT_MAX, FLAGS},
239  {"reload", "reload text file for each frame", OFFSET(reload), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
240  { "alpha", "apply alpha while rendering", OFFSET(a_expr), AV_OPT_TYPE_STRING, { .str = "1" }, .flags = FLAGS },
241  {"fix_bounds", "check and fix text coords to avoid clipping", OFFSET(fix_bounds), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
242  {"start_number", "start frame number for n/frame_num variable", OFFSET(start_number), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS},
243 
244 #if CONFIG_LIBFRIBIDI
245  {"text_shaping", "attempt to shape text before drawing", OFFSET(text_shaping), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS},
246 #endif
247 
248  /* FT_LOAD_* flags */
249  { "ft_load_flags", "set font loading flags for libfreetype", OFFSET(ft_load_flags), AV_OPT_TYPE_FLAGS, { .i64 = FT_LOAD_DEFAULT }, 0, INT_MAX, FLAGS, "ft_load_flags" },
250  { "default", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_DEFAULT }, .flags = FLAGS, .unit = "ft_load_flags" },
251  { "no_scale", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_NO_SCALE }, .flags = FLAGS, .unit = "ft_load_flags" },
252  { "no_hinting", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_NO_HINTING }, .flags = FLAGS, .unit = "ft_load_flags" },
253  { "render", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_RENDER }, .flags = FLAGS, .unit = "ft_load_flags" },
254  { "no_bitmap", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_NO_BITMAP }, .flags = FLAGS, .unit = "ft_load_flags" },
255  { "vertical_layout", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_VERTICAL_LAYOUT }, .flags = FLAGS, .unit = "ft_load_flags" },
256  { "force_autohint", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_FORCE_AUTOHINT }, .flags = FLAGS, .unit = "ft_load_flags" },
257  { "crop_bitmap", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_CROP_BITMAP }, .flags = FLAGS, .unit = "ft_load_flags" },
258  { "pedantic", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_PEDANTIC }, .flags = FLAGS, .unit = "ft_load_flags" },
259  { "ignore_global_advance_width", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH }, .flags = FLAGS, .unit = "ft_load_flags" },
260  { "no_recurse", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_NO_RECURSE }, .flags = FLAGS, .unit = "ft_load_flags" },
261  { "ignore_transform", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_IGNORE_TRANSFORM }, .flags = FLAGS, .unit = "ft_load_flags" },
262  { "monochrome", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_MONOCHROME }, .flags = FLAGS, .unit = "ft_load_flags" },
263  { "linear_design", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_LINEAR_DESIGN }, .flags = FLAGS, .unit = "ft_load_flags" },
264  { "no_autohint", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_NO_AUTOHINT }, .flags = FLAGS, .unit = "ft_load_flags" },
265  { NULL }
266 };
267 
269 
270 #undef __FTERRORS_H__
271 #define FT_ERROR_START_LIST {
272 #define FT_ERRORDEF(e, v, s) { (e), (s) },
273 #define FT_ERROR_END_LIST { 0, NULL } };
274 
275 static const struct ft_error {
276  int err;
277  const char *err_msg;
278 } ft_errors[] =
279 #include FT_ERRORS_H
280 
281 #define FT_ERRMSG(e) ft_errors[e].err_msg
282 
283 typedef struct Glyph {
284  FT_Glyph glyph;
285  FT_Glyph border_glyph;
286  uint32_t code;
287  unsigned int fontsize;
288  FT_Bitmap bitmap; ///< array holding bitmaps of font
289  FT_Bitmap border_bitmap; ///< array holding bitmaps of font border
290  FT_BBox bbox;
291  int advance;
292  int bitmap_left;
293  int bitmap_top;
294 } Glyph;
295 
296 static int glyph_cmp(const void *key, const void *b)
297 {
298  const Glyph *a = key, *bb = b;
299  int64_t diff = (int64_t)a->code - (int64_t)bb->code;
300 
301  if (diff != 0)
302  return diff > 0 ? 1 : -1;
303  else
304  return FFDIFFSIGN((int64_t)a->fontsize, (int64_t)bb->fontsize);
305 }
306 
307 /**
308  * Load glyphs corresponding to the UTF-32 codepoint code.
309  */
310 static int load_glyph(AVFilterContext *ctx, Glyph **glyph_ptr, uint32_t code)
311 {
312  DrawTextContext *s = ctx->priv;
313  FT_BitmapGlyph bitmapglyph;
314  Glyph *glyph;
315  struct AVTreeNode *node = NULL;
316  int ret;
317 
318  /* load glyph into s->face->glyph */
319  if (FT_Load_Char(s->face, code, s->ft_load_flags))
320  return AVERROR(EINVAL);
321 
322  glyph = av_mallocz(sizeof(*glyph));
323  if (!glyph) {
324  ret = AVERROR(ENOMEM);
325  goto error;
326  }
327  glyph->code = code;
328  glyph->fontsize = s->fontsize;
329 
330  if (FT_Get_Glyph(s->face->glyph, &glyph->glyph)) {
331  ret = AVERROR(EINVAL);
332  goto error;
333  }
334  if (s->borderw) {
335  glyph->border_glyph = glyph->glyph;
336  if (FT_Glyph_StrokeBorder(&glyph->border_glyph, s->stroker, 0, 0) ||
337  FT_Glyph_To_Bitmap(&glyph->border_glyph, FT_RENDER_MODE_NORMAL, 0, 1)) {
338  ret = AVERROR_EXTERNAL;
339  goto error;
340  }
341  bitmapglyph = (FT_BitmapGlyph) glyph->border_glyph;
342  glyph->border_bitmap = bitmapglyph->bitmap;
343  }
344  if (FT_Glyph_To_Bitmap(&glyph->glyph, FT_RENDER_MODE_NORMAL, 0, 1)) {
345  ret = AVERROR_EXTERNAL;
346  goto error;
347  }
348  bitmapglyph = (FT_BitmapGlyph) glyph->glyph;
349 
350  glyph->bitmap = bitmapglyph->bitmap;
351  glyph->bitmap_left = bitmapglyph->left;
352  glyph->bitmap_top = bitmapglyph->top;
353  glyph->advance = s->face->glyph->advance.x >> 6;
354 
355  /* measure text height to calculate text_height (or the maximum text height) */
356  FT_Glyph_Get_CBox(glyph->glyph, ft_glyph_bbox_pixels, &glyph->bbox);
357 
358  /* cache the newly created glyph */
359  if (!(node = av_tree_node_alloc())) {
360  ret = AVERROR(ENOMEM);
361  goto error;
362  }
363  av_tree_insert(&s->glyphs, glyph, glyph_cmp, &node);
364 
365  if (glyph_ptr)
366  *glyph_ptr = glyph;
367  return 0;
368 
369 error:
370  if (glyph)
371  av_freep(&glyph->glyph);
372 
373  av_freep(&glyph);
374  av_freep(&node);
375  return ret;
376 }
377 
378 static av_cold int set_fontsize(AVFilterContext *ctx, unsigned int fontsize)
379 {
380  int err;
381  DrawTextContext *s = ctx->priv;
382 
383  if ((err = FT_Set_Pixel_Sizes(s->face, 0, fontsize))) {
384  av_log(ctx, AV_LOG_ERROR, "Could not set font size to %d pixels: %s\n",
385  fontsize, FT_ERRMSG(err));
386  return AVERROR(EINVAL);
387  }
388 
389  s->fontsize = fontsize;
390 
391  return 0;
392 }
393 
395 {
396  DrawTextContext *s = ctx->priv;
397  int err;
398 
399  if (s->fontsize_pexpr)
400  return 0;
401 
402  if (s->fontsize_expr == NULL)
403  return AVERROR(EINVAL);
404 
406  NULL, NULL, fun2_names, fun2, 0, ctx)) < 0)
407  return err;
408 
409  return 0;
410 }
411 
413 {
414  DrawTextContext *s = ctx->priv;
415  unsigned int fontsize = s->default_fontsize;
416  int err;
417  double size, roundedsize;
418 
419  // if no fontsize specified use the default
420  if (s->fontsize_expr != NULL) {
421  if ((err = parse_fontsize(ctx)) < 0)
422  return err;
423 
424  size = av_expr_eval(s->fontsize_pexpr, s->var_values, &s->prng);
425 
426  if (!isnan(size)) {
427  roundedsize = round(size);
428  // test for overflow before cast
429  if (!(roundedsize > INT_MIN && roundedsize < INT_MAX)) {
430  av_log(ctx, AV_LOG_ERROR, "fontsize overflow\n");
431  return AVERROR(EINVAL);
432  }
433 
434  fontsize = roundedsize;
435  }
436  }
437 
438  if (fontsize == 0)
439  fontsize = 1;
440 
441  // no change
442  if (fontsize == s->fontsize)
443  return 0;
444 
445  return set_fontsize(ctx, fontsize);
446 }
447 
448 static int load_font_file(AVFilterContext *ctx, const char *path, int index)
449 {
450  DrawTextContext *s = ctx->priv;
451  int err;
452 
453  err = FT_New_Face(s->library, path, index, &s->face);
454  if (err) {
455 #if !CONFIG_LIBFONTCONFIG
456  av_log(ctx, AV_LOG_ERROR, "Could not load font \"%s\": %s\n",
457  s->fontfile, FT_ERRMSG(err));
458 #endif
459  return AVERROR(EINVAL);
460  }
461  return 0;
462 }
463 
464 #if CONFIG_LIBFONTCONFIG
465 static int load_font_fontconfig(AVFilterContext *ctx)
466 {
467  DrawTextContext *s = ctx->priv;
468  FcConfig *fontconfig;
469  FcPattern *pat, *best;
470  FcResult result = FcResultMatch;
471  FcChar8 *filename;
472  int index;
473  double size;
474  int err = AVERROR(ENOENT);
475  int parse_err;
476 
477  fontconfig = FcInitLoadConfigAndFonts();
478  if (!fontconfig) {
479  av_log(ctx, AV_LOG_ERROR, "impossible to init fontconfig\n");
480  return AVERROR_UNKNOWN;
481  }
482  pat = FcNameParse(s->fontfile ? s->fontfile :
483  (uint8_t *)(intptr_t)"default");
484  if (!pat) {
485  av_log(ctx, AV_LOG_ERROR, "could not parse fontconfig pat");
486  return AVERROR(EINVAL);
487  }
488 
489  FcPatternAddString(pat, FC_FAMILY, s->font);
490 
491  parse_err = parse_fontsize(ctx);
492  if (!parse_err) {
493  double size = av_expr_eval(s->fontsize_pexpr, s->var_values, &s->prng);
494 
495  if (isnan(size)) {
496  av_log(ctx, AV_LOG_ERROR, "impossible to find font information");
497  return AVERROR(EINVAL);
498  }
499 
500  FcPatternAddDouble(pat, FC_SIZE, size);
501  }
502 
503  FcDefaultSubstitute(pat);
504 
505  if (!FcConfigSubstitute(fontconfig, pat, FcMatchPattern)) {
506  av_log(ctx, AV_LOG_ERROR, "could not substitue fontconfig options"); /* very unlikely */
507  FcPatternDestroy(pat);
508  return AVERROR(ENOMEM);
509  }
510 
511  best = FcFontMatch(fontconfig, pat, &result);
512  FcPatternDestroy(pat);
513 
514  if (!best || result != FcResultMatch) {
515  av_log(ctx, AV_LOG_ERROR,
516  "Cannot find a valid font for the family %s\n",
517  s->font);
518  goto fail;
519  }
520 
521  if (
522  FcPatternGetInteger(best, FC_INDEX, 0, &index ) != FcResultMatch ||
523  FcPatternGetDouble (best, FC_SIZE, 0, &size ) != FcResultMatch) {
524  av_log(ctx, AV_LOG_ERROR, "impossible to find font information");
525  return AVERROR(EINVAL);
526  }
527 
528  if (FcPatternGetString(best, FC_FILE, 0, &filename) != FcResultMatch) {
529  av_log(ctx, AV_LOG_ERROR, "No file path for %s\n",
530  s->font);
531  goto fail;
532  }
533 
534  av_log(ctx, AV_LOG_INFO, "Using \"%s\"\n", filename);
535  if (parse_err)
536  s->default_fontsize = size + 0.5;
537 
538  err = load_font_file(ctx, filename, index);
539  if (err)
540  return err;
541  FcConfigDestroy(fontconfig);
542 fail:
543  FcPatternDestroy(best);
544  return err;
545 }
546 #endif
547 
548 static int load_font(AVFilterContext *ctx)
549 {
550  DrawTextContext *s = ctx->priv;
551  int err;
552 
553  /* load the face, and set up the encoding, which is by default UTF-8 */
554  err = load_font_file(ctx, s->fontfile, 0);
555  if (!err)
556  return 0;
557 #if CONFIG_LIBFONTCONFIG
558  err = load_font_fontconfig(ctx);
559  if (!err)
560  return 0;
561 #endif
562  return err;
563 }
564 
566 {
567  DrawTextContext *s = ctx->priv;
568  int err;
569  uint8_t *textbuf;
570  uint8_t *tmp;
571  size_t textbuf_size;
572 
573  if ((err = av_file_map(s->textfile, &textbuf, &textbuf_size, 0, ctx)) < 0) {
574  av_log(ctx, AV_LOG_ERROR,
575  "The text file '%s' could not be read or is empty\n",
576  s->textfile);
577  return err;
578  }
579 
580  if (textbuf_size > SIZE_MAX - 1 || !(tmp = av_realloc(s->text, textbuf_size + 1))) {
581  av_file_unmap(textbuf, textbuf_size);
582  return AVERROR(ENOMEM);
583  }
584  s->text = tmp;
585  memcpy(s->text, textbuf, textbuf_size);
586  s->text[textbuf_size] = 0;
587  av_file_unmap(textbuf, textbuf_size);
588 
589  return 0;
590 }
591 
592 static inline int is_newline(uint32_t c)
593 {
594  return c == '\n' || c == '\r' || c == '\f' || c == '\v';
595 }
596 
597 #if CONFIG_LIBFRIBIDI
598 static int shape_text(AVFilterContext *ctx)
599 {
600  DrawTextContext *s = ctx->priv;
601  uint8_t *tmp;
602  int ret = AVERROR(ENOMEM);
603  static const FriBidiFlags flags = FRIBIDI_FLAGS_DEFAULT |
604  FRIBIDI_FLAGS_ARABIC;
605  FriBidiChar *unicodestr = NULL;
606  FriBidiStrIndex len;
607  FriBidiParType direction = FRIBIDI_PAR_LTR;
608  FriBidiStrIndex line_start = 0;
609  FriBidiStrIndex line_end = 0;
610  FriBidiLevel *embedding_levels = NULL;
611  FriBidiArabicProp *ar_props = NULL;
612  FriBidiCharType *bidi_types = NULL;
613  FriBidiStrIndex i,j;
614 
615  len = strlen(s->text);
616  if (!(unicodestr = av_malloc_array(len, sizeof(*unicodestr)))) {
617  goto out;
618  }
619  len = fribidi_charset_to_unicode(FRIBIDI_CHAR_SET_UTF8,
620  s->text, len, unicodestr);
621 
622  bidi_types = av_malloc_array(len, sizeof(*bidi_types));
623  if (!bidi_types) {
624  goto out;
625  }
626 
627  fribidi_get_bidi_types(unicodestr, len, bidi_types);
628 
629  embedding_levels = av_malloc_array(len, sizeof(*embedding_levels));
630  if (!embedding_levels) {
631  goto out;
632  }
633 
634  if (!fribidi_get_par_embedding_levels(bidi_types, len, &direction,
635  embedding_levels)) {
636  goto out;
637  }
638 
639  ar_props = av_malloc_array(len, sizeof(*ar_props));
640  if (!ar_props) {
641  goto out;
642  }
643 
644  fribidi_get_joining_types(unicodestr, len, ar_props);
645  fribidi_join_arabic(bidi_types, len, embedding_levels, ar_props);
646  fribidi_shape(flags, embedding_levels, len, ar_props, unicodestr);
647 
648  for (line_end = 0, line_start = 0; line_end < len; line_end++) {
649  if (is_newline(unicodestr[line_end]) || line_end == len - 1) {
650  if (!fribidi_reorder_line(flags, bidi_types,
651  line_end - line_start + 1, line_start,
652  direction, embedding_levels, unicodestr,
653  NULL)) {
654  goto out;
655  }
656  line_start = line_end + 1;
657  }
658  }
659 
660  /* Remove zero-width fill chars put in by libfribidi */
661  for (i = 0, j = 0; i < len; i++)
662  if (unicodestr[i] != FRIBIDI_CHAR_FILL)
663  unicodestr[j++] = unicodestr[i];
664  len = j;
665 
666  if (!(tmp = av_realloc(s->text, (len * 4 + 1) * sizeof(*s->text)))) {
667  /* Use len * 4, as a unicode character can be up to 4 bytes in UTF-8 */
668  goto out;
669  }
670 
671  s->text = tmp;
672  len = fribidi_unicode_to_charset(FRIBIDI_CHAR_SET_UTF8,
673  unicodestr, len, s->text);
674  ret = 0;
675 
676 out:
677  av_free(unicodestr);
678  av_free(embedding_levels);
679  av_free(ar_props);
680  av_free(bidi_types);
681  return ret;
682 }
683 #endif
684 
685 static av_cold int init(AVFilterContext *ctx)
686 {
687  int err;
688  DrawTextContext *s = ctx->priv;
689  Glyph *glyph;
690 
692  s->fontsize_pexpr = NULL;
693 
694  s->fontsize = 0;
695  s->default_fontsize = 16;
696 
697  if (!s->fontfile && !CONFIG_LIBFONTCONFIG) {
698  av_log(ctx, AV_LOG_ERROR, "No font filename provided\n");
699  return AVERROR(EINVAL);
700  }
701 
702  if (s->textfile) {
703  if (s->text) {
704  av_log(ctx, AV_LOG_ERROR,
705  "Both text and text file provided. Please provide only one\n");
706  return AVERROR(EINVAL);
707  }
708  if ((err = load_textfile(ctx)) < 0)
709  return err;
710  }
711 
712  if (s->reload && !s->textfile)
713  av_log(ctx, AV_LOG_WARNING, "No file to reload\n");
714 
715  if (s->tc_opt_string) {
717  s->tc_opt_string, ctx);
718  if (ret < 0)
719  return ret;
720  if (s->tc24hmax)
722  if (!s->text)
723  s->text = av_strdup("");
724  }
725 
726  if (!s->text) {
727  av_log(ctx, AV_LOG_ERROR,
728  "Either text, a valid file or a timecode must be provided\n");
729  return AVERROR(EINVAL);
730  }
731 
732 #if CONFIG_LIBFRIBIDI
733  if (s->text_shaping)
734  if ((err = shape_text(ctx)) < 0)
735  return err;
736 #endif
737 
738  if ((err = FT_Init_FreeType(&(s->library)))) {
739  av_log(ctx, AV_LOG_ERROR,
740  "Could not load FreeType: %s\n", FT_ERRMSG(err));
741  return AVERROR(EINVAL);
742  }
743 
744  if ((err = load_font(ctx)) < 0)
745  return err;
746 
747  if ((err = update_fontsize(ctx)) < 0)
748  return err;
749 
750  if (s->borderw) {
751  if (FT_Stroker_New(s->library, &s->stroker)) {
752  av_log(ctx, AV_LOG_ERROR, "Coult not init FT stroker\n");
753  return AVERROR_EXTERNAL;
754  }
755  FT_Stroker_Set(s->stroker, s->borderw << 6, FT_STROKER_LINECAP_ROUND,
756  FT_STROKER_LINEJOIN_ROUND, 0);
757  }
758 
759  s->use_kerning = FT_HAS_KERNING(s->face);
760 
761  /* load the fallback glyph with code 0 */
762  load_glyph(ctx, NULL, 0);
763 
764  /* set the tabsize in pixels */
765  if ((err = load_glyph(ctx, &glyph, ' ')) < 0) {
766  av_log(ctx, AV_LOG_ERROR, "Could not set tabsize.\n");
767  return err;
768  }
769  s->tabsize *= glyph->advance;
770 
771  if (s->exp_mode == EXP_STRFTIME &&
772  (strchr(s->text, '%') || strchr(s->text, '\\')))
773  av_log(ctx, AV_LOG_WARNING, "expansion=strftime is deprecated.\n");
774 
777 
778  return 0;
779 }
780 
782 {
784 }
785 
786 static int glyph_enu_free(void *opaque, void *elem)
787 {
788  Glyph *glyph = elem;
789 
790  FT_Done_Glyph(glyph->glyph);
791  FT_Done_Glyph(glyph->border_glyph);
792  av_free(elem);
793  return 0;
794 }
795 
796 static av_cold void uninit(AVFilterContext *ctx)
797 {
798  DrawTextContext *s = ctx->priv;
799 
800  av_expr_free(s->x_pexpr);
801  av_expr_free(s->y_pexpr);
802  av_expr_free(s->a_pexpr);
804 
805  s->x_pexpr = s->y_pexpr = s->a_pexpr = s->fontsize_pexpr = NULL;
806 
807  av_freep(&s->positions);
808  s->nb_positions = 0;
809 
812  s->glyphs = NULL;
813 
814  FT_Done_Face(s->face);
815  FT_Stroker_Done(s->stroker);
816  FT_Done_FreeType(s->library);
817 
820 }
821 
823 {
824  AVFilterContext *ctx = inlink->dst;
825  DrawTextContext *s = ctx->priv;
826  int ret;
827 
829  ff_draw_color(&s->dc, &s->fontcolor, s->fontcolor.rgba);
832  ff_draw_color(&s->dc, &s->boxcolor, s->boxcolor.rgba);
833 
834  s->var_values[VAR_w] = s->var_values[VAR_W] = s->var_values[VAR_MAIN_W] = inlink->w;
835  s->var_values[VAR_h] = s->var_values[VAR_H] = s->var_values[VAR_MAIN_H] = inlink->h;
837  s->var_values[VAR_DAR] = (double)inlink->w / inlink->h * s->var_values[VAR_SAR];
838  s->var_values[VAR_HSUB] = 1 << s->dc.hsub_max;
839  s->var_values[VAR_VSUB] = 1 << s->dc.vsub_max;
840  s->var_values[VAR_X] = NAN;
841  s->var_values[VAR_Y] = NAN;
842  s->var_values[VAR_T] = NAN;
843 
845 
846  av_expr_free(s->x_pexpr);
847  av_expr_free(s->y_pexpr);
848  av_expr_free(s->a_pexpr);
849  s->x_pexpr = s->y_pexpr = s->a_pexpr = NULL;
850 
851  if ((ret = av_expr_parse(&s->x_pexpr, s->x_expr, var_names,
852  NULL, NULL, fun2_names, fun2, 0, ctx)) < 0 ||
853  (ret = av_expr_parse(&s->y_pexpr, s->y_expr, var_names,
854  NULL, NULL, fun2_names, fun2, 0, ctx)) < 0 ||
855  (ret = av_expr_parse(&s->a_pexpr, s->a_expr, var_names,
856  NULL, NULL, fun2_names, fun2, 0, ctx)) < 0)
857 
858  return AVERROR(EINVAL);
859 
860  return 0;
861 }
862 
863 static int command(AVFilterContext *ctx, const char *cmd, const char *arg, char *res, int res_len, int flags)
864 {
865  DrawTextContext *old = ctx->priv;
866  DrawTextContext *new = NULL;
867  int ret;
868 
869  if (!strcmp(cmd, "reinit")) {
870  new = av_mallocz(sizeof(DrawTextContext));
871  if (!new)
872  return AVERROR(ENOMEM);
873 
874  new->class = &drawtext_class;
875  ret = av_opt_copy(new, old);
876  if (ret < 0)
877  goto fail;
878 
879  ctx->priv = new;
880  ret = av_set_options_string(ctx, arg, "=", ":");
881  if (ret < 0) {
882  ctx->priv = old;
883  goto fail;
884  }
885 
886  ret = init(ctx);
887  if (ret < 0) {
888  uninit(ctx);
889  ctx->priv = old;
890  goto fail;
891  }
892 
893  new->reinit = 1;
894 
895  ctx->priv = old;
896  uninit(ctx);
897  av_freep(&old);
898 
899  ctx->priv = new;
900  return config_input(ctx->inputs[0]);
901  } else
902  return AVERROR(ENOSYS);
903 
904 fail:
905  av_log(ctx, AV_LOG_ERROR, "Failed to process command. Continuing with existing parameters.\n");
906  av_freep(&new);
907  return ret;
908 }
909 
910 static int func_pict_type(AVFilterContext *ctx, AVBPrint *bp,
911  char *fct, unsigned argc, char **argv, int tag)
912 {
913  DrawTextContext *s = ctx->priv;
914 
916  return 0;
917 }
918 
919 static int func_pts(AVFilterContext *ctx, AVBPrint *bp,
920  char *fct, unsigned argc, char **argv, int tag)
921 {
922  DrawTextContext *s = ctx->priv;
923  const char *fmt;
924  double pts = s->var_values[VAR_T];
925  int ret;
926 
927  fmt = argc >= 1 ? argv[0] : "flt";
928  if (argc >= 2) {
929  int64_t delta;
930  if ((ret = av_parse_time(&delta, argv[1], 1)) < 0) {
931  av_log(ctx, AV_LOG_ERROR, "Invalid delta '%s'\n", argv[1]);
932  return ret;
933  }
934  pts += (double)delta / AV_TIME_BASE;
935  }
936  if (!strcmp(fmt, "flt")) {
937  av_bprintf(bp, "%.6f", pts);
938  } else if (!strcmp(fmt, "hms")) {
939  if (isnan(pts)) {
940  av_bprintf(bp, " ??:??:??.???");
941  } else {
942  int64_t ms = llrint(pts * 1000);
943  char sign = ' ';
944  if (ms < 0) {
945  sign = '-';
946  ms = -ms;
947  }
948  if (argc >= 3) {
949  if (!strcmp(argv[2], "24HH")) {
950  ms %= 24 * 60 * 60 * 1000;
951  } else {
952  av_log(ctx, AV_LOG_ERROR, "Invalid argument '%s'\n", argv[2]);
953  return AVERROR(EINVAL);
954  }
955  }
956  av_bprintf(bp, "%c%02d:%02d:%02d.%03d", sign,
957  (int)(ms / (60 * 60 * 1000)),
958  (int)(ms / (60 * 1000)) % 60,
959  (int)(ms / 1000) % 60,
960  (int)(ms % 1000));
961  }
962  } else if (!strcmp(fmt, "localtime") ||
963  !strcmp(fmt, "gmtime")) {
964  struct tm tm;
965  time_t ms = (time_t)pts;
966  const char *timefmt = argc >= 3 ? argv[2] : "%Y-%m-%d %H:%M:%S";
967  if (!strcmp(fmt, "localtime"))
968  localtime_r(&ms, &tm);
969  else
970  gmtime_r(&ms, &tm);
971  av_bprint_strftime(bp, timefmt, &tm);
972  } else {
973  av_log(ctx, AV_LOG_ERROR, "Invalid format '%s'\n", fmt);
974  return AVERROR(EINVAL);
975  }
976  return 0;
977 }
978 
979 static int func_frame_num(AVFilterContext *ctx, AVBPrint *bp,
980  char *fct, unsigned argc, char **argv, int tag)
981 {
982  DrawTextContext *s = ctx->priv;
983 
984  av_bprintf(bp, "%d", (int)s->var_values[VAR_N]);
985  return 0;
986 }
987 
988 static int func_metadata(AVFilterContext *ctx, AVBPrint *bp,
989  char *fct, unsigned argc, char **argv, int tag)
990 {
991  DrawTextContext *s = ctx->priv;
992  AVDictionaryEntry *e = av_dict_get(s->metadata, argv[0], NULL, 0);
993 
994  if (e && e->value)
995  av_bprintf(bp, "%s", e->value);
996  else if (argc >= 2)
997  av_bprintf(bp, "%s", argv[1]);
998  return 0;
999 }
1000 
1001 static int func_strftime(AVFilterContext *ctx, AVBPrint *bp,
1002  char *fct, unsigned argc, char **argv, int tag)
1003 {
1004  const char *fmt = argc ? argv[0] : "%Y-%m-%d %H:%M:%S";
1005  time_t now;
1006  struct tm tm;
1007 
1008  time(&now);
1009  if (tag == 'L')
1010  localtime_r(&now, &tm);
1011  else
1012  tm = *gmtime_r(&now, &tm);
1013  av_bprint_strftime(bp, fmt, &tm);
1014  return 0;
1015 }
1016 
1017 static int func_eval_expr(AVFilterContext *ctx, AVBPrint *bp,
1018  char *fct, unsigned argc, char **argv, int tag)
1019 {
1020  DrawTextContext *s = ctx->priv;
1021  double res;
1022  int ret;
1023 
1024  ret = av_expr_parse_and_eval(&res, argv[0], var_names, s->var_values,
1025  NULL, NULL, fun2_names, fun2,
1026  &s->prng, 0, ctx);
1027  if (ret < 0)
1028  av_log(ctx, AV_LOG_ERROR,
1029  "Expression '%s' for the expr text expansion function is not valid\n",
1030  argv[0]);
1031  else
1032  av_bprintf(bp, "%f", res);
1033 
1034  return ret;
1035 }
1036 
1037 static int func_eval_expr_int_format(AVFilterContext *ctx, AVBPrint *bp,
1038  char *fct, unsigned argc, char **argv, int tag)
1039 {
1040  DrawTextContext *s = ctx->priv;
1041  double res;
1042  int intval;
1043  int ret;
1044  unsigned int positions = 0;
1045  char fmt_str[30] = "%";
1046 
1047  /*
1048  * argv[0] expression to be converted to `int`
1049  * argv[1] format: 'x', 'X', 'd' or 'u'
1050  * argv[2] positions printed (optional)
1051  */
1052 
1053  ret = av_expr_parse_and_eval(&res, argv[0], var_names, s->var_values,
1054  NULL, NULL, fun2_names, fun2,
1055  &s->prng, 0, ctx);
1056  if (ret < 0) {
1057  av_log(ctx, AV_LOG_ERROR,
1058  "Expression '%s' for the expr text expansion function is not valid\n",
1059  argv[0]);
1060  return ret;
1061  }
1062 
1063  if (!strchr("xXdu", argv[1][0])) {
1064  av_log(ctx, AV_LOG_ERROR, "Invalid format '%c' specified,"
1065  " allowed values: 'x', 'X', 'd', 'u'\n", argv[1][0]);
1066  return AVERROR(EINVAL);
1067  }
1068 
1069  if (argc == 3) {
1070  ret = sscanf(argv[2], "%u", &positions);
1071  if (ret != 1) {
1072  av_log(ctx, AV_LOG_ERROR, "expr_int_format(): Invalid number of positions"
1073  " to print: '%s'\n", argv[2]);
1074  return AVERROR(EINVAL);
1075  }
1076  }
1077 
1078  feclearexcept(FE_ALL_EXCEPT);
1079  intval = res;
1080  if ((ret = fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW))) {
1081  av_log(ctx, AV_LOG_ERROR, "Conversion of floating-point result to int failed. Control register: 0x%08x. Conversion result: %d\n", ret, intval);
1082  return AVERROR(EINVAL);
1083  }
1084 
1085  if (argc == 3)
1086  av_strlcatf(fmt_str, sizeof(fmt_str), "0%u", positions);
1087  av_strlcatf(fmt_str, sizeof(fmt_str), "%c", argv[1][0]);
1088 
1089  av_log(ctx, AV_LOG_DEBUG, "Formatting value %f (expr '%s') with spec '%s'\n",
1090  res, argv[0], fmt_str);
1091 
1092  av_bprintf(bp, fmt_str, intval);
1093 
1094  return 0;
1095 }
1096 
1097 static const struct drawtext_function {
1098  const char *name;
1099  unsigned argc_min, argc_max;
1100  int tag; /**< opaque argument to func */
1101  int (*func)(AVFilterContext *, AVBPrint *, char *, unsigned, char **, int);
1102 } functions[] = {
1103  { "expr", 1, 1, 0, func_eval_expr },
1104  { "e", 1, 1, 0, func_eval_expr },
1105  { "expr_int_format", 2, 3, 0, func_eval_expr_int_format },
1106  { "eif", 2, 3, 0, func_eval_expr_int_format },
1107  { "pict_type", 0, 0, 0, func_pict_type },
1108  { "pts", 0, 3, 0, func_pts },
1109  { "gmtime", 0, 1, 'G', func_strftime },
1110  { "localtime", 0, 1, 'L', func_strftime },
1111  { "frame_num", 0, 0, 0, func_frame_num },
1112  { "n", 0, 0, 0, func_frame_num },
1113  { "metadata", 1, 2, 0, func_metadata },
1114 };
1115 
1116 static int eval_function(AVFilterContext *ctx, AVBPrint *bp, char *fct,
1117  unsigned argc, char **argv)
1118 {
1119  unsigned i;
1120 
1121  for (i = 0; i < FF_ARRAY_ELEMS(functions); i++) {
1122  if (strcmp(fct, functions[i].name))
1123  continue;
1124  if (argc < functions[i].argc_min) {
1125  av_log(ctx, AV_LOG_ERROR, "%%{%s} requires at least %d arguments\n",
1126  fct, functions[i].argc_min);
1127  return AVERROR(EINVAL);
1128  }
1129  if (argc > functions[i].argc_max) {
1130  av_log(ctx, AV_LOG_ERROR, "%%{%s} requires at most %d arguments\n",
1131  fct, functions[i].argc_max);
1132  return AVERROR(EINVAL);
1133  }
1134  break;
1135  }
1136  if (i >= FF_ARRAY_ELEMS(functions)) {
1137  av_log(ctx, AV_LOG_ERROR, "%%{%s} is not known\n", fct);
1138  return AVERROR(EINVAL);
1139  }
1140  return functions[i].func(ctx, bp, fct, argc, argv, functions[i].tag);
1141 }
1142 
1143 static int expand_function(AVFilterContext *ctx, AVBPrint *bp, char **rtext)
1144 {
1145  const char *text = *rtext;
1146  char *argv[16] = { NULL };
1147  unsigned argc = 0, i;
1148  int ret;
1149 
1150  if (*text != '{') {
1151  av_log(ctx, AV_LOG_ERROR, "Stray %% near '%s'\n", text);
1152  return AVERROR(EINVAL);
1153  }
1154  text++;
1155  while (1) {
1156  if (!(argv[argc++] = av_get_token(&text, ":}"))) {
1157  ret = AVERROR(ENOMEM);
1158  goto end;
1159  }
1160  if (!*text) {
1161  av_log(ctx, AV_LOG_ERROR, "Unterminated %%{} near '%s'\n", *rtext);
1162  ret = AVERROR(EINVAL);
1163  goto end;
1164  }
1165  if (argc == FF_ARRAY_ELEMS(argv))
1166  av_freep(&argv[--argc]); /* error will be caught later */
1167  if (*text == '}')
1168  break;
1169  text++;
1170  }
1171 
1172  if ((ret = eval_function(ctx, bp, argv[0], argc - 1, argv + 1)) < 0)
1173  goto end;
1174  ret = 0;
1175  *rtext = (char *)text + 1;
1176 
1177 end:
1178  for (i = 0; i < argc; i++)
1179  av_freep(&argv[i]);
1180  return ret;
1181 }
1182 
1183 static int expand_text(AVFilterContext *ctx, char *text, AVBPrint *bp)
1184 {
1185  int ret;
1186 
1187  av_bprint_clear(bp);
1188  while (*text) {
1189  if (*text == '\\' && text[1]) {
1190  av_bprint_chars(bp, text[1], 1);
1191  text += 2;
1192  } else if (*text == '%') {
1193  text++;
1194  if ((ret = expand_function(ctx, bp, &text)) < 0)
1195  return ret;
1196  } else {
1197  av_bprint_chars(bp, *text, 1);
1198  text++;
1199  }
1200  }
1201  if (!av_bprint_is_complete(bp))
1202  return AVERROR(ENOMEM);
1203  return 0;
1204 }
1205 
1207  int width, int height,
1208  FFDrawColor *color,
1209  int x, int y, int borderw)
1210 {
1211  char *text = s->expanded_text.str;
1212  uint32_t code = 0;
1213  int i, x1, y1;
1214  uint8_t *p;
1215  Glyph *glyph = NULL;
1216 
1217  for (i = 0, p = text; *p; i++) {
1218  FT_Bitmap bitmap;
1219  Glyph dummy = { 0 };
1220  GET_UTF8(code, *p++, continue;);
1221 
1222  /* skip new line chars, just go to new line */
1223  if (code == '\n' || code == '\r' || code == '\t')
1224  continue;
1225 
1226  dummy.code = code;
1227  dummy.fontsize = s->fontsize;
1228  glyph = av_tree_find(s->glyphs, &dummy, glyph_cmp, NULL);
1229 
1230  bitmap = borderw ? glyph->border_bitmap : glyph->bitmap;
1231 
1232  if (glyph->bitmap.pixel_mode != FT_PIXEL_MODE_MONO &&
1233  glyph->bitmap.pixel_mode != FT_PIXEL_MODE_GRAY)
1234  return AVERROR(EINVAL);
1235 
1236  x1 = s->positions[i].x+s->x+x - borderw;
1237  y1 = s->positions[i].y+s->y+y - borderw;
1238 
1239  ff_blend_mask(&s->dc, color,
1240  frame->data, frame->linesize, width, height,
1241  bitmap.buffer, bitmap.pitch,
1242  bitmap.width, bitmap.rows,
1243  bitmap.pixel_mode == FT_PIXEL_MODE_MONO ? 0 : 3,
1244  0, x1, y1);
1245  }
1246 
1247  return 0;
1248 }
1249 
1250 
1252 {
1253  *color = incolor;
1254  color->rgba[3] = (color->rgba[3] * s->alpha) / 255;
1255  ff_draw_color(&s->dc, color, color->rgba);
1256 }
1257 
1259 {
1260  double alpha = av_expr_eval(s->a_pexpr, s->var_values, &s->prng);
1261 
1262  if (isnan(alpha))
1263  return;
1264 
1265  if (alpha >= 1.0)
1266  s->alpha = 255;
1267  else if (alpha <= 0)
1268  s->alpha = 0;
1269  else
1270  s->alpha = 256 * alpha;
1271 }
1272 
1274  int width, int height)
1275 {
1276  DrawTextContext *s = ctx->priv;
1277  AVFilterLink *inlink = ctx->inputs[0];
1278 
1279  uint32_t code = 0, prev_code = 0;
1280  int x = 0, y = 0, i = 0, ret;
1281  int max_text_line_w = 0, len;
1282  int box_w, box_h;
1283  char *text;
1284  uint8_t *p;
1285  int y_min = 32000, y_max = -32000;
1286  int x_min = 32000, x_max = -32000;
1287  FT_Vector delta;
1288  Glyph *glyph = NULL, *prev_glyph = NULL;
1289  Glyph dummy = { 0 };
1290 
1291  time_t now = time(0);
1292  struct tm ltime;
1293  AVBPrint *bp = &s->expanded_text;
1294 
1299 
1300  av_bprint_clear(bp);
1301 
1302  if(s->basetime != AV_NOPTS_VALUE)
1303  now= frame->pts*av_q2d(ctx->inputs[0]->time_base) + s->basetime/1000000;
1304 
1305  switch (s->exp_mode) {
1306  case EXP_NONE:
1307  av_bprintf(bp, "%s", s->text);
1308  break;
1309  case EXP_NORMAL:
1310  if ((ret = expand_text(ctx, s->text, &s->expanded_text)) < 0)
1311  return ret;
1312  break;
1313  case EXP_STRFTIME:
1314  localtime_r(&now, &ltime);
1315  av_bprint_strftime(bp, s->text, &ltime);
1316  break;
1317  }
1318 
1319  if (s->tc_opt_string) {
1320  char tcbuf[AV_TIMECODE_STR_SIZE];
1321  av_timecode_make_string(&s->tc, tcbuf, inlink->frame_count_out);
1322  av_bprint_clear(bp);
1323  av_bprintf(bp, "%s%s", s->text, tcbuf);
1324  }
1325 
1326  if (!av_bprint_is_complete(bp))
1327  return AVERROR(ENOMEM);
1328  text = s->expanded_text.str;
1329  if ((len = s->expanded_text.len) > s->nb_positions) {
1330  if (!(s->positions =
1331  av_realloc(s->positions, len*sizeof(*s->positions))))
1332  return AVERROR(ENOMEM);
1333  s->nb_positions = len;
1334  }
1335 
1336  if (s->fontcolor_expr[0]) {
1337  /* If expression is set, evaluate and replace the static value */
1339  if ((ret = expand_text(ctx, s->fontcolor_expr, &s->expanded_fontcolor)) < 0)
1340  return ret;
1342  return AVERROR(ENOMEM);
1343  av_log(s, AV_LOG_DEBUG, "Evaluated fontcolor is '%s'\n", s->expanded_fontcolor.str);
1344  ret = av_parse_color(s->fontcolor.rgba, s->expanded_fontcolor.str, -1, s);
1345  if (ret)
1346  return ret;
1347  ff_draw_color(&s->dc, &s->fontcolor, s->fontcolor.rgba);
1348  }
1349 
1350  x = 0;
1351  y = 0;
1352 
1353  if ((ret = update_fontsize(ctx)) < 0)
1354  return ret;
1355 
1356  /* load and cache glyphs */
1357  for (i = 0, p = text; *p; i++) {
1358  GET_UTF8(code, *p++, continue;);
1359 
1360  /* get glyph */
1361  dummy.code = code;
1362  dummy.fontsize = s->fontsize;
1363  glyph = av_tree_find(s->glyphs, &dummy, glyph_cmp, NULL);
1364  if (!glyph) {
1365  ret = load_glyph(ctx, &glyph, code);
1366  if (ret < 0)
1367  return ret;
1368  }
1369 
1370  y_min = FFMIN(glyph->bbox.yMin, y_min);
1371  y_max = FFMAX(glyph->bbox.yMax, y_max);
1372  x_min = FFMIN(glyph->bbox.xMin, x_min);
1373  x_max = FFMAX(glyph->bbox.xMax, x_max);
1374  }
1375  s->max_glyph_h = y_max - y_min;
1376  s->max_glyph_w = x_max - x_min;
1377 
1378  /* compute and save position for each glyph */
1379  glyph = NULL;
1380  for (i = 0, p = text; *p; i++) {
1381  GET_UTF8(code, *p++, continue;);
1382 
1383  /* skip the \n in the sequence \r\n */
1384  if (prev_code == '\r' && code == '\n')
1385  continue;
1386 
1387  prev_code = code;
1388  if (is_newline(code)) {
1389 
1390  max_text_line_w = FFMAX(max_text_line_w, x);
1391  y += s->max_glyph_h + s->line_spacing;
1392  x = 0;
1393  continue;
1394  }
1395 
1396  /* get glyph */
1397  prev_glyph = glyph;
1398  dummy.code = code;
1399  dummy.fontsize = s->fontsize;
1400  glyph = av_tree_find(s->glyphs, &dummy, glyph_cmp, NULL);
1401 
1402  /* kerning */
1403  if (s->use_kerning && prev_glyph && glyph->code) {
1404  FT_Get_Kerning(s->face, prev_glyph->code, glyph->code,
1405  ft_kerning_default, &delta);
1406  x += delta.x >> 6;
1407  }
1408 
1409  /* save position */
1410  s->positions[i].x = x + glyph->bitmap_left;
1411  s->positions[i].y = y - glyph->bitmap_top + y_max;
1412  if (code == '\t') x = (x / s->tabsize + 1)*s->tabsize;
1413  else x += glyph->advance;
1414  }
1415 
1416  max_text_line_w = FFMAX(x, max_text_line_w);
1417 
1418  s->var_values[VAR_TW] = s->var_values[VAR_TEXT_W] = max_text_line_w;
1420 
1423  s->var_values[VAR_MAX_GLYPH_A] = s->var_values[VAR_ASCENT ] = y_max;
1425 
1427 
1428  s->x = s->var_values[VAR_X] = av_expr_eval(s->x_pexpr, s->var_values, &s->prng);
1429  s->y = s->var_values[VAR_Y] = av_expr_eval(s->y_pexpr, s->var_values, &s->prng);
1430  /* It is necessary if x is expressed from y */
1431  s->x = s->var_values[VAR_X] = av_expr_eval(s->x_pexpr, s->var_values, &s->prng);
1432 
1433  update_alpha(s);
1434  update_color_with_alpha(s, &fontcolor , s->fontcolor );
1435  update_color_with_alpha(s, &shadowcolor, s->shadowcolor);
1436  update_color_with_alpha(s, &bordercolor, s->bordercolor);
1437  update_color_with_alpha(s, &boxcolor , s->boxcolor );
1438 
1439  box_w = max_text_line_w;
1440  box_h = y + s->max_glyph_h;
1441 
1442  if (s->fix_bounds) {
1443 
1444  /* calculate footprint of text effects */
1445  int boxoffset = s->draw_box ? FFMAX(s->boxborderw, 0) : 0;
1446  int borderoffset = s->borderw ? FFMAX(s->borderw, 0) : 0;
1447 
1448  int offsetleft = FFMAX3(boxoffset, borderoffset,
1449  (s->shadowx < 0 ? FFABS(s->shadowx) : 0));
1450  int offsettop = FFMAX3(boxoffset, borderoffset,
1451  (s->shadowy < 0 ? FFABS(s->shadowy) : 0));
1452 
1453  int offsetright = FFMAX3(boxoffset, borderoffset,
1454  (s->shadowx > 0 ? s->shadowx : 0));
1455  int offsetbottom = FFMAX3(boxoffset, borderoffset,
1456  (s->shadowy > 0 ? s->shadowy : 0));
1457 
1458 
1459  if (s->x - offsetleft < 0) s->x = offsetleft;
1460  if (s->y - offsettop < 0) s->y = offsettop;
1461 
1462  if (s->x + box_w + offsetright > width)
1463  s->x = FFMAX(width - box_w - offsetright, 0);
1464  if (s->y + box_h + offsetbottom > height)
1465  s->y = FFMAX(height - box_h - offsetbottom, 0);
1466  }
1467 
1468  /* draw box */
1469  if (s->draw_box)
1470  ff_blend_rectangle(&s->dc, &boxcolor,
1471  frame->data, frame->linesize, width, height,
1472  s->x - s->boxborderw, s->y - s->boxborderw,
1473  box_w + s->boxborderw * 2, box_h + s->boxborderw * 2);
1474 
1475  if (s->shadowx || s->shadowy) {
1476  if ((ret = draw_glyphs(s, frame, width, height,
1477  &shadowcolor, s->shadowx, s->shadowy, 0)) < 0)
1478  return ret;
1479  }
1480 
1481  if (s->borderw) {
1482  if ((ret = draw_glyphs(s, frame, width, height,
1483  &bordercolor, 0, 0, s->borderw)) < 0)
1484  return ret;
1485  }
1486  if ((ret = draw_glyphs(s, frame, width, height,
1487  &fontcolor, 0, 0, 0)) < 0)
1488  return ret;
1489 
1490  return 0;
1491 }
1492 
1494 {
1495  AVFilterContext *ctx = inlink->dst;
1496  AVFilterLink *outlink = ctx->outputs[0];
1497  DrawTextContext *s = ctx->priv;
1498  int ret;
1499 
1500  if (s->reload) {
1501  if ((ret = load_textfile(ctx)) < 0) {
1502  av_frame_free(&frame);
1503  return ret;
1504  }
1505 #if CONFIG_LIBFRIBIDI
1506  if (s->text_shaping)
1507  if ((ret = shape_text(ctx)) < 0) {
1508  av_frame_free(&frame);
1509  return ret;
1510  }
1511 #endif
1512  }
1513 
1514  s->var_values[VAR_N] = inlink->frame_count_out + s->start_number;
1515  s->var_values[VAR_T] = frame->pts == AV_NOPTS_VALUE ?
1516  NAN : frame->pts * av_q2d(inlink->time_base);
1517 
1518  s->var_values[VAR_PICT_TYPE] = frame->pict_type;
1519  s->metadata = frame->metadata;
1520 
1521  draw_text(ctx, frame, frame->width, frame->height);
1522 
1523  av_log(ctx, AV_LOG_DEBUG, "n:%d t:%f text_w:%d text_h:%d x:%d y:%d\n",
1524  (int)s->var_values[VAR_N], s->var_values[VAR_T],
1525  (int)s->var_values[VAR_TEXT_W], (int)s->var_values[VAR_TEXT_H],
1526  s->x, s->y);
1527 
1528  return ff_filter_frame(outlink, frame);
1529 }
1530 
1532  {
1533  .name = "default",
1534  .type = AVMEDIA_TYPE_VIDEO,
1535  .filter_frame = filter_frame,
1536  .config_props = config_input,
1537  .needs_writable = 1,
1538  },
1539  { NULL }
1540 };
1541 
1543  {
1544  .name = "default",
1545  .type = AVMEDIA_TYPE_VIDEO,
1546  },
1547  { NULL }
1548 };
1549 
1551  .name = "drawtext",
1552  .description = NULL_IF_CONFIG_SMALL("Draw text on top of video frames using libfreetype library."),
1553  .priv_size = sizeof(DrawTextContext),
1554  .priv_class = &drawtext_class,
1555  .init = init,
1556  .uninit = uninit,
1558  .inputs = avfilter_vf_drawtext_inputs,
1559  .outputs = avfilter_vf_drawtext_outputs,
1562 };
Definition: lfg.h:27
AVFilterFormats * ff_draw_supported_pixel_formats(unsigned flags)
Return the list of pixel formats supported by the draw functions.
Definition: drawutils.c:731
#define NULL
Definition: coverity.c:32
static int func_frame_num(AVFilterContext *ctx, AVBPrint *bp, char *fct, unsigned argc, char **argv, int tag)
Definition: vf_drawtext.c:979
char * y_expr
expression for y position
Definition: vf_drawtext.c:182
void av_bprintf(AVBPrint *buf, const char *fmt,...)
Definition: bprint.c:94
#define GET_UTF8(val, GET_BYTE, ERROR)
Convert a UTF-8 character (up to 4 bytes) to its 32-bit UCS-4 encoded form.
Definition: common.h:385
int tc24hmax
1 if timecode is wrapped to 24 hours, 0 otherwise
Definition: vf_drawtext.c:193
This structure describes decoded (raw) audio or video data.
Definition: frame.h:268
uint8_t * fontcolor_expr
fontcolor expression to evaluate
Definition: vf_drawtext.c:147
AVOption.
Definition: opt.h:246
void * av_realloc(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory.
Definition: mem.c:135
int x
x position to start drawing text
Definition: vf_drawtext.c:153
static double drand(void *opaque, double min, double max)
Definition: vf_drawtext.c:98
static int func_metadata(AVFilterContext *ctx, AVBPrint *bp, char *fct, unsigned argc, char **argv, int tag)
Definition: vf_drawtext.c:988
static const AVOption drawtext_options[]
Definition: vf_drawtext.c:205
const char * fmt
Definition: avisynth_c.h:861
unsigned int fontsize
font size to use
Definition: vf_drawtext.c:161
FFDrawColor boxcolor
background color
Definition: vf_drawtext.c:175
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
static av_cold int parse_fontsize(AVFilterContext *ctx)
Definition: vf_drawtext.c:394
char * x_expr
expression for x position
Definition: vf_drawtext.c:181
Main libavfilter public API header.
uint8_t * fontfile
font to be used
Definition: vf_drawtext.c:144
int av_parse_time(int64_t *timeval, const char *timestr, int duration)
Parse timestr and return in *time a corresponding number of microseconds.
Definition: parseutils.c:587
#define FLAGS
Definition: vf_drawtext.c:203
int num
Numerator.
Definition: rational.h:59
static const struct drawtext_function functions[]
int av_set_options_string(void *ctx, const char *opts, const char *key_val_sep, const char *pairs_sep)
Parse the key/value pairs list in opts.
Definition: opt.c:1426
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
Definition: undefined.txt:36
static int draw_text(AVFilterContext *ctx, AVFrame *frame, int width, int height)
Definition: vf_drawtext.c:1273
uint8_t * text
text to be drawn
Definition: vf_drawtext.c:145
void * av_tree_find(const AVTreeNode *t, void *key, int(*cmp)(const void *key, const void *b), void *next[2])
Definition: tree.c:39
const char * key
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:236
int av_expr_parse(AVExpr **expr, const char *s, const char *const *const_names, const char *const *func1_names, double(*const *funcs1)(void *, double), const char *const *func2_names, double(*const *funcs2)(void *, double, double), int log_offset, void *log_ctx)
Parse an expression.
Definition: eval.c:679
char * tc_opt_string
specified timecode option string
Definition: vf_drawtext.c:190
static int draw_glyphs(DrawTextContext *s, AVFrame *frame, int width, int height, FFDrawColor *color, int x, int y, int borderw)
Definition: vf_drawtext.c:1206
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition: bprint.c:235
int boxborderw
box border width
Definition: vf_drawtext.c:166
#define AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC
Some filters support a generic "enable" expression option that can be used to enable or disable a fil...
Definition: avfilter.h:125
struct AVTreeNode * av_tree_node_alloc(void)
Allocate an AVTreeNode.
Definition: tree.c:34
#define gmtime_r
Definition: time_internal.h:34
expansion_mode
Definition: vf_drawtext.c:131
const char * name
Pad name.
Definition: internal.h:60
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:346
int av_timecode_init_from_string(AVTimecode *tc, AVRational rate, const char *str, void *log_ctx)
Parse timecode representation (hh:mm:ss[:;.
Definition: timecode.c:194
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1080
FT_Stroker stroker
freetype stroker handle
Definition: vf_drawtext.c:179
static int glyph_enu_free(void *opaque, void *elem)
Definition: vf_drawtext.c:786
uint8_t
#define av_cold
Definition: attributes.h:82
static int func_pict_type(AVFilterContext *ctx, AVBPrint *bp, char *fct, unsigned argc, char **argv, int tag)
Definition: vf_drawtext.c:910
AVExpr * fontsize_pexpr
parsed expressions for fontsize
Definition: vf_drawtext.c:160
float delta
AVOptions.
A tree container.
AVLFG prng
random
Definition: vf_drawtext.c:189
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:90
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
FT_Face face
freetype font face handle
Definition: vf_drawtext.c:178
static int glyph_cmp(const void *key, const void *b)
Definition: vf_drawtext.c:296
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:361
static av_cold int init(AVFilterContext *ctx)
Definition: vf_drawtext.c:685
Definition: eval.c:157
int start_number
starting frame number for n/frame_num var
Definition: vf_drawtext.c:195
static int load_font_file(AVFilterContext *ctx, const char *path, int index)
Definition: vf_drawtext.c:448
Misc file utilities.
#define height
static const AVFilterPad avfilter_vf_drawtext_inputs[]
Definition: vf_drawtext.c:1531
AVDictionaryEntry * av_dict_get(const AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags)
Get a dictionary entry with matching key.
Definition: dict.c:40
static double av_q2d(AVRational a)
Convert an AVRational to a double.
Definition: rational.h:104
uint32_t tag
Definition: movenc.c:1496
char av_get_picture_type_char(enum AVPictureType pict_type)
Return a single letter to describe the given picture type pict_type.
Definition: utils.c:88
const char * name
Definition: vf_drawtext.c:1098
AVDictionary * metadata
metadata.
Definition: frame.h:554
static av_cold void uninit(AVFilterContext *ctx)
Definition: vf_drawtext.c:796
ptrdiff_t size
Definition: opengl_enc.c:100
FT_Vector * positions
positions for each element in the text
Definition: vf_drawtext.c:150
AVExpr * x_pexpr
Definition: vf_drawtext.c:183
#define av_log(a,...)
void av_tree_destroy(AVTreeNode *t)
Definition: tree.c:146
int av_parse_color(uint8_t *rgba_color, const char *color_string, int slen, void *log_ctx)
Put the RGBA values that correspond to color_string in rgba_color.
Definition: parseutils.c:354
A filter pad used for either input or output.
Definition: internal.h:54
int av_expr_parse_and_eval(double *d, const char *s, const char *const *const_names, const double *const_values, const char *const *func1_names, double(*const *funcs1)(void *, double), const char *const *func2_names, double(*const *funcs2)(void *, double, double), void *opaque, int log_offset, void *log_ctx)
Parse and evaluate an expression.
Definition: eval.c:744
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:260
double var_values[VAR_VARS_NB]
Definition: vf_drawtext.c:185
int width
Definition: frame.h:326
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
void av_file_unmap(uint8_t *bufptr, size_t size)
Unmap or free the buffer bufptr created by av_file_map().
Definition: file.c:139
int ff_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats)
A helper for query_formats() which sets all links to the same list of formats.
Definition: formats.c:568
AVBPrint expanded_text
used to contain the expanded text
Definition: vf_drawtext.c:146
int av_file_map(const char *filename, uint8_t **bufptr, size_t *size, int log_offset, void *log_ctx)
Read the file with name filename, and put its content in a newly allocated buffer or map it with mmap...
Definition: file.c:53
#define AV_BPRINT_SIZE_UNLIMITED
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:202
AVExpr * y_pexpr
parsed expressions for x and y
Definition: vf_drawtext.c:183
const char * err_msg
Definition: vf_drawtext.c:277
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:186
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition: bprint.c:69
void * priv
private data for use by the filter
Definition: avfilter.h:353
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:197
int y
y position to start drawing text
Definition: vf_drawtext.c:154
const char * arg
Definition: jacosubdec.c:66
void ff_draw_color(FFDrawContext *draw, FFDrawColor *color, const uint8_t rgba[4])
Prepare a color.
Definition: drawutils.c:231
static int expand_function(AVFilterContext *ctx, AVBPrint *bp, char **rtext)
Definition: vf_drawtext.c:1143
uint8_t vsub_max
Definition: drawutils.h:57
static av_always_inline av_const double round(double x)
Definition: libm.h:444
FFDrawColor fontcolor
foreground color
Definition: vf_drawtext.c:172
AVExpr * a_pexpr
Definition: vf_drawtext.c:187
#define FFMAX(a, b)
Definition: common.h:94
#define fail()
Definition: checkasm.h:120
char * av_get_token(const char **buf, const char *term)
Unescape the given string until a non escaped terminating char, and return the token corresponding to...
Definition: avstring.c:149
static const char *const fun2_names[]
Definition: vf_drawtext.c:94
int reload
reload text file for each frame
Definition: vf_drawtext.c:194
AVBPrint expanded_fontcolor
used to contain the expanded fontcolor spec
Definition: vf_drawtext.c:148
var_name
Definition: aeval.c:46
FFDrawContext dc
Definition: vf_drawtext.c:171
#define FFDIFFSIGN(x, y)
Comparator.
Definition: common.h:92
static const struct ft_error ft_errors[]
#define b
Definition: input.c:41
enum AVPictureType pict_type
Picture type of the frame.
Definition: frame.h:351
#define NAN
Definition: mathematics.h:64
#define FF_DRAW_PROCESS_ALPHA
Process alpha pixel component.
Definition: drawutils.h:74
#define AV_TIME_BASE
Internal time base represented as integer.
Definition: avutil.h:254
#define FFMIN(a, b)
Definition: common.h:96
#define width
int64_t basetime
base pts time in the real world for display
Definition: vf_drawtext.c:184
char * fontsize_expr
expression for fontsize
Definition: vf_drawtext.c:159
AVFormatContext * ctx
Definition: movenc.c:48
int max_glyph_h
max glyph height
Definition: vf_drawtext.c:156
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
AVRational tc_rate
frame rate for timecode
Definition: vf_drawtext.c:191
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
Definition: common.h:72
#define s(width, name)
Definition: cbs_vp9.c:257
static int av_bprint_is_complete(const AVBPrint *buf)
Test if the print buffer is complete (not truncated).
Definition: bprint.h:185
int dummy
Definition: motion.c:64
static int func_eval_expr(AVFilterContext *ctx, AVBPrint *bp, char *fct, unsigned argc, char **argv, int tag)
Definition: vf_drawtext.c:1017
static void error(const char *err)
static const AVFilterPad outputs[]
Definition: af_acontrast.c:203
#define FF_ARRAY_ELEMS(a)
AVTimecode tc
timecode context
Definition: vf_drawtext.c:192
static void update_color_with_alpha(DrawTextContext *s, FFDrawColor *color, const FFDrawColor incolor)
Definition: vf_drawtext.c:1251
void ff_blend_mask(FFDrawContext *draw, FFDrawColor *color, uint8_t *dst[], int dst_linesize[], int dst_w, int dst_h, const uint8_t *mask, int mask_linesize, int mask_w, int mask_h, int l2depth, unsigned endianness, int x0, int y0)
Blend an alpha mask with an uniform color.
Definition: drawutils.c:622
#define AV_LOG_INFO
Standard information.
Definition: log.h:187
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:251
misc drawing utilities
void av_expr_free(AVExpr *e)
Free a parsed expression previously created with av_expr_parse().
Definition: eval.c:334
Timecode helpers header.
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:299
static int load_font(AVFilterContext *ctx)
Definition: vf_drawtext.c:548
static int command(AVFilterContext *ctx, const char *cmd, const char *arg, char *res, int res_len, int flags)
Definition: vf_drawtext.c:863
timecode wraps after 24 hours
Definition: timecode.h:37
int borderw
border width
Definition: vf_drawtext.c:158
static unsigned int av_lfg_get(AVLFG *c)
Get the next random unsigned 32-bit number using an ALFG.
Definition: lfg.h:47
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several inputs
#define llrint(x)
Definition: libm.h:394
uint8_t hsub_max
Definition: drawutils.h:56
int(* func)(AVBPrint *dst, const char *in, const char *arg)
Definition: jacosubdec.c:67
Describe the class of an AVClass context structure.
Definition: log.h:67
Filter definition.
Definition: avfilter.h:144
int tabsize
tab size
Definition: vf_drawtext.c:168
int index
Definition: gxfenc.c:89
static int func_strftime(AVFilterContext *ctx, AVBPrint *bp, char *fct, unsigned argc, char **argv, int tag)
Definition: vf_drawtext.c:1001
Rational number (pair of numerator and denominator).
Definition: rational.h:58
void ff_blend_rectangle(FFDrawContext *draw, FFDrawColor *color, uint8_t *dst[], int dst_linesize[], int dst_w, int dst_h, int x0, int y0, int w, int h)
Blend a rectangle with an uniform color.
Definition: drawutils.c:445
#define isnan(x)
Definition: libm.h:340
struct AVTreeNode * glyphs
rendered glyphs, stored using the UTF-32 char code
Definition: vf_drawtext.c:180
size_t av_strlcatf(char *dst, size_t size, const char *fmt,...)
Definition: avstring.c:101
static int is_newline(uint32_t c)
Definition: vf_drawtext.c:592
const char * name
Filter name.
Definition: avfilter.h:148
av_cold void av_lfg_init(AVLFG *c, unsigned int seed)
Definition: lfg.c:32
int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags)
Init a draw context.
Definition: drawutils.c:178
static int expand_text(AVFilterContext *ctx, char *text, AVBPrint *bp)
Definition: vf_drawtext.c:1183
misc parsing utilities
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:350
int tag
opaque argument to func
Definition: vf_drawtext.c:1100
short int draw_box
draw box around text - true or false
Definition: vf_drawtext.c:165
static int config_input(AVFilterLink *inlink)
Definition: vf_drawtext.c:822
static int64_t pts
#define flags(name, subs,...)
Definition: cbs_av1.c:561
and forward the test the status of outputs and forward it to the corresponding return FFERROR_NOT_READY If the filters stores internally one or a few frame for some it can consider them to be part of the FIFO and delay acknowledging a status change accordingly Example code
static void drawtext(AVFrame *pic, int x, int y, const char *txt, uint32_t color)
Definition: af_afir.c:192
AVDictionary * metadata
Definition: vf_drawtext.c:199
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:282
void av_bprint_strftime(AVBPrint *buf, const char *fmt, const struct tm *tm)
Append a formatted date and time to a print buffer.
Definition: bprint.c:176
char * av_timecode_make_string(const AVTimecode *tc, char *buf, int framenum)
Load timecode string in buf.
Definition: timecode.c:84
AVFILTER_DEFINE_CLASS(drawtext)
The exact code depends on how similar the blocks are and how related they are to the and needs to apply these operations to the correct inlink or outlink if there are several Macros are available to factor that when no extra processing is inlink
void av_bprint_clear(AVBPrint *buf)
Reset the string to "" but keep internal allocated data.
Definition: bprint.c:227
static void update_alpha(DrawTextContext *s)
Definition: vf_drawtext.c:1258
int(* func)(AVFilterContext *, AVBPrint *, char *, unsigned, char **, int)
Definition: vf_drawtext.c:1101
static const char *const var_names[]
Definition: vf_drawtext.c:73
int use_kerning
font kerning is used - true/false
Definition: vf_drawtext.c:167
int
common internal and external API header
int av_opt_copy(void *dst, const void *src)
Copy options from src object into dest object.
Definition: opt.c:1716
static int query_formats(AVFilterContext *ctx)
Definition: vf_drawtext.c:781
FT_Library library
freetype font library handle
Definition: vf_drawtext.c:177
#define localtime_r
Definition: time_internal.h:46
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition: error.h:71
double(* eval_func2)(void *, double a, double b)
Definition: vf_drawtext.c:103
static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
Definition: vf_drawtext.c:1493
static const AVFilterPad avfilter_vf_drawtext_outputs[]
Definition: vf_drawtext.c:1542
AVFilter ff_vf_drawtext
Definition: vf_drawtext.c:1550
static av_always_inline int diff(const uint32_t a, const uint32_t b)
#define av_free(p)
char * value
Definition: dict.h:87
int len
double av_expr_eval(AVExpr *e, const double *const_values, void *opaque)
Evaluate a previously parsed expression.
Definition: eval.c:734
#define FT_ERRMSG(e)
int reinit
tells if the filter is being reinited
Definition: vf_drawtext.c:140
FFDrawColor shadowcolor
shadow color
Definition: vf_drawtext.c:173
static av_cold int update_fontsize(AVFilterContext *ctx)
Definition: vf_drawtext.c:412
#define OFFSET(x)
Definition: vf_drawtext.c:202
void * av_tree_insert(AVTreeNode **tp, void *key, int(*cmp)(const void *key, const void *b), AVTreeNode **next)
Insert or remove an element.
Definition: tree.c:59
int line_spacing
lines spacing in pixels
Definition: vf_drawtext.c:164
An instance of a filter.
Definition: avfilter.h:338
int max_glyph_w
max glyph width
Definition: vf_drawtext.c:155
static const eval_func2 fun2[]
Definition: vf_drawtext.c:105
and forward the result(frame or status change) to the corresponding input.If nothing is possible
int height
Definition: frame.h:326
static int func_pts(AVFilterContext *ctx, AVBPrint *bp, char *fct, unsigned argc, char **argv, int tag)
Definition: vf_drawtext.c:919
FILE * out
Definition: movenc.c:54
unsigned int default_fontsize
default font size to use
Definition: vf_drawtext.c:162
static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, char *res, int res_len, int flags)
Definition: af_afftdn.c:1373
#define av_freep(p)
int fix_bounds
do we let it go out of frame bounds - t/f
Definition: vf_drawtext.c:169
uint32_t av_get_random_seed(void)
Get a seed to use in conjunction with random functions.
Definition: random_seed.c:120
#define av_malloc_array(a, b)
char * textfile
file with text to be drawn
Definition: vf_drawtext.c:152
internal API functions
static int load_glyph(AVFilterContext *ctx, Glyph **glyph_ptr, uint32_t code)
Load glyphs corresponding to the UTF-32 codepoint code.
Definition: vf_drawtext.c:310
static int load_textfile(AVFilterContext *ctx)
Definition: vf_drawtext.c:565
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Frame references ownership and permissions
static int eval_function(AVFilterContext *ctx, AVBPrint *bp, char *fct, unsigned argc, char **argv)
Definition: vf_drawtext.c:1116
int ft_load_flags
flags used for loading fonts, see FT_LOAD_*
Definition: vf_drawtext.c:149
int exp_mode
expansion mode to use for the text
Definition: vf_drawtext.c:139
uint32_t flags
flags such as drop frame, +24 hours support, ...
Definition: timecode.h:43
void av_tree_enumerate(AVTreeNode *t, void *opaque, int(*cmp)(void *opaque, void *elem), int(*enu)(void *opaque, void *elem))
Apply enu(opaque, &elem) to all the elements in the tree in a given range.
Definition: tree.c:155
float min
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition: error.h:57
size_t nb_positions
number of elements of positions array
Definition: vf_drawtext.c:151
FFDrawColor bordercolor
border color
Definition: vf_drawtext.c:174
#define FFMAX3(a, b, c)
Definition: common.h:95
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:248
static av_cold int set_fontsize(AVFilterContext *ctx, unsigned int fontsize)
Definition: vf_drawtext.c:378
void * elem
Definition: tree.c:28
#define AV_TIMECODE_STR_SIZE
Definition: timecode.h:33
simple arithmetic expression evaluator
uint8_t rgba[4]
Definition: drawutils.h:63
const char * name
Definition: opengl_enc.c:102
static int func_eval_expr_int_format(AVFilterContext *ctx, AVBPrint *bp, char *fct, unsigned argc, char **argv, int tag)
Definition: vf_drawtext.c:1037
void av_bprint_chars(AVBPrint *buf, char c, unsigned n)
Append char c n times to a print buffer.
Definition: bprint.c:140
static uint8_t tmp[11]
Definition: aes_ctr.c:26