(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.
* 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:
-/* 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 )
}
}
+/**
+ 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,
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;
}
}
}
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++;
}
}
-/*****************************************************************************
+/**
* DestroySPU: subpicture destructor
- *****************************************************************************/
+ */
void VCDSubDestroySPU( subpicture_t *p_spu )
{
if( p_spu->p_sys->p_input )
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;
}
free(image_data);
}
#endif /*HAVE_LIBPNG*/
+
+\f
+/*
+ * Local variables:
+ * c-file-style: "gnu"
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ */
* 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
*
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,
* 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:
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 );
* 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:
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);
}
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;
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);
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.
*/
{
- 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;
}
* 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:
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 );
}
return NULL;
}
+
+\f
+/*
+ * Local variables:
+ * c-file-style: "gnu"
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ */
* 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:
/* 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, "
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,
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);
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;
}
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.
*/
{
- 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;
}
+\f
+/*
+ * Local variables:
+ * c-file-style: "gnu"
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ */
* 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:
"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...) \
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.
*/