OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/linux/v4l2_capture_delegate.h" | 5 #include "media/capture/video/linux/v4l2_capture_delegate.h" |
6 | 6 |
7 #include <linux/version.h> | 7 #include <linux/version.h> |
8 #include <linux/videodev2.h> | 8 #include <linux/videodev2.h> |
9 #include <poll.h> | 9 #include <poll.h> |
10 #include <sys/fcntl.h> | 10 #include <sys/fcntl.h> |
(...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
367 | 367 |
368 V4L2CaptureDelegate::V4L2CaptureDelegate( | 368 V4L2CaptureDelegate::V4L2CaptureDelegate( |
369 const VideoCaptureDeviceDescriptor& device_descriptor, | 369 const VideoCaptureDeviceDescriptor& device_descriptor, |
370 const scoped_refptr<base::SingleThreadTaskRunner>& v4l2_task_runner, | 370 const scoped_refptr<base::SingleThreadTaskRunner>& v4l2_task_runner, |
371 int power_line_frequency) | 371 int power_line_frequency) |
372 : v4l2_task_runner_(v4l2_task_runner), | 372 : v4l2_task_runner_(v4l2_task_runner), |
373 device_descriptor_(device_descriptor), | 373 device_descriptor_(device_descriptor), |
374 power_line_frequency_(power_line_frequency), | 374 power_line_frequency_(power_line_frequency), |
375 is_capturing_(false), | 375 is_capturing_(false), |
376 timeout_count_(0), | 376 timeout_count_(0), |
377 rotation_(0) {} | 377 rotation_(0), |
| 378 weak_factory_(this) {} |
378 | 379 |
379 void V4L2CaptureDelegate::AllocateAndStart( | 380 void V4L2CaptureDelegate::AllocateAndStart( |
380 int width, | 381 int width, |
381 int height, | 382 int height, |
382 float frame_rate, | 383 float frame_rate, |
383 std::unique_ptr<VideoCaptureDevice::Client> client) { | 384 std::unique_ptr<VideoCaptureDevice::Client> client) { |
384 DCHECK(v4l2_task_runner_->BelongsToCurrentThread()); | 385 DCHECK(v4l2_task_runner_->BelongsToCurrentThread()); |
385 DCHECK(client); | 386 DCHECK(client); |
386 client_ = std::move(client); | 387 client_ = std::move(client); |
387 | 388 |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
499 0) { | 500 0) { |
500 SetErrorState(FROM_HERE, "VIDIOC_STREAMON failed"); | 501 SetErrorState(FROM_HERE, "VIDIOC_STREAMON failed"); |
501 return; | 502 return; |
502 } | 503 } |
503 | 504 |
504 client_->OnStarted(); | 505 client_->OnStarted(); |
505 is_capturing_ = true; | 506 is_capturing_ = true; |
506 | 507 |
507 // Post task to start fetching frames from v4l2. | 508 // Post task to start fetching frames from v4l2. |
508 v4l2_task_runner_->PostTask( | 509 v4l2_task_runner_->PostTask( |
509 FROM_HERE, base::Bind(&V4L2CaptureDelegate::DoCapture, this)); | 510 FROM_HERE, base::Bind(&V4L2CaptureDelegate::DoCapture, GetWeakPtr())); |
510 } | 511 } |
511 | 512 |
512 void V4L2CaptureDelegate::StopAndDeAllocate() { | 513 void V4L2CaptureDelegate::StopAndDeAllocate() { |
513 DCHECK(v4l2_task_runner_->BelongsToCurrentThread()); | 514 DCHECK(v4l2_task_runner_->BelongsToCurrentThread()); |
514 // The order is important: stop streaming, clear |buffer_pool_|, | 515 // The order is important: stop streaming, clear |buffer_pool_|, |
515 // thus munmap()ing the v4l2_buffers, and then return them to the OS. | 516 // thus munmap()ing the v4l2_buffers, and then return them to the OS. |
516 v4l2_buf_type capture_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 517 v4l2_buf_type capture_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
517 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_STREAMOFF, &capture_type)) < | 518 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_STREAMOFF, &capture_type)) < |
518 0) { | 519 0) { |
519 SetErrorState(FROM_HERE, "VIDIOC_STREAMOFF failed"); | 520 SetErrorState(FROM_HERE, "VIDIOC_STREAMOFF failed"); |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
707 | 708 |
708 callback.Run(true); | 709 callback.Run(true); |
709 } | 710 } |
710 | 711 |
711 void V4L2CaptureDelegate::SetRotation(int rotation) { | 712 void V4L2CaptureDelegate::SetRotation(int rotation) { |
712 DCHECK(v4l2_task_runner_->BelongsToCurrentThread()); | 713 DCHECK(v4l2_task_runner_->BelongsToCurrentThread()); |
713 DCHECK(rotation >= 0 && rotation < 360 && rotation % 90 == 0); | 714 DCHECK(rotation >= 0 && rotation < 360 && rotation % 90 == 0); |
714 rotation_ = rotation; | 715 rotation_ = rotation; |
715 } | 716 } |
716 | 717 |
| 718 base::WeakPtr<V4L2CaptureDelegate> V4L2CaptureDelegate::GetWeakPtr() { |
| 719 return weak_factory_.GetWeakPtr(); |
| 720 } |
| 721 |
717 V4L2CaptureDelegate::~V4L2CaptureDelegate() {} | 722 V4L2CaptureDelegate::~V4L2CaptureDelegate() {} |
718 | 723 |
719 bool V4L2CaptureDelegate::MapAndQueueBuffer(int index) { | 724 bool V4L2CaptureDelegate::MapAndQueueBuffer(int index) { |
720 v4l2_buffer buffer; | 725 v4l2_buffer buffer; |
721 FillV4L2Buffer(&buffer, index); | 726 FillV4L2Buffer(&buffer, index); |
722 | 727 |
723 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QUERYBUF, &buffer)) < 0) { | 728 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QUERYBUF, &buffer)) < 0) { |
724 DLOG(ERROR) << "Error querying status of a MMAP V4L2 buffer"; | 729 DLOG(ERROR) << "Error querying status of a MMAP V4L2 buffer"; |
725 return false; | 730 return false; |
726 } | 731 } |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
813 cb.Run(std::move(blob)); | 818 cb.Run(std::move(blob)); |
814 } | 819 } |
815 | 820 |
816 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QBUF, &buffer)) < 0) { | 821 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QBUF, &buffer)) < 0) { |
817 SetErrorState(FROM_HERE, "Failed to enqueue capture buffer"); | 822 SetErrorState(FROM_HERE, "Failed to enqueue capture buffer"); |
818 return; | 823 return; |
819 } | 824 } |
820 } | 825 } |
821 | 826 |
822 v4l2_task_runner_->PostTask( | 827 v4l2_task_runner_->PostTask( |
823 FROM_HERE, base::Bind(&V4L2CaptureDelegate::DoCapture, this)); | 828 FROM_HERE, base::Bind(&V4L2CaptureDelegate::DoCapture, GetWeakPtr())); |
824 } | 829 } |
825 | 830 |
826 void V4L2CaptureDelegate::SetErrorState( | 831 void V4L2CaptureDelegate::SetErrorState( |
827 const tracked_objects::Location& from_here, | 832 const tracked_objects::Location& from_here, |
828 const std::string& reason) { | 833 const std::string& reason) { |
829 DCHECK(v4l2_task_runner_->BelongsToCurrentThread()); | 834 DCHECK(v4l2_task_runner_->BelongsToCurrentThread()); |
830 is_capturing_ = false; | 835 is_capturing_ = false; |
831 client_->OnError(from_here, reason); | 836 client_->OnError(from_here, reason); |
832 } | 837 } |
833 | 838 |
(...skipping 16 matching lines...) Expand all Loading... |
850 DLOG(ERROR) << "Error mmap()ing a V4L2 buffer into userspace"; | 855 DLOG(ERROR) << "Error mmap()ing a V4L2 buffer into userspace"; |
851 return false; | 856 return false; |
852 } | 857 } |
853 start_ = static_cast<uint8_t*>(start); | 858 start_ = static_cast<uint8_t*>(start); |
854 length_ = buffer.length; | 859 length_ = buffer.length; |
855 payload_size_ = 0; | 860 payload_size_ = 0; |
856 return true; | 861 return true; |
857 } | 862 } |
858 | 863 |
859 } // namespace media | 864 } // namespace media |
OLD | NEW |