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

DirextX编程

开发平台:

Visual C++

  1. //
  2. // CDecodedStream.cpp
  3. //
  4. #include <streams.h>
  5. #include <stdio.h>
  6. #include "CFilterMpeg2VD.h"
  7. #include "CDecodedStream.h"
  8. #include "CMpegInputPin.h"
  9. /////////////////////////////////////////////////////////////////////////////
  10. CDecodedStream::CDecodedStream(TCHAR * inObjectName,
  11.    HRESULT * outResult, 
  12.    CFilterMpeg2VD * inFilter) :
  13. CSourceStream(inObjectName, outResult, inFilter, L"Output")
  14. {
  15. mDecodeFilter = inFilter;
  16. mPosition     = NULL;
  17. mFlushing     = FALSE;
  18. mMpegController = NULL;
  19. mSamplesSent    = 0;
  20. }
  21. CDecodedStream::~CDecodedStream()
  22. {
  23. if (mPosition) 
  24. {
  25. mPosition->Release();
  26. mPosition = NULL;
  27. }
  28. }
  29. void CDecodedStream::SetController(CMpegController * inController)
  30. {
  31. mMpegController = inController;
  32. }
  33. HRESULT CDecodedStream::FillBuffer(IMediaSample *pSample)
  34. {
  35. return NOERROR;
  36. }
  37. HRESULT CDecodedStream::CompleteConnect(IPin *pReceivePin)
  38. {
  39. HRESULT hr = mDecodeFilter->CompleteConnect(PINDIR_OUTPUT, pReceivePin);
  40.     if (FAILED(hr)) 
  41. {
  42.         return hr;
  43.     }
  44.     return CBaseOutputPin::CompleteConnect(pReceivePin);
  45. }
  46. //
  47. // DecideBufferSize
  48. //
  49. // Tell the output pin's allocator what size buffers we
  50. // require. Can only do this when the input is connected
  51. //
  52. HRESULT CDecodedStream::DecideBufferSize(IMemAllocator * pAllocator,
  53.  ALLOCATOR_PROPERTIES *pprop)
  54. {
  55. // Is the input pin connected
  56. if (!mDecodeFilter->mMpegInputPin->IsConnected()) 
  57. {
  58. return E_UNEXPECTED;
  59. }
  60. ASSERT(pAllocator);
  61. ASSERT(pprop);
  62. HRESULT hr = NOERROR;
  63. pprop->cbBuffer  = mDecodeFilter->mOutputImageSize;
  64. pprop->cBuffers  = 1;
  65. pprop->cbAlign   = 1;
  66. ASSERT(pprop->cbBuffer);
  67. // Ask the allocator to reserve us some sample memory, NOTE the function
  68. // can succeed (that is return NOERROR) but still not have allocated the
  69. // memory that we requested, so we must check we got whatever we wanted
  70. ALLOCATOR_PROPERTIES Actual;
  71. hr = pAllocator->SetProperties(pprop, &Actual);
  72. if (FAILED(hr)) {
  73. return hr;
  74. }
  75. ASSERT( Actual.cBuffers == 1 );
  76. if (pprop->cBuffers > Actual.cBuffers ||
  77. pprop->cbBuffer > Actual.cbBuffer) {
  78. return E_FAIL;
  79. }
  80. return NOERROR;
  81. }
  82. HRESULT CDecodedStream::CheckMediaType(const CMediaType *mtOut)
  83. {
  84. if (mDecodeFilter->mMpegInputPin->IsConnected())
  85. {
  86. if ((mtOut->subtype == MEDIASUBTYPE_YUY2 ||
  87. mtOut->subtype == MEDIASUBTYPE_RGB24) &&
  88. mtOut->formattype == FORMAT_VideoInfo)
  89. {
  90. VIDEOINFOHEADER * pFormat = (VIDEOINFOHEADER *) mtOut->pbFormat;
  91. if (pFormat->bmiHeader.biHeight == mDecodeFilter->mImageHeight &&
  92. pFormat->bmiHeader.biWidth == mDecodeFilter->mImageWidth)
  93. {
  94. return S_OK;
  95. }
  96. }
  97. }
  98. return E_FAIL;
  99. }
  100. // ---------------------------------------------------------
  101. // Currently we only support YUY2 and RGB24 decoded out
  102. // ---------------------------------------------------------
  103. HRESULT CDecodedStream::GetMediaType(int iPosition, CMediaType *pMediaType)
  104. {
  105.     if (!mDecodeFilter->mMpegInputPin->IsConnected() || 
  106. iPosition < 0 || iPosition > 1)
  107. {
  108. return E_FAIL;
  109. }
  110. VIDEOINFOHEADER    format;
  111. ZeroMemory(&format, sizeof(VIDEOINFOHEADER));
  112. pMediaType->SetType(&MEDIATYPE_Video);
  113. switch (iPosition)
  114. {
  115. case 0:  // YUY2
  116. pMediaType->SetSubtype(&MEDIASUBTYPE_YUY2);
  117. format.bmiHeader.biBitCount    = 16;
  118. format.bmiHeader.biCompression = mmioFOURCC('Y','U','Y','2');
  119. break;
  120. case 1: // RGB24
  121. pMediaType->SetSubtype(&MEDIASUBTYPE_RGB24);
  122. format.bmiHeader.biBitCount    = 24;
  123. format.bmiHeader.biCompression = BI_RGB;
  124. break;
  125. }
  126. pMediaType->SetFormatType(&FORMAT_VideoInfo);
  127. format.bmiHeader.biSize   = sizeof(BITMAPINFOHEADER);
  128. format.bmiHeader.biPlanes = 1;
  129. format.AvgTimePerFrame    = mDecodeFilter->mSampleDuration;
  130. format.bmiHeader.biWidth  = mDecodeFilter->mImageWidth;
  131. format.bmiHeader.biHeight = mDecodeFilter->mImageHeight;
  132. format.bmiHeader.biSizeImage = mDecodeFilter->mImageWidth * mDecodeFilter->mImageHeight * format.bmiHeader.biBitCount / 8;
  133. pMediaType->SetFormat(PBYTE(&format), sizeof(VIDEOINFOHEADER));
  134.     return S_OK;
  135. } // GetMediaType
  136. STDMETHODIMP CDecodedStream::QueryId(LPWSTR * Id)
  137. {
  138. return CBaseOutputPin::QueryId(Id);
  139. }
  140. // overriden to expose IMediaPosition and IMediaSeeking control interfaces
  141. STDMETHODIMP CDecodedStream::NonDelegatingQueryInterface(REFIID riid, void **ppv) 
  142. {
  143.     CheckPointer(ppv,E_POINTER);
  144.     ValidateReadWritePtr(ppv,sizeof(PVOID));
  145.     *ppv = NULL;
  146. if (riid == IID_IMediaPosition || riid == IID_IMediaSeeking) 
  147. {
  148. // we should have an input pin by now
  149. ASSERT(mDecodeFilter->mMpegInputPin != NULL);
  150. if (mPosition == NULL) 
  151. {
  152. HRESULT hr = CreatePosPassThru(GetOwner(),
  153. FALSE,
  154. (IPin *)mDecodeFilter->mMpegInputPin,
  155. &mPosition);
  156. if (FAILED(hr)) 
  157. {
  158. return hr;
  159. }
  160. }
  161. return mPosition->QueryInterface(riid, ppv);
  162. }
  163.     else 
  164. {
  165.         return CSourceStream::NonDelegatingQueryInterface(riid, ppv);
  166.     }
  167. }
  168. // Override this if you can do something constructive to act on the
  169. // quality message.  Consider passing it upstream as well
  170. // Pass the quality mesage on upstream.
  171. STDMETHODIMP CDecodedStream::Notify(IBaseFilter * pSender, Quality q) 
  172. {
  173.     UNREFERENCED_PARAMETER(pSender);
  174.     ValidateReadPtr(pSender, sizeof(IBaseFilter));
  175.     return mDecodeFilter->mMpegInputPin->PassNotify(q);
  176. } // Notify
  177. STDMETHODIMP CDecodedStream::BeginFlush(void)
  178. {
  179. mFlushing = TRUE;
  180. mMpegController->BeginFlush();
  181. {
  182. CAutoLock   lck(&mDataAccess);
  183. mSamplesSent   = 0;
  184. }
  185. return NOERROR;
  186. }
  187. STDMETHODIMP CDecodedStream::EndFlush(void)
  188. {
  189. mMpegController->EndFlush();
  190. mFlushing = FALSE;
  191. return NOERROR;
  192. }
  193. HRESULT CDecodedStream::EndOfStream(void)
  194. {
  195. return NOERROR;
  196. }
  197. HRESULT CDecodedStream::DoBufferProcessingLoop(void)
  198. {
  199. Command com;
  200.     OnThreadStartPlay();
  201. BOOL   EOS_Flag = FALSE;
  202.     do 
  203. {
  204.         while (!CheckRequest(&com)) 
  205. {
  206. // If no data, never enter blocking reading
  207. if (mFlushing || mMpegController->IsCacheEmpty() || EOS_Flag) 
  208. {
  209. if (mDecodeFilter->mEOSReceived)
  210. {
  211. EOS_Flag = TRUE;
  212. mMpegController->EndEndOfStream();
  213. if (!mDecodeFilter->mEOSDelivered)
  214. {
  215. mDecodeFilter->mEOSDelivered = TRUE;
  216. DeliverEndOfStream();
  217. }
  218. }
  219. Sleep(1);
  220. continue;
  221. }
  222. mMpegController->SequenceHeaderChecking();
  223. BOOL pass = mMpegController->LocatePictureHeader();
  224. if (pass)
  225. {
  226. pass = mMpegController->DecodeOnePicture();
  227. }
  228. if (pass)
  229. {
  230. IMediaSample *pSample;
  231. HRESULT hr = GetDeliveryBuffer(&pSample, NULL, NULL, 0);
  232. if (FAILED(hr)) 
  233. {
  234. Sleep(1);
  235. continue;   // go round again. Perhaps the error will go away
  236. // or the allocator is decommited & we will be asked to
  237. // exit soon.
  238. }
  239. hr = DeliverCurrentPicture(pSample);
  240. if (FAILED(hr) && mDecodeFilter->mEOSReceived)
  241. {
  242. EOS_Flag = TRUE;
  243. mMpegController->EndEndOfStream();
  244. if (!mDecodeFilter->mEOSDelivered)
  245. {
  246. mDecodeFilter->mEOSDelivered = TRUE;
  247. DeliverEndOfStream();
  248. }
  249. }
  250. }
  251.         }
  252. // For all commands sent to us there must be a Reply call!
  253. if (com == CMD_RUN || com == CMD_PAUSE) 
  254. {
  255. Reply(NOERROR);
  256. }
  257. else if (com != CMD_STOP) 
  258. {
  259. Reply((DWORD) E_UNEXPECTED);
  260. DbgLog((LOG_ERROR, 1, TEXT("Unexpected command!!!")));
  261. }
  262.     } while (com != CMD_STOP);
  263. // If EOS not delivered at the moment, just do it here!
  264. // mMpegController->EndEndOfStream();
  265. // if (!mDecodeFilter->mEOSDelivered)
  266. // {
  267. // mDecodeFilter->mEOSDelivered = TRUE;
  268. // DeliverEndOfStream();
  269. // }
  270.     return S_FALSE;
  271. }
  272. HRESULT CDecodedStream::OnThreadStartPlay(void)
  273. {
  274. mSamplesSent = 0;
  275. return NOERROR;
  276. }
  277. HRESULT CDecodedStream::OnThreadDestroy(void)
  278. {
  279. return NOERROR;
  280. }
  281. HRESULT CDecodedStream::DeliverCurrentPicture(IMediaSample * pSample)
  282. {
  283. PBYTE   pOut;
  284. pSample->GetPointer(&pOut);
  285. mMpegController->GetDecoded(pOut);
  286. pSample->SetActualDataLength(mDecodeFilter->mOutputImageSize);
  287. ULONG    alreadySent = 0;
  288. {
  289. CAutoLock   lck(&mDataAccess);
  290. alreadySent  = mSamplesSent;
  291. mSamplesSent++;
  292. }
  293. LONGLONG   llStart = alreadySent;
  294. LONGLONG   llEnd   = alreadySent + 1;
  295. pSample->SetMediaTime(&llStart, &llEnd);
  296. REFERENCE_TIME rtStart = alreadySent * mDecodeFilter->mSampleDuration;
  297. REFERENCE_TIME rtEnd   = (alreadySent + 1) * mDecodeFilter->mSampleDuration;
  298. pSample->SetTime(&rtStart, &rtEnd);
  299. pSample->SetDiscontinuity(FALSE);
  300. pSample->SetPreroll(FALSE);
  301. pSample->SetSyncPoint(TRUE);
  302. HRESULT hr = Deliver(pSample);
  303. pSample->Release();
  304. return hr;
  305. }
  306. HRESULT CDecodedStream::StopThreadSafely(void)
  307. {
  308. if (ThreadExists()) 
  309. {
  310. Stop();
  311. }
  312. return NOERROR;
  313. }
  314. HRESULT CDecodedStream::RunThreadSafely(void)
  315. {
  316. if (ThreadExists()) 
  317. {
  318. Run();
  319. }
  320. return NOERROR;
  321. }