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/time.h"
55 #include "libavutil/timecode.h"
57 #include "libavutil/tree.h"
58 #include "libavutil/lfg.h"
60 #include "avfilter.h"
61 #include "drawutils.h"
62 #include "formats.h"
63 #include "internal.h"
64 #include "video.h"
65 
66 #if CONFIG_LIBFRIBIDI
67 #include <fribidi.h>
68 #endif
69 
70 #include <ft2build.h>
71 #include FT_FREETYPE_H
72 #include FT_GLYPH_H
73 #include FT_STROKER_H
74 
75 static const char *const var_names[] = {
76  "dar",
77  "hsub", "vsub",
78  "line_h", "lh", ///< line height, same as max_glyph_h
79  "main_h", "h", "H", ///< height of the input video
80  "main_w", "w", "W", ///< width of the input video
81  "max_glyph_a", "ascent", ///< max glyph ascent
82  "max_glyph_d", "descent", ///< min glyph descent
83  "max_glyph_h", ///< max glyph height
84  "max_glyph_w", ///< max glyph width
85  "n", ///< number of frame
86  "sar",
87  "t", ///< timestamp expressed in seconds
88  "text_h", "th", ///< height of the rendered text
89  "text_w", "tw", ///< width of the rendered text
90  "x",
91  "y",
92  "pict_type",
93 #if FF_API_FRAME_PKT
94  "pkt_pos",
95 #endif
96 #if FF_API_PKT_DURATION
97  "pkt_duration",
98 #endif
99 #if FF_API_FRAME_PKT
100  "pkt_size",
101 #endif
102  "duration",
103  NULL
104 };
105 
106 static const char *const fun2_names[] = {
107  "rand"
108 };
109 
110 static double drand(void *opaque, double min, double max)
111 {
112  return min + (max-min) / UINT_MAX * av_lfg_get(opaque);
113 }
114 
115 typedef double (*eval_func2)(void *, double a, double b);
116 
117 static const eval_func2 fun2[] = {
118  drand,
119  NULL
120 };
121 
122 enum var_name {
140 #if FF_API_FRAME_PKT
141  VAR_PKT_POS,
142 #endif
143 #if FF_API_PKT_DURATION
144  VAR_PKT_DURATION,
145 #endif
146 #if FF_API_FRAME_PKT
147  VAR_PKT_SIZE,
148 #endif
151 };
152 
157 };
158 
159 typedef struct DrawTextContext {
160  const AVClass *class;
161  int exp_mode; ///< expansion mode to use for the text
162  int reinit; ///< tells if the filter is being reinited
163 #if CONFIG_LIBFONTCONFIG
164  uint8_t *font; ///< font to be used
165 #endif
166  uint8_t *fontfile; ///< font to be used
167  uint8_t *text; ///< text to be drawn
168  AVBPrint expanded_text; ///< used to contain the expanded text
169  uint8_t *fontcolor_expr; ///< fontcolor expression to evaluate
170  AVBPrint expanded_fontcolor; ///< used to contain the expanded fontcolor spec
171  int ft_load_flags; ///< flags used for loading fonts, see FT_LOAD_*
172  FT_Vector *positions; ///< positions for each element in the text
173  size_t nb_positions; ///< number of elements of positions array
174  char *textfile; ///< file with text to be drawn
175  int x; ///< x position to start drawing text
176  int y; ///< y position to start drawing text
177  int max_glyph_w; ///< max glyph width
178  int max_glyph_h; ///< max glyph height
180  int borderw; ///< border width
181  char *fontsize_expr; ///< expression for fontsize
182  AVExpr *fontsize_pexpr; ///< parsed expressions for fontsize
183  unsigned int fontsize; ///< font size to use
184  unsigned int default_fontsize; ///< default font size to use
185 
186  int line_spacing; ///< lines spacing in pixels
187  short int draw_box; ///< draw box around text - true or false
188  int boxborderw; ///< box border width
189  int use_kerning; ///< font kerning is used - true/false
190  int tabsize; ///< tab size
191  int fix_bounds; ///< do we let it go out of frame bounds - t/f
192 
194  FFDrawColor fontcolor; ///< foreground color
195  FFDrawColor shadowcolor; ///< shadow color
196  FFDrawColor bordercolor; ///< border color
197  FFDrawColor boxcolor; ///< background color
198 
199  FT_Library library; ///< freetype font library handle
200  FT_Face face; ///< freetype font face handle
201  FT_Stroker stroker; ///< freetype stroker handle
202  struct AVTreeNode *glyphs; ///< rendered glyphs, stored using the UTF-32 char code
203  char *x_expr; ///< expression for x position
204  char *y_expr; ///< expression for y position
205  AVExpr *x_pexpr, *y_pexpr; ///< parsed expressions for x and y
206  int64_t basetime; ///< base pts time in the real world for display
208  char *a_expr;
210  int alpha;
211  AVLFG prng; ///< random
212  char *tc_opt_string; ///< specified timecode option string
213  AVRational tc_rate; ///< frame rate for timecode
214  AVTimecode tc; ///< timecode context
215  int tc24hmax; ///< 1 if timecode is wrapped to 24 hours, 0 otherwise
216  int reload; ///< reload text file at specified frame interval
217  int start_number; ///< starting frame number for n/frame_num var
218  char *text_source_string; ///< the string to specify text data source
220 #if CONFIG_LIBFRIBIDI
221  int text_shaping; ///< 1 to shape the text before drawing it
222 #endif
225 
226 #define OFFSET(x) offsetof(DrawTextContext, x)
227 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
228 
229 static const AVOption drawtext_options[]= {
230  {"fontfile", "set font file", OFFSET(fontfile), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS},
231  {"text", "set text", OFFSET(text), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS},
232  {"textfile", "set text file", OFFSET(textfile), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS},
233  {"fontcolor", "set foreground color", OFFSET(fontcolor.rgba), AV_OPT_TYPE_COLOR, {.str="black"}, 0, 0, FLAGS},
234  {"fontcolor_expr", "set foreground color expression", OFFSET(fontcolor_expr), AV_OPT_TYPE_STRING, {.str=""}, 0, 0, FLAGS},
235  {"boxcolor", "set box color", OFFSET(boxcolor.rgba), AV_OPT_TYPE_COLOR, {.str="white"}, 0, 0, FLAGS},
236  {"bordercolor", "set border color", OFFSET(bordercolor.rgba), AV_OPT_TYPE_COLOR, {.str="black"}, 0, 0, FLAGS},
237  {"shadowcolor", "set shadow color", OFFSET(shadowcolor.rgba), AV_OPT_TYPE_COLOR, {.str="black"}, 0, 0, FLAGS},
238  {"box", "set box", OFFSET(draw_box), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 , FLAGS},
239  {"boxborderw", "set box border width", OFFSET(boxborderw), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX , FLAGS},
240  {"line_spacing", "set line spacing in pixels", OFFSET(line_spacing), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX,FLAGS},
241  {"fontsize", "set font size", OFFSET(fontsize_expr), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0 , FLAGS},
242  {"x", "set x expression", OFFSET(x_expr), AV_OPT_TYPE_STRING, {.str="0"}, 0, 0, FLAGS},
243  {"y", "set y expression", OFFSET(y_expr), AV_OPT_TYPE_STRING, {.str="0"}, 0, 0, FLAGS},
244  {"shadowx", "set shadow x offset", OFFSET(shadowx), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX , FLAGS},
245  {"shadowy", "set shadow y offset", OFFSET(shadowy), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX , FLAGS},
246  {"borderw", "set border width", OFFSET(borderw), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX , FLAGS},
247  {"tabsize", "set tab size", OFFSET(tabsize), AV_OPT_TYPE_INT, {.i64=4}, 0, INT_MAX , FLAGS},
248  {"basetime", "set base time", OFFSET(basetime), AV_OPT_TYPE_INT64, {.i64=AV_NOPTS_VALUE}, INT64_MIN, INT64_MAX , FLAGS},
249 #if CONFIG_LIBFONTCONFIG
250  { "font", "Font name", OFFSET(font), AV_OPT_TYPE_STRING, { .str = "Sans" }, .flags = FLAGS },
251 #endif
252 
253  {"expansion", "set the expansion mode", OFFSET(exp_mode), AV_OPT_TYPE_INT, {.i64=EXP_NORMAL}, 0, 2, FLAGS, "expansion"},
254  {"none", "set no expansion", OFFSET(exp_mode), AV_OPT_TYPE_CONST, {.i64=EXP_NONE}, 0, 0, FLAGS, "expansion"},
255  {"normal", "set normal expansion", OFFSET(exp_mode), AV_OPT_TYPE_CONST, {.i64=EXP_NORMAL}, 0, 0, FLAGS, "expansion"},
256  {"strftime", "set strftime expansion (deprecated)", OFFSET(exp_mode), AV_OPT_TYPE_CONST, {.i64=EXP_STRFTIME}, 0, 0, FLAGS, "expansion"},
257 
258  {"timecode", "set initial timecode", OFFSET(tc_opt_string), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS},
259  {"tc24hmax", "set 24 hours max (timecode only)", OFFSET(tc24hmax), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
260  {"timecode_rate", "set rate (timecode only)", OFFSET(tc_rate), AV_OPT_TYPE_RATIONAL, {.dbl=0}, 0, INT_MAX, FLAGS},
261  {"r", "set rate (timecode only)", OFFSET(tc_rate), AV_OPT_TYPE_RATIONAL, {.dbl=0}, 0, INT_MAX, FLAGS},
262  {"rate", "set rate (timecode only)", OFFSET(tc_rate), AV_OPT_TYPE_RATIONAL, {.dbl=0}, 0, INT_MAX, FLAGS},
263  {"reload", "reload text file at specified frame interval", OFFSET(reload), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS},
264  { "alpha", "apply alpha while rendering", OFFSET(a_expr), AV_OPT_TYPE_STRING, { .str = "1" }, .flags = FLAGS },
265  {"fix_bounds", "check and fix text coords to avoid clipping", OFFSET(fix_bounds), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
266  {"start_number", "start frame number for n/frame_num variable", OFFSET(start_number), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS},
267  {"text_source", "the source of text", OFFSET(text_source_string), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 1, FLAGS },
268 
269 #if CONFIG_LIBFRIBIDI
270  {"text_shaping", "attempt to shape text before drawing", OFFSET(text_shaping), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS},
271 #endif
272 
273  /* FT_LOAD_* flags */
274  { "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" },
275  { "default", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_DEFAULT }, .flags = FLAGS, .unit = "ft_load_flags" },
276  { "no_scale", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_NO_SCALE }, .flags = FLAGS, .unit = "ft_load_flags" },
277  { "no_hinting", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_NO_HINTING }, .flags = FLAGS, .unit = "ft_load_flags" },
278  { "render", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_RENDER }, .flags = FLAGS, .unit = "ft_load_flags" },
279  { "no_bitmap", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_NO_BITMAP }, .flags = FLAGS, .unit = "ft_load_flags" },
280  { "vertical_layout", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_VERTICAL_LAYOUT }, .flags = FLAGS, .unit = "ft_load_flags" },
281  { "force_autohint", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_FORCE_AUTOHINT }, .flags = FLAGS, .unit = "ft_load_flags" },
282  { "crop_bitmap", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_CROP_BITMAP }, .flags = FLAGS, .unit = "ft_load_flags" },
283  { "pedantic", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_PEDANTIC }, .flags = FLAGS, .unit = "ft_load_flags" },
284  { "ignore_global_advance_width", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH }, .flags = FLAGS, .unit = "ft_load_flags" },
285  { "no_recurse", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_NO_RECURSE }, .flags = FLAGS, .unit = "ft_load_flags" },
286  { "ignore_transform", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_IGNORE_TRANSFORM }, .flags = FLAGS, .unit = "ft_load_flags" },
287  { "monochrome", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_MONOCHROME }, .flags = FLAGS, .unit = "ft_load_flags" },
288  { "linear_design", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_LINEAR_DESIGN }, .flags = FLAGS, .unit = "ft_load_flags" },
289  { "no_autohint", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_NO_AUTOHINT }, .flags = FLAGS, .unit = "ft_load_flags" },
290  { NULL }
291 };
292 
294 
295 #undef __FTERRORS_H__
296 #define FT_ERROR_START_LIST {
297 #define FT_ERRORDEF(e, v, s) { (e), (s) },
298 #define FT_ERROR_END_LIST { 0, NULL } };
299 
300 static const struct ft_error {
301  int err;
302  const char *err_msg;
303 } ft_errors[] =
304 #include FT_ERRORS_H
305 
306 #define FT_ERRMSG(e) ft_errors[e].err_msg
307 
308 typedef struct Glyph {
309  FT_Glyph glyph;
310  FT_Glyph border_glyph;
311  uint32_t code;
312  unsigned int fontsize;
313  FT_Bitmap bitmap; ///< array holding bitmaps of font
314  FT_Bitmap border_bitmap; ///< array holding bitmaps of font border
315  FT_BBox bbox;
316  int advance;
317  int bitmap_left;
318  int bitmap_top;
319 } Glyph;
320 
321 static int glyph_cmp(const void *key, const void *b)
322 {
323  const Glyph *a = key, *bb = b;
324  int64_t diff = (int64_t)a->code - (int64_t)bb->code;
325 
326  if (diff != 0)
327  return diff > 0 ? 1 : -1;
328  else
329  return FFDIFFSIGN((int64_t)a->fontsize, (int64_t)bb->fontsize);
330 }
331 
332 /**
333  * Load glyphs corresponding to the UTF-32 codepoint code.
334  */
335 static int load_glyph(AVFilterContext *ctx, Glyph **glyph_ptr, uint32_t code)
336 {
337  DrawTextContext *s = ctx->priv;
338  FT_BitmapGlyph bitmapglyph;
339  Glyph *glyph;
340  struct AVTreeNode *node = NULL;
341  int ret;
342 
343  /* load glyph into s->face->glyph */
344  if (FT_Load_Char(s->face, code, s->ft_load_flags))
345  return AVERROR(EINVAL);
346 
347  glyph = av_mallocz(sizeof(*glyph));
348  if (!glyph) {
349  ret = AVERROR(ENOMEM);
350  goto error;
351  }
352  glyph->code = code;
353  glyph->fontsize = s->fontsize;
354 
355  if (FT_Get_Glyph(s->face->glyph, &glyph->glyph)) {
356  ret = AVERROR(EINVAL);
357  goto error;
358  }
359  if (s->borderw) {
360  glyph->border_glyph = glyph->glyph;
361  if (FT_Glyph_StrokeBorder(&glyph->border_glyph, s->stroker, 0, 0) ||
362  FT_Glyph_To_Bitmap(&glyph->border_glyph, FT_RENDER_MODE_NORMAL, 0, 1)) {
364  goto error;
365  }
366  bitmapglyph = (FT_BitmapGlyph) glyph->border_glyph;
367  glyph->border_bitmap = bitmapglyph->bitmap;
368  }
369  if (FT_Glyph_To_Bitmap(&glyph->glyph, FT_RENDER_MODE_NORMAL, 0, 1)) {
371  goto error;
372  }
373  bitmapglyph = (FT_BitmapGlyph) glyph->glyph;
374 
375  glyph->bitmap = bitmapglyph->bitmap;
376  glyph->bitmap_left = bitmapglyph->left;
377  glyph->bitmap_top = bitmapglyph->top;
378  glyph->advance = s->face->glyph->advance.x >> 6;
379 
380  /* measure text height to calculate text_height (or the maximum text height) */
381  FT_Glyph_Get_CBox(glyph->glyph, ft_glyph_bbox_pixels, &glyph->bbox);
382 
383  /* cache the newly created glyph */
384  if (!(node = av_tree_node_alloc())) {
385  ret = AVERROR(ENOMEM);
386  goto error;
387  }
388  av_tree_insert(&s->glyphs, glyph, glyph_cmp, &node);
389 
390  if (glyph_ptr)
391  *glyph_ptr = glyph;
392  return 0;
393 
394 error:
395  if (glyph)
396  av_freep(&glyph->glyph);
397 
398  av_freep(&glyph);
399  av_freep(&node);
400  return ret;
401 }
402 
403 static av_cold int set_fontsize(AVFilterContext *ctx, unsigned int fontsize)
404 {
405  int err;
406  DrawTextContext *s = ctx->priv;
407 
408  if ((err = FT_Set_Pixel_Sizes(s->face, 0, fontsize))) {
409  av_log(ctx, AV_LOG_ERROR, "Could not set font size to %d pixels: %s\n",
410  fontsize, FT_ERRMSG(err));
411  return AVERROR(EINVAL);
412  }
413 
414  s->fontsize = fontsize;
415 
416  return 0;
417 }
418 
420 {
421  DrawTextContext *s = ctx->priv;
422  int err;
423 
424  if (s->fontsize_pexpr)
425  return 0;
426 
427  if (s->fontsize_expr == NULL)
428  return AVERROR(EINVAL);
429 
430  if ((err = av_expr_parse(&s->fontsize_pexpr, s->fontsize_expr, var_names,
431  NULL, NULL, fun2_names, fun2, 0, ctx)) < 0)
432  return err;
433 
434  return 0;
435 }
436 
438 {
439  DrawTextContext *s = ctx->priv;
440  unsigned int fontsize = s->default_fontsize;
441  int err;
442  double size, roundedsize;
443 
444  // if no fontsize specified use the default
445  if (s->fontsize_expr != NULL) {
446  if ((err = parse_fontsize(ctx)) < 0)
447  return err;
448 
449  size = av_expr_eval(s->fontsize_pexpr, s->var_values, &s->prng);
450 
451  if (!isnan(size)) {
452  roundedsize = round(size);
453  // test for overflow before cast
454  if (!(roundedsize > INT_MIN && roundedsize < INT_MAX)) {
455  av_log(ctx, AV_LOG_ERROR, "fontsize overflow\n");
456  return AVERROR(EINVAL);
457  }
458 
459  fontsize = roundedsize;
460  }
461  }
462 
463  if (fontsize == 0)
464  fontsize = 1;
465 
466  // no change
467  if (fontsize == s->fontsize)
468  return 0;
469 
470  return set_fontsize(ctx, fontsize);
471 }
472 
473 static int load_font_file(AVFilterContext *ctx, const char *path, int index)
474 {
475  DrawTextContext *s = ctx->priv;
476  int err;
477 
478  err = FT_New_Face(s->library, path, index, &s->face);
479  if (err) {
480 #if !CONFIG_LIBFONTCONFIG
481  av_log(ctx, AV_LOG_ERROR, "Could not load font \"%s\": %s\n",
482  s->fontfile, FT_ERRMSG(err));
483 #endif
484  return AVERROR(EINVAL);
485  }
486  return 0;
487 }
488 
489 #if CONFIG_LIBFONTCONFIG
490 static int load_font_fontconfig(AVFilterContext *ctx)
491 {
492  DrawTextContext *s = ctx->priv;
493  FcConfig *fontconfig;
494  FcPattern *pat, *best;
495  FcResult result = FcResultMatch;
496  FcChar8 *filename;
497  int index;
498  double size;
499  int err = AVERROR(ENOENT);
500  int parse_err;
501 
502  fontconfig = FcInitLoadConfigAndFonts();
503  if (!fontconfig) {
504  av_log(ctx, AV_LOG_ERROR, "impossible to init fontconfig\n");
505  return AVERROR_UNKNOWN;
506  }
507  pat = FcNameParse(s->fontfile ? s->fontfile :
508  (uint8_t *)(intptr_t)"default");
509  if (!pat) {
510  av_log(ctx, AV_LOG_ERROR, "could not parse fontconfig pat");
511  return AVERROR(EINVAL);
512  }
513 
514  FcPatternAddString(pat, FC_FAMILY, s->font);
515 
516  parse_err = parse_fontsize(ctx);
517  if (!parse_err) {
518  double size = av_expr_eval(s->fontsize_pexpr, s->var_values, &s->prng);
519 
520  if (isnan(size)) {
521  av_log(ctx, AV_LOG_ERROR, "impossible to find font information");
522  return AVERROR(EINVAL);
523  }
524 
525  FcPatternAddDouble(pat, FC_SIZE, size);
526  }
527 
528  FcDefaultSubstitute(pat);
529 
530  if (!FcConfigSubstitute(fontconfig, pat, FcMatchPattern)) {
531  av_log(ctx, AV_LOG_ERROR, "could not substitue fontconfig options"); /* very unlikely */
532  FcPatternDestroy(pat);
533  return AVERROR(ENOMEM);
534  }
535 
536  best = FcFontMatch(fontconfig, pat, &result);
537  FcPatternDestroy(pat);
538 
539  if (!best || result != FcResultMatch) {
541  "Cannot find a valid font for the family %s\n",
542  s->font);
543  goto fail;
544  }
545 
546  if (
547  FcPatternGetInteger(best, FC_INDEX, 0, &index ) != FcResultMatch ||
548  FcPatternGetDouble (best, FC_SIZE, 0, &size ) != FcResultMatch) {
549  av_log(ctx, AV_LOG_ERROR, "impossible to find font information");
550  return AVERROR(EINVAL);
551  }
552 
553  if (FcPatternGetString(best, FC_FILE, 0, &filename) != FcResultMatch) {
554  av_log(ctx, AV_LOG_ERROR, "No file path for %s\n",
555  s->font);
556  goto fail;
557  }
558 
559  av_log(ctx, AV_LOG_INFO, "Using \"%s\"\n", filename);
560  if (parse_err)
561  s->default_fontsize = size + 0.5;
562 
563  err = load_font_file(ctx, filename, index);
564  if (err)
565  return err;
566  FcConfigDestroy(fontconfig);
567 fail:
568  FcPatternDestroy(best);
569  return err;
570 }
571 #endif
572 
574 {
575  DrawTextContext *s = ctx->priv;
576  int err;
577 
578  /* load the face, and set up the encoding, which is by default UTF-8 */
579  err = load_font_file(ctx, s->fontfile, 0);
580  if (!err)
581  return 0;
582 #if CONFIG_LIBFONTCONFIG
583  err = load_font_fontconfig(ctx);
584  if (!err)
585  return 0;
586 #endif
587  return err;
588 }
589 
590 static inline int is_newline(uint32_t c)
591 {
592  return c == '\n' || c == '\r' || c == '\f' || c == '\v';
593 }
594 
596 {
597  DrawTextContext *s = ctx->priv;
598  int err;
599  uint8_t *textbuf;
600  uint8_t *tmp;
601  size_t textbuf_size;
602 
603  if ((err = av_file_map(s->textfile, &textbuf, &textbuf_size, 0, ctx)) < 0) {
605  "The text file '%s' could not be read or is empty\n",
606  s->textfile);
607  return err;
608  }
609 
610  if (textbuf_size > 0 && is_newline(textbuf[textbuf_size - 1]))
611  textbuf_size--;
612  if (textbuf_size > SIZE_MAX - 1 || !(tmp = av_realloc(s->text, textbuf_size + 1))) {
613  av_file_unmap(textbuf, textbuf_size);
614  return AVERROR(ENOMEM);
615  }
616  s->text = tmp;
617  memcpy(s->text, textbuf, textbuf_size);
618  s->text[textbuf_size] = 0;
619  av_file_unmap(textbuf, textbuf_size);
620 
621  return 0;
622 }
623 
624 #if CONFIG_LIBFRIBIDI
625 static int shape_text(AVFilterContext *ctx)
626 {
627  DrawTextContext *s = ctx->priv;
628  uint8_t *tmp;
629  int ret = AVERROR(ENOMEM);
630  static const FriBidiFlags flags = FRIBIDI_FLAGS_DEFAULT |
631  FRIBIDI_FLAGS_ARABIC;
632  FriBidiChar *unicodestr = NULL;
633  FriBidiStrIndex len;
634  FriBidiParType direction = FRIBIDI_PAR_LTR;
635  FriBidiStrIndex line_start = 0;
636  FriBidiStrIndex line_end = 0;
637  FriBidiLevel *embedding_levels = NULL;
638  FriBidiArabicProp *ar_props = NULL;
639  FriBidiCharType *bidi_types = NULL;
640  FriBidiStrIndex i,j;
641 
642  len = strlen(s->text);
643  if (!(unicodestr = av_malloc_array(len, sizeof(*unicodestr)))) {
644  goto out;
645  }
646  len = fribidi_charset_to_unicode(FRIBIDI_CHAR_SET_UTF8,
647  s->text, len, unicodestr);
648 
649  bidi_types = av_malloc_array(len, sizeof(*bidi_types));
650  if (!bidi_types) {
651  goto out;
652  }
653 
654  fribidi_get_bidi_types(unicodestr, len, bidi_types);
655 
656  embedding_levels = av_malloc_array(len, sizeof(*embedding_levels));
657  if (!embedding_levels) {
658  goto out;
659  }
660 
661  if (!fribidi_get_par_embedding_levels(bidi_types, len, &direction,
662  embedding_levels)) {
663  goto out;
664  }
665 
666  ar_props = av_malloc_array(len, sizeof(*ar_props));
667  if (!ar_props) {
668  goto out;
669  }
670 
671  fribidi_get_joining_types(unicodestr, len, ar_props);
672  fribidi_join_arabic(bidi_types, len, embedding_levels, ar_props);
673  fribidi_shape(flags, embedding_levels, len, ar_props, unicodestr);
674 
675  for (line_end = 0, line_start = 0; line_end < len; line_end++) {
676  if (is_newline(unicodestr[line_end]) || line_end == len - 1) {
677  if (!fribidi_reorder_line(flags, bidi_types,
678  line_end - line_start + 1, line_start,
679  direction, embedding_levels, unicodestr,
680  NULL)) {
681  goto out;
682  }
683  line_start = line_end + 1;
684  }
685  }
686 
687  /* Remove zero-width fill chars put in by libfribidi */
688  for (i = 0, j = 0; i < len; i++)
689  if (unicodestr[i] != FRIBIDI_CHAR_FILL)
690  unicodestr[j++] = unicodestr[i];
691  len = j;
692 
693  if (!(tmp = av_realloc(s->text, (len * 4 + 1) * sizeof(*s->text)))) {
694  /* Use len * 4, as a unicode character can be up to 4 bytes in UTF-8 */
695  goto out;
696  }
697 
698  s->text = tmp;
699  len = fribidi_unicode_to_charset(FRIBIDI_CHAR_SET_UTF8,
700  unicodestr, len, s->text);
701  ret = 0;
702 
703 out:
704  av_free(unicodestr);
705  av_free(embedding_levels);
706  av_free(ar_props);
707  av_free(bidi_types);
708  return ret;
709 }
710 #endif
711 
712 static enum AVFrameSideDataType text_source_string_parse(const char *text_source_string)
713 {
714  av_assert0(text_source_string);
715  if (!strcmp(text_source_string, "side_data_detection_bboxes")) {
717  } else {
718  return AVERROR(EINVAL);
719  }
720 }
721 
723 {
724  int err;
725  DrawTextContext *s = ctx->priv;
726  Glyph *glyph;
727 
728  av_expr_free(s->fontsize_pexpr);
729  s->fontsize_pexpr = NULL;
730 
731  s->fontsize = 0;
732  s->default_fontsize = 16;
733 
734  if (!s->fontfile && !CONFIG_LIBFONTCONFIG) {
735  av_log(ctx, AV_LOG_ERROR, "No font filename provided\n");
736  return AVERROR(EINVAL);
737  }
738 
739  if (s->textfile) {
740  if (s->text) {
742  "Both text and text file provided. Please provide only one\n");
743  return AVERROR(EINVAL);
744  }
745  if ((err = load_textfile(ctx)) < 0)
746  return err;
747  }
748 
749  if (s->reload && !s->textfile)
750  av_log(ctx, AV_LOG_WARNING, "No file to reload\n");
751 
752  if (s->tc_opt_string) {
753  int ret = av_timecode_init_from_string(&s->tc, s->tc_rate,
754  s->tc_opt_string, ctx);
755  if (ret < 0)
756  return ret;
757  if (s->tc24hmax)
758  s->tc.flags |= AV_TIMECODE_FLAG_24HOURSMAX;
759  if (!s->text)
760  s->text = av_strdup("");
761  }
762 
763  if (s->text_source_string) {
764  s->text_source = text_source_string_parse(s->text_source_string);
765  if ((int)s->text_source < 0) {
766  av_log(ctx, AV_LOG_ERROR, "Error text source: %s\n", s->text_source_string);
767  return AVERROR(EINVAL);
768  }
769  }
770 
771  if (s->text_source == AV_FRAME_DATA_DETECTION_BBOXES) {
772  if (s->text) {
773  av_log(ctx, AV_LOG_WARNING, "Multiple texts provided, will use text_source only\n");
774  av_free(s->text);
775  }
778  if (!s->text)
779  return AVERROR(ENOMEM);
780  }
781 
782  if (!s->text) {
784  "Either text, a valid file, a timecode or text source must be provided\n");
785  return AVERROR(EINVAL);
786  }
787 
788 #if CONFIG_LIBFRIBIDI
789  if (s->text_shaping)
790  if ((err = shape_text(ctx)) < 0)
791  return err;
792 #endif
793 
794  if ((err = FT_Init_FreeType(&(s->library)))) {
796  "Could not load FreeType: %s\n", FT_ERRMSG(err));
797  return AVERROR(EINVAL);
798  }
799 
800  if ((err = load_font(ctx)) < 0)
801  return err;
802 
803  if ((err = update_fontsize(ctx)) < 0)
804  return err;
805 
806  if (s->borderw) {
807  if (FT_Stroker_New(s->library, &s->stroker)) {
808  av_log(ctx, AV_LOG_ERROR, "Coult not init FT stroker\n");
809  return AVERROR_EXTERNAL;
810  }
811  FT_Stroker_Set(s->stroker, s->borderw << 6, FT_STROKER_LINECAP_ROUND,
812  FT_STROKER_LINEJOIN_ROUND, 0);
813  }
814 
815  s->use_kerning = FT_HAS_KERNING(s->face);
816 
817  /* load the fallback glyph with code 0 */
818  load_glyph(ctx, NULL, 0);
819 
820  /* set the tabsize in pixels */
821  if ((err = load_glyph(ctx, &glyph, ' ')) < 0) {
822  av_log(ctx, AV_LOG_ERROR, "Could not set tabsize.\n");
823  return err;
824  }
825  s->tabsize *= glyph->advance;
826 
827  if (s->exp_mode == EXP_STRFTIME &&
828  (strchr(s->text, '%') || strchr(s->text, '\\')))
829  av_log(ctx, AV_LOG_WARNING, "expansion=strftime is deprecated.\n");
830 
831  av_bprint_init(&s->expanded_text, 0, AV_BPRINT_SIZE_UNLIMITED);
832  av_bprint_init(&s->expanded_fontcolor, 0, AV_BPRINT_SIZE_UNLIMITED);
833 
834  return 0;
835 }
836 
838 {
840 }
841 
842 static int glyph_enu_free(void *opaque, void *elem)
843 {
844  Glyph *glyph = elem;
845 
846  FT_Done_Glyph(glyph->glyph);
847  FT_Done_Glyph(glyph->border_glyph);
848  av_free(elem);
849  return 0;
850 }
851 
853 {
854  DrawTextContext *s = ctx->priv;
855 
856  av_expr_free(s->x_pexpr);
857  av_expr_free(s->y_pexpr);
858  av_expr_free(s->a_pexpr);
859  av_expr_free(s->fontsize_pexpr);
860 
861  s->x_pexpr = s->y_pexpr = s->a_pexpr = s->fontsize_pexpr = NULL;
862 
863  av_freep(&s->positions);
864  s->nb_positions = 0;
865 
867  av_tree_destroy(s->glyphs);
868  s->glyphs = NULL;
869 
870  FT_Done_Face(s->face);
871  FT_Stroker_Done(s->stroker);
872  FT_Done_FreeType(s->library);
873 
874  av_bprint_finalize(&s->expanded_text, NULL);
875  av_bprint_finalize(&s->expanded_fontcolor, NULL);
876 }
877 
879 {
880  AVFilterContext *ctx = inlink->dst;
881  DrawTextContext *s = ctx->priv;
882  char *expr;
883  int ret;
884 
885  ff_draw_init(&s->dc, inlink->format, FF_DRAW_PROCESS_ALPHA);
886  ff_draw_color(&s->dc, &s->fontcolor, s->fontcolor.rgba);
887  ff_draw_color(&s->dc, &s->shadowcolor, s->shadowcolor.rgba);
888  ff_draw_color(&s->dc, &s->bordercolor, s->bordercolor.rgba);
889  ff_draw_color(&s->dc, &s->boxcolor, s->boxcolor.rgba);
890 
891  s->var_values[VAR_w] = s->var_values[VAR_W] = s->var_values[VAR_MAIN_W] = inlink->w;
892  s->var_values[VAR_h] = s->var_values[VAR_H] = s->var_values[VAR_MAIN_H] = inlink->h;
893  s->var_values[VAR_SAR] = inlink->sample_aspect_ratio.num ? av_q2d(inlink->sample_aspect_ratio) : 1;
894  s->var_values[VAR_DAR] = (double)inlink->w / inlink->h * s->var_values[VAR_SAR];
895  s->var_values[VAR_HSUB] = 1 << s->dc.hsub_max;
896  s->var_values[VAR_VSUB] = 1 << s->dc.vsub_max;
897  s->var_values[VAR_X] = NAN;
898  s->var_values[VAR_Y] = NAN;
899  s->var_values[VAR_T] = NAN;
900 
901  av_lfg_init(&s->prng, av_get_random_seed());
902 
903  av_expr_free(s->x_pexpr);
904  av_expr_free(s->y_pexpr);
905  av_expr_free(s->a_pexpr);
906  s->x_pexpr = s->y_pexpr = s->a_pexpr = NULL;
907 
908  if ((ret = av_expr_parse(&s->x_pexpr, expr = s->x_expr, var_names,
909  NULL, NULL, fun2_names, fun2, 0, ctx)) < 0 ||
910  (ret = av_expr_parse(&s->y_pexpr, expr = s->y_expr, var_names,
911  NULL, NULL, fun2_names, fun2, 0, ctx)) < 0 ||
912  (ret = av_expr_parse(&s->a_pexpr, expr = s->a_expr, var_names,
913  NULL, NULL, fun2_names, fun2, 0, ctx)) < 0) {
914  av_log(ctx, AV_LOG_ERROR, "Failed to parse expression: %s \n", expr);
915  return AVERROR(EINVAL);
916  }
917 
918  return 0;
919 }
920 
921 static int command(AVFilterContext *ctx, const char *cmd, const char *arg, char *res, int res_len, int flags)
922 {
923  DrawTextContext *old = ctx->priv;
924  DrawTextContext *new = NULL;
925  int ret;
926 
927  if (!strcmp(cmd, "reinit")) {
928  new = av_mallocz(sizeof(DrawTextContext));
929  if (!new)
930  return AVERROR(ENOMEM);
931 
932  new->class = &drawtext_class;
933  ret = av_opt_copy(new, old);
934  if (ret < 0)
935  goto fail;
936 
937  ctx->priv = new;
938  ret = av_set_options_string(ctx, arg, "=", ":");
939  if (ret < 0) {
940  ctx->priv = old;
941  goto fail;
942  }
943 
944  ret = init(ctx);
945  if (ret < 0) {
946  uninit(ctx);
947  ctx->priv = old;
948  goto fail;
949  }
950 
951  new->reinit = 1;
952 
953  ctx->priv = old;
954  uninit(ctx);
955  av_freep(&old);
956 
957  ctx->priv = new;
958  return config_input(ctx->inputs[0]);
959  } else
960  return AVERROR(ENOSYS);
961 
962 fail:
963  av_log(ctx, AV_LOG_ERROR, "Failed to process command. Continuing with existing parameters.\n");
964  av_freep(&new);
965  return ret;
966 }
967 
968 static int func_pict_type(AVFilterContext *ctx, AVBPrint *bp,
969  char *fct, unsigned argc, char **argv, int tag)
970 {
971  DrawTextContext *s = ctx->priv;
972 
973  av_bprintf(bp, "%c", av_get_picture_type_char(s->var_values[VAR_PICT_TYPE]));
974  return 0;
975 }
976 
977 static int func_pts(AVFilterContext *ctx, AVBPrint *bp,
978  char *fct, unsigned argc, char **argv, int tag)
979 {
980  DrawTextContext *s = ctx->priv;
981  const char *fmt;
982  double pts = s->var_values[VAR_T];
983  int ret;
984 
985  fmt = argc >= 1 ? argv[0] : "flt";
986  if (argc >= 2) {
987  int64_t delta;
988  if ((ret = av_parse_time(&delta, argv[1], 1)) < 0) {
989  av_log(ctx, AV_LOG_ERROR, "Invalid delta '%s'\n", argv[1]);
990  return ret;
991  }
993  }
994  if (!strcmp(fmt, "flt")) {
995  av_bprintf(bp, "%.6f", pts);
996  } else if (!strcmp(fmt, "hms")) {
997  if (isnan(pts)) {
998  av_bprintf(bp, " ??:??:??.???");
999  } else {
1000  int64_t ms = llrint(pts * 1000);
1001  char sign = ' ';
1002  if (ms < 0) {
1003  sign = '-';
1004  ms = -ms;
1005  }
1006  if (argc >= 3) {
1007  if (!strcmp(argv[2], "24HH")) {
1008  ms %= 24 * 60 * 60 * 1000;
1009  } else {
1010  av_log(ctx, AV_LOG_ERROR, "Invalid argument '%s'\n", argv[2]);
1011  return AVERROR(EINVAL);
1012  }
1013  }
1014  av_bprintf(bp, "%c%02d:%02d:%02d.%03d", sign,
1015  (int)(ms / (60 * 60 * 1000)),
1016  (int)(ms / (60 * 1000)) % 60,
1017  (int)(ms / 1000) % 60,
1018  (int)(ms % 1000));
1019  }
1020  } else if (!strcmp(fmt, "localtime") ||
1021  !strcmp(fmt, "gmtime")) {
1022  struct tm tm;
1023  time_t ms = (time_t)pts;
1024  const char *timefmt = argc >= 3 ? argv[2] : "%Y-%m-%d %H:%M:%S";
1025  if (!strcmp(fmt, "localtime"))
1026  localtime_r(&ms, &tm);
1027  else
1028  gmtime_r(&ms, &tm);
1029  av_bprint_strftime(bp, timefmt, &tm);
1030  } else {
1031  av_log(ctx, AV_LOG_ERROR, "Invalid format '%s'\n", fmt);
1032  return AVERROR(EINVAL);
1033  }
1034  return 0;
1035 }
1036 
1037 static int func_frame_num(AVFilterContext *ctx, AVBPrint *bp,
1038  char *fct, unsigned argc, char **argv, int tag)
1039 {
1040  DrawTextContext *s = ctx->priv;
1041 
1042  av_bprintf(bp, "%d", (int)s->var_values[VAR_N]);
1043  return 0;
1044 }
1045 
1046 static int func_metadata(AVFilterContext *ctx, AVBPrint *bp,
1047  char *fct, unsigned argc, char **argv, int tag)
1048 {
1049  DrawTextContext *s = ctx->priv;
1050  AVDictionaryEntry *e = av_dict_get(s->metadata, argv[0], NULL, 0);
1051 
1052  if (e && e->value)
1053  av_bprintf(bp, "%s", e->value);
1054  else if (argc >= 2)
1055  av_bprintf(bp, "%s", argv[1]);
1056  return 0;
1057 }
1058 
1059 static int func_strftime(AVFilterContext *ctx, AVBPrint *bp,
1060  char *fct, unsigned argc, char **argv, int tag)
1061 {
1062  const char *fmt = argc ? argv[0] : "%Y-%m-%d %H:%M:%S";
1063  const char *fmt_begin = fmt;
1064  int64_t unow;
1065  time_t now;
1066  struct tm tm;
1067  const char *begin;
1068  const char *tmp;
1069  int len;
1070  int div;
1071  AVBPrint fmt_bp;
1072 
1074 
1075  unow = av_gettime();
1076  now = unow / 1000000;
1077  if (tag == 'L' || tag == 'm')
1078  localtime_r(&now, &tm);
1079  else
1080  tm = *gmtime_r(&now, &tm);
1081 
1082  // manually parse format for %N (fractional seconds)
1083  begin = fmt;
1084  while ((begin = strchr(begin, '%'))) {
1085  tmp = begin + 1;
1086  len = 0;
1087 
1088  // skip escaped "%%"
1089  if (*tmp == '%') {
1090  begin = tmp + 1;
1091  continue;
1092  }
1093 
1094  // count digits between % and possible N
1095  while (*tmp != '\0' && av_isdigit((int)*tmp)) {
1096  len++;
1097  tmp++;
1098  }
1099 
1100  // N encountered, insert time
1101  if (*tmp == 'N') {
1102  int num_digits = 3; // default show millisecond [1,6]
1103 
1104  // if digit given, expect [1,6], warn & clamp otherwise
1105  if (len == 1) {
1106  num_digits = av_clip(*(begin + 1) - '0', 1, 6);
1107  } else if (len > 1) {
1108  av_log(ctx, AV_LOG_WARNING, "Invalid number of decimals for %%N, using default of %i\n", num_digits);
1109  }
1110 
1111  len += 2; // add % and N to get length of string part
1112 
1113  div = pow(10, 6 - num_digits);
1114 
1115  av_bprintf(&fmt_bp, "%.*s%0*d", (int)(begin - fmt_begin), fmt_begin, num_digits, (int)(unow % 1000000) / div);
1116 
1117  begin += len;
1118  fmt_begin = begin;
1119 
1120  continue;
1121  }
1122 
1123  begin = tmp;
1124  }
1125 
1126  av_bprintf(&fmt_bp, "%s", fmt_begin);
1127  if (!av_bprint_is_complete(&fmt_bp)) {
1128  av_log(ctx, AV_LOG_WARNING, "Format string truncated at %u/%u.", fmt_bp.size, fmt_bp.len);
1129  }
1130 
1131  av_bprint_strftime(bp, fmt_bp.str, &tm);
1132 
1133  av_bprint_finalize(&fmt_bp, NULL);
1134 
1135  return 0;
1136 }
1137 
1138 static int func_eval_expr(AVFilterContext *ctx, AVBPrint *bp,
1139  char *fct, unsigned argc, char **argv, int tag)
1140 {
1141  DrawTextContext *s = ctx->priv;
1142  double res;
1143  int ret;
1144 
1145  ret = av_expr_parse_and_eval(&res, argv[0], var_names, s->var_values,
1146  NULL, NULL, fun2_names, fun2,
1147  &s->prng, 0, ctx);
1148  if (ret < 0)
1150  "Expression '%s' for the expr text expansion function is not valid\n",
1151  argv[0]);
1152  else
1153  av_bprintf(bp, "%f", res);
1154 
1155  return ret;
1156 }
1157 
1159  char *fct, unsigned argc, char **argv, int tag)
1160 {
1161  DrawTextContext *s = ctx->priv;
1162  double res;
1163  int intval;
1164  int ret;
1165  unsigned int positions = 0;
1166  char fmt_str[30] = "%";
1167 
1168  /*
1169  * argv[0] expression to be converted to `int`
1170  * argv[1] format: 'x', 'X', 'd' or 'u'
1171  * argv[2] positions printed (optional)
1172  */
1173 
1174  ret = av_expr_parse_and_eval(&res, argv[0], var_names, s->var_values,
1175  NULL, NULL, fun2_names, fun2,
1176  &s->prng, 0, ctx);
1177  if (ret < 0) {
1179  "Expression '%s' for the expr text expansion function is not valid\n",
1180  argv[0]);
1181  return ret;
1182  }
1183 
1184  if (!strchr("xXdu", argv[1][0])) {
1185  av_log(ctx, AV_LOG_ERROR, "Invalid format '%c' specified,"
1186  " allowed values: 'x', 'X', 'd', 'u'\n", argv[1][0]);
1187  return AVERROR(EINVAL);
1188  }
1189 
1190  if (argc == 3) {
1191  ret = sscanf(argv[2], "%u", &positions);
1192  if (ret != 1) {
1193  av_log(ctx, AV_LOG_ERROR, "expr_int_format(): Invalid number of positions"
1194  " to print: '%s'\n", argv[2]);
1195  return AVERROR(EINVAL);
1196  }
1197  }
1198 
1199  feclearexcept(FE_ALL_EXCEPT);
1200  intval = res;
1201 #if defined(FE_INVALID) && defined(FE_OVERFLOW) && defined(FE_UNDERFLOW)
1202  if ((ret = fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW))) {
1203  av_log(ctx, AV_LOG_ERROR, "Conversion of floating-point result to int failed. Control register: 0x%08x. Conversion result: %d\n", ret, intval);
1204  return AVERROR(EINVAL);
1205  }
1206 #endif
1207 
1208  if (argc == 3)
1209  av_strlcatf(fmt_str, sizeof(fmt_str), "0%u", positions);
1210  av_strlcatf(fmt_str, sizeof(fmt_str), "%c", argv[1][0]);
1211 
1212  av_log(ctx, AV_LOG_DEBUG, "Formatting value %f (expr '%s') with spec '%s'\n",
1213  res, argv[0], fmt_str);
1214 
1215  av_bprintf(bp, fmt_str, intval);
1216 
1217  return 0;
1218 }
1219 
1220 static const struct drawtext_function {
1221  const char *name;
1222  unsigned argc_min, argc_max;
1223  int tag; /**< opaque argument to func */
1224  int (*func)(AVFilterContext *, AVBPrint *, char *, unsigned, char **, int);
1225 } functions[] = {
1226  { "expr", 1, 1, 0, func_eval_expr },
1227  { "e", 1, 1, 0, func_eval_expr },
1228  { "expr_int_format", 2, 3, 0, func_eval_expr_int_format },
1229  { "eif", 2, 3, 0, func_eval_expr_int_format },
1230  { "pict_type", 0, 0, 0, func_pict_type },
1231  { "pts", 0, 3, 0, func_pts },
1232  { "gmtime", 0, 1, 'G', func_strftime },
1233  { "localtime", 0, 1, 'L', func_strftime },
1234  { "frame_num", 0, 0, 0, func_frame_num },
1235  { "n", 0, 0, 0, func_frame_num },
1236  { "metadata", 1, 2, 0, func_metadata },
1237 };
1238 
1239 static int eval_function(AVFilterContext *ctx, AVBPrint *bp, char *fct,
1240  unsigned argc, char **argv)
1241 {
1242  unsigned i;
1243 
1244  for (i = 0; i < FF_ARRAY_ELEMS(functions); i++) {
1245  if (strcmp(fct, functions[i].name))
1246  continue;
1247  if (argc < functions[i].argc_min) {
1248  av_log(ctx, AV_LOG_ERROR, "%%{%s} requires at least %d arguments\n",
1249  fct, functions[i].argc_min);
1250  return AVERROR(EINVAL);
1251  }
1252  if (argc > functions[i].argc_max) {
1253  av_log(ctx, AV_LOG_ERROR, "%%{%s} requires at most %d arguments\n",
1254  fct, functions[i].argc_max);
1255  return AVERROR(EINVAL);
1256  }
1257  break;
1258  }
1259  if (i >= FF_ARRAY_ELEMS(functions)) {
1260  av_log(ctx, AV_LOG_ERROR, "%%{%s} is not known\n", fct);
1261  return AVERROR(EINVAL);
1262  }
1263  return functions[i].func(ctx, bp, fct, argc, argv, functions[i].tag);
1264 }
1265 
1266 static int expand_function(AVFilterContext *ctx, AVBPrint *bp, char **rtext)
1267 {
1268  const char *text = *rtext;
1269  char *argv[16] = { NULL };
1270  unsigned argc = 0, i;
1271  int ret;
1272 
1273  if (*text != '{') {
1274  av_log(ctx, AV_LOG_ERROR, "Stray %% near '%s'\n", text);
1275  return AVERROR(EINVAL);
1276  }
1277  text++;
1278  while (1) {
1279  if (!(argv[argc++] = av_get_token(&text, ":}"))) {
1280  ret = AVERROR(ENOMEM);
1281  goto end;
1282  }
1283  if (!*text) {
1284  av_log(ctx, AV_LOG_ERROR, "Unterminated %%{} near '%s'\n", *rtext);
1285  ret = AVERROR(EINVAL);
1286  goto end;
1287  }
1288  if (argc == FF_ARRAY_ELEMS(argv))
1289  av_freep(&argv[--argc]); /* error will be caught later */
1290  if (*text == '}')
1291  break;
1292  text++;
1293  }
1294 
1295  if ((ret = eval_function(ctx, bp, argv[0], argc - 1, argv + 1)) < 0)
1296  goto end;
1297  ret = 0;
1298  *rtext = (char *)text + 1;
1299 
1300 end:
1301  for (i = 0; i < argc; i++)
1302  av_freep(&argv[i]);
1303  return ret;
1304 }
1305 
1306 static int expand_text(AVFilterContext *ctx, char *text, AVBPrint *bp)
1307 {
1308  int ret;
1309 
1310  av_bprint_clear(bp);
1311  while (*text) {
1312  if (*text == '\\' && text[1]) {
1313  av_bprint_chars(bp, text[1], 1);
1314  text += 2;
1315  } else if (*text == '%') {
1316  text++;
1317  if ((ret = expand_function(ctx, bp, &text)) < 0)
1318  return ret;
1319  } else {
1320  av_bprint_chars(bp, *text, 1);
1321  text++;
1322  }
1323  }
1324  if (!av_bprint_is_complete(bp))
1325  return AVERROR(ENOMEM);
1326  return 0;
1327 }
1328 
1330  int width, int height,
1331  FFDrawColor *color,
1332  int x, int y, int borderw)
1333 {
1334  char *text = s->expanded_text.str;
1335  uint32_t code = 0;
1336  int i, x1, y1;
1337  uint8_t *p;
1338  Glyph *glyph = NULL;
1339 
1340  for (i = 0, p = text; *p; i++) {
1341  FT_Bitmap bitmap;
1342  Glyph dummy = { 0 };
1343  GET_UTF8(code, *p ? *p++ : 0, code = 0xfffd; goto continue_on_invalid;);
1344 continue_on_invalid:
1345 
1346  /* skip new line chars, just go to new line */
1347  if (code == '\n' || code == '\r' || code == '\t')
1348  continue;
1349 
1350  dummy.code = code;
1351  dummy.fontsize = s->fontsize;
1352  glyph = av_tree_find(s->glyphs, &dummy, glyph_cmp, NULL);
1353 
1354  bitmap = borderw ? glyph->border_bitmap : glyph->bitmap;
1355 
1356  if (glyph->bitmap.pixel_mode != FT_PIXEL_MODE_MONO &&
1357  glyph->bitmap.pixel_mode != FT_PIXEL_MODE_GRAY)
1358  return AVERROR(EINVAL);
1359 
1360  x1 = s->positions[i].x+s->x+x - borderw;
1361  y1 = s->positions[i].y+s->y+y - borderw;
1362 
1363  ff_blend_mask(&s->dc, color,
1364  frame->data, frame->linesize, width, height,
1365  bitmap.buffer, bitmap.pitch,
1366  bitmap.width, bitmap.rows,
1367  bitmap.pixel_mode == FT_PIXEL_MODE_MONO ? 0 : 3,
1368  0, x1, y1);
1369  }
1370 
1371  return 0;
1372 }
1373 
1374 
1376 {
1377  *color = incolor;
1378  color->rgba[3] = (color->rgba[3] * s->alpha) / 255;
1379  ff_draw_color(&s->dc, color, color->rgba);
1380 }
1381 
1383 {
1384  double alpha = av_expr_eval(s->a_pexpr, s->var_values, &s->prng);
1385 
1386  if (isnan(alpha))
1387  return;
1388 
1389  if (alpha >= 1.0)
1390  s->alpha = 255;
1391  else if (alpha <= 0)
1392  s->alpha = 0;
1393  else
1394  s->alpha = 256 * alpha;
1395 }
1396 
1398  int width, int height)
1399 {
1400  DrawTextContext *s = ctx->priv;
1401  AVFilterLink *inlink = ctx->inputs[0];
1402 
1403  uint32_t code = 0, prev_code = 0;
1404  int x = 0, y = 0, i = 0, ret;
1405  int max_text_line_w = 0, len;
1406  int box_w, box_h;
1407  char *text;
1408  uint8_t *p;
1409  int y_min = 32000, y_max = -32000;
1410  int x_min = 32000, x_max = -32000;
1411  FT_Vector delta;
1412  Glyph *glyph = NULL, *prev_glyph = NULL;
1413  Glyph dummy = { 0 };
1414 
1415  time_t now = time(0);
1416  struct tm ltime;
1417  AVBPrint *bp = &s->expanded_text;
1418 
1419  FFDrawColor fontcolor;
1420  FFDrawColor shadowcolor;
1421  FFDrawColor bordercolor;
1422  FFDrawColor boxcolor;
1423 
1424  av_bprint_clear(bp);
1425 
1426  if(s->basetime != AV_NOPTS_VALUE)
1427  now= frame->pts*av_q2d(ctx->inputs[0]->time_base) + s->basetime/1000000;
1428 
1429  switch (s->exp_mode) {
1430  case EXP_NONE:
1431  av_bprintf(bp, "%s", s->text);
1432  break;
1433  case EXP_NORMAL:
1434  if ((ret = expand_text(ctx, s->text, &s->expanded_text)) < 0)
1435  return ret;
1436  break;
1437  case EXP_STRFTIME:
1438  localtime_r(&now, &ltime);
1439  av_bprint_strftime(bp, s->text, &ltime);
1440  break;
1441  }
1442 
1443  if (s->tc_opt_string) {
1444  char tcbuf[AV_TIMECODE_STR_SIZE];
1445  av_timecode_make_string(&s->tc, tcbuf, inlink->frame_count_out);
1446  av_bprint_clear(bp);
1447  av_bprintf(bp, "%s%s", s->text, tcbuf);
1448  }
1449 
1450  if (!av_bprint_is_complete(bp))
1451  return AVERROR(ENOMEM);
1452  text = s->expanded_text.str;
1453  if ((len = s->expanded_text.len) > s->nb_positions) {
1454  if (!(s->positions =
1455  av_realloc(s->positions, len*sizeof(*s->positions))))
1456  return AVERROR(ENOMEM);
1457  s->nb_positions = len;
1458  }
1459 
1460  if (s->fontcolor_expr[0]) {
1461  /* If expression is set, evaluate and replace the static value */
1462  av_bprint_clear(&s->expanded_fontcolor);
1463  if ((ret = expand_text(ctx, s->fontcolor_expr, &s->expanded_fontcolor)) < 0)
1464  return ret;
1465  if (!av_bprint_is_complete(&s->expanded_fontcolor))
1466  return AVERROR(ENOMEM);
1467  av_log(s, AV_LOG_DEBUG, "Evaluated fontcolor is '%s'\n", s->expanded_fontcolor.str);
1468  ret = av_parse_color(s->fontcolor.rgba, s->expanded_fontcolor.str, -1, s);
1469  if (ret)
1470  return ret;
1471  ff_draw_color(&s->dc, &s->fontcolor, s->fontcolor.rgba);
1472  }
1473 
1474  x = 0;
1475  y = 0;
1476 
1477  if ((ret = update_fontsize(ctx)) < 0)
1478  return ret;
1479 
1480  /* load and cache glyphs */
1481  for (i = 0, p = text; *p; i++) {
1482  GET_UTF8(code, *p ? *p++ : 0, code = 0xfffd; goto continue_on_invalid;);
1483 continue_on_invalid:
1484 
1485  /* get glyph */
1486  dummy.code = code;
1487  dummy.fontsize = s->fontsize;
1488  glyph = av_tree_find(s->glyphs, &dummy, glyph_cmp, NULL);
1489  if (!glyph) {
1490  ret = load_glyph(ctx, &glyph, code);
1491  if (ret < 0)
1492  return ret;
1493  }
1494 
1495  y_min = FFMIN(glyph->bbox.yMin, y_min);
1496  y_max = FFMAX(glyph->bbox.yMax, y_max);
1497  x_min = FFMIN(glyph->bbox.xMin, x_min);
1498  x_max = FFMAX(glyph->bbox.xMax, x_max);
1499  }
1500  s->max_glyph_h = y_max - y_min;
1501  s->max_glyph_w = x_max - x_min;
1502 
1503  /* compute and save position for each glyph */
1504  glyph = NULL;
1505  for (i = 0, p = text; *p; i++) {
1506  GET_UTF8(code, *p ? *p++ : 0, code = 0xfffd; goto continue_on_invalid2;);
1507 continue_on_invalid2:
1508 
1509  /* skip the \n in the sequence \r\n */
1510  if (prev_code == '\r' && code == '\n')
1511  continue;
1512 
1513  prev_code = code;
1514  if (is_newline(code)) {
1515 
1516  max_text_line_w = FFMAX(max_text_line_w, x);
1517  y += s->max_glyph_h + s->line_spacing;
1518  x = 0;
1519  continue;
1520  }
1521 
1522  /* get glyph */
1523  prev_glyph = glyph;
1524  dummy.code = code;
1525  dummy.fontsize = s->fontsize;
1526  glyph = av_tree_find(s->glyphs, &dummy, glyph_cmp, NULL);
1527 
1528  /* kerning */
1529  if (s->use_kerning && prev_glyph && glyph->code) {
1530  FT_Get_Kerning(s->face, prev_glyph->code, glyph->code,
1531  ft_kerning_default, &delta);
1532  x += delta.x >> 6;
1533  }
1534 
1535  /* save position */
1536  s->positions[i].x = x + glyph->bitmap_left;
1537  s->positions[i].y = y - glyph->bitmap_top + y_max;
1538  if (code == '\t') x = (x / s->tabsize + 1)*s->tabsize;
1539  else x += glyph->advance;
1540  }
1541 
1542  max_text_line_w = FFMAX(x, max_text_line_w);
1543 
1544  s->var_values[VAR_TW] = s->var_values[VAR_TEXT_W] = max_text_line_w;
1545  s->var_values[VAR_TH] = s->var_values[VAR_TEXT_H] = y + s->max_glyph_h;
1546 
1547  s->var_values[VAR_MAX_GLYPH_W] = s->max_glyph_w;
1548  s->var_values[VAR_MAX_GLYPH_H] = s->max_glyph_h;
1549  s->var_values[VAR_MAX_GLYPH_A] = s->var_values[VAR_ASCENT ] = y_max;
1550  s->var_values[VAR_MAX_GLYPH_D] = s->var_values[VAR_DESCENT] = y_min;
1551 
1552  s->var_values[VAR_LINE_H] = s->var_values[VAR_LH] = s->max_glyph_h;
1553 
1554  if (s->text_source == AV_FRAME_DATA_DETECTION_BBOXES) {
1555  s->var_values[VAR_X] = s->x;
1556  s->var_values[VAR_Y] = s->y;
1557  } else {
1558  s->x = s->var_values[VAR_X] = av_expr_eval(s->x_pexpr, s->var_values, &s->prng);
1559  s->y = s->var_values[VAR_Y] = av_expr_eval(s->y_pexpr, s->var_values, &s->prng);
1560  /* It is necessary if x is expressed from y */
1561  s->x = s->var_values[VAR_X] = av_expr_eval(s->x_pexpr, s->var_values, &s->prng);
1562  }
1563 
1564  update_alpha(s);
1565  update_color_with_alpha(s, &fontcolor , s->fontcolor );
1566  update_color_with_alpha(s, &shadowcolor, s->shadowcolor);
1567  update_color_with_alpha(s, &bordercolor, s->bordercolor);
1568  update_color_with_alpha(s, &boxcolor , s->boxcolor );
1569 
1570  box_w = max_text_line_w;
1571  box_h = y + s->max_glyph_h;
1572 
1573  if (s->fix_bounds) {
1574 
1575  /* calculate footprint of text effects */
1576  int boxoffset = s->draw_box ? FFMAX(s->boxborderw, 0) : 0;
1577  int borderoffset = s->borderw ? FFMAX(s->borderw, 0) : 0;
1578 
1579  int offsetleft = FFMAX3(boxoffset, borderoffset,
1580  (s->shadowx < 0 ? FFABS(s->shadowx) : 0));
1581  int offsettop = FFMAX3(boxoffset, borderoffset,
1582  (s->shadowy < 0 ? FFABS(s->shadowy) : 0));
1583 
1584  int offsetright = FFMAX3(boxoffset, borderoffset,
1585  (s->shadowx > 0 ? s->shadowx : 0));
1586  int offsetbottom = FFMAX3(boxoffset, borderoffset,
1587  (s->shadowy > 0 ? s->shadowy : 0));
1588 
1589 
1590  if (s->x - offsetleft < 0) s->x = offsetleft;
1591  if (s->y - offsettop < 0) s->y = offsettop;
1592 
1593  if (s->x + box_w + offsetright > width)
1594  s->x = FFMAX(width - box_w - offsetright, 0);
1595  if (s->y + box_h + offsetbottom > height)
1596  s->y = FFMAX(height - box_h - offsetbottom, 0);
1597  }
1598 
1599  /* draw box */
1600  if (s->draw_box)
1601  ff_blend_rectangle(&s->dc, &boxcolor,
1602  frame->data, frame->linesize, width, height,
1603  s->x - s->boxborderw, s->y - s->boxborderw,
1604  box_w + s->boxborderw * 2, box_h + s->boxborderw * 2);
1605 
1606  if (s->shadowx || s->shadowy) {
1607  if ((ret = draw_glyphs(s, frame, width, height,
1608  &shadowcolor, s->shadowx, s->shadowy, 0)) < 0)
1609  return ret;
1610  }
1611 
1612  if (s->borderw) {
1613  if ((ret = draw_glyphs(s, frame, width, height,
1614  &bordercolor, 0, 0, s->borderw)) < 0)
1615  return ret;
1616  }
1617  if ((ret = draw_glyphs(s, frame, width, height,
1618  &fontcolor, 0, 0, 0)) < 0)
1619  return ret;
1620 
1621  return 0;
1622 }
1623 
1625 {
1626  AVFilterContext *ctx = inlink->dst;
1627  AVFilterLink *outlink = ctx->outputs[0];
1628  DrawTextContext *s = ctx->priv;
1629  int ret;
1631  const AVDetectionBBox *bbox;
1632  AVFrameSideData *sd;
1633  int loop = 1;
1634 
1635  if (s->text_source == AV_FRAME_DATA_DETECTION_BBOXES) {
1637  if (sd) {
1639  loop = header->nb_bboxes;
1640  } else {
1641  av_log(s, AV_LOG_WARNING, "No detection bboxes.\n");
1642  return ff_filter_frame(outlink, frame);
1643  }
1644  }
1645 
1646  if (s->reload && !(inlink->frame_count_out % s->reload)) {
1647  if ((ret = load_textfile(ctx)) < 0) {
1648  av_frame_free(&frame);
1649  return ret;
1650  }
1651 #if CONFIG_LIBFRIBIDI
1652  if (s->text_shaping)
1653  if ((ret = shape_text(ctx)) < 0) {
1654  av_frame_free(&frame);
1655  return ret;
1656  }
1657 #endif
1658  }
1659 
1660  s->var_values[VAR_N] = inlink->frame_count_out + s->start_number;
1661  s->var_values[VAR_T] = frame->pts == AV_NOPTS_VALUE ?
1662  NAN : frame->pts * av_q2d(inlink->time_base);
1663 
1664  s->var_values[VAR_PICT_TYPE] = frame->pict_type;
1665 #if FF_API_FRAME_PKT
1667  s->var_values[VAR_PKT_POS] = frame->pkt_pos;
1668  s->var_values[VAR_PKT_SIZE] = frame->pkt_size;
1670 #endif
1671 #if FF_API_PKT_DURATION
1673  s->var_values[VAR_PKT_DURATION] = frame->pkt_duration * av_q2d(inlink->time_base);
1674 
1675  if (frame->pkt_duration)
1676  s->var_values[VAR_DURATION] = frame->pkt_duration * av_q2d(inlink->time_base);
1677  else
1679 #endif
1680  s->var_values[VAR_DURATION] = frame->duration * av_q2d(inlink->time_base);
1681 
1682  s->metadata = frame->metadata;
1683 
1684  for (int i = 0; i < loop; i++) {
1685  if (header) {
1686  bbox = av_get_detection_bbox(header, i);
1687  strcpy(s->text, bbox->detect_label);
1688  for (int j = 0; j < bbox->classify_count; j++) {
1689  strcat(s->text, ", ");
1690  strcat(s->text, bbox->classify_labels[j]);
1691  }
1692  s->x = bbox->x;
1693  s->y = bbox->y - s->fontsize;
1694  }
1695  draw_text(ctx, frame, frame->width, frame->height);
1696  }
1697 
1698  av_log(ctx, AV_LOG_DEBUG, "n:%d t:%f text_w:%d text_h:%d x:%d y:%d\n",
1699  (int)s->var_values[VAR_N], s->var_values[VAR_T],
1700  (int)s->var_values[VAR_TEXT_W], (int)s->var_values[VAR_TEXT_H],
1701  s->x, s->y);
1702 
1703  return ff_filter_frame(outlink, frame);
1704 }
1705 
1707  {
1708  .name = "default",
1709  .type = AVMEDIA_TYPE_VIDEO,
1711  .filter_frame = filter_frame,
1712  .config_props = config_input,
1713  },
1714 };
1715 
1717  {
1718  .name = "default",
1719  .type = AVMEDIA_TYPE_VIDEO,
1720  },
1721 };
1722 
1724  .name = "drawtext",
1725  .description = NULL_IF_CONFIG_SMALL("Draw text on top of video frames using libfreetype library."),
1726  .priv_size = sizeof(DrawTextContext),
1727  .priv_class = &drawtext_class,
1728  .init = init,
1729  .uninit = uninit,
1733  .process_command = command,
1735 };
error
static void error(const char *err)
Definition: target_bsf_fuzzer.c:31
DrawTextContext::library
FT_Library library
freetype font library handle
Definition: vf_drawtext.c:199
OFFSET
#define OFFSET(x)
Definition: vf_drawtext.c:226
FF_ENABLE_DEPRECATION_WARNINGS
#define FF_ENABLE_DEPRECATION_WARNINGS
Definition: internal.h:81
fun2_names
static const char *const fun2_names[]
Definition: vf_drawtext.c:106
VAR_N
@ VAR_N
Definition: vf_drawtext.c:132
VAR_TEXT_H
@ VAR_TEXT_H
Definition: vf_drawtext.c:135
VAR_MAIN_H
@ VAR_MAIN_H
Definition: vf_drawtext.c:126
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
drawtext_function::func
int(* func)(AVFilterContext *, AVBPrint *, char *, unsigned, char **, int)
Definition: vf_drawtext.c:1224
AV_BPRINT_SIZE_UNLIMITED
#define AV_BPRINT_SIZE_UNLIMITED
AV_TIMECODE_STR_SIZE
#define AV_TIMECODE_STR_SIZE
Definition: timecode.h:33
FFDrawColor
Definition: drawutils.h:50
name
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default minimum maximum flags name is the option name
Definition: writing_filters.txt:88
VAR_LINE_H
@ VAR_LINE_H
Definition: vf_drawtext.c:125
VAR_Y
@ VAR_Y
Definition: vf_drawtext.c:138
VAR_MAX_GLYPH_H
@ VAR_MAX_GLYPH_H
Definition: vf_drawtext.c:130
av_clip
#define av_clip
Definition: common.h:95
DrawTextContext::a_expr
char * a_expr
Definition: vf_drawtext.c:208
av_bprint_is_complete
static int av_bprint_is_complete(const AVBPrint *buf)
Test if the print buffer is complete (not truncated).
Definition: bprint.h:215
AVERROR
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
opt.h
out
FILE * out
Definition: movenc.c:54
color
Definition: vf_paletteuse.c:509
av_lfg_init
av_cold void av_lfg_init(AVLFG *c, unsigned int seed)
Definition: lfg.c:32
av_bprint_init
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition: bprint.c:69
av_frame_get_side_data
AVFrameSideData * av_frame_get_side_data(const AVFrame *frame, enum AVFrameSideDataType type)
Definition: frame.c:824
ff_vf_drawtext
const AVFilter ff_vf_drawtext
Definition: vf_drawtext.c:1723
filter_frame
static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
Definition: vf_drawtext.c:1624
ff_filter_frame
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:971
func_pts
static int func_pts(AVFilterContext *ctx, AVBPrint *bp, char *fct, unsigned argc, char **argv, int tag)
Definition: vf_drawtext.c:977
av_parse_color
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:356
av_tree_insert
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
DrawTextContext::default_fontsize
unsigned int default_fontsize
default font size to use
Definition: vf_drawtext.c:184
VAR_TW
@ VAR_TW
Definition: vf_drawtext.c:136
VAR_ASCENT
@ VAR_ASCENT
Definition: vf_drawtext.c:128
func_frame_num
static int func_frame_num(AVFilterContext *ctx, AVBPrint *bp, char *fct, unsigned argc, char **argv, int tag)
Definition: vf_drawtext.c:1037
inlink
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
Definition: filter_design.txt:212
DrawTextContext::tc24hmax
int tc24hmax
1 if timecode is wrapped to 24 hours, 0 otherwise
Definition: vf_drawtext.c:215
drawtext_function
Definition: vf_drawtext.c:1220
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:100
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:330
tmp
static uint8_t tmp[11]
Definition: aes_ctr.c:28
DrawTextContext::x
int x
x position to start drawing text
Definition: vf_drawtext.c:175
DrawTextContext::bordercolor
FFDrawColor bordercolor
border color
Definition: vf_drawtext.c:196
AVTreeNode::elem
void * elem
Definition: tree.c:28
DrawTextContext::exp_mode
int exp_mode
expansion mode to use for the text
Definition: vf_drawtext.c:161
VAR_DESCENT
@ VAR_DESCENT
Definition: vf_drawtext.c:129
AVOption
AVOption.
Definition: opt.h:251
b
#define b
Definition: input.c:41
FILTER_QUERY_FUNC
#define FILTER_QUERY_FUNC(func)
Definition: internal.h:171
DrawTextContext::nb_positions
size_t nb_positions
number of elements of positions array
Definition: vf_drawtext.c:173
max
#define max(a, b)
Definition: cuda_runtime.h:33
func_pict_type
static int func_pict_type(AVFilterContext *ctx, AVBPrint *bp, char *fct, unsigned argc, char **argv, int tag)
Definition: vf_drawtext.c:968
AVDictionary
Definition: dict.c:32
DrawTextContext::stroker
FT_Stroker stroker
freetype stroker handle
Definition: vf_drawtext.c:201
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
AVFilter::name
const char * name
Filter name.
Definition: avfilter.h:170
expand_function
static int expand_function(AVFilterContext *ctx, AVBPrint *bp, char **rtext)
Definition: vf_drawtext.c:1266
av_tree_node_alloc
struct AVTreeNode * av_tree_node_alloc(void)
Allocate an AVTreeNode.
Definition: tree.c:34
drawtext_function::name
const char * name
Definition: vf_drawtext.c:1221
VAR_MAX_GLYPH_W
@ VAR_MAX_GLYPH_W
Definition: vf_drawtext.c:131
func_metadata
static int func_metadata(AVFilterContext *ctx, AVBPrint *bp, char *fct, unsigned argc, char **argv, int tag)
Definition: vf_drawtext.c:1046
AVERROR_UNKNOWN
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition: error.h:73
AV_OPT_TYPE_RATIONAL
@ AV_OPT_TYPE_RATIONAL
Definition: opt.h:230
DrawTextContext::prng
AVLFG prng
random
Definition: vf_drawtext.c:211
AVDetectionBBox::y
int y
Definition: detection_bbox.h:32
video.h
VAR_MAIN_W
@ VAR_MAIN_W
Definition: vf_drawtext.c:127
av_strlcatf
size_t av_strlcatf(char *dst, size_t size, const char *fmt,...)
Definition: avstring.c:104
av_tree_enumerate
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
av_get_random_seed
uint32_t av_get_random_seed(void)
Get a seed to use in conjunction with random functions.
Definition: random_seed.c:121
formats.h
DrawTextContext::start_number
int start_number
starting frame number for n/frame_num var
Definition: vf_drawtext.c:217
av_expr_parse
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:685
DrawTextContext::text
uint8_t * text
text to be drawn
Definition: vf_drawtext.c:167
DrawTextContext::expanded_text
AVBPrint expanded_text
used to contain the expanded text
Definition: vf_drawtext.c:168
av_set_options_string
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:1587
VAR_H
@ VAR_H
Definition: vf_drawtext.c:126
DrawTextContext::fontsize
unsigned int fontsize
font size to use
Definition: vf_drawtext.c:183
func_eval_expr
static int func_eval_expr(AVFilterContext *ctx, AVBPrint *bp, char *fct, unsigned argc, char **argv, int tag)
Definition: vf_drawtext.c:1138
DrawTextContext::x_expr
char * x_expr
expression for x position
Definition: vf_drawtext.c:203
positions
const static uint16_t positions[][14][3]
Definition: vf_vectorscope.c:817
AV_DETECTION_BBOX_LABEL_NAME_MAX_SIZE
#define AV_DETECTION_BBOX_LABEL_NAME_MAX_SIZE
Definition: detection_bbox.h:36
DrawTextContext::fontfile
uint8_t * fontfile
font to be used
Definition: vf_drawtext.c:166
av_file_map
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:54
AVDetectionBBox::detect_label
char detect_label[AV_DETECTION_BBOX_LABEL_NAME_MAX_SIZE]
Detect result with confidence.
Definition: detection_bbox.h:41
expansion_mode
expansion_mode
Definition: vf_drawtext.c:153
DrawTextContext::y_pexpr
AVExpr * y_pexpr
parsed expressions for x and y
Definition: vf_drawtext.c:205
fail
#define fail()
Definition: checkasm.h:137
VAR_VARS_NB
@ VAR_VARS_NB
Definition: vf_drawtext.c:150
timecode.h
dummy
int dummy
Definition: motion.c:65
EXP_NONE
@ EXP_NONE
Definition: vf_drawtext.c:154
av_timecode_make_string
char * av_timecode_make_string(const AVTimecode *tc, char *buf, int framenum)
Load timecode string in buf.
Definition: timecode.c:103
is_newline
static int is_newline(uint32_t c)
Definition: vf_drawtext.c:590
gmtime_r
#define gmtime_r
Definition: time_internal.h:34
pts
static int64_t pts
Definition: transcode_aac.c:643
ff_blend_mask
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:534
loop
static int loop
Definition: ffplay.c:335
av_expr_free
void av_expr_free(AVExpr *e)
Free a parsed expression previously created with av_expr_parse().
Definition: eval.c:336
AVFrameSideDataType
AVFrameSideDataType
Definition: frame.h:49
AVFilterPad
A filter pad used for either input or output.
Definition: internal.h:49
FFDIFFSIGN
#define FFDIFFSIGN(x, y)
Comparator.
Definition: macros.h:45
av_get_detection_bbox
static av_always_inline AVDetectionBBox * av_get_detection_bbox(const AVDetectionBBoxHeader *header, unsigned int idx)
Definition: detection_bbox.h:84
DrawTextContext::var_values
double var_values[VAR_VARS_NB]
Definition: vf_drawtext.c:207
GET_UTF8
#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:469
FLAGS
#define FLAGS
Definition: vf_drawtext.c:227
avfilter_vf_drawtext_inputs
static const AVFilterPad avfilter_vf_drawtext_inputs[]
Definition: vf_drawtext.c:1706
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
av_cold
#define av_cold
Definition: attributes.h:90
DrawTextContext::dc
FFDrawContext dc
Definition: vf_drawtext.c:193
ff_set_common_formats
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:770
update_alpha
static void update_alpha(DrawTextContext *s)
Definition: vf_drawtext.c:1382
DrawTextContext::face
FT_Face face
freetype font face handle
Definition: vf_drawtext.c:200
av_dict_get
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:60
width
#define width
s
#define s(width, name)
Definition: cbs_vp9.c:256
update_fontsize
static av_cold int update_fontsize(AVFilterContext *ctx)
Definition: vf_drawtext.c:437
DrawTextContext::y
int y
y position to start drawing text
Definition: vf_drawtext.c:176
VAR_X
@ VAR_X
Definition: vf_drawtext.c:137
av_lfg_get
static unsigned int av_lfg_get(AVLFG *c)
Get the next random unsigned 32-bit number using an ALFG.
Definition: lfg.h:53
VAR_TH
@ VAR_TH
Definition: vf_drawtext.c:135
DrawTextContext::fontcolor
FFDrawColor fontcolor
foreground color
Definition: vf_drawtext.c:194
DrawTextContext::a_pexpr
AVExpr * a_pexpr
Definition: vf_drawtext.c:209
av_q2d
static double av_q2d(AVRational a)
Convert an AVRational to a double.
Definition: rational.h:104
lfg.h
FF_DRAW_PROCESS_ALPHA
#define FF_DRAW_PROCESS_ALPHA
Process alpha pixel component.
Definition: drawutils.h:62
DrawTextContext::boxborderw
int boxborderw
box border width
Definition: vf_drawtext.c:188
AV_OPT_TYPE_INT64
@ AV_OPT_TYPE_INT64
Definition: opt.h:226
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
var_name
var_name
Definition: noise_bsf.c:46
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:201
ctx
AVFormatContext * ctx
Definition: movenc.c:48
av_expr_eval
double av_expr_eval(AVExpr *e, const double *const_values, void *opaque)
Evaluate a previously parsed expression.
Definition: eval.c:766
VAR_SAR
@ VAR_SAR
Definition: vf_drawtext.c:133
AVExpr
Definition: eval.c:157
ff_draw_init
int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags)
Definition: drawutils.c:151
DrawTextContext::fontsize_pexpr
AVExpr * fontsize_pexpr
parsed expressions for fontsize
Definition: vf_drawtext.c:182
eval_func2
double(* eval_func2)(void *, double a, double b)
Definition: vf_drawtext.c:115
ft_error::err
int err
Definition: vf_drawtext.c:301
key
const char * key
Definition: hwcontext_opencl.c:174
VAR_T
@ VAR_T
Definition: vf_drawtext.c:134
NAN
#define NAN
Definition: mathematics.h:115
FILTER_INPUTS
#define FILTER_INPUTS(array)
Definition: internal.h:194
command
static int command(AVFilterContext *ctx, const char *cmd, const char *arg, char *res, int res_len, int flags)
Definition: vf_drawtext.c:921
av_file_unmap
void av_file_unmap(uint8_t *bufptr, size_t size)
Unmap or free the buffer bufptr created by av_file_map().
Definition: file.c:145
text_source_string_parse
static enum AVFrameSideDataType text_source_string_parse(const char *text_source_string)
Definition: vf_drawtext.c:712
arg
const char * arg
Definition: jacosubdec.c:67
FFABS
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
Definition: common.h:64
time_internal.h
VAR_VSUB
@ VAR_VSUB
Definition: vf_drawtext.c:124
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:66
result
and forward the result(frame or status change) to the corresponding input. If nothing is possible
NULL
#define NULL
Definition: coverity.c:32
VAR_PICT_TYPE
@ VAR_PICT_TYPE
Definition: vf_drawtext.c:139
DrawTextContext::basetime
int64_t basetime
base pts time in the real world for display
Definition: vf_drawtext.c:206
AVRational
Rational number (pair of numerator and denominator).
Definition: rational.h:58
AVDetectionBBox::classify_labels
char classify_labels[AV_NUM_DETECTION_BBOX_CLASSIFY][AV_DETECTION_BBOX_LABEL_NAME_MAX_SIZE]
Definition: detection_bbox.h:52
AVDetectionBBoxHeader
Definition: detection_bbox.h:56
DrawTextContext::fontsize_expr
char * fontsize_expr
expression for fontsize
Definition: vf_drawtext.c:181
isnan
#define isnan(x)
Definition: libm.h:340
AV_OPT_TYPE_COLOR
@ AV_OPT_TYPE_COLOR
Definition: opt.h:240
query_formats
static int query_formats(AVFilterContext *ctx)
Definition: vf_drawtext.c:837
draw_text
static int draw_text(AVFilterContext *ctx, AVFrame *frame, int width, int height)
Definition: vf_drawtext.c:1397
parseutils.h
AVTreeNode
Definition: tree.c:26
DrawTextContext::tc_rate
AVRational tc_rate
frame rate for timecode
Definition: vf_drawtext.c:213
DrawTextContext::x_pexpr
AVExpr * x_pexpr
Definition: vf_drawtext.c:205
double
double
Definition: af_crystalizer.c:132
av_parse_time
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:589
time.h
DrawTextContext::positions
FT_Vector * positions
positions for each element in the text
Definition: vf_drawtext.c:172
VAR_MAX_GLYPH_A
@ VAR_MAX_GLYPH_A
Definition: vf_drawtext.c:128
av_bprint_strftime
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
load_font_file
static int load_font_file(AVFilterContext *ctx, const char *path, int index)
Definition: vf_drawtext.c:473
av_tree_destroy
void av_tree_destroy(AVTreeNode *t)
Definition: tree.c:146
DrawTextContext
Definition: vf_drawtext.c:159
DrawTextContext::tabsize
int tabsize
tab size
Definition: vf_drawtext.c:190
index
int index
Definition: gxfenc.c:89
c
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
var_names
static const char *const var_names[]
Definition: vf_drawtext.c:75
DrawTextContext::reload
int reload
reload text file at specified frame interval
Definition: vf_drawtext.c:216
draw_glyphs
static int draw_glyphs(DrawTextContext *s, AVFrame *frame, int width, int height, FFDrawColor *color, int x, int y, int borderw)
Definition: vf_drawtext.c:1329
DrawTextContext::text_source_string
char * text_source_string
the string to specify text data source
Definition: vf_drawtext.c:218
VAR_h
@ VAR_h
Definition: vf_drawtext.c:126
set_fontsize
static av_cold int set_fontsize(AVFilterContext *ctx, unsigned int fontsize)
Definition: vf_drawtext.c:403
uninit
static av_cold void uninit(AVFilterContext *ctx)
Definition: vf_drawtext.c:852
load_font
static int load_font(AVFilterContext *ctx)
Definition: vf_drawtext.c:573
eval.h
AVLFG
Context structure for the Lagged Fibonacci PRNG.
Definition: lfg.h:33
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:114
av_expr_parse_and_eval
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:776
av_bprint_finalize
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition: bprint.c:235
ff_blend_rectangle
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:353
localtime_r
#define localtime_r
Definition: time_internal.h:46
size
int size
Definition: twinvq_data.h:10344
DrawTextContext::draw_box
short int draw_box
draw box around text - true or false
Definition: vf_drawtext.c:187
AV_NOPTS_VALUE
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:248
AVFrameSideData::data
uint8_t * data
Definition: frame.h:238
DrawTextContext::shadowy
int shadowy
Definition: vf_drawtext.c:179
drand
static double drand(void *opaque, double min, double max)
Definition: vf_drawtext.c:110
tree.h
EXP_NORMAL
@ EXP_NORMAL
Definition: vf_drawtext.c:155
header
static const uint8_t header[24]
Definition: sdr2.c:67
diff
static av_always_inline int diff(const struct color_info *a, const struct color_info *b, const int trans_thresh)
Definition: vf_paletteuse.c:162
VAR_TEXT_W
@ VAR_TEXT_W
Definition: vf_drawtext.c:136
AVFILTER_DEFINE_CLASS
AVFILTER_DEFINE_CLASS(drawtext)
expand_text
static int expand_text(AVFilterContext *ctx, char *text, AVBPrint *bp)
Definition: vf_drawtext.c:1306
AVDetectionBBox::classify_count
uint32_t classify_count
Definition: detection_bbox.h:51
av_isdigit
static av_const int av_isdigit(int c)
Locale-independent conversion of ASCII isdigit.
Definition: avstring.h:203
height
#define height
a
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:41
AV_TIMECODE_FLAG_24HOURSMAX
@ AV_TIMECODE_FLAG_24HOURSMAX
timecode wraps after 24 hours
Definition: timecode.h:37
DrawTextContext::expanded_fontcolor
AVBPrint expanded_fontcolor
used to contain the expanded fontcolor spec
Definition: vf_drawtext.c:170
update_color_with_alpha
static void update_color_with_alpha(DrawTextContext *s, FFDrawColor *color, const FFDrawColor incolor)
Definition: vf_drawtext.c:1375
AVERROR_EXTERNAL
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition: error.h:59
VAR_LH
@ VAR_LH
Definition: vf_drawtext.c:125
fun2
static const eval_func2 fun2[]
Definition: vf_drawtext.c:117
AV_LOG_INFO
#define AV_LOG_INFO
Standard information.
Definition: log.h:191
internal.h
AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC
#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:147
av_get_picture_type_char
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:40
glyph_enu_free
static int glyph_enu_free(void *opaque, void *elem)
Definition: vf_drawtext.c:842
bprint.h
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
code
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
Definition: filter_design.txt:178
round
static av_always_inline av_const double round(double x)
Definition: libm.h:444
AV_TIME_BASE
#define AV_TIME_BASE
Internal time base represented as integer.
Definition: avutil.h:254
ff_draw_supported_pixel_formats
AVFilterFormats * ff_draw_supported_pixel_formats(unsigned flags)
Return the list of pixel formats supported by the draw functions.
Definition: drawutils.c:647
av_malloc_array
#define av_malloc_array(a, b)
Definition: tableprint_vlc.h:31
common.h
delta
float delta
Definition: vorbis_enc_data.h:430
DrawTextContext::shadowx
int shadowx
Definition: vf_drawtext.c:179
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
init
static av_cold int init(AVFilterContext *ctx)
Definition: vf_drawtext.c:722
drawtext_function::tag
int tag
opaque argument to func
Definition: vf_drawtext.c:1223
DrawTextContext::max_glyph_h
int max_glyph_h
max glyph height
Definition: vf_drawtext.c:178
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:254
FFDrawContext
Definition: drawutils.h:35
DrawTextContext::borderw
int borderw
border width
Definition: vf_drawtext.c:180
VAR_MAX_GLYPH_D
@ VAR_MAX_GLYPH_D
Definition: vf_drawtext.c:129
len
int len
Definition: vorbis_enc_data.h:426
VAR_W
@ VAR_W
Definition: vf_drawtext.c:127
AVFilterPad::name
const char * name
Pad name.
Definition: internal.h:55
config_input
static int config_input(AVFilterLink *inlink)
Definition: vf_drawtext.c:878
DrawTextContext::use_kerning
int use_kerning
font kerning is used - true/false
Definition: vf_drawtext.c:189
ff_draw_color
void ff_draw_color(FFDrawContext *draw, FFDrawColor *color, const uint8_t rgba[4])
Prepare a color.
Definition: drawutils.c:156
AVFilter
Filter definition.
Definition: avfilter.h:166
DrawTextContext::tc
AVTimecode tc
timecode context
Definition: vf_drawtext.c:214
tag
uint32_t tag
Definition: movenc.c:1709
ret
ret
Definition: filter_design.txt:187
EXP_STRFTIME
@ EXP_STRFTIME
Definition: vf_drawtext.c:156
frame
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
Definition: filter_design.txt:264
av_bprintf
void av_bprintf(AVBPrint *buf, const char *fmt,...)
Definition: bprint.c:94
VAR_HSUB
@ VAR_HSUB
Definition: vf_drawtext.c:124
VAR_DURATION
@ VAR_DURATION
Definition: vf_drawtext.c:149
DrawTextContext::ft_load_flags
int ft_load_flags
flags used for loading fonts, see FT_LOAD_*
Definition: vf_drawtext.c:171
drawtext_function::argc_max
unsigned argc_max
Definition: vf_drawtext.c:1222
random_seed.h
DrawTextContext::alpha
int alpha
Definition: vf_drawtext.c:210
ft_errors
static const struct ft_error ft_errors[]
VAR_w
@ VAR_w
Definition: vf_drawtext.c:127
drawtext_options
static const AVOption drawtext_options[]
Definition: vf_drawtext.c:229
DrawTextContext::shadowcolor
FFDrawColor shadowcolor
shadow color
Definition: vf_drawtext.c:195
eval_function
static int eval_function(AVFilterContext *ctx, AVBPrint *bp, char *fct, unsigned argc, char **argv)
Definition: vf_drawtext.c:1239
DrawTextContext::reinit
int reinit
tells if the filter is being reinited
Definition: vf_drawtext.c:162
func_strftime
static int func_strftime(AVFilterContext *ctx, AVBPrint *bp, char *fct, unsigned argc, char **argv, int tag)
Definition: vf_drawtext.c:1059
func_eval_expr_int_format
static int func_eval_expr_int_format(AVFilterContext *ctx, AVBPrint *bp, char *fct, unsigned argc, char **argv, int tag)
Definition: vf_drawtext.c:1158
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:225
avfilter.h
av_get_token
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:144
av_bprint_clear
void av_bprint_clear(AVBPrint *buf)
Reset the string to "" but keep internal allocated data.
Definition: bprint.c:227
AVDetectionBBox::x
int x
Distance in pixels from the left/top edge of the frame, together with width and height,...
Definition: detection_bbox.h:31
file.h
av_tree_find
void * av_tree_find(const AVTreeNode *t, void *key, int(*cmp)(const void *key, const void *b), void *next[2])
Definition: tree.c:39
AVFilterContext
An instance of a filter.
Definition: avfilter.h:397
av_gettime
int64_t av_gettime(void)
Get the current time in microseconds.
Definition: time.c:39
FF_DISABLE_DEPRECATION_WARNINGS
#define FF_DISABLE_DEPRECATION_WARNINGS
Definition: internal.h:80
av_strdup
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:270
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
DrawTextContext::glyphs
struct AVTreeNode * glyphs
rendered glyphs, stored using the UTF-32 char code
Definition: vf_drawtext.c:202
DrawTextContext::textfile
char * textfile
file with text to be drawn
Definition: vf_drawtext.c:174
load_textfile
static int load_textfile(AVFilterContext *ctx)
Definition: vf_drawtext.c:595
llrint
#define llrint(x)
Definition: libm.h:394
AVFrameSideData
Structure to hold side data for an AVFrame.
Definition: frame.h:236
AV_NUM_DETECTION_BBOX_CLASSIFY
#define AV_NUM_DETECTION_BBOX_CLASSIFY
At most 4 classifications based on the detected bounding box.
Definition: detection_bbox.h:50
functions
static const struct drawtext_function functions[]
av_opt_copy
int av_opt_copy(void *dst, const void *src)
Copy options from src object into dest object.
Definition: opt.c:1885
DrawTextContext::text_source
enum AVFrameSideDataType text_source
Definition: vf_drawtext.c:219
avfilter_vf_drawtext_outputs
static const AVFilterPad avfilter_vf_drawtext_outputs[]
Definition: vf_drawtext.c:1716
av_free
#define av_free(p)
Definition: tableprint_vlc.h:33
AVDictionaryEntry
Definition: dict.h:89
alpha
static const int16_t alpha[]
Definition: ilbcdata.h:55
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Definition: opt.h:244
FILTER_OUTPUTS
#define FILTER_OUTPUTS(array)
Definition: internal.h:195
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
glyph_cmp
static int glyph_cmp(const void *key, const void *b)
Definition: vf_drawtext.c:321
VAR_DAR
@ VAR_DAR
Definition: vf_drawtext.c:123
FFMAX3
#define FFMAX3(a, b, c)
Definition: macros.h:48
DrawTextContext::boxcolor
FFDrawColor boxcolor
background color
Definition: vf_drawtext.c:197
AV_OPT_TYPE_FLAGS
@ AV_OPT_TYPE_FLAGS
Definition: opt.h:224
load_glyph
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:335
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:561
parse_fontsize
static av_cold int parse_fontsize(AVFilterContext *ctx)
Definition: vf_drawtext.c:419
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
AVDetectionBBox
Definition: detection_bbox.h:26
av_bprint_chars
void av_bprint_chars(AVBPrint *buf, char c, unsigned n)
Append char c n times to a print buffer.
Definition: bprint.c:140
av_timecode_init_from_string
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:252
DrawTextContext::metadata
AVDictionary * metadata
Definition: vf_drawtext.c:223
AVDictionaryEntry::value
char * value
Definition: dict.h:91
avstring.h
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Definition: opt.h:229
drawutils.h
ft_error::err_msg
const char * err_msg
Definition: vf_drawtext.c:302
ft_error
Definition: vf_drawtext.c:300
AVTimecode
Definition: timecode.h:41
FT_ERRMSG
#define FT_ERRMSG(e)
DrawTextContext::y_expr
char * y_expr
expression for y position
Definition: vf_drawtext.c:204
int
int
Definition: ffmpeg_filter.c:354
AV_OPT_TYPE_CONST
@ AV_OPT_TYPE_CONST
Definition: opt.h:234
DrawTextContext::line_spacing
int line_spacing
lines spacing in pixels
Definition: vf_drawtext.c:186
drawtext_function::argc_min
unsigned argc_min
Definition: vf_drawtext.c:1222
detection_bbox.h
DrawTextContext::fontcolor_expr
uint8_t * fontcolor_expr
fontcolor expression to evaluate
Definition: vf_drawtext.c:169
AV_FRAME_DATA_DETECTION_BBOXES
@ AV_FRAME_DATA_DETECTION_BBOXES
Bounding boxes for object detection and classification, as described by AVDetectionBBoxHeader.
Definition: frame.h:190
DrawTextContext::max_glyph_w
int max_glyph_w
max glyph width
Definition: vf_drawtext.c:177
DrawTextContext::tc_opt_string
char * tc_opt_string
specified timecode option string
Definition: vf_drawtext.c:212
drawtext
static void drawtext(AVFrame *pic, int x, int y, const char *txt, uint32_t color)
Definition: af_afir.c:49
av_realloc
void * av_realloc(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory.
Definition: mem.c:153
DrawTextContext::fix_bounds
int fix_bounds
do we let it go out of frame bounds - t/f
Definition: vf_drawtext.c:191
min
float min
Definition: vorbis_enc_data.h:429
AVFILTERPAD_FLAG_NEEDS_WRITABLE
#define AVFILTERPAD_FLAG_NEEDS_WRITABLE
The filter expects writable frames from its input link, duplicating data buffers if needed.
Definition: internal.h:68