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