diff --git a/configure b/configure index 3cecfcd57..525ccd168 100755 --- a/configure +++ b/configure @@ -225,6 +225,7 @@ EXPERIMENT_LIST=" pred_filter lossless hybridtransform + switchable_interp " CONFIG_LIST=" external_build diff --git a/vp8/common/blockd.h b/vp8/common/blockd.h index dc0639f83..1bbaa6422 100644 --- a/vp8/common/blockd.h +++ b/vp8/common/blockd.h @@ -76,7 +76,25 @@ typedef enum { INTER_FRAME = 1 } FRAME_TYPE; -typedef enum { +typedef enum +{ + SIXTAP = 0, + BILINEAR = 1, +#if CONFIG_ENHANCED_INTERP + EIGHTTAP = 2, + EIGHTTAP_SHARP = 3, +#if CONFIG_SWITCHABLE_INTERP + SWITCHABLE /* should be the last one */ +#endif +#endif +} INTERPOLATIONFILTERTYPE; + +#if 0//CONFIG_SWITCHABLE_INTERP +#define VP8_SWITCHABLE_FILTERS 2 /* number of switchable filters */ +#endif + +typedef enum +{ DC_PRED, /* average of above and left pixels */ V_PRED, /* vertical prediction */ H_PRED, /* horizontal prediction */ @@ -226,6 +244,9 @@ typedef struct { // Flag to turn prediction signal filter on(1)/off(0 ) at the MB level unsigned int pred_filter_enabled; #endif +#if CONFIG_SWITCHABLE_INTERP + INTERPOLATIONFILTERTYPE interp_filter; +#endif } MB_MODE_INFO; diff --git a/vp8/common/entropy.h b/vp8/common/entropy.h index 8bb718a06..9993741c8 100644 --- a/vp8/common/entropy.h +++ b/vp8/common/entropy.h @@ -18,8 +18,8 @@ #include "coefupdateprobs.h" -#define SUBMVREF_COUNT 5 -#define VP8_NUMMBSPLITS 4 +//#define SUBMVREF_COUNT 5 +//#define VP8_NUMMBSPLITS 4 /* Coefficient token alphabet */ diff --git a/vp8/common/entropymode.c b/vp8/common/entropymode.c index e48df3b36..4500e9c11 100644 --- a/vp8/common/entropymode.c +++ b/vp8/common/entropymode.c @@ -9,10 +9,8 @@ */ +#include "onyxc_int.h" #include "modecont.h" -#include "entropymode.h" -#include "entropymv.h" -#include "entropy.h" #include "vpx_mem/vpx_mem.h" @@ -286,6 +284,10 @@ void vp8_init_mbmode_probs(VP8_COMMON *x) { vpx_memcpy(x->fc.sub_mv_ref_prob, vp8_sub_mv_ref_prob2, sizeof(vp8_sub_mv_ref_prob2)); vpx_memcpy(x->fc.mbsplit_prob, vp8_mbsplit_probs, sizeof(vp8_mbsplit_probs)); +#if CONFIG_SWITCHABLE_INTERP + vpx_memcpy(x->fc.switchable_interp_prob, vp8_switchable_interp_prob, + sizeof(vp8_switchable_interp_prob)); +#endif } @@ -323,6 +325,44 @@ void vp8_kf_default_bmode_probs(vp8_prob p [VP8_BINTRAMODES] [VP8_BINTRAMODES] [ } while (++i < VP8_BINTRAMODES); } +#if CONFIG_SWITCHABLE_INTERP +#if VP8_SWITCHABLE_FILTERS == 3 +const vp8_tree_index vp8_switchable_interp_tree[VP8_SWITCHABLE_FILTERS*2-2] = { + -0, 2, + -1, -2 +}; +struct vp8_token_struct vp8_switchable_interp_encodings[VP8_SWITCHABLE_FILTERS]; +const INTERPOLATIONFILTERTYPE vp8_switchable_interp[VP8_SWITCHABLE_FILTERS] = { + EIGHTTAP, SIXTAP, EIGHTTAP_SHARP}; +const int vp8_switchable_interp_map[SWITCHABLE+1] = {1, -1, 0, 2, -1}; +const vp8_prob vp8_switchable_interp_prob [VP8_SWITCHABLE_FILTERS+1] + [VP8_SWITCHABLE_FILTERS-1] = { + {248, 192}, { 32, 248}, { 32, 32}, {192, 160} +}; +#elif VP8_SWITCHABLE_FILTERS == 2 +const vp8_tree_index vp8_switchable_interp_tree[VP8_SWITCHABLE_FILTERS*2-2] = { + -0, -1, +}; +struct vp8_token_struct vp8_switchable_interp_encodings[VP8_SWITCHABLE_FILTERS]; +const vp8_prob vp8_switchable_interp_prob [VP8_SWITCHABLE_FILTERS+1] + [VP8_SWITCHABLE_FILTERS-1] = { + {248}, + { 64}, + {192}, +}; +//#define SWITCHABLE_86 +#ifdef SWITCHABLE_86 +const INTERPOLATIONFILTERTYPE vp8_switchable_interp[VP8_SWITCHABLE_FILTERS] = { + EIGHTTAP, SIXTAP}; +const int vp8_switchable_interp_map[SWITCHABLE+1] = {1, -1, 0, -1, -1}; //8, 6 +#else +const INTERPOLATIONFILTERTYPE vp8_switchable_interp[VP8_SWITCHABLE_FILTERS] = { + EIGHTTAP, EIGHTTAP_SHARP}; +const int vp8_switchable_interp_map[SWITCHABLE+1] = {-1, -1, 0, 1, -1}; //8, 8s +#endif +#endif +#endif + void vp8_entropy_mode_init() { vp8_tokens_from_tree(vp8_bmode_encodings, vp8_bmode_tree); @@ -331,6 +371,10 @@ void vp8_entropy_mode_init() { vp8_tokens_from_tree(vp8_uv_mode_encodings, vp8_uv_mode_tree); vp8_tokens_from_tree(vp8_i8x8_mode_encodings, vp8_i8x8_mode_tree); vp8_tokens_from_tree(vp8_mbsplit_encodings, vp8_mbsplit_tree); +#if CONFIG_SWITCHABLE_INTERP + vp8_tokens_from_tree(vp8_switchable_interp_encodings, + vp8_switchable_interp_tree); +#endif vp8_tokens_from_tree_offset(vp8_mv_ref_encoding_array, vp8_mv_ref_tree, NEARESTMV); diff --git a/vp8/common/entropymode.h b/vp8/common/entropymode.h index f66c1c859..f9cc263b9 100644 --- a/vp8/common/entropymode.h +++ b/vp8/common/entropymode.h @@ -12,9 +12,12 @@ #ifndef __INC_ENTROPYMODE_H #define __INC_ENTROPYMODE_H -#include "onyxc_int.h" +#include "blockd.h" #include "treecoder.h" +#define SUBMVREF_COUNT 5 +#define VP8_NUMMBSPLITS 4 + typedef const int vp8_mbsplit[16]; extern vp8_mbsplit vp8_mbsplits [VP8_NUMMBSPLITS]; @@ -56,10 +59,11 @@ extern struct vp8_token_struct vp8_sub_mv_ref_encoding_array [VP8_SUBMVREFS]; void vp8_entropy_mode_init(void); -void vp8_init_mbmode_probs(VP8_COMMON *x); -extern void vp8_init_mode_contexts(VP8_COMMON *pc); -extern void vp8_update_mode_context(VP8_COMMON *pc);; -extern void vp8_accum_mv_refs(VP8_COMMON *pc, +struct VP8Common; +void vp8_init_mbmode_probs(struct VP8Common *x); +extern void vp8_init_mode_contexts(struct VP8Common *pc); +extern void vp8_update_mode_context(struct VP8Common *pc);; +extern void vp8_accum_mv_refs(struct VP8Common *pc, MB_PREDICTION_MODE m, const int ct[4]); @@ -67,4 +71,17 @@ void vp8_default_bmode_probs(vp8_prob dest [VP8_BINTRAMODES - 1]); void vp8_kf_default_bmode_probs(vp8_prob dest [VP8_BINTRAMODES] [VP8_BINTRAMODES] [VP8_BINTRAMODES - 1]); void vp8_adapt_mode_probs(struct VP8Common *); + +#if CONFIG_SWITCHABLE_INTERP +#define VP8_SWITCHABLE_FILTERS 2 /* number of switchable filters */ +extern const INTERPOLATIONFILTERTYPE vp8_switchable_interp + [VP8_SWITCHABLE_FILTERS]; +extern const int vp8_switchable_interp_map[SWITCHABLE+1]; +extern const vp8_tree_index vp8_switchable_interp_tree + [2*(VP8_SWITCHABLE_FILTERS-1)]; +extern struct vp8_token_struct vp8_switchable_interp_encodings + [VP8_SWITCHABLE_FILTERS]; +extern const vp8_prob vp8_switchable_interp_prob + [VP8_SWITCHABLE_FILTERS+1][VP8_SWITCHABLE_FILTERS-1]; +#endif #endif diff --git a/vp8/common/entropymv.c b/vp8/common/entropymv.c index 3dd72cc76..c1ea62d27 100644 --- a/vp8/common/entropymv.c +++ b/vp8/common/entropymv.c @@ -116,7 +116,6 @@ const vp8_tree_index vp8_small_mvtree [14] = { }; struct vp8_token_struct vp8_small_mvencodings [8]; - __inline static void calc_prob(vp8_prob *p, const unsigned int ct[2], int pbits) { const unsigned int tot = ct[0] + ct[1]; if (tot) { diff --git a/vp8/common/entropymv.h b/vp8/common/entropymv.h index 96ea7ffae..c0726ecea 100644 --- a/vp8/common/entropymv.h +++ b/vp8/common/entropymv.h @@ -14,6 +14,7 @@ #include "treecoder.h" #include "vpx_config.h" +#include "blockd.h" enum { mv_max = 1023, /* max absolute value of a MV component */ @@ -78,5 +79,9 @@ extern struct vp8_token_struct vp8_small_mvencodings_hp [16]; #endif void vp8_entropy_mv_init(); +#if CONFIG_ADAPTIVE_ENTROPY +struct VP8Common; +void vp8_adapt_mv_probs(struct VP8Common *cm); +#endif #endif diff --git a/vp8/common/filter.c b/vp8/common/filter.c index 856bad5a6..78c239080 100644 --- a/vp8/common/filter.c +++ b/vp8/common/filter.c @@ -46,7 +46,7 @@ DECLARE_ALIGNED(16, const short, vp8_bilinear_filters[SUBPEL_SHIFTS][2]) = { #if CONFIG_ENHANCED_INTERP #define FILTER_ALPHA 0 -#define FILTER_ALPHA_SHARP 60 +#define FILTER_ALPHA_SHARP 1 DECLARE_ALIGNED(16, const short, vp8_sub_pel_filters_8[SUBPEL_SHIFTS][2 * INTERP_EXTEND]) = { #if SUBPEL_SHIFTS==16 #if FILTER_ALPHA == 0 @@ -91,24 +91,6 @@ DECLARE_ALIGNED(16, const short, vp8_sub_pel_filters_8[SUBPEL_SHIFTS][2 * INTERP { 0, 3, -9, 27, 118, -13, 3, -1}, { 0, 2, -6, 18, 122, -10, 2, 0}, { 0, 1, -3, 8, 126, -5, 1, 0} -#elif FILTER_ALPHA == 45 - /* alpha = 0.45 */ - { 0, 0, 0, 128, 0, 0, 0, 0}, - { 0, 1, -5, 126, 8, -3, 1, 0}, - { 0, 2, -9, 122, 17, -6, 2, 0}, - { 0, 3, -13, 117, 27, -8, 2, 0}, - { -1, 4, -15, 111, 37, -11, 3, 0}, - { -1, 4, -17, 104, 47, -13, 4, 0}, - { -1, 5, -18, 96, 58, -15, 4, -1}, - { -1, 5, -18, 87, 68, -17, 5, -1}, - { -1, 5, -18, 78, 78, -18, 5, -1}, - { -1, 5, -17, 68, 87, -18, 5, -1}, - { -1, 4, -15, 58, 96, -18, 5, -1}, - { 0, 4, -13, 47, 104, -17, 4, -1}, - { 0, 3, -11, 37, 111, -15, 4, -1}, - { 0, 2, -8, 27, 117, -13, 3, 0}, - { 0, 2, -6, 17, 122, -9, 2, 0}, - { 0, 1, -3, 8, 126, -5, 1, 0} #endif /* FILTER_ALPHA */ #else /* SUBPEL_SHIFTS==16 */ #if FILTER_ALPHA == 0 @@ -130,23 +112,48 @@ DECLARE_ALIGNED(16, const short, vp8_sub_pel_filters_8[SUBPEL_SHIFTS][2 * INTERP { -1, 5, -16, 58, 96, -18, 5, -1}, { 0, 3, -11, 37, 112, -16, 4, -1}, { 0, 2, -6, 18, 122, -10, 2, 0} -#elif FILTER_ALPHA == 45 - /* alpha = 0.45 */ - { 0, 0, 0, 128, 0, 0, 0, 0}, - { 0, 2, -9, 122, 17, -6, 2, 0}, - { -1, 4, -15, 111, 37, -11, 3, 0}, - { -1, 5, -18, 96, 58, -15, 4, -1}, - { -1, 5, -18, 78, 78, -18, 5, -1}, - { -1, 4, -15, 58, 96, -18, 5, -1}, - { 0, 3, -11, 37, 111, -15, 4, -1}, - { 0, 2, -6, 17, 122, -9, 2, 0}, #endif /* FILTER_ALPHA */ #endif /* SUBPEL_SHIFTS==16 */ }; DECLARE_ALIGNED(16, const short, vp8_sub_pel_filters_8s[SUBPEL_SHIFTS][2 * INTERP_EXTEND]) = { #if SUBPEL_SHIFTS==16 -#if FILTER_ALPHA_SHARP == 65 +#if FILTER_ALPHA_SHARP == 1 + /* dct based filter */ + {0, 0, 0, 128, 0, 0, 0, 0}, + {-1, 3, -7, 127, 8, -3, 1, 0}, + {-2, 5, -13, 125, 17, -6, 3, -1}, + {-3, 7, -17, 121, 27, -10, 5, -2}, + {-4, 9, -20, 115, 37, -13, 6, -2}, + {-4, 10, -23, 108, 48, -16, 8, -3}, + {-4, 10, -24, 100, 59, -19, 9, -3}, + {-4, 11, -24, 90, 70, -21, 10, -4}, + {-4, 11, -23, 80, 80, -23, 11, -4}, + {-4, 10, -21, 70, 90, -24, 11, -4}, + {-3, 9, -19, 59, 100, -24, 10, -4}, + {-3, 8, -16, 48, 108, -23, 10, -4}, + {-2, 6, -13, 37, 115, -20, 9, -4}, + {-2, 5, -10, 27, 121, -17, 7, -3}, + {-1, 3, -6, 17, 125, -13, 5, -2}, + {0, 1, -3, 8, 127, -7, 3, -1} +#elif FILTER_ALPHA_SHARP == 75 + {0, 0, 0, 128, 0, 0, 0, 0}, + {-1, 2, -6, 126, 9, -3, 2, -1}, + {-1, 4, -11, 123, 18, -7, 3, -1}, + {-2, 6, -16, 119, 28, -10, 5, -2}, + {-2, 7, -19, 113, 38, -13, 6, -2}, + {-3, 8, -21, 106, 49, -16, 7, -2}, + {-3, 9, -22, 99, 59, -19, 8, -3}, + {-3, 9, -23, 90, 70, -21, 9, -3}, + {-3, 9, -22, 80, 80, -22, 9, -3}, + {-3, 9, -21, 70, 90, -23, 9, -3}, + {-3, 8, -19, 59, 99, -22, 9, -3}, + {-2, 7, -16, 49, 106, -21, 8, -3}, + {-2, 6, -13, 38, 113, -19, 7, -2}, + {-2, 5, -10, 28, 119, -16, 6, -2}, + {-1, 3, -7, 18, 123, -11, 4, -1}, + {-1, 2, -3, 9, 126, -6, 2, -1} +#elif FILTER_ALPHA_SHARP == 65 /* alpha = 0.65 */ { 0, 0, 0, 128, 0, 0, 0, 0}, { 0, 2, -6, 126, 8, -3, 1, 0}, @@ -164,45 +171,27 @@ DECLARE_ALIGNED(16, const short, vp8_sub_pel_filters_8s[SUBPEL_SHIFTS][2 * INTER { -1, 4, -10, 27, 118, -14, 5, -1}, { -1, 2, -6, 18, 123, -10, 3, -1}, { 0, 1, -3, 8, 126, -6, 2, 0} -#elif FILTER_ALPHA_SHARP == 60 - /* alpha = 0.60 */ - { 0, 0, 0, 128, 0, 0, 0, 0}, - { 0, 2, -6, 126, 8, -3, 1, 0}, - { -1, 3, -10, 123, 18, -6, 2, -1}, - { -1, 4, -14, 118, 28, -9, 3, -1}, - { -1, 5, -17, 112, 38, -12, 4, -1}, - { -1, 6, -19, 105, 48, -15, 5, -1}, - { -1, 6, -20, 97, 58, -17, 6, -1}, - { -1, 6, -20, 88, 69, -19, 6, -1}, - { -1, 6, -20, 79, 79, -20, 6, -1}, - { -1, 6, -19, 69, 88, -20, 6, -1}, - { -1, 6, -17, 58, 97, -20, 6, -1}, - { -1, 5, -15, 48, 105, -19, 6, -1}, - { -1, 4, -12, 38, 112, -17, 5, -1}, - { -1, 3, -9, 28, 118, -14, 4, -1}, - { -1, 2, -6, 18, 123, -10, 3, -1}, - { 0, 1, -3, 8, 126, -6, 2, 0} -#elif FILTER_ALPHA_SHARP == 55 - /* alpha = 0.55 */ - { 0, 0, 0, 128, 0, 0, 0, 0}, - { 0, 1, -5, 126, 8, -3, 1, 0}, - { -1, 2, -10, 123, 18, -6, 2, 0}, - { -1, 4, -13, 118, 27, -9, 3, -1}, - { -1, 5, -16, 112, 37, -12, 4, -1}, - { -1, 5, -18, 105, 48, -14, 4, -1}, - { -1, 5, -19, 97, 58, -16, 5, -1}, - { -1, 6, -19, 88, 68, -18, 5, -1}, - { -1, 6, -19, 78, 78, -19, 6, -1}, - { -1, 5, -18, 68, 88, -19, 6, -1}, - { -1, 5, -16, 58, 97, -19, 5, -1}, - { -1, 4, -14, 48, 105, -18, 5, -1}, - { -1, 4, -12, 37, 112, -16, 5, -1}, - { -1, 3, -9, 27, 118, -13, 4, -1}, - { 0, 2, -6, 18, 123, -10, 2, -1}, - { 0, 1, -3, 8, 126, -5, 1, 0} #endif /* FILTER_ALPHA_SHARP */ #else /* SUBPEL_SHIFTS==16 */ -#if FILTER_ALPHA_SHARP == 65 +#if FILTER_ALPHA_SHARP == 1 + {0, 0, 0, 128, 0, 0, 0, 0}, + {-2, 5, -13, 125, 17, -6, 3, -1}, + {-4, 9, -20, 115, 37, -13, 6, -2}, + {-4, 10, -24, 100, 59, -19, 9, -3}, + {-4, 10, -23, 81, 81, -23, 10, -4}, + {-3, 9, -19, 59, 100, -24, 10, -4}, + {-2, 6, -13, 37, 115, -20, 9, -4}, + {-1, 3, -6, 17, 125, -13, 5, -2} +#elif FILTER_ALPHA_SHARP == 75 + {0, 0, 0, 128, 0, 0, 0, 0}, + {-1, 4, -11, 123, 18, -7, 3, -1}, + {-2, 7, -19, 113, 38, -13, 6, -2}, + {-3, 9, -22, 99, 59, -19, 8, -3}, + {-3, 9, -22, 80, 80, -22, 9, -3}, + {-3, 8, -19, 59, 99, -22, 9, -3}, + {-2, 6, -13, 38, 113, -19, 7, -2}, + {-1, 3, -7, 18, 123, -11, 4, -1} +#elif FILTER_ALPHA_SHARP == 65 /* alpha = 0.65 */ { 0, 0, 0, 128, 0, 0, 0, 0}, { -1, 3, -10, 123, 18, -6, 2, -1}, @@ -212,26 +201,6 @@ DECLARE_ALIGNED(16, const short, vp8_sub_pel_filters_8s[SUBPEL_SHIFTS][2 * INTER { -2, 6, -17, 59, 98, -21, 7, -2}, { -1, 5, -13, 38, 112, -17, 5, -1}, { -1, 2, -6, 18, 123, -10, 3, -1} -#elif FILTER_ALPHA_SHARP == 60 - /* alpha = 0.60 */ - { 0, 0, 0, 128, 0, 0, 0, 0}, - { -1, 3, -10, 123, 18, -6, 2, -1}, - { -1, 5, -17, 112, 38, -12, 4, -1}, - { -1, 6, -20, 97, 58, -17, 6, -1}, - { -1, 6, -20, 79, 79, -20, 6, -1}, - { -1, 6, -17, 58, 97, -20, 6, -1}, - { -1, 4, -12, 38, 112, -17, 5, -1}, - { -1, 2, -6, 18, 123, -10, 3, -1} -#elif FILTER_ALPHA_SHARP == 55 - /* alpha = 0.55 */ - { 0, 0, 0, 128, 0, 0, 0, 0}, - { -1, 2, -10, 123, 18, -6, 2, 0}, - { -1, 5, -16, 112, 37, -12, 4, -1}, - { -1, 5, -19, 97, 58, -16, 5, -1}, - { -1, 6, -19, 78, 78, -19, 6, -1}, - { -1, 5, -16, 58, 97, -19, 5, -1}, - { -1, 4, -12, 37, 112, -16, 5, -1}, - { 0, 2, -6, 18, 123, -10, 2, -1} #endif /* FILTER_ALPHA_SHARP */ #endif /* SUBPEL_SHIFTS==16 */ }; diff --git a/vp8/common/onyxc_int.h b/vp8/common/onyxc_int.h index 8f2417f66..ccecc4963 100644 --- a/vp8/common/onyxc_int.h +++ b/vp8/common/onyxc_int.h @@ -17,6 +17,7 @@ #include "loopfilter.h" #include "entropymv.h" #include "entropy.h" +#include "entropymode.h" #include "idct.h" #include "recon.h" #if CONFIG_POSTPROC @@ -82,6 +83,11 @@ typedef struct frame_contexts { #if CONFIG_HIGH_PRECISION_MV unsigned int MVcount_hp [2] [MVvals_hp]; #endif +#if CONFIG_SWITCHABLE_INTERP + vp8_prob switchable_interp_prob[VP8_SWITCHABLE_FILTERS+1] + [VP8_SWITCHABLE_FILTERS-1]; +#endif + int mode_context[6][4]; int mode_context_a[6][4]; int vp8_mode_contexts[6][4]; @@ -94,15 +100,6 @@ typedef enum { RECON_CLAMP_NOTREQUIRED = 1 } CLAMP_TYPE; -typedef enum { - SIXTAP = 0, - BILINEAR = 1, -#if CONFIG_ENHANCED_INTERP - EIGHTTAP = 2, - EIGHTTAP_SHARP = 3, -#endif -} INTERPOLATIONFILTERTYPE; - typedef enum { SINGLE_PREDICTION_ONLY = 0, COMP_PREDICTION_ONLY = 1, diff --git a/vp8/common/pred_common.c b/vp8/common/pred_common.c index 2d46496f1..b7d52a54f 100644 --- a/vp8/common/pred_common.c +++ b/vp8/common/pred_common.c @@ -62,6 +62,38 @@ unsigned char get_pred_context(VP8_COMMON *const cm, (m - cm->mode_info_stride)->mbmi.mb_skip_coeff; break; +#if CONFIG_SWITCHABLE_INTERP + case PRED_SWITCHABLE_INTERP: + { + int left_in_image = (m - 1)->mbmi.mb_in_image; + int above_in_image = (m - cm->mode_info_stride)->mbmi.mb_in_image; + int left_mode = (m - 1)->mbmi.mode; + int above_mode = (m - cm->mode_info_stride)->mbmi.mode; + int left_interp, above_interp; + if (left_in_image && left_mode >= NEARESTMV && left_mode <= SPLITMV) + left_interp = vp8_switchable_interp_map[(m - 1)->mbmi.interp_filter]; + else + left_interp = VP8_SWITCHABLE_FILTERS; + if (above_in_image && above_mode >= NEARESTMV && above_mode <= SPLITMV) + above_interp = vp8_switchable_interp_map[ + (m - cm->mode_info_stride)->mbmi.interp_filter]; + else + above_interp = VP8_SWITCHABLE_FILTERS; + + if (left_interp == above_interp) + pred_context = left_interp; + else if (left_interp == VP8_SWITCHABLE_FILTERS && + above_interp != VP8_SWITCHABLE_FILTERS) + pred_context = above_interp; + else if (left_interp != VP8_SWITCHABLE_FILTERS && + above_interp == VP8_SWITCHABLE_FILTERS) + pred_context = left_interp; + else + pred_context = VP8_SWITCHABLE_FILTERS; + } + break; +#endif + default: // TODO *** add error trap code. pred_context = 0; @@ -111,6 +143,53 @@ vp8_prob get_pred_prob(VP8_COMMON *const cm, return pred_probability; } +// This function returns a context probability ptr for coding a given +// prediction signal +vp8_prob *get_pred_probs(VP8_COMMON *const cm, + MACROBLOCKD *const xd, + PRED_ID pred_id) { + vp8_prob *pred_probability; + int pred_context; + + // Get the appropriate prediction context + pred_context = get_pred_context(cm, xd, pred_id); + + switch (pred_id) { + case PRED_SEG_ID: + pred_probability = &cm->segment_pred_probs[pred_context]; + break; + + case PRED_REF: + pred_probability = &cm->ref_pred_probs[pred_context]; + break; + + case PRED_COMP: + // In keeping with convention elsewhre the probability returned is + // the probability of a "0" outcome which in this case means the + // probability of comp pred off. + pred_probability = &cm->prob_comppred[pred_context]; + break; + +#if CONFIG_NEWENTROPY + case PRED_MBSKIP: + pred_probability = &cm->mbskip_pred_probs[pred_context]; + break; +#endif + +#if CONFIG_SWITCHABLE_INTERP + case PRED_SWITCHABLE_INTERP: + pred_probability = &cm->fc.switchable_interp_prob[pred_context][0]; + break; +#endif + default: + // TODO *** add error trap code. + pred_probability = NULL; + break; + } + + return pred_probability; +} + // This function returns the status of the given prediction signal. // I.e. is the predicted value for the given signal correct. unsigned char get_pred_flag(MACROBLOCKD *const xd, diff --git a/vp8/common/pred_common.h b/vp8/common/pred_common.h index a1b019fc6..f4992f555 100644 --- a/vp8/common/pred_common.h +++ b/vp8/common/pred_common.h @@ -22,6 +22,9 @@ typedef enum { PRED_REF = 1, PRED_COMP = 2, PRED_MBSKIP = 3, +#if CONFIG_SWITCHABLE_INTERP + PRED_SWITCHABLE_INTERP = 4, +#endif } PRED_ID; @@ -33,6 +36,10 @@ extern vp8_prob get_pred_prob(VP8_COMMON *const cm, MACROBLOCKD *const xd, PRED_ID pred_id); +extern vp8_prob *get_pred_probs(VP8_COMMON *const cm, + MACROBLOCKD *const xd, + PRED_ID pred_id); + extern unsigned char get_pred_flag(MACROBLOCKD *const xd, PRED_ID pred_id); diff --git a/vp8/common/reconinter.c b/vp8/common/reconinter.c index d94ab4449..6f7d963c6 100644 --- a/vp8/common/reconinter.c +++ b/vp8/common/reconinter.c @@ -19,6 +19,81 @@ #include "onyxc_int.h" #endif +void vp8_setup_interp_filters(MACROBLOCKD *xd, + INTERPOLATIONFILTERTYPE mcomp_filter_type, + VP8_COMMON *cm) { + if (mcomp_filter_type == SIXTAP) { + xd->subpixel_predict = SUBPIX_INVOKE( + &cm->rtcd.subpix, sixtap4x4); + xd->subpixel_predict8x4 = SUBPIX_INVOKE( + &cm->rtcd.subpix, sixtap8x4); + xd->subpixel_predict8x8 = SUBPIX_INVOKE( + &cm->rtcd.subpix, sixtap8x8); + xd->subpixel_predict16x16 = SUBPIX_INVOKE( + &cm->rtcd.subpix, sixtap16x16); + xd->subpixel_predict_avg = SUBPIX_INVOKE( + &cm->rtcd.subpix, sixtap_avg4x4); + xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE( + &cm->rtcd.subpix, sixtap_avg8x8); + xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE( + &cm->rtcd.subpix, sixtap_avg16x16); + } +#if CONFIG_ENHANCED_INTERP + else if (mcomp_filter_type == EIGHTTAP +#if CONFIG_SWITCHABLE_INTERP + || + mcomp_filter_type == SWITCHABLE +#endif + ) { + xd->subpixel_predict = SUBPIX_INVOKE( + &cm->rtcd.subpix, eighttap4x4); + xd->subpixel_predict8x4 = SUBPIX_INVOKE( + &cm->rtcd.subpix, eighttap8x4); + xd->subpixel_predict8x8 = SUBPIX_INVOKE( + &cm->rtcd.subpix, eighttap8x8); + xd->subpixel_predict16x16 = SUBPIX_INVOKE( + &cm->rtcd.subpix, eighttap16x16); + xd->subpixel_predict_avg = SUBPIX_INVOKE( + &cm->rtcd.subpix, eighttap_avg4x4); + xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE( + &cm->rtcd.subpix, eighttap_avg8x8); + xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE( + &cm->rtcd.subpix, eighttap_avg16x16); + } else if (mcomp_filter_type == EIGHTTAP_SHARP) { + xd->subpixel_predict = SUBPIX_INVOKE( + &cm->rtcd.subpix, eighttap4x4_sharp); + xd->subpixel_predict8x4 = SUBPIX_INVOKE( + &cm->rtcd.subpix, eighttap8x4_sharp); + xd->subpixel_predict8x8 = SUBPIX_INVOKE( + &cm->rtcd.subpix, eighttap8x8_sharp); + xd->subpixel_predict16x16 = SUBPIX_INVOKE( + &cm->rtcd.subpix, eighttap16x16_sharp); + xd->subpixel_predict_avg = SUBPIX_INVOKE( + &cm->rtcd.subpix, eighttap_avg4x4_sharp); + xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE( + &cm->rtcd.subpix, eighttap_avg8x8_sharp); + xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE( + &cm->rtcd.subpix, eighttap_avg16x16_sharp); + } +#endif + else { + xd->subpixel_predict = SUBPIX_INVOKE( + &cm->rtcd.subpix, bilinear4x4); + xd->subpixel_predict8x4 = SUBPIX_INVOKE( + &cm->rtcd.subpix, bilinear8x4); + xd->subpixel_predict8x8 = SUBPIX_INVOKE( + &cm->rtcd.subpix, bilinear8x8); + xd->subpixel_predict16x16 = SUBPIX_INVOKE( + &cm->rtcd.subpix, bilinear16x16); + xd->subpixel_predict_avg = SUBPIX_INVOKE( + &cm->rtcd.subpix, bilinear_avg4x4); + xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE( + &cm->rtcd.subpix, bilinear_avg8x8); + xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE( + &cm->rtcd.subpix, bilinear_avg16x16); + } +} + void vp8_copy_mem16x16_c( unsigned char *src, int src_stride, diff --git a/vp8/common/reconinter.h b/vp8/common/reconinter.h index 0f8b44f22..7755c526e 100644 --- a/vp8/common/reconinter.h +++ b/vp8/common/reconinter.h @@ -12,6 +12,10 @@ #ifndef __INC_RECONINTER_H #define __INC_RECONINTER_H +#if CONFIG_RUNTIME_CPU_DETECT +#include "onyxc_int.h" +#endif + extern void vp8_build_inter_predictors_mb(MACROBLOCKD *x); extern void vp8_build_inter16x16_predictors_mb(MACROBLOCKD *x, unsigned char *dst_y, @@ -33,5 +37,6 @@ extern void vp8_build_2nd_inter_predictors_b(BLOCKD *d, int pitch, vp8_subpix_fn extern void vp8_build_inter16x16_predictors_mbuv(MACROBLOCKD *x); extern void vp8_build_inter4x4_predictors_mbuv(MACROBLOCKD *x); +extern void vp8_setup_interp_filters(MACROBLOCKD *x, INTERPOLATIONFILTERTYPE filter, VP8_COMMON *cm); #endif diff --git a/vp8/decoder/decodemv.c b/vp8/decoder/decodemv.c index 4b4ad919e..3cfdbac0b 100644 --- a/vp8/decoder/decodemv.c +++ b/vp8/decoder/decodemv.c @@ -427,7 +427,21 @@ static const unsigned char mbsplit_fill_offset[4][16] = { { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} }; - +#if CONFIG_SWITCHABLE_INTERP +static void read_switchable_interp_probs(VP8D_COMP *pbi) { + VP8_COMMON *const cm = & pbi->common; + vp8_reader *const bc = & pbi->bc; + int i, j; + for (j = 0; j <= VP8_SWITCHABLE_FILTERS; ++j) { + //for (j = 0; j <= 0; ++j) { + for (i = 0; i < VP8_SWITCHABLE_FILTERS - 1; ++i) { + cm->fc.switchable_interp_prob[j][i] = vp8_read_literal(bc, 8); + } + } + //printf("DECODER: %d %d\n", cm->fc.switchable_interp_prob[0], + //cm->fc.switchable_interp_prob[1]); +} +#endif static void mb_mode_mv_init(VP8D_COMP *pbi) { VP8_COMMON *const cm = & pbi->common; @@ -451,6 +465,10 @@ static void mb_mode_mv_init(VP8D_COMP *pbi) { if (cm->pred_filter_mode == 2) cm->prob_pred_filter_off = (vp8_prob)vp8_read_literal(bc, 8); +#endif +#if CONFIG_SWITCHABLE_INTERP + if (cm->mcomp_filter_type == SWITCHABLE) + read_switchable_interp_probs(pbi); #endif // Decode the baseline probabilities for decoding reference frame cm->prob_intra_coded = (vp8_prob)vp8_read_literal(bc, 8); @@ -634,6 +652,19 @@ static void read_mb_modes_mv(VP8D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi, mbmi->pred_filter_enabled = cm->pred_filter_mode; } #endif +#if CONFIG_SWITCHABLE_INTERP + if (mbmi->mode >= NEARESTMV && mbmi->mode <= SPLITMV) + { + if (cm->mcomp_filter_type == SWITCHABLE) { + mbmi->interp_filter = vp8_switchable_interp[ + vp8_treed_read(bc, vp8_switchable_interp_tree, + get_pred_probs(cm, xd, PRED_SWITCHABLE_INTERP))]; + //printf("Reading: %d\n", mbmi->interp_filter); + } else { + mbmi->interp_filter = cm->mcomp_filter_type; + } + } +#endif if (cm->comp_pred_mode == COMP_PREDICTION_ONLY || (cm->comp_pred_mode == HYBRID_PREDICTION && @@ -928,8 +959,8 @@ static void read_mb_modes_mv(VP8D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi, #endif } } else { - mbmi->uv_mode = (MB_PREDICTION_MODE)vp8_read_uv_mode(bc, - pbi->common.fc.uv_mode_prob[mbmi->mode]); + mbmi->uv_mode = (MB_PREDICTION_MODE)vp8_read_uv_mode( + bc, pbi->common.fc.uv_mode_prob[mbmi->mode]); pbi->common.fc.uv_mode_counts[mbmi->mode][mbmi->uv_mode]++; } diff --git a/vp8/decoder/decodframe.c b/vp8/decoder/decodframe.c index 8cd35143a..c31595d59 100644 --- a/vp8/decoder/decodframe.c +++ b/vp8/decoder/decodframe.c @@ -261,6 +261,11 @@ static void decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd, } mode = xd->mode_info_context->mbmi.mode; +#if CONFIG_SWITCHABLE_INTERP + if (pbi->common.frame_type != KEY_FRAME) + vp8_setup_interp_filters(xd, xd->mode_info_context->mbmi.interp_filter, + &pbi->common); +#endif if (eobtotal == 0 && mode != B_PRED && mode != SPLITMV && mode != I8X8_PRED @@ -750,47 +755,7 @@ static void init_frame(VP8D_COMP *pbi) { pc->mcomp_filter_type = BILINEAR; /* To enable choice of different interploation filters */ - if (pc->mcomp_filter_type == SIXTAP) { - xd->subpixel_predict = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap4x4); - xd->subpixel_predict8x4 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap8x4); - xd->subpixel_predict8x8 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap8x8); - xd->subpixel_predict16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap16x16); - xd->subpixel_predict_avg = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap_avg4x4); - xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap_avg8x8); - xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap_avg16x16); - } -#if CONFIG_ENHANCED_INTERP - else if (pc->mcomp_filter_type == EIGHTTAP) { - xd->subpixel_predict = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap4x4); - xd->subpixel_predict8x4 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap8x4); - xd->subpixel_predict8x8 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap8x8); - xd->subpixel_predict16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap16x16); - xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE( - RTCD_VTABLE(subpix), eighttap_avg8x8); - xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE( - RTCD_VTABLE(subpix), eighttap_avg16x16); - xd->subpixel_predict_avg = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap_avg4x4); - } else if (pc->mcomp_filter_type == EIGHTTAP_SHARP) { - xd->subpixel_predict = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap4x4_sharp); - xd->subpixel_predict8x4 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap8x4_sharp); - xd->subpixel_predict8x8 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap8x8_sharp); - xd->subpixel_predict16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap16x16_sharp); - xd->subpixel_predict_avg = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap_avg4x4_sharp); - xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE( - RTCD_VTABLE(subpix), eighttap_avg8x8_sharp); - xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE( - RTCD_VTABLE(subpix), eighttap_avg16x16_sharp); - } -#endif - else { - xd->subpixel_predict = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear4x4); - xd->subpixel_predict8x4 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear8x4); - xd->subpixel_predict8x8 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear8x8); - xd->subpixel_predict16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear16x16); - xd->subpixel_predict_avg = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear_avg4x4); - xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear_avg8x8); - xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear_avg16x16); - } + vp8_setup_interp_filters(xd, pc->mcomp_filter_type, pc); } xd->left_context = &pc->left_context; @@ -1263,41 +1228,16 @@ int vp8_decode_frame(VP8D_COMP *pbi) { #endif #if CONFIG_ENHANCED_INTERP // Read the type of subpel filter to use - pc->mcomp_filter_type = vp8_read_literal(bc, 2); - /* To enable choice of different interploation filters */ - if (pc->mcomp_filter_type == SIXTAP) { - xd->subpixel_predict = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap4x4); - xd->subpixel_predict8x4 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap8x4); - xd->subpixel_predict8x8 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap8x8); - xd->subpixel_predict16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap16x16); - xd->subpixel_predict_avg = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap_avg4x4); - xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap_avg8x8); - xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), sixtap_avg16x16); - } else if (pc->mcomp_filter_type == EIGHTTAP) { - xd->subpixel_predict = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap4x4); - xd->subpixel_predict8x4 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap8x4); - xd->subpixel_predict8x8 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap8x8); - xd->subpixel_predict16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap16x16); - xd->subpixel_predict_avg = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap_avg4x4); - xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap_avg8x8); - xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap_avg16x16); - } else if (pc->mcomp_filter_type == EIGHTTAP_SHARP) { - xd->subpixel_predict = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap4x4_sharp); - xd->subpixel_predict8x4 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap8x4_sharp); - xd->subpixel_predict8x8 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap8x8_sharp); - xd->subpixel_predict16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap16x16_sharp); - xd->subpixel_predict_avg = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap_avg4x4_sharp); - xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap_avg8x8_sharp); - xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), eighttap_avg16x16_sharp); - } else { - xd->subpixel_predict = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear4x4); - xd->subpixel_predict8x4 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear8x4); - xd->subpixel_predict8x8 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear8x8); - xd->subpixel_predict16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear16x16); - xd->subpixel_predict_avg = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear_avg4x4); - xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear_avg8x8); - xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear_avg16x16); +#if CONFIG_SWITCHABLE_INTERP + if (vp8_read_bit(bc)) { + pc->mcomp_filter_type = SWITCHABLE; + } else +#endif + { + pc->mcomp_filter_type = vp8_read_literal(bc, 2); } + /* To enable choice of different interploation filters */ + vp8_setup_interp_filters(xd, pc->mcomp_filter_type, pc); #endif } diff --git a/vp8/encoder/bitstream.c b/vp8/encoder/bitstream.c index db3e30982..97e791bc6 100644 --- a/vp8/encoder/bitstream.c +++ b/vp8/encoder/bitstream.c @@ -33,17 +33,15 @@ unsigned __int64 Sectionbits[500]; #endif #ifdef ENTROPY_STATS -int intra_mode_stats[VP8_BINTRAMODES] -[VP8_BINTRAMODES] -[VP8_BINTRAMODES]; +int intra_mode_stats [VP8_BINTRAMODES] [VP8_BINTRAMODES] [VP8_BINTRAMODES]; unsigned int tree_update_hist [BLOCK_TYPES] -[COEF_BANDS] -[PREV_COEF_CONTEXTS] -[ENTROPY_NODES][2]; + [COEF_BANDS] + [PREV_COEF_CONTEXTS] + [ENTROPY_NODES][2]; unsigned int tree_update_hist_8x8 [BLOCK_TYPES_8X8] -[COEF_BANDS] -[PREV_COEF_CONTEXTS] -[ENTROPY_NODES] [2]; + [COEF_BANDS] + [PREV_COEF_CONTEXTS] + [ENTROPY_NODES] [2]; extern unsigned int active_section; #endif @@ -173,6 +171,59 @@ void update_skip_probs(VP8_COMP *cpi) { } } +#if CONFIG_SWITCHABLE_INTERP +void update_switchable_interp_probs(VP8_COMP *cpi) { + VP8_COMMON *const pc = & cpi->common; + vp8_writer *const w = & cpi->bc; + unsigned int branch_ct[32][2]; + int i, j; + for (j = 0; j <= VP8_SWITCHABLE_FILTERS; ++j) { + //for (j = 0; j <= 0; ++j) { +/* + if (!cpi->dummy_packing) +#if VP8_SWITCHABLE_FILTERS == 3 + printf("HELLO %d %d %d\n", cpi->switchable_interp_count[j][0], + cpi->switchable_interp_count[j][1], cpi->switchable_interp_count[j][2]); +#else + printf("HELLO %d %d\n", cpi->switchable_interp_count[j][0], + cpi->switchable_interp_count[j][1]); +#endif +*/ + vp8_tree_probs_from_distribution( + VP8_SWITCHABLE_FILTERS, + vp8_switchable_interp_encodings, vp8_switchable_interp_tree, + pc->fc.switchable_interp_prob[j], branch_ct, cpi->switchable_interp_count[j], + 256, 1 + ); + for (i = 0; i < VP8_SWITCHABLE_FILTERS - 1; ++i) { + if (pc->fc.switchable_interp_prob[j][i] < 1) + pc->fc.switchable_interp_prob[j][i] = 1; + vp8_write_literal(w, pc->fc.switchable_interp_prob[j][i], 8); +/* + if (!cpi->dummy_packing) +#if VP8_SWITCHABLE_FILTERS == 3 + printf("Probs %d %d [%d]\n", + pc->fc.switchable_interp_prob[j][0], + pc->fc.switchable_interp_prob[j][1], pc->frame_type); +#else + printf("Probs %d [%d]\n", pc->fc.switchable_interp_prob[j][0], + pc->frame_type); +#endif +*/ + } + } + /* + if (!cpi->dummy_packing) +#if VP8_SWITCHABLE_FILTERS == 3 + printf("Probs %d %d [%d]\n", + pc->fc.switchable_interp_prob[0], pc->fc.switchable_interp_prob[1], pc->frame_type); +#else + printf("Probs %d [%d]\n", pc->fc.switchable_interp_prob[0], pc->frame_type); +#endif + */ +} +#endif + // This function updates the reference frame prediction stats static void update_refpred_stats(VP8_COMP *cpi) { VP8_COMMON *const cm = & cpi->common; @@ -710,6 +761,10 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi) { // printf("pred_filter_mode:%d prob_pred_filter_off:%d\n", // pc->pred_filter_mode, pc->prob_pred_filter_off); #endif +#if CONFIG_SWITCHABLE_INTERP + if (pc->mcomp_filter_type == SWITCHABLE) + update_switchable_interp_probs(cpi); +#endif vp8_write_literal(w, pc->prob_intra_coded, 8); vp8_write_literal(w, pc->prob_last_coded, 8); @@ -906,6 +961,21 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi) { assert(mi->pred_filter_enabled == cpi->common.pred_filter_mode); } +#endif +#if CONFIG_SWITCHABLE_INTERP + if (mode >= NEARESTMV && mode <= SPLITMV) + { + if (cpi->common.mcomp_filter_type == SWITCHABLE) { + vp8_write_token(w, vp8_switchable_interp_tree, + get_pred_probs(&cpi->common, xd, PRED_SWITCHABLE_INTERP), + vp8_switchable_interp_encodings + + vp8_switchable_interp_map[mi->interp_filter]); + //if (!cpi->dummy_packing) printf("Reading: %d\n", mi->interp_filter); + } else { + assert (mi->interp_filter == + cpi->common.mcomp_filter_type); + } + } #endif if (mi->second_ref_frame && (mode == NEWMV || mode == SPLITMV)) { @@ -2204,9 +2274,34 @@ void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size) vp8_write_bit(bc, (xd->allow_high_precision_mv) ? 1 : 0); #endif #if CONFIG_ENHANCED_INTERP +#if CONFIG_SWITCHABLE_INTERP + if (pc->mcomp_filter_type == SWITCHABLE) { + /* Check to see if only one of the filters is actually used */ + int count[VP8_SWITCHABLE_FILTERS]; + int i, j, c = 0; + for (i = 0; i < VP8_SWITCHABLE_FILTERS; ++i) { + count[i] = 0; + for (j = 0; j <= VP8_SWITCHABLE_FILTERS; ++j) { + count[i] += cpi->switchable_interp_count[j][i]; + } + c += (count[i] > 0); + } + if (c == 1) { + /* Only one filter is used. So set the filter at frame level */ + for (i = 0; i < VP8_SWITCHABLE_FILTERS; ++i) { + if (count[i]) { + pc->mcomp_filter_type = vp8_switchable_interp[i]; + break; + } + } + } + } // Signal the type of subpel filter to use - vp8_write_literal(bc, (pc->mcomp_filter_type), 2); -#endif + vp8_write_bit(bc, (pc->mcomp_filter_type == SWITCHABLE)); + if (pc->mcomp_filter_type != SWITCHABLE) +#endif /* CONFIG_SWITCHABLE_INTERP */ + vp8_write_literal(bc, (pc->mcomp_filter_type), 2); +#endif /* CONFIG_ENHANCED_INTERP */ } vp8_write_bit(bc, pc->refresh_entropy_probs); diff --git a/vp8/encoder/block.h b/vp8/encoder/block.h index 766e80776..b69ffa94e 100644 --- a/vp8/encoder/block.h +++ b/vp8/encoder/block.h @@ -13,10 +13,10 @@ #define __INC_BLOCK_H #include "vp8/common/onyx.h" -#include "vp8/common/blockd.h" #include "vp8/common/entropymv.h" #include "vp8/common/entropy.h" #include "vpx_ports/mem.h" +#include "vp8/common/onyxc_int.h" // motion search site typedef struct { @@ -122,6 +122,10 @@ typedef struct { int bmode_costs[VP8_BINTRAMODES][VP8_BINTRAMODES][VP8_BINTRAMODES]; int i8x8_mode_costs[MB_MODE_COUNT]; int inter_bmode_costs[B_MODE_COUNT]; +#if CONFIG_SWITCHABLE_INTERP + int switchable_interp_costs[VP8_SWITCHABLE_FILTERS+1] + [VP8_SWITCHABLE_FILTERS]; +#endif // These define limits to motion vector components to prevent them from extending outside the UMV borders int mv_col_min; diff --git a/vp8/encoder/encodeframe.c b/vp8/encoder/encodeframe.c index 737348ace..909d56961 100644 --- a/vp8/encoder/encodeframe.c +++ b/vp8/encoder/encodeframe.c @@ -69,7 +69,6 @@ void vp8cx_encode_intra_macro_block(VP8_COMP *cpi, MACROBLOCK *x, static void adjust_act_zbin(VP8_COMP *cpi, MACROBLOCK *x); - #ifdef MODE_STATS unsigned int inter_y_modes[MB_MODE_COUNT]; unsigned int inter_uv_modes[VP8_UV_MODES]; @@ -1094,71 +1093,7 @@ static void encode_frame_internal(VP8_COMP *cpi) { totalrate = 0; // Functions setup for all frame types so we can use MC in AltRef - if (cm->mcomp_filter_type == SIXTAP) { - xd->subpixel_predict = SUBPIX_INVOKE( - &cpi->common.rtcd.subpix, sixtap4x4); - xd->subpixel_predict8x4 = SUBPIX_INVOKE( - &cpi->common.rtcd.subpix, sixtap8x4); - xd->subpixel_predict8x8 = SUBPIX_INVOKE( - &cpi->common.rtcd.subpix, sixtap8x8); - xd->subpixel_predict16x16 = SUBPIX_INVOKE( - &cpi->common.rtcd.subpix, sixtap16x16); - xd->subpixel_predict_avg = SUBPIX_INVOKE( - &cpi->common.rtcd.subpix, sixtap_avg4x4); - xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE( - &cpi->common.rtcd.subpix, sixtap_avg8x8); - xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE( - &cpi->common.rtcd.subpix, sixtap_avg16x16); - } -#if CONFIG_ENHANCED_INTERP - else if (cm->mcomp_filter_type == EIGHTTAP) { - xd->subpixel_predict = SUBPIX_INVOKE( - &cpi->common.rtcd.subpix, eighttap4x4); - xd->subpixel_predict8x4 = SUBPIX_INVOKE( - &cpi->common.rtcd.subpix, eighttap8x4); - xd->subpixel_predict8x8 = SUBPIX_INVOKE( - &cpi->common.rtcd.subpix, eighttap8x8); - xd->subpixel_predict16x16 = SUBPIX_INVOKE( - &cpi->common.rtcd.subpix, eighttap16x16); - xd->subpixel_predict_avg = SUBPIX_INVOKE( - &cpi->common.rtcd.subpix, eighttap_avg4x4); - xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE( - &cpi->common.rtcd.subpix, eighttap_avg8x8); - xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE( - &cpi->common.rtcd.subpix, eighttap_avg16x16); - } else if (cm->mcomp_filter_type == EIGHTTAP_SHARP) { - xd->subpixel_predict = SUBPIX_INVOKE( - &cpi->common.rtcd.subpix, eighttap4x4_sharp); - xd->subpixel_predict8x4 = SUBPIX_INVOKE( - &cpi->common.rtcd.subpix, eighttap8x4_sharp); - xd->subpixel_predict8x8 = SUBPIX_INVOKE( - &cpi->common.rtcd.subpix, eighttap8x8_sharp); - xd->subpixel_predict16x16 = SUBPIX_INVOKE( - &cpi->common.rtcd.subpix, eighttap16x16_sharp); - xd->subpixel_predict_avg = SUBPIX_INVOKE( - &cpi->common.rtcd.subpix, eighttap_avg4x4_sharp); - xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE( - &cpi->common.rtcd.subpix, eighttap_avg8x8_sharp); - xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE( - &cpi->common.rtcd.subpix, eighttap_avg16x16_sharp); - } -#endif - else { - xd->subpixel_predict = SUBPIX_INVOKE( - &cpi->common.rtcd.subpix, bilinear4x4); - xd->subpixel_predict8x4 = SUBPIX_INVOKE( - &cpi->common.rtcd.subpix, bilinear8x4); - xd->subpixel_predict8x8 = SUBPIX_INVOKE( - &cpi->common.rtcd.subpix, bilinear8x8); - xd->subpixel_predict16x16 = SUBPIX_INVOKE( - &cpi->common.rtcd.subpix, bilinear16x16); - xd->subpixel_predict_avg = SUBPIX_INVOKE( - &cpi->common.rtcd.subpix, bilinear_avg4x4); - xd->subpixel_predict_avg8x8 = SUBPIX_INVOKE( - &cpi->common.rtcd.subpix, bilinear_avg8x8); - xd->subpixel_predict_avg16x16 = SUBPIX_INVOKE( - &cpi->common.rtcd.subpix, bilinear_avg16x16); - } + vp8_setup_interp_filters(xd, cm->mcomp_filter_type, cm); // Reset frame count of inter 0,0 motion vector usage. cpi->inter_zz_count = 0; @@ -1177,7 +1112,9 @@ static void encode_frame_internal(VP8_COMP *cpi) { } cpi->pred_filter_on_count = 0; cpi->pred_filter_off_count = 0; - +#endif +#if CONFIG_SWITCHABLE_INTERP + vp8_zero(cpi->switchable_interp_count); #endif #if 0 @@ -1547,6 +1484,9 @@ void vp8cx_encode_inter_macroblock x->skip = 0; +#if CONFIG_SWITCHABLE_INTERP + vp8_setup_interp_filters(xd, xd->mode_info_context->mbmi.interp_filter, cm); +#endif if (cpi->oxcf.tuning == VP8_TUNE_SSIM) { // Adjust the zbin based on this MB rate. adjust_act_zbin(cpi, x); diff --git a/vp8/encoder/modecosts.c b/vp8/encoder/modecosts.c index 8752eead7..b1abd1e2a 100644 --- a/vp8/encoder/modecosts.c +++ b/vp8/encoder/modecosts.c @@ -46,4 +46,14 @@ void vp8_init_mode_costs(VP8_COMP *c) { vp8_cost_tokens(c->mb.i8x8_mode_costs, x->fc.i8x8_mode_prob, vp8_i8x8_mode_tree); +#if CONFIG_SWITCHABLE_INTERP + { + int i; + for (i = 0; i <= VP8_SWITCHABLE_FILTERS; ++i) + //for (i = 0; i <= 0; ++i) + vp8_cost_tokens((int *)c->mb.switchable_interp_costs[i], + x->fc.switchable_interp_prob[i], + vp8_switchable_interp_tree); + } +#endif } diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c index 05fe0ff75..5b6684ac8 100644 --- a/vp8/encoder/onyx_if.c +++ b/vp8/encoder/onyx_if.c @@ -82,16 +82,16 @@ static void set_default_lf_deltas(VP8_COMP *cpi); extern const int vp8_gf_interval_table[101]; #if CONFIG_ENHANCED_INTERP -#define SEARCH_BEST_FILTER 0 /* to search exhaustively for best filter */ +#define SEARCH_BEST_FILTER 0 /* to search for best filter */ #define RESET_FOREACH_FILTER 0 /* whether to reset the encoder state -before trying each new filter */ + * before trying each new filter */ +#define SHARP_FILTER_QTHRESH 0 /* Q threshold for 8-tap sharp filter */ #endif #if CONFIG_HIGH_PRECISION_MV #define ALTREF_HIGH_PRECISION_MV 1 /* whether to use high precision mv for altref computation */ -#define HIGH_PRECISION_MV_QTHRESH 200 /* Q threshold for use of high precision mv */ -/* Choose a very high value for now so - * that HIGH_PRECISION is always chosen - */ +#define HIGH_PRECISION_MV_QTHRESH 200 /* Q threshold for use of high precision mv + * Choose a very high value for now so + * that HIGH_PRECISION is always chosen */ #endif #if CONFIG_INTERNAL_STATS @@ -207,6 +207,7 @@ int calculate_minq_index(double maxq, } return QINDEX_RANGE - 1; } + void init_minq_luts() { int i; double maxq; @@ -706,6 +707,14 @@ void vp8_set_speed_features(VP8_COMP *cpi) { sf->thresh_mult[THR_V_PRED ] = 1000; sf->thresh_mult[THR_H_PRED ] = 1000; +#if CONFIG_NEWINTRAMODES + sf->thresh_mult[THR_D45_PRED ] = 1000; + sf->thresh_mult[THR_D135_PRED] = 1000; + sf->thresh_mult[THR_D117_PRED] = 1000; + sf->thresh_mult[THR_D153_PRED] = 1000; + sf->thresh_mult[THR_D27_PRED ] = 1000; + sf->thresh_mult[THR_D63_PRED ] = 1000; +#endif sf->thresh_mult[THR_B_PRED ] = 2000; sf->thresh_mult[THR_I8X8_PRED] = 2000; sf->thresh_mult[THR_TM ] = 1000; @@ -2902,7 +2911,13 @@ static void encode_frame_to_data_rate #endif /* list of filters to search over */ - int mcomp_filters_to_search[] = {EIGHTTAP, EIGHTTAP_SHARP, SIXTAP}; + int mcomp_filters_to_search[] = { +#if CONFIG_SWITCHABLE_INTERP + EIGHTTAP, EIGHTTAP_SHARP, SIXTAP, SWITCHABLE +#else + EIGHTTAP, EIGHTTAP_SHARP, SIXTAP, +#endif + }; int mcomp_filters = sizeof(mcomp_filters_to_search) / sizeof(*mcomp_filters_to_search); int mcomp_filter_index = 0; INT64 mcomp_filter_cost[4]; @@ -3129,8 +3144,14 @@ static void encode_frame_to_data_rate if (sf->search_best_filter) { cm->mcomp_filter_type = mcomp_filters_to_search[0]; mcomp_filter_index = 0; - } else - cm->mcomp_filter_type = EIGHTTAP; + } else { +#if CONFIG_SWITCHABLE_INTERP + cm->mcomp_filter_type = SWITCHABLE; +#else + cm->mcomp_filter_type = + (Q < SHARP_FILTER_QTHRESH ? EIGHTTAP_SHARP : EIGHTTAP); +#endif + } #endif #if CONFIG_HIGH_PRECISION_MV /* TODO: Decide this more intelligently */ @@ -3434,7 +3455,9 @@ static void encode_frame_to_data_rate Q = q_low; // Clamp cpi->zbin_over_quant - cpi->zbin_over_quant = (cpi->zbin_over_quant < zbin_oq_low) ? zbin_oq_low : (cpi->zbin_over_quant > zbin_oq_high) ? zbin_oq_high : cpi->zbin_over_quant; + cpi->zbin_over_quant = (cpi->zbin_over_quant < zbin_oq_low) ? + zbin_oq_low : (cpi->zbin_over_quant > zbin_oq_high) ? + zbin_oq_high : cpi->zbin_over_quant; // Loop = ((Q != last_q) || (last_zbin_oq != cpi->zbin_over_quant)) ? TRUE : FALSE; Loop = ((Q != last_q)) ? TRUE : FALSE; @@ -3445,6 +3468,40 @@ static void encode_frame_to_data_rate if (cpi->is_src_frame_alt_ref) Loop = FALSE; +#if CONFIG_ENHANCED_INTERP && CONFIG_SWITCHABLE_INTERP + if (cm->frame_type != KEY_FRAME && + !sf->search_best_filter && + cm->mcomp_filter_type == SWITCHABLE) { + int interp_factor = Q / 3; /* denominator is 256 */ + int count[VP8_SWITCHABLE_FILTERS]; + int tot_count = 0, c = 0, thr; + int i, j; + for (i = 0; i < VP8_SWITCHABLE_FILTERS; ++i) { + count[i] = 0; + for (j = 0; j <= VP8_SWITCHABLE_FILTERS; ++j) { + count[i] += cpi->switchable_interp_count[j][i]; + } + tot_count += count[i]; + } + + thr = ((tot_count * interp_factor + 128) >> 8); + for (i = 0; i < VP8_SWITCHABLE_FILTERS; ++i) { + c += (count[i] >= thr); + } + if (c == 1) { + /* Mostly one filter is used. So set the filter at frame level */ + for (i = 0; i < VP8_SWITCHABLE_FILTERS; ++i) { + if (count[i]) { + cm->mcomp_filter_type = vp8_switchable_interp[i]; + Loop = TRUE; /* Make sure to loop since the filter changed */ + //loop_count = -1; + break; + } + } + } + } +#endif + #if CONFIG_ENHANCED_INTERP if (Loop == FALSE && cm->frame_type != KEY_FRAME && sf->search_best_filter) { if (mcomp_filter_index < mcomp_filters) { @@ -3498,7 +3555,7 @@ static void encode_frame_to_data_rate #endif } } -#endif +#endif /* CONFIG_ENHANCED_INTERP */ if (Loop == TRUE) { loop_count++; diff --git a/vp8/encoder/onyx_int.h b/vp8/encoder/onyx_int.h index cf7193324..2821aadd0 100644 --- a/vp8/encoder/onyx_int.h +++ b/vp8/encoder/onyx_int.h @@ -102,6 +102,11 @@ typedef struct { vp8_prob sub_mv_ref_prob [SUBMVREF_COUNT][VP8_SUBMVREFS - 1]; vp8_prob mbsplit_prob [VP8_NUMMBSPLITS - 1]; +#if CONFIG_SWITCHABLE_INTERP + vp8_prob switchable_interp_prob[VP8_SWITCHABLE_FILTERS + 1] + [VP8_SWITCHABLE_FILTERS - 1]; +#endif + int mv_ref_ct[6][4][2]; int mode_context[6][4]; int mv_ref_ct_a[6][4][2]; @@ -724,6 +729,10 @@ typedef struct VP8_COMP { int pred_filter_on_count; int pred_filter_off_count; #endif +#if CONFIG_SWITCHABLE_INTERP + unsigned int switchable_interp_count[VP8_SWITCHABLE_FILTERS+1] + [VP8_SWITCHABLE_FILTERS]; +#endif } VP8_COMP; diff --git a/vp8/encoder/ratectrl.c b/vp8/encoder/ratectrl.c index 9885f8742..43f38568a 100644 --- a/vp8/encoder/ratectrl.c +++ b/vp8/encoder/ratectrl.c @@ -174,6 +174,9 @@ void vp8_save_coding_context(VP8_COMP *cpi) { vp8_copy(cc->coef_probs, cm->fc.coef_probs); vp8_copy(cc->coef_probs_8x8, cm->fc.coef_probs_8x8); +#if CONFIG_SWITCHABLE_INTERP + vp8_copy(cc->switchable_interp_prob, cm->fc.switchable_interp_prob); +#endif } void vp8_restore_coding_context(VP8_COMP *cpi) { @@ -227,6 +230,9 @@ void vp8_restore_coding_context(VP8_COMP *cpi) { vp8_copy(cm->fc.coef_probs, cc->coef_probs); vp8_copy(cm->fc.coef_probs_8x8, cc->coef_probs_8x8); +#if CONFIG_SWITCHABLE_INTERP + vp8_copy(cm->fc.switchable_interp_prob, cc->switchable_interp_prob); +#endif } diff --git a/vp8/encoder/rdopt.c b/vp8/encoder/rdopt.c index cd45074b7..5fd92a5fa 100644 --- a/vp8/encoder/rdopt.c +++ b/vp8/encoder/rdopt.c @@ -64,6 +64,11 @@ extern void vp8_ht_quantize_b(BLOCK *b, BLOCKD *d); #define INVALID_MV 0x80008000 +#if CONFIG_SWITCHABLE_INTERP +/* Factor to weigh the rate for switchable interp filters */ +#define SWITCHABLE_INTERP_RATE_FACTOR 1 +#endif + static const int auto_speed_thresh[17] = { 1000, 200, @@ -2682,6 +2687,9 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int // int all_rates[MAX_MODES]; // int all_dist[MAX_MODES]; // int intermodecost[MAX_MODES]; +#if CONFIG_SWITCHABLE_INTERP + int switchable_filter_index = 0; +#endif MB_PREDICTION_MODE uv_intra_mode; MB_PREDICTION_MODE uv_intra_mode_8x8 = 0; @@ -2792,18 +2800,18 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int // that depend on the current prediction etc. vp8_estimate_ref_frame_costs(cpi, segment_id, ref_costs); - for (mode_index = 0; mode_index < MAX_MODES; mode_index++) { +#if CONFIG_SWITCHABLE_INTERP + for (mode_index = 0; mode_index < MAX_MODES; + mode_index += (!switchable_filter_index)) { +#else + for (mode_index = 0; mode_index < MAX_MODES; ++mode_index) { +#endif int this_rd = INT_MAX; int disable_skip = 0; int other_cost = 0; int compmode_cost = 0; int mode_excluded = 0; - // Test best rd so far against threshold for trying this mode. - if (best_rd <= cpi->rd_threshes[mode_index]) { - continue; - } - // These variables hold are rolling total cost and distortion for this mode rate2 = 0; distortion2 = 0; @@ -2820,6 +2828,25 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int #if CONFIG_PRED_FILTER xd->mode_info_context->mbmi.pred_filter_enabled = 0; #endif +#if CONFIG_SWITCHABLE_INTERP + if (cpi->common.mcomp_filter_type == SWITCHABLE && + this_mode >= NEARESTMV && this_mode <= SPLITMV) { + xd->mode_info_context->mbmi.interp_filter = + vp8_switchable_interp[switchable_filter_index++]; + if (switchable_filter_index == VP8_SWITCHABLE_FILTERS) + switchable_filter_index = 0; + //printf("Searching %d (%d)\n", this_mode, switchable_filter_index); + } else { + xd->mode_info_context->mbmi.interp_filter = cpi->common.mcomp_filter_type; + } + vp8_setup_interp_filters(xd, xd->mode_info_context->mbmi.interp_filter, + &cpi->common); +#endif + + // Test best rd so far against threshold for trying this mode. + if (best_rd <= cpi->rd_threshes[mode_index]) { + continue; + } // current coding mode under rate-distortion optimization test loop #if CONFIG_HYBRIDTRANSFORM @@ -2906,7 +2933,7 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int } - if (!x->e_mbd.mode_info_context->mbmi.second_ref_frame) + if (!x->e_mbd.mode_info_context->mbmi.second_ref_frame) { switch (this_mode) { case B_PRED: { int tmp_rd; @@ -2934,7 +2961,8 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int case I8X8_PRED: { int tmp_rd; tmp_rd = rd_pick_intra8x8mby_modes(cpi, - x, &rate, &rate_y, &distortion, best_yrd); + x, &rate, &rate_y, &distortion, + best_yrd); rate2 += rate; distortion2 += distortion; @@ -2967,17 +2995,30 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int int tmp_rd; int this_rd_thresh; - this_rd_thresh = (x->e_mbd.mode_info_context->mbmi.ref_frame == LAST_FRAME) ? cpi->rd_threshes[THR_NEWMV] : cpi->rd_threshes[THR_NEWA]; - this_rd_thresh = (x->e_mbd.mode_info_context->mbmi.ref_frame == GOLDEN_FRAME) ? cpi->rd_threshes[THR_NEWG] : this_rd_thresh; + this_rd_thresh = + (x->e_mbd.mode_info_context->mbmi.ref_frame == LAST_FRAME) ? + cpi->rd_threshes[THR_NEWMV] : cpi->rd_threshes[THR_NEWA]; + this_rd_thresh = + (x->e_mbd.mode_info_context->mbmi.ref_frame == GOLDEN_FRAME) ? + cpi->rd_threshes[THR_NEWG] : this_rd_thresh; tmp_rd = vp8_rd_pick_best_mbsegmentation(cpi, x, &best_ref_mv, NULL, best_yrd, mdcounts, - &rate, &rate_y, &distortion, this_rd_thresh, seg_mvs); + &rate, &rate_y, &distortion, + this_rd_thresh, seg_mvs); rate2 += rate; distortion2 += distortion; - // If even the 'Y' rd value of split is higher than best so far then dont bother looking at UV +#if CONFIG_SWITCHABLE_INTERP + if (cpi->common.mcomp_filter_type == SWITCHABLE) + rate2 += SWITCHABLE_INTERP_RATE_FACTOR * x->switchable_interp_costs + [get_pred_context(&cpi->common, xd, PRED_SWITCHABLE_INTERP)] + [vp8_switchable_interp_map[ + x->e_mbd.mode_info_context->mbmi.interp_filter]]; +#endif + // If even the 'Y' rd value of split is higher than best so far + // then dont bother looking at UV if (tmp_rd < best_yrd) { // Now work out UV cost and add it in rd_inter4x4_uv(cpi, x, &rate_uv, &distortion_uv, cpi->common.full_pixel); @@ -3174,7 +3215,8 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int vp8_clamp_mv2(&mode_mv[this_mode], xd); // Do not bother proceeding if the vector (from newmv,nearest or near) is 0,0 as this should then be coded using the zeromv mode. - if (((this_mode == NEARMV) || (this_mode == NEARESTMV)) && (mode_mv[this_mode].as_int == 0)) { + if (((this_mode == NEARMV) || (this_mode == NEARESTMV)) && + (mode_mv[this_mode].as_int == 0)) { continue; } @@ -3183,8 +3225,10 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int // Trap vectors that reach beyond the UMV borders // Note that ALL New MV, Nearest MV Near MV and Zero MV code drops through to this point // because of the lack of break statements in the previous two cases. - if (((mode_mv[this_mode].as_mv.row >> 3) < x->mv_row_min) || ((mode_mv[this_mode].as_mv.row >> 3) > x->mv_row_max) || - ((mode_mv[this_mode].as_mv.col >> 3) < x->mv_col_min) || ((mode_mv[this_mode].as_mv.col >> 3) > x->mv_col_max)) { + if (((mode_mv[this_mode].as_mv.row >> 3) < x->mv_row_min) || + ((mode_mv[this_mode].as_mv.row >> 3) > x->mv_row_max) || + ((mode_mv[this_mode].as_mv.col >> 3) < x->mv_col_min) || + ((mode_mv[this_mode].as_mv.col >> 3) > x->mv_col_max)) { continue; } @@ -3197,6 +3241,13 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int rate2 += vp8_cost_bit(cpi->common.prob_pred_filter_off, xd->mode_info_context->mbmi.pred_filter_enabled); #endif +#if CONFIG_SWITCHABLE_INTERP + if (cpi->common.mcomp_filter_type == SWITCHABLE) + rate2 += SWITCHABLE_INTERP_RATE_FACTOR * x->switchable_interp_costs + [get_pred_context(&cpi->common, xd, PRED_SWITCHABLE_INTERP)] + [vp8_switchable_interp_map[ + x->e_mbd.mode_info_context->mbmi.interp_filter]]; +#endif vp8_build_inter16x16_predictors_mby(&x->e_mbd); @@ -3278,7 +3329,7 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int default: break; } - else { /* x->e_mbd.mode_info_context->mbmi.second_ref_frame != 0 */ + } else { /* x->e_mbd.mode_info_context->mbmi.second_ref_frame != 0 */ int ref1 = x->e_mbd.mode_info_context->mbmi.ref_frame; int ref2 = x->e_mbd.mode_info_context->mbmi.second_ref_frame; @@ -3330,12 +3381,18 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int int tmp_rd; int this_rd_thresh; - this_rd_thresh = (x->e_mbd.mode_info_context->mbmi.ref_frame == LAST_FRAME) ? cpi->rd_threshes[THR_NEWMV] : cpi->rd_threshes[THR_NEWA]; - this_rd_thresh = (x->e_mbd.mode_info_context->mbmi.ref_frame == GOLDEN_FRAME) ? cpi->rd_threshes[THR_NEWG] : this_rd_thresh; + this_rd_thresh = + (x->e_mbd.mode_info_context->mbmi.ref_frame == LAST_FRAME) ? + cpi->rd_threshes[THR_NEWMV] : cpi->rd_threshes[THR_NEWA]; + this_rd_thresh = + (x->e_mbd.mode_info_context->mbmi.ref_frame == GOLDEN_FRAME) ? + cpi->rd_threshes[THR_NEWG] : this_rd_thresh; - tmp_rd = vp8_rd_pick_best_mbsegmentation(cpi, x, &best_ref_mv, &second_best_ref_mv, + tmp_rd = vp8_rd_pick_best_mbsegmentation(cpi, x, &best_ref_mv, + &second_best_ref_mv, best_yrd, mdcounts, - &rate, &rate_y, &distortion, this_rd_thresh, seg_mvs); + &rate, &rate_y, &distortion, + this_rd_thresh, seg_mvs); rate2 += rate; distortion2 += distortion; @@ -3488,6 +3545,12 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int this_rd = RDCOST(x->rdmult, x->rddiv, rate2, distortion2); } +#if 0//CONFIG_SWITCHABLE_INTERP + if (this_mode >= NEARESTMV && this_mode <= SPLITMV && + cm->mcomp_filter_type == SWITCHABLE) + printf("mode %d (%d): %d\n", this_mode, switchable_filter_index, this_rd); +#endif + // Experimental debug code. // all_rds[mode_index] = this_rd; // all_rates[mode_index] = rate2; @@ -3560,11 +3623,17 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int } } - // Testing this mode gave rise to an improvement in best error score. Lower threshold a bit for next time - cpi->rd_thresh_mult[mode_index] = (cpi->rd_thresh_mult[mode_index] >= (MIN_THRESHMULT + 2)) ? cpi->rd_thresh_mult[mode_index] - 2 : MIN_THRESHMULT; - cpi->rd_threshes[mode_index] = (cpi->rd_baseline_thresh[mode_index] >> 7) * cpi->rd_thresh_mult[mode_index]; + // Testing this mode gave rise to an improvement in best error score. + // Lower threshold a bit for next time + cpi->rd_thresh_mult[mode_index] = + (cpi->rd_thresh_mult[mode_index] >= (MIN_THRESHMULT + 2)) ? + cpi->rd_thresh_mult[mode_index] - 2 : MIN_THRESHMULT; + cpi->rd_threshes[mode_index] = + (cpi->rd_baseline_thresh[mode_index] >> 7) * + cpi->rd_thresh_mult[mode_index]; } - // If the mode did not help improve the best error case then raise the threshold for testing that mode next time around. + // If the mode did not help improve the best error case then raise the + // threshold for testing that mode next time around. else { cpi->rd_thresh_mult[mode_index] += 4; @@ -3617,13 +3686,29 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int else ++cpi->pred_filter_off_count; #endif +#if CONFIG_SWITCHABLE_INTERP + //printf("Bestmode %d (%d): %d\n", best_mbmode.mode, best_mbmode.interp_filter, best_rd); + if (cpi->common.mcomp_filter_type == SWITCHABLE && + best_mbmode.mode >= NEARESTMV && + best_mbmode.mode <= SPLITMV) { + ++cpi->switchable_interp_count + [get_pred_context(&cpi->common, xd, PRED_SWITCHABLE_INTERP)] + [vp8_switchable_interp_map[best_mbmode.interp_filter]]; + } +#endif // Reduce the activation RD thresholds for the best choice mode - if ((cpi->rd_baseline_thresh[best_mode_index] > 0) && (cpi->rd_baseline_thresh[best_mode_index] < (INT_MAX >> 2))) { + if ((cpi->rd_baseline_thresh[best_mode_index] > 0) && + (cpi->rd_baseline_thresh[best_mode_index] < (INT_MAX >> 2))) { int best_adjustment = (cpi->rd_thresh_mult[best_mode_index] >> 2); - cpi->rd_thresh_mult[best_mode_index] = (cpi->rd_thresh_mult[best_mode_index] >= (MIN_THRESHMULT + best_adjustment)) ? cpi->rd_thresh_mult[best_mode_index] - best_adjustment : MIN_THRESHMULT; - cpi->rd_threshes[best_mode_index] = (cpi->rd_baseline_thresh[best_mode_index] >> 7) * cpi->rd_thresh_mult[best_mode_index]; + cpi->rd_thresh_mult[best_mode_index] = + (cpi->rd_thresh_mult[best_mode_index] >= + (MIN_THRESHMULT + best_adjustment)) ? + cpi->rd_thresh_mult[best_mode_index] - best_adjustment : MIN_THRESHMULT; + cpi->rd_threshes[best_mode_index] = + (cpi->rd_baseline_thresh[best_mode_index] >> 7) * + cpi->rd_thresh_mult[best_mode_index]; // If we chose a split mode then reset the new MV thresholds as well /*if ( vp8_mode_order[best_mode_index].mode == SPLITMV )