- Main Page
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

# asyncrdr.cpp

    00001 //------------------------------------------------------------------------------
    00002 // File: AsyncRdr.cpp
    00003 //
    00004 // Desc: DirectShow sample code - base library with I/O functionality.
    00005 //       This file implements I/O source filter methods and output pin
    00006 //       methods for CAsyncReader and CAsyncOutputPin.
    00007 //
    00008 // Copyright (c) 1992-2001 Microsoft Corporation.  All rights reserved.
    00009 //------------------------------------------------------------------------------
    00010
    00011
    00012 #include "stdafx.h"
    00013 #include "asyncio.h"
    00014 #include "asyncrdr.h"
    00015
    00016 // --- CAsyncOutputPin implementation ---
    00017
    00018 CAsyncOutputPin::CAsyncOutputPin(
    00019     HRESULT * phr,
    00020     CAsyncReader *pReader,
    00021     CAsyncIo *pIo,
    00022     CCritSec * pLock)
    00023   : CBasePin(
    00024         NAME("Async output pin"),
    00025         pReader,
    00026         pLock,
    00027         phr,
    00028         L"Output",
    00029         PINDIR_OUTPUT),
    00030     m_pReader(pReader),
    00031     m_pIo(pIo)
    00032 {
    00033 }
    00034
    00035 CAsyncOutputPin::~CAsyncOutputPin()
    00036 {
    00037 }
    00038
    00039 STDMETHODIMP
    00040 CAsyncOutputPin::NonDelegatingQueryInterface(REFIID riid, void** ppv)
    00041 {
    00042     CheckPointer(ppv,E_POINTER);
    00043
    00044     if (riid == IID_IAsyncReader) {
    00045         m_bQueriedForAsyncReader = TRUE;
    00046         return GetInterface((IAsyncReader*) this, ppv);
    00047     } else {
    00048         return CBasePin::NonDelegatingQueryInterface(riid, ppv);
    00049     }
    00050 }
    00051
    00052 HRESULT
    00053 CAsyncOutputPin::GetMediaType(int iPosition, CMediaType *pMediaType)
    00054 {
    00055     if (iPosition < 0) {
    00056         return E_INVALIDARG;
    00057     }
    00058     if (iPosition > 0) {
    00059         return VFW_S_NO_MORE_ITEMS;
    00060     }
    00061
    00062     *pMediaType = *m_pReader->LoadType();
    00063     return S_OK;
    00064 }
    00065
    00066 HRESULT
    00067 CAsyncOutputPin::CheckMediaType(const CMediaType* pType)
    00068 {
    00069     CAutoLock lck(m_pLock);
    00070
    00071     /*  We treat MEDIASUBTYPE_NULL subtype as a wild card */
    00072     if ((m_pReader->LoadType()->majortype == pType->majortype) &&
    00073         (m_pReader->LoadType()->subtype == MEDIASUBTYPE_NULL ||
    00074          m_pReader->LoadType()->subtype == pType->subtype)) {
    00075             return S_OK;
    00076     }
    00077     return S_FALSE;
    00078 }
    00079
    00080 HRESULT
    00081 CAsyncOutputPin::InitAllocator(IMemAllocator **ppAlloc)
    00082 {
    00083     HRESULT hr = NOERROR;
    00084     *ppAlloc = NULL;
    00085     CMemAllocator *pMemObject = NULL;
    00086
    00087     /* Create a default memory allocator */
    00088     pMemObject = new CMemAllocator(NAME("Base memory allocator"),NULL, &hr);
    00089     if (pMemObject == NULL) {
    00090         return E_OUTOFMEMORY;
    00091     }
    00092
    00093     if (FAILED(hr)) {
    00094             delete pMemObject;
    00095             return hr;
    00096     }
    00097
    00098     /* Get a reference counted IID_IMemAllocator interface */
    00099     hr = pMemObject->QueryInterface(IID_IMemAllocator,(void **)ppAlloc);
    00100     if (FAILED(hr)) {
    00101             delete pMemObject;
    00102             return E_NOINTERFACE;
    00103     }
    00104
    00105     ASSERT(*ppAlloc != NULL);
    00106     return NOERROR;
    00107 }
    00108
    00109 // we need to return an addrefed allocator, even if it is the preferred
    00110 // one, since he doesn't know whether it is the preferred one or not.
    00111 STDMETHODIMP
    00112 CAsyncOutputPin::RequestAllocator(
    00113     IMemAllocator* pPreferred,
    00114     ALLOCATOR_PROPERTIES* pProps,
    00115     IMemAllocator ** ppActual)
    00116 {
    00117     // we care about alignment but nothing else
    00118     if (!pProps->cbAlign || !m_pIo->IsAligned(pProps->cbAlign)) {
    00119        m_pIo->Alignment(&pProps->cbAlign);
    00120     }
    00121
    00122     ALLOCATOR_PROPERTIES Actual;
    00123     HRESULT hr;
    00124
    00125     if (pPreferred) {
    00126             hr = pPreferred->SetProperties(pProps, &Actual);
    00127             if (SUCCEEDED(hr) && m_pIo->IsAligned(Actual.cbAlign)) {
    00128             pPreferred->AddRef();
    00129             *ppActual = pPreferred;
    00130             return S_OK;
    00131         }
    00132     }
    00133
    00134     // create our own allocator
    00135     IMemAllocator* pAlloc;
    00136     hr = InitAllocator(&pAlloc);
    00137     if (FAILED(hr)) {
    00138         return hr;
    00139     }
    00140
    00141     //...and see if we can make it suitable
    00142     hr = pAlloc->SetProperties(pProps, &Actual);
    00143     if (SUCCEEDED(hr) && m_pIo->IsAligned(Actual.cbAlign)) {
    00144         // we need to release our refcount on pAlloc, and addref
    00145         // it to pass a refcount to the caller - this is a net nothing.
    00146         *ppActual = pAlloc;
    00147         return S_OK;
    00148     }
    00149
    00150     // failed to find a suitable allocator
    00151     pAlloc->Release();
    00152
    00153     // if we failed because of the IsAligned test, the error code will
    00154     // not be failure
    00155     if (SUCCEEDED(hr)) {
    00156         hr = VFW_E_BADALIGN;
    00157     }
    00158     return hr;
    00159 }
    00160
    00161
    00162 // queue an aligned read request. call WaitForNext to get
    00163 // completion.
    00164 STDMETHODIMP
    00165 CAsyncOutputPin::Request(
    00166     IMediaSample* pSample,
    00167     DWORD dwUser)               // user context
    00168 {
    00169     REFERENCE_TIME tStart, tStop;
    00170     HRESULT hr = pSample->GetTime(&tStart, &tStop);
    00171     if (FAILED(hr)) {
    00172         return hr;
    00173     }
    00174
    00175     LONGLONG llPos = tStart / UNITS;
    00176     LONG lLength = (LONG) ((tStop - tStart) / UNITS);
    00177     LONGLONG llTotal;
    00178     LONGLONG llAvailable;
    00179
    00180     hr = m_pIo->Length(&llTotal, &llAvailable);
    00181     if (llPos + lLength > llTotal) {
    00182
    00183         // the end needs to be aligned, but may have been aligned
    00184         // on a coarser alignment.
    00185         LONG lAlign;
    00186         m_pIo->Alignment(&lAlign);
    00187         llTotal = (llTotal + lAlign -1) & ~(lAlign-1);
    00188
    00189         if (llPos + lLength > llTotal) {
    00190             lLength = (LONG) (llTotal - llPos);
    00191
    00192             // must be reducing this!
    00193             ASSERT((llTotal * UNITS) <= tStop);
    00194             tStop = llTotal * UNITS;
    00195             pSample->SetTime(&tStart, &tStop);
    00196         }
    00197     }
    00198
    00199
    00200     BYTE* pBuffer;
    00201     hr = pSample->GetPointer(&pBuffer);
    00202     if (FAILED(hr)) {
    00203         return hr;
    00204     }
    00205
    00206     return m_pIo->Request(
    00207                         llPos,
    00208                         lLength,
    00209             TRUE,
    00210                         pBuffer,
    00211                         (LPVOID)pSample,
    00212                         dwUser);
    00213 }
    00214
    00215 // sync-aligned request. just like a request/waitfornext pair.
    00216 STDMETHODIMP
    00217 CAsyncOutputPin::SyncReadAligned(
    00218                   IMediaSample* pSample)
    00219 {
    00220     REFERENCE_TIME tStart, tStop;
    00221     HRESULT hr = pSample->GetTime(&tStart, &tStop);
    00222     if (FAILED(hr)) {
    00223         return hr;
    00224     }
    00225
    00226     LONGLONG llPos = tStart / UNITS;
    00227     LONG lLength = (LONG) ((tStop - tStart) / UNITS);
    00228     LONGLONG llTotal;
    00229     LONGLONG llAvailable;
    00230
    00231     hr = m_pIo->Length(&llTotal, &llAvailable);
    00232     if (llPos + lLength > llTotal) {
    00233
    00234         // the end needs to be aligned, but may have been aligned
    00235         // on a coarser alignment.
    00236         LONG lAlign;
    00237         m_pIo->Alignment(&lAlign);
    00238         llTotal = (llTotal + lAlign -1) & ~(lAlign-1);
    00239
    00240         if (llPos + lLength > llTotal) {
    00241             lLength = (LONG) (llTotal - llPos);
    00242
    00243             // must be reducing this!
    00244             ASSERT((llTotal * UNITS) <= tStop);
    00245             tStop = llTotal * UNITS;
    00246             pSample->SetTime(&tStart, &tStop);
    00247         }
    00248     }
    00249
    00250
    00251     BYTE* pBuffer;
    00252     hr = pSample->GetPointer(&pBuffer);
    00253     if (FAILED(hr)) {
    00254         return hr;
    00255     }
    00256
    00257     LONG cbActual;
    00258     hr = m_pIo->SyncReadAligned(
    00259                         llPos,
    00260                         lLength,
    00261                         pBuffer,
    00262             &cbActual,
    00263             pSample
    00264             );
    00265
    00266     pSample->SetActualDataLength(cbActual);
    00267     return hr;
    00268 }
    00269
    00270
    00271 //
    00272 // collect the next ready sample
    00273 STDMETHODIMP
    00274 CAsyncOutputPin::WaitForNext(
    00275     DWORD dwTimeout,
    00276     IMediaSample** ppSample,  // completed sample
    00277     DWORD * pdwUser)            // user context
    00278 {
    00279     LONG cbActual;
    00280     IMediaSample* pSample;
    00281
    00282     HRESULT hr =  m_pIo->WaitForNext(
    00283                             dwTimeout,
    00284                             (LPVOID*) &pSample,
    00285                             pdwUser,
    00286                 &cbActual
    00287                 );
    00288
    00289     if (SUCCEEDED(hr)) {
    00290         pSample->SetActualDataLength(cbActual);
    00291     }
    00292
    00293     *ppSample = pSample;
    00294     return hr;
    00295 }
    00296
    00297
    00298 //
    00299 // synchronous read that need not be aligned.
    00300 STDMETHODIMP
    00301 CAsyncOutputPin::SyncRead(
    00302     LONGLONG llPosition,        // absolute Io position
    00303     LONG lLength,               // nr bytes required
    00304     BYTE* pBuffer)              // write data here
    00305 {
    00306     return m_pIo->SyncRead(llPosition, lLength, pBuffer);
    00307 }
    00308
    00309 // return the length of the file, and the length currently
    00310 // available locally. We only support locally accessible files,
    00311 // so they are always the same
    00312 STDMETHODIMP
    00313 CAsyncOutputPin::Length(
    00314     LONGLONG* pTotal,
    00315     LONGLONG* pAvailable)
    00316 {
    00317     HRESULT hr = m_pIo->Length(pTotal, pAvailable);
    00318     return hr;
    00319 }
    00320
    00321 STDMETHODIMP
    00322 CAsyncOutputPin::BeginFlush(void)
    00323 {
    00324     return m_pIo->BeginFlush();
    00325 }
    00326
    00327 STDMETHODIMP
    00328 CAsyncOutputPin::EndFlush(void)
    00329 {
    00330     return m_pIo->EndFlush();
    00331 }
    00332
    00333
    00334 STDMETHODIMP
    00335 CAsyncOutputPin::Connect(
    00336     IPin * pReceivePin,
    00337     const AM_MEDIA_TYPE *pmt   // optional media type
    00338 )
    00339 {
    00340     return m_pReader->Connect(pReceivePin, pmt);
    00341 }
    00342
    00343
    00344 // --- CAsyncReader implementation ---
    00345
    00346 #pragma warning(disable:4355)
    00347
    00348 CAsyncReader::CAsyncReader(
    00349     TCHAR *pName,
    00350     LPUNKNOWN pUnk,
    00351     CAsyncStream *pStream,
    00352     HRESULT *phr,
    00353         const CLSID& clsid)
    00354   : CBaseFilter(
    00355         pName,
    00356             pUnk,
    00357             &m_csFilter,
    00358             clsid,
    00359         NULL
    00360         ),
    00361     m_OutputPin(
    00362         phr,
    00363         this,
    00364         &m_Io,
    00365         &m_csFilter),
    00366     m_Io(pStream)
    00367 {
    00368 }
    00369
    00370 CAsyncReader::~CAsyncReader()
    00371 {
    00372 }
    00373
    00374 STDMETHODIMP CAsyncReader::NonDelegatingQueryInterface(REFIID riid, void** ppv)
    00375 {
    00376     CheckPointer(ppv, E_POINTER);
    00377
    00378         return
    00379                 (riid == __uuidof(IAMFilterMiscFlags)) ? GetInterface((IAMFilterMiscFlags*)this, ppv) :
    00380                 __super::NonDelegatingQueryInterface(riid, ppv);
    00381 }
    00382
    00383 // IAMFilterMiscFlags
    00384
    00385 ULONG CAsyncReader::GetMiscFlags()
    00386 {
    00387         return AM_FILTER_MISC_FLAGS_IS_SOURCE;
    00388 }
    00389
    00390
    00391 int
    00392 CAsyncReader::GetPinCount()
    00393 {
    00394     return 1;
    00395 }
    00396
    00397 CBasePin *
    00398 CAsyncReader::GetPin(int n)
    00399 {
    00400     if ((GetPinCount() > 0) && (n == 0)) {
    00401         return &m_OutputPin;
    00402     } else {
    00403         return NULL;
    00404     }
    00405 }
    00406
    00407