Asyncrdr.cpp
上传用户:tuheem
上传日期:2007-05-01
资源大小:21889k
文件大小:10k
源码类别:

多媒体编程

开发平台:

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