📄 dshow.cpp
字号:
vlc_value_t val; var_Get( p_this, "dshow-config", &val ); if( val.b_bool ) { ShowDeviceProperties( p_this, p_sys->p_capture_graph_builder2, p_device_filter, b_audio ); } ConfigTuner( p_this, p_sys->p_capture_graph_builder2, p_device_filter ); var_Get( p_this, "dshow-tuner", &val ); if( val.b_bool && dshow_stream.mt.majortype != MEDIATYPE_Stream ) { /* FIXME: we do MEDIATYPE_Stream later so we don't do it twice. */ ShowTunerProperties( p_this, p_sys->p_capture_graph_builder2, p_device_filter, b_audio ); } dshow_stream.mt = p_capture_filter->CustomGetPin()->CustomGetMediaType(); dshow_stream.i_fourcc = GetFourCCFromMediaType( dshow_stream.mt ); if( dshow_stream.i_fourcc ) { if( dshow_stream.mt.majortype == MEDIATYPE_Video ) { dshow_stream.header.video = *(VIDEOINFOHEADER *)dshow_stream.mt.pbFormat; msg_Dbg( p_this, "MEDIATYPE_Video" ); msg_Dbg( p_this, "selected video pin accepts format: %4.4s", (char *)&dshow_stream.i_fourcc); } else if( dshow_stream.mt.majortype == MEDIATYPE_Audio ) { dshow_stream.header.audio = *(WAVEFORMATEX *)dshow_stream.mt.pbFormat; msg_Dbg( p_this, "MEDIATYPE_Audio" ); msg_Dbg( p_this, "selected audio pin accepts format: %4.4s", (char *)&dshow_stream.i_fourcc); } else if( dshow_stream.mt.majortype == MEDIATYPE_Stream ) { msg_Dbg( p_this, "MEDIATYPE_Stream" ); msg_Dbg( p_this, "selected stream pin accepts format: %4.4s", (char *)&dshow_stream.i_fourcc); } else { msg_Dbg( p_this, "unknown stream majortype" ); goto fail; } /* Add directshow elementary stream to our list */ dshow_stream.p_device_filter = p_device_filter; dshow_stream.p_capture_filter = p_capture_filter; p_sys->pp_streams = (dshow_stream_t **)realloc( p_sys->pp_streams, sizeof(dshow_stream_t *) * (p_sys->i_streams + 1) ); p_sys->pp_streams[p_sys->i_streams] = new dshow_stream_t; *p_sys->pp_streams[p_sys->i_streams++] = dshow_stream; return VLC_SUCCESS; } } fail: /* Remove filters from graph */ p_sys->p_graph->RemoveFilter( p_device_filter ); p_sys->p_graph->RemoveFilter( p_capture_filter ); /* Release objects */ p_device_filter->Release(); p_capture_filter->Release(); return VLC_EGENERIC;}static IBaseFilter *FindCaptureDevice( vlc_object_t *p_this, string *p_devicename, list<string> *p_listdevices, bool b_audio ){ IBaseFilter *p_base_filter = NULL; IMoniker *p_moniker = NULL; ULONG i_fetched; HRESULT hr; list<string> devicelist; /* Create the system device enumerator */ ICreateDevEnum *p_dev_enum = NULL; hr = CoCreateInstance( CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC, IID_ICreateDevEnum, (void **)&p_dev_enum ); if( FAILED(hr) ) { msg_Err( p_this, "failed to create the device enumerator (0x%lx)", hr); return NULL; } /* Create an enumerator for the video capture devices */ IEnumMoniker *p_class_enum = NULL; if( !b_audio ) hr = p_dev_enum->CreateClassEnumerator( CLSID_VideoInputDeviceCategory, &p_class_enum, 0 ); else hr = p_dev_enum->CreateClassEnumerator( CLSID_AudioInputDeviceCategory, &p_class_enum, 0 ); p_dev_enum->Release(); if( FAILED(hr) ) { msg_Err( p_this, "failed to create the class enumerator (0x%lx)", hr ); return NULL; } /* If there are no enumerators for the requested type, then * CreateClassEnumerator will succeed, but p_class_enum will be NULL */ if( p_class_enum == NULL ) { msg_Err( p_this, "no capture device was detected" ); return NULL; } /* Enumerate the devices */ /* Note that if the Next() call succeeds but there are no monikers, * it will return S_FALSE (which is not a failure). Therefore, we check * that the return code is S_OK instead of using SUCCEEDED() macro. */ while( p_class_enum->Next( 1, &p_moniker, &i_fetched ) == S_OK ) { /* Getting the property page to get the device name */ IPropertyBag *p_bag; hr = p_moniker->BindToStorage( 0, 0, IID_IPropertyBag, (void **)&p_bag ); if( SUCCEEDED(hr) ) { VARIANT var; var.vt = VT_BSTR; hr = p_bag->Read( L"FriendlyName", &var, NULL ); p_bag->Release(); if( SUCCEEDED(hr) ) { int i_convert = WideCharToMultiByte(CP_ACP, 0, var.bstrVal, SysStringLen(var.bstrVal), NULL, 0, NULL, NULL); char *p_buf = (char *)alloca( i_convert+1 ); p_buf[0] = 0; WideCharToMultiByte( CP_ACP, 0, var.bstrVal, SysStringLen(var.bstrVal), p_buf, i_convert, NULL, NULL ); SysFreeString(var.bstrVal); p_buf[i_convert] = '\0'; string devname = string(p_buf); int dup = 0; /* find out if this name is already used by a previously found device */ list<string>::const_iterator iter = devicelist.begin(); list<string>::const_iterator end = devicelist.end(); while ( iter != end ) { if( 0 == (*iter).compare(0, devname.size(), devname) ) ++dup; ++iter; } if( dup ) { /* we have a duplicate device name, append a sequence number to name to provive a unique list back to the user */ char seq[16]; sprintf(seq, " #%d", dup); devname.append(seq); } devicelist.push_back( devname ); if( p_devicename && *p_devicename == devname ) { /* Bind Moniker to a filter object */ hr = p_moniker->BindToObject( 0, 0, IID_IBaseFilter, (void **)&p_base_filter ); if( FAILED(hr) ) { msg_Err( p_this, "couldn't bind moniker to filter " "object (0x%lx)", hr ); p_moniker->Release(); p_class_enum->Release(); return NULL; } p_moniker->Release(); p_class_enum->Release(); return p_base_filter; } } } p_moniker->Release(); } p_class_enum->Release(); if( p_listdevices ) { devicelist.sort(); *p_listdevices = devicelist; } return NULL;}static size_t EnumDeviceCaps( vlc_object_t *p_this, IBaseFilter *p_filter, int i_fourcc, int i_width, int i_height, int i_channels, int i_samplespersec, int i_bitspersample, AM_MEDIA_TYPE *mt, size_t mt_max ){ IEnumPins *p_enumpins; IPin *p_output_pin; IEnumMediaTypes *p_enummt; size_t mt_count = 0; LONGLONG i_AvgTimePerFrame = 0; float r_fps = var_GetFloat( p_this, "dshow-fps" ); if( r_fps ) i_AvgTimePerFrame = 10000000000LL/(LONGLONG)(r_fps*1000.0f); if( FAILED(p_filter->EnumPins( &p_enumpins )) ) { msg_Dbg( p_this, "EnumDeviceCaps failed: no pin enumeration !"); return 0; } while( S_OK == p_enumpins->Next( 1, &p_output_pin, NULL ) ) { PIN_INFO info; if( S_OK == p_output_pin->QueryPinInfo( &info ) ) { msg_Dbg( p_this, "EnumDeviceCaps: %s pin: %S", info.dir == PINDIR_INPUT ? "input" : "output", info.achName ); if( info.pFilter ) info.pFilter->Release(); } p_output_pin->Release(); } p_enumpins->Reset(); while( !mt_count && p_enumpins->Next( 1, &p_output_pin, NULL ) == S_OK ) { PIN_INFO info; if( S_OK == p_output_pin->QueryPinInfo( &info ) ) { if( info.pFilter ) info.pFilter->Release(); if( info.dir == PINDIR_INPUT ) { p_output_pin->Release(); continue; } msg_Dbg( p_this, "EnumDeviceCaps: trying pin %S", info.achName ); } AM_MEDIA_TYPE *p_mt; /* ** Configure pin with a default compatible media if possible */ IAMStreamConfig *pSC; if( SUCCEEDED(p_output_pin->QueryInterface( IID_IAMStreamConfig, (void **)&pSC )) ) { int piCount, piSize; if( SUCCEEDED(pSC->GetNumberOfCapabilities(&piCount, &piSize)) ) { BYTE *pSCC= (BYTE *)CoTaskMemAlloc(piSize); if( NULL != pSCC ) { int i_priority = -1; for( int i=0; i<piCount; ++i ) { if( SUCCEEDED(pSC->GetStreamCaps(i, &p_mt, pSCC)) ) { int i_current_fourcc = GetFourCCFromMediaType( *p_mt ); int i_current_priority = GetFourCCPriority(i_current_fourcc); if( (i_fourcc && (i_current_fourcc != i_fourcc)) || (i_priority > i_current_priority) ) { // unwanted chroma, try next media type FreeMediaType( *p_mt ); CoTaskMemFree( (PVOID)p_mt ); continue; } if( MEDIATYPE_Video == p_mt->majortype && FORMAT_VideoInfo == p_mt->formattype ) { VIDEO_STREAM_CONFIG_CAPS *pVSCC = reinterpret_cast<VIDEO_STREAM_CONFIG_CAPS*>(pSCC); VIDEOINFOHEADER *pVih = reinterpret_cast<VIDEOINFOHEADER*>(p_mt->pbFormat); if( i_AvgTimePerFrame ) { if( pVSCC->MinFrameInterval > i_AvgTimePerFrame || i_AvgTimePerFrame > pVSCC->MaxFrameInterval ) { // required frame rate not compatible, try next media type FreeMediaType( *p_mt ); CoTaskMemFree( (PVOID)p_mt ); continue; } pVih->AvgTimePerFrame = i_AvgTimePerFrame; } if( i_width ) { if( i_width % pVSCC->OutputGranularityX || pVSCC->MinOutputSize.cx > i_width || i_width > pVSCC->MaxOutputSize.cx ) { // required width not compatible, try next media type FreeMediaType( *p_mt ); CoTaskMemFree( (PVOID)p_mt ); continue; } pVih->bmiHeader.biWidth = i_width; } if( i_height ) { if( i_height % pVSCC->OutputGranularityY || pVSCC->MinOutputSize.cy > i_height || i_height > pVSCC->MaxOutputSize.cy ) { // required height not compatible, try next media type FreeMediaType( *p_mt ); CoTaskMemFree( (PVOID)p_mt ); continue; } pVih->bmiHeader.biHeight = i_height;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -