vf_drawtext.c 78 KB

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