39 #define DEBUG(format, args...) printf (format, ## args) 41 #define DEBUG(format, args...) 48 for (
int i = 0; i < 16; i++)
54 #define setMin(a, b) if (a > b) a = b 55 #define setMax(a, b) if (a < b) a = b 61 #define revRect(r1, r2) { r1.x1 = r2.x2; r1.y1 = r2.y2; r1.x2 = r2.x1; r1.y2 = r2.y1; } 64 uint8_t * fodd, uint8_t * eodd,
65 uint8_t * feven, uint8_t * eeven)
79 bmp =
new uint8_t[MemSize];
82 memset(bmp, 0, MemSize);
83 putFieldData(0, fodd, eodd);
84 putFieldData(1, feven, eeven);
110 for (
int i = 0; i < 4; i++) {
112 pal.
getColor(paldescr[i].index, paldescr[i].trans);
118 for (
int yp = 0; yp < h; yp++) {
119 for (
int xp = 0; xp < w; xp++) {
120 uint8_t idx = bmp[(size.
y1 + yp) *
spuXres + size.
x1 + xp];
133 for (
int i = 0; i < 4; i++) {
134 if (paldescr[i].trans != 0) {
147 DEBUG(
"MinSize: (%d, %d) x (%d, %d)\n",
148 size.
x1, size.
y1, size.
x2, size.
y2);
149 if (size.
x1 > size.
x2 || size.
y1 > size.
y2)
158 memset(bmp +
spuXres * yp + xp, colorid, len);
159 setMin(minsize[colorid].x1, xp);
160 setMin(minsize[colorid].y1, yp);
161 setMax(minsize[colorid].x2, xp + len - 1);
162 setMax(minsize[colorid].y2, yp);
165 static uint8_t
getBits(uint8_t * &data, uint8_t & bitf)
180 int yp = bmpsize.y1 + field;
183 while (data < endp) {
184 uint16_t vlc =
getBits(data, bitf);
186 vlc = (vlc << 4) |
getBits(data, bitf);
188 vlc = (vlc << 4) |
getBits(data, bitf);
190 vlc = (vlc << 4) |
getBits(data, bitf);
195 uint8_t color = vlc & 0x03;
199 len = len ? len : bmpsize.x2 - xp + 1;
200 putPixel(xp, yp, len, color);
203 if (xp > bmpsize.x2) {
218 #define CMD_SPU_MENU 0x00 219 #define CMD_SPU_SHOW 0x01 220 #define CMD_SPU_HIDE 0x02 221 #define CMD_SPU_SET_PALETTE 0x03 222 #define CMD_SPU_SET_ALPHA 0x04 223 #define CMD_SPU_SET_SIZE 0x05 224 #define CMD_SPU_SET_PXD_OFFSET 0x06 225 #define CMD_SPU_CHG_COLCON 0x07 226 #define CMD_SPU_EOF 0xff 228 #define spuU32(i) ((spu[i] << 8) + spu[i+1]) 233 scaleMode = eSpuNormal;
257 DEBUG(
"dvbspu SetSpuScaling OsdSize %d x %d\n", OsdWidth, OsdHeight);
260 xscaling = yscaling = 1.0;
262 xscaling = 1280.0 / Width;
263 yscaling = 720.0 / Height;
266 xscaling = 1920.0 / Width;
267 yscaling = 1080.0/ Height;
271 xscaling = (double)OsdWidth / Width;
272 yscaling = (double)OsdHeight / Height;
274 DEBUG(
"dvbspu xscaling = %f yscaling = %f\n", xscaling, yscaling);
281 DEBUG(
"SPU pushData: pts: %d\n", pts);
289 DCSQ_offset = cmdOffs();
290 prev_DCSQ_offset = 0;
293 allowedShow = AllowedShow;
298 scaleMode = ScaleMode;
307 uint16_t ex, uint16_t ey,
311 for (
int i = 0; i < 4; i++) {
312 pld[i].
index = 0xf & (palette >> (16 + 4 * i));
313 pld[i].trans = 0xf & (palette >> (4 * i));
316 bool ne = hlpsize.x1 != sx || hlpsize.y1 != sy ||
317 hlpsize.x2 != ex || hlpsize.y2 != ey ||
318 pld[0] != hlpDescr[0] || pld[1] != hlpDescr[1] ||
319 pld[2] != hlpDescr[2] || pld[3] != hlpDescr[3];
322 DEBUG(
"setHighlight: %d,%d x %d,%d\n", sx, sy, ex, ey);
347 if (fgbmp && bgbmp) {
377 for (
int i = 0; i < 4; i++) {
378 if (paldescr[i].trans != 0) {
382 return col > 2 ? 2 : 1;
391 fgbpp = spubmp->getMinBpp(hlpDescr);
394 bgbpp = spubmp->getMinBpp(palDescr);
419 tmp = spubmp->getBitmap(hlpDescr,
palette, hlpsize);
420 fg = tmp->
Scaled(xscaling, yscaling,
true);
421 drawsize.
x1 = hlpsize.x1 * xscaling;
422 drawsize.
y1 = hlpsize.y1 * yscaling;
427 if (spubmp->getMinSize(palDescr, bgsize)) {
428 tmp = spubmp->getBitmap(palDescr,
palette, bgsize);
429 bg = tmp->
Scaled(xscaling, yscaling,
true);
430 bgdrawsize.
x1 = bgsize.
x1 * xscaling;
431 bgdrawsize.
y1 = bgsize.
y1 * yscaling;
432 bgdrawsize.
x2 = bgdrawsize.
x1 + bg->
Width();
440 restricted_osd =
false;
443 sDvbSpuRect areaSize = CalcAreaSize(drawsize, fg, bgdrawsize, bg);
444 tArea Area = { areaSize.
x1, areaSize.
y1, areaSize.
x2, areaSize.
y2, 4 };
445 if (osd->CanHandleAreas(&Area, 1) !=
oeOk) {
446 DEBUG(
"dvbspu CanHandleAreas (%d,%d)x(%d,%d), 4 failed\n", areaSize.
x1, areaSize.
y1, areaSize.
x2, areaSize.
y2);
447 restricted_osd =
true;
450 osd->SetAreas(&Area, 1);
452 if (restricted_osd) {
454 bool setarea =
false;
457 spubmp->getMinSize(hlpDescr,hlsize);
463 if (hlsize.
x1 > hlsize.
x2 || hlsize.
y1 > hlsize.
y2)
464 hlsize.
x1 = hlsize.
x2 = hlsize.
y1 = hlsize.
y2 = 0;
466 drawsize.
x1=hlsize.
x1 * xscaling;
467 drawsize.
y1=hlsize.
y1 * yscaling;
468 drawsize.
x2=hlsize.
x2 * xscaling;
469 drawsize.
y2=hlsize.
y2 * yscaling;
471 sDvbSpuRect areaSize = CalcAreaSize(drawsize, fg, bgdrawsize, bg);
473 #define DIV(a, b) (a/b)?:1 474 for (
int d = 1; !setarea && d <= 2; d++) {
477 tArea Area = { areaSize.
x1, areaSize.
y1, areaSize.
x2, areaSize.
y2,
DIV(CalcAreaBpp(fg, bg), d) };
479 if ((Area.
Width() & 7) != 0)
480 Area.
x2 += 8 - (Area.
Width() & 7);
482 if (osd->CanHandleAreas(&Area, 1) ==
oeOk &&
483 osd->SetAreas(&Area, 1) ==
oeOk)
487 if (!setarea && fg && bg) {
488 tArea Area_Both [2] = {
489 { bgdrawsize.
x1, bgdrawsize.
y1, bgdrawsize.
x2, bgdrawsize.
y2,
DIV(CalcAreaBpp(0, bg), d) },
490 { drawsize.
x1, drawsize.
y1, drawsize.
x2, drawsize.
y2,
DIV(CalcAreaBpp(fg, 0), d) }
492 if (!Area_Both[0].Intersects(Area_Both[1])) {
494 if ((Area_Both[0].Width() & 7) != 0)
495 Area_Both[0].
x2 += 8 - (Area_Both[0].
Width() & 7);
496 if ((Area_Both[1].Width() & 7) != 0)
497 Area_Both[1].x2 += 8 - (Area_Both[1].Width() & 7);
498 if (osd->CanHandleAreas(Area_Both, 2) ==
oeOk &&
499 osd->SetAreas(Area_Both, 2) ==
oeOk)
505 DEBUG(
"dvbspu: reduced AreaSize (%d, %d) (%d, %d) Bpp %d\n", areaSize.
x1, areaSize.
y1, areaSize.
x2, areaSize.
y2, (fg && bg) ? 4 : 2);
507 dsyslog(
"dvbspu: reduced AreaSize (%d, %d) (%d, %d) Bpp %d failed", areaSize.
x1, areaSize.
y1, areaSize.
x2, areaSize.
y2, (fg && bg) ? 4 : 2);
513 osd->DrawBitmap(bgdrawsize.
x1, bgdrawsize.
y1, *bg);
515 osd->DrawBitmap(drawsize.
x1, drawsize.
y1, *fg);
555 while (DCSQ_offset != prev_DCSQ_offset) {
559 uint32_t exec_time = spupts +
spuU32(i) * 1024;
560 if ((pts != 0) && (exec_time > pts))
562 DEBUG(
"offs = %d, rel = %d, time = %d, pts = %d, diff = %d\n",
563 i,
spuU32(i) * 1024, exec_time, pts, exec_time - pts);
571 prev_DCSQ_offset = DCSQ_offset;
573 DEBUG(
"offs = %d, DCSQ = %d, prev_DCSQ = %d\n",
574 i, DCSQ_offset, prev_DCSQ_offset);
580 DEBUG(
"\tshow subpicture\n");
586 DEBUG(
"\thide subpicture\n");
592 palDescr[0].index = spu[i + 2] & 0xf;
593 palDescr[1].index = spu[i + 2] >> 4;
594 palDescr[2].index = spu[i + 1] & 0xf;
595 palDescr[3].index = spu[i + 1] >> 4;
600 palDescr[0].trans = spu[i + 2] & 0xf;
601 palDescr[1].trans = spu[i + 2] >> 4;
602 palDescr[2].trans = spu[i + 1] & 0xf;
603 palDescr[3].trans = spu[i + 1] >> 4;
608 size.x1 = (spu[i + 1] << 4) | (spu[i + 2] >> 4);
609 size.x2 = ((spu[i + 2] & 0x0f) << 8) | spu[i + 3];
611 size.y1 = (spu[i + 4] << 4) | (spu[i + 5] >> 4);
612 size.y2 = ((spu[i + 5] & 0x0f) << 8) | spu[i + 6];
614 DEBUG(
"\t(%d, %d) x (%d, %d)\n",
615 size.x1, size.y1, size.x2, size.y2);
622 DEBUG(
"\todd = %d even = %d\n", fodd, feven);
633 DEBUG(
"\tspu menu\n");
640 esyslog(
"invalid sequence in control header (%.2x)",
646 if (fodd != 0 && feven != 0) {
650 spu + feven, spu + cmdOffs());
655 if ((state == spSHOW && allowedShow) || state == spMENU)
uint32_t yuv2rgb(uint32_t yuv_color)
sDvbSpuRect CalcAreaSize(sDvbSpuRect fgsize, cBitmap *fgbmp, sDvbSpuRect bgsize, cBitmap *bgbmp)
#define CMD_SPU_CHG_COLCON
#define DEBUG(format, args...)
virtual void GetOsdSize(int &Width, int &Height, double &PixelAspect)
Returns the Width, Height and PixelAspect ratio the OSD should use to best fit the resolution of the ...
int getMinBpp(const aDvbSpuPalDescr paldescr)
void setHighlight(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint32_t palette)
#define CMD_SPU_SET_PXD_OFFSET
int CalcAreaBpp(cBitmap *fgbmp, cBitmap *bgbmp)
void setPalette(const uint32_t *pal)
struct sDvbSpuPalDescr aDvbSpuPalDescr[4]
#define CMD_SPU_SET_ALPHA
void putFieldData(int field, uint8_t *data, uint8_t *endp)
void clearHighlight(void)
bool getMinSize(const aDvbSpuPalDescr paldescr, sDvbSpuRect &size) const
cBitmap * Scaled(double FactorX, double FactorY, bool AntiAlias=false) const
Creates a copy of this bitmap, scaled by the given factors.
void SetColor(int Index, tColor Color)
Sets the palette entry at Index to Color.
#define CMD_SPU_SET_PALETTE
cDvbSpuBitmap(sDvbSpuRect size, uint8_t *fodd, uint8_t *eodd, uint8_t *feven, uint8_t *eeven)
void processSPU(uint32_t pts, uint8_t *buf, bool AllowedShow)
static uint8_t getBits(uint8_t *&data, uint8_t &bitf)
static cDevice * PrimaryDevice(void)
Returns the primary device.
void setScaleMode(cSpuDecoder::eScaleMode ScaleMode)
uint32_t getColor(uint8_t idx, uint8_t trans) const
void putPixel(int xp, int yp, int len, uint8_t colorid)
void setPalette(uint32_t *pal)
void SetIndex(int x, int y, tIndex Index)
Sets the index at the given coordinates to Index.
int setTime(uint32_t pts)
cBitmap * getBitmap(const aDvbSpuPalDescr paldescr, const cDvbSpuPalette &pal, sDvbSpuRect &size) const
static cOsd * NewOsd(int Left, int Top, uint Level=OSD_LEVEL_DEFAULT)
Returns a pointer to a newly created cOsd object, which will be located at the given coordinates...