Commit 3bb0ad8d authored by Rocky Bernstein's avatar Rocky Bernstein

cvd: bitmap extraction further completed - not fully done.

ogt_parse.c, render.c: go back to 4-bit alpha since that's what DVD
and CVD have.
parent 3cbdd393
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* cvd.c : CVD Subtitle decoder thread * cvd.c : CVD Subtitle decoder thread
***************************************************************************** *****************************************************************************
* Copyright (C) 2003 VideoLAN * Copyright (C) 2003 VideoLAN
* $Id: cvd.c,v 1.2 2003/12/28 11:26:52 rocky Exp $ * $Id: cvd.c,v 1.3 2003/12/29 04:47:44 rocky Exp $
* *
* Authors: Rocky Bernstein * Authors: Rocky Bernstein
* based on code from: * based on code from:
...@@ -231,6 +231,9 @@ Reassemble( decoder_t *p_dec, block_t **pp_block ) ...@@ -231,6 +231,9 @@ Reassemble( decoder_t *p_dec, block_t **pp_block )
p_buffer[5], p_buffer[6], p_buffer[5], p_buffer[6],
p_block->i_buffer); p_block->i_buffer);
if( config_GetInt( p_dec, "spu-channel" ) != p_buffer[0] )
return NULL;
/* There is little data on the format, but it does not seem to have a /* There is little data on the format, but it does not seem to have a
good way to detect the first packet in the subtitle. It seems, good way to detect the first packet in the subtitle. It seems,
however, that it has a valid pts while later packets for the same however, that it has a valid pts while later packets for the same
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* parse.c: Philips OGT (SVCD subtitle) packet parser * parse.c: Philips OGT (SVCD subtitle) packet parser
***************************************************************************** *****************************************************************************
* Copyright (C) 2003 VideoLAN * Copyright (C) 2003 VideoLAN
* $Id: cvd_parse.c,v 1.2 2003/12/28 11:26:52 rocky Exp $ * $Id: cvd_parse.c,v 1.3 2003/12/29 04:47:44 rocky Exp $
* *
* Authors: Rocky Bernstein * Authors: Rocky Bernstein
* based on code from: * based on code from:
...@@ -181,32 +181,30 @@ E_(ParsePacket)( decoder_t *p_dec) ...@@ -181,32 +181,30 @@ E_(ParsePacket)( decoder_t *p_dec)
} }
/* Advance pointer to image pointer, update internal i_remaining counter #define advance_color_byte_pointer \
and check that we haven't goine too far in the image data. */
#define advance_color_pointer_byte \
p++; \ p++; \
i_remaining=4; \ i_remaining = 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 \
* that in vob2sub \
*/ \
if (p >= maxp) { \ if (p >= maxp) { \
msg_Warn( p_dec, \ msg_Warn( p_dec, \
"broken subtitle - tried to access beyond end " \ "broken subtitle - overflow while decoding " \
"in image extraction"); \ " padding (%d,%d,%d)\n", \
i_field, i_row, i_column ); \
return VLC_EGENERIC; \ return VLC_EGENERIC; \
} \
#define advance_color_pointer \
i_remaining--; \
if ( i_remaining == 0 ) { \
advance_color_pointer_byte; \
} }
/* Get the next field - either a palette index or a RLE count for /* 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_remaining
which indicates where we are in the byte. which indicates where we are in the byte.
*/ */
static inline ogt_color_t static inline uint8_t
ExtractField(uint8_t *p, unsigned int i_remaining) ExtractField(uint8_t *p, unsigned int i_remaining)
{ {
return ( ( *p >> 2*(i_remaining-1) ) & 0x3 ); return ( ( *p >> 4*(i_remaining-1) ) & 0xf );
} }
/***************************************************************************** /*****************************************************************************
...@@ -215,20 +213,22 @@ ExtractField(uint8_t *p, unsigned int i_remaining) ...@@ -215,20 +213,22 @@ ExtractField(uint8_t *p, unsigned int i_remaining)
This part parses the subtitle graphical data and stores it in a more This part parses the subtitle graphical data and stores it in a more
convenient structure for later rendering. convenient structure for later rendering.
The image is encoded using two bits per pixel that select a palette Image data comes interlaced and is run-length encoded (RLE). Each
entry except that value 0 starts a limited run-length encoding for field is a four-bit nibbles that is further subdivided in a two-bit
color 0. When 0 is seen, the next two bits encode one less than the repeat count and a two-bit color number - up to three pixels can be
number of pixels, so we can encode run lengths from 1 to 4. These get described in four bits. What a 0 repeat count means is unknown. It
filled with the color in palette entry 0. might be used for RLE extension. There is a special case of a 0
repeat count though. When the full nibble is zero, the rest of the
The encoding of each line is padded to a whole number of bytes. The line is filled with the color value in the next nibble. It is
first field is padded to an even byte length and the complete subtitle unknown what happens if the color value is greater than three. The
is padded to a 4-byte multiple that always include one zero byte at rest seems to use a 4-entries palette. It is not impossible that the
the end. 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.
However we'll transform this so that that the RLE is expanded and However we'll transform this so that that the RLE is expanded and
interlacing will also be removed. On output each pixel entry will by interlacing will also be removed. On output each pixel entry will by
an 8-bit alpha, y, u, and v entry. a 4-bit alpha (filling 8 bits), and 8-bit y, u, and v entry.
*****************************************************************************/ *****************************************************************************/
static int static int
...@@ -236,9 +236,108 @@ ParseImage( decoder_t *p_dec, subpicture_t * p_spu ) ...@@ -236,9 +236,108 @@ ParseImage( decoder_t *p_dec, subpicture_t * p_spu )
{ {
decoder_sys_t *p_sys = p_dec->p_sys; decoder_sys_t *p_sys = p_dec->p_sys;
dbg_print( (DECODE_DBG_CALL) , ""); unsigned int 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 */
unsigned int i_width = p_sys->i_width;
unsigned int i_height = p_sys->i_height;
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 */
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 */
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;
dbg_print( (DECODE_DBG_CALL) , "width x height: %dx%d ",
i_width, i_height);
if (p_sys && p_sys->i_debug & DECODE_DBG_IMAGE)
printf("\n");
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;
for ( i_row=i_field; i_row < i_height; i_row += 2 ) {
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
fall through with current color value */
i_pending--;
} else if ( b_filling ) {
/* 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 ) {
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 ) {
p++;
i_remaining=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 that in vob2sub
*/
if (p >= maxp) {
msg_Warn( p_dec,
"broken subtitle - overflow while decoding "
" filling (%d,%d,%d)",
i_field, i_row, i_column);
/* return VLC_EGENERIC; */
}
}
b_filling = VLC_TRUE;
} else {
/* Normal case: get color and repeat count,
this iteration will output the first (or only)
instance */
i_pending = (i_val >> 2);
i_color = i_val & 0x3;
/* This time counts against the total */
i_pending--;
}
}
/* Color is 0-3. */
p_dest[i_row*i_width+i_column] = i_color;
if (p_sys && p_sys->i_debug & DECODE_DBG_IMAGE)
printf("%1d", i_color);
}
if ( i_remaining != 0 && i_remaining !=2 ) {
advance_color_byte_pointer;
}
if (p_sys && p_sys->i_debug & DECODE_DBG_IMAGE)
printf("\n");
}
}
/* 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...*/ /* To be finished...*/
return VLC_EGENERIC; return VLC_SUCCESS;
} }
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* Philips OGT (SVCD subtitle) packet parser * Philips OGT (SVCD subtitle) packet parser
***************************************************************************** *****************************************************************************
* Copyright (C) 2003 VideoLAN * Copyright (C) 2003 VideoLAN
* $Id: ogt_parse.c,v 1.2 2003/12/28 11:26:52 rocky Exp $ * $Id: ogt_parse.c,v 1.3 2003/12/29 04:47:44 rocky Exp $
* *
* Author: Rocky Bernstein * Author: Rocky Bernstein
* based on code from: * based on code from:
...@@ -107,10 +107,11 @@ void E_(ParseHeader)( decoder_t *p_dec, uint8_t *p_buffer, block_t *p_block ) ...@@ -107,10 +107,11 @@ void E_(ParseHeader)( decoder_t *p_dec, uint8_t *p_buffer, block_t *p_block )
p_sys->pi_palette[i].s.y = *p++; p_sys->pi_palette[i].s.y = *p++;
p_sys->pi_palette[i].s.u = *p++; p_sys->pi_palette[i].s.u = *p++;
p_sys->pi_palette[i].s.v = *p++; p_sys->pi_palette[i].s.v = *p++;
/* Note alpha is 8 bits. DVD's use only 4 bits. Our rendering routine /* OGT has 8-bit resolution for alpha, but DVD's and CVDS use 4-bits.
will use an 8-bit transparancy. Since we want to use the same render routine, rather than scale up
CVD (and DVD) subtitles, we'll scale down ours.
*/ */
p_sys->pi_palette[i].s.t = *p++; p_sys->pi_palette[i].s.t = (*p++) >> 4;
} }
p_sys->i_cmd = *p++; p_sys->i_cmd = *p++;
/* We do not really know this, FIXME */ /* We do not really know this, FIXME */
...@@ -259,8 +260,8 @@ ExtractField(uint8_t *p, unsigned int i_remaining) ...@@ -259,8 +260,8 @@ ExtractField(uint8_t *p, unsigned int i_remaining)
the end. the end.
However we'll transform this so that that the RLE is expanded and However we'll transform this so that that the RLE is expanded and
interlacing will also be removed. On output each pixel entry will by interlacing will also be removed. On output each pixel entry will by
an 8-bit alpha, y, u, and v entry. an 4-bit alpha (filling 8 bits), and 8-bit y, u, and v entry.
*****************************************************************************/ *****************************************************************************/
static int static int
...@@ -282,7 +283,7 @@ ParseImage( decoder_t *p_dec, subpicture_t * p_spu ) ...@@ -282,7 +283,7 @@ ParseImage( decoder_t *p_dec, subpicture_t * p_spu )
uint8_t i_remaining; /* number of 2-bit pixels remaining uint8_t i_remaining; /* number of 2-bit pixels remaining
in byte of *p */ in byte of *p */
uint8_t i_pending_zero = 0; /* number of pixels to fill with uint8_t i_pending_zero = 0; /* number of pixels to fill with
color zero 0..4 */ color zero 0..3 */
ogt_color_t i_color; /* current pixel color: 0..3 */ ogt_color_t i_color; /* current pixel color: 0..3 */
uint8_t *p = p_sys->subtitle_data + p_sys->comp_image_offset; uint8_t *p = p_sys->subtitle_data + p_sys->comp_image_offset;
uint8_t *maxp = p + p_sys->comp_image_length; uint8_t *maxp = p + p_sys->comp_image_length;
...@@ -299,6 +300,8 @@ ParseImage( decoder_t *p_dec, subpicture_t * p_spu ) ...@@ -299,6 +300,8 @@ ParseImage( decoder_t *p_dec, subpicture_t * p_spu )
for ( i_column=0; i_column<i_width; i_column++ ) { for ( i_column=0; i_column<i_width; i_column++ ) {
if ( i_pending_zero ) { if ( i_pending_zero ) {
/* We are in the middle of a RLE expansion, just decrement and
fall through with current color value */
i_pending_zero--; i_pending_zero--;
i_color = 0; i_color = 0;
} else { } else {
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* render.c : Philips OGT (SVCD Subtitle) renderer * render.c : Philips OGT (SVCD Subtitle) renderer
***************************************************************************** *****************************************************************************
* Copyright (C) 2003 VideoLAN * Copyright (C) 2003 VideoLAN
* $Id: render.c,v 1.4 2003/12/28 04:51:52 rocky Exp $ * $Id: render.c,v 1.5 2003/12/29 04:47:44 rocky Exp $
* *
* Author: Rocky Bernstein * Author: Rocky Bernstein
* based on code from: * based on code from:
...@@ -35,8 +35,11 @@ ...@@ -35,8 +35,11 @@
#include "subtitle.h" #include "subtitle.h"
#include "render.h" #include "render.h"
/* We use 8 bits for an alpha value: 0..255. Note: For DVDs; 0.15. */ /* We use 4 bits for an alpha value: 0..15, 15 is completely transparent and
#define ALPHA_BITS (8) 0 completely opaque. Note that SVCD allow 8-bits, it should be
scaled down to use these routines.
*/
#define ALPHA_BITS (4)
#define MAX_ALPHA ((1<<ALPHA_BITS) - 1) #define MAX_ALPHA ((1<<ALPHA_BITS) - 1)
/* Horrible hack to get dbg_print to do the right thing */ /* Horrible hack to get dbg_print to do the right thing */
......
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