Change ParseUncompressedVp9Header implementation to use BitstreamReader

Bug: None
Change-Id: I91010b0102622fd8154f8ba941e61298b0584eae
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/230802
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#34899}
diff --git a/modules/video_coding/BUILD.gn b/modules/video_coding/BUILD.gn
index b6496b2..fa50637 100644
--- a/modules/video_coding/BUILD.gn
+++ b/modules/video_coding/BUILD.gn
@@ -355,6 +355,7 @@
     "../../api/video_codecs:video_codecs_api",
     "../../common_video",
     "../../modules/rtp_rtcp",
+    "../../rtc_base:bitstream_reader",
     "../../rtc_base:checks",
     "../../rtc_base:rtc_base_approved",
     "../../rtc_base:rtc_numerics",
@@ -374,6 +375,7 @@
     "../rtp_rtcp:rtp_rtcp_format",
   ]
   absl_deps = [
+    "//third_party/abseil-cpp/absl/numeric:bits",
     "//third_party/abseil-cpp/absl/strings:strings",
     "//third_party/abseil-cpp/absl/types:optional",
   ]
diff --git a/modules/video_coding/utility/vp9_uncompressed_header_parser.cc b/modules/video_coding/utility/vp9_uncompressed_header_parser.cc
index b065069..d8f24be 100644
--- a/modules/video_coding/utility/vp9_uncompressed_header_parser.cc
+++ b/modules/video_coding/utility/vp9_uncompressed_header_parser.cc
@@ -9,30 +9,13 @@
  */
 #include "modules/video_coding/utility/vp9_uncompressed_header_parser.h"
 
+#include "absl/numeric/bits.h"
 #include "absl/strings/string_view.h"
-#include "rtc_base/bit_buffer.h"
+#include "rtc_base/bitstream_reader.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/strings/string_builder.h"
 
 namespace webrtc {
-
-// Evaluates x and returns false if false.
-#define RETURN_IF_FALSE(x) \
-  if (!(x)) {              \
-    return false;          \
-  }
-
-// Evaluates x, which is intended to return an optional. If result is nullopt,
-// returns false. Else, calls fun() with the dereferenced optional as parameter.
-#define READ_OR_RETURN(x, fun)     \
-  do {                             \
-    if (auto optional_val = (x)) { \
-      fun(*optional_val);          \
-    } else {                       \
-      return false;                \
-    }                              \
-  } while (false)
-
 namespace {
 const size_t kVp9NumRefsPerFrame = 3;
 const size_t kVp9MaxRefLFDeltas = 4;
@@ -40,169 +23,32 @@
 const size_t kVp9MinTileWidthB64 = 4;
 const size_t kVp9MaxTileWidthB64 = 64;
 
-class BitstreamReader {
- public:
-  explicit BitstreamReader(rtc::BitBuffer* buffer) : buffer_(buffer) {}
-
-  // Reads on bit from the input stream and:
-  // * returns false if bit cannot be read
-  // * calls f_true() if bit is true, returns return value of that function
-  // * calls f_else() if bit is false, returns return value of that function
-  bool IfNextBoolean(
-      std::function<bool()> f_true,
-      std::function<bool()> f_false = [] { return true; }) {
-    uint32_t val;
-    if (!buffer_->ReadBits(1, val)) {
-      return false;
-    }
-    if (val != 0) {
-      return f_true();
-    }
-    return f_false();
-  }
-
-  absl::optional<bool> ReadBoolean() {
-    uint32_t val;
-    if (!buffer_->ReadBits(1, val)) {
-      return {};
-    }
-    return {val != 0};
-  }
-
-  // Reads a bit from the input stream and returns:
-  // * false if bit cannot be read
-  // * true if bit matches expected_val
-  // * false if bit does not match expected_val - in which case `error_msg` is
-  //   logged as warning, if provided.
-  bool VerifyNextBooleanIs(bool expected_val, absl::string_view error_msg) {
-    uint32_t val;
-    if (!buffer_->ReadBits(1, val)) {
-      return false;
-    }
-    if ((val != 0) != expected_val) {
-      if (!error_msg.empty()) {
-        RTC_LOG(LS_WARNING) << error_msg;
-      }
-      return false;
-    }
-    return true;
-  }
-
-  // Reads `bits` bits from the bitstream and interprets them as an unsigned
-  // integer that gets cast to the type T before returning.
-  // Returns nullopt if all bits cannot be read.
-  // If number of bits matches size of data type, the bits parameter may be
-  // omitted. Ex:
-  //  ReadUnsigned<uint8_t>(2);  // Returns uint8_t with 2 LSB populated.
-  //  ReadUnsigned<uint8_t>();   // Returns uint8_t with all 8 bits populated.
-  template <typename T>
-  absl::optional<T> ReadUnsigned(int bits = sizeof(T) * 8) {
-    RTC_DCHECK_LE(bits, 32);
-    RTC_DCHECK_LE(bits, sizeof(T) * 8);
-    uint32_t val;
-    if (!buffer_->ReadBits(bits, val)) {
-      return {};
-    }
-    return (static_cast<T>(val));
-  }
-
-  // Helper method that reads `num_bits` from the bitstream, returns:
-  // * false if bits cannot be read.
-  // * true if `expected_val` matches the read bits
-  // * false if `expected_val` does not match the read bits, and logs
-  //   `error_msg` as a warning (if provided).
-  bool VerifyNextUnsignedIs(int num_bits,
-                            uint32_t expected_val,
-                            absl::string_view error_msg) {
-    uint32_t val;
-    if (!buffer_->ReadBits(num_bits, val)) {
-      return false;
-    }
-    if (val != expected_val) {
-      if (!error_msg.empty()) {
-        RTC_LOG(LS_WARNING) << error_msg;
-      }
-      return false;
-    }
-    return true;
-  }
-
-  // Basically the same as ReadUnsigned() - but for signed integers.
-  // Here `bits` indicates the size of the value - number of bits read from the
-  // bit buffer is one higher (the sign bit). This is made to matche the spec in
-  // which eg s(4) = f(1) sign-bit, plus an f(4).
-  template <typename T>
-  absl::optional<T> ReadSigned(int bits = sizeof(T) * 8) {
-    uint32_t sign;
-    if (!buffer_->ReadBits(1, sign)) {
-      return {};
-    }
-    uint32_t val;
-    if (!buffer_->ReadBits(bits, val)) {
-      return {};
-    }
-    int64_t sign_val = val;
-    if (sign != 0) {
-      sign_val = -sign_val;
-    }
-    return {static_cast<T>(sign_val)};
-  }
-
-  // Reads `bits` from the bitstream, disregarding their value.
-  // Returns true if full number of bits were read, false otherwise.
-  bool ConsumeBits(int bits) { return buffer_->ConsumeBits(bits); }
-
-  void GetPosition(size_t* out_byte_offset, size_t* out_bit_offset) const {
-    buffer_->GetCurrentOffset(out_byte_offset, out_bit_offset);
-  }
-
- private:
-  rtc::BitBuffer* buffer_;
-};
-
-bool Vp9ReadColorConfig(BitstreamReader* br,
+void Vp9ReadColorConfig(BitstreamReader& br,
                         Vp9UncompressedHeader* frame_info) {
   if (frame_info->profile == 2 || frame_info->profile == 3) {
-    READ_OR_RETURN(br->ReadBoolean(), [frame_info](bool ten_or_twelve_bits) {
-      frame_info->bit_detph =
-          ten_or_twelve_bits ? Vp9BitDept::k12Bit : Vp9BitDept::k10Bit;
-    });
+    frame_info->bit_detph =
+        br.Read<bool>() ? Vp9BitDept::k12Bit : Vp9BitDept::k10Bit;
   } else {
     frame_info->bit_detph = Vp9BitDept::k8Bit;
   }
 
-  READ_OR_RETURN(
-      br->ReadUnsigned<uint8_t>(3), [frame_info](uint8_t color_space) {
-        frame_info->color_space = static_cast<Vp9ColorSpace>(color_space);
-      });
+  frame_info->color_space = static_cast<Vp9ColorSpace>(br.ReadBits(3));
 
   if (frame_info->color_space != Vp9ColorSpace::CS_RGB) {
-    READ_OR_RETURN(br->ReadBoolean(), [frame_info](bool color_range) {
-      frame_info->color_range =
-          color_range ? Vp9ColorRange::kFull : Vp9ColorRange::kStudio;
-    });
+    frame_info->color_range =
+        br.Read<bool>() ? Vp9ColorRange::kFull : Vp9ColorRange::kStudio;
 
     if (frame_info->profile == 1 || frame_info->profile == 3) {
-      READ_OR_RETURN(br->ReadUnsigned<uint8_t>(2),
-                     [frame_info](uint8_t subsampling) {
-                       switch (subsampling) {
-                         case 0b00:
-                           frame_info->sub_sampling = Vp9YuvSubsampling::k444;
-                           break;
-                         case 0b01:
-                           frame_info->sub_sampling = Vp9YuvSubsampling::k440;
-                           break;
-                         case 0b10:
-                           frame_info->sub_sampling = Vp9YuvSubsampling::k422;
-                           break;
-                         case 0b11:
-                           frame_info->sub_sampling = Vp9YuvSubsampling::k420;
-                           break;
-                       }
-                     });
+      static constexpr Vp9YuvSubsampling kSubSamplings[] = {
+          Vp9YuvSubsampling::k444, Vp9YuvSubsampling::k440,
+          Vp9YuvSubsampling::k422, Vp9YuvSubsampling::k420};
+      frame_info->sub_sampling = kSubSamplings[br.ReadBits(2)];
 
-      RETURN_IF_FALSE(br->VerifyNextBooleanIs(
-          0, "Failed to parse header. Reserved bit set."));
+      if (br.Read<bool>()) {
+        RTC_LOG(LS_WARNING) << "Failed to parse header. Reserved bit set.";
+        br.Invalidate();
+        return;
+      }
     } else {
       // Profile 0 or 2.
       frame_info->sub_sampling = Vp9YuvSubsampling::k420;
@@ -212,206 +58,158 @@
     frame_info->color_range = Vp9ColorRange::kFull;
     if (frame_info->profile == 1 || frame_info->profile == 3) {
       frame_info->sub_sampling = Vp9YuvSubsampling::k444;
-      RETURN_IF_FALSE(br->VerifyNextBooleanIs(
-          0, "Failed to parse header. Reserved bit set."));
+      if (br.Read<bool>()) {
+        RTC_LOG(LS_WARNING) << "Failed to parse header. Reserved bit set.";
+        br.Invalidate();
+      }
     } else {
       RTC_LOG(LS_WARNING) << "Failed to parse header. 4:4:4 color not supported"
                              " in profile 0 or 2.";
-      return false;
+      br.Invalidate();
     }
   }
-
-  return true;
 }
 
-bool ReadRefreshFrameFlags(BitstreamReader* br,
+void ReadRefreshFrameFlags(BitstreamReader& br,
                            Vp9UncompressedHeader* frame_info) {
   // Refresh frame flags.
-  READ_OR_RETURN(br->ReadUnsigned<uint8_t>(), [frame_info](uint8_t flags) {
-    for (int i = 0; i < 8; ++i) {
-      frame_info->updated_buffers.set(i, (flags & (0x01 << (7 - i))) != 0);
-    }
-  });
-  return true;
+  uint8_t flags = br.Read<uint8_t>();
+  for (int i = 0; i < 8; ++i) {
+    frame_info->updated_buffers.set(i, (flags & (0x01 << (7 - i))) != 0);
+  }
 }
 
-bool Vp9ReadFrameSize(BitstreamReader* br, Vp9UncompressedHeader* frame_info) {
+void Vp9ReadFrameSize(BitstreamReader& br, Vp9UncompressedHeader* frame_info) {
   // 16 bits: frame (width|height) - 1.
-  READ_OR_RETURN(br->ReadUnsigned<uint16_t>(), [frame_info](uint16_t width) {
-    frame_info->frame_width = width + 1;
-  });
-  READ_OR_RETURN(br->ReadUnsigned<uint16_t>(), [frame_info](uint16_t height) {
-    frame_info->frame_height = height + 1;
-  });
-  return true;
+  frame_info->frame_width = br.Read<uint16_t>() + 1;
+  frame_info->frame_height = br.Read<uint16_t>() + 1;
 }
 
-bool Vp9ReadRenderSize(BitstreamReader* br, Vp9UncompressedHeader* frame_info) {
+void Vp9ReadRenderSize(size_t total_buffer_size_bits,
+                       BitstreamReader& br,
+                       Vp9UncompressedHeader* frame_info) {
   // render_and_frame_size_different
-  return br->IfNextBoolean(
-      [&] {
-        auto& pos = frame_info->render_size_position.emplace();
-        br->GetPosition(&pos.byte_offset, &pos.bit_offset);
-        // 16 bits: render (width|height) - 1.
-        READ_OR_RETURN(br->ReadUnsigned<uint16_t>(),
-                       [frame_info](uint16_t width) {
-                         frame_info->render_width = width + 1;
-                       });
-        READ_OR_RETURN(br->ReadUnsigned<uint16_t>(),
-                       [frame_info](uint16_t height) {
-                         frame_info->render_height = height + 1;
-                       });
-        return true;
-      },
-      /*else*/
-      [&] {
-        frame_info->render_height = frame_info->frame_height;
-        frame_info->render_width = frame_info->frame_width;
-        return true;
-      });
+  if (br.Read<bool>()) {
+    frame_info->render_size_offset_bits =
+        total_buffer_size_bits - br.RemainingBitCount();
+    // 16 bits: render (width|height) - 1.
+    frame_info->render_width = br.Read<uint16_t>() + 1;
+    frame_info->render_height = br.Read<uint16_t>() + 1;
+  } else {
+    frame_info->render_height = frame_info->frame_height;
+    frame_info->render_width = frame_info->frame_width;
+  }
 }
 
-bool Vp9ReadFrameSizeFromRefs(BitstreamReader* br,
+void Vp9ReadFrameSizeFromRefs(BitstreamReader& br,
                               Vp9UncompressedHeader* frame_info) {
-  bool found_ref = false;
-  for (size_t i = 0; !found_ref && i < kVp9NumRefsPerFrame; i++) {
+  for (size_t i = 0; i < kVp9NumRefsPerFrame; i++) {
     // Size in refs.
-    br->IfNextBoolean([&] {
+    if (br.Read<bool>()) {
       frame_info->infer_size_from_reference = frame_info->reference_buffers[i];
-      found_ref = true;
-      return true;
-    });
-  }
-
-  if (!found_ref) {
-    if (!Vp9ReadFrameSize(br, frame_info)) {
-      return false;
+      return;
     }
   }
-  return Vp9ReadRenderSize(br, frame_info);
+
+  Vp9ReadFrameSize(br, frame_info);
 }
 
-bool Vp9ReadLoopfilter(BitstreamReader* br) {
+void Vp9ReadLoopfilter(BitstreamReader& br) {
   // 6 bits: filter level.
   // 3 bits: sharpness level.
-  RETURN_IF_FALSE(br->ConsumeBits(9));
+  br.ConsumeBits(9);
 
-  return br->IfNextBoolean([&] {    // if mode_ref_delta_enabled
-    return br->IfNextBoolean([&] {  // if mode_ref_delta_update
-      for (size_t i = 0; i < kVp9MaxRefLFDeltas; i++) {
-        RETURN_IF_FALSE(br->IfNextBoolean([&] { return br->ConsumeBits(7); }));
-      }
-      for (size_t i = 0; i < kVp9MaxModeLFDeltas; i++) {
-        RETURN_IF_FALSE(br->IfNextBoolean([&] { return br->ConsumeBits(7); }));
-      }
-      return true;
-    });
-  });
+  if (!br.Read<bool>()) {  // mode_ref_delta_enabled
+    return;
+  }
+  if (!br.Read<bool>()) {  // mode_ref_delta_update
+    return;
+  }
+
+  for (size_t i = 0; i < kVp9MaxRefLFDeltas; i++) {
+    if (br.Read<bool>()) {  // update_ref_delta
+      br.ConsumeBits(7);
+    }
+  }
+  for (size_t i = 0; i < kVp9MaxModeLFDeltas; i++) {
+    if (br.Read<bool>()) {  // update_mode_delta
+      br.ConsumeBits(7);
+    }
+  }
 }
 
-bool Vp9ReadQp(BitstreamReader* br, Vp9UncompressedHeader* frame_info) {
-  READ_OR_RETURN(br->ReadUnsigned<uint8_t>(),
-                 [frame_info](uint8_t qp) { frame_info->base_qp = qp; });
+void Vp9ReadQp(BitstreamReader& br, Vp9UncompressedHeader* frame_info) {
+  frame_info->base_qp = br.Read<uint8_t>();
 
   // yuv offsets
   frame_info->is_lossless = frame_info->base_qp == 0;
   for (int i = 0; i < 3; ++i) {
-    RETURN_IF_FALSE(br->IfNextBoolean([&] {  // if delta_coded
-      READ_OR_RETURN(br->ReadUnsigned<int>(4), [&](int delta) {
-        if (delta != 0) {
-          frame_info->is_lossless = false;
-        }
-      });
-      return true;
-    }));
+    if (br.Read<bool>()) {  // if delta_coded
+      if (br.ReadBits(4) != 0) {
+        frame_info->is_lossless = false;
+      }
+    }
   }
-  return true;
 }
 
-bool Vp9ReadSegmentationParams(BitstreamReader* br,
+void Vp9ReadSegmentationParams(BitstreamReader& br,
                                Vp9UncompressedHeader* frame_info) {
   constexpr int kSegmentationFeatureBits[kVp9SegLvlMax] = {8, 6, 2, 0};
   constexpr bool kSegmentationFeatureSigned[kVp9SegLvlMax] = {1, 1, 0, 0};
 
-  return br->IfNextBoolean([&] {  // segmentation_enabled
-    frame_info->segmentation_enabled = true;
-    RETURN_IF_FALSE(br->IfNextBoolean([&] {  // update_map
-      frame_info->segmentation_tree_probs.emplace();
-      for (int i = 0; i < 7; ++i) {
-        RETURN_IF_FALSE(br->IfNextBoolean(
-            [&] {
-              READ_OR_RETURN(br->ReadUnsigned<uint8_t>(), [&](uint8_t prob) {
-                (*frame_info->segmentation_tree_probs)[i] = prob;
-              });
-              return true;
-            },
-            [&] {
-              (*frame_info->segmentation_tree_probs)[i] = 255;
-              return true;
-            }));
+  frame_info->segmentation_enabled = br.Read<bool>();
+  if (!frame_info->segmentation_enabled) {
+    return;
+  }
+
+  if (br.Read<bool>()) {  // update_map
+    frame_info->segmentation_tree_probs.emplace();
+    for (int i = 0; i < 7; ++i) {
+      if (br.Read<bool>()) {
+        (*frame_info->segmentation_tree_probs)[i] = br.Read<uint8_t>();
+      } else {
+        (*frame_info->segmentation_tree_probs)[i] = 255;
       }
+    }
 
-      // temporal_update
-      frame_info->segmentation_pred_prob.emplace();
-      return br->IfNextBoolean(
-          [&] {
-            for (int i = 0; i < 3; ++i) {
-              RETURN_IF_FALSE(br->IfNextBoolean(
-                  [&] {
-                    READ_OR_RETURN(
-                        br->ReadUnsigned<uint8_t>(), [&](uint8_t prob) {
-                          (*frame_info->segmentation_pred_prob)[i] = prob;
-                        });
-                    return true;
-                  },
-                  [&] {
-                    (*frame_info->segmentation_pred_prob)[i] = 255;
-                    return true;
-                  }));
-            }
-            return true;
-          },
-          [&] {
-            frame_info->segmentation_pred_prob->fill(255);
-            return true;
-          });
-    }));
-
-    return br->IfNextBoolean([&] {  // segmentation_update_data
-      RETURN_IF_FALSE(br->IfNextBoolean([&] {
-        frame_info->segmentation_is_delta = true;
-        return true;
-      }));
-
-      for (size_t i = 0; i < kVp9MaxSegments; ++i) {
-        for (size_t j = 0; j < kVp9SegLvlMax; ++j) {
-          RETURN_IF_FALSE(br->IfNextBoolean([&] {  // feature_enabled
-            if (kSegmentationFeatureBits[j] == 0) {
-              // No feature bits used and no sign, just mark it and return.
-              frame_info->segmentation_features[i][j] = 1;
-              return true;
-            }
-            READ_OR_RETURN(
-                br->ReadUnsigned<uint8_t>(kSegmentationFeatureBits[j]),
-                [&](uint8_t feature_value) {
-                  frame_info->segmentation_features[i][j] = feature_value;
-                });
-            if (kSegmentationFeatureSigned[j]) {
-              RETURN_IF_FALSE(br->IfNextBoolean([&] {
-                (*frame_info->segmentation_features[i][j]) *= -1;
-                return true;
-              }));
-            }
-            return true;
-          }));
+    // temporal_update
+    frame_info->segmentation_pred_prob.emplace();
+    if (br.Read<bool>()) {
+      for (int i = 0; i < 3; ++i) {
+        if (br.Read<bool>()) {
+          (*frame_info->segmentation_pred_prob)[i] = br.Read<uint8_t>();
+        } else {
+          (*frame_info->segmentation_pred_prob)[i] = 255;
         }
       }
-      return true;
-    });
-  });
+    } else {
+      frame_info->segmentation_pred_prob->fill(255);
+    }
+  }
+
+  if (br.Read<bool>()) {  // segmentation_update_data
+    frame_info->segmentation_is_delta = br.Read<bool>();
+    for (size_t i = 0; i < kVp9MaxSegments; ++i) {
+      for (size_t j = 0; j < kVp9SegLvlMax; ++j) {
+        if (!br.Read<bool>()) {  // feature_enabled
+          continue;
+        }
+        if (kSegmentationFeatureBits[j] == 0) {
+          // No feature bits used and no sign, just mark it and return.
+          frame_info->segmentation_features[i][j] = 1;
+          continue;
+        }
+        frame_info->segmentation_features[i][j] =
+            br.ReadBits(kSegmentationFeatureBits[j]);
+        if (kSegmentationFeatureSigned[j] && br.Read<bool>()) {
+          (*frame_info->segmentation_features[i][j]) *= -1;
+        }
+      }
+    }
+  }
 }
 
-bool Vp9ReadTileInfo(BitstreamReader* br, Vp9UncompressedHeader* frame_info) {
+void Vp9ReadTileInfo(BitstreamReader& br, Vp9UncompressedHeader* frame_info) {
   size_t mi_cols = (frame_info->frame_width + 7) >> 3;
   size_t sb64_cols = (mi_cols + 7) >> 3;
 
@@ -427,27 +225,20 @@
   --max_log2;
 
   frame_info->tile_cols_log2 = min_log2;
-  bool done = false;
-  while (!done && frame_info->tile_cols_log2 < max_log2) {
-    RETURN_IF_FALSE(br->IfNextBoolean(
-        [&] {
-          ++frame_info->tile_cols_log2;
-          return true;
-        },
-        [&] {
-          done = true;
-          return true;
-        }));
+  while (frame_info->tile_cols_log2 < max_log2) {
+    if (br.Read<bool>()) {
+      ++frame_info->tile_cols_log2;
+    } else {
+      break;
+    }
   }
   frame_info->tile_rows_log2 = 0;
-  RETURN_IF_FALSE(br->IfNextBoolean([&] {
+  if (br.Read<bool>()) {
     ++frame_info->tile_rows_log2;
-    return br->IfNextBoolean([&] {
+    if (br.Read<bool>()) {
       ++frame_info->tile_rows_log2;
-      return true;
-    });
-  }));
-  return true;
+    }
+  }
 }
 
 const Vp9InterpolationFilter kLiteralToType[4] = {
@@ -586,60 +377,49 @@
   return oss.str();
 }
 
-bool Parse(rtc::ArrayView<const uint8_t> buf,
+void Parse(BitstreamReader& br,
            Vp9UncompressedHeader* frame_info,
            bool qp_only) {
-  rtc::BitBuffer bit_buffer(buf.data(), buf.size());
-  BitstreamReader br(&bit_buffer);
+  const size_t total_buffer_size_bits = br.RemainingBitCount();
 
   // Frame marker.
-  RETURN_IF_FALSE(br.VerifyNextUnsignedIs(
-      2, 0x2, "Failed to parse header. Frame marker should be 2."));
+  if (br.ReadBits(2) != 0b10) {
+    RTC_LOG(LS_WARNING) << "Failed to parse header. Frame marker should be 2.";
+    br.Invalidate();
+    return;
+  }
 
   // Profile has low bit first.
-  READ_OR_RETURN(br.ReadBoolean(),
-                 [frame_info](bool low) { frame_info->profile = int{low}; });
-  READ_OR_RETURN(br.ReadBoolean(), [frame_info](bool high) {
-    frame_info->profile |= int{high} << 1;
-  });
-  if (frame_info->profile > 2) {
-    RETURN_IF_FALSE(br.VerifyNextBooleanIs(
-        false, "Failed to get QP. Unsupported bitstream profile."));
+  frame_info->profile = br.ReadBit();
+  frame_info->profile |= br.ReadBit() << 1;
+  if (frame_info->profile > 2 && br.Read<bool>()) {
+    RTC_LOG(LS_WARNING)
+        << "Failed to parse header. Unsupported bitstream profile.";
+    br.Invalidate();
+    return;
   }
 
   // Show existing frame.
-  RETURN_IF_FALSE(br.IfNextBoolean([&] {
-    READ_OR_RETURN(br.ReadUnsigned<uint8_t>(3),
-                   [frame_info](uint8_t frame_idx) {
-                     frame_info->show_existing_frame = frame_idx;
-                   });
-    return true;
-  }));
-  if (frame_info->show_existing_frame.has_value()) {
-    return true;
+  if (br.Read<bool>()) {
+    frame_info->show_existing_frame = br.ReadBits(3);
+    return;
   }
 
-  READ_OR_RETURN(br.ReadBoolean(), [frame_info](bool frame_type) {
-    // Frame type: KEY_FRAME(0), INTER_FRAME(1).
-    frame_info->is_keyframe = frame_type == 0;
-  });
-  READ_OR_RETURN(br.ReadBoolean(), [frame_info](bool show_frame) {
-    frame_info->show_frame = show_frame;
-  });
-  READ_OR_RETURN(br.ReadBoolean(), [frame_info](bool error_resilient) {
-    frame_info->error_resilient = error_resilient;
-  });
+  // Frame type: KEY_FRAME(0), INTER_FRAME(1).
+  frame_info->is_keyframe = !br.Read<bool>();
+  frame_info->show_frame = br.Read<bool>();
+  frame_info->error_resilient = br.Read<bool>();
 
   if (frame_info->is_keyframe) {
-    RETURN_IF_FALSE(br.VerifyNextUnsignedIs(
-        24, 0x498342, "Failed to get QP. Invalid sync code."));
+    if (br.ReadBits(24) != 0x498342) {
+      RTC_LOG(LS_WARNING) << "Failed to parse header. Invalid sync code.";
+      br.Invalidate();
+      return;
+    }
 
-    if (!Vp9ReadColorConfig(&br, frame_info))
-      return false;
-    if (!Vp9ReadFrameSize(&br, frame_info))
-      return false;
-    if (!Vp9ReadRenderSize(&br, frame_info))
-      return false;
+    Vp9ReadColorConfig(br, frame_info);
+    Vp9ReadFrameSize(br, frame_info);
+    Vp9ReadRenderSize(total_buffer_size_bits, br, frame_info);
 
     // Key-frames implicitly update all buffers.
     frame_info->updated_buffers.set();
@@ -647,108 +427,86 @@
     // Non-keyframe.
     bool is_intra_only = false;
     if (!frame_info->show_frame) {
-      READ_OR_RETURN(br.ReadBoolean(),
-                     [&](bool intra_only) { is_intra_only = intra_only; });
+      is_intra_only = br.Read<bool>();
     }
     if (!frame_info->error_resilient) {
-      RETURN_IF_FALSE(br.ConsumeBits(2));  // Reset frame context.
+      br.ConsumeBits(2);  // Reset frame context.
     }
 
     if (is_intra_only) {
-      RETURN_IF_FALSE(br.VerifyNextUnsignedIs(
-          24, 0x498342, "Failed to get QP. Invalid sync code."));
+      if (br.ReadBits(24) != 0x498342) {
+        RTC_LOG(LS_WARNING) << "Failed to parse header. Invalid sync code.";
+        br.Invalidate();
+        return;
+      }
 
       if (frame_info->profile > 0) {
-        if (!Vp9ReadColorConfig(&br, frame_info))
-          return false;
+        Vp9ReadColorConfig(br, frame_info);
       } else {
         frame_info->color_space = Vp9ColorSpace::CS_BT_601;
         frame_info->sub_sampling = Vp9YuvSubsampling::k420;
         frame_info->bit_detph = Vp9BitDept::k8Bit;
       }
       frame_info->reference_buffers.fill(-1);
-      RETURN_IF_FALSE(ReadRefreshFrameFlags(&br, frame_info));
-      RETURN_IF_FALSE(Vp9ReadFrameSize(&br, frame_info));
-      RETURN_IF_FALSE(Vp9ReadRenderSize(&br, frame_info));
+      ReadRefreshFrameFlags(br, frame_info);
+      Vp9ReadFrameSize(br, frame_info);
+      Vp9ReadRenderSize(total_buffer_size_bits, br, frame_info);
     } else {
-      RETURN_IF_FALSE(ReadRefreshFrameFlags(&br, frame_info));
+      ReadRefreshFrameFlags(br, frame_info);
 
       frame_info->reference_buffers_sign_bias[0] = false;
       for (size_t i = 0; i < kVp9NumRefsPerFrame; i++) {
-        READ_OR_RETURN(br.ReadUnsigned<uint8_t>(3), [&](uint8_t idx) {
-          frame_info->reference_buffers[i] = idx;
-        });
-        READ_OR_RETURN(br.ReadBoolean(), [&](bool sign_bias) {
-          frame_info
-              ->reference_buffers_sign_bias[Vp9ReferenceFrame::kLast + i] =
-              sign_bias;
-        });
+        frame_info->reference_buffers[i] = br.ReadBits(3);
+        frame_info->reference_buffers_sign_bias[Vp9ReferenceFrame::kLast + i] =
+            br.Read<bool>();
       }
 
-      if (!Vp9ReadFrameSizeFromRefs(&br, frame_info))
-        return false;
+      Vp9ReadFrameSizeFromRefs(br, frame_info);
+      Vp9ReadRenderSize(total_buffer_size_bits, br, frame_info);
 
-      READ_OR_RETURN(br.ReadBoolean(), [&](bool allow_high_precision_mv) {
-        frame_info->allow_high_precision_mv = allow_high_precision_mv;
-      });
+      frame_info->allow_high_precision_mv = br.Read<bool>();
 
       // Interpolation filter.
-      RETURN_IF_FALSE(br.IfNextBoolean(
-          [frame_info] {
-            frame_info->interpolation_filter =
-                Vp9InterpolationFilter::kSwitchable;
-            return true;
-          },
-          [&] {
-            READ_OR_RETURN(
-                br.ReadUnsigned<uint8_t>(2), [frame_info](uint8_t filter) {
-                  frame_info->interpolation_filter = kLiteralToType[filter];
-                });
-            return true;
-          }));
+      if (br.Read<bool>()) {
+        frame_info->interpolation_filter = Vp9InterpolationFilter::kSwitchable;
+      } else {
+        frame_info->interpolation_filter = kLiteralToType[br.ReadBits(2)];
+      }
     }
   }
 
   if (!frame_info->error_resilient) {
     // 1 bit: Refresh frame context.
     // 1 bit: Frame parallel decoding mode.
-    RETURN_IF_FALSE(br.ConsumeBits(2));
+    br.ConsumeBits(2);
   }
 
   // Frame context index.
-  READ_OR_RETURN(br.ReadUnsigned<uint8_t>(2),
-                 [&](uint8_t idx) { frame_info->frame_context_idx = idx; });
+  frame_info->frame_context_idx = br.ReadBits(2);
 
-  if (!Vp9ReadLoopfilter(&br))
-    return false;
+  Vp9ReadLoopfilter(br);
 
   // Read base QP.
-  RETURN_IF_FALSE(Vp9ReadQp(&br, frame_info));
+  Vp9ReadQp(br, frame_info);
 
   if (qp_only) {
     // Not interested in the rest of the header, return early.
-    return true;
+    return;
   }
 
-  RETURN_IF_FALSE(Vp9ReadSegmentationParams(&br, frame_info));
-  RETURN_IF_FALSE(Vp9ReadTileInfo(&br, frame_info));
-  READ_OR_RETURN(br.ReadUnsigned<uint16_t>(), [frame_info](uint16_t size) {
-    frame_info->compressed_header_size = size;
-  });
-
-  // Trailing bits.
-  RETURN_IF_FALSE(br.ConsumeBits(bit_buffer.RemainingBitCount() % 8));
+  Vp9ReadSegmentationParams(br, frame_info);
+  Vp9ReadTileInfo(br, frame_info);
+  frame_info->compressed_header_size = br.Read<uint16_t>();
   frame_info->uncompressed_header_size =
-      buf.size() - (bit_buffer.RemainingBitCount() / 8);
-
-  return true;
+      (total_buffer_size_bits / 8) - (br.RemainingBitCount() / 8);
 }
 
 absl::optional<Vp9UncompressedHeader> ParseUncompressedVp9Header(
     rtc::ArrayView<const uint8_t> buf) {
+  BitstreamReader reader(buf);
   Vp9UncompressedHeader frame_info;
-  if (Parse(buf, &frame_info, /*qp_only=*/false) &&
-      frame_info.frame_width > 0) {
+  Parse(reader, &frame_info, /*qp_only=*/false);
+  if (reader.Ok() && frame_info.frame_width > 0) {
     return frame_info;
   }
   return absl::nullopt;
@@ -757,8 +515,10 @@
 namespace vp9 {
 
 bool GetQp(const uint8_t* buf, size_t length, int* qp) {
+  BitstreamReader reader(rtc::MakeArrayView(buf, length));
   Vp9UncompressedHeader frame_info;
-  if (!Parse(rtc::MakeArrayView(buf, length), &frame_info, /*qp_only=*/true)) {
+  Parse(reader, &frame_info, /*qp_only=*/true);
+  if (!reader.Ok()) {
     return false;
   }
   *qp = frame_info.base_qp;
diff --git a/modules/video_coding/utility/vp9_uncompressed_header_parser.h b/modules/video_coding/utility/vp9_uncompressed_header_parser.h
index 3e862bf..8d1b88c 100644
--- a/modules/video_coding/utility/vp9_uncompressed_header_parser.h
+++ b/modules/video_coding/utility/vp9_uncompressed_header_parser.h
@@ -105,11 +105,7 @@
   // Width/height of the tiles used (in units of 8x8 blocks).
   size_t tile_cols_log2 = 0;  // tile_cols = 1 << tile_cols_log2
   size_t tile_rows_log2 = 0;  // tile_rows = 1 << tile_rows_log2
-  struct BitstreamPosition {
-    size_t byte_offset = 0;
-    size_t bit_offset = 0;
-  };
-  absl::optional<BitstreamPosition> render_size_position;
+  absl::optional<size_t> render_size_offset_bits;
   Vp9InterpolationFilter interpolation_filter =
       Vp9InterpolationFilter::kEightTap;
   bool allow_high_precision_mv = false;
diff --git a/modules/video_coding/utility/vp9_uncompressed_header_parser_unittest.cc b/modules/video_coding/utility/vp9_uncompressed_header_parser_unittest.cc
index 913f43e..be0a303 100644
--- a/modules/video_coding/utility/vp9_uncompressed_header_parser_unittest.cc
+++ b/modules/video_coding/utility/vp9_uncompressed_header_parser_unittest.cc
@@ -55,11 +55,7 @@
   EXPECT_EQ(frame_info->updated_buffers, 0b10000000);
   EXPECT_EQ(frame_info->tile_cols_log2, 0u);
   EXPECT_EQ(frame_info->tile_rows_log2, 0u);
-  EXPECT_THAT(
-      frame_info->render_size_position,
-      Optional(AllOf(
-          Field(&Vp9UncompressedHeader::BitstreamPosition::byte_offset, 8u),
-          Field(&Vp9UncompressedHeader::BitstreamPosition::bit_offset, 0u))));
+  EXPECT_EQ(frame_info->render_size_offset_bits, 64u);
   EXPECT_EQ(frame_info->compressed_header_size, 23u);
   EXPECT_EQ(frame_info->uncompressed_header_size, 37u);