From fd52cb65f43d262493724899c7b0fb49971f745d Mon Sep 17 00:00:00 2001 From: Uoti Urpala Date: Tue, 28 Aug 2012 19:12:27 +0300 Subject: subs, vo: do sub bitmap change detection by comparing IDs vo_vdpau and vo_gl cache the last subtitle bitmaps uploaded to video card in case they stay the same over multiple frames. Detecting whether the bitmaps have changed and should be re-uploaded was somewhat fragile. Change the VO API to provide a bitmap ID which can be compared with what the VO has to determine whether a new upload of the bitmaps is needed. Conflicts: libvo/vo_gl.c Note: the changes for vo_gl.c were not merged. Instead, eosd_packer is modified to use the new way of detecting EOSD changes. This takes care of vo_gl, vo_gl3 and vo_direct3d, which all render EOSD. They don't need to be updated in turn. --- libmpcodecs/vf_vo.c | 16 +--------------- libvo/eosd_packer.c | 13 +++++++------ libvo/eosd_packer.h | 2 ++ libvo/vo_vdpau.c | 9 +++++++-- sub/dec_sub.c | 19 +++++++++++++------ sub/dec_sub.h | 2 +- sub/sd_ass.c | 7 ++++++- sub/sub.h | 3 ++- 8 files changed, 39 insertions(+), 32 deletions(-) diff --git a/libmpcodecs/vf_vo.c b/libmpcodecs/vf_vo.c index 076850c8c2..3aec40cd15 100644 --- a/libmpcodecs/vf_vo.c +++ b/libmpcodecs/vf_vo.c @@ -34,7 +34,6 @@ struct vf_priv_s { struct vo *vo; - bool prev_visibility; double scale_ratio; }; #define video_out (vf->priv->vo) @@ -77,9 +76,6 @@ static int config(struct vf_instance *vf, vf->priv->scale_ratio = (double) d_width / d_height * height / width; - // force EOSD change detection reset - vf->priv->prev_visibility = false; - return 1; } @@ -121,27 +117,17 @@ static int control(struct vf_instance *vf, int request, void *data) }; return vo_control(video_out, VOCTRL_GET_EQUALIZER, ¶m) == VO_TRUE; } - case VFCTRL_INIT_EOSD: { - vf->priv->prev_visibility = false; - return CONTROL_TRUE; - } - case VFCTRL_DRAW_EOSD: { struct osd_state *osd = data; osd->dim = (struct mp_eosd_res){0}; if (!video_out->config_ok || - vo_control(video_out, VOCTRL_GET_EOSD_RES, &osd->dim) != true) { - vf->priv->prev_visibility = false; + vo_control(video_out, VOCTRL_GET_EOSD_RES, &osd->dim) != true) return CONTROL_FALSE; - } osd->normal_scale = 1; osd->vsfilter_scale = vf->priv->scale_ratio; osd->unscaled = vf->default_caps & VFCAP_EOSD_UNSCALED; struct sub_bitmaps images; sub_get_bitmaps(osd, &images); - if (!vf->priv->prev_visibility) - images.changed = 2; - vf->priv->prev_visibility = true; return vo_control(video_out, VOCTRL_DRAW_EOSD, &images) == VO_TRUE; } } diff --git a/libvo/eosd_packer.c b/libvo/eosd_packer.c index 103648b7c4..8f831d512e 100644 --- a/libvo/eosd_packer.c +++ b/libvo/eosd_packer.c @@ -147,17 +147,18 @@ void eosd_packer_generate(struct eosd_packer *state, mp_eosd_images_t *imgs, ASS_Image *p; struct eosd_surface *sfc = &state->surface; - *out_need_reposition = false; - *out_need_upload = false; + *out_need_reposition = imgs->bitmap_pos_id != state->last_bitmap_pos_id; + *out_need_upload = imgs->bitmap_id != state->last_bitmap_id; *out_need_reallocate = false; - int change_state = imgs->changed; + state->last_bitmap_pos_id = imgs->bitmap_pos_id; + state->last_bitmap_id = imgs->bitmap_id; // eosd_reinit() was probably called, force full reupload. if (state->targets_count == 0 && img) - change_state = 2; + *out_need_upload = true; - if (change_state == 0) + if (!(*out_need_reposition) && !(*out_need_upload)) return; // Nothing changed, no need to redraw state->targets_count = 0; @@ -167,7 +168,7 @@ void eosd_packer_generate(struct eosd_packer *state, mp_eosd_images_t *imgs, if (!img) return; // There's nothing to render! - if (change_state == 1) + if (!(*out_need_upload)) goto eosd_skip_upload; *out_need_upload = true; diff --git a/libvo/eosd_packer.h b/libvo/eosd_packer.h index eaacd0223f..228057d3c4 100644 --- a/libvo/eosd_packer.h +++ b/libvo/eosd_packer.h @@ -58,6 +58,8 @@ struct eosd_packer { uint32_t max_surface_height; int *scratch; + int last_bitmap_id; + int last_bitmap_pos_id; }; struct eosd_packer *eosd_packer_create(void *talloc_ctx); diff --git a/libvo/vo_vdpau.c b/libvo/vo_vdpau.c index d9b59c7dbe..922ec24201 100644 --- a/libvo/vo_vdpau.c +++ b/libvo/vo_vdpau.c @@ -186,6 +186,8 @@ struct vdpctx { } *eosd_targets, osd_targets[MAX_OLD_OSD_BITMAPS][2]; int eosd_targets_size; int eosd_render_count; + int bitmap_id; + int bitmap_pos_id; // Video equalizer struct mp_csp_equalizer video_eq; @@ -812,6 +814,7 @@ static void mark_vdpau_objects_uninitialized(struct vo *vo) vc->vdp_device = VDP_INVALID_HANDLE; talloc_free(vc->osd_surface.packer); talloc_free(vc->eosd_surface.packer); + vc->bitmap_id = vc->bitmap_pos_id = 0; vc->osd_surface = vc->eosd_surface = (struct eosd_bitmap_surface){ .surface = VDP_INVALID_HANDLE, }; @@ -999,7 +1002,7 @@ static void generate_eosd(struct vo *vo, mp_eosd_images_t *imgs) struct eosd_bitmap_surface *sfc = &vc->eosd_surface; bool need_upload = false; - if (imgs->changed == 0 && sfc->packer) + if (imgs->bitmap_pos_id == vc->bitmap_pos_id) return; // Nothing changed and we still have the old data vc->eosd_render_count = 0; @@ -1007,7 +1010,7 @@ static void generate_eosd(struct vo *vo, mp_eosd_images_t *imgs) if (!imgs->imgs) return; // There's nothing to render! - if (imgs->changed == 1) + if (imgs->bitmap_id == vc->bitmap_id) goto eosd_skip_upload; need_upload = true; @@ -1069,6 +1072,8 @@ eosd_skip_upload: target->dest.y1 = p->h + p->dst_y; vc->eosd_render_count++; } + vc->bitmap_id = imgs->bitmap_id; + vc->bitmap_pos_id = imgs->bitmap_pos_id; } static void record_osd(void *ctx, int x0, int y0, int w, int h, diff --git a/sub/dec_sub.c b/sub/dec_sub.c index c710ff575a..3278c10d85 100644 --- a/sub/dec_sub.c +++ b/sub/dec_sub.c @@ -45,7 +45,7 @@ void sub_init(struct sh_sub *sh, struct osd_state *osd) if (sh->sd_driver->init(sh, osd) < 0) return; osd->sh_sub = sh; - osd->changed_outside_sd = true; + osd->bitmap_id = ++osd->bitmap_pos_id; sh->initialized = true; sh->active = true; } @@ -62,16 +62,23 @@ 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}; + *res = (struct sub_bitmaps){ .bitmap_id = osd->bitmap_id, + .bitmap_pos_id = osd->bitmap_pos_id }; if (!opts->sub_visibility || !osd->sh_sub || !osd->sh_sub->active) { - osd->changed_outside_sd = true; + /* Change ID in case we just switched from visible subtitles + * to current state. Hopefully, unnecessarily claiming that + * things may have changed is harmless for empty contents. + * Increase osd-> values ahead so that _next_ returned id + * is also guaranteed to differ from this one. + */ + res->bitmap_id = ++res->bitmap_pos_id; + osd->bitmap_id = osd->bitmap_pos_id += 2; 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; + osd->bitmap_id = res->bitmap_id; + osd->bitmap_pos_id = res->bitmap_pos_id; } void sub_reset(struct sh_sub *sh, struct osd_state *osd) diff --git a/sub/dec_sub.h b/sub/dec_sub.h index f09b555685..ae39f15f31 100644 --- a/sub/dec_sub.h +++ b/sub/dec_sub.h @@ -12,7 +12,7 @@ typedef struct mp_eosd_res { typedef struct sub_bitmaps { struct ass_image *imgs; - int changed; + int bitmap_id, bitmap_pos_id; } mp_eosd_images_t; static inline bool is_text_sub(int type) diff --git a/sub/sd_ass.c b/sub/sd_ass.c index 72dee06018..67bbd4665e 100644 --- a/sub/sd_ass.c +++ b/sub/sd_ass.c @@ -140,8 +140,13 @@ static void get_bitmaps(struct sh_sub *sh, struct osd_state *osd, ASS_Renderer *renderer = osd->ass_renderer; mp_ass_configure(renderer, opts, &osd->dim, osd->unscaled); ass_set_aspect_ratio(renderer, scale, 1); + int changed; res->imgs = ass_render_frame(renderer, ctx->ass_track, - osd->sub_pts * 1000 + .5, &res->changed); + osd->sub_pts * 1000 + .5, &changed); + if (changed == 2) + res->bitmap_id = ++res->bitmap_pos_id; + else if (changed) + res->bitmap_pos_id++; } static void reset(struct sh_sub *sh, struct osd_state *osd) diff --git a/sub/sub.h b/sub/sub.h index 8a8a2ab941..05c89af565 100644 --- a/sub/sub.h +++ b/sub/sub.h @@ -63,7 +63,8 @@ struct osd_state { struct ass_library *ass_library; struct ass_renderer *ass_renderer; struct sh_sub *sh_sub; - bool changed_outside_sd; + int bitmap_id; + int bitmap_pos_id; double sub_pts; double sub_offset; struct mp_eosd_res dim; -- cgit v1.2.3