mirror of
https://github.com/ultravideo/uvg266.git
synced 2024-11-28 03:34:06 +00:00
Picture and reference may have different sizes
This commit is contained in:
parent
af9a1c0fbb
commit
2e7d958af3
141
src/picture.c
141
src/picture.c
|
@ -27,6 +27,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include "sao.h"
|
#include "sao.h"
|
||||||
|
|
||||||
|
@ -713,7 +714,7 @@ static unsigned sad_nxn_16bit(pixel *block1, pixel *block2, unsigned n)
|
||||||
* \returns Sum of Absolute Differences
|
* \returns Sum of Absolute Differences
|
||||||
*/
|
*/
|
||||||
static unsigned cor_sad(const pixel *pic_data, const pixel *ref_data,
|
static unsigned cor_sad(const pixel *pic_data, const pixel *ref_data,
|
||||||
int block_width, int block_height, unsigned width)
|
int block_width, int block_height, unsigned pic_width)
|
||||||
{
|
{
|
||||||
pixel ref = *ref_data;
|
pixel ref = *ref_data;
|
||||||
int x, y;
|
int x, y;
|
||||||
|
@ -721,7 +722,7 @@ static unsigned cor_sad(const pixel *pic_data, const pixel *ref_data,
|
||||||
|
|
||||||
for (y = 0; y < block_height; ++y) {
|
for (y = 0; y < block_height; ++y) {
|
||||||
for (x = 0; x < block_width; ++x) {
|
for (x = 0; x < block_width; ++x) {
|
||||||
sad += abs(pic_data[y * width + x] - ref);
|
sad += abs(pic_data[y * pic_width + x] - ref);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -740,14 +741,14 @@ static unsigned cor_sad(const pixel *pic_data, const pixel *ref_data,
|
||||||
* \returns Sum of Absolute Differences
|
* \returns Sum of Absolute Differences
|
||||||
*/
|
*/
|
||||||
static unsigned ver_sad(const pixel *pic_data, const pixel *ref_data,
|
static unsigned ver_sad(const pixel *pic_data, const pixel *ref_data,
|
||||||
int block_width, int block_height, unsigned width)
|
int block_width, int block_height, unsigned pic_width)
|
||||||
{
|
{
|
||||||
int x, y;
|
int x, y;
|
||||||
unsigned sad = 0;
|
unsigned sad = 0;
|
||||||
|
|
||||||
for (y = 0; y < block_height; ++y) {
|
for (y = 0; y < block_height; ++y) {
|
||||||
for (x = 0; x < block_width; ++x) {
|
for (x = 0; x < block_width; ++x) {
|
||||||
sad += abs(pic_data[y * width + x] - ref_data[x]);
|
sad += abs(pic_data[y * pic_width + x] - ref_data[x]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -766,14 +767,14 @@ static unsigned ver_sad(const pixel *pic_data, const pixel *ref_data,
|
||||||
* \returns Sum of Absolute Differences
|
* \returns Sum of Absolute Differences
|
||||||
*/
|
*/
|
||||||
static unsigned hor_sad(const pixel *pic_data, const pixel *ref_data,
|
static unsigned hor_sad(const pixel *pic_data, const pixel *ref_data,
|
||||||
int block_width, int block_height, unsigned width)
|
int block_width, int block_height, unsigned pic_width, unsigned ref_width)
|
||||||
{
|
{
|
||||||
int x, y;
|
int x, y;
|
||||||
unsigned sad = 0;
|
unsigned sad = 0;
|
||||||
|
|
||||||
for (y = 0; y < block_height; ++y) {
|
for (y = 0; y < block_height; ++y) {
|
||||||
for (x = 0; x < block_width; ++x) {
|
for (x = 0; x < block_width; ++x) {
|
||||||
sad += abs(pic_data[y * width + x] - ref_data[y * width]);
|
sad += abs(pic_data[y * pic_width + x] - ref_data[y * ref_width]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -795,14 +796,14 @@ static unsigned hor_sad(const pixel *pic_data, const pixel *ref_data,
|
||||||
* \returns Sum of Absolute Differences
|
* \returns Sum of Absolute Differences
|
||||||
*/
|
*/
|
||||||
static unsigned reg_sad(const pixel *data1, const pixel *data2,
|
static unsigned reg_sad(const pixel *data1, const pixel *data2,
|
||||||
int width, int height, unsigned stride)
|
int width, int height, unsigned stride1, unsigned stride2)
|
||||||
{
|
{
|
||||||
int y, x;
|
int y, x;
|
||||||
unsigned sad = 0;
|
unsigned sad = 0;
|
||||||
|
|
||||||
for (y = 0; y < height; ++y) {
|
for (y = 0; y < height; ++y) {
|
||||||
for (x = 0; x < width; ++x) {
|
for (x = 0; x < width; ++x) {
|
||||||
sad += abs((int)data1[y * stride + x] - (int)data2[y * stride + x]);
|
sad += abs((int)data1[y * stride1 + x] - (int)data2[y * stride2 + x]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -827,16 +828,14 @@ static unsigned interpolated_sad(const picture *pic, const picture *ref,
|
||||||
int block_width, int block_height)
|
int block_width, int block_height)
|
||||||
{
|
{
|
||||||
pixel *pic_data, *ref_data;
|
pixel *pic_data, *ref_data;
|
||||||
int width = pic->width;
|
|
||||||
int height = pic->height;
|
|
||||||
|
|
||||||
int left, right, top, bottom;
|
int left, right, top, bottom;
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
|
||||||
// Change the movement vector to point right next to the frame. This doesn't
|
// Change the movement vector to point right next to the frame. This doesn't
|
||||||
// affect the result but removes some special cases.
|
// affect the result but removes some special cases.
|
||||||
if (ref_x > width) ref_x = width;
|
if (ref_x > ref->width) ref_x = ref->width;
|
||||||
if (ref_y > height) ref_y = height;
|
if (ref_y > ref->height) ref_y = ref->height;
|
||||||
if (ref_x + block_width < 0) ref_x = -block_width;
|
if (ref_x + block_width < 0) ref_x = -block_width;
|
||||||
if (ref_y + block_height < 0) ref_y = -block_height;
|
if (ref_y + block_height < 0) ref_y = -block_height;
|
||||||
|
|
||||||
|
@ -845,15 +844,15 @@ static unsigned interpolated_sad(const picture *pic, const picture *ref,
|
||||||
// movement vector doesn't point outside the frame.
|
// movement vector doesn't point outside the frame.
|
||||||
left = (ref_x < 0) ? -ref_x : 0;
|
left = (ref_x < 0) ? -ref_x : 0;
|
||||||
top = (ref_y < 0) ? -ref_y : 0;
|
top = (ref_y < 0) ? -ref_y : 0;
|
||||||
right = (ref_x + block_width > width) ? ref_x + block_width - width : 0;
|
right = (ref_x + block_width > ref->width) ? ref_x + block_width - ref->width : 0;
|
||||||
bottom = (ref_y + block_height > height) ? ref_y + block_height - height : 0;
|
bottom = (ref_y + block_height > ref->height) ? ref_y + block_height - ref->height : 0;
|
||||||
|
|
||||||
// Center picture to the current block and reference to the point where
|
// Center picture to the current block and reference to the point where
|
||||||
// movement vector is pointing to. That point might be outside the buffer,
|
// movement vector is pointing to. That point might be outside the buffer,
|
||||||
// but that is ok because we project the movement vector to the buffer
|
// but that is ok because we project the movement vector to the buffer
|
||||||
// before dereferencing the pointer.
|
// before dereferencing the pointer.
|
||||||
pic_data = &pic->y_data[pic_y * width + pic_x];
|
pic_data = &pic->y_data[pic_y * pic->width + pic_x];
|
||||||
ref_data = &ref->y_data[ref_y * width + ref_x];
|
ref_data = &ref->y_data[ref_y * ref->width + ref_x];
|
||||||
|
|
||||||
// The handling of movement vectors that point outside the picture is done
|
// The handling of movement vectors that point outside the picture is done
|
||||||
// in the following way.
|
// in the following way.
|
||||||
|
@ -865,86 +864,86 @@ static unsigned interpolated_sad(const picture *pic, const picture *ref,
|
||||||
// being compared is correct.
|
// being compared is correct.
|
||||||
if (top && left) {
|
if (top && left) {
|
||||||
result += cor_sad(pic_data,
|
result += cor_sad(pic_data,
|
||||||
&ref_data[top * width + left],
|
&ref_data[top * ref->width + left],
|
||||||
left, top, width);
|
left, top, pic->width);
|
||||||
result += ver_sad(&pic_data[left],
|
result += ver_sad(&pic_data[left],
|
||||||
&ref_data[top * width + left],
|
&ref_data[top * ref->width + left],
|
||||||
block_width - left, top, width);
|
block_width - left, top, pic->width);
|
||||||
result += hor_sad(&pic_data[top * width],
|
result += hor_sad(&pic_data[top * pic->width],
|
||||||
&ref_data[top * width + left],
|
&ref_data[top * ref->width + left],
|
||||||
left, block_height - top, width);
|
left, block_height - top, pic->width, ref->width);
|
||||||
result += reg_sad(&pic_data[top * width + left],
|
result += reg_sad(&pic_data[top * pic->width + left],
|
||||||
&ref_data[top * width + left],
|
&ref_data[top * ref->width + left],
|
||||||
block_width - left, block_height - top, width);
|
block_width - left, block_height - top, pic->width, ref->width);
|
||||||
} else if (top && right) {
|
} else if (top && right) {
|
||||||
result += ver_sad(pic_data,
|
result += ver_sad(pic_data,
|
||||||
&ref_data[top * width],
|
&ref_data[top * ref->width],
|
||||||
block_width - right, top, width);
|
block_width - right, top, pic->width);
|
||||||
result += cor_sad(&pic_data[block_width - right],
|
result += cor_sad(&pic_data[block_width - right],
|
||||||
&ref_data[top * width + (block_width - right - 1)],
|
&ref_data[top * ref->width + (block_width - right - 1)],
|
||||||
right, top, width);
|
right, top, pic->width);
|
||||||
result += reg_sad(&pic_data[top * width],
|
result += reg_sad(&pic_data[top * pic->width],
|
||||||
&ref_data[top * width],
|
&ref_data[top * ref->width],
|
||||||
block_width - right, block_height - top, width);
|
block_width - right, block_height - top, pic->width, ref->width);
|
||||||
result += hor_sad(&pic_data[top * width + (block_width - right)],
|
result += hor_sad(&pic_data[top * pic->width + (block_width - right)],
|
||||||
&ref_data[top * width + (block_width - right - 1)],
|
&ref_data[top * ref->width + (block_width - right - 1)],
|
||||||
right, block_height - top, width);
|
right, block_height - top, pic->width, ref->width);
|
||||||
} else if (bottom && left) {
|
} else if (bottom && left) {
|
||||||
result += hor_sad(pic_data,
|
result += hor_sad(pic_data,
|
||||||
&ref_data[left],
|
&ref_data[left],
|
||||||
left, block_height - bottom, width);
|
left, block_height - bottom, pic->width, ref->width);
|
||||||
result += reg_sad(&pic_data[left],
|
result += reg_sad(&pic_data[left],
|
||||||
&ref_data[left],
|
&ref_data[left],
|
||||||
block_width - left, block_height - bottom, width);
|
block_width - left, block_height - bottom, pic->width, ref->width);
|
||||||
result += cor_sad(&pic_data[(block_height - bottom) * width],
|
result += cor_sad(&pic_data[(block_height - bottom) * pic->width],
|
||||||
&ref_data[(block_height - bottom - 1) * width + left],
|
&ref_data[(block_height - bottom - 1) * ref->width + left],
|
||||||
left, bottom, width);
|
left, bottom, pic->width);
|
||||||
result += ver_sad(&pic_data[(block_height - bottom) * width + left],
|
result += ver_sad(&pic_data[(block_height - bottom) * pic->width + left],
|
||||||
&ref_data[(block_height - bottom - 1) * width + left],
|
&ref_data[(block_height - bottom - 1) * ref->width + left],
|
||||||
block_width - left, bottom, width);
|
block_width - left, bottom, pic->width);
|
||||||
} else if (bottom && right) {
|
} else if (bottom && right) {
|
||||||
result += reg_sad(pic_data,
|
result += reg_sad(pic_data,
|
||||||
ref_data,
|
ref_data,
|
||||||
block_width - right, block_height - bottom, width);
|
block_width - right, block_height - bottom, pic->width, ref->width);
|
||||||
result += hor_sad(&pic_data[block_width - right],
|
result += hor_sad(&pic_data[block_width - right],
|
||||||
&ref_data[block_width - right - 1],
|
&ref_data[block_width - right - 1],
|
||||||
right, block_height - bottom, width);
|
right, block_height - bottom, pic->width, ref->width);
|
||||||
result += ver_sad(&pic_data[(block_height - bottom) * width],
|
result += ver_sad(&pic_data[(block_height - bottom) * pic->width],
|
||||||
&ref_data[(block_height - bottom - 1) * width],
|
&ref_data[(block_height - bottom - 1) * ref->width],
|
||||||
block_width - right, bottom, width);
|
block_width - right, bottom, pic->width);
|
||||||
result += cor_sad(&pic_data[(block_height - bottom) * width + block_width - right],
|
result += cor_sad(&pic_data[(block_height - bottom) * pic->width + block_width - right],
|
||||||
&ref_data[(block_height - bottom - 1) * width + block_width - right - 1],
|
&ref_data[(block_height - bottom - 1) * ref->width + block_width - right - 1],
|
||||||
right, bottom, width);
|
right, bottom, pic->width);
|
||||||
} else if (top) {
|
} else if (top) {
|
||||||
result += ver_sad(pic_data,
|
result += ver_sad(pic_data,
|
||||||
&ref_data[top * width],
|
&ref_data[top * ref->width],
|
||||||
block_width, top, width);
|
block_width, top, pic->width);
|
||||||
result += reg_sad(&pic_data[top * width],
|
result += reg_sad(&pic_data[top * pic->width],
|
||||||
&ref_data[top * width],
|
&ref_data[top * ref->width],
|
||||||
block_width, block_height - top, width);
|
block_width, block_height - top, pic->width, ref->width);
|
||||||
} else if (bottom) {
|
} else if (bottom) {
|
||||||
result += reg_sad(pic_data,
|
result += reg_sad(pic_data,
|
||||||
ref_data,
|
ref_data,
|
||||||
block_width, block_height - bottom, width);
|
block_width, block_height - bottom, pic->width, ref->width);
|
||||||
result += ver_sad(&pic_data[(block_height - bottom) * width],
|
result += ver_sad(&pic_data[(block_height - bottom) * pic->width],
|
||||||
&ref_data[(block_height - bottom - 1) * width],
|
&ref_data[(block_height - bottom - 1) * ref->width],
|
||||||
block_width, bottom, width);
|
block_width, bottom, pic->width);
|
||||||
} else if (left) {
|
} else if (left) {
|
||||||
result += hor_sad(pic_data,
|
result += hor_sad(pic_data,
|
||||||
&ref_data[left],
|
&ref_data[left],
|
||||||
left, block_height, width);
|
left, block_height, pic->width, ref->width);
|
||||||
result += reg_sad(&pic_data[left],
|
result += reg_sad(&pic_data[left],
|
||||||
&ref_data[left],
|
&ref_data[left],
|
||||||
block_width - left, block_height, width);
|
block_width - left, block_height, pic->width, ref->width);
|
||||||
} else if (right) {
|
} else if (right) {
|
||||||
result += reg_sad(pic_data,
|
result += reg_sad(pic_data,
|
||||||
ref_data,
|
ref_data,
|
||||||
block_width - right, block_height, width);
|
block_width - right, block_height, pic->width, ref->width);
|
||||||
result += hor_sad(&pic_data[block_width - right],
|
result += hor_sad(&pic_data[block_width - right],
|
||||||
&ref_data[block_width - right - 1],
|
&ref_data[block_width - right - 1],
|
||||||
right, block_height, width);
|
right, block_height, pic->width, ref->width);
|
||||||
} else {
|
} else {
|
||||||
result += reg_sad(pic_data, ref_data, block_width, block_height, width);
|
result += reg_sad(pic_data, ref_data, block_width, block_height, pic->width, ref->width);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -967,14 +966,16 @@ unsigned calc_sad(const picture *pic, const picture *ref,
|
||||||
int pic_x, int pic_y, int ref_x, int ref_y,
|
int pic_x, int pic_y, int ref_x, int ref_y,
|
||||||
int block_width, int block_height)
|
int block_width, int block_height)
|
||||||
{
|
{
|
||||||
if (ref_x >= 0 && ref_x <= pic->width - block_width &&
|
assert(pic_x >= 0 && pic_x <= pic->width - block_width);
|
||||||
ref_y >= 0 && ref_y <= pic->height - block_height)
|
assert(pic_y >= 0 && pic_y <= pic->height - block_height);
|
||||||
|
if (ref_x >= 0 && ref_x <= ref->width - block_width &&
|
||||||
|
ref_y >= 0 && ref_y <= ref->height - block_height)
|
||||||
{
|
{
|
||||||
// Reference block is completely inside the frame, so just calculate the
|
// Reference block is completely inside the frame, so just calculate the
|
||||||
// SAD directly. This is the most common case, which is why it's first.
|
// SAD directly. This is the most common case, which is why it's first.
|
||||||
const pixel *pic_data = &pic->y_data[pic_y * pic->width + pic_x];
|
const pixel *pic_data = &pic->y_data[pic_y * pic->width + pic_x];
|
||||||
const pixel *ref_data = &ref->y_data[ref_y * pic->width + ref_x];
|
const pixel *ref_data = &ref->y_data[ref_y * ref->width + ref_x];
|
||||||
return reg_sad(pic_data, ref_data, block_width, block_height, pic->width);
|
return reg_sad(pic_data, ref_data, block_width, block_height, pic->width, ref->width);
|
||||||
} else {
|
} else {
|
||||||
// Call a routine that knows how to interpolate pixels outside the frame.
|
// Call a routine that knows how to interpolate pixels outside the frame.
|
||||||
return interpolated_sad(pic, ref, pic_x, pic_y, ref_x, ref_y, block_width, block_height);
|
return interpolated_sad(pic, ref, pic_x, pic_y, ref_x, ref_y, block_width, block_height);
|
||||||
|
|
Loading…
Reference in a new issue