From: Laurent Aimar Date: Sun, 26 Jul 2009 21:59:53 +0000 (+0200) Subject: Improved subtitle rendering accuracy and fixed pause on dynamic subtitles. X-Git-Tag: 1.1.0-ff~4768 X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=9b8c543c1a28e4520990b6800f09f444e72f8bdd;p=vlc 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. --- diff --git a/include/vlc_osd.h b/include/vlc_osd.h index 310b6f0491..baae6f352a 100644 --- a/include/vlc_osd.h +++ b/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 ) ); /** @}*/ diff --git a/modules/stream_out/transcode.c b/modules/stream_out/transcode.c index 79013d4853..b0b1126dfc 100644 --- a/modules/stream_out/transcode.c +++ b/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 { diff --git a/src/video_output/video_output.c b/src/video_output/video_output.c index 5b9e730eb9..280d0bead1 100644 --- a/src/video_output/video_output.c +++ b/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 diff --git a/src/video_output/vout_internal.h b/src/video_output/vout_internal.h index eb9fd1729e..773008ee9e 100644 --- a/src/video_output/vout_internal.h +++ b/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 * diff --git a/src/video_output/vout_pictures.c b/src/video_output/vout_pictures.c index 48238aaffb..e63935328d 100644 --- a/src/video_output/vout_pictures.c +++ b/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] ); diff --git a/src/video_output/vout_subpictures.c b/src/video_output/vout_subpictures.c index 4b4afd1d4c..5ee652f443 100644 --- a/src/video_output/vout_subpictures.c +++ b/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 ... */