Commit c17dee7d authored by Rocky Bernstein's avatar Rocky Bernstein

common.*: add common routine to eliminate palette from pixmap.

cvd*: finally shows subtitles (with some bugs)
ogt_parse.c: use common just added above.
parent 3bb0ad8d
......@@ -2,7 +2,7 @@
* Common SVCD and VCD subtitle routines.
*****************************************************************************
* Copyright (C) 2003 VideoLAN
* $Id: common.c,v 1.1 2003/12/28 04:51:52 rocky Exp $
* $Id: common.c,v 1.2 2003/12/30 04:43:52 rocky Exp $
*
* Author: Rocky Bernstein
* based on code from:
......@@ -161,6 +161,25 @@ vout_thread_t *VCDSubFindVout( decoder_t *p_dec )
}
/* 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.
*/
void
VCDInlinePalette ( /*inout*/ uint8_t *p_dest, decoder_sys_t *p_sys,
unsigned int i_height, unsigned int i_width )
{
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]];
}
}
/* Scales down (reduces size) of p_dest in the x direction as
determined through aspect ratio x_scale by y_scale. Scaling
is done in place. p_spu->i_width, is updated to new width
......
......@@ -2,7 +2,7 @@
* Header for Common SVCD and VCD subtitle routines.
*****************************************************************************
* Copyright (C) 2003 VideoLAN
* $Id: common.h,v 1.1 2003/12/28 04:51:52 rocky Exp $
* $Id: common.h,v 1.2 2003/12/30 04:43:52 rocky Exp $
*
* Author: Rocky Bernstein
*
......@@ -35,5 +35,9 @@ int VCDSubCropCallback( vlc_object_t *p_object, char const *psz_var,
vlc_value_t oldval, vlc_value_t newval,
void *p_data );
void VCDSubUpdateSPU( subpicture_t *p_spu, vlc_object_t *p_object );
void VCDInlinePalette ( /*inout*/ uint8_t *p_dest,
decoder_sys_t *p_sys, unsigned int i_height,
unsigned int i_width );
......@@ -2,7 +2,7 @@
* 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:
......@@ -305,7 +305,7 @@ Reassemble( decoder_t *p_dec, block_t **pp_block )
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;
......@@ -357,9 +357,12 @@ Reassemble( decoder_t *p_dec, block_t **pp_block )
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;
......@@ -371,9 +374,12 @@ Reassemble( decoder_t *p_dec, block_t **pp_block )
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;
......
......@@ -2,7 +2,7 @@
* 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:
......@@ -46,41 +46,36 @@ typedef uint8_t ogt_color_t;
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;
......@@ -156,7 +151,7 @@ E_(ParsePacket)( decoder_t *p_dec)
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;
......@@ -183,7 +178,7 @@ E_(ParsePacket)( decoder_t *p_dec)
#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 \
......@@ -197,14 +192,17 @@ E_(ParsePacket)( decoder_t *p_dec)
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 );
}
/*****************************************************************************
......@@ -236,9 +234,8 @@ ParseImage( decoder_t *p_dec, subpicture_t * p_spu )
{
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 */
......@@ -247,8 +244,8 @@ ParseImage( decoder_t *p_dec, subpicture_t * p_spu )
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 */
......@@ -256,7 +253,7 @@ ParseImage( decoder_t *p_dec, subpicture_t * p_spu )
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)
......@@ -265,10 +262,10 @@ ParseImage( decoder_t *p_dec, subpicture_t * p_spu )
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
......@@ -278,16 +275,16 @@ ParseImage( decoder_t *p_dec, subpicture_t * p_spu )
/* 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
......@@ -320,7 +317,7 @@ ParseImage( decoder_t *p_dec, subpicture_t * p_spu )
}
if ( i_remaining != 0 && i_remaining !=2 ) {
if ( i_nibble_field == 1 ) {
advance_color_byte_pointer;
}
......@@ -329,6 +326,21 @@ ParseImage( decoder_t *p_dec, subpicture_t * p_spu )
}
}
/* 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.
......
......@@ -2,7 +2,7 @@
* 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:
......@@ -214,11 +214,11 @@ E_(ParsePacket)( decoder_t *p_dec)
}
/* 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 " \
......@@ -227,19 +227,22 @@ E_(ParsePacket)( decoder_t *p_dec)
} \
#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 );
}
/*****************************************************************************
......@@ -280,8 +283,8 @@ ParseImage( decoder_t *p_dec, subpicture_t * p_spu )
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 */
......@@ -295,7 +298,7 @@ ParseImage( decoder_t *p_dec, subpicture_t * p_spu )
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++ ) {
......@@ -305,10 +308,10 @@ ParseImage( decoder_t *p_dec, subpicture_t * p_spu )
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 */
}
......@@ -325,7 +328,7 @@ ParseImage( decoder_t *p_dec, subpicture_t * p_spu )
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;
}
......@@ -347,19 +350,7 @@ ParseImage( decoder_t *p_dec, subpicture_t * p_spu )
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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment