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

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

Issue 292663010: Merge 271560 "Add a ChromeOS implementation of VideoCaptureDevic..." (Closed) Base URL: svn://svn.chromium.org/chrome/branches/1985/src/
Patch Set: 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 25
26 #if defined(OS_CHROMEOS)
27 #include "media/video/capture/linux/video_capture_device_chromeos.h"
28 #endif
29
26 namespace media { 30 namespace media {
27 31
28 // Max number of video buffers VideoCaptureDeviceLinux can allocate. 32 // Max number of video buffers VideoCaptureDeviceLinux can allocate.
29 enum { kMaxVideoBuffers = 2 }; 33 enum { kMaxVideoBuffers = 2 };
30 // Timeout in microseconds v4l2_thread_ blocks waiting for a frame from the hw. 34 // Timeout in microseconds v4l2_thread_ blocks waiting for a frame from the hw.
31 enum { kCaptureTimeoutUs = 200000 }; 35 enum { kCaptureTimeoutUs = 200000 };
32 // The number of continuous timeouts tolerated before treated as error. 36 // The number of continuous timeouts tolerated before treated as error.
33 enum { kContinuousTimeoutLimit = 10 }; 37 enum { kContinuousTimeoutLimit = 10 };
34 // Time to wait in milliseconds before v4l2_thread_ reschedules OnCaptureTask 38 // Time to wait in milliseconds before v4l2_thread_ reschedules OnCaptureTask
35 // if an event is triggered (select) but no video frame is read. 39 // if an event is triggered (select) but no video frame is read.
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
241 std::string usb_id; 245 std::string usb_id;
242 if (!ReadIdFile(vidPath, &usb_id)) 246 if (!ReadIdFile(vidPath, &usb_id))
243 return ""; 247 return "";
244 usb_id.append(":"); 248 usb_id.append(":");
245 if (!ReadIdFile(pidPath, &usb_id)) 249 if (!ReadIdFile(pidPath, &usb_id))
246 return ""; 250 return "";
247 251
248 return usb_id; 252 return usb_id;
249 } 253 }
250 254
251 VideoCaptureDevice* VideoCaptureDevice::Create(const Name& device_name) { 255 VideoCaptureDevice* VideoCaptureDevice::Create(
256 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
257 const Name& device_name) {
258 #if defined(OS_CHROMEOS)
259 VideoCaptureDeviceChromeOS* self =
260 new VideoCaptureDeviceChromeOS(ui_task_runner, device_name);
261 #else
252 VideoCaptureDeviceLinux* self = new VideoCaptureDeviceLinux(device_name); 262 VideoCaptureDeviceLinux* self = new VideoCaptureDeviceLinux(device_name);
263 #endif
253 if (!self) 264 if (!self)
254 return NULL; 265 return NULL;
255 // Test opening the device driver. This is to make sure it is available. 266 // 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 267 // We will reopen it again in our worker thread when someone
257 // allocates the camera. 268 // allocates the camera.
258 base::ScopedFD fd(HANDLE_EINTR(open(device_name.id().c_str(), O_RDONLY))); 269 base::ScopedFD fd(HANDLE_EINTR(open(device_name.id().c_str(), O_RDONLY)));
259 if (!fd.is_valid()) { 270 if (!fd.is_valid()) {
260 DVLOG(1) << "Cannot open device"; 271 DVLOG(1) << "Cannot open device";
261 delete self; 272 delete self;
262 return NULL; 273 return NULL;
263 } 274 }
264 275
265 return self; 276 return self;
266 } 277 }
267 278
268 VideoCaptureDeviceLinux::VideoCaptureDeviceLinux(const Name& device_name) 279 VideoCaptureDeviceLinux::VideoCaptureDeviceLinux(const Name& device_name)
269 : state_(kIdle), 280 : state_(kIdle),
270 device_name_(device_name), 281 device_name_(device_name),
271 v4l2_thread_("V4L2Thread"), 282 v4l2_thread_("V4L2Thread"),
272 buffer_pool_(NULL), 283 buffer_pool_(NULL),
273 buffer_pool_size_(0), 284 buffer_pool_size_(0),
274 timeout_count_(0) {} 285 timeout_count_(0),
286 rotation_(0) {
287 }
275 288
276 VideoCaptureDeviceLinux::~VideoCaptureDeviceLinux() { 289 VideoCaptureDeviceLinux::~VideoCaptureDeviceLinux() {
277 state_ = kIdle; 290 state_ = kIdle;
278 // Check if the thread is running. 291 // Check if the thread is running.
279 // This means that the device have not been DeAllocated properly. 292 // This means that the device have not been DeAllocated properly.
280 DCHECK(!v4l2_thread_.IsRunning()); 293 DCHECK(!v4l2_thread_.IsRunning());
281 v4l2_thread_.Stop(); 294 v4l2_thread_.Stop();
282 } 295 }
283 296
284 void VideoCaptureDeviceLinux::AllocateAndStart( 297 void VideoCaptureDeviceLinux::AllocateAndStart(
(...skipping 21 matching lines...) Expand all
306 FROM_HERE, 319 FROM_HERE,
307 base::Bind(&VideoCaptureDeviceLinux::OnStopAndDeAllocate, 320 base::Bind(&VideoCaptureDeviceLinux::OnStopAndDeAllocate,
308 base::Unretained(this))); 321 base::Unretained(this)));
309 v4l2_thread_.Stop(); 322 v4l2_thread_.Stop();
310 // Make sure no buffers are still allocated. 323 // Make sure no buffers are still allocated.
311 // This can happen (theoretically) if an error occurs when trying to stop 324 // This can happen (theoretically) if an error occurs when trying to stop
312 // the camera. 325 // the camera.
313 DeAllocateVideoBuffers(); 326 DeAllocateVideoBuffers();
314 } 327 }
315 328
329 void VideoCaptureDeviceLinux::SetRotation(int rotation) {
330 if (v4l2_thread_.IsRunning()) {
331 v4l2_thread_.message_loop()->PostTask(
332 FROM_HERE,
333 base::Bind(&VideoCaptureDeviceLinux::SetRotationOnV4L2Thread,
334 base::Unretained(this), rotation));
335 } else {
336 // If the |v4l2_thread_| is not running, there's no race condition and
337 // |rotation_| can be set directly.
338 rotation_ = rotation;
339 }
340 }
341
342 void VideoCaptureDeviceLinux::SetRotationOnV4L2Thread(int rotation) {
343 DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current());
344 DCHECK(rotation >= 0 && rotation < 360 && rotation % 90 == 0);
345 rotation_ = rotation;
346 }
347
316 void VideoCaptureDeviceLinux::OnAllocateAndStart(int width, 348 void VideoCaptureDeviceLinux::OnAllocateAndStart(int width,
317 int height, 349 int height,
318 int frame_rate, 350 int frame_rate,
319 scoped_ptr<Client> client) { 351 scoped_ptr<Client> client) {
320 DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current()); 352 DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current());
321 353
322 client_ = client.Pass(); 354 client_ = client.Pass();
323 355
324 // Need to open camera with O_RDWR after Linux kernel 3.3. 356 // 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))); 357 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; 546 v4l2_buffer buffer;
515 memset(&buffer, 0, sizeof(buffer)); 547 memset(&buffer, 0, sizeof(buffer));
516 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 548 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
517 buffer.memory = V4L2_MEMORY_MMAP; 549 buffer.memory = V4L2_MEMORY_MMAP;
518 // Dequeue a buffer. 550 // Dequeue a buffer.
519 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_DQBUF, &buffer)) == 0) { 551 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_DQBUF, &buffer)) == 0) {
520 client_->OnIncomingCapturedData( 552 client_->OnIncomingCapturedData(
521 static_cast<uint8*>(buffer_pool_[buffer.index].start), 553 static_cast<uint8*>(buffer_pool_[buffer.index].start),
522 buffer.bytesused, 554 buffer.bytesused,
523 capture_format_, 555 capture_format_,
524 0, 556 rotation_,
525 base::TimeTicks::Now()); 557 base::TimeTicks::Now());
526 558
527 // Enqueue the buffer again. 559 // Enqueue the buffer again.
528 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QBUF, &buffer)) == -1) { 560 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QBUF, &buffer)) == -1) {
529 SetErrorState(base::StringPrintf( 561 SetErrorState(base::StringPrintf(
530 "Failed to enqueue capture buffer errno %d", errno)); 562 "Failed to enqueue capture buffer errno %d", errno));
531 } 563 }
532 } else { 564 } else {
533 SetErrorState(base::StringPrintf( 565 SetErrorState(base::StringPrintf(
534 "Failed to dequeue capture buffer errno %d", errno)); 566 "Failed to dequeue capture buffer errno %d", errno));
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
614 646
615 void VideoCaptureDeviceLinux::SetErrorState(const std::string& reason) { 647 void VideoCaptureDeviceLinux::SetErrorState(const std::string& reason) {
616 DCHECK(!v4l2_thread_.IsRunning() || 648 DCHECK(!v4l2_thread_.IsRunning() ||
617 v4l2_thread_.message_loop() == base::MessageLoop::current()); 649 v4l2_thread_.message_loop() == base::MessageLoop::current());
618 DVLOG(1) << reason; 650 DVLOG(1) << reason;
619 state_ = kError; 651 state_ = kError;
620 client_->OnError(reason); 652 client_->OnError(reason);
621 } 653 }
622 654
623 } // namespace media 655 } // namespace media
OLDNEW
« no previous file with comments | « media/video/capture/linux/video_capture_device_linux.h ('k') | media/video/capture/mac/video_capture_device_mac.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698