[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