diff options
-rw-r--r-- | AUTHORS | 1 | ||||
-rw-r--r-- | content/browser/media/media_internals_unittest.cc | 2 | ||||
-rw-r--r-- | media/video/capture/video_capture_device.cc | 2 | ||||
-rw-r--r-- | media/video/capture/video_capture_device.h | 1 | ||||
-rw-r--r-- | media/video/capture/win/video_capture_device_factory_win.cc | 38 | ||||
-rw-r--r-- | media/video/capture/win/video_capture_device_win.cc | 194 | ||||
-rw-r--r-- | media/video/capture/win/video_capture_device_win.h | 11 |
7 files changed, 86 insertions, 163 deletions
@@ -558,6 +558,7 @@ WenSheng He <wensheng.he@samsung.com> Raghu Ram Nagaraj <r.nagaraj@samsung.com> Chanho Park <parkch98@gmail.com> Payal Pandey <payal.pandey@samsung.com> +Kenneth Strickland <ken.strickland@gmail.com> BlackBerry Limited <*@blackberry.com> Code Aurora Forum <*@codeaurora.org> diff --git a/content/browser/media/media_internals_unittest.cc b/content/browser/media/media_internals_unittest.cc index 2d43218..ad43e33 100644 --- a/content/browser/media/media_internals_unittest.cc +++ b/content/browser/media/media_internals_unittest.cc @@ -123,8 +123,6 @@ TEST_F(MediaInternalsVideoCaptureDeviceTest, #elif defined(OS_WIN) m[VideoCaptureDeviceName::MEDIA_FOUNDATION] = "Media Foundation"; m[VideoCaptureDeviceName::DIRECT_SHOW] = "Direct Show"; - m[VideoCaptureDeviceName::DIRECT_SHOW_WDM_CROSSBAR] = - "Direct Show WDM Crossbar"; #elif defined(OS_MACOSX) m[VideoCaptureDeviceName::AVFOUNDATION] = "AV Foundation"; m[VideoCaptureDeviceName::QTKIT] = "QTKit"; diff --git a/media/video/capture/video_capture_device.cc b/media/video/capture/video_capture_device.cc index dabeed3..1eb205a 100644 --- a/media/video/capture/video_capture_device.cc +++ b/media/video/capture/video_capture_device.cc @@ -88,8 +88,6 @@ const char* VideoCaptureDevice::Name::GetCaptureApiTypeString() const { return "Media Foundation"; case DIRECT_SHOW: return "Direct Show"; - case DIRECT_SHOW_WDM_CROSSBAR: - return "Direct Show WDM Crossbar"; default: NOTREACHED() << "Unknown Video Capture API type!"; return "Unknown API"; diff --git a/media/video/capture/video_capture_device.h b/media/video/capture/video_capture_device.h index fe7756f..b243b0ed 100644 --- a/media/video/capture/video_capture_device.h +++ b/media/video/capture/video_capture_device.h @@ -53,7 +53,6 @@ class MEDIA_EXPORT VideoCaptureDevice { enum CaptureApiType { MEDIA_FOUNDATION, DIRECT_SHOW, - DIRECT_SHOW_WDM_CROSSBAR, API_TYPE_UNKNOWN }; #elif defined(OS_MACOSX) diff --git a/media/video/capture/win/video_capture_device_factory_win.cc b/media/video/capture/win/video_capture_device_factory_win.cc index f254445..7f0d665 100644 --- a/media/video/capture/win/video_capture_device_factory_win.cc +++ b/media/video/capture/win/video_capture_device_factory_win.cc @@ -127,10 +127,7 @@ static bool IsDeviceBlackListed(const std::string& name) { return false; } -static void GetDeviceNamesDirectShow( - const CLSID& class_id, - const Name::CaptureApiType capture_api_type, - Names* device_names) { +static void GetDeviceNamesDirectShow(Names* device_names) { DCHECK(device_names); DVLOG(1) << " GetDeviceNamesDirectShow"; @@ -141,7 +138,8 @@ static void GetDeviceNamesDirectShow( return; ScopedComPtr<IEnumMoniker> enum_moniker; - hr = dev_enum->CreateClassEnumerator(class_id, enum_moniker.Receive(), 0); + hr = dev_enum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, + enum_moniker.Receive(), 0); // CreateClassEnumerator returns S_FALSE on some Windows OS // when no camera exist. Therefore the FAILED macro can't be used. if (hr != S_OK) @@ -178,7 +176,7 @@ static void GetDeviceNamesDirectShow( DCHECK_EQ(name.type(), VT_BSTR); id = base::SysWideToUTF8(V_BSTR(name.ptr())); } - device_names->push_back(Name(device_name, id, capture_api_type)); + device_names->push_back(Name(device_name, id, Name::DIRECT_SHOW)); } } @@ -390,7 +388,6 @@ VideoCaptureDeviceFactoryWin::VideoCaptureDeviceFactoryWin() { cmd_line->HasSwitch(switches::kForceMediaFoundationVideoCapture)); } - scoped_ptr<VideoCaptureDevice> VideoCaptureDeviceFactoryWin::Create( const Name& device_name) { DCHECK(thread_checker_.CalledOnValidThread()); @@ -407,8 +404,7 @@ scoped_ptr<VideoCaptureDevice> VideoCaptureDeviceFactoryWin::Create( if (!static_cast<VideoCaptureDeviceMFWin*>(device.get())->Init(source)) device.reset(); } else { - DCHECK(device_name.capture_api_type() == Name::DIRECT_SHOW || - device_name.capture_api_type() == Name::DIRECT_SHOW_WDM_CROSSBAR); + DCHECK(device_name.capture_api_type() == Name::DIRECT_SHOW); device.reset(new VideoCaptureDeviceWin(device_name)); DVLOG(1) << " DirectShow Device: " << device_name.name(); if (!static_cast<VideoCaptureDeviceWin*>(device.get())->Init()) @@ -422,29 +418,7 @@ void VideoCaptureDeviceFactoryWin::GetDeviceNames(Names* device_names) { if (use_media_foundation_) { GetDeviceNamesMediaFoundation(device_names); } else { - GetDeviceNamesDirectShow(CLSID_VideoInputDeviceCategory, - Name::DIRECT_SHOW, - device_names); - - Names crossbar_device_names; - GetDeviceNamesDirectShow(AM_KSCATEGORY_CROSSBAR, - Name::DIRECT_SHOW_WDM_CROSSBAR, - &crossbar_device_names); - // Search in the listed |device_names| to find a device with matching USB ID - // to each device in |crossbar_device_names|. - for (Names::iterator crossbar_device_it = crossbar_device_names.begin(); - crossbar_device_it != crossbar_device_names.end(); - ++crossbar_device_it) { - const std::string& crossbar_device_model = crossbar_device_it->GetModel(); - for (Names::const_iterator device_it = device_names->begin(); - device_it != device_names->end(); ++device_it) { - if (crossbar_device_model == device_it->GetModel()) { - crossbar_device_it->set_capabilities_id(device_it->id()); - device_names->push_back(*crossbar_device_it); - break; - } - } - } + GetDeviceNamesDirectShow(device_names); } } diff --git a/media/video/capture/win/video_capture_device_win.cc b/media/video/capture/win/video_capture_device_win.cc index 3d6cf76..320cba2 100644 --- a/media/video/capture/win/video_capture_device_win.cc +++ b/media/video/capture/win/video_capture_device_win.cc @@ -58,8 +58,8 @@ HRESULT VideoCaptureDeviceWin::GetDeviceFilter(const std::string& device_id, DCHECK(filter); ScopedComPtr<ICreateDevEnum> dev_enum; - HRESULT hr = dev_enum.CreateInstance(CLSID_SystemDeviceEnum, NULL, - CLSCTX_INPROC); + HRESULT hr = + dev_enum.CreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC); if (FAILED(hr)) return hr; @@ -85,13 +85,14 @@ HRESULT VideoCaptureDeviceWin::GetDeviceFilter(const std::string& device_id, // Find the device via DevicePath, Description or FriendlyName, whichever is // available first. static const wchar_t* kPropertyNames[] = { - L"DevicePath", L"Description", L"FriendlyName" - }; + L"DevicePath", L"Description", L"FriendlyName"}; + ScopedVariant name; - for (size_t i = 0; - i < arraysize(kPropertyNames) && name.type() != VT_BSTR; ++i) { - prop_bag->Read(kPropertyNames[i], name.Receive(), 0); + for (const auto* property_name : kPropertyNames) { + if (name.type() != VT_BSTR) + prop_bag->Read(property_name, name.Receive(), 0); } + if (name.type() == VT_BSTR) { std::string device_path(base::SysWideToUTF8(V_BSTR(name.ptr()))); if (device_path.compare(device_id) == 0) { @@ -152,19 +153,18 @@ VideoPixelFormat VideoCaptureDeviceWin::TranslateMediaSubtypeToPixelFormat( const GUID& sub_type; VideoPixelFormat format; } pixel_formats[] = { - { kMediaSubTypeI420, PIXEL_FORMAT_I420 }, - { MEDIASUBTYPE_IYUV, PIXEL_FORMAT_I420 }, - { MEDIASUBTYPE_RGB24, PIXEL_FORMAT_RGB24 }, - { MEDIASUBTYPE_RGB32, PIXEL_FORMAT_RGB32 }, - { MEDIASUBTYPE_YUY2, PIXEL_FORMAT_YUY2 }, - { MEDIASUBTYPE_MJPG, PIXEL_FORMAT_MJPEG }, - { MEDIASUBTYPE_UYVY, PIXEL_FORMAT_UYVY }, - { MEDIASUBTYPE_ARGB32, PIXEL_FORMAT_ARGB }, - { kMediaSubTypeHDYC, PIXEL_FORMAT_UYVY }, + {kMediaSubTypeI420, PIXEL_FORMAT_I420}, + {MEDIASUBTYPE_IYUV, PIXEL_FORMAT_I420}, + {MEDIASUBTYPE_RGB24, PIXEL_FORMAT_RGB24}, + {MEDIASUBTYPE_YUY2, PIXEL_FORMAT_YUY2}, + {MEDIASUBTYPE_MJPG, PIXEL_FORMAT_MJPEG}, + {MEDIASUBTYPE_UYVY, PIXEL_FORMAT_UYVY}, + {MEDIASUBTYPE_ARGB32, PIXEL_FORMAT_ARGB}, + {kMediaSubTypeHDYC, PIXEL_FORMAT_UYVY}, }; - for (const auto& pixel_format : pixel_formats) { - if (sub_type == pixel_format.sub_type) - return pixel_format.format; + for (size_t i = 0; i < arraysize(pixel_formats); ++i) { + if (sub_type == pixel_formats[i].sub_type) + return pixel_formats[i].format; } #ifndef NDEBUG WCHAR guid_str[128]; @@ -214,8 +214,7 @@ void VideoCaptureDeviceWin::ScopedMediaType::DeleteMediaType( } VideoCaptureDeviceWin::VideoCaptureDeviceWin(const Name& device_name) - : device_name_(device_name), - state_(kIdle) { + : device_name_(device_name), state_(kIdle) { DetachFromThread(); } @@ -232,22 +231,19 @@ VideoCaptureDeviceWin::~VideoCaptureDeviceWin() { if (capture_filter_.get()) graph_builder_->RemoveFilter(capture_filter_.get()); - - if (crossbar_filter_.get()) - graph_builder_->RemoveFilter(crossbar_filter_.get()); } + + if (capture_graph_builder_.get()) + capture_graph_builder_.Release(); } bool VideoCaptureDeviceWin::Init() { DCHECK(CalledOnValidThread()); HRESULT hr; - if (device_name_.capture_api_type() == Name::DIRECT_SHOW_WDM_CROSSBAR) { - hr = InstantiateWDMFiltersAndPins(); - } else { - hr = GetDeviceFilter(device_name_.id(), CLSID_VideoInputDeviceCategory, - capture_filter_.Receive()); - } + hr = GetDeviceFilter(device_name_.id(), CLSID_VideoInputDeviceCategory, + capture_filter_.Receive()); + if (!capture_filter_.get()) { DLOG(ERROR) << "Failed to create capture filter: " << logging::SystemErrorCodeToString(hr); @@ -278,6 +274,21 @@ bool VideoCaptureDeviceWin::Init() { return false; } + hr = capture_graph_builder_.CreateInstance(CLSID_CaptureGraphBuilder2, NULL, + CLSCTX_INPROC); + if (FAILED(hr)) { + DLOG(ERROR) << "Failed to create the Capture Graph Builder: " + << logging::SystemErrorCodeToString(hr); + return false; + } + + hr = capture_graph_builder_->SetFiltergraph(graph_builder_.get()); + if (FAILED(hr)) { + DLOG(ERROR) << "Failed to give graph to capture graph builder: " + << logging::SystemErrorCodeToString(hr); + return false; + } + hr = graph_builder_.QueryInterface(media_control_.Receive()); if (FAILED(hr)) { DLOG(ERROR) << "Failed to create media control builder: " @@ -292,12 +303,6 @@ bool VideoCaptureDeviceWin::Init() { return false; } - if (device_name_.capture_api_type() == Name::DIRECT_SHOW_WDM_CROSSBAR && - FAILED(AddWDMCrossbarFilterToGraphAndConnect())) { - DLOG(ERROR) << "Failed to add the WDM Crossbar filter to the graph."; - return false; - } - hr = graph_builder_->AddFilter(sink_filter_.get(), NULL); if (FAILED(hr)) { DLOG(ERROR) << "Failed to add the send filter to the graph: " @@ -305,6 +310,25 @@ bool VideoCaptureDeviceWin::Init() { return false; } + // The following code builds the upstream portions of the graph, + // for example if a capture device uses a Windows Driver Model (WDM) + // driver, the graph may require certain filters upstream from the + // WDM Video Capture filter, such as a TV Tuner filter or an Analog + // Video Crossbar filter. We try using the more prevalent + // MEDIATYPE_Interleaved first. + base::win::ScopedComPtr<IAMStreamConfig> stream_config; + + hr = capture_graph_builder_->FindInterface( + &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Interleaved, capture_filter_.get(), + IID_IAMStreamConfig, (void**)stream_config.Receive()); + if (FAILED(hr)) { + hr = capture_graph_builder_->FindInterface( + &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, capture_filter_.get(), + IID_IAMStreamConfig, (void**)stream_config.Receive()); + DLOG_IF(ERROR, FAILED(hr)) << "Failed to find CapFilter:IAMStreamConfig: " + << logging::SystemErrorCodeToString(hr); + } + return CreateCapabilityMap(); } @@ -346,8 +370,8 @@ void VideoCaptureDeviceWin::AllocateAndStart( // Get the windows capability from the capture device. // GetStreamCaps can return S_FALSE which we consider an error. Therefore the // FAILED macro can't be used. - hr = stream_config->GetStreamCaps( - found_capability.stream_index, media_type.Receive(), caps.get()); + hr = stream_config->GetStreamCaps(found_capability.stream_index, + media_type.Receive(), caps.get()); if (hr != S_OK) { SetErrorState("Failed to get capture device capabilities"); return; @@ -360,8 +384,8 @@ void VideoCaptureDeviceWin::AllocateAndStart( } // Set the sink filter to request this format. sink_filter_->SetRequestedMediaFormat( - found_capability.supported_format.pixel_format, frame_rate, - found_capability.info_header); + found_capability.supported_format.pixel_format, frame_rate, + found_capability.info_header); // Order the capture device to use this format. hr = stream_config->SetFormat(media_type.get()); if (FAILED(hr)) { @@ -389,8 +413,9 @@ void VideoCaptureDeviceWin::AllocateAndStart( hr = media_control_->Pause(); if (FAILED(hr)) { - SetErrorState("Failed to Pause the Capture device. " - "Is it already occupied?"); + SetErrorState( + "Failed to Pause the Capture device. " + "Is it already occupied?"); return; } @@ -422,24 +447,14 @@ void VideoCaptureDeviceWin::StopAndDeAllocate() { graph_builder_->Disconnect(output_capture_pin_.get()); graph_builder_->Disconnect(input_sink_pin_.get()); - if (crossbar_filter_.get()) { - graph_builder_->Disconnect(analog_video_input_pin_.get()); - graph_builder_->Disconnect(crossbar_video_output_pin_.get()); - } - - if (FAILED(hr)) { - SetErrorState("Failed to Stop the Capture device"); - return; - } client_.reset(); state_ = kIdle; } // Implements SinkFilterObserver::SinkFilterObserver. -void VideoCaptureDeviceWin::FrameReceived(const uint8* buffer, - int length) { - client_->OnIncomingCapturedData( - buffer, length, capture_format_, 0, base::TimeTicks::Now()); +void VideoCaptureDeviceWin::FrameReceived(const uint8* buffer, int length) { + client_->OnIncomingCapturedData(buffer, length, capture_format_, 0, + base::TimeTicks::Now()); } bool VideoCaptureDeviceWin::CreateCapabilityMap() { @@ -469,8 +484,8 @@ bool VideoCaptureDeviceWin::CreateCapabilityMap() { scoped_ptr<BYTE[]> caps(new BYTE[size]); for (int stream_index = 0; stream_index < count; ++stream_index) { ScopedMediaType media_type; - hr = stream_config->GetStreamCaps( - stream_index, media_type.Receive(), caps.get()); + hr = stream_config->GetStreamCaps(stream_index, media_type.Receive(), + caps.get()); // GetStreamCaps() may return S_FALSE, so don't use FAILED() or SUCCEED() // macros here since they'll trigger incorrectly. if (hr != S_OK) { @@ -507,8 +522,8 @@ bool VideoCaptureDeviceWin::CreateCapabilityMap() { // drivers may return an HRESULT of S_FALSE which SUCCEEDED() translates // into success, so explicitly check S_OK. See http://crbug.com/306237. if (hr == S_OK && list_size > 0 && max_fps) { - time_per_frame = *std::min_element(max_fps.get(), - max_fps.get() + list_size); + time_per_frame = + *std::min_element(max_fps.get(), max_fps.get() + list_size); } } @@ -547,8 +562,8 @@ void VideoCaptureDeviceWin::SetAntiFlickerInCaptureFilter() { data.Value = (power_line_frequency == kPowerLine50Hz) ? 1 : 2; data.Flags = KSPROPERTY_VIDEOPROCAMP_FLAGS_MANUAL; hr = ks_propset->Set(PROPSETID_VIDCAP_VIDEOPROCAMP, - KSPROPERTY_VIDEOPROCAMP_POWERLINE_FREQUENCY, - &data, sizeof(data), &data, sizeof(data)); + KSPROPERTY_VIDEOPROCAMP_POWERLINE_FREQUENCY, &data, + sizeof(data), &data, sizeof(data)); DLOG_IF(ERROR, FAILED(hr)) << "Anti-flicker setting failed: " << logging::SystemErrorCodeToString(hr); DVLOG_IF(2, SUCCEEDED(hr)) << "Anti-flicker set correctly."; @@ -557,63 +572,6 @@ void VideoCaptureDeviceWin::SetAntiFlickerInCaptureFilter() { } } -// Instantiate a WDM Crossbar Filter and the associated WDM Capture Filter, -// extract the correct pins from each. The necessary pins are device specific -// and usually the first Crossbar output pin, with a name similar to "Video -// Decoder Out" and the first Capture input pin, with a name like "Analog Video -// In". These pins have no special Category. -HRESULT VideoCaptureDeviceWin::InstantiateWDMFiltersAndPins() { - HRESULT hr = VideoCaptureDeviceWin::GetDeviceFilter( - device_name_.id(), - AM_KSCATEGORY_CROSSBAR, - crossbar_filter_.Receive()); - DPLOG_IF(ERROR, FAILED(hr)) << "Failed to bind WDM Crossbar filter"; - if (FAILED(hr) || !crossbar_filter_.get()) - return E_FAIL; - - // Find Crossbar Video Output Pin: This is usually the first output pin. - crossbar_video_output_pin_ = GetPin(crossbar_filter_.get(), PINDIR_OUTPUT, - GUID_NULL, MEDIATYPE_AnalogVideo); - DLOG_IF(ERROR, !crossbar_video_output_pin_.get()) - << "Failed to find Crossbar Video Output pin"; - if (!crossbar_video_output_pin_.get()) - return E_FAIL; - - // Use the WDM capture filter associated to the WDM Crossbar filter. - hr = VideoCaptureDeviceWin::GetDeviceFilter(device_name_.capabilities_id(), - AM_KSCATEGORY_CAPTURE, - capture_filter_.Receive()); - DPLOG_IF(ERROR, FAILED(hr)) << "Failed to bind WDM Capture filter"; - if (FAILED(hr) || !capture_filter_.get()) - return E_FAIL; - - // Find the WDM Capture Filter's Analog Video input Pin: usually the first - // input pin. - analog_video_input_pin_ = GetPin(capture_filter_.get(), PINDIR_INPUT, - GUID_NULL, MEDIATYPE_AnalogVideo); - DLOG_IF(ERROR, !analog_video_input_pin_.get()) - << "Failed to find WDM Video Input"; - if (!analog_video_input_pin_.get()) - return E_FAIL; - return S_OK; -} - -// Add the WDM Crossbar filter to the Graph and connect the pins previously -// found. -HRESULT VideoCaptureDeviceWin::AddWDMCrossbarFilterToGraphAndConnect() { - HRESULT hr = graph_builder_->AddFilter(crossbar_filter_.get(), NULL); - DPLOG_IF(ERROR, FAILED(hr)) << "Failed to add Crossbar filter to the graph"; - if (FAILED(hr)) - return E_FAIL; - - hr = graph_builder_->ConnectDirect(crossbar_video_output_pin_.get(), - analog_video_input_pin_.get(), NULL); - DPLOG_IF(ERROR, FAILED(hr)) << "Failed to plug WDM filters to each other"; - if (FAILED(hr)) - return E_FAIL; - return S_OK; -} - void VideoCaptureDeviceWin::SetErrorState(const std::string& reason) { DCHECK(CalledOnValidThread()); state_ = kError; diff --git a/media/video/capture/win/video_capture_device_win.h b/media/video/capture/win/video_capture_device_win.h index d1b1af4..f758c2c 100644 --- a/media/video/capture/win/video_capture_device_win.h +++ b/media/video/capture/win/video_capture_device_win.h @@ -87,8 +87,6 @@ class VideoCaptureDeviceWin bool CreateCapabilityMap(); void SetAntiFlickerInCaptureFilter(); - HRESULT InstantiateWDMFiltersAndPins(); - HRESULT AddWDMCrossbarFilterToGraphAndConnect(); void SetErrorState(const std::string& reason); Name device_name_; @@ -96,17 +94,14 @@ class VideoCaptureDeviceWin scoped_ptr<VideoCaptureDevice::Client> client_; base::win::ScopedComPtr<IBaseFilter> capture_filter_; + base::win::ScopedComPtr<IGraphBuilder> graph_builder_; + base::win::ScopedComPtr<ICaptureGraphBuilder2> capture_graph_builder_; + base::win::ScopedComPtr<IMediaControl> media_control_; base::win::ScopedComPtr<IPin> input_sink_pin_; base::win::ScopedComPtr<IPin> output_capture_pin_; - // Used for WDM devices as specified by |device_name_|. These devices need a - // WDM Crossbar Filter upstream from the Capture filter. - base::win::ScopedComPtr<IBaseFilter> crossbar_filter_; - base::win::ScopedComPtr<IPin> crossbar_video_output_pin_; - base::win::ScopedComPtr<IPin> analog_video_input_pin_; - scoped_refptr<SinkFilter> sink_filter_; // Map of all capabilities this device support. |