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