Browse Source

Improved subtitle rendering accuracy and fixed pause on dynamic subtitles.

Dynamic subtitles are used by ssa and kate.
This commit breaks the API for 2 functions used by the transcode module.
pull/2/head
Laurent Aimar 17 years ago
parent
commit
9b8c543c1a
  1. 4
      include/vlc_osd.h
  2. 8
      modules/stream_out/transcode.c
  3. 17
      src/video_output/video_output.c
  4. 3
      src/video_output/vout_internal.h
  5. 10
      src/video_output/vout_pictures.c
  6. 66
      src/video_output/vout_subpictures.c

4
include/vlc_osd.h

@ -115,7 +115,7 @@ VLC_EXPORT( void, spu_DisplaySubpicture, ( spu_t *, subpicture_t * ) );
*
* The returned list can only be used by spu_RenderSubpictures.
*/
VLC_EXPORT( subpicture_t *, spu_SortSubpictures, ( spu_t *, mtime_t display_date, bool b_paused, bool b_subtitle_only ) );
VLC_EXPORT( subpicture_t *, spu_SortSubpictures, ( spu_t *, mtime_t render_date, bool b_subtitle_only ) );
/**
* This function renders a list of subpicture_t on the provided picture.
@ -123,7 +123,7 @@ VLC_EXPORT( subpicture_t *, spu_SortSubpictures, ( spu_t *, mtime_t display_date
* \param p_fmt_dst is the format of the destination picture.
* \param p_fmt_src is the format of the original(source) video.
*/
VLC_EXPORT( void, spu_RenderSubpictures, ( spu_t *, picture_t *, const video_format_t *p_fmt_dst, subpicture_t *p_list, const video_format_t *p_fmt_src, bool b_paused ) );
VLC_EXPORT( void, spu_RenderSubpictures, ( spu_t *, picture_t *, const video_format_t *p_fmt_dst, subpicture_t *p_list, const video_format_t *p_fmt_src, mtime_t render_date ) );
/** @}*/

8
modules/stream_out/transcode.c

@ -1910,8 +1910,7 @@ static int transcode_video_process( sout_stream_t *p_stream,
/* Check if we have a subpicture to overlay */
if( p_sys->p_spu )
{
p_subpic = spu_SortSubpictures( p_sys->p_spu, p_pic->date,
false /* Fixme: check if stream is paused */, false );
p_subpic = spu_SortSubpictures( p_sys->p_spu, p_pic->date, false );
/* TODO: get another pic */
}
@ -1941,8 +1940,9 @@ static int transcode_video_process( sout_stream_t *p_stream,
fmt.i_sar_num = fmt.i_aspect * fmt.i_height / fmt.i_width;
fmt.i_sar_den = VOUT_ASPECT_FACTOR;
/* FIXME the mdate() seems highly suspicious */
spu_RenderSubpictures( p_sys->p_spu, p_pic, &fmt,
p_subpic, &id->p_decoder->fmt_out.video, false );
p_subpic, &id->p_decoder->fmt_out.video, mdate() );
}
/* Run user specified filter chain */
@ -2334,7 +2334,7 @@ static int transcode_osd_process( sout_stream_t *p_stream,
/* Check if we have a subpicture to send */
if( p_sys->p_spu && in->i_dts > 0)
{
p_subpic = spu_SortSubpictures( p_sys->p_spu, in->i_dts, false, false );
p_subpic = spu_SortSubpictures( p_sys->p_spu, in->i_dts, false );
}
else
{

17
src/video_output/video_output.c

@ -1177,17 +1177,24 @@ static void* RunThread( void *p_this )
/*
* Check for subpictures to display
*/
mtime_t spu_render_time;
if( p_vout->p->b_paused )
spu_render_time = p_vout->p->i_pause_date;
else
spu_render_time = p_picture ? p_picture->date : mdate();
subpicture_t *p_subpic = NULL;
if( display_date > 0 )
p_subpic = spu_SortSubpictures( p_vout->p_spu, display_date,
p_vout->p->b_paused, b_snapshot );
if( spu_render_time > 1 )
p_subpic = spu_SortSubpictures( p_vout->p_spu,
spu_render_time, b_snapshot );
/*
* Perform rendering
*/
p_vout->p->i_picture_displayed++;
p_directbuffer = vout_RenderPicture( p_vout, p_filtered_picture,
p_subpic, p_vout->p->b_paused );
p_directbuffer = vout_RenderPicture( p_vout,
p_filtered_picture, p_subpic,
spu_render_time );
/*
* Take a snapshot if requested

3
src/video_output/vout_internal.h

@ -107,7 +107,8 @@ struct vout_thread_sys_t
/* DO NOT use vout_RenderPicture unless you are in src/video_ouput */
picture_t *vout_RenderPicture( vout_thread_t *, picture_t *,
subpicture_t *, bool b_paused );
subpicture_t *,
mtime_t render_date );
/* DO NOT use vout_UsePictureLocked unless you are in src/video_ouput
*

10
src/video_output/vout_pictures.c

@ -335,7 +335,7 @@ static void vout_UnlockPicture( vout_thread_t *p_vout, picture_t *p_picture )
* thread which direct buffer needs to be displayed.
*/
picture_t *vout_RenderPicture( vout_thread_t *p_vout, picture_t *p_pic,
subpicture_t *p_subpic, bool b_paused )
subpicture_t *p_subpic, mtime_t render_date )
{
if( p_pic == NULL )
return NULL;
@ -356,7 +356,7 @@ picture_t *vout_RenderPicture( vout_thread_t *p_vout, picture_t *p_pic,
spu_RenderSubpictures( p_vout->p_spu,
PP_OUTPUTPICTURE[0], &p_vout->fmt_out,
p_subpic, &p_vout->fmt_in, b_paused );
p_subpic, &p_vout->fmt_in, render_date );
vout_UnlockPicture( p_vout, PP_OUTPUTPICTURE[0] );
@ -383,7 +383,7 @@ picture_t *vout_RenderPicture( vout_thread_t *p_vout, picture_t *p_pic,
picture_Copy( PP_OUTPUTPICTURE[0], p_pic );
spu_RenderSubpictures( p_vout->p_spu,
PP_OUTPUTPICTURE[0], &p_vout->fmt_out,
p_subpic, &p_vout->fmt_in, b_paused );
p_subpic, &p_vout->fmt_in, render_date );
vout_UnlockPicture( p_vout, PP_OUTPUTPICTURE[0] );
@ -419,7 +419,7 @@ picture_t *vout_RenderPicture( vout_thread_t *p_vout, picture_t *p_pic,
/* Render subpictures on the first direct buffer */
spu_RenderSubpictures( p_vout->p_spu,
p_tmp_pic, &p_vout->fmt_out,
p_subpic, &p_vout->fmt_in, b_paused );
p_subpic, &p_vout->fmt_in, render_date );
if( vout_LockPicture( p_vout, &p_vout->p_picture[0] ) )
return NULL;
@ -438,7 +438,7 @@ picture_t *vout_RenderPicture( vout_thread_t *p_vout, picture_t *p_pic,
/* Render subpictures on the first direct buffer */
spu_RenderSubpictures( p_vout->p_spu,
&p_vout->p_picture[0], &p_vout->fmt_out,
p_subpic, &p_vout->fmt_in, b_paused );
p_subpic, &p_vout->fmt_in, render_date );
}
vout_UnlockPicture( p_vout, &p_vout->p_picture[0] );

66
src/video_output/vout_subpictures.c

@ -149,7 +149,8 @@ static void SpuRenderRegion( spu_t *,
subpicture_t *, subpicture_region_t *,
const spu_scale_t scale_size,
const video_format_t *p_fmt,
const spu_area_t *p_subtitle_area, int i_subtitle_area );
const spu_area_t *p_subtitle_area, int i_subtitle_area,
mtime_t render_date );
static void UpdateSPU ( spu_t *, vlc_object_t * );
static int CropCallback( vlc_object_t *, char const *,
@ -350,13 +351,15 @@ void spu_DisplaySubpicture( spu_t *p_spu, subpicture_t *p_subpic )
void spu_RenderSubpictures( spu_t *p_spu,
picture_t *p_pic_dst, const video_format_t *p_fmt_dst,
subpicture_t *p_subpic_list,
const video_format_t *p_fmt_src, bool b_paused )
const video_format_t *p_fmt_src,
mtime_t render_date )
{
spu_private_t *p_sys = p_spu->p;
const mtime_t system_date = mdate();
const int i_source_video_width = p_fmt_src->i_width;
const int i_source_video_height = p_fmt_src->i_height;
const mtime_t i_current_date = mdate();
unsigned int i_subpicture;
subpicture_t *pp_subpicture[VOUT_MAX_SUBPICTURES];
@ -375,11 +378,11 @@ void spu_RenderSubpictures( spu_t *p_spu,
p_subpic != NULL;
p_subpic = p_subpic->p_next )
{
/* */
if( !b_paused && p_subpic->pf_pre_render )
/* TODO remove pre-render */
if( p_subpic->pf_pre_render )
p_subpic->pf_pre_render( p_spu, p_subpic, p_fmt_dst );
if( !b_paused && p_subpic->pf_update_regions )
if( p_subpic->pf_update_regions )
{
video_format_t fmt_org = *p_fmt_dst;
fmt_org.i_width =
@ -387,7 +390,8 @@ void spu_RenderSubpictures( spu_t *p_spu,
fmt_org.i_height =
fmt_org.i_visible_height = i_source_video_height;
p_subpic->pf_update_regions( p_spu, p_subpic, &fmt_org, i_current_date );
p_subpic->pf_update_regions( p_spu, p_subpic, &fmt_org,
p_subpic->b_subtitle ? render_date : system_date );
}
/* */
@ -505,7 +509,8 @@ void spu_RenderSubpictures( spu_t *p_spu,
/* */
SpuRenderRegion( p_spu, p_pic_dst, &area,
p_subpic, p_region, scale, p_fmt_dst,
p_subtitle_area, i_subtitle_area );
p_subtitle_area, i_subtitle_area,
p_subpic->b_subtitle ? render_date : system_date );
if( p_subpic->b_subtitle )
{
@ -540,12 +545,13 @@ void spu_RenderSubpictures( spu_t *p_spu,
* to be removed if a newer one is available), which makes it a lot
* more difficult to guess if a subpicture has to be rendered or not.
*****************************************************************************/
subpicture_t *spu_SortSubpictures( spu_t *p_spu, mtime_t display_date,
bool b_paused, bool b_subtitle_only )
subpicture_t *spu_SortSubpictures( spu_t *p_spu, mtime_t render_date,
bool b_subtitle_only )
{
spu_private_t *p_sys = p_spu->p;
int i_channel;
subpicture_t *p_subpic = NULL;
const mtime_t system_date = mdate();
/* Update sub-filter chain */
vlc_mutex_lock( &p_sys->lock );
@ -563,7 +569,7 @@ subpicture_t *spu_SortSubpictures( spu_t *p_spu, mtime_t display_date,
}
/* Run subpicture filters */
filter_chain_SubFilter( p_sys->p_chain, display_date );
filter_chain_SubFilter( p_sys->p_chain, render_date );
vlc_mutex_lock( &p_sys->lock );
@ -575,8 +581,9 @@ subpicture_t *spu_SortSubpictures( spu_t *p_spu, mtime_t display_date,
bool pb_available_late[VOUT_MAX_SUBPICTURES];
int i_available = 0;
mtime_t start_date = display_date;
mtime_t ephemer_date = 0;
mtime_t start_date = render_date;
mtime_t ephemer_subtitle_date = 0;
mtime_t ephemer_system_date = 0;
int i_index;
/* Select available pictures */
@ -599,25 +606,25 @@ subpicture_t *spu_SortSubpictures( spu_t *p_spu, mtime_t display_date,
{
continue;
}
if( display_date &&
display_date < p_current->i_start )
if( render_date &&
render_date < p_current->i_start )
{
/* Too early, come back next monday */
continue;
}
if( p_current->i_start > ephemer_date )
ephemer_date = p_current->i_start;
mtime_t *pi_ephemer_date = p_current->b_subtitle ? &ephemer_subtitle_date : &ephemer_system_date;
if( p_current->i_start > *pi_ephemer_date )
*pi_ephemer_date = p_current->i_start;
b_stop_valid = ( !p_current->b_ephemer || p_current->i_stop > p_current->i_start ) &&
( !p_current->b_subtitle || !b_paused ); /* XXX Assume that subtitle are pausable */
b_stop_valid = !p_current->b_ephemer || p_current->i_stop > p_current->i_start;
b_late = b_stop_valid && p_current->i_stop <= display_date;
b_late = b_stop_valid && p_current->i_stop <= p_current->b_subtitle ? render_date : system_date;
/* start_date will be used for correct automatic overlap support
* in case picture that should not be displayed anymore (display_time)
* overlap with a picture to be displayed (p_current->i_start) */
if( !b_late && !p_current->b_ephemer )
if( p_current->b_subtitle && !b_late && !p_current->b_ephemer )
start_date = p_current->i_start;
/* */
@ -638,7 +645,10 @@ subpicture_t *spu_SortSubpictures( spu_t *p_spu, mtime_t display_date,
subpicture_t *p_current = p_available_subpic[i_index];
bool b_late = pb_available_late[i_index];
if( ( b_late && p_current->i_stop <= __MAX( start_date, p_sys->i_last_sort_date ) ) ||
const mtime_t stop_date = p_current->b_subtitle ? __MAX( start_date, p_sys->i_last_sort_date ) : system_date;
const mtime_t ephemer_date = p_current->b_subtitle ? ephemer_subtitle_date : ephemer_system_date;
if( ( b_late && p_current->i_stop <= stop_date ) ||
( p_current->b_ephemer && p_current->i_start < ephemer_date ) )
{
/* Destroy late and obsolete ephemer subpictures */
@ -651,7 +661,7 @@ subpicture_t *spu_SortSubpictures( spu_t *p_spu, mtime_t display_date,
}
}
p_sys->i_last_sort_date = display_date;
p_sys->i_last_sort_date = render_date;
vlc_mutex_unlock( &p_sys->lock );
return p_subpic;
@ -1034,7 +1044,7 @@ static void SpuRenderCreateAndLoadScale( spu_t *p_spu )
static void SpuRenderText( spu_t *p_spu, bool *pb_rerender_text,
subpicture_t *p_subpic, subpicture_region_t *p_region,
int i_min_scale_ratio )
int i_min_scale_ratio, mtime_t render_date )
{
filter_t *p_text = p_spu->p->p_text;
@ -1063,7 +1073,7 @@ static void SpuRenderText( spu_t *p_spu, bool *pb_rerender_text,
* the text over time.
*/
var_SetTime( p_text, "spu-duration", p_subpic->i_stop - p_subpic->i_start );
var_SetTime( p_text, "spu-elapsed", mdate() - p_subpic->i_start );
var_SetTime( p_text, "spu-elapsed", render_date );
var_SetBool( p_text, "text-rerender", false );
var_SetInteger( p_text, "scale", i_min_scale_ratio );
@ -1326,7 +1336,8 @@ static void SpuRenderRegion( spu_t *p_spu,
subpicture_t *p_subpic, subpicture_region_t *p_region,
const spu_scale_t scale_size,
const video_format_t *p_fmt,
const spu_area_t *p_subtitle_area, int i_subtitle_area )
const spu_area_t *p_subtitle_area, int i_subtitle_area,
mtime_t render_date )
{
spu_private_t *p_sys = p_spu->p;
@ -1346,7 +1357,8 @@ static void SpuRenderRegion( spu_t *p_spu,
if( p_region->fmt.i_chroma == VLC_CODEC_TEXT )
{
const int i_min_scale_ratio = SCALE_UNIT; /* FIXME what is the right value? (scale_size is not) */
SpuRenderText( p_spu, &b_rerender_text, p_subpic, p_region, i_min_scale_ratio );
SpuRenderText( p_spu, &b_rerender_text, p_subpic, p_region,
i_min_scale_ratio, render_date );
b_restore_format = b_rerender_text;
/* Check if the rendering has failed ... */

Loading…
Cancel
Save