Go to the documentation of this file.
34 #include <sys/types.h>
42 #if CONFIG_LIBFONTCONFIG
43 #include <fontconfig/fontconfig.h>
71 #include FT_FREETYPE_H
81 "max_glyph_a",
"ascent",
82 "max_glyph_d",
"descent",
96 #if FF_API_PKT_DURATION
143 #if FF_API_PKT_DURATION
163 #if CONFIG_LIBFONTCONFIG
220 #if CONFIG_LIBFRIBIDI
226 #define OFFSET(x) offsetof(DrawTextContext, x)
227 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
249 #if CONFIG_LIBFONTCONFIG
266 {
"start_number",
"start frame number for n/frame_num variable",
OFFSET(start_number),
AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX,
FLAGS},
269 #if CONFIG_LIBFRIBIDI
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" },
280 {
"vertical_layout",
NULL, 0,
AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_VERTICAL_LAYOUT }, .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" },
286 {
"ignore_transform",
NULL, 0,
AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_IGNORE_TRANSFORM }, .flags =
FLAGS, .unit =
"ft_load_flags" },
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 } };
306 #define FT_ERRMSG(e) ft_errors[e].err_msg
308 typedef struct Glyph {
310 FT_Glyph border_glyph;
312 unsigned int fontsize;
314 FT_Bitmap border_bitmap;
323 const Glyph *
a =
key, *bb =
b;
324 int64_t
diff = (int64_t)
a->code - (int64_t)bb->code;
327 return diff > 0 ? 1 : -1;
329 return FFDIFFSIGN((int64_t)
a->fontsize, (int64_t)bb->fontsize);
338 FT_BitmapGlyph bitmapglyph;
344 if (FT_Load_Char(
s->face,
code,
s->ft_load_flags))
353 glyph->fontsize =
s->fontsize;
355 if (FT_Get_Glyph(
s->face->glyph, &glyph->glyph)) {
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)) {
366 bitmapglyph = (FT_BitmapGlyph) glyph->border_glyph;
367 glyph->border_bitmap = bitmapglyph->bitmap;
369 if (FT_Glyph_To_Bitmap(&glyph->glyph, FT_RENDER_MODE_NORMAL, 0, 1)) {
373 bitmapglyph = (FT_BitmapGlyph) glyph->glyph;
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;
381 FT_Glyph_Get_CBox(glyph->glyph, ft_glyph_bbox_pixels, &glyph->bbox);
408 if ((err = FT_Set_Pixel_Sizes(
s->face, 0, fontsize))) {
414 s->fontsize = fontsize;
424 if (
s->fontsize_pexpr)
427 if (
s->fontsize_expr ==
NULL)
440 unsigned int fontsize =
s->default_fontsize;
442 double size, roundedsize;
445 if (
s->fontsize_expr !=
NULL) {
454 if (!(roundedsize > INT_MIN && roundedsize < INT_MAX)) {
459 fontsize = roundedsize;
467 if (fontsize ==
s->fontsize)
478 err = FT_New_Face(
s->library, path,
index, &
s->face);
480 #if !CONFIG_LIBFONTCONFIG
489 #if CONFIG_LIBFONTCONFIG
493 FcConfig *fontconfig;
494 FcPattern *pat, *best;
495 FcResult
result = FcResultMatch;
502 fontconfig = FcInitLoadConfigAndFonts();
507 pat = FcNameParse(
s->fontfile ?
s->fontfile :
508 (uint8_t *)(intptr_t)
"default");
514 FcPatternAddString(pat, FC_FAMILY,
s->font);
525 FcPatternAddDouble(pat, FC_SIZE,
size);
528 FcDefaultSubstitute(pat);
530 if (!FcConfigSubstitute(fontconfig, pat, FcMatchPattern)) {
532 FcPatternDestroy(pat);
536 best = FcFontMatch(fontconfig, pat, &
result);
537 FcPatternDestroy(pat);
539 if (!best ||
result != FcResultMatch) {
541 "Cannot find a valid font for the family %s\n",
547 FcPatternGetInteger(best, FC_INDEX, 0, &
index ) != FcResultMatch ||
548 FcPatternGetDouble (best, FC_SIZE, 0, &
size ) != FcResultMatch) {
553 if (FcPatternGetString(best, FC_FILE, 0, &filename) != FcResultMatch) {
561 s->default_fontsize =
size + 0.5;
566 FcConfigDestroy(fontconfig);
568 FcPatternDestroy(best);
582 #if CONFIG_LIBFONTCONFIG
583 err = load_font_fontconfig(
ctx);
592 return c ==
'\n' ||
c ==
'\r' ||
c ==
'\f' ||
c ==
'\v';
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",
610 if (textbuf_size > 0 &&
is_newline(textbuf[textbuf_size - 1]))
612 if (textbuf_size > SIZE_MAX - 1 || !(
tmp =
av_realloc(
s->text, textbuf_size + 1))) {
617 memcpy(
s->text, textbuf, textbuf_size);
618 s->text[textbuf_size] = 0;
624 #if CONFIG_LIBFRIBIDI
630 static const FriBidiFlags
flags = FRIBIDI_FLAGS_DEFAULT |
631 FRIBIDI_FLAGS_ARABIC;
632 FriBidiChar *unicodestr =
NULL;
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;
642 len = strlen(
s->text);
646 len = fribidi_charset_to_unicode(FRIBIDI_CHAR_SET_UTF8,
647 s->text,
len, unicodestr);
654 fribidi_get_bidi_types(unicodestr,
len, bidi_types);
657 if (!embedding_levels) {
661 if (!fribidi_get_par_embedding_levels(bidi_types,
len, &direction,
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);
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,
683 line_start = line_end + 1;
688 for (
i = 0, j = 0;
i <
len;
i++)
689 if (unicodestr[
i] != FRIBIDI_CHAR_FILL)
690 unicodestr[j++] = unicodestr[
i];
699 len = fribidi_unicode_to_charset(FRIBIDI_CHAR_SET_UTF8,
700 unicodestr,
len,
s->text);
715 if (!strcmp(text_source_string,
"side_data_detection_bboxes")) {
729 s->fontsize_pexpr =
NULL;
732 s->default_fontsize = 16;
734 if (!
s->fontfile && !CONFIG_LIBFONTCONFIG) {
742 "Both text and text file provided. Please provide only one\n");
749 if (
s->reload && !
s->textfile)
752 if (
s->tc_opt_string) {
754 s->tc_opt_string,
ctx);
763 if (
s->text_source_string) {
765 if ((
int)
s->text_source < 0) {
784 "Either text, a valid file, a timecode or text source must be provided\n");
788 #if CONFIG_LIBFRIBIDI
790 if ((err = shape_text(
ctx)) < 0)
794 if ((err = FT_Init_FreeType(&(
s->library)))) {
796 "Could not load FreeType: %s\n",
FT_ERRMSG(err));
807 if (FT_Stroker_New(
s->library, &
s->stroker)) {
811 FT_Stroker_Set(
s->stroker,
s->borderw << 6, FT_STROKER_LINECAP_ROUND,
812 FT_STROKER_LINEJOIN_ROUND, 0);
815 s->use_kerning = FT_HAS_KERNING(
s->face);
825 s->tabsize *= glyph->advance;
828 (strchr(
s->text,
'%') || strchr(
s->text,
'\\')))
846 FT_Done_Glyph(glyph->glyph);
847 FT_Done_Glyph(glyph->border_glyph);
861 s->x_pexpr =
s->y_pexpr =
s->a_pexpr =
s->fontsize_pexpr =
NULL;
870 FT_Done_Face(
s->face);
871 FT_Stroker_Done(
s->stroker);
872 FT_Done_FreeType(
s->library);
895 s->var_values[
VAR_HSUB] = 1 <<
s->dc.hsub_max;
896 s->var_values[
VAR_VSUB] = 1 <<
s->dc.vsub_max;
906 s->x_pexpr =
s->y_pexpr =
s->a_pexpr =
NULL;
927 if (!strcmp(cmd,
"reinit")) {
932 new->class = &drawtext_class;
969 char *fct,
unsigned argc,
char **argv,
int tag)
978 char *fct,
unsigned argc,
char **argv,
int tag)
985 fmt = argc >= 1 ? argv[0] :
"flt";
994 if (!strcmp(fmt,
"flt")) {
996 }
else if (!strcmp(fmt,
"hms")) {
1007 if (!strcmp(argv[2],
"24HH")) {
1008 ms %= 24 * 60 * 60 * 1000;
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,
1020 }
else if (!strcmp(fmt,
"localtime") ||
1021 !strcmp(fmt,
"gmtime")) {
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"))
1038 char *fct,
unsigned argc,
char **argv,
int tag)
1047 char *fct,
unsigned argc,
char **argv,
int tag)
1060 char *fct,
unsigned argc,
char **argv,
int tag)
1062 const char *fmt = argc ? argv[0] :
"%Y-%m-%d %H:%M:%S";
1063 const char *fmt_begin = fmt;
1076 now = unow / 1000000;
1077 if (
tag ==
'L' ||
tag ==
'm')
1084 while ((begin = strchr(begin,
'%'))) {
1106 num_digits =
av_clip(*(begin + 1) -
'0', 1, 6);
1107 }
else if (
len > 1) {
1113 div = pow(10, 6 - num_digits);
1115 av_bprintf(&fmt_bp,
"%.*s%0*d", (
int)(begin - fmt_begin), fmt_begin, num_digits, (
int)(unow % 1000000) / div);
1139 char *fct,
unsigned argc,
char **argv,
int tag)
1150 "Expression '%s' for the expr text expansion function is not valid\n",
1159 char *fct,
unsigned argc,
char **argv,
int tag)
1166 char fmt_str[30] =
"%";
1179 "Expression '%s' for the expr text expansion function is not valid\n",
1184 if (!strchr(
"xXdu", argv[1][0])) {
1186 " allowed values: 'x', 'X', 'd', 'u'\n", argv[1][0]);
1194 " to print: '%s'\n", argv[2]);
1199 feclearexcept(FE_ALL_EXCEPT);
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);
1210 av_strlcatf(fmt_str,
sizeof(fmt_str),
"%c", argv[1][0]);
1213 res, argv[0], fmt_str);
1240 unsigned argc,
char **argv)
1268 const char *text = *rtext;
1269 char *argv[16] = {
NULL };
1270 unsigned argc = 0,
i;
1298 *rtext = (
char *)text + 1;
1301 for (
i = 0;
i < argc;
i++)
1312 if (*text ==
'\\' && text[1]) {
1315 }
else if (*text ==
'%') {
1332 int x,
int y,
int borderw)
1334 char *text =
s->expanded_text.str;
1338 Glyph *glyph =
NULL;
1340 for (
i = 0, p = text; *p;
i++) {
1342 Glyph
dummy = { 0 };
1344 continue_on_invalid:
1351 dummy.fontsize =
s->fontsize;
1354 bitmap = borderw ? glyph->border_bitmap : glyph->bitmap;
1356 if (glyph->bitmap.pixel_mode != FT_PIXEL_MODE_MONO &&
1357 glyph->bitmap.pixel_mode != FT_PIXEL_MODE_GRAY)
1360 x1 =
s->positions[
i].x+
s->x+x - borderw;
1361 y1 =
s->positions[
i].y+
s->y+y - borderw;
1365 bitmap.buffer, bitmap.pitch,
1366 bitmap.width, bitmap.rows,
1367 bitmap.pixel_mode == FT_PIXEL_MODE_MONO ? 0 : 3,
1378 color->rgba[3] = (
color->rgba[3] *
s->alpha) / 255;
1391 else if (
alpha <= 0)
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;
1409 int y_min = 32000, y_max = -32000;
1410 int x_min = 32000, x_max = -32000;
1412 Glyph *glyph =
NULL, *prev_glyph =
NULL;
1413 Glyph
dummy = { 0 };
1415 time_t now = time(0);
1417 AVBPrint *bp = &
s->expanded_text;
1427 now=
frame->pts*
av_q2d(
ctx->inputs[0]->time_base) +
s->basetime/1000000;
1429 switch (
s->exp_mode) {
1443 if (
s->tc_opt_string) {
1452 text =
s->expanded_text.str;
1453 if ((
len =
s->expanded_text.len) >
s->nb_positions) {
1454 if (!(
s->positions =
1457 s->nb_positions =
len;
1460 if (
s->fontcolor_expr[0]) {
1481 for (
i = 0, p = text; *p;
i++) {
1483 continue_on_invalid:
1487 dummy.fontsize =
s->fontsize;
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);
1500 s->max_glyph_h = y_max - y_min;
1501 s->max_glyph_w = x_max - x_min;
1505 for (
i = 0, p = text; *p;
i++) {
1507 continue_on_invalid2:
1510 if (prev_code ==
'\r' &&
code ==
'\n')
1516 max_text_line_w =
FFMAX(max_text_line_w, x);
1517 y +=
s->max_glyph_h +
s->line_spacing;
1525 dummy.fontsize =
s->fontsize;
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);
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;
1542 max_text_line_w =
FFMAX(x, max_text_line_w);
1570 box_w = max_text_line_w;
1571 box_h = y +
s->max_glyph_h;
1573 if (
s->fix_bounds) {
1576 int boxoffset =
s->draw_box ?
FFMAX(
s->boxborderw, 0) : 0;
1577 int borderoffset =
s->borderw ?
FFMAX(
s->borderw, 0) : 0;
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));
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));
1590 if (
s->x - offsetleft < 0)
s->x = offsetleft;
1591 if (
s->y - offsettop < 0)
s->y = offsettop;
1593 if (
s->x + box_w + offsetright >
width)
1595 if (
s->y + box_h + offsetbottom >
height)
1603 s->x -
s->boxborderw,
s->y -
s->boxborderw,
1604 box_w +
s->boxborderw * 2, box_h +
s->boxborderw * 2);
1606 if (
s->shadowx ||
s->shadowy) {
1608 &shadowcolor,
s->shadowx,
s->shadowy, 0)) < 0)
1614 &bordercolor, 0, 0,
s->borderw)) < 0)
1618 &fontcolor, 0, 0, 0)) < 0)
1646 if (
s->reload && !(
inlink->frame_count_out %
s->reload)) {
1651 #if CONFIG_LIBFRIBIDI
1652 if (
s->text_shaping)
1653 if ((
ret = shape_text(
ctx)) < 0) {
1660 s->var_values[
VAR_N] =
inlink->frame_count_out +
s->start_number;
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;
1671 #if FF_API_PKT_DURATION
1675 if (
frame->pkt_duration)
1682 s->metadata =
frame->metadata;
1684 for (
int i = 0;
i <
loop;
i++) {
1689 strcat(
s->text,
", ");
1693 s->y = bbox->
y -
s->fontsize;
1725 .description =
NULL_IF_CONFIG_SMALL(
"Draw text on top of video frames using libfreetype library."),
1727 .priv_class = &drawtext_class,
static void error(const char *err)
FT_Library library
freetype font library handle
#define FF_ENABLE_DEPRECATION_WARNINGS
static const char *const fun2_names[]
#define AV_LOG_WARNING
Something somehow does not look correct.
int(* func)(AVFilterContext *, AVBPrint *, char *, unsigned, char **, int)
#define AV_BPRINT_SIZE_UNLIMITED
#define AV_TIMECODE_STR_SIZE
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
static int av_bprint_is_complete(const AVBPrint *buf)
Test if the print buffer is complete (not truncated).
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
av_cold void av_lfg_init(AVLFG *c, unsigned int seed)
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
AVFrameSideData * av_frame_get_side_data(const AVFrame *frame, enum AVFrameSideDataType type)
const AVFilter ff_vf_drawtext
static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
static int func_pts(AVFilterContext *ctx, AVBPrint *bp, char *fct, unsigned argc, char **argv, int tag)
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.
void * av_tree_insert(AVTreeNode **tp, void *key, int(*cmp)(const void *key, const void *b), AVTreeNode **next)
Insert or remove an element.
unsigned int default_fontsize
default font size to use
static int func_frame_num(AVFilterContext *ctx, AVBPrint *bp, char *fct, unsigned argc, char **argv, int tag)
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
int tc24hmax
1 if timecode is wrapped to 24 hours, 0 otherwise
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
This structure describes decoded (raw) audio or video data.
int x
x position to start drawing text
FFDrawColor bordercolor
border color
int exp_mode
expansion mode to use for the text
#define FILTER_QUERY_FUNC(func)
size_t nb_positions
number of elements of positions array
static int func_pict_type(AVFilterContext *ctx, AVBPrint *bp, char *fct, unsigned argc, char **argv, int tag)
FT_Stroker stroker
freetype stroker handle
const char * name
Filter name.
static int expand_function(AVFilterContext *ctx, AVBPrint *bp, char **rtext)
struct AVTreeNode * av_tree_node_alloc(void)
Allocate an AVTreeNode.
static int func_metadata(AVFilterContext *ctx, AVBPrint *bp, char *fct, unsigned argc, char **argv, int tag)
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
A link between two filters.
size_t av_strlcatf(char *dst, size_t size, const char *fmt,...)
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.
uint32_t av_get_random_seed(void)
Get a seed to use in conjunction with random functions.
int start_number
starting frame number for n/frame_num var
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.
uint8_t * text
text to be drawn
AVBPrint expanded_text
used to contain the expanded text
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.
unsigned int fontsize
font size to use
static int func_eval_expr(AVFilterContext *ctx, AVBPrint *bp, char *fct, unsigned argc, char **argv, int tag)
char * x_expr
expression for x position
const static uint16_t positions[][14][3]
#define AV_DETECTION_BBOX_LABEL_NAME_MAX_SIZE
uint8_t * fontfile
font to be used
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...
char detect_label[AV_DETECTION_BBOX_LABEL_NAME_MAX_SIZE]
Detect result with confidence.
AVExpr * y_pexpr
parsed expressions for x and y
char * av_timecode_make_string(const AVTimecode *tc, char *buf, int framenum)
Load timecode string in buf.
static int is_newline(uint32_t c)
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.
void av_expr_free(AVExpr *e)
Free a parsed expression previously created with av_expr_parse().
A filter pad used for either input or output.
#define FFDIFFSIGN(x, y)
Comparator.
static av_always_inline AVDetectionBBox * av_get_detection_bbox(const AVDetectionBBoxHeader *header, unsigned int idx)
double var_values[VAR_VARS_NB]
#define GET_UTF8(val, GET_BYTE, ERROR)
Convert a UTF-8 character (up to 4 bytes) to its 32-bit UCS-4 encoded form.
static const AVFilterPad avfilter_vf_drawtext_inputs[]
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
#define FF_ARRAY_ELEMS(a)
static void update_alpha(DrawTextContext *s)
FT_Face face
freetype font face handle
AVDictionaryEntry * av_dict_get(const AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags)
Get a dictionary entry with matching key.
static av_cold int update_fontsize(AVFilterContext *ctx)
int y
y position to start drawing text
static unsigned int av_lfg_get(AVLFG *c)
Get the next random unsigned 32-bit number using an ALFG.
FFDrawColor fontcolor
foreground color
static double av_q2d(AVRational a)
Convert an AVRational to a double.
#define FF_DRAW_PROCESS_ALPHA
Process alpha pixel component.
int boxborderw
box border width
#define av_assert0(cond)
assert() equivalent, that is always enabled.
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
double av_expr_eval(AVExpr *e, const double *const_values, void *opaque)
Evaluate a previously parsed expression.
int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags)
AVExpr * fontsize_pexpr
parsed expressions for fontsize
double(* eval_func2)(void *, double a, double b)
#define FILTER_INPUTS(array)
static int command(AVFilterContext *ctx, const char *cmd, const char *arg, char *res, int res_len, int flags)
void av_file_unmap(uint8_t *bufptr, size_t size)
Unmap or free the buffer bufptr created by av_file_map().
static enum AVFrameSideDataType text_source_string_parse(const char *text_source_string)
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
Describe the class of an AVClass context structure.
and forward the result(frame or status change) to the corresponding input. If nothing is possible
int64_t basetime
base pts time in the real world for display
Rational number (pair of numerator and denominator).
char classify_labels[AV_NUM_DETECTION_BBOX_CLASSIFY][AV_DETECTION_BBOX_LABEL_NAME_MAX_SIZE]
char * fontsize_expr
expression for fontsize
static int query_formats(AVFilterContext *ctx)
static int draw_text(AVFilterContext *ctx, AVFrame *frame, int width, int height)
AVRational tc_rate
frame rate for timecode
int av_parse_time(int64_t *timeval, const char *timestr, int duration)
Parse timestr and return in *time a corresponding number of microseconds.
FT_Vector * positions
positions for each element in the text
void av_bprint_strftime(AVBPrint *buf, const char *fmt, const struct tm *tm)
Append a formatted date and time to a print buffer.
static int load_font_file(AVFilterContext *ctx, const char *path, int index)
void av_tree_destroy(AVTreeNode *t)
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
static const char *const var_names[]
int reload
reload text file at specified frame interval
static int draw_glyphs(DrawTextContext *s, AVFrame *frame, int width, int height, FFDrawColor *color, int x, int y, int borderw)
char * text_source_string
the string to specify text data source
static av_cold int set_fontsize(AVFilterContext *ctx, unsigned int fontsize)
static av_cold void uninit(AVFilterContext *ctx)
static int load_font(AVFilterContext *ctx)
Context structure for the Lagged Fibonacci PRNG.
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
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.
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
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.
short int draw_box
draw box around text - true or false
#define AV_NOPTS_VALUE
Undefined timestamp value.
static double drand(void *opaque, double min, double max)
static const uint8_t header[24]
static av_always_inline int diff(const struct color_info *a, const struct color_info *b, const int trans_thresh)
AVFILTER_DEFINE_CLASS(drawtext)
static int expand_text(AVFilterContext *ctx, char *text, AVBPrint *bp)
static av_const int av_isdigit(int c)
Locale-independent conversion of ASCII isdigit.
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
@ AV_TIMECODE_FLAG_24HOURSMAX
timecode wraps after 24 hours
AVBPrint expanded_fontcolor
used to contain the expanded fontcolor spec
static void update_color_with_alpha(DrawTextContext *s, FFDrawColor *color, const FFDrawColor incolor)
#define AVERROR_EXTERNAL
Generic error in an external library.
static const eval_func2 fun2[]
#define AV_LOG_INFO
Standard information.
#define AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC
Some filters support a generic "enable" expression option that can be used to enable or disable a fil...
char av_get_picture_type_char(enum AVPictureType pict_type)
Return a single letter to describe the given picture type pict_type.
static int glyph_enu_free(void *opaque, void *elem)
#define i(width, name, range_min, range_max)
and forward the test the status of outputs and forward it to the corresponding return FFERROR_NOT_READY If the filters stores internally one or a few frame for some it can consider them to be part of the FIFO and delay acknowledging a status change accordingly Example code
static av_always_inline av_const double round(double x)
#define AV_TIME_BASE
Internal time base represented as integer.
AVFilterFormats * ff_draw_supported_pixel_formats(unsigned flags)
Return the list of pixel formats supported by the draw functions.
#define av_malloc_array(a, b)
static av_cold int init(AVFilterContext *ctx)
int tag
opaque argument to func
int max_glyph_h
max glyph height
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
const char * name
Pad name.
static int config_input(AVFilterLink *inlink)
int use_kerning
font kerning is used - true/false
void ff_draw_color(FFDrawContext *draw, FFDrawColor *color, const uint8_t rgba[4])
Prepare a color.
AVTimecode tc
timecode context
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
void av_bprintf(AVBPrint *buf, const char *fmt,...)
int ft_load_flags
flags used for loading fonts, see FT_LOAD_*
static const struct ft_error ft_errors[]
static const AVOption drawtext_options[]
FFDrawColor shadowcolor
shadow color
static int eval_function(AVFilterContext *ctx, AVBPrint *bp, char *fct, unsigned argc, char **argv)
int reinit
tells if the filter is being reinited
static int func_strftime(AVFilterContext *ctx, AVBPrint *bp, char *fct, unsigned argc, char **argv, int tag)
static int func_eval_expr_int_format(AVFilterContext *ctx, AVBPrint *bp, char *fct, unsigned argc, char **argv, int tag)
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...
void av_bprint_clear(AVBPrint *buf)
Reset the string to "" but keep internal allocated data.
int x
Distance in pixels from the left/top edge of the frame, together with width and height,...
void * av_tree_find(const AVTreeNode *t, void *key, int(*cmp)(const void *key, const void *b), void *next[2])
int64_t av_gettime(void)
Get the current time in microseconds.
#define FF_DISABLE_DEPRECATION_WARNINGS
char * av_strdup(const char *s)
Duplicate a string.
struct AVTreeNode * glyphs
rendered glyphs, stored using the UTF-32 char code
char * textfile
file with text to be drawn
static int load_textfile(AVFilterContext *ctx)
Structure to hold side data for an AVFrame.
#define AV_NUM_DETECTION_BBOX_CLASSIFY
At most 4 classifications based on the detected bounding box.
static const struct drawtext_function functions[]
int av_opt_copy(void *dst, const void *src)
Copy options from src object into dest object.
enum AVFrameSideDataType text_source
static const AVFilterPad avfilter_vf_drawtext_outputs[]
static const int16_t alpha[]
#define FILTER_OUTPUTS(array)
static int glyph_cmp(const void *key, const void *b)
FFDrawColor boxcolor
background color
static int load_glyph(AVFilterContext *ctx, Glyph **glyph_ptr, uint32_t code)
Load glyphs corresponding to the UTF-32 codepoint code.
#define flags(name, subs,...)
static av_cold int parse_fontsize(AVFilterContext *ctx)
void av_bprint_chars(AVBPrint *buf, char c, unsigned n)
Append char c n times to a print buffer.
int av_timecode_init_from_string(AVTimecode *tc, AVRational rate, const char *str, void *log_ctx)
Parse timecode representation (hh:mm:ss[:;.
char * y_expr
expression for y position
int line_spacing
lines spacing in pixels
uint8_t * fontcolor_expr
fontcolor expression to evaluate
@ AV_FRAME_DATA_DETECTION_BBOXES
Bounding boxes for object detection and classification, as described by AVDetectionBBoxHeader.
int max_glyph_w
max glyph width
char * tc_opt_string
specified timecode option string
static void drawtext(AVFrame *pic, int x, int y, const char *txt, uint32_t color)
void * av_realloc(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory.
int fix_bounds
do we let it go out of frame bounds - t/f
#define AVFILTERPAD_FLAG_NEEDS_WRITABLE
The filter expects writable frames from its input link, duplicating data buffers if needed.