diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | dxr3configdata.c | 1 | ||||
-rw-r--r-- | dxr3configdata.h | 17 | ||||
-rw-r--r-- | dxr3osd.c | 278 | ||||
-rw-r--r-- | dxr3osd.h | 21 |
5 files changed, 297 insertions, 22 deletions
@@ -61,7 +61,7 @@ OBJS = $(PLUGIN).o dxr3multichannelaudio.o dxr3sysclock.o dxr3colormanager.o \ dxr3syncbuffer.o dxr3audiodecoder.o dxr3blackframe.o dxr3nextpts.o \ dxr3pesframe.o dxr3demuxdevice.o dxr3configdata.o dxr3ffmpeg.o \ dxr3interface_spu_encoder.o dxr3interface.o dxr3device.o \ - dxr3outputthread.o dxr3osd.o dxr3osd_subpicture.o dxr3spudecoder.o + dxr3outputthread.o dxr3osd.o dxr3spudecoder.o ### Default target: diff --git a/dxr3configdata.c b/dxr3configdata.c index 0ae0929..f3b682d 100644 --- a/dxr3configdata.c +++ b/dxr3configdata.c @@ -30,7 +30,6 @@ cDxr3ConfigData::cDxr3ConfigData() m_card = 0; m_forceletterbox = 0; m_videomode = PAL; - m_menumode = SUBPICTURE; m_brightness = 500; m_contrast = 500; m_saturation = 500; diff --git a/dxr3configdata.h b/dxr3configdata.h index 778de89..0fe6b8e 100644 --- a/dxr3configdata.h +++ b/dxr3configdata.h @@ -35,14 +35,6 @@ enum eVideoMode }; // ================================== -// possible menu modes -enum eMenuMode -{ - SUBPICTURE = 0, - MPEG -}; - -// ================================== //! global interface to access all config datas of this plugin /* With this singleton you can access very easy all possible @@ -87,14 +79,6 @@ public: { return m_videomode = videoMode; } - eMenuMode GetMenuMode() const - { - return m_menumode; - } - eMenuMode SetMenuMode(eMenuMode menuMode) - { - return m_menumode = menuMode; - } int GetBrightness() const { @@ -151,7 +135,6 @@ public: protected: eVideoMode m_videomode; int m_usewss; - eMenuMode m_menumode; int m_digitaloutput; int m_card; int m_forceletterbox; @@ -31,15 +31,287 @@ #include "dxr3osd.h" #include "dxr3interface_spu_encoder.h" -#include "dxr3osd_subpicture.h" - // ================================== // ! create osd at (Left, Top, Level) cOsd *cDxr3OsdProvider::CreateOsd(int Left, int Top, uint Level) { - return new cDxr3SubpictureOsd(Left, Top, Level); + return new cDxr3Osd(Left, Top, Level); } +// Enables some time measure debugging code +// (taken from the osdteletext plugin, thanks folks) +#ifdef timingdebug +#include <sys/timeb.h> +class cTime +{ + // Debugging: Simple class to measure time + timeb start; +public: + void Start() + { + ftime(&start); + } + void Stop(char *txt) + { + timeb t; + ftime(&t); + int s = t.time-start.time; + int ms = t.millitm - start.millitm; + if (ms<0) + { + s--; + ms += 1000; + } + printf("%s: %i.%03i\n", txt, s, ms); + } +}; +#endif + +#define MAXNUMWINDOWS 7 // OSD windows are counted 1...7 + +// ================================== +//! constructor +cDxr3Osd::cDxr3Osd(int Left, int Top, uint Level) + : cOsd(Left, Top, Level) +{ + shown = false; + Palette = new cPalette(4); + last = new cTimeMs(); + last->Set(-cDxr3ConfigData::Instance().GetOsdFlushRate()); + Spu = &cSPUEncoder::Instance(); +} + +// ================================== +cDxr3Osd::~cDxr3Osd() +{ + SetActive(false); + delete Palette; + delete last; +} + +// ================================== +void cDxr3Osd::SetActive(bool On) +{ + if (On != Active()) + { + // Clears the OSD screen image when it becomes active + // removes it from screen when it becomes inactive + cOsd::SetActive(On); + if (On) + { + Spu->Clear(); + } + else + { + Spu->StopSpu(); + } + } +} + +// ================================== +eOsdError cDxr3Osd::CanHandleAreas(const tArea *Areas, int NumAreas) +{ + + eOsdError Result = cOsd::CanHandleAreas(Areas, NumAreas); + if (Result == oeOk) + { + if (NumAreas > MAXNUMWINDOWS) + { + return oeTooManyAreas; + } + + for (int i = 0; i < NumAreas; i++) + { + if (Areas[i].bpp != 1 && + Areas[i].bpp != 2 && + Areas[i].bpp != 4 && + Areas[i].bpp != 8) + { + return oeBppNotSupported; + } + + if ((Areas[i].Width() & (8 / Areas[i].bpp - 1)) != 0) + { + return oeWrongAlignment; + } + } + } + return Result; +} + +eOsdError cDxr3Osd::SetAreas(const tArea *Areas, int NumAreas) +{ + if (shown) + { + Spu->Clear(); + shown = false; + } + return cOsd::SetAreas(Areas, NumAreas); +} + +// ================================== +void cDxr3Osd::Flush() +{ + if (!Active()) + return; + if (last->Elapsed() < cDxr3ConfigData::Instance().GetOsdFlushRate()) + return; + last->Set(); + +#ifdef timingdebug + cTime t; + t.Start(); +#endif + + cBitmap *Bitmap; + int oldi; + int newi; + int i; + int indexfree[16]; + int firstfree = -1; + int indexnoassigned[16]; + int firstnoassigned = -1; + bool colfree[16]; + int NumNewColors; + int NumOldColors; + + //determine the palette used by all bitmaps (without alpha channel) + + cPalette *newPalette = new cPalette(4); + for (i = 0; i < 16; i++) + colfree[i]=true; + for (i = 0; (Bitmap = GetBitmap(i)) != NULL; i++) + { + int nc; + const tColor *col = Bitmap->Colors(nc); + if (col) + for (int kk = 0; kk < nc; kk++) + newPalette->Index(col[kk] & 0x00FFFFFF); + } + const tColor *newColors = newPalette->Colors(NumNewColors); + const tColor *oldColors = Palette->Colors(NumOldColors); + // colors already assigned + for (newi = 0; newi < NumNewColors; newi++) + { + for (oldi = 0; oldi < NumOldColors; oldi++) + { + if (newColors[newi] == oldColors[oldi]) + { + colfree[oldi] = false; + break; + } + } + if (oldi >= NumOldColors) + { + firstnoassigned++; + indexnoassigned[firstnoassigned] = newi; + } + } + // unused colors + for (i = 0; i < NumOldColors; i++) + { + if (colfree[i]) { + firstfree++; + indexfree[firstfree] = i; + } + } + // replace unused colors with unassigned ones + for (i = 0; i <= firstnoassigned; i++) + { + newi = indexnoassigned[i]; + if (firstfree >= 0) + { + Palette->SetColor(indexfree[firstfree], newColors[newi]); + firstfree--; + } else { + Palette->Index(newColors[newi]); + } + } + delete newPalette; + + // Shove the bitmaps to the OSD global bitmap + for (int i = 0; (Bitmap = GetBitmap(i)) != NULL; i++) + { + int x1 = 0, y1 = 0, x2 = 0, y2 = 0; + if (Bitmap->Dirty(x1, y1, x2, y2)) + { + /* TODO workaround: + apparently the bitmap sent to the driver always has to be a + multiple of 8 bits wide, and (dx * dy) also has to be a + multiple of 8. Fix driver (should be able to handle any size + bitmaps!) + This isn't actually necessary with this plugin, but since other + plugins rely on this behaviour to work correctly, I left it + here. It doesn't hurt too much. + */ + +// http://article.gmane.org/gmane.linux.vdr/21572 +//#define optimize_bitmap_transfer +#ifdef optimize_bitmap_transfer + while ((x1 > 0 || x2 < Bitmap->Width() - 1) && + ((x2 - x1) & 7) != 7) + { + if (x2 < Bitmap->Width() - 1) + { + x2++; + } + else if (x1 > 0) + { + x1--; + } + } + + //TODO "... / 2" <==> Bpp??? + while ((y1 > 0 || y2 < Bitmap->Height() - 1) && + (((x2 - x1 + 1) * (y2 - y1 + 1) / 2) & 7) != 0) + { + if (y2 < Bitmap->Height() - 1) + { + y2++; + } + else if (y1 > 0) + { + y1--; + } + } + + while ((x1 > 0 || x2 < Bitmap->Width() - 1) && + (((x2 - x1 + 1) * (y2 - y1 + 1) / 2) & 7) != 0) + { + if (x2 < Bitmap->Width() - 1) + { + x2++; + } + else if (x1 > 0) + { + x1--; + } + } +#else + x1 = 0; + y1 = 0; + x2 = Bitmap->Width() - 1; + y2 = Bitmap->Height() - 1; +#endif + + Spu->SetPalette(i + 1, Palette, Bitmap); + int origx = Left() + Bitmap->X0(); + int origy = Top() + Bitmap->Y0(); + Spu->CopyBlockIntoOSD(i + 1, Bitmap->Width(), origx + x1, + origy + y1, origx + x2, origy + y2, + Bitmap->Data(x1, y1)); + Bitmap->Clean(); + } + } + + Spu->Flush(Palette); + shown = true; +#ifdef timingdebug + t.Stop("cDxr3SubpictureOsd::Flush"); +#endif +} + + // Local variables: // mode: c++ // c-file-style: "stroustrup" @@ -13,6 +13,27 @@ public: virtual cOsd *CreateOsd(int Left, int Top, uint Level); }; +// ================================== +// osd interface +class cDxr3Osd : public cOsd +{ +private: + cSPUEncoder* Spu; ///< interface to cSPUEncoder + bool shown; ///< is the osd shown? + cPalette* Palette; ///< global palette (needed by all bitmaps) + cTimeMs *last; +protected: + virtual void SetActive(bool On); +public: + cDxr3Osd(int Left, int Top, uint Level); + ~cDxr3Osd(); + + eOsdError CanHandleAreas(const tArea *Areas, int NumAreas); + eOsdError SetAreas(const tArea *Areas, int NumAreas); + + void Flush(); +}; + #endif /*_DXR3_OSD_H_*/ // Local variables: |