From: Niklas Haas <g...@haasn.dev> In the process of refactoring the signature to be more generically useful, this fixes an 11-year-old bug where the functions (incorrectly) did nothing when the stride was negative, since the stride was being used as the loop bounds for x.
Sponsored-by: Sovereign Tech Fund Signed-off-by: Niklas Haas <g...@haasn.dev> --- libswscale/swscale.c | 98 +++++++++++++++-------------- libswscale/swscale_internal.h | 6 ++ tests/ref/fate/filter-pixfmts-vflip | 4 +- 3 files changed, 60 insertions(+), 48 deletions(-) diff --git a/libswscale/swscale.c b/libswscale/swscale.c index 8b6a3a84b4..b9ec976be0 100644 --- a/libswscale/swscale.c +++ b/libswscale/swscale.c @@ -636,29 +636,31 @@ static int check_image_pointers(const uint8_t * const data[4], enum AVPixelForma return 1; } -static void xyz12Torgb48(struct SwsContext *c, uint16_t *dst, - const uint16_t *src, int stride, int h) +void ff_xyz12Torgb48(const SwsContext *c, uint8_t *dst, int dst_stride, + const uint8_t *src, int src_stride, int w, int h) { - int xp,yp; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat); - for (yp=0; yp<h; yp++) { - for (xp=0; xp+2<stride; xp+=3) { + for (int yp = 0; yp < h; yp++) { + const uint16_t *src16 = (const uint16_t *) src; + uint16_t *dst16 = (uint16_t *) dst; + + for (int xp = 0; xp < 3 * w; xp += 3) { int x, y, z, r, g, b; if (desc->flags & AV_PIX_FMT_FLAG_BE) { - x = AV_RB16(src + xp + 0); - y = AV_RB16(src + xp + 1); - z = AV_RB16(src + xp + 2); + x = AV_RB16(src16 + xp + 0); + y = AV_RB16(src16 + xp + 1); + z = AV_RB16(src16 + xp + 2); } else { - x = AV_RL16(src + xp + 0); - y = AV_RL16(src + xp + 1); - z = AV_RL16(src + xp + 2); + x = AV_RL16(src16 + xp + 0); + y = AV_RL16(src16 + xp + 1); + z = AV_RL16(src16 + xp + 2); } - x = c->xyzgamma[x>>4]; - y = c->xyzgamma[y>>4]; - z = c->xyzgamma[z>>4]; + x = c->xyzgamma[x >> 4]; + y = c->xyzgamma[y >> 4]; + z = c->xyzgamma[z >> 4]; // convert from XYZlinear to sRGBlinear r = c->xyz2rgb_matrix[0][0] * x + @@ -678,38 +680,41 @@ static void xyz12Torgb48(struct SwsContext *c, uint16_t *dst, // convert from sRGBlinear to RGB and scale from 12bit to 16bit if (desc->flags & AV_PIX_FMT_FLAG_BE) { - AV_WB16(dst + xp + 0, c->rgbgamma[r] << 4); - AV_WB16(dst + xp + 1, c->rgbgamma[g] << 4); - AV_WB16(dst + xp + 2, c->rgbgamma[b] << 4); + AV_WB16(dst16 + xp + 0, c->rgbgamma[r] << 4); + AV_WB16(dst16 + xp + 1, c->rgbgamma[g] << 4); + AV_WB16(dst16 + xp + 2, c->rgbgamma[b] << 4); } else { - AV_WL16(dst + xp + 0, c->rgbgamma[r] << 4); - AV_WL16(dst + xp + 1, c->rgbgamma[g] << 4); - AV_WL16(dst + xp + 2, c->rgbgamma[b] << 4); + AV_WL16(dst16 + xp + 0, c->rgbgamma[r] << 4); + AV_WL16(dst16 + xp + 1, c->rgbgamma[g] << 4); + AV_WL16(dst16 + xp + 2, c->rgbgamma[b] << 4); } } - src += stride; - dst += stride; + + src += src_stride; + dst += dst_stride; } } -static void rgb48Toxyz12(struct SwsContext *c, uint16_t *dst, - const uint16_t *src, int stride, int h) +void ff_rgb48Toxyz12(const SwsContext *c, uint8_t *dst, int dst_stride, + const uint8_t *src, int src_stride, int w, int h) { - int xp,yp; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->dstFormat); - for (yp=0; yp<h; yp++) { - for (xp=0; xp+2<stride; xp+=3) { + for (int yp = 0; yp < h; yp++) { + uint16_t *src16 = (uint16_t *) src; + uint16_t *dst16 = (uint16_t *) dst; + + for (int xp = 0; xp < 3 * w; xp += 3) { int x, y, z, r, g, b; if (desc->flags & AV_PIX_FMT_FLAG_BE) { - r = AV_RB16(src + xp + 0); - g = AV_RB16(src + xp + 1); - b = AV_RB16(src + xp + 2); + r = AV_RB16(src16 + xp + 0); + g = AV_RB16(src16 + xp + 1); + b = AV_RB16(src16 + xp + 2); } else { - r = AV_RL16(src + xp + 0); - g = AV_RL16(src + xp + 1); - b = AV_RL16(src + xp + 2); + r = AV_RL16(src16 + xp + 0); + g = AV_RL16(src16 + xp + 1); + b = AV_RL16(src16 + xp + 2); } r = c->rgbgammainv[r>>4]; @@ -734,17 +739,18 @@ static void rgb48Toxyz12(struct SwsContext *c, uint16_t *dst, // convert from XYZlinear to X'Y'Z' and scale from 12bit to 16bit if (desc->flags & AV_PIX_FMT_FLAG_BE) { - AV_WB16(dst + xp + 0, c->xyzgammainv[x] << 4); - AV_WB16(dst + xp + 1, c->xyzgammainv[y] << 4); - AV_WB16(dst + xp + 2, c->xyzgammainv[z] << 4); + AV_WB16(dst16 + xp + 0, c->xyzgammainv[x] << 4); + AV_WB16(dst16 + xp + 1, c->xyzgammainv[y] << 4); + AV_WB16(dst16 + xp + 2, c->xyzgammainv[z] << 4); } else { - AV_WL16(dst + xp + 0, c->xyzgammainv[x] << 4); - AV_WL16(dst + xp + 1, c->xyzgammainv[y] << 4); - AV_WL16(dst + xp + 2, c->xyzgammainv[z] << 4); + AV_WL16(dst16 + xp + 0, c->xyzgammainv[x] << 4); + AV_WL16(dst16 + xp + 1, c->xyzgammainv[y] << 4); + AV_WL16(dst16 + xp + 2, c->xyzgammainv[z] << 4); } } - src += stride; - dst += stride; + + src += src_stride; + dst += dst_stride; } } @@ -994,7 +1000,7 @@ static int scale_internal(SwsContext *c, base = srcStride[0] < 0 ? c->xyz_scratch - srcStride[0] * (srcSliceH-1) : c->xyz_scratch; - xyz12Torgb48(c, (uint16_t*)base, (const uint16_t*)src2[0], srcStride[0]/2, srcSliceH); + ff_xyz12Torgb48(c, base, srcStride[0], src2[0], srcStride[0], c->srcW, srcSliceH); src2[0] = base; } @@ -1052,21 +1058,21 @@ static int scale_internal(SwsContext *c, } if (c->dstXYZ && !(c->srcXYZ && c->srcW==c->dstW && c->srcH==c->dstH)) { - uint16_t *dst16; + uint8_t *dst; if (scale_dst) { - dst16 = (uint16_t *)dst2[0]; + dst = dst2[0]; } else { int dstY = c->dstY ? c->dstY : srcSliceY + srcSliceH; av_assert0(dstY >= ret); av_assert0(ret >= 0); av_assert0(c->dstH >= dstY); - dst16 = (uint16_t*)(dst2[0] + (dstY - ret) * dstStride2[0]); + dst = dst2[0] + (dstY - ret) * dstStride2[0]; } /* replace on the same data */ - rgb48Toxyz12(c, dst16, dst16, dstStride2[0]/2, ret); + ff_rgb48Toxyz12(c, dst, dstStride2[0], dst, dstStride2[0], c->dstW, ret); } /* reset slice direction at end of frame */ diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h index 963879cf9a..17440c99c4 100644 --- a/libswscale/swscale_internal.h +++ b/libswscale/swscale_internal.h @@ -1013,6 +1013,12 @@ void ff_copyPlane(const uint8_t *src, int srcStride, int srcSliceY, int srcSliceH, int width, uint8_t *dst, int dstStride); +void ff_xyz12Torgb48(const SwsContext *c, uint8_t *dst, int dst_stride, + const uint8_t *src, int src_stride, int w, int h); + +void ff_rgb48Toxyz12(const SwsContext *c, uint8_t *dst, int dst_stride, + const uint8_t *src, int src_stride, int w, int h); + static inline void fillPlane16(uint8_t *plane, int stride, int width, int height, int y, int alpha, int bits, const int big_endian) { diff --git a/tests/ref/fate/filter-pixfmts-vflip b/tests/ref/fate/filter-pixfmts-vflip index 5ba28917a7..4cc716799f 100644 --- a/tests/ref/fate/filter-pixfmts-vflip +++ b/tests/ref/fate/filter-pixfmts-vflip @@ -103,8 +103,8 @@ x2bgr10le 795b66a5fc83cd2cf300aae51c230f80 x2rgb10le 262c502230cf3724f8e2cf4737f18a42 xv30le 7e29ee107a1fabf3c7251f337d4b9fe5 xv36le bf1cbef0745f90881e15f5c5db3c5949 -xyz12be 810644e008deb231850d779aaa27cc7e -xyz12le 829701db461b43533cf9241e0743bc61 +xyz12be 23fa9fb36d49dce61e284d41b83e0e6b +xyz12le ef73e6d1f932a9a355df1eedd628394f y210le 9544c81f8e1fc95e9fa4009dbecfea25 y212le c801725ae31e3b8f5be269359d49f191 ya16be 55b1dbbe4d56ed0d22461685ce85520d -- 2.46.1 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".