Fill drops with last decoded frame.

Fill drops with last decoded frame to make them look like freeze at
playback and to keep decoded spatial layers in sync.

Bug: none
Change-Id: I65f7c21100985c22932a1edd441b6c724833c11e
Reviewed-on: https://webrtc-review.googlesource.com/73685
Commit-Queue: Sergey Silkin <ssilkin@webrtc.org>
Reviewed-by: Rasmus Brandt <brandtr@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#23076}
diff --git a/modules/video_coding/codecs/test/videoprocessor.cc b/modules/video_coding/codecs/test/videoprocessor.cc
index f80a18b..f6d2738 100644
--- a/modules/video_coding/codecs/test/videoprocessor.cc
+++ b/modules/video_coding/codecs/test/videoprocessor.cc
@@ -181,6 +181,7 @@
       last_encoded_frame_num_(num_simulcast_or_spatial_layers_),
       first_decoded_frame_(num_simulcast_or_spatial_layers_, true),
       last_decoded_frame_num_(num_simulcast_or_spatial_layers_),
+      decoded_frame_buffer_(num_simulcast_or_spatial_layers_),
       post_encode_time_ns_(0) {
   // Sanity checks.
   RTC_CHECK(rtc::TaskQueue::Current())
@@ -429,6 +430,16 @@
       stats_->GetFrameWithTimestamp(decoded_frame.timestamp(), spatial_idx);
   const size_t frame_number = frame_stat->frame_number;
 
+  if (decoded_frame_writers_ && !first_decoded_frame_[spatial_idx]) {
+    // Fill drops with last decoded frame to make them look like freeze at
+    // playback and to keep decoded layers in sync.
+    for (size_t i = last_decoded_frame_num_[spatial_idx] + 1; i < frame_number;
+         ++i) {
+      RTC_CHECK(decoded_frame_writers_->at(spatial_idx)
+                    ->WriteFrame(decoded_frame_buffer_[spatial_idx].data()));
+    }
+  }
+
   // Ensure that the decode order is monotonically increasing, within this
   // simulcast/spatial layer.
   RTC_CHECK(first_decoded_frame_[spatial_idx] ||
@@ -469,11 +480,12 @@
 
   if (decoded_frame_writers_) {
     ExtractI420BufferWithSize(decoded_frame, config_.codec_settings.width,
-                              config_.codec_settings.height, &tmp_i420_buffer_);
-    RTC_CHECK_EQ(tmp_i420_buffer_.size(),
+                              config_.codec_settings.height,
+                              &decoded_frame_buffer_[spatial_idx]);
+    RTC_CHECK_EQ(decoded_frame_buffer_[spatial_idx].size(),
                  decoded_frame_writers_->at(spatial_idx)->FrameLength());
     RTC_CHECK(decoded_frame_writers_->at(spatial_idx)
-                  ->WriteFrame(tmp_i420_buffer_.data()));
+                  ->WriteFrame(decoded_frame_buffer_[spatial_idx].data()));
   }
 }
 
diff --git a/modules/video_coding/codecs/test/videoprocessor.h b/modules/video_coding/codecs/test/videoprocessor.h
index 66e7525..1799b8a 100644
--- a/modules/video_coding/codecs/test/videoprocessor.h
+++ b/modules/video_coding/codecs/test/videoprocessor.h
@@ -221,7 +221,6 @@
   // and decoded bitstreams. Each frame writer is enabled by being non-null.
   IvfFileWriterList* const encoded_frame_writers_;
   FrameWriterList* const decoded_frame_writers_;
-  rtc::Buffer tmp_i420_buffer_;  // Temp storage for format conversion.
 
   // Metadata for inputed/encoded/decoded frames. Used for frame identification,
   // frame drop detection, etc. We assume that encoded/decoded frames are
@@ -237,6 +236,9 @@
   std::vector<bool> first_decoded_frame_ RTC_GUARDED_BY(sequence_checker_);
   // simulcast_svc_idx -> frame_number.
   std::vector<size_t> last_decoded_frame_num_ RTC_GUARDED_BY(sequence_checker_);
+  // simulcast_svc_idx -> buffer.
+  std::vector<rtc::Buffer> decoded_frame_buffer_
+      RTC_GUARDED_BY(sequence_checker_);
 
   // Time spent in frame encode callback. It is accumulated for layers and
   // reset when frame encode starts. When next layer is encoded post-encode time