Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(233)

Side by Side Diff: webrtc/test/frame_generator_capturer.cc

Issue 2716643002: Add framerate to VideoSinkWants and ability to signal on overuse (Closed)
Patch Set: Comments Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
(...skipping 20 matching lines...) Expand all
31 InsertFrameTask( 31 InsertFrameTask(
32 webrtc::test::FrameGeneratorCapturer* frame_generator_capturer, 32 webrtc::test::FrameGeneratorCapturer* frame_generator_capturer,
33 uint32_t repeat_interval_ms) 33 uint32_t repeat_interval_ms)
34 : frame_generator_capturer_(frame_generator_capturer), 34 : frame_generator_capturer_(frame_generator_capturer),
35 repeat_interval_ms_(repeat_interval_ms), 35 repeat_interval_ms_(repeat_interval_ms),
36 intended_run_time_ms_(-1) {} 36 intended_run_time_ms_(-1) {}
37 37
38 private: 38 private:
39 bool Run() override { 39 bool Run() override {
40 if (repeat_interval_ms_ > 0) { 40 if (repeat_interval_ms_ > 0) {
41 int64_t delay_ms; 41 // This is not a one-off frame. Check if the frame interval for this
42 int64_t time_now_ms = rtc::TimeMillis(); 42 // task queue is the same same as the current configures frame rate.
43 if (intended_run_time_ms_ > 0) { 43 uint32_t current_interval_ms =
44 delay_ms = time_now_ms - intended_run_time_ms_; 44 1000 / frame_generator_capturer_->GetCurrentConfiguredFramerate();
45 if (repeat_interval_ms_ != current_interval_ms) {
46 // Frame rate has changed since task was started, create a new instance.
47 rtc::TaskQueue::Current()->PostDelayedTask(
48 std::unique_ptr<rtc::QueuedTask>(new InsertFrameTask(
49 frame_generator_capturer_, current_interval_ms)),
50 current_interval_ms);
45 } else { 51 } else {
46 delay_ms = 0; 52 // Schedule the next frame capture event to happen at approximately the
47 intended_run_time_ms_ = time_now_ms; 53 // correct absolute time point.
48 } 54 int64_t delay_ms;
49 intended_run_time_ms_ += repeat_interval_ms_; 55 int64_t time_now_ms = rtc::TimeMillis();
50 if (delay_ms < repeat_interval_ms_) { 56 if (intended_run_time_ms_ > 0) {
51 rtc::TaskQueue::Current()->PostDelayedTask( 57 delay_ms = time_now_ms - intended_run_time_ms_;
52 std::unique_ptr<rtc::QueuedTask>(this), 58 } else {
53 repeat_interval_ms_ - delay_ms); 59 delay_ms = 0;
54 } else { 60 intended_run_time_ms_ = time_now_ms;
55 rtc::TaskQueue::Current()->PostDelayedTask( 61 }
56 std::unique_ptr<rtc::QueuedTask>(this), 0); 62 intended_run_time_ms_ += repeat_interval_ms_;
57 LOG(LS_ERROR) 63 if (delay_ms < repeat_interval_ms_) {
58 << "Frame Generator Capturer can't keep up with requested fps"; 64 rtc::TaskQueue::Current()->PostDelayedTask(
65 std::unique_ptr<rtc::QueuedTask>(this),
66 repeat_interval_ms_ - delay_ms);
67 } else {
68 rtc::TaskQueue::Current()->PostDelayedTask(
69 std::unique_ptr<rtc::QueuedTask>(this), 0);
70 LOG(LS_ERROR)
71 << "Frame Generator Capturer can't keep up with requested fps";
72 }
59 } 73 }
60 } 74 }
61 frame_generator_capturer_->InsertFrame(); 75 frame_generator_capturer_->InsertFrame();
62 // Task should be deleted only if it's not repeating. 76 // Task should be deleted only if it's not repeating.
63 return repeat_interval_ms_ == 0; 77 return repeat_interval_ms_ == 0;
ilnik 2017/03/20 10:02:52 There is now a memory leak possibility. If a repea
sprang_webrtc 2017/03/20 10:18:45 Good catch! Done.
64 } 78 }
65 79
66 webrtc::test::FrameGeneratorCapturer* const frame_generator_capturer_; 80 webrtc::test::FrameGeneratorCapturer* const frame_generator_capturer_;
67 const uint32_t repeat_interval_ms_; 81 const uint32_t repeat_interval_ms_;
68 int64_t intended_run_time_ms_; 82 int64_t intended_run_time_ms_;
69 }; 83 };
70 84
71 FrameGeneratorCapturer* FrameGeneratorCapturer::Create(int width, 85 FrameGeneratorCapturer* FrameGeneratorCapturer::Create(int width,
72 int height, 86 int height,
73 int target_fps, 87 int target_fps,
74 Clock* clock) { 88 Clock* clock) {
75 FrameGeneratorCapturer* capturer = new FrameGeneratorCapturer( 89 std::unique_ptr<FrameGeneratorCapturer> capturer(new FrameGeneratorCapturer(
76 clock, FrameGenerator::CreateSquareGenerator(width, height), target_fps); 90 clock, FrameGenerator::CreateSquareGenerator(width, height), target_fps));
77 if (!capturer->Init()) { 91 if (!capturer->Init())
78 delete capturer; 92 return nullptr;
79 return NULL;
80 }
81 93
82 return capturer; 94 return capturer.release();
83 } 95 }
84 96
85 FrameGeneratorCapturer* FrameGeneratorCapturer::CreateFromYuvFile( 97 FrameGeneratorCapturer* FrameGeneratorCapturer::CreateFromYuvFile(
86 const std::string& file_name, 98 const std::string& file_name,
87 size_t width, 99 size_t width,
88 size_t height, 100 size_t height,
89 int target_fps, 101 int target_fps,
90 Clock* clock) { 102 Clock* clock) {
91 FrameGeneratorCapturer* capturer = new FrameGeneratorCapturer( 103 std::unique_ptr<FrameGeneratorCapturer> capturer(new FrameGeneratorCapturer(
92 clock, FrameGenerator::CreateFromYuvFile( 104 clock,
93 std::vector<std::string>(1, file_name), width, height, 1), 105 FrameGenerator::CreateFromYuvFile(std::vector<std::string>(1, file_name),
94 target_fps); 106 width, height, 1),
95 if (!capturer->Init()) { 107 target_fps));
96 delete capturer; 108 if (!capturer->Init())
97 return NULL; 109 return nullptr;
98 }
99 110
100 return capturer; 111 return capturer.release();
101 } 112 }
102 113
103 FrameGeneratorCapturer::FrameGeneratorCapturer( 114 FrameGeneratorCapturer::FrameGeneratorCapturer(
104 Clock* clock, 115 Clock* clock,
105 std::unique_ptr<FrameGenerator> frame_generator, 116 std::unique_ptr<FrameGenerator> frame_generator,
106 int target_fps) 117 int target_fps)
107 : clock_(clock), 118 : clock_(clock),
108 sending_(false), 119 sending_(false),
109 sink_(nullptr), 120 sink_(nullptr),
110 sink_wants_observer_(nullptr), 121 sink_wants_observer_(nullptr),
(...skipping 11 matching lines...) Expand all
122 } 133 }
123 134
124 void FrameGeneratorCapturer::SetFakeRotation(VideoRotation rotation) { 135 void FrameGeneratorCapturer::SetFakeRotation(VideoRotation rotation) {
125 rtc::CritScope cs(&lock_); 136 rtc::CritScope cs(&lock_);
126 fake_rotation_ = rotation; 137 fake_rotation_ = rotation;
127 } 138 }
128 139
129 bool FrameGeneratorCapturer::Init() { 140 bool FrameGeneratorCapturer::Init() {
130 // This check is added because frame_generator_ might be file based and should 141 // This check is added because frame_generator_ might be file based and should
131 // not crash because a file moved. 142 // not crash because a file moved.
132 if (frame_generator_.get() == NULL) 143 if (frame_generator_.get() == nullptr)
133 return false; 144 return false;
134 145
146 int framerate_fps = GetCurrentConfiguredFramerate();
135 task_queue_.PostDelayedTask( 147 task_queue_.PostDelayedTask(
136 std::unique_ptr<rtc::QueuedTask>( 148 std::unique_ptr<rtc::QueuedTask>(
137 new InsertFrameTask(this, 1000 / target_fps_)), 149 new InsertFrameTask(this, 1000 / framerate_fps)),
138 1000 / target_fps_); 150 1000 / framerate_fps);
139 151
140 return true; 152 return true;
141 } 153 }
142 154
143 void FrameGeneratorCapturer::InsertFrame() { 155 void FrameGeneratorCapturer::InsertFrame() {
144 { 156 rtc::CritScope cs(&lock_);
145 rtc::CritScope cs(&lock_); 157 if (sending_) {
146 if (sending_) { 158 VideoFrame* frame = frame_generator_->NextFrame();
147 VideoFrame* frame = frame_generator_->NextFrame(); 159 frame->set_ntp_time_ms(clock_->CurrentNtpInMilliseconds());
148 frame->set_ntp_time_ms(clock_->CurrentNtpInMilliseconds()); 160 frame->set_rotation(fake_rotation_);
149 frame->set_rotation(fake_rotation_); 161 if (first_frame_capture_time_ == -1) {
150 if (first_frame_capture_time_ == -1) { 162 first_frame_capture_time_ = frame->ntp_time_ms();
151 first_frame_capture_time_ = frame->ntp_time_ms(); 163 }
152 } 164
153 if (sink_) 165 if (sink_) {
154 sink_->OnFrame(*frame); 166 rtc::Optional<VideoFrame> out_frame = AdaptFrame(*frame);
167 if (out_frame)
168 sink_->OnFrame(*out_frame);
155 } 169 }
156 } 170 }
157 } 171 }
158 172
159 void FrameGeneratorCapturer::Start() { 173 void FrameGeneratorCapturer::Start() {
160 rtc::CritScope cs(&lock_); 174 rtc::CritScope cs(&lock_);
161 sending_ = true; 175 sending_ = true;
162 } 176 }
163 177
164 void FrameGeneratorCapturer::Stop() { 178 void FrameGeneratorCapturer::Stop() {
(...skipping 13 matching lines...) Expand all
178 } 192 }
179 193
180 void FrameGeneratorCapturer::AddOrUpdateSink( 194 void FrameGeneratorCapturer::AddOrUpdateSink(
181 rtc::VideoSinkInterface<VideoFrame>* sink, 195 rtc::VideoSinkInterface<VideoFrame>* sink,
182 const rtc::VideoSinkWants& wants) { 196 const rtc::VideoSinkWants& wants) {
183 rtc::CritScope cs(&lock_); 197 rtc::CritScope cs(&lock_);
184 RTC_CHECK(!sink_ || sink_ == sink); 198 RTC_CHECK(!sink_ || sink_ == sink);
185 sink_ = sink; 199 sink_ = sink;
186 if (sink_wants_observer_) 200 if (sink_wants_observer_)
187 sink_wants_observer_->OnSinkWantsChanged(sink, wants); 201 sink_wants_observer_->OnSinkWantsChanged(sink, wants);
202
203 // Handle framerate within this class, just pass on resolution for possible
204 // adaptation.
205 rtc::VideoSinkWants resolution_wants = wants;
206 resolution_wants.max_framerate_fps = std::numeric_limits<int>::max();
207 VideoCapturer::AddOrUpdateSink(sink, resolution_wants);
208
209 if (wants.max_framerate_fps < target_fps_)
210 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.
188 } 211 }
189 212
190 void FrameGeneratorCapturer::RemoveSink( 213 void FrameGeneratorCapturer::RemoveSink(
191 rtc::VideoSinkInterface<VideoFrame>* sink) { 214 rtc::VideoSinkInterface<VideoFrame>* sink) {
192 rtc::CritScope cs(&lock_); 215 rtc::CritScope cs(&lock_);
193 RTC_CHECK(sink_ == sink); 216 RTC_CHECK(sink_ == sink);
194 sink_ = nullptr; 217 sink_ = nullptr;
195 } 218 }
196 219
197 void FrameGeneratorCapturer::ForceFrame() { 220 void FrameGeneratorCapturer::ForceFrame() {
198 // One-time non-repeating task, 221 // One-time non-repeating task,
199 // therefore repeat_interval_ms is 0 in InsertFrameTask() 222 // therefore repeat_interval_ms is 0 in InsertFrameTask()
200 task_queue_.PostTask( 223 task_queue_.PostTask(
201 std::unique_ptr<rtc::QueuedTask>(new InsertFrameTask(this, 0))); 224 std::unique_ptr<rtc::QueuedTask>(new InsertFrameTask(this, 0)));
202 } 225 }
203 226
227 int FrameGeneratorCapturer::GetCurrentConfiguredFramerate() {
228 rtc::CritScope cs(&lock_);
229 if (wanted_fps_ && *wanted_fps_ < target_fps_)
230 return *wanted_fps_;
231 return target_fps_;
232 }
233
204 } // namespace test 234 } // namespace test
205 } // namespace webrtc 235 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698