Commit dd50e81c authored by Laurent Aimar's avatar Laurent Aimar

Clean up crop/aspect ratio changes and associated video format.

parent 27fa51a4
......@@ -40,10 +40,6 @@ enum {
/* Controls */
VOUT_CONTROL_SOURCE_ASPECT,
VOUT_CONTROL_SOURCE_CROP_BORDER,
VOUT_CONTROL_SOURCE_CROP_RATIO,
VOUT_CONTROL_SOURCE_CROP_WINDOW,
/* OSD */
VOUT_CONTROL_OSD_MESSAGE,
......@@ -64,6 +60,11 @@ enum {
VOUT_CONTROL_ON_TOP, /* bool */
VOUT_CONTROL_DISPLAY_FILLED, /* bool */
VOUT_CONTROL_ZOOM, /* pair */
VOUT_CONTROL_ASPECT_RATIO, /* pair */
VOUT_CONTROL_CROP_BORDER, /* border */
VOUT_CONTROL_CROP_RATIO, /* pair */
VOUT_CONTROL_CROP_WINDOW, /* window */
};
typedef struct {
......@@ -86,17 +87,6 @@ typedef struct {
int channel;
char *string;
} message;
#if 0
struct {
int channel;
char *string;
text_style_t *style;
int flags;
int hmargin;
int vmargin;
mtime_t start;
mtime_t stop;
} text;
struct {
unsigned left;
unsigned top;
......@@ -109,17 +99,6 @@ typedef struct {
unsigned width;
unsigned height;
} window;
struct {
int channel;
int type;
float position;
} slider;
struct {
int channel;
int icon;
} icon;
subpicture_t *subpicture;
#endif
} u;
} vout_control_cmd_t;
......
......@@ -525,9 +525,6 @@ static void VoutDisplayEventMouse(vout_display_t *vd, int event, va_list args)
if (!vd->info.has_hide_mouse)
osys->mouse.last_moved = mdate();
/* */
vlc_mutex_unlock(&osys->lock);
/* */
vout_SendEventMouseVisible(osys->vout);
#ifdef ALLOW_DUMMY_VOUT
......@@ -535,6 +532,7 @@ static void VoutDisplayEventMouse(vout_display_t *vd, int event, va_list args)
#else
vout_SendDisplayEventMouse(osys->vout, &m);
#endif
vlc_mutex_unlock(&osys->lock);
}
static void VoutDisplayEvent(vout_display_t *vd, int event, va_list args)
......@@ -1412,7 +1410,7 @@ void vout_SendDisplayEventMouse(vout_thread_t *vout, const vlc_mouse_t *m)
vlc_mouse_t tmp;
/* The check on p_spu is needed as long as ALLOW_DUMMY_VOUT is defined */
if (vout->p->p_spu && spu_ProcessMouse( vout->p->p_spu, m, &vout->p->fmt_out))
if (vout->p->p_spu && spu_ProcessMouse( vout->p->p_spu, m, &vout->p->display.vd->source))
return;
vlc_mutex_lock( &vout->p->vfilter_lock );
......
......@@ -161,11 +161,7 @@ vout_thread_t *vout_Request( vlc_object_t *p_this, vout_thread_t *p_vout,
free( psz_filter_chain );
}
#warning "FIXME: Check RGB masks in vout_Request"
/* FIXME: check RGB masks */
if( p_vout->p->fmt_render.i_chroma != vlc_fourcc_GetCodec( VIDEO_ES, p_fmt->i_chroma ) ||
p_vout->p->fmt_render.i_width != p_fmt->i_width ||
p_vout->p->fmt_render.i_height != p_fmt->i_height ||
if( !video_format_IsSimilar( &p_vout->p->original, p_fmt ) ||
p_vout->p->b_filter_change )
{
vlc_mutex_unlock( &p_vout->p->change_lock );
......@@ -178,32 +174,6 @@ vout_thread_t *vout_Request( vlc_object_t *p_this, vout_thread_t *p_vout,
else
{
/* This video output is cool! Hijack it. */
/* Correct aspect ratio on change
* FIXME factorize this code with other aspect ration related code */
unsigned int i_sar_num;
unsigned int i_sar_den;
vlc_ureduce( &i_sar_num, &i_sar_den,
p_fmt->i_sar_num, p_fmt->i_sar_den, 50000 );
#if 0
/* What's that, it does not seems to be used correcly everywhere */
if( p_vout->i_par_num > 0 && p_vout->i_par_den > 0 )
{
i_sar_num *= p_vout->i_par_den;
i_sar_den *= p_vout->i_par_num;
}
#endif
if( i_sar_num > 0 && i_sar_den > 0 &&
( i_sar_num != p_vout->p->fmt_render.i_sar_num ||
i_sar_den != p_vout->p->fmt_render.i_sar_den ) )
{
p_vout->p->fmt_in.i_sar_num = i_sar_num;
p_vout->p->fmt_in.i_sar_den = i_sar_den;
p_vout->p->fmt_render.i_sar_num = i_sar_num;
p_vout->p->fmt_render.i_sar_den = i_sar_den;
p_vout->p->i_changes |= VOUT_ASPECT_CHANGE;
}
vlc_mutex_unlock( &p_vout->p->change_lock );
vlc_object_release( p_vout );
......@@ -272,17 +242,12 @@ vout_thread_t * (vout_Create)( vlc_object_t *p_parent, video_format_t *p_fmt )
}
/* */
p_vout->p->fmt_render = *p_fmt; /* FIXME palette */
p_vout->p->fmt_in = *p_fmt; /* FIXME palette */
p_vout->p->fmt_render.i_chroma =
p_vout->p->fmt_in.i_chroma = i_chroma;
video_format_FixRgb( &p_vout->p->fmt_render );
video_format_FixRgb( &p_vout->p->fmt_in );
p_vout->p->original = *p_fmt; /* FIXME palette */
p_vout->p->original.i_chroma = i_chroma;
video_format_FixRgb( &p_vout->p->original );
/* Initialize misc stuff */
vout_control_Init( &p_vout->p->control );
p_vout->p->i_changes = 0;
vout_chrono_Init( &p_vout->p->render, 5, 10000 ); /* Arbitrary initial time */
vout_statistic_Init( &p_vout->p->statistic );
p_vout->p->b_filter_change = 0;
......@@ -593,6 +558,42 @@ void vout_ControlChangeZoom(vout_thread_t *vout, int num, int den)
vout_control_PushPair(&vout->p->control, VOUT_CONTROL_ZOOM,
num, den);
}
void vout_ControlChangeSampleAspectRatio(vout_thread_t *vout,
unsigned num, unsigned den)
{
vout_control_PushPair(&vout->p->control, VOUT_CONTROL_ASPECT_RATIO,
num, den);
}
void vout_ControlChangeCropRatio(vout_thread_t *vout,
unsigned num, unsigned den)
{
vout_control_PushPair(&vout->p->control, VOUT_CONTROL_CROP_RATIO,
num, den);
}
void vout_ControlChangeCropWindow(vout_thread_t *vout,
int x, int y, int width, int height)
{
vout_control_cmd_t cmd;
vout_control_cmd_Init(&cmd, VOUT_CONTROL_CROP_WINDOW);
cmd.u.window.x = x;
cmd.u.window.y = y;
cmd.u.window.width = width;
cmd.u.window.height = height;
vout_control_Push(&vout->p->control, &cmd);
}
void vout_ControlChangeCropBorder(vout_thread_t *vout,
int left, int top, int right, int bottom)
{
vout_control_cmd_t cmd;
vout_control_cmd_Init(&cmd, VOUT_CONTROL_CROP_BORDER);
cmd.u.border.left = left;
cmd.u.border.top = top;
cmd.u.border.right = right;
cmd.u.border.bottom = bottom;
vout_control_Push(&vout->p->control, &cmd);
}
/*****************************************************************************
* InitThread: initialize video output thread
......@@ -613,19 +614,14 @@ static int ThreadInit(vout_thread_t *vout)
/* print some usefull debug info about different vout formats
*/
PrintVideoFormat(vout, "pic render", &vout->p->fmt_render);
PrintVideoFormat(vout, "pic in", &vout->p->fmt_in);
PrintVideoFormat(vout, "pic out", &vout->p->fmt_out);
assert(vout->p->fmt_out.i_width == vout->p->fmt_render.i_width &&
vout->p->fmt_out.i_height == vout->p->fmt_render.i_height &&
vout->p->fmt_out.i_chroma == vout->p->fmt_render.i_chroma);
PrintVideoFormat(vout, "pic render", &vout->p->original);
return VLC_SUCCESS;
}
static int ThreadDisplayPicture(vout_thread_t *vout,
bool now, mtime_t *deadline)
{
vout_display_t *vd = vout->p->display.vd;
int displayed_count = 0;
int lost_count = 0;
......@@ -743,7 +739,7 @@ static int ThreadDisplayPicture(vout_thread_t *vout,
(vout->p->decoder_pool != vout->p->display_pool || subpic)) {
picture_t *render;
if (vout->p->is_decoder_pool_slow)
render = picture_NewFromFormat(&vout->p->fmt_out);
render = picture_NewFromFormat(&vd->source);
else if (vout->p->decoder_pool != vout->p->display_pool)
render = picture_pool_Get(vout->p->display_pool);
else
......@@ -753,8 +749,8 @@ static int ThreadDisplayPicture(vout_thread_t *vout,
picture_Copy(render, filtered);
spu_RenderSubpictures(vout->p->p_spu,
render, &vout->p->fmt_out,
subpic, &vout->p->fmt_in, spu_render_time);
render, &vd->source,
subpic, &vd->source, spu_render_time);
}
if (vout->p->is_decoder_pool_slow) {
direct = picture_pool_Get(vout->p->display_pool);
......@@ -775,7 +771,7 @@ static int ThreadDisplayPicture(vout_thread_t *vout,
* Take a snapshot if requested
*/
if (direct && do_snapshot)
vout_snapshot_Set(&vout->p->snapshot, &vout->p->fmt_out, direct);
vout_snapshot_Set(&vout->p->snapshot, &vd->source, direct);
/* Render the direct buffer returned by vout_RenderPicture */
if (direct) {
......@@ -857,8 +853,8 @@ static void ThreadDisplayOsdTitle(vout_thread_t *vout, const char *string)
static void ThreadChangeFilters(vout_thread_t *vout, const char *filters)
{
es_format_t fmt;
es_format_Init(&fmt, VIDEO_ES, vout->p->fmt_render.i_chroma);
fmt.video = vout->p->fmt_render;
es_format_Init(&fmt, VIDEO_ES, vout->p->original.i_chroma);
fmt.video = vout->p->original;
vlc_mutex_lock(&vout->p->vfilter_lock);
......@@ -975,6 +971,79 @@ static void ThreadChangeZoom(vout_thread_t *vout, int num, int den)
vout_SetDisplayZoom(vout->p->display.vd, num, den);
}
static void ThreadChangeAspectRatio(vout_thread_t *vout,
unsigned num, unsigned den)
{
const video_format_t *source = &vout->p->original;
if (num > 0 && den > 0) {
num *= source->i_visible_height;
den *= source->i_visible_width;
vlc_ureduce(&num, &den, num, den, 0);
}
vout_SetDisplayAspect(vout->p->display.vd, num, den);
}
static void ThreadExecuteCropWindow(vout_thread_t *vout,
unsigned crop_num, unsigned crop_den,
unsigned x, unsigned y,
unsigned width, unsigned height)
{
const video_format_t *source = &vout->p->original;
vout_SetDisplayCrop(vout->p->display.vd,
crop_num, crop_den,
source->i_x_offset + x,
source->i_y_offset + y,
width, height);
}
static void ThreadExecuteCropBorder(vout_thread_t *vout,
unsigned left, unsigned top,
unsigned right, unsigned bottom)
{
const video_format_t *source = &vout->p->original;
ThreadExecuteCropWindow(vout, 0, 0,
left,
top,
/* At worst, it becomes < 0 (but unsigned) and will be rejected */
source->i_visible_width - (left + right),
source->i_visible_height - (top + bottom));
}
static void ThreadExecuteCropRatio(vout_thread_t *vout,
unsigned num, unsigned den)
{
const video_format_t *source = &vout->p->original;
int x, y;
int width, height;
if (num <= 0 || den <= 0) {
num = 0;
den = 0;
x = 0;
y = 0;
width = source->i_visible_width;
height = source->i_visible_height;
} else {
unsigned scaled_width = (uint64_t)source->i_visible_height * num * source->i_sar_den / den / source->i_sar_num;
unsigned scaled_height = (uint64_t)source->i_visible_width * den * source->i_sar_num / num / source->i_sar_den;
if (scaled_width < source->i_visible_width) {
x = (source->i_visible_width - scaled_width) / 2;
y = 0;
width = scaled_width;
height = source->i_visible_height;
} else {
x = 0;
y = (source->i_visible_height - scaled_height) / 2;
width = source->i_visible_width;
height = scaled_height;
}
}
ThreadExecuteCropWindow(vout, num, den, x, y, width, height);
}
static void ThreadClean(vout_thread_t *vout)
{
/* Destroy translation tables */
......@@ -1070,6 +1139,22 @@ static void *Thread(void *object)
case VOUT_CONTROL_ZOOM:
ThreadChangeZoom(vout, cmd.u.pair.a, cmd.u.pair.b);
break;
case VOUT_CONTROL_ASPECT_RATIO:
ThreadChangeAspectRatio(vout, cmd.u.pair.a, cmd.u.pair.b);
break;
case VOUT_CONTROL_CROP_RATIO:
ThreadExecuteCropRatio(vout, cmd.u.pair.a, cmd.u.pair.b);
break;
case VOUT_CONTROL_CROP_WINDOW:
ThreadExecuteCropWindow(vout, 0, 0,
cmd.u.window.x, cmd.u.window.y,
cmd.u.window.width, cmd.u.window.height);
break;
case VOUT_CONTROL_CROP_BORDER:
ThreadExecuteCropBorder(vout,
cmd.u.border.left, cmd.u.border.top,
cmd.u.border.right, cmd.u.border.bottom);
break;
default:
break;
}
......
......@@ -49,9 +49,7 @@ struct vout_thread_sys_t
config_chain_t *p_cfg;
/* */
video_format_t fmt_render; /* render format (from the decoder) */
video_format_t fmt_in; /* input (modified render) format */
video_format_t fmt_out; /* output format (for the video output) */
video_format_t original; /* Original format ie coming from the decoder */
/* Thread & synchronization */
vlc_thread_t thread;
......@@ -129,27 +127,17 @@ struct vout_thread_sys_t
vout_chrono_t render; /**< picture render time estimator */
vlc_mutex_t change_lock; /**< thread change lock */
uint16_t i_changes; /**< changes made to the thread.
\see \ref vout_changes */
};
/** \defgroup vout_changes Flags for changes
* These flags are set in the vout_thread_t::i_changes field when another
* thread changed a variable
* @{
*/
/** cropping parameters changed */
#define VOUT_CROP_CHANGE 0x1000
/** aspect ratio changed */
#define VOUT_ASPECT_CHANGE 0x2000
/**@}*/
/* TODO to move them to vlc_vout.h */
void vout_ControlChangeFullscreen(vout_thread_t *, bool fullscreen);
void vout_ControlChangeOnTop(vout_thread_t *, bool is_on_top);
void vout_ControlChangeDisplayFilled(vout_thread_t *, bool is_filled);
void vout_ControlChangeZoom(vout_thread_t *, int num, int den);
void vout_ControlChangeSampleAspectRatio(vout_thread_t *, unsigned num, unsigned den);
void vout_ControlChangeCropRatio(vout_thread_t *, unsigned num, unsigned den);
void vout_ControlChangeCropWindow(vout_thread_t *, int x, int y, int width, int height);
void vout_ControlChangeCropBorder(vout_thread_t *, int left, int top, int right, int bottom);
/* */
void vout_IntfInit( vout_thread_t * );
......
......@@ -57,6 +57,8 @@ static int ZoomCallback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * );
static int CropCallback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * );
static int CropBorderCallback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * );
static int AspectCallback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * );
static int ScalingCallback( vlc_object_t *, char const *,
......@@ -212,10 +214,10 @@ void vout_IntfInit( vout_thread_t *p_vout )
var_Create( p_vout, "crop-right", VLC_VAR_INTEGER | VLC_VAR_ISCOMMAND );
var_Create( p_vout, "crop-bottom", VLC_VAR_INTEGER | VLC_VAR_ISCOMMAND );
var_AddCallback( p_vout, "crop-left", CropCallback, NULL );
var_AddCallback( p_vout, "crop-top", CropCallback, NULL );
var_AddCallback( p_vout, "crop-right", CropCallback, NULL );
var_AddCallback( p_vout, "crop-bottom", CropCallback, NULL );
var_AddCallback( p_vout, "crop-left", CropBorderCallback, NULL );
var_AddCallback( p_vout, "crop-top", CropBorderCallback, NULL );
var_AddCallback( p_vout, "crop-right", CropBorderCallback, NULL );
var_AddCallback( p_vout, "crop-bottom", CropBorderCallback, NULL );
/* Crop object var */
var_Create( p_vout, "crop", VLC_VAR_STRING | VLC_VAR_ISCOMMAND |
......@@ -627,224 +629,59 @@ static int ZoomCallback( vlc_object_t *p_this, char const *psz_cmd,
return var_SetFloat( p_this, "scale", newval.f_float );
}
static int CropCallback( vlc_object_t *p_this, char const *psz_cmd,
vlc_value_t oldval, vlc_value_t newval, void *p_data )
static int CropCallback( vlc_object_t *object, char const *cmd,
vlc_value_t oldval, vlc_value_t newval, void *data )
{
vout_thread_t *p_vout = (vout_thread_t *)p_this;
int64_t i_aspect_num, i_aspect_den;
unsigned int i_width, i_height;
(void)oldval; (void)p_data;
/* Restore defaults */
p_vout->p->fmt_in.i_x_offset = p_vout->p->fmt_render.i_x_offset;
p_vout->p->fmt_in.i_visible_width = p_vout->p->fmt_render.i_visible_width;
p_vout->p->fmt_in.i_y_offset = p_vout->p->fmt_render.i_y_offset;
p_vout->p->fmt_in.i_visible_height = p_vout->p->fmt_render.i_visible_height;
if( !strcmp( psz_cmd, "crop" ) )
{
char *psz_end = NULL, *psz_parser = strchr( newval.psz_string, ':' );
if( psz_parser )
{
/* We're using the 3:4 syntax */
i_aspect_num = strtol( newval.psz_string, &psz_end, 10 );
if( psz_end == newval.psz_string || !i_aspect_num ) goto crop_end;
i_aspect_den = strtol( ++psz_parser, &psz_end, 10 );
if( psz_end == psz_parser || !i_aspect_den ) goto crop_end;
i_width = p_vout->p->fmt_in.i_sar_den*p_vout->p->fmt_render.i_visible_height *
i_aspect_num / i_aspect_den / p_vout->p->fmt_in.i_sar_num;
i_height = p_vout->p->fmt_render.i_visible_width*p_vout->p->fmt_in.i_sar_num *
i_aspect_den / i_aspect_num / p_vout->p->fmt_in.i_sar_den;
if( i_width < p_vout->p->fmt_render.i_visible_width )
{
p_vout->p->fmt_in.i_x_offset = p_vout->p->fmt_render.i_x_offset +
(p_vout->p->fmt_render.i_visible_width - i_width) / 2;
p_vout->p->fmt_in.i_visible_width = i_width;
}
else
{
p_vout->p->fmt_in.i_y_offset = p_vout->p->fmt_render.i_y_offset +
(p_vout->p->fmt_render.i_visible_height - i_height) / 2;
p_vout->p->fmt_in.i_visible_height = i_height;
}
}
else
{
psz_parser = strchr( newval.psz_string, 'x' );
if( psz_parser )
{
/* Maybe we're using the <width>x<height>+<left>+<top> syntax */
unsigned int i_crop_width, i_crop_height, i_crop_top, i_crop_left;
i_crop_width = strtol( newval.psz_string, &psz_end, 10 );
if( psz_end != psz_parser ) goto crop_end;
psz_parser = strchr( ++psz_end, '+' );
i_crop_height = strtol( psz_end, &psz_end, 10 );
if( psz_end != psz_parser ) goto crop_end;
psz_parser = strchr( ++psz_end, '+' );
i_crop_left = strtol( psz_end, &psz_end, 10 );
if( psz_end != psz_parser ) goto crop_end;
psz_end++;
i_crop_top = strtol( psz_end, &psz_end, 10 );
if( *psz_end != '\0' ) goto crop_end;
if( i_crop_top + i_crop_height >= p_vout->p->fmt_render.i_visible_height ||
i_crop_left + i_crop_width >= p_vout->p->fmt_render.i_visible_width )
{
msg_Err( p_vout, "Unable to crop over picture boundaries");
return VLC_EGENERIC;
}
i_width = i_crop_width;
p_vout->p->fmt_in.i_visible_width = i_width;
i_height = i_crop_height;
p_vout->p->fmt_in.i_visible_height = i_height;
p_vout->p->fmt_in.i_x_offset = i_crop_left;
p_vout->p->fmt_in.i_y_offset = i_crop_top;
}
else
{
/* Maybe we're using the <left>+<top>+<right>+<bottom> syntax */
unsigned int i_crop_top, i_crop_left, i_crop_bottom, i_crop_right;
psz_parser = strchr( newval.psz_string, '+' );
i_crop_left = strtol( newval.psz_string, &psz_end, 10 );
if( psz_end != psz_parser ) goto crop_end;
psz_parser = strchr( ++psz_end, '+' );
i_crop_top = strtol( psz_end, &psz_end, 10 );
if( psz_end != psz_parser ) goto crop_end;
psz_parser = strchr( ++psz_end, '+' );
i_crop_right = strtol( psz_end, &psz_end, 10 );
if( psz_end != psz_parser ) goto crop_end;
psz_end++;
i_crop_bottom = strtol( psz_end, &psz_end, 10 );
if( *psz_end != '\0' ) goto crop_end;
if( i_crop_top + i_crop_bottom >= p_vout->p->fmt_render.i_visible_height ||
i_crop_right + i_crop_left >= p_vout->p->fmt_render.i_visible_width )
{
msg_Err( p_vout, "Unable to crop over picture boundaries" );
return VLC_EGENERIC;
}
i_width = p_vout->p->fmt_render.i_visible_width
- i_crop_left - i_crop_right;
p_vout->p->fmt_in.i_visible_width = i_width;
i_height = p_vout->p->fmt_render.i_visible_height
- i_crop_top - i_crop_bottom;
p_vout->p->fmt_in.i_visible_height = i_height;
p_vout->p->fmt_in.i_x_offset = i_crop_left;
p_vout->p->fmt_in.i_y_offset = i_crop_top;
}
}
vout_thread_t *vout = (vout_thread_t *)object;
VLC_UNUSED(cmd); VLC_UNUSED(oldval); VLC_UNUSED(data);
unsigned num, den;
unsigned y, x;
unsigned width, height;
unsigned left, top, right, bottom;
if (sscanf(newval.psz_string, "%u:%u", &num, &den) == 2) {
vout_ControlChangeCropRatio(vout, num, den);
} else if (sscanf(newval.psz_string, "%ux%u+%u+%u",
&width, &height, &x, &y) == 4) {
vout_ControlChangeCropWindow(vout, x, y, width, height);
} else if (sscanf(newval.psz_string, "%u+%u+%u+%u",
&left, &top, &right, &bottom) == 4) {
vout_ControlChangeCropBorder(vout, left, top, right, bottom);
} else if (*newval.psz_string == '\0') {
vout_ControlChangeCropRatio(vout, 0, 0);
} else {
msg_Err(object, "Unknown crop format (%s)", newval.psz_string);
}
else if( !strcmp( psz_cmd, "crop-top" )
|| !strcmp( psz_cmd, "crop-left" )
|| !strcmp( psz_cmd, "crop-bottom" )
|| !strcmp( psz_cmd, "crop-right" ) )
{
unsigned int i_crop_top, i_crop_left, i_crop_bottom, i_crop_right;
i_crop_top = var_GetInteger( p_vout, "crop-top" );
i_crop_left = var_GetInteger( p_vout, "crop-left" );
i_crop_right = var_GetInteger( p_vout, "crop-right" );
i_crop_bottom = var_GetInteger( p_vout, "crop-bottom" );
if( i_crop_top + i_crop_bottom >= p_vout->p->fmt_render.i_visible_height ||
i_crop_right + i_crop_left >= p_vout->p->fmt_render.i_visible_width )
{
msg_Err( p_vout, "Unable to crop over picture boundaries" );
return VLC_EGENERIC;
}
i_width = p_vout->p->fmt_render.i_visible_width
- i_crop_left - i_crop_right;
p_vout->p->fmt_in.i_visible_width = i_width;
i_height = p_vout->p->fmt_render.i_visible_height
- i_crop_top - i_crop_bottom;
p_vout->p->fmt_in.i_visible_height = i_height;
p_vout->p->fmt_in.i_x_offset = i_crop_left;
p_vout->p->fmt_in.i_y_offset = i_crop_top;
}
crop_end:
p_vout->p->i_changes |= VOUT_CROP_CHANGE;
msg_Dbg( p_vout, "cropping picture %ix%i to %i,%i,%ix%i",
p_vout->p->fmt_in.i_width, p_vout->p->fmt_in.i_height,
p_vout->p->fmt_in.i_x_offset, p_vout->p->fmt_in.i_y_offset,
p_vout->p->fmt_in.i_visible_width,
p_vout->p->fmt_in.i_visible_height );
var_TriggerCallback( p_vout, "crop-update" );
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 )
static int CropBorderCallback(vlc_object_t *object, char const *cmd,
vlc_value_t oldval, vlc_value_t newval, void *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, ':' );
(void)psz_cmd; (void)oldval; (void)p_data;
/* Restore defaults */
p_vout->p->fmt_in.i_sar_num = p_vout->p->fmt_render.i_sar_num;
p_vout->p->fmt_in.i_sar_den = p_vout->p->fmt_render.i_sar_den;
if( !psz_parser ) goto aspect_end;
i_aspect_num = strtol( newval.psz_string, &psz_end, 10 );
if( psz_end == newval.psz_string || !i_aspect_num ) goto aspect_end;
i_aspect_den = strtol( ++psz_parser, &psz_end, 10 );
if( psz_end == psz_parser || !i_aspect_den ) goto aspect_end;
i_sar_num = i_aspect_num * p_vout->p->fmt_render.i_visible_height;
i_sar_den = i_aspect_den * p_vout->p->fmt_render.i_visible_width;
vlc_ureduce( &i_sar_num, &i_sar_den, i_sar_num, i_sar_den, 0 );
p_vout->p->fmt_in.i_sar_num = i_sar_num;
p_vout->p->fmt_in.i_sar_den = i_sar_den;
aspect_end:
if( p_vout->p->i_par_num && p_vout->p->i_par_den )
{
p_vout->p->fmt_in.i_sar_num *= p_vout->p->i_par_den;
p_vout->p->fmt_in.i_sar_den *= p_vout->p->i_par_num;
}
p_vout->p->i_changes |= VOUT_ASPECT_CHANGE;
msg_Dbg( p_vout, "new aspect-ratio %i:%i, sample aspect-ratio %i:%i",
p_vout->p->fmt_in.i_sar_num * p_vout->p->fmt_in.i_width,
p_vout->p->fmt_in.i_sar_den * p_vout->p->fmt_in.i_height,
p_vout->p->fmt_in.i_sar_num, p_vout->p->fmt_in.i_sar_den );
if( var_Get( p_vout, "crop", &val ) )
return VLC_EGENERIC;
vout_thread_t *vout = (vout_thread_t *)object;
VLC_UNUSED(cmd); VLC_UNUSED(oldval); VLC_UNUSED(data); VLC_UNUSED(newval);
vout_ControlChangeCropBorder(vout,
var_GetInteger(object, "crop-left"),
var_GetInteger(object, "crop-top"),
var_GetInteger(object, "crop-right"),
var_GetInteger(object, "crop-bottom"));
return VLC_SUCCESS;
}
int i_ret = CropCallback( p_this, "crop", val, val, 0 );
free( val.psz_string );
return i_ret;
static int AspectCallback( vlc_object_t *object, char const *cmd,
vlc_value_t oldval, vlc_value_t newval, void *data )
{
vout_thread_t *vout = (vout_thread_t *)object;
VLC_UNUSED(cmd); VLC_UNUSED(oldval); VLC_UNUSED(data);
unsigned num, den;
if (sscanf(newval.psz_string, "%u:%u", &num, &den) == 2 &&
(num > 0) == (den > 0))
vout_ControlChangeSampleAspectRatio(vout, num, den);
else if (*newval.psz_string == '\0')
vout_ControlChangeSampleAspectRatio(vout, 0, 0);
return VLC_SUCCESS;
}
static int ScalingCallback( vlc_object_t *p_this, char const *psz_cmd,
......
......@@ -66,7 +66,7 @@ int vout_OpenWrapper(vout_thread_t *vout, const char *name)
sys->display.title = var_CreateGetNonEmptyString(vout, "video-title");
/* */
video_format_t source = vout->p->fmt_render;
video_format_t source = vout->p->original;
source.i_visible_width = source.i_width;
source.i_visible_height = source.i_height;
source.i_x_offset = 0;
......@@ -131,37 +131,8 @@ int vout_InitWrapper(vout_thread_t *vout)
{
vout_thread_sys_t *sys = vout->p;
vout_display_t *vd = sys->display.vd;