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;