summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorscop <scop>2005-04-17 11:29:21 +0000
committerscop <scop>2005-04-17 11:29:21 +0000
commit9216c55e163f619a33770119339ae0651cd1e417 (patch)
tree64a7869a8001785d0bcdcf5523b088ac366d6602
parentb4cecb13ef4fa7389a96f721e57da2cf68cb65e4 (diff)
downloadvdr-plugin-dxr3-9216c55e163f619a33770119339ae0651cd1e417.tar.gz
vdr-plugin-dxr3-9216c55e163f619a33770119339ae0651cd1e417.tar.bz2
OSD color management rework from Luca Olivetti.
-rw-r--r--HISTORY2
-rw-r--r--dxr3colormanager.c326
-rw-r--r--dxr3colormanager.h19
-rw-r--r--dxr3interface_spu_encoder.c104
-rw-r--r--dxr3interface_spu_encoder.h2
-rw-r--r--dxr3osd_subpicture.c14
6 files changed, 257 insertions, 210 deletions
diff --git a/HISTORY b/HISTORY
index c5ebf05..8415f56 100644
--- a/HISTORY
+++ b/HISTORY
@@ -284,5 +284,5 @@ NOTE: I havent found time to include all of the languages, will be done in pre2
- remove unused dxr3unixserversocket.* from 0.2.x (Ville Skyttä)
- fix sound with the MP3 plugin and VDR >= 1.3.18 (Antti Järvinen)
- fix aspect ratio after returning from the MPlayer plugin (Luca Olivetti)
-- fix color "bleeding" in OSD (Luca Olivetti)
+- rework OSD color management, fixes color "bleeding" (Luca Olivetti)
- sync SPU decoder with VDR 1.3.23 (Ville Skyttä)
diff --git a/dxr3colormanager.c b/dxr3colormanager.c
index 563cba7..d2aa7ff 100644
--- a/dxr3colormanager.c
+++ b/dxr3colormanager.c
@@ -56,12 +56,38 @@
#include <stdio.h>
#include <string.h>
+//#define timingdebug
+// 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
+
// ==================================
//! constructor
cColorManager::cColorManager()
{
- NrOfRegions = 0;
- isopen = false;
+ NrOfRegions = -1;
for(int i = 0; i < MAX_NO_OF_REGIONS; i++)
hlr[i] = NULL;
}
@@ -82,154 +108,180 @@ cColorManager::~cColorManager()
// Opens a new highlight region
void cColorManager::OpenRegion(int y)
{
- hlr[NrOfRegions] = new yRegion();
- hlr[NrOfRegions]->Y1 = y;
- isopen = true;
+ // Calling method (cColorManager::EncodeColors)
+ // already checks MAX_NO_OF_REGIONS
+ curRegion = new yRegion();
+ curRegion->Y1 = y;
+ NrOfRegions++;
+ hlr[NrOfRegions] = curRegion;
+ NewSection(0); //there's always at least a section
}
// ==================================
// Closes the spu-highlight region
void cColorManager::CloseRegion(int y)
{
-
- hlr[NrOfRegions]->Y2 = y;
- isopen = false;
-
- if (hlr[NrOfRegions]->N != 0) // skip this region if there is no section defined
- {
- if (NrOfRegions < MAX_NO_OF_REGIONS - 1)
- {
- NrOfRegions++;
- }
- }
-
+ curRegion->Y2 = y;
}
// ==================================
void cColorManager::EncodeColors(int width, int height, unsigned char* map, unsigned char* dmap)
{
unsigned char color;
+ unsigned char oldcolor=0xFF;
unsigned char ColorIndex;
- unsigned char buffer[1024] = {0};
-
- for (int y = 0; y < height; ++y)
- {
- for(int x = 0; x < width; ++x)
- {
- color = map[y * width + x];
- if (color != 0) MaxY = y;
- if (AddColor(x, y, color, ColorIndex))
- {
- // store as the highlight region index
- buffer[x] = ColorIndex;
- }
- else
- {
- // retry with another region
- // FIXME: check limits to avoid infinite loop
- x = -1;
- }
+ int mapoffset=0;
+
+ #ifdef timingdebug
+ cTime t;
+ t.Start();
+ #endif
+
+ OpenRegion(0);
+ for (int y = 0; y < height; ++y) {
+ oldcolor=0xFF;
+ FirstSection();
+ for(int x = 0; x < width; ++x) {
+ if(x>curSection->X2) {
+ oldcolor=0xFF;
+ NextSection();
+ }
+ color = map[mapoffset + x];
+ if (color==oldcolor) dmap[mapoffset + x]=ColorIndex; else {
+ //try to map the color in the current region
+ if (AddColor(x,y,color, ColorIndex)) {
+ // store as the highlight region index
+ dmap[mapoffset + x]=ColorIndex;
+ } else {
+ CloseRegion(y-1);
+ if(NrOfRegions<=MAX_NO_OF_REGIONS-1) {
+ //retry with another region
+ OpenRegion(y);
+ x = -1;
+ oldcolor=0xFF;
+ } else
+ {
+ //give up
+ cLog::Instance() << "dxr3colormanager: too many regions!\n";
+ return;
+ }
+ }
+ }
+ }
+ mapoffset+=width;
+ }
+ //close the last highligt region
+ CloseRegion(height);
+
+ #ifdef timingdebug
+ t.Stop("EncodeColors");
+ #endif
+
+//#define colordebug
+#ifdef colordebug
+ {
+ FILE *fp;
+ fp = fopen("OSD.dump","w+");
+ u_char *pippo=dmap;
+ u_char *pippo2=map;
+ int curregion=0;
+ int cursection=0;
+
+
+ for (int dumpy=0; dumpy<height; dumpy++)
+ {
+ if(curregion<NrOfRegions) {
+ if(hlr[curregion]->Y1==dumpy) {
+ fprintf(fp,"%i",hlr[curregion]->N);
+ for(int sec=0; sec<hlr[curregion]->N; sec++) fprintf(fp,",%i",hlr[curregion]->Section[sec]->X1);
+ for(int dumpx=0; dumpx<width; dumpx++) fprintf(fp,"=");
+ fprintf(fp,"\n");
+ curregion++;
}
- dxr3_memcpy(dmap+y*width, buffer,width);
+ }
+
+ cursection=0;
+ for(int dumpx=0; dumpx<width; dumpx++) {
+ if(curregion<NrOfRegions) {
+ if(cursection<hlr[curregion]->N) {
+ if(hlr[curregion]->Section[cursection]->X1==dumpx) {
+ fprintf(fp,"|");
+ cursection++;
+ }
+ }
+ }
+ fprintf(fp,"%01X",*pippo2 & 0xF);
+ pippo2++;
+ }
+ fprintf(fp,"\n");
+
+
+ cursection=0;
+ for(int dumpx=0; dumpx<width; dumpx++) {
+ if(curregion<NrOfRegions) {
+ if(cursection<hlr[curregion]->N) {
+ if(hlr[curregion]->Section[cursection]->X1==dumpx) {
+ fprintf(fp,"|");
+ cursection++;
+ }
+ }
+ }
+ fprintf(fp,"%01X",*pippo & 0xF);
+ pippo++;
+ }
+ fprintf(fp,"\n");
+ }
+ fclose(fp);
+ printf("**** dumped\n");
}
+#endif
+
}
// ==================================
unsigned char cColorManager::AddColor(int x, int y, unsigned char color, unsigned char &ColorIndex) {
- static int yold = -1;
- xSection* Section;
- if (isopen)
- {
- // there is an opened highlight-region
- Section = GetSection(x);
-
- // checks whether we have a section defined on the formerly line on this x-position
- if (Section != NULL)
- {
- // there was a section
- if (!Section->HasColor(color, ColorIndex))
- {
- // this color is new for this section
- if (Section->AllColorsUsed())
- {
- // no more free colors
- if (yold != y)
- {
- CloseRegion(y-1);
- // terminate region
- return(0);
- }
- // create new section
- Section = NewSection(x);
- }
- // and add new color
- ColorIndex = Section->AddColor(color);
- }
- }
- else
- {
- // no section found (but region already open)
-
- // terminate region
- CloseRegion(y-1);
- yold = y;
- // open new region
- OpenRegion(y);
- // create new section
- Section = NewSection(x);
- // and add new color
- ColorIndex = Section->AddColor(color);
+ if (!curSection->HasColor(color, ColorIndex))
+ {
+ // this color is new for this section
+ if (curSection->AllColorsUsed())
+ {
+ // no more free colors
+ if (y != curRegion->Y1)
+ {
+ // terminate region
+ return(0);
}
- }
- else
- {
- // currently no region open
- yold = y;
-
- // open new region
- OpenRegion(y);
- // create new section
- Section = NewSection(x);
- // and add new color
- ColorIndex = Section->AddColor(color);
+ NewSection(x);
+ }
+ // and add new color
+ ColorIndex = curSection->AddColor(color);
}
return(1);
}
// ==================================
-xSection *cColorManager::GetSection(int x)
+void cColorManager::FirstSection(void)
{
- int i;
-
- // for every section in the current region
- for (i = 0; i < hlr[NrOfRegions]->N; i++)
- {
- if ((x <= hlr[NrOfRegions]->Section[i]->X2) && (x >= hlr[NrOfRegions]->Section[i]->X1)) // x-pos is in section
- {
- return (hlr[NrOfRegions]->Section[i]);
- }
- }
- return(NULL);
+ curSectionIndex=0;
+ curSection=curRegion->Section[0];
}
-/** Adds a new highlight region beginning from FIRST to LAST column */
-/**
-void cColorManager::AddRegion(int first, int last, unsigned int color, unsigned int opac)
+// ==================================
+void cColorManager::NextSection(void)
{
- DIAG("AddRegion(%d %d %x %x)\n",first, last, color, opac);
- hlr[NrOfRegions]->AddSection(first, last, color, opac);
+ curSectionIndex++;
+ if(curSectionIndex<curRegion->N) curSection=curRegion->Section[curSectionIndex];
+ //it shouldn't happen
+ else cLog::Instance() <<
+ "dxr3colormanager: no more sections in NextSection!\n";
}
-**/
// ==================================
// convert into SPU - hope is correct description
unsigned char* cColorManager::GetSpuData(int& len)
{
- if (isopen) // there is an opened highlight-region
- CloseRegion(MaxY);
-
- if (NrOfRegions != 0)
+ if (NrOfRegions >= 0)
{
int ptr = 0;
spudata[ptr++] = 0x07; // CHG_COLCON command
@@ -237,7 +289,7 @@ unsigned char* cColorManager::GetSpuData(int& len)
spudata[ptr++] = 0x00; // will be filled later
- for(int i = 0; i < NrOfRegions;i++)
+ for(int i = 0; i <= NrOfRegions;i++)
{
spudata[ptr++] = (hlr[i]->Y1 >> 8) & 0x0f;
spudata[ptr++] = (hlr[i]->Y1 & 0xff);
@@ -282,39 +334,25 @@ unsigned char* cColorManager::GetSpuData(int& len)
}
// ==================================
-xSection *cColorManager::NewSection(int x)
+void cColorManager::NewSection(int x)
{
- xSection* sec = new xSection(x);
- int N = hlr[NrOfRegions]->N;
- if (N >= MAX_NO_OF_SECTIONS - 1)
- cLog::Instance() << "Bummer, too many sections\n";
-
- hlr[NrOfRegions]->Section[hlr[NrOfRegions]->N] = sec;
- if (N > 0)
- hlr[NrOfRegions]->Section[hlr[NrOfRegions]->N - 1]->X2 = x-1;
- (hlr[NrOfRegions]->N)++;
-
- return(sec);
-}
-
-/**
-// No descriptions */
-/**
-void HLRegion::AddSection(int first, int last, unsigned int color, unsigned int opac)
-{
- DIAG(" AddSection %d,%d %X,%X\n",first, last, color, opac);
- Region[N] = new ColRegion(first, last, color, opac);
- assert(N<MAX_NO_OF_REGIONS -1);
- N++;
- DIAG("HL N:%d\n",N);
+ int N = curRegion->N;
+ if (N>=MAX_NO_OF_SECTIONS-1) {
+ cLog::Instance() << "dxr3colormanager: bummer, too many sections\n";
+ return; //reuse last section, not optimal but there's no other way out
+ }
+ curSection = new xSection(x);
+ curRegion->Section[N] = curSection;
+ if (N > 0) curRegion->Section[N-1]->X2 = x-1;
+ (curRegion->N)++;
+ curSectionIndex=N;
}
-**/
// ==================================
xSection::xSection(int x)
{
X1 = x;
- X2 = 0xFFF;
+ X2 = 32767;
NrOfColors = 0;
for (int i = 0; i < 4; i++)
{
@@ -351,9 +389,3 @@ bool xSection::HasColor(unsigned int color, unsigned char &ColorIndex)
}
return(false);
}
-
-/** No descriptions */
-void cColorManager::SetBgColor(unsigned int bgColor)
-{
-// cColorManager::BgColor = bgColor;
-}
diff --git a/dxr3colormanager.h b/dxr3colormanager.h
index 030be56..6048105 100644
--- a/dxr3colormanager.h
+++ b/dxr3colormanager.h
@@ -96,27 +96,22 @@ public:
/** encodes the color information as highlight spu data*/
unsigned char* GetSpuData(int &len);
- /** Adds a new highlight region beginning from FIRST to LAST column */
-// void AddRegion(int first, int last, unsigned int color, unsigned int opac=0xFFFF);
-
- /** No descriptions */
- void SetBgColor(unsigned int bgColor);
-
private: // Private attributes
yRegion *hlr[MAX_NO_OF_REGIONS];
+ yRegion *curRegion;
int NrOfRegions;
- bool isopen;
- unsigned char spudata[2*4096];
- unsigned int BgCol;
- int MaxY;
+ unsigned char spudata[(4+6*MAX_NO_OF_SECTIONS)*MAX_NO_OF_REGIONS+7];
+ xSection *curSection;
+ int curSectionIndex;
/** Opens a new highlight region */
void OpenRegion(int y);
/** Closes the spu-highlight region */
void CloseRegion(int y);
- xSection* NewSection(int x);
- xSection *GetSection(int x);
+ void NewSection(int x);
+ void FirstSection(void);
+ void NextSection(void);
};
#endif /*_DXR3COLORMANAGER_H_*/
diff --git a/dxr3interface_spu_encoder.c b/dxr3interface_spu_encoder.c
index 94a2dd9..a9a0907 100644
--- a/dxr3interface_spu_encoder.c
+++ b/dxr3interface_spu_encoder.c
@@ -360,30 +360,6 @@ int cSPUEncoder::Cmd(OSD_Command cmd, int color, int x0, int y0, int x1, int y1,
m_windows[m_lastwindow].y0 + y1,
(u_char *)data
);
-
- // calculate osd size
- CalculateActiveOsdArea();
-
- //cLog::Instance() << "(" << m_x0 << ", " << m_x1 << ") - (" << m_y0 << ", " << m_y1 << ")";
-
- m_encodeddata.count = 0;
- EncodePixelbufRle(0,0, OSDWIDTH, OSDHEIGHT-1, OSD_Screen, 0, &m_encodeddata);
-
- if (cDxr3ConfigData::Instance().GetDebug())
- {
- cLog::Instance() << "OSD Datasize: " << m_encodeddata.count << "\n";
- }
-
- if (m_encodeddata.count <= DATASIZE)
- {
- cDxr3Interface::Instance().WriteSpu((uint8_t*) &m_encodeddata, m_encodeddata.count);
- return 0;
- }
- else
- {
- cLog::Instance() << "Warning: SPU data (" << m_encodeddata.count << ") size exceeds limit\n";
- return -1;
- }
break;
case OSD_Close:
@@ -407,27 +383,13 @@ int cSPUEncoder::Cmd(OSD_Command cmd, int color, int x0, int y0, int x1, int y1,
}
}
- // encode rle
- m_encodeddata.count = 0;
- EncodePixelbufRle(0,0, OSDWIDTH, OSDHEIGHT-1, OSD_Screen, 0, &m_encodeddata);
-
+
// set windows position to 0
m_windows[m_lastwindow].x0 = 0;
m_windows[m_lastwindow].y0 = 0;
m_windows[m_lastwindow].x1 = 0;
m_windows[m_lastwindow].y1 = 0;
- if (m_encodeddata.count <= DATASIZE)
- {
- cDxr3Interface::Instance().WriteSpu((uint8_t*) &m_encodeddata, m_encodeddata.count);
- return 0;
- }
- else
- {
- cLog::Instance() << "Warning: SPU data (" << m_encodeddata.count << ") size exceeds limit\n";
- return -1;
- }
-
return 0;
break;
@@ -462,6 +424,35 @@ int cSPUEncoder::Cmd(OSD_Command cmd, int color, int x0, int y0, int x1, int y1,
return -1;
}
+
+//===================================
+//Flushes the OSD content into the spu
+int cSPUEncoder::Flush(void)
+{
+ // calculate osd size (actually dead code)
+ CalculateActiveOsdArea();
+
+ //cLog::Instance() << "(" << m_x0 << ", " << m_x1 << ") - (" << m_y0 << ", " << m_y1 << ")";
+
+ m_encodeddata.count = 0;
+ EncodePixelbufRle(0,0, OSDWIDTH, OSDHEIGHT-1, OSD_Screen, 0, &m_encodeddata);
+
+ if (cDxr3ConfigData::Instance().GetDebug())
+ {
+ cLog::Instance() << "OSD Datasize: " << m_encodeddata.count << "\n";
+ }
+
+ if (m_encodeddata.count <= DATASIZE)
+ {
+ cDxr3Interface::Instance().WriteSpu((uint8_t*) &m_encodeddata, m_encodeddata.count);
+ return 0;
+ } else
+ {
+ cLog::Instance() << "Warning: SPU data (" << m_encodeddata.count << ") size exceeds limit\n";
+ return -1;
+ }
+}
+
// ==================================
// stamps window content into full osd bitmap
void cSPUEncoder::CopyBlockIntoOSD(int linewidth, int x0, int y0, int x1, int y1, u_char *data)
@@ -762,6 +753,11 @@ void cSPUEncoder::encode_do_control(int x,int y, encodedata* ed, pixbuf* pb)
unsigned char *spudata;
spudata = m_ColorManager->GetSpuData(len);
+ //check that the highlight regions data wont overflow the buffer
+ if(i+len+2>DATASIZE) {
+ ed->count=DATASIZE+1;
+ return;
+ }
for (int si= 0; si < len; si++)
{
@@ -787,6 +783,36 @@ void cSPUEncoder::encode_do_control(int x,int y, encodedata* ed, pixbuf* pb)
}
// ==================================
+// Stop spu display
+void cSPUEncoder::StopSpu(void)
+{
+ uint8_t ed[10];
+ /* packet size */
+ ed[0]= 0;
+ ed[1]= 10;
+
+ /* pointer to the SP_DCSQT */
+ ed[2]= 0;
+ ed[3]= 4;
+
+ /* SP_DCSQT */
+ /* display duration... */
+ ed[4]= 0x00;
+ ed[5]= 0x00; //duration before turn on command occurs (will not be used)
+
+ /* pointer to next command block */
+ ed[6]= 0; //since this is the last command block, this
+ ed[7]= 4;//points back to itself
+
+ /* 0x02: stop displaying */
+ ed[8]= 0x02;
+
+ /* 0xFF: end sequence */
+ ed[9]= 0xFF;
+ cDxr3Interface::Instance().WriteSpu(ed, 10);
+}
+
+// ==================================
// we _only_ write usefull data
void cSPUEncoder::CalculateActiveOsdArea()
{
diff --git a/dxr3interface_spu_encoder.h b/dxr3interface_spu_encoder.h
index 5cebb4d..300dbe6 100644
--- a/dxr3interface_spu_encoder.h
+++ b/dxr3interface_spu_encoder.h
@@ -118,6 +118,8 @@ public:
~cSPUEncoder() {}
int Cmd(OSD_Command cmd, int color = 0, int x0 = 0, int y0 = 0, int x1 = 0, int y1 = 0, const void *data = 0);
+ int Flush(void);
+ void StopSpu(void);
private:
cSPUEncoder(cSPUEncoder&); // no copy constructor
diff --git a/dxr3osd_subpicture.c b/dxr3osd_subpicture.c
index bf5a776..ddd0e28 100644
--- a/dxr3osd_subpicture.c
+++ b/dxr3osd_subpicture.c
@@ -39,6 +39,7 @@ cDxr3SubpictureOsd::~cDxr3SubpictureOsd()
Spu->Cmd(OSD_Close);
}
}
+ Spu->StopSpu();
#if VDRVERSNUM >= 10318
delete last;
#endif
@@ -170,22 +171,13 @@ void cDxr3SubpictureOsd::Flush()
Spu->Cmd(OSD_SetPalette, 0, NumColors - 1, 0, 0, 0, Colors);
}
// commit modified data:
- //Spu->Cmd(OSD_SetBlock, Bitmap->Width(), x1, y1, x2, y2, Bitmap->Data(x1, y1));
Spu->Cmd(OSD_SetBlock, Bitmap->Width(), x1, y1, x2, y2, Bitmap->Data(x1, y1));
}
Bitmap->Clean();
}
- if (!shown)
- {
- // Showing the windows in a separate loop to avoid seeing them come up one after another
- for (int i = 0; (Bitmap = GetBitmap(i)) != NULL; i++)
- {
- Spu->Cmd(OSD_SetWindow, 0, i + 1);
- Spu->Cmd(OSD_MoveWindow, 0, Left() + Bitmap->X0(), Top() + Bitmap->Y0());
- }
- shown = true;
- }
+ Spu->Flush();
+ shown = true;
}
#endif /*VDRVERSNUM*/