Commit 88e6193e00 for ffmpeg
commit 88e6193e00c7ce2c86f857b502c2fec9376636bf
Author: Michael Niedermayer <michael@niedermayer.cc>
Date: Sat Nov 7 22:08:08 2026 +0100
swscale: write the last pixel of odd width rows in the planar to packed YUV converters
Fixes: hEgEOrq8XP97
Found during the review of https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25034
Unwritten last pixel Replicated through UnModified FFmpeg with rawvideo output
diff --git a/libswscale/rgb2rgb.h b/libswscale/rgb2rgb.h
index 6f16f95fa6..db648f2d66 100644
--- a/libswscale/rgb2rgb.h
+++ b/libswscale/rgb2rgb.h
@@ -144,16 +144,18 @@ extern void (*yuyvtoyuv422)(uint8_t *ydst, uint8_t *udst, uint8_t *vdst, const u
void ff_sws_rgb2rgb_init(void);
/**
- * Packs the chroma positions from..to-1 of one line as YUYV when
- * luma_first is set and as UYVY otherwise.
+ * Packs one line of width pixels, starting at chroma position from, as YUYV
+ * when luma_first is set and as UYVY otherwise. The luma of an odd last
+ * pixel is repeated.
*/
static inline void ff_pack_yuv422_line(uint8_t *dst, const uint8_t *ysrc,
const uint8_t *usrc, const uint8_t *vsrc,
- int from, int to, int luma_first)
+ int from, int width, int luma_first)
{
- for (int i = from; i < to; i++) {
+ for (int i = from; 2 * i < width; i++) {
+ const int y1 = 2 * i + 1 < width ? 2 * i + 1 : 2 * i;
dst[4 * i + !luma_first] = ysrc[2 * i];
- dst[4 * i + 2 + !luma_first] = ysrc[2 * i + 1];
+ dst[4 * i + 2 + !luma_first] = ysrc[y1];
dst[4 * i + luma_first] = usrc[i];
dst[4 * i + 2 + luma_first] = vsrc[i];
}
diff --git a/libswscale/rgb2rgb_template.c b/libswscale/rgb2rgb_template.c
index d857b74afb..81515904f3 100644
--- a/libswscale/rgb2rgb_template.c
+++ b/libswscale/rgb2rgb_template.c
@@ -399,7 +399,7 @@ static inline void yuvPlanartoyuy2_c(const uint8_t *ysrc, const uint8_t *usrc,
uc += 2;
vc += 2;
}
- ff_pack_yuv422_line(dst, ysrc, usrc, vsrc, chromWidth & ~1, chromWidth, 1);
+ ff_pack_yuv422_line(dst, ysrc, usrc, vsrc, chromWidth & ~1, width, 1);
#else
int *idst = (int32_t *)dst;
@@ -417,6 +417,7 @@ static inline void yuvPlanartoyuy2_c(const uint8_t *ysrc, const uint8_t *usrc,
uc++;
vc++;
}
+ ff_pack_yuv422_line(dst, ysrc, usrc, vsrc, chromWidth, width, 1);
#endif
if ((y & (vertLumPerChroma - 1)) == vertLumPerChroma - 1) {
usrc += chromStride;
@@ -460,7 +461,7 @@ static inline void yuvPlanartouyvy_c(const uint8_t *ysrc, const uint8_t *usrc,
uc += 2;
vc += 2;
}
- ff_pack_yuv422_line(dst, ysrc, usrc, vsrc, chromWidth & ~1, chromWidth, 0);
+ ff_pack_yuv422_line(dst, ysrc, usrc, vsrc, chromWidth & ~1, width, 0);
#else
int *idst = (int32_t *)dst;
@@ -478,6 +479,7 @@ static inline void yuvPlanartouyvy_c(const uint8_t *ysrc, const uint8_t *usrc,
uc++;
vc++;
}
+ ff_pack_yuv422_line(dst, ysrc, usrc, vsrc, chromWidth, width, 0);
#endif
if ((y & (vertLumPerChroma - 1)) == vertLumPerChroma - 1) {
usrc += chromStride;
diff --git a/libswscale/x86/rgb2rgb.c b/libswscale/x86/rgb2rgb.c
index f22a919575..aecdaf7a69 100644
--- a/libswscale/x86/rgb2rgb.c
+++ b/libswscale/x86/rgb2rgb.c
@@ -24,6 +24,7 @@
*/
#include <stdint.h>
+#include <string.h>
#include "config.h"
#include "libavutil/attributes.h"
@@ -1158,7 +1159,7 @@ static inline void yuvPlanartoyuy2_line_mmxext(uint8_t *dst, const uint8_t *ysrc
"cmp %4, %%"FF_REG_a" \n\t"
" jb 1b \n\t"
::"r"(dst), "r"(ysrc), "r"(usrc), "r"(vsrc), "g" (chromWidth)
- : "%"FF_REG_a
+ : "%"FF_REG_a, "memory"
);
}
@@ -1196,7 +1197,7 @@ static inline void yuvPlanartouyvy_line_mmxext(uint8_t *dst, const uint8_t *ysrc
"cmp %4, %%"FF_REG_a" \n\t"
" jb 1b \n\t"
::"r"(dst), "r"(ysrc), "r"(usrc), "r"(vsrc), "g" (chromWidth)
- : "%"FF_REG_a
+ : "%"FF_REG_a, "memory"
);
}
@@ -1210,12 +1211,19 @@ static inline void yuvPlanartopacked_mmxext(void (*pack_line)(uint8_t *, const u
for (int y = 0; y < height; y++) {
//FIXME handle 2 lines at once (fewer prefetches, reuse some chroma, but very likely memory-limited anyway)
if (chromWidth < 8) {
- ff_pack_yuv422_line(dst, ysrc, usrc, vsrc, 0, chromWidth, luma_first);
+ ff_pack_yuv422_line(dst, ysrc, usrc, vsrc, 0, width, luma_first);
} else {
pack_line(dst, ysrc, usrc, vsrc, chromWidth & ~7);
- if (chromWidth & 7) {
- x86_reg i = chromWidth - 8;
- pack_line(dst + 4 * i, ysrc + 2 * i, usrc + i, vsrc + i, 8);
+ if (width & 15) {
+ x86_reg i = ((width + 1) >> 1) - 8;
+ const uint8_t *y = ysrc + 2 * i;
+ uint8_t last[16];
+ if (width & 1) {
+ memcpy(last, y, 15);
+ last[15] = last[14];
+ y = last;
+ }
+ pack_line(dst + 4 * i, y, usrc + i, vsrc + i, 8);
}
}
if ((y&(vertLumPerChroma-1)) == vertLumPerChroma-1) {