Commit e9548f4d authored by Gildas Bazin's avatar Gildas Bazin

* src/video_output/*, include/video_output.h: support changing aspect-ratio on-the-fly.

parent d1551e17
...@@ -89,6 +89,8 @@ struct vout_thread_t ...@@ -89,6 +89,8 @@ struct vout_thread_t
unsigned int i_window_width; /**< video window width */ unsigned int i_window_width; /**< video window width */
unsigned int i_window_height; /**< video window height */ unsigned int i_window_height; /**< video window height */
unsigned int i_alignment; /**< video alignment in window */ unsigned int i_alignment; /**< video alignment in window */
unsigned int i_par_num; /**< monitor pixel aspect-ratio */
unsigned int i_par_den; /**< monitor pixel aspect-ratio */
intf_thread_t *p_parent_intf; /**< parent interface for embedded intf_thread_t *p_parent_intf; /**< parent interface for embedded
vout (if any) */ vout (if any) */
...@@ -183,8 +185,12 @@ struct vout_thread_t ...@@ -183,8 +185,12 @@ struct vout_thread_t
#define VOUT_DEPTH_CHANGE 0x0400 #define VOUT_DEPTH_CHANGE 0x0400
/** change chroma tables */ /** change chroma tables */
#define VOUT_CHROMA_CHANGE 0x0800 #define VOUT_CHROMA_CHANGE 0x0800
/** cropping parameters changed */
#define VOUT_CROP_CHANGE 0x1000
/** aspect ratio changed */
#define VOUT_ASPECT_CHANGE 0x2000
/** change/recreate picture buffers */ /** change/recreate picture buffers */
#define VOUT_PICTURE_BUFFERS_CHANGE 0x1000 #define VOUT_PICTURE_BUFFERS_CHANGE 0x4000
/**@}*/ /**@}*/
/* Alignment flags */ /* Alignment flags */
......
...@@ -216,7 +216,7 @@ vout_thread_t * __vout_Create( vlc_object_t *p_parent, video_format_t *p_fmt ) ...@@ -216,7 +216,7 @@ vout_thread_t * __vout_Create( vlc_object_t *p_parent, video_format_t *p_fmt )
input_thread_t * p_input_thread; input_thread_t * p_input_thread;
int i_index; /* loop variable */ int i_index; /* loop variable */
char * psz_plugin; char * psz_plugin;
vlc_value_t val, val2, text; vlc_value_t val, text;
unsigned int i_width = p_fmt->i_width; unsigned int i_width = p_fmt->i_width;
unsigned int i_height = p_fmt->i_height; unsigned int i_height = p_fmt->i_height;
...@@ -286,6 +286,7 @@ vout_thread_t * __vout_Create( vlc_object_t *p_parent, video_format_t *p_fmt ) ...@@ -286,6 +286,7 @@ vout_thread_t * __vout_Create( vlc_object_t *p_parent, video_format_t *p_fmt )
p_vout->b_filter_change = 0; p_vout->b_filter_change = 0;
p_vout->pf_control = 0; p_vout->pf_control = 0;
p_vout->p_parent_intf = 0; p_vout->p_parent_intf = 0;
p_vout->i_par_num = p_vout->i_par_den = 1;
/* Initialize locks */ /* Initialize locks */
vlc_mutex_init( p_vout, &p_vout->picture_lock ); vlc_mutex_init( p_vout, &p_vout->picture_lock );
...@@ -316,67 +317,6 @@ vout_thread_t * __vout_Create( vlc_object_t *p_parent, video_format_t *p_fmt ) ...@@ -316,67 +317,6 @@ vout_thread_t * __vout_Create( vlc_object_t *p_parent, video_format_t *p_fmt )
* the video output pipe */ * the video output pipe */
if( p_parent->i_object_type != VLC_OBJECT_VOUT ) if( p_parent->i_object_type != VLC_OBJECT_VOUT )
{ {
int i_monitor_aspect_x = 4 , i_monitor_aspect_y = 3;
var_Get( p_vout, "aspect-ratio", &val );
var_Get( p_vout, "monitor-aspect-ratio", &val2 );
if( val2.psz_string )
{
char *psz_parser = strchr( val2.psz_string, ':' );
if( psz_parser )
{
*psz_parser++ = '\0';
i_monitor_aspect_x = atoi( val2.psz_string );
i_monitor_aspect_y = atoi( psz_parser );
} else {
AspectRatio( VOUT_ASPECT_FACTOR * atof( val2.psz_string ),
&i_monitor_aspect_x, &i_monitor_aspect_y );
}
free( val2.psz_string );
}
/* Check whether the user tried to override aspect ratio */
if( val.psz_string )
{
unsigned int i_new_aspect = i_aspect;
char *psz_parser = strchr( val.psz_string, ':' );
int i_aspect_x, i_aspect_y;
AspectRatio( i_aspect, &i_aspect_x, &i_aspect_y );
if( psz_parser )
{
*psz_parser++ = '\0';
i_new_aspect = atoi( val.psz_string )
* VOUT_ASPECT_FACTOR / atoi( psz_parser );
}
else
{
if( atof( val.psz_string ) != 0 )
{
i_new_aspect = VOUT_ASPECT_FACTOR * atof( val.psz_string );
}
}
i_new_aspect = (int)((float)i_new_aspect
* (float)i_monitor_aspect_y*4.0/((float)i_monitor_aspect_x*3.0));
free( val.psz_string );
if( i_new_aspect && i_new_aspect != i_aspect )
{
int i_aspect_x, i_aspect_y;
AspectRatio( i_new_aspect, &i_aspect_x, &i_aspect_y );
msg_Dbg( p_vout, "overriding source aspect ratio to %i:%i",
i_aspect_x, i_aspect_y );
p_vout->render.i_aspect = i_new_aspect;
p_vout->b_override_aspect = VLC_TRUE;
}
}
/* Look for the default filter configuration */ /* Look for the default filter configuration */
var_Create( p_vout, "vout-filter", VLC_VAR_STRING | VLC_VAR_DOINHERIT ); var_Create( p_vout, "vout-filter", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
var_Get( p_vout, "vout-filter", &val ); var_Get( p_vout, "vout-filter", &val );
......
...@@ -43,6 +43,8 @@ static int ZoomCallback( vlc_object_t *, char const *, ...@@ -43,6 +43,8 @@ static int ZoomCallback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * ); vlc_value_t, vlc_value_t, void * );
static int CropCallback( vlc_object_t *, char const *, static int CropCallback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * ); vlc_value_t, vlc_value_t, void * );
static int AspectCallback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * );
static int OnTopCallback( vlc_object_t *, char const *, static int OnTopCallback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * ); vlc_value_t, vlc_value_t, void * );
static int FullscreenCallback( vlc_object_t *, char const *, static int FullscreenCallback( vlc_object_t *, char const *,
...@@ -178,15 +180,13 @@ void vout_IntfInit( vout_thread_t *p_vout ) ...@@ -178,15 +180,13 @@ void vout_IntfInit( vout_thread_t *p_vout )
/* Create a few object variables we'll need later on */ /* Create a few object variables we'll need later on */
var_Create( p_vout, "snapshot-path", VLC_VAR_STRING | VLC_VAR_DOINHERIT ); var_Create( p_vout, "snapshot-path", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
var_Create( p_vout, "snapshot-format", VLC_VAR_STRING | VLC_VAR_DOINHERIT ); var_Create( p_vout, "snapshot-format", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
var_Create( p_vout, "aspect-ratio", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
var_Create( p_vout, "monitor-aspect-ratio",
VLC_VAR_STRING | VLC_VAR_DOINHERIT );
var_Create( p_vout, "width", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); var_Create( p_vout, "width", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
var_Create( p_vout, "height", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); var_Create( p_vout, "height", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
var_Create( p_vout, "align", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); var_Create( p_vout, "align", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
var_Create( p_vout, "video-x", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); var_Create( p_vout, "video-x", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
var_Create( p_vout, "video-y", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); var_Create( p_vout, "video-y", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
/* Zoom object var */
var_Create( p_vout, "zoom", VLC_VAR_FLOAT | VLC_VAR_ISCOMMAND | var_Create( p_vout, "zoom", VLC_VAR_FLOAT | VLC_VAR_ISCOMMAND |
VLC_VAR_HASCHOICE | VLC_VAR_DOINHERIT ); VLC_VAR_HASCHOICE | VLC_VAR_DOINHERIT );
...@@ -215,7 +215,8 @@ void vout_IntfInit( vout_thread_t *p_vout ) ...@@ -215,7 +215,8 @@ void vout_IntfInit( vout_thread_t *p_vout )
var_AddCallback( p_vout, "zoom", ZoomCallback, NULL ); var_AddCallback( p_vout, "zoom", ZoomCallback, NULL );
var_Create( p_vout, "crop", VLC_VAR_STRING | VLC_VAR_ISCOMMAND | /* Crop object var */
var_Create( p_vout, "crop", VLC_VAR_STRING |
VLC_VAR_HASCHOICE | VLC_VAR_DOINHERIT ); VLC_VAR_HASCHOICE | VLC_VAR_DOINHERIT );
text.psz_string = _("Crop"); text.psz_string = _("Crop");
...@@ -235,6 +236,69 @@ void vout_IntfInit( vout_thread_t *p_vout ) ...@@ -235,6 +236,69 @@ void vout_IntfInit( vout_thread_t *p_vout )
var_Change( p_vout, "crop", VLC_VAR_ADDCHOICE, &val, &text ); var_Change( p_vout, "crop", VLC_VAR_ADDCHOICE, &val, &text );
var_AddCallback( p_vout, "crop", CropCallback, NULL ); var_AddCallback( p_vout, "crop", CropCallback, NULL );
var_Get( p_vout, "crop", &old_val );
if( old_val.psz_string && *old_val.psz_string )
var_Change( p_vout, "crop", VLC_VAR_TRIGGER_CALLBACKS, 0, 0 );
if( old_val.psz_string ) free( old_val.psz_string );
/* Monitor pixel aspect-ratio */
var_Create( p_vout, "monitor-aspect-ratio",
VLC_VAR_STRING | VLC_VAR_DOINHERIT );
var_Get( p_vout, "monitor-aspect-ratio", &val );
if( val.psz_string )
{
char *psz_parser = strchr( val.psz_string, ':' );
unsigned int i_aspect_num = 0, i_aspect_den = 0;
float i_aspect = 0;
if( psz_parser )
{
i_aspect_num = strtol( val.psz_string, 0, 0 );
i_aspect_den = strtol( ++psz_parser, 0, 0 );
}
else
{
i_aspect = atof( val.psz_string );
vlc_ureduce( &i_aspect_num, &i_aspect_den,
i_aspect *VOUT_ASPECT_FACTOR, VOUT_ASPECT_FACTOR, 0 );
}
free( val.psz_string );
if( !i_aspect_num || !i_aspect_den )
{
i_aspect_num = 4;
i_aspect_num = 3;
}
p_vout->i_par_num = i_aspect_num * 3 * 4;
p_vout->i_par_den = i_aspect_den;
vlc_ureduce( &p_vout->i_par_num, &p_vout->i_par_den,
p_vout->i_par_num, p_vout->i_par_den, 0 );
}
/* Aspect-ratio object var */
var_Create( p_vout, "aspect-ratio", VLC_VAR_STRING |
VLC_VAR_HASCHOICE | VLC_VAR_DOINHERIT );
text.psz_string = _("Aspect-ratio");
var_Change( p_vout, "aspect-ratio", VLC_VAR_SETTEXT, &text, NULL );
val.psz_string = "";
var_Change( p_vout, "aspect-ratio", VLC_VAR_DELCHOICE, &val, 0 );
val.psz_string = ""; text.psz_string = _("Default");
var_Change( p_vout, "aspect-ratio", VLC_VAR_ADDCHOICE, &val, &text );
val.psz_string = "001:1"; text.psz_string = _("1:1");
var_Change( p_vout, "aspect-ratio", VLC_VAR_ADDCHOICE, &val, &text );
val.psz_string = "004:3"; text.psz_string = _("4:3");
var_Change( p_vout, "aspect-ratio", VLC_VAR_ADDCHOICE, &val, &text );
val.psz_string = "16:9"; text.psz_string = _("16:9");
var_Change( p_vout, "aspect-ratio", VLC_VAR_ADDCHOICE, &val, &text );
val.psz_string = "221:100"; text.psz_string = _("221:100");
var_Change( p_vout, "aspect-ratio", VLC_VAR_ADDCHOICE, &val, &text );
var_AddCallback( p_vout, "aspect-ratio", AspectCallback, NULL );
var_Get( p_vout, "aspect-ratio", &old_val );
if( old_val.psz_string && *old_val.psz_string )
var_Change( p_vout, "aspect-ratio", VLC_VAR_TRIGGER_CALLBACKS, 0, 0 );
if( old_val.psz_string ) free( old_val.psz_string );
/* Add a variable to indicate if the window should be on top of others */ /* Add a variable to indicate if the window should be on top of others */
var_Create( p_vout, "video-on-top", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); var_Create( p_vout, "video-on-top", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
...@@ -488,10 +552,10 @@ static int CropCallback( vlc_object_t *p_this, char const *psz_cmd, ...@@ -488,10 +552,10 @@ static int CropCallback( vlc_object_t *p_this, char const *psz_cmd,
if( !psz_parser ) goto crop_end; if( !psz_parser ) goto crop_end;
i_aspect_num = strtol( newval.psz_string, &psz_end, 0 ); i_aspect_num = strtol( newval.psz_string, &psz_end, 0 );
if( psz_end == newval.psz_string ) goto crop_end; if( psz_end == newval.psz_string || !i_aspect_num ) goto crop_end;
i_aspect_den = strtol( ++psz_parser, &psz_end, 0 ); i_aspect_den = strtol( ++psz_parser, &psz_end, 0 );
if( psz_end == psz_parser ) goto crop_end; if( psz_end == psz_parser || !i_aspect_den ) goto crop_end;
i_width = p_vout->fmt_in.i_sar_den * p_vout->fmt_render.i_visible_height * i_width = p_vout->fmt_in.i_sar_den * p_vout->fmt_render.i_visible_height *
i_aspect_num / i_aspect_den / p_vout->fmt_in.i_sar_num; i_aspect_num / i_aspect_den / p_vout->fmt_in.i_sar_num;
...@@ -512,6 +576,8 @@ static int CropCallback( vlc_object_t *p_this, char const *psz_cmd, ...@@ -512,6 +576,8 @@ static int CropCallback( vlc_object_t *p_this, char const *psz_cmd,
} }
crop_end: crop_end:
p_vout->i_changes |= VOUT_CROP_CHANGE;
msg_Dbg( p_vout, "cropping picture %ix%i to %i,%i,%ix%i", msg_Dbg( p_vout, "cropping picture %ix%i to %i,%i,%ix%i",
p_vout->fmt_in.i_width, p_vout->fmt_in.i_height, p_vout->fmt_in.i_width, p_vout->fmt_in.i_height,
p_vout->fmt_in.i_x_offset, p_vout->fmt_in.i_y_offset, p_vout->fmt_in.i_x_offset, p_vout->fmt_in.i_y_offset,
...@@ -521,6 +587,52 @@ static int CropCallback( vlc_object_t *p_this, char const *psz_cmd, ...@@ -521,6 +587,52 @@ static int CropCallback( vlc_object_t *p_this, char const *psz_cmd,
return VLC_SUCCESS; return VLC_SUCCESS;
} }
static int AspectCallback( vlc_object_t *p_this, char const *psz_cmd,
vlc_value_t oldval, vlc_value_t newval, void *p_data )
{
vout_thread_t *p_vout = (vout_thread_t *)p_this;
unsigned int i_aspect_num, i_aspect_den, i_sar_num, i_sar_den;
vlc_value_t val;
char *psz_end, *psz_parser = strchr( newval.psz_string, ':' );
/* Restore defaults */
p_vout->fmt_in.i_sar_num = p_vout->fmt_render.i_sar_num;
p_vout->fmt_in.i_sar_den = p_vout->fmt_render.i_sar_den;
p_vout->fmt_in.i_aspect = p_vout->fmt_render.i_aspect;
p_vout->render.i_aspect = p_vout->fmt_render.i_aspect;
if( !psz_parser ) goto aspect_end;
i_aspect_num = strtol( newval.psz_string, &psz_end, 0 );
if( psz_end == newval.psz_string || !i_aspect_num ) goto aspect_end;
i_aspect_den = strtol( ++psz_parser, &psz_end, 0 );
if( psz_end == psz_parser || !i_aspect_den ) goto aspect_end;
i_sar_num = i_aspect_num * p_vout->fmt_render.i_visible_height;
i_sar_den = i_aspect_den * p_vout->fmt_render.i_visible_width;
vlc_ureduce( &i_sar_num, &i_sar_den, i_sar_num, i_sar_den, 0 );
p_vout->fmt_in.i_sar_num = i_sar_num;
p_vout->fmt_in.i_sar_den = i_sar_den;
p_vout->fmt_in.i_aspect = i_aspect_num * VOUT_ASPECT_FACTOR / i_aspect_den;
p_vout->render.i_aspect = p_vout->fmt_in.i_aspect;
aspect_end:
p_vout->i_changes |= VOUT_ASPECT_CHANGE;
vlc_ureduce( &i_aspect_num, &i_aspect_den,
p_vout->fmt_in.i_aspect, VOUT_ASPECT_FACTOR, 0 );
msg_Dbg( p_vout, "new aspect-ratio %i:%i, sample aspect-ratio %i:%i",
i_aspect_num, i_aspect_den,
p_vout->fmt_in.i_sar_num, p_vout->fmt_in.i_sar_den );
var_Get( p_vout, "crop", &val );
return CropCallback( p_this, 0, val, val, 0 );
return VLC_SUCCESS;
}
static int OnTopCallback( vlc_object_t *p_this, char const *psz_cmd, static int OnTopCallback( vlc_object_t *p_this, char const *psz_cmd,
vlc_value_t oldval, vlc_value_t newval, void *p_data ) vlc_value_t oldval, vlc_value_t newval, void *p_data )
{ {
......
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