shithub: libvpx

Download patch

ref: fba0ead5430fd09b65fa2f10cd07b1cb07a0c087
parent: 6121dd89ff2fbb32dd87f940c0ce89a3864bb0f0
parent: 4b8c6d96ec0ec2cc7c78e8e663ab7329704c92b9
author: Jim Bankoski <jimbankoski@google.com>
date: Mon Dec 22 08:36:38 EST 2014

Merge "Tokenization without huge tables."

--- a/vp9/encoder/vp9_encodemb.c
+++ b/vp9/encoder/vp9_encodemb.c
@@ -149,7 +149,6 @@
   int64_t rd_cost0, rd_cost1;
   int rate0, rate1, error0, error1, t0, t1;
   int best, band, pt, i, final_eob;
-  const TOKENVALUE *dct_value_tokens;
   const int16_t *dct_value_cost;
 
   assert((!type && !plane) || (type && plane));
@@ -169,22 +168,18 @@
 
 #if CONFIG_VP9_HIGHBITDEPTH
   if (xd->bd == 12) {
-    dct_value_tokens = vp9_dct_value_tokens_high12_ptr;
     dct_value_cost = vp9_dct_value_cost_high12_ptr;
   } else if (xd->bd == 10) {
-    dct_value_tokens = vp9_dct_value_tokens_high10_ptr;
     dct_value_cost = vp9_dct_value_cost_high10_ptr;
   } else {
-    dct_value_tokens = vp9_dct_value_tokens_ptr;
     dct_value_cost = vp9_dct_value_cost_ptr;
   }
 #else
-  dct_value_tokens = vp9_dct_value_tokens_ptr;
   dct_value_cost = vp9_dct_value_cost_ptr;
 #endif
   for (i = 0; i < eob; i++)
     token_cache[scan[i]] =
-        vp9_pt_energy_class[dct_value_tokens[qcoeff[scan[i]]].token];
+        vp9_pt_energy_class[vp9_get_token(qcoeff[scan[i]])];
 
   for (i = eob; i-- > 0;) {
     int base_bits, d2, dx;
@@ -198,7 +193,7 @@
       /* Evaluate the first possibility for this state. */
       rate0 = tokens[next][0].rate;
       rate1 = tokens[next][1].rate;
-      t0 = (dct_value_tokens + x)->token;
+      t0 = vp9_get_token(x);
       /* Consider both possible successor states. */
       if (next < default_eob) {
         band = band_translate[i + 1];
@@ -250,7 +245,7 @@
         t0 = tokens[next][0].token == EOB_TOKEN ? EOB_TOKEN : ZERO_TOKEN;
         t1 = tokens[next][1].token == EOB_TOKEN ? EOB_TOKEN : ZERO_TOKEN;
       } else {
-        t0 = t1 = (dct_value_tokens + x)->token;
+        t0 = t1 = vp9_get_token(x);
       }
       if (next < default_eob) {
         band = band_translate[i + 1];
--- a/vp9/encoder/vp9_rdopt.c
+++ b/vp9/encoder/vp9_rdopt.c
@@ -373,7 +373,7 @@
 
     // dc token
     int v = qcoeff[0];
-    int prev_t = vp9_dct_value_tokens_ptr[v].token;
+    int prev_t = vp9_get_token(v);
     cost = (*token_costs)[0][pt][prev_t] + vp9_dct_value_cost_ptr[v];
     token_cache[0] = vp9_pt_energy_class[prev_t];
     ++token_costs;
@@ -384,7 +384,7 @@
       int t;
 
       v = qcoeff[rc];
-      t = vp9_dct_value_tokens_ptr[v].token;
+      t = vp9_get_token(v);
       if (use_fast_coef_costing) {
         cost += (*token_costs)[!prev_t][!prev_t][t] + vp9_dct_value_cost_ptr[v];
       } else {
--- a/vp9/encoder/vp9_tokenize.c
+++ b/vp9/encoder/vp9_tokenize.c
@@ -23,23 +23,46 @@
 #include "vp9/encoder/vp9_encoder.h"
 #include "vp9/encoder/vp9_tokenize.h"
 
-static TOKENVALUE dct_value_tokens[DCT_MAX_VALUE * 2];
-const TOKENVALUE *vp9_dct_value_tokens_ptr;
 static int16_t dct_value_cost[DCT_MAX_VALUE * 2];
-const int16_t *vp9_dct_value_cost_ptr;
+const int16_t *vp9_dct_value_cost_ptr = dct_value_cost + DCT_MAX_VALUE;
 
 #if CONFIG_VP9_HIGHBITDEPTH
-static TOKENVALUE dct_value_tokens_high10[DCT_MAX_VALUE_HIGH10 * 2];
-const TOKENVALUE *vp9_dct_value_tokens_high10_ptr;
 static int16_t dct_value_cost_high10[DCT_MAX_VALUE_HIGH10 * 2];
-const int16_t *vp9_dct_value_cost_high10_ptr;
+const int16_t *vp9_dct_value_cost_high10_ptr =
+    dct_value_cost_high10 + DCT_MAX_VALUE_HIGH10;
 
-static TOKENVALUE dct_value_tokens_high12[DCT_MAX_VALUE_HIGH12 * 2];
-const TOKENVALUE *vp9_dct_value_tokens_high12_ptr;
 static int16_t dct_value_cost_high12[DCT_MAX_VALUE_HIGH12 * 2];
-const int16_t *vp9_dct_value_cost_high12_ptr;
+const int16_t *vp9_dct_value_cost_high12_ptr =
+    dct_value_cost_high12 + DCT_MAX_VALUE_HIGH12;
 #endif
 
+static const TOKENVALUE dct_cat_lt_10_value_tokens[] = {
+  {9, 63}, {9, 61}, {9, 59}, {9, 57}, {9, 55}, {9, 53}, {9, 51}, {9, 49},
+  {9, 47}, {9, 45}, {9, 43}, {9, 41}, {9, 39}, {9, 37}, {9, 35}, {9, 33},
+  {9, 31}, {9, 29}, {9, 27}, {9, 25}, {9, 23}, {9, 21}, {9, 19}, {9, 17},
+  {9, 15}, {9, 13}, {9, 11}, {9, 9}, {9, 7}, {9, 5}, {9, 3}, {9, 1},
+  {8, 31}, {8, 29}, {8, 27}, {8, 25}, {8, 23}, {8, 21},
+  {8, 19}, {8, 17}, {8, 15}, {8, 13}, {8, 11}, {8, 9},
+  {8, 7}, {8, 5}, {8, 3}, {8, 1},
+  {7, 15}, {7, 13}, {7, 11}, {7, 9}, {7, 7}, {7, 5}, {7, 3}, {7, 1},
+  {6, 7}, {6, 5}, {6, 3}, {6, 1}, {5, 3}, {5, 1},
+  {4, 1}, {3, 1}, {2, 1}, {1, 1}, {0, 0},
+  {1, 0},  {2, 0}, {3, 0}, {4, 0},
+  {5, 0}, {5, 2}, {6, 0}, {6, 2}, {6, 4}, {6, 6},
+  {7, 0}, {7, 2}, {7, 4}, {7, 6}, {7, 8}, {7, 10}, {7, 12}, {7, 14},
+  {8, 0}, {8, 2}, {8, 4}, {8, 6}, {8, 8}, {8, 10}, {8, 12},
+  {8, 14}, {8, 16}, {8, 18}, {8, 20}, {8, 22}, {8, 24},
+  {8, 26}, {8, 28}, {8, 30}, {9, 0}, {9, 2},
+  {9, 4}, {9, 6}, {9, 8}, {9, 10}, {9, 12}, {9, 14}, {9, 16},
+  {9, 18}, {9, 20}, {9, 22}, {9, 24}, {9, 26}, {9, 28},
+  {9, 30}, {9, 32}, {9, 34}, {9, 36}, {9, 38}, {9, 40},
+  {9, 42}, {9, 44}, {9, 46}, {9, 48}, {9, 50}, {9, 52},
+  {9, 54}, {9, 56}, {9, 58}, {9, 60}, {9, 62}
+};
+const TOKENVALUE *vp9_dct_cat_lt_10_value_tokens = dct_cat_lt_10_value_tokens +
+    (sizeof(dct_cat_lt_10_value_tokens) / sizeof(*dct_cat_lt_10_value_tokens))
+    / 2;
+
 // Array indices are identical to previously-existing CONTEXT_NODE indices
 const vp9_tree_index vp9_coef_tree[TREE_SIZE(ENTROPY_TOKENS)] = {
   -EOB_TOKEN, 2,                       // 0  = EOB
@@ -158,39 +181,21 @@
   vp9_tokens_from_tree(vp9_coef_encodings, vp9_coef_tree);
 }
 
-static void tokenize_init_one(TOKENVALUE *t, const vp9_extra_bit *const e,
+static void tokenize_init_one(const vp9_extra_bit *const e,
                               int16_t *value_cost, int max_value) {
   int i = -max_value;
-  int sign = 1;
 
+  TOKENVALUE t;
   do {
-    if (!i)
-      sign = 0;
 
-    {
-      const int a = sign ? -i : i;
-      int eb = sign;
-
-      if (a > 4) {
-        int j = 4;
-
-        while (++j < 11  &&  e[j].base_val <= a) {}
-
-        t[i].token = --j;
-        eb |= (a - e[j].base_val) << 1;
-      } else {
-        t[i].token = a;
-      }
-      t[i].extra = eb;
-    }
-
+    vp9_get_token_extra(i, &t.token, &t.extra);
     // initialize the cost for extra bits for all possible coefficient value.
     {
       int cost = 0;
-      const vp9_extra_bit *p = &e[t[i].token];
+      const vp9_extra_bit *p = &e[t.token];
 
       if (p->base_val) {
-        const int extra = t[i].extra;
+        const int extra = t.extra;
         const int length = p->len;
 
         if (length)
@@ -204,26 +209,14 @@
 }
 
 void vp9_tokenize_initialize() {
-  vp9_dct_value_tokens_ptr = dct_value_tokens + DCT_MAX_VALUE;
-  vp9_dct_value_cost_ptr = dct_value_cost + DCT_MAX_VALUE;
-
-  tokenize_init_one(dct_value_tokens + DCT_MAX_VALUE, vp9_extra_bits,
+  tokenize_init_one(vp9_extra_bits,
                     dct_value_cost + DCT_MAX_VALUE, DCT_MAX_VALUE);
 #if CONFIG_VP9_HIGHBITDEPTH
-  vp9_dct_value_tokens_high10_ptr = dct_value_tokens_high10 +
-      DCT_MAX_VALUE_HIGH10;
-  vp9_dct_value_cost_high10_ptr = dct_value_cost_high10 + DCT_MAX_VALUE_HIGH10;
-
-  tokenize_init_one(dct_value_tokens_high10 + DCT_MAX_VALUE_HIGH10,
-                    vp9_extra_bits_high10,
+  tokenize_init_one(vp9_extra_bits_high10,
                     dct_value_cost_high10 + DCT_MAX_VALUE_HIGH10,
                     DCT_MAX_VALUE_HIGH10);
-  vp9_dct_value_tokens_high12_ptr = dct_value_tokens_high12 +
-      DCT_MAX_VALUE_HIGH12;
-  vp9_dct_value_cost_high12_ptr = dct_value_cost_high12 + DCT_MAX_VALUE_HIGH12;
 
-  tokenize_init_one(dct_value_tokens_high12 + DCT_MAX_VALUE_HIGH12,
-                    vp9_extra_bits_high12,
+  tokenize_init_one(vp9_extra_bits_high12,
                     dct_value_cost_high12 + DCT_MAX_VALUE_HIGH12,
                     DCT_MAX_VALUE_HIGH12);
 #endif
@@ -309,8 +302,8 @@
       td->counts->eob_branch[tx_size][type][ref];
   const uint8_t *const band = get_band_translate(tx_size);
   const int seg_eob = get_tx_eob(&cpi->common.seg, segment_id, tx_size);
-  const TOKENVALUE *dct_value_tokens;
-
+  int16_t token;
+  EXTRABIT extra;
   int aoff, loff;
   txfrm_block_to_raster_xy(plane_bsize, tx_size, block, &aoff, &loff);
 
@@ -320,17 +313,6 @@
   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
 
   while (c < eob) {
     int v = 0;
@@ -349,14 +331,13 @@
       v = qcoeff[scan[c]];
     }
 
-    add_token(&t, coef_probs[band[c]][pt],
-              dct_value_tokens[v].extra,
-              (uint8_t)dct_value_tokens[v].token,
-              (uint8_t)skip_eob,
-              counts[band[c]][pt]);
+    vp9_get_token_extra(v, &token, &extra);
+
+    add_token(&t, coef_probs[band[c]][pt], extra, (uint8_t)token,
+              (uint8_t)skip_eob, counts[band[c]][pt]);
     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[token];
     ++c;
     pt = get_coef_context(nb, token_cache, c);
   }
--- a/vp9/encoder/vp9_tokenize.h
+++ b/vp9/encoder/vp9_tokenize.h
@@ -24,24 +24,23 @@
 
 #define EOSB_TOKEN 127     // Not signalled, encoder only
 
-typedef struct {
-  int16_t token;
 #if CONFIG_VP9_HIGHBITDEPTH
-  int32_t extra;
+  typedef int32_t EXTRABIT;
 #else
-  int16_t extra;
+  typedef int16_t EXTRABIT;
 #endif
+
+
+typedef struct {
+  int16_t token;
+  EXTRABIT extra;
 } TOKENVALUE;
 
 typedef struct {
   const vp9_prob *context_tree;
-#if CONFIG_VP9_HIGHBITDEPTH
-  int32_t extra;
-#else
-  int16_t         extra;
-#endif
-  uint8_t         token;
-  uint8_t         skip_eob_node;
+  EXTRABIT extra;
+  uint8_t token;
+  uint8_t skip_eob_node;
 } TOKENEXTRA;
 
 extern const vp9_tree_index vp9_coef_tree[];
@@ -63,6 +62,7 @@
  *  fields are not.
  */
 extern const TOKENVALUE *vp9_dct_value_tokens_ptr;
+extern const TOKENVALUE *vp9_dct_cat_lt_10_value_tokens;
 #if CONFIG_VP9_HIGHBITDEPTH
 extern const int16_t *vp9_dct_value_cost_high10_ptr;
 extern const TOKENVALUE *vp9_dct_value_tokens_high10_ptr;
@@ -69,6 +69,25 @@
 extern const int16_t *vp9_dct_value_cost_high12_ptr;
 extern const TOKENVALUE *vp9_dct_value_tokens_high12_ptr;
 #endif  // CONFIG_VP9_HIGHBITDEPTH
+
+static INLINE void vp9_get_token_extra(int v, int16_t *token, EXTRABIT *extra) {
+  if (v >= CAT6_MIN_VAL || v <= -CAT6_MIN_VAL) {
+    *token = CATEGORY6_TOKEN;
+    if (v >= CAT6_MIN_VAL)
+      *extra = 2 * v - 2 * CAT6_MIN_VAL;
+    else
+      *extra = -2 * v - 2 * CAT6_MIN_VAL + 1;
+    return;
+  }
+  *token = vp9_dct_cat_lt_10_value_tokens[v].token;
+  *extra = vp9_dct_cat_lt_10_value_tokens[v].extra;
+}
+static INLINE int16_t vp9_get_token(int v) {
+  if (v >= CAT6_MIN_VAL || v <= -CAT6_MIN_VAL)
+    return 10;
+  return vp9_dct_cat_lt_10_value_tokens[v].token;
+}
+
 
 #ifdef __cplusplus
 }  // extern "C"