Mercurial > mplayer.hg
changeset 29735:8adf928e517a
Try to recover from VDPAU display pre-emptions.
Original patch by Uoti.
author | cehoyos |
---|---|
date | Sat, 17 Oct 2009 15:15:07 +0000 |
parents | 54145563612e |
children | 252ec0ff7e30 |
files | libvo/vo_vdpau.c |
diffstat | 1 files changed, 76 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/libvo/vo_vdpau.c Fri Oct 16 08:42:00 2009 +0000 +++ b/libvo/vo_vdpau.c Sat Oct 17 15:15:07 2009 +0000 @@ -142,6 +142,7 @@ static VdpDecoderRender *vdp_decoder_render; static VdpGenerateCSCMatrix *vdp_generate_csc_matrix; +static VdpPreemptionCallbackRegister *vdp_preemption_callback_register; static void *vdpau_lib_handle; /* output_surfaces[NUM_OUTPUT_SURFACES] is misused for OSD. */ @@ -178,6 +179,8 @@ static VdpChromaType vdp_chroma_type; static VdpYCbCrFormat vdp_pixel_format; +static volatile int is_preempted; + /* draw_osd */ static unsigned char *index_data; static int index_data_size; @@ -311,6 +314,12 @@ flip_page(); } +static void preemption_callback(VdpDevice device, void *context) +{ + mp_msg(MSGT_VO, MSGL_ERR, "[vdpau] Display preemption detected\n"); + is_preempted = 1; +} + /* Initialize vdp_get_proc_address, called from preinit() */ static int win_x11_init_vdpau_procs(void) { @@ -366,6 +375,8 @@ {VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_BITMAP_SURFACE, &vdp_output_surface_render_bitmap_surface}, {VDP_FUNC_ID_GENERATE_CSC_MATRIX, &vdp_generate_csc_matrix}, + {VDP_FUNC_ID_PREEMPTION_CALLBACK_REGISTER, + &vdp_preemption_callback_register}, {0, NULL} }; @@ -385,6 +396,10 @@ return -1; } } + vdp_st = vdp_preemption_callback_register(vdp_device, + preemption_callback, NULL); + CHECK_ST_ERROR("Error when calling vdp_preemption_callback_register") + return 0; } @@ -559,6 +574,51 @@ return 1; } +static void mark_vdpau_objects_uninitialized(void) +{ + int i; + + decoder = VDP_INVALID_HANDLE; + for (i = 0; i < MAX_VIDEO_SURFACES; i++) + surface_render[i].surface = VDP_INVALID_HANDLE; + for (i = 0; i < 3; i++) { + deint_surfaces[i] = VDP_INVALID_HANDLE; + if (i < 2 && deint_mpi[i]) + deint_mpi[i]->usage_count--; + deint_mpi[i] = NULL; + } + video_mixer = VDP_INVALID_HANDLE; + vdp_flip_queue = VDP_INVALID_HANDLE; + vdp_flip_target = VDP_INVALID_HANDLE; + for (i = 0; i <= NUM_OUTPUT_SURFACES; i++) + output_surfaces[i] = VDP_INVALID_HANDLE; + vdp_device = VDP_INVALID_HANDLE; + for (i = 0; i < eosd_surface_count; i++) + eosd_surfaces[i].surface = VDP_INVALID_HANDLE; + output_surface_width = output_surface_height = -1; + eosd_render_count = 0; + visible_buf = 0; +} + +static int handle_preemption(void) +{ + if (!is_preempted) + return 0; + is_preempted = 0; + mp_msg(MSGT_VO, MSGL_INFO, "[vdpau] Attempting to recover from preemption.\n"); + mark_vdpau_objects_uninitialized(); + if (win_x11_init_vdpau_procs() < 0 || + win_x11_init_vdpau_flip_queue() < 0 || + create_vdp_mixer(vdp_chroma_type) < 0) { + mp_msg(MSGT_VO, MSGL_ERR, "[vdpau] Recovering from preemption failed\n"); + is_preempted = 1; + return -1; + } + resize(); + mp_msg(MSGT_VO, MSGL_INFO, "[vdpau] Recovered from display preemption.\n"); + return 1; +} + /* * connect to X server, create and map window, initialize all * VDPAU objects, create different surfaces etc. @@ -665,6 +725,9 @@ { int e = vo_x11_check_events(mDisplay); + if (handle_preemption() < 0) + return; + if (e & VO_EVENT_RESIZE) resize(); @@ -864,6 +927,9 @@ { mp_msg(MSGT_VO, MSGL_DBG2, "DRAW_OSD\n"); + if (handle_preemption() < 0) + return; + vo_draw_text_ext(vo_dwidth, vo_dheight, border_x, border_y, border_x, border_y, vid_width, vid_height, draw_osd_I8A8); } @@ -874,6 +940,9 @@ mp_msg(MSGT_VO, MSGL_DBG2, "\nFLIP_PAGE VID:%u -> OUT:%u\n", surface_render[vid_surface_num].surface, output_surfaces[surface_num]); + if (handle_preemption() < 0) + return; + vdp_st = vdp_presentation_queue_display(vdp_flip_queue, output_surfaces[surface_num], vo_dwidth, vo_dheight, 0); @@ -889,6 +958,10 @@ VdpStatus vdp_st; struct vdpau_render_state *rndr = (struct vdpau_render_state *)image[0]; int max_refs = image_format == IMGFMT_VDPAU_H264 ? rndr->info.h264.num_ref_frames : 2; + + if (handle_preemption() < 0) + return VO_TRUE; + if (!IMGFMT_IS_VDPAU(image_format)) return VO_FALSE; if ((decoder == VDP_INVALID_HANDLE || decoder_max_refs < max_refs) @@ -1203,6 +1276,9 @@ static int control(uint32_t request, void *data, ...) { + if (handle_preemption() < 0) + return VO_FALSE; + switch (request) { case VOCTRL_GET_DEINTERLACE: *(int*)data = deint;