* #27232: jni: added pjproject checkout as regular git content

We will remove it once the next release of pjsip (with Android support)
comes out and is merged into SFLphone.
diff --git a/jni/pjproject-android/.svn/pristine/87/87e2803278326f8e1c35e26cf2ce24b765c0d7ff.svn-base b/jni/pjproject-android/.svn/pristine/87/87e2803278326f8e1c35e26cf2ce24b765c0d7ff.svn-base
new file mode 100644
index 0000000..3a1dc38
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/87/87e2803278326f8e1c35e26cf2ce24b765c0d7ff.svn-base
@@ -0,0 +1,1478 @@
+//------------------------------------------------------------------------------

+// File: WXDebug.cpp

+//

+// Desc: DirectShow base classes - implements ActiveX system debugging

+//       facilities.

+//

+// 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

+

+#define _WINDLL

+

+#include <streams.h>

+#include <stdarg.h>

+#include <stdio.h>

+#include <dvdmedia.h>

+

+#ifdef DEBUG

+#ifdef UNICODE

+#ifndef _UNICODE

+#define _UNICODE

+#endif // _UNICODE

+#endif // UNICODE

+#endif // DEBUG

+

+#include <tchar.h>

+#include <strsafe.h>

+

+#ifdef DEBUG

+static void DisplayBITMAPINFO(const BITMAPINFOHEADER* pbmi);

+static void DisplayRECT(LPCTSTR szLabel, const RECT& rc);

+

+// The Win32 wsprintf() function writes a maximum of 1024 characters to it's output buffer.

+// See the documentation for wsprintf()'s lpOut parameter for more information.

+const INT iDEBUGINFO = 1024;                 // Used to format strings

+

+/* For every module and executable we store a debugging level for each of

+   the five categories (eg LOG_ERROR and LOG_TIMING). This makes it easy

+   to isolate and debug individual modules without seeing everybody elses

+   spurious debug output. The keys are stored in the registry under the

+   HKEY_LOCAL_MACHINE\SOFTWARE\Debug\<Module Name>\<KeyName> key values

+   NOTE these must be in the same order as their enumeration definition */

+

+const LPCTSTR pKeyNames[] = {

+    TEXT("TIMING"),      // Timing and performance measurements

+    TEXT("TRACE"),       // General step point call tracing

+    TEXT("MEMORY"),      // Memory and object allocation/destruction

+    TEXT("LOCKING"),     // Locking/unlocking of critical sections

+    TEXT("ERROR"),       // Debug error notification

+    TEXT("CUSTOM1"),

+    TEXT("CUSTOM2"),

+    TEXT("CUSTOM3"),

+    TEXT("CUSTOM4"),

+    TEXT("CUSTOM5")

+    };

+

+const TCHAR CAutoTrace::_szEntering[] = TEXT("->: %s");

+const TCHAR CAutoTrace::_szLeaving[]  = TEXT("<-: %s");

+

+const INT iMAXLEVELS = NUMELMS(pKeyNames);  // Maximum debug categories

+

+HINSTANCE m_hInst;                          // Module instance handle

+TCHAR m_ModuleName[iDEBUGINFO];             // Cut down module name

+DWORD m_Levels[iMAXLEVELS];                 // Debug level per category

+CRITICAL_SECTION m_CSDebug;                 // Controls access to list

+DWORD m_dwNextCookie;                       // Next active object ID

+ObjectDesc *pListHead = NULL;               // First active object

+DWORD m_dwObjectCount;                      // Active object count

+BOOL m_bInit = FALSE;                       // Have we been initialised

+HANDLE m_hOutput = INVALID_HANDLE_VALUE;    // Optional output written here

+DWORD dwWaitTimeout = INFINITE;             // Default timeout value

+DWORD dwTimeOffset;			    // Time of first DbgLog call

+bool g_fUseKASSERT = false;                 // don't create messagebox

+bool g_fDbgInDllEntryPoint = false;

+bool g_fAutoRefreshLevels = false;

+

+LPCTSTR pBaseKey = TEXT("SOFTWARE\\Microsoft\\DirectShow\\Debug");

+LPCTSTR pGlobalKey = TEXT("GLOBAL");

+static CHAR *pUnknownName = "UNKNOWN";

+

+LPCTSTR TimeoutName = TEXT("TIMEOUT");

+

+/* This sets the instance handle that the debug library uses to find

+   the module's file name from the Win32 GetModuleFileName function */

+

+void WINAPI DbgInitialise(HINSTANCE hInst)

+{

+    InitializeCriticalSection(&m_CSDebug);

+    m_bInit = TRUE;

+

+    m_hInst = hInst;

+    DbgInitModuleName();

+    if (GetProfileInt(m_ModuleName, TEXT("BreakOnLoad"), 0))

+       DebugBreak();

+    DbgInitModuleSettings(false);

+    DbgInitGlobalSettings(true);

+    dwTimeOffset = timeGetTime();

+}

+

+

+/* This is called to clear up any resources the debug library uses - at the

+   moment we delete our critical section and the object list. The values we

+   retrieve from the registry are all done during initialisation but we don't

+   go looking for update notifications while we are running, if the values

+   are changed then the application has to be restarted to pick them up */

+

+void WINAPI DbgTerminate()

+{

+    if (m_hOutput != INVALID_HANDLE_VALUE) {

+       EXECUTE_ASSERT(CloseHandle(m_hOutput));

+       m_hOutput = INVALID_HANDLE_VALUE;

+    }

+    DeleteCriticalSection(&m_CSDebug);

+    m_bInit = FALSE;

+}

+

+

+/* This is called by DbgInitLogLevels to read the debug settings

+   for each logging category for this module from the registry */

+

+void WINAPI DbgInitKeyLevels(HKEY hKey, bool fTakeMax)

+{

+    LONG lReturn;               // Create key return value

+    LONG lKeyPos;               // Current key category

+    DWORD dwKeySize;            // Size of the key value

+    DWORD dwKeyType;            // Receives it's type

+    DWORD dwKeyValue;           // This fields value

+

+    /* Try and read a value for each key position in turn */

+    for (lKeyPos = 0;lKeyPos < iMAXLEVELS;lKeyPos++) {

+

+        dwKeySize = sizeof(DWORD);

+        lReturn = RegQueryValueEx(

+            hKey,                       // Handle to an open key

+            pKeyNames[lKeyPos],         // Subkey name derivation

+            NULL,                       // Reserved field

+            &dwKeyType,                 // Returns the field type

+            (LPBYTE) &dwKeyValue,       // Returns the field's value

+            &dwKeySize );               // Number of bytes transferred

+

+        /* If either the key was not available or it was not a DWORD value

+           then we ensure only the high priority debug logging is output

+           but we try and update the field to a zero filled DWORD value */

+

+        if (lReturn != ERROR_SUCCESS || dwKeyType != REG_DWORD)  {

+

+            dwKeyValue = 0;

+            lReturn = RegSetValueEx(

+                hKey,                   // Handle of an open key

+                pKeyNames[lKeyPos],     // Address of subkey name

+                (DWORD) 0,              // Reserved field

+                REG_DWORD,              // Type of the key field

+                (PBYTE) &dwKeyValue,    // Value for the field

+                sizeof(DWORD));         // Size of the field buffer

+

+            if (lReturn != ERROR_SUCCESS) {

+                DbgLog((LOG_ERROR,1,TEXT("Could not create subkey %s"),pKeyNames[lKeyPos]));

+                dwKeyValue = 0;

+            }

+        }

+        if(fTakeMax)

+        {

+            m_Levels[lKeyPos] = max(dwKeyValue,m_Levels[lKeyPos]);

+        }

+        else

+        {

+            if((m_Levels[lKeyPos] & LOG_FORCIBLY_SET) == 0) {

+                m_Levels[lKeyPos] = dwKeyValue;

+            }

+        }

+    }

+

+    /*  Read the timeout value for catching hangs */

+    dwKeySize = sizeof(DWORD);

+    lReturn = RegQueryValueEx(

+        hKey,                       // Handle to an open key

+        TimeoutName,                // Subkey name derivation

+        NULL,                       // Reserved field

+        &dwKeyType,                 // Returns the field type

+        (LPBYTE) &dwWaitTimeout,    // Returns the field's value

+        &dwKeySize );               // Number of bytes transferred

+

+    /* If either the key was not available or it was not a DWORD value

+       then we ensure only the high priority debug logging is output

+       but we try and update the field to a zero filled DWORD value */

+

+    if (lReturn != ERROR_SUCCESS || dwKeyType != REG_DWORD)  {

+

+        dwWaitTimeout = INFINITE;

+        lReturn = RegSetValueEx(

+            hKey,                   // Handle of an open key

+            TimeoutName,            // Address of subkey name

+            (DWORD) 0,              // Reserved field

+            REG_DWORD,              // Type of the key field

+            (PBYTE) &dwWaitTimeout, // Value for the field

+            sizeof(DWORD));         // Size of the field buffer

+

+        if (lReturn != ERROR_SUCCESS) {

+            DbgLog((LOG_ERROR,1,TEXT("Could not create subkey %s"),pKeyNames[lKeyPos]));

+            dwWaitTimeout = INFINITE;

+        }

+    }

+}

+

+void WINAPI DbgOutString(LPCTSTR psz)

+{

+    if (m_hOutput != INVALID_HANDLE_VALUE) {

+        UINT  cb = lstrlen(psz);

+        DWORD dw;

+#ifdef UNICODE

+        CHAR szDest[2048];

+        WideCharToMultiByte(CP_ACP, 0, psz, -1, szDest, NUMELMS(szDest), 0, 0);

+        WriteFile (m_hOutput, szDest, cb, &dw, NULL);

+#else

+        WriteFile (m_hOutput, psz, cb, &dw, NULL);

+#endif

+    } else {

+        OutputDebugString (psz);

+    }

+}

+

+

+

+

+HRESULT  DbgUniqueProcessName(LPCTSTR inName, LPTSTR outName)

+{

+    HRESULT hr = S_OK;

+    const TCHAR *pIn = inName;

+    int dotPos = -1;

+

+    //scan the input and record the last '.' position

+    while (*pIn && (pIn - inName) < MAX_PATH)

+    {

+        if ( TEXT('.') == *pIn )

+            dotPos = (int)(pIn-inName);

+        ++pIn;

+    }

+

+    if (*pIn) //input should be zero-terminated within MAX_PATH

+        return E_INVALIDARG;

+

+    DWORD dwProcessId = GetCurrentProcessId();

+

+    if (dotPos < 0) 

+    {

+        //no extension in the input, appending process id to the input

+        hr = StringCchPrintf(outName, MAX_PATH, TEXT("%s_%d"), inName, dwProcessId);

+    }

+    else

+    {

+        TCHAR pathAndBasename[MAX_PATH] = {0};

+        

+        //there's an extension  - zero-terminate the path and basename first by copying

+        hr = StringCchCopyN(pathAndBasename, MAX_PATH, inName, (size_t)dotPos);

+

+        //re-combine path, basename and extension with processId appended to a basename

+        if (SUCCEEDED(hr))

+            hr = StringCchPrintf(outName, MAX_PATH, TEXT("%s_%d%s"), pathAndBasename, dwProcessId, inName + dotPos);

+    }

+

+    return hr;

+}

+

+

+/* Called by DbgInitGlobalSettings to setup alternate logging destinations

+ */

+

+void WINAPI DbgInitLogTo (

+    HKEY hKey)

+{

+    LONG  lReturn;

+    DWORD dwKeyType;

+    DWORD dwKeySize;

+    TCHAR szFile[MAX_PATH] = {0};

+    static const TCHAR cszKey[] = TEXT("LogToFile");

+

+    dwKeySize = MAX_PATH;

+    lReturn = RegQueryValueEx(

+        hKey,                       // Handle to an open key

+        cszKey,                     // Subkey name derivation

+        NULL,                       // Reserved field

+        &dwKeyType,                 // Returns the field type

+        (LPBYTE) szFile,            // Returns the field's value

+        &dwKeySize);                // Number of bytes transferred

+

+    // create an empty key if it does not already exist

+    //

+    if (lReturn != ERROR_SUCCESS || dwKeyType != REG_SZ)

+       {

+       dwKeySize = sizeof(TCHAR);

+       lReturn = RegSetValueEx(

+            hKey,                   // Handle of an open key

+            cszKey,                 // Address of subkey name

+            (DWORD) 0,              // Reserved field

+            REG_SZ,                 // Type of the key field

+            (PBYTE)szFile,          // Value for the field

+            dwKeySize);            // Size of the field buffer

+       }

+

+    // if an output-to was specified.  try to open it.

+    //

+    if (m_hOutput != INVALID_HANDLE_VALUE) {

+       EXECUTE_ASSERT(CloseHandle (m_hOutput));

+       m_hOutput = INVALID_HANDLE_VALUE;

+    }

+    if (szFile[0] != 0)

+       {

+       if (!lstrcmpi(szFile, TEXT("Console"))) {

+          m_hOutput = GetStdHandle (STD_OUTPUT_HANDLE);

+          if (m_hOutput == INVALID_HANDLE_VALUE) {

+             AllocConsole ();

+             m_hOutput = GetStdHandle (STD_OUTPUT_HANDLE);

+          }

+          SetConsoleTitle (TEXT("ActiveX Debug Output"));

+       } else if (szFile[0] &&

+                lstrcmpi(szFile, TEXT("Debug")) &&

+                lstrcmpi(szFile, TEXT("Debugger")) &&

+                lstrcmpi(szFile, TEXT("Deb")))

+          {

+            m_hOutput = CreateFile(szFile, GENERIC_WRITE,

+                                 FILE_SHARE_READ,

+                                 NULL, OPEN_ALWAYS,

+                                 FILE_ATTRIBUTE_NORMAL,

+                                 NULL);

+

+            if (INVALID_HANDLE_VALUE == m_hOutput &&

+                GetLastError() == ERROR_SHARING_VIOLATION)

+            {

+               TCHAR uniqueName[MAX_PATH] = {0};

+               if (SUCCEEDED(DbgUniqueProcessName(szFile, uniqueName)))

+               {

+                    m_hOutput = CreateFile(uniqueName, GENERIC_WRITE,

+                                         FILE_SHARE_READ,

+                                         NULL, OPEN_ALWAYS,

+                                         FILE_ATTRIBUTE_NORMAL,

+                                         NULL);

+               }

+            }

+               

+            if (INVALID_HANDLE_VALUE != m_hOutput)

+            {

+              static const TCHAR cszBar[] = TEXT("\r\n\r\n=====DbgInitialize()=====\r\n\r\n");

+              SetFilePointer (m_hOutput, 0, NULL, FILE_END);

+              DbgOutString (cszBar);

+            }

+          }

+       }

+}

+

+

+

+/* This is called by DbgInitLogLevels to read the global debug settings for

+   each logging category for this module from the registry. Normally each

+   module has it's own values set for it's different debug categories but

+   setting the global SOFTWARE\Debug\Global applies them to ALL modules */

+

+void WINAPI DbgInitGlobalSettings(bool fTakeMax)

+{

+    LONG lReturn;               // Create key return value

+    TCHAR szInfo[iDEBUGINFO];   // Constructs key names

+    HKEY hGlobalKey;            // Global override key

+

+    /* Construct the global base key name */

+    (void)StringCchPrintf(szInfo,NUMELMS(szInfo),TEXT("%s\\%s"),pBaseKey,pGlobalKey);

+

+    /* Create or open the key for this module */

+    lReturn = RegCreateKeyEx(HKEY_LOCAL_MACHINE,   // Handle of an open key

+                             szInfo,               // Address of subkey name

+                             (DWORD) 0,            // Reserved value

+                             NULL,                 // Address of class name

+                             (DWORD) 0,            // Special options flags

+                             GENERIC_READ | GENERIC_WRITE,   // Desired security access

+                             NULL,                 // Key security descriptor

+                             &hGlobalKey,          // Opened handle buffer

+                             NULL);                // What really happened

+

+    if (lReturn != ERROR_SUCCESS) {

+        lReturn = RegCreateKeyEx(HKEY_LOCAL_MACHINE,   // Handle of an open key

+                                 szInfo,               // Address of subkey name

+                                 (DWORD) 0,            // Reserved value

+                                 NULL,                 // Address of class name

+                                 (DWORD) 0,            // Special options flags

+                                 GENERIC_READ,         // Desired security access

+                                 NULL,                 // Key security descriptor

+                                 &hGlobalKey,          // Opened handle buffer

+                                 NULL);                // What really happened

+        if (lReturn != ERROR_SUCCESS) {

+            DbgLog((LOG_ERROR,1,TEXT("Could not access GLOBAL module key")));

+        }

+        return;

+    }

+

+    DbgInitKeyLevels(hGlobalKey, fTakeMax);

+    RegCloseKey(hGlobalKey);

+}

+

+

+/* This sets the debugging log levels for the different categories. We start

+   by opening (or creating if not already available) the SOFTWARE\Debug key

+   that all these settings live under. We then look at the global values

+   set under SOFTWARE\Debug\Global which apply on top of the individual

+   module settings. We then load the individual module registry settings */

+

+void WINAPI DbgInitModuleSettings(bool fTakeMax)

+{

+    LONG lReturn;               // Create key return value

+    TCHAR szInfo[iDEBUGINFO];   // Constructs key names

+    HKEY hModuleKey;            // Module key handle

+

+    /* Construct the base key name */

+    (void)StringCchPrintf(szInfo,NUMELMS(szInfo),TEXT("%s\\%s"),pBaseKey,m_ModuleName);

+

+    /* Create or open the key for this module */

+    lReturn = RegCreateKeyEx(HKEY_LOCAL_MACHINE,   // Handle of an open key

+                             szInfo,               // Address of subkey name

+                             (DWORD) 0,            // Reserved value

+                             NULL,                 // Address of class name

+                             (DWORD) 0,            // Special options flags

+                             GENERIC_READ | GENERIC_WRITE, // Desired security access

+                             NULL,                 // Key security descriptor

+                             &hModuleKey,          // Opened handle buffer

+                             NULL);                // What really happened

+

+    if (lReturn != ERROR_SUCCESS) {

+        lReturn = RegCreateKeyEx(HKEY_LOCAL_MACHINE,   // Handle of an open key

+                                 szInfo,               // Address of subkey name

+                                 (DWORD) 0,            // Reserved value

+                                 NULL,                 // Address of class name

+                                 (DWORD) 0,            // Special options flags

+                                 GENERIC_READ,         // Desired security access

+                                 NULL,                 // Key security descriptor

+                                 &hModuleKey,          // Opened handle buffer

+                                 NULL);                // What really happened

+        if (lReturn != ERROR_SUCCESS) {

+            DbgLog((LOG_ERROR,1,TEXT("Could not access module key")));

+        }

+        return;

+    }

+

+    DbgInitLogTo(hModuleKey);

+    DbgInitKeyLevels(hModuleKey, fTakeMax);

+    RegCloseKey(hModuleKey);

+}

+

+

+/* Initialise the module file name */

+

+void WINAPI DbgInitModuleName()

+{

+    TCHAR FullName[iDEBUGINFO];     // Load the full path and module name

+    LPTSTR pName;                   // Searches from the end for a backslash

+

+    GetModuleFileName(m_hInst,FullName,iDEBUGINFO);

+    pName = _tcsrchr(FullName,'\\');

+    if (pName == NULL) {

+        pName = FullName;

+    } else {

+        pName++;

+    }

+    (void)StringCchCopy(m_ModuleName,NUMELMS(m_ModuleName), pName);

+}

+

+struct MsgBoxMsg

+{

+    HWND hwnd;

+    LPCTSTR szTitle;

+    LPCTSTR szMessage;

+    DWORD dwFlags;

+    INT iResult;

+};

+

+//

+// create a thread to call MessageBox(). calling MessageBox() on

+// random threads at bad times can confuse the host (eg IE).

+//

+DWORD WINAPI MsgBoxThread(

+  __inout LPVOID lpParameter   // thread data

+  )

+{

+    MsgBoxMsg *pmsg = (MsgBoxMsg *)lpParameter;

+    pmsg->iResult = MessageBox(

+        pmsg->hwnd,

+        pmsg->szTitle,

+        pmsg->szMessage,

+        pmsg->dwFlags);

+

+    return 0;

+}

+

+INT MessageBoxOtherThread(

+    HWND hwnd,

+    LPCTSTR szTitle,

+    LPCTSTR szMessage,

+    DWORD dwFlags)

+{

+    if(g_fDbgInDllEntryPoint)

+    {

+        // can't wait on another thread because we have the loader

+        // lock held in the dll entry point.

+        // This can crash sometimes so just skip it

+        // return MessageBox(hwnd, szTitle, szMessage, dwFlags);

+        return IDCANCEL;

+    }

+    else

+    {

+        MsgBoxMsg msg = {hwnd, szTitle, szMessage, dwFlags, 0};

+        DWORD dwid;

+        HANDLE hThread = CreateThread(

+            0,                      // security

+            0,                      // stack size

+            MsgBoxThread,

+            (void *)&msg,           // arg

+            0,                      // flags

+            &dwid);

+        if(hThread)

+        {

+            WaitForSingleObject(hThread, INFINITE);

+            CloseHandle(hThread);

+            return msg.iResult;

+        }

+

+        // break into debugger on failure.

+        return IDCANCEL;

+    }

+}

+

+/* Displays a message box if the condition evaluated to FALSE */

+

+void WINAPI DbgAssert(LPCTSTR pCondition,LPCTSTR pFileName,INT iLine)

+{

+    if(g_fUseKASSERT)

+    {

+        DbgKernelAssert(pCondition, pFileName, iLine);

+    }

+    else

+    {

+

+        TCHAR szInfo[iDEBUGINFO];

+

+        (void)StringCchPrintf(szInfo, NUMELMS(szInfo),TEXT("%s \nAt line %d of %s\nContinue? (Cancel to debug)"),

+                 pCondition, iLine, pFileName);

+

+        INT MsgId = MessageBoxOtherThread(NULL,szInfo,TEXT("ASSERT Failed"),

+                                          MB_SYSTEMMODAL |

+                                          MB_ICONHAND |

+                                          MB_YESNOCANCEL |

+                                          MB_SETFOREGROUND);

+        switch (MsgId)

+        {

+          case IDNO:              /* Kill the application */

+

+              FatalAppExit(FALSE, TEXT("Application terminated"));

+              break;

+

+          case IDCANCEL:          /* Break into the debugger */

+

+              DebugBreak();

+              break;

+

+          case IDYES:             /* Ignore assertion continue execution */

+              break;

+        }

+    }

+}

+

+/* Displays a message box at a break point */

+

+void WINAPI DbgBreakPoint(LPCTSTR pCondition,LPCTSTR pFileName,INT iLine)

+{

+    if(g_fUseKASSERT)

+    {

+        DbgKernelAssert(pCondition, pFileName, iLine);

+    }

+    else

+    {

+        TCHAR szInfo[iDEBUGINFO];

+

+        (void)StringCchPrintf(szInfo, NUMELMS(szInfo),TEXT("%s \nAt line %d of %s\nContinue? (Cancel to debug)"),

+                 pCondition, iLine, pFileName);

+

+        INT MsgId = MessageBoxOtherThread(NULL,szInfo,TEXT("Hard coded break point"),

+                                          MB_SYSTEMMODAL |

+                                          MB_ICONHAND |

+                                          MB_YESNOCANCEL |

+                                          MB_SETFOREGROUND);

+        switch (MsgId)

+        {

+          case IDNO:              /* Kill the application */

+

+              FatalAppExit(FALSE, TEXT("Application terminated"));

+              break;

+

+          case IDCANCEL:          /* Break into the debugger */

+

+              DebugBreak();

+              break;

+

+          case IDYES:             /* Ignore break point continue execution */

+              break;

+        }

+    }

+}

+

+void WINAPI DbgBreakPoint(LPCTSTR pFileName,INT iLine,__format_string LPCTSTR szFormatString,...)

+{

+    // A debug break point message can have at most 2000 characters if

+    // ANSI or UNICODE characters are being used.  A debug break point message

+    // can have between 1000 and 2000 double byte characters in it.  If a

+    // particular message needs more characters, then the value of this constant

+    // should be increased.

+    const DWORD MAX_BREAK_POINT_MESSAGE_SIZE = 2000;

+

+    TCHAR szBreakPointMessage[MAX_BREAK_POINT_MESSAGE_SIZE];

+

+    va_list va;

+    va_start( va, szFormatString );

+

+    HRESULT hr = StringCchVPrintf( szBreakPointMessage, NUMELMS(szBreakPointMessage), szFormatString, va );

+

+    va_end(va);

+

+    if( FAILED(hr) ) {

+        DbgBreak( "ERROR in DbgBreakPoint().  The variable length debug message could not be displayed because StringCchVPrintf() failed." );

+        return;

+    }

+

+    ::DbgBreakPoint( szBreakPointMessage, pFileName, iLine );

+}

+

+

+/* When we initialised the library we stored in the m_Levels array the current

+   debug output level for this module for each of the five categories. When

+   some debug logging is sent to us it can be sent with a combination of the

+   categories (if it is applicable to many for example) in which case we map

+   the type's categories into their current debug levels and see if any of

+   them can be accepted. The function looks at each bit position in turn from

+   the input type field and then compares it's debug level with the modules.

+

+   A level of 0 means that output is always sent to the debugger.  This is

+   due to producing output if the input level is <= m_Levels.

+*/

+

+

+BOOL WINAPI DbgCheckModuleLevel(DWORD Type,DWORD Level)

+{

+    if(g_fAutoRefreshLevels)

+    {

+        // re-read the registry every second. We cannot use RegNotify() to

+        // notice registry changes because it's not available on win9x.

+        static DWORD g_dwLastRefresh = 0;

+        DWORD dwTime = timeGetTime();

+        if(dwTime - g_dwLastRefresh > 1000) {

+            g_dwLastRefresh = dwTime;

+

+            // there's a race condition: multiple threads could update the

+            // values. plus read and write not synchronized. no harm

+            // though.

+            DbgInitModuleSettings(false);

+        }

+    }

+

+

+    DWORD Mask = 0x01;

+

+    // If no valid bits are set return FALSE

+    if ((Type & ((1<<iMAXLEVELS)-1))) {

+

+	// speed up unconditional output.

+	if (0==Level)

+	    return(TRUE);

+	

+        for (LONG lKeyPos = 0;lKeyPos < iMAXLEVELS;lKeyPos++) {

+            if (Type & Mask) {

+                if (Level <= (m_Levels[lKeyPos] & ~LOG_FORCIBLY_SET)) {

+                    return TRUE;

+                }

+            }

+            Mask <<= 1;

+        }

+    }

+    return FALSE;

+}

+

+

+/* Set debug levels to a given value */

+

+void WINAPI DbgSetModuleLevel(DWORD Type, DWORD Level)

+{

+    DWORD Mask = 0x01;

+

+    for (LONG lKeyPos = 0;lKeyPos < iMAXLEVELS;lKeyPos++) {

+        if (Type & Mask) {

+            m_Levels[lKeyPos] = Level | LOG_FORCIBLY_SET;

+        }

+        Mask <<= 1;

+    }

+}

+

+/* whether to check registry values periodically. this isn't turned

+   automatically because of the potential performance hit. */

+void WINAPI DbgSetAutoRefreshLevels(bool fAuto)

+{

+    g_fAutoRefreshLevels = fAuto;

+}

+

+#ifdef UNICODE

+//

+// warning -- this function is implemented twice for ansi applications

+// linking to the unicode library

+//

+void WINAPI DbgLogInfo(DWORD Type,DWORD Level,__format_string LPCSTR pFormat,...)

+{

+    /* Check the current level for this type combination */

+

+    BOOL bAccept = DbgCheckModuleLevel(Type,Level);

+    if (bAccept == FALSE) {

+        return;

+    }

+

+    TCHAR szInfo[2000];

+

+    /* Format the variable length parameter list */

+

+    va_list va;

+    va_start(va, pFormat);

+

+    (void)StringCchPrintf(szInfo, NUMELMS(szInfo),

+             TEXT("%s(tid %x) %8d : "),

+             m_ModuleName,

+             GetCurrentThreadId(), timeGetTime() - dwTimeOffset);

+

+    CHAR szInfoA[2000];

+    WideCharToMultiByte(CP_ACP, 0, szInfo, -1, szInfoA, NUMELMS(szInfoA), 0, 0);

+

+    (void)StringCchVPrintfA(szInfoA + lstrlenA(szInfoA), NUMELMS(szInfoA) - lstrlenA(szInfoA), pFormat, va);

+    (void)StringCchCatA(szInfoA, NUMELMS(szInfoA), "\r\n");

+

+    WCHAR wszOutString[2000];

+    MultiByteToWideChar(CP_ACP, 0, szInfoA, -1, wszOutString, NUMELMS(wszOutString));

+    DbgOutString(wszOutString);

+

+    va_end(va);

+}

+

+void WINAPI DbgAssert(LPCSTR pCondition,LPCSTR pFileName,INT iLine)

+{

+    if(g_fUseKASSERT)

+    {

+        DbgKernelAssert(pCondition, pFileName, iLine);

+    }

+    else

+    {

+

+        TCHAR szInfo[iDEBUGINFO];

+

+        (void)StringCchPrintf(szInfo, NUMELMS(szInfo), TEXT("%hs \nAt line %d of %hs\nContinue? (Cancel to debug)"),

+                 pCondition, iLine, pFileName);

+

+        INT MsgId = MessageBoxOtherThread(NULL,szInfo,TEXT("ASSERT Failed"),

+                                          MB_SYSTEMMODAL |

+                                          MB_ICONHAND |

+                                          MB_YESNOCANCEL |

+                                          MB_SETFOREGROUND);

+        switch (MsgId)

+        {

+          case IDNO:              /* Kill the application */

+

+              FatalAppExit(FALSE, TEXT("Application terminated"));

+              break;

+

+          case IDCANCEL:          /* Break into the debugger */

+

+              DebugBreak();

+              break;

+

+          case IDYES:             /* Ignore assertion continue execution */

+              break;

+        }

+    }

+}

+

+/* Displays a message box at a break point */

+

+void WINAPI DbgBreakPoint(LPCSTR pCondition,LPCSTR pFileName,INT iLine)

+{

+    if(g_fUseKASSERT)

+    {

+        DbgKernelAssert(pCondition, pFileName, iLine);

+    }

+    else

+    {

+        TCHAR szInfo[iDEBUGINFO];

+

+        (void)StringCchPrintf(szInfo, NUMELMS(szInfo),TEXT("%hs \nAt line %d of %hs\nContinue? (Cancel to debug)"),

+                 pCondition, iLine, pFileName);

+

+        INT MsgId = MessageBoxOtherThread(NULL,szInfo,TEXT("Hard coded break point"),

+                                          MB_SYSTEMMODAL |

+                                          MB_ICONHAND |

+                                          MB_YESNOCANCEL |

+                                          MB_SETFOREGROUND);

+        switch (MsgId)

+        {

+          case IDNO:              /* Kill the application */

+

+              FatalAppExit(FALSE, TEXT("Application terminated"));

+              break;

+

+          case IDCANCEL:          /* Break into the debugger */

+

+              DebugBreak();

+              break;

+

+          case IDYES:             /* Ignore break point continue execution */

+              break;

+        }

+    }

+}

+

+void WINAPI DbgKernelAssert(LPCSTR pCondition,LPCSTR pFileName,INT iLine)

+{

+    DbgLog((LOG_ERROR,0,TEXT("Assertion FAILED (%hs) at line %d in file %hs"),

+           pCondition, iLine, pFileName));

+    DebugBreak();

+}

+

+#endif

+

+/* Print a formatted string to the debugger prefixed with this module's name

+   Because the COMBASE classes are linked statically every module loaded will

+   have their own copy of this code. It therefore helps if the module name is

+   included on the output so that the offending code can be easily found */

+

+//

+// warning -- this function is implemented twice for ansi applications

+// linking to the unicode library

+//

+void WINAPI DbgLogInfo(DWORD Type,DWORD Level,LPCTSTR pFormat,...)

+{

+

+    /* Check the current level for this type combination */

+

+    BOOL bAccept = DbgCheckModuleLevel(Type,Level);

+    if (bAccept == FALSE) {

+        return;

+    }

+

+    TCHAR szInfo[2000];

+

+    /* Format the variable length parameter list */

+

+    va_list va;

+    va_start(va, pFormat);

+

+    (void)StringCchPrintf(szInfo, NUMELMS(szInfo),

+             TEXT("%s(tid %x) %8d : "),

+             m_ModuleName,

+             GetCurrentThreadId(), timeGetTime() - dwTimeOffset);

+

+    (void)StringCchVPrintf(szInfo + lstrlen(szInfo), NUMELMS(szInfo) - lstrlen(szInfo), pFormat, va);

+    (void)StringCchCat(szInfo, NUMELMS(szInfo), TEXT("\r\n"));

+    DbgOutString(szInfo);

+

+    va_end(va);

+}

+

+

+/* If we are executing as a pure kernel filter we cannot display message

+   boxes to the user, this provides an alternative which puts the error

+   condition on the debugger output with a suitable eye catching message */

+

+void WINAPI DbgKernelAssert(LPCTSTR pCondition,LPCTSTR pFileName,INT iLine)

+{

+    DbgLog((LOG_ERROR,0,TEXT("Assertion FAILED (%s) at line %d in file %s"),

+           pCondition, iLine, pFileName));

+    DebugBreak();

+}

+

+

+

+/* Each time we create an object derived from CBaseObject the constructor will

+   call us to register the creation of the new object. We are passed a string

+   description which we store away. We return a cookie that the constructor

+   uses to identify the object when it is destroyed later on. We update the

+   total number of active objects in the DLL mainly for debugging purposes */

+

+DWORD WINAPI DbgRegisterObjectCreation(LPCSTR szObjectName,

+                                       LPCWSTR wszObjectName)

+{

+    /* If this fires you have a mixed DEBUG/RETAIL build */

+

+    ASSERT(!!szObjectName ^ !!wszObjectName);

+

+    /* Create a place holder for this object description */

+

+    ObjectDesc *pObject = new ObjectDesc;

+    ASSERT(pObject);

+

+    /* It is valid to pass a NULL object name */

+    if (pObject == NULL) {

+        return FALSE;

+    }

+

+    /* Check we have been initialised - we may not be initialised when we are

+       being pulled in from an executable which has globally defined objects

+       as they are created by the C++ run time before WinMain is called */

+

+    if (m_bInit == FALSE) {

+        DbgInitialise(GetModuleHandle(NULL));

+    }

+

+    /* Grab the list critical section */

+    EnterCriticalSection(&m_CSDebug);

+

+    /* If no name then default to UNKNOWN */

+    if (!szObjectName && !wszObjectName) {

+        szObjectName = pUnknownName;

+    }

+

+    /* Put the new description at the head of the list */

+

+    pObject->m_szName = szObjectName;

+    pObject->m_wszName = wszObjectName;

+    pObject->m_dwCookie = ++m_dwNextCookie;

+    pObject->m_pNext = pListHead;

+

+    pListHead = pObject;

+    m_dwObjectCount++;

+

+    DWORD ObjectCookie = pObject->m_dwCookie;

+    ASSERT(ObjectCookie);

+

+    if(wszObjectName) {

+        DbgLog((LOG_MEMORY,2,TEXT("Object created   %d (%ls) %d Active"),

+                pObject->m_dwCookie, wszObjectName, m_dwObjectCount));

+    } else {

+        DbgLog((LOG_MEMORY,2,TEXT("Object created   %d (%hs) %d Active"),

+                pObject->m_dwCookie, szObjectName, m_dwObjectCount));

+    }

+

+    LeaveCriticalSection(&m_CSDebug);

+    return ObjectCookie;

+}

+

+

+/* This is called by the CBaseObject destructor when an object is about to be

+   destroyed, we are passed the cookie we returned during construction that

+   identifies this object. We scan the object list for a matching cookie and

+   remove the object if successful. We also update the active object count */

+

+BOOL WINAPI DbgRegisterObjectDestruction(DWORD dwCookie)

+{

+    /* Grab the list critical section */

+    EnterCriticalSection(&m_CSDebug);

+

+    ObjectDesc *pObject = pListHead;

+    ObjectDesc *pPrevious = NULL;

+

+    /* Scan the object list looking for a cookie match */

+

+    while (pObject) {

+        if (pObject->m_dwCookie == dwCookie) {

+            break;

+        }

+        pPrevious = pObject;

+        pObject = pObject->m_pNext;

+    }

+

+    if (pObject == NULL) {

+        DbgBreak("Apparently destroying a bogus object");

+        LeaveCriticalSection(&m_CSDebug);

+        return FALSE;

+    }

+

+    /* Is the object at the head of the list */

+

+    if (pPrevious == NULL) {

+        pListHead = pObject->m_pNext;

+    } else {

+        pPrevious->m_pNext = pObject->m_pNext;

+    }

+

+    /* Delete the object and update the housekeeping information */

+

+    m_dwObjectCount--;

+

+    if(pObject->m_wszName) {

+        DbgLog((LOG_MEMORY,2,TEXT("Object destroyed %d (%ls) %d Active"),

+                pObject->m_dwCookie, pObject->m_wszName, m_dwObjectCount));

+    } else {

+        DbgLog((LOG_MEMORY,2,TEXT("Object destroyed %d (%hs) %d Active"),

+                pObject->m_dwCookie, pObject->m_szName, m_dwObjectCount));

+    }

+

+    delete pObject;

+    LeaveCriticalSection(&m_CSDebug);

+    return TRUE;

+}

+

+

+/* This runs through the active object list displaying their details */

+

+void WINAPI DbgDumpObjectRegister()

+{

+    TCHAR szInfo[iDEBUGINFO];

+

+    /* Grab the list critical section */

+

+    EnterCriticalSection(&m_CSDebug);

+    ObjectDesc *pObject = pListHead;

+

+    /* Scan the object list displaying the name and cookie */

+

+    DbgLog((LOG_MEMORY,2,TEXT("")));

+    DbgLog((LOG_MEMORY,2,TEXT("   ID             Object Description")));

+    DbgLog((LOG_MEMORY,2,TEXT("")));

+

+    while (pObject) {

+        if(pObject->m_wszName) {

+            (void)StringCchPrintf(szInfo,NUMELMS(szInfo),TEXT("%5d (%p) %30ls"),pObject->m_dwCookie, &pObject, pObject->m_wszName);

+        } else {

+            (void)StringCchPrintf(szInfo,NUMELMS(szInfo),TEXT("%5d (%p) %30hs"),pObject->m_dwCookie, &pObject, pObject->m_szName);

+        }

+        DbgLog((LOG_MEMORY,2,szInfo));

+        pObject = pObject->m_pNext;

+    }

+

+    (void)StringCchPrintf(szInfo,NUMELMS(szInfo),TEXT("Total object count %5d"),m_dwObjectCount);

+    DbgLog((LOG_MEMORY,2,TEXT("")));

+    DbgLog((LOG_MEMORY,1,szInfo));

+    LeaveCriticalSection(&m_CSDebug);

+}

+

+/*  Debug infinite wait stuff */

+DWORD WINAPI DbgWaitForSingleObject(HANDLE h)

+{

+    DWORD dwWaitResult;

+    do {

+        dwWaitResult = WaitForSingleObject(h, dwWaitTimeout);

+        ASSERT(dwWaitResult == WAIT_OBJECT_0);

+    } while (dwWaitResult == WAIT_TIMEOUT);

+    return dwWaitResult;

+}

+DWORD WINAPI DbgWaitForMultipleObjects(DWORD nCount,

+                                __in_ecount(nCount) CONST HANDLE *lpHandles,

+                                BOOL bWaitAll)

+{

+    DWORD dwWaitResult;

+    do {

+        dwWaitResult = WaitForMultipleObjects(nCount,

+                                              lpHandles,

+                                              bWaitAll,

+                                              dwWaitTimeout);

+        ASSERT((DWORD)(dwWaitResult - WAIT_OBJECT_0) < MAXIMUM_WAIT_OBJECTS);

+    } while (dwWaitResult == WAIT_TIMEOUT);

+    return dwWaitResult;

+}

+

+void WINAPI DbgSetWaitTimeout(DWORD dwTimeout)

+{

+    dwWaitTimeout = dwTimeout;

+}

+

+#endif /* DEBUG */

+

+#ifdef _OBJBASE_H_

+

+    /*  Stuff for printing out our GUID names */

+

+    GUID_STRING_ENTRY g_GuidNames[] = {

+    #define OUR_GUID_ENTRY(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \

+    { #name, { l, w1, w2, { b1, b2,  b3,  b4,  b5,  b6,  b7,  b8 } } },

+        #include <uuids.h>

+    };

+

+    CGuidNameList GuidNames;

+    int g_cGuidNames = sizeof(g_GuidNames) / sizeof(g_GuidNames[0]);

+

+    char *CGuidNameList::operator [] (const GUID &guid)

+    {

+        for (int i = 0; i < g_cGuidNames; i++) {

+            if (g_GuidNames[i].guid == guid) {

+                return g_GuidNames[i].szName;

+            }

+        }

+        if (guid == GUID_NULL) {

+            return "GUID_NULL";

+        }

+

+	// !!! add something to print FOURCC guids?

+	

+	// shouldn't this print the hex CLSID?

+        return "Unknown GUID Name";

+    }

+

+#endif /* _OBJBASE_H_ */

+

+/*  CDisp class - display our data types */

+

+// clashes with REFERENCE_TIME

+CDisp::CDisp(LONGLONG ll, int Format)

+{

+    // note: this could be combined with CDisp(LONGLONG) by

+    // introducing a default format of CDISP_REFTIME

+    LARGE_INTEGER li;

+    li.QuadPart = ll;

+    switch (Format) {

+	case CDISP_DEC:

+	{

+	    TCHAR  temp[20];

+	    int pos=20;

+	    temp[--pos] = 0;

+	    int digit;

+	    // always output at least one digit

+	    do {

+		// Get the rightmost digit - we only need the low word

+	        digit = li.LowPart % 10;

+		li.QuadPart /= 10;

+		temp[--pos] = (TCHAR) digit+L'0';

+	    } while (li.QuadPart);

+	    (void)StringCchCopy(m_String, NUMELMS(m_String), temp+pos);

+	    break;

+	}

+	case CDISP_HEX:

+	default:

+	    (void)StringCchPrintf(m_String, NUMELMS(m_String), TEXT("0x%X%8.8X"), li.HighPart, li.LowPart);

+    }

+};

+

+CDisp::CDisp(REFCLSID clsid)

+{

+#ifdef UNICODE 

+    (void)StringFromGUID2(clsid, m_String, NUMELMS(m_String));

+#else

+    WCHAR wszTemp[50];

+    (void)StringFromGUID2(clsid, wszTemp, NUMELMS(wszTemp));

+    (void)StringCchPrintf(m_String, NUMELMS(m_String), TEXT("%S"), wszTemp);

+#endif

+};

+

+#ifdef __STREAMS__

+/*  Display stuff */

+CDisp::CDisp(CRefTime llTime)

+{

+    LONGLONG llDiv;

+    if (llTime < 0) {

+        llTime = -llTime;

+        (void)StringCchCopy(m_String, NUMELMS(m_String), TEXT("-"));

+    }

+    llDiv = (LONGLONG)24 * 3600 * 10000000;

+    if (llTime >= llDiv) {

+        (void)StringCchPrintf(m_String + lstrlen(m_String), NUMELMS(m_String) - lstrlen(m_String), TEXT("%d days "), (LONG)(llTime / llDiv));

+        llTime = llTime % llDiv;

+    }

+    llDiv = (LONGLONG)3600 * 10000000;

+    if (llTime >= llDiv) {

+        (void)StringCchPrintf(m_String + lstrlen(m_String), NUMELMS(m_String) - lstrlen(m_String), TEXT("%d hrs "), (LONG)(llTime / llDiv));

+        llTime = llTime % llDiv;

+    }

+    llDiv = (LONGLONG)60 * 10000000;

+    if (llTime >= llDiv) {

+        (void)StringCchPrintf(m_String + lstrlen(m_String), NUMELMS(m_String) - lstrlen(m_String), TEXT("%d mins "), (LONG)(llTime / llDiv));

+        llTime = llTime % llDiv;

+    }

+    (void)StringCchPrintf(m_String + lstrlen(m_String), NUMELMS(m_String) - lstrlen(m_String), TEXT("%d.%3.3d sec"),

+             (LONG)llTime / 10000000,

+             (LONG)((llTime % 10000000) / 10000));

+};

+

+#endif // __STREAMS__

+

+

+/*  Display pin */

+CDisp::CDisp(IPin *pPin)

+{

+    PIN_INFO pi;

+    TCHAR str[MAX_PIN_NAME];

+    CLSID clsid;

+

+    if (pPin) {

+       pPin->QueryPinInfo(&pi);

+       pi.pFilter->GetClassID(&clsid);

+       QueryPinInfoReleaseFilter(pi);

+      #ifndef UNICODE

+       WideCharToMultiByte(GetACP(), 0, pi.achName, lstrlenW(pi.achName) + 1,

+                           str, MAX_PIN_NAME, NULL, NULL);

+      #else

+       (void)StringCchCopy(str, NUMELMS(str), pi.achName);

+      #endif

+    } else {

+       (void)StringCchCopy(str, NUMELMS(str), TEXT("NULL IPin"));

+    }

+

+    m_pString = (PTCHAR) new TCHAR[lstrlen(str)+64];

+    if (!m_pString) {

+	return;

+    }

+

+    (void)StringCchPrintf(m_pString, lstrlen(str) + 64, TEXT("%hs(%s)"), GuidNames[clsid], str);

+}

+

+/*  Display filter or pin */

+CDisp::CDisp(IUnknown *pUnk)

+{

+    IBaseFilter *pf;

+    HRESULT hr = pUnk->QueryInterface(IID_IBaseFilter, (void **)&pf);

+    if(SUCCEEDED(hr))

+    {

+        FILTER_INFO fi;

+        hr = pf->QueryFilterInfo(&fi);

+        if(SUCCEEDED(hr))

+        {

+            QueryFilterInfoReleaseGraph(fi);

+

+            size_t len = lstrlenW(fi.achName)  + 1;

+

+            m_pString = new TCHAR[len];

+            if(m_pString)

+            {

+#ifdef UNICODE

+                (void)StringCchCopy(m_pString, len, fi.achName);

+#else

+                (void)StringCchPrintf(m_pString, len, "%S", fi.achName);

+#endif

+            }

+        }

+

+        pf->Release();

+

+        return;

+    }

+

+    IPin *pp;

+    hr = pUnk->QueryInterface(IID_IPin, (void **)&pp);

+    if(SUCCEEDED(hr))

+    {

+        CDisp::CDisp(pp);

+        pp->Release();

+        return;

+    }

+}

+

+

+CDisp::~CDisp()

+{

+}

+

+CDispBasic::~CDispBasic()

+{

+    if (m_pString != m_String) {

+	delete [] m_pString;

+    }

+}

+

+CDisp::CDisp(double d)

+{

+    (void)StringCchPrintf(m_String, NUMELMS(m_String), TEXT("%d.%03d"), (int) d, (int) ((d - (int) d) * 1000));

+}

+

+

+/* If built for debug this will display the media type details. We convert the

+   major and subtypes into strings and also ask the base classes for a string

+   description of the subtype, so MEDIASUBTYPE_RGB565 becomes RGB 565 16 bit

+   We also display the fields in the BITMAPINFOHEADER structure, this should

+   succeed as we do not accept input types unless the format is big enough */

+

+#ifdef DEBUG

+void WINAPI DisplayType(LPCTSTR label, const AM_MEDIA_TYPE *pmtIn)

+{

+

+    /* Dump the GUID types and a short description */

+

+    DbgLog((LOG_TRACE,5,TEXT("")));

+    DbgLog((LOG_TRACE,2,TEXT("%s  M type %hs  S type %hs"), label,

+	    GuidNames[pmtIn->majortype],

+	    GuidNames[pmtIn->subtype]));

+    DbgLog((LOG_TRACE,5,TEXT("Subtype description %s"),GetSubtypeName(&pmtIn->subtype)));

+

+    /* Dump the generic media types */

+

+    if (pmtIn->bTemporalCompression) {

+        DbgLog((LOG_TRACE,5,TEXT("Temporally compressed")));

+    } else {

+        DbgLog((LOG_TRACE,5,TEXT("Not temporally compressed")));

+    }

+

+    if (pmtIn->bFixedSizeSamples) {

+        DbgLog((LOG_TRACE,5,TEXT("Sample size %d"),pmtIn->lSampleSize));

+    } else {

+        DbgLog((LOG_TRACE,5,TEXT("Variable size samples")));

+    }

+

+    if (pmtIn->formattype == FORMAT_VideoInfo) {

+

+        VIDEOINFOHEADER *pVideoInfo = (VIDEOINFOHEADER *)pmtIn->pbFormat;

+

+        DisplayRECT(TEXT("Source rectangle"),pVideoInfo->rcSource);

+        DisplayRECT(TEXT("Target rectangle"),pVideoInfo->rcTarget);

+        DisplayBITMAPINFO(HEADER(pmtIn->pbFormat));

+

+    } if (pmtIn->formattype == FORMAT_VideoInfo2) {

+

+        VIDEOINFOHEADER2 *pVideoInfo2 = (VIDEOINFOHEADER2 *)pmtIn->pbFormat;

+

+        DisplayRECT(TEXT("Source rectangle"),pVideoInfo2->rcSource);

+        DisplayRECT(TEXT("Target rectangle"),pVideoInfo2->rcTarget);

+        DbgLog((LOG_TRACE, 5, TEXT("Aspect Ratio: %d:%d"),

+            pVideoInfo2->dwPictAspectRatioX,

+            pVideoInfo2->dwPictAspectRatioY));

+        DisplayBITMAPINFO(&pVideoInfo2->bmiHeader);

+

+    } else if (pmtIn->majortype == MEDIATYPE_Audio) {

+        DbgLog((LOG_TRACE,2,TEXT("     Format type %hs"),

+            GuidNames[pmtIn->formattype]));

+        DbgLog((LOG_TRACE,2,TEXT("     Subtype %hs"),

+            GuidNames[pmtIn->subtype]));

+

+        if ((pmtIn->subtype != MEDIASUBTYPE_MPEG1Packet)

+          && (pmtIn->cbFormat >= sizeof(PCMWAVEFORMAT)))

+        {

+            /* Dump the contents of the WAVEFORMATEX type-specific format structure */

+

+            WAVEFORMATEX *pwfx = (WAVEFORMATEX *) pmtIn->pbFormat;

+            DbgLog((LOG_TRACE,2,TEXT("wFormatTag %u"), pwfx->wFormatTag));

+            DbgLog((LOG_TRACE,2,TEXT("nChannels %u"), pwfx->nChannels));

+            DbgLog((LOG_TRACE,2,TEXT("nSamplesPerSec %lu"), pwfx->nSamplesPerSec));

+            DbgLog((LOG_TRACE,2,TEXT("nAvgBytesPerSec %lu"), pwfx->nAvgBytesPerSec));

+            DbgLog((LOG_TRACE,2,TEXT("nBlockAlign %u"), pwfx->nBlockAlign));

+            DbgLog((LOG_TRACE,2,TEXT("wBitsPerSample %u"), pwfx->wBitsPerSample));

+

+            /* PCM uses a WAVEFORMAT and does not have the extra size field */

+

+            if (pmtIn->cbFormat >= sizeof(WAVEFORMATEX)) {

+                DbgLog((LOG_TRACE,2,TEXT("cbSize %u"), pwfx->cbSize));

+            }

+        } else {

+        }

+

+    } else {

+        DbgLog((LOG_TRACE,2,TEXT("     Format type %hs"),

+            GuidNames[pmtIn->formattype]));

+    }

+}

+

+

+void DisplayBITMAPINFO(const BITMAPINFOHEADER* pbmi)

+{

+    DbgLog((LOG_TRACE,5,TEXT("Size of BITMAPINFO structure %d"),pbmi->biSize));

+    if (pbmi->biCompression < 256) {

+        DbgLog((LOG_TRACE,2,TEXT("%dx%dx%d bit  (%d)"),

+                pbmi->biWidth, pbmi->biHeight,

+                pbmi->biBitCount, pbmi->biCompression));

+    } else {

+        DbgLog((LOG_TRACE,2,TEXT("%dx%dx%d bit '%4.4hs'"),

+                pbmi->biWidth, pbmi->biHeight,

+                pbmi->biBitCount, &pbmi->biCompression));

+    }

+

+    DbgLog((LOG_TRACE,2,TEXT("Image size %d"),pbmi->biSizeImage));

+    DbgLog((LOG_TRACE,5,TEXT("Planes %d"),pbmi->biPlanes));

+    DbgLog((LOG_TRACE,5,TEXT("X Pels per metre %d"),pbmi->biXPelsPerMeter));

+    DbgLog((LOG_TRACE,5,TEXT("Y Pels per metre %d"),pbmi->biYPelsPerMeter));

+    DbgLog((LOG_TRACE,5,TEXT("Colours used %d"),pbmi->biClrUsed));

+}

+

+

+void DisplayRECT(LPCTSTR szLabel, const RECT& rc)

+{

+    DbgLog((LOG_TRACE,5,TEXT("%s (Left %d Top %d Right %d Bottom %d)"),

+            szLabel,

+            rc.left,

+            rc.top,

+            rc.right,

+            rc.bottom));

+}

+

+

+void WINAPI DumpGraph(IFilterGraph *pGraph, DWORD dwLevel)

+{

+    if( !pGraph )

+    {

+        return;

+    }

+

+    IEnumFilters *pFilters;

+

+    DbgLog((LOG_TRACE,dwLevel,TEXT("DumpGraph [%x]"), pGraph));

+

+    if (FAILED(pGraph->EnumFilters(&pFilters))) {

+	DbgLog((LOG_TRACE,dwLevel,TEXT("EnumFilters failed!")));

+    }

+

+    IBaseFilter *pFilter;

+    ULONG	n;

+    while (pFilters->Next(1, &pFilter, &n) == S_OK) {

+	FILTER_INFO	info;

+

+	if (FAILED(pFilter->QueryFilterInfo(&info))) {

+	    DbgLog((LOG_TRACE,dwLevel,TEXT("    Filter [%p]  -- failed QueryFilterInfo"), pFilter));

+	} else {

+	    QueryFilterInfoReleaseGraph(info);

+

+	    // !!! should QueryVendorInfo here!

+	

+	    DbgLog((LOG_TRACE,dwLevel,TEXT("    Filter [%p]  '%ls'"), pFilter, info.achName));

+

+	    IEnumPins *pins;

+

+	    if (FAILED(pFilter->EnumPins(&pins))) {

+		DbgLog((LOG_TRACE,dwLevel,TEXT("EnumPins failed!")));

+	    } else {

+

+		IPin *pPin;

+		while (pins->Next(1, &pPin, &n) == S_OK) {

+		    PIN_INFO	pinInfo;

+

+		    if (FAILED(pPin->QueryPinInfo(&pinInfo))) {

+			DbgLog((LOG_TRACE,dwLevel,TEXT("          Pin [%x]  -- failed QueryPinInfo"), pPin));

+		    } else {

+			QueryPinInfoReleaseFilter(pinInfo);

+

+			IPin *pPinConnected = NULL;

+

+			HRESULT hr = pPin->ConnectedTo(&pPinConnected);

+

+			if (pPinConnected) {

+			    DbgLog((LOG_TRACE,dwLevel,TEXT("          Pin [%p]  '%ls' [%sput]")

+							   TEXT("  Connected to pin [%p]"),

+				    pPin, pinInfo.achName,

+				    pinInfo.dir == PINDIR_INPUT ? TEXT("In") : TEXT("Out"),

+				    pPinConnected));

+

+			    pPinConnected->Release();

+

+			    // perhaps we should really dump the type both ways as a sanity

+			    // check?

+			    if (pinInfo.dir == PINDIR_OUTPUT) {

+				AM_MEDIA_TYPE mt;

+

+				hr = pPin->ConnectionMediaType(&mt);

+

+				if (SUCCEEDED(hr)) {

+				    DisplayType(TEXT("Connection type"), &mt);

+

+				    FreeMediaType(mt);

+				}

+			    }

+			} else {

+			    DbgLog((LOG_TRACE,dwLevel,

+				    TEXT("          Pin [%x]  '%ls' [%sput]"),

+				    pPin, pinInfo.achName,

+				    pinInfo.dir == PINDIR_INPUT ? TEXT("In") : TEXT("Out")));

+

+			}

+		    }

+

+		    pPin->Release();

+

+		}

+

+		pins->Release();

+	    }

+

+	}

+	

+	pFilter->Release();

+    }

+

+    pFilters->Release();

+

+}

+

+#endif

+

+#endif /* PJMEDIA_VIDEO_DEV_HAS_DSHOW */