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/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 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
311 | 311 |
312 void VideoCaptureDeviceWin::AllocateAndStart( | 312 void VideoCaptureDeviceWin::AllocateAndStart( |
313 const VideoCaptureParams& params, | 313 const VideoCaptureParams& params, |
314 scoped_ptr<VideoCaptureDevice::Client> client) { | 314 scoped_ptr<VideoCaptureDevice::Client> client) { |
315 DCHECK(CalledOnValidThread()); | 315 DCHECK(CalledOnValidThread()); |
316 if (state_ != kIdle) | 316 if (state_ != kIdle) |
317 return; | 317 return; |
318 | 318 |
319 client_ = client.Pass(); | 319 client_ = client.Pass(); |
320 | 320 |
321 // Get the camera capability that best match the requested resolution. | 321 // Get the camera capability that best match the requested format. |
322 const VideoCaptureCapabilityWin& found_capability = | 322 const CapabilityWin found_capability = |
323 capabilities_.GetBestMatchedFormat( | 323 GetBestMatchedCapability(params.requested_format, capabilities_); |
324 params.requested_format.frame_size.width(), | |
325 params.requested_format.frame_size.height(), | |
326 params.requested_format.frame_rate); | |
327 VideoCaptureFormat format = found_capability.supported_format; | 324 VideoCaptureFormat format = found_capability.supported_format; |
328 | 325 |
329 // Reduce the frame rate if the requested frame rate is lower | 326 // Reduce the frame rate if the requested frame rate is lower |
330 // than the capability. | 327 // than the capability. |
331 if (format.frame_rate > params.requested_format.frame_rate) | 328 format.frame_rate = |
332 format.frame_rate = params.requested_format.frame_rate; | 329 std::min(format.frame_rate, params.requested_format.frame_rate); |
333 | 330 |
334 ScopedComPtr<IAMStreamConfig> stream_config; | 331 ScopedComPtr<IAMStreamConfig> stream_config; |
335 HRESULT hr = output_capture_pin_.QueryInterface(stream_config.Receive()); | 332 HRESULT hr = output_capture_pin_.QueryInterface(stream_config.Receive()); |
336 if (FAILED(hr)) { | 333 if (FAILED(hr)) { |
337 SetErrorState("Can't get the Capture format settings"); | 334 SetErrorState("Can't get the Capture format settings"); |
338 return; | 335 return; |
339 } | 336 } |
340 | 337 |
341 int count = 0, size = 0; | 338 int count = 0, size = 0; |
342 hr = stream_config->GetNumberOfCapabilities(&count, &size); | 339 hr = stream_config->GetNumberOfCapabilities(&count, &size); |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
494 | 491 |
495 int count = 0, size = 0; | 492 int count = 0, size = 0; |
496 hr = stream_config->GetNumberOfCapabilities(&count, &size); | 493 hr = stream_config->GetNumberOfCapabilities(&count, &size); |
497 if (FAILED(hr)) { | 494 if (FAILED(hr)) { |
498 DLOG(ERROR) << "Failed to GetNumberOfCapabilities: " | 495 DLOG(ERROR) << "Failed to GetNumberOfCapabilities: " |
499 << logging::SystemErrorCodeToString(hr); | 496 << logging::SystemErrorCodeToString(hr); |
500 return false; | 497 return false; |
501 } | 498 } |
502 | 499 |
503 scoped_ptr<BYTE[]> caps(new BYTE[size]); | 500 scoped_ptr<BYTE[]> caps(new BYTE[size]); |
504 for (int i = 0; i < count; ++i) { | 501 for (int stream_index = 0; stream_index < count; ++stream_index) { |
505 ScopedMediaType media_type; | 502 ScopedMediaType media_type; |
506 hr = stream_config->GetStreamCaps(i, media_type.Receive(), caps.get()); | 503 hr = stream_config->GetStreamCaps( |
| 504 stream_index, media_type.Receive(), caps.get()); |
507 // GetStreamCaps() may return S_FALSE, so don't use FAILED() or SUCCEED() | 505 // GetStreamCaps() may return S_FALSE, so don't use FAILED() or SUCCEED() |
508 // macros here since they'll trigger incorrectly. | 506 // macros here since they'll trigger incorrectly. |
509 if (hr != S_OK) { | 507 if (hr != S_OK) { |
510 DLOG(ERROR) << "Failed to GetStreamCaps: " | 508 DLOG(ERROR) << "Failed to GetStreamCaps: " |
511 << logging::SystemErrorCodeToString(hr); | 509 << logging::SystemErrorCodeToString(hr); |
512 return false; | 510 return false; |
513 } | 511 } |
514 | 512 |
515 if (media_type->majortype == MEDIATYPE_Video && | 513 if (media_type->majortype == MEDIATYPE_Video && |
516 media_type->formattype == FORMAT_VideoInfo) { | 514 media_type->formattype == FORMAT_VideoInfo) { |
517 VideoCaptureCapabilityWin capability(i); | 515 VideoCaptureFormat format; |
518 capability.supported_format.pixel_format = | 516 format.pixel_format = |
519 TranslateMediaSubtypeToPixelFormat(media_type->subtype); | 517 TranslateMediaSubtypeToPixelFormat(media_type->subtype); |
520 if (capability.supported_format.pixel_format == PIXEL_FORMAT_UNKNOWN) | 518 if (format.pixel_format == PIXEL_FORMAT_UNKNOWN) |
521 continue; | 519 continue; |
522 | 520 |
523 VIDEOINFOHEADER* h = | 521 VIDEOINFOHEADER* h = |
524 reinterpret_cast<VIDEOINFOHEADER*>(media_type->pbFormat); | 522 reinterpret_cast<VIDEOINFOHEADER*>(media_type->pbFormat); |
525 capability.supported_format.frame_size.SetSize(h->bmiHeader.biWidth, | 523 format.frame_size.SetSize(h->bmiHeader.biWidth, h->bmiHeader.biHeight); |
526 h->bmiHeader.biHeight); | |
527 | 524 |
528 // Try to get a better |time_per_frame| from IAMVideoControl. If not, use | 525 // Try to get a better |time_per_frame| from IAMVideoControl. If not, use |
529 // the value from VIDEOINFOHEADER. | 526 // the value from VIDEOINFOHEADER. |
530 REFERENCE_TIME time_per_frame = h->AvgTimePerFrame; | 527 REFERENCE_TIME time_per_frame = h->AvgTimePerFrame; |
531 if (video_control) { | 528 if (video_control) { |
532 ScopedCoMem<LONGLONG> max_fps; | 529 ScopedCoMem<LONGLONG> max_fps; |
533 LONG list_size = 0; | 530 LONG list_size = 0; |
534 SIZE size = {capability.supported_format.frame_size.width(), | 531 const SIZE size = {format.frame_size.width(), |
535 capability.supported_format.frame_size.height()}; | 532 format.frame_size.height()}; |
536 | 533 hr = video_control->GetFrameRateList( |
537 // GetFrameRateList doesn't return max frame rate always | 534 output_capture_pin_, stream_index, size, &list_size, &max_fps); |
538 // eg: Logitech Notebook. This may be due to a bug in that API | 535 // Can't assume the first value will return the max fps. |
539 // because GetFrameRateList array is reversed in the above camera. So | 536 // Sometimes |list_size| will be > 0, but max_fps will be NULL. Some |
540 // a util method written. Can't assume the first value will return | |
541 // the max fps. | |
542 hr = video_control->GetFrameRateList(output_capture_pin_, i, size, | |
543 &list_size, &max_fps); | |
544 // Sometimes |list_size| will be > 0, but max_fps will be NULL. Some | |
545 // drivers may return an HRESULT of S_FALSE which SUCCEEDED() translates | 537 // drivers may return an HRESULT of S_FALSE which SUCCEEDED() translates |
546 // into success, so explicitly check S_OK. See http://crbug.com/306237. | 538 // into success, so explicitly check S_OK. See http://crbug.com/306237. |
547 if (hr == S_OK && list_size > 0 && max_fps) { | 539 if (hr == S_OK && list_size > 0 && max_fps) { |
548 time_per_frame = *std::min_element(max_fps.get(), | 540 time_per_frame = *std::min_element(max_fps.get(), |
549 max_fps.get() + list_size); | 541 max_fps.get() + list_size); |
550 } | 542 } |
551 } | 543 } |
552 | 544 |
553 capability.supported_format.frame_rate = | 545 format.frame_rate = |
554 (time_per_frame > 0) | 546 (time_per_frame > 0) |
555 ? (kSecondsToReferenceTime / static_cast<float>(time_per_frame)) | 547 ? (kSecondsToReferenceTime / static_cast<float>(time_per_frame)) |
556 : 0.0; | 548 : 0.0; |
557 | 549 |
558 // DirectShow works at the moment only on integer frame_rate but the | 550 capabilities_.emplace_back(stream_index, format); |
559 // best capability matching class works on rational frame rates. | |
560 capability.frame_rate_numerator = capability.supported_format.frame_rate; | |
561 capability.frame_rate_denominator = 1; | |
562 | |
563 capabilities_.Add(capability); | |
564 } | 551 } |
565 } | 552 } |
566 | 553 |
567 return !capabilities_.empty(); | 554 return !capabilities_.empty(); |
568 } | 555 } |
569 | 556 |
570 // Set the power line frequency removal in |capture_filter_| if available. | 557 // Set the power line frequency removal in |capture_filter_| if available. |
571 void VideoCaptureDeviceWin::SetAntiFlickerInCaptureFilter() { | 558 void VideoCaptureDeviceWin::SetAntiFlickerInCaptureFilter() { |
572 const int power_line_frequency = GetPowerLineFrequencyForLocation(); | 559 const int power_line_frequency = GetPowerLineFrequencyForLocation(); |
573 if (power_line_frequency != kPowerLine50Hz && | 560 if (power_line_frequency != kPowerLine50Hz && |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
653 return E_FAIL; | 640 return E_FAIL; |
654 return S_OK; | 641 return S_OK; |
655 } | 642 } |
656 | 643 |
657 void VideoCaptureDeviceWin::SetErrorState(const std::string& reason) { | 644 void VideoCaptureDeviceWin::SetErrorState(const std::string& reason) { |
658 DCHECK(CalledOnValidThread()); | 645 DCHECK(CalledOnValidThread()); |
659 state_ = kError; | 646 state_ = kError; |
660 client_->OnError(reason); | 647 client_->OnError(reason); |
661 } | 648 } |
662 } // namespace media | 649 } // namespace media |
OLD | NEW |