[FFmpeg-devel] [PATCH 05/12] swscale/internal: fix and expose xyz12Torgb48 and rgb48Toxyz12
Niklas Haas
ffmpeg at haasn.xyz
Sat Oct 5 22:23:56 EEST 2024
From: Niklas Haas <git at 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 <git at 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
More information about the ffmpeg-devel
mailing list