1 //------------------------------------------------------------------------------
4 // Desc: DirectShow base classes - defines helper classes and functions for
5 // building multimedia filters.
7 // Copyright (c) 1992-2002 Microsoft Corporation. All rights reserved.
8 //------------------------------------------------------------------------------
14 // eliminate spurious "statement has no effect" warnings.
15 #pragma warning(disable: 4705)
17 // wrapper for whatever critical section we have
20 // make copy constructor and assignment operator inaccessible
22 CCritSec(const CCritSec
&refCritSec
);
23 CCritSec
&operator=(const CCritSec
&refCritSec
);
25 CRITICAL_SECTION m_CritSec
;
31 BOOL m_fTrace
; // Trace this one
41 InitializeCriticalSection(&m_CritSec
);
45 DeleteCriticalSection(&m_CritSec
);
49 EnterCriticalSection(&m_CritSec
);
53 LeaveCriticalSection(&m_CritSec
);
59 // To make deadlocks easier to track it is useful to insert in the
60 // code an assertion that says whether we own a critical section or
61 // not. We make the routines that do the checking globals to avoid
62 // having different numbers of member functions in the debug and
63 // retail class implementations of CCritSec. In addition we provide
64 // a routine that allows usage of specific critical sections to be
65 // traced. This is NOT on by default - there are far too many.
69 BOOL WINAPI
CritCheckIn(CCritSec
* pcCrit
);
70 BOOL WINAPI
CritCheckIn(const CCritSec
* pcCrit
);
71 BOOL WINAPI
CritCheckOut(CCritSec
* pcCrit
);
72 BOOL WINAPI
CritCheckOut(const CCritSec
* pcCrit
);
73 void WINAPI
DbgLockTrace(CCritSec
* pcCrit
, BOOL fTrace
);
75 #define CritCheckIn(x) TRUE
76 #define CritCheckOut(x) TRUE
77 #define DbgLockTrace(pc, fT)
81 // locks a critical section, and unlocks it automatically
82 // when the lock goes out of scope
85 // make copy constructor and assignment operator inaccessible
87 CAutoLock(const CAutoLock
&refAutoLock
);
88 CAutoLock
&operator=(const CAutoLock
&refAutoLock
);
94 CAutoLock(CCritSec
* plock
)
107 // wrapper for event objects
111 // make copy constructor and assignment operator inaccessible
113 CAMEvent(const CAMEvent
&refEvent
);
114 CAMEvent
&operator=(const CAMEvent
&refEvent
);
119 CAMEvent(BOOL fManualReset
= FALSE
);
122 // Cast to HANDLE - we don't support this as an lvalue
123 operator HANDLE () const { return m_hEvent
; };
125 void Set() {EXECUTE_ASSERT(SetEvent(m_hEvent
));};
126 BOOL
Wait(DWORD dwTimeout
= INFINITE
) {
127 return (WaitForSingleObject(m_hEvent
, dwTimeout
) == WAIT_OBJECT_0
);
129 void Reset() { ResetEvent(m_hEvent
); };
130 BOOL
Check() { return Wait(0); };
134 // wrapper for event objects that do message processing
135 // This adds ONE method to the CAMEvent object to allow sent
136 // messages to be processed while waiting
138 class CAMMsgEvent
: public CAMEvent
143 // Allow SEND messages to be processed while waiting
144 BOOL
WaitMsg(DWORD dwTimeout
= INFINITE
);
147 // old name supported for the time being
148 #define CTimeoutEvent CAMEvent
150 // support for a worker thread
152 // simple thread class supports creation of worker thread, synchronization
153 // and communication. Can be derived to simplify parameter passing
154 class AM_NOVTABLE CAMThread
{
156 // make copy constructor and assignment operator inaccessible
158 CAMThread(const CAMThread
&refThread
);
159 CAMThread
&operator=(const CAMThread
&refThread
);
161 CAMEvent m_EventSend
;
162 CAMEvent m_EventComplete
;
170 // thread will run this function on startup
171 // must be supplied by derived class
172 virtual DWORD
ThreadProc() = 0;
176 virtual ~CAMThread();
178 CCritSec m_AccessLock
; // locks access by client threads
179 CCritSec m_WorkerLock
; // locks access to shared objects
181 // thread initially runs this. param is actually 'this'. function
182 // just gets this and calls ThreadProc
183 static DWORD WINAPI
InitialThreadProc(LPVOID pv
);
185 // start thread running - error if already running
188 // signal the thread, and block for a response
190 DWORD
CallWorker(DWORD
);
192 // accessor thread calls this when done with thread (having told thread
195 HANDLE hThread
= (HANDLE
)InterlockedExchangePointer(&m_hThread
, 0);
197 WaitForSingleObject(hThread
, INFINITE
);
198 CloseHandle(hThread
);
203 // Return TRUE if the thread exists. FALSE otherwise
204 BOOL
ThreadExists(void) const
206 if (m_hThread
== 0) {
213 // wait for the next request
216 // is there a request?
217 BOOL
CheckRequest(DWORD
* pParam
);
219 // reply to the request
222 // If you want to do WaitForMultipleObjects you'll need to include
223 // this handle in your wait list or you won't be responsive
224 HANDLE
GetRequestHandle() const { return m_EventSend
; };
226 // Find out what the request was
227 DWORD
GetRequestParam() const { return m_dwParam
; };
229 // call CoInitializeEx (COINIT_DISABLE_OLE1DDE) if
230 // available. S_FALSE means it's not available.
231 static HRESULT
CoInitializeHelper();
237 // Implements a simple Queue ADT. The queue contains a finite number of
238 // objects, access to which is controlled by a semaphore. The semaphore
239 // is created with an initial count (N). Each time an object is added
240 // a call to WaitForSingleObject is made on the semaphore's handle. When
241 // this function returns a slot has been reserved in the queue for the new
242 // object. If no slots are available the function blocks until one becomes
243 // available. Each time an object is removed from the queue ReleaseSemaphore
244 // is called on the semaphore's handle, thus freeing a slot in the queue.
245 // If no objects are present in the queue the function blocks until an
246 // object has been added.
248 #define DEFAULT_QUEUESIZE 2
250 template <class T
> class CQueue
{
252 HANDLE hSemPut
; // Semaphore controlling queue "putting"
253 HANDLE hSemGet
; // Semaphore controlling queue "getting"
254 CRITICAL_SECTION CritSect
; // Thread seriallization
255 int nMax
; // Max objects allowed in queue
256 int iNextPut
; // Array index of next "PutMsg"
257 int iNextGet
; // Array index of next "GetMsg"
258 T
*QueueObjects
; // Array of objects (ptr's to void)
260 void Initialize(int n
) {
261 iNextPut
= iNextGet
= 0;
263 InitializeCriticalSection(&CritSect
);
264 hSemPut
= CreateSemaphore(NULL
, n
, n
, NULL
);
265 hSemGet
= CreateSemaphore(NULL
, 0, n
, NULL
);
266 QueueObjects
= new T
[n
];
276 Initialize(DEFAULT_QUEUESIZE
);
280 delete [] QueueObjects
;
281 DeleteCriticalSection(&CritSect
);
282 CloseHandle(hSemPut
);
283 CloseHandle(hSemGet
);
291 // Wait for someone to put something on our queue, returns straight
292 // away is there is already an object on the queue.
294 WaitForSingleObject(hSemGet
, INFINITE
);
296 EnterCriticalSection(&CritSect
);
297 iSlot
= iNextGet
++ % nMax
;
298 Object
= QueueObjects
[iSlot
];
299 LeaveCriticalSection(&CritSect
);
301 // Release anyone waiting to put an object onto our queue as there
302 // is now space available in the queue.
304 ReleaseSemaphore(hSemPut
, 1L, &lPrevious
);
308 void PutQueueObject(T Object
) {
312 // Wait for someone to get something from our queue, returns straight
313 // away is there is already an empty slot on the queue.
315 WaitForSingleObject(hSemPut
, INFINITE
);
317 EnterCriticalSection(&CritSect
);
318 iSlot
= iNextPut
++ % nMax
;
319 QueueObjects
[iSlot
] = Object
;
320 LeaveCriticalSection(&CritSect
);
322 // Release anyone waiting to remove an object from our queue as there
323 // is now an object available to be removed.
325 ReleaseSemaphore(hSemGet
, 1L, &lPrevious
);
329 // miscellaneous string conversion functions
330 // NOTE: as we need to use the same binaries on Win95 as on NT this code should
331 // be compiled WITHOUT unicode being defined. Otherwise we will not pick up
332 // these internal routines and the binary will not run on Win95.
334 int WINAPIV
wsprintfWInternal(LPWSTR
, LPCWSTR
, ...);
368 #define wsprintfW wsprintfWInternal
369 #define lstrcpyW lstrcpyWInternal
370 #define lstrcpynW lstrcpynWInternal
371 #define lstrcmpW lstrcmpWInternal
372 #define lstrcmpiW lstrcmpiWInternal
373 #define lstrlenW lstrlenWInternal
377 void * __stdcall
memmoveInternal(void *, const void *, size_t);
379 inline void * __cdecl
memchrInternal(const void *buf
, int chr
, size_t cnt
)
385 cld
// make sure we get the direction right
386 mov ecx
, cnt
// num of bytes to scan
387 mov edi
, buf
// pointer byte stream
388 mov eax
, chr
// byte to scan for
389 repne scasb
// look for the byte in the byte stream
390 jnz exit_memchr
// Z flag set if byte found
391 dec edi
// scasb always increments edi even when it
392 // finds the required byte
399 while ( cnt
&& (*(unsigned char *)buf
!= (unsigned char)chr
) ) {
400 buf
= (unsigned char *)buf
+ 1;
404 return(cnt
? (void *)buf
: NULL
);
408 void WINAPI
IntToWstr(int i
, LPWSTR wstr
);
410 #define WstrToInt(sz) _wtoi(sz)
411 #define atoiW(sz) _wtoi(sz)
412 #define atoiA(sz) atoi(sz)
414 // These are available to help managing bitmap VIDEOINFOHEADER media structures
416 extern const DWORD bits555
[3];
417 extern const DWORD bits565
[3];
418 extern const DWORD bits888
[3];
420 // These help convert between VIDEOINFOHEADER and BITMAPINFO structures
422 STDAPI_(const GUID
) GetTrueColorType(const BITMAPINFOHEADER
*pbmiHeader
);
423 STDAPI_(const GUID
) GetBitmapSubtype(const BITMAPINFOHEADER
*pbmiHeader
);
424 STDAPI_(WORD
) GetBitCount(const GUID
*pSubtype
);
426 // strmbase.lib implements this for compatibility with people who
427 // managed to link to this directly. we don't want to advertise it.
429 // STDAPI_(/* T */ CHAR *) GetSubtypeName(const GUID *pSubtype);
431 STDAPI_(CHAR
*) GetSubtypeNameA(const GUID
*pSubtype
);
432 STDAPI_(WCHAR
*) GetSubtypeNameW(const GUID
*pSubtype
);
435 #define GetSubtypeName GetSubtypeNameW
437 #define GetSubtypeName GetSubtypeNameA
440 STDAPI_(LONG
) GetBitmapFormatSize(const BITMAPINFOHEADER
*pHeader
);
441 STDAPI_(DWORD
) GetBitmapSize(const BITMAPINFOHEADER
*pHeader
);
442 STDAPI_(BOOL
) ContainsPalette(const VIDEOINFOHEADER
*pVideoInfo
);
443 STDAPI_(const RGBQUAD
*) GetBitmapPalette(const VIDEOINFOHEADER
*pVideoInfo
);
446 // Compares two interfaces and returns TRUE if they are on the same object
447 BOOL WINAPI
IsEqualObject(IUnknown
*pFirst
, IUnknown
*pSecond
);
449 // This is for comparing pins
450 #define EqualPins(pPin1, pPin2) IsEqualObject(pPin1, pPin2)
453 // Arithmetic helper functions
455 // Compute (a * b + rnd) / c
456 LONGLONG WINAPI
llMulDiv(LONGLONG a
, LONGLONG b
, LONGLONG c
, LONGLONG rnd
);
457 LONGLONG WINAPI
Int64x32Div32(LONGLONG a
, LONG b
, LONG c
, LONG rnd
);
460 // Avoids us dyna-linking to SysAllocString to copy BSTR strings
461 STDAPI
WriteBSTR(BSTR
* pstrDest
, LPCWSTR szSrc
);
462 STDAPI
FreeBSTR(BSTR
* pstr
);
464 // Return a wide string - allocating memory for it
467 // E_POINTER - ppszReturn == NULL
468 // E_OUTOFMEMORY - can't allocate memory for returned string
469 STDAPI
AMGetWideString(LPCWSTR pszString
, LPWSTR
*ppszReturn
);
471 // Special wait for objects owning windows
472 DWORD WINAPI
WaitDispatchingMessages(
477 HANDLE hEvent
= NULL
);
479 // HRESULT_FROM_WIN32 converts ERROR_SUCCESS to a success code, but in
480 // our use of HRESULT_FROM_WIN32, it typically means a function failed
481 // to call SetLastError(), and we still want a failure code.
483 #define AmHresultFromWin32(x) (MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, x))
485 // call GetLastError and return an HRESULT value that will fail the
486 // SUCCEEDED() macro.
487 HRESULT
AmGetLastErrorToHResult(void);
489 // duplicate of ATL's CComPtr to avoid linker conflicts.
491 IUnknown
* QzAtlComPtrAssign(IUnknown
** pp
, IUnknown
* lp
);
498 QzCComPtr() {p
=NULL
;}
501 if ((p
= lp
) != NULL
)
504 QzCComPtr(const QzCComPtr
<T
>& lp
)
506 if ((p
= lp
.p
) != NULL
)
509 ~QzCComPtr() {if (p
) p
->Release();}
510 void Release() {if (p
) p
->Release(); p
=NULL
;}
511 operator T
*() {return (T
*)p
;}
512 T
& operator*() {ASSERT(p
!=NULL
); return *p
; }
513 //The assert on operator& usually indicates a bug. If this is really
514 //what is needed, however, take the address of the p member explicitly.
515 T
** operator&() { ASSERT(p
==NULL
); return &p
; }
516 T
* operator->() { ASSERT(p
!=NULL
); return p
; }
517 T
* operator=(T
* lp
){return (T
*)QzAtlComPtrAssign((IUnknown
**)&p
, lp
);}
518 T
* operator=(const QzCComPtr
<T
>& lp
)
520 return (T
*)QzAtlComPtrAssign((IUnknown
**)&p
, lp
.p
);
523 bool operator!(){return (p
== NULL
);}
525 BOOL
operator!(){return (p
== NULL
) ? TRUE
: FALSE
;}
530 MMRESULT
CompatibleTimeSetEvent( UINT uDelay
, UINT uResolution
, LPTIMECALLBACK lpTimeProc
, DWORD_PTR dwUser
, UINT fuEvent
);
531 bool TimeKillSynchronousFlagAvailable( void );
533 #endif /* __WXUTIL__ */