modules/video_coding refactorings

The main purpose was the interface-> include rename, but other files
were also moved, eliminating the "main" dir.

To avoid breaking downstream, the "interface" directories were copied
into a new "video_coding/include" dir. The old headers got pragma
warnings added about deprecation (a very short deprecation since I plan
to remove them as soon downstream is updated).

Other files also moved:
video_coding/main/source -> video_coding
video_coding/main/test -> video_coding/test

BUG=webrtc:5095
TESTED=Passing compile-trybots with --clobber flag:
git cl try --clobber --bot=win_compile_rel --bot=linux_compile_rel --bot=android_compile_rel --bot=mac_compile_rel --bot=ios_rel --bot=linux_gn_rel --bot=win_x64_gn_rel --bot=mac_x64_gn_rel --bot=android_gn_rel -m tryserver.webrtc

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

Review URL: https://codereview.webrtc.org/1417283007 .

Cr-Commit-Position: refs/heads/master@{#10694}
diff --git a/webrtc/modules/video_coding/session_info_unittest.cc b/webrtc/modules/video_coding/session_info_unittest.cc
new file mode 100644
index 0000000..4906048
--- /dev/null
+++ b/webrtc/modules/video_coding/session_info_unittest.cc
@@ -0,0 +1,1064 @@
+/*
+ *  Copyright (c) 2012 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.
+ */
+
+#include <string.h>
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webrtc/modules/include/module_common_types.h"
+#include "webrtc/modules/video_coding/packet.h"
+#include "webrtc/modules/video_coding/session_info.h"
+
+namespace webrtc {
+
+class TestSessionInfo : public ::testing::Test {
+ protected:
+  virtual void SetUp() {
+    memset(packet_buffer_, 0, sizeof(packet_buffer_));
+    memset(frame_buffer_, 0, sizeof(frame_buffer_));
+    session_.Reset();
+    packet_.Reset();
+    packet_.frameType = kVideoFrameDelta;
+    packet_.sizeBytes = packet_buffer_size();
+    packet_.dataPtr = packet_buffer_;
+    packet_.seqNum = 0;
+    packet_.timestamp = 0;
+    frame_data.rtt_ms = 0;
+    frame_data.rolling_average_packets_per_frame = -1;
+  }
+
+  void FillPacket(uint8_t start_value) {
+    for (size_t i = 0; i < packet_buffer_size(); ++i)
+      packet_buffer_[i] = start_value + i;
+  }
+
+  void VerifyPacket(uint8_t* start_ptr, uint8_t start_value) {
+    for (size_t j = 0; j < packet_buffer_size(); ++j) {
+      ASSERT_EQ(start_value + j, start_ptr[j]);
+    }
+  }
+
+  size_t packet_buffer_size() const {
+    return sizeof(packet_buffer_) / sizeof(packet_buffer_[0]);
+  }
+  size_t frame_buffer_size() const {
+    return sizeof(frame_buffer_) / sizeof(frame_buffer_[0]);
+  }
+
+  enum { kPacketBufferSize = 10 };
+
+  uint8_t packet_buffer_[kPacketBufferSize];
+  uint8_t frame_buffer_[10 * kPacketBufferSize];
+
+  VCMSessionInfo session_;
+  VCMPacket packet_;
+  FrameData frame_data;
+};
+
+class TestVP8Partitions : public TestSessionInfo {
+ protected:
+  enum { kMaxVP8Partitions = 9 };
+
+  virtual void SetUp() {
+    TestSessionInfo::SetUp();
+    vp8_header_ = &packet_header_.type.Video.codecHeader.VP8;
+    packet_header_.frameType = kVideoFrameDelta;
+    packet_header_.type.Video.codec = kRtpVideoVp8;
+    vp8_header_->InitRTPVideoHeaderVP8();
+    fragmentation_.VerifyAndAllocateFragmentationHeader(kMaxVP8Partitions);
+  }
+
+  bool VerifyPartition(int partition_id,
+                       int packets_expected,
+                       int start_value) {
+    EXPECT_EQ(packets_expected * packet_buffer_size(),
+              fragmentation_.fragmentationLength[partition_id]);
+    for (int i = 0; i < packets_expected; ++i) {
+      size_t packet_index = fragmentation_.fragmentationOffset[partition_id] +
+          i * packet_buffer_size();
+      if (packet_index + packet_buffer_size() > frame_buffer_size())
+        return false;
+      VerifyPacket(frame_buffer_ + packet_index, start_value + i);
+    }
+    return true;
+  }
+
+  WebRtcRTPHeader packet_header_;
+  RTPVideoHeaderVP8* vp8_header_;
+  RTPFragmentationHeader fragmentation_;
+};
+
+class TestNalUnits : public TestSessionInfo {
+ protected:
+  virtual void SetUp() {
+    TestSessionInfo::SetUp();
+    packet_.codec = kVideoCodecVP8;
+  }
+
+  bool VerifyNalu(int offset, int packets_expected, int start_value) {
+    EXPECT_GE(session_.SessionLength(),
+              packets_expected * packet_buffer_size());
+    for (int i = 0; i < packets_expected; ++i) {
+      int packet_index = (offset + i) * packet_buffer_size();
+      VerifyPacket(frame_buffer_ + packet_index, start_value + i);
+    }
+    return true;
+  }
+};
+
+class TestNackList : public TestSessionInfo {
+ protected:
+  static const size_t kMaxSeqNumListLength = 30;
+
+  virtual void SetUp() {
+    TestSessionInfo::SetUp();
+    seq_num_list_length_ = 0;
+    memset(seq_num_list_, 0, sizeof(seq_num_list_));
+  }
+
+  void BuildSeqNumList(uint16_t low,
+                       uint16_t high) {
+    size_t i = 0;
+    while (low != high + 1) {
+      EXPECT_LT(i, kMaxSeqNumListLength);
+      if (i >= kMaxSeqNumListLength) {
+        seq_num_list_length_ = kMaxSeqNumListLength;
+        return;
+      }
+      seq_num_list_[i] = low;
+      low++;
+      i++;
+    }
+    seq_num_list_length_ = i;
+  }
+
+  void VerifyAll(int value) {
+    for (int i = 0; i < seq_num_list_length_; ++i)
+      EXPECT_EQ(seq_num_list_[i], value);
+  }
+
+  int seq_num_list_[kMaxSeqNumListLength];
+  int seq_num_list_length_;
+};
+
+TEST_F(TestSessionInfo, TestSimpleAPIs) {
+  packet_.isFirstPacket = true;
+  packet_.seqNum = 0xFFFE;
+  packet_.sizeBytes = packet_buffer_size();
+  packet_.frameType = kVideoFrameKey;
+  FillPacket(0);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+  EXPECT_FALSE(session_.HaveLastPacket());
+  EXPECT_EQ(kVideoFrameKey, session_.FrameType());
+
+  packet_.isFirstPacket = false;
+  packet_.markerBit = true;
+  packet_.seqNum += 1;
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+  EXPECT_TRUE(session_.HaveLastPacket());
+  EXPECT_EQ(packet_.seqNum, session_.HighSequenceNumber());
+  EXPECT_EQ(0xFFFE, session_.LowSequenceNumber());
+
+  // Insert empty packet which will be the new high sequence number.
+  // To make things more difficult we will make sure to have a wrap here.
+  packet_.isFirstPacket = false;
+  packet_.markerBit = true;
+  packet_.seqNum  = 2;
+  packet_.sizeBytes = 0;
+  packet_.frameType = kEmptyFrame;
+  EXPECT_EQ(0,
+            session_.InsertPacket(packet_,
+                                  frame_buffer_,
+                                  kNoErrors,
+                                  frame_data));
+  EXPECT_EQ(packet_.seqNum, session_.HighSequenceNumber());
+}
+
+TEST_F(TestSessionInfo, NormalOperation) {
+  packet_.seqNum = 0xFFFF;
+  packet_.isFirstPacket = true;
+  packet_.markerBit = false;
+  FillPacket(0);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+
+  packet_.isFirstPacket = false;
+  for (int i = 1; i < 9; ++i) {
+    packet_.seqNum += 1;
+    FillPacket(i);
+    ASSERT_EQ(packet_buffer_size(),
+              static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
+                                                        kNoErrors,
+                                                        frame_data)));
+  }
+
+  packet_.seqNum += 1;
+  packet_.markerBit = true;
+  FillPacket(9);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+
+  EXPECT_EQ(10 * packet_buffer_size(), session_.SessionLength());
+  for (int i = 0; i < 10; ++i) {
+    SCOPED_TRACE("Calling VerifyPacket");
+    VerifyPacket(frame_buffer_ + i * packet_buffer_size(), i);
+  }
+}
+
+TEST_F(TestSessionInfo, ErrorsEqualDecodableState) {
+  packet_.seqNum = 0xFFFF;
+  packet_.isFirstPacket = false;
+  packet_.markerBit = false;
+  FillPacket(3);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
+                                                      kWithErrors,
+                                                      frame_data)));
+  EXPECT_TRUE(session_.decodable());
+}
+
+TEST_F(TestSessionInfo, SelectiveDecodableState) {
+  packet_.seqNum = 0xFFFF;
+  packet_.isFirstPacket = false;
+  packet_.markerBit = false;
+  FillPacket(1);
+  frame_data.rolling_average_packets_per_frame = 11;
+  frame_data.rtt_ms = 150;
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
+                                                      kSelectiveErrors,
+                                                      frame_data)));
+  EXPECT_FALSE(session_.decodable());
+
+  packet_.seqNum -= 1;
+  FillPacket(0);
+  packet_.isFirstPacket = true;
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
+                                                      kSelectiveErrors,
+                                                      frame_data)));
+  EXPECT_TRUE(session_.decodable());
+
+  packet_.isFirstPacket = false;
+  packet_.seqNum += 1;
+  for (int i = 2; i < 8; ++i) {
+    packet_.seqNum += 1;
+    FillPacket(i);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
+                                                      kSelectiveErrors,
+                                                      frame_data)));
+    EXPECT_TRUE(session_.decodable());
+  }
+
+  packet_.seqNum += 1;
+  FillPacket(8);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
+                                                      kSelectiveErrors,
+                                                      frame_data)));
+  EXPECT_TRUE(session_.decodable());
+}
+
+TEST_F(TestSessionInfo, OutOfBoundsPackets1PacketFrame) {
+  packet_.seqNum = 0x0001;
+  packet_.isFirstPacket = true;
+  packet_.markerBit = true;
+  FillPacket(1);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+
+  packet_.seqNum = 0x0004;
+  packet_.isFirstPacket = true;
+  packet_.markerBit = true;
+  FillPacket(1);
+  EXPECT_EQ(-3, session_.InsertPacket(packet_,
+                                      frame_buffer_,
+                                      kNoErrors,
+                                      frame_data));
+  packet_.seqNum = 0x0000;
+  packet_.isFirstPacket = false;
+  packet_.markerBit = false;
+  FillPacket(1);
+  EXPECT_EQ(-3, session_.InsertPacket(packet_,
+                                      frame_buffer_,
+                                      kNoErrors,
+                                      frame_data));
+}
+
+TEST_F(TestSessionInfo, SetMarkerBitOnce) {
+  packet_.seqNum = 0x0005;
+  packet_.isFirstPacket = false;
+  packet_.markerBit = true;
+  FillPacket(1);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+  ++packet_.seqNum;
+  packet_.isFirstPacket = true;
+  packet_.markerBit = true;
+  FillPacket(1);
+  EXPECT_EQ(-3, session_.InsertPacket(packet_,
+                                      frame_buffer_,
+                                      kNoErrors,
+                                      frame_data));
+}
+
+TEST_F(TestSessionInfo, OutOfBoundsPacketsBase) {
+  // Allow packets in the range 5-6.
+  packet_.seqNum = 0x0005;
+  packet_.isFirstPacket = true;
+  packet_.markerBit = false;
+  FillPacket(1);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+  // Insert an older packet with a first packet set.
+  packet_.seqNum = 0x0004;
+  packet_.isFirstPacket = true;
+  packet_.markerBit = true;
+  FillPacket(1);
+  EXPECT_EQ(-3, session_.InsertPacket(packet_,
+                                      frame_buffer_,
+                                      kNoErrors,
+                                      frame_data));
+  packet_.seqNum = 0x0006;
+  packet_.isFirstPacket = true;
+  packet_.markerBit = true;
+  FillPacket(1);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+  packet_.seqNum = 0x0008;
+  packet_.isFirstPacket = false;
+  packet_.markerBit = true;
+  FillPacket(1);
+  EXPECT_EQ(-3, session_.InsertPacket(packet_,
+                                      frame_buffer_,
+                                      kNoErrors,
+                                      frame_data));
+}
+
+TEST_F(TestSessionInfo, OutOfBoundsPacketsWrap) {
+  packet_.seqNum = 0xFFFE;
+  packet_.isFirstPacket = true;
+  packet_.markerBit = false;
+  FillPacket(1);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+
+  packet_.seqNum = 0x0004;
+  packet_.isFirstPacket = false;
+  packet_.markerBit = true;
+  FillPacket(1);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+  packet_.seqNum = 0x0002;
+  packet_.isFirstPacket = false;
+  packet_.markerBit = false;
+  FillPacket(1);
+  ASSERT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+  packet_.seqNum = 0xFFF0;
+  packet_.isFirstPacket = false;
+  packet_.markerBit = false;
+  FillPacket(1);
+  EXPECT_EQ(-3,
+            session_.InsertPacket(packet_,
+                                  frame_buffer_,
+                                  kNoErrors,
+                                  frame_data));
+  packet_.seqNum = 0x0006;
+  packet_.isFirstPacket = false;
+  packet_.markerBit = false;
+  FillPacket(1);
+  EXPECT_EQ(-3,
+            session_.InsertPacket(packet_,
+                                  frame_buffer_,
+                                  kNoErrors,
+                                  frame_data));
+}
+
+TEST_F(TestSessionInfo, OutOfBoundsOutOfOrder) {
+  // Insert out of bound regular packets, and then the first and last packet.
+  // Verify that correct bounds are maintained.
+  packet_.seqNum = 0x0003;
+  packet_.isFirstPacket = false;
+  packet_.markerBit = false;
+  FillPacket(1);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+  // Insert an older packet with a first packet set.
+  packet_.seqNum = 0x0005;
+  packet_.isFirstPacket = true;
+  packet_.markerBit = false;
+  FillPacket(1);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+  packet_.seqNum = 0x0004;
+  packet_.isFirstPacket = false;
+  packet_.markerBit = false;
+  FillPacket(1);
+  EXPECT_EQ(-3, session_.InsertPacket(packet_,
+                                      frame_buffer_,
+                                      kNoErrors,
+                                      frame_data));
+  packet_.seqNum = 0x0010;
+  packet_.isFirstPacket = false;
+  packet_.markerBit = false;
+  FillPacket(1);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+  packet_.seqNum = 0x0008;
+  packet_.isFirstPacket = false;
+  packet_.markerBit = true;
+  FillPacket(1);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+
+  packet_.seqNum = 0x0009;
+  packet_.isFirstPacket = false;
+  packet_.markerBit = false;
+  FillPacket(1);
+  EXPECT_EQ(-3, session_.InsertPacket(packet_,
+                                      frame_buffer_,
+                                      kNoErrors,
+                                      frame_data));
+}
+
+TEST_F(TestVP8Partitions, TwoPartitionsOneLoss) {
+  // Partition 0 | Partition 1
+  // [ 0 ] [ 2 ] | [ 3 ]
+  packet_header_.type.Video.isFirstPacket = true;
+  vp8_header_->beginningOfPartition = true;
+  vp8_header_->partitionId = 0;
+  packet_header_.header.markerBit = false;
+  packet_header_.header.sequenceNumber = 0;
+  FillPacket(0);
+  VCMPacket* packet = new VCMPacket(packet_buffer_, packet_buffer_size(),
+                                    packet_header_);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(*packet, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+  delete packet;
+
+  packet_header_.type.Video.isFirstPacket = false;
+  vp8_header_->partitionId = 0;
+  vp8_header_->beginningOfPartition = false;
+  packet_header_.header.markerBit = false;
+  packet_header_.header.sequenceNumber += 2;
+  FillPacket(2);
+  packet = new VCMPacket(packet_buffer_, packet_buffer_size(), packet_header_);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(*packet, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+  delete packet;
+
+  packet_header_.type.Video.isFirstPacket = false;
+  vp8_header_->partitionId = 1;
+  vp8_header_->beginningOfPartition = true;
+  packet_header_.header.markerBit = true;
+  packet_header_.header.sequenceNumber += 1;
+  FillPacket(3);
+  packet = new VCMPacket(packet_buffer_, packet_buffer_size(), packet_header_);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(*packet, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+  delete packet;
+
+  // One packet should be removed (end of partition 0).
+  EXPECT_EQ(2 * packet_buffer_size(),
+            session_.BuildVP8FragmentationHeader(
+                frame_buffer_, frame_buffer_size(), &fragmentation_));
+  SCOPED_TRACE("Calling VerifyPartition");
+  EXPECT_TRUE(VerifyPartition(0, 1, 0));
+  SCOPED_TRACE("Calling VerifyPartition");
+  EXPECT_TRUE(VerifyPartition(1, 1, 3));
+}
+
+TEST_F(TestVP8Partitions, TwoPartitionsOneLoss2) {
+  // Partition 0 | Partition 1
+  // [ 1 ] [ 2 ] | [ 3 ] [ 5 ]
+  packet_header_.type.Video.isFirstPacket = true;
+  vp8_header_->beginningOfPartition = true;
+  vp8_header_->partitionId = 0;
+  packet_header_.header.markerBit = false;
+  packet_header_.header.sequenceNumber = 1;
+  FillPacket(1);
+  VCMPacket* packet = new VCMPacket(packet_buffer_, packet_buffer_size(),
+                                    packet_header_);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(*packet, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+  delete packet;
+
+  packet_header_.type.Video.isFirstPacket = false;
+  vp8_header_->partitionId = 0;
+  vp8_header_->beginningOfPartition = false;
+  packet_header_.header.markerBit = false;
+  packet_header_.header.sequenceNumber += 1;
+  FillPacket(2);
+  packet = new VCMPacket(packet_buffer_, packet_buffer_size(), packet_header_);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(*packet, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+  delete packet;
+
+  packet_header_.type.Video.isFirstPacket = false;
+  vp8_header_->partitionId = 1;
+  vp8_header_->beginningOfPartition = true;
+  packet_header_.header.markerBit = false;
+  packet_header_.header.sequenceNumber += 1;
+  FillPacket(3);
+  packet = new VCMPacket(packet_buffer_, packet_buffer_size(), packet_header_);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(*packet, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+  delete packet;
+
+  packet_header_.type.Video.isFirstPacket = false;
+  vp8_header_->partitionId = 1;
+  vp8_header_->beginningOfPartition = false;
+  packet_header_.header.markerBit = true;
+  packet_header_.header.sequenceNumber += 2;
+  FillPacket(5);
+  packet = new VCMPacket(packet_buffer_, packet_buffer_size(), packet_header_);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(*packet, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+  delete packet;
+
+  // One packet should be removed (end of partition 2), 3 left.
+  EXPECT_EQ(3 * packet_buffer_size(),
+            session_.BuildVP8FragmentationHeader(
+                frame_buffer_, frame_buffer_size(), &fragmentation_));
+  SCOPED_TRACE("Calling VerifyPartition");
+  EXPECT_TRUE(VerifyPartition(0, 2, 1));
+  SCOPED_TRACE("Calling VerifyPartition");
+  EXPECT_TRUE(VerifyPartition(1, 1, 3));
+}
+
+TEST_F(TestVP8Partitions, TwoPartitionsNoLossWrap) {
+  // Partition 0       | Partition 1
+  // [ fffd ] [ fffe ] | [ ffff ] [ 0 ]
+  packet_header_.type.Video.isFirstPacket = true;
+  vp8_header_->beginningOfPartition = true;
+  vp8_header_->partitionId = 0;
+  packet_header_.header.markerBit = false;
+  packet_header_.header.sequenceNumber = 0xfffd;
+  FillPacket(0);
+  VCMPacket* packet = new VCMPacket(packet_buffer_, packet_buffer_size(),
+                                    packet_header_);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(*packet, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+  delete packet;
+
+  packet_header_.type.Video.isFirstPacket = false;
+  vp8_header_->partitionId = 0;
+  vp8_header_->beginningOfPartition = false;
+  packet_header_.header.markerBit = false;
+  packet_header_.header.sequenceNumber += 1;
+  FillPacket(1);
+  packet = new VCMPacket(packet_buffer_, packet_buffer_size(), packet_header_);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(*packet, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+  delete packet;
+
+  packet_header_.type.Video.isFirstPacket = false;
+  vp8_header_->partitionId = 1;
+  vp8_header_->beginningOfPartition = true;
+  packet_header_.header.markerBit = false;
+  packet_header_.header.sequenceNumber += 1;
+  FillPacket(2);
+  packet = new VCMPacket(packet_buffer_, packet_buffer_size(), packet_header_);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(*packet, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+  delete packet;
+
+  packet_header_.type.Video.isFirstPacket = false;
+  vp8_header_->partitionId = 1;
+  vp8_header_->beginningOfPartition = false;
+  packet_header_.header.markerBit = true;
+  packet_header_.header.sequenceNumber += 1;
+  FillPacket(3);
+  packet = new VCMPacket(packet_buffer_, packet_buffer_size(), packet_header_);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(*packet, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+  delete packet;
+
+  // No packet should be removed.
+  EXPECT_EQ(4 * packet_buffer_size(),
+            session_.BuildVP8FragmentationHeader(
+                frame_buffer_, frame_buffer_size(), &fragmentation_));
+  SCOPED_TRACE("Calling VerifyPartition");
+  EXPECT_TRUE(VerifyPartition(0, 2, 0));
+  SCOPED_TRACE("Calling VerifyPartition");
+  EXPECT_TRUE(VerifyPartition(1, 2, 2));
+}
+
+TEST_F(TestVP8Partitions, TwoPartitionsLossWrap) {
+  // Partition 0       | Partition 1
+  // [ fffd ] [ fffe ] | [ ffff ] [ 1 ]
+  packet_header_.type.Video.isFirstPacket = true;
+  vp8_header_->beginningOfPartition = true;
+  vp8_header_->partitionId = 0;
+  packet_header_.header.markerBit = false;
+  packet_header_.header.sequenceNumber = 0xfffd;
+  FillPacket(0);
+  VCMPacket* packet = new VCMPacket(packet_buffer_, packet_buffer_size(),
+                                    packet_header_);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(*packet, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+  delete packet;
+
+  packet_header_.type.Video.isFirstPacket = false;
+  vp8_header_->partitionId = 0;
+  vp8_header_->beginningOfPartition = false;
+  packet_header_.header.markerBit = false;
+  packet_header_.header.sequenceNumber += 1;
+  FillPacket(1);
+  packet = new VCMPacket(packet_buffer_, packet_buffer_size(), packet_header_);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(*packet, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+  delete packet;
+
+  packet_header_.type.Video.isFirstPacket = false;
+  vp8_header_->partitionId = 1;
+  vp8_header_->beginningOfPartition = true;
+  packet_header_.header.markerBit = false;
+  packet_header_.header.sequenceNumber += 1;
+  FillPacket(2);
+  packet = new VCMPacket(packet_buffer_, packet_buffer_size(), packet_header_);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(*packet, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+  delete packet;
+
+  packet_header_.type.Video.isFirstPacket = false;
+  vp8_header_->partitionId = 1;
+  vp8_header_->beginningOfPartition = false;
+  packet_header_.header.markerBit = true;
+  packet_header_.header.sequenceNumber += 2;
+  FillPacket(3);
+  packet = new VCMPacket(packet_buffer_, packet_buffer_size(), packet_header_);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(*packet, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+  delete packet;
+
+  // One packet should be removed from the last partition
+  EXPECT_EQ(3 * packet_buffer_size(),
+            session_.BuildVP8FragmentationHeader(
+                frame_buffer_, frame_buffer_size(), &fragmentation_));
+  SCOPED_TRACE("Calling VerifyPartition");
+  EXPECT_TRUE(VerifyPartition(0, 2, 0));
+  SCOPED_TRACE("Calling VerifyPartition");
+  EXPECT_TRUE(VerifyPartition(1, 1, 2));
+}
+
+
+TEST_F(TestVP8Partitions, ThreePartitionsOneMissing) {
+  // Partition 1  |Partition 2    | Partition 3
+  // [ 1 ] [ 2 ]  |               | [ 5 ] | [ 6 ]
+  packet_header_.type.Video.isFirstPacket = true;
+  vp8_header_->beginningOfPartition = true;
+  vp8_header_->partitionId = 0;
+  packet_header_.header.markerBit = false;
+  packet_header_.header.sequenceNumber = 1;
+  FillPacket(1);
+  VCMPacket* packet = new VCMPacket(packet_buffer_, packet_buffer_size(),
+                                    packet_header_);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(*packet, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+  delete packet;
+
+  packet_header_.type.Video.isFirstPacket = false;
+  vp8_header_->partitionId = 0;
+  vp8_header_->beginningOfPartition = false;
+  packet_header_.header.markerBit = false;
+  packet_header_.header.sequenceNumber += 1;
+  FillPacket(2);
+  packet = new VCMPacket(packet_buffer_, packet_buffer_size(), packet_header_);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(*packet, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+  delete packet;
+
+  packet_header_.type.Video.isFirstPacket = false;
+  vp8_header_->partitionId = 2;
+  vp8_header_->beginningOfPartition = true;
+  packet_header_.header.markerBit = false;
+  packet_header_.header.sequenceNumber += 3;
+  FillPacket(5);
+  packet = new VCMPacket(packet_buffer_, packet_buffer_size(), packet_header_);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(*packet, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+  delete packet;
+
+  packet_header_.type.Video.isFirstPacket = false;
+  vp8_header_->partitionId = 2;
+  vp8_header_->beginningOfPartition = false;
+  packet_header_.header.markerBit = true;
+  packet_header_.header.sequenceNumber += 1;
+  FillPacket(6);
+  packet = new VCMPacket(packet_buffer_, packet_buffer_size(), packet_header_);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(*packet, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+  delete packet;
+
+  // No packet should be removed.
+  EXPECT_EQ(4 * packet_buffer_size(),
+            session_.BuildVP8FragmentationHeader(
+                frame_buffer_, frame_buffer_size(), &fragmentation_));
+  SCOPED_TRACE("Calling VerifyPartition");
+  EXPECT_TRUE(VerifyPartition(0, 2, 1));
+  SCOPED_TRACE("Calling VerifyPartition");
+  EXPECT_TRUE(VerifyPartition(2, 2, 5));
+}
+
+TEST_F(TestVP8Partitions, ThreePartitionsLossInSecond) {
+  // Partition 0  |Partition 1          | Partition 2
+  // [ 1 ] [ 2 ]  |        [ 4 ] [ 5 ]  | [ 6 ] [ 7 ]
+  packet_header_.type.Video.isFirstPacket = true;
+  vp8_header_->beginningOfPartition = true;
+  vp8_header_->partitionId = 0;
+  packet_header_.header.markerBit = false;
+  packet_header_.header.sequenceNumber = 1;
+  FillPacket(1);
+  VCMPacket* packet = new VCMPacket(packet_buffer_, packet_buffer_size(),
+                                    packet_header_);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(*packet, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+  delete packet;
+
+  packet_header_.type.Video.isFirstPacket = false;
+  vp8_header_->partitionId = 0;
+  vp8_header_->beginningOfPartition = false;
+  packet_header_.header.markerBit = false;
+  packet_header_.header.sequenceNumber += 1;
+  FillPacket(2);
+  packet = new VCMPacket(packet_buffer_, packet_buffer_size(),
+                         packet_header_);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(*packet, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+  delete packet;
+
+  packet_header_.type.Video.isFirstPacket = false;
+  vp8_header_->partitionId = 1;
+  vp8_header_->beginningOfPartition = false;
+  packet_header_.header.markerBit = false;
+  packet_header_.header.sequenceNumber += 2;
+  FillPacket(4);
+  packet = new VCMPacket(packet_buffer_, packet_buffer_size(), packet_header_);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(*packet, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+  delete packet;
+
+  packet_header_.type.Video.isFirstPacket = false;
+  vp8_header_->partitionId = 1;
+  vp8_header_->beginningOfPartition = false;
+  packet_header_.header.markerBit = false;
+  packet_header_.header.sequenceNumber += 1;
+  FillPacket(5);
+  packet = new VCMPacket(packet_buffer_, packet_buffer_size(), packet_header_);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(*packet, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+  delete packet;
+
+  packet_header_.type.Video.isFirstPacket = false;
+  vp8_header_->partitionId = 2;
+  vp8_header_->beginningOfPartition = true;
+  packet_header_.header.markerBit = false;
+  packet_header_.header.sequenceNumber += 1;
+  FillPacket(6);
+  packet = new VCMPacket(packet_buffer_, packet_buffer_size(), packet_header_);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(*packet, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+  delete packet;
+
+  packet_header_.type.Video.isFirstPacket = false;
+  vp8_header_->partitionId = 2;
+  vp8_header_->beginningOfPartition = false;
+  packet_header_.header.markerBit = true;
+  packet_header_.header.sequenceNumber += 1;
+  FillPacket(7);
+  packet = new VCMPacket(packet_buffer_, packet_buffer_size(), packet_header_);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(*packet, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+  delete packet;
+
+  // 2 partitions left. 2 packets removed from second partition
+  EXPECT_EQ(4 * packet_buffer_size(),
+            session_.BuildVP8FragmentationHeader(
+                frame_buffer_, frame_buffer_size(), &fragmentation_));
+  SCOPED_TRACE("Calling VerifyPartition");
+  EXPECT_TRUE(VerifyPartition(0, 2, 1));
+  SCOPED_TRACE("Calling VerifyPartition");
+  EXPECT_TRUE(VerifyPartition(2, 2, 6));
+}
+
+TEST_F(TestVP8Partitions, AggregationOverTwoPackets) {
+  // Partition 0   | Partition 1         | Partition 2
+  // [ 0           |           ]  [ 1 ]  | [ 2 ]
+  packet_header_.type.Video.isFirstPacket = true;
+  vp8_header_->beginningOfPartition = true;
+  vp8_header_->partitionId = 0;
+  packet_header_.header.markerBit = false;
+  packet_header_.header.sequenceNumber = 0;
+  FillPacket(0);
+  VCMPacket* packet = new VCMPacket(packet_buffer_, packet_buffer_size(),
+                                    packet_header_);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(*packet, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+  delete packet;
+
+  packet_header_.type.Video.isFirstPacket = false;
+  vp8_header_->partitionId = 1;
+  vp8_header_->beginningOfPartition = false;
+  packet_header_.header.markerBit = false;
+  packet_header_.header.sequenceNumber += 1;
+  FillPacket(1);
+  packet = new VCMPacket(packet_buffer_, packet_buffer_size(), packet_header_);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(*packet, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+  delete packet;
+
+  packet_header_.type.Video.isFirstPacket = false;
+  vp8_header_->partitionId = 2;
+  vp8_header_->beginningOfPartition = true;
+  packet_header_.header.markerBit = true;
+  packet_header_.header.sequenceNumber += 1;
+  FillPacket(2);
+  packet = new VCMPacket(packet_buffer_, packet_buffer_size(), packet_header_);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(*packet, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+  delete packet;
+
+  // No packets removed.
+  EXPECT_EQ(3 * packet_buffer_size(),
+            session_.BuildVP8FragmentationHeader(
+                frame_buffer_, frame_buffer_size(), &fragmentation_));
+  SCOPED_TRACE("Calling VerifyPartition");
+  EXPECT_TRUE(VerifyPartition(0, 2, 0));
+  // This partition is aggregated in partition 0
+  SCOPED_TRACE("Calling VerifyPartition");
+  EXPECT_TRUE(VerifyPartition(1, 0, 0));
+  SCOPED_TRACE("Calling VerifyPartition");
+  EXPECT_TRUE(VerifyPartition(2, 1, 2));
+}
+
+TEST_F(TestNalUnits, OnlyReceivedEmptyPacket) {
+  packet_.isFirstPacket = false;
+  packet_.completeNALU = kNaluComplete;
+  packet_.frameType = kEmptyFrame;
+  packet_.sizeBytes = 0;
+  packet_.seqNum = 0;
+  packet_.markerBit = false;
+  EXPECT_EQ(0, session_.InsertPacket(packet_,
+                                     frame_buffer_,
+                                     kNoErrors,
+                                     frame_data));
+
+  EXPECT_EQ(0U, session_.MakeDecodable());
+  EXPECT_EQ(0U, session_.SessionLength());
+}
+
+TEST_F(TestNalUnits, OneIsolatedNaluLoss) {
+  packet_.isFirstPacket = true;
+  packet_.completeNALU = kNaluComplete;
+  packet_.seqNum = 0;
+  packet_.markerBit = false;
+  FillPacket(0);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+
+  packet_.isFirstPacket = false;
+  packet_.completeNALU = kNaluComplete;
+  packet_.seqNum += 2;
+  packet_.markerBit = true;
+  FillPacket(2);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+
+  EXPECT_EQ(0U, session_.MakeDecodable());
+  EXPECT_EQ(2 * packet_buffer_size(), session_.SessionLength());
+  SCOPED_TRACE("Calling VerifyNalu");
+  EXPECT_TRUE(VerifyNalu(0, 1, 0));
+  SCOPED_TRACE("Calling VerifyNalu");
+  EXPECT_TRUE(VerifyNalu(1, 1, 2));
+}
+
+TEST_F(TestNalUnits, LossInMiddleOfNalu) {
+  packet_.isFirstPacket = true;
+  packet_.completeNALU = kNaluComplete;
+  packet_.seqNum = 0;
+  packet_.markerBit = false;
+  FillPacket(0);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+
+  packet_.isFirstPacket = false;
+  packet_.completeNALU = kNaluEnd;
+  packet_.seqNum += 2;
+  packet_.markerBit = true;
+  FillPacket(2);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+
+  EXPECT_EQ(packet_buffer_size(), session_.MakeDecodable());
+  EXPECT_EQ(packet_buffer_size(), session_.SessionLength());
+  SCOPED_TRACE("Calling VerifyNalu");
+  EXPECT_TRUE(VerifyNalu(0, 1, 0));
+}
+
+TEST_F(TestNalUnits, StartAndEndOfLastNalUnitLost) {
+  packet_.isFirstPacket = true;
+  packet_.completeNALU = kNaluComplete;
+  packet_.seqNum = 0;
+  packet_.markerBit = false;
+  FillPacket(0);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+
+  packet_.isFirstPacket = false;
+  packet_.completeNALU = kNaluIncomplete;
+  packet_.seqNum += 2;
+  packet_.markerBit = false;
+  FillPacket(1);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+
+  EXPECT_EQ(packet_buffer_size(), session_.MakeDecodable());
+  EXPECT_EQ(packet_buffer_size(), session_.SessionLength());
+  SCOPED_TRACE("Calling VerifyNalu");
+  EXPECT_TRUE(VerifyNalu(0, 1, 0));
+}
+
+TEST_F(TestNalUnits, ReorderWrapNoLoss) {
+  packet_.seqNum = 0xFFFF;
+  packet_.isFirstPacket = false;
+  packet_.completeNALU = kNaluIncomplete;
+  packet_.seqNum += 1;
+  packet_.markerBit = false;
+  FillPacket(1);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+
+  packet_.isFirstPacket = true;
+  packet_.completeNALU = kNaluComplete;
+  packet_.seqNum -= 1;
+  packet_.markerBit = false;
+  FillPacket(0);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+
+  packet_.isFirstPacket = false;
+  packet_.completeNALU = kNaluEnd;
+  packet_.seqNum += 2;
+  packet_.markerBit = true;
+  FillPacket(2);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+
+  EXPECT_EQ(0U, session_.MakeDecodable());
+  EXPECT_EQ(3 * packet_buffer_size(), session_.SessionLength());
+  SCOPED_TRACE("Calling VerifyNalu");
+  EXPECT_TRUE(VerifyNalu(0, 1, 0));
+}
+
+TEST_F(TestNalUnits, WrapLosses) {
+  packet_.seqNum = 0xFFFF;
+  packet_.isFirstPacket = false;
+  packet_.completeNALU = kNaluIncomplete;
+  packet_.markerBit = false;
+  FillPacket(1);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+
+  packet_.isFirstPacket = false;
+  packet_.completeNALU = kNaluEnd;
+  packet_.seqNum += 2;
+  packet_.markerBit = true;
+  FillPacket(2);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+
+  EXPECT_EQ(2 * packet_buffer_size(), session_.MakeDecodable());
+  EXPECT_EQ(0U, session_.SessionLength());
+}
+
+TEST_F(TestNalUnits, ReorderWrapLosses) {
+  packet_.seqNum = 0xFFFF;
+
+  packet_.isFirstPacket = false;
+  packet_.completeNALU = kNaluEnd;
+  packet_.seqNum += 2;
+  packet_.markerBit = true;
+  FillPacket(2);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+
+  packet_.seqNum -= 2;
+  packet_.isFirstPacket = false;
+  packet_.completeNALU = kNaluIncomplete;
+  packet_.markerBit = false;
+  FillPacket(1);
+  EXPECT_EQ(packet_buffer_size(),
+            static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
+                                                      kNoErrors, frame_data)));
+
+  EXPECT_EQ(2 * packet_buffer_size(), session_.MakeDecodable());
+  EXPECT_EQ(0U, session_.SessionLength());
+}
+
+}  // namespace webrtc