[mythtv] [patch] xvmc flush patch

Daniel Thor Kristjansson danielk at cat.nyu.edu
Tue Aug 24 11:10:37 EDT 2004


This replaces some of the XvMC syncs with XvMC flushes, allowing the
videocard to run more in parallel with avcodec. It doesn't seem to have
any problems with skipping around in SDTV streams. And it seems
slightly less likely to hang waiting for XvMC surfaces when you skip
around in HDTV streams.

-- Daniel
-------------- next part --------------
Index: libs/libmythtv/videoout_xvmc.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/videoout_xvmc.cpp,v
retrieving revision 1.33
diff -u -r1.33 videoout_xvmc.cpp
--- libs/libmythtv/videoout_xvmc.cpp	5 Aug 2004 07:35:02 -0000	1.33
+++ libs/libmythtv/videoout_xvmc.cpp	24 Aug 2004 15:04:48 -0000
@@ -193,7 +193,7 @@
         w_mm =  display_res->Width_mm();
         h_mm =  display_res->Height_mm();
 
-        data->display_aspect = static_cast<float>(w_mm/h_mm);
+        data->display_aspect = (float)(w_mm/h_mm);
 
         // Resize X window to fill new resolution
         XMoveResizeWindow(data->XJ_disp, data->XJ_win, 0, 0,
@@ -800,10 +800,18 @@
     int res = 0, status = 0;
 
     res = XvMCGetSurfaceStatus(disp, surf, &status);
+    if (res)
+        VERBOSE(VB_PLAYBACK, QString("Error XvMCGetSurfaceStatus %1").arg(res));
     if (status & XVMC_RENDERING)
         XvMCSyncSurface(disp, surf);
 }
 
+static void FlushSurface(Display *disp, XvMCSurface *surf)
+{
+    if (surf)
+        XvMCFlushSurface(disp, surf);
+}
+
 void VideoOutputXvMC::PrepareFrame(VideoFrame *buffer, FrameScanType t)
 {
     (void)t;
@@ -816,15 +824,13 @@
 
     xvmc_render_state_t *render = (xvmc_render_state_t *)buffer->buf;
 
-    SyncSurface(data->XJ_disp, render->p_surface);
+    VideoFrame *osdframe = (VideoFrame *)(render->p_osd_target_surface_render);
+    xvmc_render_state_t * osdrender =
+        (osdframe) ? (xvmc_render_state_t *)(osdframe->buf) : 0;
+    Display *display = data->XJ_disp;
 
-    VideoFrame *osdframe = (VideoFrame *)render->p_osd_target_surface_render;
-
-    if (osdframe)
-    {
-        xvmc_render_state_t *osdren = (xvmc_render_state_t *)osdframe->buf;
-        SyncSurface(data->XJ_disp, osdren->p_surface);
-    }
+    SyncSurface(display, render->p_surface);
+    SyncSurface(display, (osdrender) ? osdrender->p_surface : 0);
 
     render->state |= MP_XVMC_STATE_DISPLAY_PENDING;
     data->p_render_surface_to_show = render;
@@ -910,6 +916,36 @@
     pthread_mutex_unlock(&lock);
 }
 
+void FlushSlice(Display *display, XvMCSurface* current, int pict_type,
+                XvMCSurface* past, XvMCSurface* future)
+{
+    // We always display I and P frames, so flush them
+    if (!past && !future)
+    { // I frame
+        FlushSurface(display, current); // Flush I frame
+        if (FF_I_TYPE!=pict_type)
+            cerr<<"I"<<FF_I_TYPE<<":"<<pict_type;
+    }
+    else if (past && !future)
+    { // P frame
+        FlushSurface(display, past);    // Flush I/P frame
+        FlushSurface(display, current); // Flush P frame
+        if (FF_P_TYPE!=pict_type)
+            cerr<<"P"<<FF_P_TYPE<<":"<<pict_type;
+    }
+    else
+    { // B frame
+        // We don't always display B frames, so forgo flushing...
+        if (FF_B_TYPE!=pict_type) {
+            cerr<<"B"<<FF_B_TYPE<<":"<<pict_type;
+            // error? flush all!
+            FlushSurface(display, past);
+            FlushSurface(display, future);
+            FlushSurface(display, current);
+        }
+    }
+}
+
 void VideoOutputXvMC::DrawSlice(VideoFrame *frame, int x, int y, int w, int h)
 {
     (void)x;
@@ -921,10 +957,8 @@
 
     pthread_mutex_lock(&lock);
 
-    if (render->p_past_surface != NULL)
-        SyncSurface(data->XJ_disp, render->p_past_surface);
-    if (render->p_future_surface != NULL)
-        SyncSurface(data->XJ_disp, render->p_future_surface);
+    if (render->p_past_surface && !render->p_future_surface)
+        SyncSurface(data->XJ_disp, render->p_past_surface); // Sync prev-I frame
 
     int res = XvMCRenderSurface(data->XJ_disp, &data->ctx, 
                                 render->picture_structure, render->p_surface,
@@ -939,7 +973,8 @@
         cerr << "XvMCRenderSurface error\n";
     }
 
-    XvMCFlushSurface(data->XJ_disp, render->p_surface);
+    FlushSlice(data->XJ_disp, render->p_surface, render->pict_type, 
+               render->p_past_surface, render->p_future_surface);
 
     pthread_mutex_unlock(&lock);
 
@@ -1019,7 +1054,8 @@
                 XvMCCompositeSubpicture(data->XJ_disp, &data->subpicture, 
                                         data->xvimage, 0, 0, XJ_width, 
                                         XJ_height, 0, 0);
-                XvMCSyncSubpicture(data->XJ_disp, &data->subpicture);
+                // delay sync until after getnextfreeframe...
+                XvMCFlushSubpicture(data->XJ_disp, &data->subpicture);
             }
 
             if (data->subpicture_mode == BLEND_SUBPICTURE)
@@ -1029,6 +1065,7 @@
                 xvmc_render_state_t *osdren;
                 osdren = (xvmc_render_state_t *)newframe->buf;
 
+                XvMCSyncSubpicture(data->XJ_disp, &data->subpicture);
                 XvMCBlendSubpicture2(data->XJ_disp, render->p_surface,
                                      osdren->p_surface, &data->subpicture,
                                      0, 0, XJ_width, XJ_height,
@@ -1038,11 +1075,14 @@
             }
             else if (data->subpicture_mode == BACKEND_SUBPICTURE)
             {
+                XvMCSyncSubpicture(data->XJ_disp, &data->subpicture);
                 XvMCBlendSubpicture(data->XJ_disp, render->p_surface,
                                     &data->subpicture, 0, 0, XJ_width,
                                     XJ_height, 0, 0, XJ_width, XJ_height);
             }
 
+            FlushSurface(data->XJ_disp, render->p_surface);
+            
             pthread_mutex_unlock(&lock);
         }
     }


More information about the mythtv-dev mailing list