diff options
author | wm4 <wm4@nowhere> | 2012-12-22 17:17:43 +0100 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2013-01-13 20:04:12 +0100 |
commit | 1c65428d6f70f05333ecc8284e3f235c679fff26 (patch) | |
tree | 6939a94a824aba4a8929136dc906cdc1d5b5de6b | |
parent | 233cc15be99a94891bfc62bbb79af38ee192d9ff (diff) | |
download | mpv-1c65428d6f70f05333ecc8284e3f235c679fff26.tar.bz2 mpv-1c65428d6f70f05333ecc8284e3f235c679fff26.tar.xz |
sub: do not copy the target image if there is no OSD/subs
It's not easy to tell whether the OSD/subs are empty, or if something is
drawn. In general you have to use osd_draw() with a custom callback. If
nothing is visible, the callback is never invoked. (The actual reason
why this is so "hard" is the implementation of osd_libass.c, which
doesn't allow separating rendering and drawing of OSD elements, because
all OSD elements share the same ASS_Renderer.)
To simplify avoiding copies, make osd_draw_on_image() instead of the
caller use mp_image_make_writeable(). Introduce osd_draw_on_image_p(),
which works like osd_draw_on_image(), but gets the new image allocation
from an image pool. This is supposed to be an optimization, because it
reduces the frequency of large allocations/deallocations for image data.
The result of this is that the frequency of copies needed in conjunction
with vf_sub, screenshots, and vo_lavc (encoding) should be reduced.
vf_sub now always does true pass-through if no subs are shown.
Drop the pts check from vf_sub. This didn't make much sense.
-rw-r--r-- | core/screenshot.c | 2 | ||||
-rw-r--r-- | sub/sub.c | 21 | ||||
-rw-r--r-- | sub/sub.h | 5 | ||||
-rw-r--r-- | video/filter/vf_sub.c | 8 | ||||
-rw-r--r-- | video/out/vo_lavc.c | 1 |
5 files changed, 29 insertions, 8 deletions
diff --git a/core/screenshot.c b/core/screenshot.c index 0f397f2dd7..ae259fcbc0 100644 --- a/core/screenshot.c +++ b/core/screenshot.c @@ -235,8 +235,6 @@ static char *gen_fname(screenshot_ctx *ctx, const char *file_ext) static void add_subs(struct MPContext *mpctx, struct mp_image *image) { - mp_image_make_writeable(image); - int d_w = image->display_w ? image->display_w : image->w; int d_h = image->display_h ? image->display_h : image->h; @@ -39,6 +39,8 @@ #include "draw_bmp.h" #include "spudec.h" #include "subreader.h" +#include "video/mp_image.h" +#include "video/mp_image_pool.h" char * const sub_osd_names[]={ @@ -274,6 +276,7 @@ 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; }; @@ -283,11 +286,17 @@ static void draw_on_image(void *ctx, struct sub_bitmaps *imgs) 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 { + mp_image_make_writeable(closure->dest); + } mp_draw_sub_bitmaps(&osd->draw_cache, closure->dest, imgs); talloc_steal(osd, osd->draw_cache); closure->changed = true; } +// Calls mp_image_make_writeable() on the dest image if something is drawn. // Returns whether anything was drawn. bool osd_draw_on_image(struct osd_state *osd, struct mp_osd_res res, double video_pts, int draw_flags, struct mp_image *dest) @@ -298,6 +307,18 @@ bool osd_draw_on_image(struct osd_state *osd, struct mp_osd_res res, return closure.changed; } +// Like osd_draw_on_image(), but if dest needs to be copied to make it +// writeable, allocate images from the given pool. (This is a minor +// optimization to reduce "real" image sized memory allocations.) +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) @@ -222,6 +222,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_image_pool; +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, diff --git a/video/filter/vf_sub.c b/video/filter/vf_sub.c index 8cda9f5e79..c9d22995c1 100644 --- a/video/filter/vf_sub.c +++ b/video/filter/vf_sub.c @@ -155,9 +155,7 @@ static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi) struct vf_priv_s *priv = vf->priv; struct osd_state *osd = priv->osd; - if (vf->priv->opt_top_margin || vf->priv->opt_bottom_margin || - !mp_image_is_writeable(mpi)) - { + if (vf->priv->opt_top_margin || vf->priv->opt_bottom_margin) { struct mp_image *dmpi = vf_alloc_out_image(vf); mp_image_copy_attributes(dmpi, mpi); prepare_image(vf, dmpi, mpi); @@ -167,8 +165,8 @@ static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi) mp_image_set_colorspace_details(mpi, &priv->csp); - if (mpi->pts != MP_NOPTS_VALUE) - osd_draw_on_image(osd, priv->dim, mpi->pts, OSD_DRAW_SUB_FILTER, mpi); + osd_draw_on_image_p(osd, priv->dim, mpi->pts, OSD_DRAW_SUB_FILTER, + vf->out_pool, mpi); return mpi; } diff --git a/video/out/vo_lavc.c b/video/out/vo_lavc.c index 35041c7f63..2aced9351a 100644 --- a/video/out/vo_lavc.c +++ b/video/out/vo_lavc.c @@ -487,7 +487,6 @@ static void draw_osd(struct vo *vo, struct osd_state *osd) }; mp_image_set_colorspace_details(vc->lastimg, &vc->colorspace); - mp_image_make_writeable(vc->lastimg); osd_draw_on_image(osd, dim, osd->vo_pts, OSD_DRAW_SUB_ONLY, vc->lastimg); } |