summaryrefslogtreecommitdiff
path: root/dxr3interface_spu_encoder.c
diff options
context:
space:
mode:
Diffstat (limited to 'dxr3interface_spu_encoder.c')
-rw-r--r--dxr3interface_spu_encoder.c426
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";
}