Commit ac3c8d99de for ffmpeg
commit ac3c8d99de53cf3a6ab3212e5584e97419f98ed9
Author: Niklas Haas <git@haasn.dev>
Date: Thu Oct 22 20:33:07 2026 +0200
swscale/tests/swscale: allow testing negative linesizes
A negative -align_src / -align_dst value now allocates the respective
buffers vertically flipped, with negative linesizes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Niklas Haas <git@haasn.dev>
diff --git a/libswscale/tests/swscale.c b/libswscale/tests/swscale.c
index 70ea5de2e1..49bfa2a053 100644
--- a/libswscale/tests/swscale.c
+++ b/libswscale/tests/swscale.c
@@ -235,6 +235,25 @@ static void unref_buffers(AVFrame *frame)
memset(frame->linesize, 0, sizeof(frame->linesize));
}
+/* A negative alignment allocates a vertically flipped (negative stride) frame */
+static int get_buffer(AVFrame *frame, int align)
+{
+ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format);
+ int ret = av_frame_get_buffer(frame, FFABS(align));
+ if (ret < 0 || align >= 0)
+ return ret;
+
+ for (int p = 0; p < av_pix_fmt_count_planes(frame->format); p++) {
+ const int is_chroma = p == 1 || p == 2;
+ const int h = is_chroma ? AV_CEIL_RSHIFT(frame->height, desc->log2_chroma_h)
+ : frame->height;
+ frame->data[p] += (h - 1) * frame->linesize[p];
+ frame->linesize[p] = -frame->linesize[p];
+ }
+
+ return 0;
+}
+
static int checked_sws_scale_frame(SwsContext *c, AVFrame *dst, const AVFrame *src)
{
int ret = sws_scale_frame(c, dst, src);
@@ -267,7 +286,7 @@ static int scale_new(AVFrame *dst, const AVFrame *src,
for (int i = 0; ret >= 0 && i < opts->iters; i++) {
unref_buffers(dst);
if (opts->align_dst) {
- ret = av_frame_get_buffer(dst, opts->align_dst);
+ ret = get_buffer(dst, opts->align_dst);
if (ret < 0)
return ret;
}
@@ -306,7 +325,7 @@ static int scale_legacy(AVFrame *dst, const AVFrame *src,
dst->width = sws_legacy->dst_w;
dst->height = sws_legacy->dst_h;
dst->format = sws_legacy->dst_format;
- ret = av_frame_get_buffer(dst, opts->align_dst);
+ ret = get_buffer(dst, opts->align_dst);
if (ret < 0)
goto error;
@@ -596,7 +615,7 @@ static int run_test(enum AVPixelFormat src_fmt, enum AVPixelFormat dst_fmt,
if (ret < 0)
goto error;
if (opts->align_src) {
- ret = av_frame_get_buffer(src, opts->align_src);
+ ret = get_buffer(src, opts->align_src);
if (ret < 0) {
av_frame_free(&src);
goto error;
@@ -968,8 +987,10 @@ static int parse_options(int argc, char **argv, struct options *opts, FILE **fp)
" Test with a specified scaler algorithm for chroma planes\n"
" -align_src <alignment>\n"
" If nonzero, allocate source buffers with a custom stride alignment\n"
+ " If negative, the buffers are also vertically flipped (negative stride)\n"
" -align_dst <alignment>\n"
" If nonzero, allocate destination buffers with a custom stride alignment\n"
+ " If negative, the buffers are also vertically flipped (negative stride)\n"
" -api <new or legacy>\n"
" Use selected swscale API for the main conversion (default: new)\n"
" -hw <device>\n"
@@ -1062,13 +1083,15 @@ static int parse_options(int argc, char **argv, struct options *opts, FILE **fp)
}
} else if (!strcmp(argv[i], "-align_src")) {
opts->align_src = atoi(argv[i + 1]);
- if (opts->align_src < 0 || (opts->align_src & (opts->align_src - 1))) {
+ const unsigned align = FFABSU(opts->align_src);
+ if (align > INT_MAX || (align & (align - 1))) {
fprintf(stderr, "invalid alignment %s\n", argv[i + 1]);
return -1;
}
} else if (!strcmp(argv[i], "-align_dst")) {
opts->align_dst = atoi(argv[i + 1]);
- if (opts->align_dst < 0 || (opts->align_dst & (opts->align_dst - 1))) {
+ const unsigned align = FFABSU(opts->align_dst);
+ if (align > INT_MAX || (align & (align - 1))) {
fprintf(stderr, "invalid alignment %s\n", argv[i + 1]);
return -1;
}