| OLD | NEW |
| 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 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 106 // Put it as the least preferred format. | 106 // Put it as the least preferred format. |
| 107 fourccs->push_back(V4L2_PIX_FMT_JPEG); | 107 fourccs->push_back(V4L2_PIX_FMT_JPEG); |
| 108 } | 108 } |
| 109 | 109 |
| 110 // TODO(mcasas): Remove the following static methods when they are no longer | 110 // TODO(mcasas): Remove the following static methods when they are no longer |
| 111 // referenced from VideoCaptureDeviceFactory, i.e. when all OS platforms have | 111 // referenced from VideoCaptureDeviceFactory, i.e. when all OS platforms have |
| 112 // splitted the VideoCaptureDevice into VideoCaptureDevice and | 112 // splitted the VideoCaptureDevice into VideoCaptureDevice and |
| 113 // VideoCaptureDeviceFactory. | 113 // VideoCaptureDeviceFactory. |
| 114 | 114 |
| 115 // static | 115 // static |
| 116 VideoCaptureDevice* VideoCaptureDevice::Create(const Name& device_name) { | 116 VideoCaptureDevice* VideoCaptureDevice::Create( |
| 117 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, |
| 118 const Name& device_name) { |
| 117 NOTREACHED(); | 119 NOTREACHED(); |
| 118 return NULL; | 120 return NULL; |
| 119 } | 121 } |
| 120 // static | 122 // static |
| 121 void VideoCaptureDevice::GetDeviceNames(Names* device_names) { | 123 void VideoCaptureDevice::GetDeviceNames(Names* device_names) { |
| 122 NOTREACHED(); | 124 NOTREACHED(); |
| 123 } | 125 } |
| 124 | 126 |
| 125 // static | 127 // static |
| 126 void VideoCaptureDevice::GetDeviceSupportedFormats( | 128 void VideoCaptureDevice::GetDeviceSupportedFormats( |
| (...skipping 23 matching lines...) Expand all Loading... |
| 150 | 152 |
| 151 return usb_id; | 153 return usb_id; |
| 152 } | 154 } |
| 153 | 155 |
| 154 VideoCaptureDeviceLinux::VideoCaptureDeviceLinux(const Name& device_name) | 156 VideoCaptureDeviceLinux::VideoCaptureDeviceLinux(const Name& device_name) |
| 155 : state_(kIdle), | 157 : state_(kIdle), |
| 156 device_name_(device_name), | 158 device_name_(device_name), |
| 157 v4l2_thread_("V4L2Thread"), | 159 v4l2_thread_("V4L2Thread"), |
| 158 buffer_pool_(NULL), | 160 buffer_pool_(NULL), |
| 159 buffer_pool_size_(0), | 161 buffer_pool_size_(0), |
| 160 timeout_count_(0) {} | 162 timeout_count_(0), |
| 163 rotation_(0) { |
| 164 } |
| 161 | 165 |
| 162 VideoCaptureDeviceLinux::~VideoCaptureDeviceLinux() { | 166 VideoCaptureDeviceLinux::~VideoCaptureDeviceLinux() { |
| 163 state_ = kIdle; | 167 state_ = kIdle; |
| 164 // Check if the thread is running. | 168 // Check if the thread is running. |
| 165 // This means that the device have not been DeAllocated properly. | 169 // This means that the device have not been DeAllocated properly. |
| 166 DCHECK(!v4l2_thread_.IsRunning()); | 170 DCHECK(!v4l2_thread_.IsRunning()); |
| 167 v4l2_thread_.Stop(); | 171 v4l2_thread_.Stop(); |
| 168 } | 172 } |
| 169 | 173 |
| 170 void VideoCaptureDeviceLinux::AllocateAndStart( | 174 void VideoCaptureDeviceLinux::AllocateAndStart( |
| (...skipping 21 matching lines...) Expand all Loading... |
| 192 FROM_HERE, | 196 FROM_HERE, |
| 193 base::Bind(&VideoCaptureDeviceLinux::OnStopAndDeAllocate, | 197 base::Bind(&VideoCaptureDeviceLinux::OnStopAndDeAllocate, |
| 194 base::Unretained(this))); | 198 base::Unretained(this))); |
| 195 v4l2_thread_.Stop(); | 199 v4l2_thread_.Stop(); |
| 196 // Make sure no buffers are still allocated. | 200 // Make sure no buffers are still allocated. |
| 197 // This can happen (theoretically) if an error occurs when trying to stop | 201 // This can happen (theoretically) if an error occurs when trying to stop |
| 198 // the camera. | 202 // the camera. |
| 199 DeAllocateVideoBuffers(); | 203 DeAllocateVideoBuffers(); |
| 200 } | 204 } |
| 201 | 205 |
| 206 void VideoCaptureDeviceLinux::SetRotation(int rotation) { |
| 207 if (v4l2_thread_.IsRunning()) { |
| 208 v4l2_thread_.message_loop()->PostTask( |
| 209 FROM_HERE, |
| 210 base::Bind(&VideoCaptureDeviceLinux::SetRotationOnV4L2Thread, |
| 211 base::Unretained(this), rotation)); |
| 212 } else { |
| 213 // If the |v4l2_thread_| is not running, there's no race condition and |
| 214 // |rotation_| can be set directly. |
| 215 rotation_ = rotation; |
| 216 } |
| 217 } |
| 218 |
| 219 void VideoCaptureDeviceLinux::SetRotationOnV4L2Thread(int rotation) { |
| 220 DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current()); |
| 221 DCHECK(rotation >= 0 && rotation < 360 && rotation % 90 == 0); |
| 222 rotation_ = rotation; |
| 223 } |
| 224 |
| 202 void VideoCaptureDeviceLinux::OnAllocateAndStart(int width, | 225 void VideoCaptureDeviceLinux::OnAllocateAndStart(int width, |
| 203 int height, | 226 int height, |
| 204 int frame_rate, | 227 int frame_rate, |
| 205 scoped_ptr<Client> client) { | 228 scoped_ptr<Client> client) { |
| 206 DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current()); | 229 DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current()); |
| 207 | 230 |
| 208 client_ = client.Pass(); | 231 client_ = client.Pass(); |
| 209 | 232 |
| 210 // Need to open camera with O_RDWR after Linux kernel 3.3. | 233 // Need to open camera with O_RDWR after Linux kernel 3.3. |
| 211 device_fd_.reset(HANDLE_EINTR(open(device_name_.id().c_str(), O_RDWR))); | 234 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 Loading... |
| 400 v4l2_buffer buffer; | 423 v4l2_buffer buffer; |
| 401 memset(&buffer, 0, sizeof(buffer)); | 424 memset(&buffer, 0, sizeof(buffer)); |
| 402 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 425 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
| 403 buffer.memory = V4L2_MEMORY_MMAP; | 426 buffer.memory = V4L2_MEMORY_MMAP; |
| 404 // Dequeue a buffer. | 427 // Dequeue a buffer. |
| 405 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_DQBUF, &buffer)) == 0) { | 428 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_DQBUF, &buffer)) == 0) { |
| 406 client_->OnIncomingCapturedData( | 429 client_->OnIncomingCapturedData( |
| 407 static_cast<uint8*>(buffer_pool_[buffer.index].start), | 430 static_cast<uint8*>(buffer_pool_[buffer.index].start), |
| 408 buffer.bytesused, | 431 buffer.bytesused, |
| 409 capture_format_, | 432 capture_format_, |
| 410 0, | 433 rotation_, |
| 411 base::TimeTicks::Now()); | 434 base::TimeTicks::Now()); |
| 412 | 435 |
| 413 // Enqueue the buffer again. | 436 // Enqueue the buffer again. |
| 414 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QBUF, &buffer)) == -1) { | 437 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QBUF, &buffer)) == -1) { |
| 415 SetErrorState(base::StringPrintf( | 438 SetErrorState(base::StringPrintf( |
| 416 "Failed to enqueue capture buffer errno %d", errno)); | 439 "Failed to enqueue capture buffer errno %d", errno)); |
| 417 } | 440 } |
| 418 } else { | 441 } else { |
| 419 SetErrorState(base::StringPrintf( | 442 SetErrorState(base::StringPrintf( |
| 420 "Failed to dequeue capture buffer errno %d", errno)); | 443 "Failed to dequeue capture buffer errno %d", errno)); |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 500 | 523 |
| 501 void VideoCaptureDeviceLinux::SetErrorState(const std::string& reason) { | 524 void VideoCaptureDeviceLinux::SetErrorState(const std::string& reason) { |
| 502 DCHECK(!v4l2_thread_.IsRunning() || | 525 DCHECK(!v4l2_thread_.IsRunning() || |
| 503 v4l2_thread_.message_loop() == base::MessageLoop::current()); | 526 v4l2_thread_.message_loop() == base::MessageLoop::current()); |
| 504 DVLOG(1) << reason; | 527 DVLOG(1) << reason; |
| 505 state_ = kError; | 528 state_ = kError; |
| 506 client_->OnError(reason); | 529 client_->OnError(reason); |
| 507 } | 530 } |
| 508 | 531 |
| 509 } // namespace media | 532 } // namespace media |
| OLD | NEW |