1
0
mirror of https://github.com/mpv-player/mpv synced 2025-02-03 21:52:12 +00:00

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.
This commit is contained in:
wm4 2013-12-15 15:04:49 +01:00
parent 3194058309
commit 78b5324eee
3 changed files with 53 additions and 46 deletions

View File

@ -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);

View File

@ -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

View File

@ -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);
}