1 /*****************************************************************************
2 * svcdsub.c : Overlay Graphics Text (SVCD subtitles) decoder
3 *****************************************************************************
4 * Copyright (C) 2003, 2004 VideoLAN
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., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
25 *****************************************************************************/
29 /*****************************************************************************
31 *****************************************************************************/
33 #include <vlc/decoder.h>
37 /*****************************************************************************
39 *****************************************************************************/
40 static int DecoderOpen ( vlc_object_t * );
41 static int PacketizerOpen( vlc_object_t * );
42 static void DecoderClose ( vlc_object_t * );
45 set_description( _("Philips OGT (SVCD subtitle) decoder") );
46 set_capability( "decoder", 50 );
47 set_callbacks( DecoderOpen, DecoderClose );
50 set_description( _("Philips OGT (SVCD subtitle) packetizer") );
51 set_capability( "packetizer", 50 );
52 set_callbacks( PacketizerOpen, DecoderClose );
55 /*****************************************************************************
57 *****************************************************************************/
58 static subpicture_t *Decode( decoder_t *, block_t ** );
59 static block_t *Packetize ( decoder_t *, block_t ** );
60 static block_t *Reassemble ( decoder_t *, block_t * );
61 static void ParseHeader( decoder_t *, block_t * );
62 static subpicture_t *DecodePacket( decoder_t *, block_t * );
63 static void RenderImage( decoder_t *, block_t *, subpicture_region_t * );
65 #define GETINT16(p) ( (p[0] << 8) + p[1] ) ; p +=2;
67 #define GETINT32(p) ( (p[0] << 24) + (p[1] << 16) + \
68 (p[2] << 8) + (p[3]) ) ; p += 4;
70 #define SUBTITLE_BLOCK_EMPTY 0
71 #define SUBTITLE_BLOCK_PARTIAL 1
72 #define SUBTITLE_BLOCK_COMPLETE 2
78 int i_state; /* data-gathering state for this subtitle */
80 block_t *p_spu; /* Bytes of the packet. */
82 uint16_t i_image; /* image number in the subtitle stream */
83 uint8_t i_packet; /* packet number for above image number */
85 int i_spu_size; /* goal for subtitle_data_pos while gathering,
86 size of used subtitle_data later */
88 uint16_t i_image_offset; /* offset from subtitle_data to compressed
90 int i_image_length; /* size of the compressed image data */
91 int second_field_offset; /* offset of odd raster lines */
92 int metadata_offset; /* offset to data describing the image */
93 int metadata_length; /* length of metadata */
95 mtime_t i_duration; /* how long to display the image, 0 stands
96 for "until next subtitle" */
98 uint16_t i_x_start, i_y_start; /* position of top leftmost pixel of
99 image when displayed */
100 uint16_t i_width, i_height; /* dimensions in pixels of image */
102 uint8_t p_palette[4][4]; /* Palette of colors used in subtitle */
105 /*****************************************************************************
106 * DecoderOpen: open/initialize the svcdsub decoder.
107 *****************************************************************************/
108 static int DecoderOpen( vlc_object_t *p_this )
110 decoder_t *p_dec = (decoder_t*)p_this;
111 decoder_sys_t *p_sys;
113 if( p_dec->fmt_in.i_codec != VLC_FOURCC( 'o','g','t',' ' ) )
118 p_dec->p_sys = p_sys = malloc( sizeof( decoder_sys_t ) );
120 p_sys->b_packetizer = VLC_FALSE;
123 p_sys->i_state = SUBTITLE_BLOCK_EMPTY;
126 es_format_Init( &p_dec->fmt_out, SPU_ES, VLC_FOURCC( 'o','g','t',' ' ) );
128 p_dec->pf_decode_sub = Decode;
129 p_dec->pf_packetize = Packetize;
134 /*****************************************************************************
135 * PacketizerOpen: open/initialize the svcdsub packetizer.
136 *****************************************************************************/
137 static int PacketizerOpen( vlc_object_t *p_this )
139 decoder_t *p_dec = (decoder_t*)p_this;
141 if( DecoderOpen( p_this ) != VLC_SUCCESS ) return VLC_EGENERIC;
143 p_dec->p_sys->b_packetizer = VLC_TRUE;
148 /*****************************************************************************
149 * DecoderClose: closes the svcdsub decoder/packetizer.
150 *****************************************************************************/
151 void DecoderClose( vlc_object_t *p_this )
153 decoder_t *p_dec = (decoder_t*)p_this;
154 decoder_sys_t *p_sys = p_dec->p_sys;
156 if( p_sys->p_spu ) block_ChainRelease( p_sys->p_spu );
160 /*****************************************************************************
162 *****************************************************************************/
163 static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block )
165 block_t *p_block, *p_spu;
167 if( pp_block == NULL || *pp_block == NULL ) return NULL;
172 if( !(p_spu = Reassemble( p_dec, p_block )) ) return NULL;
174 /* Parse and decode */
175 return DecodePacket( p_dec, p_spu );
178 /*****************************************************************************
180 *****************************************************************************/
181 static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
183 block_t *p_block, *p_spu;
185 if( pp_block == NULL || *pp_block == NULL ) return NULL;
190 if( !(p_spu = Reassemble( p_dec, p_block )) ) return NULL;
192 p_spu->i_dts = p_spu->i_pts;
198 /*****************************************************************************
201 The data for single screen subtitle may come in one of many
202 non-contiguous packets of a stream. This routine is called when the
203 next packet in the stream comes in. The job of this routine is to
204 parse the header, if this is the beginning, and combine the packets
205 into one complete subtitle unit.
207 If everything is complete, we will return a block. Otherwise return
211 The format of the beginning of the subtitle packet that is used here.
214 -------------------------------------------
215 byte subtitle channel (0..7) in bits 0-3
216 byte subtitle packet number of this subtitle image 0-N,
217 if the subtitle packet is complete, the top bit of the byte is 1.
218 uint16 subtitle image number
220 *****************************************************************************/
221 #define SPU_HEADER_LEN 5
223 static block_t *Reassemble( decoder_t *p_dec, block_t *p_block )
225 decoder_sys_t *p_sys = p_dec->p_sys;
227 uint16_t i_expected_image;
228 uint8_t i_packet, i_expected_packet;
230 if( p_block->i_buffer < SPU_HEADER_LEN )
232 msg_Dbg( p_dec, "invalid packet header (size %d < %d)" ,
233 p_block->i_buffer, SPU_HEADER_LEN );
234 block_Release( p_block );
238 p_buffer = p_block->p_buffer;
240 if( p_sys->i_state == SUBTITLE_BLOCK_EMPTY )
242 i_expected_image = p_sys->i_image + 1;
243 i_expected_packet = 0;
247 i_expected_image = p_sys->i_image;
248 i_expected_packet = p_sys->i_packet + 1;
253 if( *p_buffer & 0x80 )
255 p_sys->i_state = SUBTITLE_BLOCK_COMPLETE;
256 i_packet = *p_buffer++ & 0x7F;
260 p_sys->i_state = SUBTITLE_BLOCK_PARTIAL;
261 i_packet = *p_buffer++;
264 p_sys->i_image = GETINT16(p_buffer);
266 if( p_sys->i_image != i_expected_image )
268 msg_Warn( p_dec, "expected subtitle image %u but found %u",
269 i_expected_image, p_sys->i_image );
272 if( i_packet != i_expected_packet )
274 msg_Warn( p_dec, "expected subtitle image packet %u but found %u",
275 i_expected_packet, i_packet );
278 p_block->p_buffer += SPU_HEADER_LEN;
279 p_block->i_buffer -= SPU_HEADER_LEN;
281 p_sys->i_packet = i_packet;
282 /* First packet in the subtitle block */
283 if( !p_sys->i_packet ) ParseHeader( p_dec, p_block );
285 block_ChainAppend( &p_sys->p_spu, p_block );
287 if( p_sys->i_state == SUBTITLE_BLOCK_COMPLETE )
289 block_t *p_spu = block_ChainGather( p_sys->p_spu );
291 if( p_spu->i_buffer != p_sys->i_spu_size )
293 msg_Warn( p_dec, "SPU packets size=%d should be %d",
294 p_spu->i_buffer, p_sys->i_spu_size );
297 msg_Dbg( p_dec, "subtitle packet complete, size=%d", p_spu->i_buffer);
299 p_sys->i_state = SUBTITLE_BLOCK_EMPTY;
307 /******************************************************************************
308 The format is roughly as follows (everything is big-endian):
311 -------------------------------------------
312 byte subtitle channel (0..7) in bits 0-3
313 byte subtitle packet number of this subtitle image 0-N,
314 if the subtitle packet is complete, the top bit of the byte is 1.
315 u_int16 subtitle image number
316 u_int16 length in bytes of the rest
317 byte option flags, unknown meaning except bit 3 (0x08) indicates
318 presence of the duration field
320 u_int32 duration in 1/90000ths of a second (optional), start time
321 is as indicated by the PTS in the PES header
324 u_int32 width (must be even)
325 u_int32 height (must be even)
326 byte[16] palette, 4 palette entries, each contains values for
327 Y, U, V and transparency, 0 standing for transparent
329 cmd>>6==1 indicates shift
330 (cmd>>4)&3 is direction from, (0=top,1=left,2=right,3=bottom)
331 u_int32 shift duration in 1/90000ths of a second
332 u_int16 offset of odd-numbered scanlines - subtitle images are
333 given in interlace order
334 byte[] limited RLE image data in interlace order (0,2,4... 1,3,5) with
335 2-bits per palette number
336 ******************************************************************************/
337 static void ParseHeader( decoder_t *p_dec, block_t *p_block )
339 decoder_sys_t *p_sys = p_dec->p_sys;
340 uint8_t *p = p_block->p_buffer;
341 uint8_t i_options, i_options2, i_cmd, i_cmd_arg;
344 p_sys->i_spu_size = GETINT16(p);
348 if( i_options & 0x08 ) { p_sys->i_duration = GETINT32(p); }
349 else p_sys->i_duration = 0; /* Ephemer subtitle */
350 p_sys->i_duration *= 100 / 9;
352 p_sys->i_x_start = GETINT16(p);
353 p_sys->i_y_start = GETINT16(p);
354 p_sys->i_width = GETINT16(p);
355 p_sys->i_height = GETINT16(p);
357 for( i = 0; i < 4; i++ )
359 p_sys->p_palette[i][0] = *p++;
360 p_sys->p_palette[i][1] = *p++;
361 p_sys->p_palette[i][2] = *p++;
362 p_sys->p_palette[i][3] = *p++;
366 /* We do not really know this, FIXME */
367 if( i_cmd ) {i_cmd_arg = GETINT32(p);}
369 /* Actually, this is measured against a different origin, so we have to
371 p_sys->second_field_offset = GETINT16(p);
372 p_sys->i_image_offset = p - p_block->p_buffer;
373 p_sys->i_image_length = p_sys->i_spu_size - p_sys->i_image_offset;
374 p_sys->metadata_length = p_sys->i_image_offset;
377 msg_Dbg( p_dec, "x-start: %d, y-start: %d, width: %d, height %d, "
378 "spu size: %d, duration: %lu (d:%d p:%d)",
379 p_sys->i_x_start, p_sys->i_y_start,
380 p_sys->i_width, p_sys->i_height,
381 p_sys->i_spu_size, (long unsigned int) p_sys->i_duration,
382 p_sys->i_image_length, p_sys->i_image_offset);
384 for( i = 0; i < 4; i++ )
386 msg_Dbg( p_dec, "palette[%d]= T: %2x, Y: %2x, u: %2x, v: %2x", i,
387 p_sys->p_palette[i][3], p_sys->p_palette[i][0],
388 p_sys->p_palette[i][1], p_sys->p_palette[i][2] );
393 /*****************************************************************************
394 * DecodePacket: parse and decode an SPU packet
395 *****************************************************************************
396 * This function parses and decodes an SPU packet and, if valid, returns a
398 *****************************************************************************/
399 static subpicture_t *DecodePacket( decoder_t *p_dec, block_t *p_data )
401 decoder_sys_t *p_sys = p_dec->p_sys;
403 subpicture_region_t *p_region;
407 /* Allocate the subpicture internal data. */
408 p_spu = p_dec->pf_spu_buffer_new( p_dec );
409 if( !p_spu ) return NULL;
411 p_spu->i_x = p_sys->i_x_start;
412 p_spu->i_x = p_spu->i_x * 3 / 4; /* FIXME: use aspect ratio for x? */
413 p_spu->i_y = p_sys->i_y_start;
414 p_spu->i_start = p_data->i_pts;
415 p_spu->i_stop = p_data->i_pts + p_sys->i_duration;
416 p_spu->b_ephemer = VLC_TRUE;
418 /* Create new SPU region */
419 memset( &fmt, 0, sizeof(video_format_t) );
420 fmt.i_chroma = VLC_FOURCC('Y','U','V','P');
421 fmt.i_aspect = VOUT_ASPECT_FACTOR;
422 fmt.i_width = fmt.i_visible_width = p_sys->i_width;
423 fmt.i_height = fmt.i_visible_height = p_sys->i_height;
424 fmt.i_x_offset = fmt.i_y_offset = 0;
425 p_region = p_spu->pf_create_region( VLC_OBJECT(p_dec), &fmt );
428 msg_Err( p_dec, "cannot allocate SPU region" );
432 p_spu->p_region = p_region;
433 p_region->i_x = p_region->i_y = 0;
436 fmt.p_palette->i_entries = 4;
437 for( i = 0; i < fmt.p_palette->i_entries; i++ )
439 fmt.p_palette->palette[i][0] = p_sys->p_palette[i][0];
440 fmt.p_palette->palette[i][1] = p_sys->p_palette[i][1];
441 fmt.p_palette->palette[i][2] = p_sys->p_palette[i][2];
442 fmt.p_palette->palette[i][3] = p_sys->p_palette[i][3];
445 RenderImage( p_dec, p_data, p_region );
450 /*****************************************************************************
451 * ParseImage: parse the image part of the subtitle
452 *****************************************************************************
453 This part parses the subtitle graphical data and renders it.
455 The image is encoded using two bits per pixel that select a palette
456 entry except that value 0 starts a limited run-length encoding for
457 color 0. When 0 is seen, the next two bits encode one less than the
458 number of pixels, so we can encode run lengths from 1 to 4. These get
459 filled with the color in palette entry 0.
461 The encoding of each line is padded to a whole number of bytes. The
462 first field is padded to an even byte length and the complete subtitle
463 is padded to a 4-byte multiple that always include one zero byte at
466 However we'll transform this so that that the RLE is expanded and
467 interlacing will also be removed.
468 *****************************************************************************/
469 static void RenderImage( decoder_t *p_dec, block_t *p_data,
470 subpicture_region_t *p_region )
472 decoder_sys_t *p_sys = p_dec->p_sys;
473 uint8_t *p_dest = p_region->picture.Y_PIXELS;
474 int i_field; /* The subtitles are interlaced */
475 int i_row, i_column; /* scanline row/column number */
476 uint8_t i_color, i_count;
479 bs_init( &bs, p_data->p_buffer + p_sys->i_image_offset,
480 p_data->i_buffer - p_sys->i_image_offset );
482 for( i_field = 0; i_field < 2; i_field++ )
484 for( i_row = i_field; i_row < p_sys->i_height; i_row += 2 )
486 for( i_column = 0; i_column < p_sys->i_width; i_column++ )
488 i_color = bs_read( &bs, 2 );
489 if( i_color == 0 && (i_count = bs_read( &bs, 2 )) )
491 i_count = __MIN( i_count, p_sys->i_width - i_column );
492 memset( &p_dest[i_row * p_region->picture.Y_PITCH +
493 i_column], 0, i_count + 1 );
498 p_dest[i_row * p_region->picture.Y_PITCH + i_column] = i_color;
505 bs_init( &bs, p_data->p_buffer + p_sys->i_image_offset +
506 p_sys->second_field_offset,
507 p_data->i_buffer - p_sys->i_image_offset -
508 p_sys->second_field_offset );