From 89a57148934ec7f150a6170ac1313f6f5c636596 Mon Sep 17 00:00:00 2001 From: Uoti Urpala Date: Sat, 25 Aug 2012 21:22:39 +0300 Subject: subs: always use sub decoder framework for libass rendering Remove subtitle selection code setting osd->ass_track directly and vf_ass/vf_vo code rendering the track directly with libass. Instead, do track selection and rendering with dec_sub.c functions. Before, mpctx->set_of_ass_tracks[] contained bare libass tracks generated from external subtitle files. For use with dec_sub.c, it now contains struct sh_sub instances with decoder already initialized. This commit breaks the sub_step command ('g' and 'y' keys) for libass-rendered subtitles. It could be fixed, but it's so useless - especially as with the existing implementation there's no practical way to get subtitle delay back to normal after using it - that I didn't bother. Conflicts: command.c mp_core.h mplayer.c --- sub/ass_mp.h | 6 ------ sub/dec_sub.c | 29 ++++++++++++++++++++++++++--- sub/dec_sub.h | 11 +++++++++++ sub/osd_libass.c | 4 +++- sub/sd.h | 3 +++ sub/sd_ass.c | 53 +++++++++++++++++++++++++++++++++++++++++++---------- sub/sub.c | 4 +++- sub/sub.h | 15 +++++++++------ 8 files changed, 98 insertions(+), 27 deletions(-) (limited to 'sub') diff --git a/sub/ass_mp.h b/sub/ass_mp.h index 095cf4311d..3cfbe147b7 100644 --- a/sub/ass_mp.h +++ b/sub/ass_mp.h @@ -61,10 +61,4 @@ typedef struct ass_image { #endif -typedef struct { - ASS_Image *imgs; - int changed; -} mp_eosd_images_t; - - #endif /* MPLAYER_ASS_MP_H */ diff --git a/sub/dec_sub.c b/sub/dec_sub.c index 7528e90e58..c710ff575a 100644 --- a/sub/dec_sub.c +++ b/sub/dec_sub.c @@ -22,8 +22,9 @@ #include "config.h" #include "libmpdemux/stheader.h" -#include "sd.h" -#include "dec_sub.h" +#include "sub/sd.h" +#include "sub/sub.h" +#include "sub/dec_sub.h" #include "options.h" extern const struct sd_functions sd_ass; @@ -33,6 +34,7 @@ void sub_init(struct sh_sub *sh, struct osd_state *osd) { struct MPOpts *opts = sh->opts; + assert(!osd->sh_sub); #ifdef CONFIG_ASS if (opts->ass_enabled && is_text_sub(sh->type)) sh->sd_driver = &sd_ass; @@ -42,6 +44,8 @@ void sub_init(struct sh_sub *sh, struct osd_state *osd) if (sh->sd_driver) { if (sh->sd_driver->init(sh, osd) < 0) return; + osd->sh_sub = sh; + osd->changed_outside_sd = true; sh->initialized = true; sh->active = true; } @@ -54,6 +58,22 @@ void sub_decode(struct sh_sub *sh, struct osd_state *osd, void *data, sh->sd_driver->decode(sh, osd, data, data_len, pts, duration); } +void sub_get_bitmaps(struct osd_state *osd, struct sub_bitmaps *res) +{ + struct MPOpts *opts = osd->opts; + + *res = (struct sub_bitmaps){.imgs = NULL, .changed = 2}; + if (!opts->sub_visibility || !osd->sh_sub || !osd->sh_sub->active) { + osd->changed_outside_sd = true; + return; + } + if (osd->sh_sub->sd_driver->get_bitmaps) + osd->sh_sub->sd_driver->get_bitmaps(osd->sh_sub, osd, res); + if (osd->changed_outside_sd) + res->changed = 2; + osd->changed_outside_sd = false; +} + void sub_reset(struct sh_sub *sh, struct osd_state *osd) { if (sh->active && sh->sd_driver->reset) @@ -62,8 +82,11 @@ void sub_reset(struct sh_sub *sh, struct osd_state *osd) void sub_switchoff(struct sh_sub *sh, struct osd_state *osd) { - if (sh->active && sh->sd_driver->switch_off) + if (sh->active && sh->sd_driver->switch_off) { + assert(osd->sh_sub == sh); sh->sd_driver->switch_off(sh, osd); + osd->sh_sub = NULL; + } sh->active = false; } diff --git a/sub/dec_sub.h b/sub/dec_sub.h index e58ad65550..f09b555685 100644 --- a/sub/dec_sub.h +++ b/sub/dec_sub.h @@ -3,12 +3,18 @@ struct sh_sub; struct osd_state; +struct ass_track; typedef struct mp_eosd_res { int w, h; // screen dimensions, including black borders int mt, mb, ml, mr; // borders (top, bottom, left, right) } mp_eosd_res_t; +typedef struct sub_bitmaps { + struct ass_image *imgs; + int changed; +} mp_eosd_images_t; + static inline bool is_text_sub(int type) { return type == 't' || type == 'm' || type == 'a'; @@ -16,9 +22,14 @@ static inline bool is_text_sub(int type) void sub_decode(struct sh_sub *sh, struct osd_state *osd, void *data, int data_len, double pts, double duration); +void sub_get_bitmaps(struct osd_state *osd, struct sub_bitmaps *res); void sub_init(struct sh_sub *sh, struct osd_state *osd); void sub_reset(struct sh_sub *sh, struct osd_state *osd); void sub_switchoff(struct sh_sub *sh, struct osd_state *osd); void sub_uninit(struct sh_sub *sh); +struct sh_sub *sd_ass_create_from_track(struct ass_track *track, + bool vsfilter_aspect, + struct MPOpts *opts); + #endif diff --git a/sub/osd_libass.c b/sub/osd_libass.c index 9f15173442..e770215ce6 100644 --- a/sub/osd_libass.c +++ b/sub/osd_libass.c @@ -331,9 +331,11 @@ void vo_update_text_progbar(struct osd_state *osd, mp_osd_obj_t* obj) void vo_update_text_sub(struct osd_state *osd, mp_osd_obj_t* obj) { + struct MPOpts *opts = osd->opts; + obj->flags |= OSDFLAG_CHANGED | OSDFLAG_VISIBLE; - if (!vo_sub || !sub_visibility) { + if (!vo_sub || !opts->sub_visibility) { obj->flags &= ~OSDFLAG_VISIBLE; return; } diff --git a/sub/sd.h b/sub/sd.h index c36110277b..7a0740f823 100644 --- a/sub/sd.h +++ b/sub/sd.h @@ -3,11 +3,14 @@ struct osd_state; struct sh_sub; +struct sub_bitmaps; struct sd_functions { int (*init)(struct sh_sub *sh, struct osd_state *osd); void (*decode)(struct sh_sub *sh, struct osd_state *osd, void *data, int data_len, double pts, double duration); + void (*get_bitmaps)(struct sh_sub *sh, struct osd_state *osd, + struct sub_bitmaps *res); void (*reset)(struct sh_sub *sh, struct osd_state *osd); void (*switch_off)(struct sh_sub *sh, struct osd_state *osd); void (*uninit)(struct sh_sub *sh); diff --git a/sub/sd_ass.c b/sub/sd_ass.c index f54c18e805..72dee06018 100644 --- a/sub/sd_ass.c +++ b/sub/sd_ass.c @@ -23,6 +23,7 @@ #include "talloc.h" +#include "options.h" #include "mpcommon.h" #include "mp_msg.h" #include "libmpdemux/stheader.h" @@ -33,6 +34,7 @@ struct sd_ass_priv { struct ass_track *ass_track; + bool vsfilter_aspect; bool incomplete_event; }; @@ -61,9 +63,7 @@ static int init(struct sh_sub *sh, struct osd_state *osd) ctx->ass_track = mp_ass_default_track(osd->ass_library, sh->opts); } - assert(osd->ass_track == NULL); - osd->ass_track = ctx->ass_track; - osd->vsfilter_aspect = sh->type == 'a'; + ctx->vsfilter_aspect = sh->type == 'a'; return 0; } @@ -125,6 +125,25 @@ static void decode(struct sh_sub *sh, struct osd_state *osd, void *data, event->Text = strdup(buf); } +static void get_bitmaps(struct sh_sub *sh, struct osd_state *osd, + struct sub_bitmaps *res) +{ + struct sd_ass_priv *ctx = sh->context; + struct MPOpts *opts = osd->opts; + + if (osd->sub_pts == MP_NOPTS_VALUE) + return; + + double scale = osd->normal_scale; + if (ctx->vsfilter_aspect && opts->ass_vsfilter_aspect_compat) + scale = osd->vsfilter_scale; + ASS_Renderer *renderer = osd->ass_renderer; + mp_ass_configure(renderer, opts, &osd->dim, osd->unscaled); + ass_set_aspect_ratio(renderer, scale, 1); + res->imgs = ass_render_frame(renderer, ctx->ass_track, + osd->sub_pts * 1000 + .5, &res->changed); +} + static void reset(struct sh_sub *sh, struct osd_state *osd) { struct sd_ass_priv *ctx = sh->context; @@ -133,12 +152,6 @@ static void reset(struct sh_sub *sh, struct osd_state *osd) ctx->incomplete_event = false; } -static void switch_off(struct sh_sub *sh, struct osd_state *osd) -{ - reset(sh, osd); - osd->ass_track = NULL; -} - static void uninit(struct sh_sub *sh) { struct sd_ass_priv *ctx = sh->context; @@ -150,7 +163,27 @@ static void uninit(struct sh_sub *sh) const struct sd_functions sd_ass = { .init = init, .decode = decode, + .get_bitmaps = get_bitmaps, .reset = reset, - .switch_off = switch_off, + .switch_off = reset, .uninit = uninit, }; + + +struct sh_sub *sd_ass_create_from_track(struct ass_track *track, + bool vsfilter_aspect, + struct MPOpts *opts) +{ + struct sh_sub *sh = talloc(NULL, struct sh_sub); + *sh = (struct sh_sub) { + .opts = opts, + .type = 'a', + .sd_driver = &sd_ass, + .context = talloc_struct(sh, struct sd_ass_priv, { + .ass_track = track, + .vsfilter_aspect = vsfilter_aspect, + }), + .initialized = true, + }; + return sh; +} diff --git a/sub/sub.c b/sub/sub.c index 67413c936e..5b5920d23c 100644 --- a/sub/sub.c +++ b/sub/sub.c @@ -30,6 +30,7 @@ #include "osdep/timer.h" #include "talloc.h" +#include "options.h" #include "mplayer.h" #include "mp_msg.h" #include "libvo/video_out.h" @@ -170,6 +171,7 @@ static int osd_update_ext(struct osd_state *osd, int dxs, int dys, int left_border, int top_border, int right_border, int bottom_border, int orig_w, int orig_h) { + struct MPOpts *opts = osd->opts; mp_osd_obj_t* obj=vo_osd_list; int chg=0; @@ -190,7 +192,7 @@ static int osd_update_ext(struct osd_state *osd, int dxs, int dys, vo_update_text_progbar(osd, obj); break; case OSDTYPE_SPU: - if(sub_visibility && vo_spudec && spudec_visible(vo_spudec)){ + if (opts->sub_visibility && vo_spudec && spudec_visible(vo_spudec)){ vo_update_spudec_sub(osd, obj); obj->flags|=OSDFLAG_VISIBLE|OSDFLAG_CHANGED; } diff --git a/sub/sub.h b/sub/sub.h index 3ad8dc9217..8a8a2ab941 100644 --- a/sub/sub.h +++ b/sub/sub.h @@ -62,15 +62,19 @@ typedef struct mp_osd_obj_s { struct osd_state { struct ass_library *ass_library; struct ass_renderer *ass_renderer; - int w, h; - char *osd_text; - struct ass_track *ass_track; - double pts; + struct sh_sub *sh_sub; + bool changed_outside_sd; + double sub_pts; double sub_offset; - bool vsfilter_aspect; + struct mp_eosd_res dim; + double normal_scale; + double vsfilter_scale; + bool unscaled; struct ass_renderer *osd_render; struct ass_library *osd_ass_library; + char *osd_text; + int w, h; struct MPOpts *opts; }; @@ -113,7 +117,6 @@ extern char *sub_cp; extern int sub_pos; extern int sub_width_p; extern int sub_alignment; -extern int sub_visibility; extern int sub_bg_color; /* subtitles background color */ extern int sub_bg_alpha; extern int spu_alignment; -- cgit v1.2.3