📄 samplecgb.cpp
字号:
HRESULT
ISampleCaptureGraphBuilder::GetMedium(
CComPtr<IPin> pPin,
REGPINMEDIUM& regPinMedium )
{
if( !pPin )
{
return E_POINTER;
}
CComPtr<IKsPin> pKsPin;
HRESULT hr = pPin.QueryInterface( &pKsPin );
if( FAILED( hr ) )
{
return hr;
}
PKSMULTIPLE_ITEM pmi;
hr = pKsPin->KsQueryMediums( &pmi );
if( FAILED( hr ) )
{
return hr;
}
REGPINMEDIUM *pMedium = (REGPINMEDIUM *)(pmi + 1);
for( ULONG i = 0; i < pmi->Count; i++ )
{
if( !::IsEqualGUID( pMedium->clsMedium, GUID_NULL ) &&
!::IsEqualGUID( pMedium->clsMedium, KSMEDIUMSETID_Standard )
)
{
regPinMedium.clsMedium = pMedium->clsMedium;
regPinMedium.dw1 = pMedium->dw1;
regPinMedium.dw2 = pMedium->dw2;
CoTaskMemFree( pmi );
return S_OK;
}
}
regPinMedium.clsMedium = GUID_NULL;
regPinMedium.dw1 = 0;
regPinMedium.dw2 = 0;
CoTaskMemFree( pmi );
return S_OK;
}
//
// Adds the MPEG2 demux and renders
// the audio and video pin until the end (until the renderers)
//
HRESULT ISampleCaptureGraphBuilder::AddMPEG2Demux( )
{
if( pMPEG2Demux_ )
{
//
// Instead of a MPEG2 demux there is a
// dump filter in which the file will be dumped
//
return S_OK;
}
HRESULT hr = pMPEG2Demux_.CoCreateInstance(CLSID_MPEG2Demultiplexer);
if( FAILED( hr ) )
{
return hr;
}
return graph_->AddFilter( static_cast<IBaseFilter *>( pMPEG2Demux_ ), L"MPEG2 Demux" );
}
HRESULT
ISampleCaptureGraphBuilder::FindVideoPin(
CComPtr<IBaseFilter> pFilter,
CComPtr<IPin>& pPin )
{
if( !pFilter )
{
return E_POINTER;
}
CComPtr<IEnumPins> pEnumPins;
HRESULT hr = pFilter->EnumPins( &pEnumPins );
if( FAILED( hr ) )
{
return hr;
}
CComPtr<IPin> pTempPin;
ULONG fetched;
hr = pEnumPins->Reset( );
while( pTempPin.Release(), S_OK == pEnumPins->Next( 1, &pTempPin, &fetched ) )
{
if( IsVideoPin( pTempPin ) )
{
#ifdef DEBUG
USES_CONVERSION;
PIN_INFO info;
pTempPin->QueryPinInfo( &info );
info.pFilter->Release( );
#endif
pPin = pTempPin;
return S_OK;
}
}
return E_FAIL;
}
BOOL ISampleCaptureGraphBuilder::IsAudioPin( CComPtr<IPin> pPin )
{
if( !pPin )
{
return FALSE; // NULL pointer
}
return HasMediaType( pPin, MEDIATYPE_Audio) ;
}
BOOL ISampleCaptureGraphBuilder::HasMediaType(CComPtr<IPin> pPin, REFGUID majorType )
{
if( !pPin )
{
return FALSE;
}
CComPtr<IEnumMediaTypes> pMediaTypes;
HRESULT hr = pPin->EnumMediaTypes( &pMediaTypes );
if( FAILED( hr ) )
{
return FALSE;
}
hr = pMediaTypes->Reset();
if( FAILED( hr ) )
{
return FALSE;
}
ULONG fetched;
AM_MEDIA_TYPE *mediaType;
while( S_OK == pMediaTypes->Next( 1, &mediaType, &fetched ) )
{
if( ::IsEqualGUID( mediaType->majortype, majorType ) )
{
DeleteMediaType( mediaType );
return TRUE;
}
DeleteMediaType( mediaType );
}
return FALSE;
}
HRESULT
ISampleCaptureGraphBuilder::FindAudioPin(
CComPtr<IBaseFilter> pFilter,
CComPtr<IPin>& pPin )
{
if( !pFilter )
{
return E_POINTER;
}
CComPtr<IEnumPins> pEnumPins;
HRESULT hr = pFilter->EnumPins( &pEnumPins );
if( FAILED( hr ) )
{
return hr;
}
CComPtr<IPin> pTempPin;
ULONG fetched;
hr = pEnumPins->Reset( );
while( pTempPin.Release(), S_OK == pEnumPins->Next( 1, &pTempPin, &fetched ) )
{
if( IsAudioPin( pTempPin ) )
{
#ifdef DEBUG
USES_CONVERSION;
PIN_INFO info;
pTempPin->QueryPinInfo( &info );
info.pFilter->Release( );
#endif
pPin = pTempPin;
return S_OK;
}
}
return E_FAIL;
}
HRESULT ISampleCaptureGraphBuilder::FindEncoder(
CComPtr<IEnumMoniker> pEncoders,
REGPINMEDIUM pinMedium,
CComPtr<IBaseFilter>& pEncoder )
{
if( ! pEncoders )
{
return E_INVALIDARG;
}
if( IsEqualGUID( pinMedium.clsMedium, GUID_NULL ) ||
IsEqualGUID( pinMedium.clsMedium, KSMEDIUMSETID_Standard ) )
{
return E_INVALIDARG;
}
HRESULT hr;
CComPtr<IBaseFilter> pFilter;
CComPtr<IMoniker> pMoniker;
ULONG fetched;
CComPtr<IPin> pPin;
while( pFilter.Release(), pMoniker.Release(),
S_OK == pEncoders->Next( 1, &pMoniker, &fetched ) )
{
hr = pMoniker->BindToObject(
0, 0, IID_IBaseFilter, reinterpret_cast<void **>( &pFilter ) );
if( FAILED( hr ) )
{
continue;
}
hr = FindPin( pFilter, pinMedium, PINDIR_INPUT, TRUE, pPin );
if( SUCCEEDED( hr ) )
{
pEncoder = pFilter;
return hr;
}
}
return E_FAIL;
}
HRESULT
ISampleCaptureGraphBuilder::RenderToMPEG2Demux(
CComPtr<IPin> pPin,
CComPtr<IEnumMoniker> pEncoders)
{
if( !pPin || !pEncoders )
{
return E_INVALIDARG;
}
REGPINMEDIUM pinMedium ;
pinMedium.clsMedium = GUID_NULL;
pinMedium.dw1 = 0;
pinMedium.dw2 = 0;
CComPtr<IBaseFilter> pFilter;
CComPtr<IMoniker> pMoniker;
ULONG fetched;
HRESULT hr;
while( pFilter.Release(), pMoniker.Release(), S_OK == pEncoders->Next( 1, &pMoniker, &fetched ) )
{
hr = pMoniker->BindToObject(
0, 0, IID_IBaseFilter, reinterpret_cast<void **>( &pFilter ) );
if( FAILED( hr ) )
{
continue;
}
hr = graph_->AddFilter( pFilter, L"Encoder" );
if( FAILED( hr ) )
{
continue;
}
hr = ConnectPin( pPin, pFilter );
if( FAILED( hr ) )
{
graph_->RemoveFilter( pFilter );
continue;
}
hr = ConnectEncoderToMPEG2Demux( pFilter, pinMedium );
if( SUCCEEDED( hr ) )
{
pEncoder_ = pFilter;
return S_OK;
}
graph_->RemoveFilter( pFilter );
}
return E_FAIL;
}
//
// Loop through every encoder available on system.
// Look first after the one that has a special medium if
// there is a special one on pPin.
// Otherwise, try to render using ICaptureGrapBuilder2
// and the encoder that matches this will be the chosen one/
// If the encoder is found, then this will be rendered to the
// MPEG2 demux.
//
HRESULT
ISampleCaptureGraphBuilder::RenderToMPEG2Demux(
CComPtr<IPin> pPin,
const REGPINMEDIUM& pinMedium,
CComPtr<IEnumMoniker> pEncoders
)
{
//
// The pin has a special medium,
// there shold be an encoder with the same
// medium
//
CComPtr< IBaseFilter > pEncoder;
HRESULT hr = FindEncoder( pEncoders, pinMedium, pEncoder );
if( FAILED( hr ) )
{
return hr;
}
hr = graph_->AddFilter( pEncoder, L"Encoder" );
if( FAILED( hr ) )
{
return hr;
}
hr = ConnectPin( pPin, pEncoder );
if( FAILED( hr ) )
{
hr = graph_->RemoveFilter( pEncoder );
return hr;
}
//
// the video pin was rendered to the same
// ( hardware? ) encoder with the same mediu
//
hr = ConnectEncoderToMPEG2Demux( pEncoder, pinMedium );
if( FAILED( hr ) )
{
hr = graph_->RemoveFilter( pEncoder );
return hr;
}
pEncoder_ = pEncoder;
return S_OK;
}
HRESULT
ISampleCaptureGraphBuilder::RenderToMPEG2Demux( CComPtr<IPin> pPin )
{
if( !pPin )
{
return E_INVALIDARG;
}
REGPINMEDIUM pinMedium;
HRESULT hr = GetMedium( pPin, pinMedium );
if( FAILED( hr ) )
{
return hr;
}
CComPtr< IEnumMoniker > pEncoders;
if( ::IsEqualGUID( pinMedium.clsMedium, GUID_NULL ) )
{
//
// Search throgh the codec category
//
hr = GetEncodersByCategory( pEncoders );
if( FAILED( hr ) )
{
return hr;
}
hr = RenderToMPEG2Demux( pPin, pEncoders );
if( SUCCEEDED( hr ) )
{
return S_OK;
}
}
else
{
//
// search through encoders category; identify
// the encoder using the medium
//
hr = GetEncodersByCategory( pEncoders );
if( FAILED( hr ) )
{
return hr;
}
hr = RenderToMPEG2Demux( pPin, pinMedium, pEncoders );
if( SUCCEEDED( hr ) )
{
return S_OK;
}
pEncoders = NULL;
hr = GetEncodersByEnumerating( pPin, pinMedium, pEncoders );
if( FAILED( hr ) )
{
return hr;
}
hr = RenderToMPEG2Demux( pPin, pinMedium, pEncoders );
if( FAILED( hr ) )
{
return hr;
}
}
return S_OK;
}
//
// pEncoder - the encoder to be connected using a multiplexer
//
//
HRESULT
ISampleCaptureGraphBuilder::ConnectEncoderToMPEG2Demux(
CComPtr< IBaseFilter > pEncoder,
const REGPINMEDIUM& pinMedium )
{
REGPINMEDIUM regPinMedium ;
regPinMedium.clsMedium = GUID_NULL;
regPinMedium.dw1 = 0;
regPinMedium.dw2 = 0;
//
// try a direct connection between
// codec and MPEG2Demux
//
HRESULT hr = ConnectFilters(
pEncoder,
pMPEG2Demux_ );
if( SUCCEEDED( hr ) )
{
return S_OK;
}
//
// no luck
// maybe I need a multiplexer
//
CComPtr< IEnumMoniker > pMultiplexers;
hr = GetMultiplexersByCategory( pMultiplexers );
if( FAILED( hr ) )
{
return hr;
}
hr = ConnectMultiplexerToMPEG2Demux( pEncoder, pMultiplexers );
if( SUCCEEDED( hr ) )
{
return S_OK;
}
if( FALSE == ::IsEqualGUID( pinMedium.clsMedium, GUID_NULL ) )
{
//
// get the multiplexers using IFilterMapper2
// assuming that the encoder and the multiplexer have the same medium
//
pMultiplexers = NULL;
hr = GetMultiplexersByFilterMapper( pMultiplexers, pinMedium );
if( FAILED( hr ) )
{
return hr;
}
hr = ConnectMultiplexerToMPEG2Demux( pEncoder, pMultiplexers );
if( SUCCEEDED( hr ) )
{
return S_OK;
}
}
return E_FAIL;
}
HRESULT
ISampleCaptureGraphBuilder::GetMultiplexersByCategory( CComPtr<IEnumMoniker>& pMultiplexers )
{
CComPtr<ICreateDevEnum> pDeviceEnum;
HRESULT hr = pDeviceEnum.CoCreateInstance( CLSID_SystemDeviceEnum );
if( FAILED( hr ) )
{
return hr;
}
return pDeviceEnum->CreateClassEnumerator( KSCATEGORY_MULTIPLEXER, &pMultiplexers, 0 );
}
HRESULT
ISampleCaptureGraphBuilder::GetMultiplexersByFilterMapper(
CComPtr<IEnumMoniker>& pMultiplexers,
const REGPINMEDIUM& pinMedium )
{
return E_NOTIMPL;
}
HRESULT
ISampleCaptureGraphBuilder::ConnectMultiplexerToMPEG2Demux(
CComPtr<IBaseFilter> pEncoder,
CComPtr< IEnumMoniker > pMultiplexers )
{
if( !pEncoder || !pMultiplexers )
{
return E_INVALIDARG;
}
CComPtr<IBaseFilter> pFilter;
CComPtr<IMoniker> pMoniker;
ULONG fetched;
HRESULT hr;
while( pFilter.Release(), pMoniker.Release(),
S_OK == pMultiplexers->Next( 1, &pMoniker, &fetched ) )
{
hr = pMoniker->BindToObject(
0, 0, IID_IBaseFilter, reinterpret_cast<void **>( &pFilter ) );
if( FAILED( hr ) )
{
continue;
}
hr = graph_->AddFilter( pFilter, NULL );
if( FAILED( hr ) )
{
continue;
}
//
// connect the encoder to the multiplexer
//
hr = ConnectFilters( pEncoder, pFilter );
if( FAILED( hr ) )
{
graph_->RemoveFilter( pFilter );
continue;
}
//
// connect the multiplexer to the encoder
//
hr = ConnectFilters( pFilter, pMPEG2Demux_ );
if( SUCCEEDED( hr ) )
{
pMultiplexer_ = pFilter;
return S_OK;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -