mirror of
https://github.com/ultravideo/uvg266.git
synced 2024-12-02 21:24:07 +00:00
Rethink SAD-calculation.
This commit is contained in:
parent
1fcb452479
commit
0e078b2d18
85
src/search.c
85
src/search.c
|
@ -36,8 +36,8 @@
|
||||||
&& (x) + (block_width) <= (width) \
|
&& (x) + (block_width) <= (width) \
|
||||||
&& (y) + (block_height) <= (height))
|
&& (y) + (block_height) <= (height))
|
||||||
|
|
||||||
unsigned corner_sad(unsigned char* pic_data, unsigned char* ref_data,
|
unsigned cor_sad(unsigned char* pic_data, unsigned char* ref_data,
|
||||||
unsigned block_width, unsigned block_height, unsigned width)
|
unsigned block_width, unsigned block_height, unsigned width)
|
||||||
{
|
{
|
||||||
unsigned char ref = *ref_data;
|
unsigned char ref = *ref_data;
|
||||||
unsigned x, y;
|
unsigned x, y;
|
||||||
|
@ -52,8 +52,8 @@ unsigned corner_sad(unsigned char* pic_data, unsigned char* ref_data,
|
||||||
return sad;
|
return sad;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned vertical_sad(unsigned char* pic_data, unsigned char* ref_data,
|
unsigned ver_sad(unsigned char* pic_data, unsigned char* ref_data,
|
||||||
unsigned block_width, unsigned block_height, unsigned width)
|
unsigned block_width, unsigned block_height, unsigned width)
|
||||||
{
|
{
|
||||||
unsigned x, y;
|
unsigned x, y;
|
||||||
unsigned sad = 0;
|
unsigned sad = 0;
|
||||||
|
@ -67,8 +67,8 @@ unsigned vertical_sad(unsigned char* pic_data, unsigned char* ref_data,
|
||||||
return sad;
|
return sad;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned horizontal_sad(unsigned char* pic_data, unsigned char* ref_data,
|
unsigned hor_sad(unsigned char* pic_data, unsigned char* ref_data,
|
||||||
unsigned block_width, unsigned block_height, unsigned width)
|
unsigned block_width, unsigned block_height, unsigned width)
|
||||||
{
|
{
|
||||||
unsigned x, y;
|
unsigned x, y;
|
||||||
unsigned sad = 0;
|
unsigned sad = 0;
|
||||||
|
@ -103,72 +103,55 @@ unsigned get_block_sad(picture *pic, picture *ref,
|
||||||
int mv_y = ref_y - pic_y;
|
int mv_y = ref_y - pic_y;
|
||||||
int width = pic->width;
|
int width = pic->width;
|
||||||
int height = pic->height;
|
int height = pic->height;
|
||||||
int left = ref_x < 0;
|
|
||||||
int right = ref_x + block_width > width;
|
// These are the number of pixels by how far the movement vector points
|
||||||
int top = ref_y < 0;
|
// outside the frame. They are always >= 0. If all of them are 0, the
|
||||||
int bottom = ref_y + block_height > height;
|
// movement vector doesn't point outside the frame.
|
||||||
|
int left = (ref_x < 0) ? -ref_x : 0;
|
||||||
|
int top = (ref_y < 0) ? -ref_y : 0;
|
||||||
|
int right = (ref_x + block_width > width) ? ref_x - width : 0;
|
||||||
|
int bottom = (ref_y + block_height > height) ? ref_y - height : 0;
|
||||||
|
|
||||||
unsigned result = 0;
|
unsigned result = 0;
|
||||||
|
|
||||||
// Center both picture buffer and reference buffer to the picture block, so
|
// Center picture to the current block and reference to the point where
|
||||||
// that further references are relative to the block rather than the
|
// movement vector is pointing to. That point might be outside the buffer,
|
||||||
// top-left corner of the picture.
|
// but that is ok because we project the movement vector to the buffer
|
||||||
|
// before dereferencing the pointer.
|
||||||
pic_data = &pic->y_data[pic_y * width + pic_x];
|
pic_data = &pic->y_data[pic_y * width + pic_x];
|
||||||
ref_data = &ref->y_data[pic_y * width + pic_x];
|
ref_data = &ref->y_data[ref_y * width + ref_x];
|
||||||
|
|
||||||
// 0 means invalid, for now.
|
// 0 means invalid, for now.
|
||||||
//if (!IN_FRAME(ref_x, ref_y, width, height, block_width, block_height)) return 0;
|
//if (!IN_FRAME(ref_x, ref_y, width, height, block_width, block_height)) return 0;
|
||||||
|
|
||||||
|
// The handling of movement vectors that point outside the picture is done
|
||||||
|
// in the following way.
|
||||||
|
// - Correct the index of ref_data so that it points to the top-left
|
||||||
|
// of the area we want to compare against.
|
||||||
|
// - Correct the index of pic_data to point inside the current block, so
|
||||||
|
// that we compare the right part of the block to the ref_data.
|
||||||
|
// - Reduce block_width and block_height so that the the size of the area
|
||||||
|
// being compared is correct.
|
||||||
if (left && top) {
|
if (left && top) {
|
||||||
result += corner_sad(pic_data, ref_data,
|
|
||||||
-ref_x, -ref_y, width);
|
|
||||||
|
|
||||||
result += vertical_sad(&pic_data[-ref_x], ref_data,
|
|
||||||
block_width - -ref_x, -ref_y, width);
|
|
||||||
|
|
||||||
result += horizontal_sad(&pic_data[-ref_y * width], ref_data,
|
|
||||||
-ref_x, block_height - -ref_y, width);
|
|
||||||
|
|
||||||
result += sad(&pic_data[-ref_y * width + -ref_x], ref_data,
|
|
||||||
block_width - -ref_x, block_height - -ref_y, width);
|
|
||||||
} else if (top) {
|
|
||||||
|
|
||||||
} else if (top && right) {
|
} else if (top && right) {
|
||||||
|
|
||||||
|
} else if (top) {
|
||||||
|
|
||||||
|
} else if (bottom && left) {
|
||||||
|
|
||||||
|
} else if (bottom && right) {
|
||||||
|
|
||||||
} else if (left) {
|
} else if (left) {
|
||||||
|
|
||||||
} else if (right) {
|
} else if (right) {
|
||||||
|
|
||||||
} else if (bottom && left) {
|
|
||||||
|
|
||||||
} else if (bottom) {
|
} else if (bottom) {
|
||||||
|
|
||||||
} else if (bottom && right) {
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
result += sad(pic_data, &ref_data[mv_y * width + mv_x], block_width, block_height, width);
|
result += sad(pic_data, ref_data, block_width, block_height, width);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if USE_CHROMA_IN_MV_SEARCH
|
|
||||||
// Halve everything because chroma is half the resolution.
|
|
||||||
width >>= 2;
|
|
||||||
pic_x >>= 2;
|
|
||||||
pic_y >>= 2;
|
|
||||||
ref_x >>= 2;
|
|
||||||
ref_y >>= 2;
|
|
||||||
block >>= 2;
|
|
||||||
|
|
||||||
pic_data = &pic->u_data[pic_y * width + pic_x];
|
|
||||||
ref_data = &ref->u_data[ref_y * width + ref_x];
|
|
||||||
result += sad(pic_data, ref_data, block_width, block_height, width);
|
|
||||||
|
|
||||||
pic_data = &pic->v_data[pic_y * width + pic_x];
|
|
||||||
ref_data = &ref->v_data[ref_y * width + ref_x];
|
|
||||||
result += sad(pic_data, ref_data, block_width, block_height, width);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue