diff options
-rw-r--r-- | sub/draw_bmp.c | 124 | ||||
-rw-r--r-- | sub/draw_bmp.h | 8 | ||||
-rw-r--r-- | sub/sub.c | 12 | ||||
-rw-r--r-- | sub/sub.h | 5 | ||||
-rw-r--r-- | video/out/vo_xv.c | 60 |
5 files changed, 173 insertions, 36 deletions
diff --git a/sub/draw_bmp.c b/sub/draw_bmp.c index e578bd0fcf..96d87eec0c 100644 --- a/sub/draw_bmp.c +++ b/sub/draw_bmp.c @@ -374,6 +374,7 @@ static void align_bbox(int xstep, int ystep, struct mp_rect *rc) rc->y1 = FFALIGN(rc->y1, ystep); } +// Post condition, if true returned: rc is inside img static bool align_bbox_for_swscale(struct mp_image *img, struct mp_rect *rc) { struct mp_rect img_rect = {0, 0, img->w, img->h}; @@ -527,4 +528,127 @@ 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 = alloc_mpi(img->w, img->h, img->imgfmt); + 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 = MP_IMAGE_BITS_PER_PIXEL_ON_PLANE(dst, 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 489e91f666..2eae68b58c 100644 --- a/sub/draw_bmp.h +++ b/sub/draw_bmp.h @@ -12,6 +12,14 @@ 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 @@ -262,6 +262,7 @@ 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; bool changed; }; @@ -269,6 +270,8 @@ 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); mp_draw_sub_bitmaps(&osd->draw_cache, closure->dest, imgs); talloc_steal(osd, osd->draw_cache); closure->changed = true; @@ -284,6 +287,15 @@ bool osd_draw_on_image(struct osd_state *osd, struct mp_osd_res res, return closure.changed; } +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}; + osd_draw(osd, res, video_pts, draw_flags, mp_draw_sub_formats, + &draw_on_image, &closure); +} + void vo_osd_changed(int new_value) { struct osd_state *osd = global_osd; @@ -223,6 +223,11 @@ struct mp_image; bool osd_draw_on_image(struct osd_state *osd, struct mp_osd_res res, double video_pts, int draw_flags, 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_xv.c b/video/out/vo_xv.c index d171559f53..3e749a5f2b 100644 --- a/video/out/vo_xv.c +++ b/video/out/vo_xv.c @@ -47,9 +47,11 @@ #include "vo.h" #include "video/vfcap.h" #include "video/mp_image.h" +#include "video/filter/vf.h" #include "x11_common.h" #include "video/memcpy_pic.h" #include "sub/sub.h" +#include "sub/draw_bmp.h" #include "aspect.h" #include "video/csputils.h" #include "core/subopt-helper.h" @@ -69,10 +71,9 @@ struct xvctx { int current_ip_buf; int num_buffers; int total_buffers; - bool have_image_copy; - bool unchanged_image; int visible_buf; - XvImage *xvimage[2 + 1]; + XvImage *xvimage[2]; + struct mp_draw_sub_backup *osd_backup; uint32_t image_width; uint32_t image_height; uint32_t image_format; @@ -83,7 +84,7 @@ struct xvctx { uint32_t max_width, max_height; // zero means: not set int mode_switched; #ifdef HAVE_SHM - XShmSegmentInfo Shminfo[2 + 1]; + XShmSegmentInfo Shminfo[2]; int Shmem_Flag; #endif }; @@ -150,7 +151,6 @@ static int config(struct vo *vo, uint32_t width, uint32_t height, } ctx->visible_buf = -1; - ctx->have_image_copy = false; /* check image formats */ ctx->xv_format = 0; @@ -210,7 +210,7 @@ static int config(struct vo *vo, uint32_t width, uint32_t height, deallocate_xvimage(vo, i); ctx->num_buffers = 2; - ctx->total_buffers = ctx->num_buffers + 1; + ctx->total_buffers = ctx->num_buffers; for (i = 0; i < ctx->total_buffers; i++) allocate_xvimage(vo, i); @@ -334,14 +334,6 @@ static struct mp_image get_xv_buffer(struct vo *vo, int buf_index) return img; } -static void copy_backup_image(struct vo *vo, int dest, int src) -{ - struct mp_image img_dest = get_xv_buffer(vo, dest); - struct mp_image img_src = get_xv_buffer(vo, src); - - copy_mpi(&img_dest, &img_src); -} - static void check_events(struct vo *vo) { int e = vo_x11_check_events(vo); @@ -371,22 +363,17 @@ static void draw_osd(struct vo *vo, struct osd_state *osd) .video_par = vo->aspdat.par, }; - if (osd_draw_on_image(osd, res, osd->vo_pts, 0, &img)) - ctx->unchanged_image = false; + osd_draw_on_image_bk(osd, res, osd->vo_pts, 0, ctx->osd_backup, &img); } static int redraw_frame(struct vo *vo) { struct xvctx *ctx = vo->priv; - if (ctx->have_image_copy) - copy_backup_image(vo, ctx->visible_buf, ctx->num_buffers); - else if (ctx->unchanged_image) { - copy_backup_image(vo, ctx->num_buffers, ctx->visible_buf); - ctx->have_image_copy = true; - } else - return false; + struct mp_image img = get_xv_buffer(vo, ctx->visible_buf); + mp_draw_sub_backup_restore(ctx->osd_backup, &img); ctx->current_buf = ctx->visible_buf; + return true; } @@ -433,6 +420,8 @@ static int draw_slice(struct vo *vo, uint8_t *image[], int stride[], int w, else memcpy_pic(dst, image[2], w, h, current_image->pitches[1], stride[2]); + mp_draw_sub_backup_reset(ctx->osd_backup); + return 0; } @@ -440,21 +429,22 @@ 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 = alloc_mpi(img.w, img.h, img.imgfmt); + copy_mpi(res, &img); + vf_clone_mpi_attributes(res, &img); // try to get an image without OSD - int id = ctx->have_image_copy ? ctx->num_buffers : ctx->visible_buf; - struct mp_image img = get_xv_buffer(vo, id); - img.display_w = vo->aspdat.prew; - img.display_h = vo->aspdat.preh; + mp_draw_sub_backup_restore(ctx->osd_backup, res); + res->display_w = vo->aspdat.prew; + res->display_h = vo->aspdat.preh; - return talloc_memdup(NULL, &img, sizeof(img)); + return res; } static uint32_t draw_image(struct vo *vo, mp_image_t *mpi) { struct xvctx *ctx = vo->priv; - ctx->have_image_copy = false; - if (mpi->flags & MP_IMGFLAG_DRAW_CALLBACK) ; // done else if (mpi->flags & MP_IMGFLAG_PLANAR) @@ -468,11 +458,8 @@ static uint32_t draw_image(struct vo *vo, mp_image_t *mpi) else return false; - if (ctx->is_paused) { - copy_backup_image(vo, ctx->num_buffers, ctx->current_buf); - ctx->have_image_copy = true; - } - ctx->unchanged_image = true; + mp_draw_sub_backup_reset(ctx->osd_backup); + return true; } @@ -635,6 +622,8 @@ 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: @@ -695,7 +684,6 @@ static int control(struct vo *vo, uint32_t request, void *data) case VOCTRL_SCREENSHOT: { struct voctrl_screenshot_args *args = data; args->out_image = get_screenshot(vo); - args->has_osd = !ctx->have_image_copy; return true; } } |