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 { ...@@ -40,10 +40,6 @@ enum {
/* Controls */ /* Controls */
VOUT_CONTROL_SOURCE_ASPECT,
VOUT_CONTROL_SOURCE_CROP_BORDER,
VOUT_CONTROL_SOURCE_CROP_RATIO,
VOUT_CONTROL_SOURCE_CROP_WINDOW,
/* OSD */ /* OSD */
VOUT_CONTROL_OSD_MESSAGE, VOUT_CONTROL_OSD_MESSAGE,
...@@ -64,6 +60,11 @@ enum { ...@@ -64,6 +60,11 @@ enum {
VOUT_CONTROL_ON_TOP, /* bool */ VOUT_CONTROL_ON_TOP, /* bool */
VOUT_CONTROL_DISPLAY_FILLED, /* bool */ VOUT_CONTROL_DISPLAY_FILLED, /* bool */
VOUT_CONTROL_ZOOM, /* pair */ 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 { typedef struct {
...@@ -86,17 +87,6 @@ typedef struct { ...@@ -86,17 +87,6 @@ typedef struct {
int channel; int channel;
char *string; char *string;
} message; } 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 { struct {
unsigned left; unsigned left;
unsigned top; unsigned top;
...@@ -109,17 +99,6 @@ typedef struct { ...@@ -109,17 +99,6 @@ typedef struct {
unsigned width; unsigned width;
unsigned height; unsigned height;
} window; } window;
struct {
int channel;
int type;
float position;
} slider;
struct {
int channel;
int icon;
} icon;
subpicture_t *subpicture;
#endif
} u; } u;
} vout_control_cmd_t; } vout_control_cmd_t;
......
...@@ -525,9 +525,6 @@ static void VoutDisplayEventMouse(vout_display_t *vd, int event, va_list args) ...@@ -525,9 +525,6 @@ static void VoutDisplayEventMouse(vout_display_t *vd, int event, va_list args)
if (!vd->info.has_hide_mouse) if (!vd->info.has_hide_mouse)
osys->mouse.last_moved = mdate(); osys->mouse.last_moved = mdate();
/* */
vlc_mutex_unlock(&osys->lock);
/* */ /* */
vout_SendEventMouseVisible(osys->vout); vout_SendEventMouseVisible(osys->vout);
#ifdef ALLOW_DUMMY_VOUT #ifdef ALLOW_DUMMY_VOUT
...@@ -535,6 +532,7 @@ static void VoutDisplayEventMouse(vout_display_t *vd, int event, va_list args) ...@@ -535,6 +532,7 @@ static void VoutDisplayEventMouse(vout_display_t *vd, int event, va_list args)
#else #else
vout_SendDisplayEventMouse(osys->vout, &m); vout_SendDisplayEventMouse(osys->vout, &m);
#endif #endif
vlc_mutex_unlock(&osys->lock);
} }
static void VoutDisplayEvent(vout_display_t *vd, int event, va_list args) 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) ...@@ -1412,7 +1410,7 @@ void vout_SendDisplayEventMouse(vout_thread_t *vout, const vlc_mouse_t *m)
vlc_mouse_t tmp; vlc_mouse_t tmp;
/* The check on p_spu is needed as long as ALLOW_DUMMY_VOUT is defined */ /* 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; return;
vlc_mutex_lock( &vout->p->vfilter_lock ); 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, ...@@ -161,11 +161,7 @@ vout_thread_t *vout_Request( vlc_object_t *p_this, vout_thread_t *p_vout,
free( psz_filter_chain ); free( psz_filter_chain );
} }
#warning "FIXME: Check RGB masks in vout_Request" if( !video_format_IsSimilar( &p_vout->p->original, p_fmt ) ||
/* 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 ||
p_vout->p->b_filter_change ) p_vout->p->b_filter_change )
{ {
vlc_mutex_unlock( &p_vout->p->change_lock ); 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, ...@@ -178,32 +174,6 @@ vout_thread_t *vout_Request( vlc_object_t *p_this, vout_thread_t *p_vout,
else else
{ {
/* This video output is cool! Hijack it. */ /* 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_mutex_unlock( &p_vout->p->change_lock );
vlc_object_release( p_vout ); vlc_object_release( p_vout );
...@@ -272,17 +242,12 @@ vout_thread_t * (vout_Create)( vlc_object_t *p_parent, video_format_t *p_fmt ) ...@@ -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->original = *p_fmt; /* FIXME palette */
p_vout->p->fmt_in = *p_fmt; /* FIXME palette */ p_vout->p->original.i_chroma = i_chroma;
video_format_FixRgb( &p_vout->p->original );
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 );
/* Initialize misc stuff */ /* Initialize misc stuff */
vout_control_Init( &p_vout->p->control ); 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_chrono_Init( &p_vout->p->render, 5, 10000 ); /* Arbitrary initial time */
vout_statistic_Init( &p_vout->p->statistic ); vout_statistic_Init( &p_vout->p->statistic );
p_vout->p->b_filter_change = 0; p_vout->p->b_filter_change = 0;
...@@ -593,6 +558,42 @@ void vout_ControlChangeZoom(vout_thread_t *vout, int num, int den) ...@@ -593,6 +558,42 @@ void vout_ControlChangeZoom(vout_thread_t *vout, int num, int den)
vout_control_PushPair(&vout->p->control, VOUT_CONTROL_ZOOM, vout_control_PushPair(&vout->p->control, VOUT_CONTROL_ZOOM,
num, den); 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 * InitThread: initialize video output thread
...@@ -613,19 +614,14 @@ static int ThreadInit(vout_thread_t *vout) ...@@ -613,19 +614,14 @@ static int ThreadInit(vout_thread_t *vout)
/* print some usefull debug info about different vout formats /* print some usefull debug info about different vout formats
*/ */
PrintVideoFormat(vout, "pic render", &vout->p->fmt_render); PrintVideoFormat(vout, "pic render", &vout->p->original);
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);
return VLC_SUCCESS; return VLC_SUCCESS;
} }
static int ThreadDisplayPicture(vout_thread_t *vout, static int ThreadDisplayPicture(vout_thread_t *vout,
bool now, mtime_t *deadline) bool now, mtime_t *deadline)
{ {
vout_display_t *vd = vout->p->display.vd;
int displayed_count = 0; int displayed_count = 0;
int lost_count = 0; int lost_count = 0;
...@@ -743,7 +739,7 @@ static int ThreadDisplayPicture(vout_thread_t *vout, ...@@ -743,7 +739,7 @@ static int ThreadDisplayPicture(vout_thread_t *vout,
(vout->p->decoder_pool != vout->p->display_pool || subpic)) { (vout->p->decoder_pool != vout->p->display_pool || subpic)) {
picture_t *render; picture_t *render;
if (vout->p->is_decoder_pool_slow) 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) else if (vout->p->decoder_pool != vout->p->display_pool)
render = picture_pool_Get(vout->p->display_pool); render = picture_pool_Get(vout->p->display_pool);
else else
...@@ -753,8 +749,8 @@ static int ThreadDisplayPicture(vout_thread_t *vout, ...@@ -753,8 +749,8 @@ static int ThreadDisplayPicture(vout_thread_t *vout,
picture_Copy(render, filtered); picture_Copy(render, filtered);
spu_RenderSubpictures(vout->p->p_spu, spu_RenderSubpictures(vout->p->p_spu,
render, &vout->p->fmt_out, render, &vd->source,
subpic, &vout->p->fmt_in, spu_render_time); subpic, &vd->source, spu_render_time);
} }
if (vout->p->is_decoder_pool_slow) { if (vout->p->is_decoder_pool_slow) {
direct = picture_pool_Get(vout->p->display_pool); direct = picture_pool_Get(vout->p->display_pool);
...@@ -775,7 +771,7 @@ static int ThreadDisplayPicture(vout_thread_t *vout, ...@@ -775,7 +771,7 @@ static int ThreadDisplayPicture(vout_thread_t *vout,
* Take a snapshot if requested * Take a snapshot if requested
*/ */
if (direct && do_snapshot) 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 */ /* Render the direct buffer returned by vout_RenderPicture */
if (direct) { if (direct) {
...@@ -857,8 +853,8 @@ static void ThreadDisplayOsdTitle(vout_thread_t *vout, const char *string) ...@@ -857,8 +853,8 @@ static void ThreadDisplayOsdTitle(vout_thread_t *vout, const char *string)
static void ThreadChangeFilters(vout_thread_t *vout, const char *filters) static void ThreadChangeFilters(vout_thread_t *vout, const char *filters)
{ {
es_format_t fmt; es_format_t fmt;
es_format_Init(&fmt, VIDEO_ES, vout->p->fmt_render.i_chroma); es_format_Init(&fmt, VIDEO_ES, vout->p->original.i_chroma);
fmt.video = vout->p->fmt_render; fmt.video = vout->p->original;
vlc_mutex_lock(&vout->p->vfilter_lock); vlc_mutex_lock(&vout->p->vfilter_lock);
...@@ -975,6 +971,79 @@ static void ThreadChangeZoom(vout_thread_t *vout, int num, int den) ...@@ -975,6 +971,79 @@ static void ThreadChangeZoom(vout_thread_t *vout, int num, int den)
vout_SetDisplayZoom(vout->p->display.vd, num, 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) static void ThreadClean(vout_thread_t *vout)
{ {
/* Destroy translation tables */ /* Destroy translation tables */
...@@ -1070,6 +1139,22 @@ static void *Thread(void *object) ...@@ -1070,6 +1139,22 @@ static void *Thread(void *object)
case VOUT_CONTROL_ZOOM: case VOUT_CONTROL_ZOOM:
ThreadChangeZoom(vout, cmd.u.pair.a, cmd.u.pair.b); ThreadChangeZoom(vout, cmd.u.pair.a, cmd.u.pair.b);
break; 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: default:
break; break;
} }
......
...@@ -49,9 +49,7 @@ struct vout_thread_sys_t ...@@ -49,9 +49,7 @@ struct vout_thread_sys_t
config_chain_t *p_cfg; config_chain_t *p_cfg;
/* */ /* */
video_format_t fmt_render; /* render format (from the decoder) */ video_format_t original; /* Original format ie coming from the decoder */
video_format_t fmt_in; /* input (modified render) format */
video_format_t fmt_out; /* output format (for the video output) */
/* Thread & synchronization */ /* Thread & synchronization */
vlc_thread_t thread; vlc_thread_t thread;
...@@ -129,27 +127,17 @@ struct vout_thread_sys_t ...@@ -129,27 +127,17 @@ struct vout_thread_sys_t
vout_chrono_t render; /**< picture render time estimator */ vout_chrono_t render; /**< picture render time estimator */
vlc_mutex_t change_lock; /**< thread change lock */ 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 */ /* TODO to move them to vlc_vout.h */
void vout_ControlChangeFullscreen(vout_thread_t *, bool fullscreen); void vout_ControlChangeFullscreen(vout_thread_t *, bool fullscreen);
void vout_ControlChangeOnTop(vout_thread_t *, bool is_on_top); void vout_ControlChangeOnTop(vout_thread_t *, bool is_on_top);
void vout_ControlChangeDisplayFilled(vout_thread_t *, bool is_filled); void vout_ControlChangeDisplayFilled(vout_thread_t *, bool is_filled);
void vout_ControlChangeZoom(vout_thread_t *, int num, int den); 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 * ); void vout_IntfInit( vout_thread_t * );
......
...@@ -57,6 +57,8 @@ static int ZoomCallback( vlc_object_t *, char const *, ...@@ -57,6 +57,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 CropBorderCallback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * );
static int AspectCallback( vlc_object_t *, char const *, static int AspectCallback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * ); vlc_value_t, vlc_value_t, void * );
static int ScalingCallback( vlc_object_t *, char const *, static int ScalingCallback( vlc_object_t *, char const *,
...@@ -212,10 +214,10 @@ void vout_IntfInit( vout_thread_t *p_vout ) ...@@ -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-right", VLC_VAR_INTEGER | VLC_VAR_ISCOMMAND );
var_Create( p_vout, "crop-bottom", 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-left", CropBorderCallback, NULL );
var_AddCallback( p_vout, "crop-top", CropCallback, NULL ); var_AddCallback( p_vout, "crop-top", CropBorderCallback, NULL );
var_AddCallback( p_vout, "crop-right", CropCallback, NULL ); var_AddCallback( p_vout, "crop-right", CropBorderCallback, NULL );
var_AddCallback( p_vout, "crop-bottom", CropCallback, NULL ); var_AddCallback( p_vout, "crop-bottom", CropBorderCallback, NULL );
/* Crop object var */ /* Crop object var */
var_Create( p_vout, "crop", VLC_VAR_STRING | VLC_VAR_ISCOMMAND | 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, ...@@ -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 ); return var_SetFloat( p_this, "scale", newval.f_float );
} }
static int CropCallback( vlc_object_t *p_this, char const *psz_cmd, static int CropCallback( vlc_object_t *object, char const *cmd,
vlc_value_t oldval, vlc_value_t newval, void *p_data ) vlc_value_t oldval, vlc_value_t newval, void *data )
{ {
vout_thread_t *p_vout = (vout_thread_t *)p_this; vout_thread_t *vout = (vout_thread_t *)object;
int64_t i_aspect_num, i_aspect_den; VLC_UNUSED(cmd); VLC_UNUSED(oldval); VLC_UNUSED(data);
unsigned int i_width, i_height; unsigned num, den;
unsigned y, x;
(void)oldval; (void)p_data; unsigned width, height;
unsigned left, top, right, bottom;
/* Restore defaults */
p_vout->p->fmt_in.i_x_offset = p_vout->p->fmt_render.i_x_offset; if (sscanf(newval.psz_string, "%u:%u", &num, &den) == 2) {
p_vout->p->fmt_in.i_visible_width = p_vout->p->fmt_render.i_visible_width; vout_ControlChangeCropRatio(vout, num, den);
p_vout->p->fmt_in.i_y_offset = p_vout->p->fmt_render.i_y_offset; } else if (sscanf(newval.psz_string, "%ux%u+%u+%u",
p_vout->p->fmt_in.i_visible_height = p_vout->p->fmt_render.i_visible_height; &width, &height, &x, &y) == 4) {
vout_ControlChangeCropWindow(vout, x, y, width, height);
if( !strcmp( psz_cmd, "crop" ) ) } else if (sscanf(newval.psz_string, "%u+%u+%u+%u",
{ &left, &top, &right, &bottom) == 4) {
char *psz_end = NULL, *psz_parser = strchr( newval.psz_string, ':' ); vout_ControlChangeCropBorder(vout, left, top, right, bottom);
if( psz_parser ) } else if (*newval.psz_string == '\0') {
{ vout_ControlChangeCropRatio(vout, 0, 0);
/* We're using the 3:4 syntax */ } else {
i_aspect_num = strtol( newval.psz_string, &psz_end, 10 ); msg_Err(object, "Unknown crop format (%s)", newval.psz_string);
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;
}
} }
}
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; return VLC_SUCCESS;
} }
static int AspectCallback( vlc_object_t *p_this, char const *psz_cmd, static int CropBorderCallback(vlc_object_t *object, char const *cmd,
vlc_value_t oldval, vlc_value_t newval, void *p_data ) vlc_value_t oldval, vlc_value_t newval, void *data)
{ {
vout_thread_t *p_vout = (vout_thread_t *)p_this; vout_thread_t *vout = (vout_thread_t *)object;
unsigned int i_aspect_num, i_aspect_den, i_sar_num, i_sar_den; VLC_UNUSED(cmd); VLC_UNUSED(oldval); VLC_UNUSED(data); VLC_UNUSED(newval);
vlc_value_t val;
vout_ControlChangeCropBorder(vout,
char *psz_end, *psz_parser = strchr( newval.psz_string, ':' ); var_GetInteger(object, "crop-left"),
(void)psz_cmd; (void)oldval; (void)p_data; var_GetInteger(object, "crop-top"),
var_GetInteger(object, "crop-right"),
/* Restore defaults */ var_GetInteger(object, "crop-bottom"));
p_vout->p->fmt_in.i_sar_num = p_vout->p->fmt_render.i_sar_num; return VLC_SUCCESS;
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;
int i_ret = CropCallback( p_this, "crop", val, val, 0 ); static int AspectCallback( vlc_object_t *object, char const *cmd,
free( val.psz_string ); vlc_value_t oldval, vlc_value_t newval, void *data )
return i_ret; {
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, 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) ...@@ -66,7 +66,7 @@ int vout_OpenWrapper(vout_thread_t *vout, const char *name)
sys->display.title = var_CreateGetNonEmptyString(vout, "video-title"); 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_width = source.i_width;
source.i_visible_height = source.i_height; source.i_visible_height = source.i_height;
source.i_x_offset = 0; source.i_x_offset = 0;
...@@ -131,37 +131,8 @@ int vout_InitWrapper(vout_thread_t *vout) ...@@ -131,37 +131,8 @@ int vout_InitWrapper(vout_thread_t *vout)
{ {
vout_thread_sys_t *sys = vout->p; vout_thread_sys_t *sys = vout->p;
vout_display_t *vd = sys->display.vd; vout_display_t *vd = sys->display.vd;
/* */
video_format_t source = vd->source; video_format_t source = vd->source;
vout->p->fmt_out.i_chroma = source.i_chroma;
vout->p->fmt_out.i_width =
vout->p->fmt_out.i_visible_width = source.i_width;
vout->p->fmt_out.i_height =
vout->p->fmt_out.i_visible_height = source.i_height;
if (source.i_sar_num > 0 && source.i_sar_den > 0) {
vlc_ureduce(&vout->p->fmt_out.i_sar_num, &vout->p->fmt_out.i_sar_den,
source.i_sar_num, source.i_sar_den, 0);
} else {
vout->p->fmt_out.i_sar_num = 1;
vout->p->fmt_out.i_sar_den = 1;
}
vout->p->fmt_out.i_sar_num = source.i_sar_num;
vout->p->fmt_out.i_sar_den = source.i_sar_den;
vout->p->fmt_out.i_x_offset = 0;
vout->p->fmt_out.i_y_offset = 0;
vout->p->fmt_out.i_rmask = source.i_rmask;
vout->p->fmt_out.i_gmask = source.i_gmask;
vout->p->fmt_out.i_bmask = source.i_bmask;
video_format_FixRgb(&vout->p->fmt_out);
if (vout->p->fmt_in.i_visible_width != source.i_visible_width ||
vout->p->fmt_in.i_visible_height != source.i_visible_height ||
vout->p->fmt_in.i_x_offset != source.i_x_offset ||
vout->p->fmt_in.i_y_offset != source.i_y_offset )
sys->i_changes |= VOUT_CROP_CHANGE;
/* XXX For non dr case, the current vout implementation force us to /* XXX For non dr case, the current vout implementation force us to
* create at most 1 direct picture (otherwise the buffers will be kept * create at most 1 direct picture (otherwise the buffers will be kept
* referenced even through the Init/End. * referenced even through the Init/End.
...@@ -213,44 +184,6 @@ int vout_ManageWrapper(vout_thread_t *vout) ...@@ -213,44 +184,6 @@ int vout_ManageWrapper(vout_thread_t *vout)
vout_thread_sys_t *sys = vout->p; vout_thread_sys_t *sys = vout->p;
vout_display_t *vd = sys->display.vd; vout_display_t *vd = sys->display.vd;
while (sys->i_changes & (VOUT_ASPECT_CHANGE |
VOUT_CROP_CHANGE)) {
/* */
if (sys->i_changes & VOUT_ASPECT_CHANGE) {
vout->p->fmt_out.i_sar_num = vout->p->fmt_in.i_sar_num;
vout->p->fmt_out.i_sar_den = vout->p->fmt_in.i_sar_den;
vout_SetDisplayAspect(vd, vout->p->fmt_in.i_sar_num, vout->p->fmt_in.i_sar_den);
sys->i_changes &= ~VOUT_ASPECT_CHANGE;
}
if (sys->i_changes & VOUT_CROP_CHANGE) {
const video_format_t crop = vout->p->fmt_in;
const video_format_t org = vout->p->fmt_render;
/* FIXME because of rounding errors, the reconstructed ratio is wrong */
unsigned num = 0;
unsigned den = 0;
if (crop.i_x_offset == org.i_x_offset &&
crop.i_visible_width == org.i_visible_width &&
crop.i_y_offset == org.i_y_offset + (org.i_visible_height - crop.i_visible_height)/2) {
vlc_ureduce(&num, &den,
crop.i_visible_width * crop.i_sar_num,
crop.i_visible_height * crop.i_sar_den, 0);
} else if (crop.i_y_offset == org.i_y_offset &&
crop.i_visible_height == org.i_visible_height &&
crop.i_x_offset == org.i_x_offset + (org.i_visible_width - crop.i_visible_width)/2) {
vlc_ureduce(&num, &den,
crop.i_visible_width * crop.i_sar_num,
crop.i_visible_height * crop.i_sar_den, 0);
}
vout_SetDisplayCrop(vd, num, den,
crop.i_x_offset, crop.i_y_offset,
crop.i_visible_width, crop.i_visible_height);
sys->i_changes &= ~VOUT_CROP_CHANGE;
}
}
bool reset_display_pool = sys->display.use_dr && vout_AreDisplayPicturesInvalid(vd); bool reset_display_pool = sys->display.use_dr && vout_AreDisplayPicturesInvalid(vd);
vout_ManageDisplay(vd, !sys->display.use_dr || reset_display_pool); vout_ManageDisplay(vd, !sys->display.use_dr || reset_display_pool);
......
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