Use RtpPacket instead of legacy RtpHeaderParser in video/ tests

Bug: None
Change-Id: Ia35daa58aae51becef40910187006398d825c5b9
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/161331
Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#30026}
diff --git a/video/end_to_end_tests/fec_tests.cc b/video/end_to_end_tests/fec_tests.cc
index b20ec29..e1fb8cf 100644
--- a/video/end_to_end_tests/fec_tests.cc
+++ b/video/end_to_end_tests/fec_tests.cc
@@ -18,6 +18,7 @@
 #include "media/engine/internal_decoder_factory.h"
 #include "modules/include/module_common_types_public.h"
 #include "modules/rtp_rtcp/source/byte_io.h"
+#include "modules/rtp_rtcp/source/rtp_packet.h"
 #include "modules/video_coding/codecs/vp8/include/vp8.h"
 #include "test/call_test.h"
 #include "test/field_trial.h"
@@ -59,19 +60,19 @@
    private:
     Action OnSendRtp(const uint8_t* packet, size_t length) override {
       rtc::CritScope lock(&crit_);
-      RTPHeader header;
-      EXPECT_TRUE(parser_->Parse(packet, length, &header));
+      RtpPacket rtp_packet;
+      EXPECT_TRUE(rtp_packet.Parse(packet, length));
 
-      EXPECT_TRUE(header.payloadType == kVideoSendPayloadType ||
-                  header.payloadType == kRedPayloadType)
+      EXPECT_TRUE(rtp_packet.PayloadType() == kVideoSendPayloadType ||
+                  rtp_packet.PayloadType() == kRedPayloadType)
           << "Unknown payload type received.";
-      EXPECT_EQ(kVideoSendSsrcs[0], header.ssrc) << "Unknown SSRC received.";
+      EXPECT_EQ(kVideoSendSsrcs[0], rtp_packet.Ssrc())
+          << "Unknown SSRC received.";
 
       // Parse RED header.
       int encapsulated_payload_type = -1;
-      if (header.payloadType == kRedPayloadType) {
-        encapsulated_payload_type =
-            static_cast<int>(packet[header.headerLength]);
+      if (rtp_packet.PayloadType() == kRedPayloadType) {
+        encapsulated_payload_type = rtp_packet.payload()[0];
 
         EXPECT_TRUE(encapsulated_payload_type == kVideoSendPayloadType ||
                     encapsulated_payload_type == kUlpfecPayloadType)
@@ -87,8 +88,8 @@
       // corresponding timestamps that were dropped.
       if (num_packets_sent_++ > 100 && random_.Rand(1, 100) <= 5) {
         if (encapsulated_payload_type == kVideoSendPayloadType) {
-          dropped_sequence_numbers_.insert(header.sequenceNumber);
-          dropped_timestamps_.insert(header.timestamp);
+          dropped_sequence_numbers_.insert(rtp_packet.SequenceNumber());
+          dropped_timestamps_.insert(rtp_packet.Timestamp());
         }
         return DROP_PACKET;
       }
@@ -169,35 +170,35 @@
  private:
   Action OnSendRtp(const uint8_t* packet, size_t length) override {
     rtc::CritScope lock(&crit_);
-    RTPHeader header;
-    EXPECT_TRUE(parser_->Parse(packet, length, &header));
+    RtpPacket rtp_packet;
+    EXPECT_TRUE(rtp_packet.Parse(packet, length));
 
-    EXPECT_TRUE(header.payloadType ==
-                    test::CallTest::kFakeVideoSendPayloadType ||
-                header.payloadType == test::CallTest::kFlexfecPayloadType ||
-                (enable_nack_ &&
-                 header.payloadType == test::CallTest::kSendRtxPayloadType))
+    EXPECT_TRUE(
+        rtp_packet.PayloadType() == test::CallTest::kFakeVideoSendPayloadType ||
+        rtp_packet.PayloadType() == test::CallTest::kFlexfecPayloadType ||
+        (enable_nack_ &&
+         rtp_packet.PayloadType() == test::CallTest::kSendRtxPayloadType))
         << "Unknown payload type received.";
     EXPECT_TRUE(
-        header.ssrc == test::CallTest::kVideoSendSsrcs[0] ||
-        header.ssrc == test::CallTest::kFlexfecSendSsrc ||
-        (enable_nack_ && header.ssrc == test::CallTest::kSendRtxSsrcs[0]))
+        rtp_packet.Ssrc() == test::CallTest::kVideoSendSsrcs[0] ||
+        rtp_packet.Ssrc() == test::CallTest::kFlexfecSendSsrc ||
+        (enable_nack_ && rtp_packet.Ssrc() == test::CallTest::kSendRtxSsrcs[0]))
         << "Unknown SSRC received.";
 
     // To reduce test flakiness, always let FlexFEC packets through.
-    if (header.payloadType == test::CallTest::kFlexfecPayloadType) {
-      EXPECT_EQ(test::CallTest::kFlexfecSendSsrc, header.ssrc);
+    if (rtp_packet.PayloadType() == test::CallTest::kFlexfecPayloadType) {
+      EXPECT_EQ(test::CallTest::kFlexfecSendSsrc, rtp_packet.Ssrc());
 
       return SEND_PACKET;
     }
 
     // To reduce test flakiness, always let RTX packets through.
-    if (header.payloadType == test::CallTest::kSendRtxPayloadType) {
-      EXPECT_EQ(test::CallTest::kSendRtxSsrcs[0], header.ssrc);
+    if (rtp_packet.PayloadType() == test::CallTest::kSendRtxPayloadType) {
+      EXPECT_EQ(test::CallTest::kSendRtxSsrcs[0], rtp_packet.Ssrc());
 
       // Parse RTX header.
       uint16_t original_sequence_number =
-          ByteReader<uint16_t>::ReadBigEndian(&packet[header.headerLength]);
+          ByteReader<uint16_t>::ReadBigEndian(rtp_packet.payload().data());
 
       // From the perspective of FEC, a retransmitted packet is no longer
       // dropped, so remove it from list of dropped packets.
@@ -205,7 +206,7 @@
           dropped_sequence_numbers_.find(original_sequence_number);
       if (seq_num_it != dropped_sequence_numbers_.end()) {
         dropped_sequence_numbers_.erase(seq_num_it);
-        auto ts_it = dropped_timestamps_.find(header.timestamp);
+        auto ts_it = dropped_timestamps_.find(rtp_packet.Timestamp());
         EXPECT_NE(ts_it, dropped_timestamps_.end());
         dropped_timestamps_.erase(ts_it);
       }
@@ -216,11 +217,12 @@
     // Simulate 5% video packet loss after rampup period. Record the
     // corresponding timestamps that were dropped.
     if (num_packets_sent_++ > 100 && random_.Rand(1, 100) <= 5) {
-      EXPECT_EQ(test::CallTest::kFakeVideoSendPayloadType, header.payloadType);
-      EXPECT_EQ(test::CallTest::kVideoSendSsrcs[0], header.ssrc);
+      EXPECT_EQ(test::CallTest::kFakeVideoSendPayloadType,
+                rtp_packet.PayloadType());
+      EXPECT_EQ(test::CallTest::kVideoSendSsrcs[0], rtp_packet.Ssrc());
 
-      dropped_sequence_numbers_.insert(header.sequenceNumber);
-      dropped_timestamps_.insert(header.timestamp);
+      dropped_sequence_numbers_.insert(rtp_packet.SequenceNumber());
+      dropped_timestamps_.insert(rtp_packet.Timestamp());
 
       return DROP_PACKET;
     }
@@ -354,26 +356,25 @@
    private:
     Action OnSendRtp(const uint8_t* packet, size_t length) override {
       rtc::CritScope lock_(&crit_);
-      RTPHeader header;
-      EXPECT_TRUE(parser_->Parse(packet, length, &header));
+      RtpPacket rtp_packet;
+      EXPECT_TRUE(rtp_packet.Parse(packet, length));
 
       int encapsulated_payload_type = -1;
-      if (header.payloadType == kRedPayloadType) {
-        encapsulated_payload_type =
-            static_cast<int>(packet[header.headerLength]);
+      if (rtp_packet.PayloadType() == kRedPayloadType) {
+        encapsulated_payload_type = rtp_packet.payload()[0];
         if (encapsulated_payload_type != kFakeVideoSendPayloadType)
           EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
       } else {
-        EXPECT_EQ(kFakeVideoSendPayloadType, header.payloadType);
+        EXPECT_EQ(kFakeVideoSendPayloadType, rtp_packet.PayloadType());
       }
 
       if (has_last_sequence_number_ &&
-          !IsNewerSequenceNumber(header.sequenceNumber,
+          !IsNewerSequenceNumber(rtp_packet.SequenceNumber(),
                                  last_sequence_number_)) {
         // Drop retransmitted packets.
         return DROP_PACKET;
       }
-      last_sequence_number_ = header.sequenceNumber;
+      last_sequence_number_ = rtp_packet.SequenceNumber();
       has_last_sequence_number_ = true;
 
       bool ulpfec_packet = encapsulated_payload_type == kUlpfecPayloadType;
@@ -384,14 +385,14 @@
         case kDropEveryOtherPacketUntilUlpfec:
           if (ulpfec_packet) {
             state_ = kDropAllMediaPacketsUntilUlpfec;
-          } else if (header.sequenceNumber % 2 == 0) {
+          } else if (rtp_packet.SequenceNumber() % 2 == 0) {
             return DROP_PACKET;
           }
           break;
         case kDropAllMediaPacketsUntilUlpfec:
           if (!ulpfec_packet)
             return DROP_PACKET;
-          ulpfec_sequence_number_ = header.sequenceNumber;
+          ulpfec_sequence_number_ = rtp_packet.SequenceNumber();
           state_ = kDropOneMediaPacket;
           break;
         case kDropOneMediaPacket:
@@ -410,7 +411,7 @@
           break;
         case kVerifyUlpfecPacketNotInNackList:
           // Continue to drop packets. Make sure no frame can be decoded.
-          if (ulpfec_packet || header.sequenceNumber % 2 == 0)
+          if (ulpfec_packet || rtp_packet.SequenceNumber() % 2 == 0)
             return DROP_PACKET;
           break;
       }
diff --git a/video/end_to_end_tests/multi_codec_receive_tests.cc b/video/end_to_end_tests/multi_codec_receive_tests.cc
index 4aaf843..354ee44 100644
--- a/video/end_to_end_tests/multi_codec_receive_tests.cc
+++ b/video/end_to_end_tests/multi_codec_receive_tests.cc
@@ -15,6 +15,7 @@
 #include "call/fake_network_pipe.h"
 #include "call/simulated_network.h"
 #include "modules/include/module_common_types_public.h"
+#include "modules/rtp_rtcp/source/rtp_packet.h"
 #include "modules/video_coding/codecs/h264/include/h264.h"
 #include "modules/video_coding/codecs/vp8/include/vp8.h"
 #include "modules/video_coding/codecs/vp9/include/vp9.h"
@@ -75,29 +76,28 @@
   Action OnSendRtp(const uint8_t* packet, size_t length) override {
     rtc::CritScope lock(&crit_);
 
-    RTPHeader header;
-    EXPECT_TRUE(parser_->Parse(packet, length, &header));
-    EXPECT_EQ(header.ssrc, test::CallTest::kVideoSendSsrcs[0]);
-    EXPECT_GE(length, header.headerLength + header.paddingLength);
-    if ((length - header.headerLength) == header.paddingLength)
+    RtpPacket rtp_packet;
+    EXPECT_TRUE(rtp_packet.Parse(packet, length));
+    EXPECT_EQ(rtp_packet.Ssrc(), test::CallTest::kVideoSendSsrcs[0]);
+    if (rtp_packet.payload_size() == 0)
       return SEND_PACKET;  // Skip padding, may be sent after OnFrame is called.
 
     if (expected_payload_type_ &&
-        header.payloadType != expected_payload_type_.value()) {
+        rtp_packet.PayloadType() != expected_payload_type_.value()) {
       return DROP_PACKET;  // All frames sent.
     }
 
-    if (!last_timestamp_ || header.timestamp != *last_timestamp_) {
+    if (!last_timestamp_ || rtp_packet.Timestamp() != *last_timestamp_) {
       // New frame.
       // Sent enough frames?
       if (num_sent_frames_ >= kFramesToObserve)
         return DROP_PACKET;
 
       ++num_sent_frames_;
-      sent_timestamps_.push_back(header.timestamp);
+      sent_timestamps_.push_back(rtp_packet.Timestamp());
     }
 
-    last_timestamp_ = header.timestamp;
+    last_timestamp_ = rtp_packet.Timestamp();
     return SEND_PACKET;
   }
 
diff --git a/video/end_to_end_tests/network_state_tests.cc b/video/end_to_end_tests/network_state_tests.cc
index eda6dae..a0977ac 100644
--- a/video/end_to_end_tests/network_state_tests.cc
+++ b/video/end_to_end_tests/network_state_tests.cc
@@ -14,6 +14,7 @@
 #include "api/video_codecs/video_encoder.h"
 #include "call/fake_network_pipe.h"
 #include "call/simulated_network.h"
+#include "modules/rtp_rtcp/source/rtp_packet.h"
 #include "rtc_base/task_queue_for_test.h"
 #include "system_wrappers/include/sleep.h"
 #include "test/call_test.h"
@@ -177,9 +178,9 @@
 
     Action OnSendRtp(const uint8_t* packet, size_t length) override {
       rtc::CritScope lock(&test_crit_);
-      RTPHeader header;
-      EXPECT_TRUE(parser_->Parse(packet, length, &header));
-      if (length == header.headerLength + header.paddingLength)
+      RtpPacket rtp_packet;
+      EXPECT_TRUE(rtp_packet.Parse(packet, length));
+      if (rtp_packet.payload_size() == 0)
         ++sender_padding_;
       ++sender_rtp_;
       packet_event_.Set();
diff --git a/video/end_to_end_tests/retransmission_tests.cc b/video/end_to_end_tests/retransmission_tests.cc
index 7aae577..407aa5f 100644
--- a/video/end_to_end_tests/retransmission_tests.cc
+++ b/video/end_to_end_tests/retransmission_tests.cc
@@ -16,6 +16,7 @@
 #include "api/test/video/function_video_encoder_factory.h"
 #include "call/fake_network_pipe.h"
 #include "call/simulated_network.h"
+#include "modules/rtp_rtcp/source/rtp_packet.h"
 #include "modules/video_coding/codecs/vp8/include/vp8.h"
 #include "rtc_base/task_queue_for_test.h"
 #include "system_wrappers/include/sleep.h"
@@ -58,13 +59,13 @@
    private:
     Action OnSendRtp(const uint8_t* packet, size_t length) override {
       rtc::CritScope lock(&crit_);
-      RTPHeader header;
-      EXPECT_TRUE(parser_->Parse(packet, length, &header));
+      RtpPacket rtp_packet;
+      EXPECT_TRUE(rtp_packet.Parse(packet, length));
 
       // Never drop retransmitted packets.
-      if (dropped_packets_.find(header.sequenceNumber) !=
+      if (dropped_packets_.find(rtp_packet.SequenceNumber()) !=
           dropped_packets_.end()) {
-        retransmitted_packets_.insert(header.sequenceNumber);
+        retransmitted_packets_.insert(rtp_packet.SequenceNumber());
         return SEND_PACKET;
       }
 
@@ -84,9 +85,9 @@
         packets_left_to_drop_ = kLossBurstSize;
 
       // Never drop padding packets as those won't be retransmitted.
-      if (packets_left_to_drop_ > 0 && header.paddingLength == 0) {
+      if (packets_left_to_drop_ > 0 && rtp_packet.padding_size() == 0) {
         --packets_left_to_drop_;
-        dropped_packets_.insert(header.sequenceNumber);
+        dropped_packets_.insert(rtp_packet.SequenceNumber());
         return DROP_PACKET;
       }
 
@@ -152,14 +153,15 @@
     }
 
     Action OnSendRtp(const uint8_t* packet, size_t length) override {
-      RTPHeader header;
-      EXPECT_TRUE(parser_->Parse(packet, length, &header));
+      RtpPacket rtp_packet;
+      EXPECT_TRUE(rtp_packet.Parse(packet, length));
 
       if (!sequence_number_to_retransmit_) {
-        sequence_number_to_retransmit_ = header.sequenceNumber;
+        sequence_number_to_retransmit_ = rtp_packet.SequenceNumber();
 
         // Don't ask for retransmission straight away, may be deduped in pacer.
-      } else if (header.sequenceNumber == *sequence_number_to_retransmit_) {
+      } else if (rtp_packet.SequenceNumber() ==
+                 *sequence_number_to_retransmit_) {
         observation_complete_.Set();
       } else {
         // Send a NACK as often as necessary until retransmission is received.
@@ -258,15 +260,15 @@
    private:
     Action OnSendRtp(const uint8_t* packet, size_t length) override {
       rtc::CritScope lock(&crit_);
-      RTPHeader header;
-      EXPECT_TRUE(parser_->Parse(packet, length, &header));
+      RtpPacket rtp_packet;
+      EXPECT_TRUE(rtp_packet.Parse(packet, length));
 
       // Drop all retransmitted packets to force a PLI.
-      if (header.timestamp <= highest_dropped_timestamp_)
+      if (rtp_packet.Timestamp() <= highest_dropped_timestamp_)
         return DROP_PACKET;
 
       if (frames_to_drop_ > 0) {
-        highest_dropped_timestamp_ = header.timestamp;
+        highest_dropped_timestamp_ = rtp_packet.Timestamp();
         --frames_to_drop_;
         return DROP_PACKET;
       }
@@ -350,29 +352,29 @@
    private:
     Action OnSendRtp(const uint8_t* packet, size_t length) override {
       rtc::CritScope lock(&crit_);
-      RTPHeader header;
-      EXPECT_TRUE(parser_->Parse(packet, length, &header));
+      RtpPacket rtp_packet;
+      EXPECT_TRUE(rtp_packet.Parse(packet, length));
 
       // Ignore padding-only packets over RTX.
-      if (header.payloadType != payload_type_) {
-        EXPECT_EQ(retransmission_ssrc_, header.ssrc);
-        if (length == header.headerLength + header.paddingLength)
+      if (rtp_packet.PayloadType() != payload_type_) {
+        EXPECT_EQ(retransmission_ssrc_, rtp_packet.Ssrc());
+        if (rtp_packet.payload_size() == 0)
           return SEND_PACKET;
       }
 
-      if (header.timestamp == retransmitted_timestamp_) {
-        EXPECT_EQ(retransmission_ssrc_, header.ssrc);
-        EXPECT_EQ(retransmission_payload_type_, header.payloadType);
+      if (rtp_packet.Timestamp() == retransmitted_timestamp_) {
+        EXPECT_EQ(retransmission_ssrc_, rtp_packet.Ssrc());
+        EXPECT_EQ(retransmission_payload_type_, rtp_packet.PayloadType());
         return SEND_PACKET;
       }
 
       // Found the final packet of the frame to inflict loss to, drop this and
       // expect a retransmission.
-      if (header.payloadType == payload_type_ && header.markerBit &&
+      if (rtp_packet.PayloadType() == payload_type_ && rtp_packet.Marker() &&
           ++marker_bits_observed_ == kDroppedFrameNumber) {
         // This should be the only dropped packet.
         EXPECT_EQ(0u, retransmitted_timestamp_);
-        retransmitted_timestamp_ = header.timestamp;
+        retransmitted_timestamp_ = rtp_packet.Timestamp();
         if (absl::c_linear_search(rendered_timestamps_,
                                   retransmitted_timestamp_)) {
           // Frame was rendered before last packet was scheduled for sending.
diff --git a/video/end_to_end_tests/rtp_rtcp_tests.cc b/video/end_to_end_tests/rtp_rtcp_tests.cc
index 97777a1..71783fe 100644
--- a/video/end_to_end_tests/rtp_rtcp_tests.cc
+++ b/video/end_to_end_tests/rtp_rtcp_tests.cc
@@ -14,6 +14,7 @@
 #include "call/fake_network_pipe.h"
 #include "call/simulated_network.h"
 #include "modules/include/module_common_types_public.h"
+#include "modules/rtp_rtcp/source/rtp_packet.h"
 #include "modules/video_coding/codecs/vp8/include/vp8.h"
 #include "rtc_base/task_queue_for_test.h"
 #include "test/call_test.h"
@@ -204,14 +205,13 @@
     }
 
     Action OnSendRtp(const uint8_t* packet, size_t length) override {
-      RTPHeader header;
-      EXPECT_TRUE(parser_->Parse(packet, length, &header));
-      const uint32_t ssrc = header.ssrc;
+      RtpPacket rtp_packet;
+      EXPECT_TRUE(rtp_packet.Parse(packet, length));
+      const uint32_t ssrc = rtp_packet.Ssrc();
       const int64_t sequence_number =
-          seq_numbers_unwrapper_.Unwrap(header.sequenceNumber);
-      const uint32_t timestamp = header.timestamp;
-      const bool only_padding =
-          header.headerLength + header.paddingLength == length;
+          seq_numbers_unwrapper_.Unwrap(rtp_packet.SequenceNumber());
+      const uint32_t timestamp = rtp_packet.Timestamp();
+      const bool only_padding = rtp_packet.payload_size() == 0;
 
       EXPECT_TRUE(ssrc_is_rtx_.find(ssrc) != ssrc_is_rtx_.end())
           << "Received SSRC that wasn't configured: " << ssrc;
@@ -422,11 +422,11 @@
     Action OnSendRtp(const uint8_t* packet, size_t length) override {
       rtc::CritScope lock(&crit_);
 
-      RTPHeader header;
-      EXPECT_TRUE(parser_->Parse(packet, length, &header));
-      const uint16_t sequence_number = header.sequenceNumber;
-      const uint32_t timestamp = header.timestamp;
-      const uint32_t ssrc = header.ssrc;
+      RtpPacket rtp_packet;
+      EXPECT_TRUE(rtp_packet.Parse(packet, length));
+      const uint16_t sequence_number = rtp_packet.SequenceNumber();
+      const uint32_t timestamp = rtp_packet.Timestamp();
+      const uint32_t ssrc = rtp_packet.Ssrc();
 
       if (ssrc == kVideoSendSsrcs[0] || ssrc == kSendRtxSsrcs[0]) {
         return SEND_PACKET;
diff --git a/video/end_to_end_tests/ssrc_tests.cc b/video/end_to_end_tests/ssrc_tests.cc
index 1251b45..8efad01 100644
--- a/video/end_to_end_tests/ssrc_tests.cc
+++ b/video/end_to_end_tests/ssrc_tests.cc
@@ -13,6 +13,7 @@
 #include "api/test/simulated_network.h"
 #include "call/fake_network_pipe.h"
 #include "call/simulated_network.h"
+#include "modules/rtp_rtcp/source/rtp_packet.h"
 #include "rtc_base/task_queue_for_test.h"
 #include "test/call_test.h"
 #include "test/gtest.h"
@@ -145,17 +146,17 @@
 
    private:
     Action OnSendRtp(const uint8_t* packet, size_t length) override {
-      RTPHeader header;
-      EXPECT_TRUE(parser_->Parse(packet, length, &header));
+      RtpPacket rtp_packet;
+      EXPECT_TRUE(rtp_packet.Parse(packet, length));
 
-      EXPECT_TRUE(valid_ssrcs_[header.ssrc])
-          << "Received unknown SSRC: " << header.ssrc;
+      EXPECT_TRUE(valid_ssrcs_[rtp_packet.Ssrc()])
+          << "Received unknown SSRC: " << rtp_packet.Ssrc();
 
-      if (!valid_ssrcs_[header.ssrc])
+      if (!valid_ssrcs_[rtp_packet.Ssrc()])
         observation_complete_.Set();
 
-      if (!is_observed_[header.ssrc]) {
-        is_observed_[header.ssrc] = true;
+      if (!is_observed_[rtp_packet.Ssrc()]) {
+        is_observed_[rtp_packet.Ssrc()] = true;
         --ssrcs_to_observe_;
         if (expect_single_ssrc_) {
           expect_single_ssrc_ = false;
@@ -269,21 +270,19 @@
 
    private:
     Action OnSendRtp(const uint8_t* packet, size_t length) override {
-      RTPHeader header;
-      EXPECT_TRUE(parser_->Parse(packet, length, &header));
+      RtpPacket rtp_packet;
+      EXPECT_TRUE(rtp_packet.Parse(packet, length));
 
-      if (!registered_rtx_ssrc_[header.ssrc])
+      if (!registered_rtx_ssrc_[rtp_packet.Ssrc()])
         return SEND_PACKET;
 
-      EXPECT_LE(header.headerLength + header.paddingLength, length);
-      const bool packet_is_redundant_payload =
-          header.headerLength + header.paddingLength < length;
+      const bool packet_is_redundant_payload = rtp_packet.payload_size() > 0;
 
       if (!packet_is_redundant_payload)
         return SEND_PACKET;
 
-      if (!observed_redundant_retransmission_[header.ssrc]) {
-        observed_redundant_retransmission_[header.ssrc] = true;
+      if (!observed_redundant_retransmission_[rtp_packet.Ssrc()]) {
+        observed_redundant_retransmission_[rtp_packet.Ssrc()] = true;
         if (--ssrcs_to_observe_ == 0)
           observation_complete_.Set();
       }
diff --git a/video/end_to_end_tests/transport_feedback_tests.cc b/video/end_to_end_tests/transport_feedback_tests.cc
index 55c8bc4..b36c9b9 100644
--- a/video/end_to_end_tests/transport_feedback_tests.cc
+++ b/video/end_to_end_tests/transport_feedback_tests.cc
@@ -16,6 +16,8 @@
 #include "call/simulated_network.h"
 #include "modules/include/module_common_types_public.h"
 #include "modules/rtp_rtcp/source/byte_io.h"
+#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
+#include "modules/rtp_rtcp/source/rtp_packet.h"
 #include "test/call_test.h"
 #include "test/field_trial.h"
 #include "test/gtest.h"
@@ -51,14 +53,13 @@
                                   BuiltInNetworkBehaviorConfig())),
                           sender_call,
                           payload_type_map),
-          parser_(RtpHeaderParser::CreateForTest()),
           first_media_ssrc_(first_media_ssrc),
           rtx_to_media_ssrcs_(ssrc_map),
           rtx_padding_observed_(false),
           retransmit_observed_(false),
           started_(false) {
-      parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
-                                          kTransportSequenceNumberExtensionId);
+      extensions_.Register<TransportSequenceNumber>(
+          kTransportSequenceNumberExtensionId);
     }
     virtual ~RtpExtensionHeaderObserver() {}
 
@@ -72,13 +73,14 @@
           return false;
 
         if (started_) {
-          RTPHeader header;
-          EXPECT_TRUE(parser_->Parse(data, length, &header));
+          RtpPacket rtp_packet(&extensions_);
+          EXPECT_TRUE(rtp_packet.Parse(data, length));
           bool drop_packet = false;
 
-          EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
-          EXPECT_EQ(options.packet_id,
-                    header.extension.transportSequenceNumber);
+          uint16_t transport_sequence_number = 0;
+          EXPECT_TRUE(rtp_packet.GetExtension<TransportSequenceNumber>(
+              &transport_sequence_number));
+          EXPECT_EQ(options.packet_id, transport_sequence_number);
           if (!streams_observed_.empty()) {
             // Unwrap packet id and verify uniqueness.
             int64_t packet_id = unwrapper_.Unwrap(options.packet_id);
@@ -89,18 +91,19 @@
           // Only drop media, and not on the first stream (otherwise it will be
           // hard to distinguish from padding, which is always sent on the first
           // stream).
-          if (header.payloadType != kSendRtxPayloadType &&
-              header.ssrc != first_media_ssrc_ &&
-              header.extension.transportSequenceNumber % 17 == 0) {
-            dropped_seq_[header.ssrc].insert(header.sequenceNumber);
+          if (rtp_packet.PayloadType() != kSendRtxPayloadType &&
+              rtp_packet.Ssrc() != first_media_ssrc_ &&
+              transport_sequence_number % 17 == 0) {
+            dropped_seq_[rtp_packet.Ssrc()].insert(rtp_packet.SequenceNumber());
             drop_packet = true;
           }
 
-          if (header.payloadType == kSendRtxPayloadType) {
+          if (rtp_packet.PayloadType() == kSendRtxPayloadType) {
             uint16_t original_sequence_number =
-                ByteReader<uint16_t>::ReadBigEndian(&data[header.headerLength]);
+                ByteReader<uint16_t>::ReadBigEndian(
+                    rtp_packet.payload().data());
             uint32_t original_ssrc =
-                rtx_to_media_ssrcs_.find(header.ssrc)->second;
+                rtx_to_media_ssrcs_.find(rtp_packet.Ssrc())->second;
             std::set<uint16_t>* seq_no_map = &dropped_seq_[original_ssrc];
             auto it = seq_no_map->find(original_sequence_number);
             if (it != seq_no_map->end()) {
@@ -110,7 +113,7 @@
               rtx_padding_observed_ = true;
             }
           } else {
-            streams_observed_.insert(header.ssrc);
+            streams_observed_.insert(rtp_packet.Ssrc());
           }
 
           if (IsDone())
@@ -149,7 +152,7 @@
    private:
     rtc::CriticalSection lock_;
     rtc::Event done_;
-    std::unique_ptr<RtpHeaderParser> parser_;
+    RtpHeaderExtensionMap extensions_;
     SequenceNumberUnwrapper unwrapper_;
     std::set<int64_t> received_packed_ids_;
     std::set<uint32_t> streams_observed_;
@@ -369,10 +372,9 @@
 
    protected:
     Action OnSendRtp(const uint8_t* packet, size_t length) override {
-      RTPHeader header;
-      EXPECT_TRUE(parser_->Parse(packet, length, &header));
-      const bool only_padding =
-          header.headerLength + header.paddingLength == length;
+      RtpPacket rtp_packet;
+      EXPECT_TRUE(rtp_packet.Parse(packet, length));
+      const bool only_padding = rtp_packet.payload_size() == 0;
       rtc::CritScope lock(&crit_);
       // Padding is expected in congested state to probe for connectivity when
       // packets has been dropped.
@@ -449,8 +451,8 @@
         : EndToEndTest(kDefaultTimeoutMs),
           video_observed_(false),
           audio_observed_(false) {
-      parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
-                                          kTransportSequenceNumberExtensionId);
+      extensions_.Register<TransportSequenceNumber>(
+          kTransportSequenceNumberExtensionId);
     }
 
     size_t GetNumVideoStreams() const override { return 1; }
@@ -468,17 +470,18 @@
     }
 
     Action OnSendRtp(const uint8_t* packet, size_t length) override {
-      RTPHeader header;
-      EXPECT_TRUE(parser_->Parse(packet, length, &header));
-      EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
+      RtpPacket rtp_packet(&extensions_);
+      EXPECT_TRUE(rtp_packet.Parse(packet, length));
+      uint16_t transport_sequence_number = 0;
+      EXPECT_TRUE(rtp_packet.GetExtension<TransportSequenceNumber>(
+          &transport_sequence_number));
       // Unwrap packet id and verify uniqueness.
-      int64_t packet_id =
-          unwrapper_.Unwrap(header.extension.transportSequenceNumber);
+      int64_t packet_id = unwrapper_.Unwrap(transport_sequence_number);
       EXPECT_TRUE(received_packet_ids_.insert(packet_id).second);
 
-      if (header.ssrc == kVideoSendSsrcs[0])
+      if (rtp_packet.Ssrc() == kVideoSendSsrcs[0])
         video_observed_ = true;
-      if (header.ssrc == kAudioSendSsrc)
+      if (rtp_packet.Ssrc() == kAudioSendSsrc)
         audio_observed_ = true;
       if (audio_observed_ && video_observed_ &&
           received_packet_ids_.size() >= kMinPacketsToWaitFor) {
@@ -506,6 +509,7 @@
     bool audio_observed_;
     SequenceNumberUnwrapper unwrapper_;
     std::set<int64_t> received_packet_ids_;
+    RtpHeaderExtensionMap extensions_;
   } test;
 
   RunBaseTest(&test);
diff --git a/video/picture_id_tests.cc b/video/picture_id_tests.cc
index 267a8e0..da952f7 100644
--- a/video/picture_id_tests.cc
+++ b/video/picture_id_tests.cc
@@ -17,6 +17,7 @@
 #include "media/engine/internal_encoder_factory.h"
 #include "media/engine/simulcast_encoder_adapter.h"
 #include "modules/rtp_rtcp/source/rtp_format.h"
+#include "modules/rtp_rtcp/source/rtp_packet.h"
 #include "modules/video_coding/codecs/vp8/include/vp8.h"
 #include "modules/video_coding/codecs/vp9/include/vp9.h"
 #include "rtc_base/numerics/safe_conversions.h"
@@ -80,27 +81,26 @@
   bool ParsePayload(const uint8_t* packet,
                     size_t length,
                     ParsedPacket* parsed) const {
-    RTPHeader header;
-    EXPECT_TRUE(parser_->Parse(packet, length, &header));
-    EXPECT_TRUE(header.ssrc == test::CallTest::kVideoSendSsrcs[0] ||
-                header.ssrc == test::CallTest::kVideoSendSsrcs[1] ||
-                header.ssrc == test::CallTest::kVideoSendSsrcs[2])
+    RtpPacket rtp_packet;
+    EXPECT_TRUE(rtp_packet.Parse(packet, length));
+    EXPECT_TRUE(rtp_packet.Ssrc() == test::CallTest::kVideoSendSsrcs[0] ||
+                rtp_packet.Ssrc() == test::CallTest::kVideoSendSsrcs[1] ||
+                rtp_packet.Ssrc() == test::CallTest::kVideoSendSsrcs[2])
         << "Unknown SSRC sent.";
 
-    EXPECT_GE(length, header.headerLength + header.paddingLength);
-    size_t payload_length = length - header.headerLength - header.paddingLength;
-    if (payload_length == 0) {
+    rtc::ArrayView<const uint8_t> rtp_payload = rtp_packet.payload();
+    if (rtp_payload.empty()) {
       return false;  // Padding packet.
     }
 
-    parsed->timestamp = header.timestamp;
-    parsed->ssrc = header.ssrc;
+    parsed->timestamp = rtp_packet.Timestamp();
+    parsed->ssrc = rtp_packet.Ssrc();
 
     std::unique_ptr<RtpDepacketizer> depacketizer(
         RtpDepacketizer::Create(codec_type_));
     RtpDepacketizer::ParsedPayload parsed_payload;
-    EXPECT_TRUE(depacketizer->Parse(
-        &parsed_payload, &packet[header.headerLength], payload_length));
+    EXPECT_TRUE(depacketizer->Parse(&parsed_payload, rtp_payload.data(),
+                                    rtp_payload.size()));
 
     switch (codec_type_) {
       case kVideoCodecVP8: {
diff --git a/video/video_send_stream_tests.cc b/video/video_send_stream_tests.cc
index 0d51cbd..c3f2de9 100644
--- a/video/video_send_stream_tests.cc
+++ b/video/video_send_stream_tests.cc
@@ -24,9 +24,12 @@
 #include "call/rtp_transport_controller_send.h"
 #include "call/simulated_network.h"
 #include "call/video_send_stream.h"
+#include "modules/rtp_rtcp/include/rtp_header_extension_map.h"
 #include "modules/rtp_rtcp/include/rtp_rtcp.h"
 #include "modules/rtp_rtcp/source/rtcp_sender.h"
 #include "modules/rtp_rtcp/source/rtp_format_vp9.h"
+#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
+#include "modules/rtp_rtcp/source/rtp_packet.h"
 #include "modules/video_coding/codecs/vp8/include/vp8.h"
 #include "modules/video_coding/codecs/vp9/include/vp9.h"
 #include "rtc_base/checks.h"
@@ -182,18 +185,17 @@
   class AbsoluteSendTimeObserver : public test::SendTest {
    public:
     AbsoluteSendTimeObserver() : SendTest(kDefaultTimeoutMs) {
-      EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
-          kRtpExtensionAbsoluteSendTime, kAbsSendTimeExtensionId));
+      extensions_.Register<AbsoluteSendTime>(kAbsSendTimeExtensionId);
     }
 
     Action OnSendRtp(const uint8_t* packet, size_t length) override {
-      RTPHeader header;
-      EXPECT_TRUE(parser_->Parse(packet, length, &header));
+      RtpPacket rtp_packet(&extensions_);
+      EXPECT_TRUE(rtp_packet.Parse(packet, length));
 
-      EXPECT_FALSE(header.extension.hasTransmissionTimeOffset);
-      EXPECT_TRUE(header.extension.hasAbsoluteSendTime);
-      EXPECT_EQ(header.extension.transmissionTimeOffset, 0);
-      if (header.extension.absoluteSendTime != 0) {
+      uint32_t abs_send_time = 0;
+      EXPECT_FALSE(rtp_packet.HasExtension<TransmissionOffset>());
+      EXPECT_TRUE(rtp_packet.GetExtension<AbsoluteSendTime>(&abs_send_time));
+      if (abs_send_time != 0) {
         // Wait for at least one packet with a non-zero send time. The send time
         // is a 16-bit value derived from the system clock, and it is valid
         // for a packet to have a zero send time. To tell that from an
@@ -220,6 +222,9 @@
     void PerformTest() override {
       EXPECT_TRUE(Wait()) << "Timed out while waiting for single RTP packet.";
     }
+
+   private:
+    RtpHeaderExtensionMap extensions_;
   } test;
 
   RunBaseTest(&test);
@@ -234,19 +239,18 @@
             return std::make_unique<test::DelayedEncoder>(
                 Clock::GetRealTimeClock(), kEncodeDelayMs);
           }) {
-      EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
-          kRtpExtensionTransmissionTimeOffset, kTimestampOffsetExtensionId));
+      extensions_.Register<TransmissionOffset>(kTimestampOffsetExtensionId);
     }
 
    private:
     Action OnSendRtp(const uint8_t* packet, size_t length) override {
-      RTPHeader header;
-      EXPECT_TRUE(parser_->Parse(packet, length, &header));
+      RtpPacket rtp_packet(&extensions_);
+      EXPECT_TRUE(rtp_packet.Parse(packet, length));
 
-      EXPECT_TRUE(header.extension.hasTransmissionTimeOffset);
-      EXPECT_FALSE(header.extension.hasAbsoluteSendTime);
-      EXPECT_GT(header.extension.transmissionTimeOffset, 0);
-      EXPECT_EQ(header.extension.absoluteSendTime, 0u);
+      int32_t toffset = 0;
+      EXPECT_TRUE(rtp_packet.GetExtension<TransmissionOffset>(&toffset));
+      EXPECT_FALSE(rtp_packet.HasExtension<AbsoluteSendTime>());
+      EXPECT_GT(toffset, 0);
       observation_complete_.Set();
 
       return SEND_PACKET;
@@ -267,6 +271,7 @@
     }
 
     test::FunctionVideoEncoderFactory encoder_factory_;
+    RtpHeaderExtensionMap extensions_;
   } test;
 
   RunBaseTest(&test);
@@ -281,18 +286,17 @@
             return std::make_unique<test::FakeEncoder>(
                 Clock::GetRealTimeClock());
           }) {
-      EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
-          kRtpExtensionTransportSequenceNumber, kExtensionId));
+      extensions_.Register<TransportSequenceNumber>(kExtensionId);
     }
 
    private:
     Action OnSendRtp(const uint8_t* packet, size_t length) override {
-      RTPHeader header;
-      EXPECT_TRUE(parser_->Parse(packet, length, &header));
+      RtpPacket rtp_packet(&extensions_);
+      EXPECT_TRUE(rtp_packet.Parse(packet, length));
 
-      EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
-      EXPECT_FALSE(header.extension.hasTransmissionTimeOffset);
-      EXPECT_FALSE(header.extension.hasAbsoluteSendTime);
+      EXPECT_TRUE(rtp_packet.HasExtension<TransportSequenceNumber>());
+      EXPECT_FALSE(rtp_packet.HasExtension<TransmissionOffset>());
+      EXPECT_FALSE(rtp_packet.HasExtension<AbsoluteSendTime>());
 
       observation_complete_.Set();
 
@@ -311,6 +315,7 @@
     }
 
     test::FunctionVideoEncoderFactory encoder_factory_;
+    RtpHeaderExtensionMap extensions_;
   } test;
 
   RunBaseTest(&test);
@@ -320,18 +325,16 @@
   class VideoRotationObserver : public test::SendTest {
    public:
     VideoRotationObserver() : SendTest(kDefaultTimeoutMs) {
-      EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
-          kRtpExtensionVideoRotation, kVideoRotationExtensionId));
+      extensions_.Register<VideoOrientation>(kVideoRotationExtensionId);
     }
 
     Action OnSendRtp(const uint8_t* packet, size_t length) override {
-      RTPHeader header;
-      EXPECT_TRUE(parser_->Parse(packet, length, &header));
+      RtpPacket rtp_packet(&extensions_);
+      EXPECT_TRUE(rtp_packet.Parse(packet, length));
       // Only the last packet of the frame is required to have the extension.
-      if (!header.markerBit)
+      if (!rtp_packet.Marker())
         return SEND_PACKET;
-      EXPECT_TRUE(header.extension.hasVideoRotation);
-      EXPECT_EQ(kVideoRotation_90, header.extension.videoRotation);
+      EXPECT_EQ(rtp_packet.GetExtension<VideoOrientation>(), kVideoRotation_90);
       observation_complete_.Set();
       return SEND_PACKET;
     }
@@ -353,6 +356,9 @@
     void PerformTest() override {
       EXPECT_TRUE(Wait()) << "Timed out while waiting for single RTP packet.";
     }
+
+   private:
+    RtpHeaderExtensionMap extensions_;
   } test;
 
   RunBaseTest(&test);
@@ -363,21 +369,21 @@
    public:
     VideoContentTypeObserver()
         : SendTest(kDefaultTimeoutMs), first_frame_sent_(false) {
-      EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
-          kRtpExtensionVideoContentType, kVideoContentTypeExtensionId));
+      extensions_.Register<VideoContentTypeExtension>(
+          kVideoContentTypeExtensionId);
     }
 
     Action OnSendRtp(const uint8_t* packet, size_t length) override {
-      RTPHeader header;
-      EXPECT_TRUE(parser_->Parse(packet, length, &header));
+      RtpPacket rtp_packet(&extensions_);
+      EXPECT_TRUE(rtp_packet.Parse(packet, length));
       // Only the last packet of the key-frame must have extension.
-      if (!header.markerBit || first_frame_sent_)
+      if (!rtp_packet.Marker() || first_frame_sent_)
         return SEND_PACKET;
       // First marker bit seen means that the first frame is sent.
       first_frame_sent_ = true;
-      EXPECT_TRUE(header.extension.hasVideoContentType);
-      EXPECT_TRUE(videocontenttypehelpers::IsScreenshare(
-          header.extension.videoContentType));
+      VideoContentType type;
+      EXPECT_TRUE(rtp_packet.GetExtension<VideoContentTypeExtension>(&type));
+      EXPECT_TRUE(videocontenttypehelpers::IsScreenshare(type));
       observation_complete_.Set();
       return SEND_PACKET;
     }
@@ -398,6 +404,7 @@
 
    private:
     bool first_frame_sent_;
+    RtpHeaderExtensionMap extensions_;
   } test;
 
   RunBaseTest(&test);
@@ -408,19 +415,18 @@
    public:
     VideoTimingObserver()
         : SendTest(kDefaultTimeoutMs), first_frame_sent_(false) {
-      EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(kRtpExtensionVideoTiming,
-                                                      kVideoTimingExtensionId));
+      extensions_.Register<VideoTimingExtension>(kVideoTimingExtensionId);
     }
 
     Action OnSendRtp(const uint8_t* packet, size_t length) override {
-      RTPHeader header;
-      EXPECT_TRUE(parser_->Parse(packet, length, &header));
+      RtpPacket rtp_packet(&extensions_);
+      EXPECT_TRUE(rtp_packet.Parse(packet, length));
       // Only the last packet of the frame must have extension.
       // Also don't check packets of the second frame if they happen to get
       // through before the test terminates.
-      if (!header.markerBit || first_frame_sent_)
+      if (!rtp_packet.Marker() || first_frame_sent_)
         return SEND_PACKET;
-      EXPECT_TRUE(header.extension.has_video_timing);
+      EXPECT_TRUE(rtp_packet.HasExtension<VideoTimingExtension>());
       observation_complete_.Set();
       first_frame_sent_ = true;
       return SEND_PACKET;
@@ -440,6 +446,7 @@
     }
 
    private:
+    RtpHeaderExtensionMap extensions_;
     bool first_frame_sent_;
   } test;
 
@@ -489,21 +496,20 @@
         sent_media_(false),
         sent_ulpfec_(false),
         header_extensions_enabled_(header_extensions_enabled) {
-    parser_->RegisterRtpHeaderExtension(kRtpExtensionAbsoluteSendTime,
-                                        kAbsSendTimeExtensionId);
-    parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
-                                        kTransportSequenceNumberExtensionId);
+    extensions_.Register<AbsoluteSendTime>(kAbsSendTimeExtensionId);
+    extensions_.Register<TransportSequenceNumber>(
+        kTransportSequenceNumberExtensionId);
   }
 
  private:
   Action OnSendRtp(const uint8_t* packet, size_t length) override {
-    RTPHeader header;
-    EXPECT_TRUE(parser_->Parse(packet, length, &header));
+    RtpPacket rtp_packet(&extensions_);
+    EXPECT_TRUE(rtp_packet.Parse(packet, length));
 
     int encapsulated_payload_type = -1;
-    if (header.payloadType == VideoSendStreamTest::kRedPayloadType) {
+    if (rtp_packet.PayloadType() == VideoSendStreamTest::kRedPayloadType) {
       EXPECT_TRUE(expect_red_);
-      encapsulated_payload_type = static_cast<int>(packet[header.headerLength]);
+      encapsulated_payload_type = rtp_packet.payload()[0];
       if (encapsulated_payload_type !=
           VideoSendStreamTest::kFakeVideoSendPayloadType) {
         EXPECT_EQ(VideoSendStreamTest::kUlpfecPayloadType,
@@ -511,9 +517,8 @@
       }
     } else {
       EXPECT_EQ(VideoSendStreamTest::kFakeVideoSendPayloadType,
-                header.payloadType);
-      if (static_cast<size_t>(header.headerLength + header.paddingLength) <
-          length) {
+                rtp_packet.PayloadType());
+      if (rtp_packet.payload_size() > 0) {
         // Not padding-only, media received outside of RED.
         EXPECT_FALSE(expect_red_);
         sent_media_ = true;
@@ -521,21 +526,27 @@
     }
 
     if (header_extensions_enabled_) {
-      EXPECT_TRUE(header.extension.hasAbsoluteSendTime);
-      uint32_t kHalf24BitsSpace = 0xFFFFFF / 2;
-      if (header.extension.absoluteSendTime <= kHalf24BitsSpace &&
-          prev_header_.extension.absoluteSendTime > kHalf24BitsSpace) {
-        // 24 bits wrap.
-        EXPECT_GT(prev_header_.extension.absoluteSendTime,
-                  header.extension.absoluteSendTime);
-      } else {
-        EXPECT_GE(header.extension.absoluteSendTime,
-                  prev_header_.extension.absoluteSendTime);
+      uint32_t abs_send_time;
+      EXPECT_TRUE(rtp_packet.GetExtension<AbsoluteSendTime>(&abs_send_time));
+      uint16_t transport_seq_num;
+      EXPECT_TRUE(
+          rtp_packet.GetExtension<TransportSequenceNumber>(&transport_seq_num));
+      if (!first_packet_) {
+        uint32_t kHalf24BitsSpace = 0xFFFFFF / 2;
+        if (abs_send_time <= kHalf24BitsSpace &&
+            prev_abs_send_time_ > kHalf24BitsSpace) {
+          // 24 bits wrap.
+          EXPECT_GT(prev_abs_send_time_, abs_send_time);
+        } else {
+          EXPECT_GE(abs_send_time, prev_abs_send_time_);
+        }
+
+        uint16_t seq_num_diff = transport_seq_num - prev_transport_seq_num_;
+        EXPECT_EQ(1, seq_num_diff);
       }
-      EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
-      uint16_t seq_num_diff = header.extension.transportSequenceNumber -
-                              prev_header_.extension.transportSequenceNumber;
-      EXPECT_EQ(1, seq_num_diff);
+      first_packet_ = false;
+      prev_abs_send_time_ = abs_send_time;
+      prev_transport_seq_num_ = transport_seq_num;
     }
 
     if (encapsulated_payload_type != -1) {
@@ -552,8 +563,6 @@
       observation_complete_.Set();
     }
 
-    prev_header_ = header;
-
     return SEND_PACKET;
   }
 
@@ -609,14 +618,17 @@
   }
 
   VideoEncoderFactory* encoder_factory_;
+  RtpHeaderExtensionMap extensions_;
   std::string payload_name_;
   const bool use_nack_;
   const bool expect_red_;
   const bool expect_ulpfec_;
   bool sent_media_;
   bool sent_ulpfec_;
-  bool header_extensions_enabled_;
-  RTPHeader prev_header_;
+  const bool header_extensions_enabled_;
+  bool first_packet_ = true;
+  uint32_t prev_abs_send_time_ = 0;
+  uint16_t prev_transport_seq_num_ = 0;
 };
 
 TEST_F(VideoSendStreamTest, SupportsUlpfecWithExtensions) {
@@ -713,12 +725,10 @@
         sent_flexfec_(false),
         header_extensions_enabled_(header_extensions_enabled),
         num_video_streams_(num_video_streams) {
-    parser_->RegisterRtpHeaderExtension(kRtpExtensionAbsoluteSendTime,
-                                        kAbsSendTimeExtensionId);
-    parser_->RegisterRtpHeaderExtension(kRtpExtensionTransmissionTimeOffset,
-                                        kTimestampOffsetExtensionId);
-    parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
-                                        kTransportSequenceNumberExtensionId);
+    extensions_.Register<AbsoluteSendTime>(kAbsSendTimeExtensionId);
+    extensions_.Register<TransmissionOffset>(kTimestampOffsetExtensionId);
+    extensions_.Register<TransportSequenceNumber>(
+        kTransportSequenceNumberExtensionId);
   }
 
   size_t GetNumFlexfecStreams() const override { return 1; }
@@ -726,25 +736,25 @@
 
  private:
   Action OnSendRtp(const uint8_t* packet, size_t length) override {
-    RTPHeader header;
-    EXPECT_TRUE(parser_->Parse(packet, length, &header));
+    RtpPacket rtp_packet(&extensions_);
+    EXPECT_TRUE(rtp_packet.Parse(packet, length));
 
-    if (header.payloadType == VideoSendStreamTest::kFlexfecPayloadType) {
-      EXPECT_EQ(VideoSendStreamTest::kFlexfecSendSsrc, header.ssrc);
+    if (rtp_packet.PayloadType() == VideoSendStreamTest::kFlexfecPayloadType) {
+      EXPECT_EQ(VideoSendStreamTest::kFlexfecSendSsrc, rtp_packet.Ssrc());
       sent_flexfec_ = true;
     } else {
       EXPECT_EQ(VideoSendStreamTest::kFakeVideoSendPayloadType,
-                header.payloadType);
+                rtp_packet.PayloadType());
       EXPECT_THAT(::testing::make_tuple(VideoSendStreamTest::kVideoSendSsrcs,
                                         num_video_streams_),
-                  ::testing::Contains(header.ssrc));
+                  ::testing::Contains(rtp_packet.Ssrc()));
       sent_media_ = true;
     }
 
     if (header_extensions_enabled_) {
-      EXPECT_TRUE(header.extension.hasAbsoluteSendTime);
-      EXPECT_TRUE(header.extension.hasTransmissionTimeOffset);
-      EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
+      EXPECT_TRUE(rtp_packet.HasExtension<AbsoluteSendTime>());
+      EXPECT_TRUE(rtp_packet.HasExtension<TransmissionOffset>());
+      EXPECT_TRUE(rtp_packet.HasExtension<TransportSequenceNumber>());
     }
 
     if (sent_media_ && sent_flexfec_) {
@@ -815,6 +825,7 @@
   }
 
   VideoEncoderFactory* encoder_factory_;
+  RtpHeaderExtensionMap extensions_;
   std::string payload_name_;
   const bool use_nack_;
   bool sent_media_;
@@ -910,15 +921,15 @@
 
    private:
     Action OnSendRtp(const uint8_t* packet, size_t length) override {
-      RTPHeader header;
-      EXPECT_TRUE(parser_->Parse(packet, length, &header));
+      RtpPacket rtp_packet;
+      EXPECT_TRUE(rtp_packet.Parse(packet, length));
 
       // NACK packets two times at some arbitrary points.
       const int kNackedPacketsAtOnceCount = 3;
       const int kRetransmitTarget = kNackedPacketsAtOnceCount * 2;
 
       // Skip padding packets because they will never be retransmitted.
-      if (header.paddingLength + header.headerLength == length) {
+      if (rtp_packet.payload_size() == 0) {
         return SEND_PACKET;
       }
 
@@ -949,12 +960,12 @@
                          &nacked_sequence_numbers_.front()));
       }
 
-      uint16_t sequence_number = header.sequenceNumber;
-      if (header.ssrc == retransmit_ssrc_ &&
+      uint16_t sequence_number = rtp_packet.SequenceNumber();
+      if (rtp_packet.Ssrc() == retransmit_ssrc_ &&
           retransmit_ssrc_ != kVideoSendSsrcs[0]) {
         // Not kVideoSendSsrcs[0], assume correct RTX packet. Extract sequence
         // number.
-        const uint8_t* rtx_header = packet + header.headerLength;
+        const uint8_t* rtx_header = rtp_packet.payload().data();
         sequence_number = (rtx_header[0] << 8) + rtx_header[1];
       }
 
@@ -963,8 +974,8 @@
         nacked_sequence_numbers_.erase(found);
 
         if (++retransmit_count_ == kRetransmitTarget) {
-          EXPECT_EQ(retransmit_ssrc_, header.ssrc);
-          EXPECT_EQ(retransmit_payload_type_, header.payloadType);
+          EXPECT_EQ(retransmit_ssrc_, rtp_packet.Ssrc());
+          EXPECT_EQ(retransmit_payload_type_, rtp_packet.PayloadType());
           observation_complete_.Set();
         }
       } else {
@@ -1057,14 +1068,14 @@
    private:
     Action OnSendRtp(const uint8_t* packet, size_t size) override {
       size_t length = size;
-      RTPHeader header;
-      EXPECT_TRUE(parser_->Parse(packet, length, &header));
+      RtpPacket rtp_packet;
+      EXPECT_TRUE(rtp_packet.Parse(packet, length));
 
       EXPECT_LE(length, max_packet_size_);
 
-      if (use_fec_) {
-        uint8_t payload_type = packet[header.headerLength];
-        bool is_fec = header.payloadType == kRedPayloadType &&
+      if (use_fec_ && rtp_packet.payload_size() > 0) {
+        uint8_t payload_type = rtp_packet.payload()[0];
+        bool is_fec = rtp_packet.PayloadType() == kRedPayloadType &&
                       payload_type == kUlpfecPayloadType;
         if (is_fec) {
           fec_packet_received_ = true;
@@ -1075,10 +1086,10 @@
       accumulated_size_ += length;
 
       if (use_fec_)
-        TriggerLossReport(header);
+        TriggerLossReport(rtp_packet);
 
       if (test_generic_packetization_) {
-        size_t overhead = header.headerLength + header.paddingLength;
+        size_t overhead = rtp_packet.headers_size() + rtp_packet.padding_size();
         // Only remove payload header and RED header if the packet actually
         // contains payload.
         if (length > overhead) {
@@ -1091,7 +1102,7 @@
       }
 
       // Marker bit set indicates last packet of a frame.
-      if (header.markerBit) {
+      if (rtp_packet.Marker()) {
         if (use_fec_ && accumulated_payload_ == current_size_rtp_ - 1) {
           // With FEC enabled, frame size is incremented asynchronously, so
           // "old" frames one byte too small may arrive. Accept, but don't
@@ -1132,7 +1143,7 @@
       return SEND_PACKET;
     }
 
-    void TriggerLossReport(const RTPHeader& header) {
+    void TriggerLossReport(const RtpPacket& rtp_packet) {
       // Send lossy receive reports to trigger FEC enabling.
       const int kLossPercent = 5;
       if (++packet_count_ % (100 / kLossPercent) == 0) {
@@ -1144,7 +1155,7 @@
         uint8_t loss_ratio =
             static_cast<uint8_t>(loss_delta * 255 / packets_delta);
         FakeReceiveStatistics lossy_receive_stats(
-            kVideoSendSsrcs[0], header.sequenceNumber,
+            kVideoSendSsrcs[0], rtp_packet.SequenceNumber(),
             packets_lost_,  // Cumulative lost.
             loss_ratio);    // Loss percent.
         RtpRtcp::Configuration config;
@@ -1309,23 +1320,23 @@
     Action OnSendRtp(const uint8_t* packet, size_t length) override {
       rtc::CritScope lock(&crit_);
       ++rtp_count_;
-      RTPHeader header;
-      EXPECT_TRUE(parser_->Parse(packet, length, &header));
-      last_sequence_number_ = header.sequenceNumber;
+      RtpPacket rtp_packet;
+      EXPECT_TRUE(rtp_packet.Parse(packet, length));
+      last_sequence_number_ = rtp_packet.SequenceNumber();
 
       if (test_state_ == kBeforeSuspend) {
         // The stream has started. Try to suspend it.
         SendRtcpFeedback(low_remb_bps_);
         test_state_ = kDuringSuspend;
       } else if (test_state_ == kDuringSuspend) {
-        if (header.paddingLength == 0) {
+        if (rtp_packet.padding_size() == 0) {
           // Received non-padding packet during suspension period. Reset the
           // counter.
           suspended_frame_count_ = 0;
         }
         SendRtcpFeedback(0);  // REMB is only sent if value is > 0.
       } else if (test_state_ == kWaitingForPacket) {
-        if (header.paddingLength == 0) {
+        if (rtp_packet.padding_size() == 0) {
           // Non-padding packet observed. Test is almost complete. Will just
           // have to wait for the stats to change.
           test_state_ = kWaitingForStats;
@@ -1449,10 +1460,9 @@
       rtc::CritScope lock(&crit_);
       last_packet_time_ms_ = clock_->TimeInMilliseconds();
 
-      RTPHeader header;
-      parser_->Parse(packet, length, &header);
-      const bool only_padding =
-          header.headerLength + header.paddingLength == length;
+      RtpPacket rtp_packet;
+      rtp_packet.Parse(packet, length);
+      const bool only_padding = rtp_packet.payload_size() == 0;
 
       if (test_state_ == kBeforeStopCapture) {
         // Packets are flowing, stop camera.
@@ -1545,9 +1555,9 @@
     Action OnSendRtp(const uint8_t* packet, size_t length) override {
       rtc::CritScope lock(&crit_);
 
-      RTPHeader header;
-      parser_->Parse(packet, length, &header);
-      padding_length_ += header.paddingLength;
+      RtpPacket rtp_packet;
+      rtp_packet.Parse(packet, length);
+      padding_length_ += rtp_packet.padding_size();
       total_length_ += length;
       return SEND_PACKET;
     }
@@ -1624,8 +1634,8 @@
       if (RtpHeaderParser::IsRtcp(packet, length))
         return DROP_PACKET;
 
-      RTPHeader header;
-      if (!parser_->Parse(packet, length, &header))
+      RtpPacket rtp_packet;
+      if (!rtp_packet.Parse(packet, length))
         return DROP_PACKET;
       RTC_DCHECK(stream_);
       VideoSendStream::Stats stats = stream_->GetStats();
@@ -1637,8 +1647,7 @@
                           "bitrate_bps", static_cast<size_t>(total_bitrate_bps),
                           "bps", false);
         if (total_bitrate_bps > kHighBitrateBps) {
-          rtp_rtcp_->SetRemb(kRembBitrateBps,
-                             std::vector<uint32_t>(1, header.ssrc));
+          rtp_rtcp_->SetRemb(kRembBitrateBps, {rtp_packet.Ssrc()});
           rtp_rtcp_->Process();
           bitrate_capped_ = true;
         } else if (bitrate_capped_ &&
@@ -1699,8 +1708,7 @@
           call_(nullptr) {
       module_process_thread_.Detach();
       task_queue_thread_.Detach();
-      EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
-          kRtpExtensionTransportSequenceNumber, kExtensionId));
+      extensions_.Register<TransportSequenceNumber>(kExtensionId);
     }
 
     void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
@@ -1792,6 +1800,7 @@
     webrtc::SequenceChecker module_process_thread_;
     webrtc::SequenceChecker task_queue_thread_;
     TaskQueueBase* const task_queue_;
+    RtpHeaderExtensionMap extensions_;
     Call* call_ RTC_GUARDED_BY(task_queue_thread_);
   } test(task_queue());
 
@@ -2685,10 +2694,10 @@
    private:
     Action OnSendRtp(const uint8_t* packet, size_t length) override {
       rtc::CritScope lock(&crit_);
-      RTPHeader header;
-      EXPECT_TRUE(parser_->Parse(packet, length, &header));
+      RtpPacket rtp_packet;
+      EXPECT_TRUE(rtp_packet.Parse(packet, length));
       ++rtp_packets_sent_;
-      media_bytes_sent_ += length - header.headerLength - header.paddingLength;
+      media_bytes_sent_ += rtp_packet.payload_size();
       return SEND_PACKET;
     }
 
@@ -3133,34 +3142,36 @@
   }
 
   Action OnSendRtp(const uint8_t* packet, size_t length) override {
-    RTPHeader header;
-    EXPECT_TRUE(parser_->Parse(packet, length, &header));
+    RtpPacket rtp_packet;
+    EXPECT_TRUE(rtp_packet.Parse(packet, length));
 
-    EXPECT_EQ(kVp9PayloadType, header.payloadType);
-    const uint8_t* payload = packet + header.headerLength;
-    size_t payload_length = length - header.headerLength - header.paddingLength;
+    EXPECT_EQ(kVp9PayloadType, rtp_packet.PayloadType());
+    rtc::ArrayView<const uint8_t> rtp_payload = rtp_packet.payload();
 
     bool new_packet = packets_sent_ == 0 ||
-                      IsNewerSequenceNumber(header.sequenceNumber,
-                                            last_header_.sequenceNumber);
-    if (payload_length > 0 && new_packet) {
+                      IsNewerSequenceNumber(rtp_packet.SequenceNumber(),
+                                            last_packet_sequence_number_);
+    if (!rtp_payload.empty() && new_packet) {
       RtpDepacketizer::ParsedPayload parsed;
       RtpDepacketizerVp9 depacketizer;
-      EXPECT_TRUE(depacketizer.Parse(&parsed, payload, payload_length));
+      EXPECT_TRUE(
+          depacketizer.Parse(&parsed, rtp_payload.data(), rtp_payload.size()));
       EXPECT_EQ(VideoCodecType::kVideoCodecVP9, parsed.video_header().codec);
       // Verify common fields for all configurations.
       const auto& vp9_header =
           absl::get<RTPVideoHeaderVP9>(parsed.video_header().video_type_header);
       VerifyCommonHeader(vp9_header);
-      CompareConsecutiveFrames(header, parsed.video_header());
+      CompareConsecutiveFrames(rtp_packet, parsed.video_header());
       // Verify configuration specific settings.
       InspectHeader(vp9_header);
 
       ++packets_sent_;
-      if (header.markerBit) {
+      if (rtp_packet.Marker()) {
         ++frames_sent_;
       }
-      last_header_ = header;
+      last_packet_marker_ = rtp_packet.Marker();
+      last_packet_sequence_number_ = rtp_packet.SequenceNumber();
+      last_packet_timestamp_ = rtp_packet.Timestamp();
       last_vp9_ = vp9_header;
     }
     return SEND_PACKET;
@@ -3344,17 +3355,18 @@
     }
   }
 
-  void CompareConsecutiveFrames(const RTPHeader& header,
+  void CompareConsecutiveFrames(const RtpPacket& rtp_packet,
                                 const RTPVideoHeader& video) const {
     const auto& vp9_header =
         absl::get<RTPVideoHeaderVP9>(video.video_type_header);
 
-    bool new_frame = packets_sent_ == 0 ||
-                     IsNewerTimestamp(header.timestamp, last_header_.timestamp);
+    bool new_frame =
+        packets_sent_ == 0 ||
+        IsNewerTimestamp(rtp_packet.Timestamp(), last_packet_timestamp_);
     EXPECT_EQ(new_frame, video.is_first_packet_in_frame);
     if (!new_frame) {
-      EXPECT_FALSE(last_header_.markerBit);
-      EXPECT_EQ(last_header_.timestamp, header.timestamp);
+      EXPECT_FALSE(last_packet_marker_);
+      EXPECT_EQ(last_packet_timestamp_, rtp_packet.Timestamp());
       EXPECT_EQ(last_vp9_.picture_id, vp9_header.picture_id);
       EXPECT_EQ(last_vp9_.temporal_idx, vp9_header.temporal_idx);
       EXPECT_EQ(last_vp9_.tl0_pic_idx, vp9_header.tl0_pic_idx);
@@ -3368,7 +3380,7 @@
     if (frames_sent_ == 0)
       return;
     EXPECT_TRUE(last_vp9_.end_of_frame);
-    EXPECT_TRUE(last_header_.markerBit);
+    EXPECT_TRUE(last_packet_marker_);
     EXPECT_TRUE(ContinuousPictureId(vp9_header));
     VerifyTl0Idx(vp9_header);
   }
@@ -3376,7 +3388,9 @@
   test::FunctionVideoEncoderFactory encoder_factory_;
   VideoCodecVP9 vp9_settings_;
   webrtc::VideoEncoderConfig encoder_config_;
-  RTPHeader last_header_;
+  bool last_packet_marker_ = false;
+  uint16_t last_packet_sequence_number_ = 0;
+  uint32_t last_packet_timestamp_ = 0;
   RTPVideoHeaderVP9 last_vp9_;
   size_t packets_sent_;
   size_t frames_sent_;