00001
00002
00003
00004
00005 #include <streams.h>
00006 #include "asyncio.h"
00007 #include "asyncrdr.h"
00008
00009 CAsyncOutputPin::CAsyncOutputPin(
00010 HRESULT * phr,
00011 CAsyncReader *pReader,
00012 CAsyncIo *pIo,
00013 CCritSec * pLock)
00014 : CBasePin(
00015 NAME("Async output pin"),
00016 pReader,
00017 pLock,
00018 phr,
00019 L"Output",
00020 PINDIR_OUTPUT),
00021 m_pReader(pReader),
00022 m_pIo(pIo)
00023 {
00024
00025 }
00026
00027 CAsyncOutputPin::~CAsyncOutputPin()
00028 {
00029 }
00030
00031 STDMETHODIMP
00032 CAsyncOutputPin::NonDelegatingQueryInterface(REFIID riid, void** ppv)
00033 {
00034 CheckPointer(ppv,E_POINTER);
00035 if (riid == IID_IAsyncReader) {
00036 m_bQueriedForAsyncReader = TRUE;
00037 return GetInterface((IAsyncReader*) this, ppv);
00038 } else {
00039 return CBasePin::NonDelegatingQueryInterface(riid, ppv);
00040 }
00041 }
00042
00043 HRESULT
00044 CAsyncOutputPin::GetMediaType(int iPosition, CMediaType *pMediaType)
00045 {
00046 if (iPosition < 0) {
00047 return E_INVALIDARG;
00048 }
00049 if (iPosition > 0) {
00050 return VFW_S_NO_MORE_ITEMS;
00051 }
00052 *pMediaType = *m_pReader->LoadType();
00053 return S_OK;
00054 }
00055
00056 HRESULT
00057 CAsyncOutputPin::CheckMediaType(const CMediaType* pType)
00058 {
00059 CAutoLock lck(m_pLock);
00060
00061
00062 if ((m_pReader->LoadType()->majortype == pType->majortype) &&
00063 (m_pReader->LoadType()->subtype == MEDIASUBTYPE_NULL ||
00064 m_pReader->LoadType()->subtype == pType->subtype)) {
00065 return S_OK;
00066 }
00067 return S_FALSE;
00068 }
00069
00070 HRESULT
00071 CAsyncOutputPin::InitAllocator(IMemAllocator **ppAlloc)
00072 {
00073 HRESULT hr = NOERROR;
00074 *ppAlloc = NULL;
00075 CMemAllocator *pMemObject = NULL;
00076
00077
00078
00079 pMemObject = new CMemAllocator(NAME("Base memory allocator"),NULL, &hr);
00080 if (pMemObject == NULL) {
00081 return E_OUTOFMEMORY;
00082 }
00083
00084 if (FAILED(hr)) {
00085 delete pMemObject;
00086 return hr;
00087 }
00088
00089
00090
00091 hr = pMemObject->QueryInterface(IID_IMemAllocator,(void **)ppAlloc);
00092 if (FAILED(hr)) {
00093 delete pMemObject;
00094 return E_NOINTERFACE;
00095 }
00096 ASSERT(*ppAlloc != NULL);
00097 return NOERROR;
00098 }
00099
00100 STDMETHODIMP
00101 CAsyncOutputPin::RequestAllocator(
00102 IMemAllocator* pPreferred,
00103 ALLOCATOR_PROPERTIES* pProps,
00104 IMemAllocator ** ppActual)
00105 {
00106
00107 if (!pProps->cbAlign || !m_pIo->IsAligned(pProps->cbAlign)) {
00108 m_pIo->Alignment(&pProps->cbAlign);
00109 }
00110 ALLOCATOR_PROPERTIES Actual;
00111 HRESULT hr;
00112 if (pPreferred) {
00113 hr = pPreferred->SetProperties(pProps, &Actual);
00114 if (SUCCEEDED(hr) && m_pIo->IsAligned(Actual.cbAlign)) {
00115 pPreferred->AddRef();
00116 *ppActual = pPreferred;
00117 return S_OK;
00118 }
00119 }
00120
00121
00122 IMemAllocator* pAlloc;
00123 hr = InitAllocator(&pAlloc);
00124 if (FAILED(hr)) {
00125 return hr;
00126 }
00127
00128
00129 hr = pAlloc->SetProperties(pProps, &Actual);
00130 if (SUCCEEDED(hr) && m_pIo->IsAligned(Actual.cbAlign)) {
00131
00132
00133 *ppActual = pAlloc;
00134 return S_OK;
00135 }
00136
00137
00138 pAlloc->Release();
00139
00140
00141
00142 if (SUCCEEDED(hr)) {
00143 hr = VFW_E_BADALIGN;
00144 }
00145 return hr;
00146 }
00147
00148 STDMETHODIMP
00149 CAsyncOutputPin::Request(
00150 IMediaSample* pSample,
00151 DWORD dwUser)
00152 {
00153 REFERENCE_TIME tStart, tStop;
00154 HRESULT hr = pSample->GetTime(&tStart, &tStop);
00155 if (FAILED(hr)) {
00156 return hr;
00157 }
00158
00159 LONGLONG llPos = tStart / UNITS;
00160 LONG lLength = (LONG) ((tStop - tStart) / UNITS);
00161
00162 LONGLONG llTotal;
00163 LONGLONG llAvailable;
00164 hr = m_pIo->Length(&llTotal, &llAvailable);
00165 if (llPos + lLength > llTotal) {
00166
00167
00168
00169 LONG lAlign;
00170 m_pIo->Alignment(&lAlign);
00171 llTotal = (llTotal + lAlign -1) & ~(lAlign-1);
00172
00173 if (llPos + lLength > llTotal) {
00174 lLength = (LONG) (llTotal - llPos);
00175
00176
00177 ASSERT((llTotal * UNITS) <= tStop);
00178 tStop = llTotal * UNITS;
00179 pSample->SetTime(&tStart, &tStop);
00180 }
00181 }
00182
00183 BYTE* pBuffer;
00184 hr = pSample->GetPointer(&pBuffer);
00185 if (FAILED(hr)) {
00186 return hr;
00187 }
00188
00189 return m_pIo->Request(
00190 llPos,
00191 lLength,
00192 TRUE,
00193 pBuffer,
00194 (LPVOID)pSample,
00195 dwUser);
00196 }
00197
00198 STDMETHODIMP
00199 CAsyncOutputPin::SyncReadAligned(
00200 IMediaSample* pSample)
00201 {
00202 REFERENCE_TIME tStart, tStop;
00203 HRESULT hr = pSample->GetTime(&tStart, &tStop);
00204 if (FAILED(hr)) {
00205 return hr;
00206 }
00207
00208 LONGLONG llPos = tStart / UNITS;
00209 LONG lLength = (LONG) ((tStop - tStart) / UNITS);
00210
00211 LONGLONG llTotal;
00212 LONGLONG llAvailable;
00213 hr = m_pIo->Length(&llTotal, &llAvailable);
00214 if (llPos + lLength > llTotal) {
00215
00216
00217
00218 LONG lAlign;
00219 m_pIo->Alignment(&lAlign);
00220 llTotal = (llTotal + lAlign -1) & ~(lAlign-1);
00221
00222 if (llPos + lLength > llTotal) {
00223 lLength = (LONG) (llTotal - llPos);
00224
00225
00226 ASSERT((llTotal * UNITS) <= tStop);
00227 tStop = llTotal * UNITS;
00228 pSample->SetTime(&tStart, &tStop);
00229 }
00230 }
00231
00232 BYTE* pBuffer;
00233 hr = pSample->GetPointer(&pBuffer);
00234 if (FAILED(hr)) {
00235 return hr;
00236 }
00237
00238 LONG cbActual;
00239 hr = m_pIo->SyncReadAligned(
00240 llPos,
00241 lLength,
00242 pBuffer,
00243 &cbActual,
00244 pSample
00245 );
00246
00247 pSample->SetActualDataLength(cbActual);
00248
00249 return hr;
00250 }
00251
00252 STDMETHODIMP
00253 CAsyncOutputPin::WaitForNext(
00254 DWORD dwTimeout,
00255 IMediaSample** ppSample,
00256 DWORD * pdwUser)
00257 {
00258 LONG cbActual;
00259
00260 IMediaSample* pSample;
00261 HRESULT hr = m_pIo->WaitForNext(
00262 dwTimeout,
00263 (LPVOID*) &pSample,
00264 pdwUser,
00265 &cbActual
00266 );
00267 if (SUCCEEDED(hr)) {
00268 pSample->SetActualDataLength(cbActual);
00269 }
00270 *ppSample = pSample;
00271
00272 return hr;
00273 }
00274
00275 STDMETHODIMP
00276 CAsyncOutputPin::SyncRead(
00277 LONGLONG llPosition,
00278 LONG lLength,
00279 BYTE* pBuffer)
00280 {
00281 return m_pIo->SyncRead(llPosition, lLength, pBuffer);
00282 }
00283
00284 STDMETHODIMP
00285 CAsyncOutputPin::Length(
00286 LONGLONG* pTotal,
00287 LONGLONG* pAvailable)
00288 {
00289 HRESULT hr = m_pIo->Length(pTotal, pAvailable);
00290 return hr;
00291 }
00292
00293 STDMETHODIMP
00294 CAsyncOutputPin::BeginFlush(void)
00295 {
00296 return m_pIo->BeginFlush();
00297 }
00298
00299 STDMETHODIMP
00300 CAsyncOutputPin::EndFlush(void)
00301 {
00302 return m_pIo->EndFlush();
00303 }
00304
00305 STDMETHODIMP
00306 CAsyncOutputPin::Connect(
00307 IPin * pReceivePin,
00308 const AM_MEDIA_TYPE *pmt
00309 )
00310 {
00311 return m_pReader->Connect(pReceivePin, pmt);
00312 }
00313
00314 #pragma warning(disable:4355)
00315
00316 CAsyncReader::CAsyncReader(
00317 TCHAR *pName,
00318 LPUNKNOWN pUnk,
00319 CAsyncStream *pStream,
00320 HRESULT *phr)
00321 : CBaseFilter(
00322 pName,
00323 pUnk,
00324 &m_csFilter,
00325 CLSID_AsyncReader,
00326 NULL
00327 ),
00328 m_OutputPin(
00329 phr,
00330 this,
00331 &m_Io,
00332 &m_csFilter),
00333 m_Io(pStream)
00334 {
00335
00336 }
00337
00338 CAsyncReader::~CAsyncReader()
00339 {
00340 }
00341
00342 int
00343 CAsyncReader::GetPinCount()
00344 {
00345 return 1;
00346 }
00347
00348 CBasePin *
00349 CAsyncReader::GetPin(int n)
00350 {
00351 if ((GetPinCount() > 0) &&
00352 (n == 0)) {
00353 return &m_OutputPin;
00354 } else {
00355 return NULL;
00356 }
00357 }
00358