📄 dshow.cpp
字号:
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 ); p_buf[0] = 0; WideCharToMultiByte( CP_ACP, 0, var.bstrVal, SysStringLen(var.bstrVal), p_buf, i_convert, NULL, NULL ); SysFreeString(var.bstrVal); if( p_listdevices ) p_listdevices->push_back( p_buf ); if( p_devicename && *p_devicename == string(p_buf) ) { /* 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(); 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 ) { for( int i=0; i<piCount; ++i ) { if( SUCCEEDED(pSC->GetStreamCaps(i, &p_mt, pSCC)) ) { int i_current_fourcc = GetFourCCFromMediaType( *p_mt ); if( !i_current_fourcc || (i_fourcc && (i_current_fourcc != i_fourcc)) ) { // incompatible or unrecognized 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; } // Set the sample size and image size. // (Round the image width up to a DWORD boundary.) p_mt->lSampleSize = pVih->bmiHeader.biSizeImage = ((pVih->bmiHeader.biWidth + 3) & ~3) * pVih->bmiHeader.biHeight * (pVih->bmiHeader.biBitCount>>3); // no cropping, use full video input buffer memset(&(pVih->rcSource), 0, sizeof(RECT)); memset(&(pVih->rcTarget), 0, sizeof(RECT)); // select this format as default if( SUCCEEDED( pSC->SetFormat(p_mt) ) ) { msg_Dbg( p_this, "EnumDeviceCaps: input pin video format configured"); // no need to check any more media types i = piCount; } else FreeMediaType( *p_mt ); } else if( p_mt->majortype == MEDIATYPE_Audio && p_mt->formattype == FORMAT_WaveFormatEx ) { AUDIO_STREAM_CONFIG_CAPS *pASCC = reinterpret_cast<AUDIO_STREAM_CONFIG_CAPS*>(pSCC); WAVEFORMATEX *pWfx = reinterpret_cast<WAVEFORMATEX*>(p_mt->pbFormat); if( i_channels ) { if( i_channels % pASCC->ChannelsGranularity || (unsigned int)i_channels < pASCC->MinimumChannels || (unsigned int)i_channels > pASCC->MaximumChannels ) { // required channels not compatible, try next media type FreeMediaType( *p_mt ); CoTaskMemFree( (PVOID)p_mt ); continue; } pWfx->nChannels = i_channels; } if( i_samplespersec ) { if( i_samplespersec % pASCC->BitsPerSampleGranularity || (unsigned int)i_samplespersec < pASCC->MinimumSampleFrequency || (unsigned int)i_samplespersec > pASCC->MaximumSampleFrequency ) { // required sampling rate not compatible, try next media type FreeMediaType( *p_mt ); CoTaskMemFree( (PVOID)p_mt ); continue; } pWfx->nSamplesPerSec = i_samplespersec; } if( i_bitspersample ) { if( i_bitspersample % pASCC->BitsPerSampleGranularity || (unsigned int)i_bitspersample < pASCC->MinimumBitsPerSample || (unsigned int)i_bitspersample > pASCC->MaximumBitsPerSample ) { // required sample size not compatible, try next media type FreeMediaType( *p_mt ); CoTaskMemFree( (PVOID)p_mt ); continue; } pWfx->wBitsPerSample = i_bitspersample; } // select this format as default if( SUCCEEDED( pSC->SetFormat(p_mt) ) ) { msg_Dbg( p_this, "EnumDeviceCaps: input pin default format configured"); // no need to check any more media types i = piCount; } } FreeMediaType( *p_mt ); CoTaskMemFree( (PVOID)p_mt ); } } CoTaskMemFree( (LPVOID)pSCC ); } } pSC->Release(); } /* ** Probe pin for available medias (may be a previously configured one) */ if( FAILED( p_output_pin->EnumMediaTypes( &p_enummt ) ) ) { p_output_pin->Release(); continue; } while( p_enummt->Next( 1, &p_mt, NULL ) == S_OK ) { int i_current_fourcc = GetFourCCFromMediaType( *p_mt ); if( i_current_fourcc && p_mt->majortype == MEDIATYPE_Video && p_mt->formattype == FORMAT_VideoInfo ) { int i_current_width = ((VIDEOINFOHEADER *)p_mt->pbFormat)->bmiHeader.biWidth; int i_current_height = ((VIDEOINFOHEADER *)p_mt->pbFormat)->bmiHeader.biHeight; LONGLONG i_current_atpf = ((VIDEOINFOHEADER *)p_mt->pbFormat)->AvgTimePerFrame; if( i_current_height < 0 ) i_current_height = -i_current_height; msg_Dbg( p_this, "EnumDeviceCaps: input pin " "accepts chroma: %4.4s, width:%i, height:%i, fps:%f", (char *)&i_current_fourcc, i_current_width, i_current_height, (10000000.0f/((float)i_current_atpf)) ); if( ( !i_fourcc || i_fourcc == i_current_fourcc ) && ( !i_width || i_width == i_current_width ) && ( !i_height || i_height == i_current_height ) && ( !i_AvgTimePerFrame || i_AvgTimePerFrame == i_current_atpf ) && mt_count < mt_max ) { /* Pick match */ mt[mt_count++] = *p_mt; } else FreeMediaType( *p_mt ); } else if( i_current_fourcc && p_mt->majortype == MEDIATYPE_Audio && p_mt->formattype == FORMAT_WaveFormatEx) { int i_current_channels = ((WAVEFORMATEX *)p_mt->pbFormat)->nChannels; int i_current_samplespersec = ((WAVEFORMATEX *)p_mt->pbFormat)->nSamplesPerSec; int i_current_bitspersample = ((WAVEFORMATEX *)p_mt->pbFormat)->wBitsPerSample; msg_Dbg( p_this, "EnumDeviceCaps: input pin " "accepts format: %4.4s, channels:%i, " "samples/sec:%i bits/sample:%i", (char *)&i_current_fourcc, i_current_channels, i_current_samplespersec, i_current_bitspersample); if( (!i_channels || i_channels == i_current_channels) && (!i_samplespersec || i_samplespersec == i_current_samplespersec) && (!i_bitspersample || i_bitspersample == i_current_bitspersample) && mt_count < mt_max ) { /* Pick match */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -