mtime_t i_last_sort_date;
};
-/* Subpicture rendered flag
- * FIXME ? it could be moved to private ? */
-#define SUBPICTURE_RENDERED (0x1000)
-#if SUBPICTURE_RENDERED < SUBPICTURE_ALIGN_MASK
-# error SUBPICTURE_RENDERED too low
-#endif
-
/*****************************************************************************
* heap managment
*****************************************************************************/
return i_ret;
}
-static void SpuRenderCreateAndLoadText( spu_t *p_spu )
+static filter_t *SpuRenderCreateAndLoadText( spu_t *p_spu )
{
- filter_t *p_text;
-
- assert( !p_spu->p->p_text );
-
- p_spu->p->p_text =
- p_text = vlc_custom_create( p_spu, sizeof(filter_t),
- VLC_OBJECT_GENERIC, "spu text" );
+ filter_t *p_text = vlc_custom_create( p_spu, sizeof(*p_text),
+ VLC_OBJECT_GENERIC, "spu text" );
if( !p_text )
- return;
+ return NULL;
p_text->p_owner = xmalloc( sizeof(*p_text->p_owner) );
p_text->p_owner->p_spu = p_spu;
p_text->pf_get_attachments = spu_get_attachments;
vlc_object_attach( p_text, p_spu );
-
- /* FIXME TOCHECK shouldn't module_need( , , psz_modulename, false ) do the
- * same than these 2 calls ? */
- char *psz_modulename = var_CreateGetString( p_spu, "text-renderer" );
- if( psz_modulename && *psz_modulename )
- {
- p_text->p_module = module_need( p_text, "text renderer",
- psz_modulename, true );
- }
- free( psz_modulename );
-
- if( !p_text->p_module )
- p_text->p_module = module_need( p_text, "text renderer", NULL, false );
+ p_text->p_module = module_need( p_text, "text renderer", "$text-renderer", false );
/* Create a few variables used for enhanced text rendering */
- var_Create( p_text, "spu-duration", VLC_VAR_TIME );
var_Create( p_text, "spu-elapsed", VLC_VAR_TIME );
var_Create( p_text, "text-rerender", VLC_VAR_BOOL );
var_Create( p_text, "scale", VLC_VAR_INTEGER );
+
+ return p_text;
}
-static filter_t *CreateAndLoadScale( vlc_object_t *p_obj,
- vlc_fourcc_t i_src_chroma, vlc_fourcc_t i_dst_chroma,
- bool b_resize )
+static filter_t *SpuRenderCreateAndLoadScale( vlc_object_t *p_obj,
+ vlc_fourcc_t i_src_chroma, vlc_fourcc_t i_dst_chroma,
+ bool b_resize )
{
- filter_t *p_scale;
-
- p_scale = vlc_custom_create( p_obj, sizeof(filter_t),
- VLC_OBJECT_GENERIC, "scale" );
+ filter_t *p_scale = vlc_custom_create( p_obj, sizeof(*p_scale),
+ VLC_OBJECT_GENERIC, "scale" );
if( !p_scale )
return NULL;
return p_scale;
}
-static void SpuRenderCreateAndLoadScale( spu_t *p_spu )
-{
- assert( !p_spu->p->p_scale );
- assert( !p_spu->p->p_scale_yuvp );
- /* XXX p_spu->p_scale is used for all conversion/scaling except yuvp to
- * yuva/rgba */
- p_spu->p->p_scale = CreateAndLoadScale( VLC_OBJECT(p_spu),
- VLC_CODEC_YUVA, VLC_CODEC_YUVA, true );
- /* This one is used for YUVP to YUVA/RGBA without scaling
- * FIXME rename it */
- p_spu->p->p_scale_yuvp = CreateAndLoadScale( VLC_OBJECT(p_spu),
- VLC_CODEC_YUVP, VLC_CODEC_YUVA, false );
-}
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, mtime_t render_date )
+ subpicture_region_t *p_region,
+ mtime_t render_date )
{
filter_t *p_text = p_spu->p->p_text;
assert( p_region->fmt.i_chroma == VLC_CODEC_TEXT );
if( !p_text || !p_text->p_module )
- goto exit;
+ return;
/* Setup 3 variables which can be used to render
* time-dependent text (and effects). The first indicates
* least show up on screen, but the effect won't change
* the text over time.
*/
- var_SetTime( p_text, "spu-duration", p_subpic->i_stop - 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 );
if( p_text->pf_render_html && p_region->psz_html )
{
p_text->pf_render_text( p_text, p_region, p_region );
}
*pb_rerender_text = var_GetBool( p_text, "text-rerender" );
-
-exit:
- p_region->i_align |= SUBPICTURE_RENDERED;
}
/**
{
return spu_scale_create( SCALE_UNIT, SCALE_UNIT );
}
-static spu_scale_t spu_scale_createq( int wn, int wd, int hn, int hd )
+static spu_scale_t spu_scale_createq( int64_t wn, int64_t wd, int64_t hn, int64_t hd )
{
return spu_scale_create( wn * SCALE_UNIT / wd,
hn * SCALE_UNIT / hd );
const subpicture_t *p_subpic,
const subpicture_region_t *p_region )
{
- const int i_delta_x = p_region->i_x;
- const int i_delta_y = p_region->i_y;
- int i_x, i_y;
-
assert( p_region->i_x != INT_MAX && p_region->i_y != INT_MAX );
- if( p_region->i_align & SUBPICTURE_ALIGN_TOP )
- {
- i_y = i_delta_y;
- }
- else if( p_region->i_align & SUBPICTURE_ALIGN_BOTTOM )
- {
- i_y = p_subpic->i_original_picture_height - p_region->fmt.i_height - i_delta_y;
- }
- else
- {
- i_y = p_subpic->i_original_picture_height / 2 - p_region->fmt.i_height / 2;
- }
-
- if( p_region->i_align & SUBPICTURE_ALIGN_LEFT )
- {
- i_x = i_delta_x;
- }
- else if( p_region->i_align & SUBPICTURE_ALIGN_RIGHT )
+ if( p_subpic->b_absolute )
{
- i_x = p_subpic->i_original_picture_width - p_region->fmt.i_width - i_delta_x;
+ *pi_x = p_region->i_x;
+ *pi_y = p_region->i_y;
}
else
{
- i_x = p_subpic->i_original_picture_width / 2 - p_region->fmt.i_width / 2;
- }
+ if( p_region->i_align & SUBPICTURE_ALIGN_TOP )
+ {
+ *pi_y = p_region->i_y;
+ }
+ else if( p_region->i_align & SUBPICTURE_ALIGN_BOTTOM )
+ {
+ *pi_y = p_subpic->i_original_picture_height - p_region->fmt.i_height - p_region->i_y;
+ }
+ else
+ {
+ *pi_y = p_subpic->i_original_picture_height / 2 - p_region->fmt.i_height / 2;
+ }
- if( p_subpic->b_absolute )
- {
- i_x = i_delta_x;
- i_y = i_delta_y;
+ if( p_region->i_align & SUBPICTURE_ALIGN_LEFT )
+ {
+ *pi_x = p_region->i_x;
+ }
+ else if( p_region->i_align & SUBPICTURE_ALIGN_RIGHT )
+ {
+ *pi_x = p_subpic->i_original_picture_width - p_region->fmt.i_width - p_region->i_x;
+ }
+ else
+ {
+ *pi_x = p_subpic->i_original_picture_width / 2 - p_region->fmt.i_width / 2;
+ }
}
-
- *pi_x = i_x;
- *pi_y = i_y;
}
/**
return r;
}
-static void SubpictureChain( subpicture_t **pp_head, subpicture_t *p_subpic )
-{
- p_subpic->p_next = *pp_head;
-
- *pp_head = p_subpic;
-}
-
/*****************************************************************************
- * SpuSortSubpictures: find the subpictures to display
+ * SpuSelectSubpictures: find the subpictures to display
*****************************************************************************
* This function parses all subpictures and decides which ones need to be
* displayed. If no picture has been selected, display_date will depend on
* 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.
*****************************************************************************/
-static subpicture_t *SpuSortSubpictures( spu_t *p_spu,
- mtime_t render_subtitle_date,
- mtime_t render_osd_date,
- bool b_subtitle_only )
+static void SpuSelectSubpictures( spu_t *p_spu,
+ unsigned int *pi_subpicture,
+ subpicture_t **pp_subpicture,
+ mtime_t render_subtitle_date,
+ mtime_t render_osd_date,
+ bool b_subtitle_only )
{
spu_private_t *p_sys = p_spu->p;
- subpicture_t *p_subpic = NULL;
+
+ /* */
+ *pi_subpicture = 0;
/* Create a list of channels */
int pi_channel[VOUT_MAX_SUBPICTURES];
pi_channel[i_channel_count++] = i_channel;
}
- /* We get an easily parsable chained list of subpictures which
- * ends with NULL since p_subpic was initialized to NULL. */
+ /* Fill up the pp_subpicture arrays with relevent pictures */
for( int i = 0; i < i_channel_count; i++ )
{
const int i_channel = pi_channel[i];
if( b_rejet )
SpuHeapDeleteSubpicture( &p_sys->heap, p_current );
else
- SubpictureChain( &p_subpic, p_current );
+ pp_subpicture[(*pi_subpicture)++] = p_current;
}
}
p_sys->i_last_sort_date = render_subtitle_date;
-
- return p_subpic;
}
subpicture_region_t **pp_dst, spu_area_t *p_dst_area,
subpicture_t *p_subpic, subpicture_region_t *p_region,
const spu_scale_t scale_size,
+ const vlc_fourcc_t *p_chroma_list,
const video_format_t *p_fmt,
const spu_area_t *p_subtitle_area, int i_subtitle_area,
mtime_t render_date )
spu_private_t *p_sys = p_spu->p;
video_format_t fmt_original = p_region->fmt;
- bool b_rerender_text = false;
- bool b_restore_format = false;
+ bool b_restore_text = false;
int i_x_offset;
int i_y_offset;
/* Render text region */
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, render_date );
- b_restore_format = b_rerender_text;
+ SpuRenderText( p_spu, &b_restore_text, p_region,
+ render_date );
/* Check if the rendering has failed ... */
if( p_region->fmt.i_chroma == VLC_CODEC_TEXT )
const bool b_force_crop = b_force_palette && p_sys->b_force_crop;
bool b_changed_palette = false;
-
/* Compute the margin which is expressed in destination pixel unit
* The margin is applied only to subtitle and when no forced crop is
* requested (dvd menu) */
region_fmt = p_region->fmt;
p_region_picture = p_region->p_picture;
+ bool b_convert_chroma = true;
+ for( int i = 0; p_chroma_list[i] && b_convert_chroma; i++ )
+ {
+ if( region_fmt.i_chroma == p_chroma_list[i] )
+ b_convert_chroma = false;
+ }
/* Scale from rendered size to destination size */
if( p_sys->p_scale && p_sys->p_scale->p_module &&
( !b_using_palette || ( p_sys->p_scale_yuvp && p_sys->p_scale_yuvp->p_module ) ) &&
- ( scale_size.w != SCALE_UNIT || scale_size.h != SCALE_UNIT || b_using_palette ) )
+ ( scale_size.w != SCALE_UNIT || scale_size.h != SCALE_UNIT ||
+ b_using_palette || b_convert_chroma) )
{
const unsigned i_dst_width = spu_scale_w( p_region->fmt.i_width, scale_size );
const unsigned i_dst_height = spu_scale_h( p_region->fmt.i_height, scale_size );
if( b_changed_palette )
b_changed = true;
+ if( b_convert_chroma && p_private->fmt.i_chroma != p_chroma_list[0] )
+ b_changed = true;
+
if( b_changed )
{
subpicture_region_private_Delete( p_private );
p_scale_yuvp->fmt_in.video = p_region->fmt;
- /* TODO converting to RGBA for RGB video output is better */
p_scale_yuvp->fmt_out.video = p_region->fmt;
- p_scale_yuvp->fmt_out.video.i_chroma = VLC_CODEC_YUVA;
+ p_scale_yuvp->fmt_out.video.i_chroma = p_chroma_list[0];
p_picture = p_scale_yuvp->pf_video_filter( p_scale_yuvp, p_picture );
if( !p_picture )
/* Conversion(except from YUVP)/Scaling */
if( p_picture &&
( p_picture->format.i_width != i_dst_width ||
- p_picture->format.i_height != i_dst_height ) )
+ p_picture->format.i_height != i_dst_height ||
+ ( b_convert_chroma && !b_using_palette ) ) )
{
p_scale->fmt_in.video = p_picture->format;
p_scale->fmt_out.video = p_picture->format;
+ if( b_convert_chroma )
+ p_scale->fmt_out.i_codec =
+ p_scale->fmt_out.video.i_chroma = p_chroma_list[0];
p_scale->fmt_out.video.i_width = i_dst_width;
p_scale->fmt_out.video.i_height = i_dst_height;
p_dst->i_x = i_x_offset;
p_dst->i_y = i_y_offset;
p_dst->i_align = 0;
+ if( p_dst->p_picture )
+ picture_Release( p_dst->p_picture );
p_dst->p_picture = picture_Hold( p_region_picture );
int i_fade_alpha = 255;
if( p_subpic->b_fade )
}
exit:
- if( b_rerender_text )
+ if( b_restore_text )
{
/* Some forms of subtitles need to be re-rendered more than
* once, eg. karaoke. We therefore restore the region to its
subpicture_region_private_Delete( p_region->p_private );
p_region->p_private = NULL;
}
- p_region->i_align &= ~SUBPICTURE_RENDERED;
- }
- if( b_restore_format )
p_region->fmt = fmt_original;
+ }
}
/**
* This function renders all sub picture units in the list.
*/
static subpicture_t *SpuRenderSubpictures( spu_t *p_spu,
+ unsigned int i_subpicture,
+ subpicture_t **pp_subpicture,
+ const vlc_fourcc_t *p_chroma_list,
const video_format_t *p_fmt_dst,
- subpicture_t *p_subpic_list,
const video_format_t *p_fmt_src,
mtime_t render_subtitle_date,
mtime_t render_osd_date )
{
spu_private_t *p_sys = p_spu->p;
- const int i_source_video_width = p_fmt_src->i_width;
- const int i_source_video_height = p_fmt_src->i_height;
-
- unsigned int i_subpicture;
- subpicture_t *pp_subpicture[VOUT_MAX_SUBPICTURES];
-
- unsigned int i_subtitle_region_count;
- spu_area_t p_subtitle_area_buffer[VOUT_MAX_SUBPICTURES];
- spu_area_t *p_subtitle_area;
- int i_subtitle_area;
-
- /* Preprocess subpictures */
- i_subpicture = 0;
- i_subtitle_region_count = 0;
- for( subpicture_t * p_subpic = p_subpic_list;
- p_subpic != NULL;
- p_subpic = p_subpic->p_next )
+ /* Count the number of regions and subtitle regions */
+ unsigned int i_subtitle_region_count = 0;
+ unsigned int i_region_count = 0;
+ for( unsigned i = 0; i < i_subpicture; i++ )
{
- subpicture_Update( p_subpic,
- p_fmt_src, p_fmt_dst,
- p_subpic->b_subtitle ? render_subtitle_date : render_osd_date );
+ const subpicture_t *p_subpic = pp_subpicture[i];
- /* */
- if( p_subpic->b_subtitle )
- {
- for( subpicture_region_t *r = p_subpic->p_region; r != NULL; r = r->p_next )
- i_subtitle_region_count++;
- }
+ unsigned i_count = 0;
+ for( subpicture_region_t *r = p_subpic->p_region; r != NULL; r = r->p_next )
+ i_count++;
- /* */
- pp_subpicture[i_subpicture++] = p_subpic;
+ if( p_subpic->b_subtitle )
+ i_subtitle_region_count += i_count;
+ i_region_count += i_count;
}
-
- /* Be sure we have at least 1 picture to process */
- if( i_subpicture <= 0 )
+ if( i_region_count <= 0 )
return NULL;
+ /* Create the output subpicture */
subpicture_t *p_output = subpicture_New( NULL );
-
- /* Now order subpicture array
- * XXX The order is *really* important for overlap subtitles positionning */
- qsort( pp_subpicture, i_subpicture, sizeof(*pp_subpicture), SubpictureCmp );
+ if( !p_output )
+ return NULL;
+ subpicture_region_t **pp_output_last = &p_output->p_region;
/* Allocate area array for subtitle overlap */
+ spu_area_t p_subtitle_area_buffer[VOUT_MAX_SUBPICTURES];
+ spu_area_t *p_subtitle_area;
+ int i_subtitle_area;
+
i_subtitle_area = 0;
p_subtitle_area = p_subtitle_area_buffer;
if( i_subtitle_region_count > sizeof(p_subtitle_area_buffer)/sizeof(*p_subtitle_area_buffer) )
if( !p_subpic->p_region )
continue;
- /* FIXME when possible use a better rendering size than source size
- * (max of display size and source size for example) FIXME */
- int i_render_width = p_subpic->i_original_picture_width;
- int i_render_height = p_subpic->i_original_picture_height;
- if( !i_render_width || !i_render_height )
+ if( p_subpic->i_original_picture_width <= 0 ||
+ p_subpic->i_original_picture_height <= 0 )
{
- if( i_render_width != 0 || i_render_height != 0 )
- msg_Err( p_spu, "unsupported original picture size %dx%d",
- i_render_width, i_render_height );
+ if( p_subpic->i_original_picture_width > 0 ||
+ p_subpic->i_original_picture_height > 0 )
+ msg_Err( p_spu, "original picture size %dx%d is unsupported",
+ p_subpic->i_original_picture_width,
+ p_subpic->i_original_picture_height );
+ else
+ msg_Warn( p_spu, "original picture size is undefined" );
- p_subpic->i_original_picture_width = i_render_width = i_source_video_width;
- p_subpic->i_original_picture_height = i_render_height = i_source_video_height;
+ p_subpic->i_original_picture_width = p_fmt_src->i_width;
+ p_subpic->i_original_picture_height = p_fmt_src->i_height;
}
if( p_sys->p_text )
{
+ /* FIXME aspect ratio ? */
p_sys->p_text->fmt_out.video.i_width =
- p_sys->p_text->fmt_out.video.i_visible_width = i_render_width;
+ p_sys->p_text->fmt_out.video.i_visible_width = p_subpic->i_original_picture_width;
p_sys->p_text->fmt_out.video.i_height =
- p_sys->p_text->fmt_out.video.i_visible_height = i_render_height;
- }
-
- /* Compute scaling from picture to source size */
- spu_scale_t scale = spu_scale_createq( i_source_video_width, i_render_width,
- i_source_video_height, i_render_height );
-
- /* Update scaling from source size to display size(p_fmt_dst) */
- scale.w = scale.w * p_fmt_dst->i_width / i_source_video_width;
- scale.h = scale.h * p_fmt_dst->i_height / i_source_video_height;
+ p_sys->p_text->fmt_out.video.i_visible_height = p_subpic->i_original_picture_height;
- /* Set default subpicture aspect ratio
- * FIXME if we only handle 1 aspect ratio per picture, why is it set per
- * region ? */
- p_region = p_subpic->p_region;
- if( !p_region->fmt.i_sar_num || !p_region->fmt.i_sar_den )
- {
- p_region->fmt.i_sar_den = p_fmt_dst->i_sar_den;
- p_region->fmt.i_sar_num = p_fmt_dst->i_sar_num;
- }
-
- /* Take care of the aspect ratio */
- if( p_region->fmt.i_sar_num * p_fmt_dst->i_sar_den !=
- p_region->fmt.i_sar_den * p_fmt_dst->i_sar_num )
- {
- /* FIXME FIXME what about region->i_x/i_y ? */
- scale.w = scale.w *
- (int64_t)p_region->fmt.i_sar_num * p_fmt_dst->i_sar_den /
- p_region->fmt.i_sar_den / p_fmt_dst->i_sar_num;
+ var_SetInteger( p_sys->p_text, "scale", SCALE_UNIT );
}
/* Render all regions
{
spu_area_t area;
+ /* Compute region scale AR */
+ video_format_t region_fmt =p_region->fmt;
+ if( region_fmt.i_sar_num <= 0 || region_fmt.i_sar_den <= 0 )
+ {
+ region_fmt.i_sar_num = p_fmt_src->i_sar_num;
+ region_fmt.i_sar_den = p_fmt_src->i_sar_den;
+ }
+
+ /* Compute scaling from original size to destination size
+ * FIXME The current scaling ensure that the heights match, the width being
+ * cropped.
+ */
+ spu_scale_t scale= spu_scale_createq( (int64_t)p_fmt_dst->i_height * p_fmt_dst->i_sar_den * region_fmt.i_sar_num,
+ (int64_t)p_subpic->i_original_picture_height * p_fmt_dst->i_sar_num * region_fmt.i_sar_den,
+ p_fmt_dst->i_height,
+ p_subpic->i_original_picture_height );
+
/* Check scale validity */
if( scale.w <= 0 || scale.h <= 0 )
continue;
/* */
- subpicture_region_t *p_render;
- SpuRenderRegion( p_spu, &p_render, &area,
- p_subpic, p_region, scale, p_fmt_dst,
+ SpuRenderRegion( p_spu, pp_output_last, &area,
+ p_subpic, p_region, scale,
+ p_chroma_list, p_fmt_dst,
p_subtitle_area, i_subtitle_area,
p_subpic->b_subtitle ? render_subtitle_date : render_osd_date );
- if( p_render )
- {
- subpicture_region_t **pp_last = &p_output->p_region;
- while( *pp_last )
- pp_last = &(*pp_last)->p_next;
- *pp_last = p_render;
- }
+ if( *pp_output_last )
+ pp_output_last = &(*pp_output_last)->p_next;
if( p_subpic->b_subtitle )
{
p_subtitle_area[i_subtitle_area++] = area;
}
}
- if( p_subpic->b_subtitle )
+ if( p_subpic->b_subtitle && p_subpic->p_region )
p_subpic->b_absolute = true;
}
p_spu );
/* Load text and scale module */
- SpuRenderCreateAndLoadText( p_spu );
- SpuRenderCreateAndLoadScale( p_spu );
+ p_sys->p_text = SpuRenderCreateAndLoadText( p_spu );
+
+ /* XXX p_spu->p_scale is used for all conversion/scaling except yuvp to
+ * yuva/rgba */
+ p_sys->p_scale = SpuRenderCreateAndLoadScale( VLC_OBJECT(p_spu),
+ VLC_CODEC_YUVA, VLC_CODEC_RGBA, true );
+
+ /* This one is used for YUVP to YUVA/RGBA without scaling
+ * FIXME rename it */
+ p_sys->p_scale_yuvp = SpuRenderCreateAndLoadScale( VLC_OBJECT(p_spu),
+ VLC_CODEC_YUVP, VLC_CODEC_YUVA, false );
/* */
p_sys->i_last_sort_date = -1;
vlc_mutex_lock( &p_spu->p->lock );
p_spu->p->p_input = p_input;
- FilterRelease( p_spu->p->p_text );
- p_spu->p->p_text = NULL;
- SpuRenderCreateAndLoadText( p_spu );
+ if( p_spu->p->p_text )
+ FilterRelease( p_spu->p->p_text );
+ p_spu->p->p_text = SpuRenderCreateAndLoadText( p_spu );
vlc_mutex_unlock( &p_spu->p->lock );
}
}
subpicture_t *spu_Render( spu_t *p_spu,
+ const vlc_fourcc_t *p_chroma_list,
const video_format_t *p_fmt_dst,
const video_format_t *p_fmt_src,
mtime_t render_subtitle_date,
filter_chain_SubFilter( p_sys->p_chain, render_osd_date );
vlc_mutex_unlock( &p_sys->chain_lock );
- /* Get the sorted list of subpicture to render */
+ static const vlc_fourcc_t p_chroma_list_default_yuv[] = {
+ VLC_CODEC_YUVA,
+ VLC_CODEC_RGBA,
+ VLC_CODEC_YUVP,
+ 0,
+ };
+ static const vlc_fourcc_t p_chroma_list_default_rgb[] = {
+ VLC_CODEC_RGBA,
+ VLC_CODEC_YUVA,
+ VLC_CODEC_YUVP,
+ 0,
+ };
+
+ if( !p_chroma_list || *p_chroma_list == 0 )
+ p_chroma_list = vlc_fourcc_IsYUV(p_fmt_dst->i_chroma) ? p_chroma_list_default_yuv
+ : p_chroma_list_default_rgb;
+
vlc_mutex_lock( &p_sys->lock );
- subpicture_t *p_list = SpuSortSubpictures( p_spu,
- render_subtitle_date,
- render_osd_date,
- b_subtitle_only );
- if( !p_list )
+ unsigned int i_subpicture;
+ subpicture_t *pp_subpicture[VOUT_MAX_SUBPICTURES];
+
+ /* Get an array of subpictures to render */
+ SpuSelectSubpictures( p_spu, &i_subpicture, pp_subpicture,
+ render_subtitle_date, render_osd_date, b_subtitle_only );
+ if( i_subpicture <= 0 )
{
vlc_mutex_unlock( &p_sys->lock );
return NULL;
}
- /* Render the current list of subpictures */
+ /* Updates the subpictures */
+ for( unsigned i = 0; i < i_subpicture; i++ )
+ {
+ subpicture_t *p_subpic = pp_subpicture[i];
+ subpicture_Update( p_subpic,
+ p_fmt_src, p_fmt_dst,
+ p_subpic->b_subtitle ? render_subtitle_date : render_osd_date );
+ }
+
+ /* Now order the subpicture array
+ * XXX The order is *really* important for overlap subtitles positionning */
+ qsort( pp_subpicture, i_subpicture, sizeof(*pp_subpicture), SubpictureCmp );
+
+ /* Render the subpictures */
subpicture_t *p_render = SpuRenderSubpictures( p_spu,
+ i_subpicture, pp_subpicture,
+ p_chroma_list,
p_fmt_dst,
- p_list,
p_fmt_src,
render_subtitle_date,
render_osd_date );