Clear the FrameBuffer in case of a backward jump in the picture id.

Even though this is against the spec we allow a stream to continue if
a backwards jump in the picture id occurs on a keyframe.

BUG=webrtc:7001, webrtc:5514

Review-Url: https://codereview.webrtc.org/2640793003
Cr-Original-Commit-Position: refs/heads/master@{#16146}
Cr-Mirrored-From: https://chromium.googlesource.com/external/webrtc
Cr-Mirrored-Commit: fcc600651dfe50e2d6e27fc77e5acbf04f5a63cd
diff --git a/modules/video_coding/frame_buffer2.cc b/modules/video_coding/frame_buffer2.cc
index 279c613..58c41bf 100644
--- a/modules/video_coding/frame_buffer2.cc
+++ b/modules/video_coding/frame_buffer2.cc
@@ -135,6 +135,7 @@
 
     PropagateDecodability(next_frame_it->second);
     AdvanceLastDecodedFrame(next_frame_it);
+    last_decoded_frame_timestamp_ = frame->timestamp;
     *frame_out = std::move(frame);
     return kFrameFound;
   } else {
@@ -189,14 +190,27 @@
 
   if (last_decoded_frame_it_ != frames_.end() &&
       key < last_decoded_frame_it_->first) {
-    LOG(LS_WARNING) << "Frame with (picture_id:spatial_id) (" << key.picture_id
-                    << ":" << static_cast<int>(key.spatial_layer)
-                    << ") inserted after frame ("
-                    << last_decoded_frame_it_->first.picture_id << ":"
-                    << static_cast<int>(
-                           last_decoded_frame_it_->first.spatial_layer)
-                    << ") was handed off for decoding, dropping frame.";
-    return last_continuous_picture_id;
+    if (AheadOf(frame->timestamp, last_decoded_frame_timestamp_) &&
+        frame->num_references == 0) {
+      // If this frame has a newer timestamp but an earlier picture id then we
+      // assume there has been a jump in the picture id due to some encoder
+      // reconfiguration or some other reason. Even though this is not according
+      // to spec we can still continue to decode from this frame if it is a
+      // keyframe.
+      LOG(LS_WARNING) << "A jump in picture id was detected, clearing buffer.";
+      ClearFramesAndHistory();
+      last_continuous_picture_id = -1;
+    } else {
+      LOG(LS_WARNING) << "Frame with (picture_id:spatial_id) ("
+                      << key.picture_id << ":"
+                      << static_cast<int>(key.spatial_layer)
+                      << ") inserted after frame ("
+                      << last_decoded_frame_it_->first.picture_id << ":"
+                      << static_cast<int>(
+                             last_decoded_frame_it_->first.spatial_layer)
+                      << ") was handed off for decoding, dropping frame.";
+      return last_continuous_picture_id;
+    }
   }
 
   auto info = frames_.insert(std::make_pair(key, FrameInfo())).first;
@@ -390,5 +404,13 @@
   }
 }
 
+void FrameBuffer::ClearFramesAndHistory() {
+  frames_.clear();
+  last_decoded_frame_it_ = frames_.end();
+  last_continuous_frame_it_ = frames_.end();
+  num_frames_history_ = 0;
+  num_frames_buffered_ = 0;
+}
+
 }  // namespace video_coding
 }  // namespace webrtc