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_CODEC_OGT )
148 p_dec->p_sys = p_sys = calloc( 1, sizeof( decoder_sys_t ) );
152 p_sys->i_debug = config_GetInt( p_this, MODULE_STRING "-debug" );
156 p_sys->i_state = SUBTITLE_BLOCK_EMPTY;
159 es_format_Init( &p_dec->fmt_out, SPU_ES, VLC_CODEC_OGT );
161 p_dec->pf_decode_sub = Decode;
162 p_dec->pf_packetize = Packetize;
164 dbg_print( (DECODE_DBG_CALL) , "");
168 /*****************************************************************************
169 * PacketizerOpen: open/initialize the svcdsub packetizer.
170 *****************************************************************************/
171 static int PacketizerOpen( vlc_object_t *p_this )
173 if( DecoderOpen( p_this ) != VLC_SUCCESS ) return VLC_EGENERIC;
178 /*****************************************************************************
179 * DecoderClose: closes the svcdsub decoder/packetizer.
180 *****************************************************************************/
181 void DecoderClose( vlc_object_t *p_this )
183 decoder_t *p_dec = (decoder_t*)p_this;
184 decoder_sys_t *p_sys = p_dec->p_sys;
186 if( p_sys->p_spu ) block_ChainRelease( p_sys->p_spu );
190 /*****************************************************************************
192 *****************************************************************************/
193 static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block )
195 block_t *p_block, *p_spu;
196 decoder_sys_t *p_sys = p_dec->p_sys;
198 dbg_print( (DECODE_DBG_CALL) , "");
200 if( pp_block == NULL || *pp_block == NULL ) return NULL;
205 if( !(p_spu = Reassemble( p_dec, p_block )) ) return NULL;
207 /* Parse and decode */
208 return DecodePacket( p_dec, p_spu );
211 /*****************************************************************************
213 *****************************************************************************/
214 static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
216 block_t *p_block, *p_spu;
218 if( pp_block == NULL || *pp_block == NULL ) return NULL;
223 if( !(p_spu = Reassemble( p_dec, p_block )) ) return NULL;
225 p_spu->i_dts = p_spu->i_pts;
231 /*****************************************************************************
234 The data for single screen subtitle may come in one of many
235 non-contiguous packets of a stream. This routine is called when the
236 next packet in the stream comes in. The job of this routine is to
237 parse the header, if this is the beginning, and combine the packets
238 into one complete subtitle unit.
240 If everything is complete, we will return a block. Otherwise return
244 The format of the beginning of the subtitle packet that is used here.
247 -------------------------------------------
248 byte subtitle channel (0..7) in bits 0-3
249 byte subtitle packet number of this subtitle image 0-N,
250 if the subtitle packet is complete, the top bit of the byte is 1.
251 uint16 subtitle image number
253 *****************************************************************************/
254 #define SPU_HEADER_LEN 5
256 static block_t *Reassemble( decoder_t *p_dec, block_t *p_block )
258 decoder_sys_t *p_sys = p_dec->p_sys;
260 uint16_t i_expected_image;
261 uint8_t i_packet, i_expected_packet;
263 if( p_block->i_buffer < SPU_HEADER_LEN )
265 msg_Dbg( p_dec, "invalid packet header (size %zu < %u)" ,
266 p_block->i_buffer, SPU_HEADER_LEN );
267 block_Release( p_block );
271 p_buffer = p_block->p_buffer;
273 /* Attach to our input thread and see if subtitle is selected. */
275 vlc_object_t * p_input;
278 p_input = vlc_object_find( p_dec, VLC_OBJECT_INPUT, FIND_PARENT );
280 if( !p_input ) return NULL;
282 if( var_Get( p_input, "sub-track", &val ) )
284 vlc_object_release( p_input );
288 vlc_object_release( p_input );
289 dbg_print( (DECODE_DBG_PACKET),
290 "val.i_int %x p_buffer[i] %x", val.i_int, p_buffer[1]);
292 /* The dummy ES that the menu selection uses has an 0x70 at
293 the head which we need to strip off. */
294 if( val.i_int == -1 || (val.i_int & 0x03) != p_buffer[1] )
296 dbg_print( DECODE_DBG_PACKET, "subtitle not for us.\n");
301 if( p_sys->i_state == SUBTITLE_BLOCK_EMPTY )
303 i_expected_image = p_sys->i_image + 1;
304 i_expected_packet = 0;
308 i_expected_image = p_sys->i_image;
309 i_expected_packet = p_sys->i_packet + 1;
314 if( *p_buffer & 0x80 )
316 p_sys->i_state = SUBTITLE_BLOCK_COMPLETE;
317 i_packet = *p_buffer++ & 0x7F;
321 p_sys->i_state = SUBTITLE_BLOCK_PARTIAL;
322 i_packet = *p_buffer++;
325 p_sys->i_image = GETINT16(p_buffer);
327 if( p_sys->i_image != i_expected_image )
329 msg_Warn( p_dec, "expected subtitle image %u but found %u",
330 i_expected_image, p_sys->i_image );
333 if( i_packet != i_expected_packet )
335 msg_Warn( p_dec, "expected subtitle image packet %u but found %u",
336 i_expected_packet, i_packet );
339 p_block->p_buffer += SPU_HEADER_LEN;
340 p_block->i_buffer -= SPU_HEADER_LEN;
342 p_sys->i_packet = i_packet;
343 /* First packet in the subtitle block */
344 if( !p_sys->i_packet ) ParseHeader( p_dec, p_block );
346 block_ChainAppend( &p_sys->p_spu, p_block );
348 if( p_sys->i_state == SUBTITLE_BLOCK_COMPLETE )
350 block_t *p_spu = block_ChainGather( p_sys->p_spu );
352 if( p_spu->i_buffer != p_sys->i_spu_size )
354 msg_Warn( p_dec, "subtitle packets size=%zu should be %zu",
355 p_spu->i_buffer, p_sys->i_spu_size );
358 dbg_print( (DECODE_DBG_PACKET),
359 "subtitle packet complete, size=%zu", p_spu->i_buffer );
361 p_sys->i_state = SUBTITLE_BLOCK_EMPTY;
369 /******************************************************************************
370 The format is roughly as follows (everything is big-endian):
373 -------------------------------------------
374 byte subtitle channel (0..7) in bits 0-3
375 byte subtitle packet number of this subtitle image 0-N,
376 if the subtitle packet is complete, the top bit of the byte is 1.
377 u_int16 subtitle image number
378 u_int16 length in bytes of the rest
379 byte option flags, unknown meaning except bit 3 (0x08) indicates
380 presence of the duration field
382 u_int32 duration in 1/90000ths of a second (optional), start time
383 is as indicated by the PTS in the PES header
386 u_int32 width (must be even)
387 u_int32 height (must be even)
388 byte[16] palette, 4 palette entries, each contains values for
389 Y, U, V and transparency, 0 standing for transparent
391 cmd>>6==1 indicates shift
392 (cmd>>4)&3 is direction from, (0=top,1=left,2=right,3=bottom)
393 u_int32 shift duration in 1/90000ths of a second
394 u_int16 offset of odd-numbered scanlines - subtitle images are
395 given in interlace order
396 byte[] limited RLE image data in interlace order (0,2,4... 1,3,5) with
397 2-bits per palette number
398 ******************************************************************************/
399 static void ParseHeader( decoder_t *p_dec, block_t *p_block )
401 decoder_sys_t *p_sys = p_dec->p_sys;
402 uint8_t *p = p_block->p_buffer;
403 uint8_t i_options, i_options2, i_cmd, i_cmd_arg;
406 p_sys->i_spu_size = GETINT16(p);
410 if( i_options & 0x08 ) { p_sys->i_duration = GETINT32(p); }
411 else p_sys->i_duration = 0; /* Ephemer subtitle */
412 p_sys->i_duration *= 100 / 9;
414 p_sys->i_x_start = GETINT16(p);
415 p_sys->i_y_start = GETINT16(p);
416 p_sys->i_width = GETINT16(p);
417 p_sys->i_height = GETINT16(p);
419 for( i = 0; i < 4; i++ )
421 p_sys->p_palette[i][0] = *p++; /* Y */
422 p_sys->p_palette[i][2] = *p++; /* Cr / V */
423 p_sys->p_palette[i][1] = *p++; /* Cb / U */
424 p_sys->p_palette[i][3] = *p++; /* T */
428 /* We do not really know this, FIXME */
429 if( i_cmd ) {i_cmd_arg = GETINT32(p);}
431 /* Actually, this is measured against a different origin, so we have to
433 p_sys->second_field_offset = GETINT16(p);
434 p_sys->i_image_offset = p - p_block->p_buffer;
435 p_sys->i_image_length = p_sys->i_spu_size - p_sys->i_image_offset;
436 p_sys->metadata_length = p_sys->i_image_offset;
438 if( p_sys->i_debug & DECODE_DBG_PACKET )
440 msg_Dbg( p_dec, "x-start: %d, y-start: %d, width: %d, height %d, "
441 "spu size: %zu, duration: %"PRIu64" (d:%zu p:%"PRIu16")",
442 p_sys->i_x_start, p_sys->i_y_start,
443 p_sys->i_width, p_sys->i_height,
444 p_sys->i_spu_size, p_sys->i_duration,
445 p_sys->i_image_length, p_sys->i_image_offset);
447 for( i = 0; i < 4; i++ )
449 msg_Dbg( p_dec, "palette[%d]= T: %2x, Y: %2x, u: %2x, v: %2x", i,
450 p_sys->p_palette[i][3], p_sys->p_palette[i][0],
451 p_sys->p_palette[i][1], p_sys->p_palette[i][2] );
456 /*****************************************************************************
457 * DecodePacket: parse and decode an subtitle packet
458 *****************************************************************************
459 * This function parses and decodes an SPU packet and, if valid, returns a
461 *****************************************************************************/
462 static subpicture_t *DecodePacket( decoder_t *p_dec, block_t *p_data )
464 decoder_sys_t *p_sys = p_dec->p_sys;
466 subpicture_region_t *p_region;
468 video_palette_t palette;
471 /* Allocate the subpicture internal data. */
472 p_spu = decoder_NewSubpicture( p_dec );
473 if( !p_spu ) return NULL;
475 p_spu->i_start = p_data->i_pts;
476 p_spu->i_stop = p_data->i_pts + p_sys->i_duration;
477 p_spu->b_ephemer = true;
479 /* Create new subtitle region */
480 memset( &fmt, 0, sizeof(video_format_t) );
481 fmt.i_chroma = VLC_CODEC_YUVP;
484 The video on which the subtitle sits, is scaled, probably
485 4:3. However subtitle bitmaps assume an 1:1 aspect ratio.
487 FIXME: We should get the video aspect ratio from somewhere.
488 Two candidates are the video and the other possibility would be
491 fmt.i_aspect = VOUT_ASPECT_FACTOR;
493 fmt.i_width = fmt.i_visible_width = p_sys->i_width;
494 fmt.i_height = fmt.i_visible_height = p_sys->i_height;
495 fmt.i_x_offset = fmt.i_y_offset = 0;
496 fmt.p_palette = &palette;
497 fmt.p_palette->i_entries = 4;
498 for( i = 0; i < fmt.p_palette->i_entries; i++ )
500 fmt.p_palette->palette[i][0] = p_sys->p_palette[i][0];
501 fmt.p_palette->palette[i][1] = p_sys->p_palette[i][1];
502 fmt.p_palette->palette[i][2] = p_sys->p_palette[i][2];
503 fmt.p_palette->palette[i][3] = p_sys->p_palette[i][3];
506 p_region = subpicture_region_New( &fmt );
509 msg_Err( p_dec, "cannot allocate SVCD subtitle region" );
510 decoder_DeleteSubpicture( p_dec, p_spu );
514 p_spu->p_region = p_region;
515 p_region->i_x = p_sys->i_x_start;
516 p_region->i_y = p_sys->i_y_start;
518 SVCDSubRenderImage( p_dec, p_data, p_region );
523 /*****************************************************************************
524 * SVCDSubRenderImage: reorders bytes of image data in subpicture region.
525 *****************************************************************************
527 The image is encoded using two bits per pixel that select a palette
528 entry except that value 0 starts a limited run-length encoding for
529 color 0. When 0 is seen, the next two bits encode one less than the
530 number of pixels, so we can encode run lengths from 1 to 4. These get
531 filled with the color in palette entry 0.
533 The encoding of each line is padded to a whole number of bytes. The
534 first field is padded to an even byte length and the complete subtitle
535 is padded to a 4-byte multiple that always include one zero byte at
538 However we'll transform this so that that the RLE is expanded and
539 interlacing will also be removed.
540 *****************************************************************************/
541 static void SVCDSubRenderImage( decoder_t *p_dec, block_t *p_data,
542 subpicture_region_t *p_region )
544 decoder_sys_t *p_sys = p_dec->p_sys;
545 uint8_t *p_dest = p_region->p_picture->Y_PIXELS;
546 int i_field; /* The subtitles are interlaced */
547 int i_row, i_column; /* scanline row/column number */
548 uint8_t i_color, i_count;
551 bs_init( &bs, p_data->p_buffer + p_sys->i_image_offset,
552 p_data->i_buffer - p_sys->i_image_offset );
554 for( i_field = 0; i_field < 2; i_field++ )
556 for( i_row = i_field; i_row < p_sys->i_height; i_row += 2 )
558 for( i_column = 0; i_column < p_sys->i_width; i_column++ )
560 i_color = bs_read( &bs, 2 );
561 if( i_color == 0 && (i_count = bs_read( &bs, 2 )) )
563 i_count = __MIN( i_count, p_sys->i_width - i_column );
564 memset( &p_dest[i_row * p_region->p_picture->Y_PITCH +
565 i_column], 0, i_count + 1 );
570 p_dest[i_row * p_region->p_picture->Y_PITCH + i_column] = i_color;
577 bs_init( &bs, p_data->p_buffer + p_sys->i_image_offset +
578 p_sys->second_field_offset,
579 p_data->i_buffer - p_sys->i_image_offset -
580 p_sys->second_field_offset );