From 3d6d549dac2aa06ecd07bb04902f55140661ace3 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 22 Dec 2012 17:50:15 +0100 Subject: vo_xv, vo_x11: simplify OSD redrawing In order to support OSD redrawing for vo_xv and vo_x11, draw_bmp.c included an awkward "backup" mechanism to copy and restore image regions that have been changed by OSD/subtitles. Replace this by a much simpler mechanism: keep a reference to the original image, and use that to restore the Xv/X framebuffers. In the worst case, this may increase cache pressure and memory usage, even if no OSD or subtitles are rendered. In practice, it seems to be always faster. --- sub/draw_bmp.c | 123 ----------------------------------------------------- sub/draw_bmp.h | 8 ---- sub/sub.c | 14 +----- sub/sub.h | 5 --- video/out/vo_x11.c | 41 ++++++++++-------- video/out/vo_xv.c | 27 ++++++------ 6 files changed, 39 insertions(+), 179 deletions(-) diff --git a/sub/draw_bmp.c b/sub/draw_bmp.c index 23e05464cc..64a12a2da5 100644 --- a/sub/draw_bmp.c +++ b/sub/draw_bmp.c @@ -512,127 +512,4 @@ void mp_draw_sub_bitmaps(struct mp_draw_sub_cache **cache, struct mp_image *dst, } } -struct mp_draw_sub_backup -{ - bool valid; - struct mp_image *image; // backed up image parts - struct line_ext *lines[MP_MAX_PLANES]; // backup range for each line -}; - -struct line_ext { - int x0, x1; // x1 is exclusive -}; - -struct mp_draw_sub_backup *mp_draw_sub_backup_new(void) -{ - return talloc_zero(NULL, struct mp_draw_sub_backup); -} - -// Signal that the full image is valid (nothing to backup). -void mp_draw_sub_backup_reset(struct mp_draw_sub_backup *backup) -{ - backup->valid = true; - if (backup->image) { - for (int p = 0; p < MP_MAX_PLANES; p++) { - int h = backup->image->h; - for (int y = 0; y < h; y++) { - struct line_ext *ext = &backup->lines[p][y]; - ext->x0 = ext->x1 = -1; - } - } - } -} - -static void backup_realloc(struct mp_draw_sub_backup *backup, - struct mp_image *img) -{ - if (backup->image && backup->image->imgfmt == img->imgfmt - && backup->image->w == img->w && backup->image->h == img->h) - return; - - talloc_free_children(backup); - backup->image = mp_image_alloc(img->imgfmt, img->w, img->h); - talloc_steal(backup, backup->image); - for (int p = 0; p < MP_MAX_PLANES; p++) { - backup->lines[p] = talloc_array(backup, struct line_ext, - backup->image->h); - } - mp_draw_sub_backup_reset(backup); -} - -static void copy_line(struct mp_image *dst, struct mp_image *src, - int p, int plane_y, int x0, int x1) -{ - int bits = dst->fmt.bpp[p]; - int xs = p ? dst->chroma_x_shift : 0; - memcpy(dst->planes[p] + plane_y * dst->stride[p] + (x0 >> xs) * bits / 8, - src->planes[p] + plane_y * src->stride[p] + (x0 >> xs) * bits / 8, - ((x1 - x0) >> xs) * bits / 8); -} - -static void backup_rect(struct mp_draw_sub_backup *backup, struct mp_image *img, - int plane, struct mp_rect rc) -{ - if (!align_bbox_for_swscale(img, &rc)) - return; - int ys = plane ? img->chroma_y_shift : 0; - int yp = ys ? ((1 << ys) - 1) : 0; - for (int y = (rc.y0 >> ys); y < ((rc.y1 + yp) >> ys); y++) { - struct line_ext *ext = &backup->lines[plane][y]; - if (ext->x0 == -1) { - copy_line(backup->image, img, plane, y, rc.x0, rc.x1); - ext->x0 = rc.x0; - ext->x1 = rc.x1; - } else { - if (rc.x0 < ext->x0) { - copy_line(backup->image, img, plane, y, rc.x0, ext->x0); - ext->x0 = rc.x0; - } - if (ext->x1 < rc.x1) { - copy_line(backup->image, img, plane, y, ext->x1, rc.x1); - ext->x1 = rc.x1; - } - } - } -} - -void mp_draw_sub_backup_add(struct mp_draw_sub_backup *backup, - struct mp_image *img, struct sub_bitmaps *sbs) -{ - backup_realloc(backup, img); - - for (int p = 0; p < img->num_planes; p++) { - for (int i = 0; i < sbs->num_parts; ++i) { - struct sub_bitmap *sb = &sbs->parts[i]; - struct mp_rect rc = {sb->x, sb->y, sb->x + sb->dw, sb->y + sb->dh}; - backup_rect(backup, img, p, rc); - } - } -} - -bool mp_draw_sub_backup_restore(struct mp_draw_sub_backup *backup, - struct mp_image *buffer) -{ - if (!backup->image || backup->image->imgfmt != buffer->imgfmt - || backup->image->w != buffer->w || backup->image->h != buffer->h - || !backup->valid) - { - backup->valid = false; - return false; - } - struct mp_image *img = backup->image; - for (int p = 0; p < img->num_planes; p++) { - int ys = p ? img->chroma_y_shift : 0; - int yp = ys ? ((1 << ys) - 1) : 0; - int p_h = ((img->h + yp) >> ys); - for (int y = 0; y < p_h; y++) { - struct line_ext *ext = &backup->lines[p][y]; - if (ext->x0 < ext->x1) { - copy_line(buffer, img, p, y, ext->x0, ext->x1); - } - } - } - return true; -} - // vim: ts=4 sw=4 et tw=80 diff --git a/sub/draw_bmp.h b/sub/draw_bmp.h index 2eae68b58c..489e91f666 100644 --- a/sub/draw_bmp.h +++ b/sub/draw_bmp.h @@ -12,14 +12,6 @@ void mp_draw_sub_bitmaps(struct mp_draw_sub_cache **cache, struct mp_image *dst, extern const bool mp_draw_sub_formats[SUBBITMAP_COUNT]; -struct mp_draw_sub_backup; -struct mp_draw_sub_backup *mp_draw_sub_backup_new(void); -void mp_draw_sub_backup_add(struct mp_draw_sub_backup *backup, - struct mp_image *img, struct sub_bitmaps *sbs); -void mp_draw_sub_backup_reset(struct mp_draw_sub_backup *backup); -bool mp_draw_sub_backup_restore(struct mp_draw_sub_backup *backup, - struct mp_image *buffer); - #endif /* MPLAYER_DRAW_BMP_H */ // vim: ts=4 sw=4 et tw=80 diff --git a/sub/sub.c b/sub/sub.c index 4baf4f1487..ea9c51a758 100644 --- a/sub/sub.c +++ b/sub/sub.c @@ -275,7 +275,6 @@ void osd_draw(struct osd_state *osd, struct mp_osd_res res, struct draw_on_image_closure { struct osd_state *osd; struct mp_image *dest; - struct mp_draw_sub_backup *bk; struct mp_image_pool *pool; bool changed; }; @@ -284,8 +283,6 @@ static void draw_on_image(void *ctx, struct sub_bitmaps *imgs) { struct draw_on_image_closure *closure = ctx; struct osd_state *osd = closure->osd; - if (closure->bk) - mp_draw_sub_backup_add(closure->bk, closure->dest, imgs); if (closure->pool) { mp_image_pool_make_writeable(closure->pool, closure->dest); } else { @@ -314,16 +311,7 @@ void osd_draw_on_image_p(struct osd_state *osd, struct mp_osd_res res, double video_pts, int draw_flags, struct mp_image_pool *pool, struct mp_image *dest) { - struct draw_on_image_closure closure = {osd, dest, .pool = pool}; - osd_draw(osd, res, video_pts, draw_flags, mp_draw_sub_formats, - &draw_on_image, &closure); -} - -void osd_draw_on_image_bk(struct osd_state *osd, struct mp_osd_res res, - double video_pts, int draw_flags, - struct mp_draw_sub_backup *bk, struct mp_image *dest) -{ - struct draw_on_image_closure closure = {osd, dest, bk}; + struct draw_on_image_closure closure = {osd, dest, pool}; osd_draw(osd, res, video_pts, draw_flags, mp_draw_sub_formats, &draw_on_image, &closure); } diff --git a/sub/sub.h b/sub/sub.h index 38b7b29f34..c7f8a8b022 100644 --- a/sub/sub.h +++ b/sub/sub.h @@ -227,11 +227,6 @@ void osd_draw_on_image_p(struct osd_state *osd, struct mp_osd_res res, double video_pts, int draw_flags, struct mp_image_pool *pool, struct mp_image *dest); -struct mp_draw_sub_backup; -void osd_draw_on_image_bk(struct osd_state *osd, struct mp_osd_res res, - double video_pts, int draw_flags, - struct mp_draw_sub_backup *bk, struct mp_image *dest); - struct mp_rect; bool sub_bitmaps_bb(struct sub_bitmaps *imgs, struct mp_rect *out_bb); diff --git a/video/out/vo_x11.c b/video/out/vo_x11.c index 8b41a7afc3..c45dac5bdd 100644 --- a/video/out/vo_x11.c +++ b/video/out/vo_x11.c @@ -55,7 +55,7 @@ extern int sws_flags; struct priv { struct vo *vo; - struct mp_draw_sub_backup *osd_backup; + struct mp_image *original_image; /* local data */ unsigned char *ImageData; @@ -268,6 +268,8 @@ static int config(struct vo *vo, uint32_t width, uint32_t height, Colormap theCmap; const struct fmt2Xfmtentry_s *fmte = fmt2Xfmt; + mp_image_unrefp(&p->original_image); + #ifdef CONFIG_XF86VM int vm = flags & VOFLAG_MODESWITCHING; #endif @@ -441,30 +443,21 @@ static void draw_osd(struct vo *vo, struct osd_state *osd) .video_par = vo->aspdat.par, }; - osd_draw_on_image_bk(osd, res, osd->vo_pts, 0, p->osd_backup, &img); + osd_draw_on_image(osd, res, osd->vo_pts, 0, &img); } static mp_image_t *get_screenshot(struct vo *vo) { struct priv *p = vo->priv; - struct mp_image img = get_x_buffer(p); - struct mp_image *res = mp_image_new_copy(&img); - mp_draw_sub_backup_restore(p->osd_backup, res); + if (!p->original_image) + return NULL; + struct mp_image *res = mp_image_new_ref(p->original_image); + mp_image_set_display_size(res, vo->aspdat.prew, vo->aspdat.preh); return res; } -static int redraw_frame(struct vo *vo) -{ - struct priv *p = vo->priv; - - struct mp_image img = get_x_buffer(p); - mp_draw_sub_backup_restore(p->osd_backup, &img); - - return true; -} - static void flip_page(struct vo *vo) { struct priv *p = vo->priv; @@ -516,7 +509,19 @@ static void draw_image(struct vo *vo, mp_image_t *mpi) } sws_scale(p->swsContext, (const uint8_t **)mpi->planes, mpi->stride, 0, mpi->h, dst, dstStride); - mp_draw_sub_backup_reset(p->osd_backup); + + mp_image_setrefp(&p->original_image, mpi); +} + +static int redraw_frame(struct vo *vo) +{ + struct priv *p = vo->priv; + + if (!p->original_image) + return false; + + draw_image(vo, p->original_image); + return true; } static int query_format(struct vo *vo, uint32_t format) @@ -551,6 +556,8 @@ static void uninit(struct vo *vo) if (p->myximage) freeMyXImage(p); + talloc_free(p->original_image); + #ifdef CONFIG_XF86VM vo_vm_close(vo); #endif @@ -571,8 +578,6 @@ static int preinit(struct vo *vo, const char *arg) return ENOSYS; } - p->osd_backup = talloc_steal(p, mp_draw_sub_backup_new()); - if (!vo_init(vo)) return -1; // Can't open X11 return 0; diff --git a/video/out/vo_xv.c b/video/out/vo_xv.c index dc7f805e4b..7a454e33c4 100644 --- a/video/out/vo_xv.c +++ b/video/out/vo_xv.c @@ -73,7 +73,7 @@ struct xvctx { int total_buffers; int visible_buf; XvImage *xvimage[2]; - struct mp_draw_sub_backup *osd_backup; + struct mp_image *original_image; uint32_t image_width; uint32_t image_height; uint32_t image_format; @@ -159,6 +159,8 @@ static int config(struct vo *vo, uint32_t width, uint32_t height, struct xvctx *ctx = vo->priv; int i; + mp_image_unrefp(&ctx->original_image); + ctx->image_height = height; ctx->image_width = width; ctx->image_format = format; @@ -383,17 +385,19 @@ static void draw_osd(struct vo *vo, struct osd_state *osd) .video_par = vo->aspdat.par, }; - osd_draw_on_image_bk(osd, res, osd->vo_pts, 0, ctx->osd_backup, &img); + osd_draw_on_image(osd, res, osd->vo_pts, 0, &img); } static int redraw_frame(struct vo *vo) { struct xvctx *ctx = vo->priv; + if (!ctx->original_image) + return false; + struct mp_image img = get_xv_buffer(vo, ctx->visible_buf); - mp_draw_sub_backup_restore(ctx->osd_backup, &img); + mp_image_copy(&img, ctx->original_image); ctx->current_buf = ctx->visible_buf; - return true; } @@ -414,12 +418,11 @@ static mp_image_t *get_screenshot(struct vo *vo) { struct xvctx *ctx = vo->priv; - struct mp_image img = get_xv_buffer(vo, ctx->visible_buf); - struct mp_image *res = mp_image_new_copy(&img); - mp_image_set_display_size(res, vo->aspdat.prew, vo->aspdat.preh); - // try to get an image without OSD - mp_draw_sub_backup_restore(ctx->osd_backup, res); + if (!ctx->original_image) + return NULL; + struct mp_image *res = mp_image_new_ref(ctx->original_image); + mp_image_set_display_size(res, vo->aspdat.prew, vo->aspdat.preh); return res; } @@ -430,7 +433,7 @@ static void draw_image(struct vo *vo, mp_image_t *mpi) struct mp_image xv_buffer = get_xv_buffer(vo, ctx->current_buf); mp_image_copy(&xv_buffer, mpi); - mp_draw_sub_backup_reset(ctx->osd_backup); + mp_image_setrefp(&ctx->original_image, mpi); } static int query_format(struct vo *vo, uint32_t format) @@ -454,6 +457,8 @@ static void uninit(struct vo *vo) struct xvctx *ctx = vo->priv; int i; + talloc_free(ctx->original_image); + ctx->visible_buf = -1; if (ctx->ai) XvFreeAdaptorInfo(ctx->ai); @@ -595,8 +600,6 @@ static int preinit(struct vo *vo, const char *arg) ctx->fo = XvListImageFormats(x11->display, x11->xv_port, (int *) &ctx->formats); - ctx->osd_backup = talloc_steal(ctx, mp_draw_sub_backup_new()); - return 0; error: -- cgit v1.2.3