Migrate VideoRtpDepacketizerVp9 implementation from BitBuffer to BitstreamReader

The new version is subjectivly cleaner
and objectively generates smaller binary size

Bug: None
Change-Id: I662596c41f30690f7e81a51804dd7feb263510c3
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/231130
Reviewed-by: Åsa Persson <asapersson@webrtc.org>
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#34935}
diff --git a/modules/rtp_rtcp/BUILD.gn b/modules/rtp_rtcp/BUILD.gn
index f9bc1ff..d3f2fe0 100644
--- a/modules/rtp_rtcp/BUILD.gn
+++ b/modules/rtp_rtcp/BUILD.gn
@@ -287,6 +287,7 @@
     "../../logging:rtc_event_audio",
     "../../logging:rtc_event_rtp_rtcp",
     "../../modules/audio_coding:audio_coding_module_typedefs",
+    "../../rtc_base:bitstream_reader",
     "../../rtc_base:checks",
     "../../rtc_base:divide_round",
     "../../rtc_base:gtest_prod",
diff --git a/modules/rtp_rtcp/source/video_rtp_depacketizer_vp9.cc b/modules/rtp_rtcp/source/video_rtp_depacketizer_vp9.cc
index be05009..cd5ebe7 100644
--- a/modules/rtp_rtcp/source/video_rtp_depacketizer_vp9.cc
+++ b/modules/rtp_rtcp/source/video_rtp_depacketizer_vp9.cc
@@ -15,20 +15,13 @@
 #include "api/video/video_codec_constants.h"
 #include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
 #include "modules/video_coding/codecs/interface/common_constants.h"
-#include "rtc_base/bit_buffer.h"
+#include "rtc_base/bitstream_reader.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
 
-#define RETURN_FALSE_ON_ERROR(x) \
-  if (!(x)) {                    \
-    return false;                \
-  }
-
 namespace webrtc {
 namespace {
 
-constexpr int kFailedToParse = 0;
-
 // Picture ID:
 //
 //      +-+-+-+-+-+-+-+-+
@@ -37,66 +30,37 @@
 // M:   | EXTENDED PID  |
 //      +-+-+-+-+-+-+-+-+
 //
-bool ParsePictureId(rtc::BitBuffer* parser, RTPVideoHeaderVP9* vp9) {
-  uint32_t picture_id;
-  uint32_t m_bit;
-  RETURN_FALSE_ON_ERROR(parser->ReadBits(1, m_bit));
-  if (m_bit) {
-    RETURN_FALSE_ON_ERROR(parser->ReadBits(15, picture_id));
+void ParsePictureId(BitstreamReader& parser, RTPVideoHeaderVP9* vp9) {
+  if (parser.ReadBit()) {  // m_bit
+    vp9->picture_id = parser.ReadBits(15);
     vp9->max_picture_id = kMaxTwoBytePictureId;
   } else {
-    RETURN_FALSE_ON_ERROR(parser->ReadBits(7, picture_id));
+    vp9->picture_id = parser.ReadBits(7);
     vp9->max_picture_id = kMaxOneBytePictureId;
   }
-  vp9->picture_id = picture_id;
-  return true;
 }
 
-// Layer indices (flexible mode):
+// Layer indices :
 //
 //      +-+-+-+-+-+-+-+-+
 // L:   |  T  |U|  S  |D|
 //      +-+-+-+-+-+-+-+-+
-//
-bool ParseLayerInfoCommon(rtc::BitBuffer* parser, RTPVideoHeaderVP9* vp9) {
-  uint32_t t, u_bit, s, d_bit;
-  RETURN_FALSE_ON_ERROR(parser->ReadBits(3, t));
-  RETURN_FALSE_ON_ERROR(parser->ReadBits(1, u_bit));
-  RETURN_FALSE_ON_ERROR(parser->ReadBits(3, s));
-  RETURN_FALSE_ON_ERROR(parser->ReadBits(1, d_bit));
-  vp9->temporal_idx = t;
-  vp9->temporal_up_switch = u_bit ? true : false;
-  if (s >= kMaxSpatialLayers)
-    return false;
-  vp9->spatial_idx = s;
-  vp9->inter_layer_predicted = d_bit ? true : false;
-  return true;
-}
-
-// Layer indices (non-flexible mode):
-//
-//      +-+-+-+-+-+-+-+-+
-// L:   |  T  |U|  S  |D|
-//      +-+-+-+-+-+-+-+-+
-//      |   TL0PICIDX   |
+//      |   TL0PICIDX   |  (non-flexible mode only)
 //      +-+-+-+-+-+-+-+-+
 //
-bool ParseLayerInfoNonFlexibleMode(rtc::BitBuffer* parser,
-                                   RTPVideoHeaderVP9* vp9) {
-  uint8_t tl0picidx;
-  RETURN_FALSE_ON_ERROR(parser->ReadUInt8(tl0picidx));
-  vp9->tl0_pic_idx = tl0picidx;
-  return true;
-}
+void ParseLayerInfo(BitstreamReader& parser, RTPVideoHeaderVP9* vp9) {
+  vp9->temporal_idx = parser.ReadBits(3);
+  vp9->temporal_up_switch = parser.Read<bool>();
+  vp9->spatial_idx = parser.ReadBits(3);
+  vp9->inter_layer_predicted = parser.Read<bool>();
+  if (vp9->spatial_idx >= kMaxSpatialLayers) {
+    parser.Invalidate();
+    return;
+  }
 
-bool ParseLayerInfo(rtc::BitBuffer* parser, RTPVideoHeaderVP9* vp9) {
-  if (!ParseLayerInfoCommon(parser, vp9))
-    return false;
-
-  if (vp9->flexible_mode)
-    return true;
-
-  return ParseLayerInfoNonFlexibleMode(parser, vp9);
+  if (!vp9->flexible_mode) {
+    vp9->tl0_pic_idx = parser.Read<uint8_t>();
+  }
 }
 
 // Reference indices:
@@ -106,19 +70,22 @@
 //      +-+-+-+-+-+-+-+-+                    N=1: An additional P_DIFF follows
 //                                                current P_DIFF.
 //
-bool ParseRefIndices(rtc::BitBuffer* parser, RTPVideoHeaderVP9* vp9) {
-  if (vp9->picture_id == kNoPictureId)
-    return false;
+void ParseRefIndices(BitstreamReader& parser, RTPVideoHeaderVP9* vp9) {
+  if (vp9->picture_id == kNoPictureId) {
+    parser.Invalidate();
+    return;
+  }
 
   vp9->num_ref_pics = 0;
-  uint32_t n_bit;
+  bool n_bit;
   do {
-    if (vp9->num_ref_pics == kMaxVp9RefPics)
-      return false;
+    if (vp9->num_ref_pics == kMaxVp9RefPics) {
+      parser.Invalidate();
+      return;
+    }
 
-    uint32_t p_diff;
-    RETURN_FALSE_ON_ERROR(parser->ReadBits(7, p_diff));
-    RETURN_FALSE_ON_ERROR(parser->ReadBits(1, n_bit));
+    uint8_t p_diff = parser.ReadBits(7);
+    n_bit = parser.Read<bool>();
 
     vp9->pid_diff[vp9->num_ref_pics] = p_diff;
     uint32_t scaled_pid = vp9->picture_id;
@@ -128,8 +95,6 @@
     }
     vp9->ref_picture_id[vp9->num_ref_pics++] = scaled_pid - p_diff;
   } while (n_bit);
-
-  return true;
 }
 
 // Scalability structure (SS).
@@ -152,54 +117,40 @@
 //      |    P_DIFF     | (OPTIONAL)    . R times    .
 //      +-+-+-+-+-+-+-+-+              -|           -|
 //
-bool ParseSsData(rtc::BitBuffer* parser, RTPVideoHeaderVP9* vp9) {
-  uint32_t n_s, y_bit, g_bit;
-  RETURN_FALSE_ON_ERROR(parser->ReadBits(3, n_s));
-  RETURN_FALSE_ON_ERROR(parser->ReadBits(1, y_bit));
-  RETURN_FALSE_ON_ERROR(parser->ReadBits(1, g_bit));
-  RETURN_FALSE_ON_ERROR(parser->ConsumeBits(3));
-  vp9->num_spatial_layers = n_s + 1;
-  vp9->spatial_layer_resolution_present = y_bit ? true : false;
+void ParseSsData(BitstreamReader& parser, RTPVideoHeaderVP9* vp9) {
+  vp9->num_spatial_layers = parser.ReadBits(3) + 1;
+  vp9->spatial_layer_resolution_present = parser.Read<bool>();
+  bool g_bit = parser.Read<bool>();
+  parser.ConsumeBits(3);
   vp9->gof.num_frames_in_gof = 0;
 
-  if (y_bit) {
+  if (vp9->spatial_layer_resolution_present) {
     for (size_t i = 0; i < vp9->num_spatial_layers; ++i) {
-      RETURN_FALSE_ON_ERROR(parser->ReadUInt16(vp9->width[i]));
-      RETURN_FALSE_ON_ERROR(parser->ReadUInt16(vp9->height[i]));
+      vp9->width[i] = parser.Read<uint16_t>();
+      vp9->height[i] = parser.Read<uint16_t>();
     }
   }
   if (g_bit) {
-    uint8_t n_g;
-    RETURN_FALSE_ON_ERROR(parser->ReadUInt8(n_g));
-    vp9->gof.num_frames_in_gof = n_g;
+    vp9->gof.num_frames_in_gof = parser.Read<uint8_t>();
   }
   for (size_t i = 0; i < vp9->gof.num_frames_in_gof; ++i) {
-    uint32_t t, u_bit, r;
-    RETURN_FALSE_ON_ERROR(parser->ReadBits(3, t));
-    RETURN_FALSE_ON_ERROR(parser->ReadBits(1, u_bit));
-    RETURN_FALSE_ON_ERROR(parser->ReadBits(2, r));
-    RETURN_FALSE_ON_ERROR(parser->ConsumeBits(2));
-    vp9->gof.temporal_idx[i] = t;
-    vp9->gof.temporal_up_switch[i] = u_bit ? true : false;
-    vp9->gof.num_ref_pics[i] = r;
+    vp9->gof.temporal_idx[i] = parser.ReadBits(3);
+    vp9->gof.temporal_up_switch[i] = parser.Read<bool>();
+    vp9->gof.num_ref_pics[i] = parser.ReadBits(2);
+    parser.ConsumeBits(2);
 
     for (uint8_t p = 0; p < vp9->gof.num_ref_pics[i]; ++p) {
-      uint8_t p_diff;
-      RETURN_FALSE_ON_ERROR(parser->ReadUInt8(p_diff));
-      vp9->gof.pid_diff[i][p] = p_diff;
+      vp9->gof.pid_diff[i][p] = parser.Read<uint8_t>();
     }
   }
-  return true;
 }
 }  // namespace
 
 absl::optional<VideoRtpDepacketizer::ParsedRtpPayload>
 VideoRtpDepacketizerVp9::Parse(rtc::CopyOnWriteBuffer rtp_payload) {
-  rtc::ArrayView<const uint8_t> payload(rtp_payload.cdata(),
-                                        rtp_payload.size());
   absl::optional<ParsedRtpPayload> result(absl::in_place);
-  int offset = ParseRtpPayload(payload, &result->video_header);
-  if (offset == kFailedToParse)
+  int offset = ParseRtpPayload(rtp_payload, &result->video_header);
+  if (offset == 0)
     return absl::nullopt;
   RTC_DCHECK_LT(offset, rtp_payload.size());
   result->video_payload =
@@ -212,12 +163,8 @@
     RTPVideoHeader* video_header) {
   RTC_DCHECK(video_header);
   // Parse mandatory first byte of payload descriptor.
-  rtc::BitBuffer parser(rtp_payload.data(), rtp_payload.size());
-  uint8_t first_byte;
-  if (!parser.ReadUInt8(first_byte)) {
-    RTC_LOG(LS_ERROR) << "Payload length is zero.";
-    return kFailedToParse;
-  }
+  BitstreamReader parser(rtp_payload);
+  uint8_t first_byte = parser.Read<uint8_t>();
   bool i_bit = first_byte & 0b1000'0000;  // PictureId present .
   bool p_bit = first_byte & 0b0100'0000;  // Inter-picture predicted.
   bool l_bit = first_byte & 0b0010'0000;  // Layer indices present.
@@ -247,23 +194,17 @@
   vp9_header.non_ref_for_inter_layer_pred = z_bit;
 
   // Parse fields that are present.
-  if (i_bit && !ParsePictureId(&parser, &vp9_header)) {
-    RTC_LOG(LS_ERROR) << "Failed parsing VP9 picture id.";
-    return kFailedToParse;
+  if (i_bit) {
+    ParsePictureId(parser, &vp9_header);
   }
-  if (l_bit && !ParseLayerInfo(&parser, &vp9_header)) {
-    RTC_LOG(LS_ERROR) << "Failed parsing VP9 layer info.";
-    return kFailedToParse;
+  if (l_bit) {
+    ParseLayerInfo(parser, &vp9_header);
   }
-  if (p_bit && f_bit && !ParseRefIndices(&parser, &vp9_header)) {
-    RTC_LOG(LS_ERROR) << "Failed parsing VP9 ref indices.";
-    return kFailedToParse;
+  if (p_bit && f_bit) {
+    ParseRefIndices(parser, &vp9_header);
   }
   if (v_bit) {
-    if (!ParseSsData(&parser, &vp9_header)) {
-      RTC_LOG(LS_ERROR) << "Failed parsing VP9 SS data.";
-      return kFailedToParse;
-    }
+    ParseSsData(parser, &vp9_header);
     if (vp9_header.spatial_layer_resolution_present) {
       // TODO(asapersson): Add support for spatial layers.
       video_header->width = vp9_header.width[0];
@@ -273,15 +214,13 @@
   video_header->is_first_packet_in_frame =
       b_bit && (!l_bit || !vp9_header.inter_layer_predicted);
 
-  size_t byte_offset;
-  size_t bit_offset;
-  parser.GetCurrentOffset(&byte_offset, &bit_offset);
-  RTC_DCHECK_EQ(bit_offset, 0);
-  if (byte_offset == rtp_payload.size()) {
-    // Empty vp9 payload data.
-    return kFailedToParse;
+  int num_remaining_bits = parser.RemainingBitCount();
+  if (num_remaining_bits <= 0) {
+    // Failed to parse or empty vp9 payload data.
+    return 0;
   }
-
-  return byte_offset;
+  // vp9 descriptor is byte aligned.
+  RTC_DCHECK_EQ(num_remaining_bits % 8, 0);
+  return rtp_payload.size() - num_remaining_bits / 8;
 }
 }  // namespace webrtc