asyncrdr.cpp
上传用户:hxb_1234
上传日期:2010-03-30
资源大小:8328k
文件大小:9k
源码类别:

VC书籍

开发平台:

Visual C++

  1. //==========================================================================;
  2. //
  3. //  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4. //  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5. //  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6. //  PURPOSE.
  7. //
  8. //  Copyright (c) 1992 - 1997  Microsoft Corporation.  All Rights Reserved.
  9. //
  10. //--------------------------------------------------------------------------;
  11. //
  12. // Implementation of Io source filter methods and output pin methods for
  13. // CAsyncReader and CAsyncOutputPin
  14. //
  15. #include "stdafx.h"
  16. #include <streams.h>
  17. #include "asyncio.h"
  18. #include "asyncrdr.h"
  19. // --- CAsyncOutputPin implementation ---
  20. CAsyncOutputPin::CAsyncOutputPin(
  21.     HRESULT * phr,
  22.     CAsyncReader *pReader,
  23.     CAsyncIo *pIo,
  24.     CCritSec * pLock)
  25.   : CBasePin(
  26. NAME("Async output pin"),
  27. pReader,
  28. pLock,
  29. phr,
  30. L"Output",
  31. PINDIR_OUTPUT),
  32.     m_pReader(pReader),
  33.     m_pIo(pIo)
  34. {
  35. }
  36. CAsyncOutputPin::~CAsyncOutputPin()
  37. {
  38. }
  39. STDMETHODIMP
  40. CAsyncOutputPin::NonDelegatingQueryInterface(REFIID riid, void** ppv)
  41. {
  42.     CheckPointer(ppv,E_POINTER);
  43.     if (riid == IID_IAsyncReader) {
  44.         m_bQueriedForAsyncReader = TRUE;
  45. return GetInterface((IAsyncReader*) this, ppv);
  46.     } else {
  47. return CBasePin::NonDelegatingQueryInterface(riid, ppv);
  48.     }
  49. }
  50. HRESULT
  51. CAsyncOutputPin::GetMediaType(int iPosition, CMediaType *pMediaType)
  52. {
  53.     if (iPosition < 0) {
  54. return E_INVALIDARG;
  55.     }
  56.     if (iPosition > 0) {
  57. return VFW_S_NO_MORE_ITEMS;
  58.     }
  59.     *pMediaType = *m_pReader->LoadType();
  60.     return S_OK;
  61. }
  62. HRESULT
  63. CAsyncOutputPin::CheckMediaType(const CMediaType* pType)
  64. {
  65.     CAutoLock lck(m_pLock);
  66.     /*  We treat MEDIASUBTYPE_NULL subtype as a wild card */
  67.     if ((m_pReader->LoadType()->majortype == pType->majortype) &&
  68. (m_pReader->LoadType()->subtype == MEDIASUBTYPE_NULL ||
  69.          m_pReader->LoadType()->subtype == pType->subtype)) {
  70.     return S_OK;
  71.     }
  72.     return S_FALSE;
  73. }
  74. HRESULT
  75. CAsyncOutputPin::InitAllocator(IMemAllocator **ppAlloc)
  76. {
  77.     HRESULT hr = NOERROR;
  78.     *ppAlloc = NULL;
  79.     CMemAllocator *pMemObject = NULL;
  80.     /* Create a default memory allocator */
  81.     pMemObject = new CMemAllocator(NAME("Base memory allocator"),NULL, &hr);
  82.     if (pMemObject == NULL) {
  83. return E_OUTOFMEMORY;
  84.     }
  85.     if (FAILED(hr)) {
  86. delete pMemObject;
  87. return hr;
  88.     }
  89.     /* Get a reference counted IID_IMemAllocator interface */
  90.     hr = pMemObject->QueryInterface(IID_IMemAllocator,(void **)ppAlloc);
  91.     if (FAILED(hr)) {
  92. delete pMemObject;
  93. return E_NOINTERFACE;
  94.     }
  95.     ASSERT(*ppAlloc != NULL);
  96.     return NOERROR;
  97. }
  98. // we need to return an addrefed allocator, even if it is the preferred
  99. // one, since he doesn't know whether it is the preferred one or not.
  100. STDMETHODIMP
  101. CAsyncOutputPin::RequestAllocator(
  102.     IMemAllocator* pPreferred,
  103.     ALLOCATOR_PROPERTIES* pProps,
  104.     IMemAllocator ** ppActual)
  105. {
  106.     // we care about alignment but nothing else
  107.     if (!pProps->cbAlign || !m_pIo->IsAligned(pProps->cbAlign)) {
  108.        m_pIo->Alignment(&pProps->cbAlign);
  109.     }
  110.     ALLOCATOR_PROPERTIES Actual;
  111.     HRESULT hr;
  112.     if (pPreferred) {
  113. hr = pPreferred->SetProperties(pProps, &Actual);
  114. if (SUCCEEDED(hr) && m_pIo->IsAligned(Actual.cbAlign)) {
  115.             pPreferred->AddRef();
  116.     *ppActual = pPreferred;
  117.             return S_OK;
  118.         }
  119.     }
  120.     // create our own allocator
  121.     IMemAllocator* pAlloc;
  122.     hr = InitAllocator(&pAlloc);
  123.     if (FAILED(hr)) {
  124.         return hr;
  125.     }
  126.     //...and see if we can make it suitable
  127.     hr = pAlloc->SetProperties(pProps, &Actual);
  128.     if (SUCCEEDED(hr) && m_pIo->IsAligned(Actual.cbAlign)) {
  129.         // we need to release our refcount on pAlloc, and addref
  130.         // it to pass a refcount to the caller - this is a net nothing.
  131.         *ppActual = pAlloc;
  132.         return S_OK;
  133.     }
  134.     // failed to find a suitable allocator
  135.     pAlloc->Release();
  136.     // if we failed because of the IsAligned test, the error code will
  137.     // not be failure
  138.     if (SUCCEEDED(hr)) {
  139.         hr = VFW_E_BADALIGN;
  140.     }
  141.     return hr;
  142. }
  143. // queue an aligned read request. call WaitForNext to get
  144. // completion.
  145. STDMETHODIMP
  146. CAsyncOutputPin::Request(
  147.     IMediaSample* pSample,
  148.     DWORD dwUser)         // user context
  149. {
  150.     REFERENCE_TIME tStart, tStop;
  151.     HRESULT hr = pSample->GetTime(&tStart, &tStop);
  152.     if (FAILED(hr)) {
  153. return hr;
  154.     }
  155.     LONGLONG llPos = tStart / UNITS;
  156.     LONG lLength = (LONG) ((tStop - tStart) / UNITS);
  157.     LONGLONG llTotal;
  158.     LONGLONG llAvailable;
  159.     hr = m_pIo->Length(&llTotal, &llAvailable);
  160.     if (llPos + lLength > llTotal) {
  161.         // the end needs to be aligned, but may have been aligned
  162.         // on a coarser alignment.
  163.         LONG lAlign;
  164.         m_pIo->Alignment(&lAlign);
  165.         llTotal = (llTotal + lAlign -1) & ~(lAlign-1);
  166.         if (llPos + lLength > llTotal) {
  167.             lLength = (LONG) (llTotal - llPos);
  168.             // must be reducing this!
  169.             ASSERT((llTotal * UNITS) <= tStop);
  170.             tStop = llTotal * UNITS;
  171.             pSample->SetTime(&tStart, &tStop);
  172.         }
  173.     }
  174.     BYTE* pBuffer;
  175.     hr = pSample->GetPointer(&pBuffer);
  176.     if (FAILED(hr)) {
  177. return hr;
  178.     }
  179.     return m_pIo->Request(
  180. llPos,
  181. lLength,
  182.                         TRUE,
  183. pBuffer,
  184. (LPVOID)pSample,
  185. dwUser);
  186. }
  187. // sync-aligned request. just like a request/waitfornext pair.
  188. STDMETHODIMP
  189. CAsyncOutputPin::SyncReadAligned(
  190.                   IMediaSample* pSample)
  191. {
  192.     REFERENCE_TIME tStart, tStop;
  193.     HRESULT hr = pSample->GetTime(&tStart, &tStop);
  194.     if (FAILED(hr)) {
  195. return hr;
  196.     }
  197.     LONGLONG llPos = tStart / UNITS;
  198.     LONG lLength = (LONG) ((tStop - tStart) / UNITS);
  199.     LONGLONG llTotal;
  200.     LONGLONG llAvailable;
  201.     hr = m_pIo->Length(&llTotal, &llAvailable);
  202.     if (llPos + lLength > llTotal) {
  203.         // the end needs to be aligned, but may have been aligned
  204.         // on a coarser alignment.
  205.         LONG lAlign;
  206.         m_pIo->Alignment(&lAlign);
  207.         llTotal = (llTotal + lAlign -1) & ~(lAlign-1);
  208.         if (llPos + lLength > llTotal) {
  209.             lLength = (LONG) (llTotal - llPos);
  210.             // must be reducing this!
  211.             ASSERT((llTotal * UNITS) <= tStop);
  212.             tStop = llTotal * UNITS;
  213.             pSample->SetTime(&tStart, &tStop);
  214.         }
  215.     }
  216.     BYTE* pBuffer;
  217.     hr = pSample->GetPointer(&pBuffer);
  218.     if (FAILED(hr)) {
  219. return hr;
  220.     }
  221.     LONG cbActual;
  222.     hr = m_pIo->SyncReadAligned(
  223. llPos,
  224. lLength,
  225. pBuffer,
  226.                         &cbActual
  227.                         );
  228.     pSample->SetActualDataLength(cbActual);
  229.     return hr;
  230. }
  231. //
  232. // collect the next ready sample
  233. STDMETHODIMP
  234. CAsyncOutputPin::WaitForNext(
  235.     DWORD dwTimeout,
  236.     IMediaSample** ppSample,  // completed sample
  237.     DWORD * pdwUser) // user context
  238. {
  239.     LONG cbActual;
  240.     IMediaSample* pSample;
  241.     HRESULT hr =  m_pIo->WaitForNext(
  242.     dwTimeout,
  243.     (LPVOID*) &pSample,
  244.     pdwUser,
  245.                             &cbActual
  246.                             );
  247.     if (SUCCEEDED(hr)) {
  248.         pSample->SetActualDataLength(cbActual);
  249.     }
  250.     *ppSample = pSample;
  251.     return hr;
  252. }
  253. //
  254. // synchronous read that need not be aligned.
  255. STDMETHODIMP
  256. CAsyncOutputPin::SyncRead(
  257.     LONGLONG llPosition, // absolute Io position
  258.     LONG lLength, // nr bytes required
  259.     BYTE* pBuffer) // write data here
  260. {
  261.     return m_pIo->SyncRead(llPosition, lLength, pBuffer);
  262. }
  263. // return the length of the file, and the length currently
  264. // available locally. We only support locally accessible files,
  265. // so they are always the same
  266. STDMETHODIMP
  267. CAsyncOutputPin::Length(
  268.     LONGLONG* pTotal,
  269.     LONGLONG* pAvailable)
  270. {
  271.     HRESULT hr = m_pIo->Length(pTotal, pAvailable);
  272.     return hr;
  273. }
  274. STDMETHODIMP
  275. CAsyncOutputPin::BeginFlush(void)
  276. {
  277.     return m_pIo->BeginFlush();
  278. }
  279. STDMETHODIMP
  280. CAsyncOutputPin::EndFlush(void)
  281. {
  282.     return m_pIo->EndFlush();
  283. }
  284. // --- CAsyncReader implementation ---
  285. #pragma warning(disable:4355)
  286. CAsyncReader::CAsyncReader(
  287.     TCHAR *pName,
  288.     LPUNKNOWN pUnk,
  289.     CAsyncStream *pStream,
  290.     HRESULT *phr)
  291.   : CBaseFilter(
  292.        pName,
  293. pUnk,
  294. &m_csFilter,
  295. CLSID_AsyncReader,
  296.         NULL
  297.     ),
  298.     m_OutputPin(
  299. phr,
  300. this,
  301. &m_Io,
  302. &m_csFilter),
  303.     m_Io(pStream)
  304. {
  305. }
  306. CAsyncReader::~CAsyncReader()
  307. {
  308. }
  309. int
  310. CAsyncReader::GetPinCount()
  311. {
  312.     return 1;
  313. }
  314. CBasePin *
  315. CAsyncReader::GetPin(int n)
  316. {
  317.     if ((GetPinCount() > 0) &&
  318. (n == 0)) {
  319. return &m_OutputPin;
  320.     } else {
  321. return NULL;
  322.     }
  323. }