www.pudn.com > myseelite_2007_06_28.zip > GraphCenter.cpp


/* 
 *  Openmysee 
 * 
 *  This program is free software; you can redistribute it and/or modify 
 *  it under the terms of the GNU General Public License as published by 
 *  the Free Software Foundation; either version 2 of the License, or 
 *  (at your option) any later version. 
 * 
 *  This program is distributed in the hope that it will be useful, 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 *  GNU General Public License for more details. 
 * 
 *  You should have received a copy of the GNU General Public License 
 *  along with this program; if not, write to the Free Software 
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 * 
 */ 
#include "stdafx.h" 
#include "GraphCenter.h" 
#include  
#include "../captureserver/TVSourceConfig.h" 
#include "../captureserver/uuids.h" 
#include  
 
 
#define SAFE_RELEASE(p) { if(p) p->Release(); p = NULL; } 
 
//构造析构函数 
CGraphCenter::CGraphCenter() :mpAsfReader( NULL) 
{ 
	m_pTVStreamSink = NULL; 
	m_pSourceFile = NULL; 
	m_pAviSplitter = NULL; 
 
	m_pGB = NULL; 
	m_pMC = NULL; 
	m_pEvent = NULL; 
 
	InitializeCriticalSection(&moCriticalSection);	 
	//保护停止标志位。 
	EnterCriticalSection(&moCriticalSection); 
	m_iIsStop = 1;			//0为运行,1为停止。-1为发生意外错误停止 
	LeaveCriticalSection(&moCriticalSection); 
 
	CreateDebugInfo(); 
} 
 
CGraphCenter::~CGraphCenter() 
{ 
	Uninitialize(); 
	EnterCriticalSection(&moCriticalSection); 
	m_iIsStop = 1;			//0为运行,1为停止。-1为发生意外错误停止 
	LeaveCriticalSection(&moCriticalSection); 
	DeleteCriticalSection(&moCriticalSection);	//保护停止标志位。 
} 
 
//将Filter添加到图中去 
STDMETHODIMP CGraphCenter::AddFilter(CLSID clsidFilter,			    
									  IBaseFilter** ppIFilter,	 
									  LPCTSTR pstrFilterName) 
{ 
	HRESULT hr; 
	assert(m_pGB); 
	assert(ppIFilter); 
	(*ppIFilter) = NULL; 
 
	// try to instantiate the filter 
	hr = CoCreateInstance(clsidFilter,  
		NULL,  
		CLSCTX_INPROC,  
		IID_IBaseFilter, 
		(LPVOID*)(ppIFilter)); 
	if(FAILED(hr)) 
	{ 
		//DbgLog((LOG_TRACE, 5, TEXT("Could not instantiate filter"))); 
		//TRACE("Could not instantiate filter"); 
		return hr; 
	} 
 
	// Check for unicode or not 
#ifndef _UNICODE 
	if(pstrFilterName) 
	{ 
		// not unicode, we need to unicodify the string 
		WCHAR wstrFilterName[256]; 
		MultiByteToWideChar(CP_ACP,  
			MB_PRECOMPOSED | MB_USEGLYPHCHARS, 
			pstrFilterName, 
			-1,  
			wstrFilterName,  
			sizeof(wstrFilterName) / sizeof(WCHAR)); 
 
		// try to add it to the filter graph 
		hr = m_pGB->AddFilter(*ppIFilter, wstrFilterName); 
	} 
	else 
	{ 
		// No filter name specified, cannot convert 
		// try to add it to the filter graph 
		hr = m_pGB->AddFilter(*ppIFilter, NULL); 
	} 
#else 
	// already unicode, no need to change anything 
	// try to add it to the filter graph 
	hr = m_pGB->AddFilter(*ppIFilter, pstrFilterName); 
#endif 
 
	// check the result of the operation 
	if(FAILED(hr)) 
	{ 
		//TRACE("Could not add filter to filter graph\n"); 
		// free the filter definitely 
		(*ppIFilter)->Release(); 
		(*ppIFilter) = NULL; 
		return hr; 
	} 
 
	// that's it 
	return hr; 
} 
 
 
//pin的连接 
STDMETHODIMP CGraphCenter::ConnectPins(IBaseFilter* pIFilterOutput,  
										LPCTSTR pstrPinNameOutput, 
										IBaseFilter* pIFilterInput,  
										LPCTSTR pstrPinNameInput, 
										AM_MEDIA_TYPE* pmt) 
{ 
	HRESULT hr; 
	assert(m_pGB); 
 
	// Parameters... 
	if((!pIFilterOutput) || (!pIFilterInput)) 
	{ 
		assert(pIFilterOutput && pIFilterInput); 
		//TRACE("ConnectPins called with NULL parameter\n"); 
		return E_INVALIDARG; 
	} 
 
	// Find the first pin 
	IPin* pIPinOutput = FindPinOnFilter(pIFilterOutput,  
		pstrPinNameOutput, 
		PINDIR_OUTPUT); 
	if(!pIPinOutput) 
	{ 
		assert(pIPinOutput); 
		return E_FAIL; 
	} 
 
	// Find the second pin 
	IPin* pIPinInput = FindPinOnFilter(pIFilterInput, 
		pstrPinNameInput, 
		PINDIR_INPUT); 
	if(!pIPinInput) 
	{ 
		assert(pIPinInput); 
		// release the other pin 
		pIPinOutput->Release(); 
		return E_FAIL; 
	} 
 
	if(FAILED(pIPinOutput->Disconnect())) 
	{ 
		assert(FALSE); 
		return E_FAIL; 
	} 
 
	if(FAILED(pIPinInput->Disconnect())) 
	{ 
		assert(FALSE); 
		return E_FAIL; 
	} 
 
	// Now just connect the two pins 
	hr = m_pGB->ConnectDirect(pIPinOutput, pIPinInput, pmt); 
//	assert(SUCCEEDED(hr)); 
	if(FAILED(hr)) 
    { 
		TraceLog1("Could not direct connect pins!, try intelligent connect"); 
        hr = m_pGB->Connect(pIPinOutput, pIPinInput); 
    } 
 
	// Release the two pins and return the result 
	pIPinOutput->Release(); 
	pIPinInput->Release(); 
 
	return hr; 
} 
 
//自动连接Filter 
STDMETHODIMP CGraphCenter::ConnectAutoPins(IBaseFilter* pIFilterOutput,  
											LPCTSTR pstrPinNameOutput, 
											IBaseFilter* pIFilterInput,  
											LPCTSTR pstrPinNameInput) 
{ 
	HRESULT hr; 
	assert(m_pGB); 
 
	// Parameters... 
	if((!pIFilterOutput) || (!pIFilterInput)) 
	{ 
		assert(pIFilterOutput && pIFilterInput); 
		//TRACE("ConnectPins called with NULL parameter\n"); 
		return E_INVALIDARG; 
	} 
 
	// Find the first pin 
	IPin* pIPinOutput = FindPinOnFilter(pIFilterOutput,  
		pstrPinNameOutput, 
		PINDIR_OUTPUT); 
	if(!pIPinOutput) 
	{ 
		assert(pIPinOutput); 
		return E_FAIL; 
	} 
 
	// Find the second pin 
	IPin* pIPinInput = FindPinOnFilter(pIFilterInput, 
		pstrPinNameInput, 
		PINDIR_INPUT); 
	if(!pIPinInput) 
	{ 
		assert(pIPinInput); 
		// release the other pin 
		pIPinOutput->Release(); 
		return E_FAIL; 
	} 
 
	if(FAILED(pIPinOutput->Disconnect())) 
	{ 
		assert(FALSE); 
		return E_FAIL; 
	} 
 
	if(FAILED(pIPinInput->Disconnect())) 
	{ 
		assert(FALSE); 
		return E_FAIL; 
	} 
 
	// Now just connect the two pins 
	hr = m_pGB->Connect(pIPinOutput, pIPinInput); 
	assert(SUCCEEDED(hr)); 
	if(FAILED(hr)) 
		//TRACE("Could not connect pins!"); 
 
	// Release the two pins and return the result 
	pIPinOutput->Release(); 
	pIPinInput->Release(); 
 
	return hr; 
} 
 
//查找filter上的pin 
STDMETHODIMP_(IPin*) CGraphCenter::FindPinOnFilter(IBaseFilter* pIFilter,  
													LPCTSTR pstrPinName, 
													PIN_DIRECTION dir) 
{ 
	HRESULT     hr; 
	IEnumPins*  pIEnumPins; 
	IPin*       pIPin; 
	PIN_INFO    pi; 
	assert(m_pGB); 
 
	// Parameters... 
	if(!pIFilter) 
		return NULL; 
 
	// Enumerate pins on the filter 
	hr = pIFilter->EnumPins(&pIEnumPins); 
	if(FAILED(hr)) 
		// pin was not found! 
		return NULL; 
 
	// Loop till we find no more pins 
	IPin* pIPinFound = NULL; 
	 
	 
	while( (!pIPinFound) && (pIEnumPins->Next(1, &pIPin, NULL)==S_OK) ) 
	{ 
		// Is this the pin? 
		hr = pIPin->QueryPinInfo(&pi); 
		if(!FAILED(hr)) 
		{ 
			// check if it is the right direction 
			if(pi.dir == dir) 
			{ 
				// Let the graph builder find the right filter 
				TCHAR strFoundPinName[256]; 
#ifndef _UNICODE 
				// not unicode, we need to de-unicodify the returned pin name 
				WideCharToMultiByte(CP_ACP, NULL, 
					pi.achName, -1, 
					strFoundPinName, sizeof(strFoundPinName), 
					NULL, NULL); 
#else 
				// just make a copy of the string 
				lstrcpyn(strFoundPinName, pi.achName, sizeof(strFoundPinName)); 
#endif 
 
				// check if there is a pin name specified	 
				if(!pstrPinName) 
				{ 
					// no name specified, take the first pin found 
					pIPinFound = pIPin; 
					pIPinFound->AddRef(); 
				} 
				// check if we have the right pin name 
				else if(lstrcmp(strFoundPinName, pstrPinName)==0) 
				{ 
					// yes we have! 
					pIPinFound = pIPin; 
					pIPinFound->AddRef(); 
				} 
			} 
 
			// release the PIN_INFO data 
			pi.pFilter->Release(); 
		} 
 
		// release the IPin pointer 
		pIPin->Release(); 
	} 
	// Finished with the enumerator, let it go (be free) 
  	pIEnumPins->Release(); 
 
	// Return whatever we have found 
	return pIPinFound; 
} 
 
//pin的连接 
STDMETHODIMP CGraphCenter::ConnectPinsEX(IBaseFilter* pIFilterOutput,  
									   Pin_type atype, 
									   IBaseFilter* pIFilterInput,  
									   LPCTSTR pstrPinNameInput,		 
									   BOOL bisAuto,AM_MEDIA_TYPE* pmt) 
{ 
	HRESULT hr; 
	assert(m_pGB); 
 
	// Parameters... 
	if((!pIFilterOutput) || (!pIFilterInput)) 
	{ 
		assert(pIFilterOutput && pIFilterInput); 
		//TRACE("ConnectPins called with NULL parameter\n"); 
		return E_INVALIDARG; 
	} 
 
	// Find the first pin 
	IPin* pIPinOutput = FindPinOnFilterbyType(pIFilterOutput,  
		atype, 
		PINDIR_OUTPUT); 
	if(!pIPinOutput) 
	{ 
		assert(pIPinOutput); 
		return E_FAIL; 
	} 
 
	// Find the second pin 
	IPin* pIPinInput = FindPinOnFilter(pIFilterInput, 
		pstrPinNameInput, 
		PINDIR_INPUT); 
	if(!pIPinInput) 
	{ 
		assert(pIPinInput); 
		// release the other pin 
		pIPinOutput->Release(); 
		return E_FAIL; 
	} 
 
	if(FAILED(pIPinOutput->Disconnect())) 
	{ 
		assert(FALSE); 
		return E_FAIL; 
	} 
 
	if(FAILED(pIPinInput->Disconnect())) 
	{ 
		assert(FALSE); 
		return E_FAIL; 
	} 
 
	if (FALSE == bisAuto) 
	{ 
		hr = m_pGB->ConnectDirect(pIPinOutput, pIPinInput, pmt); 
	} 
	else 
	{ 
		hr = m_pGB->Connect(pIPinOutput, pIPinInput); 
	} 
	// Now just connect the two pins 
 
	//	assert(SUCCEEDED(hr)); 
	if(FAILED(hr)) 
	{ 
		TraceLog1("Could not direct connect pins!, try intelligent connect"); 
		hr = m_pGB->Connect(pIPinOutput, pIPinInput); 
	} 
 
	// Release the two pins and return the result 
	pIPinOutput->Release(); 
	pIPinInput->Release(); 
 
	return hr; 
} 
 
//查找filter上满足一定条件的的媒体类型 
STDMETHODIMP_(IPin*) CGraphCenter::FindPinOnFilterbyType(IBaseFilter* pIFilter,  
														 Pin_type aType, 
														 PIN_DIRECTION dir) 
{ 
	HRESULT hr; 
	IEnumPins* enum_pin; 
	IPin* findpin = NULL; 
	IPin* pin = NULL; 
	IEnumMediaTypes* enum_media_type; 
	AM_MEDIA_TYPE* media_type = NULL; 
	AM_MEDIA_TYPE* tempmedia_type = NULL; 
 
	PIN_DIRECTION temp_dir; 
	assert(m_pGB); 
 
	hr = pIFilter->EnumPins(&enum_pin); 
	if (FAILED(hr)) 
	{ 
		return NULL; 
	} 
	enum_pin->Reset(); 
	 
	GUID formattype = (aType == VIDEO)? FORMAT_VideoInfo:FORMAT_WaveFormatEx; 
	ULONG liCount = 0; 
	 
	hr = enum_pin->Next(1,&pin,&liCount);	 
	 
	 
	while (!findpin && SUCCEEDED(hr)) 
	{ 
		 
		 //Is this the pin?		不计数 
		hr = pin->QueryDirection(&temp_dir); 
		 
		if (FAILED(hr)) 
		{ 
			break;//return NULL; 
		} 
 
		if (temp_dir != dir) 
		{ 
			continue; 
		} 
 
		//枚举媒体类型 
		hr = pin->EnumMediaTypes(&enum_media_type); 
		if (FAILED(hr)) 
		{ 
			break; 
		} 
		/* 
		enum_media_type->AddRef(); 
		iii = enum_media_type->Release();计数:1 
		*/ 
		enum_media_type->Reset(); 
		media_type = NULL; 
		hr = enum_media_type->Next(1,&media_type,&liCount); 
		while (NULL == tempmedia_type && SUCCEEDED(hr)) 
		{			 
			if((*media_type).formattype == formattype || (*media_type).formattype == FORMAT_MPEGVideo) 
			{ 
				tempmedia_type = media_type; 
				findpin = pin; 
				findpin->AddRef(); 
				break; 
			}	 
			hr = enum_media_type->Next(1,&media_type,&liCount); 
			if (0 == liCount) 
			{ 
				break; 
			} 
		} 
		hr = enum_pin->Next(1,&pin,&liCount); 
		enum_media_type->Release(); 
		if (0 == liCount) 
		{ 
			break; 
		} 
	}	 
	enum_pin->Release();	 
	return findpin; 
 
 
} 
 
STDMETHODIMP CGraphCenter::RemoveFilter(IBaseFilter* pIFilter) 
{ 
	HRESULT hr; 
 
	// Parameters... 
	if(!pIFilter) 
		// DON'T return an error, this is expected 
		return NOERROR; 
 
	assert(m_pGB); 
 
	// Just remove it from the graph 
	hr = m_pGB->RemoveFilter(pIFilter); 
 
	return hr; 
} 
 
////////////////////////////////////////////////////////////////////////// 
//以下为处理接口函数 
////////////////////////////////////////////////////////////////////////// 
 
//初始化库 
STDMETHODIMP CGraphCenter::Initialize() 
{ 
	HRESULT hr = CoInitialize(NULL); 
	if (FAILED(hr)) 
	{ 
		//TRACE0("ERROR - Could not initialize COM library"); 
		return hr; 
	} 
 
	// Create the filter graph manager and query for interfaces. 
	hr = CoCreateInstance(CLSID_FilterGraph,  
		NULL,  
		CLSCTX_INPROC_SERVER,  
		IID_IGraphBuilder,  
		(void **)&m_pGB); 
	if (FAILED(hr)) 
	{ 
		//TRACE0("ERROR - Could not create the Filter Graph Manager."); 
		return hr; 
	} 
 
	hr = m_pGB->QueryInterface(IID_IMediaControl, (void **)&m_pMC); 
	if (FAILED(hr)) 
	{ 
		//TRACE0("ERROR - Could not Get IMediaControl"); 
		return hr; 
	} 
 
	hr = m_pGB->QueryInterface(IID_IMediaEvent, (void **)&m_pEvent); 
	if (FAILED(hr)) 
	{ 
		//TRACE0("ERROR - Could not Get IMediaEvent"); 
		return hr; 
	} 
	 
	#ifdef _DEBUG 
	AddGraphToRot(m_pGB, &g_dwRegister); 
	#endif //_DEBUG 
/* 
	// for DEBUG 
#ifdef _DEBUG 
	AddGraphToRot(m_pGB, &g_dwRegister); 
#endif //_DEBUG 
*/ 
	return S_OK; 
} 
 
STDMETHODIMP CGraphCenter::Uninitialize() 
{ 
	// first unDEBUG 
#ifdef _DEBUG 
	RemoveGraphFromRot(g_dwRegister); 
#endif //_DEBUG 
 
	DisassembleGraph(); 
 
	CoUninitialize(); 
	return S_OK;	 
} 
 
//构建图 
STDMETHODIMP CGraphCenter::BuildGraph(LPCTSTR astrFileName, LPCTSTR astrZZLDirectory, LPCTSTR astrZZLFile) 
{ 
	HRESULT hr; 
	 
	if (NULL == astrZZLDirectory) 
	{ 
		MessageBox(NULL, "输入的将要生成的ZZL文件路径","错误", MB_OK|MB_ICONSTOP); 
		return E_FAIL; 
	} 
 
    char temp[512] = {0}; 
    if(astrFileName && strlen(astrFileName) > 4) 
        strcpy(temp, astrFileName+strlen(astrFileName)-4); // 只留下后缀名 
    strlwr(temp); // 忽略大小写 
    if(strcmp(temp, ".wmv") != 0 && strcmp(temp, ".wma") != 0 && strcmp(temp, ".avi") != 0 && strcmp(temp, ".wav") != 0 && strcmp(temp, ".asf") != 0) 
	{ 
		MessageBox(NULL, "文件错误或者不是avi,wav,wmv,wma,asf文件,", "错误", MB_OK|MB_ICONSTOP); 
		return E_FAIL; 
	} 
 
	//添加TV Sink Filter 
	hr = AddFilter(CLSID_TVStreamSink, &m_pTVStreamSink); 
	if (FAILED(hr)) 
	{ 
        TraceLog1("未能加载CaptureServer的filter\r\n"); 
		return hr; 
	}	 
	 
	ITVSourceConfig* lpTVSourceConfig = NULL; 
 
	hr = m_pTVStreamSink->QueryInterface(IID_ITVSouceConfig, (void**)&lpTVSourceConfig); 
	if (FAILED(hr)) 
	{ 
        TraceLog1("从Capture filter中得不到相应界面\r\n"); 
		return hr; 
	} 
 
 
	//在连接之前,一定要将ZZL目录和ZZL文件名设置好。 
	lpTVSourceConfig->SetProgramStorePath(astrZZLDirectory); 
 
	lpTVSourceConfig->SetChannelName(astrZZLFile); 
 
	 
 
	WCHAR lwszFileName[256]; 
	MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_USEGLYPHCHARS, 
		astrFileName, -1,  
		lwszFileName, sizeof(lwszFileName) / sizeof(WCHAR)); 
    wcslwr(lwszFileName); // 忽略大小写,后面的比较才能顺利进行 
 
	  
	ULONG iii; 
	//处理wmv文件 
	if (NULL != wcsstr(lwszFileName, L".wmv") || NULL != wcsstr(lwszFileName, L".asf")) 
	{		 
		hr = AddFilter(CLSID_WMAsfReader , &mpAsfReader); 
		if (FAILED(hr)) 
		{ 
            TraceLog1("加入wmv的filter失败\r\n"); 
			lpTVSourceConfig->Release(); 
			return hr; 
		} 
		 
		IFileSourceFilter* lpFileSource = NULL; 
		hr = mpAsfReader->QueryInterface(IID_IFileSourceFilter, (void**)&lpFileSource); 
		lpFileSource->Load(lwszFileName,NULL); 
		 
		/* 
		//连接 
		hr = ConnectPins(mpAsfReader, "Raw Video 0", m_pTVStreamSink, "Video"); 
		if (FAILED(hr)) 
            TraceLog1("和wmv视频接口连接时发生错误:0x%X\r\n", hr); 
		hr = ConnectPins(mpAsfReader, "Raw Audio 1", m_pTVStreamSink, "Audio"); 
		if (FAILED(hr)) 
            TraceLog1("和wmv音频接口连接时发生错误:0x%X\r\n", hr); 
		*/ 
 
		//连接 
			 
		hr = ConnectPinsEX(mpAsfReader, AUDIO, m_pTVStreamSink, "Audio"); 
		if (FAILED(hr)) 
			TraceLog1("和wmv音频接口连接时发生错误:0x%X\r\n", hr); 
 
		hr = ConnectPinsEX(mpAsfReader,VIDEO,m_pTVStreamSink,"Video"); 
		if (FAILED(hr)) 
		{ 
			TraceLog1("和wmv视频接口连接时发生错误:0x%X\r\n", hr); 
		}	 
		iii = lpFileSource->Release(); 
		lpTVSourceConfig->Release(); 
		return hr;			 
	} 
 
	//处理wma文件 
	if (NULL != wcsstr(lwszFileName, L".wma")) 
	{		 
		hr = AddFilter(CLSID_WMAsfReader , &mpAsfReader); 
		if (FAILED(hr)) 
		{ 
            TraceLog1("加入wma的filter失败\r\n"); 
			lpTVSourceConfig->Release(); 
			return hr; 
		} 
 
		IFileSourceFilter* lpFileSource = NULL; 
		hr = mpAsfReader->QueryInterface(IID_IFileSourceFilter, (void**)&lpFileSource); 
		lpFileSource->Load(lwszFileName,NULL); 
 
		//必须在连接之前将之设为单音频,否则,惨惨惨 
		lpTVSourceConfig->SetAudioOrVideoOnly(TRUE); 
		//连接		 
		hr = ConnectPins(mpAsfReader, "Raw Audio 0", m_pTVStreamSink, "Audio"); 
        if (FAILED(hr)) 
            TraceLog1("和wma视频接口连接时发生错误:0x%X\r\n", hr); 
 
		lpFileSource->Release();	 
		lpTVSourceConfig->Release(); 
		return hr;			 
	} 
 
 
	hr = m_pGB->AddSourceFilter(lwszFileName, NULL, &m_pSourceFile); 
	if (FAILED(hr)) 
	{ 
        TraceLog1("加入source filter的filter失败\r\n"); 
		lpTVSourceConfig->Release(); 
		return hr; 
	} 
 
	//处理wav文件 
	if (NULL != wcsstr(lwszFileName, L".wav")) 
	{ 
		lpTVSourceConfig->SetAudioOrVideoOnly(TRUE); 
		hr = ConnectAutoPins(m_pSourceFile, NULL, m_pTVStreamSink, "Audio"); 
        if (FAILED(hr)) 
            TraceLog1("和wav音频接口连接时发生错误:0x%X\r\n", hr); 
		lpTVSourceConfig->Release(); 
		return hr;		 
	} 
	lpTVSourceConfig->Release(); 
 
	hr = AddFilter(CLSID_AviSplitter, &m_pAviSplitter); 
	if (FAILED(hr)) 
	{ 
        TraceLog1("加入avi splitter的filter失败\r\n"); 
		return hr; 
	} 
 
	hr = ConnectPins(m_pSourceFile, NULL, m_pAviSplitter, NULL); 
	if (FAILED(hr)) 
	{ 
        TraceLog1("source filter 和 avi splitter 音频接口连接时发生错误:0x%X\r\n", hr); 
		return hr; 
	}	 
	 
	hr = ConnectPins(m_pAviSplitter, "Stream 00", m_pTVStreamSink, "Video"); 
	if (FAILED(hr)) 
	{ 
        //此时可能是Stream 00 为音频频,而Stream01为视频 
		hr = ConnectPins(m_pAviSplitter, "Stream 00", m_pTVStreamSink, "Audio"); 
		if (FAILED(hr)) 
		{ 
			TraceLog1("和 avi splitter 视频接口连接时发生错误:0x%X\r\n", hr); 
			DisassembleGraph(); 
			return hr; 
		} 
		hr = ConnectPins(m_pAviSplitter, "Stream 01", m_pTVStreamSink, "Video"); 
		if (FAILED(hr)) 
		{ 
			TraceLog1("和 avi splitter 视频接口连接时发生错误:0x%X\r\n", hr); 
			DisassembleGraph(); 
			return hr; 
		} 
		return hr; 
		 
	} 
 
 
	hr = ConnectPins(m_pAviSplitter, "Stream 01", m_pTVStreamSink, "Audio"); 
	if (FAILED(hr)) 
	{ 
        TraceLog1("和 avi splitter 音频接口连接时发生错误:0x%X\r\n", hr); 
		DisassembleGraph(); 
		return hr; 
	} 
 
	return hr; 
} 
 
STDMETHODIMP CGraphCenter::DisassembleGraph() 
{ 
	HRESULT hr; 
	hr = RemoveFilter(m_pSourceFile); 
	hr = RemoveFilter(m_pAviSplitter); 
	hr = RemoveFilter(m_pTVStreamSink); 
	hr = RemoveFilter(mpAsfReader); 
 
	ULONG iii; 
 
	if (m_pTVStreamSink) 
	{ 
		iii = m_pTVStreamSink->Release(); 
		m_pTVStreamSink = NULL; 
	} 
	if (mpAsfReader) 
	{ 
		iii = mpAsfReader->Release(); 
		mpAsfReader = NULL; 
	} 
 
	if (m_pSourceFile) 
	{ 
		iii = m_pSourceFile->Release(); 
		m_pSourceFile = NULL; 
	} 
 
	if (m_pAviSplitter) 
	{ 
		iii = m_pAviSplitter->Release(); 
		m_pAviSplitter = NULL; 
	} 
 
 
 
	/* 
	SAFE_RELEASE(m_pSourceFile) 
	SAFE_RELEASE(m_pAviSplitter) 
	SAFE_RELEASE(m_pAviSplitter) 
	SAFE_RELEASE(mpAsfReader) 
	*/ 
	return hr; 
} 
 
STDMETHODIMP CGraphCenter::Run() 
{ 
	HRESULT hr; 
	HANDLE lhhandle = NULL;	 
 
		 
	hr = m_pMC->Run(); 
	if (FAILED(hr)) 
	{ 
		return hr; 
	} 
	 
	DWORD ldwThreadID; 
	lhhandle = CreateThread(0,0,(LPTHREAD_START_ROUTINE)WaitForEnd,this,0,&ldwThreadID); 
	if (NULL != lhhandle) 
	{ 
		CloseHandle(lhhandle);		 
	} 
	else 
	{ 
		MessageBox(NULL,"错误","错误",MB_OK); 
		return E_FAIL; 
	} 
	 
	/* 
	if (SUCCEEDED(hr)) 
	{ 
		// Wait for completion. 
		long evCode; 
		hr = m_pEvent->WaitForCompletion(INFINITE, &evCode); 
 
		int i = 0; 
		// Note: Do not use INFINITE in a real application, because it 
		// can block indefinitely. 
	} 
	*/ 
	 
	 
	return hr; 
} 
 
STDMETHODIMP CGraphCenter::Stop() 
{ 
	HRESULT hr; 
	hr = m_pMC->Stop(); 
	TRACE1("CGraphCenter::Stop停止\n"); 
	//hr = DisassembleGraph(); 
	return hr; 
} 
 
void WINAPI CGraphCenter::WaitForEnd(void * apParameter) 
{ 
	/* 
	CGraphCenter* lpGraphCenter = (CGraphCenter*) apParameter; 
	HANDLE  hEvent;  
	long    evCode, param1, param2; 
	BOOLEAN bDone = FALSE; 
	HRESULT hr = S_OK; 
	hr = lpGraphCenter->m_pEvent->GetEventHandle((OAEVENT*)&hEvent); 
	if (FAILED(hr)) 
	{ 
		 
	} 
	while(!bDone)  
	{ 
		if (WAIT_OBJECT_0 == WaitForSingleObject(hEvent, 100)) 
		{  
			while (hr = lpGraphCenter->m_pEvent->GetEvent(&evCode, ¶m1, ¶m2, 0), SUCCEEDED(hr))  
			{ 
				printf("Event code: %#04x\n Params: %d, %d\n", evCode, param1, param2); 
				lpGraphCenter->m_pEvent->FreeEventParams(evCode, param1, param2); 
				bDone = (EC_COMPLETE == evCode); 
			} 
		} 
	}  
	*/ 
	 
	 
 
	CGraphCenter* lpGraphCenter = (CGraphCenter*) apParameter; 
	 
	HRESULT hr;	 
	if (NULL == lpGraphCenter->mpGetZZLStateProc) 
	{ 
		return; 
	} 
 
	ITVSourceConfig* lpTVSourceConfig; 
	int liState = 0;//0为运行,1为停止。-1为发生意外错误停止 
	EnterCriticalSection(&lpGraphCenter->moCriticalSection); 
	hr = lpGraphCenter->m_pTVStreamSink->QueryInterface(IID_ITVSouceConfig, (void**)&lpTVSourceConfig); 
	LeaveCriticalSection(&lpGraphCenter->moCriticalSection); 
 
    int bytethesamecounter = 0; 
    LONGLONG prevsize = 0; 
	while ( 0 == liState) 
	{ 
		lpTVSourceConfig->GetZZLState(&liState); 
        if(lpTVSourceConfig->EndOfStream()) 
		{ 
            TRACE1("因为EndOfStream非正常退出\n"); 
			break; 
		} 
        LONGLONG size = lpTVSourceConfig->GetTotalBytes(); 
		 
        if(size == prevsize) 
            bytethesamecounter++; 
        else 
            prevsize = size; 
 
        TraceLog1("handle file: %d bytes\r\n",size); 
        Sleep(500); 
 
        if(bytethesamecounter > 10) 
		{ 
			TRACE1("因为bytethesamecounter非正常退出\n"); 
			break; 
		} 
            
	} 
	TRACE1("end123mistate:%d\n",liState ); 
	ULONG iii = lpTVSourceConfig->Release(); 
	lpTVSourceConfig = NULL; 
	 
	EnterCriticalSection(&lpGraphCenter->moCriticalSection); 
	lpGraphCenter->m_iIsStop = 1; 
	hr = lpGraphCenter->Stop();	 
	lpGraphCenter->DisassembleGraph(); 
	LeaveCriticalSection(&lpGraphCenter->moCriticalSection); 
 
	lpGraphCenter->mpGetZZLStateProc(lpGraphCenter->mpGetZZLUserPara, 1); 
	 
 
	/* 
	hr = lpGraphCenter->m_pEvent->WaitForCompletion(INFINITE, &lpEvCode); 
	if (FAILED(hr)) 
	{ 
		lpGraphCenter->mpGetZZLStateProc(lpGraphCenter->mpGetZZLUserPara, -1); 
		EnterCriticalSection(&lpGraphCenter->moCriticalSection); 
		lpGraphCenter->m_iIsStop  = -1;		 
		LeaveCriticalSection(&lpGraphCenter->moCriticalSection); 
		return ; 
	} 
	if (EC_COMPLETE != lpEvCode && EC_USERABORT != lpEvCode) 
	{ 
		lpGraphCenter->mpGetZZLStateProc(lpGraphCenter->mpGetZZLUserPara, -1); 
		EnterCriticalSection(&lpGraphCenter->moCriticalSection); 
		lpGraphCenter->m_iIsStop = -1;		 
		LeaveCriticalSection(&lpGraphCenter->moCriticalSection); 
		return; 
	} 
	lpGraphCenter->mpGetZZLStateProc(lpGraphCenter->mpGetZZLUserPara, 1); 
	EnterCriticalSection(&lpGraphCenter->moCriticalSection); 
	lpGraphCenter->m_iIsStop = 1; 
	LeaveCriticalSection(&lpGraphCenter->moCriticalSection); 
 
	hr = lpGraphCenter->Stop();	 
	lpGraphCenter->DisassembleGraph(); 
	 
	Sleep(100); 
	*/ 
} 
 
float CGraphCenter::GetCompressedSpeed() 
{ 
	HRESULT hr; 
	float lfSpeed; 
	if (0 != GetState()) 
	{ 
		return 0; 
	} 
	assert(m_pTVStreamSink); 
 
	ITVSourceConfig* lpTVSourceConfig = NULL; 
	hr = m_pTVStreamSink->QueryInterface(IID_ITVSouceConfig, (void**)&lpTVSourceConfig); 
	if (FAILED(hr)) 
	{ 
		MessageBox(NULL, "获取速度失败", "错误", MB_OK|MB_ICONSTOP); 
		return 0; 
	} 
	lfSpeed = lpTVSourceConfig->GetCompressedSpeed(); 
	lpTVSourceConfig->Release(); 
	return lfSpeed; 
} 
 
//设置状态回调函数 
void CGraphCenter::SetStateProc(GetZZLState* apStateproc, void* apUserPara) 
{ 
	assert(apStateproc); 
	mpGetZZLStateProc = apStateproc; 
	mpGetZZLUserPara = apUserPara; 
} 
 
//创建调试信息日志 
bool CGraphCenter::CreateDebugInfo() 
{ 
    char strPath[255]; 
	char strLogFileName[255]; 
	 
	//首先设置日志打印选项 
	CDebugTrace::SetTraceLevel(6); 
	 
	CDebugTrace::SetTraceOptions(CDebugTrace::GetTraceOptions() \ 
		| CDebugTrace::Timestamp & ~CDebugTrace::LogLevel \ 
		& ~CDebugTrace::FileAndLine | CDebugTrace::AppendToFile\ 
		& ~CDebugTrace::PrintToConsole); 
	 
	if (!GetModuleFileName(NULL,strPath, 255)) 
	{ 
		TRACE1("CMediaCenter::CreateDebugInfo:GetModuleFileName()函数返回失败!\n"); 
		return false; 
	} 
	 
	//从strPath中去掉文件名,从而取得可执行文件的路径; 
	int nPosition = 0; 
	nPosition = (int)(strrchr(strPath,'\\') - strPath); 
	strPath[nPosition+1] = '\0'; 
	 
	//生成日志目录 
	strcat(strPath, "日志文件\\");	 
	if(TRUE != CreateDirectory(strPath, NULL)) 
	{ 
		int i = GetLastError(); 
		if (ERROR_ACCESS_DENIED != i && ERROR_ALREADY_EXISTS != i) 
		{ 
			MessageBox(NULL, "创建文件夹失败", "错误", MB_OK|MB_ICONSTOP); 
		} 
	} 
 
	//生成TRACE文件名 
	SYSTEMTIME loSystemTime; 
	GetLocalTime(&loSystemTime); 
	 
	sprintf(strLogFileName, "%sGetZZLDisplay%4d%02d%02d%s", strPath,loSystemTime.wYear,\ 
		loSystemTime.wMonth,loSystemTime.wDay,".log"); 
	//sprintf(strLogFileName, "%sUTMedia%4d%02d%02d%s", strPath,loSystemTime.wYear,\ 
//		loSystemTime.wMonth,loSystemTime.wDay,".log"); 
	//strcat(strPath, "GetZZLDisplay.log"); 
	CDebugTrace::SetLogFileName(strLogFileName);	     
	return true; 
}