/* Initialization */
void Init(LPBYTE pbData, LONGLONG llLength, DWORD dwKBPerSec = INFINITE)
{
m_pbData = pbData;
m_llLength = llLength;
m_dwKBPerSec = dwKBPerSec;
m_dwTimeStart = timeGetTime();
}
HRESULT SetPointer(LONGLONG llPos)
{
if (llPos < 0 || llPos > m_llLength) {
return S_FALSE;
} else {
m_llPosition = llPos;
return S_OK;
}
}
HRESULT Read(PBYTE pbBuffer,
DWORD dwBytesToRead,
BOOL bAlign,
LPDWORD pdwBytesRead)
{
CAutoLock lck(&m_csLock);
DWORD dwReadLength;
/* Wait until the bytes are here! */
DWORD dwTime = timeGetTime();
if (m_llPosition + dwBytesToRead > m_llLength) {
dwReadLength = (DWORD)(m_llLength - m_llPosition);
} else {
dwReadLength = dwBytesToRead;
}
DWORD dwTimeToArrive =
((DWORD)m_llPosition + dwReadLength) / m_dwKBPerSec;
if (dwTime - m_dwTimeStart < dwTimeToArrive) {
Sleep(dwTimeToArrive - dwTime + m_dwTimeStart);
}
CopyMemory((PVOID)pbBuffer, (PVOID)(m_pbData + m_llPosition),
dwReadLength);
m_llPosition += dwReadLength;
*pdwBytesRead = dwReadLength;
return S_OK;
}
LONGLONG Size(LONGLONG *pSizeAvailable)
{
LONGLONG llCurrentAvailable =
static_cast <LONGLONG> (UInt32x32To64((timeGetTime() - m_dwTimeStart),m_dwKBPerSec));
*pSizeAvailable = min(m_llLength, llCurrentAvailable);
return m_llLength;
}
DWORD Alignment()
{
return 1;
}
void Lock()
{
m_csLock.Lock();
}
void Unlock()
{
m_csLock.Unlock();
}
private:
CCritSec m_csLock;
PBYTE m_pbData;
LONGLONG m_llLength;
LONGLONG m_llPosition;
DWORD m_dwKBPerSec;
DWORD m_dwTimeStart;
};
class CAsyncFilter : public CAsyncReader, public IFileSourceFilter
{
public:
CAsyncFilter(LPUNKNOWN pUnk, HRESULT *phr) :
CAsyncReader(NAME("Mem Reader"), pUnk, &m_Stream, phr),
m_pFileName(NULL),
m_pbData(NULL)
{
}
~CAsyncFilter()
{
delete [] m_pbData;
delete [] m_pFileName;
}
static CUnknown * WINAPI CreateInstance(LPUNKNOWN, HRESULT *);
DECLARE_IUNKNOWN
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv)
{
if (riid == IID_IFileSourceFilter) {
return GetInterface((IFileSourceFilter *)this, ppv);
} else {
return CAsyncReader::NonDelegatingQueryInterface(riid, ppv);
}
}
/* IFileSourceFilter methods */
// Load a (new) file
STDMETHODIMP Load(LPCOLESTR lpwszFileName, const AM_MEDIA_TYPE *pmt)
{
CheckPointer(lpwszFileName, E_POINTER);
// lstrlenW is one of the few Unicode functions that works on win95
int cch = lstrlenW(lpwszFileName) + 1;
#ifndef UNICODE
TCHAR *lpszFileName=0;
lpszFileName = new char[cch * 2];
if (!lpszFileName) {
return E_OUTOFMEMORY;
}
WideCharToMultiByte(GetACP(), 0, lpwszFileName, -1,
lpszFileName, cch, NULL, NULL);
#else