mirror of https://github.com/asterisk/asterisk
				
				
				
			
			You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							270 lines
						
					
					
						
							7.6 KiB
						
					
					
				
			
		
		
	
	
							270 lines
						
					
					
						
							7.6 KiB
						
					
					
				| //------------------------------------------------------------------------------
 | |
| // File: ComBase.cpp
 | |
| //
 | |
| // Desc: DirectShow base classes - implements class hierarchy for creating
 | |
| //       COM objects.
 | |
| //
 | |
| // Copyright (c) 1992-2001 Microsoft Corporation.  All rights reserved.
 | |
| //------------------------------------------------------------------------------
 | |
| 
 | |
| #include <pjmedia-videodev/config.h>
 | |
| 
 | |
| #if defined(PJMEDIA_VIDEO_DEV_HAS_DSHOW) && PJMEDIA_VIDEO_DEV_HAS_DSHOW != 0
 | |
| 
 | |
| #include <streams.h>
 | |
| #pragma warning( disable : 4514 )   // Disable warnings re unused inline functions
 | |
| 
 | |
| 
 | |
| /* Define the static member variable */
 | |
| 
 | |
| LONG CBaseObject::m_cObjects = 0;
 | |
| 
 | |
| 
 | |
| /* Constructor */
 | |
| 
 | |
| CBaseObject::CBaseObject(__in_opt LPCTSTR pName)
 | |
| {
 | |
|     /* Increment the number of active objects */
 | |
|     InterlockedIncrement(&m_cObjects);
 | |
| 
 | |
| #ifdef DEBUG
 | |
| 
 | |
| #ifdef UNICODE
 | |
|     m_dwCookie = DbgRegisterObjectCreation(0, pName);
 | |
| #else
 | |
|     m_dwCookie = DbgRegisterObjectCreation(pName, 0);
 | |
| #endif
 | |
| 
 | |
| #endif
 | |
| }
 | |
| 
 | |
| #ifdef UNICODE
 | |
| CBaseObject::CBaseObject(const char *pName)
 | |
| {
 | |
|     /* Increment the number of active objects */
 | |
|     InterlockedIncrement(&m_cObjects);
 | |
| 
 | |
| #ifdef DEBUG
 | |
|     m_dwCookie = DbgRegisterObjectCreation(pName, 0);
 | |
| #endif
 | |
| }
 | |
| #endif
 | |
| 
 | |
| HINSTANCE	hlibOLEAut32;
 | |
| 
 | |
| /* Destructor */
 | |
| 
 | |
| CBaseObject::~CBaseObject()
 | |
| {
 | |
|     /* Decrement the number of objects active */
 | |
|     if (InterlockedDecrement(&m_cObjects) == 0) {
 | |
| 	if (hlibOLEAut32) {
 | |
| 	    FreeLibrary(hlibOLEAut32);
 | |
| 
 | |
| 	    hlibOLEAut32 = 0;
 | |
| 	}
 | |
|     };
 | |
| 
 | |
| 
 | |
| #ifdef DEBUG
 | |
|     DbgRegisterObjectDestruction(m_dwCookie);
 | |
| #endif
 | |
| }
 | |
| 
 | |
| static const TCHAR szOle32Aut[]   = TEXT("OleAut32.dll");
 | |
| 
 | |
| HINSTANCE LoadOLEAut32()
 | |
| {
 | |
|     if (hlibOLEAut32 == 0) {
 | |
| 
 | |
| 	hlibOLEAut32 = LoadLibrary(szOle32Aut);
 | |
|     }
 | |
| 
 | |
|     return hlibOLEAut32;
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Constructor */
 | |
| 
 | |
| // We know we use "this" in the initialization list, we also know we don't modify *phr.
 | |
| #pragma warning( disable : 4355 4100 )
 | |
| CUnknown::CUnknown(__in_opt LPCTSTR pName, __in_opt LPUNKNOWN pUnk)
 | |
| : CBaseObject(pName)
 | |
| /* Start the object with a reference count of zero - when the      */
 | |
| /* object is queried for it's first interface this may be          */
 | |
| /* incremented depending on whether or not this object is          */
 | |
| /* currently being aggregated upon                                 */
 | |
| , m_cRef(0)
 | |
| /* Set our pointer to our IUnknown interface.                      */
 | |
| /* If we have an outer, use its, otherwise use ours.               */
 | |
| /* This pointer effectivly points to the owner of                  */
 | |
| /* this object and can be accessed by the GetOwner() method.       */
 | |
| , m_pUnknown( pUnk != 0 ? pUnk : reinterpret_cast<LPUNKNOWN>( static_cast<PNDUNKNOWN>(this) ) )
 | |
|  /* Why the double cast?  Well, the inner cast is a type-safe cast */
 | |
|  /* to pointer to a type from which we inherit.  The second is     */
 | |
|  /* type-unsafe but works because INonDelegatingUnknown "behaves   */
 | |
|  /* like" IUnknown. (Only the names on the methods change.)        */
 | |
| {
 | |
|     // Everything we need to do has been done in the initializer list
 | |
| }
 | |
| 
 | |
| // This does the same as above except it has a useless HRESULT argument
 | |
| // use the previous constructor, this is just left for compatibility...
 | |
| CUnknown::CUnknown(__in_opt LPCTSTR pName, __in_opt LPUNKNOWN pUnk, __inout_opt HRESULT *phr) :
 | |
|     CBaseObject(pName),
 | |
|     m_cRef(0),
 | |
|     m_pUnknown( pUnk != 0 ? pUnk : reinterpret_cast<LPUNKNOWN>( static_cast<PNDUNKNOWN>(this) ) )
 | |
| {
 | |
| }
 | |
| 
 | |
| #ifdef UNICODE
 | |
| CUnknown::CUnknown(__in_opt LPCSTR pName, __in_opt LPUNKNOWN pUnk)
 | |
| : CBaseObject(pName), m_cRef(0),
 | |
|     m_pUnknown( pUnk != 0 ? pUnk : reinterpret_cast<LPUNKNOWN>( static_cast<PNDUNKNOWN>(this) ) )
 | |
| { }
 | |
| 
 | |
| CUnknown::CUnknown(__in_opt LPCSTR pName, __in_opt LPUNKNOWN pUnk, __inout_opt HRESULT *phr) :
 | |
|     CBaseObject(pName), m_cRef(0),
 | |
|     m_pUnknown( pUnk != 0 ? pUnk : reinterpret_cast<LPUNKNOWN>( static_cast<PNDUNKNOWN>(this) ) )
 | |
| { }
 | |
| 
 | |
| #endif
 | |
| 
 | |
| #pragma warning( default : 4355 4100 )
 | |
| 
 | |
| 
 | |
| /* QueryInterface */
 | |
| 
 | |
| STDMETHODIMP CUnknown::NonDelegatingQueryInterface(REFIID riid, __deref_out void ** ppv)
 | |
| {
 | |
|     CheckPointer(ppv,E_POINTER);
 | |
|     ValidateReadWritePtr(ppv,sizeof(PVOID));
 | |
| 
 | |
|     /* We know only about IUnknown */
 | |
| 
 | |
|     if (riid == IID_IUnknown) {
 | |
|         GetInterface((LPUNKNOWN) (PNDUNKNOWN) this, ppv);
 | |
|         return NOERROR;
 | |
|     } else {
 | |
|         *ppv = NULL;
 | |
|         return E_NOINTERFACE;
 | |
|     }
 | |
| }
 | |
| 
 | |
| /* We have to ensure that we DON'T use a max macro, since these will typically   */
 | |
| /* lead to one of the parameters being evaluated twice.  Since we are worried    */
 | |
| /* about concurrency, we can't afford to access the m_cRef twice since we can't  */
 | |
| /* afford to run the risk that its value having changed between accesses.        */
 | |
| 
 | |
| template<class T> inline static T ourmax( const T & a, const T & b )
 | |
| {
 | |
|     return a > b ? a : b;
 | |
| }
 | |
| 
 | |
| /* AddRef */
 | |
| 
 | |
| STDMETHODIMP_(ULONG) CUnknown::NonDelegatingAddRef()
 | |
| {
 | |
|     LONG lRef = InterlockedIncrement( &m_cRef );
 | |
|     ASSERT(lRef > 0);
 | |
|     DbgLog((LOG_MEMORY,3,TEXT("    Obj %d ref++ = %d"),
 | |
|            m_dwCookie, m_cRef));
 | |
|     return ourmax(ULONG(m_cRef), 1ul);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Release */
 | |
| 
 | |
| STDMETHODIMP_(ULONG) CUnknown::NonDelegatingRelease()
 | |
| {
 | |
|     /* If the reference count drops to zero delete ourselves */
 | |
| 
 | |
|     LONG lRef = InterlockedDecrement( &m_cRef );
 | |
|     ASSERT(lRef >= 0);
 | |
| 
 | |
|     DbgLog((LOG_MEMORY,3,TEXT("    Object %d ref-- = %d"),
 | |
| 	    m_dwCookie, m_cRef));
 | |
|     if (lRef == 0) {
 | |
| 
 | |
|         // COM rules say we must protect against re-entrancy.
 | |
|         // If we are an aggregator and we hold our own interfaces
 | |
|         // on the aggregatee, the QI for these interfaces will
 | |
|         // addref ourselves. So after doing the QI we must release
 | |
|         // a ref count on ourselves. Then, before releasing the
 | |
|         // private interface, we must addref ourselves. When we do
 | |
|         // this from the destructor here it will result in the ref
 | |
|         // count going to 1 and then back to 0 causing us to
 | |
|         // re-enter the destructor. Hence we add an extra refcount here
 | |
|         // once we know we will delete the object.
 | |
|         // for an example aggregator see filgraph\distrib.cpp.
 | |
| 
 | |
|         m_cRef++;
 | |
| 
 | |
|         delete this;
 | |
|         return ULONG(0);
 | |
|     } else {
 | |
|         //  Don't touch m_cRef again even in this leg as the object
 | |
|         //  may have just been released on another thread too
 | |
|         return ourmax(ULONG(lRef), 1ul);
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Return an interface pointer to a requesting client
 | |
|    performing a thread safe AddRef as necessary */
 | |
| 
 | |
| STDAPI GetInterface(LPUNKNOWN pUnk, __out void **ppv)
 | |
| {
 | |
|     CheckPointer(ppv, E_POINTER);
 | |
|     *ppv = pUnk;
 | |
|     pUnk->AddRef();
 | |
|     return NOERROR;
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Compares two interfaces and returns TRUE if they are on the same object */
 | |
| 
 | |
| BOOL WINAPI IsEqualObject(IUnknown *pFirst, IUnknown *pSecond)
 | |
| {
 | |
|     /*  Different objects can't have the same interface pointer for
 | |
|         any interface
 | |
|     */
 | |
|     if (pFirst == pSecond) {
 | |
|         return TRUE;
 | |
|     }
 | |
|     /*  OK - do it the hard way - check if they have the same
 | |
|         IUnknown pointers - a single object can only have one of these
 | |
|     */
 | |
|     LPUNKNOWN pUnknown1;     // Retrieve the IUnknown interface
 | |
|     LPUNKNOWN pUnknown2;     // Retrieve the other IUnknown interface
 | |
|     HRESULT hr;              // General OLE return code
 | |
| 
 | |
|     ASSERT(pFirst);
 | |
|     ASSERT(pSecond);
 | |
| 
 | |
|     /* See if the IUnknown pointers match */
 | |
| 
 | |
|     hr = pFirst->QueryInterface(IID_IUnknown,(void **) &pUnknown1);
 | |
|     if (FAILED(hr)) {
 | |
|         return FALSE;
 | |
|     }
 | |
|     ASSERT(pUnknown1);
 | |
| 
 | |
|     /* Release the extra interface we hold */
 | |
| 
 | |
|     pUnknown1->Release();
 | |
| 
 | |
|     hr = pSecond->QueryInterface(IID_IUnknown,(void **) &pUnknown2);
 | |
|     if (FAILED(hr)) {
 | |
|         return FALSE;
 | |
|     }
 | |
|     ASSERT(pUnknown2);
 | |
| 
 | |
|     /* Release the extra interface we hold */
 | |
| 
 | |
|     pUnknown2->Release();
 | |
|     return (pUnknown1 == pUnknown2);
 | |
| }
 | |
| 
 | |
| #endif /* PJMEDIA_VIDEO_DEV_HAS_DSHOW */
 |