From 82f0d373fbecc18cd2ddc748f0b330160845f2cd Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 30 Aug 2015 23:01:46 +0200 Subject: [PATCH] video: make container vs. bitstream aspect ratio configurable Utterly idiotic bullshit. Fixes #2259. --- DOCS/interface-changes.rst | 1 + DOCS/man/options.rst | 17 ++++++++++++++ common/av_common.c | 1 - options/options.c | 2 ++ options/options.h | 1 + video/decode/dec_video.c | 45 ++++++++++++++++++++++++++++---------- video/decode/vd_lavc.c | 10 ++++----- 7 files changed, 59 insertions(+), 18 deletions(-) diff --git a/DOCS/interface-changes.rst b/DOCS/interface-changes.rst index 9d1390c808..2d103ebfb3 100644 --- a/DOCS/interface-changes.rst +++ b/DOCS/interface-changes.rst @@ -20,6 +20,7 @@ Interface changes :: --- mpv 0.10.0 will be released --- + - add --video-aspect-method option - add --playlist-pos option - add --video-sync* options "display-sync-active" property diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst index c8b2460879..f1d045622a 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -633,6 +633,23 @@ Video Ignore aspect ratio information from video file and assume the video has square pixels. See also ``--video-aspect``. +``--video-aspect-method=`` + This sets the default video aspect determination method (if the aspect is + _not_ overridden by the user with ``--video-aspect`` or others). + + :hybrid: Prefer the container aspect ratio. If the bitstream aspect + switches mid-stream, switch to preferring the bitstream aspect. + This is the default behavior in mpv and mplayer2. + :container: Strictly prefer the container aspect ratio. This is apparently + the default behavior with VLC, at least with Matroska. + :bitstream: Strictly prefer the bitstream aspect ratio, unless the bitstream + aspect ratio is not set. This is apparently the default behavior + with XBMC/kodi, at least with Matroska. + + Normally you should not set this. Try the ``container`` and ``bitstream`` + choices if you encounter video that has the wrong aspect ratio in mpv, + but seems to be correct in other players. + ``--video-unscaled`` Disable scaling of the video. If the window is larger than the video, black bars are added. Otherwise, the video is cropped. The video still diff --git a/common/av_common.c b/common/av_common.c index 3611abe8f6..87616b9879 100644 --- a/common/av_common.c +++ b/common/av_common.c @@ -59,7 +59,6 @@ void mp_copy_lav_codec_headers(AVCodecContext *avctx, AVCodecContext *st) avctx->width = st->width; avctx->height = st->height; avctx->pix_fmt = st->pix_fmt; - avctx->sample_aspect_ratio = st->sample_aspect_ratio; avctx->chroma_sample_location = st->chroma_sample_location; avctx->sample_rate = st->sample_rate; avctx->channels = st->channels; diff --git a/options/options.c b/options/options.c index 2a62ef69c8..71aea336b1 100644 --- a/options/options.c +++ b/options/options.c @@ -312,6 +312,8 @@ const m_option_t mp_opts[] = { // 0 means square pixels OPT_FLOATRANGE("video-aspect", movie_aspect, 0, -1.0, 10.0), OPT_FLOAT_STORE("no-video-aspect", movie_aspect, 0, 0.0), + OPT_CHOICE("video-aspect-method", aspect_method, 0, + ({"hybrid", 0}, {"bitstream", 1}, {"container", 2})), OPT_CHOICE("field-dominance", field_dominance, 0, ({"auto", -1}, {"top", 0}, {"bottom", 1})), diff --git a/options/options.h b/options/options.h index b3d6bb18c2..5cf144a045 100644 --- a/options/options.h +++ b/options/options.h @@ -227,6 +227,7 @@ typedef struct MPOpts { struct m_obj_settings *af_settings, *af_defs; int deinterlace; float movie_aspect; + int aspect_method; int field_dominance; char **sub_name; char **sub_paths; diff --git a/video/decode/dec_video.c b/video/decode/dec_video.c index 09da72579d..34b437aa52 100644 --- a/video/decode/dec_video.c +++ b/video/decode/dec_video.c @@ -386,24 +386,45 @@ int video_reconfig_filters(struct dec_video *d_video, struct mp_image_params p = *params; struct sh_video *sh = d_video->header->video; - float decoder_aspect = p.d_w / (float)p.d_h; + // 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; if (d_video->initial_decoder_aspect == 0) - d_video->initial_decoder_aspect = decoder_aspect; + d_video->initial_decoder_aspect = dec_aspect; - // We normally prefer the container aspect, unless the decoder aspect - // changes at least once. - if (d_video->initial_decoder_aspect == decoder_aspect) { - if (sh->aspect > 0) - vf_set_dar(&p.d_w, &p.d_h, p.w, p.h, sh->aspect); - } else { - MP_VERBOSE(d_video, "Using bitstream aspect ratio.\n"); - // Even if the aspect switches back, don't use container aspect again. - d_video->initial_decoder_aspect = -1; + bool use_container = true; + switch (opts->aspect_method) { + case 0: + // We normally prefer the container aspect, unless the decoder aspect + // changes at least once. + if (dec_aspect > 0 && d_video->initial_decoder_aspect != dec_aspect) { + MP_VERBOSE(d_video, "Using bitstream aspect ratio.\n"); + // Even if the aspect switches back, don't use container aspect again. + d_video->initial_decoder_aspect = -1; + use_container = false; + } + break; + case 1: + use_container = false; + break; + } + + if (use_container && sh->aspect > 0) { + MP_VERBOSE(d_video, "Using container aspect ratio.\n"); + vf_set_dar(&p.d_w, &p.d_h, p.w, p.h, sh->aspect); } float force_aspect = opts->movie_aspect; - if (force_aspect >= 0.0) + if (force_aspect >= 0.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); + } + + // 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; + } // Detect colorspace from resolution. mp_image_params_guess_csp(&p); diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c index bc038255b7..3ba797bd0c 100644 --- a/video/decode/vd_lavc.c +++ b/video/decode/vd_lavc.c @@ -476,15 +476,12 @@ static void update_image_params(struct dec_video *vd, AVFrame *frame, av_get_pix_fmt_name(pix_fmt)); } - int d_w, d_h; - vf_set_dar(&d_w, &d_h, width, height, aspect); - *out_params = (struct mp_image_params) { .imgfmt = ctx->best_csp, .w = width, .h = height, - .d_w = d_w, - .d_h = d_h, + .d_w = 0, + .d_h = 0, .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), @@ -495,6 +492,9 @@ 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 {