From 78b5324eeefc2b8a235a8ea412283491ee009a1e Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 15 Dec 2013 15:04:49 +0100 Subject: osd: use separate ASS_Renderer for each OSD object This simplifies things, although it is slightly less efficient (probably uses a bit more memory). This also happens to fix that the OSC dropped the libass cache on every frame. --- sub/ass_mp.c | 5 ++-- sub/osd.h | 8 ++---- sub/osd_libass.c | 86 +++++++++++++++++++++++++++++++------------------------- 3 files changed, 53 insertions(+), 46 deletions(-) (limited to 'sub') diff --git a/sub/ass_mp.c b/sub/ass_mp.c index 72c22d54e6..5ae85c0d06 100644 --- a/sub/ass_mp.c +++ b/sub/ass_mp.c @@ -222,9 +222,10 @@ static void message_callback(int level, const char *format, va_list va, void *ct ASS_Library *mp_ass_init(struct MPOpts *opts) { - ASS_Library *priv; char *path = mp_find_user_config_file("fonts"); - priv = ass_library_init(); + ASS_Library *priv = ass_library_init(); + if (!priv) + abort(); ass_set_message_cb(priv, message_callback, NULL); if (path) ass_set_fonts_dir(priv, path); diff --git a/sub/osd.h b/sub/osd.h index 7f8a2f2141..d869700a92 100644 --- a/sub/osd.h +++ b/sub/osd.h @@ -115,8 +115,10 @@ struct osd_object { struct mp_osd_res vo_res; // Internally used by osd_libass.c - struct ass_track *osd_track; struct sub_bitmap *parts_cache; + struct ass_track *osd_track; + struct ass_renderer *osd_render; + struct ass_library *osd_ass_library; }; struct osd_state { @@ -155,10 +157,6 @@ struct osd_state { // Internal to sub.c struct mp_draw_sub_cache *draw_cache; - - // Internally used by osd_libass.c - struct ass_renderer *osd_render; - struct ass_library *osd_ass_library; }; // Start of OSD symbols in osd_font.pfb diff --git a/sub/osd_libass.c b/sub/osd_libass.c index 71255256a9..38ae0b99cb 100644 --- a/sub/osd_libass.c +++ b/sub/osd_libass.c @@ -41,13 +41,23 @@ static const char osd_font_pfb[] = void osd_init_backend(struct osd_state *osd) { - osd->osd_ass_library = mp_ass_init(osd->opts); - ass_add_font(osd->osd_ass_library, "mpv-osd-symbols", (void *)osd_font_pfb, +} + +static void create_ass_renderer(struct osd_state *osd, struct osd_object *obj) +{ + if (obj->osd_render) + return; + + obj->osd_ass_library = mp_ass_init(osd->opts); + ass_add_font(obj->osd_ass_library, "mpv-osd-symbols", (void *)osd_font_pfb, sizeof(osd_font_pfb) - 1); - osd->osd_render = ass_renderer_init(osd->osd_ass_library); - mp_ass_configure_fonts(osd->osd_render, osd->opts->osd_style); - ass_set_aspect_ratio(osd->osd_render, 1.0, 1.0); + obj->osd_render = ass_renderer_init(obj->osd_ass_library); + if (!obj->osd_render) + abort(); + + mp_ass_configure_fonts(obj->osd_render, osd->opts->osd_style); + ass_set_aspect_ratio(obj->osd_render, 1.0, 1.0); } void osd_destroy_backend(struct osd_state *osd) @@ -57,29 +67,41 @@ void osd_destroy_backend(struct osd_state *osd) if (obj->osd_track) ass_free_track(obj->osd_track); obj->osd_track = NULL; + if (obj->osd_render) + ass_renderer_done(obj->osd_render); + obj->osd_render = NULL; + if (obj->osd_ass_library) + ass_library_done(obj->osd_ass_library); + obj->osd_ass_library = NULL; } - if (osd->osd_render) - ass_renderer_done(osd->osd_render); - osd->osd_render = NULL; - ass_library_done(osd->osd_ass_library); - osd->osd_ass_library = NULL; } -static void create_osd_ass_track(struct osd_state *osd, struct osd_object *obj) +static void create_ass_track(struct osd_state *osd, struct osd_object *obj, + int res_x, int res_y) { + create_ass_renderer(osd, obj); + ASS_Track *track = obj->osd_track; if (!track) - track = ass_new_track(osd->osd_ass_library); + track = ass_new_track(obj->osd_ass_library); + + int old_res_x = track->PlayResX; + int old_res_y = track->PlayResY; double aspect = 1.0 * obj->vo_res.w / FFMAX(obj->vo_res.h, 1) / obj->vo_res.display_par; track->track_type = TRACK_TYPE_ASS; track->Timer = 100.; - track->PlayResY = MP_ASS_FONT_PLAYRESY; - track->PlayResX = track->PlayResY * aspect; + track->PlayResY = res_y ? res_y : MP_ASS_FONT_PLAYRESY; + track->PlayResX = res_x ? res_x : track->PlayResY * aspect; track->WrapStyle = 1; // end-of-line wrapping instead of smart wrapping + // Force libass to clear its internal cache - it doesn't check for + // PlayRes changes itself. + if (old_res_x != track->PlayResX || old_res_y != track->PlayResY) + ass_set_frame_size(obj->osd_render, 1, 1); + if (track->n_styles == 0) { track->Kerning = true; int sid = ass_alloc_style(track); @@ -87,7 +109,7 @@ static void create_osd_ass_track(struct osd_state *osd, struct osd_object *obj) ASS_Style *style = track->styles + sid; style->Alignment = 5; // top-title, left style->Name = strdup("OSD"); - mp_ass_set_style(style, MP_ASS_FONT_PLAYRESY, osd->opts->osd_style); + mp_ass_set_style(style, track->PlayResY, osd->opts->osd_style); // Set to neutral base direction, as opposed to VSFilter LTR default style->Encoding = -1; @@ -95,7 +117,7 @@ static void create_osd_ass_track(struct osd_state *osd, struct osd_object *obj) style = track->styles + sid; style->Name = strdup("Default"); const struct osd_style_opts *def = osd_style_conf.defaults; - mp_ass_set_style(style, MP_ASS_FONT_PLAYRESY, def); + mp_ass_set_style(style, track->PlayResY, def); style->Encoding = -1; } @@ -155,7 +177,7 @@ static void update_osd(struct osd_state *osd, struct osd_object *obj) { struct MPOpts *opts = osd->opts; - create_osd_ass_track(osd, obj); + create_ass_track(osd, obj, 0, 0); clear_obj(obj); if (!osd->osd_text[0]) return; @@ -257,7 +279,7 @@ static void get_osd_bar_box(struct osd_state *osd, struct osd_object *obj, struct MPOpts *opts = osd->opts; bool new_track = !obj->osd_track; - create_osd_ass_track(osd, obj); + create_ass_track(osd, obj, 0, 0); ASS_Track *track = obj->osd_track; ASS_Style *style = track->styles + track->default_style; @@ -361,24 +383,9 @@ static void update_progbar(struct osd_state *osd, struct osd_object *obj) static void update_external(struct osd_state *osd, struct osd_object *obj) { - create_osd_ass_track(osd, obj); + create_ass_track(osd, obj, osd->external_res_x, osd->external_res_y); clear_obj(obj); - if (osd->external_res_x < 1 || osd->external_res_y < 1) - return; - - ASS_Track *track = obj->osd_track; - - if (track->PlayResX != osd->external_res_x || - track->PlayResY != osd->external_res_y) - { - track->PlayResX = osd->external_res_x; - track->PlayResY = osd->external_res_y; - // Force libass to clear its internal cache - it doesn't check for - // PlayRes changes itself. - ass_set_frame_size(osd->osd_render, 1, 1); - } - bstr t = bstr0(osd->external); while (t.len) { bstr line; @@ -400,8 +407,9 @@ static void update_sub(struct osd_state *osd, struct osd_object *obj) if (!osd->sub_text || !osd->sub_text[0]) return; + create_ass_renderer(osd, obj); if (!obj->osd_track) - obj->osd_track = mp_ass_default_track(osd->osd_ass_library, osd->opts); + obj->osd_track = mp_ass_default_track(obj->osd_ass_library, osd->opts); struct osd_style_opts font = *opts->sub_text_style; font.font_size *= opts->sub_scale; @@ -410,7 +418,7 @@ static void update_sub(struct osd_state *osd, struct osd_object *obj) mp_ass_set_style(style, obj->osd_track->PlayResY, &font); #if LIBASS_VERSION >= 0x01010000 - ass_set_line_position(osd->osd_render, 100 - opts->sub_pos); + ass_set_line_position(obj->osd_render, 100 - opts->sub_pos); #endif char *escaped_text = mangle_ass(osd->sub_text); @@ -446,9 +454,9 @@ void osd_object_get_bitmaps(struct osd_state *osd, struct osd_object *obj, if (!obj->osd_track) return; - ass_set_frame_size(osd->osd_render, obj->vo_res.w, obj->vo_res.h); - ass_set_aspect_ratio(osd->osd_render, obj->vo_res.display_par, 1.0); - mp_ass_render_frame(osd->osd_render, obj->osd_track, 0, + ass_set_frame_size(obj->osd_render, obj->vo_res.w, obj->vo_res.h); + ass_set_aspect_ratio(obj->osd_render, obj->vo_res.display_par, 1.0); + mp_ass_render_frame(obj->osd_render, obj->osd_track, 0, &obj->parts_cache, out_imgs); talloc_steal(obj, obj->parts_cache); } -- cgit v1.2.3