Index: webrtc/test/frame_generator_capturer.cc |
diff --git a/webrtc/test/frame_generator_capturer.cc b/webrtc/test/frame_generator_capturer.cc |
index 9e74e40d18bf072b85ab23c2283ded7a2660bc6c..d16d8c836fac1a1b12250a18fc4f69b80130386c 100644 |
--- a/webrtc/test/frame_generator_capturer.cc |
+++ b/webrtc/test/frame_generator_capturer.cc |
@@ -37,30 +37,47 @@ class FrameGeneratorCapturer::InsertFrameTask : public rtc::QueuedTask { |
private: |
bool Run() override { |
+ bool task_completed = true; |
if (repeat_interval_ms_ > 0) { |
- 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_) { |
+ // 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>(this), |
- repeat_interval_ms_ - delay_ms); |
+ std::unique_ptr<rtc::QueuedTask>(new InsertFrameTask( |
+ frame_generator_capturer_, current_interval_ms)), |
+ current_interval_ms); |
} else { |
- rtc::TaskQueue::Current()->PostDelayedTask( |
- std::unique_ptr<rtc::QueuedTask>(this), 0); |
- LOG(LS_ERROR) |
- << "Frame Generator Capturer can't keep up with requested fps"; |
+ // 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); |
+ 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; |
} |
} |
frame_generator_capturer_->InsertFrame(); |
// Task should be deleted only if it's not repeating. |
- return repeat_interval_ms_ == 0; |
+ return task_completed; |
} |
webrtc::test::FrameGeneratorCapturer* const frame_generator_capturer_; |
@@ -72,14 +89,12 @@ FrameGeneratorCapturer* FrameGeneratorCapturer::Create(int width, |
int height, |
int target_fps, |
Clock* clock) { |
- FrameGeneratorCapturer* capturer = new FrameGeneratorCapturer( |
- clock, FrameGenerator::CreateSquareGenerator(width, height), target_fps); |
- if (!capturer->Init()) { |
- delete capturer; |
- return NULL; |
- } |
+ std::unique_ptr<FrameGeneratorCapturer> capturer(new FrameGeneratorCapturer( |
+ clock, FrameGenerator::CreateSquareGenerator(width, height), target_fps)); |
+ if (!capturer->Init()) |
+ return nullptr; |
- return capturer; |
+ return capturer.release(); |
} |
FrameGeneratorCapturer* FrameGeneratorCapturer::CreateFromYuvFile( |
@@ -88,16 +103,15 @@ FrameGeneratorCapturer* FrameGeneratorCapturer::CreateFromYuvFile( |
size_t height, |
int target_fps, |
Clock* clock) { |
- FrameGeneratorCapturer* capturer = new FrameGeneratorCapturer( |
- clock, FrameGenerator::CreateFromYuvFile( |
- std::vector<std::string>(1, file_name), width, height, 1), |
- target_fps); |
- if (!capturer->Init()) { |
- delete capturer; |
- return NULL; |
- } |
- |
- return capturer; |
+ std::unique_ptr<FrameGeneratorCapturer> capturer(new FrameGeneratorCapturer( |
+ clock, |
+ FrameGenerator::CreateFromYuvFile(std::vector<std::string>(1, file_name), |
+ width, height, 1), |
+ target_fps)); |
+ if (!capturer->Init()) |
+ return nullptr; |
+ |
+ return capturer.release(); |
} |
FrameGeneratorCapturer::FrameGeneratorCapturer( |
@@ -129,29 +143,32 @@ void FrameGeneratorCapturer::SetFakeRotation(VideoRotation rotation) { |
bool FrameGeneratorCapturer::Init() { |
// This check is added because frame_generator_ might be file based and should |
// not crash because a file moved. |
- if (frame_generator_.get() == NULL) |
+ if (frame_generator_.get() == nullptr) |
return false; |
+ int framerate_fps = GetCurrentConfiguredFramerate(); |
task_queue_.PostDelayedTask( |
std::unique_ptr<rtc::QueuedTask>( |
- new InsertFrameTask(this, 1000 / target_fps_)), |
- 1000 / target_fps_); |
+ new InsertFrameTask(this, 1000 / framerate_fps)), |
+ 1000 / framerate_fps); |
return true; |
} |
void FrameGeneratorCapturer::InsertFrame() { |
- { |
- rtc::CritScope cs(&lock_); |
- if (sending_) { |
- VideoFrame* frame = frame_generator_->NextFrame(); |
- frame->set_ntp_time_ms(clock_->CurrentNtpInMilliseconds()); |
- frame->set_rotation(fake_rotation_); |
- if (first_frame_capture_time_ == -1) { |
- first_frame_capture_time_ = frame->ntp_time_ms(); |
- } |
- if (sink_) |
- sink_->OnFrame(*frame); |
+ rtc::CritScope cs(&lock_); |
+ if (sending_) { |
+ VideoFrame* frame = frame_generator_->NextFrame(); |
+ frame->set_ntp_time_ms(clock_->CurrentNtpInMilliseconds()); |
+ frame->set_rotation(fake_rotation_); |
+ if (first_frame_capture_time_ == -1) { |
+ first_frame_capture_time_ = frame->ntp_time_ms(); |
+ } |
+ |
+ if (sink_) { |
+ rtc::Optional<VideoFrame> out_frame = AdaptFrame(*frame); |
+ if (out_frame) |
+ sink_->OnFrame(*out_frame); |
} |
} |
} |
@@ -185,6 +202,19 @@ void FrameGeneratorCapturer::AddOrUpdateSink( |
sink_ = sink; |
if (sink_wants_observer_) |
sink_wants_observer_->OnSinkWantsChanged(sink, wants); |
+ |
+ // Handle framerate within this class, just pass on resolution for possible |
+ // adaptation. |
+ rtc::VideoSinkWants resolution_wants = wants; |
+ resolution_wants.max_framerate_fps = std::numeric_limits<int>::max(); |
+ VideoCapturer::AddOrUpdateSink(sink, resolution_wants); |
+ |
+ // Ignore any requests for framerate higher than initially configured. |
+ if (wants.max_framerate_fps < target_fps_) { |
+ wanted_fps_.emplace(wants.max_framerate_fps); |
+ } else { |
+ wanted_fps_.reset(); |
+ } |
} |
void FrameGeneratorCapturer::RemoveSink( |
@@ -201,5 +231,12 @@ void FrameGeneratorCapturer::ForceFrame() { |
std::unique_ptr<rtc::QueuedTask>(new InsertFrameTask(this, 0))); |
} |
+int FrameGeneratorCapturer::GetCurrentConfiguredFramerate() { |
+ rtc::CritScope cs(&lock_); |
+ if (wanted_fps_ && *wanted_fps_ < target_fps_) |
+ return *wanted_fps_; |
+ return target_fps_; |
+} |
+ |
} // namespace test |
} // namespace webrtc |