From 3ee8d1b5da8d66a5620fc5c243a0fc62db4bb444 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= Date: Sat, 9 Mar 2024 18:36:00 +0100 Subject: [PATCH] options: add --sub-ass-colorspace option Option to control what colorspace subtitle should be converted to before drawing them. Upstream ASS specification says that all subtitles should be rendered with color primaries and transfer matching their associated video. This has certain limitations in the case of HDR/WCG content. See the discussion in libass/libass#297. To mitigate current situation add an option for users to control the render target of subtitles. This could be also accomplished with --blend-subtitles to some degree, but I don't want to mux options that are not really clear to affect this certain case. See-Also: https://github.com/libass/libass/blob/649a7c2e1fc6f4188ea1a89968560715800b883d/libass/ass_types.h#L233-L237 See-Also: https://github.com/libass/libass/issues/297 See-Also: https://github.com/mpv-player/mpv/issues/13381 Fixes: https://github.com/mpv-player/mpv/issues/13673 --- DOCS/interface-changes.rst | 1 + DOCS/man/options.rst | 15 +++++++++++++++ options/options.c | 2 ++ options/options.h | 1 + video/out/vo_gpu_next.c | 17 +++++++++++++++-- 5 files changed, 34 insertions(+), 2 deletions(-) diff --git a/DOCS/interface-changes.rst b/DOCS/interface-changes.rst index 14557de1b5ab3..af66db3fd1658 100644 --- a/DOCS/interface-changes.rst +++ b/DOCS/interface-changes.rst @@ -63,6 +63,7 @@ Interface changes - add `--border-background` option - add `video-target-params` property - add `hdr10plus` sub-parameter to `format` video filter + - add `--sub-ass-colorspace` option --- mpv 0.37.0 --- - `--save-position-on-quit` and its associated commands now store state files in %LOCALAPPDATA% instead of %APPDATA% directory by default on Windows. diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst index 6a09cf388484e..4245826bc5da0 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -2528,6 +2528,21 @@ Subtitles Default: yes. +``--sub-ass-colorspace=`` + Specify the RGB primaries and transfer function to use when rendering + ASS subtitles. + + :auto: Follow the ASS specification. This is currently equivalent to + ``video``. This behavior may change in the future. (default) + :video: Assume that ASS subtitles are in the video's colorspace. Match the + color primaries and transfer function of the ASS subtitles to those + of the associated video. + :sdr: Assume that ASS subtitles are SDR. Match them to the video's + colorspace in SDR mode. If the video is HDR/WCG, fall back to sRGB. + + This option affects ``--vo=gpu-next``, ``--vo=gpu`` always assume sRGB + colorspace for subtitles. + ``--sub-ass-vsfilter-aspect-compat=`` Stretch SSA/ASS subtitles when playing anamorphic videos for compatibility with traditional VSFilter behavior. This switch has no effect when the diff --git a/options/options.c b/options/options.c index 796a6c668bb6f..febdfd08a3f79 100644 --- a/options/options.c +++ b/options/options.c @@ -325,6 +325,8 @@ const struct m_sub_options mp_subtitle_sub_opts = { {"sub-past-video-end", OPT_BOOL(sub_past_video_end)}, {"sub-ass-force-style", OPT_REPLACED("sub-ass-style-overrides")}, {"sub-lavc-o", OPT_KEYVALUELIST(sub_avopts)}, + {"sub-ass-colorspace", OPT_CHOICE(ass_colorspace, + {"auto", 0}, {"video", 1}, {"sdr", 2})}, {0} }, .size = sizeof(OPT_BASE_STRUCT), diff --git a/options/options.h b/options/options.h index 1b7c3e358351f..8dc44e6d96bb7 100644 --- a/options/options.h +++ b/options/options.h @@ -113,6 +113,7 @@ struct mp_subtitle_opts { bool sub_clear_on_seek; int teletext_page; bool sub_past_video_end; + int ass_colorspace; char **sub_avopts; }; diff --git a/video/out/vo_gpu_next.c b/video/out/vo_gpu_next.c index 84facb9e445bb..385172472acdb 100644 --- a/video/out/vo_gpu_next.c +++ b/video/out/vo_gpu_next.c @@ -141,6 +141,8 @@ struct priv { struct m_config_cache *opts_cache; struct m_config_cache *next_opts_cache; struct gl_next_opts *next_opts; + struct m_config_cache *subtitle_opts_cache; + struct mp_subtitle_opts *subtitle_opts; struct cache shader_cache, icc_cache; struct mp_csp_equalizer_state *video_eq; struct scaler_params scalers[SCALER_COUNT]; @@ -378,8 +380,15 @@ static void update_overlays(struct vo *vo, struct mp_osd_res res, } } break; - case SUBBITMAP_LIBASS: - if (src && item->video_color_space) + case SUBBITMAP_LIBASS:; + bool video_color_space = item->video_color_space; + if (p->subtitle_opts->ass_colorspace == 2 && + (pl_color_space_is_hdr(&src->params.color) || + pl_color_primaries_is_wide_gamut(src->params.color.primaries))) + { + video_color_space = false; + } + if (src && video_color_space) ol->color = src->params.color; ol->mode = PL_OVERLAY_MONOCHROME; ol->repr.alpha = PL_ALPHA_INDEPENDENT; @@ -768,6 +777,8 @@ static void update_options(struct vo *vo) if (changed) update_render_options(vo); + m_config_cache_update(p->subtitle_opts_cache); + update_lut(p, &p->next_opts->lut); pars->params.lut = p->next_opts->lut.lut; pars->params.lut_type = p->next_opts->lut.type; @@ -1820,6 +1831,8 @@ static int preinit(struct vo *vo) p->opts_cache = m_config_cache_alloc(p, vo->global, &gl_video_conf); p->next_opts_cache = m_config_cache_alloc(p, vo->global, &gl_next_conf); p->next_opts = p->next_opts_cache->opts; + p->subtitle_opts_cache = m_config_cache_alloc(p, vo->global, &mp_subtitle_sub_opts); + p->subtitle_opts = p->subtitle_opts_cache->opts; p->video_eq = mp_csp_equalizer_create(p, vo->global); p->global = vo->global; p->log = vo->log;