1 /*****************************************************************************
2 * svcdsub.c : Overlay Graphics Text (SVCD subtitles) decoder
3 *****************************************************************************
4 * Copyright (C) 2003, 2004 the VideoLAN team
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>
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.
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.
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 *****************************************************************************/
27 /*****************************************************************************
29 *****************************************************************************/
31 #include <vlc_codec.h>
35 /*****************************************************************************
37 *****************************************************************************/
38 static int DecoderOpen ( vlc_object_t * );
39 static int PacketizerOpen( vlc_object_t * );
40 static void DecoderClose ( vlc_object_t * );
42 #define DEBUG_TEXT N_("Enable debug")
44 #define DEBUG_LONGTEXT \
45 N_("This integer when viewed in binary is a debugging mask\n" \
47 "packet assembly info 2\n" )
50 set_description( _("Philips OGT (SVCD subtitle) decoder") );
51 set_shortname( _("SVCD subtitles") );
52 set_category( CAT_INPUT );
53 set_subcategory( SUBCAT_INPUT_SCODEC );
54 set_capability( "decoder", 50 );
55 set_callbacks( DecoderOpen, DecoderClose );
57 add_integer ( MODULE_STRING "-debug", 0, NULL,
58 DEBUG_TEXT, DEBUG_LONGTEXT, VLC_TRUE );
61 set_description( _("Philips OGT (SVCD subtitle) packetizer") );
62 set_capability( "packetizer", 50 );
63 set_callbacks( PacketizerOpen, DecoderClose );
66 /*****************************************************************************
68 *****************************************************************************/
69 static subpicture_t *Decode( decoder_t *, block_t ** );
70 static block_t *Packetize ( decoder_t *, block_t ** );
71 static block_t *Reassemble ( decoder_t *, block_t * );
72 static void ParseHeader( decoder_t *, block_t * );
73 static subpicture_t *DecodePacket( decoder_t *, block_t * );
74 static void SVCDSubRenderImage( decoder_t *, block_t *, subpicture_region_t * );
76 #define DECODE_DBG_CALL 1 /* calls */
77 #define DECODE_DBG_PACKET 2 /* packet assembly info */
79 #define GETINT16(p) ( (p[0] << 8) + p[1] ) ; p +=2;
81 #define GETINT32(p) ( (p[0] << 24) + (p[1] << 16) + \
82 (p[2] << 8) + (p[3]) ) ; p += 4;
85 SUBTITLE_BLOCK_EMPTY = 0,
86 SUBTITLE_BLOCK_PARTIAL = 1,
87 SUBTITLE_BLOCK_COMPLETE = 2
91 #define DECODE_DEBUG 1
94 #define dbg_print(mask, s, args...) \
95 if (p_sys && p_sys->i_debug & mask) \
96 msg_Dbg(p_dec, "%s: "s, __func__ , ##args)
98 #define dbg_print(mask, s, args...)
103 int i_debug; /* debugging mask */
105 packet_state_t i_state; /* data-gathering state for this subtitle */
107 block_t *p_spu; /* Bytes of the packet. */
109 uint16_t i_image; /* image number in the subtitle stream */
110 uint8_t i_packet; /* packet number for above image number */
112 int i_spu_size; /* goal for subtitle_data_pos while gathering,
113 size of used subtitle_data later */
115 uint16_t i_image_offset; /* offset from subtitle_data to compressed
117 int i_image_length; /* size of the compressed image data */
118 int second_field_offset; /* offset of odd raster lines */
119 int metadata_offset; /* offset to data describing the image */
120 int metadata_length; /* length of metadata */
122 mtime_t i_duration; /* how long to display the image, 0 stands
123 for "until next subtitle" */
125 uint16_t i_x_start, i_y_start; /* position of top leftmost pixel of
126 image when displayed */
127 uint16_t i_width, i_height; /* dimensions in pixels of image */
129 uint8_t p_palette[4][4]; /* Palette of colors used in subtitle */
132 /*****************************************************************************
133 * DecoderOpen: open/initialize the svcdsub decoder.
134 *****************************************************************************/
135 static int DecoderOpen( vlc_object_t *p_this )
137 decoder_t *p_dec = (decoder_t*)p_this;
138 decoder_sys_t *p_sys;
140 if( p_dec->fmt_in.i_codec != VLC_FOURCC( 'o','g','t',' ' ) )
145 p_dec->p_sys = p_sys = calloc( 1, sizeof( decoder_sys_t ) );
146 p_sys->i_debug = config_GetInt( p_this, MODULE_STRING "-debug" );
150 p_sys->i_state = SUBTITLE_BLOCK_EMPTY;
153 es_format_Init( &p_dec->fmt_out, SPU_ES, VLC_FOURCC( 'o','g','t',' ' ) );
155 p_dec->pf_decode_sub = Decode;
156 p_dec->pf_packetize = Packetize;
158 dbg_print( (DECODE_DBG_CALL) , "");
162 /*****************************************************************************
163 * PacketizerOpen: open/initialize the svcdsub packetizer.
164 *****************************************************************************/
165 static int PacketizerOpen( vlc_object_t *p_this )
167 if( DecoderOpen( p_this ) != VLC_SUCCESS ) return VLC_EGENERIC;
172 /*****************************************************************************
173 * DecoderClose: closes the svcdsub decoder/packetizer.
174 *****************************************************************************/
175 void DecoderClose( vlc_object_t *p_this )
177 decoder_t *p_dec = (decoder_t*)p_this;
178 decoder_sys_t *p_sys = p_dec->p_sys;
180 if( p_sys->p_spu ) block_ChainRelease( p_sys->p_spu );
184 /*****************************************************************************
186 *****************************************************************************/
187 static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block )
189 block_t *p_block, *p_spu;
190 decoder_sys_t *p_sys = p_dec->p_sys;
192 dbg_print( (DECODE_DBG_CALL) , "");
194 if( pp_block == NULL || *pp_block == NULL ) return NULL;
199 if( !(p_spu = Reassemble( p_dec, p_block )) ) return NULL;
201 /* Parse and decode */
202 return DecodePacket( p_dec, p_spu );
205 /*****************************************************************************
207 *****************************************************************************/
208 static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
210 block_t *p_block, *p_spu;
212 if( pp_block == NULL || *pp_block == NULL ) return NULL;
217 if( !(p_spu = Reassemble( p_dec, p_block )) ) return NULL;
219 p_spu->i_dts = p_spu->i_pts;
225 /*****************************************************************************
228 The data for single screen subtitle may come in one of many
229 non-contiguous packets of a stream. This routine is called when the
230 next packet in the stream comes in. The job of this routine is to
231 parse the header, if this is the beginning, and combine the packets
232 into one complete subtitle unit.
234 If everything is complete, we will return a block. Otherwise return
238 The format of the beginning of the subtitle packet that is used here.
241 -------------------------------------------
242 byte subtitle channel (0..7) in bits 0-3
243 byte subtitle packet number of this subtitle image 0-N,
244 if the subtitle packet is complete, the top bit of the byte is 1.
245 uint16 subtitle image number
247 *****************************************************************************/
248 #define SPU_HEADER_LEN 5
250 static block_t *Reassemble( decoder_t *p_dec, block_t *p_block )
252 decoder_sys_t *p_sys = p_dec->p_sys;
254 uint16_t i_expected_image;
255 uint8_t i_packet, i_expected_packet;
257 if( p_block->i_buffer < SPU_HEADER_LEN )
259 msg_Dbg( p_dec, "invalid packet header (size %d < %d)" ,
260 p_block->i_buffer, SPU_HEADER_LEN );
261 block_Release( p_block );
265 p_buffer = p_block->p_buffer;
267 /* Attach to our input thread and see if subtitle is selected. */
269 vlc_object_t * p_input;
272 p_input = vlc_object_find( p_dec, VLC_OBJECT_INPUT, FIND_PARENT );
274 if( !p_input ) return NULL;
276 if( var_Get( p_input, "sub-track", &val ) )
278 vlc_object_release( p_input );
282 vlc_object_release( p_input );
283 dbg_print( (DECODE_DBG_PACKET),
284 "val.i_int %x p_buffer[i] %x", val.i_int, p_buffer[1]);
286 /* The dummy ES that the menu selection uses has an 0x70 at
287 the head which we need to strip off. */
288 if( val.i_int == -1 || (val.i_int & 0x03) != p_buffer[1] )
290 dbg_print( DECODE_DBG_PACKET, "subtitle not for us.\n");
295 if( p_sys->i_state == SUBTITLE_BLOCK_EMPTY )
297 i_expected_image = p_sys->i_image + 1;
298 i_expected_packet = 0;
302 i_expected_image = p_sys->i_image;
303 i_expected_packet = p_sys->i_packet + 1;
308 if( *p_buffer & 0x80 )
310 p_sys->i_state = SUBTITLE_BLOCK_COMPLETE;
311 i_packet = *p_buffer++ & 0x7F;
315 p_sys->i_state = SUBTITLE_BLOCK_PARTIAL;
316 i_packet = *p_buffer++;
319 p_sys->i_image = GETINT16(p_buffer);
321 if( p_sys->i_image != i_expected_image )
323 msg_Warn( p_dec, "expected subtitle image %u but found %u",
324 i_expected_image, p_sys->i_image );
327 if( i_packet != i_expected_packet )
329 msg_Warn( p_dec, "expected subtitle image packet %u but found %u",
330 i_expected_packet, i_packet );
333 p_block->p_buffer += SPU_HEADER_LEN;
334 p_block->i_buffer -= SPU_HEADER_LEN;
336 p_sys->i_packet = i_packet;
337 /* First packet in the subtitle block */
338 if( !p_sys->i_packet ) ParseHeader( p_dec, p_block );
340 block_ChainAppend( &p_sys->p_spu, p_block );
342 if( p_sys->i_state == SUBTITLE_BLOCK_COMPLETE )
344 block_t *p_spu = block_ChainGather( p_sys->p_spu );
346 if( p_spu->i_buffer != p_sys->i_spu_size )
348 msg_Warn( p_dec, "subtitle packets size=%d should be %d",
349 p_spu->i_buffer, p_sys->i_spu_size );
352 dbg_print( (DECODE_DBG_PACKET),
353 "subtitle packet complete, size=%d", p_spu->i_buffer );
355 p_sys->i_state = SUBTITLE_BLOCK_EMPTY;
363 /******************************************************************************
364 The format is roughly as follows (everything is big-endian):
367 -------------------------------------------
368 byte subtitle channel (0..7) in bits 0-3
369 byte subtitle packet number of this subtitle image 0-N,
370 if the subtitle packet is complete, the top bit of the byte is 1.
371 u_int16 subtitle image number
372 u_int16 length in bytes of the rest
373 byte option flags, unknown meaning except bit 3 (0x08) indicates
374 presence of the duration field
376 u_int32 duration in 1/90000ths of a second (optional), start time
377 is as indicated by the PTS in the PES header
380 u_int32 width (must be even)
381 u_int32 height (must be even)
382 byte[16] palette, 4 palette entries, each contains values for
383 Y, U, V and transparency, 0 standing for transparent
385 cmd>>6==1 indicates shift
386 (cmd>>4)&3 is direction from, (0=top,1=left,2=right,3=bottom)
387 u_int32 shift duration in 1/90000ths of a second
388 u_int16 offset of odd-numbered scanlines - subtitle images are
389 given in interlace order
390 byte[] limited RLE image data in interlace order (0,2,4... 1,3,5) with
391 2-bits per palette number
392 ******************************************************************************/
393 static void ParseHeader( decoder_t *p_dec, block_t *p_block )
395 decoder_sys_t *p_sys = p_dec->p_sys;
396 uint8_t *p = p_block->p_buffer;
397 uint8_t i_options, i_options2, i_cmd, i_cmd_arg;
400 p_sys->i_spu_size = GETINT16(p);
404 if( i_options & 0x08 ) { p_sys->i_duration = GETINT32(p); }
405 else p_sys->i_duration = 0; /* Ephemer subtitle */
406 p_sys->i_duration *= 100 / 9;
408 p_sys->i_x_start = GETINT16(p);
409 p_sys->i_y_start = GETINT16(p);
410 p_sys->i_width = GETINT16(p);
411 p_sys->i_height = GETINT16(p);
413 for( i = 0; i < 4; i++ )
415 p_sys->p_palette[i][0] = *p++; /* Y */
416 p_sys->p_palette[i][2] = *p++; /* Cr / V */
417 p_sys->p_palette[i][1] = *p++; /* Cb / U */
418 p_sys->p_palette[i][3] = *p++; /* T */
422 /* We do not really know this, FIXME */
423 if( i_cmd ) {i_cmd_arg = GETINT32(p);}
425 /* Actually, this is measured against a different origin, so we have to
427 p_sys->second_field_offset = GETINT16(p);
428 p_sys->i_image_offset = p - p_block->p_buffer;
429 p_sys->i_image_length = p_sys->i_spu_size - p_sys->i_image_offset;
430 p_sys->metadata_length = p_sys->i_image_offset;
432 if (p_sys && p_sys->i_debug & DECODE_DBG_PACKET)
434 msg_Dbg( p_dec, "x-start: %d, y-start: %d, width: %d, height %d, "
435 "spu size: %d, duration: %lu (d:%d p:%d)",
436 p_sys->i_x_start, p_sys->i_y_start,
437 p_sys->i_width, p_sys->i_height,
438 p_sys->i_spu_size, (long unsigned int) p_sys->i_duration,
439 p_sys->i_image_length, p_sys->i_image_offset);
441 for( i = 0; i < 4; i++ )
443 msg_Dbg( p_dec, "palette[%d]= T: %2x, Y: %2x, u: %2x, v: %2x", i,
444 p_sys->p_palette[i][3], p_sys->p_palette[i][0],
445 p_sys->p_palette[i][1], p_sys->p_palette[i][2] );
450 /*****************************************************************************
451 * DecodePacket: parse and decode an subtitle packet
452 *****************************************************************************
453 * This function parses and decodes an SPU packet and, if valid, returns a
455 *****************************************************************************/
456 static subpicture_t *DecodePacket( decoder_t *p_dec, block_t *p_data )
458 decoder_sys_t *p_sys = p_dec->p_sys;
460 subpicture_region_t *p_region;
464 /* Allocate the subpicture internal data. */
465 p_spu = p_dec->pf_spu_buffer_new( p_dec );
466 if( !p_spu ) return NULL;
468 p_spu->b_pausable = VLC_TRUE;
470 p_spu->i_x = p_sys->i_x_start;
471 p_spu->i_y = p_sys->i_y_start;
472 p_spu->i_start = p_data->i_pts;
473 p_spu->i_stop = p_data->i_pts + p_sys->i_duration;
474 p_spu->b_ephemer = VLC_TRUE;
476 /* Create new subtitle region */
477 memset( &fmt, 0, sizeof(video_format_t) );
478 fmt.i_chroma = VLC_FOURCC('Y','U','V','P');
481 The video on which the subtitle sits, is scaled, probably
482 4:3. However subtitle bitmaps assume an 1:1 aspect ratio.
484 FIXME: We should get the video aspect ratio from somewhere.
485 Two candidates are the video and the other possibility would be
488 fmt.i_aspect = VOUT_ASPECT_FACTOR;
490 fmt.i_width = fmt.i_visible_width = p_sys->i_width;
491 fmt.i_height = fmt.i_visible_height = p_sys->i_height;
492 fmt.i_x_offset = fmt.i_y_offset = 0;
493 p_region = p_spu->pf_create_region( VLC_OBJECT(p_dec), &fmt );
496 msg_Err( p_dec, "cannot allocate SVCD subtitle region" );
500 p_region->fmt.i_aspect = VOUT_ASPECT_FACTOR;
502 p_spu->p_region = p_region;
503 p_region->i_x = p_region->i_y = 0;
506 fmt.p_palette->i_entries = 4;
507 for( i = 0; i < fmt.p_palette->i_entries; i++ )
509 fmt.p_palette->palette[i][0] = p_sys->p_palette[i][0];
510 fmt.p_palette->palette[i][1] = p_sys->p_palette[i][1];
511 fmt.p_palette->palette[i][2] = p_sys->p_palette[i][2];
512 fmt.p_palette->palette[i][3] = p_sys->p_palette[i][3];
515 SVCDSubRenderImage( p_dec, p_data, p_region );
520 /*****************************************************************************
521 * SVCDSubRenderImage: reorders bytes of image data in subpicture region.
522 *****************************************************************************
524 The image is encoded using two bits per pixel that select a palette
525 entry except that value 0 starts a limited run-length encoding for
526 color 0. When 0 is seen, the next two bits encode one less than the
527 number of pixels, so we can encode run lengths from 1 to 4. These get
528 filled with the color in palette entry 0.
530 The encoding of each line is padded to a whole number of bytes. The
531 first field is padded to an even byte length and the complete subtitle
532 is padded to a 4-byte multiple that always include one zero byte at
535 However we'll transform this so that that the RLE is expanded and
536 interlacing will also be removed.
537 *****************************************************************************/
538 static void SVCDSubRenderImage( decoder_t *p_dec, block_t *p_data,
539 subpicture_region_t *p_region )
541 decoder_sys_t *p_sys = p_dec->p_sys;
542 uint8_t *p_dest = p_region->picture.Y_PIXELS;
543 int i_field; /* The subtitles are interlaced */
544 int i_row, i_column; /* scanline row/column number */
545 uint8_t i_color, i_count;
548 bs_init( &bs, p_data->p_buffer + p_sys->i_image_offset,
549 p_data->i_buffer - p_sys->i_image_offset );
551 for( i_field = 0; i_field < 2; i_field++ )
553 for( i_row = i_field; i_row < p_sys->i_height; i_row += 2 )
555 for( i_column = 0; i_column < p_sys->i_width; i_column++ )
557 i_color = bs_read( &bs, 2 );
558 if( i_color == 0 && (i_count = bs_read( &bs, 2 )) )
560 i_count = __MIN( i_count, p_sys->i_width - i_column );
561 memset( &p_dest[i_row * p_region->picture.Y_PITCH +
562 i_column], 0, i_count + 1 );
567 p_dest[i_row * p_region->picture.Y_PITCH + i_column] = i_color;
574 bs_init( &bs, p_data->p_buffer + p_sys->i_image_offset +
575 p_sys->second_field_offset,
576 p_data->i_buffer - p_sys->i_image_offset -
577 p_sys->second_field_offset );