diff options
author | scop <scop> | 2005-04-17 11:29:21 +0000 |
---|---|---|
committer | scop <scop> | 2005-04-17 11:29:21 +0000 |
commit | 9216c55e163f619a33770119339ae0651cd1e417 (patch) | |
tree | 64a7869a8001785d0bcdcf5523b088ac366d6602 | |
parent | b4cecb13ef4fa7389a96f721e57da2cf68cb65e4 (diff) | |
download | vdr-plugin-dxr3-9216c55e163f619a33770119339ae0651cd1e417.tar.gz vdr-plugin-dxr3-9216c55e163f619a33770119339ae0651cd1e417.tar.bz2 |
OSD color management rework from Luca Olivetti.
-rw-r--r-- | HISTORY | 2 | ||||
-rw-r--r-- | dxr3colormanager.c | 326 | ||||
-rw-r--r-- | dxr3colormanager.h | 19 | ||||
-rw-r--r-- | dxr3interface_spu_encoder.c | 104 | ||||
-rw-r--r-- | dxr3interface_spu_encoder.h | 2 | ||||
-rw-r--r-- | dxr3osd_subpicture.c | 14 |
6 files changed, 257 insertions, 210 deletions
@@ -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*/ |