Re: [path] vdr-1.6 better spu on ff card

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



matthieu castet a écrit :
Hi,

this patch try to handle case where the osd is limited (for example on ff card). For that it try to split area, count the really needed bpp (all transparent index can be merged together and will with my previous patch in osd.c).

Also it fix a bug in the current version : removing all the transparent baground area is ok only if it is recomputed at each draw. Otherwise a highlight request can happen outside the computed area.

With this patch I can navigate in dvd menu that produce oeOutOfMemory before.

Matthieu


I forgot the patch...
--- vdr-1.6.0/dvbspu.c	2007-02-03 11:13:18.000000000 +0100
+++ vdr-1.6.0p/dvbspu.c	2009-11-21 21:48:54.000000000 +0100
@@ -335,6 +335,35 @@
     return size;
 }
 
+int cDvbSpuBitmap::getMinBpp(const aDvbSpuPalDescr paldescr)
+{
+    int col = 1;
+    for (int i = 0; i < 4; i++) {
+        if (paldescr[i].trans != 0) {
+                col++;
+        }
+    }
+    return col > 2 ? 2 : 1;
+}
+
+int cDvbSpuDecoder::CalcAreaBpp(cBitmap *fgbmp, cBitmap *bgbmp)
+{
+        int fgbpp = 0;
+        int bgbpp = 0;
+        int ret;
+    if (fgbmp) {
+            fgbpp = spubmp->getMinBpp(hlpDescr);
+    }
+    if (bgbmp) {
+            bgbpp = spubmp->getMinBpp(palDescr);
+    }
+    ret = fgbpp + bgbpp;
+    if (ret > 2)
+            ret = 4;
+    return ret;
+}
+
+
 void cDvbSpuDecoder::Draw(void)
 {
     cMutexLock MutexLock(&mutex);
@@ -342,43 +371,89 @@
         Hide();
         return;
     }
-
+    sDvbSpuRect bgsize;
     cBitmap *fg = NULL;
     cBitmap *bg = NULL;
-    sDvbSpuRect bgsize;
-    sDvbSpuRect hlsize;
-
-    hlsize.x1 = hlpsize.x1;
-    hlsize.y1 = hlpsize.y1;
-    hlsize.x2 = hlpsize.x2;
-    hlsize.y2 = hlpsize.y2;
 
     if (highlight)
-        fg = spubmp->getBitmap(hlpDescr, palette, hlsize);
+        fg = spubmp->getBitmap(hlpDescr, palette, hlpsize);
 
     if (spubmp->getMinSize(palDescr, bgsize))
         bg = spubmp->getBitmap(palDescr, palette, bgsize);
 
-    sDvbSpuRect areaSize = CalcAreaSize(hlsize, fg, bgsize, bg);
+    if (osd == NULL) {
+            restricted_osd = false;
+            osd = cOsdProvider::NewOsd(0, 0);
+
+            tArea Area = { size.x1, size.y1, size.x2, size.y2, 4};
+            if (osd->CanHandleAreas(&Area, 1) != oeOk)
+                    restricted_osd = true;
+            else
+                osd->SetAreas(&Area, 1);
+    }
+    if (restricted_osd) {
+            sDvbSpuRect hlsize;
+            bool setarea = false;
+            /* reduce fg area (only valid if there is no bg below) */
+            if (fg) {
+                    spubmp->getMinSize(hlpDescr,hlsize);
+                    /* clip to the highligh area */
+                    setMax(hlsize.x1, hlpsize.x1);
+                    setMax(hlsize.y1, hlpsize.y1);
+                    setMin(hlsize.x2, hlpsize.x2);
+                    setMin(hlsize.y2, hlpsize.y2);
+                    if (hlsize.x1 > hlsize.x2 || hlsize.y1 > hlsize.y2) {
+                            hlsize.x1 = hlsize.x2 = hlsize.y1 = hlsize.y2 = 0;
+                    }
+            }
+            sDvbSpuRect areaSize = CalcAreaSize((fg && bg) ? hlpsize : hlsize, fg, bgsize, bg);
 
-    if (!fg || !bg || !osd) {
-       Hide();
-       }
+#define DIV(a, b) (a/b)?:1
+            for (int d = 1; !setarea && d <= 2; d++) {
 
-    if (bg || fg) {
-        if (osd == NULL) {
-           osd = cOsdProvider::NewOsd(0, 0);
-           if ((areaSize.width() & 3) != 0)
-              areaSize.x2 += 4 - (areaSize.width() & 3);
-           tArea Area = { areaSize.x1, areaSize.y1, areaSize.x2, areaSize.y2, (fg && bg) ? 4 : 2 };
-           if (osd->SetAreas(&Area, 1) != oeOk)
+                    /* first try old behaviour */
+                    tArea Area = { areaSize.x1, areaSize.y1, areaSize.x2, areaSize.y2, DIV(CalcAreaBpp(fg, bg), d) };
+            
+                    if ((Area.Width() & 7) != 0)
+                            Area.x2 += 8 - (Area.Width() & 7);
+
+                    if (osd->CanHandleAreas(&Area, 1) == oeOk &&
+                        osd->SetAreas(&Area, 1) == oeOk)
+                            setarea = true;
+
+                    /* second try to split area if there is both area */
+                    if (!setarea && fg && bg) {
+                            tArea Area_Both [2] = { 
+                                    {bgsize.x1, bgsize.y1, bgsize.x2, bgsize.y2, DIV(CalcAreaBpp(0, bg), d)},
+                                    {hlpsize.x1, hlpsize.y1, hlpsize.x2, hlpsize.y2, DIV(CalcAreaBpp(fg, 0), d)}
+                            };
+                            if (!Area_Both[0].Intersects(Area_Both[1])) {
+                                    /* there is no intersection. We can reduce hl */
+                                    Area_Both[1].x1 = hlsize.x1;
+                                    Area_Both[1].y1 = hlsize.y1;
+                                    Area_Both[1].x2 = hlsize.x2;
+                                    Area_Both[1].y2 = hlsize.y2;
+
+                                    if ((Area_Both[0].Width() & 7) != 0)
+                                            Area_Both[0].x2 += 8 - (Area_Both[0].Width() & 7);
+                                    if ((Area_Both[1].Width() & 7) != 0)
+                                            Area_Both[1].x2 += 8 - (Area_Both[1].Width() & 7);
+                                    if (osd->CanHandleAreas(Area_Both, 2) == oeOk &&
+                                        osd->SetAreas(Area_Both, 2) == oeOk)
+                                            setarea = true;
+                            }
+                    }
+            }
+            if (!setarea)
               dsyslog("dvbspu: AreaSize (%d, %d) (%d, %d) Bpp %d", areaSize.x1, areaSize.y1, areaSize.x2, areaSize.y2, (fg && bg) ? 4 : 2 );
-           }
+    }
 
+    /* we could draw use DrawPixel on osd */
+    if (bg || fg) {
         if (bg)
            osd->DrawBitmap(bgsize.x1, bgsize.y1, *bg);
         if (fg)
-           osd->DrawBitmap(hlsize.x1, hlsize.y1, *fg);
+           osd->DrawBitmap(hlpsize.x1, hlpsize.y1, *fg);
         delete fg;
         delete bg;
 
@@ -509,6 +584,7 @@
                 }
             }
             if (fodd != 0 && feven != 0) {
+                Hide();
                 delete spubmp;
                 spubmp = new cDvbSpuBitmap(size, spu + fodd, spu + feven,
                                            spu + feven, spu + cmdOffs());
--- vdr-1.6.0/dvbspu.h	2006-04-17 14:47:29.000000000 +0200
+++ vdr-1.6.0p/dvbspu.h	2009-11-21 21:38:07.000000000 +0100
@@ -82,6 +82,7 @@
 
     bool getMinSize(const aDvbSpuPalDescr paldescr,
                     sDvbSpuRect & size) const;
+    int getMinBpp(const aDvbSpuPalDescr paldescr);
     cBitmap *getBitmap(const aDvbSpuPalDescr paldescr,
                        const cDvbSpuPalette & pal,
                        sDvbSpuRect & size) const;
@@ -99,6 +100,7 @@
     uint32_t spupts;
     bool clean;
     bool ready;
+    bool restricted_osd;
 
     enum spFlag { spNONE, spHIDE, spSHOW, spMENU };
     spFlag state;
@@ -131,6 +133,7 @@
     };
 
     sDvbSpuRect CalcAreaSize(sDvbSpuRect fgsize, cBitmap *fgbmp, sDvbSpuRect bgsize, cBitmap *bgbmp);
+    int CalcAreaBpp(cBitmap *fgbmp, cBitmap *bgbmp);
 
   public:
     cDvbSpuDecoder();
_______________________________________________
vdr mailing list
vdr@xxxxxxxxxxx
http://www.linuxtv.org/cgi-bin/mailman/listinfo/vdr

[Index of Archives]     [Linux Media]     [Asterisk]     [DCCP]     [Netdev]     [Xorg]     [Util Linux NG]     [Xfree86]     [Big List of Linux Books]     [Fedora Users]     [Fedora Women]     [ALSA Devel]     [Linux USB]

  Powered by Linux