📄 tvsourcefilter.cpp
字号:
}
//
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('\0');
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('\0');
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;
}
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -