drawtext allows a file to be reloaded per frame. However, the file to be reloaded is constant across frame. With textfile now supporting text expansion, a different file can be reloaded per frame. Eg: textfile=/path/fo/file{frame_num}.txt
Signed-off-by: David Andreoletti <da...@andreoletti.net> --- doc/filters.texi | 16 +++++++++++++--- libavfilter/vf_drawtext.c | 19 ++++++++++++++++--- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index d19fd346ae..460d65dd88 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -9659,13 +9659,13 @@ The default value of @var{borderw} is 0. Set the color to be used for drawing border around text. For the syntax of this option, check the @ref{color syntax,,"Color" section in the ffmpeg-utils manual,ffmpeg-utils}. The default value of @var{bordercolor} is "black". @item expansion -Select how the @var{text} is expanded. Can be either @code{none}, +Select how the @var{text} and @var{textfile} are expanded. Can be either @code{none}, @code{strftime} (deprecated) or @code{normal} (default). See the @ref{drawtext_expansion, Text expansion} section below for details. @item basetime Set a start time for the count. Value is in microseconds. Only applied @@ -9786,15 +9786,19 @@ of UTF-8 encoded characters. This parameter is mandatory if no text string is specified with the parameter @var{text}. If both @var{text} and @var{textfile} are specified, an error is thrown. +This parameter supports (per frame) variable expansion. Per frame variable +expansion requires @code{reload=1}. See @var{expansion} for details. + + @item reload -If set to 1, the @var{textfile} will be reloaded before each frame. -Be sure to update it atomically, or it may be read partially, or even fail. +If set to 1, then before each frame, @var{textfile} file path will be expanded and then the file at said path will be reloaded. +Be sure to update the file atomically, or it may be read partially, or even fail. @item x @item y The expressions which specify the offsets where text will be drawn within the video frame. They are relative to the top/left border of the output image. @@ -10060,12 +10064,18 @@ drawtext="fontsize=15:fontfile=FreeSerif.ttf:text=LONG_LINE:y=h-line_h:x=-50*t" @item Show the content of file @file{CREDITS} off the bottom of the frame and scroll up. @example drawtext="fontsize=20:fontfile=FreeSerif.ttf:textfile=CREDITS:y=h-20*t" @end example +@item +Each frame, reload a different text file at /path/to/frameX.txt, where X is replaced with the frame number being processed by the filter +@example +drawtext="expansion:normal:textfile=/path/to/frame%@{frame_num@}.txt:reload=1" +@end example + @item Draw a single green letter "g", at the center of the input video. The glyph baseline is placed at half screen height. @example drawtext="fontsize=60:fontfile=FreeSerif.ttf:fontcolor=green:text=g:x=(w-max_glyph_w)/2:y=h/2-ascent" @end example diff --git a/libavfilter/vf_drawtext.c b/libavfilter/vf_drawtext.c index abe1ca6c35..ffb1ff2330 100644 --- a/libavfilter/vf_drawtext.c +++ b/libavfilter/vf_drawtext.c @@ -152,13 +152,14 @@ typedef struct DrawTextContext { AVBPrint expanded_text; ///< used to contain the expanded text uint8_t *fontcolor_expr; ///< fontcolor expression to evaluate AVBPrint expanded_fontcolor; ///< used to contain the expanded fontcolor spec int ft_load_flags; ///< flags used for loading fonts, see FT_LOAD_* FT_Vector *positions; ///< positions for each element in the text size_t nb_positions; ///< number of elements of positions array - char *textfile; ///< file with text to be drawn + char *textfile; ///< filename with text to be drawn + AVBPrint expanded_textfile; ///< Same as textfile, except the filename can be expanded int x; ///< x position to start drawing text int y; ///< y position to start drawing text int max_glyph_w; ///< max glyph width int max_glyph_h; ///< max glyph height int shadowx, shadowy; int borderw; ///< border width @@ -565,24 +566,33 @@ static int load_font(AVFilterContext *ctx) if (!err) return 0; #endif return err; } +static int expand_text(AVFilterContext *ctx, char *text, AVBPrint *bp); static int load_textfile(AVFilterContext *ctx) { DrawTextContext *s = ctx->priv; int err; uint8_t *textbuf; uint8_t *tmp; size_t textbuf_size; - if ((err = av_file_map(s->textfile, &textbuf, &textbuf_size, 0, ctx)) < 0) { + if ((err = expand_text(ctx, s->textfile, &s->expanded_textfile)) < 0) { + av_log(ctx, AV_LOG_ERROR, "The text file path '%s' is not expandable\n", + s->textfile); + return err; + } + + av_log(ctx, AV_LOG_DEBUG, "expanded_textfile:%s\n", s->expanded_textfile.str); + + if ((err = av_file_map(s->expanded_textfile.str, &textbuf, &textbuf_size, 0, ctx)) < 0) { av_log(ctx, AV_LOG_ERROR, "The text file '%s' could not be read or is empty\n", - s->textfile); + s->expanded_textfile.str); return err; } if (textbuf_size > SIZE_MAX - 1 || !(tmp = av_realloc(s->text, textbuf_size + 1))) { av_file_unmap(textbuf, textbuf_size); return AVERROR(ENOMEM); @@ -702,12 +712,14 @@ static av_cold int init(AVFilterContext *ctx) if (!s->fontfile && !CONFIG_LIBFONTCONFIG) { av_log(ctx, AV_LOG_ERROR, "No font filename provided\n"); return AVERROR(EINVAL); } + av_bprint_init(&s->expanded_textfile, 0, AV_BPRINT_SIZE_UNLIMITED); + if (s->textfile) { if (s->text) { av_log(ctx, AV_LOG_ERROR, "Both text and text file provided. Please provide only one\n"); return AVERROR(EINVAL); } @@ -820,12 +832,13 @@ static av_cold void uninit(AVFilterContext *ctx) FT_Done_Face(s->face); FT_Stroker_Done(s->stroker); FT_Done_FreeType(s->library); av_bprint_finalize(&s->expanded_text, NULL); av_bprint_finalize(&s->expanded_fontcolor, NULL); + av_bprint_finalize(&s->expanded_textfile, NULL); } static int config_input(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; DrawTextContext *s = ctx->priv; -- 2.26.2 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".