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>
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
84 # define dbg_print( s, args...) \
85 msg_Dbg(p_dec, "%s: "s, __func__ , ##args)
87 # define dbg_print( s, args...)
92 packet_state_t i_state
; /* data-gathering state for this subtitle */
94 block_t
*p_spu
; /* Bytes of the packet. */
96 uint16_t i_image
; /* image number in the subtitle stream */
97 uint8_t i_packet
; /* packet number for above image number */
99 size_t i_spu_size
; /* goal for subtitle_data_pos while gathering,
100 size of used subtitle_data later */
102 uint16_t i_image_offset
; /* offset from subtitle_data to compressed
104 size_t i_image_length
; /* size of the compressed image data */
105 size_t second_field_offset
; /* offset of odd raster lines */
106 size_t metadata_offset
; /* offset to data describing the image */
107 size_t metadata_length
; /* length of metadata */
109 mtime_t i_duration
; /* how long to display the image, 0 stands
110 for "until next subtitle" */
112 uint16_t i_x_start
, i_y_start
; /* position of top leftmost pixel of
113 image when displayed */
114 uint16_t i_width
, i_height
; /* dimensions in pixels of image */
116 uint8_t p_palette
[4][4]; /* Palette of colors used in subtitle */
119 /*****************************************************************************
120 * DecoderOpen: open/initialize the svcdsub decoder.
121 *****************************************************************************/
122 static int DecoderOpen( vlc_object_t
*p_this
)
124 decoder_t
*p_dec
= (decoder_t
*)p_this
;
125 decoder_sys_t
*p_sys
;
127 if( p_dec
->fmt_in
.i_codec
!= VLC_CODEC_OGT
)
130 p_dec
->p_sys
= p_sys
= calloc( 1, sizeof( decoder_sys_t
) );
137 p_sys
->i_state
= SUBTITLE_BLOCK_EMPTY
;
140 es_format_Init( &p_dec
->fmt_out
, SPU_ES
, VLC_CODEC_OGT
);
142 p_dec
->pf_decode_sub
= Decode
;
143 p_dec
->pf_packetize
= Packetize
;
148 /*****************************************************************************
149 * PacketizerOpen: open/initialize the svcdsub packetizer.
150 *****************************************************************************/
151 static int PacketizerOpen( vlc_object_t
*p_this
)
153 if( DecoderOpen( p_this
) != VLC_SUCCESS
) return VLC_EGENERIC
;
158 /*****************************************************************************
159 * DecoderClose: closes the svcdsub decoder/packetizer.
160 *****************************************************************************/
161 void DecoderClose( vlc_object_t
*p_this
)
163 decoder_t
*p_dec
= (decoder_t
*)p_this
;
164 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
166 if( p_sys
->p_spu
) block_ChainRelease( p_sys
->p_spu
);
170 /*****************************************************************************
172 *****************************************************************************/
173 static subpicture_t
*Decode( decoder_t
*p_dec
, block_t
**pp_block
)
175 block_t
*p_block
, *p_spu
;
179 if( pp_block
== NULL
|| *pp_block
== NULL
) return NULL
;
184 if( !(p_spu
= Reassemble( p_dec
, p_block
)) ) return NULL
;
186 /* Parse and decode */
187 return DecodePacket( p_dec
, p_spu
);
190 /*****************************************************************************
192 *****************************************************************************/
193 static block_t
*Packetize( decoder_t
*p_dec
, block_t
**pp_block
)
195 block_t
*p_block
, *p_spu
;
197 if( pp_block
== NULL
|| *pp_block
== NULL
) return NULL
;
202 if( !(p_spu
= Reassemble( p_dec
, p_block
)) ) return NULL
;
204 p_spu
->i_dts
= p_spu
->i_pts
;
210 /*****************************************************************************
213 The data for single screen subtitle may come in one of many
214 non-contiguous packets of a stream. This routine is called when the
215 next packet in the stream comes in. The job of this routine is to
216 parse the header, if this is the beginning, and combine the packets
217 into one complete subtitle unit.
219 If everything is complete, we will return a block. Otherwise return
223 The format of the beginning of the subtitle packet that is used here.
226 -------------------------------------------
227 byte subtitle channel (0..7) in bits 0-3
228 byte subtitle packet number of this subtitle image 0-N,
229 if the subtitle packet is complete, the top bit of the byte is 1.
230 uint16 subtitle image number
232 *****************************************************************************/
233 #define SPU_HEADER_LEN 5
235 static block_t
*Reassemble( decoder_t
*p_dec
, block_t
*p_block
)
237 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
239 uint16_t i_expected_image
;
240 uint8_t i_packet
, i_expected_packet
;
242 if( p_block
->i_flags
& (BLOCK_FLAG_DISCONTINUITY
|BLOCK_FLAG_CORRUPTED
) )
244 block_Release( p_block
);
248 if( p_block
->i_buffer
< SPU_HEADER_LEN
)
250 msg_Dbg( p_dec
, "invalid packet header (size %zu < %u)" ,
251 p_block
->i_buffer
, SPU_HEADER_LEN
);
252 block_Release( p_block
);
256 p_buffer
= p_block
->p_buffer
;
258 if( p_sys
->i_state
== SUBTITLE_BLOCK_EMPTY
)
260 i_expected_image
= p_sys
->i_image
+ 1;
261 i_expected_packet
= 0;
265 i_expected_image
= p_sys
->i_image
;
266 i_expected_packet
= p_sys
->i_packet
+ 1;
269 /* The dummy ES that the menu selection uses has an 0x70 at
270 the head which we need to strip off. */
273 if( *p_buffer
& 0x80 )
275 p_sys
->i_state
= SUBTITLE_BLOCK_COMPLETE
;
276 i_packet
= *p_buffer
++ & 0x7F;
280 p_sys
->i_state
= SUBTITLE_BLOCK_PARTIAL
;
281 i_packet
= *p_buffer
++;
284 p_sys
->i_image
= GETINT16(p_buffer
);
286 if( p_sys
->i_image
!= i_expected_image
)
288 msg_Warn( p_dec
, "expected subtitle image %u but found %u",
289 i_expected_image
, p_sys
->i_image
);
292 if( i_packet
!= i_expected_packet
)
294 msg_Warn( p_dec
, "expected subtitle image packet %u but found %u",
295 i_expected_packet
, i_packet
);
298 p_block
->p_buffer
+= SPU_HEADER_LEN
;
299 p_block
->i_buffer
-= SPU_HEADER_LEN
;
301 p_sys
->i_packet
= i_packet
;
302 /* First packet in the subtitle block */
303 if( !p_sys
->i_packet
) ParseHeader( p_dec
, p_block
);
305 block_ChainAppend( &p_sys
->p_spu
, p_block
);
307 if( p_sys
->i_state
== SUBTITLE_BLOCK_COMPLETE
)
309 block_t
*p_spu
= block_ChainGather( p_sys
->p_spu
);
311 if( p_spu
->i_buffer
!= p_sys
->i_spu_size
)
313 msg_Warn( p_dec
, "subtitle packets size=%zu should be %zu",
314 p_spu
->i_buffer
, p_sys
->i_spu_size
);
317 dbg_print( "subtitle packet complete, size=%zu", p_spu
->i_buffer
);
319 p_sys
->i_state
= SUBTITLE_BLOCK_EMPTY
;
327 /******************************************************************************
328 The format is roughly as follows (everything is big-endian):
331 -------------------------------------------
332 byte subtitle channel (0..7) in bits 0-3
333 byte subtitle packet number of this subtitle image 0-N,
334 if the subtitle packet is complete, the top bit of the byte is 1.
335 u_int16 subtitle image number
336 u_int16 length in bytes of the rest
337 byte option flags, unknown meaning except bit 3 (0x08) indicates
338 presence of the duration field
340 u_int32 duration in 1/90000ths of a second (optional), start time
341 is as indicated by the PTS in the PES header
344 u_int32 width (must be even)
345 u_int32 height (must be even)
346 byte[16] palette, 4 palette entries, each contains values for
347 Y, U, V and transparency, 0 standing for transparent
349 cmd>>6==1 indicates shift
350 (cmd>>4)&3 is direction from, (0=top,1=left,2=right,3=bottom)
351 u_int32 shift duration in 1/90000ths of a second
352 u_int16 offset of odd-numbered scanlines - subtitle images are
353 given in interlace order
354 byte[] limited RLE image data in interlace order (0,2,4... 1,3,5) with
355 2-bits per palette number
356 ******************************************************************************/
357 static void ParseHeader( decoder_t
*p_dec
, block_t
*p_block
)
359 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
360 uint8_t *p
= p_block
->p_buffer
;
361 uint8_t i_options
, i_options2
, i_cmd
, i_cmd_arg
;
364 p_sys
->i_spu_size
= GETINT16(p
);
368 if( i_options
& 0x08 ) { p_sys
->i_duration
= GETINT32(p
); }
369 else p_sys
->i_duration
= 0; /* Ephemer subtitle */
370 p_sys
->i_duration
*= 100 / 9;
372 p_sys
->i_x_start
= GETINT16(p
);
373 p_sys
->i_y_start
= GETINT16(p
);
374 p_sys
->i_width
= GETINT16(p
);
375 p_sys
->i_height
= GETINT16(p
);
377 for( i
= 0; i
< 4; i
++ )
379 p_sys
->p_palette
[i
][0] = *p
++; /* Y */
380 p_sys
->p_palette
[i
][2] = *p
++; /* Cr / V */
381 p_sys
->p_palette
[i
][1] = *p
++; /* Cb / U */
382 p_sys
->p_palette
[i
][3] = *p
++; /* T */
386 /* We do not really know this, FIXME */
387 if( i_cmd
) {i_cmd_arg
= GETINT32(p
);}
389 /* Actually, this is measured against a different origin, so we have to
391 p_sys
->second_field_offset
= GETINT16(p
);
392 p_sys
->i_image_offset
= p
- p_block
->p_buffer
;
393 p_sys
->i_image_length
= p_sys
->i_spu_size
- p_sys
->i_image_offset
;
394 p_sys
->metadata_length
= p_sys
->i_image_offset
;
397 msg_Dbg( p_dec
, "x-start: %d, y-start: %d, width: %d, height %d, "
398 "spu size: %zu, duration: %"PRIu64
" (d:%zu p:%"PRIu16
")",
399 p_sys
->i_x_start
, p_sys
->i_y_start
,
400 p_sys
->i_width
, p_sys
->i_height
,
401 p_sys
->i_spu_size
, p_sys
->i_duration
,
402 p_sys
->i_image_length
, p_sys
->i_image_offset
);
404 for( i
= 0; i
< 4; i
++ )
406 msg_Dbg( p_dec
, "palette[%d]= T: %2x, Y: %2x, u: %2x, v: %2x", i
,
407 p_sys
->p_palette
[i
][3], p_sys
->p_palette
[i
][0],
408 p_sys
->p_palette
[i
][1], p_sys
->p_palette
[i
][2] );
413 /*****************************************************************************
414 * DecodePacket: parse and decode an subtitle packet
415 *****************************************************************************
416 * This function parses and decodes an SPU packet and, if valid, returns a
418 *****************************************************************************/
419 static subpicture_t
*DecodePacket( decoder_t
*p_dec
, block_t
*p_data
)
421 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
423 subpicture_region_t
*p_region
;
425 video_palette_t palette
;
428 /* Allocate the subpicture internal data. */
429 p_spu
= decoder_NewSubpicture( p_dec
, NULL
);
430 if( !p_spu
) return NULL
;
432 p_spu
->i_start
= p_data
->i_pts
;
433 p_spu
->i_stop
= p_data
->i_pts
+ p_sys
->i_duration
;
434 p_spu
->b_ephemer
= true;
436 /* Create new subtitle region */
437 memset( &fmt
, 0, sizeof(video_format_t
) );
438 fmt
.i_chroma
= VLC_CODEC_YUVP
;
441 The video on which the subtitle sits, is scaled, probably
442 4:3. However subtitle bitmaps assume an 1:1 aspect ratio.
444 FIXME: We should get the video aspect ratio from somewhere.
445 Two candidates are the video and the other possibility would be
448 fmt
.i_sar_num
= p_sys
->i_height
;
449 fmt
.i_sar_den
= p_sys
->i_width
;
451 fmt
.i_width
= fmt
.i_visible_width
= p_sys
->i_width
;
452 fmt
.i_height
= fmt
.i_visible_height
= p_sys
->i_height
;
453 fmt
.i_x_offset
= fmt
.i_y_offset
= 0;
454 fmt
.p_palette
= &palette
;
455 fmt
.p_palette
->i_entries
= 4;
456 for( i
= 0; i
< fmt
.p_palette
->i_entries
; i
++ )
458 fmt
.p_palette
->palette
[i
][0] = p_sys
->p_palette
[i
][0];
459 fmt
.p_palette
->palette
[i
][1] = p_sys
->p_palette
[i
][1];
460 fmt
.p_palette
->palette
[i
][2] = p_sys
->p_palette
[i
][2];
461 fmt
.p_palette
->palette
[i
][3] = p_sys
->p_palette
[i
][3];
464 p_region
= subpicture_region_New( &fmt
);
467 msg_Err( p_dec
, "cannot allocate SVCD subtitle region" );
468 decoder_DeleteSubpicture( p_dec
, p_spu
);
472 p_spu
->p_region
= p_region
;
473 p_region
->i_x
= p_sys
->i_x_start
;
474 p_region
->i_y
= p_sys
->i_y_start
;
476 SVCDSubRenderImage( p_dec
, p_data
, p_region
);
481 /*****************************************************************************
482 * SVCDSubRenderImage: reorders bytes of image data in subpicture region.
483 *****************************************************************************
485 The image is encoded using two bits per pixel that select a palette
486 entry except that value 0 starts a limited run-length encoding for
487 color 0. When 0 is seen, the next two bits encode one less than the
488 number of pixels, so we can encode run lengths from 1 to 4. These get
489 filled with the color in palette entry 0.
491 The encoding of each line is padded to a whole number of bytes. The
492 first field is padded to an even byte length and the complete subtitle
493 is padded to a 4-byte multiple that always include one zero byte at
496 However we'll transform this so that that the RLE is expanded and
497 interlacing will also be removed.
498 *****************************************************************************/
499 static void SVCDSubRenderImage( decoder_t
*p_dec
, block_t
*p_data
,
500 subpicture_region_t
*p_region
)
502 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
503 uint8_t *p_dest
= p_region
->p_picture
->Y_PIXELS
;
504 int i_field
; /* The subtitles are interlaced */
505 int i_row
, i_column
; /* scanline row/column number */
506 uint8_t i_color
, i_count
;
509 bs_init( &bs
, p_data
->p_buffer
+ p_sys
->i_image_offset
,
510 p_data
->i_buffer
- p_sys
->i_image_offset
);
512 for( i_field
= 0; i_field
< 2; i_field
++ )
514 for( i_row
= i_field
; i_row
< p_sys
->i_height
; i_row
+= 2 )
516 for( i_column
= 0; i_column
< p_sys
->i_width
; i_column
++ )
518 i_color
= bs_read( &bs
, 2 );
519 if( i_color
== 0 && (i_count
= bs_read( &bs
, 2 )) )
521 i_count
= __MIN( i_count
, p_sys
->i_width
- i_column
);
522 memset( &p_dest
[i_row
* p_region
->p_picture
->Y_PITCH
+
523 i_column
], 0, i_count
+ 1 );
528 p_dest
[i_row
* p_region
->p_picture
->Y_PITCH
+ i_column
] = i_color
;
535 bs_init( &bs
, p_data
->p_buffer
+ p_sys
->i_image_offset
+
536 p_sys
->second_field_offset
,
537 p_data
->i_buffer
- p_sys
->i_image_offset
-
538 p_sys
->second_field_offset
);