summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUoti Urpala <uau@mplayer2.org>2011-12-20 03:47:16 +0200
committerUoti Urpala <uau@mplayer2.org>2011-12-20 03:47:16 +0200
commit803dc1fb8ac29666c492bd45f6b2568d19167ef4 (patch)
treee0d02adbd8bf04e0ad04efff7e97451ca6380b1f
parent827faa38436f55fbb15b7dce4abcc5c6608a428b (diff)
downloadmpv-803dc1fb8ac29666c492bd45f6b2568d19167ef4.tar.bz2
mpv-803dc1fb8ac29666c492bd45f6b2568d19167ef4.tar.xz
vo_vdpau: fix preemption recovery after recent commits
Recent commits for screenshot support and video redraw changes didn't handle vdpau driver preemption state correctly, which could make the player crash if preemption occurred. Fix this and improve preemption handling a bit otherwise.
-rw-r--r--libvo/vo_vdpau.c52
1 files changed, 27 insertions, 25 deletions
diff --git a/libvo/vo_vdpau.c b/libvo/vo_vdpau.c
index f95937c122..f8b70a4255 100644
--- a/libvo/vo_vdpau.c
+++ b/libvo/vo_vdpau.c
@@ -478,8 +478,12 @@ static int win_x11_init_vdpau_procs(struct vo *vo)
vdp_st = vdp_device_create_x11(x11->display, x11->screen, &vc->vdp_device,
&vc->vdp_get_proc_address);
if (vdp_st != VDP_STATUS_OK) {
- mp_msg(MSGT_VO, MSGL_ERR, "[vdpau] Error when calling "
- "vdp_device_create_x11: %i\n", vdp_st);
+ if (vc->is_preempted)
+ mp_msg(MSGT_VO, MSGL_DBG2, "[vdpau] Error calling "
+ "vdp_device_create_x11 while preempted: %d\n", vdp_st);
+ else
+ mp_msg(MSGT_VO, MSGL_ERR, "[vdpau] Error when calling "
+ "vdp_device_create_x11: %d\n", vdp_st);
return -1;
}
@@ -1026,9 +1030,6 @@ static void draw_eosd(struct vo *vo)
VdpOutputSurface output_surface = vc->output_surfaces[vc->surface_num];
int i;
- if (handle_preemption(vo) < 0)
- return;
-
VdpOutputSurfaceRenderBlendState blend_state = {
.struct_version = VDP_OUTPUT_SURFACE_RENDER_BLEND_STATE_VERSION,
.blend_factor_source_color =
@@ -1440,28 +1441,23 @@ static void draw_image(struct vo *vo, mp_image_t *mpi, double pts)
struct mp_image *reserved_mpi = NULL;
struct vdpau_render_state *rndr;
- if (vc->is_preempted) {
- vo->frame_loaded = true;
- return;
- }
-
if (IMGFMT_IS_VDPAU(vc->image_format)) {
rndr = mpi->priv;
reserved_mpi = mpi;
} else if (!(mpi->flags & MP_IMGFLAG_DRAW_CALLBACK)) {
- VdpStatus vdp_st;
- void *destdata[3] = {mpi->planes[0], mpi->planes[2], mpi->planes[1]};
rndr = get_surface(vo, vc->deint_counter);
vc->deint_counter = WRAP_ADD(vc->deint_counter, 1, NUM_BUFFERED_VIDEO);
- if (vc->image_format == IMGFMT_NV12)
- destdata[1] = destdata[2];
- vdp_st =
- vdp->video_surface_put_bits_y_cb_cr(rndr->surface,
- vc->vdp_pixel_format,
- (const void *const*)destdata,
- mpi->stride); // pitch
- CHECK_ST_WARNING("Error when calling "
- "vdp_video_surface_put_bits_y_cb_cr");
+ if (handle_preemption(vo) >= 0) {
+ VdpStatus vdp_st;
+ const void *destdata[3] = {mpi->planes[0], mpi->planes[2],
+ mpi->planes[1]};
+ if (vc->image_format == IMGFMT_NV12)
+ destdata[1] = destdata[2];
+ vdp_st = vdp->video_surface_put_bits_y_cb_cr(rndr->surface,
+ vc->vdp_pixel_format, destdata, mpi->stride);
+ CHECK_ST_WARNING("Error when calling "
+ "vdp_video_surface_put_bits_y_cb_cr");
+ }
} else
// We don't support slice callbacks so this shouldn't occur -
// I think the flags test above in pointless, but I'm adding
@@ -1830,8 +1826,10 @@ static int control(struct vo *vo, uint32_t request, void *data)
case VOCTRL_DRAW_EOSD:
if (!data)
return VO_FALSE;
- generate_eosd(vo, data);
- draw_eosd(vo);
+ if (status_ok(vo)) {
+ generate_eosd(vo, data);
+ draw_eosd(vo);
+ }
return VO_TRUE;
case VOCTRL_GET_EOSD_RES: {
struct mp_eosd_res *r = data;
@@ -1843,18 +1841,22 @@ static int control(struct vo *vo, uint32_t request, void *data)
}
case VOCTRL_NEWFRAME:
vc->deint_queue_pos = next_deint_queue_pos(vo, true);
- video_to_output_surface(vo);
+ if (status_ok(vo))
+ video_to_output_surface(vo);
return true;
case VOCTRL_SKIPFRAME:
vc->deint_queue_pos = next_deint_queue_pos(vo, true);
return true;
case VOCTRL_REDRAW_FRAME:
- video_to_output_surface(vo);
+ if (status_ok(vo))
+ video_to_output_surface(vo);
return true;
case VOCTRL_RESET:
forget_frames(vo);
return true;
case VOCTRL_SCREENSHOT: {
+ if (!status_ok(vo))
+ return false;
struct voctrl_screenshot_args *args = data;
if (args->full_window)
args->out_image = get_window_screenshot(vo);