diff mbox series

[FFmpeg-devel] avfilter/vf_subtitles: Respect YCbCr Matrix header

Message ID 20241013115322.1425893-1-arch1t3cht@gmail.com
State New
Headers show
Series [FFmpeg-devel] avfilter/vf_subtitles: Respect YCbCr Matrix header | expand

Checks

Context Check Description
yinshiyou/make_loongarch64 success Make finished
yinshiyou/make_fate_loongarch64 success Make fate finished

Commit Message

arch1t3cht Oct. 13, 2024, 11:53 a.m. UTC
As specified in libass's ass_types.h, the colors or ASS_Images
should be converted to YCbCr using the matrix/range specified in
the track's YCbCrMatrix field (unless that field is set to YCBCR_NONE,
and defaulting to TV.601 if the header is missing).

This does not affect any subtitles generated or transcoded by ffmpeg,
since these contain a 'YCbCrMatrix: None' header.
---
 libavfilter/vf_subtitles.c | 38 +++++++++++++++++++++++++++++++++++++-
 1 file changed, 37 insertions(+), 1 deletion(-)

Comments

arch1t3cht Oct. 13, 2024, 12:48 p.m. UTC | #1
On 13/10/2024 13:53, arch1t3cht wrote:
> As specified in libass's ass_types.h, the colors or ASS_Images
> should be converted to YCbCr using the matrix/range specified in
> the track's YCbCrMatrix field (unless that field is set to YCBCR_NONE,
> and defaulting to TV.601 if the header is missing).
> 
> This does not affect any subtitles generated or transcoded by ffmpeg,
> since these contain a 'YCbCrMatrix: None' header.
> ---
>   libavfilter/vf_subtitles.c | 38 +++++++++++++++++++++++++++++++++++++-
>   1 file changed, 37 insertions(+), 1 deletion(-)
> 
> diff --git a/libavfilter/vf_subtitles.c b/libavfilter/vf_subtitles.c
> index de1cfa7d9e..ed1d12ca76 100644
> --- a/libavfilter/vf_subtitles.c
> +++ b/libavfilter/vf_subtitles.c
> @@ -88,6 +88,40 @@ static const int ass_libavfilter_log_level_map[] = {
>       [7] = AV_LOG_DEBUG,     /* MSGL_DBG2 */
>   };
>   
> +static enum AVColorSpace ass_get_color_space(ASS_YCbCrMatrix ass_matrix, enum AVColorSpace inlink_space) {
> +    switch (ass_matrix) {
> +    case YCBCR_NONE:            return inlink_space;
> +    case YCBCR_SMPTE240M_TV:
> +    case YCBCR_SMPTE240M_PC:    return AVCOL_SPC_SMPTE240M;
> +    case YCBCR_FCC_TV:
> +    case YCBCR_FCC_PC:          return AVCOL_SPC_FCC;
> +    case YCBCR_BT709_TV:
> +    case YCBCR_BT709_PC:        return AVCOL_SPC_BT709;
> +    case YCBCR_BT601_TV:
> +    case YCBCR_BT601_PC:
> +    case YCBCR_DEFAULT:
> +    case YCBCR_UNKNOWN:
> +    default:                    return AVCOL_SPC_SMPTE170M;
> +    }
> +}
> +
> +static enum AVColorRange ass_get_color_range(ASS_YCbCrMatrix ass_matrix, enum AVColorRange inlink_range) {
> +    switch (ass_matrix) {
> +    case YCBCR_NONE:            return inlink_range;
> +    case YCBCR_SMPTE240M_PC:
> +    case YCBCR_FCC_PC:
> +    case YCBCR_BT709_PC:
> +    case YCBCR_BT601_PC:        return AVCOL_RANGE_JPEG;
> +    case YCBCR_SMPTE240M_TV:
> +    case YCBCR_FCC_TV:
> +    case YCBCR_BT709_TV:
> +    case YCBCR_BT601_TV:
> +    case YCBCR_DEFAULT:
> +    case YCBCR_UNKNOWN:
> +    default:                    return AVCOL_RANGE_MPEG;
> +    }
> +}
> +
>   static void ass_log(int ass_level, const char *fmt, va_list args, void *ctx)
>   {
>       const int ass_level_clip = av_clip(ass_level, 0,
> @@ -147,7 +181,9 @@ static int config_input(AVFilterLink *inlink)
>   {
>       AssContext *ass = inlink->dst->priv;
>   
> -    ff_draw_init2(&ass->draw, inlink->format, inlink->colorspace, inlink->color_range,
> +    ff_draw_init2(&ass->draw, inlink->format,
> +                  ass_get_color_space(ass->track->YCbCrMatrix, inlink->colorspace),
> +                  ass_get_color_range(ass->track->YCbCrMatrix, inlink->color_range),
>                     ass->alpha ? FF_DRAW_PROCESS_ALPHA : 0);
>   
>       ass_set_frame_size  (ass->renderer, inlink->w, inlink->h);

Forgot to sign off, sent an identical signed-off patch now.
diff mbox series

Patch

diff --git a/libavfilter/vf_subtitles.c b/libavfilter/vf_subtitles.c
index de1cfa7d9e..ed1d12ca76 100644
--- a/libavfilter/vf_subtitles.c
+++ b/libavfilter/vf_subtitles.c
@@ -88,6 +88,40 @@  static const int ass_libavfilter_log_level_map[] = {
     [7] = AV_LOG_DEBUG,     /* MSGL_DBG2 */
 };
 
+static enum AVColorSpace ass_get_color_space(ASS_YCbCrMatrix ass_matrix, enum AVColorSpace inlink_space) {
+    switch (ass_matrix) {
+    case YCBCR_NONE:            return inlink_space;
+    case YCBCR_SMPTE240M_TV:
+    case YCBCR_SMPTE240M_PC:    return AVCOL_SPC_SMPTE240M;
+    case YCBCR_FCC_TV:
+    case YCBCR_FCC_PC:          return AVCOL_SPC_FCC;
+    case YCBCR_BT709_TV:
+    case YCBCR_BT709_PC:        return AVCOL_SPC_BT709;
+    case YCBCR_BT601_TV:
+    case YCBCR_BT601_PC:
+    case YCBCR_DEFAULT:
+    case YCBCR_UNKNOWN:
+    default:                    return AVCOL_SPC_SMPTE170M;
+    }
+}
+
+static enum AVColorRange ass_get_color_range(ASS_YCbCrMatrix ass_matrix, enum AVColorRange inlink_range) {
+    switch (ass_matrix) {
+    case YCBCR_NONE:            return inlink_range;
+    case YCBCR_SMPTE240M_PC:
+    case YCBCR_FCC_PC:
+    case YCBCR_BT709_PC:
+    case YCBCR_BT601_PC:        return AVCOL_RANGE_JPEG;
+    case YCBCR_SMPTE240M_TV:
+    case YCBCR_FCC_TV:
+    case YCBCR_BT709_TV:
+    case YCBCR_BT601_TV:
+    case YCBCR_DEFAULT:
+    case YCBCR_UNKNOWN:
+    default:                    return AVCOL_RANGE_MPEG;
+    }
+}
+
 static void ass_log(int ass_level, const char *fmt, va_list args, void *ctx)
 {
     const int ass_level_clip = av_clip(ass_level, 0,
@@ -147,7 +181,9 @@  static int config_input(AVFilterLink *inlink)
 {
     AssContext *ass = inlink->dst->priv;
 
-    ff_draw_init2(&ass->draw, inlink->format, inlink->colorspace, inlink->color_range,
+    ff_draw_init2(&ass->draw, inlink->format,
+                  ass_get_color_space(ass->track->YCbCrMatrix, inlink->colorspace),
+                  ass_get_color_range(ass->track->YCbCrMatrix, inlink->color_range),
                   ass->alpha ? FF_DRAW_PROCESS_ALPHA : 0);
 
     ass_set_frame_size  (ass->renderer, inlink->w, inlink->h);