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