Commit a8daa86c authored by Laurent Aimar's avatar Laurent Aimar

Fixed various issue with SPU.

It is a manual backport of:
- [9b8c543c] Subtitles accuracy
- [9c462ffb] Ephemere destruction
- [fabf2399] Fixes for previous commits

It does not changes existing functions, but add 2 new ones.
parent bbf70d05
......@@ -113,6 +113,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_SortSubpicturesNew, ( spu_t *, mtime_t render_subtitle_date, bool b_subtitle_only ) );
/**
* This function renders a list of subpicture_t on the provided picture.
......@@ -121,6 +122,7 @@ VLC_EXPORT( subpicture_t *, spu_SortSubpictures, ( spu_t *, mtime_t display_date
* \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_RenderSubpicturesNew, ( 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_subtitle_date ) );
/** @}*/
......
......@@ -1945,8 +1945,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_SortSubpicturesNew( p_sys->p_spu, p_pic->date, false );
/* TODO: get another pic */
}
......@@ -1976,8 +1975,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;
spu_RenderSubpictures( p_sys->p_spu, p_pic, &fmt,
p_subpic, &id->p_decoder->fmt_out.video, false );
/* FIXME the mdate() seems highly suspicious */
spu_RenderSubpicturesNew( p_sys->p_spu, p_pic, &fmt,
p_subpic, &id->p_decoder->fmt_out.video, mdate() );
}
/* Run user specified filter chain */
......@@ -2475,7 +2475,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_SortSubpicturesNew( p_sys->p_spu, in->i_dts, false );
}
else
{
......
......@@ -182,7 +182,7 @@ libvlc_la_LIBADD = `$(VLC_CONFIG) -libs libvlc` \
libvlccore.la ../compat/libcompat.la
libvlc_la_CFLAGS = `$(VLC_CONFIG) --cflags libvlc`
libvlc_la_LDFLAGS = $(AM_LDFLAGS) `$(VLC_CONFIG) --ldflags libvlc` \
-version-info 4:1:2 \
-version-info 5:0:3 \
-export-symbols $(srcdir)/libvlc.sym
libvlc_la_DEPENDENCIES = libvlc.sym libvlccore.la
if HAVE_WIN32
......
......@@ -350,7 +350,9 @@ spu_Destroy
spu_DisplaySubpicture
spu_Init
spu_RenderSubpictures
spu_RenderSubpicturesNew
spu_SortSubpictures
spu_SortSubpicturesNew
__stats_TimerClean
__stats_TimerDump
__stats_TimersCleanAll
......
......@@ -1183,17 +1183,24 @@ static void* RunThread( void *p_this )
/*
* Check for subpictures to display
*/
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 );
mtime_t spu_render_time;
if( p_vout->p->b_paused )
spu_render_time = p_vout->p->i_pause_date;
else if( p_picture )
spu_render_time = p_picture->date > 1 ? p_picture->date : mdate();
else
spu_render_time = 0;
subpicture_t *p_subpic = spu_SortSubpicturesNew( 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
*
......
......@@ -333,7 +333,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;
......@@ -352,9 +352,9 @@ 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,
spu_RenderSubpicturesNew( 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] );
......@@ -379,9 +379,9 @@ picture_t *vout_RenderPicture( vout_thread_t *p_vout, picture_t *p_pic,
return NULL;
picture_Copy( PP_OUTPUTPICTURE[0], p_pic );
spu_RenderSubpictures( p_vout->p_spu,
spu_RenderSubpicturesNew( 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] );
......@@ -417,9 +417,9 @@ picture_t *vout_RenderPicture( vout_thread_t *p_vout, picture_t *p_pic,
p_vout->p->p_chroma->pf_video_filter( p_vout->p->p_chroma, p_pic );
/* Render subpictures on the first direct buffer */
spu_RenderSubpictures( p_vout->p_spu,
spu_RenderSubpicturesNew( 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;
......@@ -436,9 +436,9 @@ picture_t *vout_RenderPicture( vout_thread_t *p_vout, picture_t *p_pic,
p_vout->p->p_chroma->pf_video_filter( p_vout->p->p_chroma, p_pic );
/* Render subpictures on the first direct buffer */
spu_RenderSubpictures( p_vout->p_spu,
spu_RenderSubpicturesNew( 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] );
......
......@@ -154,7 +154,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 *,
......@@ -353,16 +354,18 @@ void spu_DisplaySubpicture( spu_t *p_spu, subpicture_t *p_subpic )
/**
* This function renders all sub picture units in the list.
*/
void spu_RenderSubpictures( spu_t *p_spu,
void spu_RenderSubpicturesNew( 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_subtitle_date )
{
spu_private_t *p_sys = p_spu->p;
const mtime_t render_osd_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];
......@@ -381,11 +384,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 =
......@@ -393,7 +396,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_subtitle_date : render_osd_date );
}
/* */
......@@ -511,7 +515,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_subtitle_date : render_osd_date );
if( p_subpic->b_subtitle )
{
......@@ -535,6 +540,17 @@ void spu_RenderSubpictures( spu_t *p_spu,
vlc_mutex_unlock( &p_sys->lock );
}
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 )
{
VLC_UNUSED(b_paused);
spu_RenderSubpictures( p_spu, p_pic_dst, p_fmt_dst,
p_subpic_list, p_fmt_src, mdate() );
}
/*****************************************************************************
* spu_SortSubpictures: find the subpictures to display
......@@ -546,12 +562,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_SortSubpicturesNew( spu_t *p_spu, mtime_t render_subtitle_date,
bool b_subtitle_only )
{
spu_private_t *p_sys = p_spu->p;
int i_channel;
subpicture_t *p_subpic = NULL;
const mtime_t render_osd_date = mdate();
/* Update sub-filter chain */
vlc_mutex_lock( &p_sys->lock );
......@@ -569,7 +586,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_osd_date );
vlc_mutex_lock( &p_sys->lock );
......@@ -581,8 +598,11 @@ 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_subtitle_date;
mtime_t ephemer_subtitle_date = 0;
mtime_t ephemer_osd_date = 0;
int64_t i_ephemer_subtitle_order = INT64_MIN;
int64_t i_ephemer_system_order = INT64_MIN;
int i_index;
/* Select available pictures */
......@@ -605,25 +625,31 @@ subpicture_t *spu_SortSubpictures( spu_t *p_spu, mtime_t display_date,
{
continue;
}
if( display_date &&
display_date < p_current->i_start )
const mtime_t render_date = p_current->b_subtitle ? render_subtitle_date : render_osd_date;
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_osd_date;
int64_t *pi_ephemer_order = p_current->b_subtitle ? &i_ephemer_subtitle_order : &i_ephemer_system_order;
if( p_current->i_start >= *pi_ephemer_date )
{
*pi_ephemer_date = p_current->i_start;
if( p_current->i_order > *pi_ephemer_order )
*pi_ephemer_order = p_current->i_order;
}
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 <= render_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;
/* */
......@@ -644,24 +670,40 @@ 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 ) ) ||
( p_current->b_ephemer && p_current->i_start < ephemer_date ) )
{
const mtime_t stop_date = p_current->b_subtitle ? __MAX( start_date, p_sys->i_last_sort_date ) : render_osd_date;
const mtime_t ephemer_date = p_current->b_subtitle ? ephemer_subtitle_date : ephemer_osd_date;
const int64_t i_ephemer_order = p_current->b_subtitle ? i_ephemer_subtitle_order : i_ephemer_system_order;
/* Destroy late and obsolete ephemer subpictures */
SpuHeapDeleteSubpicture( &p_sys->heap, p_current );
bool b_rejet = b_late && p_current->i_stop <= stop_date;
if( p_current->b_ephemer )
{
if( p_current->i_start < ephemer_date )
b_rejet = true;
else if( p_current->i_start == ephemer_date &&
p_current->i_order < i_ephemer_order )
b_rejet = true;
}
if( b_rejet )
SpuHeapDeleteSubpicture( &p_sys->heap, p_current );
else
{
SubpictureChain( &p_subpic, p_current );
}
}
}
p_sys->i_last_sort_date = display_date;
p_sys->i_last_sort_date = render_subtitle_date;
vlc_mutex_unlock( &p_sys->lock );
return p_subpic;
}
subpicture_t *spu_SortSubpictures( spu_t *p_spu, mtime_t display_date, bool b_paused,
bool b_subtitle_only )
{
VLC_UNUSED(b_paused);
return spu_SortSubpicturesNew( p_spu, display_date, b_subtitle_only );
}
void spu_OffsetSubtitleDate( spu_t *p_spu, mtime_t i_duration )
{
......@@ -1056,7 +1098,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;
......@@ -1085,7 +1127,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 );
......@@ -1348,7 +1390,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;
......@@ -1368,7 +1411,8 @@ static void SpuRenderRegion( spu_t *p_spu,
if( p_region->fmt.i_chroma == VLC_FOURCC_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