summaryrefslogtreecommitdiffstats
path: root/video/out
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2015-01-24 22:56:02 +0100
committerwm4 <wm4@nowhere>2015-01-24 23:16:27 +0100
commit28582322207bb962553505f0c25268f4b786287d (patch)
tree8c9611a9161f48338701fc506646aaedd8c1a491 /video/out
parent047788e3b1354562f99ce8dacdba1972ad990d03 (diff)
downloadmpv-28582322207bb962553505f0c25268f4b786287d.tar.bz2
mpv-28582322207bb962553505f0c25268f4b786287d.tar.xz
vo: simplify VOs by adding generic screenshot support
At the time screenshot support was added, images weren't refcounted yet, so screenshots required specialized implementations in the VOs. But now we can handle these things much simpler. Also see commit 5bb24980. If there are VOs in the future which can't do this (e.g. they need to write to the image passed to vo_driver->draw_image), this still could be disabled on a per-VO basis etc., so we lose no potential performance advantages.
Diffstat (limited to 'video/out')
-rw-r--r--video/out/gl_video.c6
-rw-r--r--video/out/gl_video.h1
-rw-r--r--video/out/vo.c43
-rw-r--r--video/out/vo.h5
-rw-r--r--video/out/vo_direct3d.c27
-rw-r--r--video/out/vo_opengl.c7
-rw-r--r--video/out/vo_opengl_cb.c9
-rw-r--r--video/out/vo_sdl.c14
-rw-r--r--video/out/vo_vaapi.c11
-rw-r--r--video/out/vo_vdpau.c10
-rw-r--r--video/out/vo_wayland.c11
-rw-r--r--video/out/vo_x11.c13
-rw-r--r--video/out/vo_xv.c12
13 files changed, 35 insertions, 134 deletions
diff --git a/video/out/gl_video.c b/video/out/gl_video.c
index 2eeb86f353..bc1e04b0e6 100644
--- a/video/out/gl_video.c
+++ b/video/out/gl_video.c
@@ -2188,12 +2188,6 @@ void gl_video_upload_image(struct gl_video *p, struct mp_image *mpi)
gl->BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
}
-struct mp_image *gl_video_download_image(struct gl_video *p)
-{
- struct video_image *vimg = &p->image;
- return vimg->mpi ? mp_image_new_ref(vimg->mpi) : NULL;
-}
-
static void draw_osd_cb(void *ctx, struct sub_bitmaps *imgs)
{
struct gl_video *p = ctx;
diff --git a/video/out/gl_video.h b/video/out/gl_video.h
index f62a292785..195ab40902 100644
--- a/video/out/gl_video.h
+++ b/video/out/gl_video.h
@@ -72,7 +72,6 @@ void gl_video_set_output_depth(struct gl_video *p, int r, int g, int b);
void gl_video_set_lut3d(struct gl_video *p, struct lut3d *lut3d);
void gl_video_upload_image(struct gl_video *p, struct mp_image *img);
void gl_video_render_frame(struct gl_video *p, int fbo, struct frame_timing *t);
-struct mp_image *gl_video_download_image(struct gl_video *p);
void gl_video_resize(struct gl_video *p, struct mp_rect *window,
struct mp_rect *src, struct mp_rect *dst,
struct mp_osd_res *osd, bool vflip);
diff --git a/video/out/vo.c b/video/out/vo.c
index 36bd2a9c2e..11690afb67 100644
--- a/video/out/vo.c
+++ b/video/out/vo.c
@@ -135,7 +135,8 @@ struct vo_internal {
int64_t drop_count;
bool dropped_frame; // the previous frame was dropped
- struct mp_image *dropped_image; // used to possibly redraw the dropped frame
+
+ struct mp_image *current_frame; // last frame queued to the VO
int64_t wakeup_pts; // time at which to pull frame from decoder
@@ -333,6 +334,8 @@ static void run_reconfig(void *p)
int flags = *(int *)pp[2];
int *ret = pp[3];
+ struct vo_internal *in = vo->in;
+
vo->dwidth = params->d_w;
vo->dheight = params->d_h;
@@ -347,7 +350,11 @@ static void run_reconfig(void *p)
talloc_free(vo->params);
vo->params = NULL;
}
- forget_frames(vo); // implicitly synchronized
+
+ pthread_mutex_lock(&in->lock);
+ mp_image_unrefp(&in->current_frame);
+ forget_frames(vo);
+ pthread_mutex_unlock(&in->lock);
update_display_fps(vo);
}
@@ -388,7 +395,7 @@ static void forget_frames(struct vo *vo)
in->hasframe_rendered = false;
in->drop_count = 0;
mp_image_unrefp(&in->frame_queued);
- mp_image_unrefp(&in->dropped_image);
+ // don't unref current_frame; we always want to be able to redraw it
}
#ifndef __MINGW32__
@@ -555,7 +562,8 @@ static bool render_frame(struct vo *vo)
if (in->vsync_timed && !in->hasframe)
goto nothing_done;
- mp_image_unrefp(&in->dropped_image);
+ if (img)
+ mp_image_setrefp(&in->current_frame, img);
in->rendering = true;
in->frame_queued = NULL;
@@ -598,7 +606,7 @@ static bool render_frame(struct vo *vo)
}
if (in->dropped_frame) {
- in->dropped_image = img;
+ talloc_free(img);
} else {
in->hasframe_rendered = true;
pthread_mutex_unlock(&in->lock);
@@ -679,20 +687,21 @@ static void do_redraw(struct vo *vo)
pthread_mutex_lock(&in->lock);
in->request_redraw = false;
in->want_redraw = false;
- bool skip = !in->paused && in->dropped_frame;
- struct mp_image *img = in->dropped_image;
- if (!skip) {
- in->dropped_image = NULL;
+ bool force_full_redraw = in->dropped_frame;
+ struct mp_image *img = NULL;
+ if (vo->config_ok)
+ img = mp_image_new_ref(in->current_frame);
+ if (img)
in->dropped_frame = false;
- }
pthread_mutex_unlock(&in->lock);
- if (!vo->config_ok || skip)
+ if (!img)
return;
- if (img) {
+ if (force_full_redraw) {
vo->driver->draw_image(vo, img);
} else {
+ talloc_free(img);
if (vo->driver->control(vo, VOCTRL_REDRAW_FRAME, NULL) < 1)
return;
}
@@ -749,6 +758,7 @@ static void *vo_thread(void *ptr)
wait_vo(vo, wait_until);
}
forget_frames(vo); // implicitly synchronized
+ mp_image_unrefp(&in->current_frame);
vo->driver->uninit(vo);
return NULL;
}
@@ -920,6 +930,15 @@ int vo_query_and_reset_events(struct vo *vo, int events)
return r;
}
+struct mp_image *vo_get_current_frame(struct vo *vo)
+{
+ struct vo_internal *in = vo->in;
+ pthread_mutex_lock(&in->lock);
+ struct mp_image *r = mp_image_new_ref(vo->in->current_frame);
+ pthread_mutex_unlock(&in->lock);
+ return r;
+}
+
/**
* \brief lookup an integer in a table, table must have 0 as the last key
* \param key key to search for
diff --git a/video/out/vo.h b/video/out/vo.h
index 9ae489e2cd..e5eccd3f86 100644
--- a/video/out/vo.h
+++ b/video/out/vo.h
@@ -97,9 +97,7 @@ enum mp_voctrl {
// imgfmt/w/h/d_w/d_h can be omitted for convenience.
VOCTRL_GET_COLORSPACE, // struct mp_image_params*
- // Retrieve original image.
- VOCTRL_SCREENSHOT, // struct mp_image**
- // Retrieve window contents.
+ // Retrieve window contents. (Normal screenshots use vo_get_current_frame().)
VOCTRL_SCREENSHOT_WIN, // struct mp_image**
VOCTRL_SET_COMMAND_LINE, // char**
@@ -319,6 +317,7 @@ void vo_increment_drop_count(struct vo *vo, int64_t n);
void vo_query_formats(struct vo *vo, uint8_t *list);
void vo_event(struct vo *vo, int event);
int vo_query_and_reset_events(struct vo *vo, int events);
+struct mp_image *vo_get_current_frame(struct vo *vo);
void vo_set_flip_queue_params(struct vo *vo, int64_t offset_us, bool vsync_timed);
int64_t vo_get_vsync_interval(struct vo *vo);
diff --git a/video/out/vo_direct3d.c b/video/out/vo_direct3d.c
index 5b4fb7856a..88eb619b8a 100644
--- a/video/out/vo_direct3d.c
+++ b/video/out/vo_direct3d.c
@@ -225,7 +225,6 @@ static void d3d_clear_video_textures(d3d_priv *priv);
static bool resize_d3d(d3d_priv *priv);
static void uninit(struct vo *vo);
static void flip_page(struct vo *vo);
-static mp_image_t *get_screenshot(d3d_priv *priv);
static mp_image_t *get_window_screenshot(d3d_priv *priv);
static void draw_osd(struct vo *vo);
static bool change_d3d_backbuffer(d3d_priv *priv);
@@ -1260,9 +1259,6 @@ static int control(struct vo *vo, uint32_t request, void *data)
return VO_TRUE;
case VOCTRL_GET_PANSCAN:
return VO_TRUE;
- case VOCTRL_SCREENSHOT:
- *(struct mp_image **)data = get_screenshot(priv);
- return VO_TRUE;
case VOCTRL_SCREENSHOT_WIN:
*(struct mp_image **)data = get_window_screenshot(priv);
return VO_TRUE;
@@ -1445,29 +1441,6 @@ done:
talloc_free(mpi);
}
-static mp_image_t *get_screenshot(d3d_priv *priv)
-{
- if (!priv->d3d_device)
- return NULL;
-
- if (!priv->have_image)
- return NULL;
-
- if (!priv->vo->params)
- return NULL;
-
- struct mp_image buffer;
- if (!get_video_buffer(priv, &buffer))
- return NULL;
-
- struct mp_image *image = mp_image_new_copy(&buffer);
- if (image)
- mp_image_set_attributes(image, priv->vo->params);
-
- d3d_unlock_video_objects(priv);
- return image;
-}
-
static mp_image_t *get_window_screenshot(d3d_priv *priv)
{
D3DDISPLAYMODE mode;
diff --git a/video/out/vo_opengl.c b/video/out/vo_opengl.c
index 618ed90aff..0cd8d49343 100644
--- a/video/out/vo_opengl.c
+++ b/video/out/vo_opengl.c
@@ -349,15 +349,10 @@ static int control(struct vo *vo, uint32_t request, void *data)
mpgl_unlock(p->glctx);
return VO_TRUE;
case VOCTRL_SCREENSHOT_WIN:
- case VOCTRL_SCREENSHOT:
- {
mpgl_lock(p->glctx);
- *(struct mp_image **)data = request == VOCTRL_SCREENSHOT
- ? gl_video_download_image(p->renderer)
- : glGetWindowScreenshot(p->gl);
+ *(struct mp_image **)data = glGetWindowScreenshot(p->gl);
mpgl_unlock(p->glctx);
return true;
- }
case VOCTRL_GET_HWDEC_INFO: {
struct mp_hwdec_info **arg = data;
*arg = &p->hwdec_info;
diff --git a/video/out/vo_opengl_cb.c b/video/out/vo_opengl_cb.c
index a974305b85..cee0bc1d46 100644
--- a/video/out/vo_opengl_cb.c
+++ b/video/out/vo_opengl_cb.c
@@ -64,7 +64,6 @@ struct mpv_opengl_cb_context {
mpv_opengl_cb_update_fn update_cb;
void *update_cb_ctx;
struct mp_image *waiting_frame;
- struct mp_image *displayed_frame;
struct mp_image **frame_queue;
int queued_frames;
struct mp_image_params img_params;
@@ -358,7 +357,6 @@ static void draw_image(struct vo *vo, mp_image_t *mpi)
pthread_mutex_lock(&p->ctx->lock);
mp_image_setrefp(&p->ctx->waiting_frame, mpi);
- mp_image_setrefp(&p->ctx->displayed_frame, mpi);
talloc_free(mpi);
pthread_mutex_unlock(&p->ctx->lock);
}
@@ -488,12 +486,6 @@ static int control(struct vo *vo, uint32_t request, void *data)
update(p);
pthread_mutex_unlock(&p->ctx->lock);
return VO_TRUE;
- case VOCTRL_SCREENSHOT: {
- pthread_mutex_lock(&p->ctx->lock);
- *(struct mp_image **)data = mp_image_new_ref(p->ctx->displayed_frame);
- pthread_mutex_unlock(&p->ctx->lock);
- return VO_TRUE;
- }
case VOCTRL_SET_COMMAND_LINE: {
char *arg = data;
return reparse_cmdline(p, arg);
@@ -514,7 +506,6 @@ static void uninit(struct vo *vo)
pthread_mutex_lock(&p->ctx->lock);
forget_frames(p->ctx);
- mp_image_unrefp(&p->ctx->displayed_frame);
p->ctx->img_params = (struct mp_image_params){0};
p->ctx->reconfigured = true;
p->ctx->active = NULL;
diff --git a/video/out/vo_sdl.c b/video/out/vo_sdl.c
index 9b7605643a..9a06f2e3c4 100644
--- a/video/out/vo_sdl.c
+++ b/video/out/vo_sdl.c
@@ -172,7 +172,6 @@ struct priv {
SDL_Texture *tex;
int tex_swapped;
struct mp_image_params params;
- mp_image_t *ssmpi;
struct mp_rect src_rect;
struct mp_rect dst_rect;
struct mp_osd_res osd_res;
@@ -638,7 +637,6 @@ static void uninit(struct vo *vo)
{
struct priv *vc = vo->priv;
destroy_renderer(vo);
- talloc_free(vc->ssmpi);
SDL_QuitSubSystem(SDL_INIT_VIDEO);
talloc_free(vc);
}
@@ -913,9 +911,6 @@ static void draw_image(struct vo *vo, mp_image_t *mpi)
mp_image_copy(&texmpi, mpi);
SDL_UnlockTexture(vc->tex);
-
- talloc_free(vc->ssmpi);
- vc->ssmpi = mpi;
}
SDL_Rect src, dst;
@@ -941,12 +936,6 @@ static void draw_image(struct vo *vo, mp_image_t *mpi)
draw_osd(vo);
}
-static struct mp_image *get_screenshot(struct vo *vo)
-{
- struct priv *vc = vo->priv;
- return vc->ssmpi ? mp_image_new_ref(vc->ssmpi) : NULL;
-}
-
static struct mp_image *get_window_screenshot(struct vo *vo)
{
struct priv *vc = vo->priv;
@@ -1018,9 +1007,6 @@ static int control(struct vo *vo, uint32_t request, void *data)
struct voctrl_get_equalizer_args *args = data;
return get_eq(vo, args->name, args->valueptr);
}
- case VOCTRL_SCREENSHOT:
- *(struct mp_image **)data = get_screenshot(vo);
- return true;
case VOCTRL_SCREENSHOT_WIN:
*(struct mp_image **)data = get_window_screenshot(vo);
return true;
diff --git a/video/out/vo_vaapi.c b/video/out/vo_vaapi.c
index 1c4b016e6b..de2c975823 100644
--- a/video/out/vo_vaapi.c
+++ b/video/out/vo_vaapi.c
@@ -298,14 +298,6 @@ static void draw_image(struct vo *vo, struct mp_image *mpi)
draw_osd(vo);
}
-static struct mp_image *get_screenshot(struct priv *p)
-{
- struct mp_image *hwimg = p->output_surfaces[p->visible_surface];
- if (!hwimg)
- return NULL;
- return mp_image_new_ref(hwimg);
-}
-
static void free_subpicture(struct priv *p, struct vaapi_osd_image *img)
{
if (img->image.image_id != VA_INVALID_ID)
@@ -541,9 +533,6 @@ static int control(struct vo *vo, uint32_t request, void *data)
p->output_surface = p->visible_surface;
draw_osd(vo);
return true;
- case VOCTRL_SCREENSHOT:
- *(struct mp_image **)data = get_screenshot(p);
- return true;
case VOCTRL_GET_PANSCAN:
return VO_TRUE;
case VOCTRL_SET_PANSCAN:
diff --git a/video/out/vo_vdpau.c b/video/out/vo_vdpau.c
index 1a1287c1d7..528756c05f 100644
--- a/video/out/vo_vdpau.c
+++ b/video/out/vo_vdpau.c
@@ -1049,18 +1049,10 @@ static int control(struct vo *vo, uint32_t request, void *data)
forget_frames(vo, true);
return true;
case VOCTRL_SCREENSHOT_WIN:
- case VOCTRL_SCREENSHOT:
- {
if (!status_ok(vo))
return false;
- if (request == VOCTRL_SCREENSHOT_WIN) {
- *(struct mp_image **)data = get_window_screenshot(vo);
- } else {
- *(struct mp_image **)data =
- vc->current_image ? mp_image_new_ref(vc->current_image) : NULL;
- }
+ *(struct mp_image **)data = get_window_screenshot(vo);
return true;
- }
case VOCTRL_GET_PREF_DEINT:
*(int *)data = vc->deint;
return true;
diff --git a/video/out/vo_wayland.c b/video/out/vo_wayland.c
index ed23f8af3d..9da24ddf3e 100644
--- a/video/out/vo_wayland.c
+++ b/video/out/vo_wayland.c
@@ -268,14 +268,6 @@ static bool redraw_frame(struct priv *p)
return true;
}
-static mp_image_t *get_screenshot(struct priv *p)
-{
- if (!p->original_image)
- return NULL;
-
- return mp_image_new_ref(p->original_image);
-}
-
static bool resize(struct priv *p)
{
struct vo_wayland_state *wl = p->wl;
@@ -689,9 +681,6 @@ static int control(struct vo *vo, uint32_t request, void *data)
}
case VOCTRL_REDRAW_FRAME:
return redraw_frame(p);
- case VOCTRL_SCREENSHOT:
- *(struct mp_image **)data = get_screenshot(p);
- return true;
case VOCTRL_GET_RECENT_FLIP_TIME:
{
*(int64_t*) data = p->recent_flip_time;
diff --git a/video/out/vo_x11.c b/video/out/vo_x11.c
index 32d9b731fd..aa578d4883 100644
--- a/video/out/vo_x11.c
+++ b/video/out/vo_x11.c
@@ -423,16 +423,6 @@ static struct mp_image get_x_buffer(struct priv *p, int buf_index)
return img;
}
-static mp_image_t *get_screenshot(struct vo *vo)
-{
- struct priv *p = vo->priv;
-
- if (!p->original_image)
- return NULL;
-
- return mp_image_new_ref(p->original_image);
-}
-
static void wait_for_completion(struct vo *vo, int max_outstanding)
{
#if HAVE_SHM && HAVE_XEXT
@@ -619,9 +609,6 @@ static int control(struct vo *vo, uint32_t request, void *data)
case VOCTRL_REDRAW_FRAME:
draw_image(vo, p->original_image);
return true;
- case VOCTRL_SCREENSHOT:
- *(struct mp_image **)data = get_screenshot(vo);
- return true;
}
int events = 0;
diff --git a/video/out/vo_xv.c b/video/out/vo_xv.c
index e506fc9359..11c6efc26e 100644
--- a/video/out/vo_xv.c
+++ b/video/out/vo_xv.c
@@ -648,15 +648,6 @@ static void flip_page(struct vo *vo)
XSync(vo->x11->display, False);
}
-static mp_image_t *get_screenshot(struct vo *vo)
-{
- struct xvctx *ctx = vo->priv;
- if (!ctx->original_image)
- return NULL;
-
- return mp_image_new_ref(ctx->original_image);
-}
-
// Note: REDRAW_FRAME can call this with NULL.
static void draw_image(struct vo *vo, mp_image_t *mpi)
{
@@ -839,9 +830,6 @@ static int control(struct vo *vo, uint32_t request, void *data)
case VOCTRL_REDRAW_FRAME:
draw_image(vo, ctx->original_image);
return true;
- case VOCTRL_SCREENSHOT:
- *(struct mp_image **)data = get_screenshot(vo);
- return true;
}
int events = 0;
int r = vo_x11_control(vo, &events, request, data);