├── .gitignore ├── Source ├── filters.rc ├── filters.def ├── packages.config ├── filters.cpp ├── hevcdecoder.h └── Filters.vcxproj ├── Libs └── BaseClasses │ ├── BaseClasses.vcxproj.user │ ├── seekpt.h │ ├── ddmm.h │ ├── sysclock.h │ ├── perflog.h │ ├── dllsetup.h │ ├── amextra.h │ ├── sysclock.cpp │ ├── fourcc.h │ ├── seekpt.cpp │ ├── cache.h │ ├── mtype.h │ ├── reftime.h │ ├── amextra.cpp │ ├── ddmm.cpp │ ├── msgthrd.h │ ├── checkbmi.h │ ├── cprop.h │ ├── pstream.h │ ├── schedule.h │ ├── pullpin.h │ ├── outputq.h │ ├── pstream.cpp │ ├── source.h │ ├── strmctl.h │ ├── BaseClasses.vcxproj │ ├── vtrans.h │ ├── perfstruct.h │ ├── BaseClasses.vcxproj.filters │ ├── streams.h │ ├── refclock.h │ ├── videoctl.h │ ├── combase.cpp │ ├── measure.h │ ├── schedule.cpp │ ├── transip.h │ ├── perflog.cpp │ ├── amvideo.cpp │ └── transfrm.h ├── LICENSE ├── COPYING ├── README.md └── Pristine.sln /.gitignore: -------------------------------------------------------------------------------- 1 | .vs/ 2 | Debug-*/ 3 | Release-*/ 4 | /Output 5 | /packages 6 | -------------------------------------------------------------------------------- /Source/filters.rc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define VERSION_RES_BIN_NAME "Filters.ax\0" 4 | #define VERSION_RES_BIN_DESCRIPTION "Pristine - DirectShow filters\0" 5 | #define AMOVIE_SELF_REGISTER -------------------------------------------------------------------------------- /Libs/BaseClasses/BaseClasses.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Source/filters.def: -------------------------------------------------------------------------------- 1 | LIBRARY Filters.ax 2 | 3 | EXPORTS 4 | DllMain PRIVATE 5 | DllGetClassObject PRIVATE 6 | DllCanUnloadNow PRIVATE 7 | DllRegisterServer PRIVATE 8 | DllUnregisterServer PRIVATE 9 | 10 | -------------------------------------------------------------------------------- /Source/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Source/filters.cpp: -------------------------------------------------------------------------------- 1 | #include "hevcdecoder.h" 2 | 3 | CFactoryTemplate g_Templates[] = { 4 | L"Pristine: HEVC Decoder", &CLSID_PristineHevcDecoder, CPristineHevcDecoderFilter::CreateInstance, NULL, &hevcDecoderFilt, 5 | }; 6 | int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]); 7 | 8 | STDAPI DllRegisterServer() 9 | { 10 | return AMovieDllRegisterServer2(TRUE); 11 | } 12 | 13 | STDAPI DllUnregisterServer() 14 | { 15 | return AMovieDllRegisterServer2(FALSE); 16 | } 17 | 18 | extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID); 19 | 20 | BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved) 21 | { 22 | return DllEntryPoint((HINSTANCE)(hModule), dwReason, lpReserved); 23 | } -------------------------------------------------------------------------------- /Libs/BaseClasses/seekpt.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // File: SeekPT.h 3 | // 4 | // Desc: DirectShow base classes. 5 | // 6 | // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. 7 | //------------------------------------------------------------------------------ 8 | 9 | 10 | #ifndef __seekpt_h__ 11 | #define __seekpt_h__ 12 | 13 | 14 | class CSeekingPassThru : public ISeekingPassThru, public CUnknown 15 | { 16 | public: 17 | static CUnknown *CreateInstance(__inout_opt LPUNKNOWN pUnk, __inout HRESULT *phr); 18 | CSeekingPassThru(__in_opt LPCTSTR pName, __inout_opt LPUNKNOWN pUnk, __inout HRESULT *phr); 19 | ~CSeekingPassThru(); 20 | 21 | DECLARE_IUNKNOWN; 22 | STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void ** ppv); 23 | 24 | STDMETHODIMP Init(BOOL bSupportRendering, IPin *pPin); 25 | 26 | private: 27 | CPosPassThru *m_pPosPassThru; 28 | }; 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /Libs/BaseClasses/ddmm.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // File: DDMM.h 3 | // 4 | // Desc: DirectShow base classes - efines routines for using DirectDraw 5 | // on a multimonitor system. 6 | // 7 | // Copyright (c) 1995-2001 Microsoft Corporation. All rights reserved. 8 | //------------------------------------------------------------------------------ 9 | 10 | 11 | #ifdef __cplusplus 12 | extern "C" { /* Assume C declarations for C++ */ 13 | #endif /* __cplusplus */ 14 | 15 | // DDRAW.H might not include these 16 | #ifndef DDENUM_ATTACHEDSECONDARYDEVICES 17 | #define DDENUM_ATTACHEDSECONDARYDEVICES 0x00000001L 18 | #endif 19 | 20 | typedef HRESULT (*PDRAWCREATE)(IID *,LPDIRECTDRAW *,LPUNKNOWN); 21 | typedef HRESULT (*PDRAWENUM)(LPDDENUMCALLBACKA, LPVOID); 22 | 23 | IDirectDraw * DirectDrawCreateFromDevice(__in_opt LPSTR, PDRAWCREATE, PDRAWENUM); 24 | IDirectDraw * DirectDrawCreateFromDeviceEx(__in_opt LPSTR, PDRAWCREATE, LPDIRECTDRAWENUMERATEEXA); 25 | 26 | #ifdef __cplusplus 27 | } 28 | #endif /* __cplusplus */ 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 OpenIPC 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Libs/BaseClasses/sysclock.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // File: SysClock.h 3 | // 4 | // Desc: DirectShow base classes - defines a system clock implementation of 5 | // IReferenceClock. 6 | // 7 | // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. 8 | //------------------------------------------------------------------------------ 9 | 10 | 11 | #ifndef __SYSTEMCLOCK__ 12 | #define __SYSTEMCLOCK__ 13 | 14 | // 15 | // Base clock. Uses timeGetTime ONLY 16 | // Uses most of the code in the base reference clock. 17 | // Provides GetTime 18 | // 19 | 20 | class CSystemClock : public CBaseReferenceClock, public IAMClockAdjust, public IPersist 21 | { 22 | public: 23 | // We must be able to create an instance of ourselves 24 | static CUnknown * WINAPI CreateInstance(__inout_opt LPUNKNOWN pUnk, __inout HRESULT *phr); 25 | CSystemClock(__in_opt LPCTSTR pName, __inout_opt LPUNKNOWN pUnk, __inout HRESULT *phr); 26 | 27 | DECLARE_IUNKNOWN 28 | 29 | STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void ** ppv); 30 | 31 | // Yield up our class id so that we can be persisted 32 | // Implement required Ipersist method 33 | STDMETHODIMP GetClassID(__out CLSID *pClsID); 34 | 35 | // IAMClockAdjust methods 36 | STDMETHODIMP SetClockDelta(REFERENCE_TIME rtDelta); 37 | }; //CSystemClock 38 | 39 | #endif /* __SYSTEMCLOCK__ */ 40 | -------------------------------------------------------------------------------- /Libs/BaseClasses/perflog.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // File: perflog.h 3 | // 4 | // Desc: Performance logging framework. 5 | // 6 | // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. 7 | //------------------------------------------------------------------------------ 8 | 9 | typedef struct _PERFLOG_LOGGING_PARAMS { 10 | GUID ControlGuid; 11 | void (*OnStateChanged)(void); 12 | ULONG NumberOfTraceGuids; 13 | TRACE_GUID_REGISTRATION TraceGuids[ANYSIZE_ARRAY]; 14 | } PERFLOG_LOGGING_PARAMS, *PPERFLOG_LOGGING_PARAMS; 15 | 16 | BOOL 17 | PerflogInitIfEnabled( 18 | IN HINSTANCE hInstance, 19 | __in PPERFLOG_LOGGING_PARAMS LogParams 20 | ); 21 | 22 | BOOL 23 | PerflogInitialize ( 24 | __in PPERFLOG_LOGGING_PARAMS LogParams 25 | ); 26 | 27 | VOID 28 | PerflogShutdown ( 29 | VOID 30 | ); 31 | 32 | VOID 33 | PerflogTraceEvent ( 34 | __in PEVENT_TRACE_HEADER Event 35 | ); 36 | 37 | extern ULONG PerflogEnableFlags; 38 | extern UCHAR PerflogEnableLevel; 39 | extern ULONG PerflogModuleLevel; 40 | extern TRACEHANDLE PerflogTraceHandle; 41 | extern TRACEHANDLE PerflogRegHandle; 42 | 43 | #define PerflogTracingEnabled() (PerflogTraceHandle != 0) 44 | 45 | #define PerflogEvent( _x_ ) PerflogTraceEventLevel _x_ 46 | 47 | VOID 48 | PerflogTraceEventLevel( 49 | ULONG Level, 50 | __in PEVENT_TRACE_HEADER Event 51 | ); 52 | 53 | VOID 54 | PerflogTraceEvent ( 55 | __in PEVENT_TRACE_HEADER Event 56 | ); 57 | -------------------------------------------------------------------------------- /Libs/BaseClasses/dllsetup.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // File: DllSetup.h 3 | // 4 | // Desc: DirectShow base classes. 5 | // 6 | // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. 7 | //------------------------------------------------------------------------------ 8 | 9 | 10 | // To be self registering, OLE servers must 11 | // export functions named DllRegisterServer 12 | // and DllUnregisterServer. To allow use of 13 | // custom and default implementations the 14 | // defaults are named AMovieDllRegisterServer 15 | // and AMovieDllUnregisterServer. 16 | // 17 | // To the use the default implementation you 18 | // must provide stub functions. 19 | // 20 | // i.e. STDAPI DllRegisterServer() 21 | // { 22 | // return AMovieDllRegisterServer(); 23 | // } 24 | // 25 | // STDAPI DllUnregisterServer() 26 | // { 27 | // return AMovieDllUnregisterServer(); 28 | // } 29 | // 30 | // 31 | // AMovieDllRegisterServer calls IAMovieSetup.Register(), and 32 | // AMovieDllUnregisterServer calls IAMovieSetup.Unregister(). 33 | 34 | STDAPI AMovieDllRegisterServer2( BOOL ); 35 | STDAPI AMovieDllRegisterServer(); 36 | STDAPI AMovieDllUnregisterServer(); 37 | 38 | // helper functions 39 | STDAPI EliminateSubKey( HKEY, LPCTSTR ); 40 | 41 | 42 | STDAPI 43 | AMovieSetupRegisterFilter2( const AMOVIESETUP_FILTER * const psetupdata 44 | , IFilterMapper2 * pIFM2 45 | , BOOL bRegister ); 46 | 47 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | The forked baseclasses component (/Samples/Win7Samples/multimedia/directshow) from @microsoft/Windows-classic-samples is included under src/lib. 2 | A copy of the original source code may be downloaded from git+https://github.com/microsoft/Windows-classic-samples. 3 | It is accompanied by the following license and notice below: 4 | 5 | The MIT License (MIT) 6 | 7 | Copyright (c) Microsoft Corporation 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a copy 10 | of this software and associated documentation files (the "Software"), to deal 11 | in the Software without restriction, including without limitation the rights 12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | copies of the Software, and to permit persons to whom the Software is 14 | furnished to do so, subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included in 17 | all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | THE SOFTWARE. 26 | 27 | Portions of this repo are provided under the SIL Open Font License. 28 | See the LICENSE file in individual samples for additional details. 29 | 30 | --- -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![OpenIPC logo][logo] 2 | 3 | ## Pristine 4 | **_A powerful set of open source DirectShow filters for integrating IP cameras into Windows applications_** 5 | 6 | 7 | ### Overview 8 | 9 | This project mainly allows for seamless integration with hardware-accelerated and software fallback video codecs on a well-supported but deprecated multimedia framework. Unfortunately, because of this, only H.264 will ever be supported out-of-the-box. 10 | 11 | On the other hand, some third parties have come up with sets of filters that do just that, but they are either unnecessarily bulky, their licensing makes them tough to distribute or their integration is too quirky for rapid development. 12 | 13 | In our case, we will be relying on readily available internal components whose royalties have already been paid off by the provider of the underlying piece of software or hardware fullfilling the job. 14 | 15 | 16 | ### Inner workings 17 | 18 | Pristine takes an unprecedented approach to come around all the possible downsides the alternative solutions are facing by wrapping around Media Foundation "transforms" directly within DirectShow. 19 | 20 | Depending on the requested input and output types at connection time, and depending on the needed specifications, the right decoder or encoder will be attached in a transparent manner. 21 | 22 | Furthermore, appropriate COM interfaces will allow configuring advanced settings as available. 23 | 24 | 25 | ### Technical support and donations 26 | 27 | Please **_[support our project](https://openipc.org/support-open-source)_** with donations or orders for development or maintenance. Thank you! 28 | 29 | 30 | [logo]: https://openipc.org/assets/openipc-logo-black.svg -------------------------------------------------------------------------------- /Source/hevcdecoder.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | 14 | DEFINE_GUID(CLSID_PristineHevcDecoder, 15 | 0x30108958, 0xf786, 0x49C1, 0x90, 0x17, 0xC2, 0x5C, 0x64, 0x31, 0x11, 0x0A); 16 | 17 | const AMOVIESETUP_PIN hevcDecoderPins[] = 18 | { 19 | { 20 | L"Input", // Pin string name 21 | FALSE, // Is it rendered 22 | FALSE, // Is it an output 23 | FALSE, // Allowed none 24 | FALSE, // Likewise many 25 | &CLSID_NULL, // Connects to filter 26 | NULL, // Connects to pin 27 | 0, // Number of types 28 | NULL // Pin information 29 | }, 30 | { 31 | L"Output", 32 | FALSE, 33 | TRUE, 34 | FALSE, 35 | FALSE, 36 | &CLSID_NULL, 37 | NULL, 38 | 0, 39 | NULL 40 | } 41 | }; 42 | 43 | const AMOVIESETUP_FILTER hevcDecoderFilt = 44 | { 45 | &CLSID_PristineHevcDecoder, 46 | L"Pristine: HEVC Decoder", 47 | MERIT_DO_NOT_USE, 48 | 2, // Pin number 49 | hevcDecoderPins 50 | }; 51 | 52 | class CPristineHevcDecoderFilter : public CTransformFilter 53 | { 54 | 55 | public: 56 | 57 | CPristineHevcDecoderFilter(LPUNKNOWN pUnk, HRESULT* phr); 58 | ~CPristineHevcDecoderFilter(); 59 | 60 | DECLARE_IUNKNOWN; 61 | static CUnknown* WINAPI CreateInstance(LPUNKNOWN, HRESULT *); 62 | 63 | HRESULT Transform(IMediaSample *pIn, IMediaSample *pOut); 64 | HRESULT CheckInputType(const CMediaType *mtIn); 65 | HRESULT CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut); 66 | HRESULT DecideBufferSize(IMemAllocator *pAlloc, 67 | ALLOCATOR_PROPERTIES *pProperties); 68 | HRESULT GetMediaType(int iPosition, CMediaType *pMediaType); 69 | 70 | }; -------------------------------------------------------------------------------- /Libs/BaseClasses/amextra.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // File: AMExtra.h 3 | // 4 | // Desc: DirectShow base classes. 5 | // 6 | // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. 7 | //------------------------------------------------------------------------------ 8 | 9 | 10 | #ifndef __AMEXTRA__ 11 | #define __AMEXTRA__ 12 | 13 | // Simple rendered input pin 14 | // 15 | // NOTE if your filter queues stuff before rendering then it may not be 16 | // appropriate to use this class 17 | // 18 | // In that case queue the end of stream condition until the last sample 19 | // is actually rendered and flush the condition appropriately 20 | 21 | class CRenderedInputPin : public CBaseInputPin 22 | { 23 | public: 24 | 25 | CRenderedInputPin(__in_opt LPCTSTR pObjectName, 26 | __in CBaseFilter *pFilter, 27 | __in CCritSec *pLock, 28 | __inout HRESULT *phr, 29 | __in_opt LPCWSTR pName); 30 | #ifdef UNICODE 31 | CRenderedInputPin(__in_opt LPCSTR pObjectName, 32 | __in CBaseFilter *pFilter, 33 | __in CCritSec *pLock, 34 | __inout HRESULT *phr, 35 | __in_opt LPCWSTR pName); 36 | #endif 37 | 38 | // Override methods to track end of stream state 39 | STDMETHODIMP EndOfStream(); 40 | STDMETHODIMP EndFlush(); 41 | 42 | HRESULT Active(); 43 | HRESULT Run(REFERENCE_TIME tStart); 44 | 45 | protected: 46 | 47 | // Member variables to track state 48 | BOOL m_bAtEndOfStream; // Set by EndOfStream 49 | BOOL m_bCompleteNotified; // Set when we notify for EC_COMPLETE 50 | 51 | private: 52 | void DoCompleteHandling(); 53 | }; 54 | 55 | #endif // __AMEXTRA__ 56 | 57 | -------------------------------------------------------------------------------- /Pristine.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.3.32819.101 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BaseClasses", "Libs\BaseClasses\BaseClasses.vcxproj", "{E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Filters", "Source\Filters.vcxproj", "{24DCC163-C62A-4043-BBBD-BBCC740629DA}" 9 | ProjectSection(ProjectDependencies) = postProject 10 | {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA} = {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA} 11 | EndProjectSection 12 | EndProject 13 | Global 14 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 15 | Debug|Win32 = Debug|Win32 16 | Debug|x64 = Debug|x64 17 | Release|Win32 = Release|Win32 18 | Release|x64 = Release|x64 19 | EndGlobalSection 20 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 21 | {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug|Win32.ActiveCfg = Debug|Win32 22 | {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug|Win32.Build.0 = Debug|Win32 23 | {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug|x64.ActiveCfg = Debug|x64 24 | {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug|x64.Build.0 = Debug|x64 25 | {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release|Win32.ActiveCfg = Release|Win32 26 | {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release|Win32.Build.0 = Release|Win32 27 | {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release|x64.ActiveCfg = Release|x64 28 | {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release|x64.Build.0 = Release|x64 29 | {24DCC163-C62A-4043-BBBD-BBCC740629DA}.Debug|Win32.ActiveCfg = Debug|Win32 30 | {24DCC163-C62A-4043-BBBD-BBCC740629DA}.Debug|Win32.Build.0 = Debug|Win32 31 | {24DCC163-C62A-4043-BBBD-BBCC740629DA}.Debug|x64.ActiveCfg = Debug|x64 32 | {24DCC163-C62A-4043-BBBD-BBCC740629DA}.Debug|x64.Build.0 = Debug|x64 33 | {24DCC163-C62A-4043-BBBD-BBCC740629DA}.Release|Win32.ActiveCfg = Release|Win32 34 | {24DCC163-C62A-4043-BBBD-BBCC740629DA}.Release|Win32.Build.0 = Release|Win32 35 | {24DCC163-C62A-4043-BBBD-BBCC740629DA}.Release|x64.ActiveCfg = Release|x64 36 | {24DCC163-C62A-4043-BBBD-BBCC740629DA}.Release|x64.Build.0 = Release|x64 37 | EndGlobalSection 38 | GlobalSection(SolutionProperties) = preSolution 39 | HideSolutionNode = FALSE 40 | EndGlobalSection 41 | EndGlobal -------------------------------------------------------------------------------- /Libs/BaseClasses/sysclock.cpp: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // File: SysClock.cpp 3 | // 4 | // Desc: DirectShow base classes - implements a system clock based on 5 | // IReferenceClock. 6 | // 7 | // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. 8 | //------------------------------------------------------------------------------ 9 | 10 | 11 | #include 12 | #include 13 | 14 | 15 | #ifdef FILTER_DLL 16 | 17 | /* List of class IDs and creator functions for the class factory. This 18 | provides the link between the OLE entry point in the DLL and an object 19 | being created. The class factory will call the static CreateInstance 20 | function when it is asked to create a CLSID_SystemClock object */ 21 | 22 | CFactoryTemplate g_Templates[1] = { 23 | {&CLSID_SystemClock, CSystemClock::CreateInstance} 24 | }; 25 | 26 | int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]); 27 | #endif 28 | 29 | /* This goes in the factory template table to create new instances */ 30 | CUnknown * WINAPI CSystemClock::CreateInstance(__inout_opt LPUNKNOWN pUnk, __inout HRESULT *phr) 31 | { 32 | return new CSystemClock(NAME("System reference clock"),pUnk, phr); 33 | } 34 | 35 | 36 | CSystemClock::CSystemClock(__in_opt LPCTSTR pName, __inout_opt LPUNKNOWN pUnk, __inout HRESULT *phr) : 37 | CBaseReferenceClock(pName, pUnk, phr) 38 | { 39 | } 40 | 41 | STDMETHODIMP CSystemClock::NonDelegatingQueryInterface( 42 | REFIID riid, 43 | __deref_out void ** ppv) 44 | { 45 | if (riid == IID_IPersist) 46 | { 47 | return GetInterface(static_cast(this), ppv); 48 | } 49 | else if (riid == IID_IAMClockAdjust) 50 | { 51 | return GetInterface(static_cast(this), ppv); 52 | } 53 | else 54 | { 55 | return CBaseReferenceClock::NonDelegatingQueryInterface(riid, ppv); 56 | } 57 | } 58 | 59 | /* Return the clock's clsid */ 60 | STDMETHODIMP 61 | CSystemClock::GetClassID(__out CLSID *pClsID) 62 | { 63 | CheckPointer(pClsID,E_POINTER); 64 | ValidateReadWritePtr(pClsID,sizeof(CLSID)); 65 | *pClsID = CLSID_SystemClock; 66 | return NOERROR; 67 | } 68 | 69 | 70 | STDMETHODIMP 71 | CSystemClock::SetClockDelta(REFERENCE_TIME rtDelta) 72 | { 73 | return SetTimeDelta(rtDelta); 74 | } 75 | -------------------------------------------------------------------------------- /Libs/BaseClasses/fourcc.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // File: FourCC.h 3 | // 4 | // Desc: DirectShow base classes. 5 | // 6 | // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. 7 | //------------------------------------------------------------------------------ 8 | 9 | 10 | // FOURCCMap 11 | // 12 | // provides a mapping between old-style multimedia format DWORDs 13 | // and new-style GUIDs. 14 | // 15 | // A range of 4 billion GUIDs has been allocated to ensure that this 16 | // mapping can be done straightforwardly one-to-one in both directions. 17 | // 18 | // January 95 19 | 20 | 21 | #ifndef __FOURCC__ 22 | #define __FOURCC__ 23 | 24 | 25 | // Multimedia format types are marked with DWORDs built from four 8-bit 26 | // chars and known as FOURCCs. New multimedia AM_MEDIA_TYPE definitions include 27 | // a subtype GUID. In order to simplify the mapping, GUIDs in the range: 28 | // XXXXXXXX-0000-0010-8000-00AA00389B71 29 | // are reserved for FOURCCs. 30 | 31 | class FOURCCMap : public GUID 32 | { 33 | 34 | public: 35 | FOURCCMap(); 36 | FOURCCMap(DWORD Fourcc); 37 | FOURCCMap(const GUID *); 38 | 39 | 40 | DWORD GetFOURCC(void); 41 | void SetFOURCC(DWORD fourcc); 42 | void SetFOURCC(const GUID *); 43 | 44 | private: 45 | void InitGUID(); 46 | }; 47 | 48 | #define GUID_Data2 0 49 | #define GUID_Data3 0x10 50 | #define GUID_Data4_1 0xaa000080 51 | #define GUID_Data4_2 0x719b3800 52 | 53 | inline void 54 | FOURCCMap::InitGUID() { 55 | Data2 = GUID_Data2; 56 | Data3 = GUID_Data3; 57 | ((DWORD *)Data4)[0] = GUID_Data4_1; 58 | ((DWORD *)Data4)[1] = GUID_Data4_2; 59 | } 60 | 61 | inline 62 | FOURCCMap::FOURCCMap() { 63 | InitGUID(); 64 | SetFOURCC( DWORD(0)); 65 | } 66 | 67 | inline 68 | FOURCCMap::FOURCCMap(DWORD fourcc) 69 | { 70 | InitGUID(); 71 | SetFOURCC(fourcc); 72 | } 73 | 74 | inline 75 | FOURCCMap::FOURCCMap(const GUID * pGuid) 76 | { 77 | InitGUID(); 78 | SetFOURCC(pGuid); 79 | } 80 | 81 | inline void 82 | FOURCCMap::SetFOURCC(const GUID * pGuid) 83 | { 84 | FOURCCMap * p = (FOURCCMap*) pGuid; 85 | SetFOURCC(p->GetFOURCC()); 86 | } 87 | 88 | inline void 89 | FOURCCMap::SetFOURCC(DWORD fourcc) 90 | { 91 | Data1 = fourcc; 92 | } 93 | 94 | inline DWORD 95 | FOURCCMap::GetFOURCC(void) 96 | { 97 | return Data1; 98 | } 99 | 100 | #endif /* __FOURCC__ */ 101 | 102 | -------------------------------------------------------------------------------- /Libs/BaseClasses/seekpt.cpp: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // File: SeekPT.cpp 3 | // 4 | // Desc: DirectShow base classes. 5 | // 6 | // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. 7 | //------------------------------------------------------------------------------ 8 | 9 | 10 | #include 11 | #include "seekpt.h" 12 | 13 | //================================================================== 14 | // CreateInstance 15 | // This goes in the factory template table to create new instances 16 | // If there is already a mapper instance - return that, else make one 17 | // and save it in a static variable so that forever after we can return that. 18 | //================================================================== 19 | 20 | CUnknown * CSeekingPassThru::CreateInstance(__inout_opt LPUNKNOWN pUnk, __inout HRESULT *phr) 21 | { 22 | return new CSeekingPassThru(NAME("Seeking PassThru"),pUnk, phr); 23 | } 24 | 25 | 26 | STDMETHODIMP CSeekingPassThru::NonDelegatingQueryInterface(REFIID riid, __deref_out void ** ppv) 27 | { 28 | if (riid == IID_ISeekingPassThru) { 29 | return GetInterface((ISeekingPassThru *) this, ppv); 30 | } else { 31 | if (m_pPosPassThru && 32 | (riid == IID_IMediaSeeking || 33 | riid == IID_IMediaPosition)) { 34 | return m_pPosPassThru->NonDelegatingQueryInterface(riid,ppv); 35 | } else { 36 | return CUnknown::NonDelegatingQueryInterface(riid, ppv); 37 | } 38 | } 39 | } 40 | 41 | 42 | CSeekingPassThru::CSeekingPassThru( __in_opt LPCTSTR pName, __inout_opt LPUNKNOWN pUnk, __inout HRESULT *phr ) 43 | : CUnknown(pName, pUnk, phr), 44 | m_pPosPassThru(NULL) 45 | { 46 | } 47 | 48 | 49 | CSeekingPassThru::~CSeekingPassThru() 50 | { 51 | delete m_pPosPassThru; 52 | } 53 | 54 | STDMETHODIMP CSeekingPassThru::Init(BOOL bRendererSeeking, IPin *pPin) 55 | { 56 | HRESULT hr = NOERROR; 57 | if (m_pPosPassThru) { 58 | hr = E_FAIL; 59 | } else { 60 | m_pPosPassThru = 61 | bRendererSeeking ? 62 | new CRendererPosPassThru( 63 | NAME("Render Seeking COM object"), 64 | (IUnknown *)this, 65 | &hr, 66 | pPin) : 67 | new CPosPassThru( 68 | NAME("Render Seeking COM object"), 69 | (IUnknown *)this, 70 | &hr, 71 | pPin); 72 | if (!m_pPosPassThru) { 73 | hr = E_OUTOFMEMORY; 74 | } else { 75 | if (FAILED(hr)) { 76 | delete m_pPosPassThru; 77 | m_pPosPassThru = NULL; 78 | } 79 | } 80 | } 81 | return hr; 82 | } 83 | 84 | -------------------------------------------------------------------------------- /Libs/BaseClasses/cache.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // File: Cache.h 3 | // 4 | // Desc: DirectShow base classes - efines a non-MFC generic cache class. 5 | // 6 | // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. 7 | //------------------------------------------------------------------------------ 8 | 9 | 10 | /* This class implements a simple cache. A cache object is instantiated 11 | with the number of items it is to hold. An item is a pointer to an 12 | object derived from CBaseObject (helps reduce memory leaks). The cache 13 | can then have objects added to it and removed from it. The cache size 14 | is fixed at construction time and may therefore run out or be flooded. 15 | If it runs out it returns a NULL pointer, if it fills up it also returns 16 | a NULL pointer instead of a pointer to the object just inserted */ 17 | 18 | /* Making these classes inherit from CBaseObject does nothing for their 19 | functionality but it allows us to check there are no memory leaks */ 20 | 21 | /* WARNING Be very careful when using this class, what it lets you do is 22 | store and retrieve objects so that you can minimise object creation 23 | which in turns improves efficiency. However the object you store is 24 | exactly the same as the object you get back which means that it short 25 | circuits the constructor initialisation phase. This means any class 26 | variables the object has (eg pointers) are highly likely to be invalid. 27 | Therefore ensure you reinitialise the object before using it again */ 28 | 29 | 30 | #ifndef __CACHE__ 31 | #define __CACHE__ 32 | 33 | 34 | class CCache : CBaseObject { 35 | 36 | /* Make copy constructor and assignment operator inaccessible */ 37 | 38 | CCache(const CCache &refCache); 39 | CCache &operator=(const CCache &refCache); 40 | 41 | private: 42 | 43 | /* These are initialised in the constructor. The first variable points to 44 | an array of pointers, each of which points to a CBaseObject derived 45 | object. The m_iCacheSize is the static fixed size for the cache and the 46 | m_iUsed defines the number of places filled with objects at any time. 47 | We fill the array of pointers from the start (ie m_ppObjects[0] first) 48 | and then only add and remove objects from the end position, so in this 49 | respect the array of object pointers should be treated as a stack */ 50 | 51 | CBaseObject **m_ppObjects; 52 | const INT m_iCacheSize; 53 | INT m_iUsed; 54 | 55 | public: 56 | 57 | CCache(__in_opt LPCTSTR pName,INT iItems); 58 | virtual ~CCache(); 59 | 60 | /* Add an item to the cache */ 61 | CBaseObject *AddToCache(__in CBaseObject *pObject); 62 | 63 | /* Remove an item from the cache */ 64 | CBaseObject *RemoveFromCache(); 65 | 66 | /* Delete all the objects held in the cache */ 67 | void RemoveAll(void); 68 | 69 | /* Return the cache size which is set during construction */ 70 | INT GetCacheSize(void) const {return m_iCacheSize;}; 71 | }; 72 | 73 | #endif /* __CACHE__ */ 74 | 75 | -------------------------------------------------------------------------------- /Libs/BaseClasses/mtype.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // File: MtType.h 3 | // 4 | // Desc: DirectShow base classes - defines a class that holds and manages 5 | // media type information. 6 | // 7 | // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. 8 | //------------------------------------------------------------------------------ 9 | 10 | 11 | #ifndef __MTYPE__ 12 | #define __MTYPE__ 13 | 14 | /* Helper class that derived pin objects can use to compare media 15 | types etc. Has same data members as the struct AM_MEDIA_TYPE defined 16 | in the streams IDL file, but also has (non-virtual) functions */ 17 | 18 | class CMediaType : public _AMMediaType { 19 | 20 | public: 21 | 22 | ~CMediaType(); 23 | CMediaType(); 24 | CMediaType(const GUID * majortype); 25 | CMediaType(const AM_MEDIA_TYPE&, __out_opt HRESULT* phr = NULL); 26 | CMediaType(const CMediaType&, __out_opt HRESULT* phr = NULL); 27 | 28 | CMediaType& operator=(const CMediaType&); 29 | CMediaType& operator=(const AM_MEDIA_TYPE&); 30 | 31 | BOOL operator == (const CMediaType&) const; 32 | BOOL operator != (const CMediaType&) const; 33 | 34 | HRESULT Set(const CMediaType& rt); 35 | HRESULT Set(const AM_MEDIA_TYPE& rt); 36 | 37 | BOOL IsValid() const; 38 | 39 | const GUID *Type() const { return &majortype;} ; 40 | void SetType(const GUID *); 41 | const GUID *Subtype() const { return &subtype;} ; 42 | void SetSubtype(const GUID *); 43 | 44 | BOOL IsFixedSize() const {return bFixedSizeSamples; }; 45 | BOOL IsTemporalCompressed() const {return bTemporalCompression; }; 46 | ULONG GetSampleSize() const; 47 | 48 | void SetSampleSize(ULONG sz); 49 | void SetVariableSize(); 50 | void SetTemporalCompression(BOOL bCompressed); 51 | 52 | // read/write pointer to format - can't change length without 53 | // calling SetFormat, AllocFormatBuffer or ReallocFormatBuffer 54 | 55 | BYTE* Format() const {return pbFormat; }; 56 | ULONG FormatLength() const { return cbFormat; }; 57 | 58 | void SetFormatType(const GUID *); 59 | const GUID *FormatType() const {return &formattype; }; 60 | BOOL SetFormat(__in_bcount(length) BYTE *pFormat, ULONG length); 61 | void ResetFormatBuffer(); 62 | BYTE* AllocFormatBuffer(ULONG length); 63 | BYTE* ReallocFormatBuffer(ULONG length); 64 | 65 | void InitMediaType(); 66 | 67 | BOOL MatchesPartial(const CMediaType* ppartial) const; 68 | BOOL IsPartiallySpecified(void) const; 69 | }; 70 | 71 | 72 | /* General purpose functions to copy and delete a task allocated AM_MEDIA_TYPE 73 | structure which is useful when using the IEnumMediaFormats interface as 74 | the implementation allocates the structures which you must later delete */ 75 | 76 | void WINAPI DeleteMediaType(__inout_opt AM_MEDIA_TYPE *pmt); 77 | AM_MEDIA_TYPE * WINAPI CreateMediaType(AM_MEDIA_TYPE const *pSrc); 78 | HRESULT WINAPI CopyMediaType(__out AM_MEDIA_TYPE *pmtTarget, const AM_MEDIA_TYPE *pmtSource); 79 | void WINAPI FreeMediaType(__inout AM_MEDIA_TYPE& mt); 80 | 81 | // Initialize a media type from a WAVEFORMATEX 82 | 83 | STDAPI CreateAudioMediaType( 84 | const WAVEFORMATEX *pwfx, 85 | __out AM_MEDIA_TYPE *pmt, 86 | BOOL bSetFormat); 87 | 88 | #endif /* __MTYPE__ */ 89 | 90 | -------------------------------------------------------------------------------- /Libs/BaseClasses/reftime.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // File: RefTime.h 3 | // 4 | // Desc: DirectShow base classes - defines CRefTime, a class that manages 5 | // reference times. 6 | // 7 | // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. 8 | //------------------------------------------------------------------------------ 9 | 10 | 11 | // 12 | // CRefTime 13 | // 14 | // Manage reference times. 15 | // Shares same data layout as REFERENCE_TIME, but adds some (nonvirtual) 16 | // functions providing simple comparison, conversion and arithmetic. 17 | // 18 | // A reference time (at the moment) is a unit of seconds represented in 19 | // 100ns units as is used in the Win32 FILETIME structure. BUT the time 20 | // a REFERENCE_TIME represents is NOT the time elapsed since 1/1/1601 it 21 | // will either be stream time or reference time depending upon context 22 | // 23 | // This class provides simple arithmetic operations on reference times 24 | // 25 | // keep non-virtual otherwise the data layout will not be the same as 26 | // REFERENCE_TIME 27 | 28 | 29 | // ----- 30 | // note that you are safe to cast a CRefTime* to a REFERENCE_TIME*, but 31 | // you will need to do so explicitly 32 | // ----- 33 | 34 | 35 | #ifndef __REFTIME__ 36 | #define __REFTIME__ 37 | 38 | 39 | const LONGLONG MILLISECONDS = (1000); // 10 ^ 3 40 | const LONGLONG NANOSECONDS = (1000000000); // 10 ^ 9 41 | const LONGLONG UNITS = (NANOSECONDS / 100); // 10 ^ 7 42 | 43 | /* Unfortunately an inline function here generates a call to __allmul 44 | - even for constants! 45 | */ 46 | #define MILLISECONDS_TO_100NS_UNITS(lMs) \ 47 | Int32x32To64((lMs), (UNITS / MILLISECONDS)) 48 | 49 | class CRefTime 50 | { 51 | public: 52 | 53 | // *MUST* be the only data member so that this class is exactly 54 | // equivalent to a REFERENCE_TIME. 55 | // Also, must be *no virtual functions* 56 | 57 | REFERENCE_TIME m_time; 58 | 59 | inline CRefTime() 60 | { 61 | // default to 0 time 62 | m_time = 0; 63 | }; 64 | 65 | inline CRefTime(LONG msecs) 66 | { 67 | m_time = MILLISECONDS_TO_100NS_UNITS(msecs); 68 | }; 69 | 70 | inline CRefTime(REFERENCE_TIME rt) 71 | { 72 | m_time = rt; 73 | }; 74 | 75 | inline operator REFERENCE_TIME() const 76 | { 77 | return m_time; 78 | }; 79 | 80 | inline CRefTime& operator=(const CRefTime& rt) 81 | { 82 | m_time = rt.m_time; 83 | return *this; 84 | }; 85 | 86 | inline CRefTime& operator=(const LONGLONG ll) 87 | { 88 | m_time = ll; 89 | return *this; 90 | }; 91 | 92 | inline CRefTime& operator+=(const CRefTime& rt) 93 | { 94 | return (*this = *this + rt); 95 | }; 96 | 97 | inline CRefTime& operator-=(const CRefTime& rt) 98 | { 99 | return (*this = *this - rt); 100 | }; 101 | 102 | inline LONG Millisecs(void) 103 | { 104 | return (LONG)(m_time / (UNITS / MILLISECONDS)); 105 | }; 106 | 107 | inline LONGLONG GetUnits(void) 108 | { 109 | return m_time; 110 | }; 111 | }; 112 | 113 | const LONGLONG TimeZero = 0; 114 | 115 | #endif /* __REFTIME__ */ 116 | 117 | -------------------------------------------------------------------------------- /Libs/BaseClasses/amextra.cpp: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // File: AMExtra.cpp 3 | // 4 | // Desc: DirectShow base classes - implements CRenderedInputPin class. 5 | // 6 | // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. 7 | //------------------------------------------------------------------------------ 8 | 9 | 10 | #include // DirectShow base class definitions 11 | #include // Needed for definition of timeGetTime 12 | #include // Standard data type limit definitions 13 | #include // Used for time critical log functions 14 | 15 | #include "amextra.h" 16 | 17 | #pragma warning(disable:4355) 18 | 19 | // Implements CRenderedInputPin class 20 | 21 | CRenderedInputPin::CRenderedInputPin(__in_opt LPCTSTR pObjectName, 22 | __in CBaseFilter *pFilter, 23 | __in CCritSec *pLock, 24 | __inout HRESULT *phr, 25 | __in_opt LPCWSTR pName) : 26 | CBaseInputPin(pObjectName, pFilter, pLock, phr, pName), 27 | m_bAtEndOfStream(FALSE), 28 | m_bCompleteNotified(FALSE) 29 | { 30 | } 31 | #ifdef UNICODE 32 | CRenderedInputPin::CRenderedInputPin(__in_opt LPCSTR pObjectName, 33 | __in CBaseFilter *pFilter, 34 | __in CCritSec *pLock, 35 | __inout HRESULT *phr, 36 | __in_opt LPCWSTR pName) : 37 | CBaseInputPin(pObjectName, pFilter, pLock, phr, pName), 38 | m_bAtEndOfStream(FALSE), 39 | m_bCompleteNotified(FALSE) 40 | { 41 | } 42 | #endif 43 | 44 | // Flush end of stream condition - caller should do any 45 | // necessary stream level locking before calling this 46 | 47 | STDMETHODIMP CRenderedInputPin::EndOfStream() 48 | { 49 | HRESULT hr = CheckStreaming(); 50 | 51 | // Do EC_COMPLETE handling for rendered pins 52 | if (S_OK == hr && !m_bAtEndOfStream) { 53 | m_bAtEndOfStream = TRUE; 54 | FILTER_STATE fs; 55 | EXECUTE_ASSERT(SUCCEEDED(m_pFilter->GetState(0, &fs))); 56 | if (fs == State_Running) { 57 | DoCompleteHandling(); 58 | } 59 | } 60 | return hr; 61 | } 62 | 63 | 64 | // Called to complete the flush 65 | 66 | STDMETHODIMP CRenderedInputPin::EndFlush() 67 | { 68 | CAutoLock lck(m_pLock); 69 | 70 | // Clean up renderer state 71 | m_bAtEndOfStream = FALSE; 72 | m_bCompleteNotified = FALSE; 73 | 74 | return CBaseInputPin::EndFlush(); 75 | } 76 | 77 | 78 | // Notify of Run() from filter 79 | 80 | HRESULT CRenderedInputPin::Run(REFERENCE_TIME tStart) 81 | { 82 | UNREFERENCED_PARAMETER(tStart); 83 | m_bCompleteNotified = FALSE; 84 | if (m_bAtEndOfStream) { 85 | DoCompleteHandling(); 86 | } 87 | return S_OK; 88 | } 89 | 90 | 91 | // Clear status on going into paused state 92 | 93 | HRESULT CRenderedInputPin::Active() 94 | { 95 | m_bAtEndOfStream = FALSE; 96 | m_bCompleteNotified = FALSE; 97 | return CBaseInputPin::Active(); 98 | } 99 | 100 | 101 | // Do stuff to deliver end of stream 102 | 103 | void CRenderedInputPin::DoCompleteHandling() 104 | { 105 | ASSERT(m_bAtEndOfStream); 106 | if (!m_bCompleteNotified) { 107 | m_bCompleteNotified = TRUE; 108 | m_pFilter->NotifyEvent(EC_COMPLETE, S_OK, (LONG_PTR)(IBaseFilter *)m_pFilter); 109 | } 110 | } 111 | 112 | -------------------------------------------------------------------------------- /Libs/BaseClasses/ddmm.cpp: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // File: DDMM.cpp 3 | // 4 | // Desc: DirectShow base classes - implements routines for using DirectDraw 5 | // on a multimonitor system. 6 | // 7 | // Copyright (c) 1995-2001 Microsoft Corporation. All rights reserved. 8 | //------------------------------------------------------------------------------ 9 | 10 | 11 | #include 12 | #include 13 | #include "ddmm.h" 14 | 15 | /* 16 | * FindDeviceCallback 17 | */ 18 | typedef struct { 19 | LPSTR szDevice; 20 | GUID* lpGUID; 21 | GUID GUID; 22 | BOOL fFound; 23 | } FindDeviceData; 24 | 25 | BOOL CALLBACK FindDeviceCallback(__in_opt GUID* lpGUID, __in LPSTR szName, __in LPSTR szDevice, __in LPVOID lParam) 26 | { 27 | FindDeviceData *p = (FindDeviceData*)lParam; 28 | 29 | if (lstrcmpiA(p->szDevice, szDevice) == 0) { 30 | if (lpGUID) { 31 | p->GUID = *lpGUID; 32 | p->lpGUID = &p->GUID; 33 | } else { 34 | p->lpGUID = NULL; 35 | } 36 | p->fFound = TRUE; 37 | return FALSE; 38 | } 39 | return TRUE; 40 | } 41 | 42 | 43 | BOOL CALLBACK FindDeviceCallbackEx(__in_opt GUID* lpGUID, __in LPSTR szName, __in LPSTR szDevice, __in LPVOID lParam, HMONITOR hMonitor) 44 | { 45 | FindDeviceData *p = (FindDeviceData*)lParam; 46 | 47 | if (lstrcmpiA(p->szDevice, szDevice) == 0) { 48 | if (lpGUID) { 49 | p->GUID = *lpGUID; 50 | p->lpGUID = &p->GUID; 51 | } else { 52 | p->lpGUID = NULL; 53 | } 54 | p->fFound = TRUE; 55 | return FALSE; 56 | } 57 | return TRUE; 58 | } 59 | 60 | 61 | /* 62 | * DirectDrawCreateFromDevice 63 | * 64 | * create a DirectDraw object for a particular device 65 | */ 66 | IDirectDraw * DirectDrawCreateFromDevice(__in_opt LPSTR szDevice, PDRAWCREATE DirectDrawCreateP, PDRAWENUM DirectDrawEnumerateP) 67 | { 68 | IDirectDraw* pdd = NULL; 69 | FindDeviceData find; 70 | 71 | if (szDevice == NULL) { 72 | DirectDrawCreateP(NULL, &pdd, NULL); 73 | return pdd; 74 | } 75 | 76 | find.szDevice = szDevice; 77 | find.fFound = FALSE; 78 | DirectDrawEnumerateP(FindDeviceCallback, (LPVOID)&find); 79 | 80 | if (find.fFound) 81 | { 82 | // 83 | // In 4bpp mode the following DDraw call causes a message box to be popped 84 | // up by DDraw (!?!). It's DDraw's fault, but we don't like it. So we 85 | // make sure it doesn't happen. 86 | // 87 | UINT ErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS); 88 | DirectDrawCreateP(find.lpGUID, &pdd, NULL); 89 | SetErrorMode(ErrorMode); 90 | } 91 | 92 | return pdd; 93 | } 94 | 95 | 96 | /* 97 | * DirectDrawCreateFromDeviceEx 98 | * 99 | * create a DirectDraw object for a particular device 100 | */ 101 | IDirectDraw * DirectDrawCreateFromDeviceEx(__in_opt LPSTR szDevice, PDRAWCREATE DirectDrawCreateP, LPDIRECTDRAWENUMERATEEXA DirectDrawEnumerateExP) 102 | { 103 | IDirectDraw* pdd = NULL; 104 | FindDeviceData find; 105 | 106 | if (szDevice == NULL) { 107 | DirectDrawCreateP(NULL, &pdd, NULL); 108 | return pdd; 109 | } 110 | 111 | find.szDevice = szDevice; 112 | find.fFound = FALSE; 113 | DirectDrawEnumerateExP(FindDeviceCallbackEx, (LPVOID)&find, 114 | DDENUM_ATTACHEDSECONDARYDEVICES); 115 | 116 | if (find.fFound) 117 | { 118 | // 119 | // In 4bpp mode the following DDraw call causes a message box to be popped 120 | // up by DDraw (!?!). It's DDraw's fault, but we don't like it. So we 121 | // make sure it doesn't happen. 122 | // 123 | UINT ErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS); 124 | DirectDrawCreateP(find.lpGUID, &pdd, NULL); 125 | SetErrorMode(ErrorMode); 126 | } 127 | 128 | return pdd; 129 | } 130 | -------------------------------------------------------------------------------- /Libs/BaseClasses/msgthrd.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // File: MsgThrd.h 3 | // 4 | // Desc: DirectShow base classes - provides support for a worker thread 5 | // class to which one can asynchronously post messages. 6 | // 7 | // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. 8 | //------------------------------------------------------------------------------ 9 | 10 | 11 | // Message class - really just a structure. 12 | // 13 | class CMsg { 14 | public: 15 | UINT uMsg; 16 | DWORD dwFlags; 17 | LPVOID lpParam; 18 | CAMEvent *pEvent; 19 | 20 | CMsg(UINT u, DWORD dw, __inout_opt LPVOID lp, __in_opt CAMEvent *pEvnt) 21 | : uMsg(u), dwFlags(dw), lpParam(lp), pEvent(pEvnt) {} 22 | 23 | CMsg() 24 | : uMsg(0), dwFlags(0L), lpParam(NULL), pEvent(NULL) {} 25 | }; 26 | 27 | // This is the actual thread class. It exports all the usual thread control 28 | // functions. The created thread is different from a normal WIN32 thread in 29 | // that it is prompted to perform particaular tasks by responding to messages 30 | // posted to its message queue. 31 | // 32 | class AM_NOVTABLE CMsgThread { 33 | private: 34 | static DWORD WINAPI DefaultThreadProc(__inout LPVOID lpParam); 35 | DWORD m_ThreadId; 36 | HANDLE m_hThread; 37 | 38 | protected: 39 | 40 | // if you want to override GetThreadMsg to block on other things 41 | // as well as this queue, you need access to this 42 | CGenericList m_ThreadQueue; 43 | CCritSec m_Lock; 44 | HANDLE m_hSem; 45 | LONG m_lWaiting; 46 | 47 | public: 48 | CMsgThread() 49 | : m_ThreadId(0), 50 | m_hThread(NULL), 51 | m_lWaiting(0), 52 | m_hSem(NULL), 53 | // make a list with a cache of 5 items 54 | m_ThreadQueue(NAME("MsgThread list"), 5) 55 | { 56 | } 57 | 58 | ~CMsgThread(); 59 | // override this if you want to block on other things as well 60 | // as the message loop 61 | void virtual GetThreadMsg(__out CMsg *msg); 62 | 63 | // override this if you want to do something on thread startup 64 | virtual void OnThreadInit() { 65 | }; 66 | 67 | BOOL CreateThread(); 68 | 69 | BOOL WaitForThreadExit(__out LPDWORD lpdwExitCode) { 70 | if (m_hThread != NULL) { 71 | WaitForSingleObject(m_hThread, INFINITE); 72 | return GetExitCodeThread(m_hThread, lpdwExitCode); 73 | } 74 | return FALSE; 75 | } 76 | 77 | DWORD ResumeThread() { 78 | return ::ResumeThread(m_hThread); 79 | } 80 | 81 | DWORD SuspendThread() { 82 | return ::SuspendThread(m_hThread); 83 | } 84 | 85 | int GetThreadPriority() { 86 | return ::GetThreadPriority(m_hThread); 87 | } 88 | 89 | BOOL SetThreadPriority(int nPriority) { 90 | return ::SetThreadPriority(m_hThread, nPriority); 91 | } 92 | 93 | HANDLE GetThreadHandle() { 94 | return m_hThread; 95 | } 96 | 97 | DWORD GetThreadId() { 98 | return m_ThreadId; 99 | } 100 | 101 | 102 | void PutThreadMsg(UINT uMsg, DWORD dwMsgFlags, 103 | __in_opt LPVOID lpMsgParam, __in_opt CAMEvent *pEvent = NULL) { 104 | CAutoLock lck(&m_Lock); 105 | CMsg* pMsg = new CMsg(uMsg, dwMsgFlags, lpMsgParam, pEvent); 106 | m_ThreadQueue.AddTail(pMsg); 107 | if (m_lWaiting != 0) { 108 | ReleaseSemaphore(m_hSem, m_lWaiting, 0); 109 | m_lWaiting = 0; 110 | } 111 | } 112 | 113 | // This is the function prototype of the function that the client 114 | // supplies. It is always called on the created thread, never on 115 | // the creator thread. 116 | // 117 | virtual LRESULT ThreadMessageProc( 118 | UINT uMsg, DWORD dwFlags, __inout_opt LPVOID lpParam, __in_opt CAMEvent *pEvent) = 0; 119 | }; 120 | 121 | -------------------------------------------------------------------------------- /Libs/BaseClasses/checkbmi.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 1992 - 1997 Microsoft Corporation. All Rights Reserved. 2 | 3 | #ifndef _CHECKBMI_H_ 4 | #define _CHECKBMI_H_ 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | // Helper 11 | __inline BOOL MultiplyCheckOverflow(DWORD a, DWORD b, __deref_out_range(==, a * b) DWORD *pab) { 12 | *pab = a * b; 13 | if ((a == 0) || (((*pab) / a) == b)) { 14 | return TRUE; 15 | } 16 | return FALSE; 17 | } 18 | 19 | 20 | // Checks if the fields in a BITMAPINFOHEADER won't generate 21 | // overlows and buffer overruns 22 | // This is not a complete check and does not guarantee code using this structure will be secure 23 | // from attack 24 | // Bugs this is guarding against: 25 | // 1. Total structure size calculation overflowing 26 | // 2. biClrUsed > 256 for 8-bit palettized content 27 | // 3. Total bitmap size in bytes overflowing 28 | // 4. biSize < size of the base structure leading to accessessing random memory 29 | // 5. Total structure size exceeding know size of data 30 | // 31 | 32 | __success(return != 0) __inline BOOL ValidateBitmapInfoHeader( 33 | const BITMAPINFOHEADER *pbmi, // pointer to structure to check 34 | __out_range(>=, sizeof(BITMAPINFOHEADER)) DWORD cbSize // size of memory block containing structure 35 | ) 36 | { 37 | DWORD dwWidthInBytes; 38 | DWORD dwBpp; 39 | DWORD dwWidthInBits; 40 | DWORD dwHeight; 41 | DWORD dwSizeImage; 42 | DWORD dwClrUsed; 43 | 44 | // Reject bad parameters - do the size check first to avoid reading bad memory 45 | if (cbSize < sizeof(BITMAPINFOHEADER) || 46 | pbmi->biSize < sizeof(BITMAPINFOHEADER) || 47 | pbmi->biSize > 4096) { 48 | return FALSE; 49 | } 50 | 51 | // Reject 0 size 52 | if (pbmi->biWidth == 0 || pbmi->biHeight == 0) { 53 | return FALSE; 54 | } 55 | 56 | // Use bpp of 200 for validating against further overflows if not set for compressed format 57 | dwBpp = 200; 58 | 59 | if (pbmi->biBitCount > dwBpp) { 60 | return FALSE; 61 | } 62 | 63 | // Strictly speaking abs can overflow so cast explicitly to DWORD 64 | dwHeight = (DWORD)abs(pbmi->biHeight); 65 | 66 | if (!MultiplyCheckOverflow(dwBpp, (DWORD)pbmi->biWidth, &dwWidthInBits)) { 67 | return FALSE; 68 | } 69 | 70 | // Compute correct width in bytes - rounding up to 4 bytes 71 | dwWidthInBytes = (dwWidthInBits / 8 + 3) & ~3; 72 | 73 | if (!MultiplyCheckOverflow(dwWidthInBytes, dwHeight, &dwSizeImage)) { 74 | return FALSE; 75 | } 76 | 77 | // Fail if total size is 0 - this catches indivual quantities being 0 78 | // Also don't allow huge values > 1GB which might cause arithmetic 79 | // errors for users 80 | if (dwSizeImage > 0x40000000 || 81 | pbmi->biSizeImage > 0x40000000) { 82 | return FALSE; 83 | } 84 | 85 | // Fail if biClrUsed looks bad 86 | if (pbmi->biClrUsed > 256) { 87 | return FALSE; 88 | } 89 | 90 | if (pbmi->biClrUsed == 0 && pbmi->biBitCount <= 8 && pbmi->biBitCount > 0) { 91 | dwClrUsed = (1 << pbmi->biBitCount); 92 | } else { 93 | dwClrUsed = pbmi->biClrUsed; 94 | } 95 | 96 | // Check total size 97 | if (cbSize < pbmi->biSize + dwClrUsed * sizeof(RGBQUAD) + 98 | (pbmi->biCompression == BI_BITFIELDS ? 3 * sizeof(DWORD) : 0)) { 99 | return FALSE; 100 | } 101 | 102 | // If it is RGB validate biSizeImage - lots of code assumes the size is correct 103 | if (pbmi->biCompression == BI_RGB || pbmi->biCompression == BI_BITFIELDS) { 104 | if (pbmi->biSizeImage != 0) { 105 | DWORD dwBits = (DWORD)pbmi->biWidth * (DWORD)pbmi->biBitCount; 106 | DWORD dwWidthInBytes = ((DWORD)((dwBits+31) & (~31)) / 8); 107 | DWORD dwTotalSize = (DWORD)abs(pbmi->biHeight) * dwWidthInBytes; 108 | if (dwTotalSize > pbmi->biSizeImage) { 109 | return FALSE; 110 | } 111 | } 112 | } 113 | return TRUE; 114 | } 115 | 116 | #ifdef __cplusplus 117 | } 118 | #endif 119 | 120 | #endif // _CHECKBMI_H_ 121 | -------------------------------------------------------------------------------- /Libs/BaseClasses/cprop.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // File: CProp.h 3 | // 4 | // Desc: DirectShow base classes. 5 | // 6 | // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. 7 | //------------------------------------------------------------------------------ 8 | 9 | 10 | #ifndef __CPROP__ 11 | #define __CPROP__ 12 | 13 | // Base property page class. Filters typically expose custom properties by 14 | // implementing special control interfaces, examples are IDirectDrawVideo 15 | // and IQualProp on renderers. This allows property pages to be built that 16 | // use the given interface. Applications such as the ActiveMovie OCX query 17 | // filters for the property pages they support and expose them to the user 18 | // 19 | // This class provides all the framework for a property page. A property 20 | // page is a COM object that supports IPropertyPage. We should be created 21 | // with a resource ID for the dialog which we will load when required. We 22 | // should also be given in the constructor a resource ID for a title string 23 | // we will load from the DLLs STRINGTABLE. The property page titles must be 24 | // stored in resource files so that they can be easily internationalised 25 | // 26 | // We have a number of virtual methods (not PURE) that may be overriden in 27 | // derived classes to query for interfaces and so on. These functions have 28 | // simple implementations here that just return NOERROR. Derived classes 29 | // will almost definately have to override the message handler method called 30 | // OnReceiveMessage. We have a static dialog procedure that calls the method 31 | // so that derived classes don't have to fiddle around with the this pointer 32 | 33 | class AM_NOVTABLE CBasePropertyPage : public IPropertyPage, public CUnknown 34 | { 35 | protected: 36 | 37 | LPPROPERTYPAGESITE m_pPageSite; // Details for our property site 38 | HWND m_hwnd; // Window handle for the page 39 | HWND m_Dlg; // Actual dialog window handle 40 | BOOL m_bDirty; // Has anything been changed 41 | int m_TitleId; // Resource identifier for title 42 | int m_DialogId; // Dialog resource identifier 43 | 44 | static INT_PTR CALLBACK DialogProc(HWND hwnd, 45 | UINT uMsg, 46 | WPARAM wParam, 47 | LPARAM lParam); 48 | 49 | private: 50 | BOOL m_bObjectSet ; // SetObject has been called or not. 51 | public: 52 | 53 | CBasePropertyPage(__in_opt LPCTSTR pName, // Debug only name 54 | __inout_opt LPUNKNOWN pUnk, // COM Delegator 55 | int DialogId, // Resource ID 56 | int TitleId); // To get tital 57 | 58 | #ifdef UNICODE 59 | CBasePropertyPage(__in_opt LPCSTR pName, 60 | __inout_opt LPUNKNOWN pUnk, 61 | int DialogId, 62 | int TitleId); 63 | #endif 64 | virtual ~CBasePropertyPage() { }; 65 | DECLARE_IUNKNOWN 66 | 67 | // Override these virtual methods 68 | 69 | virtual HRESULT OnConnect(IUnknown *pUnknown) { return NOERROR; }; 70 | virtual HRESULT OnDisconnect() { return NOERROR; }; 71 | virtual HRESULT OnActivate() { return NOERROR; }; 72 | virtual HRESULT OnDeactivate() { return NOERROR; }; 73 | virtual HRESULT OnApplyChanges() { return NOERROR; }; 74 | virtual INT_PTR OnReceiveMessage(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam); 75 | 76 | // These implement an IPropertyPage interface 77 | 78 | STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv); 79 | STDMETHODIMP_(ULONG) NonDelegatingRelease(); 80 | STDMETHODIMP_(ULONG) NonDelegatingAddRef(); 81 | STDMETHODIMP SetPageSite(__in_opt LPPROPERTYPAGESITE pPageSite); 82 | STDMETHODIMP Activate(HWND hwndParent, LPCRECT prect,BOOL fModal); 83 | STDMETHODIMP Deactivate(void); 84 | STDMETHODIMP GetPageInfo(__out LPPROPPAGEINFO pPageInfo); 85 | STDMETHODIMP SetObjects(ULONG cObjects, __in_ecount_opt(cObjects) LPUNKNOWN *ppUnk); 86 | STDMETHODIMP Show(UINT nCmdShow); 87 | STDMETHODIMP Move(LPCRECT prect); 88 | STDMETHODIMP IsPageDirty(void) { return m_bDirty ? S_OK : S_FALSE; } 89 | STDMETHODIMP Apply(void); 90 | STDMETHODIMP Help(LPCWSTR lpszHelpDir) { return E_NOTIMPL; } 91 | STDMETHODIMP TranslateAccelerator(__inout LPMSG lpMsg) { return E_NOTIMPL; } 92 | }; 93 | 94 | #endif // __CPROP__ 95 | 96 | -------------------------------------------------------------------------------- /Libs/BaseClasses/pstream.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // File: PStream.h 3 | // 4 | // Desc: DirectShow base classes - defines a class for persistent properties 5 | // of filters. 6 | // 7 | // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. 8 | //------------------------------------------------------------------------------ 9 | 10 | 11 | #ifndef __PSTREAM__ 12 | #define __PSTREAM__ 13 | 14 | // Base class for persistent properties of filters 15 | // (i.e. filter properties in saved graphs) 16 | 17 | // The simplest way to use this is: 18 | // 1. Arrange for your filter to inherit this class 19 | // 2. Implement in your class WriteToStream and ReadFromStream 20 | // These will override the "do nothing" functions here. 21 | // 3. Change your NonDelegatingQueryInterface to handle IPersistStream 22 | // 4. Implement SizeMax to return the number of bytes of data you save. 23 | // If you save UNICODE data, don't forget a char is 2 bytes. 24 | // 5. Whenever your data changes, call SetDirty() 25 | // 26 | // At some point you may decide to alter, or extend the format of your data. 27 | // At that point you will wish that you had a version number in all the old 28 | // saved graphs, so that you can tell, when you read them, whether they 29 | // represent the old or new form. To assist you in this, this class 30 | // writes and reads a version number. 31 | // When it writes, it calls GetSoftwareVersion() to enquire what version 32 | // of the software we have at the moment. (In effect this is a version number 33 | // of the data layout in the file). It writes this as the first thing in the data. 34 | // If you want to change the version, implement (override) GetSoftwareVersion(). 35 | // It reads this from the file into mPS_dwFileVersion before calling ReadFromStream, 36 | // so in ReadFromStream you can check mPS_dwFileVersion to see if you are reading 37 | // an old version file. 38 | // Normally you should accept files whose version is no newer than the software 39 | // version that's reading them. 40 | 41 | 42 | // CPersistStream 43 | // 44 | // Implements IPersistStream. 45 | // See 'OLE Programmers Reference (Vol 1):Structured Storage Overview' for 46 | // more implementation information. 47 | class CPersistStream : public IPersistStream { 48 | private: 49 | 50 | // Internal state: 51 | 52 | protected: 53 | DWORD mPS_dwFileVersion; // version number of file (being read) 54 | BOOL mPS_fDirty; 55 | 56 | public: 57 | 58 | // IPersistStream methods 59 | 60 | STDMETHODIMP IsDirty() 61 | {return (mPS_fDirty ? S_OK : S_FALSE);} // note FALSE means clean 62 | STDMETHODIMP Load(LPSTREAM pStm); 63 | STDMETHODIMP Save(LPSTREAM pStm, BOOL fClearDirty); 64 | STDMETHODIMP GetSizeMax(__out ULARGE_INTEGER * pcbSize) 65 | // Allow 24 bytes for version. 66 | { pcbSize->QuadPart = 12*sizeof(WCHAR)+SizeMax(); return NOERROR; } 67 | 68 | // implementation 69 | 70 | CPersistStream(IUnknown *punk, __inout HRESULT *phr); 71 | ~CPersistStream(); 72 | 73 | HRESULT SetDirty(BOOL fDirty) 74 | { mPS_fDirty = fDirty; return NOERROR;} 75 | 76 | 77 | // override to reveal IPersist & IPersistStream 78 | // STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv); 79 | 80 | // --- IPersist --- 81 | 82 | // You must override this to provide your own class id 83 | STDMETHODIMP GetClassID(__out CLSID *pClsid) PURE; 84 | 85 | // overrideable if you want 86 | // file version number. Override it if you ever change format 87 | virtual DWORD GetSoftwareVersion(void) { return 0; } 88 | 89 | 90 | //========================================================================= 91 | // OVERRIDE THESE to read and write your data 92 | // OVERRIDE THESE to read and write your data 93 | // OVERRIDE THESE to read and write your data 94 | 95 | virtual int SizeMax() {return 0;} 96 | virtual HRESULT WriteToStream(IStream *pStream); 97 | virtual HRESULT ReadFromStream(IStream *pStream); 98 | //========================================================================= 99 | 100 | private: 101 | 102 | }; 103 | 104 | 105 | // --- Useful helpers --- 106 | 107 | 108 | // Writes an int to an IStream as UNICODE. 109 | STDAPI WriteInt(IStream *pIStream, int n); 110 | 111 | // inverse of WriteInt 112 | STDAPI_(int) ReadInt(IStream *pIStream, __out HRESULT &hr); 113 | 114 | #endif // __PSTREAM__ 115 | -------------------------------------------------------------------------------- /Libs/BaseClasses/schedule.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // File: Schedule.h 3 | // 4 | // Desc: DirectShow base classes. 5 | // 6 | // Copyright (c) 1996-2001 Microsoft Corporation. All rights reserved. 7 | //------------------------------------------------------------------------------ 8 | 9 | 10 | #ifndef __CAMSchedule__ 11 | #define __CAMSchedule__ 12 | 13 | class CAMSchedule : private CBaseObject 14 | { 15 | public: 16 | virtual ~CAMSchedule(); 17 | // ev is the event we should fire if the advise time needs re-evaluating 18 | CAMSchedule( HANDLE ev ); 19 | 20 | DWORD GetAdviseCount(); 21 | REFERENCE_TIME GetNextAdviseTime(); 22 | 23 | // We need a method for derived classes to add advise packets, we return the cookie 24 | DWORD_PTR AddAdvisePacket( const REFERENCE_TIME & time1, const REFERENCE_TIME & time2, HANDLE h, BOOL periodic ); 25 | // And a way to cancel 26 | HRESULT Unadvise(DWORD_PTR dwAdviseCookie); 27 | 28 | // Tell us the time please, and we'll dispatch the expired events. We return the time of the next event. 29 | // NB: The time returned will be "useless" if you start adding extra Advises. But that's the problem of 30 | // whoever is using this helper class (typically a clock). 31 | REFERENCE_TIME Advise( const REFERENCE_TIME & rtTime ); 32 | 33 | // Get the event handle which will be set if advise time requires re-evaluation. 34 | HANDLE GetEvent() const { return m_ev; } 35 | 36 | private: 37 | // We define the nodes that will be used in our singly linked list 38 | // of advise packets. The list is ordered by time, with the 39 | // elements that will expire first at the front. 40 | class CAdvisePacket 41 | { 42 | public: 43 | CAdvisePacket() 44 | {} 45 | 46 | CAdvisePacket * m_next; 47 | DWORD_PTR m_dwAdviseCookie; 48 | REFERENCE_TIME m_rtEventTime; // Time at which event should be set 49 | REFERENCE_TIME m_rtPeriod; // Periodic time 50 | HANDLE m_hNotify; // Handle to event or semephore 51 | BOOL m_bPeriodic; // TRUE => Periodic event 52 | 53 | CAdvisePacket( __inout_opt CAdvisePacket * next, LONGLONG time ) : m_next(next), m_rtEventTime(time) 54 | {} 55 | 56 | void InsertAfter( __inout CAdvisePacket * p ) 57 | { 58 | p->m_next = m_next; 59 | m_next = p; 60 | } 61 | 62 | int IsZ() const // That is, is it the node that represents the end of the list 63 | { return m_next == 0; } 64 | 65 | CAdvisePacket * RemoveNext() 66 | { 67 | CAdvisePacket *const next = m_next; 68 | CAdvisePacket *const new_next = next->m_next; 69 | m_next = new_next; 70 | return next; 71 | } 72 | 73 | void DeleteNext() 74 | { 75 | delete RemoveNext(); 76 | } 77 | 78 | CAdvisePacket * Next() const 79 | { 80 | CAdvisePacket * result = m_next; 81 | if (result->IsZ()) result = 0; 82 | return result; 83 | } 84 | 85 | DWORD_PTR Cookie() const 86 | { return m_dwAdviseCookie; } 87 | }; 88 | 89 | // Structure is: 90 | // head -> elmt1 -> elmt2 -> z -> null 91 | // So an empty list is: head -> z -> null 92 | // Having head & z as links makes insertaion, 93 | // deletion and shunting much easier. 94 | CAdvisePacket head, z; // z is both a tail and a sentry 95 | 96 | volatile DWORD_PTR m_dwNextCookie; // Strictly increasing 97 | volatile DWORD m_dwAdviseCount; // Number of elements on list 98 | 99 | CCritSec m_Serialize; 100 | 101 | // AddAdvisePacket: adds the packet, returns the cookie (0 if failed) 102 | DWORD_PTR AddAdvisePacket( __inout CAdvisePacket * pPacket ); 103 | // Event that we should set if the packed added above will be the next to fire. 104 | const HANDLE m_ev; 105 | 106 | // A Shunt is where we have changed the first element in the 107 | // list and want it re-evaluating (i.e. repositioned) in 108 | // the list. 109 | void ShuntHead(); 110 | 111 | // Rather than delete advise packets, we cache them for future use 112 | CAdvisePacket * m_pAdviseCache; 113 | DWORD m_dwCacheCount; 114 | enum { dwCacheMax = 5 }; // Don't bother caching more than five 115 | 116 | void Delete( __inout CAdvisePacket * pLink );// This "Delete" will cache the Link 117 | 118 | // Attributes and methods for debugging 119 | public: 120 | #ifdef DEBUG 121 | void DumpLinkedList(); 122 | #else 123 | void DumpLinkedList() {} 124 | #endif 125 | 126 | }; 127 | 128 | #endif // __CAMSchedule__ 129 | -------------------------------------------------------------------------------- /Libs/BaseClasses/pullpin.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // File: PullPin.h 3 | // 4 | // Desc: DirectShow base classes - defines CPullPin class. 5 | // 6 | // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. 7 | //------------------------------------------------------------------------------ 8 | 9 | 10 | #ifndef __PULLPIN_H__ 11 | #define __PULLPIN_H__ 12 | 13 | // 14 | // CPullPin 15 | // 16 | // object supporting pulling data from an IAsyncReader interface. 17 | // Given a start/stop position, calls a pure Receive method with each 18 | // IMediaSample received. 19 | // 20 | // This is essentially for use in a MemInputPin when it finds itself 21 | // connected to an IAsyncReader pin instead of a pushing pin. 22 | // 23 | 24 | class CPullPin : public CAMThread 25 | { 26 | IAsyncReader* m_pReader; 27 | REFERENCE_TIME m_tStart; 28 | REFERENCE_TIME m_tStop; 29 | REFERENCE_TIME m_tDuration; 30 | BOOL m_bSync; 31 | 32 | enum ThreadMsg { 33 | TM_Pause, // stop pulling and wait for next message 34 | TM_Start, // start pulling 35 | TM_Exit, // stop and exit 36 | }; 37 | 38 | ThreadMsg m_State; 39 | 40 | // override pure thread proc from CAMThread 41 | DWORD ThreadProc(void); 42 | 43 | // running pull method (check m_bSync) 44 | void Process(void); 45 | 46 | // clean up any cancelled i/o after a flush 47 | void CleanupCancelled(void); 48 | 49 | // suspend thread from pulling, eg during seek 50 | HRESULT PauseThread(); 51 | 52 | // start thread pulling - create thread if necy 53 | HRESULT StartThread(); 54 | 55 | // stop and close thread 56 | HRESULT StopThread(); 57 | 58 | // called from ProcessAsync to queue and collect requests 59 | HRESULT QueueSample( 60 | __inout REFERENCE_TIME& tCurrent, 61 | REFERENCE_TIME tAlignStop, 62 | BOOL bDiscontinuity); 63 | 64 | HRESULT CollectAndDeliver( 65 | REFERENCE_TIME tStart, 66 | REFERENCE_TIME tStop); 67 | 68 | HRESULT DeliverSample( 69 | IMediaSample* pSample, 70 | REFERENCE_TIME tStart, 71 | REFERENCE_TIME tStop); 72 | 73 | protected: 74 | IMemAllocator * m_pAlloc; 75 | 76 | public: 77 | CPullPin(); 78 | virtual ~CPullPin(); 79 | 80 | // returns S_OK if successfully connected to an IAsyncReader interface 81 | // from this object 82 | // Optional allocator should be proposed as a preferred allocator if 83 | // necessary 84 | // bSync is TRUE if we are to use sync reads instead of the 85 | // async methods. 86 | HRESULT Connect(IUnknown* pUnk, IMemAllocator* pAlloc, BOOL bSync); 87 | 88 | // disconnect any connection made in Connect 89 | HRESULT Disconnect(); 90 | 91 | // agree an allocator using RequestAllocator - optional 92 | // props param specifies your requirements (non-zero fields). 93 | // returns an error code if fail to match requirements. 94 | // optional IMemAllocator interface is offered as a preferred allocator 95 | // but no error occurs if it can't be met. 96 | virtual HRESULT DecideAllocator( 97 | IMemAllocator* pAlloc, 98 | __inout_opt ALLOCATOR_PROPERTIES * pProps); 99 | 100 | // set start and stop position. if active, will start immediately at 101 | // the new position. Default is 0 to duration 102 | HRESULT Seek(REFERENCE_TIME tStart, REFERENCE_TIME tStop); 103 | 104 | // return the total duration 105 | HRESULT Duration(__out REFERENCE_TIME* ptDuration); 106 | 107 | // start pulling data 108 | HRESULT Active(void); 109 | 110 | // stop pulling data 111 | HRESULT Inactive(void); 112 | 113 | // helper functions 114 | LONGLONG AlignDown(LONGLONG ll, LONG lAlign) { 115 | // aligning downwards is just truncation 116 | return ll & ~(lAlign-1); 117 | }; 118 | 119 | LONGLONG AlignUp(LONGLONG ll, LONG lAlign) { 120 | // align up: round up to next boundary 121 | return (ll + (lAlign -1)) & ~(lAlign -1); 122 | }; 123 | 124 | // GetReader returns the (addrefed) IAsyncReader interface 125 | // for SyncRead etc 126 | IAsyncReader* GetReader() { 127 | m_pReader->AddRef(); 128 | return m_pReader; 129 | }; 130 | 131 | // -- pure -- 132 | 133 | // override this to handle data arrival 134 | // return value other than S_OK will stop data 135 | virtual HRESULT Receive(IMediaSample*) PURE; 136 | 137 | // override this to handle end-of-stream 138 | virtual HRESULT EndOfStream(void) PURE; 139 | 140 | // called on runtime errors that will have caused pulling 141 | // to stop 142 | // these errors are all returned from the upstream filter, who 143 | // will have already reported any errors to the filtergraph. 144 | virtual void OnError(HRESULT hr) PURE; 145 | 146 | // flush this pin and all downstream 147 | virtual HRESULT BeginFlush() PURE; 148 | virtual HRESULT EndFlush() PURE; 149 | 150 | }; 151 | 152 | #endif //__PULLPIN_H__ 153 | -------------------------------------------------------------------------------- /Libs/BaseClasses/outputq.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // File: OutputQ.h 3 | // 4 | // Desc: DirectShow base classes - defines the COutputQueue class, which 5 | // makes a queue of samples and sends them to an output pin. The 6 | // class will optionally send the samples to the pin directly. 7 | // 8 | // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. 9 | //------------------------------------------------------------------------------ 10 | 11 | 12 | typedef CGenericList CSampleList; 13 | 14 | class COutputQueue : public CCritSec 15 | { 16 | public: 17 | // Constructor 18 | COutputQueue(IPin *pInputPin, // Pin to send stuff to 19 | __inout HRESULT *phr, // 'Return code' 20 | BOOL bAuto = TRUE, // Ask pin if blocks 21 | BOOL bQueue = TRUE, // Send through queue (ignored if 22 | // bAuto set) 23 | LONG lBatchSize = 1, // Batch 24 | BOOL bBatchExact = FALSE,// Batch exactly to BatchSize 25 | LONG lListSize = // Likely number in the list 26 | DEFAULTCACHE, 27 | DWORD dwPriority = // Priority of thread to create 28 | THREAD_PRIORITY_NORMAL, 29 | bool bFlushingOpt = false // flushing optimization 30 | ); 31 | ~COutputQueue(); 32 | 33 | // enter flush state - discard all data 34 | void BeginFlush(); // Begin flushing samples 35 | 36 | // re-enable receives (pass this downstream) 37 | void EndFlush(); // Complete flush of samples - downstream 38 | // pin guaranteed not to block at this stage 39 | 40 | void EOS(); // Call this on End of stream 41 | 42 | void SendAnyway(); // Send batched samples anyway (if bBatchExact set) 43 | 44 | void NewSegment( 45 | REFERENCE_TIME tStart, 46 | REFERENCE_TIME tStop, 47 | double dRate); 48 | 49 | HRESULT Receive(IMediaSample *pSample); 50 | 51 | // do something with these media samples 52 | HRESULT ReceiveMultiple ( 53 | __in_ecount(nSamples) IMediaSample **pSamples, 54 | long nSamples, 55 | __out long *nSamplesProcessed); 56 | 57 | void Reset(); // Reset m_hr ready for more data 58 | 59 | // See if its idle or not 60 | BOOL IsIdle(); 61 | 62 | // give the class an event to fire after everything removed from the queue 63 | void SetPopEvent(HANDLE hEvent); 64 | 65 | protected: 66 | static DWORD WINAPI InitialThreadProc(__in LPVOID pv); 67 | DWORD ThreadProc(); 68 | BOOL IsQueued() 69 | { 70 | return m_List != NULL; 71 | }; 72 | 73 | // The critical section MUST be held when this is called 74 | void QueueSample(IMediaSample *pSample); 75 | 76 | BOOL IsSpecialSample(IMediaSample *pSample) 77 | { 78 | return (DWORD_PTR)pSample > (DWORD_PTR)(LONG_PTR)(-16); 79 | }; 80 | 81 | // Remove and Release() batched and queued samples 82 | void FreeSamples(); 83 | 84 | // Notify the thread there is something to do 85 | void NotifyThread(); 86 | 87 | 88 | protected: 89 | // Queue 'messages' 90 | #define SEND_PACKET ((IMediaSample *)(LONG_PTR)(-2)) // Send batch 91 | #define EOS_PACKET ((IMediaSample *)(LONG_PTR)(-3)) // End of stream 92 | #define RESET_PACKET ((IMediaSample *)(LONG_PTR)(-4)) // Reset m_hr 93 | #define NEW_SEGMENT ((IMediaSample *)(LONG_PTR)(-5)) // send NewSegment 94 | 95 | // new segment packet is always followed by one of these 96 | struct NewSegmentPacket { 97 | REFERENCE_TIME tStart; 98 | REFERENCE_TIME tStop; 99 | double dRate; 100 | }; 101 | 102 | // Remember input stuff 103 | IPin * const m_pPin; 104 | IMemInputPin * m_pInputPin; 105 | BOOL const m_bBatchExact; 106 | LONG const m_lBatchSize; 107 | 108 | CSampleList * m_List; 109 | HANDLE m_hSem; 110 | CAMEvent m_evFlushComplete; 111 | HANDLE m_hThread; 112 | __field_ecount_opt(m_lBatchSize) IMediaSample ** m_ppSamples; 113 | __range(0, m_lBatchSize) LONG m_nBatched; 114 | 115 | // Wait optimization 116 | LONG m_lWaiting; 117 | // Flush synchronization 118 | BOOL m_bFlushing; 119 | 120 | // flushing optimization. some downstream filters have trouble 121 | // with the queue's flushing optimization. other rely on it 122 | BOOL m_bFlushed; 123 | bool m_bFlushingOpt; 124 | 125 | // Terminate now 126 | BOOL m_bTerminate; 127 | 128 | // Send anyway flag for batching 129 | BOOL m_bSendAnyway; 130 | 131 | // Deferred 'return code' 132 | HRESULT volatile m_hr; 133 | 134 | // an event that can be fired after every deliver 135 | HANDLE m_hEventPop; 136 | }; 137 | 138 | -------------------------------------------------------------------------------- /Libs/BaseClasses/pstream.cpp: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // File: PStream.cpp 3 | // 4 | // Desc: DirectShow base classes. 5 | // 6 | // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. 7 | //------------------------------------------------------------------------------ 8 | 9 | 10 | #include 11 | #include 12 | 13 | #ifdef PERF 14 | #include 15 | #endif 16 | // #include "pstream.h" in streams.h 17 | 18 | // 19 | // Constructor 20 | // 21 | CPersistStream::CPersistStream(IUnknown *punk, __inout HRESULT *phr) 22 | : mPS_fDirty(FALSE) 23 | { 24 | mPS_dwFileVersion = GetSoftwareVersion(); 25 | } 26 | 27 | 28 | // 29 | // Destructor 30 | // 31 | CPersistStream::~CPersistStream() { 32 | // Nothing to do 33 | } 34 | 35 | #if 0 36 | SAMPLE CODE TO COPY - not active at the moment 37 | 38 | // 39 | // NonDelegatingQueryInterface 40 | // 41 | // This object supports IPersist & IPersistStream 42 | STDMETHODIMP CPersistStream::NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv) 43 | { 44 | if (riid == IID_IPersist) { 45 | return GetInterface((IPersist *) this, ppv); // ??? 46 | } 47 | else if (riid == IID_IPersistStream) { 48 | return GetInterface((IPersistStream *) this, ppv); 49 | } 50 | else { 51 | return CUnknown::NonDelegatingQueryInterface(riid, ppv); 52 | } 53 | } 54 | #endif 55 | 56 | 57 | // 58 | // WriteToStream 59 | // 60 | // Writes to the stream (default action is to write nothing) 61 | HRESULT CPersistStream::WriteToStream(IStream *pStream) 62 | { 63 | // You can override this to do things like 64 | // hr = pStream->Write(MyStructure, sizeof(MyStructure), NULL); 65 | 66 | return NOERROR; 67 | } 68 | 69 | 70 | 71 | HRESULT CPersistStream::ReadFromStream(IStream * pStream) 72 | { 73 | // You can override this to do things like 74 | // hr = pStream->Read(MyStructure, sizeof(MyStructure), NULL); 75 | 76 | return NOERROR; 77 | } 78 | 79 | 80 | // 81 | // Load 82 | // 83 | // Load all the data from the given stream 84 | STDMETHODIMP CPersistStream::Load(LPSTREAM pStm) 85 | { 86 | HRESULT hr; 87 | // Load the version number then the data 88 | mPS_dwFileVersion = ReadInt(pStm, hr); 89 | if (FAILED(hr)) { 90 | return hr; 91 | } 92 | 93 | return ReadFromStream(pStm); 94 | } // Load 95 | 96 | 97 | 98 | // 99 | // Save 100 | // 101 | // Save the contents of this Stream. 102 | STDMETHODIMP CPersistStream::Save(LPSTREAM pStm, BOOL fClearDirty) 103 | { 104 | 105 | HRESULT hr = WriteInt(pStm, GetSoftwareVersion()); 106 | if (FAILED(hr)) { 107 | return hr; 108 | } 109 | 110 | hr = WriteToStream(pStm); 111 | if (FAILED(hr)) { 112 | return hr; 113 | } 114 | 115 | mPS_fDirty = !fClearDirty; 116 | 117 | return hr; 118 | } // Save 119 | 120 | 121 | // WriteInt 122 | // 123 | // Writes an integer to an IStream as 11 UNICODE characters followed by one space. 124 | // You could use this for shorts or unsigneds or anything (up to 32 bits) 125 | // where the value isn't actually truncated by squeezing it into 32 bits. 126 | // Values such as (unsigned) 0x80000000 would come out as -2147483648 127 | // but would then load as 0x80000000 through ReadInt. Cast as you please. 128 | 129 | STDAPI WriteInt(IStream *pIStream, int n) 130 | { 131 | WCHAR Buff[13]; // Allows for trailing null that we don't write 132 | (void)StringCchPrintfW(Buff, NUMELMS(Buff),L"%011d ",n); 133 | return pIStream->Write(&(Buff[0]), 12*sizeof(WCHAR), NULL); 134 | } // WriteInt 135 | 136 | 137 | // ReadInt 138 | // 139 | // Reads an integer from an IStream. 140 | // Read as 4 bytes. You could use this for shorts or unsigneds or anything 141 | // where the value isn't actually truncated by squeezing it into 32 bits 142 | // Striped down subset of what sscanf can do (without dragging in the C runtime) 143 | 144 | STDAPI_(int) ReadInt(IStream *pIStream, __out HRESULT &hr) 145 | { 146 | 147 | int Sign = 1; 148 | unsigned int n = 0; // result wil be n*Sign 149 | WCHAR wch; 150 | 151 | hr = pIStream->Read( &wch, sizeof(wch), NULL); 152 | if (FAILED(hr)) { 153 | return 0; 154 | } 155 | 156 | if (wch==L'-'){ 157 | Sign = -1; 158 | hr = pIStream->Read( &wch, sizeof(wch), NULL); 159 | if (FAILED(hr)) { 160 | return 0; 161 | } 162 | } 163 | 164 | for( ; ; ) { 165 | if (wch>=L'0' && wch<=L'9') { 166 | n = 10*n+(int)(wch-L'0'); 167 | } else if ( wch == L' ' 168 | || wch == L'\t' 169 | || wch == L'\r' 170 | || wch == L'\n' 171 | || wch == L'\0' 172 | ) { 173 | break; 174 | } else { 175 | hr = VFW_E_INVALID_FILE_FORMAT; 176 | return 0; 177 | } 178 | 179 | hr = pIStream->Read( &wch, sizeof(wch), NULL); 180 | if (FAILED(hr)) { 181 | return 0; 182 | } 183 | } 184 | 185 | if (n==0x80000000 && Sign==-1) { 186 | // This is the negative number that has no positive version! 187 | return (int)n; 188 | } 189 | else return (int)n * Sign; 190 | } // ReadInt 191 | 192 | 193 | // The microsoft C/C++ compile generates level 4 warnings to the effect that 194 | // a particular inline function (from some base class) was not needed. 195 | // This line gets rid of hundreds of such unwanted messages and makes 196 | // -W4 compilation feasible: 197 | #pragma warning(disable: 4514) 198 | -------------------------------------------------------------------------------- /Libs/BaseClasses/source.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // File: Source.h 3 | // 4 | // Desc: DirectShow base classes - defines classes to simplify creation of 5 | // ActiveX source filters that support continuous generation of data. 6 | // No support is provided for IMediaControl or IMediaPosition. 7 | // 8 | // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. 9 | //------------------------------------------------------------------------------ 10 | 11 | 12 | // 13 | // Derive your source filter from CSource. 14 | // During construction either: 15 | // Create some CSourceStream objects to manage your pins 16 | // Provide the user with a means of doing so eg, an IPersistFile interface. 17 | // 18 | // CSource provides: 19 | // IBaseFilter interface management 20 | // IMediaFilter interface management, via CBaseFilter 21 | // Pin counting for CBaseFilter 22 | // 23 | // Derive a class from CSourceStream to manage your output pin types 24 | // Implement GetMediaType/1 to return the type you support. If you support multiple 25 | // types then overide GetMediaType/3, CheckMediaType and GetMediaTypeCount. 26 | // Implement Fillbuffer() to put data into one buffer. 27 | // 28 | // CSourceStream provides: 29 | // IPin management via CBaseOutputPin 30 | // Worker thread management 31 | 32 | #ifndef __CSOURCE__ 33 | #define __CSOURCE__ 34 | 35 | class CSourceStream; // The class that will handle each pin 36 | 37 | 38 | // 39 | // CSource 40 | // 41 | // Override construction to provide a means of creating 42 | // CSourceStream derived objects - ie a way of creating pins. 43 | class CSource : public CBaseFilter { 44 | public: 45 | 46 | CSource(__in_opt LPCTSTR pName, __inout_opt LPUNKNOWN lpunk, CLSID clsid, __inout HRESULT *phr); 47 | CSource(__in_opt LPCTSTR pName, __inout_opt LPUNKNOWN lpunk, CLSID clsid); 48 | #ifdef UNICODE 49 | CSource(__in_opt LPCSTR pName, __inout_opt LPUNKNOWN lpunk, CLSID clsid, __inout HRESULT *phr); 50 | CSource(__in_opt LPCSTR pName, __inout_opt LPUNKNOWN lpunk, CLSID clsid); 51 | #endif 52 | ~CSource(); 53 | 54 | int GetPinCount(void); 55 | CBasePin *GetPin(int n); 56 | 57 | // -- Utilities -- 58 | 59 | CCritSec* pStateLock(void) { return &m_cStateLock; } // provide our critical section 60 | 61 | HRESULT AddPin(__in CSourceStream *); 62 | HRESULT RemovePin(__in CSourceStream *); 63 | 64 | STDMETHODIMP FindPin( 65 | LPCWSTR Id, 66 | __deref_out IPin ** ppPin 67 | ); 68 | 69 | int FindPinNumber(__in IPin *iPin); 70 | 71 | protected: 72 | 73 | int m_iPins; // The number of pins on this filter. Updated by CSourceStream 74 | // constructors & destructors. 75 | CSourceStream **m_paStreams; // the pins on this filter. 76 | 77 | CCritSec m_cStateLock; // Lock this to serialize function accesses to the filter state 78 | 79 | }; 80 | 81 | 82 | // 83 | // CSourceStream 84 | // 85 | // Use this class to manage a stream of data that comes from a 86 | // pin. 87 | // Uses a worker thread to put data on the pin. 88 | class CSourceStream : public CAMThread, public CBaseOutputPin { 89 | public: 90 | 91 | CSourceStream(__in_opt LPCTSTR pObjectName, 92 | __inout HRESULT *phr, 93 | __inout CSource *pms, 94 | __in_opt LPCWSTR pName); 95 | #ifdef UNICODE 96 | CSourceStream(__in_opt LPCSTR pObjectName, 97 | __inout HRESULT *phr, 98 | __inout CSource *pms, 99 | __in_opt LPCWSTR pName); 100 | #endif 101 | virtual ~CSourceStream(void); // virtual destructor ensures derived class destructors are called too. 102 | 103 | protected: 104 | 105 | CSource *m_pFilter; // The parent of this stream 106 | 107 | // * 108 | // * Data Source 109 | // * 110 | // * The following three functions: FillBuffer, OnThreadCreate/Destroy, are 111 | // * called from within the ThreadProc. They are used in the creation of 112 | // * the media samples this pin will provide 113 | // * 114 | 115 | // Override this to provide the worker thread a means 116 | // of processing a buffer 117 | virtual HRESULT FillBuffer(IMediaSample *pSamp) PURE; 118 | 119 | // Called as the thread is created/destroyed - use to perform 120 | // jobs such as start/stop streaming mode 121 | // If OnThreadCreate returns an error the thread will exit. 122 | virtual HRESULT OnThreadCreate(void) {return NOERROR;}; 123 | virtual HRESULT OnThreadDestroy(void) {return NOERROR;}; 124 | virtual HRESULT OnThreadStartPlay(void) {return NOERROR;}; 125 | 126 | // * 127 | // * Worker Thread 128 | // * 129 | 130 | HRESULT Active(void); // Starts up the worker thread 131 | HRESULT Inactive(void); // Exits the worker thread. 132 | 133 | public: 134 | // thread commands 135 | enum Command {CMD_INIT, CMD_PAUSE, CMD_RUN, CMD_STOP, CMD_EXIT}; 136 | HRESULT Init(void) { return CallWorker(CMD_INIT); } 137 | HRESULT Exit(void) { return CallWorker(CMD_EXIT); } 138 | HRESULT Run(void) { return CallWorker(CMD_RUN); } 139 | HRESULT Pause(void) { return CallWorker(CMD_PAUSE); } 140 | HRESULT Stop(void) { return CallWorker(CMD_STOP); } 141 | 142 | protected: 143 | Command GetRequest(void) { return (Command) CAMThread::GetRequest(); } 144 | BOOL CheckRequest(Command *pCom) { return CAMThread::CheckRequest( (DWORD *) pCom); } 145 | 146 | // override these if you want to add thread commands 147 | virtual DWORD ThreadProc(void); // the thread function 148 | 149 | virtual HRESULT DoBufferProcessingLoop(void); // the loop executed whilst running 150 | 151 | 152 | // * 153 | // * AM_MEDIA_TYPE support 154 | // * 155 | 156 | // If you support more than one media type then override these 2 functions 157 | virtual HRESULT CheckMediaType(const CMediaType *pMediaType); 158 | virtual HRESULT GetMediaType(int iPosition, __inout CMediaType *pMediaType); // List pos. 0-n 159 | 160 | // If you support only one type then override this fn. 161 | // This will only be called by the default implementations 162 | // of CheckMediaType and GetMediaType(int, CMediaType*) 163 | // You must override this fn. or the above 2! 164 | virtual HRESULT GetMediaType(__inout CMediaType *pMediaType) {return E_UNEXPECTED;} 165 | 166 | STDMETHODIMP QueryId( 167 | __deref_out LPWSTR * Id 168 | ); 169 | }; 170 | 171 | #endif // __CSOURCE__ 172 | 173 | -------------------------------------------------------------------------------- /Libs/BaseClasses/strmctl.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // File: StrmCtl.h 3 | // 4 | // Desc: DirectShow base classes. 5 | // 6 | // Copyright (c) 1996-2001 Microsoft Corporation. All rights reserved. 7 | //------------------------------------------------------------------------------ 8 | 9 | 10 | #ifndef __strmctl_h__ 11 | #define __strmctl_h__ 12 | 13 | class CBaseStreamControl : public IAMStreamControl 14 | { 15 | public: 16 | // Used by the implementation 17 | enum StreamControlState 18 | { STREAM_FLOWING = 0x1000, 19 | STREAM_DISCARDING 20 | }; 21 | 22 | private: 23 | enum StreamControlState m_StreamState; // Current stream state 24 | enum StreamControlState m_StreamStateOnStop; // State after next stop 25 | // (i.e.Blocking or Discarding) 26 | 27 | REFERENCE_TIME m_tStartTime; // MAX_TIME implies none 28 | REFERENCE_TIME m_tStopTime; // MAX_TIME implies none 29 | DWORD m_dwStartCookie; // Cookie for notification to app 30 | DWORD m_dwStopCookie; // Cookie for notification to app 31 | volatile BOOL m_bIsFlushing; // No optimization pls! 32 | volatile BOOL m_bStopSendExtra; // bSendExtra was set 33 | volatile BOOL m_bStopExtraSent; // the extra one was sent 34 | 35 | CCritSec m_CritSec; // CritSec to guard above attributes 36 | 37 | // Event to fire when we can come 38 | // out of blocking, or to come out of waiting 39 | // to discard if we change our minds. 40 | // 41 | CAMEvent m_StreamEvent; 42 | 43 | // All of these methods execute immediately. Helpers for others. 44 | // 45 | void ExecuteStop(); 46 | void ExecuteStart(); 47 | void CancelStop(); 48 | void CancelStart(); 49 | 50 | // Some things we need to be told by our owning filter 51 | // Your pin must also expose IAMStreamControl when QI'd for it! 52 | // 53 | IReferenceClock * m_pRefClock; // Need it to set advises 54 | // Filter must tell us via 55 | // SetSyncSource 56 | IMediaEventSink * m_pSink; // Event sink 57 | // Filter must tell us after it 58 | // creates it in JoinFilterGraph() 59 | FILTER_STATE m_FilterState; // Just need it! 60 | // Filter must tell us via 61 | // NotifyFilterState 62 | REFERENCE_TIME m_tRunStart; // Per the Run call to the filter 63 | 64 | // This guy will return one of the three StreamControlState's. Here's what 65 | // the caller should do for each one: 66 | // 67 | // STREAM_FLOWING: Proceed as usual (render or pass the sample on) 68 | // STREAM_DISCARDING: Calculate the time 'til *pSampleStop and wait 69 | // that long for the event handle 70 | // (GetStreamEventHandle()). If the wait 71 | // expires, throw the sample away. If the event 72 | // fires, call me back - I've changed my mind. 73 | // 74 | enum StreamControlState CheckSampleTimes( __in const REFERENCE_TIME * pSampleStart, 75 | __in const REFERENCE_TIME * pSampleStop ); 76 | 77 | public: 78 | // You don't have to tell us much when we're created, but there are other 79 | // obligations that must be met. See SetSyncSource & NotifyFilterState 80 | // below. 81 | // 82 | CBaseStreamControl(__inout_opt HRESULT *phr = NULL); 83 | ~CBaseStreamControl(); 84 | 85 | // If you want this class to work properly, there are thing you need to 86 | // (keep) telling it. Filters with pins that use this class 87 | // should ensure that they pass through to this method any calls they 88 | // receive on their SetSyncSource. 89 | 90 | // We need a clock to see what time it is. This is for the 91 | // "discard in a timely fashion" logic. If we discard everything as 92 | // quick as possible, a whole 60 minute file could get discarded in the 93 | // first 10 seconds, and if somebody wants to turn streaming on at 30 94 | // minutes into the file, and they make the call more than a few seconds 95 | // after the graph is run, it may be too late! 96 | // So we hold every sample until it's time has gone, then we discard it. 97 | // The filter should call this when it gets a SetSyncSource 98 | // 99 | void SetSyncSource( IReferenceClock * pRefClock ) 100 | { 101 | CAutoLock lck(&m_CritSec); 102 | if (m_pRefClock) m_pRefClock->Release(); 103 | m_pRefClock = pRefClock; 104 | if (m_pRefClock) m_pRefClock->AddRef(); 105 | } 106 | 107 | // Set event sink for notifications 108 | // The filter should call this in its JoinFilterGraph after it creates the 109 | // IMediaEventSink 110 | // 111 | void SetFilterGraph( IMediaEventSink *pSink ) { 112 | m_pSink = pSink; 113 | } 114 | 115 | // Since we schedule in stream time, we need the tStart and must track the 116 | // state of our owning filter. 117 | // The app should call this ever state change 118 | // 119 | void NotifyFilterState( FILTER_STATE new_state, REFERENCE_TIME tStart = 0 ); 120 | 121 | // Filter should call Flushing(TRUE) in BeginFlush, 122 | // and Flushing(FALSE) in EndFlush. 123 | // 124 | void Flushing( BOOL bInProgress ); 125 | 126 | 127 | // The two main methods of IAMStreamControl 128 | 129 | // Class adds default values suitable for immediate 130 | // muting and unmuting of the stream. 131 | 132 | STDMETHODIMP StopAt( const REFERENCE_TIME * ptStop = NULL, 133 | BOOL bSendExtra = FALSE, 134 | DWORD dwCookie = 0 ); 135 | STDMETHODIMP StartAt( const REFERENCE_TIME * ptStart = NULL, 136 | DWORD dwCookie = 0 ); 137 | STDMETHODIMP GetInfo( __out AM_STREAM_INFO *pInfo); 138 | 139 | // Helper function for pin's receive method. Call this with 140 | // the sample and we'll tell you what to do with it. We'll do a 141 | // WaitForSingleObject within this call if one is required. This is 142 | // a "What should I do with this sample?" kind of call. We'll tell the 143 | // caller to either flow it or discard it. 144 | // If pSample is NULL we evaluate based on the current state 145 | // settings 146 | enum StreamControlState CheckStreamState( IMediaSample * pSample ); 147 | 148 | private: 149 | // These don't require locking, but we are relying on the fact that 150 | // m_StreamState can be retrieved with integrity, and is a snap shot that 151 | // may have just been, or may be just about to be, changed. 152 | HANDLE GetStreamEventHandle() const { return m_StreamEvent; } 153 | enum StreamControlState GetStreamState() const { return m_StreamState; } 154 | BOOL IsStreaming() const { return m_StreamState == STREAM_FLOWING; } 155 | }; 156 | 157 | #endif 158 | -------------------------------------------------------------------------------- /Libs/BaseClasses/BaseClasses.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA} 23 | BaseClasses 24 | Win32Proj 25 | 26 | 27 | 28 | StaticLibrary 29 | v143 30 | Unicode 31 | Static 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | $(Configuration)-$(Platform)\ 42 | $(Configuration)-$(Platform)\Build\ 43 | 44 | 45 | 46 | .;%(AdditionalIncludeDirectories) 47 | 48 | Level3 49 | false 50 | 51 | 52 | strmiids.lib;%(AdditionalDependencies) 53 | 54 | 55 | 56 | 57 | Disabled 58 | WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) 59 | true 60 | EnableFastChecks 61 | MultiThreadedDebug 62 | EditAndContinue 63 | 64 | 65 | $(OutDir)strmbasd.lib 66 | 67 | 68 | 69 | 70 | MaxSpeed 71 | WIN32;_NDEBUG;_LIB;%(PreprocessorDefinitions) 72 | MultiThreaded 73 | ProgramDatabase 74 | 75 | 76 | $(OutDir)strmbase.lib 77 | 78 | 79 | 80 | 81 | X64 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | -------------------------------------------------------------------------------- /Libs/BaseClasses/vtrans.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // File: VTrans.h 3 | // 4 | // Desc: DirectShow base classes - defines a video transform class. 5 | // 6 | // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. 7 | //------------------------------------------------------------------------------ 8 | 9 | 10 | // This class is derived from CTransformFilter, but is specialised to handle 11 | // the requirements of video quality control by frame dropping. 12 | // This is a non-in-place transform, (i.e. it copies the data) such as a decoder. 13 | 14 | class CVideoTransformFilter : public CTransformFilter 15 | { 16 | public: 17 | 18 | CVideoTransformFilter(__in_opt LPCTSTR, __inout_opt LPUNKNOWN, REFCLSID clsid); 19 | ~CVideoTransformFilter(); 20 | HRESULT EndFlush(); 21 | 22 | // ================================================================= 23 | // ----- override these bits --------------------------------------- 24 | // ================================================================= 25 | // The following methods are in CTransformFilter which is inherited. 26 | // They are mentioned here for completeness 27 | // 28 | // These MUST be supplied in a derived class 29 | // 30 | // NOTE: 31 | // virtual HRESULT Transform(IMediaSample * pIn, IMediaSample *pOut); 32 | // virtual HRESULT CheckInputType(const CMediaType* mtIn) PURE; 33 | // virtual HRESULT CheckTransform 34 | // (const CMediaType* mtIn, const CMediaType* mtOut) PURE; 35 | // static CCOMObject * CreateInstance(LPUNKNOWN, HRESULT *); 36 | // virtual HRESULT DecideBufferSize 37 | // (IMemAllocator * pAllocator, ALLOCATOR_PROPERTIES *pprop) PURE; 38 | // virtual HRESULT GetMediaType(int iPosition, CMediaType *pMediaType) PURE; 39 | // 40 | // These MAY also be overridden 41 | // 42 | // virtual HRESULT StopStreaming(); 43 | // virtual HRESULT SetMediaType(PIN_DIRECTION direction,const CMediaType *pmt); 44 | // virtual HRESULT CheckConnect(PIN_DIRECTION dir,IPin *pPin); 45 | // virtual HRESULT BreakConnect(PIN_DIRECTION dir); 46 | // virtual HRESULT CompleteConnect(PIN_DIRECTION direction,IPin *pReceivePin); 47 | // virtual HRESULT EndOfStream(void); 48 | // virtual HRESULT BeginFlush(void); 49 | // virtual HRESULT EndFlush(void); 50 | // virtual HRESULT NewSegment 51 | // (REFERENCE_TIME tStart,REFERENCE_TIME tStop,double dRate); 52 | #ifdef PERF 53 | 54 | // If you override this - ensure that you register all these ids 55 | // as well as any of your own, 56 | virtual void RegisterPerfId() { 57 | m_idSkip = MSR_REGISTER(TEXT("Video Transform Skip frame")); 58 | m_idFrameType = MSR_REGISTER(TEXT("Video transform frame type")); 59 | m_idLate = MSR_REGISTER(TEXT("Video Transform Lateness")); 60 | m_idTimeTillKey = MSR_REGISTER(TEXT("Video Transform Estd. time to next key")); 61 | CTransformFilter::RegisterPerfId(); 62 | } 63 | #endif 64 | 65 | protected: 66 | 67 | // =========== QUALITY MANAGEMENT IMPLEMENTATION ======================== 68 | // Frames are assumed to come in three types: 69 | // Type 1: an AVI key frame or an MPEG I frame. 70 | // This frame can be decoded with no history. 71 | // Dropping this frame means that no further frame can be decoded 72 | // until the next type 1 frame. 73 | // Type 1 frames are sync points. 74 | // Type 2: an AVI non-key frame or an MPEG P frame. 75 | // This frame cannot be decoded unless the previous type 1 frame was 76 | // decoded and all type 2 frames since have been decoded. 77 | // Dropping this frame means that no further frame can be decoded 78 | // until the next type 1 frame. 79 | // Type 3: An MPEG B frame. 80 | // This frame cannot be decoded unless the previous type 1 or 2 frame 81 | // has been decoded AND the subsequent type 1 or 2 frame has also 82 | // been decoded. (This requires decoding the frames out of sequence). 83 | // Dropping this frame affects no other frames. This implementation 84 | // does not allow for these. All non-sync-point frames are treated 85 | // as being type 2. 86 | // 87 | // The spacing of frames of type 1 in a file is not guaranteed. There MUST 88 | // be a type 1 frame at (well, near) the start of the file in order to start 89 | // decoding at all. After that there could be one every half second or so, 90 | // there could be one at the start of each scene (aka "cut", "shot") or 91 | // there could be no more at all. 92 | // If there is only a single type 1 frame then NO FRAMES CAN BE DROPPED 93 | // without losing all the rest of the movie. There is no way to tell whether 94 | // this is the case, so we find that we are in the gambling business. 95 | // To try to improve the odds, we record the greatest interval between type 1s 96 | // that we have seen and we bet on things being no worse than this in the 97 | // future. 98 | 99 | // You can tell if it's a type 1 frame by calling IsSyncPoint(). 100 | // there is no architected way to test for a type 3, so you should override 101 | // the quality management here if you have B-frames. 102 | 103 | int m_nKeyFramePeriod; // the largest observed interval between type 1 frames 104 | // 1 means every frame is type 1, 2 means every other. 105 | 106 | int m_nFramesSinceKeyFrame; // Used to count frames since the last type 1. 107 | // becomes the new m_nKeyFramePeriod if greater. 108 | 109 | BOOL m_bSkipping; // we are skipping to the next type 1 frame 110 | 111 | #ifdef PERF 112 | int m_idFrameType; // MSR id Frame type. 1=Key, 2="non-key" 113 | int m_idSkip; // MSR id skipping 114 | int m_idLate; // MSR id lateness 115 | int m_idTimeTillKey; // MSR id for guessed time till next key frame. 116 | #endif 117 | 118 | virtual HRESULT StartStreaming(); 119 | 120 | HRESULT AbortPlayback(HRESULT hr); // if something bad happens 121 | 122 | HRESULT Receive(IMediaSample *pSample); 123 | 124 | HRESULT AlterQuality(Quality q); 125 | 126 | BOOL ShouldSkipFrame(IMediaSample * pIn); 127 | 128 | int m_itrLate; // lateness from last Quality message 129 | // (this overflows at 214 secs late). 130 | int m_tDecodeStart; // timeGetTime when decode started. 131 | int m_itrAvgDecode; // Average decode time in reference units. 132 | 133 | BOOL m_bNoSkip; // debug - no skipping. 134 | 135 | // We send an EC_QUALITY_CHANGE notification to the app if we have to degrade. 136 | // We send one when we start degrading, not one for every frame, this means 137 | // we track whether we've sent one yet. 138 | BOOL m_bQualityChanged; 139 | 140 | // When non-zero, don't pass anything to renderer until next keyframe 141 | // If there are few keys, give up and eventually draw something 142 | int m_nWaitForKey; 143 | }; 144 | -------------------------------------------------------------------------------- /Libs/BaseClasses/perfstruct.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // File: PerfStruct.h 3 | // 4 | // Desc: Structures for DirectShow performance logging. 5 | // 6 | // Copyright (c) 2000-2001 Microsoft Corporation. All rights reserved. 7 | //------------------------------------------------------------------------------ 8 | 9 | 10 | #ifndef _PERFSTRUCT_H_ 11 | #define _PERFSTRUCT_H_ 12 | 13 | #include 14 | #include 15 | 16 | // {28CF047A-2437-4b24-B653-B9446A419A69} 17 | DEFINE_GUID(GUID_DSHOW_CTL, 18 | 0x28cf047a, 0x2437, 0x4b24, 0xb6, 0x53, 0xb9, 0x44, 0x6a, 0x41, 0x9a, 0x69); 19 | 20 | // {D0DA7AD6-AE80-4de5-AAFC-C126711E7593} 21 | DEFINE_GUID(GUID_VIDEOREND, 22 | 0xd0da7ad6, 0xae80, 0x4de5, 0xaa, 0xfc, 0xc1, 0x26, 0x71, 0x1e, 0x75, 0x93); 23 | 24 | // {DC70AC3E-93E5-48db-88AB-E42064EC276A} 25 | DEFINE_GUID(GUID_DSOUNDGLITCH, 26 | 0xdc70ac3e, 0x93e5, 0x48db, 0x88, 0xab, 0xe4, 0x20, 0x64, 0xec, 0x27, 0x6a); 27 | 28 | // {3d7e7d93-2fc8-4a07-a719-e0922ff2899} 29 | DEFINE_GUID(GUID_STREAMTRACE, 30 | 0x3d7e7d93, 0x2fc8, 0x4a07, 0xa7, 0x19, 0xe0, 0x92, 0x2f, 0xf2, 0x89, 0x9e); 31 | 32 | // AZFIX: the following GUIDs aren't useful right now. 33 | 34 | // {3C33F7F5-EE54-493c-BA25-1656539C05AC} 35 | DEFINE_GUID(GUID_GETTIME, 36 | 0x3c33f7f5, 0xee54, 0x493c, 0xba, 0x25, 0x16, 0x56, 0x53, 0x9c, 0x5, 0xac); 37 | 38 | // {CC44B44D-8169-4952-9E4A-A4E13295E492} 39 | DEFINE_GUID(GUID_AUDIOREND, 40 | 0xcc44b44d, 0x8169, 0x4952, 0x9e, 0x4a, 0xa4, 0xe1, 0x32, 0x95, 0xe4, 0x92); 41 | 42 | // {775D19BF-4D8B-4de6-8DC9-66BAC7B310A2} 43 | DEFINE_GUID(GUID_FRAMEDROP, 44 | 0x775d19bf, 0x4d8b, 0x4de6, 0x8d, 0xc9, 0x66, 0xba, 0xc7, 0xb3, 0x10, 0xa2); 45 | 46 | // {56D29065-EFBE-42dc-8C29-E325DC9C27D5} 47 | DEFINE_GUID(GUID_AUDIOBREAK, 48 | 0x56d29065, 0xefbe, 0x42dc, 0x8c, 0x29, 0xe3, 0x25, 0xdc, 0x9c, 0x27, 0xd5); 49 | 50 | // {E1E6EA87-95A8-497e-BFBA-0295AEBCC707} 51 | DEFINE_GUID(GUID_AUDIORECV, 52 | 0xe1e6ea87, 0x95a8, 0x497e, 0xbf, 0xba, 0x2, 0x95, 0xae, 0xbc, 0xc7, 0x7); 53 | 54 | // {10F7768A-B1E7-4242-AD90-A2D44683D9F0} 55 | DEFINE_GUID(GUID_AUDIOSLAVE, 56 | 0x10f7768a, 0xb1e7, 0x4242, 0xad, 0x90, 0xa2, 0xd4, 0x46, 0x83, 0xd9, 0xf0); 57 | 58 | // {8983803D-691A-49bc-8FF6-962A39C0198F} 59 | DEFINE_GUID(GUID_AUDIOADDBREAK, 60 | 0x8983803d, 0x691a, 0x49bc, 0x8f, 0xf6, 0x96, 0x2a, 0x39, 0xc0, 0x19, 0x8f); 61 | 62 | #define GLITCHTYPE_DSOUNDFIRSTGOOD 0 63 | #define GLITCHTYPE_DSOUNDFIRSTBAD 1 64 | 65 | typedef struct PERFINFO_DSHOW_AUDIOGLITCH { 66 | ULONGLONG cycleCounter; 67 | DWORD glitchType; 68 | LONGLONG sampleTime; 69 | LONGLONG previousTime; 70 | ULONG_PTR instanceId; 71 | } PERFINFO_DSHOW_AUDIOGLITCH, *PPERFINFO_DSHOW_AUDIOGLITCH; 72 | 73 | typedef struct PERFINFO_WMI_AUDIOGLITCH { 74 | EVENT_TRACE_HEADER header; 75 | PERFINFO_DSHOW_AUDIOGLITCH data; 76 | } PERFINFO_WMI_AUDIO_GLITCH, *PPERFINFO_WMI_AUDIOGLITCH; 77 | 78 | typedef struct PERFINFO_DSHOW_GETTIME { 79 | ULONGLONG cycleCounter; 80 | ULONGLONG dshowClock; 81 | } PERFINFO_DSHOW_GETTIME, *PPERFINFO_DSHOW_GETTIME; 82 | 83 | typedef struct PERFINFO_WMI_GETTIME { 84 | EVENT_TRACE_HEADER header; 85 | PERFINFO_DSHOW_GETTIME data; 86 | } PERFINFO_WMI_GETTIME, *PPERFINFO_WMI_GETTIME; 87 | 88 | typedef struct PERFINFO_DSHOW_AVREND { 89 | ULONGLONG cycleCounter; 90 | ULONGLONG dshowClock; 91 | ULONGLONG sampleTime; 92 | } PERFINFO_DSHOW_AVREND, *PPERFINFO_DSHOW_AVREND; 93 | 94 | typedef struct PERFINFO_WMI_AVREND { 95 | EVENT_TRACE_HEADER header; 96 | PERFINFO_DSHOW_AVREND data; 97 | } PERFINFO_WMI_AVREND, *PPERFINFO_WMI_AVREND; 98 | 99 | typedef struct PERFINFO_DSHOW_AUDIOBREAK { 100 | ULONGLONG cycleCounter; 101 | ULONGLONG dshowClock; 102 | ULONGLONG sampleTime; 103 | ULONGLONG sampleDuration; 104 | } PERFINFO_DSHOW_AUDIOBREAK, *PPERFINFO_DSHOW_AUDIOBREAK; 105 | 106 | typedef struct PERFINFO_WMI_AUDIOBREAK { 107 | EVENT_TRACE_HEADER header; 108 | PERFINFO_DSHOW_AUDIOBREAK data; 109 | } PERFINFO_WMI_AUDIOBREAK, *PPERFINFO_WMI_AUDIOBREAK; 110 | 111 | typedef struct PERFINFO_DSHOW_FRAMEDROP { 112 | ULONGLONG cycleCounter; 113 | ULONGLONG dshowClock; 114 | ULONGLONG frameTime; 115 | } PERFINFO_DSHOW_FRAMEDROP, *PPERFINFO_DSHOW_FRAMEDROP; 116 | 117 | typedef struct PERFINFO_WMI_FRAMEDROP { 118 | EVENT_TRACE_HEADER header; 119 | PERFINFO_DSHOW_FRAMEDROP data; 120 | } PERFINFO_WMI_FRAMEDROP, *PPERFINFO_WMI_FRAMEDROP; 121 | 122 | #define PERFINFO_STREAMTRACE_MPEG2DEMUX_PTS_TRANSLATION 1 123 | #define PERFINFO_STREAMTRACE_MPEG2DEMUX_SAMPLE_RECEIVED 2 124 | #define PERFINFO_STREAMTRACE_VMR_BEGIN_ADVISE 3 125 | #define PERFINFO_STREAMTRACE_VMR_END_ADVISE 4 126 | #define PERFINFO_STREAMTRACE_VMR_RECEIVE 5 127 | #define PERFINFO_STREAMTRACE_VMR_BEGIN_DEINTERLACE 6 128 | #define PERFINFO_STREAMTRACE_VMR_END_DEINTERLACE 7 129 | #define PERFINFO_STREAMTRACE_VMR_BEGIN_DECODE 8 130 | #define PERFINFO_STREAMTRACE_VMR_END_DECODE 9 131 | #define PERFINFO_STREAMTRACE_VMR_DROPPED_FRAME 10 132 | #define PERFINFO_STREAMTRACE_ENCDEC_DTFILTERINPUT 11 133 | #define PERFINFO_STREAMTRACE_ENCDEC_DTFILTEROUTPUT 12 134 | #define PERFINFO_STREAMTRACE_ENCDEC_ETFILTERINPUT 13 135 | #define PERFINFO_STREAMTRACE_ENCDEC_ETFILTEROUTPUT 14 136 | #define PERFINFO_STREAMTRACE_ENCDEC_XDSCODECINPUT 15 137 | #define PERFINFO_STREAMTRACE_SBE_DVRANALYSISINPUT_RECEIVE 16 138 | #define PERFINFO_STREAMTRACE_SBE_DVRANALYSISINPUT_DELIVER 17 139 | #define PERFINFO_STREAMTRACE_SBE_DVRINPUTPIN_RECEIVE 18 140 | #define PERFINFO_STREAMTRACE_SBE_DVROUTPUTPIN_RECEIVE 19 141 | #define PERFINFO_STREAMTRACE_VMR_RENDER_TIME 20 142 | 143 | typedef struct _PERFINFO_DSHOW_STREAMTRACE { 144 | ULONG id; 145 | ULONG reserved; 146 | ULONGLONG dshowClock; 147 | ULONGLONG data[ 4 ]; 148 | } PERFINFO_DSHOW_STREAMTRACE, *PPERFINFO_DSHOW_STREAMTRACE; 149 | 150 | typedef struct _PERFINFO_WMI_STREAMTRACE { 151 | EVENT_TRACE_HEADER header; 152 | PERFINFO_DSHOW_STREAMTRACE data; 153 | } PERFINFO_WMI_STREAMTRACE, *PPERFINFO_WMI_STREAMTRACE; 154 | 155 | 156 | typedef struct PERFINFO_DSHOW_AUDIORECV { 157 | LONGLONG streamTime ; 158 | LONGLONG sampleStart ; 159 | LONGLONG sampleStop ; 160 | LONGLONG hwduration ; 161 | BOOL discontinuity ; 162 | } PERFINFO_DSHOW_AUDIORECV, *PPERFINFO_DSHOW_AUDIORECV; 163 | 164 | typedef struct PERFINFO_WMI_AUDIORECV { 165 | EVENT_TRACE_HEADER header; 166 | PERFINFO_DSHOW_AUDIORECV data; 167 | } PERFINFO_WMI_AUDIORECV, *PPERFINFO_WMI_AUDIORECV; 168 | 169 | typedef struct PERFINFO_DSHOW_AUDIOSLAVE { 170 | LONGLONG masterClock ; 171 | LONGLONG slaveClock ; 172 | LONGLONG errorAccum ; 173 | LONGLONG lastHighErrorSeen ; 174 | LONGLONG lastLowErrorSeen ; 175 | } PERFINFO_DSHOW_AUDIOSLAVE, *PPERFINFO_DSHOW_AUDIOSLAVE; 176 | 177 | typedef struct PERFINFO_WMI_AUDIOSLAVE { 178 | EVENT_TRACE_HEADER header; 179 | PERFINFO_DSHOW_AUDIOSLAVE data; 180 | } PERFINFO_WMI_AUDIOSLAVE, *PPERFINFO_WMI_AUDIOSLAVE; 181 | 182 | typedef struct PERFINFO_DSHOW_AUDIOADDBREAK { 183 | DWORD iterNextWrite ; 184 | DWORD offsetNextWrite ; 185 | DWORD iterWrite ; 186 | DWORD offsetWrite ; 187 | } PERFINFO_DSHOW_AUDIOADDBREAK, *PPERFINFO_DSHOW_AUDIOADDBREAK; 188 | 189 | typedef struct PERFINFO_WMI_AUDIOADDBREAK { 190 | EVENT_TRACE_HEADER header; 191 | PERFINFO_DSHOW_AUDIOADDBREAK data; 192 | } PERFINFO_WMI_AUDIOADDBREAK, *PPERFINFO_WMI_AUDIOADDBREAK; 193 | 194 | #endif // _PREFSTRUCT_H_ 195 | -------------------------------------------------------------------------------- /Source/Filters.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Debug 8 | Win32 9 | 10 | 11 | Debug 12 | x64 13 | 14 | 15 | Release 16 | Win32 17 | 18 | 19 | Release 20 | x64 21 | 22 | 23 | 24 | {24DCC163-C62A-4043-BBBD-BBCC740629DA} 25 | Filters 26 | Win32Proj 27 | 28 | 29 | 30 | DynamicLibrary 31 | v143 32 | Unicode 33 | Static 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | ..\Output\$(Configuration)-$(Platform)\ 44 | ..\Output\$(Configuration)-$(Platform)\Build\ 45 | .ax 46 | 47 | 48 | true 49 | 50 | 51 | false 52 | 53 | 54 | 55 | ..\Libs\BaseClasses;%(AdditionalIncludeDirectories) 56 | 57 | Level3 58 | StdCall 59 | false 60 | 61 | 62 | false 63 | filters.def 64 | Windows 65 | ..\Libs\BaseClasses\$(Configuration)-$(Platform)\;%(AdditionalLibraryDirectories) 66 | 67 | 68 | 69 | 70 | 71 | Disabled 72 | WIN32;_WINDOWS;_USRDLL;_DEBUG;%(PreprocessorDefinitions) 73 | true 74 | EnableFastChecks 75 | MultiThreadedDebug 76 | EditAndContinue 77 | 78 | 79 | advapi32.lib;mf.lib;mfplat.lib;mfreadwrite.lib;ole32.lib;oleaut32.lib;user32.lib;winmm.lib;strmbasd.lib;%(AdditionalDependencies) 80 | true 81 | 82 | 83 | 84 | 85 | MaxSpeed 86 | WIN32;_WINDOWS;_USRDLL;_NDEBUG;%(PreprocessorDefinitions) 87 | MultiThreaded 88 | 89 | 90 | advapi32.lib;mf.lib;mfplat.lib;mfreadwrite.lib;ole32.lib;oleaut32.lib;user32.lib;winmm.lib;strmbase.lib;%(AdditionalDependencies) 91 | true 92 | true 93 | 94 | 95 | 96 | 97 | MachineX86 98 | 99 | 100 | 101 | 102 | X64 103 | 104 | 105 | MachineX64 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /Libs/BaseClasses/BaseClasses.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | Source Files 35 | 36 | 37 | Source Files 38 | 39 | 40 | Source Files 41 | 42 | 43 | Source Files 44 | 45 | 46 | Source Files 47 | 48 | 49 | Source Files 50 | 51 | 52 | Source Files 53 | 54 | 55 | Source Files 56 | 57 | 58 | Source Files 59 | 60 | 61 | Source Files 62 | 63 | 64 | Source Files 65 | 66 | 67 | Source Files 68 | 69 | 70 | Source Files 71 | 72 | 73 | Source Files 74 | 75 | 76 | Source Files 77 | 78 | 79 | Source Files 80 | 81 | 82 | Source Files 83 | 84 | 85 | Source Files 86 | 87 | 88 | Source Files 89 | 90 | 91 | Source Files 92 | 93 | 94 | Source Files 95 | 96 | 97 | Source Files 98 | 99 | 100 | Source Files 101 | 102 | 103 | Source Files 104 | 105 | 106 | Source Files 107 | 108 | 109 | Source Files 110 | 111 | 112 | 113 | 114 | Header Files 115 | 116 | 117 | Header Files 118 | 119 | 120 | Header Files 121 | 122 | 123 | Header Files 124 | 125 | 126 | Header Files 127 | 128 | 129 | Header Files 130 | 131 | 132 | Header Files 133 | 134 | 135 | Header Files 136 | 137 | 138 | Header Files 139 | 140 | 141 | Header Files 142 | 143 | 144 | Header Files 145 | 146 | 147 | Header Files 148 | 149 | 150 | Header Files 151 | 152 | 153 | Header Files 154 | 155 | 156 | Header Files 157 | 158 | 159 | Header Files 160 | 161 | 162 | Header Files 163 | 164 | 165 | Header Files 166 | 167 | 168 | Header Files 169 | 170 | 171 | Header Files 172 | 173 | 174 | Header Files 175 | 176 | 177 | Header Files 178 | 179 | 180 | Header Files 181 | 182 | 183 | Header Files 184 | 185 | 186 | Header Files 187 | 188 | 189 | Header Files 190 | 191 | 192 | Header Files 193 | 194 | 195 | Header Files 196 | 197 | 198 | Header Files 199 | 200 | 201 | Header Files 202 | 203 | 204 | Header Files 205 | 206 | 207 | Header Files 208 | 209 | 210 | Header Files 211 | 212 | 213 | Header Files 214 | 215 | 216 | Header Files 217 | 218 | 219 | Header Files 220 | 221 | 222 | -------------------------------------------------------------------------------- /Libs/BaseClasses/streams.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // File: Streams.h 3 | // 4 | // Desc: DirectShow base classes - defines overall streams architecture. 5 | // 6 | // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. 7 | //------------------------------------------------------------------------------ 8 | 9 | 10 | #ifndef __STREAMS__ 11 | #define __STREAMS__ 12 | 13 | #ifdef _MSC_VER 14 | // disable some level-4 warnings, use #pragma warning(enable:###) to re-enable 15 | #pragma warning(disable:4100) // warning C4100: unreferenced formal parameter 16 | #pragma warning(disable:4201) // warning C4201: nonstandard extension used : nameless struct/union 17 | #pragma warning(disable:4511) // warning C4511: copy constructor could not be generated 18 | #pragma warning(disable:4512) // warning C4512: assignment operator could not be generated 19 | #pragma warning(disable:4514) // warning C4514: "unreferenced inline function has been removed" 20 | 21 | #if _MSC_VER>=1100 22 | #define AM_NOVTABLE __declspec(novtable) 23 | #else 24 | #define AM_NOVTABLE 25 | #endif 26 | #endif // MSC_VER 27 | 28 | 29 | // Because of differences between Visual C++ and older Microsoft SDKs, 30 | // you may have defined _DEBUG without defining DEBUG. This logic 31 | // ensures that both will be set if Visual C++ sets _DEBUG. 32 | #ifdef _DEBUG 33 | #ifndef DEBUG 34 | #define DEBUG 35 | #endif 36 | #endif 37 | 38 | 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | 45 | 46 | #ifndef NUMELMS 47 | #if _WIN32_WINNT < 0x0600 48 | #define NUMELMS(aa) (sizeof(aa)/sizeof((aa)[0])) 49 | #else 50 | #define NUMELMS(aa) ARRAYSIZE(aa) 51 | #endif 52 | #endif 53 | 54 | /////////////////////////////////////////////////////////////////////////// 55 | // The following definitions come from the Platform SDK and are required if 56 | // the applicaiton is being compiled with the headers from Visual C++ 6.0. 57 | /////////////////////////////////////////////////// //////////////////////// 58 | #ifndef InterlockedExchangePointer 59 | #define InterlockedExchangePointer(Target, Value) \ 60 | (PVOID)InterlockedExchange((PLONG)(Target), (LONG)(Value)) 61 | #endif 62 | 63 | #ifndef _WAVEFORMATEXTENSIBLE_ 64 | #define _WAVEFORMATEXTENSIBLE_ 65 | typedef struct { 66 | WAVEFORMATEX Format; 67 | union { 68 | WORD wValidBitsPerSample; /* bits of precision */ 69 | WORD wSamplesPerBlock; /* valid if wBitsPerSample==0 */ 70 | WORD wReserved; /* If neither applies, set to zero. */ 71 | } Samples; 72 | DWORD dwChannelMask; /* which channels are */ 73 | /* present in stream */ 74 | GUID SubFormat; 75 | } WAVEFORMATEXTENSIBLE, *PWAVEFORMATEXTENSIBLE; 76 | #endif // !_WAVEFORMATEXTENSIBLE_ 77 | 78 | #if !defined(WAVE_FORMAT_EXTENSIBLE) 79 | #define WAVE_FORMAT_EXTENSIBLE 0xFFFE 80 | #endif // !defined(WAVE_FORMAT_EXTENSIBLE) 81 | 82 | #ifndef GetWindowLongPtr 83 | #define GetWindowLongPtrA GetWindowLongA 84 | #define GetWindowLongPtrW GetWindowLongW 85 | #ifdef UNICODE 86 | #define GetWindowLongPtr GetWindowLongPtrW 87 | #else 88 | #define GetWindowLongPtr GetWindowLongPtrA 89 | #endif // !UNICODE 90 | #endif // !GetWindowLongPtr 91 | 92 | #ifndef SetWindowLongPtr 93 | #define SetWindowLongPtrA SetWindowLongA 94 | #define SetWindowLongPtrW SetWindowLongW 95 | #ifdef UNICODE 96 | #define SetWindowLongPtr SetWindowLongPtrW 97 | #else 98 | #define SetWindowLongPtr SetWindowLongPtrA 99 | #endif // !UNICODE 100 | #endif // !SetWindowLongPtr 101 | 102 | #ifndef GWLP_WNDPROC 103 | #define GWLP_WNDPROC (-4) 104 | #endif 105 | #ifndef GWLP_HINSTANCE 106 | #define GWLP_HINSTANCE (-6) 107 | #endif 108 | #ifndef GWLP_HWNDPARENT 109 | #define GWLP_HWNDPARENT (-8) 110 | #endif 111 | #ifndef GWLP_USERDATA 112 | #define GWLP_USERDATA (-21) 113 | #endif 114 | #ifndef GWLP_ID 115 | #define GWLP_ID (-12) 116 | #endif 117 | #ifndef DWLP_MSGRESULT 118 | #define DWLP_MSGRESULT 0 119 | #endif 120 | #ifndef DWLP_DLGPROC 121 | #define DWLP_DLGPROC DWLP_MSGRESULT + sizeof(LRESULT) 122 | #endif 123 | #ifndef DWLP_USER 124 | #define DWLP_USER DWLP_DLGPROC + sizeof(DLGPROC) 125 | #endif 126 | 127 | 128 | #pragma warning(push) 129 | #pragma warning(disable: 4312 4244) 130 | // _GetWindowLongPtr 131 | // Templated version of GetWindowLongPtr, to suppress spurious compiler warning. 132 | template 133 | T _GetWindowLongPtr(HWND hwnd, int nIndex) 134 | { 135 | return (T)GetWindowLongPtr(hwnd, nIndex); 136 | } 137 | 138 | // _SetWindowLongPtr 139 | // Templated version of SetWindowLongPtr, to suppress spurious compiler warning. 140 | template 141 | LONG_PTR _SetWindowLongPtr(HWND hwnd, int nIndex, T p) 142 | { 143 | return SetWindowLongPtr(hwnd, nIndex, (LONG_PTR)p); 144 | } 145 | #pragma warning(pop) 146 | 147 | /////////////////////////////////////////////////////////////////////////// 148 | // End Platform SDK definitions 149 | /////////////////////////////////////////////////////////////////////////// 150 | 151 | 152 | #include // Generated IDL header file for streams interfaces 153 | #include // required by amvideo.h 154 | 155 | #include // Helper class for REFERENCE_TIME management 156 | #include // Debug support for logging and ASSERTs 157 | #include // ActiveMovie video interfaces and definitions 158 | //include amaudio.h explicitly if you need it. it requires the DX SDK. 159 | //#include // ActiveMovie audio interfaces and definitions 160 | #include // General helper classes for threads etc 161 | #include // Base COM classes to support IUnknown 162 | #include // Filter registration support functions 163 | #include // Performance measurement 164 | #include // Light weight com function prototypes 165 | 166 | #include // Simple cache container class 167 | #include // Non MFC generic list class 168 | #include // CMsgThread 169 | #include // Helper class for managing media types 170 | #include // conversions between FOURCCs and GUIDs 171 | #include // generated from control.odl 172 | #include // control interface utility classes 173 | #include // event code definitions 174 | #include // Main streams architecture class hierachy 175 | #include // Generic transform filter 176 | #include // Generic transform-in-place filter 177 | #include // declaration of type GUIDs and well-known clsids 178 | #include // Generic source filter 179 | #include // Output pin queueing 180 | #include // HRESULT status and error definitions 181 | #include // Base class for writing ActiveX renderers 182 | #include // Helps with filters that manage windows 183 | #include // Implements the IVideoWindow interface 184 | #include // Specifically video related classes 185 | #include // Base clock class 186 | #include // System clock 187 | #include // IPersistStream helper class 188 | #include // Video Transform Filter base class 189 | #include 190 | #include // Base property page class 191 | #include // IAMStreamControl support 192 | #include // External device control interface defines 193 | #include // audio filter device error event codes 194 | 195 | 196 | 197 | #else 198 | #ifdef DEBUG 199 | #pragma message("STREAMS.H included TWICE") 200 | #endif 201 | #endif // __STREAMS__ 202 | 203 | -------------------------------------------------------------------------------- /Libs/BaseClasses/refclock.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // File: RefClock.h 3 | // 4 | // Desc: DirectShow base classes - defines the IReferenceClock interface. 5 | // 6 | // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. 7 | //------------------------------------------------------------------------------ 8 | 9 | 10 | #ifndef __BASEREFCLOCK__ 11 | #define __BASEREFCLOCK__ 12 | 13 | #include 14 | 15 | const UINT RESOLUTION = 1; /* High resolution timer */ 16 | const INT ADVISE_CACHE = 4; /* Default cache size */ 17 | const LONGLONG MAX_TIME = 0x7FFFFFFFFFFFFFFF; /* Maximum LONGLONG value */ 18 | 19 | inline LONGLONG WINAPI ConvertToMilliseconds(const REFERENCE_TIME& RT) 20 | { 21 | /* This converts an arbitrary value representing a reference time 22 | into a MILLISECONDS value for use in subsequent system calls */ 23 | 24 | return (RT / (UNITS / MILLISECONDS)); 25 | } 26 | 27 | /* This class hierarchy will support an IReferenceClock interface so 28 | that an audio card (or other externally driven clock) can update the 29 | system wide clock that everyone uses. 30 | 31 | The interface will be pretty thin with probably just one update method 32 | This interface has not yet been defined. 33 | */ 34 | 35 | /* This abstract base class implements the IReferenceClock 36 | * interface. Classes that actually provide clock signals (from 37 | * whatever source) have to be derived from this class. 38 | * 39 | * The abstract class provides implementations for: 40 | * CUnknown support 41 | * locking support (CCritSec) 42 | * client advise code (creates a thread) 43 | * 44 | * Question: what can we do about quality? Change the timer 45 | * resolution to lower the system load? Up the priority of the 46 | * timer thread to force more responsive signals? 47 | * 48 | * During class construction we create a worker thread that is destroyed during 49 | * destuction. This thread executes a series of WaitForSingleObject calls, 50 | * waking up when a command is given to the thread or the next wake up point 51 | * is reached. The wakeup points are determined by clients making Advise 52 | * calls. 53 | * 54 | * Each advise call defines a point in time when they wish to be notified. A 55 | * periodic advise is a series of these such events. We maintain a list of 56 | * advise links and calculate when the nearest event notification is due for. 57 | * We then call WaitForSingleObject with a timeout equal to this time. The 58 | * handle we wait on is used by the class to signal that something has changed 59 | * and that we must reschedule the next event. This typically happens when 60 | * someone comes in and asks for an advise link while we are waiting for an 61 | * event to timeout. 62 | * 63 | * While we are modifying the list of advise requests we 64 | * are protected from interference through a critical section. Clients are NOT 65 | * advised through callbacks. One shot clients have an event set, while 66 | * periodic clients have a semaphore released for each event notification. A 67 | * semaphore allows a client to be kept up to date with the number of events 68 | * actually triggered and be assured that they can't miss multiple events being 69 | * set. 70 | * 71 | * Keeping track of advises is taken care of by the CAMSchedule class. 72 | */ 73 | 74 | class CBaseReferenceClock 75 | : public CUnknown, public IReferenceClock, public CCritSec, public IReferenceClockTimerControl 76 | { 77 | protected: 78 | virtual ~CBaseReferenceClock(); // Don't let me be created on the stack! 79 | public: 80 | CBaseReferenceClock(__in_opt LPCTSTR pName, 81 | __inout_opt LPUNKNOWN pUnk, 82 | __inout HRESULT *phr, 83 | __inout_opt CAMSchedule * pSched = 0 ); 84 | 85 | STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void ** ppv); 86 | 87 | DECLARE_IUNKNOWN 88 | 89 | /* IReferenceClock methods */ 90 | // Derived classes must implement GetPrivateTime(). All our GetTime 91 | // does is call GetPrivateTime and then check so that time does not 92 | // go backwards. A return code of S_FALSE implies that the internal 93 | // clock has gone backwards and GetTime time has halted until internal 94 | // time has caught up. (Don't know if this will be much use to folk, 95 | // but it seems odd not to use the return code for something useful.) 96 | STDMETHODIMP GetTime(__out REFERENCE_TIME *pTime); 97 | // When this is called, it sets m_rtLastGotTime to the time it returns. 98 | 99 | /* Provide standard mechanisms for scheduling events */ 100 | 101 | /* Ask for an async notification that a time has elapsed */ 102 | STDMETHODIMP AdviseTime( 103 | REFERENCE_TIME baseTime, // base reference time 104 | REFERENCE_TIME streamTime, // stream offset time 105 | HEVENT hEvent, // advise via this event 106 | __out DWORD_PTR *pdwAdviseCookie// where your cookie goes 107 | ); 108 | 109 | /* Ask for an asynchronous periodic notification that a time has elapsed */ 110 | STDMETHODIMP AdvisePeriodic( 111 | REFERENCE_TIME StartTime, // starting at this time 112 | REFERENCE_TIME PeriodTime, // time between notifications 113 | HSEMAPHORE hSemaphore, // advise via a semaphore 114 | __out DWORD_PTR *pdwAdviseCookie// where your cookie goes 115 | ); 116 | 117 | /* Cancel a request for notification(s) - if the notification was 118 | * a one shot timer then this function doesn't need to be called 119 | * as the advise is automatically cancelled, however it does no 120 | * harm to explicitly cancel a one-shot advise. It is REQUIRED that 121 | * clients call Unadvise to clear a Periodic advise setting. 122 | */ 123 | 124 | STDMETHODIMP Unadvise(DWORD_PTR dwAdviseCookie); 125 | 126 | /* Methods for the benefit of derived classes or outer objects */ 127 | 128 | // GetPrivateTime() is the REAL clock. GetTime is just a cover for 129 | // it. Derived classes will probably override this method but not 130 | // GetTime() itself. 131 | // The important point about GetPrivateTime() is it's allowed to go 132 | // backwards. Our GetTime() will keep returning the LastGotTime 133 | // until GetPrivateTime() catches up. 134 | virtual REFERENCE_TIME GetPrivateTime(); 135 | 136 | /* Provide a method for correcting drift */ 137 | STDMETHODIMP SetTimeDelta( const REFERENCE_TIME& TimeDelta ); 138 | 139 | CAMSchedule * GetSchedule() const { return m_pSchedule; } 140 | 141 | // IReferenceClockTimerControl methods 142 | // 143 | // Setting a default of 0 disables the default of 1ms 144 | STDMETHODIMP SetDefaultTimerResolution( 145 | REFERENCE_TIME timerResolution // in 100ns 146 | ); 147 | STDMETHODIMP GetDefaultTimerResolution( 148 | __out REFERENCE_TIME* pTimerResolution // in 100ns 149 | ); 150 | 151 | private: 152 | REFERENCE_TIME m_rtPrivateTime; // Current best estimate of time 153 | DWORD m_dwPrevSystemTime; // Last vaule we got from timeGetTime 154 | REFERENCE_TIME m_rtLastGotTime; // Last time returned by GetTime 155 | REFERENCE_TIME m_rtNextAdvise; // Time of next advise 156 | UINT m_TimerResolution; 157 | 158 | #ifdef PERF 159 | int m_idGetSystemTime; 160 | #endif 161 | 162 | // Thread stuff 163 | public: 164 | void TriggerThread() // Wakes thread up. Need to do this if 165 | { // time to next advise needs reevaluating. 166 | EXECUTE_ASSERT(SetEvent(m_pSchedule->GetEvent())); 167 | } 168 | 169 | 170 | private: 171 | BOOL m_bAbort; // Flag used for thread shutdown 172 | HANDLE m_hThread; // Thread handle 173 | 174 | HRESULT AdviseThread(); // Method in which the advise thread runs 175 | static DWORD __stdcall AdviseThreadFunction(__in LPVOID); // Function used to get there 176 | 177 | protected: 178 | CAMSchedule * m_pSchedule; 179 | 180 | void Restart (IN REFERENCE_TIME rtMinTime = 0I64) ; 181 | }; 182 | 183 | #endif 184 | 185 | -------------------------------------------------------------------------------- /Libs/BaseClasses/videoctl.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // File: VideoCtl.h 3 | // 4 | // Desc: DirectShow base classes. 5 | // 6 | // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. 7 | //------------------------------------------------------------------------------ 8 | 9 | 10 | #ifndef __VIDEOCTL__ 11 | #define __VIDEOCTL__ 12 | 13 | // These help with property page implementations. The first can be used to 14 | // load any string from a resource file. The buffer to load into is passed 15 | // as an input parameter. The same buffer is the return value if the string 16 | // was found otherwise it returns TEXT(""). The GetDialogSize is passed the 17 | // resource ID of a dialog box and returns the size of it in screen pixels 18 | 19 | #define STR_MAX_LENGTH 256 20 | LPTSTR WINAPI StringFromResource(__out_ecount(STR_MAX_LENGTH) LPTSTR pBuffer, int iResourceID); 21 | 22 | #ifdef UNICODE 23 | #define WideStringFromResource StringFromResource 24 | LPSTR WINAPI StringFromResource(__out_ecount(STR_MAX_LENGTH) LPSTR pBuffer, int iResourceID); 25 | #else 26 | LPWSTR WINAPI WideStringFromResource(__out_ecount(STR_MAX_LENGTH) LPWSTR pBuffer, int iResourceID); 27 | #endif 28 | 29 | 30 | BOOL WINAPI GetDialogSize(int iResourceID, // Dialog box resource identifier 31 | DLGPROC pDlgProc, // Pointer to dialog procedure 32 | LPARAM lParam, // Any user data wanted in pDlgProc 33 | __out SIZE *pResult);// Returns the size of dialog box 34 | 35 | // Class that aggregates an IDirectDraw interface 36 | 37 | class CAggDirectDraw : public IDirectDraw, public CUnknown 38 | { 39 | protected: 40 | 41 | LPDIRECTDRAW m_pDirectDraw; 42 | 43 | public: 44 | 45 | DECLARE_IUNKNOWN 46 | STDMETHODIMP NonDelegatingQueryInterface(REFIID riid,__deref_out void **ppv); 47 | 48 | // Constructor and destructor 49 | 50 | CAggDirectDraw(__in_opt LPCTSTR pName,__inout_opt LPUNKNOWN pUnk) : 51 | CUnknown(pName,pUnk), 52 | m_pDirectDraw(NULL) { }; 53 | 54 | virtual CAggDirectDraw::~CAggDirectDraw() { }; 55 | 56 | // Set the object we should be aggregating 57 | void SetDirectDraw(__inout LPDIRECTDRAW pDirectDraw) { 58 | m_pDirectDraw = pDirectDraw; 59 | } 60 | 61 | // IDirectDraw methods 62 | 63 | STDMETHODIMP Compact(); 64 | STDMETHODIMP CreateClipper(DWORD dwFlags,__deref_out LPDIRECTDRAWCLIPPER *lplpDDClipper,__inout_opt IUnknown *pUnkOuter); 65 | STDMETHODIMP CreatePalette(DWORD dwFlags,__in LPPALETTEENTRY lpColorTable,__deref_out LPDIRECTDRAWPALETTE *lplpDDPalette,__inout_opt IUnknown *pUnkOuter); 66 | STDMETHODIMP CreateSurface(__in LPDDSURFACEDESC lpDDSurfaceDesc,__deref_out LPDIRECTDRAWSURFACE *lplpDDSurface,__inout_opt IUnknown *pUnkOuter); 67 | STDMETHODIMP DuplicateSurface(__in LPDIRECTDRAWSURFACE lpDDSurface,__deref_out LPDIRECTDRAWSURFACE *lplpDupDDSurface); 68 | STDMETHODIMP EnumDisplayModes(DWORD dwSurfaceDescCount,__in LPDDSURFACEDESC lplpDDSurfaceDescList,__in LPVOID lpContext,__in LPDDENUMMODESCALLBACK lpEnumCallback); 69 | STDMETHODIMP EnumSurfaces(DWORD dwFlags,__in LPDDSURFACEDESC lpDDSD,__in LPVOID lpContext,__in LPDDENUMSURFACESCALLBACK lpEnumCallback); 70 | STDMETHODIMP FlipToGDISurface(); 71 | STDMETHODIMP GetCaps(__out LPDDCAPS lpDDDriverCaps,__out LPDDCAPS lpDDHELCaps); 72 | STDMETHODIMP GetDisplayMode(__out LPDDSURFACEDESC lpDDSurfaceDesc); 73 | STDMETHODIMP GetFourCCCodes(__inout LPDWORD lpNumCodes,__out_ecount(*lpNumCodes) LPDWORD lpCodes); 74 | STDMETHODIMP GetGDISurface(__deref_out LPDIRECTDRAWSURFACE *lplpGDIDDSurface); 75 | STDMETHODIMP GetMonitorFrequency(__out LPDWORD lpdwFrequency); 76 | STDMETHODIMP GetScanLine(__out LPDWORD lpdwScanLine); 77 | STDMETHODIMP GetVerticalBlankStatus(__out LPBOOL lpblsInVB); 78 | STDMETHODIMP Initialize(__in GUID *lpGUID); 79 | STDMETHODIMP RestoreDisplayMode(); 80 | STDMETHODIMP SetCooperativeLevel(HWND hWnd,DWORD dwFlags); 81 | STDMETHODIMP SetDisplayMode(DWORD dwWidth,DWORD dwHeight,DWORD dwBpp); 82 | STDMETHODIMP WaitForVerticalBlank(DWORD dwFlags,HANDLE hEvent); 83 | }; 84 | 85 | 86 | // Class that aggregates an IDirectDrawSurface interface 87 | 88 | class CAggDrawSurface : public IDirectDrawSurface, public CUnknown 89 | { 90 | protected: 91 | 92 | LPDIRECTDRAWSURFACE m_pDirectDrawSurface; 93 | 94 | public: 95 | 96 | DECLARE_IUNKNOWN 97 | STDMETHODIMP NonDelegatingQueryInterface(REFIID riid,__deref_out void **ppv); 98 | 99 | // Constructor and destructor 100 | 101 | CAggDrawSurface(__in_opt LPCTSTR pName,__inout_opt LPUNKNOWN pUnk) : 102 | CUnknown(pName,pUnk), 103 | m_pDirectDrawSurface(NULL) { }; 104 | 105 | virtual ~CAggDrawSurface() { }; 106 | 107 | // Set the object we should be aggregating 108 | void SetDirectDrawSurface(__inout LPDIRECTDRAWSURFACE pDirectDrawSurface) { 109 | m_pDirectDrawSurface = pDirectDrawSurface; 110 | } 111 | 112 | // IDirectDrawSurface methods 113 | 114 | STDMETHODIMP AddAttachedSurface(__in LPDIRECTDRAWSURFACE lpDDSAttachedSurface); 115 | STDMETHODIMP AddOverlayDirtyRect(__in LPRECT lpRect); 116 | STDMETHODIMP Blt(__in LPRECT lpDestRect,__in LPDIRECTDRAWSURFACE lpDDSrcSurface,__in LPRECT lpSrcRect,DWORD dwFlags,__in LPDDBLTFX lpDDBltFx); 117 | STDMETHODIMP BltBatch(__in_ecount(dwCount) LPDDBLTBATCH lpDDBltBatch,DWORD dwCount,DWORD dwFlags); 118 | STDMETHODIMP BltFast(DWORD dwX,DWORD dwY,__in LPDIRECTDRAWSURFACE lpDDSrcSurface,__in LPRECT lpSrcRect,DWORD dwTrans); 119 | STDMETHODIMP DeleteAttachedSurface(DWORD dwFlags,__in LPDIRECTDRAWSURFACE lpDDSAttachedSurface); 120 | STDMETHODIMP EnumAttachedSurfaces(__in LPVOID lpContext,__in LPDDENUMSURFACESCALLBACK lpEnumSurfacesCallback); 121 | STDMETHODIMP EnumOverlayZOrders(DWORD dwFlags,__in LPVOID lpContext,__in LPDDENUMSURFACESCALLBACK lpfnCallback); 122 | STDMETHODIMP Flip(__in LPDIRECTDRAWSURFACE lpDDSurfaceTargetOverride,DWORD dwFlags); 123 | STDMETHODIMP GetAttachedSurface(__in LPDDSCAPS lpDDSCaps,__deref_out LPDIRECTDRAWSURFACE *lplpDDAttachedSurface); 124 | STDMETHODIMP GetBltStatus(DWORD dwFlags); 125 | STDMETHODIMP GetCaps(__out LPDDSCAPS lpDDSCaps); 126 | STDMETHODIMP GetClipper(__deref_out LPDIRECTDRAWCLIPPER *lplpDDClipper); 127 | STDMETHODIMP GetColorKey(DWORD dwFlags,__out LPDDCOLORKEY lpDDColorKey); 128 | STDMETHODIMP GetDC(__out HDC *lphDC); 129 | STDMETHODIMP GetFlipStatus(DWORD dwFlags); 130 | STDMETHODIMP GetOverlayPosition(__out LPLONG lpdwX,__out LPLONG lpdwY); 131 | STDMETHODIMP GetPalette(__deref_out LPDIRECTDRAWPALETTE *lplpDDPalette); 132 | STDMETHODIMP GetPixelFormat(__out LPDDPIXELFORMAT lpDDPixelFormat); 133 | STDMETHODIMP GetSurfaceDesc(__out LPDDSURFACEDESC lpDDSurfaceDesc); 134 | STDMETHODIMP Initialize(__in LPDIRECTDRAW lpDD,__in LPDDSURFACEDESC lpDDSurfaceDesc); 135 | STDMETHODIMP IsLost(); 136 | STDMETHODIMP Lock(__in LPRECT lpDestRect,__inout LPDDSURFACEDESC lpDDSurfaceDesc,DWORD dwFlags,HANDLE hEvent); 137 | STDMETHODIMP ReleaseDC(HDC hDC); 138 | STDMETHODIMP Restore(); 139 | STDMETHODIMP SetClipper(__in LPDIRECTDRAWCLIPPER lpDDClipper); 140 | STDMETHODIMP SetColorKey(DWORD dwFlags,__in LPDDCOLORKEY lpDDColorKey); 141 | STDMETHODIMP SetOverlayPosition(LONG dwX,LONG dwY); 142 | STDMETHODIMP SetPalette(__in LPDIRECTDRAWPALETTE lpDDPalette); 143 | STDMETHODIMP Unlock(__in LPVOID lpSurfaceData); 144 | STDMETHODIMP UpdateOverlay(__in LPRECT lpSrcRect,__in LPDIRECTDRAWSURFACE lpDDDestSurface,__in LPRECT lpDestRect,DWORD dwFlags,__in LPDDOVERLAYFX lpDDOverlayFX); 145 | STDMETHODIMP UpdateOverlayDisplay(DWORD dwFlags); 146 | STDMETHODIMP UpdateOverlayZOrder(DWORD dwFlags,__in LPDIRECTDRAWSURFACE lpDDSReference); 147 | }; 148 | 149 | 150 | class CLoadDirectDraw 151 | { 152 | LPDIRECTDRAW m_pDirectDraw; // The DirectDraw driver instance 153 | HINSTANCE m_hDirectDraw; // Handle to the loaded library 154 | 155 | public: 156 | 157 | CLoadDirectDraw(); 158 | ~CLoadDirectDraw(); 159 | 160 | HRESULT LoadDirectDraw(__in LPSTR szDevice); 161 | void ReleaseDirectDraw(); 162 | HRESULT IsDirectDrawLoaded(); 163 | LPDIRECTDRAW GetDirectDraw(); 164 | BOOL IsDirectDrawVersion1(); 165 | }; 166 | 167 | #endif // __VIDEOCTL__ 168 | 169 | -------------------------------------------------------------------------------- /Libs/BaseClasses/combase.cpp: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // File: ComBase.cpp 3 | // 4 | // Desc: DirectShow base classes - implements class hierarchy for creating 5 | // COM objects. 6 | // 7 | // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. 8 | //------------------------------------------------------------------------------ 9 | 10 | 11 | #include 12 | #pragma warning( disable : 4514 ) // Disable warnings re unused inline functions 13 | 14 | 15 | /* Define the static member variable */ 16 | 17 | LONG CBaseObject::m_cObjects = 0; 18 | 19 | 20 | /* Constructor */ 21 | 22 | CBaseObject::CBaseObject(__in_opt LPCTSTR pName) 23 | { 24 | /* Increment the number of active objects */ 25 | InterlockedIncrement(&m_cObjects); 26 | 27 | #ifdef DEBUG 28 | 29 | #ifdef UNICODE 30 | m_dwCookie = DbgRegisterObjectCreation(0, pName); 31 | #else 32 | m_dwCookie = DbgRegisterObjectCreation(pName, 0); 33 | #endif 34 | 35 | #endif 36 | } 37 | 38 | #ifdef UNICODE 39 | CBaseObject::CBaseObject(const char *pName) 40 | { 41 | /* Increment the number of active objects */ 42 | InterlockedIncrement(&m_cObjects); 43 | 44 | #ifdef DEBUG 45 | m_dwCookie = DbgRegisterObjectCreation(pName, 0); 46 | #endif 47 | } 48 | #endif 49 | 50 | HINSTANCE hlibOLEAut32; 51 | 52 | /* Destructor */ 53 | 54 | CBaseObject::~CBaseObject() 55 | { 56 | /* Decrement the number of objects active */ 57 | if (InterlockedDecrement(&m_cObjects) == 0) { 58 | if (hlibOLEAut32) { 59 | FreeLibrary(hlibOLEAut32); 60 | 61 | hlibOLEAut32 = 0; 62 | } 63 | }; 64 | 65 | 66 | #ifdef DEBUG 67 | DbgRegisterObjectDestruction(m_dwCookie); 68 | #endif 69 | } 70 | 71 | static const TCHAR szOle32Aut[] = TEXT("OleAut32.dll"); 72 | 73 | HINSTANCE LoadOLEAut32() 74 | { 75 | if (hlibOLEAut32 == 0) { 76 | 77 | hlibOLEAut32 = LoadLibrary(szOle32Aut); 78 | } 79 | 80 | return hlibOLEAut32; 81 | } 82 | 83 | 84 | /* Constructor */ 85 | 86 | // We know we use "this" in the initialization list, we also know we don't modify *phr. 87 | #pragma warning( disable : 4355 4100 ) 88 | CUnknown::CUnknown(__in_opt LPCTSTR pName, __in_opt LPUNKNOWN pUnk) 89 | : CBaseObject(pName) 90 | /* Start the object with a reference count of zero - when the */ 91 | /* object is queried for it's first interface this may be */ 92 | /* incremented depending on whether or not this object is */ 93 | /* currently being aggregated upon */ 94 | , m_cRef(0) 95 | /* Set our pointer to our IUnknown interface. */ 96 | /* If we have an outer, use its, otherwise use ours. */ 97 | /* This pointer effectivly points to the owner of */ 98 | /* this object and can be accessed by the GetOwner() method. */ 99 | , m_pUnknown( pUnk != 0 ? pUnk : reinterpret_cast( static_cast(this) ) ) 100 | /* Why the double cast? Well, the inner cast is a type-safe cast */ 101 | /* to pointer to a type from which we inherit. The second is */ 102 | /* type-unsafe but works because INonDelegatingUnknown "behaves */ 103 | /* like" IUnknown. (Only the names on the methods change.) */ 104 | { 105 | // Everything we need to do has been done in the initializer list 106 | } 107 | 108 | // This does the same as above except it has a useless HRESULT argument 109 | // use the previous constructor, this is just left for compatibility... 110 | CUnknown::CUnknown(__in_opt LPCTSTR pName, __in_opt LPUNKNOWN pUnk, __inout_opt HRESULT *phr) : 111 | CBaseObject(pName), 112 | m_cRef(0), 113 | m_pUnknown( pUnk != 0 ? pUnk : reinterpret_cast( static_cast(this) ) ) 114 | { 115 | } 116 | 117 | #ifdef UNICODE 118 | CUnknown::CUnknown(__in_opt LPCSTR pName, __in_opt LPUNKNOWN pUnk) 119 | : CBaseObject(pName), m_cRef(0), 120 | m_pUnknown( pUnk != 0 ? pUnk : reinterpret_cast( static_cast(this) ) ) 121 | { } 122 | 123 | CUnknown::CUnknown(__in_opt LPCSTR pName, __in_opt LPUNKNOWN pUnk, __inout_opt HRESULT *phr) : 124 | CBaseObject(pName), m_cRef(0), 125 | m_pUnknown( pUnk != 0 ? pUnk : reinterpret_cast( static_cast(this) ) ) 126 | { } 127 | 128 | #endif 129 | 130 | #pragma warning( default : 4355 4100 ) 131 | 132 | 133 | /* QueryInterface */ 134 | 135 | STDMETHODIMP CUnknown::NonDelegatingQueryInterface(REFIID riid, __deref_out void ** ppv) 136 | { 137 | CheckPointer(ppv,E_POINTER); 138 | ValidateReadWritePtr(ppv,sizeof(PVOID)); 139 | 140 | /* We know only about IUnknown */ 141 | 142 | if (riid == IID_IUnknown) { 143 | GetInterface((LPUNKNOWN) (PNDUNKNOWN) this, ppv); 144 | return NOERROR; 145 | } else { 146 | *ppv = NULL; 147 | return E_NOINTERFACE; 148 | } 149 | } 150 | 151 | /* We have to ensure that we DON'T use a max macro, since these will typically */ 152 | /* lead to one of the parameters being evaluated twice. Since we are worried */ 153 | /* about concurrency, we can't afford to access the m_cRef twice since we can't */ 154 | /* afford to run the risk that its value having changed between accesses. */ 155 | 156 | template inline static T ourmax( const T & a, const T & b ) 157 | { 158 | return a > b ? a : b; 159 | } 160 | 161 | /* AddRef */ 162 | 163 | STDMETHODIMP_(ULONG) CUnknown::NonDelegatingAddRef() 164 | { 165 | LONG lRef = InterlockedIncrement( &m_cRef ); 166 | ASSERT(lRef > 0); 167 | DbgLog((LOG_MEMORY,3,TEXT(" Obj %d ref++ = %d"), 168 | m_dwCookie, m_cRef)); 169 | return ourmax(ULONG(m_cRef), 1ul); 170 | } 171 | 172 | 173 | /* Release */ 174 | 175 | STDMETHODIMP_(ULONG) CUnknown::NonDelegatingRelease() 176 | { 177 | /* If the reference count drops to zero delete ourselves */ 178 | 179 | LONG lRef = InterlockedDecrement( &m_cRef ); 180 | ASSERT(lRef >= 0); 181 | 182 | DbgLog((LOG_MEMORY,3,TEXT(" Object %d ref-- = %d"), 183 | m_dwCookie, m_cRef)); 184 | if (lRef == 0) { 185 | 186 | // COM rules say we must protect against re-entrancy. 187 | // If we are an aggregator and we hold our own interfaces 188 | // on the aggregatee, the QI for these interfaces will 189 | // addref ourselves. So after doing the QI we must release 190 | // a ref count on ourselves. Then, before releasing the 191 | // private interface, we must addref ourselves. When we do 192 | // this from the destructor here it will result in the ref 193 | // count going to 1 and then back to 0 causing us to 194 | // re-enter the destructor. Hence we add an extra refcount here 195 | // once we know we will delete the object. 196 | // for an example aggregator see filgraph\distrib.cpp. 197 | 198 | m_cRef++; 199 | 200 | delete this; 201 | return ULONG(0); 202 | } else { 203 | // Don't touch m_cRef again even in this leg as the object 204 | // may have just been released on another thread too 205 | return ourmax(ULONG(lRef), 1ul); 206 | } 207 | } 208 | 209 | 210 | /* Return an interface pointer to a requesting client 211 | performing a thread safe AddRef as necessary */ 212 | 213 | STDAPI GetInterface(LPUNKNOWN pUnk, __out void **ppv) 214 | { 215 | CheckPointer(ppv, E_POINTER); 216 | *ppv = pUnk; 217 | pUnk->AddRef(); 218 | return NOERROR; 219 | } 220 | 221 | 222 | /* Compares two interfaces and returns TRUE if they are on the same object */ 223 | 224 | BOOL WINAPI IsEqualObject(IUnknown *pFirst, IUnknown *pSecond) 225 | { 226 | /* Different objects can't have the same interface pointer for 227 | any interface 228 | */ 229 | if (pFirst == pSecond) { 230 | return TRUE; 231 | } 232 | /* OK - do it the hard way - check if they have the same 233 | IUnknown pointers - a single object can only have one of these 234 | */ 235 | LPUNKNOWN pUnknown1; // Retrieve the IUnknown interface 236 | LPUNKNOWN pUnknown2; // Retrieve the other IUnknown interface 237 | HRESULT hr; // General OLE return code 238 | 239 | ASSERT(pFirst); 240 | ASSERT(pSecond); 241 | 242 | /* See if the IUnknown pointers match */ 243 | 244 | hr = pFirst->QueryInterface(IID_IUnknown,(void **) &pUnknown1); 245 | if (FAILED(hr)) { 246 | return FALSE; 247 | } 248 | ASSERT(pUnknown1); 249 | 250 | /* Release the extra interface we hold */ 251 | 252 | pUnknown1->Release(); 253 | 254 | hr = pSecond->QueryInterface(IID_IUnknown,(void **) &pUnknown2); 255 | if (FAILED(hr)) { 256 | return FALSE; 257 | } 258 | ASSERT(pUnknown2); 259 | 260 | /* Release the extra interface we hold */ 261 | 262 | pUnknown2->Release(); 263 | return (pUnknown1 == pUnknown2); 264 | } 265 | 266 | -------------------------------------------------------------------------------- /Libs/BaseClasses/measure.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // File: Measure.h 3 | // 4 | // Desc: DirectShow base classes. 5 | // 6 | // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. 7 | //------------------------------------------------------------------------------ 8 | 9 | 10 | /* 11 | The idea is to pepper the source code with interesting measurements and 12 | have the last few thousand of these recorded in a circular buffer that 13 | can be post-processed to give interesting numbers. 14 | 15 | WHAT THE LOG LOOKS LIKE: 16 | 17 | Time (sec) Type Delta Incident_Name 18 | 0.055,41 NOTE -. Incident Nine - Another note 19 | 0.055,42 NOTE 0.000,01 Incident Nine - Another note 20 | 0.055,44 NOTE 0.000,02 Incident Nine - Another note 21 | 0.055,45 STOP -. Incident Eight - Also random 22 | 0.055,47 START -. Incident Seven - Random 23 | 0.055,49 NOTE 0.000,05 Incident Nine - Another note 24 | ------- ---------------- 25 | 0.125,60 STOP 0.000,03 Msr_Stop 26 | 0.125,62 START -. Msr_Start 27 | 0.125,63 START -. Incident Two - Start/Stop 28 | 0.125,65 STOP 0.000,03 Msr_Start 29 | 0.125,66 START -. Msr_Stop 30 | 0.125,68 STOP 0.000,05 Incident Two - Start/Stop 31 | 0.125,70 STOP 0.000,04 Msr_Stop 32 | 0.125,72 START -. Msr_Start 33 | 0.125,73 START -. Incident Two - Start/Stop 34 | 0.125,75 STOP 0.000,03 Msr_Start 35 | 0.125,77 START -. Msr_Stop 36 | 0.125,78 STOP 0.000,05 Incident Two - Start/Stop 37 | 0.125,80 STOP 0.000,03 Msr_Stop 38 | 0.125,81 NOTE -. Incident Three - single Note 39 | 0.125,83 START -. Incident Four - Start, no stop 40 | 0.125,85 START -. Incident Five - Single Start/Stop 41 | 0.125,87 STOP 0.000,02 Incident Five - Single Start/Stop 42 | 43 | Number Average StdDev Smallest Largest Incident_Name 44 | 10 0.000,58 0.000,10 0.000,55 0.000,85 Incident One - Note 45 | 50 0.000,05 0.000,00 0.000,05 0.000,05 Incident Two - Start/Stop 46 | 1 -. -. -. -. Incident Three - single Note 47 | 0 -. -. -. -. Incident Four - Start, no stop 48 | 1 0.000,02 -. 0.000,02 0.000,02 Incident Five - Single Start/Stop 49 | 0 -. -. -. -. Incident Six - zero occurrences 50 | 100 0.000,25 0.000,12 0.000,02 0.000,62 Incident Seven - Random 51 | 100 0.000,79 0.000,48 0.000,02 0.001,92 Incident Eight - Also random 52 | 5895 0.000,01 0.000,01 0.000,01 0.000,56 Incident Nine - Another note 53 | 10 0.000,03 0.000,00 0.000,03 0.000,04 Msr_Note 54 | 50 0.000,03 0.000,00 0.000,03 0.000,04 Msr_Start 55 | 50 0.000,04 0.000,03 0.000,03 0.000,31 Msr_Stop 56 | 57 | WHAT IT MEANS: 58 | The log shows what happened and when. Each line shows the time at which 59 | something happened (see WHAT YOU CODE below) what it was that happened 60 | and (if approporate) the time since the corresponding previous event 61 | (that's the delta column). 62 | 63 | The statistics show how many times each event occurred, what the average 64 | delta time was, also the standard deviation, largest and smalles delta. 65 | 66 | WHAT YOU CODE: 67 | 68 | Before anything else executes: - register your ids 69 | 70 | int id1 = Msr_Register("Incident One - Note"); 71 | int id2 = Msr_Register("Incident Two - Start/Stop"); 72 | int id3 = Msr_Register("Incident Three - single Note"); 73 | etc. 74 | 75 | At interesting moments: 76 | 77 | // To measure a repetitive event - e.g. end of bitblt to screen 78 | Msr_Note(Id9); // e.g. "video frame hiting the screen NOW!" 79 | 80 | or 81 | 82 | // To measure an elapsed time e.g. time taken to decode an MPEG B-frame 83 | Msr_Start(Id2); // e.g. "Starting to decode MPEG B-frame" 84 | . . . 85 | MsrStop(Id2); // "Finished MPEG decode" 86 | 87 | At the end: 88 | 89 | HANDLE hFile; 90 | hFile = CreateFile("Perf.log", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); 91 | Msr_Dump(hFile); // This writes the log out to the file 92 | CloseHandle(hFile); 93 | 94 | or 95 | 96 | Msr_Dump(NULL); // This writes it to DbgLog((LOG_TRACE,0, ... )); 97 | // but if you are writing it out to the debugger 98 | // then the times are probably all garbage because 99 | // the debugger can make things run awfully slow. 100 | 101 | A given id should be used either for start / stop or Note calls. If Notes 102 | are mixed in with Starts and Stops their statistics will be gibberish. 103 | 104 | If you code the calls in upper case i.e. MSR_START(idMunge); then you get 105 | macros which will turn into nothing unless PERF is defined. 106 | 107 | You can reset the statistical counts for a given id by calling Reset(Id). 108 | They are reset by default at the start. 109 | It logs Reset as a special incident, so you can see it in the log. 110 | 111 | The log is a circular buffer in storage (to try to minimise disk I/O). 112 | It overwrites the oldest entries once full. The statistics include ALL 113 | incidents since the last Reset, whether still visible in the log or not. 114 | */ 115 | 116 | #ifndef __MEASURE__ 117 | #define __MEASURE__ 118 | 119 | #ifdef PERF 120 | #define MSR_INIT() Msr_Init() 121 | #define MSR_TERMINATE() Msr_Terminate() 122 | #define MSR_REGISTER(a) Msr_Register(a) 123 | #define MSR_RESET(a) Msr_Reset(a) 124 | #define MSR_CONTROL(a) Msr_Control(a) 125 | #define MSR_START(a) Msr_Start(a) 126 | #define MSR_STOP(a) Msr_Stop(a) 127 | #define MSR_NOTE(a) Msr_Note(a) 128 | #define MSR_INTEGER(a,b) Msr_Integer(a,b) 129 | #define MSR_DUMP(a) Msr_Dump(a) 130 | #define MSR_DUMPSTATS(a) Msr_DumpStats(a) 131 | #else 132 | #define MSR_INIT() ((void)0) 133 | #define MSR_TERMINATE() ((void)0) 134 | #define MSR_REGISTER(a) 0 135 | #define MSR_RESET(a) ((void)0) 136 | #define MSR_CONTROL(a) ((void)0) 137 | #define MSR_START(a) ((void)0) 138 | #define MSR_STOP(a) ((void)0) 139 | #define MSR_NOTE(a) ((void)0) 140 | #define MSR_INTEGER(a,b) ((void)0) 141 | #define MSR_DUMP(a) ((void)0) 142 | #define MSR_DUMPSTATS(a) ((void)0) 143 | #endif 144 | 145 | #ifdef __cplusplus 146 | extern "C" { 147 | #endif 148 | 149 | // This must be called first - (called by the DllEntry) 150 | 151 | void WINAPI Msr_Init(void); 152 | 153 | 154 | // Call this last to clean up (or just let it fall off the end - who cares?) 155 | 156 | void WINAPI Msr_Terminate(void); 157 | 158 | 159 | // Call this to get an Id for an "incident" that you can pass to Start, Stop or Note 160 | // everything that's logged is called an "incident". 161 | 162 | int WINAPI Msr_Register(__in LPTSTR Incident); 163 | 164 | 165 | // Reset the statistical counts for an incident 166 | 167 | void WINAPI Msr_Reset(int Id); 168 | 169 | 170 | // Reset all the counts for all incidents 171 | #define MSR_RESET_ALL 0 172 | #define MSR_PAUSE 1 173 | #define MSR_RUN 2 174 | 175 | void WINAPI Msr_Control(int iAction); 176 | 177 | 178 | // log the start of an operation 179 | 180 | void WINAPI Msr_Start(int Id); 181 | 182 | 183 | // log the end of an operation 184 | 185 | void WINAPI Msr_Stop(int Id); 186 | 187 | 188 | // log a one-off or repetitive operation 189 | 190 | void WINAPI Msr_Note(int Id); 191 | 192 | 193 | // log an integer (on which we can see statistics later) 194 | void WINAPI Msr_Integer(int Id, int n); 195 | 196 | 197 | // print out all the vaialable log (it may have wrapped) and then the statistics. 198 | // When the log wraps you lose log but the statistics are still complete. 199 | // hFIle==NULL => use DbgLog 200 | // otherwise hFile must have come from CreateFile or OpenFile. 201 | 202 | void WINAPI Msr_Dump(HANDLE hFile); 203 | 204 | 205 | // just dump the statistics - never mind the log 206 | 207 | void WINAPI Msr_DumpStats(HANDLE hFile); 208 | 209 | // Type definitions in case you want to declare a pointer to the dump functions 210 | // (makes it a trifle easier to do dynamic linking 211 | // i.e. LoadModule, GetProcAddress and call that) 212 | 213 | // Typedefs so can declare MSR_DUMPPROC *MsrDumpStats; or whatever 214 | typedef void WINAPI MSR_DUMPPROC(HANDLE hFile); 215 | typedef void WINAPI MSR_CONTROLPROC(int iAction); 216 | 217 | 218 | #ifdef __cplusplus 219 | } 220 | #endif 221 | 222 | #endif // __MEASURE__ 223 | -------------------------------------------------------------------------------- /Libs/BaseClasses/schedule.cpp: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // File: Schedule.cpp 3 | // 4 | // Desc: DirectShow base classes. 5 | // 6 | // Copyright (c) 1996-2001 Microsoft Corporation. All rights reserved. 7 | //------------------------------------------------------------------------------ 8 | 9 | 10 | #include 11 | 12 | // DbgLog values (all on LOG_TIMING): 13 | // 14 | // 2 for schedulting, firing and shunting of events 15 | // 3 for wait delays and wake-up times of event thread 16 | // 4 for details of whats on the list when the thread awakes 17 | 18 | /* Construct & destructors */ 19 | 20 | CAMSchedule::CAMSchedule( HANDLE ev ) 21 | : CBaseObject(TEXT("CAMSchedule")) 22 | , head(&z, 0), z(0, MAX_TIME) 23 | , m_dwNextCookie(0), m_dwAdviseCount(0) 24 | , m_pAdviseCache(0), m_dwCacheCount(0) 25 | , m_ev( ev ) 26 | { 27 | head.m_dwAdviseCookie = z.m_dwAdviseCookie = 0; 28 | } 29 | 30 | CAMSchedule::~CAMSchedule() 31 | { 32 | m_Serialize.Lock(); 33 | 34 | // Delete cache 35 | CAdvisePacket * p = m_pAdviseCache; 36 | while (p) 37 | { 38 | CAdvisePacket *const p_next = p->m_next; 39 | delete p; 40 | p = p_next; 41 | } 42 | 43 | ASSERT( m_dwAdviseCount == 0 ); 44 | // Better to be safe than sorry 45 | if ( m_dwAdviseCount > 0 ) 46 | { 47 | DumpLinkedList(); 48 | while ( !head.m_next->IsZ() ) 49 | { 50 | head.DeleteNext(); 51 | --m_dwAdviseCount; 52 | } 53 | } 54 | 55 | // If, in the debug version, we assert twice, it means, not only 56 | // did we have left over advises, but we have also let m_dwAdviseCount 57 | // get out of sync. with the number of advises actually on the list. 58 | ASSERT( m_dwAdviseCount == 0 ); 59 | 60 | m_Serialize.Unlock(); 61 | } 62 | 63 | /* Public methods */ 64 | 65 | DWORD CAMSchedule::GetAdviseCount() 66 | { 67 | // No need to lock, m_dwAdviseCount is 32bits & declared volatile 68 | return m_dwAdviseCount; 69 | } 70 | 71 | REFERENCE_TIME CAMSchedule::GetNextAdviseTime() 72 | { 73 | CAutoLock lck(&m_Serialize); // Need to stop the linked list from changing 74 | return head.m_next->m_rtEventTime; 75 | } 76 | 77 | DWORD_PTR CAMSchedule::AddAdvisePacket 78 | ( const REFERENCE_TIME & time1 79 | , const REFERENCE_TIME & time2 80 | , HANDLE h, BOOL periodic 81 | ) 82 | { 83 | // Since we use MAX_TIME as a sentry, we can't afford to 84 | // schedule a notification at MAX_TIME 85 | ASSERT( time1 < MAX_TIME ); 86 | DWORD_PTR Result; 87 | CAdvisePacket * p; 88 | 89 | m_Serialize.Lock(); 90 | 91 | if (m_pAdviseCache) 92 | { 93 | p = m_pAdviseCache; 94 | m_pAdviseCache = p->m_next; 95 | --m_dwCacheCount; 96 | } 97 | else 98 | { 99 | p = new CAdvisePacket(); 100 | } 101 | if (p) 102 | { 103 | p->m_rtEventTime = time1; p->m_rtPeriod = time2; 104 | p->m_hNotify = h; p->m_bPeriodic = periodic; 105 | Result = AddAdvisePacket( p ); 106 | } 107 | else Result = 0; 108 | 109 | m_Serialize.Unlock(); 110 | 111 | return Result; 112 | } 113 | 114 | HRESULT CAMSchedule::Unadvise(DWORD_PTR dwAdviseCookie) 115 | { 116 | HRESULT hr = S_FALSE; 117 | CAdvisePacket * p_prev = &head; 118 | CAdvisePacket * p_n; 119 | m_Serialize.Lock(); 120 | while ( p_n = p_prev->Next() ) // The Next() method returns NULL when it hits z 121 | { 122 | if ( p_n->m_dwAdviseCookie == dwAdviseCookie ) 123 | { 124 | Delete( p_prev->RemoveNext() ); 125 | --m_dwAdviseCount; 126 | hr = S_OK; 127 | // Having found one cookie that matches, there should be no more 128 | #ifdef DEBUG 129 | while (p_n = p_prev->Next()) 130 | { 131 | ASSERT(p_n->m_dwAdviseCookie != dwAdviseCookie); 132 | p_prev = p_n; 133 | } 134 | #endif 135 | break; 136 | } 137 | p_prev = p_n; 138 | }; 139 | m_Serialize.Unlock(); 140 | return hr; 141 | } 142 | 143 | REFERENCE_TIME CAMSchedule::Advise( const REFERENCE_TIME & rtTime ) 144 | { 145 | REFERENCE_TIME rtNextTime; 146 | CAdvisePacket * pAdvise; 147 | 148 | DbgLog((LOG_TIMING, 2, 149 | TEXT("CAMSchedule::Advise( %lu ms )"), ULONG(rtTime / (UNITS / MILLISECONDS)))); 150 | 151 | CAutoLock lck(&m_Serialize); 152 | 153 | #ifdef DEBUG 154 | if (DbgCheckModuleLevel(LOG_TIMING, 4)) DumpLinkedList(); 155 | #endif 156 | 157 | // Note - DON'T cache the difference, it might overflow 158 | while ( rtTime >= (rtNextTime = (pAdvise=head.m_next)->m_rtEventTime) && 159 | !pAdvise->IsZ() ) 160 | { 161 | ASSERT(pAdvise->m_dwAdviseCookie); // If this is zero, its the head or the tail!! 162 | 163 | ASSERT(pAdvise->m_hNotify != INVALID_HANDLE_VALUE); 164 | 165 | if (pAdvise->m_bPeriodic == TRUE) 166 | { 167 | ReleaseSemaphore(pAdvise->m_hNotify,1,NULL); 168 | pAdvise->m_rtEventTime += pAdvise->m_rtPeriod; 169 | ShuntHead(); 170 | } 171 | else 172 | { 173 | ASSERT( pAdvise->m_bPeriodic == FALSE ); 174 | EXECUTE_ASSERT(SetEvent(pAdvise->m_hNotify)); 175 | --m_dwAdviseCount; 176 | Delete( head.RemoveNext() ); 177 | } 178 | 179 | } 180 | 181 | DbgLog((LOG_TIMING, 3, 182 | TEXT("CAMSchedule::Advise() Next time stamp: %lu ms, for advise %lu."), 183 | DWORD(rtNextTime / (UNITS / MILLISECONDS)), pAdvise->m_dwAdviseCookie )); 184 | 185 | return rtNextTime; 186 | } 187 | 188 | /* Private methods */ 189 | 190 | DWORD_PTR CAMSchedule::AddAdvisePacket( __inout CAdvisePacket * pPacket ) 191 | { 192 | ASSERT(pPacket->m_rtEventTime >= 0 && pPacket->m_rtEventTime < MAX_TIME); 193 | ASSERT(CritCheckIn(&m_Serialize)); 194 | 195 | CAdvisePacket * p_prev = &head; 196 | CAdvisePacket * p_n; 197 | 198 | const DWORD_PTR Result = pPacket->m_dwAdviseCookie = ++m_dwNextCookie; 199 | // This relies on the fact that z is a sentry with a maximal m_rtEventTime 200 | for(;;p_prev = p_n) 201 | { 202 | p_n = p_prev->m_next; 203 | if ( p_n->m_rtEventTime >= pPacket->m_rtEventTime ) break; 204 | } 205 | p_prev->InsertAfter( pPacket ); 206 | ++m_dwAdviseCount; 207 | 208 | DbgLog((LOG_TIMING, 2, TEXT("Added advise %lu, for thread 0x%02X, scheduled at %lu"), 209 | pPacket->m_dwAdviseCookie, GetCurrentThreadId(), (pPacket->m_rtEventTime / (UNITS / MILLISECONDS)) )); 210 | 211 | // If packet added at the head, then clock needs to re-evaluate wait time. 212 | if ( p_prev == &head ) SetEvent( m_ev ); 213 | 214 | return Result; 215 | } 216 | 217 | void CAMSchedule::Delete( __inout CAdvisePacket * pPacket ) 218 | { 219 | if ( m_dwCacheCount >= dwCacheMax ) delete pPacket; 220 | else 221 | { 222 | m_Serialize.Lock(); 223 | pPacket->m_next = m_pAdviseCache; 224 | m_pAdviseCache = pPacket; 225 | ++m_dwCacheCount; 226 | m_Serialize.Unlock(); 227 | } 228 | } 229 | 230 | 231 | // Takes the head of the list & repositions it 232 | void CAMSchedule::ShuntHead() 233 | { 234 | CAdvisePacket * p_prev = &head; 235 | CAdvisePacket * p_n; 236 | 237 | m_Serialize.Lock(); 238 | CAdvisePacket *const pPacket = head.m_next; 239 | 240 | // This will catch both an empty list, 241 | // and if somehow a MAX_TIME time gets into the list 242 | // (which would also break this method). 243 | ASSERT( pPacket->m_rtEventTime < MAX_TIME ); 244 | 245 | // This relies on the fact that z is a sentry with a maximal m_rtEventTime 246 | for(;;p_prev = p_n) 247 | { 248 | p_n = p_prev->m_next; 249 | if ( p_n->m_rtEventTime > pPacket->m_rtEventTime ) break; 250 | } 251 | // If p_prev == pPacket then we're already in the right place 252 | if (p_prev != pPacket) 253 | { 254 | head.m_next = pPacket->m_next; 255 | (p_prev->m_next = pPacket)->m_next = p_n; 256 | } 257 | #ifdef DEBUG 258 | DbgLog((LOG_TIMING, 2, TEXT("Periodic advise %lu, shunted to %lu"), 259 | pPacket->m_dwAdviseCookie, (pPacket->m_rtEventTime / (UNITS / MILLISECONDS)) )); 260 | #endif 261 | m_Serialize.Unlock(); 262 | } 263 | 264 | 265 | #ifdef DEBUG 266 | void CAMSchedule::DumpLinkedList() 267 | { 268 | m_Serialize.Lock(); 269 | int i=0; 270 | DbgLog((LOG_TIMING, 1, TEXT("CAMSchedule::DumpLinkedList() this = 0x%p"), this)); 271 | for ( CAdvisePacket * p = &head 272 | ; p 273 | ; p = p->m_next , i++ 274 | ) 275 | { 276 | DbgLog((LOG_TIMING, 1, TEXT("Advise List # %lu, Cookie %d, RefTime %lu"), 277 | i, 278 | p->m_dwAdviseCookie, 279 | p->m_rtEventTime / (UNITS / MILLISECONDS) 280 | )); 281 | } 282 | m_Serialize.Unlock(); 283 | } 284 | #endif 285 | -------------------------------------------------------------------------------- /Libs/BaseClasses/transip.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // File: TransIP.h 3 | // 4 | // Desc: DirectShow base classes - defines classes from which simple 5 | // Transform-In-Place filters may be derived. 6 | // 7 | // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. 8 | //------------------------------------------------------------------------------ 9 | 10 | 11 | // 12 | // The difference between this and Transfrm.h is that Transfrm copies the data. 13 | // 14 | // It assumes the filter has one input and one output stream, and has no 15 | // interest in memory management, interface negotiation or anything else. 16 | // 17 | // Derive your class from this, and supply Transform and the media type/format 18 | // negotiation functions. Implement that class, compile and link and 19 | // you're done. 20 | 21 | 22 | #ifndef __TRANSIP__ 23 | #define __TRANSIP__ 24 | 25 | // ====================================================================== 26 | // This is the com object that represents a simple transform filter. It 27 | // supports IBaseFilter, IMediaFilter and two pins through nested interfaces 28 | // ====================================================================== 29 | 30 | class CTransInPlaceFilter; 31 | 32 | // Several of the pin functions call filter functions to do the work, 33 | // so you can often use the pin classes unaltered, just overriding the 34 | // functions in CTransInPlaceFilter. If that's not enough and you want 35 | // to derive your own pin class, override GetPin in the filter to supply 36 | // your own pin classes to the filter. 37 | 38 | // ================================================== 39 | // Implements the input pin 40 | // ================================================== 41 | 42 | class CTransInPlaceInputPin : public CTransformInputPin 43 | { 44 | 45 | protected: 46 | CTransInPlaceFilter * const m_pTIPFilter; // our filter 47 | BOOL m_bReadOnly; // incoming stream is read only 48 | 49 | public: 50 | 51 | CTransInPlaceInputPin( 52 | __in_opt LPCTSTR pObjectName, 53 | __inout CTransInPlaceFilter *pFilter, 54 | __inout HRESULT *phr, 55 | __in_opt LPCWSTR pName); 56 | 57 | // --- IMemInputPin ----- 58 | 59 | // Provide an enumerator for media types by getting one from downstream 60 | STDMETHODIMP EnumMediaTypes( __deref_out IEnumMediaTypes **ppEnum ); 61 | 62 | // Say whether media type is acceptable. 63 | HRESULT CheckMediaType(const CMediaType* pmt); 64 | 65 | // Return our upstream allocator 66 | STDMETHODIMP GetAllocator(__deref_out IMemAllocator ** ppAllocator); 67 | 68 | // get told which allocator the upstream output pin is actually 69 | // going to use. 70 | STDMETHODIMP NotifyAllocator(IMemAllocator * pAllocator, 71 | BOOL bReadOnly); 72 | 73 | // Allow the filter to see what allocator we have 74 | // N.B. This does NOT AddRef 75 | __out IMemAllocator * PeekAllocator() const 76 | { return m_pAllocator; } 77 | 78 | // Pass this on downstream if it ever gets called. 79 | STDMETHODIMP GetAllocatorRequirements(__out ALLOCATOR_PROPERTIES *pProps); 80 | 81 | HRESULT CompleteConnect(IPin *pReceivePin); 82 | 83 | inline const BOOL ReadOnly() { return m_bReadOnly ; } 84 | 85 | }; // CTransInPlaceInputPin 86 | 87 | // ================================================== 88 | // Implements the output pin 89 | // ================================================== 90 | 91 | class CTransInPlaceOutputPin : public CTransformOutputPin 92 | { 93 | 94 | protected: 95 | // m_pFilter points to our CBaseFilter 96 | CTransInPlaceFilter * const m_pTIPFilter; 97 | 98 | public: 99 | 100 | CTransInPlaceOutputPin( 101 | __in_opt LPCTSTR pObjectName, 102 | __inout CTransInPlaceFilter *pFilter, 103 | __inout HRESULT *phr, 104 | __in_opt LPCWSTR pName); 105 | 106 | 107 | // --- CBaseOutputPin ------------ 108 | 109 | // negotiate the allocator and its buffer size/count 110 | // Insists on using our own allocator. (Actually the one upstream of us). 111 | // We don't override this - instead we just agree the default 112 | // then let the upstream filter decide for itself on reconnect 113 | // virtual HRESULT DecideAllocator(IMemInputPin * pPin, IMemAllocator ** pAlloc); 114 | 115 | // Provide a media type enumerator. Get it from upstream. 116 | STDMETHODIMP EnumMediaTypes( __deref_out IEnumMediaTypes **ppEnum ); 117 | 118 | // Say whether media type is acceptable. 119 | HRESULT CheckMediaType(const CMediaType* pmt); 120 | 121 | // This just saves the allocator being used on the output pin 122 | // Also called by input pin's GetAllocator() 123 | void SetAllocator(IMemAllocator * pAllocator); 124 | 125 | __out_opt IMemInputPin * ConnectedIMemInputPin() 126 | { return m_pInputPin; } 127 | 128 | // Allow the filter to see what allocator we have 129 | // N.B. This does NOT AddRef 130 | __out IMemAllocator * PeekAllocator() const 131 | { return m_pAllocator; } 132 | 133 | HRESULT CompleteConnect(IPin *pReceivePin); 134 | 135 | }; // CTransInPlaceOutputPin 136 | 137 | 138 | class AM_NOVTABLE CTransInPlaceFilter : public CTransformFilter 139 | { 140 | 141 | public: 142 | 143 | // map getpin/getpincount for base enum of pins to owner 144 | // override this to return more specialised pin objects 145 | 146 | virtual CBasePin *GetPin(int n); 147 | 148 | public: 149 | 150 | // Set bModifiesData == false if your derived filter does 151 | // not modify the data samples (for instance it's just copying 152 | // them somewhere else or looking at the timestamps). 153 | 154 | CTransInPlaceFilter(__in_opt LPCTSTR, __inout_opt LPUNKNOWN, REFCLSID clsid, __inout HRESULT *, 155 | bool bModifiesData = true); 156 | #ifdef UNICODE 157 | CTransInPlaceFilter(__in_opt LPCSTR, __inout_opt LPUNKNOWN, REFCLSID clsid, __inout HRESULT *, 158 | bool bModifiesData = true); 159 | #endif 160 | // The following are defined to avoid undefined pure virtuals. 161 | // Even if they are never called, they will give linkage warnings/errors 162 | 163 | // We override EnumMediaTypes to bypass the transform class enumerator 164 | // which would otherwise call this. 165 | HRESULT GetMediaType(int iPosition, __inout CMediaType *pMediaType) 166 | { DbgBreak("CTransInPlaceFilter::GetMediaType should never be called"); 167 | return E_UNEXPECTED; 168 | } 169 | 170 | // This is called when we actually have to provide our own allocator. 171 | HRESULT DecideBufferSize(IMemAllocator*, __inout ALLOCATOR_PROPERTIES *); 172 | 173 | // The functions which call this in CTransform are overridden in this 174 | // class to call CheckInputType with the assumption that the type 175 | // does not change. In Debug builds some calls will be made and 176 | // we just ensure that they do not assert. 177 | HRESULT CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut) 178 | { 179 | return S_OK; 180 | }; 181 | 182 | 183 | // ================================================================= 184 | // ----- You may want to override this ----------------------------- 185 | // ================================================================= 186 | 187 | HRESULT CompleteConnect(PIN_DIRECTION dir,IPin *pReceivePin); 188 | 189 | // chance to customize the transform process 190 | virtual HRESULT Receive(IMediaSample *pSample); 191 | 192 | // ================================================================= 193 | // ----- You MUST override these ----------------------------------- 194 | // ================================================================= 195 | 196 | virtual HRESULT Transform(IMediaSample *pSample) PURE; 197 | 198 | // this goes in the factory template table to create new instances 199 | // static CCOMObject * CreateInstance(LPUNKNOWN, HRESULT *); 200 | 201 | 202 | #ifdef PERF 203 | // Override to register performance measurement with a less generic string 204 | // You should do this to avoid confusion with other filters 205 | virtual void RegisterPerfId() 206 | {m_idTransInPlace = MSR_REGISTER(TEXT("TransInPlace"));} 207 | #endif // PERF 208 | 209 | 210 | // implementation details 211 | 212 | protected: 213 | 214 | __out_opt IMediaSample * CTransInPlaceFilter::Copy(IMediaSample *pSource); 215 | 216 | #ifdef PERF 217 | int m_idTransInPlace; // performance measuring id 218 | #endif // PERF 219 | bool m_bModifiesData; // Does this filter change the data? 220 | 221 | // these hold our input and output pins 222 | 223 | friend class CTransInPlaceInputPin; 224 | friend class CTransInPlaceOutputPin; 225 | 226 | __out CTransInPlaceInputPin *InputPin() const 227 | { 228 | return (CTransInPlaceInputPin *)m_pInput; 229 | }; 230 | __out CTransInPlaceOutputPin *OutputPin() const 231 | { 232 | return (CTransInPlaceOutputPin *)m_pOutput; 233 | }; 234 | 235 | // Helper to see if the input and output types match 236 | BOOL TypesMatch() 237 | { 238 | return InputPin()->CurrentMediaType() == 239 | OutputPin()->CurrentMediaType(); 240 | } 241 | 242 | // Are the input and output allocators different? 243 | BOOL UsingDifferentAllocators() const 244 | { 245 | return InputPin()->PeekAllocator() != OutputPin()->PeekAllocator(); 246 | } 247 | }; // CTransInPlaceFilter 248 | 249 | #endif /* __TRANSIP__ */ 250 | 251 | -------------------------------------------------------------------------------- /Libs/BaseClasses/perflog.cpp: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // File: perflog.cpp 3 | // 4 | // Desc: Macros for DirectShow performance logging. 5 | // 6 | // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. 7 | //------------------------------------------------------------------------------ 8 | 9 | #pragma warning (disable:4201) 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include "perflog.h" 19 | 20 | // 21 | // Local function prototypes. 22 | // 23 | 24 | ULONG 25 | WINAPI 26 | PerflogCallback ( 27 | WMIDPREQUESTCODE RequestCode, 28 | __in PVOID Context, 29 | __out ULONG* BufferSize, 30 | __in PVOID Buffer 31 | ); 32 | 33 | // 34 | // Event tracing function pointers. 35 | // We have to do this to run on down-level platforms. 36 | // 37 | 38 | #ifdef UNICODE 39 | 40 | ULONG 41 | (__stdcall * _RegisterTraceGuids) ( 42 | __in IN WMIDPREQUEST RequestAddress, 43 | __in IN PVOID RequestContext, 44 | IN LPCGUID ControlGuid, 45 | IN ULONG GuidCount, 46 | __in IN PTRACE_GUID_REGISTRATION TraceGuidReg, 47 | IN LPCWSTR MofImagePath, 48 | IN LPCWSTR MofResourceName, 49 | OUT PTRACEHANDLE RegistrationHandle 50 | ); 51 | 52 | #define REGISTERTRACEGUIDS_NAME "RegisterTraceGuidsW" 53 | 54 | #else 55 | 56 | ULONG 57 | (__stdcall * _RegisterTraceGuids) ( 58 | __in IN WMIDPREQUEST RequestAddress, 59 | __in IN PVOID RequestContext, 60 | IN LPCGUID ControlGuid, 61 | IN ULONG GuidCount, 62 | __in IN PTRACE_GUID_REGISTRATION TraceGuidReg, 63 | IN LPCSTR MofImagePath, 64 | IN LPCSTR MofResourceName, 65 | __out OUT PTRACEHANDLE RegistrationHandle 66 | ); 67 | 68 | #define REGISTERTRACEGUIDS_NAME "RegisterTraceGuidsA" 69 | 70 | #endif 71 | 72 | ULONG 73 | (__stdcall * _UnregisterTraceGuids) ( 74 | TRACEHANDLE RegistrationHandle 75 | ); 76 | 77 | TRACEHANDLE 78 | (__stdcall * _GetTraceLoggerHandle) ( 79 | __in PVOID Buffer 80 | ); 81 | 82 | UCHAR 83 | (__stdcall * _GetTraceEnableLevel) ( 84 | TRACEHANDLE TraceHandle 85 | ); 86 | 87 | ULONG 88 | (__stdcall * _GetTraceEnableFlags) ( 89 | TRACEHANDLE TraceHandle 90 | ); 91 | 92 | ULONG 93 | (__stdcall * _TraceEvent) ( 94 | TRACEHANDLE TraceHandle, 95 | __in PEVENT_TRACE_HEADER EventTrace 96 | ); 97 | 98 | HINSTANCE _Advapi32; 99 | 100 | // 101 | // Global variables. 102 | // 103 | 104 | BOOL EventTracingAvailable=FALSE; 105 | ULONG PerflogEnableFlags; 106 | UCHAR PerflogEnableLevel; 107 | ULONG PerflogModuleLevel = 0; 108 | void (*OnStateChanged)(void); 109 | TRACEHANDLE PerflogTraceHandle=NULL; 110 | TRACEHANDLE PerflogRegHandle; 111 | 112 | // The Win32 wsprintf() function writes a maximum of 1024 characters to it's output buffer. 113 | // See the documentation for wsprintf()'s lpOut parameter for more information. 114 | const INT iDEBUGINFO = 1024; // Used to format strings 115 | 116 | // 117 | // This routine initializes performance logging. 118 | // It should be called from DllMain(). 119 | // 120 | 121 | 122 | VOID 123 | PerflogReadModuleLevel( 124 | HINSTANCE hInstance 125 | ) 126 | { 127 | LONG lReturn; // Create key return value 128 | TCHAR szInfo[iDEBUGINFO]; // Constructs key names 129 | TCHAR szFullName[iDEBUGINFO]; // Load the full path and module name 130 | HKEY hModuleKey; // Module key handle 131 | LPTSTR pName; // Searches from the end for a backslash 132 | DWORD dwKeySize, dwKeyType, dwKeyValue; 133 | 134 | DWORD dwSize = GetModuleFileName( 135 | (hInstance ? hInstance : GetModuleHandle( NULL )), 136 | szFullName, 137 | iDEBUGINFO ); 138 | 139 | if (0 == dwSize || iDEBUGINFO == dwSize) { 140 | return; 141 | } 142 | 143 | pName = _tcsrchr(szFullName,'\\'); 144 | if (pName == NULL) { 145 | pName = szFullName; 146 | } else { 147 | pName++; 148 | } 149 | 150 | /* Construct the base key name */ 151 | (void)StringCchPrintf(szInfo,NUMELMS(szInfo),TEXT("SOFTWARE\\Debug\\%s"),pName); 152 | 153 | /* Open the key for this module */ 154 | lReturn = 155 | RegOpenKeyEx( 156 | HKEY_LOCAL_MACHINE, // Handle of an open key 157 | szInfo, // Address of subkey name 158 | (DWORD) 0, // Reserved value 159 | KEY_QUERY_VALUE, // Desired security access 160 | &hModuleKey ); // Opened handle buffer 161 | 162 | if (lReturn != ERROR_SUCCESS) { 163 | return; 164 | } 165 | 166 | dwKeySize = sizeof(DWORD); 167 | lReturn = RegQueryValueEx( 168 | hModuleKey, // Handle to an open key 169 | TEXT("PERFLOG"), 170 | NULL, // Reserved field 171 | &dwKeyType, // Returns the field type 172 | (LPBYTE) &dwKeyValue, // Returns the field's value 173 | &dwKeySize ); // Number of bytes transferred 174 | 175 | if ((lReturn == ERROR_SUCCESS) && (dwKeyType == REG_DWORD)) 176 | { 177 | PerflogModuleLevel = dwKeyValue; 178 | } 179 | 180 | RegCloseKey(hModuleKey); 181 | } 182 | 183 | BOOL PerflogInitIfEnabled( 184 | IN HINSTANCE hInstance, 185 | __in IN PPERFLOG_LOGGING_PARAMS LogParams 186 | ) 187 | { 188 | PerflogReadModuleLevel( hInstance ); 189 | if (PerflogModuleLevel) 190 | { 191 | return PerflogInitialize( LogParams ); 192 | } 193 | else 194 | { 195 | return FALSE; 196 | } 197 | } 198 | 199 | BOOL 200 | PerflogInitialize ( 201 | __in IN PPERFLOG_LOGGING_PARAMS LogParams 202 | ) 203 | { 204 | ULONG status; 205 | 206 | // 207 | // If we're running on a recent-enough platform, this will get 208 | // pointers to the event tracing routines. 209 | // 210 | 211 | _Advapi32 = GetModuleHandle (_T("ADVAPI32.DLL")); 212 | if (_Advapi32 == NULL) { 213 | return FALSE; 214 | } 215 | 216 | *((FARPROC*) &_RegisterTraceGuids) = GetProcAddress (_Advapi32, REGISTERTRACEGUIDS_NAME); 217 | *((FARPROC*) &_UnregisterTraceGuids) = GetProcAddress (_Advapi32, "UnregisterTraceGuids"); 218 | *((FARPROC*) &_GetTraceLoggerHandle) = GetProcAddress (_Advapi32, "GetTraceLoggerHandle"); 219 | *((FARPROC*) &_GetTraceEnableLevel) = GetProcAddress (_Advapi32, "GetTraceEnableLevel"); 220 | *((FARPROC*) &_GetTraceEnableFlags) = GetProcAddress (_Advapi32, "GetTraceEnableFlags"); 221 | *((FARPROC*) &_TraceEvent) = GetProcAddress (_Advapi32, "TraceEvent"); 222 | 223 | if (_RegisterTraceGuids == NULL || 224 | _UnregisterTraceGuids == NULL || 225 | _GetTraceEnableLevel == NULL || 226 | _GetTraceEnableFlags == NULL || 227 | _TraceEvent == NULL) { 228 | 229 | return FALSE; 230 | } 231 | 232 | EventTracingAvailable = TRUE; 233 | 234 | OnStateChanged = LogParams->OnStateChanged; 235 | 236 | // 237 | // Register our GUIDs. 238 | // 239 | 240 | status = _RegisterTraceGuids (PerflogCallback, 241 | LogParams, 242 | &LogParams->ControlGuid, 243 | LogParams->NumberOfTraceGuids, 244 | LogParams->TraceGuids, 245 | NULL, 246 | NULL, 247 | &PerflogRegHandle); 248 | 249 | return (status == ERROR_SUCCESS); 250 | } 251 | 252 | // 253 | // This routine shuts down performance logging. 254 | // 255 | 256 | VOID 257 | PerflogShutdown ( 258 | VOID 259 | ) 260 | { 261 | if (!EventTracingAvailable) { 262 | return; 263 | } 264 | 265 | _UnregisterTraceGuids (PerflogRegHandle); 266 | PerflogRegHandle = NULL; 267 | PerflogTraceHandle = NULL; 268 | } 269 | 270 | // 271 | // Event tracing callback routine. 272 | // It's called when controllers call event tracing control functions. 273 | // 274 | 275 | ULONG 276 | WINAPI 277 | PerflogCallback ( 278 | WMIDPREQUESTCODE RequestCode, 279 | __in PVOID Context, 280 | __out ULONG* BufferSize, 281 | __in PVOID Buffer 282 | ) 283 | { 284 | ULONG status; 285 | 286 | UNREFERENCED_PARAMETER (Context); 287 | 288 | ASSERT (EventTracingAvailable); 289 | 290 | status = ERROR_SUCCESS; 291 | 292 | switch (RequestCode) { 293 | 294 | case WMI_ENABLE_EVENTS: 295 | PerflogTraceHandle = _GetTraceLoggerHandle (Buffer); 296 | PerflogEnableFlags = _GetTraceEnableFlags (PerflogTraceHandle); 297 | PerflogEnableLevel = _GetTraceEnableLevel (PerflogTraceHandle); 298 | break; 299 | 300 | case WMI_DISABLE_EVENTS: 301 | PerflogTraceHandle = NULL; 302 | PerflogEnableFlags = 0; 303 | PerflogEnableLevel = 0; 304 | break; 305 | 306 | default: 307 | status = ERROR_INVALID_PARAMETER; 308 | } 309 | 310 | if (OnStateChanged != NULL) { 311 | OnStateChanged(); 312 | } 313 | 314 | *BufferSize = 0; 315 | return status; 316 | } 317 | 318 | // 319 | // Logging routine. 320 | // 321 | 322 | VOID 323 | PerflogTraceEvent ( 324 | __in PEVENT_TRACE_HEADER Event 325 | ) 326 | { 327 | if (!EventTracingAvailable) { 328 | return; 329 | } 330 | 331 | _TraceEvent (PerflogTraceHandle, Event); 332 | } 333 | 334 | VOID 335 | PerflogTraceEventLevel( 336 | ULONG Level, 337 | __in PEVENT_TRACE_HEADER Event 338 | ) 339 | { 340 | if ((!EventTracingAvailable) || (Level <= PerflogModuleLevel)) { 341 | return; 342 | } 343 | 344 | _TraceEvent (PerflogTraceHandle, Event); 345 | } 346 | 347 | 348 | -------------------------------------------------------------------------------- /Libs/BaseClasses/amvideo.cpp: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // File: AMVideo.cpp 3 | // 4 | // Desc: DirectShow base classes - implements helper functions for 5 | // bitmap formats. 6 | // 7 | // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. 8 | //------------------------------------------------------------------------------ 9 | 10 | 11 | #include 12 | #include 13 | 14 | // These are bit field masks for true colour devices 15 | 16 | const DWORD bits555[] = {0x007C00,0x0003E0,0x00001F}; 17 | const DWORD bits565[] = {0x00F800,0x0007E0,0x00001F}; 18 | const DWORD bits888[] = {0xFF0000,0x00FF00,0x0000FF}; 19 | 20 | // This maps bitmap subtypes into a bits per pixel value and also a 21 | // name. unicode and ansi versions are stored because we have to 22 | // return a pointer to a static string. 23 | const struct { 24 | const GUID *pSubtype; 25 | WORD BitCount; 26 | CHAR *pName; 27 | WCHAR *wszName; 28 | } BitCountMap[] = { &MEDIASUBTYPE_RGB1, 1, "RGB Monochrome", L"RGB Monochrome", 29 | &MEDIASUBTYPE_RGB4, 4, "RGB VGA", L"RGB VGA", 30 | &MEDIASUBTYPE_RGB8, 8, "RGB 8", L"RGB 8", 31 | &MEDIASUBTYPE_RGB565, 16, "RGB 565 (16 bit)", L"RGB 565 (16 bit)", 32 | &MEDIASUBTYPE_RGB555, 16, "RGB 555 (16 bit)", L"RGB 555 (16 bit)", 33 | &MEDIASUBTYPE_RGB24, 24, "RGB 24", L"RGB 24", 34 | &MEDIASUBTYPE_RGB32, 32, "RGB 32", L"RGB 32", 35 | &MEDIASUBTYPE_ARGB32, 32, "ARGB 32", L"ARGB 32", 36 | &MEDIASUBTYPE_Overlay, 0, "Overlay", L"Overlay", 37 | &GUID_NULL, 0, "UNKNOWN", L"UNKNOWN" 38 | }; 39 | 40 | // Return the size of the bitmap as defined by this header 41 | 42 | STDAPI_(DWORD) GetBitmapSize(const BITMAPINFOHEADER *pHeader) 43 | { 44 | return DIBSIZE(*pHeader); 45 | } 46 | 47 | 48 | // This is called if the header has a 16 bit colour depth and needs to work 49 | // out the detailed type from the bit fields (either RGB 565 or RGB 555) 50 | 51 | STDAPI_(const GUID) GetTrueColorType(const BITMAPINFOHEADER *pbmiHeader) 52 | { 53 | BITMAPINFO *pbmInfo = (BITMAPINFO *) pbmiHeader; 54 | ASSERT(pbmiHeader->biBitCount == 16); 55 | 56 | // If its BI_RGB then it's RGB 555 by default 57 | 58 | if (pbmiHeader->biCompression == BI_RGB) { 59 | return MEDIASUBTYPE_RGB555; 60 | } 61 | 62 | // Compare the bit fields with RGB 555 63 | 64 | DWORD *pMask = (DWORD *) pbmInfo->bmiColors; 65 | if (pMask[0] == bits555[0]) { 66 | if (pMask[1] == bits555[1]) { 67 | if (pMask[2] == bits555[2]) { 68 | return MEDIASUBTYPE_RGB555; 69 | } 70 | } 71 | } 72 | 73 | // Compare the bit fields with RGB 565 74 | 75 | pMask = (DWORD *) pbmInfo->bmiColors; 76 | if (pMask[0] == bits565[0]) { 77 | if (pMask[1] == bits565[1]) { 78 | if (pMask[2] == bits565[2]) { 79 | return MEDIASUBTYPE_RGB565; 80 | } 81 | } 82 | } 83 | return GUID_NULL; 84 | } 85 | 86 | 87 | // Given a BITMAPINFOHEADER structure this returns the GUID sub type that is 88 | // used to describe it in format negotiations. For example a video codec fills 89 | // in the format block with a VIDEOINFO structure, it also fills in the major 90 | // type with MEDIATYPE_VIDEO and the subtype with a GUID that matches the bit 91 | // count, for example if it is an eight bit image then MEDIASUBTYPE_RGB8 92 | 93 | STDAPI_(const GUID) GetBitmapSubtype(const BITMAPINFOHEADER *pbmiHeader) 94 | { 95 | ASSERT(pbmiHeader); 96 | 97 | // If it's not RGB then create a GUID from the compression type 98 | 99 | if (pbmiHeader->biCompression != BI_RGB) { 100 | if (pbmiHeader->biCompression != BI_BITFIELDS) { 101 | FOURCCMap FourCCMap(pbmiHeader->biCompression); 102 | return (const GUID) FourCCMap; 103 | } 104 | } 105 | 106 | // Map the RGB DIB bit depth to a image GUID 107 | 108 | switch(pbmiHeader->biBitCount) { 109 | case 1 : return MEDIASUBTYPE_RGB1; 110 | case 4 : return MEDIASUBTYPE_RGB4; 111 | case 8 : return MEDIASUBTYPE_RGB8; 112 | case 16 : return GetTrueColorType(pbmiHeader); 113 | case 24 : return MEDIASUBTYPE_RGB24; 114 | case 32 : return MEDIASUBTYPE_RGB32; 115 | } 116 | return GUID_NULL; 117 | } 118 | 119 | 120 | // Given a video bitmap subtype we return the number of bits per pixel it uses 121 | // We return a WORD bit count as thats what the BITMAPINFOHEADER uses. If the 122 | // GUID subtype is not found in the table we return an invalid USHRT_MAX 123 | 124 | STDAPI_(WORD) GetBitCount(const GUID *pSubtype) 125 | { 126 | ASSERT(pSubtype); 127 | const GUID *pMediaSubtype; 128 | INT iPosition = 0; 129 | 130 | // Scan the mapping list seeing if the source GUID matches any known 131 | // bitmap subtypes, the list is terminated by a GUID_NULL entry 132 | 133 | while (TRUE) { 134 | pMediaSubtype = BitCountMap[iPosition].pSubtype; 135 | if (IsEqualGUID(*pMediaSubtype,GUID_NULL)) { 136 | return USHRT_MAX; 137 | } 138 | if (IsEqualGUID(*pMediaSubtype,*pSubtype)) { 139 | return BitCountMap[iPosition].BitCount; 140 | } 141 | iPosition++; 142 | } 143 | } 144 | 145 | 146 | // Given a bitmap subtype we return a description name that can be used for 147 | // debug purposes. In a retail build this function still returns the names 148 | // If the subtype isn't found in the lookup table we return string UNKNOWN 149 | 150 | int LocateSubtype(const GUID *pSubtype) 151 | { 152 | ASSERT(pSubtype); 153 | const GUID *pMediaSubtype; 154 | INT iPosition = 0; 155 | 156 | // Scan the mapping list seeing if the source GUID matches any known 157 | // bitmap subtypes, the list is terminated by a GUID_NULL entry 158 | 159 | while (TRUE) { 160 | pMediaSubtype = BitCountMap[iPosition].pSubtype; 161 | if (IsEqualGUID(*pMediaSubtype,*pSubtype) || 162 | IsEqualGUID(*pMediaSubtype,GUID_NULL) 163 | ) 164 | { 165 | break; 166 | } 167 | 168 | iPosition++; 169 | } 170 | 171 | return iPosition; 172 | } 173 | 174 | 175 | 176 | STDAPI_(WCHAR *) GetSubtypeNameW(const GUID *pSubtype) 177 | { 178 | return BitCountMap[LocateSubtype(pSubtype)].wszName; 179 | } 180 | 181 | STDAPI_(CHAR *) GetSubtypeNameA(const GUID *pSubtype) 182 | { 183 | return BitCountMap[LocateSubtype(pSubtype)].pName; 184 | } 185 | 186 | #ifndef GetSubtypeName 187 | #error wxutil.h should have defined GetSubtypeName 188 | #endif 189 | #undef GetSubtypeName 190 | 191 | // this is here for people that linked to it directly; most people 192 | // would use the header file that picks the A or W version. 193 | STDAPI_(CHAR *) GetSubtypeName(const GUID *pSubtype) 194 | { 195 | return GetSubtypeNameA(pSubtype); 196 | } 197 | 198 | 199 | // The mechanism for describing a bitmap format is with the BITMAPINFOHEADER 200 | // This is really messy to deal with because it invariably has fields that 201 | // follow it holding bit fields, palettes and the rest. This function gives 202 | // the number of bytes required to hold a VIDEOINFO that represents it. This 203 | // count includes the prefix information (like the rcSource rectangle) the 204 | // BITMAPINFOHEADER field, and any other colour information on the end. 205 | // 206 | // WARNING If you want to copy a BITMAPINFOHEADER into a VIDEOINFO always make 207 | // sure that you use the HEADER macro because the BITMAPINFOHEADER field isn't 208 | // right at the start of the VIDEOINFO (there are a number of other fields), 209 | // 210 | // CopyMemory(HEADER(pVideoInfo),pbmi,sizeof(BITMAPINFOHEADER)); 211 | // 212 | 213 | STDAPI_(LONG) GetBitmapFormatSize(const BITMAPINFOHEADER *pHeader) 214 | { 215 | // Everyone has this to start with this 216 | LONG Size = SIZE_PREHEADER + pHeader->biSize; 217 | 218 | ASSERT(pHeader->biSize >= sizeof(BITMAPINFOHEADER)); 219 | 220 | // Does this format use a palette, if the number of colours actually used 221 | // is zero then it is set to the maximum that are allowed for that colour 222 | // depth (an example is 256 for eight bits). Truecolour formats may also 223 | // pass a palette with them in which case the used count is non zero 224 | 225 | // This would scare me. 226 | ASSERT(pHeader->biBitCount <= iPALETTE || pHeader->biClrUsed == 0); 227 | 228 | if (pHeader->biBitCount <= iPALETTE || pHeader->biClrUsed) { 229 | LONG Entries = (DWORD) 1 << pHeader->biBitCount; 230 | if (pHeader->biClrUsed) { 231 | Entries = pHeader->biClrUsed; 232 | } 233 | Size += Entries * sizeof(RGBQUAD); 234 | } 235 | 236 | // Truecolour formats may have a BI_BITFIELDS specifier for compression 237 | // type which means that room for three DWORDs should be allocated that 238 | // specify where in each pixel the RGB colour components may be found 239 | 240 | if (pHeader->biCompression == BI_BITFIELDS) { 241 | Size += SIZE_MASKS; 242 | } 243 | 244 | // A BITMAPINFO for a palettised image may also contain a palette map that 245 | // provides the information to map from a source palette to a destination 246 | // palette during a BitBlt for example, because this information is only 247 | // ever processed during drawing you don't normally store the palette map 248 | // nor have any way of knowing if it is present in the data structure 249 | 250 | return Size; 251 | } 252 | 253 | 254 | // Returns TRUE if the VIDEOINFO contains a palette 255 | 256 | STDAPI_(BOOL) ContainsPalette(const VIDEOINFOHEADER *pVideoInfo) 257 | { 258 | if (PALETTISED(pVideoInfo) == FALSE) { 259 | if (pVideoInfo->bmiHeader.biClrUsed == 0) { 260 | return FALSE; 261 | } 262 | } 263 | return TRUE; 264 | } 265 | 266 | 267 | // Return a pointer to the first entry in a palette 268 | 269 | STDAPI_(const RGBQUAD *) GetBitmapPalette(const VIDEOINFOHEADER *pVideoInfo) 270 | { 271 | if (pVideoInfo->bmiHeader.biCompression == BI_BITFIELDS) { 272 | return TRUECOLOR(pVideoInfo)->bmiColors; 273 | } 274 | return COLORS(pVideoInfo); 275 | } 276 | -------------------------------------------------------------------------------- /Libs/BaseClasses/transfrm.h: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // File: Transfrm.h 3 | // 4 | // Desc: DirectShow base classes - defines classes from which simple 5 | // transform codecs may be derived. 6 | // 7 | // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. 8 | //------------------------------------------------------------------------------ 9 | 10 | 11 | // It assumes the codec has one input and one output stream, and has no 12 | // interest in memory management, interface negotiation or anything else. 13 | // 14 | // derive your class from this, and supply Transform and the media type/format 15 | // negotiation functions. Implement that class, compile and link and 16 | // you're done. 17 | 18 | 19 | #ifndef __TRANSFRM__ 20 | #define __TRANSFRM__ 21 | 22 | // ====================================================================== 23 | // This is the com object that represents a simple transform filter. It 24 | // supports IBaseFilter, IMediaFilter and two pins through nested interfaces 25 | // ====================================================================== 26 | 27 | class CTransformFilter; 28 | 29 | // ================================================== 30 | // Implements the input pin 31 | // ================================================== 32 | 33 | class CTransformInputPin : public CBaseInputPin 34 | { 35 | friend class CTransformFilter; 36 | 37 | protected: 38 | CTransformFilter *m_pTransformFilter; 39 | 40 | 41 | public: 42 | 43 | CTransformInputPin( 44 | __in_opt LPCTSTR pObjectName, 45 | __inout CTransformFilter *pTransformFilter, 46 | __inout HRESULT * phr, 47 | __in_opt LPCWSTR pName); 48 | #ifdef UNICODE 49 | CTransformInputPin( 50 | __in_opt LPCSTR pObjectName, 51 | __inout CTransformFilter *pTransformFilter, 52 | __inout HRESULT * phr, 53 | __in_opt LPCWSTR pName); 54 | #endif 55 | 56 | STDMETHODIMP QueryId(__deref_out LPWSTR * Id) 57 | { 58 | return AMGetWideString(L"In", Id); 59 | } 60 | 61 | // Grab and release extra interfaces if required 62 | 63 | HRESULT CheckConnect(IPin *pPin); 64 | HRESULT BreakConnect(); 65 | HRESULT CompleteConnect(IPin *pReceivePin); 66 | 67 | // check that we can support this output type 68 | HRESULT CheckMediaType(const CMediaType* mtIn); 69 | 70 | // set the connection media type 71 | HRESULT SetMediaType(const CMediaType* mt); 72 | 73 | // --- IMemInputPin ----- 74 | 75 | // here's the next block of data from the stream. 76 | // AddRef it yourself if you need to hold it beyond the end 77 | // of this call. 78 | STDMETHODIMP Receive(IMediaSample * pSample); 79 | 80 | // provide EndOfStream that passes straight downstream 81 | // (there is no queued data) 82 | STDMETHODIMP EndOfStream(void); 83 | 84 | // passes it to CTransformFilter::BeginFlush 85 | STDMETHODIMP BeginFlush(void); 86 | 87 | // passes it to CTransformFilter::EndFlush 88 | STDMETHODIMP EndFlush(void); 89 | 90 | STDMETHODIMP NewSegment( 91 | REFERENCE_TIME tStart, 92 | REFERENCE_TIME tStop, 93 | double dRate); 94 | 95 | // Check if it's OK to process samples 96 | virtual HRESULT CheckStreaming(); 97 | 98 | // Media type 99 | public: 100 | CMediaType& CurrentMediaType() { return m_mt; }; 101 | 102 | }; 103 | 104 | // ================================================== 105 | // Implements the output pin 106 | // ================================================== 107 | 108 | class CTransformOutputPin : public CBaseOutputPin 109 | { 110 | friend class CTransformFilter; 111 | 112 | protected: 113 | CTransformFilter *m_pTransformFilter; 114 | 115 | public: 116 | 117 | // implement IMediaPosition by passing upstream 118 | IUnknown * m_pPosition; 119 | 120 | CTransformOutputPin( 121 | __in_opt LPCTSTR pObjectName, 122 | __inout CTransformFilter *pTransformFilter, 123 | __inout HRESULT * phr, 124 | __in_opt LPCWSTR pName); 125 | #ifdef UNICODE 126 | CTransformOutputPin( 127 | __in_opt LPCSTR pObjectName, 128 | __inout CTransformFilter *pTransformFilter, 129 | __inout HRESULT * phr, 130 | __in_opt LPCWSTR pName); 131 | #endif 132 | ~CTransformOutputPin(); 133 | 134 | // override to expose IMediaPosition 135 | STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv); 136 | 137 | // --- CBaseOutputPin ------------ 138 | 139 | STDMETHODIMP QueryId(__deref_out LPWSTR * Id) 140 | { 141 | return AMGetWideString(L"Out", Id); 142 | } 143 | 144 | // Grab and release extra interfaces if required 145 | 146 | HRESULT CheckConnect(IPin *pPin); 147 | HRESULT BreakConnect(); 148 | HRESULT CompleteConnect(IPin *pReceivePin); 149 | 150 | // check that we can support this output type 151 | HRESULT CheckMediaType(const CMediaType* mtOut); 152 | 153 | // set the connection media type 154 | HRESULT SetMediaType(const CMediaType *pmt); 155 | 156 | // called from CBaseOutputPin during connection to ask for 157 | // the count and size of buffers we need. 158 | HRESULT DecideBufferSize( 159 | IMemAllocator * pAlloc, 160 | __inout ALLOCATOR_PROPERTIES *pProp); 161 | 162 | // returns the preferred formats for a pin 163 | HRESULT GetMediaType(int iPosition, __inout CMediaType *pMediaType); 164 | 165 | // inherited from IQualityControl via CBasePin 166 | STDMETHODIMP Notify(IBaseFilter * pSender, Quality q); 167 | 168 | // Media type 169 | public: 170 | CMediaType& CurrentMediaType() { return m_mt; }; 171 | }; 172 | 173 | 174 | class AM_NOVTABLE CTransformFilter : public CBaseFilter 175 | { 176 | 177 | public: 178 | 179 | // map getpin/getpincount for base enum of pins to owner 180 | // override this to return more specialised pin objects 181 | 182 | virtual int GetPinCount(); 183 | virtual CBasePin * GetPin(int n); 184 | STDMETHODIMP FindPin(LPCWSTR Id, __deref_out IPin **ppPin); 185 | 186 | // override state changes to allow derived transform filter 187 | // to control streaming start/stop 188 | STDMETHODIMP Stop(); 189 | STDMETHODIMP Pause(); 190 | 191 | public: 192 | 193 | CTransformFilter(__in_opt LPCTSTR , __inout_opt LPUNKNOWN, REFCLSID clsid); 194 | #ifdef UNICODE 195 | CTransformFilter(__in_opt LPCSTR , __inout_opt LPUNKNOWN, REFCLSID clsid); 196 | #endif 197 | ~CTransformFilter(); 198 | 199 | // ================================================================= 200 | // ----- override these bits --------------------------------------- 201 | // ================================================================= 202 | 203 | // These must be supplied in a derived class 204 | 205 | virtual HRESULT Transform(IMediaSample * pIn, IMediaSample *pOut); 206 | 207 | // check if you can support mtIn 208 | virtual HRESULT CheckInputType(const CMediaType* mtIn) PURE; 209 | 210 | // check if you can support the transform from this input to this output 211 | virtual HRESULT CheckTransform(const CMediaType* mtIn, const CMediaType* mtOut) PURE; 212 | 213 | // this goes in the factory template table to create new instances 214 | // static CCOMObject * CreateInstance(__inout_opt LPUNKNOWN, HRESULT *); 215 | 216 | // call the SetProperties function with appropriate arguments 217 | virtual HRESULT DecideBufferSize( 218 | IMemAllocator * pAllocator, 219 | __inout ALLOCATOR_PROPERTIES *pprop) PURE; 220 | 221 | // override to suggest OUTPUT pin media types 222 | virtual HRESULT GetMediaType(int iPosition, __inout CMediaType *pMediaType) PURE; 223 | 224 | 225 | 226 | // ================================================================= 227 | // ----- Optional Override Methods ----------------------- 228 | // ================================================================= 229 | 230 | // you can also override these if you want to know about streaming 231 | virtual HRESULT StartStreaming(); 232 | virtual HRESULT StopStreaming(); 233 | 234 | // override if you can do anything constructive with quality notifications 235 | virtual HRESULT AlterQuality(Quality q); 236 | 237 | // override this to know when the media type is actually set 238 | virtual HRESULT SetMediaType(PIN_DIRECTION direction,const CMediaType *pmt); 239 | 240 | // chance to grab extra interfaces on connection 241 | virtual HRESULT CheckConnect(PIN_DIRECTION dir,IPin *pPin); 242 | virtual HRESULT BreakConnect(PIN_DIRECTION dir); 243 | virtual HRESULT CompleteConnect(PIN_DIRECTION direction,IPin *pReceivePin); 244 | 245 | // chance to customize the transform process 246 | virtual HRESULT Receive(IMediaSample *pSample); 247 | 248 | // Standard setup for output sample 249 | HRESULT InitializeOutputSample(IMediaSample *pSample, __deref_out IMediaSample **ppOutSample); 250 | 251 | // if you override Receive, you may need to override these three too 252 | virtual HRESULT EndOfStream(void); 253 | virtual HRESULT BeginFlush(void); 254 | virtual HRESULT EndFlush(void); 255 | virtual HRESULT NewSegment( 256 | REFERENCE_TIME tStart, 257 | REFERENCE_TIME tStop, 258 | double dRate); 259 | 260 | #ifdef PERF 261 | // Override to register performance measurement with a less generic string 262 | // You should do this to avoid confusion with other filters 263 | virtual void RegisterPerfId() 264 | {m_idTransform = MSR_REGISTER(TEXT("Transform"));} 265 | #endif // PERF 266 | 267 | 268 | // implementation details 269 | 270 | protected: 271 | 272 | #ifdef PERF 273 | int m_idTransform; // performance measuring id 274 | #endif 275 | BOOL m_bEOSDelivered; // have we sent EndOfStream 276 | BOOL m_bSampleSkipped; // Did we just skip a frame 277 | BOOL m_bQualityChanged; // Have we degraded? 278 | 279 | // critical section protecting filter state. 280 | 281 | CCritSec m_csFilter; 282 | 283 | // critical section stopping state changes (ie Stop) while we're 284 | // processing a sample. 285 | // 286 | // This critical section is held when processing 287 | // events that occur on the receive thread - Receive() and EndOfStream(). 288 | // 289 | // If you want to hold both m_csReceive and m_csFilter then grab 290 | // m_csFilter FIRST - like CTransformFilter::Stop() does. 291 | 292 | CCritSec m_csReceive; 293 | 294 | // these hold our input and output pins 295 | 296 | friend class CTransformInputPin; 297 | friend class CTransformOutputPin; 298 | CTransformInputPin *m_pInput; 299 | CTransformOutputPin *m_pOutput; 300 | }; 301 | 302 | #endif /* __TRANSFRM__ */ 303 | 304 | 305 | --------------------------------------------------------------------------------