Chromium Code Reviews| Index: media/capture/video/win/video_capture_device_win.cc |
| diff --git a/media/capture/video/win/video_capture_device_win.cc b/media/capture/video/win/video_capture_device_win.cc |
| index 43bd83ab52a02d7c75717b5d51d01686019d33b0..12d73a9e0b65d6ea6c083aa023bbea540e62cddb 100644 |
| --- a/media/capture/video/win/video_capture_device_win.cc |
| +++ b/media/capture/video/win/video_capture_device_win.cc |
| @@ -7,7 +7,6 @@ |
| #include <ks.h> |
| #include <ksmedia.h> |
| #include <objbase.h> |
| -#include <vidcap.h> |
| #include <algorithm> |
| #include <list> |
| @@ -266,7 +265,10 @@ void VideoCaptureDeviceWin::ScopedMediaType::DeleteMediaType( |
| VideoCaptureDeviceWin::VideoCaptureDeviceWin( |
| const VideoCaptureDeviceDescriptor& device_descriptor) |
| - : device_descriptor_(device_descriptor), state_(kIdle) { |
| + : device_descriptor_(device_descriptor), |
| + state_(kIdle), |
| + white_balance_mode_manual_(false), |
| + exposure_mode_manual_(false) { |
| // TODO(mcasas): Check that CoInitializeEx() has been called with the |
| // appropriate Apartment model, i.e., Single Threaded. |
| } |
| @@ -463,41 +465,9 @@ void VideoCaptureDeviceWin::AllocateAndStart( |
| client_->OnStarted(); |
| state_ = kCapturing; |
| -} |
| - |
| -void VideoCaptureDeviceWin::StopAndDeAllocate() { |
| - DCHECK(thread_checker_.CalledOnValidThread()); |
| - if (state_ != kCapturing) |
| - return; |
| - |
| - HRESULT hr = media_control_->Stop(); |
| - if (FAILED(hr)) { |
| - SetErrorState(FROM_HERE, "Failed to stop the capture graph.", hr); |
| - return; |
| - } |
| - |
| - graph_builder_->Disconnect(output_capture_pin_.Get()); |
| - graph_builder_->Disconnect(input_sink_pin_.Get()); |
| - |
| - client_.reset(); |
| - state_ = kIdle; |
| -} |
| - |
| -void VideoCaptureDeviceWin::TakePhoto(TakePhotoCallback callback) { |
| - DCHECK(thread_checker_.CalledOnValidThread()); |
| - // DirectShow has other means of capturing still pictures, e.g. connecting a |
| - // SampleGrabber filter to a PIN_CATEGORY_STILL of |capture_filter_|. This |
| - // way, however, is not widespread and proves too cumbersome, so we just grab |
| - // the next captured frame instead. |
| - take_photo_callbacks_.push(std::move(callback)); |
| -} |
| - |
| -void VideoCaptureDeviceWin::GetPhotoCapabilities( |
| - GetPhotoCapabilitiesCallback callback) { |
| - DCHECK(thread_checker_.CalledOnValidThread()); |
| base::win::ScopedComPtr<IKsTopologyInfo> info; |
| - HRESULT hr = capture_filter_.CopyTo(info.Receive()); |
| + hr = capture_filter_.CopyTo(info.Receive()); |
|
robliao
2017/05/11 05:14:07
Conflict warning: Receive is being renamed to GetA
mcasas
2017/05/12 18:52:49
gotcha! Will rebase.
|
| if (FAILED(hr)) { |
| SetErrorState(FROM_HERE, "Failed to obtain the topology info.", hr); |
| return; |
| @@ -513,62 +483,91 @@ void VideoCaptureDeviceWin::GetPhotoCapabilities( |
| // Every UVC camera is expected to have a single ICameraControl and a single |
| // IVideoProcAmp nodes, and both are needed; ignore any unlikely later ones. |
| GUID node_type; |
| - base::win::ScopedComPtr<ICameraControl> camera_control; |
| for (size_t i = 0; i < num_nodes; i++) { |
| info->get_NodeType(i, &node_type); |
| if (IsEqualGUID(node_type, KSNODETYPE_VIDEO_CAMERA_TERMINAL)) { |
| - hr = info->CreateNodeInstance(i, IID_PPV_ARGS(camera_control.Receive())); |
| + hr = info->CreateNodeInstance(i, IID_PPV_ARGS(camera_control_.Receive())); |
| if (SUCCEEDED(hr)) |
| break; |
| SetErrorState(FROM_HERE, "Failed to retrieve the ICameraControl.", hr); |
| return; |
| } |
| } |
| - if (!camera_control) |
| - return; |
| - base::win::ScopedComPtr<IVideoProcAmp> video_control; |
| for (size_t i = 0; i < num_nodes; i++) { |
| info->get_NodeType(i, &node_type); |
| if (IsEqualGUID(node_type, KSNODETYPE_VIDEO_PROCESSING)) { |
| - hr = info->CreateNodeInstance(i, IID_PPV_ARGS(video_control.Receive())); |
| + hr = info->CreateNodeInstance(i, IID_PPV_ARGS(video_control_.Receive())); |
| if (SUCCEEDED(hr)) |
| break; |
| SetErrorState(FROM_HERE, "Failed to retrieve the IVideoProcAmp.", hr); |
| return; |
| } |
| } |
| - if (!video_control) |
| +} |
| + |
| +void VideoCaptureDeviceWin::StopAndDeAllocate() { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + if (state_ != kCapturing) |
| + return; |
| + |
| + HRESULT hr = media_control_->Stop(); |
| + if (FAILED(hr)) { |
| + SetErrorState(FROM_HERE, "Failed to stop the capture graph.", hr); |
| + return; |
| + } |
| + |
| + graph_builder_->Disconnect(output_capture_pin_.Get()); |
| + graph_builder_->Disconnect(input_sink_pin_.Get()); |
| + |
| + client_.reset(); |
| + state_ = kIdle; |
| +} |
| + |
| +void VideoCaptureDeviceWin::TakePhoto(TakePhotoCallback callback) { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + // DirectShow has other means of capturing still pictures, e.g. connecting a |
| + // SampleGrabber filter to a PIN_CATEGORY_STILL of |capture_filter_|. This |
| + // way, however, is not widespread and proves too cumbersome, so we just grab |
| + // the next captured frame instead. |
| + take_photo_callbacks_.push(std::move(callback)); |
| +} |
| + |
| +void VideoCaptureDeviceWin::GetPhotoCapabilities( |
| + GetPhotoCapabilitiesCallback callback) { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + |
| + if (!camera_control_ || !video_control_) |
| return; |
| auto photo_capabilities = mojom::PhotoCapabilities::New(); |
| photo_capabilities->exposure_compensation = RetrieveControlRangeAndCurrent( |
| - [camera_control](auto... args) { |
| - return camera_control->getRange_Exposure(args...); |
| + [this](auto... args) { |
| + return this->camera_control_->getRange_Exposure(args...); |
| }, |
| - [camera_control](auto... args) { |
| - return camera_control->get_Exposure(args...); |
| + [this](auto... args) { |
| + return this->camera_control_->get_Exposure(args...); |
| }, |
| &photo_capabilities->supported_exposure_modes, |
| &photo_capabilities->current_exposure_mode); |
| photo_capabilities->color_temperature = RetrieveControlRangeAndCurrent( |
| - [video_control](auto... args) { |
| - return video_control->getRange_WhiteBalance(args...); |
| + [this](auto... args) { |
| + return this->video_control_->getRange_WhiteBalance(args...); |
| }, |
| - [video_control](auto... args) { |
| - return video_control->get_WhiteBalance(args...); |
| + [this](auto... args) { |
| + return this->video_control_->get_WhiteBalance(args...); |
| }, |
| &photo_capabilities->supported_white_balance_modes, |
| &photo_capabilities->current_white_balance_mode); |
| // Ignore the returned Focus control range and status. |
| RetrieveControlRangeAndCurrent( |
| - [camera_control](auto... args) { |
| - return camera_control->getRange_Focus(args...); |
| + [this](auto... args) { |
| + return this->camera_control_->getRange_Focus(args...); |
| }, |
| - [camera_control](auto... args) { |
| - return camera_control->get_Focus(args...); |
| + [this](auto... args) { |
| + return this->camera_control_->get_Focus(args...); |
| }, |
| &photo_capabilities->supported_focus_modes, |
| &photo_capabilities->current_focus_mode); |
| @@ -576,40 +575,40 @@ void VideoCaptureDeviceWin::GetPhotoCapabilities( |
| photo_capabilities->iso = mojom::Range::New(); |
| photo_capabilities->brightness = RetrieveControlRangeAndCurrent( |
| - [video_control](auto... args) { |
| - return video_control->getRange_Brightness(args...); |
| + [this](auto... args) { |
| + return this->video_control_->getRange_Brightness(args...); |
| }, |
| - [video_control](auto... args) { |
| - return video_control->get_Brightness(args...); |
| + [this](auto... args) { |
| + return this->video_control_->get_Brightness(args...); |
| }); |
| photo_capabilities->contrast = RetrieveControlRangeAndCurrent( |
| - [video_control](auto... args) { |
| - return video_control->getRange_Contrast(args...); |
| + [this](auto... args) { |
| + return this->video_control_->getRange_Contrast(args...); |
| }, |
| - [video_control](auto... args) { |
| - return video_control->get_Contrast(args...); |
| + [this](auto... args) { |
| + return this->video_control_->get_Contrast(args...); |
| }); |
| photo_capabilities->saturation = RetrieveControlRangeAndCurrent( |
| - [video_control](auto... args) { |
| - return video_control->getRange_Saturation(args...); |
| + [this](auto... args) { |
| + return this->video_control_->getRange_Saturation(args...); |
| }, |
| - [video_control](auto... args) { |
| - return video_control->get_Saturation(args...); |
| + [this](auto... args) { |
| + return this->video_control_->get_Saturation(args...); |
| }); |
| photo_capabilities->sharpness = RetrieveControlRangeAndCurrent( |
| - [video_control](auto... args) { |
| - return video_control->getRange_Sharpness(args...); |
| + [this](auto... args) { |
| + return this->video_control_->getRange_Sharpness(args...); |
| }, |
| - [video_control](auto... args) { |
| - return video_control->get_Sharpness(args...); |
| + [this](auto... args) { |
| + return this->video_control_->get_Sharpness(args...); |
| }); |
| photo_capabilities->zoom = RetrieveControlRangeAndCurrent( |
| - [camera_control](auto... args) { |
| - return camera_control->getRange_Zoom(args...); |
| + [this](auto... args) { |
| + return this->camera_control_->getRange_Zoom(args...); |
| }, |
| - [camera_control](auto... args) { |
| - return camera_control->get_Zoom(args...); |
| + [this](auto... args) { |
| + return this->camera_control_->get_Zoom(args...); |
| }); |
| photo_capabilities->red_eye_reduction = mojom::RedEyeReduction::NEVER; |
| @@ -620,6 +619,76 @@ void VideoCaptureDeviceWin::GetPhotoCapabilities( |
| callback.Run(std::move(photo_capabilities)); |
| } |
| +void VideoCaptureDeviceWin::SetPhotoOptions( |
| + mojom::PhotoSettingsPtr settings, |
| + VideoCaptureDevice::SetPhotoOptionsCallback callback) { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + |
| + if (!camera_control_ || !video_control_) |
| + return; |
| + |
| + if (settings->has_zoom) { |
| + HRESULT hr = |
| + camera_control_->put_Zoom(settings->zoom, CameraControl_Flags_Manual); |
| + DLOG_IF_FAILED_WITH_HRESULT("Zoom config failed", hr); |
| + } |
| + |
| + if (settings->has_white_balance_mode) { |
| + if (settings->white_balance_mode == mojom::MeteringMode::CONTINUOUS) { |
| + HRESULT hr = |
| + video_control_->put_WhiteBalance(0L, VideoProcAmp_Flags_Auto); |
| + DLOG_IF_FAILED_WITH_HRESULT("Auto white balance config failed", hr); |
| + |
| + white_balance_mode_manual_ = false; |
| + } else { |
| + white_balance_mode_manual_ = true; |
| + } |
| + } |
| + if (white_balance_mode_manual_ && settings->has_color_temperature) { |
| + HRESULT hr = video_control_->put_WhiteBalance(settings->color_temperature, |
| + CameraControl_Flags_Manual); |
| + DLOG_IF_FAILED_WITH_HRESULT("Color temperature config failed", hr); |
| + } |
| + |
| + if (settings->has_exposure_mode) { |
| + if (settings->exposure_mode == mojom::MeteringMode::CONTINUOUS) { |
| + HRESULT hr = camera_control_->put_Exposure(0L, VideoProcAmp_Flags_Auto); |
| + DLOG_IF_FAILED_WITH_HRESULT("Auto exposure config failed", hr); |
| + |
| + exposure_mode_manual_ = false; |
| + } else { |
| + exposure_mode_manual_ = true; |
| + } |
| + } |
| + if (exposure_mode_manual_ && settings->has_exposure_compensation) { |
| + HRESULT hr = camera_control_->put_Exposure(settings->exposure_compensation, |
| + CameraControl_Flags_Manual); |
| + DLOG_IF_FAILED_WITH_HRESULT("Exposure Compensation config failed", hr); |
| + } |
| + |
| + if (settings->has_brightness) { |
| + HRESULT hr = video_control_->put_Brightness(settings->brightness, |
| + CameraControl_Flags_Manual); |
| + DLOG_IF_FAILED_WITH_HRESULT("Brightness config failed", hr); |
| + } |
| + if (settings->has_contrast) { |
| + HRESULT hr = video_control_->put_Contrast(settings->contrast, |
| + CameraControl_Flags_Manual); |
| + DLOG_IF_FAILED_WITH_HRESULT("Contrast config failed", hr); |
| + } |
| + if (settings->has_saturation) { |
| + HRESULT hr = video_control_->put_Saturation(settings->saturation, |
| + CameraControl_Flags_Manual); |
| + DLOG_IF_FAILED_WITH_HRESULT("Saturation config failed", hr); |
| + } |
| + if (settings->has_sharpness) { |
| + HRESULT hr = video_control_->put_Sharpness(settings->sharpness, |
| + CameraControl_Flags_Manual); |
| + DLOG_IF_FAILED_WITH_HRESULT("Sharpness config failed", hr); |
| + } |
| + |
| + callback.Run(true); |
| +} |
| // Implements SinkFilterObserver::SinkFilterObserver. |
| void VideoCaptureDeviceWin::FrameReceived(const uint8_t* buffer, |
| int length, |
| @@ -656,8 +725,8 @@ bool VideoCaptureDeviceWin::CreateCapabilityMap() { |
| return false; |
| // Get interface used for getting the frame rate. |
| - ScopedComPtr<IAMVideoControl> video_control; |
| - hr = capture_filter_.CopyTo(video_control.Receive()); |
| + ScopedComPtr<IAMVideoControl> video_control_; |
|
robliao
2017/05/11 05:14:07
This declaration shadows the instance variable vid
mcasas
2017/05/12 18:52:49
Oops, unintended change.
|
| + hr = capture_filter_.CopyTo(video_control_.Receive()); |
| int count = 0, size = 0; |
| hr = stream_config->GetNumberOfCapabilities(&count, &size); |
| @@ -692,14 +761,14 @@ bool VideoCaptureDeviceWin::CreateCapabilityMap() { |
| // Try to get a better |time_per_frame| from IAMVideoControl. If not, use |
| // the value from VIDEOINFOHEADER. |
| REFERENCE_TIME time_per_frame = h->AvgTimePerFrame; |
| - if (video_control.Get()) { |
| + if (video_control_.Get()) { |
| ScopedCoMem<LONGLONG> max_fps; |
| LONG list_size = 0; |
| const SIZE size = {format.frame_size.width(), |
| format.frame_size.height()}; |
| - hr = video_control->GetFrameRateList(output_capture_pin_.Get(), |
| - stream_index, size, &list_size, |
| - &max_fps); |
| + hr = video_control_->GetFrameRateList(output_capture_pin_.Get(), |
| + stream_index, size, &list_size, |
| + &max_fps); |
| // Can't assume the first value will return the max fps. |
| // Sometimes |list_size| will be > 0, but max_fps will be NULL. Some |
| // drivers may return an HRESULT of S_FALSE which SUCCEEDED() translates |