| 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/capture/video/win/video_capture_device_win.h" | 5 #include "media/capture/video/win/video_capture_device_win.h" |
| 6 | 6 |
| 7 #include <ks.h> | 7 #include <ks.h> |
| 8 #include <ksmedia.h> | 8 #include <ksmedia.h> |
| 9 #include <objbase.h> | 9 #include <objbase.h> |
| 10 | 10 |
| (...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 458 | 458 |
| 459 // Start capturing. | 459 // Start capturing. |
| 460 hr = media_control_->Run(); | 460 hr = media_control_->Run(); |
| 461 if (FAILED(hr)) { | 461 if (FAILED(hr)) { |
| 462 SetErrorState(FROM_HERE, "Failed to start the Capture device.", hr); | 462 SetErrorState(FROM_HERE, "Failed to start the Capture device.", hr); |
| 463 return; | 463 return; |
| 464 } | 464 } |
| 465 | 465 |
| 466 client_->OnStarted(); | 466 client_->OnStarted(); |
| 467 state_ = kCapturing; | 467 state_ = kCapturing; |
| 468 |
| 469 base::win::ScopedComPtr<IKsTopologyInfo> info; |
| 470 hr = capture_filter_.CopyTo(info.GetAddressOf()); |
| 471 if (FAILED(hr)) { |
| 472 SetErrorState(FROM_HERE, "Failed to obtain the topology info.", hr); |
| 473 return; |
| 474 } |
| 475 |
| 476 DWORD num_nodes = 0; |
| 477 hr = info->get_NumNodes(&num_nodes); |
| 478 if (FAILED(hr)) { |
| 479 SetErrorState(FROM_HERE, "Failed to obtain the number of nodes.", hr); |
| 480 return; |
| 481 } |
| 482 |
| 483 // Every UVC camera is expected to have a single ICameraControl and a single |
| 484 // IVideoProcAmp nodes, and both are needed; ignore any unlikely later ones. |
| 485 GUID node_type; |
| 486 for (size_t i = 0; i < num_nodes; i++) { |
| 487 info->get_NodeType(i, &node_type); |
| 488 if (IsEqualGUID(node_type, KSNODETYPE_VIDEO_CAMERA_TERMINAL)) { |
| 489 hr = info->CreateNodeInstance(i, IID_PPV_ARGS(&camera_control_)); |
| 490 if (SUCCEEDED(hr)) |
| 491 break; |
| 492 SetErrorState(FROM_HERE, "Failed to retrieve the ICameraControl.", hr); |
| 493 return; |
| 494 } |
| 495 } |
| 496 for (size_t i = 0; i < num_nodes; i++) { |
| 497 info->get_NodeType(i, &node_type); |
| 498 if (IsEqualGUID(node_type, KSNODETYPE_VIDEO_PROCESSING)) { |
| 499 hr = info->CreateNodeInstance(i, IID_PPV_ARGS(&video_control_)); |
| 500 if (SUCCEEDED(hr)) |
| 501 break; |
| 502 SetErrorState(FROM_HERE, "Failed to retrieve the IVideoProcAmp.", hr); |
| 503 return; |
| 504 } |
| 505 } |
| 468 } | 506 } |
| 469 | 507 |
| 470 void VideoCaptureDeviceWin::StopAndDeAllocate() { | 508 void VideoCaptureDeviceWin::StopAndDeAllocate() { |
| 471 DCHECK(thread_checker_.CalledOnValidThread()); | 509 DCHECK(thread_checker_.CalledOnValidThread()); |
| 472 if (state_ != kCapturing) | 510 if (state_ != kCapturing) |
| 473 return; | 511 return; |
| 474 | 512 |
| 475 HRESULT hr = media_control_->Stop(); | 513 HRESULT hr = media_control_->Stop(); |
| 476 if (FAILED(hr)) { | 514 if (FAILED(hr)) { |
| 477 SetErrorState(FROM_HERE, "Failed to stop the capture graph.", hr); | 515 SetErrorState(FROM_HERE, "Failed to stop the capture graph.", hr); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 491 // SampleGrabber filter to a PIN_CATEGORY_STILL of |capture_filter_|. This | 529 // SampleGrabber filter to a PIN_CATEGORY_STILL of |capture_filter_|. This |
| 492 // way, however, is not widespread and proves too cumbersome, so we just grab | 530 // way, however, is not widespread and proves too cumbersome, so we just grab |
| 493 // the next captured frame instead. | 531 // the next captured frame instead. |
| 494 take_photo_callbacks_.push(std::move(callback)); | 532 take_photo_callbacks_.push(std::move(callback)); |
| 495 } | 533 } |
| 496 | 534 |
| 497 void VideoCaptureDeviceWin::GetPhotoState(GetPhotoStateCallback callback) { | 535 void VideoCaptureDeviceWin::GetPhotoState(GetPhotoStateCallback callback) { |
| 498 DCHECK(thread_checker_.CalledOnValidThread()); | 536 DCHECK(thread_checker_.CalledOnValidThread()); |
| 499 | 537 |
| 500 if (!camera_control_ || !video_control_) | 538 if (!camera_control_ || !video_control_) |
| 501 InitializeVideoAndCameraControls(); | 539 return; |
| 502 | 540 |
| 503 auto photo_capabilities = mojom::PhotoState::New(); | 541 auto photo_capabilities = mojom::PhotoState::New(); |
| 504 | 542 |
| 505 photo_capabilities->exposure_compensation = RetrieveControlRangeAndCurrent( | 543 photo_capabilities->exposure_compensation = RetrieveControlRangeAndCurrent( |
| 506 [this](auto... args) { | 544 [this](auto... args) { |
| 507 return this->camera_control_->getRange_Exposure(args...); | 545 return this->camera_control_->getRange_Exposure(args...); |
| 508 }, | 546 }, |
| 509 [this](auto... args) { | 547 [this](auto... args) { |
| 510 return this->camera_control_->get_Exposure(args...); | 548 return this->camera_control_->get_Exposure(args...); |
| 511 }, | 549 }, |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 583 | 621 |
| 584 callback.Run(std::move(photo_capabilities)); | 622 callback.Run(std::move(photo_capabilities)); |
| 585 } | 623 } |
| 586 | 624 |
| 587 void VideoCaptureDeviceWin::SetPhotoOptions( | 625 void VideoCaptureDeviceWin::SetPhotoOptions( |
| 588 mojom::PhotoSettingsPtr settings, | 626 mojom::PhotoSettingsPtr settings, |
| 589 VideoCaptureDevice::SetPhotoOptionsCallback callback) { | 627 VideoCaptureDevice::SetPhotoOptionsCallback callback) { |
| 590 DCHECK(thread_checker_.CalledOnValidThread()); | 628 DCHECK(thread_checker_.CalledOnValidThread()); |
| 591 | 629 |
| 592 if (!camera_control_ || !video_control_) | 630 if (!camera_control_ || !video_control_) |
| 593 InitializeVideoAndCameraControls(); | 631 return; |
| 594 | 632 |
| 595 HRESULT hr; | 633 HRESULT hr; |
| 596 | 634 |
| 597 if (settings->has_zoom) { | 635 if (settings->has_zoom) { |
| 598 hr = camera_control_->put_Zoom(settings->zoom, CameraControl_Flags_Manual); | 636 hr = camera_control_->put_Zoom(settings->zoom, CameraControl_Flags_Manual); |
| 599 DLOG_IF_FAILED_WITH_HRESULT("Zoom config failed", hr); | 637 DLOG_IF_FAILED_WITH_HRESULT("Zoom config failed", hr); |
| 600 if (FAILED(hr)) | 638 if (FAILED(hr)) |
| 601 return; | 639 return; |
| 602 } | 640 } |
| 603 | 641 |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 665 if (settings->has_sharpness) { | 703 if (settings->has_sharpness) { |
| 666 hr = video_control_->put_Sharpness(settings->sharpness, | 704 hr = video_control_->put_Sharpness(settings->sharpness, |
| 667 CameraControl_Flags_Manual); | 705 CameraControl_Flags_Manual); |
| 668 DLOG_IF_FAILED_WITH_HRESULT("Sharpness config failed", hr); | 706 DLOG_IF_FAILED_WITH_HRESULT("Sharpness config failed", hr); |
| 669 if (FAILED(hr)) | 707 if (FAILED(hr)) |
| 670 return; | 708 return; |
| 671 } | 709 } |
| 672 | 710 |
| 673 callback.Run(true); | 711 callback.Run(true); |
| 674 } | 712 } |
| 675 | |
| 676 void VideoCaptureDeviceWin::InitializeVideoAndCameraControls() { | |
| 677 base::win::ScopedComPtr<IKsTopologyInfo> info; | |
| 678 HRESULT hr = capture_filter_.CopyTo(info.GetAddressOf()); | |
| 679 if (FAILED(hr)) { | |
| 680 SetErrorState(FROM_HERE, "Failed to obtain the topology info.", hr); | |
| 681 return; | |
| 682 } | |
| 683 | |
| 684 DWORD num_nodes = 0; | |
| 685 hr = info->get_NumNodes(&num_nodes); | |
| 686 if (FAILED(hr)) { | |
| 687 SetErrorState(FROM_HERE, "Failed to obtain the number of nodes.", hr); | |
| 688 return; | |
| 689 } | |
| 690 | |
| 691 // Every UVC camera is expected to have a single ICameraControl and a single | |
| 692 // IVideoProcAmp nodes, and both are needed; ignore any unlikely later ones. | |
| 693 GUID node_type; | |
| 694 for (size_t i = 0; i < num_nodes; i++) { | |
| 695 info->get_NodeType(i, &node_type); | |
| 696 if (IsEqualGUID(node_type, KSNODETYPE_VIDEO_CAMERA_TERMINAL)) { | |
| 697 hr = info->CreateNodeInstance(i, IID_PPV_ARGS(&camera_control_)); | |
| 698 if (SUCCEEDED(hr)) | |
| 699 break; | |
| 700 SetErrorState(FROM_HERE, "Failed to retrieve the ICameraControl.", hr); | |
| 701 return; | |
| 702 } | |
| 703 } | |
| 704 for (size_t i = 0; i < num_nodes; i++) { | |
| 705 info->get_NodeType(i, &node_type); | |
| 706 if (IsEqualGUID(node_type, KSNODETYPE_VIDEO_PROCESSING)) { | |
| 707 hr = info->CreateNodeInstance(i, IID_PPV_ARGS(&video_control_)); | |
| 708 if (SUCCEEDED(hr)) | |
| 709 break; | |
| 710 SetErrorState(FROM_HERE, "Failed to retrieve the IVideoProcAmp.", hr); | |
| 711 return; | |
| 712 } | |
| 713 } | |
| 714 } | |
| 715 | |
| 716 // Implements SinkFilterObserver::SinkFilterObserver. | 713 // Implements SinkFilterObserver::SinkFilterObserver. |
| 717 void VideoCaptureDeviceWin::FrameReceived(const uint8_t* buffer, | 714 void VideoCaptureDeviceWin::FrameReceived(const uint8_t* buffer, |
| 718 int length, | 715 int length, |
| 719 const VideoCaptureFormat& format, | 716 const VideoCaptureFormat& format, |
| 720 base::TimeDelta timestamp) { | 717 base::TimeDelta timestamp) { |
| 721 if (first_ref_time_.is_null()) | 718 if (first_ref_time_.is_null()) |
| 722 first_ref_time_ = base::TimeTicks::Now(); | 719 first_ref_time_ = base::TimeTicks::Now(); |
| 723 | 720 |
| 724 // There is a chance that the platform does not provide us with the timestamp, | 721 // There is a chance that the platform does not provide us with the timestamp, |
| 725 // in which case, we use reference time to calculate a timestamp. | 722 // in which case, we use reference time to calculate a timestamp. |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 850 void VideoCaptureDeviceWin::SetErrorState( | 847 void VideoCaptureDeviceWin::SetErrorState( |
| 851 const tracked_objects::Location& from_here, | 848 const tracked_objects::Location& from_here, |
| 852 const std::string& reason, | 849 const std::string& reason, |
| 853 HRESULT hr) { | 850 HRESULT hr) { |
| 854 DCHECK(thread_checker_.CalledOnValidThread()); | 851 DCHECK(thread_checker_.CalledOnValidThread()); |
| 855 DLOG_IF_FAILED_WITH_HRESULT(reason, hr); | 852 DLOG_IF_FAILED_WITH_HRESULT(reason, hr); |
| 856 state_ = kError; | 853 state_ = kError; |
| 857 client_->OnError(from_here, reason); | 854 client_->OnError(from_here, reason); |
| 858 } | 855 } |
| 859 } // namespace media | 856 } // namespace media |
| OLD | NEW |