PR #23108 opened by Ramiro Polla (ramiro) URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23108 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23108.patch
The formats added in e93de9948d keep the values in the most significant bits of the uint16_t, and packed30togbra10() and gbr16ptopacked30() weren't taking into consideration the shift field from AVComponentDescriptor. Reproducible with: $ ./libswscale/tests/swscale -unscaled 1 -src gbrp10msbbe -dst x2rgb10le $ ./libswscale/tests/swscale -unscaled 1 -src x2rgb10le -dst gbrp10msbbe >From 7f952b2d3b06d60dd3d50e25207a83fe33618d4b Mon Sep 17 00:00:00 2001 From: Ramiro Polla <[email protected]> Date: Fri, 15 May 2026 22:44:13 +0200 Subject: [PATCH] swscale/swscale_unscaled: fix packed30togbra10() and gbr16ptopacked30() for GBRP 10 and 12 bit MSB formats The formats added in e93de9948d keep the values in the most significant bits of the uint16_t, and packed30togbra10() and gbr16ptopacked30() weren't taking into consideration the shift field from AVComponentDescriptor. Reproducible with: $ ./libswscale/tests/swscale -unscaled 1 -src gbrp10msbbe -dst x2rgb10le $ ./libswscale/tests/swscale -unscaled 1 -src x2rgb10le -dst gbrp10msbbe --- libswscale/swscale_unscaled.c | 45 ++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/libswscale/swscale_unscaled.c b/libswscale/swscale_unscaled.c index 0ecef7d44a..7de47dfbb7 100644 --- a/libswscale/swscale_unscaled.c +++ b/libswscale/swscale_unscaled.c @@ -818,7 +818,7 @@ static void packed16togbra16(const uint8_t *src, int srcStride, static void packed30togbra10(const uint8_t *src, int srcStride, uint16_t *dst[], const int dstStride[], int srcSliceH, - int swap, int bpc, int width) + int swap, int bpc, int shift, int width) { int x, h, i; int dst_alpha = dst[3] != NULL; @@ -835,23 +835,23 @@ static void packed30togbra10(const uint8_t *src, int srcStride, for (x = 0; x < width; x++) { unsigned p = AV_RL32(src_line); component = (p >> 20) & 0x3FF; - dst[0][x] = av_bswap16(component << scale_high | component >> scale_low); + dst[0][x] = av_bswap16((component << scale_high | component >> scale_low) << shift); component = (p >> 10) & 0x3FF; - dst[1][x] = av_bswap16(component << scale_high | component >> scale_low); + dst[1][x] = av_bswap16((component << scale_high | component >> scale_low) << shift); component = p & 0x3FF; - dst[2][x] = av_bswap16(component << scale_high | component >> scale_low); - dst[3][x] = av_bswap16(alpha_val); + dst[2][x] = av_bswap16((component << scale_high | component >> scale_low) << shift); + dst[3][x] = av_bswap16(alpha_val) << shift; src_line++; } } else { for (x = 0; x < width; x++) { unsigned p = AV_RL32(src_line); component = (p >> 20) & 0x3FF; - dst[0][x] = av_bswap16(component << scale_high | component >> scale_low); + dst[0][x] = av_bswap16((component << scale_high | component >> scale_low) << shift); component = (p >> 10) & 0x3FF; - dst[1][x] = av_bswap16(component << scale_high | component >> scale_low); + dst[1][x] = av_bswap16((component << scale_high | component >> scale_low) << shift); component = p & 0x3FF; - dst[2][x] = av_bswap16(component << scale_high | component >> scale_low); + dst[2][x] = av_bswap16((component << scale_high | component >> scale_low) << shift); src_line++; } } @@ -861,23 +861,23 @@ static void packed30togbra10(const uint8_t *src, int srcStride, for (x = 0; x < width; x++) { unsigned p = AV_RL32(src_line); component = (p >> 20) & 0x3FF; - dst[0][x] = component << scale_high | component >> scale_low; + dst[0][x] = (component << scale_high | component >> scale_low) << shift; component = (p >> 10) & 0x3FF; - dst[1][x] = component << scale_high | component >> scale_low; + dst[1][x] = (component << scale_high | component >> scale_low) << shift; component = p & 0x3FF; - dst[2][x] = component << scale_high | component >> scale_low; - dst[3][x] = alpha_val; + dst[2][x] = (component << scale_high | component >> scale_low) << shift; + dst[3][x] = alpha_val << shift; src_line++; } } else { for (x = 0; x < width; x++) { unsigned p = AV_RL32(src_line); component = (p >> 20) & 0x3FF; - dst[0][x] = component << scale_high | component >> scale_low; + dst[0][x] = (component << scale_high | component >> scale_low) << shift; component = (p >> 10) & 0x3FF; - dst[1][x] = component << scale_high | component >> scale_low; + dst[1][x] = (component << scale_high | component >> scale_low) << shift; component = p & 0x3FF; - dst[2][x] = component << scale_high | component >> scale_low; + dst[2][x] = (component << scale_high | component >> scale_low) << shift; src_line++; } } @@ -899,6 +899,7 @@ static int Rgb16ToPlanarRgb16Wrapper(SwsInternal *c, const uint8_t *const src[], const AVPixFmtDescriptor *src_format = av_pix_fmt_desc_get(c->opts.src_format); const AVPixFmtDescriptor *dst_format = av_pix_fmt_desc_get(c->opts.dst_format); int bpc = dst_format->comp[0].depth; + int shift = dst_format->comp[0].shift; int alpha = src_format->flags & AV_PIX_FMT_FLAG_ALPHA; int swap = 0; int i; @@ -935,7 +936,7 @@ static int Rgb16ToPlanarRgb16Wrapper(SwsInternal *c, const uint8_t *const src[], av_assert0(bpc >= 10); packed30togbra10(src[0], srcStride[0], dst2013, stride2013, srcSliceH, swap, - bpc, c->opts.src_w); + bpc, shift, c->opts.src_w); break; case AV_PIX_FMT_BGR48LE: case AV_PIX_FMT_BGR48BE: @@ -949,7 +950,7 @@ static int Rgb16ToPlanarRgb16Wrapper(SwsInternal *c, const uint8_t *const src[], av_assert0(bpc >= 10); packed30togbra10(src[0], srcStride[0], dst1023, stride1023, srcSliceH, swap, - bpc, c->opts.src_w); + bpc, shift, c->opts.src_w); break; default: av_log(c, AV_LOG_ERROR, @@ -1081,11 +1082,10 @@ static void gbr16ptopacked16(const uint16_t *src[], const int srcStride[], static void gbr16ptopacked30(const uint16_t *src[], const int srcStride[], uint8_t *dst, int dstStride, int srcSliceH, - int swap, int bpp, int width) + int swap, int shift, int width) { int x, h, i; - int shift = bpp - 10; - av_assert0(bpp >= 0); + av_assert0(shift >= 0); for (h = 0; h < srcSliceH; h++) { uint8_t *dest = dst + dstStride * h; @@ -1125,6 +1125,7 @@ static int planarRgb16ToRgb16Wrapper(SwsInternal *c, const uint8_t *const src[], const AVPixFmtDescriptor *src_format = av_pix_fmt_desc_get(c->opts.src_format); const AVPixFmtDescriptor *dst_format = av_pix_fmt_desc_get(c->opts.dst_format); int bits_per_sample = src_format->comp[0].depth; + int shift = src_format->comp[0].shift; int swap = 0; if ( HAVE_BIGENDIAN && !(src_format->flags & AV_PIX_FMT_FLAG_BE) || !HAVE_BIGENDIAN && src_format->flags & AV_PIX_FMT_FLAG_BE) @@ -1168,12 +1169,12 @@ static int planarRgb16ToRgb16Wrapper(SwsInternal *c, const uint8_t *const src[], case AV_PIX_FMT_X2RGB10LE: gbr16ptopacked30(src201, stride201, dst[0] + srcSliceY * dstStride[0], dstStride[0], - srcSliceH, swap, bits_per_sample, c->opts.src_w); + srcSliceH, swap, bits_per_sample + shift - 10, c->opts.src_w); break; case AV_PIX_FMT_X2BGR10LE: gbr16ptopacked30(src102, stride102, dst[0] + srcSliceY * dstStride[0], dstStride[0], - srcSliceH, swap, bits_per_sample, c->opts.src_w); + srcSliceH, swap, bits_per_sample + shift - 10, c->opts.src_w); break; default: av_log(c, AV_LOG_ERROR, -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
