1 /*
2  * Copyright (C) 2010-2020 the xine project
3  *
4  * This file is part of xine, a free video player.
5  *
6  * xine is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * xine is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19  *
20  * DVB Subtitle decoder (ETS 300 743)
21  * (c) 2004 Mike Lampard <mlampard@users.sourceforge.net>
22  * based on the application dvbsub by Dave Chapman
23  *
24  * TODO:
25  * - Implement support for teletext based subtitles
26  */
27 
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31 
32 #include <time.h>
33 #include <pthread.h>
34 #include <errno.h>
35 
36 /*#define LOG*/
37 #define LOG_MODULE "spudvb"
38 
39 #include <xine/xine_internal.h>
40 #include <xine/spu.h>
41 #include <xine/osd.h>
42 
43 #include "xine-engine/bswap.h"
44 
45 #define MAX_REGIONS 16
46 
47 #define SPU_MAX_WIDTH 1920
48 #define SPU_MAX_HEIGHT 1080
49 
50 /* sparse_array - handle large arrays efficiently when only a few entries are used */
51 
52 typedef struct {
53   uint32_t key, value;
54 } sparse_array_entry_t;
55 
56 typedef struct {
57   uint32_t sorted_entries, used_entries, max_entries;
58   sparse_array_entry_t *entries;
59 } sparse_array_t;
60 
sparse_array_new(sparse_array_t * sa)61 static void sparse_array_new (sparse_array_t *sa) {
62   sa->sorted_entries =
63   sa->used_entries   =
64   sa->max_entries    = 0;
65   sa->entries        = NULL;
66 }
67 
sparse_array_delete(sparse_array_t * sa)68 static void sparse_array_delete (sparse_array_t *sa) {
69   sa->sorted_entries =
70   sa->used_entries   =
71   sa->max_entries    = 0;
72   _x_freep (&sa->entries);
73 }
74 
_sparse_array_find(sparse_array_t * sa,uint32_t key,uint32_t * pos)75 static int _sparse_array_find (sparse_array_t *sa, uint32_t key, uint32_t *pos) {
76   uint32_t b = 0, m, e = sa->sorted_entries, l = e, k;
77   while (1) {
78     m = (b + e) >> 1;
79     if (m == l)
80       break;
81     l = m;
82     k = sa->entries[m].key;
83     if (k > key)
84       e = m;
85     else if (k < key)
86       b = m;
87     else {
88       *pos = m;
89       return 1;
90     }
91   }
92   *pos = e;
93   return 0;
94 }
95 
_sparse_array_sort(sparse_array_t * sa)96 static void _sparse_array_sort (sparse_array_t *sa) {
97   uint32_t left = sa->max_entries - sa->used_entries;
98   /* move unsorted part to end of buf */
99   uint32_t i = left + sa->sorted_entries;
100   memmove (sa->entries + i, sa->entries + sa->sorted_entries,
101     (sa->used_entries - sa->sorted_entries) * sizeof (sparse_array_entry_t));
102   /* iterate it */
103   while (i < sa->max_entries) {
104     uint32_t j, pos, startkey, stopkey, lastkey;
105     startkey = sa->entries[i].key;
106     if (_sparse_array_find (sa, startkey, &pos)) {
107       /* eliminate duplicate */
108       sa->entries[pos].value = sa->entries[i].value;
109       i++;
110       continue;
111     }
112     /* find sorted range */
113     stopkey = pos < sa->sorted_entries ? sa->entries[pos].key : 0xffffffff;
114     lastkey = startkey;
115     for (j = i + 1; j < sa->max_entries; j++) {
116       uint32_t thiskey = sa->entries[j].key;
117       if ((thiskey <= lastkey) || (thiskey >= stopkey))
118         break;
119       lastkey = thiskey;
120     }
121     j -= i;
122     if (j > left)
123       j = left;
124     /* insert it */
125     if (pos < sa->sorted_entries)
126       memmove (sa->entries + pos + j, sa->entries + pos,
127         (sa->sorted_entries - pos) * sizeof (sparse_array_entry_t));
128     memcpy (sa->entries + pos, sa->entries + i, j * sizeof (sparse_array_entry_t));
129     sa->sorted_entries += j;
130     i += j;
131   }
132   sa->used_entries = sa->sorted_entries;
133   lprintf ("sparse_array_sort: %u entries\n", (unsigned int)sa->used_entries);
134 }
135 
sparse_array_set(sparse_array_t * sa,uint32_t key,uint32_t value)136 static int sparse_array_set (sparse_array_t *sa, uint32_t key, uint32_t value) {
137   /* give some room for later sorting too */
138   if (!sa->entries || (sa->used_entries + 8 >= sa->max_entries)) {
139     uint32_t n = sa->max_entries + 128;
140     sparse_array_entry_t *se = realloc (sa->entries, n * sizeof (sparse_array_entry_t));
141     if (!se)
142       return 0;
143     sa->max_entries = n;
144     sa->entries = se;
145   }
146   sa->entries[sa->used_entries].key = key;
147   sa->entries[sa->used_entries++].value = value;
148   return 1;
149 }
150 
sparse_array_get(sparse_array_t * sa,uint32_t key,uint32_t * value)151 static int sparse_array_get (sparse_array_t *sa, uint32_t key, uint32_t *value) {
152   uint32_t pos;
153   if (sa->sorted_entries != sa->used_entries)
154     _sparse_array_sort (sa);
155   if (!_sparse_array_find (sa, key, &pos))
156     return 0;
157   *value = sa->entries[pos].value;
158   return 1;
159 }
160 
sparse_array_unset(sparse_array_t * sa,uint32_t key,uint32_t mask)161 static void sparse_array_unset (sparse_array_t *sa, uint32_t key, uint32_t mask) {
162   sparse_array_entry_t *here = sa->entries, *p = NULL, *q = sa->entries;
163   uint32_t i, n = 0;
164   if (sa->sorted_entries != sa->used_entries)
165     _sparse_array_sort (sa);
166   key &= mask;
167   for (i = sa->used_entries; i > 0; i--) {
168     if ((here->key & mask) == key) {
169       if (p) {
170         n = here - p;
171         if (n && (p != q))
172           memmove (q, p, n * sizeof (sparse_array_entry_t));
173         p = NULL;
174         q += n;
175       }
176     } else {
177       if (!p)
178         p = here;
179     }
180     here++;
181   }
182   if (p) {
183     n = here - p;
184     if (n && (p != q))
185       memmove (q, p, n * sizeof (sparse_array_entry_t));
186     q += n;
187   }
188   sa->sorted_entries =
189   sa->used_entries   = q - sa->entries;
190 }
191 
192 /* ! sparse_array */
193 
194 typedef struct {
195   uint16_t              x, y;
196   unsigned char         is_visible;
197 } visible_region_t;
198 
199 typedef struct {
200   uint8_t               page_time_out;
201   uint8_t               page_version_number;
202   uint8_t               page_state;
203   uint16_t              page_id;
204   visible_region_t      regions[MAX_REGIONS];
205 } page_t;
206 
207 typedef struct {
208   uint8_t               version_number;
209   uint8_t               empty;
210   uint8_t               depth;
211   uint8_t               CLUT_id;
212   uint16_t              width, height;
213   unsigned char         *img;
214   osd_object_t          *osd;
215 } region_t;
216 
217 typedef union {
218   clut_t   c;
219   uint32_t u32;
220 } clut_union_t;
221 
222 typedef struct {
223   uint8_t  version_number;
224   uint8_t  windowed;
225   uint16_t width;
226   uint16_t height;
227   /* window, TODO */
228   /* uint16_t x0, x1, y0, y1; */
229 } dds_t;
230 
231 typedef struct {
232 /* dvbsub stuff */
233   int                   x;
234   int                   y;
235   unsigned int          curr_obj;
236   unsigned int          curr_reg[64];
237   uint8_t              *buf;
238   int                   i;
239   int                   i_bits;
240   int                   compat_depth;
241   unsigned int          max_regions;
242   page_t                page;
243   dds_t                 dds;
244   region_t              regions[MAX_REGIONS];
245   clut_union_t          colours[MAX_REGIONS*256];
246   unsigned char         trans[MAX_REGIONS*256];
247   struct {
248     unsigned char         lut24[4], lut28[4], lut48[16];
249   }                     lut[MAX_REGIONS];
250   sparse_array_t        object_pos;
251 } dvbsub_func_t;
252 
253 typedef struct dvb_spu_decoder_s {
254   spu_decoder_t spu_decoder;
255 
256   xine_stream_t        *stream;
257 
258   spu_dvb_descriptor_t spu_descriptor;
259 
260   /* dvbsub_osd_mutex should be locked around all calls to this->osd_renderer->show()
261      and this->osd_renderer->hide() */
262   pthread_mutex_t       dvbsub_osd_mutex;
263 
264   char                 *pes_pkt_wrptr;
265   unsigned int          pes_pkt_size;
266 
267   int64_t               vpts;
268 
269   pthread_t             dvbsub_timer_thread;
270   struct timespec       dvbsub_hide_timeout;
271   pthread_cond_t        dvbsub_restart_timeout;
272   dvbsub_func_t         dvbsub;
273   int                   show;
274 
275   char                  pes_pkt[65 * 1024];
276 
277 } dvb_spu_decoder_t;
278 
reset_clut(dvbsub_func_t * dvbsub)279 static void reset_clut (dvbsub_func_t *dvbsub)
280 {
281   // XXX This function is called only from spudec_reset().
282   // - would it be enough to just zero out these entries as when opening the decoder ... ?
283   unsigned int i, r;
284   unsigned char default_trans[256];
285   clut_t default_clut[256];
286 
287 #define YUVA(r, g, b, a) (clut_t) { COMPUTE_V(r, g, b), COMPUTE_U(r, g, b), COMPUTE_V(r, g, b), a }
288 #define GETBIT(s, v1, v2, tr) \
289     r = s + ((i & 1) ? v1 : 0) + ((i & 0x10) ? v2 : 0); \
290     g = s + ((i & 2) ? v1 : 0) + ((i & 0x20) ? v2 : 0); \
291     b = s + ((i & 4) ? v1 : 0) + ((i & 0x40) ? v2 : 0); \
292     a = tr
293 
294   default_clut[0] = YUVA(0, 0, 0, 0);
295   for (i = 1; i < 256; i++) {
296     uint8_t r, g, b, a;
297     if (i < 8) {
298       GETBIT(0, 255, 0, 63);
299     } else switch (i & 0x88) {
300       case 0x00: GETBIT(  0, 85, 170, 255); break;
301       case 0x08: GETBIT(  0, 85, 170, 127); break;
302       case 0x80: GETBIT(127, 43,  85, 255); break;
303       default  : GETBIT(  0, 43,  85, 255); break;
304       }
305     default_trans[i] = a;
306     default_clut[i] = YUVA(r, g, b, a);
307   }
308 
309   /* Reset the colour LUTs */
310   for (r = 0; r < MAX_REGIONS; ++r)
311   {
312     memcpy (dvbsub->colours + r * 256, default_clut, sizeof (default_clut));
313     memcpy (dvbsub->trans + r * 256, default_trans, sizeof (default_trans));
314   }
315 
316   /* Reset the colour index LUTs */
317   for (r = 0; r < MAX_REGIONS; ++r)
318   {
319     dvbsub->lut[r].lut24[0] = 0x0;
320     dvbsub->lut[r].lut24[1] = 0x7;
321     dvbsub->lut[r].lut24[2] = 0x8;
322     dvbsub->lut[r].lut24[3] = 0xF;
323     dvbsub->lut[r].lut28[0] = 0x00;
324     dvbsub->lut[r].lut28[1] = 0x77;
325     dvbsub->lut[r].lut28[2] = 0x88;
326     dvbsub->lut[r].lut28[3] = 0xFF;
327     for (i = 0; i < 16; ++i)
328       dvbsub->lut[r].lut48[i] = i | i << 4;
329   }
330 }
331 
update_region(region_t * reg,int region_id,int region_width,int region_height,int fill,int fill_color)332 static void update_region (region_t *reg, int region_id, int region_width, int region_height, int fill, int fill_color)
333 {
334   /* reject invalid sizes and set some limits ! */
335   if ( region_width<=0 || region_height<=0 || region_width>SPU_MAX_WIDTH || region_height>SPU_MAX_HEIGHT ) {
336     _x_freep( &reg->img );
337     lprintf("rejected region %d = %dx%d\n", region_id, region_width, region_height );
338     return;
339   }
340 
341   if ( reg->width*reg->height<region_width*region_height ) {
342     lprintf("update size of region %d = %dx%d\n", region_id, region_width, region_height);
343     _x_freep( &reg->img );
344   }
345 
346   if ( !reg->img ) {
347     if ( !(reg->img = calloc(1, region_width * region_height)) ) {
348       lprintf( "can't allocate mem for region %d\n", region_id );
349       return;
350     }
351     fill = 1;
352   }
353 
354   if ( fill ) {
355     memset( reg->img, fill_color, region_width*region_height );
356     reg->empty = 1;
357     lprintf("FILL REGION %d\n", region_id);
358   }
359   reg->width = region_width;
360   reg->height = region_height;
361 }
362 
363 
do_plot(region_t * reg,int x,int y,unsigned char pixel)364 static void do_plot (region_t *reg, int x, int y, unsigned char pixel)
365 {
366   unsigned int i;
367 
368   i = (y * reg->width) + x;
369   /* do some clipping */
370   if (i < reg->width * reg->height) {
371     reg->img[i] = pixel;
372     reg->empty = 0;
373   }
374 }
375 
plot(dvbsub_func_t * dvbsub,int r,unsigned int run_length,unsigned char pixel)376 static void plot (dvbsub_func_t *dvbsub, int r, unsigned int run_length, unsigned char pixel)
377 {
378   int x2 = dvbsub->x + run_length;
379 
380   while (dvbsub->x < x2) {
381     do_plot (&dvbsub->regions[r], dvbsub->x, dvbsub->y, pixel);
382     dvbsub->x++;
383   }
384 }
385 
lookup_lut(const dvbsub_func_t * dvbsub,int r)386 static const uint8_t *lookup_lut (const dvbsub_func_t *dvbsub, int r)
387 {
388   static const uint8_t identity_lut[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
389 
390   switch (dvbsub->compat_depth)
391   {
392   case 012: return dvbsub->lut[r].lut24;
393   case 013: return dvbsub->lut[r].lut28;
394   case 023: return dvbsub->lut[r].lut48;
395   default:  return identity_lut;
396   }
397 }
398 
next_datum(dvbsub_func_t * dvbsub,int width)399 static unsigned char next_datum (dvbsub_func_t *dvbsub, int width)
400 {
401   unsigned char x = 0;
402 
403   if (!dvbsub->i_bits)
404     dvbsub->i_bits = 8;
405 
406   if (dvbsub->i_bits < width)
407   {
408     /* need to read from more than one byte; split it up */
409     width -= dvbsub->i_bits;
410     x = dvbsub->buf[dvbsub->i++] & ((1 << dvbsub->i_bits) - 1);
411     dvbsub->i_bits = 8;
412     return x << width | next_datum (dvbsub, width);
413   }
414 
415   dvbsub->i_bits = (dvbsub->i_bits - width) & 7;
416   x = (dvbsub->buf[dvbsub->i] >> dvbsub->i_bits) & ((1 << width) - 1);
417 
418   if (!dvbsub->i_bits)
419     ++dvbsub->i;
420 
421   return x;
422 }
423 
decode_2bit_pixel_code_string(dvbsub_func_t * dvbsub,int r,int n)424 static void decode_2bit_pixel_code_string (dvbsub_func_t *dvbsub, int r, int n)
425 {
426   int j;
427   const uint8_t *lut = lookup_lut (dvbsub, r);
428 
429   dvbsub->i_bits = 0;
430   j = dvbsub->i + n;
431 
432   while (dvbsub->i < j)
433   {
434     unsigned int next_bits = next_datum (dvbsub, 2);
435     unsigned int run_length;
436 
437     if (next_bits)
438     {
439       /* single pixel */
440       plot (dvbsub, r, 1, lut[next_bits]);
441       continue;
442     }
443 
444     /* switch 1 */
445     if (next_datum (dvbsub, 1) == 0)
446     {
447       /* run length, 3 to 10 pixels, colour given */
448       run_length = next_datum (dvbsub, 3);
449       plot (dvbsub, r, run_length + 3, lut[next_datum (dvbsub, 2)]);
450       continue;
451     }
452 
453     /* switch 2 */
454     if (next_datum (dvbsub, 1) == 1)
455     {
456       /* single pixel, colour 0 */
457       plot (dvbsub, r, 1, lut[0]);
458       continue;
459     }
460 
461     /* switch 3 */
462     switch (next_datum (dvbsub, 2))
463     {
464     case 0: /* end-of-string */
465       j = dvbsub->i; /* set the while cause FALSE */
466       break;
467     case 1: /* two pixels, colour 0 */
468       plot (dvbsub, r, 2, lut[0]);
469       break;
470     case 2: /* run length, 12 to 27 pixels (4-bit), colour given */
471       run_length = next_datum (dvbsub, 4);
472       plot (dvbsub, r, run_length + 12, lut[next_datum (dvbsub, 2)]);
473       break;
474     case 3: /* run length, 29 to 284 pixels (8-bit), colour given */
475       run_length = next_datum (dvbsub, 8);
476       plot (dvbsub, r, run_length + 29, lut[next_datum (dvbsub, 2)]);
477     }
478   }
479 
480   if (dvbsub->i_bits) {
481     dvbsub->i++;
482     dvbsub->i_bits = 0;
483   }
484 }
485 
decode_4bit_pixel_code_string(dvbsub_func_t * dvbsub,int r,int n)486 static void decode_4bit_pixel_code_string (dvbsub_func_t *dvbsub, int r, int n)
487 {
488   int j;
489   const uint8_t *lut = lookup_lut (dvbsub, r);
490 
491   dvbsub->i_bits = 0;
492   j = dvbsub->i + n;
493 
494   while (dvbsub->i < j)
495   {
496     unsigned int next_bits = next_datum (dvbsub, 4);
497     unsigned int run_length;
498 
499     if (next_bits)
500     {
501       /* single pixel */
502       plot (dvbsub, r, 1, lut[next_bits]);
503       continue;
504     }
505 
506     /* switch 1 */
507     if (next_datum (dvbsub, 1) == 0)
508     {
509       run_length = next_datum (dvbsub, 3);
510       if (!run_length)
511         /* end-of-string */
512         break;
513 
514       /* run length, 3 to 9 pixels, colour 0 */
515       plot (dvbsub, r, run_length + 2, lut[0]);
516       continue;
517     }
518 
519     /* switch 2 */
520     if (next_datum (dvbsub, 1) == 0)
521     {
522       /* run length, 4 to 7 pixels, colour given */
523       run_length = next_datum (dvbsub, 2);
524       plot (dvbsub, r, run_length + 4, lut[next_datum (dvbsub, 4)]);
525       continue;
526     }
527 
528     /* switch 3 */
529     switch (next_datum (dvbsub, 2))
530     {
531     case 0: /* single pixel, colour 0 */
532       plot (dvbsub, r, 1, lut[0]);
533       break;
534     case 1: /* two pixels, colour 0 */
535       plot (dvbsub, r, 2, lut[0]);
536       break;
537     case 2: /* run length, 9 to 24 pixels (4-bit), colour given */
538       run_length = next_datum (dvbsub, 4);
539       plot (dvbsub, r, run_length + 9, lut[next_datum (dvbsub, 4)]);
540       break;
541     case 3: /* run length, 25 to 280 pixels (8-bit), colour given */
542       run_length = next_datum (dvbsub, 8);
543       plot (dvbsub, r, run_length + 25, lut[next_datum (dvbsub, 4)]);
544     }
545   }
546 
547   if (dvbsub->i_bits) {
548     dvbsub->i++;
549     dvbsub->i_bits = 0;
550   }
551 }
552 
decode_8bit_pixel_code_string(dvbsub_func_t * dvbsub,int r,int n)553 static void decode_8bit_pixel_code_string (dvbsub_func_t *dvbsub, int r, int n)
554 {
555   int j;
556 
557   j = dvbsub->i + n;
558 
559   while (dvbsub->i < j)
560   {
561     unsigned int next_bits = dvbsub->buf[dvbsub->i++];
562     unsigned int run_length;
563 
564     if (next_bits)
565     {
566       /* single pixel */
567       plot (dvbsub, r, 1, next_bits);
568       continue;
569     }
570 
571     /* switch 1 */
572     run_length = dvbsub->buf[dvbsub->i] & 127;
573 
574     if (dvbsub->buf[dvbsub->i++] & 128)
575     {
576       /* run length, 3 to 127 pixels, colour given */
577       if (run_length > 2)
578         plot (dvbsub, r, run_length + 4, dvbsub->buf[dvbsub->i++]);
579       continue;
580     }
581 
582     if (!run_length)
583       /* end-of-string */
584       break;
585 
586     /* run length, 1 to 127 pixels, colour 0 */
587     plot (dvbsub, r, run_length + 2, 0);
588   }
589 }
590 
set_clut(dvbsub_func_t * dvbsub,int CLUT_id,int CLUT_entry_id,int Y_value,int Cr_value,int Cb_value,int T_value)591 static void set_clut(dvbsub_func_t *dvbsub, int CLUT_id,int CLUT_entry_id,int Y_value, int Cr_value, int Cb_value, int T_value) {
592 
593   if ((CLUT_id>=MAX_REGIONS) || (CLUT_entry_id>255)) {
594     return;
595   }
596 
597   dvbsub->colours[(CLUT_id*256)+CLUT_entry_id].c.y   = Y_value;
598   dvbsub->colours[(CLUT_id*256)+CLUT_entry_id].c.cr  = Cr_value;
599   dvbsub->colours[(CLUT_id*256)+CLUT_entry_id].c.cb  = Cb_value;
600   dvbsub->colours[(CLUT_id*256)+CLUT_entry_id].c.foo = T_value;
601 }
602 
process_CLUT_definition_segment(dvbsub_func_t * dvbsub)603 static void process_CLUT_definition_segment(dvbsub_func_t *dvbsub) {
604   int /*page_id,*/
605       segment_length,
606       CLUT_id/*,
607       CLUT_version_number*/;
608 
609   int CLUT_entry_id,
610       /*CLUT_flag_8_bit,*/
611       /*CLUT_flag_4_bit,*/
612       /*CLUT_flag_2_bit,*/
613       full_range_flag,
614       Y_value,
615       Cr_value,
616       Cb_value,
617       T_value;
618 
619   int j;
620 
621   /*page_id=(dvbsub->buf[dvbsub->i]<<8)|dvbsub->buf[dvbsub->i+1];*/ dvbsub->i+=2;
622   segment_length=(dvbsub->buf[dvbsub->i]<<8)|dvbsub->buf[dvbsub->i+1]; dvbsub->i+=2;
623   j=dvbsub->i+segment_length;
624 
625   CLUT_id=dvbsub->buf[dvbsub->i++];
626   lprintf ("process_CLUT_definition_segment: CLUT_id %d\n", CLUT_id);
627   /*CLUT_version_number=(dvbsub->buf[dvbsub->i]&0xf0)>>4;*/
628   dvbsub->i++;
629 
630   while (dvbsub->i < j) {
631     CLUT_entry_id=dvbsub->buf[dvbsub->i++];
632 
633     /*CLUT_flag_2_bit=(dvbsub->buf[dvbsub->i]&0x80)>>7;*/
634     /*CLUT_flag_4_bit=(dvbsub->buf[dvbsub->i]&0x40)>>6;*/
635     /*CLUT_flag_8_bit=(dvbsub->buf[dvbsub->i]&0x20)>>5;*/
636     full_range_flag=dvbsub->buf[dvbsub->i]&1;
637     dvbsub->i++;
638 
639     if (full_range_flag==1) {
640       Y_value=dvbsub->buf[dvbsub->i++];
641       Cr_value=dvbsub->buf[dvbsub->i++];
642       Cb_value=dvbsub->buf[dvbsub->i++];
643       T_value=dvbsub->buf[dvbsub->i++];
644     } else {
645       Y_value = dvbsub->buf[dvbsub->i] & 0xfc;
646       Cr_value = (dvbsub->buf[dvbsub->i] << 6 | dvbsub->buf[dvbsub->i + 1] >> 2) & 0xf0;
647       Cb_value = (dvbsub->buf[dvbsub->i + 1] << 2) & 0xf0;
648       T_value = (dvbsub->buf[dvbsub->i + 1] & 3) * 0x55; /* expand only this one to full range! */
649       dvbsub->i+=2;
650     }
651     set_clut(dvbsub, CLUT_id,CLUT_entry_id,Y_value,Cr_value,Cb_value,T_value);
652   }
653 }
654 
process_pixel_data_sub_block(dvbsub_func_t * dvbsub,int r,unsigned int pos,int ofs,int n)655 static void process_pixel_data_sub_block (dvbsub_func_t *dvbsub, int r, unsigned int pos, int ofs, int n)
656 {
657   int data_type;
658   int j;
659 
660   j = dvbsub->i + n;
661 
662   dvbsub->x = pos >> 16;
663   dvbsub->y = (pos & 0xffff) + ofs;
664   while (dvbsub->i < j) {
665     data_type = dvbsub->buf[dvbsub->i++];
666 
667     switch (data_type) {
668     case 0:
669       dvbsub->i++;
670     case 0x10:
671       decode_2bit_pixel_code_string (dvbsub, r, n - 1);
672       break;
673     case 0x11:
674       decode_4bit_pixel_code_string (dvbsub, r, n - 1);
675       break;
676     case 0x12:
677       decode_8bit_pixel_code_string (dvbsub, r, n - 1);
678       break;
679     case 0x20: /* 2-to-4bit colour index map */
680       /* should this be implemented since we have an 8-bit overlay? */
681       dvbsub->lut[r].lut24[0] = dvbsub->buf[dvbsub->i    ] >> 4;
682       dvbsub->lut[r].lut24[1] = dvbsub->buf[dvbsub->i    ] & 0x0f;
683       dvbsub->lut[r].lut24[2] = dvbsub->buf[dvbsub->i + 1] >> 4;
684       dvbsub->lut[r].lut24[3] = dvbsub->buf[dvbsub->i + 1] & 0x0f;
685       dvbsub->i += 2;
686       break;
687     case 0x21: /* 2-to-8bit colour index map */
688       memcpy (dvbsub->lut[r].lut28, dvbsub->buf + dvbsub->i, 4);
689       dvbsub->i += 4;
690       break;
691     case 0x22:
692       memcpy (dvbsub->lut[r].lut48, dvbsub->buf + dvbsub->i, 16);
693       dvbsub->i += 16;
694       break;
695     case 0xf0:
696       dvbsub->x = pos >> 16;
697       dvbsub->y += 2;
698       break;
699     default:
700       lprintf ("unimplemented data_type %02x in pixel_data_sub_block\n", data_type);
701     }
702   }
703 
704   dvbsub->i = j;
705 }
706 
process_page_composition_segment(dvbsub_func_t * dvbsub)707 static void process_page_composition_segment (dvbsub_func_t *dvbsub)
708 {
709   int segment_length;
710   unsigned int region_id, region_x, region_y;
711 
712   dvbsub->page.page_id = (dvbsub->buf[dvbsub->i] << 8) | dvbsub->buf[dvbsub->i + 1];
713   dvbsub->i += 2;
714   segment_length = (dvbsub->buf[dvbsub->i] << 8) | dvbsub->buf[dvbsub->i + 1];
715   dvbsub->i += 2;
716 
717   int j = dvbsub->i + segment_length;
718 
719   dvbsub->page.page_time_out = dvbsub->buf[dvbsub->i++];
720   if ( dvbsub->page.page_time_out>6 ) /* some timeout are insane, e.g. 65s ! */
721     dvbsub->page.page_time_out = 6;
722 
723   int version = (dvbsub->buf[dvbsub->i] & 0xf0) >> 4;
724   if ( version == dvbsub->page.page_version_number )
725     return;
726   dvbsub->page.page_version_number = version;
727   dvbsub->page.page_state = (dvbsub->buf[dvbsub->i] & 0x0c) >> 2;
728   dvbsub->i++;
729 
730   unsigned int r;
731   for (r=0; r<dvbsub->max_regions; r++) { /* reset */
732     dvbsub->page.regions[r].is_visible = 0;
733   }
734 
735   while (dvbsub->i < j) {
736     region_id = dvbsub->buf[dvbsub->i++];
737     dvbsub->i++;                /* reserved */
738     region_x = (dvbsub->buf[dvbsub->i] << 8) | dvbsub->buf[dvbsub->i + 1];
739     dvbsub->i += 2;
740     region_y = (dvbsub->buf[dvbsub->i] << 8) | dvbsub->buf[dvbsub->i + 1];
741     dvbsub->i += 2;
742     lprintf ("process_page_composition_segment: page_id %d, region_id %d, x %d, y %d\n",
743       dvbsub->page.page_id, region_id, region_x, region_y);
744     if (region_id >= MAX_REGIONS)
745       continue;
746     if (region_id >= dvbsub->max_regions)
747       dvbsub->max_regions = region_id + 1;
748 
749     dvbsub->page.regions[region_id].x = region_x;
750     dvbsub->page.regions[region_id].y = region_y;
751     dvbsub->page.regions[region_id].is_visible = 1;
752   }
753 }
754 
755 
process_region_composition_segment(dvbsub_func_t * dvbsub)756 static void process_region_composition_segment (dvbsub_func_t *dvbsub)
757 {
758   unsigned int segment_length,
759     region_id,
760     region_version_number,
761     region_fill_flag, region_width, region_height, region_level_of_compatibility, region_depth, CLUT_id,
762     /*region_8_bit_pixel_code,*/ region_4_bit_pixel_code /*, region_2_bit_pixel_code*/;
763   unsigned int object_id, object_type, /*object_provider_flag,*/ object_x, object_y /*, foreground_pixel_code, background_pixel_code*/;
764   int j;
765 
766   dvbsub->page.page_id = (dvbsub->buf[dvbsub->i] << 8) | dvbsub->buf[dvbsub->i + 1];
767   dvbsub->i += 2;
768   segment_length = (dvbsub->buf[dvbsub->i] << 8) | dvbsub->buf[dvbsub->i + 1];
769   dvbsub->i += 2;
770   j = dvbsub->i + segment_length;
771 
772   region_id = dvbsub->buf[dvbsub->i++];
773   region_version_number = (dvbsub->buf[dvbsub->i] & 0xf0) >> 4;
774   region_fill_flag = (dvbsub->buf[dvbsub->i] & 0x08) >> 3;
775   dvbsub->i++;
776   region_width = (dvbsub->buf[dvbsub->i] << 8) | dvbsub->buf[dvbsub->i + 1];
777   dvbsub->i += 2;
778   region_height = (dvbsub->buf[dvbsub->i] << 8) | dvbsub->buf[dvbsub->i + 1];
779   dvbsub->i += 2;
780   region_level_of_compatibility = (dvbsub->buf[dvbsub->i] & 0xe0) >> 5;
781   region_depth = (dvbsub->buf[dvbsub->i] & 0x1c) >> 2;
782   dvbsub->compat_depth = region_level_of_compatibility << 3 | region_depth;
783   dvbsub->i++;
784   CLUT_id = dvbsub->buf[dvbsub->i++];
785   /*region_8_bit_pixel_code = dvbsub->buf[*/dvbsub->i++/*]*/;
786   region_4_bit_pixel_code = (dvbsub->buf[dvbsub->i] & 0xf0) >> 4;
787   /*region_2_bit_pixel_code = (dvbsub->buf[dvbsub->i] & 0x0c) >> 2;*/
788   dvbsub->i++;
789   lprintf ("process_region_composition_segment: region_id %d (%d x %d)\n", region_id, region_width, region_height);
790 
791   if(region_id>=MAX_REGIONS)
792     return;
793 
794   if (region_id >= dvbsub->max_regions)
795     dvbsub->max_regions = region_id + 1;
796 
797   if ( dvbsub->regions[region_id].version_number == region_version_number )
798     return;
799 
800   dvbsub->regions[region_id].version_number = region_version_number;
801 
802   /* Check if region size has changed and fill background. */
803   update_region (&dvbsub->regions[region_id], region_id, region_width, region_height, region_fill_flag, region_4_bit_pixel_code);
804   if ( CLUT_id<MAX_REGIONS )
805     dvbsub->regions[region_id].CLUT_id = CLUT_id;
806 
807   sparse_array_unset (&dvbsub->object_pos, region_id << 16, 0xff0000);
808 
809   while (dvbsub->i < j) {
810     object_id = (dvbsub->buf[dvbsub->i] << 8) | dvbsub->buf[dvbsub->i + 1];
811     dvbsub->i += 2;
812     object_type = (dvbsub->buf[dvbsub->i] & 0xc0) >> 6;
813     /*object_provider_flag = (dvbsub->buf[dvbsub->i] & 0x30) >> 4;*/
814     object_x = ((dvbsub->buf[dvbsub->i] & 0x0f) << 8) | dvbsub->buf[dvbsub->i + 1];
815     dvbsub->i += 2;
816     object_y = ((dvbsub->buf[dvbsub->i] & 0x0f) << 8) | dvbsub->buf[dvbsub->i + 1];
817     dvbsub->i += 2;
818 
819     sparse_array_set (&dvbsub->object_pos, (region_id << 16) | object_id, (object_x << 16) | object_y);
820 
821     if ((object_type == 0x01) || (object_type == 0x02)) {
822       /*foreground_pixel_code = dvbsub->buf[*/dvbsub->i++/*]*/;
823       /*background_pixel_code = dvbsub->buf[*/dvbsub->i++/*]*/;
824     }
825   }
826 
827 }
828 
process_object_data_segment(dvbsub_func_t * dvbsub)829 static void process_object_data_segment (dvbsub_func_t *dvbsub)
830 {
831   unsigned int /*segment_length,*/ object_id/*, object_version_number*/, object_coding_method/*, non_modifying_colour_flag*/;
832 
833   int top_field_data_block_length, bottom_field_data_block_length;
834 
835   int old_i;
836   unsigned int r;
837 
838   dvbsub->page.page_id = (dvbsub->buf[dvbsub->i] << 8) | dvbsub->buf[dvbsub->i + 1];
839   dvbsub->i += 2;
840   /*segment_length = (dvbsub->buf[dvbsub->i] << 8) | dvbsub->buf[dvbsub->i + 1];*/
841   dvbsub->i += 2;
842 
843   object_id = (dvbsub->buf[dvbsub->i] << 8) | dvbsub->buf[dvbsub->i + 1];
844   dvbsub->i += 2;
845   dvbsub->curr_obj = object_id;
846   /*object_version_number = (dvbsub->buf[dvbsub->i] & 0xf0) >> 4;*/
847   object_coding_method = (dvbsub->buf[dvbsub->i] & 0x0c) >> 2;
848   /*non_modifying_colour_flag = (dvbsub->buf[dvbsub->i] & 0x02) >> 1;*/
849   dvbsub->i++;
850 
851   old_i = dvbsub->i;
852   for (r = 0; r < dvbsub->max_regions; r++) {
853 
854     /* If this object is in this region... */
855     if (dvbsub->regions[r].img) {
856       uint32_t pos;
857       if (sparse_array_get (&dvbsub->object_pos, (r << 16) | object_id, &pos)) {
858         dvbsub->i = old_i;
859         if (object_coding_method == 0) {
860           top_field_data_block_length = (dvbsub->buf[dvbsub->i] << 8) | dvbsub->buf[dvbsub->i + 1];
861           dvbsub->i += 2;
862           bottom_field_data_block_length = (dvbsub->buf[dvbsub->i] << 8) | dvbsub->buf[dvbsub->i + 1];
863           dvbsub->i += 2;
864 
865           process_pixel_data_sub_block (dvbsub, r, pos, 0, top_field_data_block_length);
866 
867           if (bottom_field_data_block_length == 0)
868           {
869             /* handle bottom field == top field */
870             bottom_field_data_block_length = top_field_data_block_length;
871             dvbsub->i =  old_i + 4;
872           }
873 
874           process_pixel_data_sub_block (dvbsub, r, pos, 1, bottom_field_data_block_length);
875         }
876       }
877     }
878   }
879 }
880 
process_display_definition_segment(dvbsub_func_t * dvbsub)881 static void process_display_definition_segment(dvbsub_func_t *dvbsub)
882 {
883   unsigned int version_number, segment_length;
884   uint8_t *buf = &dvbsub->buf[dvbsub->i];
885 
886   /*page_id = _X_BE_16(buf); */
887   segment_length = _X_BE_16(buf + 2);
888   buf += 4;
889 
890   if (segment_length < 5)
891     return;
892 
893   version_number = (buf[0] >> 4);
894 
895   /* Check version number */
896   if (version_number == dvbsub->dds.version_number)
897     return;
898 
899   dvbsub->dds.version_number = version_number;
900   dvbsub->dds.windowed = (buf[0] & 0x08) >> 3;
901 
902   dvbsub->dds.width  = _X_BE_16(buf + 1) + 1;
903   dvbsub->dds.height = _X_BE_16(buf + 3) + 1;
904 
905   lprintf("display_definition_segment: %ux%u, windowed=%u\n",
906           dvbsub->dds.width, dvbsub->dds.height, dvbsub->dds.windowed);
907 
908   if (dvbsub->dds.windowed) {
909 #if 0
910     if (segment_length < 13)
911       return;
912     /* TODO: window currently disabled (no samples) */
913     dvbsub->dds.x0 = _X_BE_16(buf + 5);
914     dvbsub->dds.x1 = _X_BE_16(buf + 7);
915     dvbsub->dds.y0 = _X_BE_16(buf + 9);
916     dvbsub->dds.y1 = _X_BE_16(buf + 11);
917 
918     lprintf("display_definition_segment: window (%u,%u)-(%u,%u)\n",
919             dvbsub->dds.x0, dvbsub->dds.y0, dvbsub->dds.x1, dvbsub->dds.y1,
920 #endif
921   }
922 }
923 
924 /*
925  *
926  */
927 
unlock_mutex_cancellation_func(void * mutex_gen)928 static void unlock_mutex_cancellation_func(void *mutex_gen)
929 {
930   pthread_mutex_t *mutex = (pthread_mutex_t*) mutex_gen;
931   pthread_mutex_unlock(mutex);
932 }
933 
_hide_overlays_locked(dvb_spu_decoder_t * this)934 static void _hide_overlays_locked(dvb_spu_decoder_t *this)
935 {
936   unsigned int i;
937   for (i = 0; i < this->dvbsub.max_regions; i++) {
938     if (this->dvbsub.regions[i].osd) {
939       this->stream->osd_renderer->hide( this->dvbsub.regions[i].osd, 0 );
940     }
941   }
942 }
943 
944 /* Thread routine that checks for subtitle timeout periodically.
945    To avoid unexpected subtitle hiding, calls to this->stream->osd_renderer->show()
946    should be in blocks like:
947 
948    pthread_mutex_lock(&this->dvbsub_osd_mutex);
949    this->stream->osd_renderer->show(...);
950    this->dvbsub_hide_timeout.tv_sec = time(NULL) + timeout value;
951    pthread_cond_signal(&this->dvbsub_restart_timeout);
952    pthread_mutex_unlock(&this->dvbsub_osd_mutex);
953 
954    This ensures that the timeout is changed with the lock held, and
955    that the thread is signalled to pick up the new timeout.
956 */
dvbsub_timer_func(void * this_gen)957 static void* dvbsub_timer_func(void *this_gen)
958 {
959   dvb_spu_decoder_t *this = (dvb_spu_decoder_t *) this_gen;
960   pthread_mutex_lock(&this->dvbsub_osd_mutex);
961 
962  /* If we're cancelled via pthread_cancel, unlock the mutex */
963   pthread_cleanup_push(unlock_mutex_cancellation_func, &this->dvbsub_osd_mutex);
964 
965   while(1)
966   {
967     /* Record the current timeout, and wait - note that pthread_cond_timedwait
968        will unlock the mutex on entry, and lock it on exit */
969     struct timespec timeout = this->dvbsub_hide_timeout;
970     int result = pthread_cond_timedwait(&this->dvbsub_restart_timeout,
971                                         &this->dvbsub_osd_mutex,
972                                         &this->dvbsub_hide_timeout);
973     if(result == ETIMEDOUT &&
974        timeout.tv_sec == this->dvbsub_hide_timeout.tv_sec &&
975        timeout.tv_nsec == this->dvbsub_hide_timeout.tv_nsec)
976     {
977       /* We timed out, and no-one changed the timeout underneath us.
978          Hide the OSD, then wait until we're signalled. */
979       lprintf("thread hiding\n");
980       _hide_overlays_locked(this);
981 
982       pthread_cond_wait(&this->dvbsub_restart_timeout, &this->dvbsub_osd_mutex);
983     }
984   }
985 
986   pthread_cleanup_pop(1);
987   return NULL;
988 }
989 
update_osd(dvb_spu_decoder_t * this,region_t * reg)990 static void update_osd(dvb_spu_decoder_t *this, region_t *reg)
991 {
992   if ( !reg->img ) {
993     if ( reg->osd ) {
994       pthread_mutex_lock( &this->dvbsub_osd_mutex );
995       this->stream->osd_renderer->free_object( reg->osd );
996       reg->osd = NULL;
997       pthread_mutex_unlock( &this->dvbsub_osd_mutex );
998     }
999     return;
1000   }
1001 
1002   if ( reg->osd ) {
1003     if ( reg->width!=reg->osd->width || reg->height!=reg->osd->height ) {
1004       pthread_mutex_lock( &this->dvbsub_osd_mutex );
1005       this->stream->osd_renderer->free_object( reg->osd );
1006       reg->osd = NULL;
1007       pthread_mutex_unlock( &this->dvbsub_osd_mutex );
1008     }
1009   }
1010 
1011   if ( !reg->osd )
1012     reg->osd = this->stream->osd_renderer->new_object( this->stream->osd_renderer, reg->width, reg->height );
1013 }
1014 
downscale_region_image(region_t * reg,unsigned char * dest,int dest_width)1015 static void downscale_region_image( region_t *reg, unsigned char *dest, int dest_width )
1016 {
1017   float i, k, inc=reg->width/(float)dest_width;
1018   int j;
1019   for ( j=0; j<reg->height; j++ ) {
1020     for ( i=0,k=0; i<reg->width && k<dest_width; i+=inc,k++ ) {
1021       dest[(j*dest_width)+(int)k] = reg->img[(j*reg->width)+(int)i];
1022     }
1023   }
1024 }
1025 
recalculate_trans(dvb_spu_decoder_t * this)1026 static void recalculate_trans (dvb_spu_decoder_t *this)
1027 {
1028   dvbsub_func_t *const dvbsub = &this->dvbsub;
1029   xine_spu_opacity_t opacity;
1030   unsigned int i;
1031 
1032   _x_spu_get_opacity (this->stream->xine, &opacity);
1033   for (i = 0; i < dvbsub->max_regions * 256; ++i) {
1034     /* ETSI-300-743 says "full transparency if Y == 0". */
1035     if (dvbsub->colours[i].c.y == 0)
1036       dvbsub->trans[i] = 0;
1037     else {
1038       int v = _x_spu_calculate_opacity (&dvbsub->colours[i].c, dvbsub->colours[i].c.foo, &opacity);
1039       dvbsub->trans[i] = v * 14 / 255 + 1;
1040     }
1041   }
1042 }
1043 
draw_subtitles(dvb_spu_decoder_t * this)1044 static void draw_subtitles (dvb_spu_decoder_t * this)
1045 {
1046   unsigned int r;
1047   int display=0;
1048   int64_t dum;
1049   int dest_width=0, dest_height;
1050   int max_x = 0, max_y = 0;
1051 
1052   this->stream->video_out->status(this->stream->video_out, NULL, &dest_width, &dest_height, &dum);
1053   if ( !dest_width || !dest_height )
1054     return;
1055 
1056   /* render all regions onto the page */
1057 
1058   for (r = 0; r < this->dvbsub.max_regions; r++) {
1059     if (this->dvbsub.page.regions[r].is_visible) {
1060       /* additional safety for broken HD streams without DDS ... */
1061       int x2 = this->dvbsub.page.regions[r].x + this->dvbsub.regions[r].width;
1062       int y2 = this->dvbsub.page.regions[r].y + this->dvbsub.regions[r].height;
1063       max_x = (max_x < x2) ? x2 : max_x;
1064       max_y = (max_y < y2) ? y2 : max_y;
1065       display++;
1066     }
1067   }
1068   if ( !display )
1069     return;
1070 
1071   for (r = 0; r < this->dvbsub.max_regions; r++) {
1072     region_t *reg = &this->dvbsub.regions[r];
1073     if (reg->img) {
1074       if (this->dvbsub.page.regions[r].is_visible && !reg->empty) {
1075         uint8_t *tmp = NULL;
1076         const uint8_t *img = reg->img;
1077         int img_width = reg->width;
1078 
1079         update_osd( this, reg );
1080         if (!reg->osd)
1081           continue;
1082         /* clear osd */
1083         this->stream->osd_renderer->clear( reg->osd );
1084         if (reg->width > dest_width && !(this->stream->video_out->get_capabilities(this->stream->video_out) & VO_CAP_CUSTOM_EXTENT_OVERLAY)) {
1085           lprintf("downscaling region, width %d->%d\n", reg->width, dest_width);
1086           tmp = malloc(dest_width*576);
1087           if (tmp) {
1088             downscale_region_image(reg, tmp, dest_width);
1089             img = tmp;
1090             img_width = dest_width;
1091           }
1092         }
1093         /* All DVB subs I have seen so far use same color matrix as main video. */
1094         _X_SET_CLUT_CM (&this->dvbsub.colours[reg->CLUT_id * 256].u32, 4);
1095         this->stream->osd_renderer->set_palette( reg->osd,
1096                                                  &this->dvbsub.colours[reg->CLUT_id * 256].u32,
1097                                                  &this->dvbsub.trans[reg->CLUT_id * 256]);
1098         lprintf("draw region %d: %dx%d\n", r, img_width, reg->height);
1099         this->stream->osd_renderer->draw_bitmap( reg->osd, img, 0, 0, img_width, reg->height, NULL );
1100         free(tmp);
1101       }
1102     }
1103   }
1104 
1105   pthread_mutex_lock(&this->dvbsub_osd_mutex);
1106   lprintf("this->vpts=%"PRId64"\n",this->vpts);
1107   for (r = 0; r < this->dvbsub.max_regions; r++) {
1108     region_t *reg = &this->dvbsub.regions[r];
1109     lprintf("region=%d, visible=%d, osd=%d, empty=%d\n",
1110             r, this->dvbsub.page.regions[r].is_visible, reg->osd ? 1 : 0, reg->empty );
1111     if (this->dvbsub.page.regions[r].is_visible && reg->osd && !reg->empty ) {
1112       if (max_x <= this->dvbsub.dds.width && max_y <= this->dvbsub.dds.height)
1113         this->stream->osd_renderer->set_extent(reg->osd, this->dvbsub.dds.width, this->dvbsub.dds.height);
1114       this->stream->osd_renderer->set_position( reg->osd, this->dvbsub.page.regions[r].x, this->dvbsub.page.regions[r].y );
1115       this->stream->osd_renderer->show( reg->osd, this->vpts );
1116       lprintf("show region = %d\n",r);
1117     }
1118     else {
1119       if (reg->osd) {
1120         this->stream->osd_renderer->hide( reg->osd, this->vpts );
1121         lprintf("hide region = %d\n",r);
1122       }
1123     }
1124   }
1125   this->dvbsub_hide_timeout.tv_nsec = 0;
1126   this->dvbsub_hide_timeout.tv_sec = time(NULL) + this->dvbsub.page.page_time_out;
1127   lprintf("page_time_out %d\n",this->dvbsub.page.page_time_out);
1128   pthread_cond_signal(&this->dvbsub_restart_timeout);
1129   pthread_mutex_unlock(&this->dvbsub_osd_mutex);
1130 }
1131 
_hide_overlays(dvb_spu_decoder_t * this)1132 static void _hide_overlays(dvb_spu_decoder_t *this)
1133 {
1134   pthread_mutex_lock(&this->dvbsub_osd_mutex);
1135   _hide_overlays_locked(this);
1136   pthread_mutex_unlock(&this->dvbsub_osd_mutex);
1137 }
1138 
1139 /*
1140  *
1141  */
1142 
spudec_decode_data(spu_decoder_t * this_gen,buf_element_t * buf)1143 static void spudec_decode_data (spu_decoder_t * this_gen, buf_element_t * buf)
1144 {
1145   dvb_spu_decoder_t *this = (dvb_spu_decoder_t *) this_gen;
1146   int new_i;
1147   /*int data_identifier, subtitle_stream_id;*/
1148   int segment_length, segment_type;
1149 
1150   if((buf->type & 0xffff0000)!=BUF_SPU_DVB)
1151     return;
1152 
1153   if (buf->decoder_flags & BUF_FLAG_SPECIAL) {
1154     if (buf->decoder_info[1] == BUF_SPECIAL_SPU_DVB_DESCRIPTOR) {
1155       if (buf->decoder_info[2] == 0) {
1156         /* Hide the osd - note that if the timeout thread times out, it'll rehide, which is harmless */
1157         _hide_overlays(this);
1158       }
1159       else {
1160         if (buf->decoder_info[2] < sizeof(this->spu_descriptor)) {
1161           xprintf (this->stream->xine, XINE_VERBOSITY_LOG, LOG_MODULE ": too small spu_descriptor, ignoring\n");
1162         } else {
1163           if (buf->decoder_info[2] > sizeof(this->spu_descriptor))
1164             xprintf (this->stream->xine, XINE_VERBOSITY_LOG, LOG_MODULE ": too large spu_descriptor\n");
1165           memcpy (&this->spu_descriptor, buf->decoder_info_ptr[2], sizeof(this->spu_descriptor));
1166         }
1167       }
1168     }
1169     return;
1170   }
1171 
1172   /* accumulate data */
1173   if (buf->decoder_info[2]) {
1174 
1175     this->pes_pkt_wrptr = this->pes_pkt;
1176     this->pes_pkt_size = buf->decoder_info[2];
1177 
1178     xine_fast_memcpy (this->pes_pkt, buf->content, buf->size);
1179     this->pes_pkt_wrptr += buf->size;
1180     memset (this->pes_pkt_wrptr, 0xff, sizeof(this->pes_pkt) - buf->size);
1181 
1182     this->vpts = 0;
1183 
1184     /* set DDS default (SD resolution) */
1185     this->dvbsub.dds.version_number = 0xff;
1186     this->dvbsub.dds.width = 720;
1187     this->dvbsub.dds.height = 576;
1188     this->dvbsub.dds.windowed = 0;
1189   }
1190   else {
1191     if (this->pes_pkt_wrptr != this->pes_pkt) {
1192       xine_fast_memcpy (this->pes_pkt_wrptr, buf->content, buf->size);
1193       this->pes_pkt_wrptr += buf->size;
1194     }
1195   }
1196 
1197   /* don't ask metronom for a vpts but rather do the calculation
1198    * because buf->pts could be too far in future and metronom won't accept
1199    * further backwards pts (see metronom_got_spu_packet) */
1200   if (buf->pts > 0) {
1201     metronom_t *metronom = this->stream->metronom;
1202     int64_t vpts_offset = metronom->get_option( metronom, METRONOM_VPTS_OFFSET );
1203     int64_t spu_offset = metronom->get_option( metronom, METRONOM_SPU_OFFSET );
1204     int64_t vpts = (int64_t)(buf->pts)+vpts_offset+spu_offset;
1205     metronom_clock_t *clock = this->stream->xine->clock;
1206     int64_t curvpts = clock->get_current_time( clock );
1207     /* if buf->pts is unreliable, show page asap (better than nothing) */
1208     lprintf("spu_vpts=%"PRId64" - current_vpts=%"PRId64"\n", vpts, curvpts);
1209     if ( vpts<=curvpts || (vpts-curvpts)>(5*90000) )
1210       this->vpts = 0;
1211     else
1212       this->vpts = vpts;
1213   }
1214 
1215   /* completely ignore pts since it makes a lot of problems with various providers */
1216   /* this->vpts = 0; */
1217 
1218   /* process the pes section */
1219 
1220       this->dvbsub.buf = this->pes_pkt;
1221       this->dvbsub.i = 2;
1222       /*data_identifier = this->dvbsub->buf[0]*/
1223       /*subtitle_stream_id = this->dvbsub->buf[1]*/
1224 
1225       while (this->dvbsub.i <= (int)this->pes_pkt_size) {
1226         /* SUBTITLING SEGMENT */
1227         const uint8_t *buf = this->dvbsub.buf;
1228         this->dvbsub.i++;
1229         segment_type = buf[this->dvbsub.i++];
1230 
1231         this->dvbsub.page.page_id = (buf[this->dvbsub.i] << 8) | buf[this->dvbsub.i + 1];
1232         segment_length = (buf[this->dvbsub.i + 2] << 8) | buf[this->dvbsub.i + 3];
1233         new_i = this->dvbsub.i + segment_length + 4;
1234 
1235         /* only process complete segments */
1236         if(new_i > (this->pes_pkt_wrptr - this->pes_pkt))
1237           break;
1238         /* verify we've the right segment */
1239         if (this->dvbsub.page.page_id == this->spu_descriptor.comp_page_id) {
1240           /* SEGMENT_DATA_FIELD */
1241           switch (segment_type & 0xff) {
1242             case 0x10:
1243               process_page_composition_segment (&this->dvbsub);
1244               break;
1245             case 0x11:
1246               process_region_composition_segment (&this->dvbsub);
1247               break;
1248             case 0x12:
1249               process_CLUT_definition_segment(&this->dvbsub);
1250               break;
1251             case 0x13:
1252               process_object_data_segment (&this->dvbsub);
1253               break;
1254             case 0x14:
1255               process_display_definition_segment(&this->dvbsub);
1256               break;
1257             case 0x80:          /* Page is now completely rendered */
1258               recalculate_trans(this);
1259               draw_subtitles( this );
1260               break;
1261             case 0xFF:          /* stuffing */
1262               break;
1263             default:
1264               return;
1265               break;
1266           }
1267         }
1268         this->dvbsub.i = new_i;
1269       }
1270 }
1271 
spudec_reset(spu_decoder_t * this_gen)1272 static void spudec_reset (spu_decoder_t * this_gen)
1273 {
1274   dvb_spu_decoder_t *this = (dvb_spu_decoder_t *) this_gen;
1275   unsigned int i;
1276 
1277   /* Hide the osd - if the timeout thread times out, it'll rehide harmlessly */
1278   _hide_overlays(this);
1279 
1280   for ( i=0; i<MAX_REGIONS; i++ ) {
1281     this->dvbsub.regions[i].version_number = 0xff;
1282   }
1283   this->dvbsub.page.page_version_number = 0xff;
1284   reset_clut (&this->dvbsub);
1285 }
1286 
spudec_discontinuity(spu_decoder_t * this_gen)1287 static void spudec_discontinuity (spu_decoder_t * this_gen)
1288 {
1289   /* do nothing */
1290   (void)this_gen;
1291 }
1292 
spudec_dispose_stopped(dvb_spu_decoder_t * this)1293 static void spudec_dispose_stopped (dvb_spu_decoder_t * this)
1294 {
1295   unsigned int i;
1296 
1297   pthread_mutex_destroy(&this->dvbsub_osd_mutex);
1298   pthread_cond_destroy(&this->dvbsub_restart_timeout);
1299 
1300   for ( i=0; i<MAX_REGIONS; i++ ) {
1301     _x_freep( &this->dvbsub.regions[i].img );
1302     if ( this->dvbsub.regions[i].osd )
1303       this->stream->osd_renderer->free_object( this->dvbsub.regions[i].osd );
1304   }
1305 
1306   sparse_array_delete (&this->dvbsub.object_pos);
1307 
1308   free (this);
1309 }
1310 
spudec_dispose(spu_decoder_t * this_gen)1311 static void spudec_dispose (spu_decoder_t * this_gen)
1312 {
1313   dvb_spu_decoder_t *this = (dvb_spu_decoder_t *) this_gen;
1314 
1315   pthread_cancel(this->dvbsub_timer_thread);
1316   pthread_join(this->dvbsub_timer_thread, NULL);
1317 
1318   spudec_dispose_stopped(this);
1319 }
1320 
dvb_spu_class_open_plugin(spu_decoder_class_t * class_gen,xine_stream_t * stream)1321 static spu_decoder_t *dvb_spu_class_open_plugin (spu_decoder_class_t * class_gen, xine_stream_t * stream)
1322 {
1323   dvb_spu_decoder_t *this;
1324   unsigned int i;
1325 
1326   (void)class_gen;
1327   this = calloc(1, sizeof (dvb_spu_decoder_t));
1328   if (!this)
1329     return NULL;
1330 
1331   this->spu_decoder.decode_data = spudec_decode_data;
1332   this->spu_decoder.reset = spudec_reset;
1333   this->spu_decoder.discontinuity = spudec_discontinuity;
1334   this->spu_decoder.dispose = spudec_dispose;
1335   this->spu_decoder.get_interact_info = NULL;
1336   this->spu_decoder.set_button = NULL;
1337 
1338   this->stream = stream;
1339 
1340   pthread_mutex_init(&this->dvbsub_osd_mutex, NULL);
1341   pthread_cond_init(&this->dvbsub_restart_timeout, NULL);
1342 
1343 #ifndef HAVE_ZERO_SAFE_MEM
1344   for (i = 0; i < MAX_REGIONS; i++) {
1345     this->dvbsub.regions[i].img = NULL;
1346     this->dvbsub.regions[i].osd = NULL;
1347   }
1348 #endif
1349 
1350   {
1351     xine_spu_opacity_t opacity;
1352     const clut_t black = { 0, 0, 0, 0 };
1353     int t;
1354 
1355     _x_spu_get_opacity (this->stream->xine, &opacity);
1356     t = _x_spu_calculate_opacity (&black, 0, &opacity);
1357 
1358     for (i = 0; i < MAX_REGIONS * 256; i++)
1359       this->dvbsub.colours[i].c.foo = t;
1360   }
1361 
1362   sparse_array_new (&this->dvbsub.object_pos);
1363 
1364   this->dvbsub_hide_timeout.tv_nsec = 0;
1365   this->dvbsub_hide_timeout.tv_sec = time(NULL);
1366 
1367   if (pthread_create(&this->dvbsub_timer_thread, NULL, dvbsub_timer_func, this)) {
1368     xprintf (stream->xine, XINE_VERBOSITY_LOG, LOG_MODULE ": pthread_create() failed\n");
1369     spudec_dispose_stopped(this);
1370     return NULL;
1371   }
1372 
1373   for (i = 0; i < MAX_REGIONS; i++) {
1374     this->dvbsub.regions[i].version_number = 0xff;
1375   }
1376   this->dvbsub.page.page_version_number = 0xff;
1377 
1378   return &this->spu_decoder;
1379 }
1380 
init_spu_decoder_plugin(xine_t * xine,const void * data)1381 static void *init_spu_decoder_plugin (xine_t * xine, const void *data)
1382 {
1383   (void)xine;
1384   (void)data;
1385   static const spu_decoder_class_t decode_dvb_spu_class = {
1386     .open_plugin = dvb_spu_class_open_plugin,
1387     .identifier  = "spudvb",
1388     .description = N_("DVB subtitle decoder plugin"),
1389     .dispose = NULL,
1390   };
1391   return (void *)&decode_dvb_spu_class;
1392 }
1393 
1394 
1395 /* plugin catalog information */
1396 static const uint32_t supported_types[] = { BUF_SPU_DVB, 0 };
1397 
1398 static const decoder_info_t spudec_info = {
1399   .supported_types = supported_types,
1400   .priority        = 1,
1401 };
1402 
1403 const plugin_info_t xine_plugin_info[] EXPORTED = {
1404 /* type, API, "name", version, special_info, init_function */
1405   {PLUGIN_SPU_DECODER, 17, "spudvb", XINE_VERSION_CODE, &spudec_info,
1406    &init_spu_decoder_plugin},
1407   {PLUGIN_NONE, 0, NULL, 0, NULL, NULL}
1408 };
1409