From 5d5fd803fe07ea1e825e6cd30d06ab4aefbffe0c Mon Sep 17 00:00:00 2001 From: Sam Hocevar Date: Tue, 8 May 2001 20:38:25 +0000 Subject: [PATCH] * Fixed an aspect ratio issue in the SPU decoder, and optimized the SPU renderer. --- ChangeLog | 2 + src/spu_decoder/spu_decoder.c | 11 ++- src/video_output/video_output.c | 130 ++++---------------------------- src/video_output/video_spu.c | 104 ++++++++++++++++++++----- src/video_output/video_spu.h | 8 +- src/video_parser/video_fifo.c | 3 +- 6 files changed, 112 insertions(+), 146 deletions(-) diff --git a/ChangeLog b/ChangeLog index ed10914de4..f40bc557e2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -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 . diff --git a/src/spu_decoder/spu_decoder.c b/src/spu_decoder/spu_decoder.c index 9e2faf4a23..95dee601dc 100644 --- a/src/spu_decoder/spu_decoder.c +++ b/src/spu_decoder/spu_decoder.c @@ -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 * @@ -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; diff --git a/src/video_output/video_output.c b/src/video_output/video_output.c index 7010f3dd1d..7abe3ab4da 100644 --- a/src/video_output/video_output.c +++ b/src/video_output/video_output.c @@ -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 * @@ -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 ***************************************************************************** diff --git a/src/video_output/video_spu.c b/src/video_output/video_spu.c index 52cb742d09..d21dcadf3d 100644 --- a/src/video_output/video_spu.c +++ b/src/video_output/video_spu.c @@ -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 * @@ -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; } } diff --git a/src/video_output/video_spu.h b/src/video_output/video_spu.h index 19e81c5d2f..6823a526b1 100644 --- a/src/video_output/video_spu.h +++ b/src/video_output/video_spu.h @@ -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 * Henri Fallon @@ -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 ); diff --git a/src/video_parser/video_fifo.c b/src/video_parser/video_fifo.c index d93c64adf7..eb5aee930d 100644 --- a/src/video_parser/video_fifo.c +++ b/src/video_parser/video_fifo.c @@ -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 * @@ -80,3 +80,4 @@ void vpar_InitFIFO( vpar_thread_t * p_vpar ) } #endif } + -- 2.39.5