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