Browse Source

vf_drawtext: fontconfig support.

tags/n0.11
Nicolas George 13 years ago
parent
commit
40b7a27bad
4 changed files with 111 additions and 8 deletions
  1. +1
    -0
      Changelog
  2. +3
    -0
      configure
  3. +12
    -0
      doc/filters.texi
  4. +95
    -8
      libavfilter/vf_drawtext.c

+ 1
- 0
Changelog View File

@@ -23,6 +23,7 @@ version next:
- OpenEXR image decoder - OpenEXR image decoder
- removelogo filter - removelogo filter
- drop support for ffmpeg without libavfilter - drop support for ffmpeg without libavfilter
- drawtext video filter: fontconfig support




version 0.10: version 0.10:


+ 3
- 0
configure View File

@@ -166,6 +166,7 @@ Individual component options:
External library support: External library support:
--enable-avisynth enable reading of AVISynth script files [no] --enable-avisynth enable reading of AVISynth script files [no]
--enable-bzlib enable bzlib [autodetect] --enable-bzlib enable bzlib [autodetect]
--enable-fontconfig enable fontconfig
--enable-frei0r enable frei0r video filtering --enable-frei0r enable frei0r video filtering
--enable-gnutls enable gnutls [no] --enable-gnutls enable gnutls [no]
--enable-libaacplus enable AAC+ encoding via libaacplus [no] --enable-libaacplus enable AAC+ encoding via libaacplus [no]
@@ -1022,6 +1023,7 @@ CONFIG_LIST="
dxva2 dxva2
fastdiv fastdiv
fft fft
fontconfig
frei0r frei0r
gnutls gnutls
gpl gpl
@@ -3164,6 +3166,7 @@ check_mathfunc truncf


# these are off by default, so fail if requested and not available # these are off by default, so fail if requested and not available
enabled avisynth && require2 vfw32 "windows.h vfw.h" AVIFileInit -lavifil32 enabled avisynth && require2 vfw32 "windows.h vfw.h" AVIFileInit -lavifil32
enabled fontconfig && require_pkg_config fontconfig "fontconfig/fontconfig.h" FcInit
enabled frei0r && { check_header frei0r.h || die "ERROR: frei0r.h header not found"; } enabled frei0r && { check_header frei0r.h || die "ERROR: frei0r.h header not found"; }
enabled gnutls && require_pkg_config gnutls gnutls/gnutls.h gnutls_global_init enabled gnutls && require_pkg_config gnutls gnutls/gnutls.h gnutls_global_init
enabled libaacplus && require "libaacplus >= 2.0.0" aacplus.h aacplusEncOpen -laacplus enabled libaacplus && require "libaacplus >= 2.0.0" aacplus.h aacplusEncOpen -laacplus


+ 12
- 0
doc/filters.texi View File

@@ -1414,6 +1414,9 @@ with or without text parameter. @var{rate} option must be specified.
frame rate (timecode only) frame rate (timecode only)
@end table @end table


If libavfilter was built with @code{--enable-fontconfig}, then
@option{fontfile} can be a fontconfig pattern or omitted.

Some examples follow. Some examples follow.


@itemize @itemize
@@ -1467,11 +1470,20 @@ The glyph baseline is placed at half screen height.
drawtext=fontsize=60:fontfile=FreeSerif.ttf:fontcolor=green:text=g:x=(w-max_glyph_w)/2:y=h/2-ascent drawtext=fontsize=60:fontfile=FreeSerif.ttf:fontcolor=green:text=g:x=(w-max_glyph_w)/2:y=h/2-ascent
@end example @end example


@item
Use fontconfig to set the font. Note that the colons need to be escaped.
@example
drawtext='fontfile=Linux Libertine O-40\\:style=Semibold:text=FFmpeg'
@end example

@end itemize @end itemize


For more information about libfreetype, check: For more information about libfreetype, check:
@url{http://www.freetype.org/}. @url{http://www.freetype.org/}.


For more information about fontconfig, check:
@url{http://freedesktop.org/software/fontconfig/fontconfig-user.html}.

@section fade @section fade


Apply fade-in/out effect to input video. Apply fade-in/out effect to input video.


+ 95
- 8
libavfilter/vf_drawtext.c View File

@@ -48,6 +48,9 @@
#include <freetype/config/ftheader.h> #include <freetype/config/ftheader.h>
#include FT_FREETYPE_H #include FT_FREETYPE_H
#include FT_GLYPH_H #include FT_GLYPH_H
#if CONFIG_FONTCONFIG
#include <fontconfig/fontconfig.h>
#endif


static const char *const var_names[] = { static const char *const var_names[] = {
"main_w", "w", "W", ///< width of the input video "main_w", "w", "W", ///< width of the input video
@@ -167,7 +170,7 @@ static const AVOption drawtext_options[]= {
{"boxcolor", "set box color", OFFSET(boxcolor_string), AV_OPT_TYPE_STRING, {.str="white"}, CHAR_MIN, CHAR_MAX }, {"boxcolor", "set box color", OFFSET(boxcolor_string), AV_OPT_TYPE_STRING, {.str="white"}, CHAR_MIN, CHAR_MAX },
{"shadowcolor", "set shadow color", OFFSET(shadowcolor_string), AV_OPT_TYPE_STRING, {.str="black"}, CHAR_MIN, CHAR_MAX }, {"shadowcolor", "set shadow color", OFFSET(shadowcolor_string), AV_OPT_TYPE_STRING, {.str="black"}, CHAR_MIN, CHAR_MAX },
{"box", "set box", OFFSET(draw_box), AV_OPT_TYPE_INT, {.dbl=0}, 0, 1 }, {"box", "set box", OFFSET(draw_box), AV_OPT_TYPE_INT, {.dbl=0}, 0, 1 },
{"fontsize", "set font size", OFFSET(fontsize), AV_OPT_TYPE_INT, {.dbl=16}, 1, INT_MAX },
{"fontsize", "set font size", OFFSET(fontsize), AV_OPT_TYPE_INT, {.dbl=0}, 0, INT_MAX },
{"x", "set x expression", OFFSET(x_expr), AV_OPT_TYPE_STRING, {.str="0"}, CHAR_MIN, CHAR_MAX }, {"x", "set x expression", OFFSET(x_expr), AV_OPT_TYPE_STRING, {.str="0"}, CHAR_MIN, CHAR_MAX },
{"y", "set y expression", OFFSET(y_expr), AV_OPT_TYPE_STRING, {.str="0"}, CHAR_MIN, CHAR_MAX }, {"y", "set y expression", OFFSET(y_expr), AV_OPT_TYPE_STRING, {.str="0"}, CHAR_MIN, CHAR_MAX },
{"shadowx", "set x", OFFSET(shadowx), AV_OPT_TYPE_INT, {.dbl=0}, INT_MIN, INT_MAX }, {"shadowx", "set x", OFFSET(shadowx), AV_OPT_TYPE_INT, {.dbl=0}, INT_MIN, INT_MAX },
@@ -298,6 +301,91 @@ error:
return ret; return ret;
} }


static int load_font_file(AVFilterContext *ctx, const char *path, int index,
const char **error)
{
DrawTextContext *dtext = ctx->priv;
int err;

err = FT_New_Face(dtext->library, path, index, &dtext->face);
if (err) {
*error = FT_ERRMSG(err);
return AVERROR(EINVAL);
}
return 0;
}

#if CONFIG_FONTCONFIG
static int load_font_fontconfig(AVFilterContext *ctx, const char **error)
{
DrawTextContext *dtext = ctx->priv;
FcConfig *fontconfig;
FcPattern *pattern, *fpat;
FcResult result = FcResultMatch;
FcChar8 *filename;
int err, index;
double size;

fontconfig = FcInitLoadConfigAndFonts();
if (!fontconfig) {
*error = "impossible to init fontconfig\n";
return AVERROR(EINVAL);
}
pattern = FcNameParse(dtext->fontfile ? dtext->fontfile :
(uint8_t *)(intptr_t)"default");
if (!pattern) {
*error = "could not parse fontconfig pattern";
return AVERROR(EINVAL);
}
if (!FcConfigSubstitute(fontconfig, pattern, FcMatchPattern)) {
*error = "could not substitue fontconfig options"; /* very unlikely */
return AVERROR(EINVAL);
}
FcDefaultSubstitute(pattern);
fpat = FcFontMatch(fontconfig, pattern, &result);
if (!fpat || result != FcResultMatch) {
*error = "impossible to find a matching font";
return AVERROR(EINVAL);
}
if (FcPatternGetString (fpat, FC_FILE, 0, &filename) != FcResultMatch ||
FcPatternGetInteger(fpat, FC_INDEX, 0, &index ) != FcResultMatch ||
FcPatternGetDouble (fpat, FC_SIZE, 0, &size ) != FcResultMatch) {
*error = "impossible to find font information";
return AVERROR(EINVAL);
}
av_log(ctx, AV_LOG_INFO, "Using \"%s\"\n", filename);
if (!dtext->fontsize)
dtext->fontsize = size + 0.5;
err = load_font_file(ctx, filename, index, error);
if (err)
return err;
FcPatternDestroy(fpat);
FcPatternDestroy(pattern);
FcConfigDestroy(fontconfig);
return 0;
}
#endif

static int load_font(AVFilterContext *ctx)
{
DrawTextContext *dtext = ctx->priv;
int err;
const char *error = "unknown error\n";

/* load the face, and set up the encoding, which is by default UTF-8 */
err = load_font_file(ctx, dtext->fontfile, 0, &error);
if (!err)
return 0;
#if CONFIG_FONTCONFIG
err = load_font_fontconfig(ctx, &error);
if (!err)
return 0;
#endif
av_log(ctx, AV_LOG_ERROR, "Could not load font \"%s\": %s\n",
dtext->fontfile, error);
return err;
}

static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
{ {
int err; int err;
@@ -312,7 +400,7 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
return err; return err;
} }


if (!dtext->fontfile) {
if (!dtext->fontfile && !CONFIG_FONTCONFIG) {
av_log(ctx, AV_LOG_ERROR, "No font filename provided\n"); av_log(ctx, AV_LOG_ERROR, "No font filename provided\n");
return AVERROR(EINVAL); return AVERROR(EINVAL);
} }
@@ -381,12 +469,11 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
return AVERROR(EINVAL); return AVERROR(EINVAL);
} }


/* load the face, and set up the encoding, which is by default UTF-8 */
if ((err = FT_New_Face(dtext->library, dtext->fontfile, 0, &dtext->face))) {
av_log(ctx, AV_LOG_ERROR, "Could not load fontface from file '%s': %s\n",
dtext->fontfile, FT_ERRMSG(err));
return AVERROR(EINVAL);
}
err = load_font(ctx);
if (err)
return err;
if (!dtext->fontsize)
dtext->fontsize = 16;
if ((err = FT_Set_Pixel_Sizes(dtext->face, 0, dtext->fontsize))) { if ((err = FT_Set_Pixel_Sizes(dtext->face, 0, dtext->fontsize))) {
av_log(ctx, AV_LOG_ERROR, "Could not set font size to %d pixels: %s\n", av_log(ctx, AV_LOG_ERROR, "Could not set font size to %d pixels: %s\n",
dtext->fontsize, FT_ERRMSG(err)); dtext->fontsize, FT_ERRMSG(err));


Loading…
Cancel
Save