[mythtv] [debugging patch] chatty XvMC IDCT patch, please test if you have GeForce 4Ti

Daniel Thor Kristjansson danielk at cat.nyu.edu
Mon Aug 23 23:33:14 EDT 2004


A few months ago a small part of the IDCT patch didn't make it in
because it didn't work with cards without IDCT acceleration. This
patch tries to solve that problem. I consolidated some similar code for
finding XvMC surfaces into a new less buggy find() method in
XvMCSurfaces, and I also made all the methods involved emit more
debugging info.

What I need someone with a MC acceleration only card (GeForce 4Ti) to do
is view some MPEG2 videos with XvMC acceleration enabled, if this works
just e-mail me or the list. If it doesn't, send me the output of
"mythfrontend --verbose playback" so I can track down the problem.

Thanks,
  Daniel

BTW this also includes a new "#define DISABLE_IDCT" in videoout_xvmc.h
which you can uncomment if you want to disable IDCT acceleration on a
card that supports IDCT.
-------------- next part --------------
Index: libs/libmythtv/NuppelVideoPlayer.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/NuppelVideoPlayer.cpp,v
retrieving revision 1.357
diff -u -r1.357 NuppelVideoPlayer.cpp
--- libs/libmythtv/NuppelVideoPlayer.cpp	20 Aug 2004 06:29:48 -0000	1.357
+++ libs/libmythtv/NuppelVideoPlayer.cpp	24 Aug 2004 03:15:13 -0000
@@ -404,9 +404,13 @@
         // an IDCT or MC pixel format.
         if (kVideoOutput_XvMC == forceVideoOutput) 
         {
+#ifdef DISABLE_IDCT
+            decoder->SetPixelFormat(PIX_FMT_XVMC_MPEG2_MC);
+#else
             bool idct = videoOutput->hasIDCTAcceleration();
             decoder->SetPixelFormat((idct) ? PIX_FMT_XVMC_MPEG2_IDCT :
-                                             PIX_FMT_XVMC_MPEG2_MC);
+				    PIX_FMT_XVMC_MPEG2_MC);
+#endif
         }
 #endif
 
Index: libs/libmythtv/XvMCSurfaceTypes.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/XvMCSurfaceTypes.cpp,v
retrieving revision 1.1
diff -u -r1.1 XvMCSurfaceTypes.cpp
--- libs/libmythtv/XvMCSurfaceTypes.cpp	19 Aug 2004 05:17:26 -0000	1.1
+++ libs/libmythtv/XvMCSurfaceTypes.cpp	24 Aug 2004 03:15:13 -0000
@@ -75,95 +75,100 @@
     return -1;
 }
 
-void XvMCSurfaceTypes::find(int minWidth, int minHeight,
+void XvMCSurfaceTypes::find(Display *display, 
+			    int minWidth, int minHeight,
                             int chroma, bool idct, int mpeg,
-                            int minSubpictureWidth, 
-                            int minSubpictureHeight,
-                            Display *dpy, XvPortID portMin, 
-                            XvPortID portMax, XvPortID& port, 
-                            int& surfNum) 
+                            int minSubpictWidth, int minSubpictHeight,
+                            XvPortID portMin, XvPortID portMax,
+			    XvPortID& port, int& surfNum) 
 {
-    VERBOSE(VB_PLAYBACK, 
-            QString("XvMCSurfaceTypes::find(w %1, h %2, c %3, i %4, m %5,"
-                    "sw %6, sh %7, disp, p<= %9, %10 <=p, port, surfNum)")
-            .arg(minWidth).arg(minHeight).arg(chroma).arg(idct).arg(mpeg)
-            .arg(minSubpictureWidth).arg(minSubpictureHeight)
+    VERBOSE(VB_PLAYBACK,
+            QString("XvMCSurfaceTypes::find(wxh %1x%2, chroma %3, w/idct %4,")
+            .arg(minWidth).arg(minHeight).arg(chroma).arg(idct));
+    VERBOSE(VB_PLAYBACK,
+            QString("... mpeg%1, sub wxh %2x%3, %4<=port<=%5)")
+            .arg(mpeg).arg(minSubpictWidth).arg(minSubpictHeight)
             .arg(portMin).arg(portMax));
 
-    port = 0;
-    surfNum = -1;
+    port = surfNum = 0;
+
     for (XvPortID p = portMin; p <= portMax; p++) 
     {
         VERBOSE(VB_PLAYBACK, QString("Trying XvMC port %1").arg(p));
-        XvMCSurfaceTypes surf(dpy, p);
+        XvMCSurfaceTypes surf(display, p);
         int s = surf.find(minWidth, minHeight, chroma, idct, mpeg,
-                          minSubpictureWidth, minSubpictureHeight);
+                          minSubpictWidth, minSubpictHeight);
         if (s >= 0) 
         {
-            VERBOSE(VB_PLAYBACK, QString("Found a suitable XvMC surface %1")
-                                        .arg(s));
+            VERBOSE(VB_PLAYBACK, QString("Found a suitable XvMC surface %1, on port %2").arg(s).arg(p));
             port = p;
             surfNum = s;
             return;
         }
     }
 }
-        
-inline bool XvMCSurfaceTypes::hasIDCT(int width, int height,
-                                      int chroma, Display *pdisp) 
-{
-    Display* disp = pdisp;
-    if (!pdisp)
-        disp = createXvMCDisplay();
 
-    XvAdaptorInfo *ai = 0;
-    unsigned int p_num_adaptors = 0;
+void XvMCSurfaceTypes::find(Display* display, Window win,
+				int minWidth, int minHeight, 
+				int chroma, bool idct, int mpeg,
+				int minSubpictWidth, int minSubpictHeight,
+				XvPortID& port, int& surfNum) {
+    unsigned int err, num_adaptors, i;
+    XvAdaptorInfo *ai;
 
-    Window root = DefaultRootWindow(disp);
-    int ret = XvQueryAdaptors(disp, root, &p_num_adaptors, &ai);
+    port = surfNum = 0;
 
-    if (ret != Success) 
+    err = XvQueryAdaptors(display, win, &num_adaptors, &ai);
+
+    if (err != Success) 
     {
-        printf("XvQueryAdaptors failed.\n");
-        if (!pdisp)
-            XCloseDisplay(disp);
-        return false;
+        VERBOSE(VB_IMPORTANT, QString("XvQueryAdaptors failed. err=%1").arg(err));
+        num_adaptors = 0;
     }
 
-    if (!ai) 
+    for (i = 0; i < num_adaptors; i++) 
     {
-        if (!pdisp)
-            XCloseDisplay(disp);
-        return false; // huh? no xv capable video adaptors?
+	if (ai[i].type)
+	{
+	    find(display, minWidth, minHeight, chroma, idct, mpeg,
+		 minSubpictWidth, minSubpictHeight,
+		 ai[i].base_id, ai[i].base_id + ai[i].num_ports - 1, port, surfNum);
+	    if (port) {
+		VERBOSE(VB_PLAYBACK, QString("Found XvMC surf %1 on adaptor %2, port %3")
+			.arg(surfNum).arg(i).arg(port));
+		break;
+	    }
+	}
     }
 
-    for (unsigned int i = 0; i < p_num_adaptors; i++) 
+    if (num_adaptors > 0)
+	XvFreeAdaptorInfo(ai);
+
+    return;
+}
+
+        
+inline bool XvMCSurfaceTypes::hasIDCT(int width, int height,
+                                      int chroma, Display *display)
+{
+    XvPortID port;
+    int surfNum;
+
+    if (display)
+	find(display, DefaultRootWindow(display), width, height, chroma, true,
+	     /*mpeg*/2, width, height/3, port, surfNum);
+    else
     {
-        XvPortID p = 0;
-        int s;
-        if (ai[i].type == 0)
-            continue;
-        XvMCSurfaceTypes::find(width, height, chroma,
-                               true, 2, 0, 0,
-                               disp, ai[i].base_id, 
-                               ai[i].base_id + ai[i].num_ports - 1,
-                               p, s);
-        if (0 != p) 
-        {
-            if (p_num_adaptors > 0)
-                XvFreeAdaptorInfo(ai);
-            if (!pdisp)
-                XCloseDisplay(disp);
-            return true;
-        }
+        display = createXvMCDisplay();
+	find(display, DefaultRootWindow(display), width, height, chroma, true,
+	     /*mpeg*/2, width, height/3, port, surfNum);
+        XCloseDisplay(display);
     }
 
-    if (p_num_adaptors > 0)
-        XvFreeAdaptorInfo(ai);
-    if (!pdisp)
-        XCloseDisplay(disp);
+    VERBOSE(VB_PLAYBACK, QString("hasIDCT(WxH %1x%2) --> %3")
+	    .arg(width).arg(height).arg(port>0));
 
-    return false;
+    return bool(port > 0);
 }
 
 ostream& XvMCSurfaceTypes::print(ostream& os, int s) const
Index: libs/libmythtv/XvMCSurfaceTypes.h
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/XvMCSurfaceTypes.h,v
retrieving revision 1.2
diff -u -r1.2 XvMCSurfaceTypes.h
--- libs/libmythtv/XvMCSurfaceTypes.h	19 Aug 2004 05:17:26 -0000	1.2
+++ libs/libmythtv/XvMCSurfaceTypes.h	24 Aug 2004 03:15:13 -0000
@@ -131,13 +131,21 @@
 
     int size() const { return num; }
 
-    /// Find an appropriate surface on the current display.
-    static void find(int minWidth, int minHeight, int chroma, bool idct,
-                     int mpeg, int minSubpictureWidth, 
-                     int minSubpictureHeight, Display *dpy, 
+    /// Find an appropriate surface on the current adaptor.
+    static void find(Display *display, 
+		     int minWidth, int minHeight,
+		     int chroma, bool idct, int mpeg,
+		     int minSubpictWidth, int minSubpictHeight, 
                      XvPortID portMin, XvPortID portMax,
                      XvPortID& port, int& surfNum);
 
+    /// Find an appropriate surface on the current display	
+    static void find(Display* display, Window win,
+		     int minWidth, int minHeight, 
+		     int chroma, bool idct, int mpeg,
+		     int minSubpictWidth, int minSubpictHeight,
+		     XvPortID& port, int& surfNum);
+
     /// Find out if there is an IDCT Acceleration capable surface on any port.
     static bool hasIDCT(int width, int height,
                         int chroma = XVMC_CHROMA_FORMAT_420,
Index: libs/libmythtv/avformatdecoder.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/avformatdecoder.cpp,v
retrieving revision 1.93
diff -u -r1.93 avformatdecoder.cpp
--- libs/libmythtv/avformatdecoder.cpp	19 Aug 2004 01:32:25 -0000	1.93
+++ libs/libmythtv/avformatdecoder.cpp	24 Aug 2004 03:15:13 -0000
@@ -244,19 +244,24 @@
 
 static QMap<void*, enum PixelFormat> _PixelFormatsMap;
 
-/*
 static enum PixelFormat getFormat(struct AVCodecContext *cc,
                                   const enum PixelFormat *pixfmts) 
 {
+    PixelFormat fmt=pixfmts[0];
     if (_PixelFormatsMap.end() != _PixelFormatsMap.find(cc))
-    {
-        return _PixelFormatsMap[cc];
-    }
+        fmt = *_PixelFormatsMap.find(cc);
+    else
+        VERBOSE(VB_IMPORTANT, "Pixel format not set, returning pixfmts[0]");
+    
+    if (PIX_FMT_XVMC_MPEG2_MC == fmt)
+	VERBOSE(VB_PLAYBACK, "getFormat() returning PIX_FMT_XVMC_MPEG2_MC");
+    else if (PIX_FMT_XVMC_MPEG2_IDCT == fmt)
+	VERBOSE(VB_PLAYBACK, "getFormat() returning PIX_FMT_XVMC_MPEG2_IDCT");
+    else
+	VERBOSE(VB_PLAYBACK, QString("getFormat() returning UNEXPECTED %1").arg(fmt));
 
-    VERBOSE(VB_IMPORTANT, "Pixel format not set, returning pixfmts[0]");
-    return pixfmts[0];
+    return fmt;
 }
-*/
 
 void AvFormatDecoder::SetPixelFormat(const int pixFormat) 
 {
@@ -365,7 +370,7 @@
                     if (gContext->GetNumSetting("UseXVMC", 1))
                     {
                         enc->codec_id = CODEC_ID_MPEG2VIDEO_XVMC;
-                        //enc->get_format = getFormat;
+                        enc->get_format = getFormat;
                     }
 #endif            
 #ifdef USING_VIASLICE
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 03:15:13 -0000
@@ -134,7 +134,7 @@
                : VideoOutput()
 {
     XJ_started = 0; 
-    xv_port = -1; 
+    xv_port = 0;
 
     chroma = XVMC_CHROMA_FORMAT_420;
 
@@ -235,16 +235,14 @@
     pthread_mutex_init(&lock, NULL);
 
     int (*old_handler)(Display *, XErrorEvent *);
-    int i, ret;
+    int ret;
     XJ_caught_error = 0;
 
     unsigned int p_version, p_release, p_request_base, p_event_base, 
                  p_error_base;
-    int p_num_adaptors;
-    bool usingXinerama;
-    int event_base, error_base;
 
-    XvAdaptorInfo *ai;
+    bool usingXinerama;
+    int event_base, error_base, surf_num;
 
     VideoOutput::InitBuffers(kNumBuffers, false, kNeedFreeFrames,
                              kPrebufferFrames, kKeepPrebuffer);
@@ -347,63 +345,36 @@
         printf("Using XvMC version: %d.%d\n", mc_version, mc_release);
     }
 
-    ai = NULL;
-    xv_port = -1;
-    ret = XvQueryAdaptors(data->XJ_disp, data->XJ_root,
-                          (unsigned int *)&p_num_adaptors, &ai);
-
-    if (ret != Success) 
-    {
-        printf("XvQueryAdaptors failed.\n");
-        ai = NULL;
-    }
+    xv_port = 0;
+#ifndef DISABLE_IDCT
+    XvMCSurfaceTypes::find(data->XJ_disp, data->XJ_root, 
+			   width, height, chroma, true/*idct*/, 2, 
+			   width, height/3, xv_port, surf_num);
+#endif    
+    if (xv_port > 0)
+	VERBOSE(VB_PLAYBACK,
+		QString("Found XvMC Surface with IDCT support."
+			" port=%1, surf=%2").arg(xv_port).arg(surf_num));
     else
     {
-        if ( ai )
-        {
-            for (i = 0; i < p_num_adaptors; i++) 
-            {
-                if (ai[i].type == 0)
-                    continue;
-
-                XvPortID p = 0;
-                int s;
-                XvMCSurfaceTypes::find(width, height, chroma,
-                                       true, 2, 0, 0,
-                                       data->XJ_disp, ai[i].base_id,
-                                       ai[i].base_id + ai[i].num_ports - 1,
-                                       p, s);
-                if (0 == p) 
-                {
-                    // No IDCT surface found, try to find MC surface
-                    XvMCSurfaceTypes::find(width, height, chroma,
-                                           false, 2, 0, 0,
-                                           data->XJ_disp, ai[i].base_id,
-                                           ai[i].base_id + ai[i].num_ports - 1,
-                                           p, s);
-                }
-
-                if (p != 0) 
-                {
-                    xv_port = p;
-                    XvMCSurfaceTypes surf(data->XJ_disp, p);
-                    assert(surf.size()>0);
-                    surf.set(s, &data->surface_info);
-                    data->mode_id = surf.surfaceTypeID(s);
-                    break;
-                }
-            }
-
-            if (p_num_adaptors > 0)
-                XvFreeAdaptorInfo(ai);
-        }
-    }
-
-    if (xv_port <= 0)
-    {
-        VERBOSE(VB_ALL, "Invalid xv port");
-        return false;
-    }
+	XvMCSurfaceTypes::find(data->XJ_disp, data->XJ_root,
+			       width, height, chroma, false/*mc*/, 2, 
+			       width, height/3, xv_port, surf_num);
+	if (xv_port > 0)
+	    VERBOSE(VB_PLAYBACK,
+		    QString("Found XvMC Surface with MC support."
+			    " port=%1, surf=%2").arg(xv_port).arg(surf_num));
+	else
+	{
+	    VERBOSE(VB_ALL, "Invalid xv port");
+	    return false;
+	}
+    }
+
+    XvMCSurfaceTypes surf(data->XJ_disp, xv_port);
+    assert(surf.size()>0);
+    surf.set(surf_num, &data->surface_info);
+    data->mode_id = surf.surfaceTypeID(surf_num);
 
     if (display_res)
     {
@@ -550,7 +521,8 @@
 
     if (ret != Success)
     {
-        cerr << "Unable to create XvMC Context return status:" << ret ;
+        cerr << "Unable to create XvMC Context on port "
+	     << xv_port << "return status:" << ret ;
         switch (ret)
         {
             case XvBadPort: cerr << " XvBadPort"; break;
Index: libs/libmythtv/videoout_xvmc.h
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/videoout_xvmc.h,v
retrieving revision 1.12
diff -u -r1.12 videoout_xvmc.h
--- libs/libmythtv/videoout_xvmc.h	5 Aug 2004 07:35:02 -0000	1.12
+++ libs/libmythtv/videoout_xvmc.h	24 Aug 2004 03:15:13 -0000
@@ -5,6 +5,12 @@
 
 #include <DisplayRes.h>
 #include "videooutbase.h"
+extern "C" {
+#include "../libavcodec/avcodec.h"
+#include "../libavcodec/xvmc_render.h"
+}
+
+//#define DISABLE_IDCT // disable IDCT acceleration, for debugging
 
 class VideoOutputXvMC : public VideoOutput
 {
@@ -61,7 +67,7 @@
     int XJ_screenwidth, XJ_screenheight;
     int XJ_fullscreen;
 
-    int xv_port;
+    XvPortID xv_port;
     int colorid;
 
     pthread_mutex_t lock;


More information about the mythtv-dev mailing list