mirror of
https://github.com/ultravideo/uvg266.git
synced 2024-11-27 19:24:06 +00:00
Add a more general cost function to motion search.
This commit is contained in:
parent
562a43d541
commit
571fec7c39
86
src/search.c
86
src/search.c
|
@ -28,24 +28,71 @@
|
|||
#define USE_INTRA_IN_P 0
|
||||
#define RENDER_CU 0
|
||||
#define USE_FULL_SEARCH 0
|
||||
#define USE_CHROMA_IN_MV_SEARCH 0
|
||||
|
||||
#define IN_FRAME(x, y, width, height, block) ((x) >= 0 && (y) >= 0 && (x) + (block) <= (width) && (y) + (block) <= (height))
|
||||
|
||||
|
||||
unsigned get_sad(int x, int y, int width, int height, int block, uint8_t *pic_data, uint8_t *ref_data)
|
||||
/**
|
||||
* \brief Get Sum of Absolute Differences (SAD) between two blocks in two
|
||||
* different frames.
|
||||
* \param pic First frame.
|
||||
* \param ref Second frame.
|
||||
* \param pic_x X coordinate of the first block.
|
||||
* \param pic_y Y coordinate of the first block.
|
||||
* \param ref_x X coordinate of the second block.
|
||||
* \param ref_y Y coordinate of the second block.
|
||||
* \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)
|
||||
{
|
||||
if (!IN_FRAME(x, y, width, height, block)) return 0; // This means invalid, for now.
|
||||
uint8_t *pic_data, *ref_data;
|
||||
int width = pic->width;
|
||||
int height = pic->height;
|
||||
int block = pic->width;
|
||||
|
||||
return 1 + sad(pic_data, &ref_data[y * width + x], block, block, width);
|
||||
unsigned result = 1; // Start from 1 so result is never 0.
|
||||
|
||||
// 0 means invalid, for now.
|
||||
if (!IN_FRAME(ref_x, ref_y, width, height, block)) return 0;
|
||||
|
||||
pic_data = &pic->y_data[pic_y * width + pic_x];
|
||||
ref_data = &ref->y_data[ref_y * width + ref_x];
|
||||
result += sad(pic_data, ref_data, block, block, 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, block, 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, block, width);
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void search_mv(picture *pic, uint8_t *pic_data, uint8_t *ref_data,
|
||||
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);
|
||||
|
||||
unsigned cost = get_sad(orig_x + x, orig_y + y, pic->width, pic->height, block_width, pic_data, ref_data);
|
||||
// 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;
|
||||
|
||||
|
@ -57,7 +104,8 @@ void search_mv(picture *pic, uint8_t *pic_data, uint8_t *ref_data,
|
|||
|
||||
// If initial vector is long, also try the (0, 0) vector just in case.
|
||||
if (x != 0 || y != 0) {
|
||||
cost = get_sad(orig_x, orig_y, pic->width, pic->height, block_width, pic_data, ref_data);
|
||||
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;
|
||||
|
@ -85,7 +133,9 @@ void search_mv(picture *pic, uint8_t *pic_data, uint8_t *ref_data,
|
|||
y = cur_cu->inter.mv[1];
|
||||
|
||||
// above
|
||||
cost = get_sad(orig_x + x, orig_y + y - step, pic->width, pic->height, block_width, pic_data, ref_data);
|
||||
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;
|
||||
|
@ -93,7 +143,9 @@ void search_mv(picture *pic, uint8_t *pic_data, uint8_t *ref_data,
|
|||
}
|
||||
|
||||
// left
|
||||
cost = get_sad(orig_x + x - step, orig_y + y, pic->width, pic->height, block_width, pic_data, ref_data);
|
||||
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;
|
||||
|
@ -101,7 +153,9 @@ void search_mv(picture *pic, uint8_t *pic_data, uint8_t *ref_data,
|
|||
}
|
||||
|
||||
// right
|
||||
cost = get_sad(orig_x + x + step, orig_y + y, pic->width, pic->height, block_width, pic_data, ref_data);
|
||||
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;
|
||||
|
@ -109,7 +163,9 @@ void search_mv(picture *pic, uint8_t *pic_data, uint8_t *ref_data,
|
|||
}
|
||||
|
||||
// below
|
||||
cost = get_sad(orig_x + x, orig_y + y + step, pic->width, pic->height, block_width, pic_data, ref_data);
|
||||
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;
|
||||
|
@ -158,13 +214,13 @@ void search_mv_full(picture *pic, uint8_t *pic_data, uint8_t *ref_data,
|
|||
step /= 2;
|
||||
if (step > 0) {
|
||||
search_mv_full(pic, pic_data, ref_data, cur_cu, step, orig_x, orig_y,
|
||||
x, y - step, depth);
|
||||
x, y - step, depth);
|
||||
search_mv_full(pic, pic_data, ref_data, cur_cu, step, orig_x, orig_y,
|
||||
x - step, y, depth);
|
||||
x - step, y, depth);
|
||||
search_mv_full(pic, pic_data, ref_data, cur_cu, step, orig_x, orig_y,
|
||||
x + step, y, depth);
|
||||
x + step, y, depth);
|
||||
search_mv_full(pic, pic_data, ref_data, cur_cu, step, orig_x, orig_y,
|
||||
x, y + step, depth);
|
||||
x, y + step, depth);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -315,7 +371,7 @@ void search_tree(encoder_control *encoder,
|
|||
cur_cu, 8, x, y,
|
||||
start_x, start_y, depth);
|
||||
} else {
|
||||
search_mv(cur_pic, cur_data, ref_pic->y_data,
|
||||
search_mv(cur_pic, ref_pic,
|
||||
cur_cu, x, y,
|
||||
start_x, start_y, depth);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue