X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=plugins%2Fspudec%2Fspu_decoder.c;h=ac68502651bead054eff8c6a10334229fecbe41d;hb=660db6d87715f5b677edbb8fddd071ad236511eb;hp=b0c0a7838de4bcd99d53bcdae2e45318f4326251;hpb=69c174d7ed52b49b7c97c043c545d0f1c6d4262f;p=vlc diff --git a/plugins/spudec/spu_decoder.c b/plugins/spudec/spu_decoder.c index b0c0a7838d..ac68502651 100644 --- a/plugins/spudec/spu_decoder.c +++ b/plugins/spudec/spu_decoder.c @@ -2,9 +2,10 @@ * spu_decoder.c : spu decoder thread ***************************************************************************** * Copyright (C) 2000-2001 VideoLAN - * $Id: spu_decoder.c,v 1.17 2002/04/23 22:07:05 gbazin Exp $ + * $Id: spu_decoder.c,v 1.29 2002/06/27 19:46:32 sam Exp $ * * Authors: Samuel Hocevar + * Rudolf Cornelissen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,7 +28,9 @@ #include /* malloc(), free() */ #include /* memcpy(), memset() */ -#include +#include +#include +#include #ifdef HAVE_UNISTD_H # include /* getpid() */ @@ -37,19 +40,13 @@ # include #endif -#include "video.h" -#include "video_output.h" - -#include "stream_control.h" -#include "input_ext-dec.h" - #include "spu_decoder.h" /***************************************************************************** * Local prototypes *****************************************************************************/ static int decoder_Probe ( u8 * ); -static int decoder_Run ( decoder_config_t * ); +static int decoder_Run ( decoder_fifo_t * ); static int InitThread ( spudec_thread_t * ); static void EndThread ( spudec_thread_t * ); @@ -57,7 +54,7 @@ static int SyncPacket ( spudec_thread_t * ); static void ParsePacket ( spudec_thread_t * ); static int ParseControlSequences( spudec_thread_t *, subpicture_t * ); static int ParseRLE ( spudec_thread_t *, subpicture_t *, u8 * ); -static void RenderSPU ( const vout_thread_t *, picture_t *, +static void RenderSPU ( vout_thread_t *, picture_t *, const subpicture_t * ); /***************************************************************************** @@ -101,29 +98,25 @@ static int decoder_Probe( u8 *pi_type ) /***************************************************************************** * decoder_Run: this function is called just after the thread is created *****************************************************************************/ -static int decoder_Run( decoder_config_t * p_config ) +static int decoder_Run( decoder_fifo_t * p_fifo ) { spudec_thread_t * p_spudec; - intf_WarnMsg( 3, "spudec: thread launched. Initializing ..." ); - /* Allocate the memory needed to store the thread's structure */ p_spudec = (spudec_thread_t *)malloc( sizeof(spudec_thread_t) ); if ( p_spudec == NULL ) { - intf_ErrMsg( "spudec error: not enough memory " - "for spudec_CreateThread() to create the new thread" ); - DecoderError( p_config->p_decoder_fifo ); + msg_Err( p_fifo, "out of memory" ); + DecoderError( p_fifo ); return( -1 ); } /* * Initialize the thread properties */ - p_spudec->p_config = p_config; - - p_spudec->p_fifo = p_config->p_decoder_fifo; + p_spudec->p_vout = NULL; + p_spudec->p_fifo = p_fifo; /* * Initialize thread and free configuration @@ -148,18 +141,15 @@ static int decoder_Run( decoder_config_t * p_config ) if( p_spudec->p_fifo->b_error ) { DecoderError( p_spudec->p_fifo ); + + /* End of thread */ + EndThread( p_spudec ); + return -1; } /* End of thread */ EndThread( p_spudec ); - - if( p_spudec->p_fifo->b_error ) - { - return( -1 ); - } - - return( 0 ); - + return 0; } /* following functions are local */ @@ -174,29 +164,29 @@ static int decoder_Run( decoder_config_t * p_config ) static int InitThread( spudec_thread_t *p_spudec ) { /* Find an available video output */ - vlc_mutex_lock( &p_vout_bank->lock ); - - while( p_vout_bank->i_count == 0 ) + do { - vlc_mutex_unlock( &p_vout_bank->lock ); - if( p_spudec->p_fifo->b_die || p_spudec->p_fifo->b_error ) { - return( -1 ); + return -1; + } + + p_spudec->p_vout = vlc_object_find( p_spudec->p_fifo, VLC_OBJECT_VOUT, + FIND_ANYWHERE ); + + if( p_spudec->p_vout ) + { + break; } msleep( VOUT_OUTMEM_SLEEP ); - vlc_mutex_lock( &p_vout_bank->lock ); } + while( 1 ); - /* Take the first video output FIXME: take the best one */ - p_spudec->p_vout = p_vout_bank->pp_vout[ 0 ]; - vlc_mutex_unlock( &p_vout_bank->lock ); - InitBitstream( &p_spudec->bit_stream, - p_spudec->p_config->p_decoder_fifo, NULL, NULL ); + InitBitstream( &p_spudec->bit_stream, p_spudec->p_fifo, NULL, NULL ); /* Mark thread as running and return */ - return( 0 ); + return 0; } /***************************************************************************** @@ -207,6 +197,27 @@ static int InitThread( spudec_thread_t *p_spudec ) *****************************************************************************/ static void EndThread( spudec_thread_t *p_spudec ) { + if( p_spudec->p_vout != NULL + && p_spudec->p_vout->p_subpicture != NULL ) + { + subpicture_t * p_subpic; + int i_subpic; + + for( i_subpic = 0; i_subpic < VOUT_MAX_SUBPICTURES; i_subpic++ ) + { + p_subpic = &p_spudec->p_vout->p_subpicture[i_subpic]; + + if( p_subpic != NULL && + ( ( p_subpic->i_status == RESERVED_SUBPICTURE ) + || ( p_subpic->i_status == READY_SUBPICTURE ) ) ) + { + vout_DestroySubPicture( p_spudec->p_vout, p_subpic ); + } + } + + vlc_object_release( p_spudec->p_vout ); + } + free( p_spudec ); } @@ -251,19 +262,19 @@ static void ParsePacket( spudec_thread_t *p_spudec ) u8 * p_src; unsigned int i_offset; - intf_WarnMsg( 3, "spudec: trying to gather a 0x%.2x long subtitle", - p_spudec->i_spu_size ); + msg_Dbg( p_spudec->p_fifo, "trying to gather a 0x%.2x long subtitle", + p_spudec->i_spu_size ); /* We cannot display a subpicture with no date */ if( p_spudec->p_fifo->p_first->i_pts == 0 ) { - intf_WarnMsg( 3, "spudec error: subtitle without a date" ); + msg_Warn( p_spudec->p_fifo, "subtitle without a date" ); return; } /* Allocate the subpicture internal data. */ p_spu = vout_CreateSubPicture( p_spudec->p_vout, MEMORY_SUBPICTURE, - sizeof( struct subpicture_sys_s ) + sizeof( subpicture_sys_t ) + p_spudec->i_rle_size * 4 ); /* Rationale for the "p_spudec->i_rle_size * 4": we are going to * expand the RLE stuff so that we won't need to read nibbles later @@ -277,8 +288,7 @@ static void ParsePacket( spudec_thread_t *p_spudec ) /* Fill the p_spu structure */ p_spu->pf_render = RenderSPU; - p_spu->p_sys->p_data = (u8*)p_spu->p_sys - + sizeof( struct subpicture_sys_s ); + p_spu->p_sys->p_data = (u8*)p_spu->p_sys + sizeof( subpicture_sys_t ); p_spu->p_sys->b_palette = 0; /* Get display time now. If we do it later, we may miss the PTS. */ @@ -289,17 +299,18 @@ static void ParsePacket( spudec_thread_t *p_spudec ) if( p_src == NULL ) { - intf_ErrMsg( "spudec error: could not allocate p_src" ); + msg_Err( p_spudec->p_fifo, "out of memory" ); vout_DestroySubPicture( p_spudec->p_vout, p_spu ); return; } /* Get RLE data */ - for( i_offset = 0; - i_offset + SPU_CHUNK_SIZE < p_spudec->i_rle_size; + for( i_offset = 0; i_offset < p_spudec->i_rle_size; i_offset += SPU_CHUNK_SIZE ) { - GetChunk( &p_spudec->bit_stream, p_src + i_offset, SPU_CHUNK_SIZE ); + GetChunk( &p_spudec->bit_stream, p_src + i_offset, + ( i_offset + SPU_CHUNK_SIZE < p_spudec->i_rle_size ) ? + SPU_CHUNK_SIZE : p_spudec->i_rle_size - i_offset ); /* Abort subtitle parsing if we were requested to stop */ if( p_spudec->p_fifo->b_die ) @@ -310,9 +321,6 @@ static void ParsePacket( spudec_thread_t *p_spudec ) } } - GetChunk( &p_spudec->bit_stream, p_src + i_offset, - p_spudec->i_rle_size - i_offset ); - #if 0 /* Dump the subtitle info */ intf_WarnHexDump( 5, p_spu->p_sys->p_data, p_spudec->i_rle_size ); @@ -339,9 +347,9 @@ static void ParsePacket( spudec_thread_t *p_spudec ) return; } - intf_WarnMsg( 3, "spudec: total size: 0x%x, RLE offsets: 0x%x 0x%x", - p_spudec->i_spu_size, - p_spu->p_sys->pi_offset[0], p_spu->p_sys->pi_offset[1] ); + msg_Dbg( p_spudec->p_fifo, "total size: 0x%x, RLE offsets: 0x%x 0x%x", + p_spudec->i_spu_size, + p_spu->p_sys->pi_offset[0], p_spu->p_sys->pi_offset[1] ); /* SPU is finished - we can ask the video output to display it */ vout_DisplaySubPicture( p_spudec->p_vout, p_spu ); @@ -370,12 +378,10 @@ static int ParseControlSequences( spudec_thread_t *p_spudec, u8 i_command; int i_date; - /* Dummy stuff */ - u8 *pi_color; - int i; + int i, pi_alpha[4]; /* XXX: temporary variables */ - boolean_t b_force_display = 0; + vlc_bool_t b_force_display = 0; /* Initialize the structure */ p_spu->i_start = p_spu->i_stop = 0; @@ -426,18 +432,28 @@ static int ParseControlSequences( spudec_thread_t *p_spudec, case SPU_CMD_SET_PALETTE: /* 03xxxx (palette) */ - if( p_spudec->p_config->p_demux_data && - *(int*)p_spudec->p_config->p_demux_data == 0xBeeF ) + if( p_spudec->p_fifo->p_demux_data && + *(int*)p_spudec->p_fifo->p_demux_data == 0xBeeF ) { + u32 i_color; + p_spu->p_sys->b_palette = 1; for( i = 0; i < 4 ; i++ ) { - pi_color = (void*)p_spudec->p_config->p_demux_data - + sizeof(int) + 4 * sizeof(u8) * - GetBits( &p_spudec->bit_stream, 4 ); - p_spu->p_sys->pi_yuv[3-i][0] = pi_color[2]; - p_spu->p_sys->pi_yuv[3-i][1] = pi_color[0]; - p_spu->p_sys->pi_yuv[3-i][2] = pi_color[1]; + i_color = ((u32*)((char*)p_spudec->p_fifo-> + p_demux_data + sizeof(int)))[ + GetBits(&p_spudec->bit_stream, 4) ]; + + /* FIXME: this job should be done sooner */ +#ifndef WORDS_BIGENDIAN + p_spu->p_sys->pi_yuv[3-i][0] = (i_color>>16) & 0xff; + p_spu->p_sys->pi_yuv[3-i][1] = (i_color>>0) & 0xff; + p_spu->p_sys->pi_yuv[3-i][2] = (i_color>>8) & 0xff; +#else + p_spu->p_sys->pi_yuv[3-i][0] = (i_color>>8) & 0xff; + p_spu->p_sys->pi_yuv[3-i][1] = (i_color>>24) & 0xff; + p_spu->p_sys->pi_yuv[3-i][2] = (i_color>>16) & 0xff; +#endif } } else @@ -451,11 +467,26 @@ static int ParseControlSequences( spudec_thread_t *p_spudec, case SPU_CMD_SET_ALPHACHANNEL: /* 04xxxx (alpha channel) */ - for( i = 0; i < 4 ; i++ ) + pi_alpha[3] = GetBits( &p_spudec->bit_stream, 4 ); + pi_alpha[2] = GetBits( &p_spudec->bit_stream, 4 ); + pi_alpha[1] = GetBits( &p_spudec->bit_stream, 4 ); + pi_alpha[0] = GetBits( &p_spudec->bit_stream, 4 ); + + /* Ignore blank alpha palette. Sometimes spurious blank + * alpha palettes are present - dunno why. */ + if( pi_alpha[0] | pi_alpha[1] | pi_alpha[2] | pi_alpha[3] ) { - p_spu->p_sys->pi_alpha[3-i] - = GetBits( &p_spudec->bit_stream, 4 ); + p_spu->p_sys->pi_alpha[0] = pi_alpha[0]; + p_spu->p_sys->pi_alpha[1] = pi_alpha[1]; + p_spu->p_sys->pi_alpha[2] = pi_alpha[2]; + p_spu->p_sys->pi_alpha[3] = pi_alpha[3]; } + else + { + msg_Warn( p_spudec->p_fifo, + "ignoring blank alpha palette" ); + } + i_index += 2; break; @@ -496,8 +527,8 @@ static int ParseControlSequences( spudec_thread_t *p_spudec, default: /* xx (unknown command) */ - intf_ErrMsg( "spudec error: unknown command 0x%.2x", - i_command ); + msg_Err( p_spudec->p_fifo, "unknown command 0x%.2x", + i_command ); return( 1 ); } @@ -514,21 +545,21 @@ static int ParseControlSequences( spudec_thread_t *p_spudec, /* Check that the next sequence index matches the current one */ if( i_next_seq != i_cur_seq ) { - intf_ErrMsg( "spudec error: index mismatch (0x%.4x != 0x%.4x)", - i_next_seq, i_cur_seq ); + msg_Err( p_spudec->p_fifo, "index mismatch (0x%.4x != 0x%.4x)", + i_next_seq, i_cur_seq ); return( 1 ); } if( i_index > p_spudec->i_spu_size ) { - intf_ErrMsg( "spudec error: uh-oh, we went too far (0x%.4x > 0x%.4x)", - i_index, p_spudec->i_spu_size ); + msg_Err( p_spudec->p_fifo, "uh-oh, we went too far (0x%.4x > 0x%.4x)", + i_index, p_spudec->i_spu_size ); return( 1 ); } if( !p_spu->i_start ) { - intf_ErrMsg( "spudec error: no `start display' command" ); + msg_Err( p_spudec->p_fifo, "no `start display' command" ); } if( !p_spu->i_stop ) @@ -551,9 +582,9 @@ static int ParseControlSequences( spudec_thread_t *p_spudec, /* More than one padding byte - this is very strange, but * we can deal with it */ default: - intf_WarnMsg( 2, "spudec warning: %i padding bytes, we usually " - "get 0 or 1 of them", - p_spudec->i_spu_size - i_index ); + msg_Warn( p_spudec->p_fifo, + "%i padding bytes, we usually get 0 or 1 of them", + p_spudec->i_spu_size - i_index ); while( i_index < p_spudec->i_spu_size ) { @@ -566,9 +597,9 @@ static int ParseControlSequences( spudec_thread_t *p_spudec, if( b_force_display ) { - intf_ErrMsg( "spudec: \"force display\" command" ); - intf_ErrMsg( "spudec: send mail to if you " - "want to help debugging this" ); + msg_Err( p_spudec->p_fifo, "\"force display\" command" ); + msg_Err( p_spudec->p_fifo, "send mail to if you " + "want to help debugging this" ); } /* Successfully parsed ! */ @@ -598,8 +629,8 @@ static int ParseRLE( spudec_thread_t *p_spudec, unsigned int pi_table[ 2 ]; unsigned int *pi_offset; - boolean_t b_empty_top = 1, - b_empty_bottom = 0; + vlc_bool_t b_empty_top = 1, + b_empty_bottom = 0; unsigned int i_skipped_top = 0, i_skipped_bottom = 0; @@ -641,8 +672,8 @@ static int ParseRLE( spudec_thread_t *p_spudec, else { /* We have a boo boo ! */ - intf_ErrMsg( "spudec error: unknown RLE code " - "0x%.4x", i_code ); + msg_Err( p_spudec->p_fifo, "unknown RLE code " + "0x%.4x", i_code ); return( 1 ); } } @@ -652,9 +683,9 @@ static int ParseRLE( spudec_thread_t *p_spudec, if( ( (i_code >> 2) + i_x + i_y * i_width ) > i_height * i_width ) { - intf_ErrMsg( "spudec error: out of bounds, %i at (%i,%i) is " - "out of %ix%i", - i_code >> 2, i_x, i_y, i_width, i_height ); + msg_Err( p_spudec->p_fifo, + "out of bounds, %i at (%i,%i) is out of %ix%i", + i_code >> 2, i_x, i_y, i_width, i_height ); return( 1 ); } @@ -698,8 +729,8 @@ static int ParseRLE( spudec_thread_t *p_spudec, /* Check that we didn't go too far */ if( i_x > i_width ) { - intf_ErrMsg( "spudec error: i_x overflowed, %i > %i", - i_x, i_width ); + msg_Err( p_spudec->p_fifo, "i_x overflowed, %i > %i", + i_x, i_width ); return( 1 ); } @@ -716,9 +747,9 @@ static int ParseRLE( spudec_thread_t *p_spudec, /* We shouldn't get any padding bytes */ if( i_y < i_height ) { - intf_ErrMsg( "spudec: padding bytes found in RLE sequence" ); - intf_ErrMsg( "spudec: send mail to if you " - "want to help debugging this" ); + msg_Err( p_spudec->p_fifo, "padding bytes found in RLE sequence" ); + msg_Err( p_spudec->p_fifo, "send mail to if you " + "want to help debugging this" ); /* Skip them just in case */ while( i_y < i_height ) @@ -730,8 +761,8 @@ static int ParseRLE( spudec_thread_t *p_spudec, return( 1 ); } - intf_WarnMsg( 3, "spudec: valid subtitle, size: %ix%i, position: %i,%i", - p_spu->i_width, p_spu->i_height, p_spu->i_x, p_spu->i_y ); + msg_Dbg( p_spudec->p_fifo, "valid subtitle, size: %ix%i, position: %i,%i", + p_spu->i_width, p_spu->i_height, p_spu->i_x, p_spu->i_y ); /* Crop if necessary */ if( i_skipped_top || i_skipped_bottom ) @@ -739,8 +770,8 @@ static int ParseRLE( spudec_thread_t *p_spudec, p_spu->i_y += i_skipped_top; p_spu->i_height -= i_skipped_top + i_skipped_bottom; - intf_WarnMsg( 3, "spudec: cropped to: %ix%i, position: %i,%i", - p_spu->i_width, p_spu->i_height, p_spu->i_x, p_spu->i_y ); + msg_Dbg( p_spudec->p_fifo, "cropped to: %ix%i, position: %i,%i", + p_spu->i_width, p_spu->i_height, p_spu->i_x, p_spu->i_y ); } /* Handle color if no palette was found */ @@ -795,8 +826,9 @@ static int ParseRLE( spudec_thread_t *p_spudec, p_spu->p_sys->pi_yuv[i_shade][2] = 0x80; } - intf_WarnMsg( 3, "spudec: using custom palette (border %i, inner %i, " - "shade %i)", i_border, i_inner, i_shade ); + msg_Dbg( p_spudec->p_fifo, + "using custom palette (border %i, inner %i, shade %i)", + i_border, i_inner, i_shade ); } return( 0 ); @@ -810,17 +842,19 @@ static int ParseRLE( spudec_thread_t *p_spudec, * and again. Most sanity checks are already done so that this routine can be * as fast as possible. *****************************************************************************/ -static void RenderSPU( const vout_thread_t *p_vout, picture_t *p_pic, +static void RenderSPU( vout_thread_t *p_vout, picture_t *p_pic, const subpicture_t *p_spu ) { /* Common variables */ u16 p_clut16[4]; u32 p_clut32[4]; u8 *p_dest; + u8 *p_destptr = (u8 *)p_dest; u16 *p_source = (u16 *)p_spu->p_sys->p_data; int i_x, i_y; - int i_len, i_color; + int i_len, i_color, i_colprecomp, i_destalpha; + u8 i_cnt; /* RGB-specific */ int i_xscale, i_yscale, i_width, i_height, i_ytmp, i_yreal, i_ynext; @@ -845,28 +879,37 @@ static void RenderSPU( const vout_thread_t *p_vout, picture_t *p_pic, { /* Get the RLE part, then draw the line */ i_color = *p_source & 0x3; + i_len = *p_source++ >> 2; switch( p_spu->p_sys->pi_alpha[ i_color ] ) { case 0x00: - i_x -= *p_source++ >> 2; break; case 0x0f: - i_len = *p_source++ >> 2; memset( p_dest - i_x - i_y, p_spu->p_sys->pi_yuv[i_color][0], i_len ); - i_x -= i_len; break; default: - /* FIXME: we should do transparency */ - i_len = *p_source++ >> 2; - memset( p_dest - i_x - i_y, - p_spu->p_sys->pi_yuv[i_color][0], i_len ); - i_x -= i_len; + /* To be able to divide by 16 (>>4) we add 1 to the alpha. + * This means Alpha 0 won't be completely transparent, but + * that's handled in a special case above anyway. */ + i_colprecomp = p_spu->p_sys->pi_yuv[i_color][0] + * (p_spu->p_sys->pi_alpha[ i_color ] + 1); + i_destalpha = 15 - p_spu->p_sys->pi_alpha[ i_color ]; + + for ( p_destptr = p_dest - i_x - i_y; + p_destptr < p_dest - i_x - i_y + i_len; + p_destptr++ ) + { + *p_destptr = ( i_colprecomp + + *p_destptr * i_destalpha ) >> 4; + } break; + } + i_x -= i_len; } } @@ -875,6 +918,7 @@ static void RenderSPU( const vout_thread_t *p_vout, picture_t *p_pic, /* RV16 target, scaling */ case FOURCC_RV16: + /* XXX: this is a COMPLETE HACK, memcpy is unable to do u16s anyway */ /* FIXME: get this from the DVD */ for( i_color = 0; i_color < 4; i_color++ ) { @@ -891,7 +935,7 @@ static void RenderSPU( const vout_thread_t *p_vout, picture_t *p_pic, p_dest = p_pic->p->p_pixels + ( i_width >> 6 ) * 2 /* Add the picture coordinates and the SPU coordinates */ + ( (p_spu->i_x * i_xscale) >> 6 ) * 2 - + ( (p_spu->i_y * i_yscale) >> 6 ) * p_vout->output.i_width * 2; + + ( (p_spu->i_y * i_yscale) >> 6 ) * p_pic->p->i_pitch; /* Draw until we reach the bottom of the subtitle */ for( i_y = 0 ; i_y < i_height ; ) @@ -903,7 +947,7 @@ static void RenderSPU( const vout_thread_t *p_vout, picture_t *p_pic, if( i_ytmp + 1 >= ( i_y >> 6 ) ) { /* Just one line : we precalculate i_y >> 6 */ - i_yreal = p_vout->output.i_width * 2 * i_ytmp; + i_yreal = p_pic->p->i_pitch * i_ytmp; /* Draw until we reach the end of the line */ for( i_x = i_width ; i_x ; ) @@ -939,8 +983,8 @@ static void RenderSPU( const vout_thread_t *p_vout, picture_t *p_pic, } else { - i_yreal = p_vout->output.i_width * 2 * i_ytmp; - i_ynext = p_vout->output.i_width * 2 * i_y >> 6; + i_yreal = p_pic->p->i_pitch * i_ytmp; + i_ynext = p_pic->p->i_pitch * i_y >> 6; /* Draw until we reach the end of the line */ for( i_x = i_width ; i_x ; ) @@ -957,7 +1001,7 @@ static void RenderSPU( const vout_thread_t *p_vout, picture_t *p_pic, case 0x0f: i_len = i_xscale * ( *p_source++ >> 2 ); for( i_ytmp = i_yreal ; i_ytmp < i_ynext ; - i_ytmp += p_vout->output.i_width * 2 ) + i_ytmp += p_pic->p->i_pitch ) { memset( p_dest - 2 * ( i_x >> 6 ) + i_ytmp, p_clut16[ i_color ], @@ -970,7 +1014,7 @@ static void RenderSPU( const vout_thread_t *p_vout, picture_t *p_pic, /* FIXME: we should do transparency */ i_len = i_xscale * ( *p_source++ >> 2 ); for( i_ytmp = i_yreal ; i_ytmp < i_ynext ; - i_ytmp += p_vout->output.i_width * 2 ) + i_ytmp += p_pic->p->i_pitch ) { memset( p_dest - 2 * ( i_x >> 6 ) + i_ytmp, p_clut16[ i_color ], @@ -1006,7 +1050,7 @@ static void RenderSPU( const vout_thread_t *p_vout, picture_t *p_pic, p_dest = p_pic->p->p_pixels + ( i_width >> 6 ) * 4 /* Add the picture coordinates and the SPU coordinates */ + ( (p_spu->i_x * i_xscale) >> 6 ) * 4 - + ( (p_spu->i_y * i_yscale) >> 6 ) * p_vout->output.i_width * 4; + + ( (p_spu->i_y * i_yscale) >> 6 ) * p_pic->p->i_pitch; /* Draw until we reach the bottom of the subtitle */ for( i_y = 0 ; i_y < i_height ; ) @@ -1018,7 +1062,7 @@ static void RenderSPU( const vout_thread_t *p_vout, picture_t *p_pic, if( i_ytmp + 1 >= ( i_y >> 6 ) ) { /* Just one line : we precalculate i_y >> 6 */ - i_yreal = p_vout->output.i_width * 4 * i_ytmp; + i_yreal = p_pic->p->i_pitch * i_ytmp; /* Draw until we reach the end of the line */ for( i_x = i_width ; i_x ; ) @@ -1052,8 +1096,8 @@ static void RenderSPU( const vout_thread_t *p_vout, picture_t *p_pic, } else { - i_yreal = p_vout->output.i_width * 4 * i_ytmp; - i_ynext = p_vout->output.i_width * 4 * i_y >> 6; + i_yreal = p_pic->p->i_pitch * i_ytmp; + i_ynext = p_pic->p->i_pitch * i_y >> 6; /* Draw until we reach the end of the line */ for( i_x = i_width ; i_x ; ) @@ -1070,7 +1114,7 @@ static void RenderSPU( const vout_thread_t *p_vout, picture_t *p_pic, case 0x0f: i_len = i_xscale * ( *p_source++ >> 2 ); for( i_ytmp = i_yreal ; i_ytmp < i_ynext ; - i_ytmp += p_vout->output.i_width * 4 ) + i_ytmp += p_pic->p->i_pitch ) { memset( p_dest - 4 * ( i_x >> 6 ) + i_ytmp, p_clut32[ i_color ], @@ -1083,7 +1127,7 @@ static void RenderSPU( const vout_thread_t *p_vout, picture_t *p_pic, /* FIXME: we should do transparency */ i_len = i_xscale * ( *p_source++ >> 2 ); for( i_ytmp = i_yreal ; i_ytmp < i_ynext ; - i_ytmp += p_vout->output.i_width * 4 ) + i_ytmp += p_pic->p->i_pitch ) { memset( p_dest - 4 * ( i_x >> 6 ) + i_ytmp, p_clut32[ i_color ], @@ -1098,9 +1142,80 @@ static void RenderSPU( const vout_thread_t *p_vout, picture_t *p_pic, break; + /* NVidia overlay, no scaling */ + case FOURCC_YUY2: + + p_dest = p_pic->p->p_pixels + + (p_spu->i_x + p_spu->i_width + + p_vout->output.i_width * ( p_spu->i_y + p_spu->i_height )) * 2; + /* Draw until we reach the bottom of the subtitle */ + for( i_y = p_spu->i_height * p_vout->output.i_width; + i_y ; + i_y -= p_vout->output.i_width ) + { + /* Draw until we reach the end of the line */ + for( i_x = p_spu->i_width ; i_x ; ) + { + /* Get the RLE part, then draw the line */ + i_color = *p_source & 0x3; + + switch( p_spu->p_sys->pi_alpha[ i_color ] ) + { + case 0x00: + i_x -= *p_source++ >> 2; + break; + + case 0x0f: + i_len = *p_source++ >> 2; + for( i_cnt = 0; i_cnt < i_len; i_cnt++ ) + { + /* draw a pixel */ + /* Y */ + memset( p_dest - i_x * 2 - i_y * 2 + i_cnt * 2, + p_spu->p_sys->pi_yuv[i_color][0], 1); + + if (!(i_cnt & 0x01)) + { + /* U and V */ + memset( p_dest - i_x * 2 - i_y * 2 + i_cnt * 2 + 1, + 0x80, 1); + memset( p_dest - i_x * 2 - i_y * 2 + i_cnt * 2 + 3, + 0x80, 1); + } + } + i_x -= i_len; + break; + + default: + /* FIXME: we should do transparency */ + i_len = *p_source++ >> 2; + for( i_cnt = 0; i_cnt < i_len; i_cnt++ ) + { + /* draw a pixel */ + /* Y */ + memset( p_dest - i_x * 2 - i_y * 2 + i_cnt * 2, + p_spu->p_sys->pi_yuv[i_color][0], 1); + + if (!(i_cnt & 0x01)) + { + /* U and V */ + memset( p_dest - i_x * 2 - i_y * 2 + i_cnt * 2 + 1, + 0x80, 1); + memset( p_dest - i_x * 2 - i_y * 2 + i_cnt * 2 + 3, + 0x80, 1); + } + } + i_x -= i_len; + break; + } + } + } + + break; + + default: - intf_ErrMsg( "vout error: unknown chroma, can't render SPU" ); + msg_Err( p_vout, "unknown chroma, can't render SPU" ); break; } } -