]> git.sesse.net Git - vlc/blob - modules/codec/svcdsub.c
40186b1e5bbe78fb4df42b1ee5052257438091b4
[vlc] / modules / codec / svcdsub.c
1 /*****************************************************************************
2  * svcdsub.c : Overlay Graphics Text (SVCD subtitles) decoder
3  *****************************************************************************
4  * Copyright (C) 2003, 2004 VideoLAN
5  * $Id$
6  *
7  * Authors: Rocky Bernstein
8  *          Gildas Bazin <gbazin@videolan.org>
9  *          Julio Sanchez Fernandez (http://subhandler.sourceforge.net)
10  *          Laurent Aimar <fenrir@via.ecp.fr>
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
25  *****************************************************************************/
26
27 /*****************************************************************************
28  * Preamble
29  *****************************************************************************/
30 #include <vlc/vlc.h>
31 #include <vlc/decoder.h>
32
33 #include "vlc_bits.h"
34
35 /*****************************************************************************
36  * Module descriptor.
37  *****************************************************************************/
38 static int  DecoderOpen   ( vlc_object_t * );
39 static int  PacketizerOpen( vlc_object_t * );
40 static void DecoderClose  ( vlc_object_t * );
41
42 #define DEBUG_TEXT N_( \
43      "If nonzero, this gives additional debug information." \
44      )
45
46 #define DEBUG_LONGTEXT N_( \
47     "This integer when viewed in binary is a debugging mask\n" \
48     "calls                 1\n" \
49     "packet assembly info  2\n" )
50
51 vlc_module_begin();
52     set_description( _("Philips OGT (SVCD subtitle) decoder") );
53     set_shortname( N_("SVCD subtitles"));
54     set_category( CAT_INPUT );
55     set_subcategory( SUBCAT_INPUT_SCODEC );
56     set_capability( "decoder", 50 );
57     set_callbacks( DecoderOpen, DecoderClose );
58
59     add_integer ( MODULE_STRING "-debug", 0, NULL,
60                   DEBUG_TEXT, DEBUG_LONGTEXT, VLC_TRUE );
61
62     add_submodule();
63     set_description( _("Philips OGT (SVCD subtitle) packetizer") );
64     set_capability( "packetizer", 50 );
65     set_callbacks( PacketizerOpen, DecoderClose );
66 vlc_module_end();
67
68 /*****************************************************************************
69  * Local prototypes
70  *****************************************************************************/
71 static subpicture_t *Decode( decoder_t *, block_t ** );
72 static block_t *Packetize  ( decoder_t *, block_t ** );
73 static block_t *Reassemble ( decoder_t *, block_t * );
74 static void ParseHeader( decoder_t *, block_t * );
75 static subpicture_t *DecodePacket( decoder_t *, block_t * );
76 static void SVCDSubRenderImage( decoder_t *, block_t *, subpicture_region_t * );
77
78 #define DECODE_DBG_CALL        1 /* calls */
79 #define DECODE_DBG_PACKET      2 /* packet assembly info */
80
81 #define GETINT16(p) ( (p[0] <<  8) +   p[1] )  ; p +=2;
82
83 #define GETINT32(p) ( (p[0] << 24) +  (p[1] << 16) +    \
84                       (p[2] <<  8) +  (p[3]) ) ; p += 4;
85
86 typedef enum  {
87   SUBTITLE_BLOCK_EMPTY    = 0,
88   SUBTITLE_BLOCK_PARTIAL  = 1,
89   SUBTITLE_BLOCK_COMPLETE = 2
90 } packet_state_t;
91
92 #ifndef DECODE_DEBUG
93 #define DECODE_DEBUG 1
94 #endif
95 #if DECODE_DEBUG
96 #define dbg_print(mask, s, args...) \
97    if (p_sys && p_sys->i_debug & mask) \
98      msg_Dbg(p_dec, "%s: "s, __func__ , ##args)
99 #else
100 #define dbg_print(mask, s, args...)
101 #endif
102
103 struct decoder_sys_t
104 {
105   int      i_debug;       /* debugging mask */
106
107   packet_state_t i_state; /* data-gathering state for this subtitle */
108
109   block_t  *p_spu;        /* Bytes of the packet. */
110
111   uint16_t i_image;       /* image number in the subtitle stream */
112   uint8_t  i_packet;      /* packet number for above image number */
113
114   int     i_spu_size;     /* goal for subtitle_data_pos while gathering,
115                              size of used subtitle_data later */
116
117   uint16_t i_image_offset;      /* offset from subtitle_data to compressed
118                                    image data */
119   int i_image_length;           /* size of the compressed image data */
120   int second_field_offset;      /* offset of odd raster lines */
121   int metadata_offset;          /* offset to data describing the image */
122   int metadata_length;          /* length of metadata */
123
124   mtime_t i_duration;   /* how long to display the image, 0 stands
125                            for "until next subtitle" */
126
127   uint16_t i_x_start, i_y_start; /* position of top leftmost pixel of
128                                     image when displayed */
129   uint16_t i_width, i_height;    /* dimensions in pixels of image */
130
131   uint8_t p_palette[4][4];       /* Palette of colors used in subtitle */
132 };
133
134 /*****************************************************************************
135  * DecoderOpen: open/initialize the svcdsub decoder.
136  *****************************************************************************/
137 static int DecoderOpen( vlc_object_t *p_this )
138 {
139     decoder_t     *p_dec = (decoder_t*)p_this;
140     decoder_sys_t *p_sys;
141
142     if( p_dec->fmt_in.i_codec != VLC_FOURCC( 'o','g','t',' ' ) )
143     {
144         return VLC_EGENERIC;
145     }
146
147     p_dec->p_sys = p_sys = calloc( 1, sizeof( decoder_sys_t ) );
148     p_sys->i_debug       = config_GetInt( p_this, MODULE_STRING "-debug" );
149
150     p_sys->i_image       = -1;
151
152     p_sys->i_state = SUBTITLE_BLOCK_EMPTY;
153     p_sys->p_spu   = NULL;
154
155     es_format_Init( &p_dec->fmt_out, SPU_ES, VLC_FOURCC( 'o','g','t',' ' ) );
156
157     p_dec->pf_decode_sub = Decode;
158     p_dec->pf_packetize  = Packetize;
159
160     dbg_print( (DECODE_DBG_CALL) , "");
161     return VLC_SUCCESS;
162 }
163
164 /*****************************************************************************
165  * PacketizerOpen: open/initialize the svcdsub packetizer.
166  *****************************************************************************/
167 static int PacketizerOpen( vlc_object_t *p_this )
168 {
169     if( DecoderOpen( p_this ) != VLC_SUCCESS ) return VLC_EGENERIC;
170
171     return VLC_SUCCESS;
172 }
173
174 /*****************************************************************************
175  * DecoderClose: closes the svcdsub decoder/packetizer.
176  *****************************************************************************/
177 void DecoderClose( vlc_object_t *p_this )
178 {
179     decoder_t     *p_dec = (decoder_t*)p_this;
180     decoder_sys_t *p_sys = p_dec->p_sys;
181
182     if( p_sys->p_spu ) block_ChainRelease( p_sys->p_spu );
183     free( p_sys );
184 }
185
186 /*****************************************************************************
187  * Decode:
188  *****************************************************************************/
189 static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block )
190 {
191     block_t *p_block, *p_spu;
192     decoder_sys_t *p_sys = p_dec->p_sys;
193
194     dbg_print( (DECODE_DBG_CALL) , "");
195
196     if( pp_block == NULL || *pp_block == NULL ) return NULL;
197
198     p_block = *pp_block;
199     *pp_block = NULL;
200
201     if( !(p_spu = Reassemble( p_dec, p_block )) ) return NULL;
202
203     /* Parse and decode */
204     return DecodePacket( p_dec, p_spu );
205 }
206
207 /*****************************************************************************
208  * Packetize:
209  *****************************************************************************/
210 static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
211 {
212     block_t *p_block, *p_spu;
213
214     if( pp_block == NULL || *pp_block == NULL ) return NULL;
215
216     p_block = *pp_block;
217     *pp_block = NULL;
218
219     if( !(p_spu = Reassemble( p_dec, p_block )) ) return NULL;
220
221     p_spu->i_dts = p_spu->i_pts;
222     p_spu->i_length = 0;
223
224     return p_spu;
225 }
226
227 /*****************************************************************************
228  Reassemble:
229
230  The data for single screen subtitle may come in one of many
231  non-contiguous packets of a stream. This routine is called when the
232  next packet in the stream comes in. The job of this routine is to
233  parse the header, if this is the beginning, and combine the packets
234  into one complete subtitle unit.
235
236  If everything is complete, we will return a block. Otherwise return
237  NULL.
238
239
240  The format of the beginning of the subtitle packet that is used here.
241
242    size    description
243    -------------------------------------------
244    byte    subtitle channel (0..7) in bits 0-3
245    byte    subtitle packet number of this subtitle image 0-N,
246            if the subtitle packet is complete, the top bit of the byte is 1.
247    uint16  subtitle image number
248
249  *****************************************************************************/
250 #define SPU_HEADER_LEN 5
251
252 static block_t *Reassemble( decoder_t *p_dec, block_t *p_block )
253 {
254     decoder_sys_t *p_sys = p_dec->p_sys;
255     uint8_t *p_buffer;
256     uint16_t i_expected_image;
257     uint8_t  i_packet, i_expected_packet;
258
259     if( p_block->i_buffer < SPU_HEADER_LEN )
260     {
261         msg_Dbg( p_dec, "invalid packet header (size %d < %d)" ,
262                  p_block->i_buffer, SPU_HEADER_LEN );
263         block_Release( p_block );
264         return NULL;
265     }
266
267     p_buffer = p_block->p_buffer;
268
269     /* Attach to our input thread and see if subtitle is selected. */
270     {
271         vlc_object_t * p_input;
272         vlc_value_t val;
273
274         p_input = vlc_object_find( p_dec, VLC_OBJECT_INPUT, FIND_PARENT );
275
276         if( !p_input ) return NULL;
277
278         if( var_Get( p_input, "sub-track", &val ) )
279         {
280             vlc_object_release( p_input );
281             return NULL;
282         }
283
284         vlc_object_release( p_input );
285         dbg_print( (DECODE_DBG_PACKET),
286                    "val.i_int %x p_buffer[i] %x", val.i_int, p_buffer[1]);
287
288         /* The dummy ES that the menu selection uses has an 0x70 at
289            the head which we need to strip off. */
290         if( val.i_int == -1 || (val.i_int & 0x03) != p_buffer[1] )
291         {
292             dbg_print( DECODE_DBG_PACKET, "subtitle not for us.\n");
293             return NULL;
294         }
295     }
296
297     if( p_sys->i_state == SUBTITLE_BLOCK_EMPTY )
298     {
299         i_expected_image  = p_sys->i_image + 1;
300         i_expected_packet = 0;
301     }
302     else
303     {
304         i_expected_image  = p_sys->i_image;
305         i_expected_packet = p_sys->i_packet + 1;
306     }
307
308     p_buffer += 2;
309
310     if( *p_buffer & 0x80 )
311     {
312         p_sys->i_state = SUBTITLE_BLOCK_COMPLETE;
313         i_packet       = *p_buffer++ & 0x7F;
314     }
315     else
316     {
317         p_sys->i_state = SUBTITLE_BLOCK_PARTIAL;
318         i_packet       = *p_buffer++;
319     }
320
321     p_sys->i_image = GETINT16(p_buffer);
322
323     if( p_sys->i_image != i_expected_image )
324     {
325         msg_Warn( p_dec, "expected subtitle image %u but found %u",
326                   i_expected_image, p_sys->i_image );
327     }
328
329     if( i_packet != i_expected_packet )
330     {
331         msg_Warn( p_dec, "expected subtitle image packet %u but found %u",
332                   i_expected_packet, i_packet );
333     }
334
335     p_block->p_buffer += SPU_HEADER_LEN;
336     p_block->i_buffer -= SPU_HEADER_LEN;
337
338     p_sys->i_packet = i_packet;
339     /* First packet in the subtitle block */
340     if( !p_sys->i_packet ) ParseHeader( p_dec, p_block );
341
342     block_ChainAppend( &p_sys->p_spu, p_block );
343
344     if( p_sys->i_state == SUBTITLE_BLOCK_COMPLETE )
345     {
346         block_t *p_spu = block_ChainGather( p_sys->p_spu );
347
348         if( p_spu->i_buffer != p_sys->i_spu_size )
349         {
350             msg_Warn( p_dec, "subtitle packets size=%d should be %d",
351                       p_spu->i_buffer, p_sys->i_spu_size );
352         }
353
354         dbg_print( (DECODE_DBG_PACKET),
355                  "subtitle packet complete, size=%d", p_spu->i_buffer );
356
357         p_sys->i_state = SUBTITLE_BLOCK_EMPTY;
358         p_sys->p_spu = 0;
359         return p_spu;
360     }
361
362     return NULL;
363 }
364
365 /******************************************************************************
366   The format is roughly as follows (everything is big-endian):
367  
368    size     description
369    -------------------------------------------
370    byte     subtitle channel (0..7) in bits 0-3 
371    byte     subtitle packet number of this subtitle image 0-N,
372             if the subtitle packet is complete, the top bit of the byte is 1.
373    u_int16  subtitle image number
374    u_int16  length in bytes of the rest
375    byte     option flags, unknown meaning except bit 3 (0x08) indicates
376             presence of the duration field
377    byte     unknown 
378    u_int32  duration in 1/90000ths of a second (optional), start time
379             is as indicated by the PTS in the PES header
380    u_int32  xpos
381    u_int32  ypos
382    u_int32  width (must be even)
383    u_int32  height (must be even)
384    byte[16] palette, 4 palette entries, each contains values for
385             Y, U, V and transparency, 0 standing for transparent
386    byte     command,
387             cmd>>6==1 indicates shift
388             (cmd>>4)&3 is direction from, (0=top,1=left,2=right,3=bottom)
389    u_int32  shift duration in 1/90000ths of a second
390    u_int16  offset of odd-numbered scanlines - subtitle images are 
391             given in interlace order
392    byte[]   limited RLE image data in interlace order (0,2,4... 1,3,5) with
393             2-bits per palette number
394 ******************************************************************************/
395 static void ParseHeader( decoder_t *p_dec, block_t *p_block )
396 {
397     decoder_sys_t *p_sys = p_dec->p_sys;
398     uint8_t *p = p_block->p_buffer;
399     uint8_t i_options, i_options2, i_cmd, i_cmd_arg;
400     int i;
401
402     p_sys->i_spu_size = GETINT16(p);
403     i_options  = *p++;
404     i_options2 = *p++;
405
406     if( i_options & 0x08 ) { p_sys->i_duration = GETINT32(p); }
407     else p_sys->i_duration = 0; /* Ephemer subtitle */
408     p_sys->i_duration *= 100 / 9;
409
410     p_sys->i_x_start = GETINT16(p);
411     p_sys->i_y_start = GETINT16(p);
412     p_sys->i_width   = GETINT16(p);
413     p_sys->i_height  = GETINT16(p);
414
415     for( i = 0; i < 4; i++ )
416     {
417         p_sys->p_palette[i][0] = *p++; /* Y */
418         p_sys->p_palette[i][2] = *p++; /* Cr / V */
419         p_sys->p_palette[i][1] = *p++; /* Cb / U */
420         p_sys->p_palette[i][3] = *p++; /* T */
421     }
422
423     i_cmd = *p++;
424     /* We do not really know this, FIXME */
425     if( i_cmd ) {i_cmd_arg = GETINT32(p);}
426
427     /* Actually, this is measured against a different origin, so we have to
428      * adjust it */
429     p_sys->second_field_offset = GETINT16(p);
430     p_sys->i_image_offset  = p - p_block->p_buffer;
431     p_sys->i_image_length  = p_sys->i_spu_size - p_sys->i_image_offset;
432     p_sys->metadata_length = p_sys->i_image_offset;
433
434   if (p_sys && p_sys->i_debug & DECODE_DBG_PACKET) 
435   {
436       msg_Dbg( p_dec, "x-start: %d, y-start: %d, width: %d, height %d, "
437                "spu size: %d, duration: %lu (d:%d p:%d)",
438                p_sys->i_x_start, p_sys->i_y_start, 
439                p_sys->i_width, p_sys->i_height, 
440                p_sys->i_spu_size, (long unsigned int) p_sys->i_duration,
441                p_sys->i_image_length, p_sys->i_image_offset);
442       
443       for( i = 0; i < 4; i++ )
444       {
445           msg_Dbg( p_dec, "palette[%d]= T: %2x, Y: %2x, u: %2x, v: %2x", i,
446                    p_sys->p_palette[i][3], p_sys->p_palette[i][0], 
447                    p_sys->p_palette[i][1], p_sys->p_palette[i][2] );
448       }
449   }
450 }
451
452 /*****************************************************************************
453  * DecodePacket: parse and decode an subtitle packet
454  *****************************************************************************
455  * This function parses and decodes an SPU packet and, if valid, returns a
456  * subpicture.
457  *****************************************************************************/
458 static subpicture_t *DecodePacket( decoder_t *p_dec, block_t *p_data )
459 {
460     decoder_sys_t *p_sys = p_dec->p_sys;
461     subpicture_t  *p_spu;
462     subpicture_region_t *p_region;
463     video_format_t fmt;
464     int i;
465
466     /* Allocate the subpicture internal data. */
467     p_spu = p_dec->pf_spu_buffer_new( p_dec );
468     if( !p_spu ) return NULL;
469
470     p_spu->i_x = p_sys->i_x_start;
471     p_spu->i_y = p_sys->i_y_start;
472     p_spu->i_start = p_data->i_pts;
473     p_spu->i_stop  = p_data->i_pts + p_sys->i_duration;
474     p_spu->b_ephemer = VLC_TRUE;
475
476     /* Create new subtitle region */
477     memset( &fmt, 0, sizeof(video_format_t) );
478     fmt.i_chroma = VLC_FOURCC('Y','U','V','P');
479
480     /**
481        The video on which the subtitle sits, is scaled, probably
482        4:3. However subtitle bitmaps assume an 1:1 aspect ratio.
483
484        FIXME: We should get the video aspect ratio from somewhere.
485        Two candidates are the video and the other possibility would be
486        the access module.
487     */
488     fmt.i_aspect = VOUT_ASPECT_FACTOR;
489
490     fmt.i_width = fmt.i_visible_width = p_sys->i_width;
491     fmt.i_height = fmt.i_visible_height = p_sys->i_height;
492     fmt.i_x_offset = fmt.i_y_offset = 0;
493     p_region = p_spu->pf_create_region( VLC_OBJECT(p_dec), &fmt );
494     if( !p_region )
495     {
496         msg_Err( p_dec, "cannot allocate SVCD subtitle region" );
497         //goto error;
498     }
499
500     p_region->fmt.i_aspect = VOUT_ASPECT_FACTOR;
501     
502     p_spu->p_region = p_region;
503     p_region->i_x = p_region->i_y = 0;
504
505     /* Build palette */
506     fmt.p_palette->i_entries = 4;
507     for( i = 0; i < fmt.p_palette->i_entries; i++ )
508     {
509         fmt.p_palette->palette[i][0] = p_sys->p_palette[i][0];
510         fmt.p_palette->palette[i][1] = p_sys->p_palette[i][1];
511         fmt.p_palette->palette[i][2] = p_sys->p_palette[i][2];
512         fmt.p_palette->palette[i][3] = p_sys->p_palette[i][3];
513     }
514
515     SVCDSubRenderImage( p_dec, p_data, p_region );
516
517     return p_spu;
518 }
519
520 /*****************************************************************************
521  * SVCDSubRenderImage: reorders bytes of image data in subpicture region.
522  *****************************************************************************
523
524  The image is encoded using two bits per pixel that select a palette
525  entry except that value 0 starts a limited run-length encoding for
526  color 0.  When 0 is seen, the next two bits encode one less than the
527  number of pixels, so we can encode run lengths from 1 to 4. These get
528  filled with the color in palette entry 0.
529
530  The encoding of each line is padded to a whole number of bytes.  The
531  first field is padded to an even byte length and the complete subtitle
532  is padded to a 4-byte multiple that always include one zero byte at
533  the end.
534
535  However we'll transform this so that that the RLE is expanded and
536  interlacing will also be removed.
537  *****************************************************************************/
538 static void SVCDSubRenderImage( decoder_t *p_dec, block_t *p_data,
539                                 subpicture_region_t *p_region )
540 {
541     decoder_sys_t *p_sys = p_dec->p_sys;
542     uint8_t *p_dest = p_region->picture.Y_PIXELS;
543     int i_field;            /* The subtitles are interlaced */
544     int i_row, i_column;    /* scanline row/column number */
545     uint8_t i_color, i_count;
546     bs_t bs;
547
548     bs_init( &bs, p_data->p_buffer + p_sys->i_image_offset,
549              p_data->i_buffer - p_sys->i_image_offset );
550
551     for( i_field = 0; i_field < 2; i_field++ )
552     {
553         for( i_row = i_field; i_row < p_sys->i_height; i_row += 2 )
554         {
555             for( i_column = 0; i_column < p_sys->i_width; i_column++ )
556             {
557                 i_color = bs_read( &bs, 2 );
558                 if( i_color == 0 && (i_count = bs_read( &bs, 2 )) )
559                 {
560                     i_count = __MIN( i_count, p_sys->i_width - i_column );
561                     memset( &p_dest[i_row * p_region->picture.Y_PITCH +
562                                     i_column], 0, i_count + 1 );
563                     i_column += i_count;
564                     continue;
565                 }
566
567                 p_dest[i_row * p_region->picture.Y_PITCH + i_column] = i_color;
568             }
569
570             bs_align( &bs );
571         }
572
573         /* odd field */
574         bs_init( &bs, p_data->p_buffer + p_sys->i_image_offset +
575                  p_sys->second_field_offset,
576                  p_data->i_buffer - p_sys->i_image_offset -
577                  p_sys->second_field_offset );
578     }
579 }