Optimize entropy coding of non-transform tokens

Use separate token probabilities and counters for non-transform
blocks (pixel domain) . Initial probabilities are trained with screen_content
clips. On screen_content, it improves coding performance by about
2% (from +16.4% to +18.45%).

The initial probabilities are not optimized for natural videos. So it should
not be used for natural videos. Set FOR_SCREEN_CONTENT as 0/1 to specify
whether or not to enable this patch.

Change-Id: Ifa361c94bb62aa4b783cbfa50de08c3fecae0984
This commit is contained in:
hui su 2015-04-21 14:10:19 -07:00
parent 2189a51891
commit 00c793ee5f
16 changed files with 1248 additions and 67 deletions

View File

@ -1153,6 +1153,444 @@ static const vp9_coeff_probs_model default_coef_probs_64x64[PLANE_TYPES] = {
}; };
#endif // CONFIG_TX64X64 #endif // CONFIG_TX64X64
#if CONFIG_TX_SKIP
static const
vp9_coeff_probs_pxd default_coef_probs_pxd[TX_SIZES][PLANE_TYPES] = {
{ // TX_SIZE 0
{ // Y plane
{ // Intra
{ // ctx 0
134, 203, 40, 59, 123, 156, 93, 128, 250, 149, 254,
},
{ // ctx 1
96, 150, 110, 182, 143, 161, 178, 152, 246, 161, 246,
},
{ // ctx 2
49, 123, 54, 123, 112, 153, 215, 133, 246, 166, 246,
},
{ // ctx 3
42, 105, 29, 73, 89, 144, 47, 143, 249, 148, 252,
},
{ // ctx 4
27, 85, 28, 71, 96, 135, 218, 125, 244, 182, 247,
},
{ // ctx 5
44, 130, 10, 18, 104, 143, 30, 98, 245, 145, 245,
},
},
{ // Inter
{ // ctx 0
119, 199, 129, 217, 153, 175, 230, 170, 253, 215, 254,
},
{ // ctx 1
72, 127, 132, 216, 149, 175, 229, 166, 254, 225, 254,
},
{ // ctx 2
38, 90, 88, 195, 127, 165, 228, 156, 254, 222, 250,
},
{ // ctx 3
17, 59, 61, 173, 99, 156, 214, 140, 254, 220, 254,
},
{ // ctx 4
11, 40, 37, 101, 89, 132, 216, 115, 254, 225, 254,
},
{ // ctx 5
6, 23, 18, 53, 81, 129, 105, 97, 253, 179, 253,
},
},
},
{ // UV plane
{ // Intra
{ // ctx 0
77, 209, 164, 218, 157, 175, 244, 175, 254, 248, 128,
},
{ // ctx 1
52, 122, 142, 210, 159, 175, 227, 155, 254, 246, 128,
},
{ // ctx 2
27, 88, 99, 190, 127, 162, 235, 164, 254, 233, 128,
},
{ // ctx 3
15, 46, 71, 158, 106, 150, 219, 141, 254, 244, 128,
},
{ // ctx 4
8, 37, 54, 117, 100, 142, 215, 133, 254, 234, 128,
},
{ // ctx 5
3, 17, 46, 72, 118, 143, 146, 104, 254, 220, 254,
},
},
{ // Inter
{ // ctx 0
116, 205, 194, 220, 168, 176, 240, 169, 254, 242, 254,
},
{ // ctx 1
73, 133, 184, 214, 168, 172, 232, 158, 254, 240, 254,
},
{ // ctx 2
41, 100, 122, 184, 142, 160, 224, 143, 254, 229, 254,
},
{ // ctx 3
21, 55, 79, 153, 111, 150, 218, 128, 254, 245, 254,
},
{ // ctx 4
12, 39, 51, 105, 98, 138, 209, 113, 254, 241, 254,
},
{ // ctx 5
4, 17, 37, 61, 102, 130, 137, 97, 254, 218, 254,
},
},
},
},
{ // TX_SIZE 1
{ // Y plane
{ // Intra
{ // ctx 0
40, 234, 75, 154, 108, 139, 155, 154, 252, 219, 252,
},
{ // ctx 1
25, 136, 105, 180, 150, 161, 196, 142, 249, 199, 253,
},
{ // ctx 2
17, 112, 54, 146, 95, 141, 202, 138, 250, 197, 252,
},
{ // ctx 3
11, 78, 39, 107, 88, 140, 131, 120, 248, 194, 251,
},
{ // ctx 4
6, 47, 31, 84, 95, 137, 174, 117, 249, 186, 250,
},
{ // ctx 5
5, 42, 18, 46, 95, 138, 88, 96, 241, 166, 249,
},
},
{ // Inter
{ // ctx 0
76, 241, 56, 97, 115, 154, 126, 104, 207, 141, 254,
},
{ // ctx 1
41, 145, 87, 138, 122, 148, 185, 122, 242, 205, 252,
},
{ // ctx 2
25, 100, 39, 95, 96, 142, 207, 85, 246, 205, 253,
},
{ // ctx 3
17, 77, 25, 62, 91, 135, 95, 104, 232, 185, 252,
},
{ // ctx 4
9, 38, 23, 63, 88, 127, 182, 82, 247, 194, 248,
},
{ // ctx 5
9, 36, 10, 28, 86, 127, 61, 89, 225, 159, 251,
},
},
},
{ // UV plane
{ // Intra
{ // ctx 0
76, 234, 176, 221, 163, 178, 245, 179, 254, 250, 128,
},
{ // ctx 1
27, 135, 152, 221, 165, 179, 232, 159, 254, 245, 128,
},
{ // ctx 2
12, 85, 96, 194, 127, 160, 243, 169, 254, 237, 128,
},
{ // ctx 3
7, 47, 66, 161, 108, 150, 222, 147, 254, 242, 128,
},
{ // ctx 4
4, 36, 46, 122, 91, 137, 223, 138, 254, 233, 254,
},
{ // ctx 5
1, 17, 35, 61, 110, 136, 143, 101, 254, 220, 254,
},
},
{ // Inter
{ // ctx 0
130, 234, 165, 188, 150, 160, 215, 129, 254, 251, 128,
},
{ // ctx 1
41, 139, 156, 195, 170, 165, 209, 111, 254, 253, 128,
},
{ // ctx 2
18, 84, 89, 141, 131, 157, 212, 90, 254, 249, 128,
},
{ // ctx 3
8, 40, 47, 83, 95, 147, 170, 80, 254, 252, 128,
},
{ // ctx 4
8, 36, 42, 74, 93, 136, 168, 93, 254, 245, 254,
},
{ // ctx 5
3, 28, 34, 70, 92, 129, 150, 97, 254, 236, 254,
},
},
},
},
{ // TX_SIZE 2
{ // Y plane
{ // Intra
{ // ctx 0
40, 245, 54, 152, 84, 117, 194, 188, 248, 199, 253,
},
{ // ctx 1
15, 137, 96, 199, 185, 163, 192, 142, 246, 194, 246,
},
{ // ctx 2
8, 121, 36, 158, 72, 129, 217, 169, 250, 192, 252,
},
{ // ctx 3
6, 77, 30, 124, 55, 129, 121, 118, 244, 175, 251,
},
{ // ctx 4
4, 57, 23, 65, 91, 135, 174, 141, 248, 181, 251,
},
{ // ctx 5
3, 31, 14, 36, 90, 135, 76, 92, 238, 152, 249,
},
},
{ // Inter
{ // ctx 0
118, 247, 104, 164, 139, 178, 146, 140, 232, 148, 254,
},
{ // ctx 1
24, 142, 121, 218, 152, 192, 165, 165, 244, 164, 254,
},
{ // ctx 2
10, 108, 64, 183, 110, 178, 179, 168, 239, 140, 254,
},
{ // ctx 3
5, 63, 28, 98, 88, 166, 109, 109, 229, 128, 254,
},
{ // ctx 4
5, 41, 17, 52, 85, 139, 88, 122, 223, 105, 254,
},
{ // ctx 5
2, 18, 6, 17, 91, 135, 32, 85, 164, 72, 254,
},
},
},
{ // UV plane
{ // Intra
{ // ctx 0
126, 249, 176, 212, 148, 172, 249, 178, 254, 249, 128,
},
{ // ctx 1
34, 155, 150, 204, 164, 177, 208, 134, 254, 240, 128,
},
{ // ctx 2
16, 100, 102, 181, 114, 157, 235, 156, 254, 208, 128,
},
{ // ctx 3
6, 45, 76, 133, 101, 144, 188, 123, 254, 231, 128,
},
{ // ctx 4
3, 31, 38, 93, 91, 133, 216, 129, 254, 183, 128,
},
{ // ctx 5
1, 13, 28, 32, 134, 126, 93, 92, 254, 233, 128,
},
},
{ // Inter
{ // ctx 0
155, 246, 176, 203, 154, 153, 220, 134, 254, 253, 128,
},
{ // ctx 1
29, 140, 167, 217, 189, 159, 219, 117, 254, 254, 128,
},
{ // ctx 2
10, 87, 87, 149, 138, 157, 222, 87, 254, 253, 254,
},
{ // ctx 3
3, 40, 45, 85, 96, 150, 176, 76, 254, 254, 128,
},
{ // ctx 4
4, 37, 40, 73, 94, 142, 170, 95, 254, 250, 128,
},
{ // ctx 5
1, 31, 34, 67, 100, 137, 153, 95, 254, 241, 254,
},
},
},
},
{ // TX_SIZE 3
{ // Y plane
{ // Intra
{ // ctx 0
65, 253, 69, 65, 67, 190, 95, 92, 199, 124, 227,
},
{ // ctx 1
43, 180, 139, 140, 152, 153, 160, 114, 224, 171, 235,
},
{ // ctx 2
18, 138, 27, 123, 39, 207, 205, 88, 227, 159, 221,
},
{ // ctx 3
17, 133, 21, 65, 39, 213, 32, 102, 215, 119, 242,
},
{ // ctx 4
3, 56, 16, 47, 81, 122, 198, 76, 225, 164, 240,
},
{ // ctx 5
2, 61, 7, 14, 100, 128, 29, 93, 214, 118, 238,
},
},
{ // Inter
{ // ctx 0
250, 254, 10, 33, 59, 156, 181, 106, 225, 153, 254,
},
{ // ctx 1
227, 215, 40, 41, 78, 170, 99, 59, 187, 196, 254,
},
{ // ctx 2
102, 141, 8, 17, 89, 163, 209, 64, 178, 157, 204,
},
{ // ctx 3
14, 90, 15, 43, 72, 172, 76, 80, 191, 144, 253,
},
{ // ctx 4
66, 72, 13, 30, 99, 147, 96, 127, 227, 128, 254,
},
{ // ctx 5
10, 29, 6, 19, 64, 142, 43, 78, 171, 121, 249,
},
},
},
{ // UV plane
{ // Intra
{ // ctx 0
51, 252, 195, 198, 151, 184, 251, 191, 254, 254, 128,
},
{ // ctx 1
14, 184, 112, 122, 145, 156, 233, 137, 254, 242, 128,
},
{ // ctx 2
6, 109, 154, 156, 127, 192, 206, 107, 254, 230, 128,
},
{ // ctx 3
3, 37, 88, 100, 165, 139, 212, 164, 254, 225, 254,
},
{ // ctx 4
1, 37, 82, 108, 118, 151, 197, 88, 231, 128, 254,
},
{ // ctx 5
1, 9, 52, 35, 183, 137, 77, 108, 254, 220, 128,
},
},
{ // Inter
{ // ctx 0
254, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
},
{ // ctx 1
254, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
},
{ // ctx 2
246, 1, 1, 1, 128, 128, 254, 1, 128, 128, 128,
},
{ // ctx 3
1, 1, 254, 128, 128, 128, 128, 128, 128, 128, 128,
},
{ // ctx 4
1, 1, 1, 254, 1, 254, 128, 128, 128, 128, 128,
},
{ // ctx 5
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
},
},
},
},
#if CONFIG_TX64X64
{ // TX_SIZE 3
{ // Y plane
{ // Intra
{ // ctx 0
65, 253, 69, 65, 67, 190, 95, 92, 199, 124, 227,
},
{ // ctx 1
43, 180, 139, 140, 152, 153, 160, 114, 224, 171, 235,
},
{ // ctx 2
18, 138, 27, 123, 39, 207, 205, 88, 227, 159, 221,
},
{ // ctx 3
17, 133, 21, 65, 39, 213, 32, 102, 215, 119, 242,
},
{ // ctx 4
3, 56, 16, 47, 81, 122, 198, 76, 225, 164, 240,
},
{ // ctx 5
2, 61, 7, 14, 100, 128, 29, 93, 214, 118, 238,
},
},
{ // Inter
{ // ctx 0
250, 254, 10, 33, 59, 156, 181, 106, 225, 153, 254,
},
{ // ctx 1
227, 215, 40, 41, 78, 170, 99, 59, 187, 196, 254,
},
{ // ctx 2
102, 141, 8, 17, 89, 163, 209, 64, 178, 157, 204,
},
{ // ctx 3
14, 90, 15, 43, 72, 172, 76, 80, 191, 144, 253,
},
{ // ctx 4
66, 72, 13, 30, 99, 147, 96, 127, 227, 128, 254,
},
{ // ctx 5
10, 29, 6, 19, 64, 142, 43, 78, 171, 121, 249,
},
},
},
{ // UV plane
{ // Intra
{ // ctx 0
51, 252, 195, 198, 151, 184, 251, 191, 254, 254, 128,
},
{ // ctx 1
14, 184, 112, 122, 145, 156, 233, 137, 254, 242, 128,
},
{ // ctx 2
6, 109, 154, 156, 127, 192, 206, 107, 254, 230, 128,
},
{ // ctx 3
3, 37, 88, 100, 165, 139, 212, 164, 254, 225, 254,
},
{ // ctx 4
1, 37, 82, 108, 118, 151, 197, 88, 231, 128, 254,
},
{ // ctx 5
1, 9, 52, 35, 183, 137, 77, 108, 254, 220, 128,
},
},
{ // Inter
{ // ctx 0
254, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
},
{ // ctx 1
254, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
},
{ // ctx 2
246, 1, 1, 1, 128, 128, 254, 1, 128, 128, 128,
},
{ // ctx 3
1, 1, 254, 128, 128, 128, 128, 128, 128, 128, 128,
},
{ // ctx 4
1, 1, 1, 254, 1, 254, 128, 128, 128, 128, 128,
},
{ // ctx 5
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
},
},
},
},
#endif // CONFIG_TX64X64
};
#endif // CONFIG_TX_SKIP
static void extend_to_full_distribution(vp9_prob *probs, vp9_prob p) { static void extend_to_full_distribution(vp9_prob *probs, vp9_prob p) {
vpx_memcpy(probs, vp9_pareto8_full[p = 0 ? 0 : p - 1], vpx_memcpy(probs, vp9_pareto8_full[p = 0 ? 0 : p - 1],
MODEL_NODES * sizeof(vp9_prob)); MODEL_NODES * sizeof(vp9_prob));
@ -1172,6 +1610,10 @@ void vp9_default_coef_probs(VP9_COMMON *cm) {
#if CONFIG_TX64X64 #if CONFIG_TX64X64
vp9_copy(cm->fc.coef_probs[TX_64X64], default_coef_probs_64x64); vp9_copy(cm->fc.coef_probs[TX_64X64], default_coef_probs_64x64);
#endif // CONFIG_TX64X64 #endif // CONFIG_TX64X64
#if CONFIG_TX_SKIP
vp9_copy(cm->fc.coef_probs_pxd, default_coef_probs_pxd);
#endif // CONFIG_TX_SKIP
} }
#define COEF_COUNT_SAT 24 #define COEF_COUNT_SAT 24
@ -1190,6 +1632,28 @@ static void adapt_coef_probs(VP9_COMMON *cm, TX_SIZE tx_size,
vp9_coeff_count_model *counts = cm->counts.coef[tx_size]; vp9_coeff_count_model *counts = cm->counts.coef[tx_size];
unsigned int (*eob_counts)[REF_TYPES][COEF_BANDS][COEFF_CONTEXTS] = unsigned int (*eob_counts)[REF_TYPES][COEF_BANDS][COEFF_CONTEXTS] =
cm->counts.eob_branch[tx_size]; cm->counts.eob_branch[tx_size];
#if CONFIG_TX_SKIP
vp9_coeff_probs_pxd *const probs_pxd = cm->fc.coef_probs_pxd[tx_size];
const vp9_coeff_probs_pxd *const pre_probs_pxd =
pre_fc->coef_probs_pxd[tx_size];
vp9_coeff_counts_pxd *counts_pxd = cm->counts.coef_pxd[tx_size];
unsigned int (*eob_counts_pxd)[REF_TYPES][COEFF_CONTEXTS] =
cm->counts.eob_branch_pxd[tx_size];
const vp9_tree_index vp9_coef_tree[TREE_SIZE(ENTROPY_TOKENS)] = {
-EOB_TOKEN, 2, // 0 = EOB
-ZERO_TOKEN, 4, // 1 = ZERO
-ONE_TOKEN, 6, // 2 = ONE
8, 12, // 3 = LOW_VAL
-TWO_TOKEN, 10, // 4 = TWO
-THREE_TOKEN, -FOUR_TOKEN, // 5 = THREE
14, 16, // 6 = HIGH_LOW
-CATEGORY1_TOKEN, -CATEGORY2_TOKEN, // 7 = CAT_ONE
18, 20, // 8 = CAT_THREEFOUR
-CATEGORY3_TOKEN, -CATEGORY4_TOKEN, // 9 = CAT_THREE
-CATEGORY5_TOKEN, -CATEGORY6_TOKEN // 10 = CAT_FIVE
};
#endif // CONFIG_TX_SKIP
int i, j, k, l, m; int i, j, k, l, m;
for (i = 0; i < PLANE_TYPES; ++i) for (i = 0; i < PLANE_TYPES; ++i)
@ -1210,6 +1674,25 @@ static void adapt_coef_probs(VP9_COMMON *cm, TX_SIZE tx_size,
branch_ct[m], branch_ct[m],
count_sat, update_factor); count_sat, update_factor);
} }
#if CONFIG_TX_SKIP
if (FOR_SCREEN_CONTENT) {
for (i = 0; i < PLANE_TYPES; ++i)
for (j = 0; j < REF_TYPES; ++j)
for (l = 0; l < COEFF_CONTEXTS; ++l) {
const unsigned int eob_ct[2] = {counts_pxd[i][j][l][EOB_TOKEN],
eob_counts_pxd[i][j][l] - counts_pxd[i][j][l][EOB_TOKEN]};
vp9_tree_merge_probs(vp9_coef_tree, pre_probs_pxd[i][j][l],
counts_pxd[i][j][l],
count_sat, update_factor, probs_pxd[i][j][l]);
probs_pxd[i][j][l][0] = merge_probs(pre_probs_pxd[i][j][l][0],
eob_ct,
count_sat, update_factor);
}
}
#endif // CONFIG_TX_SKIP
} }
void vp9_adapt_coef_probs(VP9_COMMON *cm) { void vp9_adapt_coef_probs(VP9_COMMON *cm) {

View File

@ -121,6 +121,7 @@ extern const vp9_extra_bit vp9_extra_bits_high12[ENTROPY_TOKENS];
/* Middle dimension reflects the coefficient position within the transform. */ /* Middle dimension reflects the coefficient position within the transform. */
#if CONFIG_TX_SKIP #if CONFIG_TX_SKIP
#define FOR_SCREEN_CONTENT 0
#define COEF_BANDS 7 #define COEF_BANDS 7
#define TX_SKIP_COEFF_BAND 6 #define TX_SKIP_COEFF_BAND 6
#else #else
@ -152,6 +153,10 @@ typedef unsigned int vp9_coeff_count[REF_TYPES][COEF_BANDS][COEFF_CONTEXTS]
[ENTROPY_TOKENS]; [ENTROPY_TOKENS];
typedef unsigned int vp9_coeff_stats[REF_TYPES][COEF_BANDS][COEFF_CONTEXTS] typedef unsigned int vp9_coeff_stats[REF_TYPES][COEF_BANDS][COEFF_CONTEXTS]
[ENTROPY_NODES][2]; [ENTROPY_NODES][2];
#if CONFIG_TX_SKIP
typedef unsigned int vp9_coeff_stats_pxd[REF_TYPES][COEFF_CONTEXTS]
[ENTROPY_NODES][2];
#endif // CONFIG_TX_SKIP
#define SUBEXP_PARAM 4 /* Subexponential code parameter */ #define SUBEXP_PARAM 4 /* Subexponential code parameter */
#define MODULUS_PARAM 13 /* Modulus parameter */ #define MODULUS_PARAM 13 /* Modulus parameter */
@ -218,6 +223,12 @@ typedef unsigned int vp9_coeff_count_model[REF_TYPES][COEF_BANDS]
void vp9_model_to_full_probs(const vp9_prob *model, vp9_prob *full); void vp9_model_to_full_probs(const vp9_prob *model, vp9_prob *full);
#if CONFIG_TX_SKIP
typedef vp9_prob vp9_coeff_probs_pxd[REF_TYPES][COEFF_CONTEXTS][ENTROPY_NODES];
typedef unsigned int vp9_coeff_counts_pxd[REF_TYPES][COEFF_CONTEXTS]
[ENTROPY_TOKENS];
#endif // CONFIG_TX_SKIP
static INLINE int get_entropy_context(TX_SIZE tx_size, const ENTROPY_CONTEXT *a, static INLINE int get_entropy_context(TX_SIZE tx_size, const ENTROPY_CONTEXT *a,
const ENTROPY_CONTEXT *l) { const ENTROPY_CONTEXT *l) {
ENTROPY_CONTEXT above_ec = 0, left_ec = 0; ENTROPY_CONTEXT above_ec = 0, left_ec = 0;

View File

@ -85,6 +85,7 @@ typedef struct frame_contexts {
#if CONFIG_TX_SKIP #if CONFIG_TX_SKIP
vp9_prob y_tx_skip_prob[2]; vp9_prob y_tx_skip_prob[2];
vp9_prob uv_tx_skip_prob[2]; vp9_prob uv_tx_skip_prob[2];
vp9_coeff_probs_pxd coef_probs_pxd[TX_SIZES][PLANE_TYPES];
#endif // CONFIG_TX_SKIP #endif // CONFIG_TX_SKIP
#if CONFIG_COPY_MODE #if CONFIG_COPY_MODE
vp9_prob copy_noref_prob[COPY_MODE_CONTEXTS][BLOCK_SIZES]; vp9_prob copy_noref_prob[COPY_MODE_CONTEXTS][BLOCK_SIZES];
@ -138,6 +139,8 @@ typedef struct {
#if CONFIG_TX_SKIP #if CONFIG_TX_SKIP
unsigned int y_tx_skip[2][2]; unsigned int y_tx_skip[2][2];
unsigned int uv_tx_skip[2][2]; unsigned int uv_tx_skip[2][2];
vp9_coeff_counts_pxd coef_pxd[TX_SIZES][PLANE_TYPES];
unsigned int eob_branch_pxd[TX_SIZES][PLANE_TYPES][REF_TYPES][COEFF_CONTEXTS];
#endif // CONFIG_TX_SKIP #endif // CONFIG_TX_SKIP
#if CONFIG_COPY_MODE #if CONFIG_COPY_MODE
unsigned int copy_noref[COPY_MODE_CONTEXTS][BLOCK_SIZES][2]; unsigned int copy_noref[COPY_MODE_CONTEXTS][BLOCK_SIZES][2];

View File

@ -15,6 +15,11 @@
#include "vp9/common/vp9_quant_common.h" #include "vp9/common/vp9_quant_common.h"
#include "vp9/common/vp9_seg_common.h" #include "vp9/common/vp9_seg_common.h"
#if CONFIG_TX_SKIP
int tx_skip_q_thresh_inter = FOR_SCREEN_CONTENT ? 255 : 64;
int tx_skip_q_thresh_intra = 255;
#endif // CONFIG_TX_SKIP
#if CONFIG_NEW_QUANT #if CONFIG_NEW_QUANT
// Bin widths expressed as a fraction over 128 of the quant stepsize, // Bin widths expressed as a fraction over 128 of the quant stepsize,
// for the quantization bins 0-4. // for the quantization bins 0-4.

View File

@ -25,10 +25,10 @@ extern "C" {
#define QINDEX_RANGE (MAXQ - MINQ + 1) #define QINDEX_RANGE (MAXQ - MINQ + 1)
#define QINDEX_BITS 8 #define QINDEX_BITS 8
#if CONFIG_TX_SKIP #if CONFIG_TX_SKIP
#define TX_SKIP_Q_THRESH_INTER 64
#define TX_SKIP_Q_THRESH_INTRA 255
#define TX_SKIP_SHIFT_THRESH 0 #define TX_SKIP_SHIFT_THRESH 0
#define PXD_QUANT_INDEX 0 #define PXD_QUANT_INDEX 0
extern int tx_skip_q_thresh_inter;
extern int tx_skip_q_thresh_intra;
#endif // CONFIG_TX_SKIP #endif // CONFIG_TX_SKIP
int16_t vp9_dc_quant(int qindex, int delta, vpx_bit_depth_t bit_depth); int16_t vp9_dc_quant(int qindex, int delta, vpx_bit_depth_t bit_depth);

View File

@ -1557,12 +1557,32 @@ static void read_coef_probs_common(vp9_coeff_probs_model *coef_probs,
vp9_diff_update_prob(r, &coef_probs[i][j][k][l][m]); vp9_diff_update_prob(r, &coef_probs[i][j][k][l][m]);
} }
#if CONFIG_TX_SKIP
static void read_coef_probs_common_pxd(vp9_coeff_probs_pxd *coef_probs,
vp9_reader *r) {
int i, j, l, m;
if (vp9_read_bit(r))
for (i = 0; i < PLANE_TYPES; ++i)
for (j = 0; j < REF_TYPES; ++j)
for (l = 0; l < COEFF_CONTEXTS; ++l)
for (m = 0; m < ENTROPY_NODES; ++m)
vp9_diff_update_prob(r, &coef_probs[i][j][l][m]);
}
#endif // CONFIG_TX_SKIP
static void read_coef_probs(FRAME_CONTEXT *fc, TX_MODE tx_mode, static void read_coef_probs(FRAME_CONTEXT *fc, TX_MODE tx_mode,
vp9_reader *r) { vp9_reader *r) {
const TX_SIZE max_tx_size = tx_mode_to_biggest_tx_size[tx_mode]; const TX_SIZE max_tx_size = tx_mode_to_biggest_tx_size[tx_mode];
TX_SIZE tx_size; TX_SIZE tx_size;
for (tx_size = TX_4X4; tx_size <= max_tx_size; ++tx_size) for (tx_size = TX_4X4; tx_size <= max_tx_size; ++tx_size)
read_coef_probs_common(fc->coef_probs[tx_size], r); read_coef_probs_common(fc->coef_probs[tx_size], r);
#if CONFIG_TX_SKIP
if (FOR_SCREEN_CONTENT)
for (tx_size = TX_4X4; tx_size <= max_tx_size; ++tx_size)
read_coef_probs_common_pxd(fc->coef_probs_pxd[tx_size], r);
#endif // CONFIG_TX_SKIP
} }
static void setup_segmentation(struct segmentation *seg, static void setup_segmentation(struct segmentation *seg,

View File

@ -412,7 +412,7 @@ static void read_intra_frame_mode_info(VP9_COMMON *const cm,
#if CONFIG_TX_SKIP #if CONFIG_TX_SKIP
if (mbmi->sb_type >= BLOCK_8X8) { if (mbmi->sb_type >= BLOCK_8X8) {
int q_idx = vp9_get_qindex(&cm->seg, mbmi->segment_id, cm->base_qindex); int q_idx = vp9_get_qindex(&cm->seg, mbmi->segment_id, cm->base_qindex);
int try_tx_skip = q_idx <= TX_SKIP_Q_THRESH_INTRA; int try_tx_skip = q_idx <= tx_skip_q_thresh_intra;
if (try_tx_skip) { if (try_tx_skip) {
if (xd->lossless) { if (xd->lossless) {
if (mbmi->tx_size == TX_4X4) if (mbmi->tx_size == TX_4X4)
@ -1510,8 +1510,8 @@ static void read_inter_frame_mode_info(VP9_COMMON *const cm,
#if CONFIG_TX_SKIP #if CONFIG_TX_SKIP
if (mbmi->sb_type >= BLOCK_8X8) { if (mbmi->sb_type >= BLOCK_8X8) {
int q_idx = vp9_get_qindex(&cm->seg, mbmi->segment_id, cm->base_qindex); int q_idx = vp9_get_qindex(&cm->seg, mbmi->segment_id, cm->base_qindex);
int try_tx_skip = inter_block ? q_idx <= TX_SKIP_Q_THRESH_INTER : int try_tx_skip = inter_block ? q_idx <= tx_skip_q_thresh_inter :
q_idx <= TX_SKIP_Q_THRESH_INTRA; q_idx <= tx_skip_q_thresh_intra;
#if CONFIG_COPY_MODE #if CONFIG_COPY_MODE
if (mbmi->copy_mode != NOREF) if (mbmi->copy_mode != NOREF)
try_tx_skip = 0; try_tx_skip = 0;

View File

@ -86,6 +86,9 @@ static int decode_coefs(VP9_COMMON *cm, const MACROBLOCKD *xd, PLANE_TYPE type,
#endif #endif
const tran_low_t *dqv_val = &dq_val[0][0]; const tran_low_t *dqv_val = &dq_val[0][0];
#endif // CONFIG_NEW_QUANT #endif // CONFIG_NEW_QUANT
#if CONFIG_TX_SKIP
int tx_skip = xd->mi[0].src_mi->mbmi.tx_skip[type];
#endif // CONFIG_TX_SKIP
const uint8_t *cat1_prob; const uint8_t *cat1_prob;
const uint8_t *cat2_prob; const uint8_t *cat2_prob;
const uint8_t *cat3_prob; const uint8_t *cat3_prob;
@ -128,7 +131,7 @@ static int decode_coefs(VP9_COMMON *cm, const MACROBLOCKD *xd, PLANE_TYPE type,
#endif #endif
#if CONFIG_TX_SKIP #if CONFIG_TX_SKIP
if (xd->mi[0].src_mi->mbmi.tx_skip[type]) if (tx_skip)
band_translate = vp9_coefband_tx_skip; band_translate = vp9_coefband_tx_skip;
#endif // CONFIG_TX_SKIP #endif // CONFIG_TX_SKIP
@ -244,6 +247,198 @@ static int decode_coefs(VP9_COMMON *cm, const MACROBLOCKD *xd, PLANE_TYPE type,
return c; return c;
} }
#if CONFIG_TX_SKIP
static int decode_coefs_pxd(VP9_COMMON *cm, const MACROBLOCKD *xd,
PLANE_TYPE type, tran_low_t *dqcoeff,
TX_SIZE tx_size, const int16_t *dq,
#if CONFIG_NEW_QUANT
const dequant_val_type_nuq *dq_val,
#endif // CONFIG_NEW_QUANT
int ctx, const int16_t *scan, const int16_t *nb,
vp9_reader *r) {
const int max_eob = 16 << (tx_size << 1);
const FRAME_CONTEXT *const fc = &cm->fc;
FRAME_COUNTS *const counts = &cm->counts;
const int ref = is_inter_block(&xd->mi[0].src_mi->mbmi);
int c = 0;
const vp9_prob *prob;
const vp9_prob (*coef_probs_pxd)[ENTROPY_TOKENS - 1] =
fc->coef_probs_pxd[tx_size][type][ref];
unsigned int (*coef_counts_pxd)[ENTROPY_TOKENS] =
counts->coef_pxd[tx_size][type][ref];
unsigned int *eob_branch_count_pxd =
counts->eob_branch_pxd[tx_size][type][ref];
uint8_t token_cache[MAX_NUM_COEFS];
const int dq_shift = (tx_size > TX_16X16) ? tx_size - TX_16X16 : 0;
int v, token;
int16_t dqv = dq[0];
#if CONFIG_NEW_QUANT
#if CONFIG_TX_SKIP
const int use_rect_quant = is_rect_quant_used(&xd->mi[0].src_mi->mbmi, type);
#endif
const tran_low_t *dqv_val = &dq_val[0][0];
#endif // CONFIG_NEW_QUANT
const uint8_t *cat1_prob;
const uint8_t *cat2_prob;
const uint8_t *cat3_prob;
const uint8_t *cat4_prob;
const uint8_t *cat5_prob;
const uint8_t *cat6_prob;
#if CONFIG_VP9_HIGHBITDEPTH
if (cm->use_highbitdepth) {
if (cm->bit_depth == VPX_BITS_10) {
cat1_prob = vp9_cat1_prob_high10;
cat2_prob = vp9_cat2_prob_high10;
cat3_prob = vp9_cat3_prob_high10;
cat4_prob = vp9_cat4_prob_high10;
cat5_prob = vp9_cat5_prob_high10;
cat6_prob = vp9_cat6_prob_high10;
} else {
cat1_prob = vp9_cat1_prob_high12;
cat2_prob = vp9_cat2_prob_high12;
cat3_prob = vp9_cat3_prob_high12;
cat4_prob = vp9_cat4_prob_high12;
cat5_prob = vp9_cat5_prob_high12;
cat6_prob = vp9_cat6_prob_high12;
}
} else {
cat1_prob = vp9_cat1_prob;
cat2_prob = vp9_cat2_prob;
cat3_prob = vp9_cat3_prob;
cat4_prob = vp9_cat4_prob;
cat5_prob = vp9_cat5_prob;
cat6_prob = vp9_cat6_prob;
}
#else
cat1_prob = vp9_cat1_prob;
cat2_prob = vp9_cat2_prob;
cat3_prob = vp9_cat3_prob;
cat4_prob = vp9_cat4_prob;
cat5_prob = vp9_cat5_prob;
cat6_prob = vp9_cat6_prob;
#endif
while (c < max_eob) {
int val = -1;
prob = coef_probs_pxd[ctx];
if (!cm->frame_parallel_decoding_mode)
++eob_branch_count_pxd[ctx];
if (!vp9_read(r, prob[EOB_CONTEXT_NODE])) {
if (!cm->frame_parallel_decoding_mode)
++coef_counts_pxd[ctx][EOB_TOKEN];
break;
}
#if CONFIG_NEW_QUANT
dqv_val = &dq_val[TX_SKIP_COEFF_BAND][0];
#endif // CONFIG_NEW_QUANT
while (!vp9_read(r, prob[ZERO_CONTEXT_NODE])) {
if (!cm->frame_parallel_decoding_mode)
++coef_counts_pxd[ctx][ZERO_TOKEN];
dqv = dq[1];
token_cache[scan[c]] = 0;
++c;
if (c >= max_eob)
return c; // zero tokens at the end (no eob token)
ctx = get_coef_context(nb, token_cache, c);
prob = coef_probs_pxd[ctx];
#if CONFIG_NEW_QUANT
dqv_val = &dq_val[TX_SKIP_COEFF_BAND][0];
#endif // CONFIG_NEW_QUANT
}
if (!vp9_read(r, prob[ONE_CONTEXT_NODE])) {
if (!cm->frame_parallel_decoding_mode)
++coef_counts_pxd[ctx][ONE_TOKEN];
token = ONE_TOKEN;
val = 1;
} else {
token = vp9_read_tree(r, coeff_subtree_high, &prob[PIVOT_NODE + 1]);
if (!cm->frame_parallel_decoding_mode)
++coef_counts_pxd[ctx][token];
switch (token) {
case TWO_TOKEN:
case THREE_TOKEN:
case FOUR_TOKEN:
val = token;
break;
case CATEGORY1_TOKEN:
val = CAT1_MIN_VAL + read_coeff(cat1_prob, 1, r);
break;
case CATEGORY2_TOKEN:
val = CAT2_MIN_VAL + read_coeff(cat2_prob, 2, r);
break;
case CATEGORY3_TOKEN:
val = CAT3_MIN_VAL + read_coeff(cat3_prob, 3, r);
break;
case CATEGORY4_TOKEN:
val = CAT4_MIN_VAL + read_coeff(cat4_prob, 4, r);
break;
case CATEGORY5_TOKEN:
val = CAT5_MIN_VAL + read_coeff(cat5_prob, 5, r);
break;
case CATEGORY6_TOKEN:
#if CONFIG_VP9_HIGHBITDEPTH
switch (cm->bit_depth) {
case VPX_BITS_8:
val = CAT6_MIN_VAL + read_coeff(cat6_prob, NUM_CAT6_BITS, r);
break;
case VPX_BITS_10:
val = CAT6_MIN_VAL +
read_coeff(cat6_prob, NUM_CAT6_BITS_HIGH10, r);
break;
case VPX_BITS_12:
val = CAT6_MIN_VAL +
read_coeff(cat6_prob, NUM_CAT6_BITS_HIGH12, r);
break;
default:
assert(0);
return -1;
}
#else
val = CAT6_MIN_VAL + read_coeff(cat6_prob, NUM_CAT6_BITS, r);
#endif
break;
}
}
#if CONFIG_NEW_QUANT
#if CONFIG_TX_SKIP
if (use_rect_quant) {
v = (val * dqv) >> dq_shift;
} else {
v = vp9_dequant_abscoeff_nuq(val, dqv, dqv_val);
v = dq_shift ? ROUND_POWER_OF_TWO(v, dq_shift) : v;
}
#else
v = vp9_dequant_abscoeff_nuq(val, dqv, dqv_val);
v = dq_shift ? ROUND_POWER_OF_TWO(v, dq_shift) : v;
#endif // CONFIG_TX_SKIP
#else // CONFIG_NEW_QUANT
v = (val * dqv) >> dq_shift;
#endif // CONFIG_NEW_QUANT
#if CONFIG_COEFFICIENT_RANGE_CHECKING
dqcoeff[scan[c]] = check_range(vp9_read_bit(r) ? -v : v);
#else
dqcoeff[scan[c]] = vp9_read_bit(r) ? -v : v;
#endif
token_cache[scan[c]] = vp9_pt_energy_class[token];
++c;
ctx = get_coef_context(nb, token_cache, c);
dqv = dq[1];
}
return c;
}
#endif // CONFIG_TX_SKIP
int vp9_decode_block_tokens(VP9_COMMON *cm, MACROBLOCKD *xd, int vp9_decode_block_tokens(VP9_COMMON *cm, MACROBLOCKD *xd,
int plane, int block, BLOCK_SIZE plane_bsize, int plane, int block, BLOCK_SIZE plane_bsize,
int x, int y, TX_SIZE tx_size, vp9_reader *r) { int x, int y, TX_SIZE tx_size, vp9_reader *r) {
@ -252,24 +447,38 @@ int vp9_decode_block_tokens(VP9_COMMON *cm, MACROBLOCKD *xd,
pd->left_context + y); pd->left_context + y);
const scan_order *so = get_scan(xd, tx_size, pd->plane_type, block); const scan_order *so = get_scan(xd, tx_size, pd->plane_type, block);
int eob; int eob;
eob = decode_coefs(cm, xd, pd->plane_type,
BLOCK_OFFSET(pd->dqcoeff, block), tx_size,
#if CONFIG_TX_SKIP #if CONFIG_TX_SKIP
xd->mi->src_mi->mbmi.tx_skip[plane != 0] ? if (xd->mi->src_mi->mbmi.tx_skip[plane != 0] && FOR_SCREEN_CONTENT)
pd->dequant_pxd : pd->dequant, eob = decode_coefs_pxd(cm, xd, pd->plane_type,
BLOCK_OFFSET(pd->dqcoeff, block), tx_size,
pd->dequant_pxd,
#if CONFIG_NEW_QUANT
pd->dequant_val_nuq_pxd,
#endif // CONFIG_NEW_QUANT
ctx, so->scan,
so->neighbors, r);
else
#endif // CONFIG_TX_SKIP
eob = decode_coefs(cm, xd, pd->plane_type,
BLOCK_OFFSET(pd->dqcoeff, block), tx_size,
#if CONFIG_TX_SKIP
xd->mi->src_mi->mbmi.tx_skip[plane != 0] ?
pd->dequant_pxd : pd->dequant,
#else #else
pd->dequant, pd->dequant,
#endif // CONFIG_TX_SKIP #endif // CONFIG_TX_SKIP
#if CONFIG_NEW_QUANT #if CONFIG_NEW_QUANT
#if CONFIG_TX_SKIP #if CONFIG_TX_SKIP
xd->mi->src_mi->mbmi.tx_skip[plane != 0] ? xd->mi->src_mi->mbmi.tx_skip[plane != 0] ?
pd->dequant_val_nuq_pxd : pd->dequant_val_nuq, pd->dequant_val_nuq_pxd : pd->dequant_val_nuq,
#else #else
pd->dequant_val_nuq, pd->dequant_val_nuq,
#endif // CONFIG_TX_SKIP #endif // CONFIG_TX_SKIP
#endif // CONFIG_NEW_QUANT #endif // CONFIG_NEW_QUANT
ctx, so->scan, ctx, so->scan,
so->neighbors, r); so->neighbors, r);
#if CONFIG_TX64X64 #if CONFIG_TX64X64
if (plane > 0) assert(tx_size != TX_64X64); if (plane > 0) assert(tx_size != TX_64X64);
#endif // CONFIG_TX64X64 #endif // CONFIG_TX64X64

View File

@ -322,16 +322,24 @@ static void pack_mb_tokens(vp9_writer *w,
// is split into two treed writes. The first treed write takes care of the // is split into two treed writes. The first treed write takes care of the
// unconstrained nodes. The second treed write takes care of the // unconstrained nodes. The second treed write takes care of the
// constrained nodes. // constrained nodes.
if (t >= TWO_TOKEN && t < EOB_TOKEN) { #if CONFIG_TX_SKIP
int len = UNCONSTRAINED_NODES - p->skip_eob_node; if (p->is_pxd_token && FOR_SCREEN_CONTENT) {
int bits = v >> (n - len);
vp9_write_tree(w, vp9_coef_tree, p->context_tree, bits, len, i);
vp9_write_tree(w, vp9_coef_con_tree,
vp9_pareto8_full[p->context_tree[PIVOT_NODE] - 1],
v, n - len, 0);
} else {
vp9_write_tree(w, vp9_coef_tree, p->context_tree, v, n, i); vp9_write_tree(w, vp9_coef_tree, p->context_tree, v, n, i);
} else {
#endif // CONFIG_TX_SKIP
if (t >= TWO_TOKEN && t < EOB_TOKEN) {
int len = UNCONSTRAINED_NODES - p->skip_eob_node;
int bits = v >> (n - len);
vp9_write_tree(w, vp9_coef_tree, p->context_tree, bits, len, i);
vp9_write_tree(w, vp9_coef_con_tree,
vp9_pareto8_full[p->context_tree[PIVOT_NODE] - 1],
v, n - len, 0);
} else {
vp9_write_tree(w, vp9_coef_tree, p->context_tree, v, n, i);
}
#if CONFIG_TX_SKIP
} }
#endif // CONFIG_TX_SKIP
if (b->base_val) { if (b->base_val) {
const int e = p->extra, l = b->len; const int e = p->extra, l = b->len;
@ -580,8 +588,8 @@ static void pack_inter_mode_mvs(VP9_COMP *cpi, const MODE_INFO *mi,
#if CONFIG_TX_SKIP #if CONFIG_TX_SKIP
if (bsize >= BLOCK_8X8) { if (bsize >= BLOCK_8X8) {
int q_idx = vp9_get_qindex(seg, segment_id, cm->base_qindex); int q_idx = vp9_get_qindex(seg, segment_id, cm->base_qindex);
int try_tx_skip = is_inter ? q_idx <= TX_SKIP_Q_THRESH_INTER : int try_tx_skip = is_inter ? q_idx <= tx_skip_q_thresh_inter :
q_idx <= TX_SKIP_Q_THRESH_INTRA; q_idx <= tx_skip_q_thresh_intra;
#if CONFIG_COPY_MODE #if CONFIG_COPY_MODE
if (mbmi->copy_mode != NOREF) { if (mbmi->copy_mode != NOREF) {
@ -999,7 +1007,7 @@ static void write_mb_modes_kf(const VP9_COMMON *cm,
#if CONFIG_TX_SKIP #if CONFIG_TX_SKIP
if (bsize >= BLOCK_8X8) { if (bsize >= BLOCK_8X8) {
int q_idx = vp9_get_qindex(seg, mbmi->segment_id, cm->base_qindex); int q_idx = vp9_get_qindex(seg, mbmi->segment_id, cm->base_qindex);
int try_tx_skip = q_idx <= TX_SKIP_Q_THRESH_INTRA; int try_tx_skip = q_idx <= tx_skip_q_thresh_intra;
if (try_tx_skip) { if (try_tx_skip) {
if (xd->lossless) { if (xd->lossless) {
if (mbmi->tx_size == TX_4X4) if (mbmi->tx_size == TX_4X4)
@ -1471,12 +1479,165 @@ static void update_coef_probs_common(vp9_writer* const bc, VP9_COMP *cpi,
} }
} }
#if CONFIG_TX_SKIP
static void build_tree_distribution_pxd(VP9_COMP *cpi, TX_SIZE tx_size,
vp9_coeff_stats_pxd *coef_branch_ct,
vp9_coeff_probs_pxd *coef_probs) {
vp9_coeff_counts_pxd *coef_counts = cpi->common.counts.coef_pxd[tx_size];
unsigned int (*eob_branch_ct)[REF_TYPES][COEFF_CONTEXTS] =
cpi->common.counts.eob_branch_pxd[tx_size];
int i, j, l, m;
for (i = 0; i < PLANE_TYPES; ++i) {
for (j = 0; j < REF_TYPES; ++j) {
for (l = 0; l < COEFF_CONTEXTS; ++l) {
vp9_tree_probs_from_distribution(vp9_coef_tree,
coef_branch_ct[i][j][l],
coef_counts[i][j][l]);
coef_branch_ct[i][j][l][0][1] = eob_branch_ct[i][j][l] -
coef_branch_ct[i][j][l][0][0];
for (m = 0; m < ENTROPY_NODES; ++m)
coef_probs[i][j][l][m] = get_binary_prob(
coef_branch_ct[i][j][l][m][0],
coef_branch_ct[i][j][l][m][1]);
}
}
}
}
static void update_coef_probs_common_pxd(vp9_writer* const bc, VP9_COMP *cpi,
TX_SIZE tx_size,
vp9_coeff_stats_pxd *frame_branch_ct,
vp9_coeff_probs_pxd *new_coef_probs) {
vp9_coeff_probs_pxd *old_coef_probs = cpi->common.fc.coef_probs_pxd[tx_size];
const vp9_prob upd = DIFF_UPDATE_PROB;
const int entropy_nodes_update = ENTROPY_NODES;
int i, j, l, t;
switch (cpi->sf.use_fast_coef_updates) {
case TWO_LOOP: {
/* dry run to see if there is any update at all needed */
int savings = 0;
int update[2] = {0, 0};
for (i = 0; i < PLANE_TYPES; ++i) {
for (j = 0; j < REF_TYPES; ++j) {
for (l = 0; l < COEFF_CONTEXTS; ++l) {
for (t = 0; t < entropy_nodes_update; ++t) {
vp9_prob newp = new_coef_probs[i][j][l][t];
const vp9_prob oldp = old_coef_probs[i][j][l][t];
int s;
int u = 0;
s = vp9_prob_diff_update_savings_search(
frame_branch_ct[i][j][l][t], oldp, &newp, upd);
if (s > 0 && newp != oldp)
u = 1;
if (u)
savings += s - (int)(vp9_cost_zero(upd));
else
savings -= (int)(vp9_cost_zero(upd));
update[u]++;
}
}
}
}
if (update[1] == 0 || savings < 0) {
vp9_write_bit(bc, 0);
return;
}
vp9_write_bit(bc, 1);
for (i = 0; i < PLANE_TYPES; ++i) {
for (j = 0; j < REF_TYPES; ++j) {
for (l = 0; l < COEFF_CONTEXTS; ++l) {
// calc probs and branch cts for this frame only
for (t = 0; t < entropy_nodes_update; ++t) {
vp9_prob newp = new_coef_probs[i][j][l][t];
vp9_prob *oldp = old_coef_probs[i][j][l] + t;
const vp9_prob upd = DIFF_UPDATE_PROB;
int s;
int u = 0;
s = vp9_prob_diff_update_savings_search(
frame_branch_ct[i][j][l][t],
*oldp, &newp, upd);
if (s > 0 && newp != *oldp)
u = 1;
vp9_write(bc, u, upd);
if (u) {
/* send/use new probability */
vp9_write_prob_diff_update(bc, newp, *oldp);
*oldp = newp;
}
}
}
}
}
return;
}
case ONE_LOOP:
case ONE_LOOP_REDUCED: {
int updates = 0;
int noupdates_before_first = 0;
for (i = 0; i < PLANE_TYPES; ++i) {
for (j = 0; j < REF_TYPES; ++j) {
for (l = 0; l < COEFF_CONTEXTS; ++l) {
// calc probs and branch cts for this frame only
for (t = 0; t < entropy_nodes_update; ++t) {
vp9_prob newp = new_coef_probs[i][j][l][t];
vp9_prob *oldp = old_coef_probs[i][j][l] + t;
int s;
int u = 0;
s = vp9_prob_diff_update_savings_search(
frame_branch_ct[i][j][l][t],
*oldp, &newp, upd);
if (s > 0 && newp != *oldp)
u = 1;
updates += u;
if (u == 0 && updates == 0) {
noupdates_before_first++;
continue;
}
if (u == 1 && updates == 1) {
int v;
// first update
vp9_write_bit(bc, 1);
for (v = 0; v < noupdates_before_first; ++v)
vp9_write(bc, 0, upd);
}
vp9_write(bc, u, upd);
if (u) {
// send/use new probability
vp9_write_prob_diff_update(bc, newp, *oldp);
*oldp = newp;
}
}
}
}
}
if (updates == 0) {
vp9_write_bit(bc, 0); // no updates
}
return;
}
default:
assert(0);
}
}
#endif // CONFIG_TX_SKIP
static void update_coef_probs(VP9_COMP *cpi, vp9_writer* w) { static void update_coef_probs(VP9_COMP *cpi, vp9_writer* w) {
const TX_MODE tx_mode = cpi->common.tx_mode; const TX_MODE tx_mode = cpi->common.tx_mode;
const TX_SIZE max_tx_size = tx_mode_to_biggest_tx_size[tx_mode]; const TX_SIZE max_tx_size = tx_mode_to_biggest_tx_size[tx_mode];
TX_SIZE tx_size; TX_SIZE tx_size;
vp9_coeff_stats frame_branch_ct[TX_SIZES][PLANE_TYPES]; vp9_coeff_stats frame_branch_ct[TX_SIZES][PLANE_TYPES];
vp9_coeff_probs_model frame_coef_probs[TX_SIZES][PLANE_TYPES]; vp9_coeff_probs_model frame_coef_probs[TX_SIZES][PLANE_TYPES];
#if CONFIG_TX_SKIP
vp9_coeff_stats_pxd frame_branch_ct_pxd[TX_SIZES][PLANE_TYPES];
vp9_coeff_probs_pxd frame_coef_probs_pxd[TX_SIZES][PLANE_TYPES];
#endif // CONFIG_TX_SKIP
for (tx_size = TX_4X4; tx_size <= max_tx_size; ++tx_size) for (tx_size = TX_4X4; tx_size <= max_tx_size; ++tx_size)
build_tree_distribution(cpi, tx_size, frame_branch_ct[tx_size], build_tree_distribution(cpi, tx_size, frame_branch_ct[tx_size],
@ -1485,6 +1646,19 @@ static void update_coef_probs(VP9_COMP *cpi, vp9_writer* w) {
for (tx_size = TX_4X4; tx_size <= max_tx_size; ++tx_size) for (tx_size = TX_4X4; tx_size <= max_tx_size; ++tx_size)
update_coef_probs_common(w, cpi, tx_size, frame_branch_ct[tx_size], update_coef_probs_common(w, cpi, tx_size, frame_branch_ct[tx_size],
frame_coef_probs[tx_size]); frame_coef_probs[tx_size]);
#if CONFIG_TX_SKIP
if (FOR_SCREEN_CONTENT) {
for (tx_size = TX_4X4; tx_size <= max_tx_size; ++tx_size)
build_tree_distribution_pxd(cpi, tx_size, frame_branch_ct_pxd[tx_size],
frame_coef_probs_pxd[tx_size]);
for (tx_size = TX_4X4; tx_size <= max_tx_size; ++tx_size)
update_coef_probs_common_pxd(w, cpi, tx_size,
frame_branch_ct_pxd[tx_size],
frame_coef_probs_pxd[tx_size]);
}
#endif // CONFIG_TX_SKIP
} }
static void encode_loopfilter(VP9_COMMON *cm, static void encode_loopfilter(VP9_COMMON *cm,

View File

@ -61,6 +61,11 @@ struct macroblock_plane {
typedef unsigned int vp9_coeff_cost[PLANE_TYPES][REF_TYPES][COEF_BANDS][2] typedef unsigned int vp9_coeff_cost[PLANE_TYPES][REF_TYPES][COEF_BANDS][2]
[COEFF_CONTEXTS][ENTROPY_TOKENS]; [COEFF_CONTEXTS][ENTROPY_TOKENS];
#if CONFIG_TX_SKIP
typedef unsigned int vp9_coeff_cost_pxd[PLANE_TYPES][REF_TYPES][2]
[COEFF_CONTEXTS][ENTROPY_TOKENS];
#endif // CONFIG_TX_SKIP
typedef struct macroblock MACROBLOCK; typedef struct macroblock MACROBLOCK;
struct macroblock { struct macroblock {
struct macroblock_plane plane[MAX_MB_PLANE]; struct macroblock_plane plane[MAX_MB_PLANE];
@ -111,6 +116,10 @@ struct macroblock {
// note that token_costs is the cost when eob node is skipped // note that token_costs is the cost when eob node is skipped
vp9_coeff_cost token_costs[TX_SIZES]; vp9_coeff_cost token_costs[TX_SIZES];
#if CONFIG_TX_SKIP
vp9_coeff_cost_pxd token_costs_pxd[TX_SIZES];
#endif // CONFIG_TX_SKIP
int in_static_area; int in_static_area;
int optimize; int optimize;

View File

@ -5043,8 +5043,8 @@ static void encode_superblock(VP9_COMP *cpi, TOKENEXTRA **t, int output_enabled,
#if CONFIG_TX_SKIP #if CONFIG_TX_SKIP
if (bsize >= BLOCK_8X8) { if (bsize >= BLOCK_8X8) {
int q_idx = vp9_get_qindex(&cm->seg, mbmi->segment_id, cm->base_qindex); int q_idx = vp9_get_qindex(&cm->seg, mbmi->segment_id, cm->base_qindex);
int try_tx_skip = is_inter_block(mbmi) ? q_idx <= TX_SKIP_Q_THRESH_INTER : int try_tx_skip = is_inter_block(mbmi) ? q_idx <= tx_skip_q_thresh_inter :
q_idx <= TX_SKIP_Q_THRESH_INTRA; q_idx <= tx_skip_q_thresh_intra;
#if CONFIG_COPY_MODE #if CONFIG_COPY_MODE
if (mbmi->copy_mode != NOREF) if (mbmi->copy_mode != NOREF)
try_tx_skip = 0; try_tx_skip = 0;

View File

@ -147,9 +147,8 @@ static int optimize_b(MACROBLOCK *mb, int plane, int block,
const int shift = (tx_size >= TX_32X32 ? tx_size - TX_16X16 : 0); const int shift = (tx_size >= TX_32X32 ? tx_size - TX_16X16 : 0);
const int mul = 1 << shift; const int mul = 1 << shift;
#if CONFIG_TX_SKIP #if CONFIG_TX_SKIP
const int16_t *dequant_ptr = int tx_skip = xd->mi[0].src_mi->mbmi.tx_skip[plane != 0];
xd->mi[0].src_mi->mbmi.tx_skip[plane != 0] ? const int16_t *dequant_ptr = tx_skip ? pd->dequant_pxd : pd->dequant;
pd->dequant_pxd : pd->dequant;
#else #else
const int16_t *dequant_ptr = pd->dequant; const int16_t *dequant_ptr = pd->dequant;
#endif // CONFIG_TX_SKIP #endif // CONFIG_TX_SKIP
@ -160,8 +159,7 @@ static int optimize_b(MACROBLOCK *mb, int plane, int block,
const dequant_val_type_nuq *dequant_val = pd->dequant_val_nuq; const dequant_val_type_nuq *dequant_val = pd->dequant_val_nuq;
#endif // CONFIG_NEW_QUANT #endif // CONFIG_NEW_QUANT
#if CONFIG_TX_SKIP #if CONFIG_TX_SKIP
const uint8_t *const band_translate = const uint8_t *const band_translate = tx_skip ?
xd->mi[0].src_mi->mbmi.tx_skip[plane != 0] ?
vp9_coefband_tx_skip : get_band_translate(tx_size); vp9_coefband_tx_skip : get_band_translate(tx_size);
#else #else
const uint8_t *const band_translate = get_band_translate(tx_size); const uint8_t *const band_translate = get_band_translate(tx_size);
@ -211,7 +209,7 @@ static int optimize_b(MACROBLOCK *mb, int plane, int block,
#else #else
dct_value_tokens = vp9_dct_value_tokens_ptr; dct_value_tokens = vp9_dct_value_tokens_ptr;
dct_value_cost = vp9_dct_value_cost_ptr; dct_value_cost = vp9_dct_value_cost_ptr;
#endif #endif // CONFIG_VP9_HIGHBITDEPTH
for (i = 0; i < eob; i++) for (i = 0; i < eob; i++)
token_cache[scan[i]] = token_cache[scan[i]] =
vp9_pt_energy_class[dct_value_tokens[qcoeff[scan[i]]].token]; vp9_pt_energy_class[dct_value_tokens[qcoeff[scan[i]]].token];
@ -233,11 +231,23 @@ static int optimize_b(MACROBLOCK *mb, int plane, int block,
if (next < default_eob) { if (next < default_eob) {
band = band_translate[i + 1]; band = band_translate[i + 1];
pt = trellis_get_coeff_context(scan, nb, i, t0, token_cache); pt = trellis_get_coeff_context(scan, nb, i, t0, token_cache);
rate0 += mb->token_costs[tx_size][type][ref][band][0][pt] #if CONFIG_TX_SKIP
[tokens[next][0].token]; if (tx_skip && FOR_SCREEN_CONTENT) {
rate1 += mb->token_costs[tx_size][type][ref][band][0][pt] rate0 += mb->token_costs_pxd[tx_size][type][ref][0][pt]
[tokens[next][1].token]; [tokens[next][0].token];
rate1 += mb->token_costs_pxd[tx_size][type][ref][0][pt]
[tokens[next][1].token];
} else {
#endif // CONFIG_TX_SKIP
rate0 += mb->token_costs[tx_size][type][ref][band][0][pt]
[tokens[next][0].token];
rate1 += mb->token_costs[tx_size][type][ref][band][0][pt]
[tokens[next][1].token];
#if CONFIG_TX_SKIP
}
#endif // CONFIG_TX_SKIP
} }
UPDATE_RD_COST(); UPDATE_RD_COST();
/* And pick the best. */ /* And pick the best. */
best = rd_cost1 < rd_cost0; best = rd_cost1 < rd_cost0;
@ -308,13 +318,25 @@ static int optimize_b(MACROBLOCK *mb, int plane, int block,
band = band_translate[i + 1]; band = band_translate[i + 1];
if (t0 != EOB_TOKEN) { if (t0 != EOB_TOKEN) {
pt = trellis_get_coeff_context(scan, nb, i, t0, token_cache); pt = trellis_get_coeff_context(scan, nb, i, t0, token_cache);
rate0 += mb->token_costs[tx_size][type][ref][band][!x][pt] #if CONFIG_TX_SKIP
[tokens[next][0].token]; if (tx_skip && FOR_SCREEN_CONTENT)
rate0 += mb->token_costs_pxd[tx_size][type][ref][!x][pt]
[tokens[next][0].token];
else
#endif // CONFIG_TX_SKIP
rate0 += mb->token_costs[tx_size][type][ref][band][!x][pt]
[tokens[next][0].token];
} }
if (t1 != EOB_TOKEN) { if (t1 != EOB_TOKEN) {
pt = trellis_get_coeff_context(scan, nb, i, t1, token_cache); pt = trellis_get_coeff_context(scan, nb, i, t1, token_cache);
rate1 += mb->token_costs[tx_size][type][ref][band][!x][pt] #if CONFIG_TX_SKIP
[tokens[next][1].token]; if (tx_skip && FOR_SCREEN_CONTENT)
rate0 += mb->token_costs_pxd[tx_size][type][ref][!x][pt]
[tokens[next][1].token];
else
#endif // CONFIG_TX_SKIP
rate1 += mb->token_costs[tx_size][type][ref][band][!x][pt]
[tokens[next][1].token];
} }
} }
@ -386,13 +408,25 @@ static int optimize_b(MACROBLOCK *mb, int plane, int block,
t1 = tokens[next][1].token; t1 = tokens[next][1].token;
/* Update the cost of each path if we're past the EOB token. */ /* Update the cost of each path if we're past the EOB token. */
if (t0 != EOB_TOKEN) { if (t0 != EOB_TOKEN) {
tokens[next][0].rate += #if CONFIG_TX_SKIP
mb->token_costs[tx_size][type][ref][band][1][0][t0]; if (tx_skip && FOR_SCREEN_CONTENT)
tokens[next][0].rate +=
mb->token_costs_pxd[tx_size][type][ref][1][0][t0];
else
#endif // CONFIG_TX_SKIP
tokens[next][0].rate +=
mb->token_costs[tx_size][type][ref][band][1][0][t0];
tokens[next][0].token = ZERO_TOKEN; tokens[next][0].token = ZERO_TOKEN;
} }
if (t1 != EOB_TOKEN) { if (t1 != EOB_TOKEN) {
tokens[next][1].rate += #if CONFIG_TX_SKIP
mb->token_costs[tx_size][type][ref][band][1][0][t1]; if (tx_skip && FOR_SCREEN_CONTENT)
tokens[next][1].rate +=
mb->token_costs_pxd[tx_size][type][ref][1][0][t1];
else
#endif // CONFIG_TX_SKIP
tokens[next][1].rate +=
mb->token_costs[tx_size][type][ref][band][1][0][t1];
tokens[next][1].token = ZERO_TOKEN; tokens[next][1].token = ZERO_TOKEN;
} }
best_index[i][0] = best_index[i][1] = 0; best_index[i][0] = best_index[i][1] = 0;
@ -408,8 +442,17 @@ static int optimize_b(MACROBLOCK *mb, int plane, int block,
error1 = tokens[next][1].error; error1 = tokens[next][1].error;
t0 = tokens[next][0].token; t0 = tokens[next][0].token;
t1 = tokens[next][1].token; t1 = tokens[next][1].token;
rate0 += mb->token_costs[tx_size][type][ref][band][0][ctx][t0]; #if CONFIG_TX_SKIP
rate1 += mb->token_costs[tx_size][type][ref][band][0][ctx][t1]; if (tx_skip && FOR_SCREEN_CONTENT) {
rate0 += mb->token_costs_pxd[tx_size][type][ref][0][ctx][t0];
rate1 += mb->token_costs_pxd[tx_size][type][ref][0][ctx][t1];
} else {
#endif // CONFIG_TX_SKIP
rate0 += mb->token_costs[tx_size][type][ref][band][0][ctx][t0];
rate1 += mb->token_costs[tx_size][type][ref][band][0][ctx][t1];
#if CONFIG_TX_SKIP
}
#endif // CONFIG_TX_SKIP
UPDATE_RD_COST(); UPDATE_RD_COST();
best = rd_cost1 < rd_cost0; best = rd_cost1 < rd_cost0;
final_eob = -1; final_eob = -1;

View File

@ -118,6 +118,27 @@ static void fill_token_costs(vp9_coeff_cost *c,
} }
} }
#if CONFIG_TX_SKIP
static void fill_token_costs_pxd(vp9_coeff_cost_pxd *c,
vp9_coeff_probs_pxd (*p)[PLANE_TYPES]) {
int i, j, l;
TX_SIZE t;
for (t = TX_4X4; t < TX_SIZES; ++t)
for (i = 0; i < PLANE_TYPES; ++i)
for (j = 0; j < REF_TYPES; ++j)
for (l = 0; l < COEFF_CONTEXTS; ++l) {
vp9_prob *probs;
probs = p[t][i][j][l];
vp9_cost_tokens((int *)c[t][i][j][0][l], probs,
vp9_coef_tree);
vp9_cost_tokens_skip((int *)c[t][i][j][1][l], probs,
vp9_coef_tree);
assert(c[t][i][j][0][l][EOB_TOKEN] ==
c[t][i][j][1][l][EOB_TOKEN]);
}
}
#endif // CONFIG_TX_SKIP
// Values are now correlated to quantizer. // Values are now correlated to quantizer.
static int sad_per_bit16lut_8[QINDEX_RANGE]; static int sad_per_bit16lut_8[QINDEX_RANGE];
static int sad_per_bit4lut_8[QINDEX_RANGE]; static int sad_per_bit4lut_8[QINDEX_RANGE];
@ -295,6 +316,10 @@ void vp9_initialize_rd_consts(VP9_COMP *cpi) {
if (!cpi->sf.use_nonrd_pick_mode || cm->frame_type == KEY_FRAME) { if (!cpi->sf.use_nonrd_pick_mode || cm->frame_type == KEY_FRAME) {
fill_token_costs(x->token_costs, cm->fc.coef_probs); fill_token_costs(x->token_costs, cm->fc.coef_probs);
#if CONFIG_TX_SKIP
if (FOR_SCREEN_CONTENT)
fill_token_costs_pxd(x->token_costs_pxd, cm->fc.coef_probs_pxd);
#endif // CONFIG_TX_SKIP
for (i = 0; i < PARTITION_CONTEXTS; ++i) for (i = 0; i < PARTITION_CONTEXTS; ++i)
vp9_cost_tokens(cpi->partition_cost[i], get_partition_probs(cm, i), vp9_cost_tokens(cpi->partition_cost[i], get_partition_probs(cm, i),

View File

@ -502,6 +502,82 @@ static INLINE int cost_coeffs(MACROBLOCK *x,
return cost; return cost;
} }
#if CONFIG_TX_SKIP
static INLINE int cost_coeffs_pxd(MACROBLOCK *x,
int plane, int block,
ENTROPY_CONTEXT *A, ENTROPY_CONTEXT *L,
TX_SIZE tx_size,
const int16_t *scan, const int16_t *nb,
int use_fast_coef_costing) {
MACROBLOCKD *const xd = &x->e_mbd;
MB_MODE_INFO *mbmi = &xd->mi[0].src_mi->mbmi;
const struct macroblock_plane *p = &x->plane[plane];
const struct macroblockd_plane *pd = &xd->plane[plane];
const PLANE_TYPE type = pd->plane_type;
const int16_t *band_count = &band_counts[tx_size][1];
const int eob = p->eobs[block];
const tran_low_t *const qcoeff = BLOCK_OFFSET(p->qcoeff, block);
unsigned int (*token_costs)[COEFF_CONTEXTS][ENTROPY_TOKENS] =
x->token_costs_pxd[tx_size][type][is_inter_block(mbmi)];
uint8_t token_cache[MAX_NUM_COEFS];
int pt = combine_entropy_contexts(*A, *L);
int c, cost;
// Check for consistency of tx_size with mode info
#if !CONFIG_SUPERTX
assert(type == PLANE_TYPE_Y ? mbmi->tx_size == tx_size
: get_uv_tx_size(mbmi, pd) == tx_size);
#endif // CONFIG_SUPERTX
if (eob == 0) {
// single eob token
cost = token_costs[0][pt][EOB_TOKEN];
c = 0;
} else {
int band_left = *band_count++;
// dc token
int v = qcoeff[0];
int prev_t = vp9_dct_value_tokens_ptr[v].token;
cost = token_costs[0][pt][prev_t] + vp9_dct_value_cost_ptr[v];
token_cache[0] = vp9_pt_energy_class[prev_t];
// ac tokens
for (c = 1; c < eob; c++) {
const int rc = scan[c];
int t;
v = qcoeff[rc];
t = vp9_dct_value_tokens_ptr[v].token;
if (use_fast_coef_costing) {
cost += token_costs[!prev_t][!prev_t][t] + vp9_dct_value_cost_ptr[v];
} else {
pt = get_coef_context(nb, token_cache, c);
cost += token_costs[!prev_t][pt][t] + vp9_dct_value_cost_ptr[v];
token_cache[rc] = vp9_pt_energy_class[t];
}
prev_t = t;
if (!--band_left) {
band_left = *band_count++;
}
}
// eob token
if (band_left) {
if (use_fast_coef_costing) {
cost += token_costs[0][!prev_t][EOB_TOKEN];
} else {
pt = get_coef_context(nb, token_cache, c);
cost += token_costs[0][pt][EOB_TOKEN];
}
}
}
// is eob first coefficient;
*A = *L = (c > 0);
return cost;
}
#endif // CONFIG_TX_SKIP
#define right_shift_signed(x, s) ((s) < 0 ? (x) << (-(s)) : (x) >> (s)) #define right_shift_signed(x, s) ((s) < 0 ? (x) << (-(s)) : (x) >> (s))
#if CONFIG_VP9_HIGHBITDEPTH #if CONFIG_VP9_HIGHBITDEPTH
@ -558,10 +634,19 @@ static void rate_block(int plane, int block, BLOCK_SIZE plane_bsize,
int x_idx, y_idx; int x_idx, y_idx;
txfrm_block_to_raster_xy(plane_bsize, tx_size, block, &x_idx, &y_idx); txfrm_block_to_raster_xy(plane_bsize, tx_size, block, &x_idx, &y_idx);
args->rate = cost_coeffs(args->x, plane, block, args->t_above + x_idx, #if CONFIG_TX_SKIP
args->t_left + y_idx, tx_size, if (args->x->e_mbd.mi[0].src_mi->mbmi.tx_skip[plane != 0] &&
args->so->scan, args->so->neighbors, FOR_SCREEN_CONTENT)
args->use_fast_coef_costing); args->rate = cost_coeffs_pxd(args->x, plane, block, args->t_above + x_idx,
args->t_left + y_idx, tx_size,
args->so->scan, args->so->neighbors,
args->use_fast_coef_costing);
else
#endif // CONFIG_TX_SKIP
args->rate = cost_coeffs(args->x, plane, block, args->t_above + x_idx,
args->t_left + y_idx, tx_size,
args->so->scan, args->so->neighbors,
args->use_fast_coef_costing);
} }
static void block_rd_txfm(int plane, int block, BLOCK_SIZE plane_bsize, static void block_rd_txfm(int plane, int block, BLOCK_SIZE plane_bsize,
@ -1695,7 +1780,7 @@ static int64_t rd_pick_intra_sby_mode(VP9_COMP *cpi, MACROBLOCK *x,
int tx_skipped = 0; int tx_skipped = 0;
int q_idx = vp9_get_qindex(&cpi->common.seg, mic->mbmi.segment_id, int q_idx = vp9_get_qindex(&cpi->common.seg, mic->mbmi.segment_id,
cpi->common.base_qindex); cpi->common.base_qindex);
int try_tx_skip = q_idx <= TX_SKIP_Q_THRESH_INTRA; int try_tx_skip = q_idx <= tx_skip_q_thresh_intra;
#endif // CONFIG_TX_SKIP #endif // CONFIG_TX_SKIP
#if CONFIG_PALETTE #if CONFIG_PALETTE
int palette_selected = 0, best_n = 0, colors, palette_ctx; int palette_selected = 0, best_n = 0, colors, palette_ctx;
@ -2137,7 +2222,7 @@ static int64_t rd_pick_intrabc_sb_mode(VP9_COMP *cpi, MACROBLOCK *x,
#if CONFIG_TX_SKIP #if CONFIG_TX_SKIP
int q_idx = vp9_get_qindex(&cpi->common.seg, mbmi->segment_id, int q_idx = vp9_get_qindex(&cpi->common.seg, mbmi->segment_id,
cpi->common.base_qindex); cpi->common.base_qindex);
int try_tx_skip = q_idx <= TX_SKIP_Q_THRESH_INTRA; int try_tx_skip = q_idx <= tx_skip_q_thresh_intra;
mbmi->tx_skip[0] = 0; mbmi->tx_skip[0] = 0;
mbmi->tx_skip[1] = 0; mbmi->tx_skip[1] = 0;
#endif // CONFIG_TX_SKIP #endif // CONFIG_TX_SKIP
@ -2284,7 +2369,7 @@ static int64_t rd_pick_intra_sbuv_mode(VP9_COMP *cpi, MACROBLOCK *x,
int q_idx = vp9_get_qindex(&cpi->common.seg, int q_idx = vp9_get_qindex(&cpi->common.seg,
xd->mi[0].src_mi->mbmi.segment_id, xd->mi[0].src_mi->mbmi.segment_id,
cpi->common.base_qindex); cpi->common.base_qindex);
int try_tx_skip = q_idx <= TX_SKIP_Q_THRESH_INTRA && bsize >= BLOCK_8X8; int try_tx_skip = q_idx <= tx_skip_q_thresh_intra && bsize >= BLOCK_8X8;
#endif // CONFIG_TX_SKIP #endif // CONFIG_TX_SKIP
#if CONFIG_PALETTE #if CONFIG_PALETTE
int palette_selected = 0, best_n = 0; int palette_selected = 0, best_n = 0;
@ -5251,7 +5336,7 @@ static int64_t handle_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
bsize, txfm_cache, ref_best_rd); bsize, txfm_cache, ref_best_rd);
#if CONFIG_TX_SKIP #if CONFIG_TX_SKIP
if (vp9_get_qindex(&cm->seg, mbmi->segment_id, cm->base_qindex) <= if (vp9_get_qindex(&cm->seg, mbmi->segment_id, cm->base_qindex) <=
TX_SKIP_Q_THRESH_INTER) { tx_skip_q_thresh_inter) {
mbmi->tx_skip[0] = 1; mbmi->tx_skip[0] = 1;
super_block_yrd(cpi, x, &rate_s, &distortion_s, &skippable_s, &psse_s, super_block_yrd(cpi, x, &rate_s, &distortion_s, &skippable_s, &psse_s,
bsize, tx_cache_s, ref_best_rd); bsize, tx_cache_s, ref_best_rd);
@ -5291,7 +5376,7 @@ static int64_t handle_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
#if CONFIG_TX_SKIP #if CONFIG_TX_SKIP
if (vp9_get_qindex(&cm->seg, mbmi->segment_id, cm->base_qindex) <= if (vp9_get_qindex(&cm->seg, mbmi->segment_id, cm->base_qindex) <=
TX_SKIP_Q_THRESH_INTER) { tx_skip_q_thresh_inter) {
super_block_uvrd(cpi, x, rate_uv, &distortion_uv, &skippable_uv, super_block_uvrd(cpi, x, rate_uv, &distortion_uv, &skippable_uv,
&sseuv, bsize, ref_best_rd - rdcosty); &sseuv, bsize, ref_best_rd - rdcosty);
mbmi->tx_skip[1] = 1; mbmi->tx_skip[1] = 1;
@ -5322,7 +5407,7 @@ static int64_t handle_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
} }
#if CONFIG_TX_SKIP #if CONFIG_TX_SKIP
if (vp9_get_qindex(&cm->seg, mbmi->segment_id, cm->base_qindex) <= if (vp9_get_qindex(&cm->seg, mbmi->segment_id, cm->base_qindex) <=
TX_SKIP_Q_THRESH_INTER) tx_skip_q_thresh_inter)
*rate_uv += vp9_cost_bit(cpi->common.fc.uv_tx_skip_prob[mbmi->tx_skip[0]], *rate_uv += vp9_cost_bit(cpi->common.fc.uv_tx_skip_prob[mbmi->tx_skip[0]],
mbmi->tx_skip[1]); mbmi->tx_skip[1]);
#endif #endif
@ -5387,7 +5472,7 @@ static void rd_pick_palette_444(VP9_COMP *cpi, MACROBLOCK *x, RD_COST *rd_cost,
#if CONFIG_TX_SKIP #if CONFIG_TX_SKIP
int q_idx = vp9_get_qindex(&cpi->common.seg, mbmi->segment_id, int q_idx = vp9_get_qindex(&cpi->common.seg, mbmi->segment_id,
cpi->common.base_qindex); cpi->common.base_qindex);
int try_tx_skip = q_idx <= TX_SKIP_Q_THRESH_INTRA; int try_tx_skip = q_idx <= tx_skip_q_thresh_intra;
int this_rate_tokenonly_s, s_s; int this_rate_tokenonly_s, s_s;
int tx_skipped = 0, tx_skipped_uv = 0; int tx_skipped = 0, tx_skipped_uv = 0;
int64_t this_distortion_s; int64_t this_distortion_s;
@ -5815,7 +5900,7 @@ void vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
#if CONFIG_TX_SKIP #if CONFIG_TX_SKIP
int tx_skipped_uv[TX_SIZES]; int tx_skipped_uv[TX_SIZES];
int q_idx = vp9_get_qindex(seg, segment_id, cm->base_qindex); int q_idx = vp9_get_qindex(seg, segment_id, cm->base_qindex);
int try_tx_skip = q_idx <= TX_SKIP_Q_THRESH_INTRA; int try_tx_skip = q_idx <= tx_skip_q_thresh_intra;
#endif // CONFIG_TX_SKIP #endif // CONFIG_TX_SKIP
#if CONFIG_COPY_MODE #if CONFIG_COPY_MODE
COPY_MODE copy_mode; COPY_MODE copy_mode;

View File

@ -164,7 +164,7 @@ const vp9_extra_bit vp9_extra_bits_high12[ENTROPY_TOKENS] = {
// CATEGORY6_TOKEN // CATEGORY6_TOKEN
{0, 0, 0, 0} // EOB_TOKEN {0, 0, 0, 0} // EOB_TOKEN
}; };
#endif #endif // CONFIG_VP9_HIGHBITDEPTH
struct vp9_token vp9_coef_encodings[ENTROPY_TOKENS]; struct vp9_token vp9_coef_encodings[ENTROPY_TOKENS];
@ -241,7 +241,7 @@ void vp9_tokenize_initialize() {
vp9_extra_bits_high12, vp9_extra_bits_high12,
dct_value_cost_high12 + DCT_MAX_VALUE_HIGH12, dct_value_cost_high12 + DCT_MAX_VALUE_HIGH12,
DCT_MAX_VALUE_HIGH12); DCT_MAX_VALUE_HIGH12);
#endif #endif // CONFIG_VP9_HIGHBITDEPTH
} }
struct tokenize_b_args { struct tokenize_b_args {
@ -319,7 +319,8 @@ static void tokenize_b(int plane, int block, BLOCK_SIZE plane_bsize,
unsigned int (*const eob_branch)[COEFF_CONTEXTS] = unsigned int (*const eob_branch)[COEFF_CONTEXTS] =
cpi->common.counts.eob_branch[tx_size][type][ref]; cpi->common.counts.eob_branch[tx_size][type][ref];
#if CONFIG_TX_SKIP #if CONFIG_TX_SKIP
const uint8_t *const band = mbmi->tx_skip[plane != 0] ? int tx_skip = mbmi->tx_skip[plane != 0];
const uint8_t *const band = tx_skip ?
vp9_coefband_tx_skip : get_band_translate(tx_size); vp9_coefband_tx_skip : get_band_translate(tx_size);
#else #else
const uint8_t *const band = get_band_translate(tx_size); const uint8_t *const band = get_band_translate(tx_size);
@ -357,7 +358,6 @@ static void tokenize_b(int plane, int block, BLOCK_SIZE plane_bsize,
add_token_no_extra(&t, coef_probs[band[c]][pt], ZERO_TOKEN, skip_eob, add_token_no_extra(&t, coef_probs[band[c]][pt], ZERO_TOKEN, skip_eob,
counts[band[c]][pt]); counts[band[c]][pt]);
eob_branch[band[c]][pt] += !skip_eob; eob_branch[band[c]][pt] += !skip_eob;
skip_eob = 1; skip_eob = 1;
token_cache[scan[c]] = 0; token_cache[scan[c]] = 0;
++c; ++c;
@ -365,13 +365,15 @@ static void tokenize_b(int plane, int block, BLOCK_SIZE plane_bsize,
v = qcoeff[scan[c]]; v = qcoeff[scan[c]];
} }
#if CONFIG_TX_SKIP
t->is_pxd_token = tx_skip;
#endif // CONFIG_TX_SKIP
add_token(&t, coef_probs[band[c]][pt], add_token(&t, coef_probs[band[c]][pt],
dct_value_tokens[v].extra, dct_value_tokens[v].extra,
(uint8_t)dct_value_tokens[v].token, (uint8_t)dct_value_tokens[v].token,
(uint8_t)skip_eob, (uint8_t)skip_eob,
counts[band[c]][pt]); counts[band[c]][pt]);
eob_branch[band[c]][pt] += !skip_eob; eob_branch[band[c]][pt] += !skip_eob;
token_cache[scan[c]] = vp9_pt_energy_class[dct_value_tokens[v].token]; token_cache[scan[c]] = vp9_pt_energy_class[dct_value_tokens[v].token];
++c; ++c;
pt = get_coef_context(nb, token_cache, c); pt = get_coef_context(nb, token_cache, c);
@ -386,6 +388,94 @@ static void tokenize_b(int plane, int block, BLOCK_SIZE plane_bsize,
vp9_set_contexts(xd, pd, plane_bsize, tx_size, c > 0, aoff, loff); vp9_set_contexts(xd, pd, plane_bsize, tx_size, c > 0, aoff, loff);
} }
#if CONFIG_TX_SKIP
static void tokenize_b_pxd(int plane, int block, BLOCK_SIZE plane_bsize,
TX_SIZE tx_size, void *arg) {
struct tokenize_b_args* const args = arg;
VP9_COMP *cpi = args->cpi;
MACROBLOCKD *xd = args->xd;
TOKENEXTRA **tp = args->tp;
uint8_t token_cache[MAX_NUM_COEFS];
struct macroblock_plane *p = &cpi->mb.plane[plane];
struct macroblockd_plane *pd = &xd->plane[plane];
MB_MODE_INFO *mbmi = &xd->mi[0].src_mi->mbmi;
int pt; /* near block/prev token context index */
int c;
int tx_skip = mbmi->tx_skip[plane != 0];
TOKENEXTRA *t = *tp; /* store tokens starting here */
int eob = p->eobs[block];
const PLANE_TYPE type = pd->plane_type;
const tran_low_t *qcoeff = BLOCK_OFFSET(p->qcoeff, block);
const int segment_id = mbmi->segment_id;
const int16_t *scan, *nb;
const scan_order *so;
const int ref = is_inter_block(mbmi);
vp9_prob (*const coef_probs_pxd)[ENTROPY_TOKENS - 1] =
cpi->common.fc.coef_probs_pxd[tx_size][type][ref];
unsigned int (*const counts_pxd)[ENTROPY_TOKENS] =
cpi->common.counts.coef_pxd[tx_size][type][ref];
unsigned int *const eob_branch_pxd =
cpi->common.counts.eob_branch_pxd[tx_size][type][ref];
const int seg_eob = get_tx_eob(&cpi->common.seg, segment_id, tx_size);
const TOKENVALUE *dct_value_tokens;
int aoff, loff;
txfrm_block_to_raster_xy(plane_bsize, tx_size, block, &aoff, &loff);
pt = get_entropy_context(tx_size, pd->above_context + aoff,
pd->left_context + loff);
so = get_scan(xd, tx_size, type, block);
scan = so->scan;
nb = so->neighbors;
c = 0;
#if CONFIG_VP9_HIGHBITDEPTH
if (cpi->common.profile >= PROFILE_2) {
dct_value_tokens = (cpi->common.bit_depth == VPX_BITS_10 ?
vp9_dct_value_tokens_high10_ptr :
vp9_dct_value_tokens_high12_ptr);
} else {
dct_value_tokens = vp9_dct_value_tokens_ptr;
}
#else
dct_value_tokens = vp9_dct_value_tokens_ptr;
#endif // CONFIG_VP9_HIGHBITDEPTH
while (c < eob) {
int v = 0;
int skip_eob = 0;
v = qcoeff[scan[c]];
while (!v) {
add_token_no_extra(&t, coef_probs_pxd[pt], ZERO_TOKEN, skip_eob,
counts_pxd[pt]);
eob_branch_pxd[pt] += !skip_eob;
skip_eob = 1;
token_cache[scan[c]] = 0;
++c;
pt = get_coef_context(nb, token_cache, c);
v = qcoeff[scan[c]];
}
t->is_pxd_token = tx_skip;
add_token(&t, coef_probs_pxd[pt],
dct_value_tokens[v].extra,
(uint8_t)dct_value_tokens[v].token,
(uint8_t)skip_eob,
counts_pxd[pt]);
eob_branch_pxd[pt] += !skip_eob;
token_cache[scan[c]] = vp9_pt_energy_class[dct_value_tokens[v].token];
++c;
pt = get_coef_context(nb, token_cache, c);
}
if (c < seg_eob) {
add_token_no_extra(&t, coef_probs_pxd[pt], EOB_TOKEN, 0,
counts_pxd[pt]);
++eob_branch_pxd[pt];
}
*tp = t;
vp9_set_contexts(xd, pd, plane_bsize, tx_size, c > 0, aoff, loff);
}
#endif // CONFIG_TX_SKIP
struct is_skippable_args { struct is_skippable_args {
MACROBLOCK *x; MACROBLOCK *x;
int *skippable; int *skippable;
@ -436,6 +526,9 @@ void vp9_tokenize_sb(VP9_COMP *cpi, TOKENEXTRA **t, int dry_run,
const int ctx = vp9_get_skip_context(xd); const int ctx = vp9_get_skip_context(xd);
const int skip_inc = !vp9_segfeature_active(&cm->seg, mbmi->segment_id, const int skip_inc = !vp9_segfeature_active(&cm->seg, mbmi->segment_id,
SEG_LVL_SKIP); SEG_LVL_SKIP);
#if CONFIG_TX_SKIP
int plane;
#endif // CONFIG_TX_SKIP
struct tokenize_b_args arg = {cpi, xd, t}; struct tokenize_b_args arg = {cpi, xd, t};
if (mbmi->skip) { if (mbmi->skip) {
if (!dry_run) if (!dry_run)
@ -448,7 +541,25 @@ void vp9_tokenize_sb(VP9_COMP *cpi, TOKENEXTRA **t, int dry_run,
if (!dry_run) { if (!dry_run) {
cm->counts.skip[ctx][0] += skip_inc; cm->counts.skip[ctx][0] += skip_inc;
vp9_foreach_transformed_block(xd, bsize, tokenize_b, &arg); #if CONFIG_TX_SKIP
if (mbmi->tx_skip[0] && FOR_SCREEN_CONTENT)
vp9_foreach_transformed_block_in_plane(xd, bsize, 0,
tokenize_b_pxd, &arg);
else
vp9_foreach_transformed_block_in_plane(xd, bsize, 0, tokenize_b, &arg);
if (mbmi->tx_skip[1] && FOR_SCREEN_CONTENT) {
for (plane = 1; plane < MAX_MB_PLANE; ++plane)
vp9_foreach_transformed_block_in_plane(xd, bsize, plane,
tokenize_b_pxd, &arg);
} else {
for (plane = 1; plane < MAX_MB_PLANE; ++plane)
vp9_foreach_transformed_block_in_plane(xd, bsize, plane,
tokenize_b, &arg);
}
#else
vp9_foreach_transformed_block(xd, bsize, tokenize_b, &arg);
#endif
} else { } else {
vp9_foreach_transformed_block(xd, bsize, set_entropy_context_b, &arg); vp9_foreach_transformed_block(xd, bsize, set_entropy_context_b, &arg);
*t = t_backup; *t = t_backup;

View File

@ -42,6 +42,9 @@ typedef struct {
#endif #endif
uint8_t token; uint8_t token;
uint8_t skip_eob_node; uint8_t skip_eob_node;
#if CONFIG_TX_SKIP
uint8_t is_pxd_token;
#endif // CONFIG_TX_SKIP
} TOKENEXTRA; } TOKENEXTRA;
extern const vp9_tree_index vp9_coef_tree[]; extern const vp9_tree_index vp9_coef_tree[];