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:
Ari Koivula 2013-10-11 15:19:21 +03:00
parent be501f720c
commit 69d1f6d1e2
2 changed files with 42 additions and 182 deletions

View file

@ -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;

View file

@ -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