⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tvsourcefilter.cpp

📁 mysee网络直播源代码Mysee Lite是Mysee独立研发的网络视频流媒体播放系统。在应有了P2P技术和一系列先进流媒体技术之后
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include "stdafx.h"
#include <process.h>
#include <Dmoreg.h>
#include <dmodshow.h>
#include <atlconv.h>
#include "networkproxy.h"
#include "graphrebuildhelper.h"
//
extern HANDLE g_hModule;

HRESULT CTVStreamSource::EnumFilters (IFilterGraph *pGraph) 
{
	IEnumFilters* pEnum  = NULL;
	IBaseFilter*  pFilter = NULL;;
	ULONG cFetched;

	HRESULT hr = pGraph->EnumFilters(&pEnum);
	if (FAILED(hr))
		return hr;
	//
	while(pEnum->Next(1, &pFilter, &cFetched) == S_OK)
	{
		FILTER_INFO FilterInfo;
		hr = pFilter->QueryFilterInfo(&FilterInfo);
		if (FAILED(hr))
		{
			ASSERT(FALSE);
			// Maybe the next one will work.
			continue;  
		}
		//
		GUID guid;
		HRESULT hr = pFilter->GetClassID(&guid);
		if (hr == S_OK)
		{
			if (CLSID_DSoundRender == guid ||
				CLSID_AudioRender == guid )
			{
				if (NULL != m_pAudioRender)
				{
					m_pAudioRender->Release();
					m_pAudioRender = NULL;
				}
				//
				m_pAudioRender = pFilter;
				pFilter->AddRef();
			}
			//			
			if (CLSID_VideoMixingRenderer  == guid ||
				CLSID_VideoRendererDefault == guid||
				CLSID_VideoRenderer        == guid)
			{
				if (NULL != m_pVideoRender)
				{
					m_pVideoRender->Release();
					m_pVideoRender = NULL;
				}
				//
				m_pVideoRender = pFilter;
				pFilter->AddRef();
			}
			
		}
		// The FILTER_INFO structure holds a pointer to the Filter Graph
		// Manager, with a reference count that must be released.
		if (FilterInfo.pGraph != NULL)
		{
			FilterInfo.pGraph->Release();
		}
		pFilter->Release();
	}
	//
	pEnum->Release();
	return S_OK;
}


//
unsigned __stdcall CTVStreamSource::ThreadFunc( void* pArguments )
{
	ASSERT(NULL != pArguments);
	CTVStreamSource* pTVSS = (CTVStreamSource*)pArguments;
	//
	CoInitialize(NULL);
	//
	MSG msg;
	WORD	m_accRequest = 0;	//累积的请求数目
	WORD	m_needRequest = 2;
	BOOL	m_videoavaible = FALSE;
	BOOL	m_audioavaible = FALSE;
	while(GetMessage(&msg, NULL, 0, 0))
	{
        if(msg.message == MEDIA_ERROR_STOP)
        {
            pTVSS->m_pAudioPin->KillPin();
            pTVSS->m_pVideoPin->KillPin();
            IGraphConfig* pConfig = pTVSS->GetGCF();
 			if(!pConfig) {
				assert(0);
				continue;
			}
			IMediaControl* pIMediaControl = NULL;
			pConfig->QueryInterface(IID_IMediaControl, (void**)&pIMediaControl);

			//错误信息因此停止图。
			HRESULT hr = pIMediaControl->Stop();
            pIMediaControl->Release();

        }
		else if (msg.message == MEDIATYPE_CHANGED)
		{
			m_accRequest++;
			if(LOWORD(msg.wParam) == 0)
				m_audioavaible = HIWORD(msg.wParam) == 1? TRUE:FALSE;
			else
				m_videoavaible = HIWORD(msg.wParam) == 1? TRUE:FALSE;

            if(m_accRequest < m_needRequest)    //如果需要等待,我们要开始一个flush操作,以避免另一个pin卡死在deliver上面!
            {
                HRESULT hr;
                if(m_audioavaible == FALSE)
                {
                    hr = pTVSS->m_pAudioPin->BeginFlushData();
                    assert(!FAILED(hr));
                }
                if(m_videoavaible == FALSE)
                {
                    hr = pTVSS->m_pVideoPin->BeginFlushData();
                    assert(!FAILED(hr));
                }
            }
            else	//累积请求数目足够,开始动态重连
			{
				m_needRequest = m_accRequest = 0;
				if(m_audioavaible)
					m_needRequest++;
				if(m_videoavaible)
					m_needRequest++;

                //flush停止
                pTVSS->m_pAudioPin->EndFlushData();
                pTVSS->m_pVideoPin->EndFlushData();

                //预先加入filter到cache里面以提高重连的成功率
/*                pTVSS->AddFilterToCache();
                GraphRebuildHelper helper;

//                IMediaControl* pIMediaControl = NULL;
//				pConfig->QueryInterface(IID_IMediaControl, (void**)&pIMediaControl);

                pTVSS->m_bDoRealStop = false;
                HRESULT hr = helper.stopgraph(pTVSS->GetFG());
                pTVSS->m_bDoRealStop = true;

                BOOL anypinOK = TRUE;
                if(m_videoavaible == TRUE)
                {
                    hr = helper.startbuilding(pTVSS->GetFG(), pTVSS->m_pVideoPin, false);
                    if(FAILED(hr))
                    {
                        char msg[100];
                        wsprintf(msg, "在连接视频时的DShow错误%X", hr);
                        MessageBox(NULL,msg,"错误", MB_OK);
                        anypinOK = FALSE;
                        pTVSS->m_pVideoPin->KillPin();
                        m_needRequest--;
                    }
                }

                if(m_audioavaible == TRUE)
                {
                    hr = helper.startbuilding(pTVSS->GetFG(), pTVSS->m_pAudioPin, true);
                    if(FAILED(hr))
                    {
                        char msg[100];
                        wsprintf(msg, "在连接音频时的DShow错误%X", hr);
                        MessageBox(NULL,msg,"错误", MB_OK);
                        anypinOK = FALSE;
                        pTVSS->m_pAudioPin->KillPin();
                        m_needRequest--;
                    }
                }*/
                
				IGraphConfig* pConfig = pTVSS->GetGCF();
				if(!pConfig) {
					assert(0);
					continue;
				}
                
                //先把Audio和Video Renderer Filter枚举到
				pTVSS->EnumFilters (pTVSS->GetFG());
				//
				IMediaControl* pIMediaControl = NULL;
				pConfig->QueryInterface(IID_IMediaControl, (void**)&pIMediaControl);

				//动态重连前,先把图stop or pause
				pTVSS->m_bDoRealStop = false;
				HRESULT hr = pIMediaControl->Stop();
//                HRESULT hr = pTVSS->Stop();
				assert(hr == S_OK);
				pTVSS->m_bDoRealStop = true;
                Sleep(500);
				//
  
				if (FALSE == pTVSS->m_iSAddFilterToCache)
					pTVSS->AddFilterToCache();

				BOOL anypinOK = TRUE;
				if(m_audioavaible == TRUE)
				{
									//
					IPin* pin = NULL;
					ULONG cFetched = 0;
					//
					IEnumPins* ppEnum = NULL;
					//

					if (S_OK == pTVSS->m_pAudioRender->EnumPins(&ppEnum))
					{
						ppEnum->Reset();
						ppEnum->Next(1, &pin, &cFetched);
						//
						HRESULT hr = S_FALSE;
						const AM_MEDIA_TYPE *pmtFirstConnection = pTVSS->m_pAudioPin->GetType();
						hr = pConfig->Reconnect(pTVSS->m_pAudioPin,
							pin, 
							pmtFirstConnection,
							NULL,
							NULL, 
							AM_GRAPH_CONFIG_RECONNECT_CACHE_REMOVED_FILTERS |
							AM_GRAPH_CONFIG_RECONNECT_USE_ONLY_CACHED_FILTERS);
						//

						if(FAILED(hr))
                        {
							anypinOK = FALSE;
                            char msg[100];
                            wsprintf(msg, "在连接音频时的DShow错误%X", hr);
                            MessageBox(NULL,msg,"错误", MB_OK);
                            pTVSS->m_pAudioPin->KillPin();
                            m_needRequest--;
                        }
					}

					if(ppEnum)
						ppEnum->Release();
					if(pin)
						pin->Release();
				}

				if(m_videoavaible == TRUE)
				{
					//
					IPin* pin = NULL;
					ULONG cFetched = 0;
					//
					IEnumPins* ppEnum = NULL;
					//
					if (S_OK == pTVSS->m_pVideoRender->EnumPins(&ppEnum))
					{
						ppEnum->Reset();
						if (S_OK == ppEnum->Next(1, &pin, &cFetched))
						{
							hr = S_FALSE;
							const AM_MEDIA_TYPE *pmtFirstConnection = pTVSS->m_pVideoPin->GetType();
							hr=	pConfig->Reconnect((IPin*)(pTVSS->m_pVideoPin),
								pin,
								pmtFirstConnection,
								NULL,
								NULL,
								AM_GRAPH_CONFIG_RECONNECT_CACHE_REMOVED_FILTERS |
								AM_GRAPH_CONFIG_RECONNECT_USE_ONLY_CACHED_FILTERS);

							if(FAILED(hr))
                            {
								anypinOK = FALSE;
                                char msg[100];
                                wsprintf(msg, "在连接音频时的DShow错误%X", hr);
                                MessageBox(NULL,msg,"错误", MB_OK);
                                pTVSS->m_pAudioPin->KillPin();
                                m_needRequest--;
                            }
						}
					}

					if(ppEnum)
						ppEnum->Release();
					if(pin)
						pin->Release();
				}
                

				m_audioavaible = m_videoavaible = FALSE;
/*				if (!anypinOK)
				{
					MessageBox(NULL, "由于一个DShow错误,播放将无法继续,需要停止后重新播放","错误", MB_OK);
				}*/

//                hr = helper.rungraph(pTVSS->GetFG());
                hr = pIMediaControl->Run();
                if(FAILED(hr))
                {
                    char msg[100];
                    wsprintf(msg, "由于DShow错误%X, 无法重新运行", hr);
                    MessageBox(NULL,msg,"错误", MB_OK);
                }
//                CRefTime rf;
//                pTVSS->Run(rf.GetUnits());

				if(pIMediaControl)
					pIMediaControl->Release();
				if(pConfig)
					pConfig->Release();
			}
		}
		//
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	//
	//
	CoUninitialize();
	//
//	_endthreadex( 0 );
	//
	return 0;
}
// filter info
const AMOVIESETUP_MEDIATYPE sudPinTypes =
{
    &MEDIATYPE_Video,            // Major type
    &MEDIASUBTYPE_NULL           // Minor type
};

const AMOVIESETUP_PIN sudPins =
{
    L"Video",                  // Pin string name
    FALSE,                      // Is it rendered
    TRUE,                       // Is it an output
    FALSE,                      // Allowed none
    FALSE,                      // Likewise many
    &CLSID_NULL,                // Connects to filters
    NULL,                       // Connects to pin
    1,                          // Number of types
    &sudPinTypes                // Pin information
};

const AMOVIESETUP_FILTER sudTVStreamSource =
{
    &CLSID_TVStreamSource,    // clsID
    L"Chaos Filter",	      // strName
    MERIT_DO_NOT_USE,         // dwMerit
    1,                        // nPins
    &sudPins                  // lpPin
};

// Global data
CFactoryTemplate g_Templates[] = 
{
    { L"Chaos Filter", &CLSID_TVStreamSource, 
	  CTVStreamSource::CreateInstance, NULL,
	  &sudTVStreamSource },
};

int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);

CTVStreamSource* g_pfilter = NULL;
//
CTVStreamSource::CTVStreamSource(LPUNKNOWN pUnk, HRESULT *phr)
: CSource(NAME("Chaos filter"), pUnk, CLSID_TVStreamSource),
  m_pComm(NULL), m_pFileReader(NULL), 
  m_pFileName(NULL), m_isAudioOnly(FALSE), m_bCanDynamicReconnect(FALSE),
  m_bUpdateComplete(FALSE), m_pVideoPin(NULL), m_pAudioPin(NULL)
{
	m_pAudioRender = NULL;
	m_pVideoRender = NULL;

	// Try calling GetVersionEx using the OSVERSIONINFOEX structure.
	// If that fails, try using the OSVERSIONINFO structure.
	ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
	osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
	if(!GetVersionEx ((OSVERSIONINFO *) &osvi)) {
		osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
		if(!GetVersionEx ((OSVERSIONINFO*) &osvi)) {
			assert(0);
		}
	}

	//
	g_pfilter = this;
	//
	m_hThread = NULL;
	m_iSAddFilterToCache = FALSE;
	//
	//
	SetLastError(0);
	m_bDoRealStop = true;
}
//
CTVStreamSource::~CTVStreamSource()
{	
	if(m_hThread != NULL)
	{
		PostThreadMessage(m_iThreadID, WM_QUIT, 0, NULL);
		if (WAIT_TIMEOUT == WaitForSingleObject(m_hThread, 5000))
		{
			TerminateThread(m_hThread, 0);
		}
	}
	//
	if (NULL != m_pAudioRender)
	{
		m_pAudioRender->Release();
		m_pAudioRender = NULL;
	}
	//
	if (NULL != m_pVideoRender)
	{
		m_pVideoRender->Release();
		m_pVideoRender = NULL;
	}
	//
	SAFE_DELETE(m_pVideoPin);
	SAFE_DELETE(m_pAudioPin);
	//
	if(NULL != m_pComm)
		m_pComm->Stop();
	//
	g_pfilter = NULL;
	//
	SAFE_DELETE(m_pComm);
	SAFE_DELETE(m_pFileReader);
	//
	SAFE_ARRAYDELETE(m_pFileName);

}
//
STDMETHODIMP CTVStreamSource::JoinFilterGraph(IFilterGraph *pGraph, LPCWSTR pName)
{
	CBaseFilter::JoinFilterGraph(pGraph, pName);

	if(pGraph != NULL)
	{
		IGraphConfig* pGCF = GetGCF();
		if(pGCF != NULL)
		{
			m_bCanDynamicReconnect = TRUE;
			pGCF->Release();
		}
	}
    if(m_bCanDynamicReconnect == FALSE)
    {
        MessageBox(NULL, "DirectX版本太低, 请安装9.0以上的版本", "错误", MB_OK);
        return E_FAIL;
    }

//	m_bCanDynamicReconnect = FALSE;

    SAFE_DELETE(m_pVideoPin);
	SAFE_DELETE(m_pAudioPin);
	//
	HRESULT hr;
	HRESULT* phr = &hr;
	m_pVideoPin = new CTVStreamSourceVideoPin(phr, this);
    if (phr)
	{
		*phr = (NULL == m_pVideoPin) ? E_OUTOFMEMORY : S_OK;
	}
	//
	m_pAudioPin = new CTVStreamSourceAudioPin(phr, this);
	//
    if (phr)
	{
		*phr = (NULL == m_pAudioPin) ? E_OUTOFMEMORY : S_OK;
	}
	//
	m_pAudioPin->SetAnotherPin(m_pVideoPin);
	m_pVideoPin->SetAnotherPin(m_pAudioPin);

	if (NULL != pGraph && NULL == m_hThread)
	{
		/*
		IMediaFilter* pIMediaFilter = NULL;
				//
				pGraph->QueryInterface(IID_IMediaFilter, (void**)&pIMediaFilter);
				pIMediaFilter->SetSyncSource(NULL);
				pIMediaFilter->Release();*/
		
//		AddFilterToCache();
		//create thread
		m_hThread = (HANDLE) _beginthreadex( NULL, 0, &ThreadFunc, this, 0, &m_iThreadID );
	}
	//
	return S_OK;
}
//
IBaseFilter* CTVStreamSource::CreateDMO( REFCLSID clsidDMO, REFCLSID catDMO)
{
	// Create the DMO Wrapper filter.
	IBaseFilter *pFilter = NULL;
	HRESULT hr = CoCreateInstance(CLSID_DMOWrapperFilter, 
								  NULL, 
								  CLSCTX_INPROC_SERVER,
								  IID_IBaseFilter, 
								  reinterpret_cast<void**>(&pFilter));
	//

	if (SUCCEEDED(hr)) 
	{
		// Query for IDMOWrapperFilter.
		IDMOWrapperFilter *pDmoWrapper = NULL;
		hr = pFilter->QueryInterface(IID_IDMOWrapperFilter, 
			reinterpret_cast<void**>(&pDmoWrapper));

		if (SUCCEEDED(hr)) 
		{     
			// Initialize the filter.
			hr = pDmoWrapper->Init(clsidDMO, catDMO); 
			pDmoWrapper->Release();

			if (SUCCEEDED(hr)) 
			{
				return pFilter;
			}
		}
		

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -