/* SPU output callbacks
* XXX use decoder_NewSubpicture and decoder_DeleteSubpicture */
- subpicture_t *(*pf_spu_buffer_new)( decoder_t * );
+ subpicture_t *(*pf_spu_buffer_new)( decoder_t *, const subpicture_updater_t * );
void (*pf_spu_buffer_del)( decoder_t *, subpicture_t * );
/* Input attachments
* buffer. You have to release it using decoder_DeleteSubpicture or by returning
* it to the caller as a pf_decode_sub return value.
*/
-VLC_EXPORT( subpicture_t *, decoder_NewSubpicture, ( decoder_t * ) LIBVLC_USED );
+VLC_EXPORT( subpicture_t *, decoder_NewSubpicture, ( decoder_t *, const subpicture_updater_t * ) LIBVLC_USED );
/**
* This function will release a subpicture created by decoder_NewSubicture.
*/
VLC_EXPORT( void, subpicture_region_ChainDelete, ( subpicture_region_t *p_head ) );
+/**
+ *
+ */
+typedef struct subpicture_updater_sys_t subpicture_updater_sys_t;
+typedef struct
+{
+ int (*pf_validate)( subpicture_t *,
+ bool has_src_changed, const video_format_t *p_fmt_src,
+ bool has_dst_changed, const video_format_t *p_fmt_dst,
+ mtime_t);
+ void (*pf_update) ( subpicture_t *,
+ const video_format_t *p_fmt_src,
+ const video_format_t *p_fmt_dst,
+ mtime_t );
+ void (*pf_destroy) ( subpicture_t * );
+ subpicture_updater_sys_t *p_sys;
+} subpicture_updater_t;
+
+typedef struct subpicture_private_t subpicture_private_t;
+
/**
* Video subtitle
*
int i_alpha; /**< transparency */
/**@}*/
- /** Pointer to function that cleans up the private data of this subtitle */
- void ( *pf_destroy ) ( subpicture_t * );
-
- /** Pointer to function that update the regions before rendering (optionnal) */
- void (*pf_update_regions)( spu_t *,
- subpicture_t *, const video_format_t *, mtime_t );
+ subpicture_updater_t updater;
- /** Private data - the subtitle plugin might want to put stuff here to
- * keep track of the subpicture */
- subpicture_sys_t *p_sys; /* subpicture data */
+ subpicture_private_t *p_private; /* Reserved to the core */
};
-
/**
* This function create a new empty subpicture.
*
* You must use subpicture_Delete to destroy it.
*/
-VLC_EXPORT( subpicture_t *, subpicture_New, ( void ) );
+VLC_EXPORT( subpicture_t *, subpicture_New, ( const subpicture_updater_t * ) );
/**
* This function delete a subpicture created by subpicture_New.
*/
static subpicture_t *ConvertSubtitle(decoder_t *dec, AVSubtitle *ffsub, mtime_t pts)
{
- subpicture_t *spu = decoder_NewSubpicture(dec);
+ subpicture_t *spu = decoder_NewSubpicture(dec, NULL);
if (!spu)
return NULL;
EnsureUTF8( psz_html );
/* Create the subpicture unit */
- p_spu = decoder_NewSubpicture( p_dec );
+ p_spu = decoder_NewSubpicture( p_dec, NULL );
if( !p_spu )
{
msg_Warn( p_dec, "can't get spu buffer" );
int i;
/* Allocate the subpicture internal data. */
- p_spu = decoder_NewSubpicture( p_dec );
+ p_spu = decoder_NewSubpicture( p_dec, NULL );
if( !p_spu ) return NULL;
p_spu->i_start = p_data->i_pts;
int i_base_y;
/* Allocate the subpicture internal data. */
- p_spu = decoder_NewSubpicture( p_dec );
+ p_spu = decoder_NewSubpicture( p_dec, NULL );
if( !p_spu )
return NULL;
bool b_use_tiger;
};
-struct subpicture_sys_t
+struct subpicture_updater_sys_t
{
decoder_sys_t *p_dec_sys;
mtime_t i_start;
static void TigerDestroySubpicture( subpicture_t *p_subpic )
{
- DecSysRelease( p_subpic->p_sys->p_dec_sys );
+ DecSysRelease( p_subpic->updater.p_sys->p_dec_sys );
+ free( p_subpic->updater.p_sys );
}
-
-static void SubpictureReleaseRegions( subpicture_t *p_subpic )
-{
- if( p_subpic->p_region)
- {
- subpicture_region_ChainDelete( p_subpic->p_region );
- p_subpic->p_region = NULL;
- }
-}
-
/*
* We get premultiplied alpha, but VLC doesn't expect this, so we demultiply
* alpha to avoid double multiply (and thus thinner text than we should)).
PROFILE_STOP( tiger_renderer_postprocess );
}
-/* Tiger renders can end up looking a bit crap since they get overlaid on top of
- a subsampled YUV image, so there can be a fair amount of chroma bleeding.
- Looks good with white though since it's all luma. Hopefully that will be the
- common case. */
-static void TigerUpdateRegions( spu_t *p_spu, subpicture_t *p_subpic, const video_format_t *p_fmt, mtime_t ts )
+static int TigerValidateSubpicture( subpicture_t *p_subpic,
+ bool b_fmt_src, const video_format_t *p_fmt_src,
+ bool b_fmt_dst, const video_format_t *p_fmt_dst,
+ mtime_t ts )
{
- decoder_sys_t *p_sys = p_subpic->p_sys->p_dec_sys;
- subpicture_region_t *p_r;
- video_format_t fmt;
- plane_t *p_plane;
- kate_float t;
- int i_ret;
+ decoder_sys_t *p_sys = p_subpic->updater.p_sys->p_dec_sys;
- VLC_UNUSED( p_spu );
+ if( b_fmt_src || b_fmt_dst )
+ return VLC_EGENERIC;
- PROFILE_START( TigerUpdateRegions );
+ PROFILE_START( TigerValidateSubpicture );
/* time in seconds from the start of the stream */
- t = (p_subpic->p_sys->i_start + ts - p_subpic->i_start ) / 1000000.0f;
+ kate_float t = (p_subpic->updater.p_sys->i_start + ts - p_subpic->i_start ) / 1000000.0f;
/* it is likely that the current region (if any) can be kept as is; test for this */
vlc_mutex_lock( &p_sys->lock );
- if( p_subpic->p_region && !p_sys->b_dirty && !tiger_renderer_is_dirty( p_sys->p_tr ))
+ int i_ret;
+ if( p_sys->b_dirty || tiger_renderer_is_dirty( p_sys->p_tr ) )
{
- PROFILE_START( tiger_renderer_update1 );
- i_ret = tiger_renderer_update( p_sys->p_tr, t, 1 );
- PROFILE_STOP( tiger_renderer_update1 );
- if( i_ret < 0 )
- {
- SubpictureReleaseRegions( p_subpic );
- vlc_mutex_unlock( &p_sys->lock );
- return;
- }
-
- if( !tiger_renderer_is_dirty( p_sys->p_tr ) )
- {
- /* we can keep the current region list */
- PROFILE_STOP( TigerUpdateRegions );
- vlc_mutex_unlock( &p_sys->lock );
- return;
- }
+ i_ret = VLC_EGENERIC;
+ goto exit;
+ }
+ if( tiger_renderer_update( p_sys->p_tr, t, 1 ) >= 0 &&
+ tiger_renderer_is_dirty( p_sys->p_tr ) )
+ {
+ i_ret = VLC_EGENERIC;
+ goto exit;
}
+
+ i_ret = VLC_SUCCESS;
+exit:
vlc_mutex_unlock( &p_sys->lock );
+ PROFILE_STOP( TigerValidateSubpicture );
+ return i_ret;
+}
+
+/* Tiger renders can end up looking a bit crap since they get overlaid on top of
+ a subsampled YUV image, so there can be a fair amount of chroma bleeding.
+ Looks good with white though since it's all luma. Hopefully that will be the
+ common case. */
+static void TigerUpdateSubpicture( subpicture_t *p_subpic,
+ const video_format_t *p_fmt_src,
+ const video_format_t *p_fmt_dst,
+ mtime_t ts )
+{
+ decoder_sys_t *p_sys = p_subpic->updater.p_sys->p_dec_sys;
+ plane_t *p_plane;
+ kate_float t;
+ int i_ret;
+
- /* we have to render again, reset current region list */
- SubpictureReleaseRegions( p_subpic );
+ /* time in seconds from the start of the stream */
+ t = (p_subpic->updater.p_sys->i_start + ts - p_subpic->i_start ) / 1000000.0f;
+
+ PROFILE_START( TigerUpdateSubpicture );
/* create a full frame region - this will also tell Tiger the size of the frame */
- fmt = *p_fmt;
- fmt.i_chroma = VLC_CODEC_RGBA;
- fmt.i_width = fmt.i_visible_width;
- fmt.i_height = fmt.i_visible_height;
+ video_format_t fmt = *p_fmt_dst;
+ fmt.i_chroma = VLC_CODEC_RGBA;
fmt.i_bits_per_pixel = 0;
- fmt.i_x_offset = fmt.i_y_offset = 0;
+ fmt.i_width =
+ fmt.i_visible_width = p_fmt_src->i_width;
+ fmt.i_height =
+ fmt.i_visible_height = p_fmt_src->i_height;
+ fmt.i_x_offset = fmt.i_y_offset = 0;
- p_r = subpicture_region_New( &fmt );
+ subpicture_region_t *p_r = subpicture_region_New( &fmt );
if( !p_r )
- {
return;
- }
p_r->i_x = 0;
p_r->i_y = 0;
p_subpic->p_region = p_r;
p_sys->b_dirty = false;
- PROFILE_STOP( TigerUpdateRegions );
+ PROFILE_STOP( TigerUpdateSubpicture );
vlc_mutex_unlock( &p_sys->lock );
/* we have an event */
/* Get a new spu */
- p_spu = decoder_NewSubpicture( p_dec );
+ subpicture_updater_sys_t *p_spu_sys = NULL;
+ if( p_sys->b_use_tiger)
+ {
+ p_spu_sys = malloc( sizeof(*p_spu_sys) );
+ if( !p_spu_sys )
+ return NULL;
+ }
+ subpicture_updater_t updater = {
+ .pf_validate = TigerValidateSubpicture,
+ .pf_update = TigerUpdateSubpicture,
+ .pf_destroy = TigerDestroySubpicture,
+ .p_sys = p_spu_sys,
+ };
+ p_spu = decoder_NewSubpicture( p_dec, p_sys->b_use_tiger ? &updater : NULL );
if( !p_spu )
{
+ free( p_spu_sys );
/* this will happen for lyrics as there is no vout - so no error */
/* msg_Err( p_dec, "Failed to allocate spu buffer" ); */
return NULL;
#ifdef HAVE_TIGER
if( p_sys->b_use_tiger)
{
- /* setup the structure to get our decoder struct back */
- p_spu->p_sys = malloc( sizeof( subpicture_sys_t ));
- if( !p_spu->p_sys )
- {
- decoder_DeleteSubpicture( p_dec, p_spu );
- return NULL;
- }
- p_spu->p_sys->p_dec_sys = p_sys;
- p_spu->p_sys->i_start = p_block->i_pts;
+ p_spu_sys->p_dec_sys = p_sys;
+ p_spu_sys->i_start = p_block->i_pts;
DecSysHold( p_sys );
p_spu->i_stop = __MAX( p_sys->i_max_stop, p_spu->i_stop );
vlc_mutex_lock( &p_sys->lock );
CHECK_TIGER_RET( tiger_renderer_add_event( p_sys->p_tr, ev->ki, ev ) );
vlc_mutex_unlock( &p_sys->lock );
-
- /* hookup render/update routines */
- p_spu->pf_update_regions = TigerUpdateRegions;
- p_spu->pf_destroy = TigerDestroySubpicture;
}
else
#endif
* Local prototypes
*****************************************************************************/
static subpicture_t *DecodeBlock( decoder_t *, block_t ** );
-static void DestroySubpicture( subpicture_t * );
-static void UpdateRegions( spu_t *,
- subpicture_t *, const video_format_t *, mtime_t );
/* Yes libass sux with threads */
typedef struct
static void DecSysRelease( decoder_sys_t *p_sys );
static void DecSysHold( decoder_sys_t *p_sys );
-struct subpicture_sys_t
+/* */
+static int SubpictureValidate( subpicture_t *,
+ bool, const video_format_t *,
+ bool, const video_format_t *,
+ mtime_t );
+static void SubpictureUpdate( subpicture_t *,
+ const video_format_t *,
+ const video_format_t *,
+ mtime_t );
+static void SubpictureDestroy( subpicture_t * );
+
+struct subpicture_updater_sys_t
{
decoder_sys_t *p_dec_sys;
void *p_subs_data;
int i_subs_len;
mtime_t i_pts;
+
+ ASS_Image *p_img;
};
typedef struct
int y1;
} rectangle_t;
-static int BuildRegions( spu_t *p_spu, rectangle_t *p_region, int i_max_region, ASS_Image *p_img_list, int i_width, int i_height );
-static void SubpictureReleaseRegions( spu_t *p_spu, subpicture_t *p_subpic );
+static int BuildRegions( rectangle_t *p_region, int i_max_region, ASS_Image *p_img_list, int i_width, int i_height );
static void RegionDraw( subpicture_region_t *p_region, ASS_Image *p_img );
static vlc_mutex_t libass_lock = VLC_STATIC_MUTEX;
return NULL;
}
- p_spu = decoder_NewSubpicture( p_dec );
- if( !p_spu )
+ subpicture_updater_sys_t *p_spu_sys = malloc( sizeof(*p_spu_sys) );
+ if( !p_spu_sys )
{
- msg_Warn( p_dec, "can't get spu buffer" );
block_Release( p_block );
return NULL;
}
- p_spu->p_sys = malloc( sizeof( subpicture_sys_t ));
- if( !p_spu->p_sys )
+ subpicture_updater_t updater = {
+ .pf_validate = SubpictureValidate,
+ .pf_update = SubpictureUpdate,
+ .pf_destroy = SubpictureDestroy,
+ .p_sys = p_spu_sys,
+ };
+ p_spu = decoder_NewSubpicture( p_dec, &updater );
+ if( !p_spu )
{
- decoder_DeleteSubpicture( p_dec, p_spu );
+ msg_Warn( p_dec, "can't get spu buffer" );
+ free( p_spu_sys );
block_Release( p_block );
return NULL;
}
- p_spu->p_sys->i_subs_len = p_block->i_buffer;
- p_spu->p_sys->p_subs_data = malloc( p_block->i_buffer );
- if( !p_spu->p_sys->p_subs_data )
+ p_spu_sys->p_img = NULL;
+ p_spu_sys->p_dec_sys = p_sys;
+ p_spu_sys->i_subs_len = p_block->i_buffer;
+ p_spu_sys->p_subs_data = malloc( p_block->i_buffer );
+ p_spu_sys->i_pts = p_block->i_pts;
+ if( !p_spu_sys->p_subs_data )
{
- free( p_spu->p_sys );
decoder_DeleteSubpicture( p_dec, p_spu );
block_Release( p_block );
return NULL;
}
- memcpy( p_spu->p_sys->p_subs_data, p_block->p_buffer,
+ memcpy( p_spu_sys->p_subs_data, p_block->p_buffer,
p_block->i_buffer );
- p_spu->p_sys->i_pts = p_block->i_pts;
p_spu->i_start = p_block->i_pts;
p_spu->i_stop = __MAX( p_sys->i_max_stop, p_block->i_pts + p_block->i_length );
vlc_mutex_lock( &libass_lock );
if( p_sys->p_track )
{
- ass_process_chunk( p_sys->p_track, p_spu->p_sys->p_subs_data, p_spu->p_sys->i_subs_len,
+ ass_process_chunk( p_sys->p_track, p_spu_sys->p_subs_data, p_spu_sys->i_subs_len,
p_block->i_pts / 1000, p_block->i_length / 1000 );
}
vlc_mutex_unlock( &libass_lock );
- p_spu->pf_update_regions = UpdateRegions;
- p_spu->pf_destroy = DestroySubpicture;
- p_spu->p_sys->p_dec_sys = p_sys;
-
- DecSysHold( p_sys );
+ DecSysHold( p_sys ); /* Keep a reference for the returned subpicture */
block_Release( p_block );
/****************************************************************************
*
****************************************************************************/
-static void DestroySubpicture( subpicture_t *p_subpic )
+static int SubpictureValidate( subpicture_t *p_subpic,
+ bool b_fmt_src, const video_format_t *p_fmt_src,
+ bool b_fmt_dst, const video_format_t *p_fmt_dst,
+ mtime_t i_ts )
{
- DecSysRelease( p_subpic->p_sys->p_dec_sys );
-
- free( p_subpic->p_sys->p_subs_data );
- free( p_subpic->p_sys );
-}
-
-static void UpdateRegions( spu_t *p_spu, subpicture_t *p_subpic,
- const video_format_t *p_fmt, mtime_t i_ts )
-{
- decoder_sys_t *p_sys = p_subpic->p_sys->p_dec_sys;
+ decoder_sys_t *p_sys = p_subpic->updater.p_sys->p_dec_sys;
ass_handle_t *p_ass = p_sys->p_ass;
- video_format_t fmt;
- bool b_fmt_changed;
-
vlc_mutex_lock( &libass_lock );
- /* */
- fmt = *p_fmt;
- fmt.i_chroma = VLC_CODEC_RGBA;
- fmt.i_width = fmt.i_visible_width;
- fmt.i_height = fmt.i_visible_height;
+ /* FIXME why this mix of src/dst */
+ video_format_t fmt = *p_fmt_dst;
+ fmt.i_chroma = VLC_CODEC_RGBA;
fmt.i_bits_per_pixel = 0;
- fmt.i_x_offset = fmt.i_y_offset = 0;
-
- b_fmt_changed = memcmp( &fmt, &p_ass->fmt, sizeof(fmt) ) != 0;
- if( b_fmt_changed )
+ fmt.i_width =
+ fmt.i_visible_width = p_fmt_src->i_width;
+ fmt.i_height =
+ fmt.i_visible_height = p_fmt_src->i_height;
+ fmt.i_x_offset =
+ fmt.i_y_offset = 0;
+
+ if( b_fmt_src || b_fmt_dst )
{
ass_set_frame_size( p_ass->p_renderer, fmt.i_width, fmt.i_height );
#if defined( LIBASS_VERSION ) && LIBASS_VERSION >= 0x00907000
- ass_set_aspect_ratio( p_ass->p_renderer, 1.0, 1.0 ); // TODO ?
+ ass_set_aspect_ratio( p_ass->p_renderer, 1.0, 1.0 ); // TODO ?
#else
- ass_set_aspect_ratio( p_ass->p_renderer, 1.0 ); // TODO ?
+ ass_set_aspect_ratio( p_ass->p_renderer, 1.0 ); // TODO ?
#endif
-
p_ass->fmt = fmt;
}
/* */
- const mtime_t i_stream_date = p_subpic->p_sys->i_pts + (i_ts - p_subpic->i_start);
+ const mtime_t i_stream_date = p_subpic->updater.p_sys->i_pts + (i_ts - p_subpic->i_start);
int i_changed;
ASS_Image *p_img = ass_render_frame( p_ass->p_renderer, p_sys->p_track,
i_stream_date/1000, &i_changed );
- if( !i_changed && !b_fmt_changed &&
+ if( !i_changed && !b_fmt_src && !b_fmt_dst &&
(p_img != NULL) == (p_subpic->p_region != NULL) )
{
vlc_mutex_unlock( &libass_lock );
- return;
+ return VLC_SUCCESS;
}
+ p_subpic->updater.p_sys->p_img = p_img;
+
+ /* The lock is released by SubpictureUpdate */
+ return VLC_EGENERIC;
+}
+
+static void SubpictureUpdate( subpicture_t *p_subpic,
+ const video_format_t *p_fmt_src,
+ const video_format_t *p_fmt_dst,
+ mtime_t i_ts )
+{
+ decoder_sys_t *p_sys = p_subpic->updater.p_sys->p_dec_sys;
+ ass_handle_t *p_ass = p_sys->p_ass;
+
+ video_format_t fmt = p_ass->fmt;
+ ASS_Image *p_img = p_subpic->updater.p_sys->p_img;
+ //vlc_assert_locked( &libass_lock );
/* */
p_subpic->i_original_picture_height = fmt.i_height;
p_subpic->i_original_picture_width = fmt.i_width;
- SubpictureReleaseRegions( p_spu, p_subpic );
/* XXX to improve efficiency we merge regions that are close minimizing
* the lost surface.
*/
const int i_max_region = 4;
rectangle_t region[i_max_region];
- const int i_region = BuildRegions( p_spu, region, i_max_region, p_img, fmt.i_width, fmt.i_height );
+ const int i_region = BuildRegions( region, i_max_region, p_img, fmt.i_width, fmt.i_height );
if( i_region <= 0 )
{
pp_region_last = &r->p_next;
}
vlc_mutex_unlock( &libass_lock );
+
+}
+static void SubpictureDestroy( subpicture_t *p_subpic )
+{
+ subpicture_updater_sys_t *p_sys = p_subpic->updater.p_sys;
+
+ DecSysRelease( p_sys->p_dec_sys );
+ free( p_sys->p_subs_data );
+ free( p_sys );
}
static rectangle_t r_create( int x0, int y0, int x1, int y1 )
__MAX(a->y0-i_dy, b->y0) < __MIN( a->y1+i_dy, b->y1 );
}
-static int BuildRegions( spu_t *p_spu, rectangle_t *p_region, int i_max_region, ASS_Image *p_img_list, int i_width, int i_height )
+static int BuildRegions( rectangle_t *p_region, int i_max_region, ASS_Image *p_img_list, int i_width, int i_height )
{
ASS_Image *p_tmp;
int i_count;
- VLC_UNUSED(p_spu);
-
#ifdef DEBUG_REGION
int64_t i_ck_start = mdate();
#endif
#endif
}
-
-static void SubpictureReleaseRegions( spu_t *p_spu, subpicture_t *p_subpic )
-{
- VLC_UNUSED( p_spu );
- subpicture_region_ChainDelete( p_subpic->p_region );
- p_subpic->p_region = NULL;
-}
-
/* */
static ass_handle_t *AssHandleHold( decoder_t *p_dec )
{
spu_properties_t spu_properties;
/* Allocate the subpicture internal data. */
- p_spu = decoder_NewSubpicture( p_dec );
+ p_spu = decoder_NewSubpicture( p_dec, NULL );
if( !p_spu ) return NULL;
p_spu->i_original_picture_width =
}
/* Create the subpicture unit */
- p_spu = decoder_NewSubpicture( p_dec );
+ p_spu = decoder_NewSubpicture( p_dec, NULL );
if( !p_spu )
{
msg_Warn( p_dec, "can't get spu buffer" );
}
/* Create the subpicture unit */
- p_spu = decoder_NewSubpicture( p_dec );
+ p_spu = decoder_NewSubpicture( p_dec, NULL );
if( !p_spu )
{
msg_Warn( p_dec, "can't get spu buffer" );
int i;
/* Allocate the subpicture internal data. */
- p_spu = decoder_NewSubpicture( p_dec );
+ p_spu = decoder_NewSubpicture( p_dec, NULL );
if( !p_spu ) return NULL;
p_spu->i_start = p_data->i_pts;
strcpy( p_sys->psz_prev_text, psz_text );
/* Create the subpicture unit */
- p_spu = decoder_NewSubpicture( p_dec );
+ p_spu = decoder_NewSubpicture( p_dec, NULL );
if( !p_spu )
{
msg_Warn( p_dec, "can't get spu buffer" );
/* If there is a page or sub to render, then we do that here */
/* Create the subpicture unit */
- p_spu = decoder_NewSubpicture( p_dec );
+ p_spu = decoder_NewSubpicture( p_dec, NULL );
if( !p_spu )
{
msg_Warn( p_dec, "can't get spu buffer" );
#include <vlc_osd.h>
#include <assert.h>
-static subpicture_t *spu_new_buffer( decoder_t *p_dec )
+static subpicture_t *spu_new_buffer( decoder_t *p_dec,
+ const subpicture_updater_t *p_upd )
{
VLC_UNUSED( p_dec );
- return subpicture_New();
+ return subpicture_New( p_upd );
}
static void spu_del_buffer( decoder_t *p_dec, subpicture_t *p_subpic )
static void vout_link_picture( decoder_t *, picture_t * );
static void vout_unlink_picture( decoder_t *, picture_t * );
-static subpicture_t *spu_new_buffer( decoder_t * );
+static subpicture_t *spu_new_buffer( decoder_t *, const subpicture_updater_t * );
static void spu_del_buffer( decoder_t *, subpicture_t * );
struct decoder_owner_sys_t
p_decoder->pf_aout_buffer_del( p_decoder, p_buffer );
}
-subpicture_t *decoder_NewSubpicture( decoder_t *p_decoder )
+subpicture_t *decoder_NewSubpicture( decoder_t *p_decoder,
+ const subpicture_updater_t *p_dyn )
{
- subpicture_t *p_subpicture = p_decoder->pf_spu_buffer_new( p_decoder );
+ subpicture_t *p_subpicture = p_decoder->pf_spu_buffer_new( p_decoder, p_dyn );
if( !p_subpicture )
msg_Warn( p_decoder, "can't get output subpicture" );
return p_subpicture;
}
+
void decoder_DeleteSubpicture( decoder_t *p_decoder, subpicture_t *p_subpicture )
{
p_decoder->pf_spu_buffer_del( p_decoder, p_subpicture );
vout_ReleasePicture( p_dec->p_owner->p_vout, p_pic );
}
-static subpicture_t *spu_new_buffer( decoder_t *p_dec )
+static subpicture_t *spu_new_buffer( decoder_t *p_dec,
+ const subpicture_updater_t *p_updater )
{
decoder_owner_sys_t *p_owner = p_dec->p_owner;
vout_thread_t *p_vout = NULL;
p_owner->p_spu_vout = p_vout;
}
- p_subpic = subpicture_New();
+ p_subpic = subpicture_New( p_updater );
if( p_subpic )
{
p_subpic->i_channel = p_owner->i_spu_channel;
if( !psz_string ) return VLC_EGENERIC;
- p_spu = subpicture_New();
+ p_spu = subpicture_New( NULL );
if( !p_spu )
return VLC_EGENERIC;
VLC_UNUSED(p_spu);
/* Create and initialize a subpicture */
- p_subpic = subpicture_New();
+ p_subpic = subpicture_New( NULL );
if( p_subpic == NULL ) return NULL;
p_subpic->i_channel = i_channel;
if( p_epg == NULL )
return VLC_EGENERIC;
- p_spu = subpicture_New();
+ p_spu = subpicture_New( NULL );
if( !p_spu )
{
vlc_epg_Delete( p_epg );
if( !psz_string ) return VLC_EGENERIC;
- p_spu = subpicture_New();
+ p_spu = subpicture_New( NULL );
if( !p_spu )
return VLC_EGENERIC;
#define SCALE_UNIT (1000)
+static void SubpictureUpdate( subpicture_t *,
+ const video_format_t *p_fmt_src,
+ const video_format_t *p_fmt_dst,
+ mtime_t i_ts );
static void SubpictureChain( subpicture_t **pp_head, subpicture_t *p_subpic );
static int SubpictureCmp( const void *s0, const void *s1 );
p_subpic != NULL;
p_subpic = p_subpic->p_next )
{
- if( p_subpic->pf_update_regions )
- {
- video_format_t fmt_org = *p_fmt_dst;
- fmt_org.i_width =
- fmt_org.i_visible_width = i_source_video_width;
- fmt_org.i_height =
- fmt_org.i_visible_height = i_source_video_height;
-
- p_subpic->pf_update_regions( p_spu, p_subpic, &fmt_org,
- p_subpic->b_subtitle ? render_subtitle_date : render_osd_date );
- }
+ SubpictureUpdate( p_subpic,
+ p_fmt_src, p_fmt_dst,
+ p_subpic->b_subtitle ? render_subtitle_date : render_osd_date );
/* */
if( p_subpic->b_subtitle )
/*****************************************************************************
* subpicture_t allocation
*****************************************************************************/
-subpicture_t *subpicture_New( void )
+struct subpicture_private_t
+{
+ video_format_t src;
+ video_format_t dst;
+};
+
+subpicture_t *subpicture_New( const subpicture_updater_t *p_upd )
{
subpicture_t *p_subpic = calloc( 1, sizeof(*p_subpic) );
if( !p_subpic )
p_subpic->b_subtitle = false;
p_subpic->i_alpha = 0xFF;
p_subpic->p_region = NULL;
- p_subpic->pf_destroy = NULL;
- p_subpic->p_sys = NULL;
+ if( p_upd )
+ {
+ subpicture_private_t *p_private = malloc( sizeof(*p_private) );
+ if( !p_private )
+ {
+ free( p_subpic );
+ return NULL;
+ }
+ video_format_Init( &p_private->src, 0 );
+ video_format_Init( &p_private->dst, 0 );
+
+ p_subpic->updater = *p_upd;
+ p_subpic->p_private = p_private;
+ }
+ else
+ {
+ p_subpic->p_private = NULL;
+
+ p_subpic->updater.pf_validate = NULL;
+ p_subpic->updater.pf_update = NULL;
+ p_subpic->updater.pf_destroy = NULL;
+ p_subpic->updater.p_sys = NULL;
+ }
return p_subpic;
}
subpicture_region_ChainDelete( p_subpic->p_region );
p_subpic->p_region = NULL;
- if( p_subpic->pf_destroy )
- {
- p_subpic->pf_destroy( p_subpic );
- }
+ if( p_subpic->updater.pf_destroy )
+ p_subpic->updater.pf_destroy( p_subpic );
+
+ free( p_subpic->p_private );
free( p_subpic );
}
if( !p_pip )
return NULL;
- subpicture_t *p_subpic = subpicture_New();
+ subpicture_t *p_subpic = subpicture_New( NULL );
if( !p_subpic )
{
picture_Release( p_pip );
return p_subpic;
}
+static void SubpictureUpdate( subpicture_t *p_subpicture,
+ const video_format_t *p_fmt_src,
+ const video_format_t *p_fmt_dst,
+ mtime_t i_ts )
+{
+ subpicture_updater_t *p_upd = &p_subpicture->updater;
+ subpicture_private_t *p_private = p_subpicture->p_private;
+
+ if( !p_upd->pf_validate )
+ return;
+ if( !p_upd->pf_validate( p_subpicture,
+ !video_format_IsSimilar( p_fmt_src,
+ &p_private->src ), p_fmt_src,
+ !video_format_IsSimilar( p_fmt_dst,
+ &p_private->dst ), p_fmt_dst,
+ i_ts ) )
+ return;
+
+ subpicture_region_ChainDelete( p_subpicture->p_region );
+ p_subpicture->p_region = NULL;
+
+ p_upd->pf_update( p_subpicture, p_fmt_src, p_fmt_dst, i_ts );
+
+ video_format_Clean( &p_private->src );
+ video_format_Clean( &p_private->dst );
+
+ video_format_Copy( &p_private->src, p_fmt_src );
+ video_format_Copy( &p_private->dst, p_fmt_dst );
+}
+
/*****************************************************************************
* subpicture_region_t allocation
*****************************************************************************/
{
filter_owner_sys_t *p_sys = p_filter->p_owner;
- subpicture_t *p_subpicture = subpicture_New();
+ subpicture_t *p_subpicture = subpicture_New( NULL );
if( p_subpicture )
p_subpicture->i_channel = p_sys->i_channel;
return p_subpicture;
static subpicture_t *spu_new_buffer( filter_t *p_filter )
{
VLC_UNUSED(p_filter);
- return subpicture_New();
+ return subpicture_New( NULL );
}
static void spu_del_buffer( filter_t *p_filter, subpicture_t *p_subpic )
{