mirror of https://github.com/mpv-player/mpv
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:
parent
1f7c099dc0
commit
0a0bb9059f
|
@ -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:
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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(¶ms, &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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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(¶ms, &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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue