| 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 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 299 return false; | 299 return false; |
| 300 } | 300 } |
| 301 | 301 |
| 302 hr = graph_builder_->AddFilter(sink_filter_, NULL); | 302 hr = graph_builder_->AddFilter(sink_filter_, NULL); |
| 303 if (FAILED(hr)) { | 303 if (FAILED(hr)) { |
| 304 DLOG(ERROR) << "Failed to add the send filter to the graph: " | 304 DLOG(ERROR) << "Failed to add the send filter to the graph: " |
| 305 << logging::SystemErrorCodeToString(hr); | 305 << logging::SystemErrorCodeToString(hr); |
| 306 return false; | 306 return false; |
| 307 } | 307 } |
| 308 | 308 |
| 309 return CreateCapabilityMap( | 309 return CreateCapabilityMap(); |
| 310 output_capture_pin_, capture_filter_, &capabilities_); | |
| 311 } | 310 } |
| 312 | 311 |
| 313 void VideoCaptureDeviceWin::AllocateAndStart( | 312 void VideoCaptureDeviceWin::AllocateAndStart( |
| 314 const VideoCaptureParams& params, | 313 const VideoCaptureParams& params, |
| 315 scoped_ptr<VideoCaptureDevice::Client> client) { | 314 scoped_ptr<VideoCaptureDevice::Client> client) { |
| 316 DCHECK(CalledOnValidThread()); | 315 DCHECK(CalledOnValidThread()); |
| 317 if (state_ != kIdle) | 316 if (state_ != kIdle) |
| 318 return; | 317 return; |
| 319 | 318 |
| 320 client_ = client.Pass(); | 319 client_ = client.Pass(); |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 467 state_ = kIdle; | 466 state_ = kIdle; |
| 468 } | 467 } |
| 469 | 468 |
| 470 // Implements SinkFilterObserver::SinkFilterObserver. | 469 // Implements SinkFilterObserver::SinkFilterObserver. |
| 471 void VideoCaptureDeviceWin::FrameReceived(const uint8* buffer, | 470 void VideoCaptureDeviceWin::FrameReceived(const uint8* buffer, |
| 472 int length) { | 471 int length) { |
| 473 client_->OnIncomingCapturedData( | 472 client_->OnIncomingCapturedData( |
| 474 buffer, length, capture_format_, 0, base::TimeTicks::Now()); | 473 buffer, length, capture_format_, 0, base::TimeTicks::Now()); |
| 475 } | 474 } |
| 476 | 475 |
| 477 bool VideoCaptureDeviceWin::CreateCapabilityMap(IPin* output_capture_pin, | 476 bool VideoCaptureDeviceWin::CreateCapabilityMap() { |
| 478 IBaseFilter* capture_filter, | 477 DCHECK(CalledOnValidThread()); |
| 479 CapabilityList* capabilities) { | |
| 480 ScopedComPtr<IAMStreamConfig> stream_config; | 478 ScopedComPtr<IAMStreamConfig> stream_config; |
| 481 HRESULT hr = output_capture_pin->QueryInterface(stream_config.Receive()); | 479 HRESULT hr = output_capture_pin_.QueryInterface(stream_config.Receive()); |
| 482 if (FAILED(hr) || !stream_config) { | 480 if (FAILED(hr)) { |
| 483 DPLOG(ERROR) << "Failed to get IAMStreamConfig interface from " | 481 DPLOG(ERROR) << "Failed to get IAMStreamConfig interface from " |
| 484 "capture device: " << logging::SystemErrorCodeToString(hr); | 482 "capture device: " << logging::SystemErrorCodeToString(hr); |
| 485 return false; | 483 return false; |
| 486 } | 484 } |
| 487 | 485 |
| 488 // Get interface used for getting the frame rate. | 486 // Get interface used for getting the frame rate. |
| 489 ScopedComPtr<IAMVideoControl> video_control; | 487 ScopedComPtr<IAMVideoControl> video_control; |
| 490 hr = capture_filter->QueryInterface(video_control.Receive()); | 488 hr = capture_filter_.QueryInterface(video_control.Receive()); |
| 491 DLOG_IF(WARNING, FAILED(hr) || !video_control) | 489 DLOG_IF(WARNING, FAILED(hr)) << "IAMVideoControl Interface NOT SUPPORTED: " |
| 492 << "IAMVideoControl Interface NOT SUPPORTED: " | 490 << logging::SystemErrorCodeToString(hr); |
| 493 << logging::SystemErrorCodeToString(hr); | |
| 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 stream_index = 0; stream_index < count; ++stream_index) { | 501 for (int stream_index = 0; stream_index < count; ++stream_index) { |
| 505 ScopedMediaType media_type; | 502 ScopedMediaType media_type; |
| 506 hr = stream_config->GetStreamCaps( | 503 hr = stream_config->GetStreamCaps( |
| 507 stream_index, media_type.Receive(), caps.get()); | 504 stream_index, media_type.Receive(), caps.get()); |
| 508 // 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() |
| 509 // macros here since they'll trigger incorrectly. | 506 // macros here since they'll trigger incorrectly. |
| 510 if (hr != S_OK || !media_type.get()) { | 507 if (hr != S_OK) { |
| 511 DLOG(ERROR) << "Failed to GetStreamCaps: " | 508 DLOG(ERROR) << "Failed to GetStreamCaps: " |
| 512 << logging::SystemErrorCodeToString(hr); | 509 << logging::SystemErrorCodeToString(hr); |
| 513 return false; | 510 return false; |
| 514 } | 511 } |
| 515 | 512 |
| 516 if (media_type->majortype == MEDIATYPE_Video && | 513 if (media_type->majortype == MEDIATYPE_Video && |
| 517 media_type->formattype == FORMAT_VideoInfo) { | 514 media_type->formattype == FORMAT_VideoInfo) { |
| 518 VideoCaptureFormat format; | 515 VideoCaptureFormat format; |
| 519 format.pixel_format = | 516 format.pixel_format = |
| 520 TranslateMediaSubtypeToPixelFormat(media_type->subtype); | 517 TranslateMediaSubtypeToPixelFormat(media_type->subtype); |
| 521 if (format.pixel_format == PIXEL_FORMAT_UNKNOWN) | 518 if (format.pixel_format == PIXEL_FORMAT_UNKNOWN) |
| 522 continue; | 519 continue; |
| 523 | 520 |
| 524 VIDEOINFOHEADER* h = | 521 VIDEOINFOHEADER* h = |
| 525 reinterpret_cast<VIDEOINFOHEADER*>(media_type->pbFormat); | 522 reinterpret_cast<VIDEOINFOHEADER*>(media_type->pbFormat); |
| 526 if (!h) { | |
| 527 DLOG(ERROR) << "VIDEOINFOHEADER is NULL"; | |
| 528 continue; | |
| 529 } | |
| 530 format.frame_size.SetSize(h->bmiHeader.biWidth, h->bmiHeader.biHeight); | 523 format.frame_size.SetSize(h->bmiHeader.biWidth, h->bmiHeader.biHeight); |
| 531 | 524 |
| 532 // 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 |
| 533 // the value from VIDEOINFOHEADER. | 526 // the value from VIDEOINFOHEADER. |
| 534 REFERENCE_TIME time_per_frame = h->AvgTimePerFrame; | 527 REFERENCE_TIME time_per_frame = h->AvgTimePerFrame; |
| 535 if (video_control) { | 528 if (video_control) { |
| 536 ScopedCoMem<LONGLONG> max_fps; | 529 ScopedCoMem<LONGLONG> max_fps; |
| 537 LONG list_size = 0; | 530 LONG list_size = 0; |
| 538 const SIZE size = {format.frame_size.width(), | 531 const SIZE size = {format.frame_size.width(), |
| 539 format.frame_size.height()}; | 532 format.frame_size.height()}; |
| 540 hr = video_control->GetFrameRateList( | 533 hr = video_control->GetFrameRateList( |
| 541 output_capture_pin, stream_index, size, &list_size, &max_fps); | 534 output_capture_pin_, stream_index, size, &list_size, &max_fps); |
| 542 // Can't assume the first value will return the max fps. | 535 // Can't assume the first value will return the max fps. |
| 543 // Sometimes |list_size| will be > 0, but max_fps will be NULL. Some | 536 // Sometimes |list_size| will be > 0, but max_fps will be NULL. Some |
| 544 // drivers may return an HRESULT of S_FALSE which SUCCEEDED() translates | 537 // drivers may return an HRESULT of S_FALSE which SUCCEEDED() translates |
| 545 // 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. |
| 546 if (hr == S_OK && list_size > 0 && max_fps) { | 539 if (hr == S_OK && list_size > 0 && max_fps) { |
| 547 time_per_frame = *std::min_element(max_fps.get(), | 540 time_per_frame = *std::min_element(max_fps.get(), |
| 548 max_fps.get() + list_size); | 541 max_fps.get() + list_size); |
| 549 } | 542 } |
| 550 } | 543 } |
| 551 | 544 |
| 552 format.frame_rate = | 545 format.frame_rate = |
| 553 (time_per_frame > 0) | 546 (time_per_frame > 0) |
| 554 ? (kSecondsToReferenceTime / static_cast<float>(time_per_frame)) | 547 ? (kSecondsToReferenceTime / static_cast<float>(time_per_frame)) |
| 555 : 0.0; | 548 : 0.0; |
| 556 | 549 |
| 557 capabilities->emplace_back(stream_index, format); | 550 capabilities_.emplace_back(stream_index, format); |
| 558 } | 551 } |
| 559 } | 552 } |
| 560 | 553 |
| 561 return !capabilities->empty(); | 554 return !capabilities_.empty(); |
| 562 } | 555 } |
| 563 | 556 |
| 564 // Set the power line frequency removal in |capture_filter_| if available. | 557 // Set the power line frequency removal in |capture_filter_| if available. |
| 565 void VideoCaptureDeviceWin::SetAntiFlickerInCaptureFilter() { | 558 void VideoCaptureDeviceWin::SetAntiFlickerInCaptureFilter() { |
| 566 const int power_line_frequency = GetPowerLineFrequencyForLocation(); | 559 const int power_line_frequency = GetPowerLineFrequencyForLocation(); |
| 567 if (power_line_frequency != kPowerLine50Hz && | 560 if (power_line_frequency != kPowerLine50Hz && |
| 568 power_line_frequency != kPowerLine60Hz) { | 561 power_line_frequency != kPowerLine60Hz) { |
| 569 return; | 562 return; |
| 570 } | 563 } |
| 571 ScopedComPtr<IKsPropertySet> ks_propset; | 564 ScopedComPtr<IKsPropertySet> ks_propset; |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 647 return E_FAIL; | 640 return E_FAIL; |
| 648 return S_OK; | 641 return S_OK; |
| 649 } | 642 } |
| 650 | 643 |
| 651 void VideoCaptureDeviceWin::SetErrorState(const std::string& reason) { | 644 void VideoCaptureDeviceWin::SetErrorState(const std::string& reason) { |
| 652 DCHECK(CalledOnValidThread()); | 645 DCHECK(CalledOnValidThread()); |
| 653 state_ = kError; | 646 state_ = kError; |
| 654 client_->OnError(reason); | 647 client_->OnError(reason); |
| 655 } | 648 } |
| 656 } // namespace media | 649 } // namespace media |
| OLD | NEW |