asyncrdr.cpp
上传用户:xjjlds
上传日期:2015-12-05
资源大小:22823k
文件大小:9k
源码类别:

多媒体编程

开发平台:

Visual C++

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