From d0f3d84620824bb8ba1c9315ada54782b805ae24 Mon Sep 17 00:00:00 2001 From: Ilya Nikolaevskiy Date: Mon, 4 Mar 2019 15:10:44 +0100 Subject: [PATCH] Wire UpdateRect signalling in test frame generators MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a lightweight signalling, which tells that two frames are the same if they are the same view of the same frame from the same file, without comparing actual buffer contents and searching for changed pixels. Bug: webrtc:10310 Change-Id: I5c6ae571fdf4cab88466cde88fe7c7a78ae121cc Reviewed-on: https://webrtc-review.googlesource.com/c/125099 Commit-Queue: Ilya Nikolaevskiy Reviewed-by: Erik Språng Cr-Commit-Position: refs/heads/master@{#26951} --- test/frame_generator.cc | 49 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/test/frame_generator.cc b/test/frame_generator.cc index 453270e774..22cc00e681 100644 --- a/test/frame_generator.cc +++ b/test/frame_generator.cc @@ -183,6 +183,7 @@ class YuvFileGenerator : public FrameGenerator { size_t height, int frame_repeat_count) : file_index_(0), + frame_index_(std::numeric_limits::max()), files_(files), width_(width), height_(height), @@ -203,8 +204,16 @@ class YuvFileGenerator : public FrameGenerator { } VideoFrame* NextFrame() override { - if (current_display_count_ == 0) - ReadNextFrame(); + // Empty update by default. + VideoFrame::UpdateRect update_rect{0, 0, 0, 0}; + if (current_display_count_ == 0) { + const bool got_new_frame = ReadNextFrame(); + // Full update on a new frame from file. + if (got_new_frame) { + update_rect = VideoFrame::UpdateRect{0, 0, static_cast(width_), + static_cast(height_)}; + } + } if (++current_display_count_ >= frame_display_count_) current_display_count_ = 0; @@ -213,18 +222,26 @@ class YuvFileGenerator : public FrameGenerator { .set_video_frame_buffer(last_read_buffer_) .set_rotation(webrtc::kVideoRotation_0) .set_timestamp_us(0) + .set_update_rect(update_rect) .build()); return temp_frame_.get(); } - void ReadNextFrame() { + // Returns true if the new frame was loaded. + // False only in case of a single file with a single frame in it. + bool ReadNextFrame() { + size_t prev_frame_index = frame_index_; + size_t prev_file_index = file_index_; last_read_buffer_ = test::ReadI420Buffer(static_cast(width_), static_cast(height_), files_[file_index_]); + ++frame_index_; if (!last_read_buffer_) { // No more frames to read in this file, rewind and move to next file. rewind(files_[file_index_]); + + frame_index_ = 0; file_index_ = (file_index_ + 1) % files_.size(); last_read_buffer_ = test::ReadI420Buffer(static_cast(width_), @@ -232,10 +249,12 @@ class YuvFileGenerator : public FrameGenerator { files_[file_index_]); RTC_CHECK(last_read_buffer_); } + return frame_index_ != prev_frame_index || file_index_ != prev_file_index; } private: size_t file_index_; + size_t frame_index_; const std::vector files_; const size_t width_; const size_t height_; @@ -348,6 +367,7 @@ class ScrollingImageFrameGenerator : public FrameGenerator { target_width_(static_cast(target_width)), target_height_(static_cast(target_height)), current_frame_num_(num_frames_ - 1), + prev_frame_not_scrolled_(false), current_source_frame_(nullptr), file_generator_(files, source_width, source_height, 1) { RTC_DCHECK(clock_ != nullptr); @@ -369,25 +389,42 @@ class ScrollingImageFrameGenerator : public FrameGenerator { size_t frame_num = (ms_since_start / kFrameDisplayTime) % num_frames_; UpdateSourceFrame(frame_num); + bool cur_frame_not_scrolled; + double scroll_factor; int64_t time_into_frame = ms_since_start % kFrameDisplayTime; if (time_into_frame < scroll_time_) { scroll_factor = static_cast(time_into_frame) / scroll_time_; + cur_frame_not_scrolled = false; } else { scroll_factor = 1.0; + cur_frame_not_scrolled = true; } CropSourceToScrolledImage(scroll_factor); + bool same_scroll_position = + prev_frame_not_scrolled_ && cur_frame_not_scrolled; + if (!same_scroll_position && current_frame_) { + // If scrolling is not finished yet, force full frame update. + current_frame_->set_update_rect( + VideoFrame::UpdateRect{0, 0, target_width_, target_height_}); + } + prev_frame_not_scrolled_ = cur_frame_not_scrolled; + return current_frame_ ? &*current_frame_ : nullptr; } void UpdateSourceFrame(size_t frame_num) { + VideoFrame::UpdateRect acc_update{0, 0, 0, 0}; while (current_frame_num_ != frame_num || current_source_frame_ == nullptr) { current_source_frame_ = file_generator_.NextFrame(); + if (current_source_frame_) + acc_update.Union(current_source_frame_->update_rect()); current_frame_num_ = (current_frame_num_ + 1) % num_frames_; } RTC_DCHECK(current_source_frame_ != nullptr); + current_source_frame_->set_update_rect(acc_update); } void CropSourceToScrolledImage(double scroll_factor) { @@ -407,6 +444,10 @@ class ScrollingImageFrameGenerator : public FrameGenerator { int offset_v = (i420_buffer->StrideV() * (pixels_scrolled_y / 2)) + (pixels_scrolled_x / 2); + VideoFrame::UpdateRect update_rect = + current_source_frame_->update_rect().IsEmpty() + ? VideoFrame::UpdateRect{0, 0, 0, 0} + : VideoFrame::UpdateRect{0, 0, target_width_, target_height_}; current_frame_ = VideoFrame::Builder() .set_video_frame_buffer(WrapI420Buffer( @@ -416,6 +457,7 @@ class ScrollingImageFrameGenerator : public FrameGenerator { i420_buffer->StrideV(), KeepRefUntilDone(i420_buffer))) .set_rotation(kVideoRotation_0) .set_timestamp_us(0) + .set_update_rect(update_rect) .build(); } @@ -428,6 +470,7 @@ class ScrollingImageFrameGenerator : public FrameGenerator { const int target_height_; size_t current_frame_num_; + bool prev_frame_not_scrolled_; VideoFrame* current_source_frame_; absl::optional current_frame_; YuvFileGenerator file_generator_;