]> git.sesse.net Git - vlc/blob - modules/codec/svcdsub.c
macosx: fixed menubar appearance in fullscreen mode by partially reverting [46c93c9cc...
[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_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     if( p_sys == NULL )
152         return VLC_ENOMEM;
153
154     p_sys->i_debug       = config_GetInt( p_this, MODULE_STRING "-debug" );
155
156     p_sys->i_image       = -1;
157
158     p_sys->i_state = SUBTITLE_BLOCK_EMPTY;
159     p_sys->p_spu   = NULL;
160
161     es_format_Init( &p_dec->fmt_out, SPU_ES, VLC_FOURCC( 'o','g','t',' ' ) );
162
163     p_dec->pf_decode_sub = Decode;
164     p_dec->pf_packetize  = Packetize;
165
166     dbg_print( (DECODE_DBG_CALL) , "");
167     return VLC_SUCCESS;
168 }
169
170 /*****************************************************************************
171  * PacketizerOpen: open/initialize the svcdsub packetizer.
172  *****************************************************************************/
173 static int PacketizerOpen( vlc_object_t *p_this )
174 {
175     if( DecoderOpen( p_this ) != VLC_SUCCESS ) return VLC_EGENERIC;
176
177     return VLC_SUCCESS;
178 }
179
180 /*****************************************************************************
181  * DecoderClose: closes the svcdsub decoder/packetizer.
182  *****************************************************************************/
183 void DecoderClose( vlc_object_t *p_this )
184 {
185     decoder_t     *p_dec = (decoder_t*)p_this;
186     decoder_sys_t *p_sys = p_dec->p_sys;
187
188     if( p_sys->p_spu ) block_ChainRelease( p_sys->p_spu );
189     free( p_sys );
190 }
191
192 /*****************************************************************************
193  * Decode:
194  *****************************************************************************/
195 static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block )
196 {
197     block_t *p_block, *p_spu;
198     decoder_sys_t *p_sys = p_dec->p_sys;
199
200     dbg_print( (DECODE_DBG_CALL) , "");
201
202     if( pp_block == NULL || *pp_block == NULL ) return NULL;
203
204     p_block = *pp_block;
205     *pp_block = NULL;
206
207     if( !(p_spu = Reassemble( p_dec, p_block )) ) return NULL;
208
209     /* Parse and decode */
210     return DecodePacket( p_dec, p_spu );
211 }
212
213 /*****************************************************************************
214  * Packetize:
215  *****************************************************************************/
216 static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
217 {
218     block_t *p_block, *p_spu;
219
220     if( pp_block == NULL || *pp_block == NULL ) return NULL;
221
222     p_block = *pp_block;
223     *pp_block = NULL;
224
225     if( !(p_spu = Reassemble( p_dec, p_block )) ) return NULL;
226
227     p_spu->i_dts = p_spu->i_pts;
228     p_spu->i_length = 0;
229
230     return p_spu;
231 }
232
233 /*****************************************************************************
234  Reassemble:
235
236  The data for single screen subtitle may come in one of many
237  non-contiguous packets of a stream. This routine is called when the
238  next packet in the stream comes in. The job of this routine is to
239  parse the header, if this is the beginning, and combine the packets
240  into one complete subtitle unit.
241
242  If everything is complete, we will return a block. Otherwise return
243  NULL.
244
245
246  The format of the beginning of the subtitle packet that is used here.
247
248    size    description
249    -------------------------------------------
250    byte    subtitle channel (0..7) in bits 0-3
251    byte    subtitle packet number of this subtitle image 0-N,
252            if the subtitle packet is complete, the top bit of the byte is 1.
253    uint16  subtitle image number
254
255  *****************************************************************************/
256 #define SPU_HEADER_LEN 5
257
258 static block_t *Reassemble( decoder_t *p_dec, block_t *p_block )
259 {
260     decoder_sys_t *p_sys = p_dec->p_sys;
261     uint8_t *p_buffer;
262     uint16_t i_expected_image;
263     uint8_t  i_packet, i_expected_packet;
264
265     if( p_block->i_buffer < SPU_HEADER_LEN )
266     {
267         msg_Dbg( p_dec, "invalid packet header (size %zu < %u)" ,
268                  p_block->i_buffer, SPU_HEADER_LEN );
269         block_Release( p_block );
270         return NULL;
271     }
272
273     p_buffer = p_block->p_buffer;
274
275     /* Attach to our input thread and see if subtitle is selected. */
276     {
277         vlc_object_t * p_input;
278         vlc_value_t val;
279
280         p_input = vlc_object_find( p_dec, VLC_OBJECT_INPUT, FIND_PARENT );
281
282         if( !p_input ) return NULL;
283
284         if( var_Get( p_input, "sub-track", &val ) )
285         {
286             vlc_object_release( p_input );
287             return NULL;
288         }
289
290         vlc_object_release( p_input );
291         dbg_print( (DECODE_DBG_PACKET),
292                    "val.i_int %x p_buffer[i] %x", val.i_int, p_buffer[1]);
293
294         /* The dummy ES that the menu selection uses has an 0x70 at
295            the head which we need to strip off. */
296         if( val.i_int == -1 || (val.i_int & 0x03) != p_buffer[1] )
297         {
298             dbg_print( DECODE_DBG_PACKET, "subtitle not for us.\n");
299             return NULL;
300         }
301     }
302
303     if( p_sys->i_state == SUBTITLE_BLOCK_EMPTY )
304     {
305         i_expected_image  = p_sys->i_image + 1;
306         i_expected_packet = 0;
307     }
308     else
309     {
310         i_expected_image  = p_sys->i_image;
311         i_expected_packet = p_sys->i_packet + 1;
312     }
313
314     p_buffer += 2;
315
316     if( *p_buffer & 0x80 )
317     {
318         p_sys->i_state = SUBTITLE_BLOCK_COMPLETE;
319         i_packet       = *p_buffer++ & 0x7F;
320     }
321     else
322     {
323         p_sys->i_state = SUBTITLE_BLOCK_PARTIAL;
324         i_packet       = *p_buffer++;
325     }
326
327     p_sys->i_image = GETINT16(p_buffer);
328
329     if( p_sys->i_image != i_expected_image )
330     {
331         msg_Warn( p_dec, "expected subtitle image %u but found %u",
332                   i_expected_image, p_sys->i_image );
333     }
334
335     if( i_packet != i_expected_packet )
336     {
337         msg_Warn( p_dec, "expected subtitle image packet %u but found %u",
338                   i_expected_packet, i_packet );
339     }
340
341     p_block->p_buffer += SPU_HEADER_LEN;
342     p_block->i_buffer -= SPU_HEADER_LEN;
343
344     p_sys->i_packet = i_packet;
345     /* First packet in the subtitle block */
346     if( !p_sys->i_packet ) ParseHeader( p_dec, p_block );
347
348     block_ChainAppend( &p_sys->p_spu, p_block );
349
350     if( p_sys->i_state == SUBTITLE_BLOCK_COMPLETE )
351     {
352         block_t *p_spu = block_ChainGather( p_sys->p_spu );
353
354         if( p_spu->i_buffer != p_sys->i_spu_size )
355         {
356             msg_Warn( p_dec, "subtitle packets size=%zu should be %zu",
357                       p_spu->i_buffer, p_sys->i_spu_size );
358         }
359
360     dbg_print( (DECODE_DBG_PACKET),
361                  "subtitle packet complete, size=%zu", p_spu->i_buffer );
362
363         p_sys->i_state = SUBTITLE_BLOCK_EMPTY;
364         p_sys->p_spu = 0;
365         return p_spu;
366     }
367
368     return NULL;
369 }
370
371 /******************************************************************************
372   The format is roughly as follows (everything is big-endian):
373  
374    size     description
375    -------------------------------------------
376    byte     subtitle channel (0..7) in bits 0-3
377    byte     subtitle packet number of this subtitle image 0-N,
378             if the subtitle packet is complete, the top bit of the byte is 1.
379    u_int16  subtitle image number
380    u_int16  length in bytes of the rest
381    byte     option flags, unknown meaning except bit 3 (0x08) indicates
382             presence of the duration field
383    byte     unknown
384    u_int32  duration in 1/90000ths of a second (optional), start time
385             is as indicated by the PTS in the PES header
386    u_int32  xpos
387    u_int32  ypos
388    u_int32  width (must be even)
389    u_int32  height (must be even)
390    byte[16] palette, 4 palette entries, each contains values for
391             Y, U, V and transparency, 0 standing for transparent
392    byte     command,
393             cmd>>6==1 indicates shift
394             (cmd>>4)&3 is direction from, (0=top,1=left,2=right,3=bottom)
395    u_int32  shift duration in 1/90000ths of a second
396    u_int16  offset of odd-numbered scanlines - subtitle images are
397             given in interlace order
398    byte[]   limited RLE image data in interlace order (0,2,4... 1,3,5) with
399             2-bits per palette number
400 ******************************************************************************/
401 static void ParseHeader( decoder_t *p_dec, block_t *p_block )
402 {
403     decoder_sys_t *p_sys = p_dec->p_sys;
404     uint8_t *p = p_block->p_buffer;
405     uint8_t i_options, i_options2, i_cmd, i_cmd_arg;
406     int i;
407
408     p_sys->i_spu_size = GETINT16(p);
409     i_options  = *p++;
410     i_options2 = *p++;
411
412     if( i_options & 0x08 ) { p_sys->i_duration = GETINT32(p); }
413     else p_sys->i_duration = 0; /* Ephemer subtitle */
414     p_sys->i_duration *= 100 / 9;
415
416     p_sys->i_x_start = GETINT16(p);
417     p_sys->i_y_start = GETINT16(p);
418     p_sys->i_width   = GETINT16(p);
419     p_sys->i_height  = GETINT16(p);
420
421     for( i = 0; i < 4; i++ )
422     {
423         p_sys->p_palette[i][0] = *p++; /* Y */
424         p_sys->p_palette[i][2] = *p++; /* Cr / V */
425         p_sys->p_palette[i][1] = *p++; /* Cb / U */
426         p_sys->p_palette[i][3] = *p++; /* T */
427     }
428
429     i_cmd = *p++;
430     /* We do not really know this, FIXME */
431     if( i_cmd ) {i_cmd_arg = GETINT32(p);}
432
433     /* Actually, this is measured against a different origin, so we have to
434      * adjust it */
435     p_sys->second_field_offset = GETINT16(p);
436     p_sys->i_image_offset  = p - p_block->p_buffer;
437     p_sys->i_image_length  = p_sys->i_spu_size - p_sys->i_image_offset;
438     p_sys->metadata_length = p_sys->i_image_offset;
439
440   if( p_sys->i_debug & DECODE_DBG_PACKET )
441   {
442       msg_Dbg( p_dec, "x-start: %d, y-start: %d, width: %d, height %d, "
443            "spu size: %zu, duration: %"PRIu64" (d:%zu p:%"PRIu16")",
444            p_sys->i_x_start, p_sys->i_y_start,
445            p_sys->i_width, p_sys->i_height,
446            p_sys->i_spu_size, p_sys->i_duration,
447            p_sys->i_image_length, p_sys->i_image_offset);
448
449       for( i = 0; i < 4; i++ )
450       {
451           msg_Dbg( p_dec, "palette[%d]= T: %2x, Y: %2x, u: %2x, v: %2x", i,
452            p_sys->p_palette[i][3], p_sys->p_palette[i][0],
453            p_sys->p_palette[i][1], p_sys->p_palette[i][2] );
454       }
455   }
456 }
457
458 /*****************************************************************************
459  * DecodePacket: parse and decode an subtitle packet
460  *****************************************************************************
461  * This function parses and decodes an SPU packet and, if valid, returns a
462  * subpicture.
463  *****************************************************************************/
464 static subpicture_t *DecodePacket( decoder_t *p_dec, block_t *p_data )
465 {
466     decoder_sys_t *p_sys = p_dec->p_sys;
467     subpicture_t  *p_spu;
468     subpicture_region_t *p_region;
469     video_format_t fmt;
470     video_palette_t palette;
471     int i;
472
473     /* Allocate the subpicture internal data. */
474     p_spu = decoder_NewSubpicture( p_dec );
475     if( !p_spu ) return NULL;
476
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     fmt.p_palette = &palette;
499     fmt.p_palette->i_entries = 4;
500     for( i = 0; i < fmt.p_palette->i_entries; i++ )
501     {
502         fmt.p_palette->palette[i][0] = p_sys->p_palette[i][0];
503         fmt.p_palette->palette[i][1] = p_sys->p_palette[i][1];
504         fmt.p_palette->palette[i][2] = p_sys->p_palette[i][2];
505         fmt.p_palette->palette[i][3] = p_sys->p_palette[i][3];
506     }
507
508     p_region = subpicture_region_New( &fmt );
509     if( !p_region )
510     {
511         msg_Err( p_dec, "cannot allocate SVCD subtitle region" );
512         decoder_DeleteSubpicture( p_dec, p_spu );
513         return NULL;
514     }
515
516     p_spu->p_region = p_region;
517     p_region->i_x = p_sys->i_x_start;
518     p_region->i_y = p_sys->i_y_start;
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->p_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->p_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->p_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 }