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 <poll.h> | 7 #include <poll.h> |
8 #include <sys/fcntl.h> | 8 #include <sys/fcntl.h> |
9 #include <sys/ioctl.h> | 9 #include <sys/ioctl.h> |
10 #include <sys/mman.h> | 10 #include <sys/mman.h> |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
91 request_buffer->memory = V4L2_MEMORY_MMAP; | 91 request_buffer->memory = V4L2_MEMORY_MMAP; |
92 request_buffer->count = count; | 92 request_buffer->count = count; |
93 } | 93 } |
94 | 94 |
95 // Returns the input |fourcc| as a std::string four char representation. | 95 // Returns the input |fourcc| as a std::string four char representation. |
96 static std::string FourccToString(uint32_t fourcc) { | 96 static std::string FourccToString(uint32_t fourcc) { |
97 return base::StringPrintf("%c%c%c%c", fourcc & 0xFF, (fourcc >> 8) & 0xFF, | 97 return base::StringPrintf("%c%c%c%c", fourcc & 0xFF, (fourcc >> 8) & 0xFF, |
98 (fourcc >> 16) & 0xFF, (fourcc >> 24) & 0xFF); | 98 (fourcc >> 16) & 0xFF, (fourcc >> 24) & 0xFF); |
99 } | 99 } |
100 | 100 |
101 // Creates a mojom::RangePtr with the range of values (min, max, current) of the | |
102 // user control associated with |control_id|. Returns an empty Range otherwise. | |
103 static mojom::RangePtr RetrieveUserControlRange(int device_fd, int control_id) { | |
104 mojom::RangePtr capability = mojom::Range::New(); | |
105 | |
106 v4l2_queryctrl range = {}; | |
107 range.id = control_id; | |
108 range.type = V4L2_CTRL_TYPE_INTEGER; | |
109 if (HANDLE_EINTR(ioctl(device_fd, VIDIOC_QUERYCTRL, &range)) < 0) | |
110 return mojom::Range::New(); | |
111 capability->max = range.maximum; | |
112 capability->min = range.minimum; | |
113 | |
114 v4l2_control current = {}; | |
115 current.id = control_id; | |
116 if (HANDLE_EINTR(ioctl(device_fd, VIDIOC_G_CTRL, ¤t)) < 0) | |
117 return mojom::Range::New(); | |
118 capability->current = current.value; | |
119 | |
120 return capability; | |
121 } | |
122 | |
101 // Class keeping track of a SPLANE V4L2 buffer, mmap()ed on construction and | 123 // Class keeping track of a SPLANE V4L2 buffer, mmap()ed on construction and |
102 // munmap()ed on destruction. | 124 // munmap()ed on destruction. |
103 class V4L2CaptureDelegate::BufferTracker | 125 class V4L2CaptureDelegate::BufferTracker |
104 : public base::RefCounted<BufferTracker> { | 126 : public base::RefCounted<BufferTracker> { |
105 public: | 127 public: |
106 BufferTracker(); | 128 BufferTracker(); |
107 // Abstract method to mmap() given |fd| according to |buffer|. | 129 // Abstract method to mmap() given |fd| according to |buffer|. |
108 bool Init(int fd, const v4l2_buffer& buffer); | 130 bool Init(int fd, const v4l2_buffer& buffer); |
109 | 131 |
110 const uint8_t* start() const { return start_; } | 132 const uint8_t* start() const { return start_; } |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
334 | 356 |
335 void V4L2CaptureDelegate::GetPhotoCapabilities( | 357 void V4L2CaptureDelegate::GetPhotoCapabilities( |
336 VideoCaptureDevice::GetPhotoCapabilitiesCallback callback) { | 358 VideoCaptureDevice::GetPhotoCapabilitiesCallback callback) { |
337 DCHECK(v4l2_task_runner_->BelongsToCurrentThread()); | 359 DCHECK(v4l2_task_runner_->BelongsToCurrentThread()); |
338 if (!device_fd_.is_valid() || !is_capturing_) | 360 if (!device_fd_.is_valid() || !is_capturing_) |
339 return; | 361 return; |
340 | 362 |
341 mojom::PhotoCapabilitiesPtr photo_capabilities = | 363 mojom::PhotoCapabilitiesPtr photo_capabilities = |
342 mojom::PhotoCapabilities::New(); | 364 mojom::PhotoCapabilities::New(); |
343 | 365 |
344 photo_capabilities->zoom = mojom::Range::New(); | 366 photo_capabilities->zoom = |
345 v4l2_queryctrl zoom_range = {}; | 367 RetrieveUserControlRange(device_fd_.get(), V4L2_CID_ZOOM_ABSOLUTE); |
346 zoom_range.id = V4L2_CID_ZOOM_ABSOLUTE; | |
347 zoom_range.type = V4L2_CTRL_TYPE_INTEGER; | |
348 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QUERYCTRL, &zoom_range)) >= | |
349 0) { | |
350 photo_capabilities->zoom->max = zoom_range.maximum * kZoomMultiplier; | |
351 photo_capabilities->zoom->min = zoom_range.minimum * kZoomMultiplier; | |
352 } | |
353 v4l2_control zoom_current = {}; | |
354 zoom_current.id = V4L2_CID_ZOOM_ABSOLUTE; | |
355 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_G_CTRL, &zoom_current)) >= 0) | |
356 photo_capabilities->zoom->current = zoom_current.value * kZoomMultiplier; | |
357 | 368 |
358 photo_capabilities->focus_mode = mojom::MeteringMode::NONE; | 369 photo_capabilities->focus_mode = mojom::MeteringMode::NONE; |
359 v4l2_control auto_focus_current = {}; | 370 v4l2_control auto_focus_current = {}; |
360 auto_focus_current.id = V4L2_CID_FOCUS_AUTO; | 371 auto_focus_current.id = V4L2_CID_FOCUS_AUTO; |
361 if (HANDLE_EINTR( | 372 if (HANDLE_EINTR( |
362 ioctl(device_fd_.get(), VIDIOC_G_CTRL, &auto_focus_current)) >= 0) { | 373 ioctl(device_fd_.get(), VIDIOC_G_CTRL, &auto_focus_current)) >= 0) { |
363 photo_capabilities->focus_mode = auto_focus_current.value | 374 photo_capabilities->focus_mode = auto_focus_current.value |
364 ? mojom::MeteringMode::CONTINUOUS | 375 ? mojom::MeteringMode::CONTINUOUS |
365 : mojom::MeteringMode::MANUAL; | 376 : mojom::MeteringMode::MANUAL; |
366 } | 377 } |
(...skipping 12 matching lines...) Expand all Loading... | |
379 photo_capabilities->white_balance_mode = mojom::MeteringMode::NONE; | 390 photo_capabilities->white_balance_mode = mojom::MeteringMode::NONE; |
380 v4l2_control white_balance_current = {}; | 391 v4l2_control white_balance_current = {}; |
381 white_balance_current.id = V4L2_CID_AUTO_WHITE_BALANCE; | 392 white_balance_current.id = V4L2_CID_AUTO_WHITE_BALANCE; |
382 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_G_CTRL, | 393 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_G_CTRL, |
383 &white_balance_current)) >= 0) { | 394 &white_balance_current)) >= 0) { |
384 photo_capabilities->white_balance_mode = | 395 photo_capabilities->white_balance_mode = |
385 white_balance_current.value ? mojom::MeteringMode::CONTINUOUS | 396 white_balance_current.value ? mojom::MeteringMode::CONTINUOUS |
386 : mojom::MeteringMode::MANUAL; | 397 : mojom::MeteringMode::MANUAL; |
387 } | 398 } |
388 | 399 |
389 photo_capabilities->color_temperature = mojom::Range::New(); | 400 photo_capabilities->color_temperature = RetrieveUserControlRange( |
390 v4l2_queryctrl color_temperature_range = {}; | 401 device_fd_.get(), V4L2_CID_WHITE_BALANCE_TEMPERATURE); |
391 color_temperature_range.id = V4L2_CID_WHITE_BALANCE_TEMPERATURE; | |
392 color_temperature_range.type = V4L2_CTRL_TYPE_INTEGER; | |
393 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QUERYCTRL, | |
394 &color_temperature_range)) >= 0) { | |
395 photo_capabilities->color_temperature->max = | |
396 color_temperature_range.maximum; | |
397 photo_capabilities->color_temperature->min = | |
398 color_temperature_range.minimum; | |
399 } | |
400 | |
401 v4l2_control color_temperature_current = {}; | |
402 color_temperature_current.id = V4L2_CID_WHITE_BALANCE_TEMPERATURE; | |
403 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_G_CTRL, | |
404 &color_temperature_current)) >= 0) { | |
405 photo_capabilities->color_temperature->current = | |
406 color_temperature_current.value; | |
407 } | |
408 | 402 |
409 photo_capabilities->iso = mojom::Range::New(); | 403 photo_capabilities->iso = mojom::Range::New(); |
410 photo_capabilities->height = mojom::Range::New(); | 404 photo_capabilities->height = mojom::Range::New(); |
411 photo_capabilities->width = mojom::Range::New(); | 405 photo_capabilities->width = mojom::Range::New(); |
412 photo_capabilities->exposure_compensation = mojom::Range::New(); | 406 photo_capabilities->exposure_compensation = mojom::Range::New(); |
413 photo_capabilities->fill_light_mode = mojom::FillLightMode::NONE; | 407 photo_capabilities->fill_light_mode = mojom::FillLightMode::NONE; |
414 photo_capabilities->red_eye_reduction = false; | 408 photo_capabilities->red_eye_reduction = false; |
409 | |
410 photo_capabilities->brightness = | |
411 RetrieveUserControlRange(device_fd_.get(), V4L2_CID_BRIGHTNESS); | |
412 photo_capabilities->contrast = | |
413 RetrieveUserControlRange(device_fd_.get(), V4L2_CID_CONTRAST); | |
414 photo_capabilities->saturation = | |
415 RetrieveUserControlRange(device_fd_.get(), V4L2_CID_SATURATION); | |
416 photo_capabilities->sharpness = | |
417 RetrieveUserControlRange(device_fd_.get(), V4L2_CID_SHARPNESS); | |
418 | |
415 callback.Run(std::move(photo_capabilities)); | 419 callback.Run(std::move(photo_capabilities)); |
416 } | 420 } |
417 | 421 |
418 void V4L2CaptureDelegate::SetPhotoOptions( | 422 void V4L2CaptureDelegate::SetPhotoOptions( |
419 mojom::PhotoSettingsPtr settings, | 423 mojom::PhotoSettingsPtr settings, |
420 VideoCaptureDevice::SetPhotoOptionsCallback callback) { | 424 VideoCaptureDevice::SetPhotoOptionsCallback callback) { |
421 DCHECK(v4l2_task_runner_->BelongsToCurrentThread()); | 425 DCHECK(v4l2_task_runner_->BelongsToCurrentThread()); |
422 if (!device_fd_.is_valid() || !is_capturing_) | 426 if (!device_fd_.is_valid() || !is_capturing_) |
423 return; | 427 return; |
424 | 428 |
(...skipping 22 matching lines...) Expand all Loading... | |
447 const int result = HANDLE_EINTR( | 451 const int result = HANDLE_EINTR( |
448 ioctl(device_fd_.get(), VIDIOC_G_CTRL, &auto_white_balance_current)); | 452 ioctl(device_fd_.get(), VIDIOC_G_CTRL, &auto_white_balance_current)); |
449 if (result >= 0 && !auto_white_balance_current.value) { | 453 if (result >= 0 && !auto_white_balance_current.value) { |
450 v4l2_control set_temperature = {}; | 454 v4l2_control set_temperature = {}; |
451 set_temperature.id = V4L2_CID_WHITE_BALANCE_TEMPERATURE; | 455 set_temperature.id = V4L2_CID_WHITE_BALANCE_TEMPERATURE; |
452 set_temperature.value = settings->color_temperature; | 456 set_temperature.value = settings->color_temperature; |
453 HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_S_CTRL, &set_temperature)); | 457 HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_S_CTRL, &set_temperature)); |
454 } | 458 } |
455 } | 459 } |
456 | 460 |
461 if (settings->has_brightness) { | |
462 v4l2_control current = {}; | |
463 current.id = V4L2_CID_BRIGHTNESS; | |
464 current.value = settings->brightness; | |
465 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_S_CTRL, ¤t)) < 0) | |
466 DPLOG(ERROR) << "setting brightness to " << settings->brightness; | |
467 } | |
468 if (settings->has_brightness) { | |
chfremer
2016/10/04 17:36:06
Copy-paste error here and the blocks below?
mcasas
2016/10/04 17:44:11
Oh, hark, good catch. Done.
| |
469 v4l2_control current = {}; | |
470 current.id = V4L2_CID_CONTRAST; | |
471 current.value = settings->contrast; | |
472 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_S_CTRL, ¤t)) < 0) | |
473 DPLOG(ERROR) << "setting contrast to " << settings->contrast; | |
474 } | |
475 if (settings->has_brightness) { | |
476 v4l2_control current = {}; | |
477 current.id = V4L2_CID_SATURATION; | |
478 current.value = settings->saturation; | |
479 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_S_CTRL, ¤t)) < 0) | |
480 DPLOG(ERROR) << "setting saturation to " << settings->saturation; | |
481 } | |
482 if (settings->has_brightness) { | |
483 v4l2_control current = {}; | |
484 current.id = V4L2_CID_SHARPNESS; | |
485 current.value = settings->sharpness; | |
486 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_S_CTRL, ¤t)) < 0) | |
487 DPLOG(ERROR) << "setting sharpness to " << settings->sharpness; | |
488 } | |
489 | |
457 callback.Run(true); | 490 callback.Run(true); |
458 } | 491 } |
459 | 492 |
460 void V4L2CaptureDelegate::SetRotation(int rotation) { | 493 void V4L2CaptureDelegate::SetRotation(int rotation) { |
461 DCHECK(v4l2_task_runner_->BelongsToCurrentThread()); | 494 DCHECK(v4l2_task_runner_->BelongsToCurrentThread()); |
462 DCHECK(rotation >= 0 && rotation < 360 && rotation % 90 == 0); | 495 DCHECK(rotation >= 0 && rotation < 360 && rotation % 90 == 0); |
463 rotation_ = rotation; | 496 rotation_ = rotation; |
464 } | 497 } |
465 | 498 |
466 V4L2CaptureDelegate::~V4L2CaptureDelegate() {} | 499 V4L2CaptureDelegate::~V4L2CaptureDelegate() {} |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
585 DLOG(ERROR) << "Error mmap()ing a V4L2 buffer into userspace"; | 618 DLOG(ERROR) << "Error mmap()ing a V4L2 buffer into userspace"; |
586 return false; | 619 return false; |
587 } | 620 } |
588 start_ = static_cast<uint8_t*>(start); | 621 start_ = static_cast<uint8_t*>(start); |
589 length_ = buffer.length; | 622 length_ = buffer.length; |
590 payload_size_ = 0; | 623 payload_size_ = 0; |
591 return true; | 624 return true; |
592 } | 625 } |
593 | 626 |
594 } // namespace media | 627 } // namespace media |
OLD | NEW |