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

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: Rebase 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 #include "ui/gfx/screen.h"
25 26
26 namespace media { 27 namespace media {
27 28
28 // Max number of video buffers VideoCaptureDeviceLinux can allocate. 29 // Max number of video buffers VideoCaptureDeviceLinux can allocate.
29 enum { kMaxVideoBuffers = 2 }; 30 enum { kMaxVideoBuffers = 2 };
30 // Timeout in microseconds v4l2_thread_ blocks waiting for a frame from the hw. 31 // Timeout in microseconds v4l2_thread_ blocks waiting for a frame from the hw.
31 enum { kCaptureTimeoutUs = 200000 }; 32 enum { kCaptureTimeoutUs = 200000 };
32 // The number of continuous timeouts tolerated before treated as error. 33 // The number of continuous timeouts tolerated before treated as error.
33 enum { kContinuousTimeoutLimit = 10 }; 34 enum { kContinuousTimeoutLimit = 10 };
34 // Time to wait in milliseconds before v4l2_thread_ reschedules OnCaptureTask 35 // Time to wait in milliseconds before v4l2_thread_ reschedules OnCaptureTask
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after
264 265
265 return self; 266 return self;
266 } 267 }
267 268
268 VideoCaptureDeviceLinux::VideoCaptureDeviceLinux(const Name& device_name) 269 VideoCaptureDeviceLinux::VideoCaptureDeviceLinux(const Name& device_name)
269 : state_(kIdle), 270 : state_(kIdle),
270 device_name_(device_name), 271 device_name_(device_name),
271 v4l2_thread_("V4L2Thread"), 272 v4l2_thread_("V4L2Thread"),
272 buffer_pool_(NULL), 273 buffer_pool_(NULL),
273 buffer_pool_size_(0), 274 buffer_pool_size_(0),
274 timeout_count_(0) {} 275 timeout_count_(0),
276 display_rotation_(gfx::Display::ROTATE_0) {
277 gfx::Screen* screen =
perkj_chrome 2014/05/09 10:11:28 This will be called on a special thread used only
278 gfx::Screen::GetScreenByType(gfx::SCREEN_TYPE_ALTERNATE);
279 if (screen) {
280 SetDisplayRotation(screen->GetPrimaryDisplay());
281 screen->AddObserver(this);
282 }
283 }
275 284
276 VideoCaptureDeviceLinux::~VideoCaptureDeviceLinux() { 285 VideoCaptureDeviceLinux::~VideoCaptureDeviceLinux() {
286 gfx::Screen* screen =
287 gfx::Screen::GetScreenByType(gfx::SCREEN_TYPE_ALTERNATE);
perkj_chrome 2014/05/09 10:11:28 Can there be a race here? ie, is it ok to not call
288 if (screen)
289 screen->RemoveObserver(this);
290
277 state_ = kIdle; 291 state_ = kIdle;
278 // Check if the thread is running. 292 // Check if the thread is running.
279 // This means that the device have not been DeAllocated properly. 293 // This means that the device have not been DeAllocated properly.
280 DCHECK(!v4l2_thread_.IsRunning()); 294 DCHECK(!v4l2_thread_.IsRunning());
281 v4l2_thread_.Stop(); 295 v4l2_thread_.Stop();
282 } 296 }
283 297
284 void VideoCaptureDeviceLinux::AllocateAndStart( 298 void VideoCaptureDeviceLinux::AllocateAndStart(
285 const VideoCaptureParams& params, 299 const VideoCaptureParams& params,
286 scoped_ptr<VideoCaptureDevice::Client> client) { 300 scoped_ptr<VideoCaptureDevice::Client> client) {
(...skipping 19 matching lines...) Expand all
306 FROM_HERE, 320 FROM_HERE,
307 base::Bind(&VideoCaptureDeviceLinux::OnStopAndDeAllocate, 321 base::Bind(&VideoCaptureDeviceLinux::OnStopAndDeAllocate,
308 base::Unretained(this))); 322 base::Unretained(this)));
309 v4l2_thread_.Stop(); 323 v4l2_thread_.Stop();
310 // Make sure no buffers are still allocated. 324 // Make sure no buffers are still allocated.
311 // This can happen (theoretically) if an error occurs when trying to stop 325 // This can happen (theoretically) if an error occurs when trying to stop
312 // the camera. 326 // the camera.
313 DeAllocateVideoBuffers(); 327 DeAllocateVideoBuffers();
314 } 328 }
315 329
330 void VideoCaptureDeviceLinux::OnDisplayBoundsChanged(
331 const gfx::Display& display) {
332 v4l2_thread_.message_loop()->PostTask(
perkj_chrome 2014/05/09 10:11:28 This thread is started in AllocateAndStart. So you
perkj_chrome 2014/05/09 10:28:44 oh- btw - this need a thread check to make sure it
333 FROM_HERE,
334 base::Bind(&VideoCaptureDeviceLinux::SetDisplayRotation,
335 base::Unretained(this), display));
336 }
337
338 void VideoCaptureDeviceLinux::OnDisplayAdded(
339 const gfx::Display& /*new_display*/) {}
340
341 void VideoCaptureDeviceLinux::OnDisplayRemoved(
342 const gfx::Display& /*old_display*/) {}
343
344 void VideoCaptureDeviceLinux::SetDisplayRotation(const gfx::Display& display) {
345 DCHECK(!v4l2_thread_.IsRunning() ||
346 v4l2_thread_.message_loop() == base::MessageLoop::current());
347 if (display.IsInternal())
348 display_rotation_ = display.rotation();
perkj_chrome 2014/05/09 10:18:52 Add a todo and a comment that this will in fact ro
349 }
350
316 void VideoCaptureDeviceLinux::OnAllocateAndStart(int width, 351 void VideoCaptureDeviceLinux::OnAllocateAndStart(int width,
317 int height, 352 int height,
318 int frame_rate, 353 int frame_rate,
319 scoped_ptr<Client> client) { 354 scoped_ptr<Client> client) {
320 DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current()); 355 DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current());
321 356
322 client_ = client.Pass(); 357 client_ = client.Pass();
323 358
324 // Need to open camera with O_RDWR after Linux kernel 3.3. 359 // 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))); 360 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; 549 v4l2_buffer buffer;
515 memset(&buffer, 0, sizeof(buffer)); 550 memset(&buffer, 0, sizeof(buffer));
516 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 551 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
517 buffer.memory = V4L2_MEMORY_MMAP; 552 buffer.memory = V4L2_MEMORY_MMAP;
518 // Dequeue a buffer. 553 // Dequeue a buffer.
519 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_DQBUF, &buffer)) == 0) { 554 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_DQBUF, &buffer)) == 0) {
520 client_->OnIncomingCapturedData( 555 client_->OnIncomingCapturedData(
521 static_cast<uint8*>(buffer_pool_[buffer.index].start), 556 static_cast<uint8*>(buffer_pool_[buffer.index].start),
522 buffer.bytesused, 557 buffer.bytesused,
523 capture_format_, 558 capture_format_,
524 0, 559 display_rotation_ * 90,
525 base::TimeTicks::Now()); 560 base::TimeTicks::Now());
526 561
527 // Enqueue the buffer again. 562 // Enqueue the buffer again.
528 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QBUF, &buffer)) == -1) { 563 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QBUF, &buffer)) == -1) {
529 SetErrorState(base::StringPrintf( 564 SetErrorState(base::StringPrintf(
530 "Failed to enqueue capture buffer errno %d", errno)); 565 "Failed to enqueue capture buffer errno %d", errno));
531 } 566 }
532 } else { 567 } else {
533 SetErrorState(base::StringPrintf( 568 SetErrorState(base::StringPrintf(
534 "Failed to dequeue capture buffer errno %d", errno)); 569 "Failed to dequeue capture buffer errno %d", errno));
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
614 649
615 void VideoCaptureDeviceLinux::SetErrorState(const std::string& reason) { 650 void VideoCaptureDeviceLinux::SetErrorState(const std::string& reason) {
616 DCHECK(!v4l2_thread_.IsRunning() || 651 DCHECK(!v4l2_thread_.IsRunning() ||
617 v4l2_thread_.message_loop() == base::MessageLoop::current()); 652 v4l2_thread_.message_loop() == base::MessageLoop::current());
618 DVLOG(1) << reason; 653 DVLOG(1) << reason;
619 state_ = kError; 654 state_ = kError;
620 client_->OnError(reason); 655 client_->OnError(reason);
621 } 656 }
622 657
623 } // namespace media 658 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698