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