| //------------------------------------------------------------------------------ | |
| // File: WXUtil.h | |
| // | |
| // Desc: DirectShow base classes - defines helper classes and functions for | |
| // building multimedia filters. | |
| // | |
| // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. | |
| //------------------------------------------------------------------------------ | |
| #ifndef __WXUTIL__ | |
| #define __WXUTIL__ | |
| // eliminate spurious "statement has no effect" warnings. | |
| #pragma warning(disable: 4705) | |
| // wrapper for whatever critical section we have | |
| class CCritSec { | |
| // make copy constructor and assignment operator inaccessible | |
| CCritSec(const CCritSec &refCritSec); | |
| CCritSec &operator=(const CCritSec &refCritSec); | |
| CRITICAL_SECTION m_CritSec; | |
| #ifdef DEBUG | |
| public: | |
| DWORD m_currentOwner; | |
| DWORD m_lockCount; | |
| BOOL m_fTrace; // Trace this one | |
| public: | |
| CCritSec(); | |
| ~CCritSec(); | |
| void Lock(); | |
| void Unlock(); | |
| #else | |
| public: | |
| CCritSec() { | |
| InitializeCriticalSection(&m_CritSec); | |
| }; | |
| ~CCritSec() { | |
| DeleteCriticalSection(&m_CritSec); | |
| }; | |
| void Lock() { | |
| EnterCriticalSection(&m_CritSec); | |
| }; | |
| void Unlock() { | |
| LeaveCriticalSection(&m_CritSec); | |
| }; | |
| #endif | |
| }; | |
| // | |
| // To make deadlocks easier to track it is useful to insert in the | |
| // code an assertion that says whether we own a critical section or | |
| // not. We make the routines that do the checking globals to avoid | |
| // having different numbers of member functions in the debug and | |
| // retail class implementations of CCritSec. In addition we provide | |
| // a routine that allows usage of specific critical sections to be | |
| // traced. This is NOT on by default - there are far too many. | |
| // | |
| #ifdef DEBUG | |
| BOOL WINAPI CritCheckIn(CCritSec * pcCrit); | |
| BOOL WINAPI CritCheckIn(const CCritSec * pcCrit); | |
| BOOL WINAPI CritCheckOut(CCritSec * pcCrit); | |
| BOOL WINAPI CritCheckOut(const CCritSec * pcCrit); | |
| void WINAPI DbgLockTrace(CCritSec * pcCrit, BOOL fTrace); | |
| #else | |
| #define CritCheckIn(x) TRUE | |
| #define CritCheckOut(x) TRUE | |
| #define DbgLockTrace(pc, fT) | |
| #endif | |
| // locks a critical section, and unlocks it automatically | |
| // when the lock goes out of scope | |
| class CAutoLock { | |
| // make copy constructor and assignment operator inaccessible | |
| CAutoLock(const CAutoLock &refAutoLock); | |
| CAutoLock &operator=(const CAutoLock &refAutoLock); | |
| protected: | |
| CCritSec * m_pLock; | |
| public: | |
| CAutoLock(CCritSec * plock) | |
| { | |
| m_pLock = plock; | |
| m_pLock->Lock(); | |
| }; | |
| ~CAutoLock() { | |
| m_pLock->Unlock(); | |
| }; | |
| }; | |
| // wrapper for event objects | |
| class CAMEvent | |
| { | |
| // make copy constructor and assignment operator inaccessible | |
| CAMEvent(const CAMEvent &refEvent); | |
| CAMEvent &operator=(const CAMEvent &refEvent); | |
| protected: | |
| HANDLE m_hEvent; | |
| public: | |
| CAMEvent(BOOL fManualReset = FALSE, __inout_opt HRESULT *phr = NULL); | |
| CAMEvent(__inout_opt HRESULT *phr); | |
| ~CAMEvent(); | |
| // Cast to HANDLE - we don't support this as an lvalue | |
| operator HANDLE () const { return m_hEvent; }; | |
| void Set() {EXECUTE_ASSERT(SetEvent(m_hEvent));}; | |
| BOOL Wait(DWORD dwTimeout = INFINITE) { | |
| return (WaitForSingleObject(m_hEvent, dwTimeout) == WAIT_OBJECT_0); | |
| }; | |
| void Reset() { ResetEvent(m_hEvent); }; | |
| BOOL Check() { return Wait(0); }; | |
| }; | |
| // wrapper for event objects that do message processing | |
| // This adds ONE method to the CAMEvent object to allow sent | |
| // messages to be processed while waiting | |
| class CAMMsgEvent : public CAMEvent | |
| { | |
| public: | |
| CAMMsgEvent(__inout_opt HRESULT *phr = NULL); | |
| // Allow SEND messages to be processed while waiting | |
| BOOL WaitMsg(DWORD dwTimeout = INFINITE); | |
| }; | |
| // old name supported for the time being | |
| #define CTimeoutEvent CAMEvent | |
| // support for a worker thread | |
| #ifdef AM_NOVTABLE | |
| // simple thread class supports creation of worker thread, synchronization | |
| // and communication. Can be derived to simplify parameter passing | |
| class AM_NOVTABLE CAMThread { | |
| // make copy constructor and assignment operator inaccessible | |
| CAMThread(const CAMThread &refThread); | |
| CAMThread &operator=(const CAMThread &refThread); | |
| CAMEvent m_EventSend; | |
| CAMEvent m_EventComplete; | |
| DWORD m_dwParam; | |
| DWORD m_dwReturnVal; | |
| protected: | |
| HANDLE m_hThread; | |
| // thread will run this function on startup | |
| // must be supplied by derived class | |
| virtual DWORD ThreadProc() = 0; | |
| public: | |
| CAMThread(__inout_opt HRESULT *phr = NULL); | |
| virtual ~CAMThread(); | |
| CCritSec m_AccessLock; // locks access by client threads | |
| CCritSec m_WorkerLock; // locks access to shared objects | |
| // thread initially runs this. param is actually 'this'. function | |
| // just gets this and calls ThreadProc | |
| static DWORD WINAPI InitialThreadProc(__inout LPVOID pv); | |
| // start thread running - error if already running | |
| BOOL Create(); | |
| // signal the thread, and block for a response | |
| // | |
| DWORD CallWorker(DWORD); | |
| // accessor thread calls this when done with thread (having told thread | |
| // to exit) | |
| void Close() { | |
| // Disable warning: Conversion from LONG to PVOID of greater size | |
| #pragma warning(push) | |
| #pragma warning(disable: 4312) | |
| HANDLE hThread = (HANDLE)InterlockedExchangePointer(&m_hThread, 0); | |
| #pragma warning(pop) | |
| if (hThread) { | |
| WaitForSingleObject(hThread, INFINITE); | |
| CloseHandle(hThread); | |
| } | |
| }; | |
| // ThreadExists | |
| // Return TRUE if the thread exists. FALSE otherwise | |
| BOOL ThreadExists(void) const | |
| { | |
| if (m_hThread == 0) { | |
| return FALSE; | |
| } else { | |
| return TRUE; | |
| } | |
| } | |
| // wait for the next request | |
| DWORD GetRequest(); | |
| // is there a request? | |
| BOOL CheckRequest(__out_opt DWORD * pParam); | |
| // reply to the request | |
| void Reply(DWORD); | |
| // If you want to do WaitForMultipleObjects you'll need to include | |
| // this handle in your wait list or you won't be responsive | |
| HANDLE GetRequestHandle() const { return m_EventSend; }; | |
| // Find out what the request was | |
| DWORD GetRequestParam() const { return m_dwParam; }; | |
| // call CoInitializeEx (COINIT_DISABLE_OLE1DDE) if | |
| // available. S_FALSE means it's not available. | |
| static HRESULT CoInitializeHelper(); | |
| }; | |
| #endif // AM_NOVTABLE | |
| // CQueue | |
| // | |
| // Implements a simple Queue ADT. The queue contains a finite number of | |
| // objects, access to which is controlled by a semaphore. The semaphore | |
| // is created with an initial count (N). Each time an object is added | |
| // a call to WaitForSingleObject is made on the semaphore's handle. When | |
| // this function returns a slot has been reserved in the queue for the new | |
| // object. If no slots are available the function blocks until one becomes | |
| // available. Each time an object is removed from the queue ReleaseSemaphore | |
| // is called on the semaphore's handle, thus freeing a slot in the queue. | |
| // If no objects are present in the queue the function blocks until an | |
| // object has been added. | |
| #define DEFAULT_QUEUESIZE 2 | |
| template <class T> class CQueue { | |
| private: | |
| HANDLE hSemPut; // Semaphore controlling queue "putting" | |
| HANDLE hSemGet; // Semaphore controlling queue "getting" | |
| CRITICAL_SECTION CritSect; // Thread seriallization | |
| int nMax; // Max objects allowed in queue | |
| int iNextPut; // Array index of next "PutMsg" | |
| int iNextGet; // Array index of next "GetMsg" | |
| T *QueueObjects; // Array of objects (ptr's to void) | |
| void Initialize(int n) { | |
| iNextPut = iNextGet = 0; | |
| nMax = n; | |
| InitializeCriticalSection(&CritSect); | |
| hSemPut = CreateSemaphore(NULL, n, n, NULL); | |
| hSemGet = CreateSemaphore(NULL, 0, n, NULL); | |
| QueueObjects = new T[n]; | |
| } | |
| public: | |
| CQueue(int n) { | |
| Initialize(n); | |
| } | |
| CQueue() { | |
| Initialize(DEFAULT_QUEUESIZE); | |
| } | |
| ~CQueue() { | |
| delete [] QueueObjects; | |
| DeleteCriticalSection(&CritSect); | |
| CloseHandle(hSemPut); | |
| CloseHandle(hSemGet); | |
| } | |
| T GetQueueObject() { | |
| int iSlot; | |
| T Object; | |
| LONG lPrevious; | |
| // Wait for someone to put something on our queue, returns straight | |
| // away is there is already an object on the queue. | |
| // | |
| WaitForSingleObject(hSemGet, INFINITE); | |
| EnterCriticalSection(&CritSect); | |
| iSlot = iNextGet++ % nMax; | |
| Object = QueueObjects[iSlot]; | |
| LeaveCriticalSection(&CritSect); | |
| // Release anyone waiting to put an object onto our queue as there | |
| // is now space available in the queue. | |
| // | |
| ReleaseSemaphore(hSemPut, 1L, &lPrevious); | |
| return Object; | |
| } | |
| void PutQueueObject(T Object) { | |
| int iSlot; | |
| LONG lPrevious; | |
| // Wait for someone to get something from our queue, returns straight | |
| // away is there is already an empty slot on the queue. | |
| // | |
| WaitForSingleObject(hSemPut, INFINITE); | |
| EnterCriticalSection(&CritSect); | |
| iSlot = iNextPut++ % nMax; | |
| QueueObjects[iSlot] = Object; | |
| LeaveCriticalSection(&CritSect); | |
| // Release anyone waiting to remove an object from our queue as there | |
| // is now an object available to be removed. | |
| // | |
| ReleaseSemaphore(hSemGet, 1L, &lPrevious); | |
| } | |
| }; | |
| // Ensures that memory is not read past the length source buffer | |
| // and that memory is not written past the length of the dst buffer | |
| // dst - buffer to copy to | |
| // dst_size - total size of destination buffer | |
| // cb_dst_offset - offset, first byte copied to dst+cb_dst_offset | |
| // src - buffer to copy from | |
| // src_size - total size of source buffer | |
| // cb_src_offset - offset, first byte copied from src+cb_src_offset | |
| // count - number of bytes to copy | |
| // | |
| // Returns: | |
| // S_OK - no error | |
| // E_INVALIDARG - values passed would lead to overrun | |
| HRESULT AMSafeMemMoveOffset( | |
| __in_bcount(dst_size) void * dst, | |
| __in size_t dst_size, | |
| __in DWORD cb_dst_offset, | |
| __in_bcount(src_size) const void * src, | |
| __in size_t src_size, | |
| __in DWORD cb_src_offset, | |
| __in size_t count); | |
| extern "C" | |
| void * __stdcall memmoveInternal(void *, const void *, size_t); | |
| inline void * __cdecl memchrInternal(const void *buf, int chr, size_t cnt) | |
| { | |
| #ifdef _X86_ | |
| void *pRet = NULL; | |
| _asm { | |
| cld // make sure we get the direction right | |
| mov ecx, cnt // num of bytes to scan | |
| mov edi, buf // pointer byte stream | |
| mov eax, chr // byte to scan for | |
| repne scasb // look for the byte in the byte stream | |
| jnz exit_memchr // Z flag set if byte found | |
| dec edi // scasb always increments edi even when it | |
| // finds the required byte | |
| mov pRet, edi | |
| exit_memchr: | |
| } | |
| return pRet; | |
| #else | |
| while ( cnt && (*(unsigned char *)buf != (unsigned char)chr) ) { | |
| buf = (unsigned char *)buf + 1; | |
| cnt--; | |
| } | |
| return(cnt ? (void *)buf : NULL); | |
| #endif | |
| } | |
| void WINAPI IntToWstr(int i, __out_ecount(12) LPWSTR wstr); | |
| #define WstrToInt(sz) _wtoi(sz) | |
| #define atoiW(sz) _wtoi(sz) | |
| #define atoiA(sz) atoi(sz) | |
| // These are available to help managing bitmap VIDEOINFOHEADER media structures | |
| extern const DWORD bits555[3]; | |
| extern const DWORD bits565[3]; | |
| extern const DWORD bits888[3]; | |
| // These help convert between VIDEOINFOHEADER and BITMAPINFO structures | |
| STDAPI_(const GUID) GetTrueColorType(const BITMAPINFOHEADER *pbmiHeader); | |
| STDAPI_(const GUID) GetBitmapSubtype(const BITMAPINFOHEADER *pbmiHeader); | |
| STDAPI_(WORD) GetBitCount(const GUID *pSubtype); | |
| // strmbase.lib implements this for compatibility with people who | |
| // managed to link to this directly. we don't want to advertise it. | |
| // | |
| // STDAPI_(/* T */ CHAR *) GetSubtypeName(const GUID *pSubtype); | |
| STDAPI_(CHAR *) GetSubtypeNameA(const GUID *pSubtype); | |
| STDAPI_(WCHAR *) GetSubtypeNameW(const GUID *pSubtype); | |
| #ifdef UNICODE | |
| #define GetSubtypeName GetSubtypeNameW | |
| #else | |
| #define GetSubtypeName GetSubtypeNameA | |
| #endif | |
| STDAPI_(LONG) GetBitmapFormatSize(const BITMAPINFOHEADER *pHeader); | |
| STDAPI_(DWORD) GetBitmapSize(const BITMAPINFOHEADER *pHeader); | |
| #ifdef __AMVIDEO__ | |
| STDAPI_(BOOL) ContainsPalette(const VIDEOINFOHEADER *pVideoInfo); | |
| STDAPI_(const RGBQUAD *) GetBitmapPalette(const VIDEOINFOHEADER *pVideoInfo); | |
| #endif // __AMVIDEO__ | |
| // Compares two interfaces and returns TRUE if they are on the same object | |
| BOOL WINAPI IsEqualObject(IUnknown *pFirst, IUnknown *pSecond); | |
| // This is for comparing pins | |
| #define EqualPins(pPin1, pPin2) IsEqualObject(pPin1, pPin2) | |
| // Arithmetic helper functions | |
| // Compute (a * b + rnd) / c | |
| LONGLONG WINAPI llMulDiv(LONGLONG a, LONGLONG b, LONGLONG c, LONGLONG rnd); | |
| LONGLONG WINAPI Int64x32Div32(LONGLONG a, LONG b, LONG c, LONG rnd); | |
| // Avoids us dyna-linking to SysAllocString to copy BSTR strings | |
| STDAPI WriteBSTR(__deref_out BSTR * pstrDest, LPCWSTR szSrc); | |
| STDAPI FreeBSTR(__deref_in BSTR* pstr); | |
| // Return a wide string - allocating memory for it | |
| // Returns: | |
| // S_OK - no error | |
| // E_POINTER - ppszReturn == NULL | |
| // E_OUTOFMEMORY - can't allocate memory for returned string | |
| STDAPI AMGetWideString(LPCWSTR pszString, __deref_out LPWSTR *ppszReturn); | |
| // Special wait for objects owning windows | |
| DWORD WINAPI WaitDispatchingMessages( | |
| HANDLE hObject, | |
| DWORD dwWait, | |
| HWND hwnd = NULL, | |
| UINT uMsg = 0, | |
| HANDLE hEvent = NULL); | |
| // HRESULT_FROM_WIN32 converts ERROR_SUCCESS to a success code, but in | |
| // our use of HRESULT_FROM_WIN32, it typically means a function failed | |
| // to call SetLastError(), and we still want a failure code. | |
| // | |
| #define AmHresultFromWin32(x) (MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, x)) | |
| // call GetLastError and return an HRESULT value that will fail the | |
| // SUCCEEDED() macro. | |
| HRESULT AmGetLastErrorToHResult(void); | |
| // duplicate of ATL's CComPtr to avoid linker conflicts. | |
| IUnknown* QzAtlComPtrAssign(__deref_inout_opt IUnknown** pp, __in_opt IUnknown* lp); | |
| template <class T> | |
| class QzCComPtr | |
| { | |
| public: | |
| typedef T _PtrClass; | |
| QzCComPtr() {p=NULL;} | |
| QzCComPtr(T* lp) | |
| { | |
| if ((p = lp) != NULL) | |
| p->AddRef(); | |
| } | |
| QzCComPtr(const QzCComPtr<T>& lp) | |
| { | |
| if ((p = lp.p) != NULL) | |
| p->AddRef(); | |
| } | |
| ~QzCComPtr() {if (p) p->Release();} | |
| void Release() {if (p) p->Release(); p=NULL;} | |
| operator T*() {return (T*)p;} | |
| T& operator*() {ASSERT(p!=NULL); return *p; } | |
| //The assert on operator& usually indicates a bug. If this is really | |
| //what is needed, however, take the address of the p member explicitly. | |
| T** operator&() { ASSERT(p==NULL); return &p; } | |
| T* operator->() { ASSERT(p!=NULL); return p; } | |
| T* operator=(T* lp){return (T*)QzAtlComPtrAssign((IUnknown**)&p, lp);} | |
| T* operator=(const QzCComPtr<T>& lp) | |
| { | |
| return (T*)QzAtlComPtrAssign((IUnknown**)&p, lp.p); | |
| } | |
| #if _MSC_VER>1020 | |
| bool operator!(){return (p == NULL);} | |
| #else | |
| BOOL operator!(){return (p == NULL) ? TRUE : FALSE;} | |
| #endif | |
| T* p; | |
| }; | |
| MMRESULT CompatibleTimeSetEvent( UINT uDelay, UINT uResolution, __in LPTIMECALLBACK lpTimeProc, DWORD_PTR dwUser, UINT fuEvent ); | |
| bool TimeKillSynchronousFlagAvailable( void ); | |
| // Helper to replace lstrcpmi | |
| __inline int lstrcmpiLocaleIndependentW(LPCWSTR lpsz1, LPCWSTR lpsz2) | |
| { | |
| return CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, lpsz1, -1, lpsz2, -1) - CSTR_EQUAL; | |
| } | |
| __inline int lstrcmpiLocaleIndependentA(LPCSTR lpsz1, LPCSTR lpsz2) | |
| { | |
| return CompareStringA(LOCALE_INVARIANT, NORM_IGNORECASE, lpsz1, -1, lpsz2, -1) - CSTR_EQUAL; | |
| } | |
| #endif /* __WXUTIL__ */ |