* Authors: Gildas Bazin <gbazin@videolan.org>
* Damien LUCAS <damien.lucas@anevia.com>
* Laurent Aimar <fenrir@via.ecp.fr>
- * Jean-Paul Saman <jpsaman #_at_# m2x dot nl>
+ * Jean-Paul Saman <jpsaman #_at_# m2x dot nl>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#define POSX_TEXT N_("X coordinate of the subpicture")
#define POSX_LONGTEXT N_("You can reposition the subpicture by providing another value here." )
-
+
#define POSY_TEXT N_("Y coordinate of the subpicture")
#define POSY_LONGTEXT N_("You can reposition the subpicture by providing another value here." )
set_category( CAT_INPUT );
set_subcategory( SUBCAT_INPUT_SCODEC );
set_callbacks( Open, Close );
-
+
add_integer( DVBSUB_CFG_PREFIX "position", 8, NULL, POS_TEXT, POS_LONGTEXT, VLC_TRUE );
change_integer_list( pi_pos_values, ppsz_pos_descriptions, 0 );
add_integer( DVBSUB_CFG_PREFIX "x", -1, NULL, POSX_TEXT, POSX_LONGTEXT, VLC_FALSE );
set_description( _("DVB subtitles encoder") );
set_capability( "encoder", 100 );
set_callbacks( OpenEncoder, CloseEncoder );
-
+
add_integer( ENC_CFG_PREFIX "x", -1, NULL, ENC_POSX_TEXT, ENC_POSX_LONGTEXT, VLC_FALSE );
add_integer( ENC_CFG_PREFIX "y", -1, NULL, ENC_POSY_TEXT, ENC_POSY_LONGTEXT, VLC_FALSE );
add_integer( ENC_CFG_PREFIX "timeout", 15, NULL, TIMEOUT_TEXT, TIMEOUT_LONGTEXT, VLC_FALSE );
int i_spu_position;
int i_spu_x;
int i_spu_y;
-
+
vlc_bool_t b_page;
dvbsub_page_t *p_page;
dvbsub_region_t *p_regions;
p_sys->p_regions = NULL;
p_sys->p_cluts = NULL;
p_sys->p_page = NULL;
-
+
var_Create( p_this, DVBSUB_CFG_PREFIX "position", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
var_Get( p_this, DVBSUB_CFG_PREFIX "position", &val );
p_sys->i_spu_position = val.i_int;
var_Create( p_this, DVBSUB_CFG_PREFIX "y", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
var_Get( p_this, DVBSUB_CFG_PREFIX "y", &val );
posy = val.i_int;
-
+
/* Check if subpicture position was overridden */
p_sys->b_absolute = VLC_TRUE;
if( posx < 0 || posy < 0)
p_sys->i_spu_x = 0;
p_sys->i_spu_y = 0;
}
-
+
es_format_Init( &p_dec->fmt_out, SPU_ES, VLC_FOURCC( 'd','v','b','s' ) );
default_clut_init( p_dec );
var_Destroy( p_this, DVBSUB_CFG_PREFIX "x" );
var_Destroy( p_this, DVBSUB_CFG_PREFIX "y" );
var_Destroy( p_this, DVBSUB_CFG_PREFIX "position" );
-
+
free_all( p_dec );
free( p_sys );
}
int i_version, i_state, i_segment_length, i_timeout, i;
/* A page is composed by 0 or more region */
-
i_segment_length = bs_read( s, 16 );
i_timeout = bs_read( s, 8 );
i_version = bs_read( s, 4 );
i_width = bs_read( s, 16 );
i_height = bs_read( s, 16 );
+#ifdef DEBUG_DVBSUB
+ msg_Dbg( p_dec, " width=%d height=%d", i_width, i_height );
+#endif
i_level_comp = bs_read( s, 3 );
i_depth = bs_read( s, 3 );
bs_skip( s, 2 ); /* Reserved */
{
if( p_region->p_pixbuf )
{
- msg_Dbg( p_dec, "region size changed (not allowed)" );
+ msg_Dbg( p_dec, " changed (not allowed)" );
free( p_region->p_pixbuf );
}
p_spu->i_stop = p_spu->i_start + (mtime_t) (i_timeout * 1000000);
p_spu->b_ephemer = VLC_TRUE;
p_spu->b_fade = VLC_TRUE;
-
+
/* Correct positioning of SPU */
p_spu->b_absolute = p_sys->b_absolute;
p_spu->i_flags = p_sys->i_spu_position;
p_spu->i_x = p_sys->i_spu_x;
- p_spu->i_y = p_sys->i_spu_y;
+ p_spu->i_y = p_sys->i_spu_y;
return p_spu;
}
encoder_region_t *p_regions;
mtime_t i_pts;
-
+
/* subpicture positioning */
int i_offset_x;
int i_offset_y;
- int i_timeout_delay;
+ int i_timeout_delay;
};
static void encode_page_composition( encoder_t *, bs_t *, subpicture_t * );
p_sys->i_offset_y = val.i_int;
var_Create( p_this, ENC_CFG_PREFIX "timeout", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
var_Get( p_this, ENC_CFG_PREFIX "timeout", &val );
- p_sys->i_timeout_delay = val.i_int;
-
+ p_sys->i_timeout_delay = val.i_int;
+
return VLC_SUCCESS;
}
subpicture_region_t *p_region = NULL;
if( !p_subpic ) return NULL;
-
+
for( p_region = p_subpic->p_region; p_region; p_region = p_region->p_next )
{
video_format_t *p_fmt = &p_region->fmt;
#if DEBUG_DVBSUB
msg_Dbg( p_enc, "YuvaYuvp: i_pixels=%d, i_iterator=%d", i_pixels, i_iterator );
-#endif
+#endif
p_fmt->i_chroma = VLC_FOURCC('Y','U','V','P');
p_fmt->p_palette = (video_palette_t *) malloc( sizeof( video_palette_t ) );
if( !p_fmt->p_palette ) break;
p_fmt->p_palette->i_entries = 0;
-
+
/* Find best iterator using Euclide’s algorithm */
for( ; i_iterator > 1 ; i_iterator-- )
{
int a = i_pixels;
int b = i_iterator;
int c;
-
+
while( b )
{
c = a % b;
a = b;
b = c;
}
-
+
if( a == 1 )
{
break;
}
}
-
+
/* Count colors, build best palette */
for( i_tolerance = 0; i_tolerance < 128; i_tolerance++ )
{
vlc_bool_t b_success = VLC_TRUE;
p_fmt->p_palette->i_entries = 0;
-
+
for( i = 0; i < i_pixels ; )
{
uint8_t y, u, v, a;
i -= i_pixels;
}
}
-
+
if( b_success )
{
break;
}
}
-
+
#if DEBUG_DVBSUB
msg_Dbg( p_enc, "best palette has %d colors", p_fmt->p_palette->i_entries );
#endif
for( p = 0; p < p_region->picture.p[0].i_visible_lines ; p++ )
{
int i_ydelta = 0, i_udelta = 0, i_vdelta = 0, i_adelta = 0;
-
+
for( n = 0; n < p_region->picture.p[0].i_pitch ; n++ )
{
int i_offset = p * p_region->picture.p[0].i_pitch + n;
int y, u, v, a;
int i_mindist, i_best;
-
+
y = (int)p_region->picture.p[0].p_pixels[i_offset];
u = (int)p_region->picture.p[1].p_pixels[i_offset];
v = (int)p_region->picture.p[2].p_pixels[i_offset];
a = (int)p_region->picture.p[3].p_pixels[i_offset];
-
+
/* Add dithering compensation */
#ifdef RANDOM_DITHERING
y += ((i_seed & 0xff) - 0x80) * i_tolerance / 0x80;
for( i_mindist = 99999999, i_best = 0, j = 0; j < p_fmt->p_palette->i_entries; j++ )
{
int i_dist = 0;
-
+
i_dist += abs((int)p_fmt->p_palette->palette[j][0] - y);
i_dist += abs((int)p_fmt->p_palette->palette[j][1] - u);
i_dist += abs((int)p_fmt->p_palette->palette[j][2] - v);
i_dist += 2 * abs((int)p_fmt->p_palette->palette[j][3] - a);
-
+
if( i_dist < i_mindist )
{
i_mindist = i_dist;
i_best = j;
}
}
-
+
/* Set pixel to best color */
p_region->picture.p[0].p_pixels[i_offset] = i_best;
-
+
/* Update dithering state */
#ifdef RANDOM_DITHERING
i_seed = (i_seed * 0x1283837) ^ 0x789479 ^ (i_seed >> 13);
block_t *p_block;
if( !p_subpic || !p_subpic->p_region ) return NULL;
-
+
/* FIXME: this is a hack to convert VLC_FOURCC('Y','U','V','A') into
* VLC_FOURCC('Y','U','V','P')
*/
p_region = p_subpic->p_region;
if( p_region->fmt.i_chroma == VLC_FOURCC('Y','U','V','A') )
- {
+ {
p_temp = YuvaYuvp( p_enc, p_subpic );
if( !p_temp )
{
}
p_region = p_subpic->p_region;
}
-
+
/* Sanity check */
if( !p_region ) return NULL;
-
+
if( p_region->fmt.i_chroma != VLC_FOURCC('T','E','X','T') &&
p_region->fmt.i_chroma != VLC_FOURCC('Y','U','V','P') ) return NULL;
-
+
if( p_region->fmt.p_palette )
{
switch( p_region->fmt.p_palette->i_entries )
default:
msg_Err( p_enc, "subpicture palette (%d) not handled",
p_region->fmt.p_palette->i_entries );
- return NULL;
+ return NULL;
}
}
/* End of hack */
-
+
#if DEBUG_DVBSUB
msg_Dbg( p_enc, "encoding subpicture" );
#endif
var_Destroy( p_this , ENC_CFG_PREFIX "x" );
var_Destroy( p_this , ENC_CFG_PREFIX "y" );
- var_Destroy( p_this , ENC_CFG_PREFIX "timeout" );
+ var_Destroy( p_this , ENC_CFG_PREFIX "timeout" );
if( p_sys->i_regions ) free( p_sys->p_regions );
free( p_sys );
p_sys->p_regions[p_sys->i_regions++] = region;
}
- if( p_sys->p_regions[i_regions].i_width <
- (int)p_region->fmt.i_visible_width )
+ if( ( p_sys->p_regions[i_regions].i_width <
+ (int)p_region->fmt.i_visible_width ) ||
+ ( p_sys->p_regions[i_regions].i_width >
+ (int)p_region->fmt.i_visible_width ) )
{
b_mode_change = VLC_TRUE;
msg_Dbg( p_enc, "region %i width change: %i -> %i",
p_sys->p_regions[i_regions].i_width =
p_region->fmt.i_visible_width;
}
- if( p_sys->p_regions[i_regions].i_height <
- (int)p_region->fmt.i_visible_height )
+ if( ( p_sys->p_regions[i_regions].i_height <
+ (int)p_region->fmt.i_visible_height ) ||
+ ( p_sys->p_regions[i_regions].i_height >
+ (int)p_region->fmt.i_visible_height ) )
{
b_mode_change = VLC_TRUE;
msg_Dbg( p_enc, "region %i height change: %i -> %i",
i_timeout = (p_subpic->i_stop - p_subpic->i_start) / 1000000;
}
- bs_write( s, 8, i_timeout + p_sys->i_timeout_delay ); /* Timeout */
+ bs_write( s, 8, i_timeout + p_sys->i_timeout_delay ); /* Timeout */
bs_write( s, 4, p_sys->i_page_ver++ );
bs_write( s, 2, b_mode_change ?
DVBSUB_PCS_STATE_CHANGE : DVBSUB_PCS_STATE_ACQUISITION );
if( !b_text )
{
video_palette_t *p_pal = p_region->fmt.p_palette;
-
+
if( !p_pal )
{
msg_Err( p_enc, "subpicture has no palette - ignoring it" );
for( i = 0; i < i_size; i++ )
{
bs_write( s, 16, p_region->psz_text[i] );
- }
+ }
/* Update segment length */
SetWBE( &s->p_start[i_length_pos/8],
{
case 0:
break;
-
+
case 4:
bs_write( s, 8, 0x10 ); /* 2 bit/pixel code string */
encode_pixel_line_2bp( p_enc, s, p_region, i_line );