Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(371)

Side by Side Diff: media/capture/video/win/video_capture_device_win.cc

Issue 2214533002: move //media/capture to //device/capture (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « media/capture/video/win/video_capture_device_win.h ('k') | testing/buildbot/gn_isolate_map.pyl » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "media/capture/video/win/video_capture_device_win.h"
6
7 #include <ks.h>
8 #include <ksmedia.h>
9
10 #include <algorithm>
11 #include <list>
12 #include <utility>
13
14 #include "base/macros.h"
15 #include "base/strings/sys_string_conversions.h"
16 #include "base/win/scoped_co_mem.h"
17 #include "base/win/scoped_variant.h"
18 #include "media/base/timestamp_constants.h"
19
20 using base::win::ScopedCoMem;
21 using base::win::ScopedComPtr;
22 using base::win::ScopedVariant;
23
24 namespace media {
25
26 // Check if a Pin matches a category.
27 bool PinMatchesCategory(IPin* pin, REFGUID category) {
28 DCHECK(pin);
29 bool found = false;
30 ScopedComPtr<IKsPropertySet> ks_property;
31 HRESULT hr = ks_property.QueryFrom(pin);
32 if (SUCCEEDED(hr)) {
33 GUID pin_category;
34 DWORD return_value;
35 hr = ks_property->Get(AMPROPSETID_Pin, AMPROPERTY_PIN_CATEGORY, NULL, 0,
36 &pin_category, sizeof(pin_category), &return_value);
37 if (SUCCEEDED(hr) && (return_value == sizeof(pin_category))) {
38 found = (pin_category == category);
39 }
40 }
41 return found;
42 }
43
44 // Check if a Pin's MediaType matches a given |major_type|.
45 bool PinMatchesMajorType(IPin* pin, REFGUID major_type) {
46 DCHECK(pin);
47 AM_MEDIA_TYPE connection_media_type;
48 const HRESULT hr = pin->ConnectionMediaType(&connection_media_type);
49 return SUCCEEDED(hr) && connection_media_type.majortype == major_type;
50 }
51
52 // Finds and creates a DirectShow Video Capture filter matching the |device_id|.
53 // static
54 HRESULT VideoCaptureDeviceWin::GetDeviceFilter(const std::string& device_id,
55 IBaseFilter** filter) {
56 DCHECK(filter);
57
58 ScopedComPtr<ICreateDevEnum> dev_enum;
59 HRESULT hr =
60 dev_enum.CreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC);
61 if (FAILED(hr))
62 return hr;
63
64 ScopedComPtr<IEnumMoniker> enum_moniker;
65 hr = dev_enum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,
66 enum_moniker.Receive(), 0);
67 // CreateClassEnumerator returns S_FALSE on some Windows OS
68 // when no camera exist. Therefore the FAILED macro can't be used.
69 if (hr != S_OK)
70 return hr;
71
72 ScopedComPtr<IBaseFilter> capture_filter;
73 for (ScopedComPtr<IMoniker> moniker;
74 enum_moniker->Next(1, moniker.Receive(), NULL) == S_OK;
75 moniker.Release()) {
76 ScopedComPtr<IPropertyBag> prop_bag;
77 hr = moniker->BindToStorage(0, 0, IID_IPropertyBag, prop_bag.ReceiveVoid());
78 if (FAILED(hr))
79 continue;
80
81 // Find |device_id| via DevicePath, Description or FriendlyName, whichever
82 // is available first and is a VT_BSTR (i.e. String) type.
83 static const wchar_t* kPropertyNames[] = {
84 L"DevicePath", L"Description", L"FriendlyName"};
85
86 ScopedVariant name;
87 for (const auto* property_name : kPropertyNames) {
88 prop_bag->Read(property_name, name.Receive(), 0);
89 if (name.type() == VT_BSTR)
90 break;
91 }
92
93 if (name.type() == VT_BSTR) {
94 const std::string device_path(base::SysWideToUTF8(V_BSTR(name.ptr())));
95 if (device_path.compare(device_id) == 0) {
96 // We have found the requested device
97 hr = moniker->BindToObject(0, 0, IID_IBaseFilter,
98 capture_filter.ReceiveVoid());
99 DLOG_IF(ERROR, FAILED(hr)) << "Failed to bind camera filter: "
100 << logging::SystemErrorCodeToString(hr);
101 break;
102 }
103 }
104 }
105
106 *filter = capture_filter.Detach();
107 if (!*filter && SUCCEEDED(hr))
108 hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
109
110 return hr;
111 }
112
113 // Finds an IPin on an IBaseFilter given the direction, Category and/or Major
114 // Type. If either |category| or |major_type| are GUID_NULL, they are ignored.
115 // static
116 ScopedComPtr<IPin> VideoCaptureDeviceWin::GetPin(IBaseFilter* filter,
117 PIN_DIRECTION pin_dir,
118 REFGUID category,
119 REFGUID major_type) {
120 ScopedComPtr<IPin> pin;
121 ScopedComPtr<IEnumPins> pin_enum;
122 HRESULT hr = filter->EnumPins(pin_enum.Receive());
123 if (pin_enum.get() == NULL)
124 return pin;
125
126 // Get first unconnected pin.
127 hr = pin_enum->Reset(); // set to first pin
128 while ((hr = pin_enum->Next(1, pin.Receive(), NULL)) == S_OK) {
129 PIN_DIRECTION this_pin_dir = static_cast<PIN_DIRECTION>(-1);
130 hr = pin->QueryDirection(&this_pin_dir);
131 if (pin_dir == this_pin_dir) {
132 if ((category == GUID_NULL || PinMatchesCategory(pin.get(), category)) &&
133 (major_type == GUID_NULL ||
134 PinMatchesMajorType(pin.get(), major_type))) {
135 return pin;
136 }
137 }
138 pin.Release();
139 }
140
141 DCHECK(!pin.get());
142 return pin;
143 }
144
145 // static
146 VideoPixelFormat
147 VideoCaptureDeviceWin::TranslateMediaSubtypeToPixelFormat(
148 const GUID& sub_type) {
149 static struct {
150 const GUID& sub_type;
151 VideoPixelFormat format;
152 } const kMediaSubtypeToPixelFormatCorrespondence[] = {
153 {kMediaSubTypeI420, PIXEL_FORMAT_I420},
154 {MEDIASUBTYPE_IYUV, PIXEL_FORMAT_I420},
155 {MEDIASUBTYPE_RGB24, PIXEL_FORMAT_RGB24},
156 {MEDIASUBTYPE_YUY2, PIXEL_FORMAT_YUY2},
157 {MEDIASUBTYPE_MJPG, PIXEL_FORMAT_MJPEG},
158 {MEDIASUBTYPE_UYVY, PIXEL_FORMAT_UYVY},
159 {MEDIASUBTYPE_ARGB32, PIXEL_FORMAT_ARGB},
160 {kMediaSubTypeHDYC, PIXEL_FORMAT_UYVY},
161 };
162 for (const auto& pixel_format : kMediaSubtypeToPixelFormatCorrespondence) {
163 if (sub_type == pixel_format.sub_type)
164 return pixel_format.format;
165 }
166 #ifndef NDEBUG
167 WCHAR guid_str[128];
168 StringFromGUID2(sub_type, guid_str, arraysize(guid_str));
169 DVLOG(2) << "Device (also) supports an unknown media type " << guid_str;
170 #endif
171 return PIXEL_FORMAT_UNKNOWN;
172 }
173
174 void VideoCaptureDeviceWin::ScopedMediaType::Free() {
175 if (!media_type_)
176 return;
177
178 DeleteMediaType(media_type_);
179 media_type_ = NULL;
180 }
181
182 AM_MEDIA_TYPE** VideoCaptureDeviceWin::ScopedMediaType::Receive() {
183 DCHECK(!media_type_);
184 return &media_type_;
185 }
186
187 // Release the format block for a media type.
188 // http://msdn.microsoft.com/en-us/library/dd375432(VS.85).aspx
189 void VideoCaptureDeviceWin::ScopedMediaType::FreeMediaType(AM_MEDIA_TYPE* mt) {
190 if (mt->cbFormat != 0) {
191 CoTaskMemFree(mt->pbFormat);
192 mt->cbFormat = 0;
193 mt->pbFormat = NULL;
194 }
195 if (mt->pUnk != NULL) {
196 NOTREACHED();
197 // pUnk should not be used.
198 mt->pUnk->Release();
199 mt->pUnk = NULL;
200 }
201 }
202
203 // Delete a media type structure that was allocated on the heap.
204 // http://msdn.microsoft.com/en-us/library/dd375432(VS.85).aspx
205 void VideoCaptureDeviceWin::ScopedMediaType::DeleteMediaType(
206 AM_MEDIA_TYPE* mt) {
207 if (mt != NULL) {
208 FreeMediaType(mt);
209 CoTaskMemFree(mt);
210 }
211 }
212
213 VideoCaptureDeviceWin::VideoCaptureDeviceWin(
214 const VideoCaptureDeviceDescriptor& device_descriptor)
215 : device_descriptor_(device_descriptor), state_(kIdle) {
216 // TODO(mcasas): Check that CoInitializeEx() has been called with the
217 // appropriate Apartment model, i.e., Single Threaded.
218 }
219
220 VideoCaptureDeviceWin::~VideoCaptureDeviceWin() {
221 DCHECK(thread_checker_.CalledOnValidThread());
222 if (media_control_.get())
223 media_control_->Stop();
224
225 if (graph_builder_.get()) {
226 if (sink_filter_.get()) {
227 graph_builder_->RemoveFilter(sink_filter_.get());
228 sink_filter_ = NULL;
229 }
230
231 if (capture_filter_.get())
232 graph_builder_->RemoveFilter(capture_filter_.get());
233 }
234
235 if (capture_graph_builder_.get())
236 capture_graph_builder_.Release();
237 }
238
239 bool VideoCaptureDeviceWin::Init() {
240 DCHECK(thread_checker_.CalledOnValidThread());
241 HRESULT hr;
242
243 hr = GetDeviceFilter(device_descriptor_.device_id, capture_filter_.Receive());
244
245 if (!capture_filter_.get()) {
246 DLOG(ERROR) << "Failed to create capture filter: "
247 << logging::SystemErrorCodeToString(hr);
248 return false;
249 }
250
251 output_capture_pin_ = GetPin(capture_filter_.get(), PINDIR_OUTPUT,
252 PIN_CATEGORY_CAPTURE, GUID_NULL);
253 if (!output_capture_pin_.get()) {
254 DLOG(ERROR) << "Failed to get capture output pin";
255 return false;
256 }
257
258 // Create the sink filter used for receiving Captured frames.
259 sink_filter_ = new SinkFilter(this);
260 if (sink_filter_.get() == NULL) {
261 DLOG(ERROR) << "Failed to create sink filter";
262 return false;
263 }
264
265 input_sink_pin_ = sink_filter_->GetPin(0);
266
267 hr = graph_builder_.CreateInstance(CLSID_FilterGraph, NULL,
268 CLSCTX_INPROC_SERVER);
269 if (FAILED(hr)) {
270 DLOG(ERROR) << "Failed to create graph builder: "
271 << logging::SystemErrorCodeToString(hr);
272 return false;
273 }
274
275 hr = capture_graph_builder_.CreateInstance(CLSID_CaptureGraphBuilder2, NULL,
276 CLSCTX_INPROC);
277 if (FAILED(hr)) {
278 DLOG(ERROR) << "Failed to create the Capture Graph Builder: "
279 << logging::SystemErrorCodeToString(hr);
280 return false;
281 }
282
283 hr = capture_graph_builder_->SetFiltergraph(graph_builder_.get());
284 if (FAILED(hr)) {
285 DLOG(ERROR) << "Failed to give graph to capture graph builder: "
286 << logging::SystemErrorCodeToString(hr);
287 return false;
288 }
289
290 hr = graph_builder_.QueryInterface(media_control_.Receive());
291 if (FAILED(hr)) {
292 DLOG(ERROR) << "Failed to create media control builder: "
293 << logging::SystemErrorCodeToString(hr);
294 return false;
295 }
296
297 hr = graph_builder_->AddFilter(capture_filter_.get(), NULL);
298 if (FAILED(hr)) {
299 DLOG(ERROR) << "Failed to add the capture device to the graph: "
300 << logging::SystemErrorCodeToString(hr);
301 return false;
302 }
303
304 hr = graph_builder_->AddFilter(sink_filter_.get(), NULL);
305 if (FAILED(hr)) {
306 DLOG(ERROR) << "Failed to add the sink filter to the graph: "
307 << logging::SystemErrorCodeToString(hr);
308 return false;
309 }
310
311 // The following code builds the upstream portions of the graph,
312 // for example if a capture device uses a Windows Driver Model (WDM)
313 // driver, the graph may require certain filters upstream from the
314 // WDM Video Capture filter, such as a TV Tuner filter or an Analog
315 // Video Crossbar filter. We try using the more prevalent
316 // MEDIATYPE_Interleaved first.
317 base::win::ScopedComPtr<IAMStreamConfig> stream_config;
318
319 hr = capture_graph_builder_->FindInterface(
320 &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Interleaved, capture_filter_.get(),
321 IID_IAMStreamConfig, (void**)stream_config.Receive());
322 if (FAILED(hr)) {
323 hr = capture_graph_builder_->FindInterface(
324 &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, capture_filter_.get(),
325 IID_IAMStreamConfig, (void**)stream_config.Receive());
326 DLOG_IF(ERROR, FAILED(hr)) << "Failed to find CapFilter:IAMStreamConfig: "
327 << logging::SystemErrorCodeToString(hr);
328 }
329
330 return CreateCapabilityMap();
331 }
332
333 void VideoCaptureDeviceWin::AllocateAndStart(
334 const VideoCaptureParams& params,
335 std::unique_ptr<VideoCaptureDevice::Client> client) {
336 DCHECK(thread_checker_.CalledOnValidThread());
337 if (state_ != kIdle)
338 return;
339
340 client_ = std::move(client);
341
342 // Get the camera capability that best match the requested format.
343 const CapabilityWin found_capability =
344 GetBestMatchedCapability(params.requested_format, capabilities_);
345
346 // Reduce the frame rate if the requested frame rate is lower
347 // than the capability.
348 const float frame_rate =
349 std::min(params.requested_format.frame_rate,
350 found_capability.supported_format.frame_rate);
351
352 ScopedComPtr<IAMStreamConfig> stream_config;
353 HRESULT hr = output_capture_pin_.QueryInterface(stream_config.Receive());
354 if (FAILED(hr)) {
355 SetErrorState(FROM_HERE, "Can't get the Capture format settings");
356 return;
357 }
358
359 int count = 0, size = 0;
360 hr = stream_config->GetNumberOfCapabilities(&count, &size);
361 if (FAILED(hr)) {
362 SetErrorState(FROM_HERE, "Failed to GetNumberOfCapabilities");
363 return;
364 }
365
366 std::unique_ptr<BYTE[]> caps(new BYTE[size]);
367 ScopedMediaType media_type;
368
369 // Get the windows capability from the capture device.
370 // GetStreamCaps can return S_FALSE which we consider an error. Therefore the
371 // FAILED macro can't be used.
372 hr = stream_config->GetStreamCaps(found_capability.stream_index,
373 media_type.Receive(), caps.get());
374 if (hr != S_OK) {
375 SetErrorState(FROM_HERE, "Failed to get capture device capabilities");
376 return;
377 }
378 if (media_type->formattype == FORMAT_VideoInfo) {
379 VIDEOINFOHEADER* h =
380 reinterpret_cast<VIDEOINFOHEADER*>(media_type->pbFormat);
381 if (frame_rate > 0)
382 h->AvgTimePerFrame = kSecondsToReferenceTime / frame_rate;
383 }
384 // Set the sink filter to request this format.
385 sink_filter_->SetRequestedMediaFormat(
386 found_capability.supported_format.pixel_format, frame_rate,
387 found_capability.info_header);
388 // Order the capture device to use this format.
389 hr = stream_config->SetFormat(media_type.get());
390 if (FAILED(hr)) {
391 // TODO(grunell): Log the error. http://crbug.com/405016.
392 SetErrorState(FROM_HERE, "Failed to set capture device output format");
393 return;
394 }
395
396 SetAntiFlickerInCaptureFilter(params);
397
398 if (media_type->subtype == kMediaSubTypeHDYC) {
399 // HDYC pixel format, used by the DeckLink capture card, needs an AVI
400 // decompressor filter after source, let |graph_builder_| add it.
401 hr = graph_builder_->Connect(output_capture_pin_.get(),
402 input_sink_pin_.get());
403 } else {
404 hr = graph_builder_->ConnectDirect(output_capture_pin_.get(),
405 input_sink_pin_.get(), NULL);
406 }
407
408 if (FAILED(hr)) {
409 SetErrorState(FROM_HERE, "Failed to connect the Capture graph.");
410 return;
411 }
412
413 hr = media_control_->Pause();
414 if (FAILED(hr)) {
415 SetErrorState(
416 FROM_HERE,
417 "Failed to pause the Capture device, is it already occupied?");
418 return;
419 }
420
421 // Get the format back from the sink filter after the filter have been
422 // connected.
423 capture_format_ = sink_filter_->ResultingFormat();
424
425 // Start capturing.
426 hr = media_control_->Run();
427 if (FAILED(hr)) {
428 SetErrorState(FROM_HERE, "Failed to start the Capture device.");
429 return;
430 }
431
432 state_ = kCapturing;
433 }
434
435 void VideoCaptureDeviceWin::StopAndDeAllocate() {
436 DCHECK(thread_checker_.CalledOnValidThread());
437 if (state_ != kCapturing)
438 return;
439
440 HRESULT hr = media_control_->Stop();
441 if (FAILED(hr)) {
442 SetErrorState(FROM_HERE, "Failed to stop the capture graph.");
443 return;
444 }
445
446 graph_builder_->Disconnect(output_capture_pin_.get());
447 graph_builder_->Disconnect(input_sink_pin_.get());
448
449 client_.reset();
450 state_ = kIdle;
451 }
452
453 // Implements SinkFilterObserver::SinkFilterObserver.
454 void VideoCaptureDeviceWin::FrameReceived(const uint8_t* buffer,
455 int length,
456 base::TimeDelta timestamp) {
457 if (first_ref_time_.is_null())
458 first_ref_time_ = base::TimeTicks::Now();
459
460 // There is a chance that the platform does not provide us with the timestamp,
461 // in which case, we use reference time to calculate a timestamp.
462 if (timestamp == media::kNoTimestamp)
463 timestamp = base::TimeTicks::Now() - first_ref_time_;
464
465 client_->OnIncomingCapturedData(buffer, length, capture_format_, 0,
466 base::TimeTicks::Now(), timestamp);
467 }
468
469 bool VideoCaptureDeviceWin::CreateCapabilityMap() {
470 DCHECK(thread_checker_.CalledOnValidThread());
471 ScopedComPtr<IAMStreamConfig> stream_config;
472 HRESULT hr = output_capture_pin_.QueryInterface(stream_config.Receive());
473 if (FAILED(hr)) {
474 DPLOG(ERROR) << "Failed to get IAMStreamConfig interface from "
475 "capture device: " << logging::SystemErrorCodeToString(hr);
476 return false;
477 }
478
479 // Get interface used for getting the frame rate.
480 ScopedComPtr<IAMVideoControl> video_control;
481 hr = capture_filter_.QueryInterface(video_control.Receive());
482 DLOG_IF(WARNING, FAILED(hr)) << "IAMVideoControl Interface NOT SUPPORTED: "
483 << logging::SystemErrorCodeToString(hr);
484
485 int count = 0, size = 0;
486 hr = stream_config->GetNumberOfCapabilities(&count, &size);
487 if (FAILED(hr)) {
488 DLOG(ERROR) << "Failed to GetNumberOfCapabilities: "
489 << logging::SystemErrorCodeToString(hr);
490 return false;
491 }
492
493 std::unique_ptr<BYTE[]> caps(new BYTE[size]);
494 for (int stream_index = 0; stream_index < count; ++stream_index) {
495 ScopedMediaType media_type;
496 hr = stream_config->GetStreamCaps(stream_index, media_type.Receive(),
497 caps.get());
498 // GetStreamCaps() may return S_FALSE, so don't use FAILED() or SUCCEED()
499 // macros here since they'll trigger incorrectly.
500 if (hr != S_OK) {
501 DLOG(ERROR) << "Failed to GetStreamCaps: "
502 << logging::SystemErrorCodeToString(hr);
503 return false;
504 }
505
506 if (media_type->majortype == MEDIATYPE_Video &&
507 media_type->formattype == FORMAT_VideoInfo) {
508 VideoCaptureFormat format;
509 format.pixel_format =
510 TranslateMediaSubtypeToPixelFormat(media_type->subtype);
511 if (format.pixel_format == PIXEL_FORMAT_UNKNOWN)
512 continue;
513
514 VIDEOINFOHEADER* h =
515 reinterpret_cast<VIDEOINFOHEADER*>(media_type->pbFormat);
516 format.frame_size.SetSize(h->bmiHeader.biWidth, h->bmiHeader.biHeight);
517
518 // Try to get a better |time_per_frame| from IAMVideoControl. If not, use
519 // the value from VIDEOINFOHEADER.
520 REFERENCE_TIME time_per_frame = h->AvgTimePerFrame;
521 if (video_control.get()) {
522 ScopedCoMem<LONGLONG> max_fps;
523 LONG list_size = 0;
524 const SIZE size = {format.frame_size.width(),
525 format.frame_size.height()};
526 hr = video_control->GetFrameRateList(output_capture_pin_.get(),
527 stream_index, size, &list_size,
528 &max_fps);
529 // Can't assume the first value will return the max fps.
530 // Sometimes |list_size| will be > 0, but max_fps will be NULL. Some
531 // drivers may return an HRESULT of S_FALSE which SUCCEEDED() translates
532 // into success, so explicitly check S_OK. See http://crbug.com/306237.
533 if (hr == S_OK && list_size > 0 && max_fps) {
534 time_per_frame =
535 *std::min_element(max_fps.get(), max_fps.get() + list_size);
536 }
537 }
538
539 format.frame_rate =
540 (time_per_frame > 0)
541 ? (kSecondsToReferenceTime / static_cast<float>(time_per_frame))
542 : 0.0;
543
544 capabilities_.emplace_back(stream_index, format, h->bmiHeader);
545 }
546 }
547
548 return !capabilities_.empty();
549 }
550
551 // Set the power line frequency removal in |capture_filter_| if available.
552 void VideoCaptureDeviceWin::SetAntiFlickerInCaptureFilter(
553 const VideoCaptureParams& params) {
554 const PowerLineFrequency power_line_frequency = GetPowerLineFrequency(params);
555 if (power_line_frequency != media::PowerLineFrequency::FREQUENCY_50HZ &&
556 power_line_frequency != media::PowerLineFrequency::FREQUENCY_60HZ) {
557 return;
558 }
559 ScopedComPtr<IKsPropertySet> ks_propset;
560 DWORD type_support = 0;
561 HRESULT hr;
562 if (SUCCEEDED(hr = ks_propset.QueryFrom(capture_filter_.get())) &&
563 SUCCEEDED(hr = ks_propset->QuerySupported(
564 PROPSETID_VIDCAP_VIDEOPROCAMP,
565 KSPROPERTY_VIDEOPROCAMP_POWERLINE_FREQUENCY,
566 &type_support)) &&
567 (type_support & KSPROPERTY_SUPPORT_SET)) {
568 KSPROPERTY_VIDEOPROCAMP_S data = {};
569 data.Property.Set = PROPSETID_VIDCAP_VIDEOPROCAMP;
570 data.Property.Id = KSPROPERTY_VIDEOPROCAMP_POWERLINE_FREQUENCY;
571 data.Property.Flags = KSPROPERTY_TYPE_SET;
572 data.Value =
573 (power_line_frequency == media::PowerLineFrequency::FREQUENCY_50HZ) ? 1
574 : 2;
575 data.Flags = KSPROPERTY_VIDEOPROCAMP_FLAGS_MANUAL;
576 hr = ks_propset->Set(PROPSETID_VIDCAP_VIDEOPROCAMP,
577 KSPROPERTY_VIDEOPROCAMP_POWERLINE_FREQUENCY, &data,
578 sizeof(data), &data, sizeof(data));
579 DLOG_IF(ERROR, FAILED(hr)) << "Anti-flicker setting failed: "
580 << logging::SystemErrorCodeToString(hr);
581 DVLOG_IF(2, SUCCEEDED(hr)) << "Anti-flicker set correctly.";
582 } else {
583 DVLOG(2) << "Anti-flicker setting not supported.";
584 }
585 }
586
587 void VideoCaptureDeviceWin::SetErrorState(
588 const tracked_objects::Location& from_here,
589 const std::string& reason) {
590 DCHECK(thread_checker_.CalledOnValidThread());
591 state_ = kError;
592 client_->OnError(from_here, reason);
593 }
594 } // namespace media
OLDNEW
« no previous file with comments | « media/capture/video/win/video_capture_device_win.h ('k') | testing/buildbot/gn_isolate_map.pyl » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698