* cvd.c : CVD Subtitle decoder thread
*****************************************************************************
* Copyright (C) 2003 VideoLAN
- * $Id: cvd.c,v 1.3 2003/12/29 04:47:44 rocky Exp $
+ * $Id: cvd.c,v 1.4 2003/12/30 04:43:52 rocky Exp $
*
* Authors: Rocky Bernstein
* based on code from:
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,
- "end position: (%d,%d): %.2x %.2x %.2x, w x h: %d x %d",
+ "end position: (%d,%d): %.2x %.2x %.2x, w x h: %dx%d",
lastx, lasty, p[1], p[2], p[3],
p_sys->i_width, p_sys->i_height );
break;
p_sys->pi_palette[3].s.t = p[2] >> 4;
dbg_print( DECODE_DBG_PACKET,
- "transparancy for primary palette (y,u,v): "
- "0x%0x 0x%0x 0x%0x",
- p[1], p[2], p[3]);
+ "transparancy for primary palette 0..3: "
+ "0x%0x 0x%0x 0x%0x 0x%0x",
+ p_sys->pi_palette[0].s.t,
+ p_sys->pi_palette[1].s.t,
+ p_sys->pi_palette[2].s.t,
+ p_sys->pi_palette[3].s.t );
break;
p_sys->pi_palette_highlight[3].s.t = p[1] >> 4;
dbg_print( DECODE_DBG_PACKET,
- "transparancy for highlight palette (y,u,v): "
- "0x%0x 0x%0x 0x%0x",
- p[1], p[2], p[3]);
+ "transparancy for primary palette 0..3: "
+ "0x%0x 0x%0x 0x%0x 0x%0x",
+ p_sys->pi_palette_highlight[0].s.t,
+ p_sys->pi_palette_highlight[1].s.t,
+ p_sys->pi_palette_highlight[2].s.t,
+ p_sys->pi_palette_highlight[3].s.t );
break;
* parse.c: Philips OGT (SVCD subtitle) packet parser
*****************************************************************************
* Copyright (C) 2003 VideoLAN
- * $Id: cvd_parse.c,v 1.3 2003/12/29 04:47:44 rocky Exp $
+ * $Id: cvd_parse.c,v 1.4 2003/12/30 04:43:52 rocky Exp $
*
* Authors: Rocky Bernstein
* based on code from:
static int ParseImage ( decoder_t *, subpicture_t * );
/*
- * We do not have information on the subtitle format used on CVD's
- * except the submux sample code and a couple of samples of dubious
- * origin. Thus, this is the result of reading some code whose
- * correctness is not known and some experimentation.
- *
- * CVD subtitles present several differences compared to SVCD OGT
- * subtitles. Firstly, the image comes first and the metadata is at
- * the end. So that the metadata can be found easily, the subtitle
- * begins with two two-byte (everything is big-endian again) that
- * describe, the total size of the subtitle data and the offset to the
- * metadata (size of the image data plus the four bytes at the
- * beginning.
- *
- * Image data comes interlaced and uses RLE. Coding is based in
- * four-bit nibbles that are further subdivided in a two-bit repeat
- * count and a two-bit color number so that up to three pixels can be
- * describe with a total of four bits. The function of a 0 repeat
- * count is unknown. It might be used for RLE extension. There is a
- * special case, though. When the full nibble is zero, the rest of
- * the line is filled with the color value in the next nibble. It is
- * unknown what happens if the color value is greater than three. The
- * rest seems to use a 4-entries palette. It is not impossible 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.
- */
-
-/* FIXME: do we really need p_buffer and p?
- Can't all of thes _offset's and _lengths's get removed?
+ We do not have information on the subtitle format used on CVD's
+ except the submux sample code and a couple of samples of dubious
+ 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.
+
+ 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
+ two-bit color number so that up to three pixels can be described in
+ four bits. The function of a 0 repeat count is unknown; it might be
+ used for RLE extension. However when the full nibble is zero, the
+ rest of the line is filled with the color value in the next nibble.
+ It is unknown what happens if the color value is greater than three.
+ The rest seems to use a 4-entries palette. It is not impossible
+ 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;
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 * 10);
+ p_spu->i_stop = p_sys->i_pts + (p_sys->i_duration * 5);
p_spu->p_sys->b_crop = VLC_FALSE;
p_spu->p_sys->i_debug = p_sys->i_debug;
#define advance_color_byte_pointer \
p++; \
- i_remaining = 2; \
+ i_nibble_field = 2; \
/* \
* This is wrong, it may exceed maxp if it is the last, check \
* should be moved to use location or the algorithm changed to \
return VLC_EGENERIC; \
}
-/* Get the next field - either a palette index or a RLE count for
- color 0. To do this we use byte image pointer p, and i_remaining
- which indicates where we are in the byte.
+#define CVD_FIELD_BITS (4)
+#define CVD_FIELD_MASK ((1<<CVD_FIELD_BITS) - 1)
+
+/* Get the next field - a 2-bit palette index and a run count. To do
+ this we use byte image pointer p, and i_nibble_field which
+ indicates where we are in the byte.
*/
static inline uint8_t
-ExtractField(uint8_t *p, unsigned int i_remaining)
+ExtractField(uint8_t *p, uint8_t i_nibble_field)
{
- return ( ( *p >> 4*(i_remaining-1) ) & 0xf );
+ return ( ( *p >> (CVD_FIELD_BITS*(i_nibble_field-1)) ) & CVD_FIELD_MASK );
}
/*****************************************************************************
{
decoder_sys_t *p_sys = p_dec->p_sys;
- unsigned int i_field; /* The subtitles are interlaced, are we on an
+ uint8_t i_field; /* The subtitles are interlaced, are we on an
even or odd scanline? */
-
unsigned int i_row; /* scanline row number */
unsigned int i_column; /* scanline column number */
uint8_t *p_dest = (uint8_t *)p_spu->p_sys->p_data;
- uint8_t i_remaining; /* number of 2-bit pixels remaining
- in byte of *p */
+ uint8_t i_nibble_field; /* The 2-bit pixels remaining in byte of *p.
+ Has value 0..2. */
vlc_bool_t b_filling; /* Filling i_color to the of the line. */
uint8_t i_pending = 0; /* number of pixels to fill with
color zero 0..3 */
uint8_t *p = p_sys->subtitle_data + p_sys->comp_image_offset;
uint8_t *maxp = p + p_sys->comp_image_length;
- dbg_print( (DECODE_DBG_CALL) , "width x height: %dx%d ",
+ dbg_print( (DECODE_DBG_CALL) , "width x height: %dx%d",
i_width, i_height);
if (p_sys && p_sys->i_debug & DECODE_DBG_IMAGE)
i_pending = 0;
for ( i_field=0; i_field < 2; i_field++ ) {
- i_remaining = 2; /* 4-bit pieces available in *p */
- b_filling = VLC_FALSE;
+ i_nibble_field = 2; /* 4-bit pieces available in *p */
for ( i_row=i_field; i_row < i_height; i_row += 2 ) {
+ b_filling = VLC_FALSE;
for ( i_column=0; i_column<i_width; i_column++ ) {
if ( i_pending ) {
/* We are in the middle of a RLE expansion, just decrement and
/* We are just filling to the end of line with one color, just
reuse current color value */
} else {
- uint8_t i_val = ExtractField(p, i_remaining--);
- if ( i_remaining == 0 ) {
+ uint8_t i_val = ExtractField(p, i_nibble_field--);
+ if ( i_nibble_field == 0 ) {
advance_color_byte_pointer;
}
if ( i_val == 0 ) {
/* fill the rest of the line with next color */
- i_color = ExtractField( p, i_remaining-- );
- if ( i_remaining == 0 ) {
+ i_color = ExtractField( p, i_nibble_field-- );
+ if ( i_nibble_field == 0 ) {
p++;
- i_remaining=2;
+ i_nibble_field=2;
/*
This is wrong, it may exceed maxp if it is the
last, check should be moved to use location or the
}
- if ( i_remaining != 0 && i_remaining !=2 ) {
+ if ( i_nibble_field == 1 ) {
advance_color_byte_pointer;
}
}
}
+ /* Dump out image not interlaced... */
+ if (p_sys && p_sys->i_debug & DECODE_DBG_IMAGE) {
+ uint8_t *p = p_dest;
+ printf("-------------------------------------\n++");
+ for ( i_row=0; i_row < i_height; i_row ++ ) {
+ for ( i_column=0; i_column<i_width; i_column++ ) {
+ printf("%1d", *p++ & 0x03);
+ }
+ printf("\n++");
+ }
+ printf("\n-------------------------------------\n");
+ }
+
+ 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.
* Philips OGT (SVCD subtitle) packet parser
*****************************************************************************
* Copyright (C) 2003 VideoLAN
- * $Id: ogt_parse.c,v 1.3 2003/12/29 04:47:44 rocky Exp $
+ * $Id: ogt_parse.c,v 1.4 2003/12/30 04:43:52 rocky Exp $
*
* Author: Rocky Bernstein
* based on code from:
}
-/* Advance pointer to image pointer, update internal i_remaining counter
+/* Advance pointer to image pointer, update internal i_2bit_field counter
and check that we haven't goine too far in the image data. */
#define advance_color_pointer_byte \
p++; \
- i_remaining=4; \
+ i_2bit_field=4; \
if (p >= maxp) { \
msg_Warn( p_dec, \
"broken subtitle - tried to access beyond end " \
} \
#define advance_color_pointer \
- i_remaining--; \
- if ( i_remaining == 0 ) { \
+ i_2bit_field--; \
+ if ( i_2bit_field == 0 ) { \
advance_color_pointer_byte; \
}
+#define OGT_FIELD_BITS (2)
+#define OGT_FIELD_MASK ((1<<OGT_FIELD_BITS) - 1)
+
/* Get the next field - either a palette index or a RLE count for
- color 0. To do this we use byte image pointer p, and i_remaining
+ color 0. To do this we use byte image pointer p, and i_2bit_field
which indicates where we are in the byte.
*/
static inline ogt_color_t
-ExtractField(uint8_t *p, unsigned int i_remaining)
+ExtractField(uint8_t *p, unsigned int i_2bit_field)
{
- return ( ( *p >> 2*(i_remaining-1) ) & 0x3 );
+ return ( ( *p >> (OGT_FIELD_BITS*(i_2bit_field-1)) ) & OGT_FIELD_MASK );
}
/*****************************************************************************
uint8_t *p_dest = (uint8_t *)p_spu->p_sys->p_data;
- uint8_t i_remaining; /* number of 2-bit pixels remaining
- in byte of *p */
+ uint8_t i_2bit_field; /* The 2-bit field to sue in byte of *p.
+ Has value 0..4. */
uint8_t i_pending_zero = 0; /* number of pixels to fill with
color zero 0..3 */
ogt_color_t i_color; /* current pixel color: 0..3 */
printf("\n");
for ( i_field=0; i_field < 2; i_field++ ) {
- i_remaining = 4;
+ i_2bit_field = 4;
for ( i_row=i_field; i_row < i_height; i_row += 2 ) {
for ( i_column=0; i_column<i_width; i_column++ ) {
i_pending_zero--;
i_color = 0;
} else {
- i_color = ExtractField( p, i_remaining);
+ i_color = ExtractField( p, i_2bit_field );
advance_color_pointer;
if ( i_color == 0 ) {
- i_pending_zero = ExtractField( p, i_remaining );
+ i_pending_zero = ExtractField( p, i_2bit_field );
advance_color_pointer;
/* Fall through with i_color == 0 to output the first cell */
}
if (p_sys && p_sys->i_debug & DECODE_DBG_IMAGE)
printf("\n");
- if ( i_remaining != 4 ) {
+ if ( i_2bit_field != 4 ) {
/* Lines are padded to complete bytes, ignore padding */
advance_color_pointer_byte;
}
printf("\n-------------------------------------\n");
}
- /* Remove color palette by expanding pixel entries to contain the
- palette values. We work from the free space at the end to the
- beginning so we can expand inline.
- */
- {
- int n = (i_height * i_width) - 1;
- uint8_t *p_from = p_dest;
- ogt_yuvt_t *p_to = (ogt_yuvt_t *) p_dest;
-
- for ( ; n >= 0 ; n-- ) {
- p_to[n] = p_sys->pi_palette[p_from[n]];
- }
- }
+ 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