]> git.sesse.net Git - vlc/blob - modules/codec/svcdsub.c
Removes trailing spaces. Removes tabs.
[vlc] / modules / codec / svcdsub.c
1 /*****************************************************************************
2  * svcdsub.c : Overlay Graphics Text (SVCD subtitles) decoder
3  *****************************************************************************
4  * Copyright (C) 2003, 2004 the VideoLAN team
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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25  *****************************************************************************/
26
27 /*****************************************************************************
28  * Preamble
29  *****************************************************************************/
30 #include <vlc/vlc.h>
31 #include <vlc_codec.h>
32 #include <vlc_osd.h>
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_("Enable debug")
43
44 #define DEBUG_LONGTEXT  \
45     N_("This integer when viewed in binary is a debugging mask\n" \
46     "calls                 1\n" \
47     "packet assembly info  2\n" )
48
49 vlc_module_begin();
50     set_description( _("Philips OGT (SVCD subtitle) decoder") );
51     set_shortname( _("SVCD subtitles") );
52     set_category( CAT_INPUT );
53     set_subcategory( SUBCAT_INPUT_SCODEC );
54     set_capability( "decoder", 50 );
55     set_callbacks( DecoderOpen, DecoderClose );
56
57     add_integer ( MODULE_STRING "-debug", 0, NULL,
58                   DEBUG_TEXT, DEBUG_LONGTEXT, VLC_TRUE );
59
60     add_submodule();
61     set_description( _("Philips OGT (SVCD subtitle) packetizer") );
62     set_capability( "packetizer", 50 );
63     set_callbacks( PacketizerOpen, DecoderClose );
64 vlc_module_end();
65
66 /*****************************************************************************
67  * Local prototypes
68  *****************************************************************************/
69 static subpicture_t *Decode( decoder_t *, block_t ** );
70 static block_t *Packetize  ( decoder_t *, block_t ** );
71 static block_t *Reassemble ( decoder_t *, block_t * );
72 static void ParseHeader( decoder_t *, block_t * );
73 static subpicture_t *DecodePacket( decoder_t *, block_t * );
74 static void SVCDSubRenderImage( decoder_t *, block_t *, subpicture_region_t * );
75
76 #define DECODE_DBG_CALL        1 /* calls */
77 #define DECODE_DBG_PACKET      2 /* packet assembly info */
78
79 #define GETINT16(p) ( (p[0] <<  8) +   p[1] )  ; p +=2;
80
81 #define GETINT32(p) ( (p[0] << 24) +  (p[1] << 16) +    \
82                       (p[2] <<  8) +  (p[3]) ) ; p += 4;
83
84 typedef enum  {
85   SUBTITLE_BLOCK_EMPTY    = 0,
86   SUBTITLE_BLOCK_PARTIAL  = 1,
87   SUBTITLE_BLOCK_COMPLETE = 2
88 } packet_state_t;
89
90 #ifndef DECODE_DEBUG
91 #define DECODE_DEBUG 1
92 #endif
93 #if DECODE_DEBUG
94 #define dbg_print(mask, s, args...) \
95    if (p_sys && p_sys->i_debug & mask) \
96      msg_Dbg(p_dec, "%s: "s, __func__ , ##args)
97 #else
98 #define dbg_print(mask, s, args...)
99 #endif
100
101 struct decoder_sys_t
102 {
103   int      i_debug;       /* debugging mask */
104
105   packet_state_t i_state; /* data-gathering state for this subtitle */
106
107   block_t  *p_spu;        /* Bytes of the packet. */
108
109   uint16_t i_image;       /* image number in the subtitle stream */
110   uint8_t  i_packet;      /* packet number for above image number */
111
112   int     i_spu_size;     /* goal for subtitle_data_pos while gathering,
113                              size of used subtitle_data later */
114
115   uint16_t i_image_offset;      /* offset from subtitle_data to compressed
116                                    image data */
117   int i_image_length;           /* size of the compressed image data */
118   int second_field_offset;      /* offset of odd raster lines */
119   int metadata_offset;          /* offset to data describing the image */
120   int metadata_length;          /* length of metadata */
121
122   mtime_t i_duration;   /* how long to display the image, 0 stands
123                            for "until next subtitle" */
124
125   uint16_t i_x_start, i_y_start; /* position of top leftmost pixel of
126                                     image when displayed */
127   uint16_t i_width, i_height;    /* dimensions in pixels of image */
128
129   uint8_t p_palette[4][4];       /* Palette of colors used in subtitle */
130 };
131
132 /*****************************************************************************
133  * DecoderOpen: open/initialize the svcdsub decoder.
134  *****************************************************************************/
135 static int DecoderOpen( vlc_object_t *p_this )
136 {
137     decoder_t     *p_dec = (decoder_t*)p_this;
138     decoder_sys_t *p_sys;
139
140     if( p_dec->fmt_in.i_codec != VLC_FOURCC( 'o','g','t',' ' ) )
141     {
142         return VLC_EGENERIC;
143     }
144
145     p_dec->p_sys = p_sys = calloc( 1, sizeof( decoder_sys_t ) );
146     p_sys->i_debug       = config_GetInt( p_this, MODULE_STRING "-debug" );
147
148     p_sys->i_image       = -1;
149
150     p_sys->i_state = SUBTITLE_BLOCK_EMPTY;
151     p_sys->p_spu   = NULL;
152
153     es_format_Init( &p_dec->fmt_out, SPU_ES, VLC_FOURCC( 'o','g','t',' ' ) );
154
155     p_dec->pf_decode_sub = Decode;
156     p_dec->pf_packetize  = Packetize;
157
158     dbg_print( (DECODE_DBG_CALL) , "");
159     return VLC_SUCCESS;
160 }
161
162 /*****************************************************************************
163  * PacketizerOpen: open/initialize the svcdsub packetizer.
164  *****************************************************************************/
165 static int PacketizerOpen( vlc_object_t *p_this )
166 {
167     if( DecoderOpen( p_this ) != VLC_SUCCESS ) return VLC_EGENERIC;
168
169     return VLC_SUCCESS;
170 }
171
172 /*****************************************************************************
173  * DecoderClose: closes the svcdsub decoder/packetizer.
174  *****************************************************************************/
175 void DecoderClose( vlc_object_t *p_this )
176 {
177     decoder_t     *p_dec = (decoder_t*)p_this;
178     decoder_sys_t *p_sys = p_dec->p_sys;
179
180     if( p_sys->p_spu ) block_ChainRelease( p_sys->p_spu );
181     free( p_sys );
182 }
183
184 /*****************************************************************************
185  * Decode:
186  *****************************************************************************/
187 static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block )
188 {
189     block_t *p_block, *p_spu;
190     decoder_sys_t *p_sys = p_dec->p_sys;
191
192     dbg_print( (DECODE_DBG_CALL) , "");
193
194     if( pp_block == NULL || *pp_block == NULL ) return NULL;
195
196     p_block = *pp_block;
197     *pp_block = NULL;
198
199     if( !(p_spu = Reassemble( p_dec, p_block )) ) return NULL;
200
201     /* Parse and decode */
202     return DecodePacket( p_dec, p_spu );
203 }
204
205 /*****************************************************************************
206  * Packetize:
207  *****************************************************************************/
208 static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
209 {
210     block_t *p_block, *p_spu;
211
212     if( pp_block == NULL || *pp_block == NULL ) return NULL;
213
214     p_block = *pp_block;
215     *pp_block = NULL;
216
217     if( !(p_spu = Reassemble( p_dec, p_block )) ) return NULL;
218
219     p_spu->i_dts = p_spu->i_pts;
220     p_spu->i_length = 0;
221
222     return p_spu;
223 }
224
225 /*****************************************************************************
226  Reassemble:
227
228  The data for single screen subtitle may come in one of many
229  non-contiguous packets of a stream. This routine is called when the
230  next packet in the stream comes in. The job of this routine is to
231  parse the header, if this is the beginning, and combine the packets
232  into one complete subtitle unit.
233
234  If everything is complete, we will return a block. Otherwise return
235  NULL.
236
237
238  The format of the beginning of the subtitle packet that is used here.
239
240    size    description
241    -------------------------------------------
242    byte    subtitle channel (0..7) in bits 0-3
243    byte    subtitle packet number of this subtitle image 0-N,
244            if the subtitle packet is complete, the top bit of the byte is 1.
245    uint16  subtitle image number
246
247  *****************************************************************************/
248 #define SPU_HEADER_LEN 5
249
250 static block_t *Reassemble( decoder_t *p_dec, block_t *p_block )
251 {
252     decoder_sys_t *p_sys = p_dec->p_sys;
253     uint8_t *p_buffer;
254     uint16_t i_expected_image;
255     uint8_t  i_packet, i_expected_packet;
256
257     if( p_block->i_buffer < SPU_HEADER_LEN )
258     {
259         msg_Dbg( p_dec, "invalid packet header (size %d < %d)" ,
260                  p_block->i_buffer, SPU_HEADER_LEN );
261         block_Release( p_block );
262         return NULL;
263     }
264
265     p_buffer = p_block->p_buffer;
266
267     /* Attach to our input thread and see if subtitle is selected. */
268     {
269         vlc_object_t * p_input;
270         vlc_value_t val;
271
272         p_input = vlc_object_find( p_dec, VLC_OBJECT_INPUT, FIND_PARENT );
273
274         if( !p_input ) return NULL;
275
276         if( var_Get( p_input, "sub-track", &val ) )
277         {
278             vlc_object_release( p_input );
279             return NULL;
280         }
281
282         vlc_object_release( p_input );
283         dbg_print( (DECODE_DBG_PACKET),
284                    "val.i_int %x p_buffer[i] %x", val.i_int, p_buffer[1]);
285
286         /* The dummy ES that the menu selection uses has an 0x70 at
287            the head which we need to strip off. */
288         if( val.i_int == -1 || (val.i_int & 0x03) != p_buffer[1] )
289         {
290             dbg_print( DECODE_DBG_PACKET, "subtitle not for us.\n");
291             return NULL;
292         }
293     }
294
295     if( p_sys->i_state == SUBTITLE_BLOCK_EMPTY )
296     {
297         i_expected_image  = p_sys->i_image + 1;
298         i_expected_packet = 0;
299     }
300     else
301     {
302         i_expected_image  = p_sys->i_image;
303         i_expected_packet = p_sys->i_packet + 1;
304     }
305
306     p_buffer += 2;
307
308     if( *p_buffer & 0x80 )
309     {
310         p_sys->i_state = SUBTITLE_BLOCK_COMPLETE;
311         i_packet       = *p_buffer++ & 0x7F;
312     }
313     else
314     {
315         p_sys->i_state = SUBTITLE_BLOCK_PARTIAL;
316         i_packet       = *p_buffer++;
317     }
318
319     p_sys->i_image = GETINT16(p_buffer);
320
321     if( p_sys->i_image != i_expected_image )
322     {
323         msg_Warn( p_dec, "expected subtitle image %u but found %u",
324                   i_expected_image, p_sys->i_image );
325     }
326
327     if( i_packet != i_expected_packet )
328     {
329         msg_Warn( p_dec, "expected subtitle image packet %u but found %u",
330                   i_expected_packet, i_packet );
331     }
332
333     p_block->p_buffer += SPU_HEADER_LEN;
334     p_block->i_buffer -= SPU_HEADER_LEN;
335
336     p_sys->i_packet = i_packet;
337     /* First packet in the subtitle block */
338     if( !p_sys->i_packet ) ParseHeader( p_dec, p_block );
339
340     block_ChainAppend( &p_sys->p_spu, p_block );
341
342     if( p_sys->i_state == SUBTITLE_BLOCK_COMPLETE )
343     {
344         block_t *p_spu = block_ChainGather( p_sys->p_spu );
345
346         if( p_spu->i_buffer != p_sys->i_spu_size )
347         {
348             msg_Warn( p_dec, "subtitle packets size=%d should be %d",
349                       p_spu->i_buffer, p_sys->i_spu_size );
350         }
351
352     dbg_print( (DECODE_DBG_PACKET),
353                  "subtitle packet complete, size=%d", p_spu->i_buffer );
354
355         p_sys->i_state = SUBTITLE_BLOCK_EMPTY;
356         p_sys->p_spu = 0;
357         return p_spu;
358     }
359
360     return NULL;
361 }
362
363 /******************************************************************************
364   The format is roughly as follows (everything is big-endian):
365  
366    size     description
367    -------------------------------------------
368    byte     subtitle channel (0..7) in bits 0-3
369    byte     subtitle packet number of this subtitle image 0-N,
370             if the subtitle packet is complete, the top bit of the byte is 1.
371    u_int16  subtitle image number
372    u_int16  length in bytes of the rest
373    byte     option flags, unknown meaning except bit 3 (0x08) indicates
374             presence of the duration field
375    byte     unknown
376    u_int32  duration in 1/90000ths of a second (optional), start time
377             is as indicated by the PTS in the PES header
378    u_int32  xpos
379    u_int32  ypos
380    u_int32  width (must be even)
381    u_int32  height (must be even)
382    byte[16] palette, 4 palette entries, each contains values for
383             Y, U, V and transparency, 0 standing for transparent
384    byte     command,
385             cmd>>6==1 indicates shift
386             (cmd>>4)&3 is direction from, (0=top,1=left,2=right,3=bottom)
387    u_int32  shift duration in 1/90000ths of a second
388    u_int16  offset of odd-numbered scanlines - subtitle images are
389             given in interlace order
390    byte[]   limited RLE image data in interlace order (0,2,4... 1,3,5) with
391             2-bits per palette number
392 ******************************************************************************/
393 static void ParseHeader( decoder_t *p_dec, block_t *p_block )
394 {
395     decoder_sys_t *p_sys = p_dec->p_sys;
396     uint8_t *p = p_block->p_buffer;
397     uint8_t i_options, i_options2, i_cmd, i_cmd_arg;
398     int i;
399
400     p_sys->i_spu_size = GETINT16(p);
401     i_options  = *p++;
402     i_options2 = *p++;
403
404     if( i_options & 0x08 ) { p_sys->i_duration = GETINT32(p); }
405     else p_sys->i_duration = 0; /* Ephemer subtitle */
406     p_sys->i_duration *= 100 / 9;
407
408     p_sys->i_x_start = GETINT16(p);
409     p_sys->i_y_start = GETINT16(p);
410     p_sys->i_width   = GETINT16(p);
411     p_sys->i_height  = GETINT16(p);
412
413     for( i = 0; i < 4; i++ )
414     {
415         p_sys->p_palette[i][0] = *p++; /* Y */
416         p_sys->p_palette[i][2] = *p++; /* Cr / V */
417         p_sys->p_palette[i][1] = *p++; /* Cb / U */
418         p_sys->p_palette[i][3] = *p++; /* T */
419     }
420
421     i_cmd = *p++;
422     /* We do not really know this, FIXME */
423     if( i_cmd ) {i_cmd_arg = GETINT32(p);}
424
425     /* Actually, this is measured against a different origin, so we have to
426      * adjust it */
427     p_sys->second_field_offset = GETINT16(p);
428     p_sys->i_image_offset  = p - p_block->p_buffer;
429     p_sys->i_image_length  = p_sys->i_spu_size - p_sys->i_image_offset;
430     p_sys->metadata_length = p_sys->i_image_offset;
431
432   if (p_sys && p_sys->i_debug & DECODE_DBG_PACKET)
433   {
434       msg_Dbg( p_dec, "x-start: %d, y-start: %d, width: %d, height %d, "
435            "spu size: %d, duration: %lu (d:%d p:%d)",
436            p_sys->i_x_start, p_sys->i_y_start,
437            p_sys->i_width, p_sys->i_height,
438            p_sys->i_spu_size, (long unsigned int) p_sys->i_duration,
439            p_sys->i_image_length, p_sys->i_image_offset);
440  
441       for( i = 0; i < 4; i++ )
442       {
443           msg_Dbg( p_dec, "palette[%d]= T: %2x, Y: %2x, u: %2x, v: %2x", i,
444            p_sys->p_palette[i][3], p_sys->p_palette[i][0],
445            p_sys->p_palette[i][1], p_sys->p_palette[i][2] );
446       }
447   }
448 }
449
450 /*****************************************************************************
451  * DecodePacket: parse and decode an subtitle packet
452  *****************************************************************************
453  * This function parses and decodes an SPU packet and, if valid, returns a
454  * subpicture.
455  *****************************************************************************/
456 static subpicture_t *DecodePacket( decoder_t *p_dec, block_t *p_data )
457 {
458     decoder_sys_t *p_sys = p_dec->p_sys;
459     subpicture_t  *p_spu;
460     subpicture_region_t *p_region;
461     video_format_t fmt;
462     int i;
463
464     /* Allocate the subpicture internal data. */
465     p_spu = p_dec->pf_spu_buffer_new( p_dec );
466     if( !p_spu ) return NULL;
467
468     p_spu->b_pausable = VLC_TRUE;
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 }