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