Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions libvmaf/src/feature/arm64/motion_neon.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,18 @@

static inline int mirror(int idx, int size)
{
if (idx < 0) return -idx;
if (idx >= size) return 2 * size - idx - 2;
// Reflect out of range indices back into [0, size) using the same
// reflect 101 boundary the five tap motion filter expects (the edge
// sample is never repeated). One reflection is not enough when size
// is below 3, so fold repeatedly until the index lands in range.
if (size == 1)
return 0;
while (idx < 0 || idx >= size) {
if (idx < 0)
idx = -idx;
if (idx >= size)
idx = 2 * size - idx - 2;
}
return idx;
}

Expand Down
14 changes: 12 additions & 2 deletions libvmaf/src/feature/integer_motion.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,18 @@ static const VmafOption options[] = {

static inline int mirror(int idx, int size)
{
if (idx < 0) return -idx;
if (idx >= size) return 2 * size - idx - 2;
// Reflect out of range indices back into [0, size) using the same
// reflect 101 boundary the five tap motion filter expects (the edge
// sample is never repeated). One reflection is not enough when size
// is below 3, so fold repeatedly until the index lands in range.
if (size == 1)
return 0;
while (idx < 0 || idx >= size) {
if (idx < 0)
idx = -idx;
if (idx >= size)
idx = 2 * size - idx - 2;
}
return idx;
}

Expand Down
14 changes: 12 additions & 2 deletions libvmaf/src/feature/x86/motion_avx2.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,18 @@

static inline int mirror(int idx, int size)
{
if (idx < 0) return -idx;
if (idx >= size) return 2 * size - idx - 2;
// Reflect out of range indices back into [0, size) using the same
// reflect 101 boundary the five tap motion filter expects (the edge
// sample is never repeated). One reflection is not enough when size
// is below 3, so fold repeatedly until the index lands in range.
if (size == 1)
return 0;
while (idx < 0 || idx >= size) {
if (idx < 0)
idx = -idx;
if (idx >= size)
idx = 2 * size - idx - 2;
}
return idx;
}

Expand Down
14 changes: 12 additions & 2 deletions libvmaf/src/feature/x86/motion_avx512.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,18 @@

static inline int mirror(int idx, int size)
{
if (idx < 0) return -idx;
if (idx >= size) return 2 * size - idx - 2;
// Reflect out of range indices back into [0, size) using the same
// reflect 101 boundary the five tap motion filter expects (the edge
// sample is never repeated). One reflection is not enough when size
// is below 3, so fold repeatedly until the index lands in range.
if (size == 1)
return 0;
while (idx < 0 || idx >= size) {
if (idx < 0)
idx = -idx;
if (idx >= size)
idx = 2 * size - idx - 2;
}
return idx;
}

Expand Down
6 changes: 4 additions & 2 deletions libvmaf/test/test_motion_neon.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,11 @@ static int compute_motion_sad(unsigned w, unsigned h,

static char *test_motion_neon_matches_scalar()
{
// w/h < 3 excluded: mirror()'s radius-2 reflection goes out of bounds there
// (same bug in scalar/AVX2), so those sizes compare garbage against garbage.
// Sizes with width or height 1 or 2 are the regression case for issue
// 1580: mirror()'s reflection used to read out of bounds there. With the
// bounded reflection scalar and NEON must still agree bit exactly.
static const struct { unsigned w, h; } sizes[] = {
{1, 1}, {2, 2}, {1, 2}, {2, 1}, {1, 5}, {5, 1}, {2, 5}, {5, 2},
{3, 3}, {4, 4}, {5, 5}, {7, 7}, {9, 9},
{15, 15}, {16, 16}, {17, 17}, {20, 4}, {33, 9}, {64, 48}, {65, 63},
};
Expand Down