From b30f17d4b8b7070ee7b3f455bdee626a9b58fe99 Mon Sep 17 00:00:00 2001 From: Ari Lemmetti Date: Mon, 10 Aug 2015 17:49:31 +0300 Subject: [PATCH] Add fractional pixel sampling for chroma --- src/inter.c | 23 +++++------------- src/strategies/generic/ipol-generic.c | 35 +++++++++++++++++++++++++++ src/strategies/generic/ipol-generic.h | 3 +++ 3 files changed, 44 insertions(+), 17 deletions(-) diff --git a/src/inter.c b/src/inter.c index 2898c620..9a65526f 100644 --- a/src/inter.c +++ b/src/inter.c @@ -139,28 +139,17 @@ void inter_recon_lcu(const encoder_state_t * const state, const kvz_picture * co extend_borders(xpos>>1, ypos>>1, (mv[0]>>2)>>1, (mv[1]>>2)>>1, state->tile->lcu_offset_x * (LCU_WIDTH>>1), state->tile->lcu_offset_y * (LCU_WIDTH>>1), ref->u, ref->width>>1, ref->height>>1, FILTER_SIZE_C, width_c, width_c, octpel_src_u); - filter_inter_octpel_chroma(state->encoder_control, octpel_src_off_u, width_c+FILTER_SIZE_C, width_c, - width_c, octpel_dst_u, width_c*8, c_off_x, c_off_y); + sample_octpel_chroma_generic(state->encoder_control, octpel_src_off_u, width_c + FILTER_SIZE_C, width_c, + width_c, lcu->rec.u + ((ypos >> 1) % LCU_WIDTH_C)*LCU_WIDTH_C + ((xpos >> 1) % LCU_WIDTH_C), LCU_WIDTH_C, c_off_x, c_off_y, mv); //Fractional chroma V - extend_borders(xpos>>1, ypos>>1, (mv[0]>>2)>>1, (mv[1]>>2)>>1, state->tile->lcu_offset_x * (LCU_WIDTH>>1), state->tile->lcu_offset_y * (LCU_WIDTH>>1), - ref->v, ref->width>>1, ref->height>>1, FILTER_SIZE_C, width_c, width_c, octpel_src_v); + extend_borders(xpos >> 1, ypos >> 1, (mv[0] >> 2) >> 1, (mv[1] >> 2) >> 1, state->tile->lcu_offset_x * (LCU_WIDTH_C >> 1), state->tile->lcu_offset_y * (LCU_WIDTH_C >> 1), + ref->v, ref->width >> 1, ref->height >> 1, FILTER_SIZE_C, width_c, width_c, octpel_src_v); - filter_inter_octpel_chroma(state->encoder_control, octpel_src_off_v, width_c+FILTER_SIZE_C, width_c, - width_c, octpel_dst_v, width_c*8, c_off_x, c_off_y); + sample_octpel_chroma_generic(state->encoder_control, octpel_src_off_v, width_c + FILTER_SIZE_C, width_c, + width_c, lcu->rec.v + ((ypos >> 1) % LCU_WIDTH_C)*LCU_WIDTH_C + ((xpos >> 1) % LCU_WIDTH_C), LCU_WIDTH_C, c_off_x, c_off_y, mv); - //Sample fractional pixels for chroma - for(y = 0; y < width_c; ++y) { - int y_in_lcu = ((y+(ypos>>1)) & ((LCU_WIDTH>>1)-1)); - int qpel_y = y*8+c_off_y; - for(x = 0; x < width_c; ++x) { - int x_in_lcu = ((x+(xpos>>1)) & ((LCU_WIDTH>>1)-1)); - int qpel_x = x*8+c_off_x; - lcu->rec.u[y_in_lcu * dst_width_c + x_in_lcu] = (kvz_pixel)octpel_dst_u[qpel_y*(width_c*8)+qpel_x]; - lcu->rec.v[y_in_lcu * dst_width_c + x_in_lcu] = (kvz_pixel)octpel_dst_v[qpel_y*(width_c*8)+qpel_x]; - } - } } mv[0] >>= 2; diff --git a/src/strategies/generic/ipol-generic.c b/src/strategies/generic/ipol-generic.c index 804723d8..a6706223 100644 --- a/src/strategies/generic/ipol-generic.c +++ b/src/strategies/generic/ipol-generic.c @@ -383,6 +383,41 @@ void filter_inter_octpel_chroma_generic(const encoder_control_t * const encoder, } } +void sample_octpel_chroma_generic(const encoder_control_t * const encoder, kvz_pixel *src, int16_t src_stride, int width, int height,kvz_pixel *dst, int16_t dst_stride, int8_t hor_flag, int8_t ver_flag, const int16_t mv[2]) +{ + //TODO: horizontal and vertical only filtering + int32_t x, y; + int16_t shift1 = KVZ_BIT_DEPTH - 8; + int32_t shift2 = 6; + int32_t shift3 = 14 - KVZ_BIT_DEPTH; + int32_t offset23 = 1 << (shift2 + shift3 - 1); + + int8_t *hor_filter = g_chroma_filter[mv[0] & 7]; + int8_t *ver_filter = g_chroma_filter[mv[1] & 7]; + +#define FILTER_SIZE_C (FILTER_SIZE / 2) +#define FILTER_OFFSET_C (FILTER_OFFSET / 2) + int16_t flipped_hor_filtered[(LCU_WIDTH_C + 1) + FILTER_SIZE_C][(LCU_WIDTH_C + 1) + FILTER_SIZE_C]; + + // Filter horizontally and flip x and y + for (x = 0; x < width; ++x) { + for (y = 0; y < height + FILTER_SIZE_C; ++y) { + int ypos = y - FILTER_OFFSET_C; + int xpos = x - FILTER_OFFSET_C; + flipped_hor_filtered[x][y] = four_tap_filter_hor_generic(hor_filter, &src[src_stride*ypos + xpos]) >> shift1; + } + } + + // Filter vertically and flip x and y + for (x = 0; x < width; ++x) { + for (y = 0; y < height; ++y) { + int ypos = y; + int xpos = x; + dst[y*dst_stride + x] = fast_clip_32bit_to_pixel(((four_tap_filter_hor_16bit_generic(ver_filter, &flipped_hor_filtered[xpos][ypos]) + offset23) >> shift2) >> shift3); + } + } +} + void extend_borders_generic(int xpos, int ypos, int mv_x, int mv_y, int off_x, int off_y, kvz_pixel *ref, int ref_width, int ref_height, int filterSize, int width, int height, kvz_pixel *dst) { diff --git a/src/strategies/generic/ipol-generic.h b/src/strategies/generic/ipol-generic.h index 64607ee2..f1a6264f 100644 --- a/src/strategies/generic/ipol-generic.h +++ b/src/strategies/generic/ipol-generic.h @@ -22,6 +22,9 @@ #include "encoder.h" int strategy_register_ipol_generic(void* opaque); + +//TODO: create strategies from sample functions void sample_quarterpel_luma_generic(const encoder_control_t * const encoder, kvz_pixel *src, int16_t src_stride, int width, int height, kvz_pixel *dst, int16_t dst_stride, int8_t hor_flag, int8_t ver_flag, const int16_t mv[2]); +void sample_octpel_chroma_generic(const encoder_control_t * const encoder, kvz_pixel *src, int16_t src_stride, int width, int height, kvz_pixel *dst, int16_t dst_stride, int8_t hor_flag, int8_t ver_flag, const int16_t mv[2]); #endif //STRATEGIES_IPOL_GENERIC_H_