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