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