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

Side by Side Diff: media/video/capture/linux/video_capture_device_linux.cc

Issue 25388002: Eliminates the use of VideoCaptureDevice1 in VideoCaptureDeviceLinux. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 7 years, 2 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 // 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/video/capture/linux/video_capture_device_linux.h" 5 #include "media/video/capture/linux/video_capture_device_linux.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <fcntl.h> 8 #include <fcntl.h>
9 #if defined(OS_OPENBSD) 9 #if defined(OS_OPENBSD)
10 #include <sys/videoio.h> 10 #include <sys/videoio.h>
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
189 delete self; 189 delete self;
190 return NULL; 190 return NULL;
191 } 191 }
192 close(fd); 192 close(fd);
193 193
194 return self; 194 return self;
195 } 195 }
196 196
197 VideoCaptureDeviceLinux::VideoCaptureDeviceLinux(const Name& device_name) 197 VideoCaptureDeviceLinux::VideoCaptureDeviceLinux(const Name& device_name)
198 : state_(kIdle), 198 : state_(kIdle),
199 client_(NULL),
200 device_name_(device_name), 199 device_name_(device_name),
201 device_fd_(-1), 200 device_fd_(-1),
202 v4l2_thread_("V4L2Thread"), 201 v4l2_thread_("V4L2Thread"),
203 buffer_pool_(NULL), 202 buffer_pool_(NULL),
204 buffer_pool_size_(0), 203 buffer_pool_size_(0),
205 timeout_count_(0) { 204 timeout_count_(0) {
206 } 205 }
207 206
208 VideoCaptureDeviceLinux::~VideoCaptureDeviceLinux() { 207 VideoCaptureDeviceLinux::~VideoCaptureDeviceLinux() {
209 state_ = kIdle; 208 state_ = kIdle;
210 // Check if the thread is running. 209 // Check if the thread is running.
211 // This means that the device have not been DeAllocated properly. 210 // This means that the device have not been DeAllocated properly.
212 DCHECK(!v4l2_thread_.IsRunning()); 211 DCHECK(!v4l2_thread_.IsRunning());
213 212
214 v4l2_thread_.Stop(); 213 v4l2_thread_.Stop();
215 if (device_fd_ >= 0) { 214 if (device_fd_ >= 0) {
216 close(device_fd_); 215 close(device_fd_);
217 } 216 }
218 } 217 }
219 218
220 void VideoCaptureDeviceLinux::Allocate( 219 void VideoCaptureDeviceLinux::AllocateAndStart(
221 const VideoCaptureCapability& capture_format, 220 const VideoCaptureCapability& capture_format,
222 VideoCaptureDevice::Client* client) { 221 scoped_ptr<VideoCaptureDevice::Client> client) {
223 if (v4l2_thread_.IsRunning()) { 222 if (v4l2_thread_.IsRunning()) {
224 return; // Wrong state. 223 return; // Wrong state.
225 } 224 }
226 v4l2_thread_.Start(); 225 v4l2_thread_.Start();
227 v4l2_thread_.message_loop() 226 v4l2_thread_.message_loop()->PostTask(
228 ->PostTask(FROM_HERE, 227 FROM_HERE,
229 base::Bind(&VideoCaptureDeviceLinux::OnAllocate, 228 base::Bind(&VideoCaptureDeviceLinux::OnAllocateAndStart,
230 base::Unretained(this), 229 base::Unretained(this),
231 capture_format.width, 230 capture_format.width,
232 capture_format.height, 231 capture_format.height,
233 capture_format.frame_rate, 232 capture_format.frame_rate,
234 client)); 233 base::Passed(&client)));
235 } 234 }
236 235
237 void VideoCaptureDeviceLinux::Start() { 236 void VideoCaptureDeviceLinux::StopAndDeAllocate() {
238 if (!v4l2_thread_.IsRunning()) { 237 if (!v4l2_thread_.IsRunning()) {
239 return; // Wrong state. 238 return; // Wrong state.
240 } 239 }
241 v4l2_thread_.message_loop()->PostTask( 240 v4l2_thread_.message_loop()->PostTask(
242 FROM_HERE, 241 FROM_HERE,
243 base::Bind(&VideoCaptureDeviceLinux::OnStart, base::Unretained(this))); 242 base::Bind(&VideoCaptureDeviceLinux::OnStopAndDeAllocate,
244 }
245
246 void VideoCaptureDeviceLinux::Stop() {
247 if (!v4l2_thread_.IsRunning()) {
248 return; // Wrong state.
249 }
250 v4l2_thread_.message_loop()->PostTask(
251 FROM_HERE,
252 base::Bind(&VideoCaptureDeviceLinux::OnStop, base::Unretained(this)));
253 }
254
255 void VideoCaptureDeviceLinux::DeAllocate() {
256 if (!v4l2_thread_.IsRunning()) {
257 return; // Wrong state.
258 }
259 v4l2_thread_.message_loop()->PostTask(
260 FROM_HERE,
261 base::Bind(&VideoCaptureDeviceLinux::OnDeAllocate,
262 base::Unretained(this))); 243 base::Unretained(this)));
263 v4l2_thread_.Stop(); 244 v4l2_thread_.Stop();
264
265 // Make sure no buffers are still allocated. 245 // Make sure no buffers are still allocated.
266 // This can happen (theoretically) if an error occurs when trying to stop 246 // This can happen (theoretically) if an error occurs when trying to stop
267 // the camera. 247 // the camera.
268 DeAllocateVideoBuffers(); 248 DeAllocateVideoBuffers();
269 } 249 }
270 250
271 const VideoCaptureDevice::Name& VideoCaptureDeviceLinux::device_name() { 251 void VideoCaptureDeviceLinux::OnAllocateAndStart(int width,
272 return device_name_; 252 int height,
273 } 253 int frame_rate,
274 254 scoped_ptr<Client> client) {
275 void VideoCaptureDeviceLinux::OnAllocate(int width,
276 int height,
277 int frame_rate,
278 Client* client) {
279 DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current()); 255 DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current());
280 256
281 client_ = client; 257 client_ = client.Pass();
282 258
283 // Need to open camera with O_RDWR after Linux kernel 3.3. 259 // Need to open camera with O_RDWR after Linux kernel 3.3.
284 if ((device_fd_ = open(device_name_.id().c_str(), O_RDWR)) < 0) { 260 if ((device_fd_ = open(device_name_.id().c_str(), O_RDWR)) < 0) {
285 SetErrorState("Failed to open V4L2 device driver."); 261 SetErrorState("Failed to open V4L2 device driver.");
286 return; 262 return;
287 } 263 }
288 264
289 // Test if this is a V4L2 capture device. 265 // Test if this is a V4L2 capture device.
290 v4l2_capability cap; 266 v4l2_capability cap;
291 if (!((ioctl(device_fd_, VIDIOC_QUERYCAP, &cap) == 0) && 267 if (!((ioctl(device_fd_, VIDIOC_QUERYCAP, &cap) == 0) &&
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
361 // Store our current width and height. 337 // Store our current width and height.
362 VideoCaptureCapability current_settings; 338 VideoCaptureCapability current_settings;
363 current_settings.color = V4l2ColorToVideoCaptureColorFormat( 339 current_settings.color = V4l2ColorToVideoCaptureColorFormat(
364 video_fmt.fmt.pix.pixelformat); 340 video_fmt.fmt.pix.pixelformat);
365 current_settings.width = video_fmt.fmt.pix.width; 341 current_settings.width = video_fmt.fmt.pix.width;
366 current_settings.height = video_fmt.fmt.pix.height; 342 current_settings.height = video_fmt.fmt.pix.height;
367 current_settings.frame_rate = frame_rate; 343 current_settings.frame_rate = frame_rate;
368 current_settings.expected_capture_delay = 0; 344 current_settings.expected_capture_delay = 0;
369 current_settings.interlaced = false; 345 current_settings.interlaced = false;
370 346
371 state_ = kAllocated;
372 // Report the resulting frame size to the client. 347 // Report the resulting frame size to the client.
373 client_->OnFrameInfo(current_settings); 348 client_->OnFrameInfo(current_settings);
374 }
375 349
376 void VideoCaptureDeviceLinux::OnDeAllocate() { 350 // Start capturing.
377 DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current());
378
379 // If we are in error state or capturing
380 // try to stop the camera.
381 if (state_ == kCapturing) {
382 OnStop();
383 }
384 if (state_ == kAllocated) {
385 state_ = kIdle;
386 }
387
388 // We need to close and open the device if we want to change the settings
389 // Otherwise VIDIOC_S_FMT will return error
390 // Sad but true.
391 close(device_fd_);
392 device_fd_ = -1;
393 }
394
395 void VideoCaptureDeviceLinux::OnStart() {
396 DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current());
397
398 if (state_ != kAllocated) {
399 return;
400 }
401
402 if (!AllocateVideoBuffers()) { 351 if (!AllocateVideoBuffers()) {
403 // Error, We can not recover. 352 // Error, We can not recover.
404 SetErrorState("Allocate buffer failed"); 353 SetErrorState("Allocate buffer failed");
405 return; 354 return;
406 } 355 }
407 356
408 // Start UVC camera. 357 // Start UVC camera.
409 v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 358 v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
410 if (ioctl(device_fd_, VIDIOC_STREAMON, &type) == -1) { 359 if (ioctl(device_fd_, VIDIOC_STREAMON, &type) == -1) {
411 SetErrorState("VIDIOC_STREAMON failed"); 360 SetErrorState("VIDIOC_STREAMON failed");
412 return; 361 return;
413 } 362 }
414 363
415 state_ = kCapturing; 364 state_ = kCapturing;
416 // Post task to start fetching frames from v4l2. 365 // Post task to start fetching frames from v4l2.
417 v4l2_thread_.message_loop()->PostTask( 366 v4l2_thread_.message_loop()->PostTask(
418 FROM_HERE, 367 FROM_HERE,
419 base::Bind(&VideoCaptureDeviceLinux::OnCaptureTask, 368 base::Bind(&VideoCaptureDeviceLinux::OnCaptureTask,
420 base::Unretained(this))); 369 base::Unretained(this)));
421 } 370 }
422 371
423 void VideoCaptureDeviceLinux::OnStop() { 372 void VideoCaptureDeviceLinux::OnStopAndDeAllocate() {
424 DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current()); 373 DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current());
425 374
426 state_ = kAllocated;
427
428 v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 375 v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
429 if (ioctl(device_fd_, VIDIOC_STREAMOFF, &type) < 0) { 376 if (ioctl(device_fd_, VIDIOC_STREAMOFF, &type) < 0) {
430 SetErrorState("VIDIOC_STREAMOFF failed"); 377 SetErrorState("VIDIOC_STREAMOFF failed");
431 return; 378 return;
432 } 379 }
433 // We don't dare to deallocate the buffers if we can't stop 380 // We don't dare to deallocate the buffers if we can't stop
434 // the capture device. 381 // the capture device.
435 DeAllocateVideoBuffers(); 382 DeAllocateVideoBuffers();
383
384 // We need to close and open the device if we want to change the settings
385 // Otherwise VIDIOC_S_FMT will return error
386 // Sad but true.
387 close(device_fd_);
388 device_fd_ = -1;
389 state_ = kIdle;
390 client_.reset();
436 } 391 }
437 392
438 void VideoCaptureDeviceLinux::OnCaptureTask() { 393 void VideoCaptureDeviceLinux::OnCaptureTask() {
439 DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current()); 394 DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current());
440 395
441 if (state_ != kCapturing) { 396 if (state_ != kCapturing) {
442 return; 397 return;
443 } 398 }
444 399
445 fd_set r_set; 400 fd_set r_set;
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
574 if (ioctl(device_fd_, VIDIOC_REQBUFS, &r_buffer) < 0) { 529 if (ioctl(device_fd_, VIDIOC_REQBUFS, &r_buffer) < 0) {
575 SetErrorState("Failed to reset buf."); 530 SetErrorState("Failed to reset buf.");
576 } 531 }
577 532
578 delete [] buffer_pool_; 533 delete [] buffer_pool_;
579 buffer_pool_ = NULL; 534 buffer_pool_ = NULL;
580 buffer_pool_size_ = 0; 535 buffer_pool_size_ = 0;
581 } 536 }
582 537
583 void VideoCaptureDeviceLinux::SetErrorState(const std::string& reason) { 538 void VideoCaptureDeviceLinux::SetErrorState(const std::string& reason) {
539 DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current());
ncarter (slow) 2013/10/01 20:45:23 The "theoretical" cleanup call to DeAllocateVideoB
Ami GONE FROM CHROMIUM 2013/10/01 21:17:27 I think line 380 is the reason for the "(theoretic
jiayl 2013/10/01 21:34:17 Done.
584 DVLOG(1) << reason; 540 DVLOG(1) << reason;
585 state_ = kError; 541 state_ = kError;
586 client_->OnError(); 542 client_->OnError();
587 } 543 }
588 544
589 } // namespace media 545 } // namespace media
OLDNEW
« no previous file with comments | « media/video/capture/linux/video_capture_device_linux.h ('k') | media/video/capture/video_capture_device_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698