[MPlayer-dev-eng] [PATCH]VDPAU: Recover from display pre-emption

Carl Eugen Hoyos cehoyos at rainbow.studorg.tuwien.ac.at
Mon Oct 5 09:55:45 CEST 2009


Hi!

I tested Uoti's display preemption patch successfully on a system where 
preemptions are (unfortunately) nothing unusual (even for vo vdpau with 
software decoding) when receiving DVB streams at the same time (KNC One 
DVB-S2 with multiproto and v4l-dvb trunk).
Attached is a version for current svn, it certainly works not as nice for 
preemptions caused by virtual display change, but it does work and I 
consider such (user) issues less important.
At least the change in control() is probably unnecessary, but I cannot 
test for ten days, so please comment.

Carl Eugen

PS: Has anybody ever tried to port gnutv to DVB-S2?
It seems the superior tuning application to me.
-------------- next part --------------
Index: libvo/vo_vdpau.c
===================================================================
--- libvo/vo_vdpau.c	(revision 29748)
+++ libvo/vo_vdpau.c	(working copy)
@@ -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. */
@@ -177,6 +178,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;
@@ -310,6 +313,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)
 {
@@ -365,6 +374,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}
     };
 
@@ -383,6 +394,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;
 }
 
@@ -528,6 +543,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_ERR, "[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.
@@ -634,6 +694,9 @@
 {
     int e = vo_x11_check_events(mDisplay);
 
+    if (handle_preemption() < 0)
+        return;
+
     if (e & VO_EVENT_RESIZE)
         resize();
 
@@ -831,6 +894,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);
 }
@@ -841,6 +907,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);
@@ -856,6 +925,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)
@@ -1165,6 +1238,8 @@
 
 static int control(uint32_t request, void *data, ...)
 {
+    handle_preemption();
+
     switch (request) {
         case VOCTRL_GET_DEINTERLACE:
             *(int*)data = deint;


More information about the MPlayer-dev-eng mailing list