From b1ff86e64fa8cd67815d7ff7b8ac6a7c320704da Mon Sep 17 00:00:00 2001 From: Sam Hocevar Date: Thu, 23 Mar 2000 06:27:35 +0000 Subject: [PATCH] =?utf8?q?=20.=20les=20sous-titres=20sont=20affich?= =?utf8?q?=EF=BF=BDs=20et=20effac=EF=BF=BDs=20=EF=BF=BD=20l'heure=20=20.?= =?utf8?q?=20une=20petite=20optimisation=20de=20l'affichage=20=20.=20atten?= =?utf8?q?tion,=20config.h.in=20a=20chang=EF=BF=BD,=20n'oubliez=20pas=20de?= =?utf8?q?=20refaire=20./configure?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- include/config.h.in | 3 + include/video.h | 1 + src/spu_decoder/spu_decoder.c | 34 ++++++---- src/video_output/video_output.c | 108 ++++++++++++++++++++------------ src/video_output/video_spu.c | 63 ++++++++----------- 5 files changed, 121 insertions(+), 88 deletions(-) diff --git a/include/config.h.in b/include/config.h.in index 8779a34fcf..16ff948cb2 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -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 diff --git a/include/video.h b/include/video.h index c9f865b456..496baa35a8 100644 --- a/include/video.h +++ b/include/video.h @@ -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 */ diff --git a/src/spu_decoder/spu_decoder.c b/src/spu_decoder/spu_decoder.c index 9c9d130e35..fbae6103fc 100644 --- a/src/spu_decoder/spu_decoder.c +++ b/src/spu_decoder/spu_decoder.c @@ -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: diff --git a/src/video_output/video_output.c b/src/video_output/video_output.c index b2b9c6add7..a4f2a769e8 100644 --- a/src/video_output/video_output.c +++ b/src/video_output/video_output.c @@ -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; } } diff --git a/src/video_output/video_spu.c b/src/video_output/video_spu.c index 1d82875ecf..1a98576a10 100644 --- a/src/video_output/video_spu.c +++ b/src/video_output/video_spu.c @@ -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; } -- 2.39.5