| 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 #include <vidcap.h> | |
| 11 | 10 |
| 12 #include <algorithm> | 11 #include <algorithm> |
| 13 #include <list> | 12 #include <list> |
| 14 #include <utility> | 13 #include <utility> |
| 15 | 14 |
| 16 #include "base/macros.h" | 15 #include "base/macros.h" |
| 17 #include "base/strings/sys_string_conversions.h" | 16 #include "base/strings/sys_string_conversions.h" |
| 18 #include "base/win/scoped_co_mem.h" | 17 #include "base/win/scoped_co_mem.h" |
| 19 #include "base/win/scoped_variant.h" | 18 #include "base/win/scoped_variant.h" |
| 20 #include "media/base/timestamp_constants.h" | 19 #include "media/base/timestamp_constants.h" |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 259 void VideoCaptureDeviceWin::ScopedMediaType::DeleteMediaType( | 258 void VideoCaptureDeviceWin::ScopedMediaType::DeleteMediaType( |
| 260 AM_MEDIA_TYPE* mt) { | 259 AM_MEDIA_TYPE* mt) { |
| 261 if (mt != NULL) { | 260 if (mt != NULL) { |
| 262 FreeMediaType(mt); | 261 FreeMediaType(mt); |
| 263 CoTaskMemFree(mt); | 262 CoTaskMemFree(mt); |
| 264 } | 263 } |
| 265 } | 264 } |
| 266 | 265 |
| 267 VideoCaptureDeviceWin::VideoCaptureDeviceWin( | 266 VideoCaptureDeviceWin::VideoCaptureDeviceWin( |
| 268 const VideoCaptureDeviceDescriptor& device_descriptor) | 267 const VideoCaptureDeviceDescriptor& device_descriptor) |
| 269 : device_descriptor_(device_descriptor), state_(kIdle) { | 268 : device_descriptor_(device_descriptor), |
| 269 state_(kIdle), |
| 270 white_balance_mode_manual_(false), |
| 271 exposure_mode_manual_(false) { |
| 270 // TODO(mcasas): Check that CoInitializeEx() has been called with the | 272 // TODO(mcasas): Check that CoInitializeEx() has been called with the |
| 271 // appropriate Apartment model, i.e., Single Threaded. | 273 // appropriate Apartment model, i.e., Single Threaded. |
| 272 } | 274 } |
| 273 | 275 |
| 274 VideoCaptureDeviceWin::~VideoCaptureDeviceWin() { | 276 VideoCaptureDeviceWin::~VideoCaptureDeviceWin() { |
| 275 DCHECK(thread_checker_.CalledOnValidThread()); | 277 DCHECK(thread_checker_.CalledOnValidThread()); |
| 276 if (media_control_.Get()) | 278 if (media_control_.Get()) |
| 277 media_control_->Stop(); | 279 media_control_->Stop(); |
| 278 | 280 |
| 279 if (graph_builder_.Get()) { | 281 if (graph_builder_.Get()) { |
| 280 if (sink_filter_.get()) { | 282 if (sink_filter_.get()) { |
| 281 graph_builder_->RemoveFilter(sink_filter_.get()); | 283 graph_builder_->RemoveFilter(sink_filter_.get()); |
| 282 sink_filter_ = NULL; | 284 sink_filter_ = NULL; |
| 283 } | 285 } |
| 284 | 286 |
| 285 if (capture_filter_.Get()) | 287 if (capture_filter_.Get()) |
| 286 graph_builder_->RemoveFilter(capture_filter_.Get()); | 288 graph_builder_->RemoveFilter(capture_filter_.Get()); |
| 287 } | 289 } |
| 288 | 290 |
| 289 if (capture_graph_builder_.Get()) | 291 if (capture_graph_builder_.Get()) |
| 290 capture_graph_builder_.Reset(); | 292 capture_graph_builder_.Reset(); |
| 291 } | 293 } |
| 292 | 294 |
| 293 bool VideoCaptureDeviceWin::Init() { | 295 bool VideoCaptureDeviceWin::Init() { |
| 294 DCHECK(thread_checker_.CalledOnValidThread()); | 296 DCHECK(thread_checker_.CalledOnValidThread()); |
| 295 HRESULT hr; | 297 HRESULT hr = GetDeviceFilter(device_descriptor_.device_id, |
| 296 | 298 capture_filter_.GetAddressOf()); |
| 297 hr = GetDeviceFilter(device_descriptor_.device_id, | |
| 298 capture_filter_.GetAddressOf()); | |
| 299 DLOG_IF_FAILED_WITH_HRESULT("Failed to create capture filter", hr); | 299 DLOG_IF_FAILED_WITH_HRESULT("Failed to create capture filter", hr); |
| 300 if (!capture_filter_.Get()) | 300 if (!capture_filter_.Get()) |
| 301 return false; | 301 return false; |
| 302 | 302 |
| 303 output_capture_pin_ = GetPin(capture_filter_.Get(), PINDIR_OUTPUT, | 303 output_capture_pin_ = GetPin(capture_filter_.Get(), PINDIR_OUTPUT, |
| 304 PIN_CATEGORY_CAPTURE, GUID_NULL); | 304 PIN_CATEGORY_CAPTURE, GUID_NULL); |
| 305 if (!output_capture_pin_.Get()) { | 305 if (!output_capture_pin_.Get()) { |
| 306 DLOG(ERROR) << "Failed to get capture output pin"; | 306 DLOG(ERROR) << "Failed to get capture output pin"; |
| 307 return false; | 307 return false; |
| 308 } | 308 } |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 424 // Set the sink filter to request this format. | 424 // Set the sink filter to request this format. |
| 425 sink_filter_->SetRequestedMediaFormat( | 425 sink_filter_->SetRequestedMediaFormat( |
| 426 found_capability.supported_format.pixel_format, frame_rate, | 426 found_capability.supported_format.pixel_format, frame_rate, |
| 427 found_capability.info_header); | 427 found_capability.info_header); |
| 428 // Order the capture device to use this format. | 428 // Order the capture device to use this format. |
| 429 hr = stream_config->SetFormat(media_type.get()); | 429 hr = stream_config->SetFormat(media_type.get()); |
| 430 if (FAILED(hr)) { | 430 if (FAILED(hr)) { |
| 431 SetErrorState(FROM_HERE, "Failed to set capture device output format", hr); | 431 SetErrorState(FROM_HERE, "Failed to set capture device output format", hr); |
| 432 return; | 432 return; |
| 433 } | 433 } |
| 434 capture_format_ = found_capability.supported_format; |
| 434 | 435 |
| 435 SetAntiFlickerInCaptureFilter(params); | 436 SetAntiFlickerInCaptureFilter(params); |
| 436 | 437 |
| 437 if (media_type->subtype == kMediaSubTypeHDYC) { | 438 if (media_type->subtype == kMediaSubTypeHDYC) { |
| 438 // HDYC pixel format, used by the DeckLink capture card, needs an AVI | 439 // HDYC pixel format, used by the DeckLink capture card, needs an AVI |
| 439 // decompressor filter after source, let |graph_builder_| add it. | 440 // decompressor filter after source, let |graph_builder_| add it. |
| 440 hr = graph_builder_->Connect(output_capture_pin_.Get(), | 441 hr = graph_builder_->Connect(output_capture_pin_.Get(), |
| 441 input_sink_pin_.Get()); | 442 input_sink_pin_.Get()); |
| 442 } else { | 443 } else { |
| 443 hr = graph_builder_->ConnectDirect(output_capture_pin_.Get(), | 444 hr = graph_builder_->ConnectDirect(output_capture_pin_.Get(), |
| (...skipping 13 matching lines...) Expand all Loading... |
| 457 | 458 |
| 458 // Start capturing. | 459 // Start capturing. |
| 459 hr = media_control_->Run(); | 460 hr = media_control_->Run(); |
| 460 if (FAILED(hr)) { | 461 if (FAILED(hr)) { |
| 461 SetErrorState(FROM_HERE, "Failed to start the Capture device.", hr); | 462 SetErrorState(FROM_HERE, "Failed to start the Capture device.", hr); |
| 462 return; | 463 return; |
| 463 } | 464 } |
| 464 | 465 |
| 465 client_->OnStarted(); | 466 client_->OnStarted(); |
| 466 state_ = kCapturing; | 467 state_ = kCapturing; |
| 467 } | |
| 468 | |
| 469 void VideoCaptureDeviceWin::StopAndDeAllocate() { | |
| 470 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 471 if (state_ != kCapturing) | |
| 472 return; | |
| 473 | |
| 474 HRESULT hr = media_control_->Stop(); | |
| 475 if (FAILED(hr)) { | |
| 476 SetErrorState(FROM_HERE, "Failed to stop the capture graph.", hr); | |
| 477 return; | |
| 478 } | |
| 479 | |
| 480 graph_builder_->Disconnect(output_capture_pin_.Get()); | |
| 481 graph_builder_->Disconnect(input_sink_pin_.Get()); | |
| 482 | |
| 483 client_.reset(); | |
| 484 state_ = kIdle; | |
| 485 } | |
| 486 | |
| 487 void VideoCaptureDeviceWin::TakePhoto(TakePhotoCallback callback) { | |
| 488 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 489 // DirectShow has other means of capturing still pictures, e.g. connecting a | |
| 490 // SampleGrabber filter to a PIN_CATEGORY_STILL of |capture_filter_|. This | |
| 491 // way, however, is not widespread and proves too cumbersome, so we just grab | |
| 492 // the next captured frame instead. | |
| 493 take_photo_callbacks_.push(std::move(callback)); | |
| 494 } | |
| 495 | |
| 496 void VideoCaptureDeviceWin::GetPhotoCapabilities( | |
| 497 GetPhotoCapabilitiesCallback callback) { | |
| 498 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 499 | 468 |
| 500 base::win::ScopedComPtr<IKsTopologyInfo> info; | 469 base::win::ScopedComPtr<IKsTopologyInfo> info; |
| 501 HRESULT hr = capture_filter_.CopyTo(info.GetAddressOf()); | 470 hr = capture_filter_.CopyTo(info.GetAddressOf()); |
| 502 if (FAILED(hr)) { | 471 if (FAILED(hr)) { |
| 503 SetErrorState(FROM_HERE, "Failed to obtain the topology info.", hr); | 472 SetErrorState(FROM_HERE, "Failed to obtain the topology info.", hr); |
| 504 return; | 473 return; |
| 505 } | 474 } |
| 506 | 475 |
| 507 DWORD num_nodes = 0; | 476 DWORD num_nodes = 0; |
| 508 hr = info->get_NumNodes(&num_nodes); | 477 hr = info->get_NumNodes(&num_nodes); |
| 509 if (FAILED(hr)) { | 478 if (FAILED(hr)) { |
| 510 SetErrorState(FROM_HERE, "Failed to obtain the number of nodes.", hr); | 479 SetErrorState(FROM_HERE, "Failed to obtain the number of nodes.", hr); |
| 511 return; | 480 return; |
| 512 } | 481 } |
| 513 | 482 |
| 514 // Every UVC camera is expected to have a single ICameraControl and a single | 483 // Every UVC camera is expected to have a single ICameraControl and a single |
| 515 // IVideoProcAmp nodes, and both are needed; ignore any unlikely later ones. | 484 // IVideoProcAmp nodes, and both are needed; ignore any unlikely later ones. |
| 516 GUID node_type; | 485 GUID node_type; |
| 517 base::win::ScopedComPtr<ICameraControl> camera_control; | |
| 518 for (size_t i = 0; i < num_nodes; i++) { | 486 for (size_t i = 0; i < num_nodes; i++) { |
| 519 info->get_NodeType(i, &node_type); | 487 info->get_NodeType(i, &node_type); |
| 520 if (IsEqualGUID(node_type, KSNODETYPE_VIDEO_CAMERA_TERMINAL)) { | 488 if (IsEqualGUID(node_type, KSNODETYPE_VIDEO_CAMERA_TERMINAL)) { |
| 521 hr = info->CreateNodeInstance(i, IID_PPV_ARGS(&camera_control)); | 489 hr = info->CreateNodeInstance(i, IID_PPV_ARGS(&camera_control_)); |
| 522 if (SUCCEEDED(hr)) | 490 if (SUCCEEDED(hr)) |
| 523 break; | 491 break; |
| 524 SetErrorState(FROM_HERE, "Failed to retrieve the ICameraControl.", hr); | 492 SetErrorState(FROM_HERE, "Failed to retrieve the ICameraControl.", hr); |
| 525 return; | 493 return; |
| 526 } | 494 } |
| 527 } | 495 } |
| 528 if (!camera_control) | |
| 529 return; | |
| 530 base::win::ScopedComPtr<IVideoProcAmp> video_control; | |
| 531 for (size_t i = 0; i < num_nodes; i++) { | 496 for (size_t i = 0; i < num_nodes; i++) { |
| 532 info->get_NodeType(i, &node_type); | 497 info->get_NodeType(i, &node_type); |
| 533 if (IsEqualGUID(node_type, KSNODETYPE_VIDEO_PROCESSING)) { | 498 if (IsEqualGUID(node_type, KSNODETYPE_VIDEO_PROCESSING)) { |
| 534 hr = info->CreateNodeInstance(i, IID_PPV_ARGS(&video_control)); | 499 hr = info->CreateNodeInstance(i, IID_PPV_ARGS(&video_control_)); |
| 535 if (SUCCEEDED(hr)) | 500 if (SUCCEEDED(hr)) |
| 536 break; | 501 break; |
| 537 SetErrorState(FROM_HERE, "Failed to retrieve the IVideoProcAmp.", hr); | 502 SetErrorState(FROM_HERE, "Failed to retrieve the IVideoProcAmp.", hr); |
| 538 return; | 503 return; |
| 539 } | 504 } |
| 540 } | 505 } |
| 541 if (!video_control) | 506 } |
| 507 |
| 508 void VideoCaptureDeviceWin::StopAndDeAllocate() { |
| 509 DCHECK(thread_checker_.CalledOnValidThread()); |
| 510 if (state_ != kCapturing) |
| 511 return; |
| 512 |
| 513 HRESULT hr = media_control_->Stop(); |
| 514 if (FAILED(hr)) { |
| 515 SetErrorState(FROM_HERE, "Failed to stop the capture graph.", hr); |
| 516 return; |
| 517 } |
| 518 |
| 519 graph_builder_->Disconnect(output_capture_pin_.Get()); |
| 520 graph_builder_->Disconnect(input_sink_pin_.Get()); |
| 521 |
| 522 client_.reset(); |
| 523 state_ = kIdle; |
| 524 } |
| 525 |
| 526 void VideoCaptureDeviceWin::TakePhoto(TakePhotoCallback callback) { |
| 527 DCHECK(thread_checker_.CalledOnValidThread()); |
| 528 // DirectShow has other means of capturing still pictures, e.g. connecting a |
| 529 // SampleGrabber filter to a PIN_CATEGORY_STILL of |capture_filter_|. This |
| 530 // way, however, is not widespread and proves too cumbersome, so we just grab |
| 531 // the next captured frame instead. |
| 532 take_photo_callbacks_.push(std::move(callback)); |
| 533 } |
| 534 |
| 535 void VideoCaptureDeviceWin::GetPhotoCapabilities( |
| 536 GetPhotoCapabilitiesCallback callback) { |
| 537 DCHECK(thread_checker_.CalledOnValidThread()); |
| 538 |
| 539 if (!camera_control_ || !video_control_) |
| 542 return; | 540 return; |
| 543 | 541 |
| 544 auto photo_capabilities = mojom::PhotoCapabilities::New(); | 542 auto photo_capabilities = mojom::PhotoCapabilities::New(); |
| 545 | 543 |
| 546 photo_capabilities->exposure_compensation = RetrieveControlRangeAndCurrent( | 544 photo_capabilities->exposure_compensation = RetrieveControlRangeAndCurrent( |
| 547 [camera_control](auto... args) { | 545 [this](auto... args) { |
| 548 return camera_control->getRange_Exposure(args...); | 546 return this->camera_control_->getRange_Exposure(args...); |
| 549 }, | 547 }, |
| 550 [camera_control](auto... args) { | 548 [this](auto... args) { |
| 551 return camera_control->get_Exposure(args...); | 549 return this->camera_control_->get_Exposure(args...); |
| 552 }, | 550 }, |
| 553 &photo_capabilities->supported_exposure_modes, | 551 &photo_capabilities->supported_exposure_modes, |
| 554 &photo_capabilities->current_exposure_mode); | 552 &photo_capabilities->current_exposure_mode); |
| 555 | 553 |
| 556 photo_capabilities->color_temperature = RetrieveControlRangeAndCurrent( | 554 photo_capabilities->color_temperature = RetrieveControlRangeAndCurrent( |
| 557 [video_control](auto... args) { | 555 [this](auto... args) { |
| 558 return video_control->getRange_WhiteBalance(args...); | 556 return this->video_control_->getRange_WhiteBalance(args...); |
| 559 }, | 557 }, |
| 560 [video_control](auto... args) { | 558 [this](auto... args) { |
| 561 return video_control->get_WhiteBalance(args...); | 559 return this->video_control_->get_WhiteBalance(args...); |
| 562 }, | 560 }, |
| 563 &photo_capabilities->supported_white_balance_modes, | 561 &photo_capabilities->supported_white_balance_modes, |
| 564 &photo_capabilities->current_white_balance_mode); | 562 &photo_capabilities->current_white_balance_mode); |
| 565 | 563 |
| 566 // Ignore the returned Focus control range and status. | 564 // Ignore the returned Focus control range and status. |
| 567 RetrieveControlRangeAndCurrent( | 565 RetrieveControlRangeAndCurrent( |
| 568 [camera_control](auto... args) { | 566 [this](auto... args) { |
| 569 return camera_control->getRange_Focus(args...); | 567 return this->camera_control_->getRange_Focus(args...); |
| 570 }, | 568 }, |
| 571 [camera_control](auto... args) { | 569 [this](auto... args) { |
| 572 return camera_control->get_Focus(args...); | 570 return this->camera_control_->get_Focus(args...); |
| 573 }, | 571 }, |
| 574 &photo_capabilities->supported_focus_modes, | 572 &photo_capabilities->supported_focus_modes, |
| 575 &photo_capabilities->current_focus_mode); | 573 &photo_capabilities->current_focus_mode); |
| 576 | 574 |
| 577 photo_capabilities->iso = mojom::Range::New(); | 575 photo_capabilities->iso = mojom::Range::New(); |
| 578 | 576 |
| 579 photo_capabilities->brightness = RetrieveControlRangeAndCurrent( | 577 photo_capabilities->brightness = RetrieveControlRangeAndCurrent( |
| 580 [video_control](auto... args) { | 578 [this](auto... args) { |
| 581 return video_control->getRange_Brightness(args...); | 579 return this->video_control_->getRange_Brightness(args...); |
| 582 }, | 580 }, |
| 583 [video_control](auto... args) { | 581 [this](auto... args) { |
| 584 return video_control->get_Brightness(args...); | 582 return this->video_control_->get_Brightness(args...); |
| 585 }); | 583 }); |
| 586 photo_capabilities->contrast = RetrieveControlRangeAndCurrent( | 584 photo_capabilities->contrast = RetrieveControlRangeAndCurrent( |
| 587 [video_control](auto... args) { | 585 [this](auto... args) { |
| 588 return video_control->getRange_Contrast(args...); | 586 return this->video_control_->getRange_Contrast(args...); |
| 589 }, | 587 }, |
| 590 [video_control](auto... args) { | 588 [this](auto... args) { |
| 591 return video_control->get_Contrast(args...); | 589 return this->video_control_->get_Contrast(args...); |
| 592 }); | 590 }); |
| 593 photo_capabilities->saturation = RetrieveControlRangeAndCurrent( | 591 photo_capabilities->saturation = RetrieveControlRangeAndCurrent( |
| 594 [video_control](auto... args) { | 592 [this](auto... args) { |
| 595 return video_control->getRange_Saturation(args...); | 593 return this->video_control_->getRange_Saturation(args...); |
| 596 }, | 594 }, |
| 597 [video_control](auto... args) { | 595 [this](auto... args) { |
| 598 return video_control->get_Saturation(args...); | 596 return this->video_control_->get_Saturation(args...); |
| 599 }); | 597 }); |
| 600 photo_capabilities->sharpness = RetrieveControlRangeAndCurrent( | 598 photo_capabilities->sharpness = RetrieveControlRangeAndCurrent( |
| 601 [video_control](auto... args) { | 599 [this](auto... args) { |
| 602 return video_control->getRange_Sharpness(args...); | 600 return this->video_control_->getRange_Sharpness(args...); |
| 603 }, | 601 }, |
| 604 [video_control](auto... args) { | 602 [this](auto... args) { |
| 605 return video_control->get_Sharpness(args...); | 603 return this->video_control_->get_Sharpness(args...); |
| 606 }); | 604 }); |
| 607 | 605 |
| 608 photo_capabilities->zoom = RetrieveControlRangeAndCurrent( | 606 photo_capabilities->zoom = RetrieveControlRangeAndCurrent( |
| 609 [camera_control](auto... args) { | 607 [this](auto... args) { |
| 610 return camera_control->getRange_Zoom(args...); | 608 return this->camera_control_->getRange_Zoom(args...); |
| 611 }, | 609 }, |
| 612 [camera_control](auto... args) { | 610 [this](auto... args) { |
| 613 return camera_control->get_Zoom(args...); | 611 return this->camera_control_->get_Zoom(args...); |
| 614 }); | 612 }); |
| 615 | 613 |
| 616 photo_capabilities->red_eye_reduction = mojom::RedEyeReduction::NEVER; | 614 photo_capabilities->red_eye_reduction = mojom::RedEyeReduction::NEVER; |
| 617 photo_capabilities->height = mojom::Range::New(); | 615 photo_capabilities->height = mojom::Range::New( |
| 618 photo_capabilities->width = mojom::Range::New(); | 616 capture_format_.frame_size.height(), capture_format_.frame_size.height(), |
| 617 capture_format_.frame_size.height(), 0 /* step */); |
| 618 photo_capabilities->width = mojom::Range::New( |
| 619 capture_format_.frame_size.width(), capture_format_.frame_size.width(), |
| 620 capture_format_.frame_size.width(), 0 /* step */); |
| 619 photo_capabilities->torch = false; | 621 photo_capabilities->torch = false; |
| 620 | 622 |
| 621 callback.Run(std::move(photo_capabilities)); | 623 callback.Run(std::move(photo_capabilities)); |
| 622 } | 624 } |
| 623 | 625 |
| 626 void VideoCaptureDeviceWin::SetPhotoOptions( |
| 627 mojom::PhotoSettingsPtr settings, |
| 628 VideoCaptureDevice::SetPhotoOptionsCallback callback) { |
| 629 DCHECK(thread_checker_.CalledOnValidThread()); |
| 630 |
| 631 if (!camera_control_ || !video_control_) |
| 632 return; |
| 633 |
| 634 HRESULT hr; |
| 635 |
| 636 if (settings->has_zoom) { |
| 637 hr = camera_control_->put_Zoom(settings->zoom, CameraControl_Flags_Manual); |
| 638 DLOG_IF_FAILED_WITH_HRESULT("Zoom config failed", hr); |
| 639 if (FAILED(hr)) |
| 640 return; |
| 641 } |
| 642 |
| 643 if (settings->has_white_balance_mode) { |
| 644 if (settings->white_balance_mode == mojom::MeteringMode::CONTINUOUS) { |
| 645 hr = video_control_->put_WhiteBalance(0L, VideoProcAmp_Flags_Auto); |
| 646 DLOG_IF_FAILED_WITH_HRESULT("Auto white balance config failed", hr); |
| 647 if (FAILED(hr)) |
| 648 return; |
| 649 |
| 650 white_balance_mode_manual_ = false; |
| 651 } else { |
| 652 white_balance_mode_manual_ = true; |
| 653 } |
| 654 } |
| 655 if (white_balance_mode_manual_ && settings->has_color_temperature) { |
| 656 hr = video_control_->put_WhiteBalance(settings->color_temperature, |
| 657 CameraControl_Flags_Manual); |
| 658 DLOG_IF_FAILED_WITH_HRESULT("Color temperature config failed", hr); |
| 659 if (FAILED(hr)) |
| 660 return; |
| 661 } |
| 662 |
| 663 if (settings->has_exposure_mode) { |
| 664 if (settings->exposure_mode == mojom::MeteringMode::CONTINUOUS) { |
| 665 hr = camera_control_->put_Exposure(0L, VideoProcAmp_Flags_Auto); |
| 666 DLOG_IF_FAILED_WITH_HRESULT("Auto exposure config failed", hr); |
| 667 if (FAILED(hr)) |
| 668 return; |
| 669 |
| 670 exposure_mode_manual_ = false; |
| 671 } else { |
| 672 exposure_mode_manual_ = true; |
| 673 } |
| 674 } |
| 675 if (exposure_mode_manual_ && settings->has_exposure_compensation) { |
| 676 hr = camera_control_->put_Exposure(settings->exposure_compensation, |
| 677 CameraControl_Flags_Manual); |
| 678 DLOG_IF_FAILED_WITH_HRESULT("Exposure Compensation config failed", hr); |
| 679 if (FAILED(hr)) |
| 680 return; |
| 681 } |
| 682 |
| 683 if (settings->has_brightness) { |
| 684 hr = video_control_->put_Brightness(settings->brightness, |
| 685 CameraControl_Flags_Manual); |
| 686 DLOG_IF_FAILED_WITH_HRESULT("Brightness config failed", hr); |
| 687 if (FAILED(hr)) |
| 688 return; |
| 689 } |
| 690 if (settings->has_contrast) { |
| 691 hr = video_control_->put_Contrast(settings->contrast, |
| 692 CameraControl_Flags_Manual); |
| 693 DLOG_IF_FAILED_WITH_HRESULT("Contrast config failed", hr); |
| 694 if (FAILED(hr)) |
| 695 return; |
| 696 } |
| 697 if (settings->has_saturation) { |
| 698 hr = video_control_->put_Saturation(settings->saturation, |
| 699 CameraControl_Flags_Manual); |
| 700 DLOG_IF_FAILED_WITH_HRESULT("Saturation config failed", hr); |
| 701 if (FAILED(hr)) |
| 702 return; |
| 703 } |
| 704 if (settings->has_sharpness) { |
| 705 hr = video_control_->put_Sharpness(settings->sharpness, |
| 706 CameraControl_Flags_Manual); |
| 707 DLOG_IF_FAILED_WITH_HRESULT("Sharpness config failed", hr); |
| 708 if (FAILED(hr)) |
| 709 return; |
| 710 } |
| 711 |
| 712 callback.Run(true); |
| 713 } |
| 624 // Implements SinkFilterObserver::SinkFilterObserver. | 714 // Implements SinkFilterObserver::SinkFilterObserver. |
| 625 void VideoCaptureDeviceWin::FrameReceived(const uint8_t* buffer, | 715 void VideoCaptureDeviceWin::FrameReceived(const uint8_t* buffer, |
| 626 int length, | 716 int length, |
| 627 const VideoCaptureFormat& format, | 717 const VideoCaptureFormat& format, |
| 628 base::TimeDelta timestamp) { | 718 base::TimeDelta timestamp) { |
| 629 if (first_ref_time_.is_null()) | 719 if (first_ref_time_.is_null()) |
| 630 first_ref_time_ = base::TimeTicks::Now(); | 720 first_ref_time_ = base::TimeTicks::Now(); |
| 631 | 721 |
| 632 // There is a chance that the platform does not provide us with the timestamp, | 722 // There is a chance that the platform does not provide us with the timestamp, |
| 633 // in which case, we use reference time to calculate a timestamp. | 723 // in which case, we use reference time to calculate a timestamp. |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 758 void VideoCaptureDeviceWin::SetErrorState( | 848 void VideoCaptureDeviceWin::SetErrorState( |
| 759 const tracked_objects::Location& from_here, | 849 const tracked_objects::Location& from_here, |
| 760 const std::string& reason, | 850 const std::string& reason, |
| 761 HRESULT hr) { | 851 HRESULT hr) { |
| 762 DCHECK(thread_checker_.CalledOnValidThread()); | 852 DCHECK(thread_checker_.CalledOnValidThread()); |
| 763 DLOG_IF_FAILED_WITH_HRESULT(reason, hr); | 853 DLOG_IF_FAILED_WITH_HRESULT(reason, hr); |
| 764 state_ = kError; | 854 state_ = kError; |
| 765 client_->OnError(from_here, reason); | 855 client_->OnError(from_here, reason); |
| 766 } | 856 } |
| 767 } // namespace media | 857 } // namespace media |
| OLD | NEW |