Commit b1ff86e6 authored by Sam Hocevar's avatar Sam Hocevar

. les sous-titres sont affich�s et effac�s � l'heure

 . une petite optimisation de l'affichage
 . attention, config.h.in a chang�, n'oubliez pas de refaire ./configure
parent aa79cd11
......@@ -277,6 +277,9 @@
* (~1 Mbyte) before using huge values */
#define VOUT_MAX_PICTURES 10
/* Number of simultaneous subpictures */
#define VOUT_MAX_SUBPICTURES 10
/* Maximum number of active areas in a rendering buffer. Active areas are areas
* of the picture which need to be cleared before re-using the buffer. If a
* picture, including its many additions such as subtitles, additionnal user
......
......@@ -119,6 +119,7 @@ typedef struct subpicture_s
int i_type; /* type */
int i_status; /* flags */
int i_size; /* data size */
struct subpicture_s * p_next; /* next SPU to be displayed */
/* Other properties */
mtime_t begin_date; /* beginning of display date */
......
......@@ -238,15 +238,16 @@ static void RunThread( spudec_thread_t *p_spudec )
/* if the values we got aren't too strange, decode the data */
if( i_rle_size < i_packet_size )
{
/* destroy the previous one */
if( p_spu ) vout_DestroySubPicture( p_spudec->p_vout, p_spu );
/* allocate the subpicture.
* FIXME: we should check if the allocation failed */
p_spu = vout_CreateSubPicture( p_spudec->p_vout,
DVD_SUBPICTURE, i_rle_size );
p_spu_data = p_spu->p_data;
/* get display time */
p_spu->begin_date = p_spu->end_date
= DECODER_FIFO_START(p_spudec->fifo)->i_pts;
/* getting the RLE part */
while( i_index++ < i_rle_size )
{
......@@ -264,9 +265,10 @@ static void RunThread( spudec_thread_t *p_spudec )
{
unsigned char i_cmd;
unsigned int i_word;
unsigned int i_date;
/* the date */
GetWord( i_word );
GetWord( i_date );
/* next offset, no next offset if == i_index-5 */
GetWord( i_word );
......@@ -280,14 +282,16 @@ static void RunThread( spudec_thread_t *p_spudec )
switch( i_cmd )
{
case 0x00:
/* 00 (display now) */
/* 00 (force displaying) */
break;
case 0x01:
/* 01 (start displaying) */
break;
p_spu->begin_date += (i_date * 1000000 / 80);
break; /* FIXME: 80 is absolutely empiric */
case 0x02:
/* 02 (stop displaying) */
break;
p_spu->end_date += (i_date * 1000000 / 80);
break; /* FIXME: 80 is absolutely empiric */
case 0x03:
/* 03xxxx (palette) */
GetWord( i_word );
......@@ -299,13 +303,21 @@ static void RunThread( spudec_thread_t *p_spudec )
case 0x05:
/* 05xxxyyyxxxyyy (coordinates) */
i_word = GetByte( &p_spudec->bit_stream );
p_spu->type.spu.i_x1 = (i_word << 4) | GetBits( &p_spudec->bit_stream, 4 );
p_spu->type.spu.i_x1 = (i_word << 4)
| GetBits( &p_spudec->bit_stream, 4 );
i_word = GetBits( &p_spudec->bit_stream, 4 );
p_spu->type.spu.i_x2 = (i_word << 8) | GetByte( &p_spudec->bit_stream );
p_spu->type.spu.i_x2 = (i_word << 8)
| GetByte( &p_spudec->bit_stream );
i_word = GetByte( &p_spudec->bit_stream );
p_spu->type.spu.i_y1 = (i_word << 4) | GetBits( &p_spudec->bit_stream, 4 );
p_spu->type.spu.i_y1 = (i_word << 4)
| GetBits( &p_spudec->bit_stream, 4 );
i_word = GetBits( &p_spudec->bit_stream, 4 );
p_spu->type.spu.i_y2 = (i_word << 8) | GetByte( &p_spudec->bit_stream );
p_spu->type.spu.i_y2 = (i_word << 8)
| GetByte( &p_spudec->bit_stream );
i_index += 6;
break;
case 0x06:
......
......@@ -171,6 +171,9 @@ vout_thread_t * vout_CreateThread ( char *psz_display, int i_root_window,
{
p_vout->p_picture[i_index].i_type = EMPTY_PICTURE;
p_vout->p_picture[i_index].i_status = FREE_PICTURE;
}
for( i_index = 0; i_index < VOUT_MAX_SUBPICTURES; i_index++)
{
p_vout->p_subpicture[i_index].i_type = EMPTY_SUBPICTURE;
p_vout->p_subpicture[i_index].i_status= FREE_SUBPICTURE;
}
......@@ -353,7 +356,7 @@ subpicture_t *vout_CreateSubPicture( vout_thread_t *p_vout, int i_type,
/*
* Look for an empty place
*/
for( i_subpic = 0; i_subpic < VOUT_MAX_PICTURES; i_subpic++ )
for( i_subpic = 0; i_subpic < VOUT_MAX_SUBPICTURES; i_subpic++ )
{
if( p_vout->p_subpicture[i_subpic].i_status == DESTROYED_SUBPICTURE )
{
......@@ -981,8 +984,8 @@ last_display_date = display_date;
#if 1
if( display_date < current_date && i_trash_count > 4 )
{
/* Picture is late: it will be destroyed and the thread will sleep and
* go to next picture */
/* Picture is late: it will be destroyed and the thread
* will sleep and go to next picture */
vlc_mutex_lock( &p_vout->picture_lock );
if( p_pic->i_refcount )
......@@ -1026,16 +1029,16 @@ last_display_date = display_date;
/*
* Find the subpictures to display - this operation does not need
* lock, since only READY_SUBPICTURE are handled. If no picture
* has been selected, display_date will depend on the subpicture
* has been selected, display_date will depend on the subpicture.
* We get an easily parsable chained list of subpictures which
* ends with NULL since p_subpic was initialized to NULL.
*/
/* FIXME: we should find *all* subpictures to display, and
* check their displaying date as well */
for( i_index = 0; i_index < VOUT_MAX_PICTURES; i_index++ )
for( i_index = 0; i_index < VOUT_MAX_SUBPICTURES; i_index++ )
{
if( p_vout->p_subpicture[i_index].i_status == READY_SUBPICTURE )
{
p_vout->p_subpicture[i_index].p_next = p_subpic;
p_subpic = &p_vout->p_subpicture[i_index];
break;
}
}
......@@ -1249,6 +1252,9 @@ static void EndThread( vout_thread_t *p_vout )
{
free( p_vout->p_picture[i_index].p_data );
}
}
for( i_index = 0; i_index < VOUT_MAX_SUBPICTURES; i_index++ )
{
if( p_vout->p_subpicture[i_index].i_status != FREE_SUBPICTURE )
{
free( p_vout->p_subpicture[i_index].p_data );
......@@ -1828,43 +1834,67 @@ static void RenderSubPicture( vout_thread_t *p_vout, subpicture_t *p_subpic )
p_vout_font_t p_font; /* text font */
int i_width, i_height; /* subpicture dimensions */
switch( p_subpic->i_type )
while( p_subpic != NULL )
{
case DVD_SUBPICTURE: /* DVD subpicture unit */
vout_RenderSPU( p_subpic->p_data, p_subpic->type.spu.i_offset,
p_subpic->type.spu.i_x1, p_subpic->type.spu.i_y1,
p_vout->p_buffer[ p_vout->i_buffer_index ].p_data,
p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line );
break;
case TEXT_SUBPICTURE: /* single line text */
/* Select default font if not specified */
p_font = p_subpic->type.text.p_font;
if( p_font == NULL )
switch( p_subpic->i_type )
{
p_font = p_vout->p_default_font;
}
case DVD_SUBPICTURE: /* DVD subpicture unit */
/* test if the picture really has to be displayed */
if( mdate() < p_subpic->begin_date )
{
break;
}
if( mdate() > p_subpic->end_date )
{
/* too late, destroying the subpic */
vout_DestroySubPicture( p_vout, p_subpic );
printf( "destroying subpicture\n" );
break;
}
vout_RenderSPU( p_subpic->p_data, p_subpic->type.spu.i_offset,
p_subpic->type.spu.i_x1, p_subpic->type.spu.i_y1,
p_vout->p_buffer[ p_vout->i_buffer_index ].p_data,
p_vout->i_bytes_per_pixel,
p_vout->i_bytes_per_line );
break;
case TEXT_SUBPICTURE: /* single line text */
/* Select default font if not specified */
p_font = p_subpic->type.text.p_font;
if( p_font == NULL )
{
p_font = p_vout->p_default_font;
}
/* Compute text size (width and height fields are ignored)
* and print it */
vout_TextSize( p_font, p_subpic->type.text.i_style, p_subpic->p_data, &i_width, &i_height );
if( !Align( p_vout, &p_subpic->i_x, &p_subpic->i_y, i_width, i_height,
p_subpic->i_horizontal_align, p_subpic->i_vertical_align ) )
{
vout_Print( p_font, p_vout->p_buffer[ p_vout->i_buffer_index ].p_data +
p_subpic->i_x * p_vout->i_bytes_per_pixel +
p_subpic->i_y * p_vout->i_bytes_per_line,
p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line,
p_subpic->type.text.i_char_color, p_subpic->type.text.i_border_color,
p_subpic->type.text.i_bg_color, p_subpic->type.text.i_style,
p_subpic->p_data );
SetBufferArea( p_vout, p_subpic->i_x, p_subpic->i_y, i_width, i_height );
}
break;
/* Compute text size (width and height fields are ignored)
* and print it */
vout_TextSize( p_font, p_subpic->type.text.i_style,
p_subpic->p_data, &i_width, &i_height );
if( !Align( p_vout, &p_subpic->i_x, &p_subpic->i_y,
i_width, i_height, p_subpic->i_horizontal_align,
p_subpic->i_vertical_align ) )
{
vout_Print( p_font,
p_vout->p_buffer[ p_vout->i_buffer_index ].p_data +
p_subpic->i_x * p_vout->i_bytes_per_pixel +
p_subpic->i_y * p_vout->i_bytes_per_line,
p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line,
p_subpic->type.text.i_char_color,
p_subpic->type.text.i_border_color,
p_subpic->type.text.i_bg_color,
p_subpic->type.text.i_style, p_subpic->p_data );
SetBufferArea( p_vout, p_subpic->i_x, p_subpic->i_y,
i_width, i_height );
}
break;
#ifdef DEBUG
default:
intf_DbgMsg("error: unknown subpicture %p type %d\n", p_subpic, p_subpic->i_type );
default:
intf_DbgMsg( "error: unknown subpicture %p type %d\n",
p_subpic, p_subpic->i_type );
#endif
}
p_subpic = p_subpic->p_next;
}
}
......
......@@ -47,7 +47,6 @@ typedef struct spu_s
} spu_t;
static int NewLine ( spu_t *p_spu, int *i_id );
static int PutPixel ( spu_t *p_spu, int len, u8 color );
/* i = get_nibble(); */
#define GET_NIBBLE( i ) \
......@@ -95,6 +94,9 @@ void vout_RenderSPU( byte_t *p_data, int p_offset[2],
int i_code = 0x00;
int i_next = 0;
int i_id = 0;
int i_color;
static int p_palette[4] = { 0x0000, 0xffff, 0x5555, 0x0000 };
boolean_t b_aligned = 1;
byte_t *p_from[2];
spu_t spu;
......@@ -108,15 +110,33 @@ void vout_RenderSPU( byte_t *p_data, int p_offset[2],
spu.height = 576;
spu.p_data = p_pic + i_x * i_bytes_per_pixel + i_y * i_bytes_per_line;
while( p_from[0] < p_data + p_offset[1] + 2 )
while( p_from[0] < p_data + p_offset[1] )
{
GET_NIBBLE( i_code );
if( i_code >= 0x04 )
{
found_code:
if( PutPixel( &spu, i_code >> 2, i_code & 3 ) < 0 )
if( ((i_code >> 2) + spu.x + spu.y * spu.width)
> spu.height * spu.width )
{
intf_DbgMsg ( "video_spu: invalid draw request ! %d %d\n",
i_code >> 2, spu.height * spu.width
- ( (i_code >> 2) + spu.x
+ spu.y * spu.width ) );
return;
}
else
{
if( (i_color = i_code & 0x3) )
{
u8 *p_target = &spu.p_data[ 2 *
( spu.x + spu.y * spu.width ) ];
memset( p_target, p_palette[i_color], 2 * (i_code >> 2) );
}
spu.x += i_code >> 2;
}
if( spu.x >= spu.width )
{
......@@ -164,45 +184,12 @@ void vout_RenderSPU( byte_t *p_data, int p_offset[2],
static int NewLine( spu_t *p_spu, int *i_id )
{
int i_ret = PutPixel( p_spu, p_spu->width - p_spu->x, 0 );
*i_id = 1 - *i_id;
p_spu->x = 0;
p_spu->y++;
*i_id = 1 - *i_id;
return i_ret;
}
static int PutPixel ( spu_t *p_spu, int i_len, u8 i_color )
{
//static int p_palette[4] = { 0x0000, 0xfef8, 0x7777, 0xffff };
static int p_palette[4] = { 0x0000, 0xffff, 0x5555, 0x0000 };
if( (i_len + p_spu->x + p_spu->y * p_spu->width)
> p_spu->height * p_spu->width )
{
intf_DbgMsg ( "video_spu: trying to draw beyond memory area! %d %d\n",
i_len, p_spu->height * p_spu->width
- ( i_len + p_spu->x + p_spu->y * p_spu->width) );
p_spu->x += i_len;
return -1;
}
else
{
if( i_color > 0x0f )
intf_DbgMsg( "video_spu: invalid color\n" );
if( i_color )
{
u8 *p_target
= &p_spu->p_data[2 * ( p_spu->x + p_spu->y * p_spu->width ) ];
memset( p_target, p_palette[i_color], 2 * i_len );
}
p_spu->x += i_len;
}
return( p_spu->width - p_spu->y );
return 0;
}
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