diff --git a/player/command.c b/player/command.c index 0bee671e88..f2f73059ef 100644 --- a/player/command.c +++ b/player/command.c @@ -2512,8 +2512,8 @@ static int mp_property_vd_imgparams(void *ctx, struct m_property *prop, if (!vd) return M_PROPERTY_UNAVAILABLE; struct mp_codec_params *c = vd->header->codec; - if (vd->vfilter->override_params.imgfmt) { - return property_imgparams(vd->vfilter->override_params, action, arg); + if (vd->vfilter->input_params.imgfmt) { + return property_imgparams(vd->vfilter->input_params, action, arg); } else if (c->disp_w && c->disp_h) { // Simplistic fallback for stupid scripts querying "width"/"height" // before the first frame is decoded. @@ -2779,7 +2779,7 @@ static int mp_property_aspect(void *ctx, struct m_property *prop, if (mpctx->d_video && aspect <= 0) { struct dec_video *d_video = mpctx->d_video; struct mp_codec_params *c = d_video->header->codec; - struct mp_image_params *params = &d_video->vfilter->override_params; + struct mp_image_params *params = &d_video->vfilter->input_params; 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); diff --git a/player/sub.c b/player/sub.c index 0492be4bc8..c20df53c60 100644 --- a/player/sub.c +++ b/player/sub.c @@ -78,7 +78,7 @@ static bool update_subtitle(struct MPContext *mpctx, double video_pts, int order return true; if (mpctx->d_video) { - struct mp_image_params params = mpctx->d_video->vfilter->override_params; + struct mp_image_params params = mpctx->d_video->vfilter->input_params; if (params.imgfmt) sub_control(dec_sub, SD_CTRL_SET_VIDEO_PARAMS, ¶ms); } diff --git a/player/video.c b/player/video.c index 33f3b4b970..9ec7eacb74 100644 --- a/player/video.c +++ b/player/video.c @@ -84,10 +84,10 @@ static int try_filter(struct MPContext *mpctx, struct mp_image_params params, vf->label = talloc_strdup(vf, label); - if (video_reconfig_filters(d_video, ¶ms) < 0) { + if (vf_reconfig(d_video->vfilter, ¶ms) < 0) { vf_remove_filter(d_video->vfilter, vf); // restore - video_reconfig_filters(d_video, ¶ms); + vf_reconfig(d_video->vfilter, ¶ms); return -1; } return 0; @@ -107,7 +107,7 @@ static void filter_reconfig(struct MPContext *mpctx, set_allowed_vo_formats(d_video->vfilter, mpctx->video_out); - if (video_reconfig_filters(d_video, ¶ms) < 0) { + if (vf_reconfig(d_video->vfilter, ¶ms) < 0) { // Most video filters don't work with hardware decoding, so this // might be the reason why filter reconfig failed. if (!probe_only && @@ -119,6 +119,8 @@ static void filter_reconfig(struct MPContext *mpctx, mp_image_unrefp(&d_video->waiting_decoded_mpi); d_video->decoder_output = (struct mp_image_params){0}; MP_VERBOSE(mpctx, "hwdec falback due to filters.\n"); + } else { + MP_FATAL(mpctx, "Cannot initialize video filters.\n"); } return; } diff --git a/video/decode/dec_video.c b/video/decode/dec_video.c index 821aa2bda4..772bab2f16 100644 --- a/video/decode/dec_video.c +++ b/video/decode/dec_video.c @@ -68,6 +68,7 @@ void video_reset_decoding(struct dec_video *d_video) d_video->decoded_pts = MP_NOPTS_VALUE; d_video->codec_pts = MP_NOPTS_VALUE; d_video->codec_dts = MP_NOPTS_VALUE; + d_video->last_format = d_video->fixed_format = (struct mp_image_params){0}; } int video_vd_control(struct dec_video *d_video, int cmd, void *arg) @@ -209,6 +210,65 @@ bool video_init_best_codec(struct dec_video *d_video, char* video_decoders) return !!d_video->vd_driver; } +static void fix_image_params(struct dec_video *d_video, + struct mp_image_params *params) +{ + struct MPOpts *opts = d_video->opts; + struct mp_image_params p = *params; + struct mp_codec_params *c = d_video->header->codec; + + MP_VERBOSE(d_video, "Decoder format: %s\n", mp_image_params_to_str(params)); + + // 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.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; + + 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 && c->par_w > 0 && c->par_h) { + MP_VERBOSE(d_video, "Using container aspect ratio.\n"); + p.p_w = c->par_w; + p.p_h = c->par_h; + } + + if (opts->movie_aspect >= 0) { + MP_VERBOSE(d_video, "Forcing user-set aspect ratio.\n"); + 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.p_w <= 0 || p.p_h <= 0) + p.p_w = p.p_h = 1; + + // Detect colorspace from resolution. + mp_image_params_guess_csp(&p); + + d_video->last_format = *params; + d_video->fixed_format = p; +} + static void add_avi_pts(struct dec_video *d_video, double pts) { if (pts != MP_NOPTS_VALUE) { @@ -329,72 +389,16 @@ struct mp_image *video_decode(struct dec_video *d_video, if (d_video->num_codec_pts_problems || pkt_pts == MP_NOPTS_VALUE) d_video->has_broken_packet_pts = 1; + if (!mp_image_params_equal(&d_video->last_format, &mpi->params)) + fix_image_params(d_video, &mpi->params); + + mpi->params = d_video->fixed_format; + mpi->pts = pts; d_video->decoded_pts = pts; return mpi; } -int video_reconfig_filters(struct dec_video *d_video, - const struct mp_image_params *params) -{ - struct MPOpts *opts = d_video->opts; - struct mp_image_params p = *params; - struct mp_codec_params *c = d_video->header->codec; - - // 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.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; - - 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 && c->par_w > 0 && c->par_h) { - MP_VERBOSE(d_video, "Using container aspect ratio.\n"); - p.p_w = c->par_w; - p.p_h = c->par_h; - } - - if (opts->movie_aspect >= 0) { - MP_VERBOSE(d_video, "Forcing user-set aspect ratio.\n"); - 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.p_w <= 0 || p.p_h <= 0) - p.p_w = p.p_h = 1; - - // Detect colorspace from resolution. - mp_image_params_guess_csp(&p); - - if (vf_reconfig(d_video->vfilter, params, &p) < 0) { - MP_FATAL(d_video, "Cannot initialize video filters.\n"); - return -1; - } - - return 0; -} - // Send a VCTRL, or if it doesn't work, translate it to a VOCTRL and try the VO. int video_vf_vo_control(struct dec_video *d_video, int vf_cmd, void *data) { diff --git a/video/decode/dec_video.h b/video/decode/dec_video.h index ad33d784f6..fe325806c6 100644 --- a/video/decode/dec_video.h +++ b/video/decode/dec_video.h @@ -69,6 +69,8 @@ struct dec_video { double decoded_pts; float fps; // FPS from demuxer or from user override + + struct mp_image_params last_format, fixed_format; float initial_decoder_aspect; // State used only by player/video.c @@ -90,9 +92,6 @@ int video_set_colors(struct dec_video *d_video, const char *item, int value); void video_reset_decoding(struct dec_video *d_video); int video_vd_control(struct dec_video *d_video, int cmd, void *arg); -int video_reconfig_filters(struct dec_video *d_video, - const struct mp_image_params *params); - int video_vf_vo_control(struct dec_video *d_video, int vf_cmd, void *data); #endif /* MPLAYER_DEC_VIDEO_H */ diff --git a/video/filter/vf.c b/video/filter/vf.c index dd5b560df3..35de0f23a7 100644 --- a/video/filter/vf.c +++ b/video/filter/vf.c @@ -211,13 +211,8 @@ void vf_print_filter_chain(struct vf_chain *c, int msglevel, if (!mp_msg_test(c->log, msglevel)) return; - char b[128] = {0}; - - mp_snprintf_cat(b, sizeof(b), "%s", mp_image_params_to_str(&c->input_params)); - mp_msg(c->log, msglevel, " [vd] %s\n", b); - for (vf_instance_t *f = c->first; f; f = f->next) { - b[0] = '\0'; + char b[128] = {0}; mp_snprintf_cat(b, sizeof(b), " [%s] ", f->info->name); mp_snprintf_cat(b, sizeof(b), "%s", mp_image_params_to_str(&f->fmt_out)); if (f->autoinserted) @@ -392,7 +387,6 @@ int vf_filter_frame(struct vf_chain *c, struct mp_image *img) return -1; } assert(mp_image_params_equal(&img->params, &c->input_params)); - vf_fix_img_params(img, &c->override_params); return vf_do_filter(c->first, img); } @@ -585,10 +579,7 @@ static int vf_reconfig_wrapper(struct vf_instance *vf, return r; } -// override_params is used to forcibly change the parameters of input images, -// while params has to match the input images exactly. -int vf_reconfig(struct vf_chain *c, const struct mp_image_params *params, - const struct mp_image_params *override_params) +int vf_reconfig(struct vf_chain *c, const struct mp_image_params *params) { int r = 0; vf_seek_reset(c); @@ -599,9 +590,8 @@ int vf_reconfig(struct vf_chain *c, const struct mp_image_params *params, vf = next; } c->input_params = *params; - c->first->fmt_in = *override_params; - c->override_params = *override_params; - struct mp_image_params cur = c->override_params; + c->first->fmt_in = *params; + struct mp_image_params cur = *params; uint8_t unused[IMGFMT_END - IMGFMT_START]; update_formats(c, c->first, unused); @@ -621,10 +611,8 @@ int vf_reconfig(struct vf_chain *c, const struct mp_image_params *params, MP_ERR(c, "Image formats incompatible or invalid.\n"); mp_msg(c->log, loglevel, "Video filter chain:\n"); vf_print_filter_chain(c, loglevel, failing); - if (r < 0) { - c->input_params = c->override_params = c->output_params = - (struct mp_image_params){0}; - } + if (r < 0) + c->input_params = c->output_params = (struct mp_image_params){0}; return r; } diff --git a/video/filter/vf.h b/video/filter/vf.h index 2e253b88e3..f828d4e735 100644 --- a/video/filter/vf.h +++ b/video/filter/vf.h @@ -111,7 +111,6 @@ struct vf_chain { struct vf_instance *first, *last; struct mp_image_params input_params; - struct mp_image_params override_params; // input to first filter struct mp_image_params output_params; uint8_t allowed_output_formats[IMGFMT_END - IMGFMT_START]; @@ -149,8 +148,7 @@ enum vf_ctrl { struct vf_chain *vf_new(struct mpv_global *global); void vf_destroy(struct vf_chain *c); -int vf_reconfig(struct vf_chain *c, const struct mp_image_params *params, - const struct mp_image_params *override_params); +int vf_reconfig(struct vf_chain *c, const struct mp_image_params *params); int vf_control_any(struct vf_chain *c, int cmd, void *arg); int vf_control_by_label(struct vf_chain *c, int cmd, void *arg, bstr label); int vf_filter_frame(struct vf_chain *c, struct mp_image *img);