* parse.c: Philips OGT (SVCD subtitle) packet parser
*****************************************************************************
* Copyright (C) 2003, 2004 VideoLAN
- * $Id: cvd_parse.c,v 1.6 2004/01/04 04:56:21 rocky Exp $
+ * $Id$
*
* Authors: Rocky Bernstein
* based on code from:
origin. Thus, this is the result of reading some code whose
correctness is not known and some experimentation.
- CVD subtitles are different in severl ways from SVCD OGT subtitles.
- First, the image comes first and the metadata is at the end. So
- that the metadata can be found easily, the subtitle packet starts
- with two bytes (everything is big-endian again) that give the total
- size of the subtitle data and the offset to the metadata - i.e. size
- of the image data plus the four bytes at the beginning.
+ CVD subtitles are different in several ways from SVCD OGT subtitles.
+ Image comes first and metadata is at the end. So that the metadata
+ can be found easily, the subtitle packet starts with two bytes
+ (everything is big-endian again) that give the total size of the
+ subtitle data and the offset to the metadata - i.e. size of the
+ image data plus the four bytes at the beginning.
Image data comes interlaced is run-length encoded. Each field is a
four-bit nibble. Each nibble contains a two-bit repeat count and a
that the fill-line complete case above is not as described and the
zero repeat count means fill line. The sample code never produces
this, so it may be untested.
-
- The metadata section does not follow a fixed pattern, every
- metadata item consists of a tag byte followed by parameters. In all
- cases known, the block (including the tag byte) is exactly four
- bytes in length. Read the code for the rest.
*/
void E_(ParseHeader)( decoder_t *p_dec, uint8_t *p_buffer, block_t *p_block )
{
decoder_sys_t *p_sys = p_dec->p_sys;
- u_int8_t *p = p_buffer+1;
+ uint8_t *p = p_buffer+1;
dbg_print( (DECODE_DBG_CALL|DECODE_DBG_PACKET),
"header: 0x%02x 0x%02x 0x%02x 0x%02x, 0x%02x, 0x%02x, size: %i",
p_sys->metadata_offset = GETINT16(p);
p_sys->metadata_length = p_sys->i_spu_size - p_sys->metadata_offset;
- p_sys->comp_image_offset = 4;
- p_sys->comp_image_length = p_sys->metadata_offset - p_sys->comp_image_offset;
+ p_sys->i_image_offset = 4;
+ p_sys->i_image_length = p_sys->metadata_offset - p_sys->i_image_offset;
dbg_print(DECODE_DBG_PACKET, "total size: %d image size: %d\n",
- p_sys->i_spu_size, p_sys->comp_image_length);
+ p_sys->i_spu_size, p_sys->i_image_length);
}
+#define ExtractXY(x, y) \
+ x = ((p[1]&0x0f)<<6) + (p[2]>>2); \
+ y = ((p[2]&0x03)<<8) + p[3];
+
+
+/*
+ We parse the metadata information here.
+
+ Although metadata information does not have to come in a fixed field
+ order, every metadata field consists of a tag byte followed by
+ parameters. In all cases known, the size including tag byte is
+ exactly four bytes in length.
+*/
+
void E_(ParseMetaInfo)( decoder_t *p_dec )
{
/* last packet in subtitle block. */
switch ( p[0] ) {
- case 0x04: /* Display duration in 1/90000ths of a second */
-
- p_sys->i_duration = (p[1]<<16) + (p[2]<<8) + p[3];
+ case 0x04: /* subtitle duration in 1/90000ths of a second */
+ {
+ mtime_t i_duration = (p[1]<<16) + (p[2]<<8) + p[3];
+ mtime_t i_duration_scale = config_GetInt( p_dec, MODULE_STRING
+ "-duration-scaling" );
+
+ dbg_print( DECODE_DBG_PACKET,
+ "subtitle display duration %lu secs (scaled %lu secs)",
+ (long unsigned int) (i_duration / 90000),
+ (long unsigned int) (i_duration * i_duration_scale / 90000)
+ );
+ p_sys->i_duration = i_duration * i_duration_scale ;
+ break;
+ }
- dbg_print( DECODE_DBG_PACKET,
- "subtitle display duration %u", p_sys->i_duration);
- break;
- case 0x0c: /* Unknown */
+ case 0x0c: /* unknown */
dbg_print( DECODE_DBG_PACKET,
"subtitle command unknown 0x%0x 0x%0x 0x%0x 0x%0x\n",
p[0], p[1], p[2], p[3]);
break;
- case 0x17: /* Position */
- p_sys->i_x_start = ((p[1]&0x0f)<<6) + (p[2]>>2);
- p_sys->i_y_start = ((p[2]&0x03)<<8) + p[3];
- dbg_print( DECODE_DBG_PACKET,
- "start position (%d,%d): %.2x %.2x %.2x",
- p_sys->i_x_start, p_sys->i_y_start,
- p[1], p[2], p[3] );
+ case 0x17: /* coordinates of subtitle upper left x, y position */
+ ExtractXY(p_sys->i_x_start, p_sys->i_y_start);
break;
- case 0x1f: /* Coordinates of the image bottom right */
+ case 0x1f: /* coordinates of subtitle bottom right x, y position */
{
- int lastx = ((p[1]&0x0f)<<6) + (p[2]>>2);
- int lasty = ((p[2]&0x03)<<8) + p[3];
+ int lastx;
+ int lasty;
+ ExtractXY(lastx, lasty);
p_sys->i_width = lastx - p_sys->i_x_start + 1;
p_sys->i_height = lasty - p_sys->i_y_start + 1;
dbg_print( DECODE_DBG_PACKET,
p_sys->p_palette[3].s.t = p[2] >> 4;
dbg_print( DECODE_DBG_PACKET,
- "transparancy for primary palette 0..3: "
+ "transparency for primary palette 0..3: "
"0x%0x 0x%0x 0x%0x 0x%0x",
p_sys->p_palette[0].s.t,
p_sys->p_palette[1].s.t,
p_sys->p_palette_highlight[3].s.t = p[1] >> 4;
dbg_print( DECODE_DBG_PACKET,
- "transparancy for primary palette 0..3: "
+ "transparency for primary palette 0..3: "
"0x%0x 0x%0x 0x%0x 0x%0x",
p_sys->p_palette_highlight[0].s.t,
p_sys->p_palette_highlight[1].s.t,
break;
case 0x47:
- /* offset to first field data, we correct to make it relative
- to comp_image_offset (usually 4) */
+ /* offset to start of even rows of interlaced image, we correct
+ to make it relative to i_image_offset (usually 4) */
p_sys->first_field_offset =
- (p[2] << 8) + p[3] - p_sys->comp_image_offset;
+ (p[2] << 8) + p[3] - p_sys->i_image_offset;
dbg_print( DECODE_DBG_PACKET,
"first_field_offset %d", p_sys->first_field_offset);
break;
case 0x4f:
- /* offset to second field data, we correct to make it relative to
- comp_image_offset (usually 4) */
+ /* offset to start of odd rows of interlaced image, we correct
+ to make it relative to i_image_offset (usually 4) */
p_sys->second_field_offset =
- (p[2] << 8) + p[3] - p_sys->comp_image_offset;
+ (p[2] << 8) + p[3] - p_sys->i_image_offset;
dbg_print( DECODE_DBG_PACKET,
"second_field_offset %d", p_sys->second_field_offset);
break;
dbg_print( (DECODE_DBG_CALL|DECODE_DBG_EXT) , "");
/* Allocate the subpicture internal data. */
- p_spu = vout_CreateSubPicture( p_sys->p_vout, MEMORY_SUBPICTURE );
- if( p_spu == NULL )
- {
- return;
- }
+ p_spu = spu_CreateSubpicture( p_sys->p_vout->p_spu );
+ if( p_spu == NULL ) return;
+
+ p_spu->i_channel = p_sys->i_subpic_channel;
/* In ParseImage we expand the run-length encoded color 0's; also
we expand pixels and remove the color palette. This should
/* Fill the p_spu structure */
vlc_mutex_init( p_dec, &p_spu->p_sys->lock );
- p_spu->pf_render = VCDSubRender;
+ p_spu->pf_render = VCDSubBlend;
p_spu->pf_destroy = VCDSubDestroySPU;
p_spu->p_sys->p_data = (uint8_t*)p_spu->p_sys + sizeof( subpicture_sys_t );
p_spu->p_sys->i_x_end = p_sys->i_x_start + p_sys->i_width - 1;
p_spu->p_sys->i_y_end = p_sys->i_y_start + p_sys->i_height - 1;
+ p_spu->i_x = p_sys->i_x_start
+ + config_GetInt( p_dec, MODULE_STRING "-horizontal-correct" );
+
+ p_spu->p_sys->p_palette[0] = p_sys->p_palette[0];
+ p_spu->p_sys->p_palette[1] = p_sys->p_palette[1];
+ p_spu->p_sys->p_palette[2] = p_sys->p_palette[2];
+ p_spu->p_sys->p_palette[3] = p_sys->p_palette[3];
+
/* FIXME: use aspect ratio for x? */
- p_spu->i_x = p_sys->i_x_start * 3 / 4;
- p_spu->i_y = p_sys->i_y_start;
+ p_spu->i_x = (p_spu->i_x * 3) / 4;
+ p_spu->i_y = p_sys->i_y_start
+ + config_GetInt( p_dec, MODULE_STRING "-vertical-correct" );
+
p_spu->i_width = p_sys->i_width;
p_spu->i_height = p_sys->i_height;
p_spu->i_start = p_sys->i_pts;
- p_spu->i_stop = p_sys->i_pts + (p_sys->i_duration * 5);
+ p_spu->i_stop = p_sys->i_pts + (p_sys->i_duration);
p_spu->p_sys->b_crop = VLC_FALSE;
p_spu->p_sys->i_debug = p_sys->i_debug;
if( ParseImage( p_dec, p_spu ) )
{
/* There was a parse error, delete the subpicture */
- vout_DestroySubPicture( p_sys->p_vout, p_spu );
+ spu_DestroySubpicture( p_sys->p_vout->p_spu, p_spu );
return;
}
/* SPU is finished - we can ask the video output to display it */
- vout_DisplaySubPicture( p_sys->p_vout, p_spu );
+ spu_DisplaySubpicture( p_sys->p_vout->p_spu, p_spu );
}
uint8_t i_pending = 0; /* number of pixels to fill with
color zero 0..3 */
ogt_color_t i_color=0; /* current pixel color: 0..3 */
- uint8_t *p = p_sys->subtitle_data + p_sys->comp_image_offset;
- uint8_t *maxp = p + p_sys->comp_image_length;
+ uint8_t *p = p_sys->subtitle_data + p_sys->i_image_offset;
+ uint8_t *maxp = p + p_sys->i_image_length;
dbg_print( (DECODE_DBG_CALL) , "width x height: %dx%d",
i_width, i_height);
}
#endif /*HAVE_LIBPNG*/
+ VCDSubHandleScaling( p_spu, p_dec );
- VCDInlinePalette( p_dest, p_sys, i_height, i_width );
-
- /* The video is automatically scaled. However subtitle bitmaps
- assume a 1:1 aspect ratio. So we need to scale to compensate for
- or undo the effects of video output scaling.
- */
- /* FIXME do the right scaling depending on vout. It may not be 4:3 */
- VCDSubScaleX( p_dec, p_spu, 3, 4 );
-
- /* To be finished...*/
return VLC_SUCCESS;
}