From 7873aff384696ef64669c51d0b5457d206536a28 Mon Sep 17 00:00:00 2001 From: Liong Sauw Ming Date: Thu, 19 Apr 2012 06:36:57 +0000 Subject: Re #1276: Integrate BaseClasses with the project and remove unnecessary classes git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@4062 74dad513-b988-da41-8d7b-12977e46ad98 --- third_party/BaseClasses/amextra.cpp | 111 -- third_party/BaseClasses/amextra.h | 56 - third_party/BaseClasses/baseclasses.sln | 38 - third_party/BaseClasses/baseclasses.vcproj | 574 +----- third_party/BaseClasses/cache.h | 74 - third_party/BaseClasses/checkbmi.h | 120 -- third_party/BaseClasses/cprop.cpp | 383 ---- third_party/BaseClasses/cprop.h | 95 - third_party/BaseClasses/ddmm.cpp | 129 -- third_party/BaseClasses/ddmm.h | 28 - third_party/BaseClasses/dllentry.cpp | 367 ---- third_party/BaseClasses/dllsetup.cpp | 693 ------- third_party/BaseClasses/dllsetup.h | 46 - third_party/BaseClasses/dxmperf.h | 250 --- third_party/BaseClasses/outputq.cpp | 801 -------- third_party/BaseClasses/outputq.h | 137 -- third_party/BaseClasses/perflog.cpp | 347 ---- third_party/BaseClasses/perflog.h | 56 - third_party/BaseClasses/perfstruct.h | 194 -- third_party/BaseClasses/pstream.cpp | 197 -- third_party/BaseClasses/pstream.h | 114 -- third_party/BaseClasses/pullpin.cpp | 588 ------ third_party/BaseClasses/pullpin.h | 152 -- third_party/BaseClasses/refclock.cpp | 402 ---- third_party/BaseClasses/schedule.cpp | 284 --- third_party/BaseClasses/schedule.h | 128 -- third_party/BaseClasses/seekpt.cpp | 83 - third_party/BaseClasses/source.cpp | 522 ------ third_party/BaseClasses/source.h | 172 -- third_party/BaseClasses/streams.h | 40 +- third_party/BaseClasses/strmctl.cpp | 402 ---- third_party/BaseClasses/strmctl.h | 157 -- third_party/BaseClasses/sysclock.cpp | 74 - third_party/BaseClasses/sysclock.h | 39 - third_party/BaseClasses/transfrm.cpp | 1016 ---------- third_party/BaseClasses/transfrm.h | 304 --- third_party/BaseClasses/transip.cpp | 974 ---------- third_party/BaseClasses/transip.h | 250 --- third_party/BaseClasses/videoctl.cpp | 746 -------- third_party/BaseClasses/videoctl.h | 168 -- third_party/BaseClasses/vtrans.cpp | 468 ----- third_party/BaseClasses/vtrans.h | 143 -- third_party/BaseClasses/winctrl.cpp | 2081 --------------------- third_party/BaseClasses/winctrl.h | 224 --- third_party/BaseClasses/winutil.cpp | 2746 ---------------------------- third_party/BaseClasses/winutil.h | 419 ----- 46 files changed, 115 insertions(+), 17277 deletions(-) delete mode 100644 third_party/BaseClasses/amextra.cpp delete mode 100644 third_party/BaseClasses/amextra.h delete mode 100644 third_party/BaseClasses/baseclasses.sln delete mode 100644 third_party/BaseClasses/cache.h delete mode 100644 third_party/BaseClasses/checkbmi.h delete mode 100644 third_party/BaseClasses/cprop.cpp delete mode 100644 third_party/BaseClasses/cprop.h delete mode 100644 third_party/BaseClasses/ddmm.cpp delete mode 100644 third_party/BaseClasses/ddmm.h delete mode 100644 third_party/BaseClasses/dllentry.cpp delete mode 100644 third_party/BaseClasses/dllsetup.cpp delete mode 100644 third_party/BaseClasses/dllsetup.h delete mode 100644 third_party/BaseClasses/dxmperf.h delete mode 100644 third_party/BaseClasses/outputq.cpp delete mode 100644 third_party/BaseClasses/outputq.h delete mode 100644 third_party/BaseClasses/perflog.cpp delete mode 100644 third_party/BaseClasses/perflog.h delete mode 100644 third_party/BaseClasses/perfstruct.h delete mode 100644 third_party/BaseClasses/pstream.cpp delete mode 100644 third_party/BaseClasses/pstream.h delete mode 100644 third_party/BaseClasses/pullpin.cpp delete mode 100644 third_party/BaseClasses/pullpin.h delete mode 100644 third_party/BaseClasses/refclock.cpp delete mode 100644 third_party/BaseClasses/schedule.cpp delete mode 100644 third_party/BaseClasses/schedule.h delete mode 100644 third_party/BaseClasses/seekpt.cpp delete mode 100644 third_party/BaseClasses/source.cpp delete mode 100644 third_party/BaseClasses/source.h delete mode 100644 third_party/BaseClasses/strmctl.cpp delete mode 100644 third_party/BaseClasses/strmctl.h delete mode 100644 third_party/BaseClasses/sysclock.cpp delete mode 100644 third_party/BaseClasses/sysclock.h delete mode 100644 third_party/BaseClasses/transfrm.cpp delete mode 100644 third_party/BaseClasses/transfrm.h delete mode 100644 third_party/BaseClasses/transip.cpp delete mode 100644 third_party/BaseClasses/transip.h delete mode 100644 third_party/BaseClasses/videoctl.cpp delete mode 100644 third_party/BaseClasses/videoctl.h delete mode 100644 third_party/BaseClasses/vtrans.cpp delete mode 100644 third_party/BaseClasses/vtrans.h delete mode 100644 third_party/BaseClasses/winctrl.cpp delete mode 100644 third_party/BaseClasses/winctrl.h delete mode 100644 third_party/BaseClasses/winutil.cpp delete mode 100644 third_party/BaseClasses/winutil.h (limited to 'third_party') diff --git a/third_party/BaseClasses/amextra.cpp b/third_party/BaseClasses/amextra.cpp deleted file mode 100644 index af0de96d..00000000 --- a/third_party/BaseClasses/amextra.cpp +++ /dev/null @@ -1,111 +0,0 @@ -//------------------------------------------------------------------------------ -// File: AMExtra.cpp -// -// Desc: DirectShow base classes - implements CRenderedInputPin class. -// -// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. -//------------------------------------------------------------------------------ - - -#include // DirectShow base class definitions -#include // Needed for definition of timeGetTime -#include // Standard data type limit definitions -#include // Used for time critical log functions - -#include "amextra.h" - -#pragma warning(disable:4355) - -// Implements CRenderedInputPin class - -CRenderedInputPin::CRenderedInputPin(__in_opt LPCTSTR pObjectName, - __in CBaseFilter *pFilter, - __in CCritSec *pLock, - __inout HRESULT *phr, - __in_opt LPCWSTR pName) : - CBaseInputPin(pObjectName, pFilter, pLock, phr, pName), - m_bAtEndOfStream(FALSE), - m_bCompleteNotified(FALSE) -{ -} -#ifdef UNICODE -CRenderedInputPin::CRenderedInputPin(__in_opt LPCSTR pObjectName, - __in CBaseFilter *pFilter, - __in CCritSec *pLock, - __inout HRESULT *phr, - __in_opt LPCWSTR pName) : - CBaseInputPin(pObjectName, pFilter, pLock, phr, pName), - m_bAtEndOfStream(FALSE), - m_bCompleteNotified(FALSE) -{ -} -#endif - -// Flush end of stream condition - caller should do any -// necessary stream level locking before calling this - -STDMETHODIMP CRenderedInputPin::EndOfStream() -{ - HRESULT hr = CheckStreaming(); - - // Do EC_COMPLETE handling for rendered pins - if (S_OK == hr && !m_bAtEndOfStream) { - m_bAtEndOfStream = TRUE; - FILTER_STATE fs; - EXECUTE_ASSERT(SUCCEEDED(m_pFilter->GetState(0, &fs))); - if (fs == State_Running) { - DoCompleteHandling(); - } - } - return hr; -} - - -// Called to complete the flush - -STDMETHODIMP CRenderedInputPin::EndFlush() -{ - CAutoLock lck(m_pLock); - - // Clean up renderer state - m_bAtEndOfStream = FALSE; - m_bCompleteNotified = FALSE; - - return CBaseInputPin::EndFlush(); -} - - -// Notify of Run() from filter - -HRESULT CRenderedInputPin::Run(REFERENCE_TIME tStart) -{ - UNREFERENCED_PARAMETER(tStart); - m_bCompleteNotified = FALSE; - if (m_bAtEndOfStream) { - DoCompleteHandling(); - } - return S_OK; -} - - -// Clear status on going into paused state - -HRESULT CRenderedInputPin::Active() -{ - m_bAtEndOfStream = FALSE; - m_bCompleteNotified = FALSE; - return CBaseInputPin::Active(); -} - - -// Do stuff to deliver end of stream - -void CRenderedInputPin::DoCompleteHandling() -{ - ASSERT(m_bAtEndOfStream); - if (!m_bCompleteNotified) { - m_bCompleteNotified = TRUE; - m_pFilter->NotifyEvent(EC_COMPLETE, S_OK, (LONG_PTR)(IBaseFilter *)m_pFilter); - } -} - diff --git a/third_party/BaseClasses/amextra.h b/third_party/BaseClasses/amextra.h deleted file mode 100644 index 5a861bf1..00000000 --- a/third_party/BaseClasses/amextra.h +++ /dev/null @@ -1,56 +0,0 @@ -//------------------------------------------------------------------------------ -// File: AMExtra.h -// -// Desc: DirectShow base classes. -// -// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. -//------------------------------------------------------------------------------ - - -#ifndef __AMEXTRA__ -#define __AMEXTRA__ - -// Simple rendered input pin -// -// NOTE if your filter queues stuff before rendering then it may not be -// appropriate to use this class -// -// In that case queue the end of stream condition until the last sample -// is actually rendered and flush the condition appropriately - -class CRenderedInputPin : public CBaseInputPin -{ -public: - - CRenderedInputPin(__in_opt LPCTSTR pObjectName, - __in CBaseFilter *pFilter, - __in CCritSec *pLock, - __inout HRESULT *phr, - __in_opt LPCWSTR pName); -#ifdef UNICODE - CRenderedInputPin(__in_opt LPCSTR pObjectName, - __in CBaseFilter *pFilter, - __in CCritSec *pLock, - __inout HRESULT *phr, - __in_opt LPCWSTR pName); -#endif - - // Override methods to track end of stream state - STDMETHODIMP EndOfStream(); - STDMETHODIMP EndFlush(); - - HRESULT Active(); - HRESULT Run(REFERENCE_TIME tStart); - -protected: - - // Member variables to track state - BOOL m_bAtEndOfStream; // Set by EndOfStream - BOOL m_bCompleteNotified; // Set when we notify for EC_COMPLETE - -private: - void DoCompleteHandling(); -}; - -#endif // __AMEXTRA__ - diff --git a/third_party/BaseClasses/baseclasses.sln b/third_party/BaseClasses/baseclasses.sln deleted file mode 100644 index a93b581e..00000000 --- a/third_party/BaseClasses/baseclasses.sln +++ /dev/null @@ -1,38 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual Studio 2005 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BaseClasses", "BaseClasses.vcproj", "{E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug_MBCS|Win32 = Debug_MBCS|Win32 - Debug_MBCS|x64 = Debug_MBCS|x64 - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release_MBCS|Win32 = Release_MBCS|Win32 - Release_MBCS|x64 = Release_MBCS|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug_MBCS|Win32.ActiveCfg = Debug_MBCS|Win32 - {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug_MBCS|Win32.Build.0 = Debug_MBCS|Win32 - {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug_MBCS|x64.ActiveCfg = Debug_MBCS|x64 - {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug_MBCS|x64.Build.0 = Debug_MBCS|x64 - {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug|Win32.ActiveCfg = Debug|Win32 - {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug|Win32.Build.0 = Debug|Win32 - {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug|x64.ActiveCfg = Debug|x64 - {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug|x64.Build.0 = Debug|x64 - {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release_MBCS|Win32.ActiveCfg = Release_MBCS|Win32 - {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release_MBCS|Win32.Build.0 = Release_MBCS|Win32 - {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release_MBCS|x64.ActiveCfg = Release_MBCS|x64 - {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release_MBCS|x64.Build.0 = Release_MBCS|x64 - {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release|Win32.ActiveCfg = Release|Win32 - {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release|Win32.Build.0 = Release|Win32 - {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release|x64.ActiveCfg = Release|x64 - {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/third_party/BaseClasses/baseclasses.vcproj b/third_party/BaseClasses/baseclasses.vcproj index 32373bad..1d310856 100644 --- a/third_party/BaseClasses/baseclasses.vcproj +++ b/third_party/BaseClasses/baseclasses.vcproj @@ -4,152 +4,23 @@ Version="8.00" Name="BaseClasses" ProjectGUID="{E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}" - RootNamespace="BaseClasses" - Keyword="Win32Proj" > - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -559,98 +346,18 @@ RelativePath=".\combase.cpp" > - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -666,45 +373,20 @@ - - - - - - - - - - - - @@ -721,26 +403,6 @@ RelativePath=".\mtype.h" > - - - - - - - - - - @@ -753,54 +415,14 @@ RelativePath=".\renbase.h" > - - - - - - - - - - - - - - - - - - - - @@ -814,12 +436,6 @@ > - - diff --git a/third_party/BaseClasses/cache.h b/third_party/BaseClasses/cache.h deleted file mode 100644 index 0a807c27..00000000 --- a/third_party/BaseClasses/cache.h +++ /dev/null @@ -1,74 +0,0 @@ -//------------------------------------------------------------------------------ -// File: Cache.h -// -// Desc: DirectShow base classes - efines a non-MFC generic cache class. -// -// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. -//------------------------------------------------------------------------------ - - -/* This class implements a simple cache. A cache object is instantiated - with the number of items it is to hold. An item is a pointer to an - object derived from CBaseObject (helps reduce memory leaks). The cache - can then have objects added to it and removed from it. The cache size - is fixed at construction time and may therefore run out or be flooded. - If it runs out it returns a NULL pointer, if it fills up it also returns - a NULL pointer instead of a pointer to the object just inserted */ - -/* Making these classes inherit from CBaseObject does nothing for their - functionality but it allows us to check there are no memory leaks */ - -/* WARNING Be very careful when using this class, what it lets you do is - store and retrieve objects so that you can minimise object creation - which in turns improves efficiency. However the object you store is - exactly the same as the object you get back which means that it short - circuits the constructor initialisation phase. This means any class - variables the object has (eg pointers) are highly likely to be invalid. - Therefore ensure you reinitialise the object before using it again */ - - -#ifndef __CACHE__ -#define __CACHE__ - - -class CCache : CBaseObject { - - /* Make copy constructor and assignment operator inaccessible */ - - CCache(const CCache &refCache); - CCache &operator=(const CCache &refCache); - -private: - - /* These are initialised in the constructor. The first variable points to - an array of pointers, each of which points to a CBaseObject derived - object. The m_iCacheSize is the static fixed size for the cache and the - m_iUsed defines the number of places filled with objects at any time. - We fill the array of pointers from the start (ie m_ppObjects[0] first) - and then only add and remove objects from the end position, so in this - respect the array of object pointers should be treated as a stack */ - - CBaseObject **m_ppObjects; - const INT m_iCacheSize; - INT m_iUsed; - -public: - - CCache(__in_opt LPCTSTR pName,INT iItems); - virtual ~CCache(); - - /* Add an item to the cache */ - CBaseObject *AddToCache(__in CBaseObject *pObject); - - /* Remove an item from the cache */ - CBaseObject *RemoveFromCache(); - - /* Delete all the objects held in the cache */ - void RemoveAll(void); - - /* Return the cache size which is set during construction */ - INT GetCacheSize(void) const {return m_iCacheSize;}; -}; - -#endif /* __CACHE__ */ - diff --git a/third_party/BaseClasses/checkbmi.h b/third_party/BaseClasses/checkbmi.h deleted file mode 100644 index 72879679..00000000 --- a/third_party/BaseClasses/checkbmi.h +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright (c) 1992 - 1997 Microsoft Corporation. All Rights Reserved. - -#ifndef _CHECKBMI_H_ -#define _CHECKBMI_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -// Helper -__inline BOOL MultiplyCheckOverflow(DWORD a, DWORD b, __deref_out_range(==, a * b) DWORD *pab) { - *pab = a * b; - if ((a == 0) || (((*pab) / a) == b)) { - return TRUE; - } - return FALSE; -} - - -// Checks if the fields in a BITMAPINFOHEADER won't generate -// overlows and buffer overruns -// This is not a complete check and does not guarantee code using this structure will be secure -// from attack -// Bugs this is guarding against: -// 1. Total structure size calculation overflowing -// 2. biClrUsed > 256 for 8-bit palettized content -// 3. Total bitmap size in bytes overflowing -// 4. biSize < size of the base structure leading to accessessing random memory -// 5. Total structure size exceeding know size of data -// - -__success(return != 0) __inline BOOL ValidateBitmapInfoHeader( - const BITMAPINFOHEADER *pbmi, // pointer to structure to check - __out_range(>=, sizeof(BITMAPINFOHEADER)) DWORD cbSize // size of memory block containing structure -) -{ - DWORD dwWidthInBytes; - DWORD dwBpp; - DWORD dwWidthInBits; - DWORD dwHeight; - DWORD dwSizeImage; - DWORD dwClrUsed; - - // Reject bad parameters - do the size check first to avoid reading bad memory - if (cbSize < sizeof(BITMAPINFOHEADER) || - pbmi->biSize < sizeof(BITMAPINFOHEADER) || - pbmi->biSize > 4096) { - return FALSE; - } - - // Reject 0 size - if (pbmi->biWidth == 0 || pbmi->biHeight == 0) { - return FALSE; - } - - // Use bpp of 200 for validating against further overflows if not set for compressed format - dwBpp = 200; - - if (pbmi->biBitCount > dwBpp) { - return FALSE; - } - - // Strictly speaking abs can overflow so cast explicitly to DWORD - dwHeight = (DWORD)abs(pbmi->biHeight); - - if (!MultiplyCheckOverflow(dwBpp, (DWORD)pbmi->biWidth, &dwWidthInBits)) { - return FALSE; - } - - // Compute correct width in bytes - rounding up to 4 bytes - dwWidthInBytes = (dwWidthInBits / 8 + 3) & ~3; - - if (!MultiplyCheckOverflow(dwWidthInBytes, dwHeight, &dwSizeImage)) { - return FALSE; - } - - // Fail if total size is 0 - this catches indivual quantities being 0 - // Also don't allow huge values > 1GB which might cause arithmetic - // errors for users - if (dwSizeImage > 0x40000000 || - pbmi->biSizeImage > 0x40000000) { - return FALSE; - } - - // Fail if biClrUsed looks bad - if (pbmi->biClrUsed > 256) { - return FALSE; - } - - if (pbmi->biClrUsed == 0 && pbmi->biBitCount <= 8 && pbmi->biBitCount > 0) { - dwClrUsed = (1 << pbmi->biBitCount); - } else { - dwClrUsed = pbmi->biClrUsed; - } - - // Check total size - if (cbSize < pbmi->biSize + dwClrUsed * sizeof(RGBQUAD) + - (pbmi->biCompression == BI_BITFIELDS ? 3 * sizeof(DWORD) : 0)) { - return FALSE; - } - - // If it is RGB validate biSizeImage - lots of code assumes the size is correct - if (pbmi->biCompression == BI_RGB || pbmi->biCompression == BI_BITFIELDS) { - if (pbmi->biSizeImage != 0) { - DWORD dwBits = (DWORD)pbmi->biWidth * (DWORD)pbmi->biBitCount; - DWORD dwWidthInBytes = ((DWORD)((dwBits+31) & (~31)) / 8); - DWORD dwTotalSize = (DWORD)abs(pbmi->biHeight) * dwWidthInBytes; - if (dwTotalSize > pbmi->biSizeImage) { - return FALSE; - } - } - } - return TRUE; -} - -#ifdef __cplusplus -} -#endif - -#endif // _CHECKBMI_H_ diff --git a/third_party/BaseClasses/cprop.cpp b/third_party/BaseClasses/cprop.cpp deleted file mode 100644 index 7bd76b4e..00000000 --- a/third_party/BaseClasses/cprop.cpp +++ /dev/null @@ -1,383 +0,0 @@ -//------------------------------------------------------------------------------ -// File: CProp.cpp -// -// Desc: DirectShow base classes - implements CBasePropertyPage class. -// -// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. -//------------------------------------------------------------------------------ - - -#include - -// Constructor for the base property page class. As described in the header -// file we must be initialised with dialog and title resource identifiers. -// The class supports IPropertyPage and overrides AddRef and Release calls -// to keep track of the reference counts. When the last count is released -// we call SetPageSite(NULL) and SetObjects(0,NULL) to release interfaces -// previously obtained by the property page when it had SetObjects called - -CBasePropertyPage::CBasePropertyPage(__in_opt LPCTSTR pName, // Debug only name - __inout_opt LPUNKNOWN pUnk, // COM Delegator - int DialogId, // Resource ID - int TitleId) : // To get tital - CUnknown(pName,pUnk), - m_DialogId(DialogId), - m_TitleId(TitleId), - m_hwnd(NULL), - m_Dlg(NULL), - m_pPageSite(NULL), - m_bObjectSet(FALSE), - m_bDirty(FALSE) -{ -} - -#ifdef UNICODE -CBasePropertyPage::CBasePropertyPage(__in_opt LPCSTR pName, // Debug only name - __inout_opt LPUNKNOWN pUnk, // COM Delegator - int DialogId, // Resource ID - int TitleId) : // To get tital - CUnknown(pName,pUnk), - m_DialogId(DialogId), - m_TitleId(TitleId), - m_hwnd(NULL), - m_Dlg(NULL), - m_pPageSite(NULL), - m_bObjectSet(FALSE), - m_bDirty(FALSE) -{ -} -#endif - -// Increment our reference count - -STDMETHODIMP_(ULONG) CBasePropertyPage::NonDelegatingAddRef() -{ - LONG lRef = InterlockedIncrement(&m_cRef); - ASSERT(lRef > 0); - return max(ULONG(m_cRef),1ul); -} - - -// Release a reference count and protect against reentrancy - -STDMETHODIMP_(ULONG) CBasePropertyPage::NonDelegatingRelease() -{ - // If the reference count drops to zero delete ourselves - - LONG lRef = InterlockedDecrement(&m_cRef); - if (lRef == 0) { - m_cRef++; - SetPageSite(NULL); - SetObjects(0,NULL); - delete this; - return ULONG(0); - } else { - // Don't touch m_cRef again here! - return max(ULONG(lRef),1ul); - } -} - - -// Expose our IPropertyPage interface - -STDMETHODIMP -CBasePropertyPage::NonDelegatingQueryInterface(REFIID riid,__deref_out void **ppv) -{ - if (riid == IID_IPropertyPage) { - return GetInterface((IPropertyPage *)this,ppv); - } else { - return CUnknown::NonDelegatingQueryInterface(riid,ppv); - } -} - - -// Get the page info so that the page site can size itself - -STDMETHODIMP CBasePropertyPage::GetPageInfo(__out LPPROPPAGEINFO pPageInfo) -{ - CheckPointer(pPageInfo,E_POINTER); - WCHAR wszTitle[STR_MAX_LENGTH]; - WideStringFromResource(wszTitle,m_TitleId); - - // Allocate dynamic memory for the property page title - - LPOLESTR pszTitle; - HRESULT hr = AMGetWideString(wszTitle, &pszTitle); - if (FAILED(hr)) { - NOTE("No caption memory"); - return hr; - } - - pPageInfo->cb = sizeof(PROPPAGEINFO); - pPageInfo->pszTitle = pszTitle; - pPageInfo->pszDocString = NULL; - pPageInfo->pszHelpFile = NULL; - pPageInfo->dwHelpContext = 0; - - // Set defaults in case GetDialogSize fails - pPageInfo->size.cx = 340; - pPageInfo->size.cy = 150; - - GetDialogSize(m_DialogId, DialogProc,0L,&pPageInfo->size); - return NOERROR; -} - - -// Handles the messages for our property window - -INT_PTR CALLBACK CBasePropertyPage::DialogProc(HWND hwnd, - UINT uMsg, - WPARAM wParam, - LPARAM lParam) -{ - CBasePropertyPage *pPropertyPage; - - switch (uMsg) { - - case WM_INITDIALOG: - - _SetWindowLongPtr(hwnd, DWLP_USER, lParam); - - // This pointer may be NULL when calculating size - - pPropertyPage = (CBasePropertyPage *) lParam; - if (pPropertyPage == NULL) { - return (LRESULT) 1; - } - pPropertyPage->m_Dlg = hwnd; - } - - // This pointer may be NULL when calculating size - - pPropertyPage = _GetWindowLongPtr(hwnd, DWLP_USER); - if (pPropertyPage == NULL) { - return (LRESULT) 1; - } - return pPropertyPage->OnReceiveMessage(hwnd,uMsg,wParam,lParam); -} - - -// Tells us the object that should be informed of the property changes - -STDMETHODIMP CBasePropertyPage::SetObjects(ULONG cObjects,__in_ecount_opt(cObjects) LPUNKNOWN *ppUnk) -{ - if (cObjects == 1) { - - if ((ppUnk == NULL) || (*ppUnk == NULL)) { - return E_POINTER; - } - - // Set a flag to say that we have set the Object - m_bObjectSet = TRUE ; - return OnConnect(*ppUnk); - - } else if (cObjects == 0) { - - // Set a flag to say that we have not set the Object for the page - m_bObjectSet = FALSE ; - return OnDisconnect(); - } - - DbgBreak("No support for more than one object"); - return E_UNEXPECTED; -} - - -// Create the window we will use to edit properties - -STDMETHODIMP CBasePropertyPage::Activate(HWND hwndParent, - LPCRECT pRect, - BOOL fModal) -{ - CheckPointer(pRect,E_POINTER); - - // Return failure if SetObject has not been called. - if (m_bObjectSet == FALSE) { - return E_UNEXPECTED; - } - - if (m_hwnd) { - return E_UNEXPECTED; - } - - m_hwnd = CreateDialogParam(g_hInst, - MAKEINTRESOURCE(m_DialogId), - hwndParent, - DialogProc, - (LPARAM) this); - if (m_hwnd == NULL) { - return E_OUTOFMEMORY; - } - - OnActivate(); - Move(pRect); - return Show(SW_SHOWNORMAL); -} - - -// Set the position of the property page - -STDMETHODIMP CBasePropertyPage::Move(LPCRECT pRect) -{ - CheckPointer(pRect,E_POINTER); - - if (m_hwnd == NULL) { - return E_UNEXPECTED; - } - - MoveWindow(m_hwnd, // Property page handle - pRect->left, // x coordinate - pRect->top, // y coordinate - WIDTH(pRect), // Overall window width - HEIGHT(pRect), // And likewise height - TRUE); // Should we repaint it - - return NOERROR; -} - - -// Display the property dialog - -STDMETHODIMP CBasePropertyPage::Show(UINT nCmdShow) -{ - // Have we been activated yet - - if (m_hwnd == NULL) { - return E_UNEXPECTED; - } - - // Ignore wrong show flags - - if ((nCmdShow != SW_SHOW) && (nCmdShow != SW_SHOWNORMAL) && (nCmdShow != SW_HIDE)) { - return E_INVALIDARG; - } - - ShowWindow(m_hwnd,nCmdShow); - InvalidateRect(m_hwnd,NULL,TRUE); - return NOERROR; -} - - -// Destroy the property page dialog - -STDMETHODIMP CBasePropertyPage::Deactivate(void) -{ - if (m_hwnd == NULL) { - return E_UNEXPECTED; - } - - // Remove WS_EX_CONTROLPARENT before DestroyWindow call - - DWORD dwStyle = GetWindowLong(m_hwnd, GWL_EXSTYLE); - dwStyle = dwStyle & (~WS_EX_CONTROLPARENT); - - // Set m_hwnd to be NULL temporarily so the message handler - // for WM_STYLECHANGING doesn't add the WS_EX_CONTROLPARENT - // style back in - HWND hwnd = m_hwnd; - m_hwnd = NULL; - SetWindowLong(hwnd, GWL_EXSTYLE, dwStyle); - m_hwnd = hwnd; - - OnDeactivate(); - - // Destroy the dialog window - - DestroyWindow(m_hwnd); - m_hwnd = NULL; - return NOERROR; -} - - -// Tells the application property page site - -STDMETHODIMP CBasePropertyPage::SetPageSite(__in_opt LPPROPERTYPAGESITE pPageSite) -{ - if (pPageSite) { - - if (m_pPageSite) { - return E_UNEXPECTED; - } - - m_pPageSite = pPageSite; - m_pPageSite->AddRef(); - - } else { - - if (m_pPageSite == NULL) { - return E_UNEXPECTED; - } - - m_pPageSite->Release(); - m_pPageSite = NULL; - } - return NOERROR; -} - - -// Apply any changes so far made - -STDMETHODIMP CBasePropertyPage::Apply() -{ - // In ActiveMovie 1.0 we used to check whether we had been activated or - // not. This is too constrictive. Apply should be allowed as long as - // SetObject was called to set an object. So we will no longer check to - // see if we have been activated (ie., m_hWnd != NULL), but instead - // make sure that m_bObjectSet is TRUE (ie., SetObject has been called). - - if (m_bObjectSet == FALSE) { - return E_UNEXPECTED; - } - - // Must have had a site set - - if (m_pPageSite == NULL) { - return E_UNEXPECTED; - } - - // Has anything changed - - if (m_bDirty == FALSE) { - return NOERROR; - } - - // Commit derived class changes - - HRESULT hr = OnApplyChanges(); - if (SUCCEEDED(hr)) { - m_bDirty = FALSE; - } - return hr; -} - - -// Base class definition for message handling - -INT_PTR CBasePropertyPage::OnReceiveMessage(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam) -{ - // we would like the TAB key to move around the tab stops in our property - // page, but for some reason OleCreatePropertyFrame clears the CONTROLPARENT - // style behind our back, so we need to switch it back on now behind its - // back. Otherwise the tab key will be useless in every page. - // - - CBasePropertyPage *pPropertyPage; - { - pPropertyPage = _GetWindowLongPtr(hwnd, DWLP_USER); - - if (pPropertyPage->m_hwnd == NULL) { - return 0; - } - switch (uMsg) { - case WM_STYLECHANGING: - if (wParam == GWL_EXSTYLE) { - LPSTYLESTRUCT lpss = (LPSTYLESTRUCT)lParam; - lpss->styleNew |= WS_EX_CONTROLPARENT; - return 0; - } - } - } - - return DefWindowProc(hwnd,uMsg,wParam,lParam); -} - diff --git a/third_party/BaseClasses/cprop.h b/third_party/BaseClasses/cprop.h deleted file mode 100644 index db449406..00000000 --- a/third_party/BaseClasses/cprop.h +++ /dev/null @@ -1,95 +0,0 @@ -//------------------------------------------------------------------------------ -// File: CProp.h -// -// Desc: DirectShow base classes. -// -// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. -//------------------------------------------------------------------------------ - - -#ifndef __CPROP__ -#define __CPROP__ - -// Base property page class. Filters typically expose custom properties by -// implementing special control interfaces, examples are IDirectDrawVideo -// and IQualProp on renderers. This allows property pages to be built that -// use the given interface. Applications such as the ActiveMovie OCX query -// filters for the property pages they support and expose them to the user -// -// This class provides all the framework for a property page. A property -// page is a COM object that supports IPropertyPage. We should be created -// with a resource ID for the dialog which we will load when required. We -// should also be given in the constructor a resource ID for a title string -// we will load from the DLLs STRINGTABLE. The property page titles must be -// stored in resource files so that they can be easily internationalised -// -// We have a number of virtual methods (not PURE) that may be overriden in -// derived classes to query for interfaces and so on. These functions have -// simple implementations here that just return NOERROR. Derived classes -// will almost definately have to override the message handler method called -// OnReceiveMessage. We have a static dialog procedure that calls the method -// so that derived classes don't have to fiddle around with the this pointer - -class AM_NOVTABLE CBasePropertyPage : public IPropertyPage, public CUnknown -{ -protected: - - LPPROPERTYPAGESITE m_pPageSite; // Details for our property site - HWND m_hwnd; // Window handle for the page - HWND m_Dlg; // Actual dialog window handle - BOOL m_bDirty; // Has anything been changed - int m_TitleId; // Resource identifier for title - int m_DialogId; // Dialog resource identifier - - static INT_PTR CALLBACK DialogProc(HWND hwnd, - UINT uMsg, - WPARAM wParam, - LPARAM lParam); - -private: - BOOL m_bObjectSet ; // SetObject has been called or not. -public: - - CBasePropertyPage(__in_opt LPCTSTR pName, // Debug only name - __inout_opt LPUNKNOWN pUnk, // COM Delegator - int DialogId, // Resource ID - int TitleId); // To get tital - -#ifdef UNICODE - CBasePropertyPage(__in_opt LPCSTR pName, - __inout_opt LPUNKNOWN pUnk, - int DialogId, - int TitleId); -#endif - virtual ~CBasePropertyPage() { }; - DECLARE_IUNKNOWN - - // Override these virtual methods - - virtual HRESULT OnConnect(IUnknown *pUnknown) { return NOERROR; }; - virtual HRESULT OnDisconnect() { return NOERROR; }; - virtual HRESULT OnActivate() { return NOERROR; }; - virtual HRESULT OnDeactivate() { return NOERROR; }; - virtual HRESULT OnApplyChanges() { return NOERROR; }; - virtual INT_PTR OnReceiveMessage(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam); - - // These implement an IPropertyPage interface - - STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv); - STDMETHODIMP_(ULONG) NonDelegatingRelease(); - STDMETHODIMP_(ULONG) NonDelegatingAddRef(); - STDMETHODIMP SetPageSite(__in_opt LPPROPERTYPAGESITE pPageSite); - STDMETHODIMP Activate(HWND hwndParent, LPCRECT prect,BOOL fModal); - STDMETHODIMP Deactivate(void); - STDMETHODIMP GetPageInfo(__out LPPROPPAGEINFO pPageInfo); - STDMETHODIMP SetObjects(ULONG cObjects, __in_ecount_opt(cObjects) LPUNKNOWN *ppUnk); - STDMETHODIMP Show(UINT nCmdShow); - STDMETHODIMP Move(LPCRECT prect); - STDMETHODIMP IsPageDirty(void) { return m_bDirty ? S_OK : S_FALSE; } - STDMETHODIMP Apply(void); - STDMETHODIMP Help(LPCWSTR lpszHelpDir) { return E_NOTIMPL; } - STDMETHODIMP TranslateAccelerator(__inout LPMSG lpMsg) { return E_NOTIMPL; } -}; - -#endif // __CPROP__ - diff --git a/third_party/BaseClasses/ddmm.cpp b/third_party/BaseClasses/ddmm.cpp deleted file mode 100644 index bfa700cb..00000000 --- a/third_party/BaseClasses/ddmm.cpp +++ /dev/null @@ -1,129 +0,0 @@ -//------------------------------------------------------------------------------ -// File: DDMM.cpp -// -// Desc: DirectShow base classes - implements routines for using DirectDraw -// on a multimonitor system. -// -// Copyright (c) 1995-2001 Microsoft Corporation. All rights reserved. -//------------------------------------------------------------------------------ - - -#include -#include -#include "ddmm.h" - -/* - * FindDeviceCallback - */ -typedef struct { - LPSTR szDevice; - GUID* lpGUID; - GUID GUID; - BOOL fFound; -} FindDeviceData; - -BOOL CALLBACK FindDeviceCallback(__in_opt GUID* lpGUID, __in LPSTR szName, __in LPSTR szDevice, __in LPVOID lParam) -{ - FindDeviceData *p = (FindDeviceData*)lParam; - - if (lstrcmpiA(p->szDevice, szDevice) == 0) { - if (lpGUID) { - p->GUID = *lpGUID; - p->lpGUID = &p->GUID; - } else { - p->lpGUID = NULL; - } - p->fFound = TRUE; - return FALSE; - } - return TRUE; -} - - -BOOL CALLBACK FindDeviceCallbackEx(__in_opt GUID* lpGUID, __in LPSTR szName, __in LPSTR szDevice, __in LPVOID lParam, HMONITOR hMonitor) -{ - FindDeviceData *p = (FindDeviceData*)lParam; - - if (lstrcmpiA(p->szDevice, szDevice) == 0) { - if (lpGUID) { - p->GUID = *lpGUID; - p->lpGUID = &p->GUID; - } else { - p->lpGUID = NULL; - } - p->fFound = TRUE; - return FALSE; - } - return TRUE; -} - - -/* - * DirectDrawCreateFromDevice - * - * create a DirectDraw object for a particular device - */ -IDirectDraw * DirectDrawCreateFromDevice(__in_opt LPSTR szDevice, PDRAWCREATE DirectDrawCreateP, PDRAWENUM DirectDrawEnumerateP) -{ - IDirectDraw* pdd = NULL; - FindDeviceData find; - - if (szDevice == NULL) { - DirectDrawCreateP(NULL, &pdd, NULL); - return pdd; - } - - find.szDevice = szDevice; - find.fFound = FALSE; - DirectDrawEnumerateP(FindDeviceCallback, (LPVOID)&find); - - if (find.fFound) - { - // - // In 4bpp mode the following DDraw call causes a message box to be popped - // up by DDraw (!?!). It's DDraw's fault, but we don't like it. So we - // make sure it doesn't happen. - // - UINT ErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS); - DirectDrawCreateP(find.lpGUID, &pdd, NULL); - SetErrorMode(ErrorMode); - } - - return pdd; -} - - -/* - * DirectDrawCreateFromDeviceEx - * - * create a DirectDraw object for a particular device - */ -IDirectDraw * DirectDrawCreateFromDeviceEx(__in_opt LPSTR szDevice, PDRAWCREATE DirectDrawCreateP, LPDIRECTDRAWENUMERATEEXA DirectDrawEnumerateExP) -{ - IDirectDraw* pdd = NULL; - FindDeviceData find; - - if (szDevice == NULL) { - DirectDrawCreateP(NULL, &pdd, NULL); - return pdd; - } - - find.szDevice = szDevice; - find.fFound = FALSE; - DirectDrawEnumerateExP(FindDeviceCallbackEx, (LPVOID)&find, - DDENUM_ATTACHEDSECONDARYDEVICES); - - if (find.fFound) - { - // - // In 4bpp mode the following DDraw call causes a message box to be popped - // up by DDraw (!?!). It's DDraw's fault, but we don't like it. So we - // make sure it doesn't happen. - // - UINT ErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS); - DirectDrawCreateP(find.lpGUID, &pdd, NULL); - SetErrorMode(ErrorMode); - } - - return pdd; -} diff --git a/third_party/BaseClasses/ddmm.h b/third_party/BaseClasses/ddmm.h deleted file mode 100644 index 7b311bc1..00000000 --- a/third_party/BaseClasses/ddmm.h +++ /dev/null @@ -1,28 +0,0 @@ -//------------------------------------------------------------------------------ -// File: DDMM.h -// -// Desc: DirectShow base classes - efines routines for using DirectDraw -// on a multimonitor system. -// -// Copyright (c) 1995-2001 Microsoft Corporation. All rights reserved. -//------------------------------------------------------------------------------ - - -#ifdef __cplusplus -extern "C" { /* Assume C declarations for C++ */ -#endif /* __cplusplus */ - -// DDRAW.H might not include these -#ifndef DDENUM_ATTACHEDSECONDARYDEVICES -#define DDENUM_ATTACHEDSECONDARYDEVICES 0x00000001L -#endif - -typedef HRESULT (*PDRAWCREATE)(IID *,LPDIRECTDRAW *,LPUNKNOWN); -typedef HRESULT (*PDRAWENUM)(LPDDENUMCALLBACKA, LPVOID); - -IDirectDraw * DirectDrawCreateFromDevice(__in_opt LPSTR, PDRAWCREATE, PDRAWENUM); -IDirectDraw * DirectDrawCreateFromDeviceEx(__in_opt LPSTR, PDRAWCREATE, LPDIRECTDRAWENUMERATEEXA); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ diff --git a/third_party/BaseClasses/dllentry.cpp b/third_party/BaseClasses/dllentry.cpp deleted file mode 100644 index 130aad6a..00000000 --- a/third_party/BaseClasses/dllentry.cpp +++ /dev/null @@ -1,367 +0,0 @@ -//------------------------------------------------------------------------------ -// File: DlleEntry.cpp -// -// Desc: DirectShow base classes - implements classes used to support dll -// entry points for COM objects. -// -// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. -//------------------------------------------------------------------------------ - - -#include -#include - -#ifdef DEBUG -#ifdef UNICODE -#ifndef _UNICODE -#define _UNICODE -#endif // _UNICODE -#endif // UNICODE - -#include -#endif // DEBUG -#include - -extern CFactoryTemplate g_Templates[]; -extern int g_cTemplates; - -HINSTANCE g_hInst; -DWORD g_amPlatform; // VER_PLATFORM_WIN32_WINDOWS etc... (from GetVersionEx) -OSVERSIONINFO g_osInfo; - -// -// an instance of this is created by the DLLGetClassObject entrypoint -// it uses the CFactoryTemplate object it is given to support the -// IClassFactory interface - -class CClassFactory : public IClassFactory, public CBaseObject -{ - -private: - const CFactoryTemplate *const m_pTemplate; - - ULONG m_cRef; - - static int m_cLocked; -public: - CClassFactory(const CFactoryTemplate *); - - // IUnknown - STDMETHODIMP QueryInterface(REFIID riid, __deref_out void ** ppv); - STDMETHODIMP_(ULONG)AddRef(); - STDMETHODIMP_(ULONG)Release(); - - // IClassFactory - STDMETHODIMP CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, __deref_out void **pv); - STDMETHODIMP LockServer(BOOL fLock); - - // allow DLLGetClassObject to know about global server lock status - static BOOL IsLocked() { - return (m_cLocked > 0); - }; -}; - -// process-wide dll locked state -int CClassFactory::m_cLocked = 0; - -CClassFactory::CClassFactory(const CFactoryTemplate *pTemplate) -: CBaseObject(NAME("Class Factory")) -, m_cRef(0) -, m_pTemplate(pTemplate) -{ -} - - -STDMETHODIMP -CClassFactory::QueryInterface(REFIID riid,__deref_out void **ppv) -{ - CheckPointer(ppv,E_POINTER) - ValidateReadWritePtr(ppv,sizeof(PVOID)); - *ppv = NULL; - - // any interface on this object is the object pointer. - if ((riid == IID_IUnknown) || (riid == IID_IClassFactory)) { - *ppv = (LPVOID) this; - // AddRef returned interface pointer - ((LPUNKNOWN) *ppv)->AddRef(); - return NOERROR; - } - - return ResultFromScode(E_NOINTERFACE); -} - - -STDMETHODIMP_(ULONG) -CClassFactory::AddRef() -{ - return ++m_cRef; -} - -STDMETHODIMP_(ULONG) -CClassFactory::Release() -{ - LONG lRef = InterlockedDecrement((volatile LONG *)&m_cRef); - if (lRef == 0) { - delete this; - return 0; - } else { - return lRef; - } -} - -STDMETHODIMP -CClassFactory::CreateInstance( - LPUNKNOWN pUnkOuter, - REFIID riid, - __deref_out void **pv) -{ - CheckPointer(pv,E_POINTER) - ValidateReadWritePtr(pv,sizeof(void *)); - *pv = NULL; - - /* Enforce the normal OLE rules regarding interfaces and delegation */ - - if (pUnkOuter != NULL) { - if (IsEqualIID(riid,IID_IUnknown) == FALSE) { - *pv = NULL; - return ResultFromScode(E_NOINTERFACE); - } - } - - /* Create the new object through the derived class's create function */ - - HRESULT hr = NOERROR; - CUnknown *pObj = m_pTemplate->CreateInstance(pUnkOuter, &hr); - - if (pObj == NULL) { - *pv = NULL; - if (SUCCEEDED(hr)) { - hr = E_OUTOFMEMORY; - } - return hr; - } - - /* Delete the object if we got a construction error */ - - if (FAILED(hr)) { - delete pObj; - *pv = NULL; - return hr; - } - - /* Get a reference counted interface on the object */ - - /* We wrap the non-delegating QI with NDAddRef & NDRelease. */ - /* This protects any outer object from being prematurely */ - /* released by an inner object that may have to be created */ - /* in order to supply the requested interface. */ - pObj->NonDelegatingAddRef(); - hr = pObj->NonDelegatingQueryInterface(riid, pv); - pObj->NonDelegatingRelease(); - /* Note that if NonDelegatingQueryInterface fails, it will */ - /* not increment the ref count, so the NonDelegatingRelease */ - /* will drop the ref back to zero and the object will "self-*/ - /* destruct". Hence we don't need additional tidy-up code */ - /* to cope with NonDelegatingQueryInterface failing. */ - - if (SUCCEEDED(hr)) { - ASSERT(*pv); - } - - return hr; -} - -STDMETHODIMP -CClassFactory::LockServer(BOOL fLock) -{ - if (fLock) { - m_cLocked++; - } else { - m_cLocked--; - } - return NOERROR; -} - - -// --- COM entrypoints ----------------------------------------- - -//called by COM to get the class factory object for a given class -__control_entrypoint(DllExport) STDAPI -DllGetClassObject( - __in REFCLSID rClsID, - __in REFIID riid, - __deref_out void **pv) -{ - *pv = NULL; - if (!(riid == IID_IUnknown) && !(riid == IID_IClassFactory)) { - return E_NOINTERFACE; - } - - // traverse the array of templates looking for one with this - // class id - for (int i = 0; i < g_cTemplates; i++) { - const CFactoryTemplate * pT = &g_Templates[i]; - if (pT->IsClassID(rClsID)) { - - // found a template - make a class factory based on this - // template - - *pv = (LPVOID) (LPUNKNOWN) new CClassFactory(pT); - if (*pv == NULL) { - return E_OUTOFMEMORY; - } - ((LPUNKNOWN)*pv)->AddRef(); - return NOERROR; - } - } - return CLASS_E_CLASSNOTAVAILABLE; -} - -// -// Call any initialization routines -// -void -DllInitClasses(BOOL bLoading) -{ - int i; - - // traverse the array of templates calling the init routine - // if they have one - for (i = 0; i < g_cTemplates; i++) { - const CFactoryTemplate * pT = &g_Templates[i]; - if (pT->m_lpfnInit != NULL) { - (*pT->m_lpfnInit)(bLoading, pT->m_ClsID); - } - } - -} - -// called by COM to determine if this dll can be unloaded -// return ok unless there are outstanding objects or a lock requested -// by IClassFactory::LockServer -// -// CClassFactory has a static function that can tell us about the locks, -// and CCOMObject has a static function that can tell us about the active -// object count -STDAPI -DllCanUnloadNow() -{ - DbgLog((LOG_MEMORY,2,TEXT("DLLCanUnloadNow called - IsLocked = %d, Active objects = %d"), - CClassFactory::IsLocked(), - CBaseObject::ObjectsActive())); - - if (CClassFactory::IsLocked() || CBaseObject::ObjectsActive()) { - return S_FALSE; - } else { - return S_OK; - } -} - - -// --- standard WIN32 entrypoints -------------------------------------- - - -extern "C" void __cdecl __security_init_cookie(void); -extern "C" BOOL WINAPI _DllEntryPoint(HINSTANCE, ULONG, __inout_opt LPVOID); -#pragma comment(linker, "/merge:.CRT=.rdata") - -extern "C" -DECLSPEC_NOINLINE -BOOL -WINAPI -DllEntryPoint( - HINSTANCE hInstance, - ULONG ulReason, - __inout_opt LPVOID pv - ) -{ - if ( ulReason == DLL_PROCESS_ATTACH ) { - // Must happen before any other code is executed. Thankfully - it's re-entrant - __security_init_cookie(); - } - return _DllEntryPoint(hInstance, ulReason, pv); -} - - -DECLSPEC_NOINLINE -BOOL -WINAPI -_DllEntryPoint( - HINSTANCE hInstance, - ULONG ulReason, - __inout_opt LPVOID pv - ) -{ -#ifdef DEBUG - extern bool g_fDbgInDllEntryPoint; - g_fDbgInDllEntryPoint = true; -#endif - - switch (ulReason) - { - - case DLL_PROCESS_ATTACH: - DisableThreadLibraryCalls(hInstance); - DbgInitialise(hInstance); - - { - // The platform identifier is used to work out whether - // full unicode support is available or not. Hence the - // default will be the lowest common denominator - i.e. N/A - g_amPlatform = VER_PLATFORM_WIN32_WINDOWS; // win95 assumed in case GetVersionEx fails - - g_osInfo.dwOSVersionInfoSize = sizeof(g_osInfo); - if (GetVersionEx(&g_osInfo)) { - g_amPlatform = g_osInfo.dwPlatformId; - } else { - DbgLog((LOG_ERROR, 1, TEXT("Failed to get the OS platform, assuming Win95"))); - } - } - - g_hInst = hInstance; - DllInitClasses(TRUE); - break; - - case DLL_PROCESS_DETACH: - DllInitClasses(FALSE); - -#ifdef DEBUG - if (CBaseObject::ObjectsActive()) { - DbgSetModuleLevel(LOG_MEMORY, 2); - TCHAR szInfo[512]; - extern TCHAR m_ModuleName[]; // Cut down module name - - TCHAR FullName[_MAX_PATH]; // Load the full path and module name - TCHAR *pName; // Searches from the end for a backslash - - GetModuleFileName(NULL,FullName,_MAX_PATH); - pName = _tcsrchr(FullName,'\\'); - if (pName == NULL) { - pName = FullName; - } else { - pName++; - } - - (void)StringCchPrintf(szInfo, NUMELMS(szInfo), TEXT("Executable: %s Pid %x Tid %x. "), - pName, GetCurrentProcessId(), GetCurrentThreadId()); - - (void)StringCchPrintf(szInfo+lstrlen(szInfo), NUMELMS(szInfo) - lstrlen(szInfo), TEXT("Module %s, %d objects left active!"), - m_ModuleName, CBaseObject::ObjectsActive()); - DbgAssert(szInfo, TEXT(__FILE__),__LINE__); - - // If running remotely wait for the Assert to be acknowledged - // before dumping out the object register - DbgDumpObjectRegister(); - } - DbgTerminate(); -#endif - break; - } - -#ifdef DEBUG - g_fDbgInDllEntryPoint = false; -#endif - return TRUE; -} - - diff --git a/third_party/BaseClasses/dllsetup.cpp b/third_party/BaseClasses/dllsetup.cpp deleted file mode 100644 index ede9c3fd..00000000 --- a/third_party/BaseClasses/dllsetup.cpp +++ /dev/null @@ -1,693 +0,0 @@ -//------------------------------------------------------------------------------ -// File: DllSetup.cpp -// -// Desc: DirectShow base classes. -// -// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. -//------------------------------------------------------------------------------ - - -#include -#include - -//--------------------------------------------------------------------------- -// defines - -#define MAX_KEY_LEN 260 - - -//--------------------------------------------------------------------------- -// externally defined functions/variable - -extern int g_cTemplates; -extern CFactoryTemplate g_Templates[]; - -//--------------------------------------------------------------------------- -// -// EliminateSubKey -// -// Try to enumerate all keys under this one. -// if we find anything, delete it completely. -// Otherwise just delete it. -// -// note - this was pinched/duplicated from -// Filgraph\Mapper.cpp - so should it be in -// a lib somewhere? -// -//--------------------------------------------------------------------------- - -STDAPI -EliminateSubKey( HKEY hkey, LPCTSTR strSubKey ) -{ - HKEY hk; - if (0 == lstrlen(strSubKey) ) { - // defensive approach - return E_FAIL; - } - - LONG lreturn = RegOpenKeyEx( hkey - , strSubKey - , 0 - , MAXIMUM_ALLOWED - , &hk ); - - ASSERT( lreturn == ERROR_SUCCESS - || lreturn == ERROR_FILE_NOT_FOUND - || lreturn == ERROR_INVALID_HANDLE ); - - if( ERROR_SUCCESS == lreturn ) - { - // Keep on enumerating the first (zero-th) - // key and deleting that - - for( ; ; ) - { - TCHAR Buffer[MAX_KEY_LEN]; - DWORD dw = MAX_KEY_LEN; - FILETIME ft; - - lreturn = RegEnumKeyEx( hk - , 0 - , Buffer - , &dw - , NULL - , NULL - , NULL - , &ft); - - ASSERT( lreturn == ERROR_SUCCESS - || lreturn == ERROR_NO_MORE_ITEMS ); - - if( ERROR_SUCCESS == lreturn ) - { - EliminateSubKey(hk, Buffer); - } - else - { - break; - } - } - - RegCloseKey(hk); - RegDeleteKey(hkey, strSubKey); - } - - return NOERROR; -} - - -//--------------------------------------------------------------------------- -// -// AMovieSetupRegisterServer() -// -// registers specfied file "szFileName" as server for -// CLSID "clsServer". A description is also required. -// The ThreadingModel and ServerType are optional, as -// they default to InprocServer32 (i.e. dll) and Both. -// -//--------------------------------------------------------------------------- - -STDAPI -AMovieSetupRegisterServer( CLSID clsServer - , LPCWSTR szDescription - , LPCWSTR szFileName - , LPCWSTR szThreadingModel = L"Both" - , LPCWSTR szServerType = L"InprocServer32" ) -{ - // temp buffer - // - TCHAR achTemp[MAX_PATH]; - - // convert CLSID uuid to string and write - // out subkey as string - CLSID\{} - // - OLECHAR szCLSID[CHARS_IN_GUID]; - HRESULT hr = StringFromGUID2( clsServer - , szCLSID - , CHARS_IN_GUID ); - ASSERT( SUCCEEDED(hr) ); - - // create key - // - HKEY hkey; - (void)StringCchPrintf( achTemp, NUMELMS(achTemp), TEXT("CLSID\\%ls"), szCLSID ); - LONG lreturn = RegCreateKey( HKEY_CLASSES_ROOT - , (LPCTSTR)achTemp - , &hkey ); - if( ERROR_SUCCESS != lreturn ) - { - return AmHresultFromWin32(lreturn); - } - - // set description string - // - - (void)StringCchPrintf( achTemp, NUMELMS(achTemp), TEXT("%ls"), szDescription ); - lreturn = RegSetValue( hkey - , (LPCTSTR)NULL - , REG_SZ - , achTemp - , sizeof(achTemp) ); - if( ERROR_SUCCESS != lreturn ) - { - RegCloseKey( hkey ); - return AmHresultFromWin32(lreturn); - } - - // create CLSID\\{"CLSID"}\\"ServerType" key, - // using key to CLSID\\{"CLSID"} passed back by - // last call to RegCreateKey(). - // - HKEY hsubkey; - - (void)StringCchPrintf( achTemp, NUMELMS(achTemp), TEXT("%ls"), szServerType ); - lreturn = RegCreateKey( hkey - , achTemp - , &hsubkey ); - if( ERROR_SUCCESS != lreturn ) - { - RegCloseKey( hkey ); - return AmHresultFromWin32(lreturn); - } - - // set Server string - // - (void)StringCchPrintf( achTemp, NUMELMS(achTemp), TEXT("%ls"), szFileName ); - lreturn = RegSetValue( hsubkey - , (LPCTSTR)NULL - , REG_SZ - , (LPCTSTR)achTemp - , sizeof(TCHAR) * (lstrlen(achTemp)+1) ); - if( ERROR_SUCCESS != lreturn ) - { - RegCloseKey( hkey ); - RegCloseKey( hsubkey ); - return AmHresultFromWin32(lreturn); - } - - (void)StringCchPrintf( achTemp, NUMELMS(achTemp), TEXT("%ls"), szThreadingModel ); - lreturn = RegSetValueEx( hsubkey - , TEXT("ThreadingModel") - , 0L - , REG_SZ - , (CONST BYTE *)achTemp - , sizeof(TCHAR) * (lstrlen(achTemp)+1) ); - - // close hkeys - // - RegCloseKey( hkey ); - RegCloseKey( hsubkey ); - - // and return - // - return HRESULT_FROM_WIN32(lreturn); - -} - - -//--------------------------------------------------------------------------- -// -// AMovieSetupUnregisterServer() -// -// default ActiveMovie dll setup function -// - to use must be called from an exported -// function named DllRegisterServer() -// -//--------------------------------------------------------------------------- - -STDAPI -AMovieSetupUnregisterServer( CLSID clsServer ) -{ - // convert CLSID uuid to string and write - // out subkey CLSID\{} - // - OLECHAR szCLSID[CHARS_IN_GUID]; - HRESULT hr = StringFromGUID2( clsServer - , szCLSID - , CHARS_IN_GUID ); - ASSERT( SUCCEEDED(hr) ); - - TCHAR achBuffer[MAX_KEY_LEN]; - (void)StringCchPrintf( achBuffer, NUMELMS(achBuffer), TEXT("CLSID\\%ls"), szCLSID ); - - // delete subkey - // - - hr = EliminateSubKey( HKEY_CLASSES_ROOT, achBuffer ); - ASSERT( SUCCEEDED(hr) ); - - // return - // - return NOERROR; -} - - -//--------------------------------------------------------------------------- -// -// AMovieSetupRegisterFilter through IFilterMapper2 -// -//--------------------------------------------------------------------------- - -STDAPI -AMovieSetupRegisterFilter2( const AMOVIESETUP_FILTER * const psetupdata - , IFilterMapper2 * pIFM2 - , 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 = pIFM2->UnregisterFilter( - 0, // default category - 0, // default instance name - *psetupdata->clsID ); - - - if( bRegister ) - { - REGFILTER2 rf2; - rf2.dwVersion = 1; - rf2.dwMerit = psetupdata->dwMerit; - rf2.cPins = psetupdata->nPins; - rf2.rgPins = psetupdata->lpPin; - - // register filter - // - DbgLog((LOG_TRACE, 3, TEXT("= = register filter"))); - hr = pIFM2->RegisterFilter(*psetupdata->clsID - , psetupdata->strName - , 0 // moniker - , 0 // category - , NULL // instance - , &rf2); - } - - // 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; -} - - -//--------------------------------------------------------------------------- -// -// RegisterAllServers() -// -//--------------------------------------------------------------------------- - -STDAPI -RegisterAllServers( LPCWSTR szFileName, BOOL bRegister ) -{ - HRESULT hr = NOERROR; - - for( int i = 0; i < g_cTemplates; i++ ) - { - // get i'th template - // - const CFactoryTemplate *pT = &g_Templates[i]; - - DbgLog((LOG_TRACE, 2, TEXT("- - register %ls"), - (LPCWSTR)pT->m_Name )); - - // register CLSID and InprocServer32 - // - if( bRegister ) - { - hr = AMovieSetupRegisterServer( *(pT->m_ClsID) - , (LPCWSTR)pT->m_Name - , szFileName ); - } - else - { - hr = AMovieSetupUnregisterServer( *(pT->m_ClsID) ); - } - - // check final error for this pass - // and break loop if we failed - // - if( FAILED(hr) ) - break; - } - - return hr; -} - - -//--------------------------------------------------------------------------- -// -// AMovieDllRegisterServer2() -// -// default ActiveMovie dll setup function -// - to use must be called from an exported -// function named DllRegisterServer() -// -// this function is table driven using the -// static members of the CFactoryTemplate -// class defined in the dll. -// -// it registers the Dll as the InprocServer32 -// and then calls the IAMovieSetup.Register -// method. -// -//--------------------------------------------------------------------------- - -STDAPI -AMovieDllRegisterServer2( BOOL bRegister ) -{ - HRESULT hr = NOERROR; - - DbgLog((LOG_TRACE, 2, TEXT("AMovieDllRegisterServer2()"))); - - // get file name (where g_hInst is the - // instance handle of the filter dll) - // - WCHAR achFileName[MAX_PATH]; - - // WIN95 doesn't support GetModuleFileNameW - // - { - char achTemp[MAX_PATH]; - - DbgLog((LOG_TRACE, 2, TEXT("- get module file name"))); - - // g_hInst handle is set in our dll entry point. Make sure - // DllEntryPoint in dllentry.cpp is called - ASSERT(g_hInst != 0); - - if( 0 == GetModuleFileNameA( g_hInst - , achTemp - , sizeof(achTemp) ) ) - { - // we've failed! - DWORD dwerr = GetLastError(); - return AmHresultFromWin32(dwerr); - } - - MultiByteToWideChar( CP_ACP - , 0L - , achTemp - , lstrlenA(achTemp) + 1 - , achFileName - , NUMELMS(achFileName) ); - } - - // - // first registering, register all OLE servers - // - if( bRegister ) - { - DbgLog((LOG_TRACE, 2, TEXT("- register OLE Servers"))); - hr = RegisterAllServers( achFileName, TRUE ); - } - - // - // next, register/unregister all filters - // - - if( SUCCEEDED(hr) ) - { - // init is ref counted so call just in case - // we're being called cold. - // - DbgLog((LOG_TRACE, 2, TEXT("- CoInitialize"))); - hr = CoInitialize( (LPVOID)NULL ); - ASSERT( SUCCEEDED(hr) ); - - // get hold of IFilterMapper2 - // - DbgLog((LOG_TRACE, 2, TEXT("- obtain IFilterMapper2"))); - IFilterMapper2 *pIFM2 = 0; - IFilterMapper *pIFM = 0; - hr = CoCreateInstance( CLSID_FilterMapper2 - , NULL - , CLSCTX_INPROC_SERVER - , IID_IFilterMapper2 - , (void **)&pIFM2 ); - if(FAILED(hr)) - { - DbgLog((LOG_TRACE, 2, TEXT("- trying IFilterMapper instead"))); - - hr = CoCreateInstance( - CLSID_FilterMapper, - NULL, - CLSCTX_INPROC_SERVER, - IID_IFilterMapper, - (void **)&pIFM); - } - if( SUCCEEDED(hr) ) - { - // scan through array of CFactoryTemplates - // registering servers and filters. - // - DbgLog((LOG_TRACE, 2, TEXT("- register Filters"))); - for( int i = 0; i < g_cTemplates; i++ ) - { - // get i'th template - // - const CFactoryTemplate *pT = &g_Templates[i]; - - if( NULL != pT->m_pAMovieSetup_Filter ) - { - DbgLog((LOG_TRACE, 2, TEXT("- - register %ls"), (LPCWSTR)pT->m_Name )); - - if(pIFM2) - { - hr = AMovieSetupRegisterFilter2( pT->m_pAMovieSetup_Filter, pIFM2, bRegister ); - } - else - { - hr = AMovieSetupRegisterFilter( pT->m_pAMovieSetup_Filter, pIFM, bRegister ); - } - } - - // check final error for this pass - // and break loop if we failed - // - if( FAILED(hr) ) - break; - } - - // release interface - // - if(pIFM2) - pIFM2->Release(); - else - pIFM->Release(); - - } - - // and clear up - // - CoFreeUnusedLibraries(); - CoUninitialize(); - } - - // - // if unregistering, unregister all OLE servers - // - if( SUCCEEDED(hr) && !bRegister ) - { - DbgLog((LOG_TRACE, 2, TEXT("- register OLE Servers"))); - hr = RegisterAllServers( achFileName, FALSE ); - } - - DbgLog((LOG_TRACE, 2, TEXT("- return %0x"), hr)); - return hr; -} - - -//--------------------------------------------------------------------------- -// -// AMovieDllRegisterServer() -// -// default ActiveMovie dll setup function -// - to use must be called from an exported -// function named DllRegisterServer() -// -// this function is table driven using the -// static members of the CFactoryTemplate -// class defined in the dll. -// -// it registers the Dll as the InprocServer32 -// and then calls the IAMovieSetup.Register -// method. -// -//--------------------------------------------------------------------------- - - -STDAPI -AMovieDllRegisterServer( void ) -{ - HRESULT hr = NOERROR; - - // get file name (where g_hInst is the - // instance handle of the filter dll) - // - WCHAR achFileName[MAX_PATH]; - - { - // WIN95 doesn't support GetModuleFileNameW - // - char achTemp[MAX_PATH]; - - if( 0 == GetModuleFileNameA( g_hInst - , achTemp - , sizeof(achTemp) ) ) - { - // we've failed! - DWORD dwerr = GetLastError(); - return AmHresultFromWin32(dwerr); - } - - MultiByteToWideChar( CP_ACP - , 0L - , achTemp - , lstrlenA(achTemp) + 1 - , achFileName - , NUMELMS(achFileName) ); - } - - // scan through array of CFactoryTemplates - // registering servers and filters. - // - for( int i = 0; i < g_cTemplates; i++ ) - { - // get i'th template - // - const CFactoryTemplate *pT = &g_Templates[i]; - - // register CLSID and InprocServer32 - // - hr = AMovieSetupRegisterServer( *(pT->m_ClsID) - , (LPCWSTR)pT->m_Name - , achFileName ); - - // instantiate all servers and get hold of - // IAMovieSetup, if implemented, and call - // IAMovieSetup.Register() method - // - if( SUCCEEDED(hr) && (NULL != pT->m_lpfnNew) ) - { - // instantiate object - // - PAMOVIESETUP psetup; - hr = CoCreateInstance( *(pT->m_ClsID) - , 0 - , CLSCTX_INPROC_SERVER - , IID_IAMovieSetup - , reinterpret_cast(&psetup) ); - if( SUCCEEDED(hr) ) - { - hr = psetup->Unregister(); - if( SUCCEEDED(hr) ) - hr = psetup->Register(); - psetup->Release(); - } - else - { - if( (E_NOINTERFACE == hr ) - || (VFW_E_NEED_OWNER == hr ) ) - hr = NOERROR; - } - } - - // check final error for this pass - // and break loop if we failed - // - if( FAILED(hr) ) - break; - - } // end-for - - return hr; -} - - -//--------------------------------------------------------------------------- -// -// AMovieDllUnregisterServer() -// -// default ActiveMovie dll uninstall function -// - to use must be called from an exported -// function named DllRegisterServer() -// -// this function is table driven using the -// static members of the CFactoryTemplate -// class defined in the dll. -// -// it calls the IAMovieSetup.Unregister -// method and then unregisters the Dll -// as the InprocServer32 -// -//--------------------------------------------------------------------------- - -STDAPI -AMovieDllUnregisterServer() -{ - // initialize return code - // - HRESULT hr = NOERROR; - - // scan through CFactory template and unregister - // all OLE servers and filters. - // - for( int i = g_cTemplates; i--; ) - { - // get i'th template - // - const CFactoryTemplate *pT = &g_Templates[i]; - - // check method exists - // - if( NULL != pT->m_lpfnNew ) - { - // instantiate object - // - PAMOVIESETUP psetup; - hr = CoCreateInstance( *(pT->m_ClsID) - , 0 - , CLSCTX_INPROC_SERVER - , IID_IAMovieSetup - , reinterpret_cast(&psetup) ); - if( SUCCEEDED(hr) ) - { - hr = psetup->Unregister(); - psetup->Release(); - } - else - { - if( (E_NOINTERFACE == hr ) - || (VFW_E_NEED_OWNER == hr ) ) - hr = NOERROR; - } - } - - // unregister CLSID and InprocServer32 - // - if( SUCCEEDED(hr) ) - { - hr = AMovieSetupUnregisterServer( *(pT->m_ClsID) ); - } - - // check final error for this pass - // and break loop if we failed - // - if( FAILED(hr) ) - break; - } - - return hr; -} diff --git a/third_party/BaseClasses/dllsetup.h b/third_party/BaseClasses/dllsetup.h deleted file mode 100644 index e363b8b6..00000000 --- a/third_party/BaseClasses/dllsetup.h +++ /dev/null @@ -1,46 +0,0 @@ -//------------------------------------------------------------------------------ -// File: DllSetup.h -// -// Desc: DirectShow base classes. -// -// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. -//------------------------------------------------------------------------------ - - -// To be self registering, OLE servers must -// export functions named DllRegisterServer -// and DllUnregisterServer. To allow use of -// custom and default implementations the -// defaults are named AMovieDllRegisterServer -// and AMovieDllUnregisterServer. -// -// To the use the default implementation you -// must provide stub functions. -// -// i.e. STDAPI DllRegisterServer() -// { -// return AMovieDllRegisterServer(); -// } -// -// STDAPI DllUnregisterServer() -// { -// return AMovieDllUnregisterServer(); -// } -// -// -// AMovieDllRegisterServer calls IAMovieSetup.Register(), and -// AMovieDllUnregisterServer calls IAMovieSetup.Unregister(). - -STDAPI AMovieDllRegisterServer2( BOOL ); -STDAPI AMovieDllRegisterServer(); -STDAPI AMovieDllUnregisterServer(); - -// helper functions -STDAPI EliminateSubKey( HKEY, LPCTSTR ); - - -STDAPI -AMovieSetupRegisterFilter2( const AMOVIESETUP_FILTER * const psetupdata - , IFilterMapper2 * pIFM2 - , BOOL bRegister ); - diff --git a/third_party/BaseClasses/dxmperf.h b/third_party/BaseClasses/dxmperf.h deleted file mode 100644 index 54a21203..00000000 --- a/third_party/BaseClasses/dxmperf.h +++ /dev/null @@ -1,250 +0,0 @@ -//------------------------------------------------------------------------------ -// File: DXMPerf.h -// -// Desc: Macros for DirectShow performance logging. -// -// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. -//------------------------------------------------------------------------------ - - -#ifndef _DXMPERF_H_ -#define _DXMPERF_H_ - -#include -#include "perflog.h" - -#ifdef _IA64_ -extern "C" unsigned __int64 __getReg( int whichReg ); -#pragma intrinsic(__getReg) -#endif // _IA64_ - - -inline ULONGLONG _RDTSC( void ) { -#ifdef _X86_ - LARGE_INTEGER li; - __asm { - _emit 0x0F - _emit 0x31 - mov li.LowPart,eax - mov li.HighPart,edx - } - return li.QuadPart; - -#if 0 // This isn't tested yet - -#elif defined (_IA64_) - -#define INL_REGID_APITC 3116 - return __getReg( INL_REGID_APITC ); - -#endif // 0 - -#else // unsupported platform - // not implemented on non x86/IA64 platforms - return 0; -#endif // _X86_/_IA64_ -} - -#define DXMPERF_VIDEOREND 0x00000001 -#define DXMPERF_AUDIOGLITCH 0x00000002 -//#define GETTIME_BIT 0x00000001 -//#define AUDIOREND_BIT 0x00000004 -//#define FRAMEDROP_BIT 0x00000008 -#define AUDIOBREAK_BIT 0x00000010 -#define DXMPERF_AUDIORECV 0x00000020 -#define DXMPERF_AUDIOSLAVE 0x00000040 -#define DXMPERF_AUDIOBREAK 0x00000080 - -#define PERFLOG_CTOR( name, iface ) -#define PERFLOG_DTOR( name, iface ) -#define PERFLOG_DELIVER( name, source, dest, sample, pmt ) -#define PERFLOG_RECEIVE( name, source, dest, sample, pmt ) -#define PERFLOG_RUN( name, iface, time, oldstate ) -#define PERFLOG_PAUSE( name, iface, oldstate ) -#define PERFLOG_STOP( name, iface, oldstate ) -#define PERFLOG_JOINGRAPH( name, iface, graph ) -#define PERFLOG_GETBUFFER( allocator, sample ) -#define PERFLOG_RELBUFFER( allocator, sample ) -#define PERFLOG_CONNECT( connector, connectee, status, pmt ) -#define PERFLOG_RXCONNECT( connector, connectee, status, pmt ) -#define PERFLOG_DISCONNECT( disconnector, disconnectee, status ) - -#define PERFLOG_GETTIME( clock, time ) /*{ \ - PERFINFO_WMI_GETTIME perfData; \ - if (NULL != g_pTraceEvent) { \ - memset( &perfData, 0, sizeof( perfData ) ); \ - perfData.header.Size = sizeof( perfData ); \ - perfData.header.Flags = WNODE_FLAG_TRACED_GUID; \ - perfData.header.Guid = GUID_GETTIME; \ - perfData.data.cycleCounter = _RDTSC(); \ - perfData.data.dshowClock = (ULONGLONG) (time); \ - if (g_perfMasks[GETTIME_INDEX] & GETTIME_BIT) \ - (*g_pTraceEvent)( g_traceHandle, (PEVENT_TRACE_HEADER) &perfData ); \ - } \ - }*/ - -#define PERFLOG_AUDIOREND( clocktime, sampletime, psample, bytetime, cbytes ) /*{ \ - PERFINFO_WMI_AVREND perfData; \ - if (NULL != g_pTraceEvent) { \ - memset( &perfData, 0, sizeof( perfData ) ); \ - perfData.header.Size = sizeof( perfData ); \ - perfData.header.Flags = WNODE_FLAG_TRACED_GUID; \ - perfData.header.Guid = GUID_AUDIOREND; \ - perfData.data.cycleCounter = _RDTSC(); \ - perfData.data.dshowClock = (clocktime); \ - perfData.data.sampleTime = (sampletime); \ - if (g_perfMasks[AUDIOREND_INDEX] & AUDIOREND_BIT) \ - (*g_pTraceEvent)( g_traceHandle, (PEVENT_TRACE_HEADER) &perfData ); \ - } \ - }*/ - -#define PERFLOG_AUDIORECV(StreamTime,SampleStart,SampleStop,Discontinuity,Duration) \ - if (PerflogEnableFlags & DXMPERF_AUDIORECV) { \ - PERFINFO_WMI_AUDIORECV perfData; \ - memset( &perfData, 0, sizeof( perfData ) ); \ - perfData.header.Size = sizeof( perfData ); \ - perfData.header.Flags = WNODE_FLAG_TRACED_GUID; \ - perfData.header.Guid = GUID_AUDIORECV; \ - perfData.data.streamTime = StreamTime; \ - perfData.data.sampleStart = SampleStart; \ - perfData.data.sampleStop = SampleStop; \ - perfData.data.discontinuity = Discontinuity; \ - perfData.data.hwduration = Duration; \ - PerflogTraceEvent((PEVENT_TRACE_HEADER) &perfData); \ - } - -#define PERFLOG_AUDIOSLAVE(MasterClock,SlaveClock,ErrorAccum,LastHighErrorSeen,LastLowErrorSeen) \ - if (PerflogEnableFlags & DXMPERF_AUDIOSLAVE) { \ - PERFINFO_WMI_AUDIOSLAVE perfData; \ - memset( &perfData, 0, sizeof( perfData ) ); \ - perfData.header.Size = sizeof( perfData ); \ - perfData.header.Flags = WNODE_FLAG_TRACED_GUID; \ - perfData.header.Guid = GUID_AUDIOSLAVE; \ - perfData.data.masterClock = MasterClock; \ - perfData.data.slaveClock = SlaveClock; \ - perfData.data.errorAccum = ErrorAccum; \ - perfData.data.lastHighErrorSeen = LastHighErrorSeen;\ - perfData.data.lastLowErrorSeen = LastLowErrorSeen; \ - PerflogTraceEvent((PEVENT_TRACE_HEADER) &perfData); \ - } - -#define PERFLOG_AUDIOADDBREAK(IterNextWrite,OffsetNextWrite,IterWrite,OffsetWrite) \ - if (PerflogEnableFlags & DXMPERF_AUDIOBREAK) { \ - PERFINFO_WMI_AUDIOADDBREAK perfData; \ - memset( &perfData, 0, sizeof( perfData ) ); \ - perfData.header.Size = sizeof( perfData ); \ - perfData.header.Flags = WNODE_FLAG_TRACED_GUID; \ - perfData.header.Guid = GUID_AUDIOADDBREAK; \ - perfData.data.iterNextWrite = IterNextWrite; \ - perfData.data.offsetNextWrite = OffsetNextWrite; \ - perfData.data.iterWrite = IterWrite; \ - perfData.data.offsetWrite = OffsetWrite; \ - PerflogTraceEvent((PEVENT_TRACE_HEADER) &perfData); \ - } - -#define PERFLOG_VIDEOREND( sampletime, clocktime, psample ) \ - if (PerflogEnableFlags & DXMPERF_VIDEOREND) { \ - PERFINFO_WMI_AVREND perfData; \ - memset( &perfData, 0, sizeof( perfData ) ); \ - perfData.header.Size = sizeof( perfData ); \ - perfData.header.Flags = WNODE_FLAG_TRACED_GUID; \ - perfData.header.Guid = GUID_VIDEOREND; \ - perfData.data.cycleCounter = _RDTSC(); \ - perfData.data.dshowClock = (clocktime); \ - perfData.data.sampleTime = (sampletime); \ - PerflogTraceEvent ((PEVENT_TRACE_HEADER) &perfData); \ - } - -#define PERFLOG_AUDIOGLITCH( instance, glitchtype, currenttime, previoustime ) \ - if (PerflogEnableFlags & DXMPERF_AUDIOGLITCH) { \ - PERFINFO_WMI_AUDIOGLITCH perfData; \ - memset( &perfData, 0, sizeof( perfData ) ); \ - perfData.header.Size = sizeof( perfData ); \ - perfData.header.Flags = WNODE_FLAG_TRACED_GUID; \ - perfData.header.Guid = GUID_DSOUNDGLITCH; \ - perfData.data.cycleCounter = _RDTSC(); \ - perfData.data.glitchType = (glitchtype); \ - perfData.data.sampleTime = (currenttime); \ - perfData.data.previousTime = (previoustime); \ - perfData.data.instanceId = (instance); \ - PerflogTraceEvent ((PEVENT_TRACE_HEADER) &perfData); \ - } - -#define PERFLOG_FRAMEDROP( sampletime, clocktime, psample, renderer ) /*{ \ - PERFINFO_WMI_FRAMEDROP perfData; \ - if (NULL != g_pTraceEvent) { \ - memset( &perfData, 0, sizeof( perfData ) ); \ - perfData.header.Size = sizeof( perfData ); \ - perfData.header.Flags = WNODE_FLAG_TRACED_GUID; \ - perfData.header.Guid = GUID_FRAMEDROP; \ - perfData.data.cycleCounter = _RDTSC(); \ - perfData.data.dshowClock = (clocktime); \ - perfData.data.frameTime = (sampletime); \ - if (g_perfMasks[FRAMEDROP_INDEX] & FRAMEDROP_BIT) \ - (*g_pTraceEvent)( g_traceHandle, (PEVENT_TRACE_HEADER) &perfData ); \ - } \ - }*/ - -/* -#define PERFLOG_AUDIOBREAK( nextwrite, writepos, msecs ) { \ - PERFINFO_WMI_AUDIOBREAK perfData; \ - if (NULL != g_pTraceEvent) { \ - memset( &perfData, 0, sizeof( perfData ) ); \ - perfData.header.Size = sizeof( perfData ); \ - perfData.header.Flags = WNODE_FLAG_TRACED_GUID; \ - perfData.header.Guid = GUID_AUDIOBREAK; \ - perfData.data.cycleCounter = _RDTSC(); \ - perfData.data.dshowClock = (writepos); \ - perfData.data.sampleTime = (nextwrite); \ - perfData.data.sampleDuration = (msecs); \ - if (g_perfMasks[AUDIOBREAK_INDEX] & AUDIOBREAK_BIT) \ - (*g_pTraceEvent)( g_traceHandle, (PEVENT_TRACE_HEADER) &perfData ); \ - } \ - } -*/ - -#define PERFLOG_AUDIOBREAK( nextwrite, writepos, msecs ) \ - if (PerflogEnableFlags & AUDIOBREAK_BIT) { \ - PERFINFO_WMI_AUDIOBREAK perfData; \ - memset( &perfData, 0, sizeof( perfData ) ); \ - perfData.header.Size = sizeof( perfData ); \ - perfData.header.Flags = WNODE_FLAG_TRACED_GUID; \ - perfData.header.Guid = GUID_AUDIOBREAK; \ - perfData.data.cycleCounter = _RDTSC(); \ - perfData.data.dshowClock = (writepos); \ - perfData.data.sampleTime = (nextwrite); \ - perfData.data.sampleDuration = (msecs); \ - PerflogTraceEvent ((PEVENT_TRACE_HEADER) &perfData); \ - } \ - - -inline -VOID PERFLOG_STREAMTRACE( - ULONG Level, - ULONG Id, - ULONGLONG DShowClock, - ULONGLONG Data1, - ULONGLONG Data2, - ULONGLONG Data3, - ULONGLONG Data4 - ) -{ - if (Level <= PerflogModuleLevel) - { - PERFINFO_WMI_STREAMTRACE perfData; - memset( &perfData, 0, sizeof( perfData ) ); - perfData.header.Size = sizeof( perfData ); - perfData.header.Flags = WNODE_FLAG_TRACED_GUID; - perfData.header.Guid = GUID_STREAMTRACE; - perfData.data.dshowClock = DShowClock; - perfData.data.id = Id; - perfData.data.data[0] = Data1; - perfData.data.data[1] = Data2; - perfData.data.data[2] = Data3; - perfData.data.data[3] = Data4; - PerflogTraceEvent((PEVENT_TRACE_HEADER) &perfData); - } -} - - -#endif // _DXMPERF_H_ diff --git a/third_party/BaseClasses/outputq.cpp b/third_party/BaseClasses/outputq.cpp deleted file mode 100644 index d3ab6175..00000000 --- a/third_party/BaseClasses/outputq.cpp +++ /dev/null @@ -1,801 +0,0 @@ -//------------------------------------------------------------------------------ -// File: OutputQ.cpp -// -// Desc: DirectShow base classes - implements COutputQueue class used by an -// output pin which may sometimes want to queue output samples on a -// separate thread and sometimes call Receive() directly on the input -// pin. -// -// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. -//------------------------------------------------------------------------------ - - -#include - - -// -// COutputQueue Constructor : -// -// Determines if a thread is to be created and creates resources -// -// pInputPin - the downstream input pin we're queueing samples to -// -// phr - changed to a failure code if this function fails -// (otherwise unchanges) -// -// bAuto - Ask pInputPin if it can block in Receive by calling -// its ReceiveCanBlock method and create a thread if -// it can block, otherwise not. -// -// bQueue - if bAuto == FALSE then we create a thread if and only -// if bQueue == TRUE -// -// lBatchSize - work in batches of lBatchSize -// -// bBatchEact - Use exact batch sizes so don't send until the -// batch is full or SendAnyway() is called -// -// lListSize - If we create a thread make the list of samples queued -// to the thread have this size cache -// -// dwPriority - If we create a thread set its priority to this -// -COutputQueue::COutputQueue( - IPin *pInputPin, // Pin to send stuff to - __inout HRESULT *phr, // 'Return code' - BOOL bAuto, // Ask pin if queue or not - BOOL bQueue, // Send through queue - LONG lBatchSize, // Batch - BOOL bBatchExact, // Batch exactly to BatchSize - LONG lListSize, - DWORD dwPriority, - bool bFlushingOpt // flushing optimization - ) : m_lBatchSize(lBatchSize), - m_bBatchExact(bBatchExact && (lBatchSize > 1)), - m_hThread(NULL), - m_hSem(NULL), - m_List(NULL), - m_pPin(pInputPin), - m_ppSamples(NULL), - m_lWaiting(0), - m_evFlushComplete(FALSE, phr), - m_pInputPin(NULL), - m_bSendAnyway(FALSE), - m_nBatched(0), - m_bFlushing(FALSE), - m_bFlushed(TRUE), - m_bFlushingOpt(bFlushingOpt), - m_bTerminate(FALSE), - m_hEventPop(NULL), - m_hr(S_OK) -{ - ASSERT(m_lBatchSize > 0); - - - if (FAILED(*phr)) { - return; - } - - // Check the input pin is OK and cache its IMemInputPin interface - - *phr = pInputPin->QueryInterface(IID_IMemInputPin, (void **)&m_pInputPin); - if (FAILED(*phr)) { - return; - } - - // See if we should ask the downstream pin - - if (bAuto) { - HRESULT hr = m_pInputPin->ReceiveCanBlock(); - if (SUCCEEDED(hr)) { - bQueue = hr == S_OK; - } - } - - // Create our sample batch - - m_ppSamples = new PMEDIASAMPLE[m_lBatchSize]; - if (m_ppSamples == NULL) { - *phr = E_OUTOFMEMORY; - return; - } - - // If we're queueing allocate resources - - if (bQueue) { - DbgLog((LOG_TRACE, 2, TEXT("Creating thread for output pin"))); - m_hSem = CreateSemaphore(NULL, 0, 0x7FFFFFFF, NULL); - if (m_hSem == NULL) { - DWORD dwError = GetLastError(); - *phr = AmHresultFromWin32(dwError); - return; - } - m_List = new CSampleList(NAME("Sample Queue List"), - lListSize, - FALSE // No lock - ); - if (m_List == NULL) { - *phr = E_OUTOFMEMORY; - return; - } - - - DWORD dwThreadId; - m_hThread = CreateThread(NULL, - 0, - InitialThreadProc, - (LPVOID)this, - 0, - &dwThreadId); - if (m_hThread == NULL) { - DWORD dwError = GetLastError(); - *phr = AmHresultFromWin32(dwError); - return; - } - SetThreadPriority(m_hThread, dwPriority); - } else { - DbgLog((LOG_TRACE, 2, TEXT("Calling input pin directly - no thread"))); - } -} - -// -// COutputQueuee Destructor : -// -// Free all resources - -// -// Thread, -// Batched samples -// -COutputQueue::~COutputQueue() -{ - DbgLog((LOG_TRACE, 3, TEXT("COutputQueue::~COutputQueue"))); - /* Free our pointer */ - if (m_pInputPin != NULL) { - m_pInputPin->Release(); - } - if (m_hThread != NULL) { - { - CAutoLock lck(this); - m_bTerminate = TRUE; - m_hr = S_FALSE; - NotifyThread(); - } - DbgWaitForSingleObject(m_hThread); - EXECUTE_ASSERT(CloseHandle(m_hThread)); - - // The thread frees the samples when asked to terminate - - ASSERT(m_List->GetCount() == 0); - delete m_List; - } else { - FreeSamples(); - } - if (m_hSem != NULL) { - EXECUTE_ASSERT(CloseHandle(m_hSem)); - } - delete [] m_ppSamples; -} - -// -// Call the real thread proc as a member function -// -DWORD WINAPI COutputQueue::InitialThreadProc(__in LPVOID pv) -{ - HRESULT hrCoInit = CAMThread::CoInitializeHelper(); - - COutputQueue *pSampleQueue = (COutputQueue *)pv; - DWORD dwReturn = pSampleQueue->ThreadProc(); - - if(hrCoInit == S_OK) { - CoUninitialize(); - } - - return dwReturn; -} - -// -// Thread sending the samples downstream : -// -// When there is nothing to do the thread sets m_lWaiting (while -// holding the critical section) and then waits for m_hSem to be -// set (not holding the critical section) -// -DWORD COutputQueue::ThreadProc() -{ - while (TRUE) { - BOOL bWait = FALSE; - IMediaSample *pSample; - LONG lNumberToSend; // Local copy - NewSegmentPacket* ppacket; - - // - // Get a batch of samples and send it if possible - // In any case exit the loop if there is a control action - // requested - // - { - CAutoLock lck(this); - while (TRUE) { - - if (m_bTerminate) { - FreeSamples(); - return 0; - } - if (m_bFlushing) { - FreeSamples(); - SetEvent(m_evFlushComplete); - } - - // Get a sample off the list - - pSample = m_List->RemoveHead(); - // inform derived class we took something off the queue - if (m_hEventPop) { - //DbgLog((LOG_TRACE,3,TEXT("Queue: Delivered SET EVENT"))); - SetEvent(m_hEventPop); - } - - if (pSample != NULL && - !IsSpecialSample(pSample)) { - - // If its just a regular sample just add it to the batch - // and exit the loop if the batch is full - - m_ppSamples[m_nBatched++] = pSample; - if (m_nBatched == m_lBatchSize) { - break; - } - } else { - - // If there was nothing in the queue and there's nothing - // to send (either because there's nothing or the batch - // isn't full) then prepare to wait - - if (pSample == NULL && - (m_bBatchExact || m_nBatched == 0)) { - - // Tell other thread to set the event when there's - // something do to - - ASSERT(m_lWaiting == 0); - m_lWaiting++; - bWait = TRUE; - } else { - - // We break out of the loop on SEND_PACKET unless - // there's nothing to send - - if (pSample == SEND_PACKET && m_nBatched == 0) { - continue; - } - - if (pSample == NEW_SEGMENT) { - // now we need the parameters - we are - // guaranteed that the next packet contains them - ppacket = (NewSegmentPacket *) m_List->RemoveHead(); - // we took something off the queue - if (m_hEventPop) { - //DbgLog((LOG_TRACE,3,TEXT("Queue: Delivered SET EVENT"))); - SetEvent(m_hEventPop); - } - - ASSERT(ppacket); - } - // EOS_PACKET falls through here and we exit the loop - // In this way it acts like SEND_PACKET - } - break; - } - } - if (!bWait) { - // We look at m_nBatched from the client side so keep - // it up to date inside the critical section - lNumberToSend = m_nBatched; // Local copy - m_nBatched = 0; - } - } - - // Wait for some more data - - if (bWait) { - DbgWaitForSingleObject(m_hSem); - continue; - } - - - - // OK - send it if there's anything to send - // We DON'T check m_bBatchExact here because either we've got - // a full batch or we dropped through because we got - // SEND_PACKET or EOS_PACKET - both of which imply we should - // flush our batch - - if (lNumberToSend != 0) { - long nProcessed; - if (m_hr == S_OK) { - ASSERT(!m_bFlushed); - HRESULT hr = m_pInputPin->ReceiveMultiple(m_ppSamples, - lNumberToSend, - &nProcessed); - /* Don't overwrite a flushing state HRESULT */ - CAutoLock lck(this); - if (m_hr == S_OK) { - m_hr = hr; - } - ASSERT(!m_bFlushed); - } - while (lNumberToSend != 0) { - m_ppSamples[--lNumberToSend]->Release(); - } - if (m_hr != S_OK) { - - // In any case wait for more data - S_OK just - // means there wasn't an error - - DbgLog((LOG_ERROR, 2, TEXT("ReceiveMultiple returned %8.8X"), - m_hr)); - } - } - - // Check for end of stream - - if (pSample == EOS_PACKET) { - - // We don't send even end of stream on if we've previously - // returned something other than S_OK - // This is because in that case the pin which returned - // something other than S_OK should have either sent - // EndOfStream() or notified the filter graph - - if (m_hr == S_OK) { - DbgLog((LOG_TRACE, 2, TEXT("COutputQueue sending EndOfStream()"))); - HRESULT hr = m_pPin->EndOfStream(); - if (FAILED(hr)) { - DbgLog((LOG_ERROR, 2, TEXT("COutputQueue got code 0x%8.8X from EndOfStream()"))); - } - } - } - - // Data from a new source - - if (pSample == RESET_PACKET) { - m_hr = S_OK; - SetEvent(m_evFlushComplete); - } - - if (pSample == NEW_SEGMENT) { - m_pPin->NewSegment(ppacket->tStart, ppacket->tStop, ppacket->dRate); - delete ppacket; - } - } -} - -// Send batched stuff anyway -void COutputQueue::SendAnyway() -{ - if (!IsQueued()) { - - // m_bSendAnyway is a private parameter checked in ReceiveMultiple - - m_bSendAnyway = TRUE; - LONG nProcessed; - ReceiveMultiple(NULL, 0, &nProcessed); - m_bSendAnyway = FALSE; - - } else { - CAutoLock lck(this); - QueueSample(SEND_PACKET); - NotifyThread(); - } -} - -void -COutputQueue::NewSegment( - REFERENCE_TIME tStart, - REFERENCE_TIME tStop, - double dRate) -{ - if (!IsQueued()) { - if (S_OK == m_hr) { - if (m_bBatchExact) { - SendAnyway(); - } - m_pPin->NewSegment(tStart, tStop, dRate); - } - } else { - if (m_hr == S_OK) { - // - // we need to queue the new segment to appear in order in the - // data, but we need to pass parameters to it. Rather than - // take the hit of wrapping every single sample so we can tell - // special ones apart, we queue special pointers to indicate - // special packets, and we guarantee (by holding the - // critical section) that the packet immediately following a - // NEW_SEGMENT value is a NewSegmentPacket containing the - // parameters. - NewSegmentPacket * ppack = new NewSegmentPacket; - if (ppack == NULL) { - return; - } - ppack->tStart = tStart; - ppack->tStop = tStop; - ppack->dRate = dRate; - - CAutoLock lck(this); - QueueSample(NEW_SEGMENT); - QueueSample( (IMediaSample*) ppack); - NotifyThread(); - } - } -} - - -// -// End of Stream is queued to output device -// -void COutputQueue::EOS() -{ - CAutoLock lck(this); - if (!IsQueued()) { - if (m_bBatchExact) { - SendAnyway(); - } - if (m_hr == S_OK) { - DbgLog((LOG_TRACE, 2, TEXT("COutputQueue sending EndOfStream()"))); - m_bFlushed = FALSE; - HRESULT hr = m_pPin->EndOfStream(); - if (FAILED(hr)) { - DbgLog((LOG_ERROR, 2, TEXT("COutputQueue got code 0x%8.8X from EndOfStream()"))); - } - } - } else { - if (m_hr == S_OK) { - m_bFlushed = FALSE; - QueueSample(EOS_PACKET); - NotifyThread(); - } - } -} - -// -// Flush all the samples in the queue -// -void COutputQueue::BeginFlush() -{ - if (IsQueued()) { - { - CAutoLock lck(this); - - // block receives -- we assume this is done by the - // filter in which we are a component - - // discard all queued data - - m_bFlushing = TRUE; - - // Make sure we discard all samples from now on - - if (m_hr == S_OK) { - m_hr = S_FALSE; - } - - // Optimize so we don't keep calling downstream all the time - - if (m_bFlushed && m_bFlushingOpt) { - return; - } - - // Make sure we really wait for the flush to complete - m_evFlushComplete.Reset(); - - NotifyThread(); - } - - // pass this downstream - - m_pPin->BeginFlush(); - } else { - // pass downstream first to avoid deadlocks - m_pPin->BeginFlush(); - CAutoLock lck(this); - // discard all queued data - - m_bFlushing = TRUE; - - // Make sure we discard all samples from now on - - if (m_hr == S_OK) { - m_hr = S_FALSE; - } - } - -} - -// -// leave flush mode - pass this downstream -void COutputQueue::EndFlush() -{ - { - CAutoLock lck(this); - ASSERT(m_bFlushing); - if (m_bFlushingOpt && m_bFlushed && IsQueued()) { - m_bFlushing = FALSE; - m_hr = S_OK; - return; - } - } - - // sync with pushing thread -- done in BeginFlush - // ensure no more data to go downstream -- done in BeginFlush - // - // Because we are synching here there is no need to hold the critical - // section (in fact we'd deadlock if we did!) - - if (IsQueued()) { - m_evFlushComplete.Wait(); - } else { - FreeSamples(); - } - - // Be daring - the caller has guaranteed no samples will arrive - // before EndFlush() returns - - m_bFlushing = FALSE; - m_bFlushed = TRUE; - - // call EndFlush on downstream pins - - m_pPin->EndFlush(); - - m_hr = S_OK; -} - -// COutputQueue::QueueSample -// -// private method to Send a sample to the output queue -// The critical section MUST be held when this is called - -void COutputQueue::QueueSample(IMediaSample *pSample) -{ - if (NULL == m_List->AddTail(pSample)) { - if (!IsSpecialSample(pSample)) { - pSample->Release(); - } - } -} - -// -// COutputQueue::Receive() -// -// Send a single sample by the multiple sample route -// (NOTE - this could be optimized if necessary) -// -// On return the sample will have been Release()'d -// - -HRESULT COutputQueue::Receive(IMediaSample *pSample) -{ - LONG nProcessed; - return ReceiveMultiple(&pSample, 1, &nProcessed); -} - -// -// COutputQueue::ReceiveMultiple() -// -// Send a set of samples to the downstream pin -// -// ppSamples - array of samples -// nSamples - how many -// nSamplesProcessed - How many were processed -// -// On return all samples will have been Release()'d -// - -HRESULT COutputQueue::ReceiveMultiple ( - __in_ecount(nSamples) IMediaSample **ppSamples, - long nSamples, - __out long *nSamplesProcessed) -{ - if (nSamples < 0) { - return E_INVALIDARG; - } - - CAutoLock lck(this); - // Either call directly or queue up the samples - - if (!IsQueued()) { - - // If we already had a bad return code then just return - - if (S_OK != m_hr) { - - // If we've never received anything since the last Flush() - // and the sticky return code is not S_OK we must be - // flushing - // ((!A || B) is equivalent to A implies B) - ASSERT(!m_bFlushed || m_bFlushing); - - // We're supposed to Release() them anyway! - *nSamplesProcessed = 0; - for (int i = 0; i < nSamples; i++) { - DbgLog((LOG_TRACE, 3, TEXT("COutputQueue (direct) : Discarding %d samples code 0x%8.8X"), - nSamples, m_hr)); - ppSamples[i]->Release(); - } - - return m_hr; - } - // - // If we're flushing the sticky return code should be S_FALSE - // - ASSERT(!m_bFlushing); - m_bFlushed = FALSE; - - ASSERT(m_nBatched < m_lBatchSize); - ASSERT(m_nBatched == 0 || m_bBatchExact); - - // Loop processing the samples in batches - - LONG iLost = 0; - long iDone = 0; - for (iDone = 0; - iDone < nSamples || (m_nBatched != 0 && m_bSendAnyway); - ) { - -//pragma message (REMIND("Implement threshold scheme")) - ASSERT(m_nBatched < m_lBatchSize); - if (iDone < nSamples) { - m_ppSamples[m_nBatched++] = ppSamples[iDone++]; - } - if (m_nBatched == m_lBatchSize || - nSamples == 0 && (m_bSendAnyway || !m_bBatchExact)) { - LONG nDone; - DbgLog((LOG_TRACE, 4, TEXT("Batching %d samples"), - m_nBatched)); - - if (m_hr == S_OK) { - m_hr = m_pInputPin->ReceiveMultiple(m_ppSamples, - m_nBatched, - &nDone); - } else { - nDone = 0; - } - iLost += m_nBatched - nDone; - for (LONG i = 0; i < m_nBatched; i++) { - m_ppSamples[i]->Release(); - } - m_nBatched = 0; - } - } - *nSamplesProcessed = iDone - iLost; - if (*nSamplesProcessed < 0) { - *nSamplesProcessed = 0; - } - return m_hr; - } else { - /* We're sending to our thread */ - - if (m_hr != S_OK) { - *nSamplesProcessed = 0; - DbgLog((LOG_TRACE, 3, TEXT("COutputQueue (queued) : Discarding %d samples code 0x%8.8X"), - nSamples, m_hr)); - for (int i = 0; i < nSamples; i++) { - ppSamples[i]->Release(); - } - return m_hr; - } - m_bFlushed = FALSE; - for (long i = 0; i < nSamples; i++) { - QueueSample(ppSamples[i]); - } - *nSamplesProcessed = nSamples; - if (!m_bBatchExact || - m_nBatched + m_List->GetCount() >= m_lBatchSize) { - NotifyThread(); - } - return S_OK; - } -} - -// Get ready for new data - cancels sticky m_hr -void COutputQueue::Reset() -{ - if (!IsQueued()) { - m_hr = S_OK; - } else { - { - CAutoLock lck(this); - QueueSample(RESET_PACKET); - NotifyThread(); - } - m_evFlushComplete.Wait(); - } -} - -// Remove and Release() all queued and Batched samples -void COutputQueue::FreeSamples() -{ - CAutoLock lck(this); - if (IsQueued()) { - while (TRUE) { - IMediaSample *pSample = m_List->RemoveHead(); - // inform derived class we took something off the queue - if (m_hEventPop) { - //DbgLog((LOG_TRACE,3,TEXT("Queue: Delivered SET EVENT"))); - SetEvent(m_hEventPop); - } - - if (pSample == NULL) { - break; - } - if (!IsSpecialSample(pSample)) { - pSample->Release(); - } else { - if (pSample == NEW_SEGMENT) { - // Free NEW_SEGMENT packet - NewSegmentPacket *ppacket = - (NewSegmentPacket *) m_List->RemoveHead(); - // inform derived class we took something off the queue - if (m_hEventPop) { - //DbgLog((LOG_TRACE,3,TEXT("Queue: Delivered SET EVENT"))); - SetEvent(m_hEventPop); - } - - ASSERT(ppacket != NULL); - delete ppacket; - } - } - } - } - for (int i = 0; i < m_nBatched; i++) { - m_ppSamples[i]->Release(); - } - m_nBatched = 0; -} - -// Notify the thread if there is something to do -// -// The critical section MUST be held when this is called -void COutputQueue::NotifyThread() -{ - // Optimize - no need to signal if it's not waiting - ASSERT(IsQueued()); - if (m_lWaiting) { - ReleaseSemaphore(m_hSem, m_lWaiting, NULL); - m_lWaiting = 0; - } -} - -// See if there's any work to do -// Returns -// TRUE if there is nothing on the queue and nothing in the batch -// and all data has been sent -// FALSE otherwise -// -BOOL COutputQueue::IsIdle() -{ - CAutoLock lck(this); - - // We're idle if - // there is no thread (!IsQueued()) OR - // the thread is waiting for more work (m_lWaiting != 0) - // AND - // there's nothing in the current batch (m_nBatched == 0) - - if (IsQueued() && m_lWaiting == 0 || m_nBatched != 0) { - return FALSE; - } else { - - // If we're idle it shouldn't be possible for there - // to be anything on the work queue - - ASSERT(!IsQueued() || m_List->GetCount() == 0); - return TRUE; - } -} - - -void COutputQueue::SetPopEvent(HANDLE hEvent) -{ - m_hEventPop = hEvent; -} diff --git a/third_party/BaseClasses/outputq.h b/third_party/BaseClasses/outputq.h deleted file mode 100644 index db3d4243..00000000 --- a/third_party/BaseClasses/outputq.h +++ /dev/null @@ -1,137 +0,0 @@ -//------------------------------------------------------------------------------ -// File: OutputQ.h -// -// Desc: DirectShow base classes - defines the COutputQueue class, which -// makes a queue of samples and sends them to an output pin. The -// class will optionally send the samples to the pin directly. -// -// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. -//------------------------------------------------------------------------------ - - -typedef CGenericList CSampleList; - -class COutputQueue : public CCritSec -{ -public: - // Constructor - COutputQueue(IPin *pInputPin, // Pin to send stuff to - __inout HRESULT *phr, // 'Return code' - BOOL bAuto = TRUE, // Ask pin if blocks - BOOL bQueue = TRUE, // Send through queue (ignored if - // bAuto set) - LONG lBatchSize = 1, // Batch - BOOL bBatchExact = FALSE,// Batch exactly to BatchSize - LONG lListSize = // Likely number in the list - DEFAULTCACHE, - DWORD dwPriority = // Priority of thread to create - THREAD_PRIORITY_NORMAL, - bool bFlushingOpt = false // flushing optimization - ); - ~COutputQueue(); - - // enter flush state - discard all data - void BeginFlush(); // Begin flushing samples - - // re-enable receives (pass this downstream) - void EndFlush(); // Complete flush of samples - downstream - // pin guaranteed not to block at this stage - - void EOS(); // Call this on End of stream - - void SendAnyway(); // Send batched samples anyway (if bBatchExact set) - - void NewSegment( - REFERENCE_TIME tStart, - REFERENCE_TIME tStop, - double dRate); - - HRESULT Receive(IMediaSample *pSample); - - // do something with these media samples - HRESULT ReceiveMultiple ( - __in_ecount(nSamples) IMediaSample **pSamples, - long nSamples, - __out long *nSamplesProcessed); - - void Reset(); // Reset m_hr ready for more data - - // See if its idle or not - BOOL IsIdle(); - - // give the class an event to fire after everything removed from the queue - void SetPopEvent(HANDLE hEvent); - -protected: - static DWORD WINAPI InitialThreadProc(__in LPVOID pv); - DWORD ThreadProc(); - BOOL IsQueued() - { - return m_List != NULL; - }; - - // The critical section MUST be held when this is called - void QueueSample(IMediaSample *pSample); - - BOOL IsSpecialSample(IMediaSample *pSample) - { - return (DWORD_PTR)pSample > (DWORD_PTR)(LONG_PTR)(-16); - }; - - // Remove and Release() batched and queued samples - void FreeSamples(); - - // Notify the thread there is something to do - void NotifyThread(); - - -protected: - // Queue 'messages' - #define SEND_PACKET ((IMediaSample *)(LONG_PTR)(-2)) // Send batch - #define EOS_PACKET ((IMediaSample *)(LONG_PTR)(-3)) // End of stream - #define RESET_PACKET ((IMediaSample *)(LONG_PTR)(-4)) // Reset m_hr - #define NEW_SEGMENT ((IMediaSample *)(LONG_PTR)(-5)) // send NewSegment - - // new segment packet is always followed by one of these - struct NewSegmentPacket { - REFERENCE_TIME tStart; - REFERENCE_TIME tStop; - double dRate; - }; - - // Remember input stuff - IPin * const m_pPin; - IMemInputPin * m_pInputPin; - BOOL const m_bBatchExact; - LONG const m_lBatchSize; - - CSampleList * m_List; - HANDLE m_hSem; - CAMEvent m_evFlushComplete; - HANDLE m_hThread; - __field_ecount_opt(m_lBatchSize) IMediaSample ** m_ppSamples; - __range(0, m_lBatchSize) LONG m_nBatched; - - // Wait optimization - LONG m_lWaiting; - // Flush synchronization - BOOL m_bFlushing; - - // flushing optimization. some downstream filters have trouble - // with the queue's flushing optimization. other rely on it - BOOL m_bFlushed; - bool m_bFlushingOpt; - - // Terminate now - BOOL m_bTerminate; - - // Send anyway flag for batching - BOOL m_bSendAnyway; - - // Deferred 'return code' - HRESULT volatile m_hr; - - // an event that can be fired after every deliver - HANDLE m_hEventPop; -}; - diff --git a/third_party/BaseClasses/perflog.cpp b/third_party/BaseClasses/perflog.cpp deleted file mode 100644 index e6425387..00000000 --- a/third_party/BaseClasses/perflog.cpp +++ /dev/null @@ -1,347 +0,0 @@ -//------------------------------------------------------------------------------ -// File: perflog.cpp -// -// Desc: Macros for DirectShow performance logging. -// -// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. -//------------------------------------------------------------------------------ - -#pragma warning (disable:4201) - -#include -#include -#include -#include -#include -#include -#include -#include "perflog.h" - -// -// Local function prototypes. -// - -ULONG -WINAPI -PerflogCallback ( - WMIDPREQUESTCODE RequestCode, - __in PVOID Context, - __out ULONG* BufferSize, - __in PVOID Buffer - ); - -// -// Event tracing function pointers. -// We have to do this to run on down-level platforms. -// - -#ifdef UNICODE - -ULONG -(__stdcall * _RegisterTraceGuids) ( - __in IN WMIDPREQUEST RequestAddress, - __in IN PVOID RequestContext, - IN LPCGUID ControlGuid, - IN ULONG GuidCount, - __in IN PTRACE_GUID_REGISTRATION TraceGuidReg, - IN LPCWSTR MofImagePath, - IN LPCWSTR MofResourceName, - OUT PTRACEHANDLE RegistrationHandle - ); - -#define REGISTERTRACEGUIDS_NAME "RegisterTraceGuidsW" - -#else - -ULONG -(__stdcall * _RegisterTraceGuids) ( - __in IN WMIDPREQUEST RequestAddress, - __in IN PVOID RequestContext, - IN LPCGUID ControlGuid, - IN ULONG GuidCount, - __in IN PTRACE_GUID_REGISTRATION TraceGuidReg, - IN LPCSTR MofImagePath, - IN LPCSTR MofResourceName, - __out OUT PTRACEHANDLE RegistrationHandle - ); - -#define REGISTERTRACEGUIDS_NAME "RegisterTraceGuidsA" - -#endif - -ULONG -(__stdcall * _UnregisterTraceGuids) ( - TRACEHANDLE RegistrationHandle - ); - -TRACEHANDLE -(__stdcall * _GetTraceLoggerHandle) ( - __in PVOID Buffer - ); - -UCHAR -(__stdcall * _GetTraceEnableLevel) ( - TRACEHANDLE TraceHandle - ); - -ULONG -(__stdcall * _GetTraceEnableFlags) ( - TRACEHANDLE TraceHandle - ); - -ULONG -(__stdcall * _TraceEvent) ( - TRACEHANDLE TraceHandle, - __in PEVENT_TRACE_HEADER EventTrace - ); - -HINSTANCE _Advapi32; - -// -// Global variables. -// - -BOOL EventTracingAvailable=FALSE; -ULONG PerflogEnableFlags; -UCHAR PerflogEnableLevel; -ULONG PerflogModuleLevel = 0; -void (*OnStateChanged)(void); -TRACEHANDLE PerflogTraceHandle=NULL; -TRACEHANDLE PerflogRegHandle; - -// 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 - -// -// This routine initializes performance logging. -// It should be called from DllMain(). -// - - -VOID -PerflogReadModuleLevel( - HINSTANCE hInstance - ) -{ - LONG lReturn; // Create key return value - TCHAR szInfo[iDEBUGINFO]; // Constructs key names - TCHAR szFullName[iDEBUGINFO]; // Load the full path and module name - HKEY hModuleKey; // Module key handle - LPTSTR pName; // Searches from the end for a backslash - DWORD dwKeySize, dwKeyType, dwKeyValue; - - DWORD dwSize = GetModuleFileName( - (hInstance ? hInstance : GetModuleHandle( NULL )), - szFullName, - iDEBUGINFO ); - - if (0 == dwSize || iDEBUGINFO == dwSize) { - return; - } - - pName = _tcsrchr(szFullName,'\\'); - if (pName == NULL) { - pName = szFullName; - } else { - pName++; - } - - /* Construct the base key name */ - (void)StringCchPrintf(szInfo,NUMELMS(szInfo),TEXT("SOFTWARE\\Debug\\%s"),pName); - - /* Open the key for this module */ - lReturn = - RegOpenKeyEx( - HKEY_LOCAL_MACHINE, // Handle of an open key - szInfo, // Address of subkey name - (DWORD) 0, // Reserved value - KEY_QUERY_VALUE, // Desired security access - &hModuleKey ); // Opened handle buffer - - if (lReturn != ERROR_SUCCESS) { - return; - } - - dwKeySize = sizeof(DWORD); - lReturn = RegQueryValueEx( - hModuleKey, // Handle to an open key - TEXT("PERFLOG"), - NULL, // Reserved field - &dwKeyType, // Returns the field type - (LPBYTE) &dwKeyValue, // Returns the field's value - &dwKeySize ); // Number of bytes transferred - - if ((lReturn == ERROR_SUCCESS) && (dwKeyType == REG_DWORD)) - { - PerflogModuleLevel = dwKeyValue; - } - - RegCloseKey(hModuleKey); -} - -BOOL PerflogInitIfEnabled( - IN HINSTANCE hInstance, - __in IN PPERFLOG_LOGGING_PARAMS LogParams - ) -{ - PerflogReadModuleLevel( hInstance ); - if (PerflogModuleLevel) - { - return PerflogInitialize( LogParams ); - } - else - { - return FALSE; - } -} - -BOOL -PerflogInitialize ( - __in IN PPERFLOG_LOGGING_PARAMS LogParams - ) -{ - ULONG status; - - // - // If we're running on a recent-enough platform, this will get - // pointers to the event tracing routines. - // - - _Advapi32 = GetModuleHandle (_T("ADVAPI32.DLL")); - if (_Advapi32 == NULL) { - return FALSE; - } - - *((FARPROC*) &_RegisterTraceGuids) = GetProcAddress (_Advapi32, REGISTERTRACEGUIDS_NAME); - *((FARPROC*) &_UnregisterTraceGuids) = GetProcAddress (_Advapi32, "UnregisterTraceGuids"); - *((FARPROC*) &_GetTraceLoggerHandle) = GetProcAddress (_Advapi32, "GetTraceLoggerHandle"); - *((FARPROC*) &_GetTraceEnableLevel) = GetProcAddress (_Advapi32, "GetTraceEnableLevel"); - *((FARPROC*) &_GetTraceEnableFlags) = GetProcAddress (_Advapi32, "GetTraceEnableFlags"); - *((FARPROC*) &_TraceEvent) = GetProcAddress (_Advapi32, "TraceEvent"); - - if (_RegisterTraceGuids == NULL || - _UnregisterTraceGuids == NULL || - _GetTraceEnableLevel == NULL || - _GetTraceEnableFlags == NULL || - _TraceEvent == NULL) { - - return FALSE; - } - - EventTracingAvailable = TRUE; - - OnStateChanged = LogParams->OnStateChanged; - - // - // Register our GUIDs. - // - - status = _RegisterTraceGuids (PerflogCallback, - LogParams, - &LogParams->ControlGuid, - LogParams->NumberOfTraceGuids, - LogParams->TraceGuids, - NULL, - NULL, - &PerflogRegHandle); - - return (status == ERROR_SUCCESS); -} - -// -// This routine shuts down performance logging. -// - -VOID -PerflogShutdown ( - VOID - ) -{ - if (!EventTracingAvailable) { - return; - } - - _UnregisterTraceGuids (PerflogRegHandle); - PerflogRegHandle = NULL; - PerflogTraceHandle = NULL; -} - -// -// Event tracing callback routine. -// It's called when controllers call event tracing control functions. -// - -ULONG -WINAPI -PerflogCallback ( - WMIDPREQUESTCODE RequestCode, - __in PVOID Context, - __out ULONG* BufferSize, - __in PVOID Buffer - ) -{ - ULONG status; - - UNREFERENCED_PARAMETER (Context); - - ASSERT (EventTracingAvailable); - - status = ERROR_SUCCESS; - - switch (RequestCode) { - - case WMI_ENABLE_EVENTS: - PerflogTraceHandle = _GetTraceLoggerHandle (Buffer); - PerflogEnableFlags = _GetTraceEnableFlags (PerflogTraceHandle); - PerflogEnableLevel = _GetTraceEnableLevel (PerflogTraceHandle); - break; - - case WMI_DISABLE_EVENTS: - PerflogTraceHandle = NULL; - PerflogEnableFlags = 0; - PerflogEnableLevel = 0; - break; - - default: - status = ERROR_INVALID_PARAMETER; - } - - if (OnStateChanged != NULL) { - OnStateChanged(); - } - - *BufferSize = 0; - return status; -} - -// -// Logging routine. -// - -VOID -PerflogTraceEvent ( - __in PEVENT_TRACE_HEADER Event - ) -{ - if (!EventTracingAvailable) { - return; - } - - _TraceEvent (PerflogTraceHandle, Event); -} - -VOID -PerflogTraceEventLevel( - ULONG Level, - __in PEVENT_TRACE_HEADER Event - ) -{ - if ((!EventTracingAvailable) || (Level <= PerflogModuleLevel)) { - return; - } - - _TraceEvent (PerflogTraceHandle, Event); -} - - diff --git a/third_party/BaseClasses/perflog.h b/third_party/BaseClasses/perflog.h deleted file mode 100644 index 503a1304..00000000 --- a/third_party/BaseClasses/perflog.h +++ /dev/null @@ -1,56 +0,0 @@ -//------------------------------------------------------------------------------ -// File: perflog.h -// -// Desc: Performance logging framework. -// -// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. -//------------------------------------------------------------------------------ - -typedef struct _PERFLOG_LOGGING_PARAMS { - GUID ControlGuid; - void (*OnStateChanged)(void); - ULONG NumberOfTraceGuids; - TRACE_GUID_REGISTRATION TraceGuids[ANYSIZE_ARRAY]; -} PERFLOG_LOGGING_PARAMS, *PPERFLOG_LOGGING_PARAMS; - -BOOL -PerflogInitIfEnabled( - IN HINSTANCE hInstance, - __in PPERFLOG_LOGGING_PARAMS LogParams - ); - -BOOL -PerflogInitialize ( - __in PPERFLOG_LOGGING_PARAMS LogParams - ); - -VOID -PerflogShutdown ( - VOID - ); - -VOID -PerflogTraceEvent ( - __in PEVENT_TRACE_HEADER Event - ); - -extern ULONG PerflogEnableFlags; -extern UCHAR PerflogEnableLevel; -extern ULONG PerflogModuleLevel; -extern TRACEHANDLE PerflogTraceHandle; -extern TRACEHANDLE PerflogRegHandle; - -#define PerflogTracingEnabled() (PerflogTraceHandle != 0) - -#define PerflogEvent( _x_ ) PerflogTraceEventLevel _x_ - -VOID -PerflogTraceEventLevel( - ULONG Level, - __in PEVENT_TRACE_HEADER Event - ); - -VOID -PerflogTraceEvent ( - __in PEVENT_TRACE_HEADER Event - ); diff --git a/third_party/BaseClasses/perfstruct.h b/third_party/BaseClasses/perfstruct.h deleted file mode 100644 index 9c67b738..00000000 --- a/third_party/BaseClasses/perfstruct.h +++ /dev/null @@ -1,194 +0,0 @@ -//------------------------------------------------------------------------------ -// File: PerfStruct.h -// -// Desc: Structures for DirectShow performance logging. -// -// Copyright (c) 2000-2001 Microsoft Corporation. All rights reserved. -//------------------------------------------------------------------------------ - - -#ifndef _PERFSTRUCT_H_ -#define _PERFSTRUCT_H_ - -#include -#include - -// {28CF047A-2437-4b24-B653-B9446A419A69} -DEFINE_GUID(GUID_DSHOW_CTL, -0x28cf047a, 0x2437, 0x4b24, 0xb6, 0x53, 0xb9, 0x44, 0x6a, 0x41, 0x9a, 0x69); - -// {D0DA7AD6-AE80-4de5-AAFC-C126711E7593} -DEFINE_GUID(GUID_VIDEOREND, -0xd0da7ad6, 0xae80, 0x4de5, 0xaa, 0xfc, 0xc1, 0x26, 0x71, 0x1e, 0x75, 0x93); - -// {DC70AC3E-93E5-48db-88AB-E42064EC276A} -DEFINE_GUID(GUID_DSOUNDGLITCH, -0xdc70ac3e, 0x93e5, 0x48db, 0x88, 0xab, 0xe4, 0x20, 0x64, 0xec, 0x27, 0x6a); - -// {3d7e7d93-2fc8-4a07-a719-e0922ff2899} -DEFINE_GUID(GUID_STREAMTRACE, -0x3d7e7d93, 0x2fc8, 0x4a07, 0xa7, 0x19, 0xe0, 0x92, 0x2f, 0xf2, 0x89, 0x9e); - -// AZFIX: the following GUIDs aren't useful right now. - -// {3C33F7F5-EE54-493c-BA25-1656539C05AC} -DEFINE_GUID(GUID_GETTIME, -0x3c33f7f5, 0xee54, 0x493c, 0xba, 0x25, 0x16, 0x56, 0x53, 0x9c, 0x5, 0xac); - -// {CC44B44D-8169-4952-9E4A-A4E13295E492} -DEFINE_GUID(GUID_AUDIOREND, -0xcc44b44d, 0x8169, 0x4952, 0x9e, 0x4a, 0xa4, 0xe1, 0x32, 0x95, 0xe4, 0x92); - -// {775D19BF-4D8B-4de6-8DC9-66BAC7B310A2} -DEFINE_GUID(GUID_FRAMEDROP, -0x775d19bf, 0x4d8b, 0x4de6, 0x8d, 0xc9, 0x66, 0xba, 0xc7, 0xb3, 0x10, 0xa2); - -// {56D29065-EFBE-42dc-8C29-E325DC9C27D5} -DEFINE_GUID(GUID_AUDIOBREAK, -0x56d29065, 0xefbe, 0x42dc, 0x8c, 0x29, 0xe3, 0x25, 0xdc, 0x9c, 0x27, 0xd5); - -// {E1E6EA87-95A8-497e-BFBA-0295AEBCC707} -DEFINE_GUID(GUID_AUDIORECV, -0xe1e6ea87, 0x95a8, 0x497e, 0xbf, 0xba, 0x2, 0x95, 0xae, 0xbc, 0xc7, 0x7); - -// {10F7768A-B1E7-4242-AD90-A2D44683D9F0} -DEFINE_GUID(GUID_AUDIOSLAVE, -0x10f7768a, 0xb1e7, 0x4242, 0xad, 0x90, 0xa2, 0xd4, 0x46, 0x83, 0xd9, 0xf0); - -// {8983803D-691A-49bc-8FF6-962A39C0198F} -DEFINE_GUID(GUID_AUDIOADDBREAK, -0x8983803d, 0x691a, 0x49bc, 0x8f, 0xf6, 0x96, 0x2a, 0x39, 0xc0, 0x19, 0x8f); - -#define GLITCHTYPE_DSOUNDFIRSTGOOD 0 -#define GLITCHTYPE_DSOUNDFIRSTBAD 1 - -typedef struct PERFINFO_DSHOW_AUDIOGLITCH { - ULONGLONG cycleCounter; - DWORD glitchType; - LONGLONG sampleTime; - LONGLONG previousTime; - ULONG_PTR instanceId; -} PERFINFO_DSHOW_AUDIOGLITCH, *PPERFINFO_DSHOW_AUDIOGLITCH; - -typedef struct PERFINFO_WMI_AUDIOGLITCH { - EVENT_TRACE_HEADER header; - PERFINFO_DSHOW_AUDIOGLITCH data; -} PERFINFO_WMI_AUDIO_GLITCH, *PPERFINFO_WMI_AUDIOGLITCH; - -typedef struct PERFINFO_DSHOW_GETTIME { - ULONGLONG cycleCounter; - ULONGLONG dshowClock; -} PERFINFO_DSHOW_GETTIME, *PPERFINFO_DSHOW_GETTIME; - -typedef struct PERFINFO_WMI_GETTIME { - EVENT_TRACE_HEADER header; - PERFINFO_DSHOW_GETTIME data; -} PERFINFO_WMI_GETTIME, *PPERFINFO_WMI_GETTIME; - -typedef struct PERFINFO_DSHOW_AVREND { - ULONGLONG cycleCounter; - ULONGLONG dshowClock; - ULONGLONG sampleTime; -} PERFINFO_DSHOW_AVREND, *PPERFINFO_DSHOW_AVREND; - -typedef struct PERFINFO_WMI_AVREND { - EVENT_TRACE_HEADER header; - PERFINFO_DSHOW_AVREND data; -} PERFINFO_WMI_AVREND, *PPERFINFO_WMI_AVREND; - -typedef struct PERFINFO_DSHOW_AUDIOBREAK { - ULONGLONG cycleCounter; - ULONGLONG dshowClock; - ULONGLONG sampleTime; - ULONGLONG sampleDuration; -} PERFINFO_DSHOW_AUDIOBREAK, *PPERFINFO_DSHOW_AUDIOBREAK; - -typedef struct PERFINFO_WMI_AUDIOBREAK { - EVENT_TRACE_HEADER header; - PERFINFO_DSHOW_AUDIOBREAK data; -} PERFINFO_WMI_AUDIOBREAK, *PPERFINFO_WMI_AUDIOBREAK; - -typedef struct PERFINFO_DSHOW_FRAMEDROP { - ULONGLONG cycleCounter; - ULONGLONG dshowClock; - ULONGLONG frameTime; -} PERFINFO_DSHOW_FRAMEDROP, *PPERFINFO_DSHOW_FRAMEDROP; - -typedef struct PERFINFO_WMI_FRAMEDROP { - EVENT_TRACE_HEADER header; - PERFINFO_DSHOW_FRAMEDROP data; -} PERFINFO_WMI_FRAMEDROP, *PPERFINFO_WMI_FRAMEDROP; - -#define PERFINFO_STREAMTRACE_MPEG2DEMUX_PTS_TRANSLATION 1 -#define PERFINFO_STREAMTRACE_MPEG2DEMUX_SAMPLE_RECEIVED 2 -#define PERFINFO_STREAMTRACE_VMR_BEGIN_ADVISE 3 -#define PERFINFO_STREAMTRACE_VMR_END_ADVISE 4 -#define PERFINFO_STREAMTRACE_VMR_RECEIVE 5 -#define PERFINFO_STREAMTRACE_VMR_BEGIN_DEINTERLACE 6 -#define PERFINFO_STREAMTRACE_VMR_END_DEINTERLACE 7 -#define PERFINFO_STREAMTRACE_VMR_BEGIN_DECODE 8 -#define PERFINFO_STREAMTRACE_VMR_END_DECODE 9 -#define PERFINFO_STREAMTRACE_VMR_DROPPED_FRAME 10 -#define PERFINFO_STREAMTRACE_ENCDEC_DTFILTERINPUT 11 -#define PERFINFO_STREAMTRACE_ENCDEC_DTFILTEROUTPUT 12 -#define PERFINFO_STREAMTRACE_ENCDEC_ETFILTERINPUT 13 -#define PERFINFO_STREAMTRACE_ENCDEC_ETFILTEROUTPUT 14 -#define PERFINFO_STREAMTRACE_ENCDEC_XDSCODECINPUT 15 -#define PERFINFO_STREAMTRACE_SBE_DVRANALYSISINPUT_RECEIVE 16 -#define PERFINFO_STREAMTRACE_SBE_DVRANALYSISINPUT_DELIVER 17 -#define PERFINFO_STREAMTRACE_SBE_DVRINPUTPIN_RECEIVE 18 -#define PERFINFO_STREAMTRACE_SBE_DVROUTPUTPIN_RECEIVE 19 -#define PERFINFO_STREAMTRACE_VMR_RENDER_TIME 20 - -typedef struct _PERFINFO_DSHOW_STREAMTRACE { - ULONG id; - ULONG reserved; - ULONGLONG dshowClock; - ULONGLONG data[ 4 ]; -} PERFINFO_DSHOW_STREAMTRACE, *PPERFINFO_DSHOW_STREAMTRACE; - -typedef struct _PERFINFO_WMI_STREAMTRACE { - EVENT_TRACE_HEADER header; - PERFINFO_DSHOW_STREAMTRACE data; -} PERFINFO_WMI_STREAMTRACE, *PPERFINFO_WMI_STREAMTRACE; - - -typedef struct PERFINFO_DSHOW_AUDIORECV { - LONGLONG streamTime ; - LONGLONG sampleStart ; - LONGLONG sampleStop ; - LONGLONG hwduration ; - BOOL discontinuity ; -} PERFINFO_DSHOW_AUDIORECV, *PPERFINFO_DSHOW_AUDIORECV; - -typedef struct PERFINFO_WMI_AUDIORECV { - EVENT_TRACE_HEADER header; - PERFINFO_DSHOW_AUDIORECV data; -} PERFINFO_WMI_AUDIORECV, *PPERFINFO_WMI_AUDIORECV; - -typedef struct PERFINFO_DSHOW_AUDIOSLAVE { - LONGLONG masterClock ; - LONGLONG slaveClock ; - LONGLONG errorAccum ; - LONGLONG lastHighErrorSeen ; - LONGLONG lastLowErrorSeen ; -} PERFINFO_DSHOW_AUDIOSLAVE, *PPERFINFO_DSHOW_AUDIOSLAVE; - -typedef struct PERFINFO_WMI_AUDIOSLAVE { - EVENT_TRACE_HEADER header; - PERFINFO_DSHOW_AUDIOSLAVE data; -} PERFINFO_WMI_AUDIOSLAVE, *PPERFINFO_WMI_AUDIOSLAVE; - -typedef struct PERFINFO_DSHOW_AUDIOADDBREAK { - DWORD iterNextWrite ; - DWORD offsetNextWrite ; - DWORD iterWrite ; - DWORD offsetWrite ; -} PERFINFO_DSHOW_AUDIOADDBREAK, *PPERFINFO_DSHOW_AUDIOADDBREAK; - -typedef struct PERFINFO_WMI_AUDIOADDBREAK { - EVENT_TRACE_HEADER header; - PERFINFO_DSHOW_AUDIOADDBREAK data; -} PERFINFO_WMI_AUDIOADDBREAK, *PPERFINFO_WMI_AUDIOADDBREAK; - -#endif // _PREFSTRUCT_H_ diff --git a/third_party/BaseClasses/pstream.cpp b/third_party/BaseClasses/pstream.cpp deleted file mode 100644 index d20171f5..00000000 --- a/third_party/BaseClasses/pstream.cpp +++ /dev/null @@ -1,197 +0,0 @@ -//------------------------------------------------------------------------------ -// File: PStream.cpp -// -// Desc: DirectShow base classes. -// -// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. -//------------------------------------------------------------------------------ - - -#include -#include - -#ifdef PERF -#include -#endif -// #include "pstream.h" in streams.h - -// -// Constructor -// -CPersistStream::CPersistStream(IUnknown *punk, __inout HRESULT *phr) - : mPS_fDirty(FALSE) -{ - mPS_dwFileVersion = GetSoftwareVersion(); -} - - -// -// Destructor -// -CPersistStream::~CPersistStream() { - // Nothing to do -} - -#if 0 -SAMPLE CODE TO COPY - not active at the moment - -// -// NonDelegatingQueryInterface -// -// This object supports IPersist & IPersistStream -STDMETHODIMP CPersistStream::NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv) -{ - if (riid == IID_IPersist) { - return GetInterface((IPersist *) this, ppv); // ??? - } - else if (riid == IID_IPersistStream) { - return GetInterface((IPersistStream *) this, ppv); - } - else { - return CUnknown::NonDelegatingQueryInterface(riid, ppv); - } -} -#endif - - -// -// WriteToStream -// -// Writes to the stream (default action is to write nothing) -HRESULT CPersistStream::WriteToStream(IStream *pStream) -{ - // You can override this to do things like - // hr = pStream->Write(MyStructure, sizeof(MyStructure), NULL); - - return NOERROR; -} - - - -HRESULT CPersistStream::ReadFromStream(IStream * pStream) -{ - // You can override this to do things like - // hr = pStream->Read(MyStructure, sizeof(MyStructure), NULL); - - return NOERROR; -} - - -// -// Load -// -// Load all the data from the given stream -STDMETHODIMP CPersistStream::Load(LPSTREAM pStm) -{ - HRESULT hr; - // Load the version number then the data - mPS_dwFileVersion = ReadInt(pStm, hr); - if (FAILED(hr)) { - return hr; - } - - return ReadFromStream(pStm); -} // Load - - - -// -// Save -// -// Save the contents of this Stream. -STDMETHODIMP CPersistStream::Save(LPSTREAM pStm, BOOL fClearDirty) -{ - - HRESULT hr = WriteInt(pStm, GetSoftwareVersion()); - if (FAILED(hr)) { - return hr; - } - - hr = WriteToStream(pStm); - if (FAILED(hr)) { - return hr; - } - - mPS_fDirty = !fClearDirty; - - return hr; -} // Save - - -// WriteInt -// -// Writes an integer to an IStream as 11 UNICODE characters followed by one space. -// You could use this for shorts or unsigneds or anything (up to 32 bits) -// where the value isn't actually truncated by squeezing it into 32 bits. -// Values such as (unsigned) 0x80000000 would come out as -2147483648 -// but would then load as 0x80000000 through ReadInt. Cast as you please. - -STDAPI WriteInt(IStream *pIStream, int n) -{ - WCHAR Buff[13]; // Allows for trailing null that we don't write - (void)StringCchPrintfW(Buff, NUMELMS(Buff),L"%011d ",n); - return pIStream->Write(&(Buff[0]), 12*sizeof(WCHAR), NULL); -} // WriteInt - - -// ReadInt -// -// Reads an integer from an IStream. -// Read as 4 bytes. You could use this for shorts or unsigneds or anything -// where the value isn't actually truncated by squeezing it into 32 bits -// Striped down subset of what sscanf can do (without dragging in the C runtime) - -STDAPI_(int) ReadInt(IStream *pIStream, __out HRESULT &hr) -{ - - int Sign = 1; - unsigned int n = 0; // result wil be n*Sign - WCHAR wch; - - hr = pIStream->Read( &wch, sizeof(wch), NULL); - if (FAILED(hr)) { - return 0; - } - - if (wch==L'-'){ - Sign = -1; - hr = pIStream->Read( &wch, sizeof(wch), NULL); - if (FAILED(hr)) { - return 0; - } - } - - for( ; ; ) { - if (wch>=L'0' && wch<=L'9') { - n = 10*n+(int)(wch-L'0'); - } else if ( wch == L' ' - || wch == L'\t' - || wch == L'\r' - || wch == L'\n' - || wch == L'\0' - ) { - break; - } else { - hr = VFW_E_INVALID_FILE_FORMAT; - return 0; - } - - hr = pIStream->Read( &wch, sizeof(wch), NULL); - if (FAILED(hr)) { - return 0; - } - } - - if (n==0x80000000 && Sign==-1) { - // This is the negative number that has no positive version! - return (int)n; - } - else return (int)n * Sign; -} // ReadInt - - -// The microsoft C/C++ compile generates level 4 warnings to the effect that -// a particular inline function (from some base class) was not needed. -// This line gets rid of hundreds of such unwanted messages and makes -// -W4 compilation feasible: -#pragma warning(disable: 4514) diff --git a/third_party/BaseClasses/pstream.h b/third_party/BaseClasses/pstream.h deleted file mode 100644 index 04b6af62..00000000 --- a/third_party/BaseClasses/pstream.h +++ /dev/null @@ -1,114 +0,0 @@ -//------------------------------------------------------------------------------ -// File: PStream.h -// -// Desc: DirectShow base classes - defines a class for persistent properties -// of filters. -// -// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. -//------------------------------------------------------------------------------ - - -#ifndef __PSTREAM__ -#define __PSTREAM__ - -// Base class for persistent properties of filters -// (i.e. filter properties in saved graphs) - -// The simplest way to use this is: -// 1. Arrange for your filter to inherit this class -// 2. Implement in your class WriteToStream and ReadFromStream -// These will override the "do nothing" functions here. -// 3. Change your NonDelegatingQueryInterface to handle IPersistStream -// 4. Implement SizeMax to return the number of bytes of data you save. -// If you save UNICODE data, don't forget a char is 2 bytes. -// 5. Whenever your data changes, call SetDirty() -// -// At some point you may decide to alter, or extend the format of your data. -// At that point you will wish that you had a version number in all the old -// saved graphs, so that you can tell, when you read them, whether they -// represent the old or new form. To assist you in this, this class -// writes and reads a version number. -// When it writes, it calls GetSoftwareVersion() to enquire what version -// of the software we have at the moment. (In effect this is a version number -// of the data layout in the file). It writes this as the first thing in the data. -// If you want to change the version, implement (override) GetSoftwareVersion(). -// It reads this from the file into mPS_dwFileVersion before calling ReadFromStream, -// so in ReadFromStream you can check mPS_dwFileVersion to see if you are reading -// an old version file. -// Normally you should accept files whose version is no newer than the software -// version that's reading them. - - -// CPersistStream -// -// Implements IPersistStream. -// See 'OLE Programmers Reference (Vol 1):Structured Storage Overview' for -// more implementation information. -class CPersistStream : public IPersistStream { - private: - - // Internal state: - - protected: - DWORD mPS_dwFileVersion; // version number of file (being read) - BOOL mPS_fDirty; - - public: - - // IPersistStream methods - - STDMETHODIMP IsDirty() - {return (mPS_fDirty ? S_OK : S_FALSE);} // note FALSE means clean - STDMETHODIMP Load(LPSTREAM pStm); - STDMETHODIMP Save(LPSTREAM pStm, BOOL fClearDirty); - STDMETHODIMP GetSizeMax(__out ULARGE_INTEGER * pcbSize) - // Allow 24 bytes for version. - { pcbSize->QuadPart = 12*sizeof(WCHAR)+SizeMax(); return NOERROR; } - - // implementation - - CPersistStream(IUnknown *punk, __inout HRESULT *phr); - ~CPersistStream(); - - HRESULT SetDirty(BOOL fDirty) - { mPS_fDirty = fDirty; return NOERROR;} - - - // override to reveal IPersist & IPersistStream - // STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv); - - // --- IPersist --- - - // You must override this to provide your own class id - STDMETHODIMP GetClassID(__out CLSID *pClsid) PURE; - - // overrideable if you want - // file version number. Override it if you ever change format - virtual DWORD GetSoftwareVersion(void) { return 0; } - - - //========================================================================= - // OVERRIDE THESE to read and write your data - // OVERRIDE THESE to read and write your data - // OVERRIDE THESE to read and write your data - - virtual int SizeMax() {return 0;} - virtual HRESULT WriteToStream(IStream *pStream); - virtual HRESULT ReadFromStream(IStream *pStream); - //========================================================================= - - private: - -}; - - -// --- Useful helpers --- - - -// Writes an int to an IStream as UNICODE. -STDAPI WriteInt(IStream *pIStream, int n); - -// inverse of WriteInt -STDAPI_(int) ReadInt(IStream *pIStream, __out HRESULT &hr); - -#endif // __PSTREAM__ diff --git a/third_party/BaseClasses/pullpin.cpp b/third_party/BaseClasses/pullpin.cpp deleted file mode 100644 index a197ba58..00000000 --- a/third_party/BaseClasses/pullpin.cpp +++ /dev/null @@ -1,588 +0,0 @@ -//------------------------------------------------------------------------------ -// File: PullPin.cpp -// -// Desc: DirectShow base classes - implements CPullPin class that pulls data -// from IAsyncReader. -// -// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. -//------------------------------------------------------------------------------ - - -#include -#include "pullpin.h" - -#ifdef DXMPERF -#include "dxmperf.h" -#endif // DXMPERF - - -CPullPin::CPullPin() - : m_pReader(NULL), - m_pAlloc(NULL), - m_State(TM_Exit) -{ -#ifdef DXMPERF - PERFLOG_CTOR( L"CPullPin", this ); -#endif // DXMPERF - -} - -CPullPin::~CPullPin() -{ - Disconnect(); - -#ifdef DXMPERF - PERFLOG_DTOR( L"CPullPin", this ); -#endif // DXMPERF - -} - -// returns S_OK if successfully connected to an IAsyncReader interface -// from this object -// Optional allocator should be proposed as a preferred allocator if -// necessary -HRESULT -CPullPin::Connect(IUnknown* pUnk, IMemAllocator* pAlloc, BOOL bSync) -{ - CAutoLock lock(&m_AccessLock); - - if (m_pReader) { - return VFW_E_ALREADY_CONNECTED; - } - - HRESULT hr = pUnk->QueryInterface(IID_IAsyncReader, (void**)&m_pReader); - if (FAILED(hr)) { - -#ifdef DXMPERF - { - AM_MEDIA_TYPE * pmt = NULL; - PERFLOG_CONNECT( this, pUnk, hr, pmt ); - } -#endif // DXMPERF - - return(hr); - } - - hr = DecideAllocator(pAlloc, NULL); - if (FAILED(hr)) { - Disconnect(); - -#ifdef DXMPERF - { - AM_MEDIA_TYPE * pmt = NULL; - PERFLOG_CONNECT( this, pUnk, hr, pmt ); - } -#endif // DXMPERF - - return hr; - } - - LONGLONG llTotal, llAvail; - hr = m_pReader->Length(&llTotal, &llAvail); - if (FAILED(hr)) { - Disconnect(); - -#ifdef DXMPERF - { - AM_MEDIA_TYPE * pmt = NULL; - PERFLOG_CONNECT( this, pUnk, hr, pmt ); - } -#endif - - return hr; - } - - // convert from file position to reference time - m_tDuration = llTotal * UNITS; - m_tStop = m_tDuration; - m_tStart = 0; - - m_bSync = bSync; - -#ifdef DXMPERF - { - AM_MEDIA_TYPE * pmt = NULL; - PERFLOG_CONNECT( this, pUnk, S_OK, pmt ); - } -#endif // DXMPERF - - - return S_OK; -} - -// disconnect any connection made in Connect -HRESULT -CPullPin::Disconnect() -{ - CAutoLock lock(&m_AccessLock); - - StopThread(); - - -#ifdef DXMPERF - PERFLOG_DISCONNECT( this, m_pReader, S_OK ); -#endif // DXMPERF - - - if (m_pReader) { - m_pReader->Release(); - m_pReader = NULL; - } - - if (m_pAlloc) { - m_pAlloc->Release(); - m_pAlloc = NULL; - } - - return S_OK; -} - -// agree an allocator using RequestAllocator - optional -// props param specifies your requirements (non-zero fields). -// returns an error code if fail to match requirements. -// optional IMemAllocator interface is offered as a preferred allocator -// but no error occurs if it can't be met. -HRESULT -CPullPin::DecideAllocator( - IMemAllocator * pAlloc, - __inout_opt ALLOCATOR_PROPERTIES * pProps) -{ - ALLOCATOR_PROPERTIES *pRequest; - ALLOCATOR_PROPERTIES Request; - if (pProps == NULL) { - Request.cBuffers = 3; - Request.cbBuffer = 64*1024; - Request.cbAlign = 0; - Request.cbPrefix = 0; - pRequest = &Request; - } else { - pRequest = pProps; - } - HRESULT hr = m_pReader->RequestAllocator( - pAlloc, - pRequest, - &m_pAlloc); - return hr; -} - -// start pulling data -HRESULT -CPullPin::Active(void) -{ - ASSERT(!ThreadExists()); - return StartThread(); -} - -// stop pulling data -HRESULT -CPullPin::Inactive(void) -{ - StopThread(); - - return S_OK; -} - -HRESULT -CPullPin::Seek(REFERENCE_TIME tStart, REFERENCE_TIME tStop) -{ - CAutoLock lock(&m_AccessLock); - - ThreadMsg AtStart = m_State; - - if (AtStart == TM_Start) { - BeginFlush(); - PauseThread(); - EndFlush(); - } - - m_tStart = tStart; - m_tStop = tStop; - - HRESULT hr = S_OK; - if (AtStart == TM_Start) { - hr = StartThread(); - } - - return hr; -} - -HRESULT -CPullPin::Duration(__out REFERENCE_TIME* ptDuration) -{ - *ptDuration = m_tDuration; - return S_OK; -} - - -HRESULT -CPullPin::StartThread() -{ - CAutoLock lock(&m_AccessLock); - - if (!m_pAlloc || !m_pReader) { - return E_UNEXPECTED; - } - - HRESULT hr; - if (!ThreadExists()) { - - // commit allocator - hr = m_pAlloc->Commit(); - if (FAILED(hr)) { - return hr; - } - - // start thread - if (!Create()) { - return E_FAIL; - } - } - - m_State = TM_Start; - hr = (HRESULT) CallWorker(m_State); - return hr; -} - -HRESULT -CPullPin::PauseThread() -{ - CAutoLock lock(&m_AccessLock); - - if (!ThreadExists()) { - return E_UNEXPECTED; - } - - // need to flush to ensure the thread is not blocked - // in WaitForNext - HRESULT hr = m_pReader->BeginFlush(); - if (FAILED(hr)) { - return hr; - } - - m_State = TM_Pause; - hr = CallWorker(TM_Pause); - - m_pReader->EndFlush(); - return hr; -} - -HRESULT -CPullPin::StopThread() -{ - CAutoLock lock(&m_AccessLock); - - if (!ThreadExists()) { - return S_FALSE; - } - - // need to flush to ensure the thread is not blocked - // in WaitForNext - HRESULT hr = m_pReader->BeginFlush(); - if (FAILED(hr)) { - return hr; - } - - m_State = TM_Exit; - hr = CallWorker(TM_Exit); - - m_pReader->EndFlush(); - - // wait for thread to completely exit - Close(); - - // decommit allocator - if (m_pAlloc) { - m_pAlloc->Decommit(); - } - - return S_OK; -} - - -DWORD -CPullPin::ThreadProc(void) -{ - while(1) { - DWORD cmd = GetRequest(); - switch(cmd) { - case TM_Exit: - Reply(S_OK); - return 0; - - case TM_Pause: - // we are paused already - Reply(S_OK); - break; - - case TM_Start: - Reply(S_OK); - Process(); - break; - } - - // at this point, there should be no outstanding requests on the - // upstream filter. - // We should force begin/endflush to ensure that this is true. - // !!!Note that we may currently be inside a BeginFlush/EndFlush pair - // on another thread, but the premature EndFlush will do no harm now - // that we are idle. - m_pReader->BeginFlush(); - CleanupCancelled(); - m_pReader->EndFlush(); - } -} - -HRESULT -CPullPin::QueueSample( - __inout REFERENCE_TIME& tCurrent, - REFERENCE_TIME tAlignStop, - BOOL bDiscontinuity - ) -{ - IMediaSample* pSample; - - HRESULT hr = m_pAlloc->GetBuffer(&pSample, NULL, NULL, 0); - if (FAILED(hr)) { - return hr; - } - - LONGLONG tStopThis = tCurrent + (pSample->GetSize() * UNITS); - if (tStopThis > tAlignStop) { - tStopThis = tAlignStop; - } - pSample->SetTime(&tCurrent, &tStopThis); - tCurrent = tStopThis; - - pSample->SetDiscontinuity(bDiscontinuity); - - hr = m_pReader->Request( - pSample, - 0); - if (FAILED(hr)) { - pSample->Release(); - - CleanupCancelled(); - OnError(hr); - } - return hr; -} - -HRESULT -CPullPin::CollectAndDeliver( - REFERENCE_TIME tStart, - REFERENCE_TIME tStop) -{ - IMediaSample* pSample = NULL; // better be sure pSample is set - DWORD_PTR dwUnused; - HRESULT hr = m_pReader->WaitForNext( - INFINITE, - &pSample, - &dwUnused); - if (FAILED(hr)) { - if (pSample) { - pSample->Release(); - } - } else { - hr = DeliverSample(pSample, tStart, tStop); - } - if (FAILED(hr)) { - CleanupCancelled(); - OnError(hr); - } - return hr; - -} - -HRESULT -CPullPin::DeliverSample( - IMediaSample* pSample, - REFERENCE_TIME tStart, - REFERENCE_TIME tStop - ) -{ - // fix up sample if past actual stop (for sector alignment) - REFERENCE_TIME t1, t2; - if (S_OK == pSample->GetTime(&t1, &t2)) { - if (t2 > tStop) { - t2 = tStop; - } - - // adjust times to be relative to (aligned) start time - t1 -= tStart; - t2 -= tStart; - HRESULT hr = pSample->SetTime(&t1, &t2); - if (FAILED(hr)) { - return hr; - } - } - -#ifdef DXMPERF - { - AM_MEDIA_TYPE * pmt = NULL; - pSample->GetMediaType( &pmt ); - PERFLOG_RECEIVE( L"CPullPin", m_pReader, this, pSample, pmt ); - } -#endif - - HRESULT hr = Receive(pSample); - pSample->Release(); - return hr; -} - -void -CPullPin::Process(void) -{ - // is there anything to do? - if (m_tStop <= m_tStart) { - EndOfStream(); - return; - } - - BOOL bDiscontinuity = TRUE; - - // if there is more than one sample at the allocator, - // then try to queue 2 at once in order to overlap. - // -- get buffer count and required alignment - ALLOCATOR_PROPERTIES Actual; - HRESULT hr = m_pAlloc->GetProperties(&Actual); - - // align the start position downwards - REFERENCE_TIME tStart = AlignDown(m_tStart / UNITS, Actual.cbAlign) * UNITS; - REFERENCE_TIME tCurrent = tStart; - - REFERENCE_TIME tStop = m_tStop; - if (tStop > m_tDuration) { - tStop = m_tDuration; - } - - // align the stop position - may be past stop, but that - // doesn't matter - REFERENCE_TIME tAlignStop = AlignUp(tStop / UNITS, Actual.cbAlign) * UNITS; - - - DWORD dwRequest; - - if (!m_bSync) { - - // Break out of the loop either if we get to the end or we're asked - // to do something else - while (tCurrent < tAlignStop) { - - // Break out without calling EndOfStream if we're asked to - // do something different - if (CheckRequest(&dwRequest)) { - return; - } - - // queue a first sample - if (Actual.cBuffers > 1) { - - hr = QueueSample(tCurrent, tAlignStop, TRUE); - bDiscontinuity = FALSE; - - if (FAILED(hr)) { - return; - } - } - - - - // loop queueing second and waiting for first.. - while (tCurrent < tAlignStop) { - - hr = QueueSample(tCurrent, tAlignStop, bDiscontinuity); - bDiscontinuity = FALSE; - - if (FAILED(hr)) { - return; - } - - hr = CollectAndDeliver(tStart, tStop); - if (S_OK != hr) { - - // stop if error, or if downstream filter said - // to stop. - return; - } - } - - if (Actual.cBuffers > 1) { - hr = CollectAndDeliver(tStart, tStop); - if (FAILED(hr)) { - return; - } - } - } - } else { - - // sync version of above loop - while (tCurrent < tAlignStop) { - - // Break out without calling EndOfStream if we're asked to - // do something different - if (CheckRequest(&dwRequest)) { - return; - } - - IMediaSample* pSample; - - hr = m_pAlloc->GetBuffer(&pSample, NULL, NULL, 0); - if (FAILED(hr)) { - OnError(hr); - return; - } - - LONGLONG tStopThis = tCurrent + (pSample->GetSize() * UNITS); - if (tStopThis > tAlignStop) { - tStopThis = tAlignStop; - } - pSample->SetTime(&tCurrent, &tStopThis); - tCurrent = tStopThis; - - if (bDiscontinuity) { - pSample->SetDiscontinuity(TRUE); - bDiscontinuity = FALSE; - } - - hr = m_pReader->SyncReadAligned(pSample); - - if (FAILED(hr)) { - pSample->Release(); - OnError(hr); - return; - } - - hr = DeliverSample(pSample, tStart, tStop); - if (hr != S_OK) { - if (FAILED(hr)) { - OnError(hr); - } - return; - } - } - } - - EndOfStream(); -} - -// after a flush, cancelled i/o will be waiting for collection -// and release -void -CPullPin::CleanupCancelled(void) -{ - while (1) { - IMediaSample * pSample; - DWORD_PTR dwUnused; - - HRESULT hr = m_pReader->WaitForNext( - 0, // no wait - &pSample, - &dwUnused); - if(pSample) { - pSample->Release(); - } else { - // no more samples - return; - } - } -} diff --git a/third_party/BaseClasses/pullpin.h b/third_party/BaseClasses/pullpin.h deleted file mode 100644 index 03ad40ec..00000000 --- a/third_party/BaseClasses/pullpin.h +++ /dev/null @@ -1,152 +0,0 @@ -//------------------------------------------------------------------------------ -// File: PullPin.h -// -// Desc: DirectShow base classes - defines CPullPin class. -// -// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. -//------------------------------------------------------------------------------ - - -#ifndef __PULLPIN_H__ -#define __PULLPIN_H__ - -// -// CPullPin -// -// object supporting pulling data from an IAsyncReader interface. -// Given a start/stop position, calls a pure Receive method with each -// IMediaSample received. -// -// This is essentially for use in a MemInputPin when it finds itself -// connected to an IAsyncReader pin instead of a pushing pin. -// - -class CPullPin : public CAMThread -{ - IAsyncReader* m_pReader; - REFERENCE_TIME m_tStart; - REFERENCE_TIME m_tStop; - REFERENCE_TIME m_tDuration; - BOOL m_bSync; - - enum ThreadMsg { - TM_Pause, // stop pulling and wait for next message - TM_Start, // start pulling - TM_Exit, // stop and exit - }; - - ThreadMsg m_State; - - // override pure thread proc from CAMThread - DWORD ThreadProc(void); - - // running pull method (check m_bSync) - void Process(void); - - // clean up any cancelled i/o after a flush - void CleanupCancelled(void); - - // suspend thread from pulling, eg during seek - HRESULT PauseThread(); - - // start thread pulling - create thread if necy - HRESULT StartThread(); - - // stop and close thread - HRESULT StopThread(); - - // called from ProcessAsync to queue and collect requests - HRESULT QueueSample( - __inout REFERENCE_TIME& tCurrent, - REFERENCE_TIME tAlignStop, - BOOL bDiscontinuity); - - HRESULT CollectAndDeliver( - REFERENCE_TIME tStart, - REFERENCE_TIME tStop); - - HRESULT DeliverSample( - IMediaSample* pSample, - REFERENCE_TIME tStart, - REFERENCE_TIME tStop); - -protected: - IMemAllocator * m_pAlloc; - -public: - CPullPin(); - virtual ~CPullPin(); - - // returns S_OK if successfully connected to an IAsyncReader interface - // from this object - // Optional allocator should be proposed as a preferred allocator if - // necessary - // bSync is TRUE if we are to use sync reads instead of the - // async methods. - HRESULT Connect(IUnknown* pUnk, IMemAllocator* pAlloc, BOOL bSync); - - // disconnect any connection made in Connect - HRESULT Disconnect(); - - // agree an allocator using RequestAllocator - optional - // props param specifies your requirements (non-zero fields). - // returns an error code if fail to match requirements. - // optional IMemAllocator interface is offered as a preferred allocator - // but no error occurs if it can't be met. - virtual HRESULT DecideAllocator( - IMemAllocator* pAlloc, - __inout_opt ALLOCATOR_PROPERTIES * pProps); - - // set start and stop position. if active, will start immediately at - // the new position. Default is 0 to duration - HRESULT Seek(REFERENCE_TIME tStart, REFERENCE_TIME tStop); - - // return the total duration - HRESULT Duration(__out REFERENCE_TIME* ptDuration); - - // start pulling data - HRESULT Active(void); - - // stop pulling data - HRESULT Inactive(void); - - // helper functions - LONGLONG AlignDown(LONGLONG ll, LONG lAlign) { - // aligning downwards is just truncation - return ll & ~(lAlign-1); - }; - - LONGLONG AlignUp(LONGLONG ll, LONG lAlign) { - // align up: round up to next boundary - return (ll + (lAlign -1)) & ~(lAlign -1); - }; - - // GetReader returns the (addrefed) IAsyncReader interface - // for SyncRead etc - IAsyncReader* GetReader() { - m_pReader->AddRef(); - return m_pReader; - }; - - // -- pure -- - - // override this to handle data arrival - // return value other than S_OK will stop data - virtual HRESULT Receive(IMediaSample*) PURE; - - // override this to handle end-of-stream - virtual HRESULT EndOfStream(void) PURE; - - // called on runtime errors that will have caused pulling - // to stop - // these errors are all returned from the upstream filter, who - // will have already reported any errors to the filtergraph. - virtual void OnError(HRESULT hr) PURE; - - // flush this pin and all downstream - virtual HRESULT BeginFlush() PURE; - virtual HRESULT EndFlush() PURE; - -}; - -#endif //__PULLPIN_H__ diff --git a/third_party/BaseClasses/refclock.cpp b/third_party/BaseClasses/refclock.cpp deleted file mode 100644 index 8ae25f44..00000000 --- a/third_party/BaseClasses/refclock.cpp +++ /dev/null @@ -1,402 +0,0 @@ -//------------------------------------------------------------------------------ -// File: RefClock.cpp -// -// Desc: DirectShow base classes - implements the IReferenceClock interface. -// -// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. -//------------------------------------------------------------------------------ - - -#include -#include - -#ifdef DXMPERF -#include "dxmperf.h" -#endif // DXMPERF - - -// 'this' used in constructor list -#pragma warning(disable:4355) - - -STDMETHODIMP CBaseReferenceClock::NonDelegatingQueryInterface( - REFIID riid, - __deref_out void ** ppv) -{ - HRESULT hr; - - if (riid == IID_IReferenceClock) - { - hr = GetInterface((IReferenceClock *) this, ppv); - } - else if (riid == IID_IReferenceClockTimerControl) - { - hr = GetInterface((IReferenceClockTimerControl *) this, ppv); - } - else - { - hr = CUnknown::NonDelegatingQueryInterface(riid, ppv); - } - return hr; -} - -CBaseReferenceClock::~CBaseReferenceClock() -{ -#ifdef DXMPERF - PERFLOG_DTOR( L"CBaseReferenceClock", (IReferenceClock *) this ); -#endif // DXMPERF - - if (m_TimerResolution) timeEndPeriod(m_TimerResolution); - - if (m_pSchedule) - { - m_pSchedule->DumpLinkedList(); - } - - if (m_hThread) - { - m_bAbort = TRUE; - TriggerThread(); - WaitForSingleObject( m_hThread, INFINITE ); - EXECUTE_ASSERT( CloseHandle(m_hThread) ); - m_hThread = 0; - EXECUTE_ASSERT( CloseHandle(m_pSchedule->GetEvent()) ); - delete m_pSchedule; - } -} - -// A derived class may supply a hThreadEvent if it has its own thread that will take care -// of calling the schedulers Advise method. (Refere to CBaseReferenceClock::AdviseThread() -// to see what such a thread has to do.) -CBaseReferenceClock::CBaseReferenceClock( __in_opt LPCTSTR pName, - __inout_opt LPUNKNOWN pUnk, - __inout HRESULT *phr, - __inout_opt CAMSchedule * pShed ) -: CUnknown( pName, pUnk ) -, m_rtLastGotTime(0) -, m_TimerResolution(0) -, m_bAbort( FALSE ) -, m_pSchedule( pShed ? pShed : new CAMSchedule(CreateEvent(NULL, FALSE, FALSE, NULL)) ) -, m_hThread(0) -{ - -#ifdef DXMPERF - PERFLOG_CTOR( pName ? pName : L"CBaseReferenceClock", (IReferenceClock *) this ); -#endif // DXMPERF - - ASSERT(m_pSchedule); - if (!m_pSchedule) - { - *phr = E_OUTOFMEMORY; - } - else - { - // Set up the highest resolution timer we can manage - TIMECAPS tc; - m_TimerResolution = (TIMERR_NOERROR == timeGetDevCaps(&tc, sizeof(tc))) - ? tc.wPeriodMin - : 1; - - timeBeginPeriod(m_TimerResolution); - - /* Initialise our system times - the derived clock should set the right values */ - m_dwPrevSystemTime = timeGetTime(); - m_rtPrivateTime = (UNITS / MILLISECONDS) * m_dwPrevSystemTime; - - #ifdef PERF - m_idGetSystemTime = MSR_REGISTER(TEXT("CBaseReferenceClock::GetTime")); - #endif - - if ( !pShed ) - { - DWORD ThreadID; - m_hThread = ::CreateThread(NULL, // Security attributes - (DWORD) 0, // Initial stack size - AdviseThreadFunction, // Thread start address - (LPVOID) this, // Thread parameter - (DWORD) 0, // Creation flags - &ThreadID); // Thread identifier - - if (m_hThread) - { - SetThreadPriority( m_hThread, THREAD_PRIORITY_TIME_CRITICAL ); - } - else - { - *phr = E_FAIL; - EXECUTE_ASSERT( CloseHandle(m_pSchedule->GetEvent()) ); - delete m_pSchedule; - m_pSchedule = NULL; - } - } - } -} - -void CBaseReferenceClock::Restart (IN REFERENCE_TIME rtMinTime) -{ - Lock(); - m_rtLastGotTime = rtMinTime ; - Unlock(); -} - -STDMETHODIMP CBaseReferenceClock::GetTime(__out REFERENCE_TIME *pTime) -{ - HRESULT hr; - if (pTime) - { - REFERENCE_TIME rtNow; - Lock(); - rtNow = GetPrivateTime(); - if (rtNow > m_rtLastGotTime) - { - m_rtLastGotTime = rtNow; - hr = S_OK; - } - else - { - hr = S_FALSE; - } - *pTime = m_rtLastGotTime; - Unlock(); - MSR_INTEGER(m_idGetSystemTime, LONG((*pTime) / (UNITS/MILLISECONDS)) ); - -#ifdef DXMPERF - PERFLOG_GETTIME( (IReferenceClock *) this, *pTime ); -#endif // DXMPERF - - } - else hr = E_POINTER; - - return hr; -} - -/* Ask for an async notification that a time has elapsed */ - -STDMETHODIMP CBaseReferenceClock::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 -{ - CheckPointer(pdwAdviseCookie, E_POINTER); - *pdwAdviseCookie = 0; - - // Check that the event is not already set - ASSERT(WAIT_TIMEOUT == WaitForSingleObject(HANDLE(hEvent),0)); - - HRESULT hr; - - const REFERENCE_TIME lRefTime = baseTime + streamTime; - if ( lRefTime <= 0 || lRefTime == MAX_TIME ) - { - hr = E_INVALIDARG; - } - else - { - *pdwAdviseCookie = m_pSchedule->AddAdvisePacket( lRefTime, 0, HANDLE(hEvent), FALSE ); - hr = *pdwAdviseCookie ? NOERROR : E_OUTOFMEMORY; - } - return hr; -} - - -/* Ask for an asynchronous periodic notification that a time has elapsed */ - -STDMETHODIMP CBaseReferenceClock::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 -{ - CheckPointer(pdwAdviseCookie, E_POINTER); - *pdwAdviseCookie = 0; - - HRESULT hr; - if (StartTime > 0 && PeriodTime > 0 && StartTime != MAX_TIME ) - { - *pdwAdviseCookie = m_pSchedule->AddAdvisePacket( StartTime, PeriodTime, HANDLE(hSemaphore), TRUE ); - hr = *pdwAdviseCookie ? NOERROR : E_OUTOFMEMORY; - } - else hr = E_INVALIDARG; - - return hr; -} - - -STDMETHODIMP CBaseReferenceClock::Unadvise(DWORD_PTR dwAdviseCookie) -{ - return m_pSchedule->Unadvise(dwAdviseCookie); -} - - -REFERENCE_TIME CBaseReferenceClock::GetPrivateTime() -{ - CAutoLock cObjectLock(this); - - - /* If the clock has wrapped then the current time will be less than - * the last time we were notified so add on the extra milliseconds - * - * The time period is long enough so that the likelihood of - * successive calls spanning the clock cycle is not considered. - */ - - DWORD dwTime = timeGetTime(); - { - m_rtPrivateTime += Int32x32To64(UNITS / MILLISECONDS, (DWORD)(dwTime - m_dwPrevSystemTime)); - m_dwPrevSystemTime = dwTime; - } - - return m_rtPrivateTime; -} - - -/* Adjust the current time by the input value. This allows an - external time source to work out some of the latency of the clock - system and adjust the "current" time accordingly. The intent is - that the time returned to the user is synchronised to a clock - source and allows drift to be catered for. - - For example: if the clock source detects a drift it can pass a delta - to the current time rather than having to set an explicit time. -*/ - -STDMETHODIMP CBaseReferenceClock::SetTimeDelta(const REFERENCE_TIME & TimeDelta) -{ -#ifdef DEBUG - - // Just break if passed an improper time delta value - LONGLONG llDelta = TimeDelta > 0 ? TimeDelta : -TimeDelta; - if (llDelta > UNITS * 1000) { - DbgLog((LOG_TRACE, 0, TEXT("Bad Time Delta"))); - //DebugBreak(); - } - - // We're going to calculate a "severity" for the time change. Max -1 - // min 8. We'll then use this as the debug logging level for a - // debug log message. - const LONG usDelta = LONG(TimeDelta/10); // Delta in micro-secs - - DWORD delta = abs(usDelta); // varying delta - // Severity == 8 - ceil(log(abs( micro-secs delta))) - int Severity = 8; - while ( delta > 0 ) - { - delta >>= 3; // div 8 - Severity--; - } - - // Sev == 0 => > 2 second delta! - DbgLog((LOG_TIMING, Severity < 0 ? 0 : Severity, - TEXT("Sev %2i: CSystemClock::SetTimeDelta(%8ld us) %lu -> %lu ms."), - Severity, usDelta, DWORD(ConvertToMilliseconds(m_rtPrivateTime)), - DWORD(ConvertToMilliseconds(TimeDelta+m_rtPrivateTime)) )); - - // Don't want the DbgBreak to fire when running stress on debug-builds. - #ifdef BREAK_ON_SEVERE_TIME_DELTA - if (Severity < 0) - DbgBreakPoint(TEXT("SetTimeDelta > 16 seconds!"), - TEXT(__FILE__),__LINE__); - #endif - -#endif - - CAutoLock cObjectLock(this); - m_rtPrivateTime += TimeDelta; - // If time goes forwards, and we have advises, then we need to - // trigger the thread so that it can re-evaluate its wait time. - // Since we don't want the cost of the thread switches if the change - // is really small, only do it if clock goes forward by more than - // 0.5 millisecond. If the time goes backwards, the thread will - // wake up "early" (relativly speaking) and will re-evaluate at - // that time. - if ( TimeDelta > 5000 && m_pSchedule->GetAdviseCount() > 0 ) TriggerThread(); - return NOERROR; -} - -// Thread stuff - -DWORD __stdcall CBaseReferenceClock::AdviseThreadFunction(__in LPVOID p) -{ - return DWORD(reinterpret_cast(p)->AdviseThread()); -} - -HRESULT CBaseReferenceClock::AdviseThread() -{ - DWORD dwWait = INFINITE; - - // The first thing we do is wait until something interesting happens - // (meaning a first advise or shutdown). This prevents us calling - // GetPrivateTime immediately which is goodness as that is a virtual - // routine and the derived class may not yet be constructed. (This - // thread is created in the base class constructor.) - - while ( !m_bAbort ) - { - // Wait for an interesting event to happen - DbgLog((LOG_TIMING, 3, TEXT("CBaseRefClock::AdviseThread() Delay: %lu ms"), dwWait )); - WaitForSingleObject(m_pSchedule->GetEvent(), dwWait); - if (m_bAbort) break; - - // There are several reasons why we need to work from the internal - // time, mainly to do with what happens when time goes backwards. - // Mainly, it stop us looping madly if an event is just about to - // expire when the clock goes backward (i.e. GetTime stop for a - // while). - const REFERENCE_TIME rtNow = GetPrivateTime(); - - DbgLog((LOG_TIMING, 3, - TEXT("CBaseRefClock::AdviseThread() Woke at = %lu ms"), - ConvertToMilliseconds(rtNow) )); - - // We must add in a millisecond, since this is the resolution of our - // WaitForSingleObject timer. Failure to do so will cause us to loop - // franticly for (approx) 1 a millisecond. - m_rtNextAdvise = m_pSchedule->Advise( 10000 + rtNow ); - LONGLONG llWait = m_rtNextAdvise - rtNow; - - ASSERT( llWait > 0 ); - - llWait = ConvertToMilliseconds(llWait); - // DON'T replace this with a max!! (The type's of these things is VERY important) - dwWait = (llWait > REFERENCE_TIME(UINT_MAX)) ? UINT_MAX : DWORD(llWait); - }; - return NOERROR; -} - -HRESULT CBaseReferenceClock::SetDefaultTimerResolution( - REFERENCE_TIME timerResolution // in 100ns - ) -{ - CAutoLock cObjectLock(this); - if( 0 == timerResolution ) { - if( m_TimerResolution ) { - timeEndPeriod( m_TimerResolution ); - m_TimerResolution = 0; - } - } else { - TIMECAPS tc; - DWORD dwMinResolution = (TIMERR_NOERROR == timeGetDevCaps(&tc, sizeof(tc))) - ? tc.wPeriodMin - : 1; - DWORD dwResolution = max( dwMinResolution, DWORD(timerResolution / 10000) ); - if( dwResolution != m_TimerResolution ) { - timeEndPeriod(m_TimerResolution); - m_TimerResolution = dwResolution; - timeBeginPeriod( m_TimerResolution ); - } - } - return S_OK; -} - -HRESULT CBaseReferenceClock::GetDefaultTimerResolution( - __out REFERENCE_TIME* pTimerResolution // in 100ns - ) -{ - if( !pTimerResolution ) { - return E_POINTER; - } - CAutoLock cObjectLock(this); - *pTimerResolution = m_TimerResolution * 10000; - return S_OK; -} diff --git a/third_party/BaseClasses/schedule.cpp b/third_party/BaseClasses/schedule.cpp deleted file mode 100644 index 7d798306..00000000 --- a/third_party/BaseClasses/schedule.cpp +++ /dev/null @@ -1,284 +0,0 @@ -//------------------------------------------------------------------------------ -// File: Schedule.cpp -// -// Desc: DirectShow base classes. -// -// Copyright (c) 1996-2001 Microsoft Corporation. All rights reserved. -//------------------------------------------------------------------------------ - - -#include - -// DbgLog values (all on LOG_TIMING): -// -// 2 for schedulting, firing and shunting of events -// 3 for wait delays and wake-up times of event thread -// 4 for details of whats on the list when the thread awakes - -/* Construct & destructors */ - -CAMSchedule::CAMSchedule( HANDLE ev ) -: CBaseObject(TEXT("CAMSchedule")) -, head(&z, 0), z(0, MAX_TIME) -, m_dwNextCookie(0), m_dwAdviseCount(0) -, m_pAdviseCache(0), m_dwCacheCount(0) -, m_ev( ev ) -{ - head.m_dwAdviseCookie = z.m_dwAdviseCookie = 0; -} - -CAMSchedule::~CAMSchedule() -{ - m_Serialize.Lock(); - - // Delete cache - CAdvisePacket * p = m_pAdviseCache; - while (p) - { - CAdvisePacket *const p_next = p->m_next; - delete p; - p = p_next; - } - - ASSERT( m_dwAdviseCount == 0 ); - // Better to be safe than sorry - if ( m_dwAdviseCount > 0 ) - { - DumpLinkedList(); - while ( !head.m_next->IsZ() ) - { - head.DeleteNext(); - --m_dwAdviseCount; - } - } - - // If, in the debug version, we assert twice, it means, not only - // did we have left over advises, but we have also let m_dwAdviseCount - // get out of sync. with the number of advises actually on the list. - ASSERT( m_dwAdviseCount == 0 ); - - m_Serialize.Unlock(); -} - -/* Public methods */ - -DWORD CAMSchedule::GetAdviseCount() -{ - // No need to lock, m_dwAdviseCount is 32bits & declared volatile - return m_dwAdviseCount; -} - -REFERENCE_TIME CAMSchedule::GetNextAdviseTime() -{ - CAutoLock lck(&m_Serialize); // Need to stop the linked list from changing - return head.m_next->m_rtEventTime; -} - -DWORD_PTR CAMSchedule::AddAdvisePacket -( const REFERENCE_TIME & time1 -, const REFERENCE_TIME & time2 -, HANDLE h, BOOL periodic -) -{ - // Since we use MAX_TIME as a sentry, we can't afford to - // schedule a notification at MAX_TIME - ASSERT( time1 < MAX_TIME ); - DWORD_PTR Result; - CAdvisePacket * p; - - m_Serialize.Lock(); - - if (m_pAdviseCache) - { - p = m_pAdviseCache; - m_pAdviseCache = p->m_next; - --m_dwCacheCount; - } - else - { - p = new CAdvisePacket(); - } - if (p) - { - p->m_rtEventTime = time1; p->m_rtPeriod = time2; - p->m_hNotify = h; p->m_bPeriodic = periodic; - Result = AddAdvisePacket( p ); - } - else Result = 0; - - m_Serialize.Unlock(); - - return Result; -} - -HRESULT CAMSchedule::Unadvise(DWORD_PTR dwAdviseCookie) -{ - HRESULT hr = S_FALSE; - CAdvisePacket * p_prev = &head; - CAdvisePacket * p_n; - m_Serialize.Lock(); - while ( p_n = p_prev->Next() ) // The Next() method returns NULL when it hits z - { - if ( p_n->m_dwAdviseCookie == dwAdviseCookie ) - { - Delete( p_prev->RemoveNext() ); - --m_dwAdviseCount; - hr = S_OK; - // Having found one cookie that matches, there should be no more - #ifdef DEBUG - while (p_n = p_prev->Next()) - { - ASSERT(p_n->m_dwAdviseCookie != dwAdviseCookie); - p_prev = p_n; - } - #endif - break; - } - p_prev = p_n; - }; - m_Serialize.Unlock(); - return hr; -} - -REFERENCE_TIME CAMSchedule::Advise( const REFERENCE_TIME & rtTime ) -{ - REFERENCE_TIME rtNextTime; - CAdvisePacket * pAdvise; - - DbgLog((LOG_TIMING, 2, - TEXT("CAMSchedule::Advise( %lu ms )"), ULONG(rtTime / (UNITS / MILLISECONDS)))); - - CAutoLock lck(&m_Serialize); - - #ifdef DEBUG - if (DbgCheckModuleLevel(LOG_TIMING, 4)) DumpLinkedList(); - #endif - - // Note - DON'T cache the difference, it might overflow - while ( rtTime >= (rtNextTime = (pAdvise=head.m_next)->m_rtEventTime) && - !pAdvise->IsZ() ) - { - ASSERT(pAdvise->m_dwAdviseCookie); // If this is zero, its the head or the tail!! - - ASSERT(pAdvise->m_hNotify != INVALID_HANDLE_VALUE); - - if (pAdvise->m_bPeriodic == TRUE) - { - ReleaseSemaphore(pAdvise->m_hNotify,1,NULL); - pAdvise->m_rtEventTime += pAdvise->m_rtPeriod; - ShuntHead(); - } - else - { - ASSERT( pAdvise->m_bPeriodic == FALSE ); - EXECUTE_ASSERT(SetEvent(pAdvise->m_hNotify)); - --m_dwAdviseCount; - Delete( head.RemoveNext() ); - } - - } - - DbgLog((LOG_TIMING, 3, - TEXT("CAMSchedule::Advise() Next time stamp: %lu ms, for advise %lu."), - DWORD(rtNextTime / (UNITS / MILLISECONDS)), pAdvise->m_dwAdviseCookie )); - - return rtNextTime; -} - -/* Private methods */ - -DWORD_PTR CAMSchedule::AddAdvisePacket( __inout CAdvisePacket * pPacket ) -{ - ASSERT(pPacket->m_rtEventTime >= 0 && pPacket->m_rtEventTime < MAX_TIME); - ASSERT(CritCheckIn(&m_Serialize)); - - CAdvisePacket * p_prev = &head; - CAdvisePacket * p_n; - - const DWORD_PTR Result = pPacket->m_dwAdviseCookie = ++m_dwNextCookie; - // This relies on the fact that z is a sentry with a maximal m_rtEventTime - for(;;p_prev = p_n) - { - p_n = p_prev->m_next; - if ( p_n->m_rtEventTime >= pPacket->m_rtEventTime ) break; - } - p_prev->InsertAfter( pPacket ); - ++m_dwAdviseCount; - - DbgLog((LOG_TIMING, 2, TEXT("Added advise %lu, for thread 0x%02X, scheduled at %lu"), - pPacket->m_dwAdviseCookie, GetCurrentThreadId(), (pPacket->m_rtEventTime / (UNITS / MILLISECONDS)) )); - - // If packet added at the head, then clock needs to re-evaluate wait time. - if ( p_prev == &head ) SetEvent( m_ev ); - - return Result; -} - -void CAMSchedule::Delete( __inout CAdvisePacket * pPacket ) -{ - if ( m_dwCacheCount >= dwCacheMax ) delete pPacket; - else - { - m_Serialize.Lock(); - pPacket->m_next = m_pAdviseCache; - m_pAdviseCache = pPacket; - ++m_dwCacheCount; - m_Serialize.Unlock(); - } -} - - -// Takes the head of the list & repositions it -void CAMSchedule::ShuntHead() -{ - CAdvisePacket * p_prev = &head; - CAdvisePacket * p_n; - - m_Serialize.Lock(); - CAdvisePacket *const pPacket = head.m_next; - - // This will catch both an empty list, - // and if somehow a MAX_TIME time gets into the list - // (which would also break this method). - ASSERT( pPacket->m_rtEventTime < MAX_TIME ); - - // This relies on the fact that z is a sentry with a maximal m_rtEventTime - for(;;p_prev = p_n) - { - p_n = p_prev->m_next; - if ( p_n->m_rtEventTime > pPacket->m_rtEventTime ) break; - } - // If p_prev == pPacket then we're already in the right place - if (p_prev != pPacket) - { - head.m_next = pPacket->m_next; - (p_prev->m_next = pPacket)->m_next = p_n; - } - #ifdef DEBUG - DbgLog((LOG_TIMING, 2, TEXT("Periodic advise %lu, shunted to %lu"), - pPacket->m_dwAdviseCookie, (pPacket->m_rtEventTime / (UNITS / MILLISECONDS)) )); - #endif - m_Serialize.Unlock(); -} - - -#ifdef DEBUG -void CAMSchedule::DumpLinkedList() -{ - m_Serialize.Lock(); - int i=0; - DbgLog((LOG_TIMING, 1, TEXT("CAMSchedule::DumpLinkedList() this = 0x%p"), this)); - for ( CAdvisePacket * p = &head - ; p - ; p = p->m_next , i++ - ) - { - DbgLog((LOG_TIMING, 1, TEXT("Advise List # %lu, Cookie %d, RefTime %lu"), - i, - p->m_dwAdviseCookie, - p->m_rtEventTime / (UNITS / MILLISECONDS) - )); - } - m_Serialize.Unlock(); -} -#endif diff --git a/third_party/BaseClasses/schedule.h b/third_party/BaseClasses/schedule.h deleted file mode 100644 index c16700a2..00000000 --- a/third_party/BaseClasses/schedule.h +++ /dev/null @@ -1,128 +0,0 @@ -//------------------------------------------------------------------------------ -// File: Schedule.h -// -// Desc: DirectShow base classes. -// -// Copyright (c) 1996-2001 Microsoft Corporation. All rights reserved. -//------------------------------------------------------------------------------ - - -#ifndef __CAMSchedule__ -#define __CAMSchedule__ - -class CAMSchedule : private CBaseObject -{ -public: - virtual ~CAMSchedule(); - // ev is the event we should fire if the advise time needs re-evaluating - CAMSchedule( HANDLE ev ); - - DWORD GetAdviseCount(); - REFERENCE_TIME GetNextAdviseTime(); - - // We need a method for derived classes to add advise packets, we return the cookie - DWORD_PTR AddAdvisePacket( const REFERENCE_TIME & time1, const REFERENCE_TIME & time2, HANDLE h, BOOL periodic ); - // And a way to cancel - HRESULT Unadvise(DWORD_PTR dwAdviseCookie); - - // Tell us the time please, and we'll dispatch the expired events. We return the time of the next event. - // NB: The time returned will be "useless" if you start adding extra Advises. But that's the problem of - // whoever is using this helper class (typically a clock). - REFERENCE_TIME Advise( const REFERENCE_TIME & rtTime ); - - // Get the event handle which will be set if advise time requires re-evaluation. - HANDLE GetEvent() const { return m_ev; } - -private: - // We define the nodes that will be used in our singly linked list - // of advise packets. The list is ordered by time, with the - // elements that will expire first at the front. - class CAdvisePacket - { - public: - CAdvisePacket() - {} - - CAdvisePacket * m_next; - DWORD_PTR m_dwAdviseCookie; - REFERENCE_TIME m_rtEventTime; // Time at which event should be set - REFERENCE_TIME m_rtPeriod; // Periodic time - HANDLE m_hNotify; // Handle to event or semephore - BOOL m_bPeriodic; // TRUE => Periodic event - - CAdvisePacket( __inout_opt CAdvisePacket * next, LONGLONG time ) : m_next(next), m_rtEventTime(time) - {} - - void InsertAfter( __inout CAdvisePacket * p ) - { - p->m_next = m_next; - m_next = p; - } - - int IsZ() const // That is, is it the node that represents the end of the list - { return m_next == 0; } - - CAdvisePacket * RemoveNext() - { - CAdvisePacket *const next = m_next; - CAdvisePacket *const new_next = next->m_next; - m_next = new_next; - return next; - } - - void DeleteNext() - { - delete RemoveNext(); - } - - CAdvisePacket * Next() const - { - CAdvisePacket * result = m_next; - if (result->IsZ()) result = 0; - return result; - } - - DWORD_PTR Cookie() const - { return m_dwAdviseCookie; } - }; - - // Structure is: - // head -> elmt1 -> elmt2 -> z -> null - // So an empty list is: head -> z -> null - // Having head & z as links makes insertaion, - // deletion and shunting much easier. - CAdvisePacket head, z; // z is both a tail and a sentry - - volatile DWORD_PTR m_dwNextCookie; // Strictly increasing - volatile DWORD m_dwAdviseCount; // Number of elements on list - - CCritSec m_Serialize; - - // AddAdvisePacket: adds the packet, returns the cookie (0 if failed) - DWORD_PTR AddAdvisePacket( __inout CAdvisePacket * pPacket ); - // Event that we should set if the packed added above will be the next to fire. - const HANDLE m_ev; - - // A Shunt is where we have changed the first element in the - // list and want it re-evaluating (i.e. repositioned) in - // the list. - void ShuntHead(); - - // Rather than delete advise packets, we cache them for future use - CAdvisePacket * m_pAdviseCache; - DWORD m_dwCacheCount; - enum { dwCacheMax = 5 }; // Don't bother caching more than five - - void Delete( __inout CAdvisePacket * pLink );// This "Delete" will cache the Link - -// Attributes and methods for debugging -public: -#ifdef DEBUG - void DumpLinkedList(); -#else - void DumpLinkedList() {} -#endif - -}; - -#endif // __CAMSchedule__ diff --git a/third_party/BaseClasses/seekpt.cpp b/third_party/BaseClasses/seekpt.cpp deleted file mode 100644 index bb13d6f0..00000000 --- a/third_party/BaseClasses/seekpt.cpp +++ /dev/null @@ -1,83 +0,0 @@ -//------------------------------------------------------------------------------ -// File: SeekPT.cpp -// -// Desc: DirectShow base classes. -// -// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. -//------------------------------------------------------------------------------ - - -#include -#include "seekpt.h" - -//================================================================== -// CreateInstance -// This goes in the factory template table to create new instances -// If there is already a mapper instance - return that, else make one -// and save it in a static variable so that forever after we can return that. -//================================================================== - -CUnknown * CSeekingPassThru::CreateInstance(__inout_opt LPUNKNOWN pUnk, __inout HRESULT *phr) -{ - return new CSeekingPassThru(NAME("Seeking PassThru"),pUnk, phr); -} - - -STDMETHODIMP CSeekingPassThru::NonDelegatingQueryInterface(REFIID riid, __deref_out void ** ppv) -{ - if (riid == IID_ISeekingPassThru) { - return GetInterface((ISeekingPassThru *) this, ppv); - } else { - if (m_pPosPassThru && - (riid == IID_IMediaSeeking || - riid == IID_IMediaPosition)) { - return m_pPosPassThru->NonDelegatingQueryInterface(riid,ppv); - } else { - return CUnknown::NonDelegatingQueryInterface(riid, ppv); - } - } -} - - -CSeekingPassThru::CSeekingPassThru( __in_opt LPCTSTR pName, __inout_opt LPUNKNOWN pUnk, __inout HRESULT *phr ) - : CUnknown(pName, pUnk, phr), - m_pPosPassThru(NULL) -{ -} - - -CSeekingPassThru::~CSeekingPassThru() -{ - delete m_pPosPassThru; -} - -STDMETHODIMP CSeekingPassThru::Init(BOOL bRendererSeeking, IPin *pPin) -{ - HRESULT hr = NOERROR; - if (m_pPosPassThru) { - hr = E_FAIL; - } else { - m_pPosPassThru = - bRendererSeeking ? - new CRendererPosPassThru( - NAME("Render Seeking COM object"), - (IUnknown *)this, - &hr, - pPin) : - new CPosPassThru( - NAME("Render Seeking COM object"), - (IUnknown *)this, - &hr, - pPin); - if (!m_pPosPassThru) { - hr = E_OUTOFMEMORY; - } else { - if (FAILED(hr)) { - delete m_pPosPassThru; - m_pPosPassThru = NULL; - } - } - } - return hr; -} - diff --git a/third_party/BaseClasses/source.cpp b/third_party/BaseClasses/source.cpp deleted file mode 100644 index ef7795c4..00000000 --- a/third_party/BaseClasses/source.cpp +++ /dev/null @@ -1,522 +0,0 @@ -//------------------------------------------------------------------------------ -// File: Source.cpp -// -// Desc: DirectShow base classes - implements CSource, which is a Quartz -// source filter 'template.' -// -// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. -//------------------------------------------------------------------------------ - - -// Locking Strategy. -// -// Hold the filter critical section (m_pFilter->pStateLock()) to serialise -// access to functions. Note that, in general, this lock may be held -// by a function when the worker thread may want to hold it. Therefore -// if you wish to access shared state from the worker thread you will -// need to add another critical section object. The execption is during -// the threads processing loop, when it is safe to get the filter critical -// section from within FillBuffer(). - -#include - - -// -// CSource::Constructor -// -// Initialise the pin count for the filter. The user will create the pins in -// the derived class. -CSource::CSource(__in_opt LPCTSTR pName, __inout_opt LPUNKNOWN lpunk, CLSID clsid) - : CBaseFilter(pName, lpunk, &m_cStateLock, clsid), - m_iPins(0), - m_paStreams(NULL) -{ -} - -CSource::CSource(__in_opt LPCTSTR pName, __inout_opt LPUNKNOWN lpunk, CLSID clsid, __inout HRESULT *phr) - : CBaseFilter(pName, lpunk, &m_cStateLock, clsid), - m_iPins(0), - m_paStreams(NULL) -{ - UNREFERENCED_PARAMETER(phr); -} - -#ifdef UNICODE -CSource::CSource(__in_opt LPCSTR pName, __inout_opt LPUNKNOWN lpunk, CLSID clsid) - : CBaseFilter(pName, lpunk, &m_cStateLock, clsid), - m_iPins(0), - m_paStreams(NULL) -{ -} - -CSource::CSource(__in_opt LPCSTR pName, __inout_opt LPUNKNOWN lpunk, CLSID clsid, __inout HRESULT *phr) - : CBaseFilter(pName, lpunk, &m_cStateLock, clsid), - m_iPins(0), - m_paStreams(NULL) -{ - UNREFERENCED_PARAMETER(phr); -} -#endif - -// -// CSource::Destructor -// -CSource::~CSource() -{ - /* Free our pins and pin array */ - while (m_iPins != 0) { - // deleting the pins causes them to be removed from the array... - delete m_paStreams[m_iPins - 1]; - } - - ASSERT(m_paStreams == NULL); -} - - -// -// Add a new pin -// -HRESULT CSource::AddPin(__in CSourceStream *pStream) -{ - CAutoLock lock(&m_cStateLock); - - /* Allocate space for this pin and the old ones */ - CSourceStream **paStreams = new CSourceStream *[m_iPins + 1]; - if (paStreams == NULL) { - return E_OUTOFMEMORY; - } - if (m_paStreams != NULL) { - CopyMemory((PVOID)paStreams, (PVOID)m_paStreams, - m_iPins * sizeof(m_paStreams[0])); - paStreams[m_iPins] = pStream; - delete [] m_paStreams; - } - m_paStreams = paStreams; - m_paStreams[m_iPins] = pStream; - m_iPins++; - return S_OK; -} - -// -// Remove a pin - pStream is NOT deleted -// -HRESULT CSource::RemovePin(__in CSourceStream *pStream) -{ - int i; - for (i = 0; i < m_iPins; i++) { - if (m_paStreams[i] == pStream) { - if (m_iPins == 1) { - delete [] m_paStreams; - m_paStreams = NULL; - } else { - /* no need to reallocate */ - while (++i < m_iPins) - m_paStreams[i - 1] = m_paStreams[i]; - } - m_iPins--; - return S_OK; - } - } - return S_FALSE; -} - -// -// FindPin -// -// Set *ppPin to the IPin* that has the id Id. -// or to NULL if the Id cannot be matched. -STDMETHODIMP CSource::FindPin(LPCWSTR Id, __deref_out IPin **ppPin) -{ - CheckPointer(ppPin,E_POINTER); - ValidateReadWritePtr(ppPin,sizeof(IPin *)); - // The -1 undoes the +1 in QueryId and ensures that totally invalid - // strings (for which WstrToInt delivers 0) give a deliver a NULL pin. - int i = WstrToInt(Id) -1; - *ppPin = GetPin(i); - if (*ppPin!=NULL){ - (*ppPin)->AddRef(); - return NOERROR; - } else { - return VFW_E_NOT_FOUND; - } -} - -// -// FindPinNumber -// -// return the number of the pin with this IPin* or -1 if none -int CSource::FindPinNumber(__in IPin *iPin) { - int i; - for (i=0; in && n>=0 it follows that m_iPins>0 - // which is what used to be checked (i.e. checking that we have a pin) - if ((n >= 0) && (n < m_iPins)) { - - ASSERT(m_paStreams[n]); - return m_paStreams[n]; - } - return NULL; -} - - -// - - -// * -// * --- CSourceStream ---- -// * - -// -// Set Id to point to a CoTaskMemAlloc'd -STDMETHODIMP CSourceStream::QueryId(__deref_out LPWSTR *Id) { - CheckPointer(Id,E_POINTER); - ValidateReadWritePtr(Id,sizeof(LPWSTR)); - - // We give the pins id's which are 1,2,... - // FindPinNumber returns -1 for an invalid pin - int i = 1+ m_pFilter->FindPinNumber(this); - if (i<1) return VFW_E_NOT_FOUND; - *Id = (LPWSTR)CoTaskMemAlloc(sizeof(WCHAR) * 12); - if (*Id==NULL) { - return E_OUTOFMEMORY; - } - IntToWstr(i, *Id); - return NOERROR; -} - - - -// -// CSourceStream::Constructor -// -// increments the number of pins present on the filter -CSourceStream::CSourceStream( - __in_opt LPCTSTR pObjectName, - __inout HRESULT *phr, - __inout CSource *ps, - __in_opt LPCWSTR pPinName) - : CBaseOutputPin(pObjectName, ps, ps->pStateLock(), phr, pPinName), - m_pFilter(ps) { - - *phr = m_pFilter->AddPin(this); -} - -#ifdef UNICODE -CSourceStream::CSourceStream( - __in_opt LPCSTR pObjectName, - __inout HRESULT *phr, - __inout CSource *ps, - __in_opt LPCWSTR pPinName) - : CBaseOutputPin(pObjectName, ps, ps->pStateLock(), phr, pPinName), - m_pFilter(ps) { - - *phr = m_pFilter->AddPin(this); -} -#endif -// -// CSourceStream::Destructor -// -// Decrements the number of pins on this filter -CSourceStream::~CSourceStream(void) { - - m_pFilter->RemovePin(this); -} - - -// -// CheckMediaType -// -// Do we support this type? Provides the default support for 1 type. -HRESULT CSourceStream::CheckMediaType(const CMediaType *pMediaType) { - - CAutoLock lock(m_pFilter->pStateLock()); - - CMediaType mt; - GetMediaType(&mt); - - if (mt == *pMediaType) { - return NOERROR; - } - - return E_FAIL; -} - - -// -// GetMediaType/3 -// -// By default we support only one type -// iPosition indexes are 0-n -HRESULT CSourceStream::GetMediaType(int iPosition, __inout CMediaType *pMediaType) { - - CAutoLock lock(m_pFilter->pStateLock()); - - if (iPosition<0) { - return E_INVALIDARG; - } - if (iPosition>0) { - return VFW_S_NO_MORE_ITEMS; - } - return GetMediaType(pMediaType); -} - - -// -// Active -// -// The pin is active - start up the worker thread -HRESULT CSourceStream::Active(void) { - - CAutoLock lock(m_pFilter->pStateLock()); - - HRESULT hr; - - if (m_pFilter->IsActive()) { - return S_FALSE; // succeeded, but did not allocate resources (they already exist...) - } - - // do nothing if not connected - its ok not to connect to - // all pins of a source filter - if (!IsConnected()) { - return NOERROR; - } - - hr = CBaseOutputPin::Active(); - if (FAILED(hr)) { - return hr; - } - - ASSERT(!ThreadExists()); - - // start the thread - if (!Create()) { - return E_FAIL; - } - - // Tell thread to initialize. If OnThreadCreate Fails, so does this. - hr = Init(); - if (FAILED(hr)) - return hr; - - return Pause(); -} - - -// -// Inactive -// -// Pin is inactive - shut down the worker thread -// Waits for the worker to exit before returning. -HRESULT CSourceStream::Inactive(void) { - - CAutoLock lock(m_pFilter->pStateLock()); - - HRESULT hr; - - // do nothing if not connected - its ok not to connect to - // all pins of a source filter - if (!IsConnected()) { - return NOERROR; - } - - // !!! need to do this before trying to stop the thread, because - // we may be stuck waiting for our own allocator!!! - - hr = CBaseOutputPin::Inactive(); // call this first to Decommit the allocator - if (FAILED(hr)) { - return hr; - } - - if (ThreadExists()) { - hr = Stop(); - - if (FAILED(hr)) { - return hr; - } - - hr = Exit(); - if (FAILED(hr)) { - return hr; - } - - Close(); // Wait for the thread to exit, then tidy up. - } - - // hr = CBaseOutputPin::Inactive(); // call this first to Decommit the allocator - //if (FAILED(hr)) { - // return hr; - //} - - return NOERROR; -} - - -// -// ThreadProc -// -// When this returns the thread exits -// Return codes > 0 indicate an error occured -DWORD CSourceStream::ThreadProc(void) { - - HRESULT hr; // the return code from calls - Command com; - - do { - com = GetRequest(); - if (com != CMD_INIT) { - DbgLog((LOG_ERROR, 1, TEXT("Thread expected init command"))); - Reply((DWORD) E_UNEXPECTED); - } - } while (com != CMD_INIT); - - DbgLog((LOG_TRACE, 1, TEXT("CSourceStream worker thread initializing"))); - - hr = OnThreadCreate(); // perform set up tasks - if (FAILED(hr)) { - DbgLog((LOG_ERROR, 1, TEXT("CSourceStream::OnThreadCreate failed. Aborting thread."))); - OnThreadDestroy(); - Reply(hr); // send failed return code from OnThreadCreate - return 1; - } - - // Initialisation suceeded - Reply(NOERROR); - - Command cmd; - do { - cmd = GetRequest(); - - switch (cmd) { - - case CMD_EXIT: - Reply(NOERROR); - break; - - case CMD_RUN: - DbgLog((LOG_ERROR, 1, TEXT("CMD_RUN received before a CMD_PAUSE???"))); - // !!! fall through??? - - case CMD_PAUSE: - Reply(NOERROR); - DoBufferProcessingLoop(); - break; - - case CMD_STOP: - Reply(NOERROR); - break; - - default: - DbgLog((LOG_ERROR, 1, TEXT("Unknown command %d received!"), cmd)); - Reply((DWORD) E_NOTIMPL); - break; - } - } while (cmd != CMD_EXIT); - - hr = OnThreadDestroy(); // tidy up. - if (FAILED(hr)) { - DbgLog((LOG_ERROR, 1, TEXT("CSourceStream::OnThreadDestroy failed. Exiting thread."))); - return 1; - } - - DbgLog((LOG_TRACE, 1, TEXT("CSourceStream worker thread exiting"))); - return 0; -} - - -// -// DoBufferProcessingLoop -// -// Grabs a buffer and calls the users processing function. -// Overridable, so that different delivery styles can be catered for. -HRESULT CSourceStream::DoBufferProcessingLoop(void) { - - Command com; - - OnThreadStartPlay(); - - do { - while (!CheckRequest(&com)) { - - IMediaSample *pSample; - - HRESULT hr = GetDeliveryBuffer(&pSample,NULL,NULL,0); - if (FAILED(hr)) { - Sleep(1); - continue; // go round again. Perhaps the error will go away - // or the allocator is decommited & we will be asked to - // exit soon. - } - - // Virtual function user will override. - hr = FillBuffer(pSample); - - if (hr == S_OK) { - hr = Deliver(pSample); - pSample->Release(); - - // downstream filter returns S_FALSE if it wants us to - // stop or an error if it's reporting an error. - if(hr != S_OK) - { - DbgLog((LOG_TRACE, 2, TEXT("Deliver() returned %08x; stopping"), hr)); - return S_OK; - } - - } else if (hr == S_FALSE) { - // derived class wants us to stop pushing data - pSample->Release(); - DeliverEndOfStream(); - return S_OK; - } else { - // derived class encountered an error - pSample->Release(); - DbgLog((LOG_ERROR, 1, TEXT("Error %08lX from FillBuffer!!!"), hr)); - DeliverEndOfStream(); - m_pFilter->NotifyEvent(EC_ERRORABORT, hr, 0); - return hr; - } - - // all paths release the sample - } - - // For all commands sent to us there must be a Reply call! - - if (com == CMD_RUN || com == CMD_PAUSE) { - Reply(NOERROR); - } else if (com != CMD_STOP) { - Reply((DWORD) E_UNEXPECTED); - DbgLog((LOG_ERROR, 1, TEXT("Unexpected command!!!"))); - } - } while (com != CMD_STOP); - - return S_FALSE; -} - diff --git a/third_party/BaseClasses/source.h b/third_party/BaseClasses/source.h deleted file mode 100644 index 528d5bcb..00000000 --- a/third_party/BaseClasses/source.h +++ /dev/null @@ -1,172 +0,0 @@ -//------------------------------------------------------------------------------ -// File: Source.h -// -// Desc: DirectShow base classes - defines classes to simplify creation of -// ActiveX source filters that support continuous generation of data. -// No support is provided for IMediaControl or IMediaPosition. -// -// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. -//------------------------------------------------------------------------------ - - -// -// Derive your source filter from CSource. -// During construction either: -// Create some CSourceStream objects to manage your pins -// Provide the user with a means of doing so eg, an IPersistFile interface. -// -// CSource provides: -// IBaseFilter interface management -// IMediaFilter interface management, via CBaseFilter -// Pin counting for CBaseFilter -// -// Derive a class from CSourceStream to manage your output pin types -// Implement GetMediaType/1 to return the type you support. If you support multiple -// types then overide GetMediaType/3, CheckMediaType and GetMediaTypeCount. -// Implement Fillbuffer() to put data into one buffer. -// -// CSourceStream provides: -// IPin management via CBaseOutputPin -// Worker thread management - -#ifndef __CSOURCE__ -#define __CSOURCE__ - -class CSourceStream; // The class that will handle each pin - - -// -// CSource -// -// Override construction to provide a means of creating -// CSourceStream derived objects - ie a way of creating pins. -class CSource : public CBaseFilter { -public: - - CSource(__in_opt LPCTSTR pName, __inout_opt LPUNKNOWN lpunk, CLSID clsid, __inout HRESULT *phr); - CSource(__in_opt LPCTSTR pName, __inout_opt LPUNKNOWN lpunk, CLSID clsid); -#ifdef UNICODE - CSource(__in_opt LPCSTR pName, __inout_opt LPUNKNOWN lpunk, CLSID clsid, __inout HRESULT *phr); - CSource(__in_opt LPCSTR pName, __inout_opt LPUNKNOWN lpunk, CLSID clsid); -#endif - ~CSource(); - - int GetPinCount(void); - CBasePin *GetPin(int n); - - // -- Utilities -- - - CCritSec* pStateLock(void) { return &m_cStateLock; } // provide our critical section - - HRESULT AddPin(__in CSourceStream *); - HRESULT RemovePin(__in CSourceStream *); - - STDMETHODIMP FindPin( - LPCWSTR Id, - __deref_out IPin ** ppPin - ); - - int FindPinNumber(__in IPin *iPin); - -protected: - - int m_iPins; // The number of pins on this filter. Updated by CSourceStream - // constructors & destructors. - CSourceStream **m_paStreams; // the pins on this filter. - - CCritSec m_cStateLock; // Lock this to serialize function accesses to the filter state - -}; - - -// -// CSourceStream -// -// Use this class to manage a stream of data that comes from a -// pin. -// Uses a worker thread to put data on the pin. -class CSourceStream : public CAMThread, public CBaseOutputPin { -public: - - CSourceStream(__in_opt LPCTSTR pObjectName, - __inout HRESULT *phr, - __inout CSource *pms, - __in_opt LPCWSTR pName); -#ifdef UNICODE - CSourceStream(__in_opt LPCSTR pObjectName, - __inout HRESULT *phr, - __inout CSource *pms, - __in_opt LPCWSTR pName); -#endif - virtual ~CSourceStream(void); // virtual destructor ensures derived class destructors are called too. - -protected: - - CSource *m_pFilter; // The parent of this stream - - // * - // * Data Source - // * - // * The following three functions: FillBuffer, OnThreadCreate/Destroy, are - // * called from within the ThreadProc. They are used in the creation of - // * the media samples this pin will provide - // * - - // Override this to provide the worker thread a means - // of processing a buffer - virtual HRESULT FillBuffer(IMediaSample *pSamp) PURE; - - // Called as the thread is created/destroyed - use to perform - // jobs such as start/stop streaming mode - // If OnThreadCreate returns an error the thread will exit. - virtual HRESULT OnThreadCreate(void) {return NOERROR;}; - virtual HRESULT OnThreadDestroy(void) {return NOERROR;}; - virtual HRESULT OnThreadStartPlay(void) {return NOERROR;}; - - // * - // * Worker Thread - // * - - HRESULT Active(void); // Starts up the worker thread - HRESULT Inactive(void); // Exits the worker thread. - -public: - // thread commands - enum Command {CMD_INIT, CMD_PAUSE, CMD_RUN, CMD_STOP, CMD_EXIT}; - HRESULT Init(void) { return CallWorker(CMD_INIT); } - HRESULT Exit(void) { return CallWorker(CMD_EXIT); } - HRESULT Run(void) { return CallWorker(CMD_RUN); } - HRESULT Pause(void) { return CallWorker(CMD_PAUSE); } - HRESULT Stop(void) { return CallWorker(CMD_STOP); } - -protected: - Command GetRequest(void) { return (Command) CAMThread::GetRequest(); } - BOOL CheckRequest(Command *pCom) { return CAMThread::CheckRequest( (DWORD *) pCom); } - - // override these if you want to add thread commands - virtual DWORD ThreadProc(void); // the thread function - - virtual HRESULT DoBufferProcessingLoop(void); // the loop executed whilst running - - - // * - // * AM_MEDIA_TYPE support - // * - - // If you support more than one media type then override these 2 functions - virtual HRESULT CheckMediaType(const CMediaType *pMediaType); - virtual HRESULT GetMediaType(int iPosition, __inout CMediaType *pMediaType); // List pos. 0-n - - // If you support only one type then override this fn. - // This will only be called by the default implementations - // of CheckMediaType and GetMediaType(int, CMediaType*) - // You must override this fn. or the above 2! - virtual HRESULT GetMediaType(__inout CMediaType *pMediaType) {return E_UNEXPECTED;} - - STDMETHODIMP QueryId( - __deref_out LPWSTR * Id - ); -}; - -#endif // __CSOURCE__ - diff --git a/third_party/BaseClasses/streams.h b/third_party/BaseClasses/streams.h index 1926321d..63f33dfe 100644 --- a/third_party/BaseClasses/streams.h +++ b/third_party/BaseClasses/streams.h @@ -159,11 +159,11 @@ LONG_PTR _SetWindowLongPtr(HWND hwnd, int nIndex, T p) //#include // ActiveMovie audio interfaces and definitions #include // General helper classes for threads etc #include // Base COM classes to support IUnknown -#include // Filter registration support functions +//#include // Filter registration support functions #include // Performance measurement -#include // Light weight com function prototypes +//#include // Light weight com function prototypes -#include // Simple cache container class +//#include // Simple cache container class #include // Non MFC generic list class #include // CMsgThread #include // Helper class for managing media types @@ -172,26 +172,26 @@ LONG_PTR _SetWindowLongPtr(HWND hwnd, int nIndex, T p) #include // control interface utility classes #include // event code definitions #include // Main streams architecture class hierachy -#include // Generic transform filter -#include // Generic transform-in-place filter +//#include // Generic transform filter +//#include // Generic transform-in-place filter #include // declaration of type GUIDs and well-known clsids -#include // Generic source filter -#include // Output pin queueing +//#include // Generic source filter +//#include // Output pin queueing #include // HRESULT status and error definitions #include // Base class for writing ActiveX renderers -#include // Helps with filters that manage windows -#include // Implements the IVideoWindow interface -#include // Specifically video related classes -#include // Base clock class -#include // System clock -#include // IPersistStream helper class -#include // Video Transform Filter base class -#include -#include // Base property page class -#include // IAMStreamControl support -#include // External device control interface defines -#include // audio filter device error event codes - +//#include // Helps with filters that manage windows +//#include // Implements the IVideoWindow interface +//#include // Specifically video related classes +const LONGLONG MAX_TIME = 0x7FFFFFFFFFFFFFFF; /* Maximum LONGLONG value */ +//#include // Base clock class +//#include // System clock +//#include // IPersistStream helper class +//#include // Video Transform Filter base class +//#include +//#include // Base property page class +//#include // IAMStreamControl support +//#include // External device control interface defines +//#include // audio filter device error event codes #else diff --git a/third_party/BaseClasses/strmctl.cpp b/third_party/BaseClasses/strmctl.cpp deleted file mode 100644 index b7f59521..00000000 --- a/third_party/BaseClasses/strmctl.cpp +++ /dev/null @@ -1,402 +0,0 @@ -//------------------------------------------------------------------------------ -// File: StrmCtl.cpp -// -// Desc: DirectShow base classes. -// -// Copyright (c) 1996-2001 Microsoft Corporation. All rights reserved. -//------------------------------------------------------------------------------ - - -#include -#include - -CBaseStreamControl::CBaseStreamControl(__inout HRESULT *phr) -: m_StreamState(STREAM_FLOWING) -, m_StreamStateOnStop(STREAM_FLOWING) // means no pending stop -, m_tStartTime(MAX_TIME) -, m_tStopTime(MAX_TIME) -, m_StreamEvent(FALSE, phr) -, m_dwStartCookie(0) -, m_dwStopCookie(0) -, m_pRefClock(NULL) -, m_FilterState(State_Stopped) -, m_bIsFlushing(FALSE) -, m_bStopSendExtra(FALSE) -{} - -CBaseStreamControl::~CBaseStreamControl() -{ - // Make sure we release the clock. - SetSyncSource(NULL); - return; -} - - -STDMETHODIMP CBaseStreamControl::StopAt(const REFERENCE_TIME * ptStop, BOOL bSendExtra, DWORD dwCookie) -{ - CAutoLock lck(&m_CritSec); - m_bStopSendExtra = FALSE; // reset - m_bStopExtraSent = FALSE; - if (ptStop) - { - if (*ptStop == MAX_TIME) - { - DbgLog((LOG_TRACE,2,TEXT("StopAt: Cancel stop"))); - CancelStop(); - // If there's now a command to start in the future, we assume - // they want to be stopped when the graph is first run - if (m_FilterState == State_Stopped && m_tStartTime < MAX_TIME) { - m_StreamState = STREAM_DISCARDING; - DbgLog((LOG_TRACE,2,TEXT("graph will begin by DISCARDING"))); - } - return NOERROR; - } - DbgLog((LOG_TRACE,2,TEXT("StopAt: %dms extra=%d"), - (int)(*ptStop/10000), bSendExtra)); - // if the first command is to stop in the future, then we assume they - // want to be started when the graph is first run - if (m_FilterState == State_Stopped && m_tStartTime > *ptStop) { - m_StreamState = STREAM_FLOWING; - DbgLog((LOG_TRACE,2,TEXT("graph will begin by FLOWING"))); - } - m_bStopSendExtra = bSendExtra; - m_tStopTime = *ptStop; - m_dwStopCookie = dwCookie; - m_StreamStateOnStop = STREAM_DISCARDING; - } - else - { - DbgLog((LOG_TRACE,2,TEXT("StopAt: now"))); - // sending an extra frame when told to stop now would mess people up - m_bStopSendExtra = FALSE; - m_tStopTime = MAX_TIME; - m_dwStopCookie = 0; - m_StreamState = STREAM_DISCARDING; - m_StreamStateOnStop = STREAM_FLOWING; // no pending stop - } - // we might change our mind what to do with a sample we're blocking - m_StreamEvent.Set(); - return NOERROR; -} - -STDMETHODIMP CBaseStreamControl::StartAt -( const REFERENCE_TIME *ptStart, DWORD dwCookie ) -{ - CAutoLock lck(&m_CritSec); - if (ptStart) - { - if (*ptStart == MAX_TIME) - { - DbgLog((LOG_TRACE,2,TEXT("StartAt: Cancel start"))); - CancelStart(); - // If there's now a command to stop in the future, we assume - // they want to be started when the graph is first run - if (m_FilterState == State_Stopped && m_tStopTime < MAX_TIME) { - DbgLog((LOG_TRACE,2,TEXT("graph will begin by FLOWING"))); - m_StreamState = STREAM_FLOWING; - } - return NOERROR; - } - DbgLog((LOG_TRACE,2,TEXT("StartAt: %dms"), (int)(*ptStart/10000))); - // if the first command is to start in the future, then we assume they - // want to be stopped when the graph is first run - if (m_FilterState == State_Stopped && m_tStopTime >= *ptStart) { - DbgLog((LOG_TRACE,2,TEXT("graph will begin by DISCARDING"))); - m_StreamState = STREAM_DISCARDING; - } - m_tStartTime = *ptStart; - m_dwStartCookie = dwCookie; - // if (m_tStopTime == m_tStartTime) CancelStop(); - } - else - { - DbgLog((LOG_TRACE,2,TEXT("StartAt: now"))); - m_tStartTime = MAX_TIME; - m_dwStartCookie = 0; - m_StreamState = STREAM_FLOWING; - } - // we might change our mind what to do with a sample we're blocking - m_StreamEvent.Set(); - return NOERROR; -} - -// Retrieve information about current settings -STDMETHODIMP CBaseStreamControl::GetInfo(__out AM_STREAM_INFO *pInfo) -{ - if (pInfo == NULL) - return E_POINTER; - - pInfo->tStart = m_tStartTime; - pInfo->tStop = m_tStopTime; - pInfo->dwStartCookie = m_dwStartCookie; - pInfo->dwStopCookie = m_dwStopCookie; - pInfo->dwFlags = m_bStopSendExtra ? AM_STREAM_INFO_STOP_SEND_EXTRA : 0; - pInfo->dwFlags |= m_tStartTime == MAX_TIME ? 0 : AM_STREAM_INFO_START_DEFINED; - pInfo->dwFlags |= m_tStopTime == MAX_TIME ? 0 : AM_STREAM_INFO_STOP_DEFINED; - switch (m_StreamState) { - default: - DbgBreak("Invalid stream state"); - case STREAM_FLOWING: - break; - case STREAM_DISCARDING: - pInfo->dwFlags |= AM_STREAM_INFO_DISCARDING; - break; - } - return S_OK; -} - - -void CBaseStreamControl::ExecuteStop() -{ - ASSERT(CritCheckIn(&m_CritSec)); - m_StreamState = m_StreamStateOnStop; - if (m_dwStopCookie && m_pSink) { - DbgLog((LOG_TRACE,2,TEXT("*sending EC_STREAM_CONTROL_STOPPED (%d)"), - m_dwStopCookie)); - m_pSink->Notify(EC_STREAM_CONTROL_STOPPED, (LONG_PTR)this, m_dwStopCookie); - } - CancelStop(); // This will do the tidy up -} - -void CBaseStreamControl::ExecuteStart() -{ - ASSERT(CritCheckIn(&m_CritSec)); - m_StreamState = STREAM_FLOWING; - if (m_dwStartCookie) { - DbgLog((LOG_TRACE,2,TEXT("*sending EC_STREAM_CONTROL_STARTED (%d)"), - m_dwStartCookie)); - m_pSink->Notify(EC_STREAM_CONTROL_STARTED, (LONG_PTR)this, m_dwStartCookie); - } - CancelStart(); // This will do the tidy up -} - -void CBaseStreamControl::CancelStop() -{ - ASSERT(CritCheckIn(&m_CritSec)); - m_tStopTime = MAX_TIME; - m_dwStopCookie = 0; - m_StreamStateOnStop = STREAM_FLOWING; -} - -void CBaseStreamControl::CancelStart() -{ - ASSERT(CritCheckIn(&m_CritSec)); - m_tStartTime = MAX_TIME; - m_dwStartCookie = 0; -} - - -// This guy will return one of the three StreamControlState's. Here's what the caller -// should do for each one: -// -// STREAM_FLOWING: Proceed as usual (render or pass the sample on) -// STREAM_DISCARDING: Calculate the time 'til *pSampleStart and wait that long -// for the event handle (GetStreamEventHandle()). If the -// wait expires, throw the sample away. If the event -// fires, call me back, I've changed my mind. -// I use pSampleStart (not Stop) so that live sources don't -// block for the duration of their samples, since the clock -// will always read approximately pSampleStart when called - - -// All through this code, you'll notice the following rules: -// - When start and stop time are the same, it's as if start was first -// - An event is considered inside the sample when it's >= sample start time -// but < sample stop time -// - if any part of the sample is supposed to be sent, we'll send the whole -// thing since we don't break it into smaller pieces -// - If we skip over a start or stop without doing it, we still signal the event -// and reset ourselves in case somebody's waiting for the event, and to make -// sure we notice that the event is past and should be forgotten -// Here are the 19 cases that have to be handled (x=start o=stop <-->=sample): -// -// 1. xo<--> start then stop -// 2. ox<--> stop then start -// 3. x start -// 4. o stop then start -// 5. x<-->o start -// 6. o<-->x stop -// 7. o start -// 8. x no change -// 9. start -// 10. stop then start -// 11. <-->xo no change -// 12. <-->ox no change -// 13. x<--> start -// 14. start -// 15. <-->x no change -// 16. o<--> stop -// 17. no change -// 18. <-->o no change -// 19. <--> no change - - -enum CBaseStreamControl::StreamControlState CBaseStreamControl::CheckSampleTimes -( __in const REFERENCE_TIME * pSampleStart, __in const REFERENCE_TIME * pSampleStop ) -{ - CAutoLock lck(&m_CritSec); - - ASSERT(!m_bIsFlushing); - ASSERT(pSampleStart && pSampleStop); - - // Don't ask me how I came up with the code below to handle all 19 cases - // - DannyMi - - if (m_tStopTime >= *pSampleStart) - { - if (m_tStartTime >= *pSampleStop) - return m_StreamState; // cases 8 11 12 15 17 18 19 - if (m_tStopTime < m_tStartTime) - ExecuteStop(); // case 10 - ExecuteStart(); // cases 3 5 7 9 13 14 - return m_StreamState; - } - - if (m_tStartTime >= *pSampleStop) - { - ExecuteStop(); // cases 6 16 - return m_StreamState; - } - - if (m_tStartTime <= m_tStopTime) - { - ExecuteStart(); - ExecuteStop(); - return m_StreamState; // case 1 - } - else - { - ExecuteStop(); - ExecuteStart(); - return m_StreamState; // cases 2 4 - } -} - - -enum CBaseStreamControl::StreamControlState CBaseStreamControl::CheckStreamState( IMediaSample * pSample ) -{ - - REFERENCE_TIME rtBufferStart, rtBufferStop; - const BOOL bNoBufferTimes = - pSample == NULL || - FAILED(pSample->GetTime(&rtBufferStart, &rtBufferStop)); - - StreamControlState state; - LONG lWait; - - do - { - // something has to break out of the blocking - if (m_bIsFlushing || m_FilterState == State_Stopped) - return STREAM_DISCARDING; - - if (bNoBufferTimes) { - // Can't do anything until we get a time stamp - state = m_StreamState; - break; - } else { - state = CheckSampleTimes( &rtBufferStart, &rtBufferStop ); - if (state == STREAM_FLOWING) - break; - - // we aren't supposed to send this, but we've been - // told to send one more than we were supposed to - // (and the stop isn't still pending and we're streaming) - if (m_bStopSendExtra && !m_bStopExtraSent && - m_tStopTime == MAX_TIME && - m_FilterState != State_Stopped) { - m_bStopExtraSent = TRUE; - DbgLog((LOG_TRACE,2,TEXT("%d sending an EXTRA frame"), - m_dwStopCookie)); - state = STREAM_FLOWING; - break; - } - } - - // We're in discarding mode - - // If we've no clock, discard as fast as we can - if (!m_pRefClock) { - break; - - // If we're paused, we can't discard in a timely manner because - // there's no such thing as stream times. We must block until - // we run or stop, or we'll end up throwing the whole stream away - // as quickly as possible - } else if (m_FilterState == State_Paused) { - lWait = INFINITE; - - } else { - // wait until it's time for the sample until we say "discard" - // ("discard in a timely fashion") - REFERENCE_TIME rtNow; - EXECUTE_ASSERT(SUCCEEDED(m_pRefClock->GetTime(&rtNow))); - rtNow -= m_tRunStart; // Into relative ref-time - lWait = LONG((rtBufferStart - rtNow)/10000); // 100ns -> ms - if (lWait < 10) break; // Not worth waiting - discard early - } - - } while(WaitForSingleObject(GetStreamEventHandle(), lWait) != WAIT_TIMEOUT); - - return state; -} - - -void CBaseStreamControl::NotifyFilterState( FILTER_STATE new_state, REFERENCE_TIME tStart ) -{ - CAutoLock lck(&m_CritSec); - - // or we will get confused - if (m_FilterState == new_state) - return; - - switch (new_state) - { - case State_Stopped: - - DbgLog((LOG_TRACE,2,TEXT("Filter is STOPPED"))); - - // execute any pending starts and stops in the right order, - // to make sure all notifications get sent, and we end up - // in the right state to begin next time (??? why not?) - - if (m_tStartTime != MAX_TIME && m_tStopTime == MAX_TIME) { - ExecuteStart(); - } else if (m_tStopTime != MAX_TIME && m_tStartTime == MAX_TIME) { - ExecuteStop(); - } else if (m_tStopTime != MAX_TIME && m_tStartTime != MAX_TIME) { - if (m_tStartTime <= m_tStopTime) { - ExecuteStart(); - ExecuteStop(); - } else { - ExecuteStop(); - ExecuteStart(); - } - } - // always start off flowing when the graph starts streaming - // unless told otherwise - m_StreamState = STREAM_FLOWING; - m_FilterState = new_state; - break; - - case State_Running: - - DbgLog((LOG_TRACE,2,TEXT("Filter is RUNNING"))); - - m_tRunStart = tStart; - // fall-through - - default: // case State_Paused: - m_FilterState = new_state; - } - // unblock! - m_StreamEvent.Set(); -} - - -void CBaseStreamControl::Flushing(BOOL bInProgress) -{ - CAutoLock lck(&m_CritSec); - m_bIsFlushing = bInProgress; - m_StreamEvent.Set(); -} diff --git a/third_party/BaseClasses/strmctl.h b/third_party/BaseClasses/strmctl.h deleted file mode 100644 index cb2adf30..00000000 --- a/third_party/BaseClasses/strmctl.h +++ /dev/null @@ -1,157 +0,0 @@ -//------------------------------------------------------------------------------ -// File: StrmCtl.h -// -// Desc: DirectShow base classes. -// -// Copyright (c) 1996-2001 Microsoft Corporation. All rights reserved. -//------------------------------------------------------------------------------ - - -#ifndef __strmctl_h__ -#define __strmctl_h__ - -class CBaseStreamControl : public IAMStreamControl -{ -public: - // Used by the implementation - enum StreamControlState - { STREAM_FLOWING = 0x1000, - STREAM_DISCARDING - }; - -private: - enum StreamControlState m_StreamState; // Current stream state - enum StreamControlState m_StreamStateOnStop; // State after next stop - // (i.e.Blocking or Discarding) - - REFERENCE_TIME m_tStartTime; // MAX_TIME implies none - REFERENCE_TIME m_tStopTime; // MAX_TIME implies none - DWORD m_dwStartCookie; // Cookie for notification to app - DWORD m_dwStopCookie; // Cookie for notification to app - volatile BOOL m_bIsFlushing; // No optimization pls! - volatile BOOL m_bStopSendExtra; // bSendExtra was set - volatile BOOL m_bStopExtraSent; // the extra one was sent - - CCritSec m_CritSec; // CritSec to guard above attributes - - // Event to fire when we can come - // out of blocking, or to come out of waiting - // to discard if we change our minds. - // - CAMEvent m_StreamEvent; - - // All of these methods execute immediately. Helpers for others. - // - void ExecuteStop(); - void ExecuteStart(); - void CancelStop(); - void CancelStart(); - - // Some things we need to be told by our owning filter - // Your pin must also expose IAMStreamControl when QI'd for it! - // - IReferenceClock * m_pRefClock; // Need it to set advises - // Filter must tell us via - // SetSyncSource - IMediaEventSink * m_pSink; // Event sink - // Filter must tell us after it - // creates it in JoinFilterGraph() - FILTER_STATE m_FilterState; // Just need it! - // Filter must tell us via - // NotifyFilterState - REFERENCE_TIME m_tRunStart; // Per the Run call to the filter - - // This guy will return one of the three StreamControlState's. Here's what - // the caller should do for each one: - // - // STREAM_FLOWING: Proceed as usual (render or pass the sample on) - // STREAM_DISCARDING: Calculate the time 'til *pSampleStop and wait - // that long for the event handle - // (GetStreamEventHandle()). If the wait - // expires, throw the sample away. If the event - // fires, call me back - I've changed my mind. - // - enum StreamControlState CheckSampleTimes( __in const REFERENCE_TIME * pSampleStart, - __in const REFERENCE_TIME * pSampleStop ); - -public: - // You don't have to tell us much when we're created, but there are other - // obligations that must be met. See SetSyncSource & NotifyFilterState - // below. - // - CBaseStreamControl(__inout_opt HRESULT *phr = NULL); - ~CBaseStreamControl(); - - // If you want this class to work properly, there are thing you need to - // (keep) telling it. Filters with pins that use this class - // should ensure that they pass through to this method any calls they - // receive on their SetSyncSource. - - // We need a clock to see what time it is. This is for the - // "discard in a timely fashion" logic. If we discard everything as - // quick as possible, a whole 60 minute file could get discarded in the - // first 10 seconds, and if somebody wants to turn streaming on at 30 - // minutes into the file, and they make the call more than a few seconds - // after the graph is run, it may be too late! - // So we hold every sample until it's time has gone, then we discard it. - // The filter should call this when it gets a SetSyncSource - // - void SetSyncSource( IReferenceClock * pRefClock ) - { - CAutoLock lck(&m_CritSec); - if (m_pRefClock) m_pRefClock->Release(); - m_pRefClock = pRefClock; - if (m_pRefClock) m_pRefClock->AddRef(); - } - - // Set event sink for notifications - // The filter should call this in its JoinFilterGraph after it creates the - // IMediaEventSink - // - void SetFilterGraph( IMediaEventSink *pSink ) { - m_pSink = pSink; - } - - // Since we schedule in stream time, we need the tStart and must track the - // state of our owning filter. - // The app should call this ever state change - // - void NotifyFilterState( FILTER_STATE new_state, REFERENCE_TIME tStart = 0 ); - - // Filter should call Flushing(TRUE) in BeginFlush, - // and Flushing(FALSE) in EndFlush. - // - void Flushing( BOOL bInProgress ); - - - // The two main methods of IAMStreamControl - - // Class adds default values suitable for immediate - // muting and unmuting of the stream. - - STDMETHODIMP StopAt( const REFERENCE_TIME * ptStop = NULL, - BOOL bSendExtra = FALSE, - DWORD dwCookie = 0 ); - STDMETHODIMP StartAt( const REFERENCE_TIME * ptStart = NULL, - DWORD dwCookie = 0 ); - STDMETHODIMP GetInfo( __out AM_STREAM_INFO *pInfo); - - // Helper function for pin's receive method. Call this with - // the sample and we'll tell you what to do with it. We'll do a - // WaitForSingleObject within this call if one is required. This is - // a "What should I do with this sample?" kind of call. We'll tell the - // caller to either flow it or discard it. - // If pSample is NULL we evaluate based on the current state - // settings - enum StreamControlState CheckStreamState( IMediaSample * pSample ); - -private: - // These don't require locking, but we are relying on the fact that - // m_StreamState can be retrieved with integrity, and is a snap shot that - // may have just been, or may be just about to be, changed. - HANDLE GetStreamEventHandle() const { return m_StreamEvent; } - enum StreamControlState GetStreamState() const { return m_StreamState; } - BOOL IsStreaming() const { return m_StreamState == STREAM_FLOWING; } -}; - -#endif diff --git a/third_party/BaseClasses/sysclock.cpp b/third_party/BaseClasses/sysclock.cpp deleted file mode 100644 index 0d582917..00000000 --- a/third_party/BaseClasses/sysclock.cpp +++ /dev/null @@ -1,74 +0,0 @@ -//------------------------------------------------------------------------------ -// File: SysClock.cpp -// -// Desc: DirectShow base classes - implements a system clock based on -// IReferenceClock. -// -// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. -//------------------------------------------------------------------------------ - - -#include -#include - - -#ifdef FILTER_DLL - -/* List of class IDs and creator functions for the class factory. This - provides the link between the OLE entry point in the DLL and an object - being created. The class factory will call the static CreateInstance - function when it is asked to create a CLSID_SystemClock object */ - -CFactoryTemplate g_Templates[1] = { - {&CLSID_SystemClock, CSystemClock::CreateInstance} -}; - -int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]); -#endif - -/* This goes in the factory template table to create new instances */ -CUnknown * WINAPI CSystemClock::CreateInstance(__inout_opt LPUNKNOWN pUnk, __inout HRESULT *phr) -{ - return new CSystemClock(NAME("System reference clock"),pUnk, phr); -} - - -CSystemClock::CSystemClock(__in_opt LPCTSTR pName, __inout_opt LPUNKNOWN pUnk, __inout HRESULT *phr) : - CBaseReferenceClock(pName, pUnk, phr) -{ -} - -STDMETHODIMP CSystemClock::NonDelegatingQueryInterface( - REFIID riid, - __deref_out void ** ppv) -{ - if (riid == IID_IPersist) - { - return GetInterface(static_cast(this), ppv); - } - else if (riid == IID_IAMClockAdjust) - { - return GetInterface(static_cast(this), ppv); - } - else - { - return CBaseReferenceClock::NonDelegatingQueryInterface(riid, ppv); - } -} - -/* Return the clock's clsid */ -STDMETHODIMP -CSystemClock::GetClassID(__out CLSID *pClsID) -{ - CheckPointer(pClsID,E_POINTER); - ValidateReadWritePtr(pClsID,sizeof(CLSID)); - *pClsID = CLSID_SystemClock; - return NOERROR; -} - - -STDMETHODIMP -CSystemClock::SetClockDelta(REFERENCE_TIME rtDelta) -{ - return SetTimeDelta(rtDelta); -} diff --git a/third_party/BaseClasses/sysclock.h b/third_party/BaseClasses/sysclock.h deleted file mode 100644 index 3976d346..00000000 --- a/third_party/BaseClasses/sysclock.h +++ /dev/null @@ -1,39 +0,0 @@ -//------------------------------------------------------------------------------ -// File: SysClock.h -// -// Desc: DirectShow base classes - defines a system clock implementation of -// IReferenceClock. -// -// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. -//------------------------------------------------------------------------------ - - -#ifndef __SYSTEMCLOCK__ -#define __SYSTEMCLOCK__ - -// -// Base clock. Uses timeGetTime ONLY -// Uses most of the code in the base reference clock. -// Provides GetTime -// - -class CSystemClock : public CBaseReferenceClock, public IAMClockAdjust, public IPersist -{ -public: - // We must be able to create an instance of ourselves - static CUnknown * WINAPI CreateInstance(__inout_opt LPUNKNOWN pUnk, __inout HRESULT *phr); - CSystemClock(__in_opt LPCTSTR pName, __inout_opt LPUNKNOWN pUnk, __inout HRESULT *phr); - - DECLARE_IUNKNOWN - - STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void ** ppv); - - // Yield up our class id so that we can be persisted - // Implement required Ipersist method - STDMETHODIMP GetClassID(__out CLSID *pClsID); - - // IAMClockAdjust methods - STDMETHODIMP SetClockDelta(REFERENCE_TIME rtDelta); -}; //CSystemClock - -#endif /* __SYSTEMCLOCK__ */ diff --git a/third_party/BaseClasses/transfrm.cpp b/third_party/BaseClasses/transfrm.cpp deleted file mode 100644 index 3d170779..00000000 --- a/third_party/BaseClasses/transfrm.cpp +++ /dev/null @@ -1,1016 +0,0 @@ -//------------------------------------------------------------------------------ -// File: Transfrm.cpp -// -// Desc: DirectShow base classes - implements class for simple transform -// filters such as video decompressors. -// -// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. -//------------------------------------------------------------------------------ - - -#include -#include - - -// ================================================================= -// Implements the CTransformFilter class -// ================================================================= - -CTransformFilter::CTransformFilter(__in_opt LPCTSTR pName, - __inout_opt LPUNKNOWN pUnk, - REFCLSID clsid) : - CBaseFilter(pName,pUnk,&m_csFilter, clsid), - m_pInput(NULL), - m_pOutput(NULL), - m_bEOSDelivered(FALSE), - m_bQualityChanged(FALSE), - m_bSampleSkipped(FALSE) -{ -#ifdef PERF - RegisterPerfId(); -#endif // PERF -} - -#ifdef UNICODE -CTransformFilter::CTransformFilter(__in_opt LPCSTR pName, - __inout_opt LPUNKNOWN pUnk, - REFCLSID clsid) : - CBaseFilter(pName,pUnk,&m_csFilter, clsid), - m_pInput(NULL), - m_pOutput(NULL), - m_bEOSDelivered(FALSE), - m_bQualityChanged(FALSE), - m_bSampleSkipped(FALSE) -{ -#ifdef PERF - RegisterPerfId(); -#endif // PERF -} -#endif - -// destructor - -CTransformFilter::~CTransformFilter() -{ - // Delete the pins - - delete m_pInput; - delete m_pOutput; -} - - -// Transform place holder - should never be called -HRESULT CTransformFilter::Transform(IMediaSample * pIn, IMediaSample *pOut) -{ - UNREFERENCED_PARAMETER(pIn); - UNREFERENCED_PARAMETER(pOut); - DbgBreak("CTransformFilter::Transform() should never be called"); - return E_UNEXPECTED; -} - - -// return the number of pins we provide - -int CTransformFilter::GetPinCount() -{ - return 2; -} - - -// return a non-addrefed CBasePin * for the user to addref if he holds onto it -// for longer than his pointer to us. We create the pins dynamically when they -// are asked for rather than in the constructor. This is because we want to -// give the derived class an oppportunity to return different pin objects - -// We return the objects as and when they are needed. If either of these fails -// then we return NULL, the assumption being that the caller will realise the -// whole deal is off and destroy us - which in turn will delete everything. - -CBasePin * -CTransformFilter::GetPin(int n) -{ - HRESULT hr = S_OK; - - // Create an input pin if necessary - - if (m_pInput == NULL) { - - m_pInput = new CTransformInputPin(NAME("Transform input pin"), - this, // Owner filter - &hr, // Result code - L"XForm In"); // Pin name - - - // Can't fail - ASSERT(SUCCEEDED(hr)); - if (m_pInput == NULL) { - return NULL; - } - m_pOutput = (CTransformOutputPin *) - new CTransformOutputPin(NAME("Transform output pin"), - this, // Owner filter - &hr, // Result code - L"XForm Out"); // Pin name - - - // Can't fail - ASSERT(SUCCEEDED(hr)); - if (m_pOutput == NULL) { - delete m_pInput; - m_pInput = NULL; - } - } - - // Return the appropriate pin - - if (n == 0) { - return m_pInput; - } else - if (n == 1) { - return m_pOutput; - } else { - return NULL; - } -} - - -// -// FindPin -// -// If Id is In or Out then return the IPin* for that pin -// creating the pin if need be. Otherwise return NULL with an error. - -STDMETHODIMP CTransformFilter::FindPin(LPCWSTR Id, __deref_out IPin **ppPin) -{ - CheckPointer(ppPin,E_POINTER); - ValidateReadWritePtr(ppPin,sizeof(IPin *)); - - if (0==lstrcmpW(Id,L"In")) { - *ppPin = GetPin(0); - } else if (0==lstrcmpW(Id,L"Out")) { - *ppPin = GetPin(1); - } else { - *ppPin = NULL; - return VFW_E_NOT_FOUND; - } - - HRESULT hr = NOERROR; - // AddRef() returned pointer - but GetPin could fail if memory is low. - if (*ppPin) { - (*ppPin)->AddRef(); - } else { - hr = E_OUTOFMEMORY; // probably. There's no pin anyway. - } - return hr; -} - - -// override these two functions if you want to inform something -// about entry to or exit from streaming state. - -HRESULT -CTransformFilter::StartStreaming() -{ - return NOERROR; -} - - -HRESULT -CTransformFilter::StopStreaming() -{ - return NOERROR; -} - - -// override this to grab extra interfaces on connection - -HRESULT -CTransformFilter::CheckConnect(PIN_DIRECTION dir, IPin *pPin) -{ - UNREFERENCED_PARAMETER(dir); - UNREFERENCED_PARAMETER(pPin); - return NOERROR; -} - - -// place holder to allow derived classes to release any extra interfaces - -HRESULT -CTransformFilter::BreakConnect(PIN_DIRECTION dir) -{ - UNREFERENCED_PARAMETER(dir); - return NOERROR; -} - - -// Let derived classes know about connection completion - -HRESULT -CTransformFilter::CompleteConnect(PIN_DIRECTION direction,IPin *pReceivePin) -{ - UNREFERENCED_PARAMETER(direction); - UNREFERENCED_PARAMETER(pReceivePin); - return NOERROR; -} - - -// override this to know when the media type is really set - -HRESULT -CTransformFilter::SetMediaType(PIN_DIRECTION direction,const CMediaType *pmt) -{ - UNREFERENCED_PARAMETER(direction); - UNREFERENCED_PARAMETER(pmt); - return NOERROR; -} - - -// Set up our output sample -HRESULT -CTransformFilter::InitializeOutputSample(IMediaSample *pSample, __deref_out IMediaSample **ppOutSample) -{ - IMediaSample *pOutSample; - - // default - times are the same - - AM_SAMPLE2_PROPERTIES * const pProps = m_pInput->SampleProps(); - DWORD dwFlags = m_bSampleSkipped ? AM_GBF_PREVFRAMESKIPPED : 0; - - // This will prevent the image renderer from switching us to DirectDraw - // when we can't do it without skipping frames because we're not on a - // keyframe. If it really has to switch us, it still will, but then we - // will have to wait for the next keyframe - if (!(pProps->dwSampleFlags & AM_SAMPLE_SPLICEPOINT)) { - dwFlags |= AM_GBF_NOTASYNCPOINT; - } - - ASSERT(m_pOutput->m_pAllocator != NULL); - HRESULT hr = m_pOutput->m_pAllocator->GetBuffer( - &pOutSample - , pProps->dwSampleFlags & AM_SAMPLE_TIMEVALID ? - &pProps->tStart : NULL - , pProps->dwSampleFlags & AM_SAMPLE_STOPVALID ? - &pProps->tStop : NULL - , dwFlags - ); - *ppOutSample = pOutSample; - if (FAILED(hr)) { - return hr; - } - - ASSERT(pOutSample); - IMediaSample2 *pOutSample2; - if (SUCCEEDED(pOutSample->QueryInterface(IID_IMediaSample2, - (void **)&pOutSample2))) { - /* Modify it */ - AM_SAMPLE2_PROPERTIES OutProps; - EXECUTE_ASSERT(SUCCEEDED(pOutSample2->GetProperties( - FIELD_OFFSET(AM_SAMPLE2_PROPERTIES, tStart), (PBYTE)&OutProps) - )); - OutProps.dwTypeSpecificFlags = pProps->dwTypeSpecificFlags; - OutProps.dwSampleFlags = - (OutProps.dwSampleFlags & AM_SAMPLE_TYPECHANGED) | - (pProps->dwSampleFlags & ~AM_SAMPLE_TYPECHANGED); - OutProps.tStart = pProps->tStart; - OutProps.tStop = pProps->tStop; - OutProps.cbData = FIELD_OFFSET(AM_SAMPLE2_PROPERTIES, dwStreamId); - hr = pOutSample2->SetProperties( - FIELD_OFFSET(AM_SAMPLE2_PROPERTIES, dwStreamId), - (PBYTE)&OutProps - ); - if (pProps->dwSampleFlags & AM_SAMPLE_DATADISCONTINUITY) { - m_bSampleSkipped = FALSE; - } - pOutSample2->Release(); - } else { - if (pProps->dwSampleFlags & AM_SAMPLE_TIMEVALID) { - pOutSample->SetTime(&pProps->tStart, - &pProps->tStop); - } - if (pProps->dwSampleFlags & AM_SAMPLE_SPLICEPOINT) { - pOutSample->SetSyncPoint(TRUE); - } - if (pProps->dwSampleFlags & AM_SAMPLE_DATADISCONTINUITY) { - pOutSample->SetDiscontinuity(TRUE); - m_bSampleSkipped = FALSE; - } - // Copy the media times - - LONGLONG MediaStart, MediaEnd; - if (pSample->GetMediaTime(&MediaStart,&MediaEnd) == NOERROR) { - pOutSample->SetMediaTime(&MediaStart,&MediaEnd); - } - } - return S_OK; -} - -// override this to customize the transform process - -HRESULT -CTransformFilter::Receive(IMediaSample *pSample) -{ - /* Check for other streams and pass them on */ - AM_SAMPLE2_PROPERTIES * const pProps = m_pInput->SampleProps(); - if (pProps->dwStreamId != AM_STREAM_MEDIA) { - return m_pOutput->m_pInputPin->Receive(pSample); - } - HRESULT hr; - ASSERT(pSample); - IMediaSample * pOutSample; - - // If no output to deliver to then no point sending us data - - ASSERT (m_pOutput != NULL) ; - - // Set up the output sample - hr = InitializeOutputSample(pSample, &pOutSample); - - if (FAILED(hr)) { - return hr; - } - - // Start timing the transform (if PERF is defined) - MSR_START(m_idTransform); - - // have the derived class transform the data - - hr = Transform(pSample, pOutSample); - - // Stop the clock and log it (if PERF is defined) - MSR_STOP(m_idTransform); - - if (FAILED(hr)) { - DbgLog((LOG_TRACE,1,TEXT("Error from transform"))); - } else { - // the Transform() function can return S_FALSE to indicate that the - // sample should not be delivered; we only deliver the sample if it's - // really S_OK (same as NOERROR, of course.) - if (hr == NOERROR) { - hr = m_pOutput->m_pInputPin->Receive(pOutSample); - m_bSampleSkipped = FALSE; // last thing no longer dropped - } else { - // S_FALSE returned from Transform is a PRIVATE agreement - // We should return NOERROR from Receive() in this cause because returning S_FALSE - // from Receive() means that this is the end of the stream and no more data should - // be sent. - if (S_FALSE == hr) { - - // Release the sample before calling notify to avoid - // deadlocks if the sample holds a lock on the system - // such as DirectDraw buffers do - pOutSample->Release(); - m_bSampleSkipped = TRUE; - if (!m_bQualityChanged) { - NotifyEvent(EC_QUALITY_CHANGE,0,0); - m_bQualityChanged = TRUE; - } - return NOERROR; - } - } - } - - // release the output buffer. If the connected pin still needs it, - // it will have addrefed it itself. - pOutSample->Release(); - - return hr; -} - - -// Return S_FALSE to mean "pass the note on upstream" -// Return NOERROR (Same as S_OK) -// to mean "I've done something about it, don't pass it on" -HRESULT CTransformFilter::AlterQuality(Quality q) -{ - UNREFERENCED_PARAMETER(q); - return S_FALSE; -} - - -// EndOfStream received. Default behaviour is to deliver straight -// downstream, since we have no queued data. If you overrode Receive -// and have queue data, then you need to handle this and deliver EOS after -// all queued data is sent -HRESULT -CTransformFilter::EndOfStream(void) -{ - HRESULT hr = NOERROR; - if (m_pOutput != NULL) { - hr = m_pOutput->DeliverEndOfStream(); - } - - return hr; -} - - -// enter flush state. Receives already blocked -// must override this if you have queued data or a worker thread -HRESULT -CTransformFilter::BeginFlush(void) -{ - HRESULT hr = NOERROR; - if (m_pOutput != NULL) { - // block receives -- done by caller (CBaseInputPin::BeginFlush) - - // discard queued data -- we have no queued data - - // free anyone blocked on receive - not possible in this filter - - // call downstream - hr = m_pOutput->DeliverBeginFlush(); - } - return hr; -} - - -// leave flush state. must override this if you have queued data -// or a worker thread -HRESULT -CTransformFilter::EndFlush(void) -{ - // sync with pushing thread -- we have no worker thread - - // ensure no more data to go downstream -- we have no queued data - - // call EndFlush on downstream pins - ASSERT (m_pOutput != NULL); - return m_pOutput->DeliverEndFlush(); - - // caller (the input pin's method) will unblock Receives -} - - -// override these so that the derived filter can catch them - -STDMETHODIMP -CTransformFilter::Stop() -{ - CAutoLock lck1(&m_csFilter); - if (m_State == State_Stopped) { - return NOERROR; - } - - // Succeed the Stop if we are not completely connected - - ASSERT(m_pInput == NULL || m_pOutput != NULL); - if (m_pInput == NULL || m_pInput->IsConnected() == FALSE || - m_pOutput->IsConnected() == FALSE) { - m_State = State_Stopped; - m_bEOSDelivered = FALSE; - return NOERROR; - } - - ASSERT(m_pInput); - ASSERT(m_pOutput); - - // decommit the input pin before locking or we can deadlock - m_pInput->Inactive(); - - // synchronize with Receive calls - - CAutoLock lck2(&m_csReceive); - m_pOutput->Inactive(); - - // allow a class derived from CTransformFilter - // to know about starting and stopping streaming - - HRESULT hr = StopStreaming(); - if (SUCCEEDED(hr)) { - // complete the state transition - m_State = State_Stopped; - m_bEOSDelivered = FALSE; - } - return hr; -} - - -STDMETHODIMP -CTransformFilter::Pause() -{ - CAutoLock lck(&m_csFilter); - HRESULT hr = NOERROR; - - if (m_State == State_Paused) { - // (This space left deliberately blank) - } - - // If we have no input pin or it isn't yet connected then when we are - // asked to pause we deliver an end of stream to the downstream filter. - // This makes sure that it doesn't sit there forever waiting for - // samples which we cannot ever deliver without an input connection. - - else if (m_pInput == NULL || m_pInput->IsConnected() == FALSE) { - if (m_pOutput && m_bEOSDelivered == FALSE) { - m_pOutput->DeliverEndOfStream(); - m_bEOSDelivered = TRUE; - } - m_State = State_Paused; - } - - // We may have an input connection but no output connection - // However, if we have an input pin we do have an output pin - - else if (m_pOutput->IsConnected() == FALSE) { - m_State = State_Paused; - } - - else { - if (m_State == State_Stopped) { - // allow a class derived from CTransformFilter - // to know about starting and stopping streaming - CAutoLock lck2(&m_csReceive); - hr = StartStreaming(); - } - if (SUCCEEDED(hr)) { - hr = CBaseFilter::Pause(); - } - } - - m_bSampleSkipped = FALSE; - m_bQualityChanged = FALSE; - return hr; -} - -HRESULT -CTransformFilter::NewSegment( - REFERENCE_TIME tStart, - REFERENCE_TIME tStop, - double dRate) -{ - if (m_pOutput != NULL) { - return m_pOutput->DeliverNewSegment(tStart, tStop, dRate); - } - return S_OK; -} - -// Check streaming status -HRESULT -CTransformInputPin::CheckStreaming() -{ - ASSERT(m_pTransformFilter->m_pOutput != NULL); - if (!m_pTransformFilter->m_pOutput->IsConnected()) { - return VFW_E_NOT_CONNECTED; - } else { - // Shouldn't be able to get any data if we're not connected! - ASSERT(IsConnected()); - - // we're flushing - if (m_bFlushing) { - return S_FALSE; - } - // Don't process stuff in Stopped state - if (IsStopped()) { - return VFW_E_WRONG_STATE; - } - if (m_bRunTimeError) { - return VFW_E_RUNTIME_ERROR; - } - return S_OK; - } -} - - -// ================================================================= -// Implements the CTransformInputPin class -// ================================================================= - - -// constructor - -CTransformInputPin::CTransformInputPin( - __in_opt LPCTSTR pObjectName, - __inout CTransformFilter *pTransformFilter, - __inout HRESULT * phr, - __in_opt LPCWSTR pName) - : CBaseInputPin(pObjectName, pTransformFilter, &pTransformFilter->m_csFilter, phr, pName) -{ - DbgLog((LOG_TRACE,2,TEXT("CTransformInputPin::CTransformInputPin"))); - m_pTransformFilter = pTransformFilter; -} - -#ifdef UNICODE -CTransformInputPin::CTransformInputPin( - __in_opt LPCSTR pObjectName, - __inout CTransformFilter *pTransformFilter, - __inout HRESULT * phr, - __in_opt LPCWSTR pName) - : CBaseInputPin(pObjectName, pTransformFilter, &pTransformFilter->m_csFilter, phr, pName) -{ - DbgLog((LOG_TRACE,2,TEXT("CTransformInputPin::CTransformInputPin"))); - m_pTransformFilter = pTransformFilter; -} -#endif - -// provides derived filter a chance to grab extra interfaces - -HRESULT -CTransformInputPin::CheckConnect(IPin *pPin) -{ - HRESULT hr = m_pTransformFilter->CheckConnect(PINDIR_INPUT,pPin); - if (FAILED(hr)) { - return hr; - } - return CBaseInputPin::CheckConnect(pPin); -} - - -// provides derived filter a chance to release it's extra interfaces - -HRESULT -CTransformInputPin::BreakConnect() -{ - // Can't disconnect unless stopped - ASSERT(IsStopped()); - m_pTransformFilter->BreakConnect(PINDIR_INPUT); - return CBaseInputPin::BreakConnect(); -} - - -// Let derived class know when the input pin is connected - -HRESULT -CTransformInputPin::CompleteConnect(IPin *pReceivePin) -{ - HRESULT hr = m_pTransformFilter->CompleteConnect(PINDIR_INPUT,pReceivePin); - if (FAILED(hr)) { - return hr; - } - return CBaseInputPin::CompleteConnect(pReceivePin); -} - - -// check that we can support a given media type - -HRESULT -CTransformInputPin::CheckMediaType(const CMediaType* pmt) -{ - // Check the input type - - HRESULT hr = m_pTransformFilter->CheckInputType(pmt); - if (S_OK != hr) { - return hr; - } - - // if the output pin is still connected, then we have - // to check the transform not just the input format - - if ((m_pTransformFilter->m_pOutput != NULL) && - (m_pTransformFilter->m_pOutput->IsConnected())) { - return m_pTransformFilter->CheckTransform( - pmt, - &m_pTransformFilter->m_pOutput->CurrentMediaType()); - } else { - return hr; - } -} - - -// set the media type for this connection - -HRESULT -CTransformInputPin::SetMediaType(const CMediaType* mtIn) -{ - // Set the base class media type (should always succeed) - HRESULT hr = CBasePin::SetMediaType(mtIn); - if (FAILED(hr)) { - return hr; - } - - // check the transform can be done (should always succeed) - ASSERT(SUCCEEDED(m_pTransformFilter->CheckInputType(mtIn))); - - return m_pTransformFilter->SetMediaType(PINDIR_INPUT,mtIn); -} - - -// ================================================================= -// Implements IMemInputPin interface -// ================================================================= - - -// provide EndOfStream that passes straight downstream -// (there is no queued data) -STDMETHODIMP -CTransformInputPin::EndOfStream(void) -{ - CAutoLock lck(&m_pTransformFilter->m_csReceive); - HRESULT hr = CheckStreaming(); - if (S_OK == hr) { - hr = m_pTransformFilter->EndOfStream(); - } - return hr; -} - - -// enter flushing state. Call default handler to block Receives, then -// pass to overridable method in filter -STDMETHODIMP -CTransformInputPin::BeginFlush(void) -{ - CAutoLock lck(&m_pTransformFilter->m_csFilter); - // Are we actually doing anything? - ASSERT(m_pTransformFilter->m_pOutput != NULL); - if (!IsConnected() || - !m_pTransformFilter->m_pOutput->IsConnected()) { - return VFW_E_NOT_CONNECTED; - } - HRESULT hr = CBaseInputPin::BeginFlush(); - if (FAILED(hr)) { - return hr; - } - - return m_pTransformFilter->BeginFlush(); -} - - -// leave flushing state. -// Pass to overridable method in filter, then call base class -// to unblock receives (finally) -STDMETHODIMP -CTransformInputPin::EndFlush(void) -{ - CAutoLock lck(&m_pTransformFilter->m_csFilter); - // Are we actually doing anything? - ASSERT(m_pTransformFilter->m_pOutput != NULL); - if (!IsConnected() || - !m_pTransformFilter->m_pOutput->IsConnected()) { - return VFW_E_NOT_CONNECTED; - } - - HRESULT hr = m_pTransformFilter->EndFlush(); - if (FAILED(hr)) { - return hr; - } - - return CBaseInputPin::EndFlush(); -} - - -// here's the next block of data from the stream. -// AddRef it yourself if you need to hold it beyond the end -// of this call. - -HRESULT -CTransformInputPin::Receive(IMediaSample * pSample) -{ - HRESULT hr; - CAutoLock lck(&m_pTransformFilter->m_csReceive); - ASSERT(pSample); - - // check all is well with the base class - hr = CBaseInputPin::Receive(pSample); - if (S_OK == hr) { - hr = m_pTransformFilter->Receive(pSample); - } - return hr; -} - - - - -// override to pass downstream -STDMETHODIMP -CTransformInputPin::NewSegment( - REFERENCE_TIME tStart, - REFERENCE_TIME tStop, - double dRate) -{ - // Save the values in the pin - CBasePin::NewSegment(tStart, tStop, dRate); - return m_pTransformFilter->NewSegment(tStart, tStop, dRate); -} - - - - -// ================================================================= -// Implements the CTransformOutputPin class -// ================================================================= - - -// constructor - -CTransformOutputPin::CTransformOutputPin( - __in_opt LPCTSTR pObjectName, - __inout CTransformFilter *pTransformFilter, - __inout HRESULT * phr, - __in_opt LPCWSTR pPinName) - : CBaseOutputPin(pObjectName, pTransformFilter, &pTransformFilter->m_csFilter, phr, pPinName), - m_pPosition(NULL) -{ - DbgLog((LOG_TRACE,2,TEXT("CTransformOutputPin::CTransformOutputPin"))); - m_pTransformFilter = pTransformFilter; - -} - -#ifdef UNICODE -CTransformOutputPin::CTransformOutputPin( - __in_opt LPCSTR pObjectName, - __inout CTransformFilter *pTransformFilter, - __inout HRESULT * phr, - __in_opt LPCWSTR pPinName) - : CBaseOutputPin(pObjectName, pTransformFilter, &pTransformFilter->m_csFilter, phr, pPinName), - m_pPosition(NULL) -{ - DbgLog((LOG_TRACE,2,TEXT("CTransformOutputPin::CTransformOutputPin"))); - m_pTransformFilter = pTransformFilter; - -} -#endif - -// destructor - -CTransformOutputPin::~CTransformOutputPin() -{ - DbgLog((LOG_TRACE,2,TEXT("CTransformOutputPin::~CTransformOutputPin"))); - - if (m_pPosition) m_pPosition->Release(); -} - - -// overriden to expose IMediaPosition and IMediaSeeking control interfaces - -STDMETHODIMP -CTransformOutputPin::NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv) -{ - CheckPointer(ppv,E_POINTER); - ValidateReadWritePtr(ppv,sizeof(PVOID)); - *ppv = NULL; - - if (riid == IID_IMediaPosition || riid == IID_IMediaSeeking) { - - // we should have an input pin by now - - ASSERT(m_pTransformFilter->m_pInput != NULL); - - if (m_pPosition == NULL) { - - HRESULT hr = CreatePosPassThru( - GetOwner(), - FALSE, - (IPin *)m_pTransformFilter->m_pInput, - &m_pPosition); - if (FAILED(hr)) { - return hr; - } - } - return m_pPosition->QueryInterface(riid, ppv); - } else { - return CBaseOutputPin::NonDelegatingQueryInterface(riid, ppv); - } -} - - -// provides derived filter a chance to grab extra interfaces - -HRESULT -CTransformOutputPin::CheckConnect(IPin *pPin) -{ - // we should have an input connection first - - ASSERT(m_pTransformFilter->m_pInput != NULL); - if ((m_pTransformFilter->m_pInput->IsConnected() == FALSE)) { - return E_UNEXPECTED; - } - - HRESULT hr = m_pTransformFilter->CheckConnect(PINDIR_OUTPUT,pPin); - if (FAILED(hr)) { - return hr; - } - return CBaseOutputPin::CheckConnect(pPin); -} - - -// provides derived filter a chance to release it's extra interfaces - -HRESULT -CTransformOutputPin::BreakConnect() -{ - // Can't disconnect unless stopped - ASSERT(IsStopped()); - m_pTransformFilter->BreakConnect(PINDIR_OUTPUT); - return CBaseOutputPin::BreakConnect(); -} - - -// Let derived class know when the output pin is connected - -HRESULT -CTransformOutputPin::CompleteConnect(IPin *pReceivePin) -{ - HRESULT hr = m_pTransformFilter->CompleteConnect(PINDIR_OUTPUT,pReceivePin); - if (FAILED(hr)) { - return hr; - } - return CBaseOutputPin::CompleteConnect(pReceivePin); -} - - -// check a given transform - must have selected input type first - -HRESULT -CTransformOutputPin::CheckMediaType(const CMediaType* pmtOut) -{ - // must have selected input first - ASSERT(m_pTransformFilter->m_pInput != NULL); - if ((m_pTransformFilter->m_pInput->IsConnected() == FALSE)) { - return E_INVALIDARG; - } - - return m_pTransformFilter->CheckTransform( - &m_pTransformFilter->m_pInput->CurrentMediaType(), - pmtOut); -} - - -// called after we have agreed a media type to actually set it in which case -// we run the CheckTransform function to get the output format type again - -HRESULT -CTransformOutputPin::SetMediaType(const CMediaType* pmtOut) -{ - HRESULT hr = NOERROR; - ASSERT(m_pTransformFilter->m_pInput != NULL); - - ASSERT(m_pTransformFilter->m_pInput->CurrentMediaType().IsValid()); - - // Set the base class media type (should always succeed) - hr = CBasePin::SetMediaType(pmtOut); - if (FAILED(hr)) { - return hr; - } - -#ifdef DEBUG - if (FAILED(m_pTransformFilter->CheckTransform(&m_pTransformFilter-> - m_pInput->CurrentMediaType(),pmtOut))) { - DbgLog((LOG_ERROR,0,TEXT("*** This filter is accepting an output media type"))); - DbgLog((LOG_ERROR,0,TEXT(" that it can't currently transform to. I hope"))); - DbgLog((LOG_ERROR,0,TEXT(" it's smart enough to reconnect its input."))); - } -#endif - - return m_pTransformFilter->SetMediaType(PINDIR_OUTPUT,pmtOut); -} - - -// pass the buffer size decision through to the main transform class - -HRESULT -CTransformOutputPin::DecideBufferSize( - IMemAllocator * pAllocator, - __inout ALLOCATOR_PROPERTIES* pProp) -{ - return m_pTransformFilter->DecideBufferSize(pAllocator, pProp); -} - - - -// return a specific media type indexed by iPosition - -HRESULT -CTransformOutputPin::GetMediaType( - int iPosition, - __inout CMediaType *pMediaType) -{ - ASSERT(m_pTransformFilter->m_pInput != NULL); - - // We don't have any media types if our input is not connected - - if (m_pTransformFilter->m_pInput->IsConnected()) { - return m_pTransformFilter->GetMediaType(iPosition,pMediaType); - } else { - return VFW_S_NO_MORE_ITEMS; - } -} - - -// Override this if you can do something constructive to act on the -// quality message. Consider passing it upstream as well - -// Pass the quality mesage on upstream. - -STDMETHODIMP -CTransformOutputPin::Notify(IBaseFilter * pSender, Quality q) -{ - UNREFERENCED_PARAMETER(pSender); - ValidateReadPtr(pSender,sizeof(IBaseFilter)); - - // First see if we want to handle this ourselves - HRESULT hr = m_pTransformFilter->AlterQuality(q); - if (hr!=S_FALSE) { - return hr; // either S_OK or a failure - } - - // S_FALSE means we pass the message on. - // Find the quality sink for our input pin and send it there - - ASSERT(m_pTransformFilter->m_pInput != NULL); - - return m_pTransformFilter->m_pInput->PassNotify(q); - -} // Notify - - -// the following removes a very large number of level 4 warnings from the microsoft -// compiler output, which are not useful at all in this case. -#pragma warning(disable:4514) diff --git a/third_party/BaseClasses/transfrm.h b/third_party/BaseClasses/transfrm.h deleted file mode 100644 index 9b276471..00000000 --- a/third_party/BaseClasses/transfrm.h +++ /dev/null @@ -1,304 +0,0 @@ -//------------------------------------------------------------------------------ -// File: Transfrm.h -// -// Desc: DirectShow base classes - defines classes from which simple -// transform codecs may be derived. -// -// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. -//------------------------------------------------------------------------------ - - -// It assumes the codec has one input and one output stream, and has no -// interest in memory management, interface negotiation or anything else. -// -// derive your class from this, and supply Transform and the media type/format -// negotiation functions. Implement that class, compile and link and -// you're done. - - -#ifndef __TRANSFRM__ -#define __TRANSFRM__ - -// ====================================================================== -// This is the com object that represents a simple transform filter. It -// supports IBaseFilter, IMediaFilter and two pins through nested interfaces -// ====================================================================== - -class CTransformFilter; - -// ================================================== -// Implements the input pin -// ================================================== - -class CTransformInputPin : public CBaseInputPin -{ - friend class CTransformFilter; - -protected: - CTransformFilter *m_pTransformFilter; - - -public: - - CTransformInputPin( - __in_opt LPCTSTR pObjectName, - __inout CTransformFilter *pTransformFilter, - __inout HRESULT * phr, - __in_opt LPCWSTR pName); -#ifdef UNICODE - CTransformInputPin( - __in_opt LPCSTR pObjectName, - __inout CTransformFilter *pTransformFilter, - __inout HRESULT * phr, - __in_opt LPCWSTR pName); -#endif - - STDMETHODIMP QueryId(__deref_out LPWSTR * Id) - { - return AMGetWideString(L"In", Id); - } - - // Grab and release extra interfaces if required - - HRESULT CheckConnect(IPin *pPin); - HRESULT BreakConnect(); - HRESULT CompleteConnect(IPin *pReceivePin); - - // check that we can support this output type - HRESULT CheckMediaType(const CMediaType* mtIn); - - // set the connection media type - HRESULT SetMediaType(const CMediaType* mt); - - // --- IMemInputPin ----- - - // here's the next block of data from the stream. - // AddRef it yourself if you need to hold it beyond the end - // of this call. - STDMETHODIMP Receive(IMediaSample * pSample); - - // provide EndOfStream that passes straight downstream - // (there is no queued data) - STDMETHODIMP EndOfStream(void); - - // passes it to CTransformFilter::BeginFlush - STDMETHODIMP BeginFlush(void); - - // passes it to CTransformFilter::EndFlush - STDMETHODIMP EndFlush(void); - - STDMETHODIMP NewSegment( - REFERENCE_TIME tStart, - REFERENCE_TIME tStop, - double dRate); - - // Check if it's OK to process samples - virtual HRESULT CheckStreaming(); - - // Media type -public: - CMediaType& CurrentMediaType() { return m_mt; }; - -}; - -// ================================================== -// Implements the output pin -// ================================================== - -class CTransformOutputPin : public CBaseOutputPin -{ - friend class CTransformFilter; - -protected: - CTransformFilter *m_pTransformFilter; - -public: - - // implement IMediaPosition by passing upstream - IUnknown * m_pPosition; - - CTransformOutputPin( - __in_opt LPCTSTR pObjectName, - __inout CTransformFilter *pTransformFilter, - __inout HRESULT * phr, - __in_opt LPCWSTR pName); -#ifdef UNICODE - CTransformOutputPin( - __in_opt LPCSTR pObjectName, - __inout CTransformFilter *pTransformFilter, - __inout HRESULT * phr, - __in_opt LPCWSTR pName); -#endif - ~CTransformOutputPin(); - - // override to expose IMediaPosition - STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv); - - // --- CBaseOutputPin ------------ - - STDMETHODIMP QueryId(__deref_out LPWSTR * Id) - { - return AMGetWideString(L"Out", Id); - } - - // Grab and release extra interfaces if required - - HRESULT CheckConnect(IPin *pPin); - HRESULT BreakConnect(); - HRESULT CompleteConnect(IPin *pReceivePin); - - // check that we can support this output type - HRESULT CheckMediaType(const CMediaType* mtOut); - - // set the connection media type - HRESULT SetMediaType(const CMediaType *pmt); - - // called from CBaseOutputPin during connection to ask for - // the count and size of buffers we need. - HRESULT DecideBufferSize( - IMemAllocator * pAlloc, - __inout ALLOCATOR_PROPERTIES *pProp); - - // returns the preferred formats for a pin - HRESULT GetMediaType(int iPosition, __inout CMediaType *pMediaType); - - // inherited from IQualityControl via CBasePin - STDMETHODIMP Notify(IBaseFilter * pSender, Quality q); - - // Media type -public: - CMediaType& CurrentMediaType() { return m_mt; }; -}; - - -class AM_NOVTABLE CTransformFilter : public CBaseFilter -{ - -public: - - // map getpin/getpincount for base enum of pins to owner - // override this to return more specialised pin objects - - virtual int GetPinCount(); - virtual CBasePin * GetPin(int n); - STDMETHODIMP FindPin(LPCWSTR Id, __deref_out IPin **ppPin); - - // override state changes to allow derived transform filter - // to control streaming start/stop - STDMETHODIMP Stop(); - STDMETHODIMP Pause(); - -public: - - CTransformFilter(__in_opt LPCTSTR , __inout_opt LPUNKNOWN, REFCLSID clsid); -#ifdef UNICODE - CTransformFilter(__in_opt LPCSTR , __inout_opt LPUNKNOWN, REFCLSID clsid); -#endif - ~CTransformFilter(); - - // ================================================================= - // ----- override these bits --------------------------------------- - // ================================================================= - - // These must be supplied in a derived class - - virtual HRESULT Transform(IMediaSample * pIn, IMediaSample *pOut); - - // check if you can support mtIn - virtual HRESULT CheckInputType(const CMediaType* mtIn) PURE; - - // check if you can support the transform from this input to this output - virtual HRESULT CheckTransform(const CMediaType* mtIn, const CMediaType* mtOut) PURE; - - // this goes in the factory template table to create new instances - // static CCOMObject * CreateInstance(__inout_opt LPUNKNOWN, HRESULT *); - - // call the SetProperties function with appropriate arguments - virtual HRESULT DecideBufferSize( - IMemAllocator * pAllocator, - __inout ALLOCATOR_PROPERTIES *pprop) PURE; - - // override to suggest OUTPUT pin media types - virtual HRESULT GetMediaType(int iPosition, __inout CMediaType *pMediaType) PURE; - - - - // ================================================================= - // ----- Optional Override Methods ----------------------- - // ================================================================= - - // you can also override these if you want to know about streaming - virtual HRESULT StartStreaming(); - virtual HRESULT StopStreaming(); - - // override if you can do anything constructive with quality notifications - virtual HRESULT AlterQuality(Quality q); - - // override this to know when the media type is actually set - virtual HRESULT SetMediaType(PIN_DIRECTION direction,const CMediaType *pmt); - - // chance to grab extra interfaces on connection - virtual HRESULT CheckConnect(PIN_DIRECTION dir,IPin *pPin); - virtual HRESULT BreakConnect(PIN_DIRECTION dir); - virtual HRESULT CompleteConnect(PIN_DIRECTION direction,IPin *pReceivePin); - - // chance to customize the transform process - virtual HRESULT Receive(IMediaSample *pSample); - - // Standard setup for output sample - HRESULT InitializeOutputSample(IMediaSample *pSample, __deref_out IMediaSample **ppOutSample); - - // if you override Receive, you may need to override these three too - virtual HRESULT EndOfStream(void); - virtual HRESULT BeginFlush(void); - virtual HRESULT EndFlush(void); - virtual HRESULT NewSegment( - REFERENCE_TIME tStart, - REFERENCE_TIME tStop, - double dRate); - -#ifdef PERF - // Override to register performance measurement with a less generic string - // You should do this to avoid confusion with other filters - virtual void RegisterPerfId() - {m_idTransform = MSR_REGISTER(TEXT("Transform"));} -#endif // PERF - - -// implementation details - -protected: - -#ifdef PERF - int m_idTransform; // performance measuring id -#endif - BOOL m_bEOSDelivered; // have we sent EndOfStream - BOOL m_bSampleSkipped; // Did we just skip a frame - BOOL m_bQualityChanged; // Have we degraded? - - // critical section protecting filter state. - - CCritSec m_csFilter; - - // critical section stopping state changes (ie Stop) while we're - // processing a sample. - // - // This critical section is held when processing - // events that occur on the receive thread - Receive() and EndOfStream(). - // - // If you want to hold both m_csReceive and m_csFilter then grab - // m_csFilter FIRST - like CTransformFilter::Stop() does. - - CCritSec m_csReceive; - - // these hold our input and output pins - - friend class CTransformInputPin; - friend class CTransformOutputPin; - CTransformInputPin *m_pInput; - CTransformOutputPin *m_pOutput; -}; - -#endif /* __TRANSFRM__ */ - - diff --git a/third_party/BaseClasses/transip.cpp b/third_party/BaseClasses/transip.cpp deleted file mode 100644 index e8e12eb5..00000000 --- a/third_party/BaseClasses/transip.cpp +++ /dev/null @@ -1,974 +0,0 @@ -//------------------------------------------------------------------------------ -// File: TransIP.cpp -// -// Desc: DirectShow base classes - implements class for simple Transform- -// In-Place filters such as audio. -// -// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. -//------------------------------------------------------------------------------ - - -// How allocators are decided. -// -// An in-place transform tries to do its work in someone else's buffers. -// It tries to persuade the filters on either side to use the same allocator -// (and for that matter the same media type). In desperation, if the downstream -// filter refuses to supply an allocator and the upstream filter offers only -// a read-only one then it will provide an allocator. -// if the upstream filter insists on a read-only allocator then the transform -// filter will (reluctantly) copy the data before transforming it. -// -// In order to pass an allocator through it needs to remember the one it got -// from the first connection to pass it on to the second one. -// -// It is good if we can avoid insisting on a particular order of connection -// (There is a precedent for insisting on the input -// being connected first. Insisting on the output being connected first is -// not allowed. That would break RenderFile.) -// -// The base pin classes (CBaseOutputPin and CBaseInputPin) both have a -// m_pAllocator member which is used in places like -// CBaseOutputPin::GetDeliveryBuffer and CBaseInputPin::Inactive. -// To avoid lots of extra overriding, we should keep these happy -// by using these pointers. -// -// When each pin is connected, it will set the corresponding m_pAllocator -// and will have a single ref-count on that allocator. -// -// Refcounts are acquired by GetAllocator calls which return AddReffed -// allocators and are released in one of: -// CBaseInputPin::Disconnect -// CBaseOutputPin::BreakConect -// In each case m_pAllocator is set to NULL after the release, so this -// is the last chance to ever release it. If there should ever be -// multiple refcounts associated with the same pointer, this had better -// be cleared up before that happens. To avoid such problems, we'll -// stick with one per pointer. - - - -// RECONNECTING and STATE CHANGES -// -// Each pin could be disconnected, connected with a read-only allocator, -// connected with an upstream read/write allocator, connected with an -// allocator from downstream or connected with its own allocator. -// Five states for each pin gives a data space of 25 states. -// -// Notation: -// -// R/W == read/write -// R-O == read-only -// -// -// -// 00 means an unconnected pin. -// <- means using a R/W allocator from the upstream filter -// <= means using a R-O allocator from an upstream filter -// || means using our own (R/W) allocator. -// -> means using a R/W allocator from a downstream filter -// (a R-O allocator from downstream is nonsense, it can't ever work). -// -// -// That makes 25 possible states. Some states are nonsense (two different -// allocators from the same place). These are just an artifact of the notation. -// <= <- Nonsense. -// <- <= Nonsense -// Some states are illegal (the output pin never accepts a R-O allocator): -// 00 <= !! Error !! -// <= <= !! Error !! -// || <= !! Error !! -// -> <= !! Error !! -// Three states appears to be inaccessible: -// -> || Inaccessible -// || -> Inaccessible -// || <- Inaccessible -// Some states only ever occur as intermediates with a pending reconnect which -// is guaranteed to finish in another state. -// -> 00 ?? unstable goes to || 00 -// 00 <- ?? unstable goes to 00 || -// -> <- ?? unstable goes to -> -> -// <- || ?? unstable goes to <- <- -// <- -> ?? unstable goes to <- <- -// And that leaves 11 possible resting states: -// 1 00 00 Nothing connected. -// 2 <- 00 Input pin connected. -// 3 <= 00 Input pin connected using R-O allocator. -// 4 || 00 Needs several state changes to get here. -// 5 00 || Output pin connected using our allocator -// 6 00 -> Downstream only connected -// 7 || || Undesirable but can be forced upon us. -// 8 <= || Copy forced. <= -> is preferable -// 9 <= -> OK - forced to copy. -// 10 <- <- Transform in place (ideal) -// 11 -> -> Transform in place (ideal) -// -// The object of the exercise is to ensure that we finish up in states -// 10 or 11 whenever possible. State 10 is only possible if the upstream -// filter has a R/W allocator (the AVI splitter notoriously -// doesn't) and state 11 is only possible if the downstream filter does -// offer an allocator. -// -// The transition table (entries marked * go via a reconnect) -// -// There are 8 possible transitions: -// A: Connect upstream to filter with R-O allocator that insists on using it. -// B: Connect upstream to filter with R-O allocator but chooses not to use it. -// C: Connect upstream to filter with R/W allocator and insists on using it. -// D: Connect upstream to filter with R/W allocator but chooses not to use it. -// E: Connect downstream to a filter that offers an allocator -// F: Connect downstream to a filter that does not offer an allocator -// G: disconnect upstream -// H: Disconnect downstream -// -// A B C D E F G H -// --------------------------------------------------------- -// 00 00 1 | 3 3 2 2 6 5 . . |1 00 00 -// <- 00 2 | . . . . *10/11 10 1 . |2 <- 00 -// <= 00 3 | . . . . *9/11 *7/8 1 . |3 <= 00 -// || 00 4 | . . . . *8 *7 1 . |4 || 00 -// 00 || 5 | 8 7 *10 7 . . . 1 |5 00 || -// 00 -> 6 | 9 11 *10 11 . . . 1 |6 00 -> -// || || 7 | . . . . . . 5 4 |7 || || -// <= || 8 | . . . . . . 5 3 |8 <= || -// <= -> 9 | . . . . . . 6 3 |9 <= -> -// <- <- 10| . . . . . . *5/6 2 |10 <- <- -// -> -> 11| . . . . . . 6 *2/3 |11 -> -> -// --------------------------------------------------------- -// A B C D E F G H -// -// All these states are accessible without requiring any filter to -// change its behaviour but not all transitions are accessible, for -// instance a transition from state 4 to anywhere other than -// state 8 requires that the upstream filter first offer a R-O allocator -// and then changes its mind and offer R/W. This is NOT allowable - it -// leads to things like the output pin getting a R/W allocator from -// upstream and then the input pin being told it can only have a R-O one. -// Note that you CAN change (say) the upstream filter for a different one, but -// only as a disconnect / connect, not as a Reconnect. (Exercise for -// the reader is to see how you get into state 4). -// -// The reconnection stuff goes as follows (some of the cases shown here as -// "no reconnect" may get one to finalise media type - an old story). -// If there is a reconnect where it says "no reconnect" here then the -// reconnection must not change the allocator choice. -// -// state 2: <- 00 transition E <- <- case C <- <- (no change) -// case D -> <- and then to -> -> -// -// state 2: <- 00 transition F <- <- (no reconnect) -// -// state 3: <= 00 transition E <= -> case A <= -> (no change) -// case B -> -> -// transition F <= || case A <= || (no change) -// case B || || -// -// state 4: || 00 transition E || || case B -> || and then all cases to -> -> -// F || || case B || || (no change) -// -// state 5: 00 || transition A <= || (no reconnect) -// B || || (no reconnect) -// C <- || all cases <- <- -// D || || (unfortunate, but upstream's choice) -// -// state 6: 00 -> transition A <= -> (no reconnect) -// B -> -> (no reconnect) -// C <- -> all cases <- <- -// D -> -> (no reconnect) -// -// state 10:<- <- transition G 00 <- case E 00 -> -// case F 00 || -// -// state 11:-> -> transition H -> 00 case A <= 00 (schizo) -// case B <= 00 -// case C <- 00 (schizo) -// case D <- 00 -// -// The Rules: -// To sort out media types: -// The input is reconnected -// if the input pin is connected and the output pin connects -// The output is reconnected -// If the output pin is connected -// and the input pin connects to a different media type -// -// To sort out allocators: -// The input is reconnected -// if the output disconnects and the input was using a downstream allocator -// The output pin calls SetAllocator to pass on a new allocator -// if the output is connected and -// if the input disconnects and the output was using an upstream allocator -// if the input acquires an allocator different from the output one -// and that new allocator is not R-O -// -// Data is copied (i.e. call getbuffer and copy the data before transforming it) -// if the two allocators are different. - - - -// CHAINS of filters: -// -// We sit between two filters (call them A and Z). We should finish up -// with the same allocator on both of our pins and that should be the -// same one that A and Z would have agreed on if we hadn't been in the -// way. Furthermore, it should not matter how many in-place transforms -// are in the way. Let B, C, D... be in-place transforms ("us"). -// Here's how it goes: -// -// 1. -// A connects to B. They agree on A's allocator. -// A-a->B -// -// 2. -// B connects to C. Same story. There is no point in a reconnect, but -// B will request an input reconnect anyway. -// A-a->B-a->C -// -// 3. -// C connects to Z. -// C insists on using A's allocator, but compromises by requesting a reconnect. -// of C's input. -// A-a->B-?->C-a->Z -// -// We now have pending reconnects on both A--->B and B--->C -// -// 4. -// The A--->B link is reconnected. -// A asks B for an allocator. B sees that it has a downstream connection so -// asks its downstream input pin i.e. C's input pin for an allocator. C sees -// that it too has a downstream connection so asks Z for an allocator. -// -// Even though Z's input pin is connected, it is being asked for an allocator. -// It could refuse, in which case the chain is done and will use A's allocator -// Alternatively, Z may supply one. A chooses either Z's or A's own one. -// B's input pin gets NotifyAllocator called to tell it the decision and it -// propagates this downstream by calling ReceiveAllocator on its output pin -// which calls NotifyAllocator on the next input pin downstream etc. -// If the choice is Z then it goes: -// A-z->B-a->C-a->Z -// A-z->B-z->C-a->Z -// A-z->B-z->C-z->Z -// -// And that's IT!! Any further (essentially spurious) reconnects peter out -// with no change in the chain. - -#include -#include -#include - - -// ================================================================= -// Implements the CTransInPlaceFilter class -// ================================================================= - -CTransInPlaceFilter::CTransInPlaceFilter - ( __in_opt LPCTSTR pName, - __inout_opt LPUNKNOWN pUnk, - REFCLSID clsid, - __inout HRESULT *phr, - bool bModifiesData - ) - : CTransformFilter(pName, pUnk, clsid), - m_bModifiesData(bModifiesData) -{ -#ifdef PERF - RegisterPerfId(); -#endif // PERF - -} // constructor - -#ifdef UNICODE -CTransInPlaceFilter::CTransInPlaceFilter - ( __in_opt LPCSTR pName, - __inout_opt LPUNKNOWN pUnk, - REFCLSID clsid, - __inout HRESULT *phr, - bool bModifiesData - ) - : CTransformFilter(pName, pUnk, clsid), - m_bModifiesData(bModifiesData) -{ -#ifdef PERF - RegisterPerfId(); -#endif // PERF - -} // constructor -#endif - -// return a non-addrefed CBasePin * for the user to addref if he holds onto it -// for longer than his pointer to us. We create the pins dynamically when they -// are asked for rather than in the constructor. This is because we want to -// give the derived class an oppportunity to return different pin objects - -// As soon as any pin is needed we create both (this is different from the -// usual transform filter) because enumerators, allocators etc are passed -// through from one pin to another and it becomes very painful if the other -// pin isn't there. If we fail to create either pin we ensure we fail both. - -CBasePin * -CTransInPlaceFilter::GetPin(int n) -{ - HRESULT hr = S_OK; - - // Create an input pin if not already done - - if (m_pInput == NULL) { - - m_pInput = new CTransInPlaceInputPin( NAME("TransInPlace input pin") - , this // Owner filter - , &hr // Result code - , L"Input" // Pin name - ); - - // Constructor for CTransInPlaceInputPin can't fail - ASSERT(SUCCEEDED(hr)); - } - - // Create an output pin if not already done - - if (m_pInput!=NULL && m_pOutput == NULL) { - - m_pOutput = new CTransInPlaceOutputPin( NAME("TransInPlace output pin") - , this // Owner filter - , &hr // Result code - , L"Output" // Pin name - ); - - // a failed return code should delete the object - - ASSERT(SUCCEEDED(hr)); - if (m_pOutput == NULL) { - delete m_pInput; - m_pInput = NULL; - } - } - - // Return the appropriate pin - - ASSERT (n>=0 && n<=1); - if (n == 0) { - return m_pInput; - } else if (n==1) { - return m_pOutput; - } else { - return NULL; - } - -} // GetPin - - - -// dir is the direction of our pin. -// pReceivePin is the pin we are connecting to. -HRESULT CTransInPlaceFilter::CompleteConnect(PIN_DIRECTION dir, IPin *pReceivePin) -{ - UNREFERENCED_PARAMETER(pReceivePin); - ASSERT(m_pInput); - ASSERT(m_pOutput); - - // if we are not part of a graph, then don't indirect the pointer - // this probably prevents use of the filter without a filtergraph - if (!m_pGraph) { - return VFW_E_NOT_IN_GRAPH; - } - - // Always reconnect the input to account for buffering changes - // - // Because we don't get to suggest a type on ReceiveConnection - // we need another way of making sure the right type gets used. - // - // One way would be to have our EnumMediaTypes return our output - // connection type first but more deterministic and simple is to - // call ReconnectEx passing the type we want to reconnect with - // via the base class ReconeectPin method. - - if (dir == PINDIR_OUTPUT) { - if( m_pInput->IsConnected() ) { - return ReconnectPin( m_pInput, &m_pOutput->CurrentMediaType() ); - } - return NOERROR; - } - - ASSERT(dir == PINDIR_INPUT); - - // Reconnect output if necessary - - if( m_pOutput->IsConnected() ) { - - if ( m_pInput->CurrentMediaType() - != m_pOutput->CurrentMediaType() - ) { - return ReconnectPin( m_pOutput, &m_pInput->CurrentMediaType() ); - } - } - return NOERROR; - -} // ComnpleteConnect - - -// -// DecideBufferSize -// -// Tell the output pin's allocator what size buffers we require. -// *pAlloc will be the allocator our output pin is using. -// - -HRESULT CTransInPlaceFilter::DecideBufferSize - ( IMemAllocator *pAlloc - , __inout ALLOCATOR_PROPERTIES *pProperties - ) -{ - ALLOCATOR_PROPERTIES Request, Actual; - HRESULT hr; - - // If we are connected upstream, get his views - if (m_pInput->IsConnected()) { - // Get the input pin allocator, and get its size and count. - // we don't care about his alignment and prefix. - - hr = InputPin()->PeekAllocator()->GetProperties(&Request); - if (FAILED(hr)) { - // Input connected but with a secretive allocator - enough! - return hr; - } - } else { - // Propose one byte - // If this isn't enough then when the other pin does get connected - // we can revise it. - ZeroMemory(&Request, sizeof(Request)); - Request.cBuffers = 1; - Request.cbBuffer = 1; - } - - - DbgLog((LOG_MEMORY,1,TEXT("Setting Allocator Requirements"))); - DbgLog((LOG_MEMORY,1,TEXT("Count %d, Size %d"), - Request.cBuffers, Request.cbBuffer)); - - // Pass the allocator requirements to our output side - // but do a little sanity checking first or we'll just hit - // asserts in the allocator. - - pProperties->cBuffers = Request.cBuffers; - pProperties->cbBuffer = Request.cbBuffer; - pProperties->cbAlign = Request.cbAlign; - if (pProperties->cBuffers<=0) {pProperties->cBuffers = 1; } - if (pProperties->cbBuffer<=0) {pProperties->cbBuffer = 1; } - hr = pAlloc->SetProperties(pProperties, &Actual); - - if (FAILED(hr)) { - return hr; - } - - DbgLog((LOG_MEMORY,1,TEXT("Obtained Allocator Requirements"))); - DbgLog((LOG_MEMORY,1,TEXT("Count %d, Size %d, Alignment %d"), - Actual.cBuffers, Actual.cbBuffer, Actual.cbAlign)); - - // Make sure we got the right alignment and at least the minimum required - - if ( (Request.cBuffers > Actual.cBuffers) - || (Request.cbBuffer > Actual.cbBuffer) - || (Request.cbAlign > Actual.cbAlign) - ) { - return E_FAIL; - } - return NOERROR; - -} // DecideBufferSize - -// -// Copy -// -// return a pointer to an identical copy of pSample -__out_opt IMediaSample * CTransInPlaceFilter::Copy(IMediaSample *pSource) -{ - IMediaSample * pDest; - - HRESULT hr; - REFERENCE_TIME tStart, tStop; - const BOOL bTime = S_OK == pSource->GetTime( &tStart, &tStop); - - // this may block for an indeterminate amount of time - hr = OutputPin()->PeekAllocator()->GetBuffer( - &pDest - , bTime ? &tStart : NULL - , bTime ? &tStop : NULL - , m_bSampleSkipped ? AM_GBF_PREVFRAMESKIPPED : 0 - ); - - if (FAILED(hr)) { - return NULL; - } - - ASSERT(pDest); - IMediaSample2 *pSample2; - if (SUCCEEDED(pDest->QueryInterface(IID_IMediaSample2, (void **)&pSample2))) { - HRESULT hrProps = pSample2->SetProperties( - FIELD_OFFSET(AM_SAMPLE2_PROPERTIES, pbBuffer), - (PBYTE)m_pInput->SampleProps()); - pSample2->Release(); - if (FAILED(hrProps)) { - pDest->Release(); - return NULL; - } - } else { - if (bTime) { - pDest->SetTime(&tStart, &tStop); - } - - if (S_OK == pSource->IsSyncPoint()) { - pDest->SetSyncPoint(TRUE); - } - if (S_OK == pSource->IsDiscontinuity() || m_bSampleSkipped) { - pDest->SetDiscontinuity(TRUE); - } - if (S_OK == pSource->IsPreroll()) { - pDest->SetPreroll(TRUE); - } - - // Copy the media type - AM_MEDIA_TYPE *pMediaType; - if (S_OK == pSource->GetMediaType(&pMediaType)) { - pDest->SetMediaType(pMediaType); - DeleteMediaType( pMediaType ); - } - - } - - m_bSampleSkipped = FALSE; - - // Copy the sample media times - REFERENCE_TIME TimeStart, TimeEnd; - if (pSource->GetMediaTime(&TimeStart,&TimeEnd) == NOERROR) { - pDest->SetMediaTime(&TimeStart,&TimeEnd); - } - - // Copy the actual data length and the actual data. - { - const long lDataLength = pSource->GetActualDataLength(); - if (FAILED(pDest->SetActualDataLength(lDataLength))) { - pDest->Release(); - return NULL; - } - - // Copy the sample data - { - BYTE *pSourceBuffer, *pDestBuffer; - long lSourceSize = pSource->GetSize(); - long lDestSize = pDest->GetSize(); - - ASSERT(lDestSize >= lSourceSize && lDestSize >= lDataLength); - - if (FAILED(pSource->GetPointer(&pSourceBuffer)) || - FAILED(pDest->GetPointer(&pDestBuffer)) || - lDestSize < lDataLength || - lDataLength < 0) { - pDest->Release(); - return NULL; - } - ASSERT(lDestSize == 0 || pSourceBuffer != NULL && pDestBuffer != NULL); - - CopyMemory( (PVOID) pDestBuffer, (PVOID) pSourceBuffer, lDataLength ); - } - } - - return pDest; - -} // Copy - - -// override this to customize the transform process - -HRESULT -CTransInPlaceFilter::Receive(IMediaSample *pSample) -{ - /* Check for other streams and pass them on */ - AM_SAMPLE2_PROPERTIES * const pProps = m_pInput->SampleProps(); - if (pProps->dwStreamId != AM_STREAM_MEDIA) { - return m_pOutput->Deliver(pSample); - } - HRESULT hr; - - // Start timing the TransInPlace (if PERF is defined) - MSR_START(m_idTransInPlace); - - if (UsingDifferentAllocators()) { - - // We have to copy the data. - - pSample = Copy(pSample); - - if (pSample==NULL) { - MSR_STOP(m_idTransInPlace); - return E_UNEXPECTED; - } - } - - // have the derived class transform the data - hr = Transform(pSample); - - // Stop the clock and log it (if PERF is defined) - MSR_STOP(m_idTransInPlace); - - if (FAILED(hr)) { - DbgLog((LOG_TRACE, 1, TEXT("Error from TransInPlace"))); - if (UsingDifferentAllocators()) { - pSample->Release(); - } - return hr; - } - - // the Transform() function can return S_FALSE to indicate that the - // sample should not be delivered; we only deliver the sample if it's - // really S_OK (same as NOERROR, of course.) - if (hr == NOERROR) { - hr = m_pOutput->Deliver(pSample); - } else { - // But it would be an error to return this private workaround - // to the caller ... - if (S_FALSE == hr) { - // S_FALSE returned from Transform is a PRIVATE agreement - // We should return NOERROR from Receive() in this cause because - // returning S_FALSE from Receive() means that this is the end - // of the stream and no more data should be sent. - m_bSampleSkipped = TRUE; - if (!m_bQualityChanged) { - NotifyEvent(EC_QUALITY_CHANGE,0,0); - m_bQualityChanged = TRUE; - } - hr = NOERROR; - } - } - - // release the output buffer. If the connected pin still needs it, - // it will have addrefed it itself. - if (UsingDifferentAllocators()) { - pSample->Release(); - } - - return hr; - -} // Receive - - - -// ================================================================= -// Implements the CTransInPlaceInputPin class -// ================================================================= - - -// constructor - -CTransInPlaceInputPin::CTransInPlaceInputPin - ( __in_opt LPCTSTR pObjectName - , __inout CTransInPlaceFilter *pFilter - , __inout HRESULT *phr - , __in_opt LPCWSTR pName - ) - : CTransformInputPin(pObjectName, - pFilter, - phr, - pName) - , m_bReadOnly(FALSE) - , m_pTIPFilter(pFilter) -{ - DbgLog((LOG_TRACE, 2 - , TEXT("CTransInPlaceInputPin::CTransInPlaceInputPin"))); - -} // constructor - - -// ================================================================= -// Implements IMemInputPin interface -// ================================================================= - - -// If the downstream filter has one then offer that (even if our own output -// pin is not using it yet. If the upstream filter chooses it then we will -// tell our output pin to ReceiveAllocator). -// Else if our output pin is using an allocator then offer that. -// ( This could mean offering the upstream filter his own allocator, -// it could mean offerring our own -// ) or it could mean offering the one from downstream -// Else fail to offer any allocator at all. - -STDMETHODIMP CTransInPlaceInputPin::GetAllocator(__deref_out IMemAllocator ** ppAllocator) -{ - CheckPointer(ppAllocator,E_POINTER); - ValidateReadWritePtr(ppAllocator,sizeof(IMemAllocator *)); - CAutoLock cObjectLock(m_pLock); - - HRESULT hr; - - if ( m_pTIPFilter->m_pOutput->IsConnected() ) { - // Store the allocator we got - hr = m_pTIPFilter->OutputPin()->ConnectedIMemInputPin() - ->GetAllocator( ppAllocator ); - if (SUCCEEDED(hr)) { - m_pTIPFilter->OutputPin()->SetAllocator( *ppAllocator ); - } - } - else { - // Help upstream filter (eg TIP filter which is having to do a copy) - // by providing a temp allocator here - we'll never use - // this allocator because when our output is connected we'll - // reconnect this pin - hr = CTransformInputPin::GetAllocator( ppAllocator ); - } - return hr; - -} // GetAllocator - - - -/* Get told which allocator the upstream output pin is actually going to use */ - - -STDMETHODIMP -CTransInPlaceInputPin::NotifyAllocator( - IMemAllocator * pAllocator, - BOOL bReadOnly) -{ - HRESULT hr = S_OK; - CheckPointer(pAllocator,E_POINTER); - ValidateReadPtr(pAllocator,sizeof(IMemAllocator)); - - CAutoLock cObjectLock(m_pLock); - - m_bReadOnly = bReadOnly; - // If we modify data then don't accept the allocator if it's - // the same as the output pin's allocator - - // If our output is not connected just accept the allocator - // We're never going to use this allocator because when our - // output pin is connected we'll reconnect this pin - if (!m_pTIPFilter->OutputPin()->IsConnected()) { - return CTransformInputPin::NotifyAllocator(pAllocator, bReadOnly); - } - - // If the allocator is read-only and we're modifying data - // and the allocator is the same as the output pin's - // then reject - if (bReadOnly && m_pTIPFilter->m_bModifiesData) { - IMemAllocator *pOutputAllocator = - m_pTIPFilter->OutputPin()->PeekAllocator(); - - // Make sure we have an output allocator - if (pOutputAllocator == NULL) { - hr = m_pTIPFilter->OutputPin()->ConnectedIMemInputPin()-> - GetAllocator(&pOutputAllocator); - if(FAILED(hr)) { - hr = CreateMemoryAllocator(&pOutputAllocator); - } - if (SUCCEEDED(hr)) { - m_pTIPFilter->OutputPin()->SetAllocator(pOutputAllocator); - pOutputAllocator->Release(); - } - } - if (pAllocator == pOutputAllocator) { - hr = E_FAIL; - } else if(SUCCEEDED(hr)) { - // Must copy so set the allocator properties on the output - ALLOCATOR_PROPERTIES Props, Actual; - hr = pAllocator->GetProperties(&Props); - if (SUCCEEDED(hr)) { - hr = pOutputAllocator->SetProperties(&Props, &Actual); - } - if (SUCCEEDED(hr)) { - if ( (Props.cBuffers > Actual.cBuffers) - || (Props.cbBuffer > Actual.cbBuffer) - || (Props.cbAlign > Actual.cbAlign) - ) { - hr = E_FAIL; - } - } - - // Set the allocator on the output pin - if (SUCCEEDED(hr)) { - hr = m_pTIPFilter->OutputPin()->ConnectedIMemInputPin() - ->NotifyAllocator( pOutputAllocator, FALSE ); - } - } - } else { - hr = m_pTIPFilter->OutputPin()->ConnectedIMemInputPin() - ->NotifyAllocator( pAllocator, bReadOnly ); - if (SUCCEEDED(hr)) { - m_pTIPFilter->OutputPin()->SetAllocator( pAllocator ); - } - } - - if (SUCCEEDED(hr)) { - - // It's possible that the old and the new are the same thing. - // AddRef before release ensures that we don't unload it. - pAllocator->AddRef(); - - if( m_pAllocator != NULL ) - m_pAllocator->Release(); - - m_pAllocator = pAllocator; // We have an allocator for the input pin - } - - return hr; - -} // NotifyAllocator - - -// EnumMediaTypes -// - pass through to our downstream filter -STDMETHODIMP CTransInPlaceInputPin::EnumMediaTypes( __deref_out IEnumMediaTypes **ppEnum ) -{ - // Can only pass through if connected - if( !m_pTIPFilter->m_pOutput->IsConnected() ) - return VFW_E_NOT_CONNECTED; - - return m_pTIPFilter->m_pOutput->GetConnected()->EnumMediaTypes( ppEnum ); - -} // EnumMediaTypes - - -// CheckMediaType -// - agree to anything if not connected, -// otherwise pass through to the downstream filter. -// This assumes that the filter does not change the media type. - -HRESULT CTransInPlaceInputPin::CheckMediaType(const CMediaType *pmt ) -{ - HRESULT hr = m_pTIPFilter->CheckInputType(pmt); - if (hr!=S_OK) return hr; - - if( m_pTIPFilter->m_pOutput->IsConnected() ) - return m_pTIPFilter->m_pOutput->GetConnected()->QueryAccept( pmt ); - else - return S_OK; - -} // CheckMediaType - - -// If upstream asks us what our requirements are, we will try to ask downstream -// if that doesn't work, we'll just take the defaults. -STDMETHODIMP -CTransInPlaceInputPin::GetAllocatorRequirements(__out ALLOCATOR_PROPERTIES *pProps) -{ - - if( m_pTIPFilter->m_pOutput->IsConnected() ) - return m_pTIPFilter->OutputPin() - ->ConnectedIMemInputPin()->GetAllocatorRequirements( pProps ); - else - return E_NOTIMPL; - -} // GetAllocatorRequirements - - -// CTransInPlaceInputPin::CompleteConnect() calls CBaseInputPin::CompleteConnect() -// and then calls CTransInPlaceFilter::CompleteConnect(). It does this because -// CTransInPlaceFilter::CompleteConnect() can reconnect a pin and we do not -// want to reconnect a pin if CBaseInputPin::CompleteConnect() fails. -HRESULT -CTransInPlaceInputPin::CompleteConnect(IPin *pReceivePin) -{ - HRESULT hr = CBaseInputPin::CompleteConnect(pReceivePin); - if (FAILED(hr)) { - return hr; - } - - return m_pTransformFilter->CompleteConnect(PINDIR_INPUT,pReceivePin); -} // CompleteConnect - - -// ================================================================= -// Implements the CTransInPlaceOutputPin class -// ================================================================= - - -// constructor - -CTransInPlaceOutputPin::CTransInPlaceOutputPin( - __in_opt LPCTSTR pObjectName, - __inout CTransInPlaceFilter *pFilter, - __inout HRESULT * phr, - __in_opt LPCWSTR pPinName) - : CTransformOutputPin( pObjectName - , pFilter - , phr - , pPinName), - m_pTIPFilter(pFilter) -{ - DbgLog(( LOG_TRACE, 2 - , TEXT("CTransInPlaceOutputPin::CTransInPlaceOutputPin"))); - -} // constructor - - -// EnumMediaTypes -// - pass through to our upstream filter -STDMETHODIMP CTransInPlaceOutputPin::EnumMediaTypes( __deref_out IEnumMediaTypes **ppEnum ) -{ - // Can only pass through if connected. - if( ! m_pTIPFilter->m_pInput->IsConnected() ) - return VFW_E_NOT_CONNECTED; - - return m_pTIPFilter->m_pInput->GetConnected()->EnumMediaTypes( ppEnum ); - -} // EnumMediaTypes - - - -// CheckMediaType -// - agree to anything if not connected, -// otherwise pass through to the upstream filter. - -HRESULT CTransInPlaceOutputPin::CheckMediaType(const CMediaType *pmt ) -{ - // Don't accept any output pin type changes if we're copying - // between allocators - it's too late to change the input - // allocator size. - if (m_pTIPFilter->UsingDifferentAllocators() && !m_pFilter->IsStopped()) { - if (*pmt == m_mt) { - return S_OK; - } else { - return VFW_E_TYPE_NOT_ACCEPTED; - } - } - - // Assumes the type does not change. That's why we're calling - // CheckINPUTType here on the OUTPUT pin. - HRESULT hr = m_pTIPFilter->CheckInputType(pmt); - if (hr!=S_OK) return hr; - - if( m_pTIPFilter->m_pInput->IsConnected() ) - return m_pTIPFilter->m_pInput->GetConnected()->QueryAccept( pmt ); - else - return S_OK; - -} // CheckMediaType - - -/* Save the allocator pointer in the output pin -*/ -void -CTransInPlaceOutputPin::SetAllocator(IMemAllocator * pAllocator) -{ - pAllocator->AddRef(); - if (m_pAllocator) { - m_pAllocator->Release(); - } - m_pAllocator = pAllocator; -} // SetAllocator - - -// CTransInPlaceOutputPin::CompleteConnect() calls CBaseOutputPin::CompleteConnect() -// and then calls CTransInPlaceFilter::CompleteConnect(). It does this because -// CTransInPlaceFilter::CompleteConnect() can reconnect a pin and we do not want to -// reconnect a pin if CBaseOutputPin::CompleteConnect() fails. -// CBaseOutputPin::CompleteConnect() often fails when our output pin is being connected -// to the Video Mixing Renderer. -HRESULT -CTransInPlaceOutputPin::CompleteConnect(IPin *pReceivePin) -{ - HRESULT hr = CBaseOutputPin::CompleteConnect(pReceivePin); - if (FAILED(hr)) { - return hr; - } - - return m_pTransformFilter->CompleteConnect(PINDIR_OUTPUT,pReceivePin); -} // CompleteConnect diff --git a/third_party/BaseClasses/transip.h b/third_party/BaseClasses/transip.h deleted file mode 100644 index 3fc335ef..00000000 --- a/third_party/BaseClasses/transip.h +++ /dev/null @@ -1,250 +0,0 @@ -//------------------------------------------------------------------------------ -// File: TransIP.h -// -// Desc: DirectShow base classes - defines classes from which simple -// Transform-In-Place filters may be derived. -// -// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. -//------------------------------------------------------------------------------ - - -// -// The difference between this and Transfrm.h is that Transfrm copies the data. -// -// It assumes the filter has one input and one output stream, and has no -// interest in memory management, interface negotiation or anything else. -// -// Derive your class from this, and supply Transform and the media type/format -// negotiation functions. Implement that class, compile and link and -// you're done. - - -#ifndef __TRANSIP__ -#define __TRANSIP__ - -// ====================================================================== -// This is the com object that represents a simple transform filter. It -// supports IBaseFilter, IMediaFilter and two pins through nested interfaces -// ====================================================================== - -class CTransInPlaceFilter; - -// Several of the pin functions call filter functions to do the work, -// so you can often use the pin classes unaltered, just overriding the -// functions in CTransInPlaceFilter. If that's not enough and you want -// to derive your own pin class, override GetPin in the filter to supply -// your own pin classes to the filter. - -// ================================================== -// Implements the input pin -// ================================================== - -class CTransInPlaceInputPin : public CTransformInputPin -{ - -protected: - CTransInPlaceFilter * const m_pTIPFilter; // our filter - BOOL m_bReadOnly; // incoming stream is read only - -public: - - CTransInPlaceInputPin( - __in_opt LPCTSTR pObjectName, - __inout CTransInPlaceFilter *pFilter, - __inout HRESULT *phr, - __in_opt LPCWSTR pName); - - // --- IMemInputPin ----- - - // Provide an enumerator for media types by getting one from downstream - STDMETHODIMP EnumMediaTypes( __deref_out IEnumMediaTypes **ppEnum ); - - // Say whether media type is acceptable. - HRESULT CheckMediaType(const CMediaType* pmt); - - // Return our upstream allocator - STDMETHODIMP GetAllocator(__deref_out IMemAllocator ** ppAllocator); - - // get told which allocator the upstream output pin is actually - // going to use. - STDMETHODIMP NotifyAllocator(IMemAllocator * pAllocator, - BOOL bReadOnly); - - // Allow the filter to see what allocator we have - // N.B. This does NOT AddRef - __out IMemAllocator * PeekAllocator() const - { return m_pAllocator; } - - // Pass this on downstream if it ever gets called. - STDMETHODIMP GetAllocatorRequirements(__out ALLOCATOR_PROPERTIES *pProps); - - HRESULT CompleteConnect(IPin *pReceivePin); - - inline const BOOL ReadOnly() { return m_bReadOnly ; } - -}; // CTransInPlaceInputPin - -// ================================================== -// Implements the output pin -// ================================================== - -class CTransInPlaceOutputPin : public CTransformOutputPin -{ - -protected: - // m_pFilter points to our CBaseFilter - CTransInPlaceFilter * const m_pTIPFilter; - -public: - - CTransInPlaceOutputPin( - __in_opt LPCTSTR pObjectName, - __inout CTransInPlaceFilter *pFilter, - __inout HRESULT *phr, - __in_opt LPCWSTR pName); - - - // --- CBaseOutputPin ------------ - - // negotiate the allocator and its buffer size/count - // Insists on using our own allocator. (Actually the one upstream of us). - // We don't override this - instead we just agree the default - // then let the upstream filter decide for itself on reconnect - // virtual HRESULT DecideAllocator(IMemInputPin * pPin, IMemAllocator ** pAlloc); - - // Provide a media type enumerator. Get it from upstream. - STDMETHODIMP EnumMediaTypes( __deref_out IEnumMediaTypes **ppEnum ); - - // Say whether media type is acceptable. - HRESULT CheckMediaType(const CMediaType* pmt); - - // This just saves the allocator being used on the output pin - // Also called by input pin's GetAllocator() - void SetAllocator(IMemAllocator * pAllocator); - - __out_opt IMemInputPin * ConnectedIMemInputPin() - { return m_pInputPin; } - - // Allow the filter to see what allocator we have - // N.B. This does NOT AddRef - __out IMemAllocator * PeekAllocator() const - { return m_pAllocator; } - - HRESULT CompleteConnect(IPin *pReceivePin); - -}; // CTransInPlaceOutputPin - - -class AM_NOVTABLE CTransInPlaceFilter : public CTransformFilter -{ - -public: - - // map getpin/getpincount for base enum of pins to owner - // override this to return more specialised pin objects - - virtual CBasePin *GetPin(int n); - -public: - - // Set bModifiesData == false if your derived filter does - // not modify the data samples (for instance it's just copying - // them somewhere else or looking at the timestamps). - - CTransInPlaceFilter(__in_opt LPCTSTR, __inout_opt LPUNKNOWN, REFCLSID clsid, __inout HRESULT *, - bool bModifiesData = true); -#ifdef UNICODE - CTransInPlaceFilter(__in_opt LPCSTR, __inout_opt LPUNKNOWN, REFCLSID clsid, __inout HRESULT *, - bool bModifiesData = true); -#endif - // The following are defined to avoid undefined pure virtuals. - // Even if they are never called, they will give linkage warnings/errors - - // We override EnumMediaTypes to bypass the transform class enumerator - // which would otherwise call this. - HRESULT GetMediaType(int iPosition, __inout CMediaType *pMediaType) - { DbgBreak("CTransInPlaceFilter::GetMediaType should never be called"); - return E_UNEXPECTED; - } - - // This is called when we actually have to provide our own allocator. - HRESULT DecideBufferSize(IMemAllocator*, __inout ALLOCATOR_PROPERTIES *); - - // The functions which call this in CTransform are overridden in this - // class to call CheckInputType with the assumption that the type - // does not change. In Debug builds some calls will be made and - // we just ensure that they do not assert. - HRESULT CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut) - { - return S_OK; - }; - - - // ================================================================= - // ----- You may want to override this ----------------------------- - // ================================================================= - - HRESULT CompleteConnect(PIN_DIRECTION dir,IPin *pReceivePin); - - // chance to customize the transform process - virtual HRESULT Receive(IMediaSample *pSample); - - // ================================================================= - // ----- You MUST override these ----------------------------------- - // ================================================================= - - virtual HRESULT Transform(IMediaSample *pSample) PURE; - - // this goes in the factory template table to create new instances - // static CCOMObject * CreateInstance(LPUNKNOWN, HRESULT *); - - -#ifdef PERF - // Override to register performance measurement with a less generic string - // You should do this to avoid confusion with other filters - virtual void RegisterPerfId() - {m_idTransInPlace = MSR_REGISTER(TEXT("TransInPlace"));} -#endif // PERF - - -// implementation details - -protected: - - __out_opt IMediaSample * CTransInPlaceFilter::Copy(IMediaSample *pSource); - -#ifdef PERF - int m_idTransInPlace; // performance measuring id -#endif // PERF - bool m_bModifiesData; // Does this filter change the data? - - // these hold our input and output pins - - friend class CTransInPlaceInputPin; - friend class CTransInPlaceOutputPin; - - __out CTransInPlaceInputPin *InputPin() const - { - return (CTransInPlaceInputPin *)m_pInput; - }; - __out CTransInPlaceOutputPin *OutputPin() const - { - return (CTransInPlaceOutputPin *)m_pOutput; - }; - - // Helper to see if the input and output types match - BOOL TypesMatch() - { - return InputPin()->CurrentMediaType() == - OutputPin()->CurrentMediaType(); - } - - // Are the input and output allocators different? - BOOL UsingDifferentAllocators() const - { - return InputPin()->PeekAllocator() != OutputPin()->PeekAllocator(); - } -}; // CTransInPlaceFilter - -#endif /* __TRANSIP__ */ - diff --git a/third_party/BaseClasses/videoctl.cpp b/third_party/BaseClasses/videoctl.cpp deleted file mode 100644 index b12ccbd3..00000000 --- a/third_party/BaseClasses/videoctl.cpp +++ /dev/null @@ -1,746 +0,0 @@ -//------------------------------------------------------------------------------ -// File: VideoCtl.cpp -// -// Desc: DirectShow base classes. -// -// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. -//------------------------------------------------------------------------------ - - -#include -#include "ddmm.h" - -// Load a string from the resource file string table. The buffer must be at -// least STR_MAX_LENGTH bytes. The easiest way to use this is to declare a -// buffer in the property page class and use it for all string loading. It -// cannot be static as multiple property pages may be active simultaneously - -LPTSTR WINAPI StringFromResource(__out_ecount(STR_MAX_LENGTH) LPTSTR pBuffer, int iResourceID) -{ - if (LoadString(g_hInst,iResourceID,pBuffer,STR_MAX_LENGTH) == 0) { - return TEXT(""); - } - return pBuffer; -} - -#ifdef UNICODE -LPSTR WINAPI StringFromResource(__out_ecount(STR_MAX_LENGTH) LPSTR pBuffer, int iResourceID) -{ - if (LoadStringA(g_hInst,iResourceID,pBuffer,STR_MAX_LENGTH) == 0) { - return ""; - } - return pBuffer; -} -#endif - - - -// Property pages typically are called through their OLE interfaces. These -// use UNICODE strings regardless of how the binary is built. So when we -// load strings from the resource file we sometimes want to convert them -// to UNICODE. This method is passed the target UNICODE buffer and does a -// convert after loading the string (if built UNICODE this is not needed) -// On WinNT we can explicitly call LoadStringW which saves two conversions - -#ifndef UNICODE - -LPWSTR WINAPI WideStringFromResource(__out_ecount(STR_MAX_LENGTH) LPWSTR pBuffer, int iResourceID) -{ - *pBuffer = 0; - - if (g_amPlatform == VER_PLATFORM_WIN32_NT) { - LoadStringW(g_hInst,iResourceID,pBuffer,STR_MAX_LENGTH); - } else { - - CHAR szBuffer[STR_MAX_LENGTH]; - DWORD dwStringLength = LoadString(g_hInst,iResourceID,szBuffer,STR_MAX_LENGTH); - // if we loaded a string convert it to wide characters, ensuring - // that we also null terminate the result. - if (dwStringLength++) { - MultiByteToWideChar(CP_ACP,0,szBuffer,dwStringLength,pBuffer,STR_MAX_LENGTH); - } - } - return pBuffer; -} - -#endif - - -// Helper function to calculate the size of the dialog - -BOOL WINAPI GetDialogSize(int iResourceID, - DLGPROC pDlgProc, - LPARAM lParam, - __out SIZE *pResult) -{ - RECT rc; - HWND hwnd; - - // Create a temporary property page - - hwnd = CreateDialogParam(g_hInst, - MAKEINTRESOURCE(iResourceID), - GetDesktopWindow(), - pDlgProc, - lParam); - if (hwnd == NULL) { - return FALSE; - } - - GetWindowRect(hwnd, &rc); - pResult->cx = rc.right - rc.left; - pResult->cy = rc.bottom - rc.top; - - DestroyWindow(hwnd); - return TRUE; -} - - -// Class that aggregates on the IDirectDraw interface. Although DirectDraw -// has the ability in its interfaces to be aggregated they're not currently -// implemented. This makes it difficult for various parts of Quartz that want -// to aggregate these interfaces. In particular the video renderer passes out -// media samples that expose IDirectDraw and IDirectDrawSurface. The filter -// graph manager also exposes IDirectDraw as a plug in distributor. For these -// objects we provide these aggregation classes that republish the interfaces - -STDMETHODIMP CAggDirectDraw::NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv) -{ - ASSERT(m_pDirectDraw); - - // Do we have this interface - - if (riid == IID_IDirectDraw) { - return GetInterface((IDirectDraw *)this,ppv); - } else { - return CUnknown::NonDelegatingQueryInterface(riid,ppv); - } -} - - -STDMETHODIMP CAggDirectDraw::Compact() -{ - ASSERT(m_pDirectDraw); - return m_pDirectDraw->Compact(); -} - - -STDMETHODIMP CAggDirectDraw::CreateClipper(DWORD dwFlags, __deref_out LPDIRECTDRAWCLIPPER *lplpDDClipper, __inout_opt IUnknown *pUnkOuter) -{ - ASSERT(m_pDirectDraw); - return m_pDirectDraw->CreateClipper(dwFlags,lplpDDClipper,pUnkOuter); -} - - -STDMETHODIMP CAggDirectDraw::CreatePalette(DWORD dwFlags, - __in LPPALETTEENTRY lpColorTable, - __deref_out LPDIRECTDRAWPALETTE *lplpDDPalette, - __inout_opt IUnknown *pUnkOuter) -{ - ASSERT(m_pDirectDraw); - return m_pDirectDraw->CreatePalette(dwFlags,lpColorTable,lplpDDPalette,pUnkOuter); -} - - -STDMETHODIMP CAggDirectDraw::CreateSurface(__in LPDDSURFACEDESC lpDDSurfaceDesc, - __deref_out LPDIRECTDRAWSURFACE *lplpDDSurface, - __inout_opt IUnknown *pUnkOuter) -{ - ASSERT(m_pDirectDraw); - return m_pDirectDraw->CreateSurface(lpDDSurfaceDesc,lplpDDSurface,pUnkOuter); -} - - -STDMETHODIMP CAggDirectDraw::DuplicateSurface(__in LPDIRECTDRAWSURFACE lpDDSurface, - __deref_out LPDIRECTDRAWSURFACE *lplpDupDDSurface) -{ - ASSERT(m_pDirectDraw); - return m_pDirectDraw->DuplicateSurface(lpDDSurface,lplpDupDDSurface); -} - - -STDMETHODIMP CAggDirectDraw::EnumDisplayModes(DWORD dwSurfaceDescCount, - __in LPDDSURFACEDESC lplpDDSurfaceDescList, - __in LPVOID lpContext, - __in LPDDENUMMODESCALLBACK lpEnumCallback) -{ - ASSERT(m_pDirectDraw); - return m_pDirectDraw->EnumDisplayModes(dwSurfaceDescCount,lplpDDSurfaceDescList,lpContext,lpEnumCallback); -} - - -STDMETHODIMP CAggDirectDraw::EnumSurfaces(DWORD dwFlags, - __in LPDDSURFACEDESC lpDDSD, - __in LPVOID lpContext, - __in LPDDENUMSURFACESCALLBACK lpEnumCallback) -{ - ASSERT(m_pDirectDraw); - return m_pDirectDraw->EnumSurfaces(dwFlags,lpDDSD,lpContext,lpEnumCallback); -} - - -STDMETHODIMP CAggDirectDraw::FlipToGDISurface() -{ - ASSERT(m_pDirectDraw); - return m_pDirectDraw->FlipToGDISurface(); -} - - -STDMETHODIMP CAggDirectDraw::GetCaps(__out LPDDCAPS lpDDDriverCaps,__out LPDDCAPS lpDDHELCaps) -{ - ASSERT(m_pDirectDraw); - return m_pDirectDraw->GetCaps(lpDDDriverCaps,lpDDHELCaps); -} - - -STDMETHODIMP CAggDirectDraw::GetDisplayMode(__out LPDDSURFACEDESC lpDDSurfaceDesc) -{ - ASSERT(m_pDirectDraw); - return m_pDirectDraw->GetDisplayMode(lpDDSurfaceDesc); -} - - -STDMETHODIMP CAggDirectDraw::GetFourCCCodes(__inout LPDWORD lpNumCodes,__out_ecount(*lpNumCodes) LPDWORD lpCodes) -{ - ASSERT(m_pDirectDraw); - return m_pDirectDraw->GetFourCCCodes(lpNumCodes,lpCodes); -} - - -STDMETHODIMP CAggDirectDraw::GetGDISurface(__deref_out LPDIRECTDRAWSURFACE *lplpGDIDDSurface) -{ - ASSERT(m_pDirectDraw); - return m_pDirectDraw->GetGDISurface(lplpGDIDDSurface); -} - - -STDMETHODIMP CAggDirectDraw::GetMonitorFrequency(__out LPDWORD lpdwFrequency) -{ - ASSERT(m_pDirectDraw); - return m_pDirectDraw->GetMonitorFrequency(lpdwFrequency); -} - - -STDMETHODIMP CAggDirectDraw::GetScanLine(__out LPDWORD lpdwScanLine) -{ - ASSERT(m_pDirectDraw); - return m_pDirectDraw->GetScanLine(lpdwScanLine); -} - - -STDMETHODIMP CAggDirectDraw::GetVerticalBlankStatus(__out LPBOOL lpblsInVB) -{ - ASSERT(m_pDirectDraw); - return m_pDirectDraw->GetVerticalBlankStatus(lpblsInVB); -} - - -STDMETHODIMP CAggDirectDraw::Initialize(__in GUID *lpGUID) -{ - ASSERT(m_pDirectDraw); - return m_pDirectDraw->Initialize(lpGUID); -} - - -STDMETHODIMP CAggDirectDraw::RestoreDisplayMode() -{ - ASSERT(m_pDirectDraw); - return m_pDirectDraw->RestoreDisplayMode(); -} - - -STDMETHODIMP CAggDirectDraw::SetCooperativeLevel(HWND hWnd,DWORD dwFlags) -{ - ASSERT(m_pDirectDraw); - return m_pDirectDraw->SetCooperativeLevel(hWnd,dwFlags); -} - - -STDMETHODIMP CAggDirectDraw::SetDisplayMode(DWORD dwWidth,DWORD dwHeight,DWORD dwBpp) -{ - ASSERT(m_pDirectDraw); - return m_pDirectDraw->SetDisplayMode(dwWidth,dwHeight,dwBpp); -} - - -STDMETHODIMP CAggDirectDraw::WaitForVerticalBlank(DWORD dwFlags,HANDLE hEvent) -{ - ASSERT(m_pDirectDraw); - return m_pDirectDraw->WaitForVerticalBlank(dwFlags,hEvent); -} - - -// Class that aggregates an IDirectDrawSurface interface. Although DirectDraw -// has the ability in its interfaces to be aggregated they're not currently -// implemented. This makes it difficult for various parts of Quartz that want -// to aggregate these interfaces. In particular the video renderer passes out -// media samples that expose IDirectDraw and IDirectDrawSurface. The filter -// graph manager also exposes IDirectDraw as a plug in distributor. For these -// objects we provide these aggregation classes that republish the interfaces - -STDMETHODIMP CAggDrawSurface::NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv) -{ - ASSERT(m_pDirectDrawSurface); - - // Do we have this interface - - if (riid == IID_IDirectDrawSurface) { - return GetInterface((IDirectDrawSurface *)this,ppv); - } else { - return CUnknown::NonDelegatingQueryInterface(riid,ppv); - } -} - - -STDMETHODIMP CAggDrawSurface::AddAttachedSurface(__in LPDIRECTDRAWSURFACE lpDDSAttachedSurface) -{ - ASSERT(m_pDirectDrawSurface); - return m_pDirectDrawSurface->AddAttachedSurface(lpDDSAttachedSurface); -} - - -STDMETHODIMP CAggDrawSurface::AddOverlayDirtyRect(__in LPRECT lpRect) -{ - ASSERT(m_pDirectDrawSurface); - return m_pDirectDrawSurface->AddOverlayDirtyRect(lpRect); -} - - -STDMETHODIMP CAggDrawSurface::Blt(__in LPRECT lpDestRect, - __in LPDIRECTDRAWSURFACE lpDDSrcSurface, - __in LPRECT lpSrcRect, - DWORD dwFlags, - __in LPDDBLTFX lpDDBltFx) -{ - ASSERT(m_pDirectDrawSurface); - return m_pDirectDrawSurface->Blt(lpDestRect,lpDDSrcSurface,lpSrcRect,dwFlags,lpDDBltFx); -} - - -STDMETHODIMP CAggDrawSurface::BltBatch(__in_ecount(dwCount) LPDDBLTBATCH lpDDBltBatch,DWORD dwCount,DWORD dwFlags) -{ - ASSERT(m_pDirectDrawSurface); - return m_pDirectDrawSurface->BltBatch(lpDDBltBatch,dwCount,dwFlags); -} - - -STDMETHODIMP CAggDrawSurface::BltFast(DWORD dwX,DWORD dwY, - __in LPDIRECTDRAWSURFACE lpDDSrcSurface, - __in LPRECT lpSrcRect, - DWORD dwTrans) -{ - ASSERT(m_pDirectDrawSurface); - return m_pDirectDrawSurface->BltFast(dwX,dwY,lpDDSrcSurface,lpSrcRect,dwTrans); -} - - -STDMETHODIMP CAggDrawSurface::DeleteAttachedSurface(DWORD dwFlags, - __in LPDIRECTDRAWSURFACE lpDDSAttachedSurface) -{ - ASSERT(m_pDirectDrawSurface); - return m_pDirectDrawSurface->DeleteAttachedSurface(dwFlags,lpDDSAttachedSurface); -} - - -STDMETHODIMP CAggDrawSurface::EnumAttachedSurfaces(__in LPVOID lpContext, - __in LPDDENUMSURFACESCALLBACK lpEnumSurfacesCallback) -{ - ASSERT(m_pDirectDrawSurface); - return m_pDirectDrawSurface->EnumAttachedSurfaces(lpContext,lpEnumSurfacesCallback); -} - - -STDMETHODIMP CAggDrawSurface::EnumOverlayZOrders(DWORD dwFlags, - __in LPVOID lpContext, - __in LPDDENUMSURFACESCALLBACK lpfnCallback) -{ - ASSERT(m_pDirectDrawSurface); - return m_pDirectDrawSurface->EnumOverlayZOrders(dwFlags,lpContext,lpfnCallback); -} - - -STDMETHODIMP CAggDrawSurface::Flip(__in LPDIRECTDRAWSURFACE lpDDSurfaceTargetOverride,DWORD dwFlags) -{ - ASSERT(m_pDirectDrawSurface); - return m_pDirectDrawSurface->Flip(lpDDSurfaceTargetOverride,dwFlags); -} - - -STDMETHODIMP CAggDrawSurface::GetAttachedSurface(__in LPDDSCAPS lpDDSCaps, - __deref_out LPDIRECTDRAWSURFACE *lplpDDAttachedSurface) -{ - ASSERT(m_pDirectDrawSurface); - return m_pDirectDrawSurface->GetAttachedSurface(lpDDSCaps,lplpDDAttachedSurface); -} - - -STDMETHODIMP CAggDrawSurface::GetBltStatus(DWORD dwFlags) -{ - ASSERT(m_pDirectDrawSurface); - return m_pDirectDrawSurface->GetBltStatus(dwFlags); -} - - -STDMETHODIMP CAggDrawSurface::GetCaps(__out LPDDSCAPS lpDDSCaps) -{ - ASSERT(m_pDirectDrawSurface); - return m_pDirectDrawSurface->GetCaps(lpDDSCaps); -} - - -STDMETHODIMP CAggDrawSurface::GetClipper(__deref_out LPDIRECTDRAWCLIPPER *lplpDDClipper) -{ - ASSERT(m_pDirectDrawSurface); - return m_pDirectDrawSurface->GetClipper(lplpDDClipper); -} - - -STDMETHODIMP CAggDrawSurface::GetColorKey(DWORD dwFlags,__out LPDDCOLORKEY lpDDColorKey) -{ - ASSERT(m_pDirectDrawSurface); - return m_pDirectDrawSurface->GetColorKey(dwFlags,lpDDColorKey); -} - - -STDMETHODIMP CAggDrawSurface::GetDC(__out HDC *lphDC) -{ - ASSERT(m_pDirectDrawSurface); - return m_pDirectDrawSurface->GetDC(lphDC); -} - - -STDMETHODIMP CAggDrawSurface::GetFlipStatus(DWORD dwFlags) -{ - ASSERT(m_pDirectDrawSurface); - return m_pDirectDrawSurface->GetFlipStatus(dwFlags); -} - - -STDMETHODIMP CAggDrawSurface::GetOverlayPosition(__out LPLONG lpdwX,__out LPLONG lpdwY) -{ - ASSERT(m_pDirectDrawSurface); - return m_pDirectDrawSurface->GetOverlayPosition(lpdwX,lpdwY); -} - - -STDMETHODIMP CAggDrawSurface::GetPalette(__deref_out LPDIRECTDRAWPALETTE *lplpDDPalette) -{ - ASSERT(m_pDirectDrawSurface); - return m_pDirectDrawSurface->GetPalette(lplpDDPalette); -} - - -STDMETHODIMP CAggDrawSurface::GetPixelFormat(__out LPDDPIXELFORMAT lpDDPixelFormat) -{ - ASSERT(m_pDirectDrawSurface); - return m_pDirectDrawSurface->GetPixelFormat(lpDDPixelFormat); -} - - -// A bit of a warning here: Our media samples in DirectShow aggregate on -// IDirectDraw and IDirectDrawSurface (ie are available through IMediaSample -// by QueryInterface). Unfortunately the underlying DirectDraw code cannot -// be aggregated so we have to use these classes. The snag is that when we -// call a different surface and pass in this interface as perhaps the source -// surface the call will fail because DirectDraw dereferences the pointer to -// get at its private data structures. Therefore we supply this workaround to give -// access to the real IDirectDraw surface. A filter can call GetSurfaceDesc -// and we will fill in the lpSurface pointer with the real underlying surface - -STDMETHODIMP CAggDrawSurface::GetSurfaceDesc(__out LPDDSURFACEDESC lpDDSurfaceDesc) -{ - ASSERT(m_pDirectDrawSurface); - - // First call down to the underlying DirectDraw - - HRESULT hr = m_pDirectDrawSurface->GetSurfaceDesc(lpDDSurfaceDesc); - if (FAILED(hr)) { - return hr; - } - - // Store the real DirectDrawSurface interface - lpDDSurfaceDesc->lpSurface = m_pDirectDrawSurface; - return hr; -} - - -STDMETHODIMP CAggDrawSurface::Initialize(__in LPDIRECTDRAW lpDD,__in LPDDSURFACEDESC lpDDSurfaceDesc) -{ - ASSERT(m_pDirectDrawSurface); - return m_pDirectDrawSurface->Initialize(lpDD,lpDDSurfaceDesc); -} - - -STDMETHODIMP CAggDrawSurface::IsLost() -{ - ASSERT(m_pDirectDrawSurface); - return m_pDirectDrawSurface->IsLost(); -} - - -STDMETHODIMP CAggDrawSurface::Lock(__in LPRECT lpDestRect, - __inout LPDDSURFACEDESC lpDDSurfaceDesc, - DWORD dwFlags, - HANDLE hEvent) -{ - ASSERT(m_pDirectDrawSurface); - return m_pDirectDrawSurface->Lock(lpDestRect,lpDDSurfaceDesc,dwFlags,hEvent); -} - - -STDMETHODIMP CAggDrawSurface::ReleaseDC(HDC hDC) -{ - ASSERT(m_pDirectDrawSurface); - return m_pDirectDrawSurface->ReleaseDC(hDC); -} - - -STDMETHODIMP CAggDrawSurface::Restore() -{ - ASSERT(m_pDirectDrawSurface); - return m_pDirectDrawSurface->Restore(); -} - - -STDMETHODIMP CAggDrawSurface::SetClipper(__in LPDIRECTDRAWCLIPPER lpDDClipper) -{ - ASSERT(m_pDirectDrawSurface); - return m_pDirectDrawSurface->SetClipper(lpDDClipper); -} - - -STDMETHODIMP CAggDrawSurface::SetColorKey(DWORD dwFlags,__in LPDDCOLORKEY lpDDColorKey) -{ - ASSERT(m_pDirectDrawSurface); - return m_pDirectDrawSurface->SetColorKey(dwFlags,lpDDColorKey); -} - - -STDMETHODIMP CAggDrawSurface::SetOverlayPosition(LONG dwX,LONG dwY) -{ - ASSERT(m_pDirectDrawSurface); - return m_pDirectDrawSurface->SetOverlayPosition(dwX,dwY); -} - - -STDMETHODIMP CAggDrawSurface::SetPalette(__in LPDIRECTDRAWPALETTE lpDDPalette) -{ - ASSERT(m_pDirectDrawSurface); - return m_pDirectDrawSurface->SetPalette(lpDDPalette); -} - - -STDMETHODIMP CAggDrawSurface::Unlock(__in LPVOID lpSurfaceData) -{ - ASSERT(m_pDirectDrawSurface); - return m_pDirectDrawSurface->Unlock(lpSurfaceData); -} - - -STDMETHODIMP CAggDrawSurface::UpdateOverlay(__in LPRECT lpSrcRect, - __in LPDIRECTDRAWSURFACE lpDDDestSurface, - __in LPRECT lpDestRect, - DWORD dwFlags, - __in LPDDOVERLAYFX lpDDOverlayFX) -{ - ASSERT(m_pDirectDrawSurface); - return m_pDirectDrawSurface->UpdateOverlay(lpSrcRect,lpDDDestSurface,lpDestRect,dwFlags,lpDDOverlayFX); -} - - -STDMETHODIMP CAggDrawSurface::UpdateOverlayDisplay(DWORD dwFlags) -{ - ASSERT(m_pDirectDrawSurface); - return m_pDirectDrawSurface->UpdateOverlayDisplay(dwFlags); -} - - -STDMETHODIMP CAggDrawSurface::UpdateOverlayZOrder(DWORD dwFlags,__in LPDIRECTDRAWSURFACE lpDDSReference) -{ - ASSERT(m_pDirectDrawSurface); - return m_pDirectDrawSurface->UpdateOverlayZOrder(dwFlags,lpDDSReference); -} - - -// DirectShow must work on multiple platforms. In particular, it also runs on -// Windows NT 3.51 which does not have DirectDraw capabilities. The filters -// cannot therefore link statically to the DirectDraw library. To make their -// lives that little bit easier we provide this class that manages loading -// and unloading the library and creating the initial IDirectDraw interface - -CLoadDirectDraw::CLoadDirectDraw() : - m_pDirectDraw(NULL), - m_hDirectDraw(NULL) -{ -} - - -// Destructor forces unload - -CLoadDirectDraw::~CLoadDirectDraw() -{ - ReleaseDirectDraw(); - - if (m_hDirectDraw) { - NOTE("Unloading library"); - FreeLibrary(m_hDirectDraw); - } -} - - -// We can't be sure that DirectDraw is always available so we can't statically -// link to the library. Therefore we load the library, get the function entry -// point addresses and call them to create the driver objects. We return S_OK -// if we manage to load DirectDraw correctly otherwise we return E_NOINTERFACE -// We initialise a DirectDraw instance by explicitely loading the library and -// calling GetProcAddress on the DirectDrawCreate entry point that it exports - -// On a multi monitor system, we can get the DirectDraw object for any -// monitor (device) with the optional szDevice parameter - -HRESULT CLoadDirectDraw::LoadDirectDraw(__in LPSTR szDevice) -{ - PDRAWCREATE pDrawCreate; - PDRAWENUM pDrawEnum; - LPDIRECTDRAWENUMERATEEXA pDrawEnumEx; - HRESULT hr = NOERROR; - - NOTE("Entering DoLoadDirectDraw"); - - // Is DirectDraw already loaded - - if (m_pDirectDraw) { - NOTE("Already loaded"); - ASSERT(m_hDirectDraw); - return NOERROR; - } - - // Make sure the library is available - - if(!m_hDirectDraw) - { - UINT ErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX); - m_hDirectDraw = LoadLibrary(TEXT("DDRAW.DLL")); - SetErrorMode(ErrorMode); - - if (m_hDirectDraw == NULL) { - DbgLog((LOG_ERROR,1,TEXT("Can't load DDRAW.DLL"))); - NOTE("No library"); - return E_NOINTERFACE; - } - } - - // Get the DLL address for the creator function - - pDrawCreate = (PDRAWCREATE)GetProcAddress(m_hDirectDraw,"DirectDrawCreate"); - // force ANSI, we assume it - pDrawEnum = (PDRAWENUM)GetProcAddress(m_hDirectDraw,"DirectDrawEnumerateA"); - pDrawEnumEx = (LPDIRECTDRAWENUMERATEEXA)GetProcAddress(m_hDirectDraw, - "DirectDrawEnumerateExA"); - - // We don't NEED DirectDrawEnumerateEx, that's just for multimon stuff - if (pDrawCreate == NULL || pDrawEnum == NULL) { - DbgLog((LOG_ERROR,1,TEXT("Can't get functions: Create=%x Enum=%x"), - pDrawCreate, pDrawEnum)); - NOTE("No entry point"); - ReleaseDirectDraw(); - return E_NOINTERFACE; - } - - DbgLog((LOG_TRACE,3,TEXT("Creating DDraw for device %s"), - szDevice ? szDevice : "")); - - // Create a DirectDraw display provider for this device, using the fancy - // multimon-aware version, if it exists - if (pDrawEnumEx) - m_pDirectDraw = DirectDrawCreateFromDeviceEx(szDevice, pDrawCreate, - pDrawEnumEx); - else - m_pDirectDraw = DirectDrawCreateFromDevice(szDevice, pDrawCreate, - pDrawEnum); - - if (m_pDirectDraw == NULL) { - DbgLog((LOG_ERROR,1,TEXT("Can't create DDraw"))); - NOTE("No instance"); - ReleaseDirectDraw(); - return E_NOINTERFACE; - } - return NOERROR; -} - - -// Called to release any DirectDraw provider we previously loaded. We may be -// called at any time especially when something goes horribly wrong and when -// we need to clean up before returning so we can't guarantee that all state -// variables are consistent so free only those really allocated allocated -// This should only be called once all reference counts have been released - -void CLoadDirectDraw::ReleaseDirectDraw() -{ - NOTE("Releasing DirectDraw driver"); - - // Release any DirectDraw provider interface - - if (m_pDirectDraw) { - NOTE("Releasing instance"); - m_pDirectDraw->Release(); - m_pDirectDraw = NULL; - } - -} - - -// Return NOERROR (S_OK) if DirectDraw has been loaded by this object - -HRESULT CLoadDirectDraw::IsDirectDrawLoaded() -{ - NOTE("Entering IsDirectDrawLoaded"); - - if (m_pDirectDraw == NULL) { - NOTE("DirectDraw not loaded"); - return S_FALSE; - } - return NOERROR; -} - - -// Return the IDirectDraw interface we look after - -LPDIRECTDRAW CLoadDirectDraw::GetDirectDraw() -{ - NOTE("Entering GetDirectDraw"); - - if (m_pDirectDraw == NULL) { - NOTE("No DirectDraw"); - return NULL; - } - - NOTE("Returning DirectDraw"); - m_pDirectDraw->AddRef(); - return m_pDirectDraw; -} - - -// Are we running on Direct Draw version 1? We need to find out as -// we rely on specific bug fixes in DirectDraw 2 for fullscreen playback. To -// find out, we simply see if it supports IDirectDraw2. Only version 2 and -// higher support this. - -BOOL CLoadDirectDraw::IsDirectDrawVersion1() -{ - - if (m_pDirectDraw == NULL) - return FALSE; - - IDirectDraw2 *p = NULL; - HRESULT hr = m_pDirectDraw->QueryInterface(IID_IDirectDraw2, (void **)&p); - if (p) - p->Release(); - if (hr == NOERROR) { - DbgLog((LOG_TRACE,3,TEXT("Direct Draw Version 2 or greater"))); - return FALSE; - } else { - DbgLog((LOG_TRACE,3,TEXT("Direct Draw Version 1"))); - return TRUE; - } -} diff --git a/third_party/BaseClasses/videoctl.h b/third_party/BaseClasses/videoctl.h deleted file mode 100644 index 30c37783..00000000 --- a/third_party/BaseClasses/videoctl.h +++ /dev/null @@ -1,168 +0,0 @@ -//------------------------------------------------------------------------------ -// File: VideoCtl.h -// -// Desc: DirectShow base classes. -// -// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. -//------------------------------------------------------------------------------ - - -#ifndef __VIDEOCTL__ -#define __VIDEOCTL__ - -// These help with property page implementations. The first can be used to -// load any string from a resource file. The buffer to load into is passed -// as an input parameter. The same buffer is the return value if the string -// was found otherwise it returns TEXT(""). The GetDialogSize is passed the -// resource ID of a dialog box and returns the size of it in screen pixels - -#define STR_MAX_LENGTH 256 -LPTSTR WINAPI StringFromResource(__out_ecount(STR_MAX_LENGTH) LPTSTR pBuffer, int iResourceID); - -#ifdef UNICODE -#define WideStringFromResource StringFromResource -LPSTR WINAPI StringFromResource(__out_ecount(STR_MAX_LENGTH) LPSTR pBuffer, int iResourceID); -#else -LPWSTR WINAPI WideStringFromResource(__out_ecount(STR_MAX_LENGTH) LPWSTR pBuffer, int iResourceID); -#endif - - -BOOL WINAPI GetDialogSize(int iResourceID, // Dialog box resource identifier - DLGPROC pDlgProc, // Pointer to dialog procedure - LPARAM lParam, // Any user data wanted in pDlgProc - __out SIZE *pResult);// Returns the size of dialog box - -// Class that aggregates an IDirectDraw interface - -class CAggDirectDraw : public IDirectDraw, public CUnknown -{ -protected: - - LPDIRECTDRAW m_pDirectDraw; - -public: - - DECLARE_IUNKNOWN - STDMETHODIMP NonDelegatingQueryInterface(REFIID riid,__deref_out void **ppv); - - // Constructor and destructor - - CAggDirectDraw(__in_opt LPCTSTR pName,__inout_opt LPUNKNOWN pUnk) : - CUnknown(pName,pUnk), - m_pDirectDraw(NULL) { }; - - virtual CAggDirectDraw::~CAggDirectDraw() { }; - - // Set the object we should be aggregating - void SetDirectDraw(__inout LPDIRECTDRAW pDirectDraw) { - m_pDirectDraw = pDirectDraw; - } - - // IDirectDraw methods - - STDMETHODIMP Compact(); - STDMETHODIMP CreateClipper(DWORD dwFlags,__deref_out LPDIRECTDRAWCLIPPER *lplpDDClipper,__inout_opt IUnknown *pUnkOuter); - STDMETHODIMP CreatePalette(DWORD dwFlags,__in LPPALETTEENTRY lpColorTable,__deref_out LPDIRECTDRAWPALETTE *lplpDDPalette,__inout_opt IUnknown *pUnkOuter); - STDMETHODIMP CreateSurface(__in LPDDSURFACEDESC lpDDSurfaceDesc,__deref_out LPDIRECTDRAWSURFACE *lplpDDSurface,__inout_opt IUnknown *pUnkOuter); - STDMETHODIMP DuplicateSurface(__in LPDIRECTDRAWSURFACE lpDDSurface,__deref_out LPDIRECTDRAWSURFACE *lplpDupDDSurface); - STDMETHODIMP EnumDisplayModes(DWORD dwSurfaceDescCount,__in LPDDSURFACEDESC lplpDDSurfaceDescList,__in LPVOID lpContext,__in LPDDENUMMODESCALLBACK lpEnumCallback); - STDMETHODIMP EnumSurfaces(DWORD dwFlags,__in LPDDSURFACEDESC lpDDSD,__in LPVOID lpContext,__in LPDDENUMSURFACESCALLBACK lpEnumCallback); - STDMETHODIMP FlipToGDISurface(); - STDMETHODIMP GetCaps(__out LPDDCAPS lpDDDriverCaps,__out LPDDCAPS lpDDHELCaps); - STDMETHODIMP GetDisplayMode(__out LPDDSURFACEDESC lpDDSurfaceDesc); - STDMETHODIMP GetFourCCCodes(__inout LPDWORD lpNumCodes,__out_ecount(*lpNumCodes) LPDWORD lpCodes); - STDMETHODIMP GetGDISurface(__deref_out LPDIRECTDRAWSURFACE *lplpGDIDDSurface); - STDMETHODIMP GetMonitorFrequency(__out LPDWORD lpdwFrequency); - STDMETHODIMP GetScanLine(__out LPDWORD lpdwScanLine); - STDMETHODIMP GetVerticalBlankStatus(__out LPBOOL lpblsInVB); - STDMETHODIMP Initialize(__in GUID *lpGUID); - STDMETHODIMP RestoreDisplayMode(); - STDMETHODIMP SetCooperativeLevel(HWND hWnd,DWORD dwFlags); - STDMETHODIMP SetDisplayMode(DWORD dwWidth,DWORD dwHeight,DWORD dwBpp); - STDMETHODIMP WaitForVerticalBlank(DWORD dwFlags,HANDLE hEvent); -}; - - -// Class that aggregates an IDirectDrawSurface interface - -class CAggDrawSurface : public IDirectDrawSurface, public CUnknown -{ -protected: - - LPDIRECTDRAWSURFACE m_pDirectDrawSurface; - -public: - - DECLARE_IUNKNOWN - STDMETHODIMP NonDelegatingQueryInterface(REFIID riid,__deref_out void **ppv); - - // Constructor and destructor - - CAggDrawSurface(__in_opt LPCTSTR pName,__inout_opt LPUNKNOWN pUnk) : - CUnknown(pName,pUnk), - m_pDirectDrawSurface(NULL) { }; - - virtual ~CAggDrawSurface() { }; - - // Set the object we should be aggregating - void SetDirectDrawSurface(__inout LPDIRECTDRAWSURFACE pDirectDrawSurface) { - m_pDirectDrawSurface = pDirectDrawSurface; - } - - // IDirectDrawSurface methods - - STDMETHODIMP AddAttachedSurface(__in LPDIRECTDRAWSURFACE lpDDSAttachedSurface); - STDMETHODIMP AddOverlayDirtyRect(__in LPRECT lpRect); - STDMETHODIMP Blt(__in LPRECT lpDestRect,__in LPDIRECTDRAWSURFACE lpDDSrcSurface,__in LPRECT lpSrcRect,DWORD dwFlags,__in LPDDBLTFX lpDDBltFx); - STDMETHODIMP BltBatch(__in_ecount(dwCount) LPDDBLTBATCH lpDDBltBatch,DWORD dwCount,DWORD dwFlags); - STDMETHODIMP BltFast(DWORD dwX,DWORD dwY,__in LPDIRECTDRAWSURFACE lpDDSrcSurface,__in LPRECT lpSrcRect,DWORD dwTrans); - STDMETHODIMP DeleteAttachedSurface(DWORD dwFlags,__in LPDIRECTDRAWSURFACE lpDDSAttachedSurface); - STDMETHODIMP EnumAttachedSurfaces(__in LPVOID lpContext,__in LPDDENUMSURFACESCALLBACK lpEnumSurfacesCallback); - STDMETHODIMP EnumOverlayZOrders(DWORD dwFlags,__in LPVOID lpContext,__in LPDDENUMSURFACESCALLBACK lpfnCallback); - STDMETHODIMP Flip(__in LPDIRECTDRAWSURFACE lpDDSurfaceTargetOverride,DWORD dwFlags); - STDMETHODIMP GetAttachedSurface(__in LPDDSCAPS lpDDSCaps,__deref_out LPDIRECTDRAWSURFACE *lplpDDAttachedSurface); - STDMETHODIMP GetBltStatus(DWORD dwFlags); - STDMETHODIMP GetCaps(__out LPDDSCAPS lpDDSCaps); - STDMETHODIMP GetClipper(__deref_out LPDIRECTDRAWCLIPPER *lplpDDClipper); - STDMETHODIMP GetColorKey(DWORD dwFlags,__out LPDDCOLORKEY lpDDColorKey); - STDMETHODIMP GetDC(__out HDC *lphDC); - STDMETHODIMP GetFlipStatus(DWORD dwFlags); - STDMETHODIMP GetOverlayPosition(__out LPLONG lpdwX,__out LPLONG lpdwY); - STDMETHODIMP GetPalette(__deref_out LPDIRECTDRAWPALETTE *lplpDDPalette); - STDMETHODIMP GetPixelFormat(__out LPDDPIXELFORMAT lpDDPixelFormat); - STDMETHODIMP GetSurfaceDesc(__out LPDDSURFACEDESC lpDDSurfaceDesc); - STDMETHODIMP Initialize(__in LPDIRECTDRAW lpDD,__in LPDDSURFACEDESC lpDDSurfaceDesc); - STDMETHODIMP IsLost(); - STDMETHODIMP Lock(__in LPRECT lpDestRect,__inout LPDDSURFACEDESC lpDDSurfaceDesc,DWORD dwFlags,HANDLE hEvent); - STDMETHODIMP ReleaseDC(HDC hDC); - STDMETHODIMP Restore(); - STDMETHODIMP SetClipper(__in LPDIRECTDRAWCLIPPER lpDDClipper); - STDMETHODIMP SetColorKey(DWORD dwFlags,__in LPDDCOLORKEY lpDDColorKey); - STDMETHODIMP SetOverlayPosition(LONG dwX,LONG dwY); - STDMETHODIMP SetPalette(__in LPDIRECTDRAWPALETTE lpDDPalette); - STDMETHODIMP Unlock(__in LPVOID lpSurfaceData); - STDMETHODIMP UpdateOverlay(__in LPRECT lpSrcRect,__in LPDIRECTDRAWSURFACE lpDDDestSurface,__in LPRECT lpDestRect,DWORD dwFlags,__in LPDDOVERLAYFX lpDDOverlayFX); - STDMETHODIMP UpdateOverlayDisplay(DWORD dwFlags); - STDMETHODIMP UpdateOverlayZOrder(DWORD dwFlags,__in LPDIRECTDRAWSURFACE lpDDSReference); -}; - - -class CLoadDirectDraw -{ - LPDIRECTDRAW m_pDirectDraw; // The DirectDraw driver instance - HINSTANCE m_hDirectDraw; // Handle to the loaded library - -public: - - CLoadDirectDraw(); - ~CLoadDirectDraw(); - - HRESULT LoadDirectDraw(__in LPSTR szDevice); - void ReleaseDirectDraw(); - HRESULT IsDirectDrawLoaded(); - LPDIRECTDRAW GetDirectDraw(); - BOOL IsDirectDrawVersion1(); -}; - -#endif // __VIDEOCTL__ - diff --git a/third_party/BaseClasses/vtrans.cpp b/third_party/BaseClasses/vtrans.cpp deleted file mode 100644 index cb4fa998..00000000 --- a/third_party/BaseClasses/vtrans.cpp +++ /dev/null @@ -1,468 +0,0 @@ -//------------------------------------------------------------------------------ -// File: Vtrans.cpp -// -// Desc: DirectShow base classes. -// -// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. -//------------------------------------------------------------------------------ - - -#include -#include -// #include // now in precomp file streams.h - -CVideoTransformFilter::CVideoTransformFilter - ( __in_opt LPCTSTR pName, __inout_opt LPUNKNOWN pUnk, REFCLSID clsid) - : CTransformFilter(pName, pUnk, clsid) - , m_itrLate(0) - , m_nKeyFramePeriod(0) // No QM until we see at least 2 key frames - , m_nFramesSinceKeyFrame(0) - , m_bSkipping(FALSE) - , m_tDecodeStart(0) - , m_itrAvgDecode(300000) // 30mSec - probably allows skipping - , m_bQualityChanged(FALSE) -{ -#ifdef PERF - RegisterPerfId(); -#endif // PERF -} - - -CVideoTransformFilter::~CVideoTransformFilter() -{ - // nothing to do -} - - -// Reset our quality management state - -HRESULT CVideoTransformFilter::StartStreaming() -{ - m_itrLate = 0; - m_nKeyFramePeriod = 0; // No QM until we see at least 2 key frames - m_nFramesSinceKeyFrame = 0; - m_bSkipping = FALSE; - m_tDecodeStart = 0; - m_itrAvgDecode = 300000; // 30mSec - probably allows skipping - m_bQualityChanged = FALSE; - m_bSampleSkipped = FALSE; - return NOERROR; -} - - -// Overriden to reset quality management information - -HRESULT CVideoTransformFilter::EndFlush() -{ - { - // Synchronize - CAutoLock lck(&m_csReceive); - - // Reset our stats - // - // Note - we don't want to call derived classes here, - // we only want to reset our internal variables and this - // is a convenient way to do it - CVideoTransformFilter::StartStreaming(); - } - return CTransformFilter::EndFlush(); -} - - -HRESULT CVideoTransformFilter::AbortPlayback(HRESULT hr) -{ - NotifyEvent(EC_ERRORABORT, hr, 0); - m_pOutput->DeliverEndOfStream(); - return hr; -} - - -// Receive() -// -// Accept a sample from upstream, decide whether to process it -// or drop it. If we process it then get a buffer from the -// allocator of the downstream connection, transform it into the -// new buffer and deliver it to the downstream filter. -// If we decide not to process it then we do not get a buffer. - -// Remember that although this code will notice format changes coming into -// the input pin, it will NOT change its output format if that results -// in the filter needing to make a corresponding output format change. Your -// derived filter will have to take care of that. (eg. a palette change if -// the input and output is an 8 bit format). If the input sample is discarded -// and nothing is sent out for this Receive, please remember to put the format -// change on the first output sample that you actually do send. -// If your filter will produce the same output type even when the input type -// changes, then this base class code will do everything you need. - -HRESULT CVideoTransformFilter::Receive(IMediaSample *pSample) -{ - // If the next filter downstream is the video renderer, then it may - // be able to operate in DirectDraw mode which saves copying the data - // and gives higher performance. In that case the buffer which we - // get from GetDeliveryBuffer will be a DirectDraw buffer, and - // drawing into this buffer draws directly onto the display surface. - // This means that any waiting for the correct time to draw occurs - // during GetDeliveryBuffer, and that once the buffer is given to us - // the video renderer will count it in its statistics as a frame drawn. - // This means that any decision to drop the frame must be taken before - // calling GetDeliveryBuffer. - - ASSERT(CritCheckIn(&m_csReceive)); - AM_MEDIA_TYPE *pmtOut, *pmt; -#ifdef DEBUG - FOURCCMap fccOut; -#endif - HRESULT hr; - ASSERT(pSample); - IMediaSample * pOutSample; - - // If no output pin to deliver to then no point sending us data - ASSERT (m_pOutput != NULL) ; - - // The source filter may dynamically ask us to start transforming from a - // different media type than the one we're using now. If we don't, we'll - // draw garbage. (typically, this is a palette change in the movie, - // but could be something more sinister like the compression type changing, - // or even the video size changing) - -#define rcS1 ((VIDEOINFOHEADER *)(pmt->pbFormat))->rcSource -#define rcT1 ((VIDEOINFOHEADER *)(pmt->pbFormat))->rcTarget - - pSample->GetMediaType(&pmt); - if (pmt != NULL && pmt->pbFormat != NULL) { - - // spew some debug output - ASSERT(!IsEqualGUID(pmt->majortype, GUID_NULL)); -#ifdef DEBUG - fccOut.SetFOURCC(&pmt->subtype); - LONG lCompression = HEADER(pmt->pbFormat)->biCompression; - LONG lBitCount = HEADER(pmt->pbFormat)->biBitCount; - LONG lStride = (HEADER(pmt->pbFormat)->biWidth * lBitCount + 7) / 8; - lStride = (lStride + 3) & ~3; - DbgLog((LOG_TRACE,3,TEXT("*Changing input type on the fly to"))); - DbgLog((LOG_TRACE,3,TEXT("FourCC: %lx Compression: %lx BitCount: %ld"), - fccOut.GetFOURCC(), lCompression, lBitCount)); - DbgLog((LOG_TRACE,3,TEXT("biHeight: %ld rcDst: (%ld, %ld, %ld, %ld)"), - HEADER(pmt->pbFormat)->biHeight, - rcT1.left, rcT1.top, rcT1.right, rcT1.bottom)); - DbgLog((LOG_TRACE,3,TEXT("rcSrc: (%ld, %ld, %ld, %ld) Stride: %ld"), - rcS1.left, rcS1.top, rcS1.right, rcS1.bottom, - lStride)); -#endif - - // now switch to using the new format. I am assuming that the - // derived filter will do the right thing when its media type is - // switched and streaming is restarted. - - StopStreaming(); - m_pInput->CurrentMediaType() = *pmt; - DeleteMediaType(pmt); - // if this fails, playback will stop, so signal an error - hr = StartStreaming(); - if (FAILED(hr)) { - return AbortPlayback(hr); - } - } - - // Now that we have noticed any format changes on the input sample, it's - // OK to discard it. - - if (ShouldSkipFrame(pSample)) { - MSR_NOTE(m_idSkip); - m_bSampleSkipped = TRUE; - return NOERROR; - } - - // Set up the output sample - hr = InitializeOutputSample(pSample, &pOutSample); - - if (FAILED(hr)) { - return hr; - } - - m_bSampleSkipped = FALSE; - - // The renderer may ask us to on-the-fly to start transforming to a - // different format. If we don't obey it, we'll draw garbage - -#define rcS ((VIDEOINFOHEADER *)(pmtOut->pbFormat))->rcSource -#define rcT ((VIDEOINFOHEADER *)(pmtOut->pbFormat))->rcTarget - - pOutSample->GetMediaType(&pmtOut); - if (pmtOut != NULL && pmtOut->pbFormat != NULL) { - - // spew some debug output - ASSERT(!IsEqualGUID(pmtOut->majortype, GUID_NULL)); -#ifdef DEBUG - fccOut.SetFOURCC(&pmtOut->subtype); - LONG lCompression = HEADER(pmtOut->pbFormat)->biCompression; - LONG lBitCount = HEADER(pmtOut->pbFormat)->biBitCount; - LONG lStride = (HEADER(pmtOut->pbFormat)->biWidth * lBitCount + 7) / 8; - lStride = (lStride + 3) & ~3; - DbgLog((LOG_TRACE,3,TEXT("*Changing output type on the fly to"))); - DbgLog((LOG_TRACE,3,TEXT("FourCC: %lx Compression: %lx BitCount: %ld"), - fccOut.GetFOURCC(), lCompression, lBitCount)); - DbgLog((LOG_TRACE,3,TEXT("biHeight: %ld rcDst: (%ld, %ld, %ld, %ld)"), - HEADER(pmtOut->pbFormat)->biHeight, - rcT.left, rcT.top, rcT.right, rcT.bottom)); - DbgLog((LOG_TRACE,3,TEXT("rcSrc: (%ld, %ld, %ld, %ld) Stride: %ld"), - rcS.left, rcS.top, rcS.right, rcS.bottom, - lStride)); -#endif - - // now switch to using the new format. I am assuming that the - // derived filter will do the right thing when its media type is - // switched and streaming is restarted. - - StopStreaming(); - m_pOutput->CurrentMediaType() = *pmtOut; - DeleteMediaType(pmtOut); - hr = StartStreaming(); - - if (SUCCEEDED(hr)) { - // a new format, means a new empty buffer, so wait for a keyframe - // before passing anything on to the renderer. - // !!! a keyframe may never come, so give up after 30 frames - DbgLog((LOG_TRACE,3,TEXT("Output format change means we must wait for a keyframe"))); - m_nWaitForKey = 30; - - // if this fails, playback will stop, so signal an error - } else { - - // Must release the sample before calling AbortPlayback - // because we might be holding the win16 lock or - // ddraw lock - pOutSample->Release(); - AbortPlayback(hr); - return hr; - } - } - - // After a discontinuity, we need to wait for the next key frame - if (pSample->IsDiscontinuity() == S_OK) { - DbgLog((LOG_TRACE,3,TEXT("Non-key discontinuity - wait for keyframe"))); - m_nWaitForKey = 30; - } - - // Start timing the transform (and log it if PERF is defined) - - if (SUCCEEDED(hr)) { - m_tDecodeStart = timeGetTime(); - MSR_START(m_idTransform); - - // have the derived class transform the data - hr = Transform(pSample, pOutSample); - - // Stop the clock (and log it if PERF is defined) - MSR_STOP(m_idTransform); - m_tDecodeStart = timeGetTime()-m_tDecodeStart; - m_itrAvgDecode = m_tDecodeStart*(10000/16) + 15*(m_itrAvgDecode/16); - - // Maybe we're waiting for a keyframe still? - if (m_nWaitForKey) - m_nWaitForKey--; - if (m_nWaitForKey && pSample->IsSyncPoint() == S_OK) - m_nWaitForKey = FALSE; - - // if so, then we don't want to pass this on to the renderer - if (m_nWaitForKey && hr == NOERROR) { - DbgLog((LOG_TRACE,3,TEXT("still waiting for a keyframe"))); - hr = S_FALSE; - } - } - - if (FAILED(hr)) { - DbgLog((LOG_TRACE,1,TEXT("Error from video transform"))); - } else { - // the Transform() function can return S_FALSE to indicate that the - // sample should not be delivered; we only deliver the sample if it's - // really S_OK (same as NOERROR, of course.) - // Try not to return S_FALSE to a direct draw buffer (it's wasteful) - // Try to take the decision earlier - before you get it. - - if (hr == NOERROR) { - hr = m_pOutput->Deliver(pOutSample); - } else { - // S_FALSE returned from Transform is a PRIVATE agreement - // We should return NOERROR from Receive() in this case because returning S_FALSE - // from Receive() means that this is the end of the stream and no more data should - // be sent. - if (S_FALSE == hr) { - - // We must Release() the sample before doing anything - // like calling the filter graph because having the - // sample means we may have the DirectDraw lock - // (== win16 lock on some versions) - pOutSample->Release(); - m_bSampleSkipped = TRUE; - if (!m_bQualityChanged) { - m_bQualityChanged = TRUE; - NotifyEvent(EC_QUALITY_CHANGE,0,0); - } - return NOERROR; - } - } - } - - // release the output buffer. If the connected pin still needs it, - // it will have addrefed it itself. - pOutSample->Release(); - ASSERT(CritCheckIn(&m_csReceive)); - - return hr; -} - - - -BOOL CVideoTransformFilter::ShouldSkipFrame( IMediaSample * pIn) -{ - REFERENCE_TIME trStart, trStopAt; - HRESULT hr = pIn->GetTime(&trStart, &trStopAt); - - // Don't skip frames with no timestamps - if (hr != S_OK) - return FALSE; - - int itrFrame = (int)(trStopAt - trStart); // frame duration - - if(S_OK==pIn->IsSyncPoint()) { - MSR_INTEGER(m_idFrameType, 1); - if ( m_nKeyFramePeriod < m_nFramesSinceKeyFrame ) { - // record the max - m_nKeyFramePeriod = m_nFramesSinceKeyFrame; - } - m_nFramesSinceKeyFrame = 0; - m_bSkipping = FALSE; - } else { - MSR_INTEGER(m_idFrameType, 2); - if ( m_nFramesSinceKeyFrame>m_nKeyFramePeriod - && m_nKeyFramePeriod>0 - ) { - // We haven't seen the key frame yet, but we were clearly being - // overoptimistic about how frequent they are. - m_nKeyFramePeriod = m_nFramesSinceKeyFrame; - } - } - - - // Whatever we might otherwise decide, - // if we are taking only a small fraction of the required frame time to decode - // then any quality problems are actually coming from somewhere else. - // Could be a net problem at the source for instance. In this case there's - // no point in us skipping frames here. - if (m_itrAvgDecode*4>itrFrame) { - - // Don't skip unless we are at least a whole frame late. - // (We would skip B frames if more than 1/2 frame late, but they're safe). - if ( m_itrLate > itrFrame ) { - - // Don't skip unless the anticipated key frame would be no more than - // 1 frame early. If the renderer has not been waiting (we *guess* - // it hasn't because we're late) then it will allow frames to be - // played early by up to a frame. - - // Let T = Stream time from now to anticipated next key frame - // = (frame duration) * (KeyFramePeriod - FramesSinceKeyFrame) - // So we skip if T - Late < one frame i.e. - // (duration) * (freq - FramesSince) - Late < duration - // or (duration) * (freq - FramesSince - 1) < Late - - // We don't dare skip until we have seen some key frames and have - // some idea how often they occur and they are reasonably frequent. - if (m_nKeyFramePeriod>0) { - // It would be crazy - but we could have a stream with key frames - // a very long way apart - and if they are further than about - // 3.5 minutes apart then we could get arithmetic overflow in - // reference time units. Therefore we switch to mSec at this point - int it = (itrFrame/10000) - * (m_nKeyFramePeriod-m_nFramesSinceKeyFrame - 1); - MSR_INTEGER(m_idTimeTillKey, it); - - // For debug - might want to see the details - dump them as scratch pad -#ifdef VTRANSPERF - MSR_INTEGER(0, itrFrame); - MSR_INTEGER(0, m_nFramesSinceKeyFrame); - MSR_INTEGER(0, m_nKeyFramePeriod); -#endif - if (m_itrLate/10000 > it) { - m_bSkipping = TRUE; - // Now we are committed. Once we start skipping, we - // cannot stop until we hit a key frame. - } else { -#ifdef VTRANSPERF - MSR_INTEGER(0, 777770); // not near enough to next key -#endif - } - } else { -#ifdef VTRANSPERF - MSR_INTEGER(0, 777771); // Next key not predictable -#endif - } - } else { -#ifdef VTRANSPERF - MSR_INTEGER(0, 777772); // Less than one frame late - MSR_INTEGER(0, m_itrLate); - MSR_INTEGER(0, itrFrame); -#endif - } - } else { -#ifdef VTRANSPERF - MSR_INTEGER(0, 777773); // Decode time short - not not worth skipping - MSR_INTEGER(0, m_itrAvgDecode); - MSR_INTEGER(0, itrFrame); -#endif - } - - ++m_nFramesSinceKeyFrame; - - if (m_bSkipping) { - // We will count down the lateness as we skip each frame. - // We re-assess each frame. The key frame might not arrive when expected. - // We reset m_itrLate if we get a new Quality message, but actually that's - // not likely because we're not sending frames on to the Renderer. In - // fact if we DID get another one it would mean that there's a long - // pipe between us and the renderer and we might need an altogether - // better strategy to avoid hunting! - m_itrLate = m_itrLate - itrFrame; - } - - MSR_INTEGER(m_idLate, (int)m_itrLate/10000 ); // Note how late we think we are - if (m_bSkipping) { - if (!m_bQualityChanged) { - m_bQualityChanged = TRUE; - NotifyEvent(EC_QUALITY_CHANGE,0,0); - } - } - return m_bSkipping; -} - - -HRESULT CVideoTransformFilter::AlterQuality(Quality q) -{ - // to reduce the amount of 64 bit arithmetic, m_itrLate is an int. - // +, -, >, == etc are not too bad, but * and / are painful. - if (m_itrLate>300000000) { - // Avoid overflow and silliness - more than 30 secs late is already silly - m_itrLate = 300000000; - } else { - m_itrLate = (int)q.Late; - } - // We ignore the other fields - - // We're actually not very good at handling this. In non-direct draw mode - // most of the time can be spent in the renderer which can skip any frame. - // In that case we'd rather the renderer handled things. - // Nevertheless we will keep an eye on it and if we really start getting - // a very long way behind then we will actually skip - but we'll still tell - // the renderer (or whoever is downstream) that they should handle quality. - - return E_FAIL; // Tell the renderer to do his thing. - -} - - - -// This will avoid several hundred useless warnings if compiled -W4 by MS VC++ v4 -#pragma warning(disable:4514) - diff --git a/third_party/BaseClasses/vtrans.h b/third_party/BaseClasses/vtrans.h deleted file mode 100644 index 49b1509b..00000000 --- a/third_party/BaseClasses/vtrans.h +++ /dev/null @@ -1,143 +0,0 @@ -//------------------------------------------------------------------------------ -// File: VTrans.h -// -// Desc: DirectShow base classes - defines a video transform class. -// -// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. -//------------------------------------------------------------------------------ - - -// This class is derived from CTransformFilter, but is specialised to handle -// the requirements of video quality control by frame dropping. -// This is a non-in-place transform, (i.e. it copies the data) such as a decoder. - -class CVideoTransformFilter : public CTransformFilter -{ - public: - - CVideoTransformFilter(__in_opt LPCTSTR, __inout_opt LPUNKNOWN, REFCLSID clsid); - ~CVideoTransformFilter(); - HRESULT EndFlush(); - - // ================================================================= - // ----- override these bits --------------------------------------- - // ================================================================= - // The following methods are in CTransformFilter which is inherited. - // They are mentioned here for completeness - // - // These MUST be supplied in a derived class - // - // NOTE: - // virtual HRESULT Transform(IMediaSample * pIn, IMediaSample *pOut); - // virtual HRESULT CheckInputType(const CMediaType* mtIn) PURE; - // virtual HRESULT CheckTransform - // (const CMediaType* mtIn, const CMediaType* mtOut) PURE; - // static CCOMObject * CreateInstance(LPUNKNOWN, HRESULT *); - // virtual HRESULT DecideBufferSize - // (IMemAllocator * pAllocator, ALLOCATOR_PROPERTIES *pprop) PURE; - // virtual HRESULT GetMediaType(int iPosition, CMediaType *pMediaType) PURE; - // - // These MAY also be overridden - // - // virtual HRESULT StopStreaming(); - // virtual HRESULT SetMediaType(PIN_DIRECTION direction,const CMediaType *pmt); - // virtual HRESULT CheckConnect(PIN_DIRECTION dir,IPin *pPin); - // virtual HRESULT BreakConnect(PIN_DIRECTION dir); - // virtual HRESULT CompleteConnect(PIN_DIRECTION direction,IPin *pReceivePin); - // virtual HRESULT EndOfStream(void); - // virtual HRESULT BeginFlush(void); - // virtual HRESULT EndFlush(void); - // virtual HRESULT NewSegment - // (REFERENCE_TIME tStart,REFERENCE_TIME tStop,double dRate); -#ifdef PERF - - // If you override this - ensure that you register all these ids - // as well as any of your own, - virtual void RegisterPerfId() { - m_idSkip = MSR_REGISTER(TEXT("Video Transform Skip frame")); - m_idFrameType = MSR_REGISTER(TEXT("Video transform frame type")); - m_idLate = MSR_REGISTER(TEXT("Video Transform Lateness")); - m_idTimeTillKey = MSR_REGISTER(TEXT("Video Transform Estd. time to next key")); - CTransformFilter::RegisterPerfId(); - } -#endif - - protected: - - // =========== QUALITY MANAGEMENT IMPLEMENTATION ======================== - // Frames are assumed to come in three types: - // Type 1: an AVI key frame or an MPEG I frame. - // This frame can be decoded with no history. - // Dropping this frame means that no further frame can be decoded - // until the next type 1 frame. - // Type 1 frames are sync points. - // Type 2: an AVI non-key frame or an MPEG P frame. - // This frame cannot be decoded unless the previous type 1 frame was - // decoded and all type 2 frames since have been decoded. - // Dropping this frame means that no further frame can be decoded - // until the next type 1 frame. - // Type 3: An MPEG B frame. - // This frame cannot be decoded unless the previous type 1 or 2 frame - // has been decoded AND the subsequent type 1 or 2 frame has also - // been decoded. (This requires decoding the frames out of sequence). - // Dropping this frame affects no other frames. This implementation - // does not allow for these. All non-sync-point frames are treated - // as being type 2. - // - // The spacing of frames of type 1 in a file is not guaranteed. There MUST - // be a type 1 frame at (well, near) the start of the file in order to start - // decoding at all. After that there could be one every half second or so, - // there could be one at the start of each scene (aka "cut", "shot") or - // there could be no more at all. - // If there is only a single type 1 frame then NO FRAMES CAN BE DROPPED - // without losing all the rest of the movie. There is no way to tell whether - // this is the case, so we find that we are in the gambling business. - // To try to improve the odds, we record the greatest interval between type 1s - // that we have seen and we bet on things being no worse than this in the - // future. - - // You can tell if it's a type 1 frame by calling IsSyncPoint(). - // there is no architected way to test for a type 3, so you should override - // the quality management here if you have B-frames. - - int m_nKeyFramePeriod; // the largest observed interval between type 1 frames - // 1 means every frame is type 1, 2 means every other. - - int m_nFramesSinceKeyFrame; // Used to count frames since the last type 1. - // becomes the new m_nKeyFramePeriod if greater. - - BOOL m_bSkipping; // we are skipping to the next type 1 frame - -#ifdef PERF - int m_idFrameType; // MSR id Frame type. 1=Key, 2="non-key" - int m_idSkip; // MSR id skipping - int m_idLate; // MSR id lateness - int m_idTimeTillKey; // MSR id for guessed time till next key frame. -#endif - - virtual HRESULT StartStreaming(); - - HRESULT AbortPlayback(HRESULT hr); // if something bad happens - - HRESULT Receive(IMediaSample *pSample); - - HRESULT AlterQuality(Quality q); - - BOOL ShouldSkipFrame(IMediaSample * pIn); - - int m_itrLate; // lateness from last Quality message - // (this overflows at 214 secs late). - int m_tDecodeStart; // timeGetTime when decode started. - int m_itrAvgDecode; // Average decode time in reference units. - - BOOL m_bNoSkip; // debug - no skipping. - - // We send an EC_QUALITY_CHANGE notification to the app if we have to degrade. - // We send one when we start degrading, not one for every frame, this means - // we track whether we've sent one yet. - BOOL m_bQualityChanged; - - // When non-zero, don't pass anything to renderer until next keyframe - // If there are few keys, give up and eventually draw something - int m_nWaitForKey; -}; diff --git a/third_party/BaseClasses/winctrl.cpp b/third_party/BaseClasses/winctrl.cpp deleted file mode 100644 index 4d1f52e3..00000000 --- a/third_party/BaseClasses/winctrl.cpp +++ /dev/null @@ -1,2081 +0,0 @@ -//------------------------------------------------------------------------------ -// File: WinCtrl.cpp -// -// Desc: DirectShow base classes - implements video control interface class. -// -// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. -//------------------------------------------------------------------------------ - - -#include -#include -#include - -// The control interface methods require us to be connected - -#define CheckConnected(pin,code) \ -{ \ - if (pin == NULL) { \ - ASSERT(!TEXT("Pin not set")); \ - } else if (pin->IsConnected() == FALSE) { \ - return (code); \ - } \ -} - -// This checks to see whether the window has a drain. An application can in -// most environments set the owner/parent of windows so that they appear in -// a compound document context (for example). In this case, the application -// would probably like to be told of any keyboard/mouse messages. Therefore -// we pass these messages on untranslated, returning TRUE if we're successful - -BOOL WINAPI PossiblyEatMessage(HWND hwndDrain, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - if (hwndDrain != NULL && !InSendMessage()) - { - switch (uMsg) - { - case WM_CHAR: - case WM_DEADCHAR: - case WM_KEYDOWN: - case WM_KEYUP: - case WM_LBUTTONDBLCLK: - case WM_LBUTTONDOWN: - case WM_LBUTTONUP: - case WM_MBUTTONDBLCLK: - case WM_MBUTTONDOWN: - case WM_MBUTTONUP: - case WM_MOUSEACTIVATE: - case WM_MOUSEMOVE: - // If we pass this on we don't get any mouse clicks - //case WM_NCHITTEST: - case WM_NCLBUTTONDBLCLK: - case WM_NCLBUTTONDOWN: - case WM_NCLBUTTONUP: - case WM_NCMBUTTONDBLCLK: - case WM_NCMBUTTONDOWN: - case WM_NCMBUTTONUP: - case WM_NCMOUSEMOVE: - case WM_NCRBUTTONDBLCLK: - case WM_NCRBUTTONDOWN: - case WM_NCRBUTTONUP: - case WM_RBUTTONDBLCLK: - case WM_RBUTTONDOWN: - case WM_RBUTTONUP: - case WM_SYSCHAR: - case WM_SYSDEADCHAR: - case WM_SYSKEYDOWN: - case WM_SYSKEYUP: - - DbgLog((LOG_TRACE, 2, TEXT("Forwarding %x to drain"))); - PostMessage(hwndDrain, uMsg, wParam, lParam); - - return TRUE; - } - } - return FALSE; -} - - -// This class implements the IVideoWindow control functions (dual interface) -// we support a large number of properties and methods designed to allow the -// client (whether it be an automation controller or a C/C++ application) to -// set and get a number of window related properties such as it's position. -// We also support some methods that duplicate the properties but provide a -// more direct and efficient mechanism as many values may be changed in one - -CBaseControlWindow::CBaseControlWindow( - __inout CBaseFilter *pFilter, // Owning filter - __in CCritSec *pInterfaceLock, // Locking object - __in_opt LPCTSTR pName, // Object description - __inout_opt LPUNKNOWN pUnk, // Normal COM ownership - __inout HRESULT *phr) : // OLE return code - - CBaseVideoWindow(pName,pUnk), - m_pInterfaceLock(pInterfaceLock), - m_hwndOwner(NULL), - m_hwndDrain(NULL), - m_bAutoShow(TRUE), - m_pFilter(pFilter), - m_bCursorHidden(FALSE), - m_pPin(NULL) -{ - ASSERT(m_pFilter); - ASSERT(m_pInterfaceLock); - ASSERT(phr); - m_BorderColour = VIDEO_COLOUR; -} - - -// Set the title caption on the base window, we don't do any field checking -// as we really don't care what title they intend to have. We can always get -// it back again later with GetWindowText. The only other complication is to -// do the necessary string conversions between ANSI and OLE Unicode strings - -STDMETHODIMP CBaseControlWindow::put_Caption(__in BSTR strCaption) -{ - CheckPointer((PVOID)strCaption,E_POINTER); - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); -#ifdef UNICODE - SetWindowText(m_hwnd, strCaption); -#else - CHAR Caption[CAPTION]; - - WideCharToMultiByte(CP_ACP,0,strCaption,-1,Caption,CAPTION,NULL,NULL); - SetWindowText(m_hwnd, Caption); -#endif - return NOERROR; -} - - -// Get the current base window title caption, once again we do no real field -// checking. We allocate a string for the window title to be filled in with -// which ensures the interface doesn't fiddle around with getting memory. A -// BSTR is a normal C string with the length at position (-1), we use the -// WriteBSTR helper function to create the caption to try and avoid OLE32 - -STDMETHODIMP CBaseControlWindow::get_Caption(__out BSTR *pstrCaption) -{ - CheckPointer(pstrCaption,E_POINTER); - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - WCHAR WideCaption[CAPTION]; - -#ifdef UNICODE - GetWindowText(m_hwnd,WideCaption,CAPTION); -#else - // Convert the ASCII caption to a UNICODE string - - TCHAR Caption[CAPTION]; - GetWindowText(m_hwnd,Caption,CAPTION); - MultiByteToWideChar(CP_ACP,0,Caption,-1,WideCaption,CAPTION); -#endif - return WriteBSTR(pstrCaption,WideCaption); -} - - -// Set the window style using GWL_EXSTYLE - -STDMETHODIMP CBaseControlWindow::put_WindowStyleEx(long WindowStyleEx) -{ - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - - // Should we be taking off WS_EX_TOPMOST - - if (GetWindowLong(m_hwnd,GWL_EXSTYLE) & WS_EX_TOPMOST) { - if ((WindowStyleEx & WS_EX_TOPMOST) == 0) { - SendMessage(m_hwnd,m_ShowStageTop,(WPARAM) FALSE,(LPARAM) 0); - } - } - - // Likewise should we be adding WS_EX_TOPMOST - - if (WindowStyleEx & WS_EX_TOPMOST) { - SendMessage(m_hwnd,m_ShowStageTop,(WPARAM) TRUE,(LPARAM) 0); - WindowStyleEx &= (~WS_EX_TOPMOST); - if (WindowStyleEx == 0) return NOERROR; - } - return DoSetWindowStyle(WindowStyleEx,GWL_EXSTYLE); -} - - -// Gets the current GWL_EXSTYLE base window style - -STDMETHODIMP CBaseControlWindow::get_WindowStyleEx(__out long *pWindowStyleEx) -{ - CheckPointer(pWindowStyleEx,E_POINTER); - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - return DoGetWindowStyle(pWindowStyleEx,GWL_EXSTYLE); -} - - -// Set the window style using GWL_STYLE - -STDMETHODIMP CBaseControlWindow::put_WindowStyle(long WindowStyle) -{ - // These styles cannot be changed dynamically - - if ((WindowStyle & WS_DISABLED) || - (WindowStyle & WS_ICONIC) || - (WindowStyle & WS_MAXIMIZE) || - (WindowStyle & WS_MINIMIZE) || - (WindowStyle & WS_HSCROLL) || - (WindowStyle & WS_VSCROLL)) { - - return E_INVALIDARG; - } - - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - return DoSetWindowStyle(WindowStyle,GWL_STYLE); -} - - -// Get the current GWL_STYLE base window style - -STDMETHODIMP CBaseControlWindow::get_WindowStyle(__out long *pWindowStyle) -{ - CheckPointer(pWindowStyle,E_POINTER); - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - return DoGetWindowStyle(pWindowStyle,GWL_STYLE); -} - - -// Change the base window style or the extended styles depending on whether -// WindowLong is GWL_STYLE or GWL_EXSTYLE. We must call SetWindowPos to have -// the window displayed in it's new style after the change which is a little -// tricky if the window is not currently visible as we realise it offscreen. -// In most cases the client will call get_WindowStyle before they call this -// and then AND and OR in extra bit settings according to the requirements - -HRESULT CBaseControlWindow::DoSetWindowStyle(long Style,long WindowLong) -{ - RECT WindowRect; - - // Get the window's visibility before setting the style - BOOL bVisible = IsWindowVisible(m_hwnd); - EXECUTE_ASSERT(GetWindowRect(m_hwnd,&WindowRect)); - - // Set the new style flags for the window - SetWindowLong(m_hwnd,WindowLong,Style); - UINT WindowFlags = SWP_SHOWWINDOW | SWP_FRAMECHANGED | SWP_NOACTIVATE; - WindowFlags |= SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE; - - // Show the window again in the current position - - if (bVisible == TRUE) { - - SetWindowPos(m_hwnd, // Base window handle - HWND_TOP, // Just a place holder - 0,0,0,0, // Leave size and position - WindowFlags); // Just draw it again - - return NOERROR; - } - - // Move the window offscreen so the user doesn't see the changes - - MoveWindow((HWND) m_hwnd, // Base window handle - GetSystemMetrics(SM_CXSCREEN), // Current desktop width - GetSystemMetrics(SM_CYSCREEN), // Likewise it's height - WIDTH(&WindowRect), // Use the same width - HEIGHT(&WindowRect), // Keep height same to - TRUE); // May as well repaint - - // Now show the previously hidden window - - SetWindowPos(m_hwnd, // Base window handle - HWND_TOP, // Just a place holder - 0,0,0,0, // Leave size and position - WindowFlags); // Just draw it again - - ShowWindow(m_hwnd,SW_HIDE); - - if (GetParent(m_hwnd)) { - - MapWindowPoints(HWND_DESKTOP, GetParent(m_hwnd), (LPPOINT)&WindowRect, 2); - } - - MoveWindow((HWND) m_hwnd, // Base window handle - WindowRect.left, // Existing x coordinate - WindowRect.top, // Existing y coordinate - WIDTH(&WindowRect), // Use the same width - HEIGHT(&WindowRect), // Keep height same to - TRUE); // May as well repaint - - return NOERROR; -} - - -// Get the current base window style (either GWL_STYLE or GWL_EXSTYLE) - -HRESULT CBaseControlWindow::DoGetWindowStyle(__out long *pStyle,long WindowLong) -{ - *pStyle = GetWindowLong(m_hwnd,WindowLong); - return NOERROR; -} - - -// Change the visibility of the base window, this takes the same parameters -// as the ShowWindow Win32 API does, so the client can have the window hidden -// or shown, minimised to an icon, or maximised to play in full screen mode -// We pass the request on to the base window to actually make the change - -STDMETHODIMP CBaseControlWindow::put_WindowState(long WindowState) -{ - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - DoShowWindow(WindowState); - return NOERROR; -} - - -// Get the current window state, this function returns a subset of the SW bit -// settings available in ShowWindow, if the window is visible then SW_SHOW is -// set, if it is hidden then the SW_HIDDEN is set, if it is either minimised -// or maximised then the SW_MINIMIZE or SW_MAXIMIZE is set respectively. The -// other SW bit settings are really set commands not readable output values - -STDMETHODIMP CBaseControlWindow::get_WindowState(__out long *pWindowState) -{ - CheckPointer(pWindowState,E_POINTER); - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - ASSERT(pWindowState); - *pWindowState = FALSE; - - // Is the window visible, a window is termed visible if it is somewhere on - // the current desktop even if it is completely obscured by other windows - // so the flag is a style for each window set with the WS_VISIBLE bit - - if (IsWindowVisible(m_hwnd) == TRUE) { - - // Is the base window iconic - if (IsIconic(m_hwnd) == TRUE) { - *pWindowState |= SW_MINIMIZE; - } - - // Has the window been maximised - else if (IsZoomed(m_hwnd) == TRUE) { - *pWindowState |= SW_MAXIMIZE; - } - - // Window is normal - else { - *pWindowState |= SW_SHOW; - } - - } else { - *pWindowState |= SW_HIDE; - } - return NOERROR; -} - - -// This makes sure that any palette we realise in the base window (through a -// media type or through the overlay interface) is done in the background and -// is therefore mapped to existing device entries rather than taking it over -// as it will do when we this window gets the keyboard focus. An application -// uses this to make sure it doesn't have it's palette removed by the window - -STDMETHODIMP CBaseControlWindow::put_BackgroundPalette(long BackgroundPalette) -{ - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - CAutoLock cWindowLock(&m_WindowLock); - - // Check this is a valid automation boolean type - - if (BackgroundPalette != OATRUE) { - if (BackgroundPalette != OAFALSE) { - return E_INVALIDARG; - } - } - - // Make sure the window realises any palette it has again - - m_bBackground = (BackgroundPalette == OATRUE ? TRUE : FALSE); - PostMessage(m_hwnd,m_RealizePalette,0,0); - PaintWindow(FALSE); - - return NOERROR; -} - - -// This returns the current background realisation setting - -STDMETHODIMP -CBaseControlWindow::get_BackgroundPalette(__out long *pBackgroundPalette) -{ - CheckPointer(pBackgroundPalette,E_POINTER); - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - CAutoLock cWindowLock(&m_WindowLock); - - // Get the current background palette setting - - *pBackgroundPalette = (m_bBackground == TRUE ? OATRUE : OAFALSE); - return NOERROR; -} - - -// Change the visibility of the base window - -STDMETHODIMP CBaseControlWindow::put_Visible(long Visible) -{ - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - - // Check this is a valid automation boolean type - - if (Visible != OATRUE) { - if (Visible != OAFALSE) { - return E_INVALIDARG; - } - } - - // Convert the boolean visibility into SW_SHOW and SW_HIDE - - INT Mode = (Visible == OATRUE ? SW_SHOWNORMAL : SW_HIDE); - DoShowWindow(Mode); - return NOERROR; -} - - -// Return OATRUE if the window is currently visible otherwise OAFALSE - -STDMETHODIMP CBaseControlWindow::get_Visible(__out long *pVisible) -{ - CheckPointer(pVisible,E_POINTER); - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - - // See if the base window has a WS_VISIBLE style - this will return TRUE - // even if the window is completely obscured by other desktop windows, we - // return FALSE if the window is not showing because of earlier calls - - BOOL Mode = IsWindowVisible(m_hwnd); - *pVisible = (Mode == TRUE ? OATRUE : OAFALSE); - return NOERROR; -} - - -// Change the left position of the base window. This keeps the window width -// and height properties the same so it effectively shunts the window left or -// right accordingly - there is the Width property to change that dimension - -STDMETHODIMP CBaseControlWindow::put_Left(long Left) -{ - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - BOOL bSuccess; - RECT WindowRect; - - // Get the current window position in a RECT - EXECUTE_ASSERT(GetWindowRect(m_hwnd,&WindowRect)); - - if (GetParent(m_hwnd)) { - - MapWindowPoints(HWND_DESKTOP, GetParent(m_hwnd), (LPPOINT)&WindowRect, 2); - } - - // Adjust the coordinates ready for SetWindowPos, the window rectangle we - // get back from GetWindowRect is in left,top,right and bottom while the - // coordinates SetWindowPos wants are left,top,width and height values - - WindowRect.bottom = WindowRect.bottom - WindowRect.top; - WindowRect.right = WindowRect.right - WindowRect.left; - UINT WindowFlags = SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOACTIVATE; - - bSuccess = SetWindowPos(m_hwnd, // Window handle - HWND_TOP, // Put it at the top - Left, // New left position - WindowRect.top, // Leave top alone - WindowRect.right, // The WIDTH (not right) - WindowRect.bottom, // The HEIGHT (not bottom) - WindowFlags); // Show window options - - if (bSuccess == FALSE) { - return E_INVALIDARG; - } - return NOERROR; -} - - -// Return the current base window left position - -STDMETHODIMP CBaseControlWindow::get_Left(__out long *pLeft) -{ - CheckPointer(pLeft,E_POINTER); - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - RECT WindowRect; - - EXECUTE_ASSERT(GetWindowRect(m_hwnd,&WindowRect)); - *pLeft = WindowRect.left; - return NOERROR; -} - - -// Change the current width of the base window. This property complements the -// left position property so we must keep the left edge constant and expand or -// contract to the right, the alternative would be to change the left edge so -// keeping the right edge constant but this is maybe a little more intuitive - -STDMETHODIMP CBaseControlWindow::put_Width(long Width) -{ - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - BOOL bSuccess; - RECT WindowRect; - - // Adjust the coordinates ready for SetWindowPos, the window rectangle we - // get back from GetWindowRect is in left,top,right and bottom while the - // coordinates SetWindowPos wants are left,top,width and height values - - EXECUTE_ASSERT(GetWindowRect(m_hwnd,&WindowRect)); - - if (GetParent(m_hwnd)) { - - MapWindowPoints(HWND_DESKTOP, GetParent(m_hwnd), (LPPOINT)&WindowRect, 2); - } - - WindowRect.bottom = WindowRect.bottom - WindowRect.top; - UINT WindowFlags = SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOACTIVATE; - - // This seems to have a bug in that calling SetWindowPos on a window with - // just the width changing causes it to ignore the width that you pass in - // and sets it to a mimimum value of 110 pixels wide (Windows NT 3.51) - - bSuccess = SetWindowPos(m_hwnd, // Window handle - HWND_TOP, // Put it at the top - WindowRect.left, // Leave left alone - WindowRect.top, // Leave top alone - Width, // New WIDTH dimension - WindowRect.bottom, // The HEIGHT (not bottom) - WindowFlags); // Show window options - - if (bSuccess == FALSE) { - return E_INVALIDARG; - } - return NOERROR; -} - - -// Return the current base window width - -STDMETHODIMP CBaseControlWindow::get_Width(__out long *pWidth) -{ - CheckPointer(pWidth,E_POINTER); - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - RECT WindowRect; - - EXECUTE_ASSERT(GetWindowRect(m_hwnd,&WindowRect)); - *pWidth = WindowRect.right - WindowRect.left; - return NOERROR; -} - - -// This allows the client program to change the top position for the window in -// the same way that changing the left position does not affect the width of -// the image so changing the top position does not affect the window height - -STDMETHODIMP CBaseControlWindow::put_Top(long Top) -{ - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - BOOL bSuccess; - RECT WindowRect; - - // Get the current window position in a RECT - EXECUTE_ASSERT(GetWindowRect(m_hwnd,&WindowRect)); - - if (GetParent(m_hwnd)) { - - MapWindowPoints(HWND_DESKTOP, GetParent(m_hwnd), (LPPOINT)&WindowRect, 2); - } - - // Adjust the coordinates ready for SetWindowPos, the window rectangle we - // get back from GetWindowRect is in left,top,right and bottom while the - // coordinates SetWindowPos wants are left,top,width and height values - - WindowRect.bottom = WindowRect.bottom - WindowRect.top; - WindowRect.right = WindowRect.right - WindowRect.left; - UINT WindowFlags = SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOACTIVATE; - - bSuccess = SetWindowPos(m_hwnd, // Window handle - HWND_TOP, // Put it at the top - WindowRect.left, // Leave left alone - Top, // New top position - WindowRect.right, // The WIDTH (not right) - WindowRect.bottom, // The HEIGHT (not bottom) - WindowFlags); // Show window flags - - if (bSuccess == FALSE) { - return E_INVALIDARG; - } - return NOERROR; -} - - -// Return the current base window top position - -STDMETHODIMP CBaseControlWindow::get_Top(long *pTop) -{ - CheckPointer(pTop,E_POINTER); - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - RECT WindowRect; - - EXECUTE_ASSERT(GetWindowRect(m_hwnd,&WindowRect)); - *pTop = WindowRect.top; - return NOERROR; -} - - -// Change the height of the window, this complements the top property so when -// we change this we must keep the top position for the base window, as said -// before we could keep the bottom and grow upwards although this is perhaps -// a little more intuitive since we already have a top position property - -STDMETHODIMP CBaseControlWindow::put_Height(long Height) -{ - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - BOOL bSuccess; - RECT WindowRect; - - // Adjust the coordinates ready for SetWindowPos, the window rectangle we - // get back from GetWindowRect is in left,top,right and bottom while the - // coordinates SetWindowPos wants are left,top,width and height values - - EXECUTE_ASSERT(GetWindowRect(m_hwnd,&WindowRect)); - - if (GetParent(m_hwnd)) { - - MapWindowPoints(HWND_DESKTOP, GetParent(m_hwnd), (LPPOINT)&WindowRect, 2); - } - - WindowRect.right = WindowRect.right - WindowRect.left; - UINT WindowFlags = SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOACTIVATE; - - bSuccess = SetWindowPos(m_hwnd, // Window handle - HWND_TOP, // Put it at the top - WindowRect.left, // Leave left alone - WindowRect.top, // Leave top alone - WindowRect.right, // The WIDTH (not right) - Height, // New height dimension - WindowFlags); // Show window flags - - if (bSuccess == FALSE) { - return E_INVALIDARG; - } - return NOERROR; -} - - -// Return the current base window height - -STDMETHODIMP CBaseControlWindow::get_Height(__out long *pHeight) -{ - CheckPointer(pHeight,E_POINTER); - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - RECT WindowRect; - - EXECUTE_ASSERT(GetWindowRect(m_hwnd,&WindowRect)); - *pHeight = WindowRect.bottom - WindowRect.top; - return NOERROR; -} - - -// This can be called to change the owning window. Setting the owner is done -// through this function, however to make the window a true child window the -// style must also be set to WS_CHILD. After resetting the owner to NULL an -// application should also set the style to WS_OVERLAPPED | WS_CLIPCHILDREN. - -// We cannot lock the object here because the SetParent causes an interthread -// SendMessage to the owner window. If they are in GetState we will sit here -// incomplete with the critical section locked therefore blocking out source -// filter threads from accessing us. Because the source thread can't enter us -// it can't get buffers or call EndOfStream so the GetState will not complete - -STDMETHODIMP CBaseControlWindow::put_Owner(OAHWND Owner) -{ - // Check we are connected otherwise reject the call - - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - m_hwndOwner = (HWND) Owner; - HWND hwndParent = m_hwndOwner; - - // Add or remove WS_CHILD as appropriate - - LONG Style = GetWindowLong(m_hwnd,GWL_STYLE); - if (Owner == NULL) { - Style &= (~WS_CHILD); - } else { - Style |= (WS_CHILD); - } - SetWindowLong(m_hwnd,GWL_STYLE,Style); - - // Don't call this with the filter locked - - SetParent(m_hwnd,hwndParent); - - PaintWindow(TRUE); - NOTE1("Changed parent %lx",hwndParent); - - return NOERROR; -} - - -// This complements the put_Owner to get the current owning window property -// we always return NOERROR although the returned window handle may be NULL -// to indicate no owning window (the desktop window doesn't qualify as one) -// If an application sets the owner we call SetParent, however that returns -// NULL until the WS_CHILD bit is set on, so we store the owner internally - -STDMETHODIMP CBaseControlWindow::get_Owner(__out OAHWND *Owner) -{ - CheckPointer(Owner,E_POINTER); - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - *Owner = (OAHWND) m_hwndOwner; - return NOERROR; -} - - -// And renderer supporting IVideoWindow may have an HWND set who will get any -// keyboard and mouse messages we receive posted on to them. This is separate -// from setting an owning window. By separating the two, applications may get -// messages sent on even when they have set no owner (perhaps it's maximised) - -STDMETHODIMP CBaseControlWindow::put_MessageDrain(OAHWND Drain) -{ - // Check we are connected otherwise reject the call - - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - m_hwndDrain = (HWND) Drain; - return NOERROR; -} - - -// Return the current message drain - -STDMETHODIMP CBaseControlWindow::get_MessageDrain(__out OAHWND *Drain) -{ - CheckPointer(Drain,E_POINTER); - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - *Drain = (OAHWND) m_hwndDrain; - return NOERROR; -} - - -// This is called by the filter graph to inform us of a message we should know -// is being sent to our owning window. We have this because as a child window -// we do not get certain messages that are only sent to top level windows. We -// must see the palette changed/changing/query messages so that we know if we -// have the foreground palette or not. We pass the message on to our window -// using SendMessage - this will cause an interthread send message to occur - -STDMETHODIMP -CBaseControlWindow::NotifyOwnerMessage(OAHWND hwnd, // Window handle - long uMsg, // Message ID - LONG_PTR wParam, // Parameters - LONG_PTR lParam) // for message -{ - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - - // Only interested in these Windows messages - - switch (uMsg) { - - case WM_SYSCOLORCHANGE: - case WM_PALETTECHANGED: - case WM_PALETTEISCHANGING: - case WM_QUERYNEWPALETTE: - case WM_DEVMODECHANGE: - case WM_DISPLAYCHANGE: - case WM_ACTIVATEAPP: - - // If we do not have an owner then ignore - - if (m_hwndOwner == NULL) { - return NOERROR; - } - SendMessage(m_hwnd,uMsg,(WPARAM)wParam,(LPARAM)lParam); - break; - - // do NOT fwd WM_MOVE. the parameters are the location of the parent - // window, NOT what the renderer should be looking at. But we need - // to make sure the overlay is moved with the parent window, so we - // do this. - case WM_MOVE: - PostMessage(m_hwnd,WM_PAINT,0,0); - break; - } - return NOERROR; -} - - -// Allow an application to have us set the base window in the foreground. We -// have this because it is difficult for one thread to do do this to a window -// owned by another thread. We ask the base window class to do the real work - -STDMETHODIMP CBaseControlWindow::SetWindowForeground(long Focus) -{ - // Check this is a valid automation boolean type - - if (Focus != OATRUE) { - if (Focus != OAFALSE) { - return E_INVALIDARG; - } - } - - // We shouldn't lock as this sends a message - - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - BOOL bFocus = (Focus == OATRUE ? TRUE : FALSE); - DoSetWindowForeground(bFocus); - - return NOERROR; -} - - -// This allows a client to set the complete window size and position in one -// atomic operation. The same affect can be had by changing each dimension -// in turn through their individual properties although some flashing will -// occur as each of them gets updated (they are better set at design time) - -STDMETHODIMP -CBaseControlWindow::SetWindowPosition(long Left,long Top,long Width,long Height) -{ - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - BOOL bSuccess; - - // Set the new size and position - UINT WindowFlags = SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOACTIVATE; - - ASSERT(IsWindow(m_hwnd)); - bSuccess = SetWindowPos(m_hwnd, // Window handle - HWND_TOP, // Put it at the top - Left, // Left position - Top, // Top position - Width, // Window width - Height, // Window height - WindowFlags); // Show window flags - ASSERT(bSuccess); -#ifdef DEBUG - DbgLog((LOG_TRACE, 1, TEXT("SWP failed error %d"), GetLastError())); -#endif - if (bSuccess == FALSE) { - return E_INVALIDARG; - } - return NOERROR; -} - - -// This complements the SetWindowPosition to return the current window place -// in device coordinates. As before the same information can be retrived by -// calling the property get functions individually but this is atomic and is -// therefore more suitable to a live environment rather than design time - -STDMETHODIMP -CBaseControlWindow::GetWindowPosition(__out long *pLeft,__out long *pTop,__out long *pWidth,__out long *pHeight) -{ - // Should check the pointers are not NULL - - CheckPointer(pLeft,E_POINTER); - CheckPointer(pTop,E_POINTER); - CheckPointer(pWidth,E_POINTER); - CheckPointer(pHeight,E_POINTER); - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - RECT WindowRect; - - // Get the current window coordinates - - EXECUTE_ASSERT(GetWindowRect(m_hwnd,&WindowRect)); - - // Convert the RECT into left,top,width and height values - - *pLeft = WindowRect.left; - *pTop = WindowRect.top; - *pWidth = WindowRect.right - WindowRect.left; - *pHeight = WindowRect.bottom - WindowRect.top; - - return NOERROR; -} - - -// When a window is maximised or iconic calling GetWindowPosition will return -// the current window position (likewise for the properties). However if the -// restored size (ie the size we'll return to when normally shown) is needed -// then this should be used. When in a normal position (neither iconic nor -// maximised) then this returns the same coordinates as GetWindowPosition - -STDMETHODIMP -CBaseControlWindow::GetRestorePosition(__out long *pLeft,__out long *pTop,__out long *pWidth,__out long *pHeight) -{ - // Should check the pointers are not NULL - - CheckPointer(pLeft,E_POINTER); - CheckPointer(pTop,E_POINTER); - CheckPointer(pWidth,E_POINTER); - CheckPointer(pHeight,E_POINTER); - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - - // Use GetWindowPlacement to find the restore position - - WINDOWPLACEMENT Place; - Place.length = sizeof(WINDOWPLACEMENT); - EXECUTE_ASSERT(GetWindowPlacement(m_hwnd,&Place)); - - RECT WorkArea; - - // We must take into account any task bar present - - if (SystemParametersInfo(SPI_GETWORKAREA,0,&WorkArea,FALSE) == TRUE) { - if (GetParent(m_hwnd) == NULL) { - Place.rcNormalPosition.top += WorkArea.top; - Place.rcNormalPosition.bottom += WorkArea.top; - Place.rcNormalPosition.left += WorkArea.left; - Place.rcNormalPosition.right += WorkArea.left; - } - } - - // Convert the RECT into left,top,width and height values - - *pLeft = Place.rcNormalPosition.left; - *pTop = Place.rcNormalPosition.top; - *pWidth = Place.rcNormalPosition.right - Place.rcNormalPosition.left; - *pHeight = Place.rcNormalPosition.bottom - Place.rcNormalPosition.top; - - return NOERROR; -} - - -// Return the current border colour, if we are playing something to a subset -// of the base window display there is an outside area exposed. The default -// action is to paint this colour in the Windows background colour (defined -// as value COLOR_WINDOW) We reset to this default when we're disconnected - -STDMETHODIMP CBaseControlWindow::get_BorderColor(__out long *Color) -{ - CheckPointer(Color,E_POINTER); - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - *Color = (long) m_BorderColour; - return NOERROR; -} - - -// This can be called to set the current border colour - -STDMETHODIMP CBaseControlWindow::put_BorderColor(long Color) -{ - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - - // Have the window repainted with the new border colour - - m_BorderColour = (COLORREF) Color; - PaintWindow(TRUE); - return NOERROR; -} - - -// Delegate fullscreen handling to plug in distributor - -STDMETHODIMP CBaseControlWindow::get_FullScreenMode(__out long *FullScreenMode) -{ - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - CheckPointer(FullScreenMode,E_POINTER); - return E_NOTIMPL; -} - - -// Delegate fullscreen handling to plug in distributor - -STDMETHODIMP CBaseControlWindow::put_FullScreenMode(long FullScreenMode) -{ - return E_NOTIMPL; -} - - -// This sets the auto show property, this property causes the base window to -// be displayed whenever we change state. This allows an application to have -// to do nothing to have the window appear but still allow them to change the -// default behaviour if for example they want to keep it hidden for longer - -STDMETHODIMP CBaseControlWindow::put_AutoShow(long AutoShow) -{ - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - - // Check this is a valid automation boolean type - - if (AutoShow != OATRUE) { - if (AutoShow != OAFALSE) { - return E_INVALIDARG; - } - } - - m_bAutoShow = (AutoShow == OATRUE ? TRUE : FALSE); - return NOERROR; -} - - -// This can be called to get the current auto show flag. The flag is updated -// when we connect and disconnect and through this interface all of which are -// controlled and serialised by means of the main renderer critical section - -STDMETHODIMP CBaseControlWindow::get_AutoShow(__out long *AutoShow) -{ - CheckPointer(AutoShow,E_POINTER); - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - *AutoShow = (m_bAutoShow == TRUE ? OATRUE : OAFALSE); - return NOERROR; -} - - -// Return the minimum ideal image size for the current video. This may differ -// to the actual video dimensions because we may be using DirectDraw hardware -// that has specific stretching requirements. For example the Cirrus Logic -// cards have a minimum stretch factor depending on the overlay surface size - -STDMETHODIMP -CBaseControlWindow::GetMinIdealImageSize(__out long *pWidth,__out long *pHeight) -{ - CheckPointer(pWidth,E_POINTER); - CheckPointer(pHeight,E_POINTER); - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - FILTER_STATE State; - - // Must not be stopped for this to work correctly - - m_pFilter->GetState(0,&State); - if (State == State_Stopped) { - return VFW_E_WRONG_STATE; - } - - RECT DefaultRect = GetDefaultRect(); - *pWidth = WIDTH(&DefaultRect); - *pHeight = HEIGHT(&DefaultRect); - return NOERROR; -} - - -// Return the maximum ideal image size for the current video. This may differ -// to the actual video dimensions because we may be using DirectDraw hardware -// that has specific stretching requirements. For example the Cirrus Logic -// cards have a maximum stretch factor depending on the overlay surface size - -STDMETHODIMP -CBaseControlWindow::GetMaxIdealImageSize(__out long *pWidth,__out long *pHeight) -{ - CheckPointer(pWidth,E_POINTER); - CheckPointer(pHeight,E_POINTER); - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - FILTER_STATE State; - - // Must not be stopped for this to work correctly - - m_pFilter->GetState(0,&State); - if (State == State_Stopped) { - return VFW_E_WRONG_STATE; - } - - RECT DefaultRect = GetDefaultRect(); - *pWidth = WIDTH(&DefaultRect); - *pHeight = HEIGHT(&DefaultRect); - return NOERROR; -} - - -// Allow an application to hide the cursor on our window - -STDMETHODIMP -CBaseControlWindow::HideCursor(long HideCursor) -{ - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - - // Check this is a valid automation boolean type - - if (HideCursor != OATRUE) { - if (HideCursor != OAFALSE) { - return E_INVALIDARG; - } - } - - m_bCursorHidden = (HideCursor == OATRUE ? TRUE : FALSE); - return NOERROR; -} - - -// Returns whether we have the cursor hidden or not - -STDMETHODIMP CBaseControlWindow::IsCursorHidden(__out long *CursorHidden) -{ - CheckPointer(CursorHidden,E_POINTER); - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - *CursorHidden = (m_bCursorHidden == TRUE ? OATRUE : OAFALSE); - return NOERROR; -} - - -// This class implements the IBasicVideo control functions (dual interface) -// we support a large number of properties and methods designed to allow the -// client (whether it be an automation controller or a C/C++ application) to -// set and get a number of video related properties such as the native video -// size. We support some methods that duplicate the properties but provide a -// more direct and efficient mechanism as many values may be changed in one - -CBaseControlVideo::CBaseControlVideo( - __inout CBaseFilter *pFilter, // Owning filter - __in CCritSec *pInterfaceLock, // Locking object - __in_opt LPCTSTR pName, // Object description - __inout_opt LPUNKNOWN pUnk, // Normal COM ownership - __inout HRESULT *phr) : // OLE return code - - CBaseBasicVideo(pName,pUnk), - m_pFilter(pFilter), - m_pInterfaceLock(pInterfaceLock), - m_pPin(NULL) -{ - ASSERT(m_pFilter); - ASSERT(m_pInterfaceLock); - ASSERT(phr); -} - -// Return an approximate average time per frame - -STDMETHODIMP CBaseControlVideo::get_AvgTimePerFrame(__out REFTIME *pAvgTimePerFrame) -{ - CheckPointer(pAvgTimePerFrame,E_POINTER); - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - CAutoLock cInterfaceLock(m_pInterfaceLock); - - VIDEOINFOHEADER *pVideoInfo = GetVideoFormat(); - if (pVideoInfo == NULL) - return E_OUTOFMEMORY; - COARefTime AvgTime(pVideoInfo->AvgTimePerFrame); - *pAvgTimePerFrame = (REFTIME) AvgTime; - - return NOERROR; -} - - -// Return an approximate bit rate for the video - -STDMETHODIMP CBaseControlVideo::get_BitRate(__out long *pBitRate) -{ - CheckPointer(pBitRate,E_POINTER); - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - CAutoLock cInterfaceLock(m_pInterfaceLock); - - VIDEOINFOHEADER *pVideoInfo = GetVideoFormat(); - if (pVideoInfo == NULL) - return E_OUTOFMEMORY; - *pBitRate = pVideoInfo->dwBitRate; - return NOERROR; -} - - -// Return an approximate bit error rate - -STDMETHODIMP CBaseControlVideo::get_BitErrorRate(__out long *pBitErrorRate) -{ - CheckPointer(pBitErrorRate,E_POINTER); - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - CAutoLock cInterfaceLock(m_pInterfaceLock); - - VIDEOINFOHEADER *pVideoInfo = GetVideoFormat(); - if (pVideoInfo == NULL) - return E_OUTOFMEMORY; - *pBitErrorRate = pVideoInfo->dwBitErrorRate; - return NOERROR; -} - - -// This returns the current video width - -STDMETHODIMP CBaseControlVideo::get_VideoWidth(__out long *pVideoWidth) -{ - CheckPointer(pVideoWidth,E_POINTER); - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - CAutoLock cInterfaceLock(m_pInterfaceLock); - - VIDEOINFOHEADER *pVideoInfo = GetVideoFormat(); - if (pVideoInfo == NULL) - return E_OUTOFMEMORY; - *pVideoWidth = pVideoInfo->bmiHeader.biWidth; - return NOERROR; -} - - -// This returns the current video height - -STDMETHODIMP CBaseControlVideo::get_VideoHeight(__out long *pVideoHeight) -{ - CheckPointer(pVideoHeight,E_POINTER); - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - CAutoLock cInterfaceLock(m_pInterfaceLock); - - VIDEOINFOHEADER *pVideoInfo = GetVideoFormat(); - if (pVideoInfo == NULL) - return E_OUTOFMEMORY; - *pVideoHeight = pVideoInfo->bmiHeader.biHeight; - return NOERROR; -} - - -// This returns the current palette the video is using as an array allocated -// by the user. To remain consistent we use PALETTEENTRY fields to return the -// colours in rather than RGBQUADs that multimedia decided to use. The memory -// is allocated by the user so we simple copy each in turn. We check that the -// number of entries requested and the start position offset are both valid -// If the number of entries evaluates to zero then we return an S_FALSE code - -STDMETHODIMP CBaseControlVideo::GetVideoPaletteEntries(long StartIndex, - long Entries, - __out long *pRetrieved, - __out_ecount_part(Entries, *pRetrieved) long *pPalette) -{ - CheckPointer(pRetrieved,E_POINTER); - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - CAutoLock cInterfaceLock(m_pInterfaceLock); - CMediaType MediaType; - - // Get the video format from the derived class - - VIDEOINFOHEADER *pVideoInfo = GetVideoFormat(); - if (pVideoInfo == NULL) - return E_OUTOFMEMORY; - BITMAPINFOHEADER *pHeader = HEADER(pVideoInfo); - - // Is the current format palettised - - if (PALETTISED(pVideoInfo) == FALSE) { - *pRetrieved = 0; - return VFW_E_NO_PALETTE_AVAILABLE; - } - - // Do they just want to know how many are available - - if (pPalette == NULL) { - *pRetrieved = pHeader->biClrUsed; - return NOERROR; - } - - // Make sure the start position is a valid offset - - if (StartIndex >= (LONG) pHeader->biClrUsed || StartIndex < 0) { - *pRetrieved = 0; - return E_INVALIDARG; - } - - // Correct the number we can retrieve - - LONG Available = (LONG) pHeader->biClrUsed - StartIndex; - *pRetrieved = max(0,min(Available,Entries)); - if (*pRetrieved == 0) { - return S_FALSE; - } - - // Copy the palette entries to the output buffer - - PALETTEENTRY *pEntries = (PALETTEENTRY *) pPalette; - RGBQUAD *pColours = COLORS(pVideoInfo) + StartIndex; - - for (LONG Count = 0;Count < *pRetrieved;Count++) { - pEntries[Count].peRed = pColours[Count].rgbRed; - pEntries[Count].peGreen = pColours[Count].rgbGreen; - pEntries[Count].peBlue = pColours[Count].rgbBlue; - pEntries[Count].peFlags = 0; - } - return NOERROR; -} - - -// This returns the current video dimensions as a method rather than a number -// of individual property get calls. For the same reasons as said before we -// cannot access the renderer media type directly as the window object thread -// may be updating it since dynamic format changes may change these values - -STDMETHODIMP CBaseControlVideo::GetVideoSize(__out long *pWidth,__out long *pHeight) -{ - CheckPointer(pWidth,E_POINTER); - CheckPointer(pHeight,E_POINTER); - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - CAutoLock cInterfaceLock(m_pInterfaceLock); - - // Get the video format from the derived class - VIDEOINFOHEADER *pVideoInfo = GetVideoFormat(); - if (pVideoInfo == NULL) - return E_OUTOFMEMORY; - *pWidth = pVideoInfo->bmiHeader.biWidth; - *pHeight = pVideoInfo->bmiHeader.biHeight; - return NOERROR; -} - - -// Set the source video rectangle as left,top,right and bottom coordinates -// rather than left,top,width and height as per OLE automation interfaces -// Then pass the rectangle on to the window object to set the source - -STDMETHODIMP -CBaseControlVideo::SetSourcePosition(long Left,long Top,long Width,long Height) -{ - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - CAutoLock cInterfaceLock(m_pInterfaceLock); - RECT SourceRect; - SourceRect.left = Left; - SourceRect.top = Top; - SourceRect.right = Left + Width; - SourceRect.bottom = Top + Height; - - // Check the source rectangle is valid - - HRESULT hr = CheckSourceRect(&SourceRect); - if (FAILED(hr)) { - return hr; - } - - // Now set the source rectangle - - hr = SetSourceRect(&SourceRect); - if (FAILED(hr)) { - return hr; - } - return OnUpdateRectangles(); -} - - -// Return the source rectangle in left,top,width and height rather than the -// left,top,right and bottom values that RECT uses (and which the window -// object returns through GetSourceRect) which requires a little work - -STDMETHODIMP -CBaseControlVideo::GetSourcePosition(__out long *pLeft,__out long *pTop,__out long *pWidth,__out long *pHeight) -{ - // Should check the pointers are non NULL - - CheckPointer(pLeft,E_POINTER); - CheckPointer(pTop,E_POINTER); - CheckPointer(pWidth,E_POINTER); - CheckPointer(pHeight,E_POINTER); - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - RECT SourceRect; - - CAutoLock cInterfaceLock(m_pInterfaceLock); - GetSourceRect(&SourceRect); - - *pLeft = SourceRect.left; - *pTop = SourceRect.top; - *pWidth = WIDTH(&SourceRect); - *pHeight = HEIGHT(&SourceRect); - - return NOERROR; -} - - -// Set the video destination as left,top,right and bottom coordinates rather -// than the left,top,width and height uses as per OLE automation interfaces -// Then pass the rectangle on to the window object to set the destination - -STDMETHODIMP -CBaseControlVideo::SetDestinationPosition(long Left,long Top,long Width,long Height) -{ - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - CAutoLock cInterfaceLock(m_pInterfaceLock); - RECT DestinationRect; - - DestinationRect.left = Left; - DestinationRect.top = Top; - DestinationRect.right = Left + Width; - DestinationRect.bottom = Top + Height; - - // Check the target rectangle is valid - - HRESULT hr = CheckTargetRect(&DestinationRect); - if (FAILED(hr)) { - return hr; - } - - // Now set the new target rectangle - - hr = SetTargetRect(&DestinationRect); - if (FAILED(hr)) { - return hr; - } - return OnUpdateRectangles(); -} - - -// Return the destination rectangle in left,top,width and height rather than -// the left,top,right and bottom values that RECT uses (and which the window -// object returns through GetDestinationRect) which requires a little work - -STDMETHODIMP -CBaseControlVideo::GetDestinationPosition(__out long *pLeft,__out long *pTop,__out long *pWidth,__out long *pHeight) -{ - // Should check the pointers are not NULL - - CheckPointer(pLeft,E_POINTER); - CheckPointer(pTop,E_POINTER); - CheckPointer(pWidth,E_POINTER); - CheckPointer(pHeight,E_POINTER); - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - RECT DestinationRect; - - CAutoLock cInterfaceLock(m_pInterfaceLock); - GetTargetRect(&DestinationRect); - - *pLeft = DestinationRect.left; - *pTop = DestinationRect.top; - *pWidth = WIDTH(&DestinationRect); - *pHeight = HEIGHT(&DestinationRect); - - return NOERROR; -} - - -// Set the source left position, the source rectangle we get back from the -// window object is a true rectangle in left,top,right and bottom positions -// so all we have to do is to update the left position and pass it back. We -// must keep the current width constant when we're updating this property - -STDMETHODIMP CBaseControlVideo::put_SourceLeft(long SourceLeft) -{ - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - CAutoLock cInterfaceLock(m_pInterfaceLock); - RECT SourceRect; - GetSourceRect(&SourceRect); - SourceRect.right = SourceLeft + WIDTH(&SourceRect); - SourceRect.left = SourceLeft; - - // Check the source rectangle is valid - - HRESULT hr = CheckSourceRect(&SourceRect); - if (FAILED(hr)) { - return hr; - } - - // Now set the source rectangle - - hr = SetSourceRect(&SourceRect); - if (FAILED(hr)) { - return hr; - } - return OnUpdateRectangles(); -} - - -// Return the current left source video position - -STDMETHODIMP CBaseControlVideo::get_SourceLeft(__out long *pSourceLeft) -{ - CheckPointer(pSourceLeft,E_POINTER); - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - CAutoLock cInterfaceLock(m_pInterfaceLock); - RECT SourceRect; - - GetSourceRect(&SourceRect); - *pSourceLeft = SourceRect.left; - return NOERROR; -} - - -// Set the source width, we get the current source rectangle and then update -// the right position to be the left position (thereby keeping it constant) -// plus the new source width we are passed in (it expands to the right) - -STDMETHODIMP CBaseControlVideo::put_SourceWidth(long SourceWidth) -{ - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - CAutoLock cInterfaceLock(m_pInterfaceLock); - RECT SourceRect; - GetSourceRect(&SourceRect); - SourceRect.right = SourceRect.left + SourceWidth; - - // Check the source rectangle is valid - - HRESULT hr = CheckSourceRect(&SourceRect); - if (FAILED(hr)) { - return hr; - } - - // Now set the source rectangle - - hr = SetSourceRect(&SourceRect); - if (FAILED(hr)) { - return hr; - } - return OnUpdateRectangles(); -} - - -// Return the current source width - -STDMETHODIMP CBaseControlVideo::get_SourceWidth(__out long *pSourceWidth) -{ - CheckPointer(pSourceWidth,E_POINTER); - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - CAutoLock cInterfaceLock(m_pInterfaceLock); - RECT SourceRect; - - GetSourceRect(&SourceRect); - *pSourceWidth = WIDTH(&SourceRect); - return NOERROR; -} - - -// Set the source top position - changing this property does not affect the -// current source height. So changing this shunts the source rectangle up and -// down appropriately. Changing the height complements this functionality by -// keeping the top position constant and simply changing the source height - -STDMETHODIMP CBaseControlVideo::put_SourceTop(long SourceTop) -{ - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - CAutoLock cInterfaceLock(m_pInterfaceLock); - RECT SourceRect; - GetSourceRect(&SourceRect); - SourceRect.bottom = SourceTop + HEIGHT(&SourceRect); - SourceRect.top = SourceTop; - - // Check the source rectangle is valid - - HRESULT hr = CheckSourceRect(&SourceRect); - if (FAILED(hr)) { - return hr; - } - - // Now set the source rectangle - - hr = SetSourceRect(&SourceRect); - if (FAILED(hr)) { - return hr; - } - return OnUpdateRectangles(); -} - - -// Return the current top position - -STDMETHODIMP CBaseControlVideo::get_SourceTop(__out long *pSourceTop) -{ - CheckPointer(pSourceTop,E_POINTER); - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - CAutoLock cInterfaceLock(m_pInterfaceLock); - RECT SourceRect; - - GetSourceRect(&SourceRect); - *pSourceTop = SourceRect.top; - return NOERROR; -} - - -// Set the source height - -STDMETHODIMP CBaseControlVideo::put_SourceHeight(long SourceHeight) -{ - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - CAutoLock cInterfaceLock(m_pInterfaceLock); - RECT SourceRect; - GetSourceRect(&SourceRect); - SourceRect.bottom = SourceRect.top + SourceHeight; - - // Check the source rectangle is valid - - HRESULT hr = CheckSourceRect(&SourceRect); - if (FAILED(hr)) { - return hr; - } - - // Now set the source rectangle - - hr = SetSourceRect(&SourceRect); - if (FAILED(hr)) { - return hr; - } - return OnUpdateRectangles(); -} - - -// Return the current source height - -STDMETHODIMP CBaseControlVideo::get_SourceHeight(__out long *pSourceHeight) -{ - CheckPointer(pSourceHeight,E_POINTER); - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - CAutoLock cInterfaceLock(m_pInterfaceLock); - RECT SourceRect; - - GetSourceRect(&SourceRect); - *pSourceHeight = HEIGHT(&SourceRect); - return NOERROR; -} - - -// Set the target left position, the target rectangle we get back from the -// window object is a true rectangle in left,top,right and bottom positions -// so all we have to do is to update the left position and pass it back. We -// must keep the current width constant when we're updating this property - -STDMETHODIMP CBaseControlVideo::put_DestinationLeft(long DestinationLeft) -{ - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - CAutoLock cInterfaceLock(m_pInterfaceLock); - RECT DestinationRect; - GetTargetRect(&DestinationRect); - DestinationRect.right = DestinationLeft + WIDTH(&DestinationRect); - DestinationRect.left = DestinationLeft; - - // Check the target rectangle is valid - - HRESULT hr = CheckTargetRect(&DestinationRect); - if (FAILED(hr)) { - return hr; - } - - // Now set the new target rectangle - - hr = SetTargetRect(&DestinationRect); - if (FAILED(hr)) { - return hr; - } - return OnUpdateRectangles(); -} - - -// Return the left position for the destination rectangle - -STDMETHODIMP CBaseControlVideo::get_DestinationLeft(__out long *pDestinationLeft) -{ - CheckPointer(pDestinationLeft,E_POINTER); - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - CAutoLock cInterfaceLock(m_pInterfaceLock); - RECT DestinationRect; - - GetTargetRect(&DestinationRect); - *pDestinationLeft = DestinationRect.left; - return NOERROR; -} - - -// Set the destination width - -STDMETHODIMP CBaseControlVideo::put_DestinationWidth(long DestinationWidth) -{ - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - CAutoLock cInterfaceLock(m_pInterfaceLock); - RECT DestinationRect; - GetTargetRect(&DestinationRect); - DestinationRect.right = DestinationRect.left + DestinationWidth; - - // Check the target rectangle is valid - - HRESULT hr = CheckTargetRect(&DestinationRect); - if (FAILED(hr)) { - return hr; - } - - // Now set the new target rectangle - - hr = SetTargetRect(&DestinationRect); - if (FAILED(hr)) { - return hr; - } - return OnUpdateRectangles(); -} - - -// Return the width for the destination rectangle - -STDMETHODIMP CBaseControlVideo::get_DestinationWidth(__out long *pDestinationWidth) -{ - CheckPointer(pDestinationWidth,E_POINTER); - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - CAutoLock cInterfaceLock(m_pInterfaceLock); - RECT DestinationRect; - - GetTargetRect(&DestinationRect); - *pDestinationWidth = WIDTH(&DestinationRect); - return NOERROR; -} - - -// Set the target top position - changing this property does not affect the -// current target height. So changing this shunts the target rectangle up and -// down appropriately. Changing the height complements this functionality by -// keeping the top position constant and simply changing the target height - -STDMETHODIMP CBaseControlVideo::put_DestinationTop(long DestinationTop) -{ - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - CAutoLock cInterfaceLock(m_pInterfaceLock); - RECT DestinationRect; - GetTargetRect(&DestinationRect); - DestinationRect.bottom = DestinationTop + HEIGHT(&DestinationRect); - DestinationRect.top = DestinationTop; - - // Check the target rectangle is valid - - HRESULT hr = CheckTargetRect(&DestinationRect); - if (FAILED(hr)) { - return hr; - } - - // Now set the new target rectangle - - hr = SetTargetRect(&DestinationRect); - if (FAILED(hr)) { - return hr; - } - return OnUpdateRectangles(); -} - - -// Return the top position for the destination rectangle - -STDMETHODIMP CBaseControlVideo::get_DestinationTop(__out long *pDestinationTop) -{ - CheckPointer(pDestinationTop,E_POINTER); - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - CAutoLock cInterfaceLock(m_pInterfaceLock); - RECT DestinationRect; - - GetTargetRect(&DestinationRect); - *pDestinationTop = DestinationRect.top; - return NOERROR; -} - - -// Set the destination height - -STDMETHODIMP CBaseControlVideo::put_DestinationHeight(long DestinationHeight) -{ - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - CAutoLock cInterfaceLock(m_pInterfaceLock); - RECT DestinationRect; - GetTargetRect(&DestinationRect); - DestinationRect.bottom = DestinationRect.top + DestinationHeight; - - // Check the target rectangle is valid - - HRESULT hr = CheckTargetRect(&DestinationRect); - if (FAILED(hr)) { - return hr; - } - - // Now set the new target rectangle - - hr = SetTargetRect(&DestinationRect); - if (FAILED(hr)) { - return hr; - } - return OnUpdateRectangles(); -} - - -// Return the height for the destination rectangle - -STDMETHODIMP CBaseControlVideo::get_DestinationHeight(__out long *pDestinationHeight) -{ - CheckPointer(pDestinationHeight,E_POINTER); - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - CAutoLock cInterfaceLock(m_pInterfaceLock); - RECT DestinationRect; - - GetTargetRect(&DestinationRect); - *pDestinationHeight = HEIGHT(&DestinationRect); - return NOERROR; -} - - -// Reset the source rectangle to the full video dimensions - -STDMETHODIMP CBaseControlVideo::SetDefaultSourcePosition() -{ - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - CAutoLock cInterfaceLock(m_pInterfaceLock); - HRESULT hr = SetDefaultSourceRect(); - if (FAILED(hr)) { - return hr; - } - return OnUpdateRectangles(); -} - - -// Return S_OK if we're using the default source otherwise S_FALSE - -STDMETHODIMP CBaseControlVideo::IsUsingDefaultSource() -{ - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - CAutoLock cInterfaceLock(m_pInterfaceLock); - return IsDefaultSourceRect(); -} - - -// Reset the video renderer to use the entire playback area - -STDMETHODIMP CBaseControlVideo::SetDefaultDestinationPosition() -{ - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - CAutoLock cInterfaceLock(m_pInterfaceLock); - HRESULT hr = SetDefaultTargetRect(); - if (FAILED(hr)) { - return hr; - } - return OnUpdateRectangles(); -} - - -// Return S_OK if we're using the default target otherwise S_FALSE - -STDMETHODIMP CBaseControlVideo::IsUsingDefaultDestination() -{ - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - CAutoLock cInterfaceLock(m_pInterfaceLock); - return IsDefaultTargetRect(); -} - - -// Return a copy of the current image in the video renderer - -STDMETHODIMP -CBaseControlVideo::GetCurrentImage(__inout long *pBufferSize,__out_bcount_part(*pBufferSize, *pBufferSize) long *pVideoImage) -{ - CheckPointer(pBufferSize,E_POINTER); - CheckConnected(m_pPin,VFW_E_NOT_CONNECTED); - CAutoLock cInterfaceLock(m_pInterfaceLock); - FILTER_STATE State; - - // Make sure we are in a paused state - - if (pVideoImage != NULL) { - m_pFilter->GetState(0,&State); - if (State != State_Paused) { - return VFW_E_NOT_PAUSED; - } - return GetStaticImage(pBufferSize,pVideoImage); - } - - // Just return the memory required - - VIDEOINFOHEADER *pVideoInfo = GetVideoFormat(); - if (pVideoInfo == NULL) - return E_OUTOFMEMORY; - RECT SourceRect; - GetSourceRect(&SourceRect); - return GetImageSize(pVideoInfo,pBufferSize,&SourceRect); -} - - -// An application has two ways of using GetCurrentImage, one is to pass a real -// buffer which should be filled with the current image. The other is to pass -// a NULL buffer pointer which is interpreted as asking us to return how much -// memory is required for the image. The constraints for when the latter can -// be called are much looser. To calculate the memory required we synthesize -// a VIDEOINFO that takes into account the source rectangle that's being used - -HRESULT CBaseControlVideo::GetImageSize(__in VIDEOINFOHEADER *pVideoInfo, - __out long *pBufferSize, - __in RECT *pSourceRect) -{ - NOTE("Entering GetImageSize"); - ASSERT(pSourceRect); - - // Check we have the correct input parameters - - if (pSourceRect == NULL || - pVideoInfo == NULL || - pBufferSize == NULL) { - - return E_UNEXPECTED; - } - - // Is the data format compatible - - if (pVideoInfo->bmiHeader.biCompression != BI_RGB) { - if (pVideoInfo->bmiHeader.biCompression != BI_BITFIELDS) { - return E_INVALIDARG; - } - } - - ASSERT(IsRectEmpty(pSourceRect) == FALSE); - - BITMAPINFOHEADER bih; - bih.biWidth = WIDTH(pSourceRect); - bih.biHeight = HEIGHT(pSourceRect); - bih.biBitCount = pVideoInfo->bmiHeader.biBitCount; - LONG Size = DIBSIZE(bih); - Size += GetBitmapFormatSize(HEADER(pVideoInfo)) - SIZE_PREHEADER; - *pBufferSize = Size; - - return NOERROR; -} - - -// Given an IMediaSample containing a linear buffer with an image and a type -// describing the bitmap make a rendering of the image into the output buffer -// This may be called by derived classes who render typical video images to -// handle the IBasicVideo GetCurrentImage method. The pVideoImage pointer may -// be NULL when passed to GetCurrentImage in which case GetImageSize will be -// called instead, which will just do the calculation of the memory required - -HRESULT CBaseControlVideo::CopyImage(IMediaSample *pMediaSample, - __in VIDEOINFOHEADER *pVideoInfo, - __inout long *pBufferSize, - __out_bcount_part(*pBufferSize, *pBufferSize) BYTE *pVideoImage, - __in RECT *pSourceRect) -{ - NOTE("Entering CopyImage"); - ASSERT(pSourceRect); - BYTE *pCurrentImage; - - // Check we have an image to copy - - if (pMediaSample == NULL || pSourceRect == NULL || - pVideoInfo == NULL || pVideoImage == NULL || - pBufferSize == NULL) { - - return E_UNEXPECTED; - } - - // Is the data format compatible - - if (pVideoInfo->bmiHeader.biCompression != BI_RGB) { - if (pVideoInfo->bmiHeader.biCompression != BI_BITFIELDS) { - return E_INVALIDARG; - } - } - - if (*pBufferSize < 0) { - return E_INVALIDARG; - } - - // Arbitrarily large size to prevent integer overflow problems - if (pVideoInfo->bmiHeader.biSize > 4096) - { - return E_INVALIDARG; - } - - ASSERT(IsRectEmpty(pSourceRect) == FALSE); - - BITMAPINFOHEADER bih; - bih.biWidth = WIDTH(pSourceRect); - bih.biHeight = HEIGHT(pSourceRect); - bih.biBitCount = pVideoInfo->bmiHeader.biBitCount; - DWORD Size = GetBitmapFormatSize(HEADER(pVideoInfo)) - SIZE_PREHEADER; - DWORD Total; - DWORD dwDibSize; - - if( !ValidateBitmapInfoHeader( HEADER(pVideoInfo), Size)) { - return E_INVALIDARG; - } - - // ValidateBitmapInfoHeader checks this but for some reason code scanning - // tools aren't picking up the annotation - __analysis_assume(Size >= sizeof(BITMAPINFOHEADER)); - - if (FAILED(SAFE_DIBSIZE(&bih, &dwDibSize))) { - return E_INVALIDARG; - } - - if (FAILED(DWordAdd(Size, dwDibSize, &Total))) { - return E_INVALIDARG; - } - - // Make sure we have a large enough buffer - - if ((DWORD)*pBufferSize < Total) { - return E_OUTOFMEMORY; - } - - // Copy the BITMAPINFO - - CopyMemory((PVOID)pVideoImage, (PVOID)&pVideoInfo->bmiHeader, Size); - ((BITMAPINFOHEADER *)pVideoImage)->biWidth = WIDTH(pSourceRect); - ((BITMAPINFOHEADER *)pVideoImage)->biHeight = HEIGHT(pSourceRect); - ((BITMAPINFOHEADER *)pVideoImage)->biSizeImage = DIBSIZE(bih); - BYTE *pImageData = pVideoImage + Size; - - // Get the pointer to it's image data - - HRESULT hr = pMediaSample->GetPointer(&pCurrentImage); - if (FAILED(hr)) { - return hr; - } - - // Now we are ready to start copying the source scan lines - - LONG ScanLine = (pVideoInfo->bmiHeader.biBitCount / 8) * WIDTH(pSourceRect); - LONG LinesToSkip = pVideoInfo->bmiHeader.biHeight; - LinesToSkip -= pSourceRect->top + HEIGHT(pSourceRect); - pCurrentImage += LinesToSkip * DIBWIDTHBYTES(pVideoInfo->bmiHeader); - pCurrentImage += pSourceRect->left * (pVideoInfo->bmiHeader.biBitCount / 8); - - // Even money on this GP faulting sometime... - - for (LONG Line = 0;Line < HEIGHT(pSourceRect);Line++) { - CopyMemory((PVOID)pImageData, (PVOID)pCurrentImage, ScanLine); - pImageData += DIBWIDTHBYTES(*(BITMAPINFOHEADER *)pVideoImage); - pCurrentImage += DIBWIDTHBYTES(pVideoInfo->bmiHeader); - } - return NOERROR; -} - - -// Called when we change media types either during connection or dynamically -// We inform the filter graph and therefore the application that the video -// size may have changed, we don't bother looking to see if it really has as -// we leave that to the application - the dimensions are the event parameters - -HRESULT CBaseControlVideo::OnVideoSizeChange() -{ - // Get the video format from the derived class - - VIDEOINFOHEADER *pVideoInfo = GetVideoFormat(); - if (pVideoInfo == NULL) - return E_OUTOFMEMORY; - WORD Width = (WORD) pVideoInfo->bmiHeader.biWidth; - WORD Height = (WORD) pVideoInfo->bmiHeader.biHeight; - - return m_pFilter->NotifyEvent(EC_VIDEO_SIZE_CHANGED, - MAKELPARAM(Width,Height), - MAKEWPARAM(0,0)); -} - - -// Set the video source rectangle. We must check the source rectangle against -// the actual video dimensions otherwise when we come to draw the pictures we -// get access violations as GDI tries to touch data outside of the image data -// Although we store the rectangle in left, top, right and bottom coordinates -// instead of left, top, width and height as OLE uses we do take into account -// that the rectangle is used up to, but not including, the right column and -// bottom row of pixels, see the Win32 documentation on RECT for more details - -HRESULT CBaseControlVideo::CheckSourceRect(__in RECT *pSourceRect) -{ - CheckPointer(pSourceRect,E_POINTER); - LONG Width,Height; - GetVideoSize(&Width,&Height); - - // Check the coordinates are greater than zero - // and that the rectangle is valid (leftleft >= pSourceRect->right) || - (pSourceRect->left < 0) || - (pSourceRect->top >= pSourceRect->bottom) || - (pSourceRect->top < 0)) { - - return E_INVALIDARG; - } - - // Check the coordinates are less than the extents - - if ((pSourceRect->right > Width) || - (pSourceRect->bottom > Height)) { - - return E_INVALIDARG; - } - return NOERROR; -} - - -// Check the target rectangle has some valid coordinates, which amounts to -// little more than checking the destination rectangle isn't empty. Derived -// classes may call this when they have their SetTargetRect method called to -// check the rectangle validity, we do not update the rectangles passed in -// Although we store the rectangle in left, top, right and bottom coordinates -// instead of left, top, width and height as OLE uses we do take into account -// that the rectangle is used up to, but not including, the right column and -// bottom row of pixels, see the Win32 documentation on RECT for more details - -HRESULT CBaseControlVideo::CheckTargetRect(__in RECT *pTargetRect) -{ - // Check the pointer is valid - - if (pTargetRect == NULL) { - return E_POINTER; - } - - // These overflow the WIDTH and HEIGHT checks - - if (pTargetRect->left > pTargetRect->right || - pTargetRect->top > pTargetRect->bottom) { - return E_INVALIDARG; - } - - // Check the rectangle has valid coordinates - - if (WIDTH(pTargetRect) <= 0 || HEIGHT(pTargetRect) <= 0) { - return E_INVALIDARG; - } - - ASSERT(IsRectEmpty(pTargetRect) == FALSE); - return NOERROR; -} - diff --git a/third_party/BaseClasses/winctrl.h b/third_party/BaseClasses/winctrl.h deleted file mode 100644 index 1080a47c..00000000 --- a/third_party/BaseClasses/winctrl.h +++ /dev/null @@ -1,224 +0,0 @@ -//------------------------------------------------------------------------------ -// File: WinCtrl.h -// -// Desc: DirectShow base classes - defines classes for video control -// interfaces. -// -// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. -//------------------------------------------------------------------------------ - - -#ifndef __WINCTRL__ -#define __WINCTRL__ - -#define ABSOL(x) (x < 0 ? -x : x) -#define NEGAT(x) (x > 0 ? -x : x) - -// Helper -BOOL WINAPI PossiblyEatMessage(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - -class CBaseControlWindow : public CBaseVideoWindow, public CBaseWindow -{ -protected: - - CBaseFilter *m_pFilter; // Pointer to owning media filter - CBasePin *m_pPin; // Controls media types for connection - CCritSec *m_pInterfaceLock; // Externally defined critical section - COLORREF m_BorderColour; // Current window border colour - BOOL m_bAutoShow; // What happens when the state changes - HWND m_hwndOwner; // Owner window that we optionally have - HWND m_hwndDrain; // HWND to post any messages received - BOOL m_bCursorHidden; // Should we hide the window cursor - -public: - - // Internal methods for other objects to get information out - - HRESULT DoSetWindowStyle(long Style,long WindowLong); - HRESULT DoGetWindowStyle(__out long *pStyle,long WindowLong); - BOOL IsAutoShowEnabled() { return m_bAutoShow; }; - COLORREF GetBorderColour() { return m_BorderColour; }; - HWND GetOwnerWindow() { return m_hwndOwner; }; - BOOL IsCursorHidden() { return m_bCursorHidden; }; - - inline BOOL PossiblyEatMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) - { - return ::PossiblyEatMessage(m_hwndDrain, uMsg, wParam, lParam); - } - - // Derived classes must call this to set the pin the filter is using - // We don't have the pin passed in to the constructor (as we do with - // the CBaseFilter object) because filters typically create the - // pins dynamically when requested in CBaseFilter::GetPin. This can - // not be called from our constructor because is is a virtual method - - void SetControlWindowPin(CBasePin *pPin) { - m_pPin = pPin; - } - -public: - - CBaseControlWindow(__inout CBaseFilter *pFilter, // Owning media filter - __in CCritSec *pInterfaceLock, // Locking object - __in_opt LPCTSTR pName, // Object description - __inout_opt LPUNKNOWN pUnk, // Normal COM ownership - __inout HRESULT *phr); // OLE return code - - // These are the properties we support - - STDMETHODIMP put_Caption(__in BSTR strCaption); - STDMETHODIMP get_Caption(__out BSTR *pstrCaption); - STDMETHODIMP put_AutoShow(long AutoShow); - STDMETHODIMP get_AutoShow(__out long *AutoShow); - STDMETHODIMP put_WindowStyle(long WindowStyle); - STDMETHODIMP get_WindowStyle(__out long *pWindowStyle); - STDMETHODIMP put_WindowStyleEx(long WindowStyleEx); - STDMETHODIMP get_WindowStyleEx(__out long *pWindowStyleEx); - STDMETHODIMP put_WindowState(long WindowState); - STDMETHODIMP get_WindowState(__out long *pWindowState); - STDMETHODIMP put_BackgroundPalette(long BackgroundPalette); - STDMETHODIMP get_BackgroundPalette(__out long *pBackgroundPalette); - STDMETHODIMP put_Visible(long Visible); - STDMETHODIMP get_Visible(__out long *pVisible); - STDMETHODIMP put_Left(long Left); - STDMETHODIMP get_Left(__out long *pLeft); - STDMETHODIMP put_Width(long Width); - STDMETHODIMP get_Width(__out long *pWidth); - STDMETHODIMP put_Top(long Top); - STDMETHODIMP get_Top(__out long *pTop); - STDMETHODIMP put_Height(long Height); - STDMETHODIMP get_Height(__out long *pHeight); - STDMETHODIMP put_Owner(OAHWND Owner); - STDMETHODIMP get_Owner(__out OAHWND *Owner); - STDMETHODIMP put_MessageDrain(OAHWND Drain); - STDMETHODIMP get_MessageDrain(__out OAHWND *Drain); - STDMETHODIMP get_BorderColor(__out long *Color); - STDMETHODIMP put_BorderColor(long Color); - STDMETHODIMP get_FullScreenMode(__out long *FullScreenMode); - STDMETHODIMP put_FullScreenMode(long FullScreenMode); - - // And these are the methods - - STDMETHODIMP SetWindowForeground(long Focus); - STDMETHODIMP NotifyOwnerMessage(OAHWND hwnd,long uMsg,LONG_PTR wParam,LONG_PTR lParam); - STDMETHODIMP GetMinIdealImageSize(__out long *pWidth,__out long *pHeight); - STDMETHODIMP GetMaxIdealImageSize(__out long *pWidth,__out long *pHeight); - STDMETHODIMP SetWindowPosition(long Left,long Top,long Width,long Height); - STDMETHODIMP GetWindowPosition(__out long *pLeft,__out long *pTop,__out long *pWidth,__out long *pHeight); - STDMETHODIMP GetRestorePosition(__out long *pLeft,__out long *pTop,__out long *pWidth,__out long *pHeight); - STDMETHODIMP HideCursor(long HideCursor); - STDMETHODIMP IsCursorHidden(__out long *CursorHidden); -}; - -// This class implements the IBasicVideo interface - -class CBaseControlVideo : public CBaseBasicVideo -{ -protected: - - CBaseFilter *m_pFilter; // Pointer to owning media filter - CBasePin *m_pPin; // Controls media types for connection - CCritSec *m_pInterfaceLock; // Externally defined critical section - -public: - - // Derived classes must provide these for the implementation - - virtual HRESULT IsDefaultTargetRect() PURE; - virtual HRESULT SetDefaultTargetRect() PURE; - virtual HRESULT SetTargetRect(RECT *pTargetRect) PURE; - virtual HRESULT GetTargetRect(RECT *pTargetRect) PURE; - virtual HRESULT IsDefaultSourceRect() PURE; - virtual HRESULT SetDefaultSourceRect() PURE; - virtual HRESULT SetSourceRect(RECT *pSourceRect) PURE; - virtual HRESULT GetSourceRect(RECT *pSourceRect) PURE; - virtual HRESULT GetStaticImage(__inout long *pBufferSize,__out_bcount_part(*pBufferSize, *pBufferSize) long *pDIBImage) PURE; - - // Derived classes must override this to return a VIDEOINFO representing - // the video format. We cannot call IPin ConnectionMediaType to get this - // format because various filters dynamically change the type when using - // DirectDraw such that the format shows the position of the logical - // bitmap in a frame buffer surface, so the size might be returned as - // 1024x768 pixels instead of 320x240 which is the real video dimensions - - __out virtual VIDEOINFOHEADER *GetVideoFormat() PURE; - - // Helper functions for creating memory renderings of a DIB image - - HRESULT GetImageSize(__in VIDEOINFOHEADER *pVideoInfo, - __out LONG *pBufferSize, - __in RECT *pSourceRect); - - HRESULT CopyImage(IMediaSample *pMediaSample, - __in VIDEOINFOHEADER *pVideoInfo, - __inout LONG *pBufferSize, - __out_bcount_part(*pBufferSize, *pBufferSize) BYTE *pVideoImage, - __in RECT *pSourceRect); - - // Override this if you want notifying when the rectangles change - virtual HRESULT OnUpdateRectangles() { return NOERROR; }; - virtual HRESULT OnVideoSizeChange(); - - // Derived classes must call this to set the pin the filter is using - // We don't have the pin passed in to the constructor (as we do with - // the CBaseFilter object) because filters typically create the - // pins dynamically when requested in CBaseFilter::GetPin. This can - // not be called from our constructor because is is a virtual method - - void SetControlVideoPin(__inout CBasePin *pPin) { - m_pPin = pPin; - } - - // Helper methods for checking rectangles - virtual HRESULT CheckSourceRect(__in RECT *pSourceRect); - virtual HRESULT CheckTargetRect(__in RECT *pTargetRect); - -public: - - CBaseControlVideo(__inout CBaseFilter *pFilter, // Owning media filter - __in CCritSec *pInterfaceLock, // Serialise interface - __in_opt LPCTSTR pName, // Object description - __inout_opt LPUNKNOWN pUnk, // Normal COM ownership - __inout HRESULT *phr); // OLE return code - - // These are the properties we support - - STDMETHODIMP get_AvgTimePerFrame(__out REFTIME *pAvgTimePerFrame); - STDMETHODIMP get_BitRate(__out long *pBitRate); - STDMETHODIMP get_BitErrorRate(__out long *pBitErrorRate); - STDMETHODIMP get_VideoWidth(__out long *pVideoWidth); - STDMETHODIMP get_VideoHeight(__out long *pVideoHeight); - STDMETHODIMP put_SourceLeft(long SourceLeft); - STDMETHODIMP get_SourceLeft(__out long *pSourceLeft); - STDMETHODIMP put_SourceWidth(long SourceWidth); - STDMETHODIMP get_SourceWidth(__out long *pSourceWidth); - STDMETHODIMP put_SourceTop(long SourceTop); - STDMETHODIMP get_SourceTop(__out long *pSourceTop); - STDMETHODIMP put_SourceHeight(long SourceHeight); - STDMETHODIMP get_SourceHeight(__out long *pSourceHeight); - STDMETHODIMP put_DestinationLeft(long DestinationLeft); - STDMETHODIMP get_DestinationLeft(__out long *pDestinationLeft); - STDMETHODIMP put_DestinationWidth(long DestinationWidth); - STDMETHODIMP get_DestinationWidth(__out long *pDestinationWidth); - STDMETHODIMP put_DestinationTop(long DestinationTop); - STDMETHODIMP get_DestinationTop(__out long *pDestinationTop); - STDMETHODIMP put_DestinationHeight(long DestinationHeight); - STDMETHODIMP get_DestinationHeight(__out long *pDestinationHeight); - - // And these are the methods - - STDMETHODIMP GetVideoSize(__out long *pWidth,__out long *pHeight); - STDMETHODIMP SetSourcePosition(long Left,long Top,long Width,long Height); - STDMETHODIMP GetSourcePosition(__out long *pLeft,__out long *pTop,__out long *pWidth,__out long *pHeight); - STDMETHODIMP GetVideoPaletteEntries(long StartIndex,long Entries,__out long *pRetrieved,__out_ecount_part(Entries, *pRetrieved) long *pPalette); - STDMETHODIMP SetDefaultSourcePosition(); - STDMETHODIMP IsUsingDefaultSource(); - STDMETHODIMP SetDestinationPosition(long Left,long Top,long Width,long Height); - STDMETHODIMP GetDestinationPosition(__out long *pLeft,__out long *pTop,__out long *pWidth,__out long *pHeight); - STDMETHODIMP SetDefaultDestinationPosition(); - STDMETHODIMP IsUsingDefaultDestination(); - STDMETHODIMP GetCurrentImage(__inout long *pBufferSize,__out_bcount_part(*pBufferSize, *pBufferSize) long *pVideoImage); -}; - -#endif // __WINCTRL__ - diff --git a/third_party/BaseClasses/winutil.cpp b/third_party/BaseClasses/winutil.cpp deleted file mode 100644 index 6653f457..00000000 --- a/third_party/BaseClasses/winutil.cpp +++ /dev/null @@ -1,2746 +0,0 @@ -//------------------------------------------------------------------------------ -// File: WinUtil.cpp -// -// Desc: DirectShow base classes - implements generic window handler class. -// -// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. -//------------------------------------------------------------------------------ - - -#include -#include -#include -#include -#include - -static UINT MsgDestroy; - -// Constructor - -CBaseWindow::CBaseWindow(BOOL bDoGetDC, bool bDoPostToDestroy) : - m_hInstance(g_hInst), - m_hwnd(NULL), - m_hdc(NULL), - m_bActivated(FALSE), - m_pClassName(NULL), - m_ClassStyles(0), - m_WindowStyles(0), - m_WindowStylesEx(0), - m_ShowStageMessage(0), - m_ShowStageTop(0), - m_MemoryDC(NULL), - m_hPalette(NULL), - m_bBackground(FALSE), -#ifdef DEBUG - m_bRealizing(FALSE), -#endif - m_bNoRealize(FALSE), - m_bDoPostToDestroy(bDoPostToDestroy) -{ - m_bDoGetDC = bDoGetDC; -} - - -// Prepare a window by spinning off a worker thread to do the creation and -// also poll the message input queue. We leave this to be called by derived -// classes because they might want to override methods like MessageLoop and -// InitialiseWindow, if we do this during construction they'll ALWAYS call -// this base class methods. We make the worker thread create the window so -// it owns it rather than the filter graph thread which is constructing us - -HRESULT CBaseWindow::PrepareWindow() -{ - if (m_hwnd) return NOERROR; - ASSERT(m_hwnd == NULL); - ASSERT(m_hdc == NULL); - - // Get the derived object's window and class styles - - m_pClassName = GetClassWindowStyles(&m_ClassStyles, - &m_WindowStyles, - &m_WindowStylesEx); - if (m_pClassName == NULL) { - return E_FAIL; - } - - // Register our special private messages - m_ShowStageMessage = RegisterWindowMessage(SHOWSTAGE); - - // RegisterWindowMessage() returns 0 if an error occurs. - if (0 == m_ShowStageMessage) { - return AmGetLastErrorToHResult(); - } - - m_ShowStageTop = RegisterWindowMessage(SHOWSTAGETOP); - if (0 == m_ShowStageTop) { - return AmGetLastErrorToHResult(); - } - - m_RealizePalette = RegisterWindowMessage(REALIZEPALETTE); - if (0 == m_RealizePalette) { - return AmGetLastErrorToHResult(); - } - - MsgDestroy = RegisterWindowMessage(TEXT("AM_DESTROY")); - if (0 == MsgDestroy) { - return AmGetLastErrorToHResult(); - } - - return DoCreateWindow(); -} - - -// Destructor just a placeholder so that we know it becomes virtual -// Derived classes MUST call DoneWithWindow in their destructors so -// that no messages arrive after the derived class constructor ends - -#ifdef DEBUG -CBaseWindow::~CBaseWindow() -{ - ASSERT(m_hwnd == NULL); - ASSERT(m_hdc == NULL); -} -#endif - - -// We use the sync worker event to have the window destroyed. All we do is -// signal the event and wait on the window thread handle. Trying to send it -// messages causes too many problems, furthermore to be on the safe side we -// just wait on the thread handle while it returns WAIT_TIMEOUT or there is -// a sent message to process on this thread. If the constructor failed to -// create the thread in the first place then the loop will get terminated - -HRESULT CBaseWindow::DoneWithWindow() -{ - if (!IsWindow(m_hwnd) || (GetWindowThreadProcessId(m_hwnd, NULL) != GetCurrentThreadId())) { - - if (IsWindow(m_hwnd)) { - - // This code should only be executed if the window exists and if the window's - // messages are processed on a different thread. - ASSERT(GetWindowThreadProcessId(m_hwnd, NULL) != GetCurrentThreadId()); - - if (m_bDoPostToDestroy) { - - HRESULT hr = S_OK; - CAMEvent m_evDone(FALSE, &hr); - if (FAILED(hr)) { - return hr; - } - - // We must post a message to destroy the window - // That way we can't be in the middle of processing a - // message posted to our window when we do go away - // Sending a message gives less synchronization. - PostMessage(m_hwnd, MsgDestroy, (WPARAM)(HANDLE)m_evDone, 0); - WaitDispatchingMessages(m_evDone, INFINITE); - } else { - SendMessage(m_hwnd, MsgDestroy, 0, 0); - } - } - - // - // This is not a leak, the window manager automatically free's - // hdc's that were got via GetDC, which is the case here. - // We set it to NULL so that we don't get any asserts later. - // - m_hdc = NULL; - - // - // We need to free this DC though because USER32 does not know - // anything about it. - // - if (m_MemoryDC) - { - EXECUTE_ASSERT(DeleteDC(m_MemoryDC)); - m_MemoryDC = NULL; - } - - // Reset the window variables - m_hwnd = NULL; - - return NOERROR; - } - const HWND hwnd = m_hwnd; - if (hwnd == NULL) { - return NOERROR; - } - - InactivateWindow(); - NOTE("Inactivated"); - - // Reset the window styles before destruction - - SetWindowLong(hwnd,GWL_STYLE,m_WindowStyles); - ASSERT(GetParent(hwnd) == NULL); - NOTE1("Reset window styles %d",m_WindowStyles); - - // UnintialiseWindow sets m_hwnd to NULL so save a copy - UninitialiseWindow(); - DbgLog((LOG_TRACE, 2, TEXT("Destroying 0x%8.8X"), hwnd)); - if (!DestroyWindow(hwnd)) { - DbgLog((LOG_TRACE, 0, TEXT("DestroyWindow %8.8X failed code %d"), - hwnd, GetLastError())); - DbgBreak(""); - } - - // Reset our state so we can be prepared again - - m_pClassName = NULL; - m_ClassStyles = 0; - m_WindowStyles = 0; - m_WindowStylesEx = 0; - m_ShowStageMessage = 0; - m_ShowStageTop = 0; - - return NOERROR; -} - - -// Called at the end to put the window in an inactive state. The pending list -// will always have been cleared by this time so event if the worker thread -// gets has been signaled and gets in to render something it will find both -// the state has been changed and that there are no available sample images -// Since we wait on the window thread to complete we don't lock the object - -HRESULT CBaseWindow::InactivateWindow() -{ - // Has the window been activated - if (m_bActivated == FALSE) { - return S_FALSE; - } - - m_bActivated = FALSE; - ShowWindow(m_hwnd,SW_HIDE); - return NOERROR; -} - - -HRESULT CBaseWindow::CompleteConnect() -{ - m_bActivated = FALSE; - return NOERROR; -} - -// This displays a normal window. We ask the base window class for default -// sizes which unless overriden will return DEFWIDTH and DEFHEIGHT. We go -// through a couple of extra hoops to get the client area the right size -// as the object specifies which accounts for the AdjustWindowRectEx calls -// We also DWORD align the left and top coordinates of the window here to -// maximise the chance of being able to use DCI/DirectDraw primary surface - -HRESULT CBaseWindow::ActivateWindow() -{ - // Has the window been sized and positioned already - - if (m_bActivated == TRUE || GetParent(m_hwnd) != NULL) { - - SetWindowPos(m_hwnd, // Our window handle - HWND_TOP, // Put it at the top - 0, 0, 0, 0, // Leave in current position - SWP_NOMOVE | // Don't change it's place - SWP_NOSIZE); // Change Z-order only - - m_bActivated = TRUE; - return S_FALSE; - } - - // Calculate the desired client rectangle - - RECT WindowRect, ClientRect = GetDefaultRect(); - GetWindowRect(m_hwnd,&WindowRect); - AdjustWindowRectEx(&ClientRect,GetWindowLong(m_hwnd,GWL_STYLE), - FALSE,GetWindowLong(m_hwnd,GWL_EXSTYLE)); - - // Align left and top edges on DWORD boundaries - - UINT WindowFlags = (SWP_NOACTIVATE | SWP_FRAMECHANGED); - WindowRect.left -= (WindowRect.left & 3); - WindowRect.top -= (WindowRect.top & 3); - - SetWindowPos(m_hwnd, // Window handle - HWND_TOP, // Put it at the top - WindowRect.left, // Align left edge - WindowRect.top, // And also top place - WIDTH(&ClientRect), // Horizontal size - HEIGHT(&ClientRect), // Vertical size - WindowFlags); // Don't show window - - m_bActivated = TRUE; - return NOERROR; -} - - -// This can be used to DWORD align the window for maximum performance - -HRESULT CBaseWindow::PerformanceAlignWindow() -{ - RECT ClientRect,WindowRect; - GetWindowRect(m_hwnd,&WindowRect); - ASSERT(m_bActivated == TRUE); - - // Don't do this if we're owned - - if (GetParent(m_hwnd)) { - return NOERROR; - } - - // Align left and top edges on DWORD boundaries - - GetClientRect(m_hwnd, &ClientRect); - MapWindowPoints(m_hwnd, HWND_DESKTOP, (LPPOINT) &ClientRect, 2); - WindowRect.left -= (ClientRect.left & 3); - WindowRect.top -= (ClientRect.top & 3); - UINT WindowFlags = (SWP_NOACTIVATE | SWP_NOSIZE); - - SetWindowPos(m_hwnd, // Window handle - HWND_TOP, // Put it at the top - WindowRect.left, // Align left edge - WindowRect.top, // And also top place - (int) 0,(int) 0, // Ignore these sizes - WindowFlags); // Don't show window - - return NOERROR; -} - - -// Install a palette into the base window - we may be called by a different -// thread to the one that owns the window. We have to be careful how we do -// the palette realisation as we could be a different thread to the window -// which would cause an inter thread send message. Therefore we realise the -// palette by sending it a special message but without the window locked - -HRESULT CBaseWindow::SetPalette(HPALETTE hPalette) -{ - // We must own the window lock during the change - { - CAutoLock cWindowLock(&m_WindowLock); - CAutoLock cPaletteLock(&m_PaletteLock); - ASSERT(hPalette); - m_hPalette = hPalette; - } - return SetPalette(); -} - - -HRESULT CBaseWindow::SetPalette() -{ - if (!m_bNoRealize) { - SendMessage(m_hwnd, m_RealizePalette, 0, 0); - return S_OK; - } else { - // Just select the palette - ASSERT(m_hdc); - ASSERT(m_MemoryDC); - - CAutoLock cPaletteLock(&m_PaletteLock); - SelectPalette(m_hdc,m_hPalette,m_bBackground); - SelectPalette(m_MemoryDC,m_hPalette,m_bBackground); - - return S_OK; - } -} - - -void CBaseWindow::UnsetPalette() -{ - CAutoLock cWindowLock(&m_WindowLock); - CAutoLock cPaletteLock(&m_PaletteLock); - - // Get a standard VGA colour palette - - HPALETTE hPalette = (HPALETTE) GetStockObject(DEFAULT_PALETTE); - ASSERT(hPalette); - - SelectPalette(GetWindowHDC(), hPalette, TRUE); - SelectPalette(GetMemoryHDC(), hPalette, TRUE); - - m_hPalette = NULL; -} - - -void CBaseWindow::LockPaletteLock() -{ - m_PaletteLock.Lock(); -} - - -void CBaseWindow::UnlockPaletteLock() -{ - m_PaletteLock.Unlock(); -} - - -// Realise our palettes in the window and device contexts - -HRESULT CBaseWindow::DoRealisePalette(BOOL bForceBackground) -{ - { - CAutoLock cPaletteLock(&m_PaletteLock); - - if (m_hPalette == NULL) { - return NOERROR; - } - - // Realize the palette on the window thread - ASSERT(m_hdc); - ASSERT(m_MemoryDC); - - SelectPalette(m_hdc,m_hPalette,m_bBackground || bForceBackground); - SelectPalette(m_MemoryDC,m_hPalette,m_bBackground); - } - - // If we grab a critical section here we can deadlock - // with the window thread because one of the side effects - // of RealizePalette is to send a WM_PALETTECHANGED message - // to every window in the system. In our handling - // of WM_PALETTECHANGED we used to grab this CS too. - // The really bad case is when our renderer calls DoRealisePalette() - // while we're in the middle of processing a palette change - // for another window. - // So don't hold the critical section while actually realising - // the palette. In any case USER is meant to manage palette - // handling - we shouldn't have to serialize everything as well - ASSERT(CritCheckOut(&m_WindowLock)); - ASSERT(CritCheckOut(&m_PaletteLock)); - - EXECUTE_ASSERT(RealizePalette(m_hdc) != GDI_ERROR); - EXECUTE_ASSERT(RealizePalette(m_MemoryDC) != GDI_ERROR); - - return (GdiFlush() == FALSE ? S_FALSE : S_OK); -} - - -// This is the global window procedure - -LRESULT CALLBACK WndProc(HWND hwnd, // Window handle - UINT uMsg, // Message ID - WPARAM wParam, // First parameter - LPARAM lParam) // Other parameter -{ - - // Get the window long that holds our window object pointer - // If it is NULL then we are initialising the window in which - // case the object pointer has been passed in the window creation - // structure. IF we get any messages before WM_NCCREATE we will - // pass them to DefWindowProc. - - CBaseWindow *pBaseWindow = _GetWindowLongPtr(hwnd,0); - - if (pBaseWindow == NULL) { - - // Get the structure pointer from the create struct. - // We can only do this for WM_NCCREATE which should be one of - // the first messages we receive. Anything before this will - // have to be passed to DefWindowProc (i.e. WM_GETMINMAXINFO) - - // If the message is WM_NCCREATE we set our pBaseWindow pointer - // and will then place it in the window structure - - // turn off WS_EX_LAYOUTRTL style for quartz windows - if (uMsg == WM_NCCREATE) { - SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) & ~0x400000); - } - - if ((uMsg != WM_NCCREATE) - || (NULL == (pBaseWindow = *(CBaseWindow**) ((LPCREATESTRUCT)lParam)->lpCreateParams))) - { - return(DefWindowProc(hwnd, uMsg, wParam, lParam)); - } - - // Set the window LONG to be the object who created us -#ifdef DEBUG - SetLastError(0); // because of the way SetWindowLong works -#endif - - LONG_PTR rc = _SetWindowLongPtr(hwnd, (DWORD) 0, pBaseWindow); - - -#ifdef DEBUG - if (0 == rc) { - // SetWindowLong MIGHT have failed. (Read the docs which admit - // that it is awkward to work out if you have had an error.) - LONG lasterror = GetLastError(); - ASSERT(0 == lasterror); - // If this is not the case we have not set the pBaseWindow pointer - // into the window structure and we will blow up. - } -#endif - - } - // See if this is the packet of death - if (uMsg == MsgDestroy && uMsg != 0) { - pBaseWindow->DoneWithWindow(); - if (pBaseWindow->m_bDoPostToDestroy) { - EXECUTE_ASSERT(SetEvent((HANDLE)wParam)); - } - return 0; - } - return pBaseWindow->OnReceiveMessage(hwnd,uMsg,wParam,lParam); -} - - -// When the window size changes we adjust our member variables that -// contain the dimensions of the client rectangle for our window so -// that we come to render an image we will know whether to stretch - -BOOL CBaseWindow::OnSize(LONG Width, LONG Height) -{ - m_Width = Width; - m_Height = Height; - return TRUE; -} - - -// This function handles the WM_CLOSE message - -BOOL CBaseWindow::OnClose() -{ - ShowWindow(m_hwnd,SW_HIDE); - return TRUE; -} - - -// This is called by the worker window thread when it receives a terminate -// message from the window object destructor to delete all the resources we -// allocated during initialisation. By the time the worker thread exits all -// processing will have been completed as the source filter disconnection -// flushes the image pending sample, therefore the GdiFlush should succeed - -HRESULT CBaseWindow::UninitialiseWindow() -{ - // Have we already cleaned up - - if (m_hwnd == NULL) { - ASSERT(m_hdc == NULL); - ASSERT(m_MemoryDC == NULL); - return NOERROR; - } - - // Release the window resources - - EXECUTE_ASSERT(GdiFlush()); - - if (m_hdc) - { - EXECUTE_ASSERT(ReleaseDC(m_hwnd,m_hdc)); - m_hdc = NULL; - } - - if (m_MemoryDC) - { - EXECUTE_ASSERT(DeleteDC(m_MemoryDC)); - m_MemoryDC = NULL; - } - - // Reset the window variables - m_hwnd = NULL; - - return NOERROR; -} - - -// This is called by the worker window thread after it has created the main -// window and it wants to initialise the rest of the owner objects window -// variables such as the device contexts. We execute this function with the -// critical section still locked. Nothing in this function must generate any -// SendMessage calls to the window because this is executing on the window -// thread so the message will never be processed and we will deadlock - -HRESULT CBaseWindow::InitialiseWindow(HWND hwnd) -{ - // Initialise the window variables - - ASSERT(IsWindow(hwnd)); - m_hwnd = hwnd; - - if (m_bDoGetDC) - { - EXECUTE_ASSERT(m_hdc = GetDC(hwnd)); - EXECUTE_ASSERT(m_MemoryDC = CreateCompatibleDC(m_hdc)); - - EXECUTE_ASSERT(SetStretchBltMode(m_hdc,COLORONCOLOR)); - EXECUTE_ASSERT(SetStretchBltMode(m_MemoryDC,COLORONCOLOR)); - } - - return NOERROR; -} - -HRESULT CBaseWindow::DoCreateWindow() -{ - WNDCLASS wndclass; // Used to register classes - BOOL bRegistered; // Is this class registered - HWND hwnd; // Handle to our window - - bRegistered = GetClassInfo(m_hInstance, // Module instance - m_pClassName, // Window class - &wndclass); // Info structure - - // if the window is to be used for drawing puposes and we are getting a DC - // for the entire lifetime of the window then changes the class style to do - // say so. If we don't set this flag then the DC comes from the cache and is - // really bad. - if (m_bDoGetDC) - { - m_ClassStyles |= CS_OWNDC; - } - - if (bRegistered == FALSE) { - - // Register the renderer window class - - wndclass.lpszClassName = m_pClassName; - wndclass.style = m_ClassStyles; - wndclass.lpfnWndProc = WndProc; - wndclass.cbClsExtra = 0; - wndclass.cbWndExtra = sizeof(CBaseWindow *); - wndclass.hInstance = m_hInstance; - wndclass.hIcon = NULL; - wndclass.hCursor = LoadCursor (NULL, IDC_ARROW); - wndclass.hbrBackground = (HBRUSH) NULL; - wndclass.lpszMenuName = NULL; - - RegisterClass(&wndclass); - } - - // Create the frame window. Pass the pBaseWindow information in the - // CreateStruct which allows our message handling loop to get hold of - // the pBaseWindow pointer. - - CBaseWindow *pBaseWindow = this; // The owner window object - hwnd = CreateWindowEx(m_WindowStylesEx, // Extended styles - m_pClassName, // Registered name - TEXT("ActiveMovie Window"), // Window title - m_WindowStyles, // Window styles - CW_USEDEFAULT, // Start x position - CW_USEDEFAULT, // Start y position - DEFWIDTH, // Window width - DEFHEIGHT, // Window height - NULL, // Parent handle - NULL, // Menu handle - m_hInstance, // Instance handle - &pBaseWindow); // Creation data - - // If we failed signal an error to the object constructor (based on the - // last Win32 error on this thread) then signal the constructor thread - // to continue, release the mutex to let others have a go and exit - - if (hwnd == NULL) { - DWORD Error = GetLastError(); - return AmHresultFromWin32(Error); - } - - // Check the window LONG is the object who created us - ASSERT(GetWindowLongPtr(hwnd, 0) == (LONG_PTR)this); - - // Initialise the window and then signal the constructor so that it can - // continue and then finally unlock the object's critical section. The - // window class is left registered even after we terminate the thread - // as we don't know when the last window has been closed. So we allow - // the operating system to free the class resources as appropriate - - InitialiseWindow(hwnd); - - DbgLog((LOG_TRACE, 2, TEXT("Created window class (%s) HWND(%8.8X)"), - m_pClassName, hwnd)); - - return S_OK; -} - - -// The base class provides some default handling and calls DefWindowProc - -LRESULT CBaseWindow::OnReceiveMessage(HWND hwnd, // Window handle - UINT uMsg, // Message ID - WPARAM wParam, // First parameter - LPARAM lParam) // Other parameter -{ - ASSERT(IsWindow(hwnd)); - - if (PossiblyEatMessage(uMsg, wParam, lParam)) - return 0; - - // This is sent by the IVideoWindow SetWindowForeground method. If the - // window is invisible we will show it and make it topmost without the - // foreground focus. If the window is visible it will also be made the - // topmost window without the foreground focus. If wParam is TRUE then - // for both cases the window will be forced into the foreground focus - - if (uMsg == m_ShowStageMessage) { - - BOOL bVisible = IsWindowVisible(hwnd); - SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, - SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | - (bVisible ? SWP_NOACTIVATE : 0)); - - // Should we bring the window to the foreground - if (wParam == TRUE) { - SetForegroundWindow(hwnd); - } - return (LRESULT) 1; - } - - // When we go fullscreen we have to add the WS_EX_TOPMOST style to the - // video window so that it comes out above any task bar (this is more - // relevant to WindowsNT than Windows95). However the SetWindowPos call - // must be on the same thread as that which created the window. The - // wParam parameter can be TRUE or FALSE to set and reset the topmost - - if (uMsg == m_ShowStageTop) { - HWND HwndTop = (wParam == TRUE ? HWND_TOPMOST : HWND_NOTOPMOST); - BOOL bVisible = IsWindowVisible(hwnd); - SetWindowPos(hwnd, HwndTop, 0, 0, 0, 0, - SWP_NOMOVE | SWP_NOSIZE | - (wParam == TRUE ? SWP_SHOWWINDOW : 0) | - (bVisible ? SWP_NOACTIVATE : 0)); - return (LRESULT) 1; - } - - // New palette stuff - if (uMsg == m_RealizePalette) { - ASSERT(m_hwnd == hwnd); - return OnPaletteChange(m_hwnd,WM_QUERYNEWPALETTE); - } - - switch (uMsg) { - - // Repaint the window if the system colours change - - case WM_SYSCOLORCHANGE: - - InvalidateRect(hwnd,NULL,FALSE); - return (LRESULT) 1; - - // Somebody has changed the palette - case WM_PALETTECHANGED: - - OnPaletteChange((HWND)wParam,uMsg); - return (LRESULT) 0; - - // We are about to receive the keyboard focus so we ask GDI to realise - // our logical palette again and hopefully it will be fully installed - // without any mapping having to be done during any picture rendering - - case WM_QUERYNEWPALETTE: - ASSERT(m_hwnd == hwnd); - return OnPaletteChange(m_hwnd,uMsg); - - // do NOT fwd WM_MOVE. the parameters are the location of the parent - // window, NOT what the renderer should be looking at. But we need - // to make sure the overlay is moved with the parent window, so we - // do this. - case WM_MOVE: - if (IsWindowVisible(m_hwnd)) { - PostMessage(m_hwnd,WM_PAINT,0,0); - } - break; - - // Store the width and height as useful base class members - - case WM_SIZE: - - OnSize(LOWORD(lParam), HIWORD(lParam)); - return (LRESULT) 0; - - // Intercept the WM_CLOSE messages to hide the window - - case WM_CLOSE: - - OnClose(); - return (LRESULT) 0; - } - return DefWindowProc(hwnd,uMsg,wParam,lParam); -} - - -// This handles the Windows palette change messages - if we do realise our -// palette then we return TRUE otherwise we return FALSE. If our window is -// foreground application then we should get first choice of colours in the -// system palette entries. We get best performance when our logical palette -// includes the standard VGA colours (at the beginning and end) otherwise -// GDI may have to map from our palette to the device palette while drawing - -LRESULT CBaseWindow::OnPaletteChange(HWND hwnd,UINT Message) -{ - // First check we are not changing the palette during closedown - - if (m_hwnd == NULL || hwnd == NULL) { - return (LRESULT) 0; - } - ASSERT(!m_bRealizing); - - // Should we realise our palette again - - if ((Message == WM_QUERYNEWPALETTE || hwnd != m_hwnd)) { - // It seems that even if we're invisible that we can get asked - // to realize our palette and this can cause really ugly side-effects - // Seems like there's another bug but this masks it a least for the - // shutting down case. - if (!IsWindowVisible(m_hwnd)) { - DbgLog((LOG_TRACE, 1, TEXT("Realizing when invisible!"))); - return (LRESULT) 0; - } - - // Avoid recursion with multiple graphs in the same app -#ifdef DEBUG - m_bRealizing = TRUE; -#endif - DoRealisePalette(Message != WM_QUERYNEWPALETTE); -#ifdef DEBUG - m_bRealizing = FALSE; -#endif - - // Should we redraw the window with the new palette - if (Message == WM_PALETTECHANGED) { - InvalidateRect(m_hwnd,NULL,FALSE); - } - } - - return (LRESULT) 1; -} - - -// Determine if the window exists. - -bool CBaseWindow::WindowExists() -{ - return !!IsWindow(m_hwnd); -} - - -// Return the default window rectangle - -RECT CBaseWindow::GetDefaultRect() -{ - RECT DefaultRect = {0,0,DEFWIDTH,DEFHEIGHT}; - ASSERT(m_hwnd); - // ASSERT(m_hdc); - return DefaultRect; -} - - -// Return the current window width - -LONG CBaseWindow::GetWindowWidth() -{ - ASSERT(m_hwnd); - // ASSERT(m_hdc); - return m_Width; -} - - -// Return the current window height - -LONG CBaseWindow::GetWindowHeight() -{ - ASSERT(m_hwnd); - // ASSERT(m_hdc); - return m_Height; -} - - -// Return the window handle - -HWND CBaseWindow::GetWindowHWND() -{ - ASSERT(m_hwnd); - // ASSERT(m_hdc); - return m_hwnd; -} - - -// Return the window drawing device context - -HDC CBaseWindow::GetWindowHDC() -{ - ASSERT(m_hwnd); - ASSERT(m_hdc); - return m_hdc; -} - - -// Return the offscreen window drawing device context - -HDC CBaseWindow::GetMemoryHDC() -{ - ASSERT(m_hwnd); - ASSERT(m_MemoryDC); - return m_MemoryDC; -} - - -#ifdef DEBUG -HPALETTE CBaseWindow::GetPalette() -{ - // The palette lock should always be held when accessing - // m_hPalette. - ASSERT(CritCheckIn(&m_PaletteLock)); - return m_hPalette; -} -#endif // DEBUG - - -// This is available to clients who want to change the window visiblity. It's -// little more than an indirection to the Win32 ShowWindow although these is -// some benefit in going through here as this function may change sometime - -HRESULT CBaseWindow::DoShowWindow(LONG ShowCmd) -{ - ShowWindow(m_hwnd,ShowCmd); - return NOERROR; -} - - -// Generate a WM_PAINT message for the video window - -void CBaseWindow::PaintWindow(BOOL bErase) -{ - InvalidateRect(m_hwnd,NULL,bErase); -} - - -// Allow an application to have us set the video window in the foreground. We -// have this because it is difficult for one thread to do do this to a window -// owned by another thread. Rather than expose the message we use to execute -// the inter thread send message we provide the interface function. All we do -// is to SendMessage to the video window renderer thread with a WM_SHOWSTAGE - -void CBaseWindow::DoSetWindowForeground(BOOL bFocus) -{ - SendMessage(m_hwnd,m_ShowStageMessage,(WPARAM) bFocus,(LPARAM) 0); -} - - -// Constructor initialises the owning object pointer. Since we are a worker -// class for the main window object we have relatively few state variables to -// look after. We are given device context handles to use later on as well as -// the source and destination rectangles (but reset them here just in case) - -CDrawImage::CDrawImage(__inout CBaseWindow *pBaseWindow) : - m_pBaseWindow(pBaseWindow), - m_hdc(NULL), - m_MemoryDC(NULL), - m_bStretch(FALSE), - m_pMediaType(NULL), - m_bUsingImageAllocator(FALSE) -{ - ASSERT(pBaseWindow); - ResetPaletteVersion(); - SetRectEmpty(&m_TargetRect); - SetRectEmpty(&m_SourceRect); - - m_perfidRenderTime = MSR_REGISTER(TEXT("Single Blt time")); -} - - -// Overlay the image time stamps on the picture. Access to this method is -// serialised by the caller. We display the sample start and end times on -// top of the video using TextOut on the device context we are handed. If -// there isn't enough room in the window for the times we don't show them - -void CDrawImage::DisplaySampleTimes(IMediaSample *pSample) -{ -#ifdef DEBUG - // - // Only allow the "annoying" time messages if the users has turned the - // logging "way up" - // - BOOL bAccept = DbgCheckModuleLevel(LOG_TRACE, 5); - if (bAccept == FALSE) { - return; - } -#endif - - TCHAR szTimes[TIMELENGTH]; // Time stamp strings - ASSERT(pSample); // Quick sanity check - RECT ClientRect; // Client window size - SIZE Size; // Size of text output - - // Get the time stamps and window size - - pSample->GetTime((REFERENCE_TIME*)&m_StartSample, (REFERENCE_TIME*)&m_EndSample); - HWND hwnd = m_pBaseWindow->GetWindowHWND(); - EXECUTE_ASSERT(GetClientRect(hwnd,&ClientRect)); - - // Format the sample time stamps - - (void)StringCchPrintf(szTimes,NUMELMS(szTimes),TEXT("%08d : %08d"), - m_StartSample.Millisecs(), - m_EndSample.Millisecs()); - - ASSERT(lstrlen(szTimes) < TIMELENGTH); - - // Put the times in the middle at the bottom of the window - - GetTextExtentPoint32(m_hdc,szTimes,lstrlen(szTimes),&Size); - INT XPos = ((ClientRect.right - ClientRect.left) - Size.cx) / 2; - INT YPos = ((ClientRect.bottom - ClientRect.top) - Size.cy) * 4 / 5; - - // Check the window is big enough to have sample times displayed - - if ((XPos > 0) && (YPos > 0)) { - TextOut(m_hdc,XPos,YPos,szTimes,lstrlen(szTimes)); - } -} - - -// This is called when the drawing code sees that the image has a down level -// palette cookie. We simply call the SetDIBColorTable Windows API with the -// palette that is found after the BITMAPINFOHEADER - we return no errors - -void CDrawImage::UpdateColourTable(HDC hdc,__in BITMAPINFOHEADER *pbmi) -{ - ASSERT(pbmi->biClrUsed); - RGBQUAD *pColourTable = (RGBQUAD *)(pbmi+1); - - // Set the new palette in the device context - - UINT uiReturn = SetDIBColorTable(hdc,(UINT) 0, - pbmi->biClrUsed, - pColourTable); - - // Should always succeed but check in debug builds - ASSERT(uiReturn == pbmi->biClrUsed); -} - - -// No source rectangle scaling is done by the base class - -RECT CDrawImage::ScaleSourceRect(const RECT *pSource) -{ - ASSERT(pSource); - return *pSource; -} - - -// This is called when the funky output pin uses our allocator. The samples we -// allocate are special because the memory is shared between us and GDI thus -// removing one copy when we ask for the image to be rendered. The source type -// information is in the main renderer m_mtIn field which is initialised when -// the media type is agreed in SetMediaType, the media type may be changed on -// the fly if, for example, the source filter needs to change the palette - -void CDrawImage::FastRender(IMediaSample *pMediaSample) -{ - BITMAPINFOHEADER *pbmi; // Image format data - DIBDATA *pDibData; // Stores DIB information - BYTE *pImage; // Pointer to image data - HBITMAP hOldBitmap; // Store the old bitmap - CImageSample *pSample; // Pointer to C++ object - - ASSERT(m_pMediaType); - - // From the untyped source format block get the VIDEOINFO and subsequently - // the BITMAPINFOHEADER structure. We can cast the IMediaSample interface - // to a CImageSample object so we can retrieve it's DIBSECTION details - - pbmi = HEADER(m_pMediaType->Format()); - pSample = (CImageSample *) pMediaSample; - pDibData = pSample->GetDIBData(); - hOldBitmap = (HBITMAP) SelectObject(m_MemoryDC,pDibData->hBitmap); - - // Get a pointer to the real image data - - HRESULT hr = pMediaSample->GetPointer(&pImage); - if (FAILED(hr)) { - return; - } - - // Do we need to update the colour table, we increment our palette cookie - // each time we get a dynamic format change. The sample palette cookie is - // stored in the DIBDATA structure so we try to keep the fields in sync - // By the time we get to draw the images the format change will be done - // so all we do is ask the renderer for what it's palette version is - - if (pDibData->PaletteVersion < GetPaletteVersion()) { - ASSERT(pbmi->biBitCount <= iPALETTE); - UpdateColourTable(m_MemoryDC,pbmi); - pDibData->PaletteVersion = GetPaletteVersion(); - } - - // This allows derived classes to change the source rectangle that we do - // the drawing with. For example a renderer may ask a codec to stretch - // the video from 320x240 to 640x480, in which case the source we see in - // here will still be 320x240, although the source we want to draw with - // should be scaled up to 640x480. The base class implementation of this - // method does nothing but return the same rectangle as we are passed in - - RECT SourceRect = ScaleSourceRect(&m_SourceRect); - - // Is the window the same size as the video - - if (m_bStretch == FALSE) { - - // Put the image straight into the window - - BitBlt( - (HDC) m_hdc, // Target device HDC - m_TargetRect.left, // X sink position - m_TargetRect.top, // Y sink position - m_TargetRect.right - m_TargetRect.left, // Destination width - m_TargetRect.bottom - m_TargetRect.top, // Destination height - m_MemoryDC, // Source device context - SourceRect.left, // X source position - SourceRect.top, // Y source position - SRCCOPY); // Simple copy - - } else { - - // Stretch the image when copying to the window - - StretchBlt( - (HDC) m_hdc, // Target device HDC - m_TargetRect.left, // X sink position - m_TargetRect.top, // Y sink position - m_TargetRect.right - m_TargetRect.left, // Destination width - m_TargetRect.bottom - m_TargetRect.top, // Destination height - m_MemoryDC, // Source device HDC - SourceRect.left, // X source position - SourceRect.top, // Y source position - SourceRect.right - SourceRect.left, // Source width - SourceRect.bottom - SourceRect.top, // Source height - SRCCOPY); // Simple copy - } - - // This displays the sample times over the top of the image. This used to - // draw the times into the offscreen device context however that actually - // writes the text into the image data buffer which may not be writable - - #ifdef DEBUG - DisplaySampleTimes(pMediaSample); - #endif - - // Put the old bitmap back into the device context so we don't leak - SelectObject(m_MemoryDC,hOldBitmap); -} - - -// This is called when there is a sample ready to be drawn, unfortunately the -// output pin was being rotten and didn't choose our super excellent shared -// memory DIB allocator so we have to do this slow render using boring old GDI -// SetDIBitsToDevice and StretchDIBits. The down side of using these GDI -// functions is that the image data has to be copied across from our address -// space into theirs before going to the screen (although in reality the cost -// is small because all they do is to map the buffer into their address space) - -void CDrawImage::SlowRender(IMediaSample *pMediaSample) -{ - // Get the BITMAPINFOHEADER for the connection - - ASSERT(m_pMediaType); - BITMAPINFOHEADER *pbmi = HEADER(m_pMediaType->Format()); - BYTE *pImage; - - // Get the image data buffer - - HRESULT hr = pMediaSample->GetPointer(&pImage); - if (FAILED(hr)) { - return; - } - - // This allows derived classes to change the source rectangle that we do - // the drawing with. For example a renderer may ask a codec to stretch - // the video from 320x240 to 640x480, in which case the source we see in - // here will still be 320x240, although the source we want to draw with - // should be scaled up to 640x480. The base class implementation of this - // method does nothing but return the same rectangle as we are passed in - - RECT SourceRect = ScaleSourceRect(&m_SourceRect); - - LONG lAdjustedSourceTop = SourceRect.top; - // if the origin of bitmap is bottom-left, adjust soruce_rect_top - // to be the bottom-left corner instead of the top-left. - if (pbmi->biHeight > 0) { - lAdjustedSourceTop = pbmi->biHeight - SourceRect.bottom; - } - // Is the window the same size as the video - - if (m_bStretch == FALSE) { - - // Put the image straight into the window - - SetDIBitsToDevice( - (HDC) m_hdc, // Target device HDC - m_TargetRect.left, // X sink position - m_TargetRect.top, // Y sink position - m_TargetRect.right - m_TargetRect.left, // Destination width - m_TargetRect.bottom - m_TargetRect.top, // Destination height - SourceRect.left, // X source position - lAdjustedSourceTop, // Adjusted Y source position - (UINT) 0, // Start scan line - pbmi->biHeight, // Scan lines present - pImage, // Image data - (BITMAPINFO *) pbmi, // DIB header - DIB_RGB_COLORS); // Type of palette - - } else { - - // Stretch the image when copying to the window - - StretchDIBits( - (HDC) m_hdc, // Target device HDC - m_TargetRect.left, // X sink position - m_TargetRect.top, // Y sink position - m_TargetRect.right - m_TargetRect.left, // Destination width - m_TargetRect.bottom - m_TargetRect.top, // Destination height - SourceRect.left, // X source position - lAdjustedSourceTop, // Adjusted Y source position - SourceRect.right - SourceRect.left, // Source width - SourceRect.bottom - SourceRect.top, // Source height - pImage, // Image data - (BITMAPINFO *) pbmi, // DIB header - DIB_RGB_COLORS, // Type of palette - SRCCOPY); // Simple image copy - } - - // This shows the sample reference times over the top of the image which - // looks a little flickery. I tried using GdiSetBatchLimit and GdiFlush to - // control the screen updates but it doesn't quite work as expected and - // only partially reduces the flicker. I also tried using a memory context - // and combining the two in that before doing a final BitBlt operation to - // the screen, unfortunately this has considerable performance penalties - // and also means that this code is not executed when compiled retail - - #ifdef DEBUG - DisplaySampleTimes(pMediaSample); - #endif -} - - -// This is called with an IMediaSample interface on the image to be drawn. We -// decide on the drawing mechanism based on who's allocator we are using. We -// may be called when the window wants an image painted by WM_PAINT messages -// We can't realise the palette here because we have the renderer lock, any -// call to realise may cause an interthread send message to the window thread -// which may in turn be waiting to get the renderer lock before servicing it - -BOOL CDrawImage::DrawImage(IMediaSample *pMediaSample) -{ - ASSERT(m_hdc); - ASSERT(m_MemoryDC); - NotifyStartDraw(); - - // If the output pin used our allocator then the samples passed are in - // fact CVideoSample objects that contain CreateDIBSection data that we - // use to do faster image rendering, they may optionally also contain a - // DirectDraw surface pointer in which case we do not do the drawing - - if (m_bUsingImageAllocator == FALSE) { - SlowRender(pMediaSample); - EXECUTE_ASSERT(GdiFlush()); - NotifyEndDraw(); - return TRUE; - } - - // This is a DIBSECTION buffer - - FastRender(pMediaSample); - EXECUTE_ASSERT(GdiFlush()); - NotifyEndDraw(); - return TRUE; -} - - -BOOL CDrawImage::DrawVideoImageHere( - HDC hdc, - IMediaSample *pMediaSample, - __in LPRECT lprcSrc, - __in LPRECT lprcDst - ) -{ - ASSERT(m_pMediaType); - BITMAPINFOHEADER *pbmi = HEADER(m_pMediaType->Format()); - BYTE *pImage; - - // Get the image data buffer - - HRESULT hr = pMediaSample->GetPointer(&pImage); - if (FAILED(hr)) { - return FALSE; - } - - RECT SourceRect; - RECT TargetRect; - - if (lprcSrc) { - SourceRect = *lprcSrc; - } - else SourceRect = ScaleSourceRect(&m_SourceRect); - - if (lprcDst) { - TargetRect = *lprcDst; - } - else TargetRect = m_TargetRect; - - LONG lAdjustedSourceTop = SourceRect.top; - // if the origin of bitmap is bottom-left, adjust soruce_rect_top - // to be the bottom-left corner instead of the top-left. - if (pbmi->biHeight > 0) { - lAdjustedSourceTop = pbmi->biHeight - SourceRect.bottom; - } - - - // Stretch the image when copying to the DC - - BOOL bRet = (0 != StretchDIBits(hdc, - TargetRect.left, - TargetRect.top, - TargetRect.right - TargetRect.left, - TargetRect.bottom - TargetRect.top, - SourceRect.left, - lAdjustedSourceTop, - SourceRect.right - SourceRect.left, - SourceRect.bottom - SourceRect.top, - pImage, - (BITMAPINFO *)pbmi, - DIB_RGB_COLORS, - SRCCOPY)); - return bRet; -} - - -// This is called by the owning window object after it has created the window -// and it's drawing contexts. We are constructed with the base window we'll -// be drawing into so when given the notification we retrive the device HDCs -// to draw with. We cannot call these in our constructor as they are virtual - -void CDrawImage::SetDrawContext() -{ - m_MemoryDC = m_pBaseWindow->GetMemoryHDC(); - m_hdc = m_pBaseWindow->GetWindowHDC(); -} - - -// This is called to set the target rectangle in the video window, it will be -// called whenever a WM_SIZE message is retrieved from the message queue. We -// simply store the rectangle and use it later when we do the drawing calls - -void CDrawImage::SetTargetRect(__in RECT *pTargetRect) -{ - ASSERT(pTargetRect); - m_TargetRect = *pTargetRect; - SetStretchMode(); -} - - -// Return the current target rectangle - -void CDrawImage::GetTargetRect(__out RECT *pTargetRect) -{ - ASSERT(pTargetRect); - *pTargetRect = m_TargetRect; -} - - -// This is called when we want to change the section of the image to draw. We -// use this information in the drawing operation calls later on. We must also -// see if the source and destination rectangles have the same dimensions. If -// not we must stretch during the drawing rather than a direct pixel copy - -void CDrawImage::SetSourceRect(__in RECT *pSourceRect) -{ - ASSERT(pSourceRect); - m_SourceRect = *pSourceRect; - SetStretchMode(); -} - - -// Return the current source rectangle - -void CDrawImage::GetSourceRect(__out RECT *pSourceRect) -{ - ASSERT(pSourceRect); - *pSourceRect = m_SourceRect; -} - - -// This is called when either the source or destination rectanges change so we -// can update the stretch flag. If the rectangles don't match we stretch the -// video during the drawing otherwise we call the fast pixel copy functions -// NOTE the source and/or the destination rectangle may be completely empty - -void CDrawImage::SetStretchMode() -{ - // Calculate the overall rectangle dimensions - - LONG SourceWidth = m_SourceRect.right - m_SourceRect.left; - LONG SinkWidth = m_TargetRect.right - m_TargetRect.left; - LONG SourceHeight = m_SourceRect.bottom - m_SourceRect.top; - LONG SinkHeight = m_TargetRect.bottom - m_TargetRect.top; - - m_bStretch = TRUE; - if (SourceWidth == SinkWidth) { - if (SourceHeight == SinkHeight) { - m_bStretch = FALSE; - } - } -} - - -// Tell us whose allocator we are using. This should be called with TRUE if -// the filter agrees to use an allocator based around the CImageAllocator -// SDK base class - whose image buffers are made through CreateDIBSection. -// Otherwise this should be called with FALSE and we will draw the images -// using SetDIBitsToDevice and StretchDIBitsToDevice. None of these calls -// can handle buffers which have non zero strides (like DirectDraw uses) - -void CDrawImage::NotifyAllocator(BOOL bUsingImageAllocator) -{ - m_bUsingImageAllocator = bUsingImageAllocator; -} - - -// Are we using the image DIBSECTION allocator - -BOOL CDrawImage::UsingImageAllocator() -{ - return m_bUsingImageAllocator; -} - - -// We need the media type of the connection so that we can get the BITMAPINFO -// from it. We use that in the calls to draw the image such as StretchDIBits -// and also when updating the colour table held in shared memory DIBSECTIONs - -void CDrawImage::NotifyMediaType(__in CMediaType *pMediaType) -{ - m_pMediaType = pMediaType; -} - - -// We store in this object a cookie maintaining the current palette version. -// Each time a palettised format is changed we increment this value so that -// when we come to draw the images we look at the colour table value they -// have and if less than the current we know to update it. This version is -// only needed and indeed used when working with shared memory DIBSECTIONs - -LONG CDrawImage::GetPaletteVersion() -{ - return m_PaletteVersion; -} - - -// Resets the current palette version number - -void CDrawImage::ResetPaletteVersion() -{ - m_PaletteVersion = PALETTE_VERSION; -} - - -// Increment the current palette version - -void CDrawImage::IncrementPaletteVersion() -{ - m_PaletteVersion++; -} - - -// Constructor must initialise the base allocator. Each sample we create has a -// palette version cookie on board. When the source filter changes the palette -// during streaming the window object increments an internal cookie counter it -// keeps as well. When it comes to render the samples it looks at the cookie -// values and if they don't match then it knows to update the sample's colour -// table. However we always create samples with a cookie of PALETTE_VERSION -// If there have been multiple format changes and we disconnect and reconnect -// thereby causing the samples to be reallocated we will create them with a -// cookie much lower than the current version, this isn't a problem since it -// will be seen by the window object and the versions will then be updated - -CImageAllocator::CImageAllocator(__inout CBaseFilter *pFilter, - __in_opt LPCTSTR pName, - __inout HRESULT *phr) : - CBaseAllocator(pName,NULL,phr,TRUE,TRUE), - m_pFilter(pFilter) -{ - ASSERT(phr); - ASSERT(pFilter); -} - - -// Check our DIB buffers have been released - -#ifdef DEBUG -CImageAllocator::~CImageAllocator() -{ - ASSERT(m_bCommitted == FALSE); -} -#endif - - -// Called from destructor and also from base class to free resources. We work -// our way through the list of media samples deleting the DIBSECTION created -// for each. All samples should be back in our list so there is no chance a -// filter is still using one to write on the display or hold on a pending list - -void CImageAllocator::Free() -{ - ASSERT(m_lAllocated == m_lFree.GetCount()); - EXECUTE_ASSERT(GdiFlush()); - CImageSample *pSample; - DIBDATA *pDibData; - - while (m_lFree.GetCount() != 0) { - pSample = (CImageSample *) m_lFree.RemoveHead(); - pDibData = pSample->GetDIBData(); - EXECUTE_ASSERT(DeleteObject(pDibData->hBitmap)); - EXECUTE_ASSERT(CloseHandle(pDibData->hMapping)); - delete pSample; - } - - m_lAllocated = 0; -} - - -// Prepare the allocator by checking all the input parameters - -STDMETHODIMP CImageAllocator::CheckSizes(__in ALLOCATOR_PROPERTIES *pRequest) -{ - // Check we have a valid connection - - if (m_pMediaType == NULL) { - return VFW_E_NOT_CONNECTED; - } - - // NOTE We always create a DIB section with the source format type which - // may contain a source palette. When we do the BitBlt drawing operation - // the target display device may contain a different palette (we may not - // have the focus) in which case GDI will do after the palette mapping - - VIDEOINFOHEADER *pVideoInfo = (VIDEOINFOHEADER *) m_pMediaType->Format(); - - // When we call CreateDIBSection it implicitly maps only enough memory - // for the image as defined by thee BITMAPINFOHEADER. If the user asks - // for an image smaller than this then we reject the call, if they ask - // for an image larger than this then we return what they can have - - if ((DWORD) pRequest->cbBuffer < pVideoInfo->bmiHeader.biSizeImage) { - return E_INVALIDARG; - } - - // Reject buffer prefixes - - if (pRequest->cbPrefix > 0) { - return E_INVALIDARG; - } - - pRequest->cbBuffer = pVideoInfo->bmiHeader.biSizeImage; - return NOERROR; -} - - -// Agree the number of media sample buffers and their sizes. The base class -// this allocator is derived from allows samples to be aligned only on byte -// boundaries NOTE the buffers are not allocated until the Commit call - -STDMETHODIMP CImageAllocator::SetProperties( - __in ALLOCATOR_PROPERTIES * pRequest, - __out ALLOCATOR_PROPERTIES * pActual) -{ - ALLOCATOR_PROPERTIES Adjusted = *pRequest; - - // Check the parameters fit with the current connection - - HRESULT hr = CheckSizes(&Adjusted); - if (FAILED(hr)) { - return hr; - } - return CBaseAllocator::SetProperties(&Adjusted, pActual); -} - - -// Commit the memory by allocating the agreed number of media samples. For -// each sample we are committed to creating we have a CImageSample object -// that we use to manage it's resources. This is initialised with a DIBDATA -// structure that contains amongst other things the GDI DIBSECTION handle -// We will access the renderer media type during this so we must have locked -// (to prevent the format changing for example). The class overrides Commit -// and Decommit to do this locking (base class Commit in turn calls Alloc) - -HRESULT CImageAllocator::Alloc(void) -{ - ASSERT(m_pMediaType); - CImageSample *pSample; - DIBDATA DibData; - - // Check the base allocator says it's ok to continue - - HRESULT hr = CBaseAllocator::Alloc(); - if (FAILED(hr)) { - return hr; - } - - // We create a new memory mapped object although we don't map it into our - // address space because GDI does that in CreateDIBSection. It is possible - // that we run out of resources before creating all the samples in which - // case the available sample list is left with those already created - - ASSERT(m_lAllocated == 0); - while (m_lAllocated < m_lCount) { - - // Create and initialise a shared memory GDI buffer - - hr = CreateDIB(m_lSize,DibData); - if (FAILED(hr)) { - return hr; - } - - // Create the sample object and pass it the DIBDATA - - pSample = CreateImageSample(DibData.pBase,m_lSize); - if (pSample == NULL) { - EXECUTE_ASSERT(DeleteObject(DibData.hBitmap)); - EXECUTE_ASSERT(CloseHandle(DibData.hMapping)); - return E_OUTOFMEMORY; - } - - // Add the completed sample to the available list - - pSample->SetDIBData(&DibData); - m_lFree.Add(pSample); - m_lAllocated++; - } - return NOERROR; -} - - -// We have a virtual method that allocates the samples so that a derived class -// may override it and allocate more specialised sample objects. So long as it -// derives its samples from CImageSample then all this code will still work ok - -CImageSample *CImageAllocator::CreateImageSample(__in_bcount(Length) LPBYTE pData,LONG Length) -{ - HRESULT hr = NOERROR; - CImageSample *pSample; - - // Allocate the new sample and check the return codes - - pSample = new CImageSample((CBaseAllocator *) this, // Base class - NAME("Video sample"), // DEBUG name - (HRESULT *) &hr, // Return code - (LPBYTE) pData, // DIB address - (LONG) Length); // Size of DIB - - if (pSample == NULL || FAILED(hr)) { - delete pSample; - return NULL; - } - return pSample; -} - - -// This function allocates a shared memory block for use by the source filter -// generating DIBs for us to render. The memory block is created in shared -// memory so that GDI doesn't have to copy the memory when we do a BitBlt - -HRESULT CImageAllocator::CreateDIB(LONG InSize,DIBDATA &DibData) -{ - BITMAPINFO *pbmi; // Format information for pin - BYTE *pBase; // Pointer to the actual image - HANDLE hMapping; // Handle to mapped object - HBITMAP hBitmap; // DIB section bitmap handle - - // Create a file mapping object and map into our address space - - hMapping = CreateFileMapping(hMEMORY, // Use system page file - NULL, // No security attributes - PAGE_READWRITE, // Full access to memory - (DWORD) 0, // Less than 4Gb in size - InSize, // Size of buffer - NULL); // No name to section - if (hMapping == NULL) { - DWORD Error = GetLastError(); - return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, Error); - } - - // NOTE We always create a DIB section with the source format type which - // may contain a source palette. When we do the BitBlt drawing operation - // the target display device may contain a different palette (we may not - // have the focus) in which case GDI will do after the palette mapping - - pbmi = (BITMAPINFO *) HEADER(m_pMediaType->Format()); - if (m_pMediaType == NULL) { - DbgBreak("Invalid media type"); - } - - hBitmap = CreateDIBSection((HDC) NULL, // NO device context - pbmi, // Format information - DIB_RGB_COLORS, // Use the palette - (VOID **) &pBase, // Pointer to image data - hMapping, // Mapped memory handle - (DWORD) 0); // Offset into memory - - if (hBitmap == NULL || pBase == NULL) { - EXECUTE_ASSERT(CloseHandle(hMapping)); - DWORD Error = GetLastError(); - return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, Error); - } - - // Initialise the DIB information structure - - DibData.hBitmap = hBitmap; - DibData.hMapping = hMapping; - DibData.pBase = pBase; - DibData.PaletteVersion = PALETTE_VERSION; - GetObject(hBitmap,sizeof(DIBSECTION),(VOID *)&DibData.DibSection); - - return NOERROR; -} - - -// We use the media type during the DIBSECTION creation - -void CImageAllocator::NotifyMediaType(__in CMediaType *pMediaType) -{ - m_pMediaType = pMediaType; -} - - -// Overriden to increment the owning object's reference count - -STDMETHODIMP_(ULONG) CImageAllocator::NonDelegatingAddRef() -{ - return m_pFilter->AddRef(); -} - - -// Overriden to decrement the owning object's reference count - -STDMETHODIMP_(ULONG) CImageAllocator::NonDelegatingRelease() -{ - return m_pFilter->Release(); -} - - -// If you derive a class from CMediaSample that has to transport specialised -// member variables and entry points then there are three alternate solutions -// The first is to create a memory buffer larger than actually required by the -// sample and store your information either at the beginning of it or at the -// end, the former being moderately safer allowing for misbehaving transform -// filters. You then adjust the buffer address when you create the base media -// sample. This has the disadvantage of breaking up the memory allocated to -// the samples into separate blocks. The second solution is to implement a -// class derived from CMediaSample and support additional interface(s) that -// convey your private data. This means defining a custom interface. The final -// alternative is to create a class that inherits from CMediaSample and adds -// the private data structures, when you get an IMediaSample in your Receive() -// call check to see if your allocator is being used, and if it is then cast -// the IMediaSample into one of your objects. Additional checks can be made -// to ensure the sample's this pointer is known to be one of your own objects - -CImageSample::CImageSample(__inout CBaseAllocator *pAllocator, - __in_opt LPCTSTR pName, - __inout HRESULT *phr, - __in_bcount(length) LPBYTE pBuffer, - LONG length) : - CMediaSample(pName,pAllocator,phr,pBuffer,length), - m_bInit(FALSE) -{ - ASSERT(pAllocator); - ASSERT(pBuffer); -} - - -// Set the shared memory DIB information - -void CImageSample::SetDIBData(__in DIBDATA *pDibData) -{ - ASSERT(pDibData); - m_DibData = *pDibData; - m_bInit = TRUE; -} - - -// Retrieve the shared memory DIB data - -__out DIBDATA *CImageSample::GetDIBData() -{ - ASSERT(m_bInit == TRUE); - return &m_DibData; -} - - -// This class handles the creation of a palette. It is fairly specialist and -// is intended to simplify palette management for video renderer filters. It -// is for this reason that the constructor requires three other objects with -// which it interacts, namely a base media filter, a base window and a base -// drawing object although the base window or the draw object may be NULL to -// ignore that part of us. We try not to create and install palettes unless -// absolutely necessary as they typically require WM_PALETTECHANGED messages -// to be sent to every window thread in the system which is very expensive - -CImagePalette::CImagePalette(__inout CBaseFilter *pBaseFilter, - __inout CBaseWindow *pBaseWindow, - __inout CDrawImage *pDrawImage) : - m_pBaseWindow(pBaseWindow), - m_pFilter(pBaseFilter), - m_pDrawImage(pDrawImage), - m_hPalette(NULL) -{ - ASSERT(m_pFilter); -} - - -// Destructor - -#ifdef DEBUG -CImagePalette::~CImagePalette() -{ - ASSERT(m_hPalette == NULL); -} -#endif - - -// We allow dynamic format changes of the palette but rather than change the -// palette every time we call this to work out whether an update is required. -// If the original type didn't use a palette and the new one does (or vica -// versa) then we return TRUE. If neither formats use a palette we'll return -// FALSE. If both formats use a palette we compare their colours and return -// FALSE if they match. This therefore short circuits palette creation unless -// absolutely necessary since installing palettes is an expensive operation - -BOOL CImagePalette::ShouldUpdate(const VIDEOINFOHEADER *pNewInfo, - const VIDEOINFOHEADER *pOldInfo) -{ - // We may not have a current format yet - - if (pOldInfo == NULL) { - return TRUE; - } - - // Do both formats not require a palette - - if (ContainsPalette(pNewInfo) == FALSE) { - if (ContainsPalette(pOldInfo) == FALSE) { - return FALSE; - } - } - - // Compare the colours to see if they match - - DWORD VideoEntries = pNewInfo->bmiHeader.biClrUsed; - if (ContainsPalette(pNewInfo) == TRUE) - if (ContainsPalette(pOldInfo) == TRUE) - if (pOldInfo->bmiHeader.biClrUsed == VideoEntries) - if (pOldInfo->bmiHeader.biClrUsed > 0) - if (memcmp((PVOID) GetBitmapPalette(pNewInfo), - (PVOID) GetBitmapPalette(pOldInfo), - VideoEntries * sizeof(RGBQUAD)) == 0) { - - return FALSE; - } - return TRUE; -} - - -// This is normally called when the input pin type is set to install a palette -// We will typically be called from two different places. The first is when we -// have negotiated a palettised media type after connection, the other is when -// we receive a new type during processing with an updated palette in which -// case we must remove and release the resources held by the current palette - -// We can be passed an optional device name if we wish to prepare a palette -// for a specific monitor on a multi monitor system - -HRESULT CImagePalette::PreparePalette(const CMediaType *pmtNew, - const CMediaType *pmtOld, - __in LPSTR szDevice) -{ - const VIDEOINFOHEADER *pNewInfo = (VIDEOINFOHEADER *) pmtNew->Format(); - const VIDEOINFOHEADER *pOldInfo = (VIDEOINFOHEADER *) pmtOld->Format(); - ASSERT(pNewInfo); - - // This is an performance optimisation, when we get a media type we check - // to see if the format requires a palette change. If either we need one - // when previously we didn't or vica versa then this returns TRUE, if we - // previously needed a palette and we do now it compares their colours - - if (ShouldUpdate(pNewInfo,pOldInfo) == FALSE) { - NOTE("No update needed"); - return S_FALSE; - } - - // We must notify the filter graph that the application may have changed - // the palette although in practice we don't bother checking to see if it - // is really different. If it tries to get the palette either the window - // or renderer lock will ensure it doesn't get in until we are finished - - RemovePalette(); - m_pFilter->NotifyEvent(EC_PALETTE_CHANGED,0,0); - - // Do we need a palette for the new format - - if (ContainsPalette(pNewInfo) == FALSE) { - NOTE("New has no palette"); - return S_FALSE; - } - - if (m_pBaseWindow) { - m_pBaseWindow->LockPaletteLock(); - } - - // If we're changing the palette on the fly then we increment our palette - // cookie which is compared against the cookie also stored in all of our - // DIBSECTION media samples. If they don't match when we come to draw it - // then we know the sample is out of date and we'll update it's palette - - NOTE("Making new colour palette"); - m_hPalette = MakePalette(pNewInfo, szDevice); - ASSERT(m_hPalette != NULL); - - if (m_pBaseWindow) { - m_pBaseWindow->UnlockPaletteLock(); - } - - // The window in which the new palette is to be realised may be a NULL - // pointer to signal that no window is in use, if so we don't call it - // Some filters just want to use this object to create/manage palettes - - if (m_pBaseWindow) m_pBaseWindow->SetPalette(m_hPalette); - - // This is the only time where we need access to the draw object to say - // to it that a new palette will be arriving on a sample real soon. The - // constructor may take a NULL pointer in which case we don't call this - - if (m_pDrawImage) m_pDrawImage->IncrementPaletteVersion(); - return NOERROR; -} - - -// Helper function to copy a palette out of any kind of VIDEOINFO (ie it may -// be YUV or true colour) into a palettised VIDEOINFO. We use this changing -// palettes on DirectDraw samples as a source filter can attach a palette to -// any buffer (eg YUV) and hand it back. We make a new palette out of that -// format and then copy the palette colours into the current connection type - -HRESULT CImagePalette::CopyPalette(const CMediaType *pSrc,__out CMediaType *pDest) -{ - // Reset the destination palette before starting - - VIDEOINFOHEADER *pDestInfo = (VIDEOINFOHEADER *) pDest->Format(); - pDestInfo->bmiHeader.biClrUsed = 0; - pDestInfo->bmiHeader.biClrImportant = 0; - - // Does the destination have a palette - - if (PALETTISED(pDestInfo) == FALSE) { - NOTE("No destination palette"); - return S_FALSE; - } - - // Does the source contain a palette - - const VIDEOINFOHEADER *pSrcInfo = (VIDEOINFOHEADER *) pSrc->Format(); - if (ContainsPalette(pSrcInfo) == FALSE) { - NOTE("No source palette"); - return S_FALSE; - } - - // The number of colours may be zero filled - - DWORD PaletteEntries = pSrcInfo->bmiHeader.biClrUsed; - if (PaletteEntries == 0) { - DWORD Maximum = (1 << pSrcInfo->bmiHeader.biBitCount); - NOTE1("Setting maximum colours (%d)",Maximum); - PaletteEntries = Maximum; - } - - // Make sure the destination has enough room for the palette - - ASSERT(pSrcInfo->bmiHeader.biClrUsed <= iPALETTE_COLORS); - ASSERT(pSrcInfo->bmiHeader.biClrImportant <= PaletteEntries); - ASSERT(COLORS(pDestInfo) == GetBitmapPalette(pDestInfo)); - pDestInfo->bmiHeader.biClrUsed = PaletteEntries; - pDestInfo->bmiHeader.biClrImportant = pSrcInfo->bmiHeader.biClrImportant; - ULONG BitmapSize = GetBitmapFormatSize(HEADER(pSrcInfo)); - - if (pDest->FormatLength() < BitmapSize) { - NOTE("Reallocating destination"); - pDest->ReallocFormatBuffer(BitmapSize); - } - - // Now copy the palette colours across - - CopyMemory((PVOID) COLORS(pDestInfo), - (PVOID) GetBitmapPalette(pSrcInfo), - PaletteEntries * sizeof(RGBQUAD)); - - return NOERROR; -} - - -// This is normally called when the palette is changed (typically during a -// dynamic format change) to remove any palette we previously installed. We -// replace it (if necessary) in the video window with a standard VGA palette -// that should always be available even if this is a true colour display - -HRESULT CImagePalette::RemovePalette() -{ - if (m_pBaseWindow) { - m_pBaseWindow->LockPaletteLock(); - } - - // Do we have a palette to remove - - if (m_hPalette != NULL) { - - if (m_pBaseWindow) { - // Make sure that the window's palette handle matches - // our palette handle. - ASSERT(m_hPalette == m_pBaseWindow->GetPalette()); - - m_pBaseWindow->UnsetPalette(); - } - - EXECUTE_ASSERT(DeleteObject(m_hPalette)); - m_hPalette = NULL; - } - - if (m_pBaseWindow) { - m_pBaseWindow->UnlockPaletteLock(); - } - - return NOERROR; -} - - -// Called to create a palette for the object, the data structure used by GDI -// to describe a palette is a LOGPALETTE, this includes a variable number of -// PALETTEENTRY fields which are the colours, we have to convert the RGBQUAD -// colour fields we are handed in a BITMAPINFO from the media type into these -// This handles extraction of palettes from true colour and YUV media formats - -// We can be passed an optional device name if we wish to prepare a palette -// for a specific monitor on a multi monitor system - -HPALETTE CImagePalette::MakePalette(const VIDEOINFOHEADER *pVideoInfo, __in LPSTR szDevice) -{ - ASSERT(ContainsPalette(pVideoInfo) == TRUE); - ASSERT(pVideoInfo->bmiHeader.biClrUsed <= iPALETTE_COLORS); - BITMAPINFOHEADER *pHeader = HEADER(pVideoInfo); - - const RGBQUAD *pColours; // Pointer to the palette - LOGPALETTE *lp; // Used to create a palette - HPALETTE hPalette; // Logical palette object - - lp = (LOGPALETTE *) new BYTE[sizeof(LOGPALETTE) + SIZE_PALETTE]; - if (lp == NULL) { - return NULL; - } - - // Unfortunately for some hare brained reason a GDI palette entry (a - // PALETTEENTRY structure) is different to a palette entry from a DIB - // format (a RGBQUAD structure) so we have to do the field conversion - // The VIDEOINFO containing the palette may be a true colour type so - // we use GetBitmapPalette to skip over any bit fields if they exist - - lp->palVersion = PALVERSION; - lp->palNumEntries = (USHORT) pHeader->biClrUsed; - if (lp->palNumEntries == 0) lp->palNumEntries = (1 << pHeader->biBitCount); - pColours = GetBitmapPalette(pVideoInfo); - - for (DWORD dwCount = 0;dwCount < lp->palNumEntries;dwCount++) { - lp->palPalEntry[dwCount].peRed = pColours[dwCount].rgbRed; - lp->palPalEntry[dwCount].peGreen = pColours[dwCount].rgbGreen; - lp->palPalEntry[dwCount].peBlue = pColours[dwCount].rgbBlue; - lp->palPalEntry[dwCount].peFlags = 0; - } - - MakeIdentityPalette(lp->palPalEntry, lp->palNumEntries, szDevice); - - // Create a logical palette - - hPalette = CreatePalette(lp); - ASSERT(hPalette != NULL); - delete[] lp; - return hPalette; -} - - -// GDI does a fair job of compressing the palette entries you give it, so for -// example if you have five entries with an RGB colour (0,0,0) it will remove -// all but one of them. When you subsequently draw an image it will map from -// your logical palette to the compressed device palette. This function looks -// to see if it is trying to be an identity palette and if so sets the flags -// field in the PALETTEENTRYs so they remain expanded to boost performance - -// We can be passed an optional device name if we wish to prepare a palette -// for a specific monitor on a multi monitor system - -HRESULT CImagePalette::MakeIdentityPalette(__inout_ecount_full(iColours) PALETTEENTRY *pEntry,INT iColours, __in LPSTR szDevice) -{ - PALETTEENTRY SystemEntries[10]; // System palette entries - BOOL bIdentityPalette = TRUE; // Is an identity palette - ASSERT(iColours <= iPALETTE_COLORS); // Should have a palette - const int PalLoCount = 10; // First ten reserved colours - const int PalHiStart = 246; // Last VGA palette entries - - // Does this have the full colour range - - if (iColours < 10) { - return S_FALSE; - } - - // Apparently some displays have odd numbers of system colours - - // Get a DC on the right monitor - it's ugly, but this is the way you have - // to do it - HDC hdc; - if (szDevice == NULL || lstrcmpiLocaleIndependentA(szDevice, "DISPLAY") == 0) - hdc = CreateDCA("DISPLAY", NULL, NULL, NULL); - else - hdc = CreateDCA(NULL, szDevice, NULL, NULL); - if (NULL == hdc) { - return E_OUTOFMEMORY; - } - INT Reserved = GetDeviceCaps(hdc,NUMRESERVED); - if (Reserved != 20) { - DeleteDC(hdc); - return S_FALSE; - } - - // Compare our palette against the first ten system entries. The reason I - // don't do a memory compare between our two arrays of colours is because - // I am not sure what will be in the flags fields for the system entries - - UINT Result = GetSystemPaletteEntries(hdc,0,PalLoCount,SystemEntries); - for (UINT Count = 0;Count < Result;Count++) { - if (SystemEntries[Count].peRed != pEntry[Count].peRed || - SystemEntries[Count].peGreen != pEntry[Count].peGreen || - SystemEntries[Count].peBlue != pEntry[Count].peBlue) { - bIdentityPalette = FALSE; - } - } - - // And likewise compare against the last ten entries - - Result = GetSystemPaletteEntries(hdc,PalHiStart,PalLoCount,SystemEntries); - for (UINT Count = 0;Count < Result;Count++) { - if (INT(Count) + PalHiStart < iColours) { - if (SystemEntries[Count].peRed != pEntry[PalHiStart + Count].peRed || - SystemEntries[Count].peGreen != pEntry[PalHiStart + Count].peGreen || - SystemEntries[Count].peBlue != pEntry[PalHiStart + Count].peBlue) { - bIdentityPalette = FALSE; - } - } - } - - // If not an identity palette then return S_FALSE - - DeleteDC(hdc); - if (bIdentityPalette == FALSE) { - return S_FALSE; - } - - // Set the non VGA entries so that GDI doesn't map them - - for (UINT Count = PalLoCount;INT(Count) < min(PalHiStart,iColours);Count++) { - pEntry[Count].peFlags = PC_NOCOLLAPSE; - } - return NOERROR; -} - - -// Constructor initialises the VIDEOINFO we keep storing the current display -// format. The format can be changed at any time, to reset the format held -// by us call the RefreshDisplayType directly (it's a public method). Since -// more than one thread will typically call us (ie window threads resetting -// the type and source threads in the type checking methods) we have a lock - -CImageDisplay::CImageDisplay() -{ - RefreshDisplayType(NULL); -} - - - -// This initialises the format we hold which contains the display device type -// We do a conversion on the display device type in here so that when we start -// type checking input formats we can assume that certain fields have been set -// correctly, an example is when we make the 16 bit mask fields explicit. This -// is normally called when we receive WM_DEVMODECHANGED device change messages - -// The optional szDeviceName parameter tells us which monitor we are interested -// in for a multi monitor system - -HRESULT CImageDisplay::RefreshDisplayType(__in_opt LPSTR szDeviceName) -{ - CAutoLock cDisplayLock(this); - - // Set the preferred format type - - ZeroMemory((PVOID)&m_Display,sizeof(VIDEOINFOHEADER)+sizeof(TRUECOLORINFO)); - m_Display.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - m_Display.bmiHeader.biBitCount = FALSE; - - // Get the bit depth of a device compatible bitmap - - // get caps of whichever monitor they are interested in (multi monitor) - HDC hdcDisplay; - // it's ugly, but this is the way you have to do it - if (szDeviceName == NULL || lstrcmpiLocaleIndependentA(szDeviceName, "DISPLAY") == 0) - hdcDisplay = CreateDCA("DISPLAY", NULL, NULL, NULL); - else - hdcDisplay = CreateDCA(NULL, szDeviceName, NULL, NULL); - if (hdcDisplay == NULL) { - ASSERT(FALSE); - DbgLog((LOG_ERROR,1,TEXT("ACK! Can't get a DC for %hs"), - szDeviceName ? szDeviceName : "")); - return E_FAIL; - } else { - DbgLog((LOG_TRACE,3,TEXT("Created a DC for %s"), - szDeviceName ? szDeviceName : "")); - } - HBITMAP hbm = CreateCompatibleBitmap(hdcDisplay,1,1); - if ( hbm ) - { - GetDIBits(hdcDisplay,hbm,0,1,NULL,(BITMAPINFO *)&m_Display.bmiHeader,DIB_RGB_COLORS); - - // This call will get the colour table or the proper bitfields - GetDIBits(hdcDisplay,hbm,0,1,NULL,(BITMAPINFO *)&m_Display.bmiHeader,DIB_RGB_COLORS); - DeleteObject(hbm); - } - DeleteDC(hdcDisplay); - - // Complete the display type initialisation - - ASSERT(CheckHeaderValidity(&m_Display)); - UpdateFormat(&m_Display); - DbgLog((LOG_TRACE,3,TEXT("New DISPLAY bit depth =%d"), - m_Display.bmiHeader.biBitCount)); - return NOERROR; -} - - -// We assume throughout this code that any bitfields masks are allowed no -// more than eight bits to store a colour component. This checks that the -// bit count assumption is enforced and also makes sure that all the bits -// set are contiguous. We return a boolean TRUE if the field checks out ok - -BOOL CImageDisplay::CheckBitFields(const VIDEOINFO *pInput) -{ - DWORD *pBitFields = (DWORD *) BITMASKS(pInput); - - for (INT iColour = iRED;iColour <= iBLUE;iColour++) { - - // First of all work out how many bits are set - - DWORD SetBits = CountSetBits(pBitFields[iColour]); - if (SetBits > iMAXBITS || SetBits == 0) { - NOTE1("Bit fields for component %d invalid",iColour); - return FALSE; - } - - // Next work out the number of zero bits prefix - DWORD PrefixBits = CountPrefixBits(pBitFields[iColour]); - - // This is going to see if all the bits set are contiguous (as they - // should be). We know how much to shift them right by from the - // count of prefix bits. The number of bits set defines a mask, we - // invert this (ones complement) and AND it with the shifted bit - // fields. If the result is NON zero then there are bit(s) sticking - // out the left hand end which means they are not contiguous - - DWORD TestField = pBitFields[iColour] >> PrefixBits; - DWORD Mask = ULONG_MAX << SetBits; - if (TestField & Mask) { - NOTE1("Bit fields for component %d not contiguous",iColour); - return FALSE; - } - } - return TRUE; -} - - -// This counts the number of bits set in the input field - -DWORD CImageDisplay::CountSetBits(DWORD Field) -{ - // This is a relatively well known bit counting algorithm - - DWORD Count = 0; - DWORD init = Field; - - // Until the input is exhausted, count the number of bits - - while (init) { - init = init & (init - 1); // Turn off the bottommost bit - Count++; - } - return Count; -} - - -// This counts the number of zero bits upto the first one set NOTE the input -// field should have been previously checked to ensure there is at least one -// set although if we don't find one set we return the impossible value 32 - -DWORD CImageDisplay::CountPrefixBits(DWORD Field) -{ - DWORD Mask = 1; - DWORD Count = 0; - - while (TRUE) { - if (Field & Mask) { - return Count; - } - Count++; - - ASSERT(Mask != 0x80000000); - if (Mask == 0x80000000) { - return Count; - } - Mask <<= 1; - } -} - - -// This is called to check the BITMAPINFOHEADER for the input type. There are -// many implicit dependancies between the fields in a header structure which -// if we validate now make for easier manipulation in subsequent handling. We -// also check that the BITMAPINFOHEADER matches it's specification such that -// fields likes the number of planes is one, that it's structure size is set -// correctly and that the bitmap dimensions have not been set as negative - -BOOL CImageDisplay::CheckHeaderValidity(const VIDEOINFO *pInput) -{ - // Check the bitmap width and height are not negative. - - if (pInput->bmiHeader.biWidth <= 0 || - pInput->bmiHeader.biHeight <= 0) { - NOTE("Invalid bitmap dimensions"); - return FALSE; - } - - // Check the compression is either BI_RGB or BI_BITFIELDS - - if (pInput->bmiHeader.biCompression != BI_RGB) { - if (pInput->bmiHeader.biCompression != BI_BITFIELDS) { - NOTE("Invalid compression format"); - return FALSE; - } - } - - // If BI_BITFIELDS compression format check the colour depth - - if (pInput->bmiHeader.biCompression == BI_BITFIELDS) { - if (pInput->bmiHeader.biBitCount != 16) { - if (pInput->bmiHeader.biBitCount != 32) { - NOTE("BI_BITFIELDS not 16/32 bit depth"); - return FALSE; - } - } - } - - // Check the assumptions about the layout of the bit fields - - if (pInput->bmiHeader.biCompression == BI_BITFIELDS) { - if (CheckBitFields(pInput) == FALSE) { - NOTE("Bit fields are not valid"); - return FALSE; - } - } - - // Are the number of planes equal to one - - if (pInput->bmiHeader.biPlanes != 1) { - NOTE("Number of planes not one"); - return FALSE; - } - - // Check the image size is consistent (it can be zero) - - if (pInput->bmiHeader.biSizeImage != GetBitmapSize(&pInput->bmiHeader)) { - if (pInput->bmiHeader.biSizeImage) { - NOTE("Image size incorrectly set"); - return FALSE; - } - } - - // Check the size of the structure - - if (pInput->bmiHeader.biSize != sizeof(BITMAPINFOHEADER)) { - NOTE("Size of BITMAPINFOHEADER wrong"); - return FALSE; - } - return CheckPaletteHeader(pInput); -} - - -// This runs a few simple tests against the palette fields in the input to -// see if it looks vaguely correct. The tests look at the number of palette -// colours present, the number considered important and the biCompression -// field which should always be BI_RGB as no other formats are meaningful - -BOOL CImageDisplay::CheckPaletteHeader(const VIDEOINFO *pInput) -{ - // The checks here are for palettised videos only - - if (PALETTISED(pInput) == FALSE) { - if (pInput->bmiHeader.biClrUsed) { - NOTE("Invalid palette entries"); - return FALSE; - } - return TRUE; - } - - // Compression type of BI_BITFIELDS is meaningless for palette video - - if (pInput->bmiHeader.biCompression != BI_RGB) { - NOTE("Palettised video must be BI_RGB"); - return FALSE; - } - - // Check the number of palette colours is correct - - if (pInput->bmiHeader.biClrUsed > PALETTE_ENTRIES(pInput)) { - NOTE("Too many colours in palette"); - return FALSE; - } - - // The number of important colours shouldn't exceed the number used - - if (pInput->bmiHeader.biClrImportant > pInput->bmiHeader.biClrUsed) { - NOTE("Too many important colours"); - return FALSE; - } - return TRUE; -} - - -// Return the format of the video display - -const VIDEOINFO *CImageDisplay::GetDisplayFormat() -{ - return &m_Display; -} - - -// Return TRUE if the display uses a palette - -BOOL CImageDisplay::IsPalettised() -{ - return PALETTISED(&m_Display); -} - - -// Return the bit depth of the current display setting - -WORD CImageDisplay::GetDisplayDepth() -{ - return m_Display.bmiHeader.biBitCount; -} - - -// Initialise the optional fields in a VIDEOINFO. These are mainly to do with -// the source and destination rectangles and palette information such as the -// number of colours present. It simplifies our code just a little if we don't -// have to keep checking for all the different valid permutations in a header -// every time we want to do anything with it (an example would be creating a -// palette). We set the base class media type before calling this function so -// that the media types between the pins match after a connection is made - -HRESULT CImageDisplay::UpdateFormat(__inout VIDEOINFO *pVideoInfo) -{ - ASSERT(pVideoInfo); - - BITMAPINFOHEADER *pbmi = HEADER(pVideoInfo); - SetRectEmpty(&pVideoInfo->rcSource); - SetRectEmpty(&pVideoInfo->rcTarget); - - // Set the number of colours explicitly - - if (PALETTISED(pVideoInfo)) { - if (pVideoInfo->bmiHeader.biClrUsed == 0) { - pVideoInfo->bmiHeader.biClrUsed = PALETTE_ENTRIES(pVideoInfo); - } - } - - // The number of important colours shouldn't exceed the number used, on - // some displays the number of important colours is not initialised when - // retrieving the display type so we set the colours used correctly - - if (pVideoInfo->bmiHeader.biClrImportant > pVideoInfo->bmiHeader.biClrUsed) { - pVideoInfo->bmiHeader.biClrImportant = PALETTE_ENTRIES(pVideoInfo); - } - - // Change the image size field to be explicit - - if (pVideoInfo->bmiHeader.biSizeImage == 0) { - pVideoInfo->bmiHeader.biSizeImage = GetBitmapSize(&pVideoInfo->bmiHeader); - } - return NOERROR; -} - - -// Lots of video rendering filters want code to check proposed formats are ok -// This checks the VIDEOINFO we are passed as a media type. If the media type -// is a valid media type then we return NOERROR otherwise E_INVALIDARG. Note -// however we only accept formats that can be easily displayed in the display -// so if we are on a 16 bit device we will not accept 24 bit images. The one -// complexity is that most displays draw 8 bit palettised images efficiently -// Also if the input format is less colour bits per pixel then we also accept - -HRESULT CImageDisplay::CheckVideoType(const VIDEOINFO *pInput) -{ - // First of all check the VIDEOINFOHEADER looks correct - - if (CheckHeaderValidity(pInput) == FALSE) { - return E_INVALIDARG; - } - - // Virtually all devices support palettised images efficiently - - if (m_Display.bmiHeader.biBitCount == pInput->bmiHeader.biBitCount) { - if (PALETTISED(pInput) == TRUE) { - ASSERT(PALETTISED(&m_Display) == TRUE); - NOTE("(Video) Type connection ACCEPTED"); - return NOERROR; - } - } - - - // Is the display depth greater than the input format - - if (m_Display.bmiHeader.biBitCount > pInput->bmiHeader.biBitCount) { - NOTE("(Video) Mismatch agreed"); - return NOERROR; - } - - // Is the display depth less than the input format - - if (m_Display.bmiHeader.biBitCount < pInput->bmiHeader.biBitCount) { - NOTE("(Video) Format mismatch"); - return E_INVALIDARG; - } - - - // Both input and display formats are either BI_RGB or BI_BITFIELDS - - ASSERT(m_Display.bmiHeader.biBitCount == pInput->bmiHeader.biBitCount); - ASSERT(PALETTISED(pInput) == FALSE); - ASSERT(PALETTISED(&m_Display) == FALSE); - - // BI_RGB 16 bit representation is implicitly RGB555, and likewise BI_RGB - // 24 bit representation is RGB888. So we initialise a pointer to the bit - // fields they really mean and check against the display device format - // This is only going to be called when both formats are equal bits pixel - - const DWORD *pInputMask = GetBitMasks(pInput); - const DWORD *pDisplayMask = GetBitMasks((VIDEOINFO *)&m_Display); - - if (pInputMask[iRED] != pDisplayMask[iRED] || - pInputMask[iGREEN] != pDisplayMask[iGREEN] || - pInputMask[iBLUE] != pDisplayMask[iBLUE]) { - - NOTE("(Video) Bit field mismatch"); - return E_INVALIDARG; - } - - NOTE("(Video) Type connection ACCEPTED"); - return NOERROR; -} - - -// Return the bit masks for the true colour VIDEOINFO provided - -const DWORD *CImageDisplay::GetBitMasks(const VIDEOINFO *pVideoInfo) -{ - static const DWORD FailMasks[] = {0,0,0}; - - if (pVideoInfo->bmiHeader.biCompression == BI_BITFIELDS) { - return BITMASKS(pVideoInfo); - } - - ASSERT(pVideoInfo->bmiHeader.biCompression == BI_RGB); - - switch (pVideoInfo->bmiHeader.biBitCount) { - case 16: return bits555; - case 24: return bits888; - case 32: return bits888; - default: return FailMasks; - } -} - - -// Check to see if we can support media type pmtIn as proposed by the output -// pin - We first check that the major media type is video and also identify -// the media sub type. Then we thoroughly check the VIDEOINFO type provided -// As well as the contained VIDEOINFO being correct the major type must be -// video, the subtype a recognised video format and the type GUID correct - -HRESULT CImageDisplay::CheckMediaType(const CMediaType *pmtIn) -{ - // Does this have a VIDEOINFOHEADER format block - - const GUID *pFormatType = pmtIn->FormatType(); - if (*pFormatType != FORMAT_VideoInfo) { - NOTE("Format GUID not a VIDEOINFOHEADER"); - return E_INVALIDARG; - } - ASSERT(pmtIn->Format()); - - // Check the format looks reasonably ok - - ULONG Length = pmtIn->FormatLength(); - if (Length < SIZE_VIDEOHEADER) { - NOTE("Format smaller than a VIDEOHEADER"); - return E_FAIL; - } - - VIDEOINFO *pInput = (VIDEOINFO *) pmtIn->Format(); - - // Check the major type is MEDIATYPE_Video - - const GUID *pMajorType = pmtIn->Type(); - if (*pMajorType != MEDIATYPE_Video) { - NOTE("Major type not MEDIATYPE_Video"); - return E_INVALIDARG; - } - - // Check we can identify the media subtype - - const GUID *pSubType = pmtIn->Subtype(); - if (GetBitCount(pSubType) == USHRT_MAX) { - NOTE("Invalid video media subtype"); - return E_INVALIDARG; - } - return CheckVideoType(pInput); -} - - -// Given a video format described by a VIDEOINFO structure we return the mask -// that is used to obtain the range of acceptable colours for this type, for -// example, the mask for a 24 bit true colour format is 0xFF in all cases. A -// 16 bit 5:6:5 display format uses 0xF8, 0xFC and 0xF8, therefore given any -// RGB triplets we can AND them with these fields to find one that is valid - -BOOL CImageDisplay::GetColourMask(__out DWORD *pMaskRed, - __out DWORD *pMaskGreen, - __out DWORD *pMaskBlue) -{ - CAutoLock cDisplayLock(this); - *pMaskRed = 0xFF; - *pMaskGreen = 0xFF; - *pMaskBlue = 0xFF; - - // If this format is palettised then it doesn't have bit fields - - if (m_Display.bmiHeader.biBitCount < 16) { - return FALSE; - } - - // If this is a 24 bit true colour display then it can handle all the - // possible colour component ranges described by a byte. It is never - // allowed for a 24 bit colour depth image to have BI_BITFIELDS set - - if (m_Display.bmiHeader.biBitCount == 24) { - ASSERT(m_Display.bmiHeader.biCompression == BI_RGB); - return TRUE; - } - - // Calculate the mask based on the format's bit fields - - const DWORD *pBitFields = (DWORD *) GetBitMasks((VIDEOINFO *)&m_Display); - DWORD *pOutputMask[] = { pMaskRed, pMaskGreen, pMaskBlue }; - - // We know from earlier testing that there are no more than iMAXBITS - // bits set in the mask and that they are all contiguous. All that - // therefore remains is to shift them into the correct position - - for (INT iColour = iRED;iColour <= iBLUE;iColour++) { - - // This works out how many bits there are and where they live - - DWORD PrefixBits = CountPrefixBits(pBitFields[iColour]); - DWORD SetBits = CountSetBits(pBitFields[iColour]); - - // The first shift moves the bit field so that it is right justified - // in the DWORD, after which we then shift it back left which then - // puts the leading bit in the bytes most significant bit position - - *(pOutputMask[iColour]) = pBitFields[iColour] >> PrefixBits; - *(pOutputMask[iColour]) <<= (iMAXBITS - SetBits); - } - return TRUE; -} - - -/* Helper to convert to VIDEOINFOHEADER2 -*/ -STDAPI ConvertVideoInfoToVideoInfo2(__inout AM_MEDIA_TYPE *pmt) -{ - if (pmt->formattype != FORMAT_VideoInfo) { - return E_INVALIDARG; - } - if (NULL == pmt->pbFormat || pmt->cbFormat < sizeof(VIDEOINFOHEADER)) { - return E_INVALIDARG; - } - VIDEOINFO *pVideoInfo = (VIDEOINFO *)pmt->pbFormat; - DWORD dwNewSize; - HRESULT hr = DWordAdd(pmt->cbFormat, sizeof(VIDEOINFOHEADER2) - sizeof(VIDEOINFOHEADER), &dwNewSize); - if (FAILED(hr)) { - return hr; - } - PVOID pvNew = CoTaskMemAlloc(dwNewSize); - if (pvNew == NULL) { - return E_OUTOFMEMORY; - } - CopyMemory(pvNew, pmt->pbFormat, FIELD_OFFSET(VIDEOINFOHEADER, bmiHeader)); - ZeroMemory((PBYTE)pvNew + FIELD_OFFSET(VIDEOINFOHEADER, bmiHeader), - sizeof(VIDEOINFOHEADER2) - sizeof(VIDEOINFOHEADER)); - CopyMemory((PBYTE)pvNew + FIELD_OFFSET(VIDEOINFOHEADER2, bmiHeader), - pmt->pbFormat + FIELD_OFFSET(VIDEOINFOHEADER, bmiHeader), - pmt->cbFormat - FIELD_OFFSET(VIDEOINFOHEADER, bmiHeader)); - VIDEOINFOHEADER2 *pVideoInfo2 = (VIDEOINFOHEADER2 *)pvNew; - pVideoInfo2->dwPictAspectRatioX = (DWORD)pVideoInfo2->bmiHeader.biWidth; - pVideoInfo2->dwPictAspectRatioY = (DWORD)abs(pVideoInfo2->bmiHeader.biHeight); - pmt->formattype = FORMAT_VideoInfo2; - CoTaskMemFree(pmt->pbFormat); - pmt->pbFormat = (PBYTE)pvNew; - pmt->cbFormat += sizeof(VIDEOINFOHEADER2) - sizeof(VIDEOINFOHEADER); - return S_OK; -} - - -// Check a media type containing VIDEOINFOHEADER -STDAPI CheckVideoInfoType(const AM_MEDIA_TYPE *pmt) -{ - if (NULL == pmt || NULL == pmt->pbFormat) { - return E_POINTER; - } - if (pmt->majortype != MEDIATYPE_Video || - pmt->formattype != FORMAT_VideoInfo || - pmt->cbFormat < sizeof(VIDEOINFOHEADER)) { - return VFW_E_TYPE_NOT_ACCEPTED; - } - const VIDEOINFOHEADER *pHeader = (const VIDEOINFOHEADER *)pmt->pbFormat; - if (!ValidateBitmapInfoHeader( - &pHeader->bmiHeader, - pmt->cbFormat - FIELD_OFFSET(VIDEOINFOHEADER, bmiHeader))) { - return VFW_E_TYPE_NOT_ACCEPTED; - } - - return S_OK; -} - -// Check a media type containing VIDEOINFOHEADER2 -STDAPI CheckVideoInfo2Type(const AM_MEDIA_TYPE *pmt) -{ - if (NULL == pmt || NULL == pmt->pbFormat) { - return E_POINTER; - } - if (pmt->majortype != MEDIATYPE_Video || - pmt->formattype != FORMAT_VideoInfo2 || - pmt->cbFormat < sizeof(VIDEOINFOHEADER2)) { - return VFW_E_TYPE_NOT_ACCEPTED; - } - const VIDEOINFOHEADER2 *pHeader = (const VIDEOINFOHEADER2 *)pmt->pbFormat; - if (!ValidateBitmapInfoHeader( - &pHeader->bmiHeader, - pmt->cbFormat - FIELD_OFFSET(VIDEOINFOHEADER2, bmiHeader))) { - return VFW_E_TYPE_NOT_ACCEPTED; - } - - return S_OK; -} diff --git a/third_party/BaseClasses/winutil.h b/third_party/BaseClasses/winutil.h deleted file mode 100644 index 6bd62354..00000000 --- a/third_party/BaseClasses/winutil.h +++ /dev/null @@ -1,419 +0,0 @@ -//------------------------------------------------------------------------------ -// File: WinUtil.h -// -// Desc: DirectShow base classes - defines generic handler classes. -// -// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. -//------------------------------------------------------------------------------ - - -// Make sure that you call PrepareWindow to initialise the window after -// the object has been constructed. It is a separate method so that -// derived classes can override useful methods like MessageLoop. Also -// any derived class must call DoneWithWindow in its destructor. If it -// doesn't a message may be retrieved and call a derived class member -// function while a thread is executing the base class destructor code - -#ifndef __WINUTIL__ -#define __WINUTIL__ - -const int DEFWIDTH = 320; // Initial window width -const int DEFHEIGHT = 240; // Initial window height -const int CAPTION = 256; // Maximum length of caption -const int TIMELENGTH = 50; // Maximum length of times -const int PROFILESTR = 128; // Normal profile string -const WORD PALVERSION = 0x300; // GDI palette version -const LONG PALETTE_VERSION = (LONG) 1; // Initial palette version -const COLORREF VIDEO_COLOUR = 0; // Defaults to black background -const HANDLE hMEMORY = (HANDLE) (-1); // Says to open as memory file - -#define WIDTH(x) ((*(x)).right - (*(x)).left) -#define HEIGHT(x) ((*(x)).bottom - (*(x)).top) -#define SHOWSTAGE TEXT("WM_SHOWSTAGE") -#define SHOWSTAGETOP TEXT("WM_SHOWSTAGETOP") -#define REALIZEPALETTE TEXT("WM_REALIZEPALETTE") - -class AM_NOVTABLE CBaseWindow -{ -protected: - - HINSTANCE m_hInstance; // Global module instance handle - HWND m_hwnd; // Handle for our window - HDC m_hdc; // Device context for the window - LONG m_Width; // Client window width - LONG m_Height; // Client window height - BOOL m_bActivated; // Has the window been activated - LPTSTR m_pClassName; // Static string holding class name - DWORD m_ClassStyles; // Passed in to our constructor - DWORD m_WindowStyles; // Likewise the initial window styles - DWORD m_WindowStylesEx; // And the extended window styles - UINT m_ShowStageMessage; // Have the window shown with focus - UINT m_ShowStageTop; // Makes the window WS_EX_TOPMOST - UINT m_RealizePalette; // Makes us realize our new palette - HDC m_MemoryDC; // Used for fast BitBlt operations - HPALETTE m_hPalette; // Handle to any palette we may have - BYTE m_bNoRealize; // Don't realize palette now - BYTE m_bBackground; // Should we realise in background - BYTE m_bRealizing; // already realizing the palette - CCritSec m_WindowLock; // Serialise window object access - BOOL m_bDoGetDC; // Should this window get a DC - bool m_bDoPostToDestroy; // Use PostMessage to destroy - CCritSec m_PaletteLock; // This lock protects m_hPalette. - // It should be held anytime the - // program use the value of m_hPalette. - - // Maps windows message procedure into C++ methods - friend LRESULT CALLBACK WndProc(HWND hwnd, // Window handle - UINT uMsg, // Message ID - WPARAM wParam, // First parameter - LPARAM lParam); // Other parameter - - virtual LRESULT OnPaletteChange(HWND hwnd, UINT Message); - -public: - - CBaseWindow(BOOL bDoGetDC = TRUE, bool bPostToDestroy = false); - -#ifdef DEBUG - virtual ~CBaseWindow(); -#endif - - virtual HRESULT DoneWithWindow(); - virtual HRESULT PrepareWindow(); - virtual HRESULT InactivateWindow(); - virtual HRESULT ActivateWindow(); - virtual BOOL OnSize(LONG Width, LONG Height); - virtual BOOL OnClose(); - virtual RECT GetDefaultRect(); - virtual HRESULT UninitialiseWindow(); - virtual HRESULT InitialiseWindow(HWND hwnd); - - HRESULT CompleteConnect(); - HRESULT DoCreateWindow(); - - HRESULT PerformanceAlignWindow(); - HRESULT DoShowWindow(LONG ShowCmd); - void PaintWindow(BOOL bErase); - void DoSetWindowForeground(BOOL bFocus); - virtual HRESULT SetPalette(HPALETTE hPalette); - void SetRealize(BOOL bRealize) - { - m_bNoRealize = !bRealize; - } - - // Jump over to the window thread to set the current palette - HRESULT SetPalette(); - void UnsetPalette(void); - virtual HRESULT DoRealisePalette(BOOL bForceBackground = FALSE); - - void LockPaletteLock(); - void UnlockPaletteLock(); - - virtual BOOL PossiblyEatMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) - { return FALSE; }; - - // Access our window information - - bool WindowExists(); - LONG GetWindowWidth(); - LONG GetWindowHeight(); - HWND GetWindowHWND(); - HDC GetMemoryHDC(); - HDC GetWindowHDC(); - - #ifdef DEBUG - HPALETTE GetPalette(); - #endif // DEBUG - - // This is the window procedure the derived object should override - - virtual LRESULT OnReceiveMessage(HWND hwnd, // Window handle - UINT uMsg, // Message ID - WPARAM wParam, // First parameter - LPARAM lParam); // Other parameter - - // Must be overriden to return class and window styles - - virtual LPTSTR GetClassWindowStyles( - __out DWORD *pClassStyles, // Class styles - __out DWORD *pWindowStyles, // Window styles - __out DWORD *pWindowStylesEx) PURE; // Extended styles -}; - - -// This helper class is entirely subservient to the owning CBaseWindow object -// All this object does is to split out the actual drawing operation from the -// main object (because it was becoming too large). We have a number of entry -// points to set things like the draw device contexts, to implement the actual -// drawing and to set the destination rectangle in the client window. We have -// no critical section locking in this class because we are used exclusively -// by the owning window object which looks after serialising calls into us - -// If you want to use this class make sure you call NotifyAllocator once the -// allocate has been agreed, also call NotifyMediaType with a pointer to a -// NON stack based CMediaType once that has been set (we keep a pointer to -// the original rather than taking a copy). When the palette changes call -// IncrementPaletteVersion (easiest thing to do is to also call this method -// in the SetMediaType method most filters implement). Finally before you -// start rendering anything call SetDrawContext so that we can get the HDCs -// for drawing from the CBaseWindow object we are given during construction - -class CDrawImage -{ -protected: - - CBaseWindow *m_pBaseWindow; // Owning video window object - CRefTime m_StartSample; // Start time for the current sample - CRefTime m_EndSample; // And likewise it's end sample time - HDC m_hdc; // Main window device context - HDC m_MemoryDC; // Offscreen draw device context - RECT m_TargetRect; // Target destination rectangle - RECT m_SourceRect; // Source image rectangle - BOOL m_bStretch; // Do we have to stretch the images - BOOL m_bUsingImageAllocator; // Are the samples shared DIBSECTIONs - CMediaType *m_pMediaType; // Pointer to the current format - int m_perfidRenderTime; // Time taken to render an image - LONG m_PaletteVersion; // Current palette version cookie - - // Draw the video images in the window - - void SlowRender(IMediaSample *pMediaSample); - void FastRender(IMediaSample *pMediaSample); - void DisplaySampleTimes(IMediaSample *pSample); - void UpdateColourTable(HDC hdc,__in BITMAPINFOHEADER *pbmi); - void SetStretchMode(); - -public: - - // Used to control the image drawing - - CDrawImage(__inout CBaseWindow *pBaseWindow); - BOOL DrawImage(IMediaSample *pMediaSample); - BOOL DrawVideoImageHere(HDC hdc, IMediaSample *pMediaSample, - __in LPRECT lprcSrc, __in LPRECT lprcDst); - void SetDrawContext(); - void SetTargetRect(__in RECT *pTargetRect); - void SetSourceRect(__in RECT *pSourceRect); - void GetTargetRect(__out RECT *pTargetRect); - void GetSourceRect(__out RECT *pSourceRect); - virtual RECT ScaleSourceRect(const RECT *pSource); - - // Handle updating palettes as they change - - LONG GetPaletteVersion(); - void ResetPaletteVersion(); - void IncrementPaletteVersion(); - - // Tell us media types and allocator assignments - - void NotifyAllocator(BOOL bUsingImageAllocator); - void NotifyMediaType(__in CMediaType *pMediaType); - BOOL UsingImageAllocator(); - - // Called when we are about to draw an image - - void NotifyStartDraw() { - MSR_START(m_perfidRenderTime); - }; - - // Called when we complete an image rendering - - void NotifyEndDraw() { - MSR_STOP(m_perfidRenderTime); - }; -}; - - -// This is the structure used to keep information about each GDI DIB. All the -// samples we create from our allocator will have a DIBSECTION allocated to -// them. When we receive the sample we know we can BitBlt straight to an HDC - -typedef struct tagDIBDATA { - - LONG PaletteVersion; // Current palette version in use - DIBSECTION DibSection; // Details of DIB section allocated - HBITMAP hBitmap; // Handle to bitmap for drawing - HANDLE hMapping; // Handle to shared memory block - BYTE *pBase; // Pointer to base memory address - -} DIBDATA; - - -// This class inherits from CMediaSample and uses all of it's methods but it -// overrides the constructor to initialise itself with the DIBDATA structure -// When we come to render an IMediaSample we will know if we are using our own -// allocator, and if we are, we can cast the IMediaSample to a pointer to one -// of these are retrieve the DIB section information and hence the HBITMAP - -class CImageSample : public CMediaSample -{ -protected: - - DIBDATA m_DibData; // Information about the DIBSECTION - BOOL m_bInit; // Is the DIB information setup - -public: - - // Constructor - - CImageSample(__inout CBaseAllocator *pAllocator, - __in_opt LPCTSTR pName, - __inout HRESULT *phr, - __in_bcount(length) LPBYTE pBuffer, - LONG length); - - // Maintain the DIB/DirectDraw state - - void SetDIBData(__in DIBDATA *pDibData); - __out DIBDATA *GetDIBData(); -}; - - -// This is an allocator based on the abstract CBaseAllocator base class that -// allocates sample buffers in shared memory. The number and size of these -// are determined when the output pin calls Prepare on us. The shared memory -// blocks are used in subsequent calls to GDI CreateDIBSection, once that -// has been done the output pin can fill the buffers with data which will -// then be handed to GDI through BitBlt calls and thereby remove one copy - -class CImageAllocator : public CBaseAllocator -{ -protected: - - CBaseFilter *m_pFilter; // Delegate reference counts to - CMediaType *m_pMediaType; // Pointer to the current format - - // Used to create and delete samples - - HRESULT Alloc(); - void Free(); - - // Manage the shared DIBSECTION and DCI/DirectDraw buffers - - HRESULT CreateDIB(LONG InSize,DIBDATA &DibData); - STDMETHODIMP CheckSizes(__in ALLOCATOR_PROPERTIES *pRequest); - virtual CImageSample *CreateImageSample(__in_bcount(Length) LPBYTE pData,LONG Length); - -public: - - // Constructor and destructor - - CImageAllocator(__inout CBaseFilter *pFilter,__in_opt LPCTSTR pName,__inout HRESULT *phr); -#ifdef DEBUG - ~CImageAllocator(); -#endif - - STDMETHODIMP_(ULONG) NonDelegatingAddRef(); - STDMETHODIMP_(ULONG) NonDelegatingRelease(); - void NotifyMediaType(__in CMediaType *pMediaType); - - // Agree the number of buffers to be used and their size - - STDMETHODIMP SetProperties( - __in ALLOCATOR_PROPERTIES *pRequest, - __out ALLOCATOR_PROPERTIES *pActual); -}; - - -// This class is a fairly specialised helper class for image renderers that -// have to create and manage palettes. The CBaseWindow class looks after -// realising palettes once they have been installed. This class can be used -// to create the palette handles from a media format (which must contain a -// VIDEOINFO structure in the format block). We try to make the palette an -// identity palette to maximise performance and also only change palettes -// if actually required to (we compare palette colours before updating). -// All the methods are virtual so that they can be overriden if so required - -class CImagePalette -{ -protected: - - CBaseWindow *m_pBaseWindow; // Window to realise palette in - CBaseFilter *m_pFilter; // Media filter to send events - CDrawImage *m_pDrawImage; // Object who will be drawing - HPALETTE m_hPalette; // The palette handle we own - -public: - - CImagePalette(__inout CBaseFilter *pBaseFilter, - __inout CBaseWindow *pBaseWindow, - __inout CDrawImage *pDrawImage); - -#ifdef DEBUG - virtual ~CImagePalette(); -#endif - - static HPALETTE MakePalette(const VIDEOINFOHEADER *pVideoInfo, __in LPSTR szDevice); - HRESULT RemovePalette(); - static HRESULT MakeIdentityPalette(__inout_ecount_full(iColours) PALETTEENTRY *pEntry,INT iColours, __in LPSTR szDevice); - HRESULT CopyPalette(const CMediaType *pSrc,__out CMediaType *pDest); - BOOL ShouldUpdate(const VIDEOINFOHEADER *pNewInfo,const VIDEOINFOHEADER *pOldInfo); - HRESULT PreparePalette(const CMediaType *pmtNew,const CMediaType *pmtOld,__in LPSTR szDevice); - - BOOL DrawVideoImageHere(HDC hdc, IMediaSample *pMediaSample, __in LPRECT lprcSrc, __in LPRECT lprcDst) - { - return m_pDrawImage->DrawVideoImageHere(hdc, pMediaSample, lprcSrc,lprcDst); - } -}; - - -// Another helper class really for video based renderers. Most such renderers -// need to know what the display format is to some degree or another. This -// class initialises itself with the display format. The format can be asked -// for through GetDisplayFormat and various other accessor functions. If a -// filter detects a display format change (perhaps it gets a WM_DEVMODECHANGE -// message then it can call RefreshDisplayType to reset that format). Also -// many video renderers will want to check formats as they are proposed by -// source filters. This class provides methods to check formats and only -// accept those video formats that can be efficiently drawn using GDI calls - -class CImageDisplay : public CCritSec -{ -protected: - - // This holds the display format; biSize should not be too big, so we can - // safely use the VIDEOINFO structure - VIDEOINFO m_Display; - - static DWORD CountSetBits(const DWORD Field); - static DWORD CountPrefixBits(const DWORD Field); - static BOOL CheckBitFields(const VIDEOINFO *pInput); - -public: - - // Constructor and destructor - - CImageDisplay(); - - // Used to manage BITMAPINFOHEADERs and the display format - - const VIDEOINFO *GetDisplayFormat(); - HRESULT RefreshDisplayType(__in_opt LPSTR szDeviceName); - static BOOL CheckHeaderValidity(const VIDEOINFO *pInput); - static BOOL CheckPaletteHeader(const VIDEOINFO *pInput); - BOOL IsPalettised(); - WORD GetDisplayDepth(); - - // Provide simple video format type checking - - HRESULT CheckMediaType(const CMediaType *pmtIn); - HRESULT CheckVideoType(const VIDEOINFO *pInput); - HRESULT UpdateFormat(__inout VIDEOINFO *pVideoInfo); - const DWORD *GetBitMasks(const VIDEOINFO *pVideoInfo); - - BOOL GetColourMask(__out DWORD *pMaskRed, - __out DWORD *pMaskGreen, - __out DWORD *pMaskBlue); -}; - -// Convert a FORMAT_VideoInfo to FORMAT_VideoInfo2 -STDAPI ConvertVideoInfoToVideoInfo2(__inout AM_MEDIA_TYPE *pmt); - -// Check a media type containing VIDEOINFOHEADER -STDAPI CheckVideoInfoType(const AM_MEDIA_TYPE *pmt); - -// Check a media type containing VIDEOINFOHEADER -STDAPI CheckVideoInfo2Type(const AM_MEDIA_TYPE *pmt); - -#endif // __WINUTIL__ - -- cgit v1.2.3