14 #define __STDC_FORMAT_MACROS // Required for format specifiers
21 #define PAGE_COMPOSITION_SEGMENT 0x10
22 #define REGION_COMPOSITION_SEGMENT 0x11
23 #define CLUT_DEFINITION_SEGMENT 0x12
24 #define OBJECT_DATA_SEGMENT 0x13
25 #define DISPLAY_DEFINITION_SEGMENT 0x14
26 #define DISPARITY_SIGNALING_SEGMENT 0x15 // DVB BlueBook A156
27 #define END_OF_DISPLAY_SET_SEGMENT 0x80
28 #define STUFFING_SEGMENT 0xFF
38 #define dbgconverter(a...) if (DebugConverter) fprintf(stderr, a)
39 #define dbgsegments(a...) if (DebugSegments) fprintf(stderr, a)
40 #define dbgpages(a...) if (DebugPages) fprintf(stderr, a)
41 #define dbgregions(a...) if (DebugRegions) fprintf(stderr, a)
42 #define dbgobjects(a...) if (DebugObjects) fprintf(stderr, a)
43 #define dbgcluts(a...) if (DebugCluts) fprintf(stderr, a)
68 int a = 0, r = 0, g = 0, b = 0;
78 for (
int i = 1; i < 16; ++i) {
80 r = (i & 1) ? 255 : 0;
81 g = (i & 2) ? 255 : 0;
82 b = (i & 4) ? 255 : 0;
85 r = (i & 1) ? 127 : 0;
86 g = (i & 2) ? 127 : 0;
87 b = (i & 4) ? 127 : 0;
93 for (
int i = 1; i < 256; ++i) {
95 r = (i & 1) ? 255 : 0;
96 g = (i & 2) ? 255 : 0;
97 b = (i & 4) ? 255 : 0;
103 r = ((i & 1) ? 85 : 0) + ((i & 0x10) ? 170 : 0);
104 g = ((i & 2) ? 85 : 0) + ((i & 0x20) ? 170 : 0);
105 b = ((i & 4) ? 85 : 0) + ((i & 0x40) ? 170 : 0);
109 r = ((i & 1) ? 85 : 0) + ((i & 0x10) ? 170 : 0);
110 g = ((i & 2) ? 85 : 0) + ((i & 0x20) ? 170 : 0);
111 b = ((i & 4) ? 85 : 0) + ((i & 0x40) ? 170 : 0);
115 r = 127 + ((i & 1) ? 43 : 0) + ((i & 0x10) ? 85 : 0);
116 g = 127 + ((i & 2) ? 43 : 0) + ((i & 0x20) ? 85 : 0);
117 b = 127 + ((i & 4) ? 43 : 0) + ((i & 0x40) ? 85 : 0);
121 r = ((i & 1) ? 43 : 0) + ((i & 0x10) ? 85 : 0);
122 g = ((i & 2) ? 43 : 0) + ((i & 0x20) ? 85 : 0);
123 b = ((i & 4) ? 43 : 0) + ((i & 0x40) ? 85 : 0);
138 default:
esyslog(
"ERROR: wrong Bpp in cSubtitleClut::SetColor(%d, %d, %08X)", Bpp, Index, Color);
148 default:
esyslog(
"ERROR: wrong Bpp in cSubtitleClut::GetPalette(%d)", Bpp);
180 int X(
void) {
return px; }
181 int Y(
void) {
return py; }
210 if (NumberOfCodes > 0) {
212 const uchar *from = &Data[1];
213 int len = NumberOfCodes * 2 - 1;
216 char txt[NumberOfCodes + 1];
218 for (
int i = 2; i < NumberOfCodes; ++i) {
219 uchar c = Data[i * 2 + 1] & 0xFF;
222 if (
' ' <= c && c <=
'~' || c ==
'\n' || 0xA0 <= c)
228 const char *s = conv.
Convert(txt);
240 int y = Even ? 0 : 1;
241 uint8_t map2to4[ 4] = { 0x00, 0x07, 0x08, 0x0F };
242 uint8_t map2to8[ 4] = { 0x00, 0x77, 0x88, 0xFF };
243 uint8_t map4to8[16] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF };
244 const uint8_t *mapTable = NULL;
246 while (!bs.
IsEOF()) {
251 case 8: mapTable = map2to8;
break;
252 case 4: mapTable = map2to4;
break;
253 default: mapTable = NULL;
break;
262 case 8: mapTable = map4to8;
break;
263 default: mapTable = NULL;
break;
283 for (
int i = 0; i < 4; ++i)
288 for (
int i = 0; i < 16; ++i)
296 default:
dbgobjects(
"unknown sub block %s %d\n", __FUNCTION__, __LINE__);
307 for (
int pos = x; pos < x + Length; pos++)
345 color = MapTable[color];
360 else if (bs->
GetBit() == 0) {
367 else if (bs->
GetBit() == 0) {
390 color = MapTable[color];
468 for (
int y = 0; y <
Height(); y++) {
469 for (
int x = 0; x <
Width(); x++)
478 if (so->ObjectId() == ObjectId)
481 if (!result && New) {
496 tmp.DrawText(0, 0, so->TextData(), palette->Color(so->ForegroundPixelCode()), palette->Color(so->BackgroundPixelCode()), font);
507 if (Level > 0 && Level < 4)
513 if (Depth > 0 && Depth < 4)
565 a->
x1 = int(round(FactorX * sr->HorizontalAddress()));
566 a->
y1 = int(round(FactorY * sr->VerticalAddress()));
567 a->
x2 = int(round(FactorX * (sr->HorizontalAddress() + sr->Width() - 1)));
568 a->
y2 = int(round(FactorY * (sr->VerticalAddress() + sr->Height() - 1)));
570 while ((a->
Width() & 3) != 0)
583 if (sc->ClutId() == ClutId)
586 if (!result && New) {
597 if (sr->RegionId() == RegionId)
600 if (!result && New) {
611 result = sr->GetObjectById(ObjectId);
633 default:
dbgpages(
"unknown page state (%s %d)\n", __FUNCTION__, __LINE__);
650 unsigned char *
Get(
int &Length);
651 void Put(
const uchar *Data,
int Length);
675 Size =
max(Size, 2048);
681 esyslog(
"ERROR: can't allocate memory for subtitle assembler");
697 unsigned char *result =
data +
pos;
758 bool AntiAlias =
true;
762 for (
int i = 0; i <
numAreas; i++) {
768 Bpp[i] =
areas[i].bpp = Bpp[i];
821 dbgconverter(
"Converter reset -----------------------\n");
838 if (Data && Length > 8) {
840 int SubstreamHeaderLength = 4;
841 bool ResetSubtitleAssembler = Data[PayloadOffset + 3] == 0x00;
844 if ((Data[7] & 0x01) && (Data[PayloadOffset - 3] & 0x81) == 0x01 && Data[PayloadOffset - 2] == 0x81) {
846 SubstreamHeaderLength = 1;
847 ResetSubtitleAssembler = Data[8] >= 5;
850 if (Length > PayloadOffset + SubstreamHeaderLength) {
854 const uchar *data = Data + PayloadOffset + SubstreamHeaderLength;
855 int length = Length - PayloadOffset - SubstreamHeaderLength;
856 if (ResetSubtitleAssembler)
860 if (data[0] == 0x20 && data[1] == 0x00 && data[2] == 0x0F)
868 if (b && b[0] == 0x0F) {
884 if (Data && Length > 8) {
886 if (Length > PayloadOffset) {
890 const uchar *data = Data + PayloadOffset;
891 int length = Length - PayloadOffset;
893 if (data[0] == 0x20 && data[1] == 0x00 && data[2] == 0x0F) {
897 const uchar *b = data;
916 #define LimitTo32Bit(n) ((n) & 0x00000000FFFFFFFFL)
917 #define MAXDELTA 40000 // max. reasonable PTS/STC delta in ms
929 if (Timeout.
TimedOut() || LastSetupLevel != NewSetupLevel) {
932 LastSetupLevel = NewSetupLevel;
937 if (Delta > (int64_t(1) << 31))
938 Delta -= (int64_t(1) << 32);
939 else if (Delta < -((int64_t(1) << 31) - 1))
940 Delta += (int64_t(1) << 32);
947 Timeout.
Set(sb->Timeout() * 1000);
952 else if (Delta < WaitMs)
972 Er =
constrain((298 * Ey + 460 * Epr) / 256, 0, 255);
973 Eg =
constrain((298 * Ey - 55 * Epb - 137 * Epr) / 256, 0, 255);
974 Eb =
constrain((298 * Ey + 543 * Epb ) / 256, 0, 255);
976 return (Er << 16) | (Eg << 8) | Eb;
981 int OsdWidth, OsdHeight;
983 int VideoWidth, VideoHeight;
1012 if (Length > 5 && bs.
GetBits(8) == 0x0F) {
1013 int segmentType = bs.
GetBits(8);
1017 int segmentLength = bs.
GetBits(16);
1023 if (sp->PageId() == pageId) {
1035 switch (segmentType) {
1038 int pageTimeout = bs.
GetBits(8);
1039 int pageVersion = bs.
GetBits(4);
1040 if (pageVersion == page->
Version())
1046 dbgpages(
"Update page id %d version %d pts %"PRId64
" timeout %d state %d\n", pageId, page->
Version(), page->
Pts(), page->
Timeout(), page->
State());
1047 while (!bs.
IsEOF()) {
1060 int regionVersion = bs.
GetBits(4);
1061 if (regionVersion == region->
Version())
1064 bool regionFillFlag = bs.
GetBit();
1066 int regionWidth = bs.
GetBits(16);
1067 if (regionWidth < 1)
1069 int regionHeight = bs.
GetBits(16);
1070 if (regionHeight < 1)
1072 region->
SetSize(regionWidth, regionHeight);
1077 dbgregions(
"Region pageId %d id %d version %d fill %d width %d height %d level %d depth %d clutId %d\n", pageId, region->
RegionId(), region->
Version(), regionFillFlag, regionWidth, regionHeight, region->
Level(), region->
Depth(), region->
ClutId());
1078 int region8bitPixelCode = bs.
GetBits(8);
1079 int region4bitPixelCode = bs.
GetBits(4);
1080 int region2bitPixelCode = bs.
GetBits(2);
1082 if (regionFillFlag) {
1083 switch (region->
Bpp()) {
1084 case 2: region->
FillRegion(region8bitPixelCode);
break;
1085 case 4: region->
FillRegion(region4bitPixelCode);
break;
1086 case 8: region->
FillRegion(region2bitPixelCode);
break;
1087 default:
dbgregions(
"unknown bpp %d (%s %d)\n", region->
Bpp(), __FUNCTION__, __LINE__);
1090 while (!bs.
IsEOF()) {
1092 int objectType = bs.
GetBits(2);
1093 object->SetCodingMethod(objectType);
1094 object->SetProviderFlag(bs.
GetBits(2));
1095 int objectHorizontalPosition = bs.
GetBits(12);
1097 int objectVerticalPosition = bs.
GetBits(12);
1098 object->SetPosition(objectHorizontalPosition, objectVerticalPosition);
1099 if (objectType == 0x01 || objectType == 0x02) {
1100 object->SetForegroundPixelCode(bs.
GetBits(8));
1101 object->SetBackgroundPixelCode(bs.
GetBits(8));
1109 int clutVersion = bs.
GetBits(4);
1110 if (clutVersion == clut->
Version())
1115 while (!bs.
IsEOF()) {
1117 bool entryClut2Flag = bs.
GetBit();
1118 bool entryClut4Flag = bs.
GetBit();
1119 bool entryClut8Flag = bs.
GetBit();
1139 value =
yuv2rgb(yval, cbval, crval);
1142 dbgcluts(
"%2d %d %d %d %08X\n", clutEntryId, entryClut2Flag ? 2 : 0, entryClut4Flag ? 4 : 0, entryClut8Flag ? 8 : 0, value);
1144 clut->
SetColor(2, clutEntryId, value);
1146 clut->
SetColor(4, clutEntryId, value);
1148 clut->
SetColor(8, clutEntryId, value);
1158 int objectVersion = bs.
GetBits(4);
1159 if (objectVersion == object->
Version())
1161 object->SetVersion(objectVersion);
1162 int codingMethod = bs.
GetBits(2);
1163 object->SetNonModifyingColorFlag(bs.
GetBit());
1165 dbgobjects(
"Object pageId %d id %d version %d method %d modify %d\n", pageId, object->
ObjectId(),
object->Version(),
object->CodingMethod(),
object->NonModifyingColorFlag());
1166 if (codingMethod == 0) {
1167 int topFieldLength = bs.
GetBits(16);
1168 int bottomFieldLength = bs.
GetBits(16);
1169 object->DecodeSubBlock(bs.
GetData(), topFieldLength,
true);
1170 if (bottomFieldLength)
1171 object->DecodeSubBlock(bs.
GetData() + topFieldLength, bottomFieldLength,
false);
1173 object->DecodeSubBlock(bs.
GetData(), topFieldLength,
false);
1176 else if (codingMethod == 1) {
1177 int numberOfCodes = bs.
GetBits(8);
1178 object->DecodeCharacterString(bs.
GetData(), numberOfCodes);
1180 #ifdef FINISHPAGE_HACK
1189 bool displayWindowFlag = bs.
GetBit();
1195 if (displayWindowFlag) {
1210 bool disparity_shift_update_sequence_page_flag = bs.
GetBit();
1213 if (disparity_shift_update_sequence_page_flag) {
1216 int division_period_count = bs.
GetBits(8);
1217 for (
int i = 0; i < division_period_count; ++i) {
1222 while (!bs.
IsEOF()) {
1224 bool disparity_shift_update_sequence_region_flag = bs.
GetBit();
1226 int number_of_subregions_minus_1 = bs.
GetBits(2);
1227 for (
int i = 0; i <= number_of_subregions_minus_1; ++i) {
1228 if (number_of_subregions_minus_1 > 0) {
1235 if (disparity_shift_update_sequence_region_flag) {
1238 int division_period_count = bs.
GetBits(8);
1239 for (
int i = 0; i < division_period_count; ++i) {
1254 dbgsegments(
"*** unknown segment type: %02X\n", segmentType);
1268 bool Reduced =
false;
1270 int HalfBpp = Bpp / 2;
1272 for (
int i = 0; i < NumAreas; i++) {
1273 if (Areas[i].bpp >= Bpp) {
1274 Areas[i].
bpp = HalfBpp;
1285 for (
int i = 0; i < NumAreas; i++) {
1293 if (sr->
Bpp() != Areas[i].
bpp) {