Delete in_order argument to RtpReceiver::IncomingRtpPacket

Bug: webrtc:7135
Change-Id: I35fbc76a5ca8d50caff918bbfd2cb13dce4cbd21
Reviewed-on: https://webrtc-review.googlesource.com/4141
Commit-Queue: Niels Moller <nisse@webrtc.org>
Reviewed-by: Stefan Holmer <stefan@webrtc.org>
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Reviewed-by: Fredrik Solenberg <solenberg@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20154}
diff --git a/modules/rtp_rtcp/include/rtp_receiver.h b/modules/rtp_rtcp/include/rtp_receiver.h
index 8931d78..9738116 100644
--- a/modules/rtp_rtcp/include/rtp_receiver.h
+++ b/modules/rtp_rtcp/include/rtp_receiver.h
@@ -79,8 +79,17 @@
   virtual bool IncomingRtpPacket(const RTPHeader& rtp_header,
                                  const uint8_t* payload,
                                  size_t payload_length,
-                                 PayloadUnion payload_specific,
-                                 bool in_order) = 0;
+                                 PayloadUnion payload_specific) = 0;
+  // TODO(nisse): Deprecated version, delete as soon as downstream
+  // applications are updated.
+  bool IncomingRtpPacket(const RTPHeader& rtp_header,
+                         const uint8_t* payload,
+                         size_t payload_length,
+                         PayloadUnion payload_specific,
+                         bool in_order /* Ignored */) {
+    return IncomingRtpPacket(rtp_header, payload, payload_length,
+                             payload_specific);
+  }
 
   // Gets the RTP timestamp and the corresponding monotonic system
   // time for the most recent in-order packet. Returns true on
diff --git a/modules/rtp_rtcp/source/rtp_receiver_impl.cc b/modules/rtp_rtcp/source/rtp_receiver_impl.cc
index a47aa15..792e08b 100644
--- a/modules/rtp_rtcp/source/rtp_receiver_impl.cc
+++ b/modules/rtp_rtcp/source/rtp_receiver_impl.cc
@@ -20,6 +20,7 @@
 
 #include "common_types.h"  // NOLINT(build/include)
 #include "modules/audio_coding/codecs/audio_format_conversion.h"
+#include "modules/include/module_common_types.h"
 #include "modules/rtp_rtcp/include/rtp_payload_registry.h"
 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
 #include "modules/rtp_rtcp/source/rtp_receiver_strategy.h"
@@ -27,6 +28,26 @@
 
 namespace webrtc {
 
+namespace {
+bool InOrderPacket(rtc::Optional<uint16_t> latest_sequence_number,
+                   uint16_t current_sequence_number) {
+  if (!latest_sequence_number)
+    return true;
+
+  // We need to distinguish between a late or retransmitted packet,
+  // and a sequence number discontinuity.
+  if (IsNewerSequenceNumber(current_sequence_number, *latest_sequence_number)) {
+    return true;
+  } else {
+    // If we have a restart of the remote side this packet is still in order.
+    return !IsNewerSequenceNumber(
+        current_sequence_number,
+        *latest_sequence_number - kDefaultMaxReorderingThreshold);
+  }
+}
+
+}  // namespace
+
 using RtpUtility::Payload;
 
 // Only return the sources in the last 10 seconds.
@@ -142,12 +163,10 @@
   return rtp_media_receiver_->Energy(array_of_energy);
 }
 
-bool RtpReceiverImpl::IncomingRtpPacket(
-  const RTPHeader& rtp_header,
-  const uint8_t* payload,
-  size_t payload_length,
-  PayloadUnion payload_specific,
-  bool in_order) {
+bool RtpReceiverImpl::IncomingRtpPacket(const RTPHeader& rtp_header,
+                                        const uint8_t* payload,
+                                        size_t payload_length,
+                                        PayloadUnion payload_specific) {
   // Trigger our callbacks.
   CheckSSRCChanged(rtp_header);
 
@@ -186,13 +205,18 @@
   {
     rtc::CritScope lock(&critical_section_rtp_receiver_);
 
-    if (in_order) {
-      if (last_received_timestamp_ != rtp_header.timestamp) {
-        last_received_timestamp_ = rtp_header.timestamp;
-        last_received_frame_time_ms_ = clock_->TimeInMilliseconds();
-      }
+    // TODO(nisse): Do not rely on InOrderPacket for recovered packets, when
+    // packet is passed as RtpPacketReceived and that information is available.
+    // We should ideally never record timestamps for retransmitted or recovered
+    // packets.
+    if (InOrderPacket(last_received_sequence_number_,
+                      rtp_header.sequenceNumber)) {
+      last_received_sequence_number_.emplace(rtp_header.sequenceNumber);
+      last_received_timestamp_ = rtp_header.timestamp;
+      last_received_frame_time_ms_ = clock_->TimeInMilliseconds();
     }
   }
+
   return true;
 }
 
@@ -237,7 +261,7 @@
 bool RtpReceiverImpl::GetLatestTimestamps(uint32_t* timestamp,
                                           int64_t* receive_time_ms) const {
   rtc::CritScope lock(&critical_section_rtp_receiver_);
-  if (last_received_frame_time_ms_ < 0)
+  if (!last_received_sequence_number_)
     return false;
 
   *timestamp = last_received_timestamp_;
diff --git a/modules/rtp_rtcp/source/rtp_receiver_impl.h b/modules/rtp_rtcp/source/rtp_receiver_impl.h
index 9257029..cd6b619 100644
--- a/modules/rtp_rtcp/source/rtp_receiver_impl.h
+++ b/modules/rtp_rtcp/source/rtp_receiver_impl.h
@@ -16,6 +16,7 @@
 #include <unordered_map>
 #include <vector>
 
+#include "api/optional.h"
 #include "modules/rtp_rtcp/include/rtp_receiver.h"
 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
 #include "modules/rtp_rtcp/source/rtp_receiver_strategy.h"
@@ -45,8 +46,7 @@
   bool IncomingRtpPacket(const RTPHeader& rtp_header,
                          const uint8_t* payload,
                          size_t payload_length,
-                         PayloadUnion payload_specific,
-                         bool in_order) override;
+                         PayloadUnion payload_specific) override;
 
   bool GetLatestTimestamps(uint32_t* timestamp,
                            int64_t* receive_time_ms) const override;
@@ -95,6 +95,9 @@
   uint32_t current_remote_csrc_[kRtpCsrcSize] RTC_GUARDED_BY(
       critical_section_rtp_receiver_);
 
+  // Sequence number and timestamps for the latest in-order packet.
+  rtc::Optional<uint16_t> last_received_sequence_number_
+      RTC_GUARDED_BY(critical_section_rtp_receiver_);
   uint32_t last_received_timestamp_
       RTC_GUARDED_BY(critical_section_rtp_receiver_);
   int64_t last_received_frame_time_ms_
diff --git a/modules/rtp_rtcp/source/rtp_receiver_unittest.cc b/modules/rtp_rtcp/source/rtp_receiver_unittest.cc
index c8c9362..3d23b50 100644
--- a/modules/rtp_rtcp/source/rtp_receiver_unittest.cc
+++ b/modules/rtp_rtcp/source/rtp_receiver_unittest.cc
@@ -34,7 +34,6 @@
 const uint32_t kSsrc2 = 124;
 const uint32_t kCsrc1 = 111;
 const uint32_t kCsrc2 = 222;
-const bool kInOrder = true;
 
 static uint32_t rtp_timestamp(int64_t time_ms) {
   return static_cast<uint32_t>(time_ms * kTestRate / 1000);
@@ -90,7 +89,7 @@
       AudioPayload{SdpAudioFormat("foo", 8000, 1), 0}};
 
   EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(
-      header, kTestPayload, sizeof(kTestPayload), payload_specific, !kInOrder));
+      header, kTestPayload, sizeof(kTestPayload), payload_specific));
   auto sources = rtp_receiver_->GetSources();
   // One SSRC source and two CSRC sources.
   EXPECT_THAT(sources, UnorderedElementsAre(
@@ -102,7 +101,7 @@
   // contributing source object with same source id and updated timestamp.
   fake_clock_.AdvanceTimeMilliseconds(1);
   EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(
-      header, kTestPayload, sizeof(kTestPayload), payload_specific, !kInOrder));
+      header, kTestPayload, sizeof(kTestPayload), payload_specific));
   sources = rtp_receiver_->GetSources();
   now_ms = fake_clock_.TimeInMilliseconds();
   EXPECT_THAT(sources, UnorderedElementsAre(
@@ -141,7 +140,7 @@
       AudioPayload{SdpAudioFormat("foo", 8000, 1), 0}};
 
   EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(
-      header, kTestPayload, sizeof(kTestPayload), payload_specific, !kInOrder));
+      header, kTestPayload, sizeof(kTestPayload), payload_specific));
   auto sources = rtp_receiver_->GetSources();
   EXPECT_THAT(sources, UnorderedElementsAre(
                            RtpSource(now_ms, kSsrc1, RtpSourceType::SSRC)));
@@ -153,7 +152,7 @@
   header.ssrc = kSsrc2;
   header.timestamp = rtp_timestamp(now_ms);
   EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(
-      header, kTestPayload, sizeof(kTestPayload), payload_specific, !kInOrder));
+      header, kTestPayload, sizeof(kTestPayload), payload_specific));
   sources = rtp_receiver_->GetSources();
   EXPECT_THAT(sources, UnorderedElementsAre(
                            RtpSource(prev_time_ms, kSsrc1, RtpSourceType::SSRC),
@@ -167,7 +166,7 @@
   prev_time_ms = now_ms;
   now_ms = fake_clock_.TimeInMilliseconds();
   EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(
-      header, kTestPayload, sizeof(kTestPayload), payload_specific, !kInOrder));
+      header, kTestPayload, sizeof(kTestPayload), payload_specific));
   sources = rtp_receiver_->GetSources();
   EXPECT_THAT(sources, UnorderedElementsAre(
                            RtpSource(prev_time_ms, kSsrc2, RtpSourceType::SSRC),
@@ -177,7 +176,7 @@
   fake_clock_.AdvanceTimeMilliseconds(kGetSourcesTimeoutMs);
   now_ms = fake_clock_.TimeInMilliseconds();
   EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(
-      header, kTestPayload, sizeof(kTestPayload), payload_specific, !kInOrder));
+      header, kTestPayload, sizeof(kTestPayload), payload_specific));
   sources = rtp_receiver_->GetSources();
   EXPECT_THAT(sources, UnorderedElementsAre(
                            RtpSource(now_ms, kSsrc1, RtpSourceType::SSRC)));
@@ -197,9 +196,8 @@
   for (size_t i = 0; i < kSourceListSize; ++i) {
     header.ssrc = i;
     header.arrOfCSRCs[0] = (i + 1);
-    EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(header, kTestPayload,
-                                                 sizeof(kTestPayload),
-                                                 payload_specific, !kInOrder));
+    EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(
+        header, kTestPayload, sizeof(kTestPayload), payload_specific));
   }
 
   RtpSource source(0, 0, RtpSourceType::SSRC);
@@ -237,7 +235,7 @@
   header.ssrc = kSsrc1;
   header.arrOfCSRCs[0] = kCsrc1;
   EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(
-      header, kTestPayload, sizeof(kTestPayload), payload_specific, !kInOrder));
+      header, kTestPayload, sizeof(kTestPayload), payload_specific));
   auto rtp_receiver_impl = static_cast<RtpReceiverImpl*>(rtp_receiver_.get());
   auto ssrc_sources = rtp_receiver_impl->ssrc_sources_for_testing();
   ASSERT_EQ(1u, ssrc_sources.size());
@@ -268,7 +266,7 @@
       AudioPayload{SdpAudioFormat("foo", 8000, 1), 0}};
 
   EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(
-      header, kTestPayload, sizeof(kTestPayload), payload_specific, !kInOrder));
+      header, kTestPayload, sizeof(kTestPayload), payload_specific));
   auto sources = rtp_receiver_->GetSources();
   EXPECT_THAT(sources, UnorderedElementsAre(RtpSource(
                            time1_ms, kSsrc1, RtpSourceType::SSRC, 10)));
@@ -283,7 +281,7 @@
   header.extension.audioLevel = 20;
 
   EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(
-      header, kTestPayload, sizeof(kTestPayload), payload_specific, !kInOrder));
+      header, kTestPayload, sizeof(kTestPayload), payload_specific));
   sources = rtp_receiver_->GetSources();
   EXPECT_THAT(sources,
               UnorderedElementsAre(
@@ -300,7 +298,7 @@
   header.extension.audioLevel = 30;
 
   EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(
-      header, kTestPayload, sizeof(kTestPayload), payload_specific, !kInOrder));
+      header, kTestPayload, sizeof(kTestPayload), payload_specific));
   sources = rtp_receiver_->GetSources();
   EXPECT_THAT(sources,
               UnorderedElementsAre(
@@ -321,7 +319,7 @@
       AudioPayload{SdpAudioFormat("foo", 8000, 1), 0}};
 
   EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(
-      header, kTestPayload, sizeof(kTestPayload), payload_specific, !kInOrder));
+      header, kTestPayload, sizeof(kTestPayload), payload_specific));
   auto sources = rtp_receiver_->GetSources();
   EXPECT_THAT(sources, UnorderedElementsAre(RtpSource(
                            time1_ms, kSsrc1, RtpSourceType::SSRC, 10)));
@@ -334,10 +332,141 @@
   header.extension.hasAudioLevel = false;
 
   EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(
-      header, kTestPayload, sizeof(kTestPayload), payload_specific, !kInOrder));
+      header, kTestPayload, sizeof(kTestPayload), payload_specific));
   sources = rtp_receiver_->GetSources();
   EXPECT_THAT(sources, UnorderedElementsAre(
                            RtpSource(time2_ms, kSsrc1, RtpSourceType::SSRC)));
 }
 
+TEST_F(RtpReceiverTest, UpdatesTimestampsIfAndOnlyIfPacketArrivesInOrder) {
+  RTPHeader header;
+  int64_t time1_ms = fake_clock_.TimeInMilliseconds();
+  header.payloadType = kPcmuPayloadType;
+  header.ssrc = kSsrc1;
+  header.timestamp = rtp_timestamp(time1_ms);
+  header.extension.hasAudioLevel = true;
+  header.extension.audioLevel = 10;
+  header.sequenceNumber = 0xfff0;
+
+  const PayloadUnion payload_specific{
+      AudioPayload{SdpAudioFormat("foo", 8000, 1), 0}};
+  uint32_t latest_timestamp;
+  int64_t latest_receive_time_ms;
+
+  // No packet received yet.
+  EXPECT_FALSE(rtp_receiver_->GetLatestTimestamps(&latest_timestamp,
+                                                  &latest_receive_time_ms));
+  // Initial packet
+  const uint32_t timestamp_1 = header.timestamp;
+  const int64_t receive_time_1 = fake_clock_.TimeInMilliseconds();
+  EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(
+      header, kTestPayload, sizeof(kTestPayload), payload_specific));
+  EXPECT_TRUE(rtp_receiver_->GetLatestTimestamps(&latest_timestamp,
+                                                 &latest_receive_time_ms));
+  EXPECT_EQ(latest_timestamp, timestamp_1);
+  EXPECT_EQ(latest_receive_time_ms, receive_time_1);
+
+  // Late packet, timestamp not recorded.
+  fake_clock_.AdvanceTimeMilliseconds(10);
+  header.timestamp -= 900;
+  header.sequenceNumber -= 2;
+
+  EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(
+      header, kTestPayload, sizeof(kTestPayload), payload_specific));
+  EXPECT_TRUE(rtp_receiver_->GetLatestTimestamps(&latest_timestamp,
+                                                 &latest_receive_time_ms));
+  EXPECT_EQ(latest_timestamp, timestamp_1);
+  EXPECT_EQ(latest_receive_time_ms, receive_time_1);
+
+  // New packet, still late, no wraparound.
+  fake_clock_.AdvanceTimeMilliseconds(10);
+  header.timestamp += 1800;
+  header.sequenceNumber += 1;
+
+  EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(
+      header, kTestPayload, sizeof(kTestPayload), payload_specific));
+  EXPECT_TRUE(rtp_receiver_->GetLatestTimestamps(&latest_timestamp,
+                                                 &latest_receive_time_ms));
+  EXPECT_EQ(latest_timestamp, timestamp_1);
+  EXPECT_EQ(latest_receive_time_ms, receive_time_1);
+
+  // New packet, new timestamp recorded
+  fake_clock_.AdvanceTimeMilliseconds(10);
+  header.timestamp += 900;
+  header.sequenceNumber += 2;
+  const uint32_t timestamp_2 = header.timestamp;
+  const int64_t receive_time_2 = fake_clock_.TimeInMilliseconds();
+  const uint16_t seqno_2 = header.sequenceNumber;
+
+  EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(
+      header, kTestPayload, sizeof(kTestPayload), payload_specific));
+  EXPECT_TRUE(rtp_receiver_->GetLatestTimestamps(&latest_timestamp,
+                                                 &latest_receive_time_ms));
+  EXPECT_EQ(latest_timestamp, timestamp_2);
+  EXPECT_EQ(latest_receive_time_ms, receive_time_2);
+
+  // New packet, timestamp wraps around
+  fake_clock_.AdvanceTimeMilliseconds(10);
+  header.timestamp += 900;
+  header.sequenceNumber += 20;
+  const uint32_t timestamp_3 = header.timestamp;
+  const int64_t receive_time_3 = fake_clock_.TimeInMilliseconds();
+  EXPECT_LT(header.sequenceNumber, seqno_2);  // Wrap-around
+
+  EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(
+      header, kTestPayload, sizeof(kTestPayload), payload_specific));
+  EXPECT_TRUE(rtp_receiver_->GetLatestTimestamps(&latest_timestamp,
+                                                 &latest_receive_time_ms));
+  EXPECT_EQ(latest_timestamp, timestamp_3);
+  EXPECT_EQ(latest_receive_time_ms, receive_time_3);
+}
+
+TEST_F(RtpReceiverTest, UpdatesTimestampsWhenStreamResets) {
+  RTPHeader header;
+  int64_t time1_ms = fake_clock_.TimeInMilliseconds();
+  header.payloadType = kPcmuPayloadType;
+  header.ssrc = kSsrc1;
+  header.timestamp = rtp_timestamp(time1_ms);
+  header.extension.hasAudioLevel = true;
+  header.extension.audioLevel = 10;
+  header.sequenceNumber = 0xfff0;
+
+  const PayloadUnion payload_specific{
+      AudioPayload{SdpAudioFormat("foo", 8000, 1), 0}};
+  uint32_t latest_timestamp;
+  int64_t latest_receive_time_ms;
+
+  // No packet received yet.
+  EXPECT_FALSE(rtp_receiver_->GetLatestTimestamps(&latest_timestamp,
+                                                  &latest_receive_time_ms));
+  // Initial packet
+  const uint32_t timestamp_1 = header.timestamp;
+  const int64_t receive_time_1 = fake_clock_.TimeInMilliseconds();
+  const uint16_t seqno_1 = header.sequenceNumber;
+  EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(
+      header, kTestPayload, sizeof(kTestPayload), payload_specific));
+  EXPECT_TRUE(rtp_receiver_->GetLatestTimestamps(&latest_timestamp,
+                                                 &latest_receive_time_ms));
+  EXPECT_EQ(latest_timestamp, timestamp_1);
+  EXPECT_EQ(latest_receive_time_ms, receive_time_1);
+
+  // Packet with far in the past seqno, but unlikely to be a wrap-around.
+  // Treated as a seqno discontinuity, and timestamp is recorded.
+  fake_clock_.AdvanceTimeMilliseconds(10);
+  header.timestamp += 900;
+  header.sequenceNumber = 0x9000;
+
+  const uint32_t timestamp_2 = header.timestamp;
+  const int64_t receive_time_2 = fake_clock_.TimeInMilliseconds();
+  const uint16_t seqno_2 = header.sequenceNumber;
+  EXPECT_LT(seqno_1 - seqno_2, 0x8000);  // In the past.
+
+  EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(
+      header, kTestPayload, sizeof(kTestPayload), payload_specific));
+  EXPECT_TRUE(rtp_receiver_->GetLatestTimestamps(&latest_timestamp,
+                                                 &latest_receive_time_ms));
+  EXPECT_EQ(latest_timestamp, timestamp_2);
+  EXPECT_EQ(latest_receive_time_ms, receive_time_2);
+}
+
 }  // namespace webrtc
diff --git a/modules/rtp_rtcp/test/testAPI/test_api.cc b/modules/rtp_rtcp/test/testAPI/test_api.cc
index c247fc7..e2afa42 100644
--- a/modules/rtp_rtcp/test/testAPI/test_api.cc
+++ b/modules/rtp_rtcp/test/testAPI/test_api.cc
@@ -58,7 +58,7 @@
   const size_t payload_length = len - header.headerLength;
   receive_statistics_->IncomingPacket(header, len, false);
   return rtp_receiver_->IncomingRtpPacket(header, payload, payload_length,
-                                          pl->typeSpecific, true);
+                                          pl->typeSpecific);
 }
 
 bool LoopBackTransport::SendRtcp(const uint8_t* data, size_t len) {
diff --git a/modules/rtp_rtcp/test/testAPI/test_api_video.cc b/modules/rtp_rtcp/test/testAPI/test_api_video.cc
index 26964fd..63b7851 100644
--- a/modules/rtp_rtcp/test/testAPI/test_api_video.cc
+++ b/modules/rtp_rtcp/test/testAPI/test_api_video.cc
@@ -171,7 +171,7 @@
       const uint8_t* payload = padding_packet + header.headerLength;
       const size_t payload_length = packet_size - header.headerLength;
       EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(
-          header, payload, payload_length, pl->typeSpecific, true));
+          header, payload, payload_length, pl->typeSpecific));
       EXPECT_EQ(0u, receiver_->payload_size());
       EXPECT_EQ(payload_length, receiver_->rtp_header().header.paddingLength);
     }
diff --git a/video/rtp_video_stream_receiver.cc b/video/rtp_video_stream_receiver.cc
index 2b1b05e..aecdfe3 100644
--- a/video/rtp_video_stream_receiver.cc
+++ b/video/rtp_video_stream_receiver.cc
@@ -280,8 +280,7 @@
 
   RTPHeader header;
   packet.GetHeader(&header);
-  bool in_order = IsPacketInOrder(header);
-  ReceivePacket(rtp_packet, rtp_packet_length, header, in_order);
+  ReceivePacket(rtp_packet, rtp_packet_length, header);
 }
 
 // TODO(pbos): Remove as soon as audio can handle a changing payload type
@@ -339,7 +338,7 @@
     // TODO(nisse): Why isn't this done for recovered packets?
     rtp_payload_registry_.SetIncomingPayloadType(header);
   }
-  ReceivePacket(packet.data(), packet.size(), header, in_order);
+  ReceivePacket(packet.data(), packet.size(), header);
   // Update receive statistics after ReceivePacket.
   // Receive statistics will be reset if the payload type changes (make sure
   // that the first packet is included in the stats).
@@ -443,8 +442,7 @@
 
 void RtpVideoStreamReceiver::ReceivePacket(const uint8_t* packet,
                                            size_t packet_length,
-                                           const RTPHeader& header,
-                                           bool in_order) {
+                                           const RTPHeader& header) {
   if (rtp_payload_registry_.IsRed(header)) {
     ParseAndHandleEncapsulatingHeader(packet, packet_length, header);
     return;
@@ -456,7 +454,7 @@
       rtp_payload_registry_.PayloadTypeToPayload(header.payloadType);
   if (pl) {
     rtp_receiver_->IncomingRtpPacket(header, payload, payload_length,
-                                     pl->typeSpecific, in_order);
+                                     pl->typeSpecific);
   }
 }
 
diff --git a/video/rtp_video_stream_receiver.h b/video/rtp_video_stream_receiver.h
index 25ea486..90e8200 100644
--- a/video/rtp_video_stream_receiver.h
+++ b/video/rtp_video_stream_receiver.h
@@ -154,8 +154,7 @@
   bool AddReceiveCodec(const VideoCodec& video_codec);
   void ReceivePacket(const uint8_t* packet,
                      size_t packet_length,
-                     const RTPHeader& header,
-                     bool in_order);
+                     const RTPHeader& header);
   // Parses and handles for instance RTX and RED headers.
   // This function assumes that it's being called from only one thread.
   void ParseAndHandleEncapsulatingHeader(const uint8_t* packet,
diff --git a/voice_engine/channel.cc b/voice_engine/channel.cc
index c3c06a0..19873f1 100644
--- a/voice_engine/channel.cc
+++ b/voice_engine/channel.cc
@@ -595,7 +595,8 @@
       rtp_payload_registry_->GetPayloadTypeFrequency(header.payloadType);
   if (header.payload_type_frequency < 0)
     return false;
-  return ReceivePacket(rtp_packet, rtp_packet_length, header, false);
+  // TODO(nisse): Pass RtpPacketReceived with |recovered()| true.
+  return ReceivePacket(rtp_packet, rtp_packet_length, header);
 }
 
 AudioMixer::Source::AudioFrameInfo Channel::GetAudioFrameWithInfo(
@@ -1148,14 +1149,13 @@
         header, packet.size(), IsPacketRetransmitted(header, in_order));
     rtp_payload_registry_->SetIncomingPayloadType(header);
 
-    ReceivePacket(packet.data(), packet.size(), header, in_order);
+    ReceivePacket(packet.data(), packet.size(), header);
   }
 }
 
 bool Channel::ReceivePacket(const uint8_t* packet,
                             size_t packet_length,
-                            const RTPHeader& header,
-                            bool in_order) {
+                            const RTPHeader& header) {
   const uint8_t* payload = packet + header.headerLength;
   assert(packet_length >= header.headerLength);
   size_t payload_length = packet_length - header.headerLength;
@@ -1165,7 +1165,7 @@
     return false;
   }
   return rtp_receiver_->IncomingRtpPacket(header, payload, payload_length,
-                                          pl->typeSpecific, in_order);
+                                          pl->typeSpecific);
 }
 
 bool Channel::IsPacketInOrder(const RTPHeader& header) const {
diff --git a/voice_engine/channel.h b/voice_engine/channel.h
index 9221115..9a79b2b 100644
--- a/voice_engine/channel.h
+++ b/voice_engine/channel.h
@@ -341,8 +341,7 @@
 
   bool ReceivePacket(const uint8_t* packet,
                      size_t packet_length,
-                     const RTPHeader& header,
-                     bool in_order);
+                     const RTPHeader& header);
   bool IsPacketInOrder(const RTPHeader& header) const;
   bool IsPacketRetransmitted(const RTPHeader& header, bool in_order) const;
   int ResendPackets(const uint16_t* sequence_numbers, int length);