mirror of
https://github.com/ultravideo/uvg266.git
synced 2024-11-23 18:14:06 +00:00
Clean up the code.
- Rename get_block_sad to calc_sad and handle special cases in general_sad. - Remove old search functions because I don't want to update or test them.
This commit is contained in:
parent
be501f720c
commit
69d1f6d1e2
216
src/search.c
216
src/search.c
|
@ -28,7 +28,6 @@
|
|||
#define USE_INTRA_IN_P 0
|
||||
//#define RENDER_CU encoder->frame==2
|
||||
#define RENDER_CU 0
|
||||
#define USE_FULL_SEARCH 0
|
||||
#define USE_CHROMA_IN_MV_SEARCH 0
|
||||
|
||||
#define IN_FRAME(x, y, width, height, block_width, block_height) \
|
||||
|
@ -48,13 +47,11 @@
|
|||
* \param block_width Width of the blocks.
|
||||
* \param block_height Height of the blocks.
|
||||
*/
|
||||
unsigned get_block_sad(picture *pic, picture *ref,
|
||||
int pic_x, int pic_y, int ref_x, int ref_y,
|
||||
int block_width, int block_height)
|
||||
unsigned general_sad(picture *pic, picture *ref,
|
||||
int pic_x, int pic_y, int ref_x, int ref_y,
|
||||
int block_width, int block_height)
|
||||
{
|
||||
uint8_t *pic_data, *ref_data;
|
||||
int mv_x = ref_x - pic_x;
|
||||
int mv_y = ref_y - pic_y;
|
||||
int width = pic->width;
|
||||
int height = pic->height;
|
||||
|
||||
|
@ -75,9 +72,6 @@ unsigned get_block_sad(picture *pic, picture *ref,
|
|||
pic_data = &pic->y_data[pic_y * width + pic_x];
|
||||
ref_data = &ref->y_data[ref_y * width + ref_x];
|
||||
|
||||
// 0 means invalid, for now.
|
||||
//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
|
||||
|
@ -173,6 +167,23 @@ unsigned get_block_sad(picture *pic, picture *ref,
|
|||
return result;
|
||||
}
|
||||
|
||||
|
||||
unsigned calc_sad(picture *pic, picture *ref,
|
||||
int pic_x, int pic_y, int ref_x, int ref_y,
|
||||
int block_width, int block_height)
|
||||
{
|
||||
if (ref_x >= 0 && ref_x <= pic->width - block_width &&
|
||||
ref_y >= 0 && ref_y <= pic->height - block_height)
|
||||
{
|
||||
uint8_t *pic_data = &pic->y_data[pic_y * pic->width + pic_x];
|
||||
uint8_t *ref_data = &ref->y_data[ref_y * pic->width + ref_x];
|
||||
reg_sad(pic_data, ref_data, block_width, block_height, pic->width);
|
||||
} else {
|
||||
return general_sad(pic, ref, pic_x, pic_y, ref_x, ref_y, block_width, block_height);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
typedef struct {
|
||||
int x;
|
||||
int y;
|
||||
|
@ -217,9 +228,9 @@ void hexagon_search(picture *pic, picture *ref,
|
|||
// Search the initial 7 points of the hexagon.
|
||||
for (i = 0; i < 7; ++i) {
|
||||
const vector2d *pattern = large_hexbs + i;
|
||||
unsigned cost = get_block_sad(pic, ref, orig_x, orig_y,
|
||||
orig_x + x + pattern->x, orig_y + y + pattern->y,
|
||||
block_width, block_width);
|
||||
unsigned cost = calc_sad(pic, ref, orig_x, orig_y,
|
||||
orig_x + x + pattern->x, orig_y + y + pattern->y,
|
||||
block_width, block_width);
|
||||
if (cost > 0 && cost < best_cost) {
|
||||
best_cost = cost;
|
||||
best_index = i;
|
||||
|
@ -228,9 +239,9 @@ void hexagon_search(picture *pic, picture *ref,
|
|||
|
||||
// Try the 0,0 vector.
|
||||
if (!(x == 0 && y == 0)) {
|
||||
unsigned cost = get_block_sad(pic, ref, orig_x, orig_y,
|
||||
orig_x, orig_y,
|
||||
block_width, block_width);
|
||||
unsigned cost = calc_sad(pic, ref, orig_x, orig_y,
|
||||
orig_x, orig_y,
|
||||
block_width, block_width);
|
||||
if (cost > 0 && cost < best_cost) {
|
||||
best_cost = cost;
|
||||
best_index = 0;
|
||||
|
@ -240,9 +251,9 @@ void hexagon_search(picture *pic, picture *ref,
|
|||
// Redo the search around the 0,0 point.
|
||||
for (i = 1; i < 7; ++i) {
|
||||
const vector2d *pattern = large_hexbs + i;
|
||||
unsigned cost = get_block_sad(pic, ref, orig_x, orig_y,
|
||||
orig_x + pattern->x, orig_y + pattern->y,
|
||||
block_width, block_width);
|
||||
unsigned cost = calc_sad(pic, ref, orig_x, orig_y,
|
||||
orig_x + pattern->x, orig_y + pattern->y,
|
||||
block_width, block_width);
|
||||
if (cost > 0 && cost < best_cost) {
|
||||
best_cost = cost;
|
||||
best_index = i;
|
||||
|
@ -271,9 +282,9 @@ void hexagon_search(picture *pic, picture *ref,
|
|||
// Iterate through the next 3 points.
|
||||
for (i = 0; i < 3; ++i) {
|
||||
const vector2d *offset = large_hexbs + start + i;
|
||||
unsigned cost = get_block_sad(pic, ref, orig_x, orig_y,
|
||||
orig_x + x + offset->x, orig_y + y + offset->y,
|
||||
block_width, block_width);
|
||||
unsigned cost = calc_sad(pic, ref, orig_x, orig_y,
|
||||
orig_x + x + offset->x, orig_y + y + offset->y,
|
||||
block_width, block_width);
|
||||
if (cost > 0 && cost < best_cost) {
|
||||
best_cost = cost;
|
||||
best_index = start + i;
|
||||
|
@ -288,9 +299,9 @@ void hexagon_search(picture *pic, picture *ref,
|
|||
best_index = 0;
|
||||
for (i = 1; i < 5; ++i) {
|
||||
const vector2d *offset = small_hexbs + i;
|
||||
unsigned cost = get_block_sad(pic, ref, orig_x, orig_y,
|
||||
orig_x + x + offset->x, orig_y + y + offset->y,
|
||||
block_width, block_width);
|
||||
unsigned cost = calc_sad(pic, ref, orig_x, orig_y,
|
||||
orig_x + x + offset->x, orig_y + y + offset->y,
|
||||
block_width, block_width);
|
||||
if (cost > 0 && cost < best_cost) {
|
||||
best_cost = cost;
|
||||
best_index = i;
|
||||
|
@ -305,146 +316,6 @@ void hexagon_search(picture *pic, picture *ref,
|
|||
cur_cu->inter.mv[1] = y << 2;
|
||||
}
|
||||
|
||||
void search_mv(picture *pic, picture *ref,
|
||||
cu_info *cur_cu, int orig_x, int orig_y, int x, int y,
|
||||
unsigned depth)
|
||||
{
|
||||
int block_width = CU_WIDTH_FROM_DEPTH(depth);
|
||||
|
||||
// Get cost for the predicted motion vector.
|
||||
unsigned cost = get_block_sad(pic, ref, orig_x, orig_y, orig_x + x, orig_y + y,
|
||||
block_width, block_width);
|
||||
unsigned best_cost = -1;
|
||||
unsigned step = 8;
|
||||
|
||||
if (cost > 0) {
|
||||
best_cost = cost;
|
||||
cur_cu->inter.mv[0] = x;
|
||||
cur_cu->inter.mv[1] = y;
|
||||
}
|
||||
|
||||
// If initial vector is long, also try the (0, 0) vector just in case.
|
||||
if (x != 0 || y != 0) {
|
||||
cost = get_block_sad(pic, ref, orig_x, orig_y, orig_x, orig_y,
|
||||
block_width, block_width);
|
||||
|
||||
if (cost > 0 && cost < best_cost) {
|
||||
best_cost = cost;
|
||||
cur_cu->inter.mv[0] = 0;
|
||||
cur_cu->inter.mv[1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
while (step > 0) {
|
||||
// Stop if current best vector is already really good.
|
||||
// This is an experimental condition.
|
||||
// The constant 1.8 is there because there is some SAD cost when comparing
|
||||
// against the reference even if the frame doesn't change. This is probably
|
||||
// due to quantization. It's value is just a guess based on the first
|
||||
// blocks of the BQMall sequence, which don't move.
|
||||
// TODO: Quantization factor probably affects what the constant should be.
|
||||
/*
|
||||
if (best_cost <= block_width * block_width * 1.8) {
|
||||
break;
|
||||
}
|
||||
*/
|
||||
|
||||
// Change center of search to the current best point.
|
||||
x = cur_cu->inter.mv[0];
|
||||
y = cur_cu->inter.mv[1];
|
||||
|
||||
// above
|
||||
cost = get_block_sad(pic, ref, orig_x, orig_y,
|
||||
orig_x + x, orig_y + y - step,
|
||||
block_width, block_width);
|
||||
if (cost > 0 && cost < best_cost) {
|
||||
best_cost = cost;
|
||||
cur_cu->inter.mv[0] = x;
|
||||
cur_cu->inter.mv[1] = y - step;
|
||||
}
|
||||
|
||||
// left
|
||||
cost = get_block_sad(pic, ref, orig_x, orig_y,
|
||||
orig_x + x - step, orig_y + y,
|
||||
block_width, block_width);
|
||||
if (cost > 0 && cost < best_cost) {
|
||||
best_cost = cost;
|
||||
cur_cu->inter.mv[0] = x - step;
|
||||
cur_cu->inter.mv[1] = y;
|
||||
}
|
||||
|
||||
// right
|
||||
cost = get_block_sad(pic, ref, orig_x, orig_y,
|
||||
orig_x + x + step, orig_y + y,
|
||||
block_width, block_width);
|
||||
if (cost > 0 && cost < best_cost) {
|
||||
best_cost = cost;
|
||||
cur_cu->inter.mv[0] = x + step;
|
||||
cur_cu->inter.mv[1] = y;
|
||||
}
|
||||
|
||||
// below
|
||||
cost = get_block_sad(pic, ref, orig_x, orig_y,
|
||||
orig_x + x, orig_y + y + step,
|
||||
block_width, block_width);
|
||||
if (cost > 0 && cost < best_cost) {
|
||||
best_cost = cost;
|
||||
cur_cu->inter.mv[0] = x;
|
||||
cur_cu->inter.mv[1] = y + step;
|
||||
}
|
||||
|
||||
// Reduce search area by half.
|
||||
step /= 2;
|
||||
}
|
||||
|
||||
cur_cu->inter.cost = best_cost + 1; // +1 so that cost is > 0.
|
||||
cur_cu->inter.mv[0] <<= 2;
|
||||
cur_cu->inter.mv[1] <<= 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Search motions vectors for a block and all it's sub-blocks.
|
||||
*
|
||||
* \param pic
|
||||
* \param pic_data picture color data starting from the block MV is being searched for.
|
||||
* \param ref_data picture color data starting from the beginning of reference pic.
|
||||
* \param cur_cu
|
||||
*/
|
||||
void search_mv_full(picture *pic, uint8_t *pic_data, uint8_t *ref_data,
|
||||
cu_info *cur_cu, unsigned step,
|
||||
int orig_x, int orig_y, int x, int y, unsigned depth)
|
||||
{
|
||||
// TODO: Inter: Handle non-square blocks.
|
||||
int block_width = CU_WIDTH_FROM_DEPTH(depth);
|
||||
int block_height = block_width;
|
||||
unsigned cost;
|
||||
|
||||
// TODO: Inter: Calculating error outside picture borders.
|
||||
// This prevents choosing vectors that need interpolating of borders to work.
|
||||
if (orig_x + x < 0 || orig_y + y < 0 || orig_x + x > pic->width - block_width
|
||||
|| orig_y + y > pic->height - block_height) return;
|
||||
|
||||
cost = reg_sad(pic_data, &ref_data[(orig_y + y) * pic->width + (orig_x + x)],
|
||||
block_width, block_height, pic->width) + 1;
|
||||
if (cost < cur_cu->inter.cost) {
|
||||
cur_cu->inter.cost = cost;
|
||||
cur_cu->inter.mv[0] = x << 2;
|
||||
cur_cu->inter.mv[1] = y << 2;
|
||||
}
|
||||
|
||||
step /= 2;
|
||||
if (step > 0) {
|
||||
search_mv_full(pic, pic_data, ref_data, cur_cu, step, orig_x, orig_y,
|
||||
x, y - step, depth);
|
||||
search_mv_full(pic, pic_data, ref_data, cur_cu, step, orig_x, orig_y,
|
||||
x - step, y, depth);
|
||||
search_mv_full(pic, pic_data, ref_data, cur_cu, step, orig_x, orig_y,
|
||||
x + step, y, depth);
|
||||
search_mv_full(pic, pic_data, ref_data, cur_cu, step, orig_x, orig_y,
|
||||
x, y + step, depth);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief
|
||||
*/
|
||||
|
@ -586,20 +457,9 @@ void search_tree(encoder_control *encoder,
|
|||
start_y = ref_cu->inter.mv[1] >> 2;
|
||||
}
|
||||
|
||||
if (USE_FULL_SEARCH) {
|
||||
search_mv_full(cur_pic, cur_data, ref_pic->y_data,
|
||||
cur_cu, 8, x, y,
|
||||
start_x, start_y, depth);
|
||||
} else {
|
||||
/*
|
||||
search_mv(cur_pic, ref_pic,
|
||||
cur_cu, x, y,
|
||||
start_x, start_y, depth);
|
||||
*/
|
||||
hexagon_search(cur_pic, ref_pic,
|
||||
cur_cu, x, y,
|
||||
start_x, start_y, depth);
|
||||
}
|
||||
hexagon_search(cur_pic, ref_pic,
|
||||
cur_cu, x, y,
|
||||
start_x, start_y, depth);
|
||||
}
|
||||
|
||||
cur_cu->type = CU_INTER;
|
||||
|
|
|
@ -6,13 +6,13 @@
|
|||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EXTERNAL FUNCTIONS
|
||||
unsigned get_block_sad(picture *pic, picture *ref,
|
||||
int pic_x, int pic_y, int ref_x, int ref_y,
|
||||
int block_width, int block_height);
|
||||
unsigned calc_sad(picture *pic, picture *ref,
|
||||
int pic_x, int pic_y, int ref_x, int ref_y,
|
||||
int block_width, int block_height);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// DEFINES
|
||||
#define TEST_SAD(X, Y) get_block_sad(g_pic, g_ref, 0, 0, (X), (Y), 8, 8)
|
||||
#define TEST_SAD(X, Y) calc_sad(g_pic, g_ref, 0, 0, (X), (Y), 8, 8)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// GLOBALS
|
||||
|
|
Loading…
Reference in a new issue