Commit 58123466 authored by Rocky Bernstein's avatar Rocky Bernstein

Fix bug in ScaleX routine which affected ratios that could span 3 pixels.

(4:3 is one of the few *not* in this category).

Allow user to override subtitle scaling via sub-aspect-ratio, 0=auto
or what we do now. 1=do nothing.
parent 7ef5157c
......@@ -2,7 +2,7 @@
* Common SVCD and VCD subtitle routines.
*****************************************************************************
* Copyright (C) 2003, 2004 VideoLAN
* $Id: common.c,v 1.4 2004/01/10 13:59:25 rocky Exp $
* $Id: common.c,v 1.5 2004/01/11 01:54:20 rocky Exp $
*
* Author: Rocky Bernstein
* based on code from:
......@@ -173,10 +173,11 @@ vout_thread_t *VCDSubFindVout( decoder_t *p_dec )
/* Remove color palette by expanding pixel entries to contain the
/**
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 )
......@@ -190,12 +191,50 @@ VCDInlinePalette ( /*inout*/ uint8_t *p_dest, decoder_sys_t *p_sys,
}
}
/**
Check to see if user has overridden subtitle aspect ratio.
0 is returned for no override which means just counteract any
scaling effects.
*/
unsigned int
VCDSubGetAROverride(vlc_object_t * p_input, vout_thread_t *p_vout)
{
char *psz_string = config_GetPsz( p_input, "sub-aspect-ratio" );
/* Check whether the user tried to override aspect ratio */
if( !psz_string ) return 0;
{
unsigned int i_new_aspect = 0;
char *psz_parser = strchr( psz_string, ':' );
if( psz_parser )
{
*psz_parser++ = '\0';
i_new_aspect = atoi( psz_string ) * VOUT_ASPECT_FACTOR
/ atoi( psz_parser );
}
else
{
i_new_aspect = p_vout->output.i_width * VOUT_ASPECT_FACTOR
* atof( psz_string )
/ p_vout->output.i_height;
}
return i_new_aspect;
}
}
/* Scales down (reduces size) of p_dest in the x direction as
/**
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
The aspect ratio is assumed to be between 1/2 and 1.
Note: the scaling truncates the new width rather than rounds it.
Perhaps something one might want to address.
*/
void
VCDSubScaleX( decoder_t *p_dec, subpicture_t *p_spu,
......@@ -208,38 +247,65 @@ VCDSubScaleX( decoder_t *p_dec, subpicture_t *p_spu,
uint8_t *p_src2 = p_src1 + PIXEL_SIZE;
uint8_t *p_dst = p_src1;
unsigned int i_new_width = (p_spu->i_width * i_scale_x) / i_scale_y ;
unsigned int used=0; /* Number of bytes used up in p_src1. */
unsigned int i_used=0; /* Number of bytes used up in p_src1. */
dbg_print( (DECODE_DBG_CALL|DECODE_DBG_TRANSFORM) ,
"aspect ratio %i:%i, Old width: %d, new width: %d",
i_scale_x, i_scale_y, p_spu->i_width, i_new_width);
if (! (i_scale_x < i_scale_y && i_scale_y < i_scale_x+i_scale_x) )
{
msg_Warn( p_dec, "Need x < y < 2x. x: %i, y: %i", i_scale_x, i_scale_y );
return;
}
for ( i_row=0; i_row <= p_spu->i_height - 1; i_row++ ) {
if (used != 0) {
if (i_used != 0) {
/* Discard the remaining piece of the column of the previous line*/
used=0;
i_used=0;
p_src1 = p_src2;
p_src2 += PIXEL_SIZE;
}
for ( i_col=0; i_col <= p_spu->i_width - 2; i_col++ ) {
unsigned int i;
unsigned int w1= i_scale_x - used;
unsigned int w2= i_scale_y - w1;
used = w2;
for (i = 0; i < PIXEL_SIZE; i++ ) {
*p_dst = ( (*p_src1 * w1) + (*p_src2 * w2) ) / i_scale_y;
p_src1++; p_src2++; p_dst++;
unsigned int w1= i_scale_x - i_used;
unsigned int w2;
if ( i_scale_y - w1 <= i_scale_x ) {
/* Average spans 2 pixels. */
w2 = i_scale_y - w1;
for (i = 0; i < PIXEL_SIZE; i++ ) {
*p_dst = ( (*p_src1 * w1) + (*p_src2 * w2) ) / i_scale_y;
p_src1++; p_src2++; p_dst++;
}
} else {
/* Average spans 3 pixels. */
unsigned int w0 = w1;
unsigned int w1 = i_scale_x;
uint8_t *p_src0 = p_src1;
w2 = i_scale_y - w0 - w1;
p_src1 = p_src2;
p_src2 += PIXEL_SIZE;
for (i = 0; i < PIXEL_SIZE; i++ ) {
*p_dst = ( (*p_src0 * w0) + (*p_src1 * w1) + (*p_src2 * w2) )
/ i_scale_y;
p_src0++; p_src1++; p_src2++; p_dst++;
}
i_col++;
}
if (i_scale_x == used) {
i_used = w2;
if (i_scale_x == i_used) {
/* End of last pixel was end of p_src2. */
p_src1 = p_src2;
p_src2 += PIXEL_SIZE;
i_col++;
used = 0;
i_used = 0;
}
}
}
......@@ -248,8 +314,8 @@ VCDSubScaleX( decoder_t *p_dec, subpicture_t *p_spu,
if ( p_sys && p_sys->i_debug & DECODE_DBG_TRANSFORM )
{
ogt_yuvt_t *p_source = (ogt_yuvt_t *) p_spu->p_sys->p_data;
for ( i_row=0; i_row < p_spu->i_height - 1; i_row++ ) {
for ( i_col=0; i_col < p_spu->i_width - 1; i_col++ ) {
for ( i_row=0; i_row < p_spu->i_height; i_row++ ) {
for ( i_col=0; i_col < p_spu->i_width; i_col++ ) {
printf("%1x", p_source->s.t);
p_source++;
}
......@@ -259,9 +325,9 @@ VCDSubScaleX( decoder_t *p_dec, subpicture_t *p_spu,
}
/*****************************************************************************
/**
* DestroySPU: subpicture destructor
*****************************************************************************/
*/
void VCDSubDestroySPU( subpicture_t *p_spu )
{
if( p_spu->p_sys->p_input )
......@@ -302,14 +368,14 @@ void VCDSubUpdateSPU( subpicture_t *p_spu, vlc_object_t *p_object )
return;
}
var_Get( p_object, "x-start", &val );
p_spu->p_sys->i_x_start = val.i_int;
var_Get( p_object, "y-start", &val );
p_spu->p_sys->i_y_start = val.i_int;
var_Get( p_object, "x-end", &val );
p_spu->p_sys->i_x_end = val.i_int;
var_Get( p_object, "y-end", &val );
p_spu->p_sys->i_y_end = val.i_int;
if ( VLC_SUCCESS == var_Get( p_object, "x-start", &val ) )
p_spu->p_sys->i_x_start = val.i_int;
if ( VLC_SUCCESS == var_Get( p_object, "y-start", &val ) )
p_spu->p_sys->i_y_start = val.i_int;
if ( VLC_SUCCESS == var_Get( p_object, "x-end", &val ) )
p_spu->p_sys->i_x_end = val.i_int;
if ( VLC_SUCCESS == var_Get( p_object, "y-end", &val ) )
p_spu->p_sys->i_y_end = val.i_int;
}
......@@ -441,3 +507,12 @@ VCDSubDumpPNG( uint8_t *p_image, decoder_t *p_dec,
free(image_data);
}
#endif /*HAVE_LIBPNG*/
/*
* Local variables:
* c-file-style: "gnu"
* tab-width: 8
* indent-tabs-mode: nil
* End:
*/
......@@ -2,7 +2,7 @@
* Header for Common SVCD and VCD subtitle routines.
*****************************************************************************
* Copyright (C) 2003, 2004 VideoLAN
* $Id: common.h,v 1.3 2004/01/03 12:54:56 rocky Exp $
* $Id: common.h,v 1.4 2004/01/11 01:54:20 rocky Exp $
*
* Author: Rocky Bernstein
*
......@@ -49,6 +49,9 @@ void VCDInlinePalette ( /*inout*/ uint8_t *p_dest,
void VCDSubDumpImage( uint8_t *p_image, uint32_t i_height,
uint32_t i_width );
unsigned int VCDSubGetAROverride(vlc_object_t * p_input,
vout_thread_t *p_vout);
#ifdef HAVE_LIBPNG
#include <png.h>
void VCDSubDumpPNG( uint8_t *p_image, decoder_t *p_dec,
......
......@@ -2,7 +2,7 @@
* cvd.c : CVD Subtitle decoder thread
*****************************************************************************
* Copyright (C) 2003 VideoLAN
* $Id: cvd.c,v 1.8 2004/01/04 16:51:59 rocky Exp $
* $Id: cvd.c,v 1.9 2004/01/11 01:54:20 rocky Exp $
*
* Authors: Rocky Bernstein
* based on code from:
......@@ -51,6 +51,10 @@ vlc_module_begin();
N_("set debug mask for additional debugging."),
N_(DEBUG_LONGTEXT), VLC_TRUE );
add_string( "sub-aspect-ratio", "", NULL,
SUB_ASPECT_RATIO_TEXT, SUB_ASPECT_RATIO_LONGTEXT,
VLC_TRUE );
add_submodule();
set_description( _("Chaoji VCD subtitle packetizer") );
set_capability( "packetizer", 50 );
......
......@@ -2,7 +2,7 @@
* parse.c: Philips OGT (SVCD subtitle) packet parser
*****************************************************************************
* Copyright (C) 2003, 2004 VideoLAN
* $Id: cvd_parse.c,v 1.9 2004/01/10 13:59:25 rocky Exp $
* $Id: cvd_parse.c,v 1.10 2004/01/11 01:54:20 rocky Exp $
*
* Authors: Rocky Bernstein
* based on code from:
......@@ -95,11 +95,11 @@ void E_(ParseHeader)( decoder_t *p_dec, uint8_t *p_buffer, block_t *p_block )
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);
}
......@@ -241,18 +241,18 @@ void E_(ParseMetaInfo)( decoder_t *p_dec )
case 0x47:
/* offset to start of even rows of interlaced image, we correct
to make it relative to comp_image_offset (usually 4) */
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 start of odd rows of interlaced image, we correct
to make it relative to comp_image_offset (usually 4) */
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;
......@@ -413,8 +413,8 @@ ParseImage( decoder_t *p_dec, subpicture_t * 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);
......@@ -524,9 +524,10 @@ ParseImage( decoder_t *p_dec, subpicture_t * p_spu )
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.
/* The video may be scaled. However subtitle bitmaps assume an 1:1
aspect ratio. So unless the user has specified otherwise, we
need to scale to compensate for or undo the effects of video
output scaling.
Perhaps this should go in the Render routine? The advantage would
be that it will deal with a dynamically changing aspect ratio.
......@@ -534,17 +535,35 @@ ParseImage( decoder_t *p_dec, subpicture_t * p_spu )
*/
{
vout_thread_t *p_vout = vlc_object_find( p_spu->p_sys->p_input,
VLC_OBJECT_VOUT,
vlc_object_t * p_input = p_spu->p_sys->p_input;
vout_thread_t *p_vout = vlc_object_find( p_input, VLC_OBJECT_VOUT,
FIND_CHILD );
unsigned int i_aspect_x, i_aspect_y;
if (p_vout) {
vout_AspectRatio( p_vout->render.i_aspect, &i_aspect_x, &i_aspect_y );
VCDSubScaleX( p_dec, p_spu, i_aspect_y, i_aspect_x );
/* Check for user-configuration override. */
unsigned int i_new_aspect = VCDSubGetAROverride( p_input, p_vout );
if (i_new_aspect == VOUT_ASPECT_FACTOR) {
/* For scaling 1:1, nothing needs to be done. Note this means
subtitles will get scaled the same way the video does.
*/
;
} else {
if (0 == i_new_aspect) {
/* Counteract the effects of background video
scaling. That's why x and y are reversed from the
else branch in the call below.
*/
vout_AspectRatio( p_vout->render.i_aspect, &i_aspect_y,
&i_aspect_x );
} else {
/* User knows best? */
vout_AspectRatio( i_new_aspect, &i_aspect_y, &i_aspect_x );
}
VCDSubScaleX( p_dec, p_spu, i_aspect_x, i_aspect_y );
}
}
}
/* To be finished...*/
return VLC_SUCCESS;
}
......
......@@ -2,7 +2,7 @@
* ogt.c : Overlay Graphics Text (SVCD subtitles) decoder thread
*****************************************************************************
* Copyright (C) 2003, 2004 VideoLAN
* $Id: ogt.c,v 1.8 2004/01/03 12:54:56 rocky Exp $
* $Id: ogt.c,v 1.9 2004/01/11 01:54:20 rocky Exp $
*
* Author: Rocky Bernstein
* based on code from:
......@@ -51,6 +51,10 @@ vlc_module_begin();
N_("set debug mask for additional debugging."),
N_(DEBUG_LONGTEXT), VLC_TRUE );
add_string( "sub-aspect-ratio", "", NULL,
SUB_ASPECT_RATIO_TEXT, SUB_ASPECT_RATIO_LONGTEXT,
VLC_TRUE );
add_submodule();
set_description( _("Philips OGT (SVCD subtitle) packetizer") );
set_capability( "packetizer", 50 );
......@@ -294,3 +298,12 @@ Reassemble( decoder_t *p_dec, block_t **pp_block )
}
return NULL;
}
/*
* Local variables:
* c-file-style: "gnu"
* tab-width: 8
* indent-tabs-mode: nil
* End:
*/
......@@ -2,7 +2,7 @@
* Philips OGT (SVCD subtitle) packet parser
*****************************************************************************
* Copyright (C) 2003, 2004 VideoLAN
* $Id: ogt_parse.c,v 1.7 2004/01/10 13:59:25 rocky Exp $
* $Id: ogt_parse.c,v 1.8 2004/01/11 01:54:20 rocky Exp $
*
* Author: Rocky Bernstein
* based on code from:
......@@ -126,9 +126,9 @@ void E_(ParseHeader)( decoder_t *p_dec, uint8_t *p_buffer, block_t *p_block )
/* Actually, this is measured against a different origin, so we have to
adjust it */
p_sys->second_field_offset = GETINT16(p);
p_sys->comp_image_offset = p - p_buffer;
p_sys->comp_image_length = p_sys->i_spu_size - p_sys->comp_image_offset;
p_sys->metadata_length = p_sys->comp_image_offset;
p_sys->i_image_offset = p - p_buffer;
p_sys->i_image_length = p_sys->i_spu_size - p_sys->i_image_offset;
p_sys->metadata_length = p_sys->i_image_offset;
if (p_sys && p_sys->i_debug & DECODE_DBG_PACKET) {
msg_Dbg( p_dec, "x-start: %d, y-start: %d, width: %d, height %d, "
......@@ -136,7 +136,7 @@ void E_(ParseHeader)( decoder_t *p_dec, uint8_t *p_buffer, block_t *p_block )
p_sys->i_x_start, p_sys->i_y_start,
p_sys->i_width, p_sys->i_height,
p_sys->i_spu_size, p_sys->i_duration,
p_sys->comp_image_length, p_sys->comp_image_offset);
p_sys->i_image_length, p_sys->i_image_offset);
for (i=0; i<4; i++) {
msg_Dbg( p_dec, "palette[%d]= T: %2x, Y: %2x, u: %2x, v: %2x", i,
......@@ -292,8 +292,8 @@ ParseImage( decoder_t *p_dec, subpicture_t * p_spu )
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 */
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);
......@@ -337,7 +337,7 @@ ParseImage( decoder_t *p_dec, subpicture_t * p_spu )
advance_color_pointer_byte;
}
}
p = p_sys->subtitle_data + p_sys->comp_image_offset
p = p_sys->subtitle_data + p_sys->i_image_offset
+ p_sys->second_field_offset;
}
......@@ -368,10 +368,10 @@ ParseImage( decoder_t *p_dec, subpicture_t * p_spu )
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.
/* The video may be scaled. However subtitle bitmaps assume an 1:1
aspect ratio. So unless the user has specified otherwise, we
need to scale to compensate for or undo the effects of video
output scaling.
Perhaps this should go in the Render routine? The advantage would
be that it will deal with a dynamically changing aspect ratio.
......@@ -379,17 +379,43 @@ ParseImage( decoder_t *p_dec, subpicture_t * p_spu )
*/
{
vout_thread_t *p_vout = vlc_object_find( p_spu->p_sys->p_input,
VLC_OBJECT_VOUT,
vlc_object_t * p_input = p_spu->p_sys->p_input;
vout_thread_t *p_vout = vlc_object_find( p_input, VLC_OBJECT_VOUT,
FIND_CHILD );
unsigned int i_aspect_x, i_aspect_y;
if (p_vout) {
vout_AspectRatio( p_vout->render.i_aspect, &i_aspect_x, &i_aspect_y );
VCDSubScaleX( p_dec, p_spu, 3, 4 );
/* Check for user-configuration override. */
unsigned int i_new_aspect = VCDSubGetAROverride( p_input, p_vout );
if (i_new_aspect == VOUT_ASPECT_FACTOR) {
/* For scaling 1:1, nothing needs to be done. Note this means
subtitles will get scaled the same way the video does.
*/
;
} else {
if (0 == i_new_aspect) {
/* Counteract the effects of background video
scaling. That's why x and y are reversed from the
else branch in the call below.
*/
vout_AspectRatio( p_vout->render.i_aspect, &i_aspect_y,
&i_aspect_x );
} else {
/* User knows best? */
vout_AspectRatio( i_new_aspect, &i_aspect_x, &i_aspect_y );
}
VCDSubScaleX( p_dec, p_spu, i_aspect_x, i_aspect_y );
}
}
}
return VLC_SUCCESS;
}
/*
* Local variables:
* c-file-style: "gnu"
* tab-width: 8
* indent-tabs-mode: nil
* End:
*/
......@@ -2,7 +2,7 @@
* subtitle.h : Common SVCD and CVD subtitles header
*****************************************************************************
* Copyright (C) 2003,2004 VideoLAN
* $Id: subtitle.h,v 1.5 2004/01/04 22:22:10 gbazin Exp $
* $Id: subtitle.h,v 1.6 2004/01/11 01:54:20 rocky Exp $
*
* Author: Rocky Bernstein
* based on code from:
......@@ -44,6 +44,21 @@
"extract subtitles 64\n" \
"misc info 128\n" )
#define SUB_ASPECT_RATIO_TEXT N_("Subtitle aspect-ratio correction")
#define SUB_ASPECT_RATIO_LONGTEXT N_( \
"Use this to force the subtitle aspect ratio. If you give a null string " \
"the right value will be determined automatically. Usually this is what " \
"you want. For OGT and CVD subtitles this undoes the effect " \
"of the underlying video scaling. And using a value of 1 will cause " \
"no correction; subtitles will be scaled with the same aspect " \
"ratio as as the underlying video (which not correct for OGT or " \
"CVD subtitles). You can also force another ratio by giving a pair of " \
"integers x:y where y should between x and twice x. For example 4:3, or " \
"16:9. Alternatively, you can give a float value expressing pixel " \
"squareness. For example 1.25 or 1.3333 which mean the same thing as " \
"4:3 and 16:9 respectively." \
)
#define DECODE_DEBUG 1
#if DECODE_DEBUG
#define dbg_print(mask, s, args...) \
......@@ -117,9 +132,9 @@ struct decoder_sys_t
int subtitle_data_size; /* size of the allocated subtitle_data */
/* Move into subpicture_sys_t? */
uint16_t comp_image_offset; /* offset from subtitle_data to compressed
uint16_t i_image_offset; /* offset from subtitle_data to compressed
image data */
int comp_image_length; /* size of the compressed image data */
int i_image_length; /* size of the compressed image data */
int first_field_offset; /* offset of even raster lines. Used
only for CVD.
*/
......
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