Message ID | 20200915211643.259961-1-jeebjp@gmail.com |
---|---|
State | New |
Headers | show |
Series | [FFmpeg-devel] avfilter/vf_scale: set RGB to always be full range | expand |
Context | Check | Description |
---|---|---|
andriy/default | pending | |
andriy/make | success | Make finished |
andriy/make_fate | success | Make fate finished |
Jan Ekström (12020-09-16): > This value - while it looks like the actual range of the content - > is nothing but the internal value of swscale. > > Thus, if we have RGB content, force the value to 1. Swscale will > ignore it, but at least the value of the output AVFrame will now > properly be "full range" instead of "limited range", as it is right > now. > --- > libavfilter/vf_scale.c | 17 +++++++++++++++++ > 1 file changed, 17 insertions(+) > > diff --git a/libavfilter/vf_scale.c b/libavfilter/vf_scale.c > index 58eee96744..12df27edf4 100644 > --- a/libavfilter/vf_scale.c > +++ b/libavfilter/vf_scale.c > @@ -751,6 +751,15 @@ scale: > || scale->out_range != AVCOL_RANGE_UNSPECIFIED) { > int in_full, out_full, brightness, contrast, saturation; > const int *inv_table, *table; > + const AVPixFmtDescriptor *out_desc = av_pix_fmt_desc_get(out->format); > + if (!out_desc) { > + av_log(ctx, AV_LOG_ERROR, > + "Failed to get the pixel format descriptor for format %d!\n", > + out->format); > + av_frame_free(&in); > + av_frame_free(frame_out); > + return AVERROR_INVALIDDATA; > + } Since the format is negotiated, I think it can be considered a severe internal bug that out_desc is not found, i.e. checked by an assert. > > sws_getColorspaceDetails(scale->sws, (int **)&inv_table, &in_full, > (int **)&table, &out_full, > @@ -768,7 +777,15 @@ scale: > else if (in_range != AVCOL_RANGE_UNSPECIFIED) > in_full = (in_range == AVCOL_RANGE_JPEG); > if (scale->out_range != AVCOL_RANGE_UNSPECIFIED) > + // note: this can be silently overridden by > + // sws_setColorspaceDetails for non-YCbCr formats > out_full = (scale->out_range == AVCOL_RANGE_JPEG); > + else if (out_desc->flags & AV_PIX_FMT_FLAG_RGB) > + // the range values received from swscale are its internal > + // identifiers, and will not be nonzero for any sort of RGB. > + // thus, if we do not set it to nonzero ourselves, this will > + // be incorrect. > + out_full = 1; > > sws_setColorspaceDetails(scale->sws, inv_table, in_full, > table, out_full, With you explanation, I think it is ok, but I do not know the topic enough to be sure. Regards,
On Wed, Sep 16, 2020 at 12:16:43AM +0300, Jan Ekström wrote: > This value - while it looks like the actual range of the content - > is nothing but the internal value of swscale. > > Thus, if we have RGB content, force the value to 1. Swscale will > ignore it, but at least the value of the output AVFrame will now > properly be "full range" instead of "limited range", as it is right > now. > --- > libavfilter/vf_scale.c | 17 +++++++++++++++++ > 1 file changed, 17 insertions(+) > > diff --git a/libavfilter/vf_scale.c b/libavfilter/vf_scale.c > index 58eee96744..12df27edf4 100644 > --- a/libavfilter/vf_scale.c > +++ b/libavfilter/vf_scale.c [...] > @@ -768,7 +777,15 @@ scale: > else if (in_range != AVCOL_RANGE_UNSPECIFIED) > in_full = (in_range == AVCOL_RANGE_JPEG); > if (scale->out_range != AVCOL_RANGE_UNSPECIFIED) > + // note: this can be silently overridden by > + // sws_setColorspaceDetails for non-YCbCr formats > out_full = (scale->out_range == AVCOL_RANGE_JPEG); > + else if (out_desc->flags & AV_PIX_FMT_FLAG_RGB) > + // the range values received from swscale are its internal > + // identifiers, and will not be nonzero for any sort of RGB. > + // thus, if we do not set it to nonzero ourselves, this will > + // be incorrect. > + out_full = 1; Does anything document the meaning of range or AVCOL_RANGE for RGB ? The enum is documented as "MPEG vs JPEG YUV range." What is limited range RGB ? what would the ranges of R,G,B be and where is that specified ? That said, changing it to full range for RGB as done by this patch is probably ok if it helps some code (for example allows simplifications) thx [...]
On Wed, Sep 16, 2020 at 11:38 PM Michael Niedermayer <michael@niedermayer.cc> wrote: > > On Wed, Sep 16, 2020 at 12:16:43AM +0300, Jan Ekström wrote: > > This value - while it looks like the actual range of the content - > > is nothing but the internal value of swscale. > > > > Thus, if we have RGB content, force the value to 1. Swscale will > > ignore it, but at least the value of the output AVFrame will now > > properly be "full range" instead of "limited range", as it is right > > now. > > --- > > libavfilter/vf_scale.c | 17 +++++++++++++++++ > > 1 file changed, 17 insertions(+) > > > > diff --git a/libavfilter/vf_scale.c b/libavfilter/vf_scale.c > > index 58eee96744..12df27edf4 100644 > > --- a/libavfilter/vf_scale.c > > +++ b/libavfilter/vf_scale.c > [...] > > @@ -768,7 +777,15 @@ scale: > > else if (in_range != AVCOL_RANGE_UNSPECIFIED) > > in_full = (in_range == AVCOL_RANGE_JPEG); > > if (scale->out_range != AVCOL_RANGE_UNSPECIFIED) > > + // note: this can be silently overridden by > > + // sws_setColorspaceDetails for non-YCbCr formats > > out_full = (scale->out_range == AVCOL_RANGE_JPEG); > > + else if (out_desc->flags & AV_PIX_FMT_FLAG_RGB) > > + // the range values received from swscale are its internal > > + // identifiers, and will not be nonzero for any sort of RGB. > > + // thus, if we do not set it to nonzero ourselves, this will > > + // be incorrect. > > + out_full = 1; > > Does anything document the meaning of range or AVCOL_RANGE for RGB ? > The enum is documented as "MPEG vs JPEG YUV range." > > What is limited range RGB ? what would the ranges of R,G,B be and where > is that specified ? > > That said, changing it to full range for RGB as done by this patch is > probably ok if it helps some code (for example allows simplifications) > I am not here to say that we would have to support limited range RGB, which I mostly only see mentioned as the PC graphics output for devices such as video projectors. The problem is just that vf_scale took that internal swscale flag and attempted to interpret that as full|limited range flag as-is. Anyways, posted a v2 which actually verifies the requested flags against the actually configured ones, while keeping the translation between swscale internal value and "is this stuff going to be full range or not". Possibly simpler to follow/read than this one :) , even though clearly more complex. Jan
On Wed, Sep 16, 2020 at 9:43 PM Jan Ekström <jeebjp@gmail.com> wrote: > > On Wed, Sep 16, 2020 at 11:38 PM Michael Niedermayer > <michael@niedermayer.cc> wrote: > > Does anything document the meaning of range or AVCOL_RANGE for RGB ? > > The enum is documented as "MPEG vs JPEG YUV range." > > > > What is limited range RGB ? what would the ranges of R,G,B be and where > > is that specified ? EBU only describes full range for 'file' based images https://tech.ebu.ch/docs/r/r103.pdf but ITU https://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.2100-2-201807-I!!PDF-E.pdf does describe narrow range RGB on p9 Kevin
On Thu, Sep 17, 2020 at 11:10:29AM +0100, Kevin Wheatley wrote: > On Wed, Sep 16, 2020 at 9:43 PM Jan Ekström <jeebjp@gmail.com> wrote: > > > > On Wed, Sep 16, 2020 at 11:38 PM Michael Niedermayer > > <michael@niedermayer.cc> wrote: > > > Does anything document the meaning of range or AVCOL_RANGE for RGB ? > > > The enum is documented as "MPEG vs JPEG YUV range." > > > > > > What is limited range RGB ? what would the ranges of R,G,B be and where > > > is that specified ? > > EBU only describes full range for 'file' based images > > https://tech.ebu.ch/docs/r/r103.pdf > > but ITU https://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.2100-2-201807-I!!PDF-E.pdf thanks for the links! [...]
diff --git a/libavfilter/vf_scale.c b/libavfilter/vf_scale.c index 58eee96744..12df27edf4 100644 --- a/libavfilter/vf_scale.c +++ b/libavfilter/vf_scale.c @@ -751,6 +751,15 @@ scale: || scale->out_range != AVCOL_RANGE_UNSPECIFIED) { int in_full, out_full, brightness, contrast, saturation; const int *inv_table, *table; + const AVPixFmtDescriptor *out_desc = av_pix_fmt_desc_get(out->format); + if (!out_desc) { + av_log(ctx, AV_LOG_ERROR, + "Failed to get the pixel format descriptor for format %d!\n", + out->format); + av_frame_free(&in); + av_frame_free(frame_out); + return AVERROR_INVALIDDATA; + } sws_getColorspaceDetails(scale->sws, (int **)&inv_table, &in_full, (int **)&table, &out_full, @@ -768,7 +777,15 @@ scale: else if (in_range != AVCOL_RANGE_UNSPECIFIED) in_full = (in_range == AVCOL_RANGE_JPEG); if (scale->out_range != AVCOL_RANGE_UNSPECIFIED) + // note: this can be silently overridden by + // sws_setColorspaceDetails for non-YCbCr formats out_full = (scale->out_range == AVCOL_RANGE_JPEG); + else if (out_desc->flags & AV_PIX_FMT_FLAG_RGB) + // the range values received from swscale are its internal + // identifiers, and will not be nonzero for any sort of RGB. + // thus, if we do not set it to nonzero ourselves, this will + // be incorrect. + out_full = 1; sws_setColorspaceDetails(scale->sws, inv_table, in_full, table, out_full,