📄 samplecgb.cpp
字号:
return E_FAIL;
}
HRESULT
ISampleCaptureGraphBuilder::BuildMPEG2Segment(CComPtr<IBaseFilter> pFilter)
{
if( ! pFilter )
{
return E_FAIL;
}
HRESULT hr = AddMPEG2Demux( );
if( FAILED( hr ) )
{
return hr;
}
//
// Search a MPEG2 pin on the
// filter
//
CComPtr<IPin> pPin;
hr = FindMPEG2Pin( pFilter, pPin );
if( SUCCEEDED( hr ) )
{
hr = ConnectPin( pPin, pMPEG2Demux_ );
if( FAILED( hr ) )
{
graph_->RemoveFilter( pMPEG2Demux_ );
return E_FAIL;
}
return S_OK;
}
//
// no pins that streams directly MPEG2 stream
//
hr = FindVideoPin( pFilter, pPin );
if( FAILED( hr ) )
{
graph_->RemoveFilter( pMPEG2Demux_ );
return hr; // no video pin
}
hr = RenderToMPEG2Demux( pPin );
if( FAILED( hr ) )
{
graph_->RemoveFilter( pMPEG2Demux_ );
return hr;
}
CComPtr<IPin> pAudioPin;
hr = FindAudioPin( pFilter, pAudioPin );
if( FAILED( hr ) )
{
//
// don't bother with audio
//
return S_OK;
}
//
// try to connect the audio pin directly to encoder
// if this is not possible, then try to find an encoder
// and connect it to the multiplexer
//
ASSERT( pEncoder_ );
hr = ConnectPin( pAudioPin, pEncoder_ );
if( FAILED( hr ) )
{
hr = ConnectAudioPinToMultiplexer( pAudioPin, pMultiplexer_ );
}
return S_OK;
}
HRESULT
ISampleCaptureGraphBuilder::ConnectAudioPinToMultiplexer(
CComPtr<IPin> pPin,
CComPtr<IBaseFilter> pMultiplexer)
{
if( !pPin || !pMultiplexer )
{
return E_INVALIDARG;
}
REGPINMEDIUM pinMedium;
HRESULT hr = GetMedium( pPin, pinMedium );
if( FAILED( hr ) )
{
return hr;
}
CComPtr<IBaseFilter> pEncoder;
CComPtr<IEnumMoniker> pEncoders;
if( FALSE == ::IsEqualGUID( pinMedium.clsMedium, GUID_NULL ) )
{
//
// search through encoders category; identify
// the encoder using the medium
//
hr = GetEncodersByCategory( pEncoders );
if( FAILED( hr ) )
{
return hr;
}
hr = FindEncoder( pEncoders, pinMedium, pEncoder );
if( SUCCEEDED( hr ) )
{
hr = graph_->AddFilter( pEncoder, L"Audio Encoder" );
if( SUCCEEDED( hr ) &&
SUCCEEDED( ConnectPin( pPin, pEncoder ) ) &&
SUCCEEDED( ConnectFilters( pEncoder, pMultiplexer ) )
)
{
return S_OK;
}
}
pEncoders = NULL;
hr = GetEncodersByEnumerating( pPin, pinMedium, pEncoders );
if( FAILED( hr ) )
{
return hr;
}
hr = FindEncoder( pEncoders, pinMedium, pEncoder );
if( SUCCEEDED( hr ) )
{
hr = graph_->AddFilter( pEncoder, L"Audio Encoder" );
if( SUCCEEDED( hr ) &&
SUCCEEDED( ConnectPin( pPin, pEncoder ) ) &&
SUCCEEDED( ConnectFilters( pEncoder, pMultiplexer ) )
)
{
return S_OK;
}
}
return E_FAIL;
}
//
// Search throgh the codec category
//
hr = GetEncodersByCategory( pEncoders );
if( FAILED( hr ) )
{
return hr;
}
CComPtr<IBaseFilter> pFilter;
CComPtr<IMoniker> pMoniker;
ULONG fetched;
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"Audio Encoder" );
if( FAILED( hr ) )
{
continue;
}
hr = ConnectPin( pPin, pFilter );
if( FAILED( hr ) )
{
graph_->RemoveFilter( pFilter );
continue;
}
hr = ConnectFilters( pFilter, pMultiplexer );
if( SUCCEEDED( hr ) )
{
return S_OK;
}
graph_->RemoveFilter( pFilter );
}
return E_FAIL;
}
HRESULT
ISampleCaptureGraphBuilder::CreateVideoPin(
CComPtr<IMpeg2Demultiplexer> pIMpeg2Demux )
{
if( !pIMpeg2Demux )
{
return E_INVALIDARG;
}
AM_MEDIA_TYPE amTypeVideo;
amTypeVideo.majortype = MEDIATYPE_Video;
amTypeVideo.subtype = MEDIASUBTYPE_MPEG2_VIDEO;
amTypeVideo.bFixedSizeSamples = TRUE;
amTypeVideo.bTemporalCompression = 0;
amTypeVideo.formattype = FORMAT_MPEG2Video;
amTypeVideo.pUnk = NULL;
amTypeVideo.cbFormat = sizeof( Mpeg2ProgramVideo );
amTypeVideo.pbFormat = Mpeg2ProgramVideo;
//
// Create video pin
//
CComPtr<IPin> pVideoOutPin;
HRESULT hr = pIMpeg2Demux->CreateOutputPin( &amTypeVideo, L"MpegVideo", &pVideoOutPin );
if( FAILED( hr ) )
{
return hr;
}
CComPtr<IMPEG2StreamIdMap> pIVideoPIDMap;
hr = pVideoOutPin->QueryInterface( &pIVideoPIDMap );
if( FAILED( hr ) )
{
return hr;
}
hr = pIVideoPIDMap->MapStreamId(VidPID_, MPEG2_PROGRAM_ELEMENTARY_STREAM , 0, 0);
if( FAILED( hr ) )
{
return hr;
}
#ifdef USE_VMR
//
// Get the VMR interface and add it to the graph
//
CComPtr<IBaseFilter> pVMR;
hr = pVMR.CoCreateInstance( CLSID_VideoMixingRenderer );
if( FAILED( hr ) )
{
return hr;
}
hr = graph_->AddFilter( pVMR, L"VMR" );
if( FAILED( hr ) )
{
return hr;
}
//
//before rendering the VMR, make the number of streams 1
//
CComPtr<IVMRFilterConfig> pConfig;
hr = pVMR.QueryInterface( &pConfig );
if( FAILED( hr ) )
{
return hr;
}
hr = pConfig->SetNumberOfStreams( 1 );
if( FAILED( hr ) )
{
return hr;
}
//
// Get the input pin from the VMR
//
CComPtr<IPin> pInputPin;
hr = graphBuilder2_->FindPin(
static_cast<IBaseFilter *>( pVMR ),
PINDIR_INPUT,
NULL,
NULL,
TRUE,
0,
&pInputPin
);
if( FAILED( hr ) )
{
hr = pIMpeg2Demux->DeleteOutputPin(L"MpegVideo");
graph_->RemoveFilter( pVMR );
return hr;
}
return graph_->Connect( pVideoOutPin, pInputPin );
#endif
return hr;
}
HRESULT
ISampleCaptureGraphBuilder::CreateAudioPin(
CComPtr<IMpeg2Demultiplexer> pIMpeg2Demux
)
{
if( !pIMpeg2Demux )
{
return E_INVALIDARG;
}
//
// for audio: could be Mpeg1, Mpeg2, AC3: if Mpeg1 failed (connect failed) try Mpeg2.if failed tried AC3
// Audio struct of AC3 can be copied from dev code.
//
AM_MEDIA_TYPE amTypeAudio;
amTypeAudio.majortype = MEDIATYPE_Audio;
amTypeAudio.subtype = MEDIASUBTYPE_MPEG2_AUDIO;
amTypeAudio.bFixedSizeSamples = TRUE;
amTypeAudio.bTemporalCompression = 0;
amTypeAudio.formattype = FORMAT_WaveFormatEx;
amTypeAudio.pUnk = NULL;
amTypeAudio.cbFormat = sizeof( MPEG1AudioFormat );
amTypeAudio.pbFormat = MPEG1AudioFormat;
CComPtr<IPin> pAudioOutPin;
HRESULT hr = pIMpeg2Demux->CreateOutputPin(&amTypeAudio, L"MpegAudio", &pAudioOutPin);
if( FAILED( hr ) )
{
return hr;
}
CComPtr<IMPEG2StreamIdMap> pIAudioPIDMap;
hr = pAudioOutPin->QueryInterface( &pIAudioPIDMap );
if( FAILED( hr ) )
{
return hr;
}
hr = pIAudioPIDMap->MapStreamId(AudPID_, MPEG2_PROGRAM_ELEMENTARY_STREAM, 0, 0);
if( FAILED( hr ) )
{
return hr;
}
/*
//
// Get the audio renderer
//
CComPtr<IBaseFilter> pAudioRenderer;
hr = pAudioRenderer.CoCreateInstance( CLSID_AudioRender );
if( FAILED( hr ) )
{
return hr;
}
hr = graph_->AddFilter( pAudioRenderer, L"Audio renderer" );
if( FAILED( hr ) )
{
return hr;
}
CComPtr<IPin> pInputPin;
hr = graphBuilder2_->FindPin(
static_cast<IBaseFilter *>( pAudioRenderer ),
PINDIR_INPUT,
NULL,
NULL,
TRUE,
0,
&pInputPin
);
hr = graph_->Connect( pAudioOutPin, pInputPin );
if(FAILED( hr ))
{
hr = pIMpeg2Demux->DeleteOutputPin(L"MpegAudio");
graph_->RemoveFilter( pAudioRenderer );
}
*/
return hr;
}
HRESULT ISampleCaptureGraphBuilder::ConfigureMPEG2Demux( CComPtr<IBaseFilter> pFilter)
{
if( ! pFilter )
{
return E_INVALIDARG;
}
//
// Create video pin and render it
//
CComPtr<IMpeg2Demultiplexer> pIMpeg2Demux;
HRESULT hr = pFilter.QueryInterface( &pIMpeg2Demux );
if( FAILED( hr ) )
{
return hr;
}
hr = CreateVideoPin( pIMpeg2Demux );
if( FAILED( hr ) )
{
return hr;
}
hr = CreateAudioPin( pIMpeg2Demux );
if( FAILED( hr ) )
{
return hr;
}
return S_OK;
}
HRESULT
ISampleCaptureGraphBuilder::ConnectFilters(CComPtr<IBaseFilter> pUpFilter, CComPtr<IBaseFilter> pDownFilter)
{
if( !pUpFilter || !pDownFilter )
{
return E_INVALIDARG;
}
// All the need pin & pin enumerator pointers
CComPtr<IEnumPins> pEnumUpFilterPins ,
pEnumDownFilterPins;
CComPtr<IPin> pUpFilterPin ,
pDownFilterPin;
HRESULT hr = S_OK;
// Get the pin enumerators for both the filtera
hr = pUpFilter->EnumPins(&pEnumUpFilterPins);
if( FAILED( hr ) )
{
return hr;
}
hr= pDownFilter->EnumPins(&pEnumDownFilterPins);
if( FAILED( hr ) )
{
return hr;
}
// Loop on every pin on the Upstream Filter
BOOL bConnected = FALSE;
PIN_DIRECTION pinDir;
ULONG nFetched = 0;
while(pUpFilterPin.Release( ), S_OK == pEnumUpFilterPins->Next(1, &pUpFilterPin, &nFetched) )
{
// Make sure that we have the output pin of the upstream filter
hr = pUpFilterPin->QueryDirection( &pinDir );
if( FAILED( hr ) || PINDIR_INPUT == pinDir )
{
continue;
}
//
// I have an output pin; loop on every pin on the Downstream Filter
//
while(pDownFilterPin.Release( ), S_OK == pEnumDownFilterPins->Next(1, &pDownFilterPin, &nFetched) )
{
hr = pDownFilterPin->QueryDirection( &pinDir );
if( FAILED( hr ) || PINDIR_OUTPUT == pinDir )
{
continue;
}
// Try to connect them and exit if u can else loop more until you can
if(SUCCEEDED(graph_->ConnectDirect(pUpFilterPin, pDownFilterPin, NULL)))
{
bConnected = TRUE;
break;
}
}
hr = pEnumDownFilterPins->Reset();
if( FAILED( hr ) )
{
return hr;
}
}
if( !bConnected )
{
return E_FAIL;
}
return S_OK;
}
HRESULT
ISampleCaptureGraphBuilder::ConnectPin(
CComPtr<IPin> pPin,
CComPtr< IBaseFilter > pDownFilter )
{
if( !pPin || !pDownFilter )
{
return E_INVALIDARG;
}
PIN_DIRECTION pinDirection;
HRESULT hr = pPin->QueryDirection( &pinDirection );
if( FAILED( hr ) || PINDIR_INPUT == pinDirection )
{
return E_FAIL;
}
//
// Add the filter to the graph
//
BOOL bConnected = FALSE;
ULONG nFetched = 0;
CComPtr<IPin> pDownFilterPin;
//
// Loop through every input pin from downstream filter
// and try to connect the pin
//
CComPtr< IEnumPins > pEnumDownFilterPins;
hr= pDownFilter->EnumPins( &pEnumDownFilterPins );
if( FAILED( hr ) )
{
return hr;
}
while(pDownFilterPin.Release( ), S_OK == pEnumDownFilterPins->Next(1, &pDownFilterPin, &nFetched) )
{
hr = pDownFilterPin->QueryDirection( &pinDirection );
if( FAILED( hr ) )
{
continue;
}
if( PINDIR_OUTPUT == pinDirection )
{
continue;
}
hr = graph_->ConnectDirect(pPin, pDownFilterPin, NULL);
if(SUCCEEDED(hr))
{
bConnected = TRUE;
break;
}
}
if( !bConnected )
{
graph_->RemoveFilter( pDownFilter );
return E_FAIL;
}
return S_OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -