Clamp decoded feature data

Not all segment feature data elements are full-range powers of two, so
there are values that can be encoded that are invalid. Add a new function
to clamp values to the maximum allowed.

Change-Id: Ie47cb80ef2d54292e6b8db9f699c57214a915bc4
diff --git a/vp9/common/vp9_seg_common.c b/vp9/common/vp9_seg_common.c
index 6ac27e3..46a6ee4 100644
--- a/vp9/common/vp9_seg_common.c
+++ b/vp9/common/vp9_seg_common.c
@@ -8,11 +8,13 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#include <assert.h>
+#include "vp9/common/vp9_blockd.h"
 #include "vp9/common/vp9_seg_common.h"
 
 static const int segfeaturedata_signed[SEG_LVL_MAX] = { 1, 1, 0, 0, 0, 0 };
-static const int seg_feature_data_bits[SEG_LVL_MAX] =
-                 { QINDEX_BITS, 6, 4, 5, 8, 2 };
+static const int seg_feature_data_max[SEG_LVL_MAX] =
+                 { MAXQ, 63, 0xf, MB_MODE_COUNT - 1, 255, TX_SIZE_MAX - 1};
 
 // These functions provide access to new segment level features.
 // Eventually these function may be "optimized out" but for the moment,
@@ -45,8 +47,8 @@
   xd->segment_feature_mask[segment_id] &= ~(1 << feature_id);
 }
 
-int vp9_seg_feature_data_bits(SEG_LVL_FEATURES feature_id) {
-  return seg_feature_data_bits[feature_id];
+int vp9_seg_feature_data_max(SEG_LVL_FEATURES feature_id) {
+  return seg_feature_data_max[feature_id];
 }
 
 int vp9_is_segfeature_signed(SEG_LVL_FEATURES feature_id) {
@@ -63,6 +65,12 @@
                      int segment_id,
                      SEG_LVL_FEATURES feature_id,
                      int seg_data) {
+  assert(seg_data <= seg_feature_data_max[feature_id]);
+  if (seg_data < 0) {
+    assert(segfeaturedata_signed[feature_id]);
+    assert(-seg_data <= seg_feature_data_max[feature_id]);
+  }
+
   xd->segment_feature_data[segment_id][feature_id] = seg_data;
 }
 
diff --git a/vp9/common/vp9_seg_common.h b/vp9/common/vp9_seg_common.h
index fb0570c..20959a7 100644
--- a/vp9/common/vp9_seg_common.h
+++ b/vp9/common/vp9_seg_common.h
@@ -29,7 +29,7 @@
                             int segment_id,
                             SEG_LVL_FEATURES feature_id);
 
-int vp9_seg_feature_data_bits(SEG_LVL_FEATURES feature_id);
+int vp9_seg_feature_data_max(SEG_LVL_FEATURES feature_id);
 
 int vp9_is_segfeature_signed(SEG_LVL_FEATURES feature_id);
 
diff --git a/vp9/decoder/vp9_dboolhuff.c b/vp9/decoder/vp9_dboolhuff.c
index dc3878e..885ec0d 100644
--- a/vp9/decoder/vp9_dboolhuff.c
+++ b/vp9/decoder/vp9_dboolhuff.c
@@ -98,3 +98,15 @@
   }
   return word;
 }
+
+int vp9_decode_unsigned_max(BOOL_DECODER *br, int max) {
+  int data = 0, bit = 0, lmax = max;
+
+  while (lmax) {
+    data |= decode_bool(br, 128) << bit++;
+    lmax >>= 1;
+  }
+  if (data > max)
+    return max;
+  return data;
+}
diff --git a/vp9/decoder/vp9_dboolhuff.h b/vp9/decoder/vp9_dboolhuff.h
index d46d81b..6529170 100644
--- a/vp9/decoder/vp9_dboolhuff.h
+++ b/vp9/decoder/vp9_dboolhuff.h
@@ -150,4 +150,6 @@
   return 0;
 }
 
+extern int vp9_decode_unsigned_max(BOOL_DECODER *br, int max);
+
 #endif
diff --git a/vp9/decoder/vp9_decodframe.c b/vp9/decoder/vp9_decodframe.c
index c083323..8c237b1 100644
--- a/vp9/decoder/vp9_decodframe.c
+++ b/vp9/decoder/vp9_decodframe.c
@@ -1134,13 +1134,13 @@
             // Update the feature data and mask
             vp9_enable_segfeature(xd, i, j);
 
-            data = (signed char)vp9_read_literal(
-                     &header_bc, vp9_seg_feature_data_bits(j));
+            data = vp9_decode_unsigned_max(&header_bc,
+                                           vp9_seg_feature_data_max(j));
 
             // Is the segment data signed..
             if (vp9_is_segfeature_signed(j)) {
               if (vp9_read_bit(&header_bc))
-                data = - data;
+                data = -data;
             }
           } else
             data = 0;
diff --git a/vp9/encoder/vp9_bitstream.c b/vp9/encoder/vp9_bitstream.c
index ae8a7c6..73c1167 100644
--- a/vp9/encoder/vp9_bitstream.c
+++ b/vp9/encoder/vp9_bitstream.c
@@ -1911,19 +1911,19 @@
               // Encode the relevant feature data
               if (Data < 0) {
                 Data = - Data;
-                vp9_write_literal(&header_bc, Data,
-                                  vp9_seg_feature_data_bits(j));
+                vp9_encode_unsigned_max(&header_bc, Data,
+                                        vp9_seg_feature_data_max(j));
                 vp9_write_bit(&header_bc, 1);
               } else {
-                vp9_write_literal(&header_bc, Data,
-                                  vp9_seg_feature_data_bits(j));
+                vp9_encode_unsigned_max(&header_bc, Data,
+                                        vp9_seg_feature_data_max(j));
                 vp9_write_bit(&header_bc, 0);
               }
             }
             // Unsigned data element so no sign bit needed
             else
-              vp9_write_literal(&header_bc, Data,
-                                vp9_seg_feature_data_bits(j));
+              vp9_encode_unsigned_max(&header_bc, Data,
+                                      vp9_seg_feature_data_max(j));
           } else
             vp9_write_bit(&header_bc, 0);
         }
diff --git a/vp9/encoder/vp9_boolhuff.c b/vp9/encoder/vp9_boolhuff.c
index 7619dfa..2689ab6 100644
--- a/vp9/encoder/vp9_boolhuff.c
+++ b/vp9/encoder/vp9_boolhuff.c
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-
+#include <assert.h>
 #include "vp9_boolhuff.h"
 
 #if defined(SECTIONBITS_OUTPUT)
@@ -64,6 +64,15 @@
     encode_bool(br, (1 & (data >> bit)), 0x80);
 }
 
+void vp9_encode_unsigned_max(BOOL_CODER *br, int data, int max) {
+  assert(data <= max);
+  while (max) {
+    encode_bool(br, data & 1, 128);
+    data >>= 1;
+    max >>= 1;
+  }
+}
+
 int vp9_recenter_nonneg(int v, int m) {
   if (v > (m << 1)) return v;
   else if (v >= m) return ((v - m) << 1);
diff --git a/vp9/encoder/vp9_boolhuff.h b/vp9/encoder/vp9_boolhuff.h
index 2fad86b..1958a41 100644
--- a/vp9/encoder/vp9_boolhuff.h
+++ b/vp9/encoder/vp9_boolhuff.h
@@ -37,6 +37,7 @@
 extern void vp9_start_encode(BOOL_CODER *bc, unsigned char *buffer);
 
 extern void vp9_encode_value(BOOL_CODER *br, int data, int bits);
+extern void vp9_encode_unsigned_max(BOOL_CODER *br, int data, int max);
 extern void vp9_stop_encode(BOOL_CODER *bc);
 extern const unsigned int vp9_prob_cost[256];