CFilterMpeg2VD.cpp
上传用户:hhs829
上传日期:2022-06-17
资源大小:586k
文件大小:12k
源码类别:

DirextX编程

开发平台:

Visual C++

  1. //
  2. // CFilterMpeg2VD.cpp
  3. //
  4. #include <streams.h>          // quartz, includes windows
  5. // Eliminate two expected level 4 warnings from the Microsoft compiler.
  6. // The class does not have an assignment or copy operator, and so cannot
  7. // be passed by value.  This is normal.  This file compiles clean at the
  8. // highest (most picky) warning level (-W4).
  9. #pragma warning(disable: 4511 4512)
  10. #include <measure.h>          // performance measurement (MSR_)
  11. #include <initguid.h>
  12. #if (1100 > _MSC_VER)
  13. #include <olectlid.h>
  14. #else
  15. #include <olectl.h>
  16. #endif
  17. #include <dvdmedia.h>
  18. #include <stdio.h>
  19. #include "CFilterMpeg2VD.h"
  20. #include "CMpegInputPin.h"
  21. #include "CDecodedStream.h"
  22. #include "CFilterMpeg2VDProp.h"
  23. // {AFF8F523-DB02-495c-A1A1-605A505500A5}
  24. DEFINE_GUID(CLSID_FilterMpeg2VD, 
  25. 0xaff8f523, 0xdb02, 0x495c, 0xa1, 0xa1, 0x60, 0x5a, 0x50, 0x55, 0x0, 0xa5);
  26. // {8EDE98CF-17A3-471b-98AB-C944727E50BA}
  27. DEFINE_GUID(CLSID_FilterMpeg2VDProp, 
  28. 0x8ede98cf, 0x17a3, 0x471b, 0x98, 0xab, 0xc9, 0x44, 0x72, 0x7e, 0x50, 0xba);
  29. //
  30. // setup data
  31. //
  32. const AMOVIESETUP_MEDIATYPE sudPinTypes =
  33. {
  34.     &MEDIATYPE_Video,           // Major type
  35.     &MEDIASUBTYPE_NULL          // Minor type
  36. };
  37. const AMOVIESETUP_PIN psudPins[] =
  38. {
  39.     {
  40.         L"Input",           // String pin name
  41.         FALSE,              // Is it rendered
  42.         FALSE,              // Is it an output
  43.         FALSE,              // Allowed none
  44.         FALSE,              // Allowed many
  45.         &CLSID_NULL,        // Connects to filter
  46.         L"Output",          // Connects to pin
  47.         1,                  // Number of types
  48.         &sudPinTypes },     // The pin details
  49.       { L"Output",          // String pin name
  50.         FALSE,              // Is it rendered
  51.         TRUE,               // Is it an output
  52.         FALSE,              // Allowed none
  53.         FALSE,              // Allowed many
  54.         &CLSID_NULL,        // Connects to filter
  55.         L"Input",           // Connects to pin
  56.         1,                  // Number of types
  57.         &sudPinTypes        // The pin details
  58.     }
  59. };
  60. const AMOVIESETUP_FILTER sudFilter =
  61. {
  62.     &CLSID_FilterMpeg2VD,       // Filter CLSID
  63.     L"HQ MPEG-2 Video Decoder",      // Filter name
  64.     MERIT_PREFERRED,            // Its merit
  65.     2,                       // Number of pins
  66.     psudPins                 // Pin details
  67. };
  68. // List of class IDs and creator functions for the class factory. This
  69. // provides the link between the OLE entry point in the DLL and an object
  70. // being created. The class factory will call the static CreateInstance
  71. CFactoryTemplate g_Templates[] = 
  72. {
  73.     { 
  74. L"HQ MPEG-2 Video Decoder",
  75. &CLSID_FilterMpeg2VD,
  76. CFilterMpeg2VD::CreateInstance,
  77. NULL,
  78. &sudFilter 
  79. }/*,
  80. L"HQ Mpeg2 VD Property Page",
  81. &CLSID_FilterMpeg2VDProp,
  82. CFilterMpeg2VDProp::CreateInstance 
  83. }*/
  84. };
  85. int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
  86. static int decoderInstances = 0;
  87. // ----------------------------------------------------------------------------
  88. //            Filter implementation
  89. // ----------------------------------------------------------------------------
  90. CFilterMpeg2VD::CFilterMpeg2VD(TCHAR *tszName, LPUNKNOWN punk, HRESULT *phr) :
  91. CSource(tszName, punk, CLSID_FilterMpeg2VD)
  92. {
  93. decoderInstances++;
  94. mSampleDuration = 0;
  95. mImageWidth     = 0;
  96. mImageHeight    = 0;
  97. mOutputImageSize = 0;
  98. mIsFlushing    = FALSE;
  99. mEOSDelivered  = FALSE;
  100. mEOSReceived   = FALSE;
  101. *phr = NOERROR;
  102. mMpegInputPin = NULL;
  103. CDecodedStream * outStream = new CDecodedStream(NAME("Output"), phr, this);
  104. if (outStream == NULL)
  105. {
  106. *phr = E_OUTOFMEMORY;
  107. }
  108. else
  109. {
  110. outStream->SetController(&mMpegController);
  111. }
  112. }
  113. CFilterMpeg2VD::~CFilterMpeg2VD()
  114. {
  115. if (mMpegInputPin)
  116. {
  117. delete mMpegInputPin;
  118. mMpegInputPin = NULL;
  119. }
  120. decoderInstances--;
  121. }
  122. //
  123. // CreateInstance
  124. //
  125. // Override CClassFactory method.
  126. // Provide the way for COM to create a CNullInPlace object
  127. //
  128. CUnknown * WINAPI CFilterMpeg2VD::CreateInstance(LPUNKNOWN punk, HRESULT *phr) 
  129. {
  130. #if 0
  131. char    szCreatorPath[256], szCreatorName[256];
  132. ::strcpy(szCreatorPath, "");
  133. ::strcpy(szCreatorName, "");
  134. HMODULE hModule = ::GetModuleHandle(NULL);
  135. ::GetModuleFileName(hModule, szCreatorPath, 256);
  136. char * backSlash = ::strrchr(szCreatorPath, '\');
  137. if (backSlash)
  138. {
  139. strcpy(szCreatorName, backSlash);
  140. }
  141. ::_strlwr(szCreatorName);
  142. // Please specify your app name with lowercase
  143. if (::strstr(szCreatorName, "graphedt") == NULL)
  144. {
  145. *phr = E_FAIL;
  146. return NULL;
  147. }
  148. #endif 
  149. // Never use more than two instances of this decoder in the same application
  150. // Beccause of global variable problems!
  151. // 2002-12-26
  152. if (decoderInstances == 1)
  153. {
  154. *phr = E_FAIL;
  155. return NULL;
  156. }
  157.     CFilterMpeg2VD *pNewObject = new CFilterMpeg2VD(NAME("Filter Mpeg2 VD"), punk, phr);
  158.     if (pNewObject == NULL) 
  159. {
  160.         *phr = E_OUTOFMEMORY;
  161.     }
  162.     return pNewObject;
  163. //
  164. // Basic COM - used here to reveal our own interfaces
  165. STDMETHODIMP CFilterMpeg2VD::NonDelegatingQueryInterface(REFIID riid, void ** ppv)
  166. {
  167. CheckPointer(ppv, E_POINTER);
  168. // if (riid == IID_ISpecifyPropertyPages) 
  169. // {
  170. // return GetInterface((ISpecifyPropertyPages *) this, ppv);
  171. // }
  172. // else 
  173. {
  174.         return CSource::NonDelegatingQueryInterface(riid, ppv);
  175.     }
  176. } // NonDelegatingQueryInterface
  177. int CFilterMpeg2VD::GetPinCount()
  178. {
  179. return 2;
  180. }
  181. CBasePin * CFilterMpeg2VD::GetPin(int n)
  182. {
  183. if (mMpegInputPin == NULL)
  184. {
  185. HRESULT hr = NOERROR;
  186. mMpegInputPin = new CMpegInputPin(NAME("Input"), this, &hr);
  187. ASSERT(mMpegInputPin);
  188. }
  189. switch (n)
  190. {
  191. case 0:
  192. return mMpegInputPin;
  193. case 1:
  194. return m_paStreams[0];
  195. default:
  196. return NULL;
  197. }
  198. }
  199. STDMETHODIMP CFilterMpeg2VD::FindPin(LPCWSTR Id, IPin ** ppPin)
  200. {
  201. return CBaseFilter::FindPin(Id, ppPin);
  202. }
  203. STDMETHODIMP CFilterMpeg2VD::Stop()
  204. {
  205. CAutoLock lck1(&m_cStateLock);
  206. if (m_State == State_Stopped) 
  207. {
  208. return NOERROR;
  209. }
  210. // Succeed the Stop if we are not completely connected
  211. ASSERT(mMpegInputPin == NULL || m_paStreams[0] != NULL);
  212. if (mMpegInputPin == NULL || mMpegInputPin->IsConnected() == FALSE ||
  213. m_paStreams[0]->IsConnected() == FALSE) 
  214. {
  215. m_State = State_Stopped;
  216. mEOSDelivered = FALSE;
  217. return NOERROR;
  218. }
  219. // Important!!! Refuse to receive any more samples
  220. mMpegController.FlushAllPending();
  221. // decommit the input pin before locking or we can deadlock
  222. mMpegInputPin->Inactive();
  223. // synchronize with Receive calls
  224. CAutoLock lck2(&m_csReceive);
  225. OutputPin()->BeginFlush();
  226. OutputPin()->Inactive();
  227. OutputPin()->EndFlush();
  228. // allow a class derived from CTransformFilter
  229. // to know about starting and stopping streaming
  230. HRESULT hr = StopStreaming();
  231. if (SUCCEEDED(hr)) 
  232. {
  233. // complete the state transition
  234. m_State = State_Stopped;
  235. mEOSDelivered = FALSE;
  236. }
  237. return hr;
  238. }
  239. STDMETHODIMP CFilterMpeg2VD::Pause()
  240. {
  241. CAutoLock lck(&m_cStateLock);
  242. HRESULT hr = NOERROR;
  243. if (m_State == State_Paused) 
  244. {
  245. // (This space left deliberately blank)
  246. }
  247. // If we have no input pin or it isn't yet connected then when we are
  248. // asked to pause we deliver an end of stream to the downstream filter.
  249. // This makes sure that it doesn't sit there forever waiting for
  250. // samples which we cannot ever deliver without an input connection.
  251. else if (mMpegInputPin == NULL || mMpegInputPin->IsConnected() == FALSE) 
  252. {
  253. if(m_paStreams[0]->IsConnected() && mEOSDelivered == FALSE) 
  254. {
  255. m_paStreams[0]->DeliverEndOfStream();
  256. mEOSDelivered = TRUE;
  257. }
  258. m_State = State_Paused;
  259. }
  260. // We may have an input connection but no output connection
  261. // However, if we have an input pin we do have an output pin
  262. else if (m_paStreams[0]->IsConnected() == FALSE) 
  263. {
  264. m_State = State_Paused;
  265. }
  266. else 
  267. {
  268. if (m_State == State_Stopped) 
  269. {
  270. // allow a class derived from CTransformFilter
  271. // to know about starting and stopping streaming
  272. CAutoLock lck2(&m_csReceive);
  273. hr = StartStreaming();
  274. }
  275. if (SUCCEEDED(hr)) 
  276. {
  277. // Make sure the receive not blocking
  278. // Make sure the out-sending thread not working
  279. mMpegController.FlushAllPending();
  280. hr = CBaseFilter::Pause();
  281. }
  282. }
  283. return hr;
  284. }
  285. HRESULT CFilterMpeg2VD::StartStreaming()
  286. {
  287. mIsFlushing  = FALSE;
  288. mEOSReceived = FALSE;
  289. return NOERROR;
  290. }
  291. HRESULT CFilterMpeg2VD::StopStreaming()
  292. {
  293. mIsFlushing  = FALSE;
  294. mEOSReceived = FALSE;
  295. return NOERROR;
  296. }
  297. HRESULT CFilterMpeg2VD::Receive(IMediaSample *pSample)
  298. {
  299. // Check for other streams and pass them on
  300. AM_SAMPLE2_PROPERTIES * const pProps = mMpegInputPin->SampleProps();
  301. if (pProps->dwStreamId != AM_STREAM_MEDIA) 
  302. {
  303. return m_paStreams[0]->Deliver(pSample);
  304. }
  305. // Receive mpeg2 data to buffer
  306. ASSERT(pSample);
  307. long lSourceSize = pSample->GetActualDataLength();
  308. BYTE * pSourceBuffer;
  309. pSample->GetPointer(&pSourceBuffer);
  310. mMpegController.ReceiveMpeg(pSourceBuffer, lSourceSize);
  311. return NOERROR;
  312. }
  313. HRESULT CFilterMpeg2VD::EndOfStream(void)
  314. {
  315. // Ignoring the more than twice EOS
  316. if (!mEOSReceived)
  317. {
  318. mEOSReceived  = TRUE;
  319. mMpegController.BeginEndOfStream();
  320. // Wait for all caching data having been fetched out
  321. // while (!mMpegController.IsCacheOutputWaiting() && 
  322. // !mMpegController.IsCacheEmpty())
  323. // {
  324. // Sleep(10);
  325. // }
  326. // mMpegController.EndEndOfStream();
  327. // mEOSDelivered = TRUE;
  328. // return m_paStreams[0]->DeliverEndOfStream();
  329. }
  330. return NOERROR;
  331. }
  332. HRESULT CFilterMpeg2VD::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
  333. {
  334. return m_paStreams[0]->DeliverNewSegment(tStart, tStop, dRate);
  335. }
  336. HRESULT CFilterMpeg2VD::BeginFlush(void)
  337. {
  338. HRESULT hr  = m_paStreams[0]->DeliverBeginFlush(); // Call downstreamly
  339. mIsFlushing = TRUE;
  340. OutputPin()->BeginFlush();
  341. return hr;
  342. }
  343. HRESULT CFilterMpeg2VD::EndFlush(void)
  344. {
  345. mEOSReceived = FALSE;
  346. OutputPin()->EndFlush();
  347. mIsFlushing = FALSE;
  348. return m_paStreams[0]->DeliverEndFlush();
  349. }
  350. HRESULT CFilterMpeg2VD::CompleteConnect(PIN_DIRECTION inDirection, IPin * inReceivePin)
  351. {
  352. if (inDirection == PINDIR_INPUT)
  353. {
  354. CMediaType  mtIn = mMpegInputPin->CurrentMediaType();
  355. if (mtIn.formattype == FORMAT_MPEG2Video)
  356. {
  357. MPEG2VIDEOINFO * pFormat = (MPEG2VIDEOINFO *) mtIn.pbFormat;
  358. mSampleDuration = pFormat->hdr.AvgTimePerFrame;
  359. mImageWidth     = pFormat->hdr.bmiHeader.biWidth;
  360. mImageHeight    = pFormat->hdr.bmiHeader.biHeight;
  361. // Init the mpeg decoder system
  362. mMpegController.Uninitialize();
  363. mMpegController.Initialize();
  364. return S_OK;
  365. }
  366. }
  367. else
  368. {
  369. CMediaType  mtOut = OutputPin()->CurrentMediaType();
  370. int bitcount = 2;
  371. if (mtOut.subtype == MEDIASUBTYPE_YUY2)
  372. {
  373. bitcount = 2;
  374. mMpegController.SetOutputType(2);
  375. }
  376. else if (mtOut.subtype == MEDIASUBTYPE_RGB24)
  377. {
  378. bitcount = 3;
  379. mMpegController.SetOutputType(1);
  380. }
  381. mOutputImageSize = mImageWidth * mImageHeight * bitcount;
  382. mMpegController.SetOutputImageSize(mOutputImageSize);
  383. return S_OK;
  384. }
  385. return E_FAIL;
  386. }
  387. /*
  388. //
  389. STDMETHODIMP CFilterMpeg2VD::GetPages(CAUUID *pPages)
  390. {
  391. pPages->cElems = 1;
  392.     pPages->pElems = (GUID *) CoTaskMemAlloc(sizeof(GUID));
  393.     if (pPages->pElems == NULL) 
  394. {
  395.         return E_OUTOFMEMORY;
  396.     }
  397.     *(pPages->pElems) = CLSID_FilterMpeg2VDProp;
  398.     return NOERROR;
  399. }
  400. */
  401. /******************************Public Routine******************************
  402. * exported entry points for registration and
  403. * unregistration (in this case they only call
  404. * through to default implmentations).
  405. *
  406. *
  407. *
  408. * History:
  409. *
  410. **************************************************************************/
  411. STDAPI DllRegisterServer()
  412. {
  413. return AMovieDllRegisterServer2( TRUE );
  414. }
  415. STDAPI DllUnregisterServer()
  416. {
  417. return AMovieDllRegisterServer2( FALSE );
  418. }
  419. // Microsoft C Compiler will give hundreds of warnings about
  420. // unused inline functions in header files.  Try to disable them.
  421. #pragma warning( disable:4514)