Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mpc-hc/mpc-hc.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkinddragon <kinddragon@users.sourceforge.net>2010-05-28 01:54:24 +0400
committerkinddragon <kinddragon@users.sourceforge.net>2010-05-28 01:54:24 +0400
commit7097fdb1c137e27c5993d1764c13928688802554 (patch)
tree9ad473ced569114d463e52e988fca8fece9b16b5 /src/filters/reader
parent96084bc5c1a3d4e74ba9e240ea6d13387cae0f7f (diff)
Updated ASync Reader
git-svn-id: https://mpc-hc.svn.sourceforge.net/svnroot/mpc-hc/trunk@1960 10f7b99b-c216-0410-bff0-8a66a9350fd8
Diffstat (limited to 'src/filters/reader')
-rw-r--r--src/filters/reader/asyncreader/asyncio.cpp373
-rw-r--r--src/filters/reader/asyncreader/asyncio.h113
-rw-r--r--src/filters/reader/asyncreader/asyncrdr.cpp277
-rw-r--r--src/filters/reader/asyncreader/asyncrdr.h38
4 files changed, 465 insertions, 336 deletions
diff --git a/src/filters/reader/asyncreader/asyncio.cpp b/src/filters/reader/asyncreader/asyncio.cpp
index 3f6494a6f..071091712 100644
--- a/src/filters/reader/asyncreader/asyncio.cpp
+++ b/src/filters/reader/asyncreader/asyncio.cpp
@@ -3,11 +3,12 @@
//
// Desc: DirectShow sample code - base library with I/O functionality.
//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
+// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------
#include "stdafx.h"
+#include <streams.h>
#include "asyncio.h"
// --- CAsyncRequest ---
@@ -28,8 +29,8 @@ CAsyncRequest::Request(
LONG lLength,
BOOL bAligned,
BYTE* pBuffer,
- LPVOID pContext, // filter's context
- DWORD dwUser) // downstream filter's context
+ LPVOID pContext, // filter's context
+ DWORD_PTR dwUser) // downstream filter's context
{
m_pIo = pIo;
m_pStream = pStream;
@@ -55,25 +56,32 @@ CAsyncRequest::Complete()
m_pStream->Lock();
m_hr = m_pStream->SetPointer(m_llPos);
- if (S_OK == m_hr) {
-
+ if(S_OK == m_hr)
+ {
DWORD dwActual;
m_hr = m_pStream->Read(m_pBuffer, m_lLength, m_bAligned, &dwActual);
- if (m_hr == OLE_S_FIRST) {
- if (m_pContext) {
+ if(m_hr == OLE_S_FIRST)
+ {
+ if(m_pContext)
+ {
IMediaSample *pSample = reinterpret_cast<IMediaSample *>(m_pContext);
pSample->SetDiscontinuity(TRUE);
m_hr = S_OK;
}
}
- if (FAILED(m_hr)) {
- } else if (dwActual != (DWORD)m_lLength) {
+ if(FAILED(m_hr))
+ {
+ }
+ else if(dwActual != (DWORD)m_lLength)
+ {
// tell caller size changed - probably because of EOF
m_lLength = (LONG) dwActual;
m_hr = S_FALSE;
- } else {
+ }
+ else
+ {
m_hr = S_OK;
}
}
@@ -83,22 +91,21 @@ CAsyncRequest::Complete()
}
-
// --- CAsyncIo ---
// note - all events created manual reset
CAsyncIo::CAsyncIo(CAsyncStream *pStream)
- : m_hThread(NULL),
- m_evWork(TRUE),
- m_evDone(TRUE),
- m_evStop(TRUE),
- m_listWork(NAME("Work list")),
- m_listDone(NAME("Done list")),
- m_bFlushing(FALSE),
- m_cItemsOut(0),
- m_bWaiting(FALSE),
- m_pStream(pStream)
+ : m_hThread(NULL),
+ m_evWork(TRUE),
+ m_evDone(TRUE),
+ m_evStop(TRUE),
+ m_listWork(NAME("Work list")),
+ m_listDone(NAME("Done list")),
+ m_bFlushing(FALSE),
+ m_cItemsOut(0),
+ m_bWaiting(FALSE),
+ m_pStream(pStream)
{
}
@@ -114,13 +121,16 @@ CAsyncIo::~CAsyncIo()
// empty the done list
POSITION pos = m_listDone.GetHeadPosition();
- while (pos) {
+ while(pos)
+ {
CAsyncRequest* pRequest = m_listDone.GetNext(pos);
delete pRequest;
}
+
m_listDone.RemoveAll();
}
+
// ready for async activity - call this before calling Request.
//
// start the worker thread if we need to
@@ -146,40 +156,46 @@ CAsyncIo::AsyncInactive(void)
// add a request to the queue.
HRESULT
CAsyncIo::Request(
- LONGLONG llPos,
- LONG lLength,
- BOOL bAligned,
- BYTE* pBuffer,
- LPVOID pContext,
- DWORD dwUser)
+ LONGLONG llPos,
+ LONG lLength,
+ BOOL bAligned,
+ BYTE * pBuffer,
+ LPVOID pContext,
+ DWORD_PTR dwUser)
{
- if (bAligned) {
- if (!IsAligned(llPos) ||
- !IsAligned(lLength) ||
- !IsAligned((LONG) pBuffer)) {
+ if(bAligned)
+ {
+ if(!IsAligned(llPos) ||
+ !IsAligned(lLength) ||
+ !IsAligned((LONG_PTR) pBuffer))
+ {
return VFW_E_BADALIGN;
}
}
- CAsyncRequest* pRequest = DNew CAsyncRequest;
+ CAsyncRequest* pRequest = new CAsyncRequest;
+ if (!pRequest)
+ return E_OUTOFMEMORY;
- HRESULT hr = pRequest->Request(
- this,
- m_pStream,
- llPos,
- lLength,
- bAligned,
- pBuffer,
- pContext,
- dwUser);
- if (SUCCEEDED(hr)) {
+ HRESULT hr = pRequest->Request(this,
+ m_pStream,
+ llPos,
+ lLength,
+ bAligned,
+ pBuffer,
+ pContext,
+ dwUser);
+ if(SUCCEEDED(hr))
+ {
// might fail if flushing
hr = PutWorkItem(pRequest);
}
- if (FAILED(hr)) {
+ if(FAILED(hr))
+ {
delete pRequest;
}
+
return hr;
}
@@ -188,38 +204,47 @@ CAsyncIo::Request(
HRESULT
CAsyncIo::WaitForNext(
DWORD dwTimeout,
- LPVOID *ppContext,
- DWORD * pdwUser,
- LONG* pcbActual)
+ LPVOID * ppContext,
+ DWORD_PTR * pdwUser,
+ LONG * pcbActual)
{
+ CheckPointer(ppContext,E_POINTER);
+ CheckPointer(pdwUser,E_POINTER);
+ CheckPointer(pcbActual,E_POINTER);
+
// some errors find a sample, others don't. Ensure that
// *ppContext is NULL if no sample found
*ppContext = NULL;
// wait until the event is set, but since we are not
// holding the critsec when waiting, we may need to re-wait
- for (;;) {
-
- if (!m_evDone.Wait(dwTimeout)) {
+ for(;;)
+ {
+ if(!m_evDone.Wait(dwTimeout))
+ {
// timeout occurred
return VFW_E_TIMEOUT;
}
// get next event from list
CAsyncRequest* pRequest = GetDoneItem();
- if (pRequest) {
+ if(pRequest)
+ {
// found a completed request
// check if ok
HRESULT hr = pRequest->GetHResult();
- if (hr == S_FALSE) {
-
+ if(hr == S_FALSE)
+ {
// this means the actual length was less than
// requested - may be ok if he aligned the end of file
- if ((pRequest->GetActualLength() +
- pRequest->GetStart()) == Size()) {
+ if((pRequest->GetActualLength() +
+ pRequest->GetStart()) == Size())
+ {
hr = S_OK;
- } else {
+ }
+ else
+ {
// it was an actual read error
hr = E_FAIL;
}
@@ -234,11 +259,13 @@ CAsyncIo::WaitForNext(
delete pRequest;
return hr;
- } else {
+ }
+ else
+ {
// Hold the critical section while checking the list state
CAutoLock lck(&m_csLists);
- if (m_bFlushing && !m_bWaiting) {
-
+ if(m_bFlushing && !m_bWaiting)
+ {
// can't block as we are between BeginFlush and EndFlush
// but note that if m_bWaiting is set, then there are some
@@ -253,38 +280,38 @@ CAsyncIo::WaitForNext(
}
}
+
// perform a synchronous read request on this thread.
// Need to hold m_csFile while doing this (done in request object)
HRESULT
CAsyncIo::SyncReadAligned(
- LONGLONG llPos,
- LONG lLength,
- BYTE* pBuffer,
- LONG* pcbActual,
- PVOID pvContext
- )
+ LONGLONG llPos,
+ LONG lLength,
+ BYTE * pBuffer,
+ LONG * pcbActual,
+ PVOID pvContext)
{
- if (!IsAligned(llPos) ||
- !IsAligned(lLength) ||
- !IsAligned((LONG) pBuffer)) {
+ CheckPointer(pcbActual,E_POINTER);
+
+ if(!IsAligned(llPos) ||
+ !IsAligned(lLength) ||
+ !IsAligned((LONG_PTR) pBuffer))
+ {
return VFW_E_BADALIGN;
}
CAsyncRequest request;
- HRESULT hr = request.Request(
- this,
- m_pStream,
- llPos,
- lLength,
- TRUE,
- pBuffer,
- pvContext,
- 0);
-
- if (FAILED(hr)) {
+ HRESULT hr = request.Request(this,
+ m_pStream,
+ llPos,
+ lLength,
+ TRUE,
+ pBuffer,
+ pvContext,
+ 0);
+ if(FAILED(hr))
return hr;
- }
hr = request.Complete();
@@ -293,13 +320,17 @@ CAsyncIo::SyncReadAligned(
return hr;
}
+
HRESULT
-CAsyncIo::Length(LONGLONG *pllTotal, LONGLONG* pllAvailable)
+CAsyncIo::Length(LONGLONG *pllTotal, LONGLONG *pllAvailable)
{
+ CheckPointer(pllTotal,E_POINTER);
+
*pllTotal = m_pStream->Size(pllAvailable);
return S_OK;
}
+
// cancel all items on the worklist onto the done list
// and refuse further requests or further WaitForNext calls
// until the end flush
@@ -329,14 +360,15 @@ CAsyncIo::BeginFlush()
m_bFlushing = TRUE;
CAsyncRequest * preq;
- while((preq = GetWorkItem()) != 0) {
+ while((preq = GetWorkItem()) != 0)
+ {
preq->Cancel();
PutDoneItem(preq);
}
// now wait for any outstanding requests to complete
- if (m_cItemsOut > 0) {
-
+ if(m_cItemsOut > 0)
+ {
// can be only one person waiting
ASSERT(!m_bWaiting);
@@ -344,7 +376,9 @@ CAsyncIo::BeginFlush()
// signalled via m_evAllDone when all outstanding items are
// done. It also tells WaitForNext to continue blocking.
m_bWaiting = TRUE;
- } else {
+ }
+ else
+ {
// all done
// force m_evDone set so that even if list is empty,
@@ -359,14 +393,15 @@ CAsyncIo::BeginFlush()
ASSERT(m_bWaiting);
// wait without holding critsec
- for (;;) {
+ for(;;)
+ {
m_evAllDone.Wait();
{
// hold critsec to check
CAutoLock lock(&m_csLists);
- if (m_cItemsOut == 0) {
-
+ if(m_cItemsOut == 0)
+ {
// now we are sure that all outstanding requests are on
// the done list and no more will be accepted
m_bWaiting = FALSE;
@@ -383,6 +418,7 @@ CAsyncIo::BeginFlush()
}
}
+
// end a flushing state
HRESULT
CAsyncIo::EndFlush()
@@ -395,20 +431,25 @@ CAsyncIo::EndFlush()
// m_evDone might have been set by BeginFlush - ensure it is
// set IFF m_listDone is non-empty
- if (m_listDone.GetCount() > 0) {
+ if(m_listDone.GetCount() > 0)
+ {
m_evDone.Set();
- } else {
+ }
+ else
+ {
m_evDone.Reset();
}
return S_OK;
}
+
// start the thread
HRESULT
CAsyncIo::StartThread(void)
{
- if (m_hThread) {
+ if(m_hThread)
+ {
return S_OK;
}
@@ -416,20 +457,22 @@ CAsyncIo::StartThread(void)
m_evStop.Reset();
DWORD dwThreadID;
- m_hThread = CreateThread(
- NULL,
- 0,
- InitialThreadProc,
- this,
- 0,
- &dwThreadID);
- if (!m_hThread) {
- DWORD dwErr = GetLastError();
+ m_hThread = CreateThread(NULL,
+ 0,
+ InitialThreadProc,
+ this,
+ 0,
+ &dwThreadID);
+ if(!m_hThread)
+ {
+ DWORD dwErr = GetLastError();
return HRESULT_FROM_WIN32(dwErr);
}
+
return S_OK;
}
+
// stop the thread and close the handle
HRESULT
CAsyncIo::CloseThread(void)
@@ -437,12 +480,13 @@ CAsyncIo::CloseThread(void)
// signal the thread-exit object
m_evStop.Set();
- if (m_hThread) {
-
+ if(m_hThread)
+ {
WaitForSingleObject(m_hThread, INFINITE);
CloseHandle(m_hThread);
m_hThread = NULL;
}
+
return S_OK;
}
@@ -455,22 +499,23 @@ CAsyncRequest*
CAsyncIo::GetWorkItem()
{
CAutoLock lck(&m_csLists);
-
CAsyncRequest * preq = m_listWork.RemoveHead();
// force event set correctly
- if (m_listWork.GetCount() == 0) {
+ if(m_listWork.GetCount() == 0)
+ {
m_evWork.Reset();
}
+
return preq;
}
+
// get an item from the done list
CAsyncRequest*
CAsyncIo::GetDoneItem()
{
CAutoLock lock(&m_csLists);
-
CAsyncRequest * preq = m_listDone.RemoveHead();
// force event set correctly if list now empty
@@ -483,14 +528,16 @@ CAsyncIo::GetDoneItem()
// has moved to the done list which means we must wait until
// cItemsOut is 0 (which is guaranteed by m_bWaiting being TRUE).
- if (m_listDone.GetCount() == 0 &&
- (!m_bFlushing || m_bWaiting)) {
+ if(m_listDone.GetCount() == 0 &&
+ (!m_bFlushing || m_bWaiting))
+ {
m_evDone.Reset();
}
return preq;
}
+
// put an item on the work list - fail if bFlushing
HRESULT
CAsyncIo::PutWorkItem(CAsyncRequest* pRequest)
@@ -498,24 +545,28 @@ CAsyncIo::PutWorkItem(CAsyncRequest* pRequest)
CAutoLock lock(&m_csLists);
HRESULT hr;
- if (m_bFlushing) {
+ if(m_bFlushing)
+ {
hr = VFW_E_WRONG_STATE;
}
- else if (m_listWork.AddTail(pRequest)) {
-
+ else if(m_listWork.AddTail(pRequest))
+ {
// event should now be in a set state - force this
m_evWork.Set();
// start the thread now if not already started
hr = StartThread();
- } else {
+ }
+ else
+ {
hr = E_OUTOFMEMORY;
}
return(hr);
}
+
// put an item on the done list - ok to do this when
// flushing
HRESULT
@@ -523,28 +574,34 @@ CAsyncIo::PutDoneItem(CAsyncRequest* pRequest)
{
ASSERT(CritCheckIn(&m_csLists));
- if (m_listDone.AddTail(pRequest)) {
-
+ if(m_listDone.AddTail(pRequest))
+ {
// event should now be in a set state - force this
m_evDone.Set();
return S_OK;
- } else {
+ }
+ else
+ {
return E_OUTOFMEMORY;
}
}
+
// called on thread to process any active requests
void
CAsyncIo::ProcessRequests(void)
{
// lock to get the item and increment the outstanding count
CAsyncRequest * preq = NULL;
- for (;;) {
+
+ for(;;)
+ {
{
CAutoLock lock(&m_csLists);
preq = GetWorkItem();
- if (preq == NULL) {
+ if(preq == NULL)
+ {
// done
return;
}
@@ -563,15 +620,16 @@ CAsyncIo::ProcessRequests(void)
PutDoneItem(preq);
- if (--m_cItemsOut == 0) {
- if (m_bWaiting) {
+ if(--m_cItemsOut == 0)
+ {
+ if(m_bWaiting)
m_evAllDone.Set();
- }
}
}
}
}
+
// the thread proc - assumes that DWORD thread param is the
// this pointer
DWORD
@@ -579,38 +637,40 @@ CAsyncIo::ThreadProc(void)
{
HANDLE ahev[] = {m_evStop, m_evWork};
- for (;;) {
- DWORD dw = WaitForMultipleObjects(
- 2,
- ahev,
- FALSE,
- INFINITE);
- if (dw == WAIT_OBJECT_0+1) {
-
- // requests need processing
- ProcessRequests();
- } else {
- // any error or stop event - we should exit
- return 0;
- }
+ for(;;)
+ {
+ DWORD dw = WaitForMultipleObjects(2,
+ ahev,
+ FALSE,
+ INFINITE);
+ if(dw == WAIT_OBJECT_0+1)
+ {
+ // requests need processing
+ ProcessRequests();
+ }
+ else
+ {
+ // any error or stop event - we should exit
+ return 0;
+ }
}
}
-
// perform a synchronous read request on this thread.
// may not be aligned - so we will have to buffer.
HRESULT
CAsyncIo::SyncRead(
- LONGLONG llPos,
- LONG lLength,
- BYTE* pBuffer)
+ LONGLONG llPos,
+ LONG lLength,
+ BYTE * pBuffer)
{
- if (IsAligned(llPos) &&
- IsAligned(lLength) &&
- IsAligned((LONG) pBuffer)) {
+ if(IsAligned(llPos) &&
+ IsAligned(lLength) &&
+ IsAligned((LONG_PTR) pBuffer))
+ {
LONG cbUnused;
- return SyncReadAligned(llPos, lLength, pBuffer, &cbUnused, NULL);
+ return SyncReadAligned(llPos, lLength, pBuffer, &cbUnused, NULL);
}
// not aligned with requirements - use buffered file handle.
@@ -618,27 +678,32 @@ CAsyncIo::SyncRead(
CAsyncRequest request;
- HRESULT hr = request.Request(
- this,
- m_pStream,
- llPos,
- lLength,
- FALSE,
- pBuffer,
- NULL,
- 0);
-
- if (FAILED(hr)) {
+ HRESULT hr = request.Request(this,
+ m_pStream,
+ llPos,
+ lLength,
+ FALSE,
+ pBuffer,
+ NULL,
+ 0);
+
+ if(FAILED(hr))
+ {
return hr;
}
return request.Complete();
}
+
// Return the alignment
HRESULT
-CAsyncIo::Alignment(LONG *pl)
+CAsyncIo::Alignment(LONG *pAlignment)
{
- *pl = Alignment();
+ CheckPointer(pAlignment,E_POINTER);
+
+ *pAlignment = Alignment();
return S_OK;
}
+
+
diff --git a/src/filters/reader/asyncreader/asyncio.h b/src/filters/reader/asyncreader/asyncio.h
index 0f463bf7a..cab2e9b48 100644
--- a/src/filters/reader/asyncreader/asyncio.h
+++ b/src/filters/reader/asyncreader/asyncio.h
@@ -3,7 +3,7 @@
//
// Desc: DirectShow sample code - base library for I/O functionality.
//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
+// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------
#pragma once
@@ -16,6 +16,7 @@
// !!! Need to use real overlapped i/o if available
// currently only uses worker thread, not overlapped i/o
+
class CAsyncIo;
class CAsyncStream;
@@ -31,6 +32,7 @@ public:
DWORD dwBytesToRead,
BOOL bAlign,
LPDWORD pdwBytesRead) = 0;
+
virtual LONGLONG Size(LONGLONG *pSizeAvailable = NULL) = 0;
virtual DWORD Alignment() = 0;
virtual void Lock() = 0;
@@ -43,60 +45,60 @@ public:
// (ie across SetFilePointer/ReadFile pairs)
class CAsyncRequest
{
- CAsyncIo *m_pIo;
+ CAsyncIo *m_pIo;
CAsyncStream *m_pStream;
LONGLONG m_llPos;
- BOOL m_bAligned;
- LONG m_lLength;
- BYTE* m_pBuffer;
- LPVOID m_pContext;
- DWORD m_dwUser;
+ BOOL m_bAligned;
+ LONG m_lLength;
+ BYTE* m_pBuffer;
+ LPVOID m_pContext;
+ DWORD_PTR m_dwUser;
HRESULT m_hr;
public:
// init the params for this request. Issue the i/o
// if overlapped i/o is possible.
HRESULT Request(
- CAsyncIo *pIo,
+ CAsyncIo *pIo,
CAsyncStream *pStream,
- LONGLONG llPos,
- LONG lLength,
+ LONGLONG llPos,
+ LONG lLength,
BOOL bAligned,
- BYTE* pBuffer,
- LPVOID pContext, // filter's context
- DWORD dwUser); // downstream filter's context
+ BYTE* pBuffer,
+ LPVOID pContext, // filter's context
+ DWORD_PTR dwUser); // downstream filter's context
// issue the i/o if not overlapped, and block until i/o complete.
// returns error code of file i/o
HRESULT Complete();
// cancels the i/o. blocks until i/o is no longer pending
- HRESULT Cancel() const
+ HRESULT Cancel()
{
- return S_OK;
+ return S_OK;
};
// accessor functions
- LPVOID GetContext() /*const*/
+ LPVOID GetContext()
{
- return m_pContext;
+ return m_pContext;
};
- DWORD GetUser() const
+ DWORD_PTR GetUser()
{
- return m_dwUser;
+ return m_dwUser;
};
- HRESULT GetHResult() const {
+ HRESULT GetHResult() {
return m_hr;
};
// we set m_lLength to the actual length
- LONG GetActualLength() const {
+ LONG GetActualLength() {
return m_lLength;
};
- LONGLONG GetStart() const {
+ LONGLONG GetStart() {
return m_llPos;
};
};
@@ -134,9 +136,11 @@ class CAsyncIo
CCritSec m_csLists; // locks access to the list and events
BOOL m_bFlushing; // true if between BeginFlush/EndFlush
+
CRequestList m_listWork;
CRequestList m_listDone;
- CAMEvent m_evWork; // set when list is not empty
+
+ CAMEvent m_evWork; // set when list is not empty
CAMEvent m_evDone;
// for correct flush behaviour: all protected by m_csLists
@@ -180,8 +184,8 @@ class CAsyncIo
// initial static thread proc calls ThreadProc with DWORD
// param as this
static DWORD WINAPI InitialThreadProc(LPVOID pv) {
- CAsyncIo * pThis = static_cast<CAsyncIo*> (pv);
- return pThis->ThreadProc();
+ CAsyncIo * pThis = (CAsyncIo*) pv;
+ return pThis->ThreadProc();
};
DWORD ThreadProc(void);
@@ -204,36 +208,34 @@ public:
// queue a requested read. must be aligned.
HRESULT Request(
- LONGLONG llPos,
- LONG lLength,
- BOOL bAligned,
- BYTE* pBuffer,
- LPVOID pContext,
- DWORD dwUser);
+ LONGLONG llPos,
+ LONG lLength,
+ BOOL bAligned,
+ BYTE* pBuffer,
+ LPVOID pContext,
+ DWORD_PTR dwUser);
// wait for the next read to complete
HRESULT WaitForNext(
- DWORD dwTimeout,
- LPVOID *ppContext,
- DWORD * pdwUser,
- LONG * pcbActual
- );
+ DWORD dwTimeout,
+ LPVOID *ppContext,
+ DWORD_PTR * pdwUser,
+ LONG * pcbActual);
// perform a read of an already aligned buffer
HRESULT SyncReadAligned(
- LONGLONG llPos,
- LONG lLength,
- BYTE* pBuffer,
- LONG* pcbActual,
- PVOID pvContext
- );
+ LONGLONG llPos,
+ LONG lLength,
+ BYTE* pBuffer,
+ LONG* pcbActual,
+ PVOID pvContext);
// perform a synchronous read. will be buffered
// if not aligned.
HRESULT SyncRead(
- LONGLONG llPos,
- LONG lLength,
- BYTE* pBuffer);
+ LONGLONG llPos,
+ LONG lLength,
+ BYTE* pBuffer);
// return length
HRESULT Length(LONGLONG *pllTotal, LONGLONG* pllAvailable);
@@ -250,17 +252,24 @@ public:
return m_pStream->Alignment();
};
- BOOL IsAligned(LONG l) {
- if ((l & (Alignment() -1)) == 0) {
- return TRUE;
- } else {
- return FALSE;
- }
+ BOOL IsAligned(LONG_PTR l)
+ {
+ // LONG_PTR is long on 32-bit or __int64 on 64-bit.
+ if ( (static_cast<LONG>(l & 0xffffffff) & (Alignment() -1)) == 0 )
+ {
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
};
+#ifndef _WIN64
BOOL IsAligned(LONGLONG ll) {
- return IsAligned( (LONG) (ll & 0xffffffff));
+ return IsAligned( (LONG) (ll & 0xffffffff));
};
+#endif
// Accessor
HANDLE StopEvent() const { return m_evDone; }
diff --git a/src/filters/reader/asyncreader/asyncrdr.cpp b/src/filters/reader/asyncreader/asyncrdr.cpp
index 5e807f8cc..c724be04a 100644
--- a/src/filters/reader/asyncreader/asyncrdr.cpp
+++ b/src/filters/reader/asyncreader/asyncrdr.cpp
@@ -5,11 +5,12 @@
// This file implements I/O source filter methods and output pin
// methods for CAsyncReader and CAsyncOutputPin.
//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
+// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------
#include "stdafx.h"
+#include <streams.h>
#include "asyncio.h"
#include "asyncrdr.h"
@@ -21,12 +22,12 @@ CAsyncOutputPin::CAsyncOutputPin(
CAsyncIo *pIo,
CCritSec * pLock)
: CBasePin(
- NAME("Async output pin"),
- pReader,
- pLock,
- phr,
- L"Output",
- PINDIR_OUTPUT),
+ NAME("Async output pin"),
+ pReader,
+ pLock,
+ phr,
+ L"Output",
+ PINDIR_OUTPUT),
m_pReader(pReader),
m_pIo(pIo)
{
@@ -36,97 +37,123 @@ CAsyncOutputPin::~CAsyncOutputPin()
{
}
-STDMETHODIMP
-CAsyncOutputPin::NonDelegatingQueryInterface(REFIID riid, void** ppv)
+
+STDMETHODIMP CAsyncOutputPin::NonDelegatingQueryInterface(REFIID riid, void** ppv)
{
CheckPointer(ppv,E_POINTER);
- if (riid == IID_IAsyncReader) {
+ if(riid == IID_IAsyncReader)
+ {
m_bQueriedForAsyncReader = TRUE;
- return GetInterface((IAsyncReader*) this, ppv);
- } else {
- return CBasePin::NonDelegatingQueryInterface(riid, ppv);
+ return GetInterface((IAsyncReader*) this, ppv);
+ }
+ else
+ {
+ return CBasePin::NonDelegatingQueryInterface(riid, ppv);
}
}
-HRESULT
-CAsyncOutputPin::GetMediaType(int iPosition, CMediaType *pMediaType)
+
+HRESULT CAsyncOutputPin::GetMediaType(int iPosition, CMediaType *pMediaType)
{
- if (iPosition < 0) {
- return E_INVALIDARG;
+ if(iPosition < 0)
+ {
+ return E_INVALIDARG;
}
- if (iPosition > 0) {
- return VFW_S_NO_MORE_ITEMS;
+ if(iPosition > 0)
+ {
+ return VFW_S_NO_MORE_ITEMS;
}
+ CheckPointer(pMediaType,E_POINTER);
+ CheckPointer(m_pReader,E_UNEXPECTED);
+
*pMediaType = *m_pReader->LoadType();
+
return S_OK;
}
-HRESULT
-CAsyncOutputPin::CheckMediaType(const CMediaType* pType)
+
+HRESULT CAsyncOutputPin::CheckMediaType(const CMediaType* pType)
{
CAutoLock lck(m_pLock);
/* We treat MEDIASUBTYPE_NULL subtype as a wild card */
- if ((m_pReader->LoadType()->majortype == pType->majortype) &&
- (m_pReader->LoadType()->subtype == MEDIASUBTYPE_NULL ||
- m_pReader->LoadType()->subtype == pType->subtype)) {
- return S_OK;
+ if((m_pReader->LoadType()->majortype == pType->majortype) &&
+ (m_pReader->LoadType()->subtype == MEDIASUBTYPE_NULL ||
+ m_pReader->LoadType()->subtype == pType->subtype))
+ {
+ return S_OK;
}
+
return S_FALSE;
}
-HRESULT
-CAsyncOutputPin::InitAllocator(IMemAllocator **ppAlloc)
+
+HRESULT CAsyncOutputPin::InitAllocator(IMemAllocator **ppAlloc)
{
+ CheckPointer(ppAlloc,E_POINTER);
+
HRESULT hr = NOERROR;
- *ppAlloc = NULL;
CMemAllocator *pMemObject = NULL;
+ *ppAlloc = NULL;
+
/* Create a default memory allocator */
- pMemObject = DNew CMemAllocator(NAME("Base memory allocator"),NULL, &hr);
- if (pMemObject == NULL) {
- return E_OUTOFMEMORY;
+ pMemObject = new CMemAllocator(NAME("Base memory allocator"), NULL, &hr);
+ if(pMemObject == NULL)
+ {
+ return E_OUTOFMEMORY;
}
-
- if (FAILED(hr)) {
- delete pMemObject;
- return hr;
+ if(FAILED(hr))
+ {
+ delete pMemObject;
+ return hr;
}
/* Get a reference counted IID_IMemAllocator interface */
hr = pMemObject->QueryInterface(IID_IMemAllocator,(void **)ppAlloc);
- if (FAILED(hr)) {
- delete pMemObject;
- return E_NOINTERFACE;
+ if(FAILED(hr))
+ {
+ delete pMemObject;
+ return E_NOINTERFACE;
}
ASSERT(*ppAlloc != NULL);
return NOERROR;
}
+
// we need to return an addrefed allocator, even if it is the preferred
// one, since he doesn't know whether it is the preferred one or not.
-STDMETHODIMP
+STDMETHODIMP
CAsyncOutputPin::RequestAllocator(
IMemAllocator* pPreferred,
ALLOCATOR_PROPERTIES* pProps,
IMemAllocator ** ppActual)
{
+ CheckPointer(pPreferred,E_POINTER);
+ CheckPointer(pProps,E_POINTER);
+ CheckPointer(ppActual,E_POINTER);
+ ASSERT(m_pIo);
+
// we care about alignment but nothing else
- if (!pProps->cbAlign || !m_pIo->IsAligned(pProps->cbAlign)) {
- m_pIo->Alignment(&pProps->cbAlign);
+ if(!pProps->cbAlign || !m_pIo->IsAligned(pProps->cbAlign))
+ {
+ m_pIo->Alignment(&pProps->cbAlign);
}
ALLOCATOR_PROPERTIES Actual;
HRESULT hr;
- if (pPreferred) {
- hr = pPreferred->SetProperties(pProps, &Actual);
- if (SUCCEEDED(hr) && m_pIo->IsAligned(Actual.cbAlign)) {
+ if(pPreferred)
+ {
+ hr = pPreferred->SetProperties(pProps, &Actual);
+
+ if(SUCCEEDED(hr) && m_pIo->IsAligned(Actual.cbAlign))
+ {
pPreferred->AddRef();
- *ppActual = pPreferred;
+ *ppActual = pPreferred;
return S_OK;
}
}
@@ -134,13 +161,15 @@ CAsyncOutputPin::RequestAllocator(
// create our own allocator
IMemAllocator* pAlloc;
hr = InitAllocator(&pAlloc);
- if (FAILED(hr)) {
+ if(FAILED(hr))
+ {
return hr;
}
//...and see if we can make it suitable
hr = pAlloc->SetProperties(pProps, &Actual);
- if (SUCCEEDED(hr) && m_pIo->IsAligned(Actual.cbAlign)) {
+ if(SUCCEEDED(hr) && m_pIo->IsAligned(Actual.cbAlign))
+ {
// we need to release our refcount on pAlloc, and addref
// it to pass a refcount to the caller - this is a net nothing.
*ppActual = pAlloc;
@@ -152,7 +181,8 @@ CAsyncOutputPin::RequestAllocator(
// if we failed because of the IsAligned test, the error code will
// not be failure
- if (SUCCEEDED(hr)) {
+ if(SUCCEEDED(hr))
+ {
hr = VFW_E_BADALIGN;
}
return hr;
@@ -161,32 +191,36 @@ CAsyncOutputPin::RequestAllocator(
// queue an aligned read request. call WaitForNext to get
// completion.
-STDMETHODIMP
-CAsyncOutputPin::Request(
+STDMETHODIMP CAsyncOutputPin::Request(
IMediaSample* pSample,
- DWORD_PTR dwUser) // user context
+ DWORD_PTR dwUser) // user context
{
+ CheckPointer(pSample,E_POINTER);
+
REFERENCE_TIME tStart, tStop;
HRESULT hr = pSample->GetTime(&tStart, &tStop);
- if (FAILED(hr)) {
- return hr;
+ if(FAILED(hr))
+ {
+ return hr;
}
LONGLONG llPos = tStart / UNITS;
LONG lLength = (LONG) ((tStop - tStart) / UNITS);
- LONGLONG llTotal;
- LONGLONG llAvailable;
- hr = m_pIo->Length(&llTotal, &llAvailable);
- if (llPos + lLength > llTotal) {
+ LONGLONG llTotal=0, llAvailable=0;
+ hr = m_pIo->Length(&llTotal, &llAvailable);
+ if(llPos + lLength > llTotal)
+ {
// the end needs to be aligned, but may have been aligned
// on a coarser alignment.
LONG lAlign;
m_pIo->Alignment(&lAlign);
+
llTotal = (llTotal + lAlign -1) & ~(lAlign-1);
- if (llPos + lLength > llTotal) {
+ if(llPos + lLength > llTotal)
+ {
lLength = (LONG) (llTotal - llPos);
// must be reducing this!
@@ -196,48 +230,54 @@ CAsyncOutputPin::Request(
}
}
-
BYTE* pBuffer;
hr = pSample->GetPointer(&pBuffer);
- if (FAILED(hr)) {
- return hr;
+ if(FAILED(hr))
+ {
+ return hr;
}
- return m_pIo->Request(
- llPos,
- lLength,
- TRUE,
- pBuffer,
- (LPVOID)pSample,
- dwUser);
+ return m_pIo->Request(llPos,
+ lLength,
+ TRUE,
+ pBuffer,
+ (LPVOID)pSample,
+ dwUser);
}
+
// sync-aligned request. just like a request/waitfornext pair.
-STDMETHODIMP
+STDMETHODIMP
CAsyncOutputPin::SyncReadAligned(
IMediaSample* pSample)
{
+ CheckPointer(pSample,E_POINTER);
+
REFERENCE_TIME tStart, tStop;
HRESULT hr = pSample->GetTime(&tStart, &tStop);
- if (FAILED(hr)) {
- return hr;
+ if(FAILED(hr))
+ {
+ return hr;
}
LONGLONG llPos = tStart / UNITS;
LONG lLength = (LONG) ((tStop - tStart) / UNITS);
+
LONGLONG llTotal;
LONGLONG llAvailable;
hr = m_pIo->Length(&llTotal, &llAvailable);
- if (llPos + lLength > llTotal) {
-
+ if(llPos + lLength > llTotal)
+ {
// the end needs to be aligned, but may have been aligned
// on a coarser alignment.
LONG lAlign;
m_pIo->Alignment(&lAlign);
+
llTotal = (llTotal + lAlign -1) & ~(lAlign-1);
- if (llPos + lLength > llTotal) {
+ if(llPos + lLength > llTotal)
+ {
lLength = (LONG) (llTotal - llPos);
// must be reducing this!
@@ -247,21 +287,19 @@ CAsyncOutputPin::SyncReadAligned(
}
}
-
BYTE* pBuffer;
hr = pSample->GetPointer(&pBuffer);
- if (FAILED(hr)) {
- return hr;
+ if(FAILED(hr))
+ {
+ return hr;
}
LONG cbActual;
- hr = m_pIo->SyncReadAligned(
- llPos,
- lLength,
- pBuffer,
- &cbActual,
- pSample
- );
+ hr = m_pIo->SyncReadAligned(llPos,
+ lLength,
+ pBuffer,
+ &cbActual,
+ pSample);
pSample->SetActualDataLength(cbActual);
return hr;
@@ -274,19 +312,20 @@ STDMETHODIMP
CAsyncOutputPin::WaitForNext(
DWORD dwTimeout,
IMediaSample** ppSample, // completed sample
- DWORD_PTR* pdwUser) // user context
+ DWORD_PTR * pdwUser) // user context
{
+ CheckPointer(ppSample,E_POINTER);
+
LONG cbActual;
- IMediaSample* pSample;
+ IMediaSample* pSample=0;
- HRESULT hr = m_pIo->WaitForNext(
- dwTimeout,
- (LPVOID*) &pSample,
- (DWORD*)pdwUser,
- &cbActual
- );
+ HRESULT hr = m_pIo->WaitForNext(dwTimeout,
+ (LPVOID*) &pSample,
+ pdwUser,
+ &cbActual);
- if (SUCCEEDED(hr)) {
+ if(SUCCEEDED(hr))
+ {
pSample->SetActualDataLength(cbActual);
}
@@ -299,13 +338,14 @@ CAsyncOutputPin::WaitForNext(
// synchronous read that need not be aligned.
STDMETHODIMP
CAsyncOutputPin::SyncRead(
- LONGLONG llPosition, // absolute Io position
- LONG lLength, // nr bytes required
- BYTE* pBuffer) // write data here
+ LONGLONG llPosition, // absolute Io position
+ LONG lLength, // nr bytes required
+ BYTE* pBuffer) // write data here
{
return m_pIo->SyncRead(llPosition, lLength, pBuffer);
}
+
// return the length of the file, and the length currently
// available locally. We only support locally accessible files,
// so they are always the same
@@ -314,16 +354,17 @@ CAsyncOutputPin::Length(
LONGLONG* pTotal,
LONGLONG* pAvailable)
{
- HRESULT hr = m_pIo->Length(pTotal, pAvailable);
- return hr;
+ return m_pIo->Length(pTotal, pAvailable);
}
+
STDMETHODIMP
CAsyncOutputPin::BeginFlush(void)
{
return m_pIo->BeginFlush();
}
+
STDMETHODIMP
CAsyncOutputPin::EndFlush(void)
{
@@ -341,6 +382,7 @@ CAsyncOutputPin::Connect(
}
+
// --- CAsyncReader implementation ---
#pragma warning(disable:4355)
@@ -352,17 +394,17 @@ CAsyncReader::CAsyncReader(
HRESULT *phr,
const CLSID& clsid)
: CBaseFilter(
- pName,
- pUnk,
- &m_csFilter,
- clsid,
- NULL
- ),
+ pName,
+ pUnk,
+ &m_csFilter,
+ clsid,
+ NULL
+ ),
m_OutputPin(
- phr,
- this,
- &m_Io,
- &m_csFilter),
+ phr,
+ this,
+ &m_Io,
+ &m_csFilter),
m_Io(pStream)
{
}
@@ -387,21 +429,22 @@ ULONG CAsyncReader::GetMiscFlags()
return AM_FILTER_MISC_FLAGS_IS_SOURCE;
}
-
-int
-CAsyncReader::GetPinCount()
+int CAsyncReader::GetPinCount()
{
return 1;
}
-CBasePin *
-CAsyncReader::GetPin(int n)
+CBasePin * CAsyncReader::GetPin(int n)
{
- if ((GetPinCount() > 0) && (n == 0)) {
- return &m_OutputPin;
- } else {
- return NULL;
+ if((GetPinCount() > 0) && (n == 0))
+ {
+ return &m_OutputPin;
+ }
+ else
+ {
+ return NULL;
}
}
+
diff --git a/src/filters/reader/asyncreader/asyncrdr.h b/src/filters/reader/asyncreader/asyncrdr.h
index 467662d0f..53572b29c 100644
--- a/src/filters/reader/asyncreader/asyncrdr.h
+++ b/src/filters/reader/asyncreader/asyncrdr.h
@@ -1,3 +1,12 @@
+//------------------------------------------------------------------------------
+// File: AsyncRdr.h
+//
+// Desc: DirectShow sample code - base library for I/O functionality.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//------------------------------------------------------------------------------
+
+
#pragma once
//
@@ -13,6 +22,7 @@
// all the work.
//
+
// the filter class (defined below)
class CAsyncReader;
@@ -39,8 +49,8 @@ public:
// constructor and destructor
CAsyncOutputPin(
HRESULT * phr,
- CAsyncReader *pReader,
- CAsyncIo *pIo,
+ CAsyncReader *pReader,
+ CAsyncIo *pIo,
CCritSec * pLock);
~CAsyncOutputPin();
@@ -79,6 +89,7 @@ public:
if (m_bQueriedForAsyncReader) {
return CBasePin::CompleteConnect(pReceivePin);
} else {
+
#ifdef VFW_E_NO_TRANSPORT
return VFW_E_NO_TRANSPORT;
#else
@@ -114,7 +125,7 @@ public:
// GetPointer until after returning from WaitForNext.
STDMETHODIMP Request(
IMediaSample* pSample,
- DWORD_PTR dwUser); // user context
+ DWORD_PTR dwUser); // user context
// block until the next sample is completed or the timeout occurs.
// timeout (millisecs) may be 0 or INFINITE. Samples may not
@@ -124,7 +135,7 @@ public:
STDMETHODIMP WaitForNext(
DWORD dwTimeout,
IMediaSample** ppSample, // completed sample
- DWORD_PTR* pdwUser); // user context
+ DWORD_PTR * pdwUser); // user context
// sync read of data. Sample passed in must have been acquired from
// the agreed allocator. Start and stop position must be aligned.
@@ -138,9 +149,9 @@ public:
// need not be aligned. Will fail if read is beyond actual total
// length.
STDMETHODIMP SyncRead(
- LONGLONG llPosition, // absolute file position
- LONG lLength, // nr bytes required
- BYTE* pBuffer); // write data here
+ LONGLONG llPosition, // absolute file position
+ LONG lLength, // nr bytes required
+ BYTE* pBuffer); // write data here
// return total length of stream, and currently available length.
// reads for beyond the available length but within the total length will
@@ -176,10 +187,10 @@ protected:
CAsyncOutputPin m_OutputPin;
// Type we think our data is
- CMediaType m_mt;
+ CMediaType m_mt;
public:
-
+
// construction / destruction
CAsyncReader(
@@ -187,14 +198,15 @@ public:
LPUNKNOWN pUnk,
CAsyncStream *pStream,
HRESULT *phr,
- const CLSID& clsid);
+ const CLSID& clsid);
+
~CAsyncReader();
- DECLARE_IUNKNOWN;
+ DECLARE_IUNKNOWN;
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv);
- // IAMFilterMiscFlags
- STDMETHODIMP_(ULONG) GetMiscFlags();
+ // IAMFilterMiscFlags
+ STDMETHODIMP_(ULONG) GetMiscFlags();
// --- CBaseFilter methods ---
int GetPinCount();