mirror of
https://github.com/mpv-player/mpv.git
synced 2025-12-28 05:33:14 +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:
@@ -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 *mp_ass_init(struct MPOpts *opts)
|
||||||
{
|
{
|
||||||
ASS_Library *priv;
|
|
||||||
char *path = mp_find_user_config_file("fonts");
|
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);
|
ass_set_message_cb(priv, message_callback, NULL);
|
||||||
if (path)
|
if (path)
|
||||||
ass_set_fonts_dir(priv, path);
|
ass_set_fonts_dir(priv, path);
|
||||||
|
|||||||
@@ -115,8 +115,10 @@ struct osd_object {
|
|||||||
struct mp_osd_res vo_res;
|
struct mp_osd_res vo_res;
|
||||||
|
|
||||||
// Internally used by osd_libass.c
|
// Internally used by osd_libass.c
|
||||||
struct ass_track *osd_track;
|
|
||||||
struct sub_bitmap *parts_cache;
|
struct sub_bitmap *parts_cache;
|
||||||
|
struct ass_track *osd_track;
|
||||||
|
struct ass_renderer *osd_render;
|
||||||
|
struct ass_library *osd_ass_library;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct osd_state {
|
struct osd_state {
|
||||||
@@ -155,10 +157,6 @@ struct osd_state {
|
|||||||
|
|
||||||
// Internal to sub.c
|
// Internal to sub.c
|
||||||
struct mp_draw_sub_cache *draw_cache;
|
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
|
// Start of OSD symbols in osd_font.pfb
|
||||||
|
|||||||
@@ -41,13 +41,23 @@ static const char osd_font_pfb[] =
|
|||||||
|
|
||||||
void osd_init_backend(struct osd_state *osd)
|
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);
|
sizeof(osd_font_pfb) - 1);
|
||||||
|
|
||||||
osd->osd_render = ass_renderer_init(osd->osd_ass_library);
|
obj->osd_render = ass_renderer_init(obj->osd_ass_library);
|
||||||
mp_ass_configure_fonts(osd->osd_render, osd->opts->osd_style);
|
if (!obj->osd_render)
|
||||||
ass_set_aspect_ratio(osd->osd_render, 1.0, 1.0);
|
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)
|
void osd_destroy_backend(struct osd_state *osd)
|
||||||
@@ -57,29 +67,41 @@ void osd_destroy_backend(struct osd_state *osd)
|
|||||||
if (obj->osd_track)
|
if (obj->osd_track)
|
||||||
ass_free_track(obj->osd_track);
|
ass_free_track(obj->osd_track);
|
||||||
obj->osd_track = NULL;
|
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;
|
ASS_Track *track = obj->osd_track;
|
||||||
if (!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) /
|
double aspect = 1.0 * obj->vo_res.w / FFMAX(obj->vo_res.h, 1) /
|
||||||
obj->vo_res.display_par;
|
obj->vo_res.display_par;
|
||||||
|
|
||||||
track->track_type = TRACK_TYPE_ASS;
|
track->track_type = TRACK_TYPE_ASS;
|
||||||
track->Timer = 100.;
|
track->Timer = 100.;
|
||||||
track->PlayResY = MP_ASS_FONT_PLAYRESY;
|
track->PlayResY = res_y ? res_y : MP_ASS_FONT_PLAYRESY;
|
||||||
track->PlayResX = track->PlayResY * aspect;
|
track->PlayResX = res_x ? res_x : track->PlayResY * aspect;
|
||||||
track->WrapStyle = 1; // end-of-line wrapping instead of smart wrapping
|
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) {
|
if (track->n_styles == 0) {
|
||||||
track->Kerning = true;
|
track->Kerning = true;
|
||||||
int sid = ass_alloc_style(track);
|
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;
|
ASS_Style *style = track->styles + sid;
|
||||||
style->Alignment = 5; // top-title, left
|
style->Alignment = 5; // top-title, left
|
||||||
style->Name = strdup("OSD");
|
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
|
// Set to neutral base direction, as opposed to VSFilter LTR default
|
||||||
style->Encoding = -1;
|
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 = track->styles + sid;
|
||||||
style->Name = strdup("Default");
|
style->Name = strdup("Default");
|
||||||
const struct osd_style_opts *def = osd_style_conf.defaults;
|
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;
|
style->Encoding = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,7 +177,7 @@ static void update_osd(struct osd_state *osd, struct osd_object *obj)
|
|||||||
{
|
{
|
||||||
struct MPOpts *opts = osd->opts;
|
struct MPOpts *opts = osd->opts;
|
||||||
|
|
||||||
create_osd_ass_track(osd, obj);
|
create_ass_track(osd, obj, 0, 0);
|
||||||
clear_obj(obj);
|
clear_obj(obj);
|
||||||
if (!osd->osd_text[0])
|
if (!osd->osd_text[0])
|
||||||
return;
|
return;
|
||||||
@@ -257,7 +279,7 @@ static void get_osd_bar_box(struct osd_state *osd, struct osd_object *obj,
|
|||||||
struct MPOpts *opts = osd->opts;
|
struct MPOpts *opts = osd->opts;
|
||||||
|
|
||||||
bool new_track = !obj->osd_track;
|
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_Track *track = obj->osd_track;
|
||||||
ASS_Style *style = track->styles + track->default_style;
|
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)
|
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);
|
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);
|
bstr t = bstr0(osd->external);
|
||||||
while (t.len) {
|
while (t.len) {
|
||||||
bstr line;
|
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])
|
if (!osd->sub_text || !osd->sub_text[0])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
create_ass_renderer(osd, obj);
|
||||||
if (!obj->osd_track)
|
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;
|
struct osd_style_opts font = *opts->sub_text_style;
|
||||||
font.font_size *= opts->sub_scale;
|
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);
|
mp_ass_set_style(style, obj->osd_track->PlayResY, &font);
|
||||||
|
|
||||||
#if LIBASS_VERSION >= 0x01010000
|
#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
|
#endif
|
||||||
|
|
||||||
char *escaped_text = mangle_ass(osd->sub_text);
|
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)
|
if (!obj->osd_track)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ass_set_frame_size(osd->osd_render, obj->vo_res.w, obj->vo_res.h);
|
ass_set_frame_size(obj->osd_render, obj->vo_res.w, obj->vo_res.h);
|
||||||
ass_set_aspect_ratio(osd->osd_render, obj->vo_res.display_par, 1.0);
|
ass_set_aspect_ratio(obj->osd_render, obj->vo_res.display_par, 1.0);
|
||||||
mp_ass_render_frame(osd->osd_render, obj->osd_track, 0,
|
mp_ass_render_frame(obj->osd_render, obj->osd_track, 0,
|
||||||
&obj->parts_cache, out_imgs);
|
&obj->parts_cache, out_imgs);
|
||||||
talloc_steal(obj, obj->parts_cache);
|
talloc_steal(obj, obj->parts_cache);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user