Support customized subtitles.
[vuplus_dvbapp] / lib / dvb / subtitle.cpp
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <fcntl.h>
4 #include <memory.h>
5 #include <time.h>
6
7 #include <asm/types.h>
8 #include <lib/dvb/idemux.h>
9 #include <lib/dvb/subtitle.h>
10 #include <lib/base/smartptr.h>
11 #include <lib/base/eerror.h>
12 #include <lib/base/nconfig.h>
13 #include <lib/gdi/gpixmap.h>
14
15 void bitstream_init(bitstream *bit, const void *buffer, int size)
16 {
17         bit->data = (__u8*) buffer;
18         bit->size = size;
19         bit->avail = 8;
20         bit->consumed = 0;
21 }
22
23 int bitstream_get(bitstream *bit)
24 {
25         int val;
26         bit->avail -= bit->size;
27         val = ((*bit->data) >> bit->avail) & ((1<<bit->size) - 1);
28         if (!bit->avail)
29         {
30                 bit->data++;
31                 bit->consumed++;
32                 bit->avail = 8;
33         }
34         return val;
35 }
36
37 static int extract_pts(pts_t &pts, __u8 *pkt)
38 {
39         pkt += 7;
40         int flags = *pkt++;
41
42         pkt++; // header length
43
44         if (flags & 0x80) /* PTS present? */
45         {
46                         /* damn gcc bug */
47                 pts  = ((unsigned long long)(((pkt[0] >> 1) & 7))) << 30;
48                 pts |=   pkt[1] << 22;
49                 pts |=  (pkt[2]>>1) << 15;
50                 pts |=   pkt[3] << 7;
51                 pts |=  (pkt[5]>>1);
52
53                 return 0;
54         } else
55                 return -1;
56 }
57
58 void eDVBSubtitleParser::subtitle_process_line(subtitle_region *region, subtitle_region_object *object, int line, __u8 *data, int len)
59 {
60         bool subcentered = ePythonConfigQuery::getConfigBoolValue("config.subtitles.dvb_subtitles_centered");
61         int x = subcentered ? (region->width - len) /2 : object->object_horizontal_position;
62         int y = object->object_vertical_position + line;
63         if (x + len > region->width)
64         {
65 //              eDebug("[SUB] !!!! XCLIP %d + %d > %d", x, len, region->width);
66                 len = region->width - x;
67         }
68         if (len < 0)
69                 return;
70         if (y >= region->height)
71         {
72 //              eDebug("[SUB] !!!! YCLIP %d >= %d", y, region->height);
73                 return;
74         }
75 //      eDebug("inserting %d bytes (into region %d)", len, region->region_id);
76 //      eDebug("put data to buffer %p", &(*region->buffer));
77         if (subcentered && region->region_id && line < 3)
78         {
79                 for (int i = 0; i < len; i++)
80                         if(data[i] <= 8)
81                         {
82                                 data[i] = 0;
83                         }
84         }
85         memcpy((__u8*)region->buffer->surface->data + region->buffer->surface->stride * y + x, data, len);
86 }
87
88 static int map_2_to_4_bit_table[4];
89 static int map_2_to_8_bit_table[4];
90 static int map_4_to_8_bit_table[16];
91
92 int eDVBSubtitleParser::subtitle_process_pixel_data(subtitle_region *region, subtitle_region_object *object, int *linenr, int *linep, __u8 *data)
93 {
94         int data_type = *data++;
95         static __u8 line[1920];
96
97         bitstream bit;
98         bit.size=0;
99         switch (data_type)
100         {
101         case 0x10: // 2bit pixel data
102 //              eDebug("2bit pixel data!");
103                 bitstream_init(&bit, data, 2);
104                 while (1)
105                 {
106                         int len=0, col=0;
107                         int code = bitstream_get(&bit);
108                         if (code)
109                         {
110                                 col = code;
111                                 len = 1;
112                         } else
113                         {
114                                 code = bitstream_get(&bit);
115                                 if (!code)
116                                 {
117                                         code = bitstream_get(&bit);
118                                         if (code == 1)
119                                         {
120                                                 col = 0;
121                                                 len = 2;
122                                         } else if (code == 2)
123                                         {
124                                                 len = bitstream_get(&bit) << 2;
125                                                 len |= bitstream_get(&bit);
126                                                 len += 12;
127                                                 col = bitstream_get(&bit);
128                                         } else if (code == 3)
129                                         {
130                                                 len = bitstream_get(&bit) << 6;
131                                                 len |= bitstream_get(&bit) << 4;
132                                                 len |= bitstream_get(&bit) << 2;
133                                                 len |= bitstream_get(&bit);
134                                                 len += 29;
135                                                 col = bitstream_get(&bit);
136                                         } else
137                                                 break;
138                                 } else if (code==1)
139                                 {
140                                         col = 0;
141                                         len = 1;
142                                 } else if (code&2)
143                                 {
144                                         if (code&1)
145                                                 len = 3 + 4 + bitstream_get(&bit);
146                                         else
147                                                 len = 3 + bitstream_get(&bit);
148                                         col = bitstream_get(&bit);
149                                 }
150                         }
151                         uint8_t c = region->depth == subtitle_region::bpp4 ?
152                                 map_2_to_4_bit_table[col] :
153                                 region->depth == subtitle_region::bpp8 ?
154                                 map_2_to_8_bit_table[col] : col;
155                         while (len && ((*linep) < m_display_size.width()))
156                         {
157                                 line[(*linep)++] = c;
158                                 len--;
159                         }
160                 }
161                 while (bit.avail != 8)
162                         bitstream_get(&bit);
163                 return bit.consumed + 1;
164         case 0x11: // 4bit pixel data
165 //              eDebug("4bit pixel data!");
166                 bitstream_init(&bit, data, 4);
167                 while (1)
168                 {
169                         int len=0, col=0;
170                         int code = bitstream_get(&bit);
171                         if (code)
172                         {
173                                 col = code;
174                                 len = 1;
175                         } else
176                         {
177                                 code = bitstream_get(&bit);
178                                 if (!code)
179                                         break;
180                                 else if (code == 0xC)
181                                 {
182                                         col = 0;
183                                         len = 1;
184                                 } else if (code == 0xD)
185                                 {
186                                         col = 0;
187                                         len = 2;
188                                 } else if (code < 8)
189                                 {
190                                         col = 0;
191                                         len = (code & 7) + 2;
192                                 } else if ((code & 0xC) == 0x8)
193                                 {
194                                         col = bitstream_get(&bit);
195                                         len = (code & 3) + 4;
196                                 } else if (code == 0xE)
197                                 {
198                                         len = bitstream_get(&bit) + 9;
199                                         col = bitstream_get(&bit);
200                                 } else if (code == 0xF)
201                                 {
202                                         len  = bitstream_get(&bit) << 4;
203                                         len |= bitstream_get(&bit);
204                                         len += 25;
205                                         col  = bitstream_get(&bit);
206                                 }
207                         }
208                         uint8_t c = region->depth == subtitle_region::bpp8 ?
209                                 map_4_to_8_bit_table[col] : col;
210                         while (len && ((*linep) < m_display_size.width()))
211                         {
212                                 line[(*linep)++] = c;
213                                 len--;
214                         }
215                 }
216                 while (bit.avail != 8)
217                         bitstream_get(&bit);
218                 return bit.consumed + 1;
219         case 0x12: // 8bit pixel data
220 //              eDebug("8bit pixel data!");
221                 bitstream_init(&bit, data, 8);
222                 while(1)
223                 {
224                         int len=0, col=0;
225                         int code = bitstream_get(&bit);
226                         if (code)
227                         {
228                                 col = code;
229                                 len = 1;
230                         } else
231                         {
232                                 code = bitstream_get(&bit);
233                                 if ((code & 0x80) == 0x80)
234                                 {
235                                         len = code&0x7F;
236                                         col = bitstream_get(&bit);
237                                 } else if (code&0x7F)
238                                 {
239                                         len = code&0x7F;
240                                         col = 0;
241                                 } else
242                                         break;
243                         }
244                         while (len && ((*linep) < m_display_size.width()))
245                         {
246                                 line[(*linep)++] = col;
247                                 len--;
248                         }
249                 }
250                 return bit.consumed + 1;
251         case 0x20:
252 //              eDebugNoNewLine("2 -> 4 bit table: ");
253                 bitstream_init(&bit, data, 4);
254                 for ( int i=0; i < 4; ++i )
255                 {
256                         map_2_to_4_bit_table[i] = bitstream_get(&bit);
257 //                      eDebugNoNewLine("%d ", map_2_to_4_bit_table[i]);
258                 }
259                 eDebug("");
260                 return bit.consumed + 1;
261         case 0x21:
262 //              eDebugNoNewLine("2 -> 8 bit table: ");
263                 bitstream_init(&bit, data, 8);
264                 for ( int i=0; i < 4; ++i )
265                 {
266                         map_2_to_8_bit_table[i] = bitstream_get(&bit);
267 //                      eDebugNoNewLine("%d ", map_2_to_8_bit_table[i]);
268                 }
269                 return bit.consumed + 1;
270         case 0x22:
271 //              eDebug("4 -> 8 bit table!");
272                 bitstream_init(&bit, data, 8);
273                 for ( int i=0; i < 16; ++i )
274                 {
275                         map_4_to_8_bit_table[i] = bitstream_get(&bit);
276 //                      eDebugNoNewLine("%d ", map_4_to_8_bit_table[i]);
277                 }
278                 return bit.consumed + 1;
279         case 0xF0:
280                 subtitle_process_line(region, object, *linenr, line, *linep);
281 /*              {
282                         int i;
283                         for (i=0; i<m_display_size.width(); ++i)
284                                 eDebugNoNewLine("%d ", line[i]);
285                         eDebug("");
286                 } */
287                 (*linenr)+=2; // interlaced
288                 *linep = 0;
289 //              eDebug("[SUB] EOL");
290                 return 1;
291         default:
292                 eDebug("subtitle_process_pixel_data: invalid data_type %02x", data_type);
293                 return -1;
294         }
295         return 0;
296 }
297
298 int eDVBSubtitleParser::subtitle_process_segment(__u8 *segment)
299 {
300         int segment_type, page_id, segment_length, processed_length;
301         if (*segment++ !=  0x0F)
302         {
303                 eDebug("out of sync.");
304                 return -1;
305         }
306         segment_type = *segment++;
307         page_id  = *segment++ << 8;
308         page_id |= *segment++;
309         segment_length  = *segment++ << 8;
310         segment_length |= *segment++;
311         if (segment_type == 0xFF)
312                 return segment_length + 6;
313         if (page_id != m_composition_page_id && page_id != m_ancillary_page_id)
314                 return segment_length + 6;
315 //      eDebug("have %d bytes of segment data", segment_length);
316
317 //      eDebug("page_id %d, segtype %02x", page_id, segment_type);
318
319         subtitle_page *page, **ppage;
320
321         page = m_pages; ppage = &m_pages;
322
323         while (page)
324         {
325                 if (page->page_id == page_id)
326                         break;
327                 ppage = &page->next;
328                 page = page->next;
329         }
330
331         processed_length = 0;
332
333         switch (segment_type)
334         {
335         case 0x10: // page composition segment
336         {
337                 int page_time_out = *segment++; processed_length++;
338                 int page_version_number = *segment >> 4;
339                 int page_state = (*segment >> 2) & 0x3;
340 //              eDebug("pcs with %d bytes data (%d:%d:%d)", segment_length, page_id, page_version_number, page_state);
341                 segment++;
342                 processed_length++;
343
344 //              eDebug("page time out: %d", page_time_out);
345 //              eDebug("page_version_number: %d" ,page_version_number);
346 //              eDebug("page_state: %d", page_state);
347
348                 if (!page)
349                 {
350 //                      eDebug("page not found");
351                         page = new subtitle_page;
352                         page->page_regions = 0;
353                         page->regions = 0;
354                         page->page_id = page_id;
355                         page->cluts = 0;
356                         page->next = 0;
357                         *ppage = page;
358                 } else
359                 {
360                         if (page->pcs_size != segment_length)
361                                 page->page_version_number = -1;
362                                 // if no update, just skip this data.
363                         if (page->page_version_number == page_version_number)
364                         {
365 //                              eDebug("skip data... ");
366                                 break;
367                         }
368                 }
369
370                 page->state = page_state;
371
372 //              eDebug("page updated: old: %d, new: %d", page->page_version_number, page_version_number);
373                         // when acquisition point or mode change: remove all displayed pages.
374                 if ((page_state == 1) || (page_state == 2))
375                 {
376                         while (page->page_regions)
377                         {
378                                 subtitle_page_region *p = page->page_regions->next;
379 //                              eDebug("delete page_region %d", page->page_regions->region_id);
380                                 delete page->page_regions;
381                                 page->page_regions = p;
382                         }
383                         while (page->regions)
384                         {
385                                 subtitle_region *p = page->regions->next;
386 //                              eDebug("delete region %d", page->regions->region_id);
387                                 while(page->regions->objects)
388                                 {
389 //                                      eDebug("delete region object");
390                                         subtitle_region_object *ob = page->regions->objects->next;
391                                         delete page->regions->objects;
392                                         page->regions->objects = ob;
393                                 }
394                                 delete page->regions;
395                                 page->regions = p;
396                         }
397
398                 }
399
400 //              eDebug("new page.. (%d)", page_state);
401
402                 page->page_time_out = page_time_out;
403
404                 page->page_version_number = page_version_number;
405
406                 subtitle_page_region **r = &page->page_regions;
407
408 //              eDebug("%d  / %d data left", processed_length, segment_length);
409
410                         // go to last entry
411                 while (*r)
412                         r = &(*r)->next;
413
414                 if (processed_length == segment_length && !page->page_regions)
415                 {
416 //                      eDebug("no regions in page.. clear screen!!");
417                         subtitle_redraw(page->page_id);
418                 }
419
420                 while (processed_length < segment_length)
421                 {
422                         subtitle_page_region *pr;
423
424                                 // append new entry to list
425                         pr = new subtitle_page_region;
426                         pr->next = 0;
427                         *r = pr;
428                         r = &pr->next;
429
430                         pr->region_id = *segment++; processed_length++;
431                         segment++; processed_length++;
432
433                         pr->region_horizontal_address  = *segment++ << 8;
434                         pr->region_horizontal_address |= *segment++;
435                         processed_length += 2;
436
437                         pr->region_vertical_address  = *segment++ << 8;
438                         pr->region_vertical_address |= *segment++;
439                         processed_length += 2;
440
441 //                      eDebug("appended active region");
442                 }
443
444                 if (processed_length != segment_length)
445                         eDebug("%d != %d", processed_length, segment_length);
446                 break;
447         }
448         case 0x11: // region composition segment
449         {
450                 int region_id = *segment++; processed_length++;
451                 int version_number = *segment >> 4;
452                 int region_fill_flag = (*segment >> 3) & 1;
453                 segment++; processed_length++;
454
455                         // if we didn't yet received the pcs for this page, drop the region
456                 if (!page)
457                 {
458                         eDebug("ignoring region %x, since page %02x doesn't yet exist.", region_id, page_id);
459                         break;
460                 }
461
462                 subtitle_region *region, **pregion;
463
464                 region = page->regions; pregion = &page->regions;
465
466                 while (region)
467                 {
468                         fflush(stdout);
469                         if (region->region_id == region_id)
470                                 break;
471                         pregion = &region->next;
472                         region = region->next;
473                 }
474
475                 if (!region)
476                 {
477 //                      eDebug("create region !!!!!!!!!!");
478                         *pregion = region = new subtitle_region;
479                         region->next = 0;
480                         region->committed = false;
481                 }
482                 else if (region->version_number != version_number)
483                 {
484                         subtitle_region_object *objects = region->objects;
485 //                      eDebug("unequal version %p %p", objects, objects?objects->next:objects);
486                         while (objects)
487                         {
488                                 subtitle_region_object *n = objects->next;
489                                 delete objects;
490                                 objects = n;
491                         }
492                         if (region->buffer)
493                         {
494 //                              eDebug("no more need of buffer %p", &(*region->buffer));
495                                 region->buffer=0;
496                         }
497                         region->committed = false;
498                 }
499                 else
500                         break;
501
502 //              eDebug("region %d:%d update", page_id, region_id);
503
504                 region->region_id = region_id;
505                 region->version_number = version_number;
506
507                 region->width  = *segment++ << 8;
508                 region->width |= *segment++;
509                 processed_length += 2;
510
511                 region->height  = *segment++ << 8;
512                 region->height |= *segment++;
513                 processed_length += 2;
514
515                 region->buffer = new gPixmap(eSize(region->width, region->height), 8, 1);
516                 memset(region->buffer->surface->data, 0, region->height * region->buffer->surface->stride);
517 //              eDebug("new buffer %p", &(*region->buffer));
518
519                 int region_level_of_compatibility, depth;
520
521                 region_level_of_compatibility = (*segment >> 5) & 7;
522                 depth = (*segment++ >> 2) & 7;
523
524                 region->depth = (subtitle_region::tDepth) depth;
525                 processed_length++;
526
527                 int CLUT_id = *segment++; processed_length++;
528
529                 region->clut_id = CLUT_id;
530
531                 int region_8bit_pixel_code, region_4bit_pixel_code, region_2bit_pixel_code;
532                 region_8bit_pixel_code = *segment++; processed_length++;
533                 region_4bit_pixel_code = *segment >> 4;
534                 region_2bit_pixel_code = (*segment++ >> 2) & 3;
535                 processed_length++;
536
537                 if (!region_fill_flag)
538                 {
539                         region_2bit_pixel_code = region_4bit_pixel_code = region_8bit_pixel_code = 0;
540                         region_fill_flag = 1;
541                 }
542
543                 if (region_fill_flag)
544                 {
545 //                      eDebug("region fill buffer %p", &(*region->buffer));
546                         if (depth == 1)
547                                 memset(region->buffer->surface->data, region_2bit_pixel_code, region->height * region->width);
548                         else if (depth == 2)
549                                 memset(region->buffer->surface->data, region_4bit_pixel_code, region->height * region->width);
550                         else if (depth == 3)
551                                 memset(region->buffer->surface->data, region_8bit_pixel_code, region->height * region->width);
552                         else
553                                 eDebug("!!!! invalid depth");
554                 }
555
556 //              eDebug("region %02x, version %d, %dx%d", region->region_id, region->version_number, region->width, region->height);
557
558                 region->objects = 0;
559                 subtitle_region_object **pobject = &region->objects;
560
561                 while (processed_length < segment_length)
562                 {
563                         subtitle_region_object *object;
564
565                         object = new subtitle_region_object;
566
567                         *pobject = object;
568                         object->next = 0;
569                         pobject = &object->next;
570
571                         object->object_id  = *segment++ << 8;
572                         object->object_id |= *segment++; processed_length += 2;
573
574                         object->object_type = *segment >> 6;
575                         object->object_provider_flag = (*segment >> 4) & 3;
576                         object->object_horizontal_position  = (*segment++ & 0xF) << 8;
577                         object->object_horizontal_position |= *segment++;
578                         processed_length += 2;
579
580                         object->object_vertical_position  = *segment++ << 8;
581                         object->object_vertical_position |= *segment++ ;
582                         processed_length += 2;
583
584                         if ((object->object_type == 1) || (object->object_type == 2))
585                         {
586                                 object->foreground_pixel_value = *segment++;
587                                 object->background_pixel_value = *segment++;
588                                 processed_length += 2;
589                         }
590                 }
591
592                 if (processed_length != segment_length)
593                         eDebug("too less data! (%d < %d)", segment_length, processed_length);
594
595                 break;
596         }
597         case 0x12: // CLUT definition segment
598         {
599                 int CLUT_id, CLUT_version_number;
600                 subtitle_clut *clut, **pclut;
601
602                 if (!page)
603                         break;
604
605 //              eDebug("CLUT: %02x", *segment);
606                 CLUT_id = *segment++;
607
608                 CLUT_version_number = *segment++ >> 4;
609                 processed_length += 2;
610
611 //              eDebug("page %d, CLUT %02x, version %d", page->page_id, CLUT_id, CLUT_version_number);
612
613                 clut = page->cluts; pclut = &page->cluts;
614
615                 while (clut)
616                 {
617                         if (clut->clut_id == CLUT_id)
618                                 break;
619                         pclut = &clut->next;
620                         clut = clut->next;
621                 }
622
623                 if (!clut)
624                 {
625                         *pclut = clut = new subtitle_clut;
626                         clut->next = 0;
627                         clut->clut_id = CLUT_id;
628                 }
629                 else if (clut->CLUT_version_number == CLUT_version_number)
630                         break;
631
632                 clut->CLUT_version_number=CLUT_version_number;
633
634                 memset(clut->entries_2bit, 0, sizeof(clut->entries_2bit));
635                 memset(clut->entries_4bit, 0, sizeof(clut->entries_4bit));
636                 memset(clut->entries_8bit, 0, sizeof(clut->entries_8bit));
637
638 //              eDebug("new Clut!");
639                 while (processed_length < segment_length)
640                 {
641                         int CLUT_entry_id, entry_CLUT_flag, full_range;
642                         int v_Y, v_Cr, v_Cb, v_T;
643
644                         CLUT_entry_id = *segment++;
645                         full_range = *segment & 1;
646                         entry_CLUT_flag = (*segment++ & 0xE0) >> 5;
647                         processed_length += 2;
648
649                         if (full_range)
650                         {
651 //                              eDebugNoNewLine("f");
652                                 v_Y  = *segment++;
653                                 v_Cr = *segment++;
654                                 v_Cb = *segment++;
655                                 v_T  = *segment++;
656                                 processed_length += 4;
657                         } else
658                         {
659 //                              eDebugNoNewLine(" ");
660                                 v_Y   = *segment & 0xFC;
661                                 v_Cr  = (*segment++ & 3) << 6;
662                                 v_Cr |= (*segment & 0xC0) >> 2;
663                                 v_Cb  = (*segment & 0x3C) << 2;
664                                 v_T   = (*segment++ & 3) << 6;
665                                 processed_length += 2;
666                         }
667
668                         if (entry_CLUT_flag & 1) // 8bit
669                         {
670 //                              eDebugNoNewLine("8b");
671                                 clut->entries_8bit[CLUT_entry_id].Y = v_Y;
672                                 clut->entries_8bit[CLUT_entry_id].Cr = v_Cr;
673                                 clut->entries_8bit[CLUT_entry_id].Cb = v_Cb;
674                                 clut->entries_8bit[CLUT_entry_id].T = v_T;
675                                 clut->entries_8bit[CLUT_entry_id].valid = 1;
676                         }
677                         if (entry_CLUT_flag & 2) // 4bit
678                         {
679 //                              eDebugNoNewLine("4b");
680                                 if (CLUT_entry_id < 16)
681                                 {
682                                         clut->entries_4bit[CLUT_entry_id].Y = v_Y;
683                                         clut->entries_4bit[CLUT_entry_id].Cr = v_Cr;
684                                         clut->entries_4bit[CLUT_entry_id].Cb = v_Cb;
685                                         clut->entries_4bit[CLUT_entry_id].T = v_T;
686                                         clut->entries_4bit[CLUT_entry_id].valid = 1;
687                                 }
688                                 else
689                                         eDebug("CLUT entry marked as 4 bit with id %d (>15)", CLUT_entry_id);
690                         }
691                         if (entry_CLUT_flag & 4) // 2bit
692                         {
693 //                              eDebugNoNewLine("2b");
694                                 if (CLUT_entry_id < 4)
695                                 {
696                                         clut->entries_2bit[CLUT_entry_id].Y = v_Y;
697                                         clut->entries_2bit[CLUT_entry_id].Cr = v_Cr;
698                                         clut->entries_2bit[CLUT_entry_id].Cb = v_Cb;
699                                         clut->entries_2bit[CLUT_entry_id].T = v_T;
700                                         clut->entries_2bit[CLUT_entry_id].valid = 1;
701                                 }
702                                 else
703                                         eDebug("CLUT entry marked as 2 bit with id %d (>3)", CLUT_entry_id);
704                         }
705 //                      eDebug(" %04x %02x %02x %02x %02x", CLUT_entry_id, v_Y, v_Cb, v_Cr, v_T);
706                 }
707                 break;
708         }
709         case 0x13: // object data segment
710         {
711                 int object_id, object_version_number, object_coding_method, non_modifying_color_flag;
712
713                 object_id  = *segment++ << 8;
714                 object_id |= *segment++;
715                 processed_length += 2;
716
717                 object_version_number = *segment >> 4;
718                 object_coding_method  = (*segment >> 2) & 3;
719                 non_modifying_color_flag = (*segment++ >> 1) & 1;
720                 processed_length++;
721
722 //              eDebug("object id %04x, version %d, object_coding_method %d (page_id %d)", object_id, object_version_number, object_coding_method, page_id);
723                 subtitle_region *region = page->regions;
724 //              eDebug("line for %d:%d", page->page_id, object_id);
725                 while (region)
726                 {
727                         subtitle_region_object *object = region->objects;
728                         while (object)
729                         {
730                                 if (object->object_id == object_id)
731                                 {
732                                         if (object_coding_method == 0)
733                                         {
734                                                 int top_field_data_blocklength, bottom_field_data_blocklength;
735                                                 int i=1, line, linep;
736
737                                                 top_field_data_blocklength  = *segment++ << 8;
738                                                 top_field_data_blocklength |= *segment++;
739
740                                                 bottom_field_data_blocklength  = *segment++ << 8;
741                                                 bottom_field_data_blocklength |= *segment++;
742 //                                              eDebug("%d / %d bytes", top_field_data_blocklength, bottom_field_data_blocklength);
743                                                 processed_length += 4;
744
745                                                 // its working on cyfra channels.. but hmm in EN300743 the default table is 0, 7, 8, 15
746                                                 map_2_to_4_bit_table[0] = 0;
747                                                 map_2_to_4_bit_table[1] = 8;
748                                                 map_2_to_4_bit_table[2] = 7;
749                                                 map_2_to_4_bit_table[3] = 15;
750
751                                                 // this map is realy untested...
752                                                 map_2_to_8_bit_table[0] = 0;
753                                                 map_2_to_8_bit_table[1] = 0x88;
754                                                 map_2_to_8_bit_table[2] = 0x77;
755                                                 map_2_to_8_bit_table[3] = 0xff;
756
757                                                 map_4_to_8_bit_table[0] = 0;
758                                                 for (; i < 16; ++i)
759                                                         map_4_to_8_bit_table[i] = i * 0x11;
760
761                                                 i = 0;
762                                                 line = 0;
763                                                 linep = 0;
764                                                 while (i < top_field_data_blocklength)
765                                                 {
766                                                         int len;
767                                                         len = subtitle_process_pixel_data(region, object, &line, &linep, segment);
768                                                         if (len < 0)
769                                                                 return -1;
770                                                         segment += len;
771                                                         processed_length += len;
772                                                         i += len;
773                                                 }
774
775                                                 line = 1;
776                                                 linep = 0;
777
778                                                 if (bottom_field_data_blocklength)
779                                                 {
780                                                         i = 0;
781                                                         while (i < bottom_field_data_blocklength)
782                                                         {
783                                                                 int len;
784                                                                 len = subtitle_process_pixel_data(region, object, &line, &linep, segment);
785                                                                 if (len < 0)
786                                                                         return -1;
787                                                                 segment += len;
788                                                                         processed_length += len;
789                                                                 i += len;
790                                                         }
791                                                 }
792                                                 else if (top_field_data_blocklength)
793                                                         eDebug("!!!! unimplemented: no bottom field! (%d : %d)", top_field_data_blocklength, bottom_field_data_blocklength);
794
795                                                 if ((top_field_data_blocklength + bottom_field_data_blocklength) & 1)
796                                                 {
797                                                         segment++; processed_length++;
798                                                 }
799                                         }
800                                         else if (object_coding_method == 1)
801                                                 eDebug("---- object_coding_method 1 unsupported!");
802                                 }
803                                 object = object->next;
804                         }
805                         region = region->next;
806                 }
807                 break;
808         }
809         case 0x14: // display definition segment
810         {
811                 if (segment_length > 4)
812                 {
813                         int dds_version_number = segment[0] >> 4;
814                         int display_window_flag = (segment[0] >> 3) & 1;
815                         int display_width = (segment[1] << 8) | (segment[2]);
816                         int display_height = (segment[3] << 8) | (segment[4]);
817 //                      eDebug("version %d, window_flag %d, display_width %d, display_height %d",
818 //                              dds_version_number, display_window_flag, display_width, display_height);
819                         processed_length += 5;
820                         m_display_size = eSize(display_width+1, display_height+1);
821                         if (display_window_flag)
822                         {
823                                 if (segment_length > 12)
824                                 {
825                                         int display_window_horizontal_position_min = (segment[4] << 8) | segment[5];
826                                         int display_window_horizontal_position_max = (segment[6] << 8) | segment[7];
827                                         int display_window_vertical_position_min = (segment[8] << 8) | segment[9];
828                                         int display_window_vertical_position_max = (segment[10] << 8) | segment[11];
829                                         eDebug("NYI hpos min %d, hpos max %d, vpos min %d, vpos max %d",
830                                                 display_window_horizontal_position_min,
831                                                 display_window_horizontal_position_max,
832                                                 display_window_vertical_position_min,
833                                                 display_window_vertical_position_max);
834                                         processed_length += 8;
835                                 }
836                                 else
837                                         eDebug("display window flag set but display definition segment to short %d!", segment_length);
838                         }
839                 }
840                 else
841                         eDebug("display definition segment to short %d!", segment_length);
842                 break;
843         }
844         case 0x80: // end of display set segment
845         {
846 //              eDebug("end of display set segment");
847                 subtitle_redraw_all();
848                 m_seen_eod = true;
849         }
850         case 0xFF: // stuffing
851                 break;
852         default:
853                 eDebug("unhandled segment type %02x", segment_type);
854         }
855
856         return segment_length + 6;
857 }
858
859 void eDVBSubtitleParser::subtitle_process_pes(__u8 *pkt, int len)
860 {
861 //      eDebugNoNewLine("subtitle_process_pes");
862         if (!extract_pts(m_show_time, pkt))
863         {
864 //              eDebug(" %lld", m_show_time);
865                 pkt += 6; len -= 6;
866                 // skip PES header
867                 pkt++; len--;
868                 pkt++; len--;
869
870                 int hdr_len = *pkt++; len--;
871
872                 pkt+=hdr_len; len-=hdr_len;
873
874                 if (*pkt != 0x20)
875                 {
876 //                      eDebug("data identifier is 0x%02x, but not 0x20", *pkt);
877                         return;
878                 }
879                 pkt++; len--; // data identifier
880                 *pkt++; len--; // stream id;
881
882                 if (len <= 0)
883                 {
884 //                      eDebug("no data left (%d)", len);
885                         return;
886                 }
887
888                 m_seen_eod = false;
889
890                 while (len && *pkt == 0x0F)
891                 {
892                         int l = subtitle_process_segment(pkt);
893                         if (l < 0)
894                                 break;
895                         pkt += l;
896                         len -= l;
897                 }
898
899                 if (len && *pkt != 0xFF)
900                         eDebug("strange data at the end");
901
902                 if (!m_seen_eod)
903                         subtitle_redraw_all();
904         }
905 //      else
906 //              eDebug("");
907 }
908
909 void eDVBSubtitleParser::subtitle_redraw_all()
910 {
911 #if 1
912         subtitle_page *page = m_pages;
913         while(page)
914         {
915                 if (page->state != 0)
916                         subtitle_redraw(page->page_id);
917                 page = page->next;
918         }
919 #else
920         subtitle_page *page = m_pages;
921         eDebug("----------- end of display set");
922         eDebug("active pages:");
923         while (page)
924         {
925                 eDebug("  page_id %02x", page->page_id);
926                 eDebug("  page_version_number: %d", page->page_version_number);
927                 eDebug("  active regions:");
928                 {
929                         subtitle_page_region *region = page->page_regions;
930                         while (region)
931                         {
932                                 eDebug("    region_id: %04x", region->region_id);
933                                 eDebug("    region_horizontal_address: %d", region->region_horizontal_address);
934                                 eDebug("    region_vertical_address: %d", region->region_vertical_address);
935
936                                 region = region->next;
937                         }
938                 }
939
940                 subtitle_redraw(page->page_id);
941                 eDebug("defined regions:");
942                 subtitle_region *region = page->regions;
943                 while (region)
944                 {
945                         eDebug("  region_id %04x, version %d, %dx%d", region->region_id, region->version_number, region->width, region->height);
946
947                         subtitle_region_object *object = region->objects;
948                         while (object)
949                         {
950                                 eDebug("  object %02x, type %d, %d:%d", object->object_id, object->object_type, object->object_horizontal_position, object->object_vertical_position);
951                                 object = object->next;
952                         }
953                         region = region->next;
954                 }
955                 page = page->next;
956         }
957 #endif
958 }
959
960 void eDVBSubtitleParser::subtitle_reset()
961 {
962         while (subtitle_page *page = m_pages)
963         {
964                         /* free page regions */
965                 while (page->page_regions)
966                 {
967                         subtitle_page_region *p = page->page_regions->next;
968                         delete page->page_regions;
969                         page->page_regions = p;
970                 }
971                         /* free regions */
972                 while (page->regions)
973                 {
974                         subtitle_region *region = page->regions;
975
976                         while (region->objects)
977                         {
978                                 subtitle_region_object *obj = region->objects;
979                                 region->objects = obj->next;
980                                 delete obj;
981                         }
982
983                         if (region->buffer)
984                         {
985 //                              eDebug("no more need of buffer 2 %p", &(*region->buffer));
986                                 region->buffer=0;
987                         }
988
989                         page->regions = region->next;
990                         delete region;
991                 }
992
993                         /* free CLUTs */
994                 while (page->cluts)
995                 {
996                         subtitle_clut *clut = page->cluts;
997                         page->cluts = clut->next;
998                         delete clut;
999                 }
1000
1001                 m_pages = page->next;
1002                 delete page;
1003         }
1004 }
1005
1006 void eDVBSubtitleParser::subtitle_redraw(int page_id)
1007 {
1008         subtitle_page *page = m_pages;
1009
1010 //      eDebug("displaying page id %d", page_id);
1011
1012         while (page)
1013         {
1014                 if (page->page_id == page_id)
1015                         break;
1016                 page = page->next;
1017         }
1018         if (!page)
1019         {
1020 //              eDebug("page not found");
1021                 return;
1022         }
1023
1024 //      eDebug("iterating regions..");
1025                 /* iterate all regions in this pcs */
1026         subtitle_page_region *region = page->page_regions;
1027
1028         eDVBSubtitlePage Page;
1029         Page.m_show_time = m_show_time;
1030         for (; region; region=region->next)
1031         {
1032 //              eDebug("region %d", region->region_id);
1033                         /* find corresponding region */
1034                 subtitle_region *reg = page->regions;
1035                 while (reg)
1036                 {
1037                         if (reg->region_id == region->region_id)
1038                                 break;
1039                         reg = reg->next;
1040                 }
1041                 if (reg)
1042                 {
1043                         if (reg->committed)
1044                                 continue;
1045 //                      eDebug("copy region %d to %d, %d", region->region_id, region->region_horizontal_address, region->region_vertical_address);
1046
1047                         int x0 = region->region_horizontal_address;
1048                         int y0 = region->region_vertical_address;
1049
1050                         if ((x0 < 0) || (y0 < 0))
1051                         {
1052 //                              eDebug("x0 %d, y0 %d", x0, y0);
1053                                 continue;
1054                         }
1055
1056                         /* find corresponding clut */
1057                         subtitle_clut *clut = page->cluts;
1058                         while (clut)
1059                         {
1060 //                              eDebug("have %d, want %d", clut->clut_id, main_clut_id);
1061                                 if (clut->clut_id == reg->clut_id)
1062                                         break;
1063                                 clut = clut->next;
1064                         }
1065
1066                         int clut_size = reg->buffer->surface->clut.colors = reg->depth == subtitle_region::bpp2 ?
1067                                 4 : reg->depth == subtitle_region::bpp4 ? 16 : 256;
1068
1069                         reg->buffer->surface->clut.data = new gRGB[clut_size];
1070 //                      eDebug("create clut data for buffer %p", &(*reg->buffer));
1071
1072                         gRGB *palette = reg->buffer->surface->clut.data;
1073
1074 //                      if (!clut)
1075 //                              eDebug("no CLUT.. use default");
1076
1077                         subtitle_clut_entry *entries=0;
1078                         switch(reg->depth)
1079                         {
1080                                 case subtitle_region::bpp2:
1081 //                                      eDebug("2BPP");
1082                                         if (clut)
1083                                                 entries = clut->entries_2bit;
1084                                         memset(palette, 0, 4 * sizeof(gRGB));
1085                                         // this table is tested on cyfra .. but in EN300743 the table palette[2] and palette[1] is swapped.. i dont understand this ;)
1086                                         palette[0].a = 0xFF;
1087                                         palette[2].r = palette[2].g = palette[2].b = 0xFF;
1088                                         palette[3].r = palette[3].g = palette[3].b = 0x80;
1089                                         break;
1090                                 case subtitle_region::bpp4: // tested on cyfra... but the map is another in EN300743... dont understand this...
1091 //                                      eDebug("4BPP");
1092                                         if (clut)
1093                                                 entries = clut->entries_4bit;
1094                                         memset(palette, 0, 16*sizeof(gRGB));
1095                                         for (int i=0; i < 16; ++i)
1096                                         {
1097                                                 if (!i)
1098                                                         palette[i].a = 0xFF;
1099                                                 else if (i & 8)
1100                                                 {
1101                                                         if (i & 1)
1102                                                                 palette[i].r = 0x80;
1103                                                         if (i & 2)
1104                                                                 palette[i].g = 0x80;
1105                                                         if (i & 4)
1106                                                                 palette[i].b = 0x80;
1107                                                 }
1108                                                 else
1109                                                 {
1110                                                         if (i & 1)
1111                                                                 palette[i].r = 0xFF;
1112                                                         if (i & 2)
1113                                                                 palette[i].g = 0xFF;
1114                                                         if (i & 4)
1115                                                                 palette[i].b = 0xFF;
1116                                                 }
1117                                         }
1118                                         break;
1119                                 case subtitle_region::bpp8:  // completely untested.. i never seen 8bit DVB subtitles
1120 //                                      eDebug("8BPP");
1121                                         if (clut)
1122                                                 entries = clut->entries_8bit;
1123                                         memset(palette, 0, 256*sizeof(gRGB));
1124                                         for (int i=0; i < 256; ++i)
1125                                         {
1126                                                 switch (i & 17)
1127                                                 {
1128                                                 case 0: // b1 == 0 && b5 == 0
1129                                                         if (!(i & 14)) // b2 == 0 && b3 == 0 && b4 == 0
1130                                                         {
1131                                                                 if (!(i & 224)) // b6 == 0 && b7 == 0 && b8 == 0
1132                                                                         palette[i].a = 0xFF;
1133                                                                 else
1134                                                                 {
1135                                                                         if (i & 128) // R = 100% x b8
1136                                                                                 palette[i].r = 0xFF;
1137                                                                         if (i & 64) // G = 100% x b7
1138                                                                                 palette[i].g = 0xFF;
1139                                                                         if (i & 32) // B = 100% x b6
1140                                                                                 palette[i].b = 0xFF;
1141                                                                         palette[i].a = 0xBF; // T = 75%
1142                                                                 }
1143                                                                 break;
1144                                                         }
1145                                                         // fallthrough !!
1146                                                 case 16: // b1 == 0 && b5 == 1
1147                                                         if (i & 128) // R = 33% x b8
1148                                                                 palette[i].r = 0x55;
1149                                                         if (i & 64) // G = 33% x b7
1150                                                                 palette[i].g = 0x55;
1151                                                         if (i & 32) // B = 33% x b6
1152                                                                 palette[i].b = 0x55;
1153                                                         if (i & 8) // R + 66,7% x b4
1154                                                                 palette[i].r += 0xAA;
1155                                                         if (i & 4) // G + 66,7% x b3
1156                                                                 palette[i].g += 0xAA;
1157                                                         if (i & 2) // B + 66,7% x b2
1158                                                                 palette[i].b += 0xAA;
1159                                                         if (i & 16) // needed for fall through from case 0!!
1160                                                                 palette[i].a = 0x80; // T = 50%
1161                                                         break;
1162                                                 case 1: // b1 == 1 && b5 == 0
1163                                                         palette[i].r =
1164                                                         palette[i].g =
1165                                                         palette[i].b = 0x80; // 50%
1166                                                         // fall through!!
1167                                                 case 17: // b1 == 1 && b5 == 1
1168                                                         if (i & 128) // R += 16.7% x b8
1169                                                                 palette[i].r += 0x2A;
1170                                                         if (i & 64) // G += 16.7% x b7
1171                                                                 palette[i].g += 0x2A;
1172                                                         if (i & 32) // B += 16.7% x b6
1173                                                                 palette[i].b += 0x2A;
1174                                                         if (i & 8) // R += 33% x b4
1175                                                                 palette[i].r += 0x55;
1176                                                         if (i & 4) // G += 33% x b3
1177                                                                 palette[i].g += 0x55;
1178                                                         if (i & 2) // B += 33% x b2
1179                                                                 palette[i].b += 0x55;
1180                                                         break;
1181                                                 }
1182                                         }
1183                                         break;
1184                         }
1185
1186                         int bgopacity = ePythonConfigQuery::getConfigIntValue("config.subtitles.subtitle_bgopacity");
1187                         int fontcolor = ePythonConfigQuery::getConfigIntValue("config.subtitles.subtitle_fontcolor");
1188                         for (int i=0; i<clut_size; ++i)
1189                         {
1190                                 if (entries && entries[i].valid)
1191                                 {
1192                                         int y = entries[i].Y,
1193                                                 cr = entries[i].Cr,
1194                                                 cb = entries[i].Cb;
1195                                         if (y > 0)
1196                                         {
1197                                                 y -= 16;
1198                                                 cr -= 128;
1199                                                 cb -= 128;
1200
1201                                                 if (fontcolor == FONTCOLOR_WHITE || fontcolor == FONTCOLOR_BLACK)
1202                                                 {
1203                                                         cr = 0;
1204                                                         cb = 0;
1205                                                 }
1206
1207                                                 palette[i].r = MAX(MIN(((298 * y            + 460 * cr) / 256), 255), 0);
1208                                                 palette[i].g = MAX(MIN(((298 * y -  55 * cb - 137 * cr) / 256), 255), 0);
1209                                                 palette[i].b = MAX(MIN(((298 * y + 543 * cb           ) / 256), 255), 0);
1210                                                 switch (fontcolor)
1211                                                 {
1212                                                         case FONTCOLOR_YELLOW:
1213                                                                 palette[i].b = 0;
1214                                                                 break;
1215                                                         case FONTCOLOR_GREEN:
1216                                                                 palette[i].r =
1217                                                                 palette[i].b = 0;
1218                                                                 break;
1219                                                         case FONTCOLOR_CYAN:
1220                                                                 palette[i].r = 0;
1221                                                                 break;
1222                                                         case FONTCOLOR_BLUE:
1223                                                                 palette[i].r =
1224                                                                 palette[i].g = 0;
1225                                                                 break;
1226                                                         case FONTCOLOR_MAGNETA:
1227                                                                 palette[i].g = 0;
1228                                                                 break;
1229                                                         case FONTCOLOR_RED:
1230                                                                 palette[i].g =
1231                                                                 palette[i].b = 0;
1232                                                                 break;
1233                                                         case FONTCOLOR_BLACK:
1234                                                                 palette[i].r = 255 - palette[i].r;
1235                                                                 palette[i].g = 255 - palette[i].g;
1236                                                                 palette[i].b = 255 - palette[i].b;
1237                                                                 break;
1238
1239                                                         default:
1240                                                                 break;
1241                                                 }
1242                                                 if (bgopacity)
1243                                                 {
1244                                                         if (palette[i].r || palette[i].g || palette[i].b)
1245                                                                 palette[i].a = (entries[i].T) & 0xFF;
1246                                                         else
1247                                                                 palette[i].a = bgopacity;
1248                                                 }
1249                                                 else
1250                                                         palette[i].a = 0x1;
1251
1252                                                 if (fontcolor == FONTCOLOR_BLACK)
1253                                                 {
1254                                                         if (bgopacity)
1255                                                         {
1256                                                                 if (255 - palette[i].r || 255 - palette[i].g || 255 - palette[i].b)
1257                                                                         palette[i].a = (entries[i].T) & 0xFF;
1258                                                                 else
1259                                                                         palette[i].a = bgopacity;
1260                                                         }
1261                                                         else
1262                                                                 palette[i].a = 0x1;
1263                                                 }
1264
1265 //                                              eDebug("override clut entry %d RGBA %02x%02x%02x%02x", i,
1266 //                                                      palette[i].r, palette[i].g, palette[i].b, palette[i].a);
1267                                         }
1268                                         else
1269                                         {
1270 //                                              eDebug("mist %d: y %d cr %d cb %d", i, y, cr, cb);
1271                                                 palette[i].r = 0;
1272                                                 palette[i].g = 0;
1273                                                 palette[i].b = 0;
1274                                                 palette[i].a = 0xFF;
1275                                         }
1276                                 }
1277 //                              eDebug("%d:%c %02x %02x %02x %02x",
1278 //                                      i, entries && entries[i].valid ? 'O': 'D', palette[i].r, palette[i].g, palette[i].b, palette[i].a);
1279                         }
1280
1281 //                      eDebug("commit buffer %p", &(*reg->buffer));
1282                         eDVBSubtitleRegion Region;
1283                         Region.m_pixmap = reg->buffer;
1284                         Region.m_position.setX(x0);
1285                         Region.m_position.setY(y0);
1286                         Page.m_regions.push_back(Region);
1287                         reg->committed = true;
1288                 }
1289 //              else
1290 //                      eDebug("region not found");
1291         }
1292         Page.m_display_size = m_display_size;
1293         m_new_subtitle_page(Page);
1294         Page.m_regions.clear();
1295 //      eDebug("page timeout is %d", page->page_time_out);
1296 //      Page.m_show_time += (page->page_time_out * 90000);
1297 //      m_new_subtitle_page(Page);
1298 //      eDebug("schon gut.");
1299 }
1300
1301 DEFINE_REF(eDVBSubtitleParser);
1302
1303 eDVBSubtitleParser::eDVBSubtitleParser(iDVBDemux *demux)
1304         :m_pages(0), m_display_size(720,576)
1305 {
1306         setStreamID(0xBD);
1307
1308         if (demux->createPESReader(eApp, m_pes_reader))
1309                 eDebug("failed to create dvb subtitle PES reader!");
1310         else
1311                 m_pes_reader->connectRead(slot(*this, &eDVBSubtitleParser::processData), m_read_connection);
1312 }
1313
1314 eDVBSubtitleParser::~eDVBSubtitleParser()
1315 {
1316         subtitle_reset();
1317 }
1318
1319 int eDVBSubtitleParser::stop()
1320 {
1321         if (m_pes_reader)
1322         {
1323                 eDebug("disable dvb subtitles");
1324                 return m_pes_reader->stop();
1325         }
1326         return -1;
1327 }
1328
1329 int eDVBSubtitleParser::start(int pid, int composition_page_id, int ancillary_page_id)
1330 {
1331         if (m_pes_reader)
1332         {
1333                 eDebug("start dvb subtitles on pid 0x%04x with composition_page_id %d and ancillary_page_id %d",
1334                         pid, composition_page_id, ancillary_page_id);
1335                 m_composition_page_id = composition_page_id;
1336                 m_ancillary_page_id = ancillary_page_id;
1337                 return m_pes_reader->start(pid);
1338         }
1339         return -1;
1340 }
1341
1342 void eDVBSubtitleParser::connectNewPage(const Slot1<void, const eDVBSubtitlePage&> &slot, ePtr<eConnection> &connection)
1343 {
1344         connection = new eConnection(this, m_new_subtitle_page.connect(slot));
1345 }