14 #define __STDC_FORMAT_MACROS // Required for format specifiers 19 #define PAGE_COMPOSITION_SEGMENT 0x10 20 #define REGION_COMPOSITION_SEGMENT 0x11 21 #define CLUT_DEFINITION_SEGMENT 0x12 22 #define OBJECT_DATA_SEGMENT 0x13 23 #define DISPLAY_DEFINITION_SEGMENT 0x14 24 #define DISPARITY_SIGNALING_SEGMENT 0x15 // DVB BlueBook A156 25 #define END_OF_DISPLAY_SET_SEGMENT 0x80 26 #define STUFFING_SEGMENT 0xFF 28 #define PGS_PALETTE_SEGMENT 0x14 29 #define PGS_OBJECT_SEGMENT 0x15 30 #define PGS_PRESENTATION_SEGMENT 0x16 31 #define PGS_WINDOW_SEGMENT 0x17 32 #define PGS_DISPLAY_SEGMENT 0x80 49 #define dbgdisplay(a...) if (DebugDisplay) SD.WriteHtml(a) 50 #define dbgpages(a...) if (DebugPages) SD.WriteHtml(a) 51 #define dbgregions(a...) if (DebugRegions) SD.WriteHtml(a) 52 #define dbgobjects(a...) if (DebugObjects) SD.WriteHtml(a) 53 #define dbgconverter(a...) if (DebugConverter) SD.WriteHtml(a) 54 #define dbgsegments(a...) if (DebugSegments) SD.WriteHtml(a) 55 #define dbgpixel(a...) if (DebugPixel) SD.WriteHtml(a) 56 #define dbgcluts(a...) if (DebugCluts) SD.WriteHtml(a) 57 #define dbgoutput(a...) if (DebugOutput) SD.WriteHtml(a) 59 #define DBGMAXBITMAPS 100 // debug output will be stopped after this many bitmaps 60 #define DBGBITMAPWIDTH 400 62 #define FIX_SUBTITLE_VERSION_BROADCASTER_STUPIDITY // some don't properly handle version numbers, which renders them useless because subtitles are not displayed 98 int w = MaxX ? int(round(MaxX *
factor)) : Scaled->
Width();
99 int h = MaxY ? int(round(MaxY * factor)) : Scaled->
Height();
100 uchar mem[w * h * 3];
101 for (
int x = 0; x < w; x++) {
102 for (
int y = 0; y < h; y++) {
104 int o = (y * w + x) * 3;
105 mem[o++] = (c & 0x00FF0000) >> 16;
106 mem[o++] = (c & 0x0000FF00) >> 8;
107 mem[o] = (c & 0x000000FF);
114 int f = open(ImgName, O_WRONLY | O_CREAT, DEFFILEMODE);
116 if (write(f, Jpeg, Size) < 0)
129 if (FILE *f = fopen(
"dbg-log.htm",
newFile ?
"w" :
"a")) {
131 va_start(ap, Format);
132 vfprintf(f, Format, ap);
150 tColor yuv2rgb(
int Y,
int Cb,
int Cr);
151 void SetColor(
int Bpp,
int Index,
tColor Color);
158 const cPalette *GetPalette(
int Bpp);
166 int a = 0, r = 0, g = 0, b = 0;
176 for (
int i = 1; i < 16; ++i) {
178 r = (i & 1) ? 255 : 0;
179 g = (i & 2) ? 255 : 0;
180 b = (i & 4) ? 255 : 0;
183 r = (i & 1) ? 127 : 0;
184 g = (i & 2) ? 127 : 0;
185 b = (i & 4) ? 127 : 0;
191 for (
int i = 1; i < 256; ++i) {
193 r = (i & 1) ? 255 : 0;
194 g = (i & 2) ? 255 : 0;
195 b = (i & 4) ? 255 : 0;
201 r = ((i & 1) ? 85 : 0) + ((i & 0x10) ? 170 : 0);
202 g = ((i & 2) ? 85 : 0) + ((i & 0x20) ? 170 : 0);
203 b = ((i & 4) ? 85 : 0) + ((i & 0x40) ? 170 : 0);
207 r = ((i & 1) ? 85 : 0) + ((i & 0x10) ? 170 : 0);
208 g = ((i & 2) ? 85 : 0) + ((i & 0x20) ? 170 : 0);
209 b = ((i & 4) ? 85 : 0) + ((i & 0x40) ? 170 : 0);
213 r = 127 + ((i & 1) ? 43 : 0) + ((i & 0x10) ? 85 : 0);
214 g = 127 + ((i & 2) ? 43 : 0) + ((i & 0x20) ? 85 : 0);
215 b = 127 + ((i & 4) ? 43 : 0) + ((i & 0x40) ? 85 : 0);
219 r = ((i & 1) ? 43 : 0) + ((i & 0x10) ? 85 : 0);
220 g = ((i & 2) ? 43 : 0) + ((i & 0x20) ? 85 : 0);
221 b = ((i & 4) ? 43 : 0) + ((i & 0x40) ? 85 : 0);
233 #ifndef FIX_SUBTITLE_VERSION_BROADCASTER_STUPIDITY 240 while (!bs.
IsEOF()) {
242 bool entryClut2Flag = bs.
GetBit();
243 bool entryClut4Flag = bs.
GetBit();
244 bool entryClut8Flag = bs.
GetBit();
264 value =
yuv2rgb(yval, cbval, crval);
267 dbgcluts(
"%2d %d %d %d %08X<br>\n", clutEntryId, entryClut2Flag ? 2 : 0, entryClut4Flag ? 4 : 0, entryClut8Flag ? 8 : 0, value);
284 for (
int i = 0; i < 256; ++i)
286 while (!bs.
IsEOF()) {
294 value =
yuv2rgb(yval, cbval, crval);
297 dbgcluts(
"%2d %08X<br>\n", clutEntryId, value);
311 Er =
constrain((298 * Ey + 460 * Epr) / 256, 0, 255);
312 Eg =
constrain((298 * Ey - 55 * Epb - 137 * Epr) / 256, 0, 255);
313 Eb =
constrain((298 * Ey + 543 * Epb ) / 256, 0, 255);
315 return (Er << 16) | (Eg << 8) | Eb;
324 default:
esyslog(
"ERROR: wrong Bpp in cSubtitleClut::SetColor(%d, %d, %08X)", Bpp, Index, Color);
334 default:
esyslog(
"ERROR: wrong Bpp in cSubtitleClut::GetPalette(%d)", Bpp);
355 bool Decode2BppCodeString(
cBitmap *Bitmap,
int px,
int py,
cBitStream *bs,
int&x,
int y,
const uint8_t *MapTable);
356 bool Decode4BppCodeString(
cBitmap *Bitmap,
int px,
int py,
cBitStream *bs,
int&x,
int y,
const uint8_t *MapTable);
357 bool Decode8BppCodeString(
cBitmap *Bitmap,
int px,
int py,
cBitStream *bs,
int&x,
int y);
358 bool DecodePgsCodeString(
cBitmap *Bitmap,
int px,
int py,
cBitStream *bs,
int&x,
int y);
359 void DecodeSubBlock(
cBitmap *Bitmap,
int px,
int py,
const uchar *Data,
int Length,
bool Even);
360 void DecodeCharacterString(
const uchar *Data,
int NumberOfCodes);
376 objectVersionNumber = -1;
377 objectCodingMethod = -1;
378 nonModifyingColorFlag =
false;
398 #ifndef FIX_SUBTITLE_VERSION_BROADCASTER_STUPIDITY 399 if (objectVersionNumber == Version)
402 objectVersionNumber = Version;
403 objectCodingMethod = bs.
GetBits(2);
404 nonModifyingColorFlag = bs.
GetBit();
406 dbgobjects(
"<b>object</b> id %d version %d method %d modify %d", objectId, objectVersionNumber, objectCodingMethod, nonModifyingColorFlag);
407 if (objectCodingMethod == 0) {
412 memcpy(topData, bs.
GetData(), topLength);
417 memcpy(botData, bs.
GetData() + topLength, botLength);
422 else if (objectCodingMethod == 1) {
423 int numberOfCodes = bs.
GetBits(8);
424 DecodeCharacterString(bs.
GetData(), numberOfCodes);
434 Render(&b, 0, 0, 0, 1);
436 if (b.
Dirty(x1, y1, x2, y2)) {
438 dbgobjects(
"<img src=\"%s\"><br>\n", *ImgName);
446 if (objectVersionNumber == Version)
448 objectVersionNumber = Version;
449 objectCodingMethod = 0;
450 int sequenceDescriptor = bs.
GetBits(8);
451 if (!(sequenceDescriptor & 0x80) && topData != NULL) {
456 topLength = bs.
GetBits(24) - 4 + 1;
458 if ((topData =
MALLOC(
uchar, topLength)) != NULL) {
459 topData[topIndex++] = 0xFF;
463 dbgobjects(
"<b>object</b> id %d version %d method %d modify %d", objectId, objectVersionNumber, objectCodingMethod, nonModifyingColorFlag);
477 if (NumberOfCodes > 0) {
478 char txt[NumberOfCodes + 1];
479 for (
int i = 0; i < NumberOfCodes; i++)
480 txt[i] = Data[i * 2 + 1];
481 txt[NumberOfCodes] = 0;
484 int len = NumberOfCodes;
486 dbgobjects(
" table %s single %d raw '%s'", CharacterTable, singleByte, from);
488 const char *s = conv.
Convert((
const char *)from);
498 int y = Even ? 0 : 1;
499 uint8_t map2to4[ 4] = { 0x00, 0x07, 0x08, 0x0F };
500 uint8_t map2to8[ 4] = { 0x00, 0x77, 0x88, 0xFF };
501 uint8_t map4to8[16] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF };
502 const uint8_t *mapTable = NULL;
504 while (!bs.
IsEOF()) {
507 dbgpixel(
"2-bit / pixel code string<br>\n");
508 switch (Bitmap->
Bpp()) {
509 case 8: mapTable = map2to8;
break;
510 case 4: mapTable = map2to4;
break;
511 default: mapTable = NULL;
break;
513 while (Decode2BppCodeString(Bitmap, px, py, &bs, x, y, mapTable) && !bs.
IsEOF())
518 dbgpixel(
"4-bit / pixel code string<br>\n");
519 switch (Bitmap->
Bpp()) {
520 case 8: mapTable = map4to8;
break;
521 default: mapTable = NULL;
break;
523 while (Decode4BppCodeString(Bitmap, px, py, &bs, x, y, mapTable) && !bs.
IsEOF())
528 dbgpixel(
"8-bit / pixel code string<br>\n");
529 while (Decode8BppCodeString(Bitmap, px, py, &bs, x, y) && !bs.
IsEOF())
533 dbgpixel(
"sub block 2 to 4 map<br>\n");
534 for (
int i = 0; i < 4; ++i)
538 dbgpixel(
"sub block 2 to 8 map<br>\n");
539 for (
int i = 0; i < 4; ++i)
543 dbgpixel(
"sub block 4 to 8 map<br>\n");
544 for (
int i = 0; i < 16; ++i)
548 dbgpixel(
"end of object line<br>\n");
553 dbgpixel(
"PGS code string, including EOLs<br>\n");
554 while (DecodePgsCodeString(Bitmap, px, py, &bs, x, y) && !bs.
IsEOF()) {
559 default:
dbgpixel(
"unknown sub block %s %d<br>\n", __FUNCTION__, __LINE__);
566 if (nonModifyingColorFlag && Index == 1)
568 for (
int pos = x; pos < x + Length; pos++)
606 color = MapTable[color];
607 DrawLine(Bitmap, px + x, py + y, color, rl);
621 else if (bs->
GetBit() == 0) {
628 else if (bs->
GetBit() == 0) {
651 color = MapTable[color];
652 DrawLine(Bitmap, px + x, py + y, color, rl);
677 DrawLine(Bitmap, px + x, py + y, color, rl);
684 while (!bs->
IsEOF()) {
691 rl = (rl << 8) + bs->
GetBits(8);
692 color = flags & 0x80 ? bs->
GetBits(8) : 0;
695 DrawLine(Bitmap, px + x, py + y, color, rl);
706 if (objectCodingMethod == 0) {
707 DecodeSubBlock(Bitmap, px, py, topData, topLength,
true);
709 DecodeSubBlock(Bitmap, px, py, botData, botLength,
false);
711 DecodeSubBlock(Bitmap, px, py, topData, topLength,
false);
713 else if (objectCodingMethod == 1) {
718 double factor = (double)lineHeight / font->
Height();
719 tmp.DrawText(0, 0, txtData, Bitmap->
Color(IndexFg), Bitmap->
Color(IndexBg), font);
738 if (so->ObjectId() == ObjectId)
775 objectProviderFlag = 0;
776 objectHorizontalPosition = 0;
777 objectVerticalPosition = 0;
778 foregroundPixelCode = 0;
779 backgroundPixelCode = 0;
786 objectProviderFlag = bs.
GetBits(2);
787 objectHorizontalPosition = bs.
GetBits(12);
789 objectVerticalPosition = bs.
GetBits(12);
790 if (objectType == 0x01 || objectType == 0x02) {
791 foregroundPixelCode = bs.
GetBits(8);
792 backgroundPixelCode = bs.
GetBits(8);
795 foregroundPixelCode = 0;
796 backgroundPixelCode = 0;
798 dbgregions(
"<b>objectref</b> id %d type %d flag %d x %d y %d fg %d bg %d<br>\n", objectId, objectType, objectProviderFlag, objectHorizontalPosition, objectVerticalPosition, foregroundPixelCode, backgroundPixelCode);
853 void SetDimensions(
int Width,
int Height);
868 regionVersionNumber = -1;
869 regionFillFlag =
false;
872 regionLevelOfCompatibility = 0;
875 region8bitPixelCode = 0;
876 region4bitPixelCode = 0;
877 region2bitPixelCode = 0;
883 #ifndef FIX_SUBTITLE_VERSION_BROADCASTER_STUPIDITY 884 if (regionVersionNumber == Version)
887 regionVersionNumber = Version;
888 regionFillFlag = bs.
GetBit();
892 regionLevelOfCompatibility = 1 << bs.
GetBits(3);
893 regionDepth = 1 << bs.
GetBits(3);
896 region8bitPixelCode = bs.
GetBits(8);
897 region4bitPixelCode = bs.
GetBits(4);
898 region2bitPixelCode = bs.
GetBits(2);
900 dbgregions(
"<b>region</b> id %d version %d fill %d width %d height %d level %d depth %d clutId %d<br>\n", regionId, regionVersionNumber, regionFillFlag, regionWidth, regionHeight, regionLevelOfCompatibility, regionDepth, clutId);
911 dbgregions(
"<b>region</b> id %d version %d clutId %d<br>\n", regionId, regionVersionNumber, clutId);
920 regionHeight = Height;
921 dbgregions(
"<b>region</b> id %d width %d height %d<br>\n", regionId, regionWidth, regionHeight);
926 if (regionFillFlag) {
927 switch (Bitmap->
Bpp()) {
928 case 2: Bitmap->
Fill(region2bitPixelCode);
break;
929 case 4: Bitmap->
Fill(region4bitPixelCode);
break;
930 case 8: Bitmap->
Fill(region8bitPixelCode);
break;
931 default:
dbgregions(
"unknown bpp %d (%s %d)<br>\n", Bitmap->
Bpp(), __FUNCTION__, __LINE__);
936 so->Render(Bitmap, sor->ObjectHorizontalPosition(), sor->ObjectVerticalPosition(), sor->ForegroundPixelCode(), sor->BackgroundPixelCode());
959 regionHorizontalAddress = x;
960 regionVerticalAddress = y;
961 dbgpages(
"<b>regionref</b> id %d tx %d y %d<br>\n", regionId, regionHorizontalAddress, regionVerticalAddress);
967 regionHorizontalAddress = bs.
GetBits(16);
968 regionVerticalAddress = bs.
GetBits(16);
969 dbgpages(
"<b>regionref</b> id %d tx %d y %d<br>\n", regionId, regionHorizontalAddress, regionVerticalAddress);
994 int64_t
Pts(
void)
const {
return pts; }
997 tArea *GetAreas(
int &NumAreas,
double FactorX,
double FactorY);
1010 pageVersionNumber = -1;
1022 #ifndef FIX_SUBTITLE_VERSION_BROADCASTER_STUPIDITY 1023 if (pageVersionNumber == Version)
1026 pageVersionNumber = Version;
1028 switch (pageState) {
1042 default:
dbgpages(
"unknown page state: %d<br>\n", pageState);
1045 dbgpages(
"<hr>\n<b>page</b> id %d version %d pts %" PRId64
" timeout %d state %d<br>\n", pageId, pageVersionNumber, pts, pageTimeout, pageState);
1056 pageTimeout = 60000;
1058 if (pageVersionNumber == Version)
1060 pageVersionNumber = Version;
1062 switch (pageState) {
1073 default:
dbgpages(
"unknown page state: %d<br>\n", pageState);
1076 dbgpages(
"<hr>\n<b>page</b> id %d version %d pts %" PRId64
" timeout %d state %d<br>\n", pageId, pageVersionNumber, pts, pageTimeout, pageState);
1083 if (regions.Count() > 0) {
1084 NumAreas = regionRefs.Count();
1089 a->
x1 = int(round(FactorX * srr->RegionHorizontalAddress()));
1090 a->
y1 = int(round(FactorY * srr->RegionVerticalAddress()));
1091 a->
x2 = int(round(FactorX * (srr->RegionHorizontalAddress() + sr->RegionWidth() - 1)));
1092 a->
y2 = int(round(FactorY * (srr->RegionVerticalAddress() + sr->RegionHeight() - 1)));
1093 a->
bpp = sr->RegionDepth();
1094 while ((a->
Width() & 3) != 0)
1110 if (sc->ClutId() == ClutId)
1123 if (sr->RegionId() == RegionId)
1129 regions.Add(Region);
1135 return objects.GetObjectById(ObjectId, New);
1146 bool Realloc(
int Size);
1151 unsigned char *Get(
int &Length);
1152 void Put(
const uchar *Data,
int Length);
1176 Size =
max(Size, 2048);
1177 if (
uchar *NewBuffer = (
uchar *)realloc(data, Size)) {
1182 esyslog(
"ERROR: can't allocate memory for subtitle assembler");
1195 if (length > pos + 5) {
1196 Length = (data[pos + 4] << 8) + data[pos + 5] + 6;
1197 if (length >= pos + Length) {
1198 unsigned char *result = data + pos;
1208 if (Length && Realloc(length + Length)) {
1209 memcpy(data + length, Data, Length);
1227 cDvbSubtitleBitmaps(
int State, int64_t Pts,
int Timeout,
tArea *Areas,
int NumAreas,
double OsdFactorX,
double OsdFactorY);
1230 int64_t
Pts(
void) {
return pts; }
1232 void AddBitmap(
cBitmap *Bitmap);
1234 void Draw(
cOsd *Osd);
1235 void DbgDump(
int WindowWidth,
int WindowHeight);
1244 numAreas = NumAreas;
1245 osdFactorX = OsdFactorX;
1246 osdFactorY = OsdFactorY;
1252 for (
int i = 0; i < bitmaps.Size(); i++)
1258 bitmaps.Append(Bitmap);
1264 bool AntiAlias =
true;
1265 if (Scale && osdFactorX > 1.0 || osdFactorY > 1.0) {
1268 for (
int i = 0; i < numAreas; i++) {
1269 Bpp[i] = areas[i].bpp;
1273 for (
int i = 0; i < numAreas; i++)
1274 areas[i].bpp = Bpp[i];
1278 if (State() == 0 || Osd->
SetAreas(areas, numAreas) ==
oeOk) {
1279 for (
int i = 0; i < bitmaps.Size(); i++) {
1281 Osd->
DrawScaledBitmap(
int(round(b->
X0() * osdFactorX)), int(round(b->
Y0() * osdFactorY)), *b, osdFactorX, osdFactorY, AntiAlias);
1293 double Start = double(Pts() - SD.
FirstPts()) / 90000;
1294 double Duration = Timeout();
1295 double End = Start + Duration;
1296 cBitmap Bitmap(WindowWidth, WindowHeight, 8);
1297 #define DBGBACKGROUND 0xA0A0A0 1299 for (
int i = 0; i < bitmaps.Size(); i++) {
1304 #define BORDER //" border=1" 1305 SD.
WriteHtml(
"<p>%s<br>", State() == 0 ?
"page update" : State() == 1 ?
"page refresh" : State() == 2 ?
"new page" :
"???");
1309 SD.
WriteHtml(
"<img src=\"%s\">", *ImgName);
1310 SD.
WriteHtml(
"</td><td style=\"height:100%%\"><table" BORDER " style=\"height:100%%\">");
1311 SD.
WriteHtml(
"<tr><td valign=top><b>%.2f</b></td></tr>", Start);
1312 SD.
WriteHtml(
"<tr><td valign=middle>%.2f</td></tr>", Duration);
1313 SD.
WriteHtml(
"<tr><td valign=bottom>%.2f</td></tr>", End);
1323 :
cThread(
"subtitle converter")
1355 dbgconverter(
"converter reset -----------------------<br>\n");
1372 if (Data && Length > 8) {
1374 int SubstreamHeaderLength = 4;
1375 bool ResetSubtitleAssembler = Data[PayloadOffset + 3] == 0x00;
1378 if ((Data[7] & 0x01) && (Data[PayloadOffset - 3] & 0x81) == 0x01 && Data[PayloadOffset - 2] == 0x81) {
1380 SubstreamHeaderLength = 1;
1381 ResetSubtitleAssembler = Data[8] >= 5;
1384 if (Length > PayloadOffset + SubstreamHeaderLength) {
1388 const uchar *data = Data + PayloadOffset + SubstreamHeaderLength;
1389 int length = Length - PayloadOffset - SubstreamHeaderLength;
1390 if (ResetSubtitleAssembler)
1394 if (data[0] == 0x20 && data[1] == 0x00 && data[2] == 0x0F)
1402 if (b && b[0] == 0x0F) {
1418 if (Data && Length > 8) {
1420 if (Length > PayloadOffset) {
1424 const uchar *data = Data + PayloadOffset;
1425 int length = Length - PayloadOffset;
1427 if (length > 2 && data[0] == 0x20 && data[1] == 0x00 && data[2] == 0x0F) {
1431 const uchar *b = data;
1432 while (length > 0) {
1452 #define LimitTo32Bit(n) ((n) & 0x00000000FFFFFFFFL) 1464 if (Timeout.
TimedOut() || LastSetupLevel != NewSetupLevel) {
1468 LastSetupLevel = NewSetupLevel;
1476 if (Delta > (int64_t(1) << 31))
1477 Delta -= (int64_t(1) << 32);
1478 else if (Delta < -((int64_t(1) << 31) - 1))
1479 Delta += (int64_t(1) << 32);
1482 if (Delta < sb->Timeout() * 1000) {
1483 if (!sb->HasBitmaps()) {
1490 Timeout.
Set(sb->Timeout() * 1000);
1491 dbgconverter(
"PTS: %" PRId64
" STC: %" PRId64
" (%" PRId64
") timeout: %d<br>\n", sb->Pts(), STC, Delta, sb->Timeout());
1508 int OsdWidth, OsdHeight;
1510 int VideoWidth, VideoHeight;
1539 if (sp->PageId() == PageId)
1552 if (Length > 5 && bs.
GetBits(8) == 0x0F) {
1553 int segmentType = bs.
GetBits(8);
1558 int segmentLength = bs.
GetBits(16);
1561 switch (segmentType) {
1564 dbgsegments(
"END_OF_DISPLAY_SET_SEGMENT (simulated)<br>\n");
1568 page->
Parse(Pts, bs);
1593 #ifndef FIX_SUBTITLE_VERSION_BROADCASTER_STUPIDITY 1597 bool displayWindowFlag = bs.
GetBit();
1603 if (displayWindowFlag) {
1617 bool disparity_shift_update_sequence_page_flag = bs.
GetBit();
1620 if (disparity_shift_update_sequence_page_flag) {
1623 int division_period_count = bs.
GetBits(8);
1624 for (
int i = 0; i < division_period_count; ++i) {
1629 while (!bs.
IsEOF()) {
1631 bool disparity_shift_update_sequence_region_flag = bs.
GetBit();
1633 int number_of_subregions_minus_1 = bs.
GetBits(2);
1634 for (
int i = 0; i <= number_of_subregions_minus_1; ++i) {
1635 if (number_of_subregions_minus_1 > 0) {
1642 if (disparity_shift_update_sequence_region_flag) {
1645 int division_period_count = bs.
GetBits(8);
1646 for (
int i = 0; i < division_period_count; ++i) {
1662 dbgsegments(
"*** unknown segment type: %02X<br>\n", segmentType);
1673 int segmentType = bs.
GetBits(8);
1674 int segmentLength = bs.
GetBits(16);
1679 switch (segmentType) {
1682 dbgsegments(
"PGS_DISPLAY_SEGMENT (simulated)<br>\n");
1697 int regionHorizontalAddress = bs.
GetBits(16);
1698 int regionVerticalAddress = bs.
GetBits(16);
1699 int regionWidth = bs.
GetBits(16);
1700 int regionHeight = bs.
GetBits(16);
1726 dbgsegments(
"*** unknown segment type: %02X<br>\n", segmentType);
1741 bool Reduced =
false;
1744 int HalfBpp = Bpp / 2;
1746 for (
int i = 0; i < NumAreas; i++) {
1747 if (Areas[i].bpp >= Bpp) {
1748 Areas[i].
bpp = HalfBpp;
1759 for (
int i = 0; i < NumAreas; i++) {
1763 cBitmap *bm =
new cBitmap(sr->RegionWidth(), sr->RegionHeight(), sr->RegionDepth());
1764 bm->
Replace(*clut->GetPalette(sr->RegionDepth()));
1765 sr->Render(bm, Page->
Objects());
1767 if (sr->RegionDepth() != Areas[i].
bpp) {
1768 if (sr->RegionLevelOfCompatibility() <= Areas[i].
bpp) {
1771 dbgregions(
"reduce region %d bpp %d level %d area bpp %d<br>\n", sr->RegionId(), sr->RegionDepth(), sr->RegionLevelOfCompatibility(), Areas[i].
bpp);
1775 dbgregions(
"condense region %d bpp %d level %d area bpp %d<br>\n", sr->RegionId(), sr->RegionDepth(), sr->RegionLevelOfCompatibility(), Areas[i].
bpp);
1780 bm->
SetOffset(srr->RegionHorizontalAddress(), srr->RegionVerticalAddress());
void SetFirstPts(int64_t FirstPts)
cVector< cBitmap * > bitmaps
void ReduceBpp(const cPalette &Palette)
Reduces the color depth of the bitmap to that of the given Palette.
int ObjectCodingMethod(void)
int RegionLevelOfCompatibility(void)
int ForegroundPixelCode(void)
cList< cDvbSubtitlePage > * pages
void ParsePgs(cBitStream &bs)
bool NonModifyingColorFlag(void)
void Parse(int64_t Pts, cBitStream &bs)
void Fill(tIndex Index)
Fills the bitmap data with the given Index.
void DrawBitmap(int x, int y, const cBitmap &Bitmap, tColor ColorFg=0, tColor ColorBg=0, bool ReplacePalette=false, bool Overlay=false)
Sets the pixels in this bitmap with the data from the given Bitmap, putting the upper left corner of ...
static bool DebugConverter
int ObjectProviderFlag(void)
cSubtitleRegionRef(int id, int x, int y)
void SetFactor(double Factor)
int PesPayloadOffset(const uchar *p)
void Clean(void)
Marks the dirty area as clean.
#define dbgconverter(a...)
int objectHorizontalPosition
void Parse(cBitStream &bs)
void Add(cListObject *Object, cListObject *After=NULL)
int Convert(const uchar *Data, int Length)
virtual eOsdError SetAreas(const tArea *Areas, int NumAreas)
Sets the sub-areas to the given areas.
int PageVersionNumber(void)
void SetOffset(int X0, int Y0)
Sets the offset of this bitmap to the given values.
#define CLUT_DEFINITION_SEGMENT
virtual void DrawScaledBitmap(int x, int y, const cBitmap &Bitmap, double FactorX, double FactorY, bool AntiAlias=false)
Sets the pixels in the OSD with the data from the given Bitmap, putting the upper left corner of the ...
#define DISPARITY_SIGNALING_SEGMENT
virtual void GetVideoSize(int &Width, int &Height, double &VideoAspect)
Returns the Width, Height and VideoAspect ratio of the currently displayed video material.
const uint8_t * GetData(void) const
const char * getCharacterTable(const unsigned char *&buffer, int &length, bool *isSingleByte)
static const char * SystemCharacterTable(void)
int64_t PesGetPts(const uchar *p)
static cString sprintf(const char *fmt,...) __attribute__((format(printf
cDvbSubtitleConverter(void)
void Action(void)
A derived cThread class must implement the code it wants to execute as a separate thread in this func...
void Parse(cBitStream &bs)
#define REGION_COMPOSITION_SEGMENT
void DbgDump(int WindowWidth, int WindowHeight)
static void SetupChanged(void)
#define OBJECT_DATA_SEGMENT
cDvbSubtitleAssembler * dvbSubtitleAssembler
tColor yuv2rgb(int Y, int Cb, int Cr)
bool Decode8BppCodeString(cBitmap *Bitmap, int px, int py, cBitStream *bs, int &x, int y)
void DrawLine(cBitmap *Bitmap, int x, int y, tIndex Index, int Length)
bool PesHasPts(const uchar *p)
int windowHorizontalOffset
int objectVerticalPosition
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 ...
static bool DebugSegments
bool Decode4BppCodeString(cBitmap *Bitmap, int px, int py, cBitStream *bs, int &x, int y, const uint8_t *MapTable)
cSubtitleClut * GetClutById(int ClutId, bool New=false)
void Render(cBitmap *Bitmap, cSubtitleObjects *Objects)
cSubtitleObject * GetObjectById(int ObjectId, bool New=false)
tArea * GetAreas(int &NumAreas, double FactorX, double FactorY)
cSubtitleClut(int ClutId)
const char * Convert(const char *From, char *To=NULL, size_t ToLength=0)
Converts the given Text from FromCode to ToCode (as set in the constructor).
void SetDimensions(int Width, int Height)
unsigned char * Get(int &Length)
bool Decode2BppCodeString(cBitmap *Bitmap, int px, int py, cBitStream *bs, int &x, int y, const uint8_t *MapTable)
int ClutVersionNumber(void)
cList< cSubtitleRegion > regions
void DecodeCharacterString(const uchar *Data, int NumberOfCodes)
virtual void Flush(void)
Actually commits all data to the OSD hardware.
cSubtitleRegion * GetRegionById(int RegionId, bool New=false)
cList< cSubtitleClut > cluts
void ParsePgs(cBitStream &bs)
bool RegionFillFlag(void)
void Render(cBitmap *Bitmap, int px, int py, tIndex IndexFg, tIndex IndexBg)
bool DecodePgsCodeString(cBitmap *Bitmap, int px, int py, cBitStream *bs, int &x, int y)
void Replace(const cPalette &Palette)
Replaces the colors of this palette with the colors from the given palette.
T * Next(const T *object) const
cDvbSubtitleAssembler(void)
bool Dirty(int &x1, int &y1, int &x2, int &y2)
Tells whether there is a dirty area and returns the bounding rectangle of that area (relative to the ...
#define PAGE_COMPOSITION_SEGMENT
void ParsePgs(int64_t Pts, cBitStream &bs)
int SubtitleFgTransparency
cString WriteJpeg(const cBitmap *Bitmap, int MaxX=0, int MaxY=0)
virtual ~cDvbSubtitleConverter()
#define PGS_OBJECT_SEGMENT
cListObject * Next(void) const
virtual eOsdError CanHandleAreas(const tArea *Areas, int NumAreas)
Checks whether the OSD can display the given set of sub-areas.
char FontOsd[MAXFONTNAME]
bool TimedOut(void) const
void AddRegionRef(cSubtitleRegionRef *rf)
static void SleepMs(int TimeoutMs)
Creates a cCondWait object and uses it to sleep for TimeoutMs milliseconds, immediately giving up the...
int ObjectVerticalPosition(void)
int ObjectVersionNumber(void)
void DrawRectangle(int x1, int y1, int x2, int y2, tColor Color)
Draws a filled rectangle defined by the upper left (x1, y1) and lower right (x2, y2) corners with the...
void bool Start(void)
Sets the description of this thread, which will be used when logging starting or stopping of the thre...
The cOsd class is the interface to the "On Screen Display".
cSubtitleObject(int ObjectId)
static cFont * CreateFont(const char *Name, int CharHeight, int CharWidth=0)
Creates a new font object with the given Name and makes its characters CharHeight pixels high...
bool Running(void)
Returns false if a derived cThread object shall leave its Action() function.
void AddBitmap(cBitmap *Bitmap)
cDvbSubtitlePage * GetPageById(int PageId, bool New=false)
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.
cDvbSubtitleBitmaps(int State, int64_t Pts, int Timeout, tArea *Areas, int NumAreas, double OsdFactorX, double OsdFactorY)
#define PGS_WINDOW_SEGMENT
void ShrinkBpp(int NewBpp)
Shrinks the color depth of the bitmap to NewBpp by keeping only the 2^NewBpp most frequently used col...
#define PGS_PALETTE_SEGMENT
tColor ArgbToColor(uint8_t A, uint8_t R, uint8_t G, uint8_t B)
cList< cSubtitleRegionRef > regionRefs
int ObjectHorizontalPosition(void)
#define OSD_LEVEL_SUBTITLES
cSubtitleObject * GetObjectById(int ObjectId, bool New=false)
int BackgroundPixelCode(void)
void WriteHtml(const char *Format,...)
void Del(cListObject *Object, bool DeleteObject=true)
void SetColor(int Bpp, int Index, tColor Color)
void FinishPage(cDvbSubtitlePage *Page)
static cDevice * PrimaryDevice(void)
Returns the primary device.
virtual int Width(uint c) const =0
Returns the width of the given character in pixel.
cDvbSubtitlePage(int PageId)
int ExtractPgsSegment(const uchar *Data, int Length, int64_t Pts)
int regionVerticalAddress
int regionHorizontalAddress
cList< cSubtitleObjectRef > objectRefs
int regionLevelOfCompatibility
#define DISPLAY_DEFINITION_SEGMENT
void SetPending(bool Pending)
virtual int64_t GetSTC(void)
Gets the current System Time Counter, which can be used to synchronize audio, video and subtitles...
int ExtractSegment(const uchar *Data, int Length, int64_t Pts)
#define PGS_DISPLAY_SEGMENT
virtual ~cDvbSubtitleAssembler()
int RegionVerticalAddress(void)
#define PGS_PRESENTATION_SEGMENT
cList< cDvbSubtitleBitmaps > * bitmaps
tColor Color(int Index) const
Returns the color at the given Index.
tColor GetColor(int x, int y) const
Returns the color at the given coordinates.
#define END_OF_DISPLAY_SET_SEGMENT
bool SetLength(int Length)
void Parse(cBitStream &bs)
virtual int Height(void) const =0
Returns the height of this font in pixel (all characters have the same height).
void DecodeSubBlock(cBitmap *Bitmap, int px, int py, const uchar *Data, int Length, bool Even)
#define dbgsegments(a...)
const cPalette * GetPalette(int Bpp)
void Put(const uchar *Data, int Length)
void Cancel(int WaitSeconds=0)
Cancels the thread by first setting 'running' to false, so that the Action() loop can finish in an or...
void ParsePgs(cBitStream &bs)
cSubtitleObjectRefPgs(cBitStream &bs)
cSubtitleObjects * Objects(void)
void SetIndex(int x, int y, tIndex Index)
Sets the index at the given coordinates to Index.
int ConvertFragments(const uchar *Data, int Length)
int SubtitleBgTransparency
int RegionVersionNumber(void)
int RegionHorizontalAddress(void)
cSubtitleRegionRef * GetRegionRefByIndex(int RegionRefIndex)
bool nonModifyingColorFlag
cSubtitleRegion(int RegionId)
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...