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 *****************************************************************************/
34 #include <vlc_common.h>
35 #include <vlc_plugin.h>
36 #include <vlc_codec.h>
40 /*****************************************************************************
42 *****************************************************************************/
43 static int DecoderOpen ( vlc_object_t * );
44 static int PacketizerOpen( vlc_object_t * );
45 static void DecoderClose ( vlc_object_t * );
47 #define DEBUG_TEXT N_("Enable debug")
49 #define DEBUG_LONGTEXT \
50 N_("This integer when viewed in binary is a debugging mask\n" \
52 "packet assembly info 2\n" )
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 );
62 add_integer ( MODULE_STRING "-debug", 0, NULL,
63 DEBUG_TEXT, DEBUG_LONGTEXT, true );
66 set_description( N_("Philips OGT (SVCD subtitle) packetizer") );
67 set_capability( "packetizer", 50 );
68 set_callbacks( PacketizerOpen, DecoderClose );
71 /*****************************************************************************
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 * );
81 #define DECODE_DBG_CALL 1 /* calls */
82 #define DECODE_DBG_PACKET 2 /* packet assembly info */
84 #define GETINT16(p) ( (p[0] << 8) + p[1] ) ; p +=2;
86 #define GETINT32(p) ( (p[0] << 24) + (p[1] << 16) + \
87 (p[2] << 8) + (p[3]) ) ; p += 4;
90 SUBTITLE_BLOCK_EMPTY = 0,
91 SUBTITLE_BLOCK_PARTIAL = 1,
92 SUBTITLE_BLOCK_COMPLETE = 2
96 #define DECODE_DEBUG 1
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)
103 #define dbg_print(mask, s, args...)
108 int i_debug; /* debugging mask */
110 packet_state_t i_state; /* data-gathering state for this subtitle */
112 block_t *p_spu; /* Bytes of the packet. */
114 uint16_t i_image; /* image number in the subtitle stream */
115 uint8_t i_packet; /* packet number for above image number */
117 size_t i_spu_size; /* goal for subtitle_data_pos while gathering,
118 size of used subtitle_data later */
120 uint16_t i_image_offset; /* offset from subtitle_data to compressed
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 */
127 mtime_t i_duration; /* how long to display the image, 0 stands
128 for "until next subtitle" */
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 */
134 uint8_t p_palette[4][4]; /* Palette of colors used in subtitle */
137 /*****************************************************************************
138 * DecoderOpen: open/initialize the svcdsub decoder.
139 *****************************************************************************/
140 static int DecoderOpen( vlc_object_t *p_this )
142 decoder_t *p_dec = (decoder_t*)p_this;
143 decoder_sys_t *p_sys;
145 if( p_dec->fmt_in.i_codec != VLC_FOURCC( 'o','g','t',' ' ) )
150 p_dec->p_sys = p_sys = calloc( 1, sizeof( decoder_sys_t ) );
151 p_sys->i_debug = config_GetInt( p_this, MODULE_STRING "-debug" );
155 p_sys->i_state = SUBTITLE_BLOCK_EMPTY;
158 es_format_Init( &p_dec->fmt_out, SPU_ES, VLC_FOURCC( 'o','g','t',' ' ) );
160 p_dec->pf_decode_sub = Decode;
161 p_dec->pf_packetize = Packetize;
163 dbg_print( (DECODE_DBG_CALL) , "");
167 /*****************************************************************************
168 * PacketizerOpen: open/initialize the svcdsub packetizer.
169 *****************************************************************************/
170 static int PacketizerOpen( vlc_object_t *p_this )
172 if( DecoderOpen( p_this ) != VLC_SUCCESS ) return VLC_EGENERIC;
177 /*****************************************************************************
178 * DecoderClose: closes the svcdsub decoder/packetizer.
179 *****************************************************************************/
180 void DecoderClose( vlc_object_t *p_this )
182 decoder_t *p_dec = (decoder_t*)p_this;
183 decoder_sys_t *p_sys = p_dec->p_sys;
185 if( p_sys->p_spu ) block_ChainRelease( p_sys->p_spu );
189 /*****************************************************************************
191 *****************************************************************************/
192 static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block )
194 block_t *p_block, *p_spu;
195 decoder_sys_t *p_sys = p_dec->p_sys;
197 dbg_print( (DECODE_DBG_CALL) , "");
199 if( pp_block == NULL || *pp_block == NULL ) return NULL;
204 if( !(p_spu = Reassemble( p_dec, p_block )) ) return NULL;
206 /* Parse and decode */
207 return DecodePacket( p_dec, p_spu );
210 /*****************************************************************************
212 *****************************************************************************/
213 static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
215 block_t *p_block, *p_spu;
217 if( pp_block == NULL || *pp_block == NULL ) return NULL;
222 if( !(p_spu = Reassemble( p_dec, p_block )) ) return NULL;
224 p_spu->i_dts = p_spu->i_pts;
230 /*****************************************************************************
233 The data for single screen subtitle may come in one of many
234 non-contiguous packets of a stream. This routine is called when the
235 next packet in the stream comes in. The job of this routine is to
236 parse the header, if this is the beginning, and combine the packets
237 into one complete subtitle unit.
239 If everything is complete, we will return a block. Otherwise return
243 The format of the beginning of the subtitle packet that is used here.
246 -------------------------------------------
247 byte subtitle channel (0..7) in bits 0-3
248 byte subtitle packet number of this subtitle image 0-N,
249 if the subtitle packet is complete, the top bit of the byte is 1.
250 uint16 subtitle image number
252 *****************************************************************************/
253 #define SPU_HEADER_LEN 5
255 static block_t *Reassemble( decoder_t *p_dec, block_t *p_block )
257 decoder_sys_t *p_sys = p_dec->p_sys;
259 uint16_t i_expected_image;
260 uint8_t i_packet, i_expected_packet;
262 if( p_block->i_buffer < SPU_HEADER_LEN )
264 msg_Dbg( p_dec, "invalid packet header (size %zu < %u)" ,
265 p_block->i_buffer, SPU_HEADER_LEN );
266 block_Release( p_block );
270 p_buffer = p_block->p_buffer;
272 /* Attach to our input thread and see if subtitle is selected. */
274 vlc_object_t * p_input;
277 p_input = vlc_object_find( p_dec, VLC_OBJECT_INPUT, FIND_PARENT );
279 if( !p_input ) return NULL;
281 if( var_Get( p_input, "sub-track", &val ) )
283 vlc_object_release( p_input );
287 vlc_object_release( p_input );
288 dbg_print( (DECODE_DBG_PACKET),
289 "val.i_int %x p_buffer[i] %x", val.i_int, p_buffer[1]);
291 /* The dummy ES that the menu selection uses has an 0x70 at
292 the head which we need to strip off. */
293 if( val.i_int == -1 || (val.i_int & 0x03) != p_buffer[1] )
295 dbg_print( DECODE_DBG_PACKET, "subtitle not for us.\n");
300 if( p_sys->i_state == SUBTITLE_BLOCK_EMPTY )
302 i_expected_image = p_sys->i_image + 1;
303 i_expected_packet = 0;
307 i_expected_image = p_sys->i_image;
308 i_expected_packet = p_sys->i_packet + 1;
313 if( *p_buffer & 0x80 )
315 p_sys->i_state = SUBTITLE_BLOCK_COMPLETE;
316 i_packet = *p_buffer++ & 0x7F;
320 p_sys->i_state = SUBTITLE_BLOCK_PARTIAL;
321 i_packet = *p_buffer++;
324 p_sys->i_image = GETINT16(p_buffer);
326 if( p_sys->i_image != i_expected_image )
328 msg_Warn( p_dec, "expected subtitle image %u but found %u",
329 i_expected_image, p_sys->i_image );
332 if( i_packet != i_expected_packet )
334 msg_Warn( p_dec, "expected subtitle image packet %u but found %u",
335 i_expected_packet, i_packet );
338 p_block->p_buffer += SPU_HEADER_LEN;
339 p_block->i_buffer -= SPU_HEADER_LEN;
341 p_sys->i_packet = i_packet;
342 /* First packet in the subtitle block */
343 if( !p_sys->i_packet ) ParseHeader( p_dec, p_block );
345 block_ChainAppend( &p_sys->p_spu, p_block );
347 if( p_sys->i_state == SUBTITLE_BLOCK_COMPLETE )
349 block_t *p_spu = block_ChainGather( p_sys->p_spu );
351 if( p_spu->i_buffer != p_sys->i_spu_size )
353 msg_Warn( p_dec, "subtitle packets size=%zu should be %zu",
354 p_spu->i_buffer, p_sys->i_spu_size );
357 dbg_print( (DECODE_DBG_PACKET),
358 "subtitle packet complete, size=%zu", p_spu->i_buffer );
360 p_sys->i_state = SUBTITLE_BLOCK_EMPTY;
368 /******************************************************************************
369 The format is roughly as follows (everything is big-endian):
372 -------------------------------------------
373 byte subtitle channel (0..7) in bits 0-3
374 byte subtitle packet number of this subtitle image 0-N,
375 if the subtitle packet is complete, the top bit of the byte is 1.
376 u_int16 subtitle image number
377 u_int16 length in bytes of the rest
378 byte option flags, unknown meaning except bit 3 (0x08) indicates
379 presence of the duration field
381 u_int32 duration in 1/90000ths of a second (optional), start time
382 is as indicated by the PTS in the PES header
385 u_int32 width (must be even)
386 u_int32 height (must be even)
387 byte[16] palette, 4 palette entries, each contains values for
388 Y, U, V and transparency, 0 standing for transparent
390 cmd>>6==1 indicates shift
391 (cmd>>4)&3 is direction from, (0=top,1=left,2=right,3=bottom)
392 u_int32 shift duration in 1/90000ths of a second
393 u_int16 offset of odd-numbered scanlines - subtitle images are
394 given in interlace order
395 byte[] limited RLE image data in interlace order (0,2,4... 1,3,5) with
396 2-bits per palette number
397 ******************************************************************************/
398 static void ParseHeader( decoder_t *p_dec, block_t *p_block )
400 decoder_sys_t *p_sys = p_dec->p_sys;
401 uint8_t *p = p_block->p_buffer;
402 uint8_t i_options, i_options2, i_cmd, i_cmd_arg;
405 p_sys->i_spu_size = GETINT16(p);
409 if( i_options & 0x08 ) { p_sys->i_duration = GETINT32(p); }
410 else p_sys->i_duration = 0; /* Ephemer subtitle */
411 p_sys->i_duration *= 100 / 9;
413 p_sys->i_x_start = GETINT16(p);
414 p_sys->i_y_start = GETINT16(p);
415 p_sys->i_width = GETINT16(p);
416 p_sys->i_height = GETINT16(p);
418 for( i = 0; i < 4; i++ )
420 p_sys->p_palette[i][0] = *p++; /* Y */
421 p_sys->p_palette[i][2] = *p++; /* Cr / V */
422 p_sys->p_palette[i][1] = *p++; /* Cb / U */
423 p_sys->p_palette[i][3] = *p++; /* T */
427 /* We do not really know this, FIXME */
428 if( i_cmd ) {i_cmd_arg = GETINT32(p);}
430 /* Actually, this is measured against a different origin, so we have to
432 p_sys->second_field_offset = GETINT16(p);
433 p_sys->i_image_offset = p - p_block->p_buffer;
434 p_sys->i_image_length = p_sys->i_spu_size - p_sys->i_image_offset;
435 p_sys->metadata_length = p_sys->i_image_offset;
437 if (p_sys && p_sys->i_debug & DECODE_DBG_PACKET)
439 msg_Dbg( p_dec, "x-start: %d, y-start: %d, width: %d, height %d, "
440 "spu size: %zu, duration: %"PRIu64" (d:%zu p:%"PRIu16")",
441 p_sys->i_x_start, p_sys->i_y_start,
442 p_sys->i_width, p_sys->i_height,
443 p_sys->i_spu_size, p_sys->i_duration,
444 p_sys->i_image_length, p_sys->i_image_offset);
446 for( i = 0; i < 4; i++ )
448 msg_Dbg( p_dec, "palette[%d]= T: %2x, Y: %2x, u: %2x, v: %2x", i,
449 p_sys->p_palette[i][3], p_sys->p_palette[i][0],
450 p_sys->p_palette[i][1], p_sys->p_palette[i][2] );
455 /*****************************************************************************
456 * DecodePacket: parse and decode an subtitle packet
457 *****************************************************************************
458 * This function parses and decodes an SPU packet and, if valid, returns a
460 *****************************************************************************/
461 static subpicture_t *DecodePacket( decoder_t *p_dec, block_t *p_data )
463 decoder_sys_t *p_sys = p_dec->p_sys;
465 subpicture_region_t *p_region;
469 /* Allocate the subpicture internal data. */
470 p_spu = p_dec->pf_spu_buffer_new( p_dec );
471 if( !p_spu ) return NULL;
473 p_spu->b_pausable = true;
475 p_spu->i_x = p_sys->i_x_start;
476 p_spu->i_y = p_sys->i_y_start;
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;
481 /* Create new subtitle region */
482 memset( &fmt, 0, sizeof(video_format_t) );
483 fmt.i_chroma = VLC_FOURCC('Y','U','V','P');
486 The video on which the subtitle sits, is scaled, probably
487 4:3. However subtitle bitmaps assume an 1:1 aspect ratio.
489 FIXME: We should get the video aspect ratio from somewhere.
490 Two candidates are the video and the other possibility would be
493 fmt.i_aspect = VOUT_ASPECT_FACTOR;
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 p_region = p_spu->pf_create_region( VLC_OBJECT(p_dec), &fmt );
501 msg_Err( p_dec, "cannot allocate SVCD subtitle region" );
505 p_region->fmt.i_aspect = VOUT_ASPECT_FACTOR;
507 p_spu->p_region = p_region;
508 p_region->i_x = p_region->i_y = 0;
511 fmt.p_palette->i_entries = 4;
512 for( i = 0; i < fmt.p_palette->i_entries; i++ )
514 fmt.p_palette->palette[i][0] = p_sys->p_palette[i][0];
515 fmt.p_palette->palette[i][1] = p_sys->p_palette[i][1];
516 fmt.p_palette->palette[i][2] = p_sys->p_palette[i][2];
517 fmt.p_palette->palette[i][3] = p_sys->p_palette[i][3];
520 SVCDSubRenderImage( p_dec, p_data, p_region );
525 /*****************************************************************************
526 * SVCDSubRenderImage: reorders bytes of image data in subpicture region.
527 *****************************************************************************
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.
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
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 )
546 decoder_sys_t *p_sys = p_dec->p_sys;
547 uint8_t *p_dest = p_region->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;
553 bs_init( &bs, p_data->p_buffer + p_sys->i_image_offset,
554 p_data->i_buffer - p_sys->i_image_offset );
556 for( i_field = 0; i_field < 2; i_field++ )
558 for( i_row = i_field; i_row < p_sys->i_height; i_row += 2 )
560 for( i_column = 0; i_column < p_sys->i_width; i_column++ )
562 i_color = bs_read( &bs, 2 );
563 if( i_color == 0 && (i_count = bs_read( &bs, 2 )) )
565 i_count = __MIN( i_count, p_sys->i_width - i_column );
566 memset( &p_dest[i_row * p_region->picture.Y_PITCH +
567 i_column], 0, i_count + 1 );
572 p_dest[i_row * p_region->picture.Y_PITCH + i_column] = i_color;
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 );