1 /*****************************************************************************
2 * svcdsub.c : Overlay Graphics Text (SVCD subtitles) decoder
3 *****************************************************************************
4 * Copyright (C) 2003, 2004 VLC authors and VideoLAN
5 * $Id: 6be8a43c02c67cf6e45c16d5579cab5813998704 $
6 *
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>
11 *
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.
16 *
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.
21 *
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 *****************************************************************************/
26
27 /*****************************************************************************
28 * Preamble
29 *****************************************************************************/
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif
33
34 #include <vlc_common.h>
35 #include <vlc_plugin.h>
36 #include <vlc_codec.h>
37 #include <vlc_bits.h>
38
39 /*****************************************************************************
40 * Module descriptor.
41 *****************************************************************************/
42 static int DecoderOpen ( vlc_object_t * );
43 static int PacketizerOpen( vlc_object_t * );
44 static void DecoderClose ( vlc_object_t * );
45
46 vlc_module_begin ()
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( "spu decoder", 50 )
52 set_callbacks( DecoderOpen, DecoderClose )
53
54 add_obsolete_integer ( "svcdsub-debug" )
55
56 add_submodule ()
57 set_description( N_("Philips OGT (SVCD subtitle) packetizer") )
58 set_capability( "packetizer", 50 )
59 set_callbacks( PacketizerOpen, DecoderClose )
60 vlc_module_end ()
61
62 /*****************************************************************************
63 * Local prototypes
64 *****************************************************************************/
65 static int 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 * );
71
72 #define GETINT16(p) GetWBE(p) ; p +=2;
73
74 #define GETINT32(p) GetDWBE(p) ; p += 4;
75
76 typedef enum {
77 SUBTITLE_BLOCK_EMPTY = 0,
78 SUBTITLE_BLOCK_PARTIAL = 1,
79 SUBTITLE_BLOCK_COMPLETE = 2
80 } packet_state_t;
81
82 struct decoder_sys_t
83 {
84 packet_state_t i_state; /* data-gathering state for this subtitle */
85
86 block_t *p_spu; /* Bytes of the packet. */
87
88 uint16_t i_image; /* image number in the subtitle stream */
89 uint8_t i_packet; /* packet number for above image number */
90
91 size_t i_spu_size; /* goal for subtitle_data_pos while gathering,
92 size of used subtitle_data later */
93
94 uint16_t i_image_offset; /* offset from subtitle_data to compressed
95 image data */
96 size_t i_image_length; /* size of the compressed image data */
97 size_t second_field_offset; /* offset of odd raster lines */
98 size_t metadata_offset; /* offset to data describing the image */
99 size_t metadata_length; /* length of metadata */
100
101 mtime_t i_duration; /* how long to display the image, 0 stands
102 for "until next subtitle" */
103
104 uint16_t i_x_start, i_y_start; /* position of top leftmost pixel of
105 image when displayed */
106 uint16_t i_width, i_height; /* dimensions in pixels of image */
107
108 uint8_t p_palette[4][4]; /* Palette of colors used in subtitle */
109 };
110
111 /*****************************************************************************
112 * DecoderOpen: open/initialize the svcdsub decoder.
113 *****************************************************************************/
DecoderOpen(vlc_object_t * p_this)114 static int DecoderOpen( vlc_object_t *p_this )
115 {
116 decoder_t *p_dec = (decoder_t*)p_this;
117 decoder_sys_t *p_sys;
118
119 if( p_dec->fmt_in.i_codec != VLC_CODEC_OGT )
120 return VLC_EGENERIC;
121
122 p_dec->p_sys = p_sys = calloc( 1, sizeof( decoder_sys_t ) );
123 if( p_sys == NULL )
124 return VLC_ENOMEM;
125
126
127 p_sys->i_image = -1;
128
129 p_sys->i_state = SUBTITLE_BLOCK_EMPTY;
130 p_sys->p_spu = NULL;
131
132 p_dec->fmt_out.i_codec = VLC_CODEC_OGT;
133
134 p_dec->pf_decode = Decode;
135 p_dec->pf_packetize = Packetize;
136
137 return VLC_SUCCESS;
138 }
139
140 /*****************************************************************************
141 * PacketizerOpen: open/initialize the svcdsub packetizer.
142 *****************************************************************************/
PacketizerOpen(vlc_object_t * p_this)143 static int PacketizerOpen( vlc_object_t *p_this )
144 {
145 if( DecoderOpen( p_this ) != VLC_SUCCESS ) return VLC_EGENERIC;
146
147 return VLC_SUCCESS;
148 }
149
150 /*****************************************************************************
151 * DecoderClose: closes the svcdsub decoder/packetizer.
152 *****************************************************************************/
DecoderClose(vlc_object_t * p_this)153 void DecoderClose( vlc_object_t *p_this )
154 {
155 decoder_t *p_dec = (decoder_t*)p_this;
156 decoder_sys_t *p_sys = p_dec->p_sys;
157
158 if( p_sys->p_spu ) block_ChainRelease( p_sys->p_spu );
159 free( p_sys );
160 }
161
162 /*****************************************************************************
163 * Decode:
164 *****************************************************************************/
Decode(decoder_t * p_dec,block_t * p_block)165 static int Decode( decoder_t *p_dec, block_t *p_block )
166 {
167 #ifndef NDEBUG
168 msg_Dbg( p_dec, "Decode" );
169 #endif
170
171 if( p_block == NULL ) /* No Drain */
172 return VLCDEC_SUCCESS;
173
174 if( !(p_block = Reassemble( p_dec, p_block )) )
175 return VLCDEC_SUCCESS;
176
177 /* Parse and decode */
178 subpicture_t *p_spu = DecodePacket( p_dec, p_block );
179 if( p_spu != NULL )
180 decoder_QueueSub( p_dec, p_spu );
181 return VLCDEC_SUCCESS;
182 }
183
184 /*****************************************************************************
185 * Packetize:
186 *****************************************************************************/
Packetize(decoder_t * p_dec,block_t ** pp_block)187 static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
188 {
189 block_t *p_block, *p_spu;
190
191 if( pp_block == NULL || *pp_block == NULL ) return NULL;
192
193 p_block = *pp_block;
194 *pp_block = NULL;
195
196 if( !(p_spu = Reassemble( p_dec, p_block )) ) return NULL;
197
198 p_spu->i_dts = p_spu->i_pts;
199 p_spu->i_length = 0;
200
201 return p_spu;
202 }
203
204 /*****************************************************************************
205 Reassemble:
206
207 The data for single screen subtitle may come in one of many
208 non-contiguous packets of a stream. This routine is called when the
209 next packet in the stream comes in. The job of this routine is to
210 parse the header, if this is the beginning, and combine the packets
211 into one complete subtitle unit.
212
213 If everything is complete, we will return a block. Otherwise return
214 NULL.
215
216
217 The format of the beginning of the subtitle packet that is used here.
218
219 size description
220 -------------------------------------------
221 byte subtitle channel (0..7) in bits 0-3
222 byte subtitle packet number of this subtitle image 0-N,
223 if the subtitle packet is complete, the top bit of the byte is 1.
224 uint16 subtitle image number
225
226 *****************************************************************************/
227 #define SPU_HEADER_LEN 5
228
Reassemble(decoder_t * p_dec,block_t * p_block)229 static block_t *Reassemble( decoder_t *p_dec, block_t *p_block )
230 {
231 decoder_sys_t *p_sys = p_dec->p_sys;
232 uint8_t *p_buffer;
233 uint16_t i_expected_image;
234 uint8_t i_packet, i_expected_packet;
235
236 if( p_block->i_flags & (BLOCK_FLAG_CORRUPTED) )
237 {
238 block_Release( p_block );
239 return NULL;
240 }
241
242 if( p_block->i_buffer < SPU_HEADER_LEN )
243 {
244 msg_Dbg( p_dec, "invalid packet header (size %zu < %u)" ,
245 p_block->i_buffer, SPU_HEADER_LEN );
246 block_Release( p_block );
247 return NULL;
248 }
249
250 p_buffer = p_block->p_buffer;
251
252 if( p_sys->i_state == SUBTITLE_BLOCK_EMPTY )
253 {
254 i_expected_image = p_sys->i_image + 1;
255 i_expected_packet = 0;
256 }
257 else
258 {
259 i_expected_image = p_sys->i_image;
260 i_expected_packet = p_sys->i_packet + 1;
261 }
262
263 /* The dummy ES that the menu selection uses has an 0x70 at
264 the head which we need to strip off. */
265 p_buffer += 2;
266
267 if( *p_buffer & 0x80 )
268 {
269 p_sys->i_state = SUBTITLE_BLOCK_COMPLETE;
270 i_packet = *p_buffer++ & 0x7F;
271 }
272 else
273 {
274 p_sys->i_state = SUBTITLE_BLOCK_PARTIAL;
275 i_packet = *p_buffer++;
276 }
277
278 p_sys->i_image = GETINT16(p_buffer);
279
280 if( p_sys->i_image != i_expected_image )
281 {
282 msg_Warn( p_dec, "expected subtitle image %u but found %u",
283 i_expected_image, p_sys->i_image );
284 }
285
286 if( i_packet != i_expected_packet )
287 {
288 msg_Warn( p_dec, "expected subtitle image packet %u but found %u",
289 i_expected_packet, i_packet );
290 }
291
292 p_block->p_buffer += SPU_HEADER_LEN;
293 p_block->i_buffer -= SPU_HEADER_LEN;
294
295 p_sys->i_packet = i_packet;
296 /* First packet in the subtitle block */
297 if( !p_sys->i_packet ) ParseHeader( p_dec, p_block );
298
299 block_ChainAppend( &p_sys->p_spu, p_block );
300
301 if( p_sys->i_state == SUBTITLE_BLOCK_COMPLETE )
302 {
303 block_t *p_spu = block_ChainGather( p_sys->p_spu );
304
305 if( unlikely( !p_spu ) )
306 {
307 block_ChainRelease( p_sys->p_spu );
308 p_sys->i_state = SUBTITLE_BLOCK_EMPTY;
309 p_sys->p_spu = NULL;
310
311 msg_Warn( p_dec, "unable to assemble blocks, discarding" );
312 return NULL;
313 }
314
315 if( p_spu->i_buffer != p_sys->i_spu_size )
316 {
317 msg_Warn( p_dec, "subtitle packets size=%zu should be %zu",
318 p_spu->i_buffer, p_sys->i_spu_size );
319 }
320
321 msg_Dbg( p_dec, "subtitle packet complete, size=%zu", p_spu->i_buffer );
322
323 p_sys->i_state = SUBTITLE_BLOCK_EMPTY;
324 p_sys->p_spu = NULL;
325 return p_spu;
326 }
327
328 return NULL;
329 }
330
331 /******************************************************************************
332 The format is roughly as follows (everything is big-endian):
333
334 size description
335 -------------------------------------------
336 byte subtitle channel (0..7) in bits 0-3
337 byte subtitle packet number of this subtitle image 0-N,
338 if the subtitle packet is complete, the top bit of the byte is 1.
339 u_int16 subtitle image number
340 u_int16 length in bytes of the rest
341 byte option flags, unknown meaning except bit 3 (0x08) indicates
342 presence of the duration field
343 byte unknown
344 u_int32 duration in 1/90000ths of a second (optional), start time
345 is as indicated by the PTS in the PES header
346 u_int32 xpos
347 u_int32 ypos
348 u_int32 width (must be even)
349 u_int32 height (must be even)
350 byte[16] palette, 4 palette entries, each contains values for
351 Y, U, V and transparency, 0 standing for transparent
352 byte command,
353 cmd>>6==1 indicates shift
354 (cmd>>4)&3 is direction from, (0=top,1=left,2=right,3=bottom)
355 u_int32 shift duration in 1/90000ths of a second
356 u_int16 offset of odd-numbered scanlines - subtitle images are
357 given in interlace order
358 byte[] limited RLE image data in interlace order (0,2,4... 1,3,5) with
359 2-bits per palette number
360 ******************************************************************************/
ParseHeader(decoder_t * p_dec,block_t * p_block)361 static void ParseHeader( decoder_t *p_dec, block_t *p_block )
362 {
363 decoder_sys_t *p_sys = p_dec->p_sys;
364 uint8_t *p = p_block->p_buffer;
365 size_t i_buffer = p_block->i_buffer;
366 uint8_t i_options, i_cmd;
367 int i;
368
369 if (i_buffer < 4) return;
370
371 p_sys->i_spu_size = GETINT16(p);
372 i_options = *p++;
373 // Skip over unused value
374 p++;
375
376 i_buffer -= 4;
377
378 if( i_options & 0x08 ) {
379 if (i_buffer < 4) return;
380 p_sys->i_duration = GETINT32(p);
381 p += 4;
382 i_buffer -= 4;
383 }
384 else p_sys->i_duration = 0; /* Ephemer subtitle */
385 p_sys->i_duration *= 100 / 9;
386
387 if (i_buffer < 25) return;
388
389 p_sys->i_x_start = GETINT16(p);
390 p_sys->i_y_start = GETINT16(p);
391 p_sys->i_width = GETINT16(p);
392 p_sys->i_height = GETINT16(p);
393
394 for( i = 0; i < 4; i++ )
395 {
396 p_sys->p_palette[i][0] = *p++; /* Y */
397 p_sys->p_palette[i][2] = *p++; /* Cr / V */
398 p_sys->p_palette[i][1] = *p++; /* Cb / U */
399 p_sys->p_palette[i][3] = *p++; /* T */
400 }
401
402 i_cmd = *p++;
403
404 i_buffer -= 25;
405
406 /* We do not really know this, FIXME */
407 if( i_cmd ) {
408 if (i_buffer < 4) return;
409 p += 4;
410 i_buffer -= 4;
411 }
412
413 /* Actually, this is measured against a different origin, so we have to
414 * adjust it */
415 if (i_buffer < 2) return;
416 p_sys->second_field_offset = GETINT16(p);
417 i_buffer -= 2;
418 p_sys->i_image_offset = p - p_block->p_buffer;
419 p_sys->i_image_length = p_sys->i_spu_size - p_sys->i_image_offset;
420 p_sys->metadata_length = p_sys->i_image_offset;
421
422 #ifndef NDEBUG
423 msg_Dbg( p_dec, "x-start: %d, y-start: %d, width: %d, height %d, "
424 "spu size: %zu, duration: %"PRIu64" (d:%zu p:%"PRIu16")",
425 p_sys->i_x_start, p_sys->i_y_start,
426 p_sys->i_width, p_sys->i_height,
427 p_sys->i_spu_size, p_sys->i_duration,
428 p_sys->i_image_length, p_sys->i_image_offset);
429
430 for( i = 0; i < 4; i++ )
431 {
432 msg_Dbg( p_dec, "palette[%d]= T: %2x, Y: %2x, u: %2x, v: %2x", i,
433 p_sys->p_palette[i][3], p_sys->p_palette[i][0],
434 p_sys->p_palette[i][1], p_sys->p_palette[i][2] );
435 }
436 #endif
437 }
438
439 /*****************************************************************************
440 * DecodePacket: parse and decode an subtitle packet
441 *****************************************************************************
442 * This function parses and decodes an SPU packet and, if valid, returns a
443 * subpicture.
444 *****************************************************************************/
DecodePacket(decoder_t * p_dec,block_t * p_data)445 static subpicture_t *DecodePacket( decoder_t *p_dec, block_t *p_data )
446 {
447 decoder_sys_t *p_sys = p_dec->p_sys;
448 subpicture_t *p_spu;
449 subpicture_region_t *p_region;
450 video_format_t fmt;
451 video_palette_t palette;
452 int i;
453
454 /* Allocate the subpicture internal data. */
455 p_spu = decoder_NewSubpicture( p_dec, NULL );
456 if( !p_spu ) return NULL;
457
458 p_spu->i_start = p_data->i_pts;
459 p_spu->i_stop = p_data->i_pts + p_sys->i_duration;
460 p_spu->b_ephemer = true;
461
462 /* Create new subtitle region */
463 video_format_Init( &fmt, VLC_CODEC_YUVP );
464
465 /**
466 The video on which the subtitle sits, is scaled, probably
467 4:3. However subtitle bitmaps assume an 1:1 aspect ratio.
468
469 FIXME: We should get the video aspect ratio from somewhere.
470 Two candidates are the video and the other possibility would be
471 the access module.
472 */
473 fmt.i_sar_num = p_sys->i_height;
474 fmt.i_sar_den = p_sys->i_width;
475
476 fmt.i_width = fmt.i_visible_width = p_sys->i_width;
477 fmt.i_height = fmt.i_visible_height = p_sys->i_height;
478 fmt.i_x_offset = fmt.i_y_offset = 0;
479 fmt.p_palette = &palette;
480 fmt.p_palette->i_entries = 4;
481 for( i = 0; i < fmt.p_palette->i_entries; i++ )
482 {
483 fmt.p_palette->palette[i][0] = p_sys->p_palette[i][0];
484 fmt.p_palette->palette[i][1] = p_sys->p_palette[i][1];
485 fmt.p_palette->palette[i][2] = p_sys->p_palette[i][2];
486 fmt.p_palette->palette[i][3] = p_sys->p_palette[i][3];
487 }
488
489 p_region = subpicture_region_New( &fmt );
490 fmt.p_palette = NULL;
491 video_format_Clean( &fmt );
492 if( !p_region )
493 {
494 msg_Err( p_dec, "cannot allocate SVCD subtitle region" );
495 subpicture_Delete( p_spu );
496 return NULL;
497 }
498
499 p_spu->p_region = p_region;
500 p_region->i_x = p_sys->i_x_start;
501 p_region->i_y = p_sys->i_y_start;
502
503 SVCDSubRenderImage( p_dec, p_data, p_region );
504
505 return p_spu;
506 }
507
508 /*****************************************************************************
509 * SVCDSubRenderImage: reorders bytes of image data in subpicture region.
510 *****************************************************************************
511
512 The image is encoded using two bits per pixel that select a palette
513 entry except that value 0 starts a limited run-length encoding for
514 color 0. When 0 is seen, the next two bits encode one less than the
515 number of pixels, so we can encode run lengths from 1 to 4. These get
516 filled with the color in palette entry 0.
517
518 The encoding of each line is padded to a whole number of bytes. The
519 first field is padded to an even byte length and the complete subtitle
520 is padded to a 4-byte multiple that always include one zero byte at
521 the end.
522
523 However we'll transform this so that that the RLE is expanded and
524 interlacing will also be removed.
525 *****************************************************************************/
SVCDSubRenderImage(decoder_t * p_dec,block_t * p_data,subpicture_region_t * p_region)526 static void SVCDSubRenderImage( decoder_t *p_dec, block_t *p_data,
527 subpicture_region_t *p_region )
528 {
529 decoder_sys_t *p_sys = p_dec->p_sys;
530 uint8_t *p_dest = p_region->p_picture->Y_PIXELS;
531 int i_field; /* The subtitles are interlaced */
532 int i_row, i_column; /* scanline row/column number */
533 uint8_t i_color, i_count;
534 bs_t bs;
535
536 bs_init( &bs, p_data->p_buffer + p_sys->i_image_offset,
537 p_data->i_buffer - p_sys->i_image_offset );
538
539 for( i_field = 0; i_field < 2; i_field++ )
540 {
541 for( i_row = i_field; i_row < p_sys->i_height; i_row += 2 )
542 {
543 for( i_column = 0; i_column < p_sys->i_width; i_column++ )
544 {
545 i_color = bs_read( &bs, 2 );
546 if( i_color == 0 && (i_count = bs_read( &bs, 2 )) )
547 {
548 i_count = __MIN( i_count, p_sys->i_width - i_column );
549 memset( &p_dest[i_row * p_region->p_picture->Y_PITCH +
550 i_column], 0, i_count + 1 );
551 i_column += i_count;
552 continue;
553 }
554
555 p_dest[i_row * p_region->p_picture->Y_PITCH + i_column] = i_color;
556 }
557
558 bs_align( &bs );
559 }
560
561 /* odd field */
562 bs_init( &bs, p_data->p_buffer + p_sys->i_image_offset +
563 p_sys->second_field_offset,
564 p_data->i_buffer - p_sys->i_image_offset -
565 p_sys->second_field_offset );
566 }
567 }
568