| 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
|
|
|