Check if the order of frames becomes ambiguous if we were to insert the incoming frame, and if so, clear the FrameBuffer.

BUG=chromium:679306

Review-Url: https://codereview.webrtc.org/2830723002
Cr-Commit-Position: refs/heads/master@{#17785}
diff --git a/webrtc/modules/video_coding/frame_buffer2.cc b/webrtc/modules/video_coding/frame_buffer2.cc
index fcd5238..acc1bb8 100644
--- a/webrtc/modules/video_coding/frame_buffer2.cc
+++ b/webrtc/modules/video_coding/frame_buffer2.cc
@@ -93,7 +93,8 @@
       if (continuous_end_it != frames_.end())
         ++continuous_end_it;
 
-      for (; frame_it != continuous_end_it; ++frame_it) {
+      for (; frame_it != continuous_end_it && frame_it != frames_.end();
+           ++frame_it) {
         if (!frame_it->second.continuous ||
             frame_it->second.num_missing_decodable > 0) {
           continue;
@@ -233,6 +234,17 @@
     }
   }
 
+  // Test if inserting this frame would cause the order of the frames to become
+  // ambiguous (covering more than half the interval of 2^16). This can happen
+  // when the picture id make large jumps mid stream.
+  if (!frames_.empty() &&
+      key < frames_.begin()->first &&
+      frames_.rbegin()->first < key) {
+    LOG(LS_WARNING) << "A jump in picture id was detected, clearing buffer.";
+    ClearFramesAndHistory();
+    last_continuous_picture_id = -1;
+  }
+
   auto info = frames_.insert(std::make_pair(key, FrameInfo())).first;
 
   if (info->second.frame) {
diff --git a/webrtc/modules/video_coding/frame_buffer2_unittest.cc b/webrtc/modules/video_coding/frame_buffer2_unittest.cc
index b67d993..04ce559 100644
--- a/webrtc/modules/video_coding/frame_buffer2_unittest.cc
+++ b/webrtc/modules/video_coding/frame_buffer2_unittest.cc
@@ -497,5 +497,24 @@
   CheckFrame(0, pid, 0);
 }
 
+TEST_F(TestFrameBuffer2, ForwardJumps) {
+  EXPECT_EQ(5453, InsertFrame(5453, 0, 1, false));
+  ExtractFrame();
+  EXPECT_EQ(5454, InsertFrame(5454, 0, 1, false, 5453));
+  ExtractFrame();
+  EXPECT_EQ(15670, InsertFrame(15670, 0, 1, false));
+  ExtractFrame();
+  EXPECT_EQ(29804, InsertFrame(29804, 0, 1, false));
+  ExtractFrame();
+  EXPECT_EQ(29805, InsertFrame(29805, 0, 1, false, 29804));
+  ExtractFrame();
+  EXPECT_EQ(29806, InsertFrame(29806, 0, 1, false, 29805));
+  ExtractFrame();
+  EXPECT_EQ(33819, InsertFrame(33819, 0, 1, false));
+  ExtractFrame();
+  EXPECT_EQ(41248, InsertFrame(41248, 0, 1, false));
+  ExtractFrame();
+}
+
 }  // namespace video_coding
 }  // namespace webrtc