diff --git a/src/cfg.c b/src/cfg.c index b798e594..6d423607 100644 --- a/src/cfg.c +++ b/src/cfg.c @@ -1471,6 +1471,9 @@ int kvz_config_parse(kvz_config *cfg, const char *name, const char *value) else if OPT("jccr") { cfg->jccr = (bool)atobool(value); } + else if OPT("amvr") { + cfg->amvr = (bool)atobool(value); + } else { return 0; } diff --git a/src/cli.c b/src/cli.c index 24cf22c4..5a0d4e46 100644 --- a/src/cli.c +++ b/src/cli.c @@ -164,6 +164,8 @@ static const struct option long_options[] = { { "chroma-qp-out", required_argument, NULL, 0 }, { "jccr", no_argument, NULL, 0 }, { "no-jccr", no_argument, NULL, 0 }, + { "amvr", no_argument, NULL, 0 }, + { "no-amvr", no_argument, NULL, 0 }, {0, 0, 0, 0} }; @@ -615,8 +617,10 @@ void print_help(void) " - both: MTS applied for both intra and inter blocks.\n" " - implicit: uses implicit MTS. Applies DST7 instead \n" " of DCT2 to certain intra blocks.\n" - " --(no-)jccr : Joint coding of chroma residual. " - " Requires rdo> = 2. [disabled]\n" + " --(no-)jccr : Joint coding of chroma residual.\n" + " Requires rdo> = 2. [disabled]\n" + " --(no-)amvr : Adaptive Motion Vector Resolution.\n" + " Code some mv's with reduced resolution [disabled]\n" "\n" /* Word wrap to this width to stay under 80 characters (including ") *************/ "Parallel processing:\n" diff --git a/src/cu.h b/src/cu.h index 98b1d174..ced2d4e0 100644 --- a/src/cu.h +++ b/src/cu.h @@ -164,6 +164,7 @@ typedef struct uint8_t mv_cand0 : 3; // \brief selected MV candidate uint8_t mv_cand1 : 3; // \brief selected MV candidate uint8_t mv_dir : 2; // \brief Probably describes if mv_ref is L0, L1 or both (bi-pred) + uint8_t imv : 2; // \brief Adaptive motion vector resolution for this block } inter; }; } cu_info_t; diff --git a/src/encode_coding_tree.c b/src/encode_coding_tree.c index 826be706..b8db2d21 100644 --- a/src/encode_coding_tree.c +++ b/src/encode_coding_tree.c @@ -579,6 +579,25 @@ static void encode_transform_coeff(encoder_state_t * const state, } } +static void change_precision(int imv, int32_t* hor, int32_t* ver) { + int dst = "\4\2\0\3"[imv]; + int src = 4; // We use quarterpel internal res + + const int shift = (int)dst - (int)src; + if (shift >= 0) + { + *hor <<= shift; + *ver <<= shift; + } + else + { + const int right_shift = -shift; + const int offset = 1 << (right_shift - 1); + *hor = *hor >= 0 ? (*hor + offset - 1) >> right_shift : (*hor + offset) >> right_shift; + *ver = *ver >= 0 ? (*ver + offset - 1) >> right_shift : (*ver + offset) >> right_shift; + } +} + /** * \brief Writes inter block parameters to the bitstream * \param state Encoder state in use @@ -673,6 +692,9 @@ static bool encode_inter_prediction_unit(encoder_state_t * const state, const int32_t mvd_hor = cur_cu->inter.mv[ref_list_idx][0] - mv_cand[cu_mv_cand][0]; const int32_t mvd_ver = cur_cu->inter.mv[ref_list_idx][1] - mv_cand[cu_mv_cand][1]; + //change_precision(KVZ_IMV_FPEL, &mvd_hor, &mvd_ver); + + kvz_encode_mvd(state, cabac, mvd_hor, mvd_ver); non_zero_mvd |= (mvd_hor != 0) || (mvd_ver != 0); @@ -1351,8 +1373,8 @@ void kvz_encode_coding_tree(encoder_state_t * const state, #endif if (cur_cu->type == CU_INTER) { - uint8_t imv_mode = 0; - + uint8_t imv_mode = KVZ_IMV_OFF; + const int num_pu = kvz_part_mode_num_parts[cur_cu->part_size]; bool non_zero_mvd = false; @@ -1369,16 +1391,16 @@ void kvz_encode_coding_tree(encoder_state_t * const state, } // imv mode, select between fullpel, half-pel and quarter-pel resolutions - // 0 = off, 1 = fullpel, 2 = quarter-pel, 3 = half-pel + // 0 = off, 1 = fullpel, 2 = 4-pel, 3 = half-pel if (ctrl->cfg.amvr && non_zero_mvd) { cabac->cur_ctx = &(cabac->ctx.imv_flag[0]); - CABAC_BIN(cabac, (imv_mode > 0), "imv_flag"); - if (imv_mode > 0) { + CABAC_BIN(cabac, (imv_mode > KVZ_IMV_OFF), "imv_flag"); + if (imv_mode > KVZ_IMV_OFF) { cabac->cur_ctx = &(cabac->ctx.imv_flag[4]); - CABAC_BIN(cabac, (imv_mode < 3), "imv_flag"); - if (imv_mode < 3) { + CABAC_BIN(cabac, (imv_mode < KVZ_IMV_HPEL), "imv_flag"); + if (imv_mode < KVZ_IMV_HPEL) { cabac->cur_ctx = &(cabac->ctx.imv_flag[1]); - CABAC_BIN(cabac, (imv_mode > 1), "imv_flag"); + CABAC_BIN(cabac, (imv_mode > KVZ_IMV_FPEL), "imv_flag"); // 1 indicates 4PEL, 0 FPEL } } } diff --git a/src/kvazaar.h b/src/kvazaar.h index 9e8e8f94..bf56f7d2 100644 --- a/src/kvazaar.h +++ b/src/kvazaar.h @@ -245,6 +245,13 @@ enum kvz_file_format KVZ_FORMAT_YUV = 2 }; +enum kvz_amvr_resolution +{ + KVZ_IMV_OFF = 0, + KVZ_IMV_FPEL = 1, + KVZ_IMV_4PEL = 2, + KVZ_IMV_HPEL = 3 +}; // Map from input format to chroma format. #define KVZ_FORMAT2CSP(format) ((enum kvz_chroma_format)format)