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;