From 7e6b3ad6930c2f1daa5c4831bbeda3fb931921e6 Mon Sep 17 00:00:00 2001 From: Facundo Gaich Date: Wed, 9 Apr 2014 00:18:35 -0300 Subject: [PATCH] lavfi/subtitles: load attached fonts to libass. Videos with complex typesetting usually have font files embedded as attachment streams. vf_subtitles now finds all attachment streams with a MIME type associated with fonts and loads them to libass so it can use them for rendering. The code was basically ported from mpv's loadfile.c@929793be7 Signed-off-by: Facundo Gaich --- libavfilter/vf_subtitles.c | 54 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/libavfilter/vf_subtitles.c b/libavfilter/vf_subtitles.c index e44f61ddcd..bce0e9fe1b 100644 --- a/libavfilter/vf_subtitles.c +++ b/libavfilter/vf_subtitles.c @@ -107,7 +107,6 @@ static av_cold int init(AVFilterContext *ctx) return AVERROR(EINVAL); } - ass_set_fonts(ass->renderer, NULL, NULL, 1, NULL, 1); return 0; } @@ -218,6 +217,9 @@ static av_cold int init_ass(AVFilterContext *ctx) if (ret < 0) return ret; + /* Initialize fonts */ + ass_set_fonts(ass->renderer, NULL, NULL, 1, NULL, 1); + ass->track = ass_read_file(ass->library, ass->filename, NULL); if (!ass->track) { av_log(ctx, AV_LOG_ERROR, @@ -249,11 +251,34 @@ static const AVOption subtitles_options[] = { {NULL}, }; +static const char *font_mimetypes[] = { + "application/x-truetype-font", + "application/vnd.ms-opentype", + "application/x-font-ttf", + NULL +}; + +static int attachment_is_font(AVStream * st) +{ + const AVDictionaryEntry *tag = NULL; + int n; + + tag = av_dict_get(st->metadata, "mimetype", NULL, AV_DICT_MATCH_CASE); + + if (tag) { + for (n = 0; font_mimetypes[n]; n++) { + if (av_strcasecmp(font_mimetypes[n], tag->value) == 0) + return 1; + } + } + return 0; +} + AVFILTER_DEFINE_CLASS(subtitles); static av_cold int init_subtitles(AVFilterContext *ctx) { - int ret, sid; + int j, ret, sid; AVDictionary *codec_opts = NULL; AVFormatContext *fmt = NULL; AVCodecContext *dec_ctx = NULL; @@ -293,6 +318,31 @@ static av_cold int init_subtitles(AVFilterContext *ctx) sid = ret; st = fmt->streams[sid]; + /* Load attached fonts */ + for (j = 0; j < fmt->nb_streams; j++) { + AVStream *st = fmt->streams[j]; + if (st->codec->codec_type == AVMEDIA_TYPE_ATTACHMENT && + attachment_is_font(st)) { + const AVDictionaryEntry *tag = NULL; + tag = av_dict_get(st->metadata, "filename", NULL, + AV_DICT_MATCH_CASE); + + if (tag) { + av_log(ctx, AV_LOG_DEBUG, "Loading attached font: %s\n", + tag->value); + ass_add_font(ass->library, tag->value, + st->codec->extradata, + st->codec->extradata_size); + } else { + av_log(ctx, AV_LOG_WARNING, + "Font attachment has no filename, ignored.\n"); + } + } + } + + /* Initialize fonts */ + ass_set_fonts(ass->renderer, NULL, NULL, 1, NULL, 1); + /* Open decoder */ dec_ctx = st->codec; dec = avcodec_find_decoder(dec_ctx->codec_id);