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 *****************************************************************************/
35 #include <vlc_codec.h>
39 /*****************************************************************************
41 *****************************************************************************/
42 static int DecoderOpen ( vlc_object_t * );
43 static int PacketizerOpen( vlc_object_t * );
44 static void DecoderClose ( vlc_object_t * );
46 #define DEBUG_TEXT N_("Enable debug")
48 #define DEBUG_LONGTEXT \
49 N_("This integer when viewed in binary is a debugging mask\n" \
51 "packet assembly info 2\n" )
54 set_description( _("Philips OGT (SVCD subtitle) decoder") );
55 set_shortname( _("SVCD subtitles") );
56 set_category( CAT_INPUT );
57 set_subcategory( SUBCAT_INPUT_SCODEC );
58 set_capability( "decoder", 50 );
59 set_callbacks( DecoderOpen, DecoderClose );
61 add_integer ( MODULE_STRING "-debug", 0, NULL,
62 DEBUG_TEXT, DEBUG_LONGTEXT, VLC_TRUE );
65 set_description( _("Philips OGT (SVCD subtitle) packetizer") );
66 set_capability( "packetizer", 50 );
67 set_callbacks( PacketizerOpen, DecoderClose );
70 /*****************************************************************************
72 *****************************************************************************/
73 static subpicture_t *Decode( decoder_t *, block_t ** );
74 static block_t *Packetize ( decoder_t *, block_t ** );
75 static block_t *Reassemble ( decoder_t *, block_t * );
76 static void ParseHeader( decoder_t *, block_t * );
77 static subpicture_t *DecodePacket( decoder_t *, block_t * );
78 static void SVCDSubRenderImage( decoder_t *, block_t *, subpicture_region_t * );
80 #define DECODE_DBG_CALL 1 /* calls */
81 #define DECODE_DBG_PACKET 2 /* packet assembly info */
83 #define GETINT16(p) ( (p[0] << 8) + p[1] ) ; p +=2;
85 #define GETINT32(p) ( (p[0] << 24) + (p[1] << 16) + \
86 (p[2] << 8) + (p[3]) ) ; p += 4;
89 SUBTITLE_BLOCK_EMPTY = 0,
90 SUBTITLE_BLOCK_PARTIAL = 1,
91 SUBTITLE_BLOCK_COMPLETE = 2
95 #define DECODE_DEBUG 1
98 #define dbg_print(mask, s, args...) \
99 if (p_sys && p_sys->i_debug & mask) \
100 msg_Dbg(p_dec, "%s: "s, __func__ , ##args)
102 #define dbg_print(mask, s, args...)
107 int i_debug; /* debugging mask */
109 packet_state_t i_state; /* data-gathering state for this subtitle */
111 block_t *p_spu; /* Bytes of the packet. */
113 uint16_t i_image; /* image number in the subtitle stream */
114 uint8_t i_packet; /* packet number for above image number */
116 size_t i_spu_size; /* goal for subtitle_data_pos while gathering,
117 size of used subtitle_data later */
119 uint16_t i_image_offset; /* offset from subtitle_data to compressed
121 size_t i_image_length; /* size of the compressed image data */
122 size_t second_field_offset; /* offset of odd raster lines */
123 size_t metadata_offset; /* offset to data describing the image */
124 size_t metadata_length; /* length of metadata */
126 mtime_t i_duration; /* how long to display the image, 0 stands
127 for "until next subtitle" */
129 uint16_t i_x_start, i_y_start; /* position of top leftmost pixel of
130 image when displayed */
131 uint16_t i_width, i_height; /* dimensions in pixels of image */
133 uint8_t p_palette[4][4]; /* Palette of colors used in subtitle */
136 /*****************************************************************************
137 * DecoderOpen: open/initialize the svcdsub decoder.
138 *****************************************************************************/
139 static int DecoderOpen( vlc_object_t *p_this )
141 decoder_t *p_dec = (decoder_t*)p_this;
142 decoder_sys_t *p_sys;
144 if( p_dec->fmt_in.i_codec != VLC_FOURCC( 'o','g','t',' ' ) )
149 p_dec->p_sys = p_sys = calloc( 1, sizeof( decoder_sys_t ) );
150 p_sys->i_debug = config_GetInt( p_this, MODULE_STRING "-debug" );
154 p_sys->i_state = SUBTITLE_BLOCK_EMPTY;
157 es_format_Init( &p_dec->fmt_out, SPU_ES, VLC_FOURCC( 'o','g','t',' ' ) );
159 p_dec->pf_decode_sub = Decode;
160 p_dec->pf_packetize = Packetize;
162 dbg_print( (DECODE_DBG_CALL) , "");
166 /*****************************************************************************
167 * PacketizerOpen: open/initialize the svcdsub packetizer.
168 *****************************************************************************/
169 static int PacketizerOpen( vlc_object_t *p_this )
171 if( DecoderOpen( p_this ) != VLC_SUCCESS ) return VLC_EGENERIC;
176 /*****************************************************************************
177 * DecoderClose: closes the svcdsub decoder/packetizer.
178 *****************************************************************************/
179 void DecoderClose( vlc_object_t *p_this )
181 decoder_t *p_dec = (decoder_t*)p_this;
182 decoder_sys_t *p_sys = p_dec->p_sys;
184 if( p_sys->p_spu ) block_ChainRelease( p_sys->p_spu );
188 /*****************************************************************************
190 *****************************************************************************/
191 static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block )
193 block_t *p_block, *p_spu;
194 decoder_sys_t *p_sys = p_dec->p_sys;
196 dbg_print( (DECODE_DBG_CALL) , "");
198 if( pp_block == NULL || *pp_block == NULL ) return NULL;
203 if( !(p_spu = Reassemble( p_dec, p_block )) ) return NULL;
205 /* Parse and decode */
206 return DecodePacket( p_dec, p_spu );
209 /*****************************************************************************
211 *****************************************************************************/
212 static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
214 block_t *p_block, *p_spu;
216 if( pp_block == NULL || *pp_block == NULL ) return NULL;
221 if( !(p_spu = Reassemble( p_dec, p_block )) ) return NULL;
223 p_spu->i_dts = p_spu->i_pts;
229 /*****************************************************************************
232 The data for single screen subtitle may come in one of many
233 non-contiguous packets of a stream. This routine is called when the
234 next packet in the stream comes in. The job of this routine is to
235 parse the header, if this is the beginning, and combine the packets
236 into one complete subtitle unit.
238 If everything is complete, we will return a block. Otherwise return
242 The format of the beginning of the subtitle packet that is used here.
245 -------------------------------------------
246 byte subtitle channel (0..7) in bits 0-3
247 byte subtitle packet number of this subtitle image 0-N,
248 if the subtitle packet is complete, the top bit of the byte is 1.
249 uint16 subtitle image number
251 *****************************************************************************/
252 #define SPU_HEADER_LEN 5
254 static block_t *Reassemble( decoder_t *p_dec, block_t *p_block )
256 decoder_sys_t *p_sys = p_dec->p_sys;
258 uint16_t i_expected_image;
259 uint8_t i_packet, i_expected_packet;
261 if( p_block->i_buffer < SPU_HEADER_LEN )
263 msg_Dbg( p_dec, "invalid packet header (size %d < %d)" ,
264 p_block->i_buffer, SPU_HEADER_LEN );
265 block_Release( p_block );
269 p_buffer = p_block->p_buffer;
271 /* Attach to our input thread and see if subtitle is selected. */
273 vlc_object_t * p_input;
276 p_input = vlc_object_find( p_dec, VLC_OBJECT_INPUT, FIND_PARENT );
278 if( !p_input ) return NULL;
280 if( var_Get( p_input, "sub-track", &val ) )
282 vlc_object_release( p_input );
286 vlc_object_release( p_input );
287 dbg_print( (DECODE_DBG_PACKET),
288 "val.i_int %x p_buffer[i] %x", val.i_int, p_buffer[1]);
290 /* The dummy ES that the menu selection uses has an 0x70 at
291 the head which we need to strip off. */
292 if( val.i_int == -1 || (val.i_int & 0x03) != p_buffer[1] )
294 dbg_print( DECODE_DBG_PACKET, "subtitle not for us.\n");
299 if( p_sys->i_state == SUBTITLE_BLOCK_EMPTY )
301 i_expected_image = p_sys->i_image + 1;
302 i_expected_packet = 0;
306 i_expected_image = p_sys->i_image;
307 i_expected_packet = p_sys->i_packet + 1;
312 if( *p_buffer & 0x80 )
314 p_sys->i_state = SUBTITLE_BLOCK_COMPLETE;
315 i_packet = *p_buffer++ & 0x7F;
319 p_sys->i_state = SUBTITLE_BLOCK_PARTIAL;
320 i_packet = *p_buffer++;
323 p_sys->i_image = GETINT16(p_buffer);
325 if( p_sys->i_image != i_expected_image )
327 msg_Warn( p_dec, "expected subtitle image %u but found %u",
328 i_expected_image, p_sys->i_image );
331 if( i_packet != i_expected_packet )
333 msg_Warn( p_dec, "expected subtitle image packet %u but found %u",
334 i_expected_packet, i_packet );
337 p_block->p_buffer += SPU_HEADER_LEN;
338 p_block->i_buffer -= SPU_HEADER_LEN;
340 p_sys->i_packet = i_packet;
341 /* First packet in the subtitle block */
342 if( !p_sys->i_packet ) ParseHeader( p_dec, p_block );
344 block_ChainAppend( &p_sys->p_spu, p_block );
346 if( p_sys->i_state == SUBTITLE_BLOCK_COMPLETE )
348 block_t *p_spu = block_ChainGather( p_sys->p_spu );
350 if( p_spu->i_buffer != p_sys->i_spu_size )
352 msg_Warn( p_dec, "subtitle packets size=%d should be %d",
353 p_spu->i_buffer, p_sys->i_spu_size );
356 dbg_print( (DECODE_DBG_PACKET),
357 "subtitle packet complete, size=%d", p_spu->i_buffer );
359 p_sys->i_state = SUBTITLE_BLOCK_EMPTY;
367 /******************************************************************************
368 The format is roughly as follows (everything is big-endian):
371 -------------------------------------------
372 byte subtitle channel (0..7) in bits 0-3
373 byte subtitle packet number of this subtitle image 0-N,
374 if the subtitle packet is complete, the top bit of the byte is 1.
375 u_int16 subtitle image number
376 u_int16 length in bytes of the rest
377 byte option flags, unknown meaning except bit 3 (0x08) indicates
378 presence of the duration field
380 u_int32 duration in 1/90000ths of a second (optional), start time
381 is as indicated by the PTS in the PES header
384 u_int32 width (must be even)
385 u_int32 height (must be even)
386 byte[16] palette, 4 palette entries, each contains values for
387 Y, U, V and transparency, 0 standing for transparent
389 cmd>>6==1 indicates shift
390 (cmd>>4)&3 is direction from, (0=top,1=left,2=right,3=bottom)
391 u_int32 shift duration in 1/90000ths of a second
392 u_int16 offset of odd-numbered scanlines - subtitle images are
393 given in interlace order
394 byte[] limited RLE image data in interlace order (0,2,4... 1,3,5) with
395 2-bits per palette number
396 ******************************************************************************/
397 static void ParseHeader( decoder_t *p_dec, block_t *p_block )
399 decoder_sys_t *p_sys = p_dec->p_sys;
400 uint8_t *p = p_block->p_buffer;
401 uint8_t i_options, i_options2, i_cmd, i_cmd_arg;
404 p_sys->i_spu_size = GETINT16(p);
408 if( i_options & 0x08 ) { p_sys->i_duration = GETINT32(p); }
409 else p_sys->i_duration = 0; /* Ephemer subtitle */
410 p_sys->i_duration *= 100 / 9;
412 p_sys->i_x_start = GETINT16(p);
413 p_sys->i_y_start = GETINT16(p);
414 p_sys->i_width = GETINT16(p);
415 p_sys->i_height = GETINT16(p);
417 for( i = 0; i < 4; i++ )
419 p_sys->p_palette[i][0] = *p++; /* Y */
420 p_sys->p_palette[i][2] = *p++; /* Cr / V */
421 p_sys->p_palette[i][1] = *p++; /* Cb / U */
422 p_sys->p_palette[i][3] = *p++; /* T */
426 /* We do not really know this, FIXME */
427 if( i_cmd ) {i_cmd_arg = GETINT32(p);}
429 /* Actually, this is measured against a different origin, so we have to
431 p_sys->second_field_offset = GETINT16(p);
432 p_sys->i_image_offset = p - p_block->p_buffer;
433 p_sys->i_image_length = p_sys->i_spu_size - p_sys->i_image_offset;
434 p_sys->metadata_length = p_sys->i_image_offset;
436 if (p_sys && p_sys->i_debug & DECODE_DBG_PACKET)
438 msg_Dbg( p_dec, "x-start: %d, y-start: %d, width: %d, height %d, "
439 "spu size: %d, duration: %lu (d:%d p:%d)",
440 p_sys->i_x_start, p_sys->i_y_start,
441 p_sys->i_width, p_sys->i_height,
442 p_sys->i_spu_size, (long unsigned int) p_sys->i_duration,
443 p_sys->i_image_length, p_sys->i_image_offset);
445 for( i = 0; i < 4; i++ )
447 msg_Dbg( p_dec, "palette[%d]= T: %2x, Y: %2x, u: %2x, v: %2x", i,
448 p_sys->p_palette[i][3], p_sys->p_palette[i][0],
449 p_sys->p_palette[i][1], p_sys->p_palette[i][2] );
454 /*****************************************************************************
455 * DecodePacket: parse and decode an subtitle packet
456 *****************************************************************************
457 * This function parses and decodes an SPU packet and, if valid, returns a
459 *****************************************************************************/
460 static subpicture_t *DecodePacket( decoder_t *p_dec, block_t *p_data )
462 decoder_sys_t *p_sys = p_dec->p_sys;
464 subpicture_region_t *p_region;
468 /* Allocate the subpicture internal data. */
469 p_spu = p_dec->pf_spu_buffer_new( p_dec );
470 if( !p_spu ) return NULL;
472 p_spu->b_pausable = VLC_TRUE;
474 p_spu->i_x = p_sys->i_x_start;
475 p_spu->i_y = p_sys->i_y_start;
476 p_spu->i_start = p_data->i_pts;
477 p_spu->i_stop = p_data->i_pts + p_sys->i_duration;
478 p_spu->b_ephemer = VLC_TRUE;
480 /* Create new subtitle region */
481 memset( &fmt, 0, sizeof(video_format_t) );
482 fmt.i_chroma = VLC_FOURCC('Y','U','V','P');
485 The video on which the subtitle sits, is scaled, probably
486 4:3. However subtitle bitmaps assume an 1:1 aspect ratio.
488 FIXME: We should get the video aspect ratio from somewhere.
489 Two candidates are the video and the other possibility would be
492 fmt.i_aspect = VOUT_ASPECT_FACTOR;
494 fmt.i_width = fmt.i_visible_width = p_sys->i_width;
495 fmt.i_height = fmt.i_visible_height = p_sys->i_height;
496 fmt.i_x_offset = fmt.i_y_offset = 0;
497 p_region = p_spu->pf_create_region( VLC_OBJECT(p_dec), &fmt );
500 msg_Err( p_dec, "cannot allocate SVCD subtitle region" );
504 p_region->fmt.i_aspect = VOUT_ASPECT_FACTOR;
506 p_spu->p_region = p_region;
507 p_region->i_x = p_region->i_y = 0;
510 fmt.p_palette->i_entries = 4;
511 for( i = 0; i < fmt.p_palette->i_entries; i++ )
513 fmt.p_palette->palette[i][0] = p_sys->p_palette[i][0];
514 fmt.p_palette->palette[i][1] = p_sys->p_palette[i][1];
515 fmt.p_palette->palette[i][2] = p_sys->p_palette[i][2];
516 fmt.p_palette->palette[i][3] = p_sys->p_palette[i][3];
519 SVCDSubRenderImage( p_dec, p_data, p_region );
524 /*****************************************************************************
525 * SVCDSubRenderImage: reorders bytes of image data in subpicture region.
526 *****************************************************************************
528 The image is encoded using two bits per pixel that select a palette
529 entry except that value 0 starts a limited run-length encoding for
530 color 0. When 0 is seen, the next two bits encode one less than the
531 number of pixels, so we can encode run lengths from 1 to 4. These get
532 filled with the color in palette entry 0.
534 The encoding of each line is padded to a whole number of bytes. The
535 first field is padded to an even byte length and the complete subtitle
536 is padded to a 4-byte multiple that always include one zero byte at
539 However we'll transform this so that that the RLE is expanded and
540 interlacing will also be removed.
541 *****************************************************************************/
542 static void SVCDSubRenderImage( decoder_t *p_dec, block_t *p_data,
543 subpicture_region_t *p_region )
545 decoder_sys_t *p_sys = p_dec->p_sys;
546 uint8_t *p_dest = p_region->picture.Y_PIXELS;
547 int i_field; /* The subtitles are interlaced */
548 int i_row, i_column; /* scanline row/column number */
549 uint8_t i_color, i_count;
552 bs_init( &bs, p_data->p_buffer + p_sys->i_image_offset,
553 p_data->i_buffer - p_sys->i_image_offset );
555 for( i_field = 0; i_field < 2; i_field++ )
557 for( i_row = i_field; i_row < p_sys->i_height; i_row += 2 )
559 for( i_column = 0; i_column < p_sys->i_width; i_column++ )
561 i_color = bs_read( &bs, 2 );
562 if( i_color == 0 && (i_count = bs_read( &bs, 2 )) )
564 i_count = __MIN( i_count, p_sys->i_width - i_column );
565 memset( &p_dest[i_row * p_region->picture.Y_PITCH +
566 i_column], 0, i_count + 1 );
571 p_dest[i_row * p_region->picture.Y_PITCH + i_column] = i_color;
578 bs_init( &bs, p_data->p_buffer + p_sys->i_image_offset +
579 p_sys->second_field_offset,
580 p_data->i_buffer - p_sys->i_image_offset -
581 p_sys->second_field_offset );