From fcfd04409008cf1eed62b778f0b388023f00c005 Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 11 Dec 2013 23:15:29 +0100 Subject: [PATCH] sd_lavc: factor out bitmap positioning code --- sub/osd.c | 31 +++++++++++++++++++++++++++++++ sub/osd.h | 3 +++ sub/sd_lavc.c | 44 ++++++++++++++------------------------------ 3 files changed, 48 insertions(+), 30 deletions(-) diff --git a/sub/osd.c b/sub/osd.c index bd06dbf8d4..66b79f7bb8 100644 --- a/sub/osd.c +++ b/sub/osd.c @@ -322,3 +322,34 @@ void osd_object_get_scale_factor(struct osd_state *osd, struct osd_object *obj, *sw = nw / (double)obj->vo_res.w; *sh = nh / (double)obj->vo_res.h; } + +// Position the subbitmaps in imgs on the screen. Basically, this fits the +// subtitle canvas (of size frame_w x frame_h) onto the screen, such that it +// fills the whole video area (especially if the video is magnified, e.g. on +// fullscreen). If compensate_par is given, adjust the way the subtitles are +// "stretched" on the screen, and letter-box the result. +void osd_rescale_bitmaps(struct sub_bitmaps *imgs, int frame_w, int frame_h, + struct mp_osd_res res, double compensate_par) +{ + int vidw = res.w - res.ml - res.mr; + int vidh = res.h - res.mt - res.mb; + double xscale = (double)vidw / frame_w; + double yscale = (double)vidh / frame_h; + if (compensate_par > 0) { + if (compensate_par > 1.0) { + xscale /= compensate_par; + } else { + yscale *= compensate_par; + } + } + int cx = vidw / 2 - (int)(frame_w * xscale) / 2; + int cy = vidh / 2 - (int)(frame_h * yscale) / 2; + for (int i = 0; i < imgs->num_parts; i++) { + struct sub_bitmap *bi = &imgs->parts[i]; + bi->x = bi->x * xscale + cx + res.ml; + bi->y = bi->y * yscale + cy + res.mt; + bi->dw = bi->w * xscale; + bi->dh = bi->h * yscale; + } + imgs->scaled = xscale != 1 || yscale != 1; +} diff --git a/sub/osd.h b/sub/osd.h index cdd681b339..fc2b76df00 100644 --- a/sub/osd.h +++ b/sub/osd.h @@ -231,6 +231,9 @@ void osd_draw_on_image_p(struct osd_state *osd, struct mp_osd_res res, void osd_object_get_scale_factor(struct osd_state *osd, struct osd_object *obj, double *sw, double *sh); +void osd_rescale_bitmaps(struct sub_bitmaps *imgs, int frame_w, int frame_h, + struct mp_osd_res res, double compensate_par); + // defined in osd_libass.c and osd_dummy.c void osd_object_get_bitmaps(struct osd_state *osd, struct osd_object *obj, diff --git a/sub/sd_lavc.c b/sub/sd_lavc.c index 9741b0de70..724a4fe77c 100644 --- a/sub/sd_lavc.c +++ b/sub/sd_lavc.c @@ -212,45 +212,29 @@ static void get_bitmaps(struct sd *sd, struct mp_osd_res d, double pts, if (priv->endpts != MP_NOPTS_VALUE && (pts >= priv->endpts || pts < priv->endpts - 300)) clear(priv); - if (priv->bitmaps_changed && priv->count > 0) - priv->outbitmaps = talloc_memdup(priv, priv->inbitmaps, - talloc_get_size(priv->inbitmaps)); + size_t size = talloc_get_size(priv->inbitmaps); + if (!priv->outbitmaps) + priv->outbitmaps = talloc_size(priv, size); + memcpy(priv->outbitmaps, priv->inbitmaps, size); int inw = priv->avctx->width; int inh = priv->avctx->height; guess_resolution(priv->avctx->codec_id, &inw, &inh); - int vidw = d.w - d.ml - d.mr; - int vidh = d.h - d.mt - d.mb; - double xscale = (double)vidw / inw; - double yscale = (double)vidh / inh; - if (priv->avctx->codec_id == AV_CODEC_ID_DVD_SUBTITLE && - opts->stretch_dvd_subs) { - // For DVD subs, try to keep the subtitle PAR at display PAR. - double video_par = - (priv->video_params.d_w / (double)priv->video_params.d_h) - / (priv->video_params.w / (double)priv->video_params.h); - if (video_par > 1.0) { - xscale /= video_par; - } else { - yscale *= video_par; - } - } - int cx = vidw / 2 - (int)(inw * xscale) / 2; - int cy = vidh / 2 - (int)(inh * yscale) / 2; - for (int i = 0; i < priv->count; i++) { - struct sub_bitmap *bi = &priv->inbitmaps[i]; - struct sub_bitmap *bo = &priv->outbitmaps[i]; - bo->x = bi->x * xscale + cx + d.ml; - bo->y = bi->y * yscale + cy + d.mt; - bo->dw = bi->w * xscale; - bo->dh = bi->h * yscale; - } res->parts = priv->outbitmaps; res->num_parts = priv->count; if (priv->bitmaps_changed) res->bitmap_id = ++res->bitmap_pos_id; priv->bitmaps_changed = false; res->format = SUBBITMAP_INDEXED; - res->scaled = xscale != 1 || yscale != 1; + + double video_par = -1; + if (priv->avctx->codec_id == AV_CODEC_ID_DVD_SUBTITLE && + opts->stretch_dvd_subs) { + // For DVD subs, try to keep the subtitle PAR at display PAR. + video_par = + (priv->video_params.d_w / (double)priv->video_params.d_h) + / (priv->video_params.w / (double)priv->video_params.h); + } + osd_rescale_bitmaps(res, inw, inh, d, video_par); } static void reset(struct sd *sd)