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

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

Issue 558503003: Windows video capture: Remove duplicated code from GetDeviceSupportedFormats* (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 3 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
OLDNEW
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/video/capture/win/video_capture_device_win.h" 5 #include "media/video/capture/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 9
10 #include <algorithm> 10 #include <algorithm>
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
216 if (capture_filter_) 216 if (capture_filter_)
217 graph_builder_->RemoveFilter(capture_filter_); 217 graph_builder_->RemoveFilter(capture_filter_);
218 218
219 if (mjpg_filter_) 219 if (mjpg_filter_)
220 graph_builder_->RemoveFilter(mjpg_filter_); 220 graph_builder_->RemoveFilter(mjpg_filter_);
221 } 221 }
222 } 222 }
223 223
224 bool VideoCaptureDeviceWin::Init() { 224 bool VideoCaptureDeviceWin::Init() {
225 DCHECK(CalledOnValidThread()); 225 DCHECK(CalledOnValidThread());
226 HRESULT hr = GetDeviceFilter(device_name_.id(), capture_filter_.Receive()); 226
227 if (!capture_filter_) { 227 if (!VideoCaptureDeviceWin::GetDeviceSupportedFormats(device_name_,
228 DLOG(ERROR) << "Failed to create capture filter: " 228 &capture_filter_,
229 << logging::SystemErrorCodeToString(hr); 229 &output_capture_pin_,
230 &capabilities_)) {
230 return false; 231 return false;
231 } 232 }
232 233
233 output_capture_pin_ =
234 GetPin(capture_filter_, PINDIR_OUTPUT, PIN_CATEGORY_CAPTURE);
235 if (!output_capture_pin_) {
236 DLOG(ERROR) << "Failed to get capture output pin";
237 return false;
238 }
239
240 // Create the sink filter used for receiving Captured frames. 234 // Create the sink filter used for receiving Captured frames.
241 sink_filter_ = new SinkFilter(this); 235 sink_filter_ = new SinkFilter(this);
242 if (sink_filter_ == NULL) { 236 if (sink_filter_ == NULL) {
243 DLOG(ERROR) << "Failed to create send filter"; 237 DLOG(ERROR) << "Failed to create send filter";
244 return false; 238 return false;
245 } 239 }
246 240
247 input_sink_pin_ = sink_filter_->GetPin(0); 241 input_sink_pin_ = sink_filter_->GetPin(0);
248 242
249 hr = graph_builder_.CreateInstance(CLSID_FilterGraph, NULL, 243 HRESULT hr = graph_builder_.CreateInstance(
250 CLSCTX_INPROC_SERVER); 244 CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER);
251 if (FAILED(hr)) { 245 if (FAILED(hr)) {
252 DLOG(ERROR) << "Failed to create graph builder: " 246 DLOG(ERROR) << "Failed to create graph builder: "
253 << logging::SystemErrorCodeToString(hr); 247 << logging::SystemErrorCodeToString(hr);
254 return false; 248 return false;
255 } 249 }
256 250
257 hr = graph_builder_.QueryInterface(media_control_.Receive()); 251 hr = graph_builder_.QueryInterface(media_control_.Receive());
258 if (FAILED(hr)) { 252 if (FAILED(hr)) {
259 DLOG(ERROR) << "Failed to create media control builder: " 253 DLOG(ERROR) << "Failed to create media control builder: "
260 << logging::SystemErrorCodeToString(hr); 254 << logging::SystemErrorCodeToString(hr);
261 return false; 255 return false;
262 } 256 }
263 257
264 hr = graph_builder_->AddFilter(capture_filter_, NULL); 258 hr = graph_builder_->AddFilter(capture_filter_, NULL);
265 if (FAILED(hr)) { 259 if (FAILED(hr)) {
266 DLOG(ERROR) << "Failed to add the capture device to the graph: " 260 DLOG(ERROR) << "Failed to add the capture device to the graph: "
267 << logging::SystemErrorCodeToString(hr); 261 << logging::SystemErrorCodeToString(hr);
268 return false; 262 return false;
269 } 263 }
270 264
271 hr = graph_builder_->AddFilter(sink_filter_, NULL); 265 hr = graph_builder_->AddFilter(sink_filter_, NULL);
272 if (FAILED(hr)) { 266 if (FAILED(hr)) {
273 DLOG(ERROR) << "Failed to add the send filter to the graph: " 267 DLOG(ERROR) << "Failed to add the send filter to the graph: "
274 << logging::SystemErrorCodeToString(hr); 268 << logging::SystemErrorCodeToString(hr);
275 return false; 269 return false;
276 } 270 }
277 271
278 return CreateCapabilityMap(); 272 return true;
279 } 273 }
280 274
281 void VideoCaptureDeviceWin::AllocateAndStart( 275 void VideoCaptureDeviceWin::AllocateAndStart(
282 const VideoCaptureParams& params, 276 const VideoCaptureParams& params,
283 scoped_ptr<VideoCaptureDevice::Client> client) { 277 scoped_ptr<VideoCaptureDevice::Client> client) {
284 DCHECK(CalledOnValidThread()); 278 DCHECK(CalledOnValidThread());
285 if (state_ != kIdle) 279 if (state_ != kIdle)
286 return; 280 return;
287 281
288 client_ = client.Pass(); 282 client_ = client.Pass();
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
432 state_ = kIdle; 426 state_ = kIdle;
433 } 427 }
434 428
435 // Implements SinkFilterObserver::SinkFilterObserver. 429 // Implements SinkFilterObserver::SinkFilterObserver.
436 void VideoCaptureDeviceWin::FrameReceived(const uint8* buffer, 430 void VideoCaptureDeviceWin::FrameReceived(const uint8* buffer,
437 int length) { 431 int length) {
438 client_->OnIncomingCapturedData( 432 client_->OnIncomingCapturedData(
439 buffer, length, capture_format_, 0, base::TimeTicks::Now()); 433 buffer, length, capture_format_, 0, base::TimeTicks::Now());
440 } 434 }
441 435
442 bool VideoCaptureDeviceWin::CreateCapabilityMap() { 436 // static
443 DCHECK(CalledOnValidThread()); 437 bool VideoCaptureDeviceWin::GetDeviceSupportedFormats(
perkj_chrome 2014/09/19 10:04:55 It looks like this is doing much more that gettign
438 const Name& device,
439 ScopedComPtr<IBaseFilter>* capture_filter,
440 ScopedComPtr<IPin>* output_capture_pin,
441 CapabilityList* capabilities) {
442 HRESULT hr = GetDeviceFilter(device.id(), capture_filter->Receive());
443 if (!capture_filter) {
444 DLOG(ERROR) << "Failed to create capture filter: "
445 << logging::SystemErrorCodeToString(hr);
446 return false;
447 }
448
449 *output_capture_pin =
450 GetPin(*capture_filter, PINDIR_OUTPUT, PIN_CATEGORY_CAPTURE);
451 if (!*output_capture_pin) {
452 DLOG(ERROR) << "Failed to get capture output pin";
453 return false;
454 }
455
444 ScopedComPtr<IAMStreamConfig> stream_config; 456 ScopedComPtr<IAMStreamConfig> stream_config;
445 HRESULT hr = output_capture_pin_.QueryInterface(stream_config.Receive()); 457 hr = output_capture_pin->QueryInterface(stream_config.Receive());
446 if (FAILED(hr)) { 458 if (FAILED(hr)) {
447 DPLOG(ERROR) << "Failed to get IAMStreamConfig interface from " 459 DPLOG(ERROR) << "Failed to get IAMStreamConfig interface from "
448 "capture device: " << logging::SystemErrorCodeToString(hr); 460 "capture device: " << logging::SystemErrorCodeToString(hr);
449 return false; 461 return false;
450 } 462 }
451 463
452 // Get interface used for getting the frame rate. 464 // Get interface used for getting the frame rate.
453 ScopedComPtr<IAMVideoControl> video_control; 465 ScopedComPtr<IAMVideoControl> video_control;
454 hr = capture_filter_.QueryInterface(video_control.Receive()); 466 hr = capture_filter->QueryInterface(video_control.Receive());
455 DLOG_IF(WARNING, FAILED(hr)) << "IAMVideoControl Interface NOT SUPPORTED: " 467 DLOG_IF(WARNING, FAILED(hr)) << "IAMVideoControl Interface NOT SUPPORTED: "
456 << logging::SystemErrorCodeToString(hr); 468 << logging::SystemErrorCodeToString(hr);
457 469
458 int count = 0, size = 0; 470 int count = 0, size = 0;
459 hr = stream_config->GetNumberOfCapabilities(&count, &size); 471 hr = stream_config->GetNumberOfCapabilities(&count, &size);
460 if (FAILED(hr)) { 472 if (FAILED(hr)) {
461 DLOG(ERROR) << "Failed to GetNumberOfCapabilities: " 473 DLOG(ERROR) << "Failed to GetNumberOfCapabilities: "
462 << logging::SystemErrorCodeToString(hr); 474 << logging::SystemErrorCodeToString(hr);
463 return false; 475 return false;
464 } 476 }
465 477
466 scoped_ptr<BYTE[]> caps(new BYTE[size]); 478 scoped_ptr<BYTE[]> caps(new BYTE[size]);
467 for (int i = 0; i < count; ++i) { 479 for (int i = 0; i < count; ++i) {
468 ScopedMediaType media_type; 480 ScopedMediaType media_type;
469 hr = stream_config->GetStreamCaps(i, media_type.Receive(), caps.get()); 481 hr = stream_config->GetStreamCaps(i, media_type.Receive(), caps.get());
470 // GetStreamCaps() may return S_FALSE, so don't use FAILED() or SUCCEED() 482 // GetStreamCaps() may return S_FALSE, so don't use FAILED() or SUCCEED()
471 // macros here since they'll trigger incorrectly. 483 // macros here since they'll trigger incorrectly.
472 if (hr != S_OK) { 484 if (hr != S_OK) {
473 DLOG(ERROR) << "Failed to GetStreamCaps: " 485 DLOG(ERROR) << "Failed to GetStreamCaps: "
474 << logging::SystemErrorCodeToString(hr); 486 << logging::SystemErrorCodeToString(hr);
475 return false; 487 continue;
476 } 488 }
477 489
478 if (media_type->majortype == MEDIATYPE_Video && 490 if (media_type->majortype == MEDIATYPE_Video &&
479 media_type->formattype == FORMAT_VideoInfo) { 491 media_type->formattype == FORMAT_VideoInfo) {
480 VideoCaptureCapabilityWin capability(i); 492 VideoCaptureCapabilityWin capability(i);
481 capability.supported_format.pixel_format = 493 capability.supported_format.pixel_format =
482 TranslateMediaSubtypeToPixelFormat(media_type->subtype); 494 TranslateMediaSubtypeToPixelFormat(media_type->subtype);
483 if (capability.supported_format.pixel_format == PIXEL_FORMAT_UNKNOWN) 495 if (capability.supported_format.pixel_format == PIXEL_FORMAT_UNKNOWN)
484 continue; 496 continue;
485 497
486 VIDEOINFOHEADER* h = 498 VIDEOINFOHEADER* h =
487 reinterpret_cast<VIDEOINFOHEADER*>(media_type->pbFormat); 499 reinterpret_cast<VIDEOINFOHEADER*>(media_type->pbFormat);
488 capability.supported_format.frame_size.SetSize(h->bmiHeader.biWidth, 500 capability.supported_format.frame_size.SetSize(h->bmiHeader.biWidth,
489 h->bmiHeader.biHeight); 501 h->bmiHeader.biHeight);
490 502
491 // Try to get a better |time_per_frame| from IAMVideoControl. If not, use 503 // Try to get a better |time_per_frame| from IAMVideoControl. If not, use
492 // the value from VIDEOINFOHEADER. 504 // the value from VIDEOINFOHEADER.
493 REFERENCE_TIME time_per_frame = h->AvgTimePerFrame; 505 REFERENCE_TIME time_per_frame = h->AvgTimePerFrame;
494 if (video_control) { 506 if (video_control) {
495 ScopedCoMem<LONGLONG> max_fps; 507 ScopedCoMem<LONGLONG> max_fps;
496 LONG list_size = 0; 508 LONG list_size = 0;
497 SIZE size = {capability.supported_format.frame_size.width(), 509 SIZE size = {capability.supported_format.frame_size.width(),
498 capability.supported_format.frame_size.height()}; 510 capability.supported_format.frame_size.height()};
499 511
500 // GetFrameRateList doesn't return max frame rate always 512 // GetFrameRateList doesn't return max frame rate always
501 // eg: Logitech Notebook. This may be due to a bug in that API 513 // eg: Logitech Notebook. This may be due to a bug in that API
502 // because GetFrameRateList array is reversed in the above camera. So 514 // because GetFrameRateList array is reversed in the above camera. So
503 // a util method written. Can't assume the first value will return 515 // a util method written. Can't assume the first value will return
504 // the max fps. 516 // the max fps.
505 hr = video_control->GetFrameRateList(output_capture_pin_, i, size, 517 hr = video_control->GetFrameRateList(*output_capture_pin, i, size,
506 &list_size, &max_fps); 518 &list_size, &max_fps);
507 // Sometimes |list_size| will be > 0, but max_fps will be NULL. Some 519 // Sometimes |list_size| will be > 0, but max_fps will be NULL. Some
508 // drivers may return an HRESULT of S_FALSE which SUCCEEDED() translates 520 // drivers may return an HRESULT of S_FALSE which SUCCEEDED() translates
509 // into success, so explicitly check S_OK. See http://crbug.com/306237. 521 // into success, so explicitly check S_OK. See http://crbug.com/306237.
510 if (hr == S_OK && list_size > 0 && max_fps) { 522 if (hr == S_OK && list_size > 0 && max_fps) {
511 time_per_frame = *std::min_element(max_fps.get(), 523 time_per_frame = *std::min_element(max_fps.get(),
512 max_fps.get() + list_size); 524 max_fps.get() + list_size);
513 } 525 }
514 } 526 }
515 527
516 capability.supported_format.frame_rate = 528 capability.supported_format.frame_rate =
517 (time_per_frame > 0) 529 (time_per_frame > 0)
518 ? (kSecondsToReferenceTime / static_cast<float>(time_per_frame)) 530 ? (kSecondsToReferenceTime / static_cast<float>(time_per_frame))
519 : 0.0; 531 : 0.0;
520 532
521 // DirectShow works at the moment only on integer frame_rate but the 533 capabilities->Add(capability);
522 // best capability matching class works on rational frame rates.
523 capability.frame_rate_numerator = capability.supported_format.frame_rate;
524 capability.frame_rate_denominator = 1;
525
526 capabilities_.Add(capability);
527 } 534 }
528 } 535 }
529 536
530 return !capabilities_.empty(); 537 return !capabilities->empty();
531 } 538 }
532 539
533 // Set the power line frequency removal in |capture_filter_| if available. 540 // Set the power line frequency removal in |capture_filter_| if available.
534 void VideoCaptureDeviceWin::SetAntiFlickerInCaptureFilter() { 541 void VideoCaptureDeviceWin::SetAntiFlickerInCaptureFilter() {
535 const int power_line_frequency = GetPowerLineFrequencyForLocation(); 542 const int power_line_frequency = GetPowerLineFrequencyForLocation();
536 if (power_line_frequency != kPowerLine50Hz && 543 if (power_line_frequency != kPowerLine50Hz &&
537 power_line_frequency != kPowerLine60Hz) { 544 power_line_frequency != kPowerLine60Hz) {
538 return; 545 return;
539 } 546 }
540 ScopedComPtr<IKsPropertySet> ks_propset; 547 ScopedComPtr<IKsPropertySet> ks_propset;
(...skipping 19 matching lines...) Expand all
560 DVLOG(2) << "Anti-flicker setting not supported."; 567 DVLOG(2) << "Anti-flicker setting not supported.";
561 } 568 }
562 } 569 }
563 570
564 void VideoCaptureDeviceWin::SetErrorState(const std::string& reason) { 571 void VideoCaptureDeviceWin::SetErrorState(const std::string& reason) {
565 DCHECK(CalledOnValidThread()); 572 DCHECK(CalledOnValidThread());
566 state_ = kError; 573 state_ = kError;
567 client_->OnError(reason); 574 client_->OnError(reason);
568 } 575 }
569 } // namespace media 576 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698