mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-04-14 00:58:38 +02:00
vf_drawtext: fontconfig support.
This commit is contained in:
parent
be9b0d2c5a
commit
40b7a27bad
@ -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
configure
vendored
3
configure
vendored
@ -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
|
||||||
|
@ -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.
|
||||||
|
@ -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 */
|
err = load_font(ctx);
|
||||||
if ((err = FT_New_Face(dtext->library, dtext->fontfile, 0, &dtext->face))) {
|
if (err)
|
||||||
av_log(ctx, AV_LOG_ERROR, "Could not load fontface from file '%s': %s\n",
|
return err;
|
||||||
dtext->fontfile, FT_ERRMSG(err));
|
if (!dtext->fontsize)
|
||||||
return AVERROR(EINVAL);
|
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…
x
Reference in New Issue
Block a user