OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/capture/video/fake_video_capture_device.h" | 5 #include "media/capture/video/fake_video_capture_device.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <algorithm> | 8 #include <algorithm> |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
(...skipping 10 matching lines...) Expand all Loading... |
21 #include "third_party/skia/include/core/SkMatrix.h" | 21 #include "third_party/skia/include/core/SkMatrix.h" |
22 #include "third_party/skia/include/core/SkPaint.h" | 22 #include "third_party/skia/include/core/SkPaint.h" |
23 #include "ui/gfx/codec/png_codec.h" | 23 #include "ui/gfx/codec/png_codec.h" |
24 | 24 |
25 namespace media { | 25 namespace media { |
26 | 26 |
27 // Sweep at 600 deg/sec. | 27 // Sweep at 600 deg/sec. |
28 static const float kPacmanAngularVelocity = 600; | 28 static const float kPacmanAngularVelocity = 600; |
29 // Beep every 500 ms. | 29 // Beep every 500 ms. |
30 static const int kBeepInterval = 500; | 30 static const int kBeepInterval = 500; |
| 31 // Gradient travels from bottom to top in 5 seconds. |
| 32 static const float kGradientFrequency = 1.f / 5; |
31 | 33 |
32 static const uint32_t kMinZoom = 100; | 34 static const uint32_t kMinZoom = 100; |
33 static const uint32_t kMaxZoom = 400; | 35 static const uint32_t kMaxZoom = 400; |
34 static const uint32_t kZoomStep = 1; | 36 static const uint32_t kZoomStep = 1; |
35 | 37 |
| 38 // Starting from top left, -45 deg gradient. |
| 39 void Draw16BitGradient(uint8_t* const pixels, |
| 40 base::TimeDelta elapsed_time, |
| 41 const gfx::Size& frame_size) { |
| 42 uint16_t* data = reinterpret_cast<uint16_t*>(pixels); |
| 43 // We calculate the color difference to the neighbour on the right or bellow, |
| 44 // so that value change from top left to bottom right is 65535 (pixel values |
| 45 // are wrapped arounf uint16_t). |
| 46 const float color_step = |
| 47 65535 / static_cast<float>(frame_size.width() + frame_size.height()); |
| 48 float start = |
| 49 fmod(65536 * elapsed_time.InSecondsF() * kGradientFrequency, 65536); |
| 50 for (int j = 0; j < frame_size.height(); ++j) { |
| 51 float value = start; |
| 52 uint16_t* row = data + j * (frame_size.width()); |
| 53 for (int i = 0; i < frame_size.width(); ++i) { |
| 54 *row++ = static_cast<unsigned>(value) & 0xFFFF; |
| 55 value += color_step; |
| 56 } |
| 57 start += color_step; |
| 58 } |
| 59 } |
| 60 |
36 void DrawPacman(bool use_argb, | 61 void DrawPacman(bool use_argb, |
37 uint8_t* const data, | 62 uint8_t* const data, |
38 base::TimeDelta elapsed_time, | 63 base::TimeDelta elapsed_time, |
39 float frame_rate, | 64 float frame_rate, |
40 const gfx::Size& frame_size, | 65 const gfx::Size& frame_size, |
41 uint32_t zoom) { | 66 uint32_t zoom) { |
42 // |kN32_SkColorType| stands for the appropriate RGBA/BGRA format. | 67 // |kN32_SkColorType| stands for the appropriate RGBA/BGRA format. |
43 const SkColorType colorspace = | 68 const SkColorType colorspace = |
44 use_argb ? kN32_SkColorType : kAlpha_8_SkColorType; | 69 use_argb ? kN32_SkColorType : kAlpha_8_SkColorType; |
45 const SkImageInfo info = SkImageInfo::Make( | 70 const SkImageInfo info = SkImageInfo::Make( |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
107 buffer.get(), gfx::PNGCodec::FORMAT_RGBA, capture_format.frame_size, | 132 buffer.get(), gfx::PNGCodec::FORMAT_RGBA, capture_format.frame_size, |
108 capture_format.frame_size.width() * 4, true /* discard_transparency */, | 133 capture_format.frame_size.width() * 4, true /* discard_transparency */, |
109 std::vector<gfx::PNGCodec::Comment>(), &blob->data); | 134 std::vector<gfx::PNGCodec::Comment>(), &blob->data); |
110 DCHECK(result); | 135 DCHECK(result); |
111 | 136 |
112 blob->mime_type = "image/png"; | 137 blob->mime_type = "image/png"; |
113 callback.Run(std::move(blob)); | 138 callback.Run(std::move(blob)); |
114 } | 139 } |
115 | 140 |
116 FakeVideoCaptureDevice::FakeVideoCaptureDevice(BufferOwnership buffer_ownership, | 141 FakeVideoCaptureDevice::FakeVideoCaptureDevice(BufferOwnership buffer_ownership, |
117 float fake_capture_rate) | 142 float fake_capture_rate, |
| 143 VideoPixelFormat pixel_format) |
118 : buffer_ownership_(buffer_ownership), | 144 : buffer_ownership_(buffer_ownership), |
119 fake_capture_rate_(fake_capture_rate), | 145 fake_capture_rate_(fake_capture_rate), |
| 146 pixel_format_(pixel_format), |
120 current_zoom_(kMinZoom), | 147 current_zoom_(kMinZoom), |
121 weak_factory_(this) {} | 148 weak_factory_(this) {} |
122 | 149 |
123 FakeVideoCaptureDevice::~FakeVideoCaptureDevice() { | 150 FakeVideoCaptureDevice::~FakeVideoCaptureDevice() { |
124 DCHECK(thread_checker_.CalledOnValidThread()); | 151 DCHECK(thread_checker_.CalledOnValidThread()); |
125 } | 152 } |
126 | 153 |
127 void FakeVideoCaptureDevice::AllocateAndStart( | 154 void FakeVideoCaptureDevice::AllocateAndStart( |
128 const VideoCaptureParams& params, | 155 const VideoCaptureParams& params, |
129 std::unique_ptr<VideoCaptureDevice::Client> client) { | 156 std::unique_ptr<VideoCaptureDevice::Client> client) { |
130 DCHECK(thread_checker_.CalledOnValidThread()); | 157 DCHECK(thread_checker_.CalledOnValidThread()); |
131 | 158 |
132 client_ = std::move(client); | 159 client_ = std::move(client); |
133 | 160 |
134 // Incoming |params| can be none of the supported formats, so we get the | 161 // Incoming |params| can be none of the supported formats, so we get the |
135 // closest thing rounded up. TODO(mcasas): Use the |params|, if they belong to | 162 // closest thing rounded up. TODO(mcasas): Use the |params|, if they belong to |
136 // the supported ones, when http://crbug.com/309554 is verified. | 163 // the supported ones, when http://crbug.com/309554 is verified. |
137 capture_format_.frame_rate = fake_capture_rate_; | 164 capture_format_.frame_rate = fake_capture_rate_; |
138 if (params.requested_format.frame_size.width() > 1280) | 165 if (params.requested_format.frame_size.width() > 1280) |
139 capture_format_.frame_size.SetSize(1920, 1080); | 166 capture_format_.frame_size.SetSize(1920, 1080); |
140 else if (params.requested_format.frame_size.width() > 640) | 167 else if (params.requested_format.frame_size.width() > 640) |
141 capture_format_.frame_size.SetSize(1280, 720); | 168 capture_format_.frame_size.SetSize(1280, 720); |
142 else if (params.requested_format.frame_size.width() > 320) | 169 else if (params.requested_format.frame_size.width() > 320) |
143 capture_format_.frame_size.SetSize(640, 480); | 170 capture_format_.frame_size.SetSize(640, 480); |
| 171 else if (params.requested_format.frame_size.width() > 96) |
| 172 capture_format_.frame_size.SetSize(320, 240); |
144 else | 173 else |
145 capture_format_.frame_size.SetSize(320, 240); | 174 capture_format_.frame_size.SetSize(96, 96); |
146 | 175 |
| 176 capture_format_.pixel_format = pixel_format_; |
147 if (buffer_ownership_ == BufferOwnership::CLIENT_BUFFERS) { | 177 if (buffer_ownership_ == BufferOwnership::CLIENT_BUFFERS) { |
148 capture_format_.pixel_storage = PIXEL_STORAGE_CPU; | 178 capture_format_.pixel_storage = PIXEL_STORAGE_CPU; |
149 capture_format_.pixel_format = PIXEL_FORMAT_ARGB; | 179 capture_format_.pixel_format = PIXEL_FORMAT_ARGB; |
150 DVLOG(1) << "starting with client argb buffers"; | 180 DVLOG(1) << "starting with client argb buffers"; |
151 } else if (buffer_ownership_ == BufferOwnership::OWN_BUFFERS) { | 181 } else if (buffer_ownership_ == BufferOwnership::OWN_BUFFERS) { |
152 capture_format_.pixel_storage = PIXEL_STORAGE_CPU; | 182 capture_format_.pixel_storage = PIXEL_STORAGE_CPU; |
153 capture_format_.pixel_format = PIXEL_FORMAT_I420; | 183 DVLOG(1) << "starting with own" << VideoPixelFormatToString(pixel_format_) |
154 DVLOG(1) << "starting with own I420 buffers"; | 184 << "buffers"; |
155 } | 185 } |
156 | 186 |
157 if (capture_format_.pixel_format == PIXEL_FORMAT_I420) { | 187 if (buffer_ownership_ != BufferOwnership::CLIENT_BUFFERS) { |
158 fake_frame_.reset(new uint8_t[VideoFrame::AllocationSize( | 188 fake_frame_.reset(new uint8_t[VideoFrame::AllocationSize( |
159 PIXEL_FORMAT_I420, capture_format_.frame_size)]); | 189 pixel_format_, capture_format_.frame_size)]); |
160 } | 190 } |
161 | 191 |
162 beep_time_ = base::TimeDelta(); | 192 beep_time_ = base::TimeDelta(); |
163 elapsed_time_ = base::TimeDelta(); | 193 elapsed_time_ = base::TimeDelta(); |
164 | 194 |
165 if (buffer_ownership_ == BufferOwnership::CLIENT_BUFFERS) | 195 if (buffer_ownership_ == BufferOwnership::CLIENT_BUFFERS) |
166 BeepAndScheduleNextCapture( | 196 BeepAndScheduleNextCapture( |
167 base::TimeTicks::Now(), | 197 base::TimeTicks::Now(), |
168 base::Bind(&FakeVideoCaptureDevice::CaptureUsingClientBuffers, | 198 base::Bind(&FakeVideoCaptureDevice::CaptureUsingClientBuffers, |
169 weak_factory_.GetWeakPtr())); | 199 weak_factory_.GetWeakPtr())); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
228 base::ThreadTaskRunnerHandle::Get()->PostTask( | 258 base::ThreadTaskRunnerHandle::Get()->PostTask( |
229 FROM_HERE, | 259 FROM_HERE, |
230 base::Bind(&DoTakeFakePhoto, base::Passed(&callback), capture_format_, | 260 base::Bind(&DoTakeFakePhoto, base::Passed(&callback), capture_format_, |
231 elapsed_time_, fake_capture_rate_, current_zoom_)); | 261 elapsed_time_, fake_capture_rate_, current_zoom_)); |
232 } | 262 } |
233 | 263 |
234 void FakeVideoCaptureDevice::CaptureUsingOwnBuffers( | 264 void FakeVideoCaptureDevice::CaptureUsingOwnBuffers( |
235 base::TimeTicks expected_execution_time) { | 265 base::TimeTicks expected_execution_time) { |
236 DCHECK(thread_checker_.CalledOnValidThread()); | 266 DCHECK(thread_checker_.CalledOnValidThread()); |
237 const size_t frame_size = capture_format_.ImageAllocationSize(); | 267 const size_t frame_size = capture_format_.ImageAllocationSize(); |
238 memset(fake_frame_.get(), 0, frame_size); | |
239 | 268 |
240 DrawPacman(false /* use_argb */, fake_frame_.get(), elapsed_time_, | 269 if (capture_format_.pixel_format == media::PIXEL_FORMAT_Y16) { |
241 fake_capture_rate_, capture_format_.frame_size, current_zoom_); | 270 Draw16BitGradient(fake_frame_.get(), elapsed_time_, |
242 | 271 capture_format_.frame_size); |
| 272 } else { |
| 273 memset(fake_frame_.get(), 0, frame_size); |
| 274 DrawPacman(false /* use_argb */, fake_frame_.get(), elapsed_time_, |
| 275 fake_capture_rate_, capture_format_.frame_size, current_zoom_); |
| 276 } |
243 // Give the captured frame to the client. | 277 // Give the captured frame to the client. |
244 base::TimeTicks now = base::TimeTicks::Now(); | 278 base::TimeTicks now = base::TimeTicks::Now(); |
245 if (first_ref_time_.is_null()) | 279 if (first_ref_time_.is_null()) |
246 first_ref_time_ = now; | 280 first_ref_time_ = now; |
247 client_->OnIncomingCapturedData(fake_frame_.get(), frame_size, | 281 client_->OnIncomingCapturedData(fake_frame_.get(), frame_size, |
248 capture_format_, 0 /* rotation */, now, | 282 capture_format_, 0 /* rotation */, now, |
249 now - first_ref_time_); | 283 now - first_ref_time_); |
250 BeepAndScheduleNextCapture( | 284 BeepAndScheduleNextCapture( |
251 expected_execution_time, | 285 expected_execution_time, |
252 base::Bind(&FakeVideoCaptureDevice::CaptureUsingOwnBuffers, | 286 base::Bind(&FakeVideoCaptureDevice::CaptureUsingOwnBuffers, |
253 weak_factory_.GetWeakPtr())); | 287 weak_factory_.GetWeakPtr())); |
254 } | 288 } |
255 | 289 |
256 void FakeVideoCaptureDevice::CaptureUsingClientBuffers( | 290 void FakeVideoCaptureDevice::CaptureUsingClientBuffers( |
257 base::TimeTicks expected_execution_time) { | 291 base::TimeTicks expected_execution_time) { |
258 DCHECK(thread_checker_.CalledOnValidThread()); | 292 DCHECK(thread_checker_.CalledOnValidThread()); |
259 | 293 |
260 std::unique_ptr<VideoCaptureDevice::Client::Buffer> capture_buffer( | 294 std::unique_ptr<VideoCaptureDevice::Client::Buffer> capture_buffer( |
261 client_->ReserveOutputBuffer(capture_format_.frame_size, | 295 client_->ReserveOutputBuffer(capture_format_.frame_size, |
262 capture_format_.pixel_format, | 296 capture_format_.pixel_format, |
263 capture_format_.pixel_storage)); | 297 capture_format_.pixel_storage)); |
264 DLOG_IF(ERROR, !capture_buffer) << "Couldn't allocate Capture Buffer"; | 298 DLOG_IF(ERROR, !capture_buffer) << "Couldn't allocate Capture Buffer"; |
265 DCHECK(capture_buffer->data()) << "Buffer has NO backing memory"; | 299 DCHECK(capture_buffer->data()) << "Buffer has NO backing memory"; |
266 | 300 |
267 DCHECK_EQ(PIXEL_STORAGE_CPU, capture_format_.pixel_storage); | 301 if (capture_format_.pixel_format == media::PIXEL_FORMAT_Y16) { |
268 DCHECK_EQ(PIXEL_FORMAT_ARGB, capture_format_.pixel_format); | 302 Draw16BitGradient(static_cast<uint8_t*>(capture_buffer->data()), |
269 uint8_t* data_ptr = static_cast<uint8_t*>(capture_buffer->data()); | 303 elapsed_time_, capture_format_.frame_size); |
270 memset(data_ptr, 0, capture_buffer->mapped_size()); | 304 } else { |
271 DrawPacman(true /* use_argb */, data_ptr, elapsed_time_, fake_capture_rate_, | 305 DCHECK_EQ(PIXEL_STORAGE_CPU, capture_format_.pixel_storage); |
272 capture_format_.frame_size, current_zoom_); | 306 DCHECK_EQ(PIXEL_FORMAT_ARGB, capture_format_.pixel_format); |
| 307 uint8_t* data_ptr = static_cast<uint8_t*>(capture_buffer->data()); |
| 308 memset(data_ptr, 0, capture_buffer->mapped_size()); |
| 309 DrawPacman(true /* use_argb */, data_ptr, elapsed_time_, fake_capture_rate_, |
| 310 capture_format_.frame_size, current_zoom_); |
| 311 } |
273 | 312 |
274 // Give the captured frame to the client. | 313 // Give the captured frame to the client. |
275 base::TimeTicks now = base::TimeTicks::Now(); | 314 base::TimeTicks now = base::TimeTicks::Now(); |
276 if (first_ref_time_.is_null()) | 315 if (first_ref_time_.is_null()) |
277 first_ref_time_ = now; | 316 first_ref_time_ = now; |
278 client_->OnIncomingCapturedBuffer(std::move(capture_buffer), capture_format_, | 317 client_->OnIncomingCapturedBuffer(std::move(capture_buffer), capture_format_, |
279 now, now - first_ref_time_); | 318 now, now - first_ref_time_); |
280 | 319 |
281 BeepAndScheduleNextCapture( | 320 BeepAndScheduleNextCapture( |
282 expected_execution_time, | 321 expected_execution_time, |
(...skipping 22 matching lines...) Expand all Loading... |
305 // Don't accumulate any debt if we are lagging behind - just post the next | 344 // Don't accumulate any debt if we are lagging behind - just post the next |
306 // frame immediately and continue as normal. | 345 // frame immediately and continue as normal. |
307 const base::TimeTicks next_execution_time = | 346 const base::TimeTicks next_execution_time = |
308 std::max(current_time, expected_execution_time + frame_interval); | 347 std::max(current_time, expected_execution_time + frame_interval); |
309 const base::TimeDelta delay = next_execution_time - current_time; | 348 const base::TimeDelta delay = next_execution_time - current_time; |
310 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | 349 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
311 FROM_HERE, base::Bind(next_capture, next_execution_time), delay); | 350 FROM_HERE, base::Bind(next_capture, next_execution_time), delay); |
312 } | 351 } |
313 | 352 |
314 } // namespace media | 353 } // namespace media |
OLD | NEW |