| 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_contrast) { |
| 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_saturation) { |
| 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_sharpness) { |
| 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 |