Package: vdr Version: 1.6.0-13 Severity: normal Tags: patch Hi,
on FF card osd memory are limited and the dvd menu sometime failed to be displayed with oeOutOfMemory error. This patch try to use less memory for dvd menu. Matthieu PS : this patch has been integrated in vdr 1.7 : http://thread.gmane.org/gmane.linux.vdr/41532 -- System Information: Debian Release: squeeze/sid APT prefers unstable APT policy: (500, 'unstable'), (500, 'testing'), (1, 'experimental') Architecture: i386 (i686) Kernel: Linux 2.6.31-1-686 (SMP w/1 CPU core) Locale: LANG=C, LC_CTYPE=C (charmap=ISO-8859-1) (ignored: LC_ALL set to fr_FR) Shell: /bin/sh linked to /bin/dash Versions of packages vdr depends on: ii adduser 3.112 add and remove users and groups ii debconf [debconf-2.0] 1.5.28 Debian configuration management sy ii libc6 2.10.2-2 GNU C Library: Shared libraries ii libcap2 1:2.17-2 support for getting/setting POSIX. ii libfontconfig1 2.6.0-4.2 generic font configuration library ii libfreetype6 2.3.11-1 FreeType 2 font engine, shared lib ii libgcc1 1:4.4.2-7 GCC support library ii libjpeg62 6b-15 The Independent JPEG Group's JPEG ii libstdc++6 4.4.2-7 The GNU Standard C++ Library v3 ii psmisc 22.9-1 utilities that use the proc file s Versions of packages vdr recommends: pn lirc <none> (no description available) ii ttf-bitstream-vera 1.10-7 The Bitstream Vera family of free ii ttf-freefont 20090104-5 Freefont Serif, Sans and Mono True vdr suggests no packages. -- debconf information excluded
--- 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();