remove unndeed variables
[vlc/asuraparaju-public.git] / modules / codec / svcdsub.c
blob184311510b59b6588e0fb88e4d0b11fd0ab465ae
1 /*****************************************************************************
2 * svcdsub.c : Overlay Graphics Text (SVCD subtitles) decoder
3 *****************************************************************************
4 * Copyright (C) 2003, 2004 the VideoLAN team
5 * $Id$
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 /*****************************************************************************
28 * Preamble
29 *****************************************************************************/
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif
34 #include <vlc_common.h>
35 #include <vlc_plugin.h>
36 #include <vlc_codec.h>
37 #include <vlc_osd.h>
38 #include "vlc_bits.h"
40 /*****************************************************************************
41 * Module descriptor.
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" \
51 "calls 1\n" \
52 "packet assembly info 2\n" )
54 vlc_module_begin ()
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 );
65 add_submodule ()
66 set_description( N_("Philips OGT (SVCD subtitle) packetizer") )
67 set_capability( "packetizer", 50 )
68 set_callbacks( PacketizerOpen, DecoderClose )
69 vlc_module_end ()
71 /*****************************************************************************
72 * Local prototypes
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;
89 typedef enum {
90 SUBTITLE_BLOCK_EMPTY = 0,
91 SUBTITLE_BLOCK_PARTIAL = 1,
92 SUBTITLE_BLOCK_COMPLETE = 2
93 } packet_state_t;
95 #ifndef DECODE_DEBUG
96 #define DECODE_DEBUG 1
97 #endif
98 #if DECODE_DEBUG
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)
102 #else
103 #define dbg_print(mask, s, args...)
104 #endif
106 struct decoder_sys_t
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
121 image data */
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_FOURCC( 'o','g','t',' ' ) )
147 return VLC_EGENERIC;
150 p_dec->p_sys = p_sys = calloc( 1, sizeof( decoder_sys_t ) );
151 if( p_sys == NULL )
152 return VLC_ENOMEM;
154 p_sys->i_debug = config_GetInt( p_this, MODULE_STRING "-debug" );
156 p_sys->i_image = -1;
158 p_sys->i_state = SUBTITLE_BLOCK_EMPTY;
159 p_sys->p_spu = NULL;
161 es_format_Init( &p_dec->fmt_out, SPU_ES, VLC_FOURCC( 'o','g','t',' ' ) );
163 p_dec->pf_decode_sub = Decode;
164 p_dec->pf_packetize = Packetize;
166 dbg_print( (DECODE_DBG_CALL) , "");
167 return VLC_SUCCESS;
170 /*****************************************************************************
171 * PacketizerOpen: open/initialize the svcdsub packetizer.
172 *****************************************************************************/
173 static int PacketizerOpen( vlc_object_t *p_this )
175 if( DecoderOpen( p_this ) != VLC_SUCCESS ) return VLC_EGENERIC;
177 return VLC_SUCCESS;
180 /*****************************************************************************
181 * DecoderClose: closes the svcdsub decoder/packetizer.
182 *****************************************************************************/
183 void DecoderClose( vlc_object_t *p_this )
185 decoder_t *p_dec = (decoder_t*)p_this;
186 decoder_sys_t *p_sys = p_dec->p_sys;
188 if( p_sys->p_spu ) block_ChainRelease( p_sys->p_spu );
189 free( p_sys );
192 /*****************************************************************************
193 * Decode:
194 *****************************************************************************/
195 static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block )
197 block_t *p_block, *p_spu;
198 decoder_sys_t *p_sys = p_dec->p_sys;
200 dbg_print( (DECODE_DBG_CALL) , "");
202 if( pp_block == NULL || *pp_block == NULL ) return NULL;
204 p_block = *pp_block;
205 *pp_block = NULL;
207 if( !(p_spu = Reassemble( p_dec, p_block )) ) return NULL;
209 /* Parse and decode */
210 return DecodePacket( p_dec, p_spu );
213 /*****************************************************************************
214 * Packetize:
215 *****************************************************************************/
216 static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
218 block_t *p_block, *p_spu;
220 if( pp_block == NULL || *pp_block == NULL ) return NULL;
222 p_block = *pp_block;
223 *pp_block = NULL;
225 if( !(p_spu = Reassemble( p_dec, p_block )) ) return NULL;
227 p_spu->i_dts = p_spu->i_pts;
228 p_spu->i_length = 0;
230 return p_spu;
233 /*****************************************************************************
234 Reassemble:
236 The data for single screen subtitle may come in one of many
237 non-contiguous packets of a stream. This routine is called when the
238 next packet in the stream comes in. The job of this routine is to
239 parse the header, if this is the beginning, and combine the packets
240 into one complete subtitle unit.
242 If everything is complete, we will return a block. Otherwise return
243 NULL.
246 The format of the beginning of the subtitle packet that is used here.
248 size description
249 -------------------------------------------
250 byte subtitle channel (0..7) in bits 0-3
251 byte subtitle packet number of this subtitle image 0-N,
252 if the subtitle packet is complete, the top bit of the byte is 1.
253 uint16 subtitle image number
255 *****************************************************************************/
256 #define SPU_HEADER_LEN 5
258 static block_t *Reassemble( decoder_t *p_dec, block_t *p_block )
260 decoder_sys_t *p_sys = p_dec->p_sys;
261 uint8_t *p_buffer;
262 uint16_t i_expected_image;
263 uint8_t i_packet, i_expected_packet;
265 if( p_block->i_buffer < SPU_HEADER_LEN )
267 msg_Dbg( p_dec, "invalid packet header (size %zu < %u)" ,
268 p_block->i_buffer, SPU_HEADER_LEN );
269 block_Release( p_block );
270 return NULL;
273 p_buffer = p_block->p_buffer;
275 /* Attach to our input thread and see if subtitle is selected. */
277 vlc_object_t * p_input;
278 vlc_value_t val;
280 p_input = vlc_object_find( p_dec, VLC_OBJECT_INPUT, FIND_PARENT );
282 if( !p_input ) return NULL;
284 if( var_Get( p_input, "sub-track", &val ) )
286 vlc_object_release( p_input );
287 return NULL;
290 vlc_object_release( p_input );
291 dbg_print( (DECODE_DBG_PACKET),
292 "val.i_int %x p_buffer[i] %x", val.i_int, p_buffer[1]);
294 /* The dummy ES that the menu selection uses has an 0x70 at
295 the head which we need to strip off. */
296 if( val.i_int == -1 || (val.i_int & 0x03) != p_buffer[1] )
298 dbg_print( DECODE_DBG_PACKET, "subtitle not for us.\n");
299 return NULL;
303 if( p_sys->i_state == SUBTITLE_BLOCK_EMPTY )
305 i_expected_image = p_sys->i_image + 1;
306 i_expected_packet = 0;
308 else
310 i_expected_image = p_sys->i_image;
311 i_expected_packet = p_sys->i_packet + 1;
314 p_buffer += 2;
316 if( *p_buffer & 0x80 )
318 p_sys->i_state = SUBTITLE_BLOCK_COMPLETE;
319 i_packet = *p_buffer++ & 0x7F;
321 else
323 p_sys->i_state = SUBTITLE_BLOCK_PARTIAL;
324 i_packet = *p_buffer++;
327 p_sys->i_image = GETINT16(p_buffer);
329 if( p_sys->i_image != i_expected_image )
331 msg_Warn( p_dec, "expected subtitle image %u but found %u",
332 i_expected_image, p_sys->i_image );
335 if( i_packet != i_expected_packet )
337 msg_Warn( p_dec, "expected subtitle image packet %u but found %u",
338 i_expected_packet, i_packet );
341 p_block->p_buffer += SPU_HEADER_LEN;
342 p_block->i_buffer -= SPU_HEADER_LEN;
344 p_sys->i_packet = i_packet;
345 /* First packet in the subtitle block */
346 if( !p_sys->i_packet ) ParseHeader( p_dec, p_block );
348 block_ChainAppend( &p_sys->p_spu, p_block );
350 if( p_sys->i_state == SUBTITLE_BLOCK_COMPLETE )
352 block_t *p_spu = block_ChainGather( p_sys->p_spu );
354 if( p_spu->i_buffer != p_sys->i_spu_size )
356 msg_Warn( p_dec, "subtitle packets size=%zu should be %zu",
357 p_spu->i_buffer, p_sys->i_spu_size );
360 dbg_print( (DECODE_DBG_PACKET),
361 "subtitle packet complete, size=%zu", p_spu->i_buffer );
363 p_sys->i_state = SUBTITLE_BLOCK_EMPTY;
364 p_sys->p_spu = 0;
365 return p_spu;
368 return NULL;
371 /******************************************************************************
372 The format is roughly as follows (everything is big-endian):
374 size description
375 -------------------------------------------
376 byte subtitle channel (0..7) in bits 0-3
377 byte subtitle packet number of this subtitle image 0-N,
378 if the subtitle packet is complete, the top bit of the byte is 1.
379 u_int16 subtitle image number
380 u_int16 length in bytes of the rest
381 byte option flags, unknown meaning except bit 3 (0x08) indicates
382 presence of the duration field
383 byte unknown
384 u_int32 duration in 1/90000ths of a second (optional), start time
385 is as indicated by the PTS in the PES header
386 u_int32 xpos
387 u_int32 ypos
388 u_int32 width (must be even)
389 u_int32 height (must be even)
390 byte[16] palette, 4 palette entries, each contains values for
391 Y, U, V and transparency, 0 standing for transparent
392 byte command,
393 cmd>>6==1 indicates shift
394 (cmd>>4)&3 is direction from, (0=top,1=left,2=right,3=bottom)
395 u_int32 shift duration in 1/90000ths of a second
396 u_int16 offset of odd-numbered scanlines - subtitle images are
397 given in interlace order
398 byte[] limited RLE image data in interlace order (0,2,4... 1,3,5) with
399 2-bits per palette number
400 ******************************************************************************/
401 static void ParseHeader( decoder_t *p_dec, block_t *p_block )
403 decoder_sys_t *p_sys = p_dec->p_sys;
404 uint8_t *p = p_block->p_buffer;
405 uint8_t i_options, i_options2, i_cmd, i_cmd_arg;
406 int i;
408 p_sys->i_spu_size = GETINT16(p);
409 i_options = *p++;
410 i_options2 = *p++;
412 if( i_options & 0x08 ) { p_sys->i_duration = GETINT32(p); }
413 else p_sys->i_duration = 0; /* Ephemer subtitle */
414 p_sys->i_duration *= 100 / 9;
416 p_sys->i_x_start = GETINT16(p);
417 p_sys->i_y_start = GETINT16(p);
418 p_sys->i_width = GETINT16(p);
419 p_sys->i_height = GETINT16(p);
421 for( i = 0; i < 4; i++ )
423 p_sys->p_palette[i][0] = *p++; /* Y */
424 p_sys->p_palette[i][2] = *p++; /* Cr / V */
425 p_sys->p_palette[i][1] = *p++; /* Cb / U */
426 p_sys->p_palette[i][3] = *p++; /* T */
429 i_cmd = *p++;
430 /* We do not really know this, FIXME */
431 if( i_cmd ) {i_cmd_arg = GETINT32(p);}
433 /* Actually, this is measured against a different origin, so we have to
434 * adjust it */
435 p_sys->second_field_offset = GETINT16(p);
436 p_sys->i_image_offset = p - p_block->p_buffer;
437 p_sys->i_image_length = p_sys->i_spu_size - p_sys->i_image_offset;
438 p_sys->metadata_length = p_sys->i_image_offset;
440 if( p_sys->i_debug & DECODE_DBG_PACKET )
442 msg_Dbg( p_dec, "x-start: %d, y-start: %d, width: %d, height %d, "
443 "spu size: %zu, duration: %"PRIu64" (d:%zu p:%"PRIu16")",
444 p_sys->i_x_start, p_sys->i_y_start,
445 p_sys->i_width, p_sys->i_height,
446 p_sys->i_spu_size, p_sys->i_duration,
447 p_sys->i_image_length, p_sys->i_image_offset);
449 for( i = 0; i < 4; i++ )
451 msg_Dbg( p_dec, "palette[%d]= T: %2x, Y: %2x, u: %2x, v: %2x", i,
452 p_sys->p_palette[i][3], p_sys->p_palette[i][0],
453 p_sys->p_palette[i][1], p_sys->p_palette[i][2] );
458 /*****************************************************************************
459 * DecodePacket: parse and decode an subtitle packet
460 *****************************************************************************
461 * This function parses and decodes an SPU packet and, if valid, returns a
462 * subpicture.
463 *****************************************************************************/
464 static subpicture_t *DecodePacket( decoder_t *p_dec, block_t *p_data )
466 decoder_sys_t *p_sys = p_dec->p_sys;
467 subpicture_t *p_spu;
468 subpicture_region_t *p_region;
469 video_format_t fmt;
470 video_palette_t palette;
471 int i;
473 /* Allocate the subpicture internal data. */
474 p_spu = decoder_NewSubpicture( p_dec );
475 if( !p_spu ) return NULL;
477 p_spu->i_start = p_data->i_pts;
478 p_spu->i_stop = p_data->i_pts + p_sys->i_duration;
479 p_spu->b_ephemer = true;
481 /* Create new subtitle region */
482 memset( &fmt, 0, sizeof(video_format_t) );
483 fmt.i_chroma = VLC_FOURCC('Y','U','V','P');
486 The video on which the subtitle sits, is scaled, probably
487 4:3. However subtitle bitmaps assume an 1:1 aspect ratio.
489 FIXME: We should get the video aspect ratio from somewhere.
490 Two candidates are the video and the other possibility would be
491 the access module.
493 fmt.i_aspect = VOUT_ASPECT_FACTOR;
495 fmt.i_width = fmt.i_visible_width = p_sys->i_width;
496 fmt.i_height = fmt.i_visible_height = p_sys->i_height;
497 fmt.i_x_offset = fmt.i_y_offset = 0;
498 fmt.p_palette = &palette;
499 fmt.p_palette->i_entries = 4;
500 for( i = 0; i < fmt.p_palette->i_entries; i++ )
502 fmt.p_palette->palette[i][0] = p_sys->p_palette[i][0];
503 fmt.p_palette->palette[i][1] = p_sys->p_palette[i][1];
504 fmt.p_palette->palette[i][2] = p_sys->p_palette[i][2];
505 fmt.p_palette->palette[i][3] = p_sys->p_palette[i][3];
508 p_region = subpicture_region_New( &fmt );
509 if( !p_region )
511 msg_Err( p_dec, "cannot allocate SVCD subtitle region" );
512 decoder_DeleteSubpicture( p_dec, p_spu );
513 return NULL;
516 p_spu->p_region = p_region;
517 p_region->i_x = p_sys->i_x_start;
518 p_region->i_y = p_sys->i_y_start;
520 SVCDSubRenderImage( p_dec, p_data, p_region );
522 return p_spu;
525 /*****************************************************************************
526 * SVCDSubRenderImage: reorders bytes of image data in subpicture region.
527 *****************************************************************************
529 The image is encoded using two bits per pixel that select a palette
530 entry except that value 0 starts a limited run-length encoding for
531 color 0. When 0 is seen, the next two bits encode one less than the
532 number of pixels, so we can encode run lengths from 1 to 4. These get
533 filled with the color in palette entry 0.
535 The encoding of each line is padded to a whole number of bytes. The
536 first field is padded to an even byte length and the complete subtitle
537 is padded to a 4-byte multiple that always include one zero byte at
538 the end.
540 However we'll transform this so that that the RLE is expanded and
541 interlacing will also be removed.
542 *****************************************************************************/
543 static void SVCDSubRenderImage( decoder_t *p_dec, block_t *p_data,
544 subpicture_region_t *p_region )
546 decoder_sys_t *p_sys = p_dec->p_sys;
547 uint8_t *p_dest = p_region->p_picture->Y_PIXELS;
548 int i_field; /* The subtitles are interlaced */
549 int i_row, i_column; /* scanline row/column number */
550 uint8_t i_color, i_count;
551 bs_t bs;
553 bs_init( &bs, p_data->p_buffer + p_sys->i_image_offset,
554 p_data->i_buffer - p_sys->i_image_offset );
556 for( i_field = 0; i_field < 2; i_field++ )
558 for( i_row = i_field; i_row < p_sys->i_height; i_row += 2 )
560 for( i_column = 0; i_column < p_sys->i_width; i_column++ )
562 i_color = bs_read( &bs, 2 );
563 if( i_color == 0 && (i_count = bs_read( &bs, 2 )) )
565 i_count = __MIN( i_count, p_sys->i_width - i_column );
566 memset( &p_dest[i_row * p_region->p_picture->Y_PITCH +
567 i_column], 0, i_count + 1 );
568 i_column += i_count;
569 continue;
572 p_dest[i_row * p_region->p_picture->Y_PITCH + i_column] = i_color;
575 bs_align( &bs );
578 /* odd field */
579 bs_init( &bs, p_data->p_buffer + p_sys->i_image_offset +
580 p_sys->second_field_offset,
581 p_data->i_buffer - p_sys->i_image_offset -
582 p_sys->second_field_offset );