TVSourceFilter.cpp
上传用户:liguizhu
上传日期:2015-11-01
资源大小:2422k
文件大小:27k
源码类别:

P2P编程

开发平台:

Visual C++

  1. #include "stdafx.h"
  2. #include <process.h>
  3. #include <Dmoreg.h>
  4. #include <dmodshow.h>
  5. #include <atlconv.h>
  6. #include "networkproxy.h"
  7. #include "graphrebuildhelper.h"
  8. //
  9. extern HANDLE g_hModule;
  10. HRESULT CTVStreamSource::EnumFilters (IFilterGraph *pGraph) 
  11. {
  12. IEnumFilters* pEnum  = NULL;
  13. IBaseFilter*  pFilter = NULL;;
  14. ULONG cFetched;
  15. HRESULT hr = pGraph->EnumFilters(&pEnum);
  16. if (FAILED(hr))
  17. return hr;
  18. //
  19. while(pEnum->Next(1, &pFilter, &cFetched) == S_OK)
  20. {
  21. FILTER_INFO FilterInfo;
  22. hr = pFilter->QueryFilterInfo(&FilterInfo);
  23. if (FAILED(hr))
  24. {
  25. ASSERT(FALSE);
  26. // Maybe the next one will work.
  27. continue;  
  28. }
  29. //
  30. GUID guid;
  31. HRESULT hr = pFilter->GetClassID(&guid);
  32. if (hr == S_OK)
  33. {
  34. if (CLSID_DSoundRender == guid ||
  35. CLSID_AudioRender == guid )
  36. {
  37. if (NULL != m_pAudioRender)
  38. {
  39. m_pAudioRender->Release();
  40. m_pAudioRender = NULL;
  41. }
  42. //
  43. m_pAudioRender = pFilter;
  44. pFilter->AddRef();
  45. }
  46. //
  47. if (CLSID_VideoMixingRenderer  == guid ||
  48. CLSID_VideoRendererDefault == guid||
  49. CLSID_VideoRenderer        == guid)
  50. {
  51. if (NULL != m_pVideoRender)
  52. {
  53. m_pVideoRender->Release();
  54. m_pVideoRender = NULL;
  55. }
  56. //
  57. m_pVideoRender = pFilter;
  58. pFilter->AddRef();
  59. }
  60. }
  61. // The FILTER_INFO structure holds a pointer to the Filter Graph
  62. // Manager, with a reference count that must be released.
  63. if (FilterInfo.pGraph != NULL)
  64. {
  65. FilterInfo.pGraph->Release();
  66. }
  67. pFilter->Release();
  68. }
  69. //
  70. pEnum->Release();
  71. return S_OK;
  72. }
  73. //
  74. unsigned __stdcall CTVStreamSource::ThreadFunc( void* pArguments )
  75. {
  76. ASSERT(NULL != pArguments);
  77. CTVStreamSource* pTVSS = (CTVStreamSource*)pArguments;
  78. //
  79. CoInitialize(NULL);
  80. //
  81. MSG msg;
  82. WORD m_accRequest = 0; //累积的请求数目
  83. WORD m_needRequest = 2;
  84. BOOL m_videoavaible = FALSE;
  85. BOOL m_audioavaible = FALSE;
  86. while(GetMessage(&msg, NULL, 0, 0))
  87. {
  88.         if(msg.message == MEDIA_ERROR_STOP)
  89.         {
  90.             pTVSS->m_pAudioPin->KillPin();
  91.             pTVSS->m_pVideoPin->KillPin();
  92.             IGraphConfig* pConfig = pTVSS->GetGCF();
  93.   if(!pConfig) {
  94. assert(0);
  95. continue;
  96. }
  97. IMediaControl* pIMediaControl = NULL;
  98. pConfig->QueryInterface(IID_IMediaControl, (void**)&pIMediaControl);
  99. //错误信息因此停止图。
  100. HRESULT hr = pIMediaControl->Stop();
  101.             pIMediaControl->Release();
  102.         }
  103. else if (msg.message == MEDIATYPE_CHANGED)
  104. {
  105. m_accRequest++;
  106. if(LOWORD(msg.wParam) == 0)
  107. m_audioavaible = HIWORD(msg.wParam) == 1? TRUE:FALSE;
  108. else
  109. m_videoavaible = HIWORD(msg.wParam) == 1? TRUE:FALSE;
  110.             if(m_accRequest < m_needRequest)    //如果需要等待,我们要开始一个flush操作,以避免另一个pin卡死在deliver上面!
  111.             {
  112.                 HRESULT hr;
  113.                 if(m_audioavaible == FALSE)
  114.                 {
  115.                     hr = pTVSS->m_pAudioPin->BeginFlushData();
  116.                     assert(!FAILED(hr));
  117.                 }
  118.                 if(m_videoavaible == FALSE)
  119.                 {
  120.                     hr = pTVSS->m_pVideoPin->BeginFlushData();
  121.                     assert(!FAILED(hr));
  122.                 }
  123.             }
  124.             else //累积请求数目足够,开始动态重连
  125. {
  126. m_needRequest = m_accRequest = 0;
  127. if(m_audioavaible)
  128. m_needRequest++;
  129. if(m_videoavaible)
  130. m_needRequest++;
  131.                 //flush停止
  132.                 pTVSS->m_pAudioPin->EndFlushData();
  133.                 pTVSS->m_pVideoPin->EndFlushData();
  134.                 //预先加入filter到cache里面以提高重连的成功率
  135. /*                pTVSS->AddFilterToCache();
  136.                 GraphRebuildHelper helper;
  137. //                IMediaControl* pIMediaControl = NULL;
  138. // pConfig->QueryInterface(IID_IMediaControl, (void**)&pIMediaControl);
  139.                 pTVSS->m_bDoRealStop = false;
  140.                 HRESULT hr = helper.stopgraph(pTVSS->GetFG());
  141.                 pTVSS->m_bDoRealStop = true;
  142.                 BOOL anypinOK = TRUE;
  143.                 if(m_videoavaible == TRUE)
  144.                 {
  145.                     hr = helper.startbuilding(pTVSS->GetFG(), pTVSS->m_pVideoPin, false);
  146.                     if(FAILED(hr))
  147.                     {
  148.                         char msg[100];
  149.                         wsprintf(msg, "在连接视频时的DShow错误%X", hr);
  150.                         MessageBox(NULL,msg,"错误", MB_OK);
  151.                         anypinOK = FALSE;
  152.                         pTVSS->m_pVideoPin->KillPin();
  153.                         m_needRequest--;
  154.                     }
  155.                 }
  156.                 if(m_audioavaible == TRUE)
  157.                 {
  158.                     hr = helper.startbuilding(pTVSS->GetFG(), pTVSS->m_pAudioPin, true);
  159.                     if(FAILED(hr))
  160.                     {
  161.                         char msg[100];
  162.                         wsprintf(msg, "在连接音频时的DShow错误%X", hr);
  163.                         MessageBox(NULL,msg,"错误", MB_OK);
  164.                         anypinOK = FALSE;
  165.                         pTVSS->m_pAudioPin->KillPin();
  166.                         m_needRequest--;
  167.                     }
  168.                 }*/
  169.                 
  170. IGraphConfig* pConfig = pTVSS->GetGCF();
  171. if(!pConfig) {
  172. assert(0);
  173. continue;
  174. }
  175.                 
  176.                 //先把Audio和Video Renderer Filter枚举到
  177. pTVSS->EnumFilters (pTVSS->GetFG());
  178. //
  179. IMediaControl* pIMediaControl = NULL;
  180. pConfig->QueryInterface(IID_IMediaControl, (void**)&pIMediaControl);
  181. //动态重连前,先把图stop or pause
  182. pTVSS->m_bDoRealStop = false;
  183. HRESULT hr = pIMediaControl->Stop();
  184. //                HRESULT hr = pTVSS->Stop();
  185. assert(hr == S_OK);
  186. pTVSS->m_bDoRealStop = true;
  187.                 Sleep(500);
  188. //
  189.   
  190. if (FALSE == pTVSS->m_iSAddFilterToCache)
  191. pTVSS->AddFilterToCache();
  192. BOOL anypinOK = TRUE;
  193. if(m_audioavaible == TRUE)
  194. {
  195. //
  196. IPin* pin = NULL;
  197. ULONG cFetched = 0;
  198. //
  199. IEnumPins* ppEnum = NULL;
  200. //
  201. if (S_OK == pTVSS->m_pAudioRender->EnumPins(&ppEnum))
  202. {
  203. ppEnum->Reset();
  204. ppEnum->Next(1, &pin, &cFetched);
  205. //
  206. HRESULT hr = S_FALSE;
  207. const AM_MEDIA_TYPE *pmtFirstConnection = pTVSS->m_pAudioPin->GetType();
  208. hr = pConfig->Reconnect(pTVSS->m_pAudioPin,
  209. pin, 
  210. pmtFirstConnection,
  211. NULL,
  212. NULL, 
  213. AM_GRAPH_CONFIG_RECONNECT_CACHE_REMOVED_FILTERS |
  214. AM_GRAPH_CONFIG_RECONNECT_USE_ONLY_CACHED_FILTERS);
  215. //
  216. if(FAILED(hr))
  217.                         {
  218. anypinOK = FALSE;
  219.                             char msg[100];
  220.                             wsprintf(msg, "在连接音频时的DShow错误%X", hr);
  221.                             MessageBox(NULL,msg,"错误", MB_OK);
  222.                             pTVSS->m_pAudioPin->KillPin();
  223.                             m_needRequest--;
  224.                         }
  225. }
  226. if(ppEnum)
  227. ppEnum->Release();
  228. if(pin)
  229. pin->Release();
  230. }
  231. if(m_videoavaible == TRUE)
  232. {
  233. //
  234. IPin* pin = NULL;
  235. ULONG cFetched = 0;
  236. //
  237. IEnumPins* ppEnum = NULL;
  238. //
  239. if (S_OK == pTVSS->m_pVideoRender->EnumPins(&ppEnum))
  240. {
  241. ppEnum->Reset();
  242. if (S_OK == ppEnum->Next(1, &pin, &cFetched))
  243. {
  244. hr = S_FALSE;
  245. const AM_MEDIA_TYPE *pmtFirstConnection = pTVSS->m_pVideoPin->GetType();
  246. hr= pConfig->Reconnect((IPin*)(pTVSS->m_pVideoPin),
  247. pin,
  248. pmtFirstConnection,
  249. NULL,
  250. NULL,
  251. AM_GRAPH_CONFIG_RECONNECT_CACHE_REMOVED_FILTERS |
  252. AM_GRAPH_CONFIG_RECONNECT_USE_ONLY_CACHED_FILTERS);
  253. if(FAILED(hr))
  254.                             {
  255. anypinOK = FALSE;
  256.                                 char msg[100];
  257.                                 wsprintf(msg, "在连接音频时的DShow错误%X", hr);
  258.                                 MessageBox(NULL,msg,"错误", MB_OK);
  259.                                 pTVSS->m_pAudioPin->KillPin();
  260.                                 m_needRequest--;
  261.                             }
  262. }
  263. }
  264. if(ppEnum)
  265. ppEnum->Release();
  266. if(pin)
  267. pin->Release();
  268. }
  269.                 
  270. m_audioavaible = m_videoavaible = FALSE;
  271. /* if (!anypinOK)
  272. {
  273. MessageBox(NULL, "由于一个DShow错误,播放将无法继续,需要停止后重新播放","错误", MB_OK);
  274. }*/
  275. //                hr = helper.rungraph(pTVSS->GetFG());
  276.                 hr = pIMediaControl->Run();
  277.                 if(FAILED(hr))
  278.                 {
  279.                     char msg[100];
  280.                     wsprintf(msg, "由于DShow错误%X, 无法重新运行", hr);
  281.                     MessageBox(NULL,msg,"错误", MB_OK);
  282.                 }
  283. //                CRefTime rf;
  284. //                pTVSS->Run(rf.GetUnits());
  285. if(pIMediaControl)
  286. pIMediaControl->Release();
  287. if(pConfig)
  288. pConfig->Release();
  289. }
  290. }
  291. //
  292. TranslateMessage(&msg);
  293. DispatchMessage(&msg);
  294. }
  295. //
  296. //
  297. CoUninitialize();
  298. //
  299. // _endthreadex( 0 );
  300. //
  301. return 0;
  302. }
  303. // filter info
  304. const AMOVIESETUP_MEDIATYPE sudPinTypes =
  305. {
  306.     &MEDIATYPE_Video,            // Major type
  307.     &MEDIASUBTYPE_NULL           // Minor type
  308. };
  309. const AMOVIESETUP_PIN sudPins =
  310. {
  311.     L"Video",                  // Pin string name
  312.     FALSE,                      // Is it rendered
  313.     TRUE,                       // Is it an output
  314.     FALSE,                      // Allowed none
  315.     FALSE,                      // Likewise many
  316.     &CLSID_NULL,                // Connects to filters
  317.     NULL,                       // Connects to pin
  318.     1,                          // Number of types
  319.     &sudPinTypes                // Pin information
  320. };
  321. const AMOVIESETUP_FILTER sudTVStreamSource =
  322. {
  323.     &CLSID_TVStreamSource,    // clsID
  324.     L"Chaos Filter",       // strName
  325.     MERIT_DO_NOT_USE,         // dwMerit
  326.     1,                        // nPins
  327.     &sudPins                  // lpPin
  328. };
  329. // Global data
  330. CFactoryTemplate g_Templates[] = 
  331. {
  332.     { L"Chaos Filter", &CLSID_TVStreamSource, 
  333.   CTVStreamSource::CreateInstance, NULL,
  334.   &sudTVStreamSource },
  335. };
  336. int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
  337. CTVStreamSource* g_pfilter = NULL;
  338. //
  339. CTVStreamSource::CTVStreamSource(LPUNKNOWN pUnk, HRESULT *phr)
  340. : CSource(NAME("Chaos filter"), pUnk, CLSID_TVStreamSource),
  341.   m_pComm(NULL), m_pFileReader(NULL), 
  342.   m_pFileName(NULL), m_isAudioOnly(FALSE), m_bCanDynamicReconnect(FALSE),
  343.   m_bUpdateComplete(FALSE), m_pVideoPin(NULL), m_pAudioPin(NULL)
  344. {
  345. m_pAudioRender = NULL;
  346. m_pVideoRender = NULL;
  347. // Try calling GetVersionEx using the OSVERSIONINFOEX structure.
  348. // If that fails, try using the OSVERSIONINFO structure.
  349. ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
  350. osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  351. if(!GetVersionEx ((OSVERSIONINFO *) &osvi)) {
  352. osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
  353. if(!GetVersionEx ((OSVERSIONINFO*) &osvi)) {
  354. assert(0);
  355. }
  356. }
  357. //
  358. g_pfilter = this;
  359. //
  360. m_hThread = NULL;
  361. m_iSAddFilterToCache = FALSE;
  362. //
  363. //
  364. SetLastError(0);
  365. m_bDoRealStop = true;
  366. }
  367. //
  368. CTVStreamSource::~CTVStreamSource()
  369. {
  370. if(m_hThread != NULL)
  371. {
  372. PostThreadMessage(m_iThreadID, WM_QUIT, 0, NULL);
  373. if (WAIT_TIMEOUT == WaitForSingleObject(m_hThread, 5000))
  374. {
  375. TerminateThread(m_hThread, 0);
  376. }
  377. }
  378. //
  379. if (NULL != m_pAudioRender)
  380. {
  381. m_pAudioRender->Release();
  382. m_pAudioRender = NULL;
  383. }
  384. //
  385. if (NULL != m_pVideoRender)
  386. {
  387. m_pVideoRender->Release();
  388. m_pVideoRender = NULL;
  389. }
  390. //
  391. SAFE_DELETE(m_pVideoPin);
  392. SAFE_DELETE(m_pAudioPin);
  393. //
  394. if(NULL != m_pComm)
  395. m_pComm->Stop();
  396. //
  397. g_pfilter = NULL;
  398. //
  399. SAFE_DELETE(m_pComm);
  400. SAFE_DELETE(m_pFileReader);
  401. //
  402. SAFE_ARRAYDELETE(m_pFileName);
  403. }
  404. //
  405. STDMETHODIMP CTVStreamSource::JoinFilterGraph(IFilterGraph *pGraph, LPCWSTR pName)
  406. {
  407. CBaseFilter::JoinFilterGraph(pGraph, pName);
  408. if(pGraph != NULL)
  409. {
  410. IGraphConfig* pGCF = GetGCF();
  411. if(pGCF != NULL)
  412. {
  413. m_bCanDynamicReconnect = TRUE;
  414. pGCF->Release();
  415. }
  416. }
  417.     if(m_bCanDynamicReconnect == FALSE)
  418.     {
  419.         MessageBox(NULL, "DirectX版本太低, 请安装9.0以上的版本", "错误", MB_OK);
  420.         return E_FAIL;
  421.     }
  422. // m_bCanDynamicReconnect = FALSE;
  423.     SAFE_DELETE(m_pVideoPin);
  424. SAFE_DELETE(m_pAudioPin);
  425. //
  426. HRESULT hr;
  427. HRESULT* phr = &hr;
  428. m_pVideoPin = new CTVStreamSourceVideoPin(phr, this);
  429.     if (phr)
  430. {
  431. *phr = (NULL == m_pVideoPin) ? E_OUTOFMEMORY : S_OK;
  432. }
  433. //
  434. m_pAudioPin = new CTVStreamSourceAudioPin(phr, this);
  435. //
  436.     if (phr)
  437. {
  438. *phr = (NULL == m_pAudioPin) ? E_OUTOFMEMORY : S_OK;
  439. }
  440. //
  441. m_pAudioPin->SetAnotherPin(m_pVideoPin);
  442. m_pVideoPin->SetAnotherPin(m_pAudioPin);
  443. if (NULL != pGraph && NULL == m_hThread)
  444. {
  445. /*
  446. IMediaFilter* pIMediaFilter = NULL;
  447. //
  448. pGraph->QueryInterface(IID_IMediaFilter, (void**)&pIMediaFilter);
  449. pIMediaFilter->SetSyncSource(NULL);
  450. pIMediaFilter->Release();*/
  451. // AddFilterToCache();
  452. //create thread
  453. m_hThread = (HANDLE) _beginthreadex( NULL, 0, &ThreadFunc, this, 0, &m_iThreadID );
  454. }
  455. //
  456. return S_OK;
  457. }
  458. //
  459. IBaseFilter* CTVStreamSource::CreateDMO( REFCLSID clsidDMO, REFCLSID catDMO)
  460. {
  461. // Create the DMO Wrapper filter.
  462. IBaseFilter *pFilter = NULL;
  463. HRESULT hr = CoCreateInstance(CLSID_DMOWrapperFilter, 
  464.   NULL, 
  465.   CLSCTX_INPROC_SERVER,
  466.   IID_IBaseFilter, 
  467.   reinterpret_cast<void**>(&pFilter));
  468. //
  469. if (SUCCEEDED(hr)) 
  470. {
  471. // Query for IDMOWrapperFilter.
  472. IDMOWrapperFilter *pDmoWrapper = NULL;
  473. hr = pFilter->QueryInterface(IID_IDMOWrapperFilter, 
  474. reinterpret_cast<void**>(&pDmoWrapper));
  475. if (SUCCEEDED(hr)) 
  476. {     
  477. // Initialize the filter.
  478. hr = pDmoWrapper->Init(clsidDMO, catDMO); 
  479. pDmoWrapper->Release();
  480. if (SUCCEEDED(hr)) 
  481. {
  482. return pFilter;
  483. }
  484. }
  485. }
  486. //
  487. return NULL;
  488. }
  489. //
  490. void CTVStreamSource::AddFilterToCache()
  491. {
  492. m_iSAddFilterToCache = TRUE;
  493. IGraphConfig* pConfig = GetGCF();
  494. if(!pConfig)
  495. return;
  496. //vp7: {083863F1-70DE-11D0-BD40-00A0C911CE86}{C204438D-6E1A-4309-B09C-0C0F749863AF}
  497. GUID rclsid_vp7 = {0xc204438d, 0x6e1a, 0x4309, {0xb0, 0x9c, 0x0c, 0x0f, 0x74, 0x98, 0x63, 0xaf}};
  498. IBaseFilter* pIBaseFilter = NULL;
  499. if (S_OK == CoCreateInstance(rclsid_vp7, 
  500.  NULL,
  501.  CLSCTX_INPROC_SERVER,
  502.  IID_IBaseFilter,
  503.  (void**)&pIBaseFilter))
  504. {
  505. pConfig->AddFilterToCache(pIBaseFilter);
  506. pIBaseFilter->Release();
  507. pIBaseFilter = NULL;
  508. }
  509. else
  510. assert(0);
  511. // WMVideo Decoder DMO: {82D353DF-90BD-4382-8BC2-3F6192B76E34}{4A69B442-28BE-4991-969C-B500ADF5D8A8}
  512. GUID rclsid_wmv = {0x82D353DF, 0x90BD, 0x4382, {0x8B, 0xC2, 0x3F, 0x61, 0x92, 0xB7, 0x6E, 0x34}};
  513. pIBaseFilter = CreateDMO( rclsid_wmv, DMOCATEGORY_VIDEO_DECODER);
  514. if (NULL != pIBaseFilter)
  515. {
  516. pConfig->AddFilterToCache(pIBaseFilter);
  517. pIBaseFilter->Release();
  518. pIBaseFilter = NULL;
  519. }
  520. else
  521. assert(0);
  522. // WMAudio Decoder DMO: {2EEB4ADF-4578-4D10-BCA7-BB955F56320A}{57F2DB8B-E6BB-4513-9D43-DCD2A6593125}
  523. GUID rclsid_wma = {0x2EEB4ADF, 0x4578, 0x4D10, {0xBC, 0xA7, 0xBB, 0x95, 0x5F, 0x56, 0x32, 0x0A}};
  524. pIBaseFilter = CreateDMO( rclsid_wma, DMOCATEGORY_AUDIO_DECODER);
  525. if (NULL != pIBaseFilter)
  526. {
  527. pConfig->AddFilterToCache(pIBaseFilter);
  528. pIBaseFilter->Release();
  529. pIBaseFilter = NULL;
  530. }
  531. else
  532. assert(0);
  533. /*
  534. //gsm{083863F1-70DE-11D0-BD40-00A0C911CE86}{6A08CF80-0E18-11CF-A24D-0020AFD79767}
  535. GUID rclsid_gsm = {0x6A08CF80, 0x0E18, 0x11CF, {0xA2, 0x4D, 0x00, 0x20, 0xAF, 0xD7, 0x97, 0x67}};
  536. //
  537. pIBaseFilter = NULL;
  538. if (S_OK == CoCreateInstance(rclsid_gsm, 
  539.  NULL,
  540.  CLSCTX_INPROC_SERVER,
  541.  IID_IBaseFilter,
  542.  (void**)&pIBaseFilter))
  543. {
  544. pConfig->AddFilterToCache(pIBaseFilter);
  545. pIBaseFilter->Release();
  546. pIBaseFilter = NULL;
  547. }
  548. else
  549. assert(0);
  550. */
  551. // 直接无法创建,只能从现有的filter中寻找(所以默认的音频必须是GSM,这样才能找到)
  552. // gsm
  553. pIBaseFilter = FindFilterFromFriendlyName(CLSID_AudioCompressorCategory, "GSM 6.10");
  554.     if (NULL != pIBaseFilter) 
  555. {
  556. pConfig->AddFilterToCache(pIBaseFilter);
  557. pIBaseFilter->Release();
  558. pIBaseFilter = NULL;
  559. }
  560. else
  561. assert(0);
  562. //
  563. pConfig->Release();
  564. }
  565. //
  566. IFilterGraph* CTVStreamSource::GetFG()
  567. {
  568. return m_pGraph;
  569. }
  570. //
  571. IGraphConfig* CTVStreamSource::GetGCF()
  572. {
  573. IGraphConfig* pConfig = NULL;
  574. GetFG()->QueryInterface(IID_IGraphConfig, (void**)&pConfig);
  575. //
  576. return pConfig;
  577. }
  578. //
  579. bool CTVStreamSource::UpdateAndStartLocalServer()
  580. {
  581. // 1. get module path & system path
  582. TCHAR lpModulePath[MAX_PATH_EX] = _T("");
  583. DWORD dwLen = GetModuleFileName((HMODULE)g_hModule, lpModulePath, MAX_PATH_EX);
  584. if(dwLen == 0)
  585. return false;
  586. TCHAR* idx = _tcsrchr(lpModulePath, _T('\'));
  587. if(idx == NULL)
  588. return false;
  589. *(idx+1) = _T('');
  590. TCHAR lpSystemPath[MAX_PATH_EX] = _T("");
  591. dwLen = ::GetSystemDirectory(lpSystemPath, MAX_PATH_EX);
  592. if(dwLen == 0)
  593. return false;
  594. _tcscat(lpSystemPath, "\");
  595. // 2. check existance of "layer1.dll" "localsrv.exe" "vp7dec.ax"
  596. bool bForceUpdate = false;
  597. if(!DoesFileExist(lpModulePath, _T("layer1.dll")))
  598. bForceUpdate = true;
  599. if(!DoesFileExist(lpModulePath, _T("localsrv.exe")))
  600. bForceUpdate = true;
  601. if(!DoesFileExist(lpSystemPath, _T("vp7dec.ax")))
  602. bForceUpdate = true;
  603. // 3. 如果需要强制升级,则不能失败,而且要显示升级界面;
  604. //    如果不需要,则允许升级失败,且不用显示升级界面
  605. STARTUPINFO si;
  606. PROCESS_INFORMATION pi;
  607. ZeroMemory( &si, sizeof(si) );
  608. si.cb = sizeof(si);
  609. ZeroMemory( &pi, sizeof(pi) );
  610. string filename = lpModulePath;
  611. filename.append(_T("xtvupdater.exe"));
  612. if( CreateProcess(  // No module name (use command line). 
  613. filename.data(), 
  614. bForceUpdate?NULL:_T(" /S "), // 如果不需要强制升级,则使用/S参数避免显示升级界面
  615. NULL,             // Process handle not inheritable. 
  616. NULL,             // Thread handle not inheritable. 
  617. FALSE,            // Set handle inheritance to FALSE. 
  618. 0,                // No creation flags. 
  619. NULL,             // Use parent's environment block. 
  620. NULL,             // Use parent's starting directory. 
  621. &si,              // Pointer to STARTUPINFO structure.
  622. &pi )             // Pointer to PROCESS_INFORMATION structure.
  623. {
  624. // Wait until child process exits.
  625. WaitForSingleObject( pi.hProcess, INFINITE );
  626. // Close process and thread handles. 
  627. CloseHandle( pi.hProcess );
  628. CloseHandle( pi.hThread );
  629. }
  630. else if(bForceUpdate) // 强制升级的话,这里可不能失败
  631. return false;
  632. // 4. 如果强制升级,那么升级成功了吗?
  633. if(bForceUpdate)
  634. {
  635. if(!DoesFileExist(lpModulePath, _T("layer1.dll")))
  636. return false;
  637. if(!DoesFileExist(lpModulePath, _T("localsrv.exe")))
  638. return false;
  639. if(!DoesFileExist(lpSystemPath, _T("vp7dec.ax")))
  640. return false;
  641. }
  642. // 5. 启动LocalServer,它会自动保证同时只存在一个实例的
  643. filename = lpModulePath;
  644. filename.append(_T("localsrv.exe"));
  645. // Start the child process. 
  646. if( !CreateProcess(  // No module name (use command line). 
  647. filename.data(), 
  648. NULL,             // Command line. 
  649. NULL,             // Process handle not inheritable. 
  650. NULL,             // Thread handle not inheritable. 
  651. FALSE,            // Set handle inheritance to FALSE. 
  652. 0,                // No creation flags. 
  653. NULL,             // Use parent's environment block. 
  654. NULL,             // Use parent's starting directory. 
  655. &si,              // Pointer to STARTUPINFO structure.
  656. &pi )             // Pointer to PROCESS_INFORMATION structure.
  657. {
  658. // 启动失败可不行
  659.         //MessageBox(NULL, "启动localsrv失败,也许直接执行它可以解决问题", "错误", MB_OK);
  660. return false;
  661. }
  662. // Close process and thread handles. 
  663. CloseHandle( pi.hProcess );
  664. CloseHandle( pi.hThread );
  665. return true;
  666. }
  667. bool CTVStreamSource::DoesFileExist(LPCTSTR path, LPCTSTR filename)
  668. {
  669. if(!path || !filename)
  670. return false;
  671. // 查找文件是否存在
  672. WIN32_FIND_DATA fileData;
  673. string match = path;
  674. match.append(filename);
  675. HANDLE hFind = FindFirstFile(match.data(), &fileData);
  676. if(hFind == INVALID_HANDLE_VALUE)
  677. return false;
  678. return true;
  679. }
  680. CUnknown * WINAPI CTVStreamSource::CreateInstance(LPUNKNOWN pUnk, HRESULT * phr)
  681. {
  682.     CTVStreamSource* pNewFilter = new CTVStreamSource(pUnk, phr);
  683. //
  684.     if (phr)
  685. {
  686. *phr = (NULL==pNewFilter) ? E_OUTOFMEMORY : S_OK;
  687. }
  688. //
  689.     return pNewFilter;
  690. }
  691. //
  692. HRESULT CTVStreamSource::_LoadFile(const char* filename)
  693. {
  694. ASSERT(strlen(filename) > 0);
  695. //
  696. SAFE_DELETE(m_pFileReader);
  697. //
  698. m_pFileReader = new ZZLFileReader();
  699. bool ret = m_pFileReader->Init(filename);
  700. //
  701. if(!ret) 
  702. {
  703. MessageBox(NULL, _T("zzl文件格式错误,无法播放!"), _T("致命错误"), MB_OK|MB_ICONSTOP);
  704. return VFW_E_CANNOT_RENDER;
  705. }
  706. //
  707. m_pVideoPin->SetMediaTime();
  708. m_pAudioPin->SetMediaTime();
  709. //
  710. return S_OK;
  711. }
  712. //
  713. HRESULT CTVStreamSource::_LoadURL(char* strURL)
  714. {
  715. //
  716. m_pComm = new NetworkProxy();
  717. //
  718. bool ret = false;
  719. if (NULL != m_pComm)
  720. {
  721. ret = m_pComm->Request(strURL);
  722. }
  723. //
  724. if(!ret) 
  725. {
  726. return VFW_E_CANNOT_RENDER;
  727. }
  728. //
  729. m_pVideoPin->SetMediaTime();
  730. m_pAudioPin->SetMediaTime(); 
  731. // 
  732. return S_OK;
  733. }
  734. //
  735. STDMETHODIMP CTVStreamSource::Load(LPCOLESTR lpwszFileName, const AM_MEDIA_TYPE *pmt) 
  736. {
  737. if(!m_bUpdateComplete)
  738. {
  739. if(!UpdateAndStartLocalServer())
  740. {
  741. // 1. get module path & system path
  742. TCHAR lpModulePath[MAX_PATH_EX] = _T("");
  743. DWORD dwLen = GetModuleFileName((HMODULE)g_hModule, lpModulePath, MAX_PATH_EX);
  744. if(dwLen == 0)
  745. return false;
  746. TCHAR* idx = _tcsrchr(lpModulePath, _T('\'));
  747. if(idx == NULL)
  748. return false;
  749. *(idx+1) = _T('');
  750. TCHAR lpSystemPath[MAX_PATH_EX] = _T("");
  751. dwLen = ::GetSystemDirectory(lpSystemPath, MAX_PATH_EX);
  752. if(dwLen == 0)
  753. return false;
  754. _tcscat(lpSystemPath, "\");
  755. if(!DoesFileExist(lpModulePath, _T("layer1.dll")) || !DoesFileExist(lpSystemPath, _T("vp7dec.ax"))) {
  756. MessageBox(NULL, _T("自动下载失败!请到www.mysee.com下载并进行安装!"), _T("错误"), MB_OK|MB_ICONSTOP);
  757. return VFW_E_CANNOT_RENDER;
  758. }
  759. }
  760. m_bUpdateComplete = TRUE;
  761. }
  762. TCHAR szFinal[MAX_PATH_EX] = _T(""); 
  763. //
  764. if(lpwszFileName) 
  765. {
  766. // 将WCHAR转换成TCHAR
  767. SAFE_ARRAYDELETE(m_pFileName);
  768. m_pFileName = new WCHAR[MAX_PATH_EX];
  769. //
  770. wcscpy(m_pFileName, lpwszFileName);
  771. }
  772. if(0 == WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, m_pFileName, -1, szFinal, sizeof(szFinal), NULL, NULL)) 
  773. {
  774. MessageBox(NULL, _T("错误的URL,无法播放!"), _T("致命错误"), MB_OK|MB_ICONSTOP);
  775. return VFW_E_CANNOT_RENDER;
  776. }
  777. // gaov protocol
  778. if(strnicmp(szFinal, "gaov://", 7) == 0)
  779.     {
  780.         return _LoadURL(szFinal);
  781.     }
  782. //
  783. char* index = strrchr(szFinal, '.');
  784. if(index != NULL)
  785. {
  786. index++;
  787. if(strnicmp(index, "gtv", 3) == 0) 
  788. {
  789. //ASSERT(FALSE);
  790. // gtv file
  791. }else if(strnicmp(index, "zzl", 3) == 0)
  792. {
  793. return _LoadFile(szFinal);
  794. }
  795. else 
  796. {
  797. index = NULL;
  798. }
  799. }
  800. //
  801. if(index == NULL) 
  802. {
  803. MessageBox(NULL, _T("无法识别的URL,后缀名必是gtv或者zzl!"), _T("致命错误"), MB_OK|MB_ICONSTOP);
  804. return VFW_E_CANNOT_RENDER;
  805. }
  806. //
  807. return _LoadURL(szFinal);
  808. }
  809. STDMETHODIMP CTVStreamSource::GetCurFile(LPOLESTR *ppszFileName, AM_MEDIA_TYPE *pmt)
  810. {
  811. CheckPointer(ppszFileName, E_POINTER);
  812. *ppszFileName = NULL;
  813. if(m_pFileName != NULL) 
  814. {
  815. *ppszFileName = (LPOLESTR) CoTaskMemAlloc(MAX_PATH_EX);
  816. if (*ppszFileName != NULL)
  817. {
  818. CopyMemory(*ppszFileName, m_pFileName, MAX_PATH_EX);
  819. }
  820. }
  821. if(pmt != NULL) 
  822. {
  823. // TODO
  824. NOTE("GetCurFile TODO");
  825. }
  826. return S_OK;
  827. }
  828. STDMETHODIMP CTVStreamSource::NonDelegatingQueryInterface(REFIID riid, void ** ppv) 
  829. {
  830. CheckPointer(ppv,E_POINTER);
  831. if (riid == IID_IFileSourceFilter) 
  832. {
  833. return GetInterface((IFileSourceFilter *) this, ppv);
  834. }
  835. else if(riid == IID_ISettings)
  836. {
  837. return GetInterface((ISettings *) this, ppv);
  838. }
  839. else
  840. {
  841. return CSource::NonDelegatingQueryInterface(riid, ppv);
  842. }
  843. }
  844. //
  845. STDMETHODIMP_(void) CTVStreamSource::SetPopMsgHWND(HWND pop) 
  846. {
  847. }
  848. //
  849. STDMETHODIMP CTVStreamSource::Stop()   
  850. {
  851. CAutoLock cObjectLock(m_pLock);
  852. if(m_bDoRealStop) {
  853. if(NULL != m_pComm)
  854. m_pComm->Stop();
  855. }
  856. //
  857. HRESULT hr = CSource::Stop();
  858. //
  859. return hr;
  860. }
  861. //
  862. /*
  863. STDMETHODIMP CTVStreamSource::Run(REFERENCE_TIME tStart) 
  864. {
  865. CAutoLock cObjectLock(m_pLock);
  866. //
  867. return CSource::Run(tStart);
  868. }
  869. STDMETHODIMP CTVStreamSource::Pause() 
  870. {
  871. CAutoLock cObjectLock(m_pLock); 
  872. //SetBaseRef(_I64_MAX);
  873. //
  874. return CSource::Pause();
  875. }*/
  876. //
  877. LONGLONG CTVStreamSource::GetBaseRef()
  878. {
  879. CAutoLock l(&m_critllBase);
  880. return m_llBaseRef;
  881. }
  882. //
  883. void CTVStreamSource::SetBaseRef( LONGLONG llBaseRef)
  884. {
  885. CAutoLock l(&m_critllBase);
  886. m_llBaseRef = llBaseRef;
  887. }
  888. LONGLONG CTVStreamSource::GetRawAudioRef()
  889. {
  890. CAutoLock l(&m_critllBase);
  891. return m_rawAudiotime;
  892. }
  893. void CTVStreamSource::SetRawAudioRef(LONGLONG llRawRef)
  894. {
  895. CAutoLock l(&m_critllBase);
  896. m_rawAudiotime = llRawRef;
  897. }
  898. //
  899. IBaseFilter* CTVStreamSource::FindFilterFromFriendlyName(REFCLSID clsid, string str)
  900. {
  901. // Create the System Device Enumerator.
  902. HRESULT hr;
  903. IBaseFilter *pFilter = NULL;
  904. ICreateDevEnum* pSysDevEnum = NULL;
  905. hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
  906. IID_ICreateDevEnum, (void **)&pSysDevEnum);
  907. // Obtain a class enumerator for the video compressor category.
  908. IEnumMoniker* pEnumCat = NULL;
  909. hr = pSysDevEnum->CreateClassEnumerator(clsid, &pEnumCat, 0);
  910. if (hr == S_OK) 
  911. {
  912. // Enumerate the monikers.
  913. IMoniker* pMoniker = NULL;
  914. ULONG cFetched;
  915. while(pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK)
  916. {
  917. IPropertyBag* pPropBag = NULL;
  918. hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag);
  919. if(hr != S_OK)
  920. break;
  921. // To retrieve the friendly name of the filter, do the following:
  922. VARIANT varName;
  923. VariantInit(&varName);
  924. hr = pPropBag->Read(L"FriendlyName", &varName, 0);
  925. if(pPropBag)
  926. pPropBag->Release();
  927. if (SUCCEEDED(hr))
  928. {
  929. // Display the name in your UI somehow.
  930. USES_CONVERSION;
  931. //string str = W2CA(varName.bstrVal);
  932. //const char* pStr = str.data();
  933. if (stricmp(W2CA(varName.bstrVal), str.data()) == 0)
  934. {
  935. //ASSERT(FALSE);
  936. VariantClear(&varName);
  937. // To create an instance of the filter, do the following:
  938. pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, (void**)&pFilter);
  939. pFilter->AddRef();
  940. pMoniker->Release();
  941. pMoniker = NULL;
  942. break;
  943. }
  944. }
  945. //
  946. VariantClear(&varName);
  947. if(pMoniker) {
  948. pMoniker->Release();
  949. pMoniker = NULL;
  950. }
  951. }//end while
  952. }
  953. if(pSysDevEnum)
  954. pSysDevEnum->Release();
  955. if(pEnumCat)
  956. pEnumCat->Release();
  957. if(!pFilter)
  958. ASSERT(FALSE);
  959. return pFilter;
  960. }
  961. //