mirror of
https://github.com/mpv-player/mpv
synced 2025-03-29 23:07:56 +00:00
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.
This commit is contained in:
parent
233cc15be9
commit
1c65428d6f
@ -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;
|
||||
|
||||
|
21
sub/sub.c
21
sub/sub.c
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user