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

DirextX编程

开发平台:

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