vf_drawtext.c 70 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918
  1. /*
  2. * Copyright (c) 2023 Francesco Carusi
  3. * Copyright (c) 2011 Stefano Sabatini
  4. * Copyright (c) 2010 S.N. Hemanth Meenakshisundaram
  5. * Copyright (c) 2003 Gustavo Sverzut Barbieri <gsbarbieri@yahoo.com.br>
  6. *
  7. * This file is part of FFmpeg.
  8. *
  9. * FFmpeg is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation; either
  12. * version 2.1 of the License, or (at your option) any later version.
  13. *
  14. * FFmpeg is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with FFmpeg; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. */
  23. /**
  24. * @file
  25. * drawtext filter, based on the original vhook/drawtext.c
  26. * filter by Gustavo Sverzut Barbieri
  27. */
  28. #include "config.h"
  29. #if HAVE_SYS_TIME_H
  30. #include <sys/time.h>
  31. #endif
  32. #include <sys/types.h>
  33. #include <sys/stat.h>
  34. #include <time.h>
  35. #if HAVE_UNISTD_H
  36. #include <unistd.h>
  37. #endif
  38. #include <fenv.h>
  39. #if CONFIG_LIBFONTCONFIG
  40. #include <fontconfig/fontconfig.h>
  41. #endif
  42. #include "libavutil/avstring.h"
  43. #include "libavutil/bprint.h"
  44. #include "libavutil/common.h"
  45. #include "libavutil/eval.h"
  46. #include "libavutil/opt.h"
  47. #include "libavutil/random_seed.h"
  48. #include "libavutil/parseutils.h"
  49. #include "libavutil/time.h"
  50. #include "libavutil/timecode.h"
  51. #include "libavutil/time_internal.h"
  52. #include "libavutil/tree.h"
  53. #include "libavutil/lfg.h"
  54. #include "libavutil/detection_bbox.h"
  55. #include "avfilter.h"
  56. #include "drawutils.h"
  57. #include "formats.h"
  58. #include "internal.h"
  59. #include "textutils.h"
  60. #include "video.h"
  61. #if CONFIG_LIBFRIBIDI
  62. #include <fribidi.h>
  63. #endif
  64. #include <ft2build.h>
  65. #include FT_FREETYPE_H
  66. #include FT_GLYPH_H
  67. #include FT_STROKER_H
  68. #include <hb.h>
  69. #include <hb-ft.h>
  70. // Ceiling operation for positive integers division
  71. #define POS_CEIL(x, y) ((x)/(y) + ((x)%(y) != 0))
  72. static const char *const var_names[] = {
  73. "dar",
  74. "hsub", "vsub",
  75. "line_h", "lh", ///< line height
  76. "main_h", "h", "H", ///< height of the input video
  77. "main_w", "w", "W", ///< width of the input video
  78. "max_glyph_a", "ascent", ///< max glyph ascender
  79. "max_glyph_d", "descent", ///< min glyph descender
  80. "max_glyph_h", ///< max glyph height
  81. "max_glyph_w", ///< max glyph width
  82. "font_a", ///< font-defined ascent
  83. "font_d", ///< font-defined descent
  84. "top_a", ///< max glyph ascender of the top line
  85. "bottom_d", ///< max glyph descender of the bottom line
  86. "n", ///< number of frame
  87. "sar",
  88. "t", ///< timestamp expressed in seconds
  89. "text_h", "th", ///< height of the rendered text
  90. "text_w", "tw", ///< width of the rendered text
  91. "x",
  92. "y",
  93. "pict_type",
  94. #if FF_API_FRAME_PKT
  95. "pkt_pos",
  96. #endif
  97. #if FF_API_FRAME_PKT
  98. "pkt_size",
  99. #endif
  100. "duration",
  101. NULL
  102. };
  103. static const char *const fun2_names[] = {
  104. "rand"
  105. };
  106. static double drand(void *opaque, double min, double max)
  107. {
  108. return min + (max-min) / UINT_MAX * av_lfg_get(opaque);
  109. }
  110. typedef double (*eval_func2)(void *, double a, double b);
  111. static const eval_func2 fun2[] = {
  112. drand,
  113. NULL
  114. };
  115. enum var_name {
  116. VAR_DAR,
  117. VAR_HSUB, VAR_VSUB,
  118. VAR_LINE_H, VAR_LH,
  119. VAR_MAIN_H, VAR_h, VAR_H,
  120. VAR_MAIN_W, VAR_w, VAR_W,
  121. VAR_MAX_GLYPH_A, VAR_ASCENT,
  122. VAR_MAX_GLYPH_D, VAR_DESCENT,
  123. VAR_MAX_GLYPH_H,
  124. VAR_MAX_GLYPH_W,
  125. VAR_FONT_A,
  126. VAR_FONT_D,
  127. VAR_TOP_A,
  128. VAR_BOTTOM_D,
  129. VAR_N,
  130. VAR_SAR,
  131. VAR_T,
  132. VAR_TEXT_H, VAR_TH,
  133. VAR_TEXT_W, VAR_TW,
  134. VAR_X,
  135. VAR_Y,
  136. VAR_PICT_TYPE,
  137. #if FF_API_FRAME_PKT
  138. VAR_PKT_POS,
  139. #endif
  140. #if FF_API_FRAME_PKT
  141. VAR_PKT_SIZE,
  142. #endif
  143. VAR_DURATION,
  144. VAR_VARS_NB
  145. };
  146. enum expansion_mode {
  147. EXP_NONE,
  148. EXP_NORMAL,
  149. EXP_STRFTIME,
  150. };
  151. enum y_alignment {
  152. YA_TEXT,
  153. YA_BASELINE,
  154. YA_FONT,
  155. };
  156. enum text_alignment {
  157. TA_LEFT = (1 << 0),
  158. TA_RIGHT = (1 << 1),
  159. TA_TOP = (1 << 2),
  160. TA_BOTTOM = (1 << 3),
  161. };
  162. typedef struct HarfbuzzData {
  163. hb_buffer_t* buf;
  164. hb_font_t* font;
  165. unsigned int glyph_count;
  166. hb_glyph_info_t* glyph_info;
  167. hb_glyph_position_t* glyph_pos;
  168. } HarfbuzzData;
  169. /** Information about a single glyph in a text line */
  170. typedef struct GlyphInfo {
  171. uint32_t code; ///< the glyph code point
  172. int x; ///< the x position of the glyph
  173. int y; ///< the y position of the glyph
  174. int shift_x64; ///< the horizontal shift of the glyph in 26.6 units
  175. int shift_y64; ///< the vertical shift of the glyph in 26.6 units
  176. } GlyphInfo;
  177. /** Information about a single line of text */
  178. typedef struct TextLine {
  179. int offset_left64; ///< offset between the origin and
  180. /// the leftmost pixel of the first glyph
  181. int offset_right64; ///< maximum offset between the origin and
  182. /// the rightmost pixel of the last glyph
  183. int width64; ///< width of the line
  184. HarfbuzzData hb_data; ///< libharfbuzz data of this text line
  185. GlyphInfo* glyphs; ///< array of glyphs in this text line
  186. int cluster_offset; ///< the offset at which this line begins
  187. } TextLine;
  188. /** A glyph as loaded and rendered using libfreetype */
  189. typedef struct Glyph {
  190. FT_Glyph glyph;
  191. FT_Glyph border_glyph;
  192. uint32_t code;
  193. unsigned int fontsize;
  194. /** Glyph bitmaps with 1/4 pixel precision in both directions */
  195. FT_BitmapGlyph bglyph[16];
  196. /** Outlined glyph bitmaps with 1/4 pixel precision in both directions */
  197. FT_BitmapGlyph border_bglyph[16];
  198. FT_BBox bbox;
  199. } Glyph;
  200. /** Global text metrics */
  201. typedef struct TextMetrics {
  202. int offset_top64; ///< ascender amount of the first line (in 26.6 units)
  203. int offset_bottom64; ///< descender amount of the last line (in 26.6 units)
  204. int offset_left64; ///< maximum offset between the origin and
  205. /// the leftmost pixel of the first glyph
  206. /// of each line (in 26.6 units)
  207. int offset_right64; ///< maximum offset between the origin and
  208. /// the rightmost pixel of the last glyph
  209. /// of each line (in 26.6 units)
  210. int line_height64; ///< the font-defined line height
  211. int width; ///< width of the longest line - ceil(width64/64)
  212. int height; ///< total height of the text - ceil(height64/64)
  213. int min_y64; ///< minimum value of bbox.yMin among glyphs (in 26.6 units)
  214. int max_y64; ///< maximum value of bbox.yMax among glyphs (in 26.6 units)
  215. int min_x64; ///< minimum value of bbox.xMin among glyphs (in 26.6 units)
  216. int max_x64; ///< maximum value of bbox.xMax among glyphs (in 26.6 units)
  217. // Position of the background box (without borders)
  218. int rect_x; ///< x position of the box
  219. int rect_y; ///< y position of the box
  220. } TextMetrics;
  221. typedef struct DrawTextContext {
  222. const AVClass *class;
  223. int exp_mode; ///< expansion mode to use for the text
  224. FFExpandTextContext expand_text; ///< expand text in case exp_mode == NORMAL
  225. int reinit; ///< tells if the filter is being reinited
  226. #if CONFIG_LIBFONTCONFIG
  227. uint8_t *font; ///< font to be used
  228. #endif
  229. uint8_t *fontfile; ///< font to be used
  230. uint8_t *text; ///< text to be drawn
  231. AVBPrint expanded_text; ///< used to contain the expanded text
  232. uint8_t *fontcolor_expr; ///< fontcolor expression to evaluate
  233. AVBPrint expanded_fontcolor; ///< used to contain the expanded fontcolor spec
  234. int ft_load_flags; ///< flags used for loading fonts, see FT_LOAD_*
  235. char *textfile; ///< file with text to be drawn
  236. double x; ///< x position to start drawing text
  237. double y; ///< y position to start drawing text
  238. int max_glyph_w; ///< max glyph width
  239. int max_glyph_h; ///< max glyph height
  240. int shadowx, shadowy;
  241. int borderw; ///< border width
  242. char *fontsize_expr; ///< expression for fontsize
  243. AVExpr *fontsize_pexpr; ///< parsed expressions for fontsize
  244. unsigned int fontsize; ///< font size to use
  245. unsigned int default_fontsize; ///< default font size to use
  246. int line_spacing; ///< lines spacing in pixels
  247. short int draw_box; ///< draw box around text - true or false
  248. char *boxborderw; ///< box border width (padding)
  249. /// allowed formats: "all", "vert|oriz", "top|right|bottom|left"
  250. int bb_top; ///< the size of the top box border
  251. int bb_right; ///< the size of the right box border
  252. int bb_bottom; ///< the size of the bottom box border
  253. int bb_left; ///< the size of the left box border
  254. int box_width; ///< the width of box
  255. int box_height; ///< the height of box
  256. int tabsize; ///< tab size
  257. int fix_bounds; ///< do we let it go out of frame bounds - t/f
  258. FFDrawContext dc;
  259. FFDrawColor fontcolor; ///< foreground color
  260. FFDrawColor shadowcolor; ///< shadow color
  261. FFDrawColor bordercolor; ///< border color
  262. FFDrawColor boxcolor; ///< background color
  263. FT_Library library; ///< freetype font library handle
  264. FT_Face face; ///< freetype font face handle
  265. FT_Stroker stroker; ///< freetype stroker handle
  266. struct AVTreeNode *glyphs; ///< rendered glyphs, stored using the UTF-32 char code
  267. char *x_expr; ///< expression for x position
  268. char *y_expr; ///< expression for y position
  269. AVExpr *x_pexpr, *y_pexpr; ///< parsed expressions for x and y
  270. int64_t basetime; ///< base pts time in the real world for display
  271. double var_values[VAR_VARS_NB];
  272. char *a_expr;
  273. AVExpr *a_pexpr;
  274. int alpha;
  275. AVLFG prng; ///< random
  276. char *tc_opt_string; ///< specified timecode option string
  277. AVRational tc_rate; ///< frame rate for timecode
  278. AVTimecode tc; ///< timecode context
  279. int tc24hmax; ///< 1 if timecode is wrapped to 24 hours, 0 otherwise
  280. int reload; ///< reload text file at specified frame interval
  281. int start_number; ///< starting frame number for n/frame_num var
  282. char *text_source_string; ///< the string to specify text data source
  283. enum AVFrameSideDataType text_source;
  284. #if CONFIG_LIBFRIBIDI
  285. int text_shaping; ///< 1 to shape the text before drawing it
  286. #endif
  287. AVDictionary *metadata;
  288. int boxw; ///< the value of the boxw parameter
  289. int boxh; ///< the value of the boxh parameter
  290. int text_align; ///< the horizontal and vertical text alignment
  291. int y_align; ///< the value of the y_align parameter
  292. TextLine *lines; ///< computed information about text lines
  293. int line_count; ///< the number of text lines
  294. uint32_t *tab_clusters; ///< the position of tab characters in the text
  295. int tab_count; ///< the number of tab characters
  296. int blank_advance64; ///< the size of the space character
  297. int tab_warning_printed; ///< ensure the tab warning to be printed only once
  298. } DrawTextContext;
  299. #define OFFSET(x) offsetof(DrawTextContext, x)
  300. #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
  301. #define TFLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM
  302. static const AVOption drawtext_options[]= {
  303. {"fontfile", "set font file", OFFSET(fontfile), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS},
  304. {"text", "set text", OFFSET(text), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, TFLAGS},
  305. {"textfile", "set text file", OFFSET(textfile), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS},
  306. {"fontcolor", "set foreground color", OFFSET(fontcolor.rgba), AV_OPT_TYPE_COLOR, {.str="black"}, 0, 0, TFLAGS},
  307. {"fontcolor_expr", "set foreground color expression", OFFSET(fontcolor_expr), AV_OPT_TYPE_STRING, {.str=""}, 0, 0, FLAGS},
  308. {"boxcolor", "set box color", OFFSET(boxcolor.rgba), AV_OPT_TYPE_COLOR, {.str="white"}, 0, 0, TFLAGS},
  309. {"bordercolor", "set border color", OFFSET(bordercolor.rgba), AV_OPT_TYPE_COLOR, {.str="black"}, 0, 0, TFLAGS},
  310. {"shadowcolor", "set shadow color", OFFSET(shadowcolor.rgba), AV_OPT_TYPE_COLOR, {.str="black"}, 0, 0, TFLAGS},
  311. {"box", "set box", OFFSET(draw_box), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, TFLAGS},
  312. {"boxborderw", "set box borders width", OFFSET(boxborderw), AV_OPT_TYPE_STRING, {.str="0"}, 0, 0, TFLAGS},
  313. {"line_spacing", "set line spacing in pixels", OFFSET(line_spacing), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, TFLAGS},
  314. {"fontsize", "set font size", OFFSET(fontsize_expr), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, TFLAGS},
  315. {"text_align", "set text alignment", OFFSET(text_align), AV_OPT_TYPE_FLAGS, {.i64=0}, 0, (TA_LEFT|TA_RIGHT|TA_TOP|TA_BOTTOM), TFLAGS, .unit = "text_align"},
  316. { "left", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TA_LEFT }, .flags = TFLAGS, .unit = "text_align" },
  317. { "L", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TA_LEFT }, .flags = TFLAGS, .unit = "text_align" },
  318. { "right", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TA_RIGHT }, .flags = TFLAGS, .unit = "text_align" },
  319. { "R", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TA_RIGHT }, .flags = TFLAGS, .unit = "text_align" },
  320. { "center", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = (TA_LEFT|TA_RIGHT) }, .flags = TFLAGS, .unit = "text_align" },
  321. { "C", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = (TA_LEFT|TA_RIGHT) }, .flags = TFLAGS, .unit = "text_align" },
  322. { "top", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TA_TOP }, .flags = TFLAGS, .unit = "text_align" },
  323. { "T", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TA_TOP }, .flags = TFLAGS, .unit = "text_align" },
  324. { "bottom", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TA_BOTTOM }, .flags = TFLAGS, .unit = "text_align" },
  325. { "B", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TA_BOTTOM }, .flags = TFLAGS, .unit = "text_align" },
  326. { "middle", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = (TA_TOP|TA_BOTTOM) }, .flags = TFLAGS, .unit = "text_align" },
  327. { "M", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = (TA_TOP|TA_BOTTOM) }, .flags = TFLAGS, .unit = "text_align" },
  328. {"x", "set x expression", OFFSET(x_expr), AV_OPT_TYPE_STRING, {.str="0"}, 0, 0, TFLAGS},
  329. {"y", "set y expression", OFFSET(y_expr), AV_OPT_TYPE_STRING, {.str="0"}, 0, 0, TFLAGS},
  330. {"boxw", "set box width", OFFSET(boxw), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, TFLAGS},
  331. {"boxh", "set box height", OFFSET(boxh), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, TFLAGS},
  332. {"shadowx", "set shadow x offset", OFFSET(shadowx), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, TFLAGS},
  333. {"shadowy", "set shadow y offset", OFFSET(shadowy), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, TFLAGS},
  334. {"borderw", "set border width", OFFSET(borderw), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, TFLAGS},
  335. {"tabsize", "set tab size", OFFSET(tabsize), AV_OPT_TYPE_INT, {.i64=4}, 0, INT_MAX, TFLAGS},
  336. {"basetime", "set base time", OFFSET(basetime), AV_OPT_TYPE_INT64, {.i64=AV_NOPTS_VALUE}, INT64_MIN, INT64_MAX, FLAGS},
  337. #if CONFIG_LIBFONTCONFIG
  338. { "font", "Font name", OFFSET(font), AV_OPT_TYPE_STRING, { .str = "Sans" }, .flags = FLAGS },
  339. #endif
  340. {"expansion", "set the expansion mode", OFFSET(exp_mode), AV_OPT_TYPE_INT, {.i64=EXP_NORMAL}, 0, 2, FLAGS, .unit = "expansion"},
  341. {"none", "set no expansion", OFFSET(exp_mode), AV_OPT_TYPE_CONST, {.i64=EXP_NONE}, 0, 0, FLAGS, .unit = "expansion"},
  342. {"normal", "set normal expansion", OFFSET(exp_mode), AV_OPT_TYPE_CONST, {.i64=EXP_NORMAL}, 0, 0, FLAGS, .unit = "expansion"},
  343. {"strftime", "set strftime expansion (deprecated)", OFFSET(exp_mode), AV_OPT_TYPE_CONST, {.i64=EXP_STRFTIME}, 0, 0, FLAGS, .unit = "expansion"},
  344. {"y_align", "set the y alignment", OFFSET(y_align), AV_OPT_TYPE_INT, {.i64=YA_TEXT}, 0, 2, TFLAGS, .unit = "y_align"},
  345. {"text", "y is referred to the top of the first text line", OFFSET(y_align), AV_OPT_TYPE_CONST, {.i64=YA_TEXT}, 0, 0, FLAGS, .unit = "y_align"},
  346. {"baseline", "y is referred to the baseline of the first line", OFFSET(y_align), AV_OPT_TYPE_CONST, {.i64=YA_BASELINE}, 0, 0, FLAGS, .unit = "y_align"},
  347. {"font", "y is referred to the font defined line metrics", OFFSET(y_align), AV_OPT_TYPE_CONST, {.i64=YA_FONT}, 0, 0, FLAGS, .unit = "y_align"},
  348. {"timecode", "set initial timecode", OFFSET(tc_opt_string), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS},
  349. {"tc24hmax", "set 24 hours max (timecode only)", OFFSET(tc24hmax), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
  350. {"timecode_rate", "set rate (timecode only)", OFFSET(tc_rate), AV_OPT_TYPE_RATIONAL, {.dbl=0}, 0, INT_MAX, FLAGS},
  351. {"r", "set rate (timecode only)", OFFSET(tc_rate), AV_OPT_TYPE_RATIONAL, {.dbl=0}, 0, INT_MAX, FLAGS},
  352. {"rate", "set rate (timecode only)", OFFSET(tc_rate), AV_OPT_TYPE_RATIONAL, {.dbl=0}, 0, INT_MAX, FLAGS},
  353. {"reload", "reload text file at specified frame interval", OFFSET(reload), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS},
  354. {"alpha", "apply alpha while rendering", OFFSET(a_expr), AV_OPT_TYPE_STRING, {.str = "1"}, .flags = TFLAGS},
  355. {"fix_bounds", "check and fix text coords to avoid clipping", OFFSET(fix_bounds), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
  356. {"start_number", "start frame number for n/frame_num variable", OFFSET(start_number), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS},
  357. {"text_source", "the source of text", OFFSET(text_source_string), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 1, FLAGS },
  358. #if CONFIG_LIBFRIBIDI
  359. {"text_shaping", "attempt to shape text before drawing", OFFSET(text_shaping), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS},
  360. #endif
  361. /* FT_LOAD_* flags */
  362. { "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, .unit = "ft_load_flags" },
  363. { "default", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_DEFAULT }, .flags = FLAGS, .unit = "ft_load_flags" },
  364. { "no_scale", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_NO_SCALE }, .flags = FLAGS, .unit = "ft_load_flags" },
  365. { "no_hinting", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_NO_HINTING }, .flags = FLAGS, .unit = "ft_load_flags" },
  366. { "render", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_RENDER }, .flags = FLAGS, .unit = "ft_load_flags" },
  367. { "no_bitmap", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_NO_BITMAP }, .flags = FLAGS, .unit = "ft_load_flags" },
  368. { "vertical_layout", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_VERTICAL_LAYOUT }, .flags = FLAGS, .unit = "ft_load_flags" },
  369. { "force_autohint", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_FORCE_AUTOHINT }, .flags = FLAGS, .unit = "ft_load_flags" },
  370. { "crop_bitmap", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_CROP_BITMAP }, .flags = FLAGS, .unit = "ft_load_flags" },
  371. { "pedantic", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_PEDANTIC }, .flags = FLAGS, .unit = "ft_load_flags" },
  372. { "ignore_global_advance_width", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH }, .flags = FLAGS, .unit = "ft_load_flags" },
  373. { "no_recurse", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_NO_RECURSE }, .flags = FLAGS, .unit = "ft_load_flags" },
  374. { "ignore_transform", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_IGNORE_TRANSFORM }, .flags = FLAGS, .unit = "ft_load_flags" },
  375. { "monochrome", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_MONOCHROME }, .flags = FLAGS, .unit = "ft_load_flags" },
  376. { "linear_design", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_LINEAR_DESIGN }, .flags = FLAGS, .unit = "ft_load_flags" },
  377. { "no_autohint", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FT_LOAD_NO_AUTOHINT }, .flags = FLAGS, .unit = "ft_load_flags" },
  378. { NULL }
  379. };
  380. AVFILTER_DEFINE_CLASS(drawtext);
  381. #undef __FTERRORS_H__
  382. #define FT_ERROR_START_LIST {
  383. #define FT_ERRORDEF(e, v, s) { (e), (s) },
  384. #define FT_ERROR_END_LIST { 0, NULL } };
  385. static const struct ft_error {
  386. int err;
  387. const char *err_msg;
  388. } ft_errors[] =
  389. #include FT_ERRORS_H
  390. #define FT_ERRMSG(e) ft_errors[e].err_msg
  391. static int glyph_cmp(const void *key, const void *b)
  392. {
  393. const Glyph *a = key, *bb = b;
  394. int64_t diff = (int64_t)a->code - (int64_t)bb->code;
  395. if (diff != 0)
  396. return diff > 0 ? 1 : -1;
  397. else
  398. return FFDIFFSIGN((int64_t)a->fontsize, (int64_t)bb->fontsize);
  399. }
  400. static av_cold int set_fontsize(AVFilterContext *ctx, unsigned int fontsize)
  401. {
  402. int err;
  403. DrawTextContext *s = ctx->priv;
  404. if ((err = FT_Set_Pixel_Sizes(s->face, 0, fontsize))) {
  405. av_log(ctx, AV_LOG_ERROR, "Could not set font size to %d pixels: %s\n",
  406. fontsize, FT_ERRMSG(err));
  407. return AVERROR(EINVAL);
  408. }
  409. s->fontsize = fontsize;
  410. return 0;
  411. }
  412. static av_cold int parse_fontsize(AVFilterContext *ctx)
  413. {
  414. DrawTextContext *s = ctx->priv;
  415. int err;
  416. if (s->fontsize_pexpr)
  417. return 0;
  418. if (s->fontsize_expr == NULL)
  419. return AVERROR(EINVAL);
  420. if ((err = av_expr_parse(&s->fontsize_pexpr, s->fontsize_expr, var_names,
  421. NULL, NULL, fun2_names, fun2, 0, ctx)) < 0)
  422. return err;
  423. return 0;
  424. }
  425. static av_cold int update_fontsize(AVFilterContext *ctx)
  426. {
  427. DrawTextContext *s = ctx->priv;
  428. unsigned int fontsize = s->default_fontsize;
  429. int err;
  430. double size, roundedsize;
  431. // if no fontsize specified use the default
  432. if (s->fontsize_expr != NULL) {
  433. if ((err = parse_fontsize(ctx)) < 0)
  434. return err;
  435. size = av_expr_eval(s->fontsize_pexpr, s->var_values, &s->prng);
  436. if (!isnan(size)) {
  437. roundedsize = round(size);
  438. // test for overflow before cast
  439. if (!(roundedsize > INT_MIN && roundedsize < INT_MAX)) {
  440. av_log(ctx, AV_LOG_ERROR, "fontsize overflow\n");
  441. return AVERROR(EINVAL);
  442. }
  443. fontsize = roundedsize;
  444. }
  445. }
  446. if (fontsize == 0)
  447. fontsize = 1;
  448. // no change
  449. if (fontsize == s->fontsize)
  450. return 0;
  451. return set_fontsize(ctx, fontsize);
  452. }
  453. static int load_font_file(AVFilterContext *ctx, const char *path, int index)
  454. {
  455. DrawTextContext *s = ctx->priv;
  456. int err;
  457. err = FT_New_Face(s->library, path, index, &s->face);
  458. if (err) {
  459. #if !CONFIG_LIBFONTCONFIG
  460. av_log(ctx, AV_LOG_ERROR, "Could not load font \"%s\": %s\n",
  461. s->fontfile, FT_ERRMSG(err));
  462. #endif
  463. return AVERROR(EINVAL);
  464. }
  465. return 0;
  466. }
  467. #if CONFIG_LIBFONTCONFIG
  468. static int load_font_fontconfig(AVFilterContext *ctx)
  469. {
  470. DrawTextContext *s = ctx->priv;
  471. FcConfig *fontconfig;
  472. FcPattern *pat, *best;
  473. FcResult result = FcResultMatch;
  474. FcChar8 *filename;
  475. int index;
  476. double size;
  477. int err = AVERROR(ENOENT);
  478. int parse_err;
  479. fontconfig = FcInitLoadConfigAndFonts();
  480. if (!fontconfig) {
  481. av_log(ctx, AV_LOG_ERROR, "impossible to init fontconfig\n");
  482. return AVERROR_UNKNOWN;
  483. }
  484. pat = FcNameParse(s->fontfile ? s->fontfile :
  485. (uint8_t *)(intptr_t)"default");
  486. if (!pat) {
  487. av_log(ctx, AV_LOG_ERROR, "could not parse fontconfig pat");
  488. return AVERROR(EINVAL);
  489. }
  490. FcPatternAddString(pat, FC_FAMILY, s->font);
  491. parse_err = parse_fontsize(ctx);
  492. if (!parse_err) {
  493. double size = av_expr_eval(s->fontsize_pexpr, s->var_values, &s->prng);
  494. if (isnan(size)) {
  495. av_log(ctx, AV_LOG_ERROR, "impossible to find font information");
  496. return AVERROR(EINVAL);
  497. }
  498. FcPatternAddDouble(pat, FC_SIZE, size);
  499. }
  500. FcDefaultSubstitute(pat);
  501. if (!FcConfigSubstitute(fontconfig, pat, FcMatchPattern)) {
  502. av_log(ctx, AV_LOG_ERROR, "could not substitue fontconfig options"); /* very unlikely */
  503. FcPatternDestroy(pat);
  504. return AVERROR(ENOMEM);
  505. }
  506. best = FcFontMatch(fontconfig, pat, &result);
  507. FcPatternDestroy(pat);
  508. if (!best || result != FcResultMatch) {
  509. av_log(ctx, AV_LOG_ERROR,
  510. "Cannot find a valid font for the family %s\n",
  511. s->font);
  512. goto fail;
  513. }
  514. if (
  515. FcPatternGetInteger(best, FC_INDEX, 0, &index ) != FcResultMatch ||
  516. FcPatternGetDouble (best, FC_SIZE, 0, &size ) != FcResultMatch) {
  517. av_log(ctx, AV_LOG_ERROR, "impossible to find font information");
  518. return AVERROR(EINVAL);
  519. }
  520. if (FcPatternGetString(best, FC_FILE, 0, &filename) != FcResultMatch) {
  521. av_log(ctx, AV_LOG_ERROR, "No file path for %s\n",
  522. s->font);
  523. goto fail;
  524. }
  525. av_log(ctx, AV_LOG_VERBOSE, "Using \"%s\"\n", filename);
  526. if (parse_err)
  527. s->default_fontsize = size + 0.5;
  528. err = load_font_file(ctx, filename, index);
  529. if (err)
  530. return err;
  531. FcConfigDestroy(fontconfig);
  532. fail:
  533. FcPatternDestroy(best);
  534. return err;
  535. }
  536. #endif
  537. static int load_font(AVFilterContext *ctx)
  538. {
  539. DrawTextContext *s = ctx->priv;
  540. int err;
  541. /* load the face, and set up the encoding, which is by default UTF-8 */
  542. err = load_font_file(ctx, s->fontfile, 0);
  543. if (!err)
  544. return 0;
  545. #if CONFIG_LIBFONTCONFIG
  546. err = load_font_fontconfig(ctx);
  547. if (!err)
  548. return 0;
  549. #endif
  550. return err;
  551. }
  552. #if CONFIG_LIBFRIBIDI
  553. static int shape_text(AVFilterContext *ctx)
  554. {
  555. DrawTextContext *s = ctx->priv;
  556. uint8_t *tmp;
  557. int ret = AVERROR(ENOMEM);
  558. static const FriBidiFlags flags = FRIBIDI_FLAGS_DEFAULT |
  559. FRIBIDI_FLAGS_ARABIC;
  560. FriBidiChar *unicodestr = NULL;
  561. FriBidiStrIndex len;
  562. FriBidiParType direction = FRIBIDI_PAR_LTR;
  563. FriBidiStrIndex line_start = 0;
  564. FriBidiStrIndex line_end = 0;
  565. FriBidiLevel *embedding_levels = NULL;
  566. FriBidiArabicProp *ar_props = NULL;
  567. FriBidiCharType *bidi_types = NULL;
  568. FriBidiStrIndex i,j;
  569. len = strlen(s->text);
  570. if (!(unicodestr = av_malloc_array(len, sizeof(*unicodestr)))) {
  571. goto out;
  572. }
  573. len = fribidi_charset_to_unicode(FRIBIDI_CHAR_SET_UTF8,
  574. s->text, len, unicodestr);
  575. bidi_types = av_malloc_array(len, sizeof(*bidi_types));
  576. if (!bidi_types) {
  577. goto out;
  578. }
  579. fribidi_get_bidi_types(unicodestr, len, bidi_types);
  580. embedding_levels = av_malloc_array(len, sizeof(*embedding_levels));
  581. if (!embedding_levels) {
  582. goto out;
  583. }
  584. if (!fribidi_get_par_embedding_levels(bidi_types, len, &direction,
  585. embedding_levels)) {
  586. goto out;
  587. }
  588. ar_props = av_malloc_array(len, sizeof(*ar_props));
  589. if (!ar_props) {
  590. goto out;
  591. }
  592. fribidi_get_joining_types(unicodestr, len, ar_props);
  593. fribidi_join_arabic(bidi_types, len, embedding_levels, ar_props);
  594. fribidi_shape(flags, embedding_levels, len, ar_props, unicodestr);
  595. for (line_end = 0, line_start = 0; line_end < len; line_end++) {
  596. if (ff_is_newline(unicodestr[line_end]) || line_end == len - 1) {
  597. if (!fribidi_reorder_line(flags, bidi_types,
  598. line_end - line_start + 1, line_start,
  599. direction, embedding_levels, unicodestr,
  600. NULL)) {
  601. goto out;
  602. }
  603. line_start = line_end + 1;
  604. }
  605. }
  606. /* Remove zero-width fill chars put in by libfribidi */
  607. for (i = 0, j = 0; i < len; i++)
  608. if (unicodestr[i] != FRIBIDI_CHAR_FILL)
  609. unicodestr[j++] = unicodestr[i];
  610. len = j;
  611. if (!(tmp = av_realloc(s->text, (len * 4 + 1) * sizeof(*s->text)))) {
  612. /* Use len * 4, as a unicode character can be up to 4 bytes in UTF-8 */
  613. goto out;
  614. }
  615. s->text = tmp;
  616. len = fribidi_unicode_to_charset(FRIBIDI_CHAR_SET_UTF8,
  617. unicodestr, len, s->text);
  618. ret = 0;
  619. out:
  620. av_free(unicodestr);
  621. av_free(embedding_levels);
  622. av_free(ar_props);
  623. av_free(bidi_types);
  624. return ret;
  625. }
  626. #endif
  627. static enum AVFrameSideDataType text_source_string_parse(const char *text_source_string)
  628. {
  629. av_assert0(text_source_string);
  630. if (!strcmp(text_source_string, "side_data_detection_bboxes")) {
  631. return AV_FRAME_DATA_DETECTION_BBOXES;
  632. } else {
  633. return AVERROR(EINVAL);
  634. }
  635. }
  636. static inline int get_subpixel_idx(int shift_x64, int shift_y64)
  637. {
  638. int idx = (shift_x64 >> 2) + (shift_y64 >> 4);
  639. return idx;
  640. }
  641. // Loads and (optionally) renders a glyph
  642. static int load_glyph(AVFilterContext *ctx, Glyph **glyph_ptr, uint32_t code, int8_t shift_x64, int8_t shift_y64)
  643. {
  644. DrawTextContext *s = ctx->priv;
  645. Glyph dummy = { 0 };
  646. Glyph *glyph;
  647. FT_Vector shift;
  648. struct AVTreeNode *node = NULL;
  649. int ret = 0;
  650. /* get glyph */
  651. dummy.code = code;
  652. dummy.fontsize = s->fontsize;
  653. glyph = av_tree_find(s->glyphs, &dummy, glyph_cmp, NULL);
  654. if (!glyph) {
  655. if (FT_Load_Glyph(s->face, code, s->ft_load_flags)) {
  656. return AVERROR(EINVAL);
  657. }
  658. glyph = av_mallocz(sizeof(*glyph));
  659. if (!glyph) {
  660. ret = AVERROR(ENOMEM);
  661. goto error;
  662. }
  663. glyph->code = code;
  664. glyph->fontsize = s->fontsize;
  665. if (FT_Get_Glyph(s->face->glyph, &glyph->glyph)) {
  666. ret = AVERROR(EINVAL);
  667. goto error;
  668. }
  669. if (s->borderw) {
  670. glyph->border_glyph = glyph->glyph;
  671. if (FT_Glyph_StrokeBorder(&glyph->border_glyph, s->stroker, 0, 0)) {
  672. ret = AVERROR_EXTERNAL;
  673. goto error;
  674. }
  675. }
  676. /* measure text height to calculate text_height (or the maximum text height) */
  677. FT_Glyph_Get_CBox(glyph->glyph, FT_GLYPH_BBOX_SUBPIXELS, &glyph->bbox);
  678. /* cache the newly created glyph */
  679. if (!(node = av_tree_node_alloc())) {
  680. ret = AVERROR(ENOMEM);
  681. goto error;
  682. }
  683. av_tree_insert(&s->glyphs, glyph, glyph_cmp, &node);
  684. } else {
  685. if (s->borderw && !glyph->border_glyph) {
  686. glyph->border_glyph = glyph->glyph;
  687. if (FT_Glyph_StrokeBorder(&glyph->border_glyph, s->stroker, 0, 0)) {
  688. ret = AVERROR_EXTERNAL;
  689. goto error;
  690. }
  691. }
  692. }
  693. // Check if a bitmap is needed
  694. if (shift_x64 >= 0 && shift_y64 >= 0) {
  695. // Get the bitmap subpixel index (0 -> 15)
  696. int idx = get_subpixel_idx(shift_x64, shift_y64);
  697. shift.x = shift_x64;
  698. shift.y = shift_y64;
  699. if (!glyph->bglyph[idx]) {
  700. FT_Glyph tmp_glyph = glyph->glyph;
  701. if (FT_Glyph_To_Bitmap(&tmp_glyph, FT_RENDER_MODE_NORMAL, &shift, 0)) {
  702. ret = AVERROR_EXTERNAL;
  703. goto error;
  704. }
  705. glyph->bglyph[idx] = (FT_BitmapGlyph)tmp_glyph;
  706. if (glyph->bglyph[idx]->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) {
  707. av_log(ctx, AV_LOG_ERROR, "Monocromatic (1bpp) fonts are not supported.\n");
  708. ret = AVERROR(EINVAL);
  709. goto error;
  710. }
  711. }
  712. if (s->borderw && !glyph->border_bglyph[idx]) {
  713. FT_Glyph tmp_glyph = glyph->border_glyph;
  714. if (FT_Glyph_To_Bitmap(&tmp_glyph, FT_RENDER_MODE_NORMAL, &shift, 0)) {
  715. ret = AVERROR_EXTERNAL;
  716. goto error;
  717. }
  718. glyph->border_bglyph[idx] = (FT_BitmapGlyph)tmp_glyph;
  719. }
  720. }
  721. if (glyph_ptr) {
  722. *glyph_ptr = glyph;
  723. }
  724. return 0;
  725. error:
  726. if (glyph && glyph->glyph)
  727. FT_Done_Glyph(glyph->glyph);
  728. av_freep(&glyph);
  729. av_freep(&node);
  730. return ret;
  731. }
  732. // Convert a string formatted as "n1|n2|...|nN" into an integer array
  733. static int string_to_array(const char *source, int *result, int result_size)
  734. {
  735. int counter = 0, size = strlen(source) + 1;
  736. char *saveptr, *curval, *dup = av_malloc(size);
  737. if (!dup)
  738. return 0;
  739. av_strlcpy(dup, source, size);
  740. if (result_size > 0 && (curval = av_strtok(dup, "|", &saveptr))) {
  741. do {
  742. result[counter++] = atoi(curval);
  743. } while ((curval = av_strtok(NULL, "|", &saveptr)) && counter < result_size);
  744. }
  745. av_free(dup);
  746. return counter;
  747. }
  748. static int func_pict_type(void *ctx, AVBPrint *bp, const char *function_name, unsigned argc, char **argv)
  749. {
  750. DrawTextContext *s = ((AVFilterContext *)ctx)->priv;
  751. av_bprintf(bp, "%c", av_get_picture_type_char(s->var_values[VAR_PICT_TYPE]));
  752. return 0;
  753. }
  754. static int func_pts(void *ctx, AVBPrint *bp, const char *function_name, unsigned argc, char **argv)
  755. {
  756. DrawTextContext *s = ((AVFilterContext *)ctx)->priv;
  757. const char *fmt;
  758. const char *strftime_fmt = NULL;
  759. const char *delta = NULL;
  760. double pts = s->var_values[VAR_T];
  761. // argv: pts, FMT, [DELTA, 24HH | strftime_fmt]
  762. fmt = argc >= 1 ? argv[0] : "flt";
  763. if (argc >= 2) {
  764. delta = argv[1];
  765. }
  766. if (argc >= 3) {
  767. if (!strcmp(fmt, "hms")) {
  768. if (!strcmp(argv[2], "24HH")) {
  769. av_log(ctx, AV_LOG_WARNING, "pts third argument 24HH is deprected, use pts:hms24hh instead\n");
  770. fmt = "hms24";
  771. } else {
  772. av_log(ctx, AV_LOG_ERROR, "Invalid argument '%s', '24HH' was expected\n", argv[2]);
  773. return AVERROR(EINVAL);
  774. }
  775. } else {
  776. strftime_fmt = argv[2];
  777. }
  778. }
  779. return ff_print_pts(ctx, bp, pts, delta, fmt, strftime_fmt);
  780. }
  781. static int func_frame_num(void *ctx, AVBPrint *bp, const char *function_name, unsigned argc, char **argv)
  782. {
  783. DrawTextContext *s = ((AVFilterContext *)ctx)->priv;
  784. av_bprintf(bp, "%d", (int)s->var_values[VAR_N]);
  785. return 0;
  786. }
  787. static int func_metadata(void *ctx, AVBPrint *bp, const char *function_name, unsigned argc, char **argv)
  788. {
  789. DrawTextContext *s = ((AVFilterContext *)ctx)->priv;
  790. AVDictionaryEntry *e = av_dict_get(s->metadata, argv[0], NULL, 0);
  791. if (e && e->value)
  792. av_bprintf(bp, "%s", e->value);
  793. else if (argc >= 2)
  794. av_bprintf(bp, "%s", argv[1]);
  795. return 0;
  796. }
  797. static int func_strftime(void *ctx, AVBPrint *bp, const char *function_name, unsigned argc, char **argv)
  798. {
  799. const char *strftime_fmt = argc ? argv[0] : NULL;
  800. return ff_print_time(ctx, bp, strftime_fmt, !strcmp(function_name, "localtime"));
  801. }
  802. static int func_eval_expr(void *ctx, AVBPrint *bp, const char *function_name, unsigned argc, char **argv)
  803. {
  804. DrawTextContext *s = ((AVFilterContext *)ctx)->priv;
  805. return ff_print_eval_expr(ctx, bp, argv[0],
  806. fun2_names, fun2,
  807. var_names, s->var_values, &s->prng);
  808. }
  809. static int func_eval_expr_int_format(void *ctx, AVBPrint *bp, const char *function_name, unsigned argc, char **argv)
  810. {
  811. DrawTextContext *s = ((AVFilterContext *)ctx)->priv;
  812. int ret;
  813. int positions = -1;
  814. /*
  815. * argv[0] expression to be converted to `int`
  816. * argv[1] format: 'x', 'X', 'd' or 'u'
  817. * argv[2] positions printed (optional)
  818. */
  819. if (argc == 3) {
  820. ret = sscanf(argv[2], "%u", &positions);
  821. if (ret != 1) {
  822. av_log(ctx, AV_LOG_ERROR, "expr_int_format(): Invalid number of positions"
  823. " to print: '%s'\n", argv[2]);
  824. return AVERROR(EINVAL);
  825. }
  826. }
  827. return ff_print_formatted_eval_expr(ctx, bp, argv[0],
  828. fun2_names, fun2,
  829. var_names, s->var_values,
  830. &s->prng,
  831. argv[1][0], positions);
  832. }
  833. static FFExpandTextFunction expand_text_functions[] = {
  834. { "e", 1, 1, func_eval_expr },
  835. { "eif", 2, 3, func_eval_expr_int_format },
  836. { "expr", 1, 1, func_eval_expr },
  837. { "expr_int_format", 2, 3, func_eval_expr_int_format },
  838. { "frame_num", 0, 0, func_frame_num },
  839. { "gmtime", 0, 1, func_strftime },
  840. { "localtime", 0, 1, func_strftime },
  841. { "metadata", 1, 2, func_metadata },
  842. { "n", 0, 0, func_frame_num },
  843. { "pict_type", 0, 0, func_pict_type },
  844. { "pts", 0, 3, func_pts }
  845. };
  846. static av_cold int init(AVFilterContext *ctx)
  847. {
  848. int err;
  849. DrawTextContext *s = ctx->priv;
  850. av_expr_free(s->fontsize_pexpr);
  851. s->fontsize_pexpr = NULL;
  852. s->fontsize = 0;
  853. s->default_fontsize = 16;
  854. if (!s->fontfile && !CONFIG_LIBFONTCONFIG) {
  855. av_log(ctx, AV_LOG_ERROR, "No font filename provided\n");
  856. return AVERROR(EINVAL);
  857. }
  858. if (s->textfile) {
  859. if (s->text) {
  860. av_log(ctx, AV_LOG_ERROR,
  861. "Both text and text file provided. Please provide only one\n");
  862. return AVERROR(EINVAL);
  863. }
  864. if ((err = ff_load_textfile(ctx, (const char *)s->textfile, &s->text, NULL)) < 0)
  865. return err;
  866. }
  867. if (s->reload && !s->textfile)
  868. av_log(ctx, AV_LOG_WARNING, "No file to reload\n");
  869. if (s->tc_opt_string) {
  870. int ret = av_timecode_init_from_string(&s->tc, s->tc_rate,
  871. s->tc_opt_string, ctx);
  872. if (ret < 0)
  873. return ret;
  874. if (s->tc24hmax)
  875. s->tc.flags |= AV_TIMECODE_FLAG_24HOURSMAX;
  876. if (!s->text)
  877. s->text = av_strdup("");
  878. }
  879. if (s->text_source_string) {
  880. s->text_source = text_source_string_parse(s->text_source_string);
  881. if ((int)s->text_source < 0) {
  882. av_log(ctx, AV_LOG_ERROR, "Error text source: %s\n", s->text_source_string);
  883. return AVERROR(EINVAL);
  884. }
  885. }
  886. if (s->text_source == AV_FRAME_DATA_DETECTION_BBOXES) {
  887. if (s->text) {
  888. av_log(ctx, AV_LOG_WARNING, "Multiple texts provided, will use text_source only\n");
  889. av_free(s->text);
  890. }
  891. s->text = av_mallocz(AV_DETECTION_BBOX_LABEL_NAME_MAX_SIZE *
  892. (AV_NUM_DETECTION_BBOX_CLASSIFY + 1));
  893. if (!s->text)
  894. return AVERROR(ENOMEM);
  895. }
  896. if (!s->text) {
  897. av_log(ctx, AV_LOG_ERROR,
  898. "Either text, a valid file, a timecode or text source must be provided\n");
  899. return AVERROR(EINVAL);
  900. }
  901. s->expand_text = (FFExpandTextContext) {
  902. .log_ctx = ctx,
  903. .functions = expand_text_functions,
  904. .functions_nb = FF_ARRAY_ELEMS(expand_text_functions)
  905. };
  906. #if CONFIG_LIBFRIBIDI
  907. if (s->text_shaping)
  908. if ((err = shape_text(ctx)) < 0)
  909. return err;
  910. #endif
  911. if ((err = FT_Init_FreeType(&(s->library)))) {
  912. av_log(ctx, AV_LOG_ERROR,
  913. "Could not load FreeType: %s\n", FT_ERRMSG(err));
  914. return AVERROR(EINVAL);
  915. }
  916. if ((err = load_font(ctx)) < 0)
  917. return err;
  918. if ((err = update_fontsize(ctx)) < 0)
  919. return err;
  920. // Always init the stroker, may be needed if borderw is set via command
  921. if (FT_Stroker_New(s->library, &s->stroker)) {
  922. av_log(ctx, AV_LOG_ERROR, "Could not init FT stroker\n");
  923. return AVERROR_EXTERNAL;
  924. }
  925. if (s->borderw) {
  926. FT_Stroker_Set(s->stroker, s->borderw << 6, FT_STROKER_LINECAP_ROUND,
  927. FT_STROKER_LINEJOIN_ROUND, 0);
  928. }
  929. /* load the fallback glyph with code 0 */
  930. load_glyph(ctx, NULL, 0, 0, 0);
  931. if (s->exp_mode == EXP_STRFTIME &&
  932. (strchr(s->text, '%') || strchr(s->text, '\\')))
  933. av_log(ctx, AV_LOG_WARNING, "expansion=strftime is deprecated.\n");
  934. av_bprint_init(&s->expanded_text, 0, AV_BPRINT_SIZE_UNLIMITED);
  935. av_bprint_init(&s->expanded_fontcolor, 0, AV_BPRINT_SIZE_UNLIMITED);
  936. return 0;
  937. }
  938. static int query_formats(AVFilterContext *ctx)
  939. {
  940. return ff_set_common_formats(ctx, ff_draw_supported_pixel_formats(0));
  941. }
  942. static int glyph_enu_border_free(void *opaque, void *elem)
  943. {
  944. Glyph *glyph = elem;
  945. if (glyph->border_glyph != NULL) {
  946. for (int t = 0; t < 16; ++t) {
  947. if (glyph->border_bglyph[t] != NULL) {
  948. FT_Done_Glyph((FT_Glyph)glyph->border_bglyph[t]);
  949. glyph->border_bglyph[t] = NULL;
  950. }
  951. }
  952. FT_Done_Glyph(glyph->border_glyph);
  953. glyph->border_glyph = NULL;
  954. }
  955. return 0;
  956. }
  957. static int glyph_enu_free(void *opaque, void *elem)
  958. {
  959. Glyph *glyph = elem;
  960. FT_Done_Glyph(glyph->glyph);
  961. FT_Done_Glyph(glyph->border_glyph);
  962. for (int t = 0; t < 16; ++t) {
  963. if (glyph->bglyph[t] != NULL) {
  964. FT_Done_Glyph((FT_Glyph)glyph->bglyph[t]);
  965. }
  966. if (glyph->border_bglyph[t] != NULL) {
  967. FT_Done_Glyph((FT_Glyph)glyph->border_bglyph[t]);
  968. }
  969. }
  970. av_free(elem);
  971. return 0;
  972. }
  973. static av_cold void uninit(AVFilterContext *ctx)
  974. {
  975. DrawTextContext *s = ctx->priv;
  976. av_expr_free(s->x_pexpr);
  977. av_expr_free(s->y_pexpr);
  978. av_expr_free(s->a_pexpr);
  979. av_expr_free(s->fontsize_pexpr);
  980. s->x_pexpr = s->y_pexpr = s->a_pexpr = s->fontsize_pexpr = NULL;
  981. av_tree_enumerate(s->glyphs, NULL, NULL, glyph_enu_free);
  982. av_tree_destroy(s->glyphs);
  983. s->glyphs = NULL;
  984. FT_Done_Face(s->face);
  985. FT_Stroker_Done(s->stroker);
  986. FT_Done_FreeType(s->library);
  987. av_bprint_finalize(&s->expanded_text, NULL);
  988. av_bprint_finalize(&s->expanded_fontcolor, NULL);
  989. }
  990. static int config_input(AVFilterLink *inlink)
  991. {
  992. AVFilterContext *ctx = inlink->dst;
  993. DrawTextContext *s = ctx->priv;
  994. char *expr;
  995. int ret;
  996. ff_draw_init2(&s->dc, inlink->format, inlink->colorspace, inlink->color_range, FF_DRAW_PROCESS_ALPHA);
  997. ff_draw_color(&s->dc, &s->fontcolor, s->fontcolor.rgba);
  998. ff_draw_color(&s->dc, &s->shadowcolor, s->shadowcolor.rgba);
  999. ff_draw_color(&s->dc, &s->bordercolor, s->bordercolor.rgba);
  1000. ff_draw_color(&s->dc, &s->boxcolor, s->boxcolor.rgba);
  1001. s->var_values[VAR_w] = s->var_values[VAR_W] = s->var_values[VAR_MAIN_W] = inlink->w;
  1002. s->var_values[VAR_h] = s->var_values[VAR_H] = s->var_values[VAR_MAIN_H] = inlink->h;
  1003. s->var_values[VAR_SAR] = inlink->sample_aspect_ratio.num ? av_q2d(inlink->sample_aspect_ratio) : 1;
  1004. s->var_values[VAR_DAR] = (double)inlink->w / inlink->h * s->var_values[VAR_SAR];
  1005. s->var_values[VAR_HSUB] = 1 << s->dc.hsub_max;
  1006. s->var_values[VAR_VSUB] = 1 << s->dc.vsub_max;
  1007. s->var_values[VAR_X] = NAN;
  1008. s->var_values[VAR_Y] = NAN;
  1009. s->var_values[VAR_T] = NAN;
  1010. av_lfg_init(&s->prng, av_get_random_seed());
  1011. av_expr_free(s->x_pexpr);
  1012. av_expr_free(s->y_pexpr);
  1013. av_expr_free(s->a_pexpr);
  1014. s->x_pexpr = s->y_pexpr = s->a_pexpr = NULL;
  1015. if ((ret = av_expr_parse(&s->x_pexpr, expr = s->x_expr, var_names,
  1016. NULL, NULL, fun2_names, fun2, 0, ctx)) < 0 ||
  1017. (ret = av_expr_parse(&s->y_pexpr, expr = s->y_expr, var_names,
  1018. NULL, NULL, fun2_names, fun2, 0, ctx)) < 0 ||
  1019. (ret = av_expr_parse(&s->a_pexpr, expr = s->a_expr, var_names,
  1020. NULL, NULL, fun2_names, fun2, 0, ctx)) < 0) {
  1021. av_log(ctx, AV_LOG_ERROR, "Failed to parse expression: %s \n", expr);
  1022. return AVERROR(EINVAL);
  1023. }
  1024. return 0;
  1025. }
  1026. static int command(AVFilterContext *ctx, const char *cmd, const char *arg, char *res, int res_len, int flags)
  1027. {
  1028. DrawTextContext *old = ctx->priv;
  1029. DrawTextContext *new = NULL;
  1030. int ret;
  1031. if (!strcmp(cmd, "reinit")) {
  1032. new = av_mallocz(sizeof(DrawTextContext));
  1033. if (!new)
  1034. return AVERROR(ENOMEM);
  1035. new->class = &drawtext_class;
  1036. ret = av_opt_copy(new, old);
  1037. if (ret < 0)
  1038. goto fail;
  1039. ctx->priv = new;
  1040. ret = av_set_options_string(ctx, arg, "=", ":");
  1041. if (ret < 0) {
  1042. ctx->priv = old;
  1043. goto fail;
  1044. }
  1045. ret = init(ctx);
  1046. if (ret < 0) {
  1047. uninit(ctx);
  1048. ctx->priv = old;
  1049. goto fail;
  1050. }
  1051. new->reinit = 1;
  1052. ctx->priv = old;
  1053. uninit(ctx);
  1054. av_freep(&old);
  1055. ctx->priv = new;
  1056. return config_input(ctx->inputs[0]);
  1057. } else {
  1058. int old_borderw = old->borderw;
  1059. if ((ret = ff_filter_process_command(ctx, cmd, arg, res, res_len, flags)) < 0) {
  1060. return ret;
  1061. }
  1062. if (old->borderw != old_borderw) {
  1063. FT_Stroker_Set(old->stroker, old->borderw << 6, FT_STROKER_LINECAP_ROUND,
  1064. FT_STROKER_LINEJOIN_ROUND, 0);
  1065. // Dispose the old border glyphs
  1066. av_tree_enumerate(old->glyphs, NULL, NULL, glyph_enu_border_free);
  1067. } else if (strcmp(cmd, "fontsize") == 0) {
  1068. av_expr_free(old->fontsize_pexpr);
  1069. old->fontsize_pexpr = NULL;
  1070. old->blank_advance64 = 0;
  1071. }
  1072. return config_input(ctx->inputs[0]);
  1073. }
  1074. fail:
  1075. av_log(ctx, AV_LOG_ERROR, "Failed to process command. Continuing with existing parameters.\n");
  1076. av_freep(&new);
  1077. return ret;
  1078. }
  1079. static void update_color_with_alpha(DrawTextContext *s, FFDrawColor *color, const FFDrawColor incolor)
  1080. {
  1081. *color = incolor;
  1082. color->rgba[3] = (color->rgba[3] * s->alpha) / 255;
  1083. ff_draw_color(&s->dc, color, color->rgba);
  1084. }
  1085. static void update_alpha(DrawTextContext *s)
  1086. {
  1087. double alpha = av_expr_eval(s->a_pexpr, s->var_values, &s->prng);
  1088. if (isnan(alpha))
  1089. return;
  1090. if (alpha >= 1.0)
  1091. s->alpha = 255;
  1092. else if (alpha <= 0)
  1093. s->alpha = 0;
  1094. else
  1095. s->alpha = 256 * alpha;
  1096. }
  1097. static int draw_glyphs(DrawTextContext *s, AVFrame *frame,
  1098. FFDrawColor *color,
  1099. TextMetrics *metrics,
  1100. int x, int y, int borderw)
  1101. {
  1102. int g, l, x1, y1, w1, h1, idx;
  1103. int dx = 0, dy = 0, pdx = 0;
  1104. GlyphInfo *info;
  1105. Glyph dummy = { 0 }, *glyph;
  1106. FT_Bitmap bitmap;
  1107. FT_BitmapGlyph b_glyph;
  1108. uint8_t j_left = 0, j_right = 0, j_top = 0, j_bottom = 0;
  1109. int line_w, offset_y = 0;
  1110. int clip_x = 0, clip_y = 0;
  1111. j_left = !!(s->text_align & TA_LEFT);
  1112. j_right = !!(s->text_align & TA_RIGHT);
  1113. j_top = !!(s->text_align & TA_TOP);
  1114. j_bottom = !!(s->text_align & TA_BOTTOM);
  1115. if (j_top && j_bottom) {
  1116. offset_y = (s->box_height - metrics->height) / 2;
  1117. } else if (j_bottom) {
  1118. offset_y = s->box_height - metrics->height;
  1119. }
  1120. if ((!j_left || j_right) && !s->tab_warning_printed && s->tab_count > 0) {
  1121. s->tab_warning_printed = 1;
  1122. av_log(s, AV_LOG_WARNING, "Tab characters are only supported with left horizontal alignment\n");
  1123. }
  1124. clip_x = FFMIN(metrics->rect_x + s->box_width + s->bb_right, frame->width);
  1125. clip_y = FFMIN(metrics->rect_y + s->box_height + s->bb_bottom, frame->height);
  1126. for (l = 0; l < s->line_count; ++l) {
  1127. TextLine *line = &s->lines[l];
  1128. line_w = POS_CEIL(line->width64, 64);
  1129. for (g = 0; g < line->hb_data.glyph_count; ++g) {
  1130. info = &line->glyphs[g];
  1131. dummy.fontsize = s->fontsize;
  1132. dummy.code = info->code;
  1133. glyph = av_tree_find(s->glyphs, &dummy, glyph_cmp, NULL);
  1134. if (!glyph) {
  1135. return AVERROR(EINVAL);
  1136. }
  1137. idx = get_subpixel_idx(info->shift_x64, info->shift_y64);
  1138. b_glyph = borderw ? glyph->border_bglyph[idx] : glyph->bglyph[idx];
  1139. bitmap = b_glyph->bitmap;
  1140. x1 = x + info->x + b_glyph->left;
  1141. y1 = y + info->y - b_glyph->top + offset_y;
  1142. w1 = bitmap.width;
  1143. h1 = bitmap.rows;
  1144. if (j_left && j_right) {
  1145. x1 += (s->box_width - line_w) / 2;
  1146. } else if (j_right) {
  1147. x1 += s->box_width - line_w;
  1148. }
  1149. // Offset of the glyph's bitmap in the visible region
  1150. dx = dy = 0;
  1151. if (x1 < metrics->rect_x - s->bb_left) {
  1152. dx = metrics->rect_x - s->bb_left - x1;
  1153. x1 = metrics->rect_x - s->bb_left;
  1154. }
  1155. if (y1 < metrics->rect_y - s->bb_top) {
  1156. dy = metrics->rect_y - s->bb_top - y1;
  1157. y1 = metrics->rect_y - s->bb_top;
  1158. }
  1159. // check if the glyph is empty or out of the clipping region
  1160. if (dx >= w1 || dy >= h1 || x1 >= clip_x || y1 >= clip_y) {
  1161. continue;
  1162. }
  1163. pdx = dx + dy * bitmap.pitch;
  1164. w1 = FFMIN(clip_x - x1, w1 - dx);
  1165. h1 = FFMIN(clip_y - y1, h1 - dy);
  1166. ff_blend_mask(&s->dc, color, frame->data, frame->linesize, clip_x, clip_y,
  1167. bitmap.buffer + pdx, bitmap.pitch, w1, h1, 3, 0, x1, y1);
  1168. }
  1169. }
  1170. return 0;
  1171. }
  1172. // Shapes a line of text using libharfbuzz
  1173. static int shape_text_hb(DrawTextContext *s, HarfbuzzData* hb, const char* text, int textLen)
  1174. {
  1175. hb->buf = hb_buffer_create();
  1176. if(!hb_buffer_allocation_successful(hb->buf)) {
  1177. return AVERROR(ENOMEM);
  1178. }
  1179. hb_buffer_set_direction(hb->buf, HB_DIRECTION_LTR);
  1180. hb_buffer_set_script(hb->buf, HB_SCRIPT_LATIN);
  1181. hb_buffer_set_language(hb->buf, hb_language_from_string("en", -1));
  1182. hb_buffer_guess_segment_properties(hb->buf);
  1183. hb->font = hb_ft_font_create(s->face, NULL);
  1184. if(hb->font == NULL) {
  1185. return AVERROR(ENOMEM);
  1186. }
  1187. hb_ft_font_set_funcs(hb->font);
  1188. hb_buffer_add_utf8(hb->buf, text, textLen, 0, -1);
  1189. hb_shape(hb->font, hb->buf, NULL, 0);
  1190. hb->glyph_info = hb_buffer_get_glyph_infos(hb->buf, &hb->glyph_count);
  1191. hb->glyph_pos = hb_buffer_get_glyph_positions(hb->buf, &hb->glyph_count);
  1192. return 0;
  1193. }
  1194. static void hb_destroy(HarfbuzzData *hb)
  1195. {
  1196. hb_buffer_destroy(hb->buf);
  1197. hb_font_destroy(hb->font);
  1198. hb->buf = NULL;
  1199. hb->font = NULL;
  1200. hb->glyph_info = NULL;
  1201. hb->glyph_pos = NULL;
  1202. }
  1203. static int measure_text(AVFilterContext *ctx, TextMetrics *metrics)
  1204. {
  1205. DrawTextContext *s = ctx->priv;
  1206. char *text = s->expanded_text.str;
  1207. char *textdup = NULL, *start = NULL;
  1208. int num_chars = 0;
  1209. int width64 = 0, w64 = 0;
  1210. int cur_min_y64 = 0, first_max_y64 = -32000;
  1211. int first_min_x64 = 32000, last_max_x64 = -32000;
  1212. int min_y64 = 32000, max_y64 = -32000, min_x64 = 32000, max_x64 = -32000;
  1213. int line_count = 0;
  1214. uint32_t code = 0;
  1215. Glyph *glyph = NULL;
  1216. int i, tab_idx = 0, last_tab_idx = 0, line_offset = 0;
  1217. char* p;
  1218. int ret = 0;
  1219. // Count the lines and the tab characters
  1220. s->tab_count = 0;
  1221. for (i = 0, p = text; 1; i++) {
  1222. GET_UTF8(code, *p ? *p++ : 0, code = 0xfffd; goto continue_on_failed;);
  1223. continue_on_failed:
  1224. if (ff_is_newline(code) || code == 0) {
  1225. ++line_count;
  1226. if (code == 0) {
  1227. break;
  1228. }
  1229. } else if (code == '\t') {
  1230. ++s->tab_count;
  1231. }
  1232. }
  1233. // Evaluate the width of the space character if needed to replace tabs
  1234. if (s->tab_count > 0 && !s->blank_advance64) {
  1235. HarfbuzzData hb_data;
  1236. ret = shape_text_hb(s, &hb_data, " ", 1);
  1237. if(ret != 0) {
  1238. goto done;
  1239. }
  1240. s->blank_advance64 = hb_data.glyph_pos[0].x_advance;
  1241. hb_destroy(&hb_data);
  1242. }
  1243. s->line_count = line_count;
  1244. s->lines = av_mallocz(line_count * sizeof(TextLine));
  1245. s->tab_clusters = av_mallocz(s->tab_count * sizeof(uint32_t));
  1246. for (i = 0; i < s->tab_count; ++i) {
  1247. s->tab_clusters[i] = -1;
  1248. }
  1249. start = textdup = av_strdup(text);
  1250. if (textdup == NULL) {
  1251. ret = AVERROR(ENOMEM);
  1252. goto done;
  1253. }
  1254. line_count = 0;
  1255. for (i = 0, p = textdup; 1; i++) {
  1256. if (*p == '\t') {
  1257. s->tab_clusters[tab_idx++] = i;
  1258. *p = ' ';
  1259. }
  1260. GET_UTF8(code, *p ? *p++ : 0, code = 0xfffd; goto continue_on_failed2;);
  1261. continue_on_failed2:
  1262. if (ff_is_newline(code) || code == 0) {
  1263. TextLine *cur_line = &s->lines[line_count];
  1264. HarfbuzzData *hb = &cur_line->hb_data;
  1265. cur_line->cluster_offset = line_offset;
  1266. ret = shape_text_hb(s, hb, start, num_chars);
  1267. if (ret != 0) {
  1268. goto done;
  1269. }
  1270. w64 = 0;
  1271. cur_min_y64 = 32000;
  1272. for (int t = 0; t < hb->glyph_count; ++t) {
  1273. uint8_t is_tab = last_tab_idx < s->tab_count &&
  1274. hb->glyph_info[t].cluster == s->tab_clusters[last_tab_idx] - line_offset;
  1275. if (is_tab) {
  1276. ++last_tab_idx;
  1277. }
  1278. ret = load_glyph(ctx, &glyph, hb->glyph_info[t].codepoint, -1, -1);
  1279. if (ret != 0) {
  1280. goto done;
  1281. }
  1282. if (line_count == 0) {
  1283. first_max_y64 = FFMAX(glyph->bbox.yMax, first_max_y64);
  1284. }
  1285. if (t == 0) {
  1286. cur_line->offset_left64 = glyph->bbox.xMin;
  1287. first_min_x64 = FFMIN(glyph->bbox.xMin, first_min_x64);
  1288. }
  1289. if (t == hb->glyph_count - 1) {
  1290. // The following code measures the width of the line up to the last
  1291. // character's horizontal advance
  1292. int last_char_width = hb->glyph_pos[t].x_advance;
  1293. // The following code measures the width of the line up to the rightmost
  1294. // visible pixel of the last character
  1295. // int last_char_width = glyph->bbox.xMax;
  1296. w64 += last_char_width;
  1297. last_max_x64 = FFMAX(last_char_width, last_max_x64);
  1298. cur_line->offset_right64 = last_char_width;
  1299. } else {
  1300. if (is_tab) {
  1301. int size = s->blank_advance64 * s->tabsize;
  1302. w64 = (w64 / size + 1) * size;
  1303. } else {
  1304. w64 += hb->glyph_pos[t].x_advance;
  1305. }
  1306. }
  1307. cur_min_y64 = FFMIN(glyph->bbox.yMin, cur_min_y64);
  1308. min_y64 = FFMIN(glyph->bbox.yMin, min_y64);
  1309. max_y64 = FFMAX(glyph->bbox.yMax, max_y64);
  1310. min_x64 = FFMIN(glyph->bbox.xMin, min_x64);
  1311. max_x64 = FFMAX(glyph->bbox.xMax, max_x64);
  1312. }
  1313. cur_line->width64 = w64;
  1314. av_log(s, AV_LOG_DEBUG, " Line: %d -- glyphs count: %d - width64: %d - offset_left64: %d - offset_right64: %d)\n",
  1315. line_count, hb->glyph_count, cur_line->width64, cur_line->offset_left64, cur_line->offset_right64);
  1316. if (w64 > width64) {
  1317. width64 = w64;
  1318. }
  1319. num_chars = -1;
  1320. start = p;
  1321. ++line_count;
  1322. line_offset = i + 1;
  1323. }
  1324. if (code == 0) break;
  1325. ++num_chars;
  1326. }
  1327. metrics->line_height64 = s->face->size->metrics.height;
  1328. metrics->width = POS_CEIL(width64, 64);
  1329. if (s->y_align == YA_FONT) {
  1330. metrics->height = POS_CEIL(metrics->line_height64 * line_count, 64);
  1331. } else {
  1332. int height64 = (metrics->line_height64 + s->line_spacing * 64) *
  1333. (FFMAX(0, line_count - 1)) + first_max_y64 - cur_min_y64;
  1334. metrics->height = POS_CEIL(height64, 64);
  1335. }
  1336. metrics->offset_top64 = first_max_y64;
  1337. metrics->offset_right64 = last_max_x64;
  1338. metrics->offset_bottom64 = cur_min_y64;
  1339. metrics->offset_left64 = first_min_x64;
  1340. metrics->min_x64 = min_x64;
  1341. metrics->min_y64 = min_y64;
  1342. metrics->max_x64 = max_x64;
  1343. metrics->max_y64 = max_y64;
  1344. done:
  1345. av_free(textdup);
  1346. return ret;
  1347. }
  1348. static int draw_text(AVFilterContext *ctx, AVFrame *frame)
  1349. {
  1350. DrawTextContext *s = ctx->priv;
  1351. AVFilterLink *inlink = ctx->inputs[0];
  1352. int x = 0, y = 0, ret;
  1353. int shift_x64, shift_y64;
  1354. int x64, y64;
  1355. Glyph *glyph = NULL;
  1356. time_t now = time(0);
  1357. struct tm ltime;
  1358. AVBPrint *bp = &s->expanded_text;
  1359. FFDrawColor fontcolor;
  1360. FFDrawColor shadowcolor;
  1361. FFDrawColor bordercolor;
  1362. FFDrawColor boxcolor;
  1363. int width = frame->width;
  1364. int height = frame->height;
  1365. int rec_x = 0, rec_y = 0, rec_width = 0, rec_height = 0;
  1366. int is_outside = 0;
  1367. int last_tab_idx = 0;
  1368. TextMetrics metrics;
  1369. av_bprint_clear(bp);
  1370. if (s->basetime != AV_NOPTS_VALUE)
  1371. now= frame->pts*av_q2d(ctx->inputs[0]->time_base) + s->basetime/1000000;
  1372. switch (s->exp_mode) {
  1373. case EXP_NONE:
  1374. av_bprintf(bp, "%s", s->text);
  1375. break;
  1376. case EXP_NORMAL:
  1377. if ((ret = ff_expand_text(&s->expand_text, s->text, &s->expanded_text)) < 0)
  1378. return ret;
  1379. break;
  1380. case EXP_STRFTIME:
  1381. localtime_r(&now, &ltime);
  1382. av_bprint_strftime(bp, s->text, &ltime);
  1383. break;
  1384. }
  1385. if (s->tc_opt_string) {
  1386. char tcbuf[AV_TIMECODE_STR_SIZE];
  1387. av_timecode_make_string(&s->tc, tcbuf, inlink->frame_count_out);
  1388. av_bprint_clear(bp);
  1389. av_bprintf(bp, "%s%s", s->text, tcbuf);
  1390. }
  1391. if (!av_bprint_is_complete(bp))
  1392. return AVERROR(ENOMEM);
  1393. if (s->fontcolor_expr[0]) {
  1394. /* If expression is set, evaluate and replace the static value */
  1395. av_bprint_clear(&s->expanded_fontcolor);
  1396. if ((ret = ff_expand_text(&s->expand_text, s->fontcolor_expr, &s->expanded_fontcolor)) < 0)
  1397. return ret;
  1398. if (!av_bprint_is_complete(&s->expanded_fontcolor))
  1399. return AVERROR(ENOMEM);
  1400. av_log(s, AV_LOG_DEBUG, "Evaluated fontcolor is '%s'\n", s->expanded_fontcolor.str);
  1401. ret = av_parse_color(s->fontcolor.rgba, s->expanded_fontcolor.str, -1, s);
  1402. if (ret)
  1403. return ret;
  1404. ff_draw_color(&s->dc, &s->fontcolor, s->fontcolor.rgba);
  1405. }
  1406. if ((ret = update_fontsize(ctx)) < 0) {
  1407. return ret;
  1408. }
  1409. if ((ret = measure_text(ctx, &metrics)) < 0) {
  1410. return ret;
  1411. }
  1412. s->max_glyph_h = POS_CEIL(metrics.max_y64 - metrics.min_y64, 64);
  1413. s->max_glyph_w = POS_CEIL(metrics.max_x64 - metrics.min_x64, 64);
  1414. s->var_values[VAR_TW] = s->var_values[VAR_TEXT_W] = metrics.width;
  1415. s->var_values[VAR_TH] = s->var_values[VAR_TEXT_H] = metrics.height;
  1416. s->var_values[VAR_MAX_GLYPH_W] = s->max_glyph_w;
  1417. s->var_values[VAR_MAX_GLYPH_H] = s->max_glyph_h;
  1418. s->var_values[VAR_MAX_GLYPH_A] = s->var_values[VAR_ASCENT] = POS_CEIL(metrics.max_y64, 64);
  1419. s->var_values[VAR_FONT_A] = s->face->size->metrics.ascender / 64;
  1420. s->var_values[VAR_MAX_GLYPH_D] = s->var_values[VAR_DESCENT] = POS_CEIL(metrics.min_y64, 64);
  1421. s->var_values[VAR_FONT_D] = -s->face->size->metrics.descender / 64;
  1422. s->var_values[VAR_TOP_A] = POS_CEIL(metrics.offset_top64, 64);
  1423. s->var_values[VAR_BOTTOM_D] = -POS_CEIL(metrics.offset_bottom64, 64);
  1424. s->var_values[VAR_LINE_H] = s->var_values[VAR_LH] = metrics.line_height64 / 64.;
  1425. if (s->text_source == AV_FRAME_DATA_DETECTION_BBOXES) {
  1426. s->var_values[VAR_X] = s->x;
  1427. s->var_values[VAR_Y] = s->y;
  1428. } else {
  1429. s->x = s->var_values[VAR_X] = av_expr_eval(s->x_pexpr, s->var_values, &s->prng);
  1430. s->y = s->var_values[VAR_Y] = av_expr_eval(s->y_pexpr, s->var_values, &s->prng);
  1431. /* It is necessary if x is expressed from y */
  1432. s->x = s->var_values[VAR_X] = av_expr_eval(s->x_pexpr, s->var_values, &s->prng);
  1433. }
  1434. update_alpha(s);
  1435. update_color_with_alpha(s, &fontcolor , s->fontcolor );
  1436. update_color_with_alpha(s, &shadowcolor, s->shadowcolor);
  1437. update_color_with_alpha(s, &bordercolor, s->bordercolor);
  1438. update_color_with_alpha(s, &boxcolor , s->boxcolor );
  1439. if (s->draw_box && s->boxborderw) {
  1440. int bbsize[4];
  1441. int count;
  1442. count = string_to_array(s->boxborderw, bbsize, 4);
  1443. if (count == 1) {
  1444. s->bb_top = s->bb_right = s->bb_bottom = s->bb_left = bbsize[0];
  1445. } else if (count == 2) {
  1446. s->bb_top = s->bb_bottom = bbsize[0];
  1447. s->bb_right = s->bb_left = bbsize[1];
  1448. } else if (count == 3) {
  1449. s->bb_top = bbsize[0];
  1450. s->bb_right = s->bb_left = bbsize[1];
  1451. s->bb_bottom = bbsize[2];
  1452. } else if (count == 4) {
  1453. s->bb_top = bbsize[0];
  1454. s->bb_right = bbsize[1];
  1455. s->bb_bottom = bbsize[2];
  1456. s->bb_left = bbsize[3];
  1457. }
  1458. } else {
  1459. s->bb_top = s->bb_right = s->bb_bottom = s->bb_left = 0;
  1460. }
  1461. if (s->fix_bounds) {
  1462. /* calculate footprint of text effects */
  1463. int borderoffset = s->borderw ? FFMAX(s->borderw, 0) : 0;
  1464. int offsetleft = FFMAX3(FFMAX(s->bb_left, 0), borderoffset,
  1465. (s->shadowx < 0 ? FFABS(s->shadowx) : 0));
  1466. int offsettop = FFMAX3(FFMAX(s->bb_top, 0), borderoffset,
  1467. (s->shadowy < 0 ? FFABS(s->shadowy) : 0));
  1468. int offsetright = FFMAX3(FFMAX(s->bb_right, 0), borderoffset,
  1469. (s->shadowx > 0 ? s->shadowx : 0));
  1470. int offsetbottom = FFMAX3(FFMAX(s->bb_bottom, 0), borderoffset,
  1471. (s->shadowy > 0 ? s->shadowy : 0));
  1472. if (s->x - offsetleft < 0) s->x = offsetleft;
  1473. if (s->y - offsettop < 0) s->y = offsettop;
  1474. if (s->x + metrics.width + offsetright > width)
  1475. s->x = FFMAX(width - metrics.width - offsetright, 0);
  1476. if (s->y + metrics.height + offsetbottom > height)
  1477. s->y = FFMAX(height - metrics.height - offsetbottom, 0);
  1478. }
  1479. x = 0;
  1480. y = 0;
  1481. x64 = (int)(s->x * 64.);
  1482. if (s->y_align == YA_FONT) {
  1483. y64 = (int)(s->y * 64. + s->face->size->metrics.ascender);
  1484. } else if (s->y_align == YA_BASELINE) {
  1485. y64 = (int)(s->y * 64.);
  1486. } else {
  1487. y64 = (int)(s->y * 64. + metrics.offset_top64);
  1488. }
  1489. for (int l = 0; l < s->line_count; ++l) {
  1490. TextLine *line = &s->lines[l];
  1491. HarfbuzzData *hb = &line->hb_data;
  1492. line->glyphs = av_mallocz(hb->glyph_count * sizeof(GlyphInfo));
  1493. for (int t = 0; t < hb->glyph_count; ++t) {
  1494. GlyphInfo *g_info = &line->glyphs[t];
  1495. uint8_t is_tab = last_tab_idx < s->tab_count &&
  1496. hb->glyph_info[t].cluster == s->tab_clusters[last_tab_idx] - line->cluster_offset;
  1497. int true_x, true_y;
  1498. if (is_tab) {
  1499. ++last_tab_idx;
  1500. }
  1501. true_x = x + hb->glyph_pos[t].x_offset;
  1502. true_y = y + hb->glyph_pos[t].y_offset;
  1503. shift_x64 = (((x64 + true_x) >> 4) & 0b0011) << 4;
  1504. shift_y64 = ((4 - (((y64 + true_y) >> 4) & 0b0011)) & 0b0011) << 4;
  1505. ret = load_glyph(ctx, &glyph, hb->glyph_info[t].codepoint, shift_x64, shift_y64);
  1506. if (ret != 0) {
  1507. return ret;
  1508. }
  1509. g_info->code = hb->glyph_info[t].codepoint;
  1510. g_info->x = (x64 + true_x) >> 6;
  1511. g_info->y = ((y64 + true_y) >> 6) + (shift_y64 > 0 ? 1 : 0);
  1512. g_info->shift_x64 = shift_x64;
  1513. g_info->shift_y64 = shift_y64;
  1514. if (!is_tab) {
  1515. x += hb->glyph_pos[t].x_advance;
  1516. } else {
  1517. int size = s->blank_advance64 * s->tabsize;
  1518. x = (x / size + 1) * size;
  1519. }
  1520. y += hb->glyph_pos[t].y_advance;
  1521. }
  1522. y += metrics.line_height64 + s->line_spacing * 64;
  1523. x = 0;
  1524. }
  1525. metrics.rect_x = s->x;
  1526. if (s->y_align == YA_BASELINE) {
  1527. metrics.rect_y = s->y - metrics.offset_top64 / 64;
  1528. } else {
  1529. metrics.rect_y = s->y;
  1530. }
  1531. s->box_width = s->boxw == 0 ? metrics.width : s->boxw;
  1532. s->box_height = s->boxh == 0 ? metrics.height : s->boxh;
  1533. if (!s->draw_box) {
  1534. // Create a border for the clipping region to take into account subpixel
  1535. // errors in text measurement and effects.
  1536. int borderoffset = s->borderw ? FFMAX(s->borderw, 0) : 0;
  1537. s->bb_left = borderoffset + (s->shadowx < 0 ? FFABS(s->shadowx) : 0) + 1;
  1538. s->bb_top = borderoffset + (s->shadowy < 0 ? FFABS(s->shadowy) : 0) + 1;
  1539. s->bb_right = borderoffset + (s->shadowx > 0 ? s->shadowx : 0) + 1;
  1540. s->bb_bottom = borderoffset + (s->shadowy > 0 ? s->shadowy : 0) + 1;
  1541. }
  1542. /* Check if the whole box is out of the frame */
  1543. is_outside = metrics.rect_x - s->bb_left >= width ||
  1544. metrics.rect_y - s->bb_top >= height ||
  1545. metrics.rect_x + s->box_width + s->bb_right <= 0 ||
  1546. metrics.rect_y + s->box_height + s->bb_bottom <= 0;
  1547. if (!is_outside) {
  1548. /* draw box */
  1549. if (s->draw_box) {
  1550. rec_x = metrics.rect_x - s->bb_left;
  1551. rec_y = metrics.rect_y - s->bb_top;
  1552. rec_width = s->box_width + s->bb_right + s->bb_left;
  1553. rec_height = s->box_height + s->bb_bottom + s->bb_top;
  1554. ff_blend_rectangle(&s->dc, &boxcolor,
  1555. frame->data, frame->linesize, width, height,
  1556. rec_x, rec_y, rec_width, rec_height);
  1557. }
  1558. if (s->shadowx || s->shadowy) {
  1559. if ((ret = draw_glyphs(s, frame, &shadowcolor, &metrics,
  1560. s->shadowx, s->shadowy, s->borderw)) < 0) {
  1561. return ret;
  1562. }
  1563. }
  1564. if (s->borderw) {
  1565. if ((ret = draw_glyphs(s, frame, &bordercolor, &metrics,
  1566. 0, 0, s->borderw)) < 0) {
  1567. return ret;
  1568. }
  1569. }
  1570. if ((ret = draw_glyphs(s, frame, &fontcolor, &metrics, 0,
  1571. 0, 0)) < 0) {
  1572. return ret;
  1573. }
  1574. }
  1575. // FREE data structures
  1576. for (int l = 0; l < s->line_count; ++l) {
  1577. TextLine *line = &s->lines[l];
  1578. av_freep(&line->glyphs);
  1579. hb_destroy(&line->hb_data);
  1580. }
  1581. av_freep(&s->lines);
  1582. av_freep(&s->tab_clusters);
  1583. return 0;
  1584. }
  1585. static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
  1586. {
  1587. AVFilterContext *ctx = inlink->dst;
  1588. AVFilterLink *outlink = ctx->outputs[0];
  1589. DrawTextContext *s = ctx->priv;
  1590. int ret;
  1591. const AVDetectionBBoxHeader *header = NULL;
  1592. const AVDetectionBBox *bbox;
  1593. AVFrameSideData *sd;
  1594. int loop = 1;
  1595. if (s->text_source == AV_FRAME_DATA_DETECTION_BBOXES) {
  1596. sd = av_frame_get_side_data(frame, AV_FRAME_DATA_DETECTION_BBOXES);
  1597. if (sd) {
  1598. header = (AVDetectionBBoxHeader *)sd->data;
  1599. loop = header->nb_bboxes;
  1600. } else {
  1601. av_log(s, AV_LOG_WARNING, "No detection bboxes.\n");
  1602. return ff_filter_frame(outlink, frame);
  1603. }
  1604. }
  1605. if (s->reload && !(inlink->frame_count_out % s->reload)) {
  1606. if ((ret = ff_load_textfile(ctx, (const char *)s->textfile, &s->text, NULL)) < 0) {
  1607. av_frame_free(&frame);
  1608. return ret;
  1609. }
  1610. #if CONFIG_LIBFRIBIDI
  1611. if (s->text_shaping)
  1612. if ((ret = shape_text(ctx)) < 0) {
  1613. av_frame_free(&frame);
  1614. return ret;
  1615. }
  1616. #endif
  1617. }
  1618. s->var_values[VAR_N] = inlink->frame_count_out + s->start_number;
  1619. s->var_values[VAR_T] = frame->pts == AV_NOPTS_VALUE ?
  1620. NAN : frame->pts * av_q2d(inlink->time_base);
  1621. s->var_values[VAR_PICT_TYPE] = frame->pict_type;
  1622. #if FF_API_FRAME_PKT
  1623. FF_DISABLE_DEPRECATION_WARNINGS
  1624. s->var_values[VAR_PKT_POS] = frame->pkt_pos;
  1625. s->var_values[VAR_PKT_SIZE] = frame->pkt_size;
  1626. FF_ENABLE_DEPRECATION_WARNINGS
  1627. #endif
  1628. s->var_values[VAR_DURATION] = frame->duration * av_q2d(inlink->time_base);
  1629. s->metadata = frame->metadata;
  1630. for (int i = 0; i < loop; i++) {
  1631. if (header) {
  1632. bbox = av_get_detection_bbox(header, i);
  1633. strcpy(s->text, bbox->detect_label);
  1634. for (int j = 0; j < bbox->classify_count; j++) {
  1635. strcat(s->text, ", ");
  1636. strcat(s->text, bbox->classify_labels[j]);
  1637. }
  1638. s->x = bbox->x;
  1639. s->y = bbox->y - s->fontsize;
  1640. }
  1641. draw_text(ctx, frame);
  1642. }
  1643. return ff_filter_frame(outlink, frame);
  1644. }
  1645. static const AVFilterPad avfilter_vf_drawtext_inputs[] = {
  1646. {
  1647. .name = "default",
  1648. .type = AVMEDIA_TYPE_VIDEO,
  1649. .flags = AVFILTERPAD_FLAG_NEEDS_WRITABLE,
  1650. .filter_frame = filter_frame,
  1651. .config_props = config_input,
  1652. },
  1653. };
  1654. const AVFilter ff_vf_drawtext = {
  1655. .name = "drawtext",
  1656. .description = NULL_IF_CONFIG_SMALL("Draw text on top of video frames using libfreetype library."),
  1657. .priv_size = sizeof(DrawTextContext),
  1658. .priv_class = &drawtext_class,
  1659. .init = init,
  1660. .uninit = uninit,
  1661. FILTER_INPUTS(avfilter_vf_drawtext_inputs),
  1662. FILTER_OUTPUTS(ff_video_default_filterpad),
  1663. FILTER_QUERY_FUNC(query_formats),
  1664. .process_command = command,
  1665. .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
  1666. };