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

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

Issue 24079003: Add VideoCaptureDevice::GetDeviceSupportedFormats to interface + implementation for Linux and Fake (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Removed parameter device_name from GetDeviceSupportedFormats. Added explanation to VCD interface. Created 7 years, 3 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
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>
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
89 GetListOfUsableFourCCs(false, &usable_fourccs); 89 GetListOfUsableFourCCs(false, &usable_fourccs);
90 90
91 memset(&fmtdesc, 0, sizeof(v4l2_fmtdesc)); 91 memset(&fmtdesc, 0, sizeof(v4l2_fmtdesc));
92 fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 92 fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
93 93
94 while (ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc) == 0) { 94 while (ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc) == 0) {
95 if (std::find(usable_fourccs.begin(), usable_fourccs.end(), 95 if (std::find(usable_fourccs.begin(), usable_fourccs.end(),
96 fmtdesc.pixelformat) != usable_fourccs.end()) 96 fmtdesc.pixelformat) != usable_fourccs.end())
97 return true; 97 return true;
98 98
99 fmtdesc.index++; 99 ++fmtdesc.index;
100 } 100 }
101 return false; 101 return false;
102 } 102 }
103 103
104 void VideoCaptureDevice::GetDeviceNames(Names* device_names) { 104 void VideoCaptureDevice::GetDeviceNames(Names* device_names) {
105 int fd = -1; 105 int fd = -1;
106 106
107 // Empty the name list. 107 // Empty the name list.
108 device_names->clear(); 108 device_names->clear();
109 109
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
245 // Make sure no buffers are still allocated. 245 // Make sure no buffers are still allocated.
246 // This can happen (theoretically) if an error occurs when trying to stop 246 // This can happen (theoretically) if an error occurs when trying to stop
247 // the camera. 247 // the camera.
248 DeAllocateVideoBuffers(); 248 DeAllocateVideoBuffers();
249 } 249 }
250 250
251 const VideoCaptureDevice::Name& VideoCaptureDeviceLinux::device_name() { 251 const VideoCaptureDevice::Name& VideoCaptureDeviceLinux::device_name() {
252 return device_name_; 252 return device_name_;
253 } 253 }
254 254
255 void VideoCaptureDeviceLinux::GetDeviceSupportedFormats(
256 VideoCaptureFormats* capture_formats) {
perkj_chrome 2013/09/13 10:33:05 To be threadsafe - all v4l2 calls in this file is
mcasas 2013/09/24 15:02:27 Done.
257
scherkus (not reviewing) 2013/09/12 17:56:00 remove blank line
mcasas 2013/09/24 15:02:27 Done.
258 if (device_name_.id().empty())
259 return;
260 int fd = open(device_name_.id().c_str(), O_RDONLY);
scherkus (not reviewing) 2013/09/12 17:56:00 use file_util::ScopedFD
scherkus (not reviewing) 2013/09/12 17:56:00 this should be wrapped with HANDLE_EINTR()
mcasas 2013/09/24 15:02:27 Done.
261 if (fd < 0)
262 return;
scherkus (not reviewing) 2013/09/12 17:56:00 DPLOG(ERROR) << "Couldn't open " << device_name_.i
mcasas 2013/09/24 15:02:27 Done.
263
264 media::VideoCaptureCapability capture_format;
scherkus (not reviewing) 2013/09/12 17:56:00 remove media::
mcasas 2013/09/24 15:02:27 Done.
265
266 v4l2_capability device;
267 // Test if this is a V4L2 capture device.
268 if ((ioctl(fd, VIDIOC_QUERYCAP, &device) == 0) &&
269 (device.capabilities & V4L2_CAP_VIDEO_CAPTURE) &&
270 !(device.capabilities & V4L2_CAP_VIDEO_OUTPUT)) {
271 // Retrieve the caps one by one, first get colorspace, then sizes, then
scherkus (not reviewing) 2013/09/12 17:56:00 instead of having this large block of code indente
mcasas 2013/09/24 15:02:27 Done.
272 // framerates. See http://linuxtv.org/downloads/v4l-dvb-apis for reference.
273 v4l2_fmtdesc pixel_format = {};
274 pixel_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
275 while (ioctl(fd, VIDIOC_ENUM_FMT, &pixel_format) == 0) {
276 capture_format.color = media::V4l2ColorToVideoCaptureColorFormat(
scherkus (not reviewing) 2013/09/12 17:56:00 remove media::
scherkus (not reviewing) 2013/09/12 17:56:00 do we have to cast here? it seems we don't have t
mcasas 2013/09/24 15:02:27 Done.
mcasas 2013/09/24 15:02:27 Done.
277 static_cast<int32>(pixel_format.pixelformat));
278
279 v4l2_frmsizeenum frame_size = {};
280 frame_size.pixel_format = pixel_format.pixelformat;
281 while (ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frame_size) == 0) {
282 if (frame_size.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
283 capture_format.width = frame_size.discrete.width;
284 capture_format.height = frame_size.discrete.height;
285 } else if (frame_size.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
286 // What to do here? We get a min-max pair for width and height, and a
287 // step for each dimensions. Is not a crazy format, ViVi uses it.
288 // TODO(mcasas) see crbug.com/249953
scherkus (not reviewing) 2013/09/12 17:56:00 nit: we format TODOs with a : after the ) also ca
scherkus (not reviewing) 2013/09/12 17:56:00 nit: use http:// in front of crbug.com (many text
mcasas 2013/09/24 15:02:27 Done.
mcasas 2013/09/24 15:02:27 Is an easy elaborate: support these devices :)
289 NOTIMPLEMENTED();
290 } else if (frame_size.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) {
291 // Same here as the case before: TODO(mcasas) see crbug.com/249953
scherkus (not reviewing) 2013/09/12 17:56:00 ditto
mcasas 2013/09/24 15:02:27 Done.
292 NOTIMPLEMENTED();
scherkus (not reviewing) 2013/09/12 17:56:00 if these are unimplemented, do you mean to continu
mcasas 2013/09/24 15:02:27 I don't know this particular case. The proposed us
293 }
294 v4l2_frmivalenum frame_interval = {};
295 frame_interval.pixel_format = pixel_format.pixelformat;
296 frame_interval.width = frame_size.discrete.width;
297 frame_interval.height = frame_size.discrete.height;
298 while (ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &frame_interval) == 0) {
299 if (frame_interval.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
300 capture_format.frame_rate =
301 (frame_interval.discrete.numerator != 0)
scherkus (not reviewing) 2013/09/12 17:56:00 I'd just use an if () statement here -- the ?: ope
mcasas 2013/09/24 15:02:27 Done.
302 ? (static_cast<float>(frame_interval.discrete.denominator) /
303 static_cast<float>(frame_interval.discrete.numerator))
304 : 0;
305
306 } else if (frame_interval.type == V4L2_FRMIVAL_TYPE_CONTINUOUS) {
307 // Same here as the case above: TODO(mcasas) see crbug.com/249953
scherkus (not reviewing) 2013/09/12 17:56:00 nit: try to start TODO comments at the beginning o
mcasas 2013/09/24 15:02:27 Done.
308 NOTIMPLEMENTED();
309 break;
310 } else if (frame_interval.type == V4L2_FRMIVAL_TYPE_STEPWISE) {
311 // Same here as the case before: TODO(mcasas) see crbug.com/249953
312 NOTIMPLEMENTED();
scherkus (not reviewing) 2013/09/12 17:56:00 ditto... is there a use case for inserting VideoCa
mcasas 2013/09/24 15:02:27 This is an easier case: yes, some devices might no
313 break;
314 }
315 capture_formats->insert(capture_formats->end(), capture_format);
scherkus (not reviewing) 2013/09/12 17:56:00 push_back() ?
mcasas 2013/09/24 15:02:27 Done.
316 ++frame_interval.index;
317 }
318 ++frame_size.index;
319 }
320 ++pixel_format.index;
321 }
322 } else {
323 // The selected device is not video capture as we like it.
324 capture_formats->clear();
325 }
326 close(fd);
327 }
328
255 void VideoCaptureDeviceLinux::OnAllocate(int width, 329 void VideoCaptureDeviceLinux::OnAllocate(int width,
256 int height, 330 int height,
257 int frame_rate, 331 int frame_rate,
258 EventHandler* observer) { 332 EventHandler* observer) {
259 DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current()); 333 DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current());
260 334
261 observer_ = observer; 335 observer_ = observer;
262 336
263 // Need to open camera with O_RDWR after Linux kernel 3.3. 337 // Need to open camera with O_RDWR after Linux kernel 3.3.
264 if ((device_fd_ = open(device_name_.id().c_str(), O_RDWR)) < 0) { 338 if ((device_fd_ = open(device_name_.id().c_str(), O_RDWR)) < 0) {
(...skipping 20 matching lines...) Expand all
285 &v4l2_formats); 359 &v4l2_formats);
286 360
287 v4l2_fmtdesc fmtdesc; 361 v4l2_fmtdesc fmtdesc;
288 memset(&fmtdesc, 0, sizeof(v4l2_fmtdesc)); 362 memset(&fmtdesc, 0, sizeof(v4l2_fmtdesc));
289 fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 363 fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
290 364
291 // Enumerate image formats. 365 // Enumerate image formats.
292 std::list<int>::iterator best = v4l2_formats.end(); 366 std::list<int>::iterator best = v4l2_formats.end();
293 while (ioctl(device_fd_, VIDIOC_ENUM_FMT, &fmtdesc) == 0) { 367 while (ioctl(device_fd_, VIDIOC_ENUM_FMT, &fmtdesc) == 0) {
294 best = std::find(v4l2_formats.begin(), best, fmtdesc.pixelformat); 368 best = std::find(v4l2_formats.begin(), best, fmtdesc.pixelformat);
295 fmtdesc.index++; 369 ++fmtdesc.index;
296 } 370 }
297 371
298 if (best == v4l2_formats.end()) { 372 if (best == v4l2_formats.end()) {
299 SetErrorState("Failed to find a supported camera format."); 373 SetErrorState("Failed to find a supported camera format.");
300 return; 374 return;
301 } 375 }
302 376
303 // Set format and frame size now. 377 // Set format and frame size now.
304 v4l2_format video_fmt; 378 v4l2_format video_fmt;
305 memset(&video_fmt, 0, sizeof(video_fmt)); 379 memset(&video_fmt, 0, sizeof(video_fmt));
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
442 } 516 }
443 v4l2_thread_.message_loop()->PostDelayedTask( 517 v4l2_thread_.message_loop()->PostDelayedTask(
444 FROM_HERE, 518 FROM_HERE,
445 base::Bind(&VideoCaptureDeviceLinux::OnCaptureTask, 519 base::Bind(&VideoCaptureDeviceLinux::OnCaptureTask,
446 base::Unretained(this)), 520 base::Unretained(this)),
447 base::TimeDelta::FromMilliseconds(kCaptureSelectWaitMs)); 521 base::TimeDelta::FromMilliseconds(kCaptureSelectWaitMs));
448 } 522 }
449 523
450 // Check if select timeout. 524 // Check if select timeout.
451 if (result == 0) { 525 if (result == 0) {
452 timeout_count_++; 526 ++timeout_count_;
453 if (timeout_count_ >= kContinuousTimeoutLimit) { 527 if (timeout_count_ >= kContinuousTimeoutLimit) {
454 SetErrorState(base::StringPrintf( 528 SetErrorState(base::StringPrintf(
455 "Continuous timeout %d times", timeout_count_)); 529 "Continuous timeout %d times", timeout_count_));
456 timeout_count_ = 0; 530 timeout_count_ = 0;
457 return; 531 return;
458 } 532 }
459 } else { 533 } else {
460 timeout_count_ = 0; 534 timeout_count_ = 0;
461 } 535 }
462 536
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
503 } 577 }
504 578
505 if (r_buffer.count > kMaxVideoBuffers) { 579 if (r_buffer.count > kMaxVideoBuffers) {
506 r_buffer.count = kMaxVideoBuffers; 580 r_buffer.count = kMaxVideoBuffers;
507 } 581 }
508 582
509 buffer_pool_size_ = r_buffer.count; 583 buffer_pool_size_ = r_buffer.count;
510 584
511 // Map the buffers. 585 // Map the buffers.
512 buffer_pool_ = new Buffer[r_buffer.count]; 586 buffer_pool_ = new Buffer[r_buffer.count];
513 for (unsigned int i = 0; i < r_buffer.count; i++) { 587 for (unsigned int i = 0; i < r_buffer.count; ++i) {
514 v4l2_buffer buffer; 588 v4l2_buffer buffer;
515 memset(&buffer, 0, sizeof(buffer)); 589 memset(&buffer, 0, sizeof(buffer));
516 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 590 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
517 buffer.memory = V4L2_MEMORY_MMAP; 591 buffer.memory = V4L2_MEMORY_MMAP;
518 buffer.index = i; 592 buffer.index = i;
519 593
520 if (ioctl(device_fd_, VIDIOC_QUERYBUF, &buffer) < 0) { 594 if (ioctl(device_fd_, VIDIOC_QUERYBUF, &buffer) < 0) {
521 return false; 595 return false;
522 } 596 }
523 597
(...skipping 11 matching lines...) Expand all
535 } 609 }
536 } 610 }
537 return true; 611 return true;
538 } 612 }
539 613
540 void VideoCaptureDeviceLinux::DeAllocateVideoBuffers() { 614 void VideoCaptureDeviceLinux::DeAllocateVideoBuffers() {
541 if (!buffer_pool_) 615 if (!buffer_pool_)
542 return; 616 return;
543 617
544 // Unmaps buffers. 618 // Unmaps buffers.
545 for (int i = 0; i < buffer_pool_size_; i++) { 619 for (int i = 0; i < buffer_pool_size_; ++i) {
546 munmap(buffer_pool_[i].start, buffer_pool_[i].length); 620 munmap(buffer_pool_[i].start, buffer_pool_[i].length);
547 } 621 }
548 v4l2_requestbuffers r_buffer; 622 v4l2_requestbuffers r_buffer;
549 memset(&r_buffer, 0, sizeof(r_buffer)); 623 memset(&r_buffer, 0, sizeof(r_buffer));
550 r_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 624 r_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
551 r_buffer.memory = V4L2_MEMORY_MMAP; 625 r_buffer.memory = V4L2_MEMORY_MMAP;
552 r_buffer.count = 0; 626 r_buffer.count = 0;
553 627
554 if (ioctl(device_fd_, VIDIOC_REQBUFS, &r_buffer) < 0) { 628 if (ioctl(device_fd_, VIDIOC_REQBUFS, &r_buffer) < 0) {
555 SetErrorState("Failed to reset buf."); 629 SetErrorState("Failed to reset buf.");
556 } 630 }
557 631
558 delete [] buffer_pool_; 632 delete [] buffer_pool_;
559 buffer_pool_ = NULL; 633 buffer_pool_ = NULL;
560 buffer_pool_size_ = 0; 634 buffer_pool_size_ = 0;
561 } 635 }
562 636
563 void VideoCaptureDeviceLinux::SetErrorState(const std::string& reason) { 637 void VideoCaptureDeviceLinux::SetErrorState(const std::string& reason) {
564 DVLOG(1) << reason; 638 DVLOG(1) << reason;
565 state_ = kError; 639 state_ = kError;
566 observer_->OnError(); 640 observer_->OnError();
567 } 641 }
568 642
569 } // namespace media 643 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698