#include <vlc_osd.h>
#include "../libvlc.h"
+#include <assert.h>
+
/*****************************************************************************
* Local prototypes
*****************************************************************************/
{
int i_index;
- vlc_object_detach( p_spu );
-
/* Destroy all remaining subpictures */
for( i_index = 0; i_index < VOUT_MAX_SUBPICTURES; i_index++ )
{
*****************************************************************************
* This function renders all sub picture units in the list.
*****************************************************************************/
+static void SpuRenderCreateBlend( spu_t *p_spu, vlc_fourcc_t i_chroma, int i_aspect )
+{
+ filter_t *p_blend;
+
+ assert( !p_spu->p_blend );
+
+ p_spu->p_blend =
+ p_blend = vlc_custom_create( p_spu, sizeof(filter_t),
+ VLC_OBJECT_GENERIC, "blend" );
+ if( !p_blend )
+ return;
+
+ es_format_Init( &p_blend->fmt_in, VIDEO_ES, 0 );
+
+ es_format_Init( &p_blend->fmt_out, VIDEO_ES, 0 );
+ p_blend->fmt_out.video.i_x_offset = 0;
+ p_blend->fmt_out.video.i_y_offset = 0;
+ p_blend->fmt_out.video.i_chroma = i_chroma;
+ p_blend->fmt_out.video.i_aspect = i_aspect;
+
+ /* The blend module will be loaded when needed with the real
+ * input format */
+ p_blend->p_module = NULL;
+
+ /* */
+ vlc_object_attach( p_blend, p_spu );
+}
+static void SpuRenderUpdateBlend( spu_t *p_spu, const video_format_t *p_vfmt )
+{
+ filter_t *p_blend = p_spu->p_blend;
+
+ assert( p_blend );
+
+ /* */
+ if( p_blend->p_module && p_blend->fmt_in.video.i_chroma != p_vfmt->i_chroma )
+ {
+ /* The chroma is not the same, we need to reload the blend module
+ * XXX to match the old behaviour just test !p_blend->fmt_in.video.i_chroma */
+ module_Unneed( p_blend, p_blend->p_module );
+ p_blend->p_module = NULL;
+ }
+
+ /* */
+ p_blend->fmt_in.video = *p_vfmt;
+
+ /* */
+ if( !p_blend->p_module )
+ p_blend->p_module = module_Need( p_blend, "video blending", 0, 0 );
+}
+static void SpuRenderCreateAndLoadText( spu_t *p_spu, int i_width, int i_height )
+{
+ filter_t *p_text;
+
+ assert( !p_spu->p_text );
+
+ p_spu->p_text =
+ p_text = vlc_custom_create( p_spu, sizeof(filter_t),
+ VLC_OBJECT_GENERIC, "spu text" );
+ if( !p_text )
+ return;
+
+ es_format_Init( &p_text->fmt_in, VIDEO_ES, 0 );
+
+ es_format_Init( &p_text->fmt_out, VIDEO_ES, 0 );
+ p_text->fmt_out.video.i_width =
+ p_text->fmt_out.video.i_visible_width = i_width;
+ p_text->fmt_out.video.i_height =
+ p_text->fmt_out.video.i_visible_height = i_height;
+
+ p_text->pf_sub_buffer_new = spu_new_buffer;
+ p_text->pf_sub_buffer_del = spu_del_buffer;
+
+ 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 );
+}
+
+static void SpuRenderCreateAndLoadScale( spu_t *p_spu )
+{
+ /* FIXME: We'll also be using it for YUVA and RGBA blending ... */
+ const vlc_fourcc_t i_dummy_chroma = VLC_FOURCC('Y','U','V','P');
+
+ filter_t *p_scale;
+
+ assert( !p_spu->p_scale );
+
+ p_spu->p_scale =
+ p_scale = vlc_custom_create( p_spu, sizeof(filter_t),
+ VLC_OBJECT_GENERIC, "scale" );
+ if( !p_scale )
+ return;
+
+ es_format_Init( &p_scale->fmt_in, VIDEO_ES, 0 );
+ p_scale->fmt_in.video.i_chroma = i_dummy_chroma;
+ p_scale->fmt_in.video.i_width =
+ p_scale->fmt_in.video.i_height = 32;
+
+ es_format_Init( &p_scale->fmt_out, VIDEO_ES, 0 );
+ p_scale->fmt_out.video.i_chroma = i_dummy_chroma;
+ p_scale->fmt_out.video.i_width =
+ p_scale->fmt_out.video.i_height = 16;
+
+ p_scale->pf_vout_buffer_new = spu_new_video_buffer;
+ p_scale->pf_vout_buffer_del = spu_del_video_buffer;
+
+ vlc_object_attach( p_scale, p_spu );
+ p_scale->p_module = module_Need( p_spu->p_scale, "video filter2", 0, 0 );
+}
+
+
void spu_RenderSubpictures( spu_t *p_spu, video_format_t *p_fmt,
picture_t *p_pic_dst, picture_t *p_pic_src,
subpicture_t *p_subpic,
if ( p_subpic->p_region ) {
spu_DestroyRegion( p_spu, p_subpic->p_region );
}
- p_subpic->p_region = p_region = p_subpic->pf_update_regions( p_fmt, p_spu, p_subpic, mdate() );
+
+ /* TODO do not reverse the scaling that was done before calling
+ * spu_RenderSubpictures, just pass it along (or do it inside
+ * spu_RenderSubpictures) */
+ video_format_t fmt_org = *p_fmt;
+ 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->p_region = p_region = p_subpic->pf_update_regions( &fmt_org, p_spu, p_subpic, mdate() );
}
else
{
p_region = p_subpic->p_region;
}
- /* Load the blending module */
+ /* Create the blending module */
if( !p_spu->p_blend && p_region )
- {
- p_spu->p_blend = vlc_object_create( p_spu, VLC_OBJECT_FILTER );
- vlc_object_attach( p_spu->p_blend, p_spu );
- p_spu->p_blend->fmt_out.video.i_x_offset =
- p_spu->p_blend->fmt_out.video.i_y_offset = 0;
- p_spu->p_blend->fmt_out.video.i_aspect = p_fmt->i_aspect;
- p_spu->p_blend->fmt_out.video.i_chroma = p_fmt->i_chroma;
-
- /* The blend module will be loaded when needed with the real
- * input format */
- memset( &p_spu->p_blend->fmt_in, 0, sizeof(p_spu->p_blend->fmt_in) );
- p_spu->p_blend->p_module = NULL;
- }
+ SpuRenderCreateBlend( p_spu, p_fmt->i_chroma, p_fmt->i_aspect );
/* Load the text rendering module; it is possible there is a
* text region somewhere in the subpicture other than the first
* element in the region list, so just load it anyway as we'll
* probably want it sooner or later. */
if( !p_spu->p_text && p_region )
- {
- char *psz_modulename = NULL;
-
- p_spu->p_text = vlc_object_create( p_spu, VLC_OBJECT_FILTER );
- vlc_object_attach( p_spu->p_text, p_spu );
-
- p_spu->p_text->fmt_out.video.i_width =
- p_spu->p_text->fmt_out.video.i_visible_width =
- p_fmt->i_width;
- p_spu->p_text->fmt_out.video.i_height =
- p_spu->p_text->fmt_out.video.i_visible_height =
- p_fmt->i_height;
-
- p_spu->p_text->pf_sub_buffer_new = spu_new_buffer;
- p_spu->p_text->pf_sub_buffer_del = spu_del_buffer;
-
- psz_modulename = var_CreateGetString( p_spu, "text-renderer" );
- if( psz_modulename && *psz_modulename )
- {
- p_spu->p_text->p_module =
- module_Need( p_spu->p_text, "text renderer",
- psz_modulename, true );
- }
- if( !p_spu->p_text->p_module )
- {
- p_spu->p_text->p_module =
- module_Need( p_spu->p_text, "text renderer", 0, 0 );
- }
- free( psz_modulename );
- }
+ SpuRenderCreateAndLoadText( p_spu, p_fmt->i_width, p_fmt->i_height );
if( p_spu->p_text )
{
(((pi_scale_width[ SCALE_DEFAULT ] > 0) || (pi_scale_height[ SCALE_DEFAULT ] > 0)) &&
((pi_scale_width[ SCALE_DEFAULT ] != 1000) || (pi_scale_height[ SCALE_DEFAULT ] != 1000)))) )
{
- p_spu->p_scale = vlc_object_create( p_spu, VLC_OBJECT_FILTER );
- vlc_object_attach( p_spu->p_scale, p_spu );
- p_spu->p_scale->fmt_out.video.i_chroma =
- p_spu->p_scale->fmt_in.video.i_chroma =
- VLC_FOURCC('Y','U','V','P');
- /* FIXME: We'll also be using it for YUVA and RGBA blending ... */
-
- p_spu->p_scale->fmt_in.video.i_width =
- p_spu->p_scale->fmt_in.video.i_height = 32;
- p_spu->p_scale->fmt_out.video.i_width =
- p_spu->p_scale->fmt_out.video.i_height = 16;
-
- p_spu->p_scale->pf_vout_buffer_new = spu_new_video_buffer;
- p_spu->p_scale->pf_vout_buffer_del = spu_del_video_buffer;
- p_spu->p_scale->p_module =
- module_Need( p_spu->p_scale, "video filter2", 0, 0 );
+ SpuRenderCreateAndLoadScale( p_spu );
}
while( p_region )
if( p_region->fmt.i_chroma != VLC_FOURCC('T','E','X','T') )
{
- if( p_spu->p_blend->fmt_in.video.i_chroma != p_region->fmt.i_chroma )
- {
- /* The chroma is not the same, we need to reload the blend module
- * XXX to match the old behaviour just test !p_spu->p_blend->fmt_in.video.i_chroma */
- if( p_spu->p_blend->p_module )
- module_Unneed( p_spu->p_blend, p_spu->p_blend->p_module );
-
- p_spu->p_blend->fmt_in.video = p_region->fmt;
- p_spu->p_blend->p_module = module_Need( p_spu->p_blend, "video blending", 0, 0 );
- }
- else
- {
- p_spu->p_blend->fmt_in.video = p_region->fmt;
- }
+ /* */
+ SpuRenderUpdateBlend( p_spu, &p_region->fmt );
/* Force cropping if requested */
if( p_spu->b_force_crop )
* This function destroys the subpictures which belong to the spu channel
* corresponding to i_channel_id.
*****************************************************************************/
-static void SpuClearChannel( spu_t *p_spu, int i_channel )
+static void SpuClearChannel( spu_t *p_spu, int i_channel, bool b_locked )
{
int i_subpic; /* subpicture index */
subpicture_t *p_subpic = NULL; /* first free subpicture */
- vlc_mutex_lock( &p_spu->subpicture_lock );
+ if( !b_locked )
+ vlc_mutex_lock( &p_spu->subpicture_lock );
for( i_subpic = 0; i_subpic < VOUT_MAX_SUBPICTURES; i_subpic++ )
{
}
}
- vlc_mutex_unlock( &p_spu->subpicture_lock );
+ if( !b_locked )
+ vlc_mutex_unlock( &p_spu->subpicture_lock );
}
/*****************************************************************************
case SPU_CHANNEL_CLEAR:
i = (int)va_arg( args, int );
- SpuClearChannel( p_spu, i );
+ SpuClearChannel( p_spu, i, false );
break;
default:
static void sub_filter_allocation_clear( filter_t *p_filter )
{
+ filter_owner_sys_t *p_sys = p_filter->p_owner;
+ SpuClearChannel( p_sys->p_spu, p_sys->i_channel, true );
free( p_filter->p_owner );
}