Commit 06b63706 authored by Gildas Bazin's avatar Gildas Bazin

* src/video_output/vout_subpictures.c, include/vlc_video.h:

  + introduce a "TEXT" subpicture region type.
  + a psz_text field stores the subpicture text.
* src/video_output/video_text.c: produce "TEXT" subpictures.
* modules/codec/subsdec.c: produce "TEXT" subpictures.
* modules/misc/freetype.c: auto sizing works again.
parent 88386ce7
......@@ -204,6 +204,8 @@ struct subpicture_region_t
video_format_t fmt; /**< format of the picture */
picture_t picture; /**< picture comprising this region */
char *psz_text; /**< text string comprising this region */
int i_x; /**< position of region */
int i_y; /**< position of region */
......
......@@ -4,7 +4,7 @@
* Copyright (C) 2000-2001 VideoLAN
* $Id$
*
* Authors: Gildas Bazin <gbazin@netcourrier.com>
* Authors: Gildas Bazin <gbazin@videolan.org>
* Samuel Hocevar <sam@zoy.org>
*
* This program is free software; you can redistribute it and/or modify
......@@ -49,7 +49,6 @@ struct decoder_sys_t
iconv_t iconv_handle; /* handle to iconv instance */
#endif
filter_t *p_render; /* text renderer filter */
};
/*****************************************************************************
......@@ -62,9 +61,6 @@ static subpicture_t *DecodeBlock ( decoder_t *, block_t ** );
static subpicture_t *ParseText ( decoder_t *, block_t * );
static void StripTags ( char * );
static subpicture_t *spu_new_buffer( filter_t * );
static void spu_del_buffer( filter_t *, subpicture_t * );
#define DEFAULT_NAME "System Default"
/*****************************************************************************
......@@ -188,22 +184,6 @@ static int OpenDecoder( vlc_object_t *p_this )
msg_Dbg( p_dec, "no iconv support available" );
#endif
/* Load the text rendering module */
p_sys->p_render = vlc_object_create( p_dec, sizeof(filter_t) );
p_sys->p_render->pf_spu_buffer_new = spu_new_buffer;
p_sys->p_render->pf_spu_buffer_del = spu_del_buffer;
p_sys->p_render->p_owner = (filter_owner_sys_t *)p_dec;
vlc_object_attach( p_sys->p_render, p_dec );
p_sys->p_render->p_module =
module_Need( p_sys->p_render, "text renderer", 0, 0 );
if( p_sys->p_render->p_module == NULL )
{
msg_Warn( p_dec, "no suitable text renderer module" );
vlc_object_detach( p_sys->p_render );
vlc_object_destroy( p_sys->p_render );
p_sys->p_render = NULL;
}
return VLC_SUCCESS;
}
......@@ -241,15 +221,6 @@ static void CloseDecoder( vlc_object_t *p_this )
}
#endif
if( p_sys->p_render )
{
if( p_sys->p_render->p_module )
module_Unneed( p_sys->p_render, p_sys->p_render->p_module );
vlc_object_detach( p_sys->p_render );
vlc_object_destroy( p_sys->p_render );
}
free( p_sys );
}
......@@ -262,6 +233,7 @@ static subpicture_t *ParseText( decoder_t *p_dec, block_t *p_block )
subpicture_t *p_spu = 0;
char *psz_subtitle;
int i_align_h, i_align_v;
video_format_t fmt;
/* We cannot display a subpicture with no date */
if( p_block->i_pts == 0 )
......@@ -271,7 +243,7 @@ static subpicture_t *ParseText( decoder_t *p_dec, block_t *p_block )
}
/* Check validity of packet data */
if( p_block->i_buffer <= 1 || p_block->p_buffer[0] == '\0' )
if( p_block->i_buffer <= 1 || p_block->p_buffer[0] == '\0' )
{
msg_Warn( p_dec, "empty subtitle" );
return NULL;
......@@ -377,29 +349,39 @@ static subpicture_t *ParseText( decoder_t *p_dec, block_t *p_block )
StripTags( psz_subtitle );
if( p_sys->p_render && p_sys->p_render->p_module &&
p_sys->p_render->pf_render_string )
p_spu = p_dec->pf_spu_buffer_new( p_dec );
if( !p_spu )
{
block_t *p_new_block = block_New( p_dec, strlen(psz_subtitle) + 1 );
if( p_new_block )
{
memcpy( p_new_block->p_buffer, psz_subtitle,
p_new_block->i_buffer );
p_new_block->i_pts = p_new_block->i_dts = p_block->i_pts;
p_new_block->i_length = p_block->i_length;
p_spu = p_sys->p_render->pf_render_string( p_sys->p_render,
p_new_block );
}
msg_Warn( p_dec, "can't get spu buffer" );
free( psz_subtitle );
return 0;
}
if( p_spu )
/* Create a new subpicture region */
memset( &fmt, 0, sizeof(video_format_t) );
fmt.i_chroma = VLC_FOURCC('T','E','X','T');
fmt.i_aspect = 0;
fmt.i_width = fmt.i_height = 0;
fmt.i_x_offset = fmt.i_y_offset = 0;
p_spu->p_region = p_spu->pf_create_region( VLC_OBJECT(p_dec), &fmt );
if( !p_spu->p_region )
{
p_spu->i_flags = OSD_ALIGN_BOTTOM | p_sys->i_align;
p_spu->i_x = i_align_h;
p_spu->i_y = i_align_v;
msg_Err( p_dec, "cannot allocate SPU region" );
free( psz_subtitle );
p_dec->pf_spu_buffer_del( p_dec, p_spu );
return 0;
}
free( psz_subtitle );
p_spu->p_region->psz_text = psz_subtitle;
p_spu->i_start = p_block->i_pts;
p_spu->i_stop = p_block->i_pts + p_block->i_length;
p_spu->b_ephemer = (p_block->i_length == 0);
p_spu->b_absolute = VLC_FALSE;
p_spu->i_flags = OSD_ALIGN_BOTTOM | p_sys->i_align;
p_spu->i_x = i_align_h;
p_spu->i_y = i_align_v;
return p_spu;
}
......@@ -445,18 +427,3 @@ static void StripTags( char *psz_text )
}
psz_text[ i - i_left_moves ] = '\0';
}
/*****************************************************************************
* Buffers allocation callbacks for the filters
*****************************************************************************/
static subpicture_t *spu_new_buffer( filter_t *p_filter )
{
decoder_t *p_dec = (decoder_t *)p_filter->p_owner;
return p_dec->pf_spu_buffer_new( p_dec );
}
static void spu_del_buffer( filter_t *p_filter, subpicture_t *p_spu )
{
decoder_t *p_dec = (decoder_t *)p_filter->p_owner;
p_dec->pf_spu_buffer_del( p_dec, p_spu );
}
......@@ -247,8 +247,7 @@ static int Create( vlc_object_t *p_this )
else
{
var_Get( p_filter, "freetype-rel-fontsize", &val );
msg_Err( p_filter, "freetype-rel-font currenlty broken, FIXME" );
i_fontsize = (int) /*p_filter->render.i_height*/ 400 / val.i_int;
i_fontsize = (int)p_filter->fmt_out.video.i_height / val.i_int;
}
msg_Dbg( p_filter, "Using fontsize: %i", i_fontsize);
......
......@@ -41,39 +41,11 @@ int vout_ShowTextRelative( vout_thread_t *p_vout, int i_channel,
int i_flags, int i_hmargin, int i_vmargin,
mtime_t i_duration )
{
subpicture_t *p_subpic = NULL;
mtime_t i_now = mdate();
if( p_vout->p_text && p_vout->p_text->p_module &&
p_vout->p_text->pf_render_string )
{
block_t *p_block = block_New( p_vout, strlen(psz_string) + 1 );
if( p_block )
{
memcpy( p_block->p_buffer, psz_string, p_block->i_buffer );
p_block->i_pts = p_block->i_dts = i_now;
p_block->i_length = i_duration;
p_subpic = p_vout->p_text->pf_render_string( p_vout->p_text,
p_block );
if( p_subpic )
{
p_subpic->i_x = i_hmargin;
p_subpic->i_y = i_vmargin;
p_subpic->i_flags = i_flags;
p_subpic->i_channel = i_channel;
vout_DisplaySubPicture( p_vout, p_subpic );
return VLC_SUCCESS;
}
}
return VLC_EGENERIC;
}
else
{
msg_Warn( p_vout, "No text renderer found" );
return VLC_EGENERIC;
}
return vout_ShowTextAbsolute( p_vout, i_channel, psz_string,
p_style, i_flags, i_hmargin, i_vmargin,
i_now, i_now + i_duration );
}
/**
......@@ -95,38 +67,42 @@ int vout_ShowTextAbsolute( vout_thread_t *p_vout, int i_channel,
int i_flags, int i_hmargin, int i_vmargin,
mtime_t i_start, mtime_t i_stop )
{
subpicture_t *p_subpic = NULL;
if( p_vout->p_text && p_vout->p_text->p_module &&
p_vout->p_text->pf_render_string )
subpicture_t *p_spu;
video_format_t fmt;
if( !psz_string ) return VLC_EGENERIC;
p_spu = vout_CreateSubPicture( p_vout, !DEFAULT_CHAN, MEMORY_SUBPICTURE );
if( !p_spu ) return VLC_EGENERIC;
/* Create a new subpicture region */
memset( &fmt, 0, sizeof(video_format_t) );
fmt.i_chroma = VLC_FOURCC('T','E','X','T');
fmt.i_aspect = 0;
fmt.i_width = fmt.i_height = 0;
fmt.i_x_offset = fmt.i_y_offset = 0;
p_spu->p_region = p_spu->pf_create_region( VLC_OBJECT(p_vout), &fmt );
if( !p_spu->p_region )
{
block_t *p_block = block_New( p_vout, strlen(psz_string) + 1 );
if( p_block )
{
memcpy( p_block->p_buffer, psz_string, p_block->i_buffer );
p_block->i_pts = p_block->i_dts = i_start;
p_block->i_length = i_stop - i_start;
p_subpic = p_vout->p_text->pf_render_string( p_vout->p_text,
p_block );
if( p_subpic )
{
p_subpic->i_x = i_hmargin;
p_subpic->i_y = i_vmargin;
p_subpic->i_flags = i_flags;
p_subpic->i_channel = i_channel;
vout_DisplaySubPicture( p_vout, p_subpic );
return VLC_SUCCESS;
}
}
return VLC_EGENERIC;
}
else
{
msg_Warn( p_vout, "No text renderer found" );
msg_Err( p_vout, "cannot allocate SPU region" );
vout_DestroySubPicture( p_vout, p_spu );
return VLC_EGENERIC;
}
p_spu->p_region->psz_text = strdup( psz_string );
p_spu->i_start = i_start;
p_spu->i_stop = i_stop;
p_spu->b_ephemer = 0;
p_spu->b_absolute = VLC_FALSE;
p_spu->i_x = i_hmargin;
p_spu->i_y = i_vmargin;
p_spu->i_flags = i_flags;
p_spu->i_channel = i_channel;
vout_DisplaySubPicture( p_vout, p_spu );
return VLC_SUCCESS;
}
......@@ -161,4 +137,3 @@ void __vout_OSDMessage( vlc_object_t *p_caller, int i_channel,
va_end( args );
}
}
......@@ -32,6 +32,7 @@
#include <vlc/vlc.h>
#include "vlc_block.h"
#include "vlc_video.h"
#include "video_output.h"
#include "vlc_filter.h"
......@@ -59,23 +60,8 @@ void vout_InitSPU( vout_thread_t *p_vout )
p_vout->p_subpicture[i_index].i_type = EMPTY_SUBPICTURE;
}
/* Load the text rendering module */
p_vout->p_text = vlc_object_create( p_vout, sizeof(filter_t) );
p_vout->p_text->pf_spu_buffer_new = spu_new_buffer;
p_vout->p_text->pf_spu_buffer_del = spu_del_buffer;
p_vout->p_text->p_owner = (filter_owner_sys_t *)p_vout;
vlc_object_attach( p_vout->p_text, p_vout );
p_vout->p_text->p_module =
module_Need( p_vout->p_text, "text renderer", 0, 0 );
if( p_vout->p_text->p_module == NULL )
{
msg_Warn( p_vout, "no suitable text renderer module" );
vlc_object_detach( p_vout->p_text );
vlc_object_destroy( p_vout->p_text );
p_vout->p_text = NULL;
}
p_vout->p_blend = NULL;
p_vout->p_text = NULL;
p_vout->i_crop_x = p_vout->i_crop_y =
p_vout->i_crop_width = p_vout->i_crop_height = 0;
......@@ -104,15 +90,6 @@ void vout_DestroySPU( vout_thread_t *p_vout )
}
}
if( p_vout->p_text )
{
if( p_vout->p_text->p_module )
module_Unneed( p_vout->p_text, p_vout->p_text->p_module );
vlc_object_detach( p_vout->p_text );
vlc_object_destroy( p_vout->p_text );
}
if( p_vout->p_blend )
{
if( p_vout->p_blend->p_module )
......@@ -122,6 +99,15 @@ void vout_DestroySPU( vout_thread_t *p_vout )
vlc_object_destroy( p_vout->p_blend );
}
if( p_vout->p_text )
{
if( p_vout->p_text->p_module )
module_Unneed( p_vout->p_text, p_vout->p_text->p_module );
vlc_object_detach( p_vout->p_text );
vlc_object_destroy( p_vout->p_text );
}
vout_AttachSPU( p_vout, VLC_FALSE );
}
......@@ -166,6 +152,16 @@ subpicture_region_t *__spu_CreateRegion( vlc_object_t *p_this,
memset( p_region, 0, sizeof(subpicture_region_t) );
p_region->p_next = 0;
p_region->fmt = *p_fmt;
p_region->psz_text = 0;
if( p_fmt->i_chroma == VLC_FOURCC('Y','U','V','P') )
p_fmt->p_palette = p_region->fmt.p_palette =
malloc( sizeof(video_palette_t) );
else p_fmt->p_palette = p_region->fmt.p_palette = NULL;
p_region->picture.p_data_orig = 0;
if( p_fmt->i_chroma == VLC_FOURCC('T','E','X','T') ) return p_region;
vout_AllocatePicture( p_this, &p_region->picture, p_fmt->i_chroma,
p_fmt->i_width, p_fmt->i_height, p_fmt->i_aspect );
......@@ -173,14 +169,10 @@ subpicture_region_t *__spu_CreateRegion( vlc_object_t *p_this,
if( !p_region->picture.i_planes )
{
free( p_region );
free( p_fmt->p_palette );
return NULL;
}
if( p_fmt->i_chroma == VLC_FOURCC('Y','U','V','P') )
p_fmt->p_palette = p_region->fmt.p_palette =
malloc( sizeof(video_palette_t) );
else p_fmt->p_palette = p_region->fmt.p_palette = NULL;
return p_region;
}
......@@ -195,6 +187,7 @@ void __spu_DestroyRegion( vlc_object_t *p_this, subpicture_region_t *p_region )
if( !p_region ) return;
if( p_region->picture.p_data_orig ) free( p_region->picture.p_data_orig );
if( p_region->fmt.p_palette ) free( p_region->fmt.p_palette );
if( p_region->psz_text ) free( p_region->psz_text );
free( p_region );
}
......@@ -389,12 +382,32 @@ void vout_RenderSubPictures( vout_thread_t *p_vout, picture_t *p_pic_dst,
p_vout->p_blend->fmt_out.video.i_chroma =
p_vout->output.i_chroma;
p_vout->p_blend->fmt_in.video = p_subpic->p_region->fmt;
p_vout->p_blend->fmt_in.video.i_chroma = VLC_FOURCC('Y','U','V','P');
p_vout->p_blend->p_module =
module_Need( p_vout->p_blend, "video blending", 0, 0 );
}
/* Load the text rendering module */
if( !p_vout->p_text && p_subpic && p_subpic->p_region )
{
p_vout->p_text = vlc_object_create( p_vout, sizeof(filter_t) );
vlc_object_attach( p_vout->p_text, p_vout );
p_vout->p_text->fmt_out.video.i_width =
p_vout->p_text->fmt_out.video.i_visible_width =
p_vout->output.i_width;
p_vout->p_text->fmt_out.video.i_height =
p_vout->p_text->fmt_out.video.i_visible_height =
p_vout->output.i_height;
p_vout->p_text->pf_spu_buffer_new = spu_new_buffer;
p_vout->p_text->pf_spu_buffer_del = spu_del_buffer;
p_vout->p_text->p_module =
module_Need( p_vout->p_text, "text renderer", 0, 0 );
}
/* Get lock */
vlc_mutex_lock( &p_vout->subpicture_lock );
......@@ -413,6 +426,42 @@ void vout_RenderSubPictures( vout_thread_t *p_vout, picture_t *p_pic_dst,
int i_x_offset = p_region->i_x + p_subpic->i_x;
int i_y_offset = p_region->i_y + p_subpic->i_y;
if( p_region->fmt.i_chroma == VLC_FOURCC('T','E','X','T') )
{
if( p_vout->p_text && p_vout->p_text->p_module &&
p_vout->p_text->pf_render_string )
{
/* TODO: do it in a less hacky way
* (modify text renderer API) */
subpicture_t *p_spu;
subpicture_region_t tmp_region;
block_t *p_new_block =
block_New( p_vout, strlen(p_region->psz_text) + 1 );
if( p_new_block )
{
memcpy( p_new_block->p_buffer, p_region->psz_text,
p_new_block->i_buffer );
p_new_block->i_pts = p_new_block->i_dts =
p_subpic->i_start;
p_new_block->i_length =
p_subpic->i_start - p_subpic->i_stop;
p_spu = p_vout->p_text->pf_render_string(
p_vout->p_text, p_new_block );
if( p_spu )
{
tmp_region = *p_region;
*p_region = *p_spu->p_region;
p_region->p_next = tmp_region.p_next;
*p_spu->p_region = tmp_region;
p_vout->p_text->pf_spu_buffer_del( p_vout->p_text,
p_spu );
}
}
}
}
if( p_subpic->i_flags & OSD_ALIGN_BOTTOM )
{
i_y_offset = p_vout->output.i_height - p_region->fmt.i_height -
......@@ -754,15 +803,24 @@ static int CropCallback( vlc_object_t *p_object, char const *psz_var,
*****************************************************************************/
static subpicture_t *spu_new_buffer( filter_t *p_filter )
{
vout_thread_t *p_vout = (vout_thread_t *)p_filter->p_owner;
subpicture_t *p_spu;
subpicture_t *p_subpic = (subpicture_t *)malloc(sizeof(subpicture_t));
memset( p_subpic, 0, sizeof(subpicture_t) );
p_subpic->b_absolute = VLC_TRUE;
p_subpic->pf_create_region = __spu_CreateRegion;
p_subpic->pf_destroy_region = __spu_DestroyRegion;
p_spu = vout_CreateSubPicture( p_vout, !DEFAULT_CHAN, MEMORY_SUBPICTURE );
return p_spu;
return p_subpic;
}
static void spu_del_buffer( filter_t *p_filter, subpicture_t *p_spu )
static void spu_del_buffer( filter_t *p_filter, subpicture_t *p_subpic )
{
vout_thread_t *p_vout = (vout_thread_t *)p_filter->p_owner;
vout_DestroySubPicture( p_vout, p_spu );
while( p_subpic->p_region )
{
subpicture_region_t *p_region = p_subpic->p_region;
p_subpic->p_region = p_region->p_next;
p_subpic->pf_destroy_region( VLC_OBJECT(p_filter), p_region );
}
free( p_subpic );
}
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