blob: 9e74e40d18bf072b85ab23c2283ded7a2660bc6c [file] [log] [blame]
pbos@webrtc.org26d12102013-05-29 13:41:03 +00001/*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000011#include "webrtc/test/frame_generator_capturer.h"
pbos@webrtc.org26d12102013-05-29 13:41:03 +000012
ilnikbaded152017-03-17 05:55:25 -070013#include <utility>
14#include <vector>
15
Peter Boströmf2f82832015-05-01 13:00:41 +020016#include "webrtc/base/criticalsection.h"
ilnikbaded152017-03-17 05:55:25 -070017#include "webrtc/base/logging.h"
pbos12411ef2015-11-23 14:47:56 -080018#include "webrtc/base/platform_thread.h"
ilnikbaded152017-03-17 05:55:25 -070019#include "webrtc/base/task_queue.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010020#include "webrtc/system_wrappers/include/clock.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010021#include "webrtc/system_wrappers/include/sleep.h"
pbos12411ef2015-11-23 14:47:56 -080022#include "webrtc/test/frame_generator.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000023#include "webrtc/video_send_stream.h"
pbos@webrtc.org26d12102013-05-29 13:41:03 +000024
25namespace webrtc {
26namespace test {
27
ilnikbaded152017-03-17 05:55:25 -070028class FrameGeneratorCapturer::InsertFrameTask : public rtc::QueuedTask {
29 public:
30 // Repeats in |repeat_interval_ms|. One-time if |repeat_interval_ms| == 0.
31 InsertFrameTask(
32 webrtc::test::FrameGeneratorCapturer* frame_generator_capturer,
33 uint32_t repeat_interval_ms)
34 : frame_generator_capturer_(frame_generator_capturer),
35 repeat_interval_ms_(repeat_interval_ms),
36 intended_run_time_ms_(-1) {}
37
38 private:
39 bool Run() override {
40 if (repeat_interval_ms_ > 0) {
lliuuf9ed2352017-03-30 10:44:38 -070041 int64_t delay_ms;
42 int64_t time_now_ms = rtc::TimeMillis();
43 if (intended_run_time_ms_ > 0) {
44 delay_ms = time_now_ms - intended_run_time_ms_;
skvlad8b45b112017-03-21 13:26:06 -070045 } else {
lliuuf9ed2352017-03-30 10:44:38 -070046 delay_ms = 0;
47 intended_run_time_ms_ = time_now_ms;
48 }
49 intended_run_time_ms_ += repeat_interval_ms_;
50 if (delay_ms < repeat_interval_ms_) {
51 rtc::TaskQueue::Current()->PostDelayedTask(
52 std::unique_ptr<rtc::QueuedTask>(this),
53 repeat_interval_ms_ - delay_ms);
54 } else {
55 rtc::TaskQueue::Current()->PostDelayedTask(
56 std::unique_ptr<rtc::QueuedTask>(this), 0);
57 LOG(LS_ERROR)
58 << "Frame Generator Capturer can't keep up with requested fps";
ilnikbaded152017-03-17 05:55:25 -070059 }
60 }
61 frame_generator_capturer_->InsertFrame();
62 // Task should be deleted only if it's not repeating.
lliuuf9ed2352017-03-30 10:44:38 -070063 return repeat_interval_ms_ == 0;
ilnikbaded152017-03-17 05:55:25 -070064 }
65
66 webrtc::test::FrameGeneratorCapturer* const frame_generator_capturer_;
67 const uint32_t repeat_interval_ms_;
68 int64_t intended_run_time_ms_;
69};
70
perkja8ba1952017-02-27 06:52:10 -080071FrameGeneratorCapturer* FrameGeneratorCapturer::Create(int width,
72 int height,
Peter Boström4b91bd02015-06-26 06:58:16 +020073 int target_fps,
74 Clock* clock) {
lliuuf9ed2352017-03-30 10:44:38 -070075 FrameGeneratorCapturer* capturer = new FrameGeneratorCapturer(
76 clock, FrameGenerator::CreateSquareGenerator(width, height), target_fps);
77 if (!capturer->Init()) {
78 delete capturer;
79 return NULL;
80 }
pbos@webrtc.org26d12102013-05-29 13:41:03 +000081
lliuuf9ed2352017-03-30 10:44:38 -070082 return capturer;
pbos@webrtc.org26d12102013-05-29 13:41:03 +000083}
84
andresp@webrtc.orgab654952013-09-19 12:14:03 +000085FrameGeneratorCapturer* FrameGeneratorCapturer::CreateFromYuvFile(
sprang@webrtc.org131bea82015-02-18 12:46:06 +000086 const std::string& file_name,
andresp@webrtc.orgab654952013-09-19 12:14:03 +000087 size_t width,
88 size_t height,
89 int target_fps,
90 Clock* clock) {
lliuuf9ed2352017-03-30 10:44:38 -070091 FrameGeneratorCapturer* capturer = new FrameGeneratorCapturer(
92 clock, FrameGenerator::CreateFromYuvFile(
93 std::vector<std::string>(1, file_name), width, height, 1),
94 target_fps);
95 if (!capturer->Init()) {
96 delete capturer;
97 return NULL;
98 }
andresp@webrtc.orgab654952013-09-19 12:14:03 +000099
lliuuf9ed2352017-03-30 10:44:38 -0700100 return capturer;
andresp@webrtc.orgab654952013-09-19 12:14:03 +0000101}
102
perkja8ba1952017-02-27 06:52:10 -0800103FrameGeneratorCapturer::FrameGeneratorCapturer(
104 Clock* clock,
105 std::unique_ptr<FrameGenerator> frame_generator,
106 int target_fps)
perkja49cbd32016-09-16 07:53:41 -0700107 : clock_(clock),
pbos@webrtc.org26d12102013-05-29 13:41:03 +0000108 sending_(false),
perkja49cbd32016-09-16 07:53:41 -0700109 sink_(nullptr),
perkj803d97f2016-11-01 11:45:46 -0700110 sink_wants_observer_(nullptr),
perkja8ba1952017-02-27 06:52:10 -0800111 frame_generator_(std::move(frame_generator)),
wu@webrtc.orgcd701192014-04-24 22:10:24 +0000112 target_fps_(target_fps),
ilnikbaded152017-03-17 05:55:25 -0700113 first_frame_capture_time_(-1),
114 task_queue_("FrameGenCapQ",
115 rtc::TaskQueue::Priority::HIGH) {
perkja8ba1952017-02-27 06:52:10 -0800116 RTC_DCHECK(frame_generator_);
perkja49cbd32016-09-16 07:53:41 -0700117 RTC_DCHECK_GT(target_fps, 0);
pbos@webrtc.org26d12102013-05-29 13:41:03 +0000118}
119
120FrameGeneratorCapturer::~FrameGeneratorCapturer() {
121 Stop();
pbos@webrtc.org26d12102013-05-29 13:41:03 +0000122}
123
Perba7dc722016-04-19 15:01:23 +0200124void FrameGeneratorCapturer::SetFakeRotation(VideoRotation rotation) {
125 rtc::CritScope cs(&lock_);
126 fake_rotation_ = rotation;
127}
128
pbos@webrtc.org26d12102013-05-29 13:41:03 +0000129bool FrameGeneratorCapturer::Init() {
pbos@webrtc.org94015242013-10-16 11:05:37 +0000130 // This check is added because frame_generator_ might be file based and should
131 // not crash because a file moved.
lliuuf9ed2352017-03-30 10:44:38 -0700132 if (frame_generator_.get() == NULL)
pbos@webrtc.org94015242013-10-16 11:05:37 +0000133 return false;
134
ilnikbaded152017-03-17 05:55:25 -0700135 task_queue_.PostDelayedTask(
136 std::unique_ptr<rtc::QueuedTask>(
lliuuf9ed2352017-03-30 10:44:38 -0700137 new InsertFrameTask(this, 1000 / target_fps_)),
138 1000 / target_fps_);
pbos@webrtc.org26d12102013-05-29 13:41:03 +0000139
pbos@webrtc.org26d12102013-05-29 13:41:03 +0000140 return true;
141}
142
143void FrameGeneratorCapturer::InsertFrame() {
lliuuf9ed2352017-03-30 10:44:38 -0700144 {
145 rtc::CritScope cs(&lock_);
146 if (sending_) {
147 VideoFrame* frame = frame_generator_->NextFrame();
148 frame->set_ntp_time_ms(clock_->CurrentNtpInMilliseconds());
149 frame->set_rotation(fake_rotation_);
150 if (first_frame_capture_time_ == -1) {
151 first_frame_capture_time_ = frame->ntp_time_ms();
152 }
153 if (sink_)
154 sink_->OnFrame(*frame);
andresp@webrtc.orgab654952013-09-19 12:14:03 +0000155 }
pbos@webrtc.org26d12102013-05-29 13:41:03 +0000156 }
pbos@webrtc.org26d12102013-05-29 13:41:03 +0000157}
158
159void FrameGeneratorCapturer::Start() {
Peter Boströmf2f82832015-05-01 13:00:41 +0200160 rtc::CritScope cs(&lock_);
pbos@webrtc.org26d12102013-05-29 13:41:03 +0000161 sending_ = true;
162}
163
164void FrameGeneratorCapturer::Stop() {
Peter Boströmf2f82832015-05-01 13:00:41 +0200165 rtc::CritScope cs(&lock_);
pbos@webrtc.org26d12102013-05-29 13:41:03 +0000166 sending_ = false;
167}
sprang867fb522015-08-03 04:38:41 -0700168
perkjfa10b552016-10-02 23:45:26 -0700169void FrameGeneratorCapturer::ChangeResolution(size_t width, size_t height) {
170 rtc::CritScope cs(&lock_);
171 frame_generator_->ChangeResolution(width, height);
172}
173
perkj803d97f2016-11-01 11:45:46 -0700174void FrameGeneratorCapturer::SetSinkWantsObserver(SinkWantsObserver* observer) {
175 rtc::CritScope cs(&lock_);
176 RTC_DCHECK(!sink_wants_observer_);
177 sink_wants_observer_ = observer;
178}
179
perkja49cbd32016-09-16 07:53:41 -0700180void FrameGeneratorCapturer::AddOrUpdateSink(
181 rtc::VideoSinkInterface<VideoFrame>* sink,
182 const rtc::VideoSinkWants& wants) {
183 rtc::CritScope cs(&lock_);
perkj803d97f2016-11-01 11:45:46 -0700184 RTC_CHECK(!sink_ || sink_ == sink);
perkja49cbd32016-09-16 07:53:41 -0700185 sink_ = sink;
perkj803d97f2016-11-01 11:45:46 -0700186 if (sink_wants_observer_)
187 sink_wants_observer_->OnSinkWantsChanged(sink, wants);
perkja49cbd32016-09-16 07:53:41 -0700188}
189
190void FrameGeneratorCapturer::RemoveSink(
191 rtc::VideoSinkInterface<VideoFrame>* sink) {
192 rtc::CritScope cs(&lock_);
193 RTC_CHECK(sink_ == sink);
194 sink_ = nullptr;
195}
196
sprang867fb522015-08-03 04:38:41 -0700197void FrameGeneratorCapturer::ForceFrame() {
ilnikbaded152017-03-17 05:55:25 -0700198 // One-time non-repeating task,
199 // therefore repeat_interval_ms is 0 in InsertFrameTask()
200 task_queue_.PostTask(
201 std::unique_ptr<rtc::QueuedTask>(new InsertFrameTask(this, 0)));
sprang867fb522015-08-03 04:38:41 -0700202}
ilnikbaded152017-03-17 05:55:25 -0700203
204} // namespace test
205} // namespace webrtc