Cleanup test::FrameGeneratorCapturer::InsertFrameTask
Fix race between FrameGeneratorCapturer destructor and inserting a frame.
(aka do not use this after reposting self to a TaskQueue)
Separate periodic case from one-time case.
When Generator can't keep up with fps, drop frames instead of trying to catch up.
Use absl::make_unique and absl::WrapUnique
Bug: None
Change-Id: I9d5d1fcacf174e28d83310099b79e26ece9b7b37
Reviewed-on: https://webrtc-review.googlesource.com/98844
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Reviewed-by: Sebastian Jansson <srte@webrtc.org>
Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#24654}
diff --git a/test/frame_generator_capturer.cc b/test/frame_generator_capturer.cc
index 87e9bb3..2e4280f 100644
--- a/test/frame_generator_capturer.cc
+++ b/test/frame_generator_capturer.cc
@@ -13,10 +13,10 @@
#include <utility>
#include <vector>
+#include "absl/memory/memory.h"
#include "call/video_send_stream.h"
#include "rtc_base/criticalsection.h"
#include "rtc_base/logging.h"
-#include "rtc_base/platform_thread.h"
#include "rtc_base/task_queue.h"
#include "rtc_base/timeutils.h"
#include "system_wrappers/include/clock.h"
@@ -26,62 +26,47 @@
class FrameGeneratorCapturer::InsertFrameTask : public rtc::QueuedTask {
public:
- // Repeats in |repeat_interval_ms|. One-time if |repeat_interval_ms| == 0.
- InsertFrameTask(
- webrtc::test::FrameGeneratorCapturer* frame_generator_capturer,
- uint32_t repeat_interval_ms)
+ explicit InsertFrameTask(FrameGeneratorCapturer* frame_generator_capturer)
: frame_generator_capturer_(frame_generator_capturer),
- repeat_interval_ms_(repeat_interval_ms),
- intended_run_time_ms_(-1) {}
+ repeat_interval_ms_(-1),
+ next_run_time_ms_(-1) {}
private:
bool Run() override {
- bool task_completed = true;
- if (repeat_interval_ms_ > 0) {
- // This is not a one-off frame. Check if the frame interval for this
- // task queue is the same same as the current configured frame rate.
- uint32_t current_interval_ms =
- 1000 / frame_generator_capturer_->GetCurrentConfiguredFramerate();
- if (repeat_interval_ms_ != current_interval_ms) {
- // Frame rate has changed since task was started, create a new instance.
- rtc::TaskQueue::Current()->PostDelayedTask(
- std::unique_ptr<rtc::QueuedTask>(new InsertFrameTask(
- frame_generator_capturer_, current_interval_ms)),
- current_interval_ms);
- } else {
- // Schedule the next frame capture event to happen at approximately the
- // correct absolute time point.
- int64_t delay_ms;
- int64_t time_now_ms = rtc::TimeMillis();
- if (intended_run_time_ms_ > 0) {
- delay_ms = time_now_ms - intended_run_time_ms_;
- } else {
- delay_ms = 0;
- intended_run_time_ms_ = time_now_ms;
- }
- intended_run_time_ms_ += repeat_interval_ms_;
- if (delay_ms < repeat_interval_ms_) {
- rtc::TaskQueue::Current()->PostDelayedTask(
- std::unique_ptr<rtc::QueuedTask>(this),
- repeat_interval_ms_ - delay_ms);
- } else {
- rtc::TaskQueue::Current()->PostDelayedTask(
- std::unique_ptr<rtc::QueuedTask>(this), 0);
- RTC_LOG(LS_ERROR)
- << "Frame Generator Capturer can't keep up with requested fps";
- }
- // Repost of this instance, make sure it is not deleted.
- task_completed = false;
- }
+ // Check if the frame interval for this
+ // task queue is the same same as the current configured frame rate.
+ int interval_ms =
+ 1000 / frame_generator_capturer_->GetCurrentConfiguredFramerate();
+ if (repeat_interval_ms_ != interval_ms) {
+ // Restart the timer if frame rate has changed since task was started.
+ next_run_time_ms_ = rtc::TimeMillis();
+ repeat_interval_ms_ = interval_ms;
}
+ // Schedule the next frame capture event to happen at approximately the
+ // correct absolute time point.
+ next_run_time_ms_ += interval_ms;
+
frame_generator_capturer_->InsertFrame();
- // Task should be deleted only if it's not repeating.
- return task_completed;
+
+ int64_t now_ms = rtc::TimeMillis();
+ if (next_run_time_ms_ < now_ms) {
+ int skipped_frames = 1 + (now_ms - next_run_time_ms_) / interval_ms;
+ next_run_time_ms_ += skipped_frames * interval_ms;
+ RTC_LOG(LS_ERROR) << "Frame Generator Capturer can't keep up with "
+ "requested fps, skipped "
+ << skipped_frames << " frame(s).";
+ }
+ int64_t delay_ms = next_run_time_ms_ - now_ms;
+ RTC_DCHECK_GE(delay_ms, 0);
+ RTC_DCHECK_LE(delay_ms, interval_ms);
+ rtc::TaskQueue::Current()->PostDelayedTask(absl::WrapUnique(this),
+ delay_ms);
+ return false;
}
webrtc::test::FrameGeneratorCapturer* const frame_generator_capturer_;
- const uint32_t repeat_interval_ms_;
- int64_t intended_run_time_ms_;
+ int repeat_interval_ms_;
+ int64_t next_run_time_ms_;
};
FrameGeneratorCapturer* FrameGeneratorCapturer::Create(
@@ -91,10 +76,10 @@
absl::optional<int> num_squares,
int target_fps,
Clock* clock) {
- std::unique_ptr<FrameGeneratorCapturer> capturer(new FrameGeneratorCapturer(
+ auto capturer = absl::make_unique<FrameGeneratorCapturer>(
clock,
FrameGenerator::CreateSquareGenerator(width, height, type, num_squares),
- target_fps));
+ target_fps);
if (!capturer->Init())
return nullptr;
@@ -107,11 +92,11 @@
size_t height,
int target_fps,
Clock* clock) {
- std::unique_ptr<FrameGeneratorCapturer> capturer(new FrameGeneratorCapturer(
+ auto capturer = absl::make_unique<FrameGeneratorCapturer>(
clock,
FrameGenerator::CreateFromYuvFile(std::vector<std::string>(1, file_name),
width, height, 1),
- target_fps));
+ target_fps);
if (!capturer->Init())
return nullptr;
@@ -124,10 +109,10 @@
int frame_repeat_count,
int target_fps,
Clock* clock) {
- std::unique_ptr<FrameGeneratorCapturer> capturer(new FrameGeneratorCapturer(
+ auto capturer = absl::make_unique<FrameGeneratorCapturer>(
clock,
FrameGenerator::CreateSlideGenerator(width, height, frame_repeat_count),
- target_fps));
+ target_fps);
if (!capturer->Init())
return nullptr;
@@ -167,10 +152,8 @@
return false;
int framerate_fps = GetCurrentConfiguredFramerate();
- task_queue_.PostDelayedTask(
- std::unique_ptr<rtc::QueuedTask>(
- new InsertFrameTask(this, 1000 / framerate_fps)),
- 1000 / framerate_fps);
+ task_queue_.PostDelayedTask(absl::make_unique<InsertFrameTask>(this),
+ 1000 / framerate_fps);
return true;
}
@@ -271,9 +254,7 @@
void FrameGeneratorCapturer::ForceFrame() {
// One-time non-repeating task,
- // therefore repeat_interval_ms is 0 in InsertFrameTask()
- task_queue_.PostTask(
- std::unique_ptr<rtc::QueuedTask>(new InsertFrameTask(this, 0)));
+ task_queue_.PostTask([this] { InsertFrame(); });
}
int FrameGeneratorCapturer::GetCurrentConfiguredFramerate() {