Chromium Code Reviews| 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..5128364e2a1858ae720c39e8a04b19bef55c13e3 100644 |
| --- a/webrtc/test/frame_generator_capturer.cc |
| +++ b/webrtc/test/frame_generator_capturer.cc |
| @@ -38,24 +38,38 @@ class FrameGeneratorCapturer::InsertFrameTask : public rtc::QueuedTask { |
| private: |
| bool Run() override { |
| 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 configures 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"; |
| + } |
| } |
| } |
| frame_generator_capturer_->InsertFrame(); |
| @@ -72,14 +86,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 +100,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 +140,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 +199,15 @@ 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); |
| + |
| + if (wants.max_framerate_fps < target_fps_) |
| + wanted_fps_.emplace(wants.max_framerate_fps); |
|
ilnik
2017/03/20 10:02:52
May it happen that |wants.max_framerate_fps| may b
sprang_webrtc
2017/03/20 10:18:45
You're right. I botched the rebase here. Fixed.
|
| } |
| void FrameGeneratorCapturer::RemoveSink( |
| @@ -201,5 +224,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 |