www.pudn.com > vc++shipinkaifa.rar > CMPEG1Builder.cpp, change:2004-01-08,size:6852b


// 
// CMPEG1Builder.cpp 
// 
 
#include <streams.h> 
#include "FltGuids.h" 
#include "CMPEG1Builder.h" 
 
///////////////////////////////////////////////////////////////////////////// 
CMPEG1Builder::CMPEG1Builder(LPUNKNOWN pUnk, HRESULT *phr) : 
CUnknown(NAME("MPEG1 Builder"), pUnk) 
{ 
} 
 
CMPEG1Builder::~CMPEG1Builder() 
{ 
} 
 
// 
// Expose our own interface 
STDMETHODIMP CMPEG1Builder::NonDelegatingQueryInterface(REFIID riid, void ** ppv) 
{ 
	CheckPointer(ppv, E_POINTER); 
 
	if (riid == IID_IMPEG1Builder)  
	{ 
		return GetInterface((IMPEG1Builder *) this, ppv); 
	} 
	else if (riid == IID_IDistributorNotify) 
	{ 
		return GetInterface((IDistributorNotify *) this, ppv); 
	} 
	else 
	{ 
		return CUnknown::NonDelegatingQueryInterface(riid, ppv); 
	} 
} 
 
// --- IMPEG1Builder methods --- 
STDMETHODIMP CMPEG1Builder::IsMPEG1File(const char * inFilePath) 
{ 
	IGraphBuilder * pBuilder = RetrieveGraphBuilder(); 
 
	// Create a file source filter 
	IBaseFilter * pSource = NULL; 
	WCHAR  wcFilePath[MAX_PATH]; 
	MultiByteToWideChar(CP_ACP, 0, inFilePath, -1, wcFilePath, MAX_PATH); 
	pBuilder->AddSourceFilter(wcFilePath, L"Source", &pSource); 
	pSource->Release(); 
 
	// Create microsoft MPEG-1 Stream Splitter 
	IBaseFilter * pSplitter = NULL; 
	CoCreateInstance(CLSID_MPEG1Splitter , NULL, CLSCTX_INPROC_SERVER, 
		IID_IBaseFilter, (void **)&pSplitter); 
	pBuilder->AddFilter(pSplitter, L"MPEG-1 Splitter"); 
	pSplitter->Release(); 
 
	// Try to connect them... 
	IPin * pOut = GetPinByDirection(pSource, PINDIR_OUTPUT); 
	IPin * pIn  = GetPinByDirection(pSplitter, PINDIR_INPUT); 
	HRESULT hr  = pBuilder->ConnectDirect(pOut, pIn, NULL); 
	 
	pBuilder->RemoveFilter(pSplitter); 
	pBuilder->RemoveFilter(pSource); 
 
	return SUCCEEDED(hr) ? S_OK : S_FALSE; 
} 
 
STDMETHODIMP CMPEG1Builder::RenderMPEG1File(const char * inFilePath) 
{ 
	IGraphBuilder * pBuilder = RetrieveGraphBuilder(); 
 
	// Create a file source filter 
	IBaseFilter * pSource = NULL; 
	WCHAR  wcFilePath[MAX_PATH]; 
	MultiByteToWideChar(CP_ACP, 0, inFilePath, -1, wcFilePath, MAX_PATH); 
	pBuilder->AddSourceFilter(wcFilePath, L"Source", &pSource); 
	pSource->Release(); 
 
	// Create microsoft MPEG-1 Stream Splitter 
	IBaseFilter * pSplitter = NULL; 
	CoCreateInstance(CLSID_MPEG1Splitter , NULL, CLSCTX_INPROC_SERVER, 
		IID_IBaseFilter, (void **)&pSplitter); 
	pBuilder->AddFilter(pSplitter, L"MPEG-1 Splitter"); 
	pSplitter->Release(); 
 
	// Create microsoft MPEG-1 Video Decoder 
	IBaseFilter * pVideoDec = NULL; 
	CoCreateInstance(CLSID_CMpegVideoCodec, NULL, CLSCTX_INPROC_SERVER, 
		IID_IBaseFilter, (void **)&pVideoDec); 
	pBuilder->AddFilter(pVideoDec, L"MPEG-1 Video Decoder"); 
	pVideoDec->Release(); 
 
	// Create microsoft MPEG-1 Audio Dedocer 
	IBaseFilter * pAudioDec = NULL; 
	CoCreateInstance(CLSID_CMpegAudioCodec, NULL, CLSCTX_INPROC_SERVER, 
		IID_IBaseFilter, (void **)&pAudioDec); 
	pBuilder->AddFilter(pAudioDec, L"MPEG-1 Audio Decoder"); 
	pAudioDec->Release(); 
 
	// Connect filters... 
	IPin * pOut = GetPinByDirection(pSource, PINDIR_OUTPUT); 
	IPin * pIn  = GetPinByDirection(pSplitter, PINDIR_INPUT); 
	HRESULT hr  = pBuilder->ConnectDirect(pOut, pIn, NULL); 
	pOut = GetPinByName(pSplitter, "Video"); 
	pIn  = GetPinByDirection(pVideoDec, PINDIR_INPUT); 
	if (pOut && pIn) 
	{ 
		hr = pBuilder->ConnectDirect(pOut, pIn, NULL); 
	} 
	pOut = GetPinByName(pSplitter, "Audio"); 
	pIn  = GetPinByDirection(pAudioDec, PINDIR_INPUT); 
	if (pOut && pIn) 
	{ 
		hr = pBuilder->ConnectDirect(pOut, pIn, NULL); 
	} 
 
	// Auto-build the rest of the filter graph 
	IPin * connected = NULL; 
	pIn = GetPinByDirection(pVideoDec, PINDIR_INPUT); 
	hr  = pIn->ConnectedTo(&connected); 
	if (SUCCEEDED(hr) && connected) 
	{ 
		connected->Release(); 
		hr = pBuilder->Render(GetPinByDirection(pVideoDec, PINDIR_OUTPUT)); 
	} 
	else 
	{ 
		pBuilder->RemoveFilter(pVideoDec); 
	} 
 
	pIn = GetPinByDirection(pAudioDec, PINDIR_INPUT); 
	hr  = pIn->ConnectedTo(&connected); 
	if (SUCCEEDED(hr) && connected) 
	{ 
		connected->Release(); 
		hr = pBuilder->Render(GetPinByDirection(pAudioDec, PINDIR_OUTPUT)); 
	} 
	else 
	{ 
		pBuilder->RemoveFilter(pAudioDec); 
	} 
 
	return hr; 
} 
 
// Utilities 
IGraphBuilder * CMPEG1Builder::RetrieveGraphBuilder(void) 
{ 
	IGraphBuilder * pBuilder = NULL; 
	QueryInterface(IID_IGraphBuilder, (void**)&pBuilder); 
	pBuilder->Release(); 
	return pBuilder; 
} 
 
IPin * CMPEG1Builder::GetPinByDirection(IBaseFilter * inFilter, PIN_DIRECTION inDirection) 
{ 
	IPin * foundPin = NULL; 
	if (inFilter) 
	{ 
		IEnumPins * pinEnum = 0; 
		if (SUCCEEDED(inFilter->EnumPins(&pinEnum))) 
		{ 
			pinEnum->Reset(); 
 
			IPin * pin = 0; 
			ULONG fetchCount = 0; 
			while (!foundPin && SUCCEEDED(pinEnum->Next(1, &pin, &fetchCount)) && fetchCount) 
			{ 
				if (pin) 
				{ 
					PIN_INFO pinInfo; 
					if (SUCCEEDED(pin->QueryPinInfo(&pinInfo))) 
					{ 
						pinInfo.pFilter->Release(); 
						if (pinInfo.dir == inDirection) 
						{ 
							foundPin = pin; 
						} 
					} 
					// If found pin, we keep pin reference. 
					// If not, we release it here. 
					if (!foundPin) 
					{ 
						pin->Release(); 
					} 
					pin = 0; 
				} 
			} 
			pinEnum->Release(); 
		} 
	} 
 
	// We don't keep outstanding reference count 
	if (foundPin) 
	{ 
		foundPin->Release(); 
	} 
	return foundPin; 
} 
 
IPin * CMPEG1Builder::GetPinByName(IBaseFilter * inFilter, const char * inPinName, BOOL inInput) 
{ 
	PIN_DIRECTION pinType = inInput ? PINDIR_INPUT : PINDIR_OUTPUT; 
	IPin * foundPin = 0; 
	if (inFilter) 
	{ 
		IEnumPins * pinEnum = 0; 
		if (SUCCEEDED(inFilter->EnumPins(&pinEnum))) 
		{ 
			pinEnum->Reset(); 
			IPin * pin = 0; 
			ULONG fetchCount = 0; 
			while (!foundPin && SUCCEEDED(pinEnum->Next(1, &pin, &fetchCount)) && fetchCount) 
			{ 
				if (pin) 
				{ 
					PIN_INFO pinInfo; 
					if (SUCCEEDED(pin->QueryPinInfo(&pinInfo))) 
					{ 
						if (pinInfo.dir == pinType) 
						{ 
							char pinName[128]; 
							::WideCharToMultiByte(CP_ACP, 0, pinInfo.achName, -1, 
								pinName, 128, NULL, NULL); 
							if (::strstr(pinName, inPinName)) 
							{ 
								foundPin = pin; 
							} 
						} 
						pinInfo.pFilter->Release(); 
 
					} 
					if (!foundPin) 
					{ 
						pin->Release(); 
					} 
					pin = 0; 
				} 
			} 
			pinEnum->Release(); 
		} 
	} 
 
	// We don't keep outstanding reference count 
	if (foundPin) 
	{ 
		foundPin->Release(); 
	} 
	return foundPin; 
} 
 
// --- IDistributorNotify methods --- 
STDMETHODIMP CMPEG1Builder::NotifyGraphChange(void) 
{ 
	return S_OK; 
} 
 
STDMETHODIMP CMPEG1Builder::Pause(void) 
{ 
	return S_OK; 
} 
 
STDMETHODIMP CMPEG1Builder::Run(REFERENCE_TIME tStart) 
{ 
	return S_OK; 
} 
 
STDMETHODIMP CMPEG1Builder::Stop(void) 
{ 
	return S_OK; 
} 
 
STDMETHODIMP CMPEG1Builder::SetSyncSource(IReferenceClock *pClock) 
{ 
	return S_OK; 
}