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

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

Issue 270263008: Add a ChromeOS implementation of VideoCaptureDevice (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Code review fixes Created 6 years, 7 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 | Annotate | Revision Log
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>
11 #else 11 #else
12 #include <linux/videodev2.h> 12 #include <linux/videodev2.h>
13 #endif 13 #endif
14 #include <sys/ioctl.h> 14 #include <sys/ioctl.h>
15 #include <sys/mman.h> 15 #include <sys/mman.h>
16 16
17 #include <list> 17 #include <list>
18 #include <string> 18 #include <string>
19 19
20 #include "base/bind.h" 20 #include "base/bind.h"
21 #include "base/files/file_enumerator.h" 21 #include "base/files/file_enumerator.h"
22 #include "base/files/scoped_file.h" 22 #include "base/files/scoped_file.h"
23 #include "base/posix/eintr_wrapper.h" 23 #include "base/posix/eintr_wrapper.h"
24 #include "base/strings/stringprintf.h" 24 #include "base/strings/stringprintf.h"
25 #if defined(OS_CHROMEOS)
26 #include "media/video/capture/linux/video_capture_device_chromeos.h"
27 #endif
25 28
26 namespace media { 29 namespace media {
27 30
28 // Max number of video buffers VideoCaptureDeviceLinux can allocate. 31 // Max number of video buffers VideoCaptureDeviceLinux can allocate.
29 enum { kMaxVideoBuffers = 2 }; 32 enum { kMaxVideoBuffers = 2 };
30 // Timeout in microseconds v4l2_thread_ blocks waiting for a frame from the hw. 33 // Timeout in microseconds v4l2_thread_ blocks waiting for a frame from the hw.
31 enum { kCaptureTimeoutUs = 200000 }; 34 enum { kCaptureTimeoutUs = 200000 };
32 // The number of continuous timeouts tolerated before treated as error. 35 // The number of continuous timeouts tolerated before treated as error.
33 enum { kContinuousTimeoutLimit = 10 }; 36 enum { kContinuousTimeoutLimit = 10 };
34 // Time to wait in milliseconds before v4l2_thread_ reschedules OnCaptureTask 37 // Time to wait in milliseconds before v4l2_thread_ reschedules OnCaptureTask
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 if (!ReadIdFile(vidPath, &usb_id)) 245 if (!ReadIdFile(vidPath, &usb_id))
243 return ""; 246 return "";
244 usb_id.append(":"); 247 usb_id.append(":");
245 if (!ReadIdFile(pidPath, &usb_id)) 248 if (!ReadIdFile(pidPath, &usb_id))
246 return ""; 249 return "";
247 250
248 return usb_id; 251 return usb_id;
249 } 252 }
250 253
251 VideoCaptureDevice* VideoCaptureDevice::Create(const Name& device_name) { 254 VideoCaptureDevice* VideoCaptureDevice::Create(const Name& device_name) {
255 #if defined(OS_CHROMEOS)
256 VideoCaptureDeviceChromeOS* self =
257 new VideoCaptureDeviceChromeOS(device_name);
258 #else
252 VideoCaptureDeviceLinux* self = new VideoCaptureDeviceLinux(device_name); 259 VideoCaptureDeviceLinux* self = new VideoCaptureDeviceLinux(device_name);
260 #endif
253 if (!self) 261 if (!self)
tommi (sloooow) - chröme 2014/05/13 11:02:51 nit: we don't check the return value from new()
Zachary Kuznia 2014/05/13 13:54:29 Done.
254 return NULL; 262 return NULL;
255 // Test opening the device driver. This is to make sure it is available. 263 // Test opening the device driver. This is to make sure it is available.
256 // We will reopen it again in our worker thread when someone 264 // We will reopen it again in our worker thread when someone
257 // allocates the camera. 265 // allocates the camera.
258 base::ScopedFD fd(HANDLE_EINTR(open(device_name.id().c_str(), O_RDONLY))); 266 base::ScopedFD fd(HANDLE_EINTR(open(device_name.id().c_str(), O_RDONLY)));
259 if (!fd.is_valid()) { 267 if (!fd.is_valid()) {
260 DVLOG(1) << "Cannot open device"; 268 DVLOG(1) << "Cannot open device";
261 delete self; 269 delete self;
262 return NULL; 270 return NULL;
263 } 271 }
264 272
265 return self; 273 return self;
266 } 274 }
267 275
268 VideoCaptureDeviceLinux::VideoCaptureDeviceLinux(const Name& device_name) 276 VideoCaptureDeviceLinux::VideoCaptureDeviceLinux(const Name& device_name)
269 : state_(kIdle), 277 : state_(kIdle),
270 device_name_(device_name), 278 device_name_(device_name),
271 v4l2_thread_("V4L2Thread"), 279 v4l2_thread_("V4L2Thread"),
272 buffer_pool_(NULL), 280 buffer_pool_(NULL),
273 buffer_pool_size_(0), 281 buffer_pool_size_(0),
274 timeout_count_(0) {} 282 timeout_count_(0),
283 rotation_(0) {
284 }
275 285
276 VideoCaptureDeviceLinux::~VideoCaptureDeviceLinux() { 286 VideoCaptureDeviceLinux::~VideoCaptureDeviceLinux() {
277 state_ = kIdle; 287 state_ = kIdle;
278 // Check if the thread is running. 288 // Check if the thread is running.
279 // This means that the device have not been DeAllocated properly. 289 // This means that the device have not been DeAllocated properly.
280 DCHECK(!v4l2_thread_.IsRunning()); 290 DCHECK(!v4l2_thread_.IsRunning());
281 v4l2_thread_.Stop(); 291 v4l2_thread_.Stop();
282 } 292 }
283 293
284 void VideoCaptureDeviceLinux::AllocateAndStart( 294 void VideoCaptureDeviceLinux::AllocateAndStart(
(...skipping 21 matching lines...) Expand all
306 FROM_HERE, 316 FROM_HERE,
307 base::Bind(&VideoCaptureDeviceLinux::OnStopAndDeAllocate, 317 base::Bind(&VideoCaptureDeviceLinux::OnStopAndDeAllocate,
308 base::Unretained(this))); 318 base::Unretained(this)));
309 v4l2_thread_.Stop(); 319 v4l2_thread_.Stop();
310 // Make sure no buffers are still allocated. 320 // Make sure no buffers are still allocated.
311 // This can happen (theoretically) if an error occurs when trying to stop 321 // This can happen (theoretically) if an error occurs when trying to stop
312 // the camera. 322 // the camera.
313 DeAllocateVideoBuffers(); 323 DeAllocateVideoBuffers();
314 } 324 }
315 325
326 void VideoCaptureDeviceLinux::SetRotation(int rotation) {
327 if (v4l2_thread_.IsRunning()) {
328 v4l2_thread_.message_loop()->PostTask(
329 FROM_HERE,
330 base::Bind(&VideoCaptureDeviceLinux::SetRotationOnV4L2Thread,
331 base::Unretained(this), rotation));
332 } else {
333 // If the |v4l2_thread_| is not running, there's no race condition and
334 // |rotation_| can be set directly.
335 rotation_ = rotation;
336 }
337 }
338
339 void VideoCaptureDeviceLinux::SetRotationOnV4L2Thread(int rotation) {
340 DCHECK(v4l2_thread_.IsRunning() &&
341 v4l2_thread_.message_loop() == base::MessageLoop::current());
tommi (sloooow) - chröme 2014/05/13 11:02:51 BelongsToCurrentThread()?
Zachary Kuznia 2014/05/13 13:54:29 Done.
342 rotation_ = rotation;
tommi (sloooow) - chröme 2014/05/13 11:02:51 DCHECK valid values of rotation?
Zachary Kuznia 2014/05/13 13:54:29 Done.
343 }
344
316 void VideoCaptureDeviceLinux::OnAllocateAndStart(int width, 345 void VideoCaptureDeviceLinux::OnAllocateAndStart(int width,
317 int height, 346 int height,
318 int frame_rate, 347 int frame_rate,
319 scoped_ptr<Client> client) { 348 scoped_ptr<Client> client) {
320 DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current()); 349 DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current());
321 350
322 client_ = client.Pass(); 351 client_ = client.Pass();
323 352
324 // Need to open camera with O_RDWR after Linux kernel 3.3. 353 // Need to open camera with O_RDWR after Linux kernel 3.3.
325 device_fd_.reset(HANDLE_EINTR(open(device_name_.id().c_str(), O_RDWR))); 354 device_fd_.reset(HANDLE_EINTR(open(device_name_.id().c_str(), O_RDWR)));
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
514 v4l2_buffer buffer; 543 v4l2_buffer buffer;
515 memset(&buffer, 0, sizeof(buffer)); 544 memset(&buffer, 0, sizeof(buffer));
516 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 545 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
517 buffer.memory = V4L2_MEMORY_MMAP; 546 buffer.memory = V4L2_MEMORY_MMAP;
518 // Dequeue a buffer. 547 // Dequeue a buffer.
519 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_DQBUF, &buffer)) == 0) { 548 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_DQBUF, &buffer)) == 0) {
520 client_->OnIncomingCapturedData( 549 client_->OnIncomingCapturedData(
521 static_cast<uint8*>(buffer_pool_[buffer.index].start), 550 static_cast<uint8*>(buffer_pool_[buffer.index].start),
522 buffer.bytesused, 551 buffer.bytesused,
523 capture_format_, 552 capture_format_,
524 0, 553 rotation_,
525 base::TimeTicks::Now()); 554 base::TimeTicks::Now());
526 555
527 // Enqueue the buffer again. 556 // Enqueue the buffer again.
528 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QBUF, &buffer)) == -1) { 557 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QBUF, &buffer)) == -1) {
529 SetErrorState(base::StringPrintf( 558 SetErrorState(base::StringPrintf(
530 "Failed to enqueue capture buffer errno %d", errno)); 559 "Failed to enqueue capture buffer errno %d", errno));
531 } 560 }
532 } else { 561 } else {
533 SetErrorState(base::StringPrintf( 562 SetErrorState(base::StringPrintf(
534 "Failed to dequeue capture buffer errno %d", errno)); 563 "Failed to dequeue capture buffer errno %d", errno));
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
614 643
615 void VideoCaptureDeviceLinux::SetErrorState(const std::string& reason) { 644 void VideoCaptureDeviceLinux::SetErrorState(const std::string& reason) {
616 DCHECK(!v4l2_thread_.IsRunning() || 645 DCHECK(!v4l2_thread_.IsRunning() ||
617 v4l2_thread_.message_loop() == base::MessageLoop::current()); 646 v4l2_thread_.message_loop() == base::MessageLoop::current());
618 DVLOG(1) << reason; 647 DVLOG(1) << reason;
619 state_ = kError; 648 state_ = kError;
620 client_->OnError(reason); 649 client_->OnError(reason);
621 } 650 }
622 651
623 } // namespace media 652 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698