Commit c8630200 authored by Rocky Bernstein's avatar Rocky Bernstein
Browse files

Don't do compensation subtitle unscaling if the underlying video

chroma does the scaling.
parent 2c55924c
......@@ -2,7 +2,7 @@
* Common SVCD and VCD subtitle routines.
*****************************************************************************
* Copyright (C) 2003, 2004 VideoLAN
* $Id: common.c,v 1.5 2004/01/11 01:54:20 rocky Exp $
* $Id: common.c,v 1.6 2004/01/14 11:47:19 rocky Exp $
*
* Author: Rocky Bernstein
* based on code from:
......@@ -188,6 +188,7 @@ VCDInlinePalette ( /*inout*/ uint8_t *p_dest, decoder_sys_t *p_sys,
for ( ; n >= 0 ; n-- ) {
p_to[n] = p_sys->p_palette[p_from[n]];
/*p_to[n] = p_sys->p_palette[p_from[3]];*/
}
}
......@@ -325,6 +326,73 @@ VCDSubScaleX( decoder_t *p_dec, subpicture_t *p_spu,
}
/* 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.
The downside is having to scale many times for each render call.
*/
void
VCDSubHandleScaling( subpicture_t *p_spu, decoder_t *p_dec )
{
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) {
/* 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 when
there is scaling. That's why x and y are reversed from
the else branch in the call below.
*/
switch( p_vout->output.i_chroma )
{
/* chromas which are not scaled: */
case VLC_FOURCC('I','4','2','0'):
case VLC_FOURCC('I','Y','U','V'):
case VLC_FOURCC('Y','V','1','2'):
case VLC_FOURCC('Y','U','Y','2'):
return;
break;
/* chromas which are scaled: */
case VLC_FOURCC('R','V','1','6'):
case VLC_FOURCC('R','V','2','4'):
case VLC_FOURCC('R','V','3','2'):
case VLC_FOURCC('R','G','B','2'):
break;
default:
msg_Err( p_vout, "unknown chroma %x",
p_vout->output.i_chroma );
return;
break;
}
/* We get here only for scaled chromas. */
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 );
}
}
}
/**
* DestroySPU: subpicture destructor
*/
......
......@@ -2,7 +2,7 @@
* Header for Common SVCD and VCD subtitle routines.
*****************************************************************************
* Copyright (C) 2003, 2004 VideoLAN
* $Id: common.h,v 1.4 2004/01/11 01:54:20 rocky Exp $
* $Id: common.h,v 1.5 2004/01/14 11:47:19 rocky Exp $
*
* Author: Rocky Bernstein
*
......@@ -31,6 +31,9 @@ void VCDSubAppendData( decoder_t *p_dec, uint8_t *buffer,
uint32_t buf_len );
vout_thread_t *VCDSubFindVout( decoder_t *p_dec );
void VCDSubHandleScaling( subpicture_t *p_spu, decoder_t *p_dec ) ;
void VCDSubScaleX( decoder_t *p_dec, subpicture_t *p_spu,
unsigned int i_scale_x, unsigned int i_scale_y );
......
......@@ -2,7 +2,7 @@
* cvd.c : CVD Subtitle decoder thread
*****************************************************************************
* Copyright (C) 2003 VideoLAN
* $Id: cvd.c,v 1.9 2004/01/11 01:54:20 rocky Exp $
* $Id: cvd.c,v 1.10 2004/01/14 11:47:19 rocky Exp $
*
* Authors: Rocky Bernstein
* based on code from:
......@@ -55,6 +55,10 @@ vlc_module_begin();
SUB_ASPECT_RATIO_TEXT, SUB_ASPECT_RATIO_LONGTEXT,
VLC_TRUE );
add_integer( MODULE_STRING "-duration-scaling", 9, NULL,
DURATION_SCALE_TEXT, DURATION_SCALE_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.10 2004/01/11 01:54:20 rocky Exp $
* $Id: cvd_parse.c,v 1.11 2004/01/14 11:47:19 rocky Exp $
*
* Authors: Rocky Bernstein
* based on code from:
......@@ -136,12 +136,20 @@ void E_(ParseMetaInfo)( decoder_t *p_dec )
switch ( p[0] ) {
case 0x04: /* subtitle duration in 1/90000ths of a second */
{
mtime_t i_duration = (p[1]<<16) + (p[2]<<8) + p[3];
mtime_t i_duration_scale = config_GetInt( p_dec, MODULE_STRING
"-duration-scaling" );
dbg_print( DECODE_DBG_PACKET,
"subtitle display duration %lu secs (scaled %lu secs)",
(long unsigned int) (i_duration / 90000),
(long unsigned int) (i_duration * i_duration_scale / 90000)
);
p_sys->i_duration = i_duration * i_duration_scale ;
break;
}
p_sys->i_duration = (p[1]<<16) + (p[2]<<8) + p[3];
dbg_print( DECODE_DBG_PACKET,
"subtitle display duration %u", p_sys->i_duration);
break;
case 0x0c: /* unknown */
dbg_print( DECODE_DBG_PACKET,
......@@ -523,46 +531,7 @@ ParseImage( decoder_t *p_dec, subpicture_t * p_spu )
#endif /*HAVE_LIBPNG*/
VCDInlinePalette( p_dest, p_sys, i_height, i_width );
/* 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.
The downside is having to scale many times for each render call.
*/
{
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) {
/* 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 );
}
}
}
VCDSubHandleScaling( p_spu, p_dec );
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.9 2004/01/11 01:54:20 rocky Exp $
* $Id: ogt.c,v 1.10 2004/01/14 11:47:19 rocky Exp $
*
* Author: Rocky Bernstein
* based on code from:
......@@ -55,6 +55,10 @@ vlc_module_begin();
SUB_ASPECT_RATIO_TEXT, SUB_ASPECT_RATIO_LONGTEXT,
VLC_TRUE );
add_integer( MODULE_STRING "-duration-scaling", 9, NULL,
DURATION_SCALE_TEXT, DURATION_SCALE_LONGTEXT,
VLC_TRUE );
add_submodule();
set_description( _("Philips OGT (SVCD subtitle) packetizer") );
set_capability( "packetizer", 50 );
......
......@@ -2,7 +2,7 @@
* Philips OGT (SVCD subtitle) packet parser
*****************************************************************************
* Copyright (C) 2003, 2004 VideoLAN
* $Id: ogt_parse.c,v 1.8 2004/01/11 01:54:20 rocky Exp $
* $Id: ogt_parse.c,v 1.9 2004/01/14 11:47:19 rocky Exp $
*
* Author: Rocky Bernstein
* based on code from:
......@@ -88,7 +88,7 @@ void E_(ParseHeader)( decoder_t *p_dec, uint8_t *p_buffer, block_t *p_block )
decoder_sys_t *p_sys = p_dec->p_sys;
uint8_t *p = p_buffer;
int i;
dbg_print( (DECODE_DBG_CALL|DECODE_DBG_EXT) , "");
p_sys->i_pts = p_block->i_pts;
......@@ -98,6 +98,8 @@ void E_(ParseHeader)( decoder_t *p_dec, uint8_t *p_buffer, block_t *p_block )
if ( p_sys->i_options & 0x08 ) {
p_sys->i_duration = GETINT32(p);
p_sys->i_duration *= config_GetInt( p_dec, MODULE_STRING
"-duration-scaling" );
} else {
/* 0 means display until next subtitle comes in. */
p_sys->i_duration = 0;
......@@ -132,10 +134,10 @@ void E_(ParseHeader)( decoder_t *p_dec, uint8_t *p_buffer, block_t *p_block )
if (p_sys && p_sys->i_debug & DECODE_DBG_PACKET) {
msg_Dbg( p_dec, "x-start: %d, y-start: %d, width: %d, height %d, "
"spu size: %d, duration: %u (d:%d p:%d)",
"spu size: %d, duration: %lu (d:%d p:%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->i_spu_size, (long unsigned int) p_sys->i_duration,
p_sys->i_image_length, p_sys->i_image_offset);
for (i=0; i<4; i++) {
......@@ -193,7 +195,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;
p_spu->p_sys->b_crop = VLC_FALSE;
p_spu->p_sys->i_debug = p_sys->i_debug;
......@@ -367,47 +369,7 @@ ParseImage( decoder_t *p_dec, subpicture_t * p_spu )
#endif /*HAVE_LIBPNG*/
VCDInlinePalette( p_dest, p_sys, i_height, i_width );
/* 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.
The downside is having to scale many times for each render call.
*/
{
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) {
/* 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 );
}
}
}
VCDSubHandleScaling( p_spu, p_dec );
return VLC_SUCCESS;
}
......
......@@ -2,7 +2,7 @@
* render.c : Philips OGT (SVCD Subtitle) renderer
*****************************************************************************
* Copyright (C) 2003, 2004 VideoLAN
* $Id: render.c,v 1.12 2004/01/14 04:50:02 rocky Exp $
* $Id: render.c,v 1.13 2004/01/14 11:47:19 rocky Exp $
*
* Author: Rocky Bernstein
* based on code from:
......@@ -311,7 +311,6 @@ static void RenderYUY2( vout_thread_t *p_vout, picture_t *p_pic,
ogt_yuvt_t *p_source;
int i_x, i_y;
const uint16_t i_spu_width = p_spu->i_width;
/* Crop-specific */
int i_x_start, i_y_start, i_x_end, i_y_end;
......@@ -338,8 +337,8 @@ static void RenderYUY2( vout_thread_t *p_vout, picture_t *p_pic,
/* Draw until we reach the bottom of the subtitle */
for( i_y = 0;
i_y < p_spu->i_height * p_pic->p->i_pitch;
i_y += p_pic->p->i_pitch )
i_y < p_spu->i_height * p_pic->p[Y_PLANE].i_pitch ;
i_y += p_pic->p[Y_PLANE].i_pitch )
{
uint8_t *p_pixel_base_y = p_pixel_base + i_y;
......@@ -355,7 +354,7 @@ static void RenderYUY2( vout_thread_t *p_vout, picture_t *p_pic,
/* Draw until we reach the end of the line */
for( ; i_x < i_spu_width; i_x++, p_source++ )
for( ; i_x < p_spu->i_width; i_x++, p_source++ )
{
if( b_crop ) {
......@@ -462,10 +461,10 @@ static void RenderYUY2( vout_thread_t *p_vout, picture_t *p_pic,
/* Force v in the range 0.255 */
static inline uint8_t
clip_8_bit(int v)
clip_5_bit(int v)
{
if (v<0) return 0;
if (v>255) return 255;
if (v>31) return 31;
return (uint8_t) v;
}
......@@ -481,11 +480,11 @@ yuv2rgb16(ogt_yuvt_t *p_yuv, uint8_t *p_rgb1, uint8_t *p_rgb2 )
int i_green = (1.1644 * i_Y) - (0.3918 * i_Cb) - (0.8130 * i_Cr);
int i_blue = (1.1644 * i_Y) + (2.0172 * i_Cb);
i_red = clip_8_bit( i_red ) >> 3;
i_green = clip_8_bit( i_green ) >> 3;
i_blue = clip_8_bit( i_blue ) >> 3;
i_red = clip_5_bit( i_red >> 3 );
i_green = clip_5_bit( i_green >> 3 );
i_blue = clip_5_bit( i_blue >> 3 );
*p_rgb1 = (i_blue << 3) | (i_red & 0x18 >> 3);
*p_rgb1 = ((i_blue & 0x1F) << 3) | (i_red & 0x18 >> 3);
*p_rgb2 = (i_red & 0x07 << 5) | (i_green & 0x1F);
......@@ -502,9 +501,10 @@ static void RenderRV16( vout_thread_t *p_vout, picture_t *p_pic,
uint8_t *p_pixel_base;
ogt_yuvt_t *p_src_start = (ogt_yuvt_t *)p_spu->p_sys->p_data;
ogt_yuvt_t *p_src_end = &p_src_start[p_spu->i_height * p_spu->i_width];
ogt_yuvt_t *p_source;
int i_x, i_y;
int i_x_src, i_y_src;
int i_y_src;
/* RGB-specific */
int i_xscale, i_yscale, i_width, i_height, i_ytmp, i_ynext;
......@@ -534,11 +534,13 @@ static void RenderRV16( vout_thread_t *p_vout, picture_t *p_pic,
p_pixel_base = p_pic->p->p_pixels + ( (p_spu->i_x * i_xscale) >> 6 ) * 2
+ ( (p_spu->i_y * i_yscale) >> 6 ) * p_pic->p->i_pitch;
i_x_start = i_xscale * p_spu->p_sys->i_x_start;
i_y_start = i_yscale * p_spu->p_sys->i_y_start;
i_x_end = i_xscale * p_spu->p_sys->i_x_end;
i_y_end = i_yscale * p_spu->p_sys->i_y_end;
i_x_start = p_sys->i_x_start;
i_y_start = i_yscale * p_sys->i_y_start;
i_x_end = p_sys->i_x_end;
i_y_end = i_yscale * p_sys->i_y_end;
p_source = (ogt_yuvt_t *)p_sys->p_data;
/* Draw until we reach the bottom of the subtitle */
i_y = 0;
for( i_y_src = 0 ; i_y_src < p_spu->i_height * p_spu->i_width;
......@@ -550,24 +552,33 @@ static void RenderRV16( vout_thread_t *p_vout, picture_t *p_pic,
p_pixel_base_y = p_pixel_base + (i_ytmp * p_pic->p->i_pitch);
i_x = 0;
if ( b_crop ) {
if ( i_y > i_y_end ) break;
if (i_x_start) {
i_x = i_x_start;
p_source += i_x_start;
}
}
/* Check whether we need to draw one line or more than one */
if( i_ytmp + 1 >= ( i_y >> 6 ) )
{
/* Draw until we reach the end of the line */
for( i_x_src = 0; i_x_src < p_spu->i_width; i_x_src++ )
/* Draw until we reach the end of the line */
for( ; i_x < p_spu->i_width; i_x++, p_source++ )
{
ogt_yuvt_t *p_source;
i_x += (1<<6);
if( b_crop
&& ( i_x < i_x_start || i_x > i_x_end
|| i_y < i_y_start || i_y > i_y_end ) )
{
continue;
}
p_source = &p_src_start[i_y_src + i_x_src];
if( b_crop ) {
/* FIXME: y cropping should be dealt with outside of this
loop.*/
if ( i_y < i_y_start) continue;
if ( i_x > i_x_end )
{
p_source += p_spu->i_width - i_x;
break;
}
}
if (p_source >= p_src_end) {
msg_Err( p_vout, "Trying to access beyond subtitle %dx%d %d",
......@@ -589,12 +600,12 @@ static void RenderRV16( vout_thread_t *p_vout, picture_t *p_pic,
/* This is the location that's going to get changed.
*/
uint8_t *p_dest = p_pixel_base_y + 2 * (i_x >> 6 );
uint8_t *p_dest = p_pixel_base_y + 2 * i_x;
int i;
uint8_t i_rgb1;
uint8_t i_rgb2;
yuv2rgb16(p_source, &i_rgb1, &i_rgb2);
for (i=0; i< 2*i_xscale; i+=2) {
for (i=0; i < i_xscale; i++) {
*p_dest++ = i_rgb1;
*p_dest++ = i_rgb2;
}
......@@ -611,7 +622,7 @@ static void RenderRV16( vout_thread_t *p_vout, picture_t *p_pic,
be completely transparent and is not correct, but
that's handled in a special case above anyway. */
uint8_t *p_pixel = p_pixel_base + 2*( i_x >> 6 );
uint8_t *p_pixel = p_pixel_base + 2*i_x;
uint16_t i_colprecomp = Y2RV16(p_source->plane[Y_PLANE])
* ( (uint16_t) (p_source->s.t+1) );
uint16_t i_destalpha = MAX_ALPHA - p_source->s.t;
......@@ -633,20 +644,22 @@ static void RenderRV16( vout_thread_t *p_vout, picture_t *p_pic,
/* Draw until we reach the end of the line */
for( i_x_src = 0; i_x_src < p_spu->i_width; i_x_src++ )
for( ; i_x < p_spu->i_width; i_x++, p_source++ )
{
ogt_yuvt_t *p_source;
i_x += (1<<6);
if( b_crop
&& ( i_x < i_x_start || i_x > i_x_end
|| i_y < i_y_start || i_y > i_y_end ) )
{
continue;
}
if( b_crop ) {
/* FIXME: y cropping should be dealt with outside of this
loop.*/
if ( i_y < i_y_start) continue;
if ( i_x > i_x_end )
{
p_source += p_spu->i_width - i_x;
break;
}
}
p_source = &p_src_start[i_y_src + i_x_src];
if (p_source >= p_src_end) {
msg_Err( p_vout, "Trying to access beyond subtitle %dx%d %d",
i_x, i_y / i_yscale, i_height);
......@@ -667,24 +680,20 @@ static void RenderRV16( vout_thread_t *p_vout, picture_t *p_pic,
/* This is the location that's going to get changed.
*/
uint8_t *p_pixel_base_x = p_pixel_base + 2 * ( i_x >> 6 );
uint8_t *p_pixel_base_x = p_pixel_base + 2 * i_x;
for( ; i_ytmp < i_ynext ; i_ytmp += p_pic->p->i_pitch )
{
/* This is the location that's going to get changed. */
uint8_t *p_dest = p_pixel_base_x + i_ytmp;
#if 1
int i;
uint8_t i_rgb1;
uint8_t i_rgb2;
yuv2rgb16(p_source, &i_rgb1, &i_rgb2);
for (i=0; i< 2*i_xscale; i+=2) {
*p_dest++ = i_rgb1;
*p_dest++ = i_rgb2;
}
#else
memset( p_dest, 0xFF, 2*i_xscale );
#endif
int i;
uint8_t i_rgb1;
uint8_t i_rgb2;
yuv2rgb16(p_source, &i_rgb1, &i_rgb2);
for (i=0; i < i_xscale; i++) {
*p_dest++ = i_rgb1;
*p_dest++ = i_rgb2;
}
}
break;
}
......
......@@ -2,7 +2,7 @@
* subtitle.h : Common SVCD and CVD subtitles header
*****************************************************************************
* Copyright (C) 2003,2004 VideoLAN
* $Id: subtitle.h,v 1.6 2004/01/11 01:54:20 rocky Exp $
* $Id: subtitle.h,v 1.7 2004/01/14 11:47:19 rocky Exp $
*
* Author: Rocky Bernstein
* based on code from:
......@@ -59,6 +59,13 @@
"4:3 and 16:9 respectively." \
)
#define DURATION_SCALE_TEXT N_("factor to increase subtitle display interval")
#define DURATION_SCALE_LONGTEXT N_( \
"If you find you need extra time for reading subtitles, " \
"you can set this higher and it will multiply the display " \
"time by that amount. Use 0 to mean until the next " \
"subtitle.")
#define DECODE_DEBUG 1
#if DECODE_DEBUG
#define dbg_print(mask, s, args...) \
......@@ -144,7 +151,7 @@ struct decoder_sys_t
int subtitle_data_pos; /* where to write next chunk */
uint32_t i_duration; /* how long to display the image, 0 stands
mtime_t i_duration; /* how long to display the image, 0 stands
for "until next subtitle" */
uint16_t i_x_start, i_y_start; /* position of top leftmost pixel of
......
Supports Markdown
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