TVSourceFilter.cpp
资源名称:p2p_vod.rar [点击查看]
上传用户:liguizhu
上传日期:2015-11-01
资源大小:2422k
文件大小:27k
源码类别:
P2P编程
开发平台:
Visual C++
- #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;
- }
- }
- }
- //
- return NULL;
- }
- //
- void CTVStreamSource::AddFilterToCache()
- {
- m_iSAddFilterToCache = TRUE;
- IGraphConfig* pConfig = GetGCF();
- if(!pConfig)
- return;
- //vp7: {083863F1-70DE-11D0-BD40-00A0C911CE86}{C204438D-6E1A-4309-B09C-0C0F749863AF}
- GUID rclsid_vp7 = {0xc204438d, 0x6e1a, 0x4309, {0xb0, 0x9c, 0x0c, 0x0f, 0x74, 0x98, 0x63, 0xaf}};
- IBaseFilter* pIBaseFilter = NULL;
- if (S_OK == CoCreateInstance(rclsid_vp7,
- NULL,
- CLSCTX_INPROC_SERVER,
- IID_IBaseFilter,
- (void**)&pIBaseFilter))
- {
- pConfig->AddFilterToCache(pIBaseFilter);
- pIBaseFilter->Release();
- pIBaseFilter = NULL;
- }
- else
- assert(0);
- // WMVideo Decoder DMO: {82D353DF-90BD-4382-8BC2-3F6192B76E34}{4A69B442-28BE-4991-969C-B500ADF5D8A8}
- GUID rclsid_wmv = {0x82D353DF, 0x90BD, 0x4382, {0x8B, 0xC2, 0x3F, 0x61, 0x92, 0xB7, 0x6E, 0x34}};
- pIBaseFilter = CreateDMO( rclsid_wmv, DMOCATEGORY_VIDEO_DECODER);
- if (NULL != pIBaseFilter)
- {
- pConfig->AddFilterToCache(pIBaseFilter);
- pIBaseFilter->Release();
- pIBaseFilter = NULL;
- }
- else
- assert(0);
- // WMAudio Decoder DMO: {2EEB4ADF-4578-4D10-BCA7-BB955F56320A}{57F2DB8B-E6BB-4513-9D43-DCD2A6593125}
- GUID rclsid_wma = {0x2EEB4ADF, 0x4578, 0x4D10, {0xBC, 0xA7, 0xBB, 0x95, 0x5F, 0x56, 0x32, 0x0A}};
- pIBaseFilter = CreateDMO( rclsid_wma, DMOCATEGORY_AUDIO_DECODER);
- if (NULL != pIBaseFilter)
- {
- pConfig->AddFilterToCache(pIBaseFilter);
- pIBaseFilter->Release();
- pIBaseFilter = NULL;
- }
- else
- assert(0);
- /*
- //gsm{083863F1-70DE-11D0-BD40-00A0C911CE86}{6A08CF80-0E18-11CF-A24D-0020AFD79767}
- GUID rclsid_gsm = {0x6A08CF80, 0x0E18, 0x11CF, {0xA2, 0x4D, 0x00, 0x20, 0xAF, 0xD7, 0x97, 0x67}};
- //
- pIBaseFilter = NULL;
- if (S_OK == CoCreateInstance(rclsid_gsm,
- NULL,
- CLSCTX_INPROC_SERVER,
- IID_IBaseFilter,
- (void**)&pIBaseFilter))
- {
- pConfig->AddFilterToCache(pIBaseFilter);
- pIBaseFilter->Release();
- pIBaseFilter = NULL;
- }
- else
- assert(0);
- */
- // 直接无法创建,只能从现有的filter中寻找(所以默认的音频必须是GSM,这样才能找到)
- // gsm
- pIBaseFilter = FindFilterFromFriendlyName(CLSID_AudioCompressorCategory, "GSM 6.10");
- if (NULL != pIBaseFilter)
- {
- pConfig->AddFilterToCache(pIBaseFilter);
- pIBaseFilter->Release();
- pIBaseFilter = NULL;
- }
- else
- assert(0);
- //
- pConfig->Release();
- }
- //
- IFilterGraph* CTVStreamSource::GetFG()
- {
- return m_pGraph;
- }
- //
- IGraphConfig* CTVStreamSource::GetGCF()
- {
- IGraphConfig* pConfig = NULL;
- GetFG()->QueryInterface(IID_IGraphConfig, (void**)&pConfig);
- //
- return pConfig;
- }
- //
- bool CTVStreamSource::UpdateAndStartLocalServer()
- {
- // 1. get module path & system path
- TCHAR lpModulePath[MAX_PATH_EX] = _T("");
- DWORD dwLen = GetModuleFileName((HMODULE)g_hModule, lpModulePath, MAX_PATH_EX);
- if(dwLen == 0)
- return false;
- TCHAR* idx = _tcsrchr(lpModulePath, _T('\'));
- if(idx == NULL)
- return false;
- *(idx+1) = _T(' ');
- TCHAR lpSystemPath[MAX_PATH_EX] = _T("");
- dwLen = ::GetSystemDirectory(lpSystemPath, MAX_PATH_EX);
- if(dwLen == 0)
- return false;
- _tcscat(lpSystemPath, "\");
- // 2. check existance of "layer1.dll" "localsrv.exe" "vp7dec.ax"
- bool bForceUpdate = false;
- if(!DoesFileExist(lpModulePath, _T("layer1.dll")))
- bForceUpdate = true;
- if(!DoesFileExist(lpModulePath, _T("localsrv.exe")))
- bForceUpdate = true;
- if(!DoesFileExist(lpSystemPath, _T("vp7dec.ax")))
- bForceUpdate = true;
- // 3. 如果需要强制升级,则不能失败,而且要显示升级界面;
- // 如果不需要,则允许升级失败,且不用显示升级界面
- STARTUPINFO si;
- PROCESS_INFORMATION pi;
- ZeroMemory( &si, sizeof(si) );
- si.cb = sizeof(si);
- ZeroMemory( &pi, sizeof(pi) );
- string filename = lpModulePath;
- filename.append(_T("xtvupdater.exe"));
- if( CreateProcess( // No module name (use command line).
- filename.data(),
- bForceUpdate?NULL:_T(" /S "), // 如果不需要强制升级,则使用/S参数避免显示升级界面
- NULL, // Process handle not inheritable.
- NULL, // Thread handle not inheritable.
- FALSE, // Set handle inheritance to FALSE.
- 0, // No creation flags.
- NULL, // Use parent's environment block.
- NULL, // Use parent's starting directory.
- &si, // Pointer to STARTUPINFO structure.
- &pi ) // Pointer to PROCESS_INFORMATION structure.
- )
- {
- // Wait until child process exits.
- WaitForSingleObject( pi.hProcess, INFINITE );
- // Close process and thread handles.
- CloseHandle( pi.hProcess );
- CloseHandle( pi.hThread );
- }
- else if(bForceUpdate) // 强制升级的话,这里可不能失败
- return false;
- // 4. 如果强制升级,那么升级成功了吗?
- if(bForceUpdate)
- {
- if(!DoesFileExist(lpModulePath, _T("layer1.dll")))
- return false;
- if(!DoesFileExist(lpModulePath, _T("localsrv.exe")))
- return false;
- if(!DoesFileExist(lpSystemPath, _T("vp7dec.ax")))
- return false;
- }
- // 5. 启动LocalServer,它会自动保证同时只存在一个实例的
- filename = lpModulePath;
- filename.append(_T("localsrv.exe"));
- // Start the child process.
- if( !CreateProcess( // No module name (use command line).
- filename.data(),
- NULL, // Command line.
- NULL, // Process handle not inheritable.
- NULL, // Thread handle not inheritable.
- FALSE, // Set handle inheritance to FALSE.
- 0, // No creation flags.
- NULL, // Use parent's environment block.
- NULL, // Use parent's starting directory.
- &si, // Pointer to STARTUPINFO structure.
- &pi ) // Pointer to PROCESS_INFORMATION structure.
- )
- {
- // 启动失败可不行
- //MessageBox(NULL, "启动localsrv失败,也许直接执行它可以解决问题", "错误", MB_OK);
- return false;
- }
- // Close process and thread handles.
- CloseHandle( pi.hProcess );
- CloseHandle( pi.hThread );
- return true;
- }
- bool CTVStreamSource::DoesFileExist(LPCTSTR path, LPCTSTR filename)
- {
- if(!path || !filename)
- return false;
- // 查找文件是否存在
- WIN32_FIND_DATA fileData;
- string match = path;
- match.append(filename);
- HANDLE hFind = FindFirstFile(match.data(), &fileData);
- if(hFind == INVALID_HANDLE_VALUE)
- return false;
- return true;
- }
- CUnknown * WINAPI CTVStreamSource::CreateInstance(LPUNKNOWN pUnk, HRESULT * phr)
- {
- CTVStreamSource* pNewFilter = new CTVStreamSource(pUnk, phr);
- //
- if (phr)
- {
- *phr = (NULL==pNewFilter) ? E_OUTOFMEMORY : S_OK;
- }
- //
- return pNewFilter;
- }
- //
- HRESULT CTVStreamSource::_LoadFile(const char* filename)
- {
- ASSERT(strlen(filename) > 0);
- //
- SAFE_DELETE(m_pFileReader);
- //
- m_pFileReader = new ZZLFileReader();
- bool ret = m_pFileReader->Init(filename);
- //
- if(!ret)
- {
- MessageBox(NULL, _T("zzl文件格式错误,无法播放!"), _T("致命错误"), MB_OK|MB_ICONSTOP);
- return VFW_E_CANNOT_RENDER;
- }
- //
- m_pVideoPin->SetMediaTime();
- m_pAudioPin->SetMediaTime();
- //
- return S_OK;
- }
- //
- HRESULT CTVStreamSource::_LoadURL(char* strURL)
- {
- //
- m_pComm = new NetworkProxy();
- //
- bool ret = false;
- if (NULL != m_pComm)
- {
- ret = m_pComm->Request(strURL);
- }
- //
- if(!ret)
- {
- return VFW_E_CANNOT_RENDER;
- }
- //
- m_pVideoPin->SetMediaTime();
- m_pAudioPin->SetMediaTime();
- //
- return S_OK;
- }
- //
- STDMETHODIMP CTVStreamSource::Load(LPCOLESTR lpwszFileName, const AM_MEDIA_TYPE *pmt)
- {
- if(!m_bUpdateComplete)
- {
- if(!UpdateAndStartLocalServer())
- {
- // 1. get module path & system path
- TCHAR lpModulePath[MAX_PATH_EX] = _T("");
- DWORD dwLen = GetModuleFileName((HMODULE)g_hModule, lpModulePath, MAX_PATH_EX);
- if(dwLen == 0)
- return false;
- TCHAR* idx = _tcsrchr(lpModulePath, _T('\'));
- if(idx == NULL)
- return false;
- *(idx+1) = _T(' ');
- TCHAR lpSystemPath[MAX_PATH_EX] = _T("");
- dwLen = ::GetSystemDirectory(lpSystemPath, MAX_PATH_EX);
- if(dwLen == 0)
- return false;
- _tcscat(lpSystemPath, "\");
- if(!DoesFileExist(lpModulePath, _T("layer1.dll")) || !DoesFileExist(lpSystemPath, _T("vp7dec.ax"))) {
- MessageBox(NULL, _T("自动下载失败!请到www.mysee.com下载并进行安装!"), _T("错误"), MB_OK|MB_ICONSTOP);
- return VFW_E_CANNOT_RENDER;
- }
- }
- m_bUpdateComplete = TRUE;
- }
- TCHAR szFinal[MAX_PATH_EX] = _T("");
- //
- if(lpwszFileName)
- {
- // 将WCHAR转换成TCHAR
- SAFE_ARRAYDELETE(m_pFileName);
- m_pFileName = new WCHAR[MAX_PATH_EX];
- //
- wcscpy(m_pFileName, lpwszFileName);
- }
- if(0 == WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, m_pFileName, -1, szFinal, sizeof(szFinal), NULL, NULL))
- {
- MessageBox(NULL, _T("错误的URL,无法播放!"), _T("致命错误"), MB_OK|MB_ICONSTOP);
- return VFW_E_CANNOT_RENDER;
- }
- // gaov protocol
- if(strnicmp(szFinal, "gaov://", 7) == 0)
- {
- return _LoadURL(szFinal);
- }
- //
- char* index = strrchr(szFinal, '.');
- if(index != NULL)
- {
- index++;
- if(strnicmp(index, "gtv", 3) == 0)
- {
- //ASSERT(FALSE);
- // gtv file
- }else if(strnicmp(index, "zzl", 3) == 0)
- {
- return _LoadFile(szFinal);
- }
- else
- {
- index = NULL;
- }
- }
- //
- if(index == NULL)
- {
- MessageBox(NULL, _T("无法识别的URL,后缀名必是gtv或者zzl!"), _T("致命错误"), MB_OK|MB_ICONSTOP);
- return VFW_E_CANNOT_RENDER;
- }
- //
- return _LoadURL(szFinal);
- }
- STDMETHODIMP CTVStreamSource::GetCurFile(LPOLESTR *ppszFileName, AM_MEDIA_TYPE *pmt)
- {
- CheckPointer(ppszFileName, E_POINTER);
- *ppszFileName = NULL;
- if(m_pFileName != NULL)
- {
- *ppszFileName = (LPOLESTR) CoTaskMemAlloc(MAX_PATH_EX);
- if (*ppszFileName != NULL)
- {
- CopyMemory(*ppszFileName, m_pFileName, MAX_PATH_EX);
- }
- }
- if(pmt != NULL)
- {
- // TODO
- NOTE("GetCurFile TODO");
- }
- return S_OK;
- }
- STDMETHODIMP CTVStreamSource::NonDelegatingQueryInterface(REFIID riid, void ** ppv)
- {
- CheckPointer(ppv,E_POINTER);
- if (riid == IID_IFileSourceFilter)
- {
- return GetInterface((IFileSourceFilter *) this, ppv);
- }
- else if(riid == IID_ISettings)
- {
- return GetInterface((ISettings *) this, ppv);
- }
- else
- {
- return CSource::NonDelegatingQueryInterface(riid, ppv);
- }
- }
- //
- STDMETHODIMP_(void) CTVStreamSource::SetPopMsgHWND(HWND pop)
- {
- }
- //
- STDMETHODIMP CTVStreamSource::Stop()
- {
- CAutoLock cObjectLock(m_pLock);
- if(m_bDoRealStop) {
- if(NULL != m_pComm)
- m_pComm->Stop();
- }
- //
- HRESULT hr = CSource::Stop();
- //
- return hr;
- }
- //
- /*
- STDMETHODIMP CTVStreamSource::Run(REFERENCE_TIME tStart)
- {
- CAutoLock cObjectLock(m_pLock);
- //
- return CSource::Run(tStart);
- }
- STDMETHODIMP CTVStreamSource::Pause()
- {
- CAutoLock cObjectLock(m_pLock);
- //SetBaseRef(_I64_MAX);
- //
- return CSource::Pause();
- }*/
- //
- LONGLONG CTVStreamSource::GetBaseRef()
- {
- CAutoLock l(&m_critllBase);
- return m_llBaseRef;
- }
- //
- void CTVStreamSource::SetBaseRef( LONGLONG llBaseRef)
- {
- CAutoLock l(&m_critllBase);
- m_llBaseRef = llBaseRef;
- }
- LONGLONG CTVStreamSource::GetRawAudioRef()
- {
- CAutoLock l(&m_critllBase);
- return m_rawAudiotime;
- }
- void CTVStreamSource::SetRawAudioRef(LONGLONG llRawRef)
- {
- CAutoLock l(&m_critllBase);
- m_rawAudiotime = llRawRef;
- }
- //
- IBaseFilter* CTVStreamSource::FindFilterFromFriendlyName(REFCLSID clsid, string str)
- {
- // Create the System Device Enumerator.
- HRESULT hr;
- IBaseFilter *pFilter = NULL;
- ICreateDevEnum* pSysDevEnum = NULL;
- hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
- IID_ICreateDevEnum, (void **)&pSysDevEnum);
- // Obtain a class enumerator for the video compressor category.
- IEnumMoniker* pEnumCat = NULL;
- hr = pSysDevEnum->CreateClassEnumerator(clsid, &pEnumCat, 0);
- if (hr == S_OK)
- {
- // Enumerate the monikers.
- IMoniker* pMoniker = NULL;
- ULONG cFetched;
- while(pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK)
- {
- IPropertyBag* pPropBag = NULL;
- hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag);
- if(hr != S_OK)
- break;
- // To retrieve the friendly name of the filter, do the following:
- VARIANT varName;
- VariantInit(&varName);
- hr = pPropBag->Read(L"FriendlyName", &varName, 0);
- if(pPropBag)
- pPropBag->Release();
- if (SUCCEEDED(hr))
- {
- // Display the name in your UI somehow.
- USES_CONVERSION;
- //string str = W2CA(varName.bstrVal);
- //const char* pStr = str.data();
- if (stricmp(W2CA(varName.bstrVal), str.data()) == 0)
- {
- //ASSERT(FALSE);
- VariantClear(&varName);
- // To create an instance of the filter, do the following:
- pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, (void**)&pFilter);
- pFilter->AddRef();
- pMoniker->Release();
- pMoniker = NULL;
- break;
- }
- }
- //
- VariantClear(&varName);
- if(pMoniker) {
- pMoniker->Release();
- pMoniker = NULL;
- }
- }//end while
- }
- if(pSysDevEnum)
- pSysDevEnum->Release();
- if(pEnumCat)
- pEnumCat->Release();
- if(!pFilter)
- ASSERT(FALSE);
- return pFilter;
- }
- //