Change H264 depacketizer to implement VideoRtpDepacketizer interface

Bug: webrtc:11152
Change-Id: If5169f47d85918356fa66e2bf3422d722044aa1f
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/165581
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Reviewed-by: Markus Handell <handellm@webrtc.org>
Reviewed-by: Sam Zackrisson <saza@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#30264}
diff --git a/modules/rtp_rtcp/source/create_video_rtp_depacketizer.cc b/modules/rtp_rtcp/source/create_video_rtp_depacketizer.cc
index d96741b..724ad8c 100644
--- a/modules/rtp_rtcp/source/create_video_rtp_depacketizer.cc
+++ b/modules/rtp_rtcp/source/create_video_rtp_depacketizer.cc
@@ -12,49 +12,21 @@
 
 #include <memory>
 
-#include "absl/memory/memory.h"
-#include "absl/types/optional.h"
+#include "api/video/video_codec_type.h"
 #include "modules/rtp_rtcp/source/video_rtp_depacketizer.h"
 #include "modules/rtp_rtcp/source/video_rtp_depacketizer_av1.h"
 #include "modules/rtp_rtcp/source/video_rtp_depacketizer_generic.h"
 #include "modules/rtp_rtcp/source/video_rtp_depacketizer_h264.h"
 #include "modules/rtp_rtcp/source/video_rtp_depacketizer_vp8.h"
 #include "modules/rtp_rtcp/source/video_rtp_depacketizer_vp9.h"
-#include "rtc_base/checks.h"
-#include "rtc_base/copy_on_write_buffer.h"
 
 namespace webrtc {
-namespace {
-
-// Wrapper over legacy RtpDepacketizer interface.
-// TODO(bugs.webrtc.org/11152): Delete when all RtpDepacketizers updated to
-// the VideoRtpDepacketizer interface.
-template <typename Depacketizer>
-class Legacy : public VideoRtpDepacketizer {
- public:
-  absl::optional<ParsedRtpPayload> Parse(
-      rtc::CopyOnWriteBuffer rtp_payload) override {
-    Depacketizer depacketizer;
-    RtpDepacketizer::ParsedPayload parsed_payload;
-    if (!depacketizer.Parse(&parsed_payload, rtp_payload.cdata(),
-                            rtp_payload.size())) {
-      return absl::nullopt;
-    }
-    absl::optional<ParsedRtpPayload> result(absl::in_place);
-    result->video_header = parsed_payload.video;
-    result->video_payload.SetData(parsed_payload.payload,
-                                  parsed_payload.payload_length);
-    return result;
-  }
-};
-
-}  // namespace
 
 std::unique_ptr<VideoRtpDepacketizer> CreateVideoRtpDepacketizer(
     VideoCodecType codec) {
   switch (codec) {
     case kVideoCodecH264:
-      return std::make_unique<Legacy<RtpDepacketizerH264>>();
+      return std::make_unique<VideoRtpDepacketizerH264>();
     case kVideoCodecVP8:
       return std::make_unique<VideoRtpDepacketizerVp8>();
     case kVideoCodecVP9:
diff --git a/modules/rtp_rtcp/source/rtp_format_h264.h b/modules/rtp_rtcp/source/rtp_format_h264.h
index fdea9a7..4661dc2 100644
--- a/modules/rtp_rtcp/source/rtp_format_h264.h
+++ b/modules/rtp_rtcp/source/rtp_format_h264.h
@@ -22,7 +22,6 @@
 #include "modules/include/module_common_types.h"
 #include "modules/rtp_rtcp/source/rtp_format.h"
 #include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
-#include "modules/rtp_rtcp/source/video_rtp_depacketizer_h264.h"
 #include "modules/video_coding/codecs/h264/include/h264_globals.h"
 #include "rtc_base/buffer.h"
 #include "rtc_base/constructor_magic.h"
diff --git a/modules/rtp_rtcp/source/video_rtp_depacketizer_h264.cc b/modules/rtp_rtcp/source/video_rtp_depacketizer_h264.cc
index 9babc67..a0bd8fb 100644
--- a/modules/rtp_rtcp/source/video_rtp_depacketizer_h264.cc
+++ b/modules/rtp_rtcp/source/video_rtp_depacketizer_h264.cc
@@ -10,11 +10,8 @@
 
 #include "modules/rtp_rtcp/source/video_rtp_depacketizer_h264.h"
 
-#include <string.h>
-
 #include <cstddef>
 #include <cstdint>
-#include <memory>
 #include <utility>
 #include <vector>
 
@@ -25,17 +22,19 @@
 #include "common_video/h264/sps_parser.h"
 #include "common_video/h264/sps_vui_rewriter.h"
 #include "modules/rtp_rtcp/source/byte_io.h"
+#include "modules/rtp_rtcp/source/video_rtp_depacketizer.h"
 #include "rtc_base/checks.h"
+#include "rtc_base/copy_on_write_buffer.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/system/fallthrough.h"
 
 namespace webrtc {
 namespace {
 
-static const size_t kNalHeaderSize = 1;
-static const size_t kFuAHeaderSize = 2;
-static const size_t kLengthFieldSize = 2;
-static const size_t kStapAHeaderSize = kNalHeaderSize + kLengthFieldSize;
+constexpr size_t kNalHeaderSize = 1;
+constexpr size_t kFuAHeaderSize = 2;
+constexpr size_t kLengthFieldSize = 2;
+constexpr size_t kStapAHeaderSize = kNalHeaderSize + kLengthFieldSize;
 
 // Bit masks for FU (A and B) indicators.
 enum NalDefs : uint8_t { kFBit = 0x80, kNriMask = 0x60, kTypeMask = 0x1F };
@@ -66,36 +65,35 @@
   return true;
 }
 
-}  // namespace
-
-RtpDepacketizerH264::RtpDepacketizerH264() : offset_(0), length_(0) {}
-RtpDepacketizerH264::~RtpDepacketizerH264() {}
-
-bool RtpDepacketizerH264::ProcessStapAOrSingleNalu(
-    ParsedPayload* parsed_payload,
-    const uint8_t* payload_data) {
-  parsed_payload->video_header().width = 0;
-  parsed_payload->video_header().height = 0;
-  parsed_payload->video_header().codec = kVideoCodecH264;
-  parsed_payload->video_header().simulcastIdx = 0;
-  parsed_payload->video_header().is_first_packet_in_frame = true;
-  auto& h264_header = absl::get<RTPVideoHeaderH264>(
-      parsed_payload->video_header().video_type_header);
+absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> ProcessStapAOrSingleNalu(
+    rtc::CopyOnWriteBuffer rtp_payload) {
+  const uint8_t* const payload_data = rtp_payload.cdata();
+  absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed_payload(
+      absl::in_place);
+  bool modified_buffer = false;
+  parsed_payload->video_payload = rtp_payload;
+  parsed_payload->video_header.width = 0;
+  parsed_payload->video_header.height = 0;
+  parsed_payload->video_header.codec = kVideoCodecH264;
+  parsed_payload->video_header.simulcastIdx = 0;
+  parsed_payload->video_header.is_first_packet_in_frame = true;
+  auto& h264_header = parsed_payload->video_header.video_type_header
+                          .emplace<RTPVideoHeaderH264>();
 
   const uint8_t* nalu_start = payload_data + kNalHeaderSize;
-  const size_t nalu_length = length_ - kNalHeaderSize;
+  const size_t nalu_length = rtp_payload.size() - kNalHeaderSize;
   uint8_t nal_type = payload_data[0] & kTypeMask;
   std::vector<size_t> nalu_start_offsets;
   if (nal_type == H264::NaluType::kStapA) {
     // Skip the StapA header (StapA NAL type + length).
-    if (length_ <= kStapAHeaderSize) {
+    if (rtp_payload.size() <= kStapAHeaderSize) {
       RTC_LOG(LS_ERROR) << "StapA header truncated.";
-      return false;
+      return absl::nullopt;
     }
 
     if (!ParseStapAStartOffsets(nalu_start, nalu_length, &nalu_start_offsets)) {
       RTC_LOG(LS_ERROR) << "StapA packet with incorrect NALU packet lengths.";
-      return false;
+      return absl::nullopt;
     }
 
     h264_header.packetization_type = kH264StapA;
@@ -105,9 +103,10 @@
     nalu_start_offsets.push_back(0);
   }
   h264_header.nalu_type = nal_type;
-  parsed_payload->video_header().frame_type = VideoFrameType::kVideoFrameDelta;
+  parsed_payload->video_header.frame_type = VideoFrameType::kVideoFrameDelta;
 
-  nalu_start_offsets.push_back(length_ + kLengthFieldSize);  // End offset.
+  nalu_start_offsets.push_back(rtp_payload.size() +
+                               kLengthFieldSize);  // End offset.
   for (size_t i = 0; i < nalu_start_offsets.size() - 1; ++i) {
     size_t start_offset = nalu_start_offsets[i];
     // End offset is actually start offset for next unit, excluding length field
@@ -115,7 +114,7 @@
     size_t end_offset = nalu_start_offsets[i + 1] - kLengthFieldSize;
     if (end_offset - start_offset < H264::kNaluTypeSize) {
       RTC_LOG(LS_ERROR) << "STAP-A packet too short";
-      return false;
+      return absl::nullopt;
     }
 
     NaluInfo nalu;
@@ -131,18 +130,18 @@
         // excessive decoder latency.
 
         // Copy any previous data first (likely just the first header).
-        std::unique_ptr<rtc::Buffer> output_buffer(new rtc::Buffer());
+        rtc::Buffer output_buffer;
         if (start_offset)
-          output_buffer->AppendData(payload_data, start_offset);
+          output_buffer.AppendData(payload_data, start_offset);
 
         absl::optional<SpsParser::SpsState> sps;
 
         SpsVuiRewriter::ParseResult result = SpsVuiRewriter::ParseAndRewriteSps(
             &payload_data[start_offset], end_offset - start_offset, &sps,
-            nullptr, output_buffer.get(), SpsVuiRewriter::Direction::kIncoming);
+            nullptr, &output_buffer, SpsVuiRewriter::Direction::kIncoming);
 
         if (result == SpsVuiRewriter::ParseResult::kVuiRewritten) {
-          if (modified_buffer_) {
+          if (modified_buffer) {
             RTC_LOG(LS_WARNING)
                 << "More than one H264 SPS NAL units needing "
                    "rewriting found within a single STAP-A packet. "
@@ -155,27 +154,29 @@
                 start_offset - (H264::kNaluTypeSize + kLengthFieldSize);
             // Stap-A Length includes payload data and type header.
             size_t rewritten_size =
-                output_buffer->size() - start_offset + H264::kNaluTypeSize;
+                output_buffer.size() - start_offset + H264::kNaluTypeSize;
             ByteWriter<uint16_t>::WriteBigEndian(
-                &(*output_buffer)[length_field_offset], rewritten_size);
+                &output_buffer[length_field_offset], rewritten_size);
           }
 
+          parsed_payload->video_payload.SetData(output_buffer.data(),
+                                                output_buffer.size());
           // Append rest of packet.
-          output_buffer->AppendData(&payload_data[end_offset],
-                                    nalu_length + kNalHeaderSize - end_offset);
+          parsed_payload->video_payload.AppendData(
+              &payload_data[end_offset],
+              nalu_length + kNalHeaderSize - end_offset);
 
-          modified_buffer_ = std::move(output_buffer);
-          length_ = modified_buffer_->size();
+          modified_buffer = true;
         }
 
         if (sps) {
-          parsed_payload->video_header().width = sps->width;
-          parsed_payload->video_header().height = sps->height;
+          parsed_payload->video_header.width = sps->width;
+          parsed_payload->video_header.height = sps->height;
           nalu.sps_id = sps->id;
         } else {
           RTC_LOG(LS_WARNING) << "Failed to parse SPS id from SPS slice.";
         }
-        parsed_payload->video_header().frame_type =
+        parsed_payload->video_header.frame_type =
             VideoFrameType::kVideoFrameKey;
         break;
       }
@@ -194,7 +195,7 @@
         break;
       }
       case H264::NaluType::kIdr:
-        parsed_payload->video_header().frame_type =
+        parsed_payload->video_header.frame_type =
             VideoFrameType::kVideoFrameKey;
         RTC_FALLTHROUGH();
       case H264::NaluType::kSlice: {
@@ -218,7 +219,7 @@
       case H264::NaluType::kStapA:
       case H264::NaluType::kFuA:
         RTC_LOG(LS_WARNING) << "Unexpected STAP-A or FU-A received.";
-        return false;
+        return absl::nullopt;
     }
 
     if (h264_header.nalus_length == kMaxNalusPerPacket) {
@@ -230,28 +231,28 @@
     }
   }
 
-  return true;
+  return parsed_payload;
 }
 
-bool RtpDepacketizerH264::ParseFuaNalu(
-    RtpDepacketizer::ParsedPayload* parsed_payload,
-    const uint8_t* payload_data) {
-  if (length_ < kFuAHeaderSize) {
+absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> ParseFuaNalu(
+    rtc::CopyOnWriteBuffer rtp_payload) {
+  if (rtp_payload.size() < kFuAHeaderSize) {
     RTC_LOG(LS_ERROR) << "FU-A NAL units truncated.";
-    return false;
+    return absl::nullopt;
   }
-  uint8_t fnri = payload_data[0] & (kFBit | kNriMask);
-  uint8_t original_nal_type = payload_data[1] & kTypeMask;
-  bool first_fragment = (payload_data[1] & kSBit) > 0;
+  absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed_payload(
+      absl::in_place);
+  uint8_t fnri = rtp_payload.cdata()[0] & (kFBit | kNriMask);
+  uint8_t original_nal_type = rtp_payload.cdata()[1] & kTypeMask;
+  bool first_fragment = (rtp_payload.cdata()[1] & kSBit) > 0;
   NaluInfo nalu;
   nalu.type = original_nal_type;
   nalu.sps_id = -1;
   nalu.pps_id = -1;
   if (first_fragment) {
-    offset_ = 0;
-    length_ -= kNalHeaderSize;
-    absl::optional<uint32_t> pps_id = PpsParser::ParsePpsIdFromSlice(
-        payload_data + 2 * kNalHeaderSize, length_ - kNalHeaderSize);
+    absl::optional<uint32_t> pps_id =
+        PpsParser::ParsePpsIdFromSlice(rtp_payload.cdata() + 2 * kNalHeaderSize,
+                                       rtp_payload.size() - 2 * kNalHeaderSize);
     if (pps_id) {
       nalu.pps_id = *pps_id;
     } else {
@@ -261,70 +262,55 @@
           << static_cast<int>(nalu.type);
     }
     uint8_t original_nal_header = fnri | original_nal_type;
-    modified_buffer_.reset(new rtc::Buffer());
-    modified_buffer_->AppendData(payload_data + kNalHeaderSize, length_);
-    (*modified_buffer_)[0] = original_nal_header;
+    rtp_payload =
+        rtp_payload.Slice(kNalHeaderSize, rtp_payload.size() - kNalHeaderSize);
+    rtp_payload[0] = original_nal_header;
+    parsed_payload->video_payload = std::move(rtp_payload);
   } else {
-    offset_ = kFuAHeaderSize;
-    length_ -= kFuAHeaderSize;
+    parsed_payload->video_payload =
+        rtp_payload.Slice(kFuAHeaderSize, rtp_payload.size() - kFuAHeaderSize);
   }
 
   if (original_nal_type == H264::NaluType::kIdr) {
-    parsed_payload->video_header().frame_type = VideoFrameType::kVideoFrameKey;
+    parsed_payload->video_header.frame_type = VideoFrameType::kVideoFrameKey;
   } else {
-    parsed_payload->video_header().frame_type =
-        VideoFrameType::kVideoFrameDelta;
+    parsed_payload->video_header.frame_type = VideoFrameType::kVideoFrameDelta;
   }
-  parsed_payload->video_header().width = 0;
-  parsed_payload->video_header().height = 0;
-  parsed_payload->video_header().codec = kVideoCodecH264;
-  parsed_payload->video_header().simulcastIdx = 0;
-  parsed_payload->video_header().is_first_packet_in_frame = first_fragment;
-  auto& h264_header = absl::get<RTPVideoHeaderH264>(
-      parsed_payload->video_header().video_type_header);
+  parsed_payload->video_header.width = 0;
+  parsed_payload->video_header.height = 0;
+  parsed_payload->video_header.codec = kVideoCodecH264;
+  parsed_payload->video_header.simulcastIdx = 0;
+  parsed_payload->video_header.is_first_packet_in_frame = first_fragment;
+  auto& h264_header = parsed_payload->video_header.video_type_header
+                          .emplace<RTPVideoHeaderH264>();
   h264_header.packetization_type = kH264FuA;
   h264_header.nalu_type = original_nal_type;
   if (first_fragment) {
     h264_header.nalus[h264_header.nalus_length] = nalu;
     h264_header.nalus_length = 1;
   }
-  return true;
+  return parsed_payload;
 }
 
-bool RtpDepacketizerH264::Parse(ParsedPayload* parsed_payload,
-                                const uint8_t* payload_data,
-                                size_t payload_data_length) {
-  RTC_CHECK(parsed_payload != nullptr);
-  if (payload_data_length == 0) {
+}  // namespace
+
+absl::optional<VideoRtpDepacketizer::ParsedRtpPayload>
+VideoRtpDepacketizerH264::Parse(rtc::CopyOnWriteBuffer rtp_payload) {
+  if (rtp_payload.size() == 0) {
     RTC_LOG(LS_ERROR) << "Empty payload.";
-    return false;
+    return absl::nullopt;
   }
 
-  offset_ = 0;
-  length_ = payload_data_length;
-  modified_buffer_.reset();
+  uint8_t nal_type = rtp_payload.cdata()[0] & kTypeMask;
 
-  uint8_t nal_type = payload_data[0] & kTypeMask;
-  parsed_payload->video_header()
-      .video_type_header.emplace<RTPVideoHeaderH264>();
   if (nal_type == H264::NaluType::kFuA) {
     // Fragmented NAL units (FU-A).
-    if (!ParseFuaNalu(parsed_payload, payload_data))
-      return false;
+    return ParseFuaNalu(std::move(rtp_payload));
   } else {
     // We handle STAP-A and single NALU's the same way here. The jitter buffer
     // will depacketize the STAP-A into NAL units later.
-    // TODO(sprang): Parse STAP-A offsets here and store in fragmentation vec.
-    if (!ProcessStapAOrSingleNalu(parsed_payload, payload_data))
-      return false;
+    return ProcessStapAOrSingleNalu(std::move(rtp_payload));
   }
-
-  const uint8_t* payload =
-      modified_buffer_ ? modified_buffer_->data() : payload_data;
-
-  parsed_payload->payload = payload + offset_;
-  parsed_payload->payload_length = length_;
-  return true;
 }
 
 }  // namespace webrtc
diff --git a/modules/rtp_rtcp/source/video_rtp_depacketizer_h264.h b/modules/rtp_rtcp/source/video_rtp_depacketizer_h264.h
index 044ad03..cbea860 100644
--- a/modules/rtp_rtcp/source/video_rtp_depacketizer_h264.h
+++ b/modules/rtp_rtcp/source/video_rtp_depacketizer_h264.h
@@ -11,33 +11,17 @@
 #ifndef MODULES_RTP_RTCP_SOURCE_VIDEO_RTP_DEPACKETIZER_H264_H_
 #define MODULES_RTP_RTCP_SOURCE_VIDEO_RTP_DEPACKETIZER_H264_H_
 
-#include <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-
-#include "modules/rtp_rtcp/source/rtp_format.h"
-#include "rtc_base/buffer.h"
+#include "absl/types/optional.h"
+#include "modules/rtp_rtcp/source/video_rtp_depacketizer.h"
+#include "rtc_base/copy_on_write_buffer.h"
 
 namespace webrtc {
-class RtpDepacketizerH264 : public RtpDepacketizer {
+class VideoRtpDepacketizerH264 : public VideoRtpDepacketizer {
  public:
-  RtpDepacketizerH264();
-  ~RtpDepacketizerH264() override;
+  ~VideoRtpDepacketizerH264() override = default;
 
-  bool Parse(ParsedPayload* parsed_payload,
-             const uint8_t* payload_data,
-             size_t payload_data_length) override;
-
- private:
-  bool ParseFuaNalu(RtpDepacketizer::ParsedPayload* parsed_payload,
-                    const uint8_t* payload_data);
-  bool ProcessStapAOrSingleNalu(RtpDepacketizer::ParsedPayload* parsed_payload,
-                                const uint8_t* payload_data);
-
-  size_t offset_;
-  size_t length_;
-  std::unique_ptr<rtc::Buffer> modified_buffer_;
+  absl::optional<ParsedRtpPayload> Parse(
+      rtc::CopyOnWriteBuffer rtp_payload) override;
 };
 }  // namespace webrtc
 
diff --git a/modules/rtp_rtcp/source/video_rtp_depacketizer_h264_unittest.cc b/modules/rtp_rtcp/source/video_rtp_depacketizer_h264_unittest.cc
index d4467aa..d7e6147 100644
--- a/modules/rtp_rtcp/source/video_rtp_depacketizer_h264_unittest.cc
+++ b/modules/rtp_rtcp/source/video_rtp_depacketizer_h264_unittest.cc
@@ -10,14 +10,16 @@
 
 #include "modules/rtp_rtcp/source/video_rtp_depacketizer_h264.h"
 
-#include <memory>
+#include <cstdint>
 #include <vector>
 
+#include "absl/types/optional.h"
 #include "api/array_view.h"
 #include "common_video/h264/h264_common.h"
 #include "modules/include/module_common_types.h"
 #include "modules/rtp_rtcp/mocks/mock_rtp_rtcp.h"
 #include "modules/rtp_rtcp/source/byte_io.h"
+#include "rtc_base/copy_on_write_buffer.h"
 #include "test/gmock.h"
 #include "test/gtest.h"
 
@@ -47,67 +49,56 @@
 // Bit masks for FU (A and B) headers.
 enum FuDefs { kSBit = 0x80, kEBit = 0x40, kRBit = 0x20 };
 
-const uint8_t kOriginalSps[] = {kSps, 0x00, 0x00, 0x03, 0x03,
-                                0xF4, 0x05, 0x03, 0xC7, 0xC0};
-const uint8_t kRewrittenSps[] = {kSps, 0x00, 0x00, 0x03, 0x03, 0xF4, 0x05, 0x03,
-                                 0xC7, 0xE0, 0x1B, 0x41, 0x10, 0x8D, 0x00};
-const uint8_t kIdrOne[] = {kIdr, 0xFF, 0x00, 0x00, 0x04};
-const uint8_t kIdrTwo[] = {kIdr, 0xFF, 0x00, 0x11};
+constexpr uint8_t kOriginalSps[] = {kSps, 0x00, 0x00, 0x03, 0x03,
+                                    0xF4, 0x05, 0x03, 0xC7, 0xC0};
+constexpr uint8_t kRewrittenSps[] = {kSps, 0x00, 0x00, 0x03, 0x03,
+                                     0xF4, 0x05, 0x03, 0xC7, 0xE0,
+                                     0x1B, 0x41, 0x10, 0x8D, 0x00};
+constexpr uint8_t kIdrOne[] = {kIdr, 0xFF, 0x00, 0x00, 0x04};
+constexpr uint8_t kIdrTwo[] = {kIdr, 0xFF, 0x00, 0x11};
 
-struct H264ParsedPayload : public RtpDepacketizer::ParsedPayload {
-  RTPVideoHeaderH264& h264() {
-    return absl::get<RTPVideoHeaderH264>(video.video_type_header);
-  }
-};
-
-class RtpDepacketizerH264Test : public ::testing::Test {
- protected:
-  RtpDepacketizerH264Test()
-      : depacketizer_(std::make_unique<RtpDepacketizerH264>()) {}
-
-  void ExpectPacket(H264ParsedPayload* parsed_payload,
-                    const uint8_t* data,
-                    size_t length) {
-    ASSERT_TRUE(parsed_payload != NULL);
-    EXPECT_THAT(std::vector<uint8_t>(
-                    parsed_payload->payload,
-                    parsed_payload->payload + parsed_payload->payload_length),
-                ::testing::ElementsAreArray(data, length));
-  }
-
-  std::unique_ptr<RtpDepacketizer> depacketizer_;
-};
-
-TEST_F(RtpDepacketizerH264Test, TestSingleNalu) {
+TEST(VideoRtpDepacketizerH264Test, SingleNalu) {
   uint8_t packet[2] = {0x05, 0xFF};  // F=0, NRI=0, Type=5 (IDR).
-  H264ParsedPayload payload;
+  rtc::CopyOnWriteBuffer rtp_payload(packet);
 
-  ASSERT_TRUE(depacketizer_->Parse(&payload, packet, sizeof(packet)));
-  ExpectPacket(&payload, packet, sizeof(packet));
-  EXPECT_EQ(VideoFrameType::kVideoFrameKey, payload.video_header().frame_type);
-  EXPECT_EQ(kVideoCodecH264, payload.video_header().codec);
-  EXPECT_TRUE(payload.video_header().is_first_packet_in_frame);
-  EXPECT_EQ(kH264SingleNalu, payload.h264().packetization_type);
-  EXPECT_EQ(kIdr, payload.h264().nalu_type);
+  VideoRtpDepacketizerH264 depacketizer;
+  absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed =
+      depacketizer.Parse(rtp_payload);
+  ASSERT_TRUE(parsed);
+
+  EXPECT_EQ(parsed->video_payload, rtp_payload);
+  EXPECT_EQ(parsed->video_header.frame_type, VideoFrameType::kVideoFrameKey);
+  EXPECT_EQ(parsed->video_header.codec, kVideoCodecH264);
+  EXPECT_TRUE(parsed->video_header.is_first_packet_in_frame);
+  const RTPVideoHeaderH264& h264 =
+      absl::get<RTPVideoHeaderH264>(parsed->video_header.video_type_header);
+  EXPECT_EQ(h264.packetization_type, kH264SingleNalu);
+  EXPECT_EQ(h264.nalu_type, kIdr);
 }
 
-TEST_F(RtpDepacketizerH264Test, TestSingleNaluSpsWithResolution) {
+TEST(VideoRtpDepacketizerH264Test, SingleNaluSpsWithResolution) {
   uint8_t packet[] = {kSps, 0x7A, 0x00, 0x1F, 0xBC, 0xD9, 0x40, 0x50,
                       0x05, 0xBA, 0x10, 0x00, 0x00, 0x03, 0x00, 0xC0,
                       0x00, 0x00, 0x03, 0x2A, 0xE0, 0xF1, 0x83, 0x25};
-  H264ParsedPayload payload;
+  rtc::CopyOnWriteBuffer rtp_payload(packet);
 
-  ASSERT_TRUE(depacketizer_->Parse(&payload, packet, sizeof(packet)));
-  ExpectPacket(&payload, packet, sizeof(packet));
-  EXPECT_EQ(VideoFrameType::kVideoFrameKey, payload.video_header().frame_type);
-  EXPECT_EQ(kVideoCodecH264, payload.video_header().codec);
-  EXPECT_TRUE(payload.video_header().is_first_packet_in_frame);
-  EXPECT_EQ(kH264SingleNalu, payload.h264().packetization_type);
-  EXPECT_EQ(1280u, payload.video_header().width);
-  EXPECT_EQ(720u, payload.video_header().height);
+  VideoRtpDepacketizerH264 depacketizer;
+  absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed =
+      depacketizer.Parse(rtp_payload);
+  ASSERT_TRUE(parsed);
+
+  EXPECT_EQ(parsed->video_payload, rtp_payload);
+  EXPECT_EQ(parsed->video_header.frame_type, VideoFrameType::kVideoFrameKey);
+  EXPECT_EQ(parsed->video_header.codec, kVideoCodecH264);
+  EXPECT_TRUE(parsed->video_header.is_first_packet_in_frame);
+  EXPECT_EQ(parsed->video_header.width, 1280u);
+  EXPECT_EQ(parsed->video_header.height, 720u);
+  const auto& h264 =
+      absl::get<RTPVideoHeaderH264>(parsed->video_header.video_type_header);
+  EXPECT_EQ(h264.packetization_type, kH264SingleNalu);
 }
 
-TEST_F(RtpDepacketizerH264Test, TestStapAKey) {
+TEST(VideoRtpDepacketizerH264Test, StapAKey) {
   // clang-format off
   const NaluInfo kExpectedNalus[] = { {H264::kSps, 0, -1},
                                       {H264::kPps, 1, 2},
@@ -124,29 +115,34 @@
                       0, 0xB, kExpectedNalus[2].type,
                         0x85, 0xB8, 0x0, 0x4, 0x0, 0x0, 0x13, 0x93, 0x12, 0x0};
   // clang-format on
+  rtc::CopyOnWriteBuffer rtp_payload(packet);
 
-  H264ParsedPayload payload;
-  ASSERT_TRUE(depacketizer_->Parse(&payload, packet, sizeof(packet)));
-  ExpectPacket(&payload, packet, sizeof(packet));
-  EXPECT_EQ(VideoFrameType::kVideoFrameKey, payload.video_header().frame_type);
-  EXPECT_EQ(kVideoCodecH264, payload.video_header().codec);
-  EXPECT_TRUE(payload.video_header().is_first_packet_in_frame);
-  const RTPVideoHeaderH264& h264 = payload.h264();
-  EXPECT_EQ(kH264StapA, h264.packetization_type);
+  VideoRtpDepacketizerH264 depacketizer;
+  absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed =
+      depacketizer.Parse(rtp_payload);
+  ASSERT_TRUE(parsed);
+
+  EXPECT_EQ(parsed->video_payload, rtp_payload);
+  EXPECT_EQ(parsed->video_header.frame_type, VideoFrameType::kVideoFrameKey);
+  EXPECT_EQ(parsed->video_header.codec, kVideoCodecH264);
+  EXPECT_TRUE(parsed->video_header.is_first_packet_in_frame);
+  const auto& h264 =
+      absl::get<RTPVideoHeaderH264>(parsed->video_header.video_type_header);
+  EXPECT_EQ(h264.packetization_type, kH264StapA);
   // NALU type for aggregated packets is the type of the first packet only.
-  EXPECT_EQ(kSps, h264.nalu_type);
-  ASSERT_EQ(3u, h264.nalus_length);
+  EXPECT_EQ(h264.nalu_type, kSps);
+  ASSERT_EQ(h264.nalus_length, 3u);
   for (size_t i = 0; i < h264.nalus_length; ++i) {
-    EXPECT_EQ(kExpectedNalus[i].type, h264.nalus[i].type)
+    EXPECT_EQ(h264.nalus[i].type, kExpectedNalus[i].type)
         << "Failed parsing nalu " << i;
-    EXPECT_EQ(kExpectedNalus[i].sps_id, h264.nalus[i].sps_id)
+    EXPECT_EQ(h264.nalus[i].sps_id, kExpectedNalus[i].sps_id)
         << "Failed parsing nalu " << i;
-    EXPECT_EQ(kExpectedNalus[i].pps_id, h264.nalus[i].pps_id)
+    EXPECT_EQ(h264.nalus[i].pps_id, kExpectedNalus[i].pps_id)
         << "Failed parsing nalu " << i;
   }
 }
 
-TEST_F(RtpDepacketizerH264Test, TestStapANaluSpsWithResolution) {
+TEST(VideoRtpDepacketizerH264Test, StapANaluSpsWithResolution) {
   uint8_t packet[] = {kStapA,  // F=0, NRI=0, Type=24.
                                // Length (2 bytes), nal header, payload.
                       0x00, 0x19, kSps, 0x7A, 0x00, 0x1F, 0xBC, 0xD9, 0x40,
@@ -154,45 +150,44 @@
                       0x00, 0x00, 0x03, 0x2A, 0xE0, 0xF1, 0x83, 0x25, 0x80,
                       0x00, 0x03, kIdr, 0xFF, 0x00, 0x00, 0x04, kIdr, 0xFF,
                       0x00, 0x11};
+  rtc::CopyOnWriteBuffer rtp_payload(packet);
 
-  H264ParsedPayload payload;
+  VideoRtpDepacketizerH264 depacketizer;
+  absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed =
+      depacketizer.Parse(rtp_payload);
+  ASSERT_TRUE(parsed);
 
-  ASSERT_TRUE(depacketizer_->Parse(&payload, packet, sizeof(packet)));
-  ExpectPacket(&payload, packet, sizeof(packet));
-  EXPECT_EQ(VideoFrameType::kVideoFrameKey, payload.video_header().frame_type);
-  EXPECT_EQ(kVideoCodecH264, payload.video_header().codec);
-  EXPECT_TRUE(payload.video_header().is_first_packet_in_frame);
-  EXPECT_EQ(kH264StapA, payload.h264().packetization_type);
-  EXPECT_EQ(1280u, payload.video_header().width);
-  EXPECT_EQ(720u, payload.video_header().height);
+  EXPECT_EQ(parsed->video_payload, rtp_payload);
+  EXPECT_EQ(parsed->video_header.frame_type, VideoFrameType::kVideoFrameKey);
+  EXPECT_EQ(parsed->video_header.codec, kVideoCodecH264);
+  EXPECT_TRUE(parsed->video_header.is_first_packet_in_frame);
+  EXPECT_EQ(parsed->video_header.width, 1280u);
+  EXPECT_EQ(parsed->video_header.height, 720u);
+  const auto& h264 =
+      absl::get<RTPVideoHeaderH264>(parsed->video_header.video_type_header);
+  EXPECT_EQ(h264.packetization_type, kH264StapA);
 }
 
-TEST_F(RtpDepacketizerH264Test, TestEmptyStapARejected) {
+TEST(VideoRtpDepacketizerH264Test, EmptyStapARejected) {
   uint8_t lone_empty_packet[] = {kStapA, 0x00, 0x00};
-
   uint8_t leading_empty_packet[] = {kStapA, 0x00, 0x00, 0x00, 0x04,
                                     kIdr,   0xFF, 0x00, 0x11};
-
   uint8_t middle_empty_packet[] = {kStapA, 0x00, 0x03, kIdr, 0xFF, 0x00, 0x00,
                                    0x00,   0x00, 0x04, kIdr, 0xFF, 0x00, 0x11};
-
   uint8_t trailing_empty_packet[] = {kStapA, 0x00, 0x03, kIdr,
                                      0xFF,   0x00, 0x00, 0x00};
 
-  H264ParsedPayload payload;
-
-  EXPECT_FALSE(depacketizer_->Parse(&payload, lone_empty_packet,
-                                    sizeof(lone_empty_packet)));
-  EXPECT_FALSE(depacketizer_->Parse(&payload, leading_empty_packet,
-                                    sizeof(leading_empty_packet)));
-  EXPECT_FALSE(depacketizer_->Parse(&payload, middle_empty_packet,
-                                    sizeof(middle_empty_packet)));
-  EXPECT_FALSE(depacketizer_->Parse(&payload, trailing_empty_packet,
-                                    sizeof(trailing_empty_packet)));
+  VideoRtpDepacketizerH264 depacketizer;
+  EXPECT_FALSE(depacketizer.Parse(rtc::CopyOnWriteBuffer(lone_empty_packet)));
+  EXPECT_FALSE(
+      depacketizer.Parse(rtc::CopyOnWriteBuffer(leading_empty_packet)));
+  EXPECT_FALSE(depacketizer.Parse(rtc::CopyOnWriteBuffer(middle_empty_packet)));
+  EXPECT_FALSE(
+      depacketizer.Parse(rtc::CopyOnWriteBuffer(trailing_empty_packet)));
 }
 
-TEST_F(RtpDepacketizerH264Test, DepacketizeWithRewriting) {
-  rtc::Buffer in_buffer;
+TEST(VideoRtpDepacketizerH264Test, DepacketizeWithRewriting) {
+  rtc::CopyOnWriteBuffer in_buffer;
   rtc::Buffer out_buffer;
 
   uint8_t kHeader[2] = {kStapA};
@@ -218,20 +213,16 @@
   out_buffer.AppendData(kHeader, 2);
   out_buffer.AppendData(kIdrTwo);
 
-  H264ParsedPayload payload;
-  EXPECT_TRUE(
-      depacketizer_->Parse(&payload, in_buffer.data(), in_buffer.size()));
-
-  std::vector<uint8_t> expected_packet_payload(
-      out_buffer.data(), &out_buffer.data()[out_buffer.size()]);
-
-  EXPECT_THAT(
-      expected_packet_payload,
-      ::testing::ElementsAreArray(payload.payload, payload.payload_length));
+  VideoRtpDepacketizerH264 depacketizer;
+  auto parsed = depacketizer.Parse(in_buffer);
+  ASSERT_TRUE(parsed);
+  EXPECT_THAT(rtc::MakeArrayView(parsed->video_payload.cdata(),
+                                 parsed->video_payload.size()),
+              ElementsAreArray(out_buffer));
 }
 
-TEST_F(RtpDepacketizerH264Test, DepacketizeWithDoubleRewriting) {
-  rtc::Buffer in_buffer;
+TEST(VideoRtpDepacketizerH264Test, DepacketizeWithDoubleRewriting) {
+  rtc::CopyOnWriteBuffer in_buffer;
   rtc::Buffer out_buffer;
 
   uint8_t kHeader[2] = {kStapA};
@@ -265,37 +256,42 @@
   out_buffer.AppendData(kHeader, 2);
   out_buffer.AppendData(kIdrTwo);
 
-  H264ParsedPayload payload;
-  EXPECT_TRUE(
-      depacketizer_->Parse(&payload, in_buffer.data(), in_buffer.size()));
-
+  VideoRtpDepacketizerH264 depacketizer;
+  auto parsed = depacketizer.Parse(in_buffer);
+  ASSERT_TRUE(parsed);
   std::vector<uint8_t> expected_packet_payload(
       out_buffer.data(), &out_buffer.data()[out_buffer.size()]);
-
-  EXPECT_THAT(
-      expected_packet_payload,
-      ::testing::ElementsAreArray(payload.payload, payload.payload_length));
+  EXPECT_THAT(rtc::MakeArrayView(parsed->video_payload.cdata(),
+                                 parsed->video_payload.size()),
+              ElementsAreArray(out_buffer));
 }
 
-TEST_F(RtpDepacketizerH264Test, TestStapADelta) {
+TEST(VideoRtpDepacketizerH264Test, StapADelta) {
   uint8_t packet[16] = {kStapA,  // F=0, NRI=0, Type=24.
                                  // Length, nal header, payload.
                         0, 0x02, kSlice, 0xFF, 0, 0x03, kSlice, 0xFF, 0x00, 0,
                         0x04, kSlice, 0xFF, 0x00, 0x11};
-  H264ParsedPayload payload;
+  rtc::CopyOnWriteBuffer rtp_payload(packet);
 
-  ASSERT_TRUE(depacketizer_->Parse(&payload, packet, sizeof(packet)));
-  ExpectPacket(&payload, packet, sizeof(packet));
-  EXPECT_EQ(VideoFrameType::kVideoFrameDelta,
-            payload.video_header().frame_type);
-  EXPECT_EQ(kVideoCodecH264, payload.video_header().codec);
-  EXPECT_TRUE(payload.video_header().is_first_packet_in_frame);
-  EXPECT_EQ(kH264StapA, payload.h264().packetization_type);
+  VideoRtpDepacketizerH264 depacketizer;
+  absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed =
+      depacketizer.Parse(rtp_payload);
+  ASSERT_TRUE(parsed);
+
+  EXPECT_EQ(parsed->video_payload.size(), rtp_payload.size());
+  EXPECT_EQ(parsed->video_payload.cdata(), rtp_payload.cdata());
+
+  EXPECT_EQ(parsed->video_header.frame_type, VideoFrameType::kVideoFrameDelta);
+  EXPECT_EQ(parsed->video_header.codec, kVideoCodecH264);
+  EXPECT_TRUE(parsed->video_header.is_first_packet_in_frame);
+  const RTPVideoHeaderH264& h264 =
+      absl::get<RTPVideoHeaderH264>(parsed->video_header.video_type_header);
+  EXPECT_EQ(h264.packetization_type, kH264StapA);
   // NALU type for aggregated packets is the type of the first packet only.
-  EXPECT_EQ(kSlice, payload.h264().nalu_type);
+  EXPECT_EQ(h264.nalu_type, kSlice);
 }
 
-TEST_F(RtpDepacketizerH264Test, TestFuA) {
+TEST(VideoRtpDepacketizerH264Test, FuA) {
   // clang-format off
   uint8_t packet1[] = {
       kFuA,          // F=0, NRI=0, Type=28.
@@ -320,107 +316,115 @@
   };
   const uint8_t kExpected3[] = {0x03};
 
-  H264ParsedPayload payload;
-
+  VideoRtpDepacketizerH264 depacketizer;
+  absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed1 =
+      depacketizer.Parse(rtc::CopyOnWriteBuffer(packet1));
+  ASSERT_TRUE(parsed1);
   // We expect that the first packet is one byte shorter since the FU-A header
   // has been replaced by the original nal header.
-  ASSERT_TRUE(depacketizer_->Parse(&payload, packet1, sizeof(packet1)));
-  ExpectPacket(&payload, kExpected1, sizeof(kExpected1));
-  EXPECT_EQ(VideoFrameType::kVideoFrameKey, payload.video_header().frame_type);
-  EXPECT_EQ(kVideoCodecH264, payload.video_header().codec);
-  EXPECT_TRUE(payload.video_header().is_first_packet_in_frame);
-  const RTPVideoHeaderH264& h264 = payload.h264();
-  EXPECT_EQ(kH264FuA, h264.packetization_type);
-  EXPECT_EQ(kIdr, h264.nalu_type);
-  ASSERT_EQ(1u, h264.nalus_length);
-  EXPECT_EQ(static_cast<H264::NaluType>(kIdr), h264.nalus[0].type);
-  EXPECT_EQ(-1, h264.nalus[0].sps_id);
-  EXPECT_EQ(0, h264.nalus[0].pps_id);
+  EXPECT_THAT(rtc::MakeArrayView(parsed1->video_payload.cdata(),
+                                 parsed1->video_payload.size()),
+              ElementsAreArray(kExpected1));
+  EXPECT_EQ(parsed1->video_header.frame_type, VideoFrameType::kVideoFrameKey);
+  EXPECT_EQ(parsed1->video_header.codec, kVideoCodecH264);
+  EXPECT_TRUE(parsed1->video_header.is_first_packet_in_frame);
+  {
+    const RTPVideoHeaderH264& h264 =
+        absl::get<RTPVideoHeaderH264>(parsed1->video_header.video_type_header);
+    EXPECT_EQ(h264.packetization_type, kH264FuA);
+    EXPECT_EQ(h264.nalu_type, kIdr);
+    ASSERT_EQ(h264.nalus_length, 1u);
+    EXPECT_EQ(h264.nalus[0].type, static_cast<H264::NaluType>(kIdr));
+    EXPECT_EQ(h264.nalus[0].sps_id, -1);
+    EXPECT_EQ(h264.nalus[0].pps_id, 0);
+  }
 
   // Following packets will be 2 bytes shorter since they will only be appended
   // onto the first packet.
-  payload = H264ParsedPayload();
-  ASSERT_TRUE(depacketizer_->Parse(&payload, packet2, sizeof(packet2)));
-  ExpectPacket(&payload, kExpected2, sizeof(kExpected2));
-  EXPECT_EQ(VideoFrameType::kVideoFrameKey, payload.video_header().frame_type);
-  EXPECT_EQ(kVideoCodecH264, payload.video_header().codec);
-  EXPECT_FALSE(payload.video_header().is_first_packet_in_frame);
+  auto parsed2 = depacketizer.Parse(rtc::CopyOnWriteBuffer(packet2));
+  EXPECT_THAT(rtc::MakeArrayView(parsed2->video_payload.cdata(),
+                                 parsed2->video_payload.size()),
+              ElementsAreArray(kExpected2));
+  EXPECT_FALSE(parsed2->video_header.is_first_packet_in_frame);
+  EXPECT_EQ(parsed2->video_header.codec, kVideoCodecH264);
   {
-    const RTPVideoHeaderH264& h264 = payload.h264();
-    EXPECT_EQ(kH264FuA, h264.packetization_type);
-    EXPECT_EQ(kIdr, h264.nalu_type);
+    const RTPVideoHeaderH264& h264 =
+        absl::get<RTPVideoHeaderH264>(parsed2->video_header.video_type_header);
+    EXPECT_EQ(h264.packetization_type, kH264FuA);
+    EXPECT_EQ(h264.nalu_type, kIdr);
     // NALU info is only expected for the first FU-A packet.
-    EXPECT_EQ(0u, h264.nalus_length);
+    EXPECT_EQ(h264.nalus_length, 0u);
   }
 
-  payload = H264ParsedPayload();
-  ASSERT_TRUE(depacketizer_->Parse(&payload, packet3, sizeof(packet3)));
-  ExpectPacket(&payload, kExpected3, sizeof(kExpected3));
-  EXPECT_EQ(VideoFrameType::kVideoFrameKey, payload.video_header().frame_type);
-  EXPECT_EQ(kVideoCodecH264, payload.video_header().codec);
-  EXPECT_FALSE(payload.video_header().is_first_packet_in_frame);
+  auto parsed3 = depacketizer.Parse(rtc::CopyOnWriteBuffer(packet3));
+  EXPECT_THAT(rtc::MakeArrayView(parsed3->video_payload.cdata(),
+                                 parsed3->video_payload.size()),
+              ElementsAreArray(kExpected3));
+  EXPECT_FALSE(parsed3->video_header.is_first_packet_in_frame);
+  EXPECT_EQ(parsed3->video_header.codec, kVideoCodecH264);
   {
-    const RTPVideoHeaderH264& h264 = payload.h264();
-    EXPECT_EQ(kH264FuA, h264.packetization_type);
-    EXPECT_EQ(kIdr, h264.nalu_type);
+    const RTPVideoHeaderH264& h264 =
+        absl::get<RTPVideoHeaderH264>(parsed3->video_header.video_type_header);
+    EXPECT_EQ(h264.packetization_type, kH264FuA);
+    EXPECT_EQ(h264.nalu_type, kIdr);
     // NALU info is only expected for the first FU-A packet.
-    ASSERT_EQ(0u, h264.nalus_length);
+    ASSERT_EQ(h264.nalus_length, 0u);
   }
 }
 
-TEST_F(RtpDepacketizerH264Test, TestEmptyPayload) {
-  // Using a wild pointer to crash on accesses from inside the depacketizer.
-  uint8_t* garbage_ptr = reinterpret_cast<uint8_t*>(0x4711);
-  H264ParsedPayload payload;
-  EXPECT_FALSE(depacketizer_->Parse(&payload, garbage_ptr, 0));
+TEST(VideoRtpDepacketizerH264Test, EmptyPayload) {
+  rtc::CopyOnWriteBuffer empty;
+  VideoRtpDepacketizerH264 depacketizer;
+  EXPECT_FALSE(depacketizer.Parse(empty));
 }
 
-TEST_F(RtpDepacketizerH264Test, TestTruncatedFuaNalu) {
+TEST(VideoRtpDepacketizerH264Test, TruncatedFuaNalu) {
   const uint8_t kPayload[] = {0x9c};
-  H264ParsedPayload payload;
-  EXPECT_FALSE(depacketizer_->Parse(&payload, kPayload, sizeof(kPayload)));
+  VideoRtpDepacketizerH264 depacketizer;
+  EXPECT_FALSE(depacketizer.Parse(rtc::CopyOnWriteBuffer(kPayload)));
 }
 
-TEST_F(RtpDepacketizerH264Test, TestTruncatedSingleStapANalu) {
+TEST(VideoRtpDepacketizerH264Test, TruncatedSingleStapANalu) {
   const uint8_t kPayload[] = {0xd8, 0x27};
-  H264ParsedPayload payload;
-  EXPECT_FALSE(depacketizer_->Parse(&payload, kPayload, sizeof(kPayload)));
+  VideoRtpDepacketizerH264 depacketizer;
+  EXPECT_FALSE(depacketizer.Parse(rtc::CopyOnWriteBuffer(kPayload)));
 }
 
-TEST_F(RtpDepacketizerH264Test, TestStapAPacketWithTruncatedNalUnits) {
+TEST(VideoRtpDepacketizerH264Test, StapAPacketWithTruncatedNalUnits) {
   const uint8_t kPayload[] = {0x58, 0xCB, 0xED, 0xDF};
-  H264ParsedPayload payload;
-  EXPECT_FALSE(depacketizer_->Parse(&payload, kPayload, sizeof(kPayload)));
+  VideoRtpDepacketizerH264 depacketizer;
+  EXPECT_FALSE(depacketizer.Parse(rtc::CopyOnWriteBuffer(kPayload)));
 }
 
-TEST_F(RtpDepacketizerH264Test, TestTruncationJustAfterSingleStapANalu) {
+TEST(VideoRtpDepacketizerH264Test, TruncationJustAfterSingleStapANalu) {
   const uint8_t kPayload[] = {0x38, 0x27, 0x27};
-  H264ParsedPayload payload;
-  EXPECT_FALSE(depacketizer_->Parse(&payload, kPayload, sizeof(kPayload)));
+  VideoRtpDepacketizerH264 depacketizer;
+  EXPECT_FALSE(depacketizer.Parse(rtc::CopyOnWriteBuffer(kPayload)));
 }
 
-TEST_F(RtpDepacketizerH264Test, TestShortSpsPacket) {
+TEST(VideoRtpDepacketizerH264Test, ShortSpsPacket) {
   const uint8_t kPayload[] = {0x27, 0x80, 0x00};
-  H264ParsedPayload payload;
-  EXPECT_TRUE(depacketizer_->Parse(&payload, kPayload, sizeof(kPayload)));
+  VideoRtpDepacketizerH264 depacketizer;
+  EXPECT_TRUE(depacketizer.Parse(rtc::CopyOnWriteBuffer(kPayload)));
 }
 
-TEST_F(RtpDepacketizerH264Test, TestSeiPacket) {
+TEST(VideoRtpDepacketizerH264Test, SeiPacket) {
   const uint8_t kPayload[] = {
       kSei,                   // F=0, NRI=0, Type=6.
       0x03, 0x03, 0x03, 0x03  // Payload.
   };
-  H264ParsedPayload payload;
-  ASSERT_TRUE(depacketizer_->Parse(&payload, kPayload, sizeof(kPayload)));
-  const RTPVideoHeaderH264& h264 = payload.h264();
-  EXPECT_EQ(VideoFrameType::kVideoFrameDelta,
-            payload.video_header().frame_type);
-  EXPECT_EQ(kH264SingleNalu, h264.packetization_type);
-  EXPECT_EQ(kSei, h264.nalu_type);
-  ASSERT_EQ(1u, h264.nalus_length);
-  EXPECT_EQ(static_cast<H264::NaluType>(kSei), h264.nalus[0].type);
-  EXPECT_EQ(-1, h264.nalus[0].sps_id);
-  EXPECT_EQ(-1, h264.nalus[0].pps_id);
+  VideoRtpDepacketizerH264 depacketizer;
+  auto parsed = depacketizer.Parse(rtc::CopyOnWriteBuffer(kPayload));
+  ASSERT_TRUE(parsed);
+  const RTPVideoHeaderH264& h264 =
+      absl::get<RTPVideoHeaderH264>(parsed->video_header.video_type_header);
+  EXPECT_EQ(parsed->video_header.frame_type, VideoFrameType::kVideoFrameDelta);
+  EXPECT_EQ(h264.packetization_type, kH264SingleNalu);
+  EXPECT_EQ(h264.nalu_type, kSei);
+  ASSERT_EQ(h264.nalus_length, 1u);
+  EXPECT_EQ(h264.nalus[0].type, static_cast<H264::NaluType>(kSei));
+  EXPECT_EQ(h264.nalus[0].sps_id, -1);
+  EXPECT_EQ(h264.nalus[0].pps_id, -1);
 }
 
 }  // namespace
diff --git a/test/fuzzers/h264_depacketizer_fuzzer.cc b/test/fuzzers/h264_depacketizer_fuzzer.cc
index 9b6455b..9712722 100644
--- a/test/fuzzers/h264_depacketizer_fuzzer.cc
+++ b/test/fuzzers/h264_depacketizer_fuzzer.cc
@@ -7,14 +7,13 @@
  *  in the file PATENTS.  All contributing project authors may
  *  be found in the AUTHORS file in the root of the source tree.
  */
-#include "modules/rtp_rtcp/source/rtp_format_h264.h"
+#include "modules/rtp_rtcp/source/video_rtp_depacketizer_h264.h"
 
 namespace webrtc {
 void FuzzOneInput(const uint8_t* data, size_t size) {
   if (size > 200000)
     return;
-  RtpDepacketizerH264 depacketizer;
-  RtpDepacketizer::ParsedPayload parsed_payload;
-  depacketizer.Parse(&parsed_payload, data, size);
+  VideoRtpDepacketizerH264 depacketizer;
+  depacketizer.Parse(rtc::CopyOnWriteBuffer(data, size));
 }
 }  // namespace webrtc