swscale: fix sws_setColorspaceDetails after sws_init_context

More commonly, this fixes the case of sws_setColorspaceDetails after
sws_getContext, since the latter implies sws_init_context.

The problem here is that sws_init_context sets up the range conversion
and fast path tables based on the values of srcRange/dstRange at init
time. This may result in locking in a "wrong" path (either using
unscaled fast path when range conversion later required, or using
scaled slow path when range conversion becomes no longer required).

There are two way outs:

1. Always initialize range conversion and unscaled converters, even if
   they will be unused, and extend the runtime check.
2. Re-do initialization if the values change after
   sws_setColorspaceDetails.

I opted for approach 1 because it was simpler and easier to reason
about.

Reword the av_log message to make it clear that this special converter
is not necessarily used, depending on whether or not there is range
conversion or YUV matrix conversion going on.
This commit is contained in:
Niklas Haas 2023-10-27 16:45:12 +02:00
parent acf63d5350
commit cedf589c09
2 changed files with 4 additions and 8 deletions

View File

@ -1016,7 +1016,7 @@ static int scale_internal(SwsContext *c,
reset_ptr(src2, c->srcFormat);
reset_ptr((void*)dst2, c->dstFormat);
if (c->convert_unscaled) {
if (c->convert_unscaled && !c->lumConvertRange && !c->chrConvertRange) {
int offset = srcSliceY_internal;
int slice_h = srcSliceH;

View File

@ -1715,30 +1715,26 @@ static av_cold int sws_init_single_context(SwsContext *c, SwsFilter *srcFilter,
if (unscaled && !usesHFilter && !usesVFilter &&
c->alphablend != SWS_ALPHA_BLEND_NONE &&
isALPHA(srcFormat) &&
(c->srcRange == c->dstRange || isAnyRGB(dstFormat)) &&
alphaless_fmt(srcFormat) == dstFormat
) {
c->convert_unscaled = ff_sws_alphablendaway;
if (flags & SWS_PRINT_INFO)
av_log(c, AV_LOG_INFO,
"using alpha blendaway %s -> %s special converter\n",
"alpha blendaway %s -> %s special converter is available\n",
av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat));
return 0;
}
/* unscaled special cases */
if (unscaled && !usesHFilter && !usesVFilter &&
(c->srcRange == c->dstRange || isAnyRGB(dstFormat) ||
isFloat(srcFormat) || isFloat(dstFormat))){
if (unscaled && !usesHFilter && !usesVFilter) {
ff_get_unscaled_swscale(c);
if (c->convert_unscaled) {
if (flags & SWS_PRINT_INFO)
av_log(c, AV_LOG_INFO,
"using unscaled %s -> %s special converter\n",
"unscaled %s -> %s special converter is available\n",
av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat));
return 0;
}
}