Commit 9b8c543c authored by Laurent Aimar's avatar Laurent Aimar

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.
parent 6456512f
......@@ -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 ) );
/** @}*/
......
......@@ -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
{
......
......@@ -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
......
......@@ -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
*
......
......@@ -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] );
......
......@@ -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 ... */
......
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