Libav
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 Libav.
7  *
8  * Libav 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  * Libav 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 Libav; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
29 #include "config.h"
30 
31 #include <sys/types.h>
32 #include <sys/time.h>
33 #include <sys/stat.h>
34 #include <time.h>
35 #include <unistd.h>
36 
37 #if CONFIG_LIBFONTCONFIG
38 #include <fontconfig/fontconfig.h>
39 #endif
40 
41 #include "libavutil/colorspace.h"
42 #include "libavutil/common.h"
43 #include "libavutil/file.h"
44 #include "libavutil/eval.h"
45 #include "libavutil/opt.h"
46 #include "libavutil/mathematics.h"
47 #include "libavutil/random_seed.h"
48 #include "libavutil/parseutils.h"
49 #include "libavutil/pixdesc.h"
51 #include "libavutil/tree.h"
52 #include "libavutil/lfg.h"
53 #include "avfilter.h"
54 #include "drawutils.h"
55 #include "formats.h"
56 #include "internal.h"
57 #include "video.h"
58 
59 #include <ft2build.h>
60 #include FT_FREETYPE_H
61 #include FT_GLYPH_H
62 
63 static const char *const var_names[] = {
64  "E",
65  "PHI",
66  "PI",
67  "main_w", "W",
68  "main_h", "H",
69  "text_w", "w",
70  "text_h", "h",
71  "x",
72  "y",
73  "n",
74  "t",
75  NULL
76 };
77 
78 static const char *const fun2_names[] = {
79  "rand"
80 };
81 
82 static double drand(void *opaque, double min, double max)
83 {
84  return min + (max-min) / UINT_MAX * av_lfg_get(opaque);
85 }
86 
87 typedef double (*eval_func2)(void *, double a, double b);
88 
89 static const eval_func2 fun2[] = {
90  drand,
91  NULL
92 };
93 
94 enum var_name {
107 };
108 
109 typedef struct DrawTextContext {
110  const AVClass *class;
111 #if CONFIG_LIBFONTCONFIG
112  uint8_t *font;
113 #endif
119  FT_Vector *positions;
120  size_t nb_positions;
121  char *textfile;
122  int x, y;
123  int w, h;
125  unsigned int fontsize;
135 
136  short int draw_box;
138  int tabsize;
140 
141  FT_Library library;
142  FT_Face face;
143  struct AVTreeNode *glyphs;
144  int hsub, vsub;
146  int pixel_step[4];
149  char *x_expr, *y_expr;
152  char *d_expr;
154  int draw;
155  char *a_expr;
157  int alpha;
160 
161 #define OFFSET(x) offsetof(DrawTextContext, x)
162 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM
163 
164 static const AVOption drawtext_options[]= {
165 #if CONFIG_LIBFONTCONFIG
166  { "font", "Font name", OFFSET(font), AV_OPT_TYPE_STRING, { .str = "Sans" }, .flags = FLAGS },
167 #endif
168  { "fontfile", NULL, OFFSET(fontfile), AV_OPT_TYPE_STRING, .flags = FLAGS },
169  { "text", NULL, OFFSET(text), AV_OPT_TYPE_STRING, .flags = FLAGS },
170  { "textfile", NULL, OFFSET(textfile), AV_OPT_TYPE_STRING, .flags = FLAGS },
171  { "fontcolor", NULL, OFFSET(fontcolor_string), AV_OPT_TYPE_STRING, { .str = "black" }, .flags = FLAGS },
172  { "boxcolor", NULL, OFFSET(boxcolor_string), AV_OPT_TYPE_STRING, { .str = "white" }, .flags = FLAGS },
173  { "shadowcolor", NULL, OFFSET(shadowcolor_string), AV_OPT_TYPE_STRING, { .str = "black" }, .flags = FLAGS },
174  { "box", NULL, OFFSET(draw_box), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS },
175  { "fontsize", NULL, OFFSET(fontsize), AV_OPT_TYPE_INT, { .i64 = 16 }, 1, 1024, FLAGS },
176  { "x", NULL, OFFSET(x_expr), AV_OPT_TYPE_STRING, { .str = "0" }, .flags = FLAGS },
177  { "y", NULL, OFFSET(y_expr), AV_OPT_TYPE_STRING, { .str = "0" }, .flags = FLAGS },
178  { "shadowx", NULL, OFFSET(shadowx), AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, FLAGS },
179  { "shadowy", NULL, OFFSET(shadowy), AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, FLAGS },
180  { "tabsize", NULL, OFFSET(tabsize), AV_OPT_TYPE_INT, { .i64 = 4 }, 0, INT_MAX, FLAGS },
181  { "draw", "if false do not draw", OFFSET(d_expr), AV_OPT_TYPE_STRING, { .str = "1" }, .flags = FLAGS },
182  { "alpha", "apply alpha while rendering", OFFSET(a_expr), AV_OPT_TYPE_STRING, { .str = "1" }, .flags = FLAGS },
183  { "fix_bounds", "if true, check and fix text coords to avoid clipping",
184  OFFSET(fix_bounds), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, FLAGS },
185 
186  /* FT_LOAD_* flags */
187  { "ft_load_flags", "set font loading flags for libfreetype", OFFSET(ft_load_flags), AV_OPT_TYPE_FLAGS, { .i64 = FT_LOAD_DEFAULT | FT_LOAD_RENDER}, 0, INT_MAX, FLAGS, "ft_load_flags" },
188  { "default", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_DEFAULT }, .flags = FLAGS, .unit = "ft_load_flags" },
189  { "no_scale", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_NO_SCALE }, .flags = FLAGS, .unit = "ft_load_flags" },
190  { "no_hinting", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_NO_HINTING }, .flags = FLAGS, .unit = "ft_load_flags" },
191  { "render", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_RENDER }, .flags = FLAGS, .unit = "ft_load_flags" },
192  { "no_bitmap", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_NO_BITMAP }, .flags = FLAGS, .unit = "ft_load_flags" },
193  { "vertical_layout", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_VERTICAL_LAYOUT }, .flags = FLAGS, .unit = "ft_load_flags" },
194  { "force_autohint", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_FORCE_AUTOHINT }, .flags = FLAGS, .unit = "ft_load_flags" },
195  { "crop_bitmap", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_CROP_BITMAP }, .flags = FLAGS, .unit = "ft_load_flags" },
196  { "pedantic", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_PEDANTIC }, .flags = FLAGS, .unit = "ft_load_flags" },
197  { "ignore_global_advance_width", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH }, .flags = FLAGS, .unit = "ft_load_flags" },
198  { "no_recurse", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_NO_RECURSE }, .flags = FLAGS, .unit = "ft_load_flags" },
199  { "ignore_transform", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_IGNORE_TRANSFORM }, .flags = FLAGS, .unit = "ft_load_flags" },
200  { "monochrome", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_MONOCHROME }, .flags = FLAGS, .unit = "ft_load_flags" },
201  { "linear_design", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_LINEAR_DESIGN }, .flags = FLAGS, .unit = "ft_load_flags" },
202  { "no_autohint", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_NO_AUTOHINT }, .flags = FLAGS, .unit = "ft_load_flags" },
203  { NULL},
204 };
205 
206 static const char *drawtext_get_name(void *ctx)
207 {
208  return "drawtext";
209 }
210 
211 static const AVClass drawtext_class = {
212  "DrawTextContext",
214  drawtext_options
215 };
216 
217 #undef __FTERRORS_H__
218 #define FT_ERROR_START_LIST {
219 #define FT_ERRORDEF(e, v, s) { (e), (s) },
220 #define FT_ERROR_END_LIST { 0, NULL } };
221 
222 struct ft_error
223 {
224  int err;
225  const char *err_msg;
226 } static ft_errors[] =
227 #include FT_ERRORS_H
228 
229 #define FT_ERRMSG(e) ft_errors[e].err_msg
230 
231 typedef struct Glyph {
232  FT_Glyph *glyph;
233  uint32_t code;
234  FT_Bitmap bitmap;
235  FT_BBox bbox;
236  int advance;
237  int bitmap_left;
238  int bitmap_top;
239 } Glyph;
240 
241 static int glyph_cmp(void *key, const void *b)
242 {
243  const Glyph *a = key, *bb = b;
244  int64_t diff = (int64_t)a->code - (int64_t)bb->code;
245  return diff > 0 ? 1 : diff < 0 ? -1 : 0;
246 }
247 
251 static int load_glyph(AVFilterContext *ctx, Glyph **glyph_ptr, uint32_t code)
252 {
253  DrawTextContext *s = ctx->priv;
254  Glyph *glyph;
255  struct AVTreeNode *node = NULL;
256  int ret;
257 
258  /* load glyph into s->face->glyph */
259  if (FT_Load_Char(s->face, code, s->ft_load_flags))
260  return AVERROR(EINVAL);
261 
262  /* save glyph */
263  if (!(glyph = av_mallocz(sizeof(*glyph))) ||
264  !(glyph->glyph = av_mallocz(sizeof(*glyph->glyph)))) {
265  ret = AVERROR(ENOMEM);
266  goto error;
267  }
268  glyph->code = code;
269 
270  if (FT_Get_Glyph(s->face->glyph, glyph->glyph)) {
271  ret = AVERROR(EINVAL);
272  goto error;
273  }
274 
275  glyph->bitmap = s->face->glyph->bitmap;
276  glyph->bitmap_left = s->face->glyph->bitmap_left;
277  glyph->bitmap_top = s->face->glyph->bitmap_top;
278  glyph->advance = s->face->glyph->advance.x >> 6;
279 
280  /* measure text height to calculate text_height (or the maximum text height) */
281  FT_Glyph_Get_CBox(*glyph->glyph, ft_glyph_bbox_pixels, &glyph->bbox);
282 
283  /* cache the newly created glyph */
284  if (!(node = av_tree_node_alloc())) {
285  ret = AVERROR(ENOMEM);
286  goto error;
287  }
288  av_tree_insert(&s->glyphs, glyph, glyph_cmp, &node);
289 
290  if (glyph_ptr)
291  *glyph_ptr = glyph;
292  return 0;
293 
294 error:
295  if (glyph)
296  av_freep(&glyph->glyph);
297  av_freep(&glyph);
298  av_freep(&node);
299  return ret;
300 }
301 
303 {
304  DrawTextContext *s = ctx->priv;
305 #if !CONFIG_LIBFONTCONFIG
306  if (!s->fontfile) {
307  av_log(ctx, AV_LOG_ERROR, "No font filename provided\n");
308  return AVERROR(EINVAL);
309  }
310 
311  return 0;
312 #else
313  FcPattern *pat, *best;
314  FcResult result = FcResultMatch;
315 
316  FcBool fc_bool;
317  FcChar8* fc_string;
318  int err = AVERROR(ENOENT);
319 
320  if (s->fontfile)
321  return 0;
322 
323  if (!FcInit())
324  return AVERROR_UNKNOWN;
325 
326  if (!(pat = FcPatternCreate()))
327  return AVERROR(ENOMEM);
328 
329  FcPatternAddString(pat, FC_FAMILY, s->font);
330  FcPatternAddBool(pat, FC_OUTLINE, FcTrue);
331  FcPatternAddDouble(pat, FC_SIZE, (double)s->fontsize);
332 
333  FcDefaultSubstitute(pat);
334 
335  if (!FcConfigSubstitute(NULL, pat, FcMatchPattern)) {
336  FcPatternDestroy(pat);
337  return AVERROR(ENOMEM);
338  }
339 
340  best = FcFontMatch(NULL, pat, &result);
341  FcPatternDestroy(pat);
342 
343  if (!best || result == FcResultNoMatch) {
344  av_log(ctx, AV_LOG_ERROR,
345  "Cannot find a valid font for the family %s\n",
346  s->font);
347  goto fail;
348  }
349 
350  if (FcPatternGetBool(best, FC_OUTLINE, 0, &fc_bool) != FcResultMatch ||
351  !fc_bool) {
352  av_log(ctx, AV_LOG_ERROR, "Outline not available for %s\n",
353  s->font);
354  goto fail;
355  }
356 
357  if (FcPatternGetString(best, FC_FAMILY, 0, &fc_string) != FcResultMatch) {
358  av_log(ctx, AV_LOG_ERROR, "No matches for %s\n",
359  s->font);
360  goto fail;
361  }
362 
363  if (FcPatternGetString(best, FC_FILE, 0, &fc_string) != FcResultMatch) {
364  av_log(ctx, AV_LOG_ERROR, "No file path for %s\n",
365  s->font);
366  goto fail;
367  }
368 
369  s->fontfile = av_strdup(fc_string);
370  if (!s->fontfile)
371  err = AVERROR(ENOMEM);
372  else
373  err = 0;
374 
375 fail:
376  FcPatternDestroy(best);
377  return err;
378 #endif
379 }
380 
382 {
383  int err;
384  DrawTextContext *s = ctx->priv;
385  Glyph *glyph;
386 
387  if ((err = parse_font(ctx)) < 0)
388  return err;
389 
390  if (s->textfile) {
391  uint8_t *textbuf;
392  size_t textbuf_size;
393 
394  if (s->text) {
395  av_log(ctx, AV_LOG_ERROR,
396  "Both text and text file provided. Please provide only one\n");
397  return AVERROR(EINVAL);
398  }
399  if ((err = av_file_map(s->textfile, &textbuf, &textbuf_size, 0, ctx)) < 0) {
400  av_log(ctx, AV_LOG_ERROR,
401  "The text file '%s' could not be read or is empty\n",
402  s->textfile);
403  return err;
404  }
405 
406  if (textbuf_size > SIZE_MAX - 1 ||
407  !(s->text = av_malloc(textbuf_size + 1))) {
408  av_file_unmap(textbuf, textbuf_size);
409  return AVERROR(ENOMEM);
410  }
411  memcpy(s->text, textbuf, textbuf_size);
412  s->text[textbuf_size] = 0;
413  av_file_unmap(textbuf, textbuf_size);
414  }
415 
416  if (!s->text) {
417  av_log(ctx, AV_LOG_ERROR,
418  "Either text or a valid file must be provided\n");
419  return AVERROR(EINVAL);
420  }
421 
422  if ((err = av_parse_color(s->fontcolor_rgba, s->fontcolor_string, -1, ctx))) {
423  av_log(ctx, AV_LOG_ERROR,
424  "Invalid font color '%s'\n", s->fontcolor_string);
425  return err;
426  }
427 
428  if ((err = av_parse_color(s->boxcolor_rgba, s->boxcolor_string, -1, ctx))) {
429  av_log(ctx, AV_LOG_ERROR,
430  "Invalid box color '%s'\n", s->boxcolor_string);
431  return err;
432  }
433 
434  if ((err = av_parse_color(s->shadowcolor_rgba, s->shadowcolor_string, -1, ctx))) {
435  av_log(ctx, AV_LOG_ERROR,
436  "Invalid shadow color '%s'\n", s->shadowcolor_string);
437  return err;
438  }
439 
440  if ((err = FT_Init_FreeType(&(s->library)))) {
441  av_log(ctx, AV_LOG_ERROR,
442  "Could not load FreeType: %s\n", FT_ERRMSG(err));
443  return AVERROR(EINVAL);
444  }
445 
446  /* load the face, and set up the encoding, which is by default UTF-8 */
447  if ((err = FT_New_Face(s->library, s->fontfile, 0, &s->face))) {
448  av_log(ctx, AV_LOG_ERROR, "Could not load fontface from file '%s': %s\n",
449  s->fontfile, FT_ERRMSG(err));
450  return AVERROR(EINVAL);
451  }
452  if ((err = FT_Set_Pixel_Sizes(s->face, 0, s->fontsize))) {
453  av_log(ctx, AV_LOG_ERROR, "Could not set font size to %d pixels: %s\n",
454  s->fontsize, FT_ERRMSG(err));
455  return AVERROR(EINVAL);
456  }
457 
458  s->use_kerning = FT_HAS_KERNING(s->face);
459 
460  /* load the fallback glyph with code 0 */
461  load_glyph(ctx, NULL, 0);
462 
463  /* set the tabsize in pixels */
464  if ((err = load_glyph(ctx, &glyph, ' ') < 0)) {
465  av_log(ctx, AV_LOG_ERROR, "Could not set tabsize.\n");
466  return err;
467  }
468  s->tabsize *= glyph->advance;
469 
470  return 0;
471 }
472 
474 {
475  static const enum AVPixelFormat pix_fmts[] = {
483  };
484 
486  return 0;
487 }
488 
489 static int glyph_enu_free(void *opaque, void *elem)
490 {
491  av_free(elem);
492  return 0;
493 }
494 
496 {
497  DrawTextContext *s = ctx->priv;
498  int i;
499 
500  av_expr_free(s->x_pexpr);
501  av_expr_free(s->y_pexpr);
502  av_expr_free(s->d_pexpr);
503  s->x_pexpr = s->y_pexpr = s->d_pexpr = NULL;
504  av_freep(&s->expanded_text);
505  av_freep(&s->positions);
508  s->glyphs = 0;
509  FT_Done_Face(s->face);
510  FT_Done_FreeType(s->library);
511 
512  for (i = 0; i < 4; i++) {
513  av_freep(&s->box_line[i]);
514  s->pixel_step[i] = 0;
515  }
516 
517 }
518 
519 static inline int is_newline(uint32_t c)
520 {
521  return c == '\n' || c == '\r' || c == '\f' || c == '\v';
522 }
523 
525 {
526  struct tm ltime;
527  time_t now = time(0);
528  uint8_t *buf = s->expanded_text;
529  int buf_size = s->expanded_text_size;
530 
531  if (!buf)
532  buf_size = 2 * strlen(s->text) + 1;
533 
534  localtime_r(&now, &ltime);
535 
536  while ((buf = av_realloc(buf, buf_size))) {
537  *buf = 1;
538  if (strftime(buf, buf_size, s->text, &ltime) != 0 || *buf == 0)
539  break;
540  buf_size *= 2;
541  }
542 
543  if (!buf)
544  return AVERROR(ENOMEM);
545  s->expanded_text = buf;
546  s->expanded_text_size = buf_size;
547 
548  return 0;
549 }
550 
552 {
553  DrawTextContext *s = ctx->priv;
554  uint32_t code = 0, prev_code = 0;
555  int x = 0, y = 0, i = 0, ret;
556  int text_height, baseline;
557  char *text;
558  uint8_t *p;
559  int str_w = 0, len;
560  int y_min = 32000, y_max = -32000;
561  FT_Vector delta;
562  Glyph *glyph = NULL, *prev_glyph = NULL;
563  Glyph dummy = { 0 };
564  int width = ctx->inputs[0]->w;
565  int height = ctx->inputs[0]->h;
566 
567  ret = expand_strftime(s);
568  if (ret < 0)
569  return ret;
570 
571  text = s->expanded_text ? s->expanded_text : s->text;
572 
573  if ((len = strlen(text)) > s->nb_positions) {
574  FT_Vector *p = av_realloc(s->positions,
575  len * sizeof(*s->positions));
576  if (!p) {
577  av_freep(s->positions);
578  s->nb_positions = 0;
579  return AVERROR(ENOMEM);
580  } else {
581  s->positions = p;
582  s->nb_positions = len;
583  }
584  }
585 
586  /* load and cache glyphs */
587  for (i = 0, p = text; *p; i++) {
588  GET_UTF8(code, *p++, continue;);
589 
590  /* get glyph */
591  dummy.code = code;
592  glyph = av_tree_find(s->glyphs, &dummy, glyph_cmp, NULL);
593  if (!glyph) {
594  ret = load_glyph(ctx, &glyph, code);
595  if (ret)
596  return ret;
597  }
598 
599  y_min = FFMIN(glyph->bbox.yMin, y_min);
600  y_max = FFMAX(glyph->bbox.yMax, y_max);
601  }
602  text_height = y_max - y_min;
603  baseline = y_max;
604 
605  /* compute and save position for each glyph */
606  glyph = NULL;
607  for (i = 0, p = text; *p; i++) {
608  GET_UTF8(code, *p++, continue;);
609 
610  /* skip the \n in the sequence \r\n */
611  if (prev_code == '\r' && code == '\n')
612  continue;
613 
614  prev_code = code;
615  if (is_newline(code)) {
616  str_w = FFMAX(str_w, x - s->x);
617  y += text_height;
618  x = 0;
619  continue;
620  }
621 
622  /* get glyph */
623  prev_glyph = glyph;
624  dummy.code = code;
625  glyph = av_tree_find(s->glyphs, &dummy, glyph_cmp, NULL);
626 
627  /* kerning */
628  if (s->use_kerning && prev_glyph && glyph->code) {
629  FT_Get_Kerning(s->face, prev_glyph->code, glyph->code,
630  ft_kerning_default, &delta);
631  x += delta.x >> 6;
632  }
633 
634  if (x + glyph->bbox.xMax >= width) {
635  str_w = FFMAX(str_w, x);
636  y += text_height;
637  x = 0;
638  }
639 
640  /* save position */
641  s->positions[i].x = x + glyph->bitmap_left;
642  s->positions[i].y = y - glyph->bitmap_top + baseline;
643  if (code == '\t') x = (x / s->tabsize + 1)*s->tabsize;
644  else x += glyph->advance;
645  }
646 
647  str_w = FFMIN(width - 1, FFMAX(str_w, x));
648  y = FFMIN(y + text_height, height - 1);
649 
650  s->w = str_w;
651  s->var_values[VAR_TEXT_W] = s->var_values[VAR_TW] = s->w;
652  s->h = y;
653  s->var_values[VAR_TEXT_H] = s->var_values[VAR_TH] = s->h;
654 
655  return 0;
656 }
657 
658 
659 static int config_input(AVFilterLink *inlink)
660 {
661  AVFilterContext *ctx = inlink->dst;
662  DrawTextContext *s = ctx->priv;
663  const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(inlink->format);
664  int ret;
665 
666  s->hsub = pix_desc->log2_chroma_w;
667  s->vsub = pix_desc->log2_chroma_h;
668 
669  s->var_values[VAR_E ] = M_E;
670  s->var_values[VAR_PHI] = M_PHI;
671  s->var_values[VAR_PI ] = M_PI;
672 
673  s->var_values[VAR_MAIN_W] =
674  s->var_values[VAR_MW] = ctx->inputs[0]->w;
675  s->var_values[VAR_MAIN_H] =
676  s->var_values[VAR_MH] = ctx->inputs[0]->h;
677 
678  s->var_values[VAR_X] = 0;
679  s->var_values[VAR_Y] = 0;
680  s->var_values[VAR_T] = NAN;
681 
683 
684  av_expr_free(s->x_pexpr);
685  av_expr_free(s->y_pexpr);
686  av_expr_free(s->d_pexpr);
687  s->x_pexpr = s->y_pexpr = s->d_pexpr = NULL;
688  if ((ret = av_expr_parse(&s->x_pexpr, s->x_expr, var_names,
689  NULL, NULL, fun2_names, fun2, 0, ctx)) < 0 ||
690  (ret = av_expr_parse(&s->y_pexpr, s->y_expr, var_names,
691  NULL, NULL, fun2_names, fun2, 0, ctx)) < 0 ||
692  (ret = av_expr_parse(&s->d_pexpr, s->d_expr, var_names,
693  NULL, NULL, fun2_names, fun2, 0, ctx)) < 0 ||
694  (ret = av_expr_parse(&s->a_pexpr, s->a_expr, var_names,
695  NULL, NULL, fun2_names, fun2, 0, ctx)) < 0)
696  return AVERROR(EINVAL);
697 
698  if ((ret =
700  inlink->w, s->boxcolor,
701  inlink->format, s->boxcolor_rgba,
702  &s->is_packed_rgb, s->rgba_map)) < 0)
703  return ret;
704 
705  if (!s->is_packed_rgb) {
706  uint8_t *rgba = s->fontcolor_rgba;
707  s->fontcolor[0] = RGB_TO_Y_CCIR(rgba[0], rgba[1], rgba[2]);
708  s->fontcolor[1] = RGB_TO_U_CCIR(rgba[0], rgba[1], rgba[2], 0);
709  s->fontcolor[2] = RGB_TO_V_CCIR(rgba[0], rgba[1], rgba[2], 0);
710  s->fontcolor[3] = rgba[3];
711  rgba = s->shadowcolor_rgba;
712  s->shadowcolor[0] = RGB_TO_Y_CCIR(rgba[0], rgba[1], rgba[2]);
713  s->shadowcolor[1] = RGB_TO_U_CCIR(rgba[0], rgba[1], rgba[2], 0);
714  s->shadowcolor[2] = RGB_TO_V_CCIR(rgba[0], rgba[1], rgba[2], 0);
715  s->shadowcolor[3] = rgba[3];
716  }
717 
718  s->draw = 1;
719 
720  return dtext_prepare_text(ctx);
721 }
722 
723 #define GET_BITMAP_VAL(r, c) \
724  bitmap->pixel_mode == FT_PIXEL_MODE_MONO ? \
725  (bitmap->buffer[(r) * bitmap->pitch + ((c)>>3)] & (0x80 >> ((c)&7))) * 255 : \
726  bitmap->buffer[(r) * bitmap->pitch + (c)]
727 
728 #define SET_PIXEL_YUV(frame, yuva_color, val, x, y, hsub, vsub) { \
729  luma_pos = ((x) ) + ((y) ) * frame->linesize[0]; \
730  alpha = yuva_color[3] * alpha_mul * (val) * 129 / 255; \
731  frame->data[0][luma_pos] = (alpha * yuva_color[0] + (255*255*129 - alpha) * frame->data[0][luma_pos] ) >> 23; \
732  if (((x) & ((1<<(hsub)) - 1)) == 0 && ((y) & ((1<<(vsub)) - 1)) == 0) {\
733  chroma_pos1 = ((x) >> (hsub)) + ((y) >> (vsub)) * frame->linesize[1]; \
734  chroma_pos2 = ((x) >> (hsub)) + ((y) >> (vsub)) * frame->linesize[2]; \
735  frame->data[1][chroma_pos1] = (alpha * yuva_color[1] + (255*255*129 - alpha) * frame->data[1][chroma_pos1]) >> 23; \
736  frame->data[2][chroma_pos2] = (alpha * yuva_color[2] + (255*255*129 - alpha) * frame->data[2][chroma_pos2]) >> 23; \
737  }\
738 }
739 
740 static inline int draw_glyph_yuv(AVFrame *frame, FT_Bitmap *bitmap, unsigned int x,
741  unsigned int y, unsigned int width, unsigned int height,
742  const uint8_t yuva_color[4], int hsub, int vsub,
743  int alpha_mul)
744 {
745  int r, c, alpha;
746  unsigned int luma_pos, chroma_pos1, chroma_pos2;
747  uint8_t src_val;
748 
749  for (r = 0; r < bitmap->rows && r+y < height; r++) {
750  for (c = 0; c < bitmap->width && c+x < width; c++) {
751  /* get intensity value in the glyph bitmap (source) */
752  src_val = GET_BITMAP_VAL(r, c);
753  if (!src_val)
754  continue;
755 
756  SET_PIXEL_YUV(frame, yuva_color, src_val, c+x, y+r, hsub, vsub);
757  }
758  }
759 
760  return 0;
761 }
762 
763 #define SET_PIXEL_RGB(frame, rgba_color, val, x, y, pixel_step, r_off, g_off, b_off, a_off) { \
764  p = frame->data[0] + (x) * pixel_step + ((y) * frame->linesize[0]); \
765  alpha = rgba_color[3] * alpha_mul * (val) * 129 / 255; \
766  *(p+r_off) = (alpha * rgba_color[0] + (255*255*129 - alpha) * *(p+r_off)) >> 23; \
767  *(p+g_off) = (alpha * rgba_color[1] + (255*255*129 - alpha) * *(p+g_off)) >> 23; \
768  *(p+b_off) = (alpha * rgba_color[2] + (255*255*129 - alpha) * *(p+b_off)) >> 23; \
769 }
770 
771 static inline int draw_glyph_rgb(AVFrame *frame, FT_Bitmap *bitmap,
772  unsigned int x, unsigned int y,
773  unsigned int width, unsigned int height, int pixel_step,
774  const uint8_t rgba_color[4], const uint8_t rgba_map[4],
775  int alpha_mul)
776 {
777  int r, c, alpha;
778  uint8_t *p;
779  uint8_t src_val;
780 
781  for (r = 0; r < bitmap->rows && r+y < height; r++) {
782  for (c = 0; c < bitmap->width && c+x < width; c++) {
783  /* get intensity value in the glyph bitmap (source) */
784  src_val = GET_BITMAP_VAL(r, c);
785  if (!src_val)
786  continue;
787 
788  SET_PIXEL_RGB(frame, rgba_color, src_val, c+x, y+r, pixel_step,
789  rgba_map[0], rgba_map[1], rgba_map[2], rgba_map[3]);
790  }
791  }
792 
793  return 0;
794 }
795 
796 static inline void drawbox(AVFrame *frame, unsigned int x, unsigned int y,
797  unsigned int width, unsigned int height,
798  uint8_t *line[4], int pixel_step[4], uint8_t color[4],
799  int hsub, int vsub, int is_rgba_packed, uint8_t rgba_map[4],
800  int alpha_mul)
801 {
802  int i, j, alpha;
803 
804  if (color[3] != 0xFF || alpha_mul != 0xFF) {
805  if (is_rgba_packed) {
806  uint8_t *p;
807  for (j = 0; j < height; j++)
808  for (i = 0; i < width; i++)
809  SET_PIXEL_RGB(frame, color, 255, i+x, y+j, pixel_step[0],
810  rgba_map[0], rgba_map[1], rgba_map[2], rgba_map[3]);
811  } else {
812  unsigned int luma_pos, chroma_pos1, chroma_pos2;
813  for (j = 0; j < height; j++)
814  for (i = 0; i < width; i++)
815  SET_PIXEL_YUV(frame, color, 255, i+x, y+j, hsub, vsub);
816  }
817  } else {
818  ff_draw_rectangle(frame->data, frame->linesize,
819  line, pixel_step, hsub, vsub,
820  x, y, width, height);
821  }
822 }
823 
824 static int draw_glyphs(DrawTextContext *s, AVFrame *frame,
825  int width, int height,
826  const uint8_t rgbcolor[4], const uint8_t yuvcolor[4],
827  int x, int y)
828 {
829  char *text = s->expanded_text;
830  uint32_t code = 0;
831  int i;
832  uint8_t *p;
833  Glyph *glyph = NULL;
834 
835  for (i = 0, p = text; *p; i++) {
836  Glyph dummy = { 0 };
837  GET_UTF8(code, *p++, continue;);
838 
839  /* skip new line chars, just go to new line */
840  if (code == '\n' || code == '\r' || code == '\t')
841  continue;
842 
843  dummy.code = code;
844  glyph = av_tree_find(s->glyphs, &dummy, (void *)glyph_cmp, NULL);
845 
846  if (glyph->bitmap.pixel_mode != FT_PIXEL_MODE_MONO &&
847  glyph->bitmap.pixel_mode != FT_PIXEL_MODE_GRAY)
848  return AVERROR(EINVAL);
849 
850  if (s->is_packed_rgb) {
851  draw_glyph_rgb(frame, &glyph->bitmap,
852  s->positions[i].x+x, s->positions[i].y+y, width, height,
853  s->pixel_step[0], rgbcolor, s->rgba_map, s->alpha);
854  } else {
855  draw_glyph_yuv(frame, &glyph->bitmap,
856  s->positions[i].x+x, s->positions[i].y+y, width, height,
857  yuvcolor, s->hsub, s->vsub, s->alpha);
858  }
859  }
860 
861  return 0;
862 }
863 
864 static int draw_text(AVFilterContext *ctx, AVFrame *frame,
865  int width, int height)
866 {
867  DrawTextContext *s = ctx->priv;
868  int ret;
869 
870  /* draw box */
871  if (s->draw_box)
872  drawbox(frame, s->x, s->y, s->w, s->h,
873  s->box_line, s->pixel_step, s->boxcolor,
874  s->hsub, s->vsub, s->is_packed_rgb,
875  s->rgba_map, s->alpha);
876 
877  if (s->shadowx || s->shadowy) {
878  if ((ret = draw_glyphs(s, frame, width, height,
879  s->shadowcolor_rgba,
880  s->shadowcolor,
881  s->x + s->shadowx,
882  s->y + s->shadowy)) < 0)
883  return ret;
884  }
885 
886  if ((ret = draw_glyphs(s, frame, width, height,
887  s->fontcolor_rgba,
888  s->fontcolor,
889  s->x,
890  s->y)) < 0)
891  return ret;
892 
893  return 0;
894 }
895 
896 static inline int normalize_double(int *n, double d)
897 {
898  int ret = 0;
899 
900  if (isnan(d)) {
901  ret = AVERROR(EINVAL);
902  } else if (d > INT_MAX || d < INT_MIN) {
903  *n = d > INT_MAX ? INT_MAX : INT_MIN;
904  ret = AVERROR(EINVAL);
905  } else
906  *n = round(d);
907 
908  return ret;
909 }
910 
912 {
913  double alpha = av_expr_eval(s->a_pexpr, s->var_values, &s->prng);
914 
915  if (isnan(alpha))
916  return;
917 
918  if (alpha >= 1.0)
919  s->alpha = 255;
920  else if (alpha <= 0)
921  s->alpha = 0;
922  else
923  s->alpha = 256 * alpha;
924 }
925 
926 static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
927 {
928  AVFilterContext *ctx = inlink->dst;
929  DrawTextContext *s = ctx->priv;
930  int ret = 0;
931 
932  if ((ret = dtext_prepare_text(ctx)) < 0) {
933  av_log(ctx, AV_LOG_ERROR, "Can't draw text\n");
934  av_frame_free(&frame);
935  return ret;
936  }
937 
938  s->var_values[VAR_T] = frame->pts == AV_NOPTS_VALUE ?
939  NAN : frame->pts * av_q2d(inlink->time_base);
940  s->var_values[VAR_X] =
941  av_expr_eval(s->x_pexpr, s->var_values, &s->prng);
942  s->var_values[VAR_Y] =
943  av_expr_eval(s->y_pexpr, s->var_values, &s->prng);
944  s->var_values[VAR_X] =
945  av_expr_eval(s->x_pexpr, s->var_values, &s->prng);
946 
947  s->draw = av_expr_eval(s->d_pexpr, s->var_values, &s->prng);
948 
949  update_alpha(s);
950 
953 
954  if (s->fix_bounds) {
955  if (s->x < 0) s->x = 0;
956  if (s->y < 0) s->y = 0;
957  if ((unsigned)s->x + (unsigned)s->w > inlink->w)
958  s->x = inlink->w - s->w;
959  if ((unsigned)s->y + (unsigned)s->h > inlink->h)
960  s->y = inlink->h - s->h;
961  }
962 
963  s->x &= ~((1 << s->hsub) - 1);
964  s->y &= ~((1 << s->vsub) - 1);
965 
966  av_log(ctx, AV_LOG_TRACE, "n:%d t:%f x:%d y:%d x+w:%d y+h:%d\n",
967  (int)s->var_values[VAR_N], s->var_values[VAR_T],
968  s->x, s->y, s->x+s->w, s->y+s->h);
969 
970  if (s->draw)
971  draw_text(inlink->dst, frame, frame->width, frame->height);
972 
973  s->var_values[VAR_N] += 1.0;
974 
975  return ff_filter_frame(inlink->dst->outputs[0], frame);
976 }
977 
979  {
980  .name = "default",
981  .type = AVMEDIA_TYPE_VIDEO,
982  .get_video_buffer = ff_null_get_video_buffer,
983  .filter_frame = filter_frame,
984  .config_props = config_input,
985  .needs_writable = 1,
986  },
987  { NULL }
988 };
989 
991  {
992  .name = "default",
993  .type = AVMEDIA_TYPE_VIDEO,
994  },
995  { NULL }
996 };
997 
999  .name = "drawtext",
1000  .description = NULL_IF_CONFIG_SMALL("Draw text on top of video frames using libfreetype library."),
1001  .priv_size = sizeof(DrawTextContext),
1002  .priv_class = &drawtext_class,
1003  .init = init,
1004  .uninit = uninit,
1006 
1007  .inputs = avfilter_vf_drawtext_inputs,
1008  .outputs = avfilter_vf_drawtext_outputs,
1009 };
Definition: lfg.h:25
int draw
set to zero to prevent drawing
Definition: vf_drawtext.c:154
void * av_malloc(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:62
#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:270
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:1768
This structure describes decoded (raw) audio or video data.
Definition: frame.h:140
AVOption.
Definition: opt.h:234
static double drand(void *opaque, double min, double max)
Definition: vf_drawtext.c:82
static const AVOption drawtext_options[]
Definition: vf_drawtext.c:164
unsigned int fontsize
font size to use
Definition: vf_drawtext.c:125
static const char * drawtext_get_name(void *ctx)
Definition: vf_drawtext.c:206
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition: pixfmt.h:64
static const AVFilterPad outputs[]
Definition: af_ashowinfo.c:259
Main libavfilter public API header.
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition: pixfmt.h:61
uint8_t * fontfile
font to be used
Definition: vf_drawtext.c:114
#define FLAGS
Definition: vf_drawtext.c:162
static int draw_glyphs(DrawTextContext *s, AVFrame *frame, int width, int height, const uint8_t rgbcolor[4], const uint8_t yuvcolor[4], int x, int y)
Definition: vf_drawtext.c:824
av_log(ac->avr, AV_LOG_TRACE, "%d samples - audio_convert: %s to %s (%s)\, len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt), use_generic ? ac->func_descr_generic :ac->func_descr)
Various defines for YUV<->RGB conversion.
AVFrame * ff_null_get_video_buffer(AVFilterLink *link, int w, int h)
Definition: video.c:30
static int draw_text(AVFilterContext *ctx, AVFrame *frame, int width, int height)
Definition: vf_drawtext.c:864
static void drawbox(AVFrame *frame, unsigned int x, unsigned int y, unsigned int width, unsigned int height, uint8_t *line[4], int pixel_step[4], uint8_t color[4], int hsub, int vsub, int is_rgba_packed, uint8_t rgba_map[4], int alpha_mul)
Definition: vf_drawtext.c:796
uint8_t * text
text to be drawn
Definition: vf_drawtext.c:115
uint8_t * box_line[4]
line used for filling the box background
Definition: vf_drawtext.c:148
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:492
#define SET_PIXEL_RGB(frame, rgba_color, val, x, y, pixel_step, r_off, g_off, b_off, a_off)
Definition: vf_drawtext.c:763
uint8_t log2_chroma_w
Amount to shift the luma width right to find the chroma width.
Definition: pixdesc.h:91
uint8_t shadowcolor[4]
shadow color
Definition: vf_drawtext.c:131
uint8_t boxcolor_rgba[4]
background color in RGBA
Definition: vf_drawtext.c:133
void av_freep(void *arg)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc() and set the pointer ...
Definition: mem.c:202
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:165
uint8_t fontcolor_rgba[4]
foreground color in RGBA
Definition: vf_drawtext.c:132
struct AVTreeNode * av_tree_node_alloc(void)
Allocate an AVTreeNode.
Definition: tree.c:31
const char * name
Pad name.
Definition: internal.h:41
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:270
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:747
static int draw_glyph_yuv(AVFrame *frame, FT_Bitmap *bitmap, unsigned int x, unsigned int y, unsigned int width, unsigned int height, const uint8_t yuva_color[4], int hsub, int vsub, int alpha_mul)
Definition: vf_drawtext.c:740
static int glyph_enu_free(void *opaque, void *elem)
Definition: vf_drawtext.c:489
void * av_tree_find(const AVTreeNode *t, void *key, int(*cmp)(void *key, const void *b), void *next[2])
Definition: tree.c:36
uint8_t
#define av_cold
Definition: attributes.h:66
float delta
AVOptions.
A tree container.
AVLFG prng
random
Definition: vf_drawtext.c:158
static av_always_inline av_const int isnan(float x)
Definition: libm.h:85
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
Definition: log.h:150
#define b
Definition: input.c:52
FT_Face face
freetype font face handle
Definition: vf_drawtext.c:142
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:211
static av_cold int init(AVFilterContext *ctx)
Definition: vf_drawtext.c:381
Definition: eval.c:128
packed ABGR 8:8:8:8, 32bpp, ABGRABGR...
Definition: pixfmt.h:91
Misc file utilities.
static double av_q2d(AVRational a)
Convert rational to double.
Definition: rational.h:69
static const AVFilterPad avfilter_vf_drawtext_inputs[]
Definition: vf_drawtext.c:978
static av_cold void uninit(AVFilterContext *ctx)
Definition: vf_drawtext.c:495
void 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:389
FT_Vector * positions
positions for each element in the text
Definition: vf_drawtext.c:119
AVExpr * x_pexpr
Definition: vf_drawtext.c:150
void av_tree_destroy(AVTreeNode *t)
Definition: tree.c:143
#define r
Definition: input.c:51
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:305
char * fontcolor_string
font color as string
Definition: vf_drawtext.c:126
A filter pad used for either input or output.
Definition: internal.h:35
uint8_t fontcolor[4]
foreground color
Definition: vf_drawtext.c:129
void * av_tree_insert(AVTreeNode **tp, void *key, int(*cmp)(void *key, const void *b), AVTreeNode **next)
Insert or remove an element.
Definition: tree.c:56
double var_values[VAR_VARS_NB]
Definition: vf_drawtext.c:151
int width
width and height of the video frame
Definition: frame.h:179
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:124
void av_file_unmap(uint8_t *bufptr, size_t size)
Unmap or free the buffer bufptr created by av_file_map().
Definition: file.c:129
void av_free(void *ptr)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc(). ...
Definition: mem.c:190
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:49
uint8_t log2_chroma_h
Amount to shift the luma height right to find the chroma height.
Definition: pixdesc.h:100
#define AVERROR(e)
Definition: error.h:43
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:80
AVExpr * y_pexpr
parsed expressions for x and y
Definition: vf_drawtext.c:150
const char * err_msg
Definition: vf_drawtext.c:225
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:148
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
Definition: pixfmt.h:92
void * priv
private data for use by the filter
Definition: avfilter.h:277
int y
position to start drawing text
Definition: vf_drawtext.c:122
Definition: graph2dot.c:48
static av_always_inline av_const double round(double x)
Definition: libm.h:151
AVExpr * a_pexpr
Definition: vf_drawtext.c:156
static int dtext_prepare_text(AVFilterContext *ctx)
Definition: vf_drawtext.c:551
#define GET_BITMAP_VAL(r, c)
Definition: vf_drawtext.c:723
#define FFMAX(a, b)
Definition: common.h:64
packed ARGB 8:8:8:8, 32bpp, ARGBARGB...
Definition: pixfmt.h:89
#define fail()
Definition: checkasm.h:80
static const char *const fun2_names[]
Definition: vf_drawtext.c:78
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition: pixfmt.h:90
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition: pixfmt.h:63
#define FFMIN(a, b)
Definition: common.h:66
static struct tm * localtime_r(const time_t *clock, struct tm *result)
Definition: time_internal.h:37
#define M_E
Definition: ratecontrol.c:42
AVFormatContext * ctx
Definition: movenc.c:48
packed RGB 8:8:8, 24bpp, BGRBGR...
Definition: pixfmt.h:62
NULL
Definition: eval.c:55
static int width
Definition: utils.c:156
char * boxcolor_string
box color as string
Definition: vf_drawtext.c:127
misc drawing utilities
void av_expr_free(AVExpr *e)
Free a parsed expression previously created with av_expr_parse().
Definition: eval.c:195
char * av_strdup(const char *s)
Duplicate the string s.
Definition: mem.c:219
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:158
size_t expanded_text_size
size in bytes of the expanded_text buffer
Definition: vf_drawtext.c:117
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:80
int pixel_step[4]
distance in bytes between the component of each pixel
Definition: vf_drawtext.c:146
static unsigned int av_lfg_get(AVLFG *c)
Get the next random unsigned 32-bit number using an ALFG.
Definition: lfg.h:38
planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples)
Definition: pixfmt.h:65
Describe the class of an AVClass context structure.
Definition: log.h:34
Filter definition.
Definition: avfilter.h:120
int tabsize
tab size
Definition: vf_drawtext.c:138
static const AVFilterPad inputs[]
Definition: af_ashowinfo.c:248
static const uint8_t color[NB_LEVELS]
Definition: log.c:62
struct AVTreeNode * glyphs
rendered glyphs, stored using the UTF-32 char code
Definition: vf_drawtext.c:143
#define M_PHI
Definition: mathematics.h:34
int h
dimension of the text block
Definition: vf_drawtext.c:123
static int is_newline(uint32_t c)
Definition: vf_drawtext.c:519
const char * name
Filter name.
Definition: avfilter.h:124
av_cold void av_lfg_init(AVLFG *c, unsigned int seed)
Definition: lfg.c:30
misc parsing utilities
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:274
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:257
struct ft_error ft_errors[]
short int draw_box
draw box around text - true or false
Definition: vf_drawtext.c:136
static int config_input(AVFilterLink *inlink)
Definition: vf_drawtext.c:659
#define RGB_TO_U_CCIR(r1, g1, b1, shift)
Definition: colorspace.h:114
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:146
#define RGB_TO_V_CCIR(r1, g1, b1, shift)
Definition: colorspace.h:118
int height
Definition: gxfenc.c:72
uint8_t shadowcolor_rgba[4]
shadow color in RGBA
Definition: vf_drawtext.c:134
static void update_alpha(DrawTextContext *s)
Definition: vf_drawtext.c:911
uint8_t rgba_map[4]
map RGBA offsets to the positions in the packed RGBA format
Definition: vf_drawtext.c:147
static const AVClass drawtext_class
Definition: vf_drawtext.c:211
static const char *const var_names[]
Definition: vf_drawtext.c:63
int use_kerning
font kerning is used - true/false
Definition: vf_drawtext.c:137
static int parse_font(AVFilterContext *ctx)
Definition: vf_drawtext.c:302
int vsub
chroma subsampling values
Definition: vf_drawtext.c:144
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:59
char * shadowcolor_string
shadow color as string
Definition: vf_drawtext.c:128
common internal and external API header
static int glyph_cmp(void *key, const void *b)
Definition: vf_drawtext.c:241
void * av_realloc(void *ptr, size_t size)
Allocate or reallocate a block of memory.
Definition: mem.c:117
static int query_formats(AVFilterContext *ctx)
Definition: vf_drawtext.c:473
FT_Library library
freetype font library handle
Definition: vf_drawtext.c:141
planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
Definition: pixfmt.h:66
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition: error.h:61
double(* eval_func2)(void *, double a, double b)
Definition: vf_drawtext.c:87
static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
Definition: vf_drawtext.c:926
static const AVFilterPad avfilter_vf_drawtext_outputs[]
Definition: vf_drawtext.c:990
AVFilter ff_vf_drawtext
Definition: vf_drawtext.c:998
#define RGB_TO_Y_CCIR(r, g, b)
Definition: colorspace.h:110
#define NAN
Definition: math.h:28
int len
uint8_t * expanded_text
used to contain the strftime()-expanded text
Definition: vf_drawtext.c:116
double av_expr_eval(AVExpr *e, const double *const_values, void *opaque)
Evaluate a previously parsed expression.
Definition: eval.c:542
#define FT_ERRMSG(e)
int ff_fill_line_with_color(uint8_t *line[4], int pixel_step[4], int w, uint8_t dst_color[4], enum AVPixelFormat pix_fmt, uint8_t rgba_color[4], int *is_packed_rgba, uint8_t rgba_map_ptr[4])
Definition: drawutils.c:29
#define OFFSET(x)
Definition: vf_drawtext.c:161
uint8_t boxcolor[4]
background color
Definition: vf_drawtext.c:130
An instance of a filter.
Definition: avfilter.h:262
static const eval_func2 fun2[]
Definition: vf_drawtext.c:89
int height
Definition: frame.h:179
planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
Definition: pixfmt.h:96
int fix_bounds
do we let it go out of frame bounds - t/f
Definition: vf_drawtext.c:139
uint32_t av_get_random_seed(void)
Get random data.
Definition: random_seed.c:95
char * textfile
file with text to be drawn
Definition: vf_drawtext.c:121
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:251
void ff_draw_rectangle(uint8_t *dst[4], int dst_linesize[4], uint8_t *src[4], int pixelstep[4], int hsub, int vsub, int x, int y, int w, int h)
Definition: drawutils.c:82
int ft_load_flags
flags used for loading fonts, see FT_LOAD_*
Definition: vf_drawtext.c:118
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:152
float min
size_t nb_positions
number of elements of positions array
Definition: vf_drawtext.c:120
AVPixelFormat
Pixel format.
Definition: pixfmt.h:57
static int expand_strftime(DrawTextContext *s)
Definition: vf_drawtext.c:524
static int draw_glyph_rgb(AVFrame *frame, FT_Bitmap *bitmap, unsigned int x, unsigned int y, unsigned int width, unsigned int height, int pixel_step, const uint8_t rgba_color[4], const uint8_t rgba_map[4], int alpha_mul)
Definition: vf_drawtext.c:771
void * av_mallocz(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:211
static int normalize_double(int *n, double d)
Definition: vf_drawtext.c:896
var_name
Definition: setpts.c:61
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:235
#define SET_PIXEL_YUV(frame, yuva_color, val, x, y, hsub, vsub)
Definition: vf_drawtext.c:728
void * elem
Definition: tree.c:27
simple arithmetic expression evaluator
AVExpr * d_pexpr
Definition: vf_drawtext.c:153