[Pkg-voip-commits] [ring] 05/18: Imported Upstream version 20160324.5.e4833b2

Alexandre Viau aviau at moszumanska.debian.org
Fri Apr 1 20:02:52 UTC 2016


This is an automated email from the git hooks/post-receive script.

aviau pushed a commit to branch master
in repository ring.

commit 4dd2fd986688d9615fa7da4e6173fe0de13a7edb
Author: aviau <alexandre at alexandreviau.net>
Date:   Fri Apr 1 15:49:09 2016 -0400

    Imported Upstream version 20160324.5.e4833b2
---
 .../src/pjmedia-audiodev/s60_g729_bitstream.h      |  171 +
 .../third_party/BaseClasses/amfilter.cpp           | 5363 ++++++++++++++++++++
 .../third_party/BaseClasses/amfilter.h             | 1587 ++++++
 .../third_party/BaseClasses/amvideo.cpp            |  280 +
 .../third_party/BaseClasses/arithutil.cpp          |  366 ++
 .../third_party/BaseClasses/combase.cpp            |  269 +
 .../third_party/BaseClasses/combase.h              |  305 ++
 .../third_party/BaseClasses/ctlutil.cpp            | 2545 ++++++++++
 .../third_party/BaseClasses/ctlutil.h              |  923 ++++
 .../third_party/BaseClasses/fourcc.h               |  101 +
 .../third_party/BaseClasses/measure.h              |  222 +
 .../third_party/BaseClasses/msgthrd.h              |  120 +
 .../third_party/BaseClasses/mtype.cpp              |  483 ++
 .../third_party/BaseClasses/mtype.h                |   89 +
 .../third_party/BaseClasses/refclock.h             |  184 +
 .../third_party/BaseClasses/reftime.h              |  116 +
 .../third_party/BaseClasses/renbase.cpp            | 2862 +++++++++++
 .../third_party/BaseClasses/renbase.h              |  478 ++
 .../third_party/BaseClasses/seekpt.h               |   30 +
 .../third_party/BaseClasses/streams.h              |  202 +
 .../third_party/BaseClasses/wxdebug.cpp            | 1478 ++++++
 .../third_party/BaseClasses/wxdebug.h              |  359 ++
 .../third_party/BaseClasses/wxlist.cpp             |  896 ++++
 .../third_party/BaseClasses/wxlist.h               |  553 ++
 .../third_party/BaseClasses/wxutil.cpp             |  773 +++
 .../third_party/BaseClasses/wxutil.h               |  532 ++
 .../third_party/g7221/common/basic_op.c            | 1835 +++++++
 .../third_party/g7221/common/basic_op.h            |  117 +
 .../third_party/g7221/common/basic_op_i.h          |  730 +++
 .../third_party/g7221/common/common.c              |  461 ++
 .../third_party/g7221/common/config.h              |   27 +
 .../third_party/g7221/common/count.h               |   28 +
 .../third_party/g7221/common/defs.h                |  205 +
 .../third_party/g7221/common/huff_def.h            |   53 +
 .../third_party/g7221/common/huff_tab.c            |  528 ++
 .../third_party/g7221/common/huff_tab.h            |   42 +
 .../third_party/g7221/common/tables.c              |  298 ++
 .../third_party/g7221/common/tables.h              |   47 +
 .../third_party/g7221/common/typedef.h             |   32 +
 .../third_party/g7221/decode/coef2sam.c            |  180 +
 .../third_party/g7221/decode/dct4_s.c              |  504 ++
 .../third_party/g7221/decode/dct4_s.h              |  856 ++++
 .../third_party/g7221/decode/decoder.c             | 1113 ++++
 .../third_party/g7221/encode/dct4_a.c              |  367 ++
 .../third_party/g7221/encode/dct4_a.h              |  728 +++
 .../third_party/g7221/encode/encoder.c             | 1125 ++++
 .../third_party/g7221/encode/sam2coef.c            |  271 +
 .../third_party/milenage/milenage.c                |  284 ++
 .../third_party/milenage/milenage.h                |   35 +
 .../third_party/milenage/rijndael.c                |  444 ++
 .../third_party/milenage/rijndael.h                |   26 +
 51 files changed, 31623 insertions(+)

diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/pjmedia/src/pjmedia-audiodev/s60_g729_bitstream.h b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/pjmedia/src/pjmedia-audiodev/s60_g729_bitstream.h
new file mode 100644
index 0000000..ae13bb1
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/pjmedia/src/pjmedia-audiodev/s60_g729_bitstream.h
@@ -0,0 +1,171 @@
+#ifndef __BITSTREAM_H_
+#define __BITSTREAM_H_
+
+#define KPackedFrameLen 10
+#define KUnpackedFrameLen 22
+
+// Below values are taken from the APS design document
+const TUint8 KG729FullPayloadBits[] = { 8, 10, 8, 1, 13, 4, 7, 5, 13, 4, 7 };
+const TUint  KNumFullFrameParams = 11;
+const TUint8 KG729SIDPayloadBits[] = { 1, 5, 4, 5 };
+const TUint  KNumSIDFrameParams = 4;
+
+/*! 
+  @class TBitStream
+  
+  @discussion Provides compression from 16-bit-word-aligned G.729 audio frames
+  (used in S60 G.729 DSP codec) to 8-bit stream, and vice versa.
+  */
+class TBitStream
+  {        
+public:
+    /*!
+      @function TBitStream
+      
+      @discussion Constructor
+      */   
+    TBitStream():iDes(iData,KUnpackedFrameLen){}
+    /*!
+      @function CompressG729Frame
+      
+      @discussion Compress either a 22-byte G.729 full rate frame to 10 bytes
+      or a 8-byte G.729 Annex.B SID frame to 2 bytes.
+      @param aSrc Reference to the uncompressed source frame data
+      @param aIsSIDFrame True if the source is a SID frame
+      @result a reference to the compressed frame
+      */
+    const TDesC8& CompressG729Frame( const TDesC8& aSrc, TBool aIsSIDFrame = EFalse );
+    
+    /*!
+      @function ExpandG729Frame
+            
+      @discussion Expand a 10-byte G.729 full rate frame to 22 bytes
+      or a 2-byte G.729 Annex.B SID frame to 8(22) bytes.
+      @param aSrc Reference to the compressed source frame data
+      @param aIsSIDFrame True if the source is a SID frame
+      @result a reference to a descriptor representing the uncompressed frame.
+      Note that SID frames are zero-padded to 22 bytes as well.
+      */
+    const TDesC8& ExpandG729Frame( const TDesC8& aSrc, TBool aIsSIDFrame = EFalse );
+
+private:
+    void Compress( TUint8 aValue, TUint8 aNumOfBits );
+    void Expand( const TUint8* aSrc, TInt aDstIdx, TUint8 aNumOfBits );
+
+private:
+    TUint8      iData[KUnpackedFrameLen];
+    TPtr8       iDes;
+    TInt        iIdx;
+    TInt        iBitOffset;
+    };
+    
+
+const TDesC8& TBitStream::CompressG729Frame( const TDesC8& aSrc, TBool aIsSIDFrame )
+    {
+    // reset data
+    iDes.FillZ(iDes.MaxLength());
+    iIdx = iBitOffset = 0;
+    
+    TInt numParams = (aIsSIDFrame) ? KNumSIDFrameParams : KNumFullFrameParams;
+    const TUint8* p = const_cast<TUint8*>(aSrc.Ptr());
+    
+    for(TInt i = 0, pIdx = 0; i < numParams; i++, pIdx += 2) 
+        {
+        TUint8 paramBits = (aIsSIDFrame) ? KG729SIDPayloadBits[i] : KG729FullPayloadBits[i];        
+        if(paramBits > 8)
+            {
+            Compress(p[pIdx+1], paramBits - 8); // msb
+            paramBits = 8;
+            }            
+        Compress(p[pIdx], paramBits); // lsb    
+        }
+
+    if( iBitOffset )
+        iIdx++;
+        
+    iDes.SetLength(iIdx);
+    return iDes;
+    }
+
+ 
+const TDesC8& TBitStream::ExpandG729Frame( const TDesC8& aSrc, TBool aIsSIDFrame )
+    {
+    // reset data
+    iDes.FillZ(iDes.MaxLength());
+    iIdx = iBitOffset = 0;
+    
+    TInt numParams = (aIsSIDFrame) ? KNumSIDFrameParams : KNumFullFrameParams;
+    const TUint8* p = const_cast<TUint8*>(aSrc.Ptr());
+    
+    for(TInt i = 0, dIdx = 0; i < numParams; i++, dIdx += 2) 
+        {
+        TUint8 paramBits = (aIsSIDFrame) ? KG729SIDPayloadBits[i] : KG729FullPayloadBits[i];
+        if(paramBits > 8)
+          {
+          Expand(p, dIdx+1, paramBits - 8); // msb
+          paramBits = 8;
+          }    
+        Expand(p, dIdx, paramBits); // lsb 
+        }
+        
+    iDes.SetLength(KUnpackedFrameLen);
+    return iDes;
+    }
+
+
+void TBitStream::Compress( TUint8 aValue, TUint8 aNumOfBits )
+  {
+    // clear bits that will be discarded
+    aValue &= (0xff >> (8 - aNumOfBits));
+    
+    // calculate required bitwise left shift
+    TInt shl = 8 - (iBitOffset + aNumOfBits);
+    
+    if (shl == 0) // no shift required
+        { 
+        iData[iIdx++] |= aValue;
+        iBitOffset = 0;
+        }
+    else if (shl > 0) // bits fit into current byte
+        { 
+        iData[iIdx] |= (aValue << shl);
+        iBitOffset += aNumOfBits;
+        }        
+    else        
+        { 
+        iBitOffset = -shl;
+        iData[iIdx] |= (aValue >> iBitOffset); // right shift
+        iData[++iIdx] |= (aValue << (8-iBitOffset)); // push remaining bits to next byte
+        }
+  }
+    
+
+void TBitStream::Expand( const TUint8* aSrc, TInt aDstIdx, TUint8 aNumOfBits )
+  {    
+    TUint8 aValue = aSrc[iIdx] & (0xff >> iBitOffset);
+       
+    // calculate required bitwise right shift
+    TInt shr = 8 - (iBitOffset + aNumOfBits);
+    
+    if (shr == 0) // no shift required
+        { 
+        iData[aDstIdx] = aValue;
+        iIdx++;
+        iBitOffset = 0;
+        }
+    else if (shr > 0) // right shift
+        { 
+        iData[aDstIdx] = (aValue >> shr);
+        iBitOffset += aNumOfBits;
+        }        
+    else // shift left and take remaining bits from the next src byte
+        {
+        iBitOffset = -shr;
+        iData[aDstIdx] = aValue << iBitOffset;                
+        iData[aDstIdx] |= aSrc[++iIdx] >> (8 - iBitOffset);
+        }
+  }
+
+#endif // __BITSTREAM_H_
+    
+// eof
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/amfilter.cpp b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/amfilter.cpp
new file mode 100644
index 0000000..282c35d
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/amfilter.cpp
@@ -0,0 +1,5363 @@
+//------------------------------------------------------------------------------
+// File: AMFilter.cpp
+//
+// Desc: DirectShow base classes - implements class hierarchy for streams
+//       architecture.
+//
+// Copyright (c) 1992-2001 Microsoft Corporation.  All rights reserved.
+//------------------------------------------------------------------------------
+
+
+//=====================================================================
+//=====================================================================
+// The following classes are declared in this header:
+//
+//
+// CBaseMediaFilter            Basic IMediaFilter support (abstract class)
+// CBaseFilter                 Support for IBaseFilter (incl. IMediaFilter)
+// CEnumPins                   Enumerate input and output pins
+// CEnumMediaTypes             Enumerate the preferred pin formats
+// CBasePin                    Abstract base class for IPin interface
+//    CBaseOutputPin           Adds data provider member functions
+//    CBaseInputPin            Implements IMemInputPin interface
+// CMediaSample                Basic transport unit for IMemInputPin
+// CBaseAllocator              General list guff for most allocators
+//    CMemAllocator            Implements memory buffer allocation
+//
+//=====================================================================
+//=====================================================================
+
+#include <pjmedia-videodev/config.h>
+
+#if defined(PJMEDIA_VIDEO_DEV_HAS_DSHOW) && PJMEDIA_VIDEO_DEV_HAS_DSHOW != 0
+
+#include <streams.h>
+#include <strsafe.h>
+
+#ifdef DXMPERF
+#include "dxmperf.h"
+#endif // DXMPERF
+
+
+//=====================================================================
+// Helpers
+//=====================================================================
+STDAPI CreateMemoryAllocator(__deref_out IMemAllocator **ppAllocator)
+{
+    return CoCreateInstance(CLSID_MemoryAllocator,
+                            0,
+                            CLSCTX_INPROC_SERVER,
+                            IID_IMemAllocator,
+                            (void **)ppAllocator);
+}
+
+//  Put this one here rather than in ctlutil.cpp to avoid linking
+//  anything brought in by ctlutil.cpp
+STDAPI CreatePosPassThru(
+    __in_opt LPUNKNOWN pAgg,
+    BOOL bRenderer,
+    IPin *pPin,
+    __deref_out IUnknown **ppPassThru
+)
+{
+    *ppPassThru = NULL;
+    IUnknown *pUnkSeek;
+    HRESULT hr = CoCreateInstance(CLSID_SeekingPassThru,
+                                  pAgg,
+                                  CLSCTX_INPROC_SERVER,
+                                  IID_IUnknown,
+                                  (void **)&pUnkSeek
+                                 );
+    if (FAILED(hr)) {
+        return hr;
+    }
+
+    ISeekingPassThru *pPassThru;
+    hr = pUnkSeek->QueryInterface(IID_ISeekingPassThru, (void**)&pPassThru);
+    if (FAILED(hr)) {
+        pUnkSeek->Release();
+        return hr;
+    }
+    hr = pPassThru->Init(bRenderer, pPin);
+    pPassThru->Release();
+    if (FAILED(hr)) {
+        pUnkSeek->Release();
+        return hr;
+    }
+    *ppPassThru = pUnkSeek;
+    return S_OK;
+}
+
+
+
+#define CONNECT_TRACE_LEVEL 3
+
+//=====================================================================
+//=====================================================================
+// Implements CBaseMediaFilter
+//=====================================================================
+//=====================================================================
+
+
+/* Constructor */
+
+CBaseMediaFilter::CBaseMediaFilter(__in_opt LPCTSTR pName,
+                   __inout_opt LPUNKNOWN    pUnk,
+                   __in CCritSec *pLock,
+                   REFCLSID clsid) :
+    CUnknown(pName, pUnk),
+    m_pLock(pLock),
+    m_clsid(clsid),
+    m_State(State_Stopped),
+    m_pClock(NULL)
+{
+}
+
+
+/* Destructor */
+
+CBaseMediaFilter::~CBaseMediaFilter()
+{
+    // must be stopped, but can't call Stop here since
+    // our critsec has been destroyed.
+
+    /* Release any clock we were using */
+
+    if (m_pClock) {
+        m_pClock->Release();
+        m_pClock = NULL;
+    }
+}
+
+
+/* Override this to say what interfaces we support and where */
+
+STDMETHODIMP
+CBaseMediaFilter::NonDelegatingQueryInterface(
+    REFIID riid,
+    __deref_out void ** ppv)
+{
+    if (riid == IID_IMediaFilter) {
+        return GetInterface((IMediaFilter *) this, ppv);
+    } else if (riid == IID_IPersist) {
+        return GetInterface((IPersist *) this, ppv);
+    } else {
+        return CUnknown::NonDelegatingQueryInterface(riid, ppv);
+    }
+}
+
+/* Return the filter's clsid */
+STDMETHODIMP
+CBaseMediaFilter::GetClassID(__out CLSID *pClsID)
+{
+    CheckPointer(pClsID,E_POINTER);
+    ValidateReadWritePtr(pClsID,sizeof(CLSID));
+    *pClsID = m_clsid;
+    return NOERROR;
+}
+
+/* Override this if your state changes are not done synchronously */
+
+STDMETHODIMP
+CBaseMediaFilter::GetState(DWORD dwMSecs, __out FILTER_STATE *State)
+{
+    UNREFERENCED_PARAMETER(dwMSecs);
+    CheckPointer(State,E_POINTER);
+    ValidateReadWritePtr(State,sizeof(FILTER_STATE));
+
+    *State = m_State;
+    return S_OK;
+}
+
+
+/* Set the clock we will use for synchronisation */
+
+STDMETHODIMP
+CBaseMediaFilter::SetSyncSource(__inout_opt IReferenceClock *pClock)
+{
+    CAutoLock cObjectLock(m_pLock);
+
+    // Ensure the new one does not go away - even if the same as the old
+    if (pClock) {
+        pClock->AddRef();
+    }
+
+    // if we have a clock, release it
+    if (m_pClock) {
+        m_pClock->Release();
+    }
+
+    // Set the new reference clock (might be NULL)
+    // Should we query it to ensure it is a clock?  Consider for a debug build.
+    m_pClock = pClock;
+
+    return NOERROR;
+}
+
+/* Return the clock we are using for synchronisation */
+STDMETHODIMP
+CBaseMediaFilter::GetSyncSource(__deref_out_opt IReferenceClock **pClock)
+{
+    CheckPointer(pClock,E_POINTER);
+    ValidateReadWritePtr(pClock,sizeof(IReferenceClock *));
+    CAutoLock cObjectLock(m_pLock);
+
+    if (m_pClock) {
+        // returning an interface... addref it...
+        m_pClock->AddRef();
+    }
+    *pClock = (IReferenceClock*)m_pClock;
+    return NOERROR;
+}
+
+
+/* Put the filter into a stopped state */
+
+STDMETHODIMP
+CBaseMediaFilter::Stop()
+{
+    CAutoLock cObjectLock(m_pLock);
+
+    m_State = State_Stopped;
+    return S_OK;
+}
+
+
+/* Put the filter into a paused state */
+
+STDMETHODIMP
+CBaseMediaFilter::Pause()
+{
+    CAutoLock cObjectLock(m_pLock);
+
+    m_State = State_Paused;
+    return S_OK;
+}
+
+
+// Put the filter into a running state.
+
+// The time parameter is the offset to be added to the samples'
+// stream time to get the reference time at which they should be presented.
+//
+// you can either add these two and compare it against the reference clock,
+// or you can call CBaseMediaFilter::StreamTime and compare that against
+// the sample timestamp.
+
+STDMETHODIMP
+CBaseMediaFilter::Run(REFERENCE_TIME tStart)
+{
+    CAutoLock cObjectLock(m_pLock);
+
+    // remember the stream time offset
+    m_tStart = tStart;
+
+    if (m_State == State_Stopped){
+        HRESULT hr = Pause();
+
+        if (FAILED(hr)) {
+            return hr;
+        }
+    }
+    m_State = State_Running;
+    return S_OK;
+}
+
+
+//
+// return the current stream time - samples with start timestamps of this
+// time or before should be rendered by now
+HRESULT
+CBaseMediaFilter::StreamTime(CRefTime& rtStream)
+{
+    // Caller must lock for synchronization
+    // We can't grab the filter lock because we want to be able to call
+    // this from worker threads without deadlocking
+
+    if (m_pClock == NULL) {
+        return VFW_E_NO_CLOCK;
+    }
+
+    // get the current reference time
+    HRESULT hr = m_pClock->GetTime((REFERENCE_TIME*)&rtStream);
+    if (FAILED(hr)) {
+        return hr;
+    }
+
+    // subtract the stream offset to get stream time
+    rtStream -= m_tStart;
+
+    return S_OK;
+}
+
+
+//=====================================================================
+//=====================================================================
+// Implements CBaseFilter
+//=====================================================================
+//=====================================================================
+
+
+/* Override this to say what interfaces we support and where */
+
+STDMETHODIMP CBaseFilter::NonDelegatingQueryInterface(REFIID riid,
+                                                      __deref_out void **ppv)
+{
+    /* Do we have this interface */
+
+    if (riid == IID_IBaseFilter) {
+        return GetInterface((IBaseFilter *) this, ppv);
+    } else if (riid == IID_IMediaFilter) {
+        return GetInterface((IMediaFilter *) this, ppv);
+    } else if (riid == IID_IPersist) {
+        return GetInterface((IPersist *) this, ppv);
+    } else if (riid == IID_IAMovieSetup) {
+        return GetInterface((IAMovieSetup *) this, ppv);
+    } else {
+        return CUnknown::NonDelegatingQueryInterface(riid, ppv);
+    }
+}
+
+#ifdef DEBUG
+STDMETHODIMP_(ULONG) CBaseFilter::NonDelegatingRelease()
+{
+    if (m_cRef == 1) {
+        KASSERT(m_pGraph == NULL);
+    }
+    return CUnknown::NonDelegatingRelease();
+}
+#endif
+
+
+/* Constructor */
+
+CBaseFilter::CBaseFilter(__in_opt LPCTSTR pName,
+             __inout_opt LPUNKNOWN  pUnk,
+             __in CCritSec   *pLock,
+             REFCLSID   clsid) :
+    CUnknown( pName, pUnk ),
+    m_pLock(pLock),
+    m_clsid(clsid),
+    m_State(State_Stopped),
+    m_pClock(NULL),
+    m_pGraph(NULL),
+    m_pSink(NULL),
+    m_pName(NULL),
+    m_PinVersion(1)
+{
+#ifdef DXMPERF
+    PERFLOG_CTOR( pName ? pName : L"CBaseFilter", (IBaseFilter *) this );
+#endif // DXMPERF
+
+    ASSERT(pLock != NULL);
+}
+
+/* Passes in a redundant HRESULT argument */
+
+CBaseFilter::CBaseFilter(__in_opt LPCTSTR pName,
+                         __in_opt LPUNKNOWN  pUnk,
+                         __in CCritSec  *pLock,
+                         REFCLSID   clsid,
+                         __inout HRESULT   *phr) :
+    CUnknown( pName, pUnk ),
+    m_pLock(pLock),
+    m_clsid(clsid),
+    m_State(State_Stopped),
+    m_pClock(NULL),
+    m_pGraph(NULL),
+    m_pSink(NULL),
+    m_pName(NULL),
+    m_PinVersion(1)
+{
+#ifdef DXMPERF
+    PERFLOG_CTOR( pName ? pName : L"CBaseFilter", (IBaseFilter *) this );
+#endif // DXMPERF
+
+    ASSERT(pLock != NULL);
+    UNREFERENCED_PARAMETER(phr);
+}
+
+#ifdef UNICODE
+CBaseFilter::CBaseFilter(__in_opt LPCSTR pName,
+             __in_opt LPUNKNOWN  pUnk,
+             __in CCritSec   *pLock,
+             REFCLSID   clsid) :
+    CUnknown( pName, pUnk ),
+    m_pLock(pLock),
+    m_clsid(clsid),
+    m_State(State_Stopped),
+    m_pClock(NULL),
+    m_pGraph(NULL),
+    m_pSink(NULL),
+    m_pName(NULL),
+    m_PinVersion(1)
+{
+#ifdef DXMPERF
+    PERFLOG_CTOR( L"CBaseFilter", (IBaseFilter *) this );
+#endif // DXMPERF
+
+    ASSERT(pLock != NULL);
+}
+CBaseFilter::CBaseFilter(__in_opt LPCSTR pName,
+                         __in_opt LPUNKNOWN  pUnk,
+                         __in CCritSec  *pLock,
+                         REFCLSID   clsid,
+                         __inout HRESULT   *phr) :
+    CUnknown( pName, pUnk ),
+    m_pLock(pLock),
+    m_clsid(clsid),
+    m_State(State_Stopped),
+    m_pClock(NULL),
+    m_pGraph(NULL),
+    m_pSink(NULL),
+    m_pName(NULL),
+    m_PinVersion(1)
+{
+#ifdef DXMPERF
+    PERFLOG_CTOR( L"CBaseFilter", (IBaseFilter *) this );
+#endif // DXMPERF
+
+    ASSERT(pLock != NULL);
+    UNREFERENCED_PARAMETER(phr);
+}
+#endif
+
+/* Destructor */
+
+CBaseFilter::~CBaseFilter()
+{
+#ifdef DXMPERF
+    PERFLOG_DTOR( L"CBaseFilter", (IBaseFilter *) this );
+#endif // DXMPERF
+
+    // NOTE we do NOT hold references on the filtergraph for m_pGraph or m_pSink
+    // When we did we had the circular reference problem.  Nothing would go away.
+
+    delete[] m_pName;
+
+    // must be stopped, but can't call Stop here since
+    // our critsec has been destroyed.
+
+    /* Release any clock we were using */
+    if (m_pClock) {
+        m_pClock->Release();
+        m_pClock = NULL;
+    }
+}
+
+/* Return the filter's clsid */
+STDMETHODIMP
+CBaseFilter::GetClassID(__out CLSID *pClsID)
+{
+    CheckPointer(pClsID,E_POINTER);
+    ValidateReadWritePtr(pClsID,sizeof(CLSID));
+    *pClsID = m_clsid;
+    return NOERROR;
+}
+
+/* Override this if your state changes are not done synchronously */
+STDMETHODIMP
+CBaseFilter::GetState(DWORD dwMSecs, __out FILTER_STATE *State)
+{
+    UNREFERENCED_PARAMETER(dwMSecs);
+    CheckPointer(State,E_POINTER);
+    ValidateReadWritePtr(State,sizeof(FILTER_STATE));
+
+    *State = m_State;
+    return S_OK;
+}
+
+
+/* Set the clock we will use for synchronisation */
+
+STDMETHODIMP
+CBaseFilter::SetSyncSource(__in_opt IReferenceClock *pClock)
+{
+    CAutoLock cObjectLock(m_pLock);
+
+    // Ensure the new one does not go away - even if the same as the old
+    if (pClock) {
+        pClock->AddRef();
+    }
+
+    // if we have a clock, release it
+    if (m_pClock) {
+        m_pClock->Release();
+    }
+
+    // Set the new reference clock (might be NULL)
+    // Should we query it to ensure it is a clock?  Consider for a debug build.
+    m_pClock = pClock;
+
+    return NOERROR;
+}
+
+/* Return the clock we are using for synchronisation */
+STDMETHODIMP
+CBaseFilter::GetSyncSource(__deref_out_opt IReferenceClock **pClock)
+{
+    CheckPointer(pClock,E_POINTER);
+    ValidateReadWritePtr(pClock,sizeof(IReferenceClock *));
+    CAutoLock cObjectLock(m_pLock);
+
+    if (m_pClock) {
+        // returning an interface... addref it...
+        m_pClock->AddRef();
+    }
+    *pClock = (IReferenceClock*)m_pClock;
+    return NOERROR;
+}
+
+
+
+// override CBaseMediaFilter Stop method, to deactivate any pins this
+// filter has.
+STDMETHODIMP
+CBaseFilter::Stop()
+{
+    CAutoLock cObjectLock(m_pLock);
+    HRESULT hr = NOERROR;
+
+    // notify all pins of the state change
+    if (m_State != State_Stopped) {
+        int cPins = GetPinCount();
+        for (int c = 0; c < cPins; c++) {
+
+            CBasePin *pPin = GetPin(c);
+            if (NULL == pPin) {
+                break;
+            }
+
+            // Disconnected pins are not activated - this saves pins worrying
+            // about this state themselves. We ignore the return code to make
+            // sure everyone is inactivated regardless. The base input pin
+            // class can return an error if it has no allocator but Stop can
+            // be used to resync the graph state after something has gone bad
+
+            if (pPin->IsConnected()) {
+                HRESULT hrTmp = pPin->Inactive();
+                if (FAILED(hrTmp) && SUCCEEDED(hr)) {
+                    hr = hrTmp;
+                }
+            }
+        }
+    }
+
+#ifdef DXMPERF
+    PERFLOG_STOP( m_pName ? m_pName : L"CBaseFilter", (IBaseFilter *) this, m_State );
+#endif // DXMPERF
+
+    m_State = State_Stopped;
+    return hr;
+}
+
+
+// override CBaseMediaFilter Pause method to activate any pins
+// this filter has (also called from Run)
+
+STDMETHODIMP
+CBaseFilter::Pause()
+{
+    CAutoLock cObjectLock(m_pLock);
+
+    // notify all pins of the change to active state
+    if (m_State == State_Stopped) {
+        int cPins = GetPinCount();
+        for (int c = 0; c < cPins; c++) {
+
+            CBasePin *pPin = GetPin(c);
+            if (NULL == pPin) {
+                break;
+            }
+
+            // Disconnected pins are not activated - this saves pins
+            // worrying about this state themselves
+
+            if (pPin->IsConnected()) {
+                HRESULT hr = pPin->Active();
+                if (FAILED(hr)) {
+                    return hr;
+                }
+            }
+        }
+    }
+
+
+#ifdef DXMPERF
+    PERFLOG_PAUSE( m_pName ? m_pName : L"CBaseFilter", (IBaseFilter *) this, m_State );
+#endif // DXMPERF
+
+    m_State = State_Paused;
+    return S_OK;
+}
+
+// Put the filter into a running state.
+
+// The time parameter is the offset to be added to the samples'
+// stream time to get the reference time at which they should be presented.
+//
+// you can either add these two and compare it against the reference clock,
+// or you can call CBaseFilter::StreamTime and compare that against
+// the sample timestamp.
+
+STDMETHODIMP
+CBaseFilter::Run(REFERENCE_TIME tStart)
+{
+    CAutoLock cObjectLock(m_pLock);
+
+    // remember the stream time offset
+    m_tStart = tStart;
+
+    if (m_State == State_Stopped){
+    HRESULT hr = Pause();
+
+    if (FAILED(hr)) {
+        return hr;
+    }
+    }
+    // notify all pins of the change to active state
+    if (m_State != State_Running) {
+        int cPins = GetPinCount();
+        for (int c = 0; c < cPins; c++) {
+
+            CBasePin *pPin = GetPin(c);
+            if (NULL == pPin) {
+                break;
+            }
+
+            // Disconnected pins are not activated - this saves pins
+            // worrying about this state themselves
+
+            if (pPin->IsConnected()) {
+                HRESULT hr = pPin->Run(tStart);
+                if (FAILED(hr)) {
+                    return hr;
+                }
+            }
+        }
+    }
+
+#ifdef DXMPERF
+    PERFLOG_RUN( m_pName ? m_pName : L"CBaseFilter", (IBaseFilter *) this, tStart, m_State );
+#endif // DXMPERF
+
+    m_State = State_Running;
+    return S_OK;
+}
+
+//
+// return the current stream time - samples with start timestamps of this
+// time or before should be rendered by now
+HRESULT
+CBaseFilter::StreamTime(CRefTime& rtStream)
+{
+    // Caller must lock for synchronization
+    // We can't grab the filter lock because we want to be able to call
+    // this from worker threads without deadlocking
+
+    if (m_pClock == NULL) {
+        return VFW_E_NO_CLOCK;
+    }
+
+    // get the current reference time
+    HRESULT hr = m_pClock->GetTime((REFERENCE_TIME*)&rtStream);
+    if (FAILED(hr)) {
+        return hr;
+    }
+
+    // subtract the stream offset to get stream time
+    rtStream -= m_tStart;
+
+    return S_OK;
+}
+
+
+/* Create an enumerator for the pins attached to this filter */
+
+STDMETHODIMP
+CBaseFilter::EnumPins(__deref_out IEnumPins **ppEnum)
+{
+    CheckPointer(ppEnum,E_POINTER);
+    ValidateReadWritePtr(ppEnum,sizeof(IEnumPins *));
+
+    /* Create a new ref counted enumerator */
+
+    *ppEnum = new CEnumPins(this,
+                        NULL);
+
+    return *ppEnum == NULL ? E_OUTOFMEMORY : NOERROR;
+}
+
+
+// default behaviour of FindPin is to assume pins are named
+// by their pin names
+STDMETHODIMP
+CBaseFilter::FindPin(
+    LPCWSTR Id,
+    __deref_out IPin ** ppPin
+)
+{
+    CheckPointer(ppPin,E_POINTER);
+    ValidateReadWritePtr(ppPin,sizeof(IPin *));
+
+    //  We're going to search the pin list so maintain integrity
+    CAutoLock lck(m_pLock);
+    int iCount = GetPinCount();
+    for (int i = 0; i < iCount; i++) {
+        CBasePin *pPin = GetPin(i);
+        if (NULL == pPin) {
+            break;
+        }
+
+        if (0 == lstrcmpW(pPin->Name(), Id)) {
+            //  Found one that matches
+            //
+            //  AddRef() and return it
+            *ppPin = pPin;
+            pPin->AddRef();
+            return S_OK;
+        }
+    }
+    *ppPin = NULL;
+    return VFW_E_NOT_FOUND;
+}
+
+/* Return information about this filter */
+
+STDMETHODIMP
+CBaseFilter::QueryFilterInfo(__out FILTER_INFO * pInfo)
+{
+    CheckPointer(pInfo,E_POINTER);
+    ValidateReadWritePtr(pInfo,sizeof(FILTER_INFO));
+
+    if (m_pName) {
+        (void)StringCchCopyW(pInfo->achName, NUMELMS(pInfo->achName), m_pName);
+    } else {
+        pInfo->achName[0] = L'\0';
+    }
+    pInfo->pGraph = m_pGraph;
+    if (m_pGraph)
+        m_pGraph->AddRef();
+    return NOERROR;
+}
+
+
+/* Provide the filter with a filter graph */
+
+STDMETHODIMP
+CBaseFilter::JoinFilterGraph(
+    __inout_opt IFilterGraph * pGraph,
+    __in_opt LPCWSTR pName)
+{
+    CAutoLock cObjectLock(m_pLock);
+
+    // NOTE: we no longer hold references on the graph (m_pGraph, m_pSink)
+
+    m_pGraph = pGraph;
+    if (m_pGraph) {
+        HRESULT hr = m_pGraph->QueryInterface(IID_IMediaEventSink,
+                        (void**) &m_pSink);
+        if (FAILED(hr)) {
+            ASSERT(m_pSink == NULL);
+        }
+        else m_pSink->Release();        // we do NOT keep a reference on it.
+    } else {
+        // if graph pointer is null, then we should
+        // also release the IMediaEventSink on the same object - we don't
+        // refcount it, so just set it to null
+        m_pSink = NULL;
+    }
+
+
+    if (m_pName) {
+        delete[] m_pName;
+        m_pName = NULL;
+    }
+
+    if (pName) {
+        size_t namelen;
+        HRESULT hr = StringCchLengthW(pName, STRSAFE_MAX_CCH, &namelen);
+        if (FAILED(hr)) {
+            return hr;
+        }
+        m_pName = new WCHAR[namelen + 1];
+        if (m_pName) {
+            (void)StringCchCopyW(m_pName, namelen + 1, pName);
+        } else {
+            return E_OUTOFMEMORY;
+        }
+    }
+
+#ifdef DXMPERF
+    PERFLOG_JOINGRAPH( m_pName ? m_pName : L"CBaseFilter",(IBaseFilter *) this, pGraph );
+#endif // DXMPERF
+
+    return NOERROR;
+}
+
+
+// return a Vendor information string. Optional - may return E_NOTIMPL.
+// memory returned should be freed using CoTaskMemFree
+// default implementation returns E_NOTIMPL
+STDMETHODIMP
+CBaseFilter::QueryVendorInfo(
+    __deref_out LPWSTR* pVendorInfo)
+{
+    UNREFERENCED_PARAMETER(pVendorInfo);
+    return E_NOTIMPL;
+}
+
+
+// send an event notification to the filter graph if we know about it.
+// returns S_OK if delivered, S_FALSE if the filter graph does not sink
+// events, or an error otherwise.
+HRESULT
+CBaseFilter::NotifyEvent(
+    long EventCode,
+    LONG_PTR EventParam1,
+    LONG_PTR EventParam2)
+{
+    // Snapshot so we don't have to lock up
+    IMediaEventSink *pSink = m_pSink;
+    if (pSink) {
+        if (EC_COMPLETE == EventCode) {
+            EventParam2 = (LONG_PTR)(IBaseFilter*)this;
+        }
+
+        return pSink->Notify(EventCode, EventParam1, EventParam2);
+    } else {
+        return E_NOTIMPL;
+    }
+}
+
+// Request reconnect
+// pPin is the pin to reconnect
+// pmt is the type to reconnect with - can be NULL
+// Calls ReconnectEx on the filter graph
+HRESULT
+CBaseFilter::ReconnectPin(
+    IPin *pPin,
+    __in_opt AM_MEDIA_TYPE const *pmt
+)
+{
+    IFilterGraph2 *pGraph2;
+    if (m_pGraph != NULL) {
+        HRESULT hr = m_pGraph->QueryInterface(IID_IFilterGraph2, (void **)&pGraph2);
+        if (SUCCEEDED(hr)) {
+            hr = pGraph2->ReconnectEx(pPin, pmt);
+            pGraph2->Release();
+            return hr;
+        } else {
+            return m_pGraph->Reconnect(pPin);
+        }
+    } else {
+        return E_NOINTERFACE;
+    }
+}
+
+
+
+/* This is the same idea as the media type version does for type enumeration
+   on pins but for the list of pins available. So if the list of pins you
+   provide changes dynamically then either override this virtual function
+   to provide the version number, or more simply call IncrementPinVersion */
+
+LONG CBaseFilter::GetPinVersion()
+{
+    return m_PinVersion;
+}
+
+
+/* Increment the current pin version cookie */
+
+void CBaseFilter::IncrementPinVersion()
+{
+    InterlockedIncrement(&m_PinVersion);
+}
+
+/* register filter */
+
+STDMETHODIMP CBaseFilter::Register()
+{
+    // get setup data, if it exists
+    //
+    LPAMOVIESETUP_FILTER psetupdata = GetSetupData();
+
+    // check we've got data
+    //
+    if( NULL == psetupdata ) return S_FALSE;
+
+    // init is ref counted so call just in case
+    // we're being called cold.
+    //
+    HRESULT hr = CoInitialize( (LPVOID)NULL );
+    ASSERT( SUCCEEDED(hr) );
+
+    // get hold of IFilterMapper
+    //
+    IFilterMapper *pIFM;
+    hr = CoCreateInstance( CLSID_FilterMapper
+                             , NULL
+                             , CLSCTX_INPROC_SERVER
+                             , IID_IFilterMapper
+                             , (void **)&pIFM       );
+    if( SUCCEEDED(hr) )
+    {
+        hr = AMovieSetupRegisterFilter( psetupdata, pIFM, TRUE );
+        pIFM->Release();
+    }
+
+    // and clear up
+    //
+    CoFreeUnusedLibraries();
+    CoUninitialize();
+
+    return NOERROR;
+}
+
+
+/* unregister filter */
+
+STDMETHODIMP CBaseFilter::Unregister()
+{
+    // get setup data, if it exists
+    //
+    LPAMOVIESETUP_FILTER psetupdata = GetSetupData();
+
+    // check we've got data
+    //
+    if( NULL == psetupdata ) return S_FALSE;
+
+    // OLE init is ref counted so call
+    // just in case we're being called cold.
+    //
+    HRESULT hr = CoInitialize( (LPVOID)NULL );
+    ASSERT( SUCCEEDED(hr) );
+
+    // get hold of IFilterMapper
+    //
+    IFilterMapper *pIFM;
+    hr = CoCreateInstance( CLSID_FilterMapper
+                             , NULL
+                             , CLSCTX_INPROC_SERVER
+                             , IID_IFilterMapper
+                             , (void **)&pIFM       );
+    if( SUCCEEDED(hr) )
+    {
+        hr = AMovieSetupRegisterFilter( psetupdata, pIFM, FALSE );
+
+        // release interface
+        //
+        pIFM->Release();
+    }
+
+    // clear up
+    //
+    CoFreeUnusedLibraries();
+    CoUninitialize();
+
+    // handle one acceptable "error" - that
+    // of filter not being registered!
+    // (couldn't find a suitable #define'd
+    // name for the error!)
+    //
+    if( 0x80070002 == hr)
+      return NOERROR;
+    else
+      return hr;
+}
+
+
+//=====================================================================
+//=====================================================================
+// Implements CEnumPins
+//=====================================================================
+//=====================================================================
+
+
+CEnumPins::CEnumPins(__in CBaseFilter *pFilter,
+                     __in_opt CEnumPins *pEnumPins) :
+    m_Position(0),
+    m_PinCount(0),
+    m_pFilter(pFilter),
+    m_cRef(1),               // Already ref counted
+    m_PinCache(NAME("Pin Cache"))
+{
+
+#ifdef DEBUG
+    m_dwCookie = DbgRegisterObjectCreation("CEnumPins", 0);
+#endif
+
+    /* We must be owned by a filter derived from CBaseFilter */
+
+    ASSERT(pFilter != NULL);
+
+    /* Hold a reference count on our filter */
+    m_pFilter->AddRef();
+
+    /* Are we creating a new enumerator */
+
+    if (pEnumPins == NULL) {
+        m_Version = m_pFilter->GetPinVersion();
+        m_PinCount = m_pFilter->GetPinCount();
+    } else {
+        ASSERT(m_Position <= m_PinCount);
+        m_Position = pEnumPins->m_Position;
+        m_PinCount = pEnumPins->m_PinCount;
+        m_Version = pEnumPins->m_Version;
+        m_PinCache.AddTail(&(pEnumPins->m_PinCache));
+    }
+}
+
+
+/* Destructor releases the reference count on our filter NOTE since we hold
+   a reference count on the filter who created us we know it is safe to
+   release it, no access can be made to it afterwards though as we have just
+   caused the last reference count to go and the object to be deleted */
+
+CEnumPins::~CEnumPins()
+{
+    m_pFilter->Release();
+
+#ifdef DEBUG
+    DbgRegisterObjectDestruction(m_dwCookie);
+#endif
+}
+
+
+/* Override this to say what interfaces we support where */
+
+STDMETHODIMP
+CEnumPins::QueryInterface(REFIID riid, __deref_out void **ppv)
+{
+    CheckPointer(ppv, E_POINTER);
+
+    /* Do we have this interface */
+
+    if (riid == IID_IEnumPins || riid == IID_IUnknown) {
+        return GetInterface((IEnumPins *) this, ppv);
+    } else {
+        *ppv = NULL;
+        return E_NOINTERFACE;
+    }
+}
+
+STDMETHODIMP_(ULONG)
+CEnumPins::AddRef()
+{
+    return InterlockedIncrement(&m_cRef);
+}
+
+STDMETHODIMP_(ULONG)
+CEnumPins::Release()
+{
+    ULONG cRef = InterlockedDecrement(&m_cRef);
+    if (cRef == 0) {
+        delete this;
+    }
+    return cRef;
+}
+
+/* One of an enumerator's basic member functions allows us to create a cloned
+   interface that initially has the same state. Since we are taking a snapshot
+   of an object (current position and all) we must lock access at the start */
+
+STDMETHODIMP 
+CEnumPins::Clone(__deref_out IEnumPins **ppEnum)
+{
+    CheckPointer(ppEnum,E_POINTER);
+    ValidateReadWritePtr(ppEnum,sizeof(IEnumPins *));
+    HRESULT hr = NOERROR;
+
+    /* Check we are still in sync with the filter */
+    if (AreWeOutOfSync() == TRUE) {
+        *ppEnum = NULL;
+        hr =  VFW_E_ENUM_OUT_OF_SYNC;
+    } else {
+        *ppEnum = new CEnumPins(m_pFilter, 
+                                this);
+        if (*ppEnum == NULL) {
+            hr = E_OUTOFMEMORY;
+        }
+    }
+    return hr;
+}
+
+
+/* Return the next pin after the current position */
+
+STDMETHODIMP
+CEnumPins::Next(ULONG cPins,        // place this many pins...
+        __out_ecount(cPins) IPin **ppPins,      // ...in this array
+        __out_opt ULONG *pcFetched)   // actual count passed returned here
+{
+    CheckPointer(ppPins,E_POINTER);
+    ValidateReadWritePtr(ppPins,cPins * sizeof(IPin *));
+
+    ASSERT(ppPins);
+
+    if (pcFetched!=NULL) {
+        ValidateWritePtr(pcFetched, sizeof(ULONG));
+        *pcFetched = 0;           // default unless we succeed
+    }
+    // now check that the parameter is valid
+    else if (cPins>1) {   // pcFetched == NULL
+        return E_INVALIDARG;
+    }
+    ULONG cFetched = 0;           // increment as we get each one.
+
+    /* Check we are still in sync with the filter */
+    if (AreWeOutOfSync() == TRUE) {
+        // If we are out of sync, we should refresh the enumerator.
+        // This will reset the position and update the other members, but
+        // will not clear cache of pins we have already returned.
+        Refresh();
+    }
+
+    /* Return each pin interface NOTE GetPin returns CBasePin * not addrefed
+       so we must QI for the IPin (which increments its reference count)
+       If while we are retrieving a pin from the filter an error occurs we
+       assume that our internal state is stale with respect to the filter
+       (for example someone has deleted a pin) so we
+       return VFW_E_ENUM_OUT_OF_SYNC                            */
+
+    while (cFetched < cPins && m_PinCount > m_Position) {
+
+        /* Get the next pin object from the filter */
+
+        CBasePin *pPin = m_pFilter->GetPin(m_Position++);
+        if (pPin == NULL) {
+            // If this happend, and it's not the first time through, then we've got a problem,
+            // since we should really go back and release the iPins, which we have previously
+            // AddRef'ed.
+            ASSERT( cFetched==0 );
+            return VFW_E_ENUM_OUT_OF_SYNC;
+        }
+
+        /* We only want to return this pin, if it is not in our cache */
+        if (0 == m_PinCache.Find(pPin))
+        {
+            /* From the object get an IPin interface */
+
+            *ppPins = pPin;
+            pPin->AddRef();
+
+            cFetched++;
+            ppPins++;
+
+            m_PinCache.AddTail(pPin);
+        }
+    }
+
+    if (pcFetched!=NULL) {
+        *pcFetched = cFetched;
+    }
+
+    return (cPins==cFetched ? NOERROR : S_FALSE);
+}
+
+
+/* Skip over one or more entries in the enumerator */
+
+STDMETHODIMP
+CEnumPins::Skip(ULONG cPins)
+{
+    /* Check we are still in sync with the filter */
+    if (AreWeOutOfSync() == TRUE) {
+        return VFW_E_ENUM_OUT_OF_SYNC;
+    }
+
+    /* Work out how many pins are left to skip over */
+    /* We could position at the end if we are asked to skip too many... */
+    /* ..which would match the base implementation for CEnumMediaTypes::Skip */
+
+    ULONG PinsLeft = m_PinCount - m_Position;
+    if (cPins > PinsLeft) {
+        return S_FALSE;
+    }
+    m_Position += cPins;
+    return NOERROR;
+}
+
+
+/* Set the current position back to the start */
+/* Reset has 4 simple steps:
+ *
+ * Set position to head of list
+ * Sync enumerator with object being enumerated
+ * Clear the cache of pins already returned
+ * return S_OK
+ */
+
+STDMETHODIMP
+CEnumPins::Reset()
+{
+    m_Version = m_pFilter->GetPinVersion();
+    m_PinCount = m_pFilter->GetPinCount();
+
+    m_Position = 0;
+
+    // Clear the cache
+    m_PinCache.RemoveAll();
+
+    return S_OK;
+}
+
+
+/* Set the current position back to the start */
+/* Refresh has 3 simple steps:
+ *
+ * Set position to head of list
+ * Sync enumerator with object being enumerated
+ * return S_OK
+ */
+
+STDMETHODIMP
+CEnumPins::Refresh()
+{
+    m_Version = m_pFilter->GetPinVersion();
+    m_PinCount = m_pFilter->GetPinCount();
+
+    m_Position = 0;
+    return S_OK;
+}
+
+
+//=====================================================================
+//=====================================================================
+// Implements CEnumMediaTypes
+//=====================================================================
+//=====================================================================
+
+
+CEnumMediaTypes::CEnumMediaTypes(__in CBasePin *pPin,
+                                 __in_opt CEnumMediaTypes *pEnumMediaTypes) :
+    m_Position(0),
+    m_pPin(pPin),
+    m_cRef(1)
+{
+
+#ifdef DEBUG
+    m_dwCookie = DbgRegisterObjectCreation("CEnumMediaTypes", 0);
+#endif
+
+    /* We must be owned by a pin derived from CBasePin */
+
+    ASSERT(pPin != NULL);
+
+    /* Hold a reference count on our pin */
+    m_pPin->AddRef();
+
+    /* Are we creating a new enumerator */
+
+    if (pEnumMediaTypes == NULL) {
+        m_Version = m_pPin->GetMediaTypeVersion();
+        return;
+    }
+
+    m_Position = pEnumMediaTypes->m_Position;
+    m_Version = pEnumMediaTypes->m_Version;
+}
+
+
+/* Destructor releases the reference count on our base pin. NOTE since we hold
+   a reference count on the pin who created us we know it is safe to release
+   it, no access can be made to it afterwards though as we might have just
+   caused the last reference count to go and the object to be deleted */
+
+CEnumMediaTypes::~CEnumMediaTypes()
+{
+#ifdef DEBUG
+    DbgRegisterObjectDestruction(m_dwCookie);
+#endif
+    m_pPin->Release();
+}
+
+
+/* Override this to say what interfaces we support where */
+
+STDMETHODIMP
+CEnumMediaTypes::QueryInterface(REFIID riid, __deref_out void **ppv)
+{
+    CheckPointer(ppv, E_POINTER);
+
+    /* Do we have this interface */
+
+    if (riid == IID_IEnumMediaTypes || riid == IID_IUnknown) {
+        return GetInterface((IEnumMediaTypes *) this, ppv);
+    } else {
+        *ppv = NULL;
+        return E_NOINTERFACE;
+    }
+}
+
+STDMETHODIMP_(ULONG)
+CEnumMediaTypes::AddRef()
+{
+    return InterlockedIncrement(&m_cRef);
+}
+
+STDMETHODIMP_(ULONG)
+CEnumMediaTypes::Release()
+{
+    ULONG cRef = InterlockedDecrement(&m_cRef);
+    if (cRef == 0) {
+        delete this;
+    }
+    return cRef;
+}
+
+/* One of an enumerator's basic member functions allows us to create a cloned
+   interface that initially has the same state. Since we are taking a snapshot
+   of an object (current position and all) we must lock access at the start */
+
+STDMETHODIMP
+CEnumMediaTypes::Clone(__deref_out IEnumMediaTypes **ppEnum)
+{
+    CheckPointer(ppEnum,E_POINTER);
+    ValidateReadWritePtr(ppEnum,sizeof(IEnumMediaTypes *));
+    HRESULT hr = NOERROR;
+
+    /* Check we are still in sync with the pin */
+    if (AreWeOutOfSync() == TRUE) {
+        *ppEnum = NULL;
+        hr = VFW_E_ENUM_OUT_OF_SYNC;
+    } else {
+
+        *ppEnum = new CEnumMediaTypes(m_pPin,
+                                      this);
+
+        if (*ppEnum == NULL) {
+            hr =  E_OUTOFMEMORY;
+        }
+    }
+    return hr;
+}
+
+
+/* Enumerate the next pin(s) after the current position. The client using this
+   interface passes in a pointer to an array of pointers each of which will
+   be filled in with a pointer to a fully initialised media type format
+   Return NOERROR if it all works,
+          S_FALSE if fewer than cMediaTypes were enumerated.
+          VFW_E_ENUM_OUT_OF_SYNC if the enumerator has been broken by
+                                 state changes in the filter
+   The actual count always correctly reflects the number of types in the array.
+*/
+
+STDMETHODIMP
+CEnumMediaTypes::Next(ULONG cMediaTypes,          // place this many types...
+                      __out_ecount(cMediaTypes) AM_MEDIA_TYPE **ppMediaTypes,   // ...in this array
+                      __out ULONG *pcFetched)           // actual count passed
+{
+    CheckPointer(ppMediaTypes,E_POINTER);
+    ValidateReadWritePtr(ppMediaTypes,cMediaTypes * sizeof(AM_MEDIA_TYPE *));
+    /* Check we are still in sync with the pin */
+    if (AreWeOutOfSync() == TRUE) {
+        return VFW_E_ENUM_OUT_OF_SYNC;
+    }
+
+    if (pcFetched!=NULL) {
+        ValidateWritePtr(pcFetched, sizeof(ULONG));
+        *pcFetched = 0;           // default unless we succeed
+    }
+    // now check that the parameter is valid
+    else if (cMediaTypes>1) {     // pcFetched == NULL
+        return E_INVALIDARG;
+    }
+    ULONG cFetched = 0;           // increment as we get each one.
+
+    /* Return each media type by asking the filter for them in turn - If we
+       have an error code retured to us while we are retrieving a media type
+       we assume that our internal state is stale with respect to the filter
+       (for example the window size changing) so we return
+       VFW_E_ENUM_OUT_OF_SYNC */
+
+    while (cMediaTypes) {
+
+        CMediaType cmt;
+
+        HRESULT hr = m_pPin->GetMediaType(m_Position++, &cmt);
+        if (S_OK != hr) {
+            break;
+        }
+
+        /* We now have a CMediaType object that contains the next media type
+           but when we assign it to the array position we CANNOT just assign
+           the AM_MEDIA_TYPE structure because as soon as the object goes out of
+           scope it will delete the memory we have just copied. The function
+           we use is CreateMediaType which allocates a task memory block */
+
+        /*  Transfer across the format block manually to save an allocate
+            and free on the format block and generally go faster */
+
+        *ppMediaTypes = (AM_MEDIA_TYPE *)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
+        if (*ppMediaTypes == NULL) {
+            break;
+        }
+
+        /*  Do a regular copy */
+        **ppMediaTypes = cmt;
+
+        /*  Make sure the destructor doesn't free these */
+        cmt.pbFormat = NULL;
+        cmt.cbFormat = NULL;
+        cmt.pUnk     = NULL;
+
+
+        ppMediaTypes++;
+        cFetched++;
+        cMediaTypes--;
+    }
+
+    if (pcFetched!=NULL) {
+        *pcFetched = cFetched;
+    }
+
+    return ( cMediaTypes==0 ? NOERROR : S_FALSE );
+}
+
+
+/* Skip over one or more entries in the enumerator */
+
+STDMETHODIMP
+CEnumMediaTypes::Skip(ULONG cMediaTypes)
+{
+    //  If we're skipping 0 elements we're guaranteed to skip the
+    //  correct number of elements
+    if (cMediaTypes == 0) {
+        return S_OK;
+    }
+
+    /* Check we are still in sync with the pin */
+    if (AreWeOutOfSync() == TRUE) {
+        return VFW_E_ENUM_OUT_OF_SYNC;
+    }
+
+    m_Position += cMediaTypes;
+
+    /*  See if we're over the end */
+    CMediaType cmt;
+    return S_OK == m_pPin->GetMediaType(m_Position - 1, &cmt) ? S_OK : S_FALSE;
+}
+
+
+/* Set the current position back to the start */
+/* Reset has 3 simple steps:
+ *
+ * set position to head of list
+ * sync enumerator with object being enumerated
+ * return S_OK
+ */
+
+STDMETHODIMP
+CEnumMediaTypes::Reset()
+
+{
+    m_Position = 0;
+
+    // Bring the enumerator back into step with the current state.  This
+    // may be a noop but ensures that the enumerator will be valid on the
+    // next call.
+    m_Version = m_pPin->GetMediaTypeVersion();
+    return NOERROR;
+}
+
+
+//=====================================================================
+//=====================================================================
+// Implements CBasePin
+//=====================================================================
+//=====================================================================
+
+
+/* NOTE The implementation of this class calls the CUnknown constructor with
+   a NULL outer unknown pointer. This has the effect of making us a self
+   contained class, ie any QueryInterface, AddRef or Release calls will be
+   routed to the class's NonDelegatingUnknown methods. You will typically
+   find that the classes that do this then override one or more of these
+   virtual functions to provide more specialised behaviour. A good example
+   of this is where a class wants to keep the QueryInterface internal but
+   still wants its lifetime controlled by the external object */
+
+/* Constructor */
+
+CBasePin::CBasePin(__in_opt LPCTSTR pObjectName,
+           __in CBaseFilter *pFilter,
+           __in CCritSec *pLock,
+           __inout HRESULT *phr,
+           __in_opt LPCWSTR pName,
+           PIN_DIRECTION dir) :
+    CUnknown( pObjectName, NULL ),
+    m_pFilter(pFilter),
+    m_pLock(pLock),
+    m_pName(NULL),
+    m_Connected(NULL),
+    m_dir(dir),
+    m_bRunTimeError(FALSE),
+    m_pQSink(NULL),
+    m_TypeVersion(1),
+    m_tStart(),
+    m_tStop(MAX_TIME),
+    m_bCanReconnectWhenActive(false),
+    m_bTryMyTypesFirst(false),
+    m_dRate(1.0)
+{
+    /*  WARNING - pFilter is often not a properly constituted object at
+        this state (in particular QueryInterface may not work) - this
+        is because its owner is often its containing object and we
+        have been called from the containing object's constructor so
+        the filter's owner has not yet had its CUnknown constructor
+        called
+    */
+#ifdef DXMPERF
+    PERFLOG_CTOR( pName ? pName : L"CBasePin", (IPin *) this );
+#endif // DXMPERF
+
+    ASSERT(pFilter != NULL);
+    ASSERT(pLock != NULL);
+
+    if (pName) {
+        size_t cchName;
+        HRESULT hr = StringCchLengthW(pName, STRSAFE_MAX_CCH, &cchName);
+        if (SUCCEEDED(hr)) {
+            m_pName = new WCHAR[cchName + 1];
+            if (m_pName) {
+                (void)StringCchCopyW(m_pName, cchName + 1, pName);
+            }
+        }
+    }
+
+#ifdef DEBUG
+    m_cRef = 0;
+#endif
+}
+
+#ifdef UNICODE
+CBasePin::CBasePin(__in_opt LPCSTR pObjectName,
+           __in CBaseFilter *pFilter,
+           __in CCritSec *pLock,
+           __inout HRESULT *phr,
+           __in_opt LPCWSTR pName,
+           PIN_DIRECTION dir) :
+    CUnknown( pObjectName, NULL ),
+    m_pFilter(pFilter),
+    m_pLock(pLock),
+    m_pName(NULL),
+    m_Connected(NULL),
+    m_dir(dir),
+    m_bRunTimeError(FALSE),
+    m_pQSink(NULL),
+    m_TypeVersion(1),
+    m_tStart(),
+    m_tStop(MAX_TIME),
+    m_bCanReconnectWhenActive(false),
+    m_bTryMyTypesFirst(false),
+    m_dRate(1.0)
+{
+    /*  WARNING - pFilter is often not a properly constituted object at
+        this state (in particular QueryInterface may not work) - this
+        is because its owner is often its containing object and we
+        have been called from the containing object's constructor so
+        the filter's owner has not yet had its CUnknown constructor
+        called
+    */
+#ifdef DXMPERF
+    PERFLOG_CTOR( pName ? pName : L"CBasePin", (IPin *) this );
+#endif // DXMPERF
+
+    ASSERT(pFilter != NULL);
+    ASSERT(pLock != NULL);
+
+    if (pName) {
+        size_t cchName;
+        HRESULT hr = StringCchLengthW(pName, STRSAFE_MAX_CCH, &cchName);
+        if (SUCCEEDED(hr)) {
+            m_pName = new WCHAR[cchName + 1];
+            if (m_pName) {
+                (void)StringCchCopyW(m_pName, cchName + 1, pName);
+            }
+        }
+    }
+
+
+#ifdef DEBUG
+    m_cRef = 0;
+#endif
+}
+#endif
+
+/* Destructor since a connected pin holds a reference count on us there is
+   no way that we can be deleted unless we are not currently connected */
+
+CBasePin::~CBasePin()
+{
+#ifdef DXMPERF
+    PERFLOG_DTOR( m_pName ? m_pName : L"CBasePin", (IPin *) this );
+#endif // DXMPERF
+
+    //  We don't call disconnect because if the filter is going away
+    //  all the pins must have a reference count of zero so they must
+    //  have been disconnected anyway - (but check the assumption)
+    ASSERT(m_Connected == FALSE);
+
+    delete[] m_pName;
+
+    // check the internal reference count is consistent
+    ASSERT(m_cRef == 0);
+}
+
+
+/* Override this to say what interfaces we support and where */
+
+STDMETHODIMP
+CBasePin::NonDelegatingQueryInterface(REFIID riid, __deref_out void ** ppv)
+{
+    /* Do we have this interface */
+
+    if (riid == IID_IPin) {
+        return GetInterface((IPin *) this, ppv);
+    } else if (riid == IID_IQualityControl) {
+        return GetInterface((IQualityControl *) this, ppv);
+    } else {
+        return CUnknown::NonDelegatingQueryInterface(riid, ppv);
+    }
+}
+
+
+/* Override to increment the owning filter's reference count */
+
+STDMETHODIMP_(ULONG)
+CBasePin::NonDelegatingAddRef()
+{
+    ASSERT(InterlockedIncrement(&m_cRef) > 0);
+    return m_pFilter->AddRef();
+}
+
+
+/* Override to decrement the owning filter's reference count */
+
+STDMETHODIMP_(ULONG)
+CBasePin::NonDelegatingRelease()
+{
+    ASSERT(InterlockedDecrement(&m_cRef) >= 0);
+    return m_pFilter->Release();
+}
+
+
+/* Displays pin connection information */
+
+#ifdef DEBUG
+void
+CBasePin::DisplayPinInfo(IPin *pReceivePin)
+{
+
+    if (DbgCheckModuleLevel(LOG_TRACE, CONNECT_TRACE_LEVEL)) {
+        PIN_INFO ConnectPinInfo;
+        PIN_INFO ReceivePinInfo;
+
+        if (FAILED(QueryPinInfo(&ConnectPinInfo))) {
+            StringCchCopyW(ConnectPinInfo.achName, sizeof(ConnectPinInfo.achName)/sizeof(WCHAR), L"Bad Pin");
+        } else {
+            QueryPinInfoReleaseFilter(ConnectPinInfo);
+        }
+
+        if (FAILED(pReceivePin->QueryPinInfo(&ReceivePinInfo))) {
+            StringCchCopyW(ReceivePinInfo.achName, sizeof(ReceivePinInfo.achName)/sizeof(WCHAR), L"Bad Pin");
+        } else {
+            QueryPinInfoReleaseFilter(ReceivePinInfo);
+        }
+
+        DbgLog((LOG_TRACE, CONNECT_TRACE_LEVEL, TEXT("Trying to connect Pins :")));
+        DbgLog((LOG_TRACE, CONNECT_TRACE_LEVEL, TEXT("    <%ls>"), ConnectPinInfo.achName));
+        DbgLog((LOG_TRACE, CONNECT_TRACE_LEVEL, TEXT("    <%ls>"), ReceivePinInfo.achName));
+    }
+}
+#endif
+
+
+/* Displays general information on the pin media type */
+
+#ifdef DEBUG
+void CBasePin::DisplayTypeInfo(IPin *pPin, const CMediaType *pmt)
+{
+    UNREFERENCED_PARAMETER(pPin);
+    if (DbgCheckModuleLevel(LOG_TRACE, CONNECT_TRACE_LEVEL)) {
+        DbgLog((LOG_TRACE, CONNECT_TRACE_LEVEL, TEXT("Trying media type:")));
+        DbgLog((LOG_TRACE, CONNECT_TRACE_LEVEL, TEXT("    major type:  %hs"),
+               GuidNames[*pmt->Type()]));
+        DbgLog((LOG_TRACE, CONNECT_TRACE_LEVEL, TEXT("    sub type  :  %hs"),
+               GuidNames[*pmt->Subtype()]));
+    }
+}
+#endif
+
+/* Asked to connect to a pin. A pin is always attached to an owning filter
+   object so we always delegate our locking to that object. We first of all
+   retrieve a media type enumerator for the input pin and see if we accept
+   any of the formats that it would ideally like, failing that we retrieve
+   our enumerator and see if it will accept any of our preferred types */
+
+STDMETHODIMP
+CBasePin::Connect(
+    IPin * pReceivePin,
+    __in_opt const AM_MEDIA_TYPE *pmt   // optional media type
+)
+{
+    CheckPointer(pReceivePin,E_POINTER);
+    ValidateReadPtr(pReceivePin,sizeof(IPin));
+    CAutoLock cObjectLock(m_pLock);
+    DisplayPinInfo(pReceivePin);
+
+    /* See if we are already connected */
+
+    if (m_Connected) {
+        DbgLog((LOG_TRACE, CONNECT_TRACE_LEVEL, TEXT("Already connected")));
+        return VFW_E_ALREADY_CONNECTED;
+    }
+
+    /* See if the filter is active */
+    if (!IsStopped() && !m_bCanReconnectWhenActive) {
+        return VFW_E_NOT_STOPPED;
+    }
+
+
+    // Find a mutually agreeable media type -
+    // Pass in the template media type. If this is partially specified,
+    // each of the enumerated media types will need to be checked against
+    // it. If it is non-null and fully specified, we will just try to connect
+    // with this.
+
+    const CMediaType * ptype = (CMediaType*)pmt;
+    HRESULT hr = AgreeMediaType(pReceivePin, ptype);
+    if (FAILED(hr)) {
+        DbgLog((LOG_TRACE, CONNECT_TRACE_LEVEL, TEXT("Failed to agree type")));
+
+        // Since the procedure is already returning an error code, there
+        // is nothing else this function can do to report the error.
+        EXECUTE_ASSERT( SUCCEEDED( BreakConnect() ) );
+
+#ifdef DXMPERF
+        PERFLOG_CONNECT( (IPin *) this, pReceivePin, hr, pmt );
+#endif // DXMPERF
+
+        return hr;
+    }
+
+    DbgLog((LOG_TRACE, CONNECT_TRACE_LEVEL, TEXT("Connection succeeded")));
+
+#ifdef DXMPERF
+    PERFLOG_CONNECT( (IPin *) this, pReceivePin, NOERROR, pmt );
+#endif // DXMPERF
+
+    return NOERROR;
+}
+
+// given a specific media type, attempt a connection (includes
+// checking that the type is acceptable to this pin)
+HRESULT
+CBasePin::AttemptConnection(
+    IPin* pReceivePin,      // connect to this pin
+    const CMediaType* pmt   // using this type
+)
+{
+    // The caller should hold the filter lock becasue this function
+    // uses m_Connected.  The caller should also hold the filter lock
+    // because this function calls SetMediaType(), IsStopped() and
+    // CompleteConnect().
+    ASSERT(CritCheckIn(m_pLock));
+
+    // Check that the connection is valid  -- need to do this for every
+    // connect attempt since BreakConnect will undo it.
+    HRESULT hr = CheckConnect(pReceivePin);
+    if (FAILED(hr)) {
+        DbgLog((LOG_TRACE, CONNECT_TRACE_LEVEL, TEXT("CheckConnect failed")));
+
+        // Since the procedure is already returning an error code, there
+        // is nothing else this function can do to report the error.
+        EXECUTE_ASSERT( SUCCEEDED( BreakConnect() ) );
+
+        return hr;
+    }
+
+    DisplayTypeInfo(pReceivePin, pmt);
+
+    /* Check we will accept this media type */
+
+    hr = CheckMediaType(pmt);
+    if (hr == NOERROR) {
+
+        /*  Make ourselves look connected otherwise ReceiveConnection
+            may not be able to complete the connection
+        */
+        m_Connected = pReceivePin;
+        m_Connected->AddRef();
+        hr = SetMediaType(pmt);
+        if (SUCCEEDED(hr)) {
+            /* See if the other pin will accept this type */
+
+            hr = pReceivePin->ReceiveConnection((IPin *)this, pmt);
+            if (SUCCEEDED(hr)) {
+                /* Complete the connection */
+
+                hr = CompleteConnect(pReceivePin);
+                if (SUCCEEDED(hr)) {
+                    return hr;
+                } else {
+                    DbgLog((LOG_TRACE,
+                            CONNECT_TRACE_LEVEL,
+                            TEXT("Failed to complete connection")));
+                    pReceivePin->Disconnect();
+                }
+            }
+        }
+    } else {
+        // we cannot use this media type
+
+        // return a specific media type error if there is one
+        // or map a general failure code to something more helpful
+        // (in particular S_FALSE gets changed to an error code)
+        if (SUCCEEDED(hr) ||
+            (hr == E_FAIL) ||
+            (hr == E_INVALIDARG)) {
+            hr = VFW_E_TYPE_NOT_ACCEPTED;
+        }
+    }
+
+    // BreakConnect and release any connection here in case CheckMediaType
+    // failed, or if we set anything up during a call back during
+    // ReceiveConnection.
+
+    // Since the procedure is already returning an error code, there
+    // is nothing else this function can do to report the error.
+    EXECUTE_ASSERT( SUCCEEDED( BreakConnect() ) );
+
+    /*  If failed then undo our state */
+    if (m_Connected) {
+        m_Connected->Release();
+        m_Connected = NULL;
+    }
+
+    return hr;
+}
+
+/* Given an enumerator we cycle through all the media types it proposes and
+   firstly suggest them to our derived pin class and if that succeeds try
+   them with the pin in a ReceiveConnection call. This means that if our pin
+   proposes a media type we still check in here that we can support it. This
+   is deliberate so that in simple cases the enumerator can hold all of the
+   media types even if some of them are not really currently available */
+
+HRESULT CBasePin::TryMediaTypes(
+    IPin *pReceivePin,
+    __in_opt const CMediaType *pmt,
+    IEnumMediaTypes *pEnum)
+{
+    /* Reset the current enumerator position */
+
+    HRESULT hr = pEnum->Reset();
+    if (FAILED(hr)) {
+        return hr;
+    }
+
+    CMediaType *pMediaType = NULL;
+    ULONG ulMediaCount = 0;
+
+    // attempt to remember a specific error code if there is one
+    HRESULT hrFailure = S_OK;
+
+    for (;;) {
+
+        /* Retrieve the next media type NOTE each time round the loop the
+           enumerator interface will allocate another AM_MEDIA_TYPE structure
+           If we are successful then we copy it into our output object, if
+           not then we must delete the memory allocated before returning */
+
+        hr = pEnum->Next(1, (AM_MEDIA_TYPE**)&pMediaType,&ulMediaCount);
+        if (hr != S_OK) {
+            if (S_OK == hrFailure) {
+                hrFailure = VFW_E_NO_ACCEPTABLE_TYPES;
+            }
+            return hrFailure;
+        }
+
+
+        ASSERT(ulMediaCount == 1);
+        ASSERT(pMediaType);
+
+        // check that this matches the partial type (if any)
+
+        if (pMediaType &&
+            ((pmt == NULL) ||
+            pMediaType->MatchesPartial(pmt))) {
+
+            hr = AttemptConnection(pReceivePin, pMediaType);
+
+            // attempt to remember a specific error code
+            if (FAILED(hr) &&
+            SUCCEEDED(hrFailure) &&
+            (hr != E_FAIL) &&
+            (hr != E_INVALIDARG) &&
+            (hr != VFW_E_TYPE_NOT_ACCEPTED)) {
+                hrFailure = hr;
+            }
+        } else {
+            hr = VFW_E_NO_ACCEPTABLE_TYPES;
+        }
+
+        if(pMediaType) {
+            DeleteMediaType(pMediaType);
+            pMediaType = NULL;
+        }
+
+        if (S_OK == hr) {
+            return hr;
+        }
+    }
+}
+
+
+/* This is called to make the connection, including the taask of finding
+   a media type for the pin connection. pmt is the proposed media type
+   from the Connect call: if this is fully specified, we will try that.
+   Otherwise we enumerate and try all the input pin's types first and
+   if that fails we then enumerate and try all our preferred media types.
+   For each media type we check it against pmt (if non-null and partially
+   specified) as well as checking that both pins will accept it.
+ */
+
+HRESULT CBasePin::AgreeMediaType(
+    IPin *pReceivePin,
+    const CMediaType *pmt)
+{
+    ASSERT(pReceivePin);
+    IEnumMediaTypes *pEnumMediaTypes = NULL;
+
+    // if the media type is fully specified then use that
+    if ( (pmt != NULL) && (!pmt->IsPartiallySpecified())) {
+
+        // if this media type fails, then we must fail the connection
+        // since if pmt is nonnull we are only allowed to connect
+        // using a type that matches it.
+
+        return AttemptConnection(pReceivePin, pmt);
+    }
+
+
+    /* Try the other pin's enumerator */
+
+    HRESULT hrFailure = VFW_E_NO_ACCEPTABLE_TYPES;
+
+    for (int i = 0; i < 2; i++) {
+        HRESULT hr;
+        if (i == (int)m_bTryMyTypesFirst) {
+            hr = pReceivePin->EnumMediaTypes(&pEnumMediaTypes);
+        } else {
+            hr = EnumMediaTypes(&pEnumMediaTypes);
+        }
+        if (SUCCEEDED(hr)) {
+            ASSERT(pEnumMediaTypes);
+            hr = TryMediaTypes(pReceivePin,pmt,pEnumMediaTypes);
+            pEnumMediaTypes->Release();
+            if (SUCCEEDED(hr)) {
+                return NOERROR;
+            } else {
+                // try to remember specific error codes if there are any
+                if ((hr != E_FAIL) &&
+                    (hr != E_INVALIDARG) &&
+                    (hr != VFW_E_TYPE_NOT_ACCEPTED)) {
+                    hrFailure = hr;
+                }
+            }
+        }
+    }
+
+    return hrFailure;
+}
+
+
+/* Called when we want to complete a connection to another filter. Failing
+   this will also fail the connection and disconnect the other pin as well */
+
+HRESULT
+CBasePin::CompleteConnect(IPin *pReceivePin)
+{
+    UNREFERENCED_PARAMETER(pReceivePin);
+    return NOERROR;
+}
+
+
+/* This is called to set the format for a pin connection - CheckMediaType
+   will have been called to check the connection format and if it didn't
+   return an error code then this (virtual) function will be invoked */
+
+HRESULT
+CBasePin::SetMediaType(const CMediaType *pmt)
+{
+    HRESULT hr = m_mt.Set(*pmt);
+    if (FAILED(hr)) {
+        return hr;
+    }
+
+    return NOERROR;
+}
+
+
+/* This is called during Connect() to provide a virtual method that can do
+   any specific check needed for connection such as QueryInterface. This
+   base class method just checks that the pin directions don't match */
+
+HRESULT
+CBasePin::CheckConnect(IPin * pPin)
+{
+    /* Check that pin directions DONT match */
+
+    PIN_DIRECTION pd;
+    pPin->QueryDirection(&pd);
+
+    ASSERT((pd == PINDIR_OUTPUT) || (pd == PINDIR_INPUT));
+    ASSERT((m_dir == PINDIR_OUTPUT) || (m_dir == PINDIR_INPUT));
+
+    // we should allow for non-input and non-output connections?
+    if (pd == m_dir) {
+        return VFW_E_INVALID_DIRECTION;
+    }
+    return NOERROR;
+}
+
+
+/* This is called when we realise we can't make a connection to the pin and
+   must undo anything we did in CheckConnect - override to release QIs done */
+
+HRESULT
+CBasePin::BreakConnect()
+{
+    return NOERROR;
+}
+
+
+/* Called normally by an output pin on an input pin to try and establish a
+   connection.
+*/
+
+STDMETHODIMP
+CBasePin::ReceiveConnection(
+    IPin * pConnector,   // this is the pin who we will connect to
+    const AM_MEDIA_TYPE *pmt  // this is the media type we will exchange
+)
+{
+    CheckPointer(pConnector,E_POINTER);
+    CheckPointer(pmt,E_POINTER);
+    ValidateReadPtr(pConnector,sizeof(IPin));
+    ValidateReadPtr(pmt,sizeof(AM_MEDIA_TYPE));
+    CAutoLock cObjectLock(m_pLock);
+
+    /* Are we already connected */
+    if (m_Connected) {
+        return VFW_E_ALREADY_CONNECTED;
+    }
+
+    /* See if the filter is active */
+    if (!IsStopped() && !m_bCanReconnectWhenActive) {
+        return VFW_E_NOT_STOPPED;
+    }
+
+    HRESULT hr = CheckConnect(pConnector);
+    if (FAILED(hr)) {
+        // Since the procedure is already returning an error code, there
+        // is nothing else this function can do to report the error.
+        EXECUTE_ASSERT( SUCCEEDED( BreakConnect() ) );
+
+#ifdef DXMPERF
+        PERFLOG_RXCONNECT( pConnector, (IPin *) this, hr, pmt );
+#endif // DXMPERF
+
+        return hr;
+    }
+
+    /* Ask derived class if this media type is ok */
+
+    CMediaType * pcmt = (CMediaType*) pmt;
+    hr = CheckMediaType(pcmt);
+    if (hr != NOERROR) {
+        // no -we don't support this media type
+
+        // Since the procedure is already returning an error code, there
+        // is nothing else this function can do to report the error.
+        EXECUTE_ASSERT( SUCCEEDED( BreakConnect() ) );
+
+        // return a specific media type error if there is one
+        // or map a general failure code to something more helpful
+        // (in particular S_FALSE gets changed to an error code)
+        if (SUCCEEDED(hr) ||
+            (hr == E_FAIL) ||
+            (hr == E_INVALIDARG)) {
+            hr = VFW_E_TYPE_NOT_ACCEPTED;
+        }
+
+#ifdef DXMPERF
+        PERFLOG_RXCONNECT( pConnector, (IPin *) this, hr, pmt );
+#endif // DXMPERF
+
+        return hr;
+    }
+
+    /* Complete the connection */
+
+    m_Connected = pConnector;
+    m_Connected->AddRef();
+    hr = SetMediaType(pcmt);
+    if (SUCCEEDED(hr)) {
+        hr = CompleteConnect(pConnector);
+        if (SUCCEEDED(hr)) {
+
+#ifdef DXMPERF
+            PERFLOG_RXCONNECT( pConnector, (IPin *) this, NOERROR, pmt );
+#endif // DXMPERF
+
+            return NOERROR;
+        }
+    }
+
+    DbgLog((LOG_TRACE, CONNECT_TRACE_LEVEL, TEXT("Failed to set the media type or failed to complete the connection.")));
+    m_Connected->Release();
+    m_Connected = NULL;
+
+    // Since the procedure is already returning an error code, there
+    // is nothing else this function can do to report the error.
+    EXECUTE_ASSERT( SUCCEEDED( BreakConnect() ) );
+
+#ifdef DXMPERF
+    PERFLOG_RXCONNECT( pConnector, (IPin *) this, hr, pmt );
+#endif // DXMPERF
+
+    return hr;
+}
+
+
+/* Called when we want to terminate a pin connection */
+
+STDMETHODIMP
+CBasePin::Disconnect()
+{
+    CAutoLock cObjectLock(m_pLock);
+
+    /* See if the filter is active */
+    if (!IsStopped()) {
+        return VFW_E_NOT_STOPPED;
+    }
+
+    return DisconnectInternal();
+}
+
+STDMETHODIMP
+CBasePin::DisconnectInternal()
+{
+    ASSERT(CritCheckIn(m_pLock));
+
+    if (m_Connected) {
+        HRESULT hr = BreakConnect();
+        if( FAILED( hr ) ) {
+
+#ifdef DXMPERF
+            PERFLOG_DISCONNECT( (IPin *) this, m_Connected, hr );
+#endif // DXMPERF
+
+            // There is usually a bug in the program if BreakConnect() fails.
+            DbgBreak( "WARNING: BreakConnect() failed in CBasePin::Disconnect()." );
+            return hr;
+        }
+
+        m_Connected->Release();
+        m_Connected = NULL;
+
+#ifdef DXMPERF
+        PERFLOG_DISCONNECT( (IPin *) this, m_Connected, S_OK );
+#endif // DXMPERF
+
+        return S_OK;
+    } else {
+        // no connection - not an error
+
+#ifdef DXMPERF
+        PERFLOG_DISCONNECT( (IPin *) this, m_Connected, S_FALSE );
+#endif // DXMPERF
+
+        return S_FALSE;
+    }
+}
+
+
+/* Return an AddRef()'d pointer to the connected pin if there is one */
+STDMETHODIMP
+CBasePin::ConnectedTo(
+    __deref_out IPin **ppPin
+)
+{
+    CheckPointer(ppPin,E_POINTER);
+    ValidateReadWritePtr(ppPin,sizeof(IPin *));
+    //
+    //  It's pointless to lock here.
+    //  The caller should ensure integrity.
+    //
+
+    IPin *pPin = m_Connected;
+    *ppPin = pPin;
+    if (pPin != NULL) {
+        pPin->AddRef();
+        return S_OK;
+    } else {
+        ASSERT(*ppPin == NULL);
+        return VFW_E_NOT_CONNECTED;
+    }
+}
+
+/* Return the media type of the connection */
+STDMETHODIMP
+CBasePin::ConnectionMediaType(
+    __out AM_MEDIA_TYPE *pmt
+)
+{
+    CheckPointer(pmt,E_POINTER);
+    ValidateReadWritePtr(pmt,sizeof(AM_MEDIA_TYPE));
+    CAutoLock cObjectLock(m_pLock);
+
+    /*  Copy constructor of m_mt allocates the memory */
+    if (IsConnected()) {
+        CopyMediaType( pmt, &m_mt );
+        return S_OK;
+    } else {
+        ((CMediaType *)pmt)->InitMediaType();
+        return VFW_E_NOT_CONNECTED;
+    }
+}
+
+/* Return information about the filter we are connect to */
+
+STDMETHODIMP
+CBasePin::QueryPinInfo(
+    __out PIN_INFO * pInfo
+)
+{
+    CheckPointer(pInfo,E_POINTER);
+    ValidateReadWritePtr(pInfo,sizeof(PIN_INFO));
+
+    pInfo->pFilter = m_pFilter;
+    if (m_pFilter) {
+        m_pFilter->AddRef();
+    }
+
+    if (m_pName) {
+        (void)StringCchCopyW(pInfo->achName, NUMELMS(pInfo->achName), m_pName);
+    } else {
+        pInfo->achName[0] = L'\0';
+    }
+
+    pInfo->dir = m_dir;
+
+    return NOERROR;
+}
+
+STDMETHODIMP
+CBasePin::QueryDirection(
+    __out PIN_DIRECTION * pPinDir
+)
+{
+    CheckPointer(pPinDir,E_POINTER);
+    ValidateReadWritePtr(pPinDir,sizeof(PIN_DIRECTION));
+
+    *pPinDir = m_dir;
+    return NOERROR;
+}
+
+// Default QueryId to return the pin's name
+STDMETHODIMP
+CBasePin::QueryId(
+    __deref_out LPWSTR * Id
+)
+{
+    //  We're not going away because someone's got a pointer to us
+    //  so there's no need to lock
+
+    return AMGetWideString(Name(), Id);
+}
+
+/* Does this pin support this media type WARNING this interface function does
+   not lock the main object as it is meant to be asynchronous by nature - if
+   the media types you support depend on some internal state that is updated
+   dynamically then you will need to implement locking in a derived class */
+
+STDMETHODIMP
+CBasePin::QueryAccept(
+    const AM_MEDIA_TYPE *pmt
+)
+{
+    CheckPointer(pmt,E_POINTER);
+    ValidateReadPtr(pmt,sizeof(AM_MEDIA_TYPE));
+
+    /* The CheckMediaType method is valid to return error codes if the media
+       type is horrible, an example might be E_INVALIDARG. What we do here
+       is map all the error codes into either S_OK or S_FALSE regardless */
+
+    HRESULT hr = CheckMediaType((CMediaType*)pmt);
+    if (FAILED(hr)) {
+        return S_FALSE;
+    }
+    // note that the only defined success codes should be S_OK and S_FALSE...
+    return hr;
+}
+
+
+/* This can be called to return an enumerator for the pin's list of preferred
+   media types. An input pin is not obliged to have any preferred formats
+   although it can do. For example, the window renderer has a preferred type
+   which describes a video image that matches the current window size. All
+   output pins should expose at least one preferred format otherwise it is
+   possible that neither pin has any types and so no connection is possible */
+
+STDMETHODIMP
+CBasePin::EnumMediaTypes(
+    __deref_out IEnumMediaTypes **ppEnum
+)
+{
+    CheckPointer(ppEnum,E_POINTER);
+    ValidateReadWritePtr(ppEnum,sizeof(IEnumMediaTypes *));
+
+    /* Create a new ref counted enumerator */
+
+    *ppEnum = new CEnumMediaTypes(this,
+                              NULL);
+
+    if (*ppEnum == NULL) {
+        return E_OUTOFMEMORY;
+    }
+
+    return NOERROR;
+}
+
+
+
+/* This is a virtual function that returns a media type corresponding with
+   place iPosition in the list. This base class simply returns an error as
+   we support no media types by default but derived classes should override */
+
+HRESULT CBasePin::GetMediaType(int iPosition, __inout CMediaType *pMediaType)
+{
+    UNREFERENCED_PARAMETER(iPosition);
+    UNREFERENCED_PARAMETER(pMediaType);
+    return E_UNEXPECTED;
+}
+
+
+/* This is a virtual function that returns the current media type version.
+   The base class initialises the media type enumerators with the value 1
+   By default we always returns that same value. A Derived class may change
+   the list of media types available and after doing so it should increment
+   the version either in a method derived from this, or more simply by just
+   incrementing the m_TypeVersion base pin variable. The type enumerators
+   call this when they want to see if their enumerations are out of date */
+
+LONG CBasePin::GetMediaTypeVersion()
+{
+    return m_TypeVersion;
+}
+
+
+/* Increment the cookie representing the current media type version */
+
+void CBasePin::IncrementTypeVersion()
+{
+    InterlockedIncrement(&m_TypeVersion);
+}
+
+
+/* Called by IMediaFilter implementation when the state changes from Stopped
+   to either paused or running and in derived classes could do things like
+   commit memory and grab hardware resource (the default is to do nothing) */
+
+HRESULT
+CBasePin::Active(void)
+{
+    return NOERROR;
+}
+
+/* Called by IMediaFilter implementation when the state changes from
+   to either paused to running and in derived classes could do things like
+   commit memory and grab hardware resource (the default is to do nothing) */
+
+HRESULT
+CBasePin::Run(REFERENCE_TIME tStart)
+{
+    UNREFERENCED_PARAMETER(tStart);
+    return NOERROR;
+}
+
+
+/* Also called by the IMediaFilter implementation when the state changes to
+   Stopped at which point you should decommit allocators and free hardware
+   resources you grabbed in the Active call (default is also to do nothing) */
+
+HRESULT
+CBasePin::Inactive(void)
+{
+    m_bRunTimeError = FALSE;
+    return NOERROR;
+}
+
+
+// Called when no more data will arrive
+STDMETHODIMP
+CBasePin::EndOfStream(void)
+{
+    return S_OK;
+}
+
+
+STDMETHODIMP
+CBasePin::SetSink(IQualityControl * piqc)
+{
+    CAutoLock cObjectLock(m_pLock);
+    if (piqc) ValidateReadPtr(piqc,sizeof(IQualityControl));
+    m_pQSink = piqc;
+    return NOERROR;
+} // SetSink
+
+
+STDMETHODIMP
+CBasePin::Notify(IBaseFilter * pSender, Quality q)
+{
+    UNREFERENCED_PARAMETER(q);
+    UNREFERENCED_PARAMETER(pSender);
+    DbgBreak("IQualityControl::Notify not over-ridden from CBasePin.  (IGNORE is OK)");
+    return E_NOTIMPL;
+} //Notify
+
+
+// NewSegment notifies of the start/stop/rate applying to the data
+// about to be received. Default implementation records data and
+// returns S_OK.
+// Override this to pass downstream.
+STDMETHODIMP
+CBasePin::NewSegment(
+                REFERENCE_TIME tStart,
+                REFERENCE_TIME tStop,
+                double dRate)
+{
+    m_tStart = tStart;
+    m_tStop = tStop;
+    m_dRate = dRate;
+
+    return S_OK;
+}
+
+
+//=====================================================================
+//=====================================================================
+// Implements CBaseOutputPin
+//=====================================================================
+//=====================================================================
+
+
+CBaseOutputPin::CBaseOutputPin(__in_opt LPCTSTR pObjectName,
+                   __in CBaseFilter *pFilter,
+                   __in CCritSec *pLock,
+                   __inout HRESULT *phr,
+                   __in_opt LPCWSTR pName) :
+    CBasePin(pObjectName, pFilter, pLock, phr, pName, PINDIR_OUTPUT),
+    m_pAllocator(NULL),
+    m_pInputPin(NULL)
+{
+    ASSERT(pFilter);
+}
+
+#ifdef UNICODE
+CBaseOutputPin::CBaseOutputPin(__in_opt LPCSTR pObjectName,
+                   __in CBaseFilter *pFilter,
+                   __in CCritSec *pLock,
+                   __inout HRESULT *phr,
+                   __in_opt LPCWSTR pName) :
+    CBasePin(pObjectName, pFilter, pLock, phr, pName, PINDIR_OUTPUT),
+    m_pAllocator(NULL),
+    m_pInputPin(NULL)
+{
+    ASSERT(pFilter);
+}
+#endif
+
+/*   This is called after a media type has been proposed
+
+     Try to complete the connection by agreeing the allocator
+*/
+HRESULT
+CBaseOutputPin::CompleteConnect(IPin *pReceivePin)
+{
+    UNREFERENCED_PARAMETER(pReceivePin);
+    return DecideAllocator(m_pInputPin, &m_pAllocator);
+}
+
+
+/* This method is called when the output pin is about to try and connect to
+   an input pin. It is at this point that you should try and grab any extra
+   interfaces that you need, in this case IMemInputPin. Because this is
+   only called if we are not currently connected we do NOT need to call
+   BreakConnect. This also makes it easier to derive classes from us as
+   BreakConnect is only called when we actually have to break a connection
+   (or a partly made connection) and not when we are checking a connection */
+
+/* Overriden from CBasePin */
+
+HRESULT
+CBaseOutputPin::CheckConnect(IPin * pPin)
+{
+    HRESULT hr = CBasePin::CheckConnect(pPin);
+    if (FAILED(hr)) {
+    return hr;
+    }
+
+    // get an input pin and an allocator interface
+    hr = pPin->QueryInterface(IID_IMemInputPin, (void **) &m_pInputPin);
+    if (FAILED(hr)) {
+        return hr;
+    }
+    return NOERROR;
+}
+
+
+/* Overriden from CBasePin */
+
+HRESULT
+CBaseOutputPin::BreakConnect()
+{
+    /* Release any allocator we hold */
+
+    if (m_pAllocator) {
+        // Always decommit the allocator because a downstream filter may or
+        // may not decommit the connection's allocator.  A memory leak could
+        // occur if the allocator is not decommited when a connection is broken.
+        HRESULT hr = m_pAllocator->Decommit();
+        if( FAILED( hr ) ) {
+            return hr;
+        }
+
+        m_pAllocator->Release();
+        m_pAllocator = NULL;
+    }
+
+    /* Release any input pin interface we hold */
+
+    if (m_pInputPin) {
+        m_pInputPin->Release();
+        m_pInputPin = NULL;
+    }
+    return NOERROR;
+}
+
+
+/* This is called when the input pin didn't give us a valid allocator */
+
+HRESULT
+CBaseOutputPin::InitAllocator(__deref_out IMemAllocator **ppAlloc)
+{
+    return CreateMemoryAllocator(ppAlloc);
+}
+
+
+/* Decide on an allocator, override this if you want to use your own allocator
+   Override DecideBufferSize to call SetProperties. If the input pin fails
+   the GetAllocator call then this will construct a CMemAllocator and call
+   DecideBufferSize on that, and if that fails then we are completely hosed.
+   If the you succeed the DecideBufferSize call, we will notify the input
+   pin of the selected allocator. NOTE this is called during Connect() which
+   therefore looks after grabbing and locking the object's critical section */
+
+// We query the input pin for its requested properties and pass this to
+// DecideBufferSize to allow it to fulfill requests that it is happy
+// with (eg most people don't care about alignment and are thus happy to
+// use the downstream pin's alignment request).
+
+HRESULT
+CBaseOutputPin::DecideAllocator(IMemInputPin *pPin, __deref_out IMemAllocator **ppAlloc)
+{
+    HRESULT hr = NOERROR;
+    *ppAlloc = NULL;
+
+    // get downstream prop request
+    // the derived class may modify this in DecideBufferSize, but
+    // we assume that he will consistently modify it the same way,
+    // so we only get it once
+    ALLOCATOR_PROPERTIES prop;
+    ZeroMemory(&prop, sizeof(prop));
+
+    // whatever he returns, we assume prop is either all zeros
+    // or he has filled it out.
+    pPin->GetAllocatorRequirements(&prop);
+
+    // if he doesn't care about alignment, then set it to 1
+    if (prop.cbAlign == 0) {
+        prop.cbAlign = 1;
+    }
+
+    /* Try the allocator provided by the input pin */
+
+    hr = pPin->GetAllocator(ppAlloc);
+    if (SUCCEEDED(hr)) {
+
+        hr = DecideBufferSize(*ppAlloc, &prop);
+        if (SUCCEEDED(hr)) {
+            hr = pPin->NotifyAllocator(*ppAlloc, FALSE);
+            if (SUCCEEDED(hr)) {
+                return NOERROR;
+            }
+        }
+    }
+
+    /* If the GetAllocator failed we may not have an interface */
+
+    if (*ppAlloc) {
+        (*ppAlloc)->Release();
+        *ppAlloc = NULL;
+    }
+
+    /* Try the output pin's allocator by the same method */
+
+    hr = InitAllocator(ppAlloc);
+    if (SUCCEEDED(hr)) {
+
+        // note - the properties passed here are in the same
+        // structure as above and may have been modified by
+        // the previous call to DecideBufferSize
+        hr = DecideBufferSize(*ppAlloc, &prop);
+        if (SUCCEEDED(hr)) {
+            hr = pPin->NotifyAllocator(*ppAlloc, FALSE);
+            if (SUCCEEDED(hr)) {
+                return NOERROR;
+            }
+        }
+    }
+
+    /* Likewise we may not have an interface to release */
+
+    if (*ppAlloc) {
+        (*ppAlloc)->Release();
+        *ppAlloc = NULL;
+    }
+    return hr;
+}
+
+
+/* This returns an empty sample buffer from the allocator WARNING the same
+   dangers and restrictions apply here as described below for Deliver() */
+
+HRESULT
+CBaseOutputPin::GetDeliveryBuffer(__deref_out IMediaSample ** ppSample,
+                                  __in_opt REFERENCE_TIME * pStartTime,
+                                  __in_opt REFERENCE_TIME * pEndTime,
+                                  DWORD dwFlags)
+{
+    if (m_pAllocator != NULL) {
+        return m_pAllocator->GetBuffer(ppSample,pStartTime,pEndTime,dwFlags);
+    } else {
+        return E_NOINTERFACE;
+    }
+}
+
+
+/* Deliver a filled-in sample to the connected input pin. NOTE the object must
+   have locked itself before calling us otherwise we may get halfway through
+   executing this method only to find the filter graph has got in and
+   disconnected us from the input pin. If the filter has no worker threads
+   then the lock is best applied on Receive(), otherwise it should be done
+   when the worker thread is ready to deliver. There is a wee snag to worker
+   threads that this shows up. The worker thread must lock the object when
+   it is ready to deliver a sample, but it may have to wait until a state
+   change has completed, but that may never complete because the state change
+   is waiting for the worker thread to complete. The way to handle this is for
+   the state change code to grab the critical section, then set an abort event
+   for the worker thread, then release the critical section and wait for the
+   worker thread to see the event we set and then signal that it has finished
+   (with another event). At which point the state change code can complete */
+
+// note (if you've still got any breath left after reading that) that you
+// need to release the sample yourself after this call. if the connected
+// input pin needs to hold onto the sample beyond the call, it will addref
+// the sample itself.
+
+// of course you must release this one and call GetDeliveryBuffer for the
+// next. You cannot reuse it directly.
+
+HRESULT
+CBaseOutputPin::Deliver(IMediaSample * pSample)
+{
+    if (m_pInputPin == NULL) {
+        return VFW_E_NOT_CONNECTED;
+    }
+
+#ifdef DXMPERF
+    PERFLOG_DELIVER( m_pName ? m_pName : L"CBaseOutputPin", (IPin *) this, (IPin  *) m_pInputPin, pSample, &m_mt );
+#endif // DXMPERF
+
+    return m_pInputPin->Receive(pSample);
+}
+
+
+// called from elsewhere in our filter to pass EOS downstream to
+// our connected input pin
+HRESULT
+CBaseOutputPin::DeliverEndOfStream(void)
+{
+    // remember this is on IPin not IMemInputPin
+    if (m_Connected == NULL) {
+        return VFW_E_NOT_CONNECTED;
+    }
+    return m_Connected->EndOfStream();
+}
+
+
+/* Commit the allocator's memory, this is called through IMediaFilter
+   which is responsible for locking the object before calling us */
+
+HRESULT
+CBaseOutputPin::Active(void)
+{
+    if (m_pAllocator == NULL) {
+        return VFW_E_NO_ALLOCATOR;
+    }
+    return m_pAllocator->Commit();
+}
+
+
+/* Free up or unprepare allocator's memory, this is called through
+   IMediaFilter which is responsible for locking the object first */
+
+HRESULT
+CBaseOutputPin::Inactive(void)
+{
+    m_bRunTimeError = FALSE;
+    if (m_pAllocator == NULL) {
+        return VFW_E_NO_ALLOCATOR;
+    }
+    return m_pAllocator->Decommit();
+}
+
+// we have a default handling of EndOfStream which is to return
+// an error, since this should be called on input pins only
+STDMETHODIMP
+CBaseOutputPin::EndOfStream(void)
+{
+    return E_UNEXPECTED;
+}
+
+
+// BeginFlush should be called on input pins only
+STDMETHODIMP
+CBaseOutputPin::BeginFlush(void)
+{
+    return E_UNEXPECTED;
+}
+
+// EndFlush should be called on input pins only
+STDMETHODIMP
+CBaseOutputPin::EndFlush(void)
+{
+    return E_UNEXPECTED;
+}
+
+// call BeginFlush on the connected input pin
+HRESULT
+CBaseOutputPin::DeliverBeginFlush(void)
+{
+    // remember this is on IPin not IMemInputPin
+    if (m_Connected == NULL) {
+        return VFW_E_NOT_CONNECTED;
+    }
+    return m_Connected->BeginFlush();
+}
+
+// call EndFlush on the connected input pin
+HRESULT
+CBaseOutputPin::DeliverEndFlush(void)
+{
+    // remember this is on IPin not IMemInputPin
+    if (m_Connected == NULL) {
+        return VFW_E_NOT_CONNECTED;
+    }
+    return m_Connected->EndFlush();
+}
+// deliver NewSegment to connected pin
+HRESULT
+CBaseOutputPin::DeliverNewSegment(
+    REFERENCE_TIME tStart,
+    REFERENCE_TIME tStop,
+    double dRate)
+{
+    if (m_Connected == NULL) {
+        return VFW_E_NOT_CONNECTED;
+    }
+    return m_Connected->NewSegment(tStart, tStop, dRate);
+}
+
+
+//=====================================================================
+//=====================================================================
+// Implements CBaseInputPin
+//=====================================================================
+//=====================================================================
+
+
+/* Constructor creates a default allocator object */
+
+CBaseInputPin::CBaseInputPin(__in_opt LPCTSTR pObjectName,
+                 __in CBaseFilter *pFilter,
+                 __in CCritSec *pLock,
+                 __inout HRESULT *phr,
+                 __in_opt LPCWSTR pPinName) :
+    CBasePin(pObjectName, pFilter, pLock, phr, pPinName, PINDIR_INPUT),
+    m_pAllocator(NULL),
+    m_bReadOnly(FALSE),
+    m_bFlushing(FALSE)
+{
+    ZeroMemory(&m_SampleProps, sizeof(m_SampleProps));
+}
+
+#ifdef UNICODE
+CBaseInputPin::CBaseInputPin(__in LPCSTR pObjectName,
+                 __in CBaseFilter *pFilter,
+                 __in CCritSec *pLock,
+                 __inout HRESULT *phr,
+                 __in_opt LPCWSTR pPinName) :
+    CBasePin(pObjectName, pFilter, pLock, phr, pPinName, PINDIR_INPUT),
+    m_pAllocator(NULL),
+    m_bReadOnly(FALSE),
+    m_bFlushing(FALSE)
+{
+    ZeroMemory(&m_SampleProps, sizeof(m_SampleProps));
+}
+#endif
+
+/* Destructor releases it's reference count on the default allocator */
+
+CBaseInputPin::~CBaseInputPin()
+{
+    if (m_pAllocator != NULL) {
+    m_pAllocator->Release();
+    m_pAllocator = NULL;
+    }
+}
+
+
+// override this to publicise our interfaces
+STDMETHODIMP
+CBaseInputPin::NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv)
+{
+    /* Do we know about this interface */
+
+    if (riid == IID_IMemInputPin) {
+        return GetInterface((IMemInputPin *) this, ppv);
+    } else {
+        return CBasePin::NonDelegatingQueryInterface(riid, ppv);
+    }
+}
+
+
+/* Return the allocator interface that this input pin would like the output
+   pin to use. NOTE subsequent calls to GetAllocator should all return an
+   interface onto the SAME object so we create one object at the start
+
+   Note:
+       The allocator is Release()'d on disconnect and replaced on
+       NotifyAllocator().
+
+   Override this to provide your own allocator.
+*/
+
+STDMETHODIMP
+CBaseInputPin::GetAllocator(
+    __deref_out IMemAllocator **ppAllocator)
+{
+    CheckPointer(ppAllocator,E_POINTER);
+    ValidateReadWritePtr(ppAllocator,sizeof(IMemAllocator *));
+    CAutoLock cObjectLock(m_pLock);
+
+    if (m_pAllocator == NULL) {
+        HRESULT hr = CreateMemoryAllocator(&m_pAllocator);
+        if (FAILED(hr)) {
+            return hr;
+        }
+    }
+    ASSERT(m_pAllocator != NULL);
+    *ppAllocator = m_pAllocator;
+    m_pAllocator->AddRef();
+    return NOERROR;
+}
+
+
+/* Tell the input pin which allocator the output pin is actually going to use
+   Override this if you care - NOTE the locking we do both here and also in
+   GetAllocator is unnecessary but derived classes that do something useful
+   will undoubtedly have to lock the object so this might help remind people */
+
+STDMETHODIMP
+CBaseInputPin::NotifyAllocator(
+    IMemAllocator * pAllocator,
+    BOOL bReadOnly)
+{
+    CheckPointer(pAllocator,E_POINTER);
+    ValidateReadPtr(pAllocator,sizeof(IMemAllocator));
+    CAutoLock cObjectLock(m_pLock);
+
+    IMemAllocator *pOldAllocator = m_pAllocator;
+    pAllocator->AddRef();
+    m_pAllocator = pAllocator;
+
+    if (pOldAllocator != NULL) {
+        pOldAllocator->Release();
+    }
+
+    // the readonly flag indicates whether samples from this allocator should
+    // be regarded as readonly - if true, then inplace transforms will not be
+    // allowed.
+    m_bReadOnly = (BYTE)bReadOnly;
+    return NOERROR;
+}
+
+
+HRESULT
+CBaseInputPin::BreakConnect()
+{
+    /* We don't need our allocator any more */
+    if (m_pAllocator) {
+        // Always decommit the allocator because a downstream filter may or
+        // may not decommit the connection's allocator.  A memory leak could
+        // occur if the allocator is not decommited when a pin is disconnected.
+        HRESULT hr = m_pAllocator->Decommit();
+        if( FAILED( hr ) ) {
+            return hr;
+        }
+
+        m_pAllocator->Release();
+        m_pAllocator = NULL;
+    }
+
+    return S_OK;
+}
+
+
+/* Do something with this media sample - this base class checks to see if the
+   format has changed with this media sample and if so checks that the filter
+   will accept it, generating a run time error if not. Once we have raised a
+   run time error we set a flag so that no more samples will be accepted
+
+   It is important that any filter should override this method and implement
+   synchronization so that samples are not processed when the pin is
+   disconnected etc
+*/
+
+STDMETHODIMP
+CBaseInputPin::Receive(IMediaSample *pSample)
+{
+    CheckPointer(pSample,E_POINTER);
+    ValidateReadPtr(pSample,sizeof(IMediaSample));
+    ASSERT(pSample);
+
+    HRESULT hr = CheckStreaming();
+    if (S_OK != hr) {
+        return hr;
+    }
+
+#ifdef DXMPERF
+    PERFLOG_RECEIVE( m_pName ? m_pName : L"CBaseInputPin", (IPin *) m_Connected, (IPin *) this, pSample, &m_mt );
+#endif // DXMPERF
+
+
+    /* Check for IMediaSample2 */
+    IMediaSample2 *pSample2;
+    if (SUCCEEDED(pSample->QueryInterface(IID_IMediaSample2, (void **)&pSample2))) {
+        hr = pSample2->GetProperties(sizeof(m_SampleProps), (PBYTE)&m_SampleProps);
+        pSample2->Release();
+        if (FAILED(hr)) {
+            return hr;
+        }
+    } else {
+        /*  Get the properties the hard way */
+        m_SampleProps.cbData = sizeof(m_SampleProps);
+        m_SampleProps.dwTypeSpecificFlags = 0;
+        m_SampleProps.dwStreamId = AM_STREAM_MEDIA;
+        m_SampleProps.dwSampleFlags = 0;
+        if (S_OK == pSample->IsDiscontinuity()) {
+            m_SampleProps.dwSampleFlags |= AM_SAMPLE_DATADISCONTINUITY;
+        }
+        if (S_OK == pSample->IsPreroll()) {
+            m_SampleProps.dwSampleFlags |= AM_SAMPLE_PREROLL;
+        }
+        if (S_OK == pSample->IsSyncPoint()) {
+            m_SampleProps.dwSampleFlags |= AM_SAMPLE_SPLICEPOINT;
+        }
+        if (SUCCEEDED(pSample->GetTime(&m_SampleProps.tStart,
+                                       &m_SampleProps.tStop))) {
+            m_SampleProps.dwSampleFlags |= AM_SAMPLE_TIMEVALID |
+                                           AM_SAMPLE_STOPVALID;
+        }
+        if (S_OK == pSample->GetMediaType(&m_SampleProps.pMediaType)) {
+            m_SampleProps.dwSampleFlags |= AM_SAMPLE_TYPECHANGED;
+        }
+        pSample->GetPointer(&m_SampleProps.pbBuffer);
+        m_SampleProps.lActual = pSample->GetActualDataLength();
+        m_SampleProps.cbBuffer = pSample->GetSize();
+    }
+
+    /* Has the format changed in this sample */
+
+    if (!(m_SampleProps.dwSampleFlags & AM_SAMPLE_TYPECHANGED)) {
+        return NOERROR;
+    }
+
+    /* Check the derived class accepts this format */
+    /* This shouldn't fail as the source must call QueryAccept first */
+
+    hr = CheckMediaType((CMediaType *)m_SampleProps.pMediaType);
+
+    if (hr == NOERROR) {
+        return NOERROR;
+    }
+
+    /* Raise a runtime error if we fail the media type */
+
+    m_bRunTimeError = TRUE;
+    EndOfStream();
+    m_pFilter->NotifyEvent(EC_ERRORABORT,VFW_E_TYPE_NOT_ACCEPTED,0);
+    return VFW_E_INVALIDMEDIATYPE;
+}
+
+
+/*  Receive multiple samples */
+STDMETHODIMP
+CBaseInputPin::ReceiveMultiple (
+    __in_ecount(nSamples) IMediaSample **pSamples,
+    long nSamples,
+    __out long *nSamplesProcessed)
+{
+    CheckPointer(pSamples,E_POINTER);
+    ValidateReadPtr(pSamples,nSamples * sizeof(IMediaSample *));
+
+    HRESULT hr = S_OK;
+    *nSamplesProcessed = 0;
+    while (nSamples-- > 0) {
+         hr = Receive(pSamples[*nSamplesProcessed]);
+
+         /*  S_FALSE means don't send any more */
+         if (hr != S_OK) {
+             break;
+         }
+         (*nSamplesProcessed)++;
+    }
+    return hr;
+}
+
+/*  See if Receive() might block */
+STDMETHODIMP
+CBaseInputPin::ReceiveCanBlock()
+{
+    /*  Ask all the output pins if they block
+        If there are no output pin assume we do block
+    */
+    int cPins = m_pFilter->GetPinCount();
+    int cOutputPins = 0;
+    for (int c = 0; c < cPins; c++) {
+        CBasePin *pPin = m_pFilter->GetPin(c);
+        if (NULL == pPin) {
+            break;
+        }
+        PIN_DIRECTION pd;
+        HRESULT hr = pPin->QueryDirection(&pd);
+        if (FAILED(hr)) {
+            return hr;
+        }
+
+        if (pd == PINDIR_OUTPUT) {
+
+            IPin *pConnected;
+            hr = pPin->ConnectedTo(&pConnected);
+            if (SUCCEEDED(hr)) {
+                ASSERT(pConnected != NULL);
+                cOutputPins++;
+                IMemInputPin *pInputPin;
+                hr = pConnected->QueryInterface(
+                                              IID_IMemInputPin,
+                                              (void **)&pInputPin);
+                pConnected->Release();
+                if (SUCCEEDED(hr)) {
+                    hr = pInputPin->ReceiveCanBlock();
+                    pInputPin->Release();
+                    if (hr != S_FALSE) {
+                        return S_OK;
+                    }
+                } else {
+                    /*  There's a transport we don't understand here */
+                    return S_OK;
+                }
+            }
+        }
+    }
+    return cOutputPins == 0 ? S_OK : S_FALSE;
+}
+
+// Default handling for BeginFlush - call at the beginning
+// of your implementation (makes sure that all Receive calls
+// fail). After calling this, you need to free any queued data
+// and then call downstream.
+STDMETHODIMP
+CBaseInputPin::BeginFlush(void)
+{
+    //  BeginFlush is NOT synchronized with streaming but is part of
+    //  a control action - hence we synchronize with the filter
+    CAutoLock lck(m_pLock);
+
+    // if we are already in mid-flush, this is probably a mistake
+    // though not harmful - try to pick it up for now so I can think about it
+    ASSERT(!m_bFlushing);
+
+    // first thing to do is ensure that no further Receive calls succeed
+    m_bFlushing = TRUE;
+
+    // now discard any data and call downstream - must do that
+    // in derived classes
+    return S_OK;
+}
+
+// default handling for EndFlush - call at end of your implementation
+// - before calling this, ensure that there is no queued data and no thread
+// pushing any more without a further receive, then call downstream,
+// then call this method to clear the m_bFlushing flag and re-enable
+// receives
+STDMETHODIMP
+CBaseInputPin::EndFlush(void)
+{
+    //  Endlush is NOT synchronized with streaming but is part of
+    //  a control action - hence we synchronize with the filter
+    CAutoLock lck(m_pLock);
+
+    // almost certainly a mistake if we are not in mid-flush
+    ASSERT(m_bFlushing);
+
+    // before calling, sync with pushing thread and ensure
+    // no more data is going downstream, then call EndFlush on
+    // downstream pins.
+
+    // now re-enable Receives
+    m_bFlushing = FALSE;
+
+    // No more errors
+    m_bRunTimeError = FALSE;
+
+    return S_OK;
+}
+
+
+STDMETHODIMP
+CBaseInputPin::Notify(IBaseFilter * pSender, Quality q)
+{
+    UNREFERENCED_PARAMETER(q);
+    CheckPointer(pSender,E_POINTER);
+    ValidateReadPtr(pSender,sizeof(IBaseFilter));
+    DbgBreak("IQuality::Notify called on an input pin");
+    return NOERROR;
+} // Notify
+
+/* Free up or unprepare allocator's memory, this is called through
+   IMediaFilter which is responsible for locking the object first */
+
+HRESULT
+CBaseInputPin::Inactive(void)
+{
+    m_bRunTimeError = FALSE;
+    if (m_pAllocator == NULL) {
+        return VFW_E_NO_ALLOCATOR;
+    }
+
+    m_bFlushing = FALSE;
+
+    return m_pAllocator->Decommit();
+}
+
+// what requirements do we have of the allocator - override if you want
+// to support other people's allocators but need a specific alignment
+// or prefix.
+STDMETHODIMP
+CBaseInputPin::GetAllocatorRequirements(__out ALLOCATOR_PROPERTIES*pProps)
+{
+    UNREFERENCED_PARAMETER(pProps);
+    return E_NOTIMPL;
+}
+
+//  Check if it's OK to process data
+//
+HRESULT
+CBaseInputPin::CheckStreaming()
+{
+    //  Shouldn't be able to get any data if we're not connected!
+    ASSERT(IsConnected());
+
+    //  Don't process stuff in Stopped state
+    if (IsStopped()) {
+        return VFW_E_WRONG_STATE;
+    }
+    if (m_bFlushing) {
+        return S_FALSE;
+    }
+    if (m_bRunTimeError) {
+        return VFW_E_RUNTIME_ERROR;
+    }
+    return S_OK;
+}
+
+// Pass on the Quality notification q to
+// a. Our QualityControl sink (if we have one) or else
+// b. to our upstream filter
+// and if that doesn't work, throw it away with a bad return code
+HRESULT
+CBaseInputPin::PassNotify(Quality& q)
+{
+    // We pass the message on, which means that we find the quality sink
+    // for our input pin and send it there
+
+    DbgLog((LOG_TRACE,3,TEXT("Passing Quality notification through transform")));
+    if (m_pQSink!=NULL) {
+        return m_pQSink->Notify(m_pFilter, q);
+    } else {
+        // no sink set, so pass it upstream
+        HRESULT hr;
+        IQualityControl * pIQC;
+
+        hr = VFW_E_NOT_FOUND;                   // default
+        if (m_Connected) {
+            m_Connected->QueryInterface(IID_IQualityControl, (void**)&pIQC);
+
+            if (pIQC!=NULL) {
+                hr = pIQC->Notify(m_pFilter, q);
+                pIQC->Release();
+            }
+        }
+        return hr;
+    }
+
+} // PassNotify
+
+//=====================================================================
+//=====================================================================
+// Memory allocation class, implements CMediaSample
+//=====================================================================
+//=====================================================================
+
+
+/* NOTE The implementation of this class calls the CUnknown constructor with
+   a NULL outer unknown pointer. This has the effect of making us a self
+   contained class, ie any QueryInterface, AddRef or Release calls will be
+   routed to the class's NonDelegatingUnknown methods. You will typically
+   find that the classes that do this then override one or more of these
+   virtual functions to provide more specialised behaviour. A good example
+   of this is where a class wants to keep the QueryInterface internal but
+   still wants it's lifetime controlled by the external object */
+
+/* The last two parameters have default values of NULL and zero */
+
+CMediaSample::CMediaSample(__in_opt LPCTSTR pName,
+               __in_opt CBaseAllocator *pAllocator,
+               __inout_opt HRESULT *phr,
+               __in_bcount_opt(length) LPBYTE pBuffer,
+               LONG length) :
+    m_pBuffer(pBuffer),             // Initialise the buffer
+    m_cbBuffer(length),             // And it's length
+    m_lActual(length),              // By default, actual = length
+    m_pMediaType(NULL),             // No media type change
+    m_dwFlags(0),                   // Nothing set
+    m_cRef(0),                      // 0 ref count
+    m_dwTypeSpecificFlags(0),       // Type specific flags
+    m_dwStreamId(AM_STREAM_MEDIA),  // Stream id
+    m_pAllocator(pAllocator)        // Allocator
+{
+#ifdef DXMPERF
+    PERFLOG_CTOR( pName ? pName : L"CMediaSample", (IMediaSample *) this );
+#endif // DXMPERF
+
+    /* We must have an owner and it must also be derived from class
+       CBaseAllocator BUT we do not hold a reference count on it */
+
+    ASSERT(pAllocator);
+
+    if (length < 0) {
+        *phr = VFW_E_BUFFER_OVERFLOW;
+        m_cbBuffer = 0;
+    }
+}
+
+#ifdef UNICODE
+CMediaSample::CMediaSample(__in_opt LPCSTR pName,
+               __in_opt CBaseAllocator *pAllocator,
+               __inout_opt HRESULT *phr,
+               __in_bcount_opt(length) LPBYTE pBuffer,
+               LONG length) :
+    m_pBuffer(pBuffer),             // Initialise the buffer
+    m_cbBuffer(length),             // And it's length
+    m_lActual(length),              // By default, actual = length
+    m_pMediaType(NULL),             // No media type change
+    m_dwFlags(0),                   // Nothing set
+    m_cRef(0),                      // 0 ref count
+    m_dwTypeSpecificFlags(0),       // Type specific flags
+    m_dwStreamId(AM_STREAM_MEDIA),  // Stream id
+    m_pAllocator(pAllocator)        // Allocator
+{
+#ifdef DXMPERF
+    PERFLOG_CTOR( L"CMediaSample", (IMediaSample *) this );
+#endif // DXMPERF
+
+    /* We must have an owner and it must also be derived from class
+       CBaseAllocator BUT we do not hold a reference count on it */
+
+    ASSERT(pAllocator);
+}
+#endif
+
+/* Destructor deletes the media type memory */
+
+CMediaSample::~CMediaSample()
+{
+#ifdef DXMPERF
+    PERFLOG_DTOR( L"CMediaSample", (IMediaSample *) this );
+#endif // DXMPERF
+
+    if (m_pMediaType) {
+    DeleteMediaType(m_pMediaType);
+    }
+}
+
+/* Override this to publicise our interfaces */
+
+STDMETHODIMP
+CMediaSample::QueryInterface(REFIID riid, __deref_out void **ppv)
+{
+    if (riid == IID_IMediaSample ||
+        riid == IID_IMediaSample2 ||
+        riid == IID_IUnknown) {
+        return GetInterface((IMediaSample *) this, ppv);
+    } else {
+        *ppv = NULL;
+        return E_NOINTERFACE;
+    }
+}
+
+STDMETHODIMP_(ULONG)
+CMediaSample::AddRef()
+{
+    return InterlockedIncrement(&m_cRef);
+}
+
+
+// --  CMediaSample lifetimes --
+//
+// On final release of this sample buffer it is not deleted but
+// returned to the freelist of the owning memory allocator
+//
+// The allocator may be waiting for the last buffer to be placed on the free
+// list in order to decommit all the memory, so the ReleaseBuffer() call may
+// result in this sample being deleted. We also need to hold a refcount on
+// the allocator to stop that going away until we have finished with this.
+// However, we cannot release the allocator before the ReleaseBuffer, as the
+// release may cause us to be deleted. Similarly we can't do it afterwards.
+//
+// Thus we must leave it to the allocator to hold an addref on our behalf.
+// When he issues us in GetBuffer, he addref's himself. When ReleaseBuffer
+// is called, he releases himself, possibly causing us and him to be deleted.
+
+
+STDMETHODIMP_(ULONG)
+CMediaSample::Release()
+{
+    /* Decrement our own private reference count */
+    LONG lRef;
+    if (m_cRef == 1) {
+        lRef = 0;
+        m_cRef = 0;
+    } else {
+        lRef = InterlockedDecrement(&m_cRef);
+    }
+    ASSERT(lRef >= 0);
+
+    DbgLog((LOG_MEMORY,3,TEXT("    Unknown %X ref-- = %d"),
+        this, m_cRef));
+
+    /* Did we release our final reference count */
+    if (lRef == 0) {
+        /* Free all resources */
+        if (m_dwFlags & Sample_TypeChanged) {
+            SetMediaType(NULL);
+        }
+        ASSERT(m_pMediaType == NULL);
+        m_dwFlags = 0;
+        m_dwTypeSpecificFlags = 0;
+        m_dwStreamId = AM_STREAM_MEDIA;
+
+        /* This may cause us to be deleted */
+        // Our refcount is reliably 0 thus no-one will mess with us
+        m_pAllocator->ReleaseBuffer(this);
+    }
+    return (ULONG)lRef;
+}
+
+
+// set the buffer pointer and length. Used by allocators that
+// want variable sized pointers or pointers into already-read data.
+// This is only available through a CMediaSample* not an IMediaSample*
+// and so cannot be changed by clients.
+HRESULT
+CMediaSample::SetPointer(__in_bcount(cBytes) BYTE * ptr, LONG cBytes)
+{
+    if (cBytes < 0) {
+        return VFW_E_BUFFER_OVERFLOW;
+    }
+    m_pBuffer = ptr;            // new buffer area (could be null)
+    m_cbBuffer = cBytes;        // length of buffer
+    m_lActual = cBytes;         // length of data in buffer (assume full)
+
+    return S_OK;
+}
+
+
+// get me a read/write pointer to this buffer's memory. I will actually
+// want to use sizeUsed bytes.
+STDMETHODIMP
+CMediaSample::GetPointer(__deref_out BYTE ** ppBuffer)
+{
+    ValidateReadWritePtr(ppBuffer,sizeof(BYTE *));
+
+    // creator must have set pointer either during
+    // constructor or by SetPointer
+    ASSERT(m_pBuffer);
+
+    *ppBuffer = m_pBuffer;
+    return NOERROR;
+}
+
+
+// return the size in bytes of this buffer
+STDMETHODIMP_(LONG)
+CMediaSample::GetSize(void)
+{
+    return m_cbBuffer;
+}
+
+
+// get the stream time at which this sample should start and finish.
+STDMETHODIMP
+CMediaSample::GetTime(
+    __out REFERENCE_TIME * pTimeStart,     // put time here
+    __out REFERENCE_TIME * pTimeEnd
+)
+{
+    ValidateReadWritePtr(pTimeStart,sizeof(REFERENCE_TIME));
+    ValidateReadWritePtr(pTimeEnd,sizeof(REFERENCE_TIME));
+
+    if (!(m_dwFlags & Sample_StopValid)) {
+        if (!(m_dwFlags & Sample_TimeValid)) {
+            return VFW_E_SAMPLE_TIME_NOT_SET;
+        } else {
+            *pTimeStart = m_Start;
+
+            //  Make sure old stuff works
+            *pTimeEnd = m_Start + 1;
+            return VFW_S_NO_STOP_TIME;
+        }
+    }
+
+    *pTimeStart = m_Start;
+    *pTimeEnd = m_End;
+    return NOERROR;
+}
+
+
+// Set the stream time at which this sample should start and finish.
+// NULL pointers means the time is reset
+STDMETHODIMP
+CMediaSample::SetTime(
+    __in_opt REFERENCE_TIME * pTimeStart,
+    __in_opt REFERENCE_TIME * pTimeEnd
+)
+{
+    if (pTimeStart == NULL) {
+        ASSERT(pTimeEnd == NULL);
+        m_dwFlags &= ~(Sample_TimeValid | Sample_StopValid);
+    } else {
+        if (pTimeEnd == NULL) {
+            m_Start = *pTimeStart;
+            m_dwFlags |= Sample_TimeValid;
+            m_dwFlags &= ~Sample_StopValid;
+        } else {
+            ValidateReadPtr(pTimeStart,sizeof(REFERENCE_TIME));
+            ValidateReadPtr(pTimeEnd,sizeof(REFERENCE_TIME));
+            ASSERT(*pTimeEnd >= *pTimeStart);
+
+            m_Start = *pTimeStart;
+            m_End = *pTimeEnd;
+            m_dwFlags |= Sample_TimeValid | Sample_StopValid;
+        }
+    }
+    return NOERROR;
+}
+
+
+// get the media times (eg bytes) for this sample
+STDMETHODIMP
+CMediaSample::GetMediaTime(
+    __out LONGLONG * pTimeStart,
+    __out LONGLONG * pTimeEnd
+)
+{
+    ValidateReadWritePtr(pTimeStart,sizeof(LONGLONG));
+    ValidateReadWritePtr(pTimeEnd,sizeof(LONGLONG));
+
+    if (!(m_dwFlags & Sample_MediaTimeValid)) {
+        return VFW_E_MEDIA_TIME_NOT_SET;
+    }
+
+    *pTimeStart = m_MediaStart;
+    *pTimeEnd = (m_MediaStart + m_MediaEnd);
+    return NOERROR;
+}
+
+
+// Set the media times for this sample
+STDMETHODIMP
+CMediaSample::SetMediaTime(
+    __in_opt LONGLONG * pTimeStart,
+    __in_opt LONGLONG * pTimeEnd
+)
+{
+    if (pTimeStart == NULL) {
+        ASSERT(pTimeEnd == NULL);
+        m_dwFlags &= ~Sample_MediaTimeValid;
+    } else {
+        if (NULL == pTimeEnd) {
+            return E_POINTER;
+        }
+        ValidateReadPtr(pTimeStart,sizeof(LONGLONG));
+        ValidateReadPtr(pTimeEnd,sizeof(LONGLONG));
+        ASSERT(*pTimeEnd >= *pTimeStart);
+
+        m_MediaStart = *pTimeStart;
+        m_MediaEnd = (LONG)(*pTimeEnd - *pTimeStart);
+        m_dwFlags |= Sample_MediaTimeValid;
+    }
+    return NOERROR;
+}
+
+
+STDMETHODIMP
+CMediaSample::IsSyncPoint(void)
+{
+    if (m_dwFlags & Sample_SyncPoint) {
+        return S_OK;
+    } else {
+        return S_FALSE;
+    }
+}
+
+
+STDMETHODIMP
+CMediaSample::SetSyncPoint(BOOL bIsSyncPoint)
+{
+    if (bIsSyncPoint) {
+        m_dwFlags |= Sample_SyncPoint;
+    } else {
+        m_dwFlags &= ~Sample_SyncPoint;
+    }
+    return NOERROR;
+}
+
+// returns S_OK if there is a discontinuity in the data (this same is
+// not a continuation of the previous stream of data
+// - there has been a seek).
+STDMETHODIMP
+CMediaSample::IsDiscontinuity(void)
+{
+    if (m_dwFlags & Sample_Discontinuity) {
+        return S_OK;
+    } else {
+        return S_FALSE;
+    }
+}
+
+// set the discontinuity property - TRUE if this sample is not a
+// continuation, but a new sample after a seek.
+STDMETHODIMP
+CMediaSample::SetDiscontinuity(BOOL bDiscont)
+{
+    // should be TRUE or FALSE
+    if (bDiscont) {
+        m_dwFlags |= Sample_Discontinuity;
+    } else {
+        m_dwFlags &= ~Sample_Discontinuity;
+    }
+    return S_OK;
+}
+
+STDMETHODIMP
+CMediaSample::IsPreroll(void)
+{
+    if (m_dwFlags & Sample_Preroll) {
+        return S_OK;
+    } else {
+        return S_FALSE;
+    }
+}
+
+
+STDMETHODIMP
+CMediaSample::SetPreroll(BOOL bIsPreroll)
+{
+    if (bIsPreroll) {
+        m_dwFlags |= Sample_Preroll;
+    } else {
+        m_dwFlags &= ~Sample_Preroll;
+    }
+    return NOERROR;
+}
+
+STDMETHODIMP_(LONG)
+CMediaSample::GetActualDataLength(void)
+{
+    return m_lActual;
+}
+
+
+STDMETHODIMP
+CMediaSample::SetActualDataLength(LONG lActual)
+{
+    if (lActual > m_cbBuffer || lActual < 0) {
+        ASSERT(lActual <= GetSize());
+        return VFW_E_BUFFER_OVERFLOW;
+    }
+    m_lActual = lActual;
+    return NOERROR;
+}
+
+
+/* These allow for limited format changes in band */
+
+STDMETHODIMP
+CMediaSample::GetMediaType(__deref_out AM_MEDIA_TYPE **ppMediaType)
+{
+    ValidateReadWritePtr(ppMediaType,sizeof(AM_MEDIA_TYPE *));
+    ASSERT(ppMediaType);
+
+    /* Do we have a new media type for them */
+
+    if (!(m_dwFlags & Sample_TypeChanged)) {
+        ASSERT(m_pMediaType == NULL);
+        *ppMediaType = NULL;
+        return S_FALSE;
+    }
+
+    ASSERT(m_pMediaType);
+
+    /* Create a copy of our media type */
+
+    *ppMediaType = CreateMediaType(m_pMediaType);
+    if (*ppMediaType == NULL) {
+        return E_OUTOFMEMORY;
+    }
+    return NOERROR;
+}
+
+
+/* Mark this sample as having a different format type */
+
+STDMETHODIMP
+CMediaSample::SetMediaType(__in_opt AM_MEDIA_TYPE *pMediaType)
+{
+    /* Delete the current media type */
+
+    if (m_pMediaType) {
+        DeleteMediaType(m_pMediaType);
+        m_pMediaType = NULL;
+    }
+
+    /* Mechanism for resetting the format type */
+
+    if (pMediaType == NULL) {
+        m_dwFlags &= ~Sample_TypeChanged;
+        return NOERROR;
+    }
+
+    ASSERT(pMediaType);
+    ValidateReadPtr(pMediaType,sizeof(AM_MEDIA_TYPE));
+
+    /* Take a copy of the media type */
+
+    m_pMediaType = CreateMediaType(pMediaType);
+    if (m_pMediaType == NULL) {
+        m_dwFlags &= ~Sample_TypeChanged;
+        return E_OUTOFMEMORY;
+    }
+
+    m_dwFlags |= Sample_TypeChanged;
+    return NOERROR;
+}
+
+// Set and get properties (IMediaSample2)
+STDMETHODIMP CMediaSample::GetProperties(
+    DWORD cbProperties,
+    __out_bcount(cbProperties) BYTE * pbProperties
+)
+{
+    if (0 != cbProperties) {
+        CheckPointer(pbProperties, E_POINTER);
+        //  Return generic stuff up to the length
+        AM_SAMPLE2_PROPERTIES Props;
+        Props.cbData     = min(cbProperties, sizeof(Props));
+        Props.dwSampleFlags = m_dwFlags & ~Sample_MediaTimeValid;
+        Props.dwTypeSpecificFlags = m_dwTypeSpecificFlags;
+        Props.pbBuffer   = m_pBuffer;
+        Props.cbBuffer   = m_cbBuffer;
+        Props.lActual    = m_lActual;
+        Props.tStart     = m_Start;
+        Props.tStop      = m_End;
+        Props.dwStreamId = m_dwStreamId;
+        if (m_dwFlags & AM_SAMPLE_TYPECHANGED) {
+            Props.pMediaType = m_pMediaType;
+        } else {
+            Props.pMediaType = NULL;
+        }
+        CopyMemory(pbProperties, &Props, Props.cbData);
+    }
+    return S_OK;
+}
+
+#define CONTAINS_FIELD(type, field, offset) \
+    ((FIELD_OFFSET(type, field) + sizeof(((type *)0)->field)) <= offset)
+
+HRESULT CMediaSample::SetProperties(
+    DWORD cbProperties,
+    __in_bcount(cbProperties) const BYTE * pbProperties
+)
+{
+
+    /*  Generic properties */
+    AM_MEDIA_TYPE *pMediaType = NULL;
+
+    if (CONTAINS_FIELD(AM_SAMPLE2_PROPERTIES, cbData, cbProperties)) {
+        CheckPointer(pbProperties, E_POINTER);
+        AM_SAMPLE2_PROPERTIES *pProps =
+            (AM_SAMPLE2_PROPERTIES *)pbProperties;
+
+        /*  Don't use more data than is actually there */
+        if (pProps->cbData < cbProperties) {
+            cbProperties = pProps->cbData;
+        }
+        /*  We only handle IMediaSample2 */
+        if (cbProperties > sizeof(*pProps) ||
+            pProps->cbData > sizeof(*pProps)) {
+            return E_INVALIDARG;
+        }
+        /*  Do checks first, the assignments (for backout) */
+        if (CONTAINS_FIELD(AM_SAMPLE2_PROPERTIES, dwSampleFlags, cbProperties)) {
+            /*  Check the flags */
+            if (pProps->dwSampleFlags &
+                    (~Sample_ValidFlags | Sample_MediaTimeValid)) {
+                return E_INVALIDARG;
+            }
+            /*  Check a flag isn't being set for a property
+                not being provided
+            */
+            if ((pProps->dwSampleFlags & AM_SAMPLE_TIMEVALID) &&
+                 !(m_dwFlags & AM_SAMPLE_TIMEVALID) &&
+                 !CONTAINS_FIELD(AM_SAMPLE2_PROPERTIES, tStop, cbProperties)) {
+                 return E_INVALIDARG;
+            }
+        }
+        /*  NB - can't SET the pointer or size */
+        if (CONTAINS_FIELD(AM_SAMPLE2_PROPERTIES, pbBuffer, cbProperties)) {
+
+            /*  Check pbBuffer */
+            if (pProps->pbBuffer != 0 && pProps->pbBuffer != m_pBuffer) {
+                return E_INVALIDARG;
+            }
+        }
+        if (CONTAINS_FIELD(AM_SAMPLE2_PROPERTIES, cbBuffer, cbProperties)) {
+
+            /*  Check cbBuffer */
+            if (pProps->cbBuffer != 0 && pProps->cbBuffer != m_cbBuffer) {
+                return E_INVALIDARG;
+            }
+        }
+        if (CONTAINS_FIELD(AM_SAMPLE2_PROPERTIES, cbBuffer, cbProperties) &&
+            CONTAINS_FIELD(AM_SAMPLE2_PROPERTIES, lActual, cbProperties)) {
+
+            /*  Check lActual */
+            if (pProps->cbBuffer < pProps->lActual) {
+                return E_INVALIDARG;
+            }
+        }
+
+        if (CONTAINS_FIELD(AM_SAMPLE2_PROPERTIES, pMediaType, cbProperties)) {
+
+            /*  Check pMediaType */
+            if (pProps->dwSampleFlags & AM_SAMPLE_TYPECHANGED) {
+                CheckPointer(pProps->pMediaType, E_POINTER);
+                pMediaType = CreateMediaType(pProps->pMediaType);
+                if (pMediaType == NULL) {
+                    return E_OUTOFMEMORY;
+                }
+            }
+        }
+
+        /*  Now do the assignments */
+        if (CONTAINS_FIELD(AM_SAMPLE2_PROPERTIES, dwStreamId, cbProperties)) {
+            m_dwStreamId = pProps->dwStreamId;
+        }
+        if (CONTAINS_FIELD(AM_SAMPLE2_PROPERTIES, dwSampleFlags, cbProperties)) {
+            /*  Set the flags */
+            m_dwFlags = pProps->dwSampleFlags |
+                                (m_dwFlags & Sample_MediaTimeValid);
+            m_dwTypeSpecificFlags = pProps->dwTypeSpecificFlags;
+        } else {
+            if (CONTAINS_FIELD(AM_SAMPLE2_PROPERTIES, dwTypeSpecificFlags, cbProperties)) {
+                m_dwTypeSpecificFlags = pProps->dwTypeSpecificFlags;
+            }
+        }
+
+        if (CONTAINS_FIELD(AM_SAMPLE2_PROPERTIES, lActual, cbProperties)) {
+            /*  Set lActual */
+            m_lActual = pProps->lActual;
+        }
+
+        if (CONTAINS_FIELD(AM_SAMPLE2_PROPERTIES, tStop, cbProperties)) {
+
+            /*  Set the times */
+            m_End   = pProps->tStop;
+        }
+        if (CONTAINS_FIELD(AM_SAMPLE2_PROPERTIES, tStart, cbProperties)) {
+
+            /*  Set the times */
+            m_Start = pProps->tStart;
+        }
+
+        if (CONTAINS_FIELD(AM_SAMPLE2_PROPERTIES, pMediaType, cbProperties)) {
+            /*  Set pMediaType */
+            if (pProps->dwSampleFlags & AM_SAMPLE_TYPECHANGED) {
+                if (m_pMediaType != NULL) {
+                    DeleteMediaType(m_pMediaType);
+                }
+                m_pMediaType = pMediaType;
+            }
+        }
+
+        /*  Fix up the type changed flag to correctly reflect the current state
+            If, for instance the input contained no type change but the
+            output does then if we don't do this we'd lose the
+            output media type.
+        */
+        if (m_pMediaType) {
+            m_dwFlags |= Sample_TypeChanged;
+        } else {
+            m_dwFlags &= ~Sample_TypeChanged;
+        }
+    }
+
+    return S_OK;
+}
+
+
+//
+// The streaming thread calls IPin::NewSegment(), IPin::EndOfStream(),
+// IMemInputPin::Receive() and IMemInputPin::ReceiveMultiple() on the
+// connected input pin.  The application thread calls Block().  The
+// following class members can only be called by the streaming thread.
+//
+//    Deliver()
+//    DeliverNewSegment()
+//    StartUsingOutputPin()
+//    StopUsingOutputPin()
+//    ChangeOutputFormat()
+//    ChangeMediaType()
+//    DynamicReconnect()
+//
+// The following class members can only be called by the application thread.
+//
+//    Block()
+//    SynchronousBlockOutputPin()
+//    AsynchronousBlockOutputPin()
+//
+
+CDynamicOutputPin::CDynamicOutputPin(
+    __in_opt LPCTSTR pObjectName,
+    __in CBaseFilter *pFilter,
+    __in CCritSec *pLock,
+    __inout HRESULT *phr,
+    __in_opt LPCWSTR pName) :
+        CBaseOutputPin(pObjectName, pFilter, pLock, phr, pName),
+        m_hStopEvent(NULL),
+        m_pGraphConfig(NULL),
+        m_bPinUsesReadOnlyAllocator(FALSE),
+        m_BlockState(NOT_BLOCKED),
+        m_hUnblockOutputPinEvent(NULL),
+        m_hNotifyCallerPinBlockedEvent(NULL),
+        m_dwBlockCallerThreadID(0),
+        m_dwNumOutstandingOutputPinUsers(0)
+{
+    HRESULT hr = Initialize();
+    if( FAILED( hr ) ) {
+        *phr = hr;
+        return;
+    }
+}
+
+#ifdef UNICODE
+CDynamicOutputPin::CDynamicOutputPin(
+    __in_opt LPCSTR pObjectName,
+    __in CBaseFilter *pFilter,
+    __in CCritSec *pLock,
+    __inout HRESULT *phr,
+    __in_opt LPCWSTR pName) :
+        CBaseOutputPin(pObjectName, pFilter, pLock, phr, pName),
+        m_hStopEvent(NULL),
+        m_pGraphConfig(NULL),
+        m_bPinUsesReadOnlyAllocator(FALSE),
+        m_BlockState(NOT_BLOCKED),
+        m_hUnblockOutputPinEvent(NULL),
+        m_hNotifyCallerPinBlockedEvent(NULL),
+        m_dwBlockCallerThreadID(0),
+        m_dwNumOutstandingOutputPinUsers(0)
+{
+    HRESULT hr = Initialize();
+    if( FAILED( hr ) ) {
+        *phr = hr;
+        return;
+    }
+}
+#endif
+
+CDynamicOutputPin::~CDynamicOutputPin()
+{
+    if(NULL != m_hUnblockOutputPinEvent) {
+        // This call should not fail because we have access to m_hUnblockOutputPinEvent
+        // and m_hUnblockOutputPinEvent is a valid event.
+        EXECUTE_ASSERT(::CloseHandle(m_hUnblockOutputPinEvent));
+    }
+
+    if(NULL != m_hNotifyCallerPinBlockedEvent) {
+        // This call should not fail because we have access to m_hNotifyCallerPinBlockedEvent
+        // and m_hNotifyCallerPinBlockedEvent is a valid event.
+        EXECUTE_ASSERT(::CloseHandle(m_hNotifyCallerPinBlockedEvent));
+    }
+}
+
+HRESULT CDynamicOutputPin::Initialize(void)
+{
+    m_hUnblockOutputPinEvent = ::CreateEvent( NULL,   // The event will have the default security descriptor.
+                                              TRUE,   // This is a manual reset event.
+                                              TRUE,   // The event is initially signaled.
+                                              NULL ); // The event is not named.
+
+    // CreateEvent() returns NULL if an error occurs.
+    if(NULL == m_hUnblockOutputPinEvent) {
+        return AmGetLastErrorToHResult();
+    }
+
+    //  Set flag to say we can reconnect while streaming.
+    SetReconnectWhenActive(true);
+
+    return S_OK;
+}
+
+STDMETHODIMP CDynamicOutputPin::NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv)
+{
+    if(riid == IID_IPinFlowControl) {
+        return GetInterface(static_cast<IPinFlowControl*>(this), ppv);
+    } else {
+        return CBaseOutputPin::NonDelegatingQueryInterface(riid, ppv);
+    }
+}
+
+STDMETHODIMP CDynamicOutputPin::Disconnect(void)
+{
+    CAutoLock cObjectLock(m_pLock);
+    return DisconnectInternal();
+}
+
+STDMETHODIMP CDynamicOutputPin::Block(DWORD dwBlockFlags, HANDLE hEvent)
+{
+    const DWORD VALID_FLAGS = AM_PIN_FLOW_CONTROL_BLOCK;
+
+    // Check for illegal flags.
+    if(dwBlockFlags & ~VALID_FLAGS) {
+        return E_INVALIDARG;
+    }
+
+    // Make sure the event is unsignaled.
+    if((dwBlockFlags & AM_PIN_FLOW_CONTROL_BLOCK) && (NULL != hEvent)) {
+        if( !::ResetEvent( hEvent ) ) {
+            return AmGetLastErrorToHResult();
+        }
+    }
+
+    // No flags are set if we are unblocking the output pin.
+    if(0 == dwBlockFlags) {
+
+        // This parameter should be NULL because unblock operations are always synchronous.
+        // There is no need to notify the caller when the event is done.
+        if(NULL != hEvent) {
+            return E_INVALIDARG;
+        }
+    }
+
+    #ifdef DEBUG
+    AssertValid();
+    #endif // DEBUG
+
+    HRESULT hr;
+
+    if(dwBlockFlags & AM_PIN_FLOW_CONTROL_BLOCK) {
+        // IPinFlowControl::Block()'s hEvent parameter is NULL if the block is synchronous.
+        // If hEvent is not NULL, the block is asynchronous.
+        if(NULL == hEvent) {
+            hr = SynchronousBlockOutputPin();
+        } else {
+            hr = AsynchronousBlockOutputPin(hEvent);
+        }
+    } else {
+        hr = UnblockOutputPin();
+    }
+
+    #ifdef DEBUG
+    AssertValid();
+    #endif // DEBUG
+
+    if(FAILED(hr)) {
+        return hr;
+    }
+
+    return S_OK;
+}
+
+HRESULT CDynamicOutputPin::SynchronousBlockOutputPin(void)
+{
+    HANDLE hNotifyCallerPinBlockedEvent = :: CreateEvent( NULL,   // The event will have the default security attributes.
+                                                          FALSE,  // This is an automatic reset event.
+                                                          FALSE,  // The event is initially unsignaled.
+                                                          NULL ); // The event is not named.
+
+    // CreateEvent() returns NULL if an error occurs.
+    if(NULL == hNotifyCallerPinBlockedEvent) {
+        return AmGetLastErrorToHResult();
+    }
+
+    HRESULT hr = AsynchronousBlockOutputPin(hNotifyCallerPinBlockedEvent);
+    if(FAILED(hr)) {
+        // This call should not fail because we have access to hNotifyCallerPinBlockedEvent
+        // and hNotifyCallerPinBlockedEvent is a valid event.
+        EXECUTE_ASSERT(::CloseHandle(hNotifyCallerPinBlockedEvent));
+
+        return hr;
+    }
+
+    hr = WaitEvent(hNotifyCallerPinBlockedEvent);
+
+    // This call should not fail because we have access to hNotifyCallerPinBlockedEvent
+    // and hNotifyCallerPinBlockedEvent is a valid event.
+    EXECUTE_ASSERT(::CloseHandle(hNotifyCallerPinBlockedEvent));
+
+    if(FAILED(hr)) {
+        return hr;
+    }
+
+    return S_OK;
+}
+
+HRESULT CDynamicOutputPin::AsynchronousBlockOutputPin(HANDLE hNotifyCallerPinBlockedEvent)
+{
+    // This function holds the m_BlockStateLock because it uses
+    // m_dwBlockCallerThreadID, m_BlockState and
+    // m_hNotifyCallerPinBlockedEvent.
+    CAutoLock alBlockStateLock(&m_BlockStateLock);
+
+    if(NOT_BLOCKED != m_BlockState) {
+        if(m_dwBlockCallerThreadID == ::GetCurrentThreadId()) {
+            return VFW_E_PIN_ALREADY_BLOCKED_ON_THIS_THREAD;
+        } else {
+            return VFW_E_PIN_ALREADY_BLOCKED;
+        }
+    }
+
+    BOOL fSuccess = ::DuplicateHandle( ::GetCurrentProcess(),
+                                       hNotifyCallerPinBlockedEvent,
+                                       ::GetCurrentProcess(),
+                                       &m_hNotifyCallerPinBlockedEvent,
+                                       EVENT_MODIFY_STATE,
+                                       FALSE,
+                                       0 );
+    if( !fSuccess ) {
+        return AmGetLastErrorToHResult();
+    }
+
+    m_BlockState = PENDING;
+    m_dwBlockCallerThreadID = ::GetCurrentThreadId();
+
+    // The output pin cannot be blocked if the streaming thread is
+    // calling IPin::NewSegment(), IPin::EndOfStream(), IMemInputPin::Receive()
+    // or IMemInputPin::ReceiveMultiple() on the connected input pin.  Also, it
+    // cannot be blocked if the streaming thread is calling DynamicReconnect(),
+    // ChangeMediaType() or ChangeOutputFormat().
+    if(!StreamingThreadUsingOutputPin()) {
+
+        // The output pin can be immediately blocked.
+        BlockOutputPin();
+    }
+
+    return S_OK;
+}
+
+void CDynamicOutputPin::BlockOutputPin(void)
+{
+    // The caller should always hold the m_BlockStateLock because this function
+    // uses m_BlockState and m_hNotifyCallerPinBlockedEvent.
+    ASSERT(CritCheckIn(&m_BlockStateLock));
+
+    // This function should not be called if the streaming thread is modifying
+    // the connection state or it's passing data downstream.
+    ASSERT(!StreamingThreadUsingOutputPin());
+
+    // This should not fail because we successfully created the event
+    // and we have the security permissions to change it's state.
+    EXECUTE_ASSERT(::ResetEvent(m_hUnblockOutputPinEvent));
+
+    // This event should not fail because AsynchronousBlockOutputPin() successfully
+    // duplicated this handle and we have the appropriate security permissions.
+    EXECUTE_ASSERT(::SetEvent(m_hNotifyCallerPinBlockedEvent));
+    EXECUTE_ASSERT(::CloseHandle(m_hNotifyCallerPinBlockedEvent));
+
+    m_BlockState = BLOCKED;
+    m_hNotifyCallerPinBlockedEvent = NULL;
+}
+
+HRESULT CDynamicOutputPin::UnblockOutputPin(void)
+{
+    // UnblockOutputPin() holds the m_BlockStateLock because it
+    // uses m_BlockState, m_dwBlockCallerThreadID and
+    // m_hNotifyCallerPinBlockedEvent.
+    CAutoLock alBlockStateLock(&m_BlockStateLock);
+
+    if(NOT_BLOCKED == m_BlockState) {
+        return S_FALSE;
+    }
+
+    // This should not fail because we successfully created the event
+    // and we have the security permissions to change it's state.
+    EXECUTE_ASSERT(::SetEvent(m_hUnblockOutputPinEvent));
+
+    // Cancel the block operation if it's still pending.
+    if(NULL != m_hNotifyCallerPinBlockedEvent) {
+        // This event should not fail because AsynchronousBlockOutputPin() successfully
+        // duplicated this handle and we have the appropriate security permissions.
+        EXECUTE_ASSERT(::SetEvent(m_hNotifyCallerPinBlockedEvent));
+        EXECUTE_ASSERT(::CloseHandle(m_hNotifyCallerPinBlockedEvent));
+    }
+
+    m_BlockState = NOT_BLOCKED;
+    m_dwBlockCallerThreadID = 0;
+    m_hNotifyCallerPinBlockedEvent = NULL;
+
+    return S_OK;
+}
+
+HRESULT CDynamicOutputPin::StartUsingOutputPin(void)
+{
+    // The caller should not hold m_BlockStateLock.  If the caller does,
+    // a deadlock could occur.
+    ASSERT(CritCheckOut(&m_BlockStateLock));
+
+    CAutoLock alBlockStateLock(&m_BlockStateLock);
+
+    #ifdef DEBUG
+    AssertValid();
+    #endif // DEBUG
+
+    // Are we in the middle of a block operation?
+    while(BLOCKED == m_BlockState) {
+        m_BlockStateLock.Unlock();
+
+        // If this ASSERT fires, a deadlock could occur.  The caller should make sure
+        // that this thread never acquires the Block State lock more than once.
+        ASSERT(CritCheckOut( &m_BlockStateLock ));
+
+        // WaitForMultipleObjects() returns WAIT_OBJECT_0 if the unblock event
+        // is fired.  It returns WAIT_OBJECT_0 + 1 if the stop event if fired.
+        // See the Windows SDK documentation for more information on
+        // WaitForMultipleObjects().
+        const DWORD UNBLOCK = WAIT_OBJECT_0;
+        const DWORD STOP = WAIT_OBJECT_0 + 1;
+
+        HANDLE ahWaitEvents[] = { m_hUnblockOutputPinEvent, m_hStopEvent };
+        DWORD dwNumWaitEvents = sizeof(ahWaitEvents)/sizeof(HANDLE);
+
+        DWORD dwReturnValue = ::WaitForMultipleObjects( dwNumWaitEvents, ahWaitEvents, FALSE, INFINITE );
+
+        m_BlockStateLock.Lock();
+
+        #ifdef DEBUG
+        AssertValid();
+        #endif // DEBUG
+
+        switch( dwReturnValue ) {
+        case UNBLOCK:
+            break;
+
+        case STOP:
+            return VFW_E_STATE_CHANGED;
+
+        case WAIT_FAILED:
+            return AmGetLastErrorToHResult();
+
+        default:
+            DbgBreak( "An Unexpected case occured in CDynamicOutputPin::StartUsingOutputPin()." );
+            return E_UNEXPECTED;
+        }
+    }
+
+    m_dwNumOutstandingOutputPinUsers++;
+
+    #ifdef DEBUG
+    AssertValid();
+    #endif // DEBUG
+
+    return S_OK;
+}
+
+void CDynamicOutputPin::StopUsingOutputPin(void)
+{
+    CAutoLock alBlockStateLock(&m_BlockStateLock);
+
+    #ifdef DEBUG
+    AssertValid();
+    #endif // DEBUG
+
+    m_dwNumOutstandingOutputPinUsers--;
+
+    if((m_dwNumOutstandingOutputPinUsers == 0) && (NOT_BLOCKED != m_BlockState)) {
+        BlockOutputPin();
+    }
+
+    #ifdef DEBUG
+    AssertValid();
+    #endif // DEBUG
+}
+
+bool CDynamicOutputPin::StreamingThreadUsingOutputPin(void)
+{
+    CAutoLock alBlockStateLock(&m_BlockStateLock);
+
+    return (m_dwNumOutstandingOutputPinUsers > 0);
+}
+
+void CDynamicOutputPin::SetConfigInfo(IGraphConfig *pGraphConfig, HANDLE hStopEvent)
+{
+    // This pointer is not addrefed because filters are not allowed to
+    // hold references to the filter graph manager.  See the documentation for
+    // IBaseFilter::JoinFilterGraph() in the Direct Show SDK for more information.
+    m_pGraphConfig = pGraphConfig;
+
+    m_hStopEvent = hStopEvent;
+}
+
+HRESULT CDynamicOutputPin::Active(void)
+{
+    // Make sure the user initialized the object by calling SetConfigInfo().
+    if((NULL == m_hStopEvent) || (NULL == m_pGraphConfig)) {
+        DbgBreak( ERROR: CDynamicOutputPin::Active() failed because m_pGraphConfig and m_hStopEvent were not initialized.  Call SetConfigInfo() to initialize them. );
+        return E_FAIL;
+    }
+
+    // If this ASSERT fires, the user may have passed an invalid event handle to SetConfigInfo().
+    // The ASSERT can also fire if the event if destroyed and then Active() is called.  An event
+    // handle is invalid if 1) the event does not exist or the user does not have the security
+    // permissions to use the event.
+    EXECUTE_ASSERT(ResetEvent(m_hStopEvent));
+
+    return CBaseOutputPin::Active();
+}
+
+HRESULT CDynamicOutputPin::Inactive(void)
+{
+    // If this ASSERT fires, the user may have passed an invalid event handle to SetConfigInfo().
+    // The ASSERT can also fire if the event if destroyed and then Active() is called.  An event
+    // handle is invalid if 1) the event does not exist or the user does not have the security
+    // permissions to use the event.
+    EXECUTE_ASSERT(SetEvent(m_hStopEvent));
+
+    return CBaseOutputPin::Inactive();
+}
+
+HRESULT CDynamicOutputPin::DeliverBeginFlush(void)
+{
+    // If this ASSERT fires, the user may have passed an invalid event handle to SetConfigInfo().
+    // The ASSERT can also fire if the event if destroyed and then DeliverBeginFlush() is called.
+    // An event handle is invalid if 1) the event does not exist or the user does not have the security
+    // permissions to use the event.
+    EXECUTE_ASSERT(SetEvent(m_hStopEvent));
+
+    return CBaseOutputPin::DeliverBeginFlush();
+}
+
+HRESULT CDynamicOutputPin::DeliverEndFlush(void)
+{
+    // If this ASSERT fires, the user may have passed an invalid event handle to SetConfigInfo().
+    // The ASSERT can also fire if the event if destroyed and then DeliverBeginFlush() is called.
+    // An event handle is invalid if 1) the event does not exist or the user does not have the security
+    // permissions to use the event.
+    EXECUTE_ASSERT(ResetEvent(m_hStopEvent));
+
+    return CBaseOutputPin::DeliverEndFlush();
+}
+
+
+// ChangeOutputFormat() either dynamicly changes the connection's format type or it dynamicly
+// reconnects the output pin.
+HRESULT CDynamicOutputPin::ChangeOutputFormat
+    (
+    const AM_MEDIA_TYPE *pmt,
+    REFERENCE_TIME tSegmentStart,
+    REFERENCE_TIME tSegmentStop,
+    double dSegmentRate
+    )
+{
+    // The caller should call StartUsingOutputPin() before calling this
+    // method.
+    ASSERT(StreamingThreadUsingOutputPin());
+
+    // Callers should always pass a valid media type to ChangeOutputFormat() .
+    ASSERT(NULL != pmt);
+
+    CMediaType cmt(*pmt);
+    HRESULT hr = ChangeMediaType(&cmt);
+    if (FAILED(hr)) {
+        return hr;
+    }
+
+    hr = DeliverNewSegment(tSegmentStart, tSegmentStop, dSegmentRate);
+    if( FAILED( hr ) ) {
+        return hr;
+    }
+
+    return S_OK;
+}
+
+HRESULT CDynamicOutputPin::ChangeMediaType(const CMediaType *pmt)
+{
+    // The caller should call StartUsingOutputPin() before calling this
+    // method.
+    ASSERT(StreamingThreadUsingOutputPin());
+
+    // This function assumes the filter graph is running.
+    ASSERT(!IsStopped());
+
+    if(!IsConnected()) {
+        return VFW_E_NOT_CONNECTED;
+    }
+
+    /*  First check if the downstream pin will accept a dynamic
+        format change
+    */
+    QzCComPtr<IPinConnection> pConnection;
+
+    m_Connected->QueryInterface(IID_IPinConnection, (void **)&pConnection);
+    if(pConnection != NULL) {
+
+        if(S_OK == pConnection->DynamicQueryAccept(pmt)) {
+
+            HRESULT hr = ChangeMediaTypeHelper(pmt);
+            if(FAILED(hr)) {
+                return hr;
+            }
+
+            return S_OK;
+        }
+    }
+
+    /*  Can't do the dynamic connection */
+    return DynamicReconnect(pmt);
+}
+
+HRESULT CDynamicOutputPin::ChangeMediaTypeHelper(const CMediaType *pmt)
+{
+    // The caller should call StartUsingOutputPin() before calling this
+    // method.
+    ASSERT(StreamingThreadUsingOutputPin());
+
+    HRESULT hr = m_Connected->ReceiveConnection(this, pmt);
+    if(FAILED(hr)) {
+        return hr;
+    }
+
+    hr = SetMediaType(pmt);
+    if(FAILED(hr)) {
+        return hr;
+    }
+
+    // Does this pin use the local memory transport?
+    if(NULL != m_pInputPin) {
+        // This function assumes that m_pInputPin and m_Connected are
+        // two different interfaces to the same object.
+        ASSERT(::IsEqualObject(m_Connected, m_pInputPin));
+
+        ALLOCATOR_PROPERTIES apInputPinRequirements;
+        apInputPinRequirements.cbAlign = 0;
+        apInputPinRequirements.cbBuffer = 0;
+        apInputPinRequirements.cbPrefix = 0;
+        apInputPinRequirements.cBuffers = 0;
+
+        m_pInputPin->GetAllocatorRequirements(&apInputPinRequirements);
+
+        // A zero allignment does not make any sense.
+        if(0 == apInputPinRequirements.cbAlign) {
+            apInputPinRequirements.cbAlign = 1;
+        }
+
+        hr = m_pAllocator->Decommit();
+        if(FAILED(hr)) {
+            return hr;
+        }
+
+        hr = DecideBufferSize(m_pAllocator,  &apInputPinRequirements);
+        if(FAILED(hr)) {
+            return hr;
+        }
+
+        hr = m_pAllocator->Commit();
+        if(FAILED(hr)) {
+            return hr;
+        }
+
+        hr = m_pInputPin->NotifyAllocator(m_pAllocator, m_bPinUsesReadOnlyAllocator);
+        if(FAILED(hr)) {
+            return hr;
+        }
+    }
+
+    return S_OK;
+}
+
+// this method has to be called from the thread that is pushing data,
+// and it's the caller's responsibility to make sure that the thread
+// has no outstand samples because they cannot be delivered after a
+// reconnect
+//
+HRESULT CDynamicOutputPin::DynamicReconnect( const CMediaType* pmt )
+{
+    // The caller should call StartUsingOutputPin() before calling this
+    // method.
+    ASSERT(StreamingThreadUsingOutputPin());
+
+    if((m_pGraphConfig == NULL) || (NULL == m_hStopEvent)) {
+        return E_FAIL;
+    }
+
+    HRESULT hr = m_pGraphConfig->Reconnect(
+        this,
+        NULL,
+        pmt,
+        NULL,
+        m_hStopEvent,
+        AM_GRAPH_CONFIG_RECONNECT_CACHE_REMOVED_FILTERS );
+
+    return hr;
+}
+
+HRESULT CDynamicOutputPin::CompleteConnect(IPin *pReceivePin)
+{
+    HRESULT hr = CBaseOutputPin::CompleteConnect(pReceivePin);
+    if(SUCCEEDED(hr)) {
+        if(!IsStopped() && m_pAllocator) {
+            hr = m_pAllocator->Commit();
+            ASSERT(hr != VFW_E_ALREADY_COMMITTED);
+        }
+    }
+
+    return hr;
+}
+
+#ifdef DEBUG
+void CDynamicOutputPin::AssertValid(void)
+{
+    // Make sure the object was correctly initialized.
+
+    // This ASSERT only fires if the object failed to initialize
+    // and the user ignored the constructor's return code (phr).
+    ASSERT(NULL != m_hUnblockOutputPinEvent);
+
+    // If either of these ASSERTs fire, the user did not correctly call
+    // SetConfigInfo().
+    ASSERT(NULL != m_hStopEvent);
+    ASSERT(NULL != m_pGraphConfig);
+
+    // Make sure the block state is consistent.
+
+    CAutoLock alBlockStateLock(&m_BlockStateLock);
+
+    // BLOCK_STATE variables only have three legal values: PENDING, BLOCKED and NOT_BLOCKED.
+    ASSERT((NOT_BLOCKED == m_BlockState) || (PENDING == m_BlockState) || (BLOCKED == m_BlockState));
+
+    // m_hNotifyCallerPinBlockedEvent is only needed when a block operation cannot complete
+    // immediately.
+    ASSERT(((NULL == m_hNotifyCallerPinBlockedEvent) && (PENDING != m_BlockState)) ||
+           ((NULL != m_hNotifyCallerPinBlockedEvent) && (PENDING == m_BlockState)) );
+
+    // m_dwBlockCallerThreadID should always be 0 if the pin is not blocked and
+    // the user is not trying to block the pin.
+    ASSERT((0 == m_dwBlockCallerThreadID) || (NOT_BLOCKED != m_BlockState));
+
+    // If this ASSERT fires, the streaming thread is using the output pin and the
+    // output pin is blocked.
+    ASSERT(((0 != m_dwNumOutstandingOutputPinUsers) && (BLOCKED != m_BlockState)) ||
+           ((0 == m_dwNumOutstandingOutputPinUsers) && (NOT_BLOCKED != m_BlockState)) ||
+           ((0 == m_dwNumOutstandingOutputPinUsers) && (NOT_BLOCKED == m_BlockState)) );
+}
+#endif // DEBUG
+
+HRESULT CDynamicOutputPin::WaitEvent(HANDLE hEvent)
+{
+    const DWORD EVENT_SIGNALED = WAIT_OBJECT_0;
+
+    DWORD dwReturnValue = ::WaitForSingleObject(hEvent, INFINITE);
+
+    switch( dwReturnValue ) {
+    case EVENT_SIGNALED:
+        return S_OK;
+
+    case WAIT_FAILED:
+        return AmGetLastErrorToHResult();
+
+    default:
+        DbgBreak( "An Unexpected case occured in CDynamicOutputPin::WaitEvent()." );
+        return E_UNEXPECTED;
+    }
+}
+
+//=====================================================================
+//=====================================================================
+// Implements CBaseAllocator
+//=====================================================================
+//=====================================================================
+
+
+/* Constructor overrides the default settings for the free list to request
+   that it be alertable (ie the list can be cast to a handle which can be
+   passed to WaitForSingleObject). Both of the allocator lists also ask for
+   object locking, the all list matches the object default settings but I
+   have included them here just so it is obvious what kind of list it is */
+
+CBaseAllocator::CBaseAllocator(__in_opt LPCTSTR pName,
+                               __inout_opt LPUNKNOWN pUnk,
+                               __inout HRESULT *phr,
+                               BOOL bEvent,
+                               BOOL fEnableReleaseCallback
+                               ) :
+    CUnknown(pName, pUnk),
+    m_lAllocated(0),
+    m_bChanged(FALSE),
+    m_bCommitted(FALSE),
+    m_bDecommitInProgress(FALSE),
+    m_lSize(0),
+    m_lCount(0),
+    m_lAlignment(0),
+    m_lPrefix(0),
+    m_hSem(NULL),
+    m_lWaiting(0),
+    m_fEnableReleaseCallback(fEnableReleaseCallback),
+    m_pNotify(NULL)
+{
+#ifdef DXMPERF
+    PERFLOG_CTOR( pName ? pName : L"CBaseAllocator", (IMemAllocator *) this );
+#endif // DXMPERF
+
+    if (bEvent) {
+        m_hSem = CreateSemaphore(NULL, 0, 0x7FFFFFFF, NULL);
+        if (m_hSem == NULL) {
+            *phr = E_OUTOFMEMORY;
+            return;
+        }
+    }
+}
+
+#ifdef UNICODE
+CBaseAllocator::CBaseAllocator(__in_opt LPCSTR pName,
+                               __inout_opt LPUNKNOWN pUnk,
+                               __inout HRESULT *phr,
+                               BOOL bEvent,
+                               BOOL fEnableReleaseCallback) :
+    CUnknown(pName, pUnk),
+    m_lAllocated(0),
+    m_bChanged(FALSE),
+    m_bCommitted(FALSE),
+    m_bDecommitInProgress(FALSE),
+    m_lSize(0),
+    m_lCount(0),
+    m_lAlignment(0),
+    m_lPrefix(0),
+    m_hSem(NULL),
+    m_lWaiting(0),
+    m_fEnableReleaseCallback(fEnableReleaseCallback),
+    m_pNotify(NULL)
+{
+#ifdef DXMPERF
+    PERFLOG_CTOR( L"CBaseAllocator", (IMemAllocator *) this );
+#endif // DXMPERF
+
+    if (bEvent) {
+        m_hSem = CreateSemaphore(NULL, 0, 0x7FFFFFFF, NULL);
+        if (m_hSem == NULL) {
+            *phr = E_OUTOFMEMORY;
+            return;
+        }
+    }
+}
+#endif
+
+/* Destructor */
+
+CBaseAllocator::~CBaseAllocator()
+{
+    // we can't call Decommit here since that would mean a call to a
+    // pure virtual in destructor.
+    // We must assume that the derived class has gone into decommit state in
+    // its destructor.
+#ifdef DXMPERF
+    PERFLOG_DTOR( L"CBaseAllocator", (IMemAllocator *) this );
+#endif // DXMPERF
+
+    ASSERT(!m_bCommitted);
+    if (m_hSem != NULL) {
+        EXECUTE_ASSERT(CloseHandle(m_hSem));
+    }
+    if (m_pNotify) {
+        m_pNotify->Release();
+    }
+}
+
+
+/* Override this to publicise our interfaces */
+
+STDMETHODIMP
+CBaseAllocator::NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv)
+{
+    /* Do we know about this interface */
+
+    if (riid == IID_IMemAllocator ||
+        riid == IID_IMemAllocatorCallbackTemp && m_fEnableReleaseCallback) {
+        return GetInterface((IMemAllocatorCallbackTemp *) this, ppv);
+    } else {
+        return CUnknown::NonDelegatingQueryInterface(riid, ppv);
+    }
+}
+
+
+/* This sets the size and count of the required samples. The memory isn't
+   actually allocated until Commit() is called, if memory has already been
+   allocated then assuming no samples are outstanding the user may call us
+   to change the buffering, the memory will be released in Commit() */
+
+STDMETHODIMP
+CBaseAllocator::SetProperties(
+                __in ALLOCATOR_PROPERTIES* pRequest,
+                __out ALLOCATOR_PROPERTIES* pActual)
+{
+    CheckPointer(pRequest, E_POINTER);
+    CheckPointer(pActual, E_POINTER);
+    ValidateReadWritePtr(pActual, sizeof(ALLOCATOR_PROPERTIES));
+    CAutoLock cObjectLock(this);
+
+    ZeroMemory(pActual, sizeof(ALLOCATOR_PROPERTIES));
+
+    ASSERT(pRequest->cbBuffer > 0);
+
+    /*  Check the alignment requested */
+    if (pRequest->cbAlign != 1) {
+        DbgLog((LOG_ERROR, 2, TEXT("Alignment requested was 0x%x, not 1"),
+               pRequest->cbAlign));
+        return VFW_E_BADALIGN;
+    }
+
+    /* Can't do this if already committed, there is an argument that says we
+       should not reject the SetProperties call if there are buffers still
+       active. However this is called by the source filter, which is the same
+       person who is holding the samples. Therefore it is not unreasonable
+       for them to free all their samples before changing the requirements */
+
+    if (m_bCommitted) {
+        return VFW_E_ALREADY_COMMITTED;
+    }
+
+    /* Must be no outstanding buffers */
+
+    if (m_lAllocated != m_lFree.GetCount()) {
+        return VFW_E_BUFFERS_OUTSTANDING;
+    }
+
+    /* There isn't any real need to check the parameters as they
+       will just be rejected when the user finally calls Commit */
+
+    pActual->cbBuffer = m_lSize = pRequest->cbBuffer;
+    pActual->cBuffers = m_lCount = pRequest->cBuffers;
+    pActual->cbAlign = m_lAlignment = pRequest->cbAlign;
+    pActual->cbPrefix = m_lPrefix = pRequest->cbPrefix;
+
+    m_bChanged = TRUE;
+    return NOERROR;
+}
+
+STDMETHODIMP
+CBaseAllocator::GetProperties(
+    __out ALLOCATOR_PROPERTIES * pActual)
+{
+    CheckPointer(pActual,E_POINTER);
+    ValidateReadWritePtr(pActual,sizeof(ALLOCATOR_PROPERTIES));
+
+    CAutoLock cObjectLock(this);
+    pActual->cbBuffer = m_lSize;
+    pActual->cBuffers = m_lCount;
+    pActual->cbAlign = m_lAlignment;
+    pActual->cbPrefix = m_lPrefix;
+    return NOERROR;
+}
+
+// get container for a sample. Blocking, synchronous call to get the
+// next free buffer (as represented by an IMediaSample interface).
+// on return, the time etc properties will be invalid, but the buffer
+// pointer and size will be correct.
+
+HRESULT CBaseAllocator::GetBuffer(__deref_out IMediaSample **ppBuffer,
+                                  __in_opt REFERENCE_TIME *pStartTime,
+                                  __in_opt REFERENCE_TIME *pEndTime,
+                                  DWORD dwFlags
+                                  )
+{
+    UNREFERENCED_PARAMETER(pStartTime);
+    UNREFERENCED_PARAMETER(pEndTime);
+    UNREFERENCED_PARAMETER(dwFlags);
+    CMediaSample *pSample;
+
+    *ppBuffer = NULL;
+    for (;;)
+    {
+        {  // scope for lock
+            CAutoLock cObjectLock(this);
+
+            /* Check we are committed */
+            if (!m_bCommitted) {
+                return VFW_E_NOT_COMMITTED;
+            }
+            pSample = (CMediaSample *) m_lFree.RemoveHead();
+            if (pSample == NULL) {
+                SetWaiting();
+            }
+        }
+
+        /* If we didn't get a sample then wait for the list to signal */
+
+        if (pSample) {
+            break;
+        }
+        if (dwFlags & AM_GBF_NOWAIT) {
+            return VFW_E_TIMEOUT;
+        }
+        ASSERT(m_hSem != NULL);
+        WaitForSingleObject(m_hSem, INFINITE);
+    }
+
+    /* Addref the buffer up to one. On release
+       back to zero instead of being deleted, it will requeue itself by
+       calling the ReleaseBuffer member function. NOTE the owner of a
+       media sample must always be derived from CBaseAllocator */
+
+
+    ASSERT(pSample->m_cRef == 0);
+    pSample->m_cRef = 1;
+    *ppBuffer = pSample;
+
+#ifdef DXMPERF
+    PERFLOG_GETBUFFER( (IMemAllocator *) this, pSample );
+#endif // DXMPERF
+
+    return NOERROR;
+}
+
+
+/* Final release of a CMediaSample will call this */
+
+STDMETHODIMP
+CBaseAllocator::ReleaseBuffer(IMediaSample * pSample)
+{
+    CheckPointer(pSample,E_POINTER);
+    ValidateReadPtr(pSample,sizeof(IMediaSample));
+
+#ifdef DXMPERF
+    PERFLOG_RELBUFFER( (IMemAllocator *) this, pSample );
+#endif // DXMPERF
+
+
+    BOOL bRelease = FALSE;
+    {
+        CAutoLock cal(this);
+
+        /* Put back on the free list */
+
+        m_lFree.Add((CMediaSample *)pSample);
+        if (m_lWaiting != 0) {
+            NotifySample();
+        }
+
+        // if there is a pending Decommit, then we need to complete it by
+        // calling Free() when the last buffer is placed on the free list
+
+        LONG l1 = m_lFree.GetCount();
+        if (m_bDecommitInProgress && (l1 == m_lAllocated)) {
+            Free();
+            m_bDecommitInProgress = FALSE;
+            bRelease = TRUE;
+        }
+    }
+
+    if (m_pNotify) {
+
+        ASSERT(m_fEnableReleaseCallback);
+
+        //
+        // Note that this is not synchronized with setting up a notification
+        // method.
+        //
+        m_pNotify->NotifyRelease();
+    }
+
+    /* For each buffer there is one AddRef, made in GetBuffer and released
+       here. This may cause the allocator and all samples to be deleted */
+
+    if (bRelease) {
+        Release();
+    }
+    return NOERROR;
+}
+
+STDMETHODIMP
+CBaseAllocator::SetNotify(
+    IMemAllocatorNotifyCallbackTemp* pNotify
+    )
+{
+    ASSERT(m_fEnableReleaseCallback);
+    CAutoLock lck(this);
+    if (pNotify) {
+        pNotify->AddRef();
+    }
+    if (m_pNotify) {
+        m_pNotify->Release();
+    }
+    m_pNotify = pNotify;
+    return S_OK;
+}
+
+STDMETHODIMP
+CBaseAllocator::GetFreeCount(
+    __out LONG* plBuffersFree
+    )
+{
+    ASSERT(m_fEnableReleaseCallback);
+    CAutoLock cObjectLock(this);
+    *plBuffersFree = m_lCount - m_lAllocated + m_lFree.GetCount();
+    return NOERROR;
+}
+
+void
+CBaseAllocator::NotifySample()
+{
+    if (m_lWaiting != 0) {
+        ASSERT(m_hSem != NULL);
+        ReleaseSemaphore(m_hSem, m_lWaiting, 0);
+        m_lWaiting = 0;
+    }
+}
+
+STDMETHODIMP
+CBaseAllocator::Commit()
+{
+    /* Check we are not decommitted */
+    CAutoLock cObjectLock(this);
+
+    // cannot need to alloc or re-alloc if we are committed
+    if (m_bCommitted) {
+        return NOERROR;
+    }
+
+    /* Allow GetBuffer calls */
+
+    m_bCommitted = TRUE;
+
+    // is there a pending decommit ? if so, just cancel it
+    if (m_bDecommitInProgress) {
+        m_bDecommitInProgress = FALSE;
+
+        // don't call Alloc at this point. He cannot allow SetProperties
+        // between Decommit and the last free, so the buffer size cannot have
+        // changed. And because some of the buffers are not free yet, he
+        // cannot re-alloc anyway.
+        return NOERROR;
+    }
+
+    DbgLog((LOG_MEMORY, 1, TEXT("Allocating: %ldx%ld"), m_lCount, m_lSize));
+
+    // actually need to allocate the samples
+    HRESULT hr = Alloc();
+    if (FAILED(hr)) {
+        m_bCommitted = FALSE;
+        return hr;
+    }
+    AddRef();
+    return NOERROR;
+}
+
+
+STDMETHODIMP
+CBaseAllocator::Decommit()
+{
+    BOOL bRelease = FALSE;
+    {
+        /* Check we are not already decommitted */
+        CAutoLock cObjectLock(this);
+        if (m_bCommitted == FALSE) {
+            if (m_bDecommitInProgress == FALSE) {
+                return NOERROR;
+            }
+        }
+
+        /* No more GetBuffer calls will succeed */
+        m_bCommitted = FALSE;
+
+        // are any buffers outstanding?
+        if (m_lFree.GetCount() < m_lAllocated) {
+            // please complete the decommit when last buffer is freed
+            m_bDecommitInProgress = TRUE;
+        } else {
+            m_bDecommitInProgress = FALSE;
+
+            // need to complete the decommit here as there are no
+            // outstanding buffers
+
+            Free();
+            bRelease = TRUE;
+        }
+
+        // Tell anyone waiting that they can go now so we can
+        // reject their call
+#pragma warning(push)
+#ifndef _PREFAST_
+#pragma warning(disable:4068)
+#endif
+#pragma prefast(suppress:__WARNING_DEREF_NULL_PTR, "Suppress warning related to Free() invalidating 'this' which is no applicable to CBaseAllocator::Free()")
+        NotifySample();
+
+#pragma warning(pop)
+    }
+
+    if (bRelease) {
+        Release();
+    }
+    return NOERROR;
+}
+
+
+/* Base definition of allocation which checks we are ok to go ahead and do
+   the full allocation. We return S_FALSE if the requirements are the same */
+
+HRESULT
+CBaseAllocator::Alloc(void)
+{
+    /* Error if he hasn't set the size yet */
+    if (m_lCount <= 0 || m_lSize <= 0 || m_lAlignment <= 0) {
+        return VFW_E_SIZENOTSET;
+    }
+
+    /* should never get here while buffers outstanding */
+    ASSERT(m_lFree.GetCount() == m_lAllocated);
+
+    /* If the requirements haven't changed then don't reallocate */
+    if (m_bChanged == FALSE) {
+        return S_FALSE;
+    }
+
+    return NOERROR;
+}
+
+/*  Implement CBaseAllocator::CSampleList::Remove(pSample)
+    Removes pSample from the list
+*/
+void
+CBaseAllocator::CSampleList::Remove(__inout CMediaSample * pSample)
+{
+    CMediaSample **pSearch;
+    for (pSearch = &m_List;
+         *pSearch != NULL;
+         pSearch = &(CBaseAllocator::NextSample(*pSearch))) {
+       if (*pSearch == pSample) {
+           *pSearch = CBaseAllocator::NextSample(pSample);
+           CBaseAllocator::NextSample(pSample) = NULL;
+           m_nOnList--;
+           return;
+       }
+    }
+    DbgBreak("Couldn't find sample in list");
+}
+
+//=====================================================================
+//=====================================================================
+// Implements CMemAllocator
+//=====================================================================
+//=====================================================================
+
+
+/* This goes in the factory template table to create new instances */
+CUnknown *CMemAllocator::CreateInstance(__inout_opt LPUNKNOWN pUnk, __inout HRESULT *phr)
+{
+    CUnknown *pUnkRet = new CMemAllocator(NAME("CMemAllocator"), pUnk, phr);
+    return pUnkRet;
+}
+
+CMemAllocator::CMemAllocator(
+    __in_opt LPCTSTR pName,
+    __inout_opt LPUNKNOWN pUnk,
+    __inout HRESULT *phr)
+    : CBaseAllocator(pName, pUnk, phr, TRUE, TRUE),
+    m_pBuffer(NULL)
+{
+}
+
+#ifdef UNICODE
+CMemAllocator::CMemAllocator(
+    __in_opt LPCSTR pName,
+    __inout_opt LPUNKNOWN pUnk,
+    __inout HRESULT *phr)
+    : CBaseAllocator(pName, pUnk, phr, TRUE, TRUE),
+    m_pBuffer(NULL)
+{
+}
+#endif
+
+/* This sets the size and count of the required samples. The memory isn't
+   actually allocated until Commit() is called, if memory has already been
+   allocated then assuming no samples are outstanding the user may call us
+   to change the buffering, the memory will be released in Commit() */
+STDMETHODIMP
+CMemAllocator::SetProperties(
+                __in ALLOCATOR_PROPERTIES* pRequest,
+                __out ALLOCATOR_PROPERTIES* pActual)
+{
+    CheckPointer(pActual,E_POINTER);
+    ValidateReadWritePtr(pActual,sizeof(ALLOCATOR_PROPERTIES));
+    CAutoLock cObjectLock(this);
+
+    ZeroMemory(pActual, sizeof(ALLOCATOR_PROPERTIES));
+
+    ASSERT(pRequest->cbBuffer > 0);
+
+    SYSTEM_INFO SysInfo;
+    GetSystemInfo(&SysInfo);
+
+    /*  Check the alignment request is a power of 2 */
+    if ((-pRequest->cbAlign & pRequest->cbAlign) != pRequest->cbAlign) {
+        DbgLog((LOG_ERROR, 1, TEXT("Alignment requested 0x%x not a power of 2!"),
+               pRequest->cbAlign));
+    }
+    /*  Check the alignment requested */
+    if (pRequest->cbAlign == 0 ||
+    (SysInfo.dwAllocationGranularity & (pRequest->cbAlign - 1)) != 0) {
+        DbgLog((LOG_ERROR, 1, TEXT("Invalid alignment 0x%x requested - granularity = 0x%x"),
+               pRequest->cbAlign, SysInfo.dwAllocationGranularity));
+        return VFW_E_BADALIGN;
+    }
+
+    /* Can't do this if already committed, there is an argument that says we
+       should not reject the SetProperties call if there are buffers still
+       active. However this is called by the source filter, which is the same
+       person who is holding the samples. Therefore it is not unreasonable
+       for them to free all their samples before changing the requirements */
+
+    if (m_bCommitted == TRUE) {
+        return VFW_E_ALREADY_COMMITTED;
+    }
+
+    /* Must be no outstanding buffers */
+
+    if (m_lFree.GetCount() < m_lAllocated) {
+        return VFW_E_BUFFERS_OUTSTANDING;
+    }
+
+    /* There isn't any real need to check the parameters as they
+       will just be rejected when the user finally calls Commit */
+
+    // round length up to alignment - remember that prefix is included in
+    // the alignment
+    LONG lSize = pRequest->cbBuffer + pRequest->cbPrefix;
+    LONG lRemainder = lSize % pRequest->cbAlign;
+    if (lRemainder != 0) {
+        lSize = lSize - lRemainder + pRequest->cbAlign;
+    }
+    pActual->cbBuffer = m_lSize = (lSize - pRequest->cbPrefix);
+
+    pActual->cBuffers = m_lCount = pRequest->cBuffers;
+    pActual->cbAlign = m_lAlignment = pRequest->cbAlign;
+    pActual->cbPrefix = m_lPrefix = pRequest->cbPrefix;
+
+    m_bChanged = TRUE;
+    return NOERROR;
+}
+
+// override this to allocate our resources when Commit is called.
+//
+// note that our resources may be already allocated when this is called,
+// since we don't free them on Decommit. We will only be called when in
+// decommit state with all buffers free.
+//
+// object locked by caller
+HRESULT
+CMemAllocator::Alloc(void)
+{
+    CAutoLock lck(this);
+
+    /* Check he has called SetProperties */
+    HRESULT hr = CBaseAllocator::Alloc();
+    if (FAILED(hr)) {
+        return hr;
+    }
+
+    /* If the requirements haven't changed then don't reallocate */
+    if (hr == S_FALSE) {
+        ASSERT(m_pBuffer);
+        return NOERROR;
+    }
+    ASSERT(hr == S_OK); // we use this fact in the loop below
+
+    /* Free the old resources */
+    if (m_pBuffer) {
+        ReallyFree();
+    }
+
+    /* Make sure we've got reasonable values */
+    if ( m_lSize < 0 || m_lPrefix < 0 || m_lCount < 0 ) {
+        return E_OUTOFMEMORY;
+    }
+
+    /* Compute the aligned size */
+    LONG lAlignedSize = m_lSize + m_lPrefix;
+
+    /*  Check overflow */
+    if (lAlignedSize < m_lSize) {
+        return E_OUTOFMEMORY;
+    }
+
+    if (m_lAlignment > 1) {
+        LONG lRemainder = lAlignedSize % m_lAlignment;
+        if (lRemainder != 0) {
+            LONG lNewSize = lAlignedSize + m_lAlignment - lRemainder;
+            if (lNewSize < lAlignedSize) {
+                return E_OUTOFMEMORY;
+            }
+            lAlignedSize = lNewSize;
+        }
+    }
+
+    /* Create the contiguous memory block for the samples
+       making sure it's properly aligned (64K should be enough!)
+    */
+    ASSERT(lAlignedSize % m_lAlignment == 0);
+
+    LONGLONG lToAllocate = m_lCount * (LONGLONG)lAlignedSize;
+
+    /*  Check overflow */
+    if (lToAllocate > MAXLONG) {
+        return E_OUTOFMEMORY;
+    }
+
+    m_pBuffer = (PBYTE)VirtualAlloc(NULL,
+                    (LONG)lToAllocate,
+                    MEM_COMMIT,
+                    PAGE_READWRITE);
+
+    if (m_pBuffer == NULL) {
+        return E_OUTOFMEMORY;
+    }
+
+    LPBYTE pNext = m_pBuffer;
+    CMediaSample *pSample;
+
+    ASSERT(m_lAllocated == 0);
+
+    // Create the new samples - we have allocated m_lSize bytes for each sample
+    // plus m_lPrefix bytes per sample as a prefix. We set the pointer to
+    // the memory after the prefix - so that GetPointer() will return a pointer
+    // to m_lSize bytes.
+    for (; m_lAllocated < m_lCount; m_lAllocated++, pNext += lAlignedSize) {
+
+
+        pSample = new CMediaSample(
+                            NAME("Default memory media sample"),
+                this,
+                            &hr,
+                            pNext + m_lPrefix,      // GetPointer() value
+                            m_lSize);               // not including prefix
+
+            ASSERT(SUCCEEDED(hr));
+        if (pSample == NULL) {
+            return E_OUTOFMEMORY;
+        }
+
+        // This CANNOT fail
+        m_lFree.Add(pSample);
+    }
+
+    m_bChanged = FALSE;
+    return NOERROR;
+}
+
+
+// override this to free up any resources we have allocated.
+// called from the base class on Decommit when all buffers have been
+// returned to the free list.
+//
+// caller has already locked the object.
+
+// in our case, we keep the memory until we are deleted, so
+// we do nothing here. The memory is deleted in the destructor by
+// calling ReallyFree()
+void
+CMemAllocator::Free(void)
+{
+    return;
+}
+
+
+// called from the destructor (and from Alloc if changing size/count) to
+// actually free up the memory
+void
+CMemAllocator::ReallyFree(void)
+{
+    /* Should never be deleting this unless all buffers are freed */
+
+    ASSERT(m_lAllocated == m_lFree.GetCount());
+
+    /* Free up all the CMediaSamples */
+
+    CMediaSample *pSample;
+    for (;;) {
+        pSample = m_lFree.RemoveHead();
+        if (pSample != NULL) {
+            delete pSample;
+        } else {
+            break;
+        }
+    }
+
+    m_lAllocated = 0;
+
+    // free the block of buffer memory
+    if (m_pBuffer) {
+        EXECUTE_ASSERT(VirtualFree(m_pBuffer, 0, MEM_RELEASE));
+        m_pBuffer = NULL;
+    }
+}
+
+
+/* Destructor frees our memory resources */
+
+CMemAllocator::~CMemAllocator()
+{
+    Decommit();
+    ReallyFree();
+}
+
+// ------------------------------------------------------------------------
+// filter registration through IFilterMapper. used if IFilterMapper is
+// not found (Quartz 1.0 install)
+
+STDAPI
+AMovieSetupRegisterFilter( const AMOVIESETUP_FILTER * const psetupdata
+                         , IFilterMapper *                  pIFM
+                         , BOOL                             bRegister  )
+{
+  DbgLog((LOG_TRACE, 3, TEXT("= AMovieSetupRegisterFilter")));
+
+  // check we've got data
+  //
+  if( NULL == psetupdata ) return S_FALSE;
+
+
+  // unregister filter
+  // (as pins are subkeys of filter's CLSID key
+  // they do not need to be removed separately).
+  //
+  DbgLog((LOG_TRACE, 3, TEXT("= = unregister filter")));
+  HRESULT hr = pIFM->UnregisterFilter( *(psetupdata->clsID) );
+
+
+  if( bRegister )
+  {
+    // register filter
+    //
+    DbgLog((LOG_TRACE, 3, TEXT("= = register filter")));
+    hr = pIFM->RegisterFilter( *(psetupdata->clsID)
+                             , psetupdata->strName
+                             , psetupdata->dwMerit    );
+    if( SUCCEEDED(hr) )
+    {
+      // all its pins
+      //
+      DbgLog((LOG_TRACE, 3, TEXT("= = register filter pins")));
+      for( UINT m1=0; m1 < psetupdata->nPins; m1++ )
+      {
+        hr = pIFM->RegisterPin( *(psetupdata->clsID)
+                              , psetupdata->lpPin[m1].strName
+                              , psetupdata->lpPin[m1].bRendered
+                              , psetupdata->lpPin[m1].bOutput
+                              , psetupdata->lpPin[m1].bZero
+                              , psetupdata->lpPin[m1].bMany
+                              , *(psetupdata->lpPin[m1].clsConnectsToFilter)
+                              , psetupdata->lpPin[m1].strConnectsToPin );
+
+        if( SUCCEEDED(hr) )
+        {
+          // and each pin's media types
+          //
+          DbgLog((LOG_TRACE, 3, TEXT("= = register filter pin types")));
+          for( UINT m2=0; m2 < psetupdata->lpPin[m1].nMediaTypes; m2++ )
+          {
+            hr = pIFM->RegisterPinType( *(psetupdata->clsID)
+                                      , psetupdata->lpPin[m1].strName
+                                      , *(psetupdata->lpPin[m1].lpMediaType[m2].clsMajorType)
+                                      , *(psetupdata->lpPin[m1].lpMediaType[m2].clsMinorType) );
+            if( FAILED(hr) ) break;
+          }
+          if( FAILED(hr) ) break;
+        }
+        if( FAILED(hr) ) break;
+      }
+    }
+  }
+
+  // handle one acceptable "error" - that
+  // of filter not being registered!
+  // (couldn't find a suitable #define'd
+  // name for the error!)
+  //
+  if( 0x80070002 == hr)
+    return NOERROR;
+  else
+    return hr;
+}
+
+//  Remove warnings about unreferenced inline functions
+#pragma warning(disable:4514)
+
+#endif /* PJMEDIA_VIDEO_DEV_HAS_DSHOW */
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/amfilter.h b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/amfilter.h
new file mode 100644
index 0000000..14f17cd
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/amfilter.h
@@ -0,0 +1,1587 @@
+//------------------------------------------------------------------------------
+// File: AMFilter.h
+//
+// Desc: DirectShow base classes - efines class hierarchy for streams
+//       architecture.
+//
+// Copyright (c) 1992-2001 Microsoft Corporation.  All rights reserved.
+//------------------------------------------------------------------------------
+
+
+#ifndef __FILTER__
+#define __FILTER__
+
+/* The following classes are declared in this header: */
+
+class CBaseMediaFilter;     // IMediaFilter support
+class CBaseFilter;          // IBaseFilter,IMediaFilter support
+class CBasePin;             // Abstract base class for IPin interface
+class CEnumPins;            // Enumerate input and output pins
+class CEnumMediaTypes;      // Enumerate the pin's preferred formats
+class CBaseOutputPin;       // Adds data provider member functions
+class CBaseInputPin;        // Implements IMemInputPin interface
+class CMediaSample;         // Basic transport unit for IMemInputPin
+class CBaseAllocator;       // General list guff for most allocators
+class CMemAllocator;        // Implements memory buffer allocation
+
+
+//=====================================================================
+//=====================================================================
+//
+// QueryFilterInfo and QueryPinInfo AddRef the interface pointers
+// they return.  You can use the macro below to release the interface.
+//
+//=====================================================================
+//=====================================================================
+
+#define QueryFilterInfoReleaseGraph(fi) if ((fi).pGraph) (fi).pGraph->Release();
+
+#define QueryPinInfoReleaseFilter(pi) if ((pi).pFilter) (pi).pFilter->Release();
+
+//=====================================================================
+//=====================================================================
+// Defines CBaseMediaFilter
+//
+// Abstract base class implementing IMediaFilter.
+//
+// Typically you will derive your filter from CBaseFilter rather than
+// this,  unless you are implementing an object such as a plug-in
+// distributor that needs to support IMediaFilter but not IBaseFilter.
+//
+// Note that IMediaFilter is derived from IPersist to allow query of
+// class id.
+//=====================================================================
+//=====================================================================
+
+class AM_NOVTABLE CBaseMediaFilter : public CUnknown,
+                                     public IMediaFilter
+{
+
+protected:
+
+    FILTER_STATE    m_State;            // current state: running, paused
+    IReferenceClock *m_pClock;          // this filter's reference clock
+    // note: all filters in a filter graph use the same clock
+
+    // offset from stream time to reference time
+    CRefTime        m_tStart;
+
+    CLSID	    m_clsid;            // This filters clsid
+                                        // used for serialization
+    CCritSec        *m_pLock;           // Object we use for locking
+
+public:
+
+    CBaseMediaFilter(
+        __in_opt LPCTSTR pName,
+        __inout_opt LPUNKNOWN pUnk,
+        __in CCritSec  *pLock,
+	REFCLSID   clsid);
+
+    virtual ~CBaseMediaFilter();
+
+    DECLARE_IUNKNOWN
+
+    // override this to say what interfaces we support where
+    STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void ** ppv);
+
+    //
+    // --- IPersist method ---
+    //
+
+    STDMETHODIMP GetClassID(__out CLSID *pClsID);
+
+    // --- IMediaFilter methods ---
+
+    STDMETHODIMP GetState(DWORD dwMSecs, __out FILTER_STATE *State);
+
+    STDMETHODIMP SetSyncSource(__inout_opt IReferenceClock *pClock);
+
+    STDMETHODIMP GetSyncSource(__deref_out_opt IReferenceClock **pClock);
+
+    // default implementation of Stop and Pause just record the
+    // state. Override to activate or de-activate your filter.
+    // Note that Run when called from Stopped state will call Pause
+    // to ensure activation, so if you are a source or transform
+    // you will probably not need to override Run.
+    STDMETHODIMP Stop();
+    STDMETHODIMP Pause();
+
+
+    // the start parameter is the difference to be added to the
+    // sample's stream time to get the reference time for
+    // its presentation
+    STDMETHODIMP Run(REFERENCE_TIME tStart);
+
+    // --- helper methods ---
+
+    // return the current stream time - ie find out what
+    // stream time should be appearing now
+    virtual HRESULT StreamTime(CRefTime& rtStream);
+
+    // Is the filter currently active? (running or paused)
+    BOOL IsActive() {
+        CAutoLock cObjectLock(m_pLock);
+        return ((m_State == State_Paused) || (m_State == State_Running));
+    };
+};
+
+//=====================================================================
+//=====================================================================
+// Defines CBaseFilter
+//
+// An abstract class providing basic IBaseFilter support for pin
+// enumeration and filter information reading.
+//
+// We cannot derive from CBaseMediaFilter since methods in IMediaFilter
+// are also in IBaseFilter and would be ambiguous. Since much of the code
+// assumes that they derive from a class that has m_State and other state
+// directly available, we duplicate code from CBaseMediaFilter rather than
+// having a member variable.
+//
+// Derive your filter from this, or from a derived object such as
+// CTransformFilter.
+//=====================================================================
+//=====================================================================
+
+
+class AM_NOVTABLE CBaseFilter : public CUnknown,        // Handles an IUnknown
+                    public IBaseFilter,     // The Filter Interface
+                    public IAMovieSetup     // For un/registration
+{
+
+friend class CBasePin;
+
+protected:
+    FILTER_STATE    m_State;            // current state: running, paused
+    IReferenceClock *m_pClock;          // this graph's ref clock
+    CRefTime        m_tStart;           // offset from stream time to reference time
+    CLSID	    m_clsid;            // This filters clsid
+                                        // used for serialization
+    CCritSec        *m_pLock;           // Object we use for locking
+
+    WCHAR           *m_pName;           // Full filter name
+    IFilterGraph    *m_pGraph;          // Graph we belong to
+    IMediaEventSink *m_pSink;           // Called with notify events
+    LONG            m_PinVersion;       // Current pin version
+
+public:
+
+    CBaseFilter(
+        __in_opt LPCTSTR pName,   // Object description
+        __inout_opt LPUNKNOWN pUnk,  // IUnknown of delegating object
+        __in CCritSec  *pLock,    // Object who maintains lock
+	REFCLSID   clsid);        // The clsid to be used to serialize this filter
+
+    CBaseFilter(
+        __in_opt LPCTSTR pName,    // Object description
+        __in_opt LPUNKNOWN pUnk,  // IUnknown of delegating object
+        __in CCritSec  *pLock,    // Object who maintains lock
+	REFCLSID   clsid,         // The clsid to be used to serialize this filter
+        __inout HRESULT   *phr);  // General OLE return code
+#ifdef UNICODE
+    CBaseFilter(
+        __in_opt LPCSTR pName,    // Object description
+        __in_opt LPUNKNOWN pUnk,  // IUnknown of delegating object
+        __in CCritSec  *pLock,    // Object who maintains lock
+	REFCLSID   clsid);        // The clsid to be used to serialize this filter
+
+    CBaseFilter(
+        __in_opt LPCSTR pName,     // Object description
+        __in_opt LPUNKNOWN pUnk,  // IUnknown of delegating object
+        __in CCritSec  *pLock,    // Object who maintains lock
+	REFCLSID   clsid,         // The clsid to be used to serialize this filter
+        __inout HRESULT   *phr);  // General OLE return code
+#endif
+    ~CBaseFilter();
+
+    DECLARE_IUNKNOWN
+
+    // override this to say what interfaces we support where
+    STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void ** ppv);
+#ifdef DEBUG
+    STDMETHODIMP_(ULONG) NonDelegatingRelease();
+#endif
+
+    //
+    // --- IPersist method ---
+    //
+
+    STDMETHODIMP GetClassID(__out CLSID *pClsID);
+
+    // --- IMediaFilter methods ---
+
+    STDMETHODIMP GetState(DWORD dwMSecs, __out FILTER_STATE *State);
+
+    STDMETHODIMP SetSyncSource(__in_opt IReferenceClock *pClock);
+
+    STDMETHODIMP GetSyncSource(__deref_out_opt IReferenceClock **pClock);
+
+
+    // override Stop and Pause so we can activate the pins.
+    // Note that Run will call Pause first if activation needed.
+    // Override these if you want to activate your filter rather than
+    // your pins.
+    STDMETHODIMP Stop();
+    STDMETHODIMP Pause();
+
+    // the start parameter is the difference to be added to the
+    // sample's stream time to get the reference time for
+    // its presentation
+    STDMETHODIMP Run(REFERENCE_TIME tStart);
+
+    // --- helper methods ---
+
+    // return the current stream time - ie find out what
+    // stream time should be appearing now
+    virtual HRESULT StreamTime(CRefTime& rtStream);
+
+    // Is the filter currently active?
+    BOOL IsActive() {
+        CAutoLock cObjectLock(m_pLock);
+        return ((m_State == State_Paused) || (m_State == State_Running));
+    };
+
+    // Is this filter stopped (without locking)
+    BOOL IsStopped() {
+        return (m_State == State_Stopped);
+    };
+
+    //
+    // --- IBaseFilter methods ---
+    //
+
+    // pin enumerator
+    STDMETHODIMP EnumPins(
+                    __deref_out IEnumPins ** ppEnum);
+
+
+    // default behaviour of FindPin assumes pin ids are their names
+    STDMETHODIMP FindPin(
+        LPCWSTR Id,
+        __deref_out IPin ** ppPin
+    );
+
+    STDMETHODIMP QueryFilterInfo(
+                    __out FILTER_INFO * pInfo);
+
+    STDMETHODIMP JoinFilterGraph(
+                    __inout_opt IFilterGraph * pGraph,
+                    __in_opt LPCWSTR pName);
+
+    // return a Vendor information string. Optional - may return E_NOTIMPL.
+    // memory returned should be freed using CoTaskMemFree
+    // default implementation returns E_NOTIMPL
+    STDMETHODIMP QueryVendorInfo(
+                    __deref_out LPWSTR* pVendorInfo
+            );
+
+    // --- helper methods ---
+
+    // send an event notification to the filter graph if we know about it.
+    // returns S_OK if delivered, S_FALSE if the filter graph does not sink
+    // events, or an error otherwise.
+    HRESULT NotifyEvent(
+        long EventCode,
+        LONG_PTR EventParam1,
+        LONG_PTR EventParam2);
+
+    // return the filter graph we belong to
+    __out_opt IFilterGraph *GetFilterGraph() {
+        return m_pGraph;
+    }
+
+    // Request reconnect
+    // pPin is the pin to reconnect
+    // pmt is the type to reconnect with - can be NULL
+    // Calls ReconnectEx on the filter graph
+    HRESULT ReconnectPin(IPin *pPin, __in_opt AM_MEDIA_TYPE const *pmt);
+
+    // find out the current pin version (used by enumerators)
+    virtual LONG GetPinVersion();
+    void IncrementPinVersion();
+
+    // you need to supply these to access the pins from the enumerator
+    // and for default Stop and Pause/Run activation.
+    virtual int GetPinCount() PURE;
+    virtual CBasePin *GetPin(int n) PURE;
+
+    // --- IAMovieSetup methods ---
+
+    STDMETHODIMP Register();    // ask filter to register itself
+    STDMETHODIMP Unregister();  // and unregister itself
+
+    // --- setup helper methods ---
+    // (override to return filters setup data)
+
+    virtual __out_opt LPAMOVIESETUP_FILTER GetSetupData(){ return NULL; }
+
+};
+
+
+//=====================================================================
+//=====================================================================
+// Defines CBasePin
+//
+// Abstract class that supports the basics of IPin
+//=====================================================================
+//=====================================================================
+
+class  AM_NOVTABLE CBasePin : public CUnknown, public IPin, public IQualityControl
+{
+
+protected:
+
+    WCHAR *         m_pName;		        // This pin's name
+    IPin            *m_Connected;               // Pin we have connected to
+    PIN_DIRECTION   m_dir;                      // Direction of this pin
+    CCritSec        *m_pLock;                   // Object we use for locking
+    bool            m_bRunTimeError;            // Run time error generated
+    bool            m_bCanReconnectWhenActive;  // OK to reconnect when active
+    bool            m_bTryMyTypesFirst;         // When connecting enumerate
+                                                // this pin's types first
+    CBaseFilter    *m_pFilter;                  // Filter we were created by
+    IQualityControl *m_pQSink;                  // Target for Quality messages
+    LONG            m_TypeVersion;              // Holds current type version
+    CMediaType      m_mt;                       // Media type of connection
+
+    CRefTime        m_tStart;                   // time from NewSegment call
+    CRefTime        m_tStop;                    // time from NewSegment
+    double          m_dRate;                    // rate from NewSegment
+
+#ifdef DEBUG
+    LONG            m_cRef;                     // Ref count tracing
+#endif
+
+    // displays pin connection information
+
+#ifdef DEBUG
+    void DisplayPinInfo(IPin *pReceivePin);
+    void DisplayTypeInfo(IPin *pPin, const CMediaType *pmt);
+#else
+    void DisplayPinInfo(IPin *pReceivePin) {};
+    void DisplayTypeInfo(IPin *pPin, const CMediaType *pmt) {};
+#endif
+
+    // used to agree a media type for a pin connection
+
+    // given a specific media type, attempt a connection (includes
+    // checking that the type is acceptable to this pin)
+    HRESULT
+    AttemptConnection(
+        IPin* pReceivePin,      // connect to this pin
+        const CMediaType* pmt   // using this type
+    );
+
+    // try all the media types in this enumerator - for each that
+    // we accept, try to connect using ReceiveConnection.
+    HRESULT TryMediaTypes(
+                        IPin *pReceivePin,          // connect to this pin
+                        __in_opt const CMediaType *pmt,  // proposed type from Connect
+                        IEnumMediaTypes *pEnum);    // try this enumerator
+
+    // establish a connection with a suitable mediatype. Needs to
+    // propose a media type if the pmt pointer is null or partially
+    // specified - use TryMediaTypes on both our and then the other pin's
+    // enumerator until we find one that works.
+    HRESULT AgreeMediaType(
+                        IPin *pReceivePin,      // connect to this pin
+                        const CMediaType *pmt);      // proposed type from Connect
+
+public:
+
+    CBasePin(
+        __in_opt LPCTSTR pObjectName,         // Object description
+        __in CBaseFilter *pFilter,       // Owning filter who knows about pins
+        __in CCritSec *pLock,            // Object who implements the lock
+        __inout HRESULT *phr,               // General OLE return code
+        __in_opt LPCWSTR pName,              // Pin name for us
+        PIN_DIRECTION dir);         // Either PINDIR_INPUT or PINDIR_OUTPUT
+#ifdef UNICODE
+    CBasePin(
+        __in_opt LPCSTR pObjectName,         // Object description
+        __in CBaseFilter *pFilter,       // Owning filter who knows about pins
+        __in CCritSec *pLock,            // Object who implements the lock
+        __inout HRESULT *phr,               // General OLE return code
+        __in_opt LPCWSTR pName,              // Pin name for us
+        PIN_DIRECTION dir);         // Either PINDIR_INPUT or PINDIR_OUTPUT
+#endif
+    virtual ~CBasePin();
+
+    DECLARE_IUNKNOWN
+
+    STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void ** ppv);
+    STDMETHODIMP_(ULONG) NonDelegatingRelease();
+    STDMETHODIMP_(ULONG) NonDelegatingAddRef();
+
+    // --- IPin methods ---
+
+    // take lead role in establishing a connection. Media type pointer
+    // may be null, or may point to partially-specified mediatype
+    // (subtype or format type may be GUID_NULL).
+    STDMETHODIMP Connect(
+        IPin * pReceivePin,
+        __in_opt const AM_MEDIA_TYPE *pmt   // optional media type
+    );
+
+    // (passive) accept a connection from another pin
+    STDMETHODIMP ReceiveConnection(
+        IPin * pConnector,      // this is the initiating connecting pin
+        const AM_MEDIA_TYPE *pmt   // this is the media type we will exchange
+    );
+
+    STDMETHODIMP Disconnect();
+
+    STDMETHODIMP ConnectedTo(__deref_out IPin **pPin);
+
+    STDMETHODIMP ConnectionMediaType(__out AM_MEDIA_TYPE *pmt);
+
+    STDMETHODIMP QueryPinInfo(
+        __out PIN_INFO * pInfo
+    );
+
+    STDMETHODIMP QueryDirection(
+    	__out PIN_DIRECTION * pPinDir
+    );
+
+    STDMETHODIMP QueryId(
+        __deref_out LPWSTR * Id
+    );
+
+    // does the pin support this media type
+    STDMETHODIMP QueryAccept(
+        const AM_MEDIA_TYPE *pmt
+    );
+
+    // return an enumerator for this pins preferred media types
+    STDMETHODIMP EnumMediaTypes(
+        __deref_out IEnumMediaTypes **ppEnum
+    );
+
+    // return an array of IPin* - the pins that this pin internally connects to
+    // All pins put in the array must be AddReffed (but no others)
+    // Errors: "Can't say" - FAIL, not enough slots - return S_FALSE
+    // Default: return E_NOTIMPL
+    // The filter graph will interpret NOT_IMPL as any input pin connects to
+    // all visible output pins and vice versa.
+    // apPin can be NULL if nPin==0 (not otherwise).
+    STDMETHODIMP QueryInternalConnections(
+        __out_ecount_part(*nPin,*nPin) IPin* *apPin,     // array of IPin*
+        __inout ULONG *nPin                  // on input, the number of slots
+                                             // on output  the number of pins
+    ) { return E_NOTIMPL; }
+
+    // Called when no more data will be sent
+    STDMETHODIMP EndOfStream(void);
+
+    // Begin/EndFlush still PURE
+
+    // NewSegment notifies of the start/stop/rate applying to the data
+    // about to be received. Default implementation records data and
+    // returns S_OK.
+    // Override this to pass downstream.
+    STDMETHODIMP NewSegment(
+                    REFERENCE_TIME tStart,
+                    REFERENCE_TIME tStop,
+                    double dRate);
+
+    //================================================================================
+    // IQualityControl methods
+    //================================================================================
+
+    STDMETHODIMP Notify(IBaseFilter * pSender, Quality q);
+
+    STDMETHODIMP SetSink(IQualityControl * piqc);
+
+    // --- helper methods ---
+
+    // Returns true if the pin is connected. false otherwise.
+    BOOL IsConnected(void) {return (m_Connected != NULL); };
+    // Return the pin this is connected to (if any)
+    IPin * GetConnected() { return m_Connected; };
+
+    // Check if our filter is currently stopped
+    BOOL IsStopped() {
+        return (m_pFilter->m_State == State_Stopped);
+    };
+
+    // find out the current type version (used by enumerators)
+    virtual LONG GetMediaTypeVersion();
+    void IncrementTypeVersion();
+
+    // switch the pin to active (paused or running) mode
+    // not an error to call this if already active
+    virtual HRESULT Active(void);
+
+    // switch the pin to inactive state - may already be inactive
+    virtual HRESULT Inactive(void);
+
+    // Notify of Run() from filter
+    virtual HRESULT Run(REFERENCE_TIME tStart);
+
+    // check if the pin can support this specific proposed type and format
+    virtual HRESULT CheckMediaType(const CMediaType *) PURE;
+
+    // set the connection to use this format (previously agreed)
+    virtual HRESULT SetMediaType(const CMediaType *);
+
+    // check that the connection is ok before verifying it
+    // can be overridden eg to check what interfaces will be supported.
+    virtual HRESULT CheckConnect(IPin *);
+
+    // Set and release resources required for a connection
+    virtual HRESULT BreakConnect();
+    virtual HRESULT CompleteConnect(IPin *pReceivePin);
+
+    // returns the preferred formats for a pin
+    virtual HRESULT GetMediaType(int iPosition, __inout CMediaType *pMediaType);
+
+    // access to NewSegment values
+    REFERENCE_TIME CurrentStopTime() {
+        return m_tStop;
+    }
+    REFERENCE_TIME CurrentStartTime() {
+        return m_tStart;
+    }
+    double CurrentRate() {
+        return m_dRate;
+    }
+
+    //  Access name
+    LPWSTR Name() { return m_pName; };
+
+    //  Can reconnectwhen active?
+    void SetReconnectWhenActive(bool bCanReconnect)
+    {
+        m_bCanReconnectWhenActive = bCanReconnect;
+    }
+
+    bool CanReconnectWhenActive()
+    {
+        return m_bCanReconnectWhenActive;
+    }
+
+protected:
+    STDMETHODIMP DisconnectInternal();
+};
+
+
+//=====================================================================
+//=====================================================================
+// Defines CEnumPins
+//
+// Pin enumerator class that works by calling CBaseFilter. This interface
+// is provided by CBaseFilter::EnumPins and calls GetPinCount() and
+// GetPin() to enumerate existing pins. Needs to be a separate object so
+// that it can be cloned (creating an existing object at the same
+// position in the enumeration)
+//
+//=====================================================================
+//=====================================================================
+
+class CEnumPins : public IEnumPins      // The interface we support
+{
+    int m_Position;                 // Current ordinal position
+    int m_PinCount;                 // Number of pins available
+    CBaseFilter *m_pFilter;         // The filter who owns us
+    LONG m_Version;                 // Pin version information
+    LONG m_cRef;
+
+    typedef CGenericList<CBasePin> CPinList;
+
+    CPinList m_PinCache;	    // These pointers have not been AddRef'ed and
+				    // so they should not be dereferenced.  They are
+				    // merely kept to ID which pins have been enumerated.
+
+#ifdef DEBUG
+    DWORD m_dwCookie;
+#endif
+
+    /* If while we are retrieving a pin for example from the filter an error
+       occurs we assume that our internal state is stale with respect to the
+       filter (someone may have deleted all the pins). We can check before
+       starting whether or not the operation is likely to fail by asking the
+       filter what it's current version number is. If the filter has not
+       overriden the GetPinVersion method then this will always match */
+
+    BOOL AreWeOutOfSync() {
+        return (m_pFilter->GetPinVersion() == m_Version ? FALSE : TRUE);
+    };
+
+    /* This method performs the same operations as Reset, except is does not clear
+       the cache of pins already enumerated. */
+
+    STDMETHODIMP Refresh();
+
+public:
+
+    CEnumPins(
+        __in CBaseFilter *pFilter,
+        __in_opt CEnumPins *pEnumPins);
+
+    virtual ~CEnumPins();
+
+    // IUnknown
+    STDMETHODIMP QueryInterface(REFIID riid, __deref_out void **ppv);
+    STDMETHODIMP_(ULONG) AddRef();
+    STDMETHODIMP_(ULONG) Release();
+
+    // IEnumPins
+    STDMETHODIMP Next(
+        ULONG cPins,         // place this many pins...
+        __out_ecount(cPins) IPin ** ppPins,    // ...in this array of IPin*
+        __out_opt ULONG * pcFetched    // actual count passed returned here
+    );
+
+    STDMETHODIMP Skip(ULONG cPins);
+    STDMETHODIMP Reset();
+    STDMETHODIMP Clone(__deref_out IEnumPins **ppEnum);
+
+
+};
+
+
+//=====================================================================
+//=====================================================================
+// Defines CEnumMediaTypes
+//
+// Enumerates the preferred formats for input and output pins
+//=====================================================================
+//=====================================================================
+
+class CEnumMediaTypes : public IEnumMediaTypes    // The interface we support
+{
+    int m_Position;           // Current ordinal position
+    CBasePin *m_pPin;         // The pin who owns us
+    LONG m_Version;           // Media type version value
+    LONG m_cRef;
+#ifdef DEBUG
+    DWORD m_dwCookie;
+#endif
+
+    /* The media types a filter supports can be quite dynamic so we add to
+       the general IEnumXXXX interface the ability to be signaled when they
+       change via an event handle the connected filter supplies. Until the
+       Reset method is called after the state changes all further calls to
+       the enumerator (except Reset) will return E_UNEXPECTED error code */
+
+    BOOL AreWeOutOfSync() {
+        return (m_pPin->GetMediaTypeVersion() == m_Version ? FALSE : TRUE);
+    };
+
+public:
+
+    CEnumMediaTypes(
+        __in CBasePin *pPin,
+        __in_opt CEnumMediaTypes *pEnumMediaTypes);
+
+    virtual ~CEnumMediaTypes();
+
+    // IUnknown
+    STDMETHODIMP QueryInterface(REFIID riid, __deref_out void **ppv);
+    STDMETHODIMP_(ULONG) AddRef();
+    STDMETHODIMP_(ULONG) Release();
+
+    // IEnumMediaTypes
+    STDMETHODIMP Next(
+        ULONG cMediaTypes,          // place this many pins...
+        __out_ecount(cMediaTypes) AM_MEDIA_TYPE ** ppMediaTypes,  // ...in this array
+        __out_opt ULONG * pcFetched           // actual count passed
+    );
+
+    STDMETHODIMP Skip(ULONG cMediaTypes);
+    STDMETHODIMP Reset();
+    STDMETHODIMP Clone(__deref_out IEnumMediaTypes **ppEnum);
+};
+
+
+
+
+//=====================================================================
+//=====================================================================
+// Defines CBaseOutputPin
+//
+// class derived from CBasePin that can pass buffers to a connected pin
+// that supports IMemInputPin. Supports IPin.
+//
+// Derive your output pin from this.
+//
+//=====================================================================
+//=====================================================================
+
+class  AM_NOVTABLE CBaseOutputPin : public CBasePin
+{
+
+protected:
+
+    IMemAllocator *m_pAllocator;
+    IMemInputPin *m_pInputPin;        // interface on the downstreaminput pin
+                                      // set up in CheckConnect when we connect.
+
+public:
+
+    CBaseOutputPin(
+        __in_opt LPCTSTR pObjectName,
+        __in CBaseFilter *pFilter,
+        __in CCritSec *pLock,
+        __inout HRESULT *phr,
+        __in_opt LPCWSTR pName);
+#ifdef UNICODE
+    CBaseOutputPin(
+        __in_opt LPCSTR pObjectName,
+        __in CBaseFilter *pFilter,
+        __in CCritSec *pLock,
+        __inout HRESULT *phr,
+        __in_opt LPCWSTR pName);
+#endif
+    // override CompleteConnect() so we can negotiate an allocator
+    virtual HRESULT CompleteConnect(IPin *pReceivePin);
+
+    // negotiate the allocator and its buffer size/count and other properties
+    // Calls DecideBufferSize to set properties
+    virtual HRESULT DecideAllocator(IMemInputPin * pPin, __deref_out IMemAllocator ** pAlloc);
+
+    // override this to set the buffer size and count. Return an error
+    // if the size/count is not to your liking.
+    // The allocator properties passed in are those requested by the
+    // input pin - use eg the alignment and prefix members if you have
+    // no preference on these.
+    virtual HRESULT DecideBufferSize(
+        IMemAllocator * pAlloc,
+        __inout ALLOCATOR_PROPERTIES * ppropInputRequest
+    ) PURE;
+
+    // returns an empty sample buffer from the allocator
+    virtual HRESULT GetDeliveryBuffer(__deref_out IMediaSample ** ppSample,
+                                      __in_opt REFERENCE_TIME * pStartTime,
+                                      __in_opt REFERENCE_TIME * pEndTime,
+                                      DWORD dwFlags);
+
+    // deliver a filled-in sample to the connected input pin
+    // note - you need to release it after calling this. The receiving
+    // pin will addref the sample if it needs to hold it beyond the
+    // call.
+    virtual HRESULT Deliver(IMediaSample *);
+
+    // override this to control the connection
+    virtual HRESULT InitAllocator(__deref_out IMemAllocator **ppAlloc);
+    HRESULT CheckConnect(IPin *pPin);
+    HRESULT BreakConnect();
+
+    // override to call Commit and Decommit
+    HRESULT Active(void);
+    HRESULT Inactive(void);
+
+    // we have a default handling of EndOfStream which is to return
+    // an error, since this should be called on input pins only
+    STDMETHODIMP EndOfStream(void);
+
+    // called from elsewhere in our filter to pass EOS downstream to
+    // our connected input pin
+    virtual HRESULT DeliverEndOfStream(void);
+
+    // same for Begin/EndFlush - we handle Begin/EndFlush since it
+    // is an error on an output pin, and we have Deliver methods to
+    // call the methods on the connected pin
+    STDMETHODIMP BeginFlush(void);
+    STDMETHODIMP EndFlush(void);
+    virtual HRESULT DeliverBeginFlush(void);
+    virtual HRESULT DeliverEndFlush(void);
+
+    // deliver NewSegment to connected pin - you will need to
+    // override this if you queue any data in your output pin.
+    virtual HRESULT DeliverNewSegment(
+                        REFERENCE_TIME tStart,
+                        REFERENCE_TIME tStop,
+                        double dRate);
+
+    //================================================================================
+    // IQualityControl methods
+    //================================================================================
+
+    // All inherited from CBasePin and not overridden here.
+    // STDMETHODIMP Notify(IBaseFilter * pSender, Quality q);
+    // STDMETHODIMP SetSink(IQualityControl * piqc);
+};
+
+
+//=====================================================================
+//=====================================================================
+// Defines CBaseInputPin
+//
+// derive your standard input pin from this.
+// you need to supply GetMediaType and CheckConnect etc (see CBasePin),
+// and you need to supply Receive to do something more useful.
+//
+//=====================================================================
+//=====================================================================
+
+class AM_NOVTABLE CBaseInputPin : public CBasePin,
+                                  public IMemInputPin
+{
+
+protected:
+
+    IMemAllocator *m_pAllocator;    // Default memory allocator
+
+    // allocator is read-only, so received samples
+    // cannot be modified (probably only relevant to in-place
+    // transforms
+    BYTE m_bReadOnly;
+
+    // in flushing state (between BeginFlush and EndFlush)
+    // if TRUE, all Receives are returned with S_FALSE
+    BYTE m_bFlushing;
+
+    // Sample properties - initalized in Receive
+    AM_SAMPLE2_PROPERTIES m_SampleProps;
+
+public:
+
+    CBaseInputPin(
+        __in_opt LPCTSTR pObjectName,
+        __in CBaseFilter *pFilter,
+        __in CCritSec *pLock,
+        __inout HRESULT *phr,
+        __in_opt LPCWSTR pName);
+#ifdef UNICODE
+    CBaseInputPin(
+        __in_opt LPCSTR pObjectName,
+        __in CBaseFilter *pFilter,
+        __in CCritSec *pLock,
+        __inout HRESULT *phr,
+        __in_opt LPCWSTR pName);
+#endif
+    virtual ~CBaseInputPin();
+
+    DECLARE_IUNKNOWN
+
+    // override this to publicise our interfaces
+    STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
+
+    // return the allocator interface that this input pin
+    // would like the output pin to use
+    STDMETHODIMP GetAllocator(__deref_out IMemAllocator ** ppAllocator);
+
+    // tell the input pin which allocator the output pin is actually
+    // going to use.
+    STDMETHODIMP NotifyAllocator(
+                    IMemAllocator * pAllocator,
+                    BOOL bReadOnly);
+
+    // do something with this media sample
+    STDMETHODIMP Receive(IMediaSample *pSample);
+
+    // do something with these media samples
+    STDMETHODIMP ReceiveMultiple (
+        __in_ecount(nSamples) IMediaSample **pSamples,
+        long nSamples,
+        __out long *nSamplesProcessed);
+
+    // See if Receive() blocks
+    STDMETHODIMP ReceiveCanBlock();
+
+    // Default handling for BeginFlush - call at the beginning
+    // of your implementation (makes sure that all Receive calls
+    // fail). After calling this, you need to free any queued data
+    // and then call downstream.
+    STDMETHODIMP BeginFlush(void);
+
+    // default handling for EndFlush - call at end of your implementation
+    // - before calling this, ensure that there is no queued data and no thread
+    // pushing any more without a further receive, then call downstream,
+    // then call this method to clear the m_bFlushing flag and re-enable
+    // receives
+    STDMETHODIMP EndFlush(void);
+
+    // this method is optional (can return E_NOTIMPL).
+    // default implementation returns E_NOTIMPL. Override if you have
+    // specific alignment or prefix needs, but could use an upstream
+    // allocator
+    STDMETHODIMP GetAllocatorRequirements(__out ALLOCATOR_PROPERTIES*pProps);
+
+    // Release the pin's allocator.
+    HRESULT BreakConnect();
+
+    // helper method to check the read-only flag
+    BOOL IsReadOnly() {
+        return m_bReadOnly;
+    };
+
+    // helper method to see if we are flushing
+    BOOL IsFlushing() {
+        return m_bFlushing;
+    };
+
+    //  Override this for checking whether it's OK to process samples
+    //  Also call this from EndOfStream.
+    virtual HRESULT CheckStreaming();
+
+    // Pass a Quality notification on to the appropriate sink
+    HRESULT PassNotify(Quality& q);
+
+
+    //================================================================================
+    // IQualityControl methods (from CBasePin)
+    //================================================================================
+
+    STDMETHODIMP Notify(IBaseFilter * pSender, Quality q);
+
+    // no need to override:
+    // STDMETHODIMP SetSink(IQualityControl * piqc);
+
+
+    // switch the pin to inactive state - may already be inactive
+    virtual HRESULT Inactive(void);
+
+    // Return sample properties pointer
+    AM_SAMPLE2_PROPERTIES * SampleProps() {
+        ASSERT(m_SampleProps.cbData != 0);
+        return &m_SampleProps;
+    }
+
+};
+
+///////////////////////////////////////////////////////////////////////////
+// CDynamicOutputPin
+//
+
+class CDynamicOutputPin : public CBaseOutputPin,
+                          public IPinFlowControl
+{
+public:
+#ifdef UNICODE
+    CDynamicOutputPin(
+        __in_opt LPCSTR pObjectName,
+        __in CBaseFilter *pFilter,
+        __in CCritSec *pLock,
+        __inout HRESULT *phr,
+        __in_opt LPCWSTR pName);
+#endif
+
+    CDynamicOutputPin(
+        __in_opt LPCTSTR pObjectName,
+        __in CBaseFilter *pFilter,
+        __in CCritSec *pLock,
+        __inout HRESULT *phr,
+        __in_opt LPCWSTR pName);
+
+    ~CDynamicOutputPin();
+
+    // IUnknown Methods
+    DECLARE_IUNKNOWN
+    STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
+
+    // IPin Methods
+    STDMETHODIMP Disconnect(void);
+
+    // IPinFlowControl Methods
+    STDMETHODIMP Block(DWORD dwBlockFlags, HANDLE hEvent);
+
+    //  Set graph config info
+    void SetConfigInfo(IGraphConfig *pGraphConfig, HANDLE hStopEvent);
+
+    #ifdef DEBUG
+    virtual HRESULT Deliver(IMediaSample *pSample);
+    virtual HRESULT DeliverEndOfStream(void);
+    virtual HRESULT DeliverNewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
+    #endif // DEBUG
+
+    HRESULT DeliverBeginFlush(void);
+    HRESULT DeliverEndFlush(void);
+
+    HRESULT Inactive(void);
+    HRESULT Active(void);
+    virtual HRESULT CompleteConnect(IPin *pReceivePin);
+
+    virtual HRESULT StartUsingOutputPin(void);
+    virtual void StopUsingOutputPin(void);
+    virtual bool StreamingThreadUsingOutputPin(void);
+
+    HRESULT ChangeOutputFormat
+        (
+        const AM_MEDIA_TYPE *pmt,
+        REFERENCE_TIME tSegmentStart,
+        REFERENCE_TIME tSegmentStop,
+        double dSegmentRate
+        );
+    HRESULT ChangeMediaType(const CMediaType *pmt);
+    HRESULT DynamicReconnect(const CMediaType *pmt);
+
+protected:
+    HRESULT SynchronousBlockOutputPin(void);
+    HRESULT AsynchronousBlockOutputPin(HANDLE hNotifyCallerPinBlockedEvent);
+    HRESULT UnblockOutputPin(void);
+
+    void BlockOutputPin(void);
+    void ResetBlockState(void);
+
+    static HRESULT WaitEvent(HANDLE hEvent);
+
+    enum BLOCK_STATE
+    {
+        NOT_BLOCKED,
+        PENDING,
+        BLOCKED
+    };
+
+    // This lock should be held when the following class members are
+    // being used: m_hNotifyCallerPinBlockedEvent, m_BlockState,
+    // m_dwBlockCallerThreadID and m_dwNumOutstandingOutputPinUsers.
+    CCritSec m_BlockStateLock;
+
+    // This event should be signaled when the output pin is
+    // not blocked.  This is a manual reset event.  For more
+    // information on events, see the documentation for
+    // CreateEvent() in the Windows SDK.
+    HANDLE m_hUnblockOutputPinEvent;
+
+    // This event will be signaled when block operation succeedes or
+    // when the user cancels the block operation.  The block operation
+    // can be canceled by calling IPinFlowControl2::Block( 0, NULL )
+    // while the block operation is pending.
+    HANDLE m_hNotifyCallerPinBlockedEvent;
+
+    // The state of the current block operation.
+    BLOCK_STATE m_BlockState;
+
+    // The ID of the thread which last called IPinFlowControl::Block().
+    // For more information on thread IDs, see the documentation for
+    // GetCurrentThreadID() in the Windows SDK.
+    DWORD m_dwBlockCallerThreadID;
+
+    // The number of times StartUsingOutputPin() has been sucessfully
+    // called and a corresponding call to StopUsingOutputPin() has not
+    // been made.  When this variable is greater than 0, the streaming
+    // thread is calling IPin::NewSegment(), IPin::EndOfStream(),
+    // IMemInputPin::Receive() or IMemInputPin::ReceiveMultiple().  The
+    // streaming thread could also be calling: DynamicReconnect(),
+    // ChangeMediaType() or ChangeOutputFormat().  The output pin cannot
+    // be blocked while the output pin is being used.
+    DWORD m_dwNumOutstandingOutputPinUsers;
+
+    // This event should be set when the IMediaFilter::Stop() is called.
+    // This is a manual reset event.  It is also set when the output pin
+    // delivers a flush to the connected input pin.
+    HANDLE m_hStopEvent;
+    IGraphConfig* m_pGraphConfig;
+
+    // TRUE if the output pin's allocator's samples are read only.
+    // Otherwise FALSE.  For more information, see the documentation
+    // for IMemInputPin::NotifyAllocator().
+    BOOL m_bPinUsesReadOnlyAllocator;
+
+private:
+    HRESULT Initialize(void);
+    HRESULT ChangeMediaTypeHelper(const CMediaType *pmt);
+
+    #ifdef DEBUG
+    void AssertValid(void);
+    #endif // DEBUG
+};
+
+class CAutoUsingOutputPin
+{
+public:
+    CAutoUsingOutputPin( __in CDynamicOutputPin* pOutputPin, __inout HRESULT* phr );
+    ~CAutoUsingOutputPin();
+
+private:
+    CDynamicOutputPin* m_pOutputPin;
+};
+
+inline CAutoUsingOutputPin::CAutoUsingOutputPin( __in CDynamicOutputPin* pOutputPin, __inout HRESULT* phr ) :
+    m_pOutputPin(NULL)
+{
+    // The caller should always pass in valid pointers.
+    ASSERT( NULL != pOutputPin );
+    ASSERT( NULL != phr );
+
+    // Make sure the user initialized phr.
+    ASSERT( S_OK == *phr );
+
+    HRESULT hr = pOutputPin->StartUsingOutputPin();
+    if( FAILED( hr ) )
+    {
+        *phr = hr;
+        return;
+    }
+
+    m_pOutputPin = pOutputPin;
+}
+
+inline CAutoUsingOutputPin::~CAutoUsingOutputPin()
+{
+    if( NULL != m_pOutputPin )
+    {
+        m_pOutputPin->StopUsingOutputPin();
+    }
+}
+
+#ifdef DEBUG
+
+inline HRESULT CDynamicOutputPin::Deliver(IMediaSample *pSample)
+{
+    // The caller should call StartUsingOutputPin() before calling this
+    // method.
+    ASSERT(StreamingThreadUsingOutputPin());
+
+    return CBaseOutputPin::Deliver(pSample);
+}
+
+inline HRESULT CDynamicOutputPin::DeliverEndOfStream(void)
+{
+    // The caller should call StartUsingOutputPin() before calling this
+    // method.
+    ASSERT( StreamingThreadUsingOutputPin() );
+
+    return CBaseOutputPin::DeliverEndOfStream();
+}
+
+inline HRESULT CDynamicOutputPin::DeliverNewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
+{
+    // The caller should call StartUsingOutputPin() before calling this
+    // method.
+    ASSERT(StreamingThreadUsingOutputPin());
+
+    return CBaseOutputPin::DeliverNewSegment(tStart, tStop, dRate);
+}
+
+#endif // DEBUG
+
+//=====================================================================
+//=====================================================================
+// Memory allocators
+//
+// the shared memory transport between pins requires the input pin
+// to provide a memory allocator that can provide sample objects. A
+// sample object supports the IMediaSample interface.
+//
+// CBaseAllocator handles the management of free and busy samples. It
+// allocates CMediaSample objects. CBaseAllocator is an abstract class:
+// in particular it has no method of initializing the list of free
+// samples. CMemAllocator is derived from CBaseAllocator and initializes
+// the list of samples using memory from the standard IMalloc interface.
+//
+// If you want your buffers to live in some special area of memory,
+// derive your allocator object from CBaseAllocator. If you derive your
+// IMemInputPin interface object from CBaseMemInputPin, you will get
+// CMemAllocator-based allocation etc for free and will just need to
+// supply the Receive handling, and media type / format negotiation.
+//=====================================================================
+//=====================================================================
+
+
+//=====================================================================
+//=====================================================================
+// Defines CMediaSample
+//
+// an object of this class supports IMediaSample and represents a buffer
+// for media data with some associated properties. Releasing it returns
+// it to a freelist managed by a CBaseAllocator derived object.
+//=====================================================================
+//=====================================================================
+
+class CMediaSample : public IMediaSample2    // The interface we support
+{
+
+protected:
+
+    friend class CBaseAllocator;
+
+    /*  Values for dwFlags - these are used for backward compatiblity
+        only now - use AM_SAMPLE_xxx
+    */
+    enum { Sample_SyncPoint       = 0x01,   /* Is this a sync point */
+           Sample_Preroll         = 0x02,   /* Is this a preroll sample */
+           Sample_Discontinuity   = 0x04,   /* Set if start of new segment */
+           Sample_TypeChanged     = 0x08,   /* Has the type changed */
+           Sample_TimeValid       = 0x10,   /* Set if time is valid */
+           Sample_MediaTimeValid  = 0x20,   /* Is the media time valid */
+           Sample_TimeDiscontinuity = 0x40, /* Time discontinuity */
+           Sample_StopValid       = 0x100,  /* Stop time valid */
+           Sample_ValidFlags      = 0x1FF
+         };
+
+    /* Properties, the media sample class can be a container for a format
+       change in which case we take a copy of a type through the SetMediaType
+       interface function and then return it when GetMediaType is called. As
+       we do no internal processing on it we leave it as a pointer */
+
+    DWORD            m_dwFlags;         /* Flags for this sample */
+                                        /* Type specific flags are packed
+                                           into the top word
+                                        */
+    DWORD            m_dwTypeSpecificFlags; /* Media type specific flags */
+    __field_ecount_opt(m_cbBuffer) LPBYTE           m_pBuffer;         /* Pointer to the complete buffer */
+    LONG             m_lActual;         /* Length of data in this sample */
+    LONG             m_cbBuffer;        /* Size of the buffer */
+    CBaseAllocator  *m_pAllocator;      /* The allocator who owns us */
+    CMediaSample     *m_pNext;          /* Chaining in free list */
+    REFERENCE_TIME   m_Start;           /* Start sample time */
+    REFERENCE_TIME   m_End;             /* End sample time */
+    LONGLONG         m_MediaStart;      /* Real media start position */
+    LONG             m_MediaEnd;        /* A difference to get the end */
+    AM_MEDIA_TYPE    *m_pMediaType;     /* Media type change data */
+    DWORD            m_dwStreamId;      /* Stream id */
+public:
+    LONG             m_cRef;            /* Reference count */
+
+
+public:
+
+    CMediaSample(
+        __in_opt LPCTSTR pName,
+        __in_opt CBaseAllocator *pAllocator,
+        __inout_opt HRESULT *phr,
+        __in_bcount_opt(length) LPBYTE pBuffer = NULL,
+        LONG length = 0);
+#ifdef UNICODE
+    CMediaSample(
+        __in_opt LPCSTR pName,
+        __in_opt CBaseAllocator *pAllocator,
+        __inout_opt HRESULT *phr,
+        __in_bcount_opt(length) LPBYTE pBuffer = NULL,
+        LONG length = 0);
+#endif
+
+    virtual ~CMediaSample();
+
+    /* Note the media sample does not delegate to its owner */
+
+    STDMETHODIMP QueryInterface(REFIID riid, __deref_out void **ppv);
+    STDMETHODIMP_(ULONG) AddRef();
+    STDMETHODIMP_(ULONG) Release();
+
+    // set the buffer pointer and length. Used by allocators that
+    // want variable sized pointers or pointers into already-read data.
+    // This is only available through a CMediaSample* not an IMediaSample*
+    // and so cannot be changed by clients.
+    HRESULT SetPointer(__in_bcount(cBytes) BYTE * ptr, LONG cBytes);
+
+    // Get me a read/write pointer to this buffer's memory.
+    STDMETHODIMP GetPointer(__deref_out BYTE ** ppBuffer);
+
+    STDMETHODIMP_(LONG) GetSize(void);
+
+    // get the stream time at which this sample should start and finish.
+    STDMETHODIMP GetTime(
+        __out REFERENCE_TIME * pTimeStart,     // put time here
+        __out REFERENCE_TIME * pTimeEnd
+    );
+
+    // Set the stream time at which this sample should start and finish.
+    STDMETHODIMP SetTime(
+        __in_opt REFERENCE_TIME * pTimeStart,     // put time here
+        __in_opt REFERENCE_TIME * pTimeEnd
+    );
+    STDMETHODIMP IsSyncPoint(void);
+    STDMETHODIMP SetSyncPoint(BOOL bIsSyncPoint);
+    STDMETHODIMP IsPreroll(void);
+    STDMETHODIMP SetPreroll(BOOL bIsPreroll);
+
+    STDMETHODIMP_(LONG) GetActualDataLength(void);
+    STDMETHODIMP SetActualDataLength(LONG lActual);
+
+    // these allow for limited format changes in band
+
+    STDMETHODIMP GetMediaType(__deref_out AM_MEDIA_TYPE **ppMediaType);
+    STDMETHODIMP SetMediaType(__in_opt AM_MEDIA_TYPE *pMediaType);
+
+    // returns S_OK if there is a discontinuity in the data (this same is
+    // not a continuation of the previous stream of data
+    // - there has been a seek).
+    STDMETHODIMP IsDiscontinuity(void);
+    // set the discontinuity property - TRUE if this sample is not a
+    // continuation, but a new sample after a seek.
+    STDMETHODIMP SetDiscontinuity(BOOL bDiscontinuity);
+
+    // get the media times for this sample
+    STDMETHODIMP GetMediaTime(
+    	__out LONGLONG * pTimeStart,
+	    __out LONGLONG * pTimeEnd
+    );
+
+    // Set the media times for this sample
+    STDMETHODIMP SetMediaTime(
+    	__in_opt LONGLONG * pTimeStart,
+	    __in_opt LONGLONG * pTimeEnd
+    );
+
+    // Set and get properties (IMediaSample2)
+    STDMETHODIMP GetProperties(
+        DWORD cbProperties,
+        __out_bcount(cbProperties) BYTE * pbProperties
+    );
+
+    STDMETHODIMP SetProperties(
+        DWORD cbProperties,
+        __in_bcount(cbProperties) const BYTE * pbProperties
+    );
+};
+
+
+//=====================================================================
+//=====================================================================
+// Defines CBaseAllocator
+//
+// Abstract base class that manages a list of media samples
+//
+// This class provides support for getting buffers from the free list,
+// including handling of commit and (asynchronous) decommit.
+//
+// Derive from this class and override the Alloc and Free functions to
+// allocate your CMediaSample (or derived) objects and add them to the
+// free list, preparing them as necessary.
+//=====================================================================
+//=====================================================================
+
+class AM_NOVTABLE CBaseAllocator : public CUnknown,// A non delegating IUnknown
+                       public IMemAllocatorCallbackTemp, // The interface we support
+                       public CCritSec             // Provides object locking
+{
+    class CSampleList;
+    friend class CSampleList;
+
+    /*  Trick to get at protected member in CMediaSample */
+    static CMediaSample * &NextSample(__in CMediaSample *pSample)
+    {
+        return pSample->m_pNext;
+    };
+
+    /*  Mini list class for the free list */
+    class CSampleList
+    {
+    public:
+        CSampleList() : m_List(NULL), m_nOnList(0) {};
+#ifdef DEBUG
+        ~CSampleList()
+        {
+            ASSERT(m_nOnList == 0);
+        };
+#endif
+        CMediaSample *Head() const { return m_List; };
+        CMediaSample *Next(__in CMediaSample *pSample) const { return CBaseAllocator::NextSample(pSample); };
+        int GetCount() const { return m_nOnList; };
+        void Add(__inout CMediaSample *pSample)
+        {
+            ASSERT(pSample != NULL);
+            CBaseAllocator::NextSample(pSample) = m_List;
+            m_List = pSample;
+            m_nOnList++;
+        };
+        CMediaSample *RemoveHead()
+        {
+            CMediaSample *pSample = m_List;
+            if (pSample != NULL) {
+                m_List = CBaseAllocator::NextSample(m_List);
+                m_nOnList--;
+            }
+            return pSample;
+        };
+        void Remove(__inout CMediaSample *pSample);
+
+    public:
+        CMediaSample *m_List;
+        int           m_nOnList;
+    };
+protected:
+
+    CSampleList m_lFree;        // Free list
+
+    /*  Note to overriders of CBaseAllocator.
+
+        We use a lazy signalling mechanism for waiting for samples.
+        This means we don't call the OS if no waits occur.
+
+        In order to implement this:
+
+        1. When a new sample is added to m_lFree call NotifySample() which
+           calls ReleaseSemaphore on m_hSem with a count of m_lWaiting and
+           sets m_lWaiting to 0.
+           This must all be done holding the allocator's critical section.
+
+        2. When waiting for a sample call SetWaiting() which increments
+           m_lWaiting BEFORE leaving the allocator's critical section.
+
+        3. Actually wait by calling WaitForSingleObject(m_hSem, INFINITE)
+           having left the allocator's critical section.  The effect of
+           this is to remove 1 from the semaphore's count.  You MUST call
+           this once having incremented m_lWaiting.
+
+        The following are then true when the critical section is not held :
+            (let nWaiting = number about to wait or waiting)
+
+            (1) if (m_lFree.GetCount() != 0) then (m_lWaiting == 0)
+            (2) m_lWaiting + Semaphore count == nWaiting
+
+        We would deadlock if
+           nWaiting != 0 &&
+           m_lFree.GetCount() != 0 &&
+           Semaphore count == 0
+
+           But from (1) if m_lFree.GetCount() != 0 then m_lWaiting == 0 so
+           from (2) Semaphore count == nWaiting (which is non-0) so the
+           deadlock can't happen.
+    */
+
+    HANDLE m_hSem;              // For signalling
+    long m_lWaiting;            // Waiting for a free element
+    long m_lCount;              // how many buffers we have agreed to provide
+    long m_lAllocated;          // how many buffers are currently allocated
+    long m_lSize;               // agreed size of each buffer
+    long m_lAlignment;          // agreed alignment
+    long m_lPrefix;             // agreed prefix (preceeds GetPointer() value)
+    BOOL m_bChanged;            // Have the buffer requirements changed
+
+    // if true, we are decommitted and can't allocate memory
+    BOOL m_bCommitted;
+    // if true, the decommit has happened, but we haven't called Free yet
+    // as there are still outstanding buffers
+    BOOL m_bDecommitInProgress;
+
+    //  Notification interface
+    IMemAllocatorNotifyCallbackTemp *m_pNotify;
+
+    BOOL m_fEnableReleaseCallback;
+
+    // called to decommit the memory when the last buffer is freed
+    // pure virtual - need to override this
+    virtual void Free(void) PURE;
+
+    // override to allocate the memory when commit called
+    virtual HRESULT Alloc(void);
+
+public:
+
+    CBaseAllocator(
+        __in_opt LPCTSTR , __inout_opt LPUNKNOWN, __inout HRESULT *,
+        BOOL bEvent = TRUE, BOOL fEnableReleaseCallback = FALSE);
+#ifdef UNICODE
+    CBaseAllocator(
+        __in_opt LPCSTR , __inout_opt LPUNKNOWN, __inout HRESULT *,
+        BOOL bEvent = TRUE, BOOL fEnableReleaseCallback = FALSE);
+#endif
+    virtual ~CBaseAllocator();
+
+    DECLARE_IUNKNOWN
+
+    // override this to publicise our interfaces
+    STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
+
+    STDMETHODIMP SetProperties(
+		    __in ALLOCATOR_PROPERTIES* pRequest,
+		    __out ALLOCATOR_PROPERTIES* pActual);
+
+    // return the properties actually being used on this allocator
+    STDMETHODIMP GetProperties(
+		    __out ALLOCATOR_PROPERTIES* pProps);
+
+    // override Commit to allocate memory. We handle the GetBuffer
+    //state changes
+    STDMETHODIMP Commit();
+
+    // override this to handle the memory freeing. We handle any outstanding
+    // GetBuffer calls
+    STDMETHODIMP Decommit();
+
+    // get container for a sample. Blocking, synchronous call to get the
+    // next free buffer (as represented by an IMediaSample interface).
+    // on return, the time etc properties will be invalid, but the buffer
+    // pointer and size will be correct. The two time parameters are
+    // optional and either may be NULL, they may alternatively be set to
+    // the start and end times the sample will have attached to it
+    // bPrevFramesSkipped is not used (used only by the video renderer's
+    // allocator where it affects quality management in direct draw).
+
+    STDMETHODIMP GetBuffer(__deref_out IMediaSample **ppBuffer,
+                           __in_opt REFERENCE_TIME * pStartTime,
+                           __in_opt REFERENCE_TIME * pEndTime,
+                           DWORD dwFlags);
+
+    // final release of a CMediaSample will call this
+    STDMETHODIMP ReleaseBuffer(IMediaSample *pBuffer);
+    // obsolete:: virtual void PutOnFreeList(CMediaSample * pSample);
+
+    STDMETHODIMP SetNotify(IMemAllocatorNotifyCallbackTemp *pNotify);
+
+    STDMETHODIMP GetFreeCount(__out LONG *plBuffersFree);
+
+    // Notify that a sample is available
+    void NotifySample();
+
+    // Notify that we're waiting for a sample
+    void SetWaiting() { m_lWaiting++; };
+};
+
+
+//=====================================================================
+//=====================================================================
+// Defines CMemAllocator
+//
+// this is an allocator based on CBaseAllocator that allocates sample
+// buffers in main memory (from 'new'). You must call SetProperties
+// before calling Commit.
+//
+// we don't free the memory when going into Decommit state. The simplest
+// way to implement this without complicating CBaseAllocator is to
+// have a Free() function, called to go into decommit state, that does
+// nothing and a ReallyFree function called from our destructor that
+// actually frees the memory.
+//=====================================================================
+//=====================================================================
+
+//  Make me one from quartz.dll
+STDAPI CreateMemoryAllocator(__deref_out IMemAllocator **ppAllocator);
+
+class CMemAllocator : public CBaseAllocator
+{
+
+protected:
+
+    LPBYTE m_pBuffer;   // combined memory for all buffers
+
+    // override to free the memory when decommit completes
+    // - we actually do nothing, and save the memory until deletion.
+    void Free(void);
+
+    // called from the destructor (and from Alloc if changing size/count) to
+    // actually free up the memory
+    void ReallyFree(void);
+
+    // overriden to allocate the memory when commit called
+    HRESULT Alloc(void);
+
+public:
+    /* This goes in the factory template table to create new instances */
+    static CUnknown *CreateInstance(__inout_opt LPUNKNOWN, __inout HRESULT *);
+
+    STDMETHODIMP SetProperties(
+		    __in ALLOCATOR_PROPERTIES* pRequest,
+		    __out ALLOCATOR_PROPERTIES* pActual);
+
+    CMemAllocator(__in_opt LPCTSTR , __inout_opt LPUNKNOWN, __inout HRESULT *);
+#ifdef UNICODE
+    CMemAllocator(__in_opt LPCSTR , __inout_opt LPUNKNOWN, __inout HRESULT *);
+#endif
+    ~CMemAllocator();
+};
+
+// helper used by IAMovieSetup implementation
+STDAPI
+AMovieSetupRegisterFilter( const AMOVIESETUP_FILTER * const psetupdata
+                         , IFilterMapper *                  pIFM
+                         , BOOL                             bRegister  );
+
+
+///////////////////////////////////////////////////////////////////////////
+// ------------------------------------------------------------------------
+// ------------------------------------------------------------------------
+// ------------------------------------------------------------------------
+// ------------------------------------------------------------------------
+///////////////////////////////////////////////////////////////////////////
+
+#endif /* __FILTER__ */
+
+
+
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/amvideo.cpp b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/amvideo.cpp
new file mode 100644
index 0000000..ad1436f
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/amvideo.cpp
@@ -0,0 +1,280 @@
+//------------------------------------------------------------------------------
+// File: AMVideo.cpp
+//
+// Desc: DirectShow base classes - implements helper functions for
+//       bitmap formats.
+//
+// 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>
+#include <limits.h>
+
+// These are bit field masks for true colour devices
+
+const DWORD bits555[] = {0x007C00,0x0003E0,0x00001F};
+const DWORD bits565[] = {0x00F800,0x0007E0,0x00001F};
+const DWORD bits888[] = {0xFF0000,0x00FF00,0x0000FF};
+
+// This maps bitmap subtypes into a bits per pixel value and also a
+// name. unicode and ansi versions are stored because we have to
+// return a pointer to a static string.
+const struct {
+    const GUID *pSubtype;
+    WORD BitCount;
+    CHAR *pName;
+    WCHAR *wszName;
+} BitCountMap[] =  { &MEDIASUBTYPE_RGB1,        1,   "RGB Monochrome",     L"RGB Monochrome",   
+                     &MEDIASUBTYPE_RGB4,        4,   "RGB VGA",            L"RGB VGA",          
+                     &MEDIASUBTYPE_RGB8,        8,   "RGB 8",              L"RGB 8",            
+                     &MEDIASUBTYPE_RGB565,      16,  "RGB 565 (16 bit)",   L"RGB 565 (16 bit)", 
+                     &MEDIASUBTYPE_RGB555,      16,  "RGB 555 (16 bit)",   L"RGB 555 (16 bit)", 
+                     &MEDIASUBTYPE_RGB24,       24,  "RGB 24",             L"RGB 24",           
+                     &MEDIASUBTYPE_RGB32,       32,  "RGB 32",             L"RGB 32",
+                     &MEDIASUBTYPE_ARGB32,    32,  "ARGB 32",             L"ARGB 32",
+                     &MEDIASUBTYPE_Overlay,     0,   "Overlay",            L"Overlay",          
+                     &GUID_NULL,                0,   "UNKNOWN",            L"UNKNOWN"           
+};
+
+// Return the size of the bitmap as defined by this header
+
+STDAPI_(DWORD) GetBitmapSize(const BITMAPINFOHEADER *pHeader)
+{
+    return DIBSIZE(*pHeader);
+}
+
+
+// This is called if the header has a 16 bit colour depth and needs to work
+// out the detailed type from the bit fields (either RGB 565 or RGB 555)
+
+STDAPI_(const GUID) GetTrueColorType(const BITMAPINFOHEADER *pbmiHeader)
+{
+    BITMAPINFO *pbmInfo = (BITMAPINFO *) pbmiHeader;
+    ASSERT(pbmiHeader->biBitCount == 16);
+
+    // If its BI_RGB then it's RGB 555 by default
+
+    if (pbmiHeader->biCompression == BI_RGB) {
+        return MEDIASUBTYPE_RGB555;
+    }
+
+    // Compare the bit fields with RGB 555
+
+    DWORD *pMask = (DWORD *) pbmInfo->bmiColors;
+    if (pMask[0] == bits555[0]) {
+        if (pMask[1] == bits555[1]) {
+            if (pMask[2] == bits555[2]) {
+                return MEDIASUBTYPE_RGB555;
+            }
+        }
+    }
+
+    // Compare the bit fields with RGB 565
+
+    pMask = (DWORD *) pbmInfo->bmiColors;
+    if (pMask[0] == bits565[0]) {
+        if (pMask[1] == bits565[1]) {
+            if (pMask[2] == bits565[2]) {
+                return MEDIASUBTYPE_RGB565;
+            }
+        }
+    }
+    return GUID_NULL;
+}
+
+
+// Given a BITMAPINFOHEADER structure this returns the GUID sub type that is
+// used to describe it in format negotiations. For example a video codec fills
+// in the format block with a VIDEOINFO structure, it also fills in the major
+// type with MEDIATYPE_VIDEO and the subtype with a GUID that matches the bit
+// count, for example if it is an eight bit image then MEDIASUBTYPE_RGB8
+
+STDAPI_(const GUID) GetBitmapSubtype(const BITMAPINFOHEADER *pbmiHeader)
+{
+    ASSERT(pbmiHeader);
+
+    // If it's not RGB then create a GUID from the compression type
+
+    if (pbmiHeader->biCompression != BI_RGB) {
+        if (pbmiHeader->biCompression != BI_BITFIELDS) {
+            FOURCCMap FourCCMap(pbmiHeader->biCompression);
+            return (const GUID) FourCCMap;
+        }
+    }
+
+    // Map the RGB DIB bit depth to a image GUID
+
+    switch(pbmiHeader->biBitCount) {
+        case 1    :   return MEDIASUBTYPE_RGB1;
+        case 4    :   return MEDIASUBTYPE_RGB4;
+        case 8    :   return MEDIASUBTYPE_RGB8;
+        case 16   :   return GetTrueColorType(pbmiHeader);
+        case 24   :   return MEDIASUBTYPE_RGB24;
+        case 32   :   return MEDIASUBTYPE_RGB32;
+    }
+    return GUID_NULL;
+}
+
+
+// Given a video bitmap subtype we return the number of bits per pixel it uses
+// We return a WORD bit count as thats what the BITMAPINFOHEADER uses. If the
+// GUID subtype is not found in the table we return an invalid USHRT_MAX
+
+STDAPI_(WORD) GetBitCount(const GUID *pSubtype)
+{
+    ASSERT(pSubtype);
+    const GUID *pMediaSubtype;
+    INT iPosition = 0;
+
+    // Scan the mapping list seeing if the source GUID matches any known
+    // bitmap subtypes, the list is terminated by a GUID_NULL entry
+
+    while (TRUE) {
+        pMediaSubtype = BitCountMap[iPosition].pSubtype;
+        if (IsEqualGUID(*pMediaSubtype,GUID_NULL)) {
+            return USHRT_MAX;
+        }
+        if (IsEqualGUID(*pMediaSubtype,*pSubtype)) {
+            return BitCountMap[iPosition].BitCount;
+        }
+        iPosition++;
+    }
+}
+
+
+// Given a bitmap subtype we return a description name that can be used for
+// debug purposes. In a retail build this function still returns the names
+// If the subtype isn't found in the lookup table we return string UNKNOWN
+
+int LocateSubtype(const GUID *pSubtype)
+{
+    ASSERT(pSubtype);
+    const GUID *pMediaSubtype;
+    INT iPosition = 0;
+
+    // Scan the mapping list seeing if the source GUID matches any known
+    // bitmap subtypes, the list is terminated by a GUID_NULL entry
+
+    while (TRUE) {
+        pMediaSubtype = BitCountMap[iPosition].pSubtype;
+        if (IsEqualGUID(*pMediaSubtype,*pSubtype) ||
+            IsEqualGUID(*pMediaSubtype,GUID_NULL)
+            )
+        {
+            break;
+        }
+        
+        iPosition++;
+    }
+
+    return iPosition;
+}
+
+
+
+STDAPI_(WCHAR *) GetSubtypeNameW(const GUID *pSubtype)
+{
+    return BitCountMap[LocateSubtype(pSubtype)].wszName;
+}
+
+STDAPI_(CHAR *) GetSubtypeNameA(const GUID *pSubtype)
+{
+    return BitCountMap[LocateSubtype(pSubtype)].pName;
+}
+
+#ifndef GetSubtypeName
+#error wxutil.h should have defined GetSubtypeName
+#endif
+#undef GetSubtypeName
+
+// this is here for people that linked to it directly; most people
+// would use the header file that picks the A or W version.
+STDAPI_(CHAR *) GetSubtypeName(const GUID *pSubtype)
+{
+    return GetSubtypeNameA(pSubtype);
+}
+
+
+// The mechanism for describing a bitmap format is with the BITMAPINFOHEADER
+// This is really messy to deal with because it invariably has fields that
+// follow it holding bit fields, palettes and the rest. This function gives
+// the number of bytes required to hold a VIDEOINFO that represents it. This
+// count includes the prefix information (like the rcSource rectangle) the
+// BITMAPINFOHEADER field, and any other colour information on the end.
+//
+// WARNING If you want to copy a BITMAPINFOHEADER into a VIDEOINFO always make
+// sure that you use the HEADER macro because the BITMAPINFOHEADER field isn't
+// right at the start of the VIDEOINFO (there are a number of other fields),
+//
+//     CopyMemory(HEADER(pVideoInfo),pbmi,sizeof(BITMAPINFOHEADER));
+//
+
+STDAPI_(LONG) GetBitmapFormatSize(const BITMAPINFOHEADER *pHeader)
+{
+    // Everyone has this to start with this  
+    LONG Size = SIZE_PREHEADER + pHeader->biSize;
+
+    ASSERT(pHeader->biSize >= sizeof(BITMAPINFOHEADER));
+    
+    // Does this format use a palette, if the number of colours actually used
+    // is zero then it is set to the maximum that are allowed for that colour
+    // depth (an example is 256 for eight bits). Truecolour formats may also
+    // pass a palette with them in which case the used count is non zero
+
+    // This would scare me.
+    ASSERT(pHeader->biBitCount <= iPALETTE || pHeader->biClrUsed == 0);
+
+    if (pHeader->biBitCount <= iPALETTE || pHeader->biClrUsed) {
+        LONG Entries = (DWORD) 1 << pHeader->biBitCount;
+        if (pHeader->biClrUsed) {
+            Entries = pHeader->biClrUsed;
+        }
+        Size += Entries * sizeof(RGBQUAD);
+    }
+
+    // Truecolour formats may have a BI_BITFIELDS specifier for compression
+    // type which means that room for three DWORDs should be allocated that
+    // specify where in each pixel the RGB colour components may be found
+
+    if (pHeader->biCompression == BI_BITFIELDS) {
+        Size += SIZE_MASKS;
+    }
+
+    // A BITMAPINFO for a palettised image may also contain a palette map that
+    // provides the information to map from a source palette to a destination
+    // palette during a BitBlt for example, because this information is only
+    // ever processed during drawing you don't normally store the palette map
+    // nor have any way of knowing if it is present in the data structure
+
+    return Size;
+}
+
+
+// Returns TRUE if the VIDEOINFO contains a palette
+
+STDAPI_(BOOL) ContainsPalette(const VIDEOINFOHEADER *pVideoInfo)
+{
+    if (PALETTISED(pVideoInfo) == FALSE) {
+        if (pVideoInfo->bmiHeader.biClrUsed == 0) {
+            return FALSE;
+        }
+    }
+    return TRUE;
+}
+
+
+// Return a pointer to the first entry in a palette
+
+STDAPI_(const RGBQUAD *) GetBitmapPalette(const VIDEOINFOHEADER *pVideoInfo)
+{
+    if (pVideoInfo->bmiHeader.biCompression == BI_BITFIELDS) {
+        return TRUECOLOR(pVideoInfo)->bmiColors;
+    }
+    return COLORS(pVideoInfo);
+}
+
+#endif /* PJMEDIA_VIDEO_DEV_HAS_DSHOW */
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/arithutil.cpp b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/arithutil.cpp
new file mode 100644
index 0000000..9600e5f
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/arithutil.cpp
@@ -0,0 +1,366 @@
+//------------------------------------------------------------------------------
+// File: ArithUtil.cpp
+//
+// Desc: DirectShow base classes - implements helper classes for building
+//       multimedia filters.
+//
+// Copyright (c) 1992-2004 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>
+
+//
+//  Declare function from largeint.h we need so that PPC can build
+//
+
+//
+// Enlarged integer divide - 64-bits / 32-bits > 32-bits
+//
+
+#ifndef _X86_
+
+#define LLtoU64(x) (*(unsigned __int64*)(void*)(&(x)))
+
+__inline
+ULONG
+WINAPI
+EnlargedUnsignedDivide (
+    IN ULARGE_INTEGER Dividend,
+    IN ULONG Divisor,
+    IN PULONG Remainder
+    )
+{
+        // return remainder if necessary
+        if (Remainder != NULL)
+                *Remainder = (ULONG)(LLtoU64(Dividend) % Divisor);
+        return (ULONG)(LLtoU64(Dividend) / Divisor);
+}
+
+#else
+__inline
+ULONG
+WINAPI
+EnlargedUnsignedDivide (
+    IN ULARGE_INTEGER Dividend,
+    IN ULONG Divisor,
+    IN PULONG Remainder
+    )
+{
+    ULONG ulResult;
+    _asm {
+        mov eax,Dividend.LowPart
+        mov edx,Dividend.HighPart
+        mov ecx,Remainder
+        div Divisor
+        or  ecx,ecx
+        jz  short label
+        mov [ecx],edx
+label:
+        mov ulResult,eax
+    }
+    return ulResult;
+}
+#endif
+
+
+/*  Arithmetic functions to help with time format conversions
+*/
+
+#ifdef _M_ALPHA
+// work around bug in version 12.00.8385 of the alpha compiler where
+// UInt32x32To64 sign-extends its arguments (?)
+#undef UInt32x32To64
+#define UInt32x32To64(a, b) (((ULONGLONG)((ULONG)(a)) & 0xffffffff) * ((ULONGLONG)((ULONG)(b)) & 0xffffffff))
+#endif
+
+/*   Compute (a * b + d) / c */
+LONGLONG WINAPI llMulDiv(LONGLONG a, LONGLONG b, LONGLONG c, LONGLONG d)
+{
+    /*  Compute the absolute values to avoid signed arithmetic problems */
+    ULARGE_INTEGER ua, ub;
+    DWORDLONG uc;
+
+    ua.QuadPart = (DWORDLONG)(a >= 0 ? a : -a);
+    ub.QuadPart = (DWORDLONG)(b >= 0 ? b : -b);
+    uc          = (DWORDLONG)(c >= 0 ? c : -c);
+    BOOL bSign = (a < 0) ^ (b < 0);
+
+    /*  Do long multiplication */
+    ULARGE_INTEGER p[2];
+    p[0].QuadPart  = UInt32x32To64(ua.LowPart, ub.LowPart);
+
+    /*  This next computation cannot overflow into p[1].HighPart because
+        the max number we can compute here is:
+
+                 (2 ** 32 - 1) * (2 ** 32 - 1) +  // ua.LowPart * ub.LowPart
+    (2 ** 32) *  (2 ** 31) * (2 ** 32 - 1) * 2    // x.LowPart * y.HighPart * 2
+
+    == 2 ** 96 - 2 ** 64 + (2 ** 64 - 2 ** 33 + 1)
+    == 2 ** 96 - 2 ** 33 + 1
+    < 2 ** 96
+    */
+
+    ULARGE_INTEGER x;
+    x.QuadPart     = UInt32x32To64(ua.LowPart, ub.HighPart) +
+                     UInt32x32To64(ua.HighPart, ub.LowPart) +
+                     p[0].HighPart;
+    p[0].HighPart  = x.LowPart;
+    p[1].QuadPart  = UInt32x32To64(ua.HighPart, ub.HighPart) + x.HighPart;
+
+    if (d != 0) {
+        ULARGE_INTEGER ud[2];
+        if (bSign) {
+            ud[0].QuadPart = (DWORDLONG)(-d);
+            if (d > 0) {
+                /*  -d < 0 */
+                ud[1].QuadPart = (DWORDLONG)(LONGLONG)-1;
+            } else {
+                ud[1].QuadPart = (DWORDLONG)0;
+            }
+        } else {
+            ud[0].QuadPart = (DWORDLONG)d;
+            if (d < 0) {
+                ud[1].QuadPart = (DWORDLONG)(LONGLONG)-1;
+            } else {
+                ud[1].QuadPart = (DWORDLONG)0;
+            }
+        }
+        /*  Now do extended addition */
+        ULARGE_INTEGER uliTotal;
+
+        /*  Add ls DWORDs */
+        uliTotal.QuadPart  = (DWORDLONG)ud[0].LowPart + p[0].LowPart;
+        p[0].LowPart       = uliTotal.LowPart;
+
+        /*  Propagate carry */
+        uliTotal.LowPart   = uliTotal.HighPart;
+        uliTotal.HighPart  = 0;
+
+        /*  Add 2nd most ls DWORDs */
+        uliTotal.QuadPart += (DWORDLONG)ud[0].HighPart + p[0].HighPart;
+        p[0].HighPart      = uliTotal.LowPart;
+
+        /*  Propagate carry */
+        uliTotal.LowPart   = uliTotal.HighPart;
+        uliTotal.HighPart  = 0;
+
+        /*  Add MS DWORDLONGs - no carry expected */
+        p[1].QuadPart     += ud[1].QuadPart + uliTotal.QuadPart;
+
+        /*  Now see if we got a sign change from the addition */
+        if ((LONG)p[1].HighPart < 0) {
+            bSign = !bSign;
+
+            /*  Negate the current value (ugh!) */
+            p[0].QuadPart  = ~p[0].QuadPart;
+            p[1].QuadPart  = ~p[1].QuadPart;
+            p[0].QuadPart += 1;
+            p[1].QuadPart += (p[0].QuadPart == 0);
+        }
+    }
+
+    /*  Now for the division */
+    if (c < 0) {
+        bSign = !bSign;
+    }
+
+
+    /*  This will catch c == 0 and overflow */
+    if (uc <= p[1].QuadPart) {
+        return bSign ? (LONGLONG)0x8000000000000000 :
+                       (LONGLONG)0x7FFFFFFFFFFFFFFF;
+    }
+
+    DWORDLONG ullResult;
+
+    /*  Do the division */
+    /*  If the dividend is a DWORD_LONG use the compiler */
+    if (p[1].QuadPart == 0) {
+        ullResult = p[0].QuadPart / uc;
+        return bSign ? -(LONGLONG)ullResult : (LONGLONG)ullResult;
+    }
+
+    /*  If the divisor is a DWORD then its simpler */
+    ULARGE_INTEGER ulic;
+    ulic.QuadPart = uc;
+    if (ulic.HighPart == 0) {
+        ULARGE_INTEGER uliDividend;
+        ULARGE_INTEGER uliResult;
+        DWORD dwDivisor = (DWORD)uc;
+        // ASSERT(p[1].HighPart == 0 && p[1].LowPart < dwDivisor);
+        uliDividend.HighPart = p[1].LowPart;
+        uliDividend.LowPart = p[0].HighPart;
+#ifndef USE_LARGEINT
+        uliResult.HighPart = (DWORD)(uliDividend.QuadPart / dwDivisor);
+        p[0].HighPart = (DWORD)(uliDividend.QuadPart % dwDivisor);
+        uliResult.LowPart = 0;
+        uliResult.QuadPart = p[0].QuadPart / dwDivisor + uliResult.QuadPart;
+#else
+        /*  NOTE - this routine will take exceptions if
+            the result does not fit in a DWORD
+        */
+        if (uliDividend.QuadPart >= (DWORDLONG)dwDivisor) {
+            uliResult.HighPart = EnlargedUnsignedDivide(
+                                     uliDividend,
+                                     dwDivisor,
+                                     &p[0].HighPart);
+        } else {
+            uliResult.HighPart = 0;
+        }
+        uliResult.LowPart = EnlargedUnsignedDivide(
+                                 p[0],
+                                 dwDivisor,
+                                 NULL);
+#endif
+        return bSign ? -(LONGLONG)uliResult.QuadPart :
+                        (LONGLONG)uliResult.QuadPart;
+    }
+
+
+    ullResult = 0;
+
+    /*  OK - do long division */
+    for (int i = 0; i < 64; i++) {
+        ullResult <<= 1;
+
+        /*  Shift 128 bit p left 1 */
+        p[1].QuadPart <<= 1;
+        if ((p[0].HighPart & 0x80000000) != 0) {
+            p[1].LowPart++;
+        }
+        p[0].QuadPart <<= 1;
+
+        /*  Compare */
+        if (uc <= p[1].QuadPart) {
+            p[1].QuadPart -= uc;
+            ullResult += 1;
+        }
+    }
+
+    return bSign ? - (LONGLONG)ullResult : (LONGLONG)ullResult;
+}
+
+LONGLONG WINAPI Int64x32Div32(LONGLONG a, LONG b, LONG c, LONG d)
+{
+    ULARGE_INTEGER ua;
+    DWORD ub;
+    DWORD uc;
+
+    /*  Compute the absolute values to avoid signed arithmetic problems */
+    ua.QuadPart = (DWORDLONG)(a >= 0 ? a : -a);
+    ub = (DWORD)(b >= 0 ? b : -b);
+    uc = (DWORD)(c >= 0 ? c : -c);
+    BOOL bSign = (a < 0) ^ (b < 0);
+
+    /*  Do long multiplication */
+    ULARGE_INTEGER p0;
+    DWORD p1;
+    p0.QuadPart  = UInt32x32To64(ua.LowPart, ub);
+
+    if (ua.HighPart != 0) {
+        ULARGE_INTEGER x;
+        x.QuadPart     = UInt32x32To64(ua.HighPart, ub) + p0.HighPart;
+        p0.HighPart  = x.LowPart;
+        p1   = x.HighPart;
+    } else {
+        p1 = 0;
+    }
+
+    if (d != 0) {
+        ULARGE_INTEGER ud0;
+        DWORD ud1;
+
+        if (bSign) {
+            //
+            //  Cast d to LONGLONG first otherwise -0x80000000 sign extends
+            //  incorrectly
+            //
+            ud0.QuadPart = (DWORDLONG)(-(LONGLONG)d);
+            if (d > 0) {
+                /*  -d < 0 */
+                ud1 = (DWORD)-1;
+            } else {
+                ud1 = (DWORD)0;
+            }
+        } else {
+            ud0.QuadPart = (DWORDLONG)d;
+            if (d < 0) {
+                ud1 = (DWORD)-1;
+            } else {
+                ud1 = (DWORD)0;
+            }
+        }
+        /*  Now do extended addition */
+        ULARGE_INTEGER uliTotal;
+
+        /*  Add ls DWORDs */
+        uliTotal.QuadPart  = (DWORDLONG)ud0.LowPart + p0.LowPart;
+        p0.LowPart       = uliTotal.LowPart;
+
+        /*  Propagate carry */
+        uliTotal.LowPart   = uliTotal.HighPart;
+        uliTotal.HighPart  = 0;
+
+        /*  Add 2nd most ls DWORDs */
+        uliTotal.QuadPart += (DWORDLONG)ud0.HighPart + p0.HighPart;
+        p0.HighPart      = uliTotal.LowPart;
+
+        /*  Add MS DWORDLONGs - no carry expected */
+        p1 += ud1 + uliTotal.HighPart;
+
+        /*  Now see if we got a sign change from the addition */
+        if ((LONG)p1 < 0) {
+            bSign = !bSign;
+
+            /*  Negate the current value (ugh!) */
+            p0.QuadPart  = ~p0.QuadPart;
+            p1 = ~p1;
+            p0.QuadPart += 1;
+            p1 += (p0.QuadPart == 0);
+        }
+    }
+
+    /*  Now for the division */
+    if (c < 0) {
+        bSign = !bSign;
+    }
+
+
+    /*  This will catch c == 0 and overflow */
+    if (uc <= p1) {
+        return bSign ? (LONGLONG)0x8000000000000000 :
+                       (LONGLONG)0x7FFFFFFFFFFFFFFF;
+    }
+
+    /*  Do the division */
+
+    /*  If the divisor is a DWORD then its simpler */
+    ULARGE_INTEGER uliDividend;
+    ULARGE_INTEGER uliResult;
+    DWORD dwDivisor = uc;
+    uliDividend.HighPart = p1;
+    uliDividend.LowPart = p0.HighPart;
+    /*  NOTE - this routine will take exceptions if
+        the result does not fit in a DWORD
+    */
+    if (uliDividend.QuadPart >= (DWORDLONG)dwDivisor) {
+        uliResult.HighPart = EnlargedUnsignedDivide(
+                                 uliDividend,
+                                 dwDivisor,
+                                 &p0.HighPart);
+    } else {
+        uliResult.HighPart = 0;
+    }
+    uliResult.LowPart = EnlargedUnsignedDivide(
+                             p0,
+                             dwDivisor,
+                             NULL);
+    return bSign ? -(LONGLONG)uliResult.QuadPart :
+                    (LONGLONG)uliResult.QuadPart;
+}
+
+#endif /* PJMEDIA_VIDEO_DEV_HAS_DSHOW */
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/combase.cpp b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/combase.cpp
new file mode 100644
index 0000000..bf7e351
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/combase.cpp
@@ -0,0 +1,269 @@
+//------------------------------------------------------------------------------
+// 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 */
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/combase.h b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/combase.h
new file mode 100644
index 0000000..f735ba9
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/combase.h
@@ -0,0 +1,305 @@
+//------------------------------------------------------------------------------
+// File: ComBase.h
+//
+// Desc: DirectShow base classes - defines a class hierarchy for creating
+//       COM objects.
+//
+// Copyright (c) 1992-2001 Microsoft Corporation.  All rights reserved.
+//------------------------------------------------------------------------------
+
+
+/*
+
+a. Derive your COM object from CUnknown
+
+b. Make a static CreateInstance function that takes an LPUNKNOWN, an HRESULT *
+   and a TCHAR *. The LPUNKNOWN defines the object to delegate IUnknown calls
+   to. The HRESULT * allows error codes to be passed around constructors and
+   the TCHAR * is a descriptive name that can be printed on the debugger.
+
+   It is important that constructors only change the HRESULT * if they have
+   to set an ERROR code, if it was successful then leave it alone or you may
+   overwrite an error code from an object previously created.
+
+   When you call a constructor the descriptive name should be in static store
+   as we do not copy the string. To stop large amounts of memory being used
+   in retail builds by all these static strings use the NAME macro,
+
+   CMyFilter = new CImplFilter(NAME("My filter"),pUnknown,phr);
+   if (FAILED(hr)) {
+       return hr;
+   }
+
+   In retail builds NAME(_x_) compiles to NULL, the base CBaseObject class
+   knows not to do anything with objects that don't have a name.
+
+c. Have a constructor for your object that passes the LPUNKNOWN, HRESULT * and
+   TCHAR * to the CUnknown constructor. You can set the HRESULT if you have an
+   error, or just simply pass it through to the constructor.
+
+   The object creation will fail in the class factory if the HRESULT indicates
+   an error (ie FAILED(HRESULT) == TRUE)
+
+d. Create a FactoryTemplate with your object's class id and CreateInstance
+   function.
+
+Then (for each interface) either
+
+Multiple inheritance
+
+1. Also derive it from ISomeInterface
+2. Include DECLARE_IUNKNOWN in your class definition to declare
+   implementations of QueryInterface, AddRef and Release that
+   call the outer unknown
+3. Override NonDelegatingQueryInterface to expose ISomeInterface by
+   code something like
+
+     if (riid == IID_ISomeInterface) {
+         return GetInterface((ISomeInterface *) this, ppv);
+     } else {
+         return CUnknown::NonDelegatingQueryInterface(riid, ppv);
+     }
+
+4. Declare and implement the member functions of ISomeInterface.
+
+or: Nested interfaces
+
+1. Declare a class derived from CUnknown
+2. Include DECLARE_IUNKNOWN in your class definition
+3. Override NonDelegatingQueryInterface to expose ISomeInterface by
+   code something like
+
+     if (riid == IID_ISomeInterface) {
+         return GetInterface((ISomeInterface *) this, ppv);
+     } else {
+         return CUnknown::NonDelegatingQueryInterface(riid, ppv);
+     }
+
+4. Implement the member functions of ISomeInterface. Use GetOwner() to
+   access the COM object class.
+
+And in your COM object class:
+
+5. Make the nested class a friend of the COM object class, and declare
+   an instance of the nested class as a member of the COM object class.
+
+   NOTE that because you must always pass the outer unknown and an hResult
+   to the CUnknown constructor you cannot use a default constructor, in
+   other words you will have to make the member variable a pointer to the
+   class and make a NEW call in your constructor to actually create it.
+
+6. override the NonDelegatingQueryInterface with code like this:
+
+     if (riid == IID_ISomeInterface) {
+         return m_pImplFilter->
+            NonDelegatingQueryInterface(IID_ISomeInterface, ppv);
+     } else {
+         return CUnknown::NonDelegatingQueryInterface(riid, ppv);
+     }
+
+You can have mixed classes which support some interfaces via multiple
+inheritance and some via nested classes
+
+*/
+
+#ifndef __COMBASE__
+#define __COMBASE__
+
+// Filter Setup data structures no defined in axextend.idl
+
+typedef REGPINTYPES
+AMOVIESETUP_MEDIATYPE, * PAMOVIESETUP_MEDIATYPE, * FAR LPAMOVIESETUP_MEDIATYPE;
+
+typedef REGFILTERPINS
+AMOVIESETUP_PIN, * PAMOVIESETUP_PIN, * FAR LPAMOVIESETUP_PIN;
+
+typedef struct _AMOVIESETUP_FILTER
+{
+  const CLSID * clsID;
+  const WCHAR * strName;
+  DWORD      dwMerit;
+  UINT       nPins;
+  const AMOVIESETUP_PIN * lpPin;
+}
+AMOVIESETUP_FILTER, * PAMOVIESETUP_FILTER, * FAR LPAMOVIESETUP_FILTER;
+
+/* The DLLENTRY module initialises the module handle on loading */
+
+extern HINSTANCE g_hInst;
+
+/* On DLL load remember which platform we are running on */
+
+extern DWORD g_amPlatform;
+extern OSVERSIONINFO g_osInfo;     // Filled in by GetVersionEx
+
+/* Version of IUnknown that is renamed to allow a class to support both
+   non delegating and delegating IUnknowns in the same COM object */
+
+#ifndef INONDELEGATINGUNKNOWN_DEFINED
+DECLARE_INTERFACE(INonDelegatingUnknown)
+{
+    STDMETHOD(NonDelegatingQueryInterface) (THIS_ REFIID, LPVOID *) PURE;
+    STDMETHOD_(ULONG, NonDelegatingAddRef)(THIS) PURE;
+    STDMETHOD_(ULONG, NonDelegatingRelease)(THIS) PURE;
+};
+#define INONDELEGATINGUNKNOWN_DEFINED
+#endif
+
+typedef INonDelegatingUnknown *PNDUNKNOWN;
+
+
+/* This is the base object class that supports active object counting. As
+   part of the debug facilities we trace every time a C++ object is created
+   or destroyed. The name of the object has to be passed up through the class
+   derivation list during construction as you cannot call virtual functions
+   in the constructor. The downside of all this is that every single object
+   constructor has to take an object name parameter that describes it */
+
+class CBaseObject
+{
+
+private:
+
+    // Disable the copy constructor and assignment by default so you will get
+    //   compiler errors instead of unexpected behaviour if you pass objects
+    //   by value or assign objects.
+    CBaseObject(const CBaseObject& objectSrc);          // no implementation
+    void operator=(const CBaseObject& objectSrc);       // no implementation
+
+private:
+    static LONG m_cObjects;     /* Total number of objects active */
+
+protected:
+#ifdef DEBUG
+    DWORD m_dwCookie;           /* Cookie identifying this object */
+#endif
+
+
+public:
+
+    /* These increment and decrement the number of active objects */
+
+    CBaseObject(__in_opt LPCTSTR pName);
+#ifdef UNICODE
+    CBaseObject(__in_opt LPCSTR pName);
+#endif
+    ~CBaseObject();
+
+    /* Call this to find if there are any CUnknown derived objects active */
+
+    static LONG ObjectsActive() {
+        return m_cObjects;
+    };
+};
+
+
+/* An object that supports one or more COM interfaces will be based on
+   this class. It supports counting of total objects for DLLCanUnloadNow
+   support, and an implementation of the core non delegating IUnknown */
+
+class AM_NOVTABLE CUnknown : public INonDelegatingUnknown,
+                 public CBaseObject
+{
+private:
+    const LPUNKNOWN m_pUnknown; /* Owner of this object */
+
+protected:                      /* So we can override NonDelegatingRelease() */
+    volatile LONG m_cRef;       /* Number of reference counts */
+
+public:
+
+    CUnknown(__in_opt LPCTSTR pName, __in_opt LPUNKNOWN pUnk);
+    virtual ~CUnknown() {};
+
+    // This is redundant, just use the other constructor
+    //   as we never touch the HRESULT in this anyway
+    CUnknown(__in_opt LPCTSTR Name, __in_opt LPUNKNOWN pUnk, __inout_opt HRESULT *phr);
+#ifdef UNICODE
+    CUnknown(__in_opt LPCSTR pName, __in_opt LPUNKNOWN pUnk);
+    CUnknown(__in_opt LPCSTR pName, __in_opt LPUNKNOWN pUnk,__inout_opt HRESULT *phr);
+#endif
+
+    /* Return the owner of this object */
+
+    LPUNKNOWN GetOwner() const {
+        return m_pUnknown;
+    };
+
+    /* Called from the class factory to create a new instance, it is
+       pure virtual so it must be overriden in your derived class */
+
+    /* static CUnknown *CreateInstance(LPUNKNOWN, HRESULT *) */
+
+    /* Non delegating unknown implementation */
+
+    STDMETHODIMP NonDelegatingQueryInterface(REFIID, __deref_out void **);
+    STDMETHODIMP_(ULONG) NonDelegatingAddRef();
+    STDMETHODIMP_(ULONG) NonDelegatingRelease();
+};
+
+/* Return an interface pointer to a requesting client
+   performing a thread safe AddRef as necessary */
+
+STDAPI GetInterface(LPUNKNOWN pUnk, __out void **ppv);
+
+/* A function that can create a new COM object */
+
+typedef CUnknown *(CALLBACK *LPFNNewCOMObject)(__in_opt LPUNKNOWN pUnkOuter, __inout_opt HRESULT *phr);
+
+/*  A function (can be NULL) which is called from the DLL entrypoint
+    routine for each factory template:
+
+    bLoading - TRUE on DLL load, FALSE on DLL unload
+    rclsid   - the m_ClsID of the entry
+*/
+typedef void (CALLBACK *LPFNInitRoutine)(BOOL bLoading, const CLSID *rclsid);
+
+/* Create one of these per object class in an array so that
+   the default class factory code can create new instances */
+
+class CFactoryTemplate {
+
+public:
+
+    const WCHAR *              m_Name;
+    const CLSID *              m_ClsID;
+    LPFNNewCOMObject           m_lpfnNew;
+    LPFNInitRoutine            m_lpfnInit;
+    const AMOVIESETUP_FILTER * m_pAMovieSetup_Filter;
+
+    BOOL IsClassID(REFCLSID rclsid) const {
+        return (IsEqualCLSID(*m_ClsID,rclsid));
+    };
+
+    CUnknown *CreateInstance(__inout_opt LPUNKNOWN pUnk, __inout_opt HRESULT *phr) const {
+        CheckPointer(phr,NULL);
+        return m_lpfnNew(pUnk, phr);
+    };
+};
+
+
+/* You must override the (pure virtual) NonDelegatingQueryInterface to return
+   interface pointers (using GetInterface) to the interfaces your derived
+   class supports (the default implementation only supports IUnknown) */
+
+#define DECLARE_IUNKNOWN                                        \
+    STDMETHODIMP QueryInterface(REFIID riid, __deref_out void **ppv) {      \
+        return GetOwner()->QueryInterface(riid,ppv);            \
+    };                                                          \
+    STDMETHODIMP_(ULONG) AddRef() {                             \
+        return GetOwner()->AddRef();                            \
+    };                                                          \
+    STDMETHODIMP_(ULONG) Release() {                            \
+        return GetOwner()->Release();                           \
+    };
+
+
+
+HINSTANCE	LoadOLEAut32();
+
+
+#endif /* __COMBASE__ */
+
+
+
+
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/ctlutil.cpp b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/ctlutil.cpp
new file mode 100644
index 0000000..2902df2
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/ctlutil.cpp
@@ -0,0 +1,2545 @@
+//------------------------------------------------------------------------------
+// File: CtlUtil.cpp
+//
+// Desc: DirectShow base classes.
+//
+// Copyright (c) 1992-2001 Microsoft Corporation.  All rights reserved.
+//------------------------------------------------------------------------------
+
+
+// Base classes implementing IDispatch parsing for the basic control dual
+// interfaces. Derive from these and implement just the custom method and
+// property methods. We also implement CPosPassThru that can be used by
+// renderers and transforms to pass by IMediaPosition and IMediaSeeking
+
+#include <pjmedia-videodev/config.h>
+
+#if defined(PJMEDIA_VIDEO_DEV_HAS_DSHOW) && PJMEDIA_VIDEO_DEV_HAS_DSHOW != 0
+
+#include <streams.h>
+#include <limits.h>
+#include "seekpt.h"
+
+// 'bool' non standard reserved word
+#pragma warning(disable:4237)
+
+
+// --- CBaseDispatch implementation ----------
+CBaseDispatch::~CBaseDispatch()
+{
+    if (m_pti) {
+	m_pti->Release();
+    }
+}
+
+
+// return 1 if we support GetTypeInfo
+
+STDMETHODIMP
+CBaseDispatch::GetTypeInfoCount(__out UINT * pctinfo)
+{
+    CheckPointer(pctinfo,E_POINTER);
+    ValidateReadWritePtr(pctinfo,sizeof(UINT *));
+    *pctinfo = 1;
+    return S_OK;
+}
+
+
+typedef HRESULT (STDAPICALLTYPE *LPLOADTYPELIB)(
+			    const OLECHAR FAR *szFile,
+			    __deref_out ITypeLib FAR* FAR* pptlib);
+
+typedef HRESULT (STDAPICALLTYPE *LPLOADREGTYPELIB)(REFGUID rguid,
+			    WORD wVerMajor,
+			    WORD wVerMinor,
+			    LCID lcid,
+			    __deref_out ITypeLib FAR* FAR* pptlib);
+
+// attempt to find our type library
+
+STDMETHODIMP
+CBaseDispatch::GetTypeInfo(
+  REFIID riid,
+  UINT itinfo,
+  LCID lcid,
+  __deref_out ITypeInfo ** pptinfo)
+{
+    CheckPointer(pptinfo,E_POINTER);
+    ValidateReadWritePtr(pptinfo,sizeof(ITypeInfo *));
+    HRESULT hr;
+
+    *pptinfo = NULL;
+
+    // we only support one type element
+    if (0 != itinfo) {
+	return TYPE_E_ELEMENTNOTFOUND;
+    }
+
+    if (NULL == pptinfo) {
+	return E_POINTER;
+    }
+
+    // always look for neutral
+    if (NULL == m_pti) {
+
+	LPLOADTYPELIB	    lpfnLoadTypeLib;
+	LPLOADREGTYPELIB    lpfnLoadRegTypeLib;
+	ITypeLib	    *ptlib;
+	HINSTANCE	    hInst;
+
+	static const char  szTypeLib[]	  = "LoadTypeLib";
+	static const char  szRegTypeLib[] = "LoadRegTypeLib";
+	static const WCHAR szControl[]	  = L"control.tlb";
+
+	//
+	// Try to get the Ole32Aut.dll module handle.
+	//
+
+	hInst = LoadOLEAut32();
+	if (hInst == NULL) {
+	    DWORD dwError = GetLastError();
+	    return AmHresultFromWin32(dwError);
+	}
+	lpfnLoadRegTypeLib = (LPLOADREGTYPELIB)GetProcAddress(hInst,
+							      szRegTypeLib);
+	if (lpfnLoadRegTypeLib == NULL) {
+	    DWORD dwError = GetLastError();
+	    return AmHresultFromWin32(dwError);
+	}
+
+	hr = (*lpfnLoadRegTypeLib)(LIBID_QuartzTypeLib, 1, 0, // version 1.0
+				   lcid, &ptlib);
+
+	if (FAILED(hr)) {
+
+	    // attempt to load directly - this will fill the
+	    // registry in if it finds it
+
+	    lpfnLoadTypeLib = (LPLOADTYPELIB)GetProcAddress(hInst, szTypeLib);
+	    if (lpfnLoadTypeLib == NULL) {
+		DWORD dwError = GetLastError();
+		return AmHresultFromWin32(dwError);
+	    }
+
+	    hr = (*lpfnLoadTypeLib)(szControl, &ptlib);
+	    if (FAILED(hr)) {
+		return hr;
+	    }
+	}
+
+	hr = ptlib->GetTypeInfoOfGuid(
+		    riid,
+		    &m_pti);
+
+	ptlib->Release();
+
+	if (FAILED(hr)) {
+	    return hr;
+	}
+    }
+
+    *pptinfo = m_pti;
+    m_pti->AddRef();
+    return S_OK;
+}
+
+
+STDMETHODIMP
+CBaseDispatch::GetIDsOfNames(
+  REFIID riid,
+  __in_ecount(cNames) LPOLESTR * rgszNames,
+  UINT cNames,
+  LCID lcid,
+  __out_ecount(cNames) DISPID * rgdispid)
+{
+    // although the IDispatch riid is dead, we use this to pass from
+    // the interface implementation class to us the iid we are talking about.
+
+    ITypeInfo * pti;
+    HRESULT hr = GetTypeInfo(riid, 0, lcid, &pti);
+
+    if (SUCCEEDED(hr)) {
+	hr = pti->GetIDsOfNames(rgszNames, cNames, rgdispid);
+
+	pti->Release();
+    }
+    return hr;
+}
+
+
+// --- CMediaControl implementation ---------
+
+CMediaControl::CMediaControl(const TCHAR * name,LPUNKNOWN pUnk) :
+    CUnknown(name, pUnk)
+{
+}
+
+// expose our interfaces IMediaControl and IUnknown
+
+STDMETHODIMP
+CMediaControl::NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv)
+{
+    ValidateReadWritePtr(ppv,sizeof(PVOID));
+    if (riid == IID_IMediaControl) {
+	return GetInterface( (IMediaControl *) this, ppv);
+    } else {
+	return CUnknown::NonDelegatingQueryInterface(riid, ppv);
+    }
+}
+
+
+// return 1 if we support GetTypeInfo
+
+STDMETHODIMP
+CMediaControl::GetTypeInfoCount(__out UINT * pctinfo)
+{
+    return m_basedisp.GetTypeInfoCount(pctinfo);
+}
+
+
+// attempt to find our type library
+
+STDMETHODIMP
+CMediaControl::GetTypeInfo(
+  UINT itinfo,
+  LCID lcid,
+  __deref_out ITypeInfo ** pptinfo)
+{
+    return m_basedisp.GetTypeInfo(
+		IID_IMediaControl,
+		itinfo,
+		lcid,
+		pptinfo);
+}
+
+
+STDMETHODIMP
+CMediaControl::GetIDsOfNames(
+  REFIID riid,
+  __in_ecount(cNames) LPOLESTR * rgszNames,
+  UINT cNames,
+  LCID lcid,
+  __out_ecount(cNames) DISPID * rgdispid)
+{
+    return m_basedisp.GetIDsOfNames(
+			IID_IMediaControl,
+			rgszNames,
+			cNames,
+			lcid,
+			rgdispid);
+}
+
+
+STDMETHODIMP
+CMediaControl::Invoke(
+  DISPID dispidMember,
+  REFIID riid,
+  LCID lcid,
+  WORD wFlags,
+  __in DISPPARAMS * pdispparams,
+  __out_opt VARIANT * pvarResult,
+  __out_opt EXCEPINFO * pexcepinfo,
+  __out_opt UINT * puArgErr)
+{
+    // this parameter is a dead leftover from an earlier interface
+    if (IID_NULL != riid) {
+	return DISP_E_UNKNOWNINTERFACE;
+    }
+
+    ITypeInfo * pti;
+    HRESULT hr = GetTypeInfo(0, lcid, &pti);
+
+    if (FAILED(hr)) {
+	return hr;
+    }
+
+    hr = pti->Invoke(
+	    (IMediaControl *)this,
+	    dispidMember,
+	    wFlags,
+	    pdispparams,
+	    pvarResult,
+	    pexcepinfo,
+	    puArgErr);
+
+    pti->Release();
+    return hr;
+}
+
+
+// --- CMediaEvent implementation ----------
+
+
+CMediaEvent::CMediaEvent(__in_opt LPCTSTR name,__in_opt LPUNKNOWN pUnk) :
+    CUnknown(name, pUnk)
+{
+}
+
+
+// expose our interfaces IMediaEvent and IUnknown
+
+STDMETHODIMP
+CMediaEvent::NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv)
+{
+    ValidateReadWritePtr(ppv,sizeof(PVOID));
+    if (riid == IID_IMediaEvent || riid == IID_IMediaEventEx) {
+	return GetInterface( (IMediaEventEx *) this, ppv);
+    } else {
+	return CUnknown::NonDelegatingQueryInterface(riid, ppv);
+    }
+}
+
+
+// return 1 if we support GetTypeInfo
+
+STDMETHODIMP
+CMediaEvent::GetTypeInfoCount(__out UINT * pctinfo)
+{
+    return m_basedisp.GetTypeInfoCount(pctinfo);
+}
+
+
+// attempt to find our type library
+
+STDMETHODIMP
+CMediaEvent::GetTypeInfo(
+  UINT itinfo,
+  LCID lcid,
+  __deref_out ITypeInfo ** pptinfo)
+{
+    return m_basedisp.GetTypeInfo(
+		IID_IMediaEvent,
+		itinfo,
+		lcid,
+		pptinfo);
+}
+
+
+STDMETHODIMP
+CMediaEvent::GetIDsOfNames(
+  REFIID riid,
+  __in_ecount(cNames) LPOLESTR * rgszNames,
+  UINT cNames,
+  LCID lcid,
+  __out_ecount(cNames) DISPID * rgdispid)
+{
+    return m_basedisp.GetIDsOfNames(
+			IID_IMediaEvent,
+			rgszNames,
+			cNames,
+			lcid,
+			rgdispid);
+}
+
+
+STDMETHODIMP
+CMediaEvent::Invoke(
+  DISPID dispidMember,
+  REFIID riid,
+  LCID lcid,
+  WORD wFlags,
+  __in DISPPARAMS * pdispparams,
+  __out_opt VARIANT * pvarResult,
+  __out_opt EXCEPINFO * pexcepinfo,
+  __out_opt UINT * puArgErr)
+{
+    // this parameter is a dead leftover from an earlier interface
+    if (IID_NULL != riid) {
+	return DISP_E_UNKNOWNINTERFACE;
+    }
+
+    ITypeInfo * pti;
+    HRESULT hr = GetTypeInfo(0, lcid, &pti);
+
+    if (FAILED(hr)) {
+	return hr;
+    }
+
+    hr = pti->Invoke(
+	    (IMediaEvent *)this,
+	    dispidMember,
+	    wFlags,
+	    pdispparams,
+	    pvarResult,
+	    pexcepinfo,
+	    puArgErr);
+
+    pti->Release();
+    return hr;
+}
+
+
+// --- CMediaPosition implementation ----------
+
+
+CMediaPosition::CMediaPosition(__in_opt LPCTSTR name,__in_opt LPUNKNOWN pUnk) :
+    CUnknown(name, pUnk)
+{
+}
+
+CMediaPosition::CMediaPosition(__in_opt LPCTSTR name,
+                               __in_opt LPUNKNOWN pUnk,
+                               __inout HRESULT * phr) :
+    CUnknown(name, pUnk)
+{
+    UNREFERENCED_PARAMETER(phr);
+}
+
+
+// expose our interfaces IMediaPosition and IUnknown
+
+STDMETHODIMP
+CMediaPosition::NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv)
+{
+    ValidateReadWritePtr(ppv,sizeof(PVOID));
+    if (riid == IID_IMediaPosition) {
+	return GetInterface( (IMediaPosition *) this, ppv);
+    } else {
+	return CUnknown::NonDelegatingQueryInterface(riid, ppv);
+    }
+}
+
+
+// return 1 if we support GetTypeInfo
+
+STDMETHODIMP
+CMediaPosition::GetTypeInfoCount(__out UINT * pctinfo)
+{
+    return m_basedisp.GetTypeInfoCount(pctinfo);
+}
+
+
+// attempt to find our type library
+
+STDMETHODIMP
+CMediaPosition::GetTypeInfo(
+  UINT itinfo,
+  LCID lcid,
+  __deref_out ITypeInfo ** pptinfo)
+{
+    return m_basedisp.GetTypeInfo(
+		IID_IMediaPosition,
+		itinfo,
+		lcid,
+		pptinfo);
+}
+
+
+STDMETHODIMP
+CMediaPosition::GetIDsOfNames(
+  REFIID riid,
+  __in_ecount(cNames) LPOLESTR * rgszNames,
+  UINT cNames,
+  LCID lcid,
+  __out_ecount(cNames) DISPID * rgdispid)
+{
+    return m_basedisp.GetIDsOfNames(
+			IID_IMediaPosition,
+			rgszNames,
+			cNames,
+			lcid,
+			rgdispid);
+}
+
+
+STDMETHODIMP
+CMediaPosition::Invoke(
+  DISPID dispidMember,
+  REFIID riid,
+  LCID lcid,
+  WORD wFlags,
+  __in DISPPARAMS * pdispparams,
+  __out_opt VARIANT * pvarResult,
+  __out_opt EXCEPINFO * pexcepinfo,
+  __out_opt UINT * puArgErr)
+{
+    // this parameter is a dead leftover from an earlier interface
+    if (IID_NULL != riid) {
+	return DISP_E_UNKNOWNINTERFACE;
+    }
+
+    ITypeInfo * pti;
+    HRESULT hr = GetTypeInfo(0, lcid, &pti);
+
+    if (FAILED(hr)) {
+	return hr;
+    }
+
+    hr = pti->Invoke(
+	    (IMediaPosition *)this,
+	    dispidMember,
+	    wFlags,
+	    pdispparams,
+	    pvarResult,
+	    pexcepinfo,
+	    puArgErr);
+
+    pti->Release();
+    return hr;
+}
+
+
+// --- IMediaPosition and IMediaSeeking pass through class ----------
+
+
+CPosPassThru::CPosPassThru(__in_opt LPCTSTR pName,
+			   __in_opt LPUNKNOWN pUnk,
+			   __inout HRESULT *phr,
+			   IPin *pPin) :
+    CMediaPosition(pName,pUnk),
+    m_pPin(pPin)
+{
+    if (pPin == NULL) {
+	*phr = E_POINTER;
+	return;
+    }
+}
+
+
+// Expose our IMediaSeeking and IMediaPosition interfaces
+
+STDMETHODIMP
+CPosPassThru::NonDelegatingQueryInterface(REFIID riid,__deref_out void **ppv)
+{
+    CheckPointer(ppv,E_POINTER);
+    *ppv = NULL;
+
+    if (riid == IID_IMediaSeeking) {
+	return GetInterface( static_cast<IMediaSeeking *>(this), ppv);
+    }
+    return CMediaPosition::NonDelegatingQueryInterface(riid,ppv);
+}
+
+
+// Return the IMediaPosition interface from our peer
+
+HRESULT
+CPosPassThru::GetPeer(IMediaPosition ** ppMP)
+{
+    *ppMP = NULL;
+
+    IPin *pConnected;
+    HRESULT hr = m_pPin->ConnectedTo(&pConnected);
+    if (FAILED(hr)) {
+	return E_NOTIMPL;
+    }
+    IMediaPosition * pMP;
+    hr = pConnected->QueryInterface(IID_IMediaPosition, (void **) &pMP);
+    pConnected->Release();
+    if (FAILED(hr)) {
+	return E_NOTIMPL;
+    }
+
+    *ppMP = pMP;
+    return S_OK;
+}
+
+
+// Return the IMediaSeeking interface from our peer
+
+HRESULT
+CPosPassThru::GetPeerSeeking(__deref_out IMediaSeeking ** ppMS)
+{
+    *ppMS = NULL;
+
+    IPin *pConnected;
+    HRESULT hr = m_pPin->ConnectedTo(&pConnected);
+    if (FAILED(hr)) {
+	return E_NOTIMPL;
+    }
+    IMediaSeeking * pMS;
+    hr = pConnected->QueryInterface(IID_IMediaSeeking, (void **) &pMS);
+    pConnected->Release();
+    if (FAILED(hr)) {
+	return E_NOTIMPL;
+    }
+
+    *ppMS = pMS;
+    return S_OK;
+}
+
+
+// --- IMediaSeeking methods ----------
+
+
+STDMETHODIMP
+CPosPassThru::GetCapabilities(__out DWORD * pCaps)
+{
+    IMediaSeeking* pMS;
+    HRESULT hr = GetPeerSeeking(&pMS);
+    if (FAILED(hr)) {
+	return hr;
+    }
+
+    hr = pMS->GetCapabilities(pCaps);
+    pMS->Release();
+    return hr;
+}
+
+STDMETHODIMP
+CPosPassThru::CheckCapabilities(__inout DWORD * pCaps)
+{
+    IMediaSeeking* pMS;
+    HRESULT hr = GetPeerSeeking(&pMS);
+    if (FAILED(hr)) {
+	return hr;
+    }
+
+    hr = pMS->CheckCapabilities(pCaps);
+    pMS->Release();
+    return hr;
+}
+
+STDMETHODIMP
+CPosPassThru::IsFormatSupported(const GUID * pFormat)
+{
+    IMediaSeeking* pMS;
+    HRESULT hr = GetPeerSeeking(&pMS);
+    if (FAILED(hr)) {
+	return hr;
+    }
+
+    hr = pMS->IsFormatSupported(pFormat);
+    pMS->Release();
+    return hr;
+}
+
+
+STDMETHODIMP
+CPosPassThru::QueryPreferredFormat(__out GUID *pFormat)
+{
+    IMediaSeeking* pMS;
+    HRESULT hr = GetPeerSeeking(&pMS);
+    if (FAILED(hr)) {
+	return hr;
+    }
+
+    hr = pMS->QueryPreferredFormat(pFormat);
+    pMS->Release();
+    return hr;
+}
+
+
+STDMETHODIMP
+CPosPassThru::SetTimeFormat(const GUID * pFormat)
+{
+    IMediaSeeking* pMS;
+    HRESULT hr = GetPeerSeeking(&pMS);
+    if (FAILED(hr)) {
+	return hr;
+    }
+
+    hr = pMS->SetTimeFormat(pFormat);
+    pMS->Release();
+    return hr;
+}
+
+
+STDMETHODIMP
+CPosPassThru::GetTimeFormat(__out GUID *pFormat)
+{
+    IMediaSeeking* pMS;
+    HRESULT hr = GetPeerSeeking(&pMS);
+    if (FAILED(hr)) {
+	return hr;
+    }
+
+    hr = pMS->GetTimeFormat(pFormat);
+    pMS->Release();
+    return hr;
+}
+
+
+STDMETHODIMP
+CPosPassThru::IsUsingTimeFormat(const GUID * pFormat)
+{
+    IMediaSeeking* pMS;
+    HRESULT hr = GetPeerSeeking(&pMS);
+    if (FAILED(hr)) {
+	return hr;
+    }
+
+    hr = pMS->IsUsingTimeFormat(pFormat);
+    pMS->Release();
+    return hr;
+}
+
+
+STDMETHODIMP
+CPosPassThru::ConvertTimeFormat(__out LONGLONG * pTarget, 
+                                __in_opt const GUID * pTargetFormat,
+				LONGLONG Source, 
+                                __in_opt const GUID * pSourceFormat )
+{
+    IMediaSeeking* pMS;
+    HRESULT hr = GetPeerSeeking(&pMS);
+    if (FAILED(hr)) {
+	return hr;
+    }
+
+    hr = pMS->ConvertTimeFormat(pTarget, pTargetFormat, Source, pSourceFormat );
+    pMS->Release();
+    return hr;
+}
+
+
+STDMETHODIMP
+CPosPassThru::SetPositions( __inout_opt LONGLONG * pCurrent, 
+                            DWORD CurrentFlags, 
+                            __inout_opt LONGLONG * pStop, 
+                            DWORD StopFlags )
+{
+    IMediaSeeking* pMS;
+    HRESULT hr = GetPeerSeeking(&pMS);
+    if (FAILED(hr)) {
+	return hr;
+    }
+
+    hr = pMS->SetPositions(pCurrent, CurrentFlags, pStop, StopFlags );
+    pMS->Release();
+    return hr;
+}
+
+STDMETHODIMP
+CPosPassThru::GetPositions(__out_opt LONGLONG *pCurrent, __out_opt LONGLONG * pStop)
+{
+    IMediaSeeking* pMS;
+    HRESULT hr = GetPeerSeeking(&pMS);
+    if (FAILED(hr)) {
+	return hr;
+    }
+
+    hr = pMS->GetPositions(pCurrent,pStop);
+    pMS->Release();
+    return hr;
+}
+
+HRESULT
+CPosPassThru::GetSeekingLongLong
+( HRESULT (__stdcall IMediaSeeking::*pMethod)( __out LONGLONG * )
+, LONGLONG * pll
+)
+{
+    IMediaSeeking* pMS;
+    HRESULT hr = GetPeerSeeking(&pMS);
+    if (SUCCEEDED(hr))
+    {
+	hr = (pMS->*pMethod)(pll);
+	pMS->Release();
+    }
+    return hr;
+}
+
+// If we don't have a current position then ask upstream
+
+STDMETHODIMP
+CPosPassThru::GetCurrentPosition(__out LONGLONG *pCurrent)
+{
+    // Can we report the current position
+    HRESULT hr = GetMediaTime(pCurrent,NULL);
+    if (SUCCEEDED(hr)) hr = NOERROR;
+    else hr = GetSeekingLongLong( &IMediaSeeking::GetCurrentPosition, pCurrent );
+    return hr;
+}
+
+
+STDMETHODIMP
+CPosPassThru::GetStopPosition(__out LONGLONG *pStop)
+{
+    return GetSeekingLongLong( &IMediaSeeking::GetStopPosition, pStop );;
+}
+
+STDMETHODIMP
+CPosPassThru::GetDuration(__out LONGLONG *pDuration)
+{
+    return GetSeekingLongLong( &IMediaSeeking::GetDuration, pDuration );;
+}
+
+
+STDMETHODIMP
+CPosPassThru::GetPreroll(__out LONGLONG *pllPreroll)
+{
+    return GetSeekingLongLong( &IMediaSeeking::GetPreroll, pllPreroll );;
+}
+
+
+STDMETHODIMP
+CPosPassThru::GetAvailable( __out_opt LONGLONG *pEarliest, __out_opt LONGLONG *pLatest )
+{
+    IMediaSeeking* pMS;
+    HRESULT hr = GetPeerSeeking(&pMS);
+    if (FAILED(hr)) {
+	return hr;
+    }
+
+    hr = pMS->GetAvailable( pEarliest, pLatest );
+    pMS->Release();
+    return hr;
+}
+
+
+STDMETHODIMP
+CPosPassThru::GetRate(__out double * pdRate)
+{
+    IMediaSeeking* pMS;
+    HRESULT hr = GetPeerSeeking(&pMS);
+    if (FAILED(hr)) {
+	return hr;
+    }
+    hr = pMS->GetRate(pdRate);
+    pMS->Release();
+    return hr;
+}
+
+
+STDMETHODIMP
+CPosPassThru::SetRate(double dRate)
+{
+    if (0.0 == dRate) {
+		return E_INVALIDARG;
+    }
+
+    IMediaSeeking* pMS;
+    HRESULT hr = GetPeerSeeking(&pMS);
+    if (FAILED(hr)) {
+	return hr;
+    }
+    hr = pMS->SetRate(dRate);
+    pMS->Release();
+    return hr;
+}
+
+
+
+
+// --- IMediaPosition methods ----------
+
+
+STDMETHODIMP
+CPosPassThru::get_Duration(__out REFTIME * plength)
+{
+    IMediaPosition* pMP;
+    HRESULT hr = GetPeer(&pMP);
+    if (FAILED(hr)) {
+	return hr;
+    }
+
+    hr = pMP->get_Duration(plength);
+    pMP->Release();
+    return hr;
+}
+
+
+STDMETHODIMP
+CPosPassThru::get_CurrentPosition(__out REFTIME * pllTime)
+{
+    IMediaPosition* pMP;
+    HRESULT hr = GetPeer(&pMP);
+    if (FAILED(hr)) {
+	return hr;
+    }
+    hr = pMP->get_CurrentPosition(pllTime);
+    pMP->Release();
+    return hr;
+}
+
+
+STDMETHODIMP
+CPosPassThru::put_CurrentPosition(REFTIME llTime)
+{
+    IMediaPosition* pMP;
+    HRESULT hr = GetPeer(&pMP);
+    if (FAILED(hr)) {
+	return hr;
+    }
+    hr = pMP->put_CurrentPosition(llTime);
+    pMP->Release();
+    return hr;
+}
+
+
+STDMETHODIMP
+CPosPassThru::get_StopTime(__out REFTIME * pllTime)
+{
+    IMediaPosition* pMP;
+    HRESULT hr = GetPeer(&pMP);
+    if (FAILED(hr)) {
+	return hr;
+    }
+    hr = pMP->get_StopTime(pllTime);
+    pMP->Release();
+    return hr;
+}
+
+
+STDMETHODIMP
+CPosPassThru::put_StopTime(REFTIME llTime)
+{
+    IMediaPosition* pMP;
+    HRESULT hr = GetPeer(&pMP);
+    if (FAILED(hr)) {
+	return hr;
+    }
+    hr = pMP->put_StopTime(llTime);
+    pMP->Release();
+    return hr;
+}
+
+
+STDMETHODIMP
+CPosPassThru::get_PrerollTime(__out REFTIME * pllTime)
+{
+    IMediaPosition* pMP;
+    HRESULT hr = GetPeer(&pMP);
+    if (FAILED(hr)) {
+	return hr;
+    }
+    hr = pMP->get_PrerollTime(pllTime);
+    pMP->Release();
+    return hr;
+}
+
+
+STDMETHODIMP
+CPosPassThru::put_PrerollTime(REFTIME llTime)
+{
+    IMediaPosition* pMP;
+    HRESULT hr = GetPeer(&pMP);
+    if (FAILED(hr)) {
+	return hr;
+    }
+    hr = pMP->put_PrerollTime(llTime);
+    pMP->Release();
+    return hr;
+}
+
+
+STDMETHODIMP
+CPosPassThru::get_Rate(__out double * pdRate)
+{
+    IMediaPosition* pMP;
+    HRESULT hr = GetPeer(&pMP);
+    if (FAILED(hr)) {
+	return hr;
+    }
+    hr = pMP->get_Rate(pdRate);
+    pMP->Release();
+    return hr;
+}
+
+
+STDMETHODIMP
+CPosPassThru::put_Rate(double dRate)
+{
+    if (0.0 == dRate) {
+		return E_INVALIDARG;
+    }
+
+    IMediaPosition* pMP;
+    HRESULT hr = GetPeer(&pMP);
+    if (FAILED(hr)) {
+	return hr;
+    }
+    hr = pMP->put_Rate(dRate);
+    pMP->Release();
+    return hr;
+}
+
+
+STDMETHODIMP
+CPosPassThru::CanSeekForward(__out LONG *pCanSeekForward)
+{
+    IMediaPosition* pMP;
+    HRESULT hr = GetPeer(&pMP);
+    if (FAILED(hr)) {
+	return hr;
+    }
+    hr = pMP->CanSeekForward(pCanSeekForward);
+    pMP->Release();
+    return hr;
+}
+
+
+STDMETHODIMP
+CPosPassThru::CanSeekBackward(__out LONG *pCanSeekBackward)
+{
+    IMediaPosition* pMP;
+    HRESULT hr = GetPeer(&pMP);
+    if (FAILED(hr)) {
+	return hr;
+    }
+    hr = pMP->CanSeekBackward(pCanSeekBackward);
+    pMP->Release();
+    return hr;
+}
+
+
+// --- Implements the CRendererPosPassThru class ----------
+
+
+// Media times (eg current frame, field, sample etc) are passed through the
+// filtergraph in media samples. When a renderer gets a sample with media
+// times in it, it will call one of the RegisterMediaTime methods we expose
+// (one takes an IMediaSample, the other takes the media times direct). We
+// store the media times internally and return them in GetCurrentPosition.
+
+CRendererPosPassThru::CRendererPosPassThru(__in_opt LPCTSTR pName,
+					   __in_opt LPUNKNOWN pUnk,
+					   __inout HRESULT *phr,
+					   IPin *pPin) :
+    CPosPassThru(pName,pUnk,phr,pPin),
+    m_StartMedia(0),
+    m_EndMedia(0),
+    m_bReset(TRUE)
+{
+}
+
+
+// Sets the media times the object should report
+
+HRESULT
+CRendererPosPassThru::RegisterMediaTime(IMediaSample *pMediaSample)
+{
+    ASSERT(pMediaSample);
+    LONGLONG StartMedia;
+    LONGLONG EndMedia;
+
+    CAutoLock cAutoLock(&m_PositionLock);
+
+    // Get the media times from the sample
+
+    HRESULT hr = pMediaSample->GetTime(&StartMedia,&EndMedia);
+    if (FAILED(hr))
+    {
+	ASSERT(hr == VFW_E_SAMPLE_TIME_NOT_SET);
+	return hr;
+    }
+
+    m_StartMedia = StartMedia;
+    m_EndMedia = EndMedia;
+    m_bReset = FALSE;
+    return NOERROR;
+}
+
+
+// Sets the media times the object should report
+
+HRESULT
+CRendererPosPassThru::RegisterMediaTime(LONGLONG StartTime,LONGLONG EndTime)
+{
+    CAutoLock cAutoLock(&m_PositionLock);
+    m_StartMedia = StartTime;
+    m_EndMedia = EndTime;
+    m_bReset = FALSE;
+    return NOERROR;
+}
+
+
+// Return the current media times registered in the object
+
+HRESULT
+CRendererPosPassThru::GetMediaTime(__out LONGLONG *pStartTime, __out_opt LONGLONG *pEndTime)
+{
+    ASSERT(pStartTime);
+
+    CAutoLock cAutoLock(&m_PositionLock);
+    if (m_bReset == TRUE) {
+	return E_FAIL;
+    }
+
+    // We don't have to return the end time
+
+    HRESULT hr = ConvertTimeFormat( pStartTime, 0, m_StartMedia, &TIME_FORMAT_MEDIA_TIME );
+    if (pEndTime && SUCCEEDED(hr)) {
+	hr = ConvertTimeFormat( pEndTime, 0, m_EndMedia, &TIME_FORMAT_MEDIA_TIME );
+    }
+    return hr;
+}
+
+
+// Resets the media times we hold
+
+HRESULT
+CRendererPosPassThru::ResetMediaTime()
+{
+    CAutoLock cAutoLock(&m_PositionLock);
+    m_StartMedia = 0;
+    m_EndMedia = 0;
+    m_bReset = TRUE;
+    return NOERROR;
+}
+
+// Intended to be called by the owing filter during EOS processing so
+// that the media times can be adjusted to the stop time.  This ensures
+// that the GetCurrentPosition will actully get to the stop position.
+HRESULT
+CRendererPosPassThru::EOS()
+{
+    HRESULT hr;
+
+    if ( m_bReset == TRUE ) hr = E_FAIL;
+    else
+    {
+	LONGLONG llStop;
+	if SUCCEEDED(hr=GetStopPosition(&llStop))
+	{
+	    CAutoLock cAutoLock(&m_PositionLock);
+	    m_StartMedia =
+	    m_EndMedia	 = llStop;
+	}
+    }
+    return hr;
+}
+
+// -- CSourceSeeking implementation ------------
+
+CSourceSeeking::CSourceSeeking(
+    __in_opt LPCTSTR pName,
+    __in_opt LPUNKNOWN pUnk,
+    __inout HRESULT* phr,
+    __in CCritSec * pLock) :
+        CUnknown(pName, pUnk),
+        m_pLock(pLock),
+        m_rtStart((long)0)
+{
+    m_rtStop = _I64_MAX / 2;
+    m_rtDuration = m_rtStop;
+    m_dRateSeeking = 1.0;
+
+    m_dwSeekingCaps = AM_SEEKING_CanSeekForwards
+        | AM_SEEKING_CanSeekBackwards
+        | AM_SEEKING_CanSeekAbsolute
+        | AM_SEEKING_CanGetStopPos
+        | AM_SEEKING_CanGetDuration;
+}
+
+HRESULT CSourceSeeking::NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv)
+{
+    if(riid == IID_IMediaSeeking) {
+        CheckPointer(ppv, E_POINTER);
+        return GetInterface(static_cast<IMediaSeeking *>(this), ppv);
+    }
+    else {
+        return CUnknown::NonDelegatingQueryInterface(riid, ppv);
+    }
+}
+
+
+HRESULT CSourceSeeking::IsFormatSupported(const GUID * pFormat)
+{
+    CheckPointer(pFormat, E_POINTER);
+    // only seeking in time (REFERENCE_TIME units) is supported
+    return *pFormat == TIME_FORMAT_MEDIA_TIME ? S_OK : S_FALSE;
+}
+
+HRESULT CSourceSeeking::QueryPreferredFormat(__out GUID *pFormat)
+{
+    CheckPointer(pFormat, E_POINTER);
+    *pFormat = TIME_FORMAT_MEDIA_TIME;
+    return S_OK;
+}
+
+HRESULT CSourceSeeking::SetTimeFormat(const GUID * pFormat)
+{
+    CheckPointer(pFormat, E_POINTER);
+
+    // nothing to set; just check that it's TIME_FORMAT_TIME
+    return *pFormat == TIME_FORMAT_MEDIA_TIME ? S_OK : E_INVALIDARG;
+}
+
+HRESULT CSourceSeeking::IsUsingTimeFormat(const GUID * pFormat)
+{
+    CheckPointer(pFormat, E_POINTER);
+    return *pFormat == TIME_FORMAT_MEDIA_TIME ? S_OK : S_FALSE;
+}
+
+HRESULT CSourceSeeking::GetTimeFormat(__out GUID *pFormat)
+{
+    CheckPointer(pFormat, E_POINTER);
+    *pFormat = TIME_FORMAT_MEDIA_TIME;
+    return S_OK;
+}
+
+HRESULT CSourceSeeking::GetDuration(__out LONGLONG *pDuration)
+{
+    CheckPointer(pDuration, E_POINTER);
+    CAutoLock lock(m_pLock);
+    *pDuration = m_rtDuration;
+    return S_OK;
+}
+
+HRESULT CSourceSeeking::GetStopPosition(__out LONGLONG *pStop)
+{
+    CheckPointer(pStop, E_POINTER);
+    CAutoLock lock(m_pLock);
+    *pStop = m_rtStop;
+    return S_OK;
+}
+
+HRESULT CSourceSeeking::GetCurrentPosition(__out LONGLONG *pCurrent)
+{
+    // GetCurrentPosition is typically supported only in renderers and
+    // not in source filters.
+    return E_NOTIMPL;
+}
+
+HRESULT CSourceSeeking::GetCapabilities( __out DWORD * pCapabilities )
+{
+    CheckPointer(pCapabilities, E_POINTER);
+    *pCapabilities = m_dwSeekingCaps;
+    return S_OK;
+}
+
+HRESULT CSourceSeeking::CheckCapabilities( __inout DWORD * pCapabilities )
+{
+    CheckPointer(pCapabilities, E_POINTER);
+
+    // make sure all requested capabilities are in our mask
+    return (~m_dwSeekingCaps & *pCapabilities) ? S_FALSE : S_OK;
+}
+
+HRESULT CSourceSeeking::ConvertTimeFormat( __out LONGLONG * pTarget, 
+                                           __in_opt const GUID * pTargetFormat,
+                                           LONGLONG Source, 
+                                           __in_opt const GUID * pSourceFormat )
+{
+    CheckPointer(pTarget, E_POINTER);
+    // format guids can be null to indicate current format
+
+    // since we only support TIME_FORMAT_MEDIA_TIME, we don't really
+    // offer any conversions.
+    if(pTargetFormat == 0 || *pTargetFormat == TIME_FORMAT_MEDIA_TIME)
+    {
+        if(pSourceFormat == 0 || *pSourceFormat == TIME_FORMAT_MEDIA_TIME)
+        {
+            *pTarget = Source;
+            return S_OK;
+        }
+    }
+
+    return E_INVALIDARG;
+}
+
+
+HRESULT CSourceSeeking::SetPositions( __inout_opt LONGLONG * pCurrent,  
+                                      DWORD CurrentFlags, 
+                                      __inout_opt LONGLONG * pStop,  
+                                      DWORD StopFlags )
+{
+    DWORD StopPosBits = StopFlags & AM_SEEKING_PositioningBitsMask;
+    DWORD StartPosBits = CurrentFlags & AM_SEEKING_PositioningBitsMask;
+
+    if(StopFlags) {
+        CheckPointer(pStop, E_POINTER);
+
+        // accept only relative, incremental, or absolute positioning
+        if(StopPosBits != StopFlags) {
+            return E_INVALIDARG;
+        }
+    }
+
+    if(CurrentFlags) {
+        CheckPointer(pCurrent, E_POINTER);
+        if(StartPosBits != AM_SEEKING_AbsolutePositioning &&
+           StartPosBits != AM_SEEKING_RelativePositioning) {
+            return E_INVALIDARG;
+        }
+    }
+
+
+    // scope for autolock
+    {
+        CAutoLock lock(m_pLock);
+
+        // set start position
+        if(StartPosBits == AM_SEEKING_AbsolutePositioning)
+        {
+            m_rtStart = *pCurrent;
+        }
+        else if(StartPosBits == AM_SEEKING_RelativePositioning)
+        {
+            m_rtStart += *pCurrent;
+        }
+
+        // set stop position
+        if(StopPosBits == AM_SEEKING_AbsolutePositioning)
+        {
+            m_rtStop = *pStop;
+        }
+        else if(StopPosBits == AM_SEEKING_IncrementalPositioning)
+        {
+            m_rtStop = m_rtStart + *pStop;
+        }
+        else if(StopPosBits == AM_SEEKING_RelativePositioning)
+        {
+            m_rtStop = m_rtStop + *pStop;
+        }
+    }
+
+
+    HRESULT hr = S_OK;
+    if(SUCCEEDED(hr) && StopPosBits) {
+        hr = ChangeStop();
+    }
+    if(StartPosBits) {
+        hr = ChangeStart();
+    }
+
+    return hr;
+}
+
+
+HRESULT CSourceSeeking::GetPositions( __out_opt LONGLONG * pCurrent, __out_opt LONGLONG * pStop )
+{
+    if(pCurrent) {
+        *pCurrent = m_rtStart;
+    }
+    if(pStop) {
+        *pStop = m_rtStop;
+    }
+
+    return S_OK;;
+}
+
+
+HRESULT CSourceSeeking::GetAvailable( __out_opt LONGLONG * pEarliest, __out_opt LONGLONG * pLatest )
+{
+    if(pEarliest) {
+        *pEarliest = 0;
+    }
+    if(pLatest) {
+        CAutoLock lock(m_pLock);
+        *pLatest = m_rtDuration;
+    }
+    return S_OK;
+}
+
+HRESULT CSourceSeeking::SetRate( double dRate)
+{
+    {
+        CAutoLock lock(m_pLock);
+        m_dRateSeeking = dRate;
+    }
+    return ChangeRate();
+}
+
+HRESULT CSourceSeeking::GetRate( __out double * pdRate)
+{
+    CheckPointer(pdRate, E_POINTER);
+    CAutoLock lock(m_pLock);
+    *pdRate = m_dRateSeeking;
+    return S_OK;
+}
+
+HRESULT CSourceSeeking::GetPreroll(__out LONGLONG *pPreroll)
+{
+    CheckPointer(pPreroll, E_POINTER);
+    *pPreroll = 0;
+    return S_OK;
+}
+
+
+
+
+
+// --- CSourcePosition implementation ----------
+
+
+CSourcePosition::CSourcePosition(__in_opt LPCTSTR pName,
+				 __in_opt LPUNKNOWN pUnk,
+				 __inout HRESULT* phr,
+				 __in CCritSec * pLock) :
+    CMediaPosition(pName, pUnk),
+    m_pLock(pLock),
+    m_Start(CRefTime((LONGLONG)0))
+{
+    m_Stop = _I64_MAX;
+    m_Rate = 1.0;
+}
+
+
+STDMETHODIMP
+CSourcePosition::get_Duration(__out REFTIME * plength)
+{
+    CheckPointer(plength,E_POINTER);
+    ValidateReadWritePtr(plength,sizeof(REFTIME));
+    CAutoLock lock(m_pLock);
+
+    *plength = m_Duration;
+    return S_OK;
+}
+
+
+STDMETHODIMP
+CSourcePosition::put_CurrentPosition(REFTIME llTime)
+{
+    m_pLock->Lock();
+    m_Start = llTime;
+    m_pLock->Unlock();
+
+    return ChangeStart();
+}
+
+
+STDMETHODIMP
+CSourcePosition::get_StopTime(__out REFTIME * pllTime)
+{
+    CheckPointer(pllTime,E_POINTER);
+    ValidateReadWritePtr(pllTime,sizeof(REFTIME));
+    CAutoLock lock(m_pLock);
+
+    *pllTime = m_Stop;
+    return S_OK;
+}
+
+
+STDMETHODIMP
+CSourcePosition::put_StopTime(REFTIME llTime)
+{
+    m_pLock->Lock();
+    m_Stop = llTime;
+    m_pLock->Unlock();
+
+    return ChangeStop();
+}
+
+
+STDMETHODIMP
+CSourcePosition::get_PrerollTime(__out REFTIME * pllTime)
+{
+    CheckPointer(pllTime,E_POINTER);
+    ValidateReadWritePtr(pllTime,sizeof(REFTIME));
+    return E_NOTIMPL;
+}
+
+
+STDMETHODIMP
+CSourcePosition::put_PrerollTime(REFTIME llTime)
+{
+    return E_NOTIMPL;
+}
+
+
+STDMETHODIMP
+CSourcePosition::get_Rate(__out double * pdRate)
+{
+    CheckPointer(pdRate,E_POINTER);
+    ValidateReadWritePtr(pdRate,sizeof(double));
+    CAutoLock lock(m_pLock);
+
+    *pdRate = m_Rate;
+    return S_OK;
+}
+
+
+STDMETHODIMP
+CSourcePosition::put_Rate(double dRate)
+{
+    m_pLock->Lock();
+    m_Rate = dRate;
+    m_pLock->Unlock();
+
+    return ChangeRate();
+}
+
+
+// By default we can seek forwards
+
+STDMETHODIMP
+CSourcePosition::CanSeekForward(__out LONG *pCanSeekForward)
+{
+    CheckPointer(pCanSeekForward,E_POINTER);
+    *pCanSeekForward = OATRUE;
+    return S_OK;
+}
+
+
+// By default we can seek backwards
+
+STDMETHODIMP
+CSourcePosition::CanSeekBackward(__out LONG *pCanSeekBackward)
+{
+    CheckPointer(pCanSeekBackward,E_POINTER);
+    *pCanSeekBackward = OATRUE;
+    return S_OK;
+}
+
+
+// --- Implementation of CBasicAudio class ----------
+
+
+CBasicAudio::CBasicAudio(__in_opt LPCTSTR pName,__in_opt LPUNKNOWN punk) :
+    CUnknown(pName, punk)
+{
+}
+
+// overriden to publicise our interfaces
+
+STDMETHODIMP
+CBasicAudio::NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv)
+{
+    ValidateReadWritePtr(ppv,sizeof(PVOID));
+    if (riid == IID_IBasicAudio) {
+	return GetInterface( (IBasicAudio *) this, ppv);
+    } else {
+	return CUnknown::NonDelegatingQueryInterface(riid, ppv);
+    }
+}
+
+
+STDMETHODIMP
+CBasicAudio::GetTypeInfoCount(__out UINT * pctinfo)
+{
+    return m_basedisp.GetTypeInfoCount(pctinfo);
+}
+
+
+STDMETHODIMP
+CBasicAudio::GetTypeInfo(
+  UINT itinfo,
+  LCID lcid,
+  __deref_out ITypeInfo ** pptinfo)
+{
+    return m_basedisp.GetTypeInfo(
+		IID_IBasicAudio,
+		itinfo,
+		lcid,
+		pptinfo);
+}
+
+
+STDMETHODIMP
+CBasicAudio::GetIDsOfNames(
+  REFIID riid,
+  __in_ecount(cNames) LPOLESTR * rgszNames,
+  UINT cNames,
+  LCID lcid,
+  __out_ecount(cNames) DISPID * rgdispid)
+{
+    return m_basedisp.GetIDsOfNames(
+			IID_IBasicAudio,
+			rgszNames,
+			cNames,
+			lcid,
+			rgdispid);
+}
+
+
+STDMETHODIMP
+CBasicAudio::Invoke(
+  DISPID dispidMember,
+  REFIID riid,
+  LCID lcid,
+  WORD wFlags,
+  __in DISPPARAMS * pdispparams,
+  __out_opt VARIANT * pvarResult,
+  __out_opt EXCEPINFO * pexcepinfo,
+  __out_opt UINT * puArgErr)
+{
+    // this parameter is a dead leftover from an earlier interface
+    if (IID_NULL != riid) {
+	return DISP_E_UNKNOWNINTERFACE;
+    }
+
+    ITypeInfo * pti;
+    HRESULT hr = GetTypeInfo(0, lcid, &pti);
+
+    if (FAILED(hr)) {
+	return hr;
+    }
+
+    hr = pti->Invoke(
+	    (IBasicAudio *)this,
+	    dispidMember,
+	    wFlags,
+	    pdispparams,
+	    pvarResult,
+	    pexcepinfo,
+	    puArgErr);
+
+    pti->Release();
+    return hr;
+}
+
+
+// --- IVideoWindow implementation ----------
+
+CBaseVideoWindow::CBaseVideoWindow(__in_opt LPCTSTR pName,__in_opt LPUNKNOWN punk) :
+    CUnknown(pName, punk)
+{
+}
+
+
+// overriden to publicise our interfaces
+
+STDMETHODIMP
+CBaseVideoWindow::NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv)
+{
+    ValidateReadWritePtr(ppv,sizeof(PVOID));
+    if (riid == IID_IVideoWindow) {
+	return GetInterface( (IVideoWindow *) this, ppv);
+    } else {
+	return CUnknown::NonDelegatingQueryInterface(riid, ppv);
+    }
+}
+
+
+STDMETHODIMP
+CBaseVideoWindow::GetTypeInfoCount(__out UINT * pctinfo)
+{
+    return m_basedisp.GetTypeInfoCount(pctinfo);
+}
+
+
+STDMETHODIMP
+CBaseVideoWindow::GetTypeInfo(
+  UINT itinfo,
+  LCID lcid,
+  __deref_out ITypeInfo ** pptinfo)
+{
+    return m_basedisp.GetTypeInfo(
+		IID_IVideoWindow,
+		itinfo,
+		lcid,
+		pptinfo);
+}
+
+
+STDMETHODIMP
+CBaseVideoWindow::GetIDsOfNames(
+  REFIID riid,
+  __in_ecount(cNames) LPOLESTR * rgszNames,
+  UINT cNames,
+  LCID lcid,
+  __out_ecount(cNames) DISPID * rgdispid)
+{
+    return m_basedisp.GetIDsOfNames(
+			IID_IVideoWindow,
+			rgszNames,
+			cNames,
+			lcid,
+			rgdispid);
+}
+
+
+STDMETHODIMP
+CBaseVideoWindow::Invoke(
+  DISPID dispidMember,
+  REFIID riid,
+  LCID lcid,
+  WORD wFlags,
+  __in DISPPARAMS * pdispparams,
+  __out_opt VARIANT * pvarResult,
+  __out_opt EXCEPINFO * pexcepinfo,
+  __out_opt UINT * puArgErr)
+{
+    // this parameter is a dead leftover from an earlier interface
+    if (IID_NULL != riid) {
+	return DISP_E_UNKNOWNINTERFACE;
+    }
+
+    ITypeInfo * pti;
+    HRESULT hr = GetTypeInfo(0, lcid, &pti);
+
+    if (FAILED(hr)) {
+	return hr;
+    }
+
+    hr = pti->Invoke(
+	    (IVideoWindow *)this,
+	    dispidMember,
+	    wFlags,
+	    pdispparams,
+	    pvarResult,
+	    pexcepinfo,
+	    puArgErr);
+
+    pti->Release();
+    return hr;
+}
+
+
+// --- IBasicVideo implementation ----------
+
+
+CBaseBasicVideo::CBaseBasicVideo(__in_opt LPCTSTR pName,__in_opt LPUNKNOWN punk) :
+    CUnknown(pName, punk)
+{
+}
+
+
+// overriden to publicise our interfaces
+
+STDMETHODIMP
+CBaseBasicVideo::NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv)
+{
+    ValidateReadWritePtr(ppv,sizeof(PVOID));
+    if (riid == IID_IBasicVideo || riid == IID_IBasicVideo2) {
+	return GetInterface( static_cast<IBasicVideo2 *>(this), ppv);
+    } else {
+	return CUnknown::NonDelegatingQueryInterface(riid, ppv);
+    }
+}
+
+
+STDMETHODIMP
+CBaseBasicVideo::GetTypeInfoCount(__out UINT * pctinfo)
+{
+    return m_basedisp.GetTypeInfoCount(pctinfo);
+}
+
+
+STDMETHODIMP
+CBaseBasicVideo::GetTypeInfo(
+  UINT itinfo,
+  LCID lcid,
+  __deref_out ITypeInfo ** pptinfo)
+{
+    return m_basedisp.GetTypeInfo(
+		IID_IBasicVideo,
+		itinfo,
+		lcid,
+		pptinfo);
+}
+
+
+STDMETHODIMP
+CBaseBasicVideo::GetIDsOfNames(
+  REFIID riid,
+  __in_ecount(cNames) LPOLESTR * rgszNames,
+  UINT cNames,
+  LCID lcid,
+  __out_ecount(cNames) DISPID * rgdispid)
+{
+    return m_basedisp.GetIDsOfNames(
+			IID_IBasicVideo,
+			rgszNames,
+			cNames,
+			lcid,
+			rgdispid);
+}
+
+
+STDMETHODIMP
+CBaseBasicVideo::Invoke(
+  DISPID dispidMember,
+  REFIID riid,
+  LCID lcid,
+  WORD wFlags,
+  __in DISPPARAMS * pdispparams,
+  __out_opt VARIANT * pvarResult,
+  __out_opt EXCEPINFO * pexcepinfo,
+  __out_opt UINT * puArgErr)
+{
+    // this parameter is a dead leftover from an earlier interface
+    if (IID_NULL != riid) {
+	return DISP_E_UNKNOWNINTERFACE;
+    }
+
+    ITypeInfo * pti;
+    HRESULT hr = GetTypeInfo(0, lcid, &pti);
+
+    if (FAILED(hr)) {
+	return hr;
+    }
+
+    hr = pti->Invoke(
+	    (IBasicVideo *)this,
+	    dispidMember,
+	    wFlags,
+	    pdispparams,
+	    pvarResult,
+	    pexcepinfo,
+	    puArgErr);
+
+    pti->Release();
+    return hr;
+}
+
+
+// --- Implementation of Deferred Commands ----------
+
+
+CDispParams::CDispParams(UINT nArgs, __in_ecount(nArgs) VARIANT* pArgs, __inout_opt HRESULT *phr)
+{
+   cNamedArgs = 0;
+   rgdispidNamedArgs = NULL;
+   cArgs = nArgs;
+
+    if (cArgs) {
+	rgvarg = new VARIANT[cArgs];
+        if (NULL == rgvarg) {
+            cArgs = 0;
+            if (phr) {
+                *phr = E_OUTOFMEMORY;
+            }
+            return;
+        }
+
+	for (UINT i = 0; i < cArgs; i++) {
+
+            //  Why aren't we using VariantCopy?
+
+	    VARIANT * pDest = &rgvarg[i];
+	    VARIANT * pSrc = &pArgs[i];
+
+	    pDest->vt = pSrc->vt;
+	    switch(pDest->vt) {
+
+	    case VT_I4:
+		pDest->lVal = pSrc->lVal;
+		break;
+
+	    case VT_UI1:
+		pDest->bVal = pSrc->bVal;
+		break;
+
+	    case VT_I2:
+		pDest->iVal = pSrc->iVal;
+		break;
+
+	    case VT_R4:
+		pDest->fltVal = pSrc->fltVal;
+		break;
+
+	    case VT_R8:
+		pDest->dblVal = pSrc->dblVal;
+		break;
+
+	    case VT_BOOL:
+		pDest->boolVal = pSrc->boolVal;
+		break;
+
+	    case VT_ERROR:
+		pDest->scode = pSrc->scode;
+		break;
+
+	    case VT_CY:
+		pDest->cyVal = pSrc->cyVal;
+		break;
+
+	    case VT_DATE:
+		pDest->date = pSrc->date;
+		break;
+
+	    case VT_BSTR:
+		if ((PVOID)pSrc->bstrVal == NULL) {
+		    pDest->bstrVal = NULL;
+		} else {
+
+		    // a BSTR is a WORD followed by a UNICODE string.
+		    // the pointer points just after the WORD
+
+		    WORD len = * (WORD*) (pSrc->bstrVal - (sizeof(WORD) / sizeof(OLECHAR)));
+		    OLECHAR* pch = new OLECHAR[len + (sizeof(WORD)/sizeof(OLECHAR))];
+                    if (pch) {
+        		WORD *pui = (WORD*)pch;
+        		*pui = len;
+         	        pDest->bstrVal = pch + (sizeof(WORD)/sizeof(OLECHAR));
+         		CopyMemory(pDest->bstrVal, pSrc->bstrVal, len*sizeof(OLECHAR));
+                    } else {
+                        cArgs = i;
+                        if (phr) {
+                            *phr = E_OUTOFMEMORY;
+                        }
+                    }
+		}
+		break;
+
+	    case VT_UNKNOWN:
+		pDest->punkVal = pSrc->punkVal;
+		pDest->punkVal->AddRef();
+		break;
+
+	    case VT_DISPATCH:
+		pDest->pdispVal = pSrc->pdispVal;
+		pDest->pdispVal->AddRef();
+		break;
+
+	    default:
+		// a type we haven't got round to adding yet!
+		ASSERT(0);
+		break;
+	    }
+	}
+
+    } else {
+	rgvarg = NULL;
+    }
+
+}
+
+
+CDispParams::~CDispParams()
+{
+    for (UINT i = 0; i < cArgs; i++) {
+	switch(rgvarg[i].vt) {
+        case VT_BSTR:
+            //  Explicitly cast BSTR to PVOID to tell code scanning tools we really mean to test the pointer
+	    if ((PVOID)rgvarg[i].bstrVal != NULL) {
+		OLECHAR * pch = rgvarg[i].bstrVal - (sizeof(WORD)/sizeof(OLECHAR));
+		delete pch;
+	    }
+	    break;
+
+	case VT_UNKNOWN:
+	    rgvarg[i].punkVal->Release();
+	    break;
+
+	case VT_DISPATCH:
+	    rgvarg[i].pdispVal->Release();
+	    break;
+	}
+    }
+    delete[] rgvarg;
+}
+
+
+// lifetime is controlled by refcounts (see defer.h)
+
+CDeferredCommand::CDeferredCommand(
+    __inout CCmdQueue * pQ,
+    __in_opt LPUNKNOWN	pUnk,
+    __inout HRESULT *	phr,
+    __in LPUNKNOWN	pUnkExecutor,
+    REFTIME	time,
+    __in GUID*	iid,
+    long	dispidMethod,
+    short	wFlags,
+    long	nArgs,
+    __in_ecount(nArgs) VARIANT*	pDispParams,
+    __out VARIANT*	pvarResult,
+    __out short*	puArgErr,
+    BOOL	bStream
+    ) :
+	CUnknown(NAME("DeferredCommand"), pUnk),
+	m_pQueue(pQ),
+	m_pUnk(pUnkExecutor),
+	m_iid(iid),
+	m_dispidMethod(dispidMethod),
+	m_wFlags(wFlags),
+	m_DispParams(nArgs, pDispParams, phr),
+	m_pvarResult(pvarResult),
+	m_bStream(bStream),
+	m_hrResult(E_ABORT)
+
+{
+    // convert REFTIME to REFERENCE_TIME
+    COARefTime convertor(time);
+    m_time = convertor;
+
+    // no check of time validity - it's ok to queue a command that's
+    // already late
+
+    // check iid is supportable on pUnk by QueryInterface for it
+    IUnknown * pInterface;
+    HRESULT hr = m_pUnk->QueryInterface(GetIID(), (void**) &pInterface);
+    if (FAILED(hr)) {
+	*phr = hr;
+	return;
+    }
+    pInterface->Release();
+
+
+    // !!! check dispidMethod and param/return types using typelib
+    ITypeInfo *pti;
+    hr = m_Dispatch.GetTypeInfo(*iid, 0, 0, &pti);
+    if (FAILED(hr)) {
+	*phr = hr;
+	return;
+    }
+    // !!! some sort of ITypeInfo validity check here
+    pti->Release();
+
+
+    // Fix up the dispid for put and get
+    if (wFlags == DISPATCH_PROPERTYPUT) {
+        m_DispParams.cNamedArgs = 1;
+        m_DispId = DISPID_PROPERTYPUT;
+        m_DispParams.rgdispidNamedArgs = &m_DispId;
+    }
+
+    // all checks ok - add to queue
+    hr = pQ->Insert(this);
+    if (FAILED(hr)) {
+	*phr = hr;
+    }
+}
+
+
+// refcounts are held by caller of InvokeAt... and by list. So if
+// we get here, we can't be on the list
+
+#if 0
+CDeferredCommand::~CDeferredCommand()
+{
+    // this assert is invalid since if the queue is deleted while we are
+    // still on the queue, we will have been removed by the queue and this
+    // m_pQueue will not have been modified.
+    // ASSERT(m_pQueue == NULL);
+
+    // we don't hold a ref count on pUnk, which is the object that should
+    // execute the command.
+    // This is because there would otherwise be a circular refcount problem
+    // since pUnk probably owns the CmdQueue object that has a refcount
+    // on us.
+    // The lifetime of pUnk is guaranteed by it being part of, or lifetime
+    // controlled by, our parent object. As long as we are on the list, pUnk
+    // must be valid. Once we are off the list, we do not use pUnk.
+
+}
+#endif
+
+
+// overriden to publicise our interfaces
+
+STDMETHODIMP
+CDeferredCommand::NonDelegatingQueryInterface(REFIID riid, __out void **ppv)
+{
+    ValidateReadWritePtr(ppv,sizeof(PVOID));
+    if (riid == IID_IDeferredCommand) {
+	return GetInterface( (IDeferredCommand *) this, ppv);
+    } else {
+	return CUnknown::NonDelegatingQueryInterface(riid, ppv);
+    }
+}
+
+
+// remove from q. this will reduce the refcount by one (since the q
+// holds a count) but can't make us go away since he must have a
+// refcount in order to call this method.
+
+STDMETHODIMP
+CDeferredCommand::Cancel()
+{
+    if (m_pQueue == NULL) {
+	return VFW_E_ALREADY_CANCELLED;
+    }
+
+    HRESULT hr = m_pQueue->Remove(this);
+    if (FAILED(hr)) {
+	return hr;
+    }
+
+    m_pQueue = NULL;
+    return S_OK;
+}
+
+
+STDMETHODIMP
+CDeferredCommand::Confidence(__out LONG* pConfidence)
+{
+    return E_NOTIMPL;
+}
+
+
+STDMETHODIMP
+CDeferredCommand::GetHResult(__out HRESULT * phrResult)
+{
+    CheckPointer(phrResult,E_POINTER);
+    ValidateReadWritePtr(phrResult,sizeof(HRESULT));
+
+    if (m_pQueue != NULL) {
+	return E_ABORT;
+    }
+    *phrResult = m_hrResult;
+    return S_OK;
+}
+
+
+// set the time to be a new time (checking that it is valid) and
+// then requeue
+
+STDMETHODIMP
+CDeferredCommand::Postpone(REFTIME newtime)
+{
+
+    // check that this time is not past
+    // convert REFTIME to REFERENCE_TIME
+    COARefTime convertor(newtime);
+
+    // check that the time has not passed
+    if (m_pQueue->CheckTime(convertor, IsStreamTime())) {
+	return VFW_E_TIME_ALREADY_PASSED;
+    }
+
+    // extract from list
+    HRESULT hr = m_pQueue->Remove(this);
+    if (FAILED(hr)) {
+	return hr;
+    }
+
+    // change time
+    m_time = convertor;
+
+    // requeue
+    hr = m_pQueue->Insert(this);
+
+    return hr;
+}
+
+
+HRESULT
+CDeferredCommand::Invoke()
+{
+    // check that we are still outstanding
+    if (m_pQueue == NULL) {
+	return VFW_E_ALREADY_CANCELLED;
+    }
+
+    // get the type info
+    ITypeInfo* pti;
+    HRESULT hr = m_Dispatch.GetTypeInfo(GetIID(), 0, 0, &pti);
+    if (FAILED(hr)) {
+	return hr;
+    }
+
+    // qi for the expected interface and then invoke it. Note that we have to
+    // treat the returned interface as IUnknown since we don't know its type.
+    IUnknown* pInterface;
+
+    hr = m_pUnk->QueryInterface(GetIID(), (void**) &pInterface);
+    if (FAILED(hr)) {
+	pti->Release();
+	return hr;
+    }
+
+    EXCEPINFO expinfo;
+    UINT uArgErr;
+    m_hrResult = pti->Invoke(
+	pInterface,
+	GetMethod(),
+	GetFlags(),
+	GetParams(),
+	GetResult(),
+	&expinfo,
+	&uArgErr);
+
+    // release the interface we QI'd for
+    pInterface->Release();
+    pti->Release();
+
+
+    // remove from list whether or not successful
+    // or we loop indefinitely
+    hr = m_pQueue->Remove(this);
+    m_pQueue = NULL;
+    return hr;
+}
+
+
+
+// --- CCmdQueue methods ----------
+
+
+CCmdQueue::CCmdQueue(__inout_opt HRESULT *phr) :
+    m_listPresentation(NAME("Presentation time command list")),
+    m_listStream(NAME("Stream time command list")),
+    m_evDue(TRUE, phr),    // manual reset
+    m_dwAdvise(0),
+    m_pClock(NULL),
+    m_bRunning(FALSE)
+{
+}
+
+
+CCmdQueue::~CCmdQueue()
+{
+    // empty all our lists
+
+    // we hold a refcount on each, so traverse and Release each
+    // entry then RemoveAll to empty the list
+    POSITION pos = m_listPresentation.GetHeadPosition();
+
+    while(pos) {
+	CDeferredCommand* pCmd = m_listPresentation.GetNext(pos);
+	pCmd->Release();
+    }
+    m_listPresentation.RemoveAll();
+
+    pos = m_listStream.GetHeadPosition();
+
+    while(pos) {
+	CDeferredCommand* pCmd = m_listStream.GetNext(pos);
+	pCmd->Release();
+    }
+    m_listStream.RemoveAll();
+
+    if (m_pClock) {
+	if (m_dwAdvise) {
+	    m_pClock->Unadvise(m_dwAdvise);
+	    m_dwAdvise = 0;
+	}
+	m_pClock->Release();
+    }
+}
+
+
+// returns a new CDeferredCommand object that will be initialised with
+// the parameters and will be added to the queue during construction.
+// returns S_OK if successfully created otherwise an error and
+// no object has been queued.
+
+HRESULT
+CCmdQueue::New(
+    __out CDeferredCommand **ppCmd,
+    __in     LPUNKNOWN	pUnk,		// this object will execute command
+    REFTIME	time,
+    __in GUID*	iid,
+    long	dispidMethod,
+    short	wFlags,
+    long	cArgs,
+    __in_ecount(cArgs) VARIANT*	pDispParams,
+    __out VARIANT*	pvarResult,
+    __out short*	puArgErr,
+    BOOL	bStream
+)
+{
+    CAutoLock lock(&m_Lock);
+
+    HRESULT hr = S_OK;
+    *ppCmd = NULL;
+
+    CDeferredCommand* pCmd;
+    pCmd = new CDeferredCommand(
+		    this,
+		    NULL,	    // not aggregated
+		    &hr,
+		    pUnk,	    // this guy will execute
+		    time,
+		    iid,
+		    dispidMethod,
+		    wFlags,
+		    cArgs,
+		    pDispParams,
+		    pvarResult,
+		    puArgErr,
+		    bStream);
+
+    if (pCmd == NULL) {
+	hr = E_OUTOFMEMORY;
+    } else {
+	*ppCmd = pCmd;
+    }
+    return hr;
+}
+
+
+HRESULT
+CCmdQueue::Insert(__in CDeferredCommand* pCmd)
+{
+    CAutoLock lock(&m_Lock);
+
+    // addref the item
+    pCmd->AddRef();
+
+    CGenericList<CDeferredCommand> * pList;
+    if (pCmd->IsStreamTime()) {
+	pList = &m_listStream;
+    } else {
+	pList = &m_listPresentation;
+    }
+    POSITION pos = pList->GetHeadPosition();
+
+    // seek past all items that are before us
+    while (pos &&
+	(pList->GetValid(pos)->GetTime() <= pCmd->GetTime())) {
+
+	pList->GetNext(pos);
+    }
+
+    // now at end of list or in front of items that come later
+    if (!pos) {
+	pList->AddTail(pCmd);
+    } else {
+	pList->AddBefore(pos, pCmd);
+    }
+
+    SetTimeAdvise();
+    return S_OK;
+}
+
+
+HRESULT
+CCmdQueue::Remove(__in CDeferredCommand* pCmd)
+{
+    CAutoLock lock(&m_Lock);
+    HRESULT hr = S_OK;
+
+    CGenericList<CDeferredCommand> * pList;
+    if (pCmd->IsStreamTime()) {
+	pList = &m_listStream;
+    } else {
+	pList = &m_listPresentation;
+    }
+    POSITION pos = pList->GetHeadPosition();
+
+    // traverse the list
+    while (pos && (pList->GetValid(pos) != pCmd)) {
+	pList->GetNext(pos);
+    }
+
+    // did we drop off the end?
+    if (!pos) {
+	hr = VFW_E_NOT_FOUND;
+    } else {
+
+	// found it - now take off list
+	pList->Remove(pos);
+
+	// Insert did an AddRef, so release it
+	pCmd->Release();
+
+	// check that timer request is still for earliest time
+	SetTimeAdvise();
+    }
+    return hr;
+}
+
+
+// set the clock used for timing
+
+HRESULT
+CCmdQueue::SetSyncSource(__in_opt IReferenceClock* pClock)
+{
+    CAutoLock lock(&m_Lock);
+
+    // addref the new clock first in case they are the same
+    if (pClock) {
+	pClock->AddRef();
+    }
+
+    // kill any advise on the old clock
+    if (m_pClock) {
+	if (m_dwAdvise) {
+	    m_pClock->Unadvise(m_dwAdvise);
+	    m_dwAdvise = 0;
+	}
+	m_pClock->Release();
+    }
+    m_pClock = pClock;
+
+    // set up a new advise
+    SetTimeAdvise();
+    return S_OK;
+}
+
+
+// set up a timer event with the reference clock
+
+void
+CCmdQueue::SetTimeAdvise(void)
+{
+    // make sure we have a clock to use
+    if (!m_pClock) {
+	return;
+    }
+
+    // reset the event whenever we are requesting a new signal
+    m_evDue.Reset();
+
+    // time 0 is earliest
+    CRefTime current;
+
+    // find the earliest presentation time
+    POSITION pos = m_listPresentation.GetHeadPosition();
+    if (pos != NULL) {
+	current = m_listPresentation.GetValid(pos)->GetTime();
+    }
+
+    // if we're running, check the stream times too
+    if (m_bRunning) {
+
+	CRefTime t;
+        pos = m_listStream.GetHeadPosition();
+	if (NULL != pos) {
+	    t = m_listStream.GetValid(pos)->GetTime();
+
+	    // add on stream time offset to get presentation time
+	    t += m_StreamTimeOffset;
+
+	    // is this earlier?
+	    if ((current == TimeZero) || (t < current)) {
+		current = t;
+	    }
+	}
+    }
+
+    // need to change?
+    if ((current > TimeZero) && (current != m_tCurrentAdvise)) {
+	if (m_dwAdvise) {
+	    m_pClock->Unadvise(m_dwAdvise);
+	    // reset the event whenever we are requesting a new signal
+	    m_evDue.Reset();
+	}
+
+	// ask for time advice - the first two params are either
+	// stream time offset and stream time or
+	// presentation time and 0. we always use the latter
+	HRESULT hr = m_pClock->AdviseTime(
+		    (REFERENCE_TIME)current,
+		    TimeZero,
+		    (HEVENT) HANDLE(m_evDue),
+		    &m_dwAdvise);
+
+	ASSERT(SUCCEEDED(hr));
+	m_tCurrentAdvise = current;
+    }
+}
+
+
+// switch to run mode. Streamtime to Presentation time mapping known.
+
+HRESULT
+CCmdQueue::Run(REFERENCE_TIME tStreamTimeOffset)
+{
+    CAutoLock lock(&m_Lock);
+
+    m_StreamTimeOffset = tStreamTimeOffset;
+    m_bRunning = TRUE;
+
+    // ensure advise is accurate
+    SetTimeAdvise();
+    return S_OK;
+}
+
+
+// switch to Stopped or Paused mode. Time mapping not known.
+
+HRESULT
+CCmdQueue::EndRun()
+{
+    CAutoLock lock(&m_Lock);
+
+    m_bRunning = FALSE;
+
+    // check timer setting - stream times
+    SetTimeAdvise();
+    return S_OK;
+}
+
+
+// return a pointer to the next due command. Blocks for msTimeout
+// milliseconds until there is a due command.
+// Stream-time commands will only become due between Run and Endrun calls.
+// The command remains queued until invoked or cancelled.
+// Returns E_ABORT if timeout occurs, otherwise S_OK (or other error).
+//
+// returns an AddRef'd object
+
+HRESULT
+CCmdQueue::GetDueCommand(__out CDeferredCommand ** ppCmd, long msTimeout)
+{
+    // loop until we timeout or find a due command
+    for (;;) {
+
+	{
+	    CAutoLock lock(&m_Lock);
+
+
+	    // find the earliest command
+	    CDeferredCommand * pCmd = NULL;
+
+	    // check the presentation time and the
+	    // stream time list to find the earliest
+
+            POSITION pos = m_listPresentation.GetHeadPosition();
+
+	    if (NULL != pos) {
+		pCmd = m_listPresentation.GetValid(pos);
+	    }
+
+	    if (m_bRunning) {
+		pos = m_listStream.GetHeadPosition();
+                if (NULL != pos) {
+                    CDeferredCommand* pStrm = m_listStream.GetValid(pos);
+
+                    CRefTime t = pStrm->GetTime() + m_StreamTimeOffset;
+                    if (!pCmd || (t < pCmd->GetTime())) {
+                        pCmd = pStrm;
+                    }
+                }
+            }
+
+	    //	if we have found one, is it due?
+	    if (pCmd) {
+		if (CheckTime(pCmd->GetTime(), pCmd->IsStreamTime())) {
+
+		    // yes it's due - addref it
+		    pCmd->AddRef();
+		    *ppCmd = pCmd;
+		    return S_OK;
+		}
+	    }
+	}
+
+	// block until the advise is signalled
+	if (WaitForSingleObject(m_evDue, msTimeout) != WAIT_OBJECT_0) {
+	    return E_ABORT;
+	}
+    }
+}
+
+
+// return a pointer to a command that will be due for a given time.
+// Pass in a stream time here. The stream time offset will be passed
+// in via the Run method.
+// Commands remain queued until invoked or cancelled.
+// This method will not block. It will report E_ABORT if there are no
+// commands due yet.
+//
+// returns an AddRef'd object
+
+HRESULT
+CCmdQueue::GetCommandDueFor(REFERENCE_TIME rtStream, __out CDeferredCommand**ppCmd)
+{
+    CAutoLock lock(&m_Lock);
+
+    CRefTime tStream(rtStream);
+
+    // find the earliest stream and presentation time commands
+    CDeferredCommand* pStream = NULL;
+    POSITION pos = m_listStream.GetHeadPosition();
+    if (NULL != pos) {
+	pStream = m_listStream.GetValid(pos);
+    }
+    CDeferredCommand* pPresent = NULL;
+    pos = m_listPresentation.GetHeadPosition();
+    if (NULL != pos) {
+	pPresent = m_listPresentation.GetValid(pos);
+    }
+
+    // is there a presentation time that has passed already
+    if (pPresent && CheckTime(pPresent->GetTime(), FALSE)) {
+	pPresent->AddRef();
+	*ppCmd = pPresent;
+	return S_OK;
+    }
+
+    // is there a stream time command due before this stream time
+    if (pStream && (pStream->GetTime() <= tStream)) {
+	pStream->AddRef();
+	*ppCmd = pStream;
+	return S_OK;
+    }
+
+    // if we are running, we can map presentation times to
+    // stream time. In this case, is there a presentation time command
+    // that will be due before this stream time is presented?
+    if (m_bRunning && pPresent) {
+
+	// this stream time will appear at...
+	tStream += m_StreamTimeOffset;
+
+	// due before that?
+	if (pPresent->GetTime() <= tStream) {
+	    *ppCmd = pPresent;
+	    return S_OK;
+	}
+    }
+
+    // no commands due yet
+    return VFW_E_NOT_FOUND;
+}
+
+#endif /* PJMEDIA_VIDEO_DEV_HAS_DSHOW */
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/ctlutil.h b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/ctlutil.h
new file mode 100644
index 0000000..7e4719c
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/ctlutil.h
@@ -0,0 +1,923 @@
+//------------------------------------------------------------------------------
+// File: CtlUtil.h
+//
+// Desc: DirectShow base classes.
+//
+// Copyright (c) 1992-2001 Microsoft Corporation.  All rights reserved.
+//------------------------------------------------------------------------------
+
+
+// Base classes implementing IDispatch parsing for the basic control dual
+// interfaces. Derive from these and implement just the custom method and
+// property methods. We also implement CPosPassThru that can be used by
+// renderers and transforms to pass by IMediaPosition and IMediaSeeking
+
+#ifndef __CTLUTIL__
+#define __CTLUTIL__
+
+// OLE Automation has different ideas of TRUE and FALSE
+
+#define OATRUE (-1)
+#define OAFALSE (0)
+
+
+// It's possible that we could replace this class with CreateStdDispatch
+
+class CBaseDispatch
+{
+    ITypeInfo * m_pti;
+
+public:
+
+    CBaseDispatch() : m_pti(NULL) {}
+    ~CBaseDispatch();
+
+    /* IDispatch methods */
+    STDMETHODIMP GetTypeInfoCount(__out UINT * pctinfo);
+
+    STDMETHODIMP GetTypeInfo(
+      REFIID riid,
+      UINT itinfo,
+      LCID lcid,
+      __deref_out ITypeInfo ** pptinfo);
+
+    STDMETHODIMP GetIDsOfNames(
+      REFIID riid,
+      __in_ecount(cNames) LPOLESTR * rgszNames,
+      UINT cNames,
+      LCID lcid,
+      __out_ecount(cNames) DISPID * rgdispid);
+};
+
+
+class AM_NOVTABLE CMediaControl :
+    public IMediaControl,
+    public CUnknown
+{
+    CBaseDispatch m_basedisp;
+
+public:
+
+    CMediaControl(const TCHAR *, LPUNKNOWN);
+
+    DECLARE_IUNKNOWN
+
+    // override this to publicise our interfaces
+    STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
+
+    /* IDispatch methods */
+    STDMETHODIMP GetTypeInfoCount(__out UINT * pctinfo);
+
+    STDMETHODIMP GetTypeInfo(
+      UINT itinfo,
+      LCID lcid,
+      __deref_out ITypeInfo ** pptinfo);
+
+    STDMETHODIMP GetIDsOfNames(
+      REFIID riid,
+      __in_ecount(cNames) LPOLESTR * rgszNames,
+      UINT cNames,
+      LCID lcid,
+      __out_ecount(cNames) DISPID * rgdispid);
+
+    STDMETHODIMP Invoke(
+      DISPID dispidMember,
+      REFIID riid,
+      LCID lcid,
+      WORD wFlags,
+      __in DISPPARAMS * pdispparams,
+      __out_opt VARIANT * pvarResult,
+      __out_opt EXCEPINFO * pexcepinfo,
+      __out_opt UINT * puArgErr);
+};
+
+
+class AM_NOVTABLE CMediaEvent :
+    public IMediaEventEx,
+    public CUnknown
+{
+    CBaseDispatch m_basedisp;
+
+public:
+
+    CMediaEvent(__in_opt LPCTSTR, __in_opt LPUNKNOWN);
+
+    DECLARE_IUNKNOWN
+
+    // override this to publicise our interfaces
+    STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
+
+    /* IDispatch methods */
+    STDMETHODIMP GetTypeInfoCount(__out UINT * pctinfo);
+
+    STDMETHODIMP GetTypeInfo(
+      UINT itinfo,
+      LCID lcid,
+      __deref_out ITypeInfo ** pptinfo);
+
+    STDMETHODIMP GetIDsOfNames(
+      REFIID riid,
+      __in_ecount(cNames) LPOLESTR * rgszNames,
+      UINT cNames,
+      LCID lcid,
+      __out_ecount(cNames) DISPID * rgdispid);
+
+    STDMETHODIMP Invoke(
+      DISPID dispidMember,
+      REFIID riid,
+      LCID lcid,
+      WORD wFlags,
+      __in DISPPARAMS * pdispparams,
+      __out_opt VARIANT * pvarResult,
+      __out_opt EXCEPINFO * pexcepinfo,
+      __out_opt UINT * puArgErr);
+};
+
+
+class AM_NOVTABLE CMediaPosition :
+    public IMediaPosition,
+    public CUnknown
+{
+    CBaseDispatch m_basedisp;
+
+
+public:
+
+    CMediaPosition(__in_opt LPCTSTR, __in_opt LPUNKNOWN);
+    CMediaPosition(__in_opt LPCTSTR, __in_opt LPUNKNOWN, __inout HRESULT *phr);
+
+    DECLARE_IUNKNOWN
+
+    // override this to publicise our interfaces
+    STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
+
+    /* IDispatch methods */
+    STDMETHODIMP GetTypeInfoCount(__out UINT * pctinfo);
+
+    STDMETHODIMP GetTypeInfo(
+      UINT itinfo,
+      LCID lcid,
+      __deref_out ITypeInfo ** pptinfo);
+
+    STDMETHODIMP GetIDsOfNames(
+      REFIID riid,
+      __in_ecount(cNames) LPOLESTR * rgszNames,
+      UINT cNames,
+      LCID lcid,
+      __out_ecount(cNames) DISPID * rgdispid);
+
+    STDMETHODIMP Invoke(
+      DISPID dispidMember,
+      REFIID riid,
+      LCID lcid,
+      WORD wFlags,
+      __in DISPPARAMS * pdispparams,
+      __out_opt VARIANT * pvarResult,
+      __out_opt EXCEPINFO * pexcepinfo,
+      __out_opt UINT * puArgErr);
+
+};
+
+
+// OA-compatibility means that we must use double as the RefTime value,
+// and REFERENCE_TIME (essentially a LONGLONG) within filters.
+// this class converts between the two
+
+class COARefTime : public CRefTime {
+public:
+
+    COARefTime() {
+    };
+
+    COARefTime(CRefTime t)
+        : CRefTime(t)
+    {
+    };
+
+    COARefTime(REFERENCE_TIME t)
+        : CRefTime(t)
+    {
+    };
+
+    COARefTime(double d) {
+        m_time = (LONGLONG) (d * 10000000);
+    };
+
+    operator double() {
+        return double(m_time) / 10000000;
+    };
+
+    operator REFERENCE_TIME() {
+        return m_time;
+    };
+
+    COARefTime& operator=(const double& rd)  {
+        m_time = (LONGLONG) (rd * 10000000);
+        return *this;
+    }
+
+    COARefTime& operator=(const REFERENCE_TIME& rt)  {
+        m_time = rt;
+        return *this;
+    }
+
+    inline BOOL operator==(const COARefTime& rt)
+    {
+        return m_time == rt.m_time;
+    };
+
+    inline BOOL operator!=(const COARefTime& rt)
+    {
+        return m_time != rt.m_time;
+    };
+
+    inline BOOL operator < (const COARefTime& rt)
+    {
+        return m_time < rt.m_time;
+    };
+
+    inline BOOL operator > (const COARefTime& rt)
+    {
+        return m_time > rt.m_time;
+    };
+
+    inline BOOL operator >= (const COARefTime& rt)
+    {
+        return m_time >= rt.m_time;
+    };
+
+    inline BOOL operator <= (const COARefTime& rt)
+    {
+        return m_time <= rt.m_time;
+    };
+
+    inline COARefTime operator+(const COARefTime& rt)
+    {
+        return COARefTime(m_time + rt.m_time);
+    };
+
+    inline COARefTime operator-(const COARefTime& rt)
+    {
+        return COARefTime(m_time - rt.m_time);
+    };
+
+    inline COARefTime operator*(LONG l)
+    {
+        return COARefTime(m_time * l);
+    };
+
+    inline COARefTime operator/(LONG l)
+    {
+        return COARefTime(m_time / l);
+    };
+
+private:
+    //  Prevent bugs from constructing from LONG (which gets
+    //  converted to double and then multiplied by 10000000
+    COARefTime(LONG);
+    LONG operator=(LONG);
+};
+
+
+// A utility class that handles IMediaPosition and IMediaSeeking on behalf
+// of single-input pin renderers, or transform filters.
+//
+// Renderers will expose this from the filter; transform filters will
+// expose it from the output pin and not the renderer.
+//
+// Create one of these, giving it your IPin* for your input pin, and delegate
+// all IMediaPosition methods to it. It will query the input pin for
+// IMediaPosition and respond appropriately.
+//
+// Call ForceRefresh if the pin connection changes.
+//
+// This class no longer caches the upstream IMediaPosition or IMediaSeeking
+// it acquires it on each method call. This means ForceRefresh is not needed.
+// The method is kept for source compatibility and to minimise the changes
+// if we need to put it back later for performance reasons.
+
+class CPosPassThru : public IMediaSeeking, public CMediaPosition
+{
+    IPin *m_pPin;
+
+    HRESULT GetPeer(__deref_out IMediaPosition **ppMP);
+    HRESULT GetPeerSeeking(__deref_out IMediaSeeking **ppMS);
+
+public:
+
+    CPosPassThru(__in_opt LPCTSTR, __in_opt LPUNKNOWN, __inout HRESULT*, IPin *);
+    DECLARE_IUNKNOWN
+
+    HRESULT ForceRefresh() {
+        return S_OK;
+    };
+
+    // override to return an accurate current position
+    virtual HRESULT GetMediaTime(__out LONGLONG *pStartTime, __out_opt LONGLONG *pEndTime) {
+        return E_FAIL;
+    }
+
+    STDMETHODIMP NonDelegatingQueryInterface(REFIID riid,__deref_out void **ppv);
+
+    // IMediaSeeking methods
+    STDMETHODIMP GetCapabilities( __out DWORD * pCapabilities );
+    STDMETHODIMP CheckCapabilities( __inout DWORD * pCapabilities );
+    STDMETHODIMP SetTimeFormat(const GUID * pFormat);
+    STDMETHODIMP GetTimeFormat(__out GUID *pFormat);
+    STDMETHODIMP IsUsingTimeFormat(const GUID * pFormat);
+    STDMETHODIMP IsFormatSupported( const GUID * pFormat);
+    STDMETHODIMP QueryPreferredFormat( __out GUID *pFormat);
+    STDMETHODIMP ConvertTimeFormat(__out LONGLONG * pTarget, 
+                                   __in_opt const GUID * pTargetFormat,
+                                   LONGLONG Source, 
+                                   __in_opt const GUID * pSourceFormat );
+    STDMETHODIMP SetPositions( __inout_opt LONGLONG * pCurrent, DWORD CurrentFlags
+                             , __inout_opt LONGLONG * pStop, DWORD StopFlags );
+
+    STDMETHODIMP GetPositions( __out_opt LONGLONG * pCurrent, __out_opt LONGLONG * pStop );
+    STDMETHODIMP GetCurrentPosition( __out LONGLONG * pCurrent );
+    STDMETHODIMP GetStopPosition( __out LONGLONG * pStop );
+    STDMETHODIMP SetRate( double dRate);
+    STDMETHODIMP GetRate( __out double * pdRate);
+    STDMETHODIMP GetDuration( __out LONGLONG *pDuration);
+    STDMETHODIMP GetAvailable( __out_opt LONGLONG *pEarliest, __out_opt LONGLONG *pLatest );
+    STDMETHODIMP GetPreroll( __out LONGLONG *pllPreroll );
+
+    // IMediaPosition properties
+    STDMETHODIMP get_Duration(__out REFTIME * plength);
+    STDMETHODIMP put_CurrentPosition(REFTIME llTime);
+    STDMETHODIMP get_StopTime(__out REFTIME * pllTime);
+    STDMETHODIMP put_StopTime(REFTIME llTime);
+    STDMETHODIMP get_PrerollTime(__out REFTIME * pllTime);
+    STDMETHODIMP put_PrerollTime(REFTIME llTime);
+    STDMETHODIMP get_Rate(__out double * pdRate);
+    STDMETHODIMP put_Rate(double dRate);
+    STDMETHODIMP get_CurrentPosition(__out REFTIME * pllTime);
+    STDMETHODIMP CanSeekForward(__out LONG *pCanSeekForward);
+    STDMETHODIMP CanSeekBackward(__out LONG *pCanSeekBackward);
+
+private:
+    HRESULT GetSeekingLongLong( HRESULT (__stdcall IMediaSeeking::*pMethod)( LONGLONG * ),
+                                __out LONGLONG * pll );
+};
+
+
+// Adds the ability to return a current position
+
+class CRendererPosPassThru : public CPosPassThru
+{
+    CCritSec m_PositionLock;    // Locks access to our position
+    LONGLONG m_StartMedia;      // Start media time last seen
+    LONGLONG m_EndMedia;        // And likewise the end media
+    BOOL m_bReset;              // Have media times been set
+
+public:
+
+    // Used to help with passing media times through graph
+
+    CRendererPosPassThru(__in_opt LPCTSTR, __in_opt LPUNKNOWN, __inout HRESULT*, IPin *);
+    HRESULT RegisterMediaTime(IMediaSample *pMediaSample);
+    HRESULT RegisterMediaTime(LONGLONG StartTime,LONGLONG EndTime);
+    HRESULT GetMediaTime(__out LONGLONG *pStartTime,__out_opt LONGLONG *pEndTime);
+    HRESULT ResetMediaTime();
+    HRESULT EOS();
+};
+
+STDAPI CreatePosPassThru(
+    __in_opt LPUNKNOWN pAgg,
+    BOOL bRenderer,
+    IPin *pPin,
+    __deref_out IUnknown **ppPassThru
+);
+
+// A class that handles the IDispatch part of IBasicAudio and leaves the
+// properties and methods themselves pure virtual.
+
+class AM_NOVTABLE CBasicAudio : public IBasicAudio, public CUnknown
+{
+    CBaseDispatch m_basedisp;
+
+public:
+
+    CBasicAudio(__in_opt LPCTSTR, __in_opt LPUNKNOWN);
+
+    DECLARE_IUNKNOWN
+
+    // override this to publicise our interfaces
+    STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
+
+    /* IDispatch methods */
+    STDMETHODIMP GetTypeInfoCount(__out UINT * pctinfo);
+
+    STDMETHODIMP GetTypeInfo(
+      UINT itinfo,
+      LCID lcid,
+      __deref_out ITypeInfo ** pptinfo);
+
+    STDMETHODIMP GetIDsOfNames(
+      REFIID riid,
+      __in_ecount(cNames) LPOLESTR * rgszNames,
+      UINT cNames,
+      LCID lcid,
+      __out_ecount(cNames) DISPID * rgdispid);
+
+    STDMETHODIMP Invoke(
+      DISPID dispidMember,
+      REFIID riid,
+      LCID lcid,
+      WORD wFlags,
+      __in DISPPARAMS * pdispparams,
+      __out_opt VARIANT * pvarResult,
+      __out_opt EXCEPINFO * pexcepinfo,
+      __out_opt UINT * puArgErr);
+};
+
+
+// A class that handles the IDispatch part of IBasicVideo and leaves the
+// properties and methods themselves pure virtual.
+
+class AM_NOVTABLE CBaseBasicVideo : public IBasicVideo2, public CUnknown
+{
+    CBaseDispatch m_basedisp;
+
+public:
+
+    CBaseBasicVideo(__in_opt LPCTSTR, __in_opt LPUNKNOWN);
+
+    DECLARE_IUNKNOWN
+
+    // override this to publicise our interfaces
+    STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
+
+    /* IDispatch methods */
+    STDMETHODIMP GetTypeInfoCount(__out UINT * pctinfo);
+
+    STDMETHODIMP GetTypeInfo(
+      UINT itinfo,
+      LCID lcid,
+      __deref_out ITypeInfo ** pptinfo);
+
+    STDMETHODIMP GetIDsOfNames(
+      REFIID riid,
+      __in_ecount(cNames) LPOLESTR * rgszNames,
+      UINT cNames,
+      LCID lcid,
+      __out_ecount(cNames) DISPID * rgdispid);
+
+    STDMETHODIMP Invoke(
+      DISPID dispidMember,
+      REFIID riid,
+      LCID lcid,
+      WORD wFlags,
+      __in DISPPARAMS * pdispparams,
+      __out_opt VARIANT * pvarResult,
+      __out_opt EXCEPINFO * pexcepinfo,
+      __out_opt UINT * puArgErr);
+
+    STDMETHODIMP GetPreferredAspectRatio(
+      __out long *plAspectX,
+      __out long *plAspectY)
+    {
+        return E_NOTIMPL;
+    }
+};
+
+
+// A class that handles the IDispatch part of IVideoWindow and leaves the
+// properties and methods themselves pure virtual.
+
+class AM_NOVTABLE CBaseVideoWindow : public IVideoWindow, public CUnknown
+{
+    CBaseDispatch m_basedisp;
+
+public:
+
+    CBaseVideoWindow(__in_opt LPCTSTR, __in_opt LPUNKNOWN);
+
+    DECLARE_IUNKNOWN
+
+    // override this to publicise our interfaces
+    STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
+
+    /* IDispatch methods */
+    STDMETHODIMP GetTypeInfoCount(__out UINT * pctinfo);
+
+    STDMETHODIMP GetTypeInfo(
+      UINT itinfo,
+      LCID lcid,
+      __deref_out ITypeInfo ** pptinfo);
+
+    STDMETHODIMP GetIDsOfNames(
+      REFIID riid,
+      __in_ecount(cNames) LPOLESTR * rgszNames,
+      UINT cNames,
+      LCID lcid,
+      __out_ecount(cNames) DISPID * rgdispid);
+
+    STDMETHODIMP Invoke(
+      DISPID dispidMember,
+      REFIID riid,
+      LCID lcid,
+      WORD wFlags,
+      __in DISPPARAMS * pdispparams,
+      __out_opt VARIANT * pvarResult,
+      __out_opt EXCEPINFO * pexcepinfo,
+      __out_opt UINT * puArgErr);
+};
+
+
+// abstract class to help source filters with their implementation
+// of IMediaPosition. Derive from this and set the duration (and stop
+// position). Also override NotifyChange to do something when the properties
+// change.
+
+class AM_NOVTABLE CSourcePosition : public CMediaPosition
+{
+
+public:
+    CSourcePosition(__in_opt LPCTSTR, __in_opt LPUNKNOWN, __inout HRESULT*, __in CCritSec *);
+
+    // IMediaPosition methods
+    STDMETHODIMP get_Duration(__out REFTIME * plength);
+    STDMETHODIMP put_CurrentPosition(REFTIME llTime);
+    STDMETHODIMP get_StopTime(__out REFTIME * pllTime);
+    STDMETHODIMP put_StopTime(REFTIME llTime);
+    STDMETHODIMP get_PrerollTime(__out REFTIME * pllTime);
+    STDMETHODIMP put_PrerollTime(REFTIME llTime);
+    STDMETHODIMP get_Rate(__out double * pdRate);
+    STDMETHODIMP put_Rate(double dRate);
+    STDMETHODIMP CanSeekForward(__out LONG *pCanSeekForward);
+    STDMETHODIMP CanSeekBackward(__out LONG *pCanSeekBackward);
+
+    // override if you can return the data you are actually working on
+    STDMETHODIMP get_CurrentPosition(__out REFTIME * pllTime) {
+        return E_NOTIMPL;
+    };
+
+protected:
+
+    // we call this to notify changes. Override to handle them
+    virtual HRESULT ChangeStart() PURE;
+    virtual HRESULT ChangeStop() PURE;
+    virtual HRESULT ChangeRate() PURE;
+
+    COARefTime m_Duration;
+    COARefTime m_Start;
+    COARefTime m_Stop;
+    double m_Rate;
+
+    CCritSec * m_pLock;
+};
+
+class AM_NOVTABLE CSourceSeeking :
+    public IMediaSeeking,
+    public CUnknown
+{
+
+public:
+
+    DECLARE_IUNKNOWN;
+    STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
+
+    // IMediaSeeking methods
+
+    STDMETHODIMP IsFormatSupported(const GUID * pFormat);
+    STDMETHODIMP QueryPreferredFormat(__out GUID *pFormat);
+    STDMETHODIMP SetTimeFormat(const GUID * pFormat);
+    STDMETHODIMP IsUsingTimeFormat(const GUID * pFormat);
+    STDMETHODIMP GetTimeFormat(__out GUID *pFormat);
+    STDMETHODIMP GetDuration(__out LONGLONG *pDuration);
+    STDMETHODIMP GetStopPosition(__out LONGLONG *pStop);
+    STDMETHODIMP GetCurrentPosition(__out LONGLONG *pCurrent);
+    STDMETHODIMP GetCapabilities( __out DWORD * pCapabilities );
+    STDMETHODIMP CheckCapabilities( __inout DWORD * pCapabilities );
+    STDMETHODIMP ConvertTimeFormat( __out LONGLONG * pTarget, 
+                                    __in_opt const GUID * pTargetFormat,
+                                    LONGLONG Source, 
+                                    __in_opt const GUID * pSourceFormat );
+
+    STDMETHODIMP SetPositions( __inout_opt LONGLONG * pCurrent,  DWORD CurrentFlags
+			     , __inout_opt LONGLONG * pStop,  DWORD StopFlags );
+
+    STDMETHODIMP GetPositions( __out_opt LONGLONG * pCurrent, __out_opt LONGLONG * pStop );
+
+    STDMETHODIMP GetAvailable( __out_opt LONGLONG * pEarliest, __out_opt LONGLONG * pLatest );
+    STDMETHODIMP SetRate( double dRate);
+    STDMETHODIMP GetRate( __out double * pdRate);
+    STDMETHODIMP GetPreroll(__out LONGLONG *pPreroll);
+
+
+protected:
+
+    // ctor
+    CSourceSeeking(__in_opt LPCTSTR, __in_opt LPUNKNOWN, __inout HRESULT*, __in CCritSec *);
+
+    // we call this to notify changes. Override to handle them
+    virtual HRESULT ChangeStart() PURE;
+    virtual HRESULT ChangeStop() PURE;
+    virtual HRESULT ChangeRate() PURE;
+
+    CRefTime m_rtDuration;      // length of stream
+    CRefTime m_rtStart;         // source will start here
+    CRefTime m_rtStop;          // source will stop here
+    double m_dRateSeeking;
+
+    // seeking capabilities
+    DWORD m_dwSeekingCaps;
+
+    CCritSec * m_pLock;
+};
+
+
+// Base classes supporting Deferred commands.
+
+// Deferred commands are queued by calls to methods on the IQueueCommand
+// interface, exposed by the filtergraph and by some filters. A successful
+// call to one of these methods will return an IDeferredCommand interface
+// representing the queued command.
+//
+// A CDeferredCommand object represents a single deferred command, and exposes
+// the IDeferredCommand interface as well as other methods permitting time
+// checks and actual execution. It contains a reference to the CCommandQueue
+// object on which it is queued.
+//
+// CCommandQueue is a base class providing a queue of CDeferredCommand
+// objects, and methods to add, remove, check status and invoke the queued
+// commands. A CCommandQueue object would be part of an object that
+// implemented IQueueCommand.
+
+class CCmdQueue;
+
+// take a copy of the params and store them. Release any allocated
+// memory in destructor
+
+class CDispParams : public DISPPARAMS
+{
+public:
+    CDispParams(UINT nArgs, __in_ecount(nArgs) VARIANT* pArgs, __inout_opt HRESULT *phr = NULL);
+    ~CDispParams();
+};
+
+
+// CDeferredCommand lifetime is controlled by refcounts. Caller of
+// InvokeAt.. gets a refcounted interface pointer, and the CCmdQueue
+// object also holds a refcount on us. Calling Cancel or Invoke takes
+// us off the CCmdQueue and thus reduces the refcount by 1. Once taken
+// off the queue we cannot be put back on the queue.
+
+class CDeferredCommand
+    : public CUnknown,
+      public IDeferredCommand
+{
+public:
+
+    CDeferredCommand(
+        __inout CCmdQueue * pQ,
+        __in_opt LPUNKNOWN   pUnk,               // aggregation outer unk
+        __inout HRESULT *   phr,
+        __in LPUNKNOWN   pUnkExecutor,       // object that will execute this cmd
+        REFTIME     time,
+        __in GUID*       iid,
+        long        dispidMethod,
+        short       wFlags,
+        long        cArgs,
+        __in_ecount(cArgs) VARIANT*    pDispParams,
+        __out VARIANT*    pvarResult,
+        __out short*      puArgErr,
+        BOOL        bStream
+        );
+
+    DECLARE_IUNKNOWN
+
+    // override this to publicise our interfaces
+    STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __out void **ppv);
+
+    // IDeferredCommand methods
+    STDMETHODIMP Cancel();
+    STDMETHODIMP Confidence(
+                    __out LONG* pConfidence);
+    STDMETHODIMP Postpone(
+                    REFTIME newtime);
+    STDMETHODIMP GetHResult(
+                    __out HRESULT* phrResult);
+
+    // other public methods
+
+    HRESULT Invoke();
+
+    // access methods
+
+    // returns TRUE if streamtime, FALSE if presentation time
+    BOOL IsStreamTime() {
+       return m_bStream;
+    };
+
+    CRefTime GetTime() {
+        return m_time;
+    };
+
+    REFIID GetIID() {
+        return *m_iid;
+    };
+
+    long GetMethod() {
+        return m_dispidMethod;
+    };
+
+    short GetFlags() {
+        return m_wFlags;
+    };
+
+    DISPPARAMS* GetParams() {
+        return &m_DispParams;
+    };
+
+    VARIANT* GetResult() {
+        return m_pvarResult;
+    };
+
+protected:
+
+    CCmdQueue* m_pQueue;
+
+    // pUnk for the interface that we will execute the command on
+    LPUNKNOWN   m_pUnk;
+
+    // stored command data
+    REFERENCE_TIME     m_time;
+    GUID*       m_iid;
+    long        m_dispidMethod;
+    short       m_wFlags;
+    VARIANT*    m_pvarResult;
+    BOOL        m_bStream;
+    CDispParams m_DispParams;
+    DISPID      m_DispId;         //  For get and put
+
+    // we use this for ITypeInfo access
+    CBaseDispatch   m_Dispatch;
+
+    // save retval here
+    HRESULT     m_hrResult;
+};
+
+
+// a list of CDeferredCommand objects. this is a base class providing
+// the basics of access to the list. If you want to use CDeferredCommand
+// objects then your queue needs to be derived from this class.
+
+class AM_NOVTABLE CCmdQueue
+{
+public:
+    CCmdQueue(__inout_opt HRESULT *phr = NULL);
+    virtual ~CCmdQueue();
+
+    // returns a new CDeferredCommand object that will be initialised with
+    // the parameters and will be added to the queue during construction.
+    // returns S_OK if successfully created otherwise an error and
+    // no object has been queued.
+    virtual HRESULT  New(
+        __out CDeferredCommand **ppCmd,
+        __in LPUNKNOWN   pUnk,
+        REFTIME     time,
+        __in GUID*       iid,
+        long        dispidMethod,
+        short       wFlags,
+        long        cArgs,
+        __in_ecount(cArgs) VARIANT*    pDispParams,
+        __out VARIANT*    pvarResult,
+        __out short*      puArgErr,
+        BOOL        bStream
+    );
+
+    // called by the CDeferredCommand object to add and remove itself
+    // from the queue
+    virtual HRESULT Insert(__in CDeferredCommand* pCmd);
+    virtual HRESULT Remove(__in CDeferredCommand* pCmd);
+
+    // Command-Due Checking
+    //
+    // There are two schemes of synchronisation: coarse and accurate. In
+    // coarse mode, you wait till the time arrives and then execute the cmd.
+    // In accurate mode, you wait until you are processing the sample that
+    // will appear at the time, and then execute the command. It's up to the
+    // filter which one it will implement. The filtergraph will always
+    // implement coarse mode for commands queued at the filtergraph.
+    //
+    // If you want coarse sync, you probably want to wait until there is a
+    // command due, and then execute it. You can do this by calling
+    // GetDueCommand. If you have several things to wait for, get the
+    // event handle from GetDueHandle() and when this is signalled then call
+    // GetDueCommand. Stream time will only advance between calls to Run and
+    // EndRun. Note that to avoid an extra thread there is no guarantee that
+    // if the handle is set there will be a command ready. Each time the
+    // event is signalled, call GetDueCommand (probably with a 0 timeout);
+    // This may return E_ABORT.
+    //
+    // If you want accurate sync, you must call GetCommandDueFor, passing
+    // as a parameter the stream time of the samples you are about to process.
+    // This will return:
+    //   -- a stream-time command due at or before that stream time
+    //   -- a presentation-time command due at or before the
+    //      time that stream time will be presented (only between Run
+    //      and EndRun calls, since outside of this, the mapping from
+    //      stream time to presentation time is not known.
+    //   -- any presentation-time command due now.
+    // This means that if you want accurate synchronisation on samples that
+    // might be processed during Paused mode, you need to use
+    // stream-time commands.
+    //
+    // In all cases, commands remain queued until Invoked or Cancelled. The
+    // setting and resetting of the event handle is managed entirely by this
+    // queue object.
+
+    // set the clock used for timing
+    virtual HRESULT SetSyncSource(__in_opt IReferenceClock*);
+
+    // switch to run mode. Streamtime to Presentation time mapping known.
+    virtual HRESULT Run(REFERENCE_TIME tStreamTimeOffset);
+
+    // switch to Stopped or Paused mode. Time mapping not known.
+    virtual HRESULT EndRun();
+
+    // return a pointer to the next due command. Blocks for msTimeout
+    // milliseconds until there is a due command.
+    // Stream-time commands will only become due between Run and Endrun calls.
+    // The command remains queued until invoked or cancelled.
+    // Returns E_ABORT if timeout occurs, otherwise S_OK (or other error).
+    // Returns an AddRef-ed object
+    virtual HRESULT GetDueCommand(__out CDeferredCommand ** ppCmd, long msTimeout);
+
+    // return the event handle that will be signalled whenever
+    // there are deferred commands due for execution (when GetDueCommand
+    // will not block).
+    HANDLE GetDueHandle() {
+        return HANDLE(m_evDue);
+    };
+
+    // return a pointer to a command that will be due for a given time.
+    // Pass in a stream time here. The stream time offset will be passed
+    // in via the Run method.
+    // Commands remain queued until invoked or cancelled.
+    // This method will not block. It will report VFW_E_NOT_FOUND if there
+    // are no commands due yet.
+    // Returns an AddRef-ed object
+    virtual HRESULT GetCommandDueFor(REFERENCE_TIME tStream, __out CDeferredCommand**ppCmd);
+
+    // check if a given time is due (TRUE if it is due yet)
+    BOOL CheckTime(CRefTime time, BOOL bStream) {
+
+        // if no clock, nothing is due!
+        if (!m_pClock) {
+            return FALSE;
+        }
+
+        // stream time
+        if (bStream) {
+
+            // not valid if not running
+            if (!m_bRunning) {
+                return FALSE;
+            }
+            // add on known stream time offset to get presentation time
+            time += m_StreamTimeOffset;
+        }
+
+        CRefTime Now;
+        m_pClock->GetTime((REFERENCE_TIME*)&Now);
+        return (time <= Now);
+    };
+
+protected:
+
+    // protect access to lists etc
+    CCritSec m_Lock;
+
+    // commands queued in presentation time are stored here
+    CGenericList<CDeferredCommand> m_listPresentation;
+
+    // commands queued in stream time are stored here
+    CGenericList<CDeferredCommand> m_listStream;
+
+    // set when any commands are due
+    CAMEvent m_evDue;
+
+    // creates an advise for the earliest time required, if any
+    void SetTimeAdvise(void);
+
+    // advise id from reference clock (0 if no outstanding advise)
+    DWORD_PTR m_dwAdvise;
+
+    // advise time is for this presentation time
+    CRefTime m_tCurrentAdvise;
+
+    // the reference clock we are using (addrefed)
+    IReferenceClock* m_pClock;
+
+    // true when running
+    BOOL m_bRunning;
+
+    // contains stream time offset when m_bRunning is true
+    CRefTime m_StreamTimeOffset;
+};
+
+#endif // __CTLUTIL__
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/fourcc.h b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/fourcc.h
new file mode 100644
index 0000000..19c0fcd
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/fourcc.h
@@ -0,0 +1,101 @@
+//------------------------------------------------------------------------------
+// File: FourCC.h
+//
+// Desc: DirectShow base classes.
+//
+// Copyright (c) 1992-2001 Microsoft Corporation.  All rights reserved.
+//------------------------------------------------------------------------------
+
+
+// FOURCCMap
+//
+// provides a mapping between old-style multimedia format DWORDs
+// and new-style GUIDs.
+//
+// A range of 4 billion GUIDs has been allocated to ensure that this
+// mapping can be done straightforwardly one-to-one in both directions.
+//
+// January 95
+
+
+#ifndef __FOURCC__
+#define __FOURCC__
+
+
+// Multimedia format types are marked with DWORDs built from four 8-bit
+// chars and known as FOURCCs. New multimedia AM_MEDIA_TYPE definitions include
+// a subtype GUID. In order to simplify the mapping, GUIDs in the range:
+//    XXXXXXXX-0000-0010-8000-00AA00389B71
+// are reserved for FOURCCs.
+
+class FOURCCMap : public GUID
+{
+
+public:
+    FOURCCMap();
+    FOURCCMap(DWORD Fourcc);
+    FOURCCMap(const GUID *);
+
+
+    DWORD GetFOURCC(void);
+    void SetFOURCC(DWORD fourcc);
+    void SetFOURCC(const GUID *);
+
+private:
+    void InitGUID();
+};
+
+#define GUID_Data2      0
+#define GUID_Data3     0x10
+#define GUID_Data4_1   0xaa000080
+#define GUID_Data4_2   0x719b3800
+
+inline void
+FOURCCMap::InitGUID() {
+    Data2 = GUID_Data2;
+    Data3 = GUID_Data3;
+    ((DWORD *)Data4)[0] = GUID_Data4_1;
+    ((DWORD *)Data4)[1] = GUID_Data4_2;
+}
+
+inline
+FOURCCMap::FOURCCMap() {
+    InitGUID();
+    SetFOURCC( DWORD(0));
+}
+
+inline
+FOURCCMap::FOURCCMap(DWORD fourcc)
+{
+    InitGUID();
+    SetFOURCC(fourcc);
+}
+
+inline
+FOURCCMap::FOURCCMap(const GUID * pGuid)
+{
+    InitGUID();
+    SetFOURCC(pGuid);
+}
+
+inline void
+FOURCCMap::SetFOURCC(const GUID * pGuid)
+{
+    FOURCCMap * p = (FOURCCMap*) pGuid;
+    SetFOURCC(p->GetFOURCC());
+}
+
+inline void
+FOURCCMap::SetFOURCC(DWORD fourcc)
+{
+    Data1 = fourcc;
+}
+
+inline DWORD
+FOURCCMap::GetFOURCC(void)
+{
+    return Data1;
+}
+
+#endif /* __FOURCC__ */
+
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/measure.h b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/measure.h
new file mode 100644
index 0000000..a71a075
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/measure.h
@@ -0,0 +1,222 @@
+//------------------------------------------------------------------------------
+// File: Measure.h
+//
+// Desc: DirectShow base classes.
+//
+// Copyright (c) 1992-2001 Microsoft Corporation.  All rights reserved.
+//------------------------------------------------------------------------------
+
+
+/*
+   The idea is to pepper the source code with interesting measurements and
+   have the last few thousand of these recorded in a circular buffer that
+   can be post-processed to give interesting numbers.
+
+   WHAT THE LOG LOOKS LIKE:
+
+  Time (sec)   Type        Delta  Incident_Name
+    0.055,41  NOTE      -.       Incident Nine  - Another note
+    0.055,42  NOTE      0.000,01 Incident Nine  - Another note
+    0.055,44  NOTE      0.000,02 Incident Nine  - Another note
+    0.055,45  STOP      -.       Incident Eight - Also random
+    0.055,47  START     -.       Incident Seven - Random
+    0.055,49  NOTE      0.000,05 Incident Nine  - Another note
+    ------- <etc.  there is a lot of this> ----------------
+    0.125,60  STOP      0.000,03 Msr_Stop
+    0.125,62  START     -.       Msr_Start
+    0.125,63  START     -.       Incident Two   - Start/Stop
+    0.125,65  STOP      0.000,03 Msr_Start
+    0.125,66  START     -.       Msr_Stop
+    0.125,68  STOP      0.000,05 Incident Two   - Start/Stop
+    0.125,70  STOP      0.000,04 Msr_Stop
+    0.125,72  START     -.       Msr_Start
+    0.125,73  START     -.       Incident Two   - Start/Stop
+    0.125,75  STOP      0.000,03 Msr_Start
+    0.125,77  START     -.       Msr_Stop
+    0.125,78  STOP      0.000,05 Incident Two   - Start/Stop
+    0.125,80  STOP      0.000,03 Msr_Stop
+    0.125,81  NOTE      -.       Incident Three - single Note
+    0.125,83  START     -.       Incident Four  - Start, no stop
+    0.125,85  START     -.       Incident Five  - Single Start/Stop
+    0.125,87  STOP      0.000,02 Incident Five  - Single Start/Stop
+
+Number      Average       StdDev     Smallest      Largest Incident_Name
+    10     0.000,58     0.000,10     0.000,55     0.000,85 Incident One   - Note
+    50     0.000,05     0.000,00     0.000,05     0.000,05 Incident Two   - Start/Stop
+     1     -.           -.           -.           -.       Incident Three - single Note
+     0     -.           -.           -.           -.       Incident Four  - Start, no stop
+     1     0.000,02     -.           0.000,02     0.000,02 Incident Five  - Single Start/Stop
+     0     -.           -.           -.           -.       Incident Six   - zero occurrences
+   100     0.000,25     0.000,12     0.000,02     0.000,62 Incident Seven - Random
+   100     0.000,79     0.000,48     0.000,02     0.001,92 Incident Eight - Also random
+  5895     0.000,01     0.000,01     0.000,01     0.000,56 Incident Nine  - Another note
+    10     0.000,03     0.000,00     0.000,03     0.000,04 Msr_Note
+    50     0.000,03     0.000,00     0.000,03     0.000,04 Msr_Start
+    50     0.000,04     0.000,03     0.000,03     0.000,31 Msr_Stop
+
+  WHAT IT MEANS:
+    The log shows what happened and when.  Each line shows the time at which
+    something happened (see WHAT YOU CODE below) what it was that happened
+    and (if approporate) the time since the corresponding previous event
+    (that's the delta column).
+
+    The statistics show how many times each event occurred, what the average
+    delta time was, also the standard deviation, largest and smalles delta.
+
+   WHAT YOU CODE:
+
+   Before anything else executes: - register your ids
+
+    int id1     = Msr_Register("Incident One   - Note");
+    int id2     = Msr_Register("Incident Two   - Start/Stop");
+    int id3     = Msr_Register("Incident Three - single Note");
+    etc.
+
+   At interesting moments:
+
+       // To measure a repetitive event - e.g. end of bitblt to screen
+       Msr_Note(Id9);             // e.g. "video frame hiting the screen NOW!"
+
+           or
+
+       // To measure an elapsed time e.g. time taken to decode an MPEG B-frame
+       Msr_Start(Id2);            // e.g. "Starting to decode MPEG B-frame"
+         . . .
+       MsrStop(Id2);              //      "Finished MPEG decode"
+
+   At the end:
+
+       HANDLE hFile;
+       hFile = CreateFile("Perf.log", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
+       Msr_Dump(hFile);           // This writes the log out to the file
+       CloseHandle(hFile);
+
+           or
+
+       Msr_Dump(NULL);            // This writes it to DbgLog((LOG_TRACE,0, ... ));
+                                  // but if you are writing it out to the debugger
+                                  // then the times are probably all garbage because
+                                  // the debugger can make things run awfully slow.
+
+    A given id should be used either for start / stop or Note calls.  If Notes
+    are mixed in with Starts and Stops their statistics will be gibberish.
+
+    If you code the calls in upper case i.e. MSR_START(idMunge); then you get
+    macros which will turn into nothing unless PERF is defined.
+
+    You can reset the statistical counts for a given id by calling Reset(Id).
+    They are reset by default at the start.
+    It logs Reset as a special incident, so you can see it in the log.
+
+    The log is a circular buffer in storage (to try to minimise disk I/O).
+    It overwrites the oldest entries once full.  The statistics include ALL
+    incidents since the last Reset, whether still visible in the log or not.
+*/
+
+#ifndef __MEASURE__
+#define __MEASURE__
+
+#ifdef PERF
+#define MSR_INIT() Msr_Init()
+#define MSR_TERMINATE() Msr_Terminate()
+#define MSR_REGISTER(a) Msr_Register(a)
+#define MSR_RESET(a) Msr_Reset(a)
+#define MSR_CONTROL(a) Msr_Control(a)
+#define MSR_START(a) Msr_Start(a)
+#define MSR_STOP(a) Msr_Stop(a)
+#define MSR_NOTE(a) Msr_Note(a)
+#define MSR_INTEGER(a,b) Msr_Integer(a,b)
+#define MSR_DUMP(a) Msr_Dump(a)
+#define MSR_DUMPSTATS(a) Msr_DumpStats(a)
+#else
+#define MSR_INIT() ((void)0)
+#define MSR_TERMINATE() ((void)0)
+#define MSR_REGISTER(a) 0
+#define MSR_RESET(a) ((void)0)
+#define MSR_CONTROL(a) ((void)0)
+#define MSR_START(a) ((void)0)
+#define MSR_STOP(a) ((void)0)
+#define MSR_NOTE(a) ((void)0)
+#define MSR_INTEGER(a,b) ((void)0)
+#define MSR_DUMP(a) ((void)0)
+#define MSR_DUMPSTATS(a) ((void)0)
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// This must be called first - (called by the DllEntry)
+
+void WINAPI Msr_Init(void);
+
+
+// Call this last to clean up (or just let it fall off the end - who cares?)
+
+void WINAPI Msr_Terminate(void);
+
+
+// Call this to get an Id for an "incident" that you can pass to Start, Stop or Note
+// everything that's logged is called an "incident".
+
+int  WINAPI Msr_Register(__in LPTSTR Incident);
+
+
+// Reset the statistical counts for an incident
+
+void WINAPI Msr_Reset(int Id);
+
+
+// Reset all the counts for all incidents
+#define MSR_RESET_ALL 0
+#define MSR_PAUSE 1
+#define MSR_RUN 2
+
+void WINAPI Msr_Control(int iAction);
+
+
+// log the start of an operation
+
+void WINAPI Msr_Start(int Id);
+
+
+// log the end of an operation
+
+void WINAPI Msr_Stop(int Id);
+
+
+// log a one-off or repetitive operation
+
+void WINAPI Msr_Note(int Id);
+
+
+// log an integer (on which we can see statistics later)
+void WINAPI Msr_Integer(int Id, int n);
+
+
+// print out all the vaialable log (it may have wrapped) and then the statistics.
+// When the log wraps you lose log but the statistics are still complete.
+// hFIle==NULL => use DbgLog
+// otherwise hFile must have come from CreateFile or OpenFile.
+
+void WINAPI Msr_Dump(HANDLE hFile);
+
+
+// just dump the statistics - never mind the log
+
+void WINAPI Msr_DumpStats(HANDLE hFile);
+
+// Type definitions in case you want to declare a pointer to the dump functions
+// (makes it a trifle easier to do dynamic linking
+// i.e. LoadModule, GetProcAddress and call that)
+
+// Typedefs so can declare MSR_DUMPPROC *MsrDumpStats; or whatever
+typedef void WINAPI MSR_DUMPPROC(HANDLE hFile);
+typedef void WINAPI MSR_CONTROLPROC(int iAction);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __MEASURE__
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/msgthrd.h b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/msgthrd.h
new file mode 100644
index 0000000..45adc01
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/msgthrd.h
@@ -0,0 +1,120 @@
+//------------------------------------------------------------------------------
+// File: MsgThrd.h
+//
+// Desc: DirectShow base classes - provides support for a worker thread 
+//       class to which one can asynchronously post messages.
+//
+// Copyright (c) 1992-2001 Microsoft Corporation.  All rights reserved.
+//------------------------------------------------------------------------------
+
+
+// Message class - really just a structure.
+//
+class CMsg {
+public:
+    UINT uMsg;
+    DWORD dwFlags;
+    LPVOID lpParam;
+    CAMEvent *pEvent;
+
+    CMsg(UINT u, DWORD dw, __inout_opt LPVOID lp, __in_opt CAMEvent *pEvnt)
+        : uMsg(u), dwFlags(dw), lpParam(lp), pEvent(pEvnt) {}
+
+    CMsg()
+        : uMsg(0), dwFlags(0L), lpParam(NULL), pEvent(NULL) {}
+};
+
+// This is the actual thread class.  It exports all the usual thread control
+// functions.  The created thread is different from a normal WIN32 thread in
+// that it is prompted to perform particaular tasks by responding to messages
+// posted to its message queue.
+//
+class AM_NOVTABLE CMsgThread {
+private:
+    static DWORD WINAPI DefaultThreadProc(__inout LPVOID lpParam);
+    DWORD               m_ThreadId;
+    HANDLE              m_hThread;
+
+protected:
+
+    // if you want to override GetThreadMsg to block on other things
+    // as well as this queue, you need access to this
+    CGenericList<CMsg>        m_ThreadQueue;
+    CCritSec                  m_Lock;
+    HANDLE                    m_hSem;
+    LONG                      m_lWaiting;
+
+public:
+    CMsgThread()
+        : m_ThreadId(0),
+        m_hThread(NULL),
+        m_lWaiting(0),
+        m_hSem(NULL),
+        // make a list with a cache of 5 items
+        m_ThreadQueue(NAME("MsgThread list"), 5)
+        {
+        }
+
+    ~CMsgThread();
+    // override this if you want to block on other things as well
+    // as the message loop
+    void virtual GetThreadMsg(__out CMsg *msg);
+
+    // override this if you want to do something on thread startup
+    virtual void OnThreadInit() {
+    };
+
+    BOOL CreateThread();
+
+    BOOL WaitForThreadExit(__out LPDWORD lpdwExitCode) {
+        if (m_hThread != NULL) {
+            WaitForSingleObject(m_hThread, INFINITE);
+            return GetExitCodeThread(m_hThread, lpdwExitCode);
+        }
+        return FALSE;
+    }
+
+    DWORD ResumeThread() {
+        return ::ResumeThread(m_hThread);
+    }
+
+    DWORD SuspendThread() {
+        return ::SuspendThread(m_hThread);
+    }
+
+    int GetThreadPriority() {
+        return ::GetThreadPriority(m_hThread);
+    }
+
+    BOOL SetThreadPriority(int nPriority) {
+        return ::SetThreadPriority(m_hThread, nPriority);
+    }
+
+    HANDLE GetThreadHandle() {
+        return m_hThread;
+    }
+
+    DWORD GetThreadId() {
+        return m_ThreadId;
+    }
+
+
+    void PutThreadMsg(UINT uMsg, DWORD dwMsgFlags,
+                      __in_opt LPVOID lpMsgParam, __in_opt CAMEvent *pEvent = NULL) {
+        CAutoLock lck(&m_Lock);
+        CMsg* pMsg = new CMsg(uMsg, dwMsgFlags, lpMsgParam, pEvent);
+        m_ThreadQueue.AddTail(pMsg);
+        if (m_lWaiting != 0) {
+            ReleaseSemaphore(m_hSem, m_lWaiting, 0);
+            m_lWaiting = 0;
+        }
+    }
+
+    // This is the function prototype of the function that the client
+    // supplies.  It is always called on the created thread, never on
+    // the creator thread.
+    //
+    virtual LRESULT ThreadMessageProc(
+        UINT uMsg, DWORD dwFlags, __inout_opt LPVOID lpParam, __in_opt CAMEvent *pEvent) = 0;
+};
+
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/mtype.cpp b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/mtype.cpp
new file mode 100644
index 0000000..8d99697
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/mtype.cpp
@@ -0,0 +1,483 @@
+//------------------------------------------------------------------------------
+// File: MType.cpp
+//
+// Desc: DirectShow base classes - implements a class that holds and 
+//       manages media type information.
+//
+// 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
+
+// helper class that derived pin objects can use to compare media
+// types etc. Has same data members as the struct AM_MEDIA_TYPE defined
+// in the streams IDL file, but also has (non-virtual) functions
+
+#include <streams.h>
+#include <mmreg.h>
+
+CMediaType::~CMediaType(){
+    FreeMediaType(*this);
+}
+
+
+CMediaType::CMediaType()
+{
+    InitMediaType();
+}
+
+
+CMediaType::CMediaType(const GUID * type)
+{
+    InitMediaType();
+    majortype = *type;
+}
+
+
+// copy constructor does a deep copy of the format block
+
+CMediaType::CMediaType(const AM_MEDIA_TYPE& rt, __out_opt HRESULT* phr)
+{
+    HRESULT hr = CopyMediaType(this, &rt);
+    if (FAILED(hr) && (NULL != phr)) {
+        *phr = hr;
+    }
+}
+
+
+CMediaType::CMediaType(const CMediaType& rt, __out_opt HRESULT* phr)
+{
+    HRESULT hr = CopyMediaType(this, &rt);
+    if (FAILED(hr) && (NULL != phr)) {
+        *phr = hr;
+    }
+}
+
+
+// this class inherits publicly from AM_MEDIA_TYPE so the compiler could generate
+// the following assignment operator itself, however it could introduce some
+// memory conflicts and leaks in the process because the structure contains
+// a dynamically allocated block (pbFormat) which it will not copy correctly
+
+CMediaType&
+CMediaType::operator=(const AM_MEDIA_TYPE& rt)
+{
+    Set(rt);
+    return *this;
+}
+
+CMediaType&
+CMediaType::operator=(const CMediaType& rt)
+{
+    *this = (AM_MEDIA_TYPE &) rt;
+    return *this;
+}
+
+BOOL
+CMediaType::operator == (const CMediaType& rt) const
+{
+    // I don't believe we need to check sample size or
+    // temporal compression flags, since I think these must
+    // be represented in the type, subtype and format somehow. They
+    // are pulled out as separate flags so that people who don't understand
+    // the particular format representation can still see them, but
+    // they should duplicate information in the format block.
+
+    return ((IsEqualGUID(majortype,rt.majortype) == TRUE) &&
+        (IsEqualGUID(subtype,rt.subtype) == TRUE) &&
+        (IsEqualGUID(formattype,rt.formattype) == TRUE) &&
+        (cbFormat == rt.cbFormat) &&
+        ( (cbFormat == 0) ||
+          pbFormat != NULL && rt.pbFormat != NULL &&
+          (memcmp(pbFormat, rt.pbFormat, cbFormat) == 0)));
+}
+
+
+BOOL
+CMediaType::operator != (const CMediaType& rt) const
+{
+    /* Check to see if they are equal */
+
+    if (*this == rt) {
+        return FALSE;
+    }
+    return TRUE;
+}
+
+
+HRESULT
+CMediaType::Set(const CMediaType& rt)
+{
+    return Set((AM_MEDIA_TYPE &) rt);
+}
+
+
+HRESULT
+CMediaType::Set(const AM_MEDIA_TYPE& rt)
+{
+    if (&rt != this) {
+        FreeMediaType(*this);
+        HRESULT hr = CopyMediaType(this, &rt);
+        if (FAILED(hr)) {
+            return E_OUTOFMEMORY;
+        }
+    }
+
+    return S_OK;    
+}
+
+
+BOOL
+CMediaType::IsValid() const
+{
+    return (!IsEqualGUID(majortype,GUID_NULL));
+}
+
+
+void
+CMediaType::SetType(const GUID* ptype)
+{
+    majortype = *ptype;
+}
+
+
+void
+CMediaType::SetSubtype(const GUID* ptype)
+{
+    subtype = *ptype;
+}
+
+
+ULONG
+CMediaType::GetSampleSize() const {
+    if (IsFixedSize()) {
+        return lSampleSize;
+    } else {
+        return 0;
+    }
+}
+
+
+void
+CMediaType::SetSampleSize(ULONG sz) {
+    if (sz == 0) {
+        SetVariableSize();
+    } else {
+        bFixedSizeSamples = TRUE;
+        lSampleSize = sz;
+    }
+}
+
+
+void
+CMediaType::SetVariableSize() {
+    bFixedSizeSamples = FALSE;
+}
+
+
+void
+CMediaType::SetTemporalCompression(BOOL bCompressed) {
+    bTemporalCompression = bCompressed;
+}
+
+BOOL
+CMediaType::SetFormat(__in_bcount(cb) BYTE * pformat, ULONG cb)
+{
+    if (NULL == AllocFormatBuffer(cb))
+	return(FALSE);
+
+    ASSERT(pbFormat);
+    memcpy(pbFormat, pformat, cb);
+    return(TRUE);
+}
+
+
+// set the type of the media type format block, this type defines what you
+// will actually find in the format pointer. For example FORMAT_VideoInfo or
+// FORMAT_WaveFormatEx. In the future this may be an interface pointer to a
+// property set. Before sending out media types this should be filled in.
+
+void
+CMediaType::SetFormatType(const GUID *pformattype)
+{
+    formattype = *pformattype;
+}
+
+
+// reset the format buffer
+
+void CMediaType::ResetFormatBuffer()
+{
+    if (cbFormat) {
+        CoTaskMemFree((PVOID)pbFormat);
+    }
+    cbFormat = 0;
+    pbFormat = NULL;
+}
+
+
+// allocate length bytes for the format and return a read/write pointer
+// If we cannot allocate the new block of memory we return NULL leaving
+// the original block of memory untouched (as does ReallocFormatBuffer)
+
+BYTE*
+CMediaType::AllocFormatBuffer(ULONG length)
+{
+    ASSERT(length);
+
+    // do the types have the same buffer size
+
+    if (cbFormat == length) {
+        return pbFormat;
+    }
+
+    // allocate the new format buffer
+
+    BYTE *pNewFormat = (PBYTE)CoTaskMemAlloc(length);
+    if (pNewFormat == NULL) {
+        if (length <= cbFormat) return pbFormat; //reuse the old block anyway.
+        return NULL;
+    }
+
+    // delete the old format
+
+    if (cbFormat != 0) {
+        ASSERT(pbFormat);
+        CoTaskMemFree((PVOID)pbFormat);
+    }
+
+    cbFormat = length;
+    pbFormat = pNewFormat;
+    return pbFormat;
+}
+
+
+// reallocate length bytes for the format and return a read/write pointer
+// to it. We keep as much information as we can given the new buffer size
+// if this fails the original format buffer is left untouched. The caller
+// is responsible for ensuring the size of memory required is non zero
+
+BYTE*
+CMediaType::ReallocFormatBuffer(ULONG length)
+{
+    ASSERT(length);
+
+    // do the types have the same buffer size
+
+    if (cbFormat == length) {
+        return pbFormat;
+    }
+
+    // allocate the new format buffer
+
+    BYTE *pNewFormat = (PBYTE)CoTaskMemAlloc(length);
+    if (pNewFormat == NULL) {
+        if (length <= cbFormat) return pbFormat; //reuse the old block anyway.
+        return NULL;
+    }
+
+    // copy any previous format (or part of if new is smaller)
+    // delete the old format and replace with the new one
+
+    if (cbFormat != 0) {
+        ASSERT(pbFormat);
+        memcpy(pNewFormat,pbFormat,min(length,cbFormat));
+        CoTaskMemFree((PVOID)pbFormat);
+    }
+
+    cbFormat = length;
+    pbFormat = pNewFormat;
+    return pNewFormat;
+}
+
+// initialise a media type structure
+
+void CMediaType::InitMediaType()
+{
+    ZeroMemory((PVOID)this, sizeof(*this));
+    lSampleSize = 1;
+    bFixedSizeSamples = TRUE;
+}
+
+
+// a partially specified media type can be passed to IPin::Connect
+// as a constraint on the media type used in the connection.
+// the type, subtype or format type can be null.
+BOOL
+CMediaType::IsPartiallySpecified(void) const
+{
+    if ((majortype == GUID_NULL) ||
+        (formattype == GUID_NULL)) {
+            return TRUE;
+    } else {
+        return FALSE;
+    }
+}
+
+BOOL
+CMediaType::MatchesPartial(const CMediaType* ppartial) const
+{
+    if ((ppartial->majortype != GUID_NULL) &&
+        (majortype != ppartial->majortype)) {
+            return FALSE;
+    }
+    if ((ppartial->subtype != GUID_NULL) &&
+        (subtype != ppartial->subtype)) {
+            return FALSE;
+    }
+
+    if (ppartial->formattype != GUID_NULL) {
+        // if the format block is specified then it must match exactly
+        if (formattype != ppartial->formattype) {
+            return FALSE;
+        }
+        if (cbFormat != ppartial->cbFormat) {
+            return FALSE;
+        }
+        if ((cbFormat != 0) &&
+            (memcmp(pbFormat, ppartial->pbFormat, cbFormat) != 0)) {
+                return FALSE;
+        }
+    }
+
+    return TRUE;
+
+}
+
+
+
+// general purpose function to delete a heap allocated AM_MEDIA_TYPE structure
+// which is useful when calling IEnumMediaTypes::Next as the interface
+// implementation allocates the structures which you must later delete
+// the format block may also be a pointer to an interface to release
+
+void WINAPI DeleteMediaType(__inout_opt AM_MEDIA_TYPE *pmt)
+{
+    // allow NULL pointers for coding simplicity
+
+    if (pmt == NULL) {
+        return;
+    }
+
+    FreeMediaType(*pmt);
+    CoTaskMemFree((PVOID)pmt);
+}
+
+
+// this also comes in useful when using the IEnumMediaTypes interface so
+// that you can copy a media type, you can do nearly the same by creating
+// a CMediaType object but as soon as it goes out of scope the destructor
+// will delete the memory it allocated (this takes a copy of the memory)
+
+AM_MEDIA_TYPE * WINAPI CreateMediaType(AM_MEDIA_TYPE const *pSrc)
+{
+    ASSERT(pSrc);
+
+    // Allocate a block of memory for the media type
+
+    AM_MEDIA_TYPE *pMediaType =
+        (AM_MEDIA_TYPE *)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
+
+    if (pMediaType == NULL) {
+        return NULL;
+    }
+    // Copy the variable length format block
+
+    HRESULT hr = CopyMediaType(pMediaType,pSrc);
+    if (FAILED(hr)) {
+        CoTaskMemFree((PVOID)pMediaType);
+        return NULL;
+    }
+
+    return pMediaType;
+}
+
+
+//  Copy 1 media type to another
+
+HRESULT WINAPI CopyMediaType(__out AM_MEDIA_TYPE *pmtTarget, const AM_MEDIA_TYPE *pmtSource)
+{
+    //  We'll leak if we copy onto one that already exists - there's one
+    //  case we can check like that - copying to itself.
+    ASSERT(pmtSource != pmtTarget);
+    *pmtTarget = *pmtSource;
+    if (pmtSource->cbFormat != 0) {
+        ASSERT(pmtSource->pbFormat != NULL);
+        pmtTarget->pbFormat = (PBYTE)CoTaskMemAlloc(pmtSource->cbFormat);
+        if (pmtTarget->pbFormat == NULL) {
+            pmtTarget->cbFormat = 0;
+            return E_OUTOFMEMORY;
+        } else {
+            CopyMemory((PVOID)pmtTarget->pbFormat, (PVOID)pmtSource->pbFormat,
+                       pmtTarget->cbFormat);
+        }
+    }
+    if (pmtTarget->pUnk != NULL) {
+        pmtTarget->pUnk->AddRef();
+    }
+
+    return S_OK;
+}
+
+//  Free an existing media type (ie free resources it holds)
+
+void WINAPI FreeMediaType(__inout AM_MEDIA_TYPE& mt)
+{
+    if (mt.cbFormat != 0) {
+        CoTaskMemFree((PVOID)mt.pbFormat);
+
+        // Strictly unnecessary but tidier
+        mt.cbFormat = 0;
+        mt.pbFormat = NULL;
+    }
+    if (mt.pUnk != NULL) {
+        mt.pUnk->Release();
+        mt.pUnk = NULL;
+    }
+}
+
+//  Initialize a media type from a WAVEFORMATEX
+
+STDAPI CreateAudioMediaType(
+    const WAVEFORMATEX *pwfx,
+    __out AM_MEDIA_TYPE *pmt,
+    BOOL bSetFormat
+)
+{
+    pmt->majortype            = MEDIATYPE_Audio;
+    if (pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
+        pmt->subtype = ((PWAVEFORMATEXTENSIBLE)pwfx)->SubFormat;
+    } else {
+        pmt->subtype              = FOURCCMap(pwfx->wFormatTag);
+    }
+    pmt->formattype           = FORMAT_WaveFormatEx;
+    pmt->bFixedSizeSamples    = TRUE;
+    pmt->bTemporalCompression = FALSE;
+    pmt->lSampleSize          = pwfx->nBlockAlign;
+    pmt->pUnk                 = NULL;
+    if (bSetFormat) {
+        if (pwfx->wFormatTag == WAVE_FORMAT_PCM) {
+            pmt->cbFormat         = sizeof(WAVEFORMATEX);
+        } else {
+            pmt->cbFormat         = sizeof(WAVEFORMATEX) + pwfx->cbSize;
+        }
+        pmt->pbFormat             = (PBYTE)CoTaskMemAlloc(pmt->cbFormat);
+        if (pmt->pbFormat == NULL) {
+            return E_OUTOFMEMORY;
+        }
+        if (pwfx->wFormatTag == WAVE_FORMAT_PCM) {
+            CopyMemory(pmt->pbFormat, pwfx, sizeof(PCMWAVEFORMAT));
+            ((WAVEFORMATEX *)pmt->pbFormat)->cbSize = 0;
+        } else {
+            CopyMemory(pmt->pbFormat, pwfx, pmt->cbFormat);
+        }
+    }
+    return S_OK;
+}
+
+// eliminate very many spurious warnings from MS compiler
+#pragma warning(disable:4514)
+
+#endif /* PJMEDIA_VIDEO_DEV_HAS_DSHOW */
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/mtype.h b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/mtype.h
new file mode 100644
index 0000000..fc2fe53
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/mtype.h
@@ -0,0 +1,89 @@
+//------------------------------------------------------------------------------
+// File: MtType.h
+//
+// Desc: DirectShow base classes - defines a class that holds and manages
+//       media type information.
+//
+// Copyright (c) 1992-2001 Microsoft Corporation.  All rights reserved.
+//------------------------------------------------------------------------------
+
+
+#ifndef __MTYPE__
+#define __MTYPE__
+
+/* Helper class that derived pin objects can use to compare media
+   types etc. Has same data members as the struct AM_MEDIA_TYPE defined
+   in the streams IDL file, but also has (non-virtual) functions */
+
+class CMediaType : public _AMMediaType {
+
+public:
+
+    ~CMediaType();
+    CMediaType();
+    CMediaType(const GUID * majortype);
+    CMediaType(const AM_MEDIA_TYPE&, __out_opt HRESULT* phr = NULL);
+    CMediaType(const CMediaType&, __out_opt HRESULT* phr = NULL);
+
+    CMediaType& operator=(const CMediaType&);
+    CMediaType& operator=(const AM_MEDIA_TYPE&);
+
+    BOOL operator == (const CMediaType&) const;
+    BOOL operator != (const CMediaType&) const;
+
+    HRESULT Set(const CMediaType& rt);
+    HRESULT Set(const AM_MEDIA_TYPE& rt);
+
+    BOOL IsValid() const;
+
+    const GUID *Type() const { return &majortype;} ;
+    void SetType(const GUID *);
+    const GUID *Subtype() const { return &subtype;} ;
+    void SetSubtype(const GUID *);
+
+    BOOL IsFixedSize() const {return bFixedSizeSamples; };
+    BOOL IsTemporalCompressed() const {return bTemporalCompression; };
+    ULONG GetSampleSize() const;
+
+    void SetSampleSize(ULONG sz);
+    void SetVariableSize();
+    void SetTemporalCompression(BOOL bCompressed);
+
+    // read/write pointer to format - can't change length without
+    // calling SetFormat, AllocFormatBuffer or ReallocFormatBuffer
+
+    BYTE*   Format() const {return pbFormat; };
+    ULONG   FormatLength() const { return cbFormat; };
+
+    void SetFormatType(const GUID *);
+    const GUID *FormatType() const {return &formattype; };
+    BOOL SetFormat(__in_bcount(length) BYTE *pFormat, ULONG length);
+    void ResetFormatBuffer();
+    BYTE* AllocFormatBuffer(ULONG length);
+    BYTE* ReallocFormatBuffer(ULONG length);
+
+    void InitMediaType();
+
+    BOOL MatchesPartial(const CMediaType* ppartial) const;
+    BOOL IsPartiallySpecified(void) const;
+};
+
+
+/* General purpose functions to copy and delete a task allocated AM_MEDIA_TYPE
+   structure which is useful when using the IEnumMediaFormats interface as
+   the implementation allocates the structures which you must later delete */
+
+void WINAPI DeleteMediaType(__inout_opt AM_MEDIA_TYPE *pmt);
+AM_MEDIA_TYPE * WINAPI CreateMediaType(AM_MEDIA_TYPE const *pSrc);
+HRESULT WINAPI CopyMediaType(__out AM_MEDIA_TYPE *pmtTarget, const AM_MEDIA_TYPE *pmtSource);
+void WINAPI FreeMediaType(__inout AM_MEDIA_TYPE& mt);
+
+//  Initialize a media type from a WAVEFORMATEX
+
+STDAPI CreateAudioMediaType(
+    const WAVEFORMATEX *pwfx,
+    __out AM_MEDIA_TYPE *pmt,
+    BOOL bSetFormat);
+
+#endif /* __MTYPE__ */
+
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/refclock.h b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/refclock.h
new file mode 100644
index 0000000..d2b0bb1
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/refclock.h
@@ -0,0 +1,184 @@
+//------------------------------------------------------------------------------
+// File: RefClock.h
+//
+// Desc: DirectShow base classes - defines the IReferenceClock interface.
+//
+// Copyright (c) 1992-2001 Microsoft Corporation.  All rights reserved.
+//------------------------------------------------------------------------------
+
+
+#ifndef __BASEREFCLOCK__
+#define __BASEREFCLOCK__
+
+#include <Schedule.h>
+
+const UINT RESOLUTION = 1;                      /* High resolution timer */
+const INT ADVISE_CACHE = 4;                     /* Default cache size */
+const LONGLONG MAX_TIME = 0x7FFFFFFFFFFFFFFF;   /* Maximum LONGLONG value */
+
+inline LONGLONG WINAPI ConvertToMilliseconds(const REFERENCE_TIME& RT)
+{
+    /* This converts an arbitrary value representing a reference time
+       into a MILLISECONDS value for use in subsequent system calls */
+
+    return (RT / (UNITS / MILLISECONDS));
+}
+
+/* This class hierarchy will support an IReferenceClock interface so
+   that an audio card (or other externally driven clock) can update the
+   system wide clock that everyone uses.
+
+   The interface will be pretty thin with probably just one update method
+   This interface has not yet been defined.
+ */
+
+/* This abstract base class implements the IReferenceClock
+ * interface.  Classes that actually provide clock signals (from
+ * whatever source) have to be derived from this class.
+ *
+ * The abstract class provides implementations for:
+ *  CUnknown support
+ *      locking support (CCritSec)
+ *  client advise code (creates a thread)
+ *
+ * Question: what can we do about quality?  Change the timer
+ * resolution to lower the system load?  Up the priority of the
+ * timer thread to force more responsive signals?
+ *
+ * During class construction we create a worker thread that is destroyed during
+ * destuction.  This thread executes a series of WaitForSingleObject calls,
+ * waking up when a command is given to the thread or the next wake up point
+ * is reached.  The wakeup points are determined by clients making Advise
+ * calls.
+ *
+ * Each advise call defines a point in time when they wish to be notified.  A
+ * periodic advise is a series of these such events.  We maintain a list of
+ * advise links and calculate when the nearest event notification is due for.
+ * We then call WaitForSingleObject with a timeout equal to this time.  The
+ * handle we wait on is used by the class to signal that something has changed
+ * and that we must reschedule the next event.  This typically happens when
+ * someone comes in and asks for an advise link while we are waiting for an
+ * event to timeout.
+ *
+ * While we are modifying the list of advise requests we
+ * are protected from interference through a critical section.  Clients are NOT
+ * advised through callbacks.  One shot clients have an event set, while
+ * periodic clients have a semaphore released for each event notification.  A
+ * semaphore allows a client to be kept up to date with the number of events
+ * actually triggered and be assured that they can't miss multiple events being
+ * set.
+ *
+ * Keeping track of advises is taken care of by the CAMSchedule class.
+ */
+
+class CBaseReferenceClock
+: public CUnknown, public IReferenceClock, public CCritSec, public IReferenceClockTimerControl 
+{
+protected:
+    virtual ~CBaseReferenceClock();     // Don't let me be created on the stack!
+public:
+    CBaseReferenceClock(__in_opt LPCTSTR pName, 
+                        __inout_opt LPUNKNOWN pUnk, 
+                        __inout HRESULT *phr, 
+                        __inout_opt CAMSchedule * pSched = 0 );
+
+    STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void ** ppv);
+
+    DECLARE_IUNKNOWN
+
+    /* IReferenceClock methods */
+    // Derived classes must implement GetPrivateTime().  All our GetTime
+    // does is call GetPrivateTime and then check so that time does not
+    // go backwards.  A return code of S_FALSE implies that the internal
+    // clock has gone backwards and GetTime time has halted until internal
+    // time has caught up. (Don't know if this will be much use to folk,
+    // but it seems odd not to use the return code for something useful.)
+    STDMETHODIMP GetTime(__out REFERENCE_TIME *pTime);
+    // When this is called, it sets m_rtLastGotTime to the time it returns.
+
+    /* Provide standard mechanisms for scheduling events */
+
+    /* Ask for an async notification that a time has elapsed */
+    STDMETHODIMP AdviseTime(
+        REFERENCE_TIME baseTime,        // base reference time
+        REFERENCE_TIME streamTime,      // stream offset time
+        HEVENT hEvent,                  // advise via this event
+        __out DWORD_PTR *pdwAdviseCookie// where your cookie goes
+    );
+
+    /* Ask for an asynchronous periodic notification that a time has elapsed */
+    STDMETHODIMP AdvisePeriodic(
+        REFERENCE_TIME StartTime,       // starting at this time
+        REFERENCE_TIME PeriodTime,      // time between notifications
+        HSEMAPHORE hSemaphore,          // advise via a semaphore
+        __out DWORD_PTR *pdwAdviseCookie// where your cookie goes
+    );
+
+    /* Cancel a request for notification(s) - if the notification was
+     * a one shot timer then this function doesn't need to be called
+     * as the advise is automatically cancelled, however it does no
+     * harm to explicitly cancel a one-shot advise.  It is REQUIRED that
+     * clients call Unadvise to clear a Periodic advise setting.
+     */
+
+    STDMETHODIMP Unadvise(DWORD_PTR dwAdviseCookie);
+
+    /* Methods for the benefit of derived classes or outer objects */
+
+    // GetPrivateTime() is the REAL clock.  GetTime is just a cover for
+    // it.  Derived classes will probably override this method but not
+    // GetTime() itself.
+    // The important point about GetPrivateTime() is it's allowed to go
+    // backwards.  Our GetTime() will keep returning the LastGotTime
+    // until GetPrivateTime() catches up.
+    virtual REFERENCE_TIME GetPrivateTime();
+
+    /* Provide a method for correcting drift */
+    STDMETHODIMP SetTimeDelta( const REFERENCE_TIME& TimeDelta );
+
+    CAMSchedule * GetSchedule() const { return m_pSchedule; }
+
+    // IReferenceClockTimerControl methods
+    //
+    // Setting a default of 0 disables the default of 1ms
+    STDMETHODIMP SetDefaultTimerResolution(
+        REFERENCE_TIME timerResolution // in 100ns
+    );
+    STDMETHODIMP GetDefaultTimerResolution(
+        __out REFERENCE_TIME* pTimerResolution // in 100ns
+    );
+
+private:
+    REFERENCE_TIME m_rtPrivateTime;     // Current best estimate of time
+    DWORD          m_dwPrevSystemTime;  // Last vaule we got from timeGetTime
+    REFERENCE_TIME m_rtLastGotTime;     // Last time returned by GetTime
+    REFERENCE_TIME m_rtNextAdvise;      // Time of next advise
+    UINT           m_TimerResolution;
+
+#ifdef PERF
+    int m_idGetSystemTime;
+#endif
+
+// Thread stuff
+public:
+    void TriggerThread()    // Wakes thread up.  Need to do this if
+    {                       // time to next advise needs reevaluating.
+        EXECUTE_ASSERT(SetEvent(m_pSchedule->GetEvent()));
+    }
+
+
+private:
+    BOOL           m_bAbort;            // Flag used for thread shutdown
+    HANDLE         m_hThread;           // Thread handle
+
+    HRESULT AdviseThread();             // Method in which the advise thread runs
+    static DWORD __stdcall AdviseThreadFunction(__in LPVOID); // Function used to get there
+
+protected:
+    CAMSchedule * m_pSchedule;
+
+    void Restart (IN REFERENCE_TIME rtMinTime = 0I64) ;
+};
+
+#endif
+
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/reftime.h b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/reftime.h
new file mode 100644
index 0000000..5bc99a6
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/reftime.h
@@ -0,0 +1,116 @@
+//------------------------------------------------------------------------------
+// File: RefTime.h
+//
+// Desc: DirectShow base classes - defines CRefTime, a class that manages
+//       reference times.
+//
+// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
+//------------------------------------------------------------------------------
+
+
+//
+// CRefTime
+//
+// Manage reference times.
+// Shares same data layout as REFERENCE_TIME, but adds some (nonvirtual)
+// functions providing simple comparison, conversion and arithmetic.
+//
+// A reference time (at the moment) is a unit of seconds represented in
+// 100ns units as is used in the Win32 FILETIME structure. BUT the time
+// a REFERENCE_TIME represents is NOT the time elapsed since 1/1/1601 it
+// will either be stream time or reference time depending upon context
+//
+// This class provides simple arithmetic operations on reference times
+//
+// keep non-virtual otherwise the data layout will not be the same as
+// REFERENCE_TIME
+
+
+// -----
+// note that you are safe to cast a CRefTime* to a REFERENCE_TIME*, but
+// you will need to do so explicitly
+// -----
+
+
+#ifndef __REFTIME__
+#define __REFTIME__
+
+
+const LONGLONG MILLISECONDS = (1000);            // 10 ^ 3
+const LONGLONG NANOSECONDS = (1000000000);       // 10 ^ 9
+const LONGLONG UNITS = (NANOSECONDS / 100);      // 10 ^ 7
+
+/*  Unfortunately an inline function here generates a call to __allmul
+    - even for constants!
+*/
+#define MILLISECONDS_TO_100NS_UNITS(lMs) \
+    Int32x32To64((lMs), (UNITS / MILLISECONDS))
+
+class CRefTime
+{
+public:
+
+    // *MUST* be the only data member so that this class is exactly
+    // equivalent to a REFERENCE_TIME.
+    // Also, must be *no virtual functions*
+
+    REFERENCE_TIME m_time;
+
+    inline CRefTime()
+    {
+        // default to 0 time
+        m_time = 0;
+    };
+
+    inline CRefTime(LONG msecs)
+    {
+        m_time = MILLISECONDS_TO_100NS_UNITS(msecs);
+    };
+
+    inline CRefTime(REFERENCE_TIME rt)
+    {
+        m_time = rt;
+    };
+
+    inline operator REFERENCE_TIME() const
+    {
+        return m_time;
+    };
+
+    inline CRefTime& operator=(const CRefTime& rt)
+    {
+        m_time = rt.m_time;
+        return *this;
+    };
+
+    inline CRefTime& operator=(const LONGLONG ll)
+    {
+        m_time = ll;
+        return *this;
+    };
+
+    inline CRefTime& operator+=(const CRefTime& rt)
+    {
+        return (*this = *this + rt);
+    };
+
+    inline CRefTime& operator-=(const CRefTime& rt)
+    {
+        return (*this = *this - rt);
+    };
+
+    inline LONG Millisecs(void)
+    {
+        return (LONG)(m_time / (UNITS / MILLISECONDS));
+    };
+
+    inline LONGLONG GetUnits(void)
+    {
+        return m_time;
+    };
+};
+
+const LONGLONG TimeZero = 0;
+
+#endif /* __REFTIME__ */
+
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/renbase.cpp b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/renbase.cpp
new file mode 100644
index 0000000..b354b5f
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/renbase.cpp
@@ -0,0 +1,2862 @@
+//------------------------------------------------------------------------------
+// File: RenBase.cpp
+//
+// Desc: DirectShow base classes.
+//
+// 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>        // DirectShow base class definitions
+#include <mmsystem.h>       // Needed for definition of timeGetTime
+#include <limits.h>         // Standard data type limit definitions
+#include <measure.h>        // Used for time critical log functions
+
+#pragma warning(disable:4355)
+
+//  Helper function for clamping time differences
+int inline TimeDiff(REFERENCE_TIME rt)
+{
+    if (rt < - (50 * UNITS)) {
+        return -(50 * UNITS);
+    } else
+    if (rt > 50 * UNITS) {
+        return 50 * UNITS;
+    } else return (int)rt;
+}
+
+// Implements the CBaseRenderer class
+
+CBaseRenderer::CBaseRenderer(REFCLSID RenderClass, // CLSID for this renderer
+                             __in_opt LPCTSTR pName,         // Debug ONLY description
+                             __inout_opt LPUNKNOWN pUnk,       // Aggregated owner object
+                             __inout HRESULT *phr) :       // General OLE return code
+
+    CBaseFilter(pName,pUnk,&m_InterfaceLock,RenderClass),
+    m_evComplete(TRUE, phr),
+    m_RenderEvent(FALSE, phr),
+    m_bAbort(FALSE),
+    m_pPosition(NULL),
+    m_ThreadSignal(TRUE, phr),
+    m_bStreaming(FALSE),
+    m_bEOS(FALSE),
+    m_bEOSDelivered(FALSE),
+    m_pMediaSample(NULL),
+    m_dwAdvise(0),
+    m_pQSink(NULL),
+    m_pInputPin(NULL),
+    m_bRepaintStatus(TRUE),
+    m_SignalTime(0),
+    m_bInReceive(FALSE),
+    m_EndOfStreamTimer(0)
+{
+    if (SUCCEEDED(*phr)) {
+        Ready();
+#ifdef PERF
+        m_idBaseStamp = MSR_REGISTER(TEXT("BaseRenderer: sample time stamp"));
+        m_idBaseRenderTime = MSR_REGISTER(TEXT("BaseRenderer: draw time (msec)"));
+        m_idBaseAccuracy = MSR_REGISTER(TEXT("BaseRenderer: Accuracy (msec)"));
+#endif
+    }
+}
+
+
+// Delete the dynamically allocated IMediaPosition and IMediaSeeking helper
+// object. The object is created when somebody queries us. These are standard
+// control interfaces for seeking and setting start/stop positions and rates.
+// We will probably also have made an input pin based on CRendererInputPin
+// that has to be deleted, it's created when an enumerator calls our GetPin
+
+CBaseRenderer::~CBaseRenderer()
+{
+    ASSERT(m_bStreaming == FALSE);
+    ASSERT(m_EndOfStreamTimer == 0);
+    StopStreaming();
+    ClearPendingSample();
+
+    // Delete any IMediaPosition implementation
+
+    if (m_pPosition) {
+        delete m_pPosition;
+        m_pPosition = NULL;
+    }
+
+    // Delete any input pin created
+
+    if (m_pInputPin) {
+        delete m_pInputPin;
+        m_pInputPin = NULL;
+    }
+
+    // Release any Quality sink
+
+    ASSERT(m_pQSink == NULL);
+}
+
+
+// This returns the IMediaPosition and IMediaSeeking interfaces
+
+HRESULT CBaseRenderer::GetMediaPositionInterface(REFIID riid, __deref_out void **ppv)
+{
+    CAutoLock cObjectCreationLock(&m_ObjectCreationLock);
+    if (m_pPosition) {
+        return m_pPosition->NonDelegatingQueryInterface(riid,ppv);
+    }
+
+    CBasePin *pPin = GetPin(0);
+    if (NULL == pPin) {
+        return E_OUTOFMEMORY;
+    }
+
+    HRESULT hr = NOERROR;
+
+    // Create implementation of this dynamically since sometimes we may
+    // never try and do a seek. The helper object implements a position
+    // control interface (IMediaPosition) which in fact simply takes the
+    // calls normally from the filter graph and passes them upstream
+
+    m_pPosition = new CRendererPosPassThru(NAME("Renderer CPosPassThru"),
+                                           CBaseFilter::GetOwner(),
+                                           (HRESULT *) &hr,
+                                           pPin);
+    if (m_pPosition == NULL) {
+        return E_OUTOFMEMORY;
+    }
+
+    if (FAILED(hr)) {
+        delete m_pPosition;
+        m_pPosition = NULL;
+        return E_NOINTERFACE;
+    }
+    return GetMediaPositionInterface(riid,ppv);
+}
+
+
+// Overriden to say what interfaces we support and where
+
+STDMETHODIMP CBaseRenderer::NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv)
+{
+    // Do we have this interface
+
+    if (riid == IID_IMediaPosition || riid == IID_IMediaSeeking) {
+        return GetMediaPositionInterface(riid,ppv);
+    } else {
+        return CBaseFilter::NonDelegatingQueryInterface(riid,ppv);
+    }
+}
+
+
+// This is called whenever we change states, we have a manual reset event that
+// is signalled whenever we don't won't the source filter thread to wait in us
+// (such as in a stopped state) and likewise is not signalled whenever it can
+// wait (during paused and running) this function sets or resets the thread
+// event. The event is used to stop source filter threads waiting in Receive
+
+HRESULT CBaseRenderer::SourceThreadCanWait(BOOL bCanWait)
+{
+    if (bCanWait == TRUE) {
+        m_ThreadSignal.Reset();
+    } else {
+        m_ThreadSignal.Set();
+    }
+    return NOERROR;
+}
+
+
+#ifdef DEBUG
+// Dump the current renderer state to the debug terminal. The hardest part of
+// the renderer is the window where we unlock everything to wait for a clock
+// to signal it is time to draw or for the application to cancel everything
+// by stopping the filter. If we get things wrong we can leave the thread in
+// WaitForRenderTime with no way for it to ever get out and we will deadlock
+
+void CBaseRenderer::DisplayRendererState()
+{
+    DbgLog((LOG_TIMING, 1, TEXT("\nTimed out in WaitForRenderTime")));
+
+    // No way should this be signalled at this point
+
+    BOOL bSignalled = m_ThreadSignal.Check();
+    DbgLog((LOG_TIMING, 1, TEXT("Signal sanity check %d"),bSignalled));
+
+    // Now output the current renderer state variables
+
+    DbgLog((LOG_TIMING, 1, TEXT("Filter state %d"),m_State));
+
+    DbgLog((LOG_TIMING, 1, TEXT("Abort flag %d"),m_bAbort));
+
+    DbgLog((LOG_TIMING, 1, TEXT("Streaming flag %d"),m_bStreaming));
+
+    DbgLog((LOG_TIMING, 1, TEXT("Clock advise link %d"),m_dwAdvise));
+
+    DbgLog((LOG_TIMING, 1, TEXT("Current media sample %x"),m_pMediaSample));
+
+    DbgLog((LOG_TIMING, 1, TEXT("EOS signalled %d"),m_bEOS));
+
+    DbgLog((LOG_TIMING, 1, TEXT("EOS delivered %d"),m_bEOSDelivered));
+
+    DbgLog((LOG_TIMING, 1, TEXT("Repaint status %d"),m_bRepaintStatus));
+
+
+    // Output the delayed end of stream timer information
+
+    DbgLog((LOG_TIMING, 1, TEXT("End of stream timer %x"),m_EndOfStreamTimer));
+
+    DbgLog((LOG_TIMING, 1, TEXT("Deliver time %s"),CDisp((LONGLONG)m_SignalTime)));
+
+
+    // Should never timeout during a flushing state
+
+    BOOL bFlushing = m_pInputPin->IsFlushing();
+    DbgLog((LOG_TIMING, 1, TEXT("Flushing sanity check %d"),bFlushing));
+
+    // Display the time we were told to start at
+    DbgLog((LOG_TIMING, 1, TEXT("Last run time %s"),CDisp((LONGLONG)m_tStart.m_time)));
+
+    // Have we got a reference clock
+    if (m_pClock == NULL) return;
+
+    // Get the current time from the wall clock
+
+    CRefTime CurrentTime,StartTime,EndTime;
+    m_pClock->GetTime((REFERENCE_TIME*) &CurrentTime);
+    CRefTime Offset = CurrentTime - m_tStart;
+
+    // Display the current time from the clock
+
+    DbgLog((LOG_TIMING, 1, TEXT("Clock time %s"),CDisp((LONGLONG)CurrentTime.m_time)));
+
+    DbgLog((LOG_TIMING, 1, TEXT("Time difference %dms"),Offset.Millisecs()));
+
+
+    // Do we have a sample ready to render
+    if (m_pMediaSample == NULL) return;
+
+    m_pMediaSample->GetTime((REFERENCE_TIME*)&StartTime, (REFERENCE_TIME*)&EndTime);
+    DbgLog((LOG_TIMING, 1, TEXT("Next sample stream times (Start %d End %d ms)"),
+           StartTime.Millisecs(),EndTime.Millisecs()));
+
+    // Calculate how long it is until it is due for rendering
+    CRefTime Wait = (m_tStart + StartTime) - CurrentTime;
+    DbgLog((LOG_TIMING, 1, TEXT("Wait required %d ms"),Wait.Millisecs()));
+}
+#endif
+
+
+// Wait until the clock sets the timer event or we're otherwise signalled. We
+// set an arbitrary timeout for this wait and if it fires then we display the
+// current renderer state on the debugger. It will often fire if the filter's
+// left paused in an application however it may also fire during stress tests
+// if the synchronisation with application seeks and state changes is faulty
+
+#define RENDER_TIMEOUT 10000
+
+HRESULT CBaseRenderer::WaitForRenderTime()
+{
+    HANDLE WaitObjects[] = { m_ThreadSignal, m_RenderEvent };
+    DWORD Result = WAIT_TIMEOUT;
+
+    // Wait for either the time to arrive or for us to be stopped
+
+    OnWaitStart();
+    while (Result == WAIT_TIMEOUT) {
+        Result = WaitForMultipleObjects(2,WaitObjects,FALSE,RENDER_TIMEOUT);
+
+#ifdef DEBUG
+        if (Result == WAIT_TIMEOUT) DisplayRendererState();
+#endif
+
+    }
+    OnWaitEnd();
+
+    // We may have been awoken without the timer firing
+
+    if (Result == WAIT_OBJECT_0) {
+        return VFW_E_STATE_CHANGED;
+    }
+
+    SignalTimerFired();
+    return NOERROR;
+}
+
+
+// Poll waiting for Receive to complete.  This really matters when
+// Receive may set the palette and cause window messages
+// The problem is that if we don't really wait for a renderer to
+// stop processing we can deadlock waiting for a transform which
+// is calling the renderer's Receive() method because the transform's
+// Stop method doesn't know to process window messages to unblock
+// the renderer's Receive processing
+void CBaseRenderer::WaitForReceiveToComplete()
+{
+    for (;;) {
+        if (!m_bInReceive) {
+            break;
+        }
+
+        MSG msg;
+        //  Receive all interthread snedmessages
+        PeekMessage(&msg, NULL, WM_NULL, WM_NULL, PM_NOREMOVE);
+
+        Sleep(1);
+    }
+
+    // If the wakebit for QS_POSTMESSAGE is set, the PeekMessage call
+    // above just cleared the changebit which will cause some messaging
+    // calls to block (waitMessage, MsgWaitFor...) now.
+    // Post a dummy message to set the QS_POSTMESSAGE bit again
+    if (HIWORD(GetQueueStatus(QS_POSTMESSAGE)) & QS_POSTMESSAGE) {
+        //  Send dummy message
+        PostThreadMessage(GetCurrentThreadId(), WM_NULL, 0, 0);
+    }
+}
+
+// A filter can have four discrete states, namely Stopped, Running, Paused,
+// Intermediate. We are in an intermediate state if we are currently trying
+// to pause but haven't yet got the first sample (or if we have been flushed
+// in paused state and therefore still have to wait for a sample to arrive)
+
+// This class contains an event called m_evComplete which is signalled when
+// the current state is completed and is not signalled when we are waiting to
+// complete the last state transition. As mentioned above the only time we
+// use this at the moment is when we wait for a media sample in paused state
+// If while we are waiting we receive an end of stream notification from the
+// source filter then we know no data is imminent so we can reset the event
+// This means that when we transition to paused the source filter must call
+// end of stream on us or send us an image otherwise we'll hang indefinately
+
+
+// Simple internal way of getting the real state
+
+FILTER_STATE CBaseRenderer::GetRealState() {
+    return m_State;
+}
+
+
+// The renderer doesn't complete the full transition to paused states until
+// it has got one media sample to render. If you ask it for its state while
+// it's waiting it will return the state along with VFW_S_STATE_INTERMEDIATE
+
+STDMETHODIMP CBaseRenderer::GetState(DWORD dwMSecs,FILTER_STATE *State)
+{
+    CheckPointer(State,E_POINTER);
+
+    if (WaitDispatchingMessages(m_evComplete, dwMSecs) == WAIT_TIMEOUT) {
+        *State = m_State;
+        return VFW_S_STATE_INTERMEDIATE;
+    }
+    *State = m_State;
+    return NOERROR;
+}
+
+
+// If we're pausing and we have no samples we don't complete the transition
+// to State_Paused and we return S_FALSE. However if the m_bAbort flag has
+// been set then all samples are rejected so there is no point waiting for
+// one. If we do have a sample then return NOERROR. We will only ever return
+// VFW_S_STATE_INTERMEDIATE from GetState after being paused with no sample
+// (calling GetState after either being stopped or Run will NOT return this)
+
+HRESULT CBaseRenderer::CompleteStateChange(FILTER_STATE OldState)
+{
+    // Allow us to be paused when disconnected
+
+    if (m_pInputPin->IsConnected() == FALSE) {
+        Ready();
+        return S_OK;
+    }
+
+    // Have we run off the end of stream
+
+    if (IsEndOfStream() == TRUE) {
+        Ready();
+        return S_OK;
+    }
+
+    // Make sure we get fresh data after being stopped
+
+    if (HaveCurrentSample() == TRUE) {
+        if (OldState != State_Stopped) {
+            Ready();
+            return S_OK;
+        }
+    }
+    NotReady();
+    return S_FALSE;
+}
+
+
+// When we stop the filter the things we do are:-
+
+//      Decommit the allocator being used in the connection
+//      Release the source filter if it's waiting in Receive
+//      Cancel any advise link we set up with the clock
+//      Any end of stream signalled is now obsolete so reset
+//      Allow us to be stopped when we are not connected
+
+STDMETHODIMP CBaseRenderer::Stop()
+{
+    CAutoLock cRendererLock(&m_InterfaceLock);
+
+    // Make sure there really is a state change
+
+    if (m_State == State_Stopped) {
+        return NOERROR;
+    }
+
+    // Is our input pin connected
+
+    if (m_pInputPin->IsConnected() == FALSE) {
+        NOTE("Input pin is not connected");
+        m_State = State_Stopped;
+        return NOERROR;
+    }
+
+    CBaseFilter::Stop();
+
+    // If we are going into a stopped state then we must decommit whatever
+    // allocator we are using it so that any source filter waiting in the
+    // GetBuffer can be released and unlock themselves for a state change
+
+    if (m_pInputPin->Allocator()) {
+        m_pInputPin->Allocator()->Decommit();
+    }
+
+    // Cancel any scheduled rendering
+
+    SetRepaintStatus(TRUE);
+    StopStreaming();
+    SourceThreadCanWait(FALSE);
+    ResetEndOfStream();
+    CancelNotification();
+
+    // There should be no outstanding clock advise
+    ASSERT(CancelNotification() == S_FALSE);
+    ASSERT(WAIT_TIMEOUT == WaitForSingleObject((HANDLE)m_RenderEvent,0));
+    ASSERT(m_EndOfStreamTimer == 0);
+
+    Ready();
+    WaitForReceiveToComplete();
+    m_bAbort = FALSE;
+
+    return NOERROR;
+}
+
+
+// When we pause the filter the things we do are:-
+
+//      Commit the allocator being used in the connection
+//      Allow a source filter thread to wait in Receive
+//      Cancel any clock advise link (we may be running)
+//      Possibly complete the state change if we have data
+//      Allow us to be paused when we are not connected
+
+STDMETHODIMP CBaseRenderer::Pause()
+{
+    CAutoLock cRendererLock(&m_InterfaceLock);
+    FILTER_STATE OldState = m_State;
+    ASSERT(m_pInputPin->IsFlushing() == FALSE);
+
+    // Make sure there really is a state change
+
+    if (m_State == State_Paused) {
+        return CompleteStateChange(State_Paused);
+    }
+
+    // Has our input pin been connected
+
+    if (m_pInputPin->IsConnected() == FALSE) {
+        NOTE("Input pin is not connected");
+        m_State = State_Paused;
+        return CompleteStateChange(State_Paused);
+    }
+
+    // Pause the base filter class
+
+    HRESULT hr = CBaseFilter::Pause();
+    if (FAILED(hr)) {
+        NOTE("Pause failed");
+        return hr;
+    }
+
+    // Enable EC_REPAINT events again
+
+    SetRepaintStatus(TRUE);
+    StopStreaming();
+    SourceThreadCanWait(TRUE);
+    CancelNotification();
+    ResetEndOfStreamTimer();
+
+    // If we are going into a paused state then we must commit whatever
+    // allocator we are using it so that any source filter can call the
+    // GetBuffer and expect to get a buffer without returning an error
+
+    if (m_pInputPin->Allocator()) {
+        m_pInputPin->Allocator()->Commit();
+    }
+
+    // There should be no outstanding advise
+    ASSERT(CancelNotification() == S_FALSE);
+    ASSERT(WAIT_TIMEOUT == WaitForSingleObject((HANDLE)m_RenderEvent,0));
+    ASSERT(m_EndOfStreamTimer == 0);
+    ASSERT(m_pInputPin->IsFlushing() == FALSE);
+
+    // When we come out of a stopped state we must clear any image we were
+    // holding onto for frame refreshing. Since renderers see state changes
+    // first we can reset ourselves ready to accept the source thread data
+    // Paused or running after being stopped causes the current position to
+    // be reset so we're not interested in passing end of stream signals
+
+    if (OldState == State_Stopped) {
+        m_bAbort = FALSE;
+        ClearPendingSample();
+    }
+    return CompleteStateChange(OldState);
+}
+
+
+// When we run the filter the things we do are:-
+
+//      Commit the allocator being used in the connection
+//      Allow a source filter thread to wait in Receive
+//      Signal the render event just to get us going
+//      Start the base class by calling StartStreaming
+//      Allow us to be run when we are not connected
+//      Signal EC_COMPLETE if we are not connected
+
+STDMETHODIMP CBaseRenderer::Run(REFERENCE_TIME StartTime)
+{
+    CAutoLock cRendererLock(&m_InterfaceLock);
+    FILTER_STATE OldState = m_State;
+
+    // Make sure there really is a state change
+
+    if (m_State == State_Running) {
+        return NOERROR;
+    }
+
+    // Send EC_COMPLETE if we're not connected
+
+    if (m_pInputPin->IsConnected() == FALSE) {
+        NotifyEvent(EC_COMPLETE,S_OK,(LONG_PTR)(IBaseFilter *)this);
+        m_State = State_Running;
+        return NOERROR;
+    }
+
+    Ready();
+
+    // Pause the base filter class
+
+    HRESULT hr = CBaseFilter::Run(StartTime);
+    if (FAILED(hr)) {
+        NOTE("Run failed");
+        return hr;
+    }
+
+    // Allow the source thread to wait
+    ASSERT(m_pInputPin->IsFlushing() == FALSE);
+    SourceThreadCanWait(TRUE);
+    SetRepaintStatus(FALSE);
+
+    // There should be no outstanding advise
+    ASSERT(CancelNotification() == S_FALSE);
+    ASSERT(WAIT_TIMEOUT == WaitForSingleObject((HANDLE)m_RenderEvent,0));
+    ASSERT(m_EndOfStreamTimer == 0);
+    ASSERT(m_pInputPin->IsFlushing() == FALSE);
+
+    // If we are going into a running state then we must commit whatever
+    // allocator we are using it so that any source filter can call the
+    // GetBuffer and expect to get a buffer without returning an error
+
+    if (m_pInputPin->Allocator()) {
+        m_pInputPin->Allocator()->Commit();
+    }
+
+    // When we come out of a stopped state we must clear any image we were
+    // holding onto for frame refreshing. Since renderers see state changes
+    // first we can reset ourselves ready to accept the source thread data
+    // Paused or running after being stopped causes the current position to
+    // be reset so we're not interested in passing end of stream signals
+
+    if (OldState == State_Stopped) {
+        m_bAbort = FALSE;
+        ClearPendingSample();
+    }
+    return StartStreaming();
+}
+
+
+// Return the number of input pins we support
+
+int CBaseRenderer::GetPinCount()
+{
+    if (m_pInputPin == NULL) {
+        //  Try to create it
+        (void)GetPin(0);
+    }
+    return m_pInputPin != NULL ? 1 : 0;
+}
+
+
+// We only support one input pin and it is numbered zero
+
+CBasePin *CBaseRenderer::GetPin(int n)
+{
+    CAutoLock cObjectCreationLock(&m_ObjectCreationLock);
+
+    // Should only ever be called with zero
+    ASSERT(n == 0);
+
+    if (n != 0) {
+        return NULL;
+    }
+
+    // Create the input pin if not already done so
+
+    if (m_pInputPin == NULL) {
+
+        // hr must be initialized to NOERROR because
+        // CRendererInputPin's constructor only changes
+        // hr's value if an error occurs.
+        HRESULT hr = NOERROR;
+
+        m_pInputPin = new CRendererInputPin(this,&hr,L"In");
+        if (NULL == m_pInputPin) {
+            return NULL;
+        }
+
+        if (FAILED(hr)) {
+            delete m_pInputPin;
+            m_pInputPin = NULL;
+            return NULL;
+        }
+    }
+    return m_pInputPin;
+}
+
+
+// If "In" then return the IPin for our input pin, otherwise NULL and error
+
+STDMETHODIMP CBaseRenderer::FindPin(LPCWSTR Id, __deref_out IPin **ppPin)
+{
+    CheckPointer(ppPin,E_POINTER);
+
+    if (0==lstrcmpW(Id,L"In")) {
+        *ppPin = GetPin(0);
+        if (*ppPin) {
+            (*ppPin)->AddRef();
+        } else {
+            return E_OUTOFMEMORY;
+        }
+    } else {
+        *ppPin = NULL;
+        return VFW_E_NOT_FOUND;
+    }
+    return NOERROR;
+}
+
+
+// Called when the input pin receives an EndOfStream notification. If we have
+// not got a sample, then notify EC_COMPLETE now. If we have samples, then set
+// m_bEOS and check for this on completing samples. If we're waiting to pause
+// then complete the transition to paused state by setting the state event
+
+HRESULT CBaseRenderer::EndOfStream()
+{
+    // Ignore these calls if we are stopped
+
+    if (m_State == State_Stopped) {
+        return NOERROR;
+    }
+
+    // If we have a sample then wait for it to be rendered
+
+    m_bEOS = TRUE;
+    if (m_pMediaSample) {
+        return NOERROR;
+    }
+
+    // If we are waiting for pause then we are now ready since we cannot now
+    // carry on waiting for a sample to arrive since we are being told there
+    // won't be any. This sets an event that the GetState function picks up
+
+    Ready();
+
+    // Only signal completion now if we are running otherwise queue it until
+    // we do run in StartStreaming. This is used when we seek because a seek
+    // causes a pause where early notification of completion is misleading
+
+    if (m_bStreaming) {
+        SendEndOfStream();
+    }
+    return NOERROR;
+}
+
+
+// When we are told to flush we should release the source thread
+
+HRESULT CBaseRenderer::BeginFlush()
+{
+    // If paused then report state intermediate until we get some data
+
+    if (m_State == State_Paused) {
+        NotReady();
+    }
+
+    SourceThreadCanWait(FALSE);
+    CancelNotification();
+    ClearPendingSample();
+    //  Wait for Receive to complete
+    WaitForReceiveToComplete();
+
+    return NOERROR;
+}
+
+
+// After flushing the source thread can wait in Receive again
+
+HRESULT CBaseRenderer::EndFlush()
+{
+    // Reset the current sample media time
+    if (m_pPosition) m_pPosition->ResetMediaTime();
+
+    // There should be no outstanding advise
+
+    ASSERT(CancelNotification() == S_FALSE);
+    SourceThreadCanWait(TRUE);
+    return NOERROR;
+}
+
+
+// We can now send EC_REPAINTs if so required
+
+HRESULT CBaseRenderer::CompleteConnect(IPin *pReceivePin)
+{
+    // The caller should always hold the interface lock because
+    // the function uses CBaseFilter::m_State.
+    ASSERT(CritCheckIn(&m_InterfaceLock));
+
+    m_bAbort = FALSE;
+
+    if (State_Running == GetRealState()) {
+        HRESULT hr = StartStreaming();
+        if (FAILED(hr)) {
+            return hr;
+        }
+
+        SetRepaintStatus(FALSE);
+    } else {
+        SetRepaintStatus(TRUE);
+    }
+
+    return NOERROR;
+}
+
+
+// Called when we go paused or running
+
+HRESULT CBaseRenderer::Active()
+{
+    return NOERROR;
+}
+
+
+// Called when we go into a stopped state
+
+HRESULT CBaseRenderer::Inactive()
+{
+    if (m_pPosition) {
+        m_pPosition->ResetMediaTime();
+    }
+    //  People who derive from this may want to override this behaviour
+    //  to keep hold of the sample in some circumstances
+    ClearPendingSample();
+
+    return NOERROR;
+}
+
+
+// Tell derived classes about the media type agreed
+
+HRESULT CBaseRenderer::SetMediaType(const CMediaType *pmt)
+{
+    return NOERROR;
+}
+
+
+// When we break the input pin connection we should reset the EOS flags. When
+// we are asked for either IMediaPosition or IMediaSeeking we will create a
+// CPosPassThru object to handles media time pass through. When we're handed
+// samples we store (by calling CPosPassThru::RegisterMediaTime) their media
+// times so we can then return a real current position of data being rendered
+
+HRESULT CBaseRenderer::BreakConnect()
+{
+    // Do we have a quality management sink
+
+    if (m_pQSink) {
+        m_pQSink->Release();
+        m_pQSink = NULL;
+    }
+
+    // Check we have a valid connection
+
+    if (m_pInputPin->IsConnected() == FALSE) {
+        return S_FALSE;
+    }
+
+    // Check we are stopped before disconnecting
+    if (m_State != State_Stopped && !m_pInputPin->CanReconnectWhenActive()) {
+        return VFW_E_NOT_STOPPED;
+    }
+
+    SetRepaintStatus(FALSE);
+    ResetEndOfStream();
+    ClearPendingSample();
+    m_bAbort = FALSE;
+
+    if (State_Running == m_State) {
+        StopStreaming();
+    }
+
+    return NOERROR;
+}
+
+
+// Retrieves the sample times for this samples (note the sample times are
+// passed in by reference not value). We return S_FALSE to say schedule this
+// sample according to the times on the sample. We also return S_OK in
+// which case the object should simply render the sample data immediately
+
+HRESULT CBaseRenderer::GetSampleTimes(IMediaSample *pMediaSample,
+                                      __out REFERENCE_TIME *pStartTime,
+                                      __out REFERENCE_TIME *pEndTime)
+{
+    ASSERT(m_dwAdvise == 0);
+    ASSERT(pMediaSample);
+
+    // If the stop time for this sample is before or the same as start time,
+    // then just ignore it (release it) and schedule the next one in line
+    // Source filters should always fill in the start and end times properly!
+
+    if (SUCCEEDED(pMediaSample->GetTime(pStartTime, pEndTime))) {
+        if (*pEndTime < *pStartTime) {
+            return VFW_E_START_TIME_AFTER_END;
+        }
+    } else {
+        // no time set in the sample... draw it now?
+        return S_OK;
+    }
+
+    // Can't synchronise without a clock so we return S_OK which tells the
+    // caller that the sample should be rendered immediately without going
+    // through the overhead of setting a timer advise link with the clock
+
+    if (m_pClock == NULL) {
+        return S_OK;
+    }
+    return ShouldDrawSampleNow(pMediaSample,pStartTime,pEndTime);
+}
+
+
+// By default all samples are drawn according to their time stamps so we
+// return S_FALSE. Returning S_OK means draw immediately, this is used
+// by the derived video renderer class in its quality management.
+
+HRESULT CBaseRenderer::ShouldDrawSampleNow(IMediaSample *pMediaSample,
+                                           __out REFERENCE_TIME *ptrStart,
+                                           __out REFERENCE_TIME *ptrEnd)
+{
+    return S_FALSE;
+}
+
+
+// We must always reset the current advise time to zero after a timer fires
+// because there are several possible ways which lead us not to do any more
+// scheduling such as the pending image being cleared after state changes
+
+void CBaseRenderer::SignalTimerFired()
+{
+    m_dwAdvise = 0;
+}
+
+
+// Cancel any notification currently scheduled. This is called by the owning
+// window object when it is told to stop streaming. If there is no timer link
+// outstanding then calling this is benign otherwise we go ahead and cancel
+// We must always reset the render event as the quality management code can
+// signal immediate rendering by setting the event without setting an advise
+// link. If we're subsequently stopped and run the first attempt to setup an
+// advise link with the reference clock will find the event still signalled
+
+HRESULT CBaseRenderer::CancelNotification()
+{
+    ASSERT(m_dwAdvise == 0 || m_pClock);
+    DWORD_PTR dwAdvise = m_dwAdvise;
+
+    // Have we a live advise link
+
+    if (m_dwAdvise) {
+        m_pClock->Unadvise(m_dwAdvise);
+        SignalTimerFired();
+        ASSERT(m_dwAdvise == 0);
+    }
+
+    // Clear the event and return our status
+
+    m_RenderEvent.Reset();
+    return (dwAdvise ? S_OK : S_FALSE);
+}
+
+
+// Responsible for setting up one shot advise links with the clock
+// Return FALSE if the sample is to be dropped (not drawn at all)
+// Return TRUE if the sample is to be drawn and in this case also
+// arrange for m_RenderEvent to be set at the appropriate time
+
+BOOL CBaseRenderer::ScheduleSample(IMediaSample *pMediaSample)
+{
+    REFERENCE_TIME StartSample, EndSample;
+
+    // Is someone pulling our leg
+
+    if (pMediaSample == NULL) {
+        return FALSE;
+    }
+
+    // Get the next sample due up for rendering.  If there aren't any ready
+    // then GetNextSampleTimes returns an error.  If there is one to be done
+    // then it succeeds and yields the sample times. If it is due now then
+    // it returns S_OK other if it's to be done when due it returns S_FALSE
+
+    HRESULT hr = GetSampleTimes(pMediaSample, &StartSample, &EndSample);
+    if (FAILED(hr)) {
+        return FALSE;
+    }
+
+    // If we don't have a reference clock then we cannot set up the advise
+    // time so we simply set the event indicating an image to render. This
+    // will cause us to run flat out without any timing or synchronisation
+
+    if (hr == S_OK) {
+        EXECUTE_ASSERT(SetEvent((HANDLE) m_RenderEvent));
+        return TRUE;
+    }
+
+    ASSERT(m_dwAdvise == 0);
+    ASSERT(m_pClock);
+    ASSERT(WAIT_TIMEOUT == WaitForSingleObject((HANDLE)m_RenderEvent,0));
+
+    // We do have a valid reference clock interface so we can ask it to
+    // set an event when the image comes due for rendering. We pass in
+    // the reference time we were told to start at and also the current
+    // stream time which is the offset from the start reference time
+
+    hr = m_pClock->AdviseTime(
+            (REFERENCE_TIME) m_tStart,          // Start run time
+            StartSample,                        // Stream time
+            (HEVENT)(HANDLE) m_RenderEvent,     // Render notification
+            &m_dwAdvise);                       // Advise cookie
+
+    if (SUCCEEDED(hr)) {
+        return TRUE;
+    }
+
+    // We could not schedule the next sample for rendering despite the fact
+    // we have a valid sample here. This is a fair indication that either
+    // the system clock is wrong or the time stamp for the sample is duff
+
+    ASSERT(m_dwAdvise == 0);
+    return FALSE;
+}
+
+
+// This is called when a sample comes due for rendering. We pass the sample
+// on to the derived class. After rendering we will initialise the timer for
+// the next sample, NOTE signal that the last one fired first, if we don't
+// do this it thinks there is still one outstanding that hasn't completed
+
+HRESULT CBaseRenderer::Render(IMediaSample *pMediaSample)
+{
+    // If the media sample is NULL then we will have been notified by the
+    // clock that another sample is ready but in the mean time someone has
+    // stopped us streaming which causes the next sample to be released
+
+    if (pMediaSample == NULL) {
+        return S_FALSE;
+    }
+
+    // If we have stopped streaming then don't render any more samples, the
+    // thread that got in and locked us and then reset this flag does not
+    // clear the pending sample as we can use it to refresh any output device
+
+    if (m_bStreaming == FALSE) {
+        return S_FALSE;
+    }
+
+    // Time how long the rendering takes
+
+    OnRenderStart(pMediaSample);
+    DoRenderSample(pMediaSample);
+    OnRenderEnd(pMediaSample);
+
+    return NOERROR;
+}
+
+
+// Checks if there is a sample waiting at the renderer
+
+BOOL CBaseRenderer::HaveCurrentSample()
+{
+    CAutoLock cRendererLock(&m_RendererLock);
+    return (m_pMediaSample == NULL ? FALSE : TRUE);
+}
+
+
+// Returns the current sample waiting at the video renderer. We AddRef the
+// sample before returning so that should it come due for rendering the
+// person who called this method will hold the remaining reference count
+// that will stop the sample being added back onto the allocator free list
+
+IMediaSample *CBaseRenderer::GetCurrentSample()
+{
+    CAutoLock cRendererLock(&m_RendererLock);
+    if (m_pMediaSample) {
+        m_pMediaSample->AddRef();
+    }
+    return m_pMediaSample;
+}
+
+
+// Called when the source delivers us a sample. We go through a few checks to
+// make sure the sample can be rendered. If we are running (streaming) then we
+// have the sample scheduled with the reference clock, if we are not streaming
+// then we have received an sample in paused mode so we can complete any state
+// transition. On leaving this function everything will be unlocked so an app
+// thread may get in and change our state to stopped (for example) in which
+// case it will also signal the thread event so that our wait call is stopped
+
+HRESULT CBaseRenderer::PrepareReceive(IMediaSample *pMediaSample)
+{
+    CAutoLock cInterfaceLock(&m_InterfaceLock);
+    m_bInReceive = TRUE;
+
+    // Check our flushing and filter state
+
+    // This function must hold the interface lock because it calls 
+    // CBaseInputPin::Receive() and CBaseInputPin::Receive() uses
+    // CBasePin::m_bRunTimeError.
+    HRESULT hr = m_pInputPin->CBaseInputPin::Receive(pMediaSample);
+
+    if (hr != NOERROR) {
+        m_bInReceive = FALSE;
+        return E_FAIL;
+    }
+
+    // Has the type changed on a media sample. We do all rendering
+    // synchronously on the source thread, which has a side effect
+    // that only one buffer is ever outstanding. Therefore when we
+    // have Receive called we can go ahead and change the format
+    // Since the format change can cause a SendMessage we just don't
+    // lock
+    if (m_pInputPin->SampleProps()->pMediaType) {
+        hr = m_pInputPin->SetMediaType(
+                (CMediaType *)m_pInputPin->SampleProps()->pMediaType);
+        if (FAILED(hr)) {
+            m_bInReceive = FALSE;
+            return hr;
+        }
+    }
+
+
+    CAutoLock cSampleLock(&m_RendererLock);
+
+    ASSERT(IsActive() == TRUE);
+    ASSERT(m_pInputPin->IsFlushing() == FALSE);
+    ASSERT(m_pInputPin->IsConnected() == TRUE);
+    ASSERT(m_pMediaSample == NULL);
+
+    // Return an error if we already have a sample waiting for rendering
+    // source pins must serialise the Receive calls - we also check that
+    // no data is being sent after the source signalled an end of stream
+
+    if (m_pMediaSample || m_bEOS || m_bAbort) {
+        Ready();
+        m_bInReceive = FALSE;
+        return E_UNEXPECTED;
+    }
+
+    // Store the media times from this sample
+    if (m_pPosition) m_pPosition->RegisterMediaTime(pMediaSample);
+
+    // Schedule the next sample if we are streaming
+
+    if ((m_bStreaming == TRUE) && (ScheduleSample(pMediaSample) == FALSE)) {
+        ASSERT(WAIT_TIMEOUT == WaitForSingleObject((HANDLE)m_RenderEvent,0));
+        ASSERT(CancelNotification() == S_FALSE);
+        m_bInReceive = FALSE;
+        return VFW_E_SAMPLE_REJECTED;
+    }
+
+    // Store the sample end time for EC_COMPLETE handling
+    m_SignalTime = m_pInputPin->SampleProps()->tStop;
+
+    // BEWARE we sometimes keep the sample even after returning the thread to
+    // the source filter such as when we go into a stopped state (we keep it
+    // to refresh the device with) so we must AddRef it to keep it safely. If
+    // we start flushing the source thread is released and any sample waiting
+    // will be released otherwise GetBuffer may never return (see BeginFlush)
+
+    m_pMediaSample = pMediaSample;
+    m_pMediaSample->AddRef();
+
+    if (m_bStreaming == FALSE) {
+        SetRepaintStatus(TRUE);
+    }
+    return NOERROR;
+}
+
+
+// Called by the source filter when we have a sample to render. Under normal
+// circumstances we set an advise link with the clock, wait for the time to
+// arrive and then render the data using the PURE virtual DoRenderSample that
+// the derived class will have overriden. After rendering the sample we may
+// also signal EOS if it was the last one sent before EndOfStream was called
+
+HRESULT CBaseRenderer::Receive(IMediaSample *pSample)
+{
+    ASSERT(pSample);
+
+    // It may return VFW_E_SAMPLE_REJECTED code to say don't bother
+
+    HRESULT hr = PrepareReceive(pSample);
+    ASSERT(m_bInReceive == SUCCEEDED(hr));
+    if (FAILED(hr)) {
+        if (hr == VFW_E_SAMPLE_REJECTED) {
+            return NOERROR;
+        }
+        return hr;
+    }
+
+    // We realize the palette in "PrepareRender()" so we have to give away the
+    // filter lock here.
+    if (m_State == State_Paused) {
+        PrepareRender();
+        // no need to use InterlockedExchange
+        m_bInReceive = FALSE;
+        {
+            // We must hold both these locks
+            CAutoLock cRendererLock(&m_InterfaceLock);
+            if (m_State == State_Stopped)
+                return NOERROR;
+
+            m_bInReceive = TRUE;
+            CAutoLock cSampleLock(&m_RendererLock);
+            OnReceiveFirstSample(pSample);
+        }
+        Ready();
+    }
+    // Having set an advise link with the clock we sit and wait. We may be
+    // awoken by the clock firing or by a state change. The rendering call
+    // will lock the critical section and check we can still render the data
+
+    hr = WaitForRenderTime();
+    if (FAILED(hr)) {
+        m_bInReceive = FALSE;
+        return NOERROR;
+    }
+
+    PrepareRender();
+
+    //  Set this here and poll it until we work out the locking correctly
+    //  It can't be right that the streaming stuff grabs the interface
+    //  lock - after all we want to be able to wait for this stuff
+    //  to complete
+    m_bInReceive = FALSE;
+
+    // We must hold both these locks
+    CAutoLock cRendererLock(&m_InterfaceLock);
+
+    // since we gave away the filter wide lock, the sate of the filter could
+    // have chnaged to Stopped
+    if (m_State == State_Stopped)
+        return NOERROR;
+
+    CAutoLock cSampleLock(&m_RendererLock);
+
+    // Deal with this sample
+
+    Render(m_pMediaSample);
+    ClearPendingSample();
+    SendEndOfStream();
+    CancelNotification();
+    return NOERROR;
+}
+
+
+// This is called when we stop or are inactivated to clear the pending sample
+// We release the media sample interface so that they can be allocated to the
+// source filter again, unless of course we are changing state to inactive in
+// which case GetBuffer will return an error. We must also reset the current
+// media sample to NULL so that we know we do not currently have an image
+
+HRESULT CBaseRenderer::ClearPendingSample()
+{
+    CAutoLock cRendererLock(&m_RendererLock);
+    if (m_pMediaSample) {
+        m_pMediaSample->Release();
+        m_pMediaSample = NULL;
+    }
+    return NOERROR;
+}
+
+
+// Used to signal end of stream according to the sample end time
+
+void CALLBACK EndOfStreamTimer(UINT uID,        // Timer identifier
+                               UINT uMsg,       // Not currently used
+                               DWORD_PTR dwUser,// User information
+                               DWORD_PTR dw1,   // Windows reserved
+                               DWORD_PTR dw2)   // is also reserved
+{
+    CBaseRenderer *pRenderer = (CBaseRenderer *) dwUser;
+    NOTE1("EndOfStreamTimer called (%d)",uID);
+    pRenderer->TimerCallback();
+}
+
+//  Do the timer callback work
+void CBaseRenderer::TimerCallback()
+{
+    //  Lock for synchronization (but don't hold this lock when calling
+    //  timeKillEvent)
+    CAutoLock cRendererLock(&m_RendererLock);
+
+    // See if we should signal end of stream now
+
+    if (m_EndOfStreamTimer) {
+        m_EndOfStreamTimer = 0;
+        SendEndOfStream();
+    }
+}
+
+
+// If we are at the end of the stream signal the filter graph but do not set
+// the state flag back to FALSE. Once we drop off the end of the stream we
+// leave the flag set (until a subsequent ResetEndOfStream). Each sample we
+// get delivered will update m_SignalTime to be the last sample's end time.
+// We must wait this long before signalling end of stream to the filtergraph
+
+#define TIMEOUT_DELIVERYWAIT 50
+#define TIMEOUT_RESOLUTION 10
+
+HRESULT CBaseRenderer::SendEndOfStream()
+{
+    ASSERT(CritCheckIn(&m_RendererLock));
+    if (m_bEOS == FALSE || m_bEOSDelivered || m_EndOfStreamTimer) {
+        return NOERROR;
+    }
+
+    // If there is no clock then signal immediately
+    if (m_pClock == NULL) {
+        return NotifyEndOfStream();
+    }
+
+    // How long into the future is the delivery time
+
+    REFERENCE_TIME Signal = m_tStart + m_SignalTime;
+    REFERENCE_TIME CurrentTime;
+    m_pClock->GetTime(&CurrentTime);
+    LONG Delay = LONG((Signal - CurrentTime) / 10000);
+
+    // Dump the timing information to the debugger
+
+    NOTE1("Delay until end of stream delivery %d",Delay);
+    NOTE1("Current %s",(LPCTSTR)CDisp((LONGLONG)CurrentTime));
+    NOTE1("Signal %s",(LPCTSTR)CDisp((LONGLONG)Signal));
+
+    // Wait for the delivery time to arrive
+
+    if (Delay < TIMEOUT_DELIVERYWAIT) {
+        return NotifyEndOfStream();
+    }
+
+    // Signal a timer callback on another worker thread
+
+    m_EndOfStreamTimer = CompatibleTimeSetEvent((UINT) Delay, // Period of timer
+                                      TIMEOUT_RESOLUTION,     // Timer resolution
+                                      EndOfStreamTimer,       // Callback function
+                                      DWORD_PTR(this),        // Used information
+                                      TIME_ONESHOT);          // Type of callback
+    if (m_EndOfStreamTimer == 0) {
+        return NotifyEndOfStream();
+    }
+    return NOERROR;
+}
+
+
+// Signals EC_COMPLETE to the filtergraph manager
+
+HRESULT CBaseRenderer::NotifyEndOfStream()
+{
+    CAutoLock cRendererLock(&m_RendererLock);
+    ASSERT(m_bEOSDelivered == FALSE);
+    ASSERT(m_EndOfStreamTimer == 0);
+
+    // Has the filter changed state
+
+    if (m_bStreaming == FALSE) {
+        ASSERT(m_EndOfStreamTimer == 0);
+        return NOERROR;
+    }
+
+    // Reset the end of stream timer
+    m_EndOfStreamTimer = 0;
+
+    // If we've been using the IMediaPosition interface, set it's start
+    // and end media "times" to the stop position by hand.  This ensures
+    // that we actually get to the end, even if the MPEG guestimate has
+    // been bad or if the quality management dropped the last few frames
+
+    if (m_pPosition) m_pPosition->EOS();
+    m_bEOSDelivered = TRUE;
+    NOTE("Sending EC_COMPLETE...");
+    return NotifyEvent(EC_COMPLETE,S_OK,(LONG_PTR)(IBaseFilter *)this);
+}
+
+
+// Reset the end of stream flag, this is typically called when we transfer to
+// stopped states since that resets the current position back to the start so
+// we will receive more samples or another EndOfStream if there aren't any. We
+// keep two separate flags one to say we have run off the end of the stream
+// (this is the m_bEOS flag) and another to say we have delivered EC_COMPLETE
+// to the filter graph. We need the latter otherwise we can end up sending an
+// EC_COMPLETE every time the source changes state and calls our EndOfStream
+
+HRESULT CBaseRenderer::ResetEndOfStream()
+{
+    ResetEndOfStreamTimer();
+    CAutoLock cRendererLock(&m_RendererLock);
+
+    m_bEOS = FALSE;
+    m_bEOSDelivered = FALSE;
+    m_SignalTime = 0;
+
+    return NOERROR;
+}
+
+
+// Kills any outstanding end of stream timer
+
+void CBaseRenderer::ResetEndOfStreamTimer()
+{
+    ASSERT(CritCheckOut(&m_RendererLock));
+    if (m_EndOfStreamTimer) {
+        timeKillEvent(m_EndOfStreamTimer);
+        m_EndOfStreamTimer = 0;
+    }
+}
+
+
+// This is called when we start running so that we can schedule any pending
+// image we have with the clock and display any timing information. If we
+// don't have any sample but we have queued an EOS flag then we send it. If
+// we do have a sample then we wait until that has been rendered before we
+// signal the filter graph otherwise we may change state before it's done
+
+HRESULT CBaseRenderer::StartStreaming()
+{
+    CAutoLock cRendererLock(&m_RendererLock);
+    if (m_bStreaming == TRUE) {
+        return NOERROR;
+    }
+
+    // Reset the streaming times ready for running
+
+    m_bStreaming = TRUE;
+
+    timeBeginPeriod(1);
+    OnStartStreaming();
+
+    // There should be no outstanding advise
+    ASSERT(WAIT_TIMEOUT == WaitForSingleObject((HANDLE)m_RenderEvent,0));
+    ASSERT(CancelNotification() == S_FALSE);
+
+    // If we have an EOS and no data then deliver it now
+
+    if (m_pMediaSample == NULL) {
+        return SendEndOfStream();
+    }
+
+    // Have the data rendered
+
+    ASSERT(m_pMediaSample);
+    if (!ScheduleSample(m_pMediaSample))
+        m_RenderEvent.Set();
+
+    return NOERROR;
+}
+
+
+// This is called when we stop streaming so that we can set our internal flag
+// indicating we are not now to schedule any more samples arriving. The state
+// change methods in the filter implementation take care of cancelling any
+// clock advise link we have set up and clearing any pending sample we have
+
+HRESULT CBaseRenderer::StopStreaming()
+{
+    CAutoLock cRendererLock(&m_RendererLock);
+    m_bEOSDelivered = FALSE;
+
+    if (m_bStreaming == TRUE) {
+        m_bStreaming = FALSE;
+        OnStopStreaming();
+        timeEndPeriod(1);
+    }
+    return NOERROR;
+}
+
+
+// We have a boolean flag that is reset when we have signalled EC_REPAINT to
+// the filter graph. We set this when we receive an image so that should any
+// conditions arise again we can send another one. By having a flag we ensure
+// we don't flood the filter graph with redundant calls. We do not set the
+// event when we receive an EndOfStream call since there is no point in us
+// sending further EC_REPAINTs. In particular the AutoShowWindow method and
+// the DirectDraw object use this method to control the window repainting
+
+void CBaseRenderer::SetRepaintStatus(BOOL bRepaint)
+{
+    CAutoLock cSampleLock(&m_RendererLock);
+    m_bRepaintStatus = bRepaint;
+}
+
+
+// Pass the window handle to the upstream filter
+
+void CBaseRenderer::SendNotifyWindow(IPin *pPin,HWND hwnd)
+{
+    IMediaEventSink *pSink;
+
+    // Does the pin support IMediaEventSink
+    HRESULT hr = pPin->QueryInterface(IID_IMediaEventSink,(void **)&pSink);
+    if (SUCCEEDED(hr)) {
+        pSink->Notify(EC_NOTIFY_WINDOW,LONG_PTR(hwnd),0);
+        pSink->Release();
+    }
+    NotifyEvent(EC_NOTIFY_WINDOW,LONG_PTR(hwnd),0);
+}
+
+
+// Signal an EC_REPAINT to the filter graph. This can be used to have data
+// sent to us. For example when a video window is first displayed it may
+// not have an image to display, at which point it signals EC_REPAINT. The
+// filtergraph will either pause the graph if stopped or if already paused
+// it will call put_CurrentPosition of the current position. Setting the
+// current position to itself has the stream flushed and the image resent
+
+#define RLOG(_x_) DbgLog((LOG_TRACE,1,TEXT(_x_)));
+
+void CBaseRenderer::SendRepaint()
+{
+    CAutoLock cSampleLock(&m_RendererLock);
+    ASSERT(m_pInputPin);
+
+    // We should not send repaint notifications when...
+    //    - An end of stream has been notified
+    //    - Our input pin is being flushed
+    //    - The input pin is not connected
+    //    - We have aborted a video playback
+    //    - There is a repaint already sent
+
+    if (m_bAbort == FALSE) {
+        if (m_pInputPin->IsConnected() == TRUE) {
+            if (m_pInputPin->IsFlushing() == FALSE) {
+                if (IsEndOfStream() == FALSE) {
+                    if (m_bRepaintStatus == TRUE) {
+                        IPin *pPin = (IPin *) m_pInputPin;
+                        NotifyEvent(EC_REPAINT,(LONG_PTR) pPin,0);
+                        SetRepaintStatus(FALSE);
+                        RLOG("Sending repaint");
+                    }
+                }
+            }
+        }
+    }
+}
+
+
+// When a video window detects a display change (WM_DISPLAYCHANGE message) it
+// can send an EC_DISPLAY_CHANGED event code along with the renderer pin. The
+// filtergraph will stop everyone and reconnect our input pin. As we're then
+// reconnected we can accept the media type that matches the new display mode
+// since we may no longer be able to draw the current image type efficiently
+
+BOOL CBaseRenderer::OnDisplayChange()
+{
+    // Ignore if we are not connected yet
+
+    CAutoLock cSampleLock(&m_RendererLock);
+    if (m_pInputPin->IsConnected() == FALSE) {
+        return FALSE;
+    }
+
+    RLOG("Notification of EC_DISPLAY_CHANGE");
+
+    // Pass our input pin as parameter on the event
+
+    IPin *pPin = (IPin *) m_pInputPin;
+    m_pInputPin->AddRef();
+    NotifyEvent(EC_DISPLAY_CHANGED,(LONG_PTR) pPin,0);
+    SetAbortSignal(TRUE);
+    ClearPendingSample();
+    m_pInputPin->Release();
+
+    return TRUE;
+}
+
+
+// Called just before we start drawing.
+// Store the current time in m_trRenderStart to allow the rendering time to be
+// logged.  Log the time stamp of the sample and how late it is (neg is early)
+
+void CBaseRenderer::OnRenderStart(IMediaSample *pMediaSample)
+{
+#ifdef PERF
+    REFERENCE_TIME trStart, trEnd;
+    pMediaSample->GetTime(&trStart, &trEnd);
+
+    MSR_INTEGER(m_idBaseStamp, (int)trStart);     // dump low order 32 bits
+
+    m_pClock->GetTime(&m_trRenderStart);
+    MSR_INTEGER(0, (int)m_trRenderStart);
+    REFERENCE_TIME trStream;
+    trStream = m_trRenderStart-m_tStart;     // convert reftime to stream time
+    MSR_INTEGER(0,(int)trStream);
+
+    const int trLate = (int)(trStream - trStart);
+    MSR_INTEGER(m_idBaseAccuracy, trLate/10000);  // dump in mSec
+#endif
+
+} // OnRenderStart
+
+
+// Called directly after drawing an image.
+// calculate the time spent drawing and log it.
+
+void CBaseRenderer::OnRenderEnd(IMediaSample *pMediaSample)
+{
+#ifdef PERF
+    REFERENCE_TIME trNow;
+    m_pClock->GetTime(&trNow);
+    MSR_INTEGER(0,(int)trNow);
+    int t = (int)((trNow - m_trRenderStart)/10000);   // convert UNITS->msec
+    MSR_INTEGER(m_idBaseRenderTime, t);
+#endif
+} // OnRenderEnd
+
+
+
+
+// Constructor must be passed the base renderer object
+
+CRendererInputPin::CRendererInputPin(__inout CBaseRenderer *pRenderer,
+                                     __inout HRESULT *phr,
+                                     __in_opt LPCWSTR pPinName) :
+    CBaseInputPin(NAME("Renderer pin"),
+                  pRenderer,
+                  &pRenderer->m_InterfaceLock,
+                  (HRESULT *) phr,
+                  pPinName)
+{
+    m_pRenderer = pRenderer;
+    ASSERT(m_pRenderer);
+}
+
+
+// Signals end of data stream on the input pin
+
+STDMETHODIMP CRendererInputPin::EndOfStream()
+{
+    CAutoLock cRendererLock(&m_pRenderer->m_InterfaceLock);
+    CAutoLock cSampleLock(&m_pRenderer->m_RendererLock);
+
+    // Make sure we're streaming ok
+
+    HRESULT hr = CheckStreaming();
+    if (hr != NOERROR) {
+        return hr;
+    }
+
+    // Pass it onto the renderer
+
+    hr = m_pRenderer->EndOfStream();
+    if (SUCCEEDED(hr)) {
+        hr = CBaseInputPin::EndOfStream();
+    }
+    return hr;
+}
+
+
+// Signals start of flushing on the input pin - we do the final reset end of
+// stream with the renderer lock unlocked but with the interface lock locked
+// We must do this because we call timeKillEvent, our timer callback method
+// has to take the renderer lock to serialise our state. Therefore holding a
+// renderer lock when calling timeKillEvent could cause a deadlock condition
+
+STDMETHODIMP CRendererInputPin::BeginFlush()
+{
+    CAutoLock cRendererLock(&m_pRenderer->m_InterfaceLock);
+    {
+        CAutoLock cSampleLock(&m_pRenderer->m_RendererLock);
+        CBaseInputPin::BeginFlush();
+        m_pRenderer->BeginFlush();
+    }
+    return m_pRenderer->ResetEndOfStream();
+}
+
+
+// Signals end of flushing on the input pin
+
+STDMETHODIMP CRendererInputPin::EndFlush()
+{
+    CAutoLock cRendererLock(&m_pRenderer->m_InterfaceLock);
+    CAutoLock cSampleLock(&m_pRenderer->m_RendererLock);
+
+    HRESULT hr = m_pRenderer->EndFlush();
+    if (SUCCEEDED(hr)) {
+        hr = CBaseInputPin::EndFlush();
+    }
+    return hr;
+}
+
+
+// Pass the sample straight through to the renderer object
+
+STDMETHODIMP CRendererInputPin::Receive(IMediaSample *pSample)
+{
+    HRESULT hr = m_pRenderer->Receive(pSample);
+    if (FAILED(hr)) {
+
+        // A deadlock could occur if the caller holds the renderer lock and
+        // attempts to acquire the interface lock.
+        ASSERT(CritCheckOut(&m_pRenderer->m_RendererLock));
+
+        {
+            // The interface lock must be held when the filter is calling
+            // IsStopped() or IsFlushing().  The interface lock must also
+            // be held because the function uses m_bRunTimeError.
+            CAutoLock cRendererLock(&m_pRenderer->m_InterfaceLock);
+
+            // We do not report errors which occur while the filter is stopping,
+            // flushing or if the m_bAbort flag is set .  Errors are expected to 
+            // occur during these operations and the streaming thread correctly 
+            // handles the errors.  
+            if (!IsStopped() && !IsFlushing() && !m_pRenderer->m_bAbort && !m_bRunTimeError) {
+
+                // EC_ERRORABORT's first parameter is the error which caused
+                // the event and its' last parameter is 0.  See the Direct
+                // Show SDK documentation for more information.
+                m_pRenderer->NotifyEvent(EC_ERRORABORT,hr,0);
+
+                {
+                    CAutoLock alRendererLock(&m_pRenderer->m_RendererLock);
+                    if (m_pRenderer->IsStreaming() && !m_pRenderer->IsEndOfStreamDelivered()) {
+                        m_pRenderer->NotifyEndOfStream();
+                    }
+                }
+    
+                m_bRunTimeError = TRUE;
+            }
+        }
+    }
+
+    return hr;
+}
+
+
+// Called when the input pin is disconnected
+
+HRESULT CRendererInputPin::BreakConnect()
+{
+    HRESULT hr = m_pRenderer->BreakConnect();
+    if (FAILED(hr)) {
+        return hr;
+    }
+    return CBaseInputPin::BreakConnect();
+}
+
+
+// Called when the input pin is connected
+
+HRESULT CRendererInputPin::CompleteConnect(IPin *pReceivePin)
+{
+    HRESULT hr = m_pRenderer->CompleteConnect(pReceivePin);
+    if (FAILED(hr)) {
+        return hr;
+    }
+    return CBaseInputPin::CompleteConnect(pReceivePin);
+}
+
+
+// Give the pin id of our one and only pin
+
+STDMETHODIMP CRendererInputPin::QueryId(__deref_out LPWSTR *Id)
+{
+    CheckPointer(Id,E_POINTER);
+
+    const WCHAR szIn[] = L"In";
+
+    *Id = (LPWSTR)CoTaskMemAlloc(sizeof(szIn));
+    if (*Id == NULL) {
+        return E_OUTOFMEMORY;
+    }
+    CopyMemory(*Id, szIn, sizeof(szIn));
+    return NOERROR;
+}
+
+
+// Will the filter accept this media type
+
+HRESULT CRendererInputPin::CheckMediaType(const CMediaType *pmt)
+{
+    return m_pRenderer->CheckMediaType(pmt);
+}
+
+
+// Called when we go paused or running
+
+HRESULT CRendererInputPin::Active()
+{
+    return m_pRenderer->Active();
+}
+
+
+// Called when we go into a stopped state
+
+HRESULT CRendererInputPin::Inactive()
+{
+    // The caller must hold the interface lock because 
+    // this function uses m_bRunTimeError.
+    ASSERT(CritCheckIn(&m_pRenderer->m_InterfaceLock));
+
+    m_bRunTimeError = FALSE;
+
+    return m_pRenderer->Inactive();
+}
+
+
+// Tell derived classes about the media type agreed
+
+HRESULT CRendererInputPin::SetMediaType(const CMediaType *pmt)
+{
+    HRESULT hr = CBaseInputPin::SetMediaType(pmt);
+    if (FAILED(hr)) {
+        return hr;
+    }
+    return m_pRenderer->SetMediaType(pmt);
+}
+
+
+// We do not keep an event object to use when setting up a timer link with
+// the clock but are given a pointer to one by the owning object through the
+// SetNotificationObject method - this must be initialised before starting
+// We can override the default quality management process to have it always
+// draw late frames, this is currently done by having the following registry
+// key (actually an INI key) called DrawLateFrames set to 1 (default is 0)
+
+const TCHAR AMQUALITY[] = TEXT("ActiveMovie");
+const TCHAR DRAWLATEFRAMES[] = TEXT("DrawLateFrames");
+
+CBaseVideoRenderer::CBaseVideoRenderer(
+      REFCLSID RenderClass, // CLSID for this renderer
+      __in_opt LPCTSTR pName,         // Debug ONLY description
+      __inout_opt LPUNKNOWN pUnk,       // Aggregated owner object
+      __inout HRESULT *phr) :       // General OLE return code
+
+    CBaseRenderer(RenderClass,pName,pUnk,phr),
+    m_cFramesDropped(0),
+    m_cFramesDrawn(0),
+    m_bSupplierHandlingQuality(FALSE)
+{
+    ResetStreamingTimes();
+
+#ifdef PERF
+    m_idTimeStamp       = MSR_REGISTER(TEXT("Frame time stamp"));
+    m_idEarliness       = MSR_REGISTER(TEXT("Earliness fudge"));
+    m_idTarget          = MSR_REGISTER(TEXT("Target (mSec)"));
+    m_idSchLateTime     = MSR_REGISTER(TEXT("mSec late when scheduled"));
+    m_idDecision        = MSR_REGISTER(TEXT("Scheduler decision code"));
+    m_idQualityRate     = MSR_REGISTER(TEXT("Quality rate sent"));
+    m_idQualityTime     = MSR_REGISTER(TEXT("Quality time sent"));
+    m_idWaitReal        = MSR_REGISTER(TEXT("Render wait"));
+    // m_idWait            = MSR_REGISTER(TEXT("wait time recorded (msec)"));
+    m_idFrameAccuracy   = MSR_REGISTER(TEXT("Frame accuracy (msecs)"));
+    m_bDrawLateFrames = GetProfileInt(AMQUALITY, DRAWLATEFRAMES, FALSE);
+    //m_idSendQuality      = MSR_REGISTER(TEXT("Processing Quality message"));
+
+    m_idRenderAvg       = MSR_REGISTER(TEXT("Render draw time Avg"));
+    m_idFrameAvg        = MSR_REGISTER(TEXT("FrameAvg"));
+    m_idWaitAvg         = MSR_REGISTER(TEXT("WaitAvg"));
+    m_idDuration        = MSR_REGISTER(TEXT("Duration"));
+    m_idThrottle        = MSR_REGISTER(TEXT("Audio-video throttle wait"));
+    // m_idDebug           = MSR_REGISTER(TEXT("Debug stuff"));
+#endif // PERF
+} // Constructor
+
+
+// Destructor is just a placeholder
+
+CBaseVideoRenderer::~CBaseVideoRenderer()
+{
+    ASSERT(m_dwAdvise == 0);
+}
+
+
+// The timing functions in this class are called by the window object and by
+// the renderer's allocator.
+// The windows object calls timing functions as it receives media sample
+// images for drawing using GDI.
+// The allocator calls timing functions when it starts passing DCI/DirectDraw
+// surfaces which are not rendered in the same way; The decompressor writes
+// directly to the surface with no separate rendering, so those code paths
+// call direct into us.  Since we only ever hand out DCI/DirectDraw surfaces
+// when we have allocated one and only one image we know there cannot be any
+// conflict between the two.
+//
+// We use timeGetTime to return the timing counts we use (since it's relative
+// performance we are interested in rather than absolute compared to a clock)
+// The window object sets the accuracy of the system clock (normally 1ms) by
+// calling timeBeginPeriod/timeEndPeriod when it changes streaming states
+
+
+// Reset all times controlling streaming.
+// Set them so that
+// 1. Frames will not initially be dropped
+// 2. The first frame will definitely be drawn (achieved by saying that there
+//    has not ben a frame drawn for a long time).
+
+HRESULT CBaseVideoRenderer::ResetStreamingTimes()
+{
+    m_trLastDraw = -1000;     // set up as first frame since ages (1 sec) ago
+    m_tStreamingStart = timeGetTime();
+    m_trRenderAvg = 0;
+    m_trFrameAvg = -1;        // -1000 fps == "unset"
+    m_trDuration = 0;         // 0 - strange value
+    m_trRenderLast = 0;
+    m_trWaitAvg = 0;
+    m_tRenderStart = 0;
+    m_cFramesDrawn = 0;
+    m_cFramesDropped = 0;
+    m_iTotAcc = 0;
+    m_iSumSqAcc = 0;
+    m_iSumSqFrameTime = 0;
+    m_trFrame = 0;          // hygeine - not really needed
+    m_trLate = 0;           // hygeine - not really needed
+    m_iSumFrameTime = 0;
+    m_nNormal = 0;
+    m_trEarliness = 0;
+    m_trTarget = -300000;  // 30mSec early
+    m_trThrottle = 0;
+    m_trRememberStampForPerf = 0;
+
+#ifdef PERF
+    m_trRememberFrameForPerf = 0;
+#endif
+
+    return NOERROR;
+} // ResetStreamingTimes
+
+
+// Reset all times controlling streaming. Note that we're now streaming. We
+// don't need to set the rendering event to have the source filter released
+// as it is done during the Run processing. When we are run we immediately
+// release the source filter thread and draw any image waiting (that image
+// may already have been drawn once as a poster frame while we were paused)
+
+HRESULT CBaseVideoRenderer::OnStartStreaming()
+{
+    ResetStreamingTimes();
+    return NOERROR;
+} // OnStartStreaming
+
+
+// Called at end of streaming.  Fixes times for property page report
+
+HRESULT CBaseVideoRenderer::OnStopStreaming()
+{
+    m_tStreamingStart = timeGetTime()-m_tStreamingStart;
+    return NOERROR;
+} // OnStopStreaming
+
+
+// Called when we start waiting for a rendering event.
+// Used to update times spent waiting and not waiting.
+
+void CBaseVideoRenderer::OnWaitStart()
+{
+    MSR_START(m_idWaitReal);
+} // OnWaitStart
+
+
+// Called when we are awoken from the wait in the window OR by our allocator
+// when it is hanging around until the next sample is due for rendering on a
+// DCI/DirectDraw surface. We add the wait time into our rolling average.
+// We grab the interface lock so that we're serialised with the application
+// thread going through the run code - which in due course ends up calling
+// ResetStreaming times - possibly as we run through this section of code
+
+void CBaseVideoRenderer::OnWaitEnd()
+{
+#ifdef PERF
+    MSR_STOP(m_idWaitReal);
+    // for a perf build we want to know just exactly how late we REALLY are.
+    // even if this means that we have to look at the clock again.
+
+    REFERENCE_TIME trRealStream;     // the real time now expressed as stream time.
+#if 0
+    m_pClock->GetTime(&trRealStream); // Calling clock here causes W95 deadlock!
+#else
+    // We will be discarding overflows like mad here!
+    // This is wrong really because timeGetTime() can wrap but it's
+    // only for PERF
+    REFERENCE_TIME tr = timeGetTime()*10000;
+    trRealStream = tr + m_llTimeOffset;
+#endif
+    trRealStream -= m_tStart;     // convert to stream time (this is a reftime)
+
+    if (m_trRememberStampForPerf==0) {
+        // This is probably the poster frame at the start, and it is not scheduled
+        // in the usual way at all.  Just count it.  The rememberstamp gets set
+        // in ShouldDrawSampleNow, so this does invalid frame recording until we
+        // actually start playing.
+        PreparePerformanceData(0, 0);
+    } else {
+        int trLate = (int)(trRealStream - m_trRememberStampForPerf);
+        int trFrame = (int)(tr - m_trRememberFrameForPerf);
+        PreparePerformanceData(trLate, trFrame);
+    }
+    m_trRememberFrameForPerf = tr;
+#endif //PERF
+} // OnWaitEnd
+
+
+// Put data on one side that describes the lateness of the current frame.
+// We don't yet know whether it will actually be drawn.  In direct draw mode,
+// this decision is up to the filter upstream, and it could change its mind.
+// The rules say that if it did draw it must call Receive().  One way or
+// another we eventually get into either OnRenderStart or OnDirectRender and
+// these both call RecordFrameLateness to update the statistics.
+
+void CBaseVideoRenderer::PreparePerformanceData(int trLate, int trFrame)
+{
+    m_trLate = trLate;
+    m_trFrame = trFrame;
+} // PreparePerformanceData
+
+
+// update the statistics:
+// m_iTotAcc, m_iSumSqAcc, m_iSumSqFrameTime, m_iSumFrameTime, m_cFramesDrawn
+// Note that because the properties page reports using these variables,
+// 1. We need to be inside a critical section
+// 2. They must all be updated together.  Updating the sums here and the count
+// elsewhere can result in imaginary jitter (i.e. attempts to find square roots
+// of negative numbers) in the property page code.
+
+void CBaseVideoRenderer::RecordFrameLateness(int trLate, int trFrame)
+{
+    // Record how timely we are.
+    int tLate = trLate/10000;
+
+    // Best estimate of moment of appearing on the screen is average of
+    // start and end draw times.  Here we have only the end time.  This may
+    // tend to show us as spuriously late by up to 1/2 frame rate achieved.
+    // Decoder probably monitors draw time.  We don't bother.
+    MSR_INTEGER( m_idFrameAccuracy, tLate );
+
+    // This is a kludge - we can get frames that are very late
+    // especially (at start-up) and they invalidate the statistics.
+    // So ignore things that are more than 1 sec off.
+    if (tLate>1000 || tLate<-1000) {
+        if (m_cFramesDrawn<=1) {
+            tLate = 0;
+        } else if (tLate>0) {
+            tLate = 1000;
+        } else {
+            tLate = -1000;
+        }
+    }
+    // The very first frame often has a invalid time, so don't
+    // count it into the statistics.   (???)
+    if (m_cFramesDrawn>1) {
+        m_iTotAcc += tLate;
+        m_iSumSqAcc += (tLate*tLate);
+    }
+
+    // calculate inter-frame time.  Doesn't make sense for first frame
+    // second frame suffers from invalid first frame stamp.
+    if (m_cFramesDrawn>2) {
+        int tFrame = trFrame/10000;    // convert to mSec else it overflows
+
+        // This is a kludge.  It can overflow anyway (a pause can cause
+        // a very long inter-frame time) and it overflows at 2**31/10**7
+        // or about 215 seconds i.e. 3min 35sec
+        if (tFrame>1000||tFrame<0) tFrame = 1000;
+        m_iSumSqFrameTime += tFrame*tFrame;
+        ASSERT(m_iSumSqFrameTime>=0);
+        m_iSumFrameTime += tFrame;
+    }
+    ++m_cFramesDrawn;
+
+} // RecordFrameLateness
+
+
+void CBaseVideoRenderer::ThrottleWait()
+{
+    if (m_trThrottle>0) {
+        int iThrottle = m_trThrottle/10000;    // convert to mSec
+        MSR_INTEGER( m_idThrottle, iThrottle);
+        DbgLog((LOG_TRACE, 0, TEXT("Throttle %d ms"), iThrottle));
+        Sleep(iThrottle);
+    } else {
+        Sleep(0);
+    }
+} // ThrottleWait
+
+
+// Whenever a frame is rendered it goes though either OnRenderStart
+// or OnDirectRender.  Data that are generated during ShouldDrawSample
+// are added to the statistics by calling RecordFrameLateness from both
+// these two places.
+
+// Called in place of OnRenderStart..OnRenderEnd
+// When a DirectDraw image is drawn
+void CBaseVideoRenderer::OnDirectRender(IMediaSample *pMediaSample)
+{
+    m_trRenderAvg = 0;
+    m_trRenderLast = 5000000;  // If we mode switch, we do NOT want this
+                               // to inhibit the new average getting going!
+                               // so we set it to half a second
+    // MSR_INTEGER(m_idRenderAvg, m_trRenderAvg/10000);
+    RecordFrameLateness(m_trLate, m_trFrame);
+    ThrottleWait();
+} // OnDirectRender
+
+
+// Called just before we start drawing.  All we do is to get the current clock
+// time (from the system) and return.  We have to store the start render time
+// in a member variable because it isn't used until we complete the drawing
+// The rest is just performance logging.
+
+void CBaseVideoRenderer::OnRenderStart(IMediaSample *pMediaSample)
+{
+    RecordFrameLateness(m_trLate, m_trFrame);
+    m_tRenderStart = timeGetTime();
+} // OnRenderStart
+
+
+// Called directly after drawing an image.  We calculate the time spent in the
+// drawing code and if this doesn't appear to have any odd looking spikes in
+// it then we add it to the current average draw time.  Measurement spikes may
+// occur if the drawing thread is interrupted and switched to somewhere else.
+
+void CBaseVideoRenderer::OnRenderEnd(IMediaSample *pMediaSample)
+{
+    // The renderer time can vary erratically if we are interrupted so we do
+    // some smoothing to help get more sensible figures out but even that is
+    // not enough as figures can go 9,10,9,9,83,9 and we must disregard 83
+
+    int tr = (timeGetTime() - m_tRenderStart)*10000;   // convert mSec->UNITS
+    if (tr < m_trRenderAvg*2 || tr < 2 * m_trRenderLast) {
+        // DO_MOVING_AVG(m_trRenderAvg, tr);
+        m_trRenderAvg = (tr + (AVGPERIOD-1)*m_trRenderAvg)/AVGPERIOD;
+    }
+    m_trRenderLast = tr;
+    ThrottleWait();
+} // OnRenderEnd
+
+
+STDMETHODIMP CBaseVideoRenderer::SetSink( IQualityControl * piqc)
+{
+
+    m_pQSink = piqc;
+
+    return NOERROR;
+} // SetSink
+
+
+STDMETHODIMP CBaseVideoRenderer::Notify( IBaseFilter * pSelf, Quality q)
+{
+    // NOTE:  We are NOT getting any locks here.  We could be called
+    // asynchronously and possibly even on a time critical thread of
+    // someone else's - so we do the minumum.  We only set one state
+    // variable (an integer) and if that happens to be in the middle
+    // of another thread reading it they will just get either the new
+    // or the old value.  Locking would achieve no more than this.
+
+    // It might be nice to check that we are being called from m_pGraph, but
+    // it turns out to be a millisecond or so per throw!
+
+    // This is heuristics, these numbers are aimed at being "what works"
+    // rather than anything based on some theory.
+    // We use a hyperbola because it's easy to calculate and it includes
+    // a panic button asymptote (which we push off just to the left)
+    // The throttling fits the following table (roughly)
+    // Proportion   Throttle (msec)
+    //     >=1000         0
+    //        900         3
+    //        800         7
+    //        700        11
+    //        600        17
+    //        500        25
+    //        400        35
+    //        300        50
+    //        200        72
+    //        125       100
+    //        100       112
+    //         50       146
+    //          0       200
+
+    // (some evidence that we could go for a sharper kink - e.g. no throttling
+    // until below the 750 mark - might give fractionally more frames on a
+    // P60-ish machine).  The easy way to get these coefficients is to use
+    // Renbase.xls follow the instructions therein using excel solver.
+
+    if (q.Proportion>=1000) { m_trThrottle = 0; }
+    else {
+        // The DWORD is to make quite sure I get unsigned arithmetic
+        // as the constant is between 2**31 and 2**32
+        m_trThrottle = -330000 + (388880000/(q.Proportion+167));
+    }
+    return NOERROR;
+} // Notify
+
+
+// Send a message to indicate what our supplier should do about quality.
+// Theory:
+// What a supplier wants to know is "is the frame I'm working on NOW
+// going to be late?".
+// F1 is the frame at the supplier (as above)
+// Tf1 is the due time for F1
+// T1 is the time at that point (NOW!)
+// Tr1 is the time that f1 WILL actually be rendered
+// L1 is the latency of the graph for frame F1 = Tr1-T1
+// D1 (for delay) is how late F1 will be beyond its due time i.e.
+// D1 = (Tr1-Tf1) which is what the supplier really wants to know.
+// Unfortunately Tr1 is in the future and is unknown, so is L1
+//
+// We could estimate L1 by its value for a previous frame,
+// L0 = Tr0-T0 and work off
+// D1' = ((T1+L0)-Tf1) = (T1 + (Tr0-T0) -Tf1)
+// Rearranging terms:
+// D1' = (T1-T0) + (Tr0-Tf1)
+//       adding (Tf0-Tf0) and rearranging again:
+//     = (T1-T0) + (Tr0-Tf0) + (Tf0-Tf1)
+//     = (T1-T0) - (Tf1-Tf0) + (Tr0-Tf0)
+// But (Tr0-Tf0) is just D0 - how late frame zero was, and this is the
+// Late field in the quality message that we send.
+// The other two terms just state what correction should be applied before
+// using the lateness of F0 to predict the lateness of F1.
+// (T1-T0) says how much time has actually passed (we have lost this much)
+// (Tf1-Tf0) says how much time should have passed if we were keeping pace
+// (we have gained this much).
+//
+// Suppliers should therefore work off:
+//    Quality.Late + (T1-T0)  - (Tf1-Tf0)
+// and see if this is "acceptably late" or even early (i.e. negative).
+// They get T1 and T0 by polling the clock, they get Tf1 and Tf0 from
+// the time stamps in the frames.  They get Quality.Late from us.
+//
+
+HRESULT CBaseVideoRenderer::SendQuality(REFERENCE_TIME trLate,
+                                        REFERENCE_TIME trRealStream)
+{
+    Quality q;
+    HRESULT hr;
+
+    // If we are the main user of time, then report this as Flood/Dry.
+    // If our suppliers are, then report it as Famine/Glut.
+    //
+    // We need to take action, but avoid hunting.  Hunting is caused by
+    // 1. Taking too much action too soon and overshooting
+    // 2. Taking too long to react (so averaging can CAUSE hunting).
+    //
+    // The reason why we use trLate as well as Wait is to reduce hunting;
+    // if the wait time is coming down and about to go into the red, we do
+    // NOT want to rely on some average which is only telling is that it used
+    // to be OK once.
+
+    q.TimeStamp = (REFERENCE_TIME)trRealStream;
+
+    if (m_trFrameAvg<0) {
+        q.Type = Famine;      // guess
+    }
+    // Is the greater part of the time taken bltting or something else
+    else if (m_trFrameAvg > 2*m_trRenderAvg) {
+        q.Type = Famine;                        // mainly other
+    } else {
+        q.Type = Flood;                         // mainly bltting
+    }
+
+    q.Proportion = 1000;               // default
+
+    if (m_trFrameAvg<0) {
+        // leave it alone - we don't know enough
+    }
+    else if ( trLate> 0 ) {
+        // try to catch up over the next second
+        // We could be Really, REALLY late, but rendering all the frames
+        // anyway, just because it's so cheap.
+
+        q.Proportion = 1000 - (int)((trLate)/(UNITS/1000));
+        if (q.Proportion<500) {
+           q.Proportion = 500;      // don't go daft. (could've been negative!)
+        } else {
+        }
+
+    } else if (  m_trWaitAvg>20000
+              && trLate<-20000
+              ){
+        // Go cautiously faster - aim at 2mSec wait.
+        if (m_trWaitAvg>=m_trFrameAvg) {
+            // This can happen because of some fudges.
+            // The waitAvg is how long we originally planned to wait
+            // The frameAvg is more honest.
+            // It means that we are spending a LOT of time waiting
+            q.Proportion = 2000;    // double.
+        } else {
+            if (m_trFrameAvg+20000 > m_trWaitAvg) {
+                q.Proportion
+                    = 1000 * (m_trFrameAvg / (m_trFrameAvg + 20000 - m_trWaitAvg));
+            } else {
+                // We're apparently spending more than the whole frame time waiting.
+                // Assume that the averages are slightly out of kilter, but that we
+                // are indeed doing a lot of waiting.  (This leg probably never
+                // happens, but the code avoids any potential divide by zero).
+                q.Proportion = 2000;
+            }
+        }
+
+        if (q.Proportion>2000) {
+            q.Proportion = 2000;    // don't go crazy.
+        }
+    }
+
+    // Tell the supplier how late frames are when they get rendered
+    // That's how late we are now.
+    // If we are in directdraw mode then the guy upstream can see the drawing
+    // times and we'll just report on the start time.  He can figure out any
+    // offset to apply.  If we are in DIB Section mode then we will apply an
+    // extra offset which is half of our drawing time.  This is usually small
+    // but can sometimes be the dominant effect.  For this we will use the
+    // average drawing time rather than the last frame.  If the last frame took
+    // a long time to draw and made us late, that's already in the lateness
+    // figure.  We should not add it in again unless we expect the next frame
+    // to be the same.  We don't, we expect the average to be a better shot.
+    // In direct draw mode the RenderAvg will be zero.
+
+    q.Late = trLate + m_trRenderAvg/2;
+
+    // log what we're doing
+    MSR_INTEGER(m_idQualityRate, q.Proportion);
+    MSR_INTEGER( m_idQualityTime, (int)q.Late / 10000 );
+
+    // A specific sink interface may be set through IPin
+
+    if (m_pQSink==NULL) {
+        // Get our input pin's peer.  We send quality management messages
+        // to any nominated receiver of these things (set in the IPin
+        // interface), or else to our source filter.
+
+        IQualityControl *pQC = NULL;
+        IPin *pOutputPin = m_pInputPin->GetConnected();
+        ASSERT(pOutputPin != NULL);
+
+        // And get an AddRef'd quality control interface
+
+        hr = pOutputPin->QueryInterface(IID_IQualityControl,(void**) &pQC);
+        if (SUCCEEDED(hr)) {
+            m_pQSink = pQC;
+        }
+    }
+    if (m_pQSink) {
+        return m_pQSink->Notify(this,q);
+    }
+
+    return S_FALSE;
+
+} // SendQuality
+
+
+// We are called with a valid IMediaSample image to decide whether this is to
+// be drawn or not.  There must be a reference clock in operation.
+// Return S_OK if it is to be drawn Now (as soon as possible)
+// Return S_FALSE if it is to be drawn when it's due
+// Return an error if we want to drop it
+// m_nNormal=-1 indicates that we dropped the previous frame and so this
+// one should be drawn early.  Respect it and update it.
+// Use current stream time plus a number of heuristics (detailed below)
+// to make the decision
+
+HRESULT CBaseVideoRenderer::ShouldDrawSampleNow(IMediaSample *pMediaSample,
+                                                __inout REFERENCE_TIME *ptrStart,
+                                                __inout REFERENCE_TIME *ptrEnd)
+{
+
+    // Don't call us unless there's a clock interface to synchronise with
+    ASSERT(m_pClock);
+
+    MSR_INTEGER(m_idTimeStamp, (int)((*ptrStart)>>32));   // high order 32 bits
+    MSR_INTEGER(m_idTimeStamp, (int)(*ptrStart));         // low order 32 bits
+
+    // We lose a bit of time depending on the monitor type waiting for the next
+    // screen refresh.  On average this might be about 8mSec - so it will be
+    // later than we think when the picture appears.  To compensate a bit
+    // we bias the media samples by -8mSec i.e. 80000 UNITs.
+    // We don't ever make a stream time negative (call it paranoia)
+    if (*ptrStart>=80000) {
+        *ptrStart -= 80000;
+        *ptrEnd -= 80000;       // bias stop to to retain valid frame duration
+    }
+
+    // Cache the time stamp now.  We will want to compare what we did with what
+    // we started with (after making the monitor allowance).
+    m_trRememberStampForPerf = *ptrStart;
+
+    // Get reference times (current and late)
+    REFERENCE_TIME trRealStream;     // the real time now expressed as stream time.
+    m_pClock->GetTime(&trRealStream);
+#ifdef PERF
+    // While the reference clock is expensive:
+    // Remember the offset from timeGetTime and use that.
+    // This overflows all over the place, but when we subtract to get
+    // differences the overflows all cancel out.
+    m_llTimeOffset = trRealStream-timeGetTime()*10000;
+#endif
+    trRealStream -= m_tStart;     // convert to stream time (this is a reftime)
+
+    // We have to wory about two versions of "lateness".  The truth, which we
+    // try to work out here and the one measured against m_trTarget which
+    // includes long term feedback.  We report statistics against the truth
+    // but for operational decisions we work to the target.
+    // We use TimeDiff to make sure we get an integer because we
+    // may actually be late (or more likely early if there is a big time
+    // gap) by a very long time.
+    const int trTrueLate = TimeDiff(trRealStream - *ptrStart);
+    const int trLate = trTrueLate;
+
+    MSR_INTEGER(m_idSchLateTime, trTrueLate/10000);
+
+    // Send quality control messages upstream, measured against target
+    HRESULT hr = SendQuality(trLate, trRealStream);
+    // Note: the filter upstream is allowed to this FAIL meaning "you do it".
+    m_bSupplierHandlingQuality = (hr==S_OK);
+
+    // Decision time!  Do we drop, draw when ready or draw immediately?
+
+    const int trDuration = (int)(*ptrEnd - *ptrStart);
+    {
+        // We need to see if the frame rate of the file has just changed.
+        // This would make comparing our previous frame rate with the current
+        // frame rate inefficent.  Hang on a moment though.  I've seen files
+        // where the frames vary between 33 and 34 mSec so as to average
+        // 30fps.  A minor variation like that won't hurt us.
+        int t = m_trDuration/32;
+        if (  trDuration > m_trDuration+t
+           || trDuration < m_trDuration-t
+           ) {
+            // There's a major variation.  Reset the average frame rate to
+            // exactly the current rate to disable decision 9002 for this frame,
+            // and remember the new rate.
+            m_trFrameAvg = trDuration;
+            m_trDuration = trDuration;
+        }
+    }
+
+    MSR_INTEGER(m_idEarliness, m_trEarliness/10000);
+    MSR_INTEGER(m_idRenderAvg, m_trRenderAvg/10000);
+    MSR_INTEGER(m_idFrameAvg, m_trFrameAvg/10000);
+    MSR_INTEGER(m_idWaitAvg, m_trWaitAvg/10000);
+    MSR_INTEGER(m_idDuration, trDuration/10000);
+
+#ifdef PERF
+    if (S_OK==pMediaSample->IsDiscontinuity()) {
+        MSR_INTEGER(m_idDecision, 9000);
+    }
+#endif
+
+    // Control the graceful slide back from slow to fast machine mode.
+    // After a frame drop accept an early frame and set the earliness to here
+    // If this frame is already later than the earliness then slide it to here
+    // otherwise do the standard slide (reduce by about 12% per frame).
+    // Note: earliness is normally NEGATIVE
+    BOOL bJustDroppedFrame
+        = (  m_bSupplierHandlingQuality
+          //  Can't use the pin sample properties because we might
+          //  not be in Receive when we call this
+          && (S_OK == pMediaSample->IsDiscontinuity())          // he just dropped one
+          )
+       || (m_nNormal==-1);                          // we just dropped one
+
+
+    // Set m_trEarliness (slide back from slow to fast machine mode)
+    if (trLate>0) {
+        m_trEarliness = 0;   // we are no longer in fast machine mode at all!
+    } else if (  (trLate>=m_trEarliness) || bJustDroppedFrame) {
+        m_trEarliness = trLate;  // Things have slipped of their own accord
+    } else {
+        m_trEarliness = m_trEarliness - m_trEarliness/8;  // graceful slide
+    }
+
+    // prepare the new wait average - but don't pollute the old one until
+    // we have finished with it.
+    int trWaitAvg;
+    {
+        // We never mix in a negative wait.  This causes us to believe in fast machines
+        // slightly more.
+        int trL = trLate<0 ? -trLate : 0;
+        trWaitAvg = (trL + m_trWaitAvg*(AVGPERIOD-1))/AVGPERIOD;
+    }
+
+
+    int trFrame;
+    {
+        REFERENCE_TIME tr = trRealStream - m_trLastDraw; // Cd be large - 4 min pause!
+        if (tr>10000000) {
+            tr = 10000000;   // 1 second - arbitrarily.
+        }
+        trFrame = int(tr);
+    }
+
+    // We will DRAW this frame IF...
+    if (
+          // ...the time we are spending drawing is a small fraction of the total
+          // observed inter-frame time so that dropping it won't help much.
+          (3*m_trRenderAvg <= m_trFrameAvg)
+
+         // ...or our supplier is NOT handling things and the next frame would
+         // be less timely than this one or our supplier CLAIMS to be handling
+         // things, and is now less than a full FOUR frames late.
+       || ( m_bSupplierHandlingQuality
+          ? (trLate <= trDuration*4)
+          : (trLate+trLate < trDuration)
+          )
+
+          // ...or we are on average waiting for over eight milliseconds then
+          // this may be just a glitch.  Draw it and we'll hope to catch up.
+       || (m_trWaitAvg > 80000)
+
+          // ...or we haven't drawn an image for over a second.  We will update
+          // the display, which stops the video looking hung.
+          // Do this regardless of how late this media sample is.
+       || ((trRealStream - m_trLastDraw) > UNITS)
+
+    ) {
+        HRESULT Result;
+
+        // We are going to play this frame.  We may want to play it early.
+        // We will play it early if we think we are in slow machine mode.
+        // If we think we are NOT in slow machine mode, we will still play
+        // it early by m_trEarliness as this controls the graceful slide back.
+        // and in addition we aim at being m_trTarget late rather than "on time".
+
+        BOOL bPlayASAP = FALSE;
+
+        // we will play it AT ONCE (slow machine mode) if...
+
+            // ...we are playing catch-up
+        if ( bJustDroppedFrame) {
+            bPlayASAP = TRUE;
+            MSR_INTEGER(m_idDecision, 9001);
+        }
+
+            // ...or if we are running below the true frame rate
+            // exact comparisons are glitchy, for these measurements,
+            // so add an extra 5% or so
+        else if (  (m_trFrameAvg > trDuration + trDuration/16)
+
+                   // It's possible to get into a state where we are losing ground, but
+                   // are a very long way ahead.  To avoid this or recover from it
+                   // we refuse to play early by more than 10 frames.
+                && (trLate > - trDuration*10)
+                ){
+            bPlayASAP = TRUE;
+            MSR_INTEGER(m_idDecision, 9002);
+        }
+#if 0
+            // ...or if we have been late and are less than one frame early
+        else if (  (trLate + trDuration > 0)
+                && (m_trWaitAvg<=20000)
+                ) {
+            bPlayASAP = TRUE;
+            MSR_INTEGER(m_idDecision, 9003);
+        }
+#endif
+        // We will NOT play it at once if we are grossly early.  On very slow frame
+        // rate movies - e.g. clock.avi - it is not a good idea to leap ahead just
+        // because we got starved (for instance by the net) and dropped one frame
+        // some time or other.  If we are more than 900mSec early, then wait.
+        if (trLate<-9000000) {
+            bPlayASAP = FALSE;
+        }
+
+        if (bPlayASAP) {
+
+            m_nNormal = 0;
+            MSR_INTEGER(m_idDecision, 0);
+            // When we are here, we are in slow-machine mode.  trLate may well
+            // oscillate between negative and positive when the supplier is
+            // dropping frames to keep sync.  We should not let that mislead
+            // us into thinking that we have as much as zero spare time!
+            // We just update with a zero wait.
+            m_trWaitAvg = (m_trWaitAvg*(AVGPERIOD-1))/AVGPERIOD;
+
+            // Assume that we draw it immediately.  Update inter-frame stats
+            m_trFrameAvg = (trFrame + m_trFrameAvg*(AVGPERIOD-1))/AVGPERIOD;
+#ifndef PERF
+            // If this is NOT a perf build, then report what we know so far
+            // without looking at the clock any more.  This assumes that we
+            // actually wait for exactly the time we hope to.  It also reports
+            // how close we get to the manipulated time stamps that we now have
+            // rather than the ones we originally started with.  It will
+            // therefore be a little optimistic.  However it's fast.
+            PreparePerformanceData(trTrueLate, trFrame);
+#endif
+            m_trLastDraw = trRealStream;
+            if (m_trEarliness > trLate) {
+                m_trEarliness = trLate;  // if we are actually early, this is neg
+            }
+            Result = S_OK;                   // Draw it now
+
+        } else {
+            ++m_nNormal;
+            // Set the average frame rate to EXACTLY the ideal rate.
+            // If we are exiting slow-machine mode then we will have caught up
+            // and be running ahead, so as we slide back to exact timing we will
+            // have a longer than usual gap at this point.  If we record this
+            // real gap then we'll think that we're running slow and go back
+            // into slow-machine mode and vever get it straight.
+            m_trFrameAvg = trDuration;
+            MSR_INTEGER(m_idDecision, 1);
+
+            // Play it early by m_trEarliness and by m_trTarget
+
+            {
+                int trE = m_trEarliness;
+                if (trE < -m_trFrameAvg) {
+                    trE = -m_trFrameAvg;
+                }
+                *ptrStart += trE;           // N.B. earliness is negative
+            }
+
+            int Delay = -trTrueLate;
+            Result = Delay<=0 ? S_OK : S_FALSE;     // OK = draw now, FALSE = wait
+
+            m_trWaitAvg = trWaitAvg;
+
+            // Predict when it will actually be drawn and update frame stats
+
+            if (Result==S_FALSE) {   // We are going to wait
+                trFrame = TimeDiff(*ptrStart-m_trLastDraw);
+                m_trLastDraw = *ptrStart;
+            } else {
+                // trFrame is already = trRealStream-m_trLastDraw;
+                m_trLastDraw = trRealStream;
+            }
+#ifndef PERF
+            int iAccuracy;
+            if (Delay>0) {
+                // Report lateness based on when we intend to play it
+                iAccuracy = TimeDiff(*ptrStart-m_trRememberStampForPerf);
+            } else {
+                // Report lateness based on playing it *now*.
+                iAccuracy = trTrueLate;     // trRealStream-RememberStampForPerf;
+            }
+            PreparePerformanceData(iAccuracy, trFrame);
+#endif
+        }
+        return Result;
+    }
+
+    // We are going to drop this frame!
+    // Of course in DirectDraw mode the guy upstream may draw it anyway.
+
+    // This will probably give a large negative wack to the wait avg.
+    m_trWaitAvg = trWaitAvg;
+
+#ifdef PERF
+    // Respect registry setting - debug only!
+    if (m_bDrawLateFrames) {
+       return S_OK;                        // draw it when it's ready
+    }                                      // even though it's late.
+#endif
+
+    // We are going to drop this frame so draw the next one early
+    // n.b. if the supplier is doing direct draw then he may draw it anyway
+    // but he's doing something funny to arrive here in that case.
+
+    MSR_INTEGER(m_idDecision, 2);
+    m_nNormal = -1;
+    return E_FAIL;                         // drop it
+
+} // ShouldDrawSampleNow
+
+
+// NOTE we're called by both the window thread and the source filter thread
+// so we have to be protected by a critical section (locked before called)
+// Also, when the window thread gets signalled to render an image, it always
+// does so regardless of how late it is. All the degradation is done when we
+// are scheduling the next sample to be drawn. Hence when we start an advise
+// link to draw a sample, that sample's time will always become the last one
+// drawn - unless of course we stop streaming in which case we cancel links
+
+BOOL CBaseVideoRenderer::ScheduleSample(IMediaSample *pMediaSample)
+{
+    // We override ShouldDrawSampleNow to add quality management
+
+    BOOL bDrawImage = CBaseRenderer::ScheduleSample(pMediaSample);
+    if (bDrawImage == FALSE) {
+	++m_cFramesDropped;
+	return FALSE;
+    }
+
+    // m_cFramesDrawn must NOT be updated here.  It has to be updated
+    // in RecordFrameLateness at the same time as the other statistics.
+    return TRUE;
+}
+
+
+// Implementation of IQualProp interface needed to support the property page
+// This is how the property page gets the data out of the scheduler. We are
+// passed into the constructor the owning object in the COM sense, this will
+// either be the video renderer or an external IUnknown if we're aggregated.
+// We initialise our CUnknown base class with this interface pointer. Then
+// all we have to do is to override NonDelegatingQueryInterface to expose
+// our IQualProp interface. The AddRef and Release are handled automatically
+// by the base class and will be passed on to the appropriate outer object
+
+STDMETHODIMP CBaseVideoRenderer::get_FramesDroppedInRenderer(__out int *pcFramesDropped)
+{
+    CheckPointer(pcFramesDropped,E_POINTER);
+    CAutoLock cVideoLock(&m_InterfaceLock);
+    *pcFramesDropped = m_cFramesDropped;
+    return NOERROR;
+} // get_FramesDroppedInRenderer
+
+
+// Set *pcFramesDrawn to the number of frames drawn since
+// streaming started.
+
+STDMETHODIMP CBaseVideoRenderer::get_FramesDrawn( int *pcFramesDrawn)
+{
+    CheckPointer(pcFramesDrawn,E_POINTER);
+    CAutoLock cVideoLock(&m_InterfaceLock);
+    *pcFramesDrawn = m_cFramesDrawn;
+    return NOERROR;
+} // get_FramesDrawn
+
+
+// Set iAvgFrameRate to the frames per hundred secs since
+// streaming started.  0 otherwise.
+
+STDMETHODIMP CBaseVideoRenderer::get_AvgFrameRate( int *piAvgFrameRate)
+{
+    CheckPointer(piAvgFrameRate,E_POINTER);
+    CAutoLock cVideoLock(&m_InterfaceLock);
+
+    int t;
+    if (m_bStreaming) {
+        t = timeGetTime()-m_tStreamingStart;
+    } else {
+        t = m_tStreamingStart;
+    }
+
+    if (t<=0) {
+        *piAvgFrameRate = 0;
+        ASSERT(m_cFramesDrawn == 0);
+    } else {
+        // i is frames per hundred seconds
+        *piAvgFrameRate = MulDiv(100000, m_cFramesDrawn, t);
+    }
+    return NOERROR;
+} // get_AvgFrameRate
+
+
+// Set *piAvg to the average sync offset since streaming started
+// in mSec.  The sync offset is the time in mSec between when the frame
+// should have been drawn and when the frame was actually drawn.
+
+STDMETHODIMP CBaseVideoRenderer::get_AvgSyncOffset(__out int *piAvg)
+{
+    CheckPointer(piAvg,E_POINTER);
+    CAutoLock cVideoLock(&m_InterfaceLock);
+
+    if (NULL==m_pClock) {
+        *piAvg = 0;
+        return NOERROR;
+    }
+
+    // Note that we didn't gather the stats on the first frame
+    // so we use m_cFramesDrawn-1 here
+    if (m_cFramesDrawn<=1) {
+        *piAvg = 0;
+    } else {
+        *piAvg = (int)(m_iTotAcc / (m_cFramesDrawn-1));
+    }
+    return NOERROR;
+} // get_AvgSyncOffset
+
+
+// To avoid dragging in the maths library - a cheap
+// approximate integer square root.
+// We do this by getting a starting guess which is between 1
+// and 2 times too large, followed by THREE iterations of
+// Newton Raphson.  (That will give accuracy to the nearest mSec
+// for the range in question - roughly 0..1000)
+//
+// It would be faster to use a linear interpolation and ONE NR, but
+// who cares.  If anyone does - the best linear interpolation is
+// to approximates sqrt(x) by
+// y = x * (sqrt(2)-1) + 1 - 1/sqrt(2) + 1/(8*(sqrt(2)-1))
+// 0r y = x*0.41421 + 0.59467
+// This minimises the maximal error in the range in question.
+// (error is about +0.008883 and then one NR will give error .0000something
+// (Of course these are integers, so you can't just multiply by 0.41421
+// you'd have to do some sort of MulDiv).
+// Anyone wanna check my maths?  (This is only for a property display!)
+
+int isqrt(int x)
+{
+    int s = 1;
+    // Make s an initial guess for sqrt(x)
+    if (x > 0x40000000) {
+       s = 0x8000;     // prevent any conceivable closed loop
+    } else {
+        while (s*s<x) {    // loop cannot possible go more than 31 times
+            s = 2*s;       // normally it goes about 6 times
+        }
+        // Three NR iterations.
+        if (x==0) {
+           s= 0; // Wouldn't it be tragic to divide by zero whenever our
+                 // accuracy was perfect!
+        } else {
+            s = (s*s+x)/(2*s);
+            if (s>=0) s = (s*s+x)/(2*s);
+            if (s>=0) s = (s*s+x)/(2*s);
+        }
+    }
+    return s;
+}
+
+//
+//  Do estimates for standard deviations for per-frame
+//  statistics
+//
+HRESULT CBaseVideoRenderer::GetStdDev(
+    int nSamples,
+    __out int *piResult,
+    LONGLONG llSumSq,
+    LONGLONG iTot
+)
+{
+    CheckPointer(piResult,E_POINTER);
+    CAutoLock cVideoLock(&m_InterfaceLock);
+
+    if (NULL==m_pClock) {
+        *piResult = 0;
+        return NOERROR;
+    }
+
+    // If S is the Sum of the Squares of observations and
+    //    T the Total (i.e. sum) of the observations and there were
+    //    N observations, then an estimate of the standard deviation is
+    //      sqrt( (S - T**2/N) / (N-1) )
+
+    if (nSamples<=1) {
+        *piResult = 0;
+    } else {
+        LONGLONG x;
+        // First frames have invalid stamps, so we get no stats for them
+        // So we need 2 frames to get 1 datum, so N is cFramesDrawn-1
+
+        // so we use m_cFramesDrawn-1 here
+        x = llSumSq - llMulDiv(iTot, iTot, nSamples, 0);
+        x = x / (nSamples-1);
+        ASSERT(x>=0);
+        *piResult = isqrt((LONG)x);
+    }
+    return NOERROR;
+}
+
+// Set *piDev to the standard deviation in mSec of the sync offset
+// of each frame since streaming started.
+
+STDMETHODIMP CBaseVideoRenderer::get_DevSyncOffset(__out int *piDev)
+{
+    // First frames have invalid stamps, so we get no stats for them
+    // So we need 2 frames to get 1 datum, so N is cFramesDrawn-1
+    return GetStdDev(m_cFramesDrawn - 1,
+                     piDev,
+                     m_iSumSqAcc,
+                     m_iTotAcc);
+} // get_DevSyncOffset
+
+
+// Set *piJitter to the standard deviation in mSec of the inter-frame time
+// of frames since streaming started.
+
+STDMETHODIMP CBaseVideoRenderer::get_Jitter(__out int *piJitter)
+{
+    // First frames have invalid stamps, so we get no stats for them
+    // So second frame gives invalid inter-frame time
+    // So we need 3 frames to get 1 datum, so N is cFramesDrawn-2
+    return GetStdDev(m_cFramesDrawn - 2,
+                     piJitter,
+                     m_iSumSqFrameTime,
+                     m_iSumFrameTime);
+} // get_Jitter
+
+
+// Overidden to return our IQualProp interface
+
+STDMETHODIMP
+CBaseVideoRenderer::NonDelegatingQueryInterface(REFIID riid,__deref_out VOID **ppv)
+{
+    // We return IQualProp and delegate everything else
+
+    if (riid == IID_IQualProp) {
+        return GetInterface( (IQualProp *)this, ppv);
+    } else if (riid == IID_IQualityControl) {
+        return GetInterface( (IQualityControl *)this, ppv);
+    }
+    return CBaseRenderer::NonDelegatingQueryInterface(riid,ppv);
+}
+
+
+// Override JoinFilterGraph so that, just before leaving
+// the graph we can send an EC_WINDOW_DESTROYED event
+
+STDMETHODIMP
+CBaseVideoRenderer::JoinFilterGraph(__inout_opt IFilterGraph *pGraph, __in_opt LPCWSTR pName)
+{
+    // Since we send EC_ACTIVATE, we also need to ensure
+    // we send EC_WINDOW_DESTROYED or the resource manager may be
+    // holding us as a focus object
+    if (!pGraph && m_pGraph) {
+
+        // We were in a graph and now we're not
+        // Do this properly in case we are aggregated
+        IBaseFilter* pFilter = this;
+        NotifyEvent(EC_WINDOW_DESTROYED, (LPARAM) pFilter, 0);
+    }
+    return CBaseFilter::JoinFilterGraph(pGraph, pName);
+}
+
+
+// This removes a large number of level 4 warnings from the
+// Microsoft compiler which in this case are not very useful
+#pragma warning(disable: 4514)
+
+#endif /* PJMEDIA_VIDEO_DEV_HAS_DSHOW */
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/renbase.h b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/renbase.h
new file mode 100644
index 0000000..c2685bb
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/renbase.h
@@ -0,0 +1,478 @@
+//------------------------------------------------------------------------------
+// File: RenBase.h
+//
+// Desc: DirectShow base classes - defines a generic ActiveX base renderer
+//       class.
+//
+// Copyright (c) 1992-2001 Microsoft Corporation.  All rights reserved.
+//------------------------------------------------------------------------------
+
+
+#ifndef __RENBASE__
+#define __RENBASE__
+
+// Forward class declarations
+
+class CBaseRenderer;
+class CBaseVideoRenderer;
+class CRendererInputPin;
+
+// This is our input pin class that channels calls to the renderer
+
+class CRendererInputPin : public CBaseInputPin
+{
+protected:
+
+    CBaseRenderer *m_pRenderer;
+
+public:
+
+    CRendererInputPin(__inout CBaseRenderer *pRenderer,
+                      __inout HRESULT *phr,
+                      __in_opt LPCWSTR Name);
+
+    // Overriden from the base pin classes
+
+    HRESULT BreakConnect();
+    HRESULT CompleteConnect(IPin *pReceivePin);
+    HRESULT SetMediaType(const CMediaType *pmt);
+    HRESULT CheckMediaType(const CMediaType *pmt);
+    HRESULT Active();
+    HRESULT Inactive();
+
+    // Add rendering behaviour to interface functions
+
+    STDMETHODIMP QueryId(__deref_out LPWSTR *Id);
+    STDMETHODIMP EndOfStream();
+    STDMETHODIMP BeginFlush();
+    STDMETHODIMP EndFlush();
+    STDMETHODIMP Receive(IMediaSample *pMediaSample);
+
+    // Helper
+    IMemAllocator inline *Allocator() const
+    {
+        return m_pAllocator;
+    }
+};
+
+// Main renderer class that handles synchronisation and state changes
+
+class CBaseRenderer : public CBaseFilter
+{
+protected:
+
+    friend class CRendererInputPin;
+
+    friend void CALLBACK EndOfStreamTimer(UINT uID,      // Timer identifier
+                                          UINT uMsg,     // Not currently used
+                                          DWORD_PTR dwUser,  // User information
+                                          DWORD_PTR dw1,     // Windows reserved
+                                          DWORD_PTR dw2);    // Is also reserved
+
+    CRendererPosPassThru *m_pPosition;  // Media seeking pass by object
+    CAMEvent m_RenderEvent;             // Used to signal timer events
+    CAMEvent m_ThreadSignal;            // Signalled to release worker thread
+    CAMEvent m_evComplete;              // Signalled when state complete
+    BOOL m_bAbort;                      // Stop us from rendering more data
+    BOOL m_bStreaming;                  // Are we currently streaming
+    DWORD_PTR m_dwAdvise;                   // Timer advise cookie
+    IMediaSample *m_pMediaSample;       // Current image media sample
+    BOOL m_bEOS;                        // Any more samples in the stream
+    BOOL m_bEOSDelivered;               // Have we delivered an EC_COMPLETE
+    CRendererInputPin *m_pInputPin;     // Our renderer input pin object
+    CCritSec m_InterfaceLock;           // Critical section for interfaces
+    CCritSec m_RendererLock;            // Controls access to internals
+    IQualityControl * m_pQSink;         // QualityControl sink
+    BOOL m_bRepaintStatus;              // Can we signal an EC_REPAINT
+    //  Avoid some deadlocks by tracking filter during stop
+    volatile BOOL  m_bInReceive;        // Inside Receive between PrepareReceive
+                                        // And actually processing the sample
+    REFERENCE_TIME m_SignalTime;        // Time when we signal EC_COMPLETE
+    UINT m_EndOfStreamTimer;            // Used to signal end of stream
+    CCritSec m_ObjectCreationLock;      // This lock protects the creation and
+                                        // of m_pPosition and m_pInputPin.  It
+                                        // ensures that two threads cannot create
+                                        // either object simultaneously.
+
+public:
+
+    CBaseRenderer(REFCLSID RenderClass, // CLSID for this renderer
+                  __in_opt LPCTSTR pName,         // Debug ONLY description
+                  __inout_opt LPUNKNOWN pUnk,       // Aggregated owner object
+                  __inout HRESULT *phr);        // General OLE return code
+
+    ~CBaseRenderer();
+
+    // Overriden to say what interfaces we support and where
+
+    virtual HRESULT GetMediaPositionInterface(REFIID riid, __deref_out void **ppv);
+    STDMETHODIMP NonDelegatingQueryInterface(REFIID, __deref_out void **);
+
+    virtual HRESULT SourceThreadCanWait(BOOL bCanWait);
+
+#ifdef DEBUG
+    // Debug only dump of the renderer state
+    void DisplayRendererState();
+#endif
+    virtual HRESULT WaitForRenderTime();
+    virtual HRESULT CompleteStateChange(FILTER_STATE OldState);
+
+    // Return internal information about this filter
+
+    BOOL IsEndOfStream() { return m_bEOS; };
+    BOOL IsEndOfStreamDelivered() { return m_bEOSDelivered; };
+    BOOL IsStreaming() { return m_bStreaming; };
+    void SetAbortSignal(BOOL bAbort) { m_bAbort = bAbort; };
+    virtual void OnReceiveFirstSample(IMediaSample *pMediaSample) { };
+    CAMEvent *GetRenderEvent() { return &m_RenderEvent; };
+
+    // Permit access to the transition state
+
+    void Ready() { m_evComplete.Set(); };
+    void NotReady() { m_evComplete.Reset(); };
+    BOOL CheckReady() { return m_evComplete.Check(); };
+
+    virtual int GetPinCount();
+    virtual CBasePin *GetPin(int n);
+    FILTER_STATE GetRealState();
+    void SendRepaint();
+    void SendNotifyWindow(IPin *pPin,HWND hwnd);
+    BOOL OnDisplayChange();
+    void SetRepaintStatus(BOOL bRepaint);
+
+    // Override the filter and pin interface functions
+
+    STDMETHODIMP Stop();
+    STDMETHODIMP Pause();
+    STDMETHODIMP Run(REFERENCE_TIME StartTime);
+    STDMETHODIMP GetState(DWORD dwMSecs, __out FILTER_STATE *State);
+    STDMETHODIMP FindPin(LPCWSTR Id, __deref_out IPin **ppPin);
+
+    // These are available for a quality management implementation
+
+    virtual void OnRenderStart(IMediaSample *pMediaSample);
+    virtual void OnRenderEnd(IMediaSample *pMediaSample);
+    virtual HRESULT OnStartStreaming() { return NOERROR; };
+    virtual HRESULT OnStopStreaming() { return NOERROR; };
+    virtual void OnWaitStart() { };
+    virtual void OnWaitEnd() { };
+    virtual void PrepareRender() { };
+
+#ifdef PERF
+    REFERENCE_TIME m_trRenderStart; // Just before we started drawing
+                                    // Set in OnRenderStart, Used in OnRenderEnd
+    int m_idBaseStamp;              // MSR_id for frame time stamp
+    int m_idBaseRenderTime;         // MSR_id for true wait time
+    int m_idBaseAccuracy;           // MSR_id for time frame is late (int)
+#endif
+
+    // Quality management implementation for scheduling rendering
+
+    virtual BOOL ScheduleSample(IMediaSample *pMediaSample);
+    virtual HRESULT GetSampleTimes(IMediaSample *pMediaSample,
+                                   __out REFERENCE_TIME *pStartTime,
+                                   __out REFERENCE_TIME *pEndTime);
+
+    virtual HRESULT ShouldDrawSampleNow(IMediaSample *pMediaSample,
+                                        __out REFERENCE_TIME *ptrStart,
+                                        __out REFERENCE_TIME *ptrEnd);
+
+    // Lots of end of stream complexities
+
+    void TimerCallback();
+    void ResetEndOfStreamTimer();
+    HRESULT NotifyEndOfStream();
+    virtual HRESULT SendEndOfStream();
+    virtual HRESULT ResetEndOfStream();
+    virtual HRESULT EndOfStream();
+
+    // Rendering is based around the clock
+
+    void SignalTimerFired();
+    virtual HRESULT CancelNotification();
+    virtual HRESULT ClearPendingSample();
+
+    // Called when the filter changes state
+
+    virtual HRESULT Active();
+    virtual HRESULT Inactive();
+    virtual HRESULT StartStreaming();
+    virtual HRESULT StopStreaming();
+    virtual HRESULT BeginFlush();
+    virtual HRESULT EndFlush();
+
+    // Deal with connections and type changes
+
+    virtual HRESULT BreakConnect();
+    virtual HRESULT SetMediaType(const CMediaType *pmt);
+    virtual HRESULT CompleteConnect(IPin *pReceivePin);
+
+    // These look after the handling of data samples
+
+    virtual HRESULT PrepareReceive(IMediaSample *pMediaSample);
+    virtual HRESULT Receive(IMediaSample *pMediaSample);
+    virtual BOOL HaveCurrentSample();
+    virtual IMediaSample *GetCurrentSample();
+    virtual HRESULT Render(IMediaSample *pMediaSample);
+
+    // Derived classes MUST override these
+    virtual HRESULT DoRenderSample(IMediaSample *pMediaSample) PURE;
+    virtual HRESULT CheckMediaType(const CMediaType *) PURE;
+
+    // Helper
+    void WaitForReceiveToComplete();
+};
+
+
+// CBaseVideoRenderer is a renderer class (see its ancestor class) and
+// it handles scheduling of media samples so that they are drawn at the
+// correct time by the reference clock.  It implements a degradation
+// strategy.  Possible degradation modes are:
+//    Drop frames here (only useful if the drawing takes significant time)
+//    Signal supplier (upstream) to drop some frame(s) - i.e. one-off skip.
+//    Signal supplier to change the frame rate - i.e. ongoing skipping.
+//    Or any combination of the above.
+// In order to determine what's useful to try we need to know what's going
+// on.  This is done by timing various operations (including the supplier).
+// This timing is done by using timeGetTime as it is accurate enough and
+// usually cheaper than calling the reference clock.  It also tells the
+// truth if there is an audio break and the reference clock stops.
+// We provide a number of public entry points (named OnXxxStart, OnXxxEnd)
+// which the rest of the renderer calls at significant moments.  These do
+// the timing.
+
+// the number of frames that the sliding averages are averaged over.
+// the rule is (1024*NewObservation + (AVGPERIOD-1) * PreviousAverage)/AVGPERIOD
+#define AVGPERIOD 4
+#define DO_MOVING_AVG(avg,obs) (avg = (1024*obs + (AVGPERIOD-1)*avg)/AVGPERIOD)
+// Spot the bug in this macro - I can't. but it doesn't work!
+
+class CBaseVideoRenderer : public CBaseRenderer,    // Base renderer class
+                           public IQualProp,        // Property page guff
+                           public IQualityControl   // Allow throttling
+{
+protected:
+
+    // Hungarian:
+    //     tFoo is the time Foo in mSec (beware m_tStart from filter.h)
+    //     trBar is the time Bar by the reference clock
+
+    //******************************************************************
+    // State variables to control synchronisation
+    //******************************************************************
+
+    // Control of sending Quality messages.  We need to know whether
+    // we are in trouble (e.g. frames being dropped) and where the time
+    // is being spent.
+
+    // When we drop a frame we play the next one early.
+    // The frame after that is likely to wait before drawing and counting this
+    // wait as spare time is unfair, so we count it as a zero wait.
+    // We therefore need to know whether we are playing frames early or not.
+
+    int m_nNormal;                  // The number of consecutive frames
+                                    // drawn at their normal time (not early)
+                                    // -1 means we just dropped a frame.
+
+#ifdef PERF
+    BOOL m_bDrawLateFrames;         // Don't drop any frames (debug and I'm
+                                    // not keen on people using it!)
+#endif
+
+    BOOL m_bSupplierHandlingQuality;// The response to Quality messages says
+                                    // our supplier is handling things.
+                                    // We will allow things to go extra late
+                                    // before dropping frames.  We will play
+                                    // very early after he has dropped one.
+
+    // Control of scheduling, frame dropping etc.
+    // We need to know where the time is being spent so as to tell whether
+    // we should be taking action here, signalling supplier or what.
+    // The variables are initialised to a mode of NOT dropping frames.
+    // They will tell the truth after a few frames.
+    // We typically record a start time for an event, later we get the time
+    // again and subtract to get the elapsed time, and we average this over
+    // a few frames.  The average is used to tell what mode we are in.
+
+    // Although these are reference times (64 bit) they are all DIFFERENCES
+    // between times which are small.  An int will go up to 214 secs before
+    // overflow.  Avoiding 64 bit multiplications and divisions seems
+    // worth while.
+
+
+
+    // Audio-video throttling.  If the user has turned up audio quality
+    // very high (in principle it could be any other stream, not just audio)
+    // then we can receive cries for help via the graph manager.  In this case
+    // we put in a wait for some time after rendering each frame.
+    int m_trThrottle;
+
+    // The time taken to render (i.e. BitBlt) frames controls which component
+    // needs to degrade.  If the blt is expensive, the renderer degrades.
+    // If the blt is cheap it's done anyway and the supplier degrades.
+    int m_trRenderAvg;              // Time frames are taking to blt
+    int m_trRenderLast;             // Time for last frame blt
+    int m_tRenderStart;             // Just before we started drawing (mSec)
+                                    // derived from timeGetTime.
+
+    // When frames are dropped we will play the next frame as early as we can.
+    // If it was a false alarm and the machine is fast we slide gently back to
+    // normal timing.  To do this, we record the offset showing just how early
+    // we really are.  This will normally be negative meaning early or zero.
+    int m_trEarliness;
+
+    // Target provides slow long-term feedback to try to reduce the
+    // average sync offset to zero.  Whenever a frame is actually rendered
+    // early we add a msec or two, whenever late we take off a few.
+    // We add or take off 1/32 of the error time.
+    // Eventually we should be hovering around zero.  For a really bad case
+    // where we were (say) 300mSec off, it might take 100 odd frames to
+    // settle down.  The rate of change of this is intended to be slower
+    // than any other mechanism in Quartz, thereby avoiding hunting.
+    int m_trTarget;
+
+    // The proportion of time spent waiting for the right moment to blt
+    // controls whether we bother to drop a frame or whether we reckon that
+    // we're doing well enough that we can stand a one-frame glitch.
+    int m_trWaitAvg;                // Average of last few wait times
+                                    // (actually we just average how early
+                                    // we were).  Negative here means LATE.
+
+    // The average inter-frame time.
+    // This is used to calculate the proportion of the time used by the
+    // three operations (supplying us, waiting, rendering)
+    int m_trFrameAvg;               // Average inter-frame time
+    int m_trDuration;               // duration of last frame.
+
+#ifdef PERF
+    // Performance logging identifiers
+    int m_idTimeStamp;              // MSR_id for frame time stamp
+    int m_idEarliness;              // MSR_id for earliness fudge
+    int m_idTarget;                 // MSR_id for Target fudge
+    int m_idWaitReal;               // MSR_id for true wait time
+    int m_idWait;                   // MSR_id for wait time recorded
+    int m_idFrameAccuracy;          // MSR_id for time frame is late (int)
+    int m_idRenderAvg;              // MSR_id for Render time recorded (int)
+    int m_idSchLateTime;            // MSR_id for lateness at scheduler
+    int m_idQualityRate;            // MSR_id for Quality rate requested
+    int m_idQualityTime;            // MSR_id for Quality time requested
+    int m_idDecision;               // MSR_id for decision code
+    int m_idDuration;               // MSR_id for duration of a frame
+    int m_idThrottle;               // MSR_id for audio-video throttling
+    //int m_idDebug;                  // MSR_id for trace style debugging
+    //int m_idSendQuality;          // MSR_id for timing the notifications per se
+#endif // PERF
+    REFERENCE_TIME m_trRememberStampForPerf;  // original time stamp of frame
+                                              // with no earliness fudges etc.
+#ifdef PERF
+    REFERENCE_TIME m_trRememberFrameForPerf;  // time when previous frame rendered
+
+    // debug...
+    int m_idFrameAvg;
+    int m_idWaitAvg;
+#endif
+
+    // PROPERTY PAGE
+    // This has edit fields that show the user what's happening
+    // These member variables hold these counts.
+
+    int m_cFramesDropped;           // cumulative frames dropped IN THE RENDERER
+    int m_cFramesDrawn;             // Frames since streaming started seen BY THE
+                                    // RENDERER (some may be dropped upstream)
+
+    // Next two support average sync offset and standard deviation of sync offset.
+    LONGLONG m_iTotAcc;                  // Sum of accuracies in mSec
+    LONGLONG m_iSumSqAcc;           // Sum of squares of (accuracies in mSec)
+
+    // Next two allow jitter calculation.  Jitter is std deviation of frame time.
+    REFERENCE_TIME m_trLastDraw;    // Time of prev frame (for inter-frame times)
+    LONGLONG m_iSumSqFrameTime;     // Sum of squares of (inter-frame time in mSec)
+    LONGLONG m_iSumFrameTime;            // Sum of inter-frame times in mSec
+
+    // To get performance statistics on frame rate, jitter etc, we need
+    // to record the lateness and inter-frame time.  What we actually need are the
+    // data above (sum, sum of squares and number of entries for each) but the data
+    // is generated just ahead of time and only later do we discover whether the
+    // frame was actually drawn or not.  So we have to hang on to the data
+    int m_trLate;                   // hold onto frame lateness
+    int m_trFrame;                  // hold onto inter-frame time
+
+    int m_tStreamingStart;          // if streaming then time streaming started
+                                    // else time of last streaming session
+                                    // used for property page statistics
+#ifdef PERF
+    LONGLONG m_llTimeOffset;        // timeGetTime()*10000+m_llTimeOffset==ref time
+#endif
+
+public:
+
+
+    CBaseVideoRenderer(REFCLSID RenderClass, // CLSID for this renderer
+                       __in_opt LPCTSTR pName,         // Debug ONLY description
+                       __inout_opt LPUNKNOWN pUnk,       // Aggregated owner object
+                       __inout HRESULT *phr);        // General OLE return code
+
+    ~CBaseVideoRenderer();
+
+    // IQualityControl methods - Notify allows audio-video throttling
+
+    STDMETHODIMP SetSink( IQualityControl * piqc);
+    STDMETHODIMP Notify( IBaseFilter * pSelf, Quality q);
+
+    // These provide a full video quality management implementation
+
+    void OnRenderStart(IMediaSample *pMediaSample);
+    void OnRenderEnd(IMediaSample *pMediaSample);
+    void OnWaitStart();
+    void OnWaitEnd();
+    HRESULT OnStartStreaming();
+    HRESULT OnStopStreaming();
+    void ThrottleWait();
+
+    // Handle the statistics gathering for our quality management
+
+    void PreparePerformanceData(int trLate, int trFrame);
+    virtual void RecordFrameLateness(int trLate, int trFrame);
+    virtual void OnDirectRender(IMediaSample *pMediaSample);
+    virtual HRESULT ResetStreamingTimes();
+    BOOL ScheduleSample(IMediaSample *pMediaSample);
+    HRESULT ShouldDrawSampleNow(IMediaSample *pMediaSample,
+                                __inout REFERENCE_TIME *ptrStart,
+                                __inout REFERENCE_TIME *ptrEnd);
+
+    virtual HRESULT SendQuality(REFERENCE_TIME trLate, REFERENCE_TIME trRealStream);
+    STDMETHODIMP JoinFilterGraph(__inout_opt IFilterGraph * pGraph, __in_opt LPCWSTR pName);
+
+    //
+    //  Do estimates for standard deviations for per-frame
+    //  statistics
+    //
+    //  *piResult = (llSumSq - iTot * iTot / m_cFramesDrawn - 1) /
+    //                            (m_cFramesDrawn - 2)
+    //  or 0 if m_cFramesDrawn <= 3
+    //
+    HRESULT GetStdDev(
+        int nSamples,
+        __out int *piResult,
+        LONGLONG llSumSq,
+        LONGLONG iTot
+    );
+public:
+
+    // IQualProp property page support
+
+    STDMETHODIMP get_FramesDroppedInRenderer(__out int *cFramesDropped);
+    STDMETHODIMP get_FramesDrawn(__out int *pcFramesDrawn);
+    STDMETHODIMP get_AvgFrameRate(__out int *piAvgFrameRate);
+    STDMETHODIMP get_Jitter(__out int *piJitter);
+    STDMETHODIMP get_AvgSyncOffset(__out int *piAvg);
+    STDMETHODIMP get_DevSyncOffset(__out int *piDev);
+
+    // Implement an IUnknown interface and expose IQualProp
+
+    DECLARE_IUNKNOWN
+    STDMETHODIMP NonDelegatingQueryInterface(REFIID riid,__deref_out VOID **ppv);
+};
+
+#endif // __RENBASE__
+
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/seekpt.h b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/seekpt.h
new file mode 100644
index 0000000..208d418
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/seekpt.h
@@ -0,0 +1,30 @@
+//------------------------------------------------------------------------------
+// File: SeekPT.h
+//
+// Desc: DirectShow base classes.
+//
+// Copyright (c) 1992-2001 Microsoft Corporation.  All rights reserved.
+//------------------------------------------------------------------------------
+
+
+#ifndef __seekpt_h__
+#define __seekpt_h__
+
+
+class CSeekingPassThru : public ISeekingPassThru, public CUnknown
+{
+public:
+    static CUnknown *CreateInstance(__inout_opt LPUNKNOWN pUnk, __inout HRESULT *phr);
+    CSeekingPassThru(__in_opt LPCTSTR pName, __inout_opt LPUNKNOWN pUnk, __inout HRESULT *phr);
+    ~CSeekingPassThru();
+
+    DECLARE_IUNKNOWN;
+    STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void ** ppv);
+
+    STDMETHODIMP Init(BOOL bSupportRendering, IPin *pPin);
+
+private:
+    CPosPassThru              *m_pPosPassThru;
+};
+
+#endif
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/streams.h b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/streams.h
new file mode 100644
index 0000000..63f33df
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/streams.h
@@ -0,0 +1,202 @@
+//------------------------------------------------------------------------------
+// File: Streams.h
+//
+// Desc: DirectShow base classes - defines overall streams architecture.
+//
+// Copyright (c) 1992-2001 Microsoft Corporation.  All rights reserved.
+//------------------------------------------------------------------------------
+
+
+#ifndef __STREAMS__
+#define __STREAMS__
+
+#ifdef	_MSC_VER
+// disable some level-4 warnings, use #pragma warning(enable:###) to re-enable
+#pragma warning(disable:4100) // warning C4100: unreferenced formal parameter
+#pragma warning(disable:4201) // warning C4201: nonstandard extension used : nameless struct/union
+#pragma warning(disable:4511) // warning C4511: copy constructor could not be generated
+#pragma warning(disable:4512) // warning C4512: assignment operator could not be generated
+#pragma warning(disable:4514) // warning C4514: "unreferenced inline function has been removed"
+
+#if _MSC_VER>=1100
+#define AM_NOVTABLE __declspec(novtable)
+#else
+#define AM_NOVTABLE
+#endif
+#endif	// MSC_VER
+
+
+// Because of differences between Visual C++ and older Microsoft SDKs,
+// you may have defined _DEBUG without defining DEBUG.  This logic
+// ensures that both will be set if Visual C++ sets _DEBUG.
+#ifdef _DEBUG
+#ifndef DEBUG
+#define DEBUG
+#endif
+#endif
+
+
+#include <windows.h>
+#include <windowsx.h>
+#include <olectl.h>
+#include <ddraw.h>
+#include <mmsystem.h>
+
+
+#ifndef NUMELMS
+#if _WIN32_WINNT < 0x0600
+   #define NUMELMS(aa) (sizeof(aa)/sizeof((aa)[0]))
+#else
+   #define NUMELMS(aa) ARRAYSIZE(aa)
+#endif   
+#endif
+
+///////////////////////////////////////////////////////////////////////////
+// The following definitions come from the Platform SDK and are required if
+// the applicaiton is being compiled with the headers from Visual C++ 6.0.
+/////////////////////////////////////////////////// ////////////////////////
+#ifndef InterlockedExchangePointer
+	#define InterlockedExchangePointer(Target, Value) \
+   (PVOID)InterlockedExchange((PLONG)(Target), (LONG)(Value))
+#endif
+
+#ifndef _WAVEFORMATEXTENSIBLE_
+#define _WAVEFORMATEXTENSIBLE_
+typedef struct {
+    WAVEFORMATEX    Format;
+    union {
+        WORD wValidBitsPerSample;       /* bits of precision  */
+        WORD wSamplesPerBlock;          /* valid if wBitsPerSample==0 */
+        WORD wReserved;                 /* If neither applies, set to zero. */
+    } Samples;
+    DWORD           dwChannelMask;      /* which channels are */
+                                        /* present in stream  */
+    GUID            SubFormat;
+} WAVEFORMATEXTENSIBLE, *PWAVEFORMATEXTENSIBLE;
+#endif // !_WAVEFORMATEXTENSIBLE_
+
+#if !defined(WAVE_FORMAT_EXTENSIBLE)
+#define  WAVE_FORMAT_EXTENSIBLE                 0xFFFE
+#endif // !defined(WAVE_FORMAT_EXTENSIBLE)
+
+#ifndef GetWindowLongPtr
+  #define GetWindowLongPtrA   GetWindowLongA
+  #define GetWindowLongPtrW   GetWindowLongW
+  #ifdef UNICODE
+    #define GetWindowLongPtr  GetWindowLongPtrW
+  #else
+    #define GetWindowLongPtr  GetWindowLongPtrA
+  #endif // !UNICODE
+#endif // !GetWindowLongPtr
+
+#ifndef SetWindowLongPtr
+  #define SetWindowLongPtrA   SetWindowLongA
+  #define SetWindowLongPtrW   SetWindowLongW
+  #ifdef UNICODE
+    #define SetWindowLongPtr  SetWindowLongPtrW
+  #else
+    #define SetWindowLongPtr  SetWindowLongPtrA
+  #endif // !UNICODE
+#endif // !SetWindowLongPtr
+
+#ifndef GWLP_WNDPROC
+  #define GWLP_WNDPROC        (-4)
+#endif
+#ifndef GWLP_HINSTANCE
+  #define GWLP_HINSTANCE      (-6)
+#endif
+#ifndef GWLP_HWNDPARENT
+  #define GWLP_HWNDPARENT     (-8)
+#endif
+#ifndef GWLP_USERDATA
+  #define GWLP_USERDATA       (-21)
+#endif
+#ifndef GWLP_ID
+  #define GWLP_ID             (-12)
+#endif
+#ifndef DWLP_MSGRESULT
+  #define DWLP_MSGRESULT  0
+#endif
+#ifndef DWLP_DLGPROC 
+  #define DWLP_DLGPROC    DWLP_MSGRESULT + sizeof(LRESULT)
+#endif
+#ifndef DWLP_USER
+  #define DWLP_USER       DWLP_DLGPROC + sizeof(DLGPROC)
+#endif
+
+
+#pragma warning(push)
+#pragma warning(disable: 4312 4244)
+// _GetWindowLongPtr
+// Templated version of GetWindowLongPtr, to suppress spurious compiler warning.
+template <class T>
+T _GetWindowLongPtr(HWND hwnd, int nIndex)
+{
+    return (T)GetWindowLongPtr(hwnd, nIndex);
+}
+
+// _SetWindowLongPtr
+// Templated version of SetWindowLongPtr, to suppress spurious compiler warning.
+template <class T>
+LONG_PTR _SetWindowLongPtr(HWND hwnd, int nIndex, T p)
+{
+    return SetWindowLongPtr(hwnd, nIndex, (LONG_PTR)p);
+}
+#pragma warning(pop)
+
+///////////////////////////////////////////////////////////////////////////
+// End Platform SDK definitions
+///////////////////////////////////////////////////////////////////////////
+
+
+#include <strmif.h>     // Generated IDL header file for streams interfaces
+#include <intsafe.h>    // required by amvideo.h
+
+#include <reftime.h>    // Helper class for REFERENCE_TIME management
+#include <wxdebug.h>    // Debug support for logging and ASSERTs
+#include <amvideo.h>    // ActiveMovie video interfaces and definitions
+//include amaudio.h explicitly if you need it.  it requires the DX SDK.
+//#include <amaudio.h>    // ActiveMovie audio interfaces and definitions
+#include <wxutil.h>     // General helper classes for threads etc
+#include <combase.h>    // Base COM classes to support IUnknown
+//#include <dllsetup.h>   // Filter registration support functions
+#include <measure.h>    // Performance measurement
+//#include <comlite.h>    // Light weight com function prototypes
+
+//#include <cache.h>      // Simple cache container class
+#include <wxlist.h>     // Non MFC generic list class
+#include <msgthrd.h>	// CMsgThread
+#include <mtype.h>      // Helper class for managing media types
+#include <fourcc.h>     // conversions between FOURCCs and GUIDs
+#include <control.h>    // generated from control.odl
+#include <ctlutil.h>    // control interface utility classes
+#include <evcode.h>     // event code definitions
+#include <amfilter.h>   // Main streams architecture class hierachy
+//#include <transfrm.h>   // Generic transform filter
+//#include <transip.h>    // Generic transform-in-place filter
+#include <uuids.h>      // declaration of type GUIDs and well-known clsids
+//#include <source.h>	// Generic source filter
+//#include <outputq.h>    // Output pin queueing
+#include <errors.h>     // HRESULT status and error definitions
+#include <renbase.h>    // Base class for writing ActiveX renderers
+//#include <winutil.h>    // Helps with filters that manage windows
+//#include <winctrl.h>    // Implements the IVideoWindow interface
+//#include <videoctl.h>   // Specifically video related classes
+const LONGLONG MAX_TIME = 0x7FFFFFFFFFFFFFFF;   /* Maximum LONGLONG value */
+//#include <refclock.h>	// Base clock class
+//#include <sysclock.h>	// System clock
+//#include <pstream.h>    // IPersistStream helper class
+//#include <vtrans.h>     // Video Transform Filter base class
+//#include <amextra.h>
+//#include <cprop.h>      // Base property page class
+//#include <strmctl.h>    // IAMStreamControl support
+//#include <edevdefs.h>   // External device control interface defines
+//#include <audevcod.h>   // audio filter device error event codes
+
+
+#else
+    #ifdef DEBUG
+    #pragma message("STREAMS.H included TWICE")
+    #endif
+#endif // __STREAMS__
+
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/wxdebug.cpp b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/wxdebug.cpp
new file mode 100644
index 0000000..3a1dc38
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/wxdebug.cpp
@@ -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 */
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/wxdebug.h b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/wxdebug.h
new file mode 100644
index 0000000..d4c69db
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/wxdebug.h
@@ -0,0 +1,359 @@
+//------------------------------------------------------------------------------
+// File: WXDebug.h
+//
+// Desc: DirectShow base classes - provides debugging facilities.
+//
+// Copyright (c) 1992-2001 Microsoft Corporation.  All rights reserved.
+//------------------------------------------------------------------------------
+
+
+#ifndef __WXDEBUG__
+#define __WXDEBUG__
+
+// This library provides fairly straight forward debugging functionality, this
+// is split into two main sections. The first is assertion handling, there are
+// three types of assertions provided here. The most commonly used one is the
+// ASSERT(condition) macro which will pop up a message box including the file
+// and line number if the condition evaluates to FALSE. Then there is the
+// EXECUTE_ASSERT macro which is the same as ASSERT except the condition will
+// still be executed in NON debug builds. The final type of assertion is the
+// KASSERT macro which is more suitable for pure (perhaps kernel) filters as
+// the condition is printed onto the debugger rather than in a message box.
+//
+// The other part of the debug module facilties is general purpose logging.
+// This is accessed by calling DbgLog(). The function takes a type and level
+// field which define the type of informational string you are presenting and
+// it's relative importance. The type field can be a combination (one or more)
+// of LOG_TIMING, LOG_TRACE, LOG_MEMORY, LOG_LOCKING and LOG_ERROR. The level
+// is a DWORD value where zero defines highest important. Use of zero as the
+// debug logging level is to be encouraged ONLY for major errors or events as
+// they will ALWAYS be displayed on the debugger. Other debug output has it's
+// level matched against the current debug output level stored in the registry
+// for this module and if less than the current setting it will be displayed.
+//
+// Each module or executable has it's own debug output level for each of the
+// five types. These are read in when the DbgInitialise function is called
+// for DLLs linking to STRMBASE.LIB this is done automatically when the DLL
+// is loaded, executables must call it explicitely with the module instance
+// handle given to them through the WINMAIN entry point. An executable must
+// also call DbgTerminate when they have finished to clean up the resources
+// the debug library uses, once again this is done automatically for DLLs
+
+// These are the five different categories of logging information
+
+enum {  LOG_TIMING = 0x01,    // Timing and performance measurements
+        LOG_TRACE = 0x02,     // General step point call tracing
+        LOG_MEMORY =  0x04,   // Memory and object allocation/destruction
+        LOG_LOCKING = 0x08,   // Locking/unlocking of critical sections
+        LOG_ERROR = 0x10,     // Debug error notification
+        LOG_CUSTOM1 = 0x20,
+        LOG_CUSTOM2 = 0x40,
+        LOG_CUSTOM3 = 0x80,
+        LOG_CUSTOM4 = 0x100,
+        LOG_CUSTOM5 = 0x200,
+};
+
+#define LOG_FORCIBLY_SET 0x80000000
+
+enum {  CDISP_HEX = 0x01,
+        CDISP_DEC = 0x02};
+
+// For each object created derived from CBaseObject (in debug builds) we
+// create a descriptor that holds it's name (statically allocated memory)
+// and a cookie we assign it. We keep a list of all the active objects
+// we have registered so that we can dump a list of remaining objects
+
+typedef struct tag_ObjectDesc {
+    LPCSTR m_szName;
+    LPCWSTR m_wszName;
+    DWORD m_dwCookie;
+    tag_ObjectDesc *m_pNext;
+} ObjectDesc;
+
+#define DLLIMPORT __declspec(dllimport)
+#define DLLEXPORT __declspec(dllexport)
+
+#ifdef DEBUG
+
+    #define NAME(x) TEXT(x)
+
+    // These are used internally by the debug library (PRIVATE)
+
+    void WINAPI DbgInitKeyLevels(HKEY hKey, bool fTakeMax);
+    void WINAPI DbgInitGlobalSettings(bool fTakeMax);
+    void WINAPI DbgInitModuleSettings(bool fTakeMax);
+    void WINAPI DbgInitModuleName();
+    DWORD WINAPI DbgRegisterObjectCreation(
+        LPCSTR szObjectName, LPCWSTR wszObjectName);
+
+    BOOL WINAPI DbgRegisterObjectDestruction(DWORD dwCookie);
+
+    // These are the PUBLIC entry points
+
+    BOOL WINAPI DbgCheckModuleLevel(DWORD Type,DWORD Level);
+    void WINAPI DbgSetModuleLevel(DWORD Type,DWORD Level);
+    void WINAPI DbgSetAutoRefreshLevels(bool fAuto);
+
+    // Initialise the library with the module handle
+
+    void WINAPI DbgInitialise(HINSTANCE hInst);
+    void WINAPI DbgTerminate();
+
+    void WINAPI DbgDumpObjectRegister();
+
+    // Display error and logging to the user
+
+    void WINAPI DbgAssert(LPCTSTR pCondition,LPCTSTR pFileName,INT iLine);
+    void WINAPI DbgBreakPoint(LPCTSTR pCondition,LPCTSTR pFileName,INT iLine);
+    void WINAPI DbgBreakPoint(LPCTSTR pFileName,INT iLine,__format_string LPCTSTR  szFormatString,...);
+
+    void WINAPI DbgKernelAssert(LPCTSTR pCondition,LPCTSTR pFileName,INT iLine);
+    void WINAPI DbgLogInfo(DWORD Type,DWORD Level,__format_string LPCTSTR pFormat,...);
+#ifdef UNICODE
+    void WINAPI DbgLogInfo(DWORD Type,DWORD Level,__format_string LPCSTR pFormat,...);
+    void WINAPI DbgAssert(LPCSTR pCondition,LPCSTR pFileName,INT iLine);
+    void WINAPI DbgBreakPoint(LPCSTR pCondition,LPCSTR pFileName,INT iLine);
+    void WINAPI DbgKernelAssert(LPCSTR pCondition,LPCSTR pFileName,INT iLine);
+#endif
+    void WINAPI DbgOutString(LPCTSTR psz);
+
+    //  Debug infinite wait stuff
+    DWORD WINAPI DbgWaitForSingleObject(HANDLE h);
+    DWORD WINAPI DbgWaitForMultipleObjects(DWORD nCount,
+                                    __in_ecount(nCount) CONST HANDLE *lpHandles,
+                                    BOOL bWaitAll);
+    void WINAPI DbgSetWaitTimeout(DWORD dwTimeout);
+
+#ifdef __strmif_h__
+    // Display a media type: Terse at level 2, verbose at level 5
+    void WINAPI DisplayType(LPCTSTR label, const AM_MEDIA_TYPE *pmtIn);
+
+    // Dump lots of information about a filter graph
+    void WINAPI DumpGraph(IFilterGraph *pGraph, DWORD dwLevel);
+#endif
+
+    #define KASSERT(_x_) if (!(_x_))         \
+        DbgKernelAssert(TEXT(#_x_),TEXT(__FILE__),__LINE__)
+
+    //  Break on the debugger without putting up a message box
+    //  message goes to debugger instead
+
+    #define KDbgBreak(_x_)                   \
+        DbgKernelAssert(TEXT(#_x_),TEXT(__FILE__),__LINE__)
+
+    // We chose a common name for our ASSERT macro, MFC also uses this name
+    // So long as the implementation evaluates the condition and handles it
+    // then we will be ok. Rather than override the behaviour expected we
+    // will leave whatever first defines ASSERT as the handler (i.e. MFC)
+    #ifndef ASSERT
+        #define ASSERT(_x_) if (!(_x_))         \
+            DbgAssert(TEXT(#_x_),TEXT(__FILE__),__LINE__)
+    #endif
+
+    #define DbgAssertAligned( _ptr_, _alignment_ ) ASSERT( ((DWORD_PTR) (_ptr_)) % (_alignment_) == 0)
+
+    //  Put up a message box informing the user of a halt
+    //  condition in the program
+
+    #define DbgBreak(_x_)                   \
+        DbgBreakPoint(TEXT(#_x_),TEXT(__FILE__),__LINE__)
+
+    #define EXECUTE_ASSERT(_x_) ASSERT(_x_)
+    #define DbgLog(_x_) DbgLogInfo _x_
+    // MFC style trace macros
+
+    #define NOTE(_x_)             DbgLog((LOG_TRACE,5,TEXT(_x_)))
+    #define NOTE1(_x_,a)          DbgLog((LOG_TRACE,5,TEXT(_x_),a))
+    #define NOTE2(_x_,a,b)        DbgLog((LOG_TRACE,5,TEXT(_x_),a,b))
+    #define NOTE3(_x_,a,b,c)      DbgLog((LOG_TRACE,5,TEXT(_x_),a,b,c))
+    #define NOTE4(_x_,a,b,c,d)    DbgLog((LOG_TRACE,5,TEXT(_x_),a,b,c,d))
+    #define NOTE5(_x_,a,b,c,d,e)  DbgLog((LOG_TRACE,5,TEXT(_x_),a,b,c,d,e))
+
+#else
+
+    // Retail builds make public debug functions inert  - WARNING the source
+    // files do not define or build any of the entry points in debug builds
+    // (public entry points compile to nothing) so if you go trying to call
+    // any of the private entry points in your source they won't compile
+
+    #define NAME(_x_) ((LPTSTR) NULL)
+
+    #define DbgInitialise(hInst)
+    #define DbgTerminate()
+    #define DbgLog(_x_) 0
+    #define DbgOutString(psz)
+    #define DbgAssertAligned( _ptr_, _alignment_ ) 0
+
+    #define DbgRegisterObjectCreation(pObjectName)
+    #define DbgRegisterObjectDestruction(dwCookie)
+    #define DbgDumpObjectRegister()
+
+    #define DbgCheckModuleLevel(Type,Level)
+    #define DbgSetModuleLevel(Type,Level)
+    #define DbgSetAutoRefreshLevels(fAuto)
+
+    #define DbgWaitForSingleObject(h)  WaitForSingleObject(h, INFINITE)
+    #define DbgWaitForMultipleObjects(nCount, lpHandles, bWaitAll)     \
+               WaitForMultipleObjects(nCount, lpHandles, bWaitAll, INFINITE)
+    #define DbgSetWaitTimeout(dwTimeout)
+
+    #define KDbgBreak(_x_)
+    #define DbgBreak(_x_)
+
+    #define KASSERT(_x_) ((void)0)
+    #ifndef ASSERT
+	#define ASSERT(_x_) ((void)0)
+    #endif
+    #define EXECUTE_ASSERT(_x_) ((void)(_x_))
+
+    // MFC style trace macros
+
+    #define NOTE(_x_) ((void)0)
+    #define NOTE1(_x_,a) ((void)0)
+    #define NOTE2(_x_,a,b) ((void)0)
+    #define NOTE3(_x_,a,b,c) ((void)0)
+    #define NOTE4(_x_,a,b,c,d) ((void)0)
+    #define NOTE5(_x_,a,b,c,d,e) ((void)0)
+
+    #define DisplayType(label, pmtIn) ((void)0)
+    #define DumpGraph(pGraph, label) ((void)0)
+#endif
+
+
+// Checks a pointer which should be non NULL - can be used as follows.
+
+#define CheckPointer(p,ret) {if((p)==NULL) return (ret);}
+
+//   HRESULT Foo(VOID *pBar)
+//   {
+//       CheckPointer(pBar,E_INVALIDARG)
+//   }
+//
+//   Or if the function returns a boolean
+//
+//   BOOL Foo(VOID *pBar)
+//   {
+//       CheckPointer(pBar,FALSE)
+//   }
+
+#define ValidateReadPtr(p,cb) 0
+#define ValidateWritePtr(p,cb) 0
+#define ValidateReadWritePtr(p,cb) 0
+#define ValidateStringPtr(p) 0
+#define ValidateStringPtrA(p) 0
+#define ValidateStringPtrW(p) 0
+
+
+#ifdef _OBJBASE_H_
+
+    //  Outputting GUID names.  If you want to include the name
+    //  associated with a GUID (eg CLSID_...) then
+    //
+    //      GuidNames[yourGUID]
+    //
+    //  Returns the name defined in uuids.h as a string
+
+    typedef struct {
+        CHAR   *szName;
+        GUID    guid;
+    } GUID_STRING_ENTRY;
+
+    class CGuidNameList {
+    public:
+        CHAR *operator [] (const GUID& guid);
+    };
+
+    extern CGuidNameList GuidNames;
+
+#endif
+
+#ifndef REMIND
+    //  REMIND macro - generates warning as reminder to complete coding
+    //  (eg) usage:
+    //
+    //  #pragma message (REMIND("Add automation support"))
+
+
+    #define QUOTE(x) #x
+    #define QQUOTE(y) QUOTE(y)
+    #define REMIND(str) __FILE__ "(" QQUOTE(__LINE__) ") :  " str
+#endif
+
+//  Method to display objects in a useful format
+//
+//  eg If you want to display a LONGLONG ll in a debug string do (eg)
+//
+//  DbgLog((LOG_TRACE, n, TEXT("Value is %s"), (LPCTSTR)CDisp(ll, CDISP_HEX)));
+
+
+class CDispBasic
+{
+public:
+    CDispBasic() { m_pString = m_String; };
+    ~CDispBasic();
+protected:
+    PTCHAR m_pString;  // normally points to m_String... unless too much data
+    TCHAR m_String[50];
+};
+class CDisp : public CDispBasic
+{
+public:
+    CDisp(LONGLONG ll, int Format = CDISP_HEX); // Display a LONGLONG in CDISP_HEX or CDISP_DEC form
+    CDisp(REFCLSID clsid);      // Display a GUID
+    CDisp(double d);            // Display a floating point number
+#ifdef __strmif_h__
+#ifdef __STREAMS__
+    CDisp(CRefTime t);          // Display a Reference Time
+#endif
+    CDisp(IPin *pPin);          // Display a pin as {filter clsid}(pin name)
+    CDisp(IUnknown *pUnk);      // Display a filter or pin
+#endif // __strmif_h__
+    ~CDisp();
+
+    //  Implement cast to (LPCTSTR) as parameter to logger
+    operator LPCTSTR()
+    {
+        return (LPCTSTR)m_pString;
+    };
+};
+
+
+#if defined(DEBUG)
+class CAutoTrace
+{
+private:
+    LPCTSTR  _szBlkName;
+    const int _level;
+    static const TCHAR _szEntering[];
+    static const TCHAR _szLeaving[];
+public:
+    CAutoTrace(LPCTSTR szBlkName, const int level = 15)
+        : _szBlkName(szBlkName), _level(level)
+    {DbgLog((LOG_TRACE, _level, _szEntering, _szBlkName));}
+
+    ~CAutoTrace()
+    {DbgLog((LOG_TRACE, _level, _szLeaving, _szBlkName));}
+};
+
+#if defined (__FUNCTION__)
+
+#define AMTRACEFN()  CAutoTrace __trace(TEXT(__FUNCTION__))
+#define AMTRACE(_x_) CAutoTrace __trace(TEXT(__FUNCTION__))
+
+#else
+
+#define AMTRACE(_x_) CAutoTrace __trace _x_
+#define AMTRACEFN()
+
+#endif
+
+#else
+
+#define AMTRACE(_x_)
+#define AMTRACEFN()
+
+#endif
+
+#endif // __WXDEBUG__
+
+
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/wxlist.cpp b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/wxlist.cpp
new file mode 100644
index 0000000..df22839
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/wxlist.cpp
@@ -0,0 +1,896 @@
+//------------------------------------------------------------------------------
+// File: WXList.cpp
+//
+// Desc: DirectShow base classes - implements a non-MFC based generic list
+//       template class.
+// 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
+
+/* A generic list of pointers to objects.
+   Objectives: avoid using MFC libraries in ndm kernel mode and
+   provide a really useful list type.
+
+   The class is thread safe in that separate threads may add and
+   delete items in the list concurrently although the application
+   must ensure that constructor and destructor access is suitably
+   synchronised.
+
+   The list name must not conflict with MFC classes as an
+   application may use both
+
+   The nodes form a doubly linked, NULL terminated chain with an anchor
+   block (the list object per se) holding pointers to the first and last
+   nodes and a count of the nodes.
+   There is a node cache to reduce the allocation and freeing overhead.
+   It optionally (determined at construction time) has an Event which is
+   set whenever the list becomes non-empty and reset whenever it becomes
+   empty.
+   It optionally (determined at construction time) has a Critical Section
+   which is entered during the important part of each operation.  (About
+   all you can do outside it is some parameter checking).
+
+   The node cache is a repository of nodes that are NOT in the list to speed
+   up storage allocation.  Each list has its own cache to reduce locking and
+   serialising.  The list accesses are serialised anyway for a given list - a
+   common cache would mean that we would have to separately serialise access
+   of all lists within the cache.  Because the cache only stores nodes that are
+   not in the list, releasing the cache does not release any list nodes.  This
+   means that list nodes can be copied or rechained from one list to another
+   without danger of creating a dangling reference if the original cache goes
+   away.
+
+   Questionable design decisions:
+   1. Retaining the warts for compatibility
+   2. Keeping an element count -i.e. counting whenever we do anything
+      instead of only when we want the count.
+   3. Making the chain pointers NULL terminated.  If the list object
+      itself looks just like a node and the list is kept as a ring then
+      it reduces the number of special cases.  All inserts look the same.
+*/
+
+
+#include <streams.h>
+
+/* set cursor to the position of each element of list in turn  */
+#define INTERNALTRAVERSELIST(list, cursor)               \
+for ( cursor = (list).GetHeadPositionI()           \
+    ; cursor!=NULL                               \
+    ; cursor = (list).Next(cursor)                \
+    )
+
+
+/* set cursor to the position of each element of list in turn
+   in reverse order
+*/
+#define INTERNALREVERSETRAVERSELIST(list, cursor)        \
+for ( cursor = (list).GetTailPositionI()           \
+    ; cursor!=NULL                               \
+    ; cursor = (list).Prev(cursor)                \
+    )
+
+/* Constructor calls a separate initialisation function that
+   creates a node cache, optionally creates a lock object
+   and optionally creates a signaling object.
+
+   By default we create a locking object, a DEFAULTCACHE sized
+   cache but no event object so the list cannot be used in calls
+   to WaitForSingleObject
+*/
+CBaseList::CBaseList(__in_opt LPCTSTR pName,    // Descriptive list name
+                     INT iItems) :    // Node cache size
+#ifdef DEBUG
+    CBaseObject(pName),
+#endif
+    m_pFirst(NULL),
+    m_pLast(NULL),
+    m_Count(0),
+    m_Cache(iItems)
+{
+} // constructor
+
+CBaseList::CBaseList(__in_opt LPCTSTR pName) :  // Descriptive list name
+#ifdef DEBUG
+    CBaseObject(pName),
+#endif
+    m_pFirst(NULL),
+    m_pLast(NULL),
+    m_Count(0),
+    m_Cache(DEFAULTCACHE)
+{
+} // constructor
+
+#ifdef UNICODE
+CBaseList::CBaseList(__in_opt LPCSTR pName,    // Descriptive list name
+                     INT iItems) :    // Node cache size
+#ifdef DEBUG
+    CBaseObject(pName),
+#endif
+    m_pFirst(NULL),
+    m_pLast(NULL),
+    m_Count(0),
+    m_Cache(iItems)
+{
+} // constructor
+
+CBaseList::CBaseList(__in_opt LPCSTR pName) :  // Descriptive list name
+#ifdef DEBUG
+    CBaseObject(pName),
+#endif
+    m_pFirst(NULL),
+    m_pLast(NULL),
+    m_Count(0),
+    m_Cache(DEFAULTCACHE)
+{
+} // constructor
+
+#endif
+
+/* The destructor enumerates all the node objects in the list and
+   in the cache deleting each in turn. We do not do any processing
+   on the objects that the list holds (i.e. points to) so if they
+   represent interfaces for example the creator of the list should
+   ensure that each of them is released before deleting us
+*/
+CBaseList::~CBaseList()
+{
+    /* Delete all our list nodes */
+
+    RemoveAll();
+
+} // destructor
+
+/* Remove all the nodes from the list but don't do anything
+   with the objects that each node looks after (this is the
+   responsibility of the creator).
+   Aa a last act we reset the signalling event
+   (if available) to indicate to clients that the list
+   does not have any entries in it.
+*/
+void CBaseList::RemoveAll()
+{
+    /* Free up all the CNode objects NOTE we don't bother putting the
+       deleted nodes into the cache as this method is only really called
+       in serious times of change such as when we are being deleted at
+       which point the cache will be deleted anway */
+
+    CNode *pn = m_pFirst;
+    while (pn) {
+        CNode *op = pn;
+        pn = pn->Next();
+        delete op;
+    }
+
+    /* Reset the object count and the list pointers */
+
+    m_Count = 0;
+    m_pFirst = m_pLast = NULL;
+
+} // RemoveAll
+
+
+
+/* Return a position enumerator for the entire list.
+   A position enumerator is a pointer to a node object cast to a
+   transparent type so all we do is return the head/tail node
+   pointer in the list.
+   WARNING because the position is a pointer to a node there is
+   an implicit assumption for users a the list class that after
+   deleting an object from the list that any other position
+   enumerators that you have may be invalid (since the node
+   may be gone).
+*/
+__out_opt POSITION CBaseList::GetHeadPositionI() const
+{
+    return (POSITION) m_pFirst;
+} // GetHeadPosition
+
+
+
+__out_opt POSITION CBaseList::GetTailPositionI() const
+{
+    return (POSITION) m_pLast;
+} // GetTailPosition
+
+
+
+/* Get the number of objects in the list,
+   Get the lock before accessing the count.
+   Locking may not be entirely necessary but it has the side effect
+   of making sure that all operations are complete before we get it.
+   So for example if a list is being added to this list then that
+   will have completed in full before we continue rather than seeing
+   an intermediate albeit valid state
+*/
+int CBaseList::GetCountI() const
+{
+    return m_Count;
+} // GetCount
+
+
+
+/* Return the object at rp, update rp to the next object from
+   the list or NULL if you have moved over the last object.
+   You may still call this function once we return NULL but
+   we will continue to return a NULL position value
+*/
+__out void *CBaseList::GetNextI(__inout POSITION& rp) const
+{
+    /* have we reached the end of the list */
+
+    if (rp == NULL) {
+        return NULL;
+    }
+
+    /* Lock the object before continuing */
+
+    void *pObject;
+
+    /* Copy the original position then step on */
+
+    CNode *pn = (CNode *) rp;
+    ASSERT(pn != NULL);
+    rp = (POSITION) pn->Next();
+
+    /* Get the object at the original position from the list */
+
+    pObject = pn->GetData();
+    // ASSERT(pObject != NULL);    // NULL pointers in the list are allowed.
+    return pObject;
+} //GetNext
+
+
+
+/* Return the object at p.
+   Asking for the object at NULL ASSERTs then returns NULL
+   The object is NOT locked.  The list is not being changed
+   in any way.  If another thread is busy deleting the object
+   then locking would only result in a change from one bad
+   behaviour to another.
+*/
+__out_opt void *CBaseList::GetI(__in_opt POSITION p) const
+{
+    if (p == NULL) {
+        return NULL;
+    }
+
+    CNode * pn = (CNode *) p;
+    void *pObject = pn->GetData();
+    // ASSERT(pObject != NULL);    // NULL pointers in the list are allowed.
+    return pObject;
+} //Get
+
+__out void *CBaseList::GetValidI(__in POSITION p) const
+{
+    CNode * pn = (CNode *) p;
+    void *pObject = pn->GetData();
+    // ASSERT(pObject != NULL);    // NULL pointers in the list are allowed.
+    return pObject;
+} //Get
+
+
+/* Return the first position in the list which holds the given pointer.
+   Return NULL if it's not found.
+*/
+__out_opt POSITION CBaseList::FindI( __in void * pObj) const
+{
+    POSITION pn;
+    INTERNALTRAVERSELIST(*this, pn){
+        if (GetI(pn)==pObj) {
+            return pn;
+        }
+    }
+    return NULL;
+} // Find
+
+
+
+/* Remove the first node in the list (deletes the pointer to its object
+   from the list, does not free the object itself).
+   Return the pointer to its object or NULL if empty
+*/
+__out_opt void *CBaseList::RemoveHeadI()
+{
+    /* All we do is get the head position and ask for that to be deleted.
+       We could special case this since some of the code path checking
+       in Remove() is redundant as we know there is no previous
+       node for example but it seems to gain little over the
+       added complexity
+    */
+
+    return RemoveI((POSITION)m_pFirst);
+} // RemoveHead
+
+
+
+/* Remove the last node in the list (deletes the pointer to its object
+   from the list, does not free the object itself).
+   Return the pointer to its object or NULL if empty
+*/
+__out_opt void *CBaseList::RemoveTailI()
+{
+    /* All we do is get the tail position and ask for that to be deleted.
+       We could special case this since some of the code path checking
+       in Remove() is redundant as we know there is no previous
+       node for example but it seems to gain little over the
+       added complexity
+    */
+
+    return RemoveI((POSITION)m_pLast);
+} // RemoveTail
+
+
+
+/* Remove the pointer to the object in this position from the list.
+   Deal with all the chain pointers
+   Return a pointer to the object removed from the list.
+   The node object that is freed as a result
+   of this operation is added to the node cache where
+   it can be used again.
+   Remove(NULL) is a harmless no-op - but probably is a wart.
+*/
+__out_opt void *CBaseList::RemoveI(__in_opt POSITION pos)
+{
+    /* Lock the critical section before continuing */
+
+    // ASSERT (pos!=NULL);     // Removing NULL is to be harmless!
+    if (pos==NULL) return NULL;
+
+
+    CNode *pCurrent = (CNode *) pos;
+    ASSERT(pCurrent != NULL);
+
+    /* Update the previous node */
+
+    CNode *pNode = pCurrent->Prev();
+    if (pNode == NULL) {
+        m_pFirst = pCurrent->Next();
+    } else {
+        pNode->SetNext(pCurrent->Next());
+    }
+
+    /* Update the following node */
+
+    pNode = pCurrent->Next();
+    if (pNode == NULL) {
+        m_pLast = pCurrent->Prev();
+    } else {
+        pNode->SetPrev(pCurrent->Prev());
+    }
+
+    /* Get the object this node was looking after */
+
+    void *pObject = pCurrent->GetData();
+
+    // ASSERT(pObject != NULL);    // NULL pointers in the list are allowed.
+
+    /* Try and add the node object to the cache -
+       a NULL return code from the cache means we ran out of room.
+       The cache size is fixed by a constructor argument when the
+       list is created and defaults to DEFAULTCACHE.
+       This means that the cache will have room for this many
+       node objects. So if you have a list of media samples
+       and you know there will never be more than five active at
+       any given time of them for example then override the default
+       constructor
+    */
+
+    m_Cache.AddToCache(pCurrent);
+
+    /* If the list is empty then reset the list event */
+
+    --m_Count;
+    ASSERT(m_Count >= 0);
+    return pObject;
+} // Remove
+
+
+
+/* Add this object to the tail end of our list
+   Return the new tail position.
+*/
+
+__out_opt POSITION CBaseList::AddTailI(__in void *pObject)
+{
+    /* Lock the critical section before continuing */
+
+    CNode *pNode;
+    // ASSERT(pObject);   // NULL pointers in the list are allowed.
+
+    /* If there is a node objects in the cache then use
+       that otherwise we will have to create a new one */
+
+    pNode = (CNode *) m_Cache.RemoveFromCache();
+    if (pNode == NULL) {
+        pNode = new CNode;
+    }
+
+    /* Check we have a valid object */
+
+    if (pNode == NULL) {
+        return NULL;
+    }
+
+    /* Initialise all the CNode object
+       just in case it came from the cache
+    */
+
+    pNode->SetData(pObject);
+    pNode->SetNext(NULL);
+    pNode->SetPrev(m_pLast);
+
+    if (m_pLast == NULL) {
+        m_pFirst = pNode;
+    } else {
+        m_pLast->SetNext(pNode);
+    }
+
+    /* Set the new last node pointer and also increment the number
+       of list entries, the critical section is unlocked when we
+       exit the function
+    */
+
+    m_pLast = pNode;
+    ++m_Count;
+
+    return (POSITION) pNode;
+} // AddTail(object)
+
+
+
+/* Add this object to the head end of our list
+   Return the new head position.
+*/
+__out_opt POSITION CBaseList::AddHeadI(__in void *pObject)
+{
+    CNode *pNode;
+    // ASSERT(pObject);  // NULL pointers in the list are allowed.
+
+    /* If there is a node objects in the cache then use
+       that otherwise we will have to create a new one */
+
+    pNode = (CNode *) m_Cache.RemoveFromCache();
+    if (pNode == NULL) {
+        pNode = new CNode;
+    }
+
+    /* Check we have a valid object */
+
+    if (pNode == NULL) {
+        return NULL;
+    }
+
+    /* Initialise all the CNode object
+       just in case it came from the cache
+    */
+
+    pNode->SetData(pObject);
+
+    /* chain it in (set four pointers) */
+    pNode->SetPrev(NULL);
+    pNode->SetNext(m_pFirst);
+
+    if (m_pFirst == NULL) {
+        m_pLast = pNode;
+    } else {
+        m_pFirst->SetPrev(pNode);
+    }
+    m_pFirst = pNode;
+
+    ++m_Count;
+
+    return (POSITION) pNode;
+} // AddHead(object)
+
+
+
+/* Add all the elements in *pList to the tail of this list.
+   Return TRUE if it all worked, FALSE if it didn't.
+   If it fails some elements may have been added.
+*/
+BOOL CBaseList::AddTail(__in CBaseList *pList)
+{
+    /* lock the object before starting then enumerate
+       each entry in the source list and add them one by one to
+       our list (while still holding the object lock)
+       Lock the other list too.
+    */
+    POSITION pos = pList->GetHeadPositionI();
+
+    while (pos) {
+       if (NULL == AddTailI(pList->GetNextI(pos))) {
+           return FALSE;
+       }
+    }
+    return TRUE;
+} // AddTail(list)
+
+
+
+/* Add all the elements in *pList to the head of this list.
+   Return TRUE if it all worked, FALSE if it didn't.
+   If it fails some elements may have been added.
+*/
+BOOL CBaseList::AddHead(__in CBaseList *pList)
+{
+    /* lock the object before starting then enumerate
+       each entry in the source list and add them one by one to
+       our list (while still holding the object lock)
+       Lock the other list too.
+
+       To avoid reversing the list, traverse it backwards.
+    */
+
+    POSITION pos;
+
+    INTERNALREVERSETRAVERSELIST(*pList, pos) {
+        if (NULL== AddHeadI(pList->GetValidI(pos))){
+            return FALSE;
+        }
+    }
+    return TRUE;
+} // AddHead(list)
+
+
+
+/* Add the object after position p
+   p is still valid after the operation.
+   AddAfter(NULL,x) adds x to the start - same as AddHead
+   Return the position of the new object, NULL if it failed
+*/
+__out_opt POSITION  CBaseList::AddAfterI(__in_opt POSITION pos, __in void * pObj)
+{
+    if (pos==NULL)
+        return AddHeadI(pObj);
+
+    /* As someone else might be furkling with the list -
+       Lock the critical section before continuing
+    */
+    CNode *pAfter = (CNode *) pos;
+    ASSERT(pAfter != NULL);
+    if (pAfter==m_pLast)
+        return AddTailI(pObj);
+
+    /* set pnode to point to a new node, preferably from the cache */
+
+    CNode *pNode = (CNode *) m_Cache.RemoveFromCache();
+    if (pNode == NULL) {
+        pNode = new CNode;
+    }
+
+    /* Check we have a valid object */
+
+    if (pNode == NULL) {
+        return NULL;
+    }
+
+    /* Initialise all the CNode object
+       just in case it came from the cache
+    */
+
+    pNode->SetData(pObj);
+
+    /* It is to be added to the middle of the list - there is a before
+       and after node.  Chain it after pAfter, before pBefore.
+    */
+    CNode * pBefore = pAfter->Next();
+    ASSERT(pBefore != NULL);
+
+    /* chain it in (set four pointers) */
+    pNode->SetPrev(pAfter);
+    pNode->SetNext(pBefore);
+    pBefore->SetPrev(pNode);
+    pAfter->SetNext(pNode);
+
+    ++m_Count;
+
+    return (POSITION) pNode;
+
+} // AddAfter(object)
+
+
+
+BOOL CBaseList::AddAfter(__in_opt POSITION p, __in CBaseList *pList)
+{
+    POSITION pos;
+    INTERNALTRAVERSELIST(*pList, pos) {
+        /* p follows along the elements being added */
+        p = AddAfterI(p, pList->GetValidI(pos));
+        if (p==NULL) return FALSE;
+    }
+    return TRUE;
+} // AddAfter(list)
+
+
+
+/* Mirror images:
+   Add the element or list after position p.
+   p is still valid after the operation.
+   AddBefore(NULL,x) adds x to the end - same as AddTail
+*/
+__out_opt POSITION CBaseList::AddBeforeI(__in_opt POSITION pos, __in void * pObj)
+{
+    if (pos==NULL)
+        return AddTailI(pObj);
+
+    /* set pnode to point to a new node, preferably from the cache */
+
+    CNode *pBefore = (CNode *) pos;
+    ASSERT(pBefore != NULL);
+    if (pBefore==m_pFirst)
+        return AddHeadI(pObj);
+
+    CNode * pNode = (CNode *) m_Cache.RemoveFromCache();
+    if (pNode == NULL) {
+        pNode = new CNode;
+    }
+
+    /* Check we have a valid object */
+
+    if (pNode == NULL) {
+        return NULL;
+    }
+
+    /* Initialise all the CNode object
+       just in case it came from the cache
+    */
+
+    pNode->SetData(pObj);
+
+    /* It is to be added to the middle of the list - there is a before
+       and after node.  Chain it after pAfter, before pBefore.
+    */
+
+    CNode * pAfter = pBefore->Prev();
+    ASSERT(pAfter != NULL);
+
+    /* chain it in (set four pointers) */
+    pNode->SetPrev(pAfter);
+    pNode->SetNext(pBefore);
+    pBefore->SetPrev(pNode);
+    pAfter->SetNext(pNode);
+
+    ++m_Count;
+
+    return (POSITION) pNode;
+
+} // Addbefore(object)
+
+
+
+BOOL CBaseList::AddBefore(__in_opt POSITION p, __in CBaseList *pList)
+{
+    POSITION pos;
+    INTERNALREVERSETRAVERSELIST(*pList, pos) {
+        /* p follows along the elements being added */
+        p = AddBeforeI(p, pList->GetValidI(pos));
+        if (p==NULL) return FALSE;
+    }
+    return TRUE;
+} // AddBefore(list)
+
+
+
+/* Split *this after position p in *this
+   Retain as *this the tail portion of the original *this
+   Add the head portion to the tail end of *pList
+   Return TRUE if it all worked, FALSE if it didn't.
+
+   e.g.
+      foo->MoveToTail(foo->GetHeadPosition(), bar);
+          moves one element from the head of foo to the tail of bar
+      foo->MoveToTail(NULL, bar);
+          is a no-op
+      foo->MoveToTail(foo->GetTailPosition, bar);
+          concatenates foo onto the end of bar and empties foo.
+
+   A better, except excessively long name might be
+       MoveElementsFromHeadThroughPositionToOtherTail
+*/
+BOOL CBaseList::MoveToTail
+        (__in_opt POSITION pos, __in CBaseList *pList)
+{
+    /* Algorithm:
+       Note that the elements (including their order) in the concatenation
+       of *pList to the head of *this is invariant.
+       1. Count elements to be moved
+       2. Join *pList onto the head of this to make one long chain
+       3. Set first/Last pointers in *this and *pList
+       4. Break the chain at the new place
+       5. Adjust counts
+       6. Set/Reset any events
+    */
+
+    if (pos==NULL) return TRUE;  // no-op.  Eliminates special cases later.
+
+
+    /* Make cMove the number of nodes to move */
+    CNode * p = (CNode *)pos;
+    int cMove = 0;            // number of nodes to move
+    while(p!=NULL) {
+       p = p->Prev();
+       ++cMove;
+    }
+
+
+    /* Join the two chains together */
+    if (pList->m_pLast!=NULL)
+        pList->m_pLast->SetNext(m_pFirst);
+    if (m_pFirst!=NULL)
+        m_pFirst->SetPrev(pList->m_pLast);
+
+
+    /* set first and last pointers */
+    p = (CNode *)pos;
+
+    if (pList->m_pFirst==NULL)
+        pList->m_pFirst = m_pFirst;
+    m_pFirst = p->Next();
+    if (m_pFirst==NULL)
+        m_pLast = NULL;
+    pList->m_pLast = p;
+
+
+    /* Break the chain after p to create the new pieces */
+    if (m_pFirst!=NULL)
+        m_pFirst->SetPrev(NULL);
+    p->SetNext(NULL);
+
+
+    /* Adjust the counts */
+    m_Count -= cMove;
+    pList->m_Count += cMove;
+
+    return TRUE;
+
+} // MoveToTail
+
+
+
+/* Mirror image of MoveToTail:
+   Split *this before position p in *this.
+   Retain in *this the head portion of the original *this
+   Add the tail portion to the start (i.e. head) of *pList
+   Return TRUE if it all worked, FALSE if it didn't.
+
+   e.g.
+      foo->MoveToHead(foo->GetTailPosition(), bar);
+          moves one element from the tail of foo to the head of bar
+      foo->MoveToHead(NULL, bar);
+          is a no-op
+      foo->MoveToHead(foo->GetHeadPosition, bar);
+          concatenates foo onto the start of bar and empties foo.
+*/
+BOOL CBaseList::MoveToHead
+        (__in_opt POSITION pos, __in CBaseList *pList)
+{
+
+    /* See the comments on the algorithm in MoveToTail */
+
+    if (pos==NULL) return TRUE;  // no-op.  Eliminates special cases later.
+
+    /* Make cMove the number of nodes to move */
+    CNode * p = (CNode *)pos;
+    int cMove = 0;            // number of nodes to move
+    while(p!=NULL) {
+       p = p->Next();
+       ++cMove;
+    }
+
+
+    /* Join the two chains together */
+    if (pList->m_pFirst!=NULL)
+        pList->m_pFirst->SetPrev(m_pLast);
+    if (m_pLast!=NULL)
+        m_pLast->SetNext(pList->m_pFirst);
+
+
+    /* set first and last pointers */
+    p = (CNode *)pos;
+
+
+    if (pList->m_pLast==NULL)
+        pList->m_pLast = m_pLast;
+
+    m_pLast = p->Prev();
+    if (m_pLast==NULL)
+        m_pFirst = NULL;
+    pList->m_pFirst = p;
+
+
+    /* Break the chain after p to create the new pieces */
+    if (m_pLast!=NULL)
+        m_pLast->SetNext(NULL);
+    p->SetPrev(NULL);
+
+
+    /* Adjust the counts */
+    m_Count -= cMove;
+    pList->m_Count += cMove;
+
+    return TRUE;
+
+} // MoveToHead
+
+
+
+/* Reverse the order of the [pointers to] objects in *this
+*/
+void CBaseList::Reverse()
+{
+    /* algorithm:
+       The obvious booby trap is that you flip pointers around and lose
+       addressability to the node that you are going to process next.
+       The easy way to avoid this is do do one chain at a time.
+
+       Run along the forward chain,
+       For each node, set the reverse pointer to the one ahead of us.
+       The reverse chain is now a copy of the old forward chain, including
+       the NULL termination.
+
+       Run along the reverse chain (i.e. old forward chain again)
+       For each node set the forward pointer of the node ahead to point back
+       to the one we're standing on.
+       The first node needs special treatment,
+       it's new forward pointer is NULL.
+       Finally set the First/Last pointers
+
+    */
+    CNode * p;
+
+    // Yes we COULD use a traverse, but it would look funny!
+    p = m_pFirst;
+    while (p!=NULL) {
+        CNode * q;
+        q = p->Next();
+        p->SetNext(p->Prev());
+        p->SetPrev(q);
+        p = q;
+    }
+
+    p = m_pFirst;
+    m_pFirst = m_pLast;
+    m_pLast = p;
+
+
+#if 0     // old version
+
+    if (m_pFirst==NULL) return;          // empty list
+    if (m_pFirst->Next()==NULL) return;  // single node list
+
+
+    /* run along forward chain */
+    for ( p = m_pFirst
+        ; p!=NULL
+        ; p = p->Next()
+        ){
+        p->SetPrev(p->Next());
+    }
+
+
+    /* special case first element */
+    m_pFirst->SetNext(NULL);     // fix the old first element
+
+
+    /* run along new reverse chain i.e. old forward chain again */
+    for ( p = m_pFirst           // start at the old first element
+        ; p->Prev()!=NULL        // while there's a node still to be set
+        ; p = p->Prev()          // work in the same direction as before
+        ){
+        p->Prev()->SetNext(p);
+    }
+
+
+    /* fix forward and reverse pointers
+       - the triple XOR swap would work but all the casts look hideous */
+    p = m_pFirst;
+    m_pFirst = m_pLast;
+    m_pLast = p;
+#endif
+
+} // Reverse
+
+#endif /* PJMEDIA_VIDEO_DEV_HAS_DSHOW */
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/wxlist.h b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/wxlist.h
new file mode 100644
index 0000000..47e7123
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/wxlist.h
@@ -0,0 +1,553 @@
+//------------------------------------------------------------------------------
+// File: WXList.h
+//
+// Desc: DirectShow base classes - defines a non-MFC generic template list
+//       class.
+//
+// Copyright (c) 1992-2001 Microsoft Corporation.  All rights reserved.
+//------------------------------------------------------------------------------
+
+
+/* A generic list of pointers to objects.
+   No storage management or copying is done on the objects pointed to.
+   Objectives: avoid using MFC libraries in ndm kernel mode and
+   provide a really useful list type.
+
+   The class is thread safe in that separate threads may add and
+   delete items in the list concurrently although the application
+   must ensure that constructor and destructor access is suitably
+   synchronised. An application can cause deadlock with operations
+   which use two lists by simultaneously calling
+   list1->Operation(list2) and list2->Operation(list1).  So don't!
+
+   The names must not conflict with MFC classes as an application
+   may use both.
+   */
+
+#ifndef __WXLIST__
+#define __WXLIST__
+
+   /* A POSITION represents (in some fashion that's opaque) a cursor
+      on the list that can be set to identify any element.  NULL is
+      a valid value and several operations regard NULL as the position
+      "one step off the end of the list".  (In an n element list there
+      are n+1 places to insert and NULL is that "n+1-th" value).
+      The POSITION of an element in the list is only invalidated if
+      that element is deleted.  Move operations may mean that what
+      was a valid POSITION in one list is now a valid POSITION in
+      a different list.
+
+      Some operations which at first sight are illegal are allowed as
+      harmless no-ops.  For instance RemoveHead is legal on an empty
+      list and it returns NULL.  This allows an atomic way to test if
+      there is an element there, and if so, get it.  The two operations
+      AddTail and RemoveHead thus implement a MONITOR (See Hoare's paper).
+
+      Single element operations return POSITIONs, non-NULL means it worked.
+      whole list operations return a BOOL.  TRUE means it all worked.
+
+      This definition is the same as the POSITION type for MFCs, so we must
+      avoid defining it twice.
+   */
+#ifndef __AFX_H__
+struct __POSITION { int unused; };
+typedef __POSITION* POSITION;
+#endif
+
+const int DEFAULTCACHE = 10;    /* Default node object cache size */
+
+/* A class representing one node in a list.
+   Each node knows a pointer to it's adjacent nodes and also a pointer
+   to the object that it looks after.
+   All of these pointers can be retrieved or set through member functions.
+*/
+class CBaseList 
+#ifdef DEBUG
+    : public CBaseObject
+#endif
+{
+    /* Making these classes inherit from CBaseObject does nothing
+       functionally but it allows us to check there are no memory
+       leaks in debug builds. 
+    */
+
+public:
+
+#ifdef DEBUG
+    class CNode : public CBaseObject {
+#else
+    class CNode {
+#endif
+
+        CNode *m_pPrev;         /* Previous node in the list */
+        CNode *m_pNext;         /* Next node in the list */
+        void *m_pObject;      /* Pointer to the object */
+
+    public:
+
+        /* Constructor - initialise the object's pointers */
+        CNode()
+#ifdef DEBUG
+            : CBaseObject(NAME("List node"))
+#endif
+        {
+        };
+
+
+        /* Return the previous node before this one */
+        __out CNode *Prev() const { return m_pPrev; };
+
+
+        /* Return the next node after this one */
+        __out CNode *Next() const { return m_pNext; };
+
+
+        /* Set the previous node before this one */
+        void SetPrev(__in_opt CNode *p) { m_pPrev = p; };
+
+
+        /* Set the next node after this one */
+        void SetNext(__in_opt CNode *p) { m_pNext = p; };
+
+
+        /* Get the pointer to the object for this node */
+        __out void *GetData() const { return m_pObject; };
+
+
+        /* Set the pointer to the object for this node */
+        void SetData(__in void *p) { m_pObject = p; };
+    };
+
+    class CNodeCache
+    {
+    public:
+        CNodeCache(INT iCacheSize) : m_iCacheSize(iCacheSize),
+                                     m_pHead(NULL),
+                                     m_iUsed(0)
+                                     {};
+        ~CNodeCache() {
+            CNode *pNode = m_pHead;
+            while (pNode) {
+                CNode *pCurrent = pNode;
+                pNode = pNode->Next();
+                delete pCurrent;
+            }
+        };
+        void AddToCache(__inout CNode *pNode)
+        {
+            if (m_iUsed < m_iCacheSize) {
+                pNode->SetNext(m_pHead);
+                m_pHead = pNode;
+                m_iUsed++;
+            } else {
+                delete pNode;
+            }
+        };
+        CNode *RemoveFromCache()
+        {
+            CNode *pNode = m_pHead;
+            if (pNode != NULL) {
+                m_pHead = pNode->Next();
+                m_iUsed--;
+                ASSERT(m_iUsed >= 0);
+            } else {
+                ASSERT(m_iUsed == 0);
+            }
+            return pNode;
+        };
+    private:
+        INT m_iCacheSize;
+        INT m_iUsed;
+        CNode *m_pHead;
+    };
+
+protected:
+
+    CNode* m_pFirst;    /* Pointer to first node in the list */
+    CNode* m_pLast;     /* Pointer to the last node in the list */
+    LONG m_Count;       /* Number of nodes currently in the list */
+
+private:
+
+    CNodeCache m_Cache; /* Cache of unused node pointers */
+
+private:
+
+    /* These override the default copy constructor and assignment
+       operator for all list classes. They are in the private class
+       declaration section so that anybody trying to pass a list
+       object by value will generate a compile time error of
+       "cannot access the private member function". If these were
+       not here then the compiler will create default constructors
+       and assignment operators which when executed first take a
+       copy of all member variables and then during destruction
+       delete them all. This must not be done for any heap
+       allocated data.
+    */
+    CBaseList(const CBaseList &refList);
+    CBaseList &operator=(const CBaseList &refList);
+
+public:
+
+    CBaseList(__in_opt LPCTSTR pName,
+              INT iItems);
+
+    CBaseList(__in_opt LPCTSTR pName);
+#ifdef UNICODE
+    CBaseList(__in_opt LPCSTR pName,
+              INT iItems);
+
+    CBaseList(__in_opt LPCSTR pName);
+#endif
+    ~CBaseList();
+
+    /* Remove all the nodes from *this i.e. make the list empty */
+    void RemoveAll();
+
+
+    /* Return a cursor which identifies the first element of *this */
+    __out_opt POSITION GetHeadPositionI() const;
+
+
+    /* Return a cursor which identifies the last element of *this */
+    __out_opt POSITION GetTailPositionI() const;
+
+
+    /* Return the number of objects in *this */
+    int GetCountI() const;
+
+protected:
+    /* Return the pointer to the object at rp,
+       Update rp to the next node in *this
+       but make it NULL if it was at the end of *this.
+       This is a wart retained for backwards compatibility.
+       GetPrev is not implemented.
+       Use Next, Prev and Get separately.
+    */
+    __out void *GetNextI(__inout POSITION& rp) const;
+
+
+    /* Return a pointer to the object at p
+       Asking for the object at NULL will return NULL harmlessly.
+    */
+    __out_opt void *GetI(__in_opt POSITION p) const;
+    __out void *GetValidI(__in POSITION p) const;
+
+public:
+    /* return the next / prev position in *this
+       return NULL when going past the end/start.
+       Next(NULL) is same as GetHeadPosition()
+       Prev(NULL) is same as GetTailPosition()
+       An n element list therefore behaves like a n+1 element
+       cycle with NULL at the start/end.
+
+       !!WARNING!! - This handling of NULL is DIFFERENT from GetNext.
+
+       Some reasons are:
+       1. For a list of n items there are n+1 positions to insert
+          These are conveniently encoded as the n POSITIONs and NULL.
+       2. If you are keeping a list sorted (fairly common) and you
+          search forward for an element to insert before and don't
+          find it you finish up with NULL as the element before which
+          to insert.  You then want that NULL to be a valid POSITION
+          so that you can insert before it and you want that insertion
+          point to mean the (n+1)-th one that doesn't have a POSITION.
+          (symmetrically if you are working backwards through the list).
+       3. It simplifies the algebra which the methods generate.
+          e.g. AddBefore(p,x) is identical to AddAfter(Prev(p),x)
+          in ALL cases.  All the other arguments probably are reflections
+          of the algebraic point.
+    */
+    __out_opt POSITION Next(__in_opt POSITION pos) const
+    {
+        if (pos == NULL) {
+            return (POSITION) m_pFirst;
+        }
+        CNode *pn = (CNode *) pos;
+        return (POSITION) pn->Next();
+    } //Next
+
+    // See Next
+    __out_opt POSITION Prev(__in_opt POSITION pos) const
+    {
+        if (pos == NULL) {
+            return (POSITION) m_pLast;
+        }
+        CNode *pn = (CNode *) pos;
+        return (POSITION) pn->Prev();
+    } //Prev
+
+
+    /* Return the first position in *this which holds the given
+       pointer.  Return NULL if the pointer was not not found.
+    */
+protected:
+    __out_opt POSITION FindI( __in void * pObj) const;
+
+    // ??? Should there be (or even should there be only)
+    // ??? POSITION FindNextAfter(void * pObj, POSITION p)
+    // ??? And of course FindPrevBefore too.
+    // ??? List.Find(&Obj) then becomes List.FindNextAfter(&Obj, NULL)
+
+
+    /* Remove the first node in *this (deletes the pointer to its
+       object from the list, does not free the object itself).
+       Return the pointer to its object.
+       If *this was already empty it will harmlessly return NULL.
+    */
+    __out_opt void *RemoveHeadI();
+
+
+    /* Remove the last node in *this (deletes the pointer to its
+       object from the list, does not free the object itself).
+       Return the pointer to its object.
+       If *this was already empty it will harmlessly return NULL.
+    */
+    __out_opt void *RemoveTailI();
+
+
+    /* Remove the node identified by p from the list (deletes the pointer
+       to its object from the list, does not free the object itself).
+       Asking to Remove the object at NULL will harmlessly return NULL.
+       Return the pointer to the object removed.
+    */
+    __out_opt void *RemoveI(__in_opt POSITION p);
+
+    /* Add single object *pObj to become a new last element of the list.
+       Return the new tail position, NULL if it fails.
+       If you are adding a COM objects, you might want AddRef it first.
+       Other existing POSITIONs in *this are still valid
+    */
+    __out_opt POSITION AddTailI(__in void * pObj);
+public:
+
+
+    /* Add all the elements in *pList to the tail of *this.
+       This duplicates all the nodes in *pList (i.e. duplicates
+       all its pointers to objects).  It does not duplicate the objects.
+       If you are adding a list of pointers to a COM object into the list
+       it's a good idea to AddRef them all  it when you AddTail it.
+       Return TRUE if it all worked, FALSE if it didn't.
+       If it fails some elements may have been added.
+       Existing POSITIONs in *this are still valid
+
+       If you actually want to MOVE the elements, use MoveToTail instead.
+    */
+    BOOL AddTail(__in CBaseList *pList);
+
+
+    /* Mirror images of AddHead: */
+
+    /* Add single object to become a new first element of the list.
+       Return the new head position, NULL if it fails.
+       Existing POSITIONs in *this are still valid
+    */
+protected:
+    __out_opt POSITION AddHeadI(__in void * pObj);
+public:
+
+    /* Add all the elements in *pList to the head of *this.
+       Same warnings apply as for AddTail.
+       Return TRUE if it all worked, FALSE if it didn't.
+       If it fails some of the objects may have been added.
+
+       If you actually want to MOVE the elements, use MoveToHead instead.
+    */
+    BOOL AddHead(__in CBaseList *pList);
+
+
+    /* Add the object *pObj to *this after position p in *this.
+       AddAfter(NULL,x) adds x to the start - equivalent to AddHead
+       Return the position of the object added, NULL if it failed.
+       Existing POSITIONs in *this are undisturbed, including p.
+    */
+protected:
+    __out_opt POSITION AddAfterI(__in_opt POSITION p, __in void * pObj);
+public:
+
+    /* Add the list *pList to *this after position p in *this
+       AddAfter(NULL,x) adds x to the start - equivalent to AddHead
+       Return TRUE if it all worked, FALSE if it didn't.
+       If it fails, some of the objects may be added
+       Existing POSITIONs in *this are undisturbed, including p.
+    */
+    BOOL AddAfter(__in_opt POSITION p, __in CBaseList *pList);
+
+
+    /* Mirror images:
+       Add the object *pObj to this-List after position p in *this.
+       AddBefore(NULL,x) adds x to the end - equivalent to AddTail
+       Return the position of the new object, NULL if it fails
+       Existing POSITIONs in *this are undisturbed, including p.
+    */
+    protected:
+    __out_opt POSITION AddBeforeI(__in_opt POSITION p, __in void * pObj);
+    public:
+
+    /* Add the list *pList to *this before position p in *this
+       AddAfter(NULL,x) adds x to the start - equivalent to AddHead
+       Return TRUE if it all worked, FALSE if it didn't.
+       If it fails, some of the objects may be added
+       Existing POSITIONs in *this are undisturbed, including p.
+    */
+    BOOL AddBefore(__in_opt POSITION p, __in CBaseList *pList);
+
+
+    /* Note that AddAfter(p,x) is equivalent to AddBefore(Next(p),x)
+       even in cases where p is NULL or Next(p) is NULL.
+       Similarly for mirror images etc.
+       This may make it easier to argue about programs.
+    */
+
+
+
+    /* The following operations do not copy any elements.
+       They move existing blocks of elements around by switching pointers.
+       They are fairly efficient for long lists as for short lists.
+       (Alas, the Count slows things down).
+
+       They split the list into two parts.
+       One part remains as the original list, the other part
+       is appended to the second list.  There are eight possible
+       variations:
+       Split the list {after/before} a given element
+       keep the {head/tail} portion in the original list
+       append the rest to the {head/tail} of the new list.
+
+       Since After is strictly equivalent to Before Next
+       we are not in serious need of the Before/After variants.
+       That leaves only four.
+
+       If you are processing a list left to right and dumping
+       the bits that you have processed into another list as
+       you go, the Tail/Tail variant gives the most natural result.
+       If you are processing in reverse order, Head/Head is best.
+
+       By using NULL positions and empty lists judiciously either
+       of the other two can be built up in two operations.
+
+       The definition of NULL (see Next/Prev etc) means that
+       degenerate cases include
+          "move all elements to new list"
+          "Split a list into two lists"
+          "Concatenate two lists"
+          (and quite a few no-ops)
+
+       !!WARNING!! The type checking won't buy you much if you get list
+       positions muddled up - e.g. use a POSITION that's in a different
+       list and see what a mess you get!
+    */
+
+    /* Split *this after position p in *this
+       Retain as *this the tail portion of the original *this
+       Add the head portion to the tail end of *pList
+       Return TRUE if it all worked, FALSE if it didn't.
+
+       e.g.
+          foo->MoveToTail(foo->GetHeadPosition(), bar);
+              moves one element from the head of foo to the tail of bar
+          foo->MoveToTail(NULL, bar);
+              is a no-op, returns NULL
+          foo->MoveToTail(foo->GetTailPosition, bar);
+              concatenates foo onto the end of bar and empties foo.
+
+       A better, except excessively long name might be
+           MoveElementsFromHeadThroughPositionToOtherTail
+    */
+    BOOL MoveToTail(__in_opt POSITION pos, __in CBaseList *pList);
+
+
+    /* Mirror image:
+       Split *this before position p in *this.
+       Retain in *this the head portion of the original *this
+       Add the tail portion to the start (i.e. head) of *pList
+
+       e.g.
+          foo->MoveToHead(foo->GetTailPosition(), bar);
+              moves one element from the tail of foo to the head of bar
+          foo->MoveToHead(NULL, bar);
+              is a no-op, returns NULL
+          foo->MoveToHead(foo->GetHeadPosition, bar);
+              concatenates foo onto the start of bar and empties foo.
+    */
+    BOOL MoveToHead(__in_opt POSITION pos, __in CBaseList *pList);
+
+
+    /* Reverse the order of the [pointers to] objects in *this
+    */
+    void Reverse();
+
+
+    /* set cursor to the position of each element of list in turn  */
+    #define TRAVERSELIST(list, cursor)               \
+    for ( cursor = (list).GetHeadPosition()           \
+        ; cursor!=NULL                               \
+        ; cursor = (list).Next(cursor)                \
+        )
+
+
+    /* set cursor to the position of each element of list in turn
+       in reverse order
+    */
+    #define REVERSETRAVERSELIST(list, cursor)        \
+    for ( cursor = (list).GetTailPosition()           \
+        ; cursor!=NULL                               \
+        ; cursor = (list).Prev(cursor)                \
+        )
+
+}; // end of class declaration
+
+template<class OBJECT> class CGenericList : public CBaseList
+{
+public:
+    CGenericList(__in_opt LPCTSTR pName,
+                 INT iItems,
+                 BOOL bLock = TRUE,
+                 BOOL bAlert = FALSE) :
+                     CBaseList(pName, iItems) {
+        UNREFERENCED_PARAMETER(bAlert);
+        UNREFERENCED_PARAMETER(bLock);
+    };
+    CGenericList(__in_opt LPCTSTR pName) :
+                     CBaseList(pName) {
+    };
+
+    __out_opt POSITION GetHeadPosition() const { return (POSITION)m_pFirst; }
+    __out_opt POSITION GetTailPosition() const { return (POSITION)m_pLast; }
+    int GetCount() const { return m_Count; }
+
+    __out OBJECT *GetNext(__inout POSITION& rp) const { return (OBJECT *) GetNextI(rp); }
+
+    __out_opt OBJECT *Get(__in_opt POSITION p) const { return (OBJECT *) GetI(p); }
+    __out OBJECT *GetValid(__in POSITION p) const { return (OBJECT *) GetValidI(p); }
+    __out_opt OBJECT *GetHead() const  { return Get(GetHeadPosition()); }
+
+    __out_opt OBJECT *RemoveHead() { return (OBJECT *) RemoveHeadI(); }
+
+    __out_opt OBJECT *RemoveTail() { return (OBJECT *) RemoveTailI(); }
+
+    __out_opt OBJECT *Remove(__in_opt POSITION p) { return (OBJECT *) RemoveI(p); }
+    __out_opt POSITION AddBefore(__in_opt POSITION p, __in OBJECT * pObj) { return AddBeforeI(p, pObj); }
+    __out_opt POSITION AddAfter(__in_opt POSITION p, __in OBJECT * pObj)  { return AddAfterI(p, pObj); }
+    __out_opt POSITION AddHead(__in OBJECT * pObj) { return AddHeadI(pObj); }
+    __out_opt POSITION AddTail(__in OBJECT * pObj)  { return AddTailI(pObj); }
+    BOOL AddTail(__in CGenericList<OBJECT> *pList)
+            { return CBaseList::AddTail((CBaseList *) pList); }
+    BOOL AddHead(__in CGenericList<OBJECT> *pList)
+            { return CBaseList::AddHead((CBaseList *) pList); }
+    BOOL AddAfter(__in_opt POSITION p, __in CGenericList<OBJECT> *pList)
+            { return CBaseList::AddAfter(p, (CBaseList *) pList); };
+    BOOL AddBefore(__in_opt POSITION p, __in CGenericList<OBJECT> *pList)
+            { return CBaseList::AddBefore(p, (CBaseList *) pList); };
+    __out_opt POSITION Find( __in OBJECT * pObj) const { return FindI(pObj); }
+}; // end of class declaration
+
+
+
+/* These define the standard list types */
+
+typedef CGenericList<CBaseObject> CBaseObjectList;
+typedef CGenericList<IUnknown> CBaseInterfaceList;
+
+#endif /* __WXLIST__ */
+
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/wxutil.cpp b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/wxutil.cpp
new file mode 100644
index 0000000..59474ed
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/wxutil.cpp
@@ -0,0 +1,773 @@
+//------------------------------------------------------------------------------
+// File: WXUtil.cpp
+//
+// Desc: DirectShow base classes - implements helper classes for building
+//       multimedia filters.
+//
+// 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>
+#define STRSAFE_NO_DEPRECATE
+#include <strsafe.h>
+
+
+// --- CAMEvent -----------------------
+CAMEvent::CAMEvent(BOOL fManualReset, __inout_opt HRESULT *phr)
+{
+    m_hEvent = CreateEvent(NULL, fManualReset, FALSE, NULL);
+    if (NULL == m_hEvent) {
+        if (NULL != phr && SUCCEEDED(*phr)) {
+            *phr = E_OUTOFMEMORY;
+        }
+    }
+}
+
+CAMEvent::CAMEvent(__inout_opt HRESULT *phr)
+{
+    m_hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+    if (NULL == m_hEvent) {
+        if (NULL != phr && SUCCEEDED(*phr)) {
+            *phr = E_OUTOFMEMORY;
+        }
+    }
+}
+
+CAMEvent::~CAMEvent()
+{
+    if (m_hEvent) {
+	EXECUTE_ASSERT(CloseHandle(m_hEvent));
+    }
+}
+
+
+// --- CAMMsgEvent -----------------------
+// One routine.  The rest is handled in CAMEvent
+
+CAMMsgEvent::CAMMsgEvent(__inout_opt HRESULT *phr) : CAMEvent(FALSE, phr)
+{
+}
+
+BOOL CAMMsgEvent::WaitMsg(DWORD dwTimeout)
+{
+    // wait for the event to be signalled, or for the
+    // timeout (in MS) to expire.  allow SENT messages
+    // to be processed while we wait
+    DWORD dwWait;
+    DWORD dwStartTime = 0;
+
+    // set the waiting period.
+    DWORD dwWaitTime = dwTimeout;
+
+    // the timeout will eventually run down as we iterate
+    // processing messages.  grab the start time so that
+    // we can calculate elapsed times.
+    if (dwWaitTime != INFINITE) {
+        dwStartTime = timeGetTime();
+    }
+
+    do {
+        dwWait = MsgWaitForMultipleObjects(1,&m_hEvent,FALSE, dwWaitTime, QS_SENDMESSAGE);
+        if (dwWait == WAIT_OBJECT_0 + 1) {
+	    MSG Message;
+            PeekMessage(&Message,NULL,0,0,PM_NOREMOVE);
+
+	    // If we have an explicit length of time to wait calculate
+	    // the next wake up point - which might be now.
+	    // If dwTimeout is INFINITE, it stays INFINITE
+	    if (dwWaitTime != INFINITE) {
+
+		DWORD dwElapsed = timeGetTime()-dwStartTime;
+
+		dwWaitTime =
+		    (dwElapsed >= dwTimeout)
+			? 0  // wake up with WAIT_TIMEOUT
+			: dwTimeout-dwElapsed;
+	    }
+        }
+    } while (dwWait == WAIT_OBJECT_0 + 1);
+
+    // return TRUE if we woke on the event handle,
+    //        FALSE if we timed out.
+    return (dwWait == WAIT_OBJECT_0);
+}
+
+// --- CAMThread ----------------------
+
+
+CAMThread::CAMThread(__inout_opt HRESULT *phr)
+    : m_EventSend(TRUE, phr),     // must be manual-reset for CheckRequest()
+      m_EventComplete(FALSE, phr)
+{
+    m_hThread = NULL;
+}
+
+CAMThread::~CAMThread() {
+    Close();
+}
+
+
+// when the thread starts, it calls this function. We unwrap the 'this'
+//pointer and call ThreadProc.
+DWORD WINAPI
+CAMThread::InitialThreadProc(__inout LPVOID pv)
+{
+    HRESULT hrCoInit = CAMThread::CoInitializeHelper();
+    if(FAILED(hrCoInit)) {
+        DbgLog((LOG_ERROR, 1, TEXT("CoInitializeEx failed.")));
+    }
+
+    CAMThread * pThread = (CAMThread *) pv;
+
+    HRESULT hr = pThread->ThreadProc();
+
+    if(SUCCEEDED(hrCoInit)) {
+        CoUninitialize();
+    }
+
+    return hr;
+}
+
+BOOL
+CAMThread::Create()
+{
+    DWORD threadid;
+
+    CAutoLock lock(&m_AccessLock);
+
+    if (ThreadExists()) {
+	return FALSE;
+    }
+
+    m_hThread = CreateThread(
+		    NULL,
+		    0,
+		    CAMThread::InitialThreadProc,
+		    this,
+		    0,
+		    &threadid);
+
+    if (!m_hThread) {
+	return FALSE;
+    }
+
+    return TRUE;
+}
+
+DWORD
+CAMThread::CallWorker(DWORD dwParam)
+{
+    // lock access to the worker thread for scope of this object
+    CAutoLock lock(&m_AccessLock);
+
+    if (!ThreadExists()) {
+	return (DWORD) E_FAIL;
+    }
+
+    // set the parameter
+    m_dwParam = dwParam;
+
+    // signal the worker thread
+    m_EventSend.Set();
+
+    // wait for the completion to be signalled
+    m_EventComplete.Wait();
+
+    // done - this is the thread's return value
+    return m_dwReturnVal;
+}
+
+// Wait for a request from the client
+DWORD
+CAMThread::GetRequest()
+{
+    m_EventSend.Wait();
+    return m_dwParam;
+}
+
+// is there a request?
+BOOL
+CAMThread::CheckRequest(__out_opt DWORD * pParam)
+{
+    if (!m_EventSend.Check()) {
+	return FALSE;
+    } else {
+	if (pParam) {
+	    *pParam = m_dwParam;
+	}
+	return TRUE;
+    }
+}
+
+// reply to the request
+void
+CAMThread::Reply(DWORD dw)
+{
+    m_dwReturnVal = dw;
+
+    // The request is now complete so CheckRequest should fail from
+    // now on
+    //
+    // This event should be reset BEFORE we signal the client or
+    // the client may Set it before we reset it and we'll then
+    // reset it (!)
+
+    m_EventSend.Reset();
+
+    // Tell the client we're finished
+
+    m_EventComplete.Set();
+}
+
+HRESULT CAMThread::CoInitializeHelper()
+{
+    // call CoInitializeEx and tell OLE not to create a window (this
+    // thread probably won't dispatch messages and will hang on
+    // broadcast msgs o/w).
+    //
+    // If CoInitEx is not available, threads that don't call CoCreate
+    // aren't affected. Threads that do will have to handle the
+    // failure. Perhaps we should fall back to CoInitialize and risk
+    // hanging?
+    //
+
+    // older versions of ole32.dll don't have CoInitializeEx
+
+    HRESULT hr = E_FAIL;
+    HINSTANCE hOle = GetModuleHandle(TEXT("ole32.dll"));
+    if(hOle)
+    {
+        typedef HRESULT (STDAPICALLTYPE *PCoInitializeEx)(
+            LPVOID pvReserved, DWORD dwCoInit);
+        PCoInitializeEx pCoInitializeEx =
+            (PCoInitializeEx)(GetProcAddress(hOle, "CoInitializeEx"));
+        if(pCoInitializeEx)
+        {
+            hr = (*pCoInitializeEx)(0, COINIT_DISABLE_OLE1DDE );
+        }
+    }
+    else
+    {
+        // caller must load ole32.dll
+        DbgBreak("couldn't locate ole32.dll");
+    }
+
+    return hr;
+}
+
+
+// destructor for CMsgThread  - cleans up any messages left in the
+// queue when the thread exited
+CMsgThread::~CMsgThread()
+{
+    if (m_hThread != NULL) {
+        WaitForSingleObject(m_hThread, INFINITE);
+        EXECUTE_ASSERT(CloseHandle(m_hThread));
+    }
+
+    POSITION pos = m_ThreadQueue.GetHeadPosition();
+    while (pos) {
+        CMsg * pMsg = m_ThreadQueue.GetNext(pos);
+        delete pMsg;
+    }
+    m_ThreadQueue.RemoveAll();
+
+    if (m_hSem != NULL) {
+        EXECUTE_ASSERT(CloseHandle(m_hSem));
+    }
+}
+
+BOOL
+CMsgThread::CreateThread(
+    )
+{
+    m_hSem = CreateSemaphore(NULL, 0, 0x7FFFFFFF, NULL);
+    if (m_hSem == NULL) {
+        return FALSE;
+    }
+
+    m_hThread = ::CreateThread(NULL, 0, DefaultThreadProc,
+			       (LPVOID)this, 0, &m_ThreadId);
+    return m_hThread != NULL;
+}
+
+
+// This is the threads message pump.  Here we get and dispatch messages to
+// clients thread proc until the client refuses to process a message.
+// The client returns a non-zero value to stop the message pump, this
+// value becomes the threads exit code.
+
+DWORD WINAPI
+CMsgThread::DefaultThreadProc(
+    __inout LPVOID lpParam
+    )
+{
+    CMsgThread *lpThis = (CMsgThread *)lpParam;
+    CMsg msg;
+    LRESULT lResult;
+
+    // !!!
+    CoInitialize(NULL);
+
+    // allow a derived class to handle thread startup
+    lpThis->OnThreadInit();
+
+    do {
+	lpThis->GetThreadMsg(&msg);
+	lResult = lpThis->ThreadMessageProc(msg.uMsg,msg.dwFlags,
+					    msg.lpParam, msg.pEvent);
+    } while (lResult == 0L);
+
+    // !!!
+    CoUninitialize();
+
+    return (DWORD)lResult;
+}
+
+
+// Block until the next message is placed on the list m_ThreadQueue.
+// copies the message to the message pointed to by *pmsg
+void
+CMsgThread::GetThreadMsg(__out CMsg *msg)
+{
+    CMsg * pmsg = NULL;
+
+    // keep trying until a message appears
+    while (TRUE) {
+        {
+            CAutoLock lck(&m_Lock);
+            pmsg = m_ThreadQueue.RemoveHead();
+            if (pmsg == NULL) {
+                m_lWaiting++;
+            } else {
+                break;
+            }
+        }
+        // the semaphore will be signalled when it is non-empty
+        WaitForSingleObject(m_hSem, INFINITE);
+    }
+    // copy fields to caller's CMsg
+    *msg = *pmsg;
+
+    // this CMsg was allocated by the 'new' in PutThreadMsg
+    delete pmsg;
+
+}
+
+// Helper function - convert int to WSTR
+void WINAPI IntToWstr(int i, __out_ecount(12) LPWSTR wstr)
+{
+#ifdef UNICODE
+    if (FAILED(StringCchPrintf(wstr, 12, L"%d", i))) {
+        wstr[0] = 0;
+    }
+#else
+    TCHAR temp[12];
+    if (FAILED(StringCchPrintf(temp, NUMELMS(temp), "%d", i))) {
+        wstr[0] = 0;
+    } else {
+        MultiByteToWideChar(CP_ACP, 0, temp, -1, wstr, 12);
+    }
+#endif
+} // IntToWstr
+
+
+#define MEMORY_ALIGNMENT        4
+#define MEMORY_ALIGNMENT_LOG2   2
+#define MEMORY_ALIGNMENT_MASK   MEMORY_ALIGNMENT - 1
+
+void * __stdcall memmoveInternal(void * dst, const void * src, size_t count)
+{
+    void * ret = dst;
+
+#ifdef _X86_
+    if (dst <= src || (char *)dst >= ((char *)src + count)) {
+
+        /*
+         * Non-Overlapping Buffers
+         * copy from lower addresses to higher addresses
+         */
+        _asm {
+            mov     esi,src
+            mov     edi,dst
+            mov     ecx,count
+            cld
+            mov     edx,ecx
+            and     edx,MEMORY_ALIGNMENT_MASK
+            shr     ecx,MEMORY_ALIGNMENT_LOG2
+            rep     movsd
+            or      ecx,edx
+            jz      memmove_done
+            rep     movsb
+memmove_done:
+        }
+    }
+    else {
+
+        /*
+         * Overlapping Buffers
+         * copy from higher addresses to lower addresses
+         */
+        _asm {
+            mov     esi,src
+            mov     edi,dst
+            mov     ecx,count
+            std
+            add     esi,ecx
+            add     edi,ecx
+            dec     esi
+            dec     edi
+            rep     movsb
+            cld
+        }
+    }
+#else
+    MoveMemory(dst, src, count);
+#endif
+
+    return ret;
+}
+
+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)
+{
+    // prevent read overruns
+    if( count + cb_src_offset < count ||   // prevent integer overflow
+        count + cb_src_offset > src_size)  // prevent read overrun
+    {
+        return E_INVALIDARG;
+    }
+
+    // prevent write overruns
+    if( count + cb_dst_offset < count ||   // prevent integer overflow
+        count + cb_dst_offset > dst_size)  // prevent write overrun
+    {
+        return E_INVALIDARG;
+    }
+
+    memmoveInternal( (BYTE *)dst+cb_dst_offset, (BYTE *)src+cb_src_offset, count);
+    return S_OK;
+}
+
+
+#ifdef DEBUG
+/******************************Public*Routine******************************\
+* Debug CCritSec helpers
+*
+* We provide debug versions of the Constructor, destructor, Lock and Unlock
+* routines.  The debug code tracks who owns each critical section by
+* maintaining a depth count.
+*
+* History:
+*
+\**************************************************************************/
+
+CCritSec::CCritSec()
+{
+    InitializeCriticalSection(&m_CritSec);
+    m_currentOwner = m_lockCount = 0;
+    m_fTrace = FALSE;
+}
+
+CCritSec::~CCritSec()
+{
+    DeleteCriticalSection(&m_CritSec);
+}
+
+void CCritSec::Lock()
+{
+    UINT tracelevel=3;
+    DWORD us = GetCurrentThreadId();
+    DWORD currentOwner = m_currentOwner;
+    if (currentOwner && (currentOwner != us)) {
+        // already owned, but not by us
+        if (m_fTrace) {
+            DbgLog((LOG_LOCKING, 2, TEXT("Thread %d about to wait for lock %x owned by %d"),
+                GetCurrentThreadId(), &m_CritSec, currentOwner));
+            tracelevel=2;
+	        // if we saw the message about waiting for the critical
+	        // section we ensure we see the message when we get the
+	        // critical section
+        }
+    }
+    EnterCriticalSection(&m_CritSec);
+    if (0 == m_lockCount++) {
+        // we now own it for the first time.  Set owner information
+        m_currentOwner = us;
+
+        if (m_fTrace) {
+            DbgLog((LOG_LOCKING, tracelevel, TEXT("Thread %d now owns lock %x"), m_currentOwner, &m_CritSec));
+        }
+    }
+}
+
+void CCritSec::Unlock() {
+    if (0 == --m_lockCount) {
+        // about to be unowned
+        if (m_fTrace) {
+            DbgLog((LOG_LOCKING, 3, TEXT("Thread %d releasing lock %x"), m_currentOwner, &m_CritSec));
+        }
+
+        m_currentOwner = 0;
+    }
+    LeaveCriticalSection(&m_CritSec);
+}
+
+void WINAPI DbgLockTrace(CCritSec * pcCrit, BOOL fTrace)
+{
+    pcCrit->m_fTrace = fTrace;
+}
+
+BOOL WINAPI CritCheckIn(CCritSec * pcCrit)
+{
+    return (GetCurrentThreadId() == pcCrit->m_currentOwner);
+}
+
+BOOL WINAPI CritCheckIn(const CCritSec * pcCrit)
+{
+    return (GetCurrentThreadId() == pcCrit->m_currentOwner);
+}
+
+BOOL WINAPI CritCheckOut(CCritSec * pcCrit)
+{
+    return (GetCurrentThreadId() != pcCrit->m_currentOwner);
+}
+
+BOOL WINAPI CritCheckOut(const CCritSec * pcCrit)
+{
+    return (GetCurrentThreadId() != pcCrit->m_currentOwner);
+}
+#endif
+
+
+STDAPI WriteBSTR(__deref_out BSTR *pstrDest, LPCWSTR szSrc)
+{
+    *pstrDest = SysAllocString( szSrc );
+    if( !(*pstrDest) ) return E_OUTOFMEMORY;
+    return NOERROR;
+}
+
+
+STDAPI FreeBSTR(__deref_in BSTR* pstr)
+{
+    if( (PVOID)*pstr == NULL ) return S_FALSE;
+    SysFreeString( *pstr );
+    return NOERROR;
+}
+
+
+// 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 psz, __deref_out LPWSTR *ppszReturn)
+{
+    CheckPointer(ppszReturn, E_POINTER);
+    ValidateReadWritePtr(ppszReturn, sizeof(LPWSTR));
+    *ppszReturn = NULL;
+    size_t nameLen;
+    HRESULT hr = StringCbLengthW(psz, 100000, &nameLen);
+    if (FAILED(hr)) {
+        return hr;
+    }
+    *ppszReturn = (LPWSTR)CoTaskMemAlloc(nameLen + sizeof(WCHAR));
+    if (*ppszReturn == NULL) {
+       return E_OUTOFMEMORY;
+    }
+    CopyMemory(*ppszReturn, psz, nameLen + sizeof(WCHAR));
+    return NOERROR;
+}
+
+// Waits for the HANDLE hObject.  While waiting messages sent
+// to windows on our thread by SendMessage will be processed.
+// Using this function to do waits and mutual exclusion
+// avoids some deadlocks in objects with windows.
+// Return codes are the same as for WaitForSingleObject
+DWORD WINAPI WaitDispatchingMessages(
+    HANDLE hObject,
+    DWORD dwWait,
+    HWND hwnd,
+    UINT uMsg,
+    HANDLE hEvent)
+{
+    BOOL bPeeked = FALSE;
+    DWORD dwResult;
+    DWORD dwStart = 0;
+    DWORD dwThreadPriority = THREAD_PRIORITY_HIGHEST;
+
+    static UINT uMsgId = 0;
+
+    HANDLE hObjects[2] = { hObject, hEvent };
+    if (dwWait != INFINITE && dwWait != 0) {
+        dwStart = GetTickCount();
+    }
+    for (; ; ) {
+        DWORD nCount = NULL != hEvent ? 2 : 1;
+
+        //  Minimize the chance of actually dispatching any messages
+        //  by seeing if we can lock immediately.
+        dwResult = WaitForMultipleObjects(nCount, hObjects, FALSE, 0);
+        if (dwResult < WAIT_OBJECT_0 + nCount) {
+            break;
+        }
+
+        DWORD dwTimeOut = dwWait;
+        if (dwTimeOut > 10) {
+            dwTimeOut = 10;
+        }
+        dwResult = MsgWaitForMultipleObjects(
+                             nCount,
+                             hObjects,
+                             FALSE,
+                             dwTimeOut,
+                             hwnd == NULL ? QS_SENDMESSAGE :
+                                            QS_SENDMESSAGE + QS_POSTMESSAGE);
+        if (dwResult == WAIT_OBJECT_0 + nCount ||
+            dwResult == WAIT_TIMEOUT && dwTimeOut != dwWait) {
+            MSG msg;
+            if (hwnd != NULL) {
+                while (PeekMessage(&msg, hwnd, uMsg, uMsg, PM_REMOVE)) {
+                    DispatchMessage(&msg);
+                }
+            }
+            // Do this anyway - the previous peek doesn't flush out the
+            // messages
+            PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
+
+            if (dwWait != INFINITE && dwWait != 0) {
+                DWORD dwNow = GetTickCount();
+
+                // Working with differences handles wrap-around
+                DWORD dwDiff = dwNow - dwStart;
+                if (dwDiff > dwWait) {
+                    dwWait = 0;
+                } else {
+                    dwWait -= dwDiff;
+                }
+                dwStart = dwNow;
+            }
+            if (!bPeeked) {
+                //  Raise our priority to prevent our message queue
+                //  building up
+                dwThreadPriority = GetThreadPriority(GetCurrentThread());
+                if (dwThreadPriority < THREAD_PRIORITY_HIGHEST) {
+                    SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
+                }
+                bPeeked = TRUE;
+            }
+        } else {
+            break;
+        }
+    }
+    if (bPeeked) {
+        SetThreadPriority(GetCurrentThread(), dwThreadPriority);
+        if (HIWORD(GetQueueStatus(QS_POSTMESSAGE)) & QS_POSTMESSAGE) {
+            if (uMsgId == 0) {
+                uMsgId = RegisterWindowMessage(TEXT("AMUnblock"));
+            }
+            if (uMsgId != 0) {
+                MSG msg;
+                //  Remove old ones
+                while (PeekMessage(&msg, (HWND)-1, uMsgId, uMsgId, PM_REMOVE)) {
+                }
+            }
+            PostThreadMessage(GetCurrentThreadId(), uMsgId, 0, 0);
+        }
+    }
+    return dwResult;
+}
+
+HRESULT AmGetLastErrorToHResult()
+{
+    DWORD dwLastError = GetLastError();
+    if(dwLastError != 0)
+    {
+        return HRESULT_FROM_WIN32(dwLastError);
+    }
+    else
+    {
+        return E_FAIL;
+    }
+}
+
+IUnknown* QzAtlComPtrAssign(__deref_inout_opt IUnknown** pp, __in_opt IUnknown* lp)
+{
+    if (lp != NULL)
+        lp->AddRef();
+    if (*pp)
+        (*pp)->Release();
+    *pp = lp;
+    return lp;
+}
+
+/******************************************************************************
+
+CompatibleTimeSetEvent
+
+    CompatibleTimeSetEvent() sets the TIME_KILL_SYNCHRONOUS flag before calling
+timeSetEvent() if the current operating system supports it.  TIME_KILL_SYNCHRONOUS
+is supported on Windows XP and later operating systems.
+
+Parameters:
+- The same parameters as timeSetEvent().  See timeSetEvent()'s documentation in 
+the Platform SDK for more information.
+
+Return Value:
+- The same return value as timeSetEvent().  See timeSetEvent()'s documentation in 
+the Platform SDK for more information.
+
+******************************************************************************/
+MMRESULT CompatibleTimeSetEvent( UINT uDelay, UINT uResolution, __in LPTIMECALLBACK lpTimeProc, DWORD_PTR dwUser, UINT fuEvent )
+{
+    #if WINVER >= 0x0501
+    {
+        static bool fCheckedVersion = false;
+        static bool fTimeKillSynchronousFlagAvailable = false; 
+
+        if( !fCheckedVersion ) {
+            fTimeKillSynchronousFlagAvailable = TimeKillSynchronousFlagAvailable();
+            fCheckedVersion = true;
+        }
+
+        if( fTimeKillSynchronousFlagAvailable ) {
+            fuEvent = fuEvent | TIME_KILL_SYNCHRONOUS;
+        }
+    }
+    #endif // WINVER >= 0x0501
+
+    return timeSetEvent( uDelay, uResolution, lpTimeProc, dwUser, fuEvent );
+}
+
+bool TimeKillSynchronousFlagAvailable( void )
+{
+    OSVERSIONINFO osverinfo;
+
+    osverinfo.dwOSVersionInfoSize = sizeof(osverinfo);
+
+    if( GetVersionEx( &osverinfo ) ) {
+        
+        // Windows XP's major version is 5 and its' minor version is 1.
+        // timeSetEvent() started supporting the TIME_KILL_SYNCHRONOUS flag
+        // in Windows XP.
+        if( (osverinfo.dwMajorVersion > 5) || 
+            ( (osverinfo.dwMajorVersion == 5) && (osverinfo.dwMinorVersion >= 1) ) ) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+
+#endif /* PJMEDIA_VIDEO_DEV_HAS_DSHOW */
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/wxutil.h b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/wxutil.h
new file mode 100644
index 0000000..305974a
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/BaseClasses/wxutil.h
@@ -0,0 +1,532 @@
+//------------------------------------------------------------------------------
+// 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__ */
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/common/basic_op.c b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/common/basic_op.c
new file mode 100644
index 0000000..028d06f
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/common/basic_op.c
@@ -0,0 +1,1835 @@
+#include "config.h"
+
+#if !PJMEDIA_LIBG7221_FUNCS_INLINED || \
+    (PJMEDIA_LIBG7221_FUNCS_INLINED && defined(__BASIC_OP_H__))
+
+/*___________________________________________________________________________
+ |                                                                           |
+ | Basic arithmetic operators.                                               |
+ |___________________________________________________________________________|
+*/
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Include-Files                                                           |
+ |___________________________________________________________________________|
+*/
+
+//#include <stdio.h>
+//#include <stdlib.h>
+#include "typedef.h"
+#include "basic_op.h"
+#include <pj/assert.h>
+
+#if (WMOPS)
+#include "count.h"
+extern BASIC_OP multiCounter[MAXCOUNTERS];
+extern int currCounter;
+
+#endif
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Constants and Globals                                                   |
+ |___________________________________________________________________________|
+*/
+#if INCLUDE_UNSAFE
+Flag g7221_Overflow = 0;
+Flag g7221_Carry = 0;
+#endif
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Functions                                                               |
+ |___________________________________________________________________________|
+*/
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : shr                                                     |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Arithmetically shift the 16 bit input var1 right var2 positions with    |
+ |   sign extension. If var2 is negative, arithmetically shift var1 left by  |
+ |   -var2 with sign extension. Saturate the result in case of underflows or |
+ |   overflows.                                                              |
+ |                                                                           |
+ |   Complexity weight : 1                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    var1                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |    var2                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    var_out                                                                |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var_out <= 0x0000 7fff.                |
+ |___________________________________________________________________________|
+*/
+LIBG7221_DEF(Word16) shr (Word16 var1, Word16 var2)
+{
+    if (var2 < 0)
+    {
+        if (var2 < -16)
+            var2 = -16;
+        return shl_nocheck(var1, (Word16) -var2);
+    }
+    else
+    {
+        return shr_nocheck(var1, var2);
+    }
+}
+/* ------------------------- End of shr() ------------------------- */
+
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : shl                                                     |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Arithmetically shift the 16 bit input var1 left var2 positions.Zero fill|
+ |   the var2 LSB of the result. If var2 is negative, arithmetically shift   |
+ |   var1 right by -var2 with sign extension. Saturate the result in case of |
+ |   underflows or overflows.                                                |
+ |                                                                           |
+ |   Complexity weight : 1                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    var1                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |    var2                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    var_out                                                                |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var_out <= 0x0000 7fff.                |
+ |___________________________________________________________________________|
+*/
+LIBG7221_DEF(Word16) shl (Word16 var1, Word16 var2)
+{
+    if (var2 < 0)
+    {
+        return shr_nocheck(var1, (Word16) -var2);
+    }
+    else
+    {
+        return shl_nocheck(var1, var2);
+    }
+}
+/* ------------------------- End of shl() ------------------------- */
+
+
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : mult                                                    |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |    Performs the multiplication of var1 by var2 and gives a 16 bit result  |
+ |    which is scaled i.e.:                                                  |
+ |             mult(var1,var2) = extract_l(L_shr((var1 times var2),15)) and  |
+ |             mult(-32768,-32768) = 32767.                                  |
+ |                                                                           |
+ |   Complexity weight : 1                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    var1                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |    var2                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    var_out                                                                |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var_out <= 0x0000 7fff.                |
+ |___________________________________________________________________________|
+*/
+LIBG7221_DEF(Word16) mult (Word16 var1, Word16 var2)
+{
+    Word16 var_out;
+    Word32 L_product;
+
+    L_product = (Word32) var1 *(Word32) var2;
+
+    L_product = (L_product & (Word32) 0xffff8000L) >> 15;
+
+    if (L_product & (Word32) 0x00010000L)
+        L_product = L_product | (Word32) 0xffff0000L;
+
+    var_out = saturate (L_product);
+#if (WMOPS)
+    multiCounter[currCounter].mult++;
+#endif
+    return (var_out);
+}
+/* ------------------------- End of mult() ------------------------- */
+
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : L_msu                                                   |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Multiply var1 by var2 and shift the result left by 1. Subtract the 32   |
+ |   bit result to L_var3 with saturation, return a 32 bit result:           |
+ |        L_msu(L_var3,var1,var2) = L_sub(L_var3,L_mult(var1,var2)).         |
+ |                                                                           |
+ |   Complexity weight : 1                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    L_var3   32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |    var1                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |    var2                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    L_var_out                                                              |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.              |
+ |___________________________________________________________________________|
+*/
+LIBG7221_DEF(Word32) L_msu (Word32 L_var3, Word16 var1, Word16 var2)
+{
+    Word32 L_var_out;
+    Word32 L_product;
+
+    L_product = L_mult (var1, var2);
+#if (WMOPS)
+    multiCounter[currCounter].L_mult--;
+#endif
+    L_var_out = L_sub (L_var3, L_product);
+#if (WMOPS)
+    multiCounter[currCounter].L_sub--;
+    multiCounter[currCounter].L_msu++;
+#endif
+    return (L_var_out);
+}
+/* ------------------------- End of L_msu() ------------------------- */
+
+#if INCLUDE_UNSAFE
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : L_macNs                                                 |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Multiply var1 by var2 and shift the result left by 1. Add the 32 bit    |
+ |   result to L_var3 without saturation, return a 32 bit result. Generate   |
+ |   carry and overflow values :                                             |
+ |        L_macNs(L_var3,var1,var2) = L_add_c(L_var3,L_mult(var1,var2)).     |
+ |                                                                           |
+ |   Complexity weight : 1                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    L_var3   32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |    var1                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |    var2                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    L_var_out                                                              |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.              |
+ |                                                                           |
+ |   Caution :                                                               |
+ |                                                                           |
+ |    In some cases the Carry flag has to be cleared or set before using     |
+ |    operators which take into account its value.                           |
+ |___________________________________________________________________________|
+*/
+LIBG7221_DEF(Word32) L_macNs (Word32 L_var3, Word16 var1, Word16 var2)
+{
+    Word32 L_var_out;
+
+    L_var_out = L_mult (var1, var2);
+#if (WMOPS)
+    multiCounter[currCounter].L_mult--;
+#endif
+    L_var_out = L_add_c (L_var3, L_var_out);
+#if (WMOPS)
+    multiCounter[currCounter].L_add_c--;
+    multiCounter[currCounter].L_macNs++;
+#endif
+    return (L_var_out);
+}
+#endif
+/* ------------------------- End of L_macNs() ------------------------- */
+
+#if INCLUDE_UNSAFE
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : L_msuNs                                                 |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Multiply var1 by var2 and shift the result left by 1. Subtract the 32   |
+ |   bit result from L_var3 without saturation, return a 32 bit result. Ge-  |
+ |   nerate carry and overflow values :                                      |
+ |        L_msuNs(L_var3,var1,var2) = L_sub_c(L_var3,L_mult(var1,var2)).     |
+ |                                                                           |
+ |   Complexity weight : 1                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    L_var3   32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |    var1                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |    var2                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    L_var_out                                                              |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.              |
+ |                                                                           |
+ |   Caution :                                                               |
+ |                                                                           |
+ |    In some cases the Carry flag has to be cleared or set before using     |
+ |    operators which take into account its value.                           |
+ |___________________________________________________________________________|
+*/
+LIBG7221_DEF(Word32) L_msuNs (Word32 L_var3, Word16 var1, Word16 var2)
+{
+    Word32 L_var_out;
+
+    L_var_out = L_mult (var1, var2);
+#if (WMOPS)
+    multiCounter[currCounter].L_mult--;
+#endif
+    L_var_out = L_sub_c (L_var3, L_var_out);
+#if (WMOPS)
+    multiCounter[currCounter].L_sub_c--;
+    multiCounter[currCounter].L_msuNs++;
+#endif
+    return (L_var_out);
+}
+#endif
+
+/* ------------------------- End of L_msuNs() ------------------------- */
+
+
+#if INCLUDE_UNSAFE
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : L_add_c                                                 |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Performs 32 bits addition of the two 32 bits variables (L_var1+L_var2+C)|
+ |   with carry. No saturation. Generate carry and Overflow values. The car- |
+ |   ry and overflow values are binary variables which can be tested and as- |
+ |   signed values.                                                          |
+ |                                                                           |
+ |   Complexity weight : 2                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    L_var1   32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |    L_var2   32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    L_var_out                                                              |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.              |
+ |                                                                           |
+ |   Caution :                                                               |
+ |                                                                           |
+ |    In some cases the Carry flag has to be cleared or set before using     |
+ |    operators which take into account its value.                           |
+ |___________________________________________________________________________|
+*/
+LIBG7221_DEF(Word32) L_add_c (Word32 L_var1, Word32 L_var2)
+{
+    Word32 L_var_out;
+    Word32 L_test;
+    Flag carry_int = 0;
+
+    L_var_out = L_var1 + L_var2 + GET_CARRY();
+
+    L_test = L_var1 + L_var2;
+
+    if ((L_var1 > 0) && (L_var2 > 0) && (L_test < 0))
+    {
+        SET_OVERFLOW(1);
+        carry_int = 0;
+    }
+    else
+    {
+        if ((L_var1 < 0) && (L_var2 < 0))
+        {
+            if (L_test >= 0)
+	    {
+                SET_OVERFLOW(1);
+                carry_int = 1;
+	    }
+            else
+	    {
+                SET_OVERFLOW(0);
+                carry_int = 1;
+	    }
+        }
+        else
+        {
+            if (((L_var1 ^ L_var2) < 0) && (L_test >= 0))
+            {
+                SET_OVERFLOW(0);
+                carry_int = 1;
+            }
+            else
+            {
+                SET_OVERFLOW(0);
+                carry_int = 0;
+            }
+        }
+    }
+
+    if (GET_CARRY())
+    {
+        if (L_test == MAX_32)
+        {
+            SET_OVERFLOW(1);
+            SET_CARRY(carry_int);
+        }
+        else
+        {
+            if (L_test == (Word32) 0xFFFFFFFFL)
+            {
+                SET_CARRY(1);
+            }
+            else
+            {
+                SET_CARRY(carry_int);
+            }
+        }
+    }
+    else
+    {
+        SET_CARRY(carry_int);
+    }
+
+#if (WMOPS)
+    multiCounter[currCounter].L_add_c++;
+#endif
+    return (L_var_out);
+}
+#endif
+
+/* ------------------------- End of L_add_c() ------------------------- */
+
+#if INCLUDE_UNSAFE
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : L_sub_c                                                 |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Performs 32 bits subtraction of the two 32 bits variables with carry    |
+ |   (borrow) : L_var1-L_var2-C. No saturation. Generate carry and Overflow  |
+ |   values. The carry and overflow values are binary variables which can    |
+ |   be tested and assigned values.                                          |
+ |                                                                           |
+ |   Complexity weight : 2                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    L_var1   32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |    L_var2   32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    L_var_out                                                              |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.              |
+ |                                                                           |
+ |   Caution :                                                               |
+ |                                                                           |
+ |    In some cases the Carry flag has to be cleared or set before using     |
+ |    operators which take into account its value.                           |
+ |___________________________________________________________________________|
+*/
+LIBG7221_DEF(Word32) L_sub_c (Word32 L_var1, Word32 L_var2)
+{
+    Word32 L_var_out;
+    Word32 L_test;
+    Flag carry_int = 0;
+
+    if (GET_CARRY())
+    {
+        SET_CARRY(0);
+        if (L_var2 != MIN_32)
+        {
+            L_var_out = L_add_c (L_var1, -L_var2);
+#if (WMOPS)
+            multiCounter[currCounter].L_add_c--;
+#endif
+        }
+        else
+        {
+            L_var_out = L_var1 - L_var2;
+            if (L_var1 > 0L)
+            {
+                SET_OVERFLOW(1);
+                SET_CARRY(0);
+            }
+        }
+    }
+    else
+    {
+        L_var_out = L_var1 - L_var2 - (Word32) 0X00000001L;
+        L_test = L_var1 - L_var2;
+
+        if ((L_test < 0) && (L_var1 > 0) && (L_var2 < 0))
+        {
+            SET_OVERFLOW(1);
+            carry_int = 0;
+        }
+        else if ((L_test > 0) && (L_var1 < 0) && (L_var2 > 0))
+        {
+            SET_OVERFLOW(1);
+            carry_int = 1;
+        }
+        else if ((L_test > 0) && ((L_var1 ^ L_var2) > 0))
+        {
+            SET_OVERFLOW(0);
+            carry_int = 1;
+        }
+        if (L_test == MIN_32)
+        {
+            SET_OVERFLOW(1);
+            SET_CARRY(carry_int);
+        }
+        else
+        {
+            SET_CARRY(carry_int);
+        }
+    }
+
+#if (WMOPS)
+    multiCounter[currCounter].L_sub_c++;
+#endif
+    return (L_var_out);
+}
+#endif
+/* ------------------------- End of L_sub_c() ------------------------- */
+
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : L_negate                                                |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Negate the 32 bit variable L_var1 with saturation; saturate in the case |
+ |   where input is -2147483648 (0x8000 0000).                               |
+ |                                                                           |
+ |   Complexity weight : 2                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    L_var1   32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    L_var_out                                                              |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.              |
+ |___________________________________________________________________________|
+*/
+LIBG7221_DEF(Word32) L_negate (Word32 L_var1)
+{
+    Word32 L_var_out;
+
+    L_var_out = (L_var1 == MIN_32) ? MAX_32 : -L_var1;
+#if (WMOPS)
+    multiCounter[currCounter].L_negate++;
+#endif
+    return (L_var_out);
+}
+/* ------------------------- End of L_negate() ------------------------- */
+
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : mult_r                                                  |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Same as mult with rounding, i.e.:                                       |
+ |     mult_r(var1,var2) = extract_l(L_shr(((var1 * var2) + 16384),15)) and  |
+ |     mult_r(-32768,-32768) = 32767.                                        |
+ |                                                                           |
+ |   Complexity weight : 2                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    var1                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |    var2                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    var_out                                                                |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var_out <= 0x0000 7fff.                |
+ |___________________________________________________________________________|
+*/
+LIBG7221_DEF(Word16) mult_r (Word16 var1, Word16 var2)
+{
+    Word16 var_out;
+    Word32 L_product_arr;
+
+    L_product_arr = (Word32) var1 *(Word32) var2;       /* product */
+    L_product_arr += (Word32) 0x00004000L;      /* round */
+    L_product_arr &= (Word32) 0xffff8000L;
+    L_product_arr >>= 15;       /* shift */
+
+    if (L_product_arr & (Word32) 0x00010000L)   /* sign extend when necessary */
+    {
+        L_product_arr |= (Word32) 0xffff0000L;
+    }
+    var_out = saturate (L_product_arr);
+#if (WMOPS)
+    multiCounter[currCounter].mult_r++;
+#endif
+    return (var_out);
+}
+/* ------------------------- End of mult_r() ------------------------- */
+
+
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : shr_r                                                   |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Same as shr(var1,var2) but with rounding. Saturate the result in case of|
+ |   underflows or overflows :                                               |
+ |    - If var2 is greater than zero :                                       |
+ |          if (sub(shl(shr(var1,var2),1),shr(var1,sub(var2,1))))            |
+ |          is equal to zero                                                 |
+ |                     then                                                  |
+ |                     shr_r(var1,var2) = shr(var1,var2)                     |
+ |                     else                                                  |
+ |                     shr_r(var1,var2) = add(shr(var1,var2),1)              |
+ |    - If var2 is less than or equal to zero :                              |
+ |                     shr_r(var1,var2) = shr(var1,var2).                    |
+ |                                                                           |
+ |   Complexity weight : 2                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    var1                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |    var2                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    var_out                                                                |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var_out <= 0x0000 7fff.                |
+ |___________________________________________________________________________|
+*/
+LIBG7221_DEF(Word16) shr_r (Word16 var1, Word16 var2)
+{
+    Word16 var_out;
+
+    if (var2 > 15)
+    {
+        var_out = 0;
+    }
+    else
+    {
+        var_out = shr (var1, var2);
+#if (WMOPS)
+        multiCounter[currCounter].shr--;
+#endif
+
+        if (var2 > 0)
+        {
+            if ((var1 & ((Word16) 1 << (var2 - 1))) != 0)
+            {
+                var_out++;
+            }
+        }
+    }
+#if (WMOPS)
+    multiCounter[currCounter].shr_r++;
+#endif
+    return (var_out);
+}
+/* ------------------------- End of shr_r() ------------------------- */
+
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : mac_r                                                   |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Multiply var1 by var2 and shift the result left by 1. Add the 32 bit    |
+ |   result to L_var3 with saturation. Round the LS 16 bits of the result    |
+ |   into the MS 16 bits with saturation and shift the result right by 16.   |
+ |   Return a 16 bit result.                                                 |
+ |            mac_r(L_var3,var1,var2) = round(L_mac(L_var3,var1,var2))       |
+ |                                                                           |
+ |   Complexity weight : 2                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    L_var3   32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |    var1                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |    var2                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    var_out                                                                |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0x0000 8000 <= L_var_out <= 0x0000 7fff.              |
+ |___________________________________________________________________________|
+*/
+LIBG7221_DEF(Word16) mac_r (Word32 L_var3, Word16 var1, Word16 var2)
+{
+    Word16 var_out;
+
+    L_var3 = L_mac (L_var3, var1, var2);
+#if (WMOPS)
+    multiCounter[currCounter].L_mac--;
+#endif
+    L_var3 = L_add (L_var3, (Word32) 0x00008000L);
+#if (WMOPS)
+    multiCounter[currCounter].L_add--;
+#endif
+    var_out = extract_h (L_var3);
+#if (WMOPS)
+    multiCounter[currCounter].extract_h--;
+    multiCounter[currCounter].mac_r++;
+#endif
+    return (var_out);
+}
+/* ------------------------- End of mac_r() ------------------------- */
+
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : msu_r                                                   |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Multiply var1 by var2 and shift the result left by 1. Subtract the 32   |
+ |   bit result to L_var3 with saturation. Round the LS 16 bits of the res-  |
+ |   ult into the MS 16 bits with saturation and shift the result right by   |
+ |   16. Return a 16 bit result.                                             |
+ |            msu_r(L_var3,var1,var2) = round(L_msu(L_var3,var1,var2))       |
+ |                                                                           |
+ |   Complexity weight : 2                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    L_var3   32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |    var1                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |    var2                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    var_out                                                                |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0x0000 8000 <= L_var_out <= 0x0000 7fff.              |
+ |___________________________________________________________________________|
+*/
+LIBG7221_DEF(Word16) msu_r (Word32 L_var3, Word16 var1, Word16 var2)
+{
+    Word16 var_out;
+
+    L_var3 = L_msu (L_var3, var1, var2);
+#if (WMOPS)
+    multiCounter[currCounter].L_msu--;
+#endif
+    L_var3 = L_add (L_var3, (Word32) 0x00008000L);
+#if (WMOPS)
+    multiCounter[currCounter].L_add--;
+#endif
+    var_out = extract_h (L_var3);
+#if (WMOPS)
+    multiCounter[currCounter].extract_h--;
+    multiCounter[currCounter].msu_r++;
+#endif
+    return (var_out);
+}
+/* ------------------------- End of msu_r() ------------------------- */
+
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : L_deposit_h                                             |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Deposit the 16 bit var1 into the 16 MS bits of the 32 bit output. The   |
+ |   16 LS bits of the output are zeroed.                                    |
+ |                                                                           |
+ |   Complexity weight : 2                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    var1                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    L_var_out                                                              |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= var_out <= 0x7fff 0000.                |
+ |___________________________________________________________________________|
+*/
+LIBG7221_DEF(Word32) L_deposit_h (Word16 var1)
+{
+    Word32 L_var_out;
+
+    L_var_out = (Word32) var1 << 16;
+#if (WMOPS)
+    multiCounter[currCounter].L_deposit_h++;
+#endif
+    return (L_var_out);
+}
+/* ------------------------- End of L_deposit_h() ------------------------- */
+
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : L_deposit_l                                             |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Deposit the 16 bit var1 into the 16 LS bits of the 32 bit output. The   |
+ |   16 MS bits of the output are sign extended.                             |
+ |                                                                           |
+ |   Complexity weight : 2                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    var1                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    L_var_out                                                              |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0xFFFF 8000 <= var_out <= 0x0000 7fff.                |
+ |___________________________________________________________________________|
+*/
+LIBG7221_DEF(Word32) L_deposit_l (Word16 var1)
+{
+    Word32 L_var_out;
+
+    L_var_out = (Word32) var1;
+#if (WMOPS)
+    multiCounter[currCounter].L_deposit_l++;
+#endif
+    return (L_var_out);
+}
+/* ------------------------- End of L_deposit_l() ------------------------- */
+
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : L_shr_r                                                 |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Same as L_shr(L_var1,var2) but with rounding. Saturate the result in    |
+ |   case of underflows or overflows :                                       |
+ |    - If var2 is greater than zero :                                       |
+ |          if (L_sub(L_shl(L_shr(L_var1,var2),1),L_shr(L_var1,sub(var2,1))))|
+ |          is equal to zero                                                 |
+ |                     then                                                  |
+ |                     L_shr_r(L_var1,var2) = L_shr(L_var1,var2)             |
+ |                     else                                                  |
+ |                     L_shr_r(L_var1,var2) = L_add(L_shr(L_var1,var2),1)    |
+ |    - If var2 is less than or equal to zero :                              |
+ |                     L_shr_r(L_var1,var2) = L_shr(L_var1,var2).            |
+ |                                                                           |
+ |   Complexity weight : 3                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    L_var1                                                                 |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= var1 <= 0x7fff ffff.                   |
+ |                                                                           |
+ |    var2                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    L_var_out                                                              |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= var_out <= 0x7fff ffff.                |
+ |___________________________________________________________________________|
+*/
+LIBG7221_DEF(Word32) L_shr_r (Word32 L_var1, Word16 var2)
+{
+    Word32 L_var_out;
+
+    if (var2 > 31)
+    {
+        L_var_out = 0;
+    }
+    else
+    {
+        L_var_out = L_shr (L_var1, var2);
+#if (WMOPS)
+        multiCounter[currCounter].L_shr--;
+#endif
+        if (var2 > 0)
+        {
+            if ((L_var1 & ((Word32) 1 << (var2 - 1))) != 0)
+            {
+                L_var_out++;
+            }
+        }
+    }
+#if (WMOPS)
+    multiCounter[currCounter].L_shr_r++;
+#endif
+    return (L_var_out);
+}
+/* ------------------------- End of L_shr_r() ------------------------- */
+
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : L_abs                                                   |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |    Absolute value of L_var1; Saturate in case where the input is          |
+ |                                                               -214783648  |
+ |                                                                           |
+ |   Complexity weight : 3                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    L_var1                                                                 |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= var1 <= 0x7fff ffff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    L_var_out                                                              |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x0000 0000 <= var_out <= 0x7fff ffff.                |
+ |___________________________________________________________________________|
+*/
+LIBG7221_DEF(Word32) L_abs (Word32 L_var1)
+{
+    Word32 L_var_out;
+
+    if (L_var1 == MIN_32)
+    {
+        L_var_out = MAX_32;
+    }
+    else
+    {
+        if (L_var1 < 0)
+        {
+            L_var_out = -L_var1;
+        }
+        else
+        {
+            L_var_out = L_var1;
+        }
+    }
+
+#if (WMOPS)
+    multiCounter[currCounter].L_abs++;
+#endif
+    return (L_var_out);
+}
+/* ------------------------- End of L_abs() ------------------------- */
+
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : norm_s                                                  |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Produces the number of left shift needed to normalize the 16 bit varia- |
+ |   ble var1 for positive values on the interval with minimum of 16384 and  |
+ |   maximum of 32767, and for negative values on the interval with minimum  |
+ |   of -32768 and maximum of -16384; in order to normalize the result, the  |
+ |   following operation must be done :                                      |
+ |                    norm_var1 = shl(var1,norm_s(var1)).                    |
+ |                                                                           |
+ |   Complexity weight : 15                                                  |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    var1                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    var_out                                                                |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0x0000 0000 <= var_out <= 0x0000 000f.                |
+ |___________________________________________________________________________|
+*/
+LIBG7221_DEF(Word16) norm_s (Word16 var1)
+{
+    Word16 var_out;
+
+    if (var1 == 0)
+    {
+        var_out = 0;
+    }
+    else
+    {
+        if ((UWord16)var1 == (UWord16)0xffff)
+        {
+            var_out = 15;
+        }
+        else
+        {
+            if (var1 < 0)
+            {
+                var1 = (Word16)(~var1);
+            }
+            for (var_out = 0; var1 < 0x4000; var_out++)
+            {
+                var1 <<= 1;
+            }
+        }
+    }
+
+#if (WMOPS)
+    multiCounter[currCounter].norm_s++;
+#endif
+    return (var_out);
+}
+/* ------------------------- End of norm_s() ------------------------- */
+
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : div_s                                                   |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Produces a result which is the fractional integer division of var1  by  |
+ |   var2; var1 and var2 must be positive and var2 must be greater or equal  |
+ |   to var1; the result is positive (leading bit equal to 0) and truncated  |
+ |   to 16 bits.                                                             |
+ |   If var1 = var2 then div(var1,var2) = 32767.                             |
+ |                                                                           |
+ |   Complexity weight : 18                                                  |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    var1                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0x0000 0000 <= var1 <= var2 and var2 != 0.            |
+ |                                                                           |
+ |    var2                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : var1 <= var2 <= 0x0000 7fff and var2 != 0.            |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    var_out                                                                |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0x0000 0000 <= var_out <= 0x0000 7fff.                |
+ |             It's a Q15 value (point between b15 and b14).                 |
+ |___________________________________________________________________________|
+*/
+LIBG7221_DEF(Word16) div_s (Word16 var1, Word16 var2)
+{
+    Word16 var_out = 0;
+    Word16 iteration;
+    Word32 L_num;
+    Word32 L_denom;
+
+    if ((var1 > var2) || (var1 < 0) || (var2 < 0))
+    {
+        //printf ("Division Error var1=%d  var2=%d\n", var1, var2);
+        //abort(); /* exit (0); */
+	pj_assert(!"Division Error");
+    }
+    if (var2 == 0)
+    {
+        //printf ("Division by 0, Fatal error \n");
+        //abort(); /* exit (0); */
+	assert(!"Division by 0");
+    }
+    if (var1 == 0)
+    {
+        var_out = 0;
+    }
+    else
+    {
+        if (var1 == var2)
+        {
+            var_out = MAX_16;
+        }
+        else
+        {
+            L_num = L_deposit_l (var1);
+#if (WMOPS)
+            multiCounter[currCounter].L_deposit_l--;
+#endif
+            L_denom = L_deposit_l (var2);
+#if (WMOPS)
+            multiCounter[currCounter].L_deposit_l--;
+#endif
+
+            for (iteration = 0; iteration < 15; iteration++)
+            {
+                var_out <<= 1;
+                L_num <<= 1;
+
+                if (L_num >= L_denom)
+                {
+                    L_num = L_sub (L_num, L_denom);
+#if (WMOPS)
+                    multiCounter[currCounter].L_sub--;
+#endif
+                    var_out = add (var_out, 1);
+#if (WMOPS)
+                    multiCounter[currCounter].add--;
+#endif
+                }
+            }
+        }
+    }
+
+#if (WMOPS)
+    multiCounter[currCounter].div_s++;
+#endif
+    return (var_out);
+}
+/* ------------------------- End of div_s() ------------------------- */
+
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : norm_l                                                  |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Produces the number of left shifts needed to normalize the 32 bit varia-|
+ |   ble L_var1 for positive values on the interval with minimum of          |
+ |   1073741824 and maximum of 2147483647, and for negative values on the in-|
+ |   terval with minimum of -2147483648 and maximum of -1073741824; in order |
+ |   to normalize the result, the following operation must be done :         |
+ |                   norm_L_var1 = L_shl(L_var1,norm_l(L_var1)).             |
+ |                                                                           |
+ |   Complexity weight : 30                                                  |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    L_var1                                                                 |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= var1 <= 0x7fff ffff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    var_out                                                                |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0x0000 0000 <= var_out <= 0x0000 001f.                |
+ |___________________________________________________________________________|
+*/
+LIBG7221_DEF(Word16) norm_l (Word32 L_var1)
+{
+    Word16 var_out;
+
+    if (L_var1 == 0)
+    {
+        var_out = 0;
+    }
+    else
+    {
+        if (L_var1 == (Word32) 0xffffffffL)
+        {
+            var_out = 31;
+        }
+        else
+        {
+            if (L_var1 < 0)
+            {
+                L_var1 = ~L_var1;
+            }
+            for (var_out = 0; L_var1 < (Word32) 0x40000000L; var_out++)
+            {
+                L_var1 <<= 1;
+            }
+        }
+    }
+
+#if (WMOPS)
+    multiCounter[currCounter].norm_l++;
+#endif
+    return (var_out);
+}
+/* ------------------------- End of norm_l() ------------------------- */
+
+
+/*
+  *****************************************************************
+   Additional operators extracted from the G.723.1 Library
+   Adapted for WMOPS calculations
+  *****************************************************************
+*/
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : L_mls                                                   |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Multiplies a 16 bit word v by a 32 bit word Lv and returns a 32 bit     |
+ |   word (multiplying 16 by 32 bit words gives 48 bit word; the function    |
+ |   extracts the 32 MSB and shift the result to the left by 1).             |
+ |                                                                           |
+ |   A 32 bit word can be written as                                         |
+ |    Lv = a  +  b * 2^16                                                    |
+ |   where a= unsigned 16 LSBs and b= signed 16 MSBs.                        |
+ |   The function returns v * Lv  /  2^15  which is equivalent to            |
+ |        a*v / 2^15 + b*v*2                                                 |
+ |                                                                           |
+ |   Complexity weight : 6 [to be confirmed]                                 |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |   Lv                                                                      |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= var1 <= 0x7fff ffff.                   |
+ |   v                                                                       |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0x8000 <= var1 <= 0x7fff.                             |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    var_out                                                                |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= var_out <= 0x7fff ffff.                |
+ |                                                                           |
+ |___________________________________________________________________________|
+*/
+LIBG7221_DEF(Word32) L_mls (Word32 Lv, Word16 v)
+{
+   Word32   Temp  ;
+
+   Temp = Lv & (Word32) 0x0000ffff ;
+   Temp = Temp * (Word32) v ;
+   Temp = L_shr_nocheck( Temp, (Word16) 15 ) ;
+   Temp = L_mac( Temp, v, extract_h(Lv) ) ;
+
+#if (WMOPS)
+   multiCounter[currCounter].L_shr--;
+   multiCounter[currCounter].L_mac--;
+   multiCounter[currCounter].extract_h--;
+   multiCounter[currCounter].L_mls++;
+#endif
+
+   return Temp ;
+}
+/* ------------------------- End of L_mls() ------------------------- */
+
+
+/*__________________________________________________________________________
+|                                                                           |
+|   Function Name : div_l                                                   |
+|                                                                           |
+|   Purpose :                                                               |
+|                                                                           |
+|   Produces a result which is the fractional integer division of L_var1 by|
+|   var2; L_var1 and var2 must be positive and var2 << 16 must be greater or|
+|   equal to L_var1; the result is positive (leading bit equal to 0) and    |
+|   truncated to 16 bits.                                                   |
+|   If L_var1 == var2 << 16 then div_l(L_var1,var2) = 32767.                |
+|                                                                           |
+|   Complexity weight : 20                                                  |
+|                                                                           |
+|   Inputs :                                                                |
+|                                                                           |
+|    L_var1                                                                 |
+|             32 bit long signed integer (Word32) whose value falls in the  |
+|             range : 0x0000 0000 <= var1 <= (var2 << 16)  and var2 != 0.   |
+|             L_var1 must be considered as a Q.31 value                     |
+|                                                                           |
+|    var2                                                                   |
+|             16 bit short signed integer (Word16) whose value falls in the |
+|             range : var1 <= (var2<< 16) <= 0x7fff0000 and var2 != 0.      |
+|             var2 must be considered as a Q.15 value                       |
+|                                                                           |
+|   Outputs :                                                               |
+|                                                                           |
+|    none                                                                   |
+|                                                                           |
+|   Return Value :                                                          |
+|                                                                           |
+|    var_out                                                                |
+|             16 bit short signed integer (Word16) whose value falls in the |
+|             range : 0x0000 0000 <= var_out <= 0x0000 7fff.                |
+|             It's a Q15 value (point between b15 and b14).                 |
+|___________________________________________________________________________|
+*/
+LIBG7221_DEF(Word16) div_l (Word32  L_num, Word16 den)
+{
+    Word16   var_out = (Word16)0;
+    Word32   L_den;
+    Word16   iteration;
+
+#if (WMOPS)
+    multiCounter[currCounter].div_l++;
+#endif
+
+    if ( den == (Word16) 0 ) {
+        //printf("Division by 0 in div_l, Fatal error \n");
+        //exit(0);
+	assert(!"Division by 0");
+    }
+
+    if ( (L_num < (Word32) 0) || (den < (Word16) 0) ) {
+        //printf("Division Error in div_l, Fatal error \n");
+        //exit(0);
+	assert(!"Division Error");
+    }
+
+    L_den = L_deposit_h( den ) ;
+#if (WMOPS)
+    multiCounter[currCounter].L_deposit_h--;
+#endif
+
+    if ( L_num >= L_den ){
+        return MAX_16 ;
+    }
+    else {
+        L_num = L_shr_nocheck(L_num, (Word16)1) ;
+        L_den = L_shr_nocheck(L_den, (Word16)1);
+#if (WMOPS)
+        multiCounter[currCounter].L_shr-=2;
+#endif
+        for(iteration=(Word16)0; iteration< (Word16)15;iteration++) {
+            var_out = shl_nocheck( var_out, (Word16)1);
+            L_num   = L_shl_nocheck( L_num, (Word16)1);
+#if (WMOPS)
+            multiCounter[currCounter].shl--;
+            multiCounter[currCounter].L_shl--;
+#endif
+            if (L_num >= L_den) {
+                L_num = L_sub(L_num,L_den);
+                var_out = add(var_out, (Word16)1);
+#if (WMOPS)
+            multiCounter[currCounter].L_sub--;
+            multiCounter[currCounter].add--;
+#endif
+            }
+        }
+
+        return var_out;
+    }
+}
+/* ------------------------- End of div_l() ------------------------- */
+
+
+/*__________________________________________________________________________
+|                                                                           |
+|   Function Name : i_mult                                                  |
+|                                                                           |
+|   Purpose :                                                               |
+|                                                                           |
+|   Integer 16-bit multiplication. No overflow protection is performed if   |
+|   ORIGINAL_G7231 is defined.                                              |
+|                                                                           |
+|   Complexity weight : TBD                                                 |
+|                                                                           |
+|   Inputs :                                                                |
+|                                                                           |
+|    a                                                                      |
+|             16 bit short signed integer (Word16).                         |
+|                                                                           |
+|    b                                                                      |
+|             16 bit short signed integer (Word16).                         |
+|                                                                           |
+|   Outputs :                                                               |
+|                                                                           |
+|    none                                                                   |
+|                                                                           |
+|   Return Value :                                                          |
+|                                                                           |
+|             16 bit short signed integer (Word16). No overflow checks      |
+|             are performed if ORIGINAL_G7231 is defined.                   |
+|___________________________________________________________________________|
+*/
+LIBG7221_DEF(Word16) i_mult (Word16 a, Word16 b)
+{
+#ifdef ORIGINAL_G7231
+   return a*b ;
+#else
+   Word32 register c=a*b;
+#if (WMOPS)
+    multiCounter[currCounter].i_mult++;
+#endif
+   return saturate(c) ;
+#endif
+}
+/* ------------------------- End of i_mult() ------------------------- */
+
+
+/*
+   ********************************************************************** 
+   The following three operators are not part of the original 
+   G.729/G.723.1 set of basic operators and implement shiftless
+   accumulation operation.
+   ********************************************************************** 
+*/
+
+/*___________________________________________________________________________
+ |
+ |   Function Name : L_mult0
+ |
+ |   Purpose :
+ |
+ |   L_mult0 is the 32 bit result of the multiplication of var1 times var2
+ |   without one left shift.
+ |
+ |   Complexity weight : 1
+ |
+ |   Inputs :
+ |
+ |    var1     16 bit short signed integer (Word16) whose value falls in the
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+ |
+ |    var2     16 bit short signed integer (Word16) whose value falls in the
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+ |
+ |   Return Value :
+ |
+ |    L_var_out
+ |             32 bit long signed integer (Word32) whose value falls in the
+ |             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.
+ |___________________________________________________________________________
+*/
+LIBG7221_DEF(Word32) L_mult0 (Word16 var1,Word16 var2)
+{
+  Word32 L_var_out;
+
+  L_var_out = (Word32)var1 * (Word32)var2;
+
+#if (WMOPS)
+    multiCounter[currCounter].L_mult0++;
+#endif
+  return(L_var_out);
+}
+/* ------------------------- End of L_mult0() ------------------------- */
+
+
+/*___________________________________________________________________________
+ |
+ |   Function Name : L_mac0
+ |
+ |   Purpose :
+ |
+ |   Multiply var1 by var2 (without left shift) and add the 32 bit result to
+ |   L_var3 with saturation, return a 32 bit result:
+ |        L_mac0(L_var3,var1,var2) = L_add(L_var3,(L_mult0(var1,var2)).
+ |
+ |   Complexity weight : 1
+ |
+ |   Inputs :
+ |
+ |    L_var3   32 bit long signed integer (Word32) whose value falls in the
+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.
+ |
+ |    var1     16 bit short signed integer (Word16) whose value falls in the
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+ |
+ |    var2     16 bit short signed integer (Word16) whose value falls in the
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+ |
+ |   Return Value :
+ |
+ |    L_var_out
+ |             32 bit long signed integer (Word32) whose value falls in the
+ |             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.
+ |___________________________________________________________________________
+*/
+LIBG7221_DEF(Word32) L_mac0 (Word32 L_var3, Word16 var1, Word16 var2)
+{
+  Word32 L_var_out;
+  Word32 L_product;
+
+  L_product = L_mult0(var1,var2);
+  L_var_out = L_add(L_var3,L_product);
+
+#if (WMOPS)
+    multiCounter[currCounter].L_mac0++;
+    multiCounter[currCounter].L_mult0--;
+    multiCounter[currCounter].L_add--;
+#endif
+  return(L_var_out);
+}
+/* ------------------------- End of L_mac0() ------------------------- */
+
+
+/*___________________________________________________________________________
+ |
+ |   Function Name : L_msu0
+ |
+ |   Purpose :
+ |
+ |   Multiply var1 by var2 (without left shift) and subtract the 32 bit
+ |   result to L_var3 with saturation, return a 32 bit result:
+ |        L_msu0(L_var3,var1,var2) = L_sub(L_var3,(L_mult0(var1,var2)).
+ |
+ |   Complexity weight : 1
+ |
+ |   Inputs :
+ |
+ |    L_var3   32 bit long signed integer (Word32) whose value falls in the
+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.
+ |
+ |    var1     16 bit short signed integer (Word16) whose value falls in the
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+ |
+ |    var2     16 bit short signed integer (Word16) whose value falls in the
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+ |
+ |   Return Value :
+ |
+ |    L_var_out
+ |             32 bit long signed integer (Word32) whose value falls in the
+ |             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.
+ |___________________________________________________________________________
+*/
+LIBG7221_DEF(Word32) L_msu0 (Word32 L_var3, Word16 var1, Word16 var2)
+{
+  Word32 L_var_out;
+  Word32 L_product;
+
+  L_product = L_mult0(var1,var2);
+  L_var_out = L_sub(L_var3,L_product);
+
+#if (WMOPS)
+    multiCounter[currCounter].L_msu0++;
+    multiCounter[currCounter].L_mult0--;
+    multiCounter[currCounter].L_sub--;
+#endif
+  return(L_var_out);
+}
+/* ------------------------- End of L_msu0() ------------------------- */
+
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : LU_shl                                                  |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Arithmetically shift the 32 bit input L_var1 left var2 positions. Zero  |
+ |   fill the var2 LSB of the result. If var2 is negative, arithmetically    |
+ |   shift L_var1 right by -var2 with sign extension. Saturate the result in |
+ |   case of underflows or overflows.                                        |
+ |                                                                           |
+ |   Complexity weight : 2                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    L_var1   32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |    var2                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    L_var_out                                                              |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.              |
+ |___________________________________________________________________________|
+*/
+LIBG7221_DEF(UWord32) LU_shl (UWord32 L_var1, Word16 var2)
+{
+    Word16 neg_var2;
+    UWord32 L_var_out = 0;
+
+    if (var2 <= 0)
+    {
+        if (var2 < -32)
+            var2 = -32;
+        neg_var2 = negate(var2);
+        L_var_out = LU_shr (L_var1, neg_var2);
+#if (WMOPS)
+        multiCounter[currCounter].negate--;
+        multiCounter[currCounter].LU_shr--;
+#endif
+    }
+    else
+    {
+        for (; var2 > 0; var2--)
+        {
+            if (L_var1 > (UWord32) 0X7fffffffL)
+            {
+                SET_OVERFLOW(1);
+                L_var_out = UMAX_32;
+                break;
+            }
+            else
+            {
+                if (L_var1 < (UWord32) 0x00000001L)
+                {
+                    SET_OVERFLOW(1);
+                    L_var_out = (UWord32)MIN_32;
+                    break;
+                }
+            }
+            L_var1 *= 2;
+            L_var_out = L_var1;
+        }
+    }
+#if (WMOPS)
+    multiCounter[currCounter].LU_shl++;
+#endif
+    return (L_var_out);
+}
+/* ------------------------- End of LU_shl() ------------------------- */
+
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : LU_shr                                                  |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Arithmetically shift the 32 bit input L_var1 right var2 positions with  |
+ |   sign extension. If var2 is negative, arithmetically shift L_var1 left   |
+ |   by -var2 and zero fill the -var2 LSB of the result. Saturate the result |
+ |   in case of underflows or overflows.                                     |
+ |                                                                           |
+ |   Complexity weight : 2                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    L_var1   32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |    var2                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    L_var_out                                                              |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.              |
+ |___________________________________________________________________________|
+*/
+LIBG7221_DEF(UWord32) LU_shr (UWord32 L_var1, Word16 var2)
+{
+    Word16  neg_var2;
+    UWord32 L_var_out;
+
+    if (var2 < 0)
+    {
+        if (var2 < -32)
+            var2 = -32;
+        neg_var2 = negate(var2);
+        L_var_out = LU_shl (L_var1, neg_var2);
+#if (WMOPS)
+        multiCounter[currCounter].negate--;
+        multiCounter[currCounter].LU_shl--;
+#endif
+    }
+    else
+    {
+        if (var2 >= 32)
+        {
+            L_var_out = 0L;
+        }
+        else
+        {
+            L_var_out = L_var1 >> var2;
+        }
+    }
+#if (WMOPS)
+    multiCounter[currCounter].LU_shr++;
+#endif
+    return (L_var_out);
+}
+/* ------------------------- End of LU_shr() ------------------------- */
+
+#endif /* PJMEDIA_LIBG7221_FUNCS_INLINED */
+
+/* ************************** END OF BASOP32.C ************************** */
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/common/basic_op.h b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/common/basic_op.h
new file mode 100644
index 0000000..45104d1
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/common/basic_op.h
@@ -0,0 +1,117 @@
+#ifndef __BASIC_OP_H__
+#define __BASIC_OP_H__
+
+#include "config.h"
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Constants and Globals                                                   |
+ |___________________________________________________________________________|
+*/
+
+#define MAX_32 (Word32)0x7fffffffL
+#define MIN_32 (Word32)0x80000000L
+
+#define MAX_16 (Word16)0x7fff
+#define MIN_16 (Word16)(pj_uint16_t)0x8000
+
+#define UMAX_32 (UWord32)0xffffffffL
+#define UMIN_32 (UWord32)0x00000000L
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Prototypes for basic arithmetic operators                               |
+ |___________________________________________________________________________|
+*/
+
+PJ_INLINE(Word16) add (Word16 var1, Word16 var2);    /* Short add,           1   */
+PJ_INLINE(Word16) sub (Word16 var1, Word16 var2);    /* Short sub,           1   */
+PJ_INLINE(Word16) abs_s (Word16 var1);               /* Short abs,           1   */
+LIBG7221_DECL(Word16) shl (Word16 var1, Word16 var2);    /* Short shift left,    1   */
+PJ_INLINE(Word16) shl_nocheck(Word16 var1, Word16 var2);
+LIBG7221_DECL(Word16) shr (Word16 var1, Word16 var2);    /* Short shift right,   1   */
+PJ_INLINE(Word16) shr_nocheck(Word16 var1, Word16 var2);
+LIBG7221_DECL(Word16) mult (Word16 var1, Word16 var2);   /* Short mult,          1   */
+PJ_INLINE(Word32) L_mult (Word16 var1, Word16 var2); /* Long mult,           1   */
+PJ_INLINE(Word16) negate (Word16 var1);              /* Short negate,        1   */
+PJ_INLINE(Word16) extract_h (Word32 L_var1);         /* Extract high,        1   */
+PJ_INLINE(Word16) extract_l (Word32 L_var1);         /* Extract low,         1   */
+PJ_INLINE(Word16) itu_round (Word32 L_var1);         /* Round,               1   */
+PJ_INLINE(Word32) L_mac (Word32 L_var3, Word16 var1, Word16 var2);   /* Mac,  1  */
+LIBG7221_DECL(Word32) L_msu (Word32 L_var3, Word16 var1, Word16 var2);   /* Msu,  1  */
+LIBG7221_DECL(Word32) L_macNs (Word32 L_var3, Word16 var1, Word16 var2); /* Mac without
+								       sat, 1   */
+LIBG7221_DECL(Word32) L_msuNs (Word32 L_var3, Word16 var1, Word16 var2); /* Msu without
+								       sat, 1   */
+//PJ_INLINE(Word32) L_add (Word32 L_var1, Word32 L_var2);    /* Long add,        2 */
+PJ_INLINE(Word32) L_sub (Word32 L_var1, Word32 L_var2);    /* Long sub,        2 */
+LIBG7221_DECL(Word32) L_add_c (Word32 L_var1, Word32 L_var2);  /* Long add with c, 2 */
+LIBG7221_DECL(Word32) L_sub_c (Word32 L_var1, Word32 L_var2);  /* Long sub with c, 2 */
+LIBG7221_DECL(Word32) L_negate (Word32 L_var1);                /* Long negate,     2 */
+LIBG7221_DECL(Word16) mult_r (Word16 var1, Word16 var2);       /* Mult with round, 2 */
+PJ_INLINE(Word32) L_shl (Word32 L_var1, Word16 var2);      /* Long shift left, 2 */
+PJ_INLINE(Word32) L_shr (Word32 L_var1, Word16 var2);      /* Long shift right, 2*/
+LIBG7221_DECL(Word16) shr_r (Word16 var1, Word16 var2);        /* Shift right with
+							     round, 2           */
+LIBG7221_DECL(Word16) mac_r (Word32 L_var3, Word16 var1, Word16 var2); /* Mac with
+                                                           rounding,2 */
+LIBG7221_DECL(Word16) msu_r (Word32 L_var3, Word16 var1, Word16 var2); /* Msu with
+                                                           rounding,2 */
+LIBG7221_DECL(Word32) L_deposit_h (Word16 var1);        /* 16 bit var1 -> MSB,     2 */
+LIBG7221_DECL(Word32) L_deposit_l (Word16 var1);        /* 16 bit var1 -> LSB,     2 */
+
+LIBG7221_DECL(Word32) L_shr_r (Word32 L_var1, Word16 var2); /* Long shift right with
+							  round,  3             */
+LIBG7221_DECL(Word32) L_abs (Word32 L_var1);            /* Long abs,              3  */
+LIBG7221_DECL(Word32) L_sat (Word32 L_var1);            /* Long saturation,       4  */
+LIBG7221_DECL(Word16) norm_s (Word16 var1);             /* Short norm,           15  */
+LIBG7221_DECL(Word16) div_s (Word16 var1, Word16 var2); /* Short division,       18  */
+LIBG7221_DECL(Word16) norm_l (Word32 L_var1);           /* Long norm,            30  */   
+
+/*
+   Additional G.723.1 operators
+*/
+LIBG7221_DECL(Word32) L_mls( Word32, Word16 ) ;    /* Weight FFS; currently assigned 1 */
+LIBG7221_DECL(Word16) div_l( Word32, Word16 ) ;    /* Weight FFS; currently assigned 1 */
+LIBG7221_DECL(Word16) i_mult(Word16 a, Word16 b);  /* Weight FFS; currently assigned 1 */
+
+/* 
+    New shiftless operators, not used in G.729/G.723.1
+*/
+LIBG7221_DECL(Word32) L_mult0(Word16 v1, Word16 v2); /* 32-bit Multiply w/o shift         1 */
+LIBG7221_DECL(Word32) L_mac0(Word32 L_v3, Word16 v1, Word16 v2); /* 32-bit Mac w/o shift  1 */
+LIBG7221_DECL(Word32) L_msu0(Word32 L_v3, Word16 v1, Word16 v2); /* 32-bit Msu w/o shift  1 */
+
+/* 
+    Additional G.722.1 operators
+*/
+LIBG7221_DECL(UWord32) LU_shl (UWord32 L_var1, Word16 var2);
+LIBG7221_DECL(UWord32) LU_shr (UWord32 L_var1, Word16 var2);
+
+#define INCLUDE_UNSAFE	    0
+
+/* Local */
+PJ_INLINE(Word16) saturate (Word32 L_var1);
+
+#if INCLUDE_UNSAFE
+    extern Flag g7221_Overflow;
+    extern Flag g7221_Carry;
+#   define SET_OVERFLOW(n)  g7221_Overflow = n
+#   define SET_CARRY(n)	    g7221_Carry = n
+
+#else
+#   define SET_OVERFLOW(n)
+#   define SET_CARRY(n)
+#   define GET_OVERFLOW()   0
+#   define GET_CARRY()	    0
+#endif
+
+#include "basic_op_i.h"
+
+#if PJMEDIA_LIBG7221_FUNCS_INLINED
+#   include "basic_op.c"
+#endif
+
+#endif /* __BASIC_OP_H__ */
+
+
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/common/basic_op_i.h b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/common/basic_op_i.h
new file mode 100644
index 0000000..d690623
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/common/basic_op_i.h
@@ -0,0 +1,730 @@
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : extract_h                                               |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Return the 16 MSB of L_var1.                                            |
+ |                                                                           |
+ |   Complexity weight : 1                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    L_var1                                                                 |
+ |             32 bit long signed integer (Word32 ) whose value falls in the |
+ |             range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    var_out                                                                |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var_out <= 0x0000 7fff.                |
+ |___________________________________________________________________________|
+*/
+PJ_INLINE(Word16) extract_h (Word32 L_var1)
+{
+    return (Word16) (L_var1 >> 16);
+}
+/* ------------------------- End of extract_h() ------------------------- */
+
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : extract_l                                               |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Return the 16 LSB of L_var1.                                            |
+ |                                                                           |
+ |   Complexity weight : 1                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    L_var1                                                                 |
+ |             32 bit long signed integer (Word32 ) whose value falls in the |
+ |             range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    var_out                                                                |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var_out <= 0x0000 7fff.                |
+ |___________________________________________________________________________|
+*/
+PJ_INLINE(Word16) extract_l (Word32 L_var1)
+{
+    return (Word16) L_var1;
+}
+
+/* ------------------------- End of extract_l() ------------------------- */
+
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : saturate                                                |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |    Limit the 32 bit input to the range of a 16 bit word.                  |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    L_var1                                                                 |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    var_out                                                                |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var_out <= 0x0000 7fff.                |
+ |___________________________________________________________________________|
+*/
+PJ_INLINE(Word16) saturate (Word32 L_var1)
+{
+    Word16 val16 = (Word16) L_var1;
+
+    if (val16 == L_var1)
+	return val16;
+
+    if (L_var1 > MAX_16)
+        return MAX_16;
+    return MIN_16;
+}
+/* ------------------------- End of saturate() ------------------------- */
+
+
+#if PJ_HAS_INT64
+PJ_INLINE(Word32) L_saturate (pj_int64_t LL_var1)
+{
+    pj_int32_t L_var1 = (pj_int32_t)LL_var1;
+    if (LL_var1 == L_var1)
+	return L_var1;
+    else if (LL_var1 > MAX_32)
+	return MAX_32;
+    else
+	return MIN_32;
+}
+#endif
+
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : add                                                     |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |    Performs the addition (var1+var2) with overflow control and saturation;|
+ |    the 16 bit result is set at +32767 when overflow occurs or at -32768   |
+ |    when underflow occurs.                                                 |
+ |                                                                           |
+ |   Complexity weight : 1                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    var1                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |    var2                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    var_out                                                                |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var_out <= 0x0000 7fff.                |
+ |___________________________________________________________________________|
+*/
+PJ_INLINE(Word16) add (Word16 var1, Word16 var2)
+{
+    return saturate (var1 + var2);
+}
+/* ------------------------- End of add() ------------------------- */
+
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : sub                                                     |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |    Performs the subtraction (var1+var2) with overflow control and satu-   |
+ |    ration; the 16 bit result is set at +32767 when overflow occurs or at  |
+ |    -32768 when underflow occurs.                                          |
+ |                                                                           |
+ |   Complexity weight : 1                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    var1                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |    var2                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    var_out                                                                |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var_out <= 0x0000 7fff.                |
+ |___________________________________________________________________________|
+*/
+PJ_INLINE(Word16) sub (Word16 var1, Word16 var2)
+{
+    return saturate ((Word32) var1 - var2);
+}
+/* ------------------------- End of sub() ------------------------- */
+
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : negate                                                  |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Negate var1 with saturation, saturate in the case where input is -32768:|
+ |                negate(var1) = sub(0,var1).                                |
+ |                                                                           |
+ |   Complexity weight : 1                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    var1                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    var_out                                                                |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var_out <= 0x0000 7fff.                |
+ |___________________________________________________________________________|
+*/
+PJ_INLINE(Word16) negate (Word16 var1)
+{
+    return (Word16)((var1 == MIN_16) ? MAX_16 : -var1);
+}
+/* ------------------------- End of negate() ------------------------- */
+
+
+
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : L_add                                                   |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   32 bits addition of the two 32 bits variables (L_var1+L_var2) with      |
+ |   overflow control and saturation; the result is set at +2147483647 when  |
+ |   overflow occurs or at -2147483648 when underflow occurs.                |
+ |                                                                           |
+ |   Complexity weight : 2                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    L_var1   32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |    L_var2   32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    L_var_out                                                              |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.              |
+ |___________________________________________________________________________|
+*/
+PJ_INLINE(Word32) L_add (Word32 L_var1, Word32 L_var2)
+{
+#if PJ_HAS_INT64
+    return L_saturate(((pj_int64_t)L_var1) + L_var2);
+#else
+    Word32 L_var_out;
+
+    L_var_out = L_var1 + L_var2;
+
+    if (((L_var1 ^ L_var2) & MIN_32) == 0)
+    {
+        if ((L_var_out ^ L_var1) & MIN_32)
+        {
+            SET_OVERFLOW(1);
+            L_var_out = (L_var1 < 0) ? MIN_32 : MAX_32;
+        }
+    }
+    return (L_var_out);
+#endif
+}
+
+/* ------------------------- End of L_add() ------------------------- */
+
+
+
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : L_sub                                                   |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   32 bits subtraction of the two 32 bits variables (L_var1-L_var2) with   |
+ |   overflow control and saturation; the result is set at +2147483647 when  |
+ |   overflow occurs or at -2147483648 when underflow occurs.                |
+ |                                                                           |
+ |   Complexity weight : 2                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    L_var1   32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |    L_var2   32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    L_var_out                                                              |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.              |
+ |___________________________________________________________________________|
+*/
+PJ_INLINE(Word32) L_sub (Word32 L_var1, Word32 L_var2)
+{
+#if PJ_HAS_INT64
+    return L_saturate((pj_int64_t)L_var1 - L_var2);
+#else
+    Word32 L_var_out;
+
+    L_var_out = L_var1 - L_var2;
+
+    if (((L_var1 ^ L_var2) & MIN_32) != 0)
+    {
+        if ((L_var_out ^ L_var1) & MIN_32)
+        {
+            L_var_out = (L_var1 < 0L) ? MIN_32 : MAX_32;
+            SET_OVERFLOW(1);
+        }
+    }
+    return (L_var_out);
+#endif
+}
+/* ------------------------- End of L_sub() ------------------------- */
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : L_mult                                                  |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   L_mult is the 32 bit result of the multiplication of var1 times var2    |
+ |   with one shift left i.e.:                                               |
+ |        L_mult(var1,var2) = L_shl((var1 times var2),1) and                 |
+ |        L_mult(-32768,-32768) = 2147483647.                                |
+ |                                                                           |
+ |   Complexity weight : 1                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    var1                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |    var2                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    L_var_out                                                              |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.              |
+ |___________________________________________________________________________|
+*/
+PJ_INLINE(Word32) L_mult (Word16 var1, Word16 var2)
+{
+    Word32 L_var_out;
+
+    L_var_out = (Word32) var1 *(Word32) var2;
+
+    if (L_var_out != (Word32) 0x40000000L)
+    {
+        return L_var_out << 1;
+    }
+    else
+    {
+        SET_OVERFLOW(1);
+        return MAX_32;
+    }
+}
+/* ------------------------- End of L_mult() ------------------------- */
+
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : L_mac                                                   |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Multiply var1 by var2 and shift the result left by 1. Add the 32 bit    |
+ |   result to L_var3 with saturation, return a 32 bit result:               |
+ |        L_mac(L_var3,var1,var2) = L_add(L_var3,L_mult(var1,var2)).         |
+ |                                                                           |
+ |   Complexity weight : 1                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    L_var3   32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |    var1                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |    var2                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    L_var_out                                                              |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.              |
+ |___________________________________________________________________________|
+*/
+PJ_INLINE(Word32) L_mac (Word32 L_var3, Word16 var1, Word16 var2)
+{
+    return L_add (L_var3, L_mult (var1, var2));
+}
+/* ------------------------- End of L_mac() ------------------------- */
+
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : round                                                   |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Round the lower 16 bits of the 32 bit input number into the MS 16 bits  |
+ |   with saturation. Shift the resulting bits right by 16 and return the 16 |
+ |   bit number:                                                             |
+ |               round(L_var1) = extract_h(L_add(L_var1,32768))              |
+ |                                                                           |
+ |   Complexity weight : 1                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    L_var1                                                                 |
+ |             32 bit long signed integer (Word32 ) whose value falls in the |
+ |             range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    var_out                                                                |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var_out <= 0x0000 7fff.                |
+ |___________________________________________________________________________|
+*/
+PJ_INLINE(Word16) itu_round (Word32 L_var1)
+{
+    return extract_h (L_add (L_var1, (Word32) 0x00008000L));
+}
+/* ------------------------- End of round() ------------------------- */
+
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : L_shr                                                   |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Arithmetically shift the 32 bit input L_var1 right var2 positions with  |
+ |   sign extension. If var2 is negative, arithmetically shift L_var1 left   |
+ |   by -var2 and zero fill the -var2 LSB of the result. Saturate the result |
+ |   in case of underflows or overflows.                                     |
+ |                                                                           |
+ |   Complexity weight : 2                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    L_var1   32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |    var2                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    L_var_out                                                              |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.              |
+ |___________________________________________________________________________|
+*/
+PJ_INLINE(Word32) L_shr_nocheck(Word32 L_var1, Word16 var2)
+{
+#if 1
+    return L_var1 >> var2;
+#else
+    if (var2 >= 31)
+    {
+        return (L_var1 < 0L) ? -1 : 0;
+    }
+    else
+    {
+        if (L_var1 < 0)
+        {
+            return ~((~L_var1) >> var2);
+        }
+        else
+        {
+            return L_var1 >> var2;
+        }
+    }
+#endif
+}
+
+PJ_INLINE(Word32) L_shl_nocheck (Word32 L_var1, Word16 var2)
+{
+#if PJ_HAS_INT64
+    return L_saturate( ((pj_int64_t)L_var1) << var2 );
+#else
+    for (; var2 > 0; var2--)
+    {
+        if (L_var1 > (Word32) 0X3fffffffL)
+        {
+            SET_OVERFLOW(1);
+            return MAX_32;
+        }
+        else
+        {
+            if (L_var1 < (Word32) 0xc0000000L)
+            {
+                SET_OVERFLOW(1);
+                return MIN_32;
+            }
+        }
+        L_var1 <<= 1;
+    }
+    return (L_var1);
+#endif
+}
+
+PJ_INLINE(Word32) L_shr (Word32 L_var1, Word16 var2)
+{
+    if (var2 < 0)
+    {
+        if (var2 < -32)
+            var2 = -32;
+        return L_shl_nocheck (L_var1, (Word16) -var2);
+    }
+    else
+    {
+	return L_shr_nocheck(L_var1, var2);
+    }
+}
+/* ------------------------- End of L_shr() ------------------------- */
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : L_shl                                                   |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |   Arithmetically shift the 32 bit input L_var1 left var2 positions. Zero  |
+ |   fill the var2 LSB of the result. If var2 is negative, arithmetically    |
+ |   shift L_var1 right by -var2 with sign extension. Saturate the result in |
+ |   case of underflows or overflows.                                        |
+ |                                                                           |
+ |   Complexity weight : 2                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    L_var1   32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |
+ |                                                                           |
+ |    var2                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    L_var_out                                                              |
+ |             32 bit long signed integer (Word32) whose value falls in the  |
+ |             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.              |
+ |___________________________________________________________________________|
+*/
+PJ_INLINE(Word32) L_shl (Word32 L_var1, Word16 var2)
+{
+    if (var2 <= 0)
+    {
+        if (var2 < -32)
+            var2 = -32;
+        return L_shr_nocheck(L_var1, (Word16) -var2);
+    }
+    else
+    {
+	return L_shl_nocheck(L_var1, var2);
+    }
+}
+/* ------------------------- End of L_shl() ------------------------- */
+
+
+/*___________________________________________________________________________
+ |                                                                           |
+ |   Function Name : abs_s                                                   |
+ |                                                                           |
+ |   Purpose :                                                               |
+ |                                                                           |
+ |    Absolute value of var1; abs_s(-32768) = 32767.                         |
+ |                                                                           |
+ |   Complexity weight : 1                                                   |
+ |                                                                           |
+ |   Inputs :                                                                |
+ |                                                                           |
+ |    var1                                                                   |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |
+ |                                                                           |
+ |   Outputs :                                                               |
+ |                                                                           |
+ |    none                                                                   |
+ |                                                                           |
+ |   Return Value :                                                          |
+ |                                                                           |
+ |    var_out                                                                |
+ |             16 bit short signed integer (Word16) whose value falls in the |
+ |             range : 0x0000 0000 <= var_out <= 0x0000 7fff.                |
+ |___________________________________________________________________________|
+*/
+PJ_INLINE(Word16) abs_s (Word16 var1)
+{
+#if 1
+    if (var1 >= 0)
+    	return var1;
+    else if (var1 == MIN_16)
+ 	return MAX_16;
+    else
+    	return (Word16)-var1;
+#else
+    if (var1 == MIN_16)
+    {
+        return MAX_16;
+    }
+    else
+    {
+        if (var1 < 0)
+        {
+            return (Word16)-var1;
+        }
+        else
+        {
+            return var1;
+        }
+    }
+#endif
+}
+/* ------------------------- End of abs_s() ------------------------- */
+
+
+PJ_INLINE(Word16) shl_nocheck(Word16 var1, Word16 var2)
+{
+#if 1
+    /* blp: this should be more optimized */
+    return saturate (((Word32)var1) << var2);
+#else
+    /* Original algorithm */
+    Word32 result = (Word32) var1 *((Word32) 1 << var2);
+
+    if ((var2 > 15 && var1 != 0) || (result != (Word32) ((Word16) result)))
+    {
+        SET_OVERFLOW(1);
+        return (Word16) ((var1 > 0) ? MAX_16 : MIN_16);
+    }
+    else
+    {
+        return extract_l (result);
+    }
+#endif
+}
+
+PJ_INLINE(Word16) shr_nocheck(Word16 var1, Word16 var2)
+{
+#if 1
+    /* blp: this should yield the same value */
+    return (Word16) (var1 >> var2);
+#else
+    /* Original algorithm */
+    if (var2 >= 15)
+    {
+        return (Word16)((var1 < 0) ? -1 : 0);
+    }
+    else
+    {
+        if (var1 < 0)
+        {
+            return (Word16) (~((~var1) >> var2));
+        }
+        else
+        {
+            return (Word16)(var1 >> var2);
+        }
+    }
+#endif
+}
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/common/common.c b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/common/common.c
new file mode 100644
index 0000000..d5eed81
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/common/common.c
@@ -0,0 +1,461 @@
+/****************************************************************************************
+**
+**   ITU-T G.722.1 (2005-05) - Fixed point implementation for main body and Annex C
+**   > Software Release 2.1 (2008-06)
+**     (Simple repackaging; no change from 2005-05 Release 2.0 code)
+**
+**   � 2004 Polycom, Inc.
+**
+**	 All rights reserved.
+**
+****************************************************************************************/
+
+/****************************************************************************************
+  Filename:    common.c    
+
+  Purpose:     Contains the functions used for both G.722.1 Annex C encoder and decoder
+		
+  Design Notes:
+
+****************************************************************************************/
+/****************************************************************************************
+ Include files                                                           
+****************************************************************************************/
+#include "defs.h"
+#include "huff_def.h"
+#include "huff_tab.h"
+#include "tables.h"
+#include "count.h"
+
+/****************************************************************************************
+ Function:    categorize
+
+ Syntax:      void categorize(Word16 number_of_available_bits,   
+                              Word16 number_of_regions,
+                              Word16 num_categorization_control_possibilities,
+                              Word16 rms_index,                  
+                              Word16 power_categories,           
+                              Word16 category_balances)          
+
+                  inputs:   number_of_regions
+                            num_categorization_control_possibilities
+                            number_of_available_bits
+                            rms_index[MAX_NUMBER_OF_REGIONS]                              
+                  
+                  outputs:  power_categories[MAX_NUMBER_OF_REGIONS]                       
+                            category_balances[MAX_NUM_CATEGORIZATION_CONTROL_POSSIBILITIES-1]
+
+ Description: Computes a series of categorizations 
+
+ WMOPS:     7kHz |    24kbit    |     32kbit
+          -------|--------------|----------------
+            AVG  |    0.14      |     0.14
+          -------|--------------|----------------  
+            MAX  |    0.15      |     0.15
+          -------|--------------|---------------- 
+   			
+           14kHz |    24kbit    |     32kbit     |     48kbit
+          -------|--------------|----------------|----------------
+            AVG  |    0.42      |     0.45       |     0.48   
+          -------|--------------|----------------|----------------
+            MAX  |    0.47      |     0.52       |     0.52   
+          -------|--------------|----------------|----------------
+
+****************************************************************************************/
+void categorize(Word16 number_of_available_bits,
+		        Word16 number_of_regions,
+		        Word16 num_categorization_control_possibilities,
+		        Word16 *rms_index,
+		        Word16 *power_categories,
+		        Word16 *category_balances)
+{
+    
+    Word16 offset;
+    Word16 temp;
+    Word16 frame_size;
+
+    /* At higher bit rates, there is an increase for most categories in average bit
+       consumption per region. We compensate for this by pretending we have fewer
+       available bits. */
+    test();
+    if (number_of_regions == NUMBER_OF_REGIONS)
+    {
+        frame_size = DCT_LENGTH;
+    }
+    else
+    {
+        frame_size = MAX_DCT_LENGTH;
+    }
+
+    temp = sub(number_of_available_bits,frame_size);
+    
+    test();
+    if (temp > 0)
+    {
+        number_of_available_bits = sub(number_of_available_bits,frame_size);
+        number_of_available_bits = extract_l(L_mult0(number_of_available_bits,5));
+        number_of_available_bits = shr_nocheck(number_of_available_bits,3);
+        number_of_available_bits = add(number_of_available_bits,frame_size);
+    }
+
+    /* calculate the offset using the original category assignments */
+    offset = calc_offset(rms_index,number_of_regions,number_of_available_bits);
+
+
+
+    /* compute the power categories based on the uniform offset */
+    compute_raw_pow_categories(power_categories,rms_index,number_of_regions,offset);
+    
+    
+    /* adjust the category assignments */
+    /* compute the new power categories and category balances */
+    comp_powercat_and_catbalance(power_categories,category_balances,rms_index,number_of_available_bits,number_of_regions,num_categorization_control_possibilities,offset);
+
+}
+    
+/***************************************************************************
+ Function:    comp_powercat_and_catbalance
+
+ Syntax:      void comp_powercat_and_catbalance(Word16 *power_categories,
+                                                Word16 *category_balances,
+                                                Word16 *rms_index,  
+                                                Word16 number_of_available_bits,                                  
+                                                Word16 number_of_regions,
+                                                Word16 num_categorization_control_possibilities,
+                                                Word16 offset)                                                    
+
+                
+                inputs:   *rms_index                              
+                          number_of_available_bits                 
+                          number_of_regions
+                          num_categorization_control_possibilities
+                          offset
+                           
+                outputs:  *power_categories  
+                          *category_balances 
+                
+                
+ Description: Computes the power_categories and the category balances
+
+ WMOPS:     7kHz |    24kbit    |     32kbit
+          -------|--------------|----------------
+            AVG  |    0.10      |     0.10
+          -------|--------------|----------------  
+            MAX  |    0.11      |     0.11
+          -------|--------------|---------------- 
+				
+           14kHz |    24kbit    |     32kbit     |     48kbit
+          -------|--------------|----------------|----------------
+            AVG  |    0.32      |     0.35       |     0.38   
+          -------|--------------|----------------|----------------
+            MAX  |    0.38      |     0.42       |     0.43   
+          -------|--------------|----------------|----------------
+
+***************************************************************************/
+void comp_powercat_and_catbalance(Word16 *power_categories,
+                                  Word16 *category_balances,
+                                  Word16 *rms_index,
+                                  Word16 number_of_available_bits,
+                                  Word16 number_of_regions,
+                                  Word16 num_categorization_control_possibilities,
+								  Word16 offset)
+{
+    
+    Word16 expected_number_of_code_bits;
+    Word16 region;
+    Word16 max_region;
+    Word16 j;
+    Word16 max_rate_categories[MAX_NUMBER_OF_REGIONS];
+    Word16 min_rate_categories[MAX_NUMBER_OF_REGIONS];
+    Word16 temp_category_balances[2*MAX_NUM_CATEGORIZATION_CONTROL_POSSIBILITIES];
+    Word16 raw_max, raw_min;
+    Word16 raw_max_index=0, raw_min_index=0;
+    Word16 max_rate_pointer, min_rate_pointer;
+    Word16 max, min;
+    Word16 itemp0;
+    Word16 itemp1;
+    Word16 min_plus_max;
+    Word16 two_x_number_of_available_bits;
+
+    Word16 temp;
+
+    expected_number_of_code_bits = 0;
+    move16();
+
+    for (region=0; region<number_of_regions; region++)
+        expected_number_of_code_bits = add(expected_number_of_code_bits,expected_bits_table[power_categories[region]]);
+
+
+    for (region=0; region<number_of_regions; region++) 
+    {
+        max_rate_categories[region] = power_categories[region];
+        move16();
+        
+        min_rate_categories[region] = power_categories[region];
+        move16();
+    }
+    
+    max = expected_number_of_code_bits;
+    move16();
+    min = expected_number_of_code_bits;
+    move16();
+    max_rate_pointer = num_categorization_control_possibilities;
+    move16();
+    min_rate_pointer = num_categorization_control_possibilities;
+    move16();
+    
+    for (j=0; j<num_categorization_control_possibilities-1; j++) 
+    {
+        min_plus_max = add(max,min);
+        two_x_number_of_available_bits = shl_nocheck(number_of_available_bits,1);
+        
+        temp = sub(min_plus_max,two_x_number_of_available_bits);
+        test();
+        if (temp <= 0) 
+        {
+            raw_min = 99;
+            move16();
+            /* Search from lowest freq regions to highest for best */
+            /* region to reassign to a higher bit rate category.   */
+            for (region=0; region<number_of_regions; region++) 
+            {
+                test();
+                if (max_rate_categories[region] > 0) 
+                {
+                    itemp0 = shl_nocheck(max_rate_categories[region],1);
+                    itemp1 = sub(offset,rms_index[region]);
+                    itemp0 = sub(itemp1,itemp0);
+                    
+                    temp = sub(itemp0,raw_min);
+                    test();
+                    if (temp < 0) 
+                    {
+                        raw_min = itemp0;
+                        raw_min_index = region;
+                    }
+                }
+            }
+            max_rate_pointer = sub(max_rate_pointer,1);
+            temp_category_balances[max_rate_pointer] = raw_min_index;
+            move16();
+
+        	max = sub(max,expected_bits_table[max_rate_categories[raw_min_index]]);
+        	max_rate_categories[raw_min_index] = sub(max_rate_categories[raw_min_index],1);
+        	move16();
+
+            max = add(max,expected_bits_table[max_rate_categories[raw_min_index]]);
+        }
+        else 
+        {
+            raw_max = -99;
+            move16();
+            /* Search from highest freq regions to lowest for best region to reassign to
+            a lower bit rate category. */
+            max_region = sub(number_of_regions,1);
+            for (region= max_region; region >= 0; region--) 
+            {
+                temp = sub(min_rate_categories[region],(NUM_CATEGORIES-1));
+                test();
+                if (temp < 0)
+                {
+                    itemp0 = shl_nocheck(min_rate_categories[region],1);
+                    itemp1 = sub(offset,rms_index[region]);
+                    itemp0 = sub(itemp1,itemp0);
+                    
+                    temp = sub(itemp0,raw_max);
+                    test();
+                    if (temp > 0) 
+                    {
+                        raw_max = itemp0;
+                        move16();
+                        raw_max_index = region;
+                        move16();
+                    }
+                }
+            }
+            temp_category_balances[min_rate_pointer] = raw_max_index;
+            move16();
+            
+            min_rate_pointer = add(min_rate_pointer,1);
+            min = sub(min,expected_bits_table[min_rate_categories[raw_max_index]]);
+            
+            min_rate_categories[raw_max_index] = add(min_rate_categories[raw_max_index],1);
+            move16();
+            
+            min = add(min,expected_bits_table[min_rate_categories[raw_max_index]]);
+        }
+    }
+    
+    for (region=0; region<number_of_regions; region++)
+    {
+        power_categories[region] = max_rate_categories[region];
+        move16();
+    }
+    
+    for (j=0; j<num_categorization_control_possibilities-1; j++)
+    {
+        category_balances[j] = temp_category_balances[max_rate_pointer++];
+        move16();
+    }
+
+}
+/***************************************************************************
+ Function:    calc_offset
+
+ Syntax:      offset=calc_offset(Word16 *rms_index,Word16 number_of_regions,Word16 available_bits)  
+
+                input:  Word16 *rms_index
+                        Word16 number_of_regions
+                        Word16 available_bits
+                        
+                output: Word16 offset                        
+
+ Description: Calculates the the category offset.  This is the shift required
+              To get the most out of the number of available bits.  A binary 
+              type search is used to find the offset.
+
+ WMOPS:     7kHz |    24kbit    |     32kbit
+          -------|--------------|----------------
+            AVG  |    0.04      |     0.04
+          -------|--------------|----------------  
+            MAX  |    0.04      |     0.04
+          -------|--------------|---------------- 
+
+           14kHz |    24kbit    |     32kbit     |     48kbit
+          -------|--------------|----------------|----------------
+            AVG  |    0.08      |     0.08       |     0.08   
+          -------|--------------|----------------|----------------
+            MAX  |    0.09      |     0.09       |     0.09   
+          -------|--------------|----------------|----------------
+
+***************************************************************************/
+Word16 calc_offset(Word16 *rms_index,Word16 number_of_regions,Word16 available_bits)    
+{
+
+    Word16 answer;
+    Word16 delta;
+    Word16 test_offset;
+    Word16 region,j;
+    Word16 power_cats[MAX_NUMBER_OF_REGIONS];
+    Word16 bits;
+    Word16 offset;
+    Word16 temp;
+
+    /* initialize vars */
+    answer = -32;
+    move16();
+    delta = 32;
+    move16();
+    
+    do 
+    {
+        test_offset = add(answer,delta);
+        
+        /* obtain a category for each region */
+        /* using the test offset             */
+        for (region=0; region<number_of_regions; region++) 
+        {
+            j = sub(test_offset,rms_index[region]);
+            j = shr_nocheck(j,1);
+            
+            /* Ensure j is between 0 and NUM_CAT-1 */
+            test();
+            if (j < 0) 
+            {
+                j = 0;
+                move16();
+            }
+            temp = sub(j,NUM_CATEGORIES-1);
+            test();
+            if (temp > 0) 
+            {
+                j = sub(NUM_CATEGORIES,1);
+                move16();
+            }
+            power_cats[region] = j;
+            move16();
+        }
+        bits = 0;
+        move16();
+
+        /* compute the number of bits that will be used given the cat assignments */
+        for (region=0; region<number_of_regions; region++)
+            bits = add(bits,expected_bits_table[power_cats[region]]);
+
+        /* if (bits > available_bits - 32) then divide the offset region for the bin search */
+        offset = sub(available_bits,32);
+        temp = sub(bits,offset);
+        test();
+        if (temp >= 0)
+        {
+            answer = test_offset;
+            move16();
+        }
+        delta = shr_nocheck(delta,1);
+        test(); /* for the while loop */
+    } while (delta > 0);
+
+    return(answer);
+}
+/***************************************************************************
+ Function:    compute_raw_pow_categories
+
+ Syntax:      void compute_raw_pow_categories(Word16 *power_categories,
+                                              Word16 *rms_index,
+                                              Word16 number_of_regions,
+                                              Word16 offset)
+              inputs:  *rms_index
+                       number_of_regions
+                       offset
+                    
+              outputs: *power_categories                    
+
+
+
+ Description: This function computes the power categories given the offset
+              This is kind of redundant since they were already computed
+              in calc_offset to determine the offset.
+
+ WMOPS:          |    24kbit    |     32kbit
+          -------|--------------|----------------
+            AVG  |    0.01      |     0.01
+          -------|--------------|----------------  
+            MAX  |    0.01      |     0.01
+          -------|--------------|---------------- 
+
+           14kHz |    24kbit    |     32kbit     |     48kbit
+          -------|--------------|----------------|----------------
+            AVG  |    0.01      |     0.01       |     0.01   
+          -------|--------------|----------------|----------------
+            MAX  |    0.01      |     0.01       |     0.01   
+          -------|--------------|----------------|----------------
+
+***************************************************************************/
+void compute_raw_pow_categories(Word16 *power_categories,Word16 *rms_index,Word16 number_of_regions,Word16 offset)
+{
+    Word16 region;
+    Word16 j;
+    Word16 temp;
+
+    for (region=0; region<number_of_regions; region++) 
+    {
+        j = sub(offset,rms_index[region]);
+        j = shr_nocheck(j,1);
+        
+        /* make sure j is between 0 and NUM_CAT-1 */
+        test();
+        if (j < 0) 
+        {
+            j = 0;
+            move16();
+        }
+        temp = sub(j,(NUM_CATEGORIES-1));
+        test();
+        if (temp > 0) 
+            j = sub(NUM_CATEGORIES,1);
+        
+        power_categories[region] = j;
+        move16();
+    }
+}
+
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/common/config.h b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/common/config.h
new file mode 100644
index 0000000..4faec78
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/common/config.h
@@ -0,0 +1,27 @@
+#ifndef __LIBG7221_CONFIG_H__
+#define __LIBG7221_CONFIG_H__
+
+#include <pj/config.h>
+
+/**
+ * Expand all basic operation functions as inline. Even if this is set to
+ * zero, some critical functions would still be expanded as inline. Note
+ * also that enabling this may generate some warning messages about functions
+ * not being referenced (with gcc).
+ *
+ * Default: 0 (no)
+ */
+#ifndef PJMEDIA_LIBG7221_FUNCS_INLINED
+#   define PJMEDIA_LIBG7221_FUNCS_INLINED   0
+#endif
+
+/* Declare/define a function that may be expanded as inline. */
+#if PJMEDIA_LIBG7221_FUNCS_INLINED
+#  define LIBG7221_DECL(type)  PJ_INLINE(type)
+#  define LIBG7221_DEF(type)   PJ_INLINE(type)
+#else
+#  define LIBG7221_DECL(type)  PJ_DECL(type)
+#  define LIBG7221_DEF(type)   PJ_DEF(type)
+#endif
+
+#endif /* __LIBG7221_CONFIG_H__ */
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/common/count.h b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/common/count.h
new file mode 100644
index 0000000..0ead727
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/common/count.h
@@ -0,0 +1,28 @@
+/* $Id: count.h 2623 2009-04-20 18:38:15Z bennylp $ */
+/* 
+ * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#ifndef COUNT_H
+#define COUNT_H
+
+#define move16()
+#define move32()
+#define logic16()
+#define logic32()
+#define test()
+
+#endif
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/common/defs.h b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/common/defs.h
new file mode 100644
index 0000000..d4c7aa2
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/common/defs.h
@@ -0,0 +1,205 @@
+/***********************************************************************
+**
+**   ITU-T G.722.1 (2005-05) - Fixed point implementation for main body and Annex C
+**   > Software Release 2.1 (2008-06)
+**     (Simple repackaging; no change from 2005-05 Release 2.0 code)
+**
+**   � 2004 Polycom, Inc.
+**
+**   All rights reserved.
+**
+***********************************************************************/
+
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+#include "g7221/common/typedef.h"
+#include "g7221/common/basic_op.h"
+
+#define  PI             3.141592653589793238462
+
+#define MAX_DCT_LENGTH      640
+#define DCT_LENGTH          320
+#define DCT_LENGTH_DIV_2    160
+#define DCT_LENGTH_DIV_4     80
+#define DCT_LENGTH_DIV_8     40
+#define DCT_LENGTH_DIV_16    20
+#define DCT_LENGTH_DIV_32    10
+#define DCT_LENGTH_DIV_64     5
+
+
+#define MAX(a,b) (a > b ? a : b)
+#define MIN(a,b) (a < b ? a : b)
+
+#define NUM_CATEGORIES                  8
+#define NUM_CATEGORIZATION_CONTROL_BITS           4
+#define NUM_CATEGORIZATION_CONTROL_POSSIBILITIES  16
+#define CORE_SIZE       10
+#define DCT_LENGTH_LOG  6
+#define MAX_DCT_LENGTH_LOG  7
+
+/*  region_size = (BLOCK_SIZE * 0.875)/NUM_REGIONS; */
+#define NUMBER_OF_REGIONS       14
+#define MAX_NUMBER_OF_REGIONS   28
+#define REGION_SIZE             20
+#define NUMBER_OF_VALID_COEFS   (NUMBER_OF_REGIONS * REGION_SIZE)
+#define MAX_NUMBER_OF_VALID_COEFS   (MAX_NUMBER_OF_REGIONS * REGION_SIZE)
+
+#define REGION_POWER_TABLE_SIZE 64
+#define REGION_POWER_TABLE_NUM_NEGATIVES 24
+
+#define MAX_NUM_CATEGORIZATION_CONTROL_BITS 5
+#define MAX_NUM_CATEGORIZATION_CONTROL_POSSIBILITIES 32
+
+#define ENCODER_SCALE_FACTOR 18318.0
+
+/* The MLT output is incorrectly scaled by the factor
+   product of ENCODER_SCALE_FACTOR and sqrt(160.)
+   This is now (9/30/96) 1.0/2^(4.5) or 1/22.627.
+   In the current implementation this  
+   must be an integer power of sqrt(2). The
+   integer power is ESF_ADJUSTMENT_TO_RMS_INDEX.
+   The -2 is to conform with the range defined in the spec. */
+
+ 
+#define ESF_ADJUSTMENT_TO_RMS_INDEX (9-2)
+ 
+
+#define INTERMEDIATE_FILES_FLAG 0
+
+/* Max bit rate is 48000 bits/sec. */
+#define MAX_BITS_PER_FRAME 960
+
+
+/***************************************************************************/
+/* Type definitions                                                        */
+/***************************************************************************/
+typedef struct
+{
+    Word16 code_bit_count;      /* bit count of the current word */
+    Word16 current_word;        /* current word in the bitstream being processed */
+    Word16 *code_word_ptr;      /* pointer to the bitstream */
+    Word16 number_of_bits_left; /* number of bits left in the current word */
+    Word16 next_bit;            /* next bit in the current word */
+}Bit_Obj;
+
+typedef struct
+{
+    Word16 seed0;
+    Word16 seed1;
+    Word16 seed2;
+    Word16 seed3;
+}Rand_Obj;
+
+/***************************************************************************/
+/* Function definitions                                                    */
+/***************************************************************************/
+extern Word16  compute_region_powers(Word16  *mlt_coefs,
+                             Word16  mag_shift,
+                             Word16  *drp_num_bits,
+                             UWord16 *drp_code_bits,
+                             Word16  *absolute_region_power_index,
+                             Word16  number_of_regions);
+
+void    vector_quantize_mlts(Word16 number_of_available_bits,
+                          Word16 number_of_regions,
+                          Word16 num_categorization_control_possibilities,
+                          Word16 *mlt_coefs,
+                          Word16 *absolute_region_power_index,
+                          Word16 *power_categories,
+                          Word16 *category_balances,
+                          Word16 *p_categorization_control,
+                          Word16 *region_mlt_bit_counts,
+                          UWord32 *region_mlt_bits);
+
+Word16  vector_huffman(Word16 category,
+                      Word16 power_index,
+                      Word16 *raw_mlt_ptr,
+                      UWord32 *word_ptr);
+
+
+void    adjust_abs_region_power_index(Word16 *absolute_region_power_index,Word16 *mlt_coefs,Word16 number_of_regions);
+
+void    bits_to_words(UWord32 *region_mlt_bits,Word16 *region_mlt_bit_counts,
+                      Word16 *drp_num_bits,UWord16 *drp_code_bits,Word16 *out_words,
+                      Word16 categorization_control, Word16  number_of_regions,
+                      Word16  num_categorization_control_bits, Word16 number_of_bits_per_frame);
+
+void    encoder(Word16  number_of_available_bits,
+                Word16  number_of_regions,
+                Word16  *mlt_coefs,
+                Word16  mag_shift,
+                Word16  *out_words);
+
+void decoder(Bit_Obj *bitobj,
+    	     Rand_Obj *randobj,
+             Word16 number_of_regions,
+             Word16 *decoder_mlt_coefs,
+	         Word16 *p_mag_shift,
+	         Word16 *p_old_mag_shift,
+	         Word16 *old_decoder_mlt_coefs,
+	         Word16 frame_error_flag);
+
+Word16  samples_to_rmlt_coefs(const Word16 *new_samples,Word16 *history,Word16 *coefs,Word16 dct_length);
+void rmlt_coefs_to_samples(Word16 *coefs,     
+                           Word16 *old_samples,           
+                           Word16 *out_samples,           
+                           Word16 dct_length,           
+                           Word16 mag_shift);
+
+Word16  index_to_array(Word16 index,Word16 *array,Word16 category);
+void    categorize(Word16 number_of_available_bits,
+                   Word16 number_of_regions,
+				   Word16 num_categorization_control_possibilities,
+		           Word16 *rms_index,
+		           Word16 *power_categories,
+		           Word16 *category_balances);
+
+Word16 calc_offset(Word16 *rms_index,Word16 number_of_regions,Word16 available_bits);    
+void   compute_raw_pow_categories(Word16 *power_categories,Word16 *rms_index,Word16 number_of_regions,Word16 offset);
+void   comp_powercat_and_catbalance(Word16 *power_categories,
+                                    Word16 *category_balances,
+                                    Word16 *rms_index,
+                                    Word16 number_of_available_bits,
+                                    Word16 number_of_regions,
+                                    Word16 num_categorization_control_possibilities,
+                                    Word16 offset);
+ 
+void dct_type_iv_a (Word16 *input,Word16 *output,Word16 dct_length);
+void dct_type_iv_s(Word16 *input,Word16 *output,Word16 dct_length);
+void decode_envelope(Bit_Obj *bitobj,
+                     Word16  number_of_regions,
+                     Word16  *decoder_region_standard_deviation,
+		             Word16  *absolute_region_power_index,
+		             Word16  *p_mag_shift);
+
+void decode_vector_quantized_mlt_indices(Bit_Obj  *bitobj,
+                                         Rand_Obj *randobj,
+                                         Word16   number_of_regions,
+                                         Word16   *decoder_region_standard_deviation,
+					                     Word16   *dedecoder_power_categories,
+					                     Word16   *dedecoder_mlt_coefs);
+
+void rate_adjust_categories(Word16 categorization_control,
+			                Word16 *decoder_power_categories,
+			                Word16 *decoder_category_balances);
+
+void get_next_bit(Bit_Obj *bitobj);
+Word16 get_rand(Rand_Obj *randobj);
+
+void test_4_frame_errors(Bit_Obj *bitobj,
+                         Word16 number_of_regions,
+                         Word16 num_categorization_control_possibilities,
+                         Word16 *frame_error_flag,
+                         Word16 categorization_control,
+                         Word16 *absolute_region_power_index);
+
+void error_handling(Word16 number_of_coefs,
+                    Word16 number_of_valid_coefs,
+                    Word16 *frame_error_flag,
+                    Word16 *decoder_mlt_coefs,
+                    Word16 *old_decoder_mlt_coefs,
+                    Word16 *p_mag_shift,
+                    Word16 *p_old_mag_shift);
+
+
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/common/huff_def.h b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/common/huff_def.h
new file mode 100644
index 0000000..dd10d9a
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/common/huff_def.h
@@ -0,0 +1,53 @@
+/***********************************************************************
+**
+**   ITU-T G.722.1 (2005-05) - Fixed point implementation for main body and Annex C
+**   > Software Release 2.1 (2008-06)
+**     (Simple repackaging; no change from 2005-05 Release 2.0 code)
+**
+**   � 2004 Polycom, Inc.
+**
+**   All rights reserved.
+**
+***********************************************************************/
+
+#define REGION_POWER_STEPSIZE_DB 3.010299957
+#define ABS_REGION_POWER_LEVELS  32
+#define DIFF_REGION_POWER_LEVELS 24
+
+#define DRP_DIFF_MIN -12
+#define DRP_DIFF_MAX 11
+
+#define MAX_NUM_BINS 16
+#define MAX_VECTOR_INDICES 625
+#define MAX_VECTOR_DIMENSION 5
+
+extern Word16  differential_region_power_bits[MAX_NUMBER_OF_REGIONS][DIFF_REGION_POWER_LEVELS];
+extern UWord16 differential_region_power_codes[MAX_NUMBER_OF_REGIONS][DIFF_REGION_POWER_LEVELS];
+extern Word16  differential_region_power_decoder_tree[MAX_NUMBER_OF_REGIONS][DIFF_REGION_POWER_LEVELS-1][2];
+extern Word16  mlt_quant_centroid[NUM_CATEGORIES][MAX_NUM_BINS];
+extern Word16  expected_bits_table[NUM_CATEGORIES];
+extern Word16  mlt_sqvh_bitcount_category_0[196];
+extern UWord16 mlt_sqvh_code_category_0[196];
+extern Word16  mlt_sqvh_bitcount_category_1[100];
+extern UWord16 mlt_sqvh_code_category_1[100];
+extern Word16  mlt_sqvh_bitcount_category_2[49];
+extern UWord16 mlt_sqvh_code_category_2[49];
+extern Word16  mlt_sqvh_bitcount_category_3[625];
+extern UWord16 mlt_sqvh_code_category_3[625];
+extern Word16  mlt_sqvh_bitcount_category_4[256];
+extern UWord16 mlt_sqvh_code_category_4[256];
+extern Word16  mlt_sqvh_bitcount_category_5[243];
+extern UWord16 mlt_sqvh_code_category_5[243];
+extern Word16  mlt_sqvh_bitcount_category_6[32];
+extern UWord16 mlt_sqvh_code_category_6[32];
+extern Word16  *table_of_bitcount_tables[NUM_CATEGORIES-1];
+extern UWord16 *table_of_code_tables[NUM_CATEGORIES-1];
+extern Word16  mlt_decoder_tree_category_0[180][2];
+extern Word16  mlt_decoder_tree_category_1[93][2];
+extern Word16  mlt_decoder_tree_category_2[47][2];
+extern Word16  mlt_decoder_tree_category_3[519][2];
+extern Word16  mlt_decoder_tree_category_4[208][2];
+extern Word16  mlt_decoder_tree_category_5[191][2];
+extern Word16  mlt_decoder_tree_category_6[31][2];
+extern Word16  *table_of_decoder_tables[NUM_CATEGORIES-1];
+
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/common/huff_tab.c b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/common/huff_tab.c
new file mode 100644
index 0000000..12ff661
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/common/huff_tab.c
@@ -0,0 +1,528 @@
+/***********************************************************************
+**
+**   ITU-T G.722.1 (2005-05) - Fixed point implementation for main body and Annex C
+**   > Software Release 2.1 (2008-06)
+**     (Simple repackaging; no change from 2005-05 Release 2.0 code)
+**
+**   � 2004 Polycom, Inc.
+**
+**   All rights reserved.
+**
+***********************************************************************/
+#include "defs.h"
+#include "huff_def.h"
+
+Word16 differential_region_power_bits[MAX_NUMBER_OF_REGIONS][DIFF_REGION_POWER_LEVELS] = {
+{99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99},
+{ 4, 6, 5, 5, 4, 4, 4, 4, 4, 4, 3, 3, 3, 4, 5, 7, 8, 9,11,11,12,12,12,12},
+{10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 3, 3, 4, 5, 7, 9,11,12,13,15,15,15,16,16},
+{12,10, 8, 6, 5, 4, 4, 4, 4, 4, 4, 3, 3, 3, 4, 4, 5, 5, 7, 9,11,13,14,14},
+{13,10, 9, 9, 7, 7, 5, 5, 4, 3, 3, 3, 3, 3, 4, 4, 4, 5, 7, 9,11,13,13,13},
+{12,13,10, 8, 6, 6, 5, 5, 4, 4, 3, 3, 3, 3, 3, 4, 5, 5, 6, 7, 9,11,14,14},
+{12,11, 9, 8, 8, 7, 5, 4, 4, 3, 3, 3, 3, 3, 4, 4, 5, 5, 7, 8,10,13,14,14},
+{15,16,15,12,10, 8, 6, 5, 4, 3, 3, 3, 2, 3, 4, 5, 5, 7, 9,11,13,16,16,16},
+{14,14,11,10, 9, 7, 7, 5, 5, 4, 3, 3, 2, 3, 3, 4, 5, 7, 9, 9,12,14,15,15},
+{ 9, 9, 9, 8, 7, 6, 5, 4, 3, 3, 3, 3, 3, 3, 4, 5, 6, 7, 8,10,11,12,13,13},
+{14,12,10, 8, 6, 6, 5, 4, 3, 3, 3, 3, 3, 3, 4, 5, 6, 8, 8, 9,11,14,14,14},
+{13,10, 9, 8, 6, 6, 5, 4, 4, 4, 3, 3, 2, 3, 4, 5, 6, 8, 9, 9,11,12,14,14},
+{16,13,12,11, 9, 6, 5, 5, 4, 4, 4, 3, 2, 3, 3, 4, 5, 7, 8,10,14,16,16,16},
+{13,14,14,14,10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9,11,14,14,14},
+{13,14,14,14,10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9,11,14,14,14},
+{13,14,14,14,10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9,11,14,14,14},
+{13,14,14,14,10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9,11,14,14,14},
+{13,14,14,14,10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9,11,14,14,14},
+{13,14,14,14,10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9,11,14,14,14},
+{13,14,14,14,10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9,11,14,14,14},
+{13,14,14,14,10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9,11,14,14,14},
+{13,14,14,14,10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9,11,14,14,14},
+{13,14,14,14,10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9,11,14,14,14},
+{13,14,14,14,10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9,11,14,14,14},
+{13,14,14,14,10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9,11,14,14,14},
+{13,14,14,14,10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9,11,14,14,14},
+{13,14,14,14,10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9,11,14,14,14},
+{13,14,14,14,10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9,11,14,14,14}};
+
+UWord16 differential_region_power_codes[MAX_NUMBER_OF_REGIONS][DIFF_REGION_POWER_LEVELS] = {
+{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+{ 8,38,18,10, 7, 6, 3, 2, 0, 1, 7, 6, 5, 4,11,78,158,318,1278,1279,2552,2553,2554,2555},
+{36, 8, 3, 5, 0, 1, 7, 6, 4, 3, 2, 5, 3, 4, 5,19,74,150,302,1213,1214,1215,2424,2425},
+{2582,644,160,41, 5,11, 7, 5, 4, 1, 0, 6, 4, 7, 3, 6, 4,21,81,323,1290,5167,10332,10333},
+{2940,366,181,180,47,46,27,10, 8, 5, 1, 0, 3, 7, 4, 9,12,26,44,182,734,2941,2942,2943},
+{3982,7967,994,249,63,26,19,18,14, 8, 6, 1, 0, 2, 5, 7,12,30,27,125,496,1990,15932,15933},
+{3254,1626,407,206,202,100,30,14, 3, 5, 3, 0, 2, 4, 2,13,24,31,102,207,812,6511,13020,13021},
+{1110,2216,1111,139,35, 9, 3,20,11, 4, 2, 1, 3, 3, 1, 0,21, 5,16,68,276,2217,2218,2219},
+{1013,1014,127,62,29, 6, 4,16, 0, 1, 3, 2, 3, 1, 5, 9,17, 5,28,30,252,1015,2024,2025},
+{381,380,372,191,94,44,16,10, 7, 3, 1, 0, 2, 6, 9,17,45,92,187,746,1494,2991,5980,5981},
+{3036,758,188,45,43,10, 4, 3, 6, 4, 2, 0, 3, 7,11,20,42,44,46,95,378,3037,3038,3039},
+{751,92,45,20,26, 4,12, 7, 4, 0, 4, 1, 3, 5, 5, 3,27,21,44,47,186,374,1500,1501},
+{45572U,5697,2849,1425,357,45,23, 6,10, 7, 2, 2, 3, 0, 4, 6, 7,88,179,713,11392,45573U,45574U,45575U},
+{2511,5016,5018,5017,312,79,38,36,30,14, 6, 0, 2, 1, 3, 5, 8,31,37,157,626,5019,5020,5021},
+{2511,5016,5018,5017,312,79,38,36,30,14, 6, 0, 2, 1, 3, 5, 8,31,37,157,626,5019,5020,5021},
+{2511,5016,5018,5017,312,79,38,36,30,14, 6, 0, 2, 1, 3, 5, 8,31,37,157,626,5019,5020,5021},
+{2511,5016,5018,5017,312,79,38,36,30,14, 6, 0, 2, 1, 3, 5, 8,31,37,157,626,5019,5020,5021},
+{2511,5016,5018,5017,312,79,38,36,30,14, 6, 0, 2, 1, 3, 5, 8,31,37,157,626,5019,5020,5021},
+{2511,5016,5018,5017,312,79,38,36,30,14, 6, 0, 2, 1, 3, 5, 8,31,37,157,626,5019,5020,5021},
+{2511,5016,5018,5017,312,79,38,36,30,14, 6, 0, 2, 1, 3, 5, 8,31,37,157,626,5019,5020,5021},
+{2511,5016,5018,5017,312,79,38,36,30,14, 6, 0, 2, 1, 3, 5, 8,31,37,157,626,5019,5020,5021},
+{2511,5016,5018,5017,312,79,38,36,30,14, 6, 0, 2, 1, 3, 5, 8,31,37,157,626,5019,5020,5021},
+{2511,5016,5018,5017,312,79,38,36,30,14, 6, 0, 2, 1, 3, 5, 8,31,37,157,626,5019,5020,5021},
+{2511,5016,5018,5017,312,79,38,36,30,14, 6, 0, 2, 1, 3, 5, 8,31,37,157,626,5019,5020,5021},
+{2511,5016,5018,5017,312,79,38,36,30,14, 6, 0, 2, 1, 3, 5, 8,31,37,157,626,5019,5020,5021},
+{2511,5016,5018,5017,312,79,38,36,30,14, 6, 0, 2, 1, 3, 5, 8,31,37,157,626,5019,5020,5021},
+{2511,5016,5018,5017,312,79,38,36,30,14, 6, 0, 2, 1, 3, 5, 8,31,37,157,626,5019,5020,5021},
+{2511,5016,5018,5017,312,79,38,36,30,14, 6, 0, 2, 1, 3, 5, 8,31,37,157,626,5019,5020,5021}};
+
+Word16 differential_region_power_decoder_tree[MAX_NUMBER_OF_REGIONS][DIFF_REGION_POWER_LEVELS-1][2] = {
+{{  0,  0},{  0,  0},{  0,  0},{  0,  0},{  0,  0},{  0,  0},{  0,  0},{  0,  0},{  0,  0},{  0,  0},{  0,  0},{  0,  0},{  0,  0},{  0,  0},{  0,  0},{  0,  0},{  0,  0},{  0,  0},{  0,  0},{  0,  0},{  0,  0},{  0,  0},{  0,  0}},
+{{  1,  2},{  3,  4},{  5,  6},{  7,  8},{  9, 10},{ 11,-12},{-11,-10},{ -8, -9},{ -7, -6},{-13, 12},{ -5, -4},{  0, 13},{ -3,-14},{ -2, 14},{ -1, 15},{-15, 16},{-16, 17},{-17, 18},{ 19, 20},{ 21, 22},{-18,-19},{-20,-21},{-22,-23}},
+{{  1,  2},{  3,  4},{  5,  6},{  7,  8},{-10, -9},{ -8,-11},{ -7, -6},{  9, -5},{ 10,-12},{ -4, 11},{-13, -3},{ 12, -2},{ 13,-14},{ -1, 14},{ 15,-15},{  0, 16},{-16, 17},{-17, 18},{-18, 19},{ 20, 21},{ 22,-19},{-20,-21},{-22,-23}},
+{{  1,  2},{  3,  4},{  5,  6},{  7,  8},{  9, 10},{-12, 11},{-11,-13},{-10, -9},{ 12,-14},{ -8, -7},{-15, -6},{ 13, -5},{-16, -4},{ 14,-17},{ 15, -3},{ 16,-18},{ -2, 17},{ 18,-19},{ -1, 19},{-20, 20},{  0, 21},{ 22,-21},{-22,-23}},
+{{  1,  2},{  3,  4},{  5,  6},{-11,-10},{  7,-12},{  8, -9},{  9,-13},{-14, 10},{ -8,-15},{-16, 11},{ -7, 12},{-17, -6},{ 13, 14},{-18, 15},{ -5, -4},{ 16, 17},{ -3, -2},{-19, 18},{ -1, 19},{-20, 20},{ 21, 22},{  0,-21},{-22,-23}},
+{{  1,  2},{  3,  4},{  5,  6},{-12,-11},{-13,  7},{  8,-14},{-10,  9},{ 10,-15},{ -9, 11},{ -8, 12},{-16, 13},{ -7, -6},{-17, 14},{ -5,-18},{ 15, -4},{ 16,-19},{ 17, -3},{-20, 18},{ -2, 19},{-21, 20},{  0, 21},{ 22, -1},{-22,-23}},
+{{  1,  2},{  3,  4},{  5,  6},{-11,  7},{-12,-10},{-13, -9},{  8,  9},{-14, -8},{ 10,-15},{ -7, 11},{-16, 12},{ -6,-17},{ 13, 14},{ -5, 15},{-18, 16},{ -4, 17},{ -3,-19},{ 18, -2},{-20, 19},{ -1, 20},{  0, 21},{ 22,-21},{-22,-23}},
+{{  1,  2},{  3,  4},{  5,-12},{  6,-11},{-10,-13},{ -9,  7},{  8,-14},{  9, -8},{-15, 10},{ -7,-16},{ 11, -6},{ 12,-17},{ 13, -5},{-18, 14},{ 15, -4},{-19, 16},{ 17, -3},{-20, 18},{ 19, 20},{ 21, 22},{  0, -2},{ -1,-21},{-22,-23}},
+{{  1,  2},{  3,  4},{  5,-12},{  6,-13},{-11,-10},{  7,-14},{  8, -9},{  9,-15},{ -8, 10},{ -7,-16},{ 11, 12},{ -6,-17},{ -5, 13},{ 14, 15},{-18, -4},{-19, 16},{ -3, 17},{ 18, -2},{-20, 19},{ 20, 21},{ 22,  0},{ -1,-21},{-22,-23}},
+{{  1,  2},{  3,  4},{  5,  6},{-11,-10},{-12, -9},{  7,  8},{-13, -8},{  9,-14},{ -7, 10},{ -6,-15},{ 11, 12},{ -5,-16},{ 13, 14},{-17, 15},{ -4, 16},{ 17,-18},{ 18, -3},{ -2, 19},{ -1,  0},{-19, 20},{-20, 21},{ 22,-21},{-22,-23}},
+{{  1,  2},{  3,  4},{  5,  6},{-11,  7},{-10,-12},{ -9,  8},{ -8,-13},{  9, -7},{ 10,-14},{ -6, 11},{-15, 12},{ -5, 13},{-16, -4},{ 14, 15},{-17, -3},{-18, 16},{ 17,-19},{ -2, 18},{-20, 19},{ -1, 20},{ 21, 22},{  0,-21},{-22,-23}},
+{{  1,  2},{  3,  4},{  5,-12},{  6,-11},{  7,  8},{-10,-13},{ -9,  9},{ -8,-14},{ 10, -7},{ 11,-15},{ -6, 12},{ -5, 13},{ -4,-16},{ 14, 15},{ -3,-17},{ 16, 17},{-18, -2},{ 18,-19},{ -1, 19},{-20, 20},{-21, 21},{ 22,  0},{-22,-23}},
+{{  1,  2},{  3,  4},{  5,-12},{-13,  6},{-11,  7},{-14,  8},{-10,  9},{-15, -9},{ -8, 10},{ -7,-16},{ 11, -6},{ 12, -5},{-17, 13},{ 14,-18},{ 15, -4},{ 16,-19},{ 17, -3},{ 18, -2},{ 19, -1},{-20, 20},{ 21, 22},{  0,-21},{-22,-23}},
+{{  1,  2},{  3,  4},{-12,  5},{-11,-13},{  6,-14},{-10,  7},{  8,-15},{ -9,  9},{-16, 10},{ -8,-17},{ 11, 12},{ -7,-18},{ -6, 13},{ 14, -5},{ 15,-19},{ -4, 16},{-20, 17},{ 18, 19},{ 20, 21},{ 22,  0},{ -1, -3},{ -2,-21},{-22,-23}},
+{{  1,  2},{  3,  4},{-12,  5},{-11,-13},{  6,-14},{-10,  7},{  8,-15},{ -9,  9},{-16, 10},{ -8,-17},{ 11, 12},{ -7,-18},{ -6, 13},{ 14, -5},{ 15,-19},{ -4, 16},{-20, 17},{ 18, 19},{ 20, 21},{ 22,  0},{ -1, -3},{ -2,-21},{-22,-23}},
+{{  1,  2},{  3,  4},{-12,  5},{-11,-13},{  6,-14},{-10,  7},{  8,-15},{ -9,  9},{-16, 10},{ -8,-17},{ 11, 12},{ -7,-18},{ -6, 13},{ 14, -5},{ 15,-19},{ -4, 16},{-20, 17},{ 18, 19},{ 20, 21},{ 22,  0},{ -1, -3},{ -2,-21},{-22,-23}},
+{{  1,  2},{  3,  4},{-12,  5},{-11,-13},{  6,-14},{-10,  7},{  8,-15},{ -9,  9},{-16, 10},{ -8,-17},{ 11, 12},{ -7,-18},{ -6, 13},{ 14, -5},{ 15,-19},{ -4, 16},{-20, 17},{ 18, 19},{ 20, 21},{ 22,  0},{ -1, -3},{ -2,-21},{-22,-23}},
+{{  1,  2},{  3,  4},{-12,  5},{-11,-13},{  6,-14},{-10,  7},{  8,-15},{ -9,  9},{-16, 10},{ -8,-17},{ 11, 12},{ -7,-18},{ -6, 13},{ 14, -5},{ 15,-19},{ -4, 16},{-20, 17},{ 18, 19},{ 20, 21},{ 22,  0},{ -1, -3},{ -2,-21},{-22,-23}},
+{{  1,  2},{  3,  4},{-12,  5},{-11,-13},{  6,-14},{-10,  7},{  8,-15},{ -9,  9},{-16, 10},{ -8,-17},{ 11, 12},{ -7,-18},{ -6, 13},{ 14, -5},{ 15,-19},{ -4, 16},{-20, 17},{ 18, 19},{ 20, 21},{ 22,  0},{ -1, -3},{ -2,-21},{-22,-23}},
+{{  1,  2},{  3,  4},{-12,  5},{-11,-13},{  6,-14},{-10,  7},{  8,-15},{ -9,  9},{-16, 10},{ -8,-17},{ 11, 12},{ -7,-18},{ -6, 13},{ 14, -5},{ 15,-19},{ -4, 16},{-20, 17},{ 18, 19},{ 20, 21},{ 22,  0},{ -1, -3},{ -2,-21},{-22,-23}},
+{{  1,  2},{  3,  4},{-12,  5},{-11,-13},{  6,-14},{-10,  7},{  8,-15},{ -9,  9},{-16, 10},{ -8,-17},{ 11, 12},{ -7,-18},{ -6, 13},{ 14, -5},{ 15,-19},{ -4, 16},{-20, 17},{ 18, 19},{ 20, 21},{ 22,  0},{ -1, -3},{ -2,-21},{-22,-23}},
+{{  1,  2},{  3,  4},{-12,  5},{-11,-13},{  6,-14},{-10,  7},{  8,-15},{ -9,  9},{-16, 10},{ -8,-17},{ 11, 12},{ -7,-18},{ -6, 13},{ 14, -5},{ 15,-19},{ -4, 16},{-20, 17},{ 18, 19},{ 20, 21},{ 22,  0},{ -1, -3},{ -2,-21},{-22,-23}},
+{{  1,  2},{  3,  4},{-12,  5},{-11,-13},{  6,-14},{-10,  7},{  8,-15},{ -9,  9},{-16, 10},{ -8,-17},{ 11, 12},{ -7,-18},{ -6, 13},{ 14, -5},{ 15,-19},{ -4, 16},{-20, 17},{ 18, 19},{ 20, 21},{ 22,  0},{ -1, -3},{ -2,-21},{-22,-23}},
+{{  1,  2},{  3,  4},{-12,  5},{-11,-13},{  6,-14},{-10,  7},{  8,-15},{ -9,  9},{-16, 10},{ -8,-17},{ 11, 12},{ -7,-18},{ -6, 13},{ 14, -5},{ 15,-19},{ -4, 16},{-20, 17},{ 18, 19},{ 20, 21},{ 22,  0},{ -1, -3},{ -2,-21},{-22,-23}},
+{{  1,  2},{  3,  4},{-12,  5},{-11,-13},{  6,-14},{-10,  7},{  8,-15},{ -9,  9},{-16, 10},{ -8,-17},{ 11, 12},{ -7,-18},{ -6, 13},{ 14, -5},{ 15,-19},{ -4, 16},{-20, 17},{ 18, 19},{ 20, 21},{ 22,  0},{ -1, -3},{ -2,-21},{-22,-23}},
+{{  1,  2},{  3,  4},{-12,  5},{-11,-13},{  6,-14},{-10,  7},{  8,-15},{ -9,  9},{-16, 10},{ -8,-17},{ 11, 12},{ -7,-18},{ -6, 13},{ 14, -5},{ 15,-19},{ -4, 16},{-20, 17},{ 18, 19},{ 20, 21},{ 22,  0},{ -1, -3},{ -2,-21},{-22,-23}},
+{{  1,  2},{  3,  4},{-12,  5},{-11,-13},{  6,-14},{-10,  7},{  8,-15},{ -9,  9},{-16, 10},{ -8,-17},{ 11, 12},{ -7,-18},{ -6, 13},{ 14, -5},{ 15,-19},{ -4, 16},{-20, 17},{ 18, 19},{ 20, 21},{ 22,  0},{ -1, -3},{ -2,-21},{-22,-23}},
+{{  1,  2},{  3,  4},{-12,  5},{-11,-13},{  6,-14},{-10,  7},{  8,-15},{ -9,  9},{-16, 10},{ -8,-17},{ 11, 12},{ -7,-18},{ -6, 13},{ 14, -5},{ 15,-19},{ -4, 16},{-20, 17},{ 18, 19},{ 20, 21},{ 22,  0},{ -1, -3},{ -2,-21},{-22,-23}}};
+
+Word16 mlt_quant_centroid[NUM_CATEGORIES][MAX_NUM_BINS] = {
+{    0, 1606, 3119, 4586, 6049, 7502, 8941,10406,11851,13292,14736,16146,17566,19351,    0,    0},
+{    0, 2229, 4341, 6401, 8471,10531,12583,14588,16673,18924,    0,    0,    0,    0,    0,    0},
+{    0, 3055, 5998, 8929,11806,14680,17680,    0,    0,    0,    0,    0,    0,    0,    0,    0},
+{    0, 4121, 8192,12259,16322,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0},
+{    0, 5413,11071,16315,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0},
+{    0, 6785,14300,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0},
+{    0, 8044,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0},
+{    0, 8019,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0}};
+
+Word16 expected_bits_table[NUM_CATEGORIES] = {52, 47, 43, 37, 29, 22, 16,   0};
+
+
+Word16 mlt_sqvh_bitcount_category_0[196] = {
+ 1, 4, 6, 6, 7, 7, 8, 8, 8, 9, 9,10,11,11, 4, 5,
+ 6, 7, 7, 8, 8, 9, 9, 9, 9,10,11,11, 5, 6, 7, 8,
+ 8, 9, 9, 9, 9,10,10,10,11,12, 6, 7, 8, 9, 9, 9,
+ 9,10,10,10,10,11,12,13, 7, 7, 8, 9, 9, 9,10,10,
+10,10,11,11,12,13, 8, 8, 9, 9, 9,10,10,10,10,11,
+11,12,13,14, 8, 8, 9, 9,10,10,11,11,11,12,12,13,
+13,15, 8, 8, 9, 9,10,10,11,11,11,12,12,13,14,15,
+ 9, 9, 9,10,10,10,11,11,12,13,12,14,15,16, 9, 9,
+10,10,10,10,11,12,12,14,14,16,16,16, 9, 9,10,10,
+11,11,12,13,13,14,14,15,15,16,10,10,10,11,11,12,
+12,13,15,15,16,14,15,15,11,11,11,12,13,13,13,15,
+16,16,16,16,14,15,11,11,12,13,13,14,15,16,16,16,
+16,16,16,14};
+UWord16 mlt_sqvh_code_category_0[196] = {
+    1,    2,    1,   24,   14,   51,    9,   68,  110,   26,  218,   54,  154,  761,    3,   10,
+   22,    8,   58,   22,   71,   16,   30,   50,  213,   75,   94,  632,   15,   18,   52,   23,
+  107,    5,   54,   63,  239,   46,  276,  271,  851,  252,   28,   10,   12,    1,   22,  133,
+  191,   55,  105,  278,  317,  554,  310,  276,   32,   50,   94,   20,  187,  219,   13,  268,
+  473,  445,  145,  849, 1277,  623,    1,   14,    0,   55,  238,  121,  120,  269,  318,  530,
+  639, 1117,  509,  556,   24,   78,   51,  153,   62,  308,   16,   25,   68, 1058,  428,  277,
+ 2233, 1114,   92,  108,  141,  223,  270,  381,   24,  212,  760,   35, 1063,  279, 1717, 3439,
+    7,   21,  152,   73,  309,  310,   95,  944, 1890, 2232, 1891, 5107,10213, 4981,   61,   62,
+    9,   79,  474,  475,  848, 1059, 1056, 1716,  139, 4978, 4983, 4983,  140,  186,   76,  444,
+  144,  633, 1057,  838, 2237, 4472, 4473,10212,10212, 4983,   74,   78,  311,  213,  850, 1062,
+ 1119,  508,  276,  277, 4982, 4473,10212,10212,  208,   70,  555,  418,   68,  510, 2552, 1115,
+ 4980, 4979, 4982, 4982, 4473,10212,  215,   71,  253,  511,  839, 1718, 2488, 6876, 6877, 4979,
+ 4979, 4982, 4982, 4473};
+Word16 mlt_sqvh_bitcount_category_1[100] = {
+ 1, 4, 5, 6, 7, 8, 8, 9,10,10, 4, 5, 6, 7, 7, 8,
+ 8, 9, 9,11, 5, 5, 6, 7, 8, 8, 9, 9,10,11, 6, 6,
+ 7, 8, 8, 9, 9,10,11,12, 7, 7, 8, 8, 9, 9,10,11,
+11,13, 8, 8, 8, 9, 9,10,10,11,12,14, 8, 8, 8, 9,
+10,11,11,12,13,15, 9, 9, 9,10,11,12,12,14,14,14,
+ 9, 9, 9,10,11,12,14,16,14,14,10,10,11,12,13,14,
+16,16,16,14};
+UWord16 mlt_sqvh_code_category_1[100] = {
+    1,    2,   11,   27,   31,    9,  120,   31,  275,  310,    1,    0,   12,    5,   33,   54,
+  102,  111,  246,  448,   10,   14,   31,   39,   59,  100,  114,  202,  485,  969,   24,   26,
+   36,   52,  103,   30,  120,  242,   69, 1244,   35,   32,   14,   61,  113,  117,  233,  486,
+  487, 2491,   13,   12,   69,  110,  149,   35,  495,  449, 1978, 7751,   76,   75,  122,  136,
+  213,   68,  623,  930, 3959, 9961,  115,   16,  107,  225,  424,  850, 1936, 7916, 4981, 4981,
+  148,  154,  243,  407,  988,  851, 7750,19920, 7916, 4981,  406,  274,  464,  931, 3874, 7917,
+19921,19920,19920, 7916};
+Word16 mlt_sqvh_bitcount_category_2[49] = {
+ 1, 4, 5, 7, 8, 9,10, 3, 4, 5, 7, 8, 9,10, 5, 5,
+ 6, 7, 8,10,10, 7, 6, 7, 8, 9,10,12, 8, 8, 8, 9,
+10,12,14, 8, 9, 9,10,11,15,16, 9,10,11,12,13,16,
+15};
+UWord16 mlt_sqvh_code_category_2[49] = {
+    1,    0,   10,   11,   28,   62,  363,    3,    2,    9,    8,   24,   53,  352,    7,    8,
+   13,   25,   89,   74,  355,   10,   23,   24,   29,   55,  354, 1449,   25,   19,   30,   52,
+  108,  438, 5793,   91,   36,   63,  353,  725,11584,23170,  180,   75,  218,  439, 2897,23171,
+11584};
+Word16 mlt_sqvh_bitcount_category_3[625] = {
+ 2, 4, 6, 8,10, 5, 5, 6, 8,10, 7, 8, 8,10,12, 9,
+ 9,10,12,15,10,11,13,16,16, 5, 6, 8,10,11, 5, 6,
+ 8,10,12, 7, 7, 8,10,13, 9, 9,10,12,15,12,11,13,
+16,16, 7, 9,10,12,15, 7, 8,10,12,13, 9, 9,11,13,
+16,11,11,12,14,16,12,12,14,16,14, 9,11,12,16,16,
+ 9,10,13,15,16,10,11,12,16,16,13,13,16,16,16,16,
+16,15,16,16,11,13,16,16,15,11,13,15,16,16,13,13,
+16,16,16,14,16,16,16,16,16,16,16,16,16, 4, 6, 8,
+10,13, 6, 6, 8,10,13, 9, 8,10,12,16,10,10,11,15,
+16,13,12,14,16,16, 5, 6, 8,11,13, 6, 6, 8,10,13,
+ 8, 8, 9,11,14,10,10,12,12,16,13,12,13,15,16, 7,
+ 8, 9,12,16, 7, 8,10,12,14, 9, 9,10,13,16,11,10,
+12,15,16,13,13,16,16,15, 9,11,13,16,16, 9,10,12,
+15,16,10,11,13,16,16,13,12,16,16,16,16,16,16,16,
+16,11,13,16,16,16,11,13,16,16,16,12,13,15,16,16,
+16,16,16,16,16,16,16,16,16,16, 6, 8,11,13,16, 8,
+ 8,10,12,16,11,10,11,13,16,12,13,13,15,16,16,16,
+14,16,15, 6, 8,10,13,16, 8, 8,10,12,16,10,10,11,
+13,16,13,12,13,16,16,14,14,14,16,16, 8, 9,11,13,
+16, 8, 9,11,16,14,10,10,12,15,16,12,12,13,16,16,
+15,16,16,16,16,10,12,15,16,16,10,12,12,14,16,12,
+12,13,16,16,14,15,16,16,16,16,16,16,16,16,12,15,
+15,16,16,13,13,16,16,14,14,16,16,16,16,16,16,16,
+16,16,14,15,16,16,16, 8,10,13,15,16,10,11,13,16,
+16,13,13,14,16,16,16,16,16,16,16,16,16,16,16,16,
+ 8,10,11,15,16, 9,10,12,16,16,12,12,15,16,16,16,
+14,16,16,16,16,16,16,16,16, 9,11,14,16,16,10,11,
+13,16,16,14,13,14,16,16,16,15,15,16,16,16,16,16,
+16,16,11,13,16,16,16,11,13,15,16,16,13,16,16,16,
+16,16,16,16,16,16,16,16,16,16,16,15,16,16,16,16,
+14,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+16,16,16,16, 9,13,16,16,16,11,13,16,16,16,14,15,
+16,16,16,15,16,16,16,16,16,16,16,16,16, 9,13,15,
+15,16,12,13,14,16,16,16,15,16,16,16,16,16,16,16,
+16,16,16,16,16,16,11,13,15,16,16,12,14,16,16,16,
+16,16,16,16,16,16,16,16,16,16,16,15,15,16,16,16,
+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,15,
+16,16,13,16,16,16,16,16,16,16,16,16,16,16,16,16,
+16};
+UWord16 mlt_sqvh_code_category_3[625] = {
+    3,    8,   46,  145,  228,    4,    8,   47,   28,  455,   89,    2,  180,    5, 1335,  250,
+   12,  644, 1311,  139,  729,  251,  870, 2172, 2211,    5,   23,  112,  334, 1469,   21,    3,
+    5,  111, 2014,   88,   79,  152,  124, 2685,  297,   48,  110, 1310,  149,  501, 1231,  153,
+ 2267, 2569,   57,   13,  653, 2587,  143,   75,  124,  118, 2611, 5242,   61,   50,  253, 3633,
+ 2216,  476,   39,   57, 1926, 2236, 2586, 1329, 1920, 2566, 1926,  296,  233, 2590, 2240, 2217,
+  253,  613,  867,  144,  318,  614,  252, 2589, 2242, 2218,  872,  866, 2187, 2296, 2155, 2568,
+ 2227,  150, 2567, 2296,  199, 2686, 2160, 2290,19145,  232, 2680,  128, 2192, 2212, 2684,  793,
+ 2281, 2223, 2242, 1934, 2165, 2146, 2291, 2296, 2222, 2189, 2187, 2296, 2296,    6,    4,   82,
+  725, 3632,   15,   21,   56,  599,  148,    3,  162,   42,  411, 2301,  735,  654,  930,  137,
+ 2586,  869, 1334, 1931, 2300, 2213,    9,   22,  146, 1290, 5240,    5,   12,   53,  630,  875,
+   80,    9,    8,   86, 2002,  210,  117,   56, 2019, 2162,  146,  397,  868,  131, 2151,   77,
+  160,  365, 2610, 2252,   59,   54,   41, 2591, 1928,  226,   14,  121, 5792, 2295, 1197,  728,
+  408,  130, 2157, 3635,  155, 2573, 2587,  130,  314,   64,  144, 2173, 2176,  115,   30,  409,
+  153, 2590,  631,   26, 4787, 2221, 2174, 2683, 1863, 2572,  319, 2150, 2177, 2194, 2571, 2257,
+  319,   65,  145, 2251, 2156, 2161,  909,  864, 2193, 2197, 2246, 2588, 5797,  156, 2258, 2221,
+ 2158, 2199, 2214, 2152,  319, 2188, 2264, 2572,  319,  319,   30,  117,  219,  865, 2263,  147,
+  127,  239,  410, 2247,   27,  324, 1468, 2681, 2180, 1328, 5241,  147,  142, 2237, 2241, 2245,
+ 1921, 2262,  142,   41,   11,  505, 2682, 2591,    0,   26,  229, 2015, 2577,  464,   98,   87,
+ 5243, 2166,  149, 2016, 5244, 2190, 2198, 9573,11598,11599, 2235, 2190,  144,  298, 1004, 5245,
+ 2277,  156,  104,  254, 2560, 1922,  612,  325, 2017,  129, 2588, 2608, 1330,  871, 2144, 2145,
+  132, 2147, 2148, 2149, 2144,  119, 1331,  133, 2153, 2154,  211,   58, 2609, 1923, 2159,  510,
+  163, 5246, 2163, 2164, 1924,  134, 2167, 2168, 2168, 2169, 2170, 2171, 2168, 2168, 1332,  135,
+  136, 2175, 2153,  150,  873, 2178, 2179, 1923, 1925, 2181, 2182, 2183, 2163, 2184, 2185, 2186,
+ 2168, 2168, 1924,  134, 2167, 2168, 2168,   58,  326, 2687,  138, 2191,   31,   66,  874, 2195,
+ 2196,  151,  152, 1927, 2200, 2201, 2202, 2203, 2204, 2205, 2206, 2207, 2208, 2209, 2210, 2205,
+   55,  103, 1230,  140, 2215,  118,   15, 1333, 2219, 2220, 2018,  511,  141, 2224, 2225, 2226,
+ 1929, 2228, 2229, 2230, 2231, 2232, 2233, 2234, 2229,  366, 1005, 1930, 2238, 2239,   12, 1006,
+ 5247, 2243, 2244, 1932, 3634, 1933, 2248, 2249, 2250,  145,  146, 2253, 2253, 2254, 2255, 2256,
+ 2253, 2253, 1291, 5793, 2259, 2260, 2261,  477, 5794,  147, 2265, 2266, 5795, 2268, 2269, 2270,
+ 2270, 2271, 2272, 2273, 2274, 2274, 2275, 2276, 2273, 2274, 2274,  148, 2278, 2279, 2280, 2260,
+ 1935, 2282, 2283, 2284, 2265, 2285, 2286, 2287, 2270, 2270, 2288, 2289, 2273, 2274, 2274, 2271,
+ 2272, 2273, 2274, 2274,  233, 5796, 2292, 2293, 2294, 1292, 3724, 2297, 2298, 2299, 2000,  151,
+ 2302, 2303, 2200,  152, 2561, 2562, 2563, 2205, 2564, 2565, 2204, 2205, 2205,  363,  154,  154,
+  155, 2570,   59, 3725, 2001, 2574, 2575, 2576,  157, 2578, 2579, 2224, 2580, 2581, 2582, 2583,
+ 2229, 2584, 2585, 2228, 2229, 2229,  654, 5798,  158, 2589, 2238, 2392, 2003, 2592, 2593, 2243,
+ 2594, 2595, 2596, 2597, 2248, 2598, 2599, 2600, 2253, 2253, 2250,  145,  146, 2253, 2253, 2601,
+ 2602, 2603, 2604, 2260, 2605, 2606, 2607, 6336, 2265, 6337, 6338, 6339, 2270, 2270, 6340, 6341,
+ 2273, 2274, 2274, 2271, 2272, 2273, 2274, 2274, 6342, 6343, 2259, 2260, 2260,38288U,38289U,  147,
+ 2265, 2265, 5795, 2268, 2269, 2270, 2270, 2271, 2272, 2273, 2274, 2274, 2271, 2272, 2273, 2274,
+ 2274};
+Word16 mlt_sqvh_bitcount_category_4[256] = {
+ 2, 4, 7,10, 4, 5, 7,10, 7, 8,10,14,11,11,15,15,
+ 4, 5, 9,12, 5, 5, 8,12, 8, 7,10,15,11,11,15,15,
+ 7, 9,12,15, 8, 8,12,15,10,10,13,15,14,14,15,13,
+11,13,15,15,11,13,15,15,14,15,15,13,15,15,13,13,
+ 4, 5, 9,13, 5, 6, 9,13, 9, 9,11,15,14,13,15,15,
+ 4, 6, 9,12, 5, 6, 9,13, 9, 8,11,15,13,12,15,15,
+ 7, 9,12,15, 7, 8,11,15,10,10,14,15,14,15,15,14,
+10,12,15,15,11,13,15,15,15,15,15,14,15,15,14,14,
+ 6, 9,13,14, 8, 9,12,15,12,12,15,15,15,15,15,15,
+ 7, 9,13,15, 8, 9,12,15,11,12,15,15,15,15,15,15,
+ 9,11,15,15, 9,11,15,15,14,14,15,15,15,15,15,15,
+14,15,15,15,14,15,15,15,15,15,15,15,14,14,15,15,
+ 9,12,15,15,12,13,15,15,15,15,15,15,15,15,15,15,
+10,12,15,15,12,14,15,15,15,15,15,15,15,15,15,15,
+14,15,15,15,15,15,15,15,15,15,15,15,14,14,15,15,
+15,15,15,15,15,15,15,15,14,14,15,15,14,14,15,15};
+UWord16 mlt_sqvh_code_category_4[256] = {
+    1,    2,    4,  572,   10,    0,   69,  712,   91,   10,   46, 9182, 1426, 1430,30172,30194,
+    9,   28,   22, 2258,   16,   25,  142, 2179,   15,  111,  719, 1521, 1131, 1437, 1520,30196,
+   88,  283, 3803,30193,   13,  236, 2856,30166,  545,  951, 5709, 1522, 3241, 9180,30179, 5709,
+ 1088, 4356,30410,30175, 1146,  377,30162,30163, 8715,30176,30165, 5709,30197,30184, 5709, 5709,
+    1,   23,   28, 5710,   26,   14,   29, 7538,  102,  103, 1429, 1524, 3237, 7060,30401,30201,
+   15,   13,  470, 3768,   24,   15,  281, 5747,   24,  181, 1128,30206, 5711, 3531,30156,30158,
+  116,  100, 2260,30187,  119,  234, 1764,30171,  716,  883, 9183,30164, 3236, 1528,30180, 9183,
+  885, 2870, 1532,30160, 1431, 5708,30192,30205,30402,30168,30173, 9183,30157,30161, 9183, 9183,
+   54,   25, 1621,15211,  180,  287, 2261,30198,  808,  811,30411,30413,30414,22986,22987,30411,
+   24,  273,  376,30159,  137,  280, 2871, 1523, 1768, 2259, 1525,30167, 1526,30169,30170, 1525,
+  443, 1434, 1527,30174,  474, 1769,30177,30178, 3238, 3239,30181,30181,30182,30183,30181,30181,
+ 3240,30185,30186, 1527, 9181,30188,30189,30177,30190,30191,30181,30181, 3238, 3239,30181,30181,
+  440, 2857, 1529,30195, 2294, 7061, 1530,30199,30200, 1531,30202,30411,30203,30204,30411,30411,
+  203, 2872,30207,30400,  189,11492,30403,30404,30405,30406,30407, 1525,30408,30409, 1525, 1525,
+ 8714, 1533,30412, 1527, 1534, 1535,30415,30177,30416,30417,30181,30181, 3238, 3239,30181,30181,
+30418,30419, 1527, 1527,30420,30421,30177,30177, 3238, 3239,30181,30181, 3238, 3239,30181,30181};
+Word16 mlt_sqvh_bitcount_category_5[243] = {
+ 2, 4, 8, 4, 5, 9, 9,10,14, 4, 6,11, 5, 6,12,10,
+11,15, 9,11,15,10,13,15,14,15, 6, 4, 6,12, 6, 7,
+12,12,12,15, 5, 7,13, 6, 7,13,12,13,15,10,12,15,
+11,13,15,15,15, 7, 8,13,15,11,12,15,15,15, 7,10,
+13,15,12,15,15,15,15, 7,15,15, 7,15,15, 7, 6, 7,
+ 7, 4, 5,11, 5, 7,12,11,12,15, 6, 7,13, 7, 8,14,
+12,14,15,11,13,15,12,13,15,15,15, 8, 5, 6,13, 7,
+ 8,15,12,14,15, 6, 8,14, 7, 8,15,14,15,15,12,12,
+15,12,13,15,15,15, 8, 9,13,15,12,13,15,15,15, 8,
+11,13,15,13,13,15,15,15, 8,14,15, 8,15,15, 8, 7,
+ 8, 8, 8,10,15,11,12,15,15,15, 7,10,12,15,12,13,
+15,15,15, 8,14,15, 7,15,15, 8, 7, 8, 8, 8,12,15,
+12,13,15,15,15, 8,11,13,15,13,15,15,15,15, 8,15,
+15, 8,15,15, 8, 7, 8, 8,14,15, 6,15,15, 8, 7, 8,
+ 8,15,15, 8,15,15, 8, 7, 8, 8, 6, 8, 8, 7, 8, 8,
+ 7, 8, 8};
+UWord16 mlt_sqvh_code_category_5[243] = {
+    0,    5,  220,   10,   16,  443,  390,  391,14333,   11,   26, 1566,   26,   54, 3135,  508,
+ 1558,28581,  255, 1782,28599,  885, 6208,28578,14335,28579,   54,    9,   35, 3129,   27,   68,
+ 3537, 1562, 3568,28610,   25,   62, 4078,   58,  118, 7763, 3107, 7758,28563,  778, 3131,28598,
+  780, 7123,28630,28593,28586,  118,  243, 6210,28614, 1018, 3567,28601,28611,28570,   68,  388,
+ 6256,28619, 1559,28562,28606,28565,28591,  118,28594,28571,   62,28618,28590,  118,   58,  118,
+  118,    4,   28, 1781,   31,   60, 3134, 1938, 3882,28574,   25,   96, 7757,   49,  126,14244,
+ 3883,14334,28613, 1769, 4077,28602, 3106, 7756,28582,28621,28566,  126,   14,   61, 4079,   61,
+  138,28491, 3536, 8153,28573,   49,   96,12442,  119,  240,28490,12443,28560,28561, 3111, 3580,
+28564, 3130, 7759,28567,28568,28569,  240,  444, 6209,28572, 3569, 6211,28575,28576,28577,  138,
+  778, 7760,28580, 7761, 7762,28583,28584,28585,  240,14319,28587,   96,28588,28589,  240,  119,
+  240,  240,  139,  968,28592, 1554, 3581,28595,28596,28597,   60,  971, 3560,28600, 3582, 7132,
+28603,28604,28605,  126,14332,28607,   96,28608,28609,  126,   49,  126,  126,  241, 1558,28612,
+ 1563, 6257,28615,28616,28617,  138, 1559, 7133,28620, 6220,28622,28623,28624,28625,  240,28626,
+28627,   96,28628,28629,  240,  119,  240,  240, 8152,28631,   61,28632,28633,  138,   61,  138,
+  138,28634,28635,   96,28636,28637,  240,  119,  240,  240,   49,   96,   96,  119,  240,  240,
+  119,  240,  240};
+Word16 mlt_sqvh_bitcount_category_6[32] = {
+ 1, 4, 4, 6, 4, 6, 6, 8, 4, 6, 6, 8, 6, 9, 8,10,
+ 4, 6, 7, 8, 6, 9, 8,11, 6, 9, 8,10, 8,10, 9,11};
+UWord16 mlt_sqvh_code_category_6[32] = {
+    1,    2,    4,    2,    5,   29,   24,  101,    3,   31,   28,  105,    3,    5,  102,  424,
+    1,   30,    0,  107,   27,  200,  103,  806,    1,    4,  104,  402,    3,  425,  213,  807};
+
+Word16 *table_of_bitcount_tables[NUM_CATEGORIES-1] = {
+mlt_sqvh_bitcount_category_0,
+mlt_sqvh_bitcount_category_1,
+mlt_sqvh_bitcount_category_2,
+mlt_sqvh_bitcount_category_3,
+mlt_sqvh_bitcount_category_4,
+mlt_sqvh_bitcount_category_5,
+mlt_sqvh_bitcount_category_6
+};
+
+
+UWord16 *table_of_code_tables[NUM_CATEGORIES-1] = {
+(UWord16 *)mlt_sqvh_code_category_0,
+(UWord16 *)mlt_sqvh_code_category_1,
+(UWord16 *)mlt_sqvh_code_category_2,
+(UWord16 *)mlt_sqvh_code_category_3,
+(UWord16 *)mlt_sqvh_code_category_4,
+(UWord16 *)mlt_sqvh_code_category_5,
+(UWord16 *)mlt_sqvh_code_category_6
+};
+
+Word16 mlt_decoder_tree_category_0[180][2] = {
+{   1,   0},{   2,   3},{   4,   5},{   6,   7},{   8,   9},{  -1, -14},{  10,  11},{  12,  13},
+{  14,  15},{  16,  17},{  18,  19},{ -15,  20},{  21,  22},{  23, -28},{  24,  -2},{  25,  26},
+{  27,  28},{  29,  30},{  31,  32},{ -29,  33},{ -16,  34},{  -3,  35},{  36,  37},{ -42,  38},
+{  39,  40},{  41,  42},{  43,  44},{ -17,  45},{ -43,  46},{  47,  48},{  -4,  49},{ -56,  50},
+{  51,  52},{  53,  54},{  55,  56},{ -57,  -5},{ -30,  57},{  58,  59},{ -18,  60},{  61, -70},
+{  62,  63},{  64,  -6},{  65,  66},{ -44,  67},{ -71,  68},{  69,  70},{ -19, -31},{ -84,  71},
+{  72,  73},{  74,  75},{  76,  77},{  -7,  78},{  79, -20},{  80,  81},{ -85,  82},{ -98,  83},
+{ -58,  84},{  85, -32},{ -99,  86},{  -8,  87},{  88,  89},{ -72, -45},{  90, -33},{  91,-112},
+{ -21,  92},{ -59,-113},{ -46,  93},{  -9,  94},{ -22,  95},{  96,  97},{  98,  99},{ -23, -86},
+{ 100, 101},{ -34, -73},{ 102,-126},{-127, -35},{ 103, -47},{ 104, 105},{ 106, 107},{-140,-100},
+{-114, -87},{ 108, 109},{ 110, 111},{-141, -60},{ 112, -48},{ 113, -24},{ -10, -61},{ 114,-101},
+{ 115, 116},{ -74, -36},{ 117,-128},{ 118, -62},{ 119, 120},{ -37, 121},{ -11, -49},{ -88, 122},
+{ 123,-115},{-154, -25},{-142, 124},{-155,-129},{ 125, -50},{ 126, 127},{ -76, -75},{ 128, 129},
+{ -63, -77},{-102, -39},{ -38, 130},{ -51, 131},{ -89,-116},{-117,-156},{ 132, -52},{ -78, 133},
+{ 134,-103},{ 135, 136},{-143, -65},{ 137, -64},{-130,-131},{ -90, 138},{-104, -91},{ -92, 139},
+{-169,-183},{ -26,-118},{ 140, 141},{-144, -66},{ -12, 142},{-168, 143},{-105,-157},{ 144,-182},
+{ 145, 146},{ -79, 147},{ -53,-170},{ 148, 149},{ -27,-145},{ 150, -80},{-106, -13},{-132, -67},
+{-158, -40},{-119, 151},{ 152,-107},{ 153, 154},{ -41,-184},{ 155, 156},{ -54, 157},{-171, 158},
+{ -94, 159},{-134,-146},{ -93,-133},{-159,-108},{ 160, -81},{ 161,-160},{ 162, -68},{-120,-122},
+{-172, 163},{ -55, -95},{ 164,-109},{-161, -82},{-173,-185},{ 165, -69},{-147,-186},{ 166, 167},
+{-121, -96},{ 168,-148},{-174, 169},{ 170,-136},{ -83, 171},{ 172, 173},{-135,-110},{-187, 174},
+{-149,-150},{ 175,-123},{-162,-163},{ -97,-175},{-188, 176},{ 177, 178},{ 179,-111},{-151,-124},
+{-137,-177},{-176,-125},{-164,-138},{-189,-190},};
+Word16 mlt_decoder_tree_category_1[93][2] = {
+{   1,   0},{   2,   3},{   4,   5},{   6,   7},{   8, -10},{  -1,   9},{  10,  11},{  12,  13},
+{ -11,  14},{  15,  16},{  17,  18},{ -20,  -2},{  19,  20},{ -21,  21},{  22,  23},{ -12,  24},
+{  25,  26},{  27,  28},{  29,  30},{ -30,  31},{ -31,  -3},{  32, -22},{  33, -13},{  34,  35},
+{  36,  37},{  38,  39},{  40,  -4},{ -41, -14},{  41, -40},{ -32,  42},{  43, -23},{  44,  45},
+{  46,  47},{  48,  -5},{ -51, -50},{ -42,  49},{ -33,  50},{ -15,  51},{  52,  53},{  54, -24},
+{  55, -43},{  56, -52},{  57, -61},{ -60,  58},{ -25,  59},{ -16, -34},{  -6,  60},{ -62,  61},
+{ -71,  62},{ -35,  -7},{  63, -72},{ -53, -17},{  64, -44},{ -26, -70},{  65, -45},{ -36,  66},
+{ -63,  67},{ -80, -54},{ -81,  68},{ -27,  69},{  70, -82},{ -18,  71},{  72, -55},{  73, -64},
+{  74, -73},{  75, -46},{ -37,  76},{ -91,  -8},{  -9,  77},{ -90, -83},{  78, -28},{  79, -56},
+{ -65, -38},{ -74,  80},{ -19, -57},{ -92,  81},{ -47, -48},{  82, -66},{  83, -29},{ -84,  84},
+{ -75, -85},{ -67, -93},{ -39,  85},{ -76,  86},{ -58,  87},{  88, -49},{ -94,  89},{  90, -68},
+{  91, -78},{ -86, -59},{ -77, -95},{  92, -69},{ -87, -96},};
+Word16 mlt_decoder_tree_category_2[47][2] = {
+{   1,   0},{   2,   3},{   4,   5},{   6,  -7},{  -1,   7},{  -8,   8},{   9,  10},{  11,  12},
+{  13, -14},{ -15,  -9},{  -2,  14},{  15,  16},{  17,  18},{  19, -16},{  20, -22},{ -10,  21},
+{ -21,  -3},{  22,  23},{  24,  25},{ -23, -17},{  26,  27},{  28, -29},{ -11, -28},{  29,  30},
+{  -4, -24},{ -30,  31},{  32, -18},{  33, -35},{ -36,  34},{ -31, -12},{  35, -25},{  -5, -37},
+{  36,  37},{ -42,  38},{ -19, -43},{ -32,  39},{ -13, -38},{ -26, -20},{  40,  -6},{ -44,  41},
+{  42, -39},{ -33, -45},{  43, -27},{  44, -46},{  45, -34},{ -40,  46},{ -41, -47},};
+Word16 mlt_decoder_tree_category_3[519][2] = {
+{   1,   2},{   3,   4},{   5,   0},{   6,   7},{   8,   9},{  10,  11},{  12,  13},{  14,  15},
+{  16,  17},{-125,  18},{  -1,  19},{  20,  21},{  22,  23},{  24,  25},{  -5, -25},{  26,  27},
+{  -6,-150},{  28,  29},{  30,  31},{  32,  33},{  34, -30},{  35,  36},{  37,  38},{  39, -31},
+{-126,-155},{  40,  41},{-156,  42},{  43,-130},{  44,-131},{-151, -26},{  45,  46},{-250,  47},
+{  48,  49},{  50,  51},{  52,-275},{  53,  54},{  -2,  -7},{  55,  56},{  57,  58},{  59,  60},
+{  61,  62},{  63,  64},{  65,  66},{  67,  68},{  69,  70},{  71, -50},{  72,-180},{  73,  74},
+{  75,  76},{  77, -55},{  78,-175},{  79, -36},{  80,  81},{ -35, -10},{  82,  83},{-280,  84},
+{ -11,  85},{  86, -32},{  87,  88},{  89,-161},{  90,-276},{  91,  92},{-281,  93},{  -8,  94},
+{  95,  96},{  97,-157},{-181,-400},{-132,  98},{-375,  99},{-160, 100},{-127, 101},{ -27, 102},
+{ 103,-251},{ -56, 104},{ 105,-256},{-300,  -3},{-152,-255},{ 106, 107},{ -37, 108},{-305, 109},
+{-176, 110},{-136, 111},{ -12, 112},{ 113, 114},{ 115,-135},{ 116, 117},{-162, 118},{ -16, -51},
+{-186, 119},{ 120, 121},{ 122, 123},{ -41, 124},{ -61, 125},{ 126, 127},{ 128, 129},{ 130, -60},
+{ 131, 132},{-306, 133},{ 134,-205},{-405, 135},{ 136, 137},{ 138, 139},{-185, 140},{ 141,-500},
+{ -15, 142},{ 143, -80},{ -75, -40},{-301, 144},{ 145, 146},{-200, 147},{ 148, 149},{ 150, 151},
+{ 152,-525},{ 153,-177},{-425, 154},{ 155, -13},{-430, 156},{ 157,-406},{ 158, 159},{-206,-380},
+{ 160, 161},{ 162, 163},{ 164,-182},{-137, 165},{-286, 166},{ 167,-401},{ 168, 169},{ -42, -33},
+{ 170,-166},{ -57,-325},{ 171,-187},{ -38, 172},{ 173, 174},{-165,-330},{  -4,-282},{ 175,-257},
+{-261,-311},{-376, 176},{ 177, 178},{ -28, 179},{ 180,  -9},{-285, 181},{ 182, 183},{ 184,-277},
+{ 185,-133},{-310, -81},{ -85, 186},{-158,-210},{ -17, 187},{ 188, 189},{ 190, -52},{-141, 191},
+{ 192,-128},{-191, -20},{ 193,-140},{ 194, 195},{-211,-260},{ 196, 197},{ 198, 199},{ 200, -66},
+{-201,-225},{-381, 201},{ 202, 203},{ 204, 205},{ 206, 207},{-163,-287},{ 208,-100},{ 209, 210},
+{ 211, 212},{ 213,-252},{-105, -76},{ 214, 215},{ 216, -21},{ -86, -62},{-307, 217},{ -65,-455},
+{-550, 218},{ 219, 220},{ 221, 222},{ 223, 224},{ 225,-230},{-142, 226},{-302,-426},{-431, 227},
+{ 228, 229},{ 230,-190},{-402, -46},{-153,-450},{-505, 231},{ 232, 233},{ 234, 235},{ 236, 237},
+{ 238, 239},{-262, -29},{ 240, 241},{ 242, 243},{-167, -67},{-331,-530},{ 244, 245},{ 246, 247},
+{ 248, 249},{ 250, 251},{ 252, 253},{ 254, 255},{ 256, 257},{ 258, 259},{ 260, 261},{ 262,-336},
+{ 263,-171},{-192,-207},{-258,-138},{ 264, 265},{ 266, 267},{ 268, 269},{ 270, 271},{ 272, 273},
+{ 274, -45},{-335,-411},{ -43, -18},{-265, -71},{-316,-326},{-350,-407},{-146, -14},{ 275, 276},
+{ 277, 278},{ 279, 280},{ 281,-216},{ -34,-283},{-291,-312},{-410,-168},{-555, 282},{ -70, -53},
+{-235, -87},{ -77,-183},{-315,-332},{-178, -58},{ 283, 284},{ 285, 286},{ 287, 288},{ 289, 290},
+{ 291, 292},{ 293, 294},{ 295, 296},{ 297, 298},{-202,-226},{-170,-267},{-134,-290},{-355,-385},
+{-386, -47},{-526,-196},{ 299, 300},{ 301, 302},{ 303, 304},{ 305, 306},{ 307, 308},{ 309, 310},
+{ 311, 312},{ 313, 314},{ 315, 316},{ 317, 318},{ 319, 320},{ 321, 322},{ 323, 324},{ 325,-111},
+{-231,-253},{ -91, -82},{-172,-145},{ -22,-317},{ -90,-356},{-382,-159},{ 326, 327},{ 328, 329},
+{ 330, 331},{ 332, 333},{ 334, 335},{-106,-263},{-278,-215},{-110, -39},{-101,-377},{-129, -63},
+{-436,-195},{-506,-531},{ 336,-212},{-154,-266},{ -59,-288},{-292,-303},{-337,-432},{-188,-451},
+{-456,-460},{-501,-236},{-551, 337},{ 338, 339},{ 340, 341},{ 342, 343},{ 344, 345},{ 346, 347},
+{ 348, 349},{ 350, 351},{ 352, 353},{ 354, 355},{ 356, 357},{ 358, 359},{ 360, 361},{ 362, 363},
+{ 364, 365},{ 366, 367},{ 368, 369},{ 370, 371},{ 372, 373},{ 374, 375},{ 376, 377},{ 378, 379},
+{ 380, 381},{ 382, 383},{ 384, 385},{ 386, 387},{ 388, 389},{ 390, 391},{ 392, 393},{ 394, 395},
+{ 396, 397},{ 398, 399},{ 400, 401},{ 402, 403},{ 404, 405},{ 406, 407},{ -72,-272},{-309,-333},
+{-340,-360},{ -68,-387},{-184,-416},{-427,-147},{-435,-437},{-115,-480},{-510,-532},{-164,-556},
+{ 408,-295},{-296,-297},{-107,-313},{-193,-173},{-320,-327},{-341,-351},{-352,-143},{-378, -19},
+{-403,-412},{-268, -54},{ -83,-441},{-442,-457},{-475, -44},{ -97,-511},{-515,-208},{-527,-528},
+{-237,-536},{-552, 409},{ 410, 411},{ 412, 413},{ 414, 415},{ 416, 417},{ 418, 419},{ 420, 421},
+{ 422, 423},{ 424, 425},{ 426, 427},{ 428, 429},{ 430, 431},{ 432, 433},{ 434, 435},{ 436, 437},
+{ 438, 439},{ 440, 441},{ 442, 443},{ 444, 445},{ 446, 447},{ 448, 449},{ 450, 451},{ 452, 453},
+{ 454, 455},{ 456, 457},{ 458, 459},{ 460, 461},{ 462, 463},{ 464, 465},{ 466, 467},{ 468, 469},
+{ 470, 471},{ 472, 473},{ 474, 475},{ 476, 477},{ 478, 479},{ 480, 481},{ 482, 483},{ 484, 485},
+{ 486, 487},{ 488, 489},{ 490, 491},{ 492, 493},{ 494, 495},{ 496, 497},{ 498, 499},{ 500, 501},
+{ 502, 503},{ 504, 505},{ 506, 507},{ 508, 509},{ 510, 511},{ 512, 513},{ 514, 515},{ 516, 517},
+{ 518,-104},{ -84,-218},{-318,-319},{-117,-321},{-322,-323},{-219,-174},{-243,-328},{-329, -94},
+{-228,-194},{-240,-334},{-102,-229},{-169,-338},{-339,-116},{-289,-342},{-343,-345},{-346,-347},
+{ -23,-203},{-214,-353},{-204,-220},{-357,-358},{-264,-361},{-362,-363},{-365,-366},{-367, -92},
+{-245,-121},{-293,-379},{-108,-232},{-221,-383},{-384,-233},{-294,-241},{-388,-389},{-390,-391},
+{-392,-393},{-394,-395},{-396,-397},{-398, -24},{-109,-149},{-242,-404},{ -64, -79},{ -89,-408},
+{-409,-213},{-120,-113},{-413,-414},{-415, -96},{-417,-418},{-419,-420},{-421,-422},{-423,-298},
+{ -69,-269},{-428,-429},{ -78,-270},{ -88,-433},{-434,-271},{-234,-259},{-438,-439},{-440,-227},
+{-179,-443},{-445,-446},{-447,-223},{-238,-452},{-453,-454},{-273,-254},{-246,-458},{-459, -48},
+{-461,-462},{-463,-465},{-466,-467},{-468,-470},{-471,-304},{-476,-477},{-478,-112},{-481,-482},
+{-483,-485},{-486,-487},{-490,-491},{-103,-118},{-502,-503},{-504,-189},{ -93,-507},{-508,-509},
+{-148,-139},{-512,-513},{-308,-516},{-517,-518},{-520,-521},{ -73, -98},{ -95, -49},{-529,-222},
+{-217,-197},{-533,-534},{-535,-284},{-537,-538},{-540,-541},{-542,-543},{-545,-546},{-144,-198},
+{-314,-553},{-209,-279},{-557,-558},{-560,-561},{-562,-563},{-565,-566},{-567,-575},{-576,-577},
+{-578,-580},{-581,-582},{-583,-585},{-586,-587},{-590,-591},{-600,-601},{-605,-606},};
+Word16 mlt_decoder_tree_category_4[208][2] = {
+{   1,   2},{   3,   0},{   4,   5},{   6,   7},{   8,   9},{  10,  11},{  12, -64},{  -1,  13},
+{  14, -16},{  -4,  15},{  16,  17},{  18, -80},{  -5,  19},{  20,  21},{ -20,  22},{  23, -65},
+{ -84, -21},{ -68,  24},{ -17,  25},{  26,  27},{  28, -81},{ -69, -85},{  29,  30},{  31,  32},
+{-128,  33},{  34,  35},{  -2,  36},{  37,  38},{-144,  39},{  40,  -6},{  41,  42},{ -32,  43},
+{  44,  -8},{  45, -25},{ -96,  46},{  47,-100},{  -9,  48},{  49, -36},{  50, -24},{  51,  52},
+{  53,-148},{  54,  55},{ -22,  56},{  57,  58},{-132, -89},{  59,  60},{-101,  61},{ -37,  62},
+{ -18,  63},{ -88,-129},{ -66, -70},{ -97,  64},{ -72, -73},{  65,-145},{-149, -86},{  66, -33},
+{  67,-133},{  68,  69},{  70,  71},{-192,  72},{  73,-160},{ -82,  74},{-164,  75},{ -10,  76},
+{  77,-208},{  78, -40},{  79,  80},{  -3,  81},{  -7,  82},{  83,  84},{-104,  85},{  86, -26},
+{  87,-105},{  88,-112},{  89,  90},{  91, -41},{  92,  93},{  94,  95},{ -48,  96},{ -90,  97},
+{  98, -28},{ -52,  99},{ -12, 100},{ 101, -74},{ -13,-116},{-161, 102},{ 103, -29},{-102, 104},
+{-152,-165},{ 105, 106},{ 107, 108},{ 109, 110},{ 111,-212},{ 112, 113},{-136, 114},{ 115,-137},
+{ 116, -23},{ -19,-153},{ -98,-134},{-196, 117},{ 118, 119},{ -38,-193},{-113,-150},{-209, 120},
+{ 121, -93},{ -83, 122},{ 123, 124},{ 125, 126},{ 127, 128},{ 129, 130},{ 131, -34},{-146, -53},
+{ 132, 133},{ 134, 135},{ 136, 137},{ 138,-130},{ -49, 139},{ 140, 141},{-117, -42},{ -67, -92},
+{ 142, -87},{ -77,-197},{ -71, 143},{ 144, 145},{ 146, 147},{ 148, 149},{ 150, 151},{ 152, 153},
+{ 154, 155},{ 156, 157},{ 158, 159},{ 160, 161},{ 162, 163},{ 164, 165},{ 166, 167},{ 168, 169},
+{-108, -76},{-168,-169},{-176, -44},{-224, -56},{ -45,-180},{ -11,-106},{-213, 170},{ 171, 172},
+{ 173, 174},{ 175, 176},{ 177, 178},{ 179, 180},{ 181, 182},{ 183, 184},{ 185, 186},{ 187, 188},
+{ 189, 190},{ 191, 192},{ 193, 194},{ 195, 196},{ 197, 198},{ 199, 200},{ 201, 202},{ 203, 204},
+{ 205, 206},{ 207,-131},{ -30, -27},{ -43,-151},{ -75,-154},{-156,-162},{-109,-194},{-198,-201},
+{-114,-225},{-228,-229},{-141,-142},{ -94,-124},{ -95,-147},{-115,-125},{ -54, -55},{-107, -58},
+{ -39,-155},{-121,-157},{-158,-103},{ -14,-122},{-163, -51},{ -57,-166},{-167, -46},{-110,-170},
+{-172,-173},{ -61,-177},{-178, -99},{-181,-182},{-184,-185},{-118, -35},{ -15,-195},{ -31, -60},
+{-135,-199},{-200, -79},{-202,-204},{-205,-119},{ -91,-210},{-211, -78},{-120,-214},{-215,-216},
+{-217,-218},{-220,-221},{ -50,-138},{-226,-139},{-140,-230},{-232,-233},{-240,-241},{-244,-245},
+};
+Word16 mlt_decoder_tree_category_5[191][2] = {
+{   1,   2},{   0,   3},{   4,   5},{   6,   7},{   8,   9},{  10,  11},{ -81,  -1},{  12,  13},
+{  14, -27},{  -3,  -9},{  15,  16},{  17,  18},{  19,  20},{-108,  21},{  -4,  22},{  23, -36},
+{ -12,  24},{ -82,  25},{  26, -84},{  27, -90},{ -10, -30},{  28,  29},{  30, -28},{  31,-117},
+{ -13,  32},{ -39,  33},{  34,-109},{  35, -93},{ -85,-111},{ -37,  36},{ -31,  37},{ -91,  38},
+{  39,  40},{ -40,-120},{  41,  42},{-118,  43},{ -94,  44},{-112,-162},{  45,  46},{  -2,  47},
+{  48,  49},{-121,-189},{  50, -54},{  51,  52},{  53, -18},{  54,  55},{  -6,  56},{  57,  -5},
+{-135,  58},{  59,  60},{  61,  62},{ -63,  63},{  64,  -7},{ -15,  65},{  66,  67},{ -45,  68},
+{  69,  70},{  71, -21},{  72,  73},{  74,  75},{  76,  77},{-163,  78},{  79,-171},{-144,  80},
+{ -48,  81},{ -57,  82},{  83,  84},{-165,  85},{ -16,-198},{  86,  87},{ -11,  88},{  89, -99},
+{  90, -83},{ -19,  91},{  92,  93},{  94,  95},{  96,  97},{  98,  99},{ -87, 100},{ 101, 102},
+{-190, -66},{ -33,-192},{ 103, 104},{ 105, 106},{-102, -42},{ 107,-126},{ 108, -29},{-129, -46},
+{ -86, -14},{-114, -32},{-172, 109},{ 110, -58},{ -34,-138},{ 111, 112},{ 113, 114},{ 115, 116},
+{ 117, 118},{ 119, 120},{-127,-166},{-174, 121},{ 122, 123},{ 124, 125},{ -88, -96},{ 126,-100},
+{ -38,-110},{ -22,-136},{ -55,-139},{-201, 127},{ -64,-193},{ 128, -49},{-175,-199},{ 129, 130},
+{ 131, 132},{ 133, 134},{ 135, 136},{ 137, 138},{ 139, 140},{ 141, 142},{ 143, 144},{ 145, 146},
+{ 147, 148},{ 149, 150},{-103, -92},{ -43,-130},{-145,-147},{-148, -41},{-216,-115},{-119,-123},
+{ -95, 151},{ 152, 153},{ 154, 155},{ 156, 157},{ 158, 159},{ 160, 161},{ 162, 163},{ 164, 165},
+{ 166, 167},{ 168, 169},{ 170, 171},{ 172, 173},{ 174, 175},{ 176, 177},{ 178, 179},{ 180, 181},
+{ 182, 183},{ 184, 185},{ 186, 187},{ 188, 189},{ 190,-153},{-180,  -8},{ -97, -24},{-122,-113},
+{-124,-125},{ -67, -44},{-128, -69},{-106,-131},{-132,-133},{ -61, -73},{-137,-116},{ -89,-140},
+{-141,-142},{ -23, -25},{-146, -17},{-104,-149},{-150,-151},{ -52,-154},{-156,-157},{ -76, -70},
+{-164, -51},{ -72,-167},{-168,-169},{ -47, -20},{-173, -59},{-101,-176},{-177,-178},{ -68,-181},
+{-183,-184},{ -35, -60},{-191, -98},{ -56,-194},{-195,-196},{ -75, -65},{-200,-105},{-202,-203},
+{-204,-205},{-207,-208},{-210,-211},{ -50,-217},{-219,-220},{-225,-226},{-228,-229},};
+Word16 mlt_decoder_tree_category_6[31][2] = {
+{   1,   0},{   2,   3},{   4,   5},{   6,   7},{   8, -16},{  -1,  -8},{  -2,  -4},{   9,  10},
+{  11,  12},{  13,  14},{  15,  16},{  17, -24},{  -3, -12},{  -6,  18},{  19, -20},{ -10,  -5},
+{ -17,  -9},{ -18,  20},{  21,  22},{  23,  24},{  25, -28},{  26,  -7},{ -14, -22},{ -26, -11},
+{  27, -19},{ -25, -13},{ -21,  28},{  29, -30},{ -27,  30},{ -15, -29},{ -23, -31},};
+
+Word16 *table_of_decoder_tables[NUM_CATEGORIES-1] = {
+(Word16 *)mlt_decoder_tree_category_0,
+(Word16 *)mlt_decoder_tree_category_1,
+(Word16 *)mlt_decoder_tree_category_2,
+(Word16 *)mlt_decoder_tree_category_3,
+(Word16 *)mlt_decoder_tree_category_4,
+(Word16 *)mlt_decoder_tree_category_5,
+(Word16 *)mlt_decoder_tree_category_6,
+};
+
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/common/huff_tab.h b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/common/huff_tab.h
new file mode 100644
index 0000000..5ccd650
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/common/huff_tab.h
@@ -0,0 +1,42 @@
+/***********************************************************************
+**
+**   ITU-T G.722.1 (2005-05) - Fixed point implementation for main body and Annex C
+**   > Software Release 2.1 (2008-06)
+**     (Simple repackaging; no change from 2005-05 Release 2.0 code)
+**
+**   � 2004 Polycom, Inc.
+**
+**   All rights reserved.
+**
+***********************************************************************/
+
+extern Word16  differential_region_power_bits[MAX_NUMBER_OF_REGIONS][DIFF_REGION_POWER_LEVELS];
+extern UWord16 differential_region_power_codes[MAX_NUMBER_OF_REGIONS][DIFF_REGION_POWER_LEVELS];
+extern Word16  differential_region_power_decoder_tree[MAX_NUMBER_OF_REGIONS][DIFF_REGION_POWER_LEVELS-1][2];
+extern Word16  mlt_quant_centroid[NUM_CATEGORIES][MAX_NUM_BINS];
+extern Word16  expected_bits_table[NUM_CATEGORIES];
+extern Word16  mlt_sqvh_bitcount_category_0[196];
+extern UWord16 mlt_sqvh_code_category_0[196];
+extern Word16  mlt_sqvh_bitcount_category_1[100];
+extern UWord16 mlt_sqvh_code_category_1[100];
+extern Word16  mlt_sqvh_bitcount_category_2[49];
+extern UWord16 mlt_sqvh_code_category_2[49];
+extern Word16  mlt_sqvh_bitcount_category_3[625];
+extern UWord16 mlt_sqvh_code_category_3[625];
+extern Word16  mlt_sqvh_bitcount_category_4[256];
+extern UWord16 mlt_sqvh_code_category_4[256];
+extern Word16  mlt_sqvh_bitcount_category_5[243];
+extern UWord16 mlt_sqvh_code_category_5[243];
+extern Word16  mlt_sqvh_bitcount_category_6[32];
+extern UWord16 mlt_sqvh_code_category_6[32];
+extern Word16  *table_of_bitcount_tables[NUM_CATEGORIES-1];
+extern UWord16 *table_of_code_tables[NUM_CATEGORIES-1];
+extern Word16  mlt_decoder_tree_category_0[180][2];
+extern Word16  mlt_decoder_tree_category_1[93][2];
+extern Word16  mlt_decoder_tree_category_2[47][2];
+extern Word16  mlt_decoder_tree_category_3[519][2];
+extern Word16  mlt_decoder_tree_category_4[208][2];
+extern Word16  mlt_decoder_tree_category_5[191][2];
+extern Word16  mlt_decoder_tree_category_6[31][2];
+extern Word16  *table_of_decoder_tables[NUM_CATEGORIES-1];
+
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/common/tables.c b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/common/tables.c
new file mode 100644
index 0000000..1018e64
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/common/tables.c
@@ -0,0 +1,298 @@
+/****************************************************************************
+**
+**   ITU-T G.722.1 (2005-05) - Fixed point implementation for main body and Annex C
+**   > Software Release 2.1 (2008-06)
+**     (Simple repackaging; no change from 2005-05 Release 2.0 code)
+**
+**   � 2004 Polycom, Inc.
+**
+**   All rights reserved.
+**
+****************************************************************************/
+
+/****************************************************************************
+  Filename:    tables.c    
+
+  Purpose:     Contains tables used by G.722.1 Annex C
+		
+  Design Notes:
+
+****************************************************************************/
+
+/***************************************************************************
+ Include files                                                           
+***************************************************************************/
+#include "defs.h"
+
+Word16 int_region_standard_deviation_table[REGION_POWER_TABLE_SIZE] = {
+    0,     0,   0, 0, 0, 0, 0, 0, 0, 0,
+    0,     0,   0, 0, 0, 0, 0, 0, 0, 0,
+    0,     0,   1, 1, 1, 1, 2, 3, 4, 6,
+    8,    11,   16, 23, 32, 45, 64, 91, 128, 181,
+  256,   362,  512, 724, 1024, 1448, 2048, 2896, 4096, 5793,
+ 8192, 11585, 16384, 23170, 0,0,0,0,0,0,
+ 0,0,0,0};
+
+Word16 standard_deviation_inverse_table[REGION_POWER_TABLE_SIZE] = {
+  32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767,
+  32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767,
+  32767, 32767, 32767, 32767, 32767, 23170, 16384, 11585, 8192, 5793,
+  4096, 2896, 2048, 1448, 1024, 724, 512, 362, 256, 181,
+  128, 91, 64, 45, 32, 23, 16, 11, 8, 6,
+  4, 3, 2, 1, 1, 1, 1, 0, 0, 0,
+  0, 0, 0, 0};
+
+
+Word16 step_size_inverse_table[NUM_CATEGORIES]={
+	23167,16384,11585,8192,5793,4096,2896,2896
+};
+ 
+
+Word16 vector_dimension[NUM_CATEGORIES] =  { 2, 2, 2, 4, 4, 5, 5, 1};
+Word16 number_of_vectors[NUM_CATEGORIES] = {10,10,10, 5, 5, 4, 4,20};
+/* The last category isn't really coded with scalar quantization. */
+
+Word16 max_bin[NUM_CATEGORIES] = {13, 9, 6, 4, 3, 2, 1, 1};
+
+Word16 max_bin_plus_one_inverse[NUM_CATEGORIES] = 
+{
+	2341,3277,4682,6554,8193,10923,16385,16385
+};
+
+/*
+ * Release 1.2.
+ * Add new version of int_dead_zone[] to go with
+ * changes to vector_huffman() in encoder.c.
+ * 
+ */
+
+/************** See new version of table below
+Word16 int_dead_zone[NUM_CATEGORIES]=
+{
+	9830,10813,11796,12780,13763,14746,16384,16384
+};
+***************/
+
+/******** New version of table added in Release 1.2 ********/
+Word16 int_dead_zone[NUM_CATEGORIES]=         
+{
+2457, 2703, 2949, 3195, 3440, 3686, 4096, 4096
+};
+
+ 
+/*
+ * Release 1.2.
+ * Added this new table to go with
+ * changes to vector_huffman() in encoder.c,
+ * accompanies the new table for int_dead_zone[].
+ */
+
+Word16 int_dead_zone_low_bits[NUM_CATEGORIES]=
+{
+2, 1, 0, 0, 3, 2, 0, 0
+};
+
+
+Word16 samples_to_rmlt_window[DCT_LENGTH]=
+{   44,   134,   224,   314,   404,   494,   584,   674,   764,   853,
+   943,  1033,  1123,  1213,  1302,  1392,  1482,  1571,  1661,  1750,
+  1840,  1929,  2019,  2108,  2197,  2286,  2376,  2465,  2554,  2643,
+  2732,  2821,  2909,  2998,  3087,  3175,  3264,  3352,  3441,  3529,
+  3617,  3705,  3793,  3881,  3969,  4057,  4144,  4232,  4319,  4407,
+  4494,  4581,  4668,  4755,  4842,  4928,  5015,  5101,  5188,  5274,
+  5360,  5446,  5532,  5617,  5703,  5788,  5873,  5959,  6043,  6128,
+  6213,  6297,  6382,  6466,  6550,  6634,  6718,  6801,  6885,  6968,
+  7051,  7134,  7217,  7299,  7382,  7464,  7546,  7628,  7709,  7791,
+  7872,  7953,  8034,  8115,  8195,  8276,  8356,  8436,  8515,  8595,
+  8674,  8753,  8832,  8911,  8989,  9068,  9146,  9223,  9301,  9378,
+  9455,  9532,  9609,  9685,  9762,  9838,  9913,  9989, 10064, 10139,
+ 10214, 10288, 10363, 10437, 10510, 10584, 10657, 10730, 10803, 10875,
+ 10948, 11020, 11091, 11163, 11234, 11305, 11375, 11446, 11516, 11586,
+ 11655, 11724, 11793, 11862, 11930, 11998, 12066, 12134, 12201, 12268,
+ 12334, 12401, 12467, 12532, 12598, 12663, 12728, 12792, 12857, 12920,
+ 12984, 13047, 13110, 13173, 13235, 13297, 13359, 13420, 13481, 13542,
+ 13602, 13662, 13722, 13782, 13841, 13899, 13958, 14016, 14074, 14131,
+ 14188, 14245, 14301, 14357, 14413, 14468, 14523, 14578, 14632, 14686,
+ 14739, 14793, 14845, 14898, 14950, 15002, 15053, 15104, 15155, 15205,
+ 15255, 15305, 15354, 15403, 15451, 15500, 15547, 15595, 15642, 15688,
+ 15734, 15780, 15826, 15871, 15916, 15960, 16004, 16047, 16091, 16133,
+ 16176, 16218, 16259, 16300, 16341, 16382, 16422, 16461, 16501, 16540,
+ 16578, 16616, 16654, 16691, 16728, 16764, 16800, 16836, 16871, 16906,
+ 16940, 16974, 17008, 17041, 17074, 17106, 17138, 17170, 17201, 17232,
+ 17262, 17292, 17321, 17350, 17379, 17407, 17435, 17462, 17489, 17516,
+ 17542, 17567, 17593, 17617, 17642, 17666, 17689, 17713, 17735, 17758,
+ 17779, 17801, 17822, 17842, 17863, 17882, 17901, 17920, 17939, 17957,
+ 17974, 17991, 18008, 18024, 18040, 18055, 18070, 18085, 18099, 18113,
+ 18126, 18139, 18151, 18163, 18174, 18185, 18196, 18206, 18216, 18225,
+ 18234, 18242, 18250, 18257, 18265, 18271, 18277, 18283, 18288, 18293,
+ 18298, 18302, 18305, 18308, 18311, 18313, 18315, 18316, 18317, 18317,
+};
+
+Word16 rmlt_to_samples_window[DCT_LENGTH]=
+{  44,    133,   222,   310,   399,   488,   577,   666,   754,   843,
+   932,   1020,  1109,  1198,  1286,  1375,  1464,  1552,  1641,  1729,
+   1817,  1906,  1994,  2082,  2171,  2259,  2347,  2435,  2523,  2611,
+   2699,  2786,  2874,  2962,  3049,  3137,  3224,  3312,  3399,  3486,
+   3573,  3660,  3747,  3834,  3921,  4008,  4094,  4181,  4267,  4353,
+   4439,  4526,  4611,  4697,  4783,  4869,  4954,  5040,  5125,  5210,
+   5295,  5380,  5465,  5549,  5634,  5718,  5802,  5886,  5970,  6054,
+   6138,  6221,  6304,  6388,  6471,  6553,  6636,  6719,  6801,  6883,
+   6965,  7047,  7129,  7211,  7292,  7373,  7454,  7535,  7616,  7696,
+   7777,  7857,  7937,  8016,  8096,  8175,  8254,  8333,  8412,  8491,
+   8569,  8647,  8725,  8803,  8880,  8957,  9035,  9111,  9188,  9264,
+   9341,  9417,  9492,  9568,  9643,  9718,  9793,  9868,  9942, 10016,
+  10090, 10163, 10237, 10310, 10383, 10455, 10528, 10600, 10672, 10743,
+  10815, 10886, 10957, 11027, 11098, 11168, 11237, 11307, 11376, 11445,
+  11514, 11582, 11650, 11718, 11785, 11853, 11920, 11986, 12053, 12119,
+  12185, 12250, 12315, 12380, 12445, 12509, 12573, 12637, 12701, 12764,
+  12826, 12889, 12951, 13013, 13075, 13136, 13197, 13257, 13318, 13378,
+  13437, 13497, 13556, 13614, 13673, 13731, 13788, 13846, 13903, 13959,
+  14016, 14072, 14128, 14183, 14238, 14292, 14347, 14401, 14454, 14508,
+  14561, 14613, 14665, 14717, 14769, 14820, 14871, 14921, 14971, 15021,
+  15070, 15119, 15168, 15216, 15264, 15311, 15359, 15405, 15452, 15498,
+  15544, 15589, 15634, 15678, 15722, 15766, 15810, 15853, 15895, 15938,
+  15979, 16021, 16062, 16103, 16143, 16183, 16223, 16262, 16300, 16339,
+  16377, 16414, 16452, 16488, 16525, 16561, 16596, 16632, 16666, 16701,
+  16735, 16768, 16801, 16834, 16867, 16899, 16930, 16961, 16992, 17022,
+  17052, 17082, 17111, 17140, 17168, 17196, 17223, 17250, 17277, 17303,
+  17329, 17354, 17379, 17404, 17428, 17452, 17475, 17498, 17520, 17542,
+  17564, 17585, 17606, 17626, 17646, 17665, 17684, 17703, 17721, 17739,
+  17756, 17773, 17790, 17806, 17821, 17836, 17851, 17865, 17879, 17893,
+  17906, 17918, 17931, 17942, 17954, 17965, 17975, 17985, 17995, 18004,
+  18012, 18021, 18028, 18036, 18043, 18049, 18055, 18061, 18066, 18071,
+  18076, 18079, 18083, 18086, 18089, 18091, 18093, 18094, 18095, 18095,
+};
+
+Word16 max_samples_to_rmlt_window[MAX_DCT_LENGTH]={
+0,		43,		89,		133,	178,	222,	268,	314,	357,	403,
+447,	493,	538,	582,	628,	671,	717,	763,	807,	853,
+896,	942,	987,	1031,	1077,	1121,	1166,	1212,	1256,	1301,
+1345,	1390,	1436,	1480,	1526,	1569,	1615,	1660,	1704,	1749,
+1793,	1838,	1884,	1928,	1973,	2016,	2062,	2107,	2151,	2196,
+2239,	2285,	2331,	2374,	2419,	2463,	2508,	2553,	2597,	2642,
+2685,	2730,	2776,	2819,	2864,	2908,	2952,	2998,	3041,	3086,
+3129,	3174,	3219,	3263,	3307,	3350,	3396,	3440,	3483,	3528,
+3571,	3616,	3661,	3704,	3748,	3791,	3836,	3881,	3923,	3968,
+4011,	4055,	4100,	4143,	4187,	4230,	4274,	4318,	4362,	4406,
+4448,	4493,	4537,	4580,	4624,	4666,	4710,	4755,	4797,	4841,
+4883,	4927,	4971,	5013,	5057,	5099,	5144,	5187,	5229,	5273,
+5315,	5359,	5402,	5444,	5488,	5530,	5573,	5617,	5658,	5702,
+5743,	5787,	5830,	5871,	5915,	5956,	6000,	6043,	6084,	6127,
+6169,	6211,	6254,	6296,	6339,	6380,	6423,	6465,	6507,	6549,
+6590,	6633,	6675,	6716,	6759,	6799,	6842,	6884,	6925,	6967,
+7007,	7050,	7092,	7132,	7175,	7215,	7257,	7299,	7339,	7381,
+7421,	7462,	7504,	7544,	7586,	7626,	7667,	7709,	7749,	7790,
+7830,	7871,	7912,	7952,	7993,	8032,	8073,	8114,	8153,	8194,
+8234,	8275,	8315,	8355,	8395,	8434,	8474,	8515,	8554,	8594,
+8632,	8673,	8713,	8752,	8792,	8830,	8871,	8910,	8949,	8989,
+9027,	9066,	9106,	9144,	9184,	9221,	9261,	9300,	9338,	9378,
+9415,	9454,	9493,	9531,	9570,	9607,	9646,	9685,	9722,	9761,
+9798,	9836,	9875,	9912,	9950,	9987,	10025,	10064,	10100,	10138,
+10175,	10213,	10250,	10287,	10325,	10361,	10398,	10436,	10472,	10510,
+10545,	10583,	10620,	10656,	10692,	10728,	10766,	10803,	10838,	10874,
+10910,	10947,	10983,	11018,	11055,	11089,	11126,	11162,	11197,	11233,
+11268,	11303,	11340,	11374,	11410,	11444,	11480,	11515,	11549,	11585,
+11619,	11654,	11689,	11723,	11758,	11791,	11826,	11861,	11895,	11930,
+11963,	11997,	12032,	12065,	12099,	12132,	12166,	12201,	12233,	12267,
+12300,	12333,	12367,	12400,	12433,	12465,	12499,	12532,	12563,	12597,
+12629,	12662,	12695,	12727,	12759,	12790,	12823,	12856,	12887,	12920,
+12951,	12983,	13016,	13046,	13078,	13109,	13141,	13173,	13203,	13235,
+13266,	13296,	13328,	13358,	13389,	13419,	13450,	13481,	13510,	13541,
+13571,	13602,	13632,	13661,	13692,	13721,	13751,	13781,	13810,	13840,
+13869,	13898,	13929,	13957,	13986,	14015,	14044,	14073,	14101,	14130,
+14158,	14187,	14216,	14244,	14272,	14300,	14328,	14357,	14384,	14412,
+14439,	14468,	14495,	14522,	14550,	14577,	14604,	14632,	14658,	14686,
+14711,	14739,	14765,	14792,	14819,	14844,	14871,	14897,	14923,	14949,
+14975,	15001,	15027,	15053,	15079,	15103,	15129,	15155,	15180,	15205,
+15229,	15255,	15280,	15304,	15329,	15353,	15378,	15403,	15426,	15451,
+15475,	15499,	15523,	15546,	15570,	15594,	15618,	15641,	15664,	15688,
+15711,	15734,	15757,	15780,	15802,	15825,	15848,	15871,	15892,	15915,
+15937,	15960,	15982,	16003,	16026,	16047,	16069,	16090,	16112,	16133,
+16154,	16175,	16197,	16217,	16239,	16259,	16279,	16301,	16320,	16341,
+16361,	16382,	16402,	16421,	16441,	16461,	16481,	16501,	16520,	16539,
+16558,	16578,	16597,	16615,	16635,	16653,	16672,	16691,	16709,	16728,
+16746,	16764,	16782,	16800,	16818,	16835,	16853,	16871,	16888,	16905,
+16923,	16940,	16957,	16974,	16991,	17008,	17024,	17041,	17057,	17074,
+17090,	17106,	17122,	17138,	17154,	17169,	17185,	17201,	17216,	17231,
+17246,	17262,	17277,	17291,	17306,	17321,	17336,	17350,	17364,	17379,
+17393,	17407,	17421,	17435,	17449,	17462,	17476,	17490,	17502,	17515,
+17528,	17542,	17554,	17567,	17580,	17592,	17605,	17618,	17629,	17642,
+17653,	17666,	17678,	17689,	17701,	17712,	17724,	17736,	17746,	17757,
+17768,	17779,	17790,	17800,	17811,	17822,	17832,	17842,	17852,	17862,
+17872,	17882,	17892,	17902,	17911,	17920,	17930,	17938,	17947,	17956,
+17965,	17974,	17983,	17991,	17999,	18008,	18016,	18025,	18032,	18040,
+18047,	18055,	18063,	18070,	18078,	18085,	18092,	18099,	18106,	18112,
+18119,	18126,	18132,	18138,	18144,	18151,	18157,	18163,	18168,	18174,
+18179,	18185,	18191,	18196,	18201,	18206,	18211,	18216,	18220,	18225,
+18229,	18234,	18238,	18242,	18246,	18250,	18254,	18257,	18260,	18264,
+18268,	18271,	18274,	18277,	18280,	18283,	18286,	18288,	18291,	18293,
+18295,	18297,	18300,	18301,	18303,	18305,	18306,	18308,	18309,	18311,
+18312,	18312,	18314,	18315,	18315,	18316,	18316,	18317,	18317,	18317
+};
+
+Word16 max_rmlt_to_samples_window[MAX_DCT_LENGTH]={
+0,		43,		88,		131,	176,	219,	265,	310,	353,	398,
+442,	487,	532,	575,	620,	663,	709,	754,	797,	842,
+885,	931,	975,	1019,	1064,	1107,	1152,	1197,	1240,	1286,
+1329,	1373,	1419,	1462,	1507,	1550,	1595,	1640,	1683,	1728,
+1771,	1816,	1861,	1904,	1949,	1992,	2037,	2081,	2125,	2170,
+2212,	2258,	2302,	2345,	2390,	2433,	2477,	2522,	2565,	2610,
+2652,	2697,	2742,	2784,	2829,	2872,	2916,	2961,	3004,	3048,
+3091,	3136,	3180,	3223,	3267,	3310,	3354,	3399,	3441,	3485,
+3528,	3572,	3616,	3659,	3703,	3745,	3790,	3834,	3876,	3920,
+3962,	4006,	4050,	4093,	4136,	4179,	4222,	4266,	4309,	4352,
+4394,	4438,	4482,	4524,	4568,	4610,	4653,	4697,	4739,	4782,
+4824,	4867,	4911,	4953,	4996,	5038,	5081,	5124,	5166,	5209,
+5251,	5294,	5337,	5378,	5421,	5463,	5506,	5548,	5590,	5633,
+5674,	5717,	5759,	5800,	5843,	5884,	5927,	5970,	6011,	6053,
+6094,	6136,	6178,	6219,	6262,	6302,	6345,	6387,	6428,	6470,
+6510,	6552,	6594,	6635,	6677,	6717,	6759,	6801,	6841,	6883,
+6922,	6964,	7006,	7046,	7087,	7127,	7169,	7210,	7250,	7291,
+7331,	7372,	7413,	7453,	7494,	7533,	7574,	7615,	7655,	7695,
+7735,	7776,	7816,	7855,	7896,	7935,	7975,	8016,	8054,	8095,
+8134,	8174,	8214,	8253,	8293,	8332,	8371,	8412,	8450,	8490,
+8528,	8568,	8607,	8646,	8685,	8723,	8763,	8802,	8840,	8879,
+8917,	8956,	8995,	9033,	9072,	9109,	9148,	9187,	9225,	9264,
+9301,	9340,	9378,	9415,	9454,	9491,	9529,	9567,	9604,	9642,
+9679,	9717,	9755,	9791,	9829,	9866,	9903,	9941,	9977,	10015,
+10051,	10089,	10126,	10162,	10199,	10235,	10272,	10309,	10345,	10382,
+10417,	10454,	10491,	10526,	10563,	10598,	10635,	10672,	10706,	10742,
+10778,	10814,	10850,	10885,	10921,	10955,	10991,	11027,	11061,	11097,
+11131,	11166,	11202,	11236,	11271,	11305,	11340,	11376,	11409,	11444,
+11478,	11513,	11547,	11580,	11615,	11648,	11683,	11717,	11751,	11785,
+11817,	11852,	11886,	11918,	11952,	11985,	12018,	12053,	12085,	12118,
+12150,	12184,	12217,	12249,	12282,	12314,	12347,	12380,	12411,	12444,
+12476,	12508,	12541,	12572,	12604,	12635,	12668,	12700,	12731,	12763,
+12794,	12826,	12858,	12888,	12920,	12950,	12982,	13013,	13043,	13074,
+13105,	13135,	13166,	13196,	13227,	13257,	13287,	13317,	13347,	13377,
+13407,	13437,	13467,	13496,	13525,	13555,	13585,	13614,	13643,	13672,
+13701,	13730,	13760,	13787,	13817,	13845,	13873,	13903,	13930,	13959,
+13987,	14015,	14043,	14071,	14099,	14126,	14154,	14183,	14209,	14237,
+14264,	14292,	14319,	14346,	14373,	14400,	14427,	14454,	14480,	14507,
+14533,	14560,	14586,	14612,	14639,	14664,	14691,	14717,	14742,	14768,
+14793,	14819,	14845,	14870,	14896,	14920,	14945,	14971,	14996,	15020,
+15044,	15070,	15094,	15118,	15143,	15167,	15192,	15216,	15239,	15263,
+15287,	15311,	15335,	15358,	15382,	15405,	15428,	15452,	15474,	15498,
+15520,	15543,	15566,	15588,	15611,	15633,	15656,	15678,	15700,	15722,
+15744,	15766,	15788,	15809,	15831,	15852,	15874,	15895,	15916,	15937,
+15958,	15979,	16000,	16020,	16041,	16061,	16082,	16103,	16122,	16143,
+16162,	16183,	16203,	16222,	16242,	16261,	16281,	16300,	16319,	16339,
+16357,	16377,	16396,	16414,	16433,	16451,	16470,	16488,	16506,	16525,
+16542,	16561,	16579,	16596,	16614,	16631,	16649,	16667,	16683,	16700,
+16717,	16735,	16752,	16768,	16785,	16801,	16818,	16834,	16850,	16867,
+16883,	16899,	16915,	16930,	16945,	16961,	16977,	16992,	17007,	17022,
+17037,	17052,	17067,	17081,	17096,	17111,	17126,	17140,	17154,	17168,
+17182,	17196,	17209,	17223,	17237,	17250,	17264,	17277,	17290,	17303,
+17315,	17329,	17341,	17354,	17367,	17379,	17391,	17404,	17415,	17428,
+17439,	17451,	17463,	17475,	17486,	17497,	17509,	17520,	17531,	17542,
+17552,	17563,	17574,	17584,	17595,	17605,	17616,	17626,	17636,	17646,
+17655,	17665,	17675,	17684,	17694,	17703,	17712,	17721,	17730,	17739,
+17747,	17756,	17764,	17773,	17781,	17789,	17798,	17806,	17813,	17821,
+17829,	17836,	17843,	17851,	17858,	17866,	17872,	17879,	17886,	17893,
+17899,	17906,	17912,	17918,	17924,	17931,	17937,	17942,	17948,	17953,
+17959,	17964,	17970,	17975,	17980,	17985,	17990,	17995,	17999,	18004,
+18008,	18012,	18016,	18021,	18025,	18028,	18032,	18036,	18039,	18043,
+18046,	18049,	18052,	18055,	18058,	18061,	18064,	18067,	18069,	18071,
+18073,	18075,	18078,	18079,	18081,	18083,	18084,	18086,	18087,	18089,
+18090,	18090,	18091,	18092,	18093,	18094,	18094,	18095,	18095,	18095
+};
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/common/tables.h b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/common/tables.h
new file mode 100644
index 0000000..ddf29eb
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/common/tables.h
@@ -0,0 +1,47 @@
+/***********************************************************************
+**
+**   ITU-T G.722.1 (2005-05) - Fixed point implementation for main body and Annex C
+**   > Software Release 2.1 (2008-06)
+**     (Simple repackaging; no change from 2005-05 Release 2.0 code)
+**
+**   � 1999 PictureTel Coporation
+**          Andover, MA, USA  
+**
+**	    All rights reserved.
+**
+***********************************************************************/
+
+/***********************************************************************
+  Filename:    tables.h    
+
+  Purpose:     Contains table definitions used by G.722.1 Annex C
+		
+  Design Notes:
+
+***********************************************************************/
+
+/***********************************************************************
+ Include files                                                           
+***********************************************************************/
+#define REGION_POWER_TABLE_SIZE 64
+#define NUM_CATEGORIES          8
+#define DCT_LENGTH              320
+#define MAX_DCT_LENGTH          640
+
+extern Word16 int_region_standard_deviation_table[REGION_POWER_TABLE_SIZE];
+extern Word16 standard_deviation_inverse_table[REGION_POWER_TABLE_SIZE];
+extern Word16 step_size_inverse_table[NUM_CATEGORIES];
+extern Word16 vector_dimension[NUM_CATEGORIES];
+extern Word16 number_of_vectors[NUM_CATEGORIES];
+/* The last category isn't really coded with scalar quantization. */
+extern Word16 max_bin[NUM_CATEGORIES];
+extern Word16 max_bin_plus_one_inverse[NUM_CATEGORIES];
+extern Word16 int_dead_zone[NUM_CATEGORIES];
+extern Word16 samples_to_rmlt_window[DCT_LENGTH];
+extern Word16 rmlt_to_samples_window[DCT_LENGTH];
+
+/* Add next line in Release 1.2 */
+extern Word16 int_dead_zone_low_bits[NUM_CATEGORIES];
+
+extern Word16 max_samples_to_rmlt_window[MAX_DCT_LENGTH];
+extern Word16 max_rmlt_to_samples_window[MAX_DCT_LENGTH];
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/common/typedef.h b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/common/typedef.h
new file mode 100644
index 0000000..6daa807
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/common/typedef.h
@@ -0,0 +1,32 @@
+/* $Id: typedef.h 2623 2009-04-20 18:38:15Z bennylp $ */
+/* 
+ * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#ifndef TYPEDEF_H
+#define TYPEDEF_H
+
+#include <pj/types.h>
+
+typedef pj_int8_t Word8;
+typedef pj_int16_t Word16;
+typedef pj_int32_t Word32;
+typedef pj_uint16_t UWord16;
+typedef pj_uint32_t UWord32;
+typedef int Flag;
+
+#endif /* TYPEDEF_H */
+
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/decode/coef2sam.c b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/decode/coef2sam.c
new file mode 100644
index 0000000..87deab0
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/decode/coef2sam.c
@@ -0,0 +1,180 @@
+/*****************************************************************************
+**
+**   ITU-T G.722.1 (2005-05) - Fixed point implementation for main body and Annex C
+**   > Software Release 2.1 (2008-06)
+**     (Simple repackaging; no change from 2005-05 Release 2.0 code)
+**
+**   � 2004 Polycom, Inc.
+**
+**   All rights reserved.
+**
+*****************************************************************************/
+
+/*****************************************************************************
+* Filename: rmlt_coefs_to_samples.c
+*
+* Purpose:  Convert Reversed MLT (Modulated Lapped Transform) 
+*           Coefficients to Samples
+*
+*     The "Reversed MLT" is an overlapped block transform which uses
+*     even symmetry * on the left, odd symmetry on the right and a
+*     Type IV DCT as the block transform.  * It is thus similar to a
+*     MLT which uses odd symmetry on the left, even symmetry * on the
+*     right and a Type IV DST as the block transform.  In fact, it is
+*     equivalent * to reversing the order of the samples, performing
+*     an MLT and then negating all * the even-numbered coefficients.
+*
+*****************************************************************************/
+
+/***************************************************************************
+ Include files                                                           
+***************************************************************************/
+#include "defs.h"
+#include "tables.h"
+#include "count.h"
+
+/***************************************************************************
+ Function:     rmlt_coefs_to_samples 
+
+ Syntax:       void rmlt_coefs_to_samples(Word16 *coefs,       
+                                          Word16 *old_samples, 
+                                          Word16 *out_samples, 
+                                          Word16 dct_length,
+                                          Word16 mag_shift)    
+            
+               inputs:    Word16 *coefs
+                          Word16 *old_samples
+                          Word16 dct_length
+                          Word16 mag_shift
+                          
+                          
+               outputs:   Word16 *out_samples
+               
+ Description:  Converts the mlt_coefs to samples
+
+ Design Notes:
+ 
+ WMOPS:     7kHz |    24kbit    |    32kbit
+          -------|--------------|----------------
+            AVG  |     1.91     |    1.91
+          -------|--------------|----------------  
+            MAX  |     1.91     |    1.91
+          -------|--------------|---------------- 
+				
+           14kHz |    24kbit    |    32kbit      |     48kbit
+          -------|--------------|----------------|----------------
+            AVG  |     3.97     |    3.97        |     3.97   
+          -------|--------------|----------------|----------------
+            MAX  |     3.97     |    3.97        |     3.97   
+          -------|--------------|----------------|----------------
+
+***************************************************************************/
+
+void rmlt_coefs_to_samples(Word16 *coefs,     
+                           Word16 *old_samples,
+                           Word16 *out_samples,           
+                           Word16 dct_length,
+                           Word16 mag_shift)             
+{
+
+    
+    Word16	index, vals_left;
+    Word16	new_samples[MAX_DCT_LENGTH];
+    Word16	*new_ptr, *old_ptr;
+    Word16	*win_new, *win_old;
+    Word16	*out_ptr;
+    Word16  half_dct_size;
+    Word32  sum;
+
+    
+
+    half_dct_size = shr_nocheck(dct_length,1);
+    
+    /* Perform a Type IV (inverse) DCT on the coefficients */
+    dct_type_iv_s(coefs, new_samples, dct_length);
+    
+    test();
+    if (mag_shift > 0) 
+    {
+        for(index=0;index<dct_length;index++)
+        {
+            new_samples[index] = shr_nocheck(new_samples[index],mag_shift);
+            move16();
+        }
+    }
+    else 
+    {
+        test();
+        if (mag_shift < 0) 
+        {
+            mag_shift = negate(mag_shift);
+            for(index=0;index<dct_length;index++)
+            {
+                new_samples[index] = shl_nocheck(new_samples[index],mag_shift);
+                move16();
+            }
+        }
+
+    }
+
+    /* Get the first half of the windowed samples */
+    
+    out_ptr = out_samples;
+    move16();
+    test();
+    if (dct_length==DCT_LENGTH)
+    {
+        win_new = rmlt_to_samples_window;
+        move16();
+        win_old = rmlt_to_samples_window + dct_length;
+        move16();
+    }
+    else
+    {
+        win_new = max_rmlt_to_samples_window;
+        move16();
+        win_old = max_rmlt_to_samples_window + dct_length;
+        move16();
+    }
+    old_ptr = old_samples;
+    move16();
+    new_ptr = new_samples + half_dct_size;
+    move16();
+    
+    for (vals_left = half_dct_size;    vals_left > 0;    vals_left--)
+    {
+        sum = 0L;
+        move32();
+        sum = L_mac(sum,*win_new++, *--new_ptr);
+        sum = L_mac(sum,*--win_old, *old_ptr++);
+        *out_ptr++ = itu_round(L_shl_nocheck(sum,2));
+        move16();
+
+    }
+    
+    /* Get the second half of the windowed samples */
+    
+    for (vals_left = half_dct_size;    vals_left > 0;    vals_left--)
+    {
+        sum = 0L;
+        move32();
+        sum = L_mac(sum,*win_new++, *new_ptr++);
+        sum = L_mac(sum,negate(*--win_old), *--old_ptr);
+        *out_ptr++ = itu_round(L_shl_nocheck(sum,2));
+        move16();
+    }
+        
+    /* Save the second half of the new samples for   */
+    /* next time, when they will be the old samples. */
+    
+    /* pointer arithmetic */
+    new_ptr = new_samples + half_dct_size;
+    move16();
+    old_ptr = old_samples;
+    move16();
+    for (vals_left = half_dct_size;    vals_left > 0;    vals_left--)
+    {
+        *old_ptr++ = *new_ptr++;
+        move16();
+    }
+}
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/decode/dct4_s.c b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/decode/dct4_s.c
new file mode 100644
index 0000000..0123a13
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/decode/dct4_s.c
@@ -0,0 +1,504 @@
+/********************************************************************************
+**
+**   ITU-T G.722.1 (2005-05) - Fixed point implementation for main body and Annex C
+**   > Software Release 2.1 (2008-06)
+**     (Simple repackaging; no change from 2005-05 Release 2.0 code)
+**
+**   � 2004 Polycom, Inc.
+**
+**   All rights reserved.
+**
+********************************************************************************/
+
+/********************************************************************************
+* Filename: dct_type_iv_s.c
+*
+* Purpose:  Discrete Cosine Transform, Type IV used for inverse MLT
+*
+* The basis functions are
+*
+*	 cos(PI*(t+0.5)*(k+0.5)/block_length)
+*
+* for time t and basis function number k.  Due to the symmetry of the expression
+* in t and k, it is clear that the forward and inverse transforms are the same.
+*
+*********************************************************************************/
+
+/***************************************************************************
+ Include files                                                           
+***************************************************************************/
+#include "defs.h"
+#include "count.h"
+#include "dct4_s.h"
+
+/***************************************************************************
+ External variable declarations                                          
+***************************************************************************/
+extern Word16    syn_bias_7khz[DCT_LENGTH];
+extern Word16    dither[DCT_LENGTH];
+extern Word16    max_dither[MAX_DCT_LENGTH];
+
+extern Word16       dct_core_s[DCT_LENGTH_DIV_32][DCT_LENGTH_DIV_32];
+extern cos_msin_t	s_cos_msin_2[DCT_LENGTH_DIV_32];
+extern cos_msin_t	s_cos_msin_4[DCT_LENGTH_DIV_16];
+extern cos_msin_t	s_cos_msin_8[DCT_LENGTH_DIV_8];
+extern cos_msin_t	s_cos_msin_16[DCT_LENGTH_DIV_4];
+extern cos_msin_t	s_cos_msin_32[DCT_LENGTH_DIV_2];
+extern cos_msin_t	s_cos_msin_64[DCT_LENGTH];
+extern cos_msin_t	*s_cos_msin_table[];
+
+/********************************************************************************
+ Function:    dct_type_iv_s
+
+ Syntax:      void dct_type_iv_s (Word16 *input,Word16 *output,Word16 dct_length)
+              
+
+ Description: Discrete Cosine Transform, Type IV used for inverse MLT
+
+ Design Notes:
+ 
+ WMOPS:     7kHz |    24kbit    |    32kbit
+          -------|--------------|----------------
+            AVG  |     1.74     |     1.74
+          -------|--------------|----------------  
+            MAX  |     1.74     |     1.74
+          -------|--------------|---------------- 
+				
+           14kHz |    24kbit    |    32kbit      |     48kbit
+          -------|--------------|----------------|----------------
+            AVG  |     3.62     |     3.62       |      3.62   
+          -------|--------------|----------------|----------------
+            MAX  |     3.62     |     3.62       |      3.62   
+          -------|--------------|----------------|----------------
+
+********************************************************************************/
+
+void dct_type_iv_s (Word16 *input,Word16 *output,Word16 dct_length)
+{
+    Word16   buffer_a[MAX_DCT_LENGTH], buffer_b[MAX_DCT_LENGTH], buffer_c[MAX_DCT_LENGTH];
+    Word16   *in_ptr, *in_ptr_low, *in_ptr_high, *next_in_base;
+    Word16   *out_ptr_low, *out_ptr_high, *next_out_base;
+    Word16   *out_buffer, *in_buffer, *buffer_swap;
+    Word16   in_val_low, in_val_high;
+    Word16   out_val_low, out_val_high;
+    Word16   in_low_even, in_low_odd;
+    Word16   in_high_even, in_high_odd;
+    Word16   out_low_even, out_low_odd;
+    Word16   out_high_even, out_high_odd;
+    Word16   *pair_ptr;
+    Word16   cos_even, cos_odd, msin_even, msin_odd;
+    Word16   set_span, set_count, set_count_log, pairs_left, sets_left;
+    Word16   i,k;
+    Word16   index;
+    Word16   dummy;
+    Word32 	 sum;
+    cos_msin_t	**table_ptr_ptr, *cos_msin_ptr;
+
+    Word32 acca;
+    Word16 temp;
+
+    Word16   dct_length_log;
+    Word16   *dither_ptr;
+    
+    /*++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+    /* Do the sum/difference butterflies, the first part of */
+    /* converting one N-point transform into 32 - 10 point transforms  */
+    /* transforms, where N = 1 << DCT_LENGTH_LOG.           */
+    /*++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+    test();
+    if (dct_length==DCT_LENGTH)
+    {
+        dct_length_log = DCT_LENGTH_LOG;
+        move16();
+        dither_ptr = dither;
+        move16();
+    }
+    else
+    {
+        dct_length_log = MAX_DCT_LENGTH_LOG;
+        move16();
+        dither_ptr = max_dither;
+        move16();
+    }
+    
+    in_buffer  = input;
+    move16();
+    out_buffer = buffer_a;
+    move16();
+    
+    index=0;
+    move16();
+    
+    i=0;
+    move16();
+
+    for (set_count_log = 0;    set_count_log <= dct_length_log - 2;    set_count_log++) 
+    {
+
+        /*===========================================================*/
+        /* Initialization for the loop over sets at the current size */
+        /*===========================================================*/
+        
+        /*    set_span      = 1 << (DCT_LENGTH_LOG - set_count_log); */
+        set_span = shr_nocheck(dct_length,set_count_log);
+           
+        set_count     = shl_nocheck(1,set_count_log);
+        in_ptr        = in_buffer;
+        move16();
+        next_out_base = out_buffer;
+        move16();
+        
+        /*=====================================*/
+        /* Loop over all the sets of this size */
+        /*=====================================*/
+        temp = sub(index,1);
+        test();
+        if(temp < 0)
+        {
+            for (sets_left = set_count;sets_left > 0;sets_left--) 
+            {
+    
+                /*||||||||||||||||||||||||||||||||||||||||||||*/
+                /* Set up output pointers for the current set */
+                /*||||||||||||||||||||||||||||||||||||||||||||*/
+                /* pointer arithmetic */
+                out_ptr_low    = next_out_base;
+                move16();
+                next_out_base += set_span;
+                move16();
+                out_ptr_high   = next_out_base;
+                move16();
+
+                /*||||||||||||||||||||||||||||||||||||||||||||||||||*/
+                /* Loop over all the butterflies in the current set */
+                /*||||||||||||||||||||||||||||||||||||||||||||||||||*/
+                    
+                do 
+                {
+                    in_val_low      = *in_ptr++;
+                    move16();
+                    in_val_high     = *in_ptr++;
+                    move16();
+
+                    /* BEST METHOD OF GETTING RID OF BIAS, BUT COMPUTATIONALLY UNPLEASANT */
+                    /* ALTERNATIVE METHOD, SMEARS BIAS OVER THE ENTIRE FRAME, COMPUTATIONALLY SIMPLEST. */
+                    /* IF THIS WORKS, IT'S PREFERABLE */
+                        
+                    dummy = add(in_val_low,dither_ptr[i++]);
+		    // blp: addition of two 16bits vars, there's no way
+		    //      they'll overflow a 32bit var
+                    //acca = L_add(dummy,in_val_high);
+		    acca = dummy + in_val_high;
+                    out_val_low = extract_l(L_shr_nocheck(acca,1));
+                    
+                    dummy = add(in_val_low,dither_ptr[i++]);
+		    // blp: addition of two 16bits vars, there's no way
+		    //      they'll overflow a 32bit var
+                    //acca = L_add(dummy,-in_val_high);
+		    acca = dummy - in_val_high;
+                    out_val_high = extract_l(L_shr_nocheck(acca,1));
+                    
+                    *out_ptr_low++  = out_val_low;
+                    move16();
+                    *--out_ptr_high = out_val_high;
+                    move16();
+
+                    test();
+                    
+                    /* this involves comparison of pointers */
+                    /* pointer arithmetic */
+
+                } while (out_ptr_low < out_ptr_high);
+    
+            } /* End of loop over sets of the current size */
+        }
+        else
+        {
+            for (sets_left = set_count;    sets_left > 0;    sets_left--) 
+            {
+                /*||||||||||||||||||||||||||||||||||||||||||||*/
+                /* Set up output pointers for the current set */
+                /*||||||||||||||||||||||||||||||||||||||||||||*/
+                
+                out_ptr_low    = next_out_base;
+                move16();
+                next_out_base += set_span;
+                move16();
+                out_ptr_high   = next_out_base;
+                move16();
+
+            	/*||||||||||||||||||||||||||||||||||||||||||||||||||*/
+            	/* Loop over all the butterflies in the current set */
+            	/*||||||||||||||||||||||||||||||||||||||||||||||||||*/
+                
+                do 
+                {
+                    in_val_low      = *in_ptr++;
+                    move16();
+                    in_val_high     = *in_ptr++;
+                    move16();
+
+                    out_val_low     = add(in_val_low,in_val_high);
+                    out_val_high    = add(in_val_low,negate(in_val_high));
+                    
+                    *out_ptr_low++  = out_val_low;
+                    move16();
+                    *--out_ptr_high = out_val_high;
+                    move16();
+
+                    test();
+                } while (out_ptr_low < out_ptr_high);
+    
+            } /* End of loop over sets of the current size */
+        }
+
+        /*============================================================*/
+        /* Decide which buffers to use as input and output next time. */
+        /* Except for the first time (when the input buffer is the    */
+        /* subroutine input) we just alternate the local buffers.     */
+        /*============================================================*/
+        
+        in_buffer = out_buffer;
+        move16();
+        
+        test();
+        if (out_buffer == buffer_a)
+        {
+            out_buffer = buffer_b;
+            move16();
+        }
+        else
+        {
+            out_buffer = buffer_a;
+            move16();
+        }
+        
+        index = add(index,1);
+    } /* End of loop over set sizes */
+
+
+    /*++++++++++++++++++++++++++++++++*/
+    /* Do 32 - 10 point transforms */
+    /*++++++++++++++++++++++++++++++++*/
+    
+    pair_ptr = in_buffer;
+    move16();
+    buffer_swap = buffer_c;
+    move16();
+
+    for (pairs_left = 1 << (dct_length_log - 1);    pairs_left > 0;    pairs_left--) 
+    {
+        for ( k=0; k<CORE_SIZE; k++ )
+        {
+#if PJ_HAS_INT64
+	    /* blp: danger danger! not really compatible but faster */
+	    pj_int64_t sum64=0;
+            move32();
+            
+            for ( i=0; i<CORE_SIZE; i++ )
+            {
+                sum64 += L_mult(pair_ptr[i], dct_core_s[i][k]);
+            }
+	    sum = L_saturate(sum64);
+#else
+            sum=0L;
+            move32();
+            
+            for ( i=0; i<CORE_SIZE; i++ )
+            {
+                sum = L_mac(sum, pair_ptr[i],dct_core_s[i][k]);
+            }
+#endif
+            buffer_swap[k] = itu_round(sum);
+        }
+        
+        pair_ptr   += CORE_SIZE;
+        move16();
+        buffer_swap += CORE_SIZE;
+        move16();
+    }
+    
+    for (i=0;i<dct_length;i++)
+    {
+        in_buffer[i] = buffer_c[i];
+        move16();
+    }
+
+    table_ptr_ptr = s_cos_msin_table;
+    move16();
+
+    /*++++++++++++++++++++++++++++++*/
+    /* Perform rotation butterflies */
+    /*++++++++++++++++++++++++++++++*/
+    index=0;
+    move16();
+    
+    for (set_count_log = dct_length_log - 2 ;    set_count_log >= 0;    set_count_log--) 
+    {
+
+        /*===========================================================*/
+        /* Initialization for the loop over sets at the current size */
+        /*===========================================================*/
+        
+        /*    set_span      = 1 << (DCT_LENGTH_LOG - set_count_log); */
+        set_span = shr_nocheck(dct_length,set_count_log);
+        
+        set_count     = shl_nocheck(1,set_count_log);
+        next_in_base  = in_buffer;
+        move16();
+        test();
+        if (set_count_log == 0)
+        {
+            next_out_base = output;
+            move16();
+        }
+        else
+        {
+            next_out_base = out_buffer;
+            move16();
+        }
+        
+        /*=====================================*/
+        /* Loop over all the sets of this size */
+        /*=====================================*/
+
+        for (sets_left = set_count;    sets_left > 0;    sets_left--) 
+        {
+
+            /*|||||||||||||||||||||||||||||||||||||||||*/
+            /* Set up the pointers for the current set */
+            /*|||||||||||||||||||||||||||||||||||||||||*/
+            
+            in_ptr_low     = next_in_base;
+            move16();
+            
+            temp = shr_nocheck(set_span,1);
+            in_ptr_high    = in_ptr_low + temp;
+            move16();
+            
+            next_in_base  += set_span;
+            move16();
+            
+            out_ptr_low    = next_out_base;
+            move16();
+            
+            next_out_base += set_span;
+            move16();
+            out_ptr_high   = next_out_base;
+            move16();
+            
+            cos_msin_ptr   = *table_ptr_ptr;
+            move16();
+
+            /*||||||||||||||||||||||||||||||||||||||||||||||||||||||*/
+            /* Loop over all the butterfly pairs in the current set */
+            /*||||||||||||||||||||||||||||||||||||||||||||||||||||||*/
+
+	        do 
+            {
+                in_low_even     = *in_ptr_low++;
+                move16();
+                in_low_odd      = *in_ptr_low++;
+                move16();
+                in_high_even    = *in_ptr_high++;
+                move16();
+                in_high_odd     = *in_ptr_high++;
+                move16();
+                cos_even        = cos_msin_ptr[0].cosine;
+                move16();
+                msin_even       = cos_msin_ptr[0].minus_sine;
+                move16();
+                cos_odd         = cos_msin_ptr[1].cosine;
+                move16();
+                msin_odd        = cos_msin_ptr[1].minus_sine;
+                move16();
+                cos_msin_ptr   += 2;
+                
+                sum = 0L;
+                move32();
+                
+                sum = L_mac(sum,cos_even,in_low_even);
+                sum = L_mac(sum,negate(msin_even),in_high_even);
+                out_low_even = itu_round(L_shl_nocheck(sum,1));
+                
+                sum = 0L;
+                move32();
+                sum = L_mac(sum,msin_even,in_low_even);
+                sum = L_mac(sum,cos_even,in_high_even);
+                out_high_even = itu_round(L_shl_nocheck(sum,1));
+                
+                sum = 0L;
+                move32();
+                sum = L_mac(sum,cos_odd,in_low_odd);
+                sum = L_mac(sum,msin_odd,in_high_odd);
+                out_low_odd = itu_round(L_shl_nocheck(sum,1));
+                
+                sum = 0L;
+                move32();
+                sum = L_mac(sum,msin_odd,in_low_odd);
+                sum = L_mac(sum,negate(cos_odd),in_high_odd);
+                out_high_odd = itu_round(L_shl_nocheck(sum,1));
+                
+                *out_ptr_low++  = out_low_even;
+                move16();
+                *--out_ptr_high = out_high_even;
+                move16();
+                *out_ptr_low++  = out_low_odd;
+                move16();
+                *--out_ptr_high = out_high_odd;
+                move16();
+            
+                test();
+            } while (out_ptr_low < out_ptr_high);
+
+	    } /* End of loop over sets of the current size */
+
+        /*=============================================*/
+        /* Swap input and output buffers for next time */
+        /*=============================================*/
+        
+        buffer_swap = in_buffer;
+        move16();
+        in_buffer   = out_buffer;
+        move16();
+        out_buffer  = buffer_swap;
+        move16();
+        
+        index = add(index,1);
+        table_ptr_ptr++;
+    }
+    /*------------------------------------
+    
+         ADD IN BIAS FOR OUTPUT
+         
+    -----------------------------------*/
+    if (dct_length==DCT_LENGTH)
+    {
+        for(i=0;i<320;i++) 
+        {
+	   // blp: addition of two 16bits vars, there's no way
+	   //      they'll overflow a 32bit var
+           //sum = L_add(output[i],syn_bias_7khz[i]);
+	   sum = output[i] + syn_bias_7khz[i];
+           acca = L_sub(sum,32767);
+           test();
+           if (acca > 0) 
+           {
+               sum = 32767L;
+               move32();
+           }
+	   // blp: addition of two 16bits vars, there's no way
+	   //      they'll overflow 32bit var
+           //acca = L_add(sum,32768L);
+	   acca = sum + 32768;
+           test();
+           if (acca < 0) 
+           {
+               sum = -32768L;
+               move32();
+           }
+           output[i] = extract_l(sum);
+        }
+    }
+}
+
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/decode/dct4_s.h b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/decode/dct4_s.h
new file mode 100644
index 0000000..010e52d
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/decode/dct4_s.h
@@ -0,0 +1,856 @@
+/***********************************************************************
+**
+**   ITU-T G.722.1 (2005-05) - Fixed point implementation for main body and Annex C
+**   > Software Release 2.1 (2008-06)
+**     (Simple repackaging; no change from 2005-05 Release 2.0 code)
+**
+**   � 2004 Polycom, Inc.
+**
+**   All rights reserved.
+**
+***********************************************************************/
+
+/***********************************************************************
+  Filename:    dct4_s.h    
+
+  Purpose:     Contains tables used by dct4_s.c
+		
+  Design Notes:
+
+***********************************************************************/
+
+/***************************************************************************
+ Include files                                                           
+***************************************************************************/
+
+typedef struct 
+{
+    Word16 cosine;
+    Word16 minus_sine;
+} cos_msin_t;
+
+/***************************************************************************
+  The dct_core_s table was generated by the following code
+
+      for(i=0;i<10;++i)
+      {
+          for(k=0;k<10;++k)
+          {
+              dct_core_s[i][k]=(short) (FTOI(((.9*32768.)*cos(3.1415926*(k+0.5)*(i+0.5)/10.))));
+          }
+      }
+***************************************************************************/
+Word16 dct_core_s[10][10] = {
+{ 29400,   28676,   27246,   25145,   22425,   19153,   15409,   11286,    6885,  2314 },
+{ 28676,   22425,   11286,   -2314,  -15409,  -25145,  -29400,  -27246,  -19153,  -6885 },
+{ 27246,   11286,  -11286,  -27246,  -27246,  -11286,   11286,   27246,   27246,  11286 },
+{ 25145,   -2314,  -27246,  -22425,    6885,   28676,   19153,  -11286,  -29400,  -15409 },
+{ 22425,  -15409,  -27246,    6885,   29400,    2314,  -28676,  -11286,   25145,  19153 },
+{ 19153,  -25145,  -11286,   28676,    2314,  -29400,    6885,   27246,  -15409,  -22425 },
+{ 15409,  -29400,   11286,   19153,  -28676,    6885,   22425,  -27246,    2314,  25145 },
+{ 11286,  -27246,   27246,  -11286,  -11286,   27246,  -27246,   11286,   11286,  -27246 },
+{  6885,  -19153,   27246,  -29400,   25145,  -15409,    2314,   11286,  -22425,  28676 },
+{  2314,   -6885,   11286,  -15409,   19153,  -22425,   25145,  -27246,   28676,  -29400 }
+};    
+
+Word16 syn_bias_7khz[DCT_LENGTH] = {
+ -4,  4, -5, -2,  0, -4,  6,  2, -2, -4,
+ -3,  3,  0,  0, -2,  4,  0,  0,  3, -6,
+  8,  5,  4,  5, -8,  0, -2,  0,  0, -3,
+  3,  0,  0,  0,  1, -1, -2,  0,  0,  2,
+ -2, -5, -2,  3,  2, -1, -1, -6,  3,  1,
+ -7,  4,  4,  0,  1,  4,  1,  0,  1, -5,
+ -1,  1, -6,  0, -1, -1,  3,  0, -2,  1,
+  2, -4,  0,  9,  0, -3,  1,  1,  1,  0,
+ -3, -2, -1, -4, -2,  0,  5,  2, -3,  5,
+  0, -2,  4,  4,  0, -6, -4,  2,  0,  0,
+  0, -1, -1, -2,  0,  6,  1,  0,  0, -1,
+  0, -4, -1,  0, -4,  1, -1, -5,  0,  1,
+  2,  4,  0, -8, -4,  0, -2, -2,  2,  5,
+ -3, -1,  1, -4,  0,  0,  0, -1, -3,  0,
+ -5, -4,  0, -2,  0,  7,  1,  0,  5, -2,
+ -1,  2,  2, -2,  3,  7, -3,  4,  1, -4,
+  0,  0,  3, -7, -5,  0,  0,  4,  0, -2,
+ -1,  0, -5,  0,  2,  0, 11,  5, -1,  0,
+  2,  2, -2, -2,  5,  4, -3,  1,  0, -2,
+  1,  3,  2,  0,  1,  0,  0,  0,  5,  6,
+ -2, -1,  0,  2,  3,  2,  0, -3,  4,  5,
+  0, -1,  0,  3,  1, -2, -3, -2, -1,  2,
+ -1, -1, -2, -7,  4,  6, -5, -6, -3, -4,
+  0,  2, -5, -2,  3,  0,  0,  0,  2, -2,
+ -4,  3,  3,  1,  0,  0,  4, -1,  8, 13,
+  1,  2,  0,  2,  0, -1,  4, -3,  1,  0,
+ -1,  3,  0,  0, -5,  0,  6,  2,  4,  5,
+  2, -1, -1,  3,  6,  1,  1,  2, -4,  0,
+ -1, -6, -2, -2,  2,  1,  2,  6,  2,  0,
+ -2, -2,  0, -1,  2,  0,  0,  3, -2,  1,
+  3,  1,  2, -1, -2,  2,  2, -4,  0,  0,
+ -3,  0, -4, -3,  6,  7,  2,  2,  0, -3};
+
+Word16 dither[DCT_LENGTH]= {
+  1,  0,  0,  0,  1,  0,  0,  1,  1,  1,
+  1,  0,  0,  0,  1,  1,  1,  1,  1,  0,
+  0,  1,  1,  1,  0,  1,  1,  0,  0,  0,
+  1,  0,  0,  1,  0,  1,  0,  0,  1,  0,
+  1,  0,  0,  0,  1,  0,  1,  0,  0,  0,
+  1,  1,  1,  1,  1,  0,  0,  1,  0,  0,
+  0,  0,  1,  0,  0,  0,  1,  0,  0,  1,
+  1,  1,  1,  1,  1,  0,  1,  0,  0,  1,
+  1,  0,  0,  1,  0,  0,  0,  1,  0,  1,
+  0,  0,  1,  1,  0,  1,  0,  1,  1,  1,
+  1,  0,  0,  0,  0,  1,  1,  1,  1,  1,
+  0,  0,  0,  1,  0,  1,  0,  0,  0,  1,
+  1,  1,  0,  0,  1,  1,  1,  1,  1,  0,
+  0,  1,  1,  1,  1,  0,  1,  1,  1,  0,
+  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,
+  1,  0,  1,  1,  1,  1,  0,  0,  0,  0,
+  1,  1,  0,  1,  0,  0,  1,  0,  0,  1,
+  0,  0,  0,  1,  1,  0,  0,  1,  1,  1,
+  1,  0,  0,  0,  0,  0,  1,  1,  1,  1,
+  1,  0,  0,  1,  1,  0,  1,  1,  0,  0,
+  1,  1,  1,  0,  1,  1,  0,  1,  0,  1,
+  0,  0,  1,  1,  1,  1,  1,  1,  0,  1,
+  0,  1,  1,  1,  1,  0,  1,  1,  1,  0,
+  1,  1,  1,  0,  1,  1,  1,  0,  1,  0,
+  1,  1,  0,  0,  1,  0,  0,  1,  0,  1,
+  0,  1,  1,  0,  1,  0,  1,  0,  1,  1,
+  1,  0,  1,  0,  1,  0,  1,  1,  1,  1,
+  0,  1,  0,  0,  0,  1,  0,  0,  0,  1,
+  1,  0,  0,  0,  1,  0,  0,  1,  0,  1,
+  1,  0,  1,  1,  0,  0,  1,  1,  0,  1,
+  1,  0,  1,  1,  1,  1,  1,  1,  0,  1,
+  1,  1,  1,  0,  1,  0,  0,  0,  1,  0};
+
+Word16 max_dither[MAX_DCT_LENGTH]= {
+  1,  0,  1,  0,  1,  1,  0,  1,  0,  1,
+  1,  1,  0,  0,  0,  0,  0,  1,  1,  1,
+  1,  1,  1,  0,  1,  1,  0,  0,  0,  1,
+  0,  0,  0,  1,  0,  0,  0,  0,  0,  0,
+  1,  1,  1,  0,  1,  0,  1,  1,  1,  1,
+  0,  1,  0,  1,  1,  1,  1,  1,  1,  0,
+  1,  0,  1,  1,  0,  1,  0,  0,  0,  1,
+  0,  1,  1,  1,  1,  1,  0,  1,  1,  0,
+  0,  0,  1,  1,  0,  0,  0,  1,  1,  1,
+  1,  0,  1,  1,  1,  1,  1,  0,  0,  0,
+  1,  0,  1,  0,  1,  0,  0,  0,  1,  1,
+  0,  1,  1,  1,  1,  1,  1,  0,  1,  0,
+  0,  0,  1,  0,  1,  0,  0,  0,  1,  0,
+  0,  1,  0,  1,  0,  0,  0,  0,  1,  0,
+  1,  0,  0,  1,  0,  1,  0,  0,  0,  1,
+  0,  1,  0,  0,  1,  1,  1,  1,  0,  1,
+  1,  0,  0,  0,  1,  1,  0,  1,  0,  1,
+  0,  1,  0,  1,  0,  1,  1,  1,  0,  1,
+  1,  0,  0,  1,  1,  1,  1,  0,  1,  1,
+  1,  1,  1,  0,  1,  1,  0,  0,  0,  0,
+  1,  0,  1,  0,  0,  0,  0,  1,  1,  0,
+  1,  1,  0,  0,  0,  0,  1,  0,  0,  1,
+  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,
+  0,  0,  1,  1,  1,  0,  1,  1,  1,  0,
+  0,  1,  1,  1,  1,  1,  1,  1,  0,  0,
+  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,
+  0,  0,  1,  1,  0,  1,  0,  1,  0,  1,
+  0,  0,  1,  1,  1,  1,  1,  1,  0,  1,
+  0,  1,  1,  1,  0,  1,  0,  1,  0,  0,
+  0,  1,  0,  1,  1,  0,  0,  0,  1,  0,
+  1,  1,  0,  0,  1,  1,  1,  1,  0,  0,
+  0,  0,  1,  1,  1,  1,  0,  0,  1,  1,
+  1,  1,  1,  0,  1,  0,  0,  0,  1,  0,
+  0,  1,  1,  1,  0,  1,  0,  1,  0,  0,
+  1,  1,  0,  1,  0,  1,  1,  0,  0,  0,
+  0,  1,  1,  0,  1,  1,  1,  0,  1,  1,
+  0,  0,  1,  1,  1,  1,  1,  1,  0,  1,
+  1,  1,  0,  0,  0,  1,  1,  1,  1,  0,
+  0,  1,  0,  1,  0,  1,  1,  0,  1,  0,
+  1,  1,  1,  0,  0,  1,  1,  0,  0,  1,
+  0,  1,  0,  0,  0,  1,  1,  0,  0,  1,
+  0,  0,  1,  1,  0,  1,  0,  1,  0,  1,
+  1,  1,  0,  1,  0,  0,  1,  1,  0,  0,
+  1,  0,  1,  0,  1,  0,  0,  1,  0,  0,
+  0,  1,  0,  1,  1,  1,  1,  1,  1,  0,
+  0,  1,  1,  0,  0,  0,  1,  1,  1,  0,
+  1,  1,  1,  0,  1,  1,  1,  0,  0,  0,
+  0,  0,  1,  0,  0,  1,  0,  0,  0,  1,
+  0,  0,  0,  1,  1,  0,  0,  1,  0,  1,
+  1,  1,  1,  1,  0,  0,  1,  0,  1,  0,
+  0,  1,  0,  1,  1,  1,  1,  1,  1,  0,
+  0,  0,  1,  0,  1,  0,  0,  1,  0,  1,
+  1,  0,  1,  0,  1,  1,  0,  0,  1,  1,
+  1,  1,  1,  0,  1,  0,  0,  1,  1,  1,
+  0,  1,  0,  1,  0,  1,  0,  0,  0,  1,
+  1,  0,  0,  1,  0,  0,  1,  1,  0,  1,
+  1,  0,  1,  0,  1,  1,  0,  0,  1,  1,
+  0,  0,  0,  1,  0,  1,  1,  1,  0,  0,
+  1,  0,  1,  0,  1,  1,  0,  0,  0,  1,
+  1,  0,  1,  0,  0,  1,  1,  1,  0,  1,
+  0,  0,  1,  1,  1,  1,  1,  0,  0,  0,
+  0,  1,  0,  1,  0,  0,  1,  0,  1,  0,
+  0,  1,  1,  1,  1,  0,  0,  0,  1,  0,
+  0,  1,  0,  1,  0,  1,  0,  0,  0,  0
+};
+
+
+/********************************************************************************
+  The s_cos_min tables were generated by the following code:
+      double		angle, scale;
+      int		    index;
+
+      for (index = 0;index < length;index++) 
+      {
+          angle = scale * ((double)index + 0.5);
+          table[index].cosine     = (short) (FTOI((18427)* cos(angle)));
+          table[index].minus_sine = (short) (FTOI((18427)*(-sin(angle))));
+      }
+
+
+********************************************************************************/
+
+cos_msin_t	s_cos_msin_2[DCT_LENGTH_DIV_32] = {
+    {  18413   ,   -723   } , 
+    {  18299   ,   -2166   } , 
+    {  18073   ,   -3595   } , 
+    {  17735   ,   -5002   } , 
+    {  17288   ,   -6378   } , 
+    {  16734   ,   -7715   } , 
+    {  16077   ,   -9004   } , 
+    {  15321   ,   -10237   } , 
+    {  14471   ,   -11408   } , 
+    {  13531   ,   -12508   } 
+    };
+cos_msin_t	s_cos_msin_4[DCT_LENGTH_DIV_16] = {
+    {  18423   ,   -362   } , 
+    {  18395   ,   -1085   } , 
+    {  18338   ,   -1806   } , 
+    {  18253   ,   -2525   } , 
+    {  18140   ,   -3239   } , 
+    {  17999   ,   -3949   } , 
+    {  17830   ,   -4653   } , 
+    {  17634   ,   -5349   } , 
+    {  17410   ,   -6037   } , 
+    {  17159   ,   -6716   } , 
+    {  16883   ,   -7385   } , 
+    {  16580   ,   -8042   } , 
+    {  16251   ,   -8686   } , 
+    {  15898   ,   -9318   } , 
+    {  15520   ,   -9935   } , 
+    {  15118   ,   -10536   } , 
+    {  14692   ,   -11122   } , 
+    {  14244   ,   -11690   } , 
+    {  13774   ,   -12240   } , 
+    {  13283   ,   -12772   } 
+    };
+cos_msin_t	s_cos_msin_8[DCT_LENGTH_DIV_8] = {
+    {  18426   ,   -181   } , 
+    {  18419   ,   -543   } , 
+    {  18405   ,   -904   } , 
+    {  18384   ,   -1265   } , 
+    {  18355   ,   -1626   } , 
+    {  18320   ,   -1986   } , 
+    {  18277   ,   -2345   } , 
+    {  18228   ,   -2704   } , 
+    {  18171   ,   -3061   } , 
+    {  18107   ,   -3417   } , 
+    {  18037   ,   -3772   } , 
+    {  17959   ,   -4126   } , 
+    {  17875   ,   -4477   } , 
+    {  17783   ,   -4827   } , 
+    {  17685   ,   -5176   } , 
+    {  17580   ,   -5522   } , 
+    {  17468   ,   -5866   } , 
+    {  17350   ,   -6208   } , 
+    {  17225   ,   -6547   } , 
+    {  17093   ,   -6884   } , 
+    {  16954   ,   -7219   } , 
+    {  16809   ,   -7550   } , 
+    {  16658   ,   -7879   } , 
+    {  16500   ,   -8204   } , 
+    {  16336   ,   -8526   } , 
+    {  16165   ,   -8846   } , 
+    {  15988   ,   -9161   } , 
+    {  15805   ,   -9473   } , 
+    {  15616   ,   -9782   } , 
+    {  15421   ,   -10087   } , 
+    {  15220   ,   -10387   } , 
+    {  15013   ,   -10684   } , 
+    {  14801   ,   -10977   } , 
+    {  14582   ,   -11265   } , 
+    {  14358   ,   -11550   } , 
+    {  14129   ,   -11829   } , 
+    {  13894   ,   -12104   } , 
+    {  13654   ,   -12375   } , 
+    {  13408   ,   -12641   } , 
+    {  13157   ,   -12901   } 
+    };
+cos_msin_t	s_cos_msin_16[DCT_LENGTH_DIV_4] = {
+    {  18427   ,   -90   } , 
+    {  18425   ,   -271   } , 
+    {  18421   ,   -452   } , 
+    {  18416   ,   -633   } , 
+    {  18409   ,   -814   } , 
+    {  18400   ,   -995   } , 
+    {  18389   ,   -1175   } , 
+    {  18377   ,   -1356   } , 
+    {  18363   ,   -1536   } , 
+    {  18347   ,   -1716   } , 
+    {  18329   ,   -1896   } , 
+    {  18310   ,   -2076   } , 
+    {  18288   ,   -2256   } , 
+    {  18265   ,   -2435   } , 
+    {  18241   ,   -2614   } , 
+    {  18214   ,   -2793   } , 
+    {  18186   ,   -2972   } , 
+    {  18156   ,   -3150   } , 
+    {  18124   ,   -3328   } , 
+    {  18090   ,   -3506   } , 
+    {  18055   ,   -3684   } , 
+    {  18018   ,   -3861   } , 
+    {  17979   ,   -4037   } , 
+    {  17939   ,   -4214   } , 
+    {  17897   ,   -4390   } , 
+    {  17853   ,   -4565   } , 
+    {  17807   ,   -4740   } , 
+    {  17760   ,   -4915   } , 
+    {  17710   ,   -5089   } , 
+    {  17660   ,   -5262   } , 
+    {  17607   ,   -5436   } , 
+    {  17553   ,   -5608   } , 
+    {  17497   ,   -5780   } , 
+    {  17439   ,   -5952   } , 
+    {  17380   ,   -6123   } , 
+    {  17319   ,   -6293   } , 
+    {  17257   ,   -6463   } , 
+    {  17192   ,   -6632   } , 
+    {  17126   ,   -6800   } , 
+    {  17059   ,   -6968   } , 
+    {  16990   ,   -7135   } , 
+    {  16919   ,   -7302   } , 
+    {  16846   ,   -7467   } , 
+    {  16772   ,   -7632   } , 
+    {  16696   ,   -7797   } , 
+    {  16619   ,   -7960   } , 
+    {  16540   ,   -8123   } , 
+    {  16459   ,   -8285   } , 
+    {  16377   ,   -8446   } , 
+    {  16294   ,   -8607   } , 
+    {  16208   ,   -8766   } , 
+    {  16121   ,   -8925   } , 
+    {  16033   ,   -9083   } , 
+    {  15943   ,   -9240   } , 
+    {  15852   ,   -9396   } , 
+    {  15759   ,   -9551   } , 
+    {  15664   ,   -9705   } , 
+    {  15568   ,   -9858   } , 
+    {  15471   ,   -10011   } , 
+    {  15372   ,   -10162   } , 
+    {  15271   ,   -10313   } , 
+    {  15169   ,   -10462   } , 
+    {  15066   ,   -10610   } , 
+    {  14961   ,   -10758   } , 
+    {  14854   ,   -10904   } , 
+    {  14747   ,   -11049   } , 
+    {  14637   ,   -11194   } , 
+    {  14527   ,   -11337   } , 
+    {  14415   ,   -11479   } , 
+    {  14301   ,   -11620   } , 
+    {  14187   ,   -11760   } , 
+    {  14071   ,   -11898   } , 
+    {  13953   ,   -12036   } , 
+    {  13834   ,   -12172   } , 
+    {  13714   ,   -12308   } , 
+    {  13593   ,   -12442   } , 
+    {  13470   ,   -12575   } , 
+    {  13346   ,   -12706   } , 
+    {  13220   ,   -12837   } , 
+    {  13094   ,   -12966   } 
+    };
+cos_msin_t	s_cos_msin_32[DCT_LENGTH_DIV_2] = {
+    {  18427   ,   -45   } , 
+    {  18427   ,   -136   } , 
+    {  18426   ,   -226   } , 
+    {  18424   ,   -317   } , 
+    {  18423   ,   -407   } , 
+    {  18420   ,   -497   } , 
+    {  18418   ,   -588   } , 
+    {  18415   ,   -678   } , 
+    {  18411   ,   -769   } , 
+    {  18407   ,   -859   } , 
+    {  18403   ,   -949   } , 
+    {  18398   ,   -1040   } , 
+    {  18392   ,   -1130   } , 
+    {  18387   ,   -1220   } , 
+    {  18380   ,   -1310   } , 
+    {  18374   ,   -1401   } , 
+    {  18367   ,   -1491   } , 
+    {  18359   ,   -1581   } , 
+    {  18351   ,   -1671   } , 
+    {  18343   ,   -1761   } , 
+    {  18334   ,   -1851   } , 
+    {  18324   ,   -1941   } , 
+    {  18315   ,   -2031   } , 
+    {  18305   ,   -2121   } , 
+    {  18294   ,   -2211   } , 
+    {  18283   ,   -2301   } , 
+    {  18271   ,   -2390   } , 
+    {  18259   ,   -2480   } , 
+    {  18247   ,   -2570   } , 
+    {  18234   ,   -2659   } , 
+    {  18221   ,   -2749   } , 
+    {  18207   ,   -2838   } , 
+    {  18193   ,   -2927   } , 
+    {  18178   ,   -3017   } , 
+    {  18163   ,   -3106   } , 
+    {  18148   ,   -3195   } , 
+    {  18132   ,   -3284   } , 
+    {  18116   ,   -3373   } , 
+    {  18099   ,   -3462   } , 
+    {  18082   ,   -3551   } , 
+    {  18064   ,   -3639   } , 
+    {  18046   ,   -3728   } , 
+    {  18027   ,   -3816   } , 
+    {  18009   ,   -3905   } , 
+    {  17989   ,   -3993   } , 
+    {  17969   ,   -4081   } , 
+    {  17949   ,   -4170   } , 
+    {  17928   ,   -4258   } , 
+    {  17907   ,   -4346   } , 
+    {  17886   ,   -4434   } , 
+    {  17864   ,   -4521   } , 
+    {  17841   ,   -4609   } , 
+    {  17818   ,   -4696   } , 
+    {  17795   ,   -4784   } , 
+    {  17772   ,   -4871   } , 
+    {  17747   ,   -4958   } , 
+    {  17723   ,   -5045   } , 
+    {  17698   ,   -5132   } , 
+    {  17672   ,   -5219   } , 
+    {  17647   ,   -5306   } , 
+    {  17620   ,   -5392   } , 
+    {  17594   ,   -5479   } , 
+    {  17567   ,   -5565   } , 
+    {  17539   ,   -5651   } , 
+    {  17511   ,   -5737   } , 
+    {  17483   ,   -5823   } , 
+    {  17454   ,   -5909   } , 
+    {  17425   ,   -5994   } , 
+    {  17395   ,   -6080   } , 
+    {  17365   ,   -6165   } , 
+    {  17335   ,   -6250   } , 
+    {  17304   ,   -6335   } , 
+    {  17272   ,   -6420   } , 
+    {  17241   ,   -6505   } , 
+    {  17208   ,   -6590   } , 
+    {  17176   ,   -6674   } , 
+    {  17143   ,   -6758   } , 
+    {  17110   ,   -6842   } , 
+    {  17076   ,   -6926   } , 
+    {  17042   ,   -7010   } , 
+    {  17007   ,   -7093   } , 
+    {  16972   ,   -7177   } , 
+    {  16937   ,   -7260   } , 
+    {  16901   ,   -7343   } , 
+    {  16864   ,   -7426   } , 
+    {  16828   ,   -7509   } , 
+    {  16791   ,   -7591   } , 
+    {  16753   ,   -7674   } , 
+    {  16715   ,   -7756   } , 
+    {  16677   ,   -7838   } , 
+    {  16638   ,   -7919   } , 
+    {  16599   ,   -8001   } , 
+    {  16560   ,   -8082   } , 
+    {  16520   ,   -8164   } , 
+    {  16480   ,   -8245   } , 
+    {  16439   ,   -8325   } , 
+    {  16398   ,   -8406   } , 
+    {  16357   ,   -8486   } , 
+    {  16315   ,   -8567   } , 
+    {  16272   ,   -8647   } , 
+    {  16230   ,   -8726   } , 
+    {  16187   ,   -8806   } , 
+    {  16143   ,   -8885   } , 
+    {  16100   ,   -8964   } , 
+    {  16055   ,   -9043   } , 
+    {  16011   ,   -9122   } , 
+    {  15966   ,   -9200   } , 
+    {  15920   ,   -9279   } , 
+    {  15875   ,   -9357   } , 
+    {  15829   ,   -9435   } , 
+    {  15782   ,   -9512   } , 
+    {  15735   ,   -9589   } , 
+    {  15688   ,   -9667   } , 
+    {  15640   ,   -9744   } , 
+    {  15592   ,   -9820   } , 
+    {  15544   ,   -9897   } , 
+    {  15495   ,   -9973   } , 
+    {  15446   ,   -10049   } , 
+    {  15396   ,   -10124   } , 
+    {  15347   ,   -10200   } , 
+    {  15296   ,   -10275   } , 
+    {  15246   ,   -10350   } , 
+    {  15195   ,   -10425   } , 
+    {  15143   ,   -10499   } , 
+    {  15092   ,   -10573   } , 
+    {  15040   ,   -10647   } , 
+    {  14987   ,   -10721   } , 
+    {  14934   ,   -10794   } , 
+    {  14881   ,   -10868   } , 
+    {  14828   ,   -10941   } , 
+    {  14774   ,   -11013   } , 
+    {  14719   ,   -11086   } , 
+    {  14665   ,   -11158   } , 
+    {  14610   ,   -11230   } , 
+    {  14555   ,   -11301   } , 
+    {  14499   ,   -11372   } , 
+    {  14443   ,   -11444   } , 
+    {  14387   ,   -11514   } , 
+    {  14330   ,   -11585   } , 
+    {  14273   ,   -11655   } , 
+    {  14216   ,   -11725   } , 
+    {  14158   ,   -11795   } , 
+    {  14100   ,   -11864   } , 
+    {  14041   ,   -11933   } , 
+    {  13983   ,   -12002   } , 
+    {  13924   ,   -12070   } , 
+    {  13864   ,   -12138   } , 
+    {  13804   ,   -12206   } , 
+    {  13744   ,   -12274   } , 
+    {  13684   ,   -12341   } , 
+    {  13623   ,   -12408   } , 
+    {  13562   ,   -12475   } , 
+    {  13501   ,   -12541   } , 
+    {  13439   ,   -12608   } , 
+    {  13377   ,   -12673   } , 
+    {  13314   ,   -12739   } , 
+    {  13252   ,   -12804   } , 
+    {  13189   ,   -12869   } , 
+    {  13125   ,   -12934   } , 
+    {  13062   ,   -12998   } 
+    };
+cos_msin_t	s_cos_msin_64[DCT_LENGTH] = {
+{18426,	-21},
+{18426,	-66},
+{18426,	-110},
+{18426,	-154},
+{18425,	-198},
+{18425,	-242},
+{18424,	-286},
+{18424,	-331},
+{18423,	-374},
+{18421,	-419},
+{18421,	-463},
+{18419,	-507},
+{18418,	-552},
+{18417,	-595},
+{18415,	-639},
+{18414,	-684},
+{18412,	-728},
+{18410,	-772},
+{18408,	-816},
+{18406,	-860},
+{18404,	-904},
+{18402,	-949},
+{18400,	-992},
+{18397,	-1037},
+{18394,	-1081},
+{18392,	-1125},
+{18389,	-1169},
+{18387,	-1213},
+{18384,	-1257},
+{18380,	-1301},
+{18378,	-1345},
+{18374,	-1389},
+{18371,	-1433},
+{18367,	-1477},
+{18364,	-1521},
+{18360,	-1566},
+{18356,	-1609},
+{18352,	-1653},
+{18348,	-1697},
+{18344,	-1742},
+{18339,	-1785},
+{18335,	-1829},
+{18331,	-1873},
+{18326,	-1917},
+{18322,	-1961},
+{18317,	-2005},
+{18312,	-2049},
+{18307,	-2092},
+{18302,	-2137},
+{18297,	-2180},
+{18292,	-2224},
+{18286,	-2268},
+{18281,	-2312},
+{18275,	-2356},
+{18270,	-2399},
+{18264,	-2443},
+{18258,	-2487},
+{18252,	-2531},
+{18246,	-2574},
+{18240,	-2618},
+{18233,	-2662},
+{18227,	-2706},
+{18220,	-2749},
+{18214,	-2793},
+{18207,	-2836},
+{18200,	-2880},
+{18193,	-2924},
+{18186,	-2967},
+{18179,	-3011},
+{18172,	-3055},
+{18164,	-3098},
+{18157,	-3142},
+{18149,	-3185},
+{18141,	-3229},
+{18134,	-3272},
+{18126,	-3316},
+{18118,	-3359},
+{18109,	-3403},
+{18101,	-3446},
+{18094,	-3489},
+{18085,	-3533},
+{18076,	-3576},
+{18068,	-3619},
+{18059,	-3663},
+{18050,	-3706},
+{18041,	-3749},
+{18032,	-3792},
+{18023,	-3836},
+{18014,	-3879},
+{18005,	-3922},
+{17995,	-3965},
+{17986,	-4008},
+{17975,	-4051},
+{17966,	-4094},
+{17956,	-4138},
+{17946,	-4180},
+{17936,	-4224},
+{17926,	-4266},
+{17916,	-4309},
+{17905,	-4353},
+{17895,	-4395},
+{17884,	-4438},
+{17874,	-4481},
+{17863,	-4524},
+{17852,	-4567},
+{17841,	-4609},
+{17830,	-4652},
+{17819,	-4695},
+{17807,	-4738},
+{17796,	-4780},
+{17784,	-4823},
+{17772,	-4865},
+{17761,	-4908},
+{17749,	-4951},
+{17738,	-4993},
+{17725,	-5036},
+{17713,	-5078},
+{17701,	-5121},
+{17689,	-5163},
+{17676,	-5205},
+{17664,	-5248},
+{17651,	-5290},
+{17638,	-5333},
+{17626,	-5375},
+{17613,	-5417},
+{17599,	-5459},
+{17586,	-5501},
+{17573,	-5544},
+{17560,	-5586},
+{17546,	-5627},
+{17533,	-5670},
+{17519,	-5712},
+{17505,	-5753},
+{17492,	-5795},
+{17478,	-5837},
+{17464,	-5879},
+{17450,	-5921},
+{17435,	-5963},
+{17421,	-6005},
+{17406,	-6046},
+{17392,	-6088},
+{17377,	-6130},
+{17363,	-6172},
+{17348,	-6213},
+{17333,	-6254},
+{17318,	-6296},
+{17303,	-6338},
+{17288,	-6379},
+{17272,	-6420},
+{17257,	-6462},
+{17241,	-6503},
+{17225,	-6545},
+{17210,	-6586},
+{17194,	-6627},
+{17178,	-6668},
+{17162,	-6709},
+{17145,	-6750},
+{17130,	-6791},
+{17113,	-6832},
+{17097,	-6874},
+{17080,	-6915},
+{17064,	-6956},
+{17047,	-6996},
+{17030,	-7037},
+{17013,	-7078},
+{16996,	-7119},
+{16979,	-7159},
+{16962,	-7200},
+{16945,	-7241},
+{16927,	-7281},
+{16910,	-7322},
+{16892,	-7362},
+{16874,	-7403},
+{16856,	-7444},
+{16838,	-7484},
+{16821,	-7524},
+{16802,	-7564},
+{16784,	-7605},
+{16766,	-7645},
+{16748,	-7685},
+{16729,	-7725},
+{16711,	-7765},
+{16692,	-7805},
+{16674,	-7845},
+{16654,	-7885},
+{16635,	-7925},
+{16616,	-7964},
+{16597,	-8004},
+{16578,	-8044},
+{16559,	-8084},
+{16539,	-8124},
+{16520,	-8164},
+{16500,	-8203},
+{16480,	-8242},
+{16461,	-8282},
+{16441,	-8322},
+{16421,	-8361},
+{16401,	-8400},
+{16380,	-8440},
+{16360,	-8479},
+{16340,	-8518},
+{16319,	-8557},
+{16299,	-8597},
+{16278,	-8635},
+{16257,	-8674},
+{16237,	-8713},
+{16215,	-8752},
+{16195,	-8791},
+{16173,	-8829},
+{16152,	-8868},
+{16131,	-8907},
+{16110,	-8946},
+{16088,	-8985},
+{16067,	-9023},
+{16045,	-9061},
+{16023,	-9100},
+{16001,	-9138},
+{15979,	-9176},
+{15957,	-9215},
+{15935,	-9253},
+{15913,	-9291},
+{15891,	-9329},
+{15868,	-9367},
+{15846,	-9405},
+{15823,	-9443},
+{15800,	-9481},
+{15778,	-9519},
+{15755,	-9557},
+{15732,	-9595},
+{15709,	-9632},
+{15686,	-9670},
+{15662,	-9708},
+{15639,	-9745},
+{15615,	-9782},
+{15592,	-9820},
+{15569,	-9857},
+{15544,	-9894},
+{15521,	-9932},
+{15497,	-9969},
+{15473,	-10006},
+{15449,	-10043},
+{15425,	-10080},
+{15401,	-10117},
+{15377,	-10154},
+{15352,	-10191},
+{15327,	-10227},
+{15303,	-10264},
+{15278,	-10301},
+{15254,	-10337},
+{15229,	-10374},
+{15204,	-10411},
+{15180,	-10447},
+{15154,	-10483},
+{15129,	-10519},
+{15104,	-10556},
+{15078,	-10592},
+{15053,	-10628},
+{15027,	-10664},
+{15002,	-10700},
+{14976,	-10736},
+{14950,	-10772},
+{14924,	-10808},
+{14898,	-10844},
+{14872,	-10879},
+{14846,	-10915},
+{14820,	-10950},
+{14794,	-10985},
+{14767,	-11021},
+{14741,	-11056},
+{14714,	-11092},
+{14687,	-11127},
+{14661,	-11162},
+{14635,	-11197},
+{14607,	-11232},
+{14581,	-11267},
+{14554,	-11302},
+{14526,	-11337},
+{14499,	-11372},
+{14472,	-11407},
+{14444,	-11441},
+{14417,	-11476},
+{14389,	-11511},
+{14362,	-11545},
+{14334,	-11579},
+{14306,	-11614},
+{14278,	-11648},
+{14251,	-11682},
+{14222,	-11716},
+{14194,	-11750},
+{14166,	-11784},
+{14137,	-11818},
+{14109,	-11852},
+{14081,	-11886},
+{14053,	-11919},
+{14023,	-11953},
+{13995,	-11987},
+{13966,	-12020},
+{13937,	-12054},
+{13909,	-12087},
+{13879,	-12120},
+{13851,	-12153},
+{13821,	-12187},
+{13792,	-12220},
+{13763,	-12253},
+{13733,	-12286},
+{13704,	-12319},
+{13674,	-12351},
+{13645,	-12385},
+{13615,	-12417},
+{13585,	-12450},
+{13555,	-12482},
+{13525,	-12514},
+{13495,	-12546},
+{13465,	-12579},
+{13435,	-12611},
+{13405,	-12644},
+{13374,	-12676},
+{13345,	-12708},
+{13314,	-12739},
+{13283,	-12772}
+};
+
+
+
+cos_msin_t	*s_cos_msin_table[] = {s_cos_msin_2,  s_cos_msin_4,
+                                   s_cos_msin_8,  s_cos_msin_16,
+                                   s_cos_msin_32, s_cos_msin_64
+                                  };
+
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/decode/decoder.c b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/decode/decoder.c
new file mode 100644
index 0000000..ab81a30
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/decode/decoder.c
@@ -0,0 +1,1113 @@
+/***************************************************************************
+**
+**   ITU-T G.722.1 (2005-05) - Fixed point implementation for main body and Annex C
+**   > Software Release 2.1 (2008-06)
+**     (Simple repackaging; no change from 2005-05 Release 2.0 code)
+**
+**   � 2004 Polycom, Inc.
+**
+**   All rights reserved.
+**
+***************************************************************************/
+
+/***************************************************************************
+  Filename:    decoder.c    
+
+  Purpose:     Contains files used to implement the G.722.1 Annex C decoder
+		
+  Design Notes:
+
+***************************************************************************/
+
+/***************************************************************************
+ Include files                                                           
+***************************************************************************/
+#include "defs.h"
+#include "tables.h"
+#include "huff_def.h"
+#include "count.h"
+
+
+/***************************************************************************
+ Function:    decoder
+
+ Syntax:      void decoder(Bit_Obj *bitobj,                   
+                           Rand_Obj *randobj,             
+                           Word16 number_of_regions,
+                           Word16 *decoder_mlt_coefs,     
+                           Word16 *p_mag_shift,           
+                           Word16 *p_old_mag_shift,       
+                           Word16 *old_decoder_mlt_coefs,    
+                           Word16 frame_error_flag)      
+              
+              inputs:    Bit_Obj *bitobj
+                         Rand_Obj *randobj
+                         Word16 number_of_regions
+                         Word16 *p_old_mag_shift
+                         Word16 *old_decoder_mlt_coefs
+                         Word16 frame_error_flag
+              
+              outputs:   Word16 *decoder_mlt_coefs,    
+                         Word16 *p_mag_shift,          
+                  
+                  
+
+ Description: Decodes the out_words into mlt coefs using G.722.1 Annex C
+
+ Design Notes:
+ 
+ WMOPS:     7kHz |   24kbit    |    32kbit
+          -------|-------------|----------------
+            AVG  |    0.84     |    0.94
+          -------|-------------|----------------  
+            MAX  |    0.90     |    1.00
+          -------|-------------|---------------- 
+				
+           14kHz |   24kbit    |    32kbit      |     48kbit
+          -------|-------------|----------------|----------------
+            AVG  |    1.31     |    1.56        |     1.88   
+          -------|-------------|----------------|----------------
+            MAX  |    1.59     |    1.80        |     1.98   
+          -------|-------------|----------------|----------------
+				
+***************************************************************************/
+void decoder(Bit_Obj *bitobj,
+             Rand_Obj *randobj,
+             Word16 number_of_regions,
+	         Word16 *decoder_mlt_coefs,
+	         Word16 *p_mag_shift,
+             Word16 *p_old_mag_shift,
+             Word16 *old_decoder_mlt_coefs,
+             Word16 frame_error_flag)
+{
+
+
+    Word16  absolute_region_power_index[MAX_NUMBER_OF_REGIONS];
+    Word16  decoder_power_categories[MAX_NUMBER_OF_REGIONS];
+    Word16  decoder_category_balances[MAX_NUM_CATEGORIZATION_CONTROL_POSSIBILITIES-1];
+    UWord16 categorization_control;
+    Word16  decoder_region_standard_deviation[MAX_NUMBER_OF_REGIONS];
+    Word16  i;
+
+    Word16  num_categorization_control_bits;
+    Word16  num_categorization_control_possibilities;
+    Word16  number_of_coefs;
+    Word16  number_of_valid_coefs;
+    
+    
+    test();
+    if (number_of_regions==NUMBER_OF_REGIONS)
+    {
+        num_categorization_control_bits = NUM_CATEGORIZATION_CONTROL_BITS;
+        move16();
+        num_categorization_control_possibilities = NUM_CATEGORIZATION_CONTROL_POSSIBILITIES;
+        move16();
+        number_of_coefs = DCT_LENGTH;
+        move16();
+        number_of_valid_coefs = NUMBER_OF_VALID_COEFS;
+        move16();
+    }
+    else
+    {
+        num_categorization_control_bits = MAX_NUM_CATEGORIZATION_CONTROL_BITS;
+        move16();
+        num_categorization_control_possibilities = MAX_NUM_CATEGORIZATION_CONTROL_POSSIBILITIES;
+        move16();
+        number_of_coefs = MAX_DCT_LENGTH;
+        move16();
+        number_of_valid_coefs = MAX_NUMBER_OF_VALID_COEFS;
+        move16();
+    }
+
+    test();
+    if (frame_error_flag == 0) 
+    {
+
+        /* convert the bits to absolute region power index and decoder_region_standard_deviation */
+        
+        decode_envelope(bitobj,
+                        number_of_regions,
+                        decoder_region_standard_deviation,
+		                absolute_region_power_index,
+		                p_mag_shift);
+
+        /* fill the categorization_control with NUM_CATEGORIZATION_CONTROL_BITS */
+        categorization_control = 0;
+        for (i=0; i<num_categorization_control_bits; i++) 
+        {
+        	get_next_bit(bitobj);
+        	categorization_control = shl_nocheck(categorization_control,1);
+        	categorization_control = add(categorization_control,bitobj->next_bit);
+        }
+        
+        bitobj->number_of_bits_left = sub(bitobj->number_of_bits_left,num_categorization_control_bits);
+
+        /* obtain decoder power categories and category balances */
+        /* based on the absolute region power index              */
+        categorize(bitobj->number_of_bits_left,
+	               number_of_regions,
+	               num_categorization_control_possibilities,
+	               absolute_region_power_index,
+	               decoder_power_categories,
+	               decoder_category_balances);
+
+        /* perform adjustmaents to the power categories and category balances based on the cat control */
+        rate_adjust_categories(categorization_control,
+			                   decoder_power_categories,
+			                   decoder_category_balances);
+
+        /* decode the quantized bits into mlt coefs */
+        decode_vector_quantized_mlt_indices(bitobj,
+                                            randobj,
+                                            number_of_regions,
+                                            decoder_region_standard_deviation,
+					                        decoder_power_categories,
+					                        decoder_mlt_coefs);
+
+        /* test for frame errors */
+        test_4_frame_errors(bitobj,
+                            number_of_regions,
+                            num_categorization_control_possibilities,
+                            &frame_error_flag,
+                            categorization_control,
+                            absolute_region_power_index);
+    }
+
+    /* perform error handling operations */
+    error_handling(number_of_coefs,
+                   number_of_valid_coefs,
+                   &frame_error_flag,
+                   decoder_mlt_coefs,
+                   old_decoder_mlt_coefs,
+                   p_mag_shift,
+                   p_old_mag_shift);
+
+}
+
+/***************************************************************************
+ Function:    decode_envelope
+
+ Syntax:      void decode_envelope(Bit_Obj *bitobj,                              
+                                   Word16  number_of_regions,
+                                   Word16  *decoder_region_standard_deviation,   
+                                   Word16  *absolute_region_power_index,         
+                                   Word16  *p_mag_shift)                         
+              
+              inputs:   Bit_Obj *bitobj
+                        Word16  number_of_regions
+                        
+                        
+              outputs:  Word16  *decoder_region_standard_deviation
+                        Word16  *absolute_region_power_index
+                        Word16  *p_mag_shift
+              
+ 
+ Description: Recover differential_region_power_index from code bits
+
+ Design Notes:
+ 
+ WMOPS:     7kHz |    24kbit    |    32kbit
+          -------|--------------|----------------
+            AVG  |     0.04     |    0.04
+          -------|--------------|----------------  
+            MAX  |     0.05     |    0.05
+          -------|--------------|---------------- 
+				
+           14kHz |    24kbit    |    32kbit      |     48kbit
+          -------|--------------|----------------|----------------
+            AVG  |     0.08     |    0.08        |     0.08   
+          -------|--------------|----------------|----------------
+            MAX  |     0.10     |    0.10        |     0.10   
+          -------|--------------|----------------|----------------
+				
+***************************************************************************/
+void decode_envelope(Bit_Obj *bitobj,
+                     Word16  number_of_regions,
+                     Word16  *decoder_region_standard_deviation,
+		             Word16  *absolute_region_power_index,
+		             Word16  *p_mag_shift)
+     
+{
+    Word16 region;
+    Word16 i;
+    Word16 index;
+    Word16 differential_region_power_index[MAX_NUMBER_OF_REGIONS];
+    Word16 max_index;
+    
+    Word16 temp;
+    Word16 temp1;
+    Word16 temp2;
+    Word32 acca;
+
+    index = 0;
+    move16();
+
+    /* get 5 bits from the current code word */
+    for (i=0; i<5; i++) 
+    {
+        get_next_bit(bitobj);
+        index = shl_nocheck(index,1);
+        index = add(index,bitobj->next_bit);
+    }
+    bitobj->number_of_bits_left = sub(bitobj->number_of_bits_left,5);
+
+    /* ESF_ADJUSTMENT_TO_RMS_INDEX compensates for the current (9/30/96)
+        IMLT being scaled to high by the ninth power of sqrt(2). */
+    differential_region_power_index[0] = sub(index,ESF_ADJUSTMENT_TO_RMS_INDEX);
+    move16();
+
+    /* obtain differential_region_power_index */
+    for (region=1; region<number_of_regions; region++) 
+    {
+        index = 0;
+        move16();
+        do 
+        {
+            get_next_bit(bitobj);
+            test();
+            if (bitobj->next_bit == 0)
+            {
+	            index = differential_region_power_decoder_tree[region][index][0];
+                move16();
+            }
+            else
+            {
+	            index = differential_region_power_decoder_tree[region][index][1];
+                move16();
+            }
+            bitobj->number_of_bits_left = sub(bitobj->number_of_bits_left,1);
+            test();
+        } while (index > 0);
+        
+        differential_region_power_index[region] = negate(index);
+        move16();
+    }
+
+    /* Reconstruct absolute_region_power_index[] from differential_region_power_index[]. */
+    absolute_region_power_index[0] = differential_region_power_index[0];
+    move16();
+    for (region=1; region<number_of_regions; region++) 
+    {
+        acca = L_add(absolute_region_power_index[region-1],differential_region_power_index[region]);
+        acca = L_add(acca,DRP_DIFF_MIN);
+        absolute_region_power_index[region] = extract_l(acca);        
+    }
+
+    /* Reconstruct decoder_region_standard_deviation[] from absolute_region_power_index[]. */
+    /* DEBUG!!!! - This integer method jointly computes the mag_shift
+       and the standard deviations already mag_shift compensated. It
+       relies on REGION_POWER_STEPSIZE_DB being exactly 3.010299957 db
+       or a square root of 2 chnage in standard deviation. If
+       REGION_POWER_STEPSIZE_DB changes, this software must be
+       reworked. */
+
+    temp = 0;
+    move16();
+    max_index = 0;
+    move16();
+    for (region=0; region<number_of_regions; region++) 
+    {
+        acca = L_add(absolute_region_power_index[region],REGION_POWER_TABLE_NUM_NEGATIVES);
+        i = extract_l(acca);
+        
+        temp1 = sub(i,max_index);
+        test();
+        if (temp1 > 0) 
+        {
+            max_index = i;
+            move16();
+        }
+        temp = add(temp,int_region_standard_deviation_table[i]);
+    }
+    i = 9;
+    move16();
+
+    temp1 = sub(temp,8);
+    temp2 = sub(max_index,28);
+    test();
+    test();
+    logic16();
+    test();
+    logic16();
+    while ((i >= 0) && ((temp1 >= 0) || (temp2 > 0))) 
+    {
+        i = sub(i,1);
+        temp = shr_nocheck(temp,1);
+        max_index = sub(max_index,2);
+        temp1 = sub(temp,8);
+        temp2 = sub(max_index,28);
+        test();
+        test();
+        logic16();
+        test();
+        logic16();
+    }
+    
+    *p_mag_shift = i;
+    move16();
+    
+    /* pointer arithmetic */
+    temp = (Word16 )(REGION_POWER_TABLE_NUM_NEGATIVES + (*p_mag_shift * 2));
+    
+    for (region=0; region<number_of_regions; region++) 
+    {
+        acca = L_add(absolute_region_power_index[region],temp);
+        i = extract_l(acca);
+        decoder_region_standard_deviation[region] = int_region_standard_deviation_table[i];
+        move16();
+    }
+
+}
+
+/***************************************************************************
+ Function:     rate_adjust_categories
+
+ Syntax:       void rate_adjust_categories(Word16 categorization_control,            
+                                           Word16 *decoder_power_categories,         
+                                           Word16 *decoder_category_balances)        
+               
+               inputs:    Word16 categorization_control,   
+                          Word16 *decoder_power_categories,
+                          Word16 *decoder_category_balances
+                          
+               outputs:   Word16 categorization_control,   
+                          Word16 *decoder_power_categories,
+ 
+ Description:  Adjust the power categories based on the categorization control
+
+ Design Notes:
+ 
+ WMOPS:     7kHz |    24kbit    |    32kbit
+          -------|--------------|----------------
+            AVG  |    0.00      |    0.00
+          -------|--------------|----------------  
+            MAX  |    0.00      |    0.00
+          -------|--------------|---------------- 
+				
+           14kHz |    24kbit    |    32kbit      |     48kbit
+          -------|--------------|----------------|----------------
+            AVG  |    0.00      |    0.00        |     0.00   
+          -------|--------------|----------------|----------------
+            MAX  |    0.01      |    0.01        |     0.01   
+          -------|--------------|----------------|----------------
+				
+***************************************************************************/
+void rate_adjust_categories(Word16 categorization_control,
+			                Word16 *decoder_power_categories,
+			                Word16 *decoder_category_balances)
+{
+    Word16 i;
+    Word16 region;
+    
+    i = 0;
+    move16();
+
+    test();
+    while (categorization_control > 0) 
+    {
+        region = decoder_category_balances[i++];
+        move16();
+        decoder_power_categories[region] = add(decoder_power_categories[region],1);
+        move16();
+        categorization_control = sub(categorization_control,1);
+    }
+
+}
+
+/***************************************************************************
+ Function:    decode_vector_quantized_mlt_indices
+
+ Syntax:      void decode_vector_quantized_mlt_indices(Bit_Obj  *bitobj,                                      
+                                                       Rand_Obj *randobj,                           
+                                                       Word16   number_of_regions,
+                                                       Word16   *decoder_region_standard_deviation, 
+                                                       Word16   *decoder_power_categories,          
+                                                       Word16   *decoder_mlt_coefs)                 
+              inputs:    Bit_Obj  *bitobj                           
+                         Rand_Obj *randobj
+                         Word16   number_of_regions
+                         Word16   *decoder_region_standard_deviation
+                         Word16   *decoder_power_categories
+            
+            
+              outputs:   Word16   *decoder_mlt_coefs
+             
+
+ Description: Decode MLT coefficients
+
+ Design Notes:
+ 
+ WMOPS:     7kHz |    24kbit    |    32kbit
+          -------|--------------|----------------
+            AVG  |    0.60      |    0.72
+          -------|--------------|----------------  
+            MAX  |    0.67      |    0.76
+          -------|--------------|---------------- 
+				
+           14kHz |    24kbit    |    32kbit      |     48kbit
+          -------|--------------|----------------|----------------
+            AVG  |    0.77      |    0.98        |     1.28   
+          -------|--------------|----------------|----------------
+            MAX  |    1.05      |    1.18        |     1.36   
+          -------|--------------|----------------|----------------
+				
+***************************************************************************/
+void decode_vector_quantized_mlt_indices(Bit_Obj  *bitobj,
+                                         Rand_Obj *randobj,
+                                         Word16   number_of_regions,
+                                         Word16   *decoder_region_standard_deviation,
+					                     Word16   *decoder_power_categories,
+					                     Word16   *decoder_mlt_coefs)
+{
+    Word16 standard_deviation;
+    Word16 *decoder_mlt_ptr;
+    Word16 decoder_mlt_value;
+    Word16 noifillpos;
+    Word16 noifillneg;
+    Word16 noise_fill_factor[3] = {5793,8192,23170};
+    Word16 region;
+    Word16 category;
+    Word16 j,n;
+    Word16 k[MAX_VECTOR_DIMENSION];
+    Word16 vec_dim;
+    Word16 num_vecs;
+    Word16 index;
+    Word16 bit=0;
+    Word16 signs_index=0;
+    Word16 num_sign_bits;
+    Word16 ran_out_of_bits_flag;
+    Word16 *decoder_table_ptr;
+    Word16 random_word;
+    
+    Word16 temp1;
+    Word16 temp;
+    Word32 acca;
+
+    ran_out_of_bits_flag = 0;
+    move16();
+
+    for (region=0; region<number_of_regions; region++) 
+    {
+        category = (Word16)decoder_power_categories[region];
+        move16();
+        acca = L_mult0(region,REGION_SIZE);
+        index = extract_l(acca);
+        decoder_mlt_ptr = &decoder_mlt_coefs[index];
+        move16();
+        standard_deviation = decoder_region_standard_deviation[region];
+        move16();
+        
+        temp = sub(category,7);
+        test();
+        if (temp < 0)
+        {
+            /* Get the proper table of decoder tables, vec_dim, and num_vecs for the cat */
+            decoder_table_ptr = (Word16 *) table_of_decoder_tables[category];
+            move16();
+            vec_dim = vector_dimension[category];
+            move16();
+            num_vecs = number_of_vectors[category];
+            move16();
+            
+            for (n=0; n<num_vecs; n++) 
+            {
+                index = 0;
+                move16();
+                
+                /* get index */
+                do 
+                {
+                    test();
+                    if (bitobj->number_of_bits_left <= 0) 
+                    {
+                        ran_out_of_bits_flag = 1;
+                        move16();
+    	                break;
+    	            }
+    
+    	            get_next_bit(bitobj);
+	                
+                    test();
+                    if (bitobj->next_bit == 0)
+	                {
+                        temp = shl_nocheck(index,1);
+                        index = (Word16)*(decoder_table_ptr + temp);
+                        move16();
+                    }
+	                else
+	                {
+                        temp = shl_nocheck(index,1);
+                        index = (Word16)*(decoder_table_ptr + temp + 1);
+                        move16();
+                    }
+	                bitobj->number_of_bits_left = sub(bitobj->number_of_bits_left,1);
+                    test();
+	            
+                } while (index > 0);
+	  
+                test();
+                if (ran_out_of_bits_flag != 0)
+	                break;
+	  
+                index = negate(index);
+	            
+                /* convert index into array used to access the centroid table */
+                /* get the number of sign bits in the index */
+                num_sign_bits = index_to_array(index,k,category);
+
+	            temp = sub(bitobj->number_of_bits_left,num_sign_bits);
+                test();
+                if (temp >= 0) 
+                {
+
+	                test();
+                    if (num_sign_bits != 0) 
+                    {
+	                    signs_index = 0;
+	                    move16();
+                        for (j=0; j<num_sign_bits; j++) 
+                        {
+		                    get_next_bit(bitobj);
+       		                signs_index = shl_nocheck(signs_index,1);
+		                    signs_index = add(signs_index,bitobj->next_bit);
+		                    bitobj->number_of_bits_left = sub(bitobj->number_of_bits_left,1);
+	                    }
+	                    temp = sub(num_sign_bits,1);
+                        bit = shl_nocheck(1,(temp));
+	                }
+	                
+                    for (j=0; j<vec_dim; j++) 
+                    {
+	                    acca = L_mult0(standard_deviation,mlt_quant_centroid[category][k[j]]);
+                        acca = L_shr_nocheck(acca,12);
+                        decoder_mlt_value = extract_l(acca);
+	                    
+                        test();
+                        if (decoder_mlt_value != 0) 
+                        {
+		                    test();
+                            if ((signs_index & bit) == 0)
+		                        decoder_mlt_value = negate(decoder_mlt_value);
+		                    bit = shr_nocheck(bit,1);
+	                    }
+                        *decoder_mlt_ptr++ = decoder_mlt_value;
+                        move16();
+	                }
+	            }
+	            else 
+                {
+	                ran_out_of_bits_flag = 1;
+                    move16();
+	                break;
+	            }
+	        }
+            /* If ran out of bits during decoding do noise fill for remaining regions. */
+            /* DEBUG!! - For now also redo all of last region with all noise fill. */
+        	test();
+            if (ran_out_of_bits_flag != 0) 
+            {
+        	    temp = add(region,1);
+                for (j=temp; j<number_of_regions; j++)
+                {
+                    decoder_power_categories[j] = 7;
+                    move16();
+                }
+        	    category = 7;
+                move16();
+        	    decoder_mlt_ptr = &decoder_mlt_coefs[region*REGION_SIZE];
+                move16();
+        	}
+        }
+
+        temp = sub(category,5);
+        temp1 = sub(category,6);
+        test();
+        test();
+        logic16();
+        if ((temp == 0) || (temp1 == 0))
+        {
+ 
+	        decoder_mlt_ptr = &decoder_mlt_coefs[region*REGION_SIZE];
+	        move16();
+            noifillpos = mult(standard_deviation,noise_fill_factor[category - 5]);
+            noifillneg = negate(noifillpos);
+
+	        random_word = get_rand(randobj);
+
+	        for (j=0; j<10; j++) 
+            {
+	            test();
+                if (*decoder_mlt_ptr == 0) 
+                {
+	                logic16();
+                    test();
+                    if ((random_word & 1) == 0) 
+                    {
+                        temp1 = noifillneg;
+                        move16();
+                    }
+	                else
+                    {
+                        temp1 = noifillpos;
+                        move16();
+                    }
+	                *decoder_mlt_ptr = temp1;
+                    move16();
+	                random_word = shr_nocheck(random_word,1);
+	            }
+	            /* pointer arithmetic */
+                decoder_mlt_ptr++;
+	        }
+	        random_word = get_rand(randobj);
+	        for (j=0; j<10; j++) 
+            {
+	            test();
+                if (*decoder_mlt_ptr == 0) 
+                {
+	                logic16();
+                    test();
+                    if ((random_word & 1) == 0) 
+                    {
+                        temp1 = noifillneg;
+                        move16();
+                    }
+	                else
+                    {
+                        temp1 = noifillpos;
+                        move16();
+                    }
+	                *decoder_mlt_ptr = temp1;
+                    move16();
+	                random_word  = shr_nocheck(random_word,1);
+	            }
+	            /* pointer arithmetic */
+                decoder_mlt_ptr++;
+	        }
+        }
+
+        /* if (category == 7) */
+        temp1 = sub(category,7);
+        test();
+        if (temp1 == 0)
+        {
+	        index = sub(category,5);
+            noifillpos = mult(standard_deviation,noise_fill_factor[index]);
+	        noifillneg = negate(noifillpos);
+
+            random_word = get_rand(randobj);
+            for (j=0; j<10; j++) 
+            {
+                logic16();
+                test();
+                if ((random_word & 1) == 0) 
+                {
+                    temp1 = noifillneg;
+                    move16();
+                }
+                else
+                {
+                    temp1 = noifillpos;
+                    move16();
+                }
+                *decoder_mlt_ptr++ = temp1;
+                move16();
+                random_word = shr_nocheck(random_word,1);
+            }
+            random_word = get_rand(randobj);
+            for (j=0; j<10; j++) 
+            {
+                logic16();
+                test();
+                if ((random_word & 1) == 0) 
+                {
+                    temp1 = noifillneg;
+                    move16();
+                }
+                else
+                {
+                    temp1 = noifillpos;
+                    move16();
+                }
+                
+                *decoder_mlt_ptr++ = temp1;
+                move16();
+                random_word = shr_nocheck(random_word,1);
+            }
+        }
+    }
+
+    test();
+    if (ran_out_of_bits_flag)
+        bitobj->number_of_bits_left = sub(bitobj->number_of_bits_left,1);
+}
+/****************************************************************************************
+ Function:    index_to_array 
+
+ Syntax:      number_of_non_zero = index_to_array(Word16 index, 
+                                                  Word16 array[MAX_VECTOR_DIMENSION],
+                                                  Word16 category)
+
+                inputs:  Word16 index
+                         Word16 category                     
+                       
+                outputs: Word16 array[MAX_VECTOR_DIMENSION] - used in decoder to access
+                                                             mlt_quant_centroid table
+                        
+                         Word16 number_of_non_zero          - number of non zero elements
+                                                             in the array
+ 
+ Description: Computes an array of sign bits with the length of the category vector
+              Returns the number of sign bits and the array
+
+ WMOPS:     7kHz |    24kbit    |    32kbit
+          -------|--------------|----------------
+            AVG  |     0.00     |     0.00
+          -------|--------------|----------------  
+            MAX  |     0.00     |     0.00
+          -------|--------------|---------------- 
+
+           14kHz |    24kbit    |    32kbit      |     48kbit
+          -------|--------------|----------------|----------------
+            AVG  |     0.00     |     0.00       |      0.00   
+          -------|--------------|----------------|----------------
+            MAX  |     0.00     |     0.00       |      0.00   
+          -------|--------------|----------------|----------------
+
+****************************************************************************************/
+Word16 index_to_array(Word16 index,Word16 *array,Word16 category)
+{
+    Word16 j,q,p;
+    Word16 number_of_non_zero;
+    Word16 max_bin_plus_one;
+    Word16 inverse_of_max_bin_plus_one;
+    Word16 temp;
+
+    number_of_non_zero = 0;
+    move16();
+
+    p = index;
+    move16();
+
+    max_bin_plus_one = add(max_bin[category],1);
+    inverse_of_max_bin_plus_one = max_bin_plus_one_inverse[category];
+    move16();
+
+    temp = sub(vector_dimension[category],1);
+    for (j=temp; j>=0; j--) 
+    {
+        q = mult(p,inverse_of_max_bin_plus_one);
+		temp = extract_l(L_mult0(q,max_bin_plus_one));
+        array[j] = sub(p,temp);
+        move16();
+
+        p = q;
+        move16();
+
+        temp = array[j];
+        move16();
+        test();
+        if (temp != 0) 
+            number_of_non_zero = add(number_of_non_zero,1);
+    }
+    return(number_of_non_zero);
+}
+/***************************************************************************
+ Function:     test_4_frame_errors
+
+ Syntax:       void test_4_frame_errors(Bit_Obj *bitobj,                        
+                                        Word16 number_of_regions,
+                                        Word16 num_categorization_control_possibilities,
+                                        Word16 *frame_error_flag,                
+                                        Word16 categorization_control,          
+                                        Word16 *absolute_region_power_index)    
+        
+               inputs:   bit_obj
+                         number_of_regions
+                         num_categorization_control_possibilities
+                         frame_error_flag
+                         categorization_control
+                         absolute_region_power_index
+               
+               
+               outputs:  frame_error_flag
+               
+               
+               
+        
+ Description:  Tests for error conditions and sets the frame_error_flag accordingly 
+
+ Design Notes:
+ 
+ WMOPS:     7kHz |    24kbit    |    32kbit
+          -------|--------------|----------------
+            AVG  |    0.01      |     0.01
+          -------|--------------|----------------  
+            MAX  |    0.04      |     0.08
+          -------|--------------|---------------- 
+				
+           14kHz |    24kbit    |    32kbit      |     48kbit
+          -------|--------------|----------------|----------------
+            AVG  |    0.01      |     0.01       |      0.01   
+          -------|--------------|----------------|----------------
+            MAX  |    0.02      |     0.06       |      0.08   
+          -------|--------------|----------------|----------------
+				
+***************************************************************************/
+void test_4_frame_errors(Bit_Obj *bitobj,
+                         Word16 number_of_regions,
+                         Word16 num_categorization_control_possibilities,
+                         Word16 *frame_error_flag,
+                         Word16 categorization_control,
+                         Word16 *absolute_region_power_index)
+{
+    Word16 region;
+    Word16 i;
+    Word16 temp;
+    Word32 acca;
+    Word32 accb;
+    
+    /* Test for bit stream errors. */
+
+    test();
+    if (bitobj->number_of_bits_left > 0) 
+    {
+        for (i=0; i<bitobj->number_of_bits_left; i++) 
+        {
+            get_next_bit(bitobj);
+            test();
+            if (bitobj->next_bit == 0) 
+            {
+                *frame_error_flag = 1;
+                move16();
+            }
+        }	
+    }
+    else 
+    {
+        temp = sub(categorization_control,sub(num_categorization_control_possibilities,1));
+        test();
+        if (temp < 0) 
+        {
+            test();
+            if (bitobj->number_of_bits_left < 0)
+            {
+                *frame_error_flag |= 2;
+                logic16();
+            }
+        }
+    }
+
+    /* checks to ensure that abs_region_power_index is within range */
+    /* the error flag is set if it is out of range */
+    for (region=0; region<number_of_regions; region++) 
+    {
+        /*  the next two lines of comments were modified in release 1.2
+	   *  to correct the description of the range of 
+	   *  absolute_region_power_index[] to be tested in the next
+	   *  9 lines of code.
+	   */
+	  /*  if ((absolute_region_power_index[region] > 31) ||
+            (absolute_region_power_index[region] < -8) */
+
+        acca = L_add(absolute_region_power_index[region],ESF_ADJUSTMENT_TO_RMS_INDEX);
+        accb = L_sub(acca,31);
+        acca = L_add(acca,8);
+        test();
+
+        /* the next line was modifed in release 1.2 to
+	   * correct miss typed code and error checking.
+	   */
+        if ((accb > 0) || (acca < 0))
+        {
+            *frame_error_flag |= 4;
+            logic16();
+        }
+    }
+
+}
+/***************************************************************************
+ Function:    error_handling
+
+ Syntax:      void error_handling(Word16 number_of_coefs,
+                                  Word16 number_of_valid_coefs,
+                                  Word16 *frame_error_flag,     
+                                  Word16 *decoder_mlt_coefs,    
+                                  Word16 *old_decoder_mlt_coefs,
+                                  Word16 *p_mag_shift,          
+                                  Word16 *p_old_mag_shift)      
+              
+              inputs:  number_of_coefs
+                       number_of_valid_coefs
+                       frame_error_flag
+                       old_decoder_mlt_coefs
+                       p_old_mag_shift
+              
+              
+              outputs: decoder_mlt_coefs
+                       old_decoder_mlt_coefs
+                       p_mag_shift
+                       p_old_mag_shift
+ 
+       
+
+ Description: If both the current and previous frames are errored,             
+              set the mlt coefficients to 0. If only the current frame         
+              is errored, then repeat the previous frame's mlt coefficients.   
+    
+ Design Notes:
+ 
+ WMOPS:     7kHz |    24kbit    |    32kbit
+          -------|--------------|----------------
+            AVG  |    0.02      |     0.02
+          -------|--------------|----------------  
+            MAX  |    0.03      |     0.03
+          -------|--------------|---------------- 
+				
+           14kHz |    24kbit    |    32kbit      |     48kbit
+          -------|--------------|----------------|----------------
+            AVG  |    0.03      |     0.03       |     0.03   
+          -------|--------------|----------------|----------------
+            MAX  |    0.03      |     0.03       |     0.06   
+          -------|--------------|----------------|----------------
+				
+***************************************************************************/
+void error_handling(Word16 number_of_coefs,
+                    Word16 number_of_valid_coefs,
+                    Word16 *frame_error_flag,
+                    Word16 *decoder_mlt_coefs,
+                    Word16 *old_decoder_mlt_coefs,
+                    Word16 *p_mag_shift,
+                    Word16 *p_old_mag_shift)
+{
+    Word16 i;
+
+    test();
+    if (*frame_error_flag != 0) 
+    {
+
+        for (i = 0; i < number_of_valid_coefs; i++)
+        {
+            decoder_mlt_coefs[i] = old_decoder_mlt_coefs[i];
+            move16();
+        }
+
+        for (i = 0; i < number_of_valid_coefs; i++)
+        {
+            old_decoder_mlt_coefs[i] = 0;
+            move16();
+        }
+        
+        *p_mag_shift = *p_old_mag_shift;
+        move16();
+
+        *p_old_mag_shift = 0;
+        move16();
+    }
+    else 
+    {
+        /* Store in case next frame is errored. */
+        for (i = 0; i < number_of_valid_coefs; i++)
+        {
+            old_decoder_mlt_coefs[i] = decoder_mlt_coefs[i];
+            move16();
+        }
+  
+        *p_old_mag_shift = *p_mag_shift;
+        move16();
+    }
+
+
+    /* Zero out the upper 1/8 of the spectrum. */
+    for (i = number_of_valid_coefs; i < number_of_coefs; i++)
+    {
+        decoder_mlt_coefs[i] = 0;
+        move16();
+    }
+
+}
+/****************************************************************************************
+ Function:    get_next_bit
+
+ Syntax:      void get_next_bit(Bit_Obj *bitobj)
+ 
+ Description: Returns the next bit in the current word inside the bit object
+ 
+ WMOPS:     7kHz |    24kbit    |    32kbit
+          -------|--------------|----------------
+            AVG  |    0.00      |    0.00
+          -------|--------------|----------------  
+            MAX  |    0.00      |    0.00
+          -------|--------------|---------------- 
+
+           14kHz |    24kbit    |    32kbit      |     48kbit
+          -------|--------------|----------------|----------------
+            AVG  |    0.00      |    0.00        |     0.00   
+          -------|--------------|----------------|----------------
+            MAX  |    0.00      |    0.00        |     0.00   
+          -------|--------------|----------------|----------------
+
+****************************************************************************************/
+void get_next_bit(Bit_Obj *bitobj)
+{
+    Word16 temp;
+
+    test();
+    if (bitobj->code_bit_count == 0)
+    {                        
+        bitobj->current_word = *bitobj->code_word_ptr++; 
+        move16();
+        bitobj->code_bit_count = 16;           
+        move16();
+    }
+    bitobj->code_bit_count = sub(bitobj->code_bit_count,1);
+    temp = shr_nocheck(bitobj->current_word,bitobj->code_bit_count);
+    logic16();
+    bitobj->next_bit = (Word16 )(temp & 1);
+
+}
+/****************************************************************************************
+ Function:    get_rand
+
+ Syntax:      Word16 get_rand(Rand_Obj *randobj)
+ 
+ Description: Returns a random Word16 based on the seeds inside the rand object  
+ 
+ WMOPS:     7kHz |    24kbit    |    32kbit
+          -------|--------------|----------------
+            AVG  |    0.00      |    0.00
+          -------|--------------|----------------  
+            MAX  |    0.00      |    0.00
+          -------|--------------|---------------- 
+
+           14kHz |    24kbit    |    32kbit      |     48kbit
+          -------|--------------|----------------|----------------
+            AVG  |    0.00      |    0.00        |     0.00   
+          -------|--------------|----------------|----------------
+            MAX  |    0.00      |    0.00        |     0.00   
+          -------|--------------|----------------|----------------
+
+****************************************************************************************/
+Word16 get_rand(Rand_Obj *randobj)
+{
+    Word16 random_word;
+    Word32 acca;
+
+    acca = L_add(randobj->seed0,randobj->seed3); 
+    random_word = extract_l(acca);
+    
+    logic16();
+    test();
+	if ((random_word & 32768L) != 0)
+        random_word = add(random_word,1);
+    
+    randobj->seed3 = randobj->seed2;
+    move16();
+    randobj->seed2 = randobj->seed1;
+    move16();
+    randobj->seed1 = randobj->seed0;
+    move16();
+    randobj->seed0 = random_word;
+    move16();
+
+    return(random_word);
+}
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/encode/dct4_a.c b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/encode/dct4_a.c
new file mode 100644
index 0000000..94ddf9f
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/encode/dct4_a.c
@@ -0,0 +1,367 @@
+/*********************************************************************************
+**   ITU-T G.722.1 (2005-05) - Fixed point implementation for main body and Annex C
+**   > Software Release 2.1 (2008-06)
+**     (Simple repackaging; no change from 2005-05 Release 2.0 code)
+**
+**   � 2004 Polycom, Inc.
+**
+**	 All rights reserved.
+**
+*********************************************************************************/
+
+/*********************************************************************************
+* Filename: dct_type_iv_a.c
+*
+* Purpose:  Discrete Cosine Transform, Type IV used for MLT
+*
+* The basis functions are
+*
+*	 cos(PI*(t+0.5)*(k+0.5)/block_length)
+*
+* for time t and basis function number k.  Due to the symmetry of the expression
+* in t and k, it is clear that the forward and inverse transforms are the same.
+*
+*********************************************************************************/
+
+/*********************************************************************************
+ Include files                                                           
+*********************************************************************************/
+#include "defs.h"
+#include "count.h"
+#include "dct4_a.h"
+
+/*********************************************************************************
+ External variable declarations                                          
+*********************************************************************************/
+extern Word16       anal_bias[DCT_LENGTH];
+extern Word16       dct_core_a[DCT_LENGTH_DIV_32][DCT_LENGTH_DIV_32];
+extern cos_msin_t   a_cos_msin_2 [DCT_LENGTH_DIV_32];
+extern cos_msin_t   a_cos_msin_4 [DCT_LENGTH_DIV_16];
+extern cos_msin_t   a_cos_msin_8 [DCT_LENGTH_DIV_8];
+extern cos_msin_t   a_cos_msin_16[DCT_LENGTH_DIV_4];
+extern cos_msin_t   a_cos_msin_32[DCT_LENGTH_DIV_2];
+extern cos_msin_t   a_cos_msin_64[DCT_LENGTH];
+extern cos_msin_t   *a_cos_msin_table[];
+
+/*********************************************************************************
+ Function:    dct_type_iv_a
+
+ Syntax:      void dct_type_iv_a (input, output, dct_length) 
+                        Word16   input[], output[], dct_length;              
+
+ Description: Discrete Cosine Transform, Type IV used for MLT
+
+ Design Notes:
+                
+ WMOPS:          |    24kbit    |     32kbit
+          -------|--------------|----------------
+            AVG  |    1.14      |     1.14
+          -------|--------------|----------------  
+            MAX  |    1.14      |     1.14
+          -------|--------------|---------------- 
+                
+           14kHz |    24kbit    |     32kbit     |     48kbit
+          -------|--------------|----------------|----------------
+            AVG  |    2.57      |     2.57       |     2.57
+          -------|--------------|----------------|----------------
+            MAX  |    2.57      |     2.57       |     2.57
+          -------|--------------|----------------|----------------
+
+*********************************************************************************/
+
+void dct_type_iv_a (Word16 *input,Word16 *output,Word16 dct_length)
+{
+    Word16   buffer_a[MAX_DCT_LENGTH], buffer_b[MAX_DCT_LENGTH], buffer_c[MAX_DCT_LENGTH];
+    Word16   *in_ptr, *in_ptr_low, *in_ptr_high, *next_in_base;
+    Word16   *out_ptr_low, *out_ptr_high, *next_out_base;
+    Word16   *out_buffer, *in_buffer, *buffer_swap;
+    Word16   in_val_low, in_val_high;
+    Word16   out_val_low, out_val_high;
+    Word16   in_low_even, in_low_odd;
+    Word16   in_high_even, in_high_odd;
+    Word16   out_low_even, out_low_odd;
+    Word16   out_high_even, out_high_odd;
+    Word16   *pair_ptr;
+    Word16   cos_even, cos_odd, msin_even, msin_odd;
+    Word16   neg_cos_odd;
+    Word16   neg_msin_even;
+    Word32   sum;
+    Word16   set_span, set_count, set_count_log, pairs_left, sets_left;
+    Word16   i,k;
+    Word16   index;
+    cos_msin_t  **table_ptr_ptr, *cos_msin_ptr;
+    
+    Word16   temp;
+    Word32   acca;
+
+    Word16   dct_length_log;
+
+
+    /*++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+    /* Do the sum/difference butterflies, the first part of */
+    /* converting one N-point transform into N/2 two-point  */
+    /* transforms, where N = 1 << DCT_LENGTH_LOG. = 64/128  */
+    /*++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+    test();
+    if (dct_length==DCT_LENGTH)
+    {
+        dct_length_log = DCT_LENGTH_LOG;
+
+        /* Add bias offsets */
+        for (i=0;i<dct_length;i++)
+        {
+            input[i] = add(input[i],anal_bias[i]);
+            move16();
+        }
+    }
+    else
+        dct_length_log = MAX_DCT_LENGTH_LOG;
+
+    index = 0L;
+    move16();
+
+    in_buffer  = input;
+    move16();
+
+    out_buffer = buffer_a;
+    move16();
+
+    temp = sub(dct_length_log,2);
+    for (set_count_log=0;set_count_log<=temp;set_count_log++)
+    {
+
+        /*===========================================================*/
+        /* Initialization for the loop over sets at the current size */
+        /*===========================================================*/
+
+        /*    set_span      = 1 << (DCT_LENGTH_LOG - set_count_log); */
+        set_span = shr_nocheck(dct_length,set_count_log);
+
+        set_count     = shl_nocheck(1,set_count_log);
+
+        in_ptr        = in_buffer;
+        move16();
+
+        next_out_base = out_buffer;
+        move16();
+
+        /*=====================================*/
+        /* Loop over all the sets of this size */
+        /*=====================================*/
+
+        for (sets_left=set_count;sets_left>0;sets_left--)
+        {
+
+            /*||||||||||||||||||||||||||||||||||||||||||||*/
+            /* Set up output pointers for the current set */
+            /*||||||||||||||||||||||||||||||||||||||||||||*/
+
+            out_ptr_low    = next_out_base;
+            next_out_base  = next_out_base + set_span;
+            out_ptr_high   = next_out_base;
+
+            /*||||||||||||||||||||||||||||||||||||||||||||||||||*/
+            /* Loop over all the butterflies in the current set */
+            /*||||||||||||||||||||||||||||||||||||||||||||||||||*/
+
+            do 
+            {
+                in_val_low      = *in_ptr++;
+                in_val_high     = *in_ptr++;
+		// blp: addition of two 16bits vars, there's no way
+		//      they'll overflow a 32bit var
+                //acca            = L_add(in_val_low,in_val_high);
+		acca = (in_val_low + in_val_high);
+		acca            = L_shr_nocheck(acca,1);
+                out_val_low     = extract_l(acca);
+
+                acca            = L_sub(in_val_low,in_val_high);
+                acca            = L_shr_nocheck(acca,1);
+                out_val_high    = extract_l(acca);
+
+                *out_ptr_low++  = out_val_low;
+                *--out_ptr_high = out_val_high;
+
+                test();
+            } while (out_ptr_low < out_ptr_high);
+
+        } /* End of loop over sets of the current size */
+
+        /*============================================================*/
+        /* Decide which buffers to use as input and output next time. */
+        /* Except for the first time (when the input buffer is the    */
+        /* subroutine input) we just alternate the local buffers.     */
+        /*============================================================*/
+
+        in_buffer = out_buffer;
+        move16();
+        if (out_buffer == buffer_a)
+            out_buffer = buffer_b;
+        else
+            out_buffer = buffer_a;
+        index = add(index,1);
+
+    } /* End of loop over set sizes */
+
+
+    /*++++++++++++++++++++++++++++++++*/
+    /* Do N/2 two-point transforms,   */
+    /* where N =  1 << DCT_LENGTH_LOG */
+    /*++++++++++++++++++++++++++++++++*/
+
+    pair_ptr = in_buffer;
+    move16();
+
+    buffer_swap = buffer_c;
+    move16();
+
+    temp = sub(dct_length_log,1);
+    temp = shl_nocheck(1,temp);
+
+    for (pairs_left=temp; pairs_left > 0; pairs_left--)
+    {
+        for ( k=0; k<CORE_SIZE; k++ )
+        {
+#if PJ_HAS_INT64
+	    /* blp: danger danger! not really compatible but faster */
+	    pj_int64_t sum64=0;
+            move32();
+            
+            for ( i=0; i<CORE_SIZE; i++ )
+            {
+                sum64 += L_mult(pair_ptr[i], dct_core_a[i][k]);
+            }
+	    sum = L_saturate(sum64);
+#else
+            sum=0L;
+            move32();
+            for ( i=0; i<CORE_SIZE; i++ )
+            {
+                sum = L_mac(sum, pair_ptr[i],dct_core_a[i][k]);
+            }
+#endif
+            buffer_swap[k] = itu_round(sum);
+        }
+        /* address arithmetic */
+        pair_ptr   += CORE_SIZE;
+        buffer_swap += CORE_SIZE;
+    }
+
+    for (i=0;i<dct_length;i++)
+    {
+        in_buffer[i] = buffer_c[i];
+        move16();
+    }
+    
+    table_ptr_ptr = a_cos_msin_table;
+
+    /*++++++++++++++++++++++++++++++*/
+    /* Perform rotation butterflies */
+    /*++++++++++++++++++++++++++++++*/
+    temp = sub(dct_length_log,2);
+    for (set_count_log = temp; set_count_log >= 0;    set_count_log--)
+    {
+        /*===========================================================*/
+        /* Initialization for the loop over sets at the current size */
+        /*===========================================================*/
+        /*    set_span      = 1 << (DCT_LENGTH_LOG - set_count_log); */
+        set_span = shr_nocheck(dct_length,set_count_log);
+
+        set_count     = shl_nocheck(1,set_count_log);
+        next_in_base  = in_buffer;
+        move16();
+
+        test();
+        if (set_count_log == 0)
+        {
+            next_out_base = output;
+        }
+        else
+        {
+            next_out_base = out_buffer;
+        }
+
+
+        /*=====================================*/
+        /* Loop over all the sets of this size */
+        /*=====================================*/
+        for (sets_left = set_count; sets_left > 0;sets_left--)
+        {
+            /*|||||||||||||||||||||||||||||||||||||||||*/
+            /* Set up the pointers for the current set */
+            /*|||||||||||||||||||||||||||||||||||||||||*/
+            in_ptr_low     = next_in_base;
+            move16();
+            temp           = shr_nocheck(set_span,1);
+
+            /* address arithmetic */
+            in_ptr_high    = in_ptr_low + temp;
+            next_in_base  += set_span;
+            out_ptr_low    = next_out_base;
+            next_out_base += set_span;
+            out_ptr_high   = next_out_base;
+            cos_msin_ptr   = *table_ptr_ptr;
+
+            /*||||||||||||||||||||||||||||||||||||||||||||||||||||||*/
+            /* Loop over all the butterfly pairs in the current set */
+            /*||||||||||||||||||||||||||||||||||||||||||||||||||||||*/
+
+            do 
+            {
+                /* address arithmetic */
+                in_low_even     = *in_ptr_low++;
+                in_low_odd      = *in_ptr_low++;
+                in_high_even    = *in_ptr_high++;
+                in_high_odd     = *in_ptr_high++;
+                cos_even        = cos_msin_ptr[0].cosine;
+                move16();
+                msin_even       = cos_msin_ptr[0].minus_sine;
+                move16();
+                cos_odd         = cos_msin_ptr[1].cosine;
+                move16();
+                msin_odd        = cos_msin_ptr[1].minus_sine;
+                move16();
+                cos_msin_ptr   += 2;
+
+                sum = 0L;
+                sum=L_mac(sum,cos_even,in_low_even);
+                neg_msin_even = negate(msin_even);
+                sum=L_mac(sum,neg_msin_even,in_high_even);
+                out_low_even = itu_round(sum);
+
+                sum = 0L;
+                sum=L_mac(sum,msin_even,in_low_even);
+                sum=L_mac(sum,cos_even,in_high_even);
+                out_high_even= itu_round(sum);
+
+                sum = 0L;
+                sum=L_mac(sum,cos_odd,in_low_odd);
+                sum=L_mac(sum,msin_odd,in_high_odd);
+                out_low_odd= itu_round(sum);
+
+                sum = 0L;
+                sum=L_mac(sum,msin_odd,in_low_odd);
+                neg_cos_odd = negate(cos_odd);
+                sum=L_mac(sum,neg_cos_odd,in_high_odd);
+                out_high_odd= itu_round(sum);
+
+                *out_ptr_low++  = out_low_even;
+                *--out_ptr_high = out_high_even;
+                *out_ptr_low++  = out_low_odd;
+                *--out_ptr_high = out_high_odd;
+                test();
+            } while (out_ptr_low < out_ptr_high);
+
+        } /* End of loop over sets of the current size */
+
+        /*=============================================*/
+        /* Swap input and output buffers for next time */
+        /*=============================================*/
+
+        buffer_swap = in_buffer;
+        in_buffer   = out_buffer;
+        out_buffer  = buffer_swap;
+        table_ptr_ptr++;
+    }
+}
+
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/encode/dct4_a.h b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/encode/dct4_a.h
new file mode 100644
index 0000000..74f3d93
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/encode/dct4_a.h
@@ -0,0 +1,728 @@
+/****************************************************************************
+**
+**   ITU-T G.722.1 (2005-05) - Fixed point implementation for main body and Annex C
+**   > Software Release 2.1 (2008-06)
+**     (Simple repackaging; no change from 2005-05 Release 2.0 code)
+**
+**   � 2004 Polycom, Inc.
+**
+**	 All rights reserved.
+**
+****************************************************************************/
+
+/****************************************************************************
+  Filename:    dct4_a.h    
+
+  Purpose:     Contains tables used by dct4_a.c
+		
+  Design Notes:
+
+****************************************************************************/
+
+/***************************************************************************
+ Include files                                                           
+***************************************************************************/
+#include <stdio.h>
+#include <math.h>
+
+typedef struct 
+{
+    Word16	cosine;
+    Word16	minus_sine;
+} cos_msin_t;
+
+cos_msin_t	a_cos_msin_2[10] = {
+    {  29805   ,   -1171   } , 
+    {  29621   ,   -3506   } , 
+    {  29255   ,   -5819   } , 
+    {  28708   ,   -8097   } , 
+    {  27984   ,   -10324   } , 
+    {  27088   ,   -12488   } , 
+    {  26025   ,   -14575   } , 
+    {  24801   ,   -16572   } , 
+    {  23425   ,   -18466   } , 
+    {  21903   ,   -20247   }  
+    }; 
+cos_msin_t	a_cos_msin_4[20] = {
+    {  29822   ,   -586   } , 
+    {  29776   ,   -1756   } , 
+    {  29684   ,   -2924   } , 
+    {  29547   ,   -4087   } , 
+    {  29364   ,   -5244   } , 
+    {  29135   ,   -6392   } , 
+    {  28862   ,   -7531   } , 
+    {  28544   ,   -8659   } , 
+    {  28182   ,   -9773   } , 
+    {  27776   ,   -10871   } , 
+    {  27328   ,   -11954   } , 
+    {  26838   ,   -13017   } , 
+    {  26306   ,   -14061   } , 
+    {  25734   ,   -15083   } , 
+    {  25122   ,   -16081   } , 
+    {  24471   ,   -17055   } , 
+    {  23783   ,   -18003   } , 
+    {  23057   ,   -18923   } , 
+    {  22297   ,   -19813   } , 
+    {  21502   ,   -20673   } 
+    };
+cos_msin_t	a_cos_msin_8[40] = {
+    {  29827   ,   -293   } , 
+    {  29815   ,   -878   } , 
+    {  29792   ,   -1464   } , 
+    {  29758   ,   -2048   } , 
+    {  29712   ,   -2632   } , 
+    {  29654   ,   -3215   } , 
+    {  29586   ,   -3797   } , 
+    {  29505   ,   -4377   } , 
+    {  29414   ,   -4955   } , 
+    {  29311   ,   -5532   } , 
+    {  29196   ,   -6106   } , 
+    {  29071   ,   -6678   } , 
+    {  28934   ,   -7248   } , 
+    {  28786   ,   -7814   } , 
+    {  28627   ,   -8378   } , 
+    {  28457   ,   -8938   } , 
+    {  28276   ,   -9495   } , 
+    {  28084   ,   -10049   } , 
+    {  27882   ,   -10598   } , 
+    {  27668   ,   -11144   } , 
+    {  27444   ,   -11685   } , 
+    {  27209   ,   -12221   } , 
+    {  26964   ,   -12753   } , 
+    {  26709   ,   -13280   } , 
+    {  26443   ,   -13802   } , 
+    {  26167   ,   -14318   } , 
+    {  25881   ,   -14829   } , 
+    {  25584   ,   -15335   } , 
+    {  25278   ,   -15834   } , 
+    {  24963   ,   -16327   } , 
+    {  24637   ,   -16814   } , 
+    {  24302   ,   -17295   } , 
+    {  23958   ,   -17769   } , 
+    {  23605   ,   -18236   } , 
+    {  23242   ,   -18695   } , 
+    {  22871   ,   -19148   } , 
+    {  22490   ,   -19594   } , 
+    {  22101   ,   -20031   } , 
+    {  21704   ,   -20461   } , 
+    {  21298   ,   -20884   } 
+    };
+cos_msin_t	a_cos_msin_16[80] = {
+    {  29828   ,   -146   } , 
+    {  29825   ,   -439   } , 
+    {  29819   ,   -732   } , 
+    {  29811   ,   -1025   } , 
+    {  29799   ,   -1317   } , 
+    {  29785   ,   -1610   } , 
+    {  29767   ,   -1902   } , 
+    {  29747   ,   -2194   } , 
+    {  29724   ,   -2486   } , 
+    {  29698   ,   -2778   } , 
+    {  29670   ,   -3069   } , 
+    {  29638   ,   -3360   } , 
+    {  29604   ,   -3651   } , 
+    {  29567   ,   -3942   } , 
+    {  29526   ,   -4232   } , 
+    {  29483   ,   -4521   } , 
+    {  29438   ,   -4811   } , 
+    {  29389   ,   -5099   } , 
+    {  29338   ,   -5388   } , 
+    {  29283   ,   -5676   } , 
+    {  29226   ,   -5963   } , 
+    {  29166   ,   -6249   } , 
+    {  29103   ,   -6535   } , 
+    {  29038   ,   -6821   } , 
+    {  28969   ,   -7106   } , 
+    {  28898   ,   -7390   } , 
+    {  28824   ,   -7673   } , 
+    {  28748   ,   -7956   } , 
+    {  28668   ,   -8237   } , 
+    {  28586   ,   -8518   } , 
+    {  28501   ,   -8799   } , 
+    {  28413   ,   -9078   } , 
+    {  28323   ,   -9357   } , 
+    {  28229   ,   -9634   } , 
+    {  28133   ,   -9911   } , 
+    {  28035   ,   -10187   } , 
+    {  27933   ,   -10461   } , 
+    {  27829   ,   -10735   } , 
+    {  27723   ,   -11008   } , 
+    {  27613   ,   -11279   } , 
+    {  27501   ,   -11550   } , 
+    {  27387   ,   -11819   } , 
+    {  27269   ,   -12088   } , 
+    {  27149   ,   -12355   } , 
+    {  27027   ,   -12621   } , 
+    {  26901   ,   -12885   } , 
+    {  26774   ,   -13149   } , 
+    {  26643   ,   -13411   } , 
+    {  26510   ,   -13672   } , 
+    {  26375   ,   -13932   } , 
+    {  26237   ,   -14190   } , 
+    {  26096   ,   -14447   } , 
+    {  25953   ,   -14702   } , 
+    {  25807   ,   -14956   } , 
+    {  25659   ,   -15209   } , 
+    {  25509   ,   -15460   } , 
+    {  25356   ,   -15710   } , 
+    {  25200   ,   -15958   } , 
+    {  25043   ,   -16205   } , 
+    {  24882   ,   -16450   } , 
+    {  24720   ,   -16693   } , 
+    {  24554   ,   -16935   } , 
+    {  24387   ,   -17175   } , 
+    {  24217   ,   -17414   } , 
+    {  24045   ,   -17651   } , 
+    {  23871   ,   -17886   } , 
+    {  23694   ,   -18119   } , 
+    {  23515   ,   -18351   } , 
+    {  23334   ,   -18581   } , 
+    {  23150   ,   -18809   } , 
+    {  22964   ,   -19036   } , 
+    {  22776   ,   -19260   } , 
+    {  22586   ,   -19483   } , 
+    {  22394   ,   -19704   } , 
+    {  22199   ,   -19923   } , 
+    {  22003   ,   -20140   } , 
+    {  21804   ,   -20355   } , 
+    {  21603   ,   -20568   } , 
+    {  21400   ,   -20779   } , 
+    {  21195   ,   -20988   } 
+    };
+cos_msin_t	a_cos_msin_32[160]= {
+    {  29828   ,   -73   } , 
+    {  29827   ,   -220   } , 
+    {  29826   ,   -366   } , 
+    {  29824   ,   -512   } , 
+    {  29821   ,   -659   } , 
+    {  29817   ,   -805   } , 
+    {  29813   ,   -952   } , 
+    {  29808   ,   -1098   } , 
+    {  29802   ,   -1244   } , 
+    {  29796   ,   -1390   } , 
+    {  29789   ,   -1537   } , 
+    {  29781   ,   -1683   } , 
+    {  29772   ,   -1829   } , 
+    {  29763   ,   -1975   } , 
+    {  29753   ,   -2121   } , 
+    {  29742   ,   -2267   } , 
+    {  29730   ,   -2413   } , 
+    {  29718   ,   -2559   } , 
+    {  29705   ,   -2705   } , 
+    {  29692   ,   -2851   } , 
+    {  29677   ,   -2997   } , 
+    {  29662   ,   -3142   } , 
+    {  29646   ,   -3288   } , 
+    {  29630   ,   -3433   } , 
+    {  29613   ,   -3579   } , 
+    {  29595   ,   -3724   } , 
+    {  29576   ,   -3869   } , 
+    {  29557   ,   -4014   } , 
+    {  29537   ,   -4159   } , 
+    {  29516   ,   -4304   } , 
+    {  29494   ,   -4449   } , 
+    {  29472   ,   -4594   } , 
+    {  29449   ,   -4738   } , 
+    {  29426   ,   -4883   } , 
+    {  29401   ,   -5027   } , 
+    {  29376   ,   -5172   } , 
+    {  29351   ,   -5316   } , 
+    {  29324   ,   -5460   } , 
+    {  29297   ,   -5604   } , 
+    {  29269   ,   -5747   } , 
+    {  29241   ,   -5891   } , 
+    {  29211   ,   -6034   } , 
+    {  29181   ,   -6178   } , 
+    {  29151   ,   -6321   } , 
+    {  29119   ,   -6464   } , 
+    {  29087   ,   -6607   } , 
+    {  29054   ,   -6749   } , 
+    {  29021   ,   -6892   } , 
+    {  28987   ,   -7034   } , 
+    {  28952   ,   -7177   } , 
+    {  28916   ,   -7319   } , 
+    {  28880   ,   -7460   } , 
+    {  28843   ,   -7602   } , 
+    {  28805   ,   -7744   } , 
+    {  28767   ,   -7885   } , 
+    {  28728   ,   -8026   } , 
+    {  28688   ,   -8167   } , 
+    {  28648   ,   -8308   } , 
+    {  28607   ,   -8448   } , 
+    {  28565   ,   -8589   } , 
+    {  28522   ,   -8729   } , 
+    {  28479   ,   -8869   } , 
+    {  28435   ,   -9008   } , 
+    {  28391   ,   -9148   } , 
+    {  28346   ,   -9287   } , 
+    {  28300   ,   -9426   } , 
+    {  28253   ,   -9565   } , 
+    {  28206   ,   -9703   } , 
+    {  28158   ,   -9842   } , 
+    {  28109   ,   -9980   } , 
+    {  28060   ,   -10118   } , 
+    {  28010   ,   -10255   } , 
+    {  27959   ,   -10393   } , 
+    {  27908   ,   -10530   } , 
+    {  27856   ,   -10667   } , 
+    {  27803   ,   -10803   } , 
+    {  27750   ,   -10940   } , 
+    {  27696   ,   -11076   } , 
+    {  27641   ,   -11212   } , 
+    {  27586   ,   -11347   } , 
+    {  27529   ,   -11482   } , 
+    {  27473   ,   -11617   } , 
+    {  27415   ,   -11752   } , 
+    {  27357   ,   -11886   } , 
+    {  27299   ,   -12021   } , 
+    {  27239   ,   -12154   } , 
+    {  27179   ,   -12288   } , 
+    {  27119   ,   -12421   } , 
+    {  27057   ,   -12554   } , 
+    {  26996   ,   -12687   } , 
+    {  26933   ,   -12819   } , 
+    {  26870   ,   -12951   } , 
+    {  26806   ,   -13083   } , 
+    {  26741   ,   -13215   } , 
+    {  26676   ,   -13346   } , 
+    {  26610   ,   -13476   } , 
+    {  26544   ,   -13607   } , 
+    {  26477   ,   -13737   } , 
+    {  26409   ,   -13867   } , 
+    {  26340   ,   -13996   } , 
+    {  26271   ,   -14125   } , 
+    {  26202   ,   -14254   } , 
+    {  26132   ,   -14383   } , 
+    {  26061   ,   -14511   } , 
+    {  25989   ,   -14638   } , 
+    {  25917   ,   -14766   } , 
+    {  25844   ,   -14893   } , 
+    {  25771   ,   -15020   } , 
+    {  25697   ,   -15146   } , 
+    {  25622   ,   -15272   } , 
+    {  25547   ,   -15397   } , 
+    {  25471   ,   -15523   } , 
+    {  25394   ,   -15648   } , 
+    {  25317   ,   -15772   } , 
+    {  25239   ,   -15896   } , 
+    {  25161   ,   -16020   } , 
+    {  25082   ,   -16143   } , 
+    {  25003   ,   -16266   } , 
+    {  24923   ,   -16389   } , 
+    {  24842   ,   -16511   } , 
+    {  24760   ,   -16632   } , 
+    {  24678   ,   -16754   } , 
+    {  24596   ,   -16875   } , 
+    {  24513   ,   -16995   } , 
+    {  24429   ,   -17115   } , 
+    {  24345   ,   -17235   } , 
+    {  24260   ,   -17354   } , 
+    {  24174   ,   -17473   } , 
+    {  24088   ,   -17592   } , 
+    {  24002   ,   -17710   } , 
+    {  23914   ,   -17827   } , 
+    {  23827   ,   -17945   } , 
+    {  23738   ,   -18061   } , 
+    {  23649   ,   -18178   } , 
+    {  23560   ,   -18293   } , 
+    {  23470   ,   -18409   } , 
+    {  23379   ,   -18524   } , 
+    {  23288   ,   -18638   } , 
+    {  23196   ,   -18752   } , 
+    {  23104   ,   -18866   } , 
+    {  23011   ,   -18979   } , 
+    {  22917   ,   -19092   } , 
+    {  22824   ,   -19204   } , 
+    {  22729   ,   -19316   } , 
+    {  22634   ,   -19427   } , 
+    {  22538   ,   -19538   } , 
+    {  22442   ,   -19649   } , 
+    {  22345   ,   -19759   } , 
+    {  22248   ,   -19868   } , 
+    {  22150   ,   -19977   } , 
+    {  22052   ,   -20086   } , 
+    {  21953   ,   -20194   } , 
+    {  21854   ,   -20301   } , 
+    {  21754   ,   -20408   } , 
+    {  21653   ,   -20515   } , 
+    {  21552   ,   -20621   } , 
+    {  21451   ,   -20726   } , 
+    {  21349   ,   -20831   } , 
+    {  21246   ,   -20936   } , 
+    {  21143   ,   -21040   } 
+    };
+cos_msin_t	a_cos_msin_64[320] = {
+{29827,	-34},
+{29827,	-106},
+{29827,	-177},
+{29827,	-249},
+{29826,	-320},
+{29825,	-392},
+{29824,	-463},
+{29823,	-535},
+{29821,	-606},
+{29819,	-678},
+{29818,	-750},
+{29816,	-821},
+{29814,	-893},
+{29812,	-964},
+{29809,	-1035},
+{29807,	-1106},
+{29804,	-1177},
+{29801,	-1249},
+{29797,	-1320},
+{29795,	-1392},
+{29791,	-1463},
+{29787,	-1535},
+{29784,	-1606},
+{29780,	-1678},
+{29776,	-1749},
+{29771,	-1820},
+{29767,	-1892},
+{29763,	-1963},
+{29758,	-2035},
+{29753,	-2106},
+{29748,	-2177},
+{29742,	-2249},
+{29737,	-2320},
+{29731,	-2391},
+{29726,	-2462},
+{29719,	-2534},
+{29713,	-2605},
+{29707,	-2676},
+{29701,	-2747},
+{29694,	-2819},
+{29686,	-2890},
+{29680,	-2961},
+{29673,	-3032},
+{29665,	-3103},
+{29658,	-3174},
+{29650,	-3245},
+{29643,	-3316},
+{29635,	-3387},
+{29626,	-3459},
+{29618,	-3529},
+{29610,	-3600},
+{29601,	-3671},
+{29592,	-3742},
+{29583,	-3813},
+{29574,	-3884},
+{29564,	-3955},
+{29554,	-4026},
+{29544,	-4097},
+{29535,	-4167},
+{29525,	-4238},
+{29514,	-4309},
+{29504,	-4380},
+{29493,	-4450},
+{29483,	-4521},
+{29472,	-4591},
+{29461,	-4662},
+{29450,	-4733},
+{29439,	-4803},
+{29427,	-4874},
+{29415,	-4944},
+{29403,	-5015},
+{29391,	-5085},
+{29379,	-5155},
+{29366,	-5226},
+{29353,	-5296},
+{29341,	-5367},
+{29328,	-5438},
+{29314,	-5508},
+{29301,	-5578},
+{29289,	-5648},
+{29274,	-5718},
+{29260,	-5788},
+{29247,	-5858},
+{29232,	-5928},
+{29218,	-5998},
+{29204,	-6068},
+{29188,	-6139},
+{29175,	-6209},
+{29159,	-6279},
+{29145,	-6348},
+{29128,	-6418},
+{29114,	-6488},
+{29097,	-6557},
+{29082,	-6627},
+{29066,	-6697},
+{29050,	-6767},
+{29034,	-6837},
+{29017,	-6906},
+{29001,	-6975},
+{28984,	-7045},
+{28966,	-7114},
+{28950,	-7184},
+{28933,	-7254},
+{28915,	-7323},
+{28897,	-7392},
+{28880,	-7461},
+{28862,	-7530},
+{28843,	-7600},
+{28825,	-7669},
+{28807,	-7738},
+{28788,	-7806},
+{28769,	-7875},
+{28751,	-7944},
+{28732,	-8014},
+{28712,	-8082},
+{28692,	-8151},
+{28672,	-8219},
+{28653,	-8289},
+{28633,	-8357},
+{28613,	-8425},
+{28593,	-8494},
+{28572,	-8563},
+{28551,	-8632},
+{28531,	-8700},
+{28510,	-8768},
+{28488,	-8837},
+{28468,	-8905},
+{28447,	-8973},
+{28425,	-9041},
+{28403,	-9109},
+{28381,	-9177},
+{28359,	-9245},
+{28336,	-9313},
+{28315,	-9381},
+{28292,	-9448},
+{28269,	-9517},
+{28246,	-9584},
+{28223,	-9652},
+{28200,	-9720},
+{28176,	-9787},
+{28153,	-9854},
+{28129,	-9922},
+{28105,	-9990},
+{28082,	-10056},
+{28057,	-10124},
+{28032,	-10191},
+{28009,	-10258},
+{27984,	-10326},
+{27959,	-10392},
+{27934,	-10460},
+{27909,	-10526},
+{27883,	-10593},
+{27858,	-10661},
+{27832,	-10727},
+{27807,	-10794},
+{27780,	-10860},
+{27754,	-10927},
+{27728,	-10993},
+{27701,	-11059},
+{27676,	-11126},
+{27648,	-11192},
+{27622,	-11259},
+{27595,	-11324},
+{27567,	-11391},
+{27540,	-11456},
+{27512,	-11523},
+{27484,	-11588},
+{27456,	-11655},
+{27429,	-11720},
+{27401,	-11786},
+{27372,	-11852},
+{27344,	-11917},
+{27315,	-11982},
+{27286,	-12049},
+{27257,	-12114},
+{27229,	-12179},
+{27199,	-12244},
+{27169,	-12309},
+{27140,	-12375},
+{27110,	-12439},
+{27080,	-12505},
+{27050,	-12570},
+{27019,	-12634},
+{26990,	-12699},
+{26958,	-12764},
+{26928,	-12828},
+{26897,	-12892},
+{26866,	-12956},
+{26835,	-13021},
+{26804,	-13086},
+{26773,	-13149},
+{26741,	-13214},
+{26709,	-13278},
+{26677,	-13342},
+{26645,	-13406},
+{26613,	-13470},
+{26581,	-13534},
+{26549,	-13597},
+{26515,	-13661},
+{26483,	-13725},
+{26450,	-13788},
+{26417,	-13851},
+{26384,	-13915},
+{26350,	-13978},
+{26316,	-14041},
+{26283,	-14103},
+{26248,	-14166},
+{26215,	-14229},
+{26180,	-14292},
+{26146,	-14355},
+{26112,	-14417},
+{26077,	-14480},
+{26042,	-14543},
+{26008,	-14605},
+{25972,	-14667},
+{25937,	-14730},
+{25901,	-14792},
+{25866,	-14854},
+{25830,	-14916},
+{25794,	-14977},
+{25759,	-15039},
+{25723,	-15101},
+{25687,	-15162},
+{25650,	-15224},
+{25613,	-15286},
+{25577,	-15347},
+{25540,	-15408},
+{25503,	-15470},
+{25465,	-15531},
+{25428,	-15592},
+{25391,	-15653},
+{25353,	-15714},
+{25315,	-15774},
+{25277,	-15834},
+{25240,	-15895},
+{25201,	-15956},
+{25162,	-16016},
+{25124,	-16076},
+{25086,	-16136},
+{25047,	-16196},
+{25008,	-16256},
+{24969,	-16316},
+{24930,	-16375},
+{24891,	-16436},
+{24851,	-16496},
+{24811,	-16555},
+{24772,	-16615},
+{24732,	-16674},
+{24692,	-16732},
+{24652,	-16791},
+{24612,	-16852},
+{24572,	-16911},
+{24531,	-16969},
+{24490,	-17027},
+{24449,	-17086},
+{24408,	-17145},
+{24367,	-17203},
+{24325,	-17261},
+{24284,	-17320},
+{24242,	-17379},
+{24200,	-17436},
+{24158,	-17494},
+{24116,	-17552},
+{24075,	-17610},
+{24032,	-17668},
+{23990,	-17725},
+{23947,	-17782},
+{23904,	-17840},
+{23862,	-17897},
+{23819,	-17954},
+{23775,	-18011},
+{23732,	-18068},
+{23689,	-18125},
+{23645,	-18181},
+{23602,	-18238},
+{23558,	-18294},
+{23514,	-18351},
+{23470,	-18407},
+{23426,	-18464},
+{23381,	-18520},
+{23337,	-18576},
+{23293,	-18632},
+{23248,	-18688},
+{23202,	-18743},
+{23158,	-18799},
+{23112,	-18854},
+{23068,	-18910},
+{23022,	-18964},
+{22977,	-19020},
+{22931,	-19074},
+{22885,	-19129},
+{22839,	-19185},
+{22793,	-19239},
+{22747,	-19294},
+{22700,	-19348},
+{22655,	-19403},
+{22607,	-19457},
+{22561,	-19511},
+{22514,	-19565},
+{22467,	-19619},
+{22421,	-19673},
+{22373,	-19726},
+{22326,	-19780},
+{22279,	-19834},
+{22230,	-19887},
+{22183,	-19940},
+{22135,	-19993},
+{22087,	-20047},
+{22039,	-20099},
+{21991,	-20152},
+{21942,	-20205},
+{21894,	-20257},
+{21845,	-20309},
+{21797,	-20362},
+{21748,	-20413},
+{21699,	-20466},
+{21650,	-20518},
+{21601,	-20570},
+{21551,	-20621},
+{21502,	-20674}
+};
+
+cos_msin_t	*a_cos_msin_table[] = {a_cos_msin_2, a_cos_msin_4,
+                                   a_cos_msin_8, a_cos_msin_16,
+                                   a_cos_msin_32,a_cos_msin_64
+			                      };
+
+Word16 dct_core_a[10][10] = {
+
+{ 10453,  10196,   9688,   8941,   7973,   6810,   5479,   4013,   2448,    823 },
+{ 10196,   7973,   4013,   -823,  -5479,  -8941, -10453,  -9688,  -6810,  -2448 },
+{ 9688 ,   4013,  -4013,  -9688,  -9688,  -4013,   4013,   9688,   9688,   4013 },
+{ 8941 ,   -823,  -9688,  -7973,   2448,  10196,   6810,  -4013, -10453,  -5479 },
+{ 7973 ,  -5479,  -9688,   2448,  10453,    823, -10196,  -4013,   8941,   6810 },
+{ 6810 ,  -8941,  -4013,  10196,    823, -10453,   2448,   9688,  -5479,  -7973 },
+{ 5479 , -10453,   4013,   6810, -10196,   2448,   7973,  -9688,    823,   8941 },
+{ 4013 ,  -9688,   9688,  -4013,  -4013,   9688,  -9688,   4013,   4013,  -9688 },
+{ 2448 ,  -6810,   9688, -10453,   8941,  -5479,    823,   4013,  -7973,  10196 },
+{ 823  ,  -2448,   4013,  -5479,   6810,  -7973,   8941,  -9688,  10196, -10453 }};
+
+Word16 anal_bias[320] = {
+  1,  1,  3,  1,  4,  1,  3, -2,  4,  3,
+  4,  1,  3,  0,  2, -3,  0,  0,  2,  2,
+  4,  1,  1, -5,  4,  1,  2, -1,  0, -1,
+  1, -2,  0,  2,  2,  2,  4,  1,  3,  0,
+  5,  3,  2,  0,  3,  0,  1, -4,  1,  1,
+  2,  0,  4,  0,  1, -4,  6,  1,  3, -1,
+  1,  0,  0, -4,  1,  1,  3,  1,  3,  2,
+  4, -2,  4,  3,  5,  1,  3,  0,  1, -3,
+  1,  1,  2,  0,  4,  1,  2, -4,  4,  2,
+  2, -1,  1, -1,  1, -4,  0,  0,  3,  0,
+  5,  2,  3, -1,  6,  2,  5,  0,  4,  0,
+  1, -3,  1,  0,  3,  0,  4,  0,  1, -3,
+  4,  1,  3, -1,  1, -2,  1, -4,  0,  1,
+  2,  1,  3,  2,  2, -2,  4,  3,  3,  0,
+  3,  0,  0, -2,  1,  0,  2,  0,  5, -1,
+  1, -3,  4,  2,  2,  0,  2, -3,  1, -4,
+ -1,  1,  2,  2,  4,  1,  3, -1,  5,  2,
+  2,  0,  3, -1,  2, -3,  0,  1,  2,  2,
+  4,  0,  1, -5,  5,  1,  3,  0,  2, -1,
+  0, -2,  1,  2,  2,  2,  4,  1,  0,  0,
+  4,  2,  4,  1,  4, -1,  1, -4,  0,  1,
+  3,  1,  5,  1,  1, -2,  4,  0,  2,  0,
+  2, -1,  0, -2,  0,  1,  1,  1,  4,  2,
+  3, -2,  5,  4,  4,  0,  3,  0,  3, -4,
+  1,  2,  2,  0,  4,  1,  0, -3,  4,  2,
+  3, -1,  1, -1,  1, -4,  0,  2,  3,  1,
+  4,  1,  3,  0,  3,  3,  4,  1,  2,  0,
+  1, -3,  2,  2,  2,  1,  5,  0,  1, -4,
+  4,  1,  3, -2,  3, -1,  0, -2,  0,  2,
+  2,  0,  5,  1,  4, -1,  4,  3,  4,  1,
+  3,  0,  1, -4,  2,  0,  3,  1,  5,  0,
+  1, -5,  5,  2,  2,  0,  0,  0,  0, -4};
+
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/encode/encoder.c b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/encode/encoder.c
new file mode 100644
index 0000000..2d878cc
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/encode/encoder.c
@@ -0,0 +1,1125 @@
+/***************************************************************************
+**
+**   ITU-T G.722.1 (2005-05) - Fixed point implementation for main body and Annex C
+**   > Software Release 2.1 (2008-06)
+**     (Simple repackaging; no change from 2005-05 Release 2.0 code)
+**
+**   � 2004 Polycom, Inc.
+**
+**   All rights reserved.
+**
+***************************************************************************/
+
+/***************************************************************************
+  Filename:    encoder.c    
+
+  Purpose:     Contains files used to implement the G.722.1 Annex C encoder
+
+  Design Notes:
+
+***************************************************************************/
+
+/***************************************************************************
+ Include files                                                           
+***************************************************************************/
+
+#include <stdio.h>
+#include <math.h>
+#include "defs.h"
+#include "huff_def.h"
+#include "tables.h"
+#include "count.h"
+
+/***************************************************************************
+ Function:    encoder                                                     
+                                                                         
+ Syntax:      void encoder(Word16 number_of_available_bits,                     
+                           Word16 number_of_regions,
+                           Word16 mlt_coefs,                                        
+                           Word16 mag_shift,                                        
+                           Word16 out_words)                                        
+              
+              inputs:   number_of_available_bits
+                        number_of_regions
+                        mag_shift
+                        mlt_coefs[DCT_LENGTH]
+                        
+              outputs:  out_words[MAX_BITS_PER_FRAME/16]
+                                                                         
+                                                                         
+ Description: Encodes the mlt coefs into out_words using G.722.1 Annex C
+                                                           
+                                                                         
+ WMOPS:     7kHz |    24kbit    |     32kbit
+          -------|--------------|----------------
+            AVG  |    0.93      |     1.04
+          -------|--------------|----------------  
+            MAX  |    1.20      |     1.28
+          -------|--------------|---------------- 
+                                                                        
+           14kHz |    24kbit    |     32kbit     |     48kbit
+          -------|--------------|----------------|----------------
+            AVG  |    1.39      |     1.71       |     2.01
+          -------|--------------|----------------|----------------
+            MAX  |    2.00      |     2.30       |     2.52
+          -------|--------------|----------------|----------------
+                                                                         
+***************************************************************************/
+
+void encoder(Word16  number_of_available_bits,
+             Word16  number_of_regions,
+             Word16  *mlt_coefs,
+             Word16  mag_shift,
+             Word16  *out_words)
+{
+
+    Word16  num_categorization_control_bits;
+    Word16  num_categorization_control_possibilities;
+    Word16  number_of_bits_per_frame;
+    Word16  number_of_envelope_bits;
+    Word16  categorization_control;
+    Word16  region;
+    Word16  absolute_region_power_index[MAX_NUMBER_OF_REGIONS];
+    Word16  power_categories[MAX_NUMBER_OF_REGIONS];
+    Word16  category_balances[MAX_NUM_CATEGORIZATION_CONTROL_POSSIBILITIES-1];
+    Word16  drp_num_bits[MAX_NUMBER_OF_REGIONS+1];
+    UWord16 drp_code_bits[MAX_NUMBER_OF_REGIONS+1];
+    Word16  region_mlt_bit_counts[MAX_NUMBER_OF_REGIONS];
+    UWord32 region_mlt_bits[4*MAX_NUMBER_OF_REGIONS];
+    Word16  mag_shift_offset;
+
+    Word16 temp;
+
+    /* initialize variables */
+    test();
+    if (number_of_regions == NUMBER_OF_REGIONS)
+    {
+        num_categorization_control_bits = NUM_CATEGORIZATION_CONTROL_BITS;
+        move16();
+        num_categorization_control_possibilities = NUM_CATEGORIZATION_CONTROL_POSSIBILITIES;
+        move16();
+    } 
+    else
+    {
+        num_categorization_control_bits = MAX_NUM_CATEGORIZATION_CONTROL_BITS;
+        move16();
+        num_categorization_control_possibilities = MAX_NUM_CATEGORIZATION_CONTROL_POSSIBILITIES;
+        move16();
+    }
+
+    number_of_bits_per_frame = number_of_available_bits;
+    move16();
+
+    for (region=0; region<number_of_regions; region++)
+    {
+        region_mlt_bit_counts[region] = 0;
+        move16();
+    }
+    
+    /* Estimate power envelope. */
+    number_of_envelope_bits = compute_region_powers(mlt_coefs,
+                                                    mag_shift,
+                                                    drp_num_bits,
+                                                    drp_code_bits,
+                                                    absolute_region_power_index,
+                                                    number_of_regions);
+
+    /* Adjust number of available bits based on power envelope estimate */
+    temp = sub(number_of_available_bits,number_of_envelope_bits);
+    number_of_available_bits = sub(temp,num_categorization_control_bits);
+
+    /* get categorizations */
+    categorize(number_of_available_bits,
+               number_of_regions,
+               num_categorization_control_possibilities,
+               absolute_region_power_index,
+               power_categories,
+               category_balances);
+
+    /* Adjust absolute_region_category_index[] for mag_shift.
+       This assumes that REGION_POWER_STEPSIZE_DB is defined
+       to be exactly 3.010299957 or 20.0 times log base 10
+       of square root of 2. */
+    temp = shl_nocheck(mag_shift,1);
+    mag_shift_offset = add(temp,REGION_POWER_TABLE_NUM_NEGATIVES);
+    
+    for (region=0; region<number_of_regions; region++)
+    {
+        absolute_region_power_index[region] = add(absolute_region_power_index[region],mag_shift_offset);
+        move16();
+    }
+
+    /* adjust the absolute power region index based on the mlt coefs */
+    adjust_abs_region_power_index(absolute_region_power_index,mlt_coefs,number_of_regions);
+
+
+    /* quantize and code the mlt coefficients based on categorizations */
+    vector_quantize_mlts(number_of_available_bits,
+                         number_of_regions,
+                         num_categorization_control_possibilities,
+                         mlt_coefs,
+                         absolute_region_power_index,
+                         power_categories,
+                         category_balances,
+                         &categorization_control,
+                         region_mlt_bit_counts,
+                         region_mlt_bits);
+
+    /* stuff bits into words */
+    bits_to_words(region_mlt_bits,
+                  region_mlt_bit_counts,
+                  drp_num_bits,
+                  drp_code_bits,
+                  out_words,
+                  categorization_control,
+                  number_of_regions,
+                  num_categorization_control_bits,
+                  number_of_bits_per_frame);
+
+}
+
+/***************************************************************************
+ Function:    bits_to_words
+
+ Syntax:      bits_to_words(UWord32 *region_mlt_bits,              
+                            Word16  *region_mlt_bit_counts,                                                             
+                            Word16  *drp_num_bits,                                                                      
+                            UWord16 *drp_code_bits,                                                                     
+                            Word16  *out_words,                                                                         
+                            Word16  categorization_control,                                                                         
+                            Word16  number_of_regions,
+                            Word16  num_categorization_control_bits,
+                            Word16  number_of_bits_per_frame)                                                           
+                                                                   
+                                                                   
+ Description: Stuffs the bits into words for output
+
+ WMOPS:     7kHz |    24kbit    |      32kbit
+          -------|--------------|----------------
+            AVG  |    0.09      |     0.12
+          -------|--------------|----------------  
+            MAX  |    0.10      |     0.13
+          -------|--------------|---------------- 
+          
+           14kHz |    24kbit    |     32kbit     |     48kbit
+          -------|--------------|----------------|----------------
+            AVG  |    0.12      |     0.15       |     0.19
+          -------|--------------|----------------|----------------
+            MAX  |    0.14      |     0.17       |     0.21
+          -------|--------------|----------------|----------------
+
+***************************************************************************/
+void bits_to_words(UWord32 *region_mlt_bits,
+                   Word16  *region_mlt_bit_counts,
+                   Word16  *drp_num_bits,
+                   UWord16 *drp_code_bits,
+                   Word16  *out_words,
+                   Word16  categorization_control,
+                   Word16  number_of_regions,
+                   Word16  num_categorization_control_bits,
+                   Word16  number_of_bits_per_frame)
+{
+    Word16  out_word_index = 0;
+    Word16  j;
+    Word16  region;
+    Word16  out_word;
+    Word16  region_bit_count;
+    Word16  current_word_bits_left;
+    UWord16 slice;
+    Word16  out_word_bits_free = 16;
+    UWord32 *in_word_ptr;
+    UWord32 current_word;
+    
+    Word32  acca = 0;
+    Word32  accb;
+    Word16  temp;
+
+    /* First set up the categorization control bits to look like one more set of region power bits. */
+    out_word = 0;
+    move16();
+
+    drp_num_bits[number_of_regions] = num_categorization_control_bits;
+    move16();
+    
+    drp_code_bits[number_of_regions] = (UWord16)categorization_control;
+    move16();
+
+    /* These code bits are right justified. */
+    for (region=0; region <= number_of_regions; region++)
+    {
+        current_word_bits_left = drp_num_bits[region];
+        move16();
+        
+        current_word = (UWord32)drp_code_bits[region];
+        move16();
+        
+        j = sub(current_word_bits_left,out_word_bits_free);
+
+        test();
+        if (j >= 0)
+        {
+            temp = extract_l(L_shr_nocheck(current_word,j));
+            out_word = add(out_word,temp);
+
+            out_words[out_word_index++] = out_word;
+            move16();
+            
+            out_word_bits_free = 16;
+            move16();
+            
+            out_word_bits_free = sub(out_word_bits_free,j);
+            
+            acca = (current_word << out_word_bits_free);
+            out_word = extract_l(acca);
+        }
+        else
+        {
+            j = negate(j);
+
+            acca = (current_word << j);
+            accb = L_deposit_l(out_word);
+            acca = L_add(accb,acca);
+            out_word = extract_l(acca);
+            
+            out_word_bits_free = sub(out_word_bits_free,current_word_bits_left);
+        }
+    }
+
+    /* These code bits are left justified. */
+    
+    for (region=0;region<number_of_regions; region++)
+    {
+        accb = L_deposit_l(out_word_index);
+        accb = L_shl_nocheck(accb,4);
+        accb = L_sub(accb,number_of_bits_per_frame);
+        test();
+        if(accb < 0)        
+        {
+            temp = shl_nocheck(region,2);
+            in_word_ptr = &region_mlt_bits[temp];
+            region_bit_count = region_mlt_bit_counts[region];
+            move16();
+
+            temp = sub(32,region_bit_count);
+            test();
+            if(temp > 0)
+                current_word_bits_left = region_bit_count;
+            else
+                current_word_bits_left = 32;
+
+            current_word = *in_word_ptr++;
+    
+            acca = L_deposit_l(out_word_index);
+            acca = L_shl_nocheck(acca,4);
+            acca = L_sub(acca,number_of_bits_per_frame);
+            
+            /* from while loop */
+            test();
+            test();
+            logic16(); 
+            while ((region_bit_count > 0) && (acca < 0))
+            {
+                /* from while loop */
+                test();
+                test();
+                logic16(); 
+                
+                temp = sub(current_word_bits_left,out_word_bits_free);
+                test();
+                if (temp >= 0)
+                {
+                    temp = sub(32,out_word_bits_free);
+                    accb = LU_shr(current_word,temp);
+                    slice = (UWord16)extract_l(accb);
+                    
+                    out_word = add(out_word,slice);
+    
+                    test();
+                    current_word <<= out_word_bits_free;
+
+                    current_word_bits_left = sub(current_word_bits_left,out_word_bits_free);
+                    out_words[out_word_index++] = extract_l(out_word);
+                    move16();
+
+                    out_word = 0;
+                    move16();
+
+                    out_word_bits_free = 16;
+                    move16();
+                }
+                else
+                {
+                    temp = sub(32,current_word_bits_left);
+                    accb = LU_shr(current_word,temp);
+                    slice = (UWord16)extract_l(accb);
+                    
+                    temp = sub(out_word_bits_free,current_word_bits_left);
+                    test();
+                    accb = slice << temp;
+                    acca = L_deposit_l(out_word);
+                    acca = L_add(acca,accb);
+                    out_word = extract_l(acca);
+                    out_word_bits_free = sub(out_word_bits_free,current_word_bits_left);
+                    
+                    current_word_bits_left = 0;
+                    move16();
+                }
+    
+                test();
+                if (current_word_bits_left == 0)
+                {
+                    current_word = *in_word_ptr++;
+                    region_bit_count = sub(region_bit_count,32);
+                    
+                    /* current_word_bits_left = MIN(32,region_bit_count); */
+                    temp = sub(32,region_bit_count);
+                    test();
+                    if(temp > 0)
+                        current_word_bits_left = region_bit_count;
+                    else
+                        current_word_bits_left = 32;
+                    
+                }
+                acca = L_deposit_l(out_word_index);
+                acca = L_shl_nocheck(acca,4);
+                acca = L_sub(acca,number_of_bits_per_frame);
+            }
+            accb = L_deposit_l(out_word_index);
+            accb = L_shl_nocheck(accb,4);
+            accb = L_sub(accb,number_of_bits_per_frame);
+        }
+    }
+
+    /* Fill out with 1's. */
+
+    test();
+    while (acca < 0)
+    {
+        test();
+        current_word = 0x0000ffff;
+        move32();
+
+        temp = sub(16,out_word_bits_free);
+        acca = LU_shr(current_word,temp);
+        slice = (UWord16)extract_l(acca);
+
+        out_word = add(out_word,slice);
+        out_words[out_word_index++] = out_word;
+        move16();
+
+        out_word = 0;
+        move16();
+        
+        out_word_bits_free = 16;
+        move16();
+        
+        acca = L_deposit_l(out_word_index);
+        acca = L_shl_nocheck(acca,4);
+        acca = L_sub(acca,number_of_bits_per_frame);
+    }
+}
+/***************************************************************************
+ Function:    adjust_abs_region_power_index
+
+ Syntax:      adjust_abs_region_power_index(Word16 *absolute_region_power_index,
+                                            Word16 *mlt_coefs,
+                                            Word16 number_of_regions)
+
+              inputs:   *mlt_coefs
+                        *absolute_region_power_index
+                        number_of_regions
+            
+              outputs:  *absolute_region_power_index
+ 
+ Description: Adjusts the absolute power index
+ 
+ 
+ WMOPS:     7kHz |    24kbit    |      32kbit
+          -------|--------------|----------------
+            AVG  |    0.03      |      0.03
+          -------|--------------|----------------  
+            MAX  |    0.12      |      0.12
+          -------|--------------|---------------- 
+
+           14kHz |    24kbit    |     32kbit     |     48kbit
+          -------|--------------|----------------|----------------
+            AVG  |    0.03      |     0.03       |     0.03
+          -------|--------------|----------------|----------------
+            MAX  |    0.14      |     0.14       |     0.14
+          -------|--------------|----------------|----------------
+
+***************************************************************************/
+void adjust_abs_region_power_index(Word16 *absolute_region_power_index,Word16 *mlt_coefs,Word16 number_of_regions)
+{
+    Word16 n,i;
+    Word16 region;
+    Word16 *raw_mlt_ptr;
+    
+    Word32 acca;
+    Word16 temp;
+
+    for (region=0; region<number_of_regions; region++)
+    {
+        n = sub(absolute_region_power_index[region],39);
+        n = shr_nocheck(n,1);
+        
+        test();
+        if (n > 0)
+        {
+            temp = extract_l(L_mult0(region,REGION_SIZE));
+
+            raw_mlt_ptr = &mlt_coefs[temp];
+
+            for (i=0; i<REGION_SIZE; i++)
+            {
+                acca = L_shl_nocheck(*raw_mlt_ptr,16);
+                acca = L_add(acca,32768L);
+                acca = L_shr_nocheck(acca,n);
+                acca = L_shr_nocheck(acca,16);
+                *raw_mlt_ptr++ = extract_l(acca);
+            }
+
+            temp = shl_nocheck(n,1);
+            temp = sub(absolute_region_power_index[region],temp);
+            absolute_region_power_index[region] = temp;
+            move16();
+        }
+    }
+}
+
+/***************************************************************************
+ Function:    compute_region_powers
+
+ Syntax:      Word16 compute_region_powers(Word16  *mlt_coefs,                         
+                                           Word16  mag_shift,                         
+                                           Word16  *drp_num_bits,                      
+                                           UWord16 *drp_code_bits,                     
+                                           Word16  *absolute_region_power_index,       
+                                           Word16  number_of_regions)
+                mlt_coefs[DCT_LENGTH];                      
+                mag_shift;                                          
+                drp_num_bits[MAX_NUMBER_OF_REGIONS];                      
+                drp_code_bits[MAX_NUMBER_OF_REGIONS];                     
+                absolute_region_power_index[MAX_NUMBER_OF_REGIONS];       
+                number_of_regions;
+                                                                   
+ Description: Computes the power for each of the regions
+
+ 
+ WMOPS:     7kHz |    24kbit    |    32kbit
+          -------|--------------|----------------
+            AVG  |    0.09      |    0.09
+          -------|--------------|----------------  
+            MAX  |    0.13      |    0.13
+          -------|--------------|---------------- 
+
+           14kHz |    24kbit    |     32kbit     |     48kbit
+          -------|--------------|----------------|----------------
+            AVG  |    0.20      |     0.20       |     0.20
+          -------|--------------|----------------|----------------
+            MAX  |    0.29      |     0.29       |     0.29
+          -------|--------------|----------------|----------------
+
+***************************************************************************/
+
+Word16 compute_region_powers(Word16  *mlt_coefs,
+                             Word16  mag_shift,
+                             Word16  *drp_num_bits,
+                             UWord16 *drp_code_bits,
+                             Word16  *absolute_region_power_index,
+                             Word16  number_of_regions)
+{
+
+    Word16 *input_ptr;
+    Word32 long_accumulator;
+    Word16 itemp1;
+    Word16 power_shift;
+    Word16 region;
+    Word16 j;
+    Word16 differential_region_power_index[MAX_NUMBER_OF_REGIONS];
+    Word16 number_of_bits;
+    
+    Word32 acca;
+    Word16 temp;
+    Word16 temp1;
+    Word16 temp2;
+
+
+    input_ptr = mlt_coefs;
+    for (region=0; region<number_of_regions; region++)
+    {
+        long_accumulator = L_deposit_l(0);
+
+        for (j=0; j<REGION_SIZE; j++)
+        {
+            itemp1 = *input_ptr++;
+            move16();
+            long_accumulator = L_mac0(long_accumulator,itemp1,itemp1);
+        }
+
+        power_shift = 0;
+        move16();
+
+        acca = (long_accumulator & 0x7fff0000L);
+        logic32();
+
+        test();
+        while (acca > 0)
+        {
+            test();
+            long_accumulator = L_shr_nocheck(long_accumulator,1);
+            
+            acca = (long_accumulator & 0x7fff0000L);
+            logic32();
+
+            power_shift = add(power_shift,1);
+        }
+        
+        acca = L_sub(long_accumulator,32767);
+        
+        temp = add(power_shift,15);
+        test();
+        test();
+        logic16();
+        while ((acca <= 0) && (temp >= 0))
+        {
+            test();
+            test();
+            logic16();
+            
+            long_accumulator = L_shl_nocheck(long_accumulator,1);
+            acca = L_sub(long_accumulator,32767);
+            power_shift--;
+            temp = add(power_shift,15);
+        }
+        long_accumulator = L_shr_nocheck(long_accumulator,1);
+        /* 28963 corresponds to square root of 2 times REGION_SIZE(20). */
+        acca = L_sub(long_accumulator,28963);
+        
+        test();
+        if (acca >= 0)
+            power_shift = add(power_shift,1);
+        
+        acca = L_deposit_l(mag_shift);
+        acca = L_shl_nocheck(acca,1);
+        acca = L_sub(power_shift,acca);
+        acca = L_add(35,acca);
+        acca = L_sub(acca,REGION_POWER_TABLE_NUM_NEGATIVES);
+        absolute_region_power_index[region] = extract_l(acca);
+    }
+
+
+    /* Before we differentially encode the quantized region powers, adjust upward the
+    valleys to make sure all the peaks can be accurately represented. */
+    temp = sub(number_of_regions,2);
+
+    for (region = temp; region >= 0; region--)
+    {
+        temp1 = sub(absolute_region_power_index[region+1],DRP_DIFF_MAX);
+        temp2 = sub(absolute_region_power_index[region],temp1);
+        test();
+        if (temp2 < 0)
+        {
+            absolute_region_power_index[region] = temp1;
+            move16();
+        }
+    }
+
+    /* The MLT is currently scaled too low by the factor
+       ENCODER_SCALE_FACTOR(=18318)/32768 * (1./sqrt(160).
+       This is the ninth power of 1 over the square root of 2.
+       So later we will add ESF_ADJUSTMENT_TO_RMS_INDEX (now 9)
+       to drp_code_bits[0]. */
+
+    /* drp_code_bits[0] can range from 1 to 31. 0 will be used only as an escape sequence. */
+    temp1 = sub(1,ESF_ADJUSTMENT_TO_RMS_INDEX);
+    temp2 = sub(absolute_region_power_index[0],temp1);
+    test();
+    if (temp2 < 0)
+    {
+        absolute_region_power_index[0] = temp1;
+        move16();
+    }
+    
+    temp1 = sub(31,ESF_ADJUSTMENT_TO_RMS_INDEX);
+
+	/*
+	 * The next line was corrected in Release 1.2 
+	 */
+
+    temp2 = sub(absolute_region_power_index[0], temp1);  
+    test();
+    if (temp2 > 0)
+    {
+        absolute_region_power_index[0] = temp1;
+        move16();
+    }
+
+    differential_region_power_index[0] = absolute_region_power_index[0];
+    move16();
+    
+    number_of_bits = 5;
+    move16();
+    
+    drp_num_bits[0] = 5;
+    move16();
+    
+    drp_code_bits[0] = (UWord16)add(absolute_region_power_index[0],ESF_ADJUSTMENT_TO_RMS_INDEX);
+    move16();
+
+    /* Lower limit the absolute region power indices to -8 and upper limit them to 31. Such extremes
+     may be mathematically impossible anyway.*/
+    for (region=1; region<number_of_regions; region++)
+    {
+        temp1 = sub(-8,ESF_ADJUSTMENT_TO_RMS_INDEX);
+        temp2 = sub(absolute_region_power_index[region],temp1);
+        test();
+        if (temp2 < 0)
+        {
+            absolute_region_power_index[region] = temp1;
+            move16();
+        }
+
+        temp1 = sub(31,ESF_ADJUSTMENT_TO_RMS_INDEX);
+        temp2 = sub(absolute_region_power_index[region],temp1);
+        test();
+        if (temp2 > 0)
+        {
+            absolute_region_power_index[region] = temp1;
+            move16();
+        }
+    }
+
+    for (region=1; region<number_of_regions; region++)
+    {
+        j = sub(absolute_region_power_index[region],absolute_region_power_index[region-1]);
+        temp = sub(j,DRP_DIFF_MIN);
+        test();
+        if (temp < 0)
+        {
+            j = DRP_DIFF_MIN;
+        }
+        j = sub(j,DRP_DIFF_MIN);
+        move16();
+        differential_region_power_index[region] = j;
+        move16();
+        
+        temp = add(absolute_region_power_index[region-1],differential_region_power_index[region]);
+        temp = add(temp,DRP_DIFF_MIN);
+        absolute_region_power_index[region] = temp;
+        move16();
+
+        number_of_bits = add(number_of_bits,differential_region_power_bits[region][j]);
+        drp_num_bits[region] = differential_region_power_bits[region][j];
+        move16();
+        drp_code_bits[region] = differential_region_power_codes[region][j];
+        move16();
+    }
+
+    return (number_of_bits);
+}
+
+/***************************************************************************
+ Function:    vector_quantize_mlts
+
+ Syntax:      void vector_quantize_mlts(number_of_available_bits,
+                                        number_of_regions,                     
+                                        num_categorization_control_possibilities,
+                                        mlt_coefs,                                    
+                                        absolute_region_power_index,                  
+                                        power_categories,                             
+                                        category_balances,                            
+                                        p_categorization_control,                               
+                                        region_mlt_bit_counts,                        
+                                        region_mlt_bits)                              
+                                                                                    
+              Word16 number_of_available_bits;                                        
+              Word16 number_of_regions;
+              Word16 num_categorization_control_possibilities;
+              Word16 mlt_coefs[DCT_LENGTH];                                         
+              Word16 absolute_region_power_index[MAX_NUMBER_OF_REGIONS];                  
+              Word16 power_categories[MAX_NUMBER_OF_REGIONS];                             
+              Word16 category_balances[MAX_NUM_CATEGORIZATION_CONTROL_POSSIBILITIES-1];         
+              Word16 *p_categorization_control;                                                 
+              Word16 region_mlt_bit_counts[MAX_NUMBER_OF_REGIONS];                        
+              Word32 region_mlt_bits[4*MAX_NUMBER_OF_REGIONS];                            
+
+ Description: Scalar quantized vector Huffman coding (SQVH)
+
+ 
+ WMOPS:     7kHz |    24kbit    |     32kbit
+          -------|--------------|----------------
+            AVG  |    0.57      |     0.65
+          -------|--------------|----------------  
+            MAX  |    0.78      |     0.83
+          -------|--------------|---------------- 
+
+           14kHz |    24kbit    |     32kbit     |     48kbit
+          -------|--------------|----------------|----------------
+            AVG  |    0.62      |     0.90       |     1.11
+          -------|--------------|----------------|----------------
+            MAX  |    1.16      |     1.39       |     1.54
+          -------|--------------|----------------|----------------
+
+***************************************************************************/
+
+void vector_quantize_mlts(Word16 number_of_available_bits,
+                          Word16 number_of_regions,
+                          Word16 num_categorization_control_possibilities,
+                          Word16 *mlt_coefs,
+                          Word16 *absolute_region_power_index,
+                          Word16 *power_categories,
+                          Word16 *category_balances,
+                          Word16 *p_categorization_control,
+                          Word16 *region_mlt_bit_counts,
+                          UWord32 *region_mlt_bits)
+{
+
+    Word16 *raw_mlt_ptr;
+    Word16 region;
+    Word16 category;
+    Word16 total_mlt_bits = 0;
+
+    Word16 temp;
+    Word16 temp1;
+    Word16 temp2;
+
+    /* Start in the middle of the categorization control range. */
+    temp = shr_nocheck(num_categorization_control_possibilities,1);
+    temp = sub(temp,1);
+    for (*p_categorization_control = 0; *p_categorization_control < temp; (*p_categorization_control)++)
+    {
+        region = category_balances[*p_categorization_control];
+        move16();
+        power_categories[region] = add(power_categories[region],1);
+        move16();
+    }
+
+    for (region=0; region<number_of_regions; region++)
+    {
+        category = power_categories[region];
+        move16();
+        temp = extract_l(L_mult0(region,REGION_SIZE));
+        raw_mlt_ptr = &mlt_coefs[temp];
+        move16();
+        temp = sub(category,(NUM_CATEGORIES-1));
+        test();
+        if (temp < 0)
+        {
+            region_mlt_bit_counts[region] =
+            vector_huffman(category, absolute_region_power_index[region],raw_mlt_ptr,
+                           &region_mlt_bits[shl_nocheck(region,2)]);
+        }
+        else
+        {
+            region_mlt_bit_counts[region] = 0;
+            move16();
+        }
+        total_mlt_bits = add(total_mlt_bits,region_mlt_bit_counts[region]);
+    }
+
+
+    /* If too few bits... */
+    temp = sub(total_mlt_bits,number_of_available_bits);
+    test();
+    test();
+    logic16();
+    while ((temp < 0) && (*p_categorization_control > 0))
+    {
+        test();
+        test();
+        logic16();
+        (*p_categorization_control)--;
+        region = category_balances[*p_categorization_control];
+        move16();
+        
+        power_categories[region] = sub(power_categories[region],1);
+        move16();
+
+        total_mlt_bits = sub(total_mlt_bits,region_mlt_bit_counts[region]);
+        category = power_categories[region];
+        move16();
+        
+        raw_mlt_ptr = &mlt_coefs[region*REGION_SIZE];
+        move16();
+        
+        temp = sub(category,(NUM_CATEGORIES-1));
+        test();
+        if (temp < 0)
+        {
+            region_mlt_bit_counts[region] =
+                vector_huffman(category, absolute_region_power_index[region],raw_mlt_ptr,
+                           &region_mlt_bits[shl_nocheck(region,2)]);
+        }
+        else
+        {
+            region_mlt_bit_counts[region] = 0;
+            move16();
+        }
+        total_mlt_bits = add(total_mlt_bits,region_mlt_bit_counts[region]);
+        temp = sub(total_mlt_bits,number_of_available_bits);
+    }
+
+    /* If too many bits... */
+    /* Set up for while loop test */
+    temp1 = sub(total_mlt_bits,number_of_available_bits);
+    temp2 = sub(*p_categorization_control,sub(num_categorization_control_possibilities,1));
+    test();
+    test();
+    logic16();
+    
+    while ((temp1 > 0) && (temp2 < 0))
+    {
+        /* operations for while contitions */
+        test();
+        test();
+        logic16();
+        
+        region = category_balances[*p_categorization_control];
+        move16();
+        
+        power_categories[region] = add(power_categories[region],1);
+        move16();
+
+        total_mlt_bits = sub(total_mlt_bits,region_mlt_bit_counts[region]);
+        category = power_categories[region];
+        move16();
+        
+        temp = extract_l(L_mult0(region,REGION_SIZE));
+        raw_mlt_ptr = &mlt_coefs[temp];
+        move16();
+        
+        temp = sub(category,(NUM_CATEGORIES-1));
+        test();
+        if (temp < 0)
+        {
+            region_mlt_bit_counts[region] =
+                vector_huffman(category, absolute_region_power_index[region],raw_mlt_ptr,
+                           &region_mlt_bits[shl_nocheck(region,2)]);
+        }
+        else
+        {
+            region_mlt_bit_counts[region] = 0;
+            move16();
+        }
+        total_mlt_bits = add(total_mlt_bits,region_mlt_bit_counts[region]);
+        (*p_categorization_control)++;
+        
+        temp1 = sub(total_mlt_bits,number_of_available_bits);
+        temp2 = sub(*p_categorization_control,sub(num_categorization_control_possibilities,1));
+    }
+}
+
+/***************************************************************************
+ Function:    vector_huffman
+
+ Syntax:      Word16 vector_huffman(Word16  category,     
+                                    Word16  power_index,  
+                                    Word16  *raw_mlt_ptr,  
+                                    UWord32 *word_ptr)     
+                                              
+              inputs:     Word16  category
+                          Word16  power_index
+                          Word16  *raw_mlt_ptr
+             
+              outputs:    number_of_region_bits
+                          *word_ptr
+                                      
+
+ Description: Huffman encoding for each region based on category and power_index  
+
+ WMOPS:     7kHz |    24kbit    |     32kbit
+          -------|--------------|----------------
+            AVG  |    0.03      |     0.03
+          -------|--------------|----------------  
+            MAX  |    0.04      |     0.04
+          -------|--------------|---------------- 
+
+           14kHz |    24kbit    |     32kbit     |     48kbit
+          -------|--------------|----------------|----------------
+            AVG  |    0.03      |     0.03       |     0.03
+          -------|--------------|----------------|----------------
+            MAX  |    0.04      |     0.04       |     0.04
+          -------|--------------|----------------|----------------
+
+***************************************************************************/
+Word16 vector_huffman(Word16 category,
+                      Word16 power_index,
+                      Word16 *raw_mlt_ptr,
+                      UWord32 *word_ptr)
+{
+ 
+
+    Word16  inv_of_step_size_times_std_dev;
+    Word16  j,n;
+    Word16  k;
+    Word16  number_of_region_bits;
+    Word16  number_of_non_zero;
+    Word16  vec_dim;
+    Word16  num_vecs;
+    Word16  kmax, kmax_plus_one;
+    Word16  index,signs_index;
+    Word16  *bitcount_table_ptr;
+    UWord16 *code_table_ptr;
+    Word32  code_bits;
+    Word16  number_of_code_bits;
+    UWord32 current_word;
+    Word16  current_word_bits_free;
+    
+    Word32 acca;
+    Word32 accb;
+    Word16 temp;
+
+    Word16 mytemp;			 /* new variable in Release 1.2 */
+    Word16 myacca;			 /* new variable in Release 1.2 */
+
+
+    /* initialize variables */
+    vec_dim = vector_dimension[category];
+    move16();
+
+    num_vecs = number_of_vectors[category];
+    move16();
+
+    kmax = max_bin[category];
+    move16();
+
+    kmax_plus_one = add(kmax,1);
+    move16();
+
+    current_word = 0L;
+    move16();
+
+    current_word_bits_free = 32;
+    move16();
+
+    number_of_region_bits = 0;
+    move16();
+
+    /* set up table pointers */
+    bitcount_table_ptr = (Word16 *)table_of_bitcount_tables[category];
+    code_table_ptr = (UWord16 *) table_of_code_tables[category];
+
+    /* compute inverse of step size * standard deviation */
+    acca = L_mult(step_size_inverse_table[category],standard_deviation_inverse_table[power_index]);
+    acca = L_shr_nocheck(acca,1);
+    acca = L_add(acca,4096);
+    acca = L_shr_nocheck(acca,13);
+
+	/*
+	 *  The next two lines are new to Release 1.2 
+	 */
+     
+	mytemp = (Word16)(acca & 0x3);
+    acca = L_shr_nocheck(acca,2);
+
+    inv_of_step_size_times_std_dev = extract_l(acca);
+
+
+    for (n=0; n<num_vecs; n++)
+    {
+        index = 0;
+        move16();
+        
+        signs_index = 0;
+        move16();
+        
+        number_of_non_zero = 0;
+        move16();
+        
+        for (j=0; j<vec_dim; j++)
+        {
+            k = abs_s(*raw_mlt_ptr);
+            
+            acca = L_mult(k,inv_of_step_size_times_std_dev);
+            acca = L_shr_nocheck(acca,1);
+		    
+			/*
+			 *  The next four lines are new to Release 1.2
+			 */
+
+			myacca = (Word16)L_mult(k,mytemp);
+			myacca = (Word16)L_shr_nocheck(myacca,1);
+			myacca = (Word16)L_add(myacca,int_dead_zone_low_bits[category]);
+			myacca = (Word16)L_shr_nocheck(myacca,2);
+
+            acca = L_add(acca,int_dead_zone[category]);
+
+			/*
+			 *  The next two lines are new to Release 1.2
+			 */
+
+			acca = L_add(acca,myacca);
+			acca = L_shr_nocheck(acca,13);
+
+            k = extract_l(acca);
+
+            test();
+            if (k != 0)
+            {
+                number_of_non_zero = add(number_of_non_zero,1);
+                signs_index = shl_nocheck(signs_index,1);
+                
+                test();
+                if (*raw_mlt_ptr > 0)
+                {
+                    signs_index = add(signs_index,1);
+                }
+                
+                temp = sub(k,kmax);
+                test();
+                if (temp > 0)
+                {
+                    k = kmax;
+                    move16();
+                }
+            }
+            acca = L_shr_nocheck(L_mult(index,(kmax_plus_one)),1);
+            index = extract_l(acca);
+            index = add(index,k);
+            raw_mlt_ptr++;
+        }
+
+        code_bits = *(code_table_ptr+index);
+        number_of_code_bits = add((*(bitcount_table_ptr+index)),number_of_non_zero);
+        number_of_region_bits = add(number_of_region_bits,number_of_code_bits);
+
+        acca = code_bits << number_of_non_zero;
+        accb = L_deposit_l(signs_index);
+        acca = L_add(acca,accb);
+        code_bits = acca;
+        move32();
+
+        /* msb of codebits is transmitted first. */
+        j = sub(current_word_bits_free,number_of_code_bits);
+        test();
+        if (j >= 0)
+        {
+            test();
+            acca = code_bits << j;
+            current_word = L_add(current_word,acca);
+            current_word_bits_free = j;
+            move16();
+        }
+        else
+        {
+            j = negate(j);
+            acca = L_shr_nocheck(code_bits,j);
+            current_word = L_add(current_word,acca);
+            
+            *word_ptr++ = current_word;
+            move16();
+
+            current_word_bits_free = sub(32,j);
+            test();
+            current_word = code_bits << current_word_bits_free;
+        }
+    }
+
+    *word_ptr++ = current_word;
+    move16();
+
+    return (number_of_region_bits);
+}
+
+
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/encode/sam2coef.c b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/encode/sam2coef.c
new file mode 100644
index 0000000..3dd5b76
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/g7221/encode/sam2coef.c
@@ -0,0 +1,271 @@
+/******************************************************************************
+**
+**   ITU-T G.722.1 (2005-05) - Fixed point implementation for main body and Annex C
+**   > Software Release 2.1 (2008-06)
+**     (Simple repackaging; no change from 2005-05 Release 2.0 code)
+**
+**   � 2004 Polycom, Inc.
+**
+**	 All rights reserved.
+**
+******************************************************************************/
+
+/******************************************************************************
+* Filename: samples_to_rmlt_coefs.c
+*
+* Purpose:  Convert Samples to Reversed MLT (Modulated Lapped Transform) 
+*           Coefficients
+*
+*     The "Reversed MLT" is an overlapped block transform which uses
+*     even symmetry * on the left, odd symmetry on the right and a
+*     Type IV DCT as the block transform.  * It is thus similar to a
+*     MLT which uses odd symmetry on the left, even symmetry * on the
+*     right and a Type IV DST as the block transform.  In fact, it is
+*     equivalent * to reversing the order of the samples, performing
+*     an MLT and then negating all * the even-numbered coefficients.
+*
+******************************************************************************/
+
+/***************************************************************************
+ Include files                                                           
+***************************************************************************/
+#include "defs.h"
+#include "tables.h"
+#include "count.h"
+
+/***************************************************************************
+ Function:    samples_to_rmlt_coefs 
+
+ Syntax:      Word16 samples_to_rmlt_coefs(new_samples, 
+                                           old_samples,
+                                           coefs,
+                                           dct_length)
+                    Word16 *new_samples;           
+                    Word16 *old_samples;           
+                    Word16 *coefs;                 
+                    Word16 dct_length;
+
+ Description: Convert samples to MLT coefficients
+
+ Design Notes:
+
+ WMOPS:     7kHz |    24kbit    |     32kbit
+          -------|--------------|----------------
+            AVG  |    1.40      |     1.40
+          -------|--------------|----------------  
+            MAX  |    1.40      |     1.40
+          -------|--------------|---------------- 
+				
+           14kHz |    24kbit    |     32kbit     |     48kbit
+          -------|--------------|----------------|----------------
+            AVG  |    3.07      |     3.07       |     3.07
+          -------|--------------|----------------|----------------
+            MAX  |    3.10      |     3.10       |     3.10
+          -------|--------------|----------------|----------------
+				
+***************************************************************************/
+
+Word16 samples_to_rmlt_coefs(const Word16 *new_samples,Word16 *old_samples,Word16 *coefs,Word16 dct_length)
+{
+
+    Word16	index, vals_left,mag_shift,n;
+    Word16	windowed_data[MAX_DCT_LENGTH];
+    Word16	*old_ptr;
+    const Word16 *new_ptr, *sam_low, *sam_high;
+    Word16	*win_low, *win_high;
+    Word16	*dst_ptr;
+    Word16  neg_win_low;
+    Word16  samp_high;
+    Word16  half_dct_size;
+    
+    Word32	acca;
+    Word32	accb;
+    Word16	temp;
+    Word16	temp1;
+    Word16	temp2;
+    Word16	temp5;
+   
+    half_dct_size = shr_nocheck(dct_length,1);
+   
+    /*++++++++++++++++++++++++++++++++++++++++++++*/
+    /* Get the first half of the windowed samples */
+    /*++++++++++++++++++++++++++++++++++++++++++++*/
+    
+    dst_ptr  = windowed_data;
+    move16();
+    
+    /* address arithmetic */
+    test();
+    if (dct_length==DCT_LENGTH)
+    {
+        win_high = samples_to_rmlt_window + half_dct_size;
+    }
+    else
+    {
+        win_high = max_samples_to_rmlt_window + half_dct_size;
+    }
+    
+    win_low  = win_high;
+    move16();
+    
+    /* address arithmetic */
+    sam_high = old_samples + half_dct_size;
+    
+    sam_low  = sam_high;
+    move16();
+    
+    for (vals_left = half_dct_size;vals_left > 0;vals_left--)
+    {
+        acca = 0L;
+        move32();
+        
+        acca = L_mac(acca,*--win_low, *--sam_low);
+        acca = L_mac(acca,*win_high++, *sam_high++);
+        temp = itu_round(acca); 
+        
+        *dst_ptr++ = temp;
+        move16();
+    }           
+    
+    /*+++++++++++++++++++++++++++++++++++++++++++++*/
+    /* Get the second half of the windowed samples */
+    /*+++++++++++++++++++++++++++++++++++++++++++++*/
+    
+    sam_low  = new_samples;
+    move16();
+
+    /* address arithmetic */
+    sam_high = new_samples + dct_length;
+    
+    for (vals_left = half_dct_size;    vals_left > 0;    vals_left--)
+    {
+        acca = 0L;
+        move32();
+
+        acca = L_mac(acca,*--win_high, *sam_low++);
+        neg_win_low = negate(*win_low++);
+        samp_high = *--sam_high;
+        acca = L_mac(acca, neg_win_low, samp_high);
+        temp = itu_round(acca); 
+        
+        *dst_ptr++=temp;
+        move16();
+    }
+       
+    /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+    /* Save the new samples for next time, when they will be the old samples */
+    /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+    
+    new_ptr = new_samples;
+    move16();
+
+    old_ptr = old_samples;
+    move16();
+
+    for (vals_left = dct_length;vals_left > 0;vals_left--)
+    {
+        *old_ptr++ = *new_ptr++;
+        move16();
+    }
+    
+    /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+    /* Calculate how many bits to shift up the input to the DCT.             */
+    /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+    
+    temp1=0;
+    move16();
+
+    for(index=0;index<dct_length;index++)
+    {
+        temp2 = abs_s(windowed_data[index]);
+        temp = sub(temp2,temp1);
+        test();
+        if(temp > 0)
+        {
+            move16();
+            temp1 = temp2;
+        }
+    }
+    
+    mag_shift=0;
+    move16();
+
+    temp = sub(temp1,14000);
+    test();
+    if (temp >= 0)
+    {
+        mag_shift = 0;
+        move16();
+    }
+    else
+    {
+        temp = sub(temp1,438);
+        test();
+        if(temp < 0)
+            temp = add(temp1,1);
+        else 
+        {
+            temp = temp1;
+            move16();
+        }
+        accb = L_mult(temp,9587);
+        acca = L_shr_nocheck(accb,20);
+        temp5 = extract_l(acca);
+        temp = norm_s(temp5);
+        test();
+        if (temp == 0)
+        {
+            mag_shift = 9;
+            move16();
+        }
+        else
+            mag_shift = sub(temp,6);
+        
+    }
+
+    acca = 0L;
+    move32();
+    for(index=0; index<dct_length; index++)
+    {
+        temp = abs_s( windowed_data[index]);
+        acca = L_add(acca,temp);
+    }
+    
+    acca = L_shr_nocheck(acca,7);
+    
+    test();
+    if (temp1 < acca)
+    {
+        mag_shift = sub(mag_shift,1);
+    }
+
+    test();
+    if (mag_shift > 0) 
+    {
+        for(index=0;index<dct_length;index++)
+        {
+            windowed_data[index] = shl_nocheck(windowed_data[index],mag_shift);
+        }
+    }
+    else 
+    {
+        test();
+        if (mag_shift < 0) 
+        {
+            n = negate(mag_shift);
+            for(index=0;index<dct_length;index++)
+            {
+                windowed_data[index] = shr_nocheck(windowed_data[index],n);
+                move16();
+            }
+        }
+    }
+
+    /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+    /* Perform a Type IV DCT on the windowed data to get the coefficients */
+    /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+    dct_type_iv_a(windowed_data, coefs, dct_length);
+
+    return(mag_shift);
+}
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/milenage/milenage.c b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/milenage/milenage.c
new file mode 100644
index 0000000..66dae9b
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/milenage/milenage.c
@@ -0,0 +1,284 @@
+/*-------------------------------------------------------------------
+ *          Example algorithms f1, f1*, f2, f3, f4, f5, f5*
+ *-------------------------------------------------------------------
+ *
+ *  A sample implementation of the example 3GPP authentication and
+ *  key agreement functions f1, f1*, f2, f3, f4, f5 and f5*.  This is
+ *  a byte-oriented implementation of the functions, and of the block
+ *  cipher kernel function Rijndael.
+ *
+ *  This has been coded for clarity, not necessarily for efficiency.
+ *
+ *  The functions f2, f3, f4 and f5 share the same inputs and have
+ *  been coded together as a single function.  f1, f1* and f5* are
+ *  all coded separately.
+ *
+ *-----------------------------------------------------------------*/
+
+#include "milenage.h"
+#include "rijndael.h"
+
+/*--------------------------- prototypes --------------------------*/
+
+
+
+/*-------------------------------------------------------------------
+ *                            Algorithm f1
+ *-------------------------------------------------------------------
+ *
+ *  Computes network authentication code MAC-A from key K, random
+ *  challenge RAND, sequence number SQN and authentication management
+ *  field AMF.
+ *
+ *-----------------------------------------------------------------*/
+
+void f1    ( u8 k[16], u8 rand[16], u8 sqn[6], u8 amf[2], 
+             u8 mac_a[8], u8 op[16] )
+{
+  u8 op_c[16];
+  u8 temp[16];
+  u8 in1[16];
+  u8 out1[16];
+  u8 rijndaelInput[16];
+  u8 i;
+
+  RijndaelKeySchedule( k );
+
+  ComputeOPc( op_c, op );
+
+  for (i=0; i<16; i++)
+    rijndaelInput[i] = rand[i] ^ op_c[i];
+  RijndaelEncrypt( rijndaelInput, temp );
+
+  for (i=0; i<6; i++)
+  {
+    in1[i]    = sqn[i];
+    in1[i+8]  = sqn[i];
+  }
+  for (i=0; i<2; i++)
+  {
+    in1[i+6]  = amf[i];
+    in1[i+14] = amf[i];
+  }
+
+  /* XOR op_c and in1, rotate by r1=64, and XOR *
+   * on the constant c1 (which is all zeroes)   */
+
+  for (i=0; i<16; i++)
+    rijndaelInput[(i+8) % 16] = in1[i] ^ op_c[i];
+
+  /* XOR on the value temp computed before */
+
+  for (i=0; i<16; i++)
+    rijndaelInput[i] ^= temp[i];
+  
+  RijndaelEncrypt( rijndaelInput, out1 );
+  for (i=0; i<16; i++)
+    out1[i] ^= op_c[i];
+
+  for (i=0; i<8; i++)
+    mac_a[i] = out1[i];
+
+  return;
+} /* end of function f1 */
+
+
+  
+/*-------------------------------------------------------------------
+ *                            Algorithms f2-f5
+ *-------------------------------------------------------------------
+ *
+ *  Takes key K and random challenge RAND, and returns response RES,
+ *  confidentiality key CK, integrity key IK and anonymity key AK.
+ *
+ *-----------------------------------------------------------------*/
+
+void f2345 ( u8 k[16], u8 rand[16],
+             u8 res[8], u8 ck[16], u8 ik[16], u8 ak[6], u8 op[16] )
+{
+  u8 op_c[16];
+  u8 temp[16];
+  u8 out[16];
+  u8 rijndaelInput[16];
+  u8 i;
+
+  RijndaelKeySchedule( k );
+
+  ComputeOPc( op_c, op );
+
+  for (i=0; i<16; i++)
+    rijndaelInput[i] = rand[i] ^ op_c[i];
+  RijndaelEncrypt( rijndaelInput, temp );
+
+  /* To obtain output block OUT2: XOR OPc and TEMP,    *
+   * rotate by r2=0, and XOR on the constant c2 (which *
+   * is all zeroes except that the last bit is 1).     */
+
+  for (i=0; i<16; i++)
+    rijndaelInput[i] = temp[i] ^ op_c[i];
+  rijndaelInput[15] ^= 1;
+
+  RijndaelEncrypt( rijndaelInput, out );
+  for (i=0; i<16; i++)
+    out[i] ^= op_c[i];
+
+  for (i=0; i<8; i++)
+    res[i] = out[i+8];
+  for (i=0; i<6; i++)
+    ak[i]  = out[i];
+
+  /* To obtain output block OUT3: XOR OPc and TEMP,        *
+   * rotate by r3=32, and XOR on the constant c3 (which    *
+   * is all zeroes except that the next to last bit is 1). */
+
+  for (i=0; i<16; i++)
+    rijndaelInput[(i+12) % 16] = temp[i] ^ op_c[i];
+  rijndaelInput[15] ^= 2;
+
+  RijndaelEncrypt( rijndaelInput, out );
+  for (i=0; i<16; i++)
+    out[i] ^= op_c[i];
+
+  for (i=0; i<16; i++)
+    ck[i] = out[i];
+
+  /* To obtain output block OUT4: XOR OPc and TEMP,         *
+   * rotate by r4=64, and XOR on the constant c4 (which     *
+   * is all zeroes except that the 2nd from last bit is 1). */
+
+  for (i=0; i<16; i++)
+    rijndaelInput[(i+8) % 16] = temp[i] ^ op_c[i];
+  rijndaelInput[15] ^= 4;
+
+  RijndaelEncrypt( rijndaelInput, out );
+  for (i=0; i<16; i++)
+    out[i] ^= op_c[i];
+
+  for (i=0; i<16; i++)
+    ik[i] = out[i];
+
+  return;
+} /* end of function f2345 */
+
+  
+/*-------------------------------------------------------------------
+ *                            Algorithm f1*
+ *-------------------------------------------------------------------
+ *
+ *  Computes resynch authentication code MAC-S from key K, random
+ *  challenge RAND, sequence number SQN and authentication management
+ *  field AMF.
+ *
+ *-----------------------------------------------------------------*/
+
+void f1star( u8 k[16], u8 rand[16], u8 sqn[6], u8 amf[2], 
+             u8 mac_s[8], u8 op[16] )
+{
+  u8 op_c[16];
+  u8 temp[16];
+  u8 in1[16];
+  u8 out1[16];
+  u8 rijndaelInput[16];
+  u8 i;
+
+  RijndaelKeySchedule( k );
+
+  ComputeOPc( op_c, op );
+
+  for (i=0; i<16; i++)
+    rijndaelInput[i] = rand[i] ^ op_c[i];
+  RijndaelEncrypt( rijndaelInput, temp );
+
+  for (i=0; i<6; i++)
+  {
+    in1[i]    = sqn[i];
+    in1[i+8]  = sqn[i];
+  }
+  for (i=0; i<2; i++)
+  {
+    in1[i+6]  = amf[i];
+    in1[i+14] = amf[i];
+  }
+
+  /* XOR op_c and in1, rotate by r1=64, and XOR *
+   * on the constant c1 (which is all zeroes)   */
+
+  for (i=0; i<16; i++)
+    rijndaelInput[(i+8) % 16] = in1[i] ^ op_c[i];
+
+  /* XOR on the value temp computed before */
+
+  for (i=0; i<16; i++)
+    rijndaelInput[i] ^= temp[i];
+  
+  RijndaelEncrypt( rijndaelInput, out1 );
+  for (i=0; i<16; i++)
+    out1[i] ^= op_c[i];
+
+  for (i=0; i<8; i++)
+    mac_s[i] = out1[i+8];
+
+  return;
+} /* end of function f1star */
+
+  
+/*-------------------------------------------------------------------
+ *                            Algorithm f5*
+ *-------------------------------------------------------------------
+ *
+ *  Takes key K and random challenge RAND, and returns resynch
+ *  anonymity key AK.
+ *
+ *-----------------------------------------------------------------*/
+
+void f5star( u8 k[16], u8 rand[16],
+             u8 ak[6], u8 op[16] )
+{
+  u8 op_c[16];
+  u8 temp[16];
+  u8 out[16];
+  u8 rijndaelInput[16];
+  u8 i;
+
+  RijndaelKeySchedule( k );
+
+  ComputeOPc( op_c, op );
+
+  for (i=0; i<16; i++)
+    rijndaelInput[i] = rand[i] ^ op_c[i];
+  RijndaelEncrypt( rijndaelInput, temp );
+
+  /* To obtain output block OUT5: XOR OPc and TEMP,         *
+   * rotate by r5=96, and XOR on the constant c5 (which     *
+   * is all zeroes except that the 3rd from last bit is 1). */
+
+  for (i=0; i<16; i++)
+    rijndaelInput[(i+4) % 16] = temp[i] ^ op_c[i];
+  rijndaelInput[15] ^= 8;
+
+  RijndaelEncrypt( rijndaelInput, out );
+  for (i=0; i<16; i++)
+    out[i] ^= op_c[i];
+
+  for (i=0; i<6; i++)
+    ak[i] = out[i];
+
+  return;
+} /* end of function f5star */
+
+  
+/*-------------------------------------------------------------------
+ *  Function to compute OPc from OP and K.  Assumes key schedule has
+    already been performed.
+ *-----------------------------------------------------------------*/
+
+void ComputeOPc( u8 op_c[16], u8 op[16] )
+{
+  u8 i;
+  
+  RijndaelEncrypt( op, op_c );
+  for (i=0; i<16; i++)
+    op_c[i] ^= op[i];
+
+  return;
+} /* end of function ComputeOPc */
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/milenage/milenage.h b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/milenage/milenage.h
new file mode 100644
index 0000000..a5f407f
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/milenage/milenage.h
@@ -0,0 +1,35 @@
+/*-------------------------------------------------------------------
+ *          Example algorithms f1, f1*, f2, f3, f4, f5, f5*
+ *-------------------------------------------------------------------
+ *
+ *  A sample implementation of the example 3GPP authentication and
+ *  key agreement functions f1, f1*, f2, f3, f4, f5 and f5*.  This is
+ *  a byte-oriented implementation of the functions, and of the block
+ *  cipher kernel function Rijndael.
+ *
+ *  This has been coded for clarity, not necessarily for efficiency.
+ *
+ *  The functions f2, f3, f4 and f5 share the same inputs and have
+ *  been coded together as a single function.  f1, f1* and f5* are
+ *  all coded separately.
+ *
+ *-----------------------------------------------------------------*/
+
+#ifndef MILENAGE_H
+#define MILENAGE_H
+
+typedef unsigned char u8;
+
+
+void f1    ( u8 k[16], u8 rand[16], u8 sqn[6], u8 amf[2],
+             u8 mac_a[8], u8 op[16] );
+void f2345 ( u8 k[16], u8 rand[16],
+             u8 res[8], u8 ck[16], u8 ik[16], u8 ak[6], u8 op[16] );
+void f1star( u8 k[16], u8 rand[16], u8 sqn[6], u8 amf[2],
+             u8 mac_s[8], u8 op[16] );
+void f5star( u8 k[16], u8 rand[16],
+             u8 ak[6], u8 op[16] );
+void ComputeOPc( u8 op_c[16], u8 op[16] );
+
+
+#endif
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/milenage/rijndael.c b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/milenage/rijndael.c
new file mode 100644
index 0000000..86557b9
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/milenage/rijndael.c
@@ -0,0 +1,444 @@
+/*-------------------------------------------------------------------
+ *                      Rijndael Implementation
+ *-------------------------------------------------------------------
+ *
+ *  A sample 32-bit orientated implementation of Rijndael, the
+ *  suggested kernel for the example 3GPP authentication and key
+ *  agreement functions.
+ *
+ *  This implementation draws on the description in section 5.2 of
+ *  the AES proposal and also on the implementation by
+ *  Dr B. R. Gladman <brg at gladman.uk.net> 9th October 2000.
+ *  It uses a number of large (4k) lookup tables to implement the
+ *  algorithm in an efficient manner.
+ *
+ *  Note: in this implementation the State is stored in four 32-bit
+ *  words, one per column of the State, with the top byte of the
+ *  column being the _least_ significant byte of the word.
+ *
+*-----------------------------------------------------------------*/
+
+#include <pj/types.h>
+
+#if defined(PJ_IS_LITTLE_ENDIAN) && PJ_IS_LITTLE_ENDIAN != 0
+#	define LITTLE_ENDIAN	/* For INTEL architecture */
+#endif
+
+typedef unsigned char   u8;
+typedef unsigned int	 u32;
+
+/* Circular byte rotates of 32 bit values */
+
+#define rot1(x) ((x <<  8) | (x >> 24))
+#define rot2(x) ((x << 16) | (x >> 16))
+#define rot3(x) ((x << 24) | (x >>  8))
+
+/* Extract a byte from a 32-bit u32 */
+
+#define byte0(x)    ((u8)(x))
+#define byte1(x)    ((u8)(x >>  8))
+#define byte2(x)    ((u8)(x >> 16))
+#define byte3(x)    ((u8)(x >> 24))
+
+
+/* Put or get a 32 bit u32 (v) in machine order from a byte	*
+ * address in (x)                                           */
+
+#ifdef  LITTLE_ENDIAN
+
+#define u32_in(x)     (*(u32*)(x))
+#define u32_out(x,y)  (*(u32*)(x) = y)
+
+#else
+
+/* Invert byte order in a 32 bit variable */
+
+__inline u32 byte_swap(const u32 x)
+{
+    return rot1(x) & 0x00ff00ff | rot3(x) & 0xff00ff00;
+}
+__inline u32 u32_in(const u8 x[])
+{
+  return byte_swap(*(u32*)x);
+};
+__inline void u32_out(u8 x[], const u32 v) 
+{
+  *(u32*)x = byte_swap(v);
+};
+
+#endif
+
+/*--------------- The lookup tables ----------------------------*/
+
+static u32 rnd_con[10] = 
+{ 
+ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36
+};
+
+static u32 ft_tab[4][256] = 
+{
+ {
+ 0xA56363C6,0x847C7CF8,0x997777EE,0x8D7B7BF6,0x0DF2F2FF,0xBD6B6BD6,0xB16F6FDE,0x54C5C591,
+ 0x50303060,0x03010102,0xA96767CE,0x7D2B2B56,0x19FEFEE7,0x62D7D7B5,0xE6ABAB4D,0x9A7676EC,
+ 0x45CACA8F,0x9D82821F,0x40C9C989,0x877D7DFA,0x15FAFAEF,0xEB5959B2,0xC947478E,0x0BF0F0FB,
+ 0xECADAD41,0x67D4D4B3,0xFDA2A25F,0xEAAFAF45,0xBF9C9C23,0xF7A4A453,0x967272E4,0x5BC0C09B,
+ 0xC2B7B775,0x1CFDFDE1,0xAE93933D,0x6A26264C,0x5A36366C,0x413F3F7E,0x02F7F7F5,0x4FCCCC83,
+ 0x5C343468,0xF4A5A551,0x34E5E5D1,0x08F1F1F9,0x937171E2,0x73D8D8AB,0x53313162,0x3F15152A,
+ 0x0C040408,0x52C7C795,0x65232346,0x5EC3C39D,0x28181830,0xA1969637,0x0F05050A,0xB59A9A2F,
+ 0x0907070E,0x36121224,0x9B80801B,0x3DE2E2DF,0x26EBEBCD,0x6927274E,0xCDB2B27F,0x9F7575EA,
+ 0x1B090912,0x9E83831D,0x742C2C58,0x2E1A1A34,0x2D1B1B36,0xB26E6EDC,0xEE5A5AB4,0xFBA0A05B,
+ 0xF65252A4,0x4D3B3B76,0x61D6D6B7,0xCEB3B37D,0x7B292952,0x3EE3E3DD,0x712F2F5E,0x97848413,
+ 0xF55353A6,0x68D1D1B9,0000000000,0x2CEDEDC1,0x60202040,0x1FFCFCE3,0xC8B1B179,0xED5B5BB6,
+ 0xBE6A6AD4,0x46CBCB8D,0xD9BEBE67,0x4B393972,0xDE4A4A94,0xD44C4C98,0xE85858B0,0x4ACFCF85,
+ 0x6BD0D0BB,0x2AEFEFC5,0xE5AAAA4F,0x16FBFBED,0xC5434386,0xD74D4D9A,0x55333366,0x94858511,
+ 0xCF45458A,0x10F9F9E9,0x06020204,0x817F7FFE,0xF05050A0,0x443C3C78,0xBA9F9F25,0xE3A8A84B,
+ 0xF35151A2,0xFEA3A35D,0xC0404080,0x8A8F8F05,0xAD92923F,0xBC9D9D21,0x48383870,0x04F5F5F1,
+ 0xDFBCBC63,0xC1B6B677,0x75DADAAF,0x63212142,0x30101020,0x1AFFFFE5,0x0EF3F3FD,0x6DD2D2BF,
+ 0x4CCDCD81,0x140C0C18,0x35131326,0x2FECECC3,0xE15F5FBE,0xA2979735,0xCC444488,0x3917172E,
+ 0x57C4C493,0xF2A7A755,0x827E7EFC,0x473D3D7A,0xAC6464C8,0xE75D5DBA,0x2B191932,0x957373E6,
+ 0xA06060C0,0x98818119,0xD14F4F9E,0x7FDCDCA3,0x66222244,0x7E2A2A54,0xAB90903B,0x8388880B,
+ 0xCA46468C,0x29EEEEC7,0xD3B8B86B,0x3C141428,0x79DEDEA7,0xE25E5EBC,0x1D0B0B16,0x76DBDBAD,
+ 0x3BE0E0DB,0x56323264,0x4E3A3A74,0x1E0A0A14,0xDB494992,0x0A06060C,0x6C242448,0xE45C5CB8,
+ 0x5DC2C29F,0x6ED3D3BD,0xEFACAC43,0xA66262C4,0xA8919139,0xA4959531,0x37E4E4D3,0x8B7979F2,
+ 0x32E7E7D5,0x43C8C88B,0x5937376E,0xB76D6DDA,0x8C8D8D01,0x64D5D5B1,0xD24E4E9C,0xE0A9A949,
+ 0xB46C6CD8,0xFA5656AC,0x07F4F4F3,0x25EAEACF,0xAF6565CA,0x8E7A7AF4,0xE9AEAE47,0x18080810,
+ 0xD5BABA6F,0x887878F0,0x6F25254A,0x722E2E5C,0x241C1C38,0xF1A6A657,0xC7B4B473,0x51C6C697,
+ 0x23E8E8CB,0x7CDDDDA1,0x9C7474E8,0x211F1F3E,0xDD4B4B96,0xDCBDBD61,0x868B8B0D,0x858A8A0F,
+ 0x907070E0,0x423E3E7C,0xC4B5B571,0xAA6666CC,0xD8484890,0x05030306,0x01F6F6F7,0x120E0E1C,
+ 0xA36161C2,0x5F35356A,0xF95757AE,0xD0B9B969,0x91868617,0x58C1C199,0x271D1D3A,0xB99E9E27,
+ 0x38E1E1D9,0x13F8F8EB,0xB398982B,0x33111122,0xBB6969D2,0x70D9D9A9,0x898E8E07,0xA7949433,
+ 0xB69B9B2D,0x221E1E3C,0x92878715,0x20E9E9C9,0x49CECE87,0xFF5555AA,0x78282850,0x7ADFDFA5,
+ 0x8F8C8C03,0xF8A1A159,0x80898909,0x170D0D1A,0xDABFBF65,0x31E6E6D7,0xC6424284,0xB86868D0,
+ 0xC3414182,0xB0999929,0x772D2D5A,0x110F0F1E,0xCBB0B07B,0xFC5454A8,0xD6BBBB6D,0x3A16162C 
+ },
+ {
+ 0x6363C6A5,0x7C7CF884,0x7777EE99,0x7B7BF68D,0xF2F2FF0D,0x6B6BD6BD,0x6F6FDEB1,0xC5C59154,
+ 0x30306050,0x01010203,0x6767CEA9,0x2B2B567D,0xFEFEE719,0xD7D7B562,0xABAB4DE6,0x7676EC9A,
+ 0xCACA8F45,0x82821F9D,0xC9C98940,0x7D7DFA87,0xFAFAEF15,0x5959B2EB,0x47478EC9,0xF0F0FB0B,
+ 0xADAD41EC,0xD4D4B367,0xA2A25FFD,0xAFAF45EA,0x9C9C23BF,0xA4A453F7,0x7272E496,0xC0C09B5B,
+ 0xB7B775C2,0xFDFDE11C,0x93933DAE,0x26264C6A,0x36366C5A,0x3F3F7E41,0xF7F7F502,0xCCCC834F,
+ 0x3434685C,0xA5A551F4,0xE5E5D134,0xF1F1F908,0x7171E293,0xD8D8AB73,0x31316253,0x15152A3F,
+ 0x0404080C,0xC7C79552,0x23234665,0xC3C39D5E,0x18183028,0x969637A1,0x05050A0F,0x9A9A2FB5,
+ 0x07070E09,0x12122436,0x80801B9B,0xE2E2DF3D,0xEBEBCD26,0x27274E69,0xB2B27FCD,0x7575EA9F,
+ 0x0909121B,0x83831D9E,0x2C2C5874,0x1A1A342E,0x1B1B362D,0x6E6EDCB2,0x5A5AB4EE,0xA0A05BFB,
+ 0x5252A4F6,0x3B3B764D,0xD6D6B761,0xB3B37DCE,0x2929527B,0xE3E3DD3E,0x2F2F5E71,0x84841397,
+ 0x5353A6F5,0xD1D1B968,0000000000,0xEDEDC12C,0x20204060,0xFCFCE31F,0xB1B179C8,0x5B5BB6ED,
+ 0x6A6AD4BE,0xCBCB8D46,0xBEBE67D9,0x3939724B,0x4A4A94DE,0x4C4C98D4,0x5858B0E8,0xCFCF854A,
+ 0xD0D0BB6B,0xEFEFC52A,0xAAAA4FE5,0xFBFBED16,0x434386C5,0x4D4D9AD7,0x33336655,0x85851194,
+ 0x45458ACF,0xF9F9E910,0x02020406,0x7F7FFE81,0x5050A0F0,0x3C3C7844,0x9F9F25BA,0xA8A84BE3,
+ 0x5151A2F3,0xA3A35DFE,0x404080C0,0x8F8F058A,0x92923FAD,0x9D9D21BC,0x38387048,0xF5F5F104,
+ 0xBCBC63DF,0xB6B677C1,0xDADAAF75,0x21214263,0x10102030,0xFFFFE51A,0xF3F3FD0E,0xD2D2BF6D,
+ 0xCDCD814C,0x0C0C1814,0x13132635,0xECECC32F,0x5F5FBEE1,0x979735A2,0x444488CC,0x17172E39,
+ 0xC4C49357,0xA7A755F2,0x7E7EFC82,0x3D3D7A47,0x6464C8AC,0x5D5DBAE7,0x1919322B,0x7373E695,
+ 0x6060C0A0,0x81811998,0x4F4F9ED1,0xDCDCA37F,0x22224466,0x2A2A547E,0x90903BAB,0x88880B83,
+ 0x46468CCA,0xEEEEC729,0xB8B86BD3,0x1414283C,0xDEDEA779,0x5E5EBCE2,0x0B0B161D,0xDBDBAD76,
+ 0xE0E0DB3B,0x32326456,0x3A3A744E,0x0A0A141E,0x494992DB,0x06060C0A,0x2424486C,0x5C5CB8E4,
+ 0xC2C29F5D,0xD3D3BD6E,0xACAC43EF,0x6262C4A6,0x919139A8,0x959531A4,0xE4E4D337,0x7979F28B,
+ 0xE7E7D532,0xC8C88B43,0x37376E59,0x6D6DDAB7,0x8D8D018C,0xD5D5B164,0x4E4E9CD2,0xA9A949E0,
+ 0x6C6CD8B4,0x5656ACFA,0xF4F4F307,0xEAEACF25,0x6565CAAF,0x7A7AF48E,0xAEAE47E9,0x08081018,
+ 0xBABA6FD5,0x7878F088,0x25254A6F,0x2E2E5C72,0x1C1C3824,0xA6A657F1,0xB4B473C7,0xC6C69751,
+ 0xE8E8CB23,0xDDDDA17C,0x7474E89C,0x1F1F3E21,0x4B4B96DD,0xBDBD61DC,0x8B8B0D86,0x8A8A0F85,
+ 0x7070E090,0x3E3E7C42,0xB5B571C4,0x6666CCAA,0x484890D8,0x03030605,0xF6F6F701,0x0E0E1C12,
+ 0x6161C2A3,0x35356A5F,0x5757AEF9,0xB9B969D0,0x86861791,0xC1C19958,0x1D1D3A27,0x9E9E27B9,
+ 0xE1E1D938,0xF8F8EB13,0x98982BB3,0x11112233,0x6969D2BB,0xD9D9A970,0x8E8E0789,0x949433A7,
+ 0x9B9B2DB6,0x1E1E3C22,0x87871592,0xE9E9C920,0xCECE8749,0x5555AAFF,0x28285078,0xDFDFA57A,
+ 0x8C8C038F,0xA1A159F8,0x89890980,0x0D0D1A17,0xBFBF65DA,0xE6E6D731,0x424284C6,0x6868D0B8,
+ 0x414182C3,0x999929B0,0x2D2D5A77,0x0F0F1E11,0xB0B07BCB,0x5454A8FC,0xBBBB6DD6,0x16162C3A 
+ },
+ {
+ 0x63C6A563,0x7CF8847C,0x77EE9977,0x7BF68D7B,0xF2FF0DF2,0x6BD6BD6B,0x6FDEB16F,0xC59154C5,
+ 0x30605030,0x01020301,0x67CEA967,0x2B567D2B,0xFEE719FE,0xD7B562D7,0xAB4DE6AB,0x76EC9A76,
+ 0xCA8F45CA,0x821F9D82,0xC98940C9,0x7DFA877D,0xFAEF15FA,0x59B2EB59,0x478EC947,0xF0FB0BF0,
+ 0xAD41ECAD,0xD4B367D4,0xA25FFDA2,0xAF45EAAF,0x9C23BF9C,0xA453F7A4,0x72E49672,0xC09B5BC0,
+ 0xB775C2B7,0xFDE11CFD,0x933DAE93,0x264C6A26,0x366C5A36,0x3F7E413F,0xF7F502F7,0xCC834FCC,
+ 0x34685C34,0xA551F4A5,0xE5D134E5,0xF1F908F1,0x71E29371,0xD8AB73D8,0x31625331,0x152A3F15,
+ 0x04080C04,0xC79552C7,0x23466523,0xC39D5EC3,0x18302818,0x9637A196,0x050A0F05,0x9A2FB59A,
+ 0x070E0907,0x12243612,0x801B9B80,0xE2DF3DE2,0xEBCD26EB,0x274E6927,0xB27FCDB2,0x75EA9F75,
+ 0x09121B09,0x831D9E83,0x2C58742C,0x1A342E1A,0x1B362D1B,0x6EDCB26E,0x5AB4EE5A,0xA05BFBA0,
+ 0x52A4F652,0x3B764D3B,0xD6B761D6,0xB37DCEB3,0x29527B29,0xE3DD3EE3,0x2F5E712F,0x84139784,
+ 0x53A6F553,0xD1B968D1,0000000000,0xEDC12CED,0x20406020,0xFCE31FFC,0xB179C8B1,0x5BB6ED5B,
+ 0x6AD4BE6A,0xCB8D46CB,0xBE67D9BE,0x39724B39,0x4A94DE4A,0x4C98D44C,0x58B0E858,0xCF854ACF,
+ 0xD0BB6BD0,0xEFC52AEF,0xAA4FE5AA,0xFBED16FB,0x4386C543,0x4D9AD74D,0x33665533,0x85119485,
+ 0x458ACF45,0xF9E910F9,0x02040602,0x7FFE817F,0x50A0F050,0x3C78443C,0x9F25BA9F,0xA84BE3A8,
+ 0x51A2F351,0xA35DFEA3,0x4080C040,0x8F058A8F,0x923FAD92,0x9D21BC9D,0x38704838,0xF5F104F5,
+ 0xBC63DFBC,0xB677C1B6,0xDAAF75DA,0x21426321,0x10203010,0xFFE51AFF,0xF3FD0EF3,0xD2BF6DD2,
+ 0xCD814CCD,0x0C18140C,0x13263513,0xECC32FEC,0x5FBEE15F,0x9735A297,0x4488CC44,0x172E3917,
+ 0xC49357C4,0xA755F2A7,0x7EFC827E,0x3D7A473D,0x64C8AC64,0x5DBAE75D,0x19322B19,0x73E69573,
+ 0x60C0A060,0x81199881,0x4F9ED14F,0xDCA37FDC,0x22446622,0x2A547E2A,0x903BAB90,0x880B8388,
+ 0x468CCA46,0xEEC729EE,0xB86BD3B8,0x14283C14,0xDEA779DE,0x5EBCE25E,0x0B161D0B,0xDBAD76DB,
+ 0xE0DB3BE0,0x32645632,0x3A744E3A,0x0A141E0A,0x4992DB49,0x060C0A06,0x24486C24,0x5CB8E45C,
+ 0xC29F5DC2,0xD3BD6ED3,0xAC43EFAC,0x62C4A662,0x9139A891,0x9531A495,0xE4D337E4,0x79F28B79,
+ 0xE7D532E7,0xC88B43C8,0x376E5937,0x6DDAB76D,0x8D018C8D,0xD5B164D5,0x4E9CD24E,0xA949E0A9,
+ 0x6CD8B46C,0x56ACFA56,0xF4F307F4,0xEACF25EA,0x65CAAF65,0x7AF48E7A,0xAE47E9AE,0x08101808,
+ 0xBA6FD5BA,0x78F08878,0x254A6F25,0x2E5C722E,0x1C38241C,0xA657F1A6,0xB473C7B4,0xC69751C6,
+ 0xE8CB23E8,0xDDA17CDD,0x74E89C74,0x1F3E211F,0x4B96DD4B,0xBD61DCBD,0x8B0D868B,0x8A0F858A,
+ 0x70E09070,0x3E7C423E,0xB571C4B5,0x66CCAA66,0x4890D848,0x03060503,0xF6F701F6,0x0E1C120E,
+ 0x61C2A361,0x356A5F35,0x57AEF957,0xB969D0B9,0x86179186,0xC19958C1,0x1D3A271D,0x9E27B99E,
+ 0xE1D938E1,0xF8EB13F8,0x982BB398,0x11223311,0x69D2BB69,0xD9A970D9,0x8E07898E,0x9433A794,
+ 0x9B2DB69B,0x1E3C221E,0x87159287,0xE9C920E9,0xCE8749CE,0x55AAFF55,0x28507828,0xDFA57ADF,
+ 0x8C038F8C,0xA159F8A1,0x89098089,0x0D1A170D,0xBF65DABF,0xE6D731E6,0x4284C642,0x68D0B868,
+ 0x4182C341,0x9929B099,0x2D5A772D,0x0F1E110F,0xB07BCBB0,0x54A8FC54,0xBB6DD6BB,0x162C3A16 
+ },
+ {
+ 0xC6A56363,0xF8847C7C,0xEE997777,0xF68D7B7B,0xFF0DF2F2,0xD6BD6B6B,0xDEB16F6F,0x9154C5C5,
+ 0x60503030,0x02030101,0xCEA96767,0x567D2B2B,0xE719FEFE,0xB562D7D7,0x4DE6ABAB,0xEC9A7676,
+ 0x8F45CACA,0x1F9D8282,0x8940C9C9,0xFA877D7D,0xEF15FAFA,0xB2EB5959,0x8EC94747,0xFB0BF0F0,
+ 0x41ECADAD,0xB367D4D4,0x5FFDA2A2,0x45EAAFAF,0x23BF9C9C,0x53F7A4A4,0xE4967272,0x9B5BC0C0,
+ 0x75C2B7B7,0xE11CFDFD,0x3DAE9393,0x4C6A2626,0x6C5A3636,0x7E413F3F,0xF502F7F7,0x834FCCCC,
+ 0x685C3434,0x51F4A5A5,0xD134E5E5,0xF908F1F1,0xE2937171,0xAB73D8D8,0x62533131,0x2A3F1515,
+ 0x080C0404,0x9552C7C7,0x46652323,0x9D5EC3C3,0x30281818,0x37A19696,0x0A0F0505,0x2FB59A9A,
+ 0x0E090707,0x24361212,0x1B9B8080,0xDF3DE2E2,0xCD26EBEB,0x4E692727,0x7FCDB2B2,0xEA9F7575,
+ 0x121B0909,0x1D9E8383,0x58742C2C,0x342E1A1A,0x362D1B1B,0xDCB26E6E,0xB4EE5A5A,0x5BFBA0A0,
+ 0xA4F65252,0x764D3B3B,0xB761D6D6,0x7DCEB3B3,0x527B2929,0xDD3EE3E3,0x5E712F2F,0x13978484,
+ 0xA6F55353,0xB968D1D1,0000000000,0xC12CEDED,0x40602020,0xE31FFCFC,0x79C8B1B1,0xB6ED5B5B,
+ 0xD4BE6A6A,0x8D46CBCB,0x67D9BEBE,0x724B3939,0x94DE4A4A,0x98D44C4C,0xB0E85858,0x854ACFCF,
+ 0xBB6BD0D0,0xC52AEFEF,0x4FE5AAAA,0xED16FBFB,0x86C54343,0x9AD74D4D,0x66553333,0x11948585,
+ 0x8ACF4545,0xE910F9F9,0x04060202,0xFE817F7F,0xA0F05050,0x78443C3C,0x25BA9F9F,0x4BE3A8A8,
+ 0xA2F35151,0x5DFEA3A3,0x80C04040,0x058A8F8F,0x3FAD9292,0x21BC9D9D,0x70483838,0xF104F5F5,
+ 0x63DFBCBC,0x77C1B6B6,0xAF75DADA,0x42632121,0x20301010,0xE51AFFFF,0xFD0EF3F3,0xBF6DD2D2,
+ 0x814CCDCD,0x18140C0C,0x26351313,0xC32FECEC,0xBEE15F5F,0x35A29797,0x88CC4444,0x2E391717,
+ 0x9357C4C4,0x55F2A7A7,0xFC827E7E,0x7A473D3D,0xC8AC6464,0xBAE75D5D,0x322B1919,0xE6957373,
+ 0xC0A06060,0x19988181,0x9ED14F4F,0xA37FDCDC,0x44662222,0x547E2A2A,0x3BAB9090,0x0B838888,
+ 0x8CCA4646,0xC729EEEE,0x6BD3B8B8,0x283C1414,0xA779DEDE,0xBCE25E5E,0x161D0B0B,0xAD76DBDB,
+ 0xDB3BE0E0,0x64563232,0x744E3A3A,0x141E0A0A,0x92DB4949,0x0C0A0606,0x486C2424,0xB8E45C5C,
+ 0x9F5DC2C2,0xBD6ED3D3,0x43EFACAC,0xC4A66262,0x39A89191,0x31A49595,0xD337E4E4,0xF28B7979,
+ 0xD532E7E7,0x8B43C8C8,0x6E593737,0xDAB76D6D,0x018C8D8D,0xB164D5D5,0x9CD24E4E,0x49E0A9A9,
+ 0xD8B46C6C,0xACFA5656,0xF307F4F4,0xCF25EAEA,0xCAAF6565,0xF48E7A7A,0x47E9AEAE,0x10180808,
+ 0x6FD5BABA,0xF0887878,0x4A6F2525,0x5C722E2E,0x38241C1C,0x57F1A6A6,0x73C7B4B4,0x9751C6C6,
+ 0xCB23E8E8,0xA17CDDDD,0xE89C7474,0x3E211F1F,0x96DD4B4B,0x61DCBDBD,0x0D868B8B,0x0F858A8A,
+ 0xE0907070,0x7C423E3E,0x71C4B5B5,0xCCAA6666,0x90D84848,0x06050303,0xF701F6F6,0x1C120E0E,
+ 0xC2A36161,0x6A5F3535,0xAEF95757,0x69D0B9B9,0x17918686,0x9958C1C1,0x3A271D1D,0x27B99E9E,
+ 0xD938E1E1,0xEB13F8F8,0x2BB39898,0x22331111,0xD2BB6969,0xA970D9D9,0x07898E8E,0x33A79494,
+ 0x2DB69B9B,0x3C221E1E,0x15928787,0xC920E9E9,0x8749CECE,0xAAFF5555,0x50782828,0xA57ADFDF,
+ 0x038F8C8C,0x59F8A1A1,0x09808989,0x1A170D0D,0x65DABFBF,0xD731E6E6,0x84C64242,0xD0B86868,
+ 0x82C34141,0x29B09999,0x5A772D2D,0x1E110F0F,0x7BCBB0B0,0xA8FC5454,0x6DD6BBBB,0x2C3A1616 
+ } 
+};
+
+static u32 fl_tab[4][256] = 
+{
+ {
+ 0x00000063,0x0000007C,0x00000077,0x0000007B,0x000000F2,0x0000006B,0x0000006F,0x000000C5,
+ 0x00000030,0x00000001,0x00000067,0x0000002B,0x000000FE,0x000000D7,0x000000AB,0x00000076,
+ 0x000000CA,0x00000082,0x000000C9,0x0000007D,0x000000FA,0x00000059,0x00000047,0x000000F0,
+ 0x000000AD,0x000000D4,0x000000A2,0x000000AF,0x0000009C,0x000000A4,0x00000072,0x000000C0,
+ 0x000000B7,0x000000FD,0x00000093,0x00000026,0x00000036,0x0000003F,0x000000F7,0x000000CC,
+ 0x00000034,0x000000A5,0x000000E5,0x000000F1,0x00000071,0x000000D8,0x00000031,0x00000015,
+ 0x00000004,0x000000C7,0x00000023,0x000000C3,0x00000018,0x00000096,0x00000005,0x0000009A,
+ 0x00000007,0x00000012,0x00000080,0x000000E2,0x000000EB,0x00000027,0x000000B2,0x00000075,
+ 0x00000009,0x00000083,0x0000002C,0x0000001A,0x0000001B,0x0000006E,0x0000005A,0x000000A0,
+ 0x00000052,0x0000003B,0x000000D6,0x000000B3,0x00000029,0x000000E3,0x0000002F,0x00000084,
+ 0x00000053,0x000000D1,0x00000000,0x000000ED,0x00000020,0x000000FC,0x000000B1,0x0000005B,
+ 0x0000006A,0x000000CB,0x000000BE,0x00000039,0x0000004A,0x0000004C,0x00000058,0x000000CF,
+ 0x000000D0,0x000000EF,0x000000AA,0x000000FB,0x00000043,0x0000004D,0x00000033,0x00000085,
+ 0x00000045,0x000000F9,0x00000002,0x0000007F,0x00000050,0x0000003C,0x0000009F,0x000000A8,
+ 0x00000051,0x000000A3,0x00000040,0x0000008F,0x00000092,0x0000009D,0x00000038,0x000000F5,
+ 0x000000BC,0x000000B6,0x000000DA,0x00000021,0x00000010,0x000000FF,0x000000F3,0x000000D2,
+ 0x000000CD,0x0000000C,0x00000013,0x000000EC,0x0000005F,0x00000097,0x00000044,0x00000017,
+ 0x000000C4,0x000000A7,0x0000007E,0x0000003D,0x00000064,0x0000005D,0x00000019,0x00000073,
+ 0x00000060,0x00000081,0x0000004F,0x000000DC,0x00000022,0x0000002A,0x00000090,0x00000088,
+ 0x00000046,0x000000EE,0x000000B8,0x00000014,0x000000DE,0x0000005E,0x0000000B,0x000000DB,
+ 0x000000E0,0x00000032,0x0000003A,0x0000000A,0x00000049,0x00000006,0x00000024,0x0000005C,
+ 0x000000C2,0x000000D3,0x000000AC,0x00000062,0x00000091,0x00000095,0x000000E4,0x00000079,
+ 0x000000E7,0x000000C8,0x00000037,0x0000006D,0x0000008D,0x000000D5,0x0000004E,0x000000A9,
+ 0x0000006C,0x00000056,0x000000F4,0x000000EA,0x00000065,0x0000007A,0x000000AE,0x00000008,
+ 0x000000BA,0x00000078,0x00000025,0x0000002E,0x0000001C,0x000000A6,0x000000B4,0x000000C6,
+ 0x000000E8,0x000000DD,0x00000074,0x0000001F,0x0000004B,0x000000BD,0x0000008B,0x0000008A,
+ 0x00000070,0x0000003E,0x000000B5,0x00000066,0x00000048,0x00000003,0x000000F6,0x0000000E,
+ 0x00000061,0x00000035,0x00000057,0x000000B9,0x00000086,0x000000C1,0x0000001D,0x0000009E,
+ 0x000000E1,0x000000F8,0x00000098,0x00000011,0x00000069,0x000000D9,0x0000008E,0x00000094,
+ 0x0000009B,0x0000001E,0x00000087,0x000000E9,0x000000CE,0x00000055,0x00000028,0x000000DF,
+ 0x0000008C,0x000000A1,0x00000089,0x0000000D,0x000000BF,0x000000E6,0x00000042,0x00000068,
+ 0x00000041,0x00000099,0x0000002D,0x0000000F,0x000000B0,0x00000054,0x000000BB,0x00000016 
+ },
+ {
+ 0x00006300,0x00007C00,0x00007700,0x00007B00,0x0000F200,0x00006B00,0x00006F00,0x0000C500,
+ 0x00003000,0x00000100,0x00006700,0x00002B00,0x0000FE00,0x0000D700,0x0000AB00,0x00007600,
+ 0x0000CA00,0x00008200,0x0000C900,0x00007D00,0x0000FA00,0x00005900,0x00004700,0x0000F000,
+ 0x0000AD00,0x0000D400,0x0000A200,0x0000AF00,0x00009C00,0x0000A400,0x00007200,0x0000C000,
+ 0x0000B700,0x0000FD00,0x00009300,0x00002600,0x00003600,0x00003F00,0x0000F700,0x0000CC00,
+ 0x00003400,0x0000A500,0x0000E500,0x0000F100,0x00007100,0x0000D800,0x00003100,0x00001500,
+ 0x00000400,0x0000C700,0x00002300,0x0000C300,0x00001800,0x00009600,0x00000500,0x00009A00,
+ 0x00000700,0x00001200,0x00008000,0x0000E200,0x0000EB00,0x00002700,0x0000B200,0x00007500,
+ 0x00000900,0x00008300,0x00002C00,0x00001A00,0x00001B00,0x00006E00,0x00005A00,0x0000A000,
+ 0x00005200,0x00003B00,0x0000D600,0x0000B300,0x00002900,0x0000E300,0x00002F00,0x00008400,
+ 0x00005300,0x0000D100,0000000000,0x0000ED00,0x00002000,0x0000FC00,0x0000B100,0x00005B00,
+ 0x00006A00,0x0000CB00,0x0000BE00,0x00003900,0x00004A00,0x00004C00,0x00005800,0x0000CF00,
+ 0x0000D000,0x0000EF00,0x0000AA00,0x0000FB00,0x00004300,0x00004D00,0x00003300,0x00008500,
+ 0x00004500,0x0000F900,0x00000200,0x00007F00,0x00005000,0x00003C00,0x00009F00,0x0000A800,
+ 0x00005100,0x0000A300,0x00004000,0x00008F00,0x00009200,0x00009D00,0x00003800,0x0000F500,
+ 0x0000BC00,0x0000B600,0x0000DA00,0x00002100,0x00001000,0x0000FF00,0x0000F300,0x0000D200,
+ 0x0000CD00,0x00000C00,0x00001300,0x0000EC00,0x00005F00,0x00009700,0x00004400,0x00001700,
+ 0x0000C400,0x0000A700,0x00007E00,0x00003D00,0x00006400,0x00005D00,0x00001900,0x00007300,
+ 0x00006000,0x00008100,0x00004F00,0x0000DC00,0x00002200,0x00002A00,0x00009000,0x00008800,
+ 0x00004600,0x0000EE00,0x0000B800,0x00001400,0x0000DE00,0x00005E00,0x00000B00,0x0000DB00,
+ 0x0000E000,0x00003200,0x00003A00,0x00000A00,0x00004900,0x00000600,0x00002400,0x00005C00,
+ 0x0000C200,0x0000D300,0x0000AC00,0x00006200,0x00009100,0x00009500,0x0000E400,0x00007900,
+ 0x0000E700,0x0000C800,0x00003700,0x00006D00,0x00008D00,0x0000D500,0x00004E00,0x0000A900,
+ 0x00006C00,0x00005600,0x0000F400,0x0000EA00,0x00006500,0x00007A00,0x0000AE00,0x00000800,
+ 0x0000BA00,0x00007800,0x00002500,0x00002E00,0x00001C00,0x0000A600,0x0000B400,0x0000C600,
+ 0x0000E800,0x0000DD00,0x00007400,0x00001F00,0x00004B00,0x0000BD00,0x00008B00,0x00008A00,
+ 0x00007000,0x00003E00,0x0000B500,0x00006600,0x00004800,0x00000300,0x0000F600,0x00000E00,
+ 0x00006100,0x00003500,0x00005700,0x0000B900,0x00008600,0x0000C100,0x00001D00,0x00009E00,
+ 0x0000E100,0x0000F800,0x00009800,0x00001100,0x00006900,0x0000D900,0x00008E00,0x00009400,
+ 0x00009B00,0x00001E00,0x00008700,0x0000E900,0x0000CE00,0x00005500,0x00002800,0x0000DF00,
+ 0x00008C00,0x0000A100,0x00008900,0x00000D00,0x0000BF00,0x0000E600,0x00004200,0x00006800,
+ 0x00004100,0x00009900,0x00002D00,0x00000F00,0x0000B000,0x00005400,0x0000BB00,0x00001600 
+ },
+ {
+ 0x00630000,0x007C0000,0x00770000,0x007B0000,0x00F20000,0x006B0000,0x006F0000,0x00C50000,
+ 0x00300000,0x00010000,0x00670000,0x002B0000,0x00FE0000,0x00D70000,0x00AB0000,0x00760000,
+ 0x00CA0000,0x00820000,0x00C90000,0x007D0000,0x00FA0000,0x00590000,0x00470000,0x00F00000,
+ 0x00AD0000,0x00D40000,0x00A20000,0x00AF0000,0x009C0000,0x00A40000,0x00720000,0x00C00000,
+ 0x00B70000,0x00FD0000,0x00930000,0x00260000,0x00360000,0x003F0000,0x00F70000,0x00CC0000,
+ 0x00340000,0x00A50000,0x00E50000,0x00F10000,0x00710000,0x00D80000,0x00310000,0x00150000,
+ 0x00040000,0x00C70000,0x00230000,0x00C30000,0x00180000,0x00960000,0x00050000,0x009A0000,
+ 0x00070000,0x00120000,0x00800000,0x00E20000,0x00EB0000,0x00270000,0x00B20000,0x00750000,
+ 0x00090000,0x00830000,0x002C0000,0x001A0000,0x001B0000,0x006E0000,0x005A0000,0x00A00000,
+ 0x00520000,0x003B0000,0x00D60000,0x00B30000,0x00290000,0x00E30000,0x002F0000,0x00840000,
+ 0x00530000,0x00D10000,0000000000,0x00ED0000,0x00200000,0x00FC0000,0x00B10000,0x005B0000,
+ 0x006A0000,0x00CB0000,0x00BE0000,0x00390000,0x004A0000,0x004C0000,0x00580000,0x00CF0000,
+ 0x00D00000,0x00EF0000,0x00AA0000,0x00FB0000,0x00430000,0x004D0000,0x00330000,0x00850000,
+ 0x00450000,0x00F90000,0x00020000,0x007F0000,0x00500000,0x003C0000,0x009F0000,0x00A80000,
+ 0x00510000,0x00A30000,0x00400000,0x008F0000,0x00920000,0x009D0000,0x00380000,0x00F50000,
+ 0x00BC0000,0x00B60000,0x00DA0000,0x00210000,0x00100000,0x00FF0000,0x00F30000,0x00D20000,
+ 0x00CD0000,0x000C0000,0x00130000,0x00EC0000,0x005F0000,0x00970000,0x00440000,0x00170000,
+ 0x00C40000,0x00A70000,0x007E0000,0x003D0000,0x00640000,0x005D0000,0x00190000,0x00730000,
+ 0x00600000,0x00810000,0x004F0000,0x00DC0000,0x00220000,0x002A0000,0x00900000,0x00880000,
+ 0x00460000,0x00EE0000,0x00B80000,0x00140000,0x00DE0000,0x005E0000,0x000B0000,0x00DB0000,
+ 0x00E00000,0x00320000,0x003A0000,0x000A0000,0x00490000,0x00060000,0x00240000,0x005C0000,
+ 0x00C20000,0x00D30000,0x00AC0000,0x00620000,0x00910000,0x00950000,0x00E40000,0x00790000,
+ 0x00E70000,0x00C80000,0x00370000,0x006D0000,0x008D0000,0x00D50000,0x004E0000,0x00A90000,
+ 0x006C0000,0x00560000,0x00F40000,0x00EA0000,0x00650000,0x007A0000,0x00AE0000,0x00080000,
+ 0x00BA0000,0x00780000,0x00250000,0x002E0000,0x001C0000,0x00A60000,0x00B40000,0x00C60000,
+ 0x00E80000,0x00DD0000,0x00740000,0x001F0000,0x004B0000,0x00BD0000,0x008B0000,0x008A0000,
+ 0x00700000,0x003E0000,0x00B50000,0x00660000,0x00480000,0x00030000,0x00F60000,0x000E0000,
+ 0x00610000,0x00350000,0x00570000,0x00B90000,0x00860000,0x00C10000,0x001D0000,0x009E0000,
+ 0x00E10000,0x00F80000,0x00980000,0x00110000,0x00690000,0x00D90000,0x008E0000,0x00940000,
+ 0x009B0000,0x001E0000,0x00870000,0x00E90000,0x00CE0000,0x00550000,0x00280000,0x00DF0000,
+ 0x008C0000,0x00A10000,0x00890000,0x000D0000,0x00BF0000,0x00E60000,0x00420000,0x00680000,
+ 0x00410000,0x00990000,0x002D0000,0x000F0000,0x00B00000,0x00540000,0x00BB0000,0x00160000 
+ },
+ {
+ 0x63000000,0x7C000000,0x77000000,0x7B000000,0xF2000000,0x6B000000,0x6F000000,0xC5000000,
+ 0x30000000,0x01000000,0x67000000,0x2B000000,0xFE000000,0xD7000000,0xAB000000,0x76000000,
+ 0xCA000000,0x82000000,0xC9000000,0x7D000000,0xFA000000,0x59000000,0x47000000,0xF0000000,
+ 0xAD000000,0xD4000000,0xA2000000,0xAF000000,0x9C000000,0xA4000000,0x72000000,0xC0000000,
+ 0xB7000000,0xFD000000,0x93000000,0x26000000,0x36000000,0x3F000000,0xF7000000,0xCC000000,
+ 0x34000000,0xA5000000,0xE5000000,0xF1000000,0x71000000,0xD8000000,0x31000000,0x15000000,
+ 0x04000000,0xC7000000,0x23000000,0xC3000000,0x18000000,0x96000000,0x05000000,0x9A000000,
+ 0x07000000,0x12000000,0x80000000,0xE2000000,0xEB000000,0x27000000,0xB2000000,0x75000000,
+ 0x09000000,0x83000000,0x2C000000,0x1A000000,0x1B000000,0x6E000000,0x5A000000,0xA0000000,
+ 0x52000000,0x3B000000,0xD6000000,0xB3000000,0x29000000,0xE3000000,0x2F000000,0x84000000,
+ 0x53000000,0xD1000000,0000000000,0xED000000,0x20000000,0xFC000000,0xB1000000,0x5B000000,
+ 0x6A000000,0xCB000000,0xBE000000,0x39000000,0x4A000000,0x4C000000,0x58000000,0xCF000000,
+ 0xD0000000,0xEF000000,0xAA000000,0xFB000000,0x43000000,0x4D000000,0x33000000,0x85000000,
+ 0x45000000,0xF9000000,0x02000000,0x7F000000,0x50000000,0x3C000000,0x9F000000,0xA8000000,
+ 0x51000000,0xA3000000,0x40000000,0x8F000000,0x92000000,0x9D000000,0x38000000,0xF5000000,
+ 0xBC000000,0xB6000000,0xDA000000,0x21000000,0x10000000,0xFF000000,0xF3000000,0xD2000000,
+ 0xCD000000,0x0C000000,0x13000000,0xEC000000,0x5F000000,0x97000000,0x44000000,0x17000000,
+ 0xC4000000,0xA7000000,0x7E000000,0x3D000000,0x64000000,0x5D000000,0x19000000,0x73000000,
+ 0x60000000,0x81000000,0x4F000000,0xDC000000,0x22000000,0x2A000000,0x90000000,0x88000000,
+ 0x46000000,0xEE000000,0xB8000000,0x14000000,0xDE000000,0x5E000000,0x0B000000,0xDB000000,
+ 0xE0000000,0x32000000,0x3A000000,0x0A000000,0x49000000,0x06000000,0x24000000,0x5C000000,
+ 0xC2000000,0xD3000000,0xAC000000,0x62000000,0x91000000,0x95000000,0xE4000000,0x79000000,
+ 0xE7000000,0xC8000000,0x37000000,0x6D000000,0x8D000000,0xD5000000,0x4E000000,0xA9000000,
+ 0x6C000000,0x56000000,0xF4000000,0xEA000000,0x65000000,0x7A000000,0xAE000000,0x08000000,
+ 0xBA000000,0x78000000,0x25000000,0x2E000000,0x1C000000,0xA6000000,0xB4000000,0xC6000000,
+ 0xE8000000,0xDD000000,0x74000000,0x1F000000,0x4B000000,0xBD000000,0x8B000000,0x8A000000,
+ 0x70000000,0x3E000000,0xB5000000,0x66000000,0x48000000,0x03000000,0xF6000000,0x0E000000,
+ 0x61000000,0x35000000,0x57000000,0xB9000000,0x86000000,0xC1000000,0x1D000000,0x9E000000,
+ 0xE1000000,0xF8000000,0x98000000,0x11000000,0x69000000,0xD9000000,0x8E000000,0x94000000,
+ 0x9B000000,0x1E000000,0x87000000,0xE9000000,0xCE000000,0x55000000,0x28000000,0xDF000000,
+ 0x8C000000,0xA1000000,0x89000000,0x0D000000,0xBF000000,0xE6000000,0x42000000,0x68000000,
+ 0x41000000,0x99000000,0x2D000000,0x0F000000,0xB0000000,0x54000000,0xBB000000,0x16000000 
+ } 
+};
+
+/*----------------- The workspace ------------------------------*/
+
+static u32 Ekey[44];	/* The expanded key */
+
+/*------ The round Function.  4 table lookups and 4 Exors ------*/
+#define f_rnd(x, n)                     \
+  ( ft_tab[0][byte0(x[n])]              \
+  ^ ft_tab[1][byte1(x[(n + 1) & 3])]    \
+  ^ ft_tab[2][byte2(x[(n + 2) & 3])]    \
+  ^ ft_tab[3][byte3(x[(n + 3) & 3])] )
+
+#define f_round(bo, bi, k)          \
+    bo[0] = f_rnd(bi, 0) ^ k[0];    \
+    bo[1] = f_rnd(bi, 1) ^ k[1];    \
+    bo[2] = f_rnd(bi, 2) ^ k[2];    \
+    bo[3] = f_rnd(bi, 3) ^ k[3];    \
+    k += 4
+
+/*--- The S Box lookup used in constructing the Key schedule ---*/
+#define ls_box(x)       \
+ (  fl_tab[0][byte0(x)] \
+  ^ fl_tab[1][byte1(x)] \
+  ^ fl_tab[2][byte2(x)] \
+  ^ fl_tab[3][byte3(x)] )
+
+/*------------ The last round function (no MixColumn) ----------*/
+#define lf_rnd(x, n)                    \
+  ( fl_tab[0][byte0(x[n])]              \
+  ^ fl_tab[1][byte1(x[(n + 1) & 3])]    \
+  ^ fl_tab[2][byte2(x[(n + 2) & 3])]    \
+  ^ fl_tab[3][byte3(x[(n + 3) & 3])] )
+
+
+/*-----------------------------------------------------------
+ * RijndaelKeySchedule
+ *   Initialise the key schedule from a supplied key
+ */
+void RijndaelKeySchedule(u8 key[16])
+{
+    u32  t;
+    u32  *ek=Ekey,	    /* pointer to the expanded key   */
+         *rc=rnd_con;   /* pointer to the round constant */
+
+    Ekey[0] = u32_in(key     );
+    Ekey[1] = u32_in(key +  4);
+    Ekey[2] = u32_in(key +  8);
+    Ekey[3] = u32_in(key + 12);
+
+	while(ek < Ekey + 40)
+    {
+		t = rot3(ek[3]);
+        ek[4] = ek[0] ^ ls_box(t) ^ *rc++;
+        ek[5] = ek[1] ^ ek[4];
+        ek[6] = ek[2] ^ ek[5];
+        ek[7] = ek[3] ^ ek[6];
+        ek += 4;
+    }
+}
+
+/*-----------------------------------------------------------
+ * RijndaelEncrypt
+ *   Encrypt an input block
+ */
+void RijndaelEncrypt(u8 in[16], u8 out[16])
+{
+    u32    b0[4], b1[4], *kp = Ekey;
+
+    b0[0] = u32_in(in     ) ^ *kp++;
+    b0[1] = u32_in(in +  4) ^ *kp++;
+    b0[2] = u32_in(in +  8) ^ *kp++;
+    b0[3] = u32_in(in + 12) ^ *kp++;
+
+    f_round(b1, b0, kp); 
+    f_round(b0, b1, kp);
+    f_round(b1, b0, kp); 
+    f_round(b0, b1, kp);
+    f_round(b1, b0, kp); 
+    f_round(b0, b1, kp);
+    f_round(b1, b0, kp); 
+    f_round(b0, b1, kp);
+    f_round(b1, b0, kp); 
+
+    u32_out(out,      lf_rnd(b1, 0) ^ kp[0]); 
+    u32_out(out +  4, lf_rnd(b1, 1) ^ kp[1]);
+    u32_out(out +  8, lf_rnd(b1, 2) ^ kp[2]); 
+    u32_out(out + 12, lf_rnd(b1, 3) ^ kp[3]);
+}
diff --git a/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/milenage/rijndael.h b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/milenage/rijndael.h
new file mode 100644
index 0000000..4e728a5
--- /dev/null
+++ b/daemon/contrib/tarballs-unpacked/pjproject-2.4.5.tar.bz2/pjproject-2.4.5/third_party/milenage/rijndael.h
@@ -0,0 +1,26 @@
+/*-------------------------------------------------------------------
+ *          Example algorithms f1, f1*, f2, f3, f4, f5, f5*
+ *-------------------------------------------------------------------
+ *
+ *  A sample implementation of the example 3GPP authentication and
+ *  key agreement functions f1, f1*, f2, f3, f4, f5 and f5*.  This is
+ *  a byte-oriented implementation of the functions, and of the block
+ *  cipher kernel function Rijndael.
+ *
+ *  This has been coded for clarity, not necessarily for efficiency.
+ *
+ *  The functions f2, f3, f4 and f5 share the same inputs and have
+ *  been coded together as a single function.  f1, f1* and f5* are
+ *  all coded separately.
+ *
+ *-----------------------------------------------------------------*/
+
+#ifndef RIJNDAEL_H
+#define RIJNDAEL_H
+
+
+void RijndaelKeySchedule( u8 key[16] );
+void RijndaelEncrypt( u8 input[16], u8 output[16] );
+
+
+#endif

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-voip/ring.git



More information about the Pkg-voip-commits mailing list