Commit 5d5fd803 authored by Sam Hocevar's avatar Sam Hocevar

  * Fixed an aspect ratio issue in the SPU decoder, and optimized the
    SPU renderer.
parent 03f0895b
......@@ -3,6 +3,8 @@
#===================#
HEAD
* Fixed an aspect ratio issue in the SPU decoder, and optimized the
SPU renderer.
* Speed optimization in the handling of the unusual ephemer DVD subtitles.
* Little optimization to bozo's UnalignedShowBits fix.
* Race fix in the packet cache by Jon Lech Johansen <jon-vl@nanocrew.net>.
......
......@@ -2,7 +2,7 @@
* spu_decoder.c : spu decoder thread
*****************************************************************************
* Copyright (C) 2000 VideoLAN
* $Id: spu_decoder.c,v 1.42 2001/05/07 04:42:42 sam Exp $
* $Id: spu_decoder.c,v 1.43 2001/05/08 20:38:25 sam Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
*
......@@ -504,17 +504,16 @@ static int ParseControlSequences( spudec_thread_t *p_spudec,
/* Get rid of padding bytes */
switch( p_spudec->i_spu_size - i_index )
{
/* Zero or one padding byte, quite usual */
case 1:
RemoveBits( &p_spudec->bit_stream, 8 );
i_index++;
case 0:
/* Zero or one padding byte, quite usual */
break;
/* More than one padding byte - this is very strange, but
* we can deal with it */
default:
/* More than one padding byte - this is very strange, but
* we can deal with it */
intf_WarnMsg( 2, "spudec warning: %i padding bytes, we usually "
"get 1 or none",
p_spudec->i_spu_size - i_index );
......@@ -542,7 +541,6 @@ static int ParseControlSequences( spudec_thread_t *p_spudec,
static int ParseRLE( u8 *p_src, subpicture_t * p_spu )
{
unsigned int i_code;
unsigned int i_id = 0;
unsigned int i_width = p_spu->i_width;
unsigned int i_height = p_spu->i_height;
......@@ -551,6 +549,7 @@ static int ParseRLE( u8 *p_src, subpicture_t * p_spu )
u16 *p_dest = (u16 *)p_spu->p_data;
/* The subtitles are interlaced, we need two offsets */
unsigned int i_id = 0; /* Start on the even SPU layer */
unsigned int pi_table[ 2 ];
unsigned int *pi_offset;
......
......@@ -5,7 +5,7 @@
* thread, and destroy a previously oppened video output thread.
*****************************************************************************
* Copyright (C) 2000 VideoLAN
* $Id: video_output.c,v 1.127 2001/05/08 00:43:57 sam Exp $
* $Id: video_output.c,v 1.128 2001/05/08 20:38:25 sam Exp $
*
* Authors: Vincent Seguin <seguin@via.ecp.fr>
*
......@@ -72,11 +72,9 @@ static void SetBufferArea ( vout_thread_t *p_vout, int i_x, int i_y,
static void SetBufferPicture ( vout_thread_t *p_vout, picture_t *p_pic );
static void RenderPicture ( vout_thread_t *p_vout, picture_t *p_pic );
static void RenderPictureInfo ( vout_thread_t *p_vout, picture_t *p_pic );
static void RenderSubPicture ( vout_thread_t *p_vout,
static void RenderSubPicture ( vout_thread_t *p_vout, picture_t *p_pic,
subpicture_t *p_subpic );
static void RenderInterface ( vout_thread_t *p_vout );
static int RenderIdle ( vout_thread_t *p_vout );
static int RenderSplash ( vout_thread_t *p_vout );
static void RenderInfo ( vout_thread_t *p_vout );
static int Manage ( vout_thread_t *p_vout );
static int Align ( vout_thread_t *p_vout, int *pi_x,
......@@ -1198,18 +1196,14 @@ static void RunThread( vout_thread_t *p_vout)
RenderPictureInfo( p_vout, p_pic );
RenderInfo( p_vout );
}
}
if( b_display ) /* XXX: quick HACK */
{
if( p_subpic )
{
RenderSubPicture( p_vout, p_subpic );
RenderSubPicture( p_vout, p_pic, p_subpic );
}
}
/* Render interface and subpicture */
if( b_display && p_vout->b_interface && p_vout->b_need_render )
{
RenderInterface( p_vout );
}
}
else if( p_vout->b_active && p_vout->b_need_render
&& p_vout->init_display_date == 0)
......@@ -1229,10 +1223,6 @@ static void RunThread( vout_thread_t *p_vout)
if( b_display )
{
p_vout->last_idle_date = current_date;
if( p_vout->b_interface )
{
RenderInterface( p_vout );
}
}
}
......@@ -1248,17 +1238,7 @@ static void RunThread( vout_thread_t *p_vout)
*/
if( p_vout->init_display_date > 0 && p_vout->b_need_render )
{
if( p_vout->b_active &&
mdate()-p_vout->init_display_date < 5000000)
{
/* there is something to display ! */
b_display = 1;
RenderSplash( p_vout );
} else {
/* no splash screen ! */
p_vout->init_display_date=0;
}
p_vout->init_display_date = 0;
}
......@@ -1895,42 +1875,6 @@ static void RenderPictureInfo( vout_thread_t *p_vout, picture_t *p_pic )
#endif
}
/*****************************************************************************
* RenderSplash: render splash picture
*****************************************************************************
* This function will print something on the screen. It will return 0 if
* nothing has been rendered, or 1 if something has been changed on the screen.
* Note that if you absolutely want something to be printed, you will have
* to force it by setting the last idle date to 0.
* Unlike other rendering functions, this one calls the SetBufferPicture
* function when needed.
*****************************************************************************/
int RenderSplash( vout_thread_t *p_vout )
{
int i_x = 0, i_y = 0; /* text position */
int i_width, i_height; /* text size */
char *psz_text = "VideoLAN Client (" VERSION ")"; /* text to display */
memset( p_vout->p_buffer[ p_vout->i_buffer_index ].p_data,
p_vout->i_bytes_per_line * p_vout->i_height, 12);
// SetBufferPicture( p_vout, NULL );
vout_TextSize( p_vout->p_large_font, WIDE_TEXT | OUTLINED_TEXT, psz_text,
&i_width, &i_height );
if( !Align( p_vout, &i_x, &i_y, i_width, i_height, CENTER_RALIGN, CENTER_RALIGN ) )
{
vout_Print( p_vout->p_large_font,
p_vout->p_buffer[ p_vout->i_buffer_index ].p_data +
i_x * p_vout->i_bytes_per_pixel + (i_y - 16 ) * p_vout->i_bytes_per_line,
p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line,
p_vout->i_white_pixel, p_vout->i_gray_pixel, 0,
WIDE_TEXT | OUTLINED_TEXT, psz_text, 100);
SetBufferArea( p_vout, i_x, i_y, i_width, i_height);
}
return( 1 );
}
/*****************************************************************************
* RenderIdle: render idle picture
*****************************************************************************
......@@ -2037,7 +1981,8 @@ static void RenderInfo( vout_thread_t *p_vout )
*****************************************************************************
* This function renders a sub picture unit.
*****************************************************************************/
static void RenderSubPicture( vout_thread_t *p_vout, subpicture_t *p_subpic )
static void RenderSubPicture( vout_thread_t *p_vout, picture_t *p_pic,
subpicture_t *p_subpic )
{
p_vout_font_t p_font; /* text font */
int i_width, i_height; /* subpicture dimensions */
......@@ -2047,9 +1992,11 @@ static void RenderSubPicture( vout_thread_t *p_vout, subpicture_t *p_subpic )
switch( p_subpic->i_type )
{
case DVD_SUBPICTURE: /* DVD subpicture unit */
vout_RenderSPU( &p_vout->p_buffer[ p_vout->i_buffer_index ],
p_subpic, p_vout->i_bytes_per_pixel,
p_vout->i_bytes_per_line );
vout_RenderRGBSPU( p_pic, p_subpic,
&p_vout->p_buffer[ p_vout->i_buffer_index ],
p_vout->i_bytes_per_pixel,
p_vout->i_bytes_per_line );
/* vout_RenderYUVSPU( p_pic, p_subpic ); */
break;
case TEXT_SUBPICTURE: /* single line text */
......@@ -2094,55 +2041,6 @@ static void RenderSubPicture( vout_thread_t *p_vout, subpicture_t *p_subpic )
}
}
/*****************************************************************************
* RenderInterface: render the interface
*****************************************************************************
* This function renders the interface, if any.
*****************************************************************************/
static void RenderInterface( vout_thread_t *p_vout )
{
int i_height, i_text_height; /* total and text height */
int i_width_1, i_width_2; /* text width */
int i_byte; /* byte index */
const char *psz_text_1 = "[1-9] Channel [i]nfo [c]olor [g/G]amma";
const char *psz_text_2 = "[+/-] Volume [m]ute [s]caling [Q]uit";
/* Get text size */
vout_TextSize( p_vout->p_large_font, OUTLINED_TEXT, psz_text_1, &i_width_1, &i_height );
vout_TextSize( p_vout->p_large_font, OUTLINED_TEXT, psz_text_2, &i_width_2, &i_text_height );
i_height += i_text_height;
/* Render background */
for( i_byte = (p_vout->i_height - i_height) * p_vout->i_bytes_per_line;
i_byte < p_vout->i_height * p_vout->i_bytes_per_line;
i_byte++ )
{
/* XXX?? noooo ! */
p_vout->p_buffer[ p_vout->i_buffer_index ].p_data[ i_byte ] = p_vout->i_blue_pixel;
}
/* Render text, if not larger than screen */
if( i_width_1 < p_vout->i_width )
{
vout_Print( p_vout->p_large_font, p_vout->p_buffer[ p_vout->i_buffer_index ].p_data +
(p_vout->i_height - i_height) * p_vout->i_bytes_per_line,
p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line,
p_vout->i_white_pixel, p_vout->i_black_pixel, 0,
OUTLINED_TEXT, psz_text_1, 100 );
}
if( i_width_2 < p_vout->i_width )
{
vout_Print( p_vout->p_large_font, p_vout->p_buffer[ p_vout->i_buffer_index ].p_data +
(p_vout->i_height - i_height + i_text_height) * p_vout->i_bytes_per_line,
p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line,
p_vout->i_white_pixel, p_vout->i_black_pixel, 0,
OUTLINED_TEXT, psz_text_2, 100 );
}
/* Activate modified area */
SetBufferArea( p_vout, 0, p_vout->i_height - i_height, p_vout->i_width, i_height );
}
/*****************************************************************************
* Manage: manage thread
*****************************************************************************
......
......@@ -2,7 +2,7 @@
* video_spu.c : DVD subpicture units functions
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
* $Id: video_spu.c,v 1.20 2001/04/06 09:15:48 sam Exp $
* $Id: video_spu.c,v 1.21 2001/05/08 20:38:25 sam Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
*
......@@ -42,29 +42,29 @@
static int p_palette[4] = { 0x0000, 0xffff, 0x5555, 0x8888 };
/*****************************************************************************
* vout_RenderSPU: draw an SPU on a picture
* vout_RenderRGBSPU: draw an SPU on a picture
*****************************************************************************
* This is a fast implementation of the subpicture drawing code. The data
* has been preprocessed once in spu_decoder.c, so we don't need to parse the
* RLE buffer again and again. Most sanity checks are done in spu_decoder.c
* so that this routine can be as fast as possible.
*****************************************************************************/
void vout_RenderSPU( vout_buffer_t *p_buffer, subpicture_t *p_spu,
int i_bytes_per_pixel, int i_bytes_per_line )
void vout_RenderRGBSPU( picture_t *p_pic, const subpicture_t *p_spu,
vout_buffer_t *p_buffer,
int i_bytes_per_pixel, int i_bytes_per_line )
{
int i_len, i_color;
u16 *p_source = (u16 *)p_spu->p_data;
/* FIXME: we need a way to get 720 and 576 from the stream */
int i_xscale = ( p_buffer->i_pic_width << 6 ) / 720;
int i_yscale = ( p_buffer->i_pic_height << 6 ) / 576;
int i_xscale = ( p_buffer->i_pic_width << 6 ) / p_pic->i_width;
int i_yscale = ( p_buffer->i_pic_height << 6 ) / p_pic->i_height;
int i_width = p_spu->i_width * i_xscale;
int i_height = p_spu->i_height * i_yscale;
int i_x = 0, i_y = 0, i_ytmp, i_yreal, i_ynext;
int i_x, i_y, i_ytmp, i_yreal, i_ynext;
u8 *p_dest = p_buffer->p_data
u8 *p_dest = p_buffer->p_data + ( i_width >> 6 ) * i_bytes_per_pixel
/* Add the picture coordinates and the SPU coordinates */
+ ( p_buffer->i_pic_x + ((p_spu->i_x * i_xscale) >> 6))
* i_bytes_per_pixel
......@@ -72,7 +72,9 @@ void vout_RenderSPU( vout_buffer_t *p_buffer, subpicture_t *p_spu,
* i_bytes_per_line;
/* Draw until we reach the bottom of the subtitle */
for( i_y = 0 ; i_y < i_height ; /* i_y incremented below */ )
i_y = 0;
while( i_y < i_height )
{
i_ytmp = i_y >> 6;
i_y += i_yscale;
......@@ -84,20 +86,28 @@ void vout_RenderSPU( vout_buffer_t *p_buffer, subpicture_t *p_spu,
i_yreal = i_bytes_per_line * i_ytmp;
/* Draw until we reach the end of the line */
for( i_x = 0 ; i_x < i_width ; i_x += i_len )
i_x = i_width;
while( i_x )
{
/* Get RLE information */
i_len = i_xscale * ( *p_source >> 2 );
i_color = *p_source++ & 0x3;
/* Get the RLE part */
i_color = *p_source & 0x3;
/* Draw the line */
if( i_color )
{
memset( p_dest + i_bytes_per_pixel * ( i_x >> 6 )
i_len = i_xscale * ( *p_source++ >> 2 );
memset( p_dest - i_bytes_per_pixel * ( i_x >> 6 )
+ i_yreal,
p_palette[ i_color ],
i_bytes_per_pixel * ( ( i_len >> 6 ) + 1 ) );
i_x -= i_len;
continue;
}
i_x -= i_xscale * ( *p_source++ >> 2 );
}
}
else
......@@ -106,27 +116,81 @@ void vout_RenderSPU( vout_buffer_t *p_buffer, subpicture_t *p_spu,
i_ynext = i_bytes_per_line * i_y >> 6;
/* Draw until we reach the end of the line */
for( i_x = 0 ; i_x < i_width ; i_x += i_len )
i_x = i_width;
while( i_x )
{
/* Get RLE information */
i_len = i_xscale * ( *p_source >> 2 );
i_color = *p_source++ & 0x3;
/* Get the RLE part */
i_color = *p_source & 0x3;
/* Draw as many lines as needed */
if( i_color )
{
i_len = i_xscale * ( *p_source++ >> 2 );
for( i_ytmp = i_yreal ;
i_ytmp < i_ynext ;
i_ytmp += i_bytes_per_line )
{
memset( p_dest + i_bytes_per_pixel * ( i_x >> 6 )
memset( p_dest - i_bytes_per_pixel * ( i_x >> 6 )
+ i_ytmp,
p_palette[ i_color ],
i_bytes_per_pixel * ( ( i_len >> 6 ) + 1 ) );
}
i_x -= i_len;
continue;
}
i_x -= i_xscale * ( *p_source++ >> 2 );
}
}
}
}
/*****************************************************************************
* vout_RenderYUVSPU: draw an SPU on an YUV overlay
*****************************************************************************
* This is a fast implementation of the subpicture drawing code. The data
* has been preprocessed once in spu_decoder.c, so we don't need to parse the
* RLE buffer again and again. Most sanity checks are done in spu_decoder.c
* so that this routine can be as fast as possible.
*****************************************************************************/
void vout_RenderYUVSPU( picture_t *p_pic, const subpicture_t *p_spu )
{
int i_len, i_color;
u16 *p_source = (u16 *)p_spu->p_data;
int i_x, i_y;
u8 *p_dest = p_pic->p_y + p_spu->i_x + p_spu->i_width
+ p_pic->i_width * ( p_spu->i_y + p_spu->i_height );
/* Draw until we reach the bottom of the subtitle */
i_y = p_spu->i_height * p_pic->i_width;
while( i_y )
{
/* Draw until we reach the end of the line */
i_x = p_spu->i_width;
while( i_x )
{
/* Draw the line if needed */
i_color = *p_source & 0x3;
if( i_color )
{
i_len = *p_source++ >> 2;
memset( p_dest - i_x - i_y, p_palette[ i_color ], i_len );
i_x -= i_len;
continue;
}
i_x -= *p_source++ >> 2;
}
i_y -= p_pic->i_width;
}
}
......@@ -2,7 +2,7 @@
* video_spu.h : DVD subpicture units functions
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
* $Id: video_spu.h,v 1.8 2001/03/21 13:42:35 sam Exp $
* $Id: video_spu.h,v 1.9 2001/05/08 20:38:25 sam Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
* Henri Fallon <henri@via.ecp.fr>
......@@ -25,6 +25,8 @@
/*****************************************************************************
* Prototypes
*****************************************************************************/
void vout_RenderSPU ( vout_buffer_t *p_buffer, subpicture_t *p_subpic,
int i_bytes_per_pixel, int i_bytes_per_line );
void vout_RenderRGBSPU( picture_t *p_pic, const subpicture_t *p_spu,
vout_buffer_t *p_buffer,
int i_bytes_per_pixel, int i_bytes_per_line );
void vout_RenderYUVSPU( picture_t *p_pic, const subpicture_t *p_spu );
......@@ -2,7 +2,7 @@
* video_fifo.c : video FIFO management
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
* $Id: video_fifo.c,v 1.31 2001/05/06 04:32:02 sam Exp $
* $Id: video_fifo.c,v 1.32 2001/05/08 20:38:25 sam Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
......@@ -80,3 +80,4 @@ void vpar_InitFIFO( vpar_thread_t * p_vpar )
}
#endif
}
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