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