diff options
Diffstat (limited to 'dxr3interface_spu_encoder.c')
-rw-r--r-- | dxr3interface_spu_encoder.c | 426 |
1 files changed, 23 insertions, 403 deletions
diff --git a/dxr3interface_spu_encoder.c b/dxr3interface_spu_encoder.c index 59b1a33..e47a2c1 100644 --- a/dxr3interface_spu_encoder.c +++ b/dxr3interface_spu_encoder.c @@ -28,12 +28,6 @@ #include "dxr3interface_spu_encoder.h" -/* -ToDo: - - cSPUEncoder::encode_do_row: FIXME: watch this space for EOL -*/ - - // ================================== // dec. cSpuData::~cSpuData() @@ -75,18 +69,13 @@ void cSpuData::WriteRle(int *higher_nibble, int length, int color) } - - // ================================== -cSPUEncoder::cSPUEncoder() +cSPUEncoder::cSPUEncoder() { - // clear osd - memset(OSD_Screen, 0x00 ,OSDWIDTH * OSDHEIGHT); - memset(OSD_Screen2, 0x00 ,OSDWIDTH * OSDHEIGHT); - memset(OSD_Screen3, 0x00 ,OSDWIDTH * OSDHEIGHT); + m_lastwindow = 0; - // set active area to 0 - //m_x0 = m_x1 = m_y0 = m_y1 = 0; + // clear osd + memset(m_OSD, 0x00 ,OSDWIDTH * OSDHEIGHT); } // ================================== @@ -94,15 +83,6 @@ cSPUEncoder::cSPUEncoder() // makes life nicer :) int cSPUEncoder::Cmd(OSD_Command cmd, int color, int x0, int y0, int x1, int y1, const void *data) { - u_char *cp; - unsigned char idx = 0; - int opacity = 0; -#if VDRVERSNUM >= 10307 - const tColor *col; -#else - eDvbColor *col; -#endif - switch (cmd) { case OSD_SetWindow: @@ -125,6 +105,9 @@ int cSPUEncoder::Cmd(OSD_Command cmd, int color, int x0, int y0, int x1, int y1, m_windows[m_lastwindow].x1 = x1; m_windows[m_lastwindow].y1 = y1; + // calculate new active osd area + CalculateActiveOsdArea(); + return 0; break; @@ -136,31 +119,6 @@ int cSPUEncoder::Cmd(OSD_Command cmd, int color, int x0, int y0, int x1, int y1, // data has 4 byte for each color: // R,G,B, and a opacity value: 0->transparent, 1..254->mix, 255->pixel - #if VDRVERSNUM >= 10307 - col = (tColor*)data; - #else - eDvbColor *col; - col = (eDvbColor*)data; - #endif - - m_windows[m_lastwindow].NumColors = x0; - - for (int x = color, i = 0; x <= x0; x++,i++) - { - m_palManager.AddColor((int)*col & 0xFFFFFF); - - idx = m_palManager.GetIndex((int)*col & 0xFFFFFF); - if (m_palManager.HasChanged()) - { - cDxr3Interface::Instance().SetPalette(m_palManager.GetPalette()); - } - - opacity = ((*col & 0xFF000000) >> 24) * 0xF / 0xFF; - m_windows[m_lastwindow].colors[i] = (opacity << 4) | idx; - m_windows[m_lastwindow].opacity[i] = opacity; - col++; - } - return 0; break; @@ -171,93 +129,20 @@ int cSPUEncoder::Cmd(OSD_Command cmd, int color, int x0, int y0, int x1, int y1, // inc<=0 uses blockwidth as linewidth // returns 0 on success, -1 on clipping all pixel - CopyBlockIntoOSD - ( - color, - m_windows[m_lastwindow].x0 + x0, - m_windows[m_lastwindow].y0 + y0, - m_windows[m_lastwindow].x0 + x1, - 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() << "Waring: SPU data (" << m_encodeddata.count << ") size exceeds limit\n"; - return -1; - } + return 0; break; case OSD_Close: // clear colors from plattemanager - #if VDRVERSNUM >= 10307 - if ((col = (tColor*)m_windows[m_lastwindow].colors) != NULL) - #else - if ((col = (eDvbColor*)m_windows[m_lastwindow].colors) != NULL) - #endif - { - for (int i = 0; i < m_windows[m_lastwindow].NumColors; ++i) - { - m_palManager.RemoveColor((int)(col[i]) & 0xFFFFFF); - } - } - - // clear osd - for (int i = m_windows[m_lastwindow].y0; i <= m_windows[m_lastwindow].y1; ++i) - { - cp = &OSD_Screen[i*OSDWIDTH + m_windows[m_lastwindow].x0]; - if ((cp+m_windows[m_lastwindow].x1-m_windows[m_lastwindow].x0+1) < &OSD_Screen[OSDWIDTH * OSDHEIGHT-1]) - { - for (int xx=0; xx <= (m_windows[m_lastwindow].x1-m_windows[m_lastwindow].x0); xx++) - { - *(cp+xx) = 0x00; - } - } - else - { - continue; - } - } - - // 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() << "Waring: SPU data (" << m_encodeddata.count << ") size exceeds limit\n"; - return -1; - } + // calculate new active osd area + CalculateActiveOsdArea(); return 0; break; @@ -316,8 +201,8 @@ void cSPUEncoder::CopyBlockIntoOSD(int linewidth, int x0, int y0, int x1, int y1 for (i = y0; i <= y1; ++i) { - cp = &OSD_Screen[i*OSDWIDTH + x0]; - if ((cp+x1-x0+1) < &OSD_Screen[OSDWIDTH * OSDHEIGHT-1]) + cp = &m_OSD[i*OSDWIDTH + x0]; + if ((cp+x1-x0+1) < &m_OSD[OSDWIDTH * OSDHEIGHT-1]) { for (int xx=0; xx <= (x1-x0); xx++) { @@ -333,288 +218,23 @@ void cSPUEncoder::CopyBlockIntoOSD(int linewidth, int x0, int y0, int x1, int y1 } // ================================== -// taken from mplayer (spuenc.c) -void cSPUEncoder::EncodePixelbufRle(int x, int y, int w, int h, u_char *inbuf, int stride, encodedata *ed) -{ - pixbuf pb; - int i, row; - pb.x = w; - pb.y = h; - - if (cDxr3Interface::Instance().GetHorizontalSize() < 700) - { - double fac = (double)OSDWIDTH / (double)OSDWIDTH2; - ScaleOSD(fac, inbuf,10); - inbuf = OSD_Screen2; - } - - m_ColorManager = new cColorManager(); - - // Encode colors into highlight regions - m_ColorManager->EncodeColors(w, h, inbuf, OSD_Screen3); - inbuf = OSD_Screen3; - - pb.pixels = inbuf; - ed->count= 4; - ed->nibblewaiting= 0; - - row= 0; - for (i= 0; i < pb.y; i++) - { - encode_do_row(ed, &pb, row); - row+= 2; - if (row > pb.y) - { - row= 1; - ed->oddstart= ed->count; - } - } - encode_do_control(x,y, ed, &pb); - - delete m_ColorManager; -} - -// ================================== -void cSPUEncoder::ScaleOSD(double fac, unsigned char* buf, unsigned char NumColors) -{ - int y,x,s,d; - unsigned char dline[2 * OSDWIDTH + 10]; - - memset(OSD_Screen2, 0x00 ,OSDWIDTH * OSDHEIGHT); - - for (y = 0; y < OSDHEIGHT; y++) - { - memset(dline,0,2*OSDWIDTH+10); - - for (s=0,d=0; s < OSDWIDTH; s++,d+=2) - { - // stretch line to double width to 1440 - dline[d] = buf[y*OSDWIDTH + s]; - } - - for (d=1; d < (2*OSDWIDTH); d+=2) - { - #if VDRVERSNUM <= 10307 - // 'interpolate' values - if ((dline[d-1] == BLACK) || (dline[d+1] == BLACK)) - { - dline[d] = BLACK; - } - else if ((dline[d-1] == WHITE) || (dline[d+1] == WHITE)) - { - dline[d] = WHITE; - } - else if ((dline[d-1] == CYAN) || (dline[d+1] == CYAN)) - { - dline[d] = CYAN; - } - else - { - dline[d] = dline[d+1]; - } - #else /*VDRVERSNUM*/ - dline[d] = dline[d+1]; - #endif /*VDRVERSNUM*/ - } - - for (s=0, x = 0; x < OSDWIDTH2; x++,s+=3) - { - // now take every third pixel (1440/3=480) - OSD_Screen2[y * OSDWIDTH + x] = dline[s]; - } - } -} - -// ================================== -// taken from mplayer (spuenc.c) -void cSPUEncoder::encode_put_nibble(encodedata* ed, u_char nibble) -{ - if (ed->nibblewaiting) - { - ed->data[ed->count++]|= nibble; - ed->nibblewaiting= 0; - } - else - { - ed->data[ed->count]= nibble<<4; - ed->nibblewaiting= 1; - } -} - -// ================================== -// taken from mplayer (spuenc.c) -void cSPUEncoder::encode_pixels(encodedata* ed, int color, int number) -{ - if (number > 3) - { - if (number > 15) - { - encode_put_nibble(ed, 0); - if (number > 63) - { - encode_put_nibble(ed, (number & 0xC0)>>6); - } - } - encode_put_nibble(ed, (number & 0x3C)>>2); - } - encode_put_nibble(ed, ((number & 0xF)<<2) | color); -} - -// ================================== -// taken from mplayer (spuenc.c) -void cSPUEncoder::encode_eol(encodedata* ed) -{ - if (ed->nibblewaiting) - { - ed->count++; - ed->nibblewaiting= 0; - } - ed->data[ed->count++]= 0x00; - ed->data[ed->count++]= 0x00; -} - -// ================================== -// taken from mplayer (spuenc.c) -void cSPUEncoder::encode_do_row(encodedata* ed, pixbuf* pb, int row) -{ - int i= 0; - u_char* pix= pb->pixels + row * pb->x; - int color= *pix & 0x03; - int n= 0; /* the number of pixels of this color */ - - while (i++ < pb->x) - { - /* FIXME: watch this space for EOL */ - if ((*pix & 0x03) != color || n == 255 ) - { - encode_pixels( ed, color, n ); - color= *pix & 0x03; - n= 1; - } - else - { - n++; - } - pix++; - } - - /* this small optimization: (n>63) can save up to two bytes per line - * I wonder if this is compatible with all the hardware... */ - if (color == 0 && n > 63) - { - encode_eol( ed ); - } - else - { - encode_pixels( ed, color, n ); - } - - if (ed->nibblewaiting) - { - ed->count++; - ed->nibblewaiting= 0; - } -} - -// ================================== -// taken from mplayer (spuenc.c) -void cSPUEncoder::encode_do_control(int x,int y, encodedata* ed, pixbuf* pb) -{ - int controlstart= ed->count; - int x1; - int i; - u_int top, left, bottom, right; - - top= y; //this forces the first bit to be visible on a TV - left= x; //you could actually pass in x/y and do some nice - - bottom= top + pb->y - 1; - right= left + pb->x - 1; - - /* start at x0+2*/ - i= controlstart; - - x1= (i); //marker for last command block address - - /* display duration... */ - ed->data[i++]= 0x00; - ed->data[i++]= 0x00; //duration before turn on command occurs (will not be used) - - /* x1 */ - ed->data[i++]= x1 >> 8; //since this is the last command block, this - ed->data[i++]= x1 & 0xff;//points back to itself - - /* 0x00: force displaying */ - ed->data[i++]= 0x00; - - /* 0x03: palette info */ - ed->data[i++]= 0x03; - ed->data[i++]= 0x01; - ed->data[i++]= 0x23; - - /* 0x04: transparency info (reversed) */ - ed->data[i++]= 0x04; // SET_CONTR - ed->data[i++]= 0xFF; - ed->data[i++]= 0x70; - - /* 0x05: coordinates */ - ed->data[i++]= 0x05; // SET_DAREA - ed->data[i++]= left >> 4; - ed->data[i++]= ((left&0xf)<<4)+(right>>8); - ed->data[i++]= (right&0xff); - ed->data[i++]= top >> 4; - ed->data[i++]= ((top&0xf)<<4)+(bottom>>8); - ed->data[i++]= (bottom&0xff); - - /* 0x06: both fields' offsets */ - ed->data[i++]= 0x06; // SET_DSPXA - ed->data[i++]= 0x00; - ed->data[i++]= 0x04; - ed->data[i++]= ed->oddstart >> 8; - ed->data[i++]= ed->oddstart & 0xff; - - int len; - unsigned char *spudata; - - spudata = m_ColorManager->GetSpuData(len); - - for (int si= 0; si < len; si++) - { - ed->data[i++] = *(spudata + si); - } - - /* 0xFF: end sequence */ - ed->data[i++]= 0xFF; - if (! i&1 ) - { - ed->data[i++]= 0xff; - } - - /* x0 */ - ed->data[2]= (controlstart) >> 8; - ed->data[3]= (controlstart) & 0xff; - - /* packet size */ - ed->data[0]= i >> 8; - ed->data[1]= i & 0xff; - - ed->count= i; -} - -// ================================== // we _only_ write usefull data void cSPUEncoder::CalculateActiveOsdArea() { // reset - //m_x0 = m_x1 = m_y0 = m_y1 = 0; + m_active_osd.Reset(); // calculate -/* for (int i = 1; i < 8; i++) + for (int i = 0; i < 8; i++) { - m_x0 = max(m_x0, m_windows[i].x0); - m_x1 = max(m_x1, m_windows[i].y0); - m_y0 = max(m_y0, m_windows[i].x1); - m_y1 = max(m_y1, m_windows[i].y1); + m_active_osd.x0 = max(m_active_osd.x0, m_windows[i].x0); + m_active_osd.x1 = max(m_active_osd.x1, m_windows[i].y0); + m_active_osd.y0 = max(m_active_osd.y0, m_windows[i].x1); + m_active_osd.y1 = max(m_active_osd.y1, m_windows[i].y1); } -*/ + + cLog::Instance() << "OSD x0: " << m_active_osd.x0 << "\n"; + cLog::Instance() << "OSD y0: " << m_active_osd.y0 << "\n"; + cLog::Instance() << "OSD x1: " << m_active_osd.x1 << "\n"; + cLog::Instance() << "OSD y1: " << m_active_osd.y1 << "\n"; } |