video: move handling of -x/-y/-xy options to VO

Now the calculations of the final display size are done after the filter
chain. This makes the difference between display aspect ratio and window
size a bit more clear, especially in the -xy case.

With an empty filter chain, the behavior of the options should be the
same, except that they don't affect vo_image and vo_lavc anymore.
This commit is contained in:
wm4 2013-01-22 13:28:31 +01:00
parent c9396c0aab
commit f2dcdca0c2
11 changed files with 94 additions and 88 deletions

View File

@ -55,8 +55,6 @@ const vd_functions_t * const mpcodecs_vd_drivers[] = {
int mpcodecs_config_vo(sh_video_t *sh, int w, int h, unsigned int out_fmt)
{
struct MPOpts *opts = sh->opts;
int screen_size_x = 0;
int screen_size_y = 0;
vf_instance_t *vf = sh->vfilter;
int vocfg_flags = 0;
@ -130,53 +128,25 @@ int mpcodecs_config_vo(sh_video_t *sh, int w, int h, unsigned int out_fmt)
else if (sh->stream_aspect != 0.0)
sh->aspect = sh->stream_aspect;
if (opts->screen_size_x || opts->screen_size_y) {
screen_size_x = opts->screen_size_x;
screen_size_y = opts->screen_size_y;
if (!opts->vidmode) {
if (!screen_size_x)
screen_size_x = 1;
if (!screen_size_y)
screen_size_y = 1;
if (screen_size_x <= 8)
screen_size_x *= sh->disp_w;
if (screen_size_y <= 8)
screen_size_y *= sh->disp_h;
int d_w = sh->disp_w;
int d_h = sh->disp_h;
if (sh->aspect > 0.01) {
int new_w = d_h * sh->aspect;
int new_h = d_h;
// we don't like horizontal downscale
if (new_w < d_w) {
new_w = d_w;
new_h = d_w / sh->aspect;
}
} else {
// check source format aspect, calculate prescale ::atmos
screen_size_x = sh->disp_w;
screen_size_y = sh->disp_h;
if (opts->screen_size_xy >= 0.001) {
if (opts->screen_size_xy <= 8) {
// -xy means x+y scale
screen_size_x *= opts->screen_size_xy;
screen_size_y *= opts->screen_size_xy;
} else {
// -xy means forced width while keeping correct aspect
screen_size_x = opts->screen_size_xy;
screen_size_y = opts->screen_size_xy * sh->disp_h / sh->disp_w;
}
}
if (sh->aspect > 0.01) {
mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VIDEO_ASPECT=%1.4f\n",
sh->aspect);
int w = screen_size_y * sh->aspect;
int h = screen_size_y;
// we don't like horizontal downscale || user forced width:
if (w < screen_size_x || opts->screen_size_xy > 8) {
w = screen_size_x;
h = screen_size_x / sh->aspect;
}
if (abs(screen_size_x - w) >= 4 || abs(screen_size_y - h) >= 4) {
screen_size_x = w;
screen_size_y = h;
mp_tmsg(MSGT_CPLAYER, MSGL_V, "Aspect ratio is %.2f:1 - "
"scaling to correct movie aspect.\n", sh->aspect);
}
} else {
mp_tmsg(MSGT_CPLAYER, MSGL_V, "Movie-Aspect is undefined - no prescaling applied.\n");
if (abs(d_w - new_w) >= 4 || abs(d_h - new_h) >= 4) {
d_w = new_w;
d_h = new_h;
mp_tmsg(MSGT_CPLAYER, MSGL_V, "Aspect ratio is %.2f:1 - "
"scaling to correct movie aspect.\n", sh->aspect);
}
mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VIDEO_ASPECT=%1.4f\n", sh->aspect);
}
vocfg_flags = (opts->fullscreen ? VOFLAG_FULLSCREEN : 0)
@ -186,11 +156,10 @@ int mpcodecs_config_vo(sh_video_t *sh, int w, int h, unsigned int out_fmt)
// Time to config libvo!
mp_msg(MSGT_CPLAYER, MSGL_V,
"VO Config (%dx%d->%dx%d,flags=%d,0x%X)\n", sh->disp_w,
sh->disp_h, screen_size_x, screen_size_y, vocfg_flags, out_fmt);
sh->disp_h, d_w, d_h, vocfg_flags, out_fmt);
if (vf_config_wrapper
(vf, sh->disp_w, sh->disp_h, screen_size_x, screen_size_y, vocfg_flags,
out_fmt) == 0) {
if (vf_config_wrapper(vf, sh->disp_w, sh->disp_h, d_w, d_h, vocfg_flags,
out_fmt) == 0) {
mp_tmsg(MSGT_CPLAYER, MSGL_WARN, "FATAL: Cannot initialize video driver.\n");
sh->vf_initialized = -1;
return 0;

View File

@ -514,16 +514,12 @@ void vf_uninit_filter_chain(vf_instance_t *vf)
}
}
// When cropping an image that had old_w/old_h/*d_width/*d_height to the new
// size new_w/new_h, adjust *d_width/*d_height such that the new image has
// the same pixel aspect ratio.
void vf_rescale_dsize(struct vf_instance *vf, int *d_width, int *d_height,
int old_w, int old_h, int new_w, int new_h)
// When changing the size of an image that had old_w/old_h with
// DAR *d_width/*d_height to the new size new_w/new_h, adjust
// *d_width/*d_height such that the new image has the same pixel aspect ratio.
void vf_rescale_dsize(int *d_width, int *d_height, int old_w, int old_h,
int new_w, int new_h)
{
// No idea what this is about
if (vf->opts->screen_size_x || vf->opts->screen_size_y)
return;
*d_width = *d_width * new_w / old_w;
*d_height = *d_height * new_h / old_h;
}

View File

@ -144,8 +144,8 @@ int vf_config_wrapper(struct vf_instance *vf,
unsigned int flags, unsigned int outfmt);
void vf_print_filter_chain(int msglevel, struct vf_instance *vf);
void vf_rescale_dsize(struct vf_instance *vf, int *d_width, int *d_height,
int old_w, int old_h, int new_w, int new_h);
void vf_rescale_dsize(int *d_width, int *d_height, int old_w, int old_h,
int new_w, int new_h);
static inline int norm_qscale(int qscale, int type)
{

View File

@ -63,7 +63,7 @@ static int config(struct vf_instance *vf,
mp_tmsg(MSGT_VFILTER, MSGL_WARN, "[CROP] Bad position/width/height - cropped area outside of the original!\n");
return 0;
}
vf_rescale_dsize(vf, &d_width, &d_height, width, height,
vf_rescale_dsize(&d_width, &d_height, width, height,
vf->priv->crop_w, vf->priv->crop_h);
return vf_next_config(vf,vf->priv->crop_w,vf->priv->crop_h,d_width,d_height,flags,outfmt);
}

View File

@ -101,7 +101,7 @@ static int config(struct vf_instance *vf,
vf->priv->exp_x = MP_ALIGN_DOWN(vf->priv->exp_x, fmt.align_x);
vf->priv->exp_y = MP_ALIGN_DOWN(vf->priv->exp_y, fmt.align_y);
vf_rescale_dsize(vf, &d_width, &d_height, width, height,
vf_rescale_dsize(&d_width, &d_height, width, height,
vf->priv->exp_w, vf->priv->exp_h);
return vf_next_config(vf,vf->priv->exp_w,vf->priv->exp_h,d_width,d_height,flags,outfmt);

View File

@ -34,7 +34,7 @@ static int config(struct vf_instance *vf, int width, int height,
{
struct mp_imgfmt_desc desc = mp_imgfmt_get_desc(fmt);
int a_w = MP_ALIGN_DOWN(width, desc.align_x);
vf_rescale_dsize(vf, &d_width, &d_height, width, height, a_w, height);
vf_rescale_dsize(&d_width, &d_height, width, height, a_w, height);
return vf_next_config(vf, a_w, height, d_width, d_height, flags, fmt);
}

View File

@ -77,7 +77,7 @@ static int config(struct vf_instance *vf, int width, int height,
struct mp_imgfmt_desc desc = mp_imgfmt_get_desc(outfmt);
int a_w = MP_ALIGN_DOWN(width, desc.align_x);
int a_h = MP_ALIGN_DOWN(height, desc.align_y);
vf_rescale_dsize(vf, &d_width, &d_height, width, height, a_w, a_h);
vf_rescale_dsize(&d_width, &d_height, width, height, a_w, a_h);
return vf_next_config(vf, a_h, a_w, d_height, d_width, flags, outfmt);
}

View File

@ -303,9 +303,6 @@ static int config(struct vf_instance *vf,
return 0;
}
vf->priv->fmt=best;
if (!opts->screen_size_x && !opts->screen_size_y
&& !(opts->screen_size_xy >= 0.001)) {
// Compute new d_width and d_height, preserving aspect
// while ensuring that both are >= output size in pixels.
if (vf->priv->h * d_width > vf->priv->w * d_height) {
@ -317,7 +314,6 @@ static int config(struct vf_instance *vf,
}
//d_width=d_width*vf->priv->w/width;
//d_height=d_height*vf->priv->h/height;
}
return vf_next_config(vf,vf->priv->w,vf->priv->h,d_width,d_height,flags,best);
}

View File

@ -148,8 +148,6 @@ static inline uint8_t ana_convert(int coeff[6], uint8_t left[3], uint8_t right[3
static int config(struct vf_instance *vf, int width, int height, int d_width,
int d_height, unsigned int flags, unsigned int outfmt)
{
struct MPOpts *opts = vf->opts;
if ((width & 1) || (height & 1)) {
mp_msg(MSGT_VFILTER, MSGL_WARN, "[stereo3d] invalid height or width\n");
return 0;
@ -271,10 +269,8 @@ static int config(struct vf_instance *vf, int width, int height, int d_width,
return 0;
break;
}
if (!opts->screen_size_x && !opts->screen_size_y) {
d_width = d_width * vf->priv->out.width / width;
d_height = d_height * vf->priv->out.height / height;
}
vf_rescale_dsize(&d_width, &d_height, width, height,
vf->priv->out.width, vf->priv->out.height);
return vf_next_config(vf, vf->priv->out.width, vf->priv->out.height,
d_width, d_height, flags, outfmt);
}

View File

@ -68,7 +68,7 @@ static int config(struct vf_instance *vf,
double dar = (double)d_width / d_height;
double sar = (double)width / height;
vf_rescale_dsize(vf, &d_width, &d_height, width, height,
vf_rescale_dsize(&d_width, &d_height, width, height,
vf->priv->outw, vf->priv->outh);
vf->priv->dim = (struct mp_osd_res) {

View File

@ -356,6 +356,63 @@ struct vo *init_best_video_out(struct MPOpts *opts,
return NULL;
}
// Set window size (vo->dwidth/dheight) and position (vo->dx/dy) according to
// the video display size d_w/d_h.
// NOTE: currently, all GUI backends do their own handling of window geometry
// additional to this code. This is to deal with initial window placement,
// fullscreen handling, avoiding resize on config() with no size change,
// multi-monitor stuff, and possibly more.
static void determine_window_geometry(struct vo *vo, int d_w, int d_h)
{
struct MPOpts *opts = vo->opts;
int vid_w = vo->aspdat.orgw;
int vid_h = vo->aspdat.orgh;
if (opts->screen_size_x || opts->screen_size_y) {
d_w = opts->screen_size_x;
d_h = opts->screen_size_y;
if (!opts->vidmode) {
if (!d_w)
d_w = 1;
if (!d_h)
d_h = 1;
if (d_w <= 8)
d_w *= vid_w;
if (d_h <= 8)
d_h *= vid_h;
}
}
// This is only for applying monitor pixel aspect
// Store d_w/d_h, because aspect() uses it
aspect_save_videores(vo, vid_w, vid_h, d_w, d_h);
aspect(vo, &d_w, &d_h, A_NOZOOM);
if (opts->screen_size_xy >= 0.001) {
if (opts->screen_size_xy <= 8) {
// -xy means x+y scale
d_w *= opts->screen_size_xy;
d_h *= opts->screen_size_xy;
} else {
// -xy means forced width while keeping correct aspect
d_h = opts->screen_size_xy * d_h / d_w;
d_w = opts->screen_size_xy;
}
}
vo->dx = (int)(opts->vo_screenwidth - d_w) / 2;
vo->dy = (int)(opts->vo_screenheight - d_h) / 2;
geometry(&vo->dx, &vo->dy, &d_w, &d_h,
opts->vo_screenwidth, opts->vo_screenheight);
geometry_xy_changed |= xinerama_screen >= 0;
vo->dx += xinerama_x;
vo->dy += xinerama_y;
vo->dwidth = d_w;
vo->dheight = d_h;
}
static int event_fd_callback(void *ctx, int fd)
{
struct vo *vo = ctx;
@ -367,21 +424,13 @@ int vo_config(struct vo *vo, uint32_t width, uint32_t height,
uint32_t d_width, uint32_t d_height, uint32_t flags,
uint32_t format)
{
struct MPOpts *opts = vo->opts;
panscan_init(vo);
aspect_save_videores(vo, width, height, d_width, d_height);
if (vo_control(vo, VOCTRL_UPDATE_SCREENINFO, NULL) == VO_TRUE) {
aspect(vo, &d_width, &d_height, A_NOZOOM);
vo->dx = (int)(opts->vo_screenwidth - d_width) / 2;
vo->dy = (int)(opts->vo_screenheight - d_height) / 2;
geometry(&vo->dx, &vo->dy, &d_width, &d_height,
opts->vo_screenwidth, opts->vo_screenheight);
geometry_xy_changed |= xinerama_screen >= 0;
vo->dx += xinerama_x;
vo->dy += xinerama_y;
vo->dwidth = d_width;
vo->dheight = d_height;
determine_window_geometry(vo, d_width, d_height);
d_width = vo->dwidth;
d_height = vo->dheight;
}
vo->default_caps = vo->driver->query_format(vo, format);