diff options
-rw-r--r-- | core/command.c | 145 | ||||
-rw-r--r-- | core/mplayer.c | 1 | ||||
-rw-r--r-- | video/decode/dec_video.c | 51 | ||||
-rw-r--r-- | video/decode/dec_video.h | 2 | ||||
-rw-r--r-- | video/decode/vd.c | 10 | ||||
-rw-r--r-- | video/filter/vf.c | 17 | ||||
-rw-r--r-- | video/filter/vf_scale.c | 69 | ||||
-rw-r--r-- | video/filter/vf_sub.c | 12 | ||||
-rw-r--r-- | video/mp_image.c | 2 | ||||
-rw-r--r-- | video/out/vo.c | 9 |
10 files changed, 150 insertions, 168 deletions
diff --git a/core/command.c b/core/command.c index af5e24d494..a5504438de 100644 --- a/core/command.c +++ b/core/command.c @@ -1093,13 +1093,16 @@ static int mp_property_deinterlace(m_option_t *prop, int action, return M_PROPERTY_NOT_IMPLEMENTED; } -static int colormatrix_property_helper(m_option_t *prop, int action, - void *arg, MPContext *mpctx) +// Generic option + requires hard refresh to make changes take effect. +static int video_refresh_property_helper(m_option_t *prop, int action, + void *arg, MPContext *mpctx) { int r = mp_property_generic_option(prop, action, arg, mpctx); if (action == M_PROPERTY_SET) { - if (mpctx->sh_video) - set_video_colorspace(mpctx->sh_video); + if (mpctx->sh_video) { + reinit_video_filters(mpctx); + mp_force_video_refresh(mpctx); + } } return r; } @@ -1108,88 +1111,98 @@ static int mp_property_colormatrix(m_option_t *prop, int action, void *arg, MPContext *mpctx) { if (action != M_PROPERTY_PRINT) - return colormatrix_property_helper(prop, action, arg, mpctx); + return video_refresh_property_helper(prop, action, arg, mpctx); struct MPOpts *opts = &mpctx->opts; - struct mp_csp_details actual = { .format = -1 }; - char *req_csp = mp_csp_names[opts->requested_colorspace]; - char *real_csp = NULL; - if (mpctx->sh_video) { - struct vf_instance *vf = mpctx->sh_video->vfilter; - if (vf->control(vf, VFCTRL_GET_YUV_COLORSPACE, &actual) == true) { - real_csp = mp_csp_names[actual.format]; - } else { - real_csp = "Unknown"; - } + + struct mp_csp_details vo_csp = {0}; + if (mpctx->sh_video && mpctx->sh_video->vfilter) + vf_control(mpctx->sh_video->vfilter, VFCTRL_GET_YUV_COLORSPACE, &vo_csp); + + struct mp_image_params vd_csp = {0}; + if (mpctx->sh_video) + vd_control(mpctx->sh_video, VDCTRL_GET_PARAMS, &vd_csp); + + char *res = talloc_asprintf(NULL, "%s", + mp_csp_names[opts->requested_colorspace]); + if (!vo_csp.format) { + res = talloc_asprintf_append(res, " (VO: unknown)"); + } else if (vo_csp.format != opts->requested_colorspace) { + res = talloc_asprintf_append(res, " (VO: %s)", + mp_csp_names[vo_csp.format]); + } + if (!vd_csp.colorspace) { + res = talloc_asprintf_append(res, " (VD: unknown)"); + } else if (!vo_csp.format || vd_csp.colorspace != vo_csp.format) { + res = talloc_asprintf_append(res, " (VD: %s)", + mp_csp_names[vd_csp.colorspace]); } - char *res; - if (opts->requested_colorspace == MP_CSP_AUTO && real_csp) { - // Caveat: doesn't handle the case when the autodetected colorspace - // is different from the actual colorspace as used by the - // VO - the OSD will display the VO colorspace without - // indication that it doesn't match the requested colorspace. - res = talloc_asprintf(NULL, "Auto (%s)", real_csp); - } else if (opts->requested_colorspace == actual.format || !real_csp) { - res = talloc_strdup(NULL, req_csp); - } else - res = talloc_asprintf(NULL, mp_gtext("%s, but %s used"), - req_csp, real_csp); *(char **)arg = res; return M_PROPERTY_OK; } -static int levels_property_helper(int offset, m_option_t *prop, int action, - void *arg, MPContext *mpctx) +static int mp_property_colormatrix_input_range(m_option_t *prop, int action, + void *arg, MPContext *mpctx) { if (action != M_PROPERTY_PRINT) - return colormatrix_property_helper(prop, action, arg, mpctx); + return video_refresh_property_helper(prop, action, arg, mpctx); - struct m_option opt = {0}; - mp_property_generic_option(prop, M_PROPERTY_GET_TYPE, &opt, mpctx); - assert(opt.type); + struct MPOpts *opts = &mpctx->opts; - int requested = 0; - mp_property_generic_option(prop, M_PROPERTY_GET, &requested, mpctx); + struct mp_csp_details vo_csp = {0}; + if (mpctx->sh_video && mpctx->sh_video->vfilter) + vf_control(mpctx->sh_video->vfilter, VFCTRL_GET_YUV_COLORSPACE, &vo_csp ); - struct mp_csp_details actual = {0}; - int actual_level = -1; - char *req_level = m_option_print(&opt, &requested); - char *real_level = NULL; - if (mpctx->sh_video) { - struct vf_instance *vf = mpctx->sh_video->vfilter; - if (vf->control(vf, VFCTRL_GET_YUV_COLORSPACE, &actual) == true) { - actual_level = *(enum mp_csp_levels *)(((char *)&actual) + offset); - real_level = m_option_print(&opt, &actual_level); - } else { - real_level = talloc_strdup(NULL, "Unknown"); - } + struct mp_image_params vd_csp = {0}; + if (mpctx->sh_video) + vd_control(mpctx->sh_video, VDCTRL_GET_PARAMS, &vd_csp); + + char *res = talloc_asprintf(NULL, "%s", + mp_csp_levels_names[opts->requested_input_range]); + if (!vo_csp.levels_in) { + res = talloc_asprintf_append(res, " (VO: unknown)"); + } else if (vo_csp.levels_in != opts->requested_input_range) { + res = talloc_asprintf_append(res, " (VO: %s)", + mp_csp_levels_names[vo_csp.levels_in]); + } + if (!vd_csp.colorlevels) { + res = talloc_asprintf_append(res, " (VD: unknown)"); + } else if (!vo_csp.levels_in || vd_csp.colorlevels != vo_csp.levels_in) { + res = talloc_asprintf_append(res, " (VD: %s)", + mp_csp_levels_names[vd_csp.colorlevels]); } - char *res; - if (requested == MP_CSP_LEVELS_AUTO && real_level) { - res = talloc_asprintf(NULL, "Auto (%s)", real_level); - } else if (requested == actual_level || !real_level) { - res = talloc_strdup(NULL, real_level); - } else - res = talloc_asprintf(NULL, mp_gtext("%s, but %s used"), - req_level, real_level); - talloc_free(req_level); - talloc_free(real_level); *(char **)arg = res; return M_PROPERTY_OK; } -static int mp_property_colormatrix_input_range(m_option_t *prop, int action, - void *arg, MPContext *mpctx) -{ - return levels_property_helper(offsetof(struct mp_csp_details, levels_in), - prop, action, arg, mpctx); -} - static int mp_property_colormatrix_output_range(m_option_t *prop, int action, void *arg, MPContext *mpctx) { - return levels_property_helper(offsetof(struct mp_csp_details, levels_out), - prop, action, arg, mpctx); + if (action != M_PROPERTY_PRINT) { + int r = mp_property_generic_option(prop, action, arg, mpctx); + if (action == M_PROPERTY_SET) { + if (mpctx->sh_video) + set_video_output_levels(mpctx->sh_video); + } + return r; + } + + struct MPOpts *opts = &mpctx->opts; + + int req = opts->requested_output_range; + struct mp_csp_details actual = {0}; + if (mpctx->sh_video && mpctx->sh_video->vfilter) + vf_control(mpctx->sh_video->vfilter, VFCTRL_GET_YUV_COLORSPACE, &actual); + + char *res = talloc_asprintf(NULL, "%s", mp_csp_levels_names[req]); + if (!actual.levels_out) { + res = talloc_asprintf_append(res, " (Actual: unknown)"); + } else if (actual.levels_out != req) { + res = talloc_asprintf_append(res, " (Actual: %s)", + mp_csp_levels_names[actual.levels_out]); + } + *(char **)arg = res; + return M_PROPERTY_OK; } /// Panscan (RW) diff --git a/core/mplayer.c b/core/mplayer.c index 363d89cc53..c2efe82f13 100644 --- a/core/mplayer.c +++ b/core/mplayer.c @@ -2385,6 +2385,7 @@ void mp_force_video_refresh(struct MPContext *mpctx) { struct MPOpts *opts = &mpctx->opts; + // If not paused, the next frame should come soon enough. if (opts->pause && mpctx->last_vo_pts != MP_NOPTS_VALUE) queue_seek(mpctx, MPSEEK_ABSOLUTE, mpctx->last_vo_pts, 1); } diff --git a/video/decode/dec_video.c b/video/decode/dec_video.c index cd9e8be1e5..595ffb0e16 100644 --- a/video/decode/dec_video.c +++ b/video/decode/dec_video.c @@ -106,62 +106,27 @@ int get_video_colors(sh_video_t *sh_video, const char *item, int *value) // This is affected by user-specified overrides (aspect, colorspace...). bool get_video_params(struct sh_video *sh, struct mp_image_params *p) { - struct MPOpts *opts = sh->opts; - if (!sh->vf_input) return false; *p = *sh->vf_input; - - // Apply user overrides - if (opts->requested_colorspace != MP_CSP_AUTO) - p->colorspace = opts->requested_colorspace; - if (opts->requested_input_range != MP_CSP_LEVELS_AUTO) - p->colorlevels = opts->requested_input_range; - - // Make sure the user-overrides are consistent (no RGB csp for YUV, etc.) - mp_image_params_guess_csp(p); - return true; } -void set_video_colorspace(struct sh_video *sh) +void set_video_output_levels(struct sh_video *sh) { struct MPOpts *opts = sh->opts; - struct vf_instance *vf = sh->vfilter; - struct mp_image_params params; - if (!get_video_params(sh, ¶ms)) + if (!sh->vfilter) return; - struct mp_csp_details requested = { - .format = params.colorspace, - .levels_in = params.colorlevels, - .levels_out = opts->requested_output_range, - }; - if (requested.levels_out == MP_CSP_LEVELS_AUTO) - requested.levels_out = MP_CSP_LEVELS_PC; - - vf_control(vf, VFCTRL_SET_YUV_COLORSPACE, &requested); - - struct mp_csp_details actual = MP_CSP_DETAILS_DEFAULTS; - vf_control(vf, VFCTRL_GET_YUV_COLORSPACE, &actual); - - int success = actual.format == requested.format - && actual.levels_in == requested.levels_in - && actual.levels_out == requested.levels_out; - - if (!success) - mp_tmsg(MSGT_DECVIDEO, MSGL_WARN, - "Colorspace details not fully supported by selected vo.\n"); - - if (actual.format != requested.format - && requested.format == MP_CSP_SMPTE_240M) { - // BT.709 is pretty close, much better than BT.601 - requested.format = MP_CSP_BT_709; - vf_control(vf, VFCTRL_SET_YUV_COLORSPACE, &requested); + struct mp_csp_details csp; + if (vf_control(sh->vfilter, VFCTRL_GET_YUV_COLORSPACE, &csp) > 0) { + csp.levels_out = opts->requested_output_range; + if (csp.levels_out == MP_CSP_LEVELS_AUTO) + csp.levels_out = MP_CSP_LEVELS_PC; + vf_control(sh->vfilter, VFCTRL_SET_YUV_COLORSPACE, &csp); } - } void resync_video_stream(sh_video_t *sh_video) diff --git a/video/decode/dec_video.h b/video/decode/dec_video.h index 88161ee54f..141442fa19 100644 --- a/video/decode/dec_video.h +++ b/video/decode/dec_video.h @@ -39,7 +39,7 @@ int get_video_colors(sh_video_t *sh_video, const char *item, int *value); int set_video_colors(sh_video_t *sh_video, const char *item, int value); struct mp_image_params; bool get_video_params(struct sh_video *sh, struct mp_image_params *p); -void set_video_colorspace(struct sh_video *sh); +void set_video_output_levels(struct sh_video *sh); void resync_video_stream(sh_video_t *sh_video); void video_reinit_vo(struct sh_video *sh_video); int get_current_video_decoder_lag(sh_video_t *sh_video); diff --git a/video/decode/vd.c b/video/decode/vd.c index b344491c6b..98b9b155df 100644 --- a/video/decode/vd.c +++ b/video/decode/vd.c @@ -152,6 +152,14 @@ int mpcodecs_reconfig_vo(sh_video_t *sh, const struct mp_image_params *params) p.d_w = d_w; p.d_h = d_h; + // Apply user overrides + if (opts->requested_colorspace != MP_CSP_AUTO) + p.colorspace = opts->requested_colorspace; + if (opts->requested_input_range != MP_CSP_LEVELS_AUTO) + p.colorlevels = opts->requested_input_range; + + // Detect colorspace from resolution. + // Make sure the user-overrides are consistent (no RGB csp for YUV, etc.). mp_image_params_guess_csp(&p); vocfg_flags = (opts->fullscreen ? VOFLAG_FULLSCREEN : 0) | @@ -177,7 +185,7 @@ int mpcodecs_reconfig_vo(sh_video_t *sh, const struct mp_image_params *params) sh->vf_input = talloc(sh, struct mp_image_params); *sh->vf_input = p; - set_video_colorspace(sh); + set_video_output_levels(sh); if (opts->gamma_gamma != 1000) set_video_colors(sh, "gamma", opts->gamma_gamma); diff --git a/video/filter/vf.c b/video/filter/vf.c index 1570e8402c..8946aeb801 100644 --- a/video/filter/vf.c +++ b/video/filter/vf.c @@ -170,6 +170,8 @@ static void print_fmt(int msglevel, struct vf_format *fmt) mp_msg(MSGT_VFILTER, msglevel, "->%dx%d", p->d_w, p->d_h); mp_msg(MSGT_VFILTER, msglevel, " %s %#x", mp_imgfmt_to_name(p->imgfmt), fmt->flags); + mp_msg(MSGT_VFILTER, msglevel, " %s/%s", mp_csp_names[p->colorspace], + mp_csp_levels_names[p->colorlevels]); } else { mp_msg(MSGT_VFILTER, msglevel, "???"); } @@ -357,8 +359,19 @@ unsigned int vf_match_csp(vf_instance_t **vfp, const unsigned int *list, // Ownership of img is transferred from caller to the filter chain. void vf_add_output_frame(struct vf_instance *vf, struct mp_image *img) { - if (img) + if (img) { + struct mp_image_params *p = &vf->fmt_out.params; + // vf_vo doesn't have output config + if (vf->fmt_out.configured) { + assert(p->imgfmt == img->imgfmt); + assert(p->w == img->w && p->h == img->h); + // Too many filters which don't set these correctly + img->colorspace = p->colorspace; + img->levels = p->colorlevels; + img->chroma_location = p->chroma_location; + } MP_TARRAY_APPEND(vf, vf->out_queued, vf->num_out_queued, img); + } } static struct mp_image *vf_dequeue_output_frame(struct vf_instance *vf) @@ -486,6 +499,8 @@ int vf_next_config(struct vf_instance *vf, .colorlevels = vf->fmt_in.params.colorlevels, .chroma_location = vf->fmt_in.params.chroma_location, }; + // Fix csp in case of pixel format change + mp_image_params_guess_csp(&p); int r = vf_reconfig_wrapper(vf->next, &p, voflags); return r < 0 ? 0 : 1; } diff --git a/video/filter/vf_scale.c b/video/filter/vf_scale.c index f357581bb3..2a1c397807 100644 --- a/video/filter/vf_scale.c +++ b/video/filter/vf_scale.c @@ -50,7 +50,6 @@ static struct vf_priv_s { int interlaced; int noup; int accurate_rnd; - struct mp_csp_details colorspace; } const vf_priv_dflt = { 0, 0, -1,-1, @@ -59,7 +58,7 @@ static struct vf_priv_s { }; static int mp_sws_set_colorspace(struct SwsContext *sws, - struct mp_csp_details *csp); + struct mp_image_params *p); //===========================================================================// @@ -197,20 +196,19 @@ static unsigned int find_best_out(vf_instance_t *vf, int in_format){ return best; } -static int config(struct vf_instance *vf, - int width, int height, int d_width, int d_height, - unsigned int flags, unsigned int outfmt){ +static int reconfig(struct vf_instance *vf, struct mp_image_params *p, int flags) +{ + int width = p->w, height = p->h, d_width = p->d_w, d_height = p->d_h; + unsigned int outfmt = p->imgfmt; unsigned int best=find_best_out(vf, outfmt); int int_sws_flags=0; int round_w=0, round_h=0; SwsFilter *srcFilter, *dstFilter; enum PixelFormat dfmt, sfmt; - vf->priv->colorspace = (struct mp_csp_details) {0}; - if(!best){ mp_msg(MSGT_VFILTER,MSGL_WARN,"SwScale: no supported outfmt found :(\n"); - return 0; + return -1; } sfmt = imgfmt2pixfmt(outfmt); dfmt = imgfmt2pixfmt(best); @@ -235,7 +233,7 @@ static int config(struct vf_instance *vf, // and find out what the heck he thinks MPlayer should do // with this nonsense. mp_msg(MSGT_VFILTER, MSGL_ERR, "SwScale: EUSERBROKEN Check your parameters, they make no sense!\n"); - return 0; + return -1; } if (vf->priv->w == -1) @@ -301,7 +299,7 @@ static int config(struct vf_instance *vf, if(!vf->priv->ctx){ // error... mp_msg(MSGT_VFILTER,MSGL_WARN,"Couldn't init SwScaler for this setup\n"); - return 0; + return -1; } vf->priv->fmt=best; // Compute new d_width and d_height, preserving aspect @@ -315,7 +313,17 @@ 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); + p->w = vf->priv->w; + p->h = vf->priv->h; + p->d_w = d_width; + p->d_h = d_height; + p->imgfmt = best; + mp_sws_set_colorspace(vf->priv->ctx, p); + // In particular, fix up colorspace/levels if YUV<->RGB conversion is + // performed. + p->colorlevels = MP_CSP_LEVELS_TV; // in case output is YUV + mp_image_params_guess_csp(p); + return vf_next_reconfig(vf, p, flags); } static void scale(struct SwsContext *sws1, struct SwsContext *sws2, uint8_t *src[MP_MAX_PLANES], int src_stride[MP_MAX_PLANES], @@ -407,30 +415,6 @@ static int control(struct vf_instance *vf, int request, void* data){ if(r<0) break; return CONTROL_TRUE; - case VFCTRL_SET_YUV_COLORSPACE: { - struct mp_csp_details colorspace = *(struct mp_csp_details *)data; - if (mp_sws_set_colorspace(vf->priv->ctx, &colorspace) >= 0) { - vf->priv->colorspace = colorspace; - return 1; - } - break; - } - case VFCTRL_GET_YUV_COLORSPACE: { - /* This scale filter should never react to colorspace commands if it - * doesn't do YUV->RGB conversion. But because finding out whether this - * is really YUV->RGB (and not YUV->YUV or anything else) is hard, - * react only if the colorspace has been set explicitly before. The - * trick is that mp_sws_set_colorspace does not succeed for YUV->YUV - * and RGB->YUV conversions, which makes this code correct in "most" - * cases. (This would be trivial to do correctly if libswscale exposed - * functionality like isYUV()). - */ - if (vf->priv->colorspace.format) { - *(struct mp_csp_details *)data = vf->priv->colorspace; - return CONTROL_TRUE; - } - break; - } default: break; } @@ -446,26 +430,22 @@ static const int mp_csp_to_swscale[MP_CSP_COUNT] = { // Adjust the colorspace used for YUV->RGB conversion. On other conversions, // do nothing or return an error. -// The csp argument is set to the supported values. // Return 0 on success and -1 on error. static int mp_sws_set_colorspace(struct SwsContext *sws, - struct mp_csp_details *csp) + struct mp_image_params *p) { int *table, *inv_table; int brightness, contrast, saturation, srcRange, dstRange; - csp->levels_out = MP_CSP_LEVELS_PC; - // NOTE: returns an error if the destination format is YUV if (sws_getColorspaceDetails(sws, &inv_table, &srcRange, &table, &dstRange, &brightness, &contrast, &saturation) == -1) goto error_out; - int sws_csp = mp_csp_to_swscale[csp->format]; + int sws_csp = mp_csp_to_swscale[p->colorspace]; if (sws_csp == 0) { // colorspace not supported, go with a reasonable default - csp->format = SWS_CS_ITU601; - sws_csp = MP_CSP_BT_601; + sws_csp = SWS_CS_ITU601; } /* The swscale API for these is hardly documented. @@ -473,7 +453,7 @@ static int mp_sws_set_colorspace(struct SwsContext *sws, * for YUV->RGB conversions, and conversions to limited-range RGB are * not supported. */ - srcRange = csp->levels_in == MP_CSP_LEVELS_PC; + srcRange = p->colorlevels == MP_CSP_LEVELS_PC; const int *new_inv_table = sws_getCoefficients(sws_csp); if (sws_setColorspaceDetails(sws, new_inv_table, srcRange, table, dstRange, @@ -483,7 +463,6 @@ static int mp_sws_set_colorspace(struct SwsContext *sws, return 0; error_out: - *csp = (struct mp_csp_details){0}; return -1; } @@ -509,7 +488,7 @@ static void uninit(struct vf_instance *vf){ } static int vf_open(vf_instance_t *vf, char *args){ - vf->config=config; + vf->reconfig=reconfig; vf->filter=filter; vf->query_format=query_format; vf->control= control; diff --git a/video/filter/vf_sub.c b/video/filter/vf_sub.c index e918574c30..e85a58afb7 100644 --- a/video/filter/vf_sub.c +++ b/video/filter/vf_sub.c @@ -39,7 +39,6 @@ #include "video/sws_utils.h" #include "video/memcpy_pic.h" -#include "video/csputils.h" #include "core/m_option.h" #include "core/m_struct.h" @@ -49,12 +48,10 @@ static const struct vf_priv_s { int outh, outw; - struct mp_csp_details csp; - struct osd_state *osd; struct mp_osd_res dim; } vf_priv_dflt = { - .csp = MP_CSP_DETAILS_DEFAULTS, + 0 }; static int config(struct vf_instance *vf, @@ -109,8 +106,6 @@ static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi) mpi = dmpi; } - mp_image_set_colorspace_details(mpi, &priv->csp); - osd_draw_on_image_p(osd, priv->dim, mpi->pts, OSD_DRAW_SUB_FILTER, vf->out_pool, mpi); @@ -132,11 +127,6 @@ static int control(vf_instance_t *vf, int request, void *data) break; case VFCTRL_INIT_OSD: return CONTROL_TRUE; - case VFCTRL_SET_YUV_COLORSPACE: { - struct mp_csp_details colorspace = *(struct mp_csp_details *)data; - vf->priv->csp = colorspace; - break; - } } return vf_next_control(vf, request, data); } diff --git a/video/mp_image.c b/video/mp_image.c index c1e4ba18e7..029c5fa91b 100644 --- a/video/mp_image.c +++ b/video/mp_image.c @@ -439,6 +439,8 @@ void mp_image_set_colorspace_details(struct mp_image *image, { struct mp_image_params params; mp_image_params_from_image(¶ms, image); + params.colorspace = csp->format; + params.colorlevels = csp->levels_in; mp_image_params_guess_csp(¶ms); image->colorspace = params.colorspace; image->levels = params.colorlevels; diff --git a/video/out/vo.c b/video/out/vo.c index e05b1ae8a6..425c49aab8 100644 --- a/video/out/vo.c +++ b/video/out/vo.c @@ -441,6 +441,15 @@ int vo_reconfig(struct vo *vo, struct mp_image_params *params, int flags) vo->waiting_mpi = NULL; vo->redrawing = false; vo->hasframe = false; + if (vo->config_ok) { + // Legacy + struct mp_csp_details csp; + if (vo_control(vo, VOCTRL_GET_YUV_COLORSPACE, &csp) > 0) { + csp.levels_in = params->colorlevels; + csp.format = params->colorspace; + vo_control(vo, VOCTRL_SET_YUV_COLORSPACE, &csp); + } + } return ret; } |