mirror of https://code.videolan.org/videolan/vlc
vlc_filter: return a non-text subpicture region when rendering text regions
We no longer need to ugly hack that marks the output region as marked and we don't mix the input and output regions.
This commit is contained in:
parent
569c1d039a
commit
fe415420f3
|
@ -100,8 +100,11 @@ struct vlc_filter_operations
|
|||
/** Filter a subpicture (sub filter) */
|
||||
subpicture_t *(*filter_sub)(filter_t *, subpicture_t *);
|
||||
|
||||
/** Render text (text renderer) */
|
||||
int (*render)(filter_t *, subpicture_region_t *,
|
||||
/** Render text (text renderer)
|
||||
*
|
||||
* \return a picture-based region or NULL
|
||||
*/
|
||||
subpicture_region_t * (*render)(filter_t *,
|
||||
const subpicture_region_t *, const vlc_fourcc_t *);
|
||||
};
|
||||
|
||||
|
|
|
@ -342,8 +342,7 @@ error:
|
|||
*****************************************************************************
|
||||
* This function merges the previously rendered freetype glyphs into a picture
|
||||
*****************************************************************************/
|
||||
static int RenderYUVP( const subpicture_region_t *p_region_in,
|
||||
subpicture_region_t *p_region,
|
||||
static subpicture_region_t *RenderYUVP( const subpicture_region_t *p_region_in,
|
||||
const line_desc_t *p_line,
|
||||
const FT_BBox *p_regionbbox,
|
||||
const FT_BBox *p_bbox )
|
||||
|
@ -372,20 +371,16 @@ static int RenderYUVP( const subpicture_region_t *p_region_in,
|
|||
|
||||
fmt.p_palette = p_region_in->fmt.p_palette ? p_region_in->fmt.p_palette : malloc(sizeof(*fmt.p_palette));
|
||||
|
||||
assert( !p_region->p_picture );
|
||||
p_region->p_picture = picture_NewFromFormat( &fmt );
|
||||
if( !p_region->p_picture )
|
||||
subpicture_region_t *p_region = subpicture_region_New(&fmt);
|
||||
if (unlikely(p_region == NULL))
|
||||
{
|
||||
if (p_region_in->fmt.p_palette == NULL)
|
||||
free(fmt.p_palette);
|
||||
return VLC_EGENERIC;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const unsigned regionnum = p_region_in->fmt.i_sar_num;
|
||||
const unsigned regionden = p_region_in->fmt.i_sar_den;
|
||||
p_region->fmt = fmt;
|
||||
p_region->fmt.i_sar_num = regionnum;
|
||||
p_region->fmt.i_sar_den = regionden;
|
||||
p_region->fmt.i_sar_num = p_region_in->fmt.i_sar_num;
|
||||
p_region->fmt.i_sar_den = p_region_in->fmt.i_sar_den;
|
||||
|
||||
/* Calculate text color components
|
||||
* Only use the first color */
|
||||
|
@ -463,7 +458,7 @@ static int RenderYUVP( const subpicture_region_t *p_region_in,
|
|||
memset( p_top, 0, fmt.i_width );
|
||||
}
|
||||
|
||||
return VLC_SUCCESS;
|
||||
return p_region;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
|
@ -641,9 +636,8 @@ static void RenderCharAXYZ( filter_t *p_filter,
|
|||
}
|
||||
}
|
||||
|
||||
static inline int RenderAXYZ( filter_t *p_filter,
|
||||
static inline subpicture_region_t *RenderAXYZ( filter_t *p_filter,
|
||||
const subpicture_region_t *p_region_in,
|
||||
subpicture_region_t *p_region,
|
||||
const line_desc_t *p_line_head,
|
||||
const FT_BBox *p_regionbbox,
|
||||
const FT_BBox *p_paddedtextbbox,
|
||||
|
@ -666,15 +660,14 @@ static inline int RenderAXYZ( filter_t *p_filter,
|
|||
fmt.space = p_region_in->fmt.space;
|
||||
fmt.mastering = p_region_in->fmt.mastering;
|
||||
|
||||
picture_t *p_picture = p_region->p_picture = picture_NewFromFormat( &fmt );
|
||||
if( !p_region->p_picture )
|
||||
return VLC_EGENERIC;
|
||||
subpicture_region_t *p_region = subpicture_region_New(&fmt);
|
||||
if (unlikely(p_region == NULL))
|
||||
return NULL;
|
||||
|
||||
const unsigned regionnum = p_region_in->fmt.i_sar_num;
|
||||
const unsigned regionden = p_region_in->fmt.i_sar_den;
|
||||
p_region->fmt = fmt;
|
||||
p_region->fmt.i_sar_num = regionnum;
|
||||
p_region->fmt.i_sar_den = regionden;
|
||||
picture_t *p_picture = p_region->p_picture;
|
||||
|
||||
p_region->fmt.i_sar_num = p_region_in->fmt.i_sar_num;
|
||||
p_region->fmt.i_sar_den = p_region_in->fmt.i_sar_den;
|
||||
|
||||
/* Initialize the picture background */
|
||||
const text_style_t *p_style = p_sys->p_default_style;
|
||||
|
@ -713,7 +706,7 @@ static inline int RenderAXYZ( filter_t *p_filter,
|
|||
}
|
||||
}
|
||||
|
||||
return VLC_SUCCESS;
|
||||
return p_region;
|
||||
}
|
||||
|
||||
static void UpdateDefaultLiveStyles( filter_t *p_filter )
|
||||
|
@ -980,14 +973,15 @@ static size_t SegmentsToTextAndStyles( filter_t *p_filter, const text_segment_t
|
|||
* needed glyphs into memory. It is used as pf_add_string callback in
|
||||
* the vout method by this module
|
||||
*/
|
||||
static int Render( filter_t *p_filter, subpicture_region_t *p_region_out,
|
||||
static subpicture_region_t *Render( filter_t *p_filter,
|
||||
const subpicture_region_t *p_region_in,
|
||||
const vlc_fourcc_t *p_chroma_list )
|
||||
{
|
||||
if( !p_region_in || !p_region_in->p_text )
|
||||
return VLC_EGENERIC;
|
||||
return NULL;
|
||||
|
||||
filter_sys_t *p_sys = p_filter->p_sys;
|
||||
subpicture_region_t *region = NULL;
|
||||
bool b_grid = (p_region_in->text_flags & VLC_SUBPIC_TEXT_FLAG_GRID_MODE) != 0;
|
||||
p_sys->i_scale = ( b_grid ) ? 100 : var_InheritInteger( p_filter, "sub-text-scale");
|
||||
|
||||
|
@ -1001,7 +995,7 @@ static int Render( filter_t *p_filter, subpicture_region_t *p_region_out,
|
|||
if( !p_sys->p_faceid )
|
||||
{
|
||||
msg_Err( p_filter, "Render(): Error loading default face" );
|
||||
return VLC_EGENERIC;
|
||||
return NULL;
|
||||
}
|
||||
p_sys->i_font_default_size = i_font_default_size;
|
||||
}
|
||||
|
@ -1015,7 +1009,7 @@ static int Render( filter_t *p_filter, subpicture_region_t *p_region_out,
|
|||
{
|
||||
free( text_block.pp_styles );
|
||||
free( text_block.p_uchars );
|
||||
return VLC_EGENERIC;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* */
|
||||
|
@ -1125,12 +1119,11 @@ static int Render( filter_t *p_filter, subpicture_region_t *p_region_out,
|
|||
regionbbox = paddedbbox;
|
||||
}
|
||||
|
||||
rv = VLC_EGENERIC;
|
||||
for( const vlc_fourcc_t *p_chroma = p_chroma_list; *p_chroma != 0; p_chroma++ )
|
||||
{
|
||||
if( *p_chroma == VLC_CODEC_YUVP )
|
||||
rv = RenderYUVP( p_region_in, p_region_out, text_block.p_laid,
|
||||
®ionbbox, &bbox );
|
||||
region = RenderYUVP( p_region_in, text_block.p_laid,
|
||||
®ionbbox, &bbox );
|
||||
else
|
||||
{
|
||||
const ft_drawing_functions *func;
|
||||
|
@ -1163,29 +1156,29 @@ static int Render( filter_t *p_filter, subpicture_region_t *p_region_out,
|
|||
else
|
||||
continue;
|
||||
|
||||
rv = RenderAXYZ( p_filter, p_region_in, p_region_out, text_block.p_laid,
|
||||
®ionbbox, &paddedbbox, &bbox,
|
||||
*p_chroma,
|
||||
func );
|
||||
region = RenderAXYZ( p_filter, p_region_in, text_block.p_laid,
|
||||
®ionbbox, &paddedbbox, &bbox,
|
||||
*p_chroma,
|
||||
func );
|
||||
}
|
||||
|
||||
if( rv == VLC_SUCCESS )
|
||||
if( region != NULL )
|
||||
{
|
||||
subpicture_region_TextMarkRendered( p_region_out );
|
||||
|
||||
/* Avoid useless pixels:
|
||||
* reshrink/trim Region Box to padded text one,
|
||||
* but update offsets to keep position and have same rendering */
|
||||
// if( (bboxcolor & 0xFF) == 0 )
|
||||
{
|
||||
p_region_out->i_x = (paddedbbox.xMin - regionbbox.xMin) + p_region_in->i_x;
|
||||
p_region_out->i_y = (regionbbox.yMax - paddedbbox.yMax) + p_region_in->i_y;
|
||||
region->i_x = (paddedbbox.xMin - regionbbox.xMin) + p_region_in->i_x;
|
||||
region->i_y = (regionbbox.yMax - paddedbbox.yMax) + p_region_in->i_y;
|
||||
}
|
||||
// else /* case where the bounding box is larger and visible */
|
||||
// {
|
||||
// p_region_out->i_x = p_region_in->i_x;
|
||||
// p_region_out->i_y = p_region_in->i_y;
|
||||
// region->i_x = p_region_in->i_x;
|
||||
// region->i_y = p_region_in->i_y;
|
||||
// }
|
||||
region->i_alpha = p_region_in->i_alpha;
|
||||
region->i_align = p_region_in->i_align;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1198,7 +1191,7 @@ done:
|
|||
if( text_block.pp_ruby )
|
||||
FreeRubyBlockArray( text_block.pp_ruby, text_block.i_count );
|
||||
|
||||
return rv;
|
||||
return region;
|
||||
}
|
||||
|
||||
static const struct vlc_filter_operations filter_ops =
|
||||
|
|
|
@ -37,8 +37,7 @@
|
|||
|
||||
static int Create (filter_t *);
|
||||
static void Destroy(filter_t *);
|
||||
static int RenderText(filter_t *,
|
||||
subpicture_region_t *,
|
||||
static subpicture_region_t *RenderText(filter_t *,
|
||||
const subpicture_region_t *,
|
||||
const vlc_fourcc_t *);
|
||||
|
||||
|
@ -97,8 +96,7 @@ static NSString * languageCodeForString(NSString *string) {
|
|||
return (NSString *)CFStringTokenizerCopyBestStringLanguage((CFStringRef)string, CFRangeMake(0, [string length]));
|
||||
}
|
||||
|
||||
static int RenderText(filter_t *p_filter,
|
||||
subpicture_region_t *p_region_out,
|
||||
static subpicture_region_t *RenderText(filter_t *p_filter,
|
||||
const subpicture_region_t *p_region_in,
|
||||
const vlc_fourcc_t *p_chroma_list)
|
||||
{
|
||||
|
@ -107,7 +105,7 @@ static int RenderText(filter_t *p_filter,
|
|||
const text_segment_t *p_segment = p_region_in->p_text;
|
||||
|
||||
if (!p_segment)
|
||||
return VLC_EGENERIC;
|
||||
return NULL;
|
||||
|
||||
for ( const text_segment_t *s = p_segment; s != NULL; s = s->p_next ) {
|
||||
if ( !s->psz_text )
|
||||
|
@ -155,6 +153,6 @@ static int RenderText(filter_t *p_filter,
|
|||
[p_sys->speechSynthesizer startSpeakingString:stringToSpeech];
|
||||
}
|
||||
|
||||
return VLC_SUCCESS;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,8 +56,7 @@ DEFINE_GUID(CLSID_SpObjectTokenCategory, 0xa910187f, 0x0c7a, 0x45ac, 0x92,0xcc,
|
|||
extern "C" {
|
||||
static int Create (filter_t *);
|
||||
static void Destroy(filter_t *);
|
||||
static int RenderText(filter_t *,
|
||||
subpicture_region_t *,
|
||||
static subpicture_region_t *RenderText(filter_t *,
|
||||
const subpicture_region_t *,
|
||||
const vlc_fourcc_t *);
|
||||
}
|
||||
|
@ -213,8 +212,7 @@ error:
|
|||
return -ENOENT;
|
||||
}
|
||||
|
||||
static int RenderText(filter_t *p_filter,
|
||||
subpicture_region_t *,
|
||||
static subpicture_region_t *RenderText(filter_t *p_filter,
|
||||
const subpicture_region_t *region_in,
|
||||
const vlc_fourcc_t *)
|
||||
{
|
||||
|
@ -223,7 +221,7 @@ static int RenderText(filter_t *p_filter,
|
|||
sys->cmd.render_text.region = region_in;
|
||||
sys->cmd_available.post();
|
||||
sys->cmd_ready.wait();
|
||||
return VLC_EGENERIC; /* We don't generate output region. */
|
||||
return NULL; /* We don't generate output region. */
|
||||
}
|
||||
|
||||
static const struct vlc_filter_operations filter_ops = []{
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
*****************************************************************************/
|
||||
static int Create ( filter_t * );
|
||||
static void Destroy ( filter_t * );
|
||||
static int RenderText( filter_t *p_filter, subpicture_region_t *p_region_out,
|
||||
static subpicture_region_t *RenderText( filter_t *p_filter,
|
||||
const subpicture_region_t *p_region_in,
|
||||
const vlc_fourcc_t * );
|
||||
|
||||
|
@ -328,25 +328,22 @@ static char * SegmentsToSVG( text_segment_t *p_segment, int i_height, int *pi_to
|
|||
return psz_result;
|
||||
}
|
||||
|
||||
static int RenderText( filter_t *p_filter, subpicture_region_t *p_region_out,
|
||||
static subpicture_region_t *RenderText( filter_t *p_filter,
|
||||
const subpicture_region_t *p_region_in,
|
||||
const vlc_fourcc_t *p_chroma_list )
|
||||
{
|
||||
/* Sanity check */
|
||||
if( !p_region_in || !p_region_out || !p_region_in->p_text )
|
||||
return VLC_EGENERIC;
|
||||
if( !p_region_in || !p_region_in->p_text )
|
||||
return NULL;
|
||||
|
||||
for( size_t i=0; p_chroma_list[i]; i++ )
|
||||
{
|
||||
if( p_chroma_list[i] == VLC_CODEC_BGRA )
|
||||
break;
|
||||
if( p_chroma_list[i] == 0 )
|
||||
return VLC_EGENERIC;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p_region_out->i_x = p_region_in->i_x;
|
||||
p_region_out->i_y = p_region_in->i_y;
|
||||
|
||||
unsigned i_width = p_filter->fmt_out.video.i_visible_width;
|
||||
if( (unsigned) p_region_in->i_x <= i_width )
|
||||
i_width -= p_region_in->i_x;
|
||||
|
@ -356,7 +353,7 @@ static int RenderText( filter_t *p_filter, subpicture_region_t *p_region_out,
|
|||
i_height -= p_region_in->i_y;
|
||||
|
||||
if( i_height == 0 || i_width == 0 )
|
||||
return VLC_EGENERIC;
|
||||
return NULL;
|
||||
|
||||
char *psz_svg;
|
||||
/* Check if the data is SVG or pure text. In the latter case,
|
||||
|
@ -379,19 +376,23 @@ static int RenderText( filter_t *p_filter, subpicture_region_t *p_region_out,
|
|||
}
|
||||
|
||||
if( !psz_svg )
|
||||
return VLC_EGENERIC;
|
||||
return NULL;
|
||||
|
||||
picture_t *p_picture = svg_RenderPicture( p_filter, psz_svg );
|
||||
|
||||
free( psz_svg );
|
||||
|
||||
if (p_picture)
|
||||
{
|
||||
p_region_out->p_picture = p_picture;
|
||||
video_format_Clean( &p_region_out->fmt );
|
||||
video_format_Copy( &p_region_out->fmt, &p_picture->format );
|
||||
subpicture_region_TextMarkRendered(p_region_out);
|
||||
return VLC_SUCCESS;
|
||||
}
|
||||
return VLC_EGENERIC;
|
||||
if (p_picture == NULL)
|
||||
return NULL;
|
||||
|
||||
subpicture_region_t *p_region_out = subpicture_region_ForPicture(&p_picture->format, p_picture);
|
||||
picture_Release(p_picture);
|
||||
if (unlikely(p_region_out == NULL))
|
||||
return NULL;
|
||||
p_region_out->i_x = p_region_in->i_x;
|
||||
p_region_out->i_y = p_region_in->i_y;
|
||||
p_region_out->i_alpha = p_region_in->i_alpha;
|
||||
p_region_out->i_align = p_region_in->i_align;
|
||||
|
||||
return p_region_out;
|
||||
}
|
||||
|
|
|
@ -37,13 +37,13 @@ vlc_module_begin ()
|
|||
vlc_module_end ()
|
||||
|
||||
|
||||
static int RenderText( filter_t *p_filter, subpicture_region_t *p_region_out,
|
||||
static subpicture_region_t *RenderText( filter_t *p_filter,
|
||||
const subpicture_region_t *p_region_in,
|
||||
const vlc_fourcc_t *p_chroma_list )
|
||||
{
|
||||
VLC_UNUSED(p_filter); VLC_UNUSED(p_region_out); VLC_UNUSED(p_region_in);
|
||||
VLC_UNUSED(p_filter); VLC_UNUSED(p_region_in);
|
||||
VLC_UNUSED(p_chroma_list);
|
||||
return VLC_EGENERIC;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const struct vlc_filter_operations filter_ops = {
|
||||
|
|
|
@ -313,7 +313,7 @@ static filter_t *SpuRenderCreateAndLoadScale(vlc_object_t *object,
|
|||
return scale;
|
||||
}
|
||||
|
||||
static int SpuRenderText(spu_t *spu,
|
||||
static subpicture_region_t *SpuRenderText(spu_t *spu,
|
||||
subpicture_region_t *region,
|
||||
unsigned i_original_width,
|
||||
unsigned i_original_height,
|
||||
|
@ -327,7 +327,7 @@ static int SpuRenderText(spu_t *spu,
|
|||
if(unlikely(text == NULL))
|
||||
{
|
||||
vlc_mutex_unlock(&sys->textlock);
|
||||
return VLC_EGENERIC;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// assume rendered text is in sRGB if nothing is set
|
||||
|
@ -347,10 +347,11 @@ static int SpuRenderText(spu_t *spu,
|
|||
text->fmt_out.video.i_height =
|
||||
text->fmt_out.video.i_visible_height = i_original_height;
|
||||
|
||||
int i_ret = text->ops->render(text, region, region, chroma_list);
|
||||
subpicture_region_t *rendered_region = text->ops->render(text, region, chroma_list);
|
||||
assert(rendered_region == NULL || !subpicture_region_IsText(rendered_region));
|
||||
|
||||
vlc_mutex_unlock(&sys->textlock);
|
||||
return i_ret;
|
||||
return rendered_region;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -808,13 +809,15 @@ static subpicture_region_t *SpuRenderRegion(spu_t *spu,
|
|||
/* Render text region */
|
||||
if (subpicture_region_IsText( region ))
|
||||
{
|
||||
if(SpuRenderText(spu, region,
|
||||
subpicture_region_t *rendered_text =
|
||||
SpuRenderText(spu, region,
|
||||
i_original_width, i_original_height,
|
||||
chroma_list) != VLC_SUCCESS)
|
||||
return NULL;
|
||||
if(subpicture_region_IsText( region ))
|
||||
chroma_list);
|
||||
if ( rendered_text == NULL)
|
||||
// not a rendering error for Text-To-Speech
|
||||
return NULL;
|
||||
// FIXME notify the caller it is allocated
|
||||
region = rendered_text;
|
||||
}
|
||||
|
||||
video_format_AdjustColorSpace(®ion->fmt);
|
||||
|
@ -1530,9 +1533,16 @@ static void spu_PrerenderText(spu_t *spu, subpicture_t *p_subpic,
|
|||
{
|
||||
if(!subpicture_region_IsText( region ))
|
||||
continue;
|
||||
SpuRenderText(spu, region,
|
||||
i_original_picture_width, i_original_picture_height,
|
||||
chroma_list);
|
||||
subpicture_region_t *rendered_text =
|
||||
SpuRenderText(spu, region,
|
||||
i_original_picture_width, i_original_picture_height,
|
||||
chroma_list);
|
||||
if (rendered_text == NULL)
|
||||
vlc_spu_regions_remove(&p_subpic->regions, region);
|
||||
else
|
||||
// replace the text region with the rendered region
|
||||
vlc_list_replace(®ion->node, &rendered_text->node);
|
||||
subpicture_region_Delete(region);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -255,15 +255,15 @@ static int OpenWindow(vlc_window_t *wnd)
|
|||
return VLC_SUCCESS;
|
||||
}
|
||||
|
||||
static int TextRendererRender(filter_t *filter, subpicture_region_t *region_out,
|
||||
static subpicture_region_t *TextRendererRender(filter_t *filter,
|
||||
const subpicture_region_t *region_in,
|
||||
const vlc_fourcc_t *chroma_list)
|
||||
{
|
||||
(void) region_out; (void) chroma_list;
|
||||
(void) chroma_list;
|
||||
struct input_decoder_scenario *scenario = &input_decoder_scenarios[current_scenario];
|
||||
if (scenario->text_renderer_render != NULL)
|
||||
scenario->text_renderer_render(filter, region_in);
|
||||
return VLC_EGENERIC;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int OpenTextRenderer(filter_t *filter)
|
||||
|
|
Loading…
Reference in New Issue