Refactor VP8 de-packetizer.

It's duplicated to parse VP8 RTP packet at the moment. We firstly call
RTPPayloadParser functions to save parsed information in RTPPayload
structure, then copy them to RTP header.

This CL removes RTPPayloadParser class and directly saves parsed data in
RTP header.

R=pbos@webrtc.org, stefan@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/27449004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@7211 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/modules/modules.gyp b/webrtc/modules/modules.gyp
index f517568..4086299 100644
--- a/webrtc/modules/modules.gyp
+++ b/webrtc/modules/modules.gyp
@@ -217,7 +217,6 @@
             'rtp_rtcp/source/rtp_packet_history_unittest.cc',
             'rtp_rtcp/source/rtp_payload_registry_unittest.cc',
             'rtp_rtcp/source/rtp_rtcp_impl_unittest.cc',
-            'rtp_rtcp/source/rtp_utility_unittest.cc',
             'rtp_rtcp/source/rtp_header_extension_unittest.cc',
             'rtp_rtcp/source/rtp_sender_unittest.cc',
             'rtp_rtcp/source/vp8_partition_aggregator_unittest.cc',
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_format_vp8.cc b/webrtc/modules/rtp_rtcp/source/rtp_format_vp8.cc
index e638c36..a3d673b 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_format_vp8.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtp_format_vp8.cc
@@ -15,10 +15,223 @@
 
 #include <vector>
 
-#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
 #include "webrtc/modules/rtp_rtcp/source/vp8_partition_aggregator.h"
+#include "webrtc/system_wrappers/interface/logging.h"
 
 namespace webrtc {
+namespace {
+struct ParsedPayload {
+  ParsedPayload() : data(NULL), data_length(0) {}
+
+  const uint8_t* data;  // Start address of parsed payload data.
+  int data_length;      // Length of parsed payload data.
+};
+
+int ParseVP8PictureID(RTPVideoHeaderVP8* vp8,
+                      const uint8_t** data,
+                      int* data_length,
+                      int* parsed_bytes) {
+  assert(vp8 != NULL);
+  if (*data_length <= 0)
+    return -1;
+
+  vp8->pictureId = (**data & 0x7F);
+  if (**data & 0x80) {
+    (*data)++;
+    (*parsed_bytes)++;
+    if (--(*data_length) <= 0)
+      return -1;
+    // PictureId is 15 bits
+    vp8->pictureId = (vp8->pictureId << 8) + **data;
+  }
+  (*data)++;
+  (*parsed_bytes)++;
+  (*data_length)--;
+  return 0;
+}
+
+int ParseVP8Tl0PicIdx(RTPVideoHeaderVP8* vp8,
+                      const uint8_t** data,
+                      int* data_length,
+                      int* parsed_bytes) {
+  assert(vp8 != NULL);
+  if (*data_length <= 0)
+    return -1;
+
+  vp8->tl0PicIdx = **data;
+  (*data)++;
+  (*parsed_bytes)++;
+  (*data_length)--;
+  return 0;
+}
+
+int ParseVP8TIDAndKeyIdx(RTPVideoHeaderVP8* vp8,
+                         const uint8_t** data,
+                         int* data_length,
+                         int* parsed_bytes,
+                         bool has_tid,
+                         bool has_key_idx) {
+  assert(vp8 != NULL);
+  if (*data_length <= 0)
+    return -1;
+
+  if (has_tid) {
+    vp8->temporalIdx = ((**data >> 6) & 0x03);
+    vp8->layerSync = (**data & 0x20) ? true : false;  // Y bit
+  }
+  if (has_key_idx) {
+    vp8->keyIdx = (**data & 0x1F);
+  }
+  (*data)++;
+  (*parsed_bytes)++;
+  (*data_length)--;
+  return 0;
+}
+
+int ParseVP8Extension(RTPVideoHeaderVP8* vp8,
+                      const uint8_t* data,
+                      int data_length) {
+  assert(vp8 != NULL);
+  int parsed_bytes = 0;
+  if (data_length <= 0)
+    return -1;
+  // Optional X field is present.
+  bool has_picture_id = (*data & 0x80) ? true : false;   // I bit
+  bool has_tl0_pic_idx = (*data & 0x40) ? true : false;  // L bit
+  bool has_tid = (*data & 0x20) ? true : false;          // T bit
+  bool has_key_idx = (*data & 0x10) ? true : false;      // K bit
+
+  // Advance data and decrease remaining payload size.
+  data++;
+  parsed_bytes++;
+  data_length--;
+
+  if (has_picture_id) {
+    if (ParseVP8PictureID(vp8, &data, &data_length, &parsed_bytes) != 0) {
+      return -1;
+    }
+  }
+
+  if (has_tl0_pic_idx) {
+    if (ParseVP8Tl0PicIdx(vp8, &data, &data_length, &parsed_bytes) != 0) {
+      return -1;
+    }
+  }
+
+  if (has_tid || has_key_idx) {
+    if (ParseVP8TIDAndKeyIdx(
+            vp8, &data, &data_length, &parsed_bytes, has_tid, has_key_idx) !=
+        0) {
+      return -1;
+    }
+  }
+  return parsed_bytes;
+}
+
+int ParseVP8FrameSize(WebRtcRTPHeader* rtp_header,
+                      const uint8_t* data,
+                      int data_length) {
+  assert(rtp_header != NULL);
+  if (rtp_header->frameType != kVideoFrameKey) {
+    // Included in payload header for I-frames.
+    return 0;
+  }
+  if (data_length < 10) {
+    // For an I-frame we should always have the uncompressed VP8 header
+    // in the beginning of the partition.
+    return -1;
+  }
+  rtp_header->type.Video.width = ((data[7] << 8) + data[6]) & 0x3FFF;
+  rtp_header->type.Video.height = ((data[9] << 8) + data[8]) & 0x3FFF;
+  return 0;
+}
+
+//
+// VP8 format:
+//
+// Payload descriptor
+//       0 1 2 3 4 5 6 7
+//      +-+-+-+-+-+-+-+-+
+//      |X|R|N|S|PartID | (REQUIRED)
+//      +-+-+-+-+-+-+-+-+
+// X:   |I|L|T|K|  RSV  | (OPTIONAL)
+//      +-+-+-+-+-+-+-+-+
+// I:   |   PictureID   | (OPTIONAL)
+//      +-+-+-+-+-+-+-+-+
+// L:   |   TL0PICIDX   | (OPTIONAL)
+//      +-+-+-+-+-+-+-+-+
+// T/K: |TID:Y| KEYIDX  | (OPTIONAL)
+//      +-+-+-+-+-+-+-+-+
+//
+// Payload header (considered part of the actual payload, sent to decoder)
+//       0 1 2 3 4 5 6 7
+//      +-+-+-+-+-+-+-+-+
+//      |Size0|H| VER |P|
+//      +-+-+-+-+-+-+-+-+
+//      |      ...      |
+//      +               +
+bool ParseVP8(WebRtcRTPHeader* rtp_header,
+              const uint8_t* data,
+              int data_length,
+              ParsedPayload* payload) {
+  assert(rtp_header != NULL);
+  // Parse mandatory first byte of payload descriptor.
+  bool extension = (*data & 0x80) ? true : false;               // X bit
+  bool beginning_of_partition = (*data & 0x10) ? true : false;  // S bit
+  int partition_id = (*data & 0x0F);                            // PartID field
+
+  rtp_header->type.Video.isFirstPacket =
+      beginning_of_partition && (partition_id == 0);
+
+  rtp_header->type.Video.codecHeader.VP8.nonReference =
+      (*data & 0x20) ? true : false;  // N bit
+  rtp_header->type.Video.codecHeader.VP8.partitionId = partition_id;
+  rtp_header->type.Video.codecHeader.VP8.beginningOfPartition =
+      beginning_of_partition;
+  rtp_header->type.Video.codecHeader.VP8.pictureId = kNoPictureId;
+  rtp_header->type.Video.codecHeader.VP8.tl0PicIdx = kNoTl0PicIdx;
+  rtp_header->type.Video.codecHeader.VP8.temporalIdx = kNoTemporalIdx;
+  rtp_header->type.Video.codecHeader.VP8.layerSync = false;
+  rtp_header->type.Video.codecHeader.VP8.keyIdx = kNoKeyIdx;
+
+  if (partition_id > 8) {
+    // Weak check for corrupt data: PartID MUST NOT be larger than 8.
+    return false;
+  }
+
+  // Advance data and decrease remaining payload size.
+  data++;
+  data_length--;
+
+  if (extension) {
+    const int parsed_bytes = ParseVP8Extension(
+        &rtp_header->type.Video.codecHeader.VP8, data, data_length);
+    if (parsed_bytes < 0)
+      return false;
+    data += parsed_bytes;
+    data_length -= parsed_bytes;
+  }
+
+  if (data_length <= 0) {
+    LOG(LS_ERROR) << "Error parsing VP8 payload descriptor!";
+    return false;
+  }
+
+  // Read P bit from payload header (only at beginning of first partition).
+  if (data_length > 0 && beginning_of_partition && partition_id == 0) {
+    rtp_header->frameType = (*data & 0x01) ? kVideoFrameDelta : kVideoFrameKey;
+  } else {
+    rtp_header->frameType = kVideoFrameDelta;
+  }
+
+  if (0 != ParseVP8FrameSize(rtp_header, data, data_length)) {
+    return false;
+  }
+  payload->data = data;
+  payload->data_length = data_length;
+  return true;
+}
+}  // namespace
 
 // Define how the VP8PacketizerModes are implemented.
 // Modes are: kStrict, kAggregate, kEqualSize.
@@ -523,48 +736,15 @@
 bool RtpDepacketizerVp8::Parse(WebRtcRTPHeader* rtp_header,
                                const uint8_t* payload_data,
                                size_t payload_data_length) {
-  RtpUtility::RTPPayload parsed_packet;
-  RtpUtility::RTPPayloadParser rtp_payload_parser(
-      kRtpVideoVp8, payload_data, payload_data_length);
-
-  if (!rtp_payload_parser.Parse(parsed_packet))
+  ParsedPayload payload;
+  if (!ParseVP8(rtp_header, payload_data, payload_data_length, &payload))
     return false;
 
-  if (parsed_packet.info.VP8.dataLength == 0)
+  if (payload.data_length == 0)
     return true;
 
-  rtp_header->frameType = (parsed_packet.frameType == RtpUtility::kIFrame)
-                              ? kVideoFrameKey
-                              : kVideoFrameDelta;
-
-  RTPVideoHeaderVP8* to_header = &rtp_header->type.Video.codecHeader.VP8;
-  RtpUtility::RTPPayloadVP8* from_header = &parsed_packet.info.VP8;
-
-  rtp_header->type.Video.isFirstPacket =
-      from_header->beginningOfPartition && (from_header->partitionID == 0);
-  to_header->nonReference = from_header->nonReferenceFrame;
-  to_header->pictureId =
-      from_header->hasPictureID ? from_header->pictureID : kNoPictureId;
-  to_header->tl0PicIdx =
-      from_header->hasTl0PicIdx ? from_header->tl0PicIdx : kNoTl0PicIdx;
-  if (from_header->hasTID) {
-    to_header->temporalIdx = from_header->tID;
-    to_header->layerSync = from_header->layerSync;
-  } else {
-    to_header->temporalIdx = kNoTemporalIdx;
-    to_header->layerSync = false;
-  }
-  to_header->keyIdx = from_header->hasKeyIdx ? from_header->keyIdx : kNoKeyIdx;
-
-  rtp_header->type.Video.width = from_header->frameWidth;
-  rtp_header->type.Video.height = from_header->frameHeight;
-
-  to_header->partitionId = from_header->partitionID;
-  to_header->beginningOfPartition = from_header->beginningOfPartition;
-
-  if (callback_->OnReceivedPayloadData(parsed_packet.info.VP8.data,
-                                       parsed_packet.info.VP8.dataLength,
-                                       rtp_header) != 0) {
+  if (callback_->OnReceivedPayloadData(
+          payload.data, payload.data_length, rtp_header) != 0) {
     return false;
   }
   return true;
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_format_vp8_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtp_format_vp8_unittest.cc
index c6574e6..7a4dbcf 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_format_vp8_unittest.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtp_format_vp8_unittest.cc
@@ -12,17 +12,76 @@
  * This file includes unit tests for the VP8 packetizer.
  */
 
+#include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h"
 #include "webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h"
 #include "webrtc/modules/rtp_rtcp/source/rtp_format_vp8_test_helper.h"
 #include "webrtc/system_wrappers/interface/compile_assert.h"
 #include "webrtc/typedefs.h"
 
-#define CHECK_ARRAY_SIZE(expected_size, array)                       \
-  COMPILE_ASSERT(expected_size == sizeof(array) / sizeof(array[0]),  \
+#define CHECK_ARRAY_SIZE(expected_size, array)                      \
+  COMPILE_ASSERT(expected_size == sizeof(array) / sizeof(array[0]), \
                  check_array_size);
 
+using ::testing::_;
+using ::testing::Args;
+using ::testing::ElementsAreArray;
+using ::testing::Return;
+
 namespace webrtc {
+namespace {
+// Payload descriptor
+//       0 1 2 3 4 5 6 7
+//      +-+-+-+-+-+-+-+-+
+//      |X|R|N|S|PartID | (REQUIRED)
+//      +-+-+-+-+-+-+-+-+
+// X:   |I|L|T|K|  RSV  | (OPTIONAL)
+//      +-+-+-+-+-+-+-+-+
+// I:   |   PictureID   | (OPTIONAL)
+//      +-+-+-+-+-+-+-+-+
+// L:   |   TL0PICIDX   | (OPTIONAL)
+//      +-+-+-+-+-+-+-+-+
+// T/K: |TID:Y| KEYIDX  | (OPTIONAL)
+//      +-+-+-+-+-+-+-+-+
+//
+// Payload header
+//       0 1 2 3 4 5 6 7
+//      +-+-+-+-+-+-+-+-+
+//      |Size0|H| VER |P|
+//      +-+-+-+-+-+-+-+-+
+//      |     Size1     |
+//      +-+-+-+-+-+-+-+-+
+//      |     Size2     |
+//      +-+-+-+-+-+-+-+-+
+//      | Bytes 4..N of |
+//      | VP8 payload   |
+//      :               :
+//      +-+-+-+-+-+-+-+-+
+//      | OPTIONAL RTP  |
+//      | padding       |
+//      :               :
+//      +-+-+-+-+-+-+-+-+
+
+void VerifyBasicHeader(WebRtcRTPHeader* header, bool N, bool S, int part_id) {
+  ASSERT_TRUE(header != NULL);
+  EXPECT_EQ(N, header->type.Video.codecHeader.VP8.nonReference);
+  EXPECT_EQ(S, header->type.Video.codecHeader.VP8.beginningOfPartition);
+  EXPECT_EQ(part_id, header->type.Video.codecHeader.VP8.partitionId);
+}
+
+void VerifyExtensions(WebRtcRTPHeader* header,
+                      int16_t picture_id,   /* I */
+                      int16_t tl0_pic_idx,  /* L */
+                      uint8_t temporal_idx, /* T */
+                      int key_idx /* K */) {
+  ASSERT_TRUE(header != NULL);
+  EXPECT_EQ(picture_id, header->type.Video.codecHeader.VP8.pictureId);
+  EXPECT_EQ(tl0_pic_idx, header->type.Video.codecHeader.VP8.tl0PicIdx);
+  EXPECT_EQ(temporal_idx, header->type.Video.codecHeader.VP8.temporalIdx);
+  EXPECT_EQ(key_idx, header->type.Video.codecHeader.VP8.keyIdx);
+}
+}  // namespace
 
 class RtpPacketizerVp8Test : public ::testing::Test {
  protected:
@@ -35,7 +94,8 @@
     hdr_info_.layerSync = false;
     hdr_info_.tl0PicIdx = kNoTl0PicIdx;
     hdr_info_.keyIdx = kNoKeyIdx;
-    if (helper_ != NULL) return false;
+    if (helper_ != NULL)
+      return false;
     helper_ = new test::RtpFormatVp8TestHelper(&hdr_info_);
     return helper_->Init(partition_sizes, num_partitions);
   }
@@ -59,14 +119,17 @@
   // The expected sizes are obtained by running a verified good implementation.
   const int kExpectedSizes[] = {9, 9, 12, 11, 11, 11, 10};
   const int kExpectedPart[] = {0, 0, 1, 2, 2, 2, 2};
-  const bool kExpectedFragStart[] =
-      {true, false, true, true, false, false, false};
+  const bool kExpectedFragStart[] = {true,  false, true, true,
+                                     false, false, false};
   const int kExpectedNum = sizeof(kExpectedSizes) / sizeof(kExpectedSizes[0]);
   CHECK_ARRAY_SIZE(kExpectedNum, kExpectedPart);
   CHECK_ARRAY_SIZE(kExpectedNum, kExpectedFragStart);
 
-  helper_->GetAllPacketsAndCheck(&packetizer, kExpectedSizes, kExpectedPart,
-                                 kExpectedFragStart, kExpectedNum);
+  helper_->GetAllPacketsAndCheck(&packetizer,
+                                 kExpectedSizes,
+                                 kExpectedPart,
+                                 kExpectedFragStart,
+                                 kExpectedNum);
 }
 
 TEST_F(RtpPacketizerVp8Test, TestAggregateMode) {
@@ -89,8 +152,11 @@
   CHECK_ARRAY_SIZE(kExpectedNum, kExpectedPart);
   CHECK_ARRAY_SIZE(kExpectedNum, kExpectedFragStart);
 
-  helper_->GetAllPacketsAndCheck(&packetizer, kExpectedSizes, kExpectedPart,
-                                 kExpectedFragStart, kExpectedNum);
+  helper_->GetAllPacketsAndCheck(&packetizer,
+                                 kExpectedSizes,
+                                 kExpectedPart,
+                                 kExpectedFragStart,
+                                 kExpectedNum);
 }
 
 TEST_F(RtpPacketizerVp8Test, TestAggregateModeManyPartitions1) {
@@ -113,8 +179,11 @@
   CHECK_ARRAY_SIZE(kExpectedNum, kExpectedPart);
   CHECK_ARRAY_SIZE(kExpectedNum, kExpectedFragStart);
 
-  helper_->GetAllPacketsAndCheck(&packetizer, kExpectedSizes, kExpectedPart,
-                                 kExpectedFragStart, kExpectedNum);
+  helper_->GetAllPacketsAndCheck(&packetizer,
+                                 kExpectedSizes,
+                                 kExpectedPart,
+                                 kExpectedFragStart,
+                                 kExpectedNum);
 }
 
 TEST_F(RtpPacketizerVp8Test, TestAggregateModeManyPartitions2) {
@@ -137,8 +206,11 @@
   CHECK_ARRAY_SIZE(kExpectedNum, kExpectedPart);
   CHECK_ARRAY_SIZE(kExpectedNum, kExpectedFragStart);
 
-  helper_->GetAllPacketsAndCheck(&packetizer, kExpectedSizes, kExpectedPart,
-                                 kExpectedFragStart, kExpectedNum);
+  helper_->GetAllPacketsAndCheck(&packetizer,
+                                 kExpectedSizes,
+                                 kExpectedPart,
+                                 kExpectedFragStart,
+                                 kExpectedNum);
 }
 
 TEST_F(RtpPacketizerVp8Test, TestAggregateModeTwoLargePartitions) {
@@ -161,8 +233,11 @@
   CHECK_ARRAY_SIZE(kExpectedNum, kExpectedPart);
   CHECK_ARRAY_SIZE(kExpectedNum, kExpectedFragStart);
 
-  helper_->GetAllPacketsAndCheck(&packetizer, kExpectedSizes, kExpectedPart,
-                                 kExpectedFragStart, kExpectedNum);
+  helper_->GetAllPacketsAndCheck(&packetizer,
+                                 kExpectedSizes,
+                                 kExpectedPart,
+                                 kExpectedFragStart,
+                                 kExpectedNum);
 }
 
 // Verify that EqualSize mode is forced if fragmentation info is missing.
@@ -172,7 +247,7 @@
   ASSERT_TRUE(Init(kSizeVector, kNumPartitions));
 
   hdr_info_.pictureId = 200;  // > 0x7F should produce 2-byte PictureID
-  const int kMaxSize = 12;  // Small enough to produce 4 packets.
+  const int kMaxSize = 12;    // Small enough to produce 4 packets.
   RtpPacketizerVp8 packetizer(hdr_info_, kMaxSize);
   packetizer.SetPayloadData(
       helper_->payload_data(), helper_->payload_size(), NULL);
@@ -187,8 +262,11 @@
   CHECK_ARRAY_SIZE(kExpectedNum, kExpectedFragStart);
 
   helper_->set_sloppy_partitioning(true);
-  helper_->GetAllPacketsAndCheck(&packetizer, kExpectedSizes, kExpectedPart,
-                                 kExpectedFragStart, kExpectedNum);
+  helper_->GetAllPacketsAndCheck(&packetizer,
+                                 kExpectedSizes,
+                                 kExpectedPart,
+                                 kExpectedFragStart,
+                                 kExpectedNum);
 }
 
 // Verify that non-reference bit is set. EqualSize mode fallback is expected.
@@ -213,8 +291,11 @@
   CHECK_ARRAY_SIZE(kExpectedNum, kExpectedFragStart);
 
   helper_->set_sloppy_partitioning(true);
-  helper_->GetAllPacketsAndCheck(&packetizer, kExpectedSizes, kExpectedPart,
-                                 kExpectedFragStart, kExpectedNum);
+  helper_->GetAllPacketsAndCheck(&packetizer,
+                                 kExpectedSizes,
+                                 kExpectedPart,
+                                 kExpectedFragStart,
+                                 kExpectedNum);
 }
 
 // Verify Tl0PicIdx and TID fields, and layerSync bit.
@@ -241,8 +322,11 @@
   CHECK_ARRAY_SIZE(kExpectedNum, kExpectedPart);
   CHECK_ARRAY_SIZE(kExpectedNum, kExpectedFragStart);
 
-  helper_->GetAllPacketsAndCheck(&packetizer, kExpectedSizes, kExpectedPart,
-                                 kExpectedFragStart, kExpectedNum);
+  helper_->GetAllPacketsAndCheck(&packetizer,
+                                 kExpectedSizes,
+                                 kExpectedPart,
+                                 kExpectedFragStart,
+                                 kExpectedNum);
 }
 
 // Verify KeyIdx field.
@@ -267,8 +351,11 @@
   CHECK_ARRAY_SIZE(kExpectedNum, kExpectedPart);
   CHECK_ARRAY_SIZE(kExpectedNum, kExpectedFragStart);
 
-  helper_->GetAllPacketsAndCheck(&packetizer, kExpectedSizes, kExpectedPart,
-                                 kExpectedFragStart, kExpectedNum);
+  helper_->GetAllPacketsAndCheck(&packetizer,
+                                 kExpectedSizes,
+                                 kExpectedPart,
+                                 kExpectedFragStart,
+                                 kExpectedNum);
 }
 
 // Verify TID field and KeyIdx field in combination.
@@ -294,7 +381,202 @@
   CHECK_ARRAY_SIZE(kExpectedNum, kExpectedPart);
   CHECK_ARRAY_SIZE(kExpectedNum, kExpectedFragStart);
 
-  helper_->GetAllPacketsAndCheck(&packetizer, kExpectedSizes, kExpectedPart,
-                                 kExpectedFragStart, kExpectedNum);
+  helper_->GetAllPacketsAndCheck(&packetizer,
+                                 kExpectedSizes,
+                                 kExpectedPart,
+                                 kExpectedFragStart,
+                                 kExpectedNum);
 }
-}  // namespace
+
+class RtpDepacketizerVp8Test : public ::testing::Test {
+ protected:
+  RtpDepacketizerVp8Test()
+      : callback_(),
+        depacketizer_(RtpDepacketizer::Create(kRtpVideoVp8, &callback_)) {}
+
+  void ExpectPacket(const uint8_t* data, size_t length) {
+    EXPECT_CALL(callback_, OnReceivedPayloadData(_, length, _))
+        .With(Args<0, 1>(ElementsAreArray(data, length)))
+        .Times(1)
+        .WillOnce(Return(0));
+  }
+
+  MockRtpData callback_;
+  scoped_ptr<RtpDepacketizer> depacketizer_;
+};
+
+TEST_F(RtpDepacketizerVp8Test, BasicHeader) {
+  const uint8_t kHeaderLength = 1;
+  uint8_t packet[4] = {0};
+  packet[0] = 0x14;  // Binary 0001 0100; S = 1, PartID = 4.
+  packet[1] = 0x01;  // P frame.
+
+  WebRtcRTPHeader rtp_header;
+  memset(&rtp_header, 0, sizeof(rtp_header));
+
+  ExpectPacket(packet + kHeaderLength, sizeof(packet) - kHeaderLength);
+  EXPECT_TRUE(depacketizer_->Parse(&rtp_header, packet, sizeof(packet)));
+
+  EXPECT_EQ(kVideoFrameDelta, rtp_header.frameType);
+  VerifyBasicHeader(&rtp_header, 0, 1, 4);
+  VerifyExtensions(
+      &rtp_header, kNoPictureId, kNoTl0PicIdx, kNoTemporalIdx, kNoKeyIdx);
+}
+
+TEST_F(RtpDepacketizerVp8Test, PictureID) {
+  const uint8_t kHeaderLength1 = 3;
+  const uint8_t kHeaderLength2 = 4;
+  const uint8_t kPictureId = 17;
+  uint8_t packet[10] = {0};
+  packet[0] = 0xA0;
+  packet[1] = 0x80;
+  packet[2] = kPictureId;
+
+  WebRtcRTPHeader rtp_header;
+  memset(&rtp_header, 0, sizeof(rtp_header));
+
+  ExpectPacket(packet + kHeaderLength1, sizeof(packet) - kHeaderLength1);
+  EXPECT_TRUE(depacketizer_->Parse(&rtp_header, packet, sizeof(packet)));
+  EXPECT_EQ(kVideoFrameDelta, rtp_header.frameType);
+  VerifyBasicHeader(&rtp_header, 1, 0, 0);
+  VerifyExtensions(
+      &rtp_header, kPictureId, kNoTl0PicIdx, kNoTemporalIdx, kNoKeyIdx);
+
+  // Re-use packet, but change to long PictureID.
+  packet[2] = 0x80 | kPictureId;
+  packet[3] = kPictureId;
+  memset(&rtp_header, 0, sizeof(rtp_header));
+
+  ExpectPacket(packet + kHeaderLength2, sizeof(packet) - kHeaderLength2);
+  EXPECT_TRUE(depacketizer_->Parse(&rtp_header, packet, sizeof(packet)));
+  VerifyBasicHeader(&rtp_header, 1, 0, 0);
+  VerifyExtensions(&rtp_header,
+                   (kPictureId << 8) + kPictureId,
+                   kNoTl0PicIdx,
+                   kNoTemporalIdx,
+                   kNoKeyIdx);
+}
+
+TEST_F(RtpDepacketizerVp8Test, Tl0PicIdx) {
+  const uint8_t kHeaderLength = 3;
+  const uint8_t kTl0PicIdx = 17;
+  uint8_t packet[13] = {0};
+  packet[0] = 0x90;
+  packet[1] = 0x40;
+  packet[2] = kTl0PicIdx;
+
+  WebRtcRTPHeader rtp_header;
+  memset(&rtp_header, 0, sizeof(rtp_header));
+
+  ExpectPacket(packet + kHeaderLength, sizeof(packet) - kHeaderLength);
+  EXPECT_TRUE(depacketizer_->Parse(&rtp_header, packet, sizeof(packet)));
+  EXPECT_EQ(kVideoFrameKey, rtp_header.frameType);
+  VerifyBasicHeader(&rtp_header, 0, 1, 0);
+  VerifyExtensions(
+      &rtp_header, kNoPictureId, kTl0PicIdx, kNoTemporalIdx, kNoKeyIdx);
+}
+
+TEST_F(RtpDepacketizerVp8Test, TIDAndLayerSync) {
+  const uint8_t kHeaderLength = 3;
+  uint8_t packet[10] = {0};
+  packet[0] = 0x88;
+  packet[1] = 0x20;
+  packet[2] = 0x80;  // TID(2) + LayerSync(false)
+
+  WebRtcRTPHeader rtp_header;
+  memset(&rtp_header, 0, sizeof(rtp_header));
+
+  ExpectPacket(packet + kHeaderLength, sizeof(packet) - kHeaderLength);
+  EXPECT_TRUE(depacketizer_->Parse(&rtp_header, packet, sizeof(packet)));
+  EXPECT_EQ(kVideoFrameDelta, rtp_header.frameType);
+  VerifyBasicHeader(&rtp_header, 0, 0, 8);
+  VerifyExtensions(&rtp_header, kNoPictureId, kNoTl0PicIdx, 2, kNoKeyIdx);
+  EXPECT_FALSE(rtp_header.type.Video.codecHeader.VP8.layerSync);
+}
+
+TEST_F(RtpDepacketizerVp8Test, KeyIdx) {
+  const uint8_t kHeaderLength = 3;
+  const uint8_t kKeyIdx = 17;
+  uint8_t packet[10] = {0};
+  packet[0] = 0x88;
+  packet[1] = 0x10;  // K = 1.
+  packet[2] = kKeyIdx;
+
+  WebRtcRTPHeader rtp_header;
+  memset(&rtp_header, 0, sizeof(rtp_header));
+
+  ExpectPacket(packet + kHeaderLength, sizeof(packet) - kHeaderLength);
+  EXPECT_TRUE(depacketizer_->Parse(&rtp_header, packet, sizeof(packet)));
+  EXPECT_EQ(kVideoFrameDelta, rtp_header.frameType);
+  VerifyBasicHeader(&rtp_header, 0, 0, 8);
+  VerifyExtensions(
+      &rtp_header, kNoPictureId, kNoTl0PicIdx, kNoTemporalIdx, kKeyIdx);
+}
+
+TEST_F(RtpDepacketizerVp8Test, MultipleExtensions) {
+  const uint8_t kHeaderLength = 6;
+  uint8_t packet[10] = {0};
+  packet[0] = 0x88;
+  packet[1] = 0x80 | 0x40 | 0x20 | 0x10;
+  packet[2] = 0x80 | 17;           // PictureID, high 7 bits.
+  packet[3] = 17;                  // PictureID, low 8 bits.
+  packet[4] = 42;                  // Tl0PicIdx.
+  packet[5] = 0x40 | 0x20 | 0x11;  // TID(1) + LayerSync(true) + KEYIDX(17).
+
+  WebRtcRTPHeader rtp_header;
+  memset(&rtp_header, 0, sizeof(rtp_header));
+
+  ExpectPacket(packet + kHeaderLength, sizeof(packet) - kHeaderLength);
+  EXPECT_TRUE(depacketizer_->Parse(&rtp_header, packet, sizeof(packet)));
+  EXPECT_EQ(kVideoFrameDelta, rtp_header.frameType);
+  VerifyBasicHeader(&rtp_header, 0, 0, 8);
+  VerifyExtensions(&rtp_header, (17 << 8) + 17, 42, 1, 17);
+}
+
+TEST_F(RtpDepacketizerVp8Test, TooShortHeader) {
+  uint8_t packet[4] = {0};
+  packet[0] = 0x88;
+  packet[1] = 0x80 | 0x40 | 0x20 | 0x10;  // All extensions are enabled...
+  packet[2] = 0x80 | 17;  // ... but only 2 bytes PictureID is provided.
+  packet[3] = 17;         // PictureID, low 8 bits.
+
+  WebRtcRTPHeader rtp_header;
+  memset(&rtp_header, 0, sizeof(rtp_header));
+
+  EXPECT_FALSE(depacketizer_->Parse(&rtp_header, packet, sizeof(packet)));
+}
+
+TEST_F(RtpDepacketizerVp8Test, TestWithPacketizer) {
+  const uint8_t kHeaderLength = 5;
+  uint8_t payload[10] = {0};
+  uint8_t packet[20] = {0};
+  RTPVideoHeaderVP8 input_header;
+  input_header.nonReference = true;
+  input_header.pictureId = 300;
+  input_header.temporalIdx = 1;
+  input_header.layerSync = false;
+  input_header.tl0PicIdx = kNoTl0PicIdx;  // Disable.
+  input_header.keyIdx = 31;
+  RtpPacketizerVp8 packetizer(input_header, 20);
+  packetizer.SetPayloadData(payload, 10, NULL);
+  bool last;
+  size_t send_bytes;
+  ASSERT_TRUE(packetizer.NextPacket(packet, &send_bytes, &last));
+  ASSERT_TRUE(last);
+
+  WebRtcRTPHeader rtp_header;
+  memset(&rtp_header, 0, sizeof(rtp_header));
+
+  ExpectPacket(packet + kHeaderLength, sizeof(packet) - kHeaderLength);
+  EXPECT_TRUE(depacketizer_->Parse(&rtp_header, packet, sizeof(packet)));
+  EXPECT_EQ(kVideoFrameKey, rtp_header.frameType);
+  VerifyBasicHeader(&rtp_header, 1, 1, 0);
+  VerifyExtensions(&rtp_header,
+                   input_header.pictureId,
+                   input_header.tl0PicIdx,
+                   input_header.temporalIdx,
+                   input_header.keyIdx);
+  EXPECT_EQ(rtp_header.type.Video.codecHeader.VP8.layerSync,
+            input_header.layerSync);
+}
+}  // namespace webrtc
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.cc b/webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.cc
index 764e9ac..22fae10 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.cc
@@ -24,7 +24,6 @@
 
 using RtpUtility::GetCurrentRTP;
 using RtpUtility::Payload;
-using RtpUtility::RTPPayloadParser;
 using RtpUtility::StringCompare;
 
 RtpReceiver* RtpReceiver::CreateVideoReceiver(
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_utility.cc b/webrtc/modules/rtp_rtcp/source/rtp_utility.cc
index 95389b4..441a9c5 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_utility.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtp_utility.cc
@@ -188,33 +188,6 @@
   return 1 << exp;
 }
 
-void RTPPayload::SetType(RtpVideoCodecTypes videoType) {
-  type = videoType;
-
-  switch (type) {
-    case kRtpVideoGeneric:
-      break;
-    case kRtpVideoVp8: {
-      info.VP8.nonReferenceFrame = false;
-      info.VP8.beginningOfPartition = false;
-      info.VP8.partitionID = 0;
-      info.VP8.hasPictureID = false;
-      info.VP8.hasTl0PicIdx = false;
-      info.VP8.hasTID = false;
-      info.VP8.hasKeyIdx = false;
-      info.VP8.pictureID = -1;
-      info.VP8.tl0PicIdx = -1;
-      info.VP8.tID = -1;
-      info.VP8.layerSync = false;
-      info.VP8.frameWidth = 0;
-      info.VP8.frameHeight = 0;
-      break;
-    }
-    default:
-      break;
-  }
-}
-
 RtpHeaderParser::RtpHeaderParser(const uint8_t* rtpData,
                                  const size_t rtpDataLength)
     : _ptrRTPDataBegin(rtpData),
@@ -565,208 +538,6 @@
   }
   return num_zero_bytes;
 }
-
-RTPPayloadParser::RTPPayloadParser(const RtpVideoCodecTypes videoType,
-                                   const uint8_t* payloadData,
-                                   uint16_t payloadDataLength)
-    : _dataPtr(payloadData),
-      _dataLength(payloadDataLength),
-      _videoType(videoType) {}
-
-RTPPayloadParser::~RTPPayloadParser() {
-}
-
-bool RTPPayloadParser::Parse(RTPPayload& parsedPacket) const {
-  parsedPacket.SetType(_videoType);
-
-  switch (_videoType) {
-    case kRtpVideoGeneric:
-      return ParseGeneric(parsedPacket);
-    case kRtpVideoVp8:
-      return ParseVP8(parsedPacket);
-    default:
-      return false;
-  }
-}
-
-bool RTPPayloadParser::ParseGeneric(RTPPayload& /*parsedPacket*/) const {
-  return false;
-}
-
-//
-// VP8 format:
-//
-// Payload descriptor
-//       0 1 2 3 4 5 6 7
-//      +-+-+-+-+-+-+-+-+
-//      |X|R|N|S|PartID | (REQUIRED)
-//      +-+-+-+-+-+-+-+-+
-// X:   |I|L|T|K|  RSV  | (OPTIONAL)
-//      +-+-+-+-+-+-+-+-+
-// I:   |   PictureID   | (OPTIONAL)
-//      +-+-+-+-+-+-+-+-+
-// L:   |   TL0PICIDX   | (OPTIONAL)
-//      +-+-+-+-+-+-+-+-+
-// T/K: |TID:Y| KEYIDX  | (OPTIONAL)
-//      +-+-+-+-+-+-+-+-+
-//
-// Payload header (considered part of the actual payload, sent to decoder)
-//       0 1 2 3 4 5 6 7
-//      +-+-+-+-+-+-+-+-+
-//      |Size0|H| VER |P|
-//      +-+-+-+-+-+-+-+-+
-//      |      ...      |
-//      +               +
-
-bool RTPPayloadParser::ParseVP8(RTPPayload& parsedPacket) const {
-  RTPPayloadVP8* vp8 = &parsedPacket.info.VP8;
-  const uint8_t* dataPtr = _dataPtr;
-  int dataLength = _dataLength;
-
-  // Parse mandatory first byte of payload descriptor
-  bool extension = (*dataPtr & 0x80) ? true : false;            // X bit
-  vp8->nonReferenceFrame = (*dataPtr & 0x20) ? true : false;    // N bit
-  vp8->beginningOfPartition = (*dataPtr & 0x10) ? true : false; // S bit
-  vp8->partitionID = (*dataPtr & 0x0F);          // PartID field
-
-  if (vp8->partitionID > 8) {
-    // Weak check for corrupt data: PartID MUST NOT be larger than 8.
-    return false;
-  }
-
-  // Advance dataPtr and decrease remaining payload size
-  dataPtr++;
-  dataLength--;
-
-  if (extension) {
-    const int parsedBytes = ParseVP8Extension(vp8, dataPtr, dataLength);
-    if (parsedBytes < 0) return false;
-    dataPtr += parsedBytes;
-    dataLength -= parsedBytes;
-  }
-
-  if (dataLength <= 0) {
-    LOG(LS_ERROR) << "Error parsing VP8 payload descriptor!";
-    return false;
-  }
-
-  // Read P bit from payload header (only at beginning of first partition)
-  if (dataLength > 0 && vp8->beginningOfPartition && vp8->partitionID == 0) {
-    parsedPacket.frameType = (*dataPtr & 0x01) ? kPFrame : kIFrame;
-  } else {
-    parsedPacket.frameType = kPFrame;
-  }
-  if (0 != ParseVP8FrameSize(parsedPacket, dataPtr, dataLength)) {
-    return false;
-  }
-  parsedPacket.info.VP8.data       = dataPtr;
-  parsedPacket.info.VP8.dataLength = dataLength;
-  return true;
-}
-
-int RTPPayloadParser::ParseVP8FrameSize(RTPPayload& parsedPacket,
-                                        const uint8_t* dataPtr,
-                                        int dataLength) const {
-  if (parsedPacket.frameType != kIFrame) {
-    // Included in payload header for I-frames.
-    return 0;
-  }
-  if (dataLength < 10) {
-    // For an I-frame we should always have the uncompressed VP8 header
-    // in the beginning of the partition.
-    return -1;
-  }
-  RTPPayloadVP8* vp8 = &parsedPacket.info.VP8;
-  vp8->frameWidth = ((dataPtr[7] << 8) + dataPtr[6]) & 0x3FFF;
-  vp8->frameHeight = ((dataPtr[9] << 8) + dataPtr[8]) & 0x3FFF;
-  return 0;
-}
-
-int RTPPayloadParser::ParseVP8Extension(RTPPayloadVP8* vp8,
-                                        const uint8_t* dataPtr,
-                                        int dataLength) const {
-  int parsedBytes = 0;
-  if (dataLength <= 0) return -1;
-  // Optional X field is present
-  vp8->hasPictureID = (*dataPtr & 0x80) ? true : false; // I bit
-  vp8->hasTl0PicIdx = (*dataPtr & 0x40) ? true : false; // L bit
-  vp8->hasTID = (*dataPtr & 0x20) ? true : false;       // T bit
-  vp8->hasKeyIdx = (*dataPtr & 0x10) ? true : false;    // K bit
-
-  // Advance dataPtr and decrease remaining payload size
-  dataPtr++;
-  parsedBytes++;
-  dataLength--;
-
-  if (vp8->hasPictureID) {
-    if (ParseVP8PictureID(vp8, &dataPtr, &dataLength, &parsedBytes) != 0) {
-      return -1;
-    }
-  }
-
-  if (vp8->hasTl0PicIdx) {
-    if (ParseVP8Tl0PicIdx(vp8, &dataPtr, &dataLength, &parsedBytes) != 0) {
-      return -1;
-    }
-  }
-
-  if (vp8->hasTID || vp8->hasKeyIdx) {
-    if (ParseVP8TIDAndKeyIdx(vp8, &dataPtr, &dataLength, &parsedBytes) != 0) {
-      return -1;
-    }
-  }
-  return parsedBytes;
-}
-
-int RTPPayloadParser::ParseVP8PictureID(RTPPayloadVP8* vp8,
-                                        const uint8_t** dataPtr,
-                                        int* dataLength,
-                                        int* parsedBytes) const {
-  if (*dataLength <= 0) return -1;
-  vp8->pictureID = (**dataPtr & 0x7F);
-  if (**dataPtr & 0x80) {
-    (*dataPtr)++;
-    (*parsedBytes)++;
-    if (--(*dataLength) <= 0) return -1;
-    // PictureID is 15 bits
-    vp8->pictureID = (vp8->pictureID << 8) +** dataPtr;
-  }
-  (*dataPtr)++;
-  (*parsedBytes)++;
-  (*dataLength)--;
-  return 0;
-}
-
-int RTPPayloadParser::ParseVP8Tl0PicIdx(RTPPayloadVP8* vp8,
-                                        const uint8_t** dataPtr,
-                                        int* dataLength,
-                                        int* parsedBytes) const {
-  if (*dataLength <= 0) return -1;
-  vp8->tl0PicIdx = **dataPtr;
-  (*dataPtr)++;
-  (*parsedBytes)++;
-  (*dataLength)--;
-  return 0;
-}
-
-int RTPPayloadParser::ParseVP8TIDAndKeyIdx(RTPPayloadVP8* vp8,
-                                           const uint8_t** dataPtr,
-                                           int* dataLength,
-                                           int* parsedBytes) const {
-  if (*dataLength <= 0) return -1;
-  if (vp8->hasTID) {
-    vp8->tID = ((**dataPtr >> 6) & 0x03);
-    vp8->layerSync = (**dataPtr & 0x20) ? true : false;  // Y bit
-  }
-  if (vp8->hasKeyIdx) {
-    vp8->keyIdx = (**dataPtr & 0x1F);
-  }
-  (*dataPtr)++;
-  (*parsedBytes)++;
-  (*dataLength)--;
-  return 0;
-}
-
 }  // namespace RtpUtility
 
 }  // namespace webrtc
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_utility.h b/webrtc/modules/rtp_rtcp/source/rtp_utility.h
index ef50570..3a3ad5e 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_utility.h
+++ b/webrtc/modules/rtp_rtcp/source/rtp_utility.h
@@ -115,97 +115,7 @@
         const uint8_t* const _ptrRTPDataBegin;
         const uint8_t* const _ptrRTPDataEnd;
     };
-
-    enum FrameTypes
-    {
-        kIFrame,    // key frame
-        kPFrame         // Delta frame
-    };
-
-    struct RTPPayloadVP8
-    {
-        bool                 nonReferenceFrame;
-        bool                 beginningOfPartition;
-        int                  partitionID;
-        bool                 hasPictureID;
-        bool                 hasTl0PicIdx;
-        bool                 hasTID;
-        bool                 hasKeyIdx;
-        int                  pictureID;
-        int                  tl0PicIdx;
-        int                  tID;
-        bool                 layerSync;
-        int                  keyIdx;
-        int                  frameWidth;
-        int                  frameHeight;
-
-        const uint8_t*   data;
-        uint16_t         dataLength;
-    };
-
-    union RTPPayloadUnion
-    {
-        RTPPayloadVP8   VP8;
-    };
-
-    struct RTPPayload
-    {
-        void SetType(RtpVideoCodecTypes videoType);
-
-        RtpVideoCodecTypes  type;
-        FrameTypes          frameType;
-        RTPPayloadUnion     info;
-    };
-
-    // RTP payload parser
-    class RTPPayloadParser
-    {
-    public:
-        RTPPayloadParser(const RtpVideoCodecTypes payloadType,
-                         const uint8_t* payloadData,
-                         // Length w/o padding.
-                         const uint16_t payloadDataLength);
-
-        ~RTPPayloadParser();
-
-        bool Parse(RTPPayload& parsedPacket) const;
-
-    private:
-        bool ParseGeneric(RTPPayload& parsedPacket) const;
-
-        bool ParseVP8(RTPPayload& parsedPacket) const;
-
-        int ParseVP8Extension(RTPPayloadVP8 *vp8,
-                              const uint8_t *dataPtr,
-                              int dataLength) const;
-
-        int ParseVP8PictureID(RTPPayloadVP8 *vp8,
-                              const uint8_t **dataPtr,
-                              int *dataLength,
-                              int *parsedBytes) const;
-
-        int ParseVP8Tl0PicIdx(RTPPayloadVP8 *vp8,
-                              const uint8_t **dataPtr,
-                              int *dataLength,
-                              int *parsedBytes) const;
-
-        int ParseVP8TIDAndKeyIdx(RTPPayloadVP8 *vp8,
-                                 const uint8_t **dataPtr,
-                                 int *dataLength,
-                                 int *parsedBytes) const;
-
-        int ParseVP8FrameSize(RTPPayload& parsedPacket,
-                              const uint8_t *dataPtr,
-                              int dataLength) const;
-
-    private:
-        const uint8_t*        _dataPtr;
-        const uint16_t        _dataLength;
-        const RtpVideoCodecTypes    _videoType;
-    };
-
-    }  // namespace RtpUtility
-
+}  // namespace RtpUtility
 }  // namespace webrtc
 
 #endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_UTILITY_H_
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_utility_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtp_utility_unittest.cc
deleted file mode 100644
index 82ec953..0000000
--- a/webrtc/modules/rtp_rtcp/source/rtp_utility_unittest.cc
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
- *
- *  Use of this source code is governed by a BSD-style license
- *  that can be found in the LICENSE file in the root of the source
- *  tree. An additional intellectual property rights grant can be found
- *  in the file PATENTS.  All contributing project authors may
- *  be found in the AUTHORS file in the root of the source tree.
- */
-
-/*
- * This file conatins unit tests for the RtpUtility.
- */
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h"
-#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
-#include "webrtc/typedefs.h"
-
-namespace webrtc {
-
-using RtpUtility::RTPPayloadParser;
-using RtpUtility::RTPPayload;
-using RtpUtility::RTPPayloadVP8;
-
-// Payload descriptor
-//       0 1 2 3 4 5 6 7
-//      +-+-+-+-+-+-+-+-+
-//      |X|R|N|S|PartID | (REQUIRED)
-//      +-+-+-+-+-+-+-+-+
-// X:   |I|L|T|K|  RSV  | (OPTIONAL)
-//      +-+-+-+-+-+-+-+-+
-// I:   |   PictureID   | (OPTIONAL)
-//      +-+-+-+-+-+-+-+-+
-// L:   |   TL0PICIDX   | (OPTIONAL)
-//      +-+-+-+-+-+-+-+-+
-// T/K: |TID:Y| KEYIDX  | (OPTIONAL)
-//      +-+-+-+-+-+-+-+-+
-//
-// Payload header
-//       0 1 2 3 4 5 6 7
-//      +-+-+-+-+-+-+-+-+
-//      |Size0|H| VER |P|
-//      +-+-+-+-+-+-+-+-+
-//      |     Size1     |
-//      +-+-+-+-+-+-+-+-+
-//      |     Size2     |
-//      +-+-+-+-+-+-+-+-+
-//      | Bytes 4..N of |
-//      | VP8 payload   |
-//      :               :
-//      +-+-+-+-+-+-+-+-+
-//      | OPTIONAL RTP  |
-//      | padding       |
-//      :               :
-//      +-+-+-+-+-+-+-+-+
-
-void VerifyBasicHeader(const RTPPayloadVP8 &header,
-                       bool N, bool S, int PartID) {
-  EXPECT_EQ(N, header.nonReferenceFrame);
-  EXPECT_EQ(S, header.beginningOfPartition);
-  EXPECT_EQ(PartID, header.partitionID);
-}
-
-void VerifyExtensions(const RTPPayloadVP8 &header,
-                      bool I, bool L, bool T, bool K) {
-  EXPECT_EQ(I, header.hasPictureID);
-  EXPECT_EQ(L, header.hasTl0PicIdx);
-  EXPECT_EQ(T, header.hasTID);
-  EXPECT_EQ(K, header.hasKeyIdx);
-}
-
-TEST(ParseVP8Test, BasicHeader) {
-  uint8_t payload[4] = {0};
-  payload[0] = 0x14;  // Binary 0001 0100; S = 1, PartID = 4.
-  payload[1] = 0x01;  // P frame.
-
-  RTPPayloadParser rtpPayloadParser(kRtpVideoVp8, payload, 4);
-
-  RTPPayload parsedPacket;
-  ASSERT_TRUE(rtpPayloadParser.Parse(parsedPacket));
-
-  EXPECT_EQ(RtpUtility::kPFrame, parsedPacket.frameType);
-  EXPECT_EQ(kRtpVideoVp8, parsedPacket.type);
-
-  VerifyBasicHeader(parsedPacket.info.VP8, 0 /*N*/, 1 /*S*/, 4 /*PartID*/);
-  VerifyExtensions(parsedPacket.info.VP8, 0 /*I*/, 0 /*L*/, 0 /*T*/, 0 /*K*/);
-
-  EXPECT_EQ(payload + 1, parsedPacket.info.VP8.data);
-  EXPECT_EQ(4 - 1, parsedPacket.info.VP8.dataLength);
-}
-
-TEST(ParseVP8Test, PictureID) {
-  uint8_t payload[10] = {0};
-  payload[0] = 0xA0;
-  payload[1] = 0x80;
-  payload[2] = 17;
-
-  RTPPayloadParser rtpPayloadParser(kRtpVideoVp8, payload, 10);
-
-  RTPPayload parsedPacket;
-  ASSERT_TRUE(rtpPayloadParser.Parse(parsedPacket));
-
-  EXPECT_EQ(RtpUtility::kPFrame, parsedPacket.frameType);
-  EXPECT_EQ(kRtpVideoVp8, parsedPacket.type);
-
-  VerifyBasicHeader(parsedPacket.info.VP8, 1 /*N*/, 0 /*S*/, 0 /*PartID*/);
-  VerifyExtensions(parsedPacket.info.VP8, 1 /*I*/, 0 /*L*/, 0 /*T*/, 0 /*K*/);
-
-  EXPECT_EQ(17, parsedPacket.info.VP8.pictureID);
-
-  EXPECT_EQ(payload + 3, parsedPacket.info.VP8.data);
-  EXPECT_EQ(10 - 3, parsedPacket.info.VP8.dataLength);
-
-
-  // Re-use payload, but change to long PictureID.
-  payload[2] = 0x80 | 17;
-  payload[3] = 17;
-  RTPPayloadParser rtpPayloadParser2(kRtpVideoVp8, payload, 10);
-
-  ASSERT_TRUE(rtpPayloadParser2.Parse(parsedPacket));
-
-  VerifyBasicHeader(parsedPacket.info.VP8, 1 /*N*/, 0 /*S*/, 0 /*PartID*/);
-  VerifyExtensions(parsedPacket.info.VP8, 1 /*I*/, 0 /*L*/, 0 /*T*/, 0 /*K*/);
-
-  EXPECT_EQ((17<<8) + 17, parsedPacket.info.VP8.pictureID);
-
-  EXPECT_EQ(payload + 4, parsedPacket.info.VP8.data);
-  EXPECT_EQ(10 - 4, parsedPacket.info.VP8.dataLength);
-}
-
-TEST(ParseVP8Test, Tl0PicIdx) {
-  uint8_t payload[13] = {0};
-  payload[0] = 0x90;
-  payload[1] = 0x40;
-  payload[2] = 17;
-
-  RTPPayloadParser rtpPayloadParser(kRtpVideoVp8, payload, 13);
-
-  RTPPayload parsedPacket;
-  ASSERT_TRUE(rtpPayloadParser.Parse(parsedPacket));
-
-  EXPECT_EQ(RtpUtility::kIFrame, parsedPacket.frameType);
-  EXPECT_EQ(kRtpVideoVp8, parsedPacket.type);
-
-  VerifyBasicHeader(parsedPacket.info.VP8, 0 /*N*/, 1 /*S*/, 0 /*PartID*/);
-  VerifyExtensions(parsedPacket.info.VP8, 0 /*I*/, 1 /*L*/, 0 /*T*/, 0 /*K*/);
-
-  EXPECT_EQ(17, parsedPacket.info.VP8.tl0PicIdx);
-
-  EXPECT_EQ(payload + 3, parsedPacket.info.VP8.data);
-  EXPECT_EQ(13 - 3, parsedPacket.info.VP8.dataLength);
-}
-
-TEST(ParseVP8Test, TIDAndLayerSync) {
-  uint8_t payload[10] = {0};
-  payload[0] = 0x88;
-  payload[1] = 0x20;
-  payload[2] = 0x80;  // TID(2) + LayerSync(false)
-
-  RTPPayloadParser rtpPayloadParser(kRtpVideoVp8, payload, 10);
-
-  RTPPayload parsedPacket;
-  ASSERT_TRUE(rtpPayloadParser.Parse(parsedPacket));
-
-  EXPECT_EQ(RtpUtility::kPFrame, parsedPacket.frameType);
-  EXPECT_EQ(kRtpVideoVp8, parsedPacket.type);
-
-  VerifyBasicHeader(parsedPacket.info.VP8, 0 /*N*/, 0 /*S*/, 8 /*PartID*/);
-  VerifyExtensions(parsedPacket.info.VP8, 0 /*I*/, 0 /*L*/, 1 /*T*/, 0 /*K*/);
-
-  EXPECT_EQ(2, parsedPacket.info.VP8.tID);
-  EXPECT_FALSE(parsedPacket.info.VP8.layerSync);
-
-  EXPECT_EQ(payload + 3, parsedPacket.info.VP8.data);
-  EXPECT_EQ(10 - 3, parsedPacket.info.VP8.dataLength);
-}
-
-TEST(ParseVP8Test, KeyIdx) {
-  uint8_t payload[10] = {0};
-  payload[0] = 0x88;
-  payload[1] = 0x10;  // K = 1.
-  payload[2] = 0x11;  // KEYIDX = 17 decimal.
-
-  RTPPayloadParser rtpPayloadParser(kRtpVideoVp8, payload, 10);
-
-  RTPPayload parsedPacket;
-  ASSERT_TRUE(rtpPayloadParser.Parse(parsedPacket));
-
-  EXPECT_EQ(RtpUtility::kPFrame, parsedPacket.frameType);
-  EXPECT_EQ(kRtpVideoVp8, parsedPacket.type);
-
-  VerifyBasicHeader(parsedPacket.info.VP8, 0 /*N*/, 0 /*S*/, 8 /*PartID*/);
-  VerifyExtensions(parsedPacket.info.VP8, 0 /*I*/, 0 /*L*/, 0 /*T*/, 1 /*K*/);
-
-  EXPECT_EQ(17, parsedPacket.info.VP8.keyIdx);
-
-  EXPECT_EQ(payload + 3, parsedPacket.info.VP8.data);
-  EXPECT_EQ(10 - 3, parsedPacket.info.VP8.dataLength);
-}
-
-TEST(ParseVP8Test, MultipleExtensions) {
-  uint8_t payload[10] = {0};
-  payload[0] = 0x88;
-  payload[1] = 0x80 | 0x40 | 0x20 | 0x10;
-  payload[2] = 0x80 | 17;    // PictureID, high 7 bits.
-  payload[3] = 17;           // PictureID, low 8 bits.
-  payload[4] = 42;           // Tl0PicIdx.
-  payload[5] = 0x40 | 0x20 | 0x11;  // TID(1) + LayerSync(true) + KEYIDX(17).
-
-  RTPPayloadParser rtpPayloadParser(kRtpVideoVp8, payload, 10);
-
-  RTPPayload parsedPacket;
-  ASSERT_TRUE(rtpPayloadParser.Parse(parsedPacket));
-
-  EXPECT_EQ(RtpUtility::kPFrame, parsedPacket.frameType);
-  EXPECT_EQ(kRtpVideoVp8, parsedPacket.type);
-
-  VerifyBasicHeader(parsedPacket.info.VP8, 0 /*N*/, 0 /*S*/, 8 /*PartID*/);
-  VerifyExtensions(parsedPacket.info.VP8, 1 /*I*/, 1 /*L*/, 1 /*T*/, 1 /*K*/);
-
-  EXPECT_EQ((17<<8) + 17, parsedPacket.info.VP8.pictureID);
-  EXPECT_EQ(42, parsedPacket.info.VP8.tl0PicIdx);
-  EXPECT_EQ(1, parsedPacket.info.VP8.tID);
-  EXPECT_EQ(17, parsedPacket.info.VP8.keyIdx);
-
-  EXPECT_EQ(payload + 6, parsedPacket.info.VP8.data);
-  EXPECT_EQ(10 - 6, parsedPacket.info.VP8.dataLength);
-}
-
-TEST(ParseVP8Test, TooShortHeader) {
-  uint8_t payload[4] = {0};
-  payload[0] = 0x88;
-  payload[1] = 0x80 | 0x40 | 0x20 | 0x10;  // All extensions are enabled...
-  payload[2] = 0x80 | 17;  // ... but only 2 bytes PictureID is provided.
-  payload[3] = 17;  // PictureID, low 8 bits.
-
-  RTPPayloadParser rtpPayloadParser(kRtpVideoVp8, payload, 4);
-
-  RTPPayload parsedPacket;
-  EXPECT_FALSE(rtpPayloadParser.Parse(parsedPacket));
-}
-
-TEST(ParseVP8Test, TestWithPacketizer) {
-  uint8_t payload[10] = {0};
-  uint8_t packet[20] = {0};
-  RTPVideoHeaderVP8 inputHeader;
-  inputHeader.nonReference = true;
-  inputHeader.pictureId = 300;
-  inputHeader.temporalIdx = 1;
-  inputHeader.layerSync = false;
-  inputHeader.tl0PicIdx = kNoTl0PicIdx;  // Disable.
-  inputHeader.keyIdx = 31;
-  RtpPacketizerVp8 packetizer(inputHeader, 20);
-  packetizer.SetPayloadData(payload, 10, NULL);
-  bool last;
-  size_t send_bytes;
-  ASSERT_TRUE(packetizer.NextPacket(packet, &send_bytes, &last));
-  ASSERT_TRUE(last);
-
-  RTPPayloadParser rtpPayloadParser(kRtpVideoVp8, packet, send_bytes);
-
-  RTPPayload parsedPacket;
-  ASSERT_TRUE(rtpPayloadParser.Parse(parsedPacket));
-
-  EXPECT_EQ(RtpUtility::kIFrame, parsedPacket.frameType);
-  EXPECT_EQ(kRtpVideoVp8, parsedPacket.type);
-
-  VerifyBasicHeader(parsedPacket.info.VP8,
-                    inputHeader.nonReference /*N*/,
-                    1 /*S*/,
-                    0 /*PartID*/);
-  VerifyExtensions(parsedPacket.info.VP8,
-                   1 /*I*/,
-                   0 /*L*/,
-                   1 /*T*/,
-                   1 /*K*/);
-
-  EXPECT_EQ(inputHeader.pictureId, parsedPacket.info.VP8.pictureID);
-  EXPECT_EQ(inputHeader.temporalIdx, parsedPacket.info.VP8.tID);
-  EXPECT_EQ(inputHeader.layerSync, parsedPacket.info.VP8.layerSync);
-  EXPECT_EQ(inputHeader.keyIdx, parsedPacket.info.VP8.keyIdx);
-
-  EXPECT_EQ(packet + 5, parsedPacket.info.VP8.data);
-  EXPECT_EQ(send_bytes - 5, parsedPacket.info.VP8.dataLength);
-}
-
-}  // namespace