video: switch from using display aspect to sample aspect

MPlayer traditionally always used the display aspect ratio, e.g. 16:9,
while FFmpeg uses the sample (aka pixel) aspect ratio.

Both have a bunch of advantages and disadvantages. Actually, it seems
using sample aspect ratio is generally nicer. The main reason for the
change is making mpv closer to how FFmpeg works in order to make life
easier. It's also nice that everything uses integer fractions instead
of floats now (except --video-aspect option/property).

Note that there is at least 1 user-visible change: vf_dsize now does
not set the display size, only the display aspect ratio. This is
because the image_params d_w/d_h fields did not just set the display
aspect, but also the size (except in encoding mode).
This commit is contained in:
wm4 2015-12-19 20:04:31 +01:00
parent 1f7c099dc0
commit 0a0bb9059f
37 changed files with 154 additions and 215 deletions

View File

@ -151,15 +151,15 @@ Available filters are:
:yes: Enable accurate rounding.
``dsize[=w:h:aspect-method:r:aspect]``
Changes the intended display size/aspect at an arbitrary point in the
Changes the intended display aspect at an arbitrary point in the
filter chain. Aspect can be given as a fraction (4/3) or floating point
number (1.33). Alternatively, you may specify the exact display width and
height desired. Note that this filter does *not* do any scaling itself; it
number (1.33). Note that this filter does *not* do any scaling itself; it
just affects what later scalers (software or hardware) will do when
auto-scaling to the correct aspect.
``<w>,<h>``
New display width and height.
New aspect ratio given by a display width and height. Unlike older mpv
versions or MPlayer, this does not set the display size.
Can also be these special values:

View File

@ -147,7 +147,10 @@ static void add_streams(demuxer_t *demuxer)
double ar;
if (stream_control(demuxer->stream, STREAM_CTRL_GET_ASPECT_RATIO, &ar)
== STREAM_OK)
sh->video->aspect = ar;
{
sh->video->par_w = 1728 * ar; // being lazy here
sh->video->par_h = 1728 / ar;
}
}
if (src->audio)
sh->audio = src->audio;

View File

@ -589,12 +589,8 @@ static void handle_stream(demuxer_t *demuxer, int i)
sh_video->fps = fps;
if (priv->format_hack.image_format)
sh_video->fps = demuxer->opts->mf_fps;
if (st->sample_aspect_ratio.num)
sh_video->aspect = codec->width * st->sample_aspect_ratio.num
/ (float)(codec->height * st->sample_aspect_ratio.den);
else
sh_video->aspect = codec->width * codec->sample_aspect_ratio.num
/ (float)(codec->height * codec->sample_aspect_ratio.den);
sh_video->par_w = st->sample_aspect_ratio.num;
sh_video->par_h = st->sample_aspect_ratio.den;
uint8_t *sd = av_stream_get_side_data(st, AV_PKT_DATA_DISPLAYMATRIX, NULL);
if (sd) {

View File

@ -48,6 +48,7 @@
#include "misc/bstr.h"
#include "stream/stream.h"
#include "video/csputils.h"
#include "video/mp_image.h"
#include "demux.h"
#include "stheader.h"
#include "ebml.h"
@ -1367,10 +1368,14 @@ static int demux_mkv_open_video(demuxer_t *demuxer, mkv_track_t *track)
sh_v->fps = track->v_frate;
sh_v->disp_w = track->v_width;
sh_v->disp_h = track->v_height;
uint32_t dw = track->v_dwidth_set ? track->v_dwidth : track->v_width;
uint32_t dh = track->v_dheight_set ? track->v_dheight : track->v_height;
sh_v->aspect = (dw && dh) ? (double) dw / dh : 0;
MP_VERBOSE(demuxer, "Aspect: %f\n", sh_v->aspect);
int dw = track->v_dwidth_set ? track->v_dwidth : track->v_width;
int dh = track->v_dheight_set ? track->v_dheight : track->v_height;
struct mp_image_params p = {.w = track->v_width, .h = track->v_height};
mp_image_params_set_dsize(&p, dw, dh);
sh_v->par_w = p.p_w;
sh_v->par_h = p.p_h;
sh_v->stereo_mode = track->stereo_mode;
return 0;

View File

@ -83,7 +83,7 @@ typedef struct sh_audio {
typedef struct sh_video {
bool avi_dts; // use DTS timing; first frame and DTS is 0
float fps; // frames per second (set only if constant fps)
float aspect; // aspect ratio stored in the file (for prescaling)
int par_w, par_h; // pixel aspect ratio (0 if unknown/square)
int bits_per_coded_sample;
int disp_w, disp_h; // display size
int rotate; // intended display rotation, in degrees, [0, 359]

View File

@ -2449,8 +2449,8 @@ static int property_imgparams(struct mp_image_params p, int action, void *arg)
if (!p.imgfmt)
return M_PROPERTY_UNAVAILABLE;
double dar = p.d_w / (double)p.d_h;
double sar = p.w / (double)p.h;
int d_w, d_h;
mp_image_params_get_dsize(&p, &d_w, &d_h);
struct mp_imgfmt_desc desc = mp_imgfmt_get_desc(p.imgfmt);
int bpp = 0;
@ -2465,10 +2465,10 @@ static int property_imgparams(struct mp_image_params p, int action, void *arg)
.unavailable = !(desc.flags & MP_IMGFLAG_PLANAR)},
{"w", SUB_PROP_INT(p.w)},
{"h", SUB_PROP_INT(p.h)},
{"dw", SUB_PROP_INT(p.d_w)},
{"dh", SUB_PROP_INT(p.d_h)},
{"aspect", SUB_PROP_FLOAT(dar)},
{"par", SUB_PROP_FLOAT(dar / sar)},
{"dw", SUB_PROP_INT(d_w)},
{"dh", SUB_PROP_INT(d_h)},
{"aspect", SUB_PROP_FLOAT(d_w / (double)d_h)},
{"par", SUB_PROP_FLOAT(p.p_w / (double)p.p_h)},
{"colormatrix",
SUB_PROP_STR(m_opt_choice_str(mp_csp_names, p.colorspace))},
{"colorlevels",
@ -2561,8 +2561,8 @@ static int mp_property_window_scale(void *ctx, struct m_property *prop,
return M_PROPERTY_UNAVAILABLE;
struct mp_image_params params = get_video_out_params(mpctx);
int vid_w = params.d_w;
int vid_h = params.d_h;
int vid_w, vid_h;
mp_image_params_get_dsize(&params, &vid_w, &vid_h);
if (vid_w < 1 || vid_h < 1)
return M_PROPERTY_UNAVAILABLE;
@ -2781,8 +2781,10 @@ static int mp_property_aspect(void *ctx, struct m_property *prop,
struct dec_video *d_video = mpctx->d_video;
struct sh_video *sh_video = d_video->header->video;
struct mp_image_params *params = &d_video->vfilter->override_params;
if (params && params->d_w && params->d_h) {
aspect = (float)params->d_w / params->d_h;
if (params && params->p_w > 0 && params->p_h > 0) {
int d_w, d_h;
mp_image_params_get_dsize(params, &d_w, &d_h);
aspect = (float)d_w / d_h;
} else if (sh_video->disp_w && sh_video->disp_h) {
aspect = (float)sh_video->disp_w / sh_video->disp_h;
}

View File

@ -889,7 +889,7 @@ int handle_force_window(struct MPContext *mpctx, bool force)
struct mp_image_params p = {
.imgfmt = config_format,
.w = w, .h = h,
.d_w = w, .d_h = h,
.p_w = 1, .p_h = 1,
};
if (vo_reconfig(vo, &p) < 0)
goto err;

View File

@ -308,14 +308,7 @@ static char *gen_fname(screenshot_ctx *ctx, const char *file_ext)
static void add_subs(struct MPContext *mpctx, struct mp_image *image)
{
double sar = (double)image->w / image->h;
double dar = (double)image->params.d_w / image->params.d_h;
struct mp_osd_res res = {
.w = image->w,
.h = image->h,
.display_par = sar / dar,
};
struct mp_osd_res res = osd_res_from_image_params(&image->params);
osd_draw_on_image(mpctx->osd, res, mpctx->video_pts,
OSD_DRAW_SUB_ONLY, image);
}

View File

@ -1186,8 +1186,11 @@ void write_video(struct MPContext *mpctx, double endpts)
const struct vo_driver *info = mpctx->video_out->driver;
char extra[20] = {0};
if (p.w != p.d_w || p.h != p.d_h)
snprintf(extra, sizeof(extra), " => %dx%d", p.d_w, p.d_h);
if (p.p_w != p.p_h) {
int d_w, d_h;
mp_image_params_get_dsize(&p, &d_w, &d_h);
snprintf(extra, sizeof(extra), " => %dx%d", d_w, d_h);
}
MP_INFO(mpctx, "VO: [%s] %dx%d%s %s\n",
info->name, p.w, p.h, extra, vo_format_name(p.imgfmt));
MP_VERBOSE(mpctx, "VO: Description: %s\n", info->description);

View File

@ -388,13 +388,10 @@ void osd_draw_on_image_p(struct osd_state *osd, struct mp_osd_res res,
// ratio if the image does not have a 1:1 pixel aspect ratio.
struct mp_osd_res osd_res_from_image_params(const struct mp_image_params *p)
{
double sar = (double)p->w / p->h;
double dar = (double)p->d_w / p->d_h;
return (struct mp_osd_res) {
.w = p->w,
.h = p->h,
.display_par = sar / dar,
.display_par = p->p_h / (double)p->p_w,
};
}

View File

@ -343,11 +343,9 @@ static void get_bitmaps(struct sd *sd, struct mp_osd_res dim, double pts,
opts->ass_vsfilter_aspect_compat))
{
// Let's use the original video PAR for vsfilter compatibility:
double par = scale
* (ctx->video_params.d_w / (double)ctx->video_params.d_h)
/ (ctx->video_params.w / (double)ctx->video_params.h);
double par = ctx->video_params.p_w / (double)ctx->video_params.p_h;
if (isnormal(par))
scale = par;
scale *= par;
}
configure_ass(sd, &dim, converted, track);
ass_set_pixel_aspect(renderer, scale);

View File

@ -318,11 +318,10 @@ static void get_bitmaps(struct sd *sd, struct mp_osd_res d, double pts,
double video_par = 0;
if (priv->avctx->codec_id == AV_CODEC_ID_DVD_SUBTITLE &&
opts->stretch_dvd_subs) {
opts->stretch_dvd_subs)
{
// For DVD subs, try to keep the subtitle PAR at display PAR.
double par =
(priv->video_params.d_w / (double)priv->video_params.d_h)
/ (priv->video_params.w / (double)priv->video_params.h);
double par = priv->video_params.p_w / (double)priv->video_params.p_h;
if (isnormal(par))
video_par = par;
}

View File

@ -15,14 +15,15 @@
* with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "options/options.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>
#include <libavutil/rational.h>
#include "config.h"
#include "options/options.h"
#include "common/msg.h"
#include "osdep/timer.h"
@ -342,7 +343,7 @@ int video_reconfig_filters(struct dec_video *d_video,
// While mp_image_params normally always have to have d_w/d_h set, the
// decoder signals unknown bitstream aspect ratio with both set to 0.
float dec_aspect = p.d_w > 0 && p.d_h > 0 ? p.d_w / (float)p.d_h : 0;
float dec_aspect = p.p_w > 0 && p.p_h > 0 ? p.p_w / (float)p.p_h : 0;
if (d_video->initial_decoder_aspect == 0)
d_video->initial_decoder_aspect = dec_aspect;
@ -363,22 +364,25 @@ int video_reconfig_filters(struct dec_video *d_video,
break;
}
if (use_container && sh->aspect > 0) {
if (use_container && sh->par_w > 0 && sh->par_h) {
MP_VERBOSE(d_video, "Using container aspect ratio.\n");
vf_set_dar(&p.d_w, &p.d_h, p.w, p.h, sh->aspect);
p.p_w = sh->par_w;
p.p_h = sh->par_h;
}
float force_aspect = opts->movie_aspect;
if (force_aspect >= 0.0) {
if (opts->movie_aspect >= 0) {
MP_VERBOSE(d_video, "Forcing user-set aspect ratio.\n");
vf_set_dar(&p.d_w, &p.d_h, p.w, p.h, force_aspect);
if (opts->movie_aspect == 0) {
p.p_w = p.p_h = 1;
} else {
AVRational a = av_d2q(opts->movie_aspect, INT_MAX);
mp_image_params_set_dsize(&p, a.num, a.den);
}
}
// Assume square pixels if no aspect ratio is set at all.
if (p.d_w <= 0 || p.d_h <= 0) {
p.d_w = p.w;
p.d_h = p.h;
}
if (p.p_w <= 0 || p.p_h <= 0)
p.p_w = p.p_h = 1;
// Detect colorspace from resolution.
mp_image_params_guess_csp(&p);

View File

@ -484,7 +484,6 @@ static void update_image_params(struct dec_video *vd, AVFrame *frame,
struct MPOpts *opts = ctx->opts;
int width = frame->width;
int height = frame->height;
float aspect = av_q2d(frame->sample_aspect_ratio) * width / height;
int pix_fmt = frame->format;
if (pix_fmt != ctx->pix_fmt) {
@ -499,8 +498,8 @@ static void update_image_params(struct dec_video *vd, AVFrame *frame,
.imgfmt = ctx->best_csp,
.w = width,
.h = height,
.d_w = 0,
.d_h = 0,
.p_w = frame->sample_aspect_ratio.num,
.p_h = frame->sample_aspect_ratio.den,
.colorspace = avcol_spc_to_mp_csp(ctx->avctx->colorspace),
.colorlevels = avcol_range_to_mp_csp_levels(ctx->avctx->color_range),
.primaries = avcol_pri_to_mp_csp_prim(ctx->avctx->color_primaries),
@ -511,9 +510,6 @@ static void update_image_params(struct dec_video *vd, AVFrame *frame,
.stereo_in = vd->header->video->stereo_mode,
};
if (aspect > 0)
vf_set_dar(&out_params->d_w, &out_params->d_h, width, height, aspect);
if (opts->video_rotate < 0) {
out_params->rotate = 0;
} else {

View File

@ -700,28 +700,3 @@ void vf_destroy(struct vf_chain *c)
vf_chain_forget_frames(c);
talloc_free(c);
}
// 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)
{
*d_width = *d_width * new_w / old_w;
*d_height = *d_height * new_h / old_h;
}
// Set *d_width/*d_height to display aspect ratio with the givem source size
void vf_set_dar(int *d_w, int *d_h, int w, int h, double dar)
{
*d_w = w;
*d_h = h;
if (dar > 0.01) {
*d_w = h * dar + 0.5;
// we don't like horizontal downscale
if (*d_w < w) {
*d_w = w;
*d_h = w / dar + 0.5;
}
}
}

View File

@ -174,10 +174,4 @@ void vf_add_output_frame(struct vf_instance *vf, struct mp_image *img);
// default wrappers:
int vf_next_query_format(struct vf_instance *vf, unsigned int fmt);
// Helpers
void vf_rescale_dsize(int *d_width, int *d_height, int old_w, int old_h,
int new_w, int new_h);
void vf_set_dar(int *d_width, int *d_height, int w, int h, double dar);
#endif /* MPLAYER_VF_H */

View File

@ -42,7 +42,7 @@ static const struct vf_priv_s {
static int reconfig(struct vf_instance *vf, struct mp_image_params *in,
struct mp_image_params *out)
{
int width = in->w, height = in->h, d_width = in->d_w, d_height = in->d_h;
int width = in->w, height = in->h;
// calculate the missing parameters:
if(vf->priv->crop_w<=0 || vf->priv->crop_w>width) vf->priv->crop_w=width;
@ -63,13 +63,9 @@ static int reconfig(struct vf_instance *vf, struct mp_image_params *in,
return -1;
}
vf_rescale_dsize(&d_width, &d_height, width, height,
vf->priv->crop_w, vf->priv->crop_h);
*out = *in;
out->w = vf->priv->crop_w;
out->h = vf->priv->crop_h;
out->d_w = d_width;
out->d_h = d_height;
return 0;
}

View File

@ -93,10 +93,11 @@ static void set_imgprop(struct vf_dlopen_picdata *out, const mp_image_t *mpi)
static int reconfig(struct vf_instance *vf, struct mp_image_params *in,
struct mp_image_params *out)
{
mp_image_params_get_dsize(in, &vf->priv->filter.in_d_width,
&vf->priv->filter.in_d_height);
vf->priv->filter.in_width = in->w;
vf->priv->filter.in_height = in->h;
vf->priv->filter.in_d_width = in->d_w;
vf->priv->filter.in_d_height = in->d_h;
vf->priv->filter.in_fmt = talloc_strdup(vf, mp_imgfmt_to_name(in->imgfmt));
vf->priv->filter.out_width = vf->priv->filter.in_width;
vf->priv->filter.out_height = vf->priv->filter.in_height;
@ -164,8 +165,8 @@ static int reconfig(struct vf_instance *vf, struct mp_image_params *in,
*out = *in;
out->w = vf->priv->out_width;
out->h = vf->priv->out_height;
out->d_w = vf->priv->filter.out_d_width;
out->d_h = vf->priv->filter.out_d_height;
mp_image_params_set_dsize(out, vf->priv->filter.out_d_width,
vf->priv->filter.out_d_height);
out->imgfmt = vf->priv->outfmt;
return 0;
}

View File

@ -39,7 +39,9 @@ struct vf_priv_s {
static int reconfig(struct vf_instance *vf, struct mp_image_params *in,
struct mp_image_params *out)
{
int width = in->w, height = in->h, d_width = in->d_w, d_height = in->d_h;
int width = in->w, height = in->h;
int d_width, d_height;
mp_image_params_get_dsize(in, &d_width, &d_height);
int w = vf->priv->w;
int h = vf->priv->h;
if (vf->priv->aspect < 0.001) { // did the user input aspect or w,h params
@ -75,8 +77,7 @@ static int reconfig(struct vf_instance *vf, struct mp_image_params *in,
}
}
*out = *in;
out->d_w = d_width;
out->d_h = d_height;
mp_image_params_set_dsize(out, d_width, d_height);
return 0;
}

View File

@ -72,7 +72,7 @@ static int reconfig(struct vf_instance *vf, struct mp_image_params *in,
else if( vf->priv->exp_h<height ) vf->priv->exp_h=height;
if (vf->priv->aspect) {
float adjusted_aspect = vf->priv->aspect;
adjusted_aspect *= ((double)width/height) / ((double)in->d_w/in->d_h);
adjusted_aspect *= (double)in->p_w/in->p_h;
if (vf->priv->exp_h < vf->priv->exp_w / adjusted_aspect) {
vf->priv->exp_h = vf->priv->exp_w / adjusted_aspect + 0.5;
} else {
@ -96,9 +96,6 @@ static int reconfig(struct vf_instance *vf, struct mp_image_params *in,
out->w = vf->priv->exp_w;
out->h = vf->priv->exp_h;
vf_rescale_dsize(&out->d_w, &out->d_h, width, height,
vf->priv->exp_w, vf->priv->exp_h);
return 0;
}

View File

@ -20,6 +20,8 @@
#include <string.h>
#include <inttypes.h>
#include <libavutil/rational.h>
#include "common/msg.h"
#include "common/common.h"
@ -100,12 +102,16 @@ static int reconfig(struct vf_instance *vf, struct mp_image_params *in,
out->stereo_out = p->stereo_out;
if (p->rotate >= 0)
out->rotate = p->rotate;
AVRational dsize;
mp_image_params_get_dsize(out, &dsize.num, &dsize.den);
if (p->dw > 0)
out->d_w = p->dw;
dsize.num = p->dw;
if (p->dh > 0)
out->d_h = p->dh;
dsize.den = p->dh;
if (p->dar > 0)
vf_set_dar(&out->d_w, &out->d_h, out->w, out->h, p->dar);
dsize = av_d2q(p->dar, INT_MAX);
mp_image_params_set_dsize(out, dsize.num, dsize.den);
// Make sure the user-overrides are consistent (no RGB csp for YUV, etc.).
mp_image_params_guess_csp(out);

View File

@ -103,30 +103,7 @@ static void destroy_graph(struct vf_instance *vf)
p->eof = false;
}
static AVRational par_from_sar_dar(int width, int height,
int d_width, int d_height)
{
return av_div_q((AVRational){d_width, d_height},
(AVRational){width, height});
}
static void dar_from_sar_par(int width, int height, AVRational par,
int *out_dw, int *out_dh)
{
*out_dw = width;
*out_dh = height;
if (par.num != 0 && par.den != 0) {
double d = av_q2d(par);
if (d > 1.0) {
*out_dw = floor(*out_dw * d + 0.5);
} else {
*out_dh = floor(*out_dh / d + 0.5);
}
}
}
static bool recreate_graph(struct vf_instance *vf, int width, int height,
int d_width, int d_height, unsigned int fmt)
static bool recreate_graph(struct vf_instance *vf, struct mp_image_params *fmt)
{
void *tmp = talloc_new(NULL);
struct vf_priv_s *p = vf->priv;
@ -168,13 +145,12 @@ static bool recreate_graph(struct vf_instance *vf, int width, int height,
char *sws_flags = talloc_asprintf(tmp, "flags=%"PRId64, p->cfg_sws_flags);
graph->scale_sws_opts = av_strdup(sws_flags);
AVRational par = par_from_sar_dar(width, height, d_width, d_height);
AVRational timebase = AV_TIME_BASE_Q;
char *src_args = talloc_asprintf(tmp, "%d:%d:%d:%d:%d:%d:%d",
width, height, imgfmt2pixfmt(fmt),
fmt->w, fmt->h, imgfmt2pixfmt(fmt->imgfmt),
timebase.num, timebase.den,
par.num, par.den);
fmt->p_w, fmt->p_h);
if (avfilter_graph_create_filter(&in, avfilter_get_by_name("buffer"),
"src", src_args, NULL, graph) < 0)
@ -225,7 +201,7 @@ static void reset(vf_instance_t *vf)
struct vf_priv_s *p = vf->priv;
struct mp_image_params *f = &vf->fmt_in;
if (p->graph && f->imgfmt)
recreate_graph(vf, f->w, f->h, f->d_w, f->d_h, f->imgfmt);
recreate_graph(vf, f);
}
static int reconfig(struct vf_instance *vf, struct mp_image_params *in,
@ -240,7 +216,7 @@ static int reconfig(struct vf_instance *vf, struct mp_image_params *in,
return -1;
}
if (!recreate_graph(vf, in->w, in->h, in->d_w, in->d_h, in->imgfmt))
if (!recreate_graph(vf, in))
return -1;
AVFilterLink *l_out = p->out->inputs[0];
@ -251,13 +227,10 @@ static int reconfig(struct vf_instance *vf, struct mp_image_params *in,
p->par_in = l_in->sample_aspect_ratio;
int dw, dh;
dar_from_sar_par(l_out->w, l_out->h, l_out->sample_aspect_ratio, &dw, &dh);
out->w = l_out->w;
out->h = l_out->h;
out->d_w = dw;
out->d_h = dh;
out->p_w = l_out->sample_aspect_ratio.num;
out->p_h = l_out->sample_aspect_ratio.den;
out->imgfmt = pixfmt2imgfmt(l_out->format);
return 0;
}

View File

@ -76,7 +76,10 @@ static int find_best_out(vf_instance_t *vf, int in_format)
static int reconfig(struct vf_instance *vf, struct mp_image_params *in,
struct mp_image_params *out)
{
int width = in->w, height = in->h, d_width = in->d_w, d_height = in->d_h;
int width = in->w, height = in->h;
int d_width, d_height;
mp_image_params_get_dsize(in, &d_width, &d_height);
unsigned int best = find_best_out(vf, in->imgfmt);
int round_w = 0, round_h = 0;
@ -154,8 +157,7 @@ static int reconfig(struct vf_instance *vf, struct mp_image_params *in,
*out = *in;
out->w = vf->priv->w;
out->h = vf->priv->h;
out->d_w = d_width;
out->d_h = d_height;
mp_image_params_set_dsize(out, d_width, d_height);
out->imgfmt = best;
// Second-guess what libswscale is going to output and what not.

View File

@ -52,31 +52,23 @@ struct vf_priv_s {
static int reconfig(struct vf_instance *vf, struct mp_image_params *in,
struct mp_image_params *out)
{
int width = in->w, height = in->h, d_width = in->d_w, d_height = in->d_h;
int width = in->w, height = in->h;
vf->priv->outh = height + vf->priv->opt_top_margin +
vf->priv->opt_bottom_margin;
vf->priv->outw = width;
double dar = (double)d_width / d_height;
double sar = (double)width / height;
vf_rescale_dsize(&d_width, &d_height, width, height,
vf->priv->outw, vf->priv->outh);
vf->priv->dim = (struct mp_osd_res) {
.w = vf->priv->outw,
.h = vf->priv->outh,
.mt = vf->priv->opt_top_margin,
.mb = vf->priv->opt_bottom_margin,
.display_par = sar / dar,
.display_par = in->p_w / (double)in->p_h,
};
*out = *in;
out->w = vf->priv->outw;
out->h = vf->priv->outh;
out->d_w = d_width;
out->d_h = d_height;
return 0;
}

View File

@ -651,8 +651,6 @@ error:
static int reconfig(struct vf_instance *vf, struct mp_image_params *in,
struct mp_image_params *out)
{
int width = in->w, height = in->h, d_width = in->d_w, d_height = in->d_h;
struct vf_priv_s *p = vf->priv;
p->fmt_in = *in;
@ -669,18 +667,15 @@ static int reconfig(struct vf_instance *vf, struct mp_image_params *in,
}
struct mp_imgfmt_desc desc = mp_imgfmt_get_desc(in->imgfmt);
if (width % desc.align_x || height % desc.align_y) {
if (in->w % desc.align_x || in->h % desc.align_y) {
MP_FATAL(vf, "VapourSynth does not allow unaligned/cropped video sizes.\n");
destroy_vs(vf);
return -1;
}
vf_rescale_dsize(&d_width, &d_height, width, height, vi->width, vi->height);
*out = *in;
out->w = vi->width;
out->h = vi->height;
out->d_w = d_width;
out->d_h = d_height;
return 0;
}

View File

@ -291,8 +291,8 @@ const char *image_writer_file_ext(const struct image_writer_opts *opts)
struct mp_image *convert_image(struct mp_image *image, int destfmt,
struct mp_log *log)
{
int d_w = image->params.d_w;
int d_h = image->params.d_h;
int d_w, d_h;
mp_image_params_get_dsize(&image->params, &d_w, &d_h);
bool is_anamorphic = image->w != d_w || image->h != d_h;
// Caveat: no colorspace/levels conversion done if pixel formats equal

View File

@ -27,6 +27,7 @@
#include <libavutil/mem.h>
#include <libavutil/common.h>
#include <libavutil/bswap.h>
#include <libavutil/rational.h>
#include <libavcodec/avcodec.h>
#include "talloc.h"
@ -116,8 +117,9 @@ int mp_image_plane_h(struct mp_image *mpi, int plane)
void mp_image_set_size(struct mp_image *mpi, int w, int h)
{
assert(w >= 0 && h >= 0);
mpi->w = mpi->params.w = mpi->params.d_w = w;
mpi->h = mpi->params.h = mpi->params.d_h = h;
mpi->w = mpi->params.w = w;
mpi->h = mpi->params.h = h;
mpi->params.p_w = mpi->params.p_h = 1;
}
void mp_image_set_params(struct mp_image *image,
@ -385,8 +387,8 @@ void mp_image_copy_attributes(struct mp_image *dst, struct mp_image *src)
dst->params.stereo_in = src->params.stereo_in;
dst->params.stereo_out = src->params.stereo_out;
if (dst->w == src->w && dst->h == src->h) {
dst->params.d_w = src->params.d_w;
dst->params.d_h = src->params.d_h;
dst->params.p_w = src->params.p_w;
dst->params.p_h = src->params.p_h;
}
dst->params.primaries = src->params.primaries;
dst->params.gamma = src->params.gamma;
@ -477,13 +479,32 @@ void mp_image_vflip(struct mp_image *img)
}
}
// Display size derived from image size and pixel aspect ratio.
void mp_image_params_get_dsize(const struct mp_image_params *p,
int *d_w, int *d_h)
{
*d_w = p->w;
*d_h = p->h;
if (p->p_w > p->p_h && p->p_h >= 1)
*d_w = MPCLAMP(*d_w * (int64_t)p->p_w / p->p_h, 0, INT_MAX);
if (p->p_h > p->p_w && p->p_w >= 1)
*d_h = MPCLAMP(*d_h * (int64_t)p->p_h / p->p_w, 0, INT_MAX);
}
void mp_image_params_set_dsize(struct mp_image_params *p, int d_w, int d_h)
{
AVRational ds = av_div_q((AVRational){d_w, d_h}, (AVRational){p->w, p->h});
p->p_w = ds.num;
p->p_h = ds.den;
}
char *mp_image_params_to_str_buf(char *b, size_t bs,
const struct mp_image_params *p)
{
if (p && p->imgfmt) {
snprintf(b, bs, "%dx%d", p->w, p->h);
if (p->w != p->d_w || p->h != p->d_h)
mp_snprintf_cat(b, bs, "->%dx%d", p->d_w, p->d_h);
if (p->p_w != p->p_h || !p->p_w)
mp_snprintf_cat(b, bs, " [%d:%d]", p->p_w, p->p_h);
mp_snprintf_cat(b, bs, " %s", mp_imgfmt_to_name(p->imgfmt));
mp_snprintf_cat(b, bs, " %s/%s",
m_opt_choice_str(mp_csp_names, p->colorspace),
@ -515,7 +536,7 @@ bool mp_image_params_valid(const struct mp_image_params *p)
if (p->w <= 0 || p->h <= 0 || (p->w + 128LL) * (p->h + 128LL) >= INT_MAX / 8)
return false;
if (p->d_w <= 0 || p->d_h <= 0)
if (p->p_w <= 0 || p->p_h <= 0)
return false;
if (p->rotate < 0 || p->rotate >= 360)
@ -533,7 +554,7 @@ bool mp_image_params_equal(const struct mp_image_params *p1,
{
return p1->imgfmt == p2->imgfmt &&
p1->w == p2->w && p1->h == p2->h &&
p1->d_w == p2->d_w && p1->d_h == p2->d_h &&
p1->p_w == p2->p_w && p1->p_h == p2->p_h &&
p1->colorspace == p2->colorspace &&
p1->colorlevels == p2->colorlevels &&
p1->primaries == p2->primaries &&
@ -555,12 +576,6 @@ void mp_image_set_attributes(struct mp_image *image,
nparams.h = image->h;
if (nparams.imgfmt != params->imgfmt)
mp_image_params_guess_csp(&nparams);
if (nparams.w != params->w || nparams.h != params->h) {
if (nparams.d_w && nparams.d_h) {
vf_rescale_dsize(&nparams.d_w, &nparams.d_h,
params->w, params->h, nparams.w, nparams.h);
}
}
mp_image_set_params(image, &nparams);
}

View File

@ -40,7 +40,7 @@
struct mp_image_params {
enum mp_imgfmt imgfmt; // pixel format
int w, h; // image dimensions
int d_w, d_h; // define display aspect ratio (never 0/0)
int p_w, p_h; // define pixel aspect ratio (never 0/0)
enum mp_csp colorspace;
enum mp_csp_levels colorlevels;
enum mp_csp_prim primaries;
@ -137,6 +137,10 @@ bool mp_image_params_valid(const struct mp_image_params *p);
bool mp_image_params_equal(const struct mp_image_params *p1,
const struct mp_image_params *p2);
void mp_image_params_get_dsize(const struct mp_image_params *p,
int *d_w, int *d_h);
void mp_image_params_set_dsize(struct mp_image_params *p, int d_w, int d_h);
void mp_image_set_params(struct mp_image *image,
const struct mp_image_params *params);

View File

@ -135,8 +135,8 @@ void mp_get_src_dst_rects(struct mp_log *log, struct mp_vo_opts *opts,
{
int src_w = video->w;
int src_h = video->h;
int src_dw = video->d_w;
int src_dh = video->d_h;
int src_dw, src_dh;
mp_image_params_get_dsize(video, &src_dw, &src_dh);
if (video->rotate % 180 == 90 && (vo_caps & VO_CAP_ROTATE90)) {
MPSWAP(int, src_w, src_h);
MPSWAP(int, src_dw, src_dh);
@ -174,8 +174,8 @@ void mp_get_src_dst_rects(struct mp_log *log, struct mp_vo_opts *opts,
mp_verbose(log, "Window size: %dx%d\n",
window_w, window_h);
mp_verbose(log, "Video source: %dx%d (%dx%d)\n",
video->w, video->h, video->d_w, video->d_h);
mp_verbose(log, "Video source: %dx%d (%d:%d)\n",
video->w, video->h, video->p_w, video->p_h);
mp_verbose(log, "Video display: (%d, %d) %dx%d -> (%d, %d) %dx%d\n",
src.x0, src.y0, sw, sh, dst.x0, dst.y0, dw, dh);
mp_verbose(log, "Video scale: %f/%f\n",

View File

@ -508,8 +508,7 @@ static void run_reconfig(void *p)
struct vo_internal *in = vo->in;
vo->dwidth = params->d_w;
vo->dheight = params->d_h;
mp_image_params_get_dsize(params, &vo->dwidth, &vo->dheight);
talloc_free(vo->params);
vo->params = talloc_memdup(vo, params, sizeof(*params));

View File

@ -305,8 +305,8 @@ static int reconfig(struct vo *vo, struct mp_image_params *params)
.imgfmt = IMGFMT,
.w = w,
.h = h,
.d_w = w,
.d_h = h,
.p_w = 1,
.p_h = 1,
};
talloc_free(p->cur_frame);

View File

@ -93,8 +93,7 @@ static int reconfig(struct vo *vo, struct mp_image_params *params)
{
struct priv *vc = vo->priv;
enum AVPixelFormat pix_fmt = imgfmt2pixfmt(params->imgfmt);
AVRational display_aspect_ratio, image_aspect_ratio;
AVRational aspect;
AVRational aspect = {params->p_w, params->p_h};
uint32_t width = params->w;
uint32_t height = params->h;
@ -103,12 +102,6 @@ static int reconfig(struct vo *vo, struct mp_image_params *params)
pthread_mutex_lock(&vo->encode_lavc_ctx->lock);
display_aspect_ratio.num = params->d_w;
display_aspect_ratio.den = params->d_h;
image_aspect_ratio.num = width;
image_aspect_ratio.den = height;
aspect = av_div_q(display_aspect_ratio, image_aspect_ratio);
if (vc->stream) {
/* NOTE:
* in debug builds we get a "comparison between signed and unsigned"

View File

@ -299,8 +299,8 @@ static bool resize(struct priv *p)
.imgfmt = p->video_format->mp_format,
.w = p->dst_w,
.h = p->dst_h,
.d_w = p->dst_w,
.d_h = p->dst_h,
.p_w = 1,
.p_h = 1,
};
mp_image_params_guess_csp(&p->sws->dst);

View File

@ -259,8 +259,8 @@ static bool resize(struct vo *vo)
.imgfmt = fmte->mpfmt,
.w = p->dst_w,
.h = p->dst_h,
.d_w = p->dst_w,
.d_h = p->dst_h,
.p_w = 1,
.p_h = 1,
};
mp_image_params_guess_csp(&p->sws->dst);

View File

@ -82,12 +82,12 @@ void vo_calc_window_geometry(struct vo *vo, const struct mp_rect *screen,
// The case of calling this function even though no video was configured
// yet (i.e. vo->params==NULL) happens when vo_opengl creates a hidden
// window in order to create an OpenGL context.
struct mp_image_params params = { .d_w = 320, .d_h = 200 };
struct mp_image_params params = { .w = 320, .h = 200 };
if (vo->params)
params = *vo->params;
int d_w = params.d_w;
int d_h = params.d_h;
int d_w, d_h;
mp_image_params_get_dsize(&params, &d_w, &d_h);
if ((vo->driver->caps & VO_CAP_ROTATE90) && params.rotate % 180 == 90)
MPSWAP(int, d_w, d_h);
d_w = MPCLAMP(d_w * opts->window_scale, 1, 16000);

View File

@ -159,8 +159,8 @@ int mp_sws_reinit(struct mp_sws_context *ctx)
struct mp_image_params *dst = &ctx->dst;
// Neutralize unsupported or ignored parameters.
src->d_w = dst->d_w = 0;
src->d_h = dst->d_h = 0;
src->p_w = dst->p_w = 0;
src->p_h = dst->p_h = 0;
if (cache_valid(ctx))
return 0;

View File

@ -37,8 +37,8 @@ static struct mp_image *download_image(struct mp_hwdec_ctx *hwctx,
VdpStatus vdp_st;
struct mp_image *res = NULL;
int w = mpi->params.d_w;
int h = mpi->params.d_h;
int w, h;
mp_image_params_get_dsize(&mpi->params, &w, &h);
// Abuse this lock for our own purposes. It could use its own lock instead.
pthread_mutex_lock(&ctx->pool_lock);