Commit 0397dee0 authored by Finn Hughes's avatar Finn Hughes Committed by Jean-Paul Saman

Improve performance of zvbi subtitles

Ignore wholly translucent rows at the top and bottom of the subtitle page

Only create an overlay large enough for the remaining rows and only only ask
zvbi to render those rows.

One happy side effect is that now --vbi-text no longer outputs header text
for some teletext streams (although --vbi-text is still unusable imho).

Reducing the size of the overlay allows stutter free playback of teletext
subtitles on significantly slower hardware.
parent 14818f23
...@@ -178,7 +178,9 @@ static subpicture_t *Subpicture( decoder_t *p_dec, video_format_t *p_fmt, ...@@ -178,7 +178,9 @@ static subpicture_t *Subpicture( decoder_t *p_dec, video_format_t *p_fmt,
static void EventHandler( vbi_event *ev, void *user_data ); static void EventHandler( vbi_event *ev, void *user_data );
static int OpaquePage( picture_t *p_src, const vbi_page p_page, static int OpaquePage( picture_t *p_src, const vbi_page p_page,
const video_format_t fmt, bool b_opaque ); const video_format_t fmt, bool b_opaque, const int text_offset );
static int get_first_visible_row( vbi_char *p_text, int rows, int columns);
static int get_last_visible_row( vbi_char *p_text, int rows, int columns);
/* Properties callbacks */ /* Properties callbacks */
static int RequestPage( vlc_object_t *p_this, char const *psz_cmd, static int RequestPage( vlc_object_t *p_this, char const *psz_cmd,
...@@ -385,10 +387,21 @@ static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block ) ...@@ -385,10 +387,21 @@ static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block )
msg_Dbg( p_dec, "we now have page: %d ready for display", msg_Dbg( p_dec, "we now have page: %d ready for display",
i_wanted_page ); i_wanted_page );
#endif #endif
/* Ignore transparent rows at the beginning and end */
int i_first_row = get_first_visible_row( p_page.text, p_page.rows, p_page.columns );
if ( i_first_row < 0 )
goto error;
int i_num_rows = get_last_visible_row( p_page.text, p_page.rows, p_page.columns ) - i_first_row + 1;
#ifdef ZVBI_DEBUG
msg_Dbg( p_dec, "After top and tail of page we have rows %i-%i of %i",
i_first_row + 1, i_first_row + i_num_rows, p_page.rows );
#endif
/* If there is a page or sub to render, then we do that here */ /* If there is a page or sub to render, then we do that here */
/* Create the subpicture unit */ /* Create the subpicture unit */
p_spu = Subpicture( p_dec, &fmt, p_sys->b_text, p_spu = Subpicture( p_dec, &fmt, p_sys->b_text,
p_page.columns, p_page.rows, p_page.columns, i_num_rows,
i_align, p_block->i_pts ); i_align, p_block->i_pts );
if( !p_spu ) if( !p_spu )
goto error; goto error;
...@@ -400,13 +413,9 @@ static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block ) ...@@ -400,13 +413,9 @@ static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block )
char p_text[i_textsize+1]; char p_text[i_textsize+1];
i_total = vbi_print_page_region( &p_page, p_text, i_textsize, i_total = vbi_print_page_region( &p_page, p_text, i_textsize,
"UTF-8", 0, 0, 0, 0, p_page.columns, p_page.rows ); "UTF-8", 0, 0, 0, i_first_row, p_page.columns, i_num_rows );
p_text[i_total] = '\0'; p_text[i_total] = '\0';
/* Strip off the pagenumber */ p_spu->p_region->psz_text = strdup( p_text );
if( i_total <= 40 )
goto error;
p_spu->p_region->psz_text = strdup( &p_text[8] );
#ifdef ZVBI_DEBUG #ifdef ZVBI_DEBUG
msg_Info( p_dec, "page %x-%x(%d)\n%s", p_page.pgno, p_page.subno, i_total, p_text ); msg_Info( p_dec, "page %x-%x(%d)\n%s", p_page.pgno, p_page.subno, i_total, p_text );
#endif #endif
...@@ -417,14 +426,22 @@ static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block ) ...@@ -417,14 +426,22 @@ static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block )
/* ZVBI is stupid enough to assume pitch == width */ /* ZVBI is stupid enough to assume pitch == width */
p_pic->p->i_pitch = 4 * fmt.i_width; p_pic->p->i_pitch = 4 * fmt.i_width;
vbi_draw_vt_page( &p_page, ZVBI_PIXFMT_RGBA32,
p_spu->p_region->p_picture->p->p_pixels, 1, 1 ); /* Maintain subtitle postion */
p_spu->p_region->i_y = i_first_row*10;
p_spu->i_original_picture_width = p_page.columns*12;
p_spu->i_original_picture_height = p_page.rows*10;
vbi_draw_vt_page_region( &p_page, ZVBI_PIXFMT_RGBA32,
p_spu->p_region->p_picture->p->p_pixels, -1,
0, i_first_row, p_page.columns, i_num_rows,
1, 1);
vlc_mutex_lock( &p_sys->lock ); vlc_mutex_lock( &p_sys->lock );
memcpy( p_sys->nav_link, &p_page.nav_link, sizeof( p_sys->nav_link )) ; memcpy( p_sys->nav_link, &p_page.nav_link, sizeof( p_sys->nav_link )) ;
vlc_mutex_unlock( &p_sys->lock ); vlc_mutex_unlock( &p_sys->lock );
OpaquePage( p_pic, p_page, fmt, b_opaque ); OpaquePage( p_pic, p_page, fmt, b_opaque, i_first_row * p_page.columns );
} }
exit: exit:
...@@ -492,7 +509,7 @@ static subpicture_t *Subpicture( decoder_t *p_dec, video_format_t *p_fmt, ...@@ -492,7 +509,7 @@ static subpicture_t *Subpicture( decoder_t *p_dec, video_format_t *p_fmt,
p_spu->i_start = i_pts; p_spu->i_start = i_pts;
p_spu->i_stop = 0; p_spu->i_stop = 0;
p_spu->b_ephemer = true; p_spu->b_ephemer = true;
p_spu->b_absolute = false; p_spu->b_absolute = true;
if( !b_text ) if( !b_text )
{ {
...@@ -546,8 +563,34 @@ static void EventHandler( vbi_event *ev, void *user_data ) ...@@ -546,8 +563,34 @@ static void EventHandler( vbi_event *ev, void *user_data )
msg_Dbg( p_dec, "Network ID changed" ); msg_Dbg( p_dec, "Network ID changed" );
} }
static int get_first_visible_row( vbi_char *p_text, int rows, int columns)
{
for ( int i = 0; i < rows * columns; i++ )
{
if ( p_text[i].opacity != VBI_TRANSPARENT_SPACE )
{
return i / columns;
}
}
return rows;
}
static int get_last_visible_row( vbi_char *p_text, int rows, int columns)
{
for ( int i = rows * columns - 1; i >= 0; i-- )
{
if (p_text[i].opacity != VBI_TRANSPARENT_SPACE)
{
return ( i + columns - 1) / columns;
}
}
return 0;
}
static int OpaquePage( picture_t *p_src, const vbi_page p_page, static int OpaquePage( picture_t *p_src, const vbi_page p_page,
const video_format_t fmt, bool b_opaque ) const video_format_t fmt, bool b_opaque, const int text_offset )
{ {
unsigned int x, y; unsigned int x, y;
...@@ -558,8 +601,8 @@ static int OpaquePage( picture_t *p_src, const vbi_page p_page, ...@@ -558,8 +601,8 @@ static int OpaquePage( picture_t *p_src, const vbi_page p_page,
{ {
for( x = 0; x < fmt.i_width; x++ ) for( x = 0; x < fmt.i_width; x++ )
{ {
const vbi_opacity opacity = p_page.text[ y/10 * p_page.columns + x/12 ].opacity; const vbi_opacity opacity = p_page.text[ text_offset + y/10 * p_page.columns + x/12 ].opacity;
const int background = p_page.text[ y/10 * p_page.columns + x/12 ].background; const int background = p_page.text[ text_offset + y/10 * p_page.columns + x/12 ].background;
uint32_t *p_pixel = (uint32_t*)&p_src->p->p_pixels[y * p_src->p->i_pitch + 4*x]; uint32_t *p_pixel = (uint32_t*)&p_src->p->p_pixels[y * p_src->p->i_pitch + 4*x];
switch( opacity ) switch( opacity )
......
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