more work on dvb subtitles (not finished/working yet)
[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(struct 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(struct 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(struct subtitle_page *page, int object_id, int line, __u8 *data, int len)
58 {
59         struct subtitle_region *region = page->regions;
60 //      eDebug("line for %d:%d", page->page_id, object_id);
61         while (region)
62         {
63                 struct 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(struct 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         struct 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         struct 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                                 struct 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                 struct 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                         struct 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                 struct 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                         struct subtitle_region_object *objects = region->region_objects;
434                         while (objects)
435                         {
436                                 struct 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                 struct subtitle_region_object **pobject = &region->region_objects;
504
505                 while (processed_length < segment_length)
506                 {
507
508                         struct subtitle_region_object *object;
509
510                         object = new subtitle_region_object;
511
512                         *pobject = object;
513                         object->next = 0;
514                         pobject = &object->next;
515
516                         object->object_id  = *segment++ << 8;
517                         object->object_id |= *segment++; processed_length += 2;
518
519                         object->object_type = *segment >> 6;
520                         object->object_provider_flag = (*segment >> 4) & 3;
521                         object->object_horizontal_position  = (*segment++ & 0xF) << 8;
522                         object->object_horizontal_position |= *segment++;
523                         processed_length += 2;
524
525                         object->object_vertical_position  = *segment++ << 8;
526                         object->object_vertical_position |= *segment++ ;
527                         processed_length += 2;
528
529                         if ((object->object_type == 1) || (object->object_type == 2))
530                         {
531                                 object->foreground_pixel_value = *segment++;
532                                 object->background_pixel_value = *segment++;
533                                 processed_length += 2;
534                         }
535                 }
536
537                 if (processed_length != segment_length)
538                         eDebug("too less data! (%d < %d)", segment_length, processed_length);
539
540                 break;
541         }
542         case 0x12: // CLUT definition segment
543         {
544                 int CLUT_id, CLUT_version_number;
545                 struct subtitle_clut *clut, **pclut;
546
547                 if (!page)
548                         break;
549
550                 //eDebug("CLUT: %02x", *segment);
551                 CLUT_id = *segment++;
552
553                 CLUT_version_number = *segment++ >> 4;
554                 processed_length += 2;
555
556                 //eDebug("page %d, CLUT %02x, version %d", page->page_id, CLUT_id, CLUT_version_number);
557
558                 clut = page->cluts; pclut = &page->cluts;
559
560                 while (clut)
561                 {
562                         if (clut->clut_id == CLUT_id)
563                                 break;
564                         pclut = &clut->next;
565                         clut = clut->next;
566                 }
567
568                 if (!clut)
569                 {
570                         *pclut = clut = new subtitle_clut;
571                         clut->next = 0;
572                         clut->clut_id = CLUT_id;
573                 }
574                 else if (clut->CLUT_version_number == CLUT_version_number)
575                         break;
576
577                 clut->CLUT_version_number=CLUT_version_number;
578                 clut->size_2 = clut->size_4 = clut->size_8 = 0;
579
580                         /* invalidate CLUT if updated. */
581                 if ((this->current_clut_page_id == page_id) && (this->current_clut_id == CLUT_id))
582                         this->current_clut_id = -1;
583
584                 //eDebug("new clut");
585                 while (processed_length < segment_length)
586                 {
587                         int CLUT_entry_id, entry_CLUT_flag, full_range;
588                         int v_Y, v_Cr, v_Cb, v_T;
589
590                         CLUT_entry_id = *segment++;
591                         full_range = *segment & 1;
592                         entry_CLUT_flag = (*segment++ & 0xE0) >> 5;
593                         processed_length += 2;
594
595                         if (full_range)
596                         {
597                                 v_Y  = *segment++;
598                                 v_Cr = *segment++;
599                                 v_Cb = *segment++;
600                                 v_T  = *segment++;
601                                 processed_length += 4;
602                         } else
603                         {
604                                 v_Y   = *segment & 0xFC;
605                                 v_Cr  = (*segment++ & 3) << 6;
606                                 v_Cr |= (*segment & 0xC0) >> 2;
607                                 v_Cb  = (*segment & 0x3C) << 2;
608                                 v_T   = (*segment++ & 3) << 6;
609                                 processed_length += 2;
610                         }
611
612                         if (entry_CLUT_flag & 1) // 8bit
613                         {
614                                 ASSERT(CLUT_entry_id < 256);
615                                 ++clut->size_8;
616                                 clut->entries_8bit[CLUT_entry_id].Y = v_Y;
617                                 clut->entries_8bit[CLUT_entry_id].Cr = v_Cr;
618                                 clut->entries_8bit[CLUT_entry_id].Cb = v_Cb;
619                                 clut->entries_8bit[CLUT_entry_id].T = v_T;
620                         }
621                         if (entry_CLUT_flag & 2) // 4bit
622                         {
623                                 ASSERT(CLUT_entry_id < 16);
624                                 ++clut->size_4;
625                                 clut->entries_4bit[CLUT_entry_id].Y = v_Y;
626                                 clut->entries_4bit[CLUT_entry_id].Cr = v_Cr;
627                                 clut->entries_4bit[CLUT_entry_id].Cb = v_Cb;
628                                 clut->entries_4bit[CLUT_entry_id].T = v_T;
629                         }
630                         if (entry_CLUT_flag & 4) // 2bit
631                         {
632                                 ASSERT(CLUT_entry_id < 4);
633                                 ++clut->size_2;
634                                 clut->entries_2bit[CLUT_entry_id].Y = v_Y;
635                                 clut->entries_2bit[CLUT_entry_id].Cr = v_Cr;
636                                 clut->entries_2bit[CLUT_entry_id].Cb = v_Cb;
637                                 clut->entries_2bit[CLUT_entry_id].T = v_T;
638                         }
639                         //eDebug("  %04x %02x %02x %02x %02x", CLUT_entry_id, v_Y, v_Cb, v_Cr, v_T);
640                 }
641                 break;
642         }
643         case 0x13: // object data segment
644         {
645                 int object_id, object_version_number, object_coding_method, non_modifying_color_flag;
646
647                 object_id  = *segment++ << 8;
648                 object_id |= *segment++;
649                 processed_length += 2;
650
651                 object_version_number = *segment >> 4;
652                 object_coding_method  = (*segment >> 2) & 3;
653                 non_modifying_color_flag = (*segment++ >> 1) & 1;
654                 processed_length++;
655
656                 //eDebug("object id %04x, version %d, object_coding_method %d (page_id %d)", object_id, object_version_number, object_coding_method, page_id);
657
658                 if (object_coding_method == 0)
659                 {
660                         int top_field_data_blocklength, bottom_field_data_blocklength;
661                         int i, line, linep;
662
663                         top_field_data_blocklength  = *segment++ << 8;
664                         top_field_data_blocklength |= *segment++;
665
666                         bottom_field_data_blocklength  = *segment++ << 8;
667                         bottom_field_data_blocklength |= *segment++;
668                         //eDebug("%d / %d bytes", top_field_data_blocklength, bottom_field_data_blocklength);
669                         processed_length += 4;
670
671                         i = 0;
672                         line = 0;
673                         linep = 0;
674                         while (i < top_field_data_blocklength)
675                         {
676                                 int len;
677                                 len = subtitle_process_pixel_data(page, object_id, &line, &linep, segment);
678                                 if (len < 0)
679                                         return -1;
680                                 segment += len;
681                                 processed_length += len;
682                                 i += len;
683                         }
684
685                         line = 1;
686                         linep = 0;
687
688                         if (bottom_field_data_blocklength)
689                         {
690                                 i = 0;
691                                 while (i < bottom_field_data_blocklength)
692                                 {
693                                         int len;
694                                         len = subtitle_process_pixel_data(page, object_id, &line, &linep, segment);
695                                         if (len < 0)
696                                                 return -1;
697                                         segment += len;
698                                         processed_length += len;
699                                         i += len;
700                                 }
701                         }
702                         else if (top_field_data_blocklength)
703                                 eDebug("!!!! unimplemented: no bottom field! (%d : %d)", top_field_data_blocklength, bottom_field_data_blocklength);
704
705                         if ((top_field_data_blocklength + bottom_field_data_blocklength) & 1)
706                         {
707                                 segment++; processed_length++;
708                         }
709                 }
710                 else if (object_coding_method == 1)
711                         eDebug("---- object_coding_method 1 unsupported!");
712
713                 break;
714         }
715         case 0x80: // end of display set segment
716         {
717 //              eDebug("end of display set segment");
718                 subtitle_redraw_all();
719         }
720         case 0xFF: // stuffing
721                 break;
722         default:
723                 eDebug("unhandled segment type %02x", segment_type);
724         }
725
726         return segment_length + 6;
727 }
728
729 void eDVBSubtitleParser::subtitle_process_pes(__u8 *pkt, int len)
730 {
731         eDebug("subtitle_process_pes");
732         if (!extract_pts(show_time, pkt))
733         {
734                 pkt += 6; len -= 6;
735                 // skip PES header
736                 pkt++; len--;
737                 pkt++; len--;
738
739                 int hdr_len = *pkt++; len--;
740
741                 pkt+=hdr_len; len-=hdr_len;
742
743                 if (*pkt != 0x20)
744                 {
745                         //eDebug("data identifier is 0x%02x, but not 0x20", *pkt);
746                         return;
747                 }
748                 pkt++; len--; // data identifier
749                 *pkt++; len--; // stream id;
750
751                 if (len <= 0)
752                 {
753                         //eDebug("no data left (%d)", len);
754                         return;
755                 }
756
757                 while (len && *pkt == 0x0F)
758                 {
759                         int l = subtitle_process_segment(pkt);
760                         if (l < 0)
761                                 break;
762                         pkt += l;
763                         len -= l;
764                 }
765         //      if (len && *pkt != 0xFF)
766         //              eDebug("strange data at the end");
767         }
768         else
769                 eDebug("dvb subtitle packet without PTS.. ignore!!");
770 }
771
772 void eDVBSubtitleParser::subtitle_clear_screen()
773 {
774                 /* clear bbox */
775         int y;
776
777         //eDebug("BBOX clear %d:%d -> %d:%d", this->bbox_left, this->bbox_top, this->bbox_right, this->bbox_bottom);
778
779         // do not draw when anyone has locked the
780         // framebuffer ( non enigma plugins... )
781         this->bbox_right = 720;
782         if (this->bbox_right > this->bbox_left)
783                 for (y=this->bbox_top; y < this->bbox_bottom; ++y)
784                         ; // TODO fixmee clear subtitle screen
785
786         this->bbox_right = 0;
787         this->bbox_left = this->screen_width;
788         this->bbox_top = this->screen_height;
789         this->bbox_bottom = 0;
790 }
791
792 void eDVBSubtitleParser::subtitle_redraw_all()
793 {
794 #if 1
795         struct subtitle_page *page = this->pages;
796         if ( page )
797         {
798                 struct subtitle_page_region *region = page->page_regions;
799                 if ( region )
800                         subtitle_clear_screen();
801         }
802         while(page)
803         {
804                 subtitle_redraw(page->page_id);
805                 page = page->next;
806         }
807 #else
808         subtitle_clear_screen();
809
810         struct subtitle_page *page = this->pages;
811         //eDebug("----------- end of display set");
812         //eDebug("active pages:");
813         while (page)
814         {
815                 //eDebug("  page_id %02x", page->page_id);
816                 //eDebug("  page_version_number: %d", page->page_version_number);
817                 //eDebug("  active regions:");
818                 {
819                         struct subtitle_page_region *region = page->page_regions;
820                         while (region)
821                         {
822                                 //eDebug("    region_id: %04x", region->region_id);
823                                 //eDebug("    region_horizontal_address: %d", region->region_horizontal_address);
824                                 //eDebug("    region_vertical_address: %d", region->region_vertical_address);
825
826                                 region = region->next;
827                         }
828                 }
829
830                 subtitle_redraw(page->page_id);
831                 //eDebug("defined regions:");
832                 struct subtitle_region *region = page->regions;
833                 while (region)
834                 {
835                         //eDebug("  region_id %04x, version %d, %dx%d", region->region_id, region->region_version_number, region->region_width, region->region_height);
836
837                         struct subtitle_region_object *object = region->region_objects;
838                         while (object)
839                         {
840                                 //eDebug("  object %02x, type %d, %d:%d", object->object_id, object->object_type, object->object_horizontal_position, object->object_vertical_position);
841                                 object = object->next;
842                         }
843                         region = region->next;
844                 }
845                 page = page->next;
846         }
847 #endif
848 }
849
850 void eDVBSubtitleParser::subtitle_reset()
851 {
852         while (struct subtitle_page *page = this->pages)
853         {
854                         /* free page regions */
855                 while (page->page_regions)
856                 {
857                         struct subtitle_page_region *p = page->page_regions->next;
858                         delete page->page_regions;
859                         page->page_regions = p;
860                 }
861                         /* free regions */
862                 while (page->regions)
863                 {
864                         struct subtitle_region *region = page->regions;
865
866                         while (region->region_objects)
867                         {
868                                 struct subtitle_region_object *obj = region->region_objects;
869                                 region->region_objects = obj->next;
870                                 delete obj;
871                         }
872
873                         if (region->region_buffer)
874                         {
875                                 if (region->region_buffer->surface)
876                                         delete region->region_buffer->surface;
877                                 region->region_buffer=0;
878                         }
879
880                         page->regions = region->next;
881                         delete region;
882                 }
883
884                         /* free CLUTs */
885                 while (page->cluts)
886                 {
887                         struct subtitle_clut *clut = page->cluts;
888                         page->cluts = clut->next;
889                         delete clut;
890                 }
891
892                 this->pages = page->next;
893                 delete page;
894         }
895 }
896
897 void eDVBSubtitleParser::subtitle_redraw(int page_id)
898 {
899         struct subtitle_page *page = this->pages;
900
901         //eDebug("displaying page id %d", page_id);
902
903         while (page)
904         {
905                 if (page->page_id == page_id)
906                         break;
907                 page = page->next;
908         }
909         if (!page)
910         {
911                 //eDebug("page not found");
912                 return;
913         }
914
915
916         //eDebug("iterating regions..");
917                 /* iterate all regions in this pcs */
918         struct subtitle_page_region *region = page->page_regions;
919         while (region)
920         {
921                 //eDebug("region %d", region->region_id);
922                         /* find corresponding region */
923                 struct subtitle_region *reg = page->regions;
924                 while (reg)
925                 {
926                         if (reg->region_id == region->region_id)
927                                 break;
928                         reg = reg->next;
929                 }
930                 if (reg)
931                 {
932                         int y;
933                         //eDebug("copy region %d to %d, %d", region->region_id, region->region_horizontal_address, region->region_vertical_address);
934
935                         int x0 = region->region_horizontal_address;
936                         int y0 = region->region_vertical_address;
937                         int x1 = x0 + reg->region_width;
938                         int y1 = y0 + reg->region_height;
939
940                         if ((x0 < 0) || (y0 < 0) || (x0 > this->screen_width) || (x0 > this->screen_height))
941                                 continue;
942
943                                 /* adjust bbox */
944                         if (x0 < this->bbox_left)
945                                 this->bbox_left = x0;
946                         if (y0 < this->bbox_top)
947                                 this->bbox_top = y0;
948                         if (x1 > this->bbox_right)
949                                 this->bbox_right = x1;
950                         if (y1 > this->bbox_bottom)
951                                 this->bbox_bottom = y1;
952
953                         int timeout = page->page_time_out;
954
955                         /* find corresponding clut */
956                         struct subtitle_clut *clut = page->cluts;
957                         while (clut)
958                         {
959                         //eDebug("have %d, want %d", clut->clut_id, main_clut_id);
960                                 if (clut->clut_id == reg->clut_id)
961                                         break;
962                                 clut = clut->next;
963                         }
964                         if (clut)
965                         {
966                                 // TODO fill region->surface->clut !!!!!
967                         }
968                         else
969                         {
970                                 // apply default clut depending on region->region_depth
971                                 // TODO fill region->surface->clut !!!!!
972                         }
973                         // TODO Blit Region Pixmap !!!
974                         eDebug("blit region");
975                 }
976                 else
977                         eDebug("region not found");
978                 region = region->next;
979         }
980         //eDebug("schon gut.");
981 }
982
983 DEFINE_REF(eDVBSubtitleParser);
984
985 eDVBSubtitleParser::eDVBSubtitleParser(iDVBDemux *demux)
986 {
987         setStreamID(0xBD);
988
989         if (demux->createPESReader(eApp, m_pes_reader))
990                 eDebug("failed to create dvb subtitle PES reader!");
991         else
992                 m_pes_reader->connectRead(slot(*this, &eDVBSubtitleParser::processData), m_read_connection);
993 }
994
995 eDVBSubtitleParser::~eDVBSubtitleParser()
996 {
997         subtitle_reset();
998 }
999
1000 int eDVBSubtitleParser::start(int pid)
1001 {
1002 #if 0
1003         eDebug("eDVBSubtitleParser::start(%04x)", pid);
1004         if (m_pes_reader)
1005                 return m_pes_reader->start(pid);
1006         else
1007                 return -1;
1008 #endif
1009 }
1010
1011 void eDVBSubtitleParser::connectNewRegion(const Slot1<void, const eDVBSubtitleRegion&> &slot, ePtr<eConnection> &connection)
1012 {
1013         connection = new eConnection(this, m_new_subtitle_region.connect(slot));
1014 }