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