1 /*****************************************************************************
2 * svcdsub.c : Overlay Graphics Text (SVCD subtitles) decoder
3 *****************************************************************************
4 * Copyright (C) 2003, 2004 VLC authors and 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 it
13 * under the terms of the GNU Lesser General Public License as published by
14 * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public License
23 * along with this program; if not, write to the Free Software Foundation,
24 * 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>
39 /*****************************************************************************
41 *****************************************************************************/
42 static int DecoderOpen ( vlc_object_t * );
43 static int PacketizerOpen( vlc_object_t * );
44 static void DecoderClose ( vlc_object_t * );
47 set_description( N_("Philips OGT (SVCD subtitle) decoder") )
48 set_shortname( N_("SVCD subtitles") )
49 set_category( CAT_INPUT )
50 set_subcategory( SUBCAT_INPUT_SCODEC )
51 set_capability( "decoder", 50 )
52 set_callbacks( DecoderOpen, DecoderClose )
54 add_obsolete_integer ( MODULE_STRING "-debug" )
57 set_description( N_("Philips OGT (SVCD subtitle) packetizer") )
58 set_capability( "packetizer", 50 )
59 set_callbacks( PacketizerOpen, DecoderClose )
62 /*****************************************************************************
64 *****************************************************************************/
65 static subpicture_t *Decode( decoder_t *, block_t ** );
66 static block_t *Packetize ( decoder_t *, block_t ** );
67 static block_t *Reassemble ( decoder_t *, block_t * );
68 static void ParseHeader( decoder_t *, block_t * );
69 static subpicture_t *DecodePacket( decoder_t *, block_t * );
70 static void SVCDSubRenderImage( decoder_t *, block_t *, subpicture_region_t * );
72 #define GETINT16(p) ( (p[0] << 8) + p[1] ) ; p +=2;
74 #define GETINT32(p) ( (p[0] << 24) + (p[1] << 16) + \
75 (p[2] << 8) + (p[3]) ) ; p += 4;
78 SUBTITLE_BLOCK_EMPTY = 0,
79 SUBTITLE_BLOCK_PARTIAL = 1,
80 SUBTITLE_BLOCK_COMPLETE = 2
85 packet_state_t i_state; /* data-gathering state for this subtitle */
87 block_t *p_spu; /* Bytes of the packet. */
89 uint16_t i_image; /* image number in the subtitle stream */
90 uint8_t i_packet; /* packet number for above image number */
92 size_t i_spu_size; /* goal for subtitle_data_pos while gathering,
93 size of used subtitle_data later */
95 uint16_t i_image_offset; /* offset from subtitle_data to compressed
97 size_t i_image_length; /* size of the compressed image data */
98 size_t second_field_offset; /* offset of odd raster lines */
99 size_t metadata_offset; /* offset to data describing the image */
100 size_t metadata_length; /* length of metadata */
102 mtime_t i_duration; /* how long to display the image, 0 stands
103 for "until next subtitle" */
105 uint16_t i_x_start, i_y_start; /* position of top leftmost pixel of
106 image when displayed */
107 uint16_t i_width, i_height; /* dimensions in pixels of image */
109 uint8_t p_palette[4][4]; /* Palette of colors used in subtitle */
112 /*****************************************************************************
113 * DecoderOpen: open/initialize the svcdsub decoder.
114 *****************************************************************************/
115 static int DecoderOpen( vlc_object_t *p_this )
117 decoder_t *p_dec = (decoder_t*)p_this;
118 decoder_sys_t *p_sys;
120 if( p_dec->fmt_in.i_codec != VLC_CODEC_OGT )
123 p_dec->p_sys = p_sys = calloc( 1, sizeof( decoder_sys_t ) );
130 p_sys->i_state = SUBTITLE_BLOCK_EMPTY;
133 es_format_Init( &p_dec->fmt_out, SPU_ES, VLC_CODEC_OGT );
135 p_dec->pf_decode_sub = Decode;
136 p_dec->pf_packetize = Packetize;
141 /*****************************************************************************
142 * PacketizerOpen: open/initialize the svcdsub packetizer.
143 *****************************************************************************/
144 static int PacketizerOpen( vlc_object_t *p_this )
146 if( DecoderOpen( p_this ) != VLC_SUCCESS ) return VLC_EGENERIC;
151 /*****************************************************************************
152 * DecoderClose: closes the svcdsub decoder/packetizer.
153 *****************************************************************************/
154 void DecoderClose( vlc_object_t *p_this )
156 decoder_t *p_dec = (decoder_t*)p_this;
157 decoder_sys_t *p_sys = p_dec->p_sys;
159 if( p_sys->p_spu ) block_ChainRelease( p_sys->p_spu );
163 /*****************************************************************************
165 *****************************************************************************/
166 static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block )
168 block_t *p_block, *p_spu;
171 msg_Dbg( p_dec, "Decode" );
174 if( pp_block == NULL || *pp_block == NULL ) return NULL;
179 if( !(p_spu = Reassemble( p_dec, p_block )) ) return NULL;
181 /* Parse and decode */
182 return DecodePacket( p_dec, p_spu );
185 /*****************************************************************************
187 *****************************************************************************/
188 static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
190 block_t *p_block, *p_spu;
192 if( pp_block == NULL || *pp_block == NULL ) return NULL;
197 if( !(p_spu = Reassemble( p_dec, p_block )) ) return NULL;
199 p_spu->i_dts = p_spu->i_pts;
205 /*****************************************************************************
208 The data for single screen subtitle may come in one of many
209 non-contiguous packets of a stream. This routine is called when the
210 next packet in the stream comes in. The job of this routine is to
211 parse the header, if this is the beginning, and combine the packets
212 into one complete subtitle unit.
214 If everything is complete, we will return a block. Otherwise return
218 The format of the beginning of the subtitle packet that is used here.
221 -------------------------------------------
222 byte subtitle channel (0..7) in bits 0-3
223 byte subtitle packet number of this subtitle image 0-N,
224 if the subtitle packet is complete, the top bit of the byte is 1.
225 uint16 subtitle image number
227 *****************************************************************************/
228 #define SPU_HEADER_LEN 5
230 static block_t *Reassemble( decoder_t *p_dec, block_t *p_block )
232 decoder_sys_t *p_sys = p_dec->p_sys;
234 uint16_t i_expected_image;
235 uint8_t i_packet, i_expected_packet;
237 if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
239 block_Release( p_block );
243 if( p_block->i_buffer < SPU_HEADER_LEN )
245 msg_Dbg( p_dec, "invalid packet header (size %zu < %u)" ,
246 p_block->i_buffer, SPU_HEADER_LEN );
247 block_Release( p_block );
251 p_buffer = p_block->p_buffer;
253 if( p_sys->i_state == SUBTITLE_BLOCK_EMPTY )
255 i_expected_image = p_sys->i_image + 1;
256 i_expected_packet = 0;
260 i_expected_image = p_sys->i_image;
261 i_expected_packet = p_sys->i_packet + 1;
264 /* The dummy ES that the menu selection uses has an 0x70 at
265 the head which we need to strip off. */
268 if( *p_buffer & 0x80 )
270 p_sys->i_state = SUBTITLE_BLOCK_COMPLETE;
271 i_packet = *p_buffer++ & 0x7F;
275 p_sys->i_state = SUBTITLE_BLOCK_PARTIAL;
276 i_packet = *p_buffer++;
279 p_sys->i_image = GETINT16(p_buffer);
281 if( p_sys->i_image != i_expected_image )
283 msg_Warn( p_dec, "expected subtitle image %u but found %u",
284 i_expected_image, p_sys->i_image );
287 if( i_packet != i_expected_packet )
289 msg_Warn( p_dec, "expected subtitle image packet %u but found %u",
290 i_expected_packet, i_packet );
293 p_block->p_buffer += SPU_HEADER_LEN;
294 p_block->i_buffer -= SPU_HEADER_LEN;
296 p_sys->i_packet = i_packet;
297 /* First packet in the subtitle block */
298 if( !p_sys->i_packet ) ParseHeader( p_dec, p_block );
300 block_ChainAppend( &p_sys->p_spu, p_block );
302 if( p_sys->i_state == SUBTITLE_BLOCK_COMPLETE )
304 block_t *p_spu = block_ChainGather( p_sys->p_spu );
306 if( p_spu->i_buffer != p_sys->i_spu_size )
308 msg_Warn( p_dec, "subtitle packets size=%zu should be %zu",
309 p_spu->i_buffer, p_sys->i_spu_size );
312 msg_Dbg( p_dec, "subtitle packet complete, size=%zu", p_spu->i_buffer );
314 p_sys->i_state = SUBTITLE_BLOCK_EMPTY;
322 /******************************************************************************
323 The format is roughly as follows (everything is big-endian):
326 -------------------------------------------
327 byte subtitle channel (0..7) in bits 0-3
328 byte subtitle packet number of this subtitle image 0-N,
329 if the subtitle packet is complete, the top bit of the byte is 1.
330 u_int16 subtitle image number
331 u_int16 length in bytes of the rest
332 byte option flags, unknown meaning except bit 3 (0x08) indicates
333 presence of the duration field
335 u_int32 duration in 1/90000ths of a second (optional), start time
336 is as indicated by the PTS in the PES header
339 u_int32 width (must be even)
340 u_int32 height (must be even)
341 byte[16] palette, 4 palette entries, each contains values for
342 Y, U, V and transparency, 0 standing for transparent
344 cmd>>6==1 indicates shift
345 (cmd>>4)&3 is direction from, (0=top,1=left,2=right,3=bottom)
346 u_int32 shift duration in 1/90000ths of a second
347 u_int16 offset of odd-numbered scanlines - subtitle images are
348 given in interlace order
349 byte[] limited RLE image data in interlace order (0,2,4... 1,3,5) with
350 2-bits per palette number
351 ******************************************************************************/
352 static void ParseHeader( decoder_t *p_dec, block_t *p_block )
354 decoder_sys_t *p_sys = p_dec->p_sys;
355 uint8_t *p = p_block->p_buffer;
356 uint8_t i_options, i_options2, i_cmd, i_cmd_arg;
359 p_sys->i_spu_size = GETINT16(p);
363 if( i_options & 0x08 ) { p_sys->i_duration = GETINT32(p); }
364 else p_sys->i_duration = 0; /* Ephemer subtitle */
365 p_sys->i_duration *= 100 / 9;
367 p_sys->i_x_start = GETINT16(p);
368 p_sys->i_y_start = GETINT16(p);
369 p_sys->i_width = GETINT16(p);
370 p_sys->i_height = GETINT16(p);
372 for( i = 0; i < 4; i++ )
374 p_sys->p_palette[i][0] = *p++; /* Y */
375 p_sys->p_palette[i][2] = *p++; /* Cr / V */
376 p_sys->p_palette[i][1] = *p++; /* Cb / U */
377 p_sys->p_palette[i][3] = *p++; /* T */
381 /* We do not really know this, FIXME */
382 if( i_cmd ) {i_cmd_arg = GETINT32(p);}
384 /* Actually, this is measured against a different origin, so we have to
386 p_sys->second_field_offset = GETINT16(p);
387 p_sys->i_image_offset = p - p_block->p_buffer;
388 p_sys->i_image_length = p_sys->i_spu_size - p_sys->i_image_offset;
389 p_sys->metadata_length = p_sys->i_image_offset;
392 msg_Dbg( p_dec, "x-start: %d, y-start: %d, width: %d, height %d, "
393 "spu size: %zu, duration: %"PRIu64" (d:%zu p:%"PRIu16")",
394 p_sys->i_x_start, p_sys->i_y_start,
395 p_sys->i_width, p_sys->i_height,
396 p_sys->i_spu_size, p_sys->i_duration,
397 p_sys->i_image_length, p_sys->i_image_offset);
399 for( i = 0; i < 4; i++ )
401 msg_Dbg( p_dec, "palette[%d]= T: %2x, Y: %2x, u: %2x, v: %2x", i,
402 p_sys->p_palette[i][3], p_sys->p_palette[i][0],
403 p_sys->p_palette[i][1], p_sys->p_palette[i][2] );
408 /*****************************************************************************
409 * DecodePacket: parse and decode an subtitle packet
410 *****************************************************************************
411 * This function parses and decodes an SPU packet and, if valid, returns a
413 *****************************************************************************/
414 static subpicture_t *DecodePacket( decoder_t *p_dec, block_t *p_data )
416 decoder_sys_t *p_sys = p_dec->p_sys;
418 subpicture_region_t *p_region;
420 video_palette_t palette;
423 /* Allocate the subpicture internal data. */
424 p_spu = decoder_NewSubpicture( p_dec, NULL );
425 if( !p_spu ) return NULL;
427 p_spu->i_start = p_data->i_pts;
428 p_spu->i_stop = p_data->i_pts + p_sys->i_duration;
429 p_spu->b_ephemer = true;
431 /* Create new subtitle region */
432 memset( &fmt, 0, sizeof(video_format_t) );
433 fmt.i_chroma = VLC_CODEC_YUVP;
436 The video on which the subtitle sits, is scaled, probably
437 4:3. However subtitle bitmaps assume an 1:1 aspect ratio.
439 FIXME: We should get the video aspect ratio from somewhere.
440 Two candidates are the video and the other possibility would be
443 fmt.i_sar_num = p_sys->i_height;
444 fmt.i_sar_den = p_sys->i_width;
446 fmt.i_width = fmt.i_visible_width = p_sys->i_width;
447 fmt.i_height = fmt.i_visible_height = p_sys->i_height;
448 fmt.i_x_offset = fmt.i_y_offset = 0;
449 fmt.p_palette = &palette;
450 fmt.p_palette->i_entries = 4;
451 for( i = 0; i < fmt.p_palette->i_entries; i++ )
453 fmt.p_palette->palette[i][0] = p_sys->p_palette[i][0];
454 fmt.p_palette->palette[i][1] = p_sys->p_palette[i][1];
455 fmt.p_palette->palette[i][2] = p_sys->p_palette[i][2];
456 fmt.p_palette->palette[i][3] = p_sys->p_palette[i][3];
459 p_region = subpicture_region_New( &fmt );
462 msg_Err( p_dec, "cannot allocate SVCD subtitle region" );
463 subpicture_Delete( p_spu );
467 p_spu->p_region = p_region;
468 p_region->i_x = p_sys->i_x_start;
469 p_region->i_y = p_sys->i_y_start;
471 SVCDSubRenderImage( p_dec, p_data, p_region );
476 /*****************************************************************************
477 * SVCDSubRenderImage: reorders bytes of image data in subpicture region.
478 *****************************************************************************
480 The image is encoded using two bits per pixel that select a palette
481 entry except that value 0 starts a limited run-length encoding for
482 color 0. When 0 is seen, the next two bits encode one less than the
483 number of pixels, so we can encode run lengths from 1 to 4. These get
484 filled with the color in palette entry 0.
486 The encoding of each line is padded to a whole number of bytes. The
487 first field is padded to an even byte length and the complete subtitle
488 is padded to a 4-byte multiple that always include one zero byte at
491 However we'll transform this so that that the RLE is expanded and
492 interlacing will also be removed.
493 *****************************************************************************/
494 static void SVCDSubRenderImage( decoder_t *p_dec, block_t *p_data,
495 subpicture_region_t *p_region )
497 decoder_sys_t *p_sys = p_dec->p_sys;
498 uint8_t *p_dest = p_region->p_picture->Y_PIXELS;
499 int i_field; /* The subtitles are interlaced */
500 int i_row, i_column; /* scanline row/column number */
501 uint8_t i_color, i_count;
504 bs_init( &bs, p_data->p_buffer + p_sys->i_image_offset,
505 p_data->i_buffer - p_sys->i_image_offset );
507 for( i_field = 0; i_field < 2; i_field++ )
509 for( i_row = i_field; i_row < p_sys->i_height; i_row += 2 )
511 for( i_column = 0; i_column < p_sys->i_width; i_column++ )
513 i_color = bs_read( &bs, 2 );
514 if( i_color == 0 && (i_count = bs_read( &bs, 2 )) )
516 i_count = __MIN( i_count, p_sys->i_width - i_column );
517 memset( &p_dest[i_row * p_region->p_picture->Y_PITCH +
518 i_column], 0, i_count + 1 );
523 p_dest[i_row * p_region->p_picture->Y_PITCH + i_column] = i_color;
530 bs_init( &bs, p_data->p_buffer + p_sys->i_image_offset +
531 p_sys->second_field_offset,
532 p_data->i_buffer - p_sys->i_image_offset -
533 p_sys->second_field_offset );