Add functions to read from/write to bitstream values with known max value

Bug: webrtc:10342
Change-Id: I701b09de574eb463daaf8d2c19008ac3452879eb
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/144033
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Philip Eliasson <philipel@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28465}
diff --git a/rtc_base/bit_buffer.cc b/rtc_base/bit_buffer.cc
index 59b71fc..a6dc1c7 100644
--- a/rtc_base/bit_buffer.cc
+++ b/rtc_base/bit_buffer.cc
@@ -159,6 +159,29 @@
   return true;
 }
 
+bool BitBuffer::ReadNonSymmetric(uint32_t* val, uint32_t num_values) {
+  RTC_DCHECK_GT(num_values, 0);
+  RTC_DCHECK_LE(num_values, uint32_t{1} << 31);
+  size_t count_bits = CountBits(num_values);
+  uint32_t num_min_bits_values = (uint32_t{1} << count_bits) - num_values;
+
+  if (!ReadBits(val, count_bits - 1)) {
+    return false;
+  }
+
+  if (*val < num_min_bits_values) {
+    return true;
+  }
+
+  uint32_t extra_bit;
+  if (!ReadBits(&extra_bit, /*bit_count=*/1)) {
+    return false;
+  }
+
+  *val = (*val << 1) + extra_bit - num_min_bits_values;
+  return true;
+}
+
 bool BitBuffer::ReadExponentialGolomb(uint32_t* val) {
   if (!val) {
     return false;
@@ -282,6 +305,27 @@
   return ConsumeBits(total_bits);
 }
 
+bool BitBufferWriter::WriteNonSymmetric(uint32_t val, uint32_t num_values) {
+  RTC_DCHECK_LT(val, num_values);
+  RTC_DCHECK_LE(num_values, uint32_t{1} << 31);
+  size_t count_bits = CountBits(num_values);
+  uint32_t num_min_bits_values = (uint32_t{1} << count_bits) - num_values;
+
+  return val < num_min_bits_values
+             ? WriteBits(val, count_bits - 1)
+             : WriteBits(val + num_min_bits_values, count_bits);
+}
+
+size_t BitBufferWriter::SizeNonSymmetricBits(uint32_t val,
+                                             uint32_t num_values) {
+  RTC_DCHECK_LT(val, num_values);
+  RTC_DCHECK_LE(num_values, uint32_t{1} << 31);
+  size_t count_bits = CountBits(num_values);
+  uint32_t num_min_bits_values = (uint32_t{1} << count_bits) - num_values;
+
+  return val < num_min_bits_values ? (count_bits - 1) : count_bits;
+}
+
 bool BitBufferWriter::WriteExponentialGolomb(uint32_t val) {
   // We don't support reading UINT32_MAX, because it doesn't fit in a uint32_t
   // when encoded, so don't support writing it either.