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