Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mpc-hc/sanear.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Marsev <alex.marsev@gmail.com>2015-07-22 02:20:27 +0300
committerAlex Marsev <alex.marsev@gmail.com>2015-07-22 02:20:27 +0300
commit86c10cfdbcd7f6ea72cf0ada7fc4947bce546fb9 (patch)
tree253931a1c1b78a1031ac60d8655710f87167f52e
parent2c278482c2b7190bed0722b40c1a5913d7e500f8 (diff)
Remove dll files from core releasev0.1-core
-rw-r--r--.gitmodules9
-rw-r--r--dll/base.props23
-rw-r--r--dll/sanear-dll.sln88
-rw-r--r--dll/sanear.props9
-rw-r--r--dll/skel/register.bat25
-rw-r--r--dll/skel/unregister.bat25
-rw-r--r--dll/src/baseclasses.vcxproj151
-rw-r--r--dll/src/baseclasses/amextra.cpp111
-rw-r--r--dll/src/baseclasses/amextra.h56
-rw-r--r--dll/src/baseclasses/amfilter.cpp5358
-rw-r--r--dll/src/baseclasses/amfilter.h1587
-rw-r--r--dll/src/baseclasses/amvideo.cpp275
-rw-r--r--dll/src/baseclasses/arithutil.cpp360
-rw-r--r--dll/src/baseclasses/cache.h74
-rw-r--r--dll/src/baseclasses/checkbmi.h120
-rw-r--r--dll/src/baseclasses/combase.cpp265
-rw-r--r--dll/src/baseclasses/combase.h300
-rw-r--r--dll/src/baseclasses/cprop.cpp383
-rw-r--r--dll/src/baseclasses/cprop.h95
-rw-r--r--dll/src/baseclasses/ctlutil.cpp2541
-rw-r--r--dll/src/baseclasses/ctlutil.h923
-rw-r--r--dll/src/baseclasses/ddmm.cpp129
-rw-r--r--dll/src/baseclasses/ddmm.h28
-rw-r--r--dll/src/baseclasses/dllentry.cpp351
-rw-r--r--dll/src/baseclasses/dllsetup.cpp693
-rw-r--r--dll/src/baseclasses/dllsetup.h46
-rw-r--r--dll/src/baseclasses/dxmperf.h250
-rw-r--r--dll/src/baseclasses/fourcc.h101
-rw-r--r--dll/src/baseclasses/measure.h222
-rw-r--r--dll/src/baseclasses/msgthrd.h120
-rw-r--r--dll/src/baseclasses/mtype.cpp478
-rw-r--r--dll/src/baseclasses/mtype.h89
-rw-r--r--dll/src/baseclasses/outputq.cpp801
-rw-r--r--dll/src/baseclasses/outputq.h137
-rw-r--r--dll/src/baseclasses/perflog.cpp347
-rw-r--r--dll/src/baseclasses/perflog.h56
-rw-r--r--dll/src/baseclasses/perfstruct.h194
-rw-r--r--dll/src/baseclasses/pstream.cpp197
-rw-r--r--dll/src/baseclasses/pstream.h114
-rw-r--r--dll/src/baseclasses/pullpin.cpp588
-rw-r--r--dll/src/baseclasses/pullpin.h152
-rw-r--r--dll/src/baseclasses/refclock.cpp402
-rw-r--r--dll/src/baseclasses/refclock.h184
-rw-r--r--dll/src/baseclasses/reftime.h116
-rw-r--r--dll/src/baseclasses/renbase.cpp2858
-rw-r--r--dll/src/baseclasses/renbase.h478
-rw-r--r--dll/src/baseclasses/schedule.cpp284
-rw-r--r--dll/src/baseclasses/schedule.h128
-rw-r--r--dll/src/baseclasses/seekpt.cpp83
-rw-r--r--dll/src/baseclasses/seekpt.h30
-rw-r--r--dll/src/baseclasses/source.cpp522
-rw-r--r--dll/src/baseclasses/source.h172
-rw-r--r--dll/src/baseclasses/streams.cpp1
-rw-r--r--dll/src/baseclasses/streams.h204
-rw-r--r--dll/src/baseclasses/strmctl.cpp402
-rw-r--r--dll/src/baseclasses/strmctl.h157
-rw-r--r--dll/src/baseclasses/sysclock.cpp74
-rw-r--r--dll/src/baseclasses/sysclock.h39
-rw-r--r--dll/src/baseclasses/transfrm.cpp1016
-rw-r--r--dll/src/baseclasses/transfrm.h304
-rw-r--r--dll/src/baseclasses/transip.cpp974
-rw-r--r--dll/src/baseclasses/transip.h250
-rw-r--r--dll/src/baseclasses/videoctl.cpp734
-rw-r--r--dll/src/baseclasses/videoctl.h168
-rw-r--r--dll/src/baseclasses/vtrans.cpp468
-rw-r--r--dll/src/baseclasses/vtrans.h143
-rw-r--r--dll/src/baseclasses/winctrl.cpp2081
-rw-r--r--dll/src/baseclasses/winctrl.h224
-rw-r--r--dll/src/baseclasses/winutil.cpp2746
-rw-r--r--dll/src/baseclasses/winutil.h419
-rw-r--r--dll/src/baseclasses/wxdebug.cpp1472
-rw-r--r--dll/src/baseclasses/wxdebug.h359
-rw-r--r--dll/src/baseclasses/wxlist.cpp891
-rw-r--r--dll/src/baseclasses/wxlist.h553
-rw-r--r--dll/src/baseclasses/wxutil.cpp755
-rw-r--r--dll/src/baseclasses/wxutil.h532
-rw-r--r--dll/src/bs2b.vcxproj81
m---------dll/src/libbs2b0
-rw-r--r--dll/src/sanear-dll.vcxproj158
-rw-r--r--dll/src/sanear-dll/Entry.cpp127
-rw-r--r--dll/src/sanear-dll/OuterFilter.cpp98
-rw-r--r--dll/src/sanear-dll/OuterFilter.h35
-rw-r--r--dll/src/sanear-dll/RegistryKey.cpp78
-rw-r--r--dll/src/sanear-dll/RegistryKey.h27
-rw-r--r--dll/src/sanear-dll/TrayWindow.cpp390
-rw-r--r--dll/src/sanear-dll/TrayWindow.h44
-rw-r--r--dll/src/sanear-dll/pch.cpp1
-rw-r--r--dll/src/sanear-dll/pch.h43
-rw-r--r--dll/src/sanear-dll/resource.h16
-rw-r--r--dll/src/sanear-dll/sanear.def5
-rw-r--r--dll/src/sanear-dll/sanear.icobin49281 -> 0 bytes
-rw-r--r--dll/src/sanear-dll/sanear.rc105
-rw-r--r--dll/src/sanear-dll/sanear.svg79
m---------dll/src/soundtouch0
-rw-r--r--dll/src/soundtouch.vcxproj105
m---------dll/src/soxr0
-rw-r--r--dll/src/soxr-config.h13
-rw-r--r--dll/src/soxr.vcxproj93
-rw-r--r--dll/src/zita-resampler.vcxproj85
-rw-r--r--dll/src/zita-resampler/AUTHORS1
-rw-r--r--dll/src/zita-resampler/COPYING674
-rw-r--r--dll/src/zita-resampler/INSTALL31
-rw-r--r--dll/src/zita-resampler/README45
-rw-r--r--dll/src/zita-resampler/apps/Makefile73
-rw-r--r--dll/src/zita-resampler/apps/audiofile.cc270
-rw-r--r--dll/src/zita-resampler/apps/audiofile.h119
-rw-r--r--dll/src/zita-resampler/apps/dither.cc126
-rw-r--r--dll/src/zita-resampler/apps/dither.h58
-rw-r--r--dll/src/zita-resampler/apps/zresample.180
-rw-r--r--dll/src/zita-resampler/apps/zresample.cc272
-rw-r--r--dll/src/zita-resampler/apps/zretune.173
-rw-r--r--dll/src/zita-resampler/apps/zretune.cc257
-rw-r--r--dll/src/zita-resampler/docs/filt1.pngbin9528 -> 0 bytes
-rw-r--r--dll/src/zita-resampler/docs/filt2.pngbin3117 -> 0 bytes
-rw-r--r--dll/src/zita-resampler/docs/inpdist.pngbin14940 -> 0 bytes
-rw-r--r--dll/src/zita-resampler/docs/resampler.html574
-rw-r--r--dll/src/zita-resampler/docs/src-1kHz.pngbin34429 -> 0 bytes
-rw-r--r--dll/src/zita-resampler/docs/zita-1kHz.pngbin34459 -> 0 bytes
-rw-r--r--dll/src/zita-resampler/docs/zitadocs.css18
-rw-r--r--dll/src/zita-resampler/libs/Makefile68
-rw-r--r--dll/src/zita-resampler/libs/resampler-table.cc161
-rw-r--r--dll/src/zita-resampler/libs/resampler.cc263
-rw-r--r--dll/src/zita-resampler/libs/vresampler.cc269
-rw-r--r--dll/src/zita-resampler/libs/zita-resampler/resampler-table.h86
-rw-r--r--dll/src/zita-resampler/libs/zita-resampler/resampler.h76
-rw-r--r--dll/src/zita-resampler/libs/zita-resampler/vresampler.h83
126 files changed, 0 insertions, 43354 deletions
diff --git a/.gitmodules b/.gitmodules
deleted file mode 100644
index c1807b9..0000000
--- a/.gitmodules
+++ /dev/null
@@ -1,9 +0,0 @@
-[submodule "libbs2b"]
- path = dll/src/libbs2b
- url = git://github.com/alexmarsev/libbs2b.git
-[submodule "soxr"]
- path = dll/src/soxr
- url = git://github.com/alexmarsev/soxr.git
-[submodule "soundtouch"]
- path = dll/src/soundtouch
- url = git://github.com/alexmarsev/soundtouch.git
diff --git a/dll/base.props b/dll/base.props
deleted file mode 100644
index 53e1624..0000000
--- a/dll/base.props
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <PropertyGroup>
- <OutDir>$(SolutionDir)bin\$(Configuration)$(PlatformArchitecture)\obj\</OutDir>
- <BinDir>$(SolutionDir)bin\$(Configuration)$(PlatformArchitecture)\</BinDir>
- <IntDir>$(SolutionDir)bin\$(Configuration)$(PlatformArchitecture)\obj\$(ProjectName)\</IntDir>
- </PropertyGroup>
- <PropertyGroup Label="Configuration">
- <PlatformToolset>v140</PlatformToolset>
- </PropertyGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
- <ClCompile>
- <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
- </ClCompile>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
- <ClCompile>
- <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
- <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <AssemblerOutput>AssemblyAndSourceCode</AssemblerOutput>
- </ClCompile>
- </ItemDefinitionGroup>
-</Project>
diff --git a/dll/sanear-dll.sln b/dll/sanear-dll.sln
deleted file mode 100644
index 211589a..0000000
--- a/dll/sanear-dll.sln
+++ /dev/null
@@ -1,88 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 2013
-VisualStudioVersion = 12.0.31101.0
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sanear-dll", "src\sanear-dll.vcxproj", "{E02FD084-ED17-46C7-B5A6-F0BBB7966BBB}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sanear", "..\sanear.vcxproj", "{BB2B61AF-734A-4DAD-9326-07F4F9EA088F}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "baseclasses", "src\baseclasses.vcxproj", "{B8375339-1932-4CC0-AE5B-257672078E41}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bs2b", "src\bs2b.vcxproj", "{C59B751C-F10D-4DE0-B580-73CB03B27B6E}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "soxr", "src\soxr.vcxproj", "{2D2A92FF-1FB6-4926-AFFB-5E00D27939FC}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "soundtouch", "src\soundtouch.vcxproj", "{3C1B816A-645C-4E1F-A006-5C47263E59C5}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zita-resampler", "src\zita-resampler.vcxproj", "{34DC7A3D-B219-4F42-A1E5-8DBB22DEC08C}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Win32 = Debug|Win32
- Debug|x64 = Debug|x64
- Release|Win32 = Release|Win32
- Release|x64 = Release|x64
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {E02FD084-ED17-46C7-B5A6-F0BBB7966BBB}.Debug|Win32.ActiveCfg = Debug|Win32
- {E02FD084-ED17-46C7-B5A6-F0BBB7966BBB}.Debug|Win32.Build.0 = Debug|Win32
- {E02FD084-ED17-46C7-B5A6-F0BBB7966BBB}.Debug|x64.ActiveCfg = Debug|x64
- {E02FD084-ED17-46C7-B5A6-F0BBB7966BBB}.Debug|x64.Build.0 = Debug|x64
- {E02FD084-ED17-46C7-B5A6-F0BBB7966BBB}.Release|Win32.ActiveCfg = Release|Win32
- {E02FD084-ED17-46C7-B5A6-F0BBB7966BBB}.Release|Win32.Build.0 = Release|Win32
- {E02FD084-ED17-46C7-B5A6-F0BBB7966BBB}.Release|x64.ActiveCfg = Release|x64
- {E02FD084-ED17-46C7-B5A6-F0BBB7966BBB}.Release|x64.Build.0 = Release|x64
- {BB2B61AF-734A-4DAD-9326-07F4F9EA088F}.Debug|Win32.ActiveCfg = Debug|Win32
- {BB2B61AF-734A-4DAD-9326-07F4F9EA088F}.Debug|Win32.Build.0 = Debug|Win32
- {BB2B61AF-734A-4DAD-9326-07F4F9EA088F}.Debug|x64.ActiveCfg = Debug|x64
- {BB2B61AF-734A-4DAD-9326-07F4F9EA088F}.Debug|x64.Build.0 = Debug|x64
- {BB2B61AF-734A-4DAD-9326-07F4F9EA088F}.Release|Win32.ActiveCfg = Release|Win32
- {BB2B61AF-734A-4DAD-9326-07F4F9EA088F}.Release|Win32.Build.0 = Release|Win32
- {BB2B61AF-734A-4DAD-9326-07F4F9EA088F}.Release|x64.ActiveCfg = Release|x64
- {BB2B61AF-734A-4DAD-9326-07F4F9EA088F}.Release|x64.Build.0 = Release|x64
- {B8375339-1932-4CC0-AE5B-257672078E41}.Debug|Win32.ActiveCfg = Debug|Win32
- {B8375339-1932-4CC0-AE5B-257672078E41}.Debug|Win32.Build.0 = Debug|Win32
- {B8375339-1932-4CC0-AE5B-257672078E41}.Debug|x64.ActiveCfg = Debug|x64
- {B8375339-1932-4CC0-AE5B-257672078E41}.Debug|x64.Build.0 = Debug|x64
- {B8375339-1932-4CC0-AE5B-257672078E41}.Release|Win32.ActiveCfg = Release|Win32
- {B8375339-1932-4CC0-AE5B-257672078E41}.Release|Win32.Build.0 = Release|Win32
- {B8375339-1932-4CC0-AE5B-257672078E41}.Release|x64.ActiveCfg = Release|x64
- {B8375339-1932-4CC0-AE5B-257672078E41}.Release|x64.Build.0 = Release|x64
- {C59B751C-F10D-4DE0-B580-73CB03B27B6E}.Debug|Win32.ActiveCfg = Debug|Win32
- {C59B751C-F10D-4DE0-B580-73CB03B27B6E}.Debug|Win32.Build.0 = Debug|Win32
- {C59B751C-F10D-4DE0-B580-73CB03B27B6E}.Debug|x64.ActiveCfg = Debug|x64
- {C59B751C-F10D-4DE0-B580-73CB03B27B6E}.Debug|x64.Build.0 = Debug|x64
- {C59B751C-F10D-4DE0-B580-73CB03B27B6E}.Release|Win32.ActiveCfg = Release|Win32
- {C59B751C-F10D-4DE0-B580-73CB03B27B6E}.Release|Win32.Build.0 = Release|Win32
- {C59B751C-F10D-4DE0-B580-73CB03B27B6E}.Release|x64.ActiveCfg = Release|x64
- {C59B751C-F10D-4DE0-B580-73CB03B27B6E}.Release|x64.Build.0 = Release|x64
- {2D2A92FF-1FB6-4926-AFFB-5E00D27939FC}.Debug|Win32.ActiveCfg = Debug|Win32
- {2D2A92FF-1FB6-4926-AFFB-5E00D27939FC}.Debug|Win32.Build.0 = Debug|Win32
- {2D2A92FF-1FB6-4926-AFFB-5E00D27939FC}.Debug|x64.ActiveCfg = Debug|x64
- {2D2A92FF-1FB6-4926-AFFB-5E00D27939FC}.Debug|x64.Build.0 = Debug|x64
- {2D2A92FF-1FB6-4926-AFFB-5E00D27939FC}.Release|Win32.ActiveCfg = Release|Win32
- {2D2A92FF-1FB6-4926-AFFB-5E00D27939FC}.Release|Win32.Build.0 = Release|Win32
- {2D2A92FF-1FB6-4926-AFFB-5E00D27939FC}.Release|x64.ActiveCfg = Release|x64
- {2D2A92FF-1FB6-4926-AFFB-5E00D27939FC}.Release|x64.Build.0 = Release|x64
- {3C1B816A-645C-4E1F-A006-5C47263E59C5}.Debug|Win32.ActiveCfg = Debug|Win32
- {3C1B816A-645C-4E1F-A006-5C47263E59C5}.Debug|Win32.Build.0 = Debug|Win32
- {3C1B816A-645C-4E1F-A006-5C47263E59C5}.Debug|x64.ActiveCfg = Debug|x64
- {3C1B816A-645C-4E1F-A006-5C47263E59C5}.Debug|x64.Build.0 = Debug|x64
- {3C1B816A-645C-4E1F-A006-5C47263E59C5}.Release|Win32.ActiveCfg = Release|Win32
- {3C1B816A-645C-4E1F-A006-5C47263E59C5}.Release|Win32.Build.0 = Release|Win32
- {3C1B816A-645C-4E1F-A006-5C47263E59C5}.Release|x64.ActiveCfg = Release|x64
- {3C1B816A-645C-4E1F-A006-5C47263E59C5}.Release|x64.Build.0 = Release|x64
- {34DC7A3D-B219-4F42-A1E5-8DBB22DEC08C}.Debug|Win32.ActiveCfg = Debug|Win32
- {34DC7A3D-B219-4F42-A1E5-8DBB22DEC08C}.Debug|Win32.Build.0 = Debug|Win32
- {34DC7A3D-B219-4F42-A1E5-8DBB22DEC08C}.Debug|x64.ActiveCfg = Debug|x64
- {34DC7A3D-B219-4F42-A1E5-8DBB22DEC08C}.Debug|x64.Build.0 = Debug|x64
- {34DC7A3D-B219-4F42-A1E5-8DBB22DEC08C}.Release|Win32.ActiveCfg = Release|Win32
- {34DC7A3D-B219-4F42-A1E5-8DBB22DEC08C}.Release|Win32.Build.0 = Release|Win32
- {34DC7A3D-B219-4F42-A1E5-8DBB22DEC08C}.Release|x64.ActiveCfg = Release|x64
- {34DC7A3D-B219-4F42-A1E5-8DBB22DEC08C}.Release|x64.Build.0 = Release|x64
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
-EndGlobal
diff --git a/dll/sanear.props b/dll/sanear.props
deleted file mode 100644
index 35da4c2..0000000
--- a/dll/sanear.props
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$(SolutionDir)base.props" />
- <ItemDefinitionGroup>
- <ClCompile>
- <AdditionalIncludeDirectories>$(SolutionDir)src\baseclasses;$(SolutionDir)src\soxr\src;$(SolutionDir)src\libbs2b\src;$(SolutionDir)src\soundtouch\include;$(SolutionDir)src\zita-resampler\libs;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- </ClCompile>
- </ItemDefinitionGroup>
-</Project>
diff --git a/dll/skel/register.bat b/dll/skel/register.bat
deleted file mode 100644
index 50d9d05..0000000
--- a/dll/skel/register.bat
+++ /dev/null
@@ -1,25 +0,0 @@
-@echo off
-cd /d "%~dp0"
-
-regsvr32.exe sanear.ax /s
-if %ERRORLEVEL% neq 0 goto fail
-
-if "%PROCESSOR_ARCHITECTURE%" == "x86" goto ok
-regsvr32.exe sanear64.ax /s
-if %ERRORLEVEL% neq 0 goto fail
-
-:ok
-echo.
-echo Registration succeeded
-echo.
-goto done
-
-:fail
-echo.
-echo Registration failed!
-echo.
-echo Try to right-click on %~nx0 and select "Run as administrator"
-echo.
-
-:done
-pause >nul
diff --git a/dll/skel/unregister.bat b/dll/skel/unregister.bat
deleted file mode 100644
index d53d7e4..0000000
--- a/dll/skel/unregister.bat
+++ /dev/null
@@ -1,25 +0,0 @@
-@echo off
-cd /d "%~dp0"
-
-regsvr32.exe /u sanear.ax /s
-if %ERRORLEVEL% neq 0 goto fail
-
-if "%PROCESSOR_ARCHITECTURE%" == "x86" goto ok
-regsvr32.exe /u sanear64.ax /s
-if %ERRORLEVEL% neq 0 goto fail
-
-:ok
-echo.
-echo Unregistration succeeded
-echo.
-goto done
-
-:fail
-echo.
-echo Unregistration failed!
-echo.
-echo Try to right-click on %~nx0 and select "Run as administrator"
-echo.
-
-:done
-pause >nul
diff --git a/dll/src/baseclasses.vcxproj b/dll/src/baseclasses.vcxproj
deleted file mode 100644
index b494cb6..0000000
--- a/dll/src/baseclasses.vcxproj
+++ /dev/null
@@ -1,151 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup Label="ProjectConfigurations">
- <ProjectConfiguration Include="Debug|Win32">
- <Configuration>Debug</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Debug|x64">
- <Configuration>Debug</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|Win32">
- <Configuration>Release</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|x64">
- <Configuration>Release</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- </ItemGroup>
- <PropertyGroup Label="Globals">
- <ProjectGuid>{B8375339-1932-4CC0-AE5B-257672078E41}</ProjectGuid>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
- <Import Project="..\base.props" />
- <PropertyGroup Label="Configuration">
- <CharacterSet>Unicode</CharacterSet>
- <ConfigurationType>StaticLibrary</ConfigurationType>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
- <UseDebugLibraries>true</UseDebugLibraries>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
- <UseDebugLibraries>false</UseDebugLibraries>
- <WholeProgramOptimization>true</WholeProgramOptimization>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
- <ImportGroup Label="ExtensionSettings">
- </ImportGroup>
- <ImportGroup Label="PropertySheets">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <ItemDefinitionGroup>
- <ClCompile>
- <WarningLevel>Level3</WarningLevel>
- <SDLCheck>true</SDLCheck>
- <MultiProcessorCompilation>true</MultiProcessorCompilation>
- <PrecompiledHeader>Use</PrecompiledHeader>
- <PrecompiledHeaderFile>streams.h</PrecompiledHeaderFile>
- <AdditionalIncludeDirectories>baseclasses</AdditionalIncludeDirectories>
- </ClCompile>
- <Link>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- </Link>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
- <ClCompile>
- <Optimization>Disabled</Optimization>
- <MinimalRebuild>false</MinimalRebuild>
- </ClCompile>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
- <ClCompile>
- <Optimization>MaxSpeed</Optimization>
- <FunctionLevelLinking>true</FunctionLevelLinking>
- <IntrinsicFunctions>true</IntrinsicFunctions>
- </ClCompile>
- <Link>
- <EnableCOMDATFolding>true</EnableCOMDATFolding>
- <OptimizeReferences>true</OptimizeReferences>
- </Link>
- </ItemDefinitionGroup>
- <ItemGroup>
- <ClInclude Include="baseclasses\amextra.h" />
- <ClInclude Include="baseclasses\amfilter.h" />
- <ClInclude Include="baseclasses\cache.h" />
- <ClInclude Include="baseclasses\checkbmi.h" />
- <ClInclude Include="baseclasses\combase.h" />
- <ClInclude Include="baseclasses\cprop.h" />
- <ClInclude Include="baseclasses\ctlutil.h" />
- <ClInclude Include="baseclasses\ddmm.h" />
- <ClInclude Include="baseclasses\dllsetup.h" />
- <ClInclude Include="baseclasses\dxmperf.h" />
- <ClInclude Include="baseclasses\fourcc.h" />
- <ClInclude Include="baseclasses\measure.h" />
- <ClInclude Include="baseclasses\msgthrd.h" />
- <ClInclude Include="baseclasses\mtype.h" />
- <ClInclude Include="baseclasses\outputq.h" />
- <ClInclude Include="baseclasses\perflog.h" />
- <ClInclude Include="baseclasses\perfstruct.h" />
- <ClInclude Include="baseclasses\pstream.h" />
- <ClInclude Include="baseclasses\pullpin.h" />
- <ClInclude Include="baseclasses\refclock.h" />
- <ClInclude Include="baseclasses\reftime.h" />
- <ClInclude Include="baseclasses\renbase.h" />
- <ClInclude Include="baseclasses\schedule.h" />
- <ClInclude Include="baseclasses\seekpt.h" />
- <ClInclude Include="baseclasses\source.h" />
- <ClInclude Include="baseclasses\streams.h" />
- <ClInclude Include="baseclasses\strmctl.h" />
- <ClInclude Include="baseclasses\sysclock.h" />
- <ClInclude Include="baseclasses\transfrm.h" />
- <ClInclude Include="baseclasses\transip.h" />
- <ClInclude Include="baseclasses\videoctl.h" />
- <ClInclude Include="baseclasses\vtrans.h" />
- <ClInclude Include="baseclasses\winctrl.h" />
- <ClInclude Include="baseclasses\winutil.h" />
- <ClInclude Include="baseclasses\wxdebug.h" />
- <ClInclude Include="baseclasses\wxlist.h" />
- <ClInclude Include="baseclasses\wxutil.h" />
- </ItemGroup>
- <ItemGroup>
- <ClCompile Include="baseclasses\amextra.cpp" />
- <ClCompile Include="baseclasses\amfilter.cpp" />
- <ClCompile Include="baseclasses\amvideo.cpp" />
- <ClCompile Include="baseclasses\arithutil.cpp" />
- <ClCompile Include="baseclasses\combase.cpp" />
- <ClCompile Include="baseclasses\cprop.cpp" />
- <ClCompile Include="baseclasses\ctlutil.cpp" />
- <ClCompile Include="baseclasses\ddmm.cpp" />
- <ClCompile Include="baseclasses\dllentry.cpp" />
- <ClCompile Include="baseclasses\dllsetup.cpp" />
- <ClCompile Include="baseclasses\mtype.cpp" />
- <ClCompile Include="baseclasses\outputq.cpp" />
- <ClCompile Include="baseclasses\perflog.cpp" />
- <ClCompile Include="baseclasses\pstream.cpp" />
- <ClCompile Include="baseclasses\pullpin.cpp" />
- <ClCompile Include="baseclasses\refclock.cpp" />
- <ClCompile Include="baseclasses\renbase.cpp" />
- <ClCompile Include="baseclasses\schedule.cpp" />
- <ClCompile Include="baseclasses\seekpt.cpp" />
- <ClCompile Include="baseclasses\source.cpp" />
- <ClCompile Include="baseclasses\streams.cpp">
- <PrecompiledHeader>Create</PrecompiledHeader>
- </ClCompile>
- <ClCompile Include="baseclasses\strmctl.cpp" />
- <ClCompile Include="baseclasses\sysclock.cpp" />
- <ClCompile Include="baseclasses\transfrm.cpp" />
- <ClCompile Include="baseclasses\transip.cpp" />
- <ClCompile Include="baseclasses\videoctl.cpp" />
- <ClCompile Include="baseclasses\vtrans.cpp" />
- <ClCompile Include="baseclasses\winctrl.cpp" />
- <ClCompile Include="baseclasses\winutil.cpp" />
- <ClCompile Include="baseclasses\wxdebug.cpp" />
- <ClCompile Include="baseclasses\wxlist.cpp" />
- <ClCompile Include="baseclasses\wxutil.cpp" />
- </ItemGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
- <ImportGroup Label="ExtensionTargets">
- </ImportGroup>
-</Project> \ No newline at end of file
diff --git a/dll/src/baseclasses/amextra.cpp b/dll/src/baseclasses/amextra.cpp
deleted file mode 100644
index af0de96..0000000
--- a/dll/src/baseclasses/amextra.cpp
+++ /dev/null
@@ -1,111 +0,0 @@
-//------------------------------------------------------------------------------
-// File: AMExtra.cpp
-//
-// Desc: DirectShow base classes - implements CRenderedInputPin class.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-#include <streams.h> // DirectShow base class definitions
-#include <mmsystem.h> // Needed for definition of timeGetTime
-#include <limits.h> // Standard data type limit definitions
-#include <measure.h> // Used for time critical log functions
-
-#include "amextra.h"
-
-#pragma warning(disable:4355)
-
-// Implements CRenderedInputPin class
-
-CRenderedInputPin::CRenderedInputPin(__in_opt LPCTSTR pObjectName,
- __in CBaseFilter *pFilter,
- __in CCritSec *pLock,
- __inout HRESULT *phr,
- __in_opt LPCWSTR pName) :
- CBaseInputPin(pObjectName, pFilter, pLock, phr, pName),
- m_bAtEndOfStream(FALSE),
- m_bCompleteNotified(FALSE)
-{
-}
-#ifdef UNICODE
-CRenderedInputPin::CRenderedInputPin(__in_opt LPCSTR pObjectName,
- __in CBaseFilter *pFilter,
- __in CCritSec *pLock,
- __inout HRESULT *phr,
- __in_opt LPCWSTR pName) :
- CBaseInputPin(pObjectName, pFilter, pLock, phr, pName),
- m_bAtEndOfStream(FALSE),
- m_bCompleteNotified(FALSE)
-{
-}
-#endif
-
-// Flush end of stream condition - caller should do any
-// necessary stream level locking before calling this
-
-STDMETHODIMP CRenderedInputPin::EndOfStream()
-{
- HRESULT hr = CheckStreaming();
-
- // Do EC_COMPLETE handling for rendered pins
- if (S_OK == hr && !m_bAtEndOfStream) {
- m_bAtEndOfStream = TRUE;
- FILTER_STATE fs;
- EXECUTE_ASSERT(SUCCEEDED(m_pFilter->GetState(0, &fs)));
- if (fs == State_Running) {
- DoCompleteHandling();
- }
- }
- return hr;
-}
-
-
-// Called to complete the flush
-
-STDMETHODIMP CRenderedInputPin::EndFlush()
-{
- CAutoLock lck(m_pLock);
-
- // Clean up renderer state
- m_bAtEndOfStream = FALSE;
- m_bCompleteNotified = FALSE;
-
- return CBaseInputPin::EndFlush();
-}
-
-
-// Notify of Run() from filter
-
-HRESULT CRenderedInputPin::Run(REFERENCE_TIME tStart)
-{
- UNREFERENCED_PARAMETER(tStart);
- m_bCompleteNotified = FALSE;
- if (m_bAtEndOfStream) {
- DoCompleteHandling();
- }
- return S_OK;
-}
-
-
-// Clear status on going into paused state
-
-HRESULT CRenderedInputPin::Active()
-{
- m_bAtEndOfStream = FALSE;
- m_bCompleteNotified = FALSE;
- return CBaseInputPin::Active();
-}
-
-
-// Do stuff to deliver end of stream
-
-void CRenderedInputPin::DoCompleteHandling()
-{
- ASSERT(m_bAtEndOfStream);
- if (!m_bCompleteNotified) {
- m_bCompleteNotified = TRUE;
- m_pFilter->NotifyEvent(EC_COMPLETE, S_OK, (LONG_PTR)(IBaseFilter *)m_pFilter);
- }
-}
-
diff --git a/dll/src/baseclasses/amextra.h b/dll/src/baseclasses/amextra.h
deleted file mode 100644
index 5a861bf..0000000
--- a/dll/src/baseclasses/amextra.h
+++ /dev/null
@@ -1,56 +0,0 @@
-//------------------------------------------------------------------------------
-// File: AMExtra.h
-//
-// Desc: DirectShow base classes.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-#ifndef __AMEXTRA__
-#define __AMEXTRA__
-
-// Simple rendered input pin
-//
-// NOTE if your filter queues stuff before rendering then it may not be
-// appropriate to use this class
-//
-// In that case queue the end of stream condition until the last sample
-// is actually rendered and flush the condition appropriately
-
-class CRenderedInputPin : public CBaseInputPin
-{
-public:
-
- CRenderedInputPin(__in_opt LPCTSTR pObjectName,
- __in CBaseFilter *pFilter,
- __in CCritSec *pLock,
- __inout HRESULT *phr,
- __in_opt LPCWSTR pName);
-#ifdef UNICODE
- CRenderedInputPin(__in_opt LPCSTR pObjectName,
- __in CBaseFilter *pFilter,
- __in CCritSec *pLock,
- __inout HRESULT *phr,
- __in_opt LPCWSTR pName);
-#endif
-
- // Override methods to track end of stream state
- STDMETHODIMP EndOfStream();
- STDMETHODIMP EndFlush();
-
- HRESULT Active();
- HRESULT Run(REFERENCE_TIME tStart);
-
-protected:
-
- // Member variables to track state
- BOOL m_bAtEndOfStream; // Set by EndOfStream
- BOOL m_bCompleteNotified; // Set when we notify for EC_COMPLETE
-
-private:
- void DoCompleteHandling();
-};
-
-#endif // __AMEXTRA__
-
diff --git a/dll/src/baseclasses/amfilter.cpp b/dll/src/baseclasses/amfilter.cpp
deleted file mode 100644
index 03c13d1..0000000
--- a/dll/src/baseclasses/amfilter.cpp
+++ /dev/null
@@ -1,5358 +0,0 @@
-//------------------------------------------------------------------------------
-// File: AMFilter.cpp
-//
-// Desc: DirectShow base classes - implements class hierarchy for streams
-// architecture.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-//=====================================================================
-//=====================================================================
-// The following classes are declared in this header:
-//
-//
-// CBaseMediaFilter Basic IMediaFilter support (abstract class)
-// CBaseFilter Support for IBaseFilter (incl. IMediaFilter)
-// CEnumPins Enumerate input and output pins
-// CEnumMediaTypes Enumerate the preferred pin formats
-// CBasePin Abstract base class for IPin interface
-// CBaseOutputPin Adds data provider member functions
-// CBaseInputPin Implements IMemInputPin interface
-// CMediaSample Basic transport unit for IMemInputPin
-// CBaseAllocator General list guff for most allocators
-// CMemAllocator Implements memory buffer allocation
-//
-//=====================================================================
-//=====================================================================
-
-#include <streams.h>
-#include <strsafe.h>
-
-#ifdef DXMPERF
-#include "dxmperf.h"
-#endif // DXMPERF
-
-
-//=====================================================================
-// Helpers
-//=====================================================================
-STDAPI CreateMemoryAllocator(__deref_out IMemAllocator **ppAllocator)
-{
- return CoCreateInstance(CLSID_MemoryAllocator,
- 0,
- CLSCTX_INPROC_SERVER,
- IID_IMemAllocator,
- (void **)ppAllocator);
-}
-
-// Put this one here rather than in ctlutil.cpp to avoid linking
-// anything brought in by ctlutil.cpp
-STDAPI CreatePosPassThru(
- __in_opt LPUNKNOWN pAgg,
- BOOL bRenderer,
- IPin *pPin,
- __deref_out IUnknown **ppPassThru
-)
-{
- *ppPassThru = NULL;
- IUnknown *pUnkSeek;
- HRESULT hr = CoCreateInstance(CLSID_SeekingPassThru,
- pAgg,
- CLSCTX_INPROC_SERVER,
- IID_IUnknown,
- (void **)&pUnkSeek
- );
- if (FAILED(hr)) {
- return hr;
- }
-
- ISeekingPassThru *pPassThru;
- hr = pUnkSeek->QueryInterface(IID_ISeekingPassThru, (void**)&pPassThru);
- if (FAILED(hr)) {
- pUnkSeek->Release();
- return hr;
- }
- hr = pPassThru->Init(bRenderer, pPin);
- pPassThru->Release();
- if (FAILED(hr)) {
- pUnkSeek->Release();
- return hr;
- }
- *ppPassThru = pUnkSeek;
- return S_OK;
-}
-
-
-
-#define CONNECT_TRACE_LEVEL 3
-
-//=====================================================================
-//=====================================================================
-// Implements CBaseMediaFilter
-//=====================================================================
-//=====================================================================
-
-
-/* Constructor */
-
-CBaseMediaFilter::CBaseMediaFilter(__in_opt LPCTSTR pName,
- __inout_opt LPUNKNOWN pUnk,
- __in CCritSec *pLock,
- REFCLSID clsid) :
- CUnknown(pName, pUnk),
- m_pLock(pLock),
- m_clsid(clsid),
- m_State(State_Stopped),
- m_pClock(NULL)
-{
-}
-
-
-/* Destructor */
-
-CBaseMediaFilter::~CBaseMediaFilter()
-{
- // must be stopped, but can't call Stop here since
- // our critsec has been destroyed.
-
- /* Release any clock we were using */
-
- if (m_pClock) {
- m_pClock->Release();
- m_pClock = NULL;
- }
-}
-
-
-/* Override this to say what interfaces we support and where */
-
-STDMETHODIMP
-CBaseMediaFilter::NonDelegatingQueryInterface(
- REFIID riid,
- __deref_out void ** ppv)
-{
- if (riid == IID_IMediaFilter) {
- return GetInterface((IMediaFilter *) this, ppv);
- } else if (riid == IID_IPersist) {
- return GetInterface((IPersist *) this, ppv);
- } else {
- return CUnknown::NonDelegatingQueryInterface(riid, ppv);
- }
-}
-
-/* Return the filter's clsid */
-STDMETHODIMP
-CBaseMediaFilter::GetClassID(__out CLSID *pClsID)
-{
- CheckPointer(pClsID,E_POINTER);
- ValidateReadWritePtr(pClsID,sizeof(CLSID));
- *pClsID = m_clsid;
- return NOERROR;
-}
-
-/* Override this if your state changes are not done synchronously */
-
-STDMETHODIMP
-CBaseMediaFilter::GetState(DWORD dwMSecs, __out FILTER_STATE *State)
-{
- UNREFERENCED_PARAMETER(dwMSecs);
- CheckPointer(State,E_POINTER);
- ValidateReadWritePtr(State,sizeof(FILTER_STATE));
-
- *State = m_State;
- return S_OK;
-}
-
-
-/* Set the clock we will use for synchronisation */
-
-STDMETHODIMP
-CBaseMediaFilter::SetSyncSource(__inout_opt IReferenceClock *pClock)
-{
- CAutoLock cObjectLock(m_pLock);
-
- // Ensure the new one does not go away - even if the same as the old
- if (pClock) {
- pClock->AddRef();
- }
-
- // if we have a clock, release it
- if (m_pClock) {
- m_pClock->Release();
- }
-
- // Set the new reference clock (might be NULL)
- // Should we query it to ensure it is a clock? Consider for a debug build.
- m_pClock = pClock;
-
- return NOERROR;
-}
-
-/* Return the clock we are using for synchronisation */
-STDMETHODIMP
-CBaseMediaFilter::GetSyncSource(__deref_out_opt IReferenceClock **pClock)
-{
- CheckPointer(pClock,E_POINTER);
- ValidateReadWritePtr(pClock,sizeof(IReferenceClock *));
- CAutoLock cObjectLock(m_pLock);
-
- if (m_pClock) {
- // returning an interface... addref it...
- m_pClock->AddRef();
- }
- *pClock = (IReferenceClock*)m_pClock;
- return NOERROR;
-}
-
-
-/* Put the filter into a stopped state */
-
-STDMETHODIMP
-CBaseMediaFilter::Stop()
-{
- CAutoLock cObjectLock(m_pLock);
-
- m_State = State_Stopped;
- return S_OK;
-}
-
-
-/* Put the filter into a paused state */
-
-STDMETHODIMP
-CBaseMediaFilter::Pause()
-{
- CAutoLock cObjectLock(m_pLock);
-
- m_State = State_Paused;
- return S_OK;
-}
-
-
-// Put the filter into a running state.
-
-// The time parameter is the offset to be added to the samples'
-// stream time to get the reference time at which they should be presented.
-//
-// you can either add these two and compare it against the reference clock,
-// or you can call CBaseMediaFilter::StreamTime and compare that against
-// the sample timestamp.
-
-STDMETHODIMP
-CBaseMediaFilter::Run(REFERENCE_TIME tStart)
-{
- CAutoLock cObjectLock(m_pLock);
-
- // remember the stream time offset
- m_tStart = tStart;
-
- if (m_State == State_Stopped){
- HRESULT hr = Pause();
-
- if (FAILED(hr)) {
- return hr;
- }
- }
- m_State = State_Running;
- return S_OK;
-}
-
-
-//
-// return the current stream time - samples with start timestamps of this
-// time or before should be rendered by now
-HRESULT
-CBaseMediaFilter::StreamTime(CRefTime& rtStream)
-{
- // Caller must lock for synchronization
- // We can't grab the filter lock because we want to be able to call
- // this from worker threads without deadlocking
-
- if (m_pClock == NULL) {
- return VFW_E_NO_CLOCK;
- }
-
- // get the current reference time
- HRESULT hr = m_pClock->GetTime((REFERENCE_TIME*)&rtStream);
- if (FAILED(hr)) {
- return hr;
- }
-
- // subtract the stream offset to get stream time
- rtStream -= m_tStart;
-
- return S_OK;
-}
-
-
-//=====================================================================
-//=====================================================================
-// Implements CBaseFilter
-//=====================================================================
-//=====================================================================
-
-
-/* Override this to say what interfaces we support and where */
-
-STDMETHODIMP CBaseFilter::NonDelegatingQueryInterface(REFIID riid,
- __deref_out void **ppv)
-{
- /* Do we have this interface */
-
- if (riid == IID_IBaseFilter) {
- return GetInterface((IBaseFilter *) this, ppv);
- } else if (riid == IID_IMediaFilter) {
- return GetInterface((IMediaFilter *) this, ppv);
- } else if (riid == IID_IPersist) {
- return GetInterface((IPersist *) this, ppv);
- } else if (riid == IID_IAMovieSetup) {
- return GetInterface((IAMovieSetup *) this, ppv);
- } else {
- return CUnknown::NonDelegatingQueryInterface(riid, ppv);
- }
-}
-
-#ifdef DEBUG
-STDMETHODIMP_(ULONG) CBaseFilter::NonDelegatingRelease()
-{
- if (m_cRef == 1) {
- KASSERT(m_pGraph == NULL);
- }
- return CUnknown::NonDelegatingRelease();
-}
-#endif
-
-
-/* Constructor */
-
-CBaseFilter::CBaseFilter(__in_opt LPCTSTR pName,
- __inout_opt LPUNKNOWN pUnk,
- __in CCritSec *pLock,
- REFCLSID clsid) :
- CUnknown( pName, pUnk ),
- m_pLock(pLock),
- m_clsid(clsid),
- m_State(State_Stopped),
- m_pClock(NULL),
- m_pGraph(NULL),
- m_pSink(NULL),
- m_pName(NULL),
- m_PinVersion(1)
-{
-#ifdef DXMPERF
- PERFLOG_CTOR( pName ? pName : L"CBaseFilter", (IBaseFilter *) this );
-#endif // DXMPERF
-
- ASSERT(pLock != NULL);
-}
-
-/* Passes in a redundant HRESULT argument */
-
-CBaseFilter::CBaseFilter(__in_opt LPCTSTR pName,
- __in_opt LPUNKNOWN pUnk,
- __in CCritSec *pLock,
- REFCLSID clsid,
- __inout HRESULT *phr) :
- CUnknown( pName, pUnk ),
- m_pLock(pLock),
- m_clsid(clsid),
- m_State(State_Stopped),
- m_pClock(NULL),
- m_pGraph(NULL),
- m_pSink(NULL),
- m_pName(NULL),
- m_PinVersion(1)
-{
-#ifdef DXMPERF
- PERFLOG_CTOR( pName ? pName : L"CBaseFilter", (IBaseFilter *) this );
-#endif // DXMPERF
-
- ASSERT(pLock != NULL);
- UNREFERENCED_PARAMETER(phr);
-}
-
-#ifdef UNICODE
-CBaseFilter::CBaseFilter(__in_opt LPCSTR pName,
- __in_opt LPUNKNOWN pUnk,
- __in CCritSec *pLock,
- REFCLSID clsid) :
- CUnknown( pName, pUnk ),
- m_pLock(pLock),
- m_clsid(clsid),
- m_State(State_Stopped),
- m_pClock(NULL),
- m_pGraph(NULL),
- m_pSink(NULL),
- m_pName(NULL),
- m_PinVersion(1)
-{
-#ifdef DXMPERF
- PERFLOG_CTOR( L"CBaseFilter", (IBaseFilter *) this );
-#endif // DXMPERF
-
- ASSERT(pLock != NULL);
-}
-CBaseFilter::CBaseFilter(__in_opt LPCSTR pName,
- __in_opt LPUNKNOWN pUnk,
- __in CCritSec *pLock,
- REFCLSID clsid,
- __inout HRESULT *phr) :
- CUnknown( pName, pUnk ),
- m_pLock(pLock),
- m_clsid(clsid),
- m_State(State_Stopped),
- m_pClock(NULL),
- m_pGraph(NULL),
- m_pSink(NULL),
- m_pName(NULL),
- m_PinVersion(1)
-{
-#ifdef DXMPERF
- PERFLOG_CTOR( L"CBaseFilter", (IBaseFilter *) this );
-#endif // DXMPERF
-
- ASSERT(pLock != NULL);
- UNREFERENCED_PARAMETER(phr);
-}
-#endif
-
-/* Destructor */
-
-CBaseFilter::~CBaseFilter()
-{
-#ifdef DXMPERF
- PERFLOG_DTOR( L"CBaseFilter", (IBaseFilter *) this );
-#endif // DXMPERF
-
- // NOTE we do NOT hold references on the filtergraph for m_pGraph or m_pSink
- // When we did we had the circular reference problem. Nothing would go away.
-
- delete[] m_pName;
-
- // must be stopped, but can't call Stop here since
- // our critsec has been destroyed.
-
- /* Release any clock we were using */
- if (m_pClock) {
- m_pClock->Release();
- m_pClock = NULL;
- }
-}
-
-/* Return the filter's clsid */
-STDMETHODIMP
-CBaseFilter::GetClassID(__out CLSID *pClsID)
-{
- CheckPointer(pClsID,E_POINTER);
- ValidateReadWritePtr(pClsID,sizeof(CLSID));
- *pClsID = m_clsid;
- return NOERROR;
-}
-
-/* Override this if your state changes are not done synchronously */
-STDMETHODIMP
-CBaseFilter::GetState(DWORD dwMSecs, __out FILTER_STATE *State)
-{
- UNREFERENCED_PARAMETER(dwMSecs);
- CheckPointer(State,E_POINTER);
- ValidateReadWritePtr(State,sizeof(FILTER_STATE));
-
- *State = m_State;
- return S_OK;
-}
-
-
-/* Set the clock we will use for synchronisation */
-
-STDMETHODIMP
-CBaseFilter::SetSyncSource(__in_opt IReferenceClock *pClock)
-{
- CAutoLock cObjectLock(m_pLock);
-
- // Ensure the new one does not go away - even if the same as the old
- if (pClock) {
- pClock->AddRef();
- }
-
- // if we have a clock, release it
- if (m_pClock) {
- m_pClock->Release();
- }
-
- // Set the new reference clock (might be NULL)
- // Should we query it to ensure it is a clock? Consider for a debug build.
- m_pClock = pClock;
-
- return NOERROR;
-}
-
-/* Return the clock we are using for synchronisation */
-STDMETHODIMP
-CBaseFilter::GetSyncSource(__deref_out_opt IReferenceClock **pClock)
-{
- CheckPointer(pClock,E_POINTER);
- ValidateReadWritePtr(pClock,sizeof(IReferenceClock *));
- CAutoLock cObjectLock(m_pLock);
-
- if (m_pClock) {
- // returning an interface... addref it...
- m_pClock->AddRef();
- }
- *pClock = (IReferenceClock*)m_pClock;
- return NOERROR;
-}
-
-
-
-// override CBaseMediaFilter Stop method, to deactivate any pins this
-// filter has.
-STDMETHODIMP
-CBaseFilter::Stop()
-{
- CAutoLock cObjectLock(m_pLock);
- HRESULT hr = NOERROR;
-
- // notify all pins of the state change
- if (m_State != State_Stopped) {
- int cPins = GetPinCount();
- for (int c = 0; c < cPins; c++) {
-
- CBasePin *pPin = GetPin(c);
- if (NULL == pPin) {
- break;
- }
-
- // Disconnected pins are not activated - this saves pins worrying
- // about this state themselves. We ignore the return code to make
- // sure everyone is inactivated regardless. The base input pin
- // class can return an error if it has no allocator but Stop can
- // be used to resync the graph state after something has gone bad
-
- if (pPin->IsConnected()) {
- HRESULT hrTmp = pPin->Inactive();
- if (FAILED(hrTmp) && SUCCEEDED(hr)) {
- hr = hrTmp;
- }
- }
- }
- }
-
-#ifdef DXMPERF
- PERFLOG_STOP( m_pName ? m_pName : L"CBaseFilter", (IBaseFilter *) this, m_State );
-#endif // DXMPERF
-
- m_State = State_Stopped;
- return hr;
-}
-
-
-// override CBaseMediaFilter Pause method to activate any pins
-// this filter has (also called from Run)
-
-STDMETHODIMP
-CBaseFilter::Pause()
-{
- CAutoLock cObjectLock(m_pLock);
-
- // notify all pins of the change to active state
- if (m_State == State_Stopped) {
- int cPins = GetPinCount();
- for (int c = 0; c < cPins; c++) {
-
- CBasePin *pPin = GetPin(c);
- if (NULL == pPin) {
- break;
- }
-
- // Disconnected pins are not activated - this saves pins
- // worrying about this state themselves
-
- if (pPin->IsConnected()) {
- HRESULT hr = pPin->Active();
- if (FAILED(hr)) {
- return hr;
- }
- }
- }
- }
-
-
-#ifdef DXMPERF
- PERFLOG_PAUSE( m_pName ? m_pName : L"CBaseFilter", (IBaseFilter *) this, m_State );
-#endif // DXMPERF
-
- m_State = State_Paused;
- return S_OK;
-}
-
-// Put the filter into a running state.
-
-// The time parameter is the offset to be added to the samples'
-// stream time to get the reference time at which they should be presented.
-//
-// you can either add these two and compare it against the reference clock,
-// or you can call CBaseFilter::StreamTime and compare that against
-// the sample timestamp.
-
-STDMETHODIMP
-CBaseFilter::Run(REFERENCE_TIME tStart)
-{
- CAutoLock cObjectLock(m_pLock);
-
- // remember the stream time offset
- m_tStart = tStart;
-
- if (m_State == State_Stopped){
- HRESULT hr = Pause();
-
- if (FAILED(hr)) {
- return hr;
- }
- }
- // notify all pins of the change to active state
- if (m_State != State_Running) {
- int cPins = GetPinCount();
- for (int c = 0; c < cPins; c++) {
-
- CBasePin *pPin = GetPin(c);
- if (NULL == pPin) {
- break;
- }
-
- // Disconnected pins are not activated - this saves pins
- // worrying about this state themselves
-
- if (pPin->IsConnected()) {
- HRESULT hr = pPin->Run(tStart);
- if (FAILED(hr)) {
- return hr;
- }
- }
- }
- }
-
-#ifdef DXMPERF
- PERFLOG_RUN( m_pName ? m_pName : L"CBaseFilter", (IBaseFilter *) this, tStart, m_State );
-#endif // DXMPERF
-
- m_State = State_Running;
- return S_OK;
-}
-
-//
-// return the current stream time - samples with start timestamps of this
-// time or before should be rendered by now
-HRESULT
-CBaseFilter::StreamTime(CRefTime& rtStream)
-{
- // Caller must lock for synchronization
- // We can't grab the filter lock because we want to be able to call
- // this from worker threads without deadlocking
-
- if (m_pClock == NULL) {
- return VFW_E_NO_CLOCK;
- }
-
- // get the current reference time
- HRESULT hr = m_pClock->GetTime((REFERENCE_TIME*)&rtStream);
- if (FAILED(hr)) {
- return hr;
- }
-
- // subtract the stream offset to get stream time
- rtStream -= m_tStart;
-
- return S_OK;
-}
-
-
-/* Create an enumerator for the pins attached to this filter */
-
-STDMETHODIMP
-CBaseFilter::EnumPins(__deref_out IEnumPins **ppEnum)
-{
- CheckPointer(ppEnum,E_POINTER);
- ValidateReadWritePtr(ppEnum,sizeof(IEnumPins *));
-
- /* Create a new ref counted enumerator */
-
- *ppEnum = new CEnumPins(this,
- NULL);
-
- return *ppEnum == NULL ? E_OUTOFMEMORY : NOERROR;
-}
-
-
-// default behaviour of FindPin is to assume pins are named
-// by their pin names
-STDMETHODIMP
-CBaseFilter::FindPin(
- LPCWSTR Id,
- __deref_out IPin ** ppPin
-)
-{
- CheckPointer(ppPin,E_POINTER);
- ValidateReadWritePtr(ppPin,sizeof(IPin *));
-
- // We're going to search the pin list so maintain integrity
- CAutoLock lck(m_pLock);
- int iCount = GetPinCount();
- for (int i = 0; i < iCount; i++) {
- CBasePin *pPin = GetPin(i);
- if (NULL == pPin) {
- break;
- }
-
- if (0 == lstrcmpW(pPin->Name(), Id)) {
- // Found one that matches
- //
- // AddRef() and return it
- *ppPin = pPin;
- pPin->AddRef();
- return S_OK;
- }
- }
- *ppPin = NULL;
- return VFW_E_NOT_FOUND;
-}
-
-/* Return information about this filter */
-
-STDMETHODIMP
-CBaseFilter::QueryFilterInfo(__out FILTER_INFO * pInfo)
-{
- CheckPointer(pInfo,E_POINTER);
- ValidateReadWritePtr(pInfo,sizeof(FILTER_INFO));
-
- if (m_pName) {
- (void)StringCchCopyW(pInfo->achName, NUMELMS(pInfo->achName), m_pName);
- } else {
- pInfo->achName[0] = L'\0';
- }
- pInfo->pGraph = m_pGraph;
- if (m_pGraph)
- m_pGraph->AddRef();
- return NOERROR;
-}
-
-
-/* Provide the filter with a filter graph */
-
-STDMETHODIMP
-CBaseFilter::JoinFilterGraph(
- __inout_opt IFilterGraph * pGraph,
- __in_opt LPCWSTR pName)
-{
- CAutoLock cObjectLock(m_pLock);
-
- // NOTE: we no longer hold references on the graph (m_pGraph, m_pSink)
-
- m_pGraph = pGraph;
- if (m_pGraph) {
- HRESULT hr = m_pGraph->QueryInterface(IID_IMediaEventSink,
- (void**) &m_pSink);
- if (FAILED(hr)) {
- ASSERT(m_pSink == NULL);
- }
- else m_pSink->Release(); // we do NOT keep a reference on it.
- } else {
- // if graph pointer is null, then we should
- // also release the IMediaEventSink on the same object - we don't
- // refcount it, so just set it to null
- m_pSink = NULL;
- }
-
-
- if (m_pName) {
- delete[] m_pName;
- m_pName = NULL;
- }
-
- if (pName) {
- size_t namelen;
- HRESULT hr = StringCchLengthW(pName, STRSAFE_MAX_CCH, &namelen);
- if (FAILED(hr)) {
- return hr;
- }
- m_pName = new WCHAR[namelen + 1];
- if (m_pName) {
- (void)StringCchCopyW(m_pName, namelen + 1, pName);
- } else {
- return E_OUTOFMEMORY;
- }
- }
-
-#ifdef DXMPERF
- PERFLOG_JOINGRAPH( m_pName ? m_pName : L"CBaseFilter",(IBaseFilter *) this, pGraph );
-#endif // DXMPERF
-
- return NOERROR;
-}
-
-
-// return a Vendor information string. Optional - may return E_NOTIMPL.
-// memory returned should be freed using CoTaskMemFree
-// default implementation returns E_NOTIMPL
-STDMETHODIMP
-CBaseFilter::QueryVendorInfo(
- __deref_out LPWSTR* pVendorInfo)
-{
- UNREFERENCED_PARAMETER(pVendorInfo);
- return E_NOTIMPL;
-}
-
-
-// send an event notification to the filter graph if we know about it.
-// returns S_OK if delivered, S_FALSE if the filter graph does not sink
-// events, or an error otherwise.
-HRESULT
-CBaseFilter::NotifyEvent(
- long EventCode,
- LONG_PTR EventParam1,
- LONG_PTR EventParam2)
-{
- // Snapshot so we don't have to lock up
- IMediaEventSink *pSink = m_pSink;
- if (pSink) {
- if (EC_COMPLETE == EventCode) {
- EventParam2 = (LONG_PTR)(IBaseFilter*)this;
- }
-
- return pSink->Notify(EventCode, EventParam1, EventParam2);
- } else {
- return E_NOTIMPL;
- }
-}
-
-// Request reconnect
-// pPin is the pin to reconnect
-// pmt is the type to reconnect with - can be NULL
-// Calls ReconnectEx on the filter graph
-HRESULT
-CBaseFilter::ReconnectPin(
- IPin *pPin,
- __in_opt AM_MEDIA_TYPE const *pmt
-)
-{
- IFilterGraph2 *pGraph2;
- if (m_pGraph != NULL) {
- HRESULT hr = m_pGraph->QueryInterface(IID_IFilterGraph2, (void **)&pGraph2);
- if (SUCCEEDED(hr)) {
- hr = pGraph2->ReconnectEx(pPin, pmt);
- pGraph2->Release();
- return hr;
- } else {
- return m_pGraph->Reconnect(pPin);
- }
- } else {
- return E_NOINTERFACE;
- }
-}
-
-
-
-/* This is the same idea as the media type version does for type enumeration
- on pins but for the list of pins available. So if the list of pins you
- provide changes dynamically then either override this virtual function
- to provide the version number, or more simply call IncrementPinVersion */
-
-LONG CBaseFilter::GetPinVersion()
-{
- return m_PinVersion;
-}
-
-
-/* Increment the current pin version cookie */
-
-void CBaseFilter::IncrementPinVersion()
-{
- InterlockedIncrement(&m_PinVersion);
-}
-
-/* register filter */
-
-STDMETHODIMP CBaseFilter::Register()
-{
- // get setup data, if it exists
- //
- LPAMOVIESETUP_FILTER psetupdata = GetSetupData();
-
- // check we've got data
- //
- if( NULL == psetupdata ) return S_FALSE;
-
- // init is ref counted so call just in case
- // we're being called cold.
- //
- HRESULT hr = CoInitialize( (LPVOID)NULL );
- ASSERT( SUCCEEDED(hr) );
-
- // get hold of IFilterMapper
- //
- IFilterMapper *pIFM;
- hr = CoCreateInstance( CLSID_FilterMapper
- , NULL
- , CLSCTX_INPROC_SERVER
- , IID_IFilterMapper
- , (void **)&pIFM );
- if( SUCCEEDED(hr) )
- {
- hr = AMovieSetupRegisterFilter( psetupdata, pIFM, TRUE );
- pIFM->Release();
- }
-
- // and clear up
- //
- CoFreeUnusedLibraries();
- CoUninitialize();
-
- return NOERROR;
-}
-
-
-/* unregister filter */
-
-STDMETHODIMP CBaseFilter::Unregister()
-{
- // get setup data, if it exists
- //
- LPAMOVIESETUP_FILTER psetupdata = GetSetupData();
-
- // check we've got data
- //
- if( NULL == psetupdata ) return S_FALSE;
-
- // OLE init is ref counted so call
- // just in case we're being called cold.
- //
- HRESULT hr = CoInitialize( (LPVOID)NULL );
- ASSERT( SUCCEEDED(hr) );
-
- // get hold of IFilterMapper
- //
- IFilterMapper *pIFM;
- hr = CoCreateInstance( CLSID_FilterMapper
- , NULL
- , CLSCTX_INPROC_SERVER
- , IID_IFilterMapper
- , (void **)&pIFM );
- if( SUCCEEDED(hr) )
- {
- hr = AMovieSetupRegisterFilter( psetupdata, pIFM, FALSE );
-
- // release interface
- //
- pIFM->Release();
- }
-
- // clear up
- //
- CoFreeUnusedLibraries();
- CoUninitialize();
-
- // handle one acceptable "error" - that
- // of filter not being registered!
- // (couldn't find a suitable #define'd
- // name for the error!)
- //
- if( 0x80070002 == hr)
- return NOERROR;
- else
- return hr;
-}
-
-
-//=====================================================================
-//=====================================================================
-// Implements CEnumPins
-//=====================================================================
-//=====================================================================
-
-
-CEnumPins::CEnumPins(__in CBaseFilter *pFilter,
- __in_opt CEnumPins *pEnumPins) :
- m_Position(0),
- m_PinCount(0),
- m_pFilter(pFilter),
- m_cRef(1), // Already ref counted
- m_PinCache(NAME("Pin Cache"))
-{
-
-#ifdef DEBUG
- m_dwCookie = DbgRegisterObjectCreation("CEnumPins", 0);
-#endif
-
- /* We must be owned by a filter derived from CBaseFilter */
-
- ASSERT(pFilter != NULL);
-
- /* Hold a reference count on our filter */
- m_pFilter->AddRef();
-
- /* Are we creating a new enumerator */
-
- if (pEnumPins == NULL) {
- m_Version = m_pFilter->GetPinVersion();
- m_PinCount = m_pFilter->GetPinCount();
- } else {
- ASSERT(m_Position <= m_PinCount);
- m_Position = pEnumPins->m_Position;
- m_PinCount = pEnumPins->m_PinCount;
- m_Version = pEnumPins->m_Version;
- m_PinCache.AddTail(&(pEnumPins->m_PinCache));
- }
-}
-
-
-/* Destructor releases the reference count on our filter NOTE since we hold
- a reference count on the filter who created us we know it is safe to
- release it, no access can be made to it afterwards though as we have just
- caused the last reference count to go and the object to be deleted */
-
-CEnumPins::~CEnumPins()
-{
- m_pFilter->Release();
-
-#ifdef DEBUG
- DbgRegisterObjectDestruction(m_dwCookie);
-#endif
-}
-
-
-/* Override this to say what interfaces we support where */
-
-STDMETHODIMP
-CEnumPins::QueryInterface(REFIID riid, __deref_out void **ppv)
-{
- CheckPointer(ppv, E_POINTER);
-
- /* Do we have this interface */
-
- if (riid == IID_IEnumPins || riid == IID_IUnknown) {
- return GetInterface((IEnumPins *) this, ppv);
- } else {
- *ppv = NULL;
- return E_NOINTERFACE;
- }
-}
-
-STDMETHODIMP_(ULONG)
-CEnumPins::AddRef()
-{
- return InterlockedIncrement(&m_cRef);
-}
-
-STDMETHODIMP_(ULONG)
-CEnumPins::Release()
-{
- ULONG cRef = InterlockedDecrement(&m_cRef);
- if (cRef == 0) {
- delete this;
- }
- return cRef;
-}
-
-/* One of an enumerator's basic member functions allows us to create a cloned
- interface that initially has the same state. Since we are taking a snapshot
- of an object (current position and all) we must lock access at the start */
-
-STDMETHODIMP
-CEnumPins::Clone(__deref_out IEnumPins **ppEnum)
-{
- CheckPointer(ppEnum,E_POINTER);
- ValidateReadWritePtr(ppEnum,sizeof(IEnumPins *));
- HRESULT hr = NOERROR;
-
- /* Check we are still in sync with the filter */
- if (AreWeOutOfSync() == TRUE) {
- *ppEnum = NULL;
- hr = VFW_E_ENUM_OUT_OF_SYNC;
- } else {
- *ppEnum = new CEnumPins(m_pFilter,
- this);
- if (*ppEnum == NULL) {
- hr = E_OUTOFMEMORY;
- }
- }
- return hr;
-}
-
-
-/* Return the next pin after the current position */
-
-STDMETHODIMP
-CEnumPins::Next(ULONG cPins, // place this many pins...
- __out_ecount(cPins) IPin **ppPins, // ...in this array
- __out_opt ULONG *pcFetched) // actual count passed returned here
-{
- CheckPointer(ppPins,E_POINTER);
- ValidateReadWritePtr(ppPins,cPins * sizeof(IPin *));
-
- ASSERT(ppPins);
-
- if (pcFetched!=NULL) {
- ValidateWritePtr(pcFetched, sizeof(ULONG));
- *pcFetched = 0; // default unless we succeed
- }
- // now check that the parameter is valid
- else if (cPins>1) { // pcFetched == NULL
- return E_INVALIDARG;
- }
- ULONG cFetched = 0; // increment as we get each one.
-
- /* Check we are still in sync with the filter */
- if (AreWeOutOfSync() == TRUE) {
- // If we are out of sync, we should refresh the enumerator.
- // This will reset the position and update the other members, but
- // will not clear cache of pins we have already returned.
- Refresh();
- }
-
- /* Return each pin interface NOTE GetPin returns CBasePin * not addrefed
- so we must QI for the IPin (which increments its reference count)
- If while we are retrieving a pin from the filter an error occurs we
- assume that our internal state is stale with respect to the filter
- (for example someone has deleted a pin) so we
- return VFW_E_ENUM_OUT_OF_SYNC */
-
- while (cFetched < cPins && m_PinCount > m_Position) {
-
- /* Get the next pin object from the filter */
-
- CBasePin *pPin = m_pFilter->GetPin(m_Position++);
- if (pPin == NULL) {
- // If this happend, and it's not the first time through, then we've got a problem,
- // since we should really go back and release the iPins, which we have previously
- // AddRef'ed.
- ASSERT( cFetched==0 );
- return VFW_E_ENUM_OUT_OF_SYNC;
- }
-
- /* We only want to return this pin, if it is not in our cache */
- if (0 == m_PinCache.Find(pPin))
- {
- /* From the object get an IPin interface */
-
- *ppPins = pPin;
- pPin->AddRef();
-
- cFetched++;
- ppPins++;
-
- m_PinCache.AddTail(pPin);
- }
- }
-
- if (pcFetched!=NULL) {
- *pcFetched = cFetched;
- }
-
- return (cPins==cFetched ? NOERROR : S_FALSE);
-}
-
-
-/* Skip over one or more entries in the enumerator */
-
-STDMETHODIMP
-CEnumPins::Skip(ULONG cPins)
-{
- /* Check we are still in sync with the filter */
- if (AreWeOutOfSync() == TRUE) {
- return VFW_E_ENUM_OUT_OF_SYNC;
- }
-
- /* Work out how many pins are left to skip over */
- /* We could position at the end if we are asked to skip too many... */
- /* ..which would match the base implementation for CEnumMediaTypes::Skip */
-
- ULONG PinsLeft = m_PinCount - m_Position;
- if (cPins > PinsLeft) {
- return S_FALSE;
- }
- m_Position += cPins;
- return NOERROR;
-}
-
-
-/* Set the current position back to the start */
-/* Reset has 4 simple steps:
- *
- * Set position to head of list
- * Sync enumerator with object being enumerated
- * Clear the cache of pins already returned
- * return S_OK
- */
-
-STDMETHODIMP
-CEnumPins::Reset()
-{
- m_Version = m_pFilter->GetPinVersion();
- m_PinCount = m_pFilter->GetPinCount();
-
- m_Position = 0;
-
- // Clear the cache
- m_PinCache.RemoveAll();
-
- return S_OK;
-}
-
-
-/* Set the current position back to the start */
-/* Refresh has 3 simple steps:
- *
- * Set position to head of list
- * Sync enumerator with object being enumerated
- * return S_OK
- */
-
-STDMETHODIMP
-CEnumPins::Refresh()
-{
- m_Version = m_pFilter->GetPinVersion();
- m_PinCount = m_pFilter->GetPinCount();
-
- m_Position = 0;
- return S_OK;
-}
-
-
-//=====================================================================
-//=====================================================================
-// Implements CEnumMediaTypes
-//=====================================================================
-//=====================================================================
-
-
-CEnumMediaTypes::CEnumMediaTypes(__in CBasePin *pPin,
- __in_opt CEnumMediaTypes *pEnumMediaTypes) :
- m_Position(0),
- m_pPin(pPin),
- m_cRef(1)
-{
-
-#ifdef DEBUG
- m_dwCookie = DbgRegisterObjectCreation("CEnumMediaTypes", 0);
-#endif
-
- /* We must be owned by a pin derived from CBasePin */
-
- ASSERT(pPin != NULL);
-
- /* Hold a reference count on our pin */
- m_pPin->AddRef();
-
- /* Are we creating a new enumerator */
-
- if (pEnumMediaTypes == NULL) {
- m_Version = m_pPin->GetMediaTypeVersion();
- return;
- }
-
- m_Position = pEnumMediaTypes->m_Position;
- m_Version = pEnumMediaTypes->m_Version;
-}
-
-
-/* Destructor releases the reference count on our base pin. NOTE since we hold
- a reference count on the pin who created us we know it is safe to release
- it, no access can be made to it afterwards though as we might have just
- caused the last reference count to go and the object to be deleted */
-
-CEnumMediaTypes::~CEnumMediaTypes()
-{
-#ifdef DEBUG
- DbgRegisterObjectDestruction(m_dwCookie);
-#endif
- m_pPin->Release();
-}
-
-
-/* Override this to say what interfaces we support where */
-
-STDMETHODIMP
-CEnumMediaTypes::QueryInterface(REFIID riid, __deref_out void **ppv)
-{
- CheckPointer(ppv, E_POINTER);
-
- /* Do we have this interface */
-
- if (riid == IID_IEnumMediaTypes || riid == IID_IUnknown) {
- return GetInterface((IEnumMediaTypes *) this, ppv);
- } else {
- *ppv = NULL;
- return E_NOINTERFACE;
- }
-}
-
-STDMETHODIMP_(ULONG)
-CEnumMediaTypes::AddRef()
-{
- return InterlockedIncrement(&m_cRef);
-}
-
-STDMETHODIMP_(ULONG)
-CEnumMediaTypes::Release()
-{
- ULONG cRef = InterlockedDecrement(&m_cRef);
- if (cRef == 0) {
- delete this;
- }
- return cRef;
-}
-
-/* One of an enumerator's basic member functions allows us to create a cloned
- interface that initially has the same state. Since we are taking a snapshot
- of an object (current position and all) we must lock access at the start */
-
-STDMETHODIMP
-CEnumMediaTypes::Clone(__deref_out IEnumMediaTypes **ppEnum)
-{
- CheckPointer(ppEnum,E_POINTER);
- ValidateReadWritePtr(ppEnum,sizeof(IEnumMediaTypes *));
- HRESULT hr = NOERROR;
-
- /* Check we are still in sync with the pin */
- if (AreWeOutOfSync() == TRUE) {
- *ppEnum = NULL;
- hr = VFW_E_ENUM_OUT_OF_SYNC;
- } else {
-
- *ppEnum = new CEnumMediaTypes(m_pPin,
- this);
-
- if (*ppEnum == NULL) {
- hr = E_OUTOFMEMORY;
- }
- }
- return hr;
-}
-
-
-/* Enumerate the next pin(s) after the current position. The client using this
- interface passes in a pointer to an array of pointers each of which will
- be filled in with a pointer to a fully initialised media type format
- Return NOERROR if it all works,
- S_FALSE if fewer than cMediaTypes were enumerated.
- VFW_E_ENUM_OUT_OF_SYNC if the enumerator has been broken by
- state changes in the filter
- The actual count always correctly reflects the number of types in the array.
-*/
-
-STDMETHODIMP
-CEnumMediaTypes::Next(ULONG cMediaTypes, // place this many types...
- __out_ecount(cMediaTypes) AM_MEDIA_TYPE **ppMediaTypes, // ...in this array
- __out ULONG *pcFetched) // actual count passed
-{
- CheckPointer(ppMediaTypes,E_POINTER);
- ValidateReadWritePtr(ppMediaTypes,cMediaTypes * sizeof(AM_MEDIA_TYPE *));
- /* Check we are still in sync with the pin */
- if (AreWeOutOfSync() == TRUE) {
- return VFW_E_ENUM_OUT_OF_SYNC;
- }
-
- if (pcFetched!=NULL) {
- ValidateWritePtr(pcFetched, sizeof(ULONG));
- *pcFetched = 0; // default unless we succeed
- }
- // now check that the parameter is valid
- else if (cMediaTypes>1) { // pcFetched == NULL
- return E_INVALIDARG;
- }
- ULONG cFetched = 0; // increment as we get each one.
-
- /* Return each media type by asking the filter for them in turn - If we
- have an error code retured to us while we are retrieving a media type
- we assume that our internal state is stale with respect to the filter
- (for example the window size changing) so we return
- VFW_E_ENUM_OUT_OF_SYNC */
-
- while (cMediaTypes) {
-
- CMediaType cmt;
-
- HRESULT hr = m_pPin->GetMediaType(m_Position++, &cmt);
- if (S_OK != hr) {
- break;
- }
-
- /* We now have a CMediaType object that contains the next media type
- but when we assign it to the array position we CANNOT just assign
- the AM_MEDIA_TYPE structure because as soon as the object goes out of
- scope it will delete the memory we have just copied. The function
- we use is CreateMediaType which allocates a task memory block */
-
- /* Transfer across the format block manually to save an allocate
- and free on the format block and generally go faster */
-
- *ppMediaTypes = (AM_MEDIA_TYPE *)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
- if (*ppMediaTypes == NULL) {
- break;
- }
-
- /* Do a regular copy */
- **ppMediaTypes = cmt;
-
- /* Make sure the destructor doesn't free these */
- cmt.pbFormat = NULL;
- cmt.cbFormat = NULL;
- cmt.pUnk = NULL;
-
-
- ppMediaTypes++;
- cFetched++;
- cMediaTypes--;
- }
-
- if (pcFetched!=NULL) {
- *pcFetched = cFetched;
- }
-
- return ( cMediaTypes==0 ? NOERROR : S_FALSE );
-}
-
-
-/* Skip over one or more entries in the enumerator */
-
-STDMETHODIMP
-CEnumMediaTypes::Skip(ULONG cMediaTypes)
-{
- // If we're skipping 0 elements we're guaranteed to skip the
- // correct number of elements
- if (cMediaTypes == 0) {
- return S_OK;
- }
-
- /* Check we are still in sync with the pin */
- if (AreWeOutOfSync() == TRUE) {
- return VFW_E_ENUM_OUT_OF_SYNC;
- }
-
- m_Position += cMediaTypes;
-
- /* See if we're over the end */
- CMediaType cmt;
- return S_OK == m_pPin->GetMediaType(m_Position - 1, &cmt) ? S_OK : S_FALSE;
-}
-
-
-/* Set the current position back to the start */
-/* Reset has 3 simple steps:
- *
- * set position to head of list
- * sync enumerator with object being enumerated
- * return S_OK
- */
-
-STDMETHODIMP
-CEnumMediaTypes::Reset()
-
-{
- m_Position = 0;
-
- // Bring the enumerator back into step with the current state. This
- // may be a noop but ensures that the enumerator will be valid on the
- // next call.
- m_Version = m_pPin->GetMediaTypeVersion();
- return NOERROR;
-}
-
-
-//=====================================================================
-//=====================================================================
-// Implements CBasePin
-//=====================================================================
-//=====================================================================
-
-
-/* NOTE The implementation of this class calls the CUnknown constructor with
- a NULL outer unknown pointer. This has the effect of making us a self
- contained class, ie any QueryInterface, AddRef or Release calls will be
- routed to the class's NonDelegatingUnknown methods. You will typically
- find that the classes that do this then override one or more of these
- virtual functions to provide more specialised behaviour. A good example
- of this is where a class wants to keep the QueryInterface internal but
- still wants its lifetime controlled by the external object */
-
-/* Constructor */
-
-CBasePin::CBasePin(__in_opt LPCTSTR pObjectName,
- __in CBaseFilter *pFilter,
- __in CCritSec *pLock,
- __inout HRESULT *phr,
- __in_opt LPCWSTR pName,
- PIN_DIRECTION dir) :
- CUnknown( pObjectName, NULL ),
- m_pFilter(pFilter),
- m_pLock(pLock),
- m_pName(NULL),
- m_Connected(NULL),
- m_dir(dir),
- m_bRunTimeError(FALSE),
- m_pQSink(NULL),
- m_TypeVersion(1),
- m_tStart(),
- m_tStop(MAX_TIME),
- m_bCanReconnectWhenActive(false),
- m_bTryMyTypesFirst(false),
- m_dRate(1.0)
-{
- /* WARNING - pFilter is often not a properly constituted object at
- this state (in particular QueryInterface may not work) - this
- is because its owner is often its containing object and we
- have been called from the containing object's constructor so
- the filter's owner has not yet had its CUnknown constructor
- called
- */
-#ifdef DXMPERF
- PERFLOG_CTOR( pName ? pName : L"CBasePin", (IPin *) this );
-#endif // DXMPERF
-
- ASSERT(pFilter != NULL);
- ASSERT(pLock != NULL);
-
- if (pName) {
- size_t cchName;
- HRESULT hr = StringCchLengthW(pName, STRSAFE_MAX_CCH, &cchName);
- if (SUCCEEDED(hr)) {
- m_pName = new WCHAR[cchName + 1];
- if (m_pName) {
- (void)StringCchCopyW(m_pName, cchName + 1, pName);
- }
- }
- }
-
-#ifdef DEBUG
- m_cRef = 0;
-#endif
-}
-
-#ifdef UNICODE
-CBasePin::CBasePin(__in_opt LPCSTR pObjectName,
- __in CBaseFilter *pFilter,
- __in CCritSec *pLock,
- __inout HRESULT *phr,
- __in_opt LPCWSTR pName,
- PIN_DIRECTION dir) :
- CUnknown( pObjectName, NULL ),
- m_pFilter(pFilter),
- m_pLock(pLock),
- m_pName(NULL),
- m_Connected(NULL),
- m_dir(dir),
- m_bRunTimeError(FALSE),
- m_pQSink(NULL),
- m_TypeVersion(1),
- m_tStart(),
- m_tStop(MAX_TIME),
- m_bCanReconnectWhenActive(false),
- m_bTryMyTypesFirst(false),
- m_dRate(1.0)
-{
- /* WARNING - pFilter is often not a properly constituted object at
- this state (in particular QueryInterface may not work) - this
- is because its owner is often its containing object and we
- have been called from the containing object's constructor so
- the filter's owner has not yet had its CUnknown constructor
- called
- */
-#ifdef DXMPERF
- PERFLOG_CTOR( pName ? pName : L"CBasePin", (IPin *) this );
-#endif // DXMPERF
-
- ASSERT(pFilter != NULL);
- ASSERT(pLock != NULL);
-
- if (pName) {
- size_t cchName;
- HRESULT hr = StringCchLengthW(pName, STRSAFE_MAX_CCH, &cchName);
- if (SUCCEEDED(hr)) {
- m_pName = new WCHAR[cchName + 1];
- if (m_pName) {
- (void)StringCchCopyW(m_pName, cchName + 1, pName);
- }
- }
- }
-
-
-#ifdef DEBUG
- m_cRef = 0;
-#endif
-}
-#endif
-
-/* Destructor since a connected pin holds a reference count on us there is
- no way that we can be deleted unless we are not currently connected */
-
-CBasePin::~CBasePin()
-{
-#ifdef DXMPERF
- PERFLOG_DTOR( m_pName ? m_pName : L"CBasePin", (IPin *) this );
-#endif // DXMPERF
-
- // We don't call disconnect because if the filter is going away
- // all the pins must have a reference count of zero so they must
- // have been disconnected anyway - (but check the assumption)
- ASSERT(m_Connected == FALSE);
-
- delete[] m_pName;
-
- // check the internal reference count is consistent
- ASSERT(m_cRef == 0);
-}
-
-
-/* Override this to say what interfaces we support and where */
-
-STDMETHODIMP
-CBasePin::NonDelegatingQueryInterface(REFIID riid, __deref_out void ** ppv)
-{
- /* Do we have this interface */
-
- if (riid == IID_IPin) {
- return GetInterface((IPin *) this, ppv);
- } else if (riid == IID_IQualityControl) {
- return GetInterface((IQualityControl *) this, ppv);
- } else {
- return CUnknown::NonDelegatingQueryInterface(riid, ppv);
- }
-}
-
-
-/* Override to increment the owning filter's reference count */
-
-STDMETHODIMP_(ULONG)
-CBasePin::NonDelegatingAddRef()
-{
- ASSERT(InterlockedIncrement(&m_cRef) > 0);
- return m_pFilter->AddRef();
-}
-
-
-/* Override to decrement the owning filter's reference count */
-
-STDMETHODIMP_(ULONG)
-CBasePin::NonDelegatingRelease()
-{
- ASSERT(InterlockedDecrement(&m_cRef) >= 0);
- return m_pFilter->Release();
-}
-
-
-/* Displays pin connection information */
-
-#ifdef DEBUG
-void
-CBasePin::DisplayPinInfo(IPin *pReceivePin)
-{
-
- if (DbgCheckModuleLevel(LOG_TRACE, CONNECT_TRACE_LEVEL)) {
- PIN_INFO ConnectPinInfo;
- PIN_INFO ReceivePinInfo;
-
- if (FAILED(QueryPinInfo(&ConnectPinInfo))) {
- StringCchCopyW(ConnectPinInfo.achName, sizeof(ConnectPinInfo.achName)/sizeof(WCHAR), L"Bad Pin");
- } else {
- QueryPinInfoReleaseFilter(ConnectPinInfo);
- }
-
- if (FAILED(pReceivePin->QueryPinInfo(&ReceivePinInfo))) {
- StringCchCopyW(ReceivePinInfo.achName, sizeof(ReceivePinInfo.achName)/sizeof(WCHAR), L"Bad Pin");
- } else {
- QueryPinInfoReleaseFilter(ReceivePinInfo);
- }
-
- DbgLog((LOG_TRACE, CONNECT_TRACE_LEVEL, TEXT("Trying to connect Pins :")));
- DbgLog((LOG_TRACE, CONNECT_TRACE_LEVEL, TEXT(" <%ls>"), ConnectPinInfo.achName));
- DbgLog((LOG_TRACE, CONNECT_TRACE_LEVEL, TEXT(" <%ls>"), ReceivePinInfo.achName));
- }
-}
-#endif
-
-
-/* Displays general information on the pin media type */
-
-#ifdef DEBUG
-void CBasePin::DisplayTypeInfo(IPin *pPin, const CMediaType *pmt)
-{
- UNREFERENCED_PARAMETER(pPin);
- if (DbgCheckModuleLevel(LOG_TRACE, CONNECT_TRACE_LEVEL)) {
- DbgLog((LOG_TRACE, CONNECT_TRACE_LEVEL, TEXT("Trying media type:")));
- DbgLog((LOG_TRACE, CONNECT_TRACE_LEVEL, TEXT(" major type: %hs"),
- GuidNames[*pmt->Type()]));
- DbgLog((LOG_TRACE, CONNECT_TRACE_LEVEL, TEXT(" sub type : %hs"),
- GuidNames[*pmt->Subtype()]));
- }
-}
-#endif
-
-/* Asked to connect to a pin. A pin is always attached to an owning filter
- object so we always delegate our locking to that object. We first of all
- retrieve a media type enumerator for the input pin and see if we accept
- any of the formats that it would ideally like, failing that we retrieve
- our enumerator and see if it will accept any of our preferred types */
-
-STDMETHODIMP
-CBasePin::Connect(
- IPin * pReceivePin,
- __in_opt const AM_MEDIA_TYPE *pmt // optional media type
-)
-{
- CheckPointer(pReceivePin,E_POINTER);
- ValidateReadPtr(pReceivePin,sizeof(IPin));
- CAutoLock cObjectLock(m_pLock);
- DisplayPinInfo(pReceivePin);
-
- /* See if we are already connected */
-
- if (m_Connected) {
- DbgLog((LOG_TRACE, CONNECT_TRACE_LEVEL, TEXT("Already connected")));
- return VFW_E_ALREADY_CONNECTED;
- }
-
- /* See if the filter is active */
- if (!IsStopped() && !m_bCanReconnectWhenActive) {
- return VFW_E_NOT_STOPPED;
- }
-
-
- // Find a mutually agreeable media type -
- // Pass in the template media type. If this is partially specified,
- // each of the enumerated media types will need to be checked against
- // it. If it is non-null and fully specified, we will just try to connect
- // with this.
-
- const CMediaType * ptype = (CMediaType*)pmt;
- HRESULT hr = AgreeMediaType(pReceivePin, ptype);
- if (FAILED(hr)) {
- DbgLog((LOG_TRACE, CONNECT_TRACE_LEVEL, TEXT("Failed to agree type")));
-
- // Since the procedure is already returning an error code, there
- // is nothing else this function can do to report the error.
- EXECUTE_ASSERT( SUCCEEDED( BreakConnect() ) );
-
-#ifdef DXMPERF
- PERFLOG_CONNECT( (IPin *) this, pReceivePin, hr, pmt );
-#endif // DXMPERF
-
- return hr;
- }
-
- DbgLog((LOG_TRACE, CONNECT_TRACE_LEVEL, TEXT("Connection succeeded")));
-
-#ifdef DXMPERF
- PERFLOG_CONNECT( (IPin *) this, pReceivePin, NOERROR, pmt );
-#endif // DXMPERF
-
- return NOERROR;
-}
-
-// given a specific media type, attempt a connection (includes
-// checking that the type is acceptable to this pin)
-HRESULT
-CBasePin::AttemptConnection(
- IPin* pReceivePin, // connect to this pin
- const CMediaType* pmt // using this type
-)
-{
- // The caller should hold the filter lock becasue this function
- // uses m_Connected. The caller should also hold the filter lock
- // because this function calls SetMediaType(), IsStopped() and
- // CompleteConnect().
- ASSERT(CritCheckIn(m_pLock));
-
- // Check that the connection is valid -- need to do this for every
- // connect attempt since BreakConnect will undo it.
- HRESULT hr = CheckConnect(pReceivePin);
- if (FAILED(hr)) {
- DbgLog((LOG_TRACE, CONNECT_TRACE_LEVEL, TEXT("CheckConnect failed")));
-
- // Since the procedure is already returning an error code, there
- // is nothing else this function can do to report the error.
- EXECUTE_ASSERT( SUCCEEDED( BreakConnect() ) );
-
- return hr;
- }
-
- DisplayTypeInfo(pReceivePin, pmt);
-
- /* Check we will accept this media type */
-
- hr = CheckMediaType(pmt);
- if (hr == NOERROR) {
-
- /* Make ourselves look connected otherwise ReceiveConnection
- may not be able to complete the connection
- */
- m_Connected = pReceivePin;
- m_Connected->AddRef();
- hr = SetMediaType(pmt);
- if (SUCCEEDED(hr)) {
- /* See if the other pin will accept this type */
-
- hr = pReceivePin->ReceiveConnection((IPin *)this, pmt);
- if (SUCCEEDED(hr)) {
- /* Complete the connection */
-
- hr = CompleteConnect(pReceivePin);
- if (SUCCEEDED(hr)) {
- return hr;
- } else {
- DbgLog((LOG_TRACE,
- CONNECT_TRACE_LEVEL,
- TEXT("Failed to complete connection")));
- pReceivePin->Disconnect();
- }
- }
- }
- } else {
- // we cannot use this media type
-
- // return a specific media type error if there is one
- // or map a general failure code to something more helpful
- // (in particular S_FALSE gets changed to an error code)
- if (SUCCEEDED(hr) ||
- (hr == E_FAIL) ||
- (hr == E_INVALIDARG)) {
- hr = VFW_E_TYPE_NOT_ACCEPTED;
- }
- }
-
- // BreakConnect and release any connection here in case CheckMediaType
- // failed, or if we set anything up during a call back during
- // ReceiveConnection.
-
- // Since the procedure is already returning an error code, there
- // is nothing else this function can do to report the error.
- EXECUTE_ASSERT( SUCCEEDED( BreakConnect() ) );
-
- /* If failed then undo our state */
- if (m_Connected) {
- m_Connected->Release();
- m_Connected = NULL;
- }
-
- return hr;
-}
-
-/* Given an enumerator we cycle through all the media types it proposes and
- firstly suggest them to our derived pin class and if that succeeds try
- them with the pin in a ReceiveConnection call. This means that if our pin
- proposes a media type we still check in here that we can support it. This
- is deliberate so that in simple cases the enumerator can hold all of the
- media types even if some of them are not really currently available */
-
-HRESULT CBasePin::TryMediaTypes(
- IPin *pReceivePin,
- __in_opt const CMediaType *pmt,
- IEnumMediaTypes *pEnum)
-{
- /* Reset the current enumerator position */
-
- HRESULT hr = pEnum->Reset();
- if (FAILED(hr)) {
- return hr;
- }
-
- CMediaType *pMediaType = NULL;
- ULONG ulMediaCount = 0;
-
- // attempt to remember a specific error code if there is one
- HRESULT hrFailure = S_OK;
-
- for (;;) {
-
- /* Retrieve the next media type NOTE each time round the loop the
- enumerator interface will allocate another AM_MEDIA_TYPE structure
- If we are successful then we copy it into our output object, if
- not then we must delete the memory allocated before returning */
-
- hr = pEnum->Next(1, (AM_MEDIA_TYPE**)&pMediaType,&ulMediaCount);
- if (hr != S_OK) {
- if (S_OK == hrFailure) {
- hrFailure = VFW_E_NO_ACCEPTABLE_TYPES;
- }
- return hrFailure;
- }
-
-
- ASSERT(ulMediaCount == 1);
- ASSERT(pMediaType);
-
- // check that this matches the partial type (if any)
-
- if (pMediaType &&
- ((pmt == NULL) ||
- pMediaType->MatchesPartial(pmt))) {
-
- hr = AttemptConnection(pReceivePin, pMediaType);
-
- // attempt to remember a specific error code
- if (FAILED(hr) &&
- SUCCEEDED(hrFailure) &&
- (hr != E_FAIL) &&
- (hr != E_INVALIDARG) &&
- (hr != VFW_E_TYPE_NOT_ACCEPTED)) {
- hrFailure = hr;
- }
- } else {
- hr = VFW_E_NO_ACCEPTABLE_TYPES;
- }
-
- if(pMediaType) {
- DeleteMediaType(pMediaType);
- pMediaType = NULL;
- }
-
- if (S_OK == hr) {
- return hr;
- }
- }
-}
-
-
-/* This is called to make the connection, including the taask of finding
- a media type for the pin connection. pmt is the proposed media type
- from the Connect call: if this is fully specified, we will try that.
- Otherwise we enumerate and try all the input pin's types first and
- if that fails we then enumerate and try all our preferred media types.
- For each media type we check it against pmt (if non-null and partially
- specified) as well as checking that both pins will accept it.
- */
-
-HRESULT CBasePin::AgreeMediaType(
- IPin *pReceivePin,
- const CMediaType *pmt)
-{
- ASSERT(pReceivePin);
- IEnumMediaTypes *pEnumMediaTypes = NULL;
-
- // if the media type is fully specified then use that
- if ( (pmt != NULL) && (!pmt->IsPartiallySpecified())) {
-
- // if this media type fails, then we must fail the connection
- // since if pmt is nonnull we are only allowed to connect
- // using a type that matches it.
-
- return AttemptConnection(pReceivePin, pmt);
- }
-
-
- /* Try the other pin's enumerator */
-
- HRESULT hrFailure = VFW_E_NO_ACCEPTABLE_TYPES;
-
- for (int i = 0; i < 2; i++) {
- HRESULT hr;
- if (i == (int)m_bTryMyTypesFirst) {
- hr = pReceivePin->EnumMediaTypes(&pEnumMediaTypes);
- } else {
- hr = EnumMediaTypes(&pEnumMediaTypes);
- }
- if (SUCCEEDED(hr)) {
- ASSERT(pEnumMediaTypes);
- hr = TryMediaTypes(pReceivePin,pmt,pEnumMediaTypes);
- pEnumMediaTypes->Release();
- if (SUCCEEDED(hr)) {
- return NOERROR;
- } else {
- // try to remember specific error codes if there are any
- if ((hr != E_FAIL) &&
- (hr != E_INVALIDARG) &&
- (hr != VFW_E_TYPE_NOT_ACCEPTED)) {
- hrFailure = hr;
- }
- }
- }
- }
-
- return hrFailure;
-}
-
-
-/* Called when we want to complete a connection to another filter. Failing
- this will also fail the connection and disconnect the other pin as well */
-
-HRESULT
-CBasePin::CompleteConnect(IPin *pReceivePin)
-{
- UNREFERENCED_PARAMETER(pReceivePin);
- return NOERROR;
-}
-
-
-/* This is called to set the format for a pin connection - CheckMediaType
- will have been called to check the connection format and if it didn't
- return an error code then this (virtual) function will be invoked */
-
-HRESULT
-CBasePin::SetMediaType(const CMediaType *pmt)
-{
- HRESULT hr = m_mt.Set(*pmt);
- if (FAILED(hr)) {
- return hr;
- }
-
- return NOERROR;
-}
-
-
-/* This is called during Connect() to provide a virtual method that can do
- any specific check needed for connection such as QueryInterface. This
- base class method just checks that the pin directions don't match */
-
-HRESULT
-CBasePin::CheckConnect(IPin * pPin)
-{
- /* Check that pin directions DONT match */
-
- PIN_DIRECTION pd;
- pPin->QueryDirection(&pd);
-
- ASSERT((pd == PINDIR_OUTPUT) || (pd == PINDIR_INPUT));
- ASSERT((m_dir == PINDIR_OUTPUT) || (m_dir == PINDIR_INPUT));
-
- // we should allow for non-input and non-output connections?
- if (pd == m_dir) {
- return VFW_E_INVALID_DIRECTION;
- }
- return NOERROR;
-}
-
-
-/* This is called when we realise we can't make a connection to the pin and
- must undo anything we did in CheckConnect - override to release QIs done */
-
-HRESULT
-CBasePin::BreakConnect()
-{
- return NOERROR;
-}
-
-
-/* Called normally by an output pin on an input pin to try and establish a
- connection.
-*/
-
-STDMETHODIMP
-CBasePin::ReceiveConnection(
- IPin * pConnector, // this is the pin who we will connect to
- const AM_MEDIA_TYPE *pmt // this is the media type we will exchange
-)
-{
- CheckPointer(pConnector,E_POINTER);
- CheckPointer(pmt,E_POINTER);
- ValidateReadPtr(pConnector,sizeof(IPin));
- ValidateReadPtr(pmt,sizeof(AM_MEDIA_TYPE));
- CAutoLock cObjectLock(m_pLock);
-
- /* Are we already connected */
- if (m_Connected) {
- return VFW_E_ALREADY_CONNECTED;
- }
-
- /* See if the filter is active */
- if (!IsStopped() && !m_bCanReconnectWhenActive) {
- return VFW_E_NOT_STOPPED;
- }
-
- HRESULT hr = CheckConnect(pConnector);
- if (FAILED(hr)) {
- // Since the procedure is already returning an error code, there
- // is nothing else this function can do to report the error.
- EXECUTE_ASSERT( SUCCEEDED( BreakConnect() ) );
-
-#ifdef DXMPERF
- PERFLOG_RXCONNECT( pConnector, (IPin *) this, hr, pmt );
-#endif // DXMPERF
-
- return hr;
- }
-
- /* Ask derived class if this media type is ok */
-
- CMediaType * pcmt = (CMediaType*) pmt;
- hr = CheckMediaType(pcmt);
- if (hr != NOERROR) {
- // no -we don't support this media type
-
- // Since the procedure is already returning an error code, there
- // is nothing else this function can do to report the error.
- EXECUTE_ASSERT( SUCCEEDED( BreakConnect() ) );
-
- // return a specific media type error if there is one
- // or map a general failure code to something more helpful
- // (in particular S_FALSE gets changed to an error code)
- if (SUCCEEDED(hr) ||
- (hr == E_FAIL) ||
- (hr == E_INVALIDARG)) {
- hr = VFW_E_TYPE_NOT_ACCEPTED;
- }
-
-#ifdef DXMPERF
- PERFLOG_RXCONNECT( pConnector, (IPin *) this, hr, pmt );
-#endif // DXMPERF
-
- return hr;
- }
-
- /* Complete the connection */
-
- m_Connected = pConnector;
- m_Connected->AddRef();
- hr = SetMediaType(pcmt);
- if (SUCCEEDED(hr)) {
- hr = CompleteConnect(pConnector);
- if (SUCCEEDED(hr)) {
-
-#ifdef DXMPERF
- PERFLOG_RXCONNECT( pConnector, (IPin *) this, NOERROR, pmt );
-#endif // DXMPERF
-
- return NOERROR;
- }
- }
-
- DbgLog((LOG_TRACE, CONNECT_TRACE_LEVEL, TEXT("Failed to set the media type or failed to complete the connection.")));
- m_Connected->Release();
- m_Connected = NULL;
-
- // Since the procedure is already returning an error code, there
- // is nothing else this function can do to report the error.
- EXECUTE_ASSERT( SUCCEEDED( BreakConnect() ) );
-
-#ifdef DXMPERF
- PERFLOG_RXCONNECT( pConnector, (IPin *) this, hr, pmt );
-#endif // DXMPERF
-
- return hr;
-}
-
-
-/* Called when we want to terminate a pin connection */
-
-STDMETHODIMP
-CBasePin::Disconnect()
-{
- CAutoLock cObjectLock(m_pLock);
-
- /* See if the filter is active */
- if (!IsStopped()) {
- return VFW_E_NOT_STOPPED;
- }
-
- return DisconnectInternal();
-}
-
-STDMETHODIMP
-CBasePin::DisconnectInternal()
-{
- ASSERT(CritCheckIn(m_pLock));
-
- if (m_Connected) {
- HRESULT hr = BreakConnect();
- if( FAILED( hr ) ) {
-
-#ifdef DXMPERF
- PERFLOG_DISCONNECT( (IPin *) this, m_Connected, hr );
-#endif // DXMPERF
-
- // There is usually a bug in the program if BreakConnect() fails.
- DbgBreak( "WARNING: BreakConnect() failed in CBasePin::Disconnect()." );
- return hr;
- }
-
- m_Connected->Release();
- m_Connected = NULL;
-
-#ifdef DXMPERF
- PERFLOG_DISCONNECT( (IPin *) this, m_Connected, S_OK );
-#endif // DXMPERF
-
- return S_OK;
- } else {
- // no connection - not an error
-
-#ifdef DXMPERF
- PERFLOG_DISCONNECT( (IPin *) this, m_Connected, S_FALSE );
-#endif // DXMPERF
-
- return S_FALSE;
- }
-}
-
-
-/* Return an AddRef()'d pointer to the connected pin if there is one */
-STDMETHODIMP
-CBasePin::ConnectedTo(
- __deref_out IPin **ppPin
-)
-{
- CheckPointer(ppPin,E_POINTER);
- ValidateReadWritePtr(ppPin,sizeof(IPin *));
- //
- // It's pointless to lock here.
- // The caller should ensure integrity.
- //
-
- IPin *pPin = m_Connected;
- *ppPin = pPin;
- if (pPin != NULL) {
- pPin->AddRef();
- return S_OK;
- } else {
- ASSERT(*ppPin == NULL);
- return VFW_E_NOT_CONNECTED;
- }
-}
-
-/* Return the media type of the connection */
-STDMETHODIMP
-CBasePin::ConnectionMediaType(
- __out AM_MEDIA_TYPE *pmt
-)
-{
- CheckPointer(pmt,E_POINTER);
- ValidateReadWritePtr(pmt,sizeof(AM_MEDIA_TYPE));
- CAutoLock cObjectLock(m_pLock);
-
- /* Copy constructor of m_mt allocates the memory */
- if (IsConnected()) {
- CopyMediaType( pmt, &m_mt );
- return S_OK;
- } else {
- ((CMediaType *)pmt)->InitMediaType();
- return VFW_E_NOT_CONNECTED;
- }
-}
-
-/* Return information about the filter we are connect to */
-
-STDMETHODIMP
-CBasePin::QueryPinInfo(
- __out PIN_INFO * pInfo
-)
-{
- CheckPointer(pInfo,E_POINTER);
- ValidateReadWritePtr(pInfo,sizeof(PIN_INFO));
-
- pInfo->pFilter = m_pFilter;
- if (m_pFilter) {
- m_pFilter->AddRef();
- }
-
- if (m_pName) {
- (void)StringCchCopyW(pInfo->achName, NUMELMS(pInfo->achName), m_pName);
- } else {
- pInfo->achName[0] = L'\0';
- }
-
- pInfo->dir = m_dir;
-
- return NOERROR;
-}
-
-STDMETHODIMP
-CBasePin::QueryDirection(
- __out PIN_DIRECTION * pPinDir
-)
-{
- CheckPointer(pPinDir,E_POINTER);
- ValidateReadWritePtr(pPinDir,sizeof(PIN_DIRECTION));
-
- *pPinDir = m_dir;
- return NOERROR;
-}
-
-// Default QueryId to return the pin's name
-STDMETHODIMP
-CBasePin::QueryId(
- __deref_out LPWSTR * Id
-)
-{
- // We're not going away because someone's got a pointer to us
- // so there's no need to lock
-
- return AMGetWideString(Name(), Id);
-}
-
-/* Does this pin support this media type WARNING this interface function does
- not lock the main object as it is meant to be asynchronous by nature - if
- the media types you support depend on some internal state that is updated
- dynamically then you will need to implement locking in a derived class */
-
-STDMETHODIMP
-CBasePin::QueryAccept(
- const AM_MEDIA_TYPE *pmt
-)
-{
- CheckPointer(pmt,E_POINTER);
- ValidateReadPtr(pmt,sizeof(AM_MEDIA_TYPE));
-
- /* The CheckMediaType method is valid to return error codes if the media
- type is horrible, an example might be E_INVALIDARG. What we do here
- is map all the error codes into either S_OK or S_FALSE regardless */
-
- HRESULT hr = CheckMediaType((CMediaType*)pmt);
- if (FAILED(hr)) {
- return S_FALSE;
- }
- // note that the only defined success codes should be S_OK and S_FALSE...
- return hr;
-}
-
-
-/* This can be called to return an enumerator for the pin's list of preferred
- media types. An input pin is not obliged to have any preferred formats
- although it can do. For example, the window renderer has a preferred type
- which describes a video image that matches the current window size. All
- output pins should expose at least one preferred format otherwise it is
- possible that neither pin has any types and so no connection is possible */
-
-STDMETHODIMP
-CBasePin::EnumMediaTypes(
- __deref_out IEnumMediaTypes **ppEnum
-)
-{
- CheckPointer(ppEnum,E_POINTER);
- ValidateReadWritePtr(ppEnum,sizeof(IEnumMediaTypes *));
-
- /* Create a new ref counted enumerator */
-
- *ppEnum = new CEnumMediaTypes(this,
- NULL);
-
- if (*ppEnum == NULL) {
- return E_OUTOFMEMORY;
- }
-
- return NOERROR;
-}
-
-
-
-/* This is a virtual function that returns a media type corresponding with
- place iPosition in the list. This base class simply returns an error as
- we support no media types by default but derived classes should override */
-
-HRESULT CBasePin::GetMediaType(int iPosition, __inout CMediaType *pMediaType)
-{
- UNREFERENCED_PARAMETER(iPosition);
- UNREFERENCED_PARAMETER(pMediaType);
- return E_UNEXPECTED;
-}
-
-
-/* This is a virtual function that returns the current media type version.
- The base class initialises the media type enumerators with the value 1
- By default we always returns that same value. A Derived class may change
- the list of media types available and after doing so it should increment
- the version either in a method derived from this, or more simply by just
- incrementing the m_TypeVersion base pin variable. The type enumerators
- call this when they want to see if their enumerations are out of date */
-
-LONG CBasePin::GetMediaTypeVersion()
-{
- return m_TypeVersion;
-}
-
-
-/* Increment the cookie representing the current media type version */
-
-void CBasePin::IncrementTypeVersion()
-{
- InterlockedIncrement(&m_TypeVersion);
-}
-
-
-/* Called by IMediaFilter implementation when the state changes from Stopped
- to either paused or running and in derived classes could do things like
- commit memory and grab hardware resource (the default is to do nothing) */
-
-HRESULT
-CBasePin::Active(void)
-{
- return NOERROR;
-}
-
-/* Called by IMediaFilter implementation when the state changes from
- to either paused to running and in derived classes could do things like
- commit memory and grab hardware resource (the default is to do nothing) */
-
-HRESULT
-CBasePin::Run(REFERENCE_TIME tStart)
-{
- UNREFERENCED_PARAMETER(tStart);
- return NOERROR;
-}
-
-
-/* Also called by the IMediaFilter implementation when the state changes to
- Stopped at which point you should decommit allocators and free hardware
- resources you grabbed in the Active call (default is also to do nothing) */
-
-HRESULT
-CBasePin::Inactive(void)
-{
- m_bRunTimeError = FALSE;
- return NOERROR;
-}
-
-
-// Called when no more data will arrive
-STDMETHODIMP
-CBasePin::EndOfStream(void)
-{
- return S_OK;
-}
-
-
-STDMETHODIMP
-CBasePin::SetSink(IQualityControl * piqc)
-{
- CAutoLock cObjectLock(m_pLock);
- if (piqc) ValidateReadPtr(piqc,sizeof(IQualityControl));
- m_pQSink = piqc;
- return NOERROR;
-} // SetSink
-
-
-STDMETHODIMP
-CBasePin::Notify(IBaseFilter * pSender, Quality q)
-{
- UNREFERENCED_PARAMETER(q);
- UNREFERENCED_PARAMETER(pSender);
- DbgBreak("IQualityControl::Notify not over-ridden from CBasePin. (IGNORE is OK)");
- return E_NOTIMPL;
-} //Notify
-
-
-// NewSegment notifies of the start/stop/rate applying to the data
-// about to be received. Default implementation records data and
-// returns S_OK.
-// Override this to pass downstream.
-STDMETHODIMP
-CBasePin::NewSegment(
- REFERENCE_TIME tStart,
- REFERENCE_TIME tStop,
- double dRate)
-{
- m_tStart = tStart;
- m_tStop = tStop;
- m_dRate = dRate;
-
- return S_OK;
-}
-
-
-//=====================================================================
-//=====================================================================
-// Implements CBaseOutputPin
-//=====================================================================
-//=====================================================================
-
-
-CBaseOutputPin::CBaseOutputPin(__in_opt LPCTSTR pObjectName,
- __in CBaseFilter *pFilter,
- __in CCritSec *pLock,
- __inout HRESULT *phr,
- __in_opt LPCWSTR pName) :
- CBasePin(pObjectName, pFilter, pLock, phr, pName, PINDIR_OUTPUT),
- m_pAllocator(NULL),
- m_pInputPin(NULL)
-{
- ASSERT(pFilter);
-}
-
-#ifdef UNICODE
-CBaseOutputPin::CBaseOutputPin(__in_opt LPCSTR pObjectName,
- __in CBaseFilter *pFilter,
- __in CCritSec *pLock,
- __inout HRESULT *phr,
- __in_opt LPCWSTR pName) :
- CBasePin(pObjectName, pFilter, pLock, phr, pName, PINDIR_OUTPUT),
- m_pAllocator(NULL),
- m_pInputPin(NULL)
-{
- ASSERT(pFilter);
-}
-#endif
-
-/* This is called after a media type has been proposed
-
- Try to complete the connection by agreeing the allocator
-*/
-HRESULT
-CBaseOutputPin::CompleteConnect(IPin *pReceivePin)
-{
- UNREFERENCED_PARAMETER(pReceivePin);
- return DecideAllocator(m_pInputPin, &m_pAllocator);
-}
-
-
-/* This method is called when the output pin is about to try and connect to
- an input pin. It is at this point that you should try and grab any extra
- interfaces that you need, in this case IMemInputPin. Because this is
- only called if we are not currently connected we do NOT need to call
- BreakConnect. This also makes it easier to derive classes from us as
- BreakConnect is only called when we actually have to break a connection
- (or a partly made connection) and not when we are checking a connection */
-
-/* Overriden from CBasePin */
-
-HRESULT
-CBaseOutputPin::CheckConnect(IPin * pPin)
-{
- HRESULT hr = CBasePin::CheckConnect(pPin);
- if (FAILED(hr)) {
- return hr;
- }
-
- // get an input pin and an allocator interface
- hr = pPin->QueryInterface(IID_IMemInputPin, (void **) &m_pInputPin);
- if (FAILED(hr)) {
- return hr;
- }
- return NOERROR;
-}
-
-
-/* Overriden from CBasePin */
-
-HRESULT
-CBaseOutputPin::BreakConnect()
-{
- /* Release any allocator we hold */
-
- if (m_pAllocator) {
- // Always decommit the allocator because a downstream filter may or
- // may not decommit the connection's allocator. A memory leak could
- // occur if the allocator is not decommited when a connection is broken.
- HRESULT hr = m_pAllocator->Decommit();
- if( FAILED( hr ) ) {
- return hr;
- }
-
- m_pAllocator->Release();
- m_pAllocator = NULL;
- }
-
- /* Release any input pin interface we hold */
-
- if (m_pInputPin) {
- m_pInputPin->Release();
- m_pInputPin = NULL;
- }
- return NOERROR;
-}
-
-
-/* This is called when the input pin didn't give us a valid allocator */
-
-HRESULT
-CBaseOutputPin::InitAllocator(__deref_out IMemAllocator **ppAlloc)
-{
- return CreateMemoryAllocator(ppAlloc);
-}
-
-
-/* Decide on an allocator, override this if you want to use your own allocator
- Override DecideBufferSize to call SetProperties. If the input pin fails
- the GetAllocator call then this will construct a CMemAllocator and call
- DecideBufferSize on that, and if that fails then we are completely hosed.
- If the you succeed the DecideBufferSize call, we will notify the input
- pin of the selected allocator. NOTE this is called during Connect() which
- therefore looks after grabbing and locking the object's critical section */
-
-// We query the input pin for its requested properties and pass this to
-// DecideBufferSize to allow it to fulfill requests that it is happy
-// with (eg most people don't care about alignment and are thus happy to
-// use the downstream pin's alignment request).
-
-HRESULT
-CBaseOutputPin::DecideAllocator(IMemInputPin *pPin, __deref_out IMemAllocator **ppAlloc)
-{
- HRESULT hr = NOERROR;
- *ppAlloc = NULL;
-
- // get downstream prop request
- // the derived class may modify this in DecideBufferSize, but
- // we assume that he will consistently modify it the same way,
- // so we only get it once
- ALLOCATOR_PROPERTIES prop;
- ZeroMemory(&prop, sizeof(prop));
-
- // whatever he returns, we assume prop is either all zeros
- // or he has filled it out.
- pPin->GetAllocatorRequirements(&prop);
-
- // if he doesn't care about alignment, then set it to 1
- if (prop.cbAlign == 0) {
- prop.cbAlign = 1;
- }
-
- /* Try the allocator provided by the input pin */
-
- hr = pPin->GetAllocator(ppAlloc);
- if (SUCCEEDED(hr)) {
-
- hr = DecideBufferSize(*ppAlloc, &prop);
- if (SUCCEEDED(hr)) {
- hr = pPin->NotifyAllocator(*ppAlloc, FALSE);
- if (SUCCEEDED(hr)) {
- return NOERROR;
- }
- }
- }
-
- /* If the GetAllocator failed we may not have an interface */
-
- if (*ppAlloc) {
- (*ppAlloc)->Release();
- *ppAlloc = NULL;
- }
-
- /* Try the output pin's allocator by the same method */
-
- hr = InitAllocator(ppAlloc);
- if (SUCCEEDED(hr)) {
-
- // note - the properties passed here are in the same
- // structure as above and may have been modified by
- // the previous call to DecideBufferSize
- hr = DecideBufferSize(*ppAlloc, &prop);
- if (SUCCEEDED(hr)) {
- hr = pPin->NotifyAllocator(*ppAlloc, FALSE);
- if (SUCCEEDED(hr)) {
- return NOERROR;
- }
- }
- }
-
- /* Likewise we may not have an interface to release */
-
- if (*ppAlloc) {
- (*ppAlloc)->Release();
- *ppAlloc = NULL;
- }
- return hr;
-}
-
-
-/* This returns an empty sample buffer from the allocator WARNING the same
- dangers and restrictions apply here as described below for Deliver() */
-
-HRESULT
-CBaseOutputPin::GetDeliveryBuffer(__deref_out IMediaSample ** ppSample,
- __in_opt REFERENCE_TIME * pStartTime,
- __in_opt REFERENCE_TIME * pEndTime,
- DWORD dwFlags)
-{
- if (m_pAllocator != NULL) {
- return m_pAllocator->GetBuffer(ppSample,pStartTime,pEndTime,dwFlags);
- } else {
- return E_NOINTERFACE;
- }
-}
-
-
-/* Deliver a filled-in sample to the connected input pin. NOTE the object must
- have locked itself before calling us otherwise we may get halfway through
- executing this method only to find the filter graph has got in and
- disconnected us from the input pin. If the filter has no worker threads
- then the lock is best applied on Receive(), otherwise it should be done
- when the worker thread is ready to deliver. There is a wee snag to worker
- threads that this shows up. The worker thread must lock the object when
- it is ready to deliver a sample, but it may have to wait until a state
- change has completed, but that may never complete because the state change
- is waiting for the worker thread to complete. The way to handle this is for
- the state change code to grab the critical section, then set an abort event
- for the worker thread, then release the critical section and wait for the
- worker thread to see the event we set and then signal that it has finished
- (with another event). At which point the state change code can complete */
-
-// note (if you've still got any breath left after reading that) that you
-// need to release the sample yourself after this call. if the connected
-// input pin needs to hold onto the sample beyond the call, it will addref
-// the sample itself.
-
-// of course you must release this one and call GetDeliveryBuffer for the
-// next. You cannot reuse it directly.
-
-HRESULT
-CBaseOutputPin::Deliver(IMediaSample * pSample)
-{
- if (m_pInputPin == NULL) {
- return VFW_E_NOT_CONNECTED;
- }
-
-#ifdef DXMPERF
- PERFLOG_DELIVER( m_pName ? m_pName : L"CBaseOutputPin", (IPin *) this, (IPin *) m_pInputPin, pSample, &m_mt );
-#endif // DXMPERF
-
- return m_pInputPin->Receive(pSample);
-}
-
-
-// called from elsewhere in our filter to pass EOS downstream to
-// our connected input pin
-HRESULT
-CBaseOutputPin::DeliverEndOfStream(void)
-{
- // remember this is on IPin not IMemInputPin
- if (m_Connected == NULL) {
- return VFW_E_NOT_CONNECTED;
- }
- return m_Connected->EndOfStream();
-}
-
-
-/* Commit the allocator's memory, this is called through IMediaFilter
- which is responsible for locking the object before calling us */
-
-HRESULT
-CBaseOutputPin::Active(void)
-{
- if (m_pAllocator == NULL) {
- return VFW_E_NO_ALLOCATOR;
- }
- return m_pAllocator->Commit();
-}
-
-
-/* Free up or unprepare allocator's memory, this is called through
- IMediaFilter which is responsible for locking the object first */
-
-HRESULT
-CBaseOutputPin::Inactive(void)
-{
- m_bRunTimeError = FALSE;
- if (m_pAllocator == NULL) {
- return VFW_E_NO_ALLOCATOR;
- }
- return m_pAllocator->Decommit();
-}
-
-// we have a default handling of EndOfStream which is to return
-// an error, since this should be called on input pins only
-STDMETHODIMP
-CBaseOutputPin::EndOfStream(void)
-{
- return E_UNEXPECTED;
-}
-
-
-// BeginFlush should be called on input pins only
-STDMETHODIMP
-CBaseOutputPin::BeginFlush(void)
-{
- return E_UNEXPECTED;
-}
-
-// EndFlush should be called on input pins only
-STDMETHODIMP
-CBaseOutputPin::EndFlush(void)
-{
- return E_UNEXPECTED;
-}
-
-// call BeginFlush on the connected input pin
-HRESULT
-CBaseOutputPin::DeliverBeginFlush(void)
-{
- // remember this is on IPin not IMemInputPin
- if (m_Connected == NULL) {
- return VFW_E_NOT_CONNECTED;
- }
- return m_Connected->BeginFlush();
-}
-
-// call EndFlush on the connected input pin
-HRESULT
-CBaseOutputPin::DeliverEndFlush(void)
-{
- // remember this is on IPin not IMemInputPin
- if (m_Connected == NULL) {
- return VFW_E_NOT_CONNECTED;
- }
- return m_Connected->EndFlush();
-}
-// deliver NewSegment to connected pin
-HRESULT
-CBaseOutputPin::DeliverNewSegment(
- REFERENCE_TIME tStart,
- REFERENCE_TIME tStop,
- double dRate)
-{
- if (m_Connected == NULL) {
- return VFW_E_NOT_CONNECTED;
- }
- return m_Connected->NewSegment(tStart, tStop, dRate);
-}
-
-
-//=====================================================================
-//=====================================================================
-// Implements CBaseInputPin
-//=====================================================================
-//=====================================================================
-
-
-/* Constructor creates a default allocator object */
-
-CBaseInputPin::CBaseInputPin(__in_opt LPCTSTR pObjectName,
- __in CBaseFilter *pFilter,
- __in CCritSec *pLock,
- __inout HRESULT *phr,
- __in_opt LPCWSTR pPinName) :
- CBasePin(pObjectName, pFilter, pLock, phr, pPinName, PINDIR_INPUT),
- m_pAllocator(NULL),
- m_bReadOnly(FALSE),
- m_bFlushing(FALSE)
-{
- ZeroMemory(&m_SampleProps, sizeof(m_SampleProps));
-}
-
-#ifdef UNICODE
-CBaseInputPin::CBaseInputPin(__in LPCSTR pObjectName,
- __in CBaseFilter *pFilter,
- __in CCritSec *pLock,
- __inout HRESULT *phr,
- __in_opt LPCWSTR pPinName) :
- CBasePin(pObjectName, pFilter, pLock, phr, pPinName, PINDIR_INPUT),
- m_pAllocator(NULL),
- m_bReadOnly(FALSE),
- m_bFlushing(FALSE)
-{
- ZeroMemory(&m_SampleProps, sizeof(m_SampleProps));
-}
-#endif
-
-/* Destructor releases it's reference count on the default allocator */
-
-CBaseInputPin::~CBaseInputPin()
-{
- if (m_pAllocator != NULL) {
- m_pAllocator->Release();
- m_pAllocator = NULL;
- }
-}
-
-
-// override this to publicise our interfaces
-STDMETHODIMP
-CBaseInputPin::NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv)
-{
- /* Do we know about this interface */
-
- if (riid == IID_IMemInputPin) {
- return GetInterface((IMemInputPin *) this, ppv);
- } else {
- return CBasePin::NonDelegatingQueryInterface(riid, ppv);
- }
-}
-
-
-/* Return the allocator interface that this input pin would like the output
- pin to use. NOTE subsequent calls to GetAllocator should all return an
- interface onto the SAME object so we create one object at the start
-
- Note:
- The allocator is Release()'d on disconnect and replaced on
- NotifyAllocator().
-
- Override this to provide your own allocator.
-*/
-
-STDMETHODIMP
-CBaseInputPin::GetAllocator(
- __deref_out IMemAllocator **ppAllocator)
-{
- CheckPointer(ppAllocator,E_POINTER);
- ValidateReadWritePtr(ppAllocator,sizeof(IMemAllocator *));
- CAutoLock cObjectLock(m_pLock);
-
- if (m_pAllocator == NULL) {
- HRESULT hr = CreateMemoryAllocator(&m_pAllocator);
- if (FAILED(hr)) {
- return hr;
- }
- }
- ASSERT(m_pAllocator != NULL);
- *ppAllocator = m_pAllocator;
- m_pAllocator->AddRef();
- return NOERROR;
-}
-
-
-/* Tell the input pin which allocator the output pin is actually going to use
- Override this if you care - NOTE the locking we do both here and also in
- GetAllocator is unnecessary but derived classes that do something useful
- will undoubtedly have to lock the object so this might help remind people */
-
-STDMETHODIMP
-CBaseInputPin::NotifyAllocator(
- IMemAllocator * pAllocator,
- BOOL bReadOnly)
-{
- CheckPointer(pAllocator,E_POINTER);
- ValidateReadPtr(pAllocator,sizeof(IMemAllocator));
- CAutoLock cObjectLock(m_pLock);
-
- IMemAllocator *pOldAllocator = m_pAllocator;
- pAllocator->AddRef();
- m_pAllocator = pAllocator;
-
- if (pOldAllocator != NULL) {
- pOldAllocator->Release();
- }
-
- // the readonly flag indicates whether samples from this allocator should
- // be regarded as readonly - if true, then inplace transforms will not be
- // allowed.
- m_bReadOnly = (BYTE)bReadOnly;
- return NOERROR;
-}
-
-
-HRESULT
-CBaseInputPin::BreakConnect()
-{
- /* We don't need our allocator any more */
- if (m_pAllocator) {
- // Always decommit the allocator because a downstream filter may or
- // may not decommit the connection's allocator. A memory leak could
- // occur if the allocator is not decommited when a pin is disconnected.
- HRESULT hr = m_pAllocator->Decommit();
- if( FAILED( hr ) ) {
- return hr;
- }
-
- m_pAllocator->Release();
- m_pAllocator = NULL;
- }
-
- return S_OK;
-}
-
-
-/* Do something with this media sample - this base class checks to see if the
- format has changed with this media sample and if so checks that the filter
- will accept it, generating a run time error if not. Once we have raised a
- run time error we set a flag so that no more samples will be accepted
-
- It is important that any filter should override this method and implement
- synchronization so that samples are not processed when the pin is
- disconnected etc
-*/
-
-STDMETHODIMP
-CBaseInputPin::Receive(IMediaSample *pSample)
-{
- CheckPointer(pSample,E_POINTER);
- ValidateReadPtr(pSample,sizeof(IMediaSample));
- ASSERT(pSample);
-
- HRESULT hr = CheckStreaming();
- if (S_OK != hr) {
- return hr;
- }
-
-#ifdef DXMPERF
- PERFLOG_RECEIVE( m_pName ? m_pName : L"CBaseInputPin", (IPin *) m_Connected, (IPin *) this, pSample, &m_mt );
-#endif // DXMPERF
-
-
- /* Check for IMediaSample2 */
- IMediaSample2 *pSample2;
- if (SUCCEEDED(pSample->QueryInterface(IID_IMediaSample2, (void **)&pSample2))) {
- hr = pSample2->GetProperties(sizeof(m_SampleProps), (PBYTE)&m_SampleProps);
- pSample2->Release();
- if (FAILED(hr)) {
- return hr;
- }
- } else {
- /* Get the properties the hard way */
- m_SampleProps.cbData = sizeof(m_SampleProps);
- m_SampleProps.dwTypeSpecificFlags = 0;
- m_SampleProps.dwStreamId = AM_STREAM_MEDIA;
- m_SampleProps.dwSampleFlags = 0;
- if (S_OK == pSample->IsDiscontinuity()) {
- m_SampleProps.dwSampleFlags |= AM_SAMPLE_DATADISCONTINUITY;
- }
- if (S_OK == pSample->IsPreroll()) {
- m_SampleProps.dwSampleFlags |= AM_SAMPLE_PREROLL;
- }
- if (S_OK == pSample->IsSyncPoint()) {
- m_SampleProps.dwSampleFlags |= AM_SAMPLE_SPLICEPOINT;
- }
- if (SUCCEEDED(pSample->GetTime(&m_SampleProps.tStart,
- &m_SampleProps.tStop))) {
- m_SampleProps.dwSampleFlags |= AM_SAMPLE_TIMEVALID |
- AM_SAMPLE_STOPVALID;
- }
- if (S_OK == pSample->GetMediaType(&m_SampleProps.pMediaType)) {
- m_SampleProps.dwSampleFlags |= AM_SAMPLE_TYPECHANGED;
- }
- pSample->GetPointer(&m_SampleProps.pbBuffer);
- m_SampleProps.lActual = pSample->GetActualDataLength();
- m_SampleProps.cbBuffer = pSample->GetSize();
- }
-
- /* Has the format changed in this sample */
-
- if (!(m_SampleProps.dwSampleFlags & AM_SAMPLE_TYPECHANGED)) {
- return NOERROR;
- }
-
- /* Check the derived class accepts this format */
- /* This shouldn't fail as the source must call QueryAccept first */
-
- hr = CheckMediaType((CMediaType *)m_SampleProps.pMediaType);
-
- if (hr == NOERROR) {
- return NOERROR;
- }
-
- /* Raise a runtime error if we fail the media type */
-
- m_bRunTimeError = TRUE;
- EndOfStream();
- m_pFilter->NotifyEvent(EC_ERRORABORT,VFW_E_TYPE_NOT_ACCEPTED,0);
- return VFW_E_INVALIDMEDIATYPE;
-}
-
-
-/* Receive multiple samples */
-STDMETHODIMP
-CBaseInputPin::ReceiveMultiple (
- __in_ecount(nSamples) IMediaSample **pSamples,
- long nSamples,
- __out long *nSamplesProcessed)
-{
- CheckPointer(pSamples,E_POINTER);
- ValidateReadPtr(pSamples,nSamples * sizeof(IMediaSample *));
-
- HRESULT hr = S_OK;
- *nSamplesProcessed = 0;
- while (nSamples-- > 0) {
- hr = Receive(pSamples[*nSamplesProcessed]);
-
- /* S_FALSE means don't send any more */
- if (hr != S_OK) {
- break;
- }
- (*nSamplesProcessed)++;
- }
- return hr;
-}
-
-/* See if Receive() might block */
-STDMETHODIMP
-CBaseInputPin::ReceiveCanBlock()
-{
- /* Ask all the output pins if they block
- If there are no output pin assume we do block
- */
- int cPins = m_pFilter->GetPinCount();
- int cOutputPins = 0;
- for (int c = 0; c < cPins; c++) {
- CBasePin *pPin = m_pFilter->GetPin(c);
- if (NULL == pPin) {
- break;
- }
- PIN_DIRECTION pd;
- HRESULT hr = pPin->QueryDirection(&pd);
- if (FAILED(hr)) {
- return hr;
- }
-
- if (pd == PINDIR_OUTPUT) {
-
- IPin *pConnected;
- hr = pPin->ConnectedTo(&pConnected);
- if (SUCCEEDED(hr)) {
- ASSERT(pConnected != NULL);
- cOutputPins++;
- IMemInputPin *pInputPin;
- hr = pConnected->QueryInterface(
- IID_IMemInputPin,
- (void **)&pInputPin);
- pConnected->Release();
- if (SUCCEEDED(hr)) {
- hr = pInputPin->ReceiveCanBlock();
- pInputPin->Release();
- if (hr != S_FALSE) {
- return S_OK;
- }
- } else {
- /* There's a transport we don't understand here */
- return S_OK;
- }
- }
- }
- }
- return cOutputPins == 0 ? S_OK : S_FALSE;
-}
-
-// Default handling for BeginFlush - call at the beginning
-// of your implementation (makes sure that all Receive calls
-// fail). After calling this, you need to free any queued data
-// and then call downstream.
-STDMETHODIMP
-CBaseInputPin::BeginFlush(void)
-{
- // BeginFlush is NOT synchronized with streaming but is part of
- // a control action - hence we synchronize with the filter
- CAutoLock lck(m_pLock);
-
- // if we are already in mid-flush, this is probably a mistake
- // though not harmful - try to pick it up for now so I can think about it
- ASSERT(!m_bFlushing);
-
- // first thing to do is ensure that no further Receive calls succeed
- m_bFlushing = TRUE;
-
- // now discard any data and call downstream - must do that
- // in derived classes
- return S_OK;
-}
-
-// default handling for EndFlush - call at end of your implementation
-// - before calling this, ensure that there is no queued data and no thread
-// pushing any more without a further receive, then call downstream,
-// then call this method to clear the m_bFlushing flag and re-enable
-// receives
-STDMETHODIMP
-CBaseInputPin::EndFlush(void)
-{
- // Endlush is NOT synchronized with streaming but is part of
- // a control action - hence we synchronize with the filter
- CAutoLock lck(m_pLock);
-
- // almost certainly a mistake if we are not in mid-flush
- ASSERT(m_bFlushing);
-
- // before calling, sync with pushing thread and ensure
- // no more data is going downstream, then call EndFlush on
- // downstream pins.
-
- // now re-enable Receives
- m_bFlushing = FALSE;
-
- // No more errors
- m_bRunTimeError = FALSE;
-
- return S_OK;
-}
-
-
-STDMETHODIMP
-CBaseInputPin::Notify(IBaseFilter * pSender, Quality q)
-{
- UNREFERENCED_PARAMETER(q);
- CheckPointer(pSender,E_POINTER);
- ValidateReadPtr(pSender,sizeof(IBaseFilter));
- DbgBreak("IQuality::Notify called on an input pin");
- return NOERROR;
-} // Notify
-
-/* Free up or unprepare allocator's memory, this is called through
- IMediaFilter which is responsible for locking the object first */
-
-HRESULT
-CBaseInputPin::Inactive(void)
-{
- m_bRunTimeError = FALSE;
- if (m_pAllocator == NULL) {
- return VFW_E_NO_ALLOCATOR;
- }
-
- m_bFlushing = FALSE;
-
- return m_pAllocator->Decommit();
-}
-
-// what requirements do we have of the allocator - override if you want
-// to support other people's allocators but need a specific alignment
-// or prefix.
-STDMETHODIMP
-CBaseInputPin::GetAllocatorRequirements(__out ALLOCATOR_PROPERTIES*pProps)
-{
- UNREFERENCED_PARAMETER(pProps);
- return E_NOTIMPL;
-}
-
-// Check if it's OK to process data
-//
-HRESULT
-CBaseInputPin::CheckStreaming()
-{
- // Shouldn't be able to get any data if we're not connected!
- ASSERT(IsConnected());
-
- // Don't process stuff in Stopped state
- if (IsStopped()) {
- return VFW_E_WRONG_STATE;
- }
- if (m_bFlushing) {
- return S_FALSE;
- }
- if (m_bRunTimeError) {
- return VFW_E_RUNTIME_ERROR;
- }
- return S_OK;
-}
-
-// Pass on the Quality notification q to
-// a. Our QualityControl sink (if we have one) or else
-// b. to our upstream filter
-// and if that doesn't work, throw it away with a bad return code
-HRESULT
-CBaseInputPin::PassNotify(Quality& q)
-{
- // We pass the message on, which means that we find the quality sink
- // for our input pin and send it there
-
- DbgLog((LOG_TRACE,3,TEXT("Passing Quality notification through transform")));
- if (m_pQSink!=NULL) {
- return m_pQSink->Notify(m_pFilter, q);
- } else {
- // no sink set, so pass it upstream
- HRESULT hr;
- IQualityControl * pIQC;
-
- hr = VFW_E_NOT_FOUND; // default
- if (m_Connected) {
- m_Connected->QueryInterface(IID_IQualityControl, (void**)&pIQC);
-
- if (pIQC!=NULL) {
- hr = pIQC->Notify(m_pFilter, q);
- pIQC->Release();
- }
- }
- return hr;
- }
-
-} // PassNotify
-
-//=====================================================================
-//=====================================================================
-// Memory allocation class, implements CMediaSample
-//=====================================================================
-//=====================================================================
-
-
-/* NOTE The implementation of this class calls the CUnknown constructor with
- a NULL outer unknown pointer. This has the effect of making us a self
- contained class, ie any QueryInterface, AddRef or Release calls will be
- routed to the class's NonDelegatingUnknown methods. You will typically
- find that the classes that do this then override one or more of these
- virtual functions to provide more specialised behaviour. A good example
- of this is where a class wants to keep the QueryInterface internal but
- still wants it's lifetime controlled by the external object */
-
-/* The last two parameters have default values of NULL and zero */
-
-CMediaSample::CMediaSample(__in_opt LPCTSTR pName,
- __in_opt CBaseAllocator *pAllocator,
- __inout_opt HRESULT *phr,
- __in_bcount_opt(length) LPBYTE pBuffer,
- LONG length) :
- m_pBuffer(pBuffer), // Initialise the buffer
- m_cbBuffer(length), // And it's length
- m_lActual(length), // By default, actual = length
- m_pMediaType(NULL), // No media type change
- m_dwFlags(0), // Nothing set
- m_cRef(0), // 0 ref count
- m_dwTypeSpecificFlags(0), // Type specific flags
- m_dwStreamId(AM_STREAM_MEDIA), // Stream id
- m_pAllocator(pAllocator) // Allocator
-{
-#ifdef DXMPERF
- PERFLOG_CTOR( pName ? pName : L"CMediaSample", (IMediaSample *) this );
-#endif // DXMPERF
-
- /* We must have an owner and it must also be derived from class
- CBaseAllocator BUT we do not hold a reference count on it */
-
- ASSERT(pAllocator);
-
- if (length < 0) {
- *phr = VFW_E_BUFFER_OVERFLOW;
- m_cbBuffer = 0;
- }
-}
-
-#ifdef UNICODE
-CMediaSample::CMediaSample(__in_opt LPCSTR pName,
- __in_opt CBaseAllocator *pAllocator,
- __inout_opt HRESULT *phr,
- __in_bcount_opt(length) LPBYTE pBuffer,
- LONG length) :
- m_pBuffer(pBuffer), // Initialise the buffer
- m_cbBuffer(length), // And it's length
- m_lActual(length), // By default, actual = length
- m_pMediaType(NULL), // No media type change
- m_dwFlags(0), // Nothing set
- m_cRef(0), // 0 ref count
- m_dwTypeSpecificFlags(0), // Type specific flags
- m_dwStreamId(AM_STREAM_MEDIA), // Stream id
- m_pAllocator(pAllocator) // Allocator
-{
-#ifdef DXMPERF
- PERFLOG_CTOR( L"CMediaSample", (IMediaSample *) this );
-#endif // DXMPERF
-
- /* We must have an owner and it must also be derived from class
- CBaseAllocator BUT we do not hold a reference count on it */
-
- ASSERT(pAllocator);
-}
-#endif
-
-/* Destructor deletes the media type memory */
-
-CMediaSample::~CMediaSample()
-{
-#ifdef DXMPERF
- PERFLOG_DTOR( L"CMediaSample", (IMediaSample *) this );
-#endif // DXMPERF
-
- if (m_pMediaType) {
- DeleteMediaType(m_pMediaType);
- }
-}
-
-/* Override this to publicise our interfaces */
-
-STDMETHODIMP
-CMediaSample::QueryInterface(REFIID riid, __deref_out void **ppv)
-{
- if (riid == IID_IMediaSample ||
- riid == IID_IMediaSample2 ||
- riid == IID_IUnknown) {
- return GetInterface((IMediaSample *) this, ppv);
- } else {
- *ppv = NULL;
- return E_NOINTERFACE;
- }
-}
-
-STDMETHODIMP_(ULONG)
-CMediaSample::AddRef()
-{
- return InterlockedIncrement(&m_cRef);
-}
-
-
-// -- CMediaSample lifetimes --
-//
-// On final release of this sample buffer it is not deleted but
-// returned to the freelist of the owning memory allocator
-//
-// The allocator may be waiting for the last buffer to be placed on the free
-// list in order to decommit all the memory, so the ReleaseBuffer() call may
-// result in this sample being deleted. We also need to hold a refcount on
-// the allocator to stop that going away until we have finished with this.
-// However, we cannot release the allocator before the ReleaseBuffer, as the
-// release may cause us to be deleted. Similarly we can't do it afterwards.
-//
-// Thus we must leave it to the allocator to hold an addref on our behalf.
-// When he issues us in GetBuffer, he addref's himself. When ReleaseBuffer
-// is called, he releases himself, possibly causing us and him to be deleted.
-
-
-STDMETHODIMP_(ULONG)
-CMediaSample::Release()
-{
- /* Decrement our own private reference count */
- LONG lRef;
- if (m_cRef == 1) {
- lRef = 0;
- m_cRef = 0;
- } else {
- lRef = InterlockedDecrement(&m_cRef);
- }
- ASSERT(lRef >= 0);
-
- DbgLog((LOG_MEMORY,3,TEXT(" Unknown %X ref-- = %d"),
- this, m_cRef));
-
- /* Did we release our final reference count */
- if (lRef == 0) {
- /* Free all resources */
- if (m_dwFlags & Sample_TypeChanged) {
- SetMediaType(NULL);
- }
- ASSERT(m_pMediaType == NULL);
- m_dwFlags = 0;
- m_dwTypeSpecificFlags = 0;
- m_dwStreamId = AM_STREAM_MEDIA;
-
- /* This may cause us to be deleted */
- // Our refcount is reliably 0 thus no-one will mess with us
- m_pAllocator->ReleaseBuffer(this);
- }
- return (ULONG)lRef;
-}
-
-
-// set the buffer pointer and length. Used by allocators that
-// want variable sized pointers or pointers into already-read data.
-// This is only available through a CMediaSample* not an IMediaSample*
-// and so cannot be changed by clients.
-HRESULT
-CMediaSample::SetPointer(__in_bcount(cBytes) BYTE * ptr, LONG cBytes)
-{
- if (cBytes < 0) {
- return VFW_E_BUFFER_OVERFLOW;
- }
- m_pBuffer = ptr; // new buffer area (could be null)
- m_cbBuffer = cBytes; // length of buffer
- m_lActual = cBytes; // length of data in buffer (assume full)
-
- return S_OK;
-}
-
-
-// get me a read/write pointer to this buffer's memory. I will actually
-// want to use sizeUsed bytes.
-STDMETHODIMP
-CMediaSample::GetPointer(__deref_out BYTE ** ppBuffer)
-{
- ValidateReadWritePtr(ppBuffer,sizeof(BYTE *));
-
- // creator must have set pointer either during
- // constructor or by SetPointer
- ASSERT(m_pBuffer);
-
- *ppBuffer = m_pBuffer;
- return NOERROR;
-}
-
-
-// return the size in bytes of this buffer
-STDMETHODIMP_(LONG)
-CMediaSample::GetSize(void)
-{
- return m_cbBuffer;
-}
-
-
-// get the stream time at which this sample should start and finish.
-STDMETHODIMP
-CMediaSample::GetTime(
- __out REFERENCE_TIME * pTimeStart, // put time here
- __out REFERENCE_TIME * pTimeEnd
-)
-{
- ValidateReadWritePtr(pTimeStart,sizeof(REFERENCE_TIME));
- ValidateReadWritePtr(pTimeEnd,sizeof(REFERENCE_TIME));
-
- if (!(m_dwFlags & Sample_StopValid)) {
- if (!(m_dwFlags & Sample_TimeValid)) {
- return VFW_E_SAMPLE_TIME_NOT_SET;
- } else {
- *pTimeStart = m_Start;
-
- // Make sure old stuff works
- *pTimeEnd = m_Start + 1;
- return VFW_S_NO_STOP_TIME;
- }
- }
-
- *pTimeStart = m_Start;
- *pTimeEnd = m_End;
- return NOERROR;
-}
-
-
-// Set the stream time at which this sample should start and finish.
-// NULL pointers means the time is reset
-STDMETHODIMP
-CMediaSample::SetTime(
- __in_opt REFERENCE_TIME * pTimeStart,
- __in_opt REFERENCE_TIME * pTimeEnd
-)
-{
- if (pTimeStart == NULL) {
- ASSERT(pTimeEnd == NULL);
- m_dwFlags &= ~(Sample_TimeValid | Sample_StopValid);
- } else {
- if (pTimeEnd == NULL) {
- m_Start = *pTimeStart;
- m_dwFlags |= Sample_TimeValid;
- m_dwFlags &= ~Sample_StopValid;
- } else {
- ValidateReadPtr(pTimeStart,sizeof(REFERENCE_TIME));
- ValidateReadPtr(pTimeEnd,sizeof(REFERENCE_TIME));
- ASSERT(*pTimeEnd >= *pTimeStart);
-
- m_Start = *pTimeStart;
- m_End = *pTimeEnd;
- m_dwFlags |= Sample_TimeValid | Sample_StopValid;
- }
- }
- return NOERROR;
-}
-
-
-// get the media times (eg bytes) for this sample
-STDMETHODIMP
-CMediaSample::GetMediaTime(
- __out LONGLONG * pTimeStart,
- __out LONGLONG * pTimeEnd
-)
-{
- ValidateReadWritePtr(pTimeStart,sizeof(LONGLONG));
- ValidateReadWritePtr(pTimeEnd,sizeof(LONGLONG));
-
- if (!(m_dwFlags & Sample_MediaTimeValid)) {
- return VFW_E_MEDIA_TIME_NOT_SET;
- }
-
- *pTimeStart = m_MediaStart;
- *pTimeEnd = (m_MediaStart + m_MediaEnd);
- return NOERROR;
-}
-
-
-// Set the media times for this sample
-STDMETHODIMP
-CMediaSample::SetMediaTime(
- __in_opt LONGLONG * pTimeStart,
- __in_opt LONGLONG * pTimeEnd
-)
-{
- if (pTimeStart == NULL) {
- ASSERT(pTimeEnd == NULL);
- m_dwFlags &= ~Sample_MediaTimeValid;
- } else {
- if (NULL == pTimeEnd) {
- return E_POINTER;
- }
- ValidateReadPtr(pTimeStart,sizeof(LONGLONG));
- ValidateReadPtr(pTimeEnd,sizeof(LONGLONG));
- ASSERT(*pTimeEnd >= *pTimeStart);
-
- m_MediaStart = *pTimeStart;
- m_MediaEnd = (LONG)(*pTimeEnd - *pTimeStart);
- m_dwFlags |= Sample_MediaTimeValid;
- }
- return NOERROR;
-}
-
-
-STDMETHODIMP
-CMediaSample::IsSyncPoint(void)
-{
- if (m_dwFlags & Sample_SyncPoint) {
- return S_OK;
- } else {
- return S_FALSE;
- }
-}
-
-
-STDMETHODIMP
-CMediaSample::SetSyncPoint(BOOL bIsSyncPoint)
-{
- if (bIsSyncPoint) {
- m_dwFlags |= Sample_SyncPoint;
- } else {
- m_dwFlags &= ~Sample_SyncPoint;
- }
- return NOERROR;
-}
-
-// returns S_OK if there is a discontinuity in the data (this same is
-// not a continuation of the previous stream of data
-// - there has been a seek).
-STDMETHODIMP
-CMediaSample::IsDiscontinuity(void)
-{
- if (m_dwFlags & Sample_Discontinuity) {
- return S_OK;
- } else {
- return S_FALSE;
- }
-}
-
-// set the discontinuity property - TRUE if this sample is not a
-// continuation, but a new sample after a seek.
-STDMETHODIMP
-CMediaSample::SetDiscontinuity(BOOL bDiscont)
-{
- // should be TRUE or FALSE
- if (bDiscont) {
- m_dwFlags |= Sample_Discontinuity;
- } else {
- m_dwFlags &= ~Sample_Discontinuity;
- }
- return S_OK;
-}
-
-STDMETHODIMP
-CMediaSample::IsPreroll(void)
-{
- if (m_dwFlags & Sample_Preroll) {
- return S_OK;
- } else {
- return S_FALSE;
- }
-}
-
-
-STDMETHODIMP
-CMediaSample::SetPreroll(BOOL bIsPreroll)
-{
- if (bIsPreroll) {
- m_dwFlags |= Sample_Preroll;
- } else {
- m_dwFlags &= ~Sample_Preroll;
- }
- return NOERROR;
-}
-
-STDMETHODIMP_(LONG)
-CMediaSample::GetActualDataLength(void)
-{
- return m_lActual;
-}
-
-
-STDMETHODIMP
-CMediaSample::SetActualDataLength(LONG lActual)
-{
- if (lActual > m_cbBuffer || lActual < 0) {
- ASSERT(lActual <= GetSize());
- return VFW_E_BUFFER_OVERFLOW;
- }
- m_lActual = lActual;
- return NOERROR;
-}
-
-
-/* These allow for limited format changes in band */
-
-STDMETHODIMP
-CMediaSample::GetMediaType(__deref_out AM_MEDIA_TYPE **ppMediaType)
-{
- ValidateReadWritePtr(ppMediaType,sizeof(AM_MEDIA_TYPE *));
- ASSERT(ppMediaType);
-
- /* Do we have a new media type for them */
-
- if (!(m_dwFlags & Sample_TypeChanged)) {
- ASSERT(m_pMediaType == NULL);
- *ppMediaType = NULL;
- return S_FALSE;
- }
-
- ASSERT(m_pMediaType);
-
- /* Create a copy of our media type */
-
- *ppMediaType = CreateMediaType(m_pMediaType);
- if (*ppMediaType == NULL) {
- return E_OUTOFMEMORY;
- }
- return NOERROR;
-}
-
-
-/* Mark this sample as having a different format type */
-
-STDMETHODIMP
-CMediaSample::SetMediaType(__in_opt AM_MEDIA_TYPE *pMediaType)
-{
- /* Delete the current media type */
-
- if (m_pMediaType) {
- DeleteMediaType(m_pMediaType);
- m_pMediaType = NULL;
- }
-
- /* Mechanism for resetting the format type */
-
- if (pMediaType == NULL) {
- m_dwFlags &= ~Sample_TypeChanged;
- return NOERROR;
- }
-
- ASSERT(pMediaType);
- ValidateReadPtr(pMediaType,sizeof(AM_MEDIA_TYPE));
-
- /* Take a copy of the media type */
-
- m_pMediaType = CreateMediaType(pMediaType);
- if (m_pMediaType == NULL) {
- m_dwFlags &= ~Sample_TypeChanged;
- return E_OUTOFMEMORY;
- }
-
- m_dwFlags |= Sample_TypeChanged;
- return NOERROR;
-}
-
-// Set and get properties (IMediaSample2)
-STDMETHODIMP CMediaSample::GetProperties(
- DWORD cbProperties,
- __out_bcount(cbProperties) BYTE * pbProperties
-)
-{
- if (0 != cbProperties) {
- CheckPointer(pbProperties, E_POINTER);
- // Return generic stuff up to the length
- AM_SAMPLE2_PROPERTIES Props;
- Props.cbData = min(cbProperties, sizeof(Props));
- Props.dwSampleFlags = m_dwFlags & ~Sample_MediaTimeValid;
- Props.dwTypeSpecificFlags = m_dwTypeSpecificFlags;
- Props.pbBuffer = m_pBuffer;
- Props.cbBuffer = m_cbBuffer;
- Props.lActual = m_lActual;
- Props.tStart = m_Start;
- Props.tStop = m_End;
- Props.dwStreamId = m_dwStreamId;
- if (m_dwFlags & AM_SAMPLE_TYPECHANGED) {
- Props.pMediaType = m_pMediaType;
- } else {
- Props.pMediaType = NULL;
- }
- CopyMemory(pbProperties, &Props, Props.cbData);
- }
- return S_OK;
-}
-
-#define CONTAINS_FIELD(type, field, offset) \
- ((FIELD_OFFSET(type, field) + sizeof(((type *)0)->field)) <= offset)
-
-HRESULT CMediaSample::SetProperties(
- DWORD cbProperties,
- __in_bcount(cbProperties) const BYTE * pbProperties
-)
-{
-
- /* Generic properties */
- AM_MEDIA_TYPE *pMediaType = NULL;
-
- if (CONTAINS_FIELD(AM_SAMPLE2_PROPERTIES, cbData, cbProperties)) {
- CheckPointer(pbProperties, E_POINTER);
- AM_SAMPLE2_PROPERTIES *pProps =
- (AM_SAMPLE2_PROPERTIES *)pbProperties;
-
- /* Don't use more data than is actually there */
- if (pProps->cbData < cbProperties) {
- cbProperties = pProps->cbData;
- }
- /* We only handle IMediaSample2 */
- if (cbProperties > sizeof(*pProps) ||
- pProps->cbData > sizeof(*pProps)) {
- return E_INVALIDARG;
- }
- /* Do checks first, the assignments (for backout) */
- if (CONTAINS_FIELD(AM_SAMPLE2_PROPERTIES, dwSampleFlags, cbProperties)) {
- /* Check the flags */
- if (pProps->dwSampleFlags &
- (~Sample_ValidFlags | Sample_MediaTimeValid)) {
- return E_INVALIDARG;
- }
- /* Check a flag isn't being set for a property
- not being provided
- */
- if ((pProps->dwSampleFlags & AM_SAMPLE_TIMEVALID) &&
- !(m_dwFlags & AM_SAMPLE_TIMEVALID) &&
- !CONTAINS_FIELD(AM_SAMPLE2_PROPERTIES, tStop, cbProperties)) {
- return E_INVALIDARG;
- }
- }
- /* NB - can't SET the pointer or size */
- if (CONTAINS_FIELD(AM_SAMPLE2_PROPERTIES, pbBuffer, cbProperties)) {
-
- /* Check pbBuffer */
- if (pProps->pbBuffer != 0 && pProps->pbBuffer != m_pBuffer) {
- return E_INVALIDARG;
- }
- }
- if (CONTAINS_FIELD(AM_SAMPLE2_PROPERTIES, cbBuffer, cbProperties)) {
-
- /* Check cbBuffer */
- if (pProps->cbBuffer != 0 && pProps->cbBuffer != m_cbBuffer) {
- return E_INVALIDARG;
- }
- }
- if (CONTAINS_FIELD(AM_SAMPLE2_PROPERTIES, cbBuffer, cbProperties) &&
- CONTAINS_FIELD(AM_SAMPLE2_PROPERTIES, lActual, cbProperties)) {
-
- /* Check lActual */
- if (pProps->cbBuffer < pProps->lActual) {
- return E_INVALIDARG;
- }
- }
-
- if (CONTAINS_FIELD(AM_SAMPLE2_PROPERTIES, pMediaType, cbProperties)) {
-
- /* Check pMediaType */
- if (pProps->dwSampleFlags & AM_SAMPLE_TYPECHANGED) {
- CheckPointer(pProps->pMediaType, E_POINTER);
- pMediaType = CreateMediaType(pProps->pMediaType);
- if (pMediaType == NULL) {
- return E_OUTOFMEMORY;
- }
- }
- }
-
- /* Now do the assignments */
- if (CONTAINS_FIELD(AM_SAMPLE2_PROPERTIES, dwStreamId, cbProperties)) {
- m_dwStreamId = pProps->dwStreamId;
- }
- if (CONTAINS_FIELD(AM_SAMPLE2_PROPERTIES, dwSampleFlags, cbProperties)) {
- /* Set the flags */
- m_dwFlags = pProps->dwSampleFlags |
- (m_dwFlags & Sample_MediaTimeValid);
- m_dwTypeSpecificFlags = pProps->dwTypeSpecificFlags;
- } else {
- if (CONTAINS_FIELD(AM_SAMPLE2_PROPERTIES, dwTypeSpecificFlags, cbProperties)) {
- m_dwTypeSpecificFlags = pProps->dwTypeSpecificFlags;
- }
- }
-
- if (CONTAINS_FIELD(AM_SAMPLE2_PROPERTIES, lActual, cbProperties)) {
- /* Set lActual */
- m_lActual = pProps->lActual;
- }
-
- if (CONTAINS_FIELD(AM_SAMPLE2_PROPERTIES, tStop, cbProperties)) {
-
- /* Set the times */
- m_End = pProps->tStop;
- }
- if (CONTAINS_FIELD(AM_SAMPLE2_PROPERTIES, tStart, cbProperties)) {
-
- /* Set the times */
- m_Start = pProps->tStart;
- }
-
- if (CONTAINS_FIELD(AM_SAMPLE2_PROPERTIES, pMediaType, cbProperties)) {
- /* Set pMediaType */
- if (pProps->dwSampleFlags & AM_SAMPLE_TYPECHANGED) {
- if (m_pMediaType != NULL) {
- DeleteMediaType(m_pMediaType);
- }
- m_pMediaType = pMediaType;
- }
- }
-
- /* Fix up the type changed flag to correctly reflect the current state
- If, for instance the input contained no type change but the
- output does then if we don't do this we'd lose the
- output media type.
- */
- if (m_pMediaType) {
- m_dwFlags |= Sample_TypeChanged;
- } else {
- m_dwFlags &= ~Sample_TypeChanged;
- }
- }
-
- return S_OK;
-}
-
-
-//
-// The streaming thread calls IPin::NewSegment(), IPin::EndOfStream(),
-// IMemInputPin::Receive() and IMemInputPin::ReceiveMultiple() on the
-// connected input pin. The application thread calls Block(). The
-// following class members can only be called by the streaming thread.
-//
-// Deliver()
-// DeliverNewSegment()
-// StartUsingOutputPin()
-// StopUsingOutputPin()
-// ChangeOutputFormat()
-// ChangeMediaType()
-// DynamicReconnect()
-//
-// The following class members can only be called by the application thread.
-//
-// Block()
-// SynchronousBlockOutputPin()
-// AsynchronousBlockOutputPin()
-//
-
-CDynamicOutputPin::CDynamicOutputPin(
- __in_opt LPCTSTR pObjectName,
- __in CBaseFilter *pFilter,
- __in CCritSec *pLock,
- __inout HRESULT *phr,
- __in_opt LPCWSTR pName) :
- CBaseOutputPin(pObjectName, pFilter, pLock, phr, pName),
- m_hStopEvent(NULL),
- m_pGraphConfig(NULL),
- m_bPinUsesReadOnlyAllocator(FALSE),
- m_BlockState(NOT_BLOCKED),
- m_hUnblockOutputPinEvent(NULL),
- m_hNotifyCallerPinBlockedEvent(NULL),
- m_dwBlockCallerThreadID(0),
- m_dwNumOutstandingOutputPinUsers(0)
-{
- HRESULT hr = Initialize();
- if( FAILED( hr ) ) {
- *phr = hr;
- return;
- }
-}
-
-#ifdef UNICODE
-CDynamicOutputPin::CDynamicOutputPin(
- __in_opt LPCSTR pObjectName,
- __in CBaseFilter *pFilter,
- __in CCritSec *pLock,
- __inout HRESULT *phr,
- __in_opt LPCWSTR pName) :
- CBaseOutputPin(pObjectName, pFilter, pLock, phr, pName),
- m_hStopEvent(NULL),
- m_pGraphConfig(NULL),
- m_bPinUsesReadOnlyAllocator(FALSE),
- m_BlockState(NOT_BLOCKED),
- m_hUnblockOutputPinEvent(NULL),
- m_hNotifyCallerPinBlockedEvent(NULL),
- m_dwBlockCallerThreadID(0),
- m_dwNumOutstandingOutputPinUsers(0)
-{
- HRESULT hr = Initialize();
- if( FAILED( hr ) ) {
- *phr = hr;
- return;
- }
-}
-#endif
-
-CDynamicOutputPin::~CDynamicOutputPin()
-{
- if(NULL != m_hUnblockOutputPinEvent) {
- // This call should not fail because we have access to m_hUnblockOutputPinEvent
- // and m_hUnblockOutputPinEvent is a valid event.
- EXECUTE_ASSERT(::CloseHandle(m_hUnblockOutputPinEvent));
- }
-
- if(NULL != m_hNotifyCallerPinBlockedEvent) {
- // This call should not fail because we have access to m_hNotifyCallerPinBlockedEvent
- // and m_hNotifyCallerPinBlockedEvent is a valid event.
- EXECUTE_ASSERT(::CloseHandle(m_hNotifyCallerPinBlockedEvent));
- }
-}
-
-HRESULT CDynamicOutputPin::Initialize(void)
-{
- m_hUnblockOutputPinEvent = ::CreateEvent( NULL, // The event will have the default security descriptor.
- TRUE, // This is a manual reset event.
- TRUE, // The event is initially signaled.
- NULL ); // The event is not named.
-
- // CreateEvent() returns NULL if an error occurs.
- if(NULL == m_hUnblockOutputPinEvent) {
- return AmGetLastErrorToHResult();
- }
-
- // Set flag to say we can reconnect while streaming.
- SetReconnectWhenActive(true);
-
- return S_OK;
-}
-
-STDMETHODIMP CDynamicOutputPin::NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv)
-{
- if(riid == IID_IPinFlowControl) {
- return GetInterface(static_cast<IPinFlowControl*>(this), ppv);
- } else {
- return CBaseOutputPin::NonDelegatingQueryInterface(riid, ppv);
- }
-}
-
-STDMETHODIMP CDynamicOutputPin::Disconnect(void)
-{
- CAutoLock cObjectLock(m_pLock);
- return DisconnectInternal();
-}
-
-STDMETHODIMP CDynamicOutputPin::Block(DWORD dwBlockFlags, HANDLE hEvent)
-{
- const DWORD VALID_FLAGS = AM_PIN_FLOW_CONTROL_BLOCK;
-
- // Check for illegal flags.
- if(dwBlockFlags & ~VALID_FLAGS) {
- return E_INVALIDARG;
- }
-
- // Make sure the event is unsignaled.
- if((dwBlockFlags & AM_PIN_FLOW_CONTROL_BLOCK) && (NULL != hEvent)) {
- if( !::ResetEvent( hEvent ) ) {
- return AmGetLastErrorToHResult();
- }
- }
-
- // No flags are set if we are unblocking the output pin.
- if(0 == dwBlockFlags) {
-
- // This parameter should be NULL because unblock operations are always synchronous.
- // There is no need to notify the caller when the event is done.
- if(NULL != hEvent) {
- return E_INVALIDARG;
- }
- }
-
- #ifdef DEBUG
- AssertValid();
- #endif // DEBUG
-
- HRESULT hr;
-
- if(dwBlockFlags & AM_PIN_FLOW_CONTROL_BLOCK) {
- // IPinFlowControl::Block()'s hEvent parameter is NULL if the block is synchronous.
- // If hEvent is not NULL, the block is asynchronous.
- if(NULL == hEvent) {
- hr = SynchronousBlockOutputPin();
- } else {
- hr = AsynchronousBlockOutputPin(hEvent);
- }
- } else {
- hr = UnblockOutputPin();
- }
-
- #ifdef DEBUG
- AssertValid();
- #endif // DEBUG
-
- if(FAILED(hr)) {
- return hr;
- }
-
- return S_OK;
-}
-
-HRESULT CDynamicOutputPin::SynchronousBlockOutputPin(void)
-{
- HANDLE hNotifyCallerPinBlockedEvent = :: CreateEvent( NULL, // The event will have the default security attributes.
- FALSE, // This is an automatic reset event.
- FALSE, // The event is initially unsignaled.
- NULL ); // The event is not named.
-
- // CreateEvent() returns NULL if an error occurs.
- if(NULL == hNotifyCallerPinBlockedEvent) {
- return AmGetLastErrorToHResult();
- }
-
- HRESULT hr = AsynchronousBlockOutputPin(hNotifyCallerPinBlockedEvent);
- if(FAILED(hr)) {
- // This call should not fail because we have access to hNotifyCallerPinBlockedEvent
- // and hNotifyCallerPinBlockedEvent is a valid event.
- EXECUTE_ASSERT(::CloseHandle(hNotifyCallerPinBlockedEvent));
-
- return hr;
- }
-
- hr = WaitEvent(hNotifyCallerPinBlockedEvent);
-
- // This call should not fail because we have access to hNotifyCallerPinBlockedEvent
- // and hNotifyCallerPinBlockedEvent is a valid event.
- EXECUTE_ASSERT(::CloseHandle(hNotifyCallerPinBlockedEvent));
-
- if(FAILED(hr)) {
- return hr;
- }
-
- return S_OK;
-}
-
-HRESULT CDynamicOutputPin::AsynchronousBlockOutputPin(HANDLE hNotifyCallerPinBlockedEvent)
-{
- // This function holds the m_BlockStateLock because it uses
- // m_dwBlockCallerThreadID, m_BlockState and
- // m_hNotifyCallerPinBlockedEvent.
- CAutoLock alBlockStateLock(&m_BlockStateLock);
-
- if(NOT_BLOCKED != m_BlockState) {
- if(m_dwBlockCallerThreadID == ::GetCurrentThreadId()) {
- return VFW_E_PIN_ALREADY_BLOCKED_ON_THIS_THREAD;
- } else {
- return VFW_E_PIN_ALREADY_BLOCKED;
- }
- }
-
- BOOL fSuccess = ::DuplicateHandle( ::GetCurrentProcess(),
- hNotifyCallerPinBlockedEvent,
- ::GetCurrentProcess(),
- &m_hNotifyCallerPinBlockedEvent,
- EVENT_MODIFY_STATE,
- FALSE,
- 0 );
- if( !fSuccess ) {
- return AmGetLastErrorToHResult();
- }
-
- m_BlockState = PENDING;
- m_dwBlockCallerThreadID = ::GetCurrentThreadId();
-
- // The output pin cannot be blocked if the streaming thread is
- // calling IPin::NewSegment(), IPin::EndOfStream(), IMemInputPin::Receive()
- // or IMemInputPin::ReceiveMultiple() on the connected input pin. Also, it
- // cannot be blocked if the streaming thread is calling DynamicReconnect(),
- // ChangeMediaType() or ChangeOutputFormat().
- if(!StreamingThreadUsingOutputPin()) {
-
- // The output pin can be immediately blocked.
- BlockOutputPin();
- }
-
- return S_OK;
-}
-
-void CDynamicOutputPin::BlockOutputPin(void)
-{
- // The caller should always hold the m_BlockStateLock because this function
- // uses m_BlockState and m_hNotifyCallerPinBlockedEvent.
- ASSERT(CritCheckIn(&m_BlockStateLock));
-
- // This function should not be called if the streaming thread is modifying
- // the connection state or it's passing data downstream.
- ASSERT(!StreamingThreadUsingOutputPin());
-
- // This should not fail because we successfully created the event
- // and we have the security permissions to change it's state.
- EXECUTE_ASSERT(::ResetEvent(m_hUnblockOutputPinEvent));
-
- // This event should not fail because AsynchronousBlockOutputPin() successfully
- // duplicated this handle and we have the appropriate security permissions.
- EXECUTE_ASSERT(::SetEvent(m_hNotifyCallerPinBlockedEvent));
- EXECUTE_ASSERT(::CloseHandle(m_hNotifyCallerPinBlockedEvent));
-
- m_BlockState = BLOCKED;
- m_hNotifyCallerPinBlockedEvent = NULL;
-}
-
-HRESULT CDynamicOutputPin::UnblockOutputPin(void)
-{
- // UnblockOutputPin() holds the m_BlockStateLock because it
- // uses m_BlockState, m_dwBlockCallerThreadID and
- // m_hNotifyCallerPinBlockedEvent.
- CAutoLock alBlockStateLock(&m_BlockStateLock);
-
- if(NOT_BLOCKED == m_BlockState) {
- return S_FALSE;
- }
-
- // This should not fail because we successfully created the event
- // and we have the security permissions to change it's state.
- EXECUTE_ASSERT(::SetEvent(m_hUnblockOutputPinEvent));
-
- // Cancel the block operation if it's still pending.
- if(NULL != m_hNotifyCallerPinBlockedEvent) {
- // This event should not fail because AsynchronousBlockOutputPin() successfully
- // duplicated this handle and we have the appropriate security permissions.
- EXECUTE_ASSERT(::SetEvent(m_hNotifyCallerPinBlockedEvent));
- EXECUTE_ASSERT(::CloseHandle(m_hNotifyCallerPinBlockedEvent));
- }
-
- m_BlockState = NOT_BLOCKED;
- m_dwBlockCallerThreadID = 0;
- m_hNotifyCallerPinBlockedEvent = NULL;
-
- return S_OK;
-}
-
-HRESULT CDynamicOutputPin::StartUsingOutputPin(void)
-{
- // The caller should not hold m_BlockStateLock. If the caller does,
- // a deadlock could occur.
- ASSERT(CritCheckOut(&m_BlockStateLock));
-
- CAutoLock alBlockStateLock(&m_BlockStateLock);
-
- #ifdef DEBUG
- AssertValid();
- #endif // DEBUG
-
- // Are we in the middle of a block operation?
- while(BLOCKED == m_BlockState) {
- m_BlockStateLock.Unlock();
-
- // If this ASSERT fires, a deadlock could occur. The caller should make sure
- // that this thread never acquires the Block State lock more than once.
- ASSERT(CritCheckOut( &m_BlockStateLock ));
-
- // WaitForMultipleObjects() returns WAIT_OBJECT_0 if the unblock event
- // is fired. It returns WAIT_OBJECT_0 + 1 if the stop event if fired.
- // See the Windows SDK documentation for more information on
- // WaitForMultipleObjects().
- const DWORD UNBLOCK = WAIT_OBJECT_0;
- const DWORD STOP = WAIT_OBJECT_0 + 1;
-
- HANDLE ahWaitEvents[] = { m_hUnblockOutputPinEvent, m_hStopEvent };
- DWORD dwNumWaitEvents = sizeof(ahWaitEvents)/sizeof(HANDLE);
-
- DWORD dwReturnValue = ::WaitForMultipleObjects( dwNumWaitEvents, ahWaitEvents, FALSE, INFINITE );
-
- m_BlockStateLock.Lock();
-
- #ifdef DEBUG
- AssertValid();
- #endif // DEBUG
-
- switch( dwReturnValue ) {
- case UNBLOCK:
- break;
-
- case STOP:
- return VFW_E_STATE_CHANGED;
-
- case WAIT_FAILED:
- return AmGetLastErrorToHResult();
-
- default:
- DbgBreak( "An Unexpected case occured in CDynamicOutputPin::StartUsingOutputPin()." );
- return E_UNEXPECTED;
- }
- }
-
- m_dwNumOutstandingOutputPinUsers++;
-
- #ifdef DEBUG
- AssertValid();
- #endif // DEBUG
-
- return S_OK;
-}
-
-void CDynamicOutputPin::StopUsingOutputPin(void)
-{
- CAutoLock alBlockStateLock(&m_BlockStateLock);
-
- #ifdef DEBUG
- AssertValid();
- #endif // DEBUG
-
- m_dwNumOutstandingOutputPinUsers--;
-
- if((m_dwNumOutstandingOutputPinUsers == 0) && (NOT_BLOCKED != m_BlockState)) {
- BlockOutputPin();
- }
-
- #ifdef DEBUG
- AssertValid();
- #endif // DEBUG
-}
-
-bool CDynamicOutputPin::StreamingThreadUsingOutputPin(void)
-{
- CAutoLock alBlockStateLock(&m_BlockStateLock);
-
- return (m_dwNumOutstandingOutputPinUsers > 0);
-}
-
-void CDynamicOutputPin::SetConfigInfo(IGraphConfig *pGraphConfig, HANDLE hStopEvent)
-{
- // This pointer is not addrefed because filters are not allowed to
- // hold references to the filter graph manager. See the documentation for
- // IBaseFilter::JoinFilterGraph() in the Direct Show SDK for more information.
- m_pGraphConfig = pGraphConfig;
-
- m_hStopEvent = hStopEvent;
-}
-
-HRESULT CDynamicOutputPin::Active(void)
-{
- // Make sure the user initialized the object by calling SetConfigInfo().
- if((NULL == m_hStopEvent) || (NULL == m_pGraphConfig)) {
- DbgBreak( ERROR: CDynamicOutputPin::Active() failed because m_pGraphConfig and m_hStopEvent were not initialized. Call SetConfigInfo() to initialize them. );
- return E_FAIL;
- }
-
- // If this ASSERT fires, the user may have passed an invalid event handle to SetConfigInfo().
- // The ASSERT can also fire if the event if destroyed and then Active() is called. An event
- // handle is invalid if 1) the event does not exist or the user does not have the security
- // permissions to use the event.
- EXECUTE_ASSERT(ResetEvent(m_hStopEvent));
-
- return CBaseOutputPin::Active();
-}
-
-HRESULT CDynamicOutputPin::Inactive(void)
-{
- // If this ASSERT fires, the user may have passed an invalid event handle to SetConfigInfo().
- // The ASSERT can also fire if the event if destroyed and then Active() is called. An event
- // handle is invalid if 1) the event does not exist or the user does not have the security
- // permissions to use the event.
- EXECUTE_ASSERT(SetEvent(m_hStopEvent));
-
- return CBaseOutputPin::Inactive();
-}
-
-HRESULT CDynamicOutputPin::DeliverBeginFlush(void)
-{
- // If this ASSERT fires, the user may have passed an invalid event handle to SetConfigInfo().
- // The ASSERT can also fire if the event if destroyed and then DeliverBeginFlush() is called.
- // An event handle is invalid if 1) the event does not exist or the user does not have the security
- // permissions to use the event.
- EXECUTE_ASSERT(SetEvent(m_hStopEvent));
-
- return CBaseOutputPin::DeliverBeginFlush();
-}
-
-HRESULT CDynamicOutputPin::DeliverEndFlush(void)
-{
- // If this ASSERT fires, the user may have passed an invalid event handle to SetConfigInfo().
- // The ASSERT can also fire if the event if destroyed and then DeliverBeginFlush() is called.
- // An event handle is invalid if 1) the event does not exist or the user does not have the security
- // permissions to use the event.
- EXECUTE_ASSERT(ResetEvent(m_hStopEvent));
-
- return CBaseOutputPin::DeliverEndFlush();
-}
-
-
-// ChangeOutputFormat() either dynamicly changes the connection's format type or it dynamicly
-// reconnects the output pin.
-HRESULT CDynamicOutputPin::ChangeOutputFormat
- (
- const AM_MEDIA_TYPE *pmt,
- REFERENCE_TIME tSegmentStart,
- REFERENCE_TIME tSegmentStop,
- double dSegmentRate
- )
-{
- // The caller should call StartUsingOutputPin() before calling this
- // method.
- ASSERT(StreamingThreadUsingOutputPin());
-
- // Callers should always pass a valid media type to ChangeOutputFormat() .
- ASSERT(NULL != pmt);
-
- CMediaType cmt(*pmt);
- HRESULT hr = ChangeMediaType(&cmt);
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = DeliverNewSegment(tSegmentStart, tSegmentStop, dSegmentRate);
- if( FAILED( hr ) ) {
- return hr;
- }
-
- return S_OK;
-}
-
-HRESULT CDynamicOutputPin::ChangeMediaType(const CMediaType *pmt)
-{
- // The caller should call StartUsingOutputPin() before calling this
- // method.
- ASSERT(StreamingThreadUsingOutputPin());
-
- // This function assumes the filter graph is running.
- ASSERT(!IsStopped());
-
- if(!IsConnected()) {
- return VFW_E_NOT_CONNECTED;
- }
-
- /* First check if the downstream pin will accept a dynamic
- format change
- */
- QzCComPtr<IPinConnection> pConnection;
-
- m_Connected->QueryInterface(IID_IPinConnection, (void **)&pConnection);
- if(pConnection != NULL) {
-
- if(S_OK == pConnection->DynamicQueryAccept(pmt)) {
-
- HRESULT hr = ChangeMediaTypeHelper(pmt);
- if(FAILED(hr)) {
- return hr;
- }
-
- return S_OK;
- }
- }
-
- /* Can't do the dynamic connection */
- return DynamicReconnect(pmt);
-}
-
-HRESULT CDynamicOutputPin::ChangeMediaTypeHelper(const CMediaType *pmt)
-{
- // The caller should call StartUsingOutputPin() before calling this
- // method.
- ASSERT(StreamingThreadUsingOutputPin());
-
- HRESULT hr = m_Connected->ReceiveConnection(this, pmt);
- if(FAILED(hr)) {
- return hr;
- }
-
- hr = SetMediaType(pmt);
- if(FAILED(hr)) {
- return hr;
- }
-
- // Does this pin use the local memory transport?
- if(NULL != m_pInputPin) {
- // This function assumes that m_pInputPin and m_Connected are
- // two different interfaces to the same object.
- ASSERT(::IsEqualObject(m_Connected, m_pInputPin));
-
- ALLOCATOR_PROPERTIES apInputPinRequirements;
- apInputPinRequirements.cbAlign = 0;
- apInputPinRequirements.cbBuffer = 0;
- apInputPinRequirements.cbPrefix = 0;
- apInputPinRequirements.cBuffers = 0;
-
- m_pInputPin->GetAllocatorRequirements(&apInputPinRequirements);
-
- // A zero allignment does not make any sense.
- if(0 == apInputPinRequirements.cbAlign) {
- apInputPinRequirements.cbAlign = 1;
- }
-
- hr = m_pAllocator->Decommit();
- if(FAILED(hr)) {
- return hr;
- }
-
- hr = DecideBufferSize(m_pAllocator, &apInputPinRequirements);
- if(FAILED(hr)) {
- return hr;
- }
-
- hr = m_pAllocator->Commit();
- if(FAILED(hr)) {
- return hr;
- }
-
- hr = m_pInputPin->NotifyAllocator(m_pAllocator, m_bPinUsesReadOnlyAllocator);
- if(FAILED(hr)) {
- return hr;
- }
- }
-
- return S_OK;
-}
-
-// this method has to be called from the thread that is pushing data,
-// and it's the caller's responsibility to make sure that the thread
-// has no outstand samples because they cannot be delivered after a
-// reconnect
-//
-HRESULT CDynamicOutputPin::DynamicReconnect( const CMediaType* pmt )
-{
- // The caller should call StartUsingOutputPin() before calling this
- // method.
- ASSERT(StreamingThreadUsingOutputPin());
-
- if((m_pGraphConfig == NULL) || (NULL == m_hStopEvent)) {
- return E_FAIL;
- }
-
- HRESULT hr = m_pGraphConfig->Reconnect(
- this,
- NULL,
- pmt,
- NULL,
- m_hStopEvent,
- AM_GRAPH_CONFIG_RECONNECT_CACHE_REMOVED_FILTERS );
-
- return hr;
-}
-
-HRESULT CDynamicOutputPin::CompleteConnect(IPin *pReceivePin)
-{
- HRESULT hr = CBaseOutputPin::CompleteConnect(pReceivePin);
- if(SUCCEEDED(hr)) {
- if(!IsStopped() && m_pAllocator) {
- hr = m_pAllocator->Commit();
- ASSERT(hr != VFW_E_ALREADY_COMMITTED);
- }
- }
-
- return hr;
-}
-
-#ifdef DEBUG
-void CDynamicOutputPin::AssertValid(void)
-{
- // Make sure the object was correctly initialized.
-
- // This ASSERT only fires if the object failed to initialize
- // and the user ignored the constructor's return code (phr).
- ASSERT(NULL != m_hUnblockOutputPinEvent);
-
- // If either of these ASSERTs fire, the user did not correctly call
- // SetConfigInfo().
- ASSERT(NULL != m_hStopEvent);
- ASSERT(NULL != m_pGraphConfig);
-
- // Make sure the block state is consistent.
-
- CAutoLock alBlockStateLock(&m_BlockStateLock);
-
- // BLOCK_STATE variables only have three legal values: PENDING, BLOCKED and NOT_BLOCKED.
- ASSERT((NOT_BLOCKED == m_BlockState) || (PENDING == m_BlockState) || (BLOCKED == m_BlockState));
-
- // m_hNotifyCallerPinBlockedEvent is only needed when a block operation cannot complete
- // immediately.
- ASSERT(((NULL == m_hNotifyCallerPinBlockedEvent) && (PENDING != m_BlockState)) ||
- ((NULL != m_hNotifyCallerPinBlockedEvent) && (PENDING == m_BlockState)) );
-
- // m_dwBlockCallerThreadID should always be 0 if the pin is not blocked and
- // the user is not trying to block the pin.
- ASSERT((0 == m_dwBlockCallerThreadID) || (NOT_BLOCKED != m_BlockState));
-
- // If this ASSERT fires, the streaming thread is using the output pin and the
- // output pin is blocked.
- ASSERT(((0 != m_dwNumOutstandingOutputPinUsers) && (BLOCKED != m_BlockState)) ||
- ((0 == m_dwNumOutstandingOutputPinUsers) && (NOT_BLOCKED != m_BlockState)) ||
- ((0 == m_dwNumOutstandingOutputPinUsers) && (NOT_BLOCKED == m_BlockState)) );
-}
-#endif // DEBUG
-
-HRESULT CDynamicOutputPin::WaitEvent(HANDLE hEvent)
-{
- const DWORD EVENT_SIGNALED = WAIT_OBJECT_0;
-
- DWORD dwReturnValue = ::WaitForSingleObject(hEvent, INFINITE);
-
- switch( dwReturnValue ) {
- case EVENT_SIGNALED:
- return S_OK;
-
- case WAIT_FAILED:
- return AmGetLastErrorToHResult();
-
- default:
- DbgBreak( "An Unexpected case occured in CDynamicOutputPin::WaitEvent()." );
- return E_UNEXPECTED;
- }
-}
-
-//=====================================================================
-//=====================================================================
-// Implements CBaseAllocator
-//=====================================================================
-//=====================================================================
-
-
-/* Constructor overrides the default settings for the free list to request
- that it be alertable (ie the list can be cast to a handle which can be
- passed to WaitForSingleObject). Both of the allocator lists also ask for
- object locking, the all list matches the object default settings but I
- have included them here just so it is obvious what kind of list it is */
-
-CBaseAllocator::CBaseAllocator(__in_opt LPCTSTR pName,
- __inout_opt LPUNKNOWN pUnk,
- __inout HRESULT *phr,
- BOOL bEvent,
- BOOL fEnableReleaseCallback
- ) :
- CUnknown(pName, pUnk),
- m_lAllocated(0),
- m_bChanged(FALSE),
- m_bCommitted(FALSE),
- m_bDecommitInProgress(FALSE),
- m_lSize(0),
- m_lCount(0),
- m_lAlignment(0),
- m_lPrefix(0),
- m_hSem(NULL),
- m_lWaiting(0),
- m_fEnableReleaseCallback(fEnableReleaseCallback),
- m_pNotify(NULL)
-{
-#ifdef DXMPERF
- PERFLOG_CTOR( pName ? pName : L"CBaseAllocator", (IMemAllocator *) this );
-#endif // DXMPERF
-
- if (bEvent) {
- m_hSem = CreateSemaphore(NULL, 0, 0x7FFFFFFF, NULL);
- if (m_hSem == NULL) {
- *phr = E_OUTOFMEMORY;
- return;
- }
- }
-}
-
-#ifdef UNICODE
-CBaseAllocator::CBaseAllocator(__in_opt LPCSTR pName,
- __inout_opt LPUNKNOWN pUnk,
- __inout HRESULT *phr,
- BOOL bEvent,
- BOOL fEnableReleaseCallback) :
- CUnknown(pName, pUnk),
- m_lAllocated(0),
- m_bChanged(FALSE),
- m_bCommitted(FALSE),
- m_bDecommitInProgress(FALSE),
- m_lSize(0),
- m_lCount(0),
- m_lAlignment(0),
- m_lPrefix(0),
- m_hSem(NULL),
- m_lWaiting(0),
- m_fEnableReleaseCallback(fEnableReleaseCallback),
- m_pNotify(NULL)
-{
-#ifdef DXMPERF
- PERFLOG_CTOR( L"CBaseAllocator", (IMemAllocator *) this );
-#endif // DXMPERF
-
- if (bEvent) {
- m_hSem = CreateSemaphore(NULL, 0, 0x7FFFFFFF, NULL);
- if (m_hSem == NULL) {
- *phr = E_OUTOFMEMORY;
- return;
- }
- }
-}
-#endif
-
-/* Destructor */
-
-CBaseAllocator::~CBaseAllocator()
-{
- // we can't call Decommit here since that would mean a call to a
- // pure virtual in destructor.
- // We must assume that the derived class has gone into decommit state in
- // its destructor.
-#ifdef DXMPERF
- PERFLOG_DTOR( L"CBaseAllocator", (IMemAllocator *) this );
-#endif // DXMPERF
-
- ASSERT(!m_bCommitted);
- if (m_hSem != NULL) {
- EXECUTE_ASSERT(CloseHandle(m_hSem));
- }
- if (m_pNotify) {
- m_pNotify->Release();
- }
-}
-
-
-/* Override this to publicise our interfaces */
-
-STDMETHODIMP
-CBaseAllocator::NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv)
-{
- /* Do we know about this interface */
-
- if (riid == IID_IMemAllocator ||
- riid == IID_IMemAllocatorCallbackTemp && m_fEnableReleaseCallback) {
- return GetInterface((IMemAllocatorCallbackTemp *) this, ppv);
- } else {
- return CUnknown::NonDelegatingQueryInterface(riid, ppv);
- }
-}
-
-
-/* This sets the size and count of the required samples. The memory isn't
- actually allocated until Commit() is called, if memory has already been
- allocated then assuming no samples are outstanding the user may call us
- to change the buffering, the memory will be released in Commit() */
-
-STDMETHODIMP
-CBaseAllocator::SetProperties(
- __in ALLOCATOR_PROPERTIES* pRequest,
- __out ALLOCATOR_PROPERTIES* pActual)
-{
- CheckPointer(pRequest, E_POINTER);
- CheckPointer(pActual, E_POINTER);
- ValidateReadWritePtr(pActual, sizeof(ALLOCATOR_PROPERTIES));
- CAutoLock cObjectLock(this);
-
- ZeroMemory(pActual, sizeof(ALLOCATOR_PROPERTIES));
-
- ASSERT(pRequest->cbBuffer > 0);
-
- /* Check the alignment requested */
- if (pRequest->cbAlign != 1) {
- DbgLog((LOG_ERROR, 2, TEXT("Alignment requested was 0x%x, not 1"),
- pRequest->cbAlign));
- return VFW_E_BADALIGN;
- }
-
- /* Can't do this if already committed, there is an argument that says we
- should not reject the SetProperties call if there are buffers still
- active. However this is called by the source filter, which is the same
- person who is holding the samples. Therefore it is not unreasonable
- for them to free all their samples before changing the requirements */
-
- if (m_bCommitted) {
- return VFW_E_ALREADY_COMMITTED;
- }
-
- /* Must be no outstanding buffers */
-
- if (m_lAllocated != m_lFree.GetCount()) {
- return VFW_E_BUFFERS_OUTSTANDING;
- }
-
- /* There isn't any real need to check the parameters as they
- will just be rejected when the user finally calls Commit */
-
- pActual->cbBuffer = m_lSize = pRequest->cbBuffer;
- pActual->cBuffers = m_lCount = pRequest->cBuffers;
- pActual->cbAlign = m_lAlignment = pRequest->cbAlign;
- pActual->cbPrefix = m_lPrefix = pRequest->cbPrefix;
-
- m_bChanged = TRUE;
- return NOERROR;
-}
-
-STDMETHODIMP
-CBaseAllocator::GetProperties(
- __out ALLOCATOR_PROPERTIES * pActual)
-{
- CheckPointer(pActual,E_POINTER);
- ValidateReadWritePtr(pActual,sizeof(ALLOCATOR_PROPERTIES));
-
- CAutoLock cObjectLock(this);
- pActual->cbBuffer = m_lSize;
- pActual->cBuffers = m_lCount;
- pActual->cbAlign = m_lAlignment;
- pActual->cbPrefix = m_lPrefix;
- return NOERROR;
-}
-
-// get container for a sample. Blocking, synchronous call to get the
-// next free buffer (as represented by an IMediaSample interface).
-// on return, the time etc properties will be invalid, but the buffer
-// pointer and size will be correct.
-
-HRESULT CBaseAllocator::GetBuffer(__deref_out IMediaSample **ppBuffer,
- __in_opt REFERENCE_TIME *pStartTime,
- __in_opt REFERENCE_TIME *pEndTime,
- DWORD dwFlags
- )
-{
- UNREFERENCED_PARAMETER(pStartTime);
- UNREFERENCED_PARAMETER(pEndTime);
- UNREFERENCED_PARAMETER(dwFlags);
- CMediaSample *pSample;
-
- *ppBuffer = NULL;
- for (;;)
- {
- { // scope for lock
- CAutoLock cObjectLock(this);
-
- /* Check we are committed */
- if (!m_bCommitted) {
- return VFW_E_NOT_COMMITTED;
- }
- pSample = (CMediaSample *) m_lFree.RemoveHead();
- if (pSample == NULL) {
- SetWaiting();
- }
- }
-
- /* If we didn't get a sample then wait for the list to signal */
-
- if (pSample) {
- break;
- }
- if (dwFlags & AM_GBF_NOWAIT) {
- return VFW_E_TIMEOUT;
- }
- ASSERT(m_hSem != NULL);
- WaitForSingleObject(m_hSem, INFINITE);
- }
-
- /* Addref the buffer up to one. On release
- back to zero instead of being deleted, it will requeue itself by
- calling the ReleaseBuffer member function. NOTE the owner of a
- media sample must always be derived from CBaseAllocator */
-
-
- ASSERT(pSample->m_cRef == 0);
- pSample->m_cRef = 1;
- *ppBuffer = pSample;
-
-#ifdef DXMPERF
- PERFLOG_GETBUFFER( (IMemAllocator *) this, pSample );
-#endif // DXMPERF
-
- return NOERROR;
-}
-
-
-/* Final release of a CMediaSample will call this */
-
-STDMETHODIMP
-CBaseAllocator::ReleaseBuffer(IMediaSample * pSample)
-{
- CheckPointer(pSample,E_POINTER);
- ValidateReadPtr(pSample,sizeof(IMediaSample));
-
-#ifdef DXMPERF
- PERFLOG_RELBUFFER( (IMemAllocator *) this, pSample );
-#endif // DXMPERF
-
-
- BOOL bRelease = FALSE;
- {
- CAutoLock cal(this);
-
- /* Put back on the free list */
-
- m_lFree.Add((CMediaSample *)pSample);
- if (m_lWaiting != 0) {
- NotifySample();
- }
-
- // if there is a pending Decommit, then we need to complete it by
- // calling Free() when the last buffer is placed on the free list
-
- LONG l1 = m_lFree.GetCount();
- if (m_bDecommitInProgress && (l1 == m_lAllocated)) {
- Free();
- m_bDecommitInProgress = FALSE;
- bRelease = TRUE;
- }
- }
-
- if (m_pNotify) {
-
- ASSERT(m_fEnableReleaseCallback);
-
- //
- // Note that this is not synchronized with setting up a notification
- // method.
- //
- m_pNotify->NotifyRelease();
- }
-
- /* For each buffer there is one AddRef, made in GetBuffer and released
- here. This may cause the allocator and all samples to be deleted */
-
- if (bRelease) {
- Release();
- }
- return NOERROR;
-}
-
-STDMETHODIMP
-CBaseAllocator::SetNotify(
- IMemAllocatorNotifyCallbackTemp* pNotify
- )
-{
- ASSERT(m_fEnableReleaseCallback);
- CAutoLock lck(this);
- if (pNotify) {
- pNotify->AddRef();
- }
- if (m_pNotify) {
- m_pNotify->Release();
- }
- m_pNotify = pNotify;
- return S_OK;
-}
-
-STDMETHODIMP
-CBaseAllocator::GetFreeCount(
- __out LONG* plBuffersFree
- )
-{
- ASSERT(m_fEnableReleaseCallback);
- CAutoLock cObjectLock(this);
- *plBuffersFree = m_lCount - m_lAllocated + m_lFree.GetCount();
- return NOERROR;
-}
-
-void
-CBaseAllocator::NotifySample()
-{
- if (m_lWaiting != 0) {
- ASSERT(m_hSem != NULL);
- ReleaseSemaphore(m_hSem, m_lWaiting, 0);
- m_lWaiting = 0;
- }
-}
-
-STDMETHODIMP
-CBaseAllocator::Commit()
-{
- /* Check we are not decommitted */
- CAutoLock cObjectLock(this);
-
- // cannot need to alloc or re-alloc if we are committed
- if (m_bCommitted) {
- return NOERROR;
- }
-
- /* Allow GetBuffer calls */
-
- m_bCommitted = TRUE;
-
- // is there a pending decommit ? if so, just cancel it
- if (m_bDecommitInProgress) {
- m_bDecommitInProgress = FALSE;
-
- // don't call Alloc at this point. He cannot allow SetProperties
- // between Decommit and the last free, so the buffer size cannot have
- // changed. And because some of the buffers are not free yet, he
- // cannot re-alloc anyway.
- return NOERROR;
- }
-
- DbgLog((LOG_MEMORY, 1, TEXT("Allocating: %ldx%ld"), m_lCount, m_lSize));
-
- // actually need to allocate the samples
- HRESULT hr = Alloc();
- if (FAILED(hr)) {
- m_bCommitted = FALSE;
- return hr;
- }
- AddRef();
- return NOERROR;
-}
-
-
-STDMETHODIMP
-CBaseAllocator::Decommit()
-{
- BOOL bRelease = FALSE;
- {
- /* Check we are not already decommitted */
- CAutoLock cObjectLock(this);
- if (m_bCommitted == FALSE) {
- if (m_bDecommitInProgress == FALSE) {
- return NOERROR;
- }
- }
-
- /* No more GetBuffer calls will succeed */
- m_bCommitted = FALSE;
-
- // are any buffers outstanding?
- if (m_lFree.GetCount() < m_lAllocated) {
- // please complete the decommit when last buffer is freed
- m_bDecommitInProgress = TRUE;
- } else {
- m_bDecommitInProgress = FALSE;
-
- // need to complete the decommit here as there are no
- // outstanding buffers
-
- Free();
- bRelease = TRUE;
- }
-
- // Tell anyone waiting that they can go now so we can
- // reject their call
-#pragma warning(push)
-#ifndef _PREFAST_
-#pragma warning(disable:4068)
-#endif
-#pragma prefast(suppress:__WARNING_DEREF_NULL_PTR, "Suppress warning related to Free() invalidating 'this' which is no applicable to CBaseAllocator::Free()")
- NotifySample();
-
-#pragma warning(pop)
- }
-
- if (bRelease) {
- Release();
- }
- return NOERROR;
-}
-
-
-/* Base definition of allocation which checks we are ok to go ahead and do
- the full allocation. We return S_FALSE if the requirements are the same */
-
-HRESULT
-CBaseAllocator::Alloc(void)
-{
- /* Error if he hasn't set the size yet */
- if (m_lCount <= 0 || m_lSize <= 0 || m_lAlignment <= 0) {
- return VFW_E_SIZENOTSET;
- }
-
- /* should never get here while buffers outstanding */
- ASSERT(m_lFree.GetCount() == m_lAllocated);
-
- /* If the requirements haven't changed then don't reallocate */
- if (m_bChanged == FALSE) {
- return S_FALSE;
- }
-
- return NOERROR;
-}
-
-/* Implement CBaseAllocator::CSampleList::Remove(pSample)
- Removes pSample from the list
-*/
-void
-CBaseAllocator::CSampleList::Remove(__inout CMediaSample * pSample)
-{
- CMediaSample **pSearch;
- for (pSearch = &m_List;
- *pSearch != NULL;
- pSearch = &(CBaseAllocator::NextSample(*pSearch))) {
- if (*pSearch == pSample) {
- *pSearch = CBaseAllocator::NextSample(pSample);
- CBaseAllocator::NextSample(pSample) = NULL;
- m_nOnList--;
- return;
- }
- }
- DbgBreak("Couldn't find sample in list");
-}
-
-//=====================================================================
-//=====================================================================
-// Implements CMemAllocator
-//=====================================================================
-//=====================================================================
-
-
-/* This goes in the factory template table to create new instances */
-CUnknown *CMemAllocator::CreateInstance(__inout_opt LPUNKNOWN pUnk, __inout HRESULT *phr)
-{
- CUnknown *pUnkRet = new CMemAllocator(NAME("CMemAllocator"), pUnk, phr);
- return pUnkRet;
-}
-
-CMemAllocator::CMemAllocator(
- __in_opt LPCTSTR pName,
- __inout_opt LPUNKNOWN pUnk,
- __inout HRESULT *phr)
- : CBaseAllocator(pName, pUnk, phr, TRUE, TRUE),
- m_pBuffer(NULL)
-{
-}
-
-#ifdef UNICODE
-CMemAllocator::CMemAllocator(
- __in_opt LPCSTR pName,
- __inout_opt LPUNKNOWN pUnk,
- __inout HRESULT *phr)
- : CBaseAllocator(pName, pUnk, phr, TRUE, TRUE),
- m_pBuffer(NULL)
-{
-}
-#endif
-
-/* This sets the size and count of the required samples. The memory isn't
- actually allocated until Commit() is called, if memory has already been
- allocated then assuming no samples are outstanding the user may call us
- to change the buffering, the memory will be released in Commit() */
-STDMETHODIMP
-CMemAllocator::SetProperties(
- __in ALLOCATOR_PROPERTIES* pRequest,
- __out ALLOCATOR_PROPERTIES* pActual)
-{
- CheckPointer(pActual,E_POINTER);
- ValidateReadWritePtr(pActual,sizeof(ALLOCATOR_PROPERTIES));
- CAutoLock cObjectLock(this);
-
- ZeroMemory(pActual, sizeof(ALLOCATOR_PROPERTIES));
-
- ASSERT(pRequest->cbBuffer > 0);
-
- SYSTEM_INFO SysInfo;
- GetSystemInfo(&SysInfo);
-
- /* Check the alignment request is a power of 2 */
- if ((-pRequest->cbAlign & pRequest->cbAlign) != pRequest->cbAlign) {
- DbgLog((LOG_ERROR, 1, TEXT("Alignment requested 0x%x not a power of 2!"),
- pRequest->cbAlign));
- }
- /* Check the alignment requested */
- if (pRequest->cbAlign == 0 ||
- (SysInfo.dwAllocationGranularity & (pRequest->cbAlign - 1)) != 0) {
- DbgLog((LOG_ERROR, 1, TEXT("Invalid alignment 0x%x requested - granularity = 0x%x"),
- pRequest->cbAlign, SysInfo.dwAllocationGranularity));
- return VFW_E_BADALIGN;
- }
-
- /* Can't do this if already committed, there is an argument that says we
- should not reject the SetProperties call if there are buffers still
- active. However this is called by the source filter, which is the same
- person who is holding the samples. Therefore it is not unreasonable
- for them to free all their samples before changing the requirements */
-
- if (m_bCommitted == TRUE) {
- return VFW_E_ALREADY_COMMITTED;
- }
-
- /* Must be no outstanding buffers */
-
- if (m_lFree.GetCount() < m_lAllocated) {
- return VFW_E_BUFFERS_OUTSTANDING;
- }
-
- /* There isn't any real need to check the parameters as they
- will just be rejected when the user finally calls Commit */
-
- // round length up to alignment - remember that prefix is included in
- // the alignment
- LONG lSize = pRequest->cbBuffer + pRequest->cbPrefix;
- LONG lRemainder = lSize % pRequest->cbAlign;
- if (lRemainder != 0) {
- lSize = lSize - lRemainder + pRequest->cbAlign;
- }
- pActual->cbBuffer = m_lSize = (lSize - pRequest->cbPrefix);
-
- pActual->cBuffers = m_lCount = pRequest->cBuffers;
- pActual->cbAlign = m_lAlignment = pRequest->cbAlign;
- pActual->cbPrefix = m_lPrefix = pRequest->cbPrefix;
-
- m_bChanged = TRUE;
- return NOERROR;
-}
-
-// override this to allocate our resources when Commit is called.
-//
-// note that our resources may be already allocated when this is called,
-// since we don't free them on Decommit. We will only be called when in
-// decommit state with all buffers free.
-//
-// object locked by caller
-HRESULT
-CMemAllocator::Alloc(void)
-{
- CAutoLock lck(this);
-
- /* Check he has called SetProperties */
- HRESULT hr = CBaseAllocator::Alloc();
- if (FAILED(hr)) {
- return hr;
- }
-
- /* If the requirements haven't changed then don't reallocate */
- if (hr == S_FALSE) {
- ASSERT(m_pBuffer);
- return NOERROR;
- }
- ASSERT(hr == S_OK); // we use this fact in the loop below
-
- /* Free the old resources */
- if (m_pBuffer) {
- ReallyFree();
- }
-
- /* Make sure we've got reasonable values */
- if ( m_lSize < 0 || m_lPrefix < 0 || m_lCount < 0 ) {
- return E_OUTOFMEMORY;
- }
-
- /* Compute the aligned size */
- LONG lAlignedSize = m_lSize + m_lPrefix;
-
- /* Check overflow */
- if (lAlignedSize < m_lSize) {
- return E_OUTOFMEMORY;
- }
-
- if (m_lAlignment > 1) {
- LONG lRemainder = lAlignedSize % m_lAlignment;
- if (lRemainder != 0) {
- LONG lNewSize = lAlignedSize + m_lAlignment - lRemainder;
- if (lNewSize < lAlignedSize) {
- return E_OUTOFMEMORY;
- }
- lAlignedSize = lNewSize;
- }
- }
-
- /* Create the contiguous memory block for the samples
- making sure it's properly aligned (64K should be enough!)
- */
- ASSERT(lAlignedSize % m_lAlignment == 0);
-
- LONGLONG lToAllocate = m_lCount * (LONGLONG)lAlignedSize;
-
- /* Check overflow */
- if (lToAllocate > MAXLONG) {
- return E_OUTOFMEMORY;
- }
-
- m_pBuffer = (PBYTE)VirtualAlloc(NULL,
- (LONG)lToAllocate,
- MEM_COMMIT,
- PAGE_READWRITE);
-
- if (m_pBuffer == NULL) {
- return E_OUTOFMEMORY;
- }
-
- LPBYTE pNext = m_pBuffer;
- CMediaSample *pSample;
-
- ASSERT(m_lAllocated == 0);
-
- // Create the new samples - we have allocated m_lSize bytes for each sample
- // plus m_lPrefix bytes per sample as a prefix. We set the pointer to
- // the memory after the prefix - so that GetPointer() will return a pointer
- // to m_lSize bytes.
- for (; m_lAllocated < m_lCount; m_lAllocated++, pNext += lAlignedSize) {
-
-
- pSample = new CMediaSample(
- NAME("Default memory media sample"),
- this,
- &hr,
- pNext + m_lPrefix, // GetPointer() value
- m_lSize); // not including prefix
-
- ASSERT(SUCCEEDED(hr));
- if (pSample == NULL) {
- return E_OUTOFMEMORY;
- }
-
- // This CANNOT fail
- m_lFree.Add(pSample);
- }
-
- m_bChanged = FALSE;
- return NOERROR;
-}
-
-
-// override this to free up any resources we have allocated.
-// called from the base class on Decommit when all buffers have been
-// returned to the free list.
-//
-// caller has already locked the object.
-
-// in our case, we keep the memory until we are deleted, so
-// we do nothing here. The memory is deleted in the destructor by
-// calling ReallyFree()
-void
-CMemAllocator::Free(void)
-{
- return;
-}
-
-
-// called from the destructor (and from Alloc if changing size/count) to
-// actually free up the memory
-void
-CMemAllocator::ReallyFree(void)
-{
- /* Should never be deleting this unless all buffers are freed */
-
- ASSERT(m_lAllocated == m_lFree.GetCount());
-
- /* Free up all the CMediaSamples */
-
- CMediaSample *pSample;
- for (;;) {
- pSample = m_lFree.RemoveHead();
- if (pSample != NULL) {
- delete pSample;
- } else {
- break;
- }
- }
-
- m_lAllocated = 0;
-
- // free the block of buffer memory
- if (m_pBuffer) {
- EXECUTE_ASSERT(VirtualFree(m_pBuffer, 0, MEM_RELEASE));
- m_pBuffer = NULL;
- }
-}
-
-
-/* Destructor frees our memory resources */
-
-CMemAllocator::~CMemAllocator()
-{
- Decommit();
- ReallyFree();
-}
-
-// ------------------------------------------------------------------------
-// filter registration through IFilterMapper. used if IFilterMapper is
-// not found (Quartz 1.0 install)
-
-STDAPI
-AMovieSetupRegisterFilter( const AMOVIESETUP_FILTER * const psetupdata
- , IFilterMapper * pIFM
- , BOOL bRegister )
-{
- DbgLog((LOG_TRACE, 3, TEXT("= AMovieSetupRegisterFilter")));
-
- // check we've got data
- //
- if( NULL == psetupdata ) return S_FALSE;
-
-
- // unregister filter
- // (as pins are subkeys of filter's CLSID key
- // they do not need to be removed separately).
- //
- DbgLog((LOG_TRACE, 3, TEXT("= = unregister filter")));
- HRESULT hr = pIFM->UnregisterFilter( *(psetupdata->clsID) );
-
-
- if( bRegister )
- {
- // register filter
- //
- DbgLog((LOG_TRACE, 3, TEXT("= = register filter")));
- hr = pIFM->RegisterFilter( *(psetupdata->clsID)
- , psetupdata->strName
- , psetupdata->dwMerit );
- if( SUCCEEDED(hr) )
- {
- // all its pins
- //
- DbgLog((LOG_TRACE, 3, TEXT("= = register filter pins")));
- for( UINT m1=0; m1 < psetupdata->nPins; m1++ )
- {
- hr = pIFM->RegisterPin( *(psetupdata->clsID)
- , psetupdata->lpPin[m1].strName
- , psetupdata->lpPin[m1].bRendered
- , psetupdata->lpPin[m1].bOutput
- , psetupdata->lpPin[m1].bZero
- , psetupdata->lpPin[m1].bMany
- , *(psetupdata->lpPin[m1].clsConnectsToFilter)
- , psetupdata->lpPin[m1].strConnectsToPin );
-
- if( SUCCEEDED(hr) )
- {
- // and each pin's media types
- //
- DbgLog((LOG_TRACE, 3, TEXT("= = register filter pin types")));
- for( UINT m2=0; m2 < psetupdata->lpPin[m1].nMediaTypes; m2++ )
- {
- hr = pIFM->RegisterPinType( *(psetupdata->clsID)
- , psetupdata->lpPin[m1].strName
- , *(psetupdata->lpPin[m1].lpMediaType[m2].clsMajorType)
- , *(psetupdata->lpPin[m1].lpMediaType[m2].clsMinorType) );
- if( FAILED(hr) ) break;
- }
- if( FAILED(hr) ) break;
- }
- if( FAILED(hr) ) break;
- }
- }
- }
-
- // handle one acceptable "error" - that
- // of filter not being registered!
- // (couldn't find a suitable #define'd
- // name for the error!)
- //
- if( 0x80070002 == hr)
- return NOERROR;
- else
- return hr;
-}
-
-// Remove warnings about unreferenced inline functions
-#pragma warning(disable:4514)
-
diff --git a/dll/src/baseclasses/amfilter.h b/dll/src/baseclasses/amfilter.h
deleted file mode 100644
index 14f17cd..0000000
--- a/dll/src/baseclasses/amfilter.h
+++ /dev/null
@@ -1,1587 +0,0 @@
-//------------------------------------------------------------------------------
-// File: AMFilter.h
-//
-// Desc: DirectShow base classes - efines class hierarchy for streams
-// architecture.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-#ifndef __FILTER__
-#define __FILTER__
-
-/* The following classes are declared in this header: */
-
-class CBaseMediaFilter; // IMediaFilter support
-class CBaseFilter; // IBaseFilter,IMediaFilter support
-class CBasePin; // Abstract base class for IPin interface
-class CEnumPins; // Enumerate input and output pins
-class CEnumMediaTypes; // Enumerate the pin's preferred formats
-class CBaseOutputPin; // Adds data provider member functions
-class CBaseInputPin; // Implements IMemInputPin interface
-class CMediaSample; // Basic transport unit for IMemInputPin
-class CBaseAllocator; // General list guff for most allocators
-class CMemAllocator; // Implements memory buffer allocation
-
-
-//=====================================================================
-//=====================================================================
-//
-// QueryFilterInfo and QueryPinInfo AddRef the interface pointers
-// they return. You can use the macro below to release the interface.
-//
-//=====================================================================
-//=====================================================================
-
-#define QueryFilterInfoReleaseGraph(fi) if ((fi).pGraph) (fi).pGraph->Release();
-
-#define QueryPinInfoReleaseFilter(pi) if ((pi).pFilter) (pi).pFilter->Release();
-
-//=====================================================================
-//=====================================================================
-// Defines CBaseMediaFilter
-//
-// Abstract base class implementing IMediaFilter.
-//
-// Typically you will derive your filter from CBaseFilter rather than
-// this, unless you are implementing an object such as a plug-in
-// distributor that needs to support IMediaFilter but not IBaseFilter.
-//
-// Note that IMediaFilter is derived from IPersist to allow query of
-// class id.
-//=====================================================================
-//=====================================================================
-
-class AM_NOVTABLE CBaseMediaFilter : public CUnknown,
- public IMediaFilter
-{
-
-protected:
-
- FILTER_STATE m_State; // current state: running, paused
- IReferenceClock *m_pClock; // this filter's reference clock
- // note: all filters in a filter graph use the same clock
-
- // offset from stream time to reference time
- CRefTime m_tStart;
-
- CLSID m_clsid; // This filters clsid
- // used for serialization
- CCritSec *m_pLock; // Object we use for locking
-
-public:
-
- CBaseMediaFilter(
- __in_opt LPCTSTR pName,
- __inout_opt LPUNKNOWN pUnk,
- __in CCritSec *pLock,
- REFCLSID clsid);
-
- virtual ~CBaseMediaFilter();
-
- DECLARE_IUNKNOWN
-
- // override this to say what interfaces we support where
- STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void ** ppv);
-
- //
- // --- IPersist method ---
- //
-
- STDMETHODIMP GetClassID(__out CLSID *pClsID);
-
- // --- IMediaFilter methods ---
-
- STDMETHODIMP GetState(DWORD dwMSecs, __out FILTER_STATE *State);
-
- STDMETHODIMP SetSyncSource(__inout_opt IReferenceClock *pClock);
-
- STDMETHODIMP GetSyncSource(__deref_out_opt IReferenceClock **pClock);
-
- // default implementation of Stop and Pause just record the
- // state. Override to activate or de-activate your filter.
- // Note that Run when called from Stopped state will call Pause
- // to ensure activation, so if you are a source or transform
- // you will probably not need to override Run.
- STDMETHODIMP Stop();
- STDMETHODIMP Pause();
-
-
- // the start parameter is the difference to be added to the
- // sample's stream time to get the reference time for
- // its presentation
- STDMETHODIMP Run(REFERENCE_TIME tStart);
-
- // --- helper methods ---
-
- // return the current stream time - ie find out what
- // stream time should be appearing now
- virtual HRESULT StreamTime(CRefTime& rtStream);
-
- // Is the filter currently active? (running or paused)
- BOOL IsActive() {
- CAutoLock cObjectLock(m_pLock);
- return ((m_State == State_Paused) || (m_State == State_Running));
- };
-};
-
-//=====================================================================
-//=====================================================================
-// Defines CBaseFilter
-//
-// An abstract class providing basic IBaseFilter support for pin
-// enumeration and filter information reading.
-//
-// We cannot derive from CBaseMediaFilter since methods in IMediaFilter
-// are also in IBaseFilter and would be ambiguous. Since much of the code
-// assumes that they derive from a class that has m_State and other state
-// directly available, we duplicate code from CBaseMediaFilter rather than
-// having a member variable.
-//
-// Derive your filter from this, or from a derived object such as
-// CTransformFilter.
-//=====================================================================
-//=====================================================================
-
-
-class AM_NOVTABLE CBaseFilter : public CUnknown, // Handles an IUnknown
- public IBaseFilter, // The Filter Interface
- public IAMovieSetup // For un/registration
-{
-
-friend class CBasePin;
-
-protected:
- FILTER_STATE m_State; // current state: running, paused
- IReferenceClock *m_pClock; // this graph's ref clock
- CRefTime m_tStart; // offset from stream time to reference time
- CLSID m_clsid; // This filters clsid
- // used for serialization
- CCritSec *m_pLock; // Object we use for locking
-
- WCHAR *m_pName; // Full filter name
- IFilterGraph *m_pGraph; // Graph we belong to
- IMediaEventSink *m_pSink; // Called with notify events
- LONG m_PinVersion; // Current pin version
-
-public:
-
- CBaseFilter(
- __in_opt LPCTSTR pName, // Object description
- __inout_opt LPUNKNOWN pUnk, // IUnknown of delegating object
- __in CCritSec *pLock, // Object who maintains lock
- REFCLSID clsid); // The clsid to be used to serialize this filter
-
- CBaseFilter(
- __in_opt LPCTSTR pName, // Object description
- __in_opt LPUNKNOWN pUnk, // IUnknown of delegating object
- __in CCritSec *pLock, // Object who maintains lock
- REFCLSID clsid, // The clsid to be used to serialize this filter
- __inout HRESULT *phr); // General OLE return code
-#ifdef UNICODE
- CBaseFilter(
- __in_opt LPCSTR pName, // Object description
- __in_opt LPUNKNOWN pUnk, // IUnknown of delegating object
- __in CCritSec *pLock, // Object who maintains lock
- REFCLSID clsid); // The clsid to be used to serialize this filter
-
- CBaseFilter(
- __in_opt LPCSTR pName, // Object description
- __in_opt LPUNKNOWN pUnk, // IUnknown of delegating object
- __in CCritSec *pLock, // Object who maintains lock
- REFCLSID clsid, // The clsid to be used to serialize this filter
- __inout HRESULT *phr); // General OLE return code
-#endif
- ~CBaseFilter();
-
- DECLARE_IUNKNOWN
-
- // override this to say what interfaces we support where
- STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void ** ppv);
-#ifdef DEBUG
- STDMETHODIMP_(ULONG) NonDelegatingRelease();
-#endif
-
- //
- // --- IPersist method ---
- //
-
- STDMETHODIMP GetClassID(__out CLSID *pClsID);
-
- // --- IMediaFilter methods ---
-
- STDMETHODIMP GetState(DWORD dwMSecs, __out FILTER_STATE *State);
-
- STDMETHODIMP SetSyncSource(__in_opt IReferenceClock *pClock);
-
- STDMETHODIMP GetSyncSource(__deref_out_opt IReferenceClock **pClock);
-
-
- // override Stop and Pause so we can activate the pins.
- // Note that Run will call Pause first if activation needed.
- // Override these if you want to activate your filter rather than
- // your pins.
- STDMETHODIMP Stop();
- STDMETHODIMP Pause();
-
- // the start parameter is the difference to be added to the
- // sample's stream time to get the reference time for
- // its presentation
- STDMETHODIMP Run(REFERENCE_TIME tStart);
-
- // --- helper methods ---
-
- // return the current stream time - ie find out what
- // stream time should be appearing now
- virtual HRESULT StreamTime(CRefTime& rtStream);
-
- // Is the filter currently active?
- BOOL IsActive() {
- CAutoLock cObjectLock(m_pLock);
- return ((m_State == State_Paused) || (m_State == State_Running));
- };
-
- // Is this filter stopped (without locking)
- BOOL IsStopped() {
- return (m_State == State_Stopped);
- };
-
- //
- // --- IBaseFilter methods ---
- //
-
- // pin enumerator
- STDMETHODIMP EnumPins(
- __deref_out IEnumPins ** ppEnum);
-
-
- // default behaviour of FindPin assumes pin ids are their names
- STDMETHODIMP FindPin(
- LPCWSTR Id,
- __deref_out IPin ** ppPin
- );
-
- STDMETHODIMP QueryFilterInfo(
- __out FILTER_INFO * pInfo);
-
- STDMETHODIMP JoinFilterGraph(
- __inout_opt IFilterGraph * pGraph,
- __in_opt LPCWSTR pName);
-
- // return a Vendor information string. Optional - may return E_NOTIMPL.
- // memory returned should be freed using CoTaskMemFree
- // default implementation returns E_NOTIMPL
- STDMETHODIMP QueryVendorInfo(
- __deref_out LPWSTR* pVendorInfo
- );
-
- // --- helper methods ---
-
- // send an event notification to the filter graph if we know about it.
- // returns S_OK if delivered, S_FALSE if the filter graph does not sink
- // events, or an error otherwise.
- HRESULT NotifyEvent(
- long EventCode,
- LONG_PTR EventParam1,
- LONG_PTR EventParam2);
-
- // return the filter graph we belong to
- __out_opt IFilterGraph *GetFilterGraph() {
- return m_pGraph;
- }
-
- // Request reconnect
- // pPin is the pin to reconnect
- // pmt is the type to reconnect with - can be NULL
- // Calls ReconnectEx on the filter graph
- HRESULT ReconnectPin(IPin *pPin, __in_opt AM_MEDIA_TYPE const *pmt);
-
- // find out the current pin version (used by enumerators)
- virtual LONG GetPinVersion();
- void IncrementPinVersion();
-
- // you need to supply these to access the pins from the enumerator
- // and for default Stop and Pause/Run activation.
- virtual int GetPinCount() PURE;
- virtual CBasePin *GetPin(int n) PURE;
-
- // --- IAMovieSetup methods ---
-
- STDMETHODIMP Register(); // ask filter to register itself
- STDMETHODIMP Unregister(); // and unregister itself
-
- // --- setup helper methods ---
- // (override to return filters setup data)
-
- virtual __out_opt LPAMOVIESETUP_FILTER GetSetupData(){ return NULL; }
-
-};
-
-
-//=====================================================================
-//=====================================================================
-// Defines CBasePin
-//
-// Abstract class that supports the basics of IPin
-//=====================================================================
-//=====================================================================
-
-class AM_NOVTABLE CBasePin : public CUnknown, public IPin, public IQualityControl
-{
-
-protected:
-
- WCHAR * m_pName; // This pin's name
- IPin *m_Connected; // Pin we have connected to
- PIN_DIRECTION m_dir; // Direction of this pin
- CCritSec *m_pLock; // Object we use for locking
- bool m_bRunTimeError; // Run time error generated
- bool m_bCanReconnectWhenActive; // OK to reconnect when active
- bool m_bTryMyTypesFirst; // When connecting enumerate
- // this pin's types first
- CBaseFilter *m_pFilter; // Filter we were created by
- IQualityControl *m_pQSink; // Target for Quality messages
- LONG m_TypeVersion; // Holds current type version
- CMediaType m_mt; // Media type of connection
-
- CRefTime m_tStart; // time from NewSegment call
- CRefTime m_tStop; // time from NewSegment
- double m_dRate; // rate from NewSegment
-
-#ifdef DEBUG
- LONG m_cRef; // Ref count tracing
-#endif
-
- // displays pin connection information
-
-#ifdef DEBUG
- void DisplayPinInfo(IPin *pReceivePin);
- void DisplayTypeInfo(IPin *pPin, const CMediaType *pmt);
-#else
- void DisplayPinInfo(IPin *pReceivePin) {};
- void DisplayTypeInfo(IPin *pPin, const CMediaType *pmt) {};
-#endif
-
- // used to agree a media type for a pin connection
-
- // given a specific media type, attempt a connection (includes
- // checking that the type is acceptable to this pin)
- HRESULT
- AttemptConnection(
- IPin* pReceivePin, // connect to this pin
- const CMediaType* pmt // using this type
- );
-
- // try all the media types in this enumerator - for each that
- // we accept, try to connect using ReceiveConnection.
- HRESULT TryMediaTypes(
- IPin *pReceivePin, // connect to this pin
- __in_opt const CMediaType *pmt, // proposed type from Connect
- IEnumMediaTypes *pEnum); // try this enumerator
-
- // establish a connection with a suitable mediatype. Needs to
- // propose a media type if the pmt pointer is null or partially
- // specified - use TryMediaTypes on both our and then the other pin's
- // enumerator until we find one that works.
- HRESULT AgreeMediaType(
- IPin *pReceivePin, // connect to this pin
- const CMediaType *pmt); // proposed type from Connect
-
-public:
-
- CBasePin(
- __in_opt LPCTSTR pObjectName, // Object description
- __in CBaseFilter *pFilter, // Owning filter who knows about pins
- __in CCritSec *pLock, // Object who implements the lock
- __inout HRESULT *phr, // General OLE return code
- __in_opt LPCWSTR pName, // Pin name for us
- PIN_DIRECTION dir); // Either PINDIR_INPUT or PINDIR_OUTPUT
-#ifdef UNICODE
- CBasePin(
- __in_opt LPCSTR pObjectName, // Object description
- __in CBaseFilter *pFilter, // Owning filter who knows about pins
- __in CCritSec *pLock, // Object who implements the lock
- __inout HRESULT *phr, // General OLE return code
- __in_opt LPCWSTR pName, // Pin name for us
- PIN_DIRECTION dir); // Either PINDIR_INPUT or PINDIR_OUTPUT
-#endif
- virtual ~CBasePin();
-
- DECLARE_IUNKNOWN
-
- STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void ** ppv);
- STDMETHODIMP_(ULONG) NonDelegatingRelease();
- STDMETHODIMP_(ULONG) NonDelegatingAddRef();
-
- // --- IPin methods ---
-
- // take lead role in establishing a connection. Media type pointer
- // may be null, or may point to partially-specified mediatype
- // (subtype or format type may be GUID_NULL).
- STDMETHODIMP Connect(
- IPin * pReceivePin,
- __in_opt const AM_MEDIA_TYPE *pmt // optional media type
- );
-
- // (passive) accept a connection from another pin
- STDMETHODIMP ReceiveConnection(
- IPin * pConnector, // this is the initiating connecting pin
- const AM_MEDIA_TYPE *pmt // this is the media type we will exchange
- );
-
- STDMETHODIMP Disconnect();
-
- STDMETHODIMP ConnectedTo(__deref_out IPin **pPin);
-
- STDMETHODIMP ConnectionMediaType(__out AM_MEDIA_TYPE *pmt);
-
- STDMETHODIMP QueryPinInfo(
- __out PIN_INFO * pInfo
- );
-
- STDMETHODIMP QueryDirection(
- __out PIN_DIRECTION * pPinDir
- );
-
- STDMETHODIMP QueryId(
- __deref_out LPWSTR * Id
- );
-
- // does the pin support this media type
- STDMETHODIMP QueryAccept(
- const AM_MEDIA_TYPE *pmt
- );
-
- // return an enumerator for this pins preferred media types
- STDMETHODIMP EnumMediaTypes(
- __deref_out IEnumMediaTypes **ppEnum
- );
-
- // return an array of IPin* - the pins that this pin internally connects to
- // All pins put in the array must be AddReffed (but no others)
- // Errors: "Can't say" - FAIL, not enough slots - return S_FALSE
- // Default: return E_NOTIMPL
- // The filter graph will interpret NOT_IMPL as any input pin connects to
- // all visible output pins and vice versa.
- // apPin can be NULL if nPin==0 (not otherwise).
- STDMETHODIMP QueryInternalConnections(
- __out_ecount_part(*nPin,*nPin) IPin* *apPin, // array of IPin*
- __inout ULONG *nPin // on input, the number of slots
- // on output the number of pins
- ) { return E_NOTIMPL; }
-
- // Called when no more data will be sent
- STDMETHODIMP EndOfStream(void);
-
- // Begin/EndFlush still PURE
-
- // NewSegment notifies of the start/stop/rate applying to the data
- // about to be received. Default implementation records data and
- // returns S_OK.
- // Override this to pass downstream.
- STDMETHODIMP NewSegment(
- REFERENCE_TIME tStart,
- REFERENCE_TIME tStop,
- double dRate);
-
- //================================================================================
- // IQualityControl methods
- //================================================================================
-
- STDMETHODIMP Notify(IBaseFilter * pSender, Quality q);
-
- STDMETHODIMP SetSink(IQualityControl * piqc);
-
- // --- helper methods ---
-
- // Returns true if the pin is connected. false otherwise.
- BOOL IsConnected(void) {return (m_Connected != NULL); };
- // Return the pin this is connected to (if any)
- IPin * GetConnected() { return m_Connected; };
-
- // Check if our filter is currently stopped
- BOOL IsStopped() {
- return (m_pFilter->m_State == State_Stopped);
- };
-
- // find out the current type version (used by enumerators)
- virtual LONG GetMediaTypeVersion();
- void IncrementTypeVersion();
-
- // switch the pin to active (paused or running) mode
- // not an error to call this if already active
- virtual HRESULT Active(void);
-
- // switch the pin to inactive state - may already be inactive
- virtual HRESULT Inactive(void);
-
- // Notify of Run() from filter
- virtual HRESULT Run(REFERENCE_TIME tStart);
-
- // check if the pin can support this specific proposed type and format
- virtual HRESULT CheckMediaType(const CMediaType *) PURE;
-
- // set the connection to use this format (previously agreed)
- virtual HRESULT SetMediaType(const CMediaType *);
-
- // check that the connection is ok before verifying it
- // can be overridden eg to check what interfaces will be supported.
- virtual HRESULT CheckConnect(IPin *);
-
- // Set and release resources required for a connection
- virtual HRESULT BreakConnect();
- virtual HRESULT CompleteConnect(IPin *pReceivePin);
-
- // returns the preferred formats for a pin
- virtual HRESULT GetMediaType(int iPosition, __inout CMediaType *pMediaType);
-
- // access to NewSegment values
- REFERENCE_TIME CurrentStopTime() {
- return m_tStop;
- }
- REFERENCE_TIME CurrentStartTime() {
- return m_tStart;
- }
- double CurrentRate() {
- return m_dRate;
- }
-
- // Access name
- LPWSTR Name() { return m_pName; };
-
- // Can reconnectwhen active?
- void SetReconnectWhenActive(bool bCanReconnect)
- {
- m_bCanReconnectWhenActive = bCanReconnect;
- }
-
- bool CanReconnectWhenActive()
- {
- return m_bCanReconnectWhenActive;
- }
-
-protected:
- STDMETHODIMP DisconnectInternal();
-};
-
-
-//=====================================================================
-//=====================================================================
-// Defines CEnumPins
-//
-// Pin enumerator class that works by calling CBaseFilter. This interface
-// is provided by CBaseFilter::EnumPins and calls GetPinCount() and
-// GetPin() to enumerate existing pins. Needs to be a separate object so
-// that it can be cloned (creating an existing object at the same
-// position in the enumeration)
-//
-//=====================================================================
-//=====================================================================
-
-class CEnumPins : public IEnumPins // The interface we support
-{
- int m_Position; // Current ordinal position
- int m_PinCount; // Number of pins available
- CBaseFilter *m_pFilter; // The filter who owns us
- LONG m_Version; // Pin version information
- LONG m_cRef;
-
- typedef CGenericList<CBasePin> CPinList;
-
- CPinList m_PinCache; // These pointers have not been AddRef'ed and
- // so they should not be dereferenced. They are
- // merely kept to ID which pins have been enumerated.
-
-#ifdef DEBUG
- DWORD m_dwCookie;
-#endif
-
- /* If while we are retrieving a pin for example from the filter an error
- occurs we assume that our internal state is stale with respect to the
- filter (someone may have deleted all the pins). We can check before
- starting whether or not the operation is likely to fail by asking the
- filter what it's current version number is. If the filter has not
- overriden the GetPinVersion method then this will always match */
-
- BOOL AreWeOutOfSync() {
- return (m_pFilter->GetPinVersion() == m_Version ? FALSE : TRUE);
- };
-
- /* This method performs the same operations as Reset, except is does not clear
- the cache of pins already enumerated. */
-
- STDMETHODIMP Refresh();
-
-public:
-
- CEnumPins(
- __in CBaseFilter *pFilter,
- __in_opt CEnumPins *pEnumPins);
-
- virtual ~CEnumPins();
-
- // IUnknown
- STDMETHODIMP QueryInterface(REFIID riid, __deref_out void **ppv);
- STDMETHODIMP_(ULONG) AddRef();
- STDMETHODIMP_(ULONG) Release();
-
- // IEnumPins
- STDMETHODIMP Next(
- ULONG cPins, // place this many pins...
- __out_ecount(cPins) IPin ** ppPins, // ...in this array of IPin*
- __out_opt ULONG * pcFetched // actual count passed returned here
- );
-
- STDMETHODIMP Skip(ULONG cPins);
- STDMETHODIMP Reset();
- STDMETHODIMP Clone(__deref_out IEnumPins **ppEnum);
-
-
-};
-
-
-//=====================================================================
-//=====================================================================
-// Defines CEnumMediaTypes
-//
-// Enumerates the preferred formats for input and output pins
-//=====================================================================
-//=====================================================================
-
-class CEnumMediaTypes : public IEnumMediaTypes // The interface we support
-{
- int m_Position; // Current ordinal position
- CBasePin *m_pPin; // The pin who owns us
- LONG m_Version; // Media type version value
- LONG m_cRef;
-#ifdef DEBUG
- DWORD m_dwCookie;
-#endif
-
- /* The media types a filter supports can be quite dynamic so we add to
- the general IEnumXXXX interface the ability to be signaled when they
- change via an event handle the connected filter supplies. Until the
- Reset method is called after the state changes all further calls to
- the enumerator (except Reset) will return E_UNEXPECTED error code */
-
- BOOL AreWeOutOfSync() {
- return (m_pPin->GetMediaTypeVersion() == m_Version ? FALSE : TRUE);
- };
-
-public:
-
- CEnumMediaTypes(
- __in CBasePin *pPin,
- __in_opt CEnumMediaTypes *pEnumMediaTypes);
-
- virtual ~CEnumMediaTypes();
-
- // IUnknown
- STDMETHODIMP QueryInterface(REFIID riid, __deref_out void **ppv);
- STDMETHODIMP_(ULONG) AddRef();
- STDMETHODIMP_(ULONG) Release();
-
- // IEnumMediaTypes
- STDMETHODIMP Next(
- ULONG cMediaTypes, // place this many pins...
- __out_ecount(cMediaTypes) AM_MEDIA_TYPE ** ppMediaTypes, // ...in this array
- __out_opt ULONG * pcFetched // actual count passed
- );
-
- STDMETHODIMP Skip(ULONG cMediaTypes);
- STDMETHODIMP Reset();
- STDMETHODIMP Clone(__deref_out IEnumMediaTypes **ppEnum);
-};
-
-
-
-
-//=====================================================================
-//=====================================================================
-// Defines CBaseOutputPin
-//
-// class derived from CBasePin that can pass buffers to a connected pin
-// that supports IMemInputPin. Supports IPin.
-//
-// Derive your output pin from this.
-//
-//=====================================================================
-//=====================================================================
-
-class AM_NOVTABLE CBaseOutputPin : public CBasePin
-{
-
-protected:
-
- IMemAllocator *m_pAllocator;
- IMemInputPin *m_pInputPin; // interface on the downstreaminput pin
- // set up in CheckConnect when we connect.
-
-public:
-
- CBaseOutputPin(
- __in_opt LPCTSTR pObjectName,
- __in CBaseFilter *pFilter,
- __in CCritSec *pLock,
- __inout HRESULT *phr,
- __in_opt LPCWSTR pName);
-#ifdef UNICODE
- CBaseOutputPin(
- __in_opt LPCSTR pObjectName,
- __in CBaseFilter *pFilter,
- __in CCritSec *pLock,
- __inout HRESULT *phr,
- __in_opt LPCWSTR pName);
-#endif
- // override CompleteConnect() so we can negotiate an allocator
- virtual HRESULT CompleteConnect(IPin *pReceivePin);
-
- // negotiate the allocator and its buffer size/count and other properties
- // Calls DecideBufferSize to set properties
- virtual HRESULT DecideAllocator(IMemInputPin * pPin, __deref_out IMemAllocator ** pAlloc);
-
- // override this to set the buffer size and count. Return an error
- // if the size/count is not to your liking.
- // The allocator properties passed in are those requested by the
- // input pin - use eg the alignment and prefix members if you have
- // no preference on these.
- virtual HRESULT DecideBufferSize(
- IMemAllocator * pAlloc,
- __inout ALLOCATOR_PROPERTIES * ppropInputRequest
- ) PURE;
-
- // returns an empty sample buffer from the allocator
- virtual HRESULT GetDeliveryBuffer(__deref_out IMediaSample ** ppSample,
- __in_opt REFERENCE_TIME * pStartTime,
- __in_opt REFERENCE_TIME * pEndTime,
- DWORD dwFlags);
-
- // deliver a filled-in sample to the connected input pin
- // note - you need to release it after calling this. The receiving
- // pin will addref the sample if it needs to hold it beyond the
- // call.
- virtual HRESULT Deliver(IMediaSample *);
-
- // override this to control the connection
- virtual HRESULT InitAllocator(__deref_out IMemAllocator **ppAlloc);
- HRESULT CheckConnect(IPin *pPin);
- HRESULT BreakConnect();
-
- // override to call Commit and Decommit
- HRESULT Active(void);
- HRESULT Inactive(void);
-
- // we have a default handling of EndOfStream which is to return
- // an error, since this should be called on input pins only
- STDMETHODIMP EndOfStream(void);
-
- // called from elsewhere in our filter to pass EOS downstream to
- // our connected input pin
- virtual HRESULT DeliverEndOfStream(void);
-
- // same for Begin/EndFlush - we handle Begin/EndFlush since it
- // is an error on an output pin, and we have Deliver methods to
- // call the methods on the connected pin
- STDMETHODIMP BeginFlush(void);
- STDMETHODIMP EndFlush(void);
- virtual HRESULT DeliverBeginFlush(void);
- virtual HRESULT DeliverEndFlush(void);
-
- // deliver NewSegment to connected pin - you will need to
- // override this if you queue any data in your output pin.
- virtual HRESULT DeliverNewSegment(
- REFERENCE_TIME tStart,
- REFERENCE_TIME tStop,
- double dRate);
-
- //================================================================================
- // IQualityControl methods
- //================================================================================
-
- // All inherited from CBasePin and not overridden here.
- // STDMETHODIMP Notify(IBaseFilter * pSender, Quality q);
- // STDMETHODIMP SetSink(IQualityControl * piqc);
-};
-
-
-//=====================================================================
-//=====================================================================
-// Defines CBaseInputPin
-//
-// derive your standard input pin from this.
-// you need to supply GetMediaType and CheckConnect etc (see CBasePin),
-// and you need to supply Receive to do something more useful.
-//
-//=====================================================================
-//=====================================================================
-
-class AM_NOVTABLE CBaseInputPin : public CBasePin,
- public IMemInputPin
-{
-
-protected:
-
- IMemAllocator *m_pAllocator; // Default memory allocator
-
- // allocator is read-only, so received samples
- // cannot be modified (probably only relevant to in-place
- // transforms
- BYTE m_bReadOnly;
-
- // in flushing state (between BeginFlush and EndFlush)
- // if TRUE, all Receives are returned with S_FALSE
- BYTE m_bFlushing;
-
- // Sample properties - initalized in Receive
- AM_SAMPLE2_PROPERTIES m_SampleProps;
-
-public:
-
- CBaseInputPin(
- __in_opt LPCTSTR pObjectName,
- __in CBaseFilter *pFilter,
- __in CCritSec *pLock,
- __inout HRESULT *phr,
- __in_opt LPCWSTR pName);
-#ifdef UNICODE
- CBaseInputPin(
- __in_opt LPCSTR pObjectName,
- __in CBaseFilter *pFilter,
- __in CCritSec *pLock,
- __inout HRESULT *phr,
- __in_opt LPCWSTR pName);
-#endif
- virtual ~CBaseInputPin();
-
- DECLARE_IUNKNOWN
-
- // override this to publicise our interfaces
- STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
-
- // return the allocator interface that this input pin
- // would like the output pin to use
- STDMETHODIMP GetAllocator(__deref_out IMemAllocator ** ppAllocator);
-
- // tell the input pin which allocator the output pin is actually
- // going to use.
- STDMETHODIMP NotifyAllocator(
- IMemAllocator * pAllocator,
- BOOL bReadOnly);
-
- // do something with this media sample
- STDMETHODIMP Receive(IMediaSample *pSample);
-
- // do something with these media samples
- STDMETHODIMP ReceiveMultiple (
- __in_ecount(nSamples) IMediaSample **pSamples,
- long nSamples,
- __out long *nSamplesProcessed);
-
- // See if Receive() blocks
- STDMETHODIMP ReceiveCanBlock();
-
- // Default handling for BeginFlush - call at the beginning
- // of your implementation (makes sure that all Receive calls
- // fail). After calling this, you need to free any queued data
- // and then call downstream.
- STDMETHODIMP BeginFlush(void);
-
- // default handling for EndFlush - call at end of your implementation
- // - before calling this, ensure that there is no queued data and no thread
- // pushing any more without a further receive, then call downstream,
- // then call this method to clear the m_bFlushing flag and re-enable
- // receives
- STDMETHODIMP EndFlush(void);
-
- // this method is optional (can return E_NOTIMPL).
- // default implementation returns E_NOTIMPL. Override if you have
- // specific alignment or prefix needs, but could use an upstream
- // allocator
- STDMETHODIMP GetAllocatorRequirements(__out ALLOCATOR_PROPERTIES*pProps);
-
- // Release the pin's allocator.
- HRESULT BreakConnect();
-
- // helper method to check the read-only flag
- BOOL IsReadOnly() {
- return m_bReadOnly;
- };
-
- // helper method to see if we are flushing
- BOOL IsFlushing() {
- return m_bFlushing;
- };
-
- // Override this for checking whether it's OK to process samples
- // Also call this from EndOfStream.
- virtual HRESULT CheckStreaming();
-
- // Pass a Quality notification on to the appropriate sink
- HRESULT PassNotify(Quality& q);
-
-
- //================================================================================
- // IQualityControl methods (from CBasePin)
- //================================================================================
-
- STDMETHODIMP Notify(IBaseFilter * pSender, Quality q);
-
- // no need to override:
- // STDMETHODIMP SetSink(IQualityControl * piqc);
-
-
- // switch the pin to inactive state - may already be inactive
- virtual HRESULT Inactive(void);
-
- // Return sample properties pointer
- AM_SAMPLE2_PROPERTIES * SampleProps() {
- ASSERT(m_SampleProps.cbData != 0);
- return &m_SampleProps;
- }
-
-};
-
-///////////////////////////////////////////////////////////////////////////
-// CDynamicOutputPin
-//
-
-class CDynamicOutputPin : public CBaseOutputPin,
- public IPinFlowControl
-{
-public:
-#ifdef UNICODE
- CDynamicOutputPin(
- __in_opt LPCSTR pObjectName,
- __in CBaseFilter *pFilter,
- __in CCritSec *pLock,
- __inout HRESULT *phr,
- __in_opt LPCWSTR pName);
-#endif
-
- CDynamicOutputPin(
- __in_opt LPCTSTR pObjectName,
- __in CBaseFilter *pFilter,
- __in CCritSec *pLock,
- __inout HRESULT *phr,
- __in_opt LPCWSTR pName);
-
- ~CDynamicOutputPin();
-
- // IUnknown Methods
- DECLARE_IUNKNOWN
- STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
-
- // IPin Methods
- STDMETHODIMP Disconnect(void);
-
- // IPinFlowControl Methods
- STDMETHODIMP Block(DWORD dwBlockFlags, HANDLE hEvent);
-
- // Set graph config info
- void SetConfigInfo(IGraphConfig *pGraphConfig, HANDLE hStopEvent);
-
- #ifdef DEBUG
- virtual HRESULT Deliver(IMediaSample *pSample);
- virtual HRESULT DeliverEndOfStream(void);
- virtual HRESULT DeliverNewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
- #endif // DEBUG
-
- HRESULT DeliverBeginFlush(void);
- HRESULT DeliverEndFlush(void);
-
- HRESULT Inactive(void);
- HRESULT Active(void);
- virtual HRESULT CompleteConnect(IPin *pReceivePin);
-
- virtual HRESULT StartUsingOutputPin(void);
- virtual void StopUsingOutputPin(void);
- virtual bool StreamingThreadUsingOutputPin(void);
-
- HRESULT ChangeOutputFormat
- (
- const AM_MEDIA_TYPE *pmt,
- REFERENCE_TIME tSegmentStart,
- REFERENCE_TIME tSegmentStop,
- double dSegmentRate
- );
- HRESULT ChangeMediaType(const CMediaType *pmt);
- HRESULT DynamicReconnect(const CMediaType *pmt);
-
-protected:
- HRESULT SynchronousBlockOutputPin(void);
- HRESULT AsynchronousBlockOutputPin(HANDLE hNotifyCallerPinBlockedEvent);
- HRESULT UnblockOutputPin(void);
-
- void BlockOutputPin(void);
- void ResetBlockState(void);
-
- static HRESULT WaitEvent(HANDLE hEvent);
-
- enum BLOCK_STATE
- {
- NOT_BLOCKED,
- PENDING,
- BLOCKED
- };
-
- // This lock should be held when the following class members are
- // being used: m_hNotifyCallerPinBlockedEvent, m_BlockState,
- // m_dwBlockCallerThreadID and m_dwNumOutstandingOutputPinUsers.
- CCritSec m_BlockStateLock;
-
- // This event should be signaled when the output pin is
- // not blocked. This is a manual reset event. For more
- // information on events, see the documentation for
- // CreateEvent() in the Windows SDK.
- HANDLE m_hUnblockOutputPinEvent;
-
- // This event will be signaled when block operation succeedes or
- // when the user cancels the block operation. The block operation
- // can be canceled by calling IPinFlowControl2::Block( 0, NULL )
- // while the block operation is pending.
- HANDLE m_hNotifyCallerPinBlockedEvent;
-
- // The state of the current block operation.
- BLOCK_STATE m_BlockState;
-
- // The ID of the thread which last called IPinFlowControl::Block().
- // For more information on thread IDs, see the documentation for
- // GetCurrentThreadID() in the Windows SDK.
- DWORD m_dwBlockCallerThreadID;
-
- // The number of times StartUsingOutputPin() has been sucessfully
- // called and a corresponding call to StopUsingOutputPin() has not
- // been made. When this variable is greater than 0, the streaming
- // thread is calling IPin::NewSegment(), IPin::EndOfStream(),
- // IMemInputPin::Receive() or IMemInputPin::ReceiveMultiple(). The
- // streaming thread could also be calling: DynamicReconnect(),
- // ChangeMediaType() or ChangeOutputFormat(). The output pin cannot
- // be blocked while the output pin is being used.
- DWORD m_dwNumOutstandingOutputPinUsers;
-
- // This event should be set when the IMediaFilter::Stop() is called.
- // This is a manual reset event. It is also set when the output pin
- // delivers a flush to the connected input pin.
- HANDLE m_hStopEvent;
- IGraphConfig* m_pGraphConfig;
-
- // TRUE if the output pin's allocator's samples are read only.
- // Otherwise FALSE. For more information, see the documentation
- // for IMemInputPin::NotifyAllocator().
- BOOL m_bPinUsesReadOnlyAllocator;
-
-private:
- HRESULT Initialize(void);
- HRESULT ChangeMediaTypeHelper(const CMediaType *pmt);
-
- #ifdef DEBUG
- void AssertValid(void);
- #endif // DEBUG
-};
-
-class CAutoUsingOutputPin
-{
-public:
- CAutoUsingOutputPin( __in CDynamicOutputPin* pOutputPin, __inout HRESULT* phr );
- ~CAutoUsingOutputPin();
-
-private:
- CDynamicOutputPin* m_pOutputPin;
-};
-
-inline CAutoUsingOutputPin::CAutoUsingOutputPin( __in CDynamicOutputPin* pOutputPin, __inout HRESULT* phr ) :
- m_pOutputPin(NULL)
-{
- // The caller should always pass in valid pointers.
- ASSERT( NULL != pOutputPin );
- ASSERT( NULL != phr );
-
- // Make sure the user initialized phr.
- ASSERT( S_OK == *phr );
-
- HRESULT hr = pOutputPin->StartUsingOutputPin();
- if( FAILED( hr ) )
- {
- *phr = hr;
- return;
- }
-
- m_pOutputPin = pOutputPin;
-}
-
-inline CAutoUsingOutputPin::~CAutoUsingOutputPin()
-{
- if( NULL != m_pOutputPin )
- {
- m_pOutputPin->StopUsingOutputPin();
- }
-}
-
-#ifdef DEBUG
-
-inline HRESULT CDynamicOutputPin::Deliver(IMediaSample *pSample)
-{
- // The caller should call StartUsingOutputPin() before calling this
- // method.
- ASSERT(StreamingThreadUsingOutputPin());
-
- return CBaseOutputPin::Deliver(pSample);
-}
-
-inline HRESULT CDynamicOutputPin::DeliverEndOfStream(void)
-{
- // The caller should call StartUsingOutputPin() before calling this
- // method.
- ASSERT( StreamingThreadUsingOutputPin() );
-
- return CBaseOutputPin::DeliverEndOfStream();
-}
-
-inline HRESULT CDynamicOutputPin::DeliverNewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
-{
- // The caller should call StartUsingOutputPin() before calling this
- // method.
- ASSERT(StreamingThreadUsingOutputPin());
-
- return CBaseOutputPin::DeliverNewSegment(tStart, tStop, dRate);
-}
-
-#endif // DEBUG
-
-//=====================================================================
-//=====================================================================
-// Memory allocators
-//
-// the shared memory transport between pins requires the input pin
-// to provide a memory allocator that can provide sample objects. A
-// sample object supports the IMediaSample interface.
-//
-// CBaseAllocator handles the management of free and busy samples. It
-// allocates CMediaSample objects. CBaseAllocator is an abstract class:
-// in particular it has no method of initializing the list of free
-// samples. CMemAllocator is derived from CBaseAllocator and initializes
-// the list of samples using memory from the standard IMalloc interface.
-//
-// If you want your buffers to live in some special area of memory,
-// derive your allocator object from CBaseAllocator. If you derive your
-// IMemInputPin interface object from CBaseMemInputPin, you will get
-// CMemAllocator-based allocation etc for free and will just need to
-// supply the Receive handling, and media type / format negotiation.
-//=====================================================================
-//=====================================================================
-
-
-//=====================================================================
-//=====================================================================
-// Defines CMediaSample
-//
-// an object of this class supports IMediaSample and represents a buffer
-// for media data with some associated properties. Releasing it returns
-// it to a freelist managed by a CBaseAllocator derived object.
-//=====================================================================
-//=====================================================================
-
-class CMediaSample : public IMediaSample2 // The interface we support
-{
-
-protected:
-
- friend class CBaseAllocator;
-
- /* Values for dwFlags - these are used for backward compatiblity
- only now - use AM_SAMPLE_xxx
- */
- enum { Sample_SyncPoint = 0x01, /* Is this a sync point */
- Sample_Preroll = 0x02, /* Is this a preroll sample */
- Sample_Discontinuity = 0x04, /* Set if start of new segment */
- Sample_TypeChanged = 0x08, /* Has the type changed */
- Sample_TimeValid = 0x10, /* Set if time is valid */
- Sample_MediaTimeValid = 0x20, /* Is the media time valid */
- Sample_TimeDiscontinuity = 0x40, /* Time discontinuity */
- Sample_StopValid = 0x100, /* Stop time valid */
- Sample_ValidFlags = 0x1FF
- };
-
- /* Properties, the media sample class can be a container for a format
- change in which case we take a copy of a type through the SetMediaType
- interface function and then return it when GetMediaType is called. As
- we do no internal processing on it we leave it as a pointer */
-
- DWORD m_dwFlags; /* Flags for this sample */
- /* Type specific flags are packed
- into the top word
- */
- DWORD m_dwTypeSpecificFlags; /* Media type specific flags */
- __field_ecount_opt(m_cbBuffer) LPBYTE m_pBuffer; /* Pointer to the complete buffer */
- LONG m_lActual; /* Length of data in this sample */
- LONG m_cbBuffer; /* Size of the buffer */
- CBaseAllocator *m_pAllocator; /* The allocator who owns us */
- CMediaSample *m_pNext; /* Chaining in free list */
- REFERENCE_TIME m_Start; /* Start sample time */
- REFERENCE_TIME m_End; /* End sample time */
- LONGLONG m_MediaStart; /* Real media start position */
- LONG m_MediaEnd; /* A difference to get the end */
- AM_MEDIA_TYPE *m_pMediaType; /* Media type change data */
- DWORD m_dwStreamId; /* Stream id */
-public:
- LONG m_cRef; /* Reference count */
-
-
-public:
-
- CMediaSample(
- __in_opt LPCTSTR pName,
- __in_opt CBaseAllocator *pAllocator,
- __inout_opt HRESULT *phr,
- __in_bcount_opt(length) LPBYTE pBuffer = NULL,
- LONG length = 0);
-#ifdef UNICODE
- CMediaSample(
- __in_opt LPCSTR pName,
- __in_opt CBaseAllocator *pAllocator,
- __inout_opt HRESULT *phr,
- __in_bcount_opt(length) LPBYTE pBuffer = NULL,
- LONG length = 0);
-#endif
-
- virtual ~CMediaSample();
-
- /* Note the media sample does not delegate to its owner */
-
- STDMETHODIMP QueryInterface(REFIID riid, __deref_out void **ppv);
- STDMETHODIMP_(ULONG) AddRef();
- STDMETHODIMP_(ULONG) Release();
-
- // set the buffer pointer and length. Used by allocators that
- // want variable sized pointers or pointers into already-read data.
- // This is only available through a CMediaSample* not an IMediaSample*
- // and so cannot be changed by clients.
- HRESULT SetPointer(__in_bcount(cBytes) BYTE * ptr, LONG cBytes);
-
- // Get me a read/write pointer to this buffer's memory.
- STDMETHODIMP GetPointer(__deref_out BYTE ** ppBuffer);
-
- STDMETHODIMP_(LONG) GetSize(void);
-
- // get the stream time at which this sample should start and finish.
- STDMETHODIMP GetTime(
- __out REFERENCE_TIME * pTimeStart, // put time here
- __out REFERENCE_TIME * pTimeEnd
- );
-
- // Set the stream time at which this sample should start and finish.
- STDMETHODIMP SetTime(
- __in_opt REFERENCE_TIME * pTimeStart, // put time here
- __in_opt REFERENCE_TIME * pTimeEnd
- );
- STDMETHODIMP IsSyncPoint(void);
- STDMETHODIMP SetSyncPoint(BOOL bIsSyncPoint);
- STDMETHODIMP IsPreroll(void);
- STDMETHODIMP SetPreroll(BOOL bIsPreroll);
-
- STDMETHODIMP_(LONG) GetActualDataLength(void);
- STDMETHODIMP SetActualDataLength(LONG lActual);
-
- // these allow for limited format changes in band
-
- STDMETHODIMP GetMediaType(__deref_out AM_MEDIA_TYPE **ppMediaType);
- STDMETHODIMP SetMediaType(__in_opt AM_MEDIA_TYPE *pMediaType);
-
- // returns S_OK if there is a discontinuity in the data (this same is
- // not a continuation of the previous stream of data
- // - there has been a seek).
- STDMETHODIMP IsDiscontinuity(void);
- // set the discontinuity property - TRUE if this sample is not a
- // continuation, but a new sample after a seek.
- STDMETHODIMP SetDiscontinuity(BOOL bDiscontinuity);
-
- // get the media times for this sample
- STDMETHODIMP GetMediaTime(
- __out LONGLONG * pTimeStart,
- __out LONGLONG * pTimeEnd
- );
-
- // Set the media times for this sample
- STDMETHODIMP SetMediaTime(
- __in_opt LONGLONG * pTimeStart,
- __in_opt LONGLONG * pTimeEnd
- );
-
- // Set and get properties (IMediaSample2)
- STDMETHODIMP GetProperties(
- DWORD cbProperties,
- __out_bcount(cbProperties) BYTE * pbProperties
- );
-
- STDMETHODIMP SetProperties(
- DWORD cbProperties,
- __in_bcount(cbProperties) const BYTE * pbProperties
- );
-};
-
-
-//=====================================================================
-//=====================================================================
-// Defines CBaseAllocator
-//
-// Abstract base class that manages a list of media samples
-//
-// This class provides support for getting buffers from the free list,
-// including handling of commit and (asynchronous) decommit.
-//
-// Derive from this class and override the Alloc and Free functions to
-// allocate your CMediaSample (or derived) objects and add them to the
-// free list, preparing them as necessary.
-//=====================================================================
-//=====================================================================
-
-class AM_NOVTABLE CBaseAllocator : public CUnknown,// A non delegating IUnknown
- public IMemAllocatorCallbackTemp, // The interface we support
- public CCritSec // Provides object locking
-{
- class CSampleList;
- friend class CSampleList;
-
- /* Trick to get at protected member in CMediaSample */
- static CMediaSample * &NextSample(__in CMediaSample *pSample)
- {
- return pSample->m_pNext;
- };
-
- /* Mini list class for the free list */
- class CSampleList
- {
- public:
- CSampleList() : m_List(NULL), m_nOnList(0) {};
-#ifdef DEBUG
- ~CSampleList()
- {
- ASSERT(m_nOnList == 0);
- };
-#endif
- CMediaSample *Head() const { return m_List; };
- CMediaSample *Next(__in CMediaSample *pSample) const { return CBaseAllocator::NextSample(pSample); };
- int GetCount() const { return m_nOnList; };
- void Add(__inout CMediaSample *pSample)
- {
- ASSERT(pSample != NULL);
- CBaseAllocator::NextSample(pSample) = m_List;
- m_List = pSample;
- m_nOnList++;
- };
- CMediaSample *RemoveHead()
- {
- CMediaSample *pSample = m_List;
- if (pSample != NULL) {
- m_List = CBaseAllocator::NextSample(m_List);
- m_nOnList--;
- }
- return pSample;
- };
- void Remove(__inout CMediaSample *pSample);
-
- public:
- CMediaSample *m_List;
- int m_nOnList;
- };
-protected:
-
- CSampleList m_lFree; // Free list
-
- /* Note to overriders of CBaseAllocator.
-
- We use a lazy signalling mechanism for waiting for samples.
- This means we don't call the OS if no waits occur.
-
- In order to implement this:
-
- 1. When a new sample is added to m_lFree call NotifySample() which
- calls ReleaseSemaphore on m_hSem with a count of m_lWaiting and
- sets m_lWaiting to 0.
- This must all be done holding the allocator's critical section.
-
- 2. When waiting for a sample call SetWaiting() which increments
- m_lWaiting BEFORE leaving the allocator's critical section.
-
- 3. Actually wait by calling WaitForSingleObject(m_hSem, INFINITE)
- having left the allocator's critical section. The effect of
- this is to remove 1 from the semaphore's count. You MUST call
- this once having incremented m_lWaiting.
-
- The following are then true when the critical section is not held :
- (let nWaiting = number about to wait or waiting)
-
- (1) if (m_lFree.GetCount() != 0) then (m_lWaiting == 0)
- (2) m_lWaiting + Semaphore count == nWaiting
-
- We would deadlock if
- nWaiting != 0 &&
- m_lFree.GetCount() != 0 &&
- Semaphore count == 0
-
- But from (1) if m_lFree.GetCount() != 0 then m_lWaiting == 0 so
- from (2) Semaphore count == nWaiting (which is non-0) so the
- deadlock can't happen.
- */
-
- HANDLE m_hSem; // For signalling
- long m_lWaiting; // Waiting for a free element
- long m_lCount; // how many buffers we have agreed to provide
- long m_lAllocated; // how many buffers are currently allocated
- long m_lSize; // agreed size of each buffer
- long m_lAlignment; // agreed alignment
- long m_lPrefix; // agreed prefix (preceeds GetPointer() value)
- BOOL m_bChanged; // Have the buffer requirements changed
-
- // if true, we are decommitted and can't allocate memory
- BOOL m_bCommitted;
- // if true, the decommit has happened, but we haven't called Free yet
- // as there are still outstanding buffers
- BOOL m_bDecommitInProgress;
-
- // Notification interface
- IMemAllocatorNotifyCallbackTemp *m_pNotify;
-
- BOOL m_fEnableReleaseCallback;
-
- // called to decommit the memory when the last buffer is freed
- // pure virtual - need to override this
- virtual void Free(void) PURE;
-
- // override to allocate the memory when commit called
- virtual HRESULT Alloc(void);
-
-public:
-
- CBaseAllocator(
- __in_opt LPCTSTR , __inout_opt LPUNKNOWN, __inout HRESULT *,
- BOOL bEvent = TRUE, BOOL fEnableReleaseCallback = FALSE);
-#ifdef UNICODE
- CBaseAllocator(
- __in_opt LPCSTR , __inout_opt LPUNKNOWN, __inout HRESULT *,
- BOOL bEvent = TRUE, BOOL fEnableReleaseCallback = FALSE);
-#endif
- virtual ~CBaseAllocator();
-
- DECLARE_IUNKNOWN
-
- // override this to publicise our interfaces
- STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
-
- STDMETHODIMP SetProperties(
- __in ALLOCATOR_PROPERTIES* pRequest,
- __out ALLOCATOR_PROPERTIES* pActual);
-
- // return the properties actually being used on this allocator
- STDMETHODIMP GetProperties(
- __out ALLOCATOR_PROPERTIES* pProps);
-
- // override Commit to allocate memory. We handle the GetBuffer
- //state changes
- STDMETHODIMP Commit();
-
- // override this to handle the memory freeing. We handle any outstanding
- // GetBuffer calls
- STDMETHODIMP Decommit();
-
- // get container for a sample. Blocking, synchronous call to get the
- // next free buffer (as represented by an IMediaSample interface).
- // on return, the time etc properties will be invalid, but the buffer
- // pointer and size will be correct. The two time parameters are
- // optional and either may be NULL, they may alternatively be set to
- // the start and end times the sample will have attached to it
- // bPrevFramesSkipped is not used (used only by the video renderer's
- // allocator where it affects quality management in direct draw).
-
- STDMETHODIMP GetBuffer(__deref_out IMediaSample **ppBuffer,
- __in_opt REFERENCE_TIME * pStartTime,
- __in_opt REFERENCE_TIME * pEndTime,
- DWORD dwFlags);
-
- // final release of a CMediaSample will call this
- STDMETHODIMP ReleaseBuffer(IMediaSample *pBuffer);
- // obsolete:: virtual void PutOnFreeList(CMediaSample * pSample);
-
- STDMETHODIMP SetNotify(IMemAllocatorNotifyCallbackTemp *pNotify);
-
- STDMETHODIMP GetFreeCount(__out LONG *plBuffersFree);
-
- // Notify that a sample is available
- void NotifySample();
-
- // Notify that we're waiting for a sample
- void SetWaiting() { m_lWaiting++; };
-};
-
-
-//=====================================================================
-//=====================================================================
-// Defines CMemAllocator
-//
-// this is an allocator based on CBaseAllocator that allocates sample
-// buffers in main memory (from 'new'). You must call SetProperties
-// before calling Commit.
-//
-// we don't free the memory when going into Decommit state. The simplest
-// way to implement this without complicating CBaseAllocator is to
-// have a Free() function, called to go into decommit state, that does
-// nothing and a ReallyFree function called from our destructor that
-// actually frees the memory.
-//=====================================================================
-//=====================================================================
-
-// Make me one from quartz.dll
-STDAPI CreateMemoryAllocator(__deref_out IMemAllocator **ppAllocator);
-
-class CMemAllocator : public CBaseAllocator
-{
-
-protected:
-
- LPBYTE m_pBuffer; // combined memory for all buffers
-
- // override to free the memory when decommit completes
- // - we actually do nothing, and save the memory until deletion.
- void Free(void);
-
- // called from the destructor (and from Alloc if changing size/count) to
- // actually free up the memory
- void ReallyFree(void);
-
- // overriden to allocate the memory when commit called
- HRESULT Alloc(void);
-
-public:
- /* This goes in the factory template table to create new instances */
- static CUnknown *CreateInstance(__inout_opt LPUNKNOWN, __inout HRESULT *);
-
- STDMETHODIMP SetProperties(
- __in ALLOCATOR_PROPERTIES* pRequest,
- __out ALLOCATOR_PROPERTIES* pActual);
-
- CMemAllocator(__in_opt LPCTSTR , __inout_opt LPUNKNOWN, __inout HRESULT *);
-#ifdef UNICODE
- CMemAllocator(__in_opt LPCSTR , __inout_opt LPUNKNOWN, __inout HRESULT *);
-#endif
- ~CMemAllocator();
-};
-
-// helper used by IAMovieSetup implementation
-STDAPI
-AMovieSetupRegisterFilter( const AMOVIESETUP_FILTER * const psetupdata
- , IFilterMapper * pIFM
- , BOOL bRegister );
-
-
-///////////////////////////////////////////////////////////////////////////
-// ------------------------------------------------------------------------
-// ------------------------------------------------------------------------
-// ------------------------------------------------------------------------
-// ------------------------------------------------------------------------
-///////////////////////////////////////////////////////////////////////////
-
-#endif /* __FILTER__ */
-
-
-
diff --git a/dll/src/baseclasses/amvideo.cpp b/dll/src/baseclasses/amvideo.cpp
deleted file mode 100644
index 42fe446..0000000
--- a/dll/src/baseclasses/amvideo.cpp
+++ /dev/null
@@ -1,275 +0,0 @@
-//------------------------------------------------------------------------------
-// File: AMVideo.cpp
-//
-// Desc: DirectShow base classes - implements helper functions for
-// bitmap formats.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-#include <streams.h>
-#include <limits.h>
-
-// These are bit field masks for true colour devices
-
-const DWORD bits555[] = {0x007C00,0x0003E0,0x00001F};
-const DWORD bits565[] = {0x00F800,0x0007E0,0x00001F};
-const DWORD bits888[] = {0xFF0000,0x00FF00,0x0000FF};
-
-// This maps bitmap subtypes into a bits per pixel value and also a
-// name. unicode and ansi versions are stored because we have to
-// return a pointer to a static string.
-const struct {
- const GUID *pSubtype;
- WORD BitCount;
- CHAR *pName;
- WCHAR *wszName;
-} BitCountMap[] = { &MEDIASUBTYPE_RGB1, 1, "RGB Monochrome", L"RGB Monochrome",
- &MEDIASUBTYPE_RGB4, 4, "RGB VGA", L"RGB VGA",
- &MEDIASUBTYPE_RGB8, 8, "RGB 8", L"RGB 8",
- &MEDIASUBTYPE_RGB565, 16, "RGB 565 (16 bit)", L"RGB 565 (16 bit)",
- &MEDIASUBTYPE_RGB555, 16, "RGB 555 (16 bit)", L"RGB 555 (16 bit)",
- &MEDIASUBTYPE_RGB24, 24, "RGB 24", L"RGB 24",
- &MEDIASUBTYPE_RGB32, 32, "RGB 32", L"RGB 32",
- &MEDIASUBTYPE_ARGB32, 32, "ARGB 32", L"ARGB 32",
- &MEDIASUBTYPE_Overlay, 0, "Overlay", L"Overlay",
- &GUID_NULL, 0, "UNKNOWN", L"UNKNOWN"
-};
-
-// Return the size of the bitmap as defined by this header
-
-STDAPI_(DWORD) GetBitmapSize(const BITMAPINFOHEADER *pHeader)
-{
- return DIBSIZE(*pHeader);
-}
-
-
-// This is called if the header has a 16 bit colour depth and needs to work
-// out the detailed type from the bit fields (either RGB 565 or RGB 555)
-
-STDAPI_(const GUID) GetTrueColorType(const BITMAPINFOHEADER *pbmiHeader)
-{
- BITMAPINFO *pbmInfo = (BITMAPINFO *) pbmiHeader;
- ASSERT(pbmiHeader->biBitCount == 16);
-
- // If its BI_RGB then it's RGB 555 by default
-
- if (pbmiHeader->biCompression == BI_RGB) {
- return MEDIASUBTYPE_RGB555;
- }
-
- // Compare the bit fields with RGB 555
-
- DWORD *pMask = (DWORD *) pbmInfo->bmiColors;
- if (pMask[0] == bits555[0]) {
- if (pMask[1] == bits555[1]) {
- if (pMask[2] == bits555[2]) {
- return MEDIASUBTYPE_RGB555;
- }
- }
- }
-
- // Compare the bit fields with RGB 565
-
- pMask = (DWORD *) pbmInfo->bmiColors;
- if (pMask[0] == bits565[0]) {
- if (pMask[1] == bits565[1]) {
- if (pMask[2] == bits565[2]) {
- return MEDIASUBTYPE_RGB565;
- }
- }
- }
- return GUID_NULL;
-}
-
-
-// Given a BITMAPINFOHEADER structure this returns the GUID sub type that is
-// used to describe it in format negotiations. For example a video codec fills
-// in the format block with a VIDEOINFO structure, it also fills in the major
-// type with MEDIATYPE_VIDEO and the subtype with a GUID that matches the bit
-// count, for example if it is an eight bit image then MEDIASUBTYPE_RGB8
-
-STDAPI_(const GUID) GetBitmapSubtype(const BITMAPINFOHEADER *pbmiHeader)
-{
- ASSERT(pbmiHeader);
-
- // If it's not RGB then create a GUID from the compression type
-
- if (pbmiHeader->biCompression != BI_RGB) {
- if (pbmiHeader->biCompression != BI_BITFIELDS) {
- FOURCCMap FourCCMap(pbmiHeader->biCompression);
- return (const GUID) FourCCMap;
- }
- }
-
- // Map the RGB DIB bit depth to a image GUID
-
- switch(pbmiHeader->biBitCount) {
- case 1 : return MEDIASUBTYPE_RGB1;
- case 4 : return MEDIASUBTYPE_RGB4;
- case 8 : return MEDIASUBTYPE_RGB8;
- case 16 : return GetTrueColorType(pbmiHeader);
- case 24 : return MEDIASUBTYPE_RGB24;
- case 32 : return MEDIASUBTYPE_RGB32;
- }
- return GUID_NULL;
-}
-
-
-// Given a video bitmap subtype we return the number of bits per pixel it uses
-// We return a WORD bit count as thats what the BITMAPINFOHEADER uses. If the
-// GUID subtype is not found in the table we return an invalid USHRT_MAX
-
-STDAPI_(WORD) GetBitCount(const GUID *pSubtype)
-{
- ASSERT(pSubtype);
- const GUID *pMediaSubtype;
- INT iPosition = 0;
-
- // Scan the mapping list seeing if the source GUID matches any known
- // bitmap subtypes, the list is terminated by a GUID_NULL entry
-
- while (TRUE) {
- pMediaSubtype = BitCountMap[iPosition].pSubtype;
- if (IsEqualGUID(*pMediaSubtype,GUID_NULL)) {
- return USHRT_MAX;
- }
- if (IsEqualGUID(*pMediaSubtype,*pSubtype)) {
- return BitCountMap[iPosition].BitCount;
- }
- iPosition++;
- }
-}
-
-
-// Given a bitmap subtype we return a description name that can be used for
-// debug purposes. In a retail build this function still returns the names
-// If the subtype isn't found in the lookup table we return string UNKNOWN
-
-int LocateSubtype(const GUID *pSubtype)
-{
- ASSERT(pSubtype);
- const GUID *pMediaSubtype;
- INT iPosition = 0;
-
- // Scan the mapping list seeing if the source GUID matches any known
- // bitmap subtypes, the list is terminated by a GUID_NULL entry
-
- while (TRUE) {
- pMediaSubtype = BitCountMap[iPosition].pSubtype;
- if (IsEqualGUID(*pMediaSubtype,*pSubtype) ||
- IsEqualGUID(*pMediaSubtype,GUID_NULL)
- )
- {
- break;
- }
-
- iPosition++;
- }
-
- return iPosition;
-}
-
-
-
-STDAPI_(WCHAR *) GetSubtypeNameW(const GUID *pSubtype)
-{
- return BitCountMap[LocateSubtype(pSubtype)].wszName;
-}
-
-STDAPI_(CHAR *) GetSubtypeNameA(const GUID *pSubtype)
-{
- return BitCountMap[LocateSubtype(pSubtype)].pName;
-}
-
-#ifndef GetSubtypeName
-#error wxutil.h should have defined GetSubtypeName
-#endif
-#undef GetSubtypeName
-
-// this is here for people that linked to it directly; most people
-// would use the header file that picks the A or W version.
-STDAPI_(CHAR *) GetSubtypeName(const GUID *pSubtype)
-{
- return GetSubtypeNameA(pSubtype);
-}
-
-
-// The mechanism for describing a bitmap format is with the BITMAPINFOHEADER
-// This is really messy to deal with because it invariably has fields that
-// follow it holding bit fields, palettes and the rest. This function gives
-// the number of bytes required to hold a VIDEOINFO that represents it. This
-// count includes the prefix information (like the rcSource rectangle) the
-// BITMAPINFOHEADER field, and any other colour information on the end.
-//
-// WARNING If you want to copy a BITMAPINFOHEADER into a VIDEOINFO always make
-// sure that you use the HEADER macro because the BITMAPINFOHEADER field isn't
-// right at the start of the VIDEOINFO (there are a number of other fields),
-//
-// CopyMemory(HEADER(pVideoInfo),pbmi,sizeof(BITMAPINFOHEADER));
-//
-
-STDAPI_(LONG) GetBitmapFormatSize(const BITMAPINFOHEADER *pHeader)
-{
- // Everyone has this to start with this
- LONG Size = SIZE_PREHEADER + pHeader->biSize;
-
- ASSERT(pHeader->biSize >= sizeof(BITMAPINFOHEADER));
-
- // Does this format use a palette, if the number of colours actually used
- // is zero then it is set to the maximum that are allowed for that colour
- // depth (an example is 256 for eight bits). Truecolour formats may also
- // pass a palette with them in which case the used count is non zero
-
- // This would scare me.
- ASSERT(pHeader->biBitCount <= iPALETTE || pHeader->biClrUsed == 0);
-
- if (pHeader->biBitCount <= iPALETTE || pHeader->biClrUsed) {
- LONG Entries = (DWORD) 1 << pHeader->biBitCount;
- if (pHeader->biClrUsed) {
- Entries = pHeader->biClrUsed;
- }
- Size += Entries * sizeof(RGBQUAD);
- }
-
- // Truecolour formats may have a BI_BITFIELDS specifier for compression
- // type which means that room for three DWORDs should be allocated that
- // specify where in each pixel the RGB colour components may be found
-
- if (pHeader->biCompression == BI_BITFIELDS) {
- Size += SIZE_MASKS;
- }
-
- // A BITMAPINFO for a palettised image may also contain a palette map that
- // provides the information to map from a source palette to a destination
- // palette during a BitBlt for example, because this information is only
- // ever processed during drawing you don't normally store the palette map
- // nor have any way of knowing if it is present in the data structure
-
- return Size;
-}
-
-
-// Returns TRUE if the VIDEOINFO contains a palette
-
-STDAPI_(BOOL) ContainsPalette(const VIDEOINFOHEADER *pVideoInfo)
-{
- if (PALETTISED(pVideoInfo) == FALSE) {
- if (pVideoInfo->bmiHeader.biClrUsed == 0) {
- return FALSE;
- }
- }
- return TRUE;
-}
-
-
-// Return a pointer to the first entry in a palette
-
-STDAPI_(const RGBQUAD *) GetBitmapPalette(const VIDEOINFOHEADER *pVideoInfo)
-{
- if (pVideoInfo->bmiHeader.biCompression == BI_BITFIELDS) {
- return TRUECOLOR(pVideoInfo)->bmiColors;
- }
- return COLORS(pVideoInfo);
-}
diff --git a/dll/src/baseclasses/arithutil.cpp b/dll/src/baseclasses/arithutil.cpp
deleted file mode 100644
index cd0d127..0000000
--- a/dll/src/baseclasses/arithutil.cpp
+++ /dev/null
@@ -1,360 +0,0 @@
-//------------------------------------------------------------------------------
-// File: ArithUtil.cpp
-//
-// Desc: DirectShow base classes - implements helper classes for building
-// multimedia filters.
-//
-// Copyright (c) 1992-2004 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-#include <streams.h>
-
-//
-// Declare function from largeint.h we need so that PPC can build
-//
-
-//
-// Enlarged integer divide - 64-bits / 32-bits > 32-bits
-//
-
-#ifndef _X86_
-
-#define LLtoU64(x) (*(unsigned __int64*)(void*)(&(x)))
-
-__inline
-ULONG
-WINAPI
-EnlargedUnsignedDivide (
- IN ULARGE_INTEGER Dividend,
- IN ULONG Divisor,
- IN PULONG Remainder
- )
-{
- // return remainder if necessary
- if (Remainder != NULL)
- *Remainder = (ULONG)(LLtoU64(Dividend) % Divisor);
- return (ULONG)(LLtoU64(Dividend) / Divisor);
-}
-
-#else
-__inline
-ULONG
-WINAPI
-EnlargedUnsignedDivide (
- IN ULARGE_INTEGER Dividend,
- IN ULONG Divisor,
- IN PULONG Remainder
- )
-{
- ULONG ulResult;
- _asm {
- mov eax,Dividend.LowPart
- mov edx,Dividend.HighPart
- mov ecx,Remainder
- div Divisor
- or ecx,ecx
- jz short label
- mov [ecx],edx
-label:
- mov ulResult,eax
- }
- return ulResult;
-}
-#endif
-
-
-/* Arithmetic functions to help with time format conversions
-*/
-
-#ifdef _M_ALPHA
-// work around bug in version 12.00.8385 of the alpha compiler where
-// UInt32x32To64 sign-extends its arguments (?)
-#undef UInt32x32To64
-#define UInt32x32To64(a, b) (((ULONGLONG)((ULONG)(a)) & 0xffffffff) * ((ULONGLONG)((ULONG)(b)) & 0xffffffff))
-#endif
-
-/* Compute (a * b + d) / c */
-LONGLONG WINAPI llMulDiv(LONGLONG a, LONGLONG b, LONGLONG c, LONGLONG d)
-{
- /* Compute the absolute values to avoid signed arithmetic problems */
- ULARGE_INTEGER ua, ub;
- DWORDLONG uc;
-
- ua.QuadPart = (DWORDLONG)(a >= 0 ? a : -a);
- ub.QuadPart = (DWORDLONG)(b >= 0 ? b : -b);
- uc = (DWORDLONG)(c >= 0 ? c : -c);
- BOOL bSign = (a < 0) ^ (b < 0);
-
- /* Do long multiplication */
- ULARGE_INTEGER p[2];
- p[0].QuadPart = UInt32x32To64(ua.LowPart, ub.LowPart);
-
- /* This next computation cannot overflow into p[1].HighPart because
- the max number we can compute here is:
-
- (2 ** 32 - 1) * (2 ** 32 - 1) + // ua.LowPart * ub.LowPart
- (2 ** 32) * (2 ** 31) * (2 ** 32 - 1) * 2 // x.LowPart * y.HighPart * 2
-
- == 2 ** 96 - 2 ** 64 + (2 ** 64 - 2 ** 33 + 1)
- == 2 ** 96 - 2 ** 33 + 1
- < 2 ** 96
- */
-
- ULARGE_INTEGER x;
- x.QuadPart = UInt32x32To64(ua.LowPart, ub.HighPart) +
- UInt32x32To64(ua.HighPart, ub.LowPart) +
- p[0].HighPart;
- p[0].HighPart = x.LowPart;
- p[1].QuadPart = UInt32x32To64(ua.HighPart, ub.HighPart) + x.HighPart;
-
- if (d != 0) {
- ULARGE_INTEGER ud[2];
- if (bSign) {
- ud[0].QuadPart = (DWORDLONG)(-d);
- if (d > 0) {
- /* -d < 0 */
- ud[1].QuadPart = (DWORDLONG)(LONGLONG)-1;
- } else {
- ud[1].QuadPart = (DWORDLONG)0;
- }
- } else {
- ud[0].QuadPart = (DWORDLONG)d;
- if (d < 0) {
- ud[1].QuadPart = (DWORDLONG)(LONGLONG)-1;
- } else {
- ud[1].QuadPart = (DWORDLONG)0;
- }
- }
- /* Now do extended addition */
- ULARGE_INTEGER uliTotal;
-
- /* Add ls DWORDs */
- uliTotal.QuadPart = (DWORDLONG)ud[0].LowPart + p[0].LowPart;
- p[0].LowPart = uliTotal.LowPart;
-
- /* Propagate carry */
- uliTotal.LowPart = uliTotal.HighPart;
- uliTotal.HighPart = 0;
-
- /* Add 2nd most ls DWORDs */
- uliTotal.QuadPart += (DWORDLONG)ud[0].HighPart + p[0].HighPart;
- p[0].HighPart = uliTotal.LowPart;
-
- /* Propagate carry */
- uliTotal.LowPart = uliTotal.HighPart;
- uliTotal.HighPart = 0;
-
- /* Add MS DWORDLONGs - no carry expected */
- p[1].QuadPart += ud[1].QuadPart + uliTotal.QuadPart;
-
- /* Now see if we got a sign change from the addition */
- if ((LONG)p[1].HighPart < 0) {
- bSign = !bSign;
-
- /* Negate the current value (ugh!) */
- p[0].QuadPart = ~p[0].QuadPart;
- p[1].QuadPart = ~p[1].QuadPart;
- p[0].QuadPart += 1;
- p[1].QuadPart += (p[0].QuadPart == 0);
- }
- }
-
- /* Now for the division */
- if (c < 0) {
- bSign = !bSign;
- }
-
-
- /* This will catch c == 0 and overflow */
- if (uc <= p[1].QuadPart) {
- return bSign ? (LONGLONG)0x8000000000000000 :
- (LONGLONG)0x7FFFFFFFFFFFFFFF;
- }
-
- DWORDLONG ullResult;
-
- /* Do the division */
- /* If the dividend is a DWORD_LONG use the compiler */
- if (p[1].QuadPart == 0) {
- ullResult = p[0].QuadPart / uc;
- return bSign ? -(LONGLONG)ullResult : (LONGLONG)ullResult;
- }
-
- /* If the divisor is a DWORD then its simpler */
- ULARGE_INTEGER ulic;
- ulic.QuadPart = uc;
- if (ulic.HighPart == 0) {
- ULARGE_INTEGER uliDividend;
- ULARGE_INTEGER uliResult;
- DWORD dwDivisor = (DWORD)uc;
- // ASSERT(p[1].HighPart == 0 && p[1].LowPart < dwDivisor);
- uliDividend.HighPart = p[1].LowPart;
- uliDividend.LowPart = p[0].HighPart;
-#ifndef USE_LARGEINT
- uliResult.HighPart = (DWORD)(uliDividend.QuadPart / dwDivisor);
- p[0].HighPart = (DWORD)(uliDividend.QuadPart % dwDivisor);
- uliResult.LowPart = 0;
- uliResult.QuadPart = p[0].QuadPart / dwDivisor + uliResult.QuadPart;
-#else
- /* NOTE - this routine will take exceptions if
- the result does not fit in a DWORD
- */
- if (uliDividend.QuadPart >= (DWORDLONG)dwDivisor) {
- uliResult.HighPart = EnlargedUnsignedDivide(
- uliDividend,
- dwDivisor,
- &p[0].HighPart);
- } else {
- uliResult.HighPart = 0;
- }
- uliResult.LowPart = EnlargedUnsignedDivide(
- p[0],
- dwDivisor,
- NULL);
-#endif
- return bSign ? -(LONGLONG)uliResult.QuadPart :
- (LONGLONG)uliResult.QuadPart;
- }
-
-
- ullResult = 0;
-
- /* OK - do long division */
- for (int i = 0; i < 64; i++) {
- ullResult <<= 1;
-
- /* Shift 128 bit p left 1 */
- p[1].QuadPart <<= 1;
- if ((p[0].HighPart & 0x80000000) != 0) {
- p[1].LowPart++;
- }
- p[0].QuadPart <<= 1;
-
- /* Compare */
- if (uc <= p[1].QuadPart) {
- p[1].QuadPart -= uc;
- ullResult += 1;
- }
- }
-
- return bSign ? - (LONGLONG)ullResult : (LONGLONG)ullResult;
-}
-
-LONGLONG WINAPI Int64x32Div32(LONGLONG a, LONG b, LONG c, LONG d)
-{
- ULARGE_INTEGER ua;
- DWORD ub;
- DWORD uc;
-
- /* Compute the absolute values to avoid signed arithmetic problems */
- ua.QuadPart = (DWORDLONG)(a >= 0 ? a : -a);
- ub = (DWORD)(b >= 0 ? b : -b);
- uc = (DWORD)(c >= 0 ? c : -c);
- BOOL bSign = (a < 0) ^ (b < 0);
-
- /* Do long multiplication */
- ULARGE_INTEGER p0;
- DWORD p1;
- p0.QuadPart = UInt32x32To64(ua.LowPart, ub);
-
- if (ua.HighPart != 0) {
- ULARGE_INTEGER x;
- x.QuadPart = UInt32x32To64(ua.HighPart, ub) + p0.HighPart;
- p0.HighPart = x.LowPart;
- p1 = x.HighPart;
- } else {
- p1 = 0;
- }
-
- if (d != 0) {
- ULARGE_INTEGER ud0;
- DWORD ud1;
-
- if (bSign) {
- //
- // Cast d to LONGLONG first otherwise -0x80000000 sign extends
- // incorrectly
- //
- ud0.QuadPart = (DWORDLONG)(-(LONGLONG)d);
- if (d > 0) {
- /* -d < 0 */
- ud1 = (DWORD)-1;
- } else {
- ud1 = (DWORD)0;
- }
- } else {
- ud0.QuadPart = (DWORDLONG)d;
- if (d < 0) {
- ud1 = (DWORD)-1;
- } else {
- ud1 = (DWORD)0;
- }
- }
- /* Now do extended addition */
- ULARGE_INTEGER uliTotal;
-
- /* Add ls DWORDs */
- uliTotal.QuadPart = (DWORDLONG)ud0.LowPart + p0.LowPart;
- p0.LowPart = uliTotal.LowPart;
-
- /* Propagate carry */
- uliTotal.LowPart = uliTotal.HighPart;
- uliTotal.HighPart = 0;
-
- /* Add 2nd most ls DWORDs */
- uliTotal.QuadPart += (DWORDLONG)ud0.HighPart + p0.HighPart;
- p0.HighPart = uliTotal.LowPart;
-
- /* Add MS DWORDLONGs - no carry expected */
- p1 += ud1 + uliTotal.HighPart;
-
- /* Now see if we got a sign change from the addition */
- if ((LONG)p1 < 0) {
- bSign = !bSign;
-
- /* Negate the current value (ugh!) */
- p0.QuadPart = ~p0.QuadPart;
- p1 = ~p1;
- p0.QuadPart += 1;
- p1 += (p0.QuadPart == 0);
- }
- }
-
- /* Now for the division */
- if (c < 0) {
- bSign = !bSign;
- }
-
-
- /* This will catch c == 0 and overflow */
- if (uc <= p1) {
- return bSign ? (LONGLONG)0x8000000000000000 :
- (LONGLONG)0x7FFFFFFFFFFFFFFF;
- }
-
- /* Do the division */
-
- /* If the divisor is a DWORD then its simpler */
- ULARGE_INTEGER uliDividend;
- ULARGE_INTEGER uliResult;
- DWORD dwDivisor = uc;
- uliDividend.HighPart = p1;
- uliDividend.LowPart = p0.HighPart;
- /* NOTE - this routine will take exceptions if
- the result does not fit in a DWORD
- */
- if (uliDividend.QuadPart >= (DWORDLONG)dwDivisor) {
- uliResult.HighPart = EnlargedUnsignedDivide(
- uliDividend,
- dwDivisor,
- &p0.HighPart);
- } else {
- uliResult.HighPart = 0;
- }
- uliResult.LowPart = EnlargedUnsignedDivide(
- p0,
- dwDivisor,
- NULL);
- return bSign ? -(LONGLONG)uliResult.QuadPart :
- (LONGLONG)uliResult.QuadPart;
-}
diff --git a/dll/src/baseclasses/cache.h b/dll/src/baseclasses/cache.h
deleted file mode 100644
index 0a807c2..0000000
--- a/dll/src/baseclasses/cache.h
+++ /dev/null
@@ -1,74 +0,0 @@
-//------------------------------------------------------------------------------
-// File: Cache.h
-//
-// Desc: DirectShow base classes - efines a non-MFC generic cache class.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-/* This class implements a simple cache. A cache object is instantiated
- with the number of items it is to hold. An item is a pointer to an
- object derived from CBaseObject (helps reduce memory leaks). The cache
- can then have objects added to it and removed from it. The cache size
- is fixed at construction time and may therefore run out or be flooded.
- If it runs out it returns a NULL pointer, if it fills up it also returns
- a NULL pointer instead of a pointer to the object just inserted */
-
-/* Making these classes inherit from CBaseObject does nothing for their
- functionality but it allows us to check there are no memory leaks */
-
-/* WARNING Be very careful when using this class, what it lets you do is
- store and retrieve objects so that you can minimise object creation
- which in turns improves efficiency. However the object you store is
- exactly the same as the object you get back which means that it short
- circuits the constructor initialisation phase. This means any class
- variables the object has (eg pointers) are highly likely to be invalid.
- Therefore ensure you reinitialise the object before using it again */
-
-
-#ifndef __CACHE__
-#define __CACHE__
-
-
-class CCache : CBaseObject {
-
- /* Make copy constructor and assignment operator inaccessible */
-
- CCache(const CCache &refCache);
- CCache &operator=(const CCache &refCache);
-
-private:
-
- /* These are initialised in the constructor. The first variable points to
- an array of pointers, each of which points to a CBaseObject derived
- object. The m_iCacheSize is the static fixed size for the cache and the
- m_iUsed defines the number of places filled with objects at any time.
- We fill the array of pointers from the start (ie m_ppObjects[0] first)
- and then only add and remove objects from the end position, so in this
- respect the array of object pointers should be treated as a stack */
-
- CBaseObject **m_ppObjects;
- const INT m_iCacheSize;
- INT m_iUsed;
-
-public:
-
- CCache(__in_opt LPCTSTR pName,INT iItems);
- virtual ~CCache();
-
- /* Add an item to the cache */
- CBaseObject *AddToCache(__in CBaseObject *pObject);
-
- /* Remove an item from the cache */
- CBaseObject *RemoveFromCache();
-
- /* Delete all the objects held in the cache */
- void RemoveAll(void);
-
- /* Return the cache size which is set during construction */
- INT GetCacheSize(void) const {return m_iCacheSize;};
-};
-
-#endif /* __CACHE__ */
-
diff --git a/dll/src/baseclasses/checkbmi.h b/dll/src/baseclasses/checkbmi.h
deleted file mode 100644
index 7287967..0000000
--- a/dll/src/baseclasses/checkbmi.h
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright (c) 1992 - 1997 Microsoft Corporation. All Rights Reserved.
-
-#ifndef _CHECKBMI_H_
-#define _CHECKBMI_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// Helper
-__inline BOOL MultiplyCheckOverflow(DWORD a, DWORD b, __deref_out_range(==, a * b) DWORD *pab) {
- *pab = a * b;
- if ((a == 0) || (((*pab) / a) == b)) {
- return TRUE;
- }
- return FALSE;
-}
-
-
-// Checks if the fields in a BITMAPINFOHEADER won't generate
-// overlows and buffer overruns
-// This is not a complete check and does not guarantee code using this structure will be secure
-// from attack
-// Bugs this is guarding against:
-// 1. Total structure size calculation overflowing
-// 2. biClrUsed > 256 for 8-bit palettized content
-// 3. Total bitmap size in bytes overflowing
-// 4. biSize < size of the base structure leading to accessessing random memory
-// 5. Total structure size exceeding know size of data
-//
-
-__success(return != 0) __inline BOOL ValidateBitmapInfoHeader(
- const BITMAPINFOHEADER *pbmi, // pointer to structure to check
- __out_range(>=, sizeof(BITMAPINFOHEADER)) DWORD cbSize // size of memory block containing structure
-)
-{
- DWORD dwWidthInBytes;
- DWORD dwBpp;
- DWORD dwWidthInBits;
- DWORD dwHeight;
- DWORD dwSizeImage;
- DWORD dwClrUsed;
-
- // Reject bad parameters - do the size check first to avoid reading bad memory
- if (cbSize < sizeof(BITMAPINFOHEADER) ||
- pbmi->biSize < sizeof(BITMAPINFOHEADER) ||
- pbmi->biSize > 4096) {
- return FALSE;
- }
-
- // Reject 0 size
- if (pbmi->biWidth == 0 || pbmi->biHeight == 0) {
- return FALSE;
- }
-
- // Use bpp of 200 for validating against further overflows if not set for compressed format
- dwBpp = 200;
-
- if (pbmi->biBitCount > dwBpp) {
- return FALSE;
- }
-
- // Strictly speaking abs can overflow so cast explicitly to DWORD
- dwHeight = (DWORD)abs(pbmi->biHeight);
-
- if (!MultiplyCheckOverflow(dwBpp, (DWORD)pbmi->biWidth, &dwWidthInBits)) {
- return FALSE;
- }
-
- // Compute correct width in bytes - rounding up to 4 bytes
- dwWidthInBytes = (dwWidthInBits / 8 + 3) & ~3;
-
- if (!MultiplyCheckOverflow(dwWidthInBytes, dwHeight, &dwSizeImage)) {
- return FALSE;
- }
-
- // Fail if total size is 0 - this catches indivual quantities being 0
- // Also don't allow huge values > 1GB which might cause arithmetic
- // errors for users
- if (dwSizeImage > 0x40000000 ||
- pbmi->biSizeImage > 0x40000000) {
- return FALSE;
- }
-
- // Fail if biClrUsed looks bad
- if (pbmi->biClrUsed > 256) {
- return FALSE;
- }
-
- if (pbmi->biClrUsed == 0 && pbmi->biBitCount <= 8 && pbmi->biBitCount > 0) {
- dwClrUsed = (1 << pbmi->biBitCount);
- } else {
- dwClrUsed = pbmi->biClrUsed;
- }
-
- // Check total size
- if (cbSize < pbmi->biSize + dwClrUsed * sizeof(RGBQUAD) +
- (pbmi->biCompression == BI_BITFIELDS ? 3 * sizeof(DWORD) : 0)) {
- return FALSE;
- }
-
- // If it is RGB validate biSizeImage - lots of code assumes the size is correct
- if (pbmi->biCompression == BI_RGB || pbmi->biCompression == BI_BITFIELDS) {
- if (pbmi->biSizeImage != 0) {
- DWORD dwBits = (DWORD)pbmi->biWidth * (DWORD)pbmi->biBitCount;
- DWORD dwWidthInBytes = ((DWORD)((dwBits+31) & (~31)) / 8);
- DWORD dwTotalSize = (DWORD)abs(pbmi->biHeight) * dwWidthInBytes;
- if (dwTotalSize > pbmi->biSizeImage) {
- return FALSE;
- }
- }
- }
- return TRUE;
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // _CHECKBMI_H_
diff --git a/dll/src/baseclasses/combase.cpp b/dll/src/baseclasses/combase.cpp
deleted file mode 100644
index ec62a88..0000000
--- a/dll/src/baseclasses/combase.cpp
+++ /dev/null
@@ -1,265 +0,0 @@
-//------------------------------------------------------------------------------
-// File: ComBase.cpp
-//
-// Desc: DirectShow base classes - implements class hierarchy for creating
-// COM objects.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-#include <streams.h>
-#pragma warning( disable : 4514 ) // Disable warnings re unused inline functions
-
-
-/* Define the static member variable */
-
-LONG CBaseObject::m_cObjects = 0;
-
-
-/* Constructor */
-
-CBaseObject::CBaseObject(__in_opt LPCTSTR pName)
-{
- /* Increment the number of active objects */
- InterlockedIncrement(&m_cObjects);
-
-#ifdef DEBUG
-
-#ifdef UNICODE
- m_dwCookie = DbgRegisterObjectCreation(0, pName);
-#else
- m_dwCookie = DbgRegisterObjectCreation(pName, 0);
-#endif
-
-#endif
-}
-
-#ifdef UNICODE
-CBaseObject::CBaseObject(const char *pName)
-{
- /* Increment the number of active objects */
- InterlockedIncrement(&m_cObjects);
-
-#ifdef DEBUG
- m_dwCookie = DbgRegisterObjectCreation(pName, 0);
-#endif
-}
-#endif
-
-HINSTANCE hlibOLEAut32;
-
-/* Destructor */
-
-CBaseObject::~CBaseObject()
-{
- /* Decrement the number of objects active */
- if (InterlockedDecrement(&m_cObjects) == 0) {
- if (hlibOLEAut32) {
- FreeLibrary(hlibOLEAut32);
-
- hlibOLEAut32 = 0;
- }
- };
-
-
-#ifdef DEBUG
- DbgRegisterObjectDestruction(m_dwCookie);
-#endif
-}
-
-static const TCHAR szOle32Aut[] = TEXT("OleAut32.dll");
-
-HINSTANCE LoadOLEAut32()
-{
- if (hlibOLEAut32 == 0) {
-
- hlibOLEAut32 = LoadLibrary(szOle32Aut);
- }
-
- return hlibOLEAut32;
-}
-
-
-/* Constructor */
-
-// We know we use "this" in the initialization list, we also know we don't modify *phr.
-#pragma warning( disable : 4355 4100 )
-CUnknown::CUnknown(__in_opt LPCTSTR pName, __in_opt LPUNKNOWN pUnk)
-: CBaseObject(pName)
-/* Start the object with a reference count of zero - when the */
-/* object is queried for it's first interface this may be */
-/* incremented depending on whether or not this object is */
-/* currently being aggregated upon */
-, m_cRef(0)
-/* Set our pointer to our IUnknown interface. */
-/* If we have an outer, use its, otherwise use ours. */
-/* This pointer effectivly points to the owner of */
-/* this object and can be accessed by the GetOwner() method. */
-, m_pUnknown( pUnk != 0 ? pUnk : reinterpret_cast<LPUNKNOWN>( static_cast<PNDUNKNOWN>(this) ) )
- /* Why the double cast? Well, the inner cast is a type-safe cast */
- /* to pointer to a type from which we inherit. The second is */
- /* type-unsafe but works because INonDelegatingUnknown "behaves */
- /* like" IUnknown. (Only the names on the methods change.) */
-{
- // Everything we need to do has been done in the initializer list
-}
-
-// This does the same as above except it has a useless HRESULT argument
-// use the previous constructor, this is just left for compatibility...
-CUnknown::CUnknown(__in_opt LPCTSTR pName, __in_opt LPUNKNOWN pUnk, __inout_opt HRESULT *phr) :
- CBaseObject(pName),
- m_cRef(0),
- m_pUnknown( pUnk != 0 ? pUnk : reinterpret_cast<LPUNKNOWN>( static_cast<PNDUNKNOWN>(this) ) )
-{
-}
-
-#ifdef UNICODE
-CUnknown::CUnknown(__in_opt LPCSTR pName, __in_opt LPUNKNOWN pUnk)
-: CBaseObject(pName), m_cRef(0),
- m_pUnknown( pUnk != 0 ? pUnk : reinterpret_cast<LPUNKNOWN>( static_cast<PNDUNKNOWN>(this) ) )
-{ }
-
-CUnknown::CUnknown(__in_opt LPCSTR pName, __in_opt LPUNKNOWN pUnk, __inout_opt HRESULT *phr) :
- CBaseObject(pName), m_cRef(0),
- m_pUnknown( pUnk != 0 ? pUnk : reinterpret_cast<LPUNKNOWN>( static_cast<PNDUNKNOWN>(this) ) )
-{ }
-
-#endif
-
-#pragma warning( default : 4355 4100 )
-
-
-/* QueryInterface */
-
-STDMETHODIMP CUnknown::NonDelegatingQueryInterface(REFIID riid, __deref_out void ** ppv)
-{
- CheckPointer(ppv,E_POINTER);
- ValidateReadWritePtr(ppv,sizeof(PVOID));
-
- /* We know only about IUnknown */
-
- if (riid == IID_IUnknown) {
- GetInterface((LPUNKNOWN) (PNDUNKNOWN) this, ppv);
- return NOERROR;
- } else {
- *ppv = NULL;
- return E_NOINTERFACE;
- }
-}
-
-/* We have to ensure that we DON'T use a max macro, since these will typically */
-/* lead to one of the parameters being evaluated twice. Since we are worried */
-/* about concurrency, we can't afford to access the m_cRef twice since we can't */
-/* afford to run the risk that its value having changed between accesses. */
-
-template<class T> inline static T ourmax( const T & a, const T & b )
-{
- return a > b ? a : b;
-}
-
-/* AddRef */
-
-STDMETHODIMP_(ULONG) CUnknown::NonDelegatingAddRef()
-{
- LONG lRef = InterlockedIncrement( &m_cRef );
- ASSERT(lRef > 0);
- DbgLog((LOG_MEMORY,3,TEXT(" Obj %d ref++ = %d"),
- m_dwCookie, m_cRef));
- return ourmax(ULONG(m_cRef), 1ul);
-}
-
-
-/* Release */
-
-STDMETHODIMP_(ULONG) CUnknown::NonDelegatingRelease()
-{
- /* If the reference count drops to zero delete ourselves */
-
- LONG lRef = InterlockedDecrement( &m_cRef );
- ASSERT(lRef >= 0);
-
- DbgLog((LOG_MEMORY,3,TEXT(" Object %d ref-- = %d"),
- m_dwCookie, m_cRef));
- if (lRef == 0) {
-
- // COM rules say we must protect against re-entrancy.
- // If we are an aggregator and we hold our own interfaces
- // on the aggregatee, the QI for these interfaces will
- // addref ourselves. So after doing the QI we must release
- // a ref count on ourselves. Then, before releasing the
- // private interface, we must addref ourselves. When we do
- // this from the destructor here it will result in the ref
- // count going to 1 and then back to 0 causing us to
- // re-enter the destructor. Hence we add an extra refcount here
- // once we know we will delete the object.
- // for an example aggregator see filgraph\distrib.cpp.
-
- m_cRef++;
-
- delete this;
- return ULONG(0);
- } else {
- // Don't touch m_cRef again even in this leg as the object
- // may have just been released on another thread too
- return ourmax(ULONG(lRef), 1ul);
- }
-}
-
-
-/* Return an interface pointer to a requesting client
- performing a thread safe AddRef as necessary */
-
-STDAPI GetInterface(LPUNKNOWN pUnk, __out void **ppv)
-{
- CheckPointer(ppv, E_POINTER);
- *ppv = pUnk;
- pUnk->AddRef();
- return NOERROR;
-}
-
-
-/* Compares two interfaces and returns TRUE if they are on the same object */
-
-BOOL WINAPI IsEqualObject(IUnknown *pFirst, IUnknown *pSecond)
-{
- /* Different objects can't have the same interface pointer for
- any interface
- */
- if (pFirst == pSecond) {
- return TRUE;
- }
- /* OK - do it the hard way - check if they have the same
- IUnknown pointers - a single object can only have one of these
- */
- LPUNKNOWN pUnknown1; // Retrieve the IUnknown interface
- LPUNKNOWN pUnknown2; // Retrieve the other IUnknown interface
- HRESULT hr; // General OLE return code
-
- ASSERT(pFirst);
- ASSERT(pSecond);
-
- /* See if the IUnknown pointers match */
-
- hr = pFirst->QueryInterface(IID_IUnknown,(void **) &pUnknown1);
- if (FAILED(hr)) {
- return FALSE;
- }
- ASSERT(pUnknown1);
-
- /* Release the extra interface we hold */
-
- pUnknown1->Release();
-
- hr = pSecond->QueryInterface(IID_IUnknown,(void **) &pUnknown2);
- if (FAILED(hr)) {
- return FALSE;
- }
- ASSERT(pUnknown2);
-
- /* Release the extra interface we hold */
-
- pUnknown2->Release();
- return (pUnknown1 == pUnknown2);
-}
-
diff --git a/dll/src/baseclasses/combase.h b/dll/src/baseclasses/combase.h
deleted file mode 100644
index 65b0fcc..0000000
--- a/dll/src/baseclasses/combase.h
+++ /dev/null
@@ -1,300 +0,0 @@
-//------------------------------------------------------------------------------
-// File: ComBase.h
-//
-// Desc: DirectShow base classes - defines a class hierarchy for creating
-// COM objects.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-/*
-
-a. Derive your COM object from CUnknown
-
-b. Make a static CreateInstance function that takes an LPUNKNOWN, an HRESULT *
- and a TCHAR *. The LPUNKNOWN defines the object to delegate IUnknown calls
- to. The HRESULT * allows error codes to be passed around constructors and
- the TCHAR * is a descriptive name that can be printed on the debugger.
-
- It is important that constructors only change the HRESULT * if they have
- to set an ERROR code, if it was successful then leave it alone or you may
- overwrite an error code from an object previously created.
-
- When you call a constructor the descriptive name should be in static store
- as we do not copy the string. To stop large amounts of memory being used
- in retail builds by all these static strings use the NAME macro,
-
- CMyFilter = new CImplFilter(NAME("My filter"),pUnknown,phr);
- if (FAILED(hr)) {
- return hr;
- }
-
- In retail builds NAME(_x_) compiles to NULL, the base CBaseObject class
- knows not to do anything with objects that don't have a name.
-
-c. Have a constructor for your object that passes the LPUNKNOWN, HRESULT * and
- TCHAR * to the CUnknown constructor. You can set the HRESULT if you have an
- error, or just simply pass it through to the constructor.
-
- The object creation will fail in the class factory if the HRESULT indicates
- an error (ie FAILED(HRESULT) == TRUE)
-
-d. Create a FactoryTemplate with your object's class id and CreateInstance
- function.
-
-Then (for each interface) either
-
-Multiple inheritance
-
-1. Also derive it from ISomeInterface
-2. Include DECLARE_IUNKNOWN in your class definition to declare
- implementations of QueryInterface, AddRef and Release that
- call the outer unknown
-3. Override NonDelegatingQueryInterface to expose ISomeInterface by
- code something like
-
- if (riid == IID_ISomeInterface) {
- return GetInterface((ISomeInterface *) this, ppv);
- } else {
- return CUnknown::NonDelegatingQueryInterface(riid, ppv);
- }
-
-4. Declare and implement the member functions of ISomeInterface.
-
-or: Nested interfaces
-
-1. Declare a class derived from CUnknown
-2. Include DECLARE_IUNKNOWN in your class definition
-3. Override NonDelegatingQueryInterface to expose ISomeInterface by
- code something like
-
- if (riid == IID_ISomeInterface) {
- return GetInterface((ISomeInterface *) this, ppv);
- } else {
- return CUnknown::NonDelegatingQueryInterface(riid, ppv);
- }
-
-4. Implement the member functions of ISomeInterface. Use GetOwner() to
- access the COM object class.
-
-And in your COM object class:
-
-5. Make the nested class a friend of the COM object class, and declare
- an instance of the nested class as a member of the COM object class.
-
- NOTE that because you must always pass the outer unknown and an hResult
- to the CUnknown constructor you cannot use a default constructor, in
- other words you will have to make the member variable a pointer to the
- class and make a NEW call in your constructor to actually create it.
-
-6. override the NonDelegatingQueryInterface with code like this:
-
- if (riid == IID_ISomeInterface) {
- return m_pImplFilter->
- NonDelegatingQueryInterface(IID_ISomeInterface, ppv);
- } else {
- return CUnknown::NonDelegatingQueryInterface(riid, ppv);
- }
-
-You can have mixed classes which support some interfaces via multiple
-inheritance and some via nested classes
-
-*/
-
-#ifndef __COMBASE__
-#define __COMBASE__
-
-// Filter Setup data structures no defined in axextend.idl
-
-typedef REGPINTYPES
-AMOVIESETUP_MEDIATYPE, * PAMOVIESETUP_MEDIATYPE, * FAR LPAMOVIESETUP_MEDIATYPE;
-
-typedef REGFILTERPINS
-AMOVIESETUP_PIN, * PAMOVIESETUP_PIN, * FAR LPAMOVIESETUP_PIN;
-
-typedef struct _AMOVIESETUP_FILTER
-{
- const CLSID * clsID;
- const WCHAR * strName;
- DWORD dwMerit;
- UINT nPins;
- const AMOVIESETUP_PIN * lpPin;
-}
-AMOVIESETUP_FILTER, * PAMOVIESETUP_FILTER, * FAR LPAMOVIESETUP_FILTER;
-
-/* The DLLENTRY module initialises the module handle on loading */
-
-extern HINSTANCE g_hInst;
-
-/* Version of IUnknown that is renamed to allow a class to support both
- non delegating and delegating IUnknowns in the same COM object */
-
-#ifndef INONDELEGATINGUNKNOWN_DEFINED
-DECLARE_INTERFACE(INonDelegatingUnknown)
-{
- STDMETHOD(NonDelegatingQueryInterface) (THIS_ REFIID, LPVOID *) PURE;
- STDMETHOD_(ULONG, NonDelegatingAddRef)(THIS) PURE;
- STDMETHOD_(ULONG, NonDelegatingRelease)(THIS) PURE;
-};
-#define INONDELEGATINGUNKNOWN_DEFINED
-#endif
-
-typedef INonDelegatingUnknown *PNDUNKNOWN;
-
-
-/* This is the base object class that supports active object counting. As
- part of the debug facilities we trace every time a C++ object is created
- or destroyed. The name of the object has to be passed up through the class
- derivation list during construction as you cannot call virtual functions
- in the constructor. The downside of all this is that every single object
- constructor has to take an object name parameter that describes it */
-
-class CBaseObject
-{
-
-private:
-
- // Disable the copy constructor and assignment by default so you will get
- // compiler errors instead of unexpected behaviour if you pass objects
- // by value or assign objects.
- CBaseObject(const CBaseObject& objectSrc); // no implementation
- void operator=(const CBaseObject& objectSrc); // no implementation
-
-private:
- static LONG m_cObjects; /* Total number of objects active */
-
-protected:
-#ifdef DEBUG
- DWORD m_dwCookie; /* Cookie identifying this object */
-#endif
-
-
-public:
-
- /* These increment and decrement the number of active objects */
-
- CBaseObject(__in_opt LPCTSTR pName);
-#ifdef UNICODE
- CBaseObject(__in_opt LPCSTR pName);
-#endif
- ~CBaseObject();
-
- /* Call this to find if there are any CUnknown derived objects active */
-
- static LONG ObjectsActive() {
- return m_cObjects;
- };
-};
-
-
-/* An object that supports one or more COM interfaces will be based on
- this class. It supports counting of total objects for DLLCanUnloadNow
- support, and an implementation of the core non delegating IUnknown */
-
-class AM_NOVTABLE CUnknown : public INonDelegatingUnknown,
- public CBaseObject
-{
-private:
- const LPUNKNOWN m_pUnknown; /* Owner of this object */
-
-protected: /* So we can override NonDelegatingRelease() */
- volatile LONG m_cRef; /* Number of reference counts */
-
-public:
-
- CUnknown(__in_opt LPCTSTR pName, __in_opt LPUNKNOWN pUnk);
- virtual ~CUnknown() {};
-
- // This is redundant, just use the other constructor
- // as we never touch the HRESULT in this anyway
- CUnknown(__in_opt LPCTSTR Name, __in_opt LPUNKNOWN pUnk, __inout_opt HRESULT *phr);
-#ifdef UNICODE
- CUnknown(__in_opt LPCSTR pName, __in_opt LPUNKNOWN pUnk);
- CUnknown(__in_opt LPCSTR pName, __in_opt LPUNKNOWN pUnk,__inout_opt HRESULT *phr);
-#endif
-
- /* Return the owner of this object */
-
- LPUNKNOWN GetOwner() const {
- return m_pUnknown;
- };
-
- /* Called from the class factory to create a new instance, it is
- pure virtual so it must be overriden in your derived class */
-
- /* static CUnknown *CreateInstance(LPUNKNOWN, HRESULT *) */
-
- /* Non delegating unknown implementation */
-
- STDMETHODIMP NonDelegatingQueryInterface(REFIID, __deref_out void **);
- STDMETHODIMP_(ULONG) NonDelegatingAddRef();
- STDMETHODIMP_(ULONG) NonDelegatingRelease();
-};
-
-/* Return an interface pointer to a requesting client
- performing a thread safe AddRef as necessary */
-
-STDAPI GetInterface(LPUNKNOWN pUnk, __out void **ppv);
-
-/* A function that can create a new COM object */
-
-typedef CUnknown *(CALLBACK *LPFNNewCOMObject)(__in_opt LPUNKNOWN pUnkOuter, __inout_opt HRESULT *phr);
-
-/* A function (can be NULL) which is called from the DLL entrypoint
- routine for each factory template:
-
- bLoading - TRUE on DLL load, FALSE on DLL unload
- rclsid - the m_ClsID of the entry
-*/
-typedef void (CALLBACK *LPFNInitRoutine)(BOOL bLoading, const CLSID *rclsid);
-
-/* Create one of these per object class in an array so that
- the default class factory code can create new instances */
-
-class CFactoryTemplate {
-
-public:
-
- const WCHAR * m_Name;
- const CLSID * m_ClsID;
- LPFNNewCOMObject m_lpfnNew;
- LPFNInitRoutine m_lpfnInit;
- const AMOVIESETUP_FILTER * m_pAMovieSetup_Filter;
-
- BOOL IsClassID(REFCLSID rclsid) const {
- return (IsEqualCLSID(*m_ClsID,rclsid));
- };
-
- CUnknown *CreateInstance(__inout_opt LPUNKNOWN pUnk, __inout_opt HRESULT *phr) const {
- CheckPointer(phr,NULL);
- return m_lpfnNew(pUnk, phr);
- };
-};
-
-
-/* You must override the (pure virtual) NonDelegatingQueryInterface to return
- interface pointers (using GetInterface) to the interfaces your derived
- class supports (the default implementation only supports IUnknown) */
-
-#define DECLARE_IUNKNOWN \
- STDMETHODIMP QueryInterface(REFIID riid, __deref_out void **ppv) { \
- return GetOwner()->QueryInterface(riid,ppv); \
- }; \
- STDMETHODIMP_(ULONG) AddRef() { \
- return GetOwner()->AddRef(); \
- }; \
- STDMETHODIMP_(ULONG) Release() { \
- return GetOwner()->Release(); \
- };
-
-
-
-HINSTANCE LoadOLEAut32();
-
-
-#endif /* __COMBASE__ */
-
-
-
-
diff --git a/dll/src/baseclasses/cprop.cpp b/dll/src/baseclasses/cprop.cpp
deleted file mode 100644
index 7bd76b4..0000000
--- a/dll/src/baseclasses/cprop.cpp
+++ /dev/null
@@ -1,383 +0,0 @@
-//------------------------------------------------------------------------------
-// File: CProp.cpp
-//
-// Desc: DirectShow base classes - implements CBasePropertyPage class.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-#include <streams.h>
-
-// Constructor for the base property page class. As described in the header
-// file we must be initialised with dialog and title resource identifiers.
-// The class supports IPropertyPage and overrides AddRef and Release calls
-// to keep track of the reference counts. When the last count is released
-// we call SetPageSite(NULL) and SetObjects(0,NULL) to release interfaces
-// previously obtained by the property page when it had SetObjects called
-
-CBasePropertyPage::CBasePropertyPage(__in_opt LPCTSTR pName, // Debug only name
- __inout_opt LPUNKNOWN pUnk, // COM Delegator
- int DialogId, // Resource ID
- int TitleId) : // To get tital
- CUnknown(pName,pUnk),
- m_DialogId(DialogId),
- m_TitleId(TitleId),
- m_hwnd(NULL),
- m_Dlg(NULL),
- m_pPageSite(NULL),
- m_bObjectSet(FALSE),
- m_bDirty(FALSE)
-{
-}
-
-#ifdef UNICODE
-CBasePropertyPage::CBasePropertyPage(__in_opt LPCSTR pName, // Debug only name
- __inout_opt LPUNKNOWN pUnk, // COM Delegator
- int DialogId, // Resource ID
- int TitleId) : // To get tital
- CUnknown(pName,pUnk),
- m_DialogId(DialogId),
- m_TitleId(TitleId),
- m_hwnd(NULL),
- m_Dlg(NULL),
- m_pPageSite(NULL),
- m_bObjectSet(FALSE),
- m_bDirty(FALSE)
-{
-}
-#endif
-
-// Increment our reference count
-
-STDMETHODIMP_(ULONG) CBasePropertyPage::NonDelegatingAddRef()
-{
- LONG lRef = InterlockedIncrement(&m_cRef);
- ASSERT(lRef > 0);
- return max(ULONG(m_cRef),1ul);
-}
-
-
-// Release a reference count and protect against reentrancy
-
-STDMETHODIMP_(ULONG) CBasePropertyPage::NonDelegatingRelease()
-{
- // If the reference count drops to zero delete ourselves
-
- LONG lRef = InterlockedDecrement(&m_cRef);
- if (lRef == 0) {
- m_cRef++;
- SetPageSite(NULL);
- SetObjects(0,NULL);
- delete this;
- return ULONG(0);
- } else {
- // Don't touch m_cRef again here!
- return max(ULONG(lRef),1ul);
- }
-}
-
-
-// Expose our IPropertyPage interface
-
-STDMETHODIMP
-CBasePropertyPage::NonDelegatingQueryInterface(REFIID riid,__deref_out void **ppv)
-{
- if (riid == IID_IPropertyPage) {
- return GetInterface((IPropertyPage *)this,ppv);
- } else {
- return CUnknown::NonDelegatingQueryInterface(riid,ppv);
- }
-}
-
-
-// Get the page info so that the page site can size itself
-
-STDMETHODIMP CBasePropertyPage::GetPageInfo(__out LPPROPPAGEINFO pPageInfo)
-{
- CheckPointer(pPageInfo,E_POINTER);
- WCHAR wszTitle[STR_MAX_LENGTH];
- WideStringFromResource(wszTitle,m_TitleId);
-
- // Allocate dynamic memory for the property page title
-
- LPOLESTR pszTitle;
- HRESULT hr = AMGetWideString(wszTitle, &pszTitle);
- if (FAILED(hr)) {
- NOTE("No caption memory");
- return hr;
- }
-
- pPageInfo->cb = sizeof(PROPPAGEINFO);
- pPageInfo->pszTitle = pszTitle;
- pPageInfo->pszDocString = NULL;
- pPageInfo->pszHelpFile = NULL;
- pPageInfo->dwHelpContext = 0;
-
- // Set defaults in case GetDialogSize fails
- pPageInfo->size.cx = 340;
- pPageInfo->size.cy = 150;
-
- GetDialogSize(m_DialogId, DialogProc,0L,&pPageInfo->size);
- return NOERROR;
-}
-
-
-// Handles the messages for our property window
-
-INT_PTR CALLBACK CBasePropertyPage::DialogProc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam)
-{
- CBasePropertyPage *pPropertyPage;
-
- switch (uMsg) {
-
- case WM_INITDIALOG:
-
- _SetWindowLongPtr(hwnd, DWLP_USER, lParam);
-
- // This pointer may be NULL when calculating size
-
- pPropertyPage = (CBasePropertyPage *) lParam;
- if (pPropertyPage == NULL) {
- return (LRESULT) 1;
- }
- pPropertyPage->m_Dlg = hwnd;
- }
-
- // This pointer may be NULL when calculating size
-
- pPropertyPage = _GetWindowLongPtr<CBasePropertyPage*>(hwnd, DWLP_USER);
- if (pPropertyPage == NULL) {
- return (LRESULT) 1;
- }
- return pPropertyPage->OnReceiveMessage(hwnd,uMsg,wParam,lParam);
-}
-
-
-// Tells us the object that should be informed of the property changes
-
-STDMETHODIMP CBasePropertyPage::SetObjects(ULONG cObjects,__in_ecount_opt(cObjects) LPUNKNOWN *ppUnk)
-{
- if (cObjects == 1) {
-
- if ((ppUnk == NULL) || (*ppUnk == NULL)) {
- return E_POINTER;
- }
-
- // Set a flag to say that we have set the Object
- m_bObjectSet = TRUE ;
- return OnConnect(*ppUnk);
-
- } else if (cObjects == 0) {
-
- // Set a flag to say that we have not set the Object for the page
- m_bObjectSet = FALSE ;
- return OnDisconnect();
- }
-
- DbgBreak("No support for more than one object");
- return E_UNEXPECTED;
-}
-
-
-// Create the window we will use to edit properties
-
-STDMETHODIMP CBasePropertyPage::Activate(HWND hwndParent,
- LPCRECT pRect,
- BOOL fModal)
-{
- CheckPointer(pRect,E_POINTER);
-
- // Return failure if SetObject has not been called.
- if (m_bObjectSet == FALSE) {
- return E_UNEXPECTED;
- }
-
- if (m_hwnd) {
- return E_UNEXPECTED;
- }
-
- m_hwnd = CreateDialogParam(g_hInst,
- MAKEINTRESOURCE(m_DialogId),
- hwndParent,
- DialogProc,
- (LPARAM) this);
- if (m_hwnd == NULL) {
- return E_OUTOFMEMORY;
- }
-
- OnActivate();
- Move(pRect);
- return Show(SW_SHOWNORMAL);
-}
-
-
-// Set the position of the property page
-
-STDMETHODIMP CBasePropertyPage::Move(LPCRECT pRect)
-{
- CheckPointer(pRect,E_POINTER);
-
- if (m_hwnd == NULL) {
- return E_UNEXPECTED;
- }
-
- MoveWindow(m_hwnd, // Property page handle
- pRect->left, // x coordinate
- pRect->top, // y coordinate
- WIDTH(pRect), // Overall window width
- HEIGHT(pRect), // And likewise height
- TRUE); // Should we repaint it
-
- return NOERROR;
-}
-
-
-// Display the property dialog
-
-STDMETHODIMP CBasePropertyPage::Show(UINT nCmdShow)
-{
- // Have we been activated yet
-
- if (m_hwnd == NULL) {
- return E_UNEXPECTED;
- }
-
- // Ignore wrong show flags
-
- if ((nCmdShow != SW_SHOW) && (nCmdShow != SW_SHOWNORMAL) && (nCmdShow != SW_HIDE)) {
- return E_INVALIDARG;
- }
-
- ShowWindow(m_hwnd,nCmdShow);
- InvalidateRect(m_hwnd,NULL,TRUE);
- return NOERROR;
-}
-
-
-// Destroy the property page dialog
-
-STDMETHODIMP CBasePropertyPage::Deactivate(void)
-{
- if (m_hwnd == NULL) {
- return E_UNEXPECTED;
- }
-
- // Remove WS_EX_CONTROLPARENT before DestroyWindow call
-
- DWORD dwStyle = GetWindowLong(m_hwnd, GWL_EXSTYLE);
- dwStyle = dwStyle & (~WS_EX_CONTROLPARENT);
-
- // Set m_hwnd to be NULL temporarily so the message handler
- // for WM_STYLECHANGING doesn't add the WS_EX_CONTROLPARENT
- // style back in
- HWND hwnd = m_hwnd;
- m_hwnd = NULL;
- SetWindowLong(hwnd, GWL_EXSTYLE, dwStyle);
- m_hwnd = hwnd;
-
- OnDeactivate();
-
- // Destroy the dialog window
-
- DestroyWindow(m_hwnd);
- m_hwnd = NULL;
- return NOERROR;
-}
-
-
-// Tells the application property page site
-
-STDMETHODIMP CBasePropertyPage::SetPageSite(__in_opt LPPROPERTYPAGESITE pPageSite)
-{
- if (pPageSite) {
-
- if (m_pPageSite) {
- return E_UNEXPECTED;
- }
-
- m_pPageSite = pPageSite;
- m_pPageSite->AddRef();
-
- } else {
-
- if (m_pPageSite == NULL) {
- return E_UNEXPECTED;
- }
-
- m_pPageSite->Release();
- m_pPageSite = NULL;
- }
- return NOERROR;
-}
-
-
-// Apply any changes so far made
-
-STDMETHODIMP CBasePropertyPage::Apply()
-{
- // In ActiveMovie 1.0 we used to check whether we had been activated or
- // not. This is too constrictive. Apply should be allowed as long as
- // SetObject was called to set an object. So we will no longer check to
- // see if we have been activated (ie., m_hWnd != NULL), but instead
- // make sure that m_bObjectSet is TRUE (ie., SetObject has been called).
-
- if (m_bObjectSet == FALSE) {
- return E_UNEXPECTED;
- }
-
- // Must have had a site set
-
- if (m_pPageSite == NULL) {
- return E_UNEXPECTED;
- }
-
- // Has anything changed
-
- if (m_bDirty == FALSE) {
- return NOERROR;
- }
-
- // Commit derived class changes
-
- HRESULT hr = OnApplyChanges();
- if (SUCCEEDED(hr)) {
- m_bDirty = FALSE;
- }
- return hr;
-}
-
-
-// Base class definition for message handling
-
-INT_PTR CBasePropertyPage::OnReceiveMessage(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
-{
- // we would like the TAB key to move around the tab stops in our property
- // page, but for some reason OleCreatePropertyFrame clears the CONTROLPARENT
- // style behind our back, so we need to switch it back on now behind its
- // back. Otherwise the tab key will be useless in every page.
- //
-
- CBasePropertyPage *pPropertyPage;
- {
- pPropertyPage = _GetWindowLongPtr<CBasePropertyPage*>(hwnd, DWLP_USER);
-
- if (pPropertyPage->m_hwnd == NULL) {
- return 0;
- }
- switch (uMsg) {
- case WM_STYLECHANGING:
- if (wParam == GWL_EXSTYLE) {
- LPSTYLESTRUCT lpss = (LPSTYLESTRUCT)lParam;
- lpss->styleNew |= WS_EX_CONTROLPARENT;
- return 0;
- }
- }
- }
-
- return DefWindowProc(hwnd,uMsg,wParam,lParam);
-}
-
diff --git a/dll/src/baseclasses/cprop.h b/dll/src/baseclasses/cprop.h
deleted file mode 100644
index db44940..0000000
--- a/dll/src/baseclasses/cprop.h
+++ /dev/null
@@ -1,95 +0,0 @@
-//------------------------------------------------------------------------------
-// File: CProp.h
-//
-// Desc: DirectShow base classes.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-#ifndef __CPROP__
-#define __CPROP__
-
-// Base property page class. Filters typically expose custom properties by
-// implementing special control interfaces, examples are IDirectDrawVideo
-// and IQualProp on renderers. This allows property pages to be built that
-// use the given interface. Applications such as the ActiveMovie OCX query
-// filters for the property pages they support and expose them to the user
-//
-// This class provides all the framework for a property page. A property
-// page is a COM object that supports IPropertyPage. We should be created
-// with a resource ID for the dialog which we will load when required. We
-// should also be given in the constructor a resource ID for a title string
-// we will load from the DLLs STRINGTABLE. The property page titles must be
-// stored in resource files so that they can be easily internationalised
-//
-// We have a number of virtual methods (not PURE) that may be overriden in
-// derived classes to query for interfaces and so on. These functions have
-// simple implementations here that just return NOERROR. Derived classes
-// will almost definately have to override the message handler method called
-// OnReceiveMessage. We have a static dialog procedure that calls the method
-// so that derived classes don't have to fiddle around with the this pointer
-
-class AM_NOVTABLE CBasePropertyPage : public IPropertyPage, public CUnknown
-{
-protected:
-
- LPPROPERTYPAGESITE m_pPageSite; // Details for our property site
- HWND m_hwnd; // Window handle for the page
- HWND m_Dlg; // Actual dialog window handle
- BOOL m_bDirty; // Has anything been changed
- int m_TitleId; // Resource identifier for title
- int m_DialogId; // Dialog resource identifier
-
- static INT_PTR CALLBACK DialogProc(HWND hwnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam);
-
-private:
- BOOL m_bObjectSet ; // SetObject has been called or not.
-public:
-
- CBasePropertyPage(__in_opt LPCTSTR pName, // Debug only name
- __inout_opt LPUNKNOWN pUnk, // COM Delegator
- int DialogId, // Resource ID
- int TitleId); // To get tital
-
-#ifdef UNICODE
- CBasePropertyPage(__in_opt LPCSTR pName,
- __inout_opt LPUNKNOWN pUnk,
- int DialogId,
- int TitleId);
-#endif
- virtual ~CBasePropertyPage() { };
- DECLARE_IUNKNOWN
-
- // Override these virtual methods
-
- virtual HRESULT OnConnect(IUnknown *pUnknown) { return NOERROR; };
- virtual HRESULT OnDisconnect() { return NOERROR; };
- virtual HRESULT OnActivate() { return NOERROR; };
- virtual HRESULT OnDeactivate() { return NOERROR; };
- virtual HRESULT OnApplyChanges() { return NOERROR; };
- virtual INT_PTR OnReceiveMessage(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
-
- // These implement an IPropertyPage interface
-
- STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
- STDMETHODIMP_(ULONG) NonDelegatingRelease();
- STDMETHODIMP_(ULONG) NonDelegatingAddRef();
- STDMETHODIMP SetPageSite(__in_opt LPPROPERTYPAGESITE pPageSite);
- STDMETHODIMP Activate(HWND hwndParent, LPCRECT prect,BOOL fModal);
- STDMETHODIMP Deactivate(void);
- STDMETHODIMP GetPageInfo(__out LPPROPPAGEINFO pPageInfo);
- STDMETHODIMP SetObjects(ULONG cObjects, __in_ecount_opt(cObjects) LPUNKNOWN *ppUnk);
- STDMETHODIMP Show(UINT nCmdShow);
- STDMETHODIMP Move(LPCRECT prect);
- STDMETHODIMP IsPageDirty(void) { return m_bDirty ? S_OK : S_FALSE; }
- STDMETHODIMP Apply(void);
- STDMETHODIMP Help(LPCWSTR lpszHelpDir) { return E_NOTIMPL; }
- STDMETHODIMP TranslateAccelerator(__inout LPMSG lpMsg) { return E_NOTIMPL; }
-};
-
-#endif // __CPROP__
-
diff --git a/dll/src/baseclasses/ctlutil.cpp b/dll/src/baseclasses/ctlutil.cpp
deleted file mode 100644
index 8ccb9dc..0000000
--- a/dll/src/baseclasses/ctlutil.cpp
+++ /dev/null
@@ -1,2541 +0,0 @@
-//------------------------------------------------------------------------------
-// File: CtlUtil.cpp
-//
-// Desc: DirectShow base classes.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-// Base classes implementing IDispatch parsing for the basic control dual
-// interfaces. Derive from these and implement just the custom method and
-// property methods. We also implement CPosPassThru that can be used by
-// renderers and transforms to pass by IMediaPosition and IMediaSeeking
-
-
-#include <streams.h>
-#include <limits.h>
-#include "seekpt.h"
-
-// 'bool' non standard reserved word
-#pragma warning(disable:4237)
-
-
-// --- CBaseDispatch implementation ----------
-CBaseDispatch::~CBaseDispatch()
-{
- if (m_pti) {
- m_pti->Release();
- }
-}
-
-
-// return 1 if we support GetTypeInfo
-
-STDMETHODIMP
-CBaseDispatch::GetTypeInfoCount(__out UINT * pctinfo)
-{
- CheckPointer(pctinfo,E_POINTER);
- ValidateReadWritePtr(pctinfo,sizeof(UINT *));
- *pctinfo = 1;
- return S_OK;
-}
-
-
-typedef HRESULT (STDAPICALLTYPE *LPLOADTYPELIB)(
- const OLECHAR FAR *szFile,
- __deref_out ITypeLib FAR* FAR* pptlib);
-
-typedef HRESULT (STDAPICALLTYPE *LPLOADREGTYPELIB)(REFGUID rguid,
- WORD wVerMajor,
- WORD wVerMinor,
- LCID lcid,
- __deref_out ITypeLib FAR* FAR* pptlib);
-
-// attempt to find our type library
-
-STDMETHODIMP
-CBaseDispatch::GetTypeInfo(
- REFIID riid,
- UINT itinfo,
- LCID lcid,
- __deref_out ITypeInfo ** pptinfo)
-{
- CheckPointer(pptinfo,E_POINTER);
- ValidateReadWritePtr(pptinfo,sizeof(ITypeInfo *));
- HRESULT hr;
-
- *pptinfo = NULL;
-
- // we only support one type element
- if (0 != itinfo) {
- return TYPE_E_ELEMENTNOTFOUND;
- }
-
- if (NULL == pptinfo) {
- return E_POINTER;
- }
-
- // always look for neutral
- if (NULL == m_pti) {
-
- LPLOADTYPELIB lpfnLoadTypeLib;
- LPLOADREGTYPELIB lpfnLoadRegTypeLib;
- ITypeLib *ptlib;
- HINSTANCE hInst;
-
- static const char szTypeLib[] = "LoadTypeLib";
- static const char szRegTypeLib[] = "LoadRegTypeLib";
- static const WCHAR szControl[] = L"control.tlb";
-
- //
- // Try to get the Ole32Aut.dll module handle.
- //
-
- hInst = LoadOLEAut32();
- if (hInst == NULL) {
- DWORD dwError = GetLastError();
- return AmHresultFromWin32(dwError);
- }
- lpfnLoadRegTypeLib = (LPLOADREGTYPELIB)GetProcAddress(hInst,
- szRegTypeLib);
- if (lpfnLoadRegTypeLib == NULL) {
- DWORD dwError = GetLastError();
- return AmHresultFromWin32(dwError);
- }
-
- hr = (*lpfnLoadRegTypeLib)(LIBID_QuartzTypeLib, 1, 0, // version 1.0
- lcid, &ptlib);
-
- if (FAILED(hr)) {
-
- // attempt to load directly - this will fill the
- // registry in if it finds it
-
- lpfnLoadTypeLib = (LPLOADTYPELIB)GetProcAddress(hInst, szTypeLib);
- if (lpfnLoadTypeLib == NULL) {
- DWORD dwError = GetLastError();
- return AmHresultFromWin32(dwError);
- }
-
- hr = (*lpfnLoadTypeLib)(szControl, &ptlib);
- if (FAILED(hr)) {
- return hr;
- }
- }
-
- hr = ptlib->GetTypeInfoOfGuid(
- riid,
- &m_pti);
-
- ptlib->Release();
-
- if (FAILED(hr)) {
- return hr;
- }
- }
-
- *pptinfo = m_pti;
- m_pti->AddRef();
- return S_OK;
-}
-
-
-STDMETHODIMP
-CBaseDispatch::GetIDsOfNames(
- REFIID riid,
- __in_ecount(cNames) LPOLESTR * rgszNames,
- UINT cNames,
- LCID lcid,
- __out_ecount(cNames) DISPID * rgdispid)
-{
- // although the IDispatch riid is dead, we use this to pass from
- // the interface implementation class to us the iid we are talking about.
-
- ITypeInfo * pti;
- HRESULT hr = GetTypeInfo(riid, 0, lcid, &pti);
-
- if (SUCCEEDED(hr)) {
- hr = pti->GetIDsOfNames(rgszNames, cNames, rgdispid);
-
- pti->Release();
- }
- return hr;
-}
-
-
-// --- CMediaControl implementation ---------
-
-CMediaControl::CMediaControl(const TCHAR * name,LPUNKNOWN pUnk) :
- CUnknown(name, pUnk)
-{
-}
-
-// expose our interfaces IMediaControl and IUnknown
-
-STDMETHODIMP
-CMediaControl::NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv)
-{
- ValidateReadWritePtr(ppv,sizeof(PVOID));
- if (riid == IID_IMediaControl) {
- return GetInterface( (IMediaControl *) this, ppv);
- } else {
- return CUnknown::NonDelegatingQueryInterface(riid, ppv);
- }
-}
-
-
-// return 1 if we support GetTypeInfo
-
-STDMETHODIMP
-CMediaControl::GetTypeInfoCount(__out UINT * pctinfo)
-{
- return m_basedisp.GetTypeInfoCount(pctinfo);
-}
-
-
-// attempt to find our type library
-
-STDMETHODIMP
-CMediaControl::GetTypeInfo(
- UINT itinfo,
- LCID lcid,
- __deref_out ITypeInfo ** pptinfo)
-{
- return m_basedisp.GetTypeInfo(
- IID_IMediaControl,
- itinfo,
- lcid,
- pptinfo);
-}
-
-
-STDMETHODIMP
-CMediaControl::GetIDsOfNames(
- REFIID riid,
- __in_ecount(cNames) LPOLESTR * rgszNames,
- UINT cNames,
- LCID lcid,
- __out_ecount(cNames) DISPID * rgdispid)
-{
- return m_basedisp.GetIDsOfNames(
- IID_IMediaControl,
- rgszNames,
- cNames,
- lcid,
- rgdispid);
-}
-
-
-STDMETHODIMP
-CMediaControl::Invoke(
- DISPID dispidMember,
- REFIID riid,
- LCID lcid,
- WORD wFlags,
- __in DISPPARAMS * pdispparams,
- __out_opt VARIANT * pvarResult,
- __out_opt EXCEPINFO * pexcepinfo,
- __out_opt UINT * puArgErr)
-{
- // this parameter is a dead leftover from an earlier interface
- if (IID_NULL != riid) {
- return DISP_E_UNKNOWNINTERFACE;
- }
-
- ITypeInfo * pti;
- HRESULT hr = GetTypeInfo(0, lcid, &pti);
-
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = pti->Invoke(
- (IMediaControl *)this,
- dispidMember,
- wFlags,
- pdispparams,
- pvarResult,
- pexcepinfo,
- puArgErr);
-
- pti->Release();
- return hr;
-}
-
-
-// --- CMediaEvent implementation ----------
-
-
-CMediaEvent::CMediaEvent(__in_opt LPCTSTR name,__in_opt LPUNKNOWN pUnk) :
- CUnknown(name, pUnk)
-{
-}
-
-
-// expose our interfaces IMediaEvent and IUnknown
-
-STDMETHODIMP
-CMediaEvent::NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv)
-{
- ValidateReadWritePtr(ppv,sizeof(PVOID));
- if (riid == IID_IMediaEvent || riid == IID_IMediaEventEx) {
- return GetInterface( (IMediaEventEx *) this, ppv);
- } else {
- return CUnknown::NonDelegatingQueryInterface(riid, ppv);
- }
-}
-
-
-// return 1 if we support GetTypeInfo
-
-STDMETHODIMP
-CMediaEvent::GetTypeInfoCount(__out UINT * pctinfo)
-{
- return m_basedisp.GetTypeInfoCount(pctinfo);
-}
-
-
-// attempt to find our type library
-
-STDMETHODIMP
-CMediaEvent::GetTypeInfo(
- UINT itinfo,
- LCID lcid,
- __deref_out ITypeInfo ** pptinfo)
-{
- return m_basedisp.GetTypeInfo(
- IID_IMediaEvent,
- itinfo,
- lcid,
- pptinfo);
-}
-
-
-STDMETHODIMP
-CMediaEvent::GetIDsOfNames(
- REFIID riid,
- __in_ecount(cNames) LPOLESTR * rgszNames,
- UINT cNames,
- LCID lcid,
- __out_ecount(cNames) DISPID * rgdispid)
-{
- return m_basedisp.GetIDsOfNames(
- IID_IMediaEvent,
- rgszNames,
- cNames,
- lcid,
- rgdispid);
-}
-
-
-STDMETHODIMP
-CMediaEvent::Invoke(
- DISPID dispidMember,
- REFIID riid,
- LCID lcid,
- WORD wFlags,
- __in DISPPARAMS * pdispparams,
- __out_opt VARIANT * pvarResult,
- __out_opt EXCEPINFO * pexcepinfo,
- __out_opt UINT * puArgErr)
-{
- // this parameter is a dead leftover from an earlier interface
- if (IID_NULL != riid) {
- return DISP_E_UNKNOWNINTERFACE;
- }
-
- ITypeInfo * pti;
- HRESULT hr = GetTypeInfo(0, lcid, &pti);
-
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = pti->Invoke(
- (IMediaEvent *)this,
- dispidMember,
- wFlags,
- pdispparams,
- pvarResult,
- pexcepinfo,
- puArgErr);
-
- pti->Release();
- return hr;
-}
-
-
-// --- CMediaPosition implementation ----------
-
-
-CMediaPosition::CMediaPosition(__in_opt LPCTSTR name,__in_opt LPUNKNOWN pUnk) :
- CUnknown(name, pUnk)
-{
-}
-
-CMediaPosition::CMediaPosition(__in_opt LPCTSTR name,
- __in_opt LPUNKNOWN pUnk,
- __inout HRESULT * phr) :
- CUnknown(name, pUnk)
-{
- UNREFERENCED_PARAMETER(phr);
-}
-
-
-// expose our interfaces IMediaPosition and IUnknown
-
-STDMETHODIMP
-CMediaPosition::NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv)
-{
- ValidateReadWritePtr(ppv,sizeof(PVOID));
- if (riid == IID_IMediaPosition) {
- return GetInterface( (IMediaPosition *) this, ppv);
- } else {
- return CUnknown::NonDelegatingQueryInterface(riid, ppv);
- }
-}
-
-
-// return 1 if we support GetTypeInfo
-
-STDMETHODIMP
-CMediaPosition::GetTypeInfoCount(__out UINT * pctinfo)
-{
- return m_basedisp.GetTypeInfoCount(pctinfo);
-}
-
-
-// attempt to find our type library
-
-STDMETHODIMP
-CMediaPosition::GetTypeInfo(
- UINT itinfo,
- LCID lcid,
- __deref_out ITypeInfo ** pptinfo)
-{
- return m_basedisp.GetTypeInfo(
- IID_IMediaPosition,
- itinfo,
- lcid,
- pptinfo);
-}
-
-
-STDMETHODIMP
-CMediaPosition::GetIDsOfNames(
- REFIID riid,
- __in_ecount(cNames) LPOLESTR * rgszNames,
- UINT cNames,
- LCID lcid,
- __out_ecount(cNames) DISPID * rgdispid)
-{
- return m_basedisp.GetIDsOfNames(
- IID_IMediaPosition,
- rgszNames,
- cNames,
- lcid,
- rgdispid);
-}
-
-
-STDMETHODIMP
-CMediaPosition::Invoke(
- DISPID dispidMember,
- REFIID riid,
- LCID lcid,
- WORD wFlags,
- __in DISPPARAMS * pdispparams,
- __out_opt VARIANT * pvarResult,
- __out_opt EXCEPINFO * pexcepinfo,
- __out_opt UINT * puArgErr)
-{
- // this parameter is a dead leftover from an earlier interface
- if (IID_NULL != riid) {
- return DISP_E_UNKNOWNINTERFACE;
- }
-
- ITypeInfo * pti;
- HRESULT hr = GetTypeInfo(0, lcid, &pti);
-
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = pti->Invoke(
- (IMediaPosition *)this,
- dispidMember,
- wFlags,
- pdispparams,
- pvarResult,
- pexcepinfo,
- puArgErr);
-
- pti->Release();
- return hr;
-}
-
-
-// --- IMediaPosition and IMediaSeeking pass through class ----------
-
-
-CPosPassThru::CPosPassThru(__in_opt LPCTSTR pName,
- __in_opt LPUNKNOWN pUnk,
- __inout HRESULT *phr,
- IPin *pPin) :
- CMediaPosition(pName,pUnk),
- m_pPin(pPin)
-{
- if (pPin == NULL) {
- *phr = E_POINTER;
- return;
- }
-}
-
-
-// Expose our IMediaSeeking and IMediaPosition interfaces
-
-STDMETHODIMP
-CPosPassThru::NonDelegatingQueryInterface(REFIID riid,__deref_out void **ppv)
-{
- CheckPointer(ppv,E_POINTER);
- *ppv = NULL;
-
- if (riid == IID_IMediaSeeking) {
- return GetInterface( static_cast<IMediaSeeking *>(this), ppv);
- }
- return CMediaPosition::NonDelegatingQueryInterface(riid,ppv);
-}
-
-
-// Return the IMediaPosition interface from our peer
-
-HRESULT
-CPosPassThru::GetPeer(IMediaPosition ** ppMP)
-{
- *ppMP = NULL;
-
- IPin *pConnected;
- HRESULT hr = m_pPin->ConnectedTo(&pConnected);
- if (FAILED(hr)) {
- return E_NOTIMPL;
- }
- IMediaPosition * pMP;
- hr = pConnected->QueryInterface(IID_IMediaPosition, (void **) &pMP);
- pConnected->Release();
- if (FAILED(hr)) {
- return E_NOTIMPL;
- }
-
- *ppMP = pMP;
- return S_OK;
-}
-
-
-// Return the IMediaSeeking interface from our peer
-
-HRESULT
-CPosPassThru::GetPeerSeeking(__deref_out IMediaSeeking ** ppMS)
-{
- *ppMS = NULL;
-
- IPin *pConnected;
- HRESULT hr = m_pPin->ConnectedTo(&pConnected);
- if (FAILED(hr)) {
- return E_NOTIMPL;
- }
- IMediaSeeking * pMS;
- hr = pConnected->QueryInterface(IID_IMediaSeeking, (void **) &pMS);
- pConnected->Release();
- if (FAILED(hr)) {
- return E_NOTIMPL;
- }
-
- *ppMS = pMS;
- return S_OK;
-}
-
-
-// --- IMediaSeeking methods ----------
-
-
-STDMETHODIMP
-CPosPassThru::GetCapabilities(__out DWORD * pCaps)
-{
- IMediaSeeking* pMS;
- HRESULT hr = GetPeerSeeking(&pMS);
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = pMS->GetCapabilities(pCaps);
- pMS->Release();
- return hr;
-}
-
-STDMETHODIMP
-CPosPassThru::CheckCapabilities(__inout DWORD * pCaps)
-{
- IMediaSeeking* pMS;
- HRESULT hr = GetPeerSeeking(&pMS);
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = pMS->CheckCapabilities(pCaps);
- pMS->Release();
- return hr;
-}
-
-STDMETHODIMP
-CPosPassThru::IsFormatSupported(const GUID * pFormat)
-{
- IMediaSeeking* pMS;
- HRESULT hr = GetPeerSeeking(&pMS);
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = pMS->IsFormatSupported(pFormat);
- pMS->Release();
- return hr;
-}
-
-
-STDMETHODIMP
-CPosPassThru::QueryPreferredFormat(__out GUID *pFormat)
-{
- IMediaSeeking* pMS;
- HRESULT hr = GetPeerSeeking(&pMS);
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = pMS->QueryPreferredFormat(pFormat);
- pMS->Release();
- return hr;
-}
-
-
-STDMETHODIMP
-CPosPassThru::SetTimeFormat(const GUID * pFormat)
-{
- IMediaSeeking* pMS;
- HRESULT hr = GetPeerSeeking(&pMS);
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = pMS->SetTimeFormat(pFormat);
- pMS->Release();
- return hr;
-}
-
-
-STDMETHODIMP
-CPosPassThru::GetTimeFormat(__out GUID *pFormat)
-{
- IMediaSeeking* pMS;
- HRESULT hr = GetPeerSeeking(&pMS);
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = pMS->GetTimeFormat(pFormat);
- pMS->Release();
- return hr;
-}
-
-
-STDMETHODIMP
-CPosPassThru::IsUsingTimeFormat(const GUID * pFormat)
-{
- IMediaSeeking* pMS;
- HRESULT hr = GetPeerSeeking(&pMS);
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = pMS->IsUsingTimeFormat(pFormat);
- pMS->Release();
- return hr;
-}
-
-
-STDMETHODIMP
-CPosPassThru::ConvertTimeFormat(__out LONGLONG * pTarget,
- __in_opt const GUID * pTargetFormat,
- LONGLONG Source,
- __in_opt const GUID * pSourceFormat )
-{
- IMediaSeeking* pMS;
- HRESULT hr = GetPeerSeeking(&pMS);
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = pMS->ConvertTimeFormat(pTarget, pTargetFormat, Source, pSourceFormat );
- pMS->Release();
- return hr;
-}
-
-
-STDMETHODIMP
-CPosPassThru::SetPositions( __inout_opt LONGLONG * pCurrent,
- DWORD CurrentFlags,
- __inout_opt LONGLONG * pStop,
- DWORD StopFlags )
-{
- IMediaSeeking* pMS;
- HRESULT hr = GetPeerSeeking(&pMS);
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = pMS->SetPositions(pCurrent, CurrentFlags, pStop, StopFlags );
- pMS->Release();
- return hr;
-}
-
-STDMETHODIMP
-CPosPassThru::GetPositions(__out_opt LONGLONG *pCurrent, __out_opt LONGLONG * pStop)
-{
- IMediaSeeking* pMS;
- HRESULT hr = GetPeerSeeking(&pMS);
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = pMS->GetPositions(pCurrent,pStop);
- pMS->Release();
- return hr;
-}
-
-HRESULT
-CPosPassThru::GetSeekingLongLong
-( HRESULT (__stdcall IMediaSeeking::*pMethod)( __out LONGLONG * )
-, LONGLONG * pll
-)
-{
- IMediaSeeking* pMS;
- HRESULT hr = GetPeerSeeking(&pMS);
- if (SUCCEEDED(hr))
- {
- hr = (pMS->*pMethod)(pll);
- pMS->Release();
- }
- return hr;
-}
-
-// If we don't have a current position then ask upstream
-
-STDMETHODIMP
-CPosPassThru::GetCurrentPosition(__out LONGLONG *pCurrent)
-{
- // Can we report the current position
- HRESULT hr = GetMediaTime(pCurrent,NULL);
- if (SUCCEEDED(hr)) hr = NOERROR;
- else hr = GetSeekingLongLong( &IMediaSeeking::GetCurrentPosition, pCurrent );
- return hr;
-}
-
-
-STDMETHODIMP
-CPosPassThru::GetStopPosition(__out LONGLONG *pStop)
-{
- return GetSeekingLongLong( &IMediaSeeking::GetStopPosition, pStop );;
-}
-
-STDMETHODIMP
-CPosPassThru::GetDuration(__out LONGLONG *pDuration)
-{
- return GetSeekingLongLong( &IMediaSeeking::GetDuration, pDuration );;
-}
-
-
-STDMETHODIMP
-CPosPassThru::GetPreroll(__out LONGLONG *pllPreroll)
-{
- return GetSeekingLongLong( &IMediaSeeking::GetPreroll, pllPreroll );;
-}
-
-
-STDMETHODIMP
-CPosPassThru::GetAvailable( __out_opt LONGLONG *pEarliest, __out_opt LONGLONG *pLatest )
-{
- IMediaSeeking* pMS;
- HRESULT hr = GetPeerSeeking(&pMS);
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = pMS->GetAvailable( pEarliest, pLatest );
- pMS->Release();
- return hr;
-}
-
-
-STDMETHODIMP
-CPosPassThru::GetRate(__out double * pdRate)
-{
- IMediaSeeking* pMS;
- HRESULT hr = GetPeerSeeking(&pMS);
- if (FAILED(hr)) {
- return hr;
- }
- hr = pMS->GetRate(pdRate);
- pMS->Release();
- return hr;
-}
-
-
-STDMETHODIMP
-CPosPassThru::SetRate(double dRate)
-{
- if (0.0 == dRate) {
- return E_INVALIDARG;
- }
-
- IMediaSeeking* pMS;
- HRESULT hr = GetPeerSeeking(&pMS);
- if (FAILED(hr)) {
- return hr;
- }
- hr = pMS->SetRate(dRate);
- pMS->Release();
- return hr;
-}
-
-
-
-
-// --- IMediaPosition methods ----------
-
-
-STDMETHODIMP
-CPosPassThru::get_Duration(__out REFTIME * plength)
-{
- IMediaPosition* pMP;
- HRESULT hr = GetPeer(&pMP);
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = pMP->get_Duration(plength);
- pMP->Release();
- return hr;
-}
-
-
-STDMETHODIMP
-CPosPassThru::get_CurrentPosition(__out REFTIME * pllTime)
-{
- IMediaPosition* pMP;
- HRESULT hr = GetPeer(&pMP);
- if (FAILED(hr)) {
- return hr;
- }
- hr = pMP->get_CurrentPosition(pllTime);
- pMP->Release();
- return hr;
-}
-
-
-STDMETHODIMP
-CPosPassThru::put_CurrentPosition(REFTIME llTime)
-{
- IMediaPosition* pMP;
- HRESULT hr = GetPeer(&pMP);
- if (FAILED(hr)) {
- return hr;
- }
- hr = pMP->put_CurrentPosition(llTime);
- pMP->Release();
- return hr;
-}
-
-
-STDMETHODIMP
-CPosPassThru::get_StopTime(__out REFTIME * pllTime)
-{
- IMediaPosition* pMP;
- HRESULT hr = GetPeer(&pMP);
- if (FAILED(hr)) {
- return hr;
- }
- hr = pMP->get_StopTime(pllTime);
- pMP->Release();
- return hr;
-}
-
-
-STDMETHODIMP
-CPosPassThru::put_StopTime(REFTIME llTime)
-{
- IMediaPosition* pMP;
- HRESULT hr = GetPeer(&pMP);
- if (FAILED(hr)) {
- return hr;
- }
- hr = pMP->put_StopTime(llTime);
- pMP->Release();
- return hr;
-}
-
-
-STDMETHODIMP
-CPosPassThru::get_PrerollTime(__out REFTIME * pllTime)
-{
- IMediaPosition* pMP;
- HRESULT hr = GetPeer(&pMP);
- if (FAILED(hr)) {
- return hr;
- }
- hr = pMP->get_PrerollTime(pllTime);
- pMP->Release();
- return hr;
-}
-
-
-STDMETHODIMP
-CPosPassThru::put_PrerollTime(REFTIME llTime)
-{
- IMediaPosition* pMP;
- HRESULT hr = GetPeer(&pMP);
- if (FAILED(hr)) {
- return hr;
- }
- hr = pMP->put_PrerollTime(llTime);
- pMP->Release();
- return hr;
-}
-
-
-STDMETHODIMP
-CPosPassThru::get_Rate(__out double * pdRate)
-{
- IMediaPosition* pMP;
- HRESULT hr = GetPeer(&pMP);
- if (FAILED(hr)) {
- return hr;
- }
- hr = pMP->get_Rate(pdRate);
- pMP->Release();
- return hr;
-}
-
-
-STDMETHODIMP
-CPosPassThru::put_Rate(double dRate)
-{
- if (0.0 == dRate) {
- return E_INVALIDARG;
- }
-
- IMediaPosition* pMP;
- HRESULT hr = GetPeer(&pMP);
- if (FAILED(hr)) {
- return hr;
- }
- hr = pMP->put_Rate(dRate);
- pMP->Release();
- return hr;
-}
-
-
-STDMETHODIMP
-CPosPassThru::CanSeekForward(__out LONG *pCanSeekForward)
-{
- IMediaPosition* pMP;
- HRESULT hr = GetPeer(&pMP);
- if (FAILED(hr)) {
- return hr;
- }
- hr = pMP->CanSeekForward(pCanSeekForward);
- pMP->Release();
- return hr;
-}
-
-
-STDMETHODIMP
-CPosPassThru::CanSeekBackward(__out LONG *pCanSeekBackward)
-{
- IMediaPosition* pMP;
- HRESULT hr = GetPeer(&pMP);
- if (FAILED(hr)) {
- return hr;
- }
- hr = pMP->CanSeekBackward(pCanSeekBackward);
- pMP->Release();
- return hr;
-}
-
-
-// --- Implements the CRendererPosPassThru class ----------
-
-
-// Media times (eg current frame, field, sample etc) are passed through the
-// filtergraph in media samples. When a renderer gets a sample with media
-// times in it, it will call one of the RegisterMediaTime methods we expose
-// (one takes an IMediaSample, the other takes the media times direct). We
-// store the media times internally and return them in GetCurrentPosition.
-
-CRendererPosPassThru::CRendererPosPassThru(__in_opt LPCTSTR pName,
- __in_opt LPUNKNOWN pUnk,
- __inout HRESULT *phr,
- IPin *pPin) :
- CPosPassThru(pName,pUnk,phr,pPin),
- m_StartMedia(0),
- m_EndMedia(0),
- m_bReset(TRUE)
-{
-}
-
-
-// Sets the media times the object should report
-
-HRESULT
-CRendererPosPassThru::RegisterMediaTime(IMediaSample *pMediaSample)
-{
- ASSERT(pMediaSample);
- LONGLONG StartMedia;
- LONGLONG EndMedia;
-
- CAutoLock cAutoLock(&m_PositionLock);
-
- // Get the media times from the sample
-
- HRESULT hr = pMediaSample->GetTime(&StartMedia,&EndMedia);
- if (FAILED(hr))
- {
- ASSERT(hr == VFW_E_SAMPLE_TIME_NOT_SET);
- return hr;
- }
-
- m_StartMedia = StartMedia;
- m_EndMedia = EndMedia;
- m_bReset = FALSE;
- return NOERROR;
-}
-
-
-// Sets the media times the object should report
-
-HRESULT
-CRendererPosPassThru::RegisterMediaTime(LONGLONG StartTime,LONGLONG EndTime)
-{
- CAutoLock cAutoLock(&m_PositionLock);
- m_StartMedia = StartTime;
- m_EndMedia = EndTime;
- m_bReset = FALSE;
- return NOERROR;
-}
-
-
-// Return the current media times registered in the object
-
-HRESULT
-CRendererPosPassThru::GetMediaTime(__out LONGLONG *pStartTime, __out_opt LONGLONG *pEndTime)
-{
- ASSERT(pStartTime);
-
- CAutoLock cAutoLock(&m_PositionLock);
- if (m_bReset == TRUE) {
- return E_FAIL;
- }
-
- // We don't have to return the end time
-
- HRESULT hr = ConvertTimeFormat( pStartTime, 0, m_StartMedia, &TIME_FORMAT_MEDIA_TIME );
- if (pEndTime && SUCCEEDED(hr)) {
- hr = ConvertTimeFormat( pEndTime, 0, m_EndMedia, &TIME_FORMAT_MEDIA_TIME );
- }
- return hr;
-}
-
-
-// Resets the media times we hold
-
-HRESULT
-CRendererPosPassThru::ResetMediaTime()
-{
- CAutoLock cAutoLock(&m_PositionLock);
- m_StartMedia = 0;
- m_EndMedia = 0;
- m_bReset = TRUE;
- return NOERROR;
-}
-
-// Intended to be called by the owing filter during EOS processing so
-// that the media times can be adjusted to the stop time. This ensures
-// that the GetCurrentPosition will actully get to the stop position.
-HRESULT
-CRendererPosPassThru::EOS()
-{
- HRESULT hr;
-
- if ( m_bReset == TRUE ) hr = E_FAIL;
- else
- {
- LONGLONG llStop;
- if SUCCEEDED(hr=GetStopPosition(&llStop))
- {
- CAutoLock cAutoLock(&m_PositionLock);
- m_StartMedia =
- m_EndMedia = llStop;
- }
- }
- return hr;
-}
-
-// -- CSourceSeeking implementation ------------
-
-CSourceSeeking::CSourceSeeking(
- __in_opt LPCTSTR pName,
- __in_opt LPUNKNOWN pUnk,
- __inout HRESULT* phr,
- __in CCritSec * pLock) :
- CUnknown(pName, pUnk),
- m_pLock(pLock),
- m_rtStart((long)0)
-{
- m_rtStop = _I64_MAX / 2;
- m_rtDuration = m_rtStop;
- m_dRateSeeking = 1.0;
-
- m_dwSeekingCaps = AM_SEEKING_CanSeekForwards
- | AM_SEEKING_CanSeekBackwards
- | AM_SEEKING_CanSeekAbsolute
- | AM_SEEKING_CanGetStopPos
- | AM_SEEKING_CanGetDuration;
-}
-
-HRESULT CSourceSeeking::NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv)
-{
- if(riid == IID_IMediaSeeking) {
- CheckPointer(ppv, E_POINTER);
- return GetInterface(static_cast<IMediaSeeking *>(this), ppv);
- }
- else {
- return CUnknown::NonDelegatingQueryInterface(riid, ppv);
- }
-}
-
-
-HRESULT CSourceSeeking::IsFormatSupported(const GUID * pFormat)
-{
- CheckPointer(pFormat, E_POINTER);
- // only seeking in time (REFERENCE_TIME units) is supported
- return *pFormat == TIME_FORMAT_MEDIA_TIME ? S_OK : S_FALSE;
-}
-
-HRESULT CSourceSeeking::QueryPreferredFormat(__out GUID *pFormat)
-{
- CheckPointer(pFormat, E_POINTER);
- *pFormat = TIME_FORMAT_MEDIA_TIME;
- return S_OK;
-}
-
-HRESULT CSourceSeeking::SetTimeFormat(const GUID * pFormat)
-{
- CheckPointer(pFormat, E_POINTER);
-
- // nothing to set; just check that it's TIME_FORMAT_TIME
- return *pFormat == TIME_FORMAT_MEDIA_TIME ? S_OK : E_INVALIDARG;
-}
-
-HRESULT CSourceSeeking::IsUsingTimeFormat(const GUID * pFormat)
-{
- CheckPointer(pFormat, E_POINTER);
- return *pFormat == TIME_FORMAT_MEDIA_TIME ? S_OK : S_FALSE;
-}
-
-HRESULT CSourceSeeking::GetTimeFormat(__out GUID *pFormat)
-{
- CheckPointer(pFormat, E_POINTER);
- *pFormat = TIME_FORMAT_MEDIA_TIME;
- return S_OK;
-}
-
-HRESULT CSourceSeeking::GetDuration(__out LONGLONG *pDuration)
-{
- CheckPointer(pDuration, E_POINTER);
- CAutoLock lock(m_pLock);
- *pDuration = m_rtDuration;
- return S_OK;
-}
-
-HRESULT CSourceSeeking::GetStopPosition(__out LONGLONG *pStop)
-{
- CheckPointer(pStop, E_POINTER);
- CAutoLock lock(m_pLock);
- *pStop = m_rtStop;
- return S_OK;
-}
-
-HRESULT CSourceSeeking::GetCurrentPosition(__out LONGLONG *pCurrent)
-{
- // GetCurrentPosition is typically supported only in renderers and
- // not in source filters.
- return E_NOTIMPL;
-}
-
-HRESULT CSourceSeeking::GetCapabilities( __out DWORD * pCapabilities )
-{
- CheckPointer(pCapabilities, E_POINTER);
- *pCapabilities = m_dwSeekingCaps;
- return S_OK;
-}
-
-HRESULT CSourceSeeking::CheckCapabilities( __inout DWORD * pCapabilities )
-{
- CheckPointer(pCapabilities, E_POINTER);
-
- // make sure all requested capabilities are in our mask
- return (~m_dwSeekingCaps & *pCapabilities) ? S_FALSE : S_OK;
-}
-
-HRESULT CSourceSeeking::ConvertTimeFormat( __out LONGLONG * pTarget,
- __in_opt const GUID * pTargetFormat,
- LONGLONG Source,
- __in_opt const GUID * pSourceFormat )
-{
- CheckPointer(pTarget, E_POINTER);
- // format guids can be null to indicate current format
-
- // since we only support TIME_FORMAT_MEDIA_TIME, we don't really
- // offer any conversions.
- if(pTargetFormat == 0 || *pTargetFormat == TIME_FORMAT_MEDIA_TIME)
- {
- if(pSourceFormat == 0 || *pSourceFormat == TIME_FORMAT_MEDIA_TIME)
- {
- *pTarget = Source;
- return S_OK;
- }
- }
-
- return E_INVALIDARG;
-}
-
-
-HRESULT CSourceSeeking::SetPositions( __inout_opt LONGLONG * pCurrent,
- DWORD CurrentFlags,
- __inout_opt LONGLONG * pStop,
- DWORD StopFlags )
-{
- DWORD StopPosBits = StopFlags & AM_SEEKING_PositioningBitsMask;
- DWORD StartPosBits = CurrentFlags & AM_SEEKING_PositioningBitsMask;
-
- if(StopFlags) {
- CheckPointer(pStop, E_POINTER);
-
- // accept only relative, incremental, or absolute positioning
- if(StopPosBits != StopFlags) {
- return E_INVALIDARG;
- }
- }
-
- if(CurrentFlags) {
- CheckPointer(pCurrent, E_POINTER);
- if(StartPosBits != AM_SEEKING_AbsolutePositioning &&
- StartPosBits != AM_SEEKING_RelativePositioning) {
- return E_INVALIDARG;
- }
- }
-
-
- // scope for autolock
- {
- CAutoLock lock(m_pLock);
-
- // set start position
- if(StartPosBits == AM_SEEKING_AbsolutePositioning)
- {
- m_rtStart = *pCurrent;
- }
- else if(StartPosBits == AM_SEEKING_RelativePositioning)
- {
- m_rtStart += *pCurrent;
- }
-
- // set stop position
- if(StopPosBits == AM_SEEKING_AbsolutePositioning)
- {
- m_rtStop = *pStop;
- }
- else if(StopPosBits == AM_SEEKING_IncrementalPositioning)
- {
- m_rtStop = m_rtStart + *pStop;
- }
- else if(StopPosBits == AM_SEEKING_RelativePositioning)
- {
- m_rtStop = m_rtStop + *pStop;
- }
- }
-
-
- HRESULT hr = S_OK;
- if(SUCCEEDED(hr) && StopPosBits) {
- hr = ChangeStop();
- }
- if(StartPosBits) {
- hr = ChangeStart();
- }
-
- return hr;
-}
-
-
-HRESULT CSourceSeeking::GetPositions( __out_opt LONGLONG * pCurrent, __out_opt LONGLONG * pStop )
-{
- if(pCurrent) {
- *pCurrent = m_rtStart;
- }
- if(pStop) {
- *pStop = m_rtStop;
- }
-
- return S_OK;;
-}
-
-
-HRESULT CSourceSeeking::GetAvailable( __out_opt LONGLONG * pEarliest, __out_opt LONGLONG * pLatest )
-{
- if(pEarliest) {
- *pEarliest = 0;
- }
- if(pLatest) {
- CAutoLock lock(m_pLock);
- *pLatest = m_rtDuration;
- }
- return S_OK;
-}
-
-HRESULT CSourceSeeking::SetRate( double dRate)
-{
- {
- CAutoLock lock(m_pLock);
- m_dRateSeeking = dRate;
- }
- return ChangeRate();
-}
-
-HRESULT CSourceSeeking::GetRate( __out double * pdRate)
-{
- CheckPointer(pdRate, E_POINTER);
- CAutoLock lock(m_pLock);
- *pdRate = m_dRateSeeking;
- return S_OK;
-}
-
-HRESULT CSourceSeeking::GetPreroll(__out LONGLONG *pPreroll)
-{
- CheckPointer(pPreroll, E_POINTER);
- *pPreroll = 0;
- return S_OK;
-}
-
-
-
-
-
-// --- CSourcePosition implementation ----------
-
-
-CSourcePosition::CSourcePosition(__in_opt LPCTSTR pName,
- __in_opt LPUNKNOWN pUnk,
- __inout HRESULT* phr,
- __in CCritSec * pLock) :
- CMediaPosition(pName, pUnk),
- m_pLock(pLock),
- m_Start(CRefTime((LONGLONG)0))
-{
- m_Stop = _I64_MAX;
- m_Rate = 1.0;
-}
-
-
-STDMETHODIMP
-CSourcePosition::get_Duration(__out REFTIME * plength)
-{
- CheckPointer(plength,E_POINTER);
- ValidateReadWritePtr(plength,sizeof(REFTIME));
- CAutoLock lock(m_pLock);
-
- *plength = m_Duration;
- return S_OK;
-}
-
-
-STDMETHODIMP
-CSourcePosition::put_CurrentPosition(REFTIME llTime)
-{
- m_pLock->Lock();
- m_Start = llTime;
- m_pLock->Unlock();
-
- return ChangeStart();
-}
-
-
-STDMETHODIMP
-CSourcePosition::get_StopTime(__out REFTIME * pllTime)
-{
- CheckPointer(pllTime,E_POINTER);
- ValidateReadWritePtr(pllTime,sizeof(REFTIME));
- CAutoLock lock(m_pLock);
-
- *pllTime = m_Stop;
- return S_OK;
-}
-
-
-STDMETHODIMP
-CSourcePosition::put_StopTime(REFTIME llTime)
-{
- m_pLock->Lock();
- m_Stop = llTime;
- m_pLock->Unlock();
-
- return ChangeStop();
-}
-
-
-STDMETHODIMP
-CSourcePosition::get_PrerollTime(__out REFTIME * pllTime)
-{
- CheckPointer(pllTime,E_POINTER);
- ValidateReadWritePtr(pllTime,sizeof(REFTIME));
- return E_NOTIMPL;
-}
-
-
-STDMETHODIMP
-CSourcePosition::put_PrerollTime(REFTIME llTime)
-{
- return E_NOTIMPL;
-}
-
-
-STDMETHODIMP
-CSourcePosition::get_Rate(__out double * pdRate)
-{
- CheckPointer(pdRate,E_POINTER);
- ValidateReadWritePtr(pdRate,sizeof(double));
- CAutoLock lock(m_pLock);
-
- *pdRate = m_Rate;
- return S_OK;
-}
-
-
-STDMETHODIMP
-CSourcePosition::put_Rate(double dRate)
-{
- m_pLock->Lock();
- m_Rate = dRate;
- m_pLock->Unlock();
-
- return ChangeRate();
-}
-
-
-// By default we can seek forwards
-
-STDMETHODIMP
-CSourcePosition::CanSeekForward(__out LONG *pCanSeekForward)
-{
- CheckPointer(pCanSeekForward,E_POINTER);
- *pCanSeekForward = OATRUE;
- return S_OK;
-}
-
-
-// By default we can seek backwards
-
-STDMETHODIMP
-CSourcePosition::CanSeekBackward(__out LONG *pCanSeekBackward)
-{
- CheckPointer(pCanSeekBackward,E_POINTER);
- *pCanSeekBackward = OATRUE;
- return S_OK;
-}
-
-
-// --- Implementation of CBasicAudio class ----------
-
-
-CBasicAudio::CBasicAudio(__in_opt LPCTSTR pName,__in_opt LPUNKNOWN punk) :
- CUnknown(pName, punk)
-{
-}
-
-// overriden to publicise our interfaces
-
-STDMETHODIMP
-CBasicAudio::NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv)
-{
- ValidateReadWritePtr(ppv,sizeof(PVOID));
- if (riid == IID_IBasicAudio) {
- return GetInterface( (IBasicAudio *) this, ppv);
- } else {
- return CUnknown::NonDelegatingQueryInterface(riid, ppv);
- }
-}
-
-
-STDMETHODIMP
-CBasicAudio::GetTypeInfoCount(__out UINT * pctinfo)
-{
- return m_basedisp.GetTypeInfoCount(pctinfo);
-}
-
-
-STDMETHODIMP
-CBasicAudio::GetTypeInfo(
- UINT itinfo,
- LCID lcid,
- __deref_out ITypeInfo ** pptinfo)
-{
- return m_basedisp.GetTypeInfo(
- IID_IBasicAudio,
- itinfo,
- lcid,
- pptinfo);
-}
-
-
-STDMETHODIMP
-CBasicAudio::GetIDsOfNames(
- REFIID riid,
- __in_ecount(cNames) LPOLESTR * rgszNames,
- UINT cNames,
- LCID lcid,
- __out_ecount(cNames) DISPID * rgdispid)
-{
- return m_basedisp.GetIDsOfNames(
- IID_IBasicAudio,
- rgszNames,
- cNames,
- lcid,
- rgdispid);
-}
-
-
-STDMETHODIMP
-CBasicAudio::Invoke(
- DISPID dispidMember,
- REFIID riid,
- LCID lcid,
- WORD wFlags,
- __in DISPPARAMS * pdispparams,
- __out_opt VARIANT * pvarResult,
- __out_opt EXCEPINFO * pexcepinfo,
- __out_opt UINT * puArgErr)
-{
- // this parameter is a dead leftover from an earlier interface
- if (IID_NULL != riid) {
- return DISP_E_UNKNOWNINTERFACE;
- }
-
- ITypeInfo * pti;
- HRESULT hr = GetTypeInfo(0, lcid, &pti);
-
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = pti->Invoke(
- (IBasicAudio *)this,
- dispidMember,
- wFlags,
- pdispparams,
- pvarResult,
- pexcepinfo,
- puArgErr);
-
- pti->Release();
- return hr;
-}
-
-
-// --- IVideoWindow implementation ----------
-
-CBaseVideoWindow::CBaseVideoWindow(__in_opt LPCTSTR pName,__in_opt LPUNKNOWN punk) :
- CUnknown(pName, punk)
-{
-}
-
-
-// overriden to publicise our interfaces
-
-STDMETHODIMP
-CBaseVideoWindow::NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv)
-{
- ValidateReadWritePtr(ppv,sizeof(PVOID));
- if (riid == IID_IVideoWindow) {
- return GetInterface( (IVideoWindow *) this, ppv);
- } else {
- return CUnknown::NonDelegatingQueryInterface(riid, ppv);
- }
-}
-
-
-STDMETHODIMP
-CBaseVideoWindow::GetTypeInfoCount(__out UINT * pctinfo)
-{
- return m_basedisp.GetTypeInfoCount(pctinfo);
-}
-
-
-STDMETHODIMP
-CBaseVideoWindow::GetTypeInfo(
- UINT itinfo,
- LCID lcid,
- __deref_out ITypeInfo ** pptinfo)
-{
- return m_basedisp.GetTypeInfo(
- IID_IVideoWindow,
- itinfo,
- lcid,
- pptinfo);
-}
-
-
-STDMETHODIMP
-CBaseVideoWindow::GetIDsOfNames(
- REFIID riid,
- __in_ecount(cNames) LPOLESTR * rgszNames,
- UINT cNames,
- LCID lcid,
- __out_ecount(cNames) DISPID * rgdispid)
-{
- return m_basedisp.GetIDsOfNames(
- IID_IVideoWindow,
- rgszNames,
- cNames,
- lcid,
- rgdispid);
-}
-
-
-STDMETHODIMP
-CBaseVideoWindow::Invoke(
- DISPID dispidMember,
- REFIID riid,
- LCID lcid,
- WORD wFlags,
- __in DISPPARAMS * pdispparams,
- __out_opt VARIANT * pvarResult,
- __out_opt EXCEPINFO * pexcepinfo,
- __out_opt UINT * puArgErr)
-{
- // this parameter is a dead leftover from an earlier interface
- if (IID_NULL != riid) {
- return DISP_E_UNKNOWNINTERFACE;
- }
-
- ITypeInfo * pti;
- HRESULT hr = GetTypeInfo(0, lcid, &pti);
-
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = pti->Invoke(
- (IVideoWindow *)this,
- dispidMember,
- wFlags,
- pdispparams,
- pvarResult,
- pexcepinfo,
- puArgErr);
-
- pti->Release();
- return hr;
-}
-
-
-// --- IBasicVideo implementation ----------
-
-
-CBaseBasicVideo::CBaseBasicVideo(__in_opt LPCTSTR pName,__in_opt LPUNKNOWN punk) :
- CUnknown(pName, punk)
-{
-}
-
-
-// overriden to publicise our interfaces
-
-STDMETHODIMP
-CBaseBasicVideo::NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv)
-{
- ValidateReadWritePtr(ppv,sizeof(PVOID));
- if (riid == IID_IBasicVideo || riid == IID_IBasicVideo2) {
- return GetInterface( static_cast<IBasicVideo2 *>(this), ppv);
- } else {
- return CUnknown::NonDelegatingQueryInterface(riid, ppv);
- }
-}
-
-
-STDMETHODIMP
-CBaseBasicVideo::GetTypeInfoCount(__out UINT * pctinfo)
-{
- return m_basedisp.GetTypeInfoCount(pctinfo);
-}
-
-
-STDMETHODIMP
-CBaseBasicVideo::GetTypeInfo(
- UINT itinfo,
- LCID lcid,
- __deref_out ITypeInfo ** pptinfo)
-{
- return m_basedisp.GetTypeInfo(
- IID_IBasicVideo,
- itinfo,
- lcid,
- pptinfo);
-}
-
-
-STDMETHODIMP
-CBaseBasicVideo::GetIDsOfNames(
- REFIID riid,
- __in_ecount(cNames) LPOLESTR * rgszNames,
- UINT cNames,
- LCID lcid,
- __out_ecount(cNames) DISPID * rgdispid)
-{
- return m_basedisp.GetIDsOfNames(
- IID_IBasicVideo,
- rgszNames,
- cNames,
- lcid,
- rgdispid);
-}
-
-
-STDMETHODIMP
-CBaseBasicVideo::Invoke(
- DISPID dispidMember,
- REFIID riid,
- LCID lcid,
- WORD wFlags,
- __in DISPPARAMS * pdispparams,
- __out_opt VARIANT * pvarResult,
- __out_opt EXCEPINFO * pexcepinfo,
- __out_opt UINT * puArgErr)
-{
- // this parameter is a dead leftover from an earlier interface
- if (IID_NULL != riid) {
- return DISP_E_UNKNOWNINTERFACE;
- }
-
- ITypeInfo * pti;
- HRESULT hr = GetTypeInfo(0, lcid, &pti);
-
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = pti->Invoke(
- (IBasicVideo *)this,
- dispidMember,
- wFlags,
- pdispparams,
- pvarResult,
- pexcepinfo,
- puArgErr);
-
- pti->Release();
- return hr;
-}
-
-
-// --- Implementation of Deferred Commands ----------
-
-
-CDispParams::CDispParams(UINT nArgs, __in_ecount(nArgs) VARIANT* pArgs, __inout_opt HRESULT *phr)
-{
- cNamedArgs = 0;
- rgdispidNamedArgs = NULL;
- cArgs = nArgs;
-
- if (cArgs) {
- rgvarg = new VARIANT[cArgs];
- if (NULL == rgvarg) {
- cArgs = 0;
- if (phr) {
- *phr = E_OUTOFMEMORY;
- }
- return;
- }
-
- for (UINT i = 0; i < cArgs; i++) {
-
- // Why aren't we using VariantCopy?
-
- VARIANT * pDest = &rgvarg[i];
- VARIANT * pSrc = &pArgs[i];
-
- pDest->vt = pSrc->vt;
- switch(pDest->vt) {
-
- case VT_I4:
- pDest->lVal = pSrc->lVal;
- break;
-
- case VT_UI1:
- pDest->bVal = pSrc->bVal;
- break;
-
- case VT_I2:
- pDest->iVal = pSrc->iVal;
- break;
-
- case VT_R4:
- pDest->fltVal = pSrc->fltVal;
- break;
-
- case VT_R8:
- pDest->dblVal = pSrc->dblVal;
- break;
-
- case VT_BOOL:
- pDest->boolVal = pSrc->boolVal;
- break;
-
- case VT_ERROR:
- pDest->scode = pSrc->scode;
- break;
-
- case VT_CY:
- pDest->cyVal = pSrc->cyVal;
- break;
-
- case VT_DATE:
- pDest->date = pSrc->date;
- break;
-
- case VT_BSTR:
- if ((PVOID)pSrc->bstrVal == NULL) {
- pDest->bstrVal = NULL;
- } else {
-
- // a BSTR is a WORD followed by a UNICODE string.
- // the pointer points just after the WORD
-
- WORD len = * (WORD*) (pSrc->bstrVal - (sizeof(WORD) / sizeof(OLECHAR)));
- OLECHAR* pch = new OLECHAR[len + (sizeof(WORD)/sizeof(OLECHAR))];
- if (pch) {
- WORD *pui = (WORD*)pch;
- *pui = len;
- pDest->bstrVal = pch + (sizeof(WORD)/sizeof(OLECHAR));
- CopyMemory(pDest->bstrVal, pSrc->bstrVal, len*sizeof(OLECHAR));
- } else {
- cArgs = i;
- if (phr) {
- *phr = E_OUTOFMEMORY;
- }
- }
- }
- break;
-
- case VT_UNKNOWN:
- pDest->punkVal = pSrc->punkVal;
- pDest->punkVal->AddRef();
- break;
-
- case VT_DISPATCH:
- pDest->pdispVal = pSrc->pdispVal;
- pDest->pdispVal->AddRef();
- break;
-
- default:
- // a type we haven't got round to adding yet!
- ASSERT(0);
- break;
- }
- }
-
- } else {
- rgvarg = NULL;
- }
-
-}
-
-
-CDispParams::~CDispParams()
-{
- for (UINT i = 0; i < cArgs; i++) {
- switch(rgvarg[i].vt) {
- case VT_BSTR:
- // Explicitly cast BSTR to PVOID to tell code scanning tools we really mean to test the pointer
- if ((PVOID)rgvarg[i].bstrVal != NULL) {
- OLECHAR * pch = rgvarg[i].bstrVal - (sizeof(WORD)/sizeof(OLECHAR));
- delete pch;
- }
- break;
-
- case VT_UNKNOWN:
- rgvarg[i].punkVal->Release();
- break;
-
- case VT_DISPATCH:
- rgvarg[i].pdispVal->Release();
- break;
- }
- }
- delete[] rgvarg;
-}
-
-
-// lifetime is controlled by refcounts (see defer.h)
-
-CDeferredCommand::CDeferredCommand(
- __inout CCmdQueue * pQ,
- __in_opt LPUNKNOWN pUnk,
- __inout HRESULT * phr,
- __in LPUNKNOWN pUnkExecutor,
- REFTIME time,
- __in GUID* iid,
- long dispidMethod,
- short wFlags,
- long nArgs,
- __in_ecount(nArgs) VARIANT* pDispParams,
- __out VARIANT* pvarResult,
- __out short* puArgErr,
- BOOL bStream
- ) :
- CUnknown(NAME("DeferredCommand"), pUnk),
- m_pQueue(pQ),
- m_pUnk(pUnkExecutor),
- m_iid(iid),
- m_dispidMethod(dispidMethod),
- m_wFlags(wFlags),
- m_DispParams(nArgs, pDispParams, phr),
- m_pvarResult(pvarResult),
- m_bStream(bStream),
- m_hrResult(E_ABORT)
-
-{
- // convert REFTIME to REFERENCE_TIME
- COARefTime convertor(time);
- m_time = convertor;
-
- // no check of time validity - it's ok to queue a command that's
- // already late
-
- // check iid is supportable on pUnk by QueryInterface for it
- IUnknown * pInterface;
- HRESULT hr = m_pUnk->QueryInterface(GetIID(), (void**) &pInterface);
- if (FAILED(hr)) {
- *phr = hr;
- return;
- }
- pInterface->Release();
-
-
- // !!! check dispidMethod and param/return types using typelib
- ITypeInfo *pti;
- hr = m_Dispatch.GetTypeInfo(*iid, 0, 0, &pti);
- if (FAILED(hr)) {
- *phr = hr;
- return;
- }
- // !!! some sort of ITypeInfo validity check here
- pti->Release();
-
-
- // Fix up the dispid for put and get
- if (wFlags == DISPATCH_PROPERTYPUT) {
- m_DispParams.cNamedArgs = 1;
- m_DispId = DISPID_PROPERTYPUT;
- m_DispParams.rgdispidNamedArgs = &m_DispId;
- }
-
- // all checks ok - add to queue
- hr = pQ->Insert(this);
- if (FAILED(hr)) {
- *phr = hr;
- }
-}
-
-
-// refcounts are held by caller of InvokeAt... and by list. So if
-// we get here, we can't be on the list
-
-#if 0
-CDeferredCommand::~CDeferredCommand()
-{
- // this assert is invalid since if the queue is deleted while we are
- // still on the queue, we will have been removed by the queue and this
- // m_pQueue will not have been modified.
- // ASSERT(m_pQueue == NULL);
-
- // we don't hold a ref count on pUnk, which is the object that should
- // execute the command.
- // This is because there would otherwise be a circular refcount problem
- // since pUnk probably owns the CmdQueue object that has a refcount
- // on us.
- // The lifetime of pUnk is guaranteed by it being part of, or lifetime
- // controlled by, our parent object. As long as we are on the list, pUnk
- // must be valid. Once we are off the list, we do not use pUnk.
-
-}
-#endif
-
-
-// overriden to publicise our interfaces
-
-STDMETHODIMP
-CDeferredCommand::NonDelegatingQueryInterface(REFIID riid, __out void **ppv)
-{
- ValidateReadWritePtr(ppv,sizeof(PVOID));
- if (riid == IID_IDeferredCommand) {
- return GetInterface( (IDeferredCommand *) this, ppv);
- } else {
- return CUnknown::NonDelegatingQueryInterface(riid, ppv);
- }
-}
-
-
-// remove from q. this will reduce the refcount by one (since the q
-// holds a count) but can't make us go away since he must have a
-// refcount in order to call this method.
-
-STDMETHODIMP
-CDeferredCommand::Cancel()
-{
- if (m_pQueue == NULL) {
- return VFW_E_ALREADY_CANCELLED;
- }
-
- HRESULT hr = m_pQueue->Remove(this);
- if (FAILED(hr)) {
- return hr;
- }
-
- m_pQueue = NULL;
- return S_OK;
-}
-
-
-STDMETHODIMP
-CDeferredCommand::Confidence(__out LONG* pConfidence)
-{
- return E_NOTIMPL;
-}
-
-
-STDMETHODIMP
-CDeferredCommand::GetHResult(__out HRESULT * phrResult)
-{
- CheckPointer(phrResult,E_POINTER);
- ValidateReadWritePtr(phrResult,sizeof(HRESULT));
-
- if (m_pQueue != NULL) {
- return E_ABORT;
- }
- *phrResult = m_hrResult;
- return S_OK;
-}
-
-
-// set the time to be a new time (checking that it is valid) and
-// then requeue
-
-STDMETHODIMP
-CDeferredCommand::Postpone(REFTIME newtime)
-{
-
- // check that this time is not past
- // convert REFTIME to REFERENCE_TIME
- COARefTime convertor(newtime);
-
- // check that the time has not passed
- if (m_pQueue->CheckTime(convertor, IsStreamTime())) {
- return VFW_E_TIME_ALREADY_PASSED;
- }
-
- // extract from list
- HRESULT hr = m_pQueue->Remove(this);
- if (FAILED(hr)) {
- return hr;
- }
-
- // change time
- m_time = convertor;
-
- // requeue
- hr = m_pQueue->Insert(this);
-
- return hr;
-}
-
-
-HRESULT
-CDeferredCommand::Invoke()
-{
- // check that we are still outstanding
- if (m_pQueue == NULL) {
- return VFW_E_ALREADY_CANCELLED;
- }
-
- // get the type info
- ITypeInfo* pti;
- HRESULT hr = m_Dispatch.GetTypeInfo(GetIID(), 0, 0, &pti);
- if (FAILED(hr)) {
- return hr;
- }
-
- // qi for the expected interface and then invoke it. Note that we have to
- // treat the returned interface as IUnknown since we don't know its type.
- IUnknown* pInterface;
-
- hr = m_pUnk->QueryInterface(GetIID(), (void**) &pInterface);
- if (FAILED(hr)) {
- pti->Release();
- return hr;
- }
-
- EXCEPINFO expinfo;
- UINT uArgErr;
- m_hrResult = pti->Invoke(
- pInterface,
- GetMethod(),
- GetFlags(),
- GetParams(),
- GetResult(),
- &expinfo,
- &uArgErr);
-
- // release the interface we QI'd for
- pInterface->Release();
- pti->Release();
-
-
- // remove from list whether or not successful
- // or we loop indefinitely
- hr = m_pQueue->Remove(this);
- m_pQueue = NULL;
- return hr;
-}
-
-
-
-// --- CCmdQueue methods ----------
-
-
-CCmdQueue::CCmdQueue(__inout_opt HRESULT *phr) :
- m_listPresentation(NAME("Presentation time command list")),
- m_listStream(NAME("Stream time command list")),
- m_evDue(TRUE, phr), // manual reset
- m_dwAdvise(0),
- m_pClock(NULL),
- m_bRunning(FALSE)
-{
-}
-
-
-CCmdQueue::~CCmdQueue()
-{
- // empty all our lists
-
- // we hold a refcount on each, so traverse and Release each
- // entry then RemoveAll to empty the list
- POSITION pos = m_listPresentation.GetHeadPosition();
-
- while(pos) {
- CDeferredCommand* pCmd = m_listPresentation.GetNext(pos);
- pCmd->Release();
- }
- m_listPresentation.RemoveAll();
-
- pos = m_listStream.GetHeadPosition();
-
- while(pos) {
- CDeferredCommand* pCmd = m_listStream.GetNext(pos);
- pCmd->Release();
- }
- m_listStream.RemoveAll();
-
- if (m_pClock) {
- if (m_dwAdvise) {
- m_pClock->Unadvise(m_dwAdvise);
- m_dwAdvise = 0;
- }
- m_pClock->Release();
- }
-}
-
-
-// returns a new CDeferredCommand object that will be initialised with
-// the parameters and will be added to the queue during construction.
-// returns S_OK if successfully created otherwise an error and
-// no object has been queued.
-
-HRESULT
-CCmdQueue::New(
- __out CDeferredCommand **ppCmd,
- __in LPUNKNOWN pUnk, // this object will execute command
- REFTIME time,
- __in GUID* iid,
- long dispidMethod,
- short wFlags,
- long cArgs,
- __in_ecount(cArgs) VARIANT* pDispParams,
- __out VARIANT* pvarResult,
- __out short* puArgErr,
- BOOL bStream
-)
-{
- CAutoLock lock(&m_Lock);
-
- HRESULT hr = S_OK;
- *ppCmd = NULL;
-
- CDeferredCommand* pCmd;
- pCmd = new CDeferredCommand(
- this,
- NULL, // not aggregated
- &hr,
- pUnk, // this guy will execute
- time,
- iid,
- dispidMethod,
- wFlags,
- cArgs,
- pDispParams,
- pvarResult,
- puArgErr,
- bStream);
-
- if (pCmd == NULL) {
- hr = E_OUTOFMEMORY;
- } else {
- *ppCmd = pCmd;
- }
- return hr;
-}
-
-
-HRESULT
-CCmdQueue::Insert(__in CDeferredCommand* pCmd)
-{
- CAutoLock lock(&m_Lock);
-
- // addref the item
- pCmd->AddRef();
-
- CGenericList<CDeferredCommand> * pList;
- if (pCmd->IsStreamTime()) {
- pList = &m_listStream;
- } else {
- pList = &m_listPresentation;
- }
- POSITION pos = pList->GetHeadPosition();
-
- // seek past all items that are before us
- while (pos &&
- (pList->GetValid(pos)->GetTime() <= pCmd->GetTime())) {
-
- pList->GetNext(pos);
- }
-
- // now at end of list or in front of items that come later
- if (!pos) {
- pList->AddTail(pCmd);
- } else {
- pList->AddBefore(pos, pCmd);
- }
-
- SetTimeAdvise();
- return S_OK;
-}
-
-
-HRESULT
-CCmdQueue::Remove(__in CDeferredCommand* pCmd)
-{
- CAutoLock lock(&m_Lock);
- HRESULT hr = S_OK;
-
- CGenericList<CDeferredCommand> * pList;
- if (pCmd->IsStreamTime()) {
- pList = &m_listStream;
- } else {
- pList = &m_listPresentation;
- }
- POSITION pos = pList->GetHeadPosition();
-
- // traverse the list
- while (pos && (pList->GetValid(pos) != pCmd)) {
- pList->GetNext(pos);
- }
-
- // did we drop off the end?
- if (!pos) {
- hr = VFW_E_NOT_FOUND;
- } else {
-
- // found it - now take off list
- pList->Remove(pos);
-
- // Insert did an AddRef, so release it
- pCmd->Release();
-
- // check that timer request is still for earliest time
- SetTimeAdvise();
- }
- return hr;
-}
-
-
-// set the clock used for timing
-
-HRESULT
-CCmdQueue::SetSyncSource(__in_opt IReferenceClock* pClock)
-{
- CAutoLock lock(&m_Lock);
-
- // addref the new clock first in case they are the same
- if (pClock) {
- pClock->AddRef();
- }
-
- // kill any advise on the old clock
- if (m_pClock) {
- if (m_dwAdvise) {
- m_pClock->Unadvise(m_dwAdvise);
- m_dwAdvise = 0;
- }
- m_pClock->Release();
- }
- m_pClock = pClock;
-
- // set up a new advise
- SetTimeAdvise();
- return S_OK;
-}
-
-
-// set up a timer event with the reference clock
-
-void
-CCmdQueue::SetTimeAdvise(void)
-{
- // make sure we have a clock to use
- if (!m_pClock) {
- return;
- }
-
- // reset the event whenever we are requesting a new signal
- m_evDue.Reset();
-
- // time 0 is earliest
- CRefTime current;
-
- // find the earliest presentation time
- POSITION pos = m_listPresentation.GetHeadPosition();
- if (pos != NULL) {
- current = m_listPresentation.GetValid(pos)->GetTime();
- }
-
- // if we're running, check the stream times too
- if (m_bRunning) {
-
- CRefTime t;
- pos = m_listStream.GetHeadPosition();
- if (NULL != pos) {
- t = m_listStream.GetValid(pos)->GetTime();
-
- // add on stream time offset to get presentation time
- t += m_StreamTimeOffset;
-
- // is this earlier?
- if ((current == TimeZero) || (t < current)) {
- current = t;
- }
- }
- }
-
- // need to change?
- if ((current > TimeZero) && (current != m_tCurrentAdvise)) {
- if (m_dwAdvise) {
- m_pClock->Unadvise(m_dwAdvise);
- // reset the event whenever we are requesting a new signal
- m_evDue.Reset();
- }
-
- // ask for time advice - the first two params are either
- // stream time offset and stream time or
- // presentation time and 0. we always use the latter
- HRESULT hr = m_pClock->AdviseTime(
- (REFERENCE_TIME)current,
- TimeZero,
- (HEVENT) HANDLE(m_evDue),
- &m_dwAdvise);
-
- ASSERT(SUCCEEDED(hr));
- m_tCurrentAdvise = current;
- }
-}
-
-
-// switch to run mode. Streamtime to Presentation time mapping known.
-
-HRESULT
-CCmdQueue::Run(REFERENCE_TIME tStreamTimeOffset)
-{
- CAutoLock lock(&m_Lock);
-
- m_StreamTimeOffset = tStreamTimeOffset;
- m_bRunning = TRUE;
-
- // ensure advise is accurate
- SetTimeAdvise();
- return S_OK;
-}
-
-
-// switch to Stopped or Paused mode. Time mapping not known.
-
-HRESULT
-CCmdQueue::EndRun()
-{
- CAutoLock lock(&m_Lock);
-
- m_bRunning = FALSE;
-
- // check timer setting - stream times
- SetTimeAdvise();
- return S_OK;
-}
-
-
-// return a pointer to the next due command. Blocks for msTimeout
-// milliseconds until there is a due command.
-// Stream-time commands will only become due between Run and Endrun calls.
-// The command remains queued until invoked or cancelled.
-// Returns E_ABORT if timeout occurs, otherwise S_OK (or other error).
-//
-// returns an AddRef'd object
-
-HRESULT
-CCmdQueue::GetDueCommand(__out CDeferredCommand ** ppCmd, long msTimeout)
-{
- // loop until we timeout or find a due command
- for (;;) {
-
- {
- CAutoLock lock(&m_Lock);
-
-
- // find the earliest command
- CDeferredCommand * pCmd = NULL;
-
- // check the presentation time and the
- // stream time list to find the earliest
-
- POSITION pos = m_listPresentation.GetHeadPosition();
-
- if (NULL != pos) {
- pCmd = m_listPresentation.GetValid(pos);
- }
-
- if (m_bRunning) {
- pos = m_listStream.GetHeadPosition();
- if (NULL != pos) {
- CDeferredCommand* pStrm = m_listStream.GetValid(pos);
-
- CRefTime t = pStrm->GetTime() + m_StreamTimeOffset;
- if (!pCmd || (t < pCmd->GetTime())) {
- pCmd = pStrm;
- }
- }
- }
-
- // if we have found one, is it due?
- if (pCmd) {
- if (CheckTime(pCmd->GetTime(), pCmd->IsStreamTime())) {
-
- // yes it's due - addref it
- pCmd->AddRef();
- *ppCmd = pCmd;
- return S_OK;
- }
- }
- }
-
- // block until the advise is signalled
- if (WaitForSingleObject(m_evDue, msTimeout) != WAIT_OBJECT_0) {
- return E_ABORT;
- }
- }
-}
-
-
-// return a pointer to a command that will be due for a given time.
-// Pass in a stream time here. The stream time offset will be passed
-// in via the Run method.
-// Commands remain queued until invoked or cancelled.
-// This method will not block. It will report E_ABORT if there are no
-// commands due yet.
-//
-// returns an AddRef'd object
-
-HRESULT
-CCmdQueue::GetCommandDueFor(REFERENCE_TIME rtStream, __out CDeferredCommand**ppCmd)
-{
- CAutoLock lock(&m_Lock);
-
- CRefTime tStream(rtStream);
-
- // find the earliest stream and presentation time commands
- CDeferredCommand* pStream = NULL;
- POSITION pos = m_listStream.GetHeadPosition();
- if (NULL != pos) {
- pStream = m_listStream.GetValid(pos);
- }
- CDeferredCommand* pPresent = NULL;
- pos = m_listPresentation.GetHeadPosition();
- if (NULL != pos) {
- pPresent = m_listPresentation.GetValid(pos);
- }
-
- // is there a presentation time that has passed already
- if (pPresent && CheckTime(pPresent->GetTime(), FALSE)) {
- pPresent->AddRef();
- *ppCmd = pPresent;
- return S_OK;
- }
-
- // is there a stream time command due before this stream time
- if (pStream && (pStream->GetTime() <= tStream)) {
- pStream->AddRef();
- *ppCmd = pStream;
- return S_OK;
- }
-
- // if we are running, we can map presentation times to
- // stream time. In this case, is there a presentation time command
- // that will be due before this stream time is presented?
- if (m_bRunning && pPresent) {
-
- // this stream time will appear at...
- tStream += m_StreamTimeOffset;
-
- // due before that?
- if (pPresent->GetTime() <= tStream) {
- *ppCmd = pPresent;
- return S_OK;
- }
- }
-
- // no commands due yet
- return VFW_E_NOT_FOUND;
-}
-
diff --git a/dll/src/baseclasses/ctlutil.h b/dll/src/baseclasses/ctlutil.h
deleted file mode 100644
index 7e4719c..0000000
--- a/dll/src/baseclasses/ctlutil.h
+++ /dev/null
@@ -1,923 +0,0 @@
-//------------------------------------------------------------------------------
-// File: CtlUtil.h
-//
-// Desc: DirectShow base classes.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-// Base classes implementing IDispatch parsing for the basic control dual
-// interfaces. Derive from these and implement just the custom method and
-// property methods. We also implement CPosPassThru that can be used by
-// renderers and transforms to pass by IMediaPosition and IMediaSeeking
-
-#ifndef __CTLUTIL__
-#define __CTLUTIL__
-
-// OLE Automation has different ideas of TRUE and FALSE
-
-#define OATRUE (-1)
-#define OAFALSE (0)
-
-
-// It's possible that we could replace this class with CreateStdDispatch
-
-class CBaseDispatch
-{
- ITypeInfo * m_pti;
-
-public:
-
- CBaseDispatch() : m_pti(NULL) {}
- ~CBaseDispatch();
-
- /* IDispatch methods */
- STDMETHODIMP GetTypeInfoCount(__out UINT * pctinfo);
-
- STDMETHODIMP GetTypeInfo(
- REFIID riid,
- UINT itinfo,
- LCID lcid,
- __deref_out ITypeInfo ** pptinfo);
-
- STDMETHODIMP GetIDsOfNames(
- REFIID riid,
- __in_ecount(cNames) LPOLESTR * rgszNames,
- UINT cNames,
- LCID lcid,
- __out_ecount(cNames) DISPID * rgdispid);
-};
-
-
-class AM_NOVTABLE CMediaControl :
- public IMediaControl,
- public CUnknown
-{
- CBaseDispatch m_basedisp;
-
-public:
-
- CMediaControl(const TCHAR *, LPUNKNOWN);
-
- DECLARE_IUNKNOWN
-
- // override this to publicise our interfaces
- STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
-
- /* IDispatch methods */
- STDMETHODIMP GetTypeInfoCount(__out UINT * pctinfo);
-
- STDMETHODIMP GetTypeInfo(
- UINT itinfo,
- LCID lcid,
- __deref_out ITypeInfo ** pptinfo);
-
- STDMETHODIMP GetIDsOfNames(
- REFIID riid,
- __in_ecount(cNames) LPOLESTR * rgszNames,
- UINT cNames,
- LCID lcid,
- __out_ecount(cNames) DISPID * rgdispid);
-
- STDMETHODIMP Invoke(
- DISPID dispidMember,
- REFIID riid,
- LCID lcid,
- WORD wFlags,
- __in DISPPARAMS * pdispparams,
- __out_opt VARIANT * pvarResult,
- __out_opt EXCEPINFO * pexcepinfo,
- __out_opt UINT * puArgErr);
-};
-
-
-class AM_NOVTABLE CMediaEvent :
- public IMediaEventEx,
- public CUnknown
-{
- CBaseDispatch m_basedisp;
-
-public:
-
- CMediaEvent(__in_opt LPCTSTR, __in_opt LPUNKNOWN);
-
- DECLARE_IUNKNOWN
-
- // override this to publicise our interfaces
- STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
-
- /* IDispatch methods */
- STDMETHODIMP GetTypeInfoCount(__out UINT * pctinfo);
-
- STDMETHODIMP GetTypeInfo(
- UINT itinfo,
- LCID lcid,
- __deref_out ITypeInfo ** pptinfo);
-
- STDMETHODIMP GetIDsOfNames(
- REFIID riid,
- __in_ecount(cNames) LPOLESTR * rgszNames,
- UINT cNames,
- LCID lcid,
- __out_ecount(cNames) DISPID * rgdispid);
-
- STDMETHODIMP Invoke(
- DISPID dispidMember,
- REFIID riid,
- LCID lcid,
- WORD wFlags,
- __in DISPPARAMS * pdispparams,
- __out_opt VARIANT * pvarResult,
- __out_opt EXCEPINFO * pexcepinfo,
- __out_opt UINT * puArgErr);
-};
-
-
-class AM_NOVTABLE CMediaPosition :
- public IMediaPosition,
- public CUnknown
-{
- CBaseDispatch m_basedisp;
-
-
-public:
-
- CMediaPosition(__in_opt LPCTSTR, __in_opt LPUNKNOWN);
- CMediaPosition(__in_opt LPCTSTR, __in_opt LPUNKNOWN, __inout HRESULT *phr);
-
- DECLARE_IUNKNOWN
-
- // override this to publicise our interfaces
- STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
-
- /* IDispatch methods */
- STDMETHODIMP GetTypeInfoCount(__out UINT * pctinfo);
-
- STDMETHODIMP GetTypeInfo(
- UINT itinfo,
- LCID lcid,
- __deref_out ITypeInfo ** pptinfo);
-
- STDMETHODIMP GetIDsOfNames(
- REFIID riid,
- __in_ecount(cNames) LPOLESTR * rgszNames,
- UINT cNames,
- LCID lcid,
- __out_ecount(cNames) DISPID * rgdispid);
-
- STDMETHODIMP Invoke(
- DISPID dispidMember,
- REFIID riid,
- LCID lcid,
- WORD wFlags,
- __in DISPPARAMS * pdispparams,
- __out_opt VARIANT * pvarResult,
- __out_opt EXCEPINFO * pexcepinfo,
- __out_opt UINT * puArgErr);
-
-};
-
-
-// OA-compatibility means that we must use double as the RefTime value,
-// and REFERENCE_TIME (essentially a LONGLONG) within filters.
-// this class converts between the two
-
-class COARefTime : public CRefTime {
-public:
-
- COARefTime() {
- };
-
- COARefTime(CRefTime t)
- : CRefTime(t)
- {
- };
-
- COARefTime(REFERENCE_TIME t)
- : CRefTime(t)
- {
- };
-
- COARefTime(double d) {
- m_time = (LONGLONG) (d * 10000000);
- };
-
- operator double() {
- return double(m_time) / 10000000;
- };
-
- operator REFERENCE_TIME() {
- return m_time;
- };
-
- COARefTime& operator=(const double& rd) {
- m_time = (LONGLONG) (rd * 10000000);
- return *this;
- }
-
- COARefTime& operator=(const REFERENCE_TIME& rt) {
- m_time = rt;
- return *this;
- }
-
- inline BOOL operator==(const COARefTime& rt)
- {
- return m_time == rt.m_time;
- };
-
- inline BOOL operator!=(const COARefTime& rt)
- {
- return m_time != rt.m_time;
- };
-
- inline BOOL operator < (const COARefTime& rt)
- {
- return m_time < rt.m_time;
- };
-
- inline BOOL operator > (const COARefTime& rt)
- {
- return m_time > rt.m_time;
- };
-
- inline BOOL operator >= (const COARefTime& rt)
- {
- return m_time >= rt.m_time;
- };
-
- inline BOOL operator <= (const COARefTime& rt)
- {
- return m_time <= rt.m_time;
- };
-
- inline COARefTime operator+(const COARefTime& rt)
- {
- return COARefTime(m_time + rt.m_time);
- };
-
- inline COARefTime operator-(const COARefTime& rt)
- {
- return COARefTime(m_time - rt.m_time);
- };
-
- inline COARefTime operator*(LONG l)
- {
- return COARefTime(m_time * l);
- };
-
- inline COARefTime operator/(LONG l)
- {
- return COARefTime(m_time / l);
- };
-
-private:
- // Prevent bugs from constructing from LONG (which gets
- // converted to double and then multiplied by 10000000
- COARefTime(LONG);
- LONG operator=(LONG);
-};
-
-
-// A utility class that handles IMediaPosition and IMediaSeeking on behalf
-// of single-input pin renderers, or transform filters.
-//
-// Renderers will expose this from the filter; transform filters will
-// expose it from the output pin and not the renderer.
-//
-// Create one of these, giving it your IPin* for your input pin, and delegate
-// all IMediaPosition methods to it. It will query the input pin for
-// IMediaPosition and respond appropriately.
-//
-// Call ForceRefresh if the pin connection changes.
-//
-// This class no longer caches the upstream IMediaPosition or IMediaSeeking
-// it acquires it on each method call. This means ForceRefresh is not needed.
-// The method is kept for source compatibility and to minimise the changes
-// if we need to put it back later for performance reasons.
-
-class CPosPassThru : public IMediaSeeking, public CMediaPosition
-{
- IPin *m_pPin;
-
- HRESULT GetPeer(__deref_out IMediaPosition **ppMP);
- HRESULT GetPeerSeeking(__deref_out IMediaSeeking **ppMS);
-
-public:
-
- CPosPassThru(__in_opt LPCTSTR, __in_opt LPUNKNOWN, __inout HRESULT*, IPin *);
- DECLARE_IUNKNOWN
-
- HRESULT ForceRefresh() {
- return S_OK;
- };
-
- // override to return an accurate current position
- virtual HRESULT GetMediaTime(__out LONGLONG *pStartTime, __out_opt LONGLONG *pEndTime) {
- return E_FAIL;
- }
-
- STDMETHODIMP NonDelegatingQueryInterface(REFIID riid,__deref_out void **ppv);
-
- // IMediaSeeking methods
- STDMETHODIMP GetCapabilities( __out DWORD * pCapabilities );
- STDMETHODIMP CheckCapabilities( __inout DWORD * pCapabilities );
- STDMETHODIMP SetTimeFormat(const GUID * pFormat);
- STDMETHODIMP GetTimeFormat(__out GUID *pFormat);
- STDMETHODIMP IsUsingTimeFormat(const GUID * pFormat);
- STDMETHODIMP IsFormatSupported( const GUID * pFormat);
- STDMETHODIMP QueryPreferredFormat( __out GUID *pFormat);
- STDMETHODIMP ConvertTimeFormat(__out LONGLONG * pTarget,
- __in_opt const GUID * pTargetFormat,
- LONGLONG Source,
- __in_opt const GUID * pSourceFormat );
- STDMETHODIMP SetPositions( __inout_opt LONGLONG * pCurrent, DWORD CurrentFlags
- , __inout_opt LONGLONG * pStop, DWORD StopFlags );
-
- STDMETHODIMP GetPositions( __out_opt LONGLONG * pCurrent, __out_opt LONGLONG * pStop );
- STDMETHODIMP GetCurrentPosition( __out LONGLONG * pCurrent );
- STDMETHODIMP GetStopPosition( __out LONGLONG * pStop );
- STDMETHODIMP SetRate( double dRate);
- STDMETHODIMP GetRate( __out double * pdRate);
- STDMETHODIMP GetDuration( __out LONGLONG *pDuration);
- STDMETHODIMP GetAvailable( __out_opt LONGLONG *pEarliest, __out_opt LONGLONG *pLatest );
- STDMETHODIMP GetPreroll( __out LONGLONG *pllPreroll );
-
- // IMediaPosition properties
- STDMETHODIMP get_Duration(__out REFTIME * plength);
- STDMETHODIMP put_CurrentPosition(REFTIME llTime);
- STDMETHODIMP get_StopTime(__out REFTIME * pllTime);
- STDMETHODIMP put_StopTime(REFTIME llTime);
- STDMETHODIMP get_PrerollTime(__out REFTIME * pllTime);
- STDMETHODIMP put_PrerollTime(REFTIME llTime);
- STDMETHODIMP get_Rate(__out double * pdRate);
- STDMETHODIMP put_Rate(double dRate);
- STDMETHODIMP get_CurrentPosition(__out REFTIME * pllTime);
- STDMETHODIMP CanSeekForward(__out LONG *pCanSeekForward);
- STDMETHODIMP CanSeekBackward(__out LONG *pCanSeekBackward);
-
-private:
- HRESULT GetSeekingLongLong( HRESULT (__stdcall IMediaSeeking::*pMethod)( LONGLONG * ),
- __out LONGLONG * pll );
-};
-
-
-// Adds the ability to return a current position
-
-class CRendererPosPassThru : public CPosPassThru
-{
- CCritSec m_PositionLock; // Locks access to our position
- LONGLONG m_StartMedia; // Start media time last seen
- LONGLONG m_EndMedia; // And likewise the end media
- BOOL m_bReset; // Have media times been set
-
-public:
-
- // Used to help with passing media times through graph
-
- CRendererPosPassThru(__in_opt LPCTSTR, __in_opt LPUNKNOWN, __inout HRESULT*, IPin *);
- HRESULT RegisterMediaTime(IMediaSample *pMediaSample);
- HRESULT RegisterMediaTime(LONGLONG StartTime,LONGLONG EndTime);
- HRESULT GetMediaTime(__out LONGLONG *pStartTime,__out_opt LONGLONG *pEndTime);
- HRESULT ResetMediaTime();
- HRESULT EOS();
-};
-
-STDAPI CreatePosPassThru(
- __in_opt LPUNKNOWN pAgg,
- BOOL bRenderer,
- IPin *pPin,
- __deref_out IUnknown **ppPassThru
-);
-
-// A class that handles the IDispatch part of IBasicAudio and leaves the
-// properties and methods themselves pure virtual.
-
-class AM_NOVTABLE CBasicAudio : public IBasicAudio, public CUnknown
-{
- CBaseDispatch m_basedisp;
-
-public:
-
- CBasicAudio(__in_opt LPCTSTR, __in_opt LPUNKNOWN);
-
- DECLARE_IUNKNOWN
-
- // override this to publicise our interfaces
- STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
-
- /* IDispatch methods */
- STDMETHODIMP GetTypeInfoCount(__out UINT * pctinfo);
-
- STDMETHODIMP GetTypeInfo(
- UINT itinfo,
- LCID lcid,
- __deref_out ITypeInfo ** pptinfo);
-
- STDMETHODIMP GetIDsOfNames(
- REFIID riid,
- __in_ecount(cNames) LPOLESTR * rgszNames,
- UINT cNames,
- LCID lcid,
- __out_ecount(cNames) DISPID * rgdispid);
-
- STDMETHODIMP Invoke(
- DISPID dispidMember,
- REFIID riid,
- LCID lcid,
- WORD wFlags,
- __in DISPPARAMS * pdispparams,
- __out_opt VARIANT * pvarResult,
- __out_opt EXCEPINFO * pexcepinfo,
- __out_opt UINT * puArgErr);
-};
-
-
-// A class that handles the IDispatch part of IBasicVideo and leaves the
-// properties and methods themselves pure virtual.
-
-class AM_NOVTABLE CBaseBasicVideo : public IBasicVideo2, public CUnknown
-{
- CBaseDispatch m_basedisp;
-
-public:
-
- CBaseBasicVideo(__in_opt LPCTSTR, __in_opt LPUNKNOWN);
-
- DECLARE_IUNKNOWN
-
- // override this to publicise our interfaces
- STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
-
- /* IDispatch methods */
- STDMETHODIMP GetTypeInfoCount(__out UINT * pctinfo);
-
- STDMETHODIMP GetTypeInfo(
- UINT itinfo,
- LCID lcid,
- __deref_out ITypeInfo ** pptinfo);
-
- STDMETHODIMP GetIDsOfNames(
- REFIID riid,
- __in_ecount(cNames) LPOLESTR * rgszNames,
- UINT cNames,
- LCID lcid,
- __out_ecount(cNames) DISPID * rgdispid);
-
- STDMETHODIMP Invoke(
- DISPID dispidMember,
- REFIID riid,
- LCID lcid,
- WORD wFlags,
- __in DISPPARAMS * pdispparams,
- __out_opt VARIANT * pvarResult,
- __out_opt EXCEPINFO * pexcepinfo,
- __out_opt UINT * puArgErr);
-
- STDMETHODIMP GetPreferredAspectRatio(
- __out long *plAspectX,
- __out long *plAspectY)
- {
- return E_NOTIMPL;
- }
-};
-
-
-// A class that handles the IDispatch part of IVideoWindow and leaves the
-// properties and methods themselves pure virtual.
-
-class AM_NOVTABLE CBaseVideoWindow : public IVideoWindow, public CUnknown
-{
- CBaseDispatch m_basedisp;
-
-public:
-
- CBaseVideoWindow(__in_opt LPCTSTR, __in_opt LPUNKNOWN);
-
- DECLARE_IUNKNOWN
-
- // override this to publicise our interfaces
- STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
-
- /* IDispatch methods */
- STDMETHODIMP GetTypeInfoCount(__out UINT * pctinfo);
-
- STDMETHODIMP GetTypeInfo(
- UINT itinfo,
- LCID lcid,
- __deref_out ITypeInfo ** pptinfo);
-
- STDMETHODIMP GetIDsOfNames(
- REFIID riid,
- __in_ecount(cNames) LPOLESTR * rgszNames,
- UINT cNames,
- LCID lcid,
- __out_ecount(cNames) DISPID * rgdispid);
-
- STDMETHODIMP Invoke(
- DISPID dispidMember,
- REFIID riid,
- LCID lcid,
- WORD wFlags,
- __in DISPPARAMS * pdispparams,
- __out_opt VARIANT * pvarResult,
- __out_opt EXCEPINFO * pexcepinfo,
- __out_opt UINT * puArgErr);
-};
-
-
-// abstract class to help source filters with their implementation
-// of IMediaPosition. Derive from this and set the duration (and stop
-// position). Also override NotifyChange to do something when the properties
-// change.
-
-class AM_NOVTABLE CSourcePosition : public CMediaPosition
-{
-
-public:
- CSourcePosition(__in_opt LPCTSTR, __in_opt LPUNKNOWN, __inout HRESULT*, __in CCritSec *);
-
- // IMediaPosition methods
- STDMETHODIMP get_Duration(__out REFTIME * plength);
- STDMETHODIMP put_CurrentPosition(REFTIME llTime);
- STDMETHODIMP get_StopTime(__out REFTIME * pllTime);
- STDMETHODIMP put_StopTime(REFTIME llTime);
- STDMETHODIMP get_PrerollTime(__out REFTIME * pllTime);
- STDMETHODIMP put_PrerollTime(REFTIME llTime);
- STDMETHODIMP get_Rate(__out double * pdRate);
- STDMETHODIMP put_Rate(double dRate);
- STDMETHODIMP CanSeekForward(__out LONG *pCanSeekForward);
- STDMETHODIMP CanSeekBackward(__out LONG *pCanSeekBackward);
-
- // override if you can return the data you are actually working on
- STDMETHODIMP get_CurrentPosition(__out REFTIME * pllTime) {
- return E_NOTIMPL;
- };
-
-protected:
-
- // we call this to notify changes. Override to handle them
- virtual HRESULT ChangeStart() PURE;
- virtual HRESULT ChangeStop() PURE;
- virtual HRESULT ChangeRate() PURE;
-
- COARefTime m_Duration;
- COARefTime m_Start;
- COARefTime m_Stop;
- double m_Rate;
-
- CCritSec * m_pLock;
-};
-
-class AM_NOVTABLE CSourceSeeking :
- public IMediaSeeking,
- public CUnknown
-{
-
-public:
-
- DECLARE_IUNKNOWN;
- STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
-
- // IMediaSeeking methods
-
- STDMETHODIMP IsFormatSupported(const GUID * pFormat);
- STDMETHODIMP QueryPreferredFormat(__out GUID *pFormat);
- STDMETHODIMP SetTimeFormat(const GUID * pFormat);
- STDMETHODIMP IsUsingTimeFormat(const GUID * pFormat);
- STDMETHODIMP GetTimeFormat(__out GUID *pFormat);
- STDMETHODIMP GetDuration(__out LONGLONG *pDuration);
- STDMETHODIMP GetStopPosition(__out LONGLONG *pStop);
- STDMETHODIMP GetCurrentPosition(__out LONGLONG *pCurrent);
- STDMETHODIMP GetCapabilities( __out DWORD * pCapabilities );
- STDMETHODIMP CheckCapabilities( __inout DWORD * pCapabilities );
- STDMETHODIMP ConvertTimeFormat( __out LONGLONG * pTarget,
- __in_opt const GUID * pTargetFormat,
- LONGLONG Source,
- __in_opt const GUID * pSourceFormat );
-
- STDMETHODIMP SetPositions( __inout_opt LONGLONG * pCurrent, DWORD CurrentFlags
- , __inout_opt LONGLONG * pStop, DWORD StopFlags );
-
- STDMETHODIMP GetPositions( __out_opt LONGLONG * pCurrent, __out_opt LONGLONG * pStop );
-
- STDMETHODIMP GetAvailable( __out_opt LONGLONG * pEarliest, __out_opt LONGLONG * pLatest );
- STDMETHODIMP SetRate( double dRate);
- STDMETHODIMP GetRate( __out double * pdRate);
- STDMETHODIMP GetPreroll(__out LONGLONG *pPreroll);
-
-
-protected:
-
- // ctor
- CSourceSeeking(__in_opt LPCTSTR, __in_opt LPUNKNOWN, __inout HRESULT*, __in CCritSec *);
-
- // we call this to notify changes. Override to handle them
- virtual HRESULT ChangeStart() PURE;
- virtual HRESULT ChangeStop() PURE;
- virtual HRESULT ChangeRate() PURE;
-
- CRefTime m_rtDuration; // length of stream
- CRefTime m_rtStart; // source will start here
- CRefTime m_rtStop; // source will stop here
- double m_dRateSeeking;
-
- // seeking capabilities
- DWORD m_dwSeekingCaps;
-
- CCritSec * m_pLock;
-};
-
-
-// Base classes supporting Deferred commands.
-
-// Deferred commands are queued by calls to methods on the IQueueCommand
-// interface, exposed by the filtergraph and by some filters. A successful
-// call to one of these methods will return an IDeferredCommand interface
-// representing the queued command.
-//
-// A CDeferredCommand object represents a single deferred command, and exposes
-// the IDeferredCommand interface as well as other methods permitting time
-// checks and actual execution. It contains a reference to the CCommandQueue
-// object on which it is queued.
-//
-// CCommandQueue is a base class providing a queue of CDeferredCommand
-// objects, and methods to add, remove, check status and invoke the queued
-// commands. A CCommandQueue object would be part of an object that
-// implemented IQueueCommand.
-
-class CCmdQueue;
-
-// take a copy of the params and store them. Release any allocated
-// memory in destructor
-
-class CDispParams : public DISPPARAMS
-{
-public:
- CDispParams(UINT nArgs, __in_ecount(nArgs) VARIANT* pArgs, __inout_opt HRESULT *phr = NULL);
- ~CDispParams();
-};
-
-
-// CDeferredCommand lifetime is controlled by refcounts. Caller of
-// InvokeAt.. gets a refcounted interface pointer, and the CCmdQueue
-// object also holds a refcount on us. Calling Cancel or Invoke takes
-// us off the CCmdQueue and thus reduces the refcount by 1. Once taken
-// off the queue we cannot be put back on the queue.
-
-class CDeferredCommand
- : public CUnknown,
- public IDeferredCommand
-{
-public:
-
- CDeferredCommand(
- __inout CCmdQueue * pQ,
- __in_opt LPUNKNOWN pUnk, // aggregation outer unk
- __inout HRESULT * phr,
- __in LPUNKNOWN pUnkExecutor, // object that will execute this cmd
- REFTIME time,
- __in GUID* iid,
- long dispidMethod,
- short wFlags,
- long cArgs,
- __in_ecount(cArgs) VARIANT* pDispParams,
- __out VARIANT* pvarResult,
- __out short* puArgErr,
- BOOL bStream
- );
-
- DECLARE_IUNKNOWN
-
- // override this to publicise our interfaces
- STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __out void **ppv);
-
- // IDeferredCommand methods
- STDMETHODIMP Cancel();
- STDMETHODIMP Confidence(
- __out LONG* pConfidence);
- STDMETHODIMP Postpone(
- REFTIME newtime);
- STDMETHODIMP GetHResult(
- __out HRESULT* phrResult);
-
- // other public methods
-
- HRESULT Invoke();
-
- // access methods
-
- // returns TRUE if streamtime, FALSE if presentation time
- BOOL IsStreamTime() {
- return m_bStream;
- };
-
- CRefTime GetTime() {
- return m_time;
- };
-
- REFIID GetIID() {
- return *m_iid;
- };
-
- long GetMethod() {
- return m_dispidMethod;
- };
-
- short GetFlags() {
- return m_wFlags;
- };
-
- DISPPARAMS* GetParams() {
- return &m_DispParams;
- };
-
- VARIANT* GetResult() {
- return m_pvarResult;
- };
-
-protected:
-
- CCmdQueue* m_pQueue;
-
- // pUnk for the interface that we will execute the command on
- LPUNKNOWN m_pUnk;
-
- // stored command data
- REFERENCE_TIME m_time;
- GUID* m_iid;
- long m_dispidMethod;
- short m_wFlags;
- VARIANT* m_pvarResult;
- BOOL m_bStream;
- CDispParams m_DispParams;
- DISPID m_DispId; // For get and put
-
- // we use this for ITypeInfo access
- CBaseDispatch m_Dispatch;
-
- // save retval here
- HRESULT m_hrResult;
-};
-
-
-// a list of CDeferredCommand objects. this is a base class providing
-// the basics of access to the list. If you want to use CDeferredCommand
-// objects then your queue needs to be derived from this class.
-
-class AM_NOVTABLE CCmdQueue
-{
-public:
- CCmdQueue(__inout_opt HRESULT *phr = NULL);
- virtual ~CCmdQueue();
-
- // returns a new CDeferredCommand object that will be initialised with
- // the parameters and will be added to the queue during construction.
- // returns S_OK if successfully created otherwise an error and
- // no object has been queued.
- virtual HRESULT New(
- __out CDeferredCommand **ppCmd,
- __in LPUNKNOWN pUnk,
- REFTIME time,
- __in GUID* iid,
- long dispidMethod,
- short wFlags,
- long cArgs,
- __in_ecount(cArgs) VARIANT* pDispParams,
- __out VARIANT* pvarResult,
- __out short* puArgErr,
- BOOL bStream
- );
-
- // called by the CDeferredCommand object to add and remove itself
- // from the queue
- virtual HRESULT Insert(__in CDeferredCommand* pCmd);
- virtual HRESULT Remove(__in CDeferredCommand* pCmd);
-
- // Command-Due Checking
- //
- // There are two schemes of synchronisation: coarse and accurate. In
- // coarse mode, you wait till the time arrives and then execute the cmd.
- // In accurate mode, you wait until you are processing the sample that
- // will appear at the time, and then execute the command. It's up to the
- // filter which one it will implement. The filtergraph will always
- // implement coarse mode for commands queued at the filtergraph.
- //
- // If you want coarse sync, you probably want to wait until there is a
- // command due, and then execute it. You can do this by calling
- // GetDueCommand. If you have several things to wait for, get the
- // event handle from GetDueHandle() and when this is signalled then call
- // GetDueCommand. Stream time will only advance between calls to Run and
- // EndRun. Note that to avoid an extra thread there is no guarantee that
- // if the handle is set there will be a command ready. Each time the
- // event is signalled, call GetDueCommand (probably with a 0 timeout);
- // This may return E_ABORT.
- //
- // If you want accurate sync, you must call GetCommandDueFor, passing
- // as a parameter the stream time of the samples you are about to process.
- // This will return:
- // -- a stream-time command due at or before that stream time
- // -- a presentation-time command due at or before the
- // time that stream time will be presented (only between Run
- // and EndRun calls, since outside of this, the mapping from
- // stream time to presentation time is not known.
- // -- any presentation-time command due now.
- // This means that if you want accurate synchronisation on samples that
- // might be processed during Paused mode, you need to use
- // stream-time commands.
- //
- // In all cases, commands remain queued until Invoked or Cancelled. The
- // setting and resetting of the event handle is managed entirely by this
- // queue object.
-
- // set the clock used for timing
- virtual HRESULT SetSyncSource(__in_opt IReferenceClock*);
-
- // switch to run mode. Streamtime to Presentation time mapping known.
- virtual HRESULT Run(REFERENCE_TIME tStreamTimeOffset);
-
- // switch to Stopped or Paused mode. Time mapping not known.
- virtual HRESULT EndRun();
-
- // return a pointer to the next due command. Blocks for msTimeout
- // milliseconds until there is a due command.
- // Stream-time commands will only become due between Run and Endrun calls.
- // The command remains queued until invoked or cancelled.
- // Returns E_ABORT if timeout occurs, otherwise S_OK (or other error).
- // Returns an AddRef-ed object
- virtual HRESULT GetDueCommand(__out CDeferredCommand ** ppCmd, long msTimeout);
-
- // return the event handle that will be signalled whenever
- // there are deferred commands due for execution (when GetDueCommand
- // will not block).
- HANDLE GetDueHandle() {
- return HANDLE(m_evDue);
- };
-
- // return a pointer to a command that will be due for a given time.
- // Pass in a stream time here. The stream time offset will be passed
- // in via the Run method.
- // Commands remain queued until invoked or cancelled.
- // This method will not block. It will report VFW_E_NOT_FOUND if there
- // are no commands due yet.
- // Returns an AddRef-ed object
- virtual HRESULT GetCommandDueFor(REFERENCE_TIME tStream, __out CDeferredCommand**ppCmd);
-
- // check if a given time is due (TRUE if it is due yet)
- BOOL CheckTime(CRefTime time, BOOL bStream) {
-
- // if no clock, nothing is due!
- if (!m_pClock) {
- return FALSE;
- }
-
- // stream time
- if (bStream) {
-
- // not valid if not running
- if (!m_bRunning) {
- return FALSE;
- }
- // add on known stream time offset to get presentation time
- time += m_StreamTimeOffset;
- }
-
- CRefTime Now;
- m_pClock->GetTime((REFERENCE_TIME*)&Now);
- return (time <= Now);
- };
-
-protected:
-
- // protect access to lists etc
- CCritSec m_Lock;
-
- // commands queued in presentation time are stored here
- CGenericList<CDeferredCommand> m_listPresentation;
-
- // commands queued in stream time are stored here
- CGenericList<CDeferredCommand> m_listStream;
-
- // set when any commands are due
- CAMEvent m_evDue;
-
- // creates an advise for the earliest time required, if any
- void SetTimeAdvise(void);
-
- // advise id from reference clock (0 if no outstanding advise)
- DWORD_PTR m_dwAdvise;
-
- // advise time is for this presentation time
- CRefTime m_tCurrentAdvise;
-
- // the reference clock we are using (addrefed)
- IReferenceClock* m_pClock;
-
- // true when running
- BOOL m_bRunning;
-
- // contains stream time offset when m_bRunning is true
- CRefTime m_StreamTimeOffset;
-};
-
-#endif // __CTLUTIL__
diff --git a/dll/src/baseclasses/ddmm.cpp b/dll/src/baseclasses/ddmm.cpp
deleted file mode 100644
index bfa700c..0000000
--- a/dll/src/baseclasses/ddmm.cpp
+++ /dev/null
@@ -1,129 +0,0 @@
-//------------------------------------------------------------------------------
-// File: DDMM.cpp
-//
-// Desc: DirectShow base classes - implements routines for using DirectDraw
-// on a multimonitor system.
-//
-// Copyright (c) 1995-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-#include <streams.h>
-#include <ddraw.h>
-#include "ddmm.h"
-
-/*
- * FindDeviceCallback
- */
-typedef struct {
- LPSTR szDevice;
- GUID* lpGUID;
- GUID GUID;
- BOOL fFound;
-} FindDeviceData;
-
-BOOL CALLBACK FindDeviceCallback(__in_opt GUID* lpGUID, __in LPSTR szName, __in LPSTR szDevice, __in LPVOID lParam)
-{
- FindDeviceData *p = (FindDeviceData*)lParam;
-
- if (lstrcmpiA(p->szDevice, szDevice) == 0) {
- if (lpGUID) {
- p->GUID = *lpGUID;
- p->lpGUID = &p->GUID;
- } else {
- p->lpGUID = NULL;
- }
- p->fFound = TRUE;
- return FALSE;
- }
- return TRUE;
-}
-
-
-BOOL CALLBACK FindDeviceCallbackEx(__in_opt GUID* lpGUID, __in LPSTR szName, __in LPSTR szDevice, __in LPVOID lParam, HMONITOR hMonitor)
-{
- FindDeviceData *p = (FindDeviceData*)lParam;
-
- if (lstrcmpiA(p->szDevice, szDevice) == 0) {
- if (lpGUID) {
- p->GUID = *lpGUID;
- p->lpGUID = &p->GUID;
- } else {
- p->lpGUID = NULL;
- }
- p->fFound = TRUE;
- return FALSE;
- }
- return TRUE;
-}
-
-
-/*
- * DirectDrawCreateFromDevice
- *
- * create a DirectDraw object for a particular device
- */
-IDirectDraw * DirectDrawCreateFromDevice(__in_opt LPSTR szDevice, PDRAWCREATE DirectDrawCreateP, PDRAWENUM DirectDrawEnumerateP)
-{
- IDirectDraw* pdd = NULL;
- FindDeviceData find;
-
- if (szDevice == NULL) {
- DirectDrawCreateP(NULL, &pdd, NULL);
- return pdd;
- }
-
- find.szDevice = szDevice;
- find.fFound = FALSE;
- DirectDrawEnumerateP(FindDeviceCallback, (LPVOID)&find);
-
- if (find.fFound)
- {
- //
- // In 4bpp mode the following DDraw call causes a message box to be popped
- // up by DDraw (!?!). It's DDraw's fault, but we don't like it. So we
- // make sure it doesn't happen.
- //
- UINT ErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
- DirectDrawCreateP(find.lpGUID, &pdd, NULL);
- SetErrorMode(ErrorMode);
- }
-
- return pdd;
-}
-
-
-/*
- * DirectDrawCreateFromDeviceEx
- *
- * create a DirectDraw object for a particular device
- */
-IDirectDraw * DirectDrawCreateFromDeviceEx(__in_opt LPSTR szDevice, PDRAWCREATE DirectDrawCreateP, LPDIRECTDRAWENUMERATEEXA DirectDrawEnumerateExP)
-{
- IDirectDraw* pdd = NULL;
- FindDeviceData find;
-
- if (szDevice == NULL) {
- DirectDrawCreateP(NULL, &pdd, NULL);
- return pdd;
- }
-
- find.szDevice = szDevice;
- find.fFound = FALSE;
- DirectDrawEnumerateExP(FindDeviceCallbackEx, (LPVOID)&find,
- DDENUM_ATTACHEDSECONDARYDEVICES);
-
- if (find.fFound)
- {
- //
- // In 4bpp mode the following DDraw call causes a message box to be popped
- // up by DDraw (!?!). It's DDraw's fault, but we don't like it. So we
- // make sure it doesn't happen.
- //
- UINT ErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
- DirectDrawCreateP(find.lpGUID, &pdd, NULL);
- SetErrorMode(ErrorMode);
- }
-
- return pdd;
-}
diff --git a/dll/src/baseclasses/ddmm.h b/dll/src/baseclasses/ddmm.h
deleted file mode 100644
index 7b311bc..0000000
--- a/dll/src/baseclasses/ddmm.h
+++ /dev/null
@@ -1,28 +0,0 @@
-//------------------------------------------------------------------------------
-// File: DDMM.h
-//
-// Desc: DirectShow base classes - efines routines for using DirectDraw
-// on a multimonitor system.
-//
-// Copyright (c) 1995-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-#ifdef __cplusplus
-extern "C" { /* Assume C declarations for C++ */
-#endif /* __cplusplus */
-
-// DDRAW.H might not include these
-#ifndef DDENUM_ATTACHEDSECONDARYDEVICES
-#define DDENUM_ATTACHEDSECONDARYDEVICES 0x00000001L
-#endif
-
-typedef HRESULT (*PDRAWCREATE)(IID *,LPDIRECTDRAW *,LPUNKNOWN);
-typedef HRESULT (*PDRAWENUM)(LPDDENUMCALLBACKA, LPVOID);
-
-IDirectDraw * DirectDrawCreateFromDevice(__in_opt LPSTR, PDRAWCREATE, PDRAWENUM);
-IDirectDraw * DirectDrawCreateFromDeviceEx(__in_opt LPSTR, PDRAWCREATE, LPDIRECTDRAWENUMERATEEXA);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
diff --git a/dll/src/baseclasses/dllentry.cpp b/dll/src/baseclasses/dllentry.cpp
deleted file mode 100644
index cec0695..0000000
--- a/dll/src/baseclasses/dllentry.cpp
+++ /dev/null
@@ -1,351 +0,0 @@
-//------------------------------------------------------------------------------
-// File: DlleEntry.cpp
-//
-// Desc: DirectShow base classes - implements classes used to support dll
-// entry points for COM objects.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-#include <streams.h>
-#include <initguid.h>
-
-#ifdef DEBUG
-#ifdef UNICODE
-#ifndef _UNICODE
-#define _UNICODE
-#endif // _UNICODE
-#endif // UNICODE
-
-#include <tchar.h>
-#endif // DEBUG
-#include <strsafe.h>
-
-extern CFactoryTemplate g_Templates[];
-extern int g_cTemplates;
-
-HINSTANCE g_hInst;
-
-//
-// an instance of this is created by the DLLGetClassObject entrypoint
-// it uses the CFactoryTemplate object it is given to support the
-// IClassFactory interface
-
-class CClassFactory : public IClassFactory, public CBaseObject
-{
-
-private:
- const CFactoryTemplate *const m_pTemplate;
-
- ULONG m_cRef;
-
- static int m_cLocked;
-public:
- CClassFactory(const CFactoryTemplate *);
-
- // IUnknown
- STDMETHODIMP QueryInterface(REFIID riid, __deref_out void ** ppv);
- STDMETHODIMP_(ULONG)AddRef();
- STDMETHODIMP_(ULONG)Release();
-
- // IClassFactory
- STDMETHODIMP CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, __deref_out void **pv);
- STDMETHODIMP LockServer(BOOL fLock);
-
- // allow DLLGetClassObject to know about global server lock status
- static BOOL IsLocked() {
- return (m_cLocked > 0);
- };
-};
-
-// process-wide dll locked state
-int CClassFactory::m_cLocked = 0;
-
-CClassFactory::CClassFactory(const CFactoryTemplate *pTemplate)
-: CBaseObject(NAME("Class Factory"))
-, m_cRef(0)
-, m_pTemplate(pTemplate)
-{
-}
-
-
-STDMETHODIMP
-CClassFactory::QueryInterface(REFIID riid,__deref_out void **ppv)
-{
- CheckPointer(ppv,E_POINTER)
- ValidateReadWritePtr(ppv,sizeof(PVOID));
- *ppv = NULL;
-
- // any interface on this object is the object pointer.
- if ((riid == IID_IUnknown) || (riid == IID_IClassFactory)) {
- *ppv = (LPVOID) this;
- // AddRef returned interface pointer
- ((LPUNKNOWN) *ppv)->AddRef();
- return NOERROR;
- }
-
- return ResultFromScode(E_NOINTERFACE);
-}
-
-
-STDMETHODIMP_(ULONG)
-CClassFactory::AddRef()
-{
- return ++m_cRef;
-}
-
-STDMETHODIMP_(ULONG)
-CClassFactory::Release()
-{
- LONG lRef = InterlockedDecrement((volatile LONG *)&m_cRef);
- if (lRef == 0) {
- delete this;
- return 0;
- } else {
- return lRef;
- }
-}
-
-STDMETHODIMP
-CClassFactory::CreateInstance(
- LPUNKNOWN pUnkOuter,
- REFIID riid,
- __deref_out void **pv)
-{
- CheckPointer(pv,E_POINTER)
- ValidateReadWritePtr(pv,sizeof(void *));
- *pv = NULL;
-
- /* Enforce the normal OLE rules regarding interfaces and delegation */
-
- if (pUnkOuter != NULL) {
- if (IsEqualIID(riid,IID_IUnknown) == FALSE) {
- *pv = NULL;
- return ResultFromScode(E_NOINTERFACE);
- }
- }
-
- /* Create the new object through the derived class's create function */
-
- HRESULT hr = NOERROR;
- CUnknown *pObj = m_pTemplate->CreateInstance(pUnkOuter, &hr);
-
- if (pObj == NULL) {
- *pv = NULL;
- if (SUCCEEDED(hr)) {
- hr = E_OUTOFMEMORY;
- }
- return hr;
- }
-
- /* Delete the object if we got a construction error */
-
- if (FAILED(hr)) {
- delete pObj;
- *pv = NULL;
- return hr;
- }
-
- /* Get a reference counted interface on the object */
-
- /* We wrap the non-delegating QI with NDAddRef & NDRelease. */
- /* This protects any outer object from being prematurely */
- /* released by an inner object that may have to be created */
- /* in order to supply the requested interface. */
- pObj->NonDelegatingAddRef();
- hr = pObj->NonDelegatingQueryInterface(riid, pv);
- pObj->NonDelegatingRelease();
- /* Note that if NonDelegatingQueryInterface fails, it will */
- /* not increment the ref count, so the NonDelegatingRelease */
- /* will drop the ref back to zero and the object will "self-*/
- /* destruct". Hence we don't need additional tidy-up code */
- /* to cope with NonDelegatingQueryInterface failing. */
-
- if (SUCCEEDED(hr)) {
- ASSERT(*pv);
- }
-
- return hr;
-}
-
-STDMETHODIMP
-CClassFactory::LockServer(BOOL fLock)
-{
- if (fLock) {
- m_cLocked++;
- } else {
- m_cLocked--;
- }
- return NOERROR;
-}
-
-
-// --- COM entrypoints -----------------------------------------
-
-//called by COM to get the class factory object for a given class
-__control_entrypoint(DllExport) STDAPI
-DllGetClassObject(
- __in REFCLSID rClsID,
- __in REFIID riid,
- __deref_out void **pv)
-{
- *pv = NULL;
- if (!(riid == IID_IUnknown) && !(riid == IID_IClassFactory)) {
- return E_NOINTERFACE;
- }
-
- // traverse the array of templates looking for one with this
- // class id
- for (int i = 0; i < g_cTemplates; i++) {
- const CFactoryTemplate * pT = &g_Templates[i];
- if (pT->IsClassID(rClsID)) {
-
- // found a template - make a class factory based on this
- // template
-
- *pv = (LPVOID) (LPUNKNOWN) new CClassFactory(pT);
- if (*pv == NULL) {
- return E_OUTOFMEMORY;
- }
- ((LPUNKNOWN)*pv)->AddRef();
- return NOERROR;
- }
- }
- return CLASS_E_CLASSNOTAVAILABLE;
-}
-
-//
-// Call any initialization routines
-//
-void
-DllInitClasses(BOOL bLoading)
-{
- int i;
-
- // traverse the array of templates calling the init routine
- // if they have one
- for (i = 0; i < g_cTemplates; i++) {
- const CFactoryTemplate * pT = &g_Templates[i];
- if (pT->m_lpfnInit != NULL) {
- (*pT->m_lpfnInit)(bLoading, pT->m_ClsID);
- }
- }
-
-}
-
-// called by COM to determine if this dll can be unloaded
-// return ok unless there are outstanding objects or a lock requested
-// by IClassFactory::LockServer
-//
-// CClassFactory has a static function that can tell us about the locks,
-// and CCOMObject has a static function that can tell us about the active
-// object count
-STDAPI
-DllCanUnloadNow()
-{
- DbgLog((LOG_MEMORY,2,TEXT("DLLCanUnloadNow called - IsLocked = %d, Active objects = %d"),
- CClassFactory::IsLocked(),
- CBaseObject::ObjectsActive()));
-
- if (CClassFactory::IsLocked() || CBaseObject::ObjectsActive()) {
- return S_FALSE;
- } else {
- return S_OK;
- }
-}
-
-
-// --- standard WIN32 entrypoints --------------------------------------
-
-
-extern "C" void __cdecl __security_init_cookie(void);
-extern "C" BOOL WINAPI _DllEntryPoint(HINSTANCE, ULONG, __inout_opt LPVOID);
-#pragma comment(linker, "/merge:.CRT=.rdata")
-
-extern "C"
-DECLSPEC_NOINLINE
-BOOL
-WINAPI
-DllEntryPoint(
- HINSTANCE hInstance,
- ULONG ulReason,
- __inout_opt LPVOID pv
- )
-{
- if ( ulReason == DLL_PROCESS_ATTACH ) {
- // Must happen before any other code is executed. Thankfully - it's re-entrant
- __security_init_cookie();
- }
- return _DllEntryPoint(hInstance, ulReason, pv);
-}
-
-
-DECLSPEC_NOINLINE
-BOOL
-WINAPI
-_DllEntryPoint(
- HINSTANCE hInstance,
- ULONG ulReason,
- __inout_opt LPVOID pv
- )
-{
-#ifdef DEBUG
- extern bool g_fDbgInDllEntryPoint;
- g_fDbgInDllEntryPoint = true;
-#endif
-
- switch (ulReason)
- {
-
- case DLL_PROCESS_ATTACH:
- DisableThreadLibraryCalls(hInstance);
- DbgInitialise(hInstance);
-
- g_hInst = hInstance;
- DllInitClasses(TRUE);
- break;
-
- case DLL_PROCESS_DETACH:
- DllInitClasses(FALSE);
-
-#ifdef DEBUG
- if (CBaseObject::ObjectsActive()) {
- DbgSetModuleLevel(LOG_MEMORY, 2);
- TCHAR szInfo[512];
- extern TCHAR m_ModuleName[]; // Cut down module name
-
- TCHAR FullName[_MAX_PATH]; // Load the full path and module name
- TCHAR *pName; // Searches from the end for a backslash
-
- GetModuleFileName(NULL,FullName,_MAX_PATH);
- pName = _tcsrchr(FullName,'\\');
- if (pName == NULL) {
- pName = FullName;
- } else {
- pName++;
- }
-
- (void)StringCchPrintf(szInfo, NUMELMS(szInfo), TEXT("Executable: %s Pid %x Tid %x. "),
- pName, GetCurrentProcessId(), GetCurrentThreadId());
-
- (void)StringCchPrintf(szInfo+lstrlen(szInfo), NUMELMS(szInfo) - lstrlen(szInfo), TEXT("Module %s, %d objects left active!"),
- m_ModuleName, CBaseObject::ObjectsActive());
- DbgAssert(szInfo, TEXT(__FILE__),__LINE__);
-
- // If running remotely wait for the Assert to be acknowledged
- // before dumping out the object register
- DbgDumpObjectRegister();
- }
- DbgTerminate();
-#endif
- break;
- }
-
-#ifdef DEBUG
- g_fDbgInDllEntryPoint = false;
-#endif
- return TRUE;
-}
-
-
diff --git a/dll/src/baseclasses/dllsetup.cpp b/dll/src/baseclasses/dllsetup.cpp
deleted file mode 100644
index f1ba9b6..0000000
--- a/dll/src/baseclasses/dllsetup.cpp
+++ /dev/null
@@ -1,693 +0,0 @@
-//------------------------------------------------------------------------------
-// File: DllSetup.cpp
-//
-// Desc: DirectShow base classes.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-#include <streams.h>
-#include <strsafe.h>
-
-//---------------------------------------------------------------------------
-// defines
-
-#define MAX_KEY_LEN 260
-
-
-//---------------------------------------------------------------------------
-// externally defined functions/variable
-
-extern int g_cTemplates;
-extern CFactoryTemplate g_Templates[];
-
-//---------------------------------------------------------------------------
-//
-// EliminateSubKey
-//
-// Try to enumerate all keys under this one.
-// if we find anything, delete it completely.
-// Otherwise just delete it.
-//
-// note - this was pinched/duplicated from
-// Filgraph\Mapper.cpp - so should it be in
-// a lib somewhere?
-//
-//---------------------------------------------------------------------------
-
-STDAPI
-EliminateSubKey( HKEY hkey, LPCTSTR strSubKey )
-{
- HKEY hk;
- if (0 == lstrlen(strSubKey) ) {
- // defensive approach
- return E_FAIL;
- }
-
- LONG lreturn = RegOpenKeyEx( hkey
- , strSubKey
- , 0
- , MAXIMUM_ALLOWED
- , &hk );
-
- ASSERT( lreturn == ERROR_SUCCESS
- || lreturn == ERROR_FILE_NOT_FOUND
- || lreturn == ERROR_INVALID_HANDLE );
-
- if( ERROR_SUCCESS == lreturn )
- {
- // Keep on enumerating the first (zero-th)
- // key and deleting that
-
- for( ; ; )
- {
- TCHAR Buffer[MAX_KEY_LEN];
- DWORD dw = MAX_KEY_LEN;
- FILETIME ft;
-
- lreturn = RegEnumKeyEx( hk
- , 0
- , Buffer
- , &dw
- , NULL
- , NULL
- , NULL
- , &ft);
-
- ASSERT( lreturn == ERROR_SUCCESS
- || lreturn == ERROR_NO_MORE_ITEMS );
-
- if( ERROR_SUCCESS == lreturn )
- {
- EliminateSubKey(hk, Buffer);
- }
- else
- {
- break;
- }
- }
-
- RegCloseKey(hk);
- RegDeleteKey(hkey, strSubKey);
- }
-
- return NOERROR;
-}
-
-
-//---------------------------------------------------------------------------
-//
-// AMovieSetupRegisterServer()
-//
-// registers specfied file "szFileName" as server for
-// CLSID "clsServer". A description is also required.
-// The ThreadingModel and ServerType are optional, as
-// they default to InprocServer32 (i.e. dll) and Both.
-//
-//---------------------------------------------------------------------------
-
-STDAPI
-AMovieSetupRegisterServer( CLSID clsServer
- , LPCWSTR szDescription
- , LPCWSTR szFileName
- , LPCWSTR szThreadingModel = L"Both"
- , LPCWSTR szServerType = L"InprocServer32" )
-{
- // temp buffer
- //
- TCHAR achTemp[MAX_PATH];
-
- // convert CLSID uuid to string and write
- // out subkey as string - CLSID\{}
- //
- OLECHAR szCLSID[CHARS_IN_GUID];
- HRESULT hr = StringFromGUID2( clsServer
- , szCLSID
- , CHARS_IN_GUID );
- ASSERT( SUCCEEDED(hr) );
-
- // create key
- //
- HKEY hkey;
- (void)StringCchPrintf( achTemp, NUMELMS(achTemp), TEXT("CLSID\\%ls"), szCLSID );
- LONG lreturn = RegCreateKey( HKEY_CLASSES_ROOT
- , (LPCTSTR)achTemp
- , &hkey );
- if( ERROR_SUCCESS != lreturn )
- {
- return AmHresultFromWin32(lreturn);
- }
-
- // set description string
- //
-
- (void)StringCchPrintf( achTemp, NUMELMS(achTemp), TEXT("%ls"), szDescription );
- lreturn = RegSetValue( hkey
- , (LPCTSTR)NULL
- , REG_SZ
- , achTemp
- , sizeof(achTemp) );
- if( ERROR_SUCCESS != lreturn )
- {
- RegCloseKey( hkey );
- return AmHresultFromWin32(lreturn);
- }
-
- // create CLSID\\{"CLSID"}\\"ServerType" key,
- // using key to CLSID\\{"CLSID"} passed back by
- // last call to RegCreateKey().
- //
- HKEY hsubkey;
-
- (void)StringCchPrintf( achTemp, NUMELMS(achTemp), TEXT("%ls"), szServerType );
- lreturn = RegCreateKey( hkey
- , achTemp
- , &hsubkey );
- if( ERROR_SUCCESS != lreturn )
- {
- RegCloseKey( hkey );
- return AmHresultFromWin32(lreturn);
- }
-
- // set Server string
- //
- (void)StringCchPrintf( achTemp, NUMELMS(achTemp), TEXT("%ls"), szFileName );
- lreturn = RegSetValue( hsubkey
- , (LPCTSTR)NULL
- , REG_SZ
- , (LPCTSTR)achTemp
- , sizeof(TCHAR) * (lstrlen(achTemp)+1) );
- if( ERROR_SUCCESS != lreturn )
- {
- RegCloseKey( hkey );
- RegCloseKey( hsubkey );
- return AmHresultFromWin32(lreturn);
- }
-
- (void)StringCchPrintf( achTemp, NUMELMS(achTemp), TEXT("%ls"), szThreadingModel );
- lreturn = RegSetValueEx( hsubkey
- , TEXT("ThreadingModel")
- , 0L
- , REG_SZ
- , (CONST BYTE *)achTemp
- , sizeof(TCHAR) * (lstrlen(achTemp)+1) );
-
- // close hkeys
- //
- RegCloseKey( hkey );
- RegCloseKey( hsubkey );
-
- // and return
- //
- return HRESULT_FROM_WIN32(lreturn);
-
-}
-
-
-//---------------------------------------------------------------------------
-//
-// AMovieSetupUnregisterServer()
-//
-// default ActiveMovie dll setup function
-// - to use must be called from an exported
-// function named DllRegisterServer()
-//
-//---------------------------------------------------------------------------
-
-STDAPI
-AMovieSetupUnregisterServer( CLSID clsServer )
-{
- // convert CLSID uuid to string and write
- // out subkey CLSID\{}
- //
- OLECHAR szCLSID[CHARS_IN_GUID];
- HRESULT hr = StringFromGUID2( clsServer
- , szCLSID
- , CHARS_IN_GUID );
- ASSERT( SUCCEEDED(hr) );
-
- TCHAR achBuffer[MAX_KEY_LEN];
- (void)StringCchPrintf( achBuffer, NUMELMS(achBuffer), TEXT("CLSID\\%ls"), szCLSID );
-
- // delete subkey
- //
-
- hr = EliminateSubKey( HKEY_CLASSES_ROOT, achBuffer );
- ASSERT( SUCCEEDED(hr) );
-
- // return
- //
- return NOERROR;
-}
-
-
-//---------------------------------------------------------------------------
-//
-// AMovieSetupRegisterFilter through IFilterMapper2
-//
-//---------------------------------------------------------------------------
-
-STDAPI
-AMovieSetupRegisterFilter2( const AMOVIESETUP_FILTER * const psetupdata
- , IFilterMapper2 * pIFM2
- , BOOL bRegister )
-{
- DbgLog((LOG_TRACE, 3, TEXT("= AMovieSetupRegisterFilter")));
-
- // check we've got data
- //
- if( NULL == psetupdata ) return S_FALSE;
-
-
- // unregister filter
- // (as pins are subkeys of filter's CLSID key
- // they do not need to be removed separately).
- //
- DbgLog((LOG_TRACE, 3, TEXT("= = unregister filter")));
- HRESULT hr = pIFM2->UnregisterFilter(
- 0, // default category
- 0, // default instance name
- *psetupdata->clsID );
-
-
- if( bRegister )
- {
- REGFILTER2 rf2;
- rf2.dwVersion = 1;
- rf2.dwMerit = psetupdata->dwMerit;
- rf2.cPins = psetupdata->nPins;
- rf2.rgPins = psetupdata->lpPin;
-
- // register filter
- //
- DbgLog((LOG_TRACE, 3, TEXT("= = register filter")));
- hr = pIFM2->RegisterFilter(*psetupdata->clsID
- , psetupdata->strName
- , 0 // moniker
- , 0 // category
- , NULL // instance
- , &rf2);
- }
-
- // handle one acceptable "error" - that
- // of filter not being registered!
- // (couldn't find a suitable #define'd
- // name for the error!)
- //
- if( 0x80070002 == hr)
- return NOERROR;
- else
- return hr;
-}
-
-
-//---------------------------------------------------------------------------
-//
-// RegisterAllServers()
-//
-//---------------------------------------------------------------------------
-
-STDAPI
-RegisterAllServers( LPCWSTR szFileName, BOOL bRegister )
-{
- HRESULT hr = NOERROR;
-
- for( int i = 0; i < g_cTemplates; i++ )
- {
- // get i'th template
- //
- const CFactoryTemplate *pT = &g_Templates[i];
-
- DbgLog((LOG_TRACE, 2, TEXT("- - register %ls"),
- (LPCWSTR)pT->m_Name ));
-
- // register CLSID and InprocServer32
- //
- if( bRegister )
- {
- hr = AMovieSetupRegisterServer( *(pT->m_ClsID)
- , (LPCWSTR)pT->m_Name
- , szFileName );
- }
- else
- {
- hr = AMovieSetupUnregisterServer( *(pT->m_ClsID) );
- }
-
- // check final error for this pass
- // and break loop if we failed
- //
- if( FAILED(hr) )
- break;
- }
-
- return hr;
-}
-
-
-//---------------------------------------------------------------------------
-//
-// AMovieDllRegisterServer2()
-//
-// default ActiveMovie dll setup function
-// - to use must be called from an exported
-// function named DllRegisterServer()
-//
-// this function is table driven using the
-// static members of the CFactoryTemplate
-// class defined in the dll.
-//
-// it registers the Dll as the InprocServer32
-// and then calls the IAMovieSetup.Register
-// method.
-//
-//---------------------------------------------------------------------------
-
-STDAPI
-AMovieDllRegisterServer2( BOOL bRegister )
-{
- HRESULT hr = NOERROR;
-
- DbgLog((LOG_TRACE, 2, TEXT("AMovieDllRegisterServer2()")));
-
- // get file name (where g_hInst is the
- // instance handle of the filter dll)
- //
- WCHAR achFileName[MAX_PATH];
-
- // WIN95 doesn't support GetModuleFileNameW
- //
- {
- char achTemp[MAX_PATH];
-
- DbgLog((LOG_TRACE, 2, TEXT("- get module file name")));
-
- // g_hInst handle is set in our dll entry point. Make sure
- // DllEntryPoint in dllentry.cpp is called
- ASSERT(g_hInst != 0);
-
- if( 0 == GetModuleFileNameA( g_hInst
- , achTemp
- , sizeof(achTemp) ) )
- {
- // we've failed!
- DWORD dwerr = GetLastError();
- return AmHresultFromWin32(dwerr);
- }
-
- MultiByteToWideChar( CP_ACP
- , 0L
- , achTemp
- , lstrlenA(achTemp) + 1
- , achFileName
- , NUMELMS(achFileName) );
- }
-
- //
- // first registering, register all OLE servers
- //
- if( bRegister )
- {
- DbgLog((LOG_TRACE, 2, TEXT("- register OLE Servers")));
- hr = RegisterAllServers( achFileName, TRUE );
- }
-
- //
- // next, register/unregister all filters
- //
-
- if( SUCCEEDED(hr) )
- {
- // init is ref counted so call just in case
- // we're being called cold.
- //
- DbgLog((LOG_TRACE, 2, TEXT("- CoInitialize")));
- hr = CoInitialize( (LPVOID)NULL );
- ASSERT( SUCCEEDED(hr) );
-
- // get hold of IFilterMapper2
- //
- DbgLog((LOG_TRACE, 2, TEXT("- obtain IFilterMapper2")));
- IFilterMapper2 *pIFM2 = 0;
- IFilterMapper *pIFM = 0;
- hr = CoCreateInstance( CLSID_FilterMapper2
- , NULL
- , CLSCTX_INPROC_SERVER
- , IID_IFilterMapper2
- , (void **)&pIFM2 );
- if(FAILED(hr))
- {
- DbgLog((LOG_TRACE, 2, TEXT("- trying IFilterMapper instead")));
-
- hr = CoCreateInstance(
- CLSID_FilterMapper,
- NULL,
- CLSCTX_INPROC_SERVER,
- IID_IFilterMapper,
- (void **)&pIFM);
- }
- if( SUCCEEDED(hr) )
- {
- // scan through array of CFactoryTemplates
- // registering servers and filters.
- //
- DbgLog((LOG_TRACE, 2, TEXT("- register Filters")));
- for( int i = 0; i < g_cTemplates; i++ )
- {
- // get i'th template
- //
- const CFactoryTemplate *pT = &g_Templates[i];
-
- if( NULL != pT->m_pAMovieSetup_Filter )
- {
- DbgLog((LOG_TRACE, 2, TEXT("- - register %ls"), (LPCWSTR)pT->m_Name ));
-
- if(pIFM2)
- {
- hr = AMovieSetupRegisterFilter2( pT->m_pAMovieSetup_Filter, pIFM2, bRegister );
- }
- else
- {
- hr = AMovieSetupRegisterFilter( pT->m_pAMovieSetup_Filter, pIFM, bRegister );
- }
- }
-
- // check final error for this pass
- // and break loop if we failed
- //
- if( FAILED(hr) )
- break;
- }
-
- // release interface
- //
- if(pIFM2)
- pIFM2->Release();
- else
- pIFM->Release();
-
- }
-
- // and clear up
- //
- CoFreeUnusedLibraries();
- CoUninitialize();
- }
-
- //
- // if unregistering, unregister all OLE servers
- //
- if( SUCCEEDED(hr) && !bRegister )
- {
- DbgLog((LOG_TRACE, 2, TEXT("- register OLE Servers")));
- hr = RegisterAllServers( achFileName, FALSE );
- }
-
- DbgLog((LOG_TRACE, 2, TEXT("- return %0x"), hr));
- return hr;
-}
-
-
-//---------------------------------------------------------------------------
-//
-// AMovieDllRegisterServer()
-//
-// default ActiveMovie dll setup function
-// - to use must be called from an exported
-// function named DllRegisterServer()
-//
-// this function is table driven using the
-// static members of the CFactoryTemplate
-// class defined in the dll.
-//
-// it registers the Dll as the InprocServer32
-// and then calls the IAMovieSetup.Register
-// method.
-//
-//---------------------------------------------------------------------------
-
-
-STDAPI
-AMovieDllRegisterServer( void )
-{
- HRESULT hr = NOERROR;
-
- // get file name (where g_hInst is the
- // instance handle of the filter dll)
- //
- WCHAR achFileName[MAX_PATH];
-
- {
- // WIN95 doesn't support GetModuleFileNameW
- //
- char achTemp[MAX_PATH];
-
- if( 0 == GetModuleFileNameA( g_hInst
- , achTemp
- , sizeof(achTemp) ) )
- {
- // we've failed!
- DWORD dwerr = GetLastError();
- return AmHresultFromWin32(dwerr);
- }
-
- MultiByteToWideChar( CP_ACP
- , 0L
- , achTemp
- , lstrlenA(achTemp) + 1
- , achFileName
- , NUMELMS(achFileName) );
- }
-
- // scan through array of CFactoryTemplates
- // registering servers and filters.
- //
- for( int i = 0; i < g_cTemplates; i++ )
- {
- // get i'th template
- //
- const CFactoryTemplate *pT = &g_Templates[i];
-
- // register CLSID and InprocServer32
- //
- hr = AMovieSetupRegisterServer( *(pT->m_ClsID)
- , (LPCWSTR)pT->m_Name
- , achFileName );
-
- // instantiate all servers and get hold of
- // IAMovieSetup, if implemented, and call
- // IAMovieSetup.Register() method
- //
- if( SUCCEEDED(hr) && (NULL != pT->m_lpfnNew) )
- {
- // instantiate object
- //
- PAMOVIESETUP psetup;
- hr = CoCreateInstance( *(pT->m_ClsID)
- , 0
- , CLSCTX_INPROC_SERVER
- , IID_IAMovieSetup
- , reinterpret_cast<void**>(&psetup) );
- if( SUCCEEDED(hr) )
- {
- hr = psetup->Unregister();
- if( SUCCEEDED(hr) )
- hr = psetup->Register();
- psetup->Release();
- }
- else
- {
- if( (E_NOINTERFACE == hr )
- || (VFW_E_NEED_OWNER == hr ) )
- hr = NOERROR;
- }
- }
-
- // check final error for this pass
- // and break loop if we failed
- //
- if( FAILED(hr) )
- break;
-
- } // end-for
-
- return hr;
-}
-
-
-//---------------------------------------------------------------------------
-//
-// AMovieDllUnregisterServer()
-//
-// default ActiveMovie dll uninstall function
-// - to use must be called from an exported
-// function named DllRegisterServer()
-//
-// this function is table driven using the
-// static members of the CFactoryTemplate
-// class defined in the dll.
-//
-// it calls the IAMovieSetup.Unregister
-// method and then unregisters the Dll
-// as the InprocServer32
-//
-//---------------------------------------------------------------------------
-
-STDAPI
-AMovieDllUnregisterServer()
-{
- // initialize return code
- //
- HRESULT hr = NOERROR;
-
- // scan through CFactory template and unregister
- // all OLE servers and filters.
- //
- for( int i = g_cTemplates; i--; )
- {
- // get i'th template
- //
- const CFactoryTemplate *pT = &g_Templates[i];
-
- // check method exists
- //
- if( NULL != pT->m_lpfnNew )
- {
- // instantiate object
- //
- PAMOVIESETUP psetup;
- hr = CoCreateInstance( *(pT->m_ClsID)
- , 0
- , CLSCTX_INPROC_SERVER
- , IID_IAMovieSetup
- , reinterpret_cast<void**>(&psetup) );
- if( SUCCEEDED(hr) )
- {
- hr = psetup->Unregister();
- psetup->Release();
- }
- else
- {
- if( (E_NOINTERFACE == hr )
- || (VFW_E_NEED_OWNER == hr ) )
- hr = NOERROR;
- }
- }
-
- // unregister CLSID and InprocServer32
- //
- if( SUCCEEDED(hr) )
- {
- hr = AMovieSetupUnregisterServer( *(pT->m_ClsID) );
- }
-
- // check final error for this pass
- // and break loop if we failed
- //
- if( FAILED(hr) )
- break;
- }
-
- return hr;
-}
diff --git a/dll/src/baseclasses/dllsetup.h b/dll/src/baseclasses/dllsetup.h
deleted file mode 100644
index e363b8b..0000000
--- a/dll/src/baseclasses/dllsetup.h
+++ /dev/null
@@ -1,46 +0,0 @@
-//------------------------------------------------------------------------------
-// File: DllSetup.h
-//
-// Desc: DirectShow base classes.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-// To be self registering, OLE servers must
-// export functions named DllRegisterServer
-// and DllUnregisterServer. To allow use of
-// custom and default implementations the
-// defaults are named AMovieDllRegisterServer
-// and AMovieDllUnregisterServer.
-//
-// To the use the default implementation you
-// must provide stub functions.
-//
-// i.e. STDAPI DllRegisterServer()
-// {
-// return AMovieDllRegisterServer();
-// }
-//
-// STDAPI DllUnregisterServer()
-// {
-// return AMovieDllUnregisterServer();
-// }
-//
-//
-// AMovieDllRegisterServer calls IAMovieSetup.Register(), and
-// AMovieDllUnregisterServer calls IAMovieSetup.Unregister().
-
-STDAPI AMovieDllRegisterServer2( BOOL );
-STDAPI AMovieDllRegisterServer();
-STDAPI AMovieDllUnregisterServer();
-
-// helper functions
-STDAPI EliminateSubKey( HKEY, LPCTSTR );
-
-
-STDAPI
-AMovieSetupRegisterFilter2( const AMOVIESETUP_FILTER * const psetupdata
- , IFilterMapper2 * pIFM2
- , BOOL bRegister );
-
diff --git a/dll/src/baseclasses/dxmperf.h b/dll/src/baseclasses/dxmperf.h
deleted file mode 100644
index 54a2120..0000000
--- a/dll/src/baseclasses/dxmperf.h
+++ /dev/null
@@ -1,250 +0,0 @@
-//------------------------------------------------------------------------------
-// File: DXMPerf.h
-//
-// Desc: Macros for DirectShow performance logging.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-#ifndef _DXMPERF_H_
-#define _DXMPERF_H_
-
-#include <perfstruct.h>
-#include "perflog.h"
-
-#ifdef _IA64_
-extern "C" unsigned __int64 __getReg( int whichReg );
-#pragma intrinsic(__getReg)
-#endif // _IA64_
-
-
-inline ULONGLONG _RDTSC( void ) {
-#ifdef _X86_
- LARGE_INTEGER li;
- __asm {
- _emit 0x0F
- _emit 0x31
- mov li.LowPart,eax
- mov li.HighPart,edx
- }
- return li.QuadPart;
-
-#if 0 // This isn't tested yet
-
-#elif defined (_IA64_)
-
-#define INL_REGID_APITC 3116
- return __getReg( INL_REGID_APITC );
-
-#endif // 0
-
-#else // unsupported platform
- // not implemented on non x86/IA64 platforms
- return 0;
-#endif // _X86_/_IA64_
-}
-
-#define DXMPERF_VIDEOREND 0x00000001
-#define DXMPERF_AUDIOGLITCH 0x00000002
-//#define GETTIME_BIT 0x00000001
-//#define AUDIOREND_BIT 0x00000004
-//#define FRAMEDROP_BIT 0x00000008
-#define AUDIOBREAK_BIT 0x00000010
-#define DXMPERF_AUDIORECV 0x00000020
-#define DXMPERF_AUDIOSLAVE 0x00000040
-#define DXMPERF_AUDIOBREAK 0x00000080
-
-#define PERFLOG_CTOR( name, iface )
-#define PERFLOG_DTOR( name, iface )
-#define PERFLOG_DELIVER( name, source, dest, sample, pmt )
-#define PERFLOG_RECEIVE( name, source, dest, sample, pmt )
-#define PERFLOG_RUN( name, iface, time, oldstate )
-#define PERFLOG_PAUSE( name, iface, oldstate )
-#define PERFLOG_STOP( name, iface, oldstate )
-#define PERFLOG_JOINGRAPH( name, iface, graph )
-#define PERFLOG_GETBUFFER( allocator, sample )
-#define PERFLOG_RELBUFFER( allocator, sample )
-#define PERFLOG_CONNECT( connector, connectee, status, pmt )
-#define PERFLOG_RXCONNECT( connector, connectee, status, pmt )
-#define PERFLOG_DISCONNECT( disconnector, disconnectee, status )
-
-#define PERFLOG_GETTIME( clock, time ) /*{ \
- PERFINFO_WMI_GETTIME perfData; \
- if (NULL != g_pTraceEvent) { \
- memset( &perfData, 0, sizeof( perfData ) ); \
- perfData.header.Size = sizeof( perfData ); \
- perfData.header.Flags = WNODE_FLAG_TRACED_GUID; \
- perfData.header.Guid = GUID_GETTIME; \
- perfData.data.cycleCounter = _RDTSC(); \
- perfData.data.dshowClock = (ULONGLONG) (time); \
- if (g_perfMasks[GETTIME_INDEX] & GETTIME_BIT) \
- (*g_pTraceEvent)( g_traceHandle, (PEVENT_TRACE_HEADER) &perfData ); \
- } \
- }*/
-
-#define PERFLOG_AUDIOREND( clocktime, sampletime, psample, bytetime, cbytes ) /*{ \
- PERFINFO_WMI_AVREND perfData; \
- if (NULL != g_pTraceEvent) { \
- memset( &perfData, 0, sizeof( perfData ) ); \
- perfData.header.Size = sizeof( perfData ); \
- perfData.header.Flags = WNODE_FLAG_TRACED_GUID; \
- perfData.header.Guid = GUID_AUDIOREND; \
- perfData.data.cycleCounter = _RDTSC(); \
- perfData.data.dshowClock = (clocktime); \
- perfData.data.sampleTime = (sampletime); \
- if (g_perfMasks[AUDIOREND_INDEX] & AUDIOREND_BIT) \
- (*g_pTraceEvent)( g_traceHandle, (PEVENT_TRACE_HEADER) &perfData ); \
- } \
- }*/
-
-#define PERFLOG_AUDIORECV(StreamTime,SampleStart,SampleStop,Discontinuity,Duration) \
- if (PerflogEnableFlags & DXMPERF_AUDIORECV) { \
- PERFINFO_WMI_AUDIORECV perfData; \
- memset( &perfData, 0, sizeof( perfData ) ); \
- perfData.header.Size = sizeof( perfData ); \
- perfData.header.Flags = WNODE_FLAG_TRACED_GUID; \
- perfData.header.Guid = GUID_AUDIORECV; \
- perfData.data.streamTime = StreamTime; \
- perfData.data.sampleStart = SampleStart; \
- perfData.data.sampleStop = SampleStop; \
- perfData.data.discontinuity = Discontinuity; \
- perfData.data.hwduration = Duration; \
- PerflogTraceEvent((PEVENT_TRACE_HEADER) &perfData); \
- }
-
-#define PERFLOG_AUDIOSLAVE(MasterClock,SlaveClock,ErrorAccum,LastHighErrorSeen,LastLowErrorSeen) \
- if (PerflogEnableFlags & DXMPERF_AUDIOSLAVE) { \
- PERFINFO_WMI_AUDIOSLAVE perfData; \
- memset( &perfData, 0, sizeof( perfData ) ); \
- perfData.header.Size = sizeof( perfData ); \
- perfData.header.Flags = WNODE_FLAG_TRACED_GUID; \
- perfData.header.Guid = GUID_AUDIOSLAVE; \
- perfData.data.masterClock = MasterClock; \
- perfData.data.slaveClock = SlaveClock; \
- perfData.data.errorAccum = ErrorAccum; \
- perfData.data.lastHighErrorSeen = LastHighErrorSeen;\
- perfData.data.lastLowErrorSeen = LastLowErrorSeen; \
- PerflogTraceEvent((PEVENT_TRACE_HEADER) &perfData); \
- }
-
-#define PERFLOG_AUDIOADDBREAK(IterNextWrite,OffsetNextWrite,IterWrite,OffsetWrite) \
- if (PerflogEnableFlags & DXMPERF_AUDIOBREAK) { \
- PERFINFO_WMI_AUDIOADDBREAK perfData; \
- memset( &perfData, 0, sizeof( perfData ) ); \
- perfData.header.Size = sizeof( perfData ); \
- perfData.header.Flags = WNODE_FLAG_TRACED_GUID; \
- perfData.header.Guid = GUID_AUDIOADDBREAK; \
- perfData.data.iterNextWrite = IterNextWrite; \
- perfData.data.offsetNextWrite = OffsetNextWrite; \
- perfData.data.iterWrite = IterWrite; \
- perfData.data.offsetWrite = OffsetWrite; \
- PerflogTraceEvent((PEVENT_TRACE_HEADER) &perfData); \
- }
-
-#define PERFLOG_VIDEOREND( sampletime, clocktime, psample ) \
- if (PerflogEnableFlags & DXMPERF_VIDEOREND) { \
- PERFINFO_WMI_AVREND perfData; \
- memset( &perfData, 0, sizeof( perfData ) ); \
- perfData.header.Size = sizeof( perfData ); \
- perfData.header.Flags = WNODE_FLAG_TRACED_GUID; \
- perfData.header.Guid = GUID_VIDEOREND; \
- perfData.data.cycleCounter = _RDTSC(); \
- perfData.data.dshowClock = (clocktime); \
- perfData.data.sampleTime = (sampletime); \
- PerflogTraceEvent ((PEVENT_TRACE_HEADER) &perfData); \
- }
-
-#define PERFLOG_AUDIOGLITCH( instance, glitchtype, currenttime, previoustime ) \
- if (PerflogEnableFlags & DXMPERF_AUDIOGLITCH) { \
- PERFINFO_WMI_AUDIOGLITCH perfData; \
- memset( &perfData, 0, sizeof( perfData ) ); \
- perfData.header.Size = sizeof( perfData ); \
- perfData.header.Flags = WNODE_FLAG_TRACED_GUID; \
- perfData.header.Guid = GUID_DSOUNDGLITCH; \
- perfData.data.cycleCounter = _RDTSC(); \
- perfData.data.glitchType = (glitchtype); \
- perfData.data.sampleTime = (currenttime); \
- perfData.data.previousTime = (previoustime); \
- perfData.data.instanceId = (instance); \
- PerflogTraceEvent ((PEVENT_TRACE_HEADER) &perfData); \
- }
-
-#define PERFLOG_FRAMEDROP( sampletime, clocktime, psample, renderer ) /*{ \
- PERFINFO_WMI_FRAMEDROP perfData; \
- if (NULL != g_pTraceEvent) { \
- memset( &perfData, 0, sizeof( perfData ) ); \
- perfData.header.Size = sizeof( perfData ); \
- perfData.header.Flags = WNODE_FLAG_TRACED_GUID; \
- perfData.header.Guid = GUID_FRAMEDROP; \
- perfData.data.cycleCounter = _RDTSC(); \
- perfData.data.dshowClock = (clocktime); \
- perfData.data.frameTime = (sampletime); \
- if (g_perfMasks[FRAMEDROP_INDEX] & FRAMEDROP_BIT) \
- (*g_pTraceEvent)( g_traceHandle, (PEVENT_TRACE_HEADER) &perfData ); \
- } \
- }*/
-
-/*
-#define PERFLOG_AUDIOBREAK( nextwrite, writepos, msecs ) { \
- PERFINFO_WMI_AUDIOBREAK perfData; \
- if (NULL != g_pTraceEvent) { \
- memset( &perfData, 0, sizeof( perfData ) ); \
- perfData.header.Size = sizeof( perfData ); \
- perfData.header.Flags = WNODE_FLAG_TRACED_GUID; \
- perfData.header.Guid = GUID_AUDIOBREAK; \
- perfData.data.cycleCounter = _RDTSC(); \
- perfData.data.dshowClock = (writepos); \
- perfData.data.sampleTime = (nextwrite); \
- perfData.data.sampleDuration = (msecs); \
- if (g_perfMasks[AUDIOBREAK_INDEX] & AUDIOBREAK_BIT) \
- (*g_pTraceEvent)( g_traceHandle, (PEVENT_TRACE_HEADER) &perfData ); \
- } \
- }
-*/
-
-#define PERFLOG_AUDIOBREAK( nextwrite, writepos, msecs ) \
- if (PerflogEnableFlags & AUDIOBREAK_BIT) { \
- PERFINFO_WMI_AUDIOBREAK perfData; \
- memset( &perfData, 0, sizeof( perfData ) ); \
- perfData.header.Size = sizeof( perfData ); \
- perfData.header.Flags = WNODE_FLAG_TRACED_GUID; \
- perfData.header.Guid = GUID_AUDIOBREAK; \
- perfData.data.cycleCounter = _RDTSC(); \
- perfData.data.dshowClock = (writepos); \
- perfData.data.sampleTime = (nextwrite); \
- perfData.data.sampleDuration = (msecs); \
- PerflogTraceEvent ((PEVENT_TRACE_HEADER) &perfData); \
- } \
-
-
-inline
-VOID PERFLOG_STREAMTRACE(
- ULONG Level,
- ULONG Id,
- ULONGLONG DShowClock,
- ULONGLONG Data1,
- ULONGLONG Data2,
- ULONGLONG Data3,
- ULONGLONG Data4
- )
-{
- if (Level <= PerflogModuleLevel)
- {
- PERFINFO_WMI_STREAMTRACE perfData;
- memset( &perfData, 0, sizeof( perfData ) );
- perfData.header.Size = sizeof( perfData );
- perfData.header.Flags = WNODE_FLAG_TRACED_GUID;
- perfData.header.Guid = GUID_STREAMTRACE;
- perfData.data.dshowClock = DShowClock;
- perfData.data.id = Id;
- perfData.data.data[0] = Data1;
- perfData.data.data[1] = Data2;
- perfData.data.data[2] = Data3;
- perfData.data.data[3] = Data4;
- PerflogTraceEvent((PEVENT_TRACE_HEADER) &perfData);
- }
-}
-
-
-#endif // _DXMPERF_H_
diff --git a/dll/src/baseclasses/fourcc.h b/dll/src/baseclasses/fourcc.h
deleted file mode 100644
index 19c0fcd..0000000
--- a/dll/src/baseclasses/fourcc.h
+++ /dev/null
@@ -1,101 +0,0 @@
-//------------------------------------------------------------------------------
-// File: FourCC.h
-//
-// Desc: DirectShow base classes.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-// FOURCCMap
-//
-// provides a mapping between old-style multimedia format DWORDs
-// and new-style GUIDs.
-//
-// A range of 4 billion GUIDs has been allocated to ensure that this
-// mapping can be done straightforwardly one-to-one in both directions.
-//
-// January 95
-
-
-#ifndef __FOURCC__
-#define __FOURCC__
-
-
-// Multimedia format types are marked with DWORDs built from four 8-bit
-// chars and known as FOURCCs. New multimedia AM_MEDIA_TYPE definitions include
-// a subtype GUID. In order to simplify the mapping, GUIDs in the range:
-// XXXXXXXX-0000-0010-8000-00AA00389B71
-// are reserved for FOURCCs.
-
-class FOURCCMap : public GUID
-{
-
-public:
- FOURCCMap();
- FOURCCMap(DWORD Fourcc);
- FOURCCMap(const GUID *);
-
-
- DWORD GetFOURCC(void);
- void SetFOURCC(DWORD fourcc);
- void SetFOURCC(const GUID *);
-
-private:
- void InitGUID();
-};
-
-#define GUID_Data2 0
-#define GUID_Data3 0x10
-#define GUID_Data4_1 0xaa000080
-#define GUID_Data4_2 0x719b3800
-
-inline void
-FOURCCMap::InitGUID() {
- Data2 = GUID_Data2;
- Data3 = GUID_Data3;
- ((DWORD *)Data4)[0] = GUID_Data4_1;
- ((DWORD *)Data4)[1] = GUID_Data4_2;
-}
-
-inline
-FOURCCMap::FOURCCMap() {
- InitGUID();
- SetFOURCC( DWORD(0));
-}
-
-inline
-FOURCCMap::FOURCCMap(DWORD fourcc)
-{
- InitGUID();
- SetFOURCC(fourcc);
-}
-
-inline
-FOURCCMap::FOURCCMap(const GUID * pGuid)
-{
- InitGUID();
- SetFOURCC(pGuid);
-}
-
-inline void
-FOURCCMap::SetFOURCC(const GUID * pGuid)
-{
- FOURCCMap * p = (FOURCCMap*) pGuid;
- SetFOURCC(p->GetFOURCC());
-}
-
-inline void
-FOURCCMap::SetFOURCC(DWORD fourcc)
-{
- Data1 = fourcc;
-}
-
-inline DWORD
-FOURCCMap::GetFOURCC(void)
-{
- return Data1;
-}
-
-#endif /* __FOURCC__ */
-
diff --git a/dll/src/baseclasses/measure.h b/dll/src/baseclasses/measure.h
deleted file mode 100644
index a71a075..0000000
--- a/dll/src/baseclasses/measure.h
+++ /dev/null
@@ -1,222 +0,0 @@
-//------------------------------------------------------------------------------
-// File: Measure.h
-//
-// Desc: DirectShow base classes.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-/*
- The idea is to pepper the source code with interesting measurements and
- have the last few thousand of these recorded in a circular buffer that
- can be post-processed to give interesting numbers.
-
- WHAT THE LOG LOOKS LIKE:
-
- Time (sec) Type Delta Incident_Name
- 0.055,41 NOTE -. Incident Nine - Another note
- 0.055,42 NOTE 0.000,01 Incident Nine - Another note
- 0.055,44 NOTE 0.000,02 Incident Nine - Another note
- 0.055,45 STOP -. Incident Eight - Also random
- 0.055,47 START -. Incident Seven - Random
- 0.055,49 NOTE 0.000,05 Incident Nine - Another note
- ------- <etc. there is a lot of this> ----------------
- 0.125,60 STOP 0.000,03 Msr_Stop
- 0.125,62 START -. Msr_Start
- 0.125,63 START -. Incident Two - Start/Stop
- 0.125,65 STOP 0.000,03 Msr_Start
- 0.125,66 START -. Msr_Stop
- 0.125,68 STOP 0.000,05 Incident Two - Start/Stop
- 0.125,70 STOP 0.000,04 Msr_Stop
- 0.125,72 START -. Msr_Start
- 0.125,73 START -. Incident Two - Start/Stop
- 0.125,75 STOP 0.000,03 Msr_Start
- 0.125,77 START -. Msr_Stop
- 0.125,78 STOP 0.000,05 Incident Two - Start/Stop
- 0.125,80 STOP 0.000,03 Msr_Stop
- 0.125,81 NOTE -. Incident Three - single Note
- 0.125,83 START -. Incident Four - Start, no stop
- 0.125,85 START -. Incident Five - Single Start/Stop
- 0.125,87 STOP 0.000,02 Incident Five - Single Start/Stop
-
-Number Average StdDev Smallest Largest Incident_Name
- 10 0.000,58 0.000,10 0.000,55 0.000,85 Incident One - Note
- 50 0.000,05 0.000,00 0.000,05 0.000,05 Incident Two - Start/Stop
- 1 -. -. -. -. Incident Three - single Note
- 0 -. -. -. -. Incident Four - Start, no stop
- 1 0.000,02 -. 0.000,02 0.000,02 Incident Five - Single Start/Stop
- 0 -. -. -. -. Incident Six - zero occurrences
- 100 0.000,25 0.000,12 0.000,02 0.000,62 Incident Seven - Random
- 100 0.000,79 0.000,48 0.000,02 0.001,92 Incident Eight - Also random
- 5895 0.000,01 0.000,01 0.000,01 0.000,56 Incident Nine - Another note
- 10 0.000,03 0.000,00 0.000,03 0.000,04 Msr_Note
- 50 0.000,03 0.000,00 0.000,03 0.000,04 Msr_Start
- 50 0.000,04 0.000,03 0.000,03 0.000,31 Msr_Stop
-
- WHAT IT MEANS:
- The log shows what happened and when. Each line shows the time at which
- something happened (see WHAT YOU CODE below) what it was that happened
- and (if approporate) the time since the corresponding previous event
- (that's the delta column).
-
- The statistics show how many times each event occurred, what the average
- delta time was, also the standard deviation, largest and smalles delta.
-
- WHAT YOU CODE:
-
- Before anything else executes: - register your ids
-
- int id1 = Msr_Register("Incident One - Note");
- int id2 = Msr_Register("Incident Two - Start/Stop");
- int id3 = Msr_Register("Incident Three - single Note");
- etc.
-
- At interesting moments:
-
- // To measure a repetitive event - e.g. end of bitblt to screen
- Msr_Note(Id9); // e.g. "video frame hiting the screen NOW!"
-
- or
-
- // To measure an elapsed time e.g. time taken to decode an MPEG B-frame
- Msr_Start(Id2); // e.g. "Starting to decode MPEG B-frame"
- . . .
- MsrStop(Id2); // "Finished MPEG decode"
-
- At the end:
-
- HANDLE hFile;
- hFile = CreateFile("Perf.log", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
- Msr_Dump(hFile); // This writes the log out to the file
- CloseHandle(hFile);
-
- or
-
- Msr_Dump(NULL); // This writes it to DbgLog((LOG_TRACE,0, ... ));
- // but if you are writing it out to the debugger
- // then the times are probably all garbage because
- // the debugger can make things run awfully slow.
-
- A given id should be used either for start / stop or Note calls. If Notes
- are mixed in with Starts and Stops their statistics will be gibberish.
-
- If you code the calls in upper case i.e. MSR_START(idMunge); then you get
- macros which will turn into nothing unless PERF is defined.
-
- You can reset the statistical counts for a given id by calling Reset(Id).
- They are reset by default at the start.
- It logs Reset as a special incident, so you can see it in the log.
-
- The log is a circular buffer in storage (to try to minimise disk I/O).
- It overwrites the oldest entries once full. The statistics include ALL
- incidents since the last Reset, whether still visible in the log or not.
-*/
-
-#ifndef __MEASURE__
-#define __MEASURE__
-
-#ifdef PERF
-#define MSR_INIT() Msr_Init()
-#define MSR_TERMINATE() Msr_Terminate()
-#define MSR_REGISTER(a) Msr_Register(a)
-#define MSR_RESET(a) Msr_Reset(a)
-#define MSR_CONTROL(a) Msr_Control(a)
-#define MSR_START(a) Msr_Start(a)
-#define MSR_STOP(a) Msr_Stop(a)
-#define MSR_NOTE(a) Msr_Note(a)
-#define MSR_INTEGER(a,b) Msr_Integer(a,b)
-#define MSR_DUMP(a) Msr_Dump(a)
-#define MSR_DUMPSTATS(a) Msr_DumpStats(a)
-#else
-#define MSR_INIT() ((void)0)
-#define MSR_TERMINATE() ((void)0)
-#define MSR_REGISTER(a) 0
-#define MSR_RESET(a) ((void)0)
-#define MSR_CONTROL(a) ((void)0)
-#define MSR_START(a) ((void)0)
-#define MSR_STOP(a) ((void)0)
-#define MSR_NOTE(a) ((void)0)
-#define MSR_INTEGER(a,b) ((void)0)
-#define MSR_DUMP(a) ((void)0)
-#define MSR_DUMPSTATS(a) ((void)0)
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// This must be called first - (called by the DllEntry)
-
-void WINAPI Msr_Init(void);
-
-
-// Call this last to clean up (or just let it fall off the end - who cares?)
-
-void WINAPI Msr_Terminate(void);
-
-
-// Call this to get an Id for an "incident" that you can pass to Start, Stop or Note
-// everything that's logged is called an "incident".
-
-int WINAPI Msr_Register(__in LPTSTR Incident);
-
-
-// Reset the statistical counts for an incident
-
-void WINAPI Msr_Reset(int Id);
-
-
-// Reset all the counts for all incidents
-#define MSR_RESET_ALL 0
-#define MSR_PAUSE 1
-#define MSR_RUN 2
-
-void WINAPI Msr_Control(int iAction);
-
-
-// log the start of an operation
-
-void WINAPI Msr_Start(int Id);
-
-
-// log the end of an operation
-
-void WINAPI Msr_Stop(int Id);
-
-
-// log a one-off or repetitive operation
-
-void WINAPI Msr_Note(int Id);
-
-
-// log an integer (on which we can see statistics later)
-void WINAPI Msr_Integer(int Id, int n);
-
-
-// print out all the vaialable log (it may have wrapped) and then the statistics.
-// When the log wraps you lose log but the statistics are still complete.
-// hFIle==NULL => use DbgLog
-// otherwise hFile must have come from CreateFile or OpenFile.
-
-void WINAPI Msr_Dump(HANDLE hFile);
-
-
-// just dump the statistics - never mind the log
-
-void WINAPI Msr_DumpStats(HANDLE hFile);
-
-// Type definitions in case you want to declare a pointer to the dump functions
-// (makes it a trifle easier to do dynamic linking
-// i.e. LoadModule, GetProcAddress and call that)
-
-// Typedefs so can declare MSR_DUMPPROC *MsrDumpStats; or whatever
-typedef void WINAPI MSR_DUMPPROC(HANDLE hFile);
-typedef void WINAPI MSR_CONTROLPROC(int iAction);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // __MEASURE__
diff --git a/dll/src/baseclasses/msgthrd.h b/dll/src/baseclasses/msgthrd.h
deleted file mode 100644
index 45adc01..0000000
--- a/dll/src/baseclasses/msgthrd.h
+++ /dev/null
@@ -1,120 +0,0 @@
-//------------------------------------------------------------------------------
-// File: MsgThrd.h
-//
-// Desc: DirectShow base classes - provides support for a worker thread
-// class to which one can asynchronously post messages.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-// Message class - really just a structure.
-//
-class CMsg {
-public:
- UINT uMsg;
- DWORD dwFlags;
- LPVOID lpParam;
- CAMEvent *pEvent;
-
- CMsg(UINT u, DWORD dw, __inout_opt LPVOID lp, __in_opt CAMEvent *pEvnt)
- : uMsg(u), dwFlags(dw), lpParam(lp), pEvent(pEvnt) {}
-
- CMsg()
- : uMsg(0), dwFlags(0L), lpParam(NULL), pEvent(NULL) {}
-};
-
-// This is the actual thread class. It exports all the usual thread control
-// functions. The created thread is different from a normal WIN32 thread in
-// that it is prompted to perform particaular tasks by responding to messages
-// posted to its message queue.
-//
-class AM_NOVTABLE CMsgThread {
-private:
- static DWORD WINAPI DefaultThreadProc(__inout LPVOID lpParam);
- DWORD m_ThreadId;
- HANDLE m_hThread;
-
-protected:
-
- // if you want to override GetThreadMsg to block on other things
- // as well as this queue, you need access to this
- CGenericList<CMsg> m_ThreadQueue;
- CCritSec m_Lock;
- HANDLE m_hSem;
- LONG m_lWaiting;
-
-public:
- CMsgThread()
- : m_ThreadId(0),
- m_hThread(NULL),
- m_lWaiting(0),
- m_hSem(NULL),
- // make a list with a cache of 5 items
- m_ThreadQueue(NAME("MsgThread list"), 5)
- {
- }
-
- ~CMsgThread();
- // override this if you want to block on other things as well
- // as the message loop
- void virtual GetThreadMsg(__out CMsg *msg);
-
- // override this if you want to do something on thread startup
- virtual void OnThreadInit() {
- };
-
- BOOL CreateThread();
-
- BOOL WaitForThreadExit(__out LPDWORD lpdwExitCode) {
- if (m_hThread != NULL) {
- WaitForSingleObject(m_hThread, INFINITE);
- return GetExitCodeThread(m_hThread, lpdwExitCode);
- }
- return FALSE;
- }
-
- DWORD ResumeThread() {
- return ::ResumeThread(m_hThread);
- }
-
- DWORD SuspendThread() {
- return ::SuspendThread(m_hThread);
- }
-
- int GetThreadPriority() {
- return ::GetThreadPriority(m_hThread);
- }
-
- BOOL SetThreadPriority(int nPriority) {
- return ::SetThreadPriority(m_hThread, nPriority);
- }
-
- HANDLE GetThreadHandle() {
- return m_hThread;
- }
-
- DWORD GetThreadId() {
- return m_ThreadId;
- }
-
-
- void PutThreadMsg(UINT uMsg, DWORD dwMsgFlags,
- __in_opt LPVOID lpMsgParam, __in_opt CAMEvent *pEvent = NULL) {
- CAutoLock lck(&m_Lock);
- CMsg* pMsg = new CMsg(uMsg, dwMsgFlags, lpMsgParam, pEvent);
- m_ThreadQueue.AddTail(pMsg);
- if (m_lWaiting != 0) {
- ReleaseSemaphore(m_hSem, m_lWaiting, 0);
- m_lWaiting = 0;
- }
- }
-
- // This is the function prototype of the function that the client
- // supplies. It is always called on the created thread, never on
- // the creator thread.
- //
- virtual LRESULT ThreadMessageProc(
- UINT uMsg, DWORD dwFlags, __inout_opt LPVOID lpParam, __in_opt CAMEvent *pEvent) = 0;
-};
-
diff --git a/dll/src/baseclasses/mtype.cpp b/dll/src/baseclasses/mtype.cpp
deleted file mode 100644
index fffbcf7..0000000
--- a/dll/src/baseclasses/mtype.cpp
+++ /dev/null
@@ -1,478 +0,0 @@
-//------------------------------------------------------------------------------
-// File: MType.cpp
-//
-// Desc: DirectShow base classes - implements a class that holds and
-// manages media type information.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-// helper class that derived pin objects can use to compare media
-// types etc. Has same data members as the struct AM_MEDIA_TYPE defined
-// in the streams IDL file, but also has (non-virtual) functions
-
-#include <streams.h>
-#include <mmreg.h>
-
-CMediaType::~CMediaType(){
- FreeMediaType(*this);
-}
-
-
-CMediaType::CMediaType()
-{
- InitMediaType();
-}
-
-
-CMediaType::CMediaType(const GUID * type)
-{
- InitMediaType();
- majortype = *type;
-}
-
-
-// copy constructor does a deep copy of the format block
-
-CMediaType::CMediaType(const AM_MEDIA_TYPE& rt, __out_opt HRESULT* phr)
-{
- HRESULT hr = CopyMediaType(this, &rt);
- if (FAILED(hr) && (NULL != phr)) {
- *phr = hr;
- }
-}
-
-
-CMediaType::CMediaType(const CMediaType& rt, __out_opt HRESULT* phr)
-{
- HRESULT hr = CopyMediaType(this, &rt);
- if (FAILED(hr) && (NULL != phr)) {
- *phr = hr;
- }
-}
-
-
-// this class inherits publicly from AM_MEDIA_TYPE so the compiler could generate
-// the following assignment operator itself, however it could introduce some
-// memory conflicts and leaks in the process because the structure contains
-// a dynamically allocated block (pbFormat) which it will not copy correctly
-
-CMediaType&
-CMediaType::operator=(const AM_MEDIA_TYPE& rt)
-{
- Set(rt);
- return *this;
-}
-
-CMediaType&
-CMediaType::operator=(const CMediaType& rt)
-{
- *this = (AM_MEDIA_TYPE &) rt;
- return *this;
-}
-
-BOOL
-CMediaType::operator == (const CMediaType& rt) const
-{
- // I don't believe we need to check sample size or
- // temporal compression flags, since I think these must
- // be represented in the type, subtype and format somehow. They
- // are pulled out as separate flags so that people who don't understand
- // the particular format representation can still see them, but
- // they should duplicate information in the format block.
-
- return ((IsEqualGUID(majortype,rt.majortype) == TRUE) &&
- (IsEqualGUID(subtype,rt.subtype) == TRUE) &&
- (IsEqualGUID(formattype,rt.formattype) == TRUE) &&
- (cbFormat == rt.cbFormat) &&
- ( (cbFormat == 0) ||
- pbFormat != NULL && rt.pbFormat != NULL &&
- (memcmp(pbFormat, rt.pbFormat, cbFormat) == 0)));
-}
-
-
-BOOL
-CMediaType::operator != (const CMediaType& rt) const
-{
- /* Check to see if they are equal */
-
- if (*this == rt) {
- return FALSE;
- }
- return TRUE;
-}
-
-
-HRESULT
-CMediaType::Set(const CMediaType& rt)
-{
- return Set((AM_MEDIA_TYPE &) rt);
-}
-
-
-HRESULT
-CMediaType::Set(const AM_MEDIA_TYPE& rt)
-{
- if (&rt != this) {
- FreeMediaType(*this);
- HRESULT hr = CopyMediaType(this, &rt);
- if (FAILED(hr)) {
- return E_OUTOFMEMORY;
- }
- }
-
- return S_OK;
-}
-
-
-BOOL
-CMediaType::IsValid() const
-{
- return (!IsEqualGUID(majortype,GUID_NULL));
-}
-
-
-void
-CMediaType::SetType(const GUID* ptype)
-{
- majortype = *ptype;
-}
-
-
-void
-CMediaType::SetSubtype(const GUID* ptype)
-{
- subtype = *ptype;
-}
-
-
-ULONG
-CMediaType::GetSampleSize() const {
- if (IsFixedSize()) {
- return lSampleSize;
- } else {
- return 0;
- }
-}
-
-
-void
-CMediaType::SetSampleSize(ULONG sz) {
- if (sz == 0) {
- SetVariableSize();
- } else {
- bFixedSizeSamples = TRUE;
- lSampleSize = sz;
- }
-}
-
-
-void
-CMediaType::SetVariableSize() {
- bFixedSizeSamples = FALSE;
-}
-
-
-void
-CMediaType::SetTemporalCompression(BOOL bCompressed) {
- bTemporalCompression = bCompressed;
-}
-
-BOOL
-CMediaType::SetFormat(__in_bcount(cb) BYTE * pformat, ULONG cb)
-{
- if (NULL == AllocFormatBuffer(cb))
- return(FALSE);
-
- ASSERT(pbFormat);
- memcpy(pbFormat, pformat, cb);
- return(TRUE);
-}
-
-
-// set the type of the media type format block, this type defines what you
-// will actually find in the format pointer. For example FORMAT_VideoInfo or
-// FORMAT_WaveFormatEx. In the future this may be an interface pointer to a
-// property set. Before sending out media types this should be filled in.
-
-void
-CMediaType::SetFormatType(const GUID *pformattype)
-{
- formattype = *pformattype;
-}
-
-
-// reset the format buffer
-
-void CMediaType::ResetFormatBuffer()
-{
- if (cbFormat) {
- CoTaskMemFree((PVOID)pbFormat);
- }
- cbFormat = 0;
- pbFormat = NULL;
-}
-
-
-// allocate length bytes for the format and return a read/write pointer
-// If we cannot allocate the new block of memory we return NULL leaving
-// the original block of memory untouched (as does ReallocFormatBuffer)
-
-BYTE*
-CMediaType::AllocFormatBuffer(ULONG length)
-{
- ASSERT(length);
-
- // do the types have the same buffer size
-
- if (cbFormat == length) {
- return pbFormat;
- }
-
- // allocate the new format buffer
-
- BYTE *pNewFormat = (PBYTE)CoTaskMemAlloc(length);
- if (pNewFormat == NULL) {
- if (length <= cbFormat) return pbFormat; //reuse the old block anyway.
- return NULL;
- }
-
- // delete the old format
-
- if (cbFormat != 0) {
- ASSERT(pbFormat);
- CoTaskMemFree((PVOID)pbFormat);
- }
-
- cbFormat = length;
- pbFormat = pNewFormat;
- return pbFormat;
-}
-
-
-// reallocate length bytes for the format and return a read/write pointer
-// to it. We keep as much information as we can given the new buffer size
-// if this fails the original format buffer is left untouched. The caller
-// is responsible for ensuring the size of memory required is non zero
-
-BYTE*
-CMediaType::ReallocFormatBuffer(ULONG length)
-{
- ASSERT(length);
-
- // do the types have the same buffer size
-
- if (cbFormat == length) {
- return pbFormat;
- }
-
- // allocate the new format buffer
-
- BYTE *pNewFormat = (PBYTE)CoTaskMemAlloc(length);
- if (pNewFormat == NULL) {
- if (length <= cbFormat) return pbFormat; //reuse the old block anyway.
- return NULL;
- }
-
- // copy any previous format (or part of if new is smaller)
- // delete the old format and replace with the new one
-
- if (cbFormat != 0) {
- ASSERT(pbFormat);
- memcpy(pNewFormat,pbFormat,min(length,cbFormat));
- CoTaskMemFree((PVOID)pbFormat);
- }
-
- cbFormat = length;
- pbFormat = pNewFormat;
- return pNewFormat;
-}
-
-// initialise a media type structure
-
-void CMediaType::InitMediaType()
-{
- ZeroMemory((PVOID)this, sizeof(*this));
- lSampleSize = 1;
- bFixedSizeSamples = TRUE;
-}
-
-
-// a partially specified media type can be passed to IPin::Connect
-// as a constraint on the media type used in the connection.
-// the type, subtype or format type can be null.
-BOOL
-CMediaType::IsPartiallySpecified(void) const
-{
- if ((majortype == GUID_NULL) ||
- (formattype == GUID_NULL)) {
- return TRUE;
- } else {
- return FALSE;
- }
-}
-
-BOOL
-CMediaType::MatchesPartial(const CMediaType* ppartial) const
-{
- if ((ppartial->majortype != GUID_NULL) &&
- (majortype != ppartial->majortype)) {
- return FALSE;
- }
- if ((ppartial->subtype != GUID_NULL) &&
- (subtype != ppartial->subtype)) {
- return FALSE;
- }
-
- if (ppartial->formattype != GUID_NULL) {
- // if the format block is specified then it must match exactly
- if (formattype != ppartial->formattype) {
- return FALSE;
- }
- if (cbFormat != ppartial->cbFormat) {
- return FALSE;
- }
- if ((cbFormat != 0) &&
- (memcmp(pbFormat, ppartial->pbFormat, cbFormat) != 0)) {
- return FALSE;
- }
- }
-
- return TRUE;
-
-}
-
-
-
-// general purpose function to delete a heap allocated AM_MEDIA_TYPE structure
-// which is useful when calling IEnumMediaTypes::Next as the interface
-// implementation allocates the structures which you must later delete
-// the format block may also be a pointer to an interface to release
-
-void WINAPI DeleteMediaType(__inout_opt AM_MEDIA_TYPE *pmt)
-{
- // allow NULL pointers for coding simplicity
-
- if (pmt == NULL) {
- return;
- }
-
- FreeMediaType(*pmt);
- CoTaskMemFree((PVOID)pmt);
-}
-
-
-// this also comes in useful when using the IEnumMediaTypes interface so
-// that you can copy a media type, you can do nearly the same by creating
-// a CMediaType object but as soon as it goes out of scope the destructor
-// will delete the memory it allocated (this takes a copy of the memory)
-
-AM_MEDIA_TYPE * WINAPI CreateMediaType(AM_MEDIA_TYPE const *pSrc)
-{
- ASSERT(pSrc);
-
- // Allocate a block of memory for the media type
-
- AM_MEDIA_TYPE *pMediaType =
- (AM_MEDIA_TYPE *)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
-
- if (pMediaType == NULL) {
- return NULL;
- }
- // Copy the variable length format block
-
- HRESULT hr = CopyMediaType(pMediaType,pSrc);
- if (FAILED(hr)) {
- CoTaskMemFree((PVOID)pMediaType);
- return NULL;
- }
-
- return pMediaType;
-}
-
-
-// Copy 1 media type to another
-
-HRESULT WINAPI CopyMediaType(__out AM_MEDIA_TYPE *pmtTarget, const AM_MEDIA_TYPE *pmtSource)
-{
- // We'll leak if we copy onto one that already exists - there's one
- // case we can check like that - copying to itself.
- ASSERT(pmtSource != pmtTarget);
- *pmtTarget = *pmtSource;
- if (pmtSource->cbFormat != 0) {
- ASSERT(pmtSource->pbFormat != NULL);
- pmtTarget->pbFormat = (PBYTE)CoTaskMemAlloc(pmtSource->cbFormat);
- if (pmtTarget->pbFormat == NULL) {
- pmtTarget->cbFormat = 0;
- return E_OUTOFMEMORY;
- } else {
- CopyMemory((PVOID)pmtTarget->pbFormat, (PVOID)pmtSource->pbFormat,
- pmtTarget->cbFormat);
- }
- }
- if (pmtTarget->pUnk != NULL) {
- pmtTarget->pUnk->AddRef();
- }
-
- return S_OK;
-}
-
-// Free an existing media type (ie free resources it holds)
-
-void WINAPI FreeMediaType(__inout AM_MEDIA_TYPE& mt)
-{
- if (mt.cbFormat != 0) {
- CoTaskMemFree((PVOID)mt.pbFormat);
-
- // Strictly unnecessary but tidier
- mt.cbFormat = 0;
- mt.pbFormat = NULL;
- }
- if (mt.pUnk != NULL) {
- mt.pUnk->Release();
- mt.pUnk = NULL;
- }
-}
-
-// Initialize a media type from a WAVEFORMATEX
-
-STDAPI CreateAudioMediaType(
- const WAVEFORMATEX *pwfx,
- __out AM_MEDIA_TYPE *pmt,
- BOOL bSetFormat
-)
-{
- pmt->majortype = MEDIATYPE_Audio;
- if (pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
- pmt->subtype = ((PWAVEFORMATEXTENSIBLE)pwfx)->SubFormat;
- } else {
- pmt->subtype = FOURCCMap(pwfx->wFormatTag);
- }
- pmt->formattype = FORMAT_WaveFormatEx;
- pmt->bFixedSizeSamples = TRUE;
- pmt->bTemporalCompression = FALSE;
- pmt->lSampleSize = pwfx->nBlockAlign;
- pmt->pUnk = NULL;
- if (bSetFormat) {
- if (pwfx->wFormatTag == WAVE_FORMAT_PCM) {
- pmt->cbFormat = sizeof(WAVEFORMATEX);
- } else {
- pmt->cbFormat = sizeof(WAVEFORMATEX) + pwfx->cbSize;
- }
- pmt->pbFormat = (PBYTE)CoTaskMemAlloc(pmt->cbFormat);
- if (pmt->pbFormat == NULL) {
- return E_OUTOFMEMORY;
- }
- if (pwfx->wFormatTag == WAVE_FORMAT_PCM) {
- CopyMemory(pmt->pbFormat, pwfx, sizeof(PCMWAVEFORMAT));
- ((WAVEFORMATEX *)pmt->pbFormat)->cbSize = 0;
- } else {
- CopyMemory(pmt->pbFormat, pwfx, pmt->cbFormat);
- }
- }
- return S_OK;
-}
-
-// eliminate very many spurious warnings from MS compiler
-#pragma warning(disable:4514)
diff --git a/dll/src/baseclasses/mtype.h b/dll/src/baseclasses/mtype.h
deleted file mode 100644
index fc2fe53..0000000
--- a/dll/src/baseclasses/mtype.h
+++ /dev/null
@@ -1,89 +0,0 @@
-//------------------------------------------------------------------------------
-// File: MtType.h
-//
-// Desc: DirectShow base classes - defines a class that holds and manages
-// media type information.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-#ifndef __MTYPE__
-#define __MTYPE__
-
-/* Helper class that derived pin objects can use to compare media
- types etc. Has same data members as the struct AM_MEDIA_TYPE defined
- in the streams IDL file, but also has (non-virtual) functions */
-
-class CMediaType : public _AMMediaType {
-
-public:
-
- ~CMediaType();
- CMediaType();
- CMediaType(const GUID * majortype);
- CMediaType(const AM_MEDIA_TYPE&, __out_opt HRESULT* phr = NULL);
- CMediaType(const CMediaType&, __out_opt HRESULT* phr = NULL);
-
- CMediaType& operator=(const CMediaType&);
- CMediaType& operator=(const AM_MEDIA_TYPE&);
-
- BOOL operator == (const CMediaType&) const;
- BOOL operator != (const CMediaType&) const;
-
- HRESULT Set(const CMediaType& rt);
- HRESULT Set(const AM_MEDIA_TYPE& rt);
-
- BOOL IsValid() const;
-
- const GUID *Type() const { return &majortype;} ;
- void SetType(const GUID *);
- const GUID *Subtype() const { return &subtype;} ;
- void SetSubtype(const GUID *);
-
- BOOL IsFixedSize() const {return bFixedSizeSamples; };
- BOOL IsTemporalCompressed() const {return bTemporalCompression; };
- ULONG GetSampleSize() const;
-
- void SetSampleSize(ULONG sz);
- void SetVariableSize();
- void SetTemporalCompression(BOOL bCompressed);
-
- // read/write pointer to format - can't change length without
- // calling SetFormat, AllocFormatBuffer or ReallocFormatBuffer
-
- BYTE* Format() const {return pbFormat; };
- ULONG FormatLength() const { return cbFormat; };
-
- void SetFormatType(const GUID *);
- const GUID *FormatType() const {return &formattype; };
- BOOL SetFormat(__in_bcount(length) BYTE *pFormat, ULONG length);
- void ResetFormatBuffer();
- BYTE* AllocFormatBuffer(ULONG length);
- BYTE* ReallocFormatBuffer(ULONG length);
-
- void InitMediaType();
-
- BOOL MatchesPartial(const CMediaType* ppartial) const;
- BOOL IsPartiallySpecified(void) const;
-};
-
-
-/* General purpose functions to copy and delete a task allocated AM_MEDIA_TYPE
- structure which is useful when using the IEnumMediaFormats interface as
- the implementation allocates the structures which you must later delete */
-
-void WINAPI DeleteMediaType(__inout_opt AM_MEDIA_TYPE *pmt);
-AM_MEDIA_TYPE * WINAPI CreateMediaType(AM_MEDIA_TYPE const *pSrc);
-HRESULT WINAPI CopyMediaType(__out AM_MEDIA_TYPE *pmtTarget, const AM_MEDIA_TYPE *pmtSource);
-void WINAPI FreeMediaType(__inout AM_MEDIA_TYPE& mt);
-
-// Initialize a media type from a WAVEFORMATEX
-
-STDAPI CreateAudioMediaType(
- const WAVEFORMATEX *pwfx,
- __out AM_MEDIA_TYPE *pmt,
- BOOL bSetFormat);
-
-#endif /* __MTYPE__ */
-
diff --git a/dll/src/baseclasses/outputq.cpp b/dll/src/baseclasses/outputq.cpp
deleted file mode 100644
index 6b43ab4..0000000
--- a/dll/src/baseclasses/outputq.cpp
+++ /dev/null
@@ -1,801 +0,0 @@
-//------------------------------------------------------------------------------
-// File: OutputQ.cpp
-//
-// Desc: DirectShow base classes - implements COutputQueue class used by an
-// output pin which may sometimes want to queue output samples on a
-// separate thread and sometimes call Receive() directly on the input
-// pin.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-#include <streams.h>
-
-
-//
-// COutputQueue Constructor :
-//
-// Determines if a thread is to be created and creates resources
-//
-// pInputPin - the downstream input pin we're queueing samples to
-//
-// phr - changed to a failure code if this function fails
-// (otherwise unchanges)
-//
-// bAuto - Ask pInputPin if it can block in Receive by calling
-// its ReceiveCanBlock method and create a thread if
-// it can block, otherwise not.
-//
-// bQueue - if bAuto == FALSE then we create a thread if and only
-// if bQueue == TRUE
-//
-// lBatchSize - work in batches of lBatchSize
-//
-// bBatchEact - Use exact batch sizes so don't send until the
-// batch is full or SendAnyway() is called
-//
-// lListSize - If we create a thread make the list of samples queued
-// to the thread have this size cache
-//
-// dwPriority - If we create a thread set its priority to this
-//
-COutputQueue::COutputQueue(
- IPin *pInputPin, // Pin to send stuff to
- __inout HRESULT *phr, // 'Return code'
- BOOL bAuto, // Ask pin if queue or not
- BOOL bQueue, // Send through queue
- LONG lBatchSize, // Batch
- BOOL bBatchExact, // Batch exactly to BatchSize
- LONG lListSize,
- DWORD dwPriority,
- bool bFlushingOpt // flushing optimization
- ) : m_lBatchSize(lBatchSize),
- m_bBatchExact(bBatchExact && (lBatchSize > 1)),
- m_hThread(NULL),
- m_hSem(NULL),
- m_List(NULL),
- m_pPin(pInputPin),
- m_ppSamples(NULL),
- m_lWaiting(0),
- m_evFlushComplete(FALSE, phr),
- m_pInputPin(NULL),
- m_bSendAnyway(FALSE),
- m_nBatched(0),
- m_bFlushing(FALSE),
- m_bFlushed(TRUE),
- m_bFlushingOpt(bFlushingOpt),
- m_bTerminate(FALSE),
- m_hEventPop(NULL),
- m_hr(S_OK)
-{
- ASSERT(m_lBatchSize > 0);
-
-
- if (FAILED(*phr)) {
- return;
- }
-
- // Check the input pin is OK and cache its IMemInputPin interface
-
- *phr = pInputPin->QueryInterface(IID_IMemInputPin, (void **)&m_pInputPin);
- if (FAILED(*phr)) {
- return;
- }
-
- // See if we should ask the downstream pin
-
- if (bAuto) {
- HRESULT hr = m_pInputPin->ReceiveCanBlock();
- if (SUCCEEDED(hr)) {
- bQueue = hr == S_OK;
- }
- }
-
- // Create our sample batch
-
- m_ppSamples = new PMEDIASAMPLE[m_lBatchSize];
- if (m_ppSamples == NULL) {
- *phr = E_OUTOFMEMORY;
- return;
- }
-
- // If we're queueing allocate resources
-
- if (bQueue) {
- DbgLog((LOG_TRACE, 2, TEXT("Creating thread for output pin")));
- m_hSem = CreateSemaphore(NULL, 0, 0x7FFFFFFF, NULL);
- if (m_hSem == NULL) {
- DWORD dwError = GetLastError();
- *phr = AmHresultFromWin32(dwError);
- return;
- }
- m_List = new CSampleList(NAME("Sample Queue List"),
- lListSize,
- FALSE // No lock
- );
- if (m_List == NULL) {
- *phr = E_OUTOFMEMORY;
- return;
- }
-
-
- DWORD dwThreadId;
- m_hThread = CreateThread(NULL,
- 0,
- InitialThreadProc,
- (LPVOID)this,
- 0,
- &dwThreadId);
- if (m_hThread == NULL) {
- DWORD dwError = GetLastError();
- *phr = AmHresultFromWin32(dwError);
- return;
- }
- SetThreadPriority(m_hThread, dwPriority);
- } else {
- DbgLog((LOG_TRACE, 2, TEXT("Calling input pin directly - no thread")));
- }
-}
-
-//
-// COutputQueuee Destructor :
-//
-// Free all resources -
-//
-// Thread,
-// Batched samples
-//
-COutputQueue::~COutputQueue()
-{
- DbgLog((LOG_TRACE, 3, TEXT("COutputQueue::~COutputQueue")));
- /* Free our pointer */
- if (m_pInputPin != NULL) {
- m_pInputPin->Release();
- }
- if (m_hThread != NULL) {
- {
- CAutoLock lck(this);
- m_bTerminate = TRUE;
- m_hr = S_FALSE;
- NotifyThread();
- }
- DbgWaitForSingleObject(m_hThread);
- EXECUTE_ASSERT(CloseHandle(m_hThread));
-
- // The thread frees the samples when asked to terminate
-
- ASSERT(m_List->GetCount() == 0);
- delete m_List;
- } else {
- FreeSamples();
- }
- if (m_hSem != NULL) {
- EXECUTE_ASSERT(CloseHandle(m_hSem));
- }
- delete [] m_ppSamples;
-}
-
-//
-// Call the real thread proc as a member function
-//
-DWORD WINAPI COutputQueue::InitialThreadProc(__in LPVOID pv)
-{
- HRESULT hrCoInit = CAMThread::CoInitializeHelper();
-
- COutputQueue *pSampleQueue = (COutputQueue *)pv;
- DWORD dwReturn = pSampleQueue->ThreadProc();
-
- if(hrCoInit == S_OK) {
- CoUninitialize();
- }
-
- return dwReturn;
-}
-
-//
-// Thread sending the samples downstream :
-//
-// When there is nothing to do the thread sets m_lWaiting (while
-// holding the critical section) and then waits for m_hSem to be
-// set (not holding the critical section)
-//
-DWORD COutputQueue::ThreadProc()
-{
- while (TRUE) {
- BOOL bWait = FALSE;
- IMediaSample *pSample;
- LONG lNumberToSend; // Local copy
- NewSegmentPacket* ppacket = 0;
-
- //
- // Get a batch of samples and send it if possible
- // In any case exit the loop if there is a control action
- // requested
- //
- {
- CAutoLock lck(this);
- while (TRUE) {
-
- if (m_bTerminate) {
- FreeSamples();
- return 0;
- }
- if (m_bFlushing) {
- FreeSamples();
- SetEvent(m_evFlushComplete);
- }
-
- // Get a sample off the list
-
- pSample = m_List->RemoveHead();
- // inform derived class we took something off the queue
- if (m_hEventPop) {
- //DbgLog((LOG_TRACE,3,TEXT("Queue: Delivered SET EVENT")));
- SetEvent(m_hEventPop);
- }
-
- if (pSample != NULL &&
- !IsSpecialSample(pSample)) {
-
- // If its just a regular sample just add it to the batch
- // and exit the loop if the batch is full
-
- m_ppSamples[m_nBatched++] = pSample;
- if (m_nBatched == m_lBatchSize) {
- break;
- }
- } else {
-
- // If there was nothing in the queue and there's nothing
- // to send (either because there's nothing or the batch
- // isn't full) then prepare to wait
-
- if (pSample == NULL &&
- (m_bBatchExact || m_nBatched == 0)) {
-
- // Tell other thread to set the event when there's
- // something do to
-
- ASSERT(m_lWaiting == 0);
- m_lWaiting++;
- bWait = TRUE;
- } else {
-
- // We break out of the loop on SEND_PACKET unless
- // there's nothing to send
-
- if (pSample == SEND_PACKET && m_nBatched == 0) {
- continue;
- }
-
- if (pSample == NEW_SEGMENT) {
- // now we need the parameters - we are
- // guaranteed that the next packet contains them
- ppacket = (NewSegmentPacket *) m_List->RemoveHead();
- // we took something off the queue
- if (m_hEventPop) {
- //DbgLog((LOG_TRACE,3,TEXT("Queue: Delivered SET EVENT")));
- SetEvent(m_hEventPop);
- }
-
- ASSERT(ppacket);
- }
- // EOS_PACKET falls through here and we exit the loop
- // In this way it acts like SEND_PACKET
- }
- break;
- }
- }
- if (!bWait) {
- // We look at m_nBatched from the client side so keep
- // it up to date inside the critical section
- lNumberToSend = m_nBatched; // Local copy
- m_nBatched = 0;
- }
- }
-
- // Wait for some more data
-
- if (bWait) {
- DbgWaitForSingleObject(m_hSem);
- continue;
- }
-
-
-
- // OK - send it if there's anything to send
- // We DON'T check m_bBatchExact here because either we've got
- // a full batch or we dropped through because we got
- // SEND_PACKET or EOS_PACKET - both of which imply we should
- // flush our batch
-
- if (lNumberToSend != 0) {
- long nProcessed;
- if (m_hr == S_OK) {
- ASSERT(!m_bFlushed);
- HRESULT hr = m_pInputPin->ReceiveMultiple(m_ppSamples,
- lNumberToSend,
- &nProcessed);
- /* Don't overwrite a flushing state HRESULT */
- CAutoLock lck(this);
- if (m_hr == S_OK) {
- m_hr = hr;
- }
- ASSERT(!m_bFlushed);
- }
- while (lNumberToSend != 0) {
- m_ppSamples[--lNumberToSend]->Release();
- }
- if (m_hr != S_OK) {
-
- // In any case wait for more data - S_OK just
- // means there wasn't an error
-
- DbgLog((LOG_ERROR, 2, TEXT("ReceiveMultiple returned %8.8X"),
- m_hr));
- }
- }
-
- // Check for end of stream
-
- if (pSample == EOS_PACKET) {
-
- // We don't send even end of stream on if we've previously
- // returned something other than S_OK
- // This is because in that case the pin which returned
- // something other than S_OK should have either sent
- // EndOfStream() or notified the filter graph
-
- if (m_hr == S_OK) {
- DbgLog((LOG_TRACE, 2, TEXT("COutputQueue sending EndOfStream()")));
- HRESULT hr = m_pPin->EndOfStream();
- if (FAILED(hr)) {
- DbgLog((LOG_ERROR, 2, TEXT("COutputQueue got code 0x%8.8X from EndOfStream()")));
- }
- }
- }
-
- // Data from a new source
-
- if (pSample == RESET_PACKET) {
- m_hr = S_OK;
- SetEvent(m_evFlushComplete);
- }
-
- if (pSample == NEW_SEGMENT) {
- m_pPin->NewSegment(ppacket->tStart, ppacket->tStop, ppacket->dRate);
- delete ppacket;
- }
- }
-}
-
-// Send batched stuff anyway
-void COutputQueue::SendAnyway()
-{
- if (!IsQueued()) {
-
- // m_bSendAnyway is a private parameter checked in ReceiveMultiple
-
- m_bSendAnyway = TRUE;
- LONG nProcessed;
- ReceiveMultiple(NULL, 0, &nProcessed);
- m_bSendAnyway = FALSE;
-
- } else {
- CAutoLock lck(this);
- QueueSample(SEND_PACKET);
- NotifyThread();
- }
-}
-
-void
-COutputQueue::NewSegment(
- REFERENCE_TIME tStart,
- REFERENCE_TIME tStop,
- double dRate)
-{
- if (!IsQueued()) {
- if (S_OK == m_hr) {
- if (m_bBatchExact) {
- SendAnyway();
- }
- m_pPin->NewSegment(tStart, tStop, dRate);
- }
- } else {
- if (m_hr == S_OK) {
- //
- // we need to queue the new segment to appear in order in the
- // data, but we need to pass parameters to it. Rather than
- // take the hit of wrapping every single sample so we can tell
- // special ones apart, we queue special pointers to indicate
- // special packets, and we guarantee (by holding the
- // critical section) that the packet immediately following a
- // NEW_SEGMENT value is a NewSegmentPacket containing the
- // parameters.
- NewSegmentPacket * ppack = new NewSegmentPacket;
- if (ppack == NULL) {
- return;
- }
- ppack->tStart = tStart;
- ppack->tStop = tStop;
- ppack->dRate = dRate;
-
- CAutoLock lck(this);
- QueueSample(NEW_SEGMENT);
- QueueSample( (IMediaSample*) ppack);
- NotifyThread();
- }
- }
-}
-
-
-//
-// End of Stream is queued to output device
-//
-void COutputQueue::EOS()
-{
- CAutoLock lck(this);
- if (!IsQueued()) {
- if (m_bBatchExact) {
- SendAnyway();
- }
- if (m_hr == S_OK) {
- DbgLog((LOG_TRACE, 2, TEXT("COutputQueue sending EndOfStream()")));
- m_bFlushed = FALSE;
- HRESULT hr = m_pPin->EndOfStream();
- if (FAILED(hr)) {
- DbgLog((LOG_ERROR, 2, TEXT("COutputQueue got code 0x%8.8X from EndOfStream()")));
- }
- }
- } else {
- if (m_hr == S_OK) {
- m_bFlushed = FALSE;
- QueueSample(EOS_PACKET);
- NotifyThread();
- }
- }
-}
-
-//
-// Flush all the samples in the queue
-//
-void COutputQueue::BeginFlush()
-{
- if (IsQueued()) {
- {
- CAutoLock lck(this);
-
- // block receives -- we assume this is done by the
- // filter in which we are a component
-
- // discard all queued data
-
- m_bFlushing = TRUE;
-
- // Make sure we discard all samples from now on
-
- if (m_hr == S_OK) {
- m_hr = S_FALSE;
- }
-
- // Optimize so we don't keep calling downstream all the time
-
- if (m_bFlushed && m_bFlushingOpt) {
- return;
- }
-
- // Make sure we really wait for the flush to complete
- m_evFlushComplete.Reset();
-
- NotifyThread();
- }
-
- // pass this downstream
-
- m_pPin->BeginFlush();
- } else {
- // pass downstream first to avoid deadlocks
- m_pPin->BeginFlush();
- CAutoLock lck(this);
- // discard all queued data
-
- m_bFlushing = TRUE;
-
- // Make sure we discard all samples from now on
-
- if (m_hr == S_OK) {
- m_hr = S_FALSE;
- }
- }
-
-}
-
-//
-// leave flush mode - pass this downstream
-void COutputQueue::EndFlush()
-{
- {
- CAutoLock lck(this);
- ASSERT(m_bFlushing);
- if (m_bFlushingOpt && m_bFlushed && IsQueued()) {
- m_bFlushing = FALSE;
- m_hr = S_OK;
- return;
- }
- }
-
- // sync with pushing thread -- done in BeginFlush
- // ensure no more data to go downstream -- done in BeginFlush
- //
- // Because we are synching here there is no need to hold the critical
- // section (in fact we'd deadlock if we did!)
-
- if (IsQueued()) {
- m_evFlushComplete.Wait();
- } else {
- FreeSamples();
- }
-
- // Be daring - the caller has guaranteed no samples will arrive
- // before EndFlush() returns
-
- m_bFlushing = FALSE;
- m_bFlushed = TRUE;
-
- // call EndFlush on downstream pins
-
- m_pPin->EndFlush();
-
- m_hr = S_OK;
-}
-
-// COutputQueue::QueueSample
-//
-// private method to Send a sample to the output queue
-// The critical section MUST be held when this is called
-
-void COutputQueue::QueueSample(IMediaSample *pSample)
-{
- if (NULL == m_List->AddTail(pSample)) {
- if (!IsSpecialSample(pSample)) {
- pSample->Release();
- }
- }
-}
-
-//
-// COutputQueue::Receive()
-//
-// Send a single sample by the multiple sample route
-// (NOTE - this could be optimized if necessary)
-//
-// On return the sample will have been Release()'d
-//
-
-HRESULT COutputQueue::Receive(IMediaSample *pSample)
-{
- LONG nProcessed;
- return ReceiveMultiple(&pSample, 1, &nProcessed);
-}
-
-//
-// COutputQueue::ReceiveMultiple()
-//
-// Send a set of samples to the downstream pin
-//
-// ppSamples - array of samples
-// nSamples - how many
-// nSamplesProcessed - How many were processed
-//
-// On return all samples will have been Release()'d
-//
-
-HRESULT COutputQueue::ReceiveMultiple (
- __in_ecount(nSamples) IMediaSample **ppSamples,
- long nSamples,
- __out long *nSamplesProcessed)
-{
- if (nSamples < 0) {
- return E_INVALIDARG;
- }
-
- CAutoLock lck(this);
- // Either call directly or queue up the samples
-
- if (!IsQueued()) {
-
- // If we already had a bad return code then just return
-
- if (S_OK != m_hr) {
-
- // If we've never received anything since the last Flush()
- // and the sticky return code is not S_OK we must be
- // flushing
- // ((!A || B) is equivalent to A implies B)
- ASSERT(!m_bFlushed || m_bFlushing);
-
- // We're supposed to Release() them anyway!
- *nSamplesProcessed = 0;
- for (int i = 0; i < nSamples; i++) {
- DbgLog((LOG_TRACE, 3, TEXT("COutputQueue (direct) : Discarding %d samples code 0x%8.8X"),
- nSamples, m_hr));
- ppSamples[i]->Release();
- }
-
- return m_hr;
- }
- //
- // If we're flushing the sticky return code should be S_FALSE
- //
- ASSERT(!m_bFlushing);
- m_bFlushed = FALSE;
-
- ASSERT(m_nBatched < m_lBatchSize);
- ASSERT(m_nBatched == 0 || m_bBatchExact);
-
- // Loop processing the samples in batches
-
- LONG iLost = 0;
- long iDone = 0;
- for (iDone = 0;
- iDone < nSamples || (m_nBatched != 0 && m_bSendAnyway);
- ) {
-
-//pragma message (REMIND("Implement threshold scheme"))
- ASSERT(m_nBatched < m_lBatchSize);
- if (iDone < nSamples) {
- m_ppSamples[m_nBatched++] = ppSamples[iDone++];
- }
- if (m_nBatched == m_lBatchSize ||
- nSamples == 0 && (m_bSendAnyway || !m_bBatchExact)) {
- LONG nDone;
- DbgLog((LOG_TRACE, 4, TEXT("Batching %d samples"),
- m_nBatched));
-
- if (m_hr == S_OK) {
- m_hr = m_pInputPin->ReceiveMultiple(m_ppSamples,
- m_nBatched,
- &nDone);
- } else {
- nDone = 0;
- }
- iLost += m_nBatched - nDone;
- for (LONG i = 0; i < m_nBatched; i++) {
- m_ppSamples[i]->Release();
- }
- m_nBatched = 0;
- }
- }
- *nSamplesProcessed = iDone - iLost;
- if (*nSamplesProcessed < 0) {
- *nSamplesProcessed = 0;
- }
- return m_hr;
- } else {
- /* We're sending to our thread */
-
- if (m_hr != S_OK) {
- *nSamplesProcessed = 0;
- DbgLog((LOG_TRACE, 3, TEXT("COutputQueue (queued) : Discarding %d samples code 0x%8.8X"),
- nSamples, m_hr));
- for (int i = 0; i < nSamples; i++) {
- ppSamples[i]->Release();
- }
- return m_hr;
- }
- m_bFlushed = FALSE;
- for (long i = 0; i < nSamples; i++) {
- QueueSample(ppSamples[i]);
- }
- *nSamplesProcessed = nSamples;
- if (!m_bBatchExact ||
- m_nBatched + m_List->GetCount() >= m_lBatchSize) {
- NotifyThread();
- }
- return S_OK;
- }
-}
-
-// Get ready for new data - cancels sticky m_hr
-void COutputQueue::Reset()
-{
- if (!IsQueued()) {
- m_hr = S_OK;
- } else {
- {
- CAutoLock lck(this);
- QueueSample(RESET_PACKET);
- NotifyThread();
- }
- m_evFlushComplete.Wait();
- }
-}
-
-// Remove and Release() all queued and Batched samples
-void COutputQueue::FreeSamples()
-{
- CAutoLock lck(this);
- if (IsQueued()) {
- while (TRUE) {
- IMediaSample *pSample = m_List->RemoveHead();
- // inform derived class we took something off the queue
- if (m_hEventPop) {
- //DbgLog((LOG_TRACE,3,TEXT("Queue: Delivered SET EVENT")));
- SetEvent(m_hEventPop);
- }
-
- if (pSample == NULL) {
- break;
- }
- if (!IsSpecialSample(pSample)) {
- pSample->Release();
- } else {
- if (pSample == NEW_SEGMENT) {
- // Free NEW_SEGMENT packet
- NewSegmentPacket *ppacket =
- (NewSegmentPacket *) m_List->RemoveHead();
- // inform derived class we took something off the queue
- if (m_hEventPop) {
- //DbgLog((LOG_TRACE,3,TEXT("Queue: Delivered SET EVENT")));
- SetEvent(m_hEventPop);
- }
-
- ASSERT(ppacket != NULL);
- delete ppacket;
- }
- }
- }
- }
- for (int i = 0; i < m_nBatched; i++) {
- m_ppSamples[i]->Release();
- }
- m_nBatched = 0;
-}
-
-// Notify the thread if there is something to do
-//
-// The critical section MUST be held when this is called
-void COutputQueue::NotifyThread()
-{
- // Optimize - no need to signal if it's not waiting
- ASSERT(IsQueued());
- if (m_lWaiting) {
- ReleaseSemaphore(m_hSem, m_lWaiting, NULL);
- m_lWaiting = 0;
- }
-}
-
-// See if there's any work to do
-// Returns
-// TRUE if there is nothing on the queue and nothing in the batch
-// and all data has been sent
-// FALSE otherwise
-//
-BOOL COutputQueue::IsIdle()
-{
- CAutoLock lck(this);
-
- // We're idle if
- // there is no thread (!IsQueued()) OR
- // the thread is waiting for more work (m_lWaiting != 0)
- // AND
- // there's nothing in the current batch (m_nBatched == 0)
-
- if (IsQueued() && m_lWaiting == 0 || m_nBatched != 0) {
- return FALSE;
- } else {
-
- // If we're idle it shouldn't be possible for there
- // to be anything on the work queue
-
- ASSERT(!IsQueued() || m_List->GetCount() == 0);
- return TRUE;
- }
-}
-
-
-void COutputQueue::SetPopEvent(HANDLE hEvent)
-{
- m_hEventPop = hEvent;
-}
diff --git a/dll/src/baseclasses/outputq.h b/dll/src/baseclasses/outputq.h
deleted file mode 100644
index db3d424..0000000
--- a/dll/src/baseclasses/outputq.h
+++ /dev/null
@@ -1,137 +0,0 @@
-//------------------------------------------------------------------------------
-// File: OutputQ.h
-//
-// Desc: DirectShow base classes - defines the COutputQueue class, which
-// makes a queue of samples and sends them to an output pin. The
-// class will optionally send the samples to the pin directly.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-typedef CGenericList<IMediaSample> CSampleList;
-
-class COutputQueue : public CCritSec
-{
-public:
- // Constructor
- COutputQueue(IPin *pInputPin, // Pin to send stuff to
- __inout HRESULT *phr, // 'Return code'
- BOOL bAuto = TRUE, // Ask pin if blocks
- BOOL bQueue = TRUE, // Send through queue (ignored if
- // bAuto set)
- LONG lBatchSize = 1, // Batch
- BOOL bBatchExact = FALSE,// Batch exactly to BatchSize
- LONG lListSize = // Likely number in the list
- DEFAULTCACHE,
- DWORD dwPriority = // Priority of thread to create
- THREAD_PRIORITY_NORMAL,
- bool bFlushingOpt = false // flushing optimization
- );
- ~COutputQueue();
-
- // enter flush state - discard all data
- void BeginFlush(); // Begin flushing samples
-
- // re-enable receives (pass this downstream)
- void EndFlush(); // Complete flush of samples - downstream
- // pin guaranteed not to block at this stage
-
- void EOS(); // Call this on End of stream
-
- void SendAnyway(); // Send batched samples anyway (if bBatchExact set)
-
- void NewSegment(
- REFERENCE_TIME tStart,
- REFERENCE_TIME tStop,
- double dRate);
-
- HRESULT Receive(IMediaSample *pSample);
-
- // do something with these media samples
- HRESULT ReceiveMultiple (
- __in_ecount(nSamples) IMediaSample **pSamples,
- long nSamples,
- __out long *nSamplesProcessed);
-
- void Reset(); // Reset m_hr ready for more data
-
- // See if its idle or not
- BOOL IsIdle();
-
- // give the class an event to fire after everything removed from the queue
- void SetPopEvent(HANDLE hEvent);
-
-protected:
- static DWORD WINAPI InitialThreadProc(__in LPVOID pv);
- DWORD ThreadProc();
- BOOL IsQueued()
- {
- return m_List != NULL;
- };
-
- // The critical section MUST be held when this is called
- void QueueSample(IMediaSample *pSample);
-
- BOOL IsSpecialSample(IMediaSample *pSample)
- {
- return (DWORD_PTR)pSample > (DWORD_PTR)(LONG_PTR)(-16);
- };
-
- // Remove and Release() batched and queued samples
- void FreeSamples();
-
- // Notify the thread there is something to do
- void NotifyThread();
-
-
-protected:
- // Queue 'messages'
- #define SEND_PACKET ((IMediaSample *)(LONG_PTR)(-2)) // Send batch
- #define EOS_PACKET ((IMediaSample *)(LONG_PTR)(-3)) // End of stream
- #define RESET_PACKET ((IMediaSample *)(LONG_PTR)(-4)) // Reset m_hr
- #define NEW_SEGMENT ((IMediaSample *)(LONG_PTR)(-5)) // send NewSegment
-
- // new segment packet is always followed by one of these
- struct NewSegmentPacket {
- REFERENCE_TIME tStart;
- REFERENCE_TIME tStop;
- double dRate;
- };
-
- // Remember input stuff
- IPin * const m_pPin;
- IMemInputPin * m_pInputPin;
- BOOL const m_bBatchExact;
- LONG const m_lBatchSize;
-
- CSampleList * m_List;
- HANDLE m_hSem;
- CAMEvent m_evFlushComplete;
- HANDLE m_hThread;
- __field_ecount_opt(m_lBatchSize) IMediaSample ** m_ppSamples;
- __range(0, m_lBatchSize) LONG m_nBatched;
-
- // Wait optimization
- LONG m_lWaiting;
- // Flush synchronization
- BOOL m_bFlushing;
-
- // flushing optimization. some downstream filters have trouble
- // with the queue's flushing optimization. other rely on it
- BOOL m_bFlushed;
- bool m_bFlushingOpt;
-
- // Terminate now
- BOOL m_bTerminate;
-
- // Send anyway flag for batching
- BOOL m_bSendAnyway;
-
- // Deferred 'return code'
- HRESULT volatile m_hr;
-
- // an event that can be fired after every deliver
- HANDLE m_hEventPop;
-};
-
diff --git a/dll/src/baseclasses/perflog.cpp b/dll/src/baseclasses/perflog.cpp
deleted file mode 100644
index e642538..0000000
--- a/dll/src/baseclasses/perflog.cpp
+++ /dev/null
@@ -1,347 +0,0 @@
-//------------------------------------------------------------------------------
-// File: perflog.cpp
-//
-// Desc: Macros for DirectShow performance logging.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-#pragma warning (disable:4201)
-
-#include <streams.h>
-#include <windows.h>
-#include <tchar.h>
-#include <winperf.h>
-#include <wmistr.h>
-#include <evntrace.h>
-#include <strsafe.h>
-#include "perflog.h"
-
-//
-// Local function prototypes.
-//
-
-ULONG
-WINAPI
-PerflogCallback (
- WMIDPREQUESTCODE RequestCode,
- __in PVOID Context,
- __out ULONG* BufferSize,
- __in PVOID Buffer
- );
-
-//
-// Event tracing function pointers.
-// We have to do this to run on down-level platforms.
-//
-
-#ifdef UNICODE
-
-ULONG
-(__stdcall * _RegisterTraceGuids) (
- __in IN WMIDPREQUEST RequestAddress,
- __in IN PVOID RequestContext,
- IN LPCGUID ControlGuid,
- IN ULONG GuidCount,
- __in IN PTRACE_GUID_REGISTRATION TraceGuidReg,
- IN LPCWSTR MofImagePath,
- IN LPCWSTR MofResourceName,
- OUT PTRACEHANDLE RegistrationHandle
- );
-
-#define REGISTERTRACEGUIDS_NAME "RegisterTraceGuidsW"
-
-#else
-
-ULONG
-(__stdcall * _RegisterTraceGuids) (
- __in IN WMIDPREQUEST RequestAddress,
- __in IN PVOID RequestContext,
- IN LPCGUID ControlGuid,
- IN ULONG GuidCount,
- __in IN PTRACE_GUID_REGISTRATION TraceGuidReg,
- IN LPCSTR MofImagePath,
- IN LPCSTR MofResourceName,
- __out OUT PTRACEHANDLE RegistrationHandle
- );
-
-#define REGISTERTRACEGUIDS_NAME "RegisterTraceGuidsA"
-
-#endif
-
-ULONG
-(__stdcall * _UnregisterTraceGuids) (
- TRACEHANDLE RegistrationHandle
- );
-
-TRACEHANDLE
-(__stdcall * _GetTraceLoggerHandle) (
- __in PVOID Buffer
- );
-
-UCHAR
-(__stdcall * _GetTraceEnableLevel) (
- TRACEHANDLE TraceHandle
- );
-
-ULONG
-(__stdcall * _GetTraceEnableFlags) (
- TRACEHANDLE TraceHandle
- );
-
-ULONG
-(__stdcall * _TraceEvent) (
- TRACEHANDLE TraceHandle,
- __in PEVENT_TRACE_HEADER EventTrace
- );
-
-HINSTANCE _Advapi32;
-
-//
-// Global variables.
-//
-
-BOOL EventTracingAvailable=FALSE;
-ULONG PerflogEnableFlags;
-UCHAR PerflogEnableLevel;
-ULONG PerflogModuleLevel = 0;
-void (*OnStateChanged)(void);
-TRACEHANDLE PerflogTraceHandle=NULL;
-TRACEHANDLE PerflogRegHandle;
-
-// The Win32 wsprintf() function writes a maximum of 1024 characters to it's output buffer.
-// See the documentation for wsprintf()'s lpOut parameter for more information.
-const INT iDEBUGINFO = 1024; // Used to format strings
-
-//
-// This routine initializes performance logging.
-// It should be called from DllMain().
-//
-
-
-VOID
-PerflogReadModuleLevel(
- HINSTANCE hInstance
- )
-{
- LONG lReturn; // Create key return value
- TCHAR szInfo[iDEBUGINFO]; // Constructs key names
- TCHAR szFullName[iDEBUGINFO]; // Load the full path and module name
- HKEY hModuleKey; // Module key handle
- LPTSTR pName; // Searches from the end for a backslash
- DWORD dwKeySize, dwKeyType, dwKeyValue;
-
- DWORD dwSize = GetModuleFileName(
- (hInstance ? hInstance : GetModuleHandle( NULL )),
- szFullName,
- iDEBUGINFO );
-
- if (0 == dwSize || iDEBUGINFO == dwSize) {
- return;
- }
-
- pName = _tcsrchr(szFullName,'\\');
- if (pName == NULL) {
- pName = szFullName;
- } else {
- pName++;
- }
-
- /* Construct the base key name */
- (void)StringCchPrintf(szInfo,NUMELMS(szInfo),TEXT("SOFTWARE\\Debug\\%s"),pName);
-
- /* Open the key for this module */
- lReturn =
- RegOpenKeyEx(
- HKEY_LOCAL_MACHINE, // Handle of an open key
- szInfo, // Address of subkey name
- (DWORD) 0, // Reserved value
- KEY_QUERY_VALUE, // Desired security access
- &hModuleKey ); // Opened handle buffer
-
- if (lReturn != ERROR_SUCCESS) {
- return;
- }
-
- dwKeySize = sizeof(DWORD);
- lReturn = RegQueryValueEx(
- hModuleKey, // Handle to an open key
- TEXT("PERFLOG"),
- NULL, // Reserved field
- &dwKeyType, // Returns the field type
- (LPBYTE) &dwKeyValue, // Returns the field's value
- &dwKeySize ); // Number of bytes transferred
-
- if ((lReturn == ERROR_SUCCESS) && (dwKeyType == REG_DWORD))
- {
- PerflogModuleLevel = dwKeyValue;
- }
-
- RegCloseKey(hModuleKey);
-}
-
-BOOL PerflogInitIfEnabled(
- IN HINSTANCE hInstance,
- __in IN PPERFLOG_LOGGING_PARAMS LogParams
- )
-{
- PerflogReadModuleLevel( hInstance );
- if (PerflogModuleLevel)
- {
- return PerflogInitialize( LogParams );
- }
- else
- {
- return FALSE;
- }
-}
-
-BOOL
-PerflogInitialize (
- __in IN PPERFLOG_LOGGING_PARAMS LogParams
- )
-{
- ULONG status;
-
- //
- // If we're running on a recent-enough platform, this will get
- // pointers to the event tracing routines.
- //
-
- _Advapi32 = GetModuleHandle (_T("ADVAPI32.DLL"));
- if (_Advapi32 == NULL) {
- return FALSE;
- }
-
- *((FARPROC*) &_RegisterTraceGuids) = GetProcAddress (_Advapi32, REGISTERTRACEGUIDS_NAME);
- *((FARPROC*) &_UnregisterTraceGuids) = GetProcAddress (_Advapi32, "UnregisterTraceGuids");
- *((FARPROC*) &_GetTraceLoggerHandle) = GetProcAddress (_Advapi32, "GetTraceLoggerHandle");
- *((FARPROC*) &_GetTraceEnableLevel) = GetProcAddress (_Advapi32, "GetTraceEnableLevel");
- *((FARPROC*) &_GetTraceEnableFlags) = GetProcAddress (_Advapi32, "GetTraceEnableFlags");
- *((FARPROC*) &_TraceEvent) = GetProcAddress (_Advapi32, "TraceEvent");
-
- if (_RegisterTraceGuids == NULL ||
- _UnregisterTraceGuids == NULL ||
- _GetTraceEnableLevel == NULL ||
- _GetTraceEnableFlags == NULL ||
- _TraceEvent == NULL) {
-
- return FALSE;
- }
-
- EventTracingAvailable = TRUE;
-
- OnStateChanged = LogParams->OnStateChanged;
-
- //
- // Register our GUIDs.
- //
-
- status = _RegisterTraceGuids (PerflogCallback,
- LogParams,
- &LogParams->ControlGuid,
- LogParams->NumberOfTraceGuids,
- LogParams->TraceGuids,
- NULL,
- NULL,
- &PerflogRegHandle);
-
- return (status == ERROR_SUCCESS);
-}
-
-//
-// This routine shuts down performance logging.
-//
-
-VOID
-PerflogShutdown (
- VOID
- )
-{
- if (!EventTracingAvailable) {
- return;
- }
-
- _UnregisterTraceGuids (PerflogRegHandle);
- PerflogRegHandle = NULL;
- PerflogTraceHandle = NULL;
-}
-
-//
-// Event tracing callback routine.
-// It's called when controllers call event tracing control functions.
-//
-
-ULONG
-WINAPI
-PerflogCallback (
- WMIDPREQUESTCODE RequestCode,
- __in PVOID Context,
- __out ULONG* BufferSize,
- __in PVOID Buffer
- )
-{
- ULONG status;
-
- UNREFERENCED_PARAMETER (Context);
-
- ASSERT (EventTracingAvailable);
-
- status = ERROR_SUCCESS;
-
- switch (RequestCode) {
-
- case WMI_ENABLE_EVENTS:
- PerflogTraceHandle = _GetTraceLoggerHandle (Buffer);
- PerflogEnableFlags = _GetTraceEnableFlags (PerflogTraceHandle);
- PerflogEnableLevel = _GetTraceEnableLevel (PerflogTraceHandle);
- break;
-
- case WMI_DISABLE_EVENTS:
- PerflogTraceHandle = NULL;
- PerflogEnableFlags = 0;
- PerflogEnableLevel = 0;
- break;
-
- default:
- status = ERROR_INVALID_PARAMETER;
- }
-
- if (OnStateChanged != NULL) {
- OnStateChanged();
- }
-
- *BufferSize = 0;
- return status;
-}
-
-//
-// Logging routine.
-//
-
-VOID
-PerflogTraceEvent (
- __in PEVENT_TRACE_HEADER Event
- )
-{
- if (!EventTracingAvailable) {
- return;
- }
-
- _TraceEvent (PerflogTraceHandle, Event);
-}
-
-VOID
-PerflogTraceEventLevel(
- ULONG Level,
- __in PEVENT_TRACE_HEADER Event
- )
-{
- if ((!EventTracingAvailable) || (Level <= PerflogModuleLevel)) {
- return;
- }
-
- _TraceEvent (PerflogTraceHandle, Event);
-}
-
-
diff --git a/dll/src/baseclasses/perflog.h b/dll/src/baseclasses/perflog.h
deleted file mode 100644
index 503a130..0000000
--- a/dll/src/baseclasses/perflog.h
+++ /dev/null
@@ -1,56 +0,0 @@
-//------------------------------------------------------------------------------
-// File: perflog.h
-//
-// Desc: Performance logging framework.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-typedef struct _PERFLOG_LOGGING_PARAMS {
- GUID ControlGuid;
- void (*OnStateChanged)(void);
- ULONG NumberOfTraceGuids;
- TRACE_GUID_REGISTRATION TraceGuids[ANYSIZE_ARRAY];
-} PERFLOG_LOGGING_PARAMS, *PPERFLOG_LOGGING_PARAMS;
-
-BOOL
-PerflogInitIfEnabled(
- IN HINSTANCE hInstance,
- __in PPERFLOG_LOGGING_PARAMS LogParams
- );
-
-BOOL
-PerflogInitialize (
- __in PPERFLOG_LOGGING_PARAMS LogParams
- );
-
-VOID
-PerflogShutdown (
- VOID
- );
-
-VOID
-PerflogTraceEvent (
- __in PEVENT_TRACE_HEADER Event
- );
-
-extern ULONG PerflogEnableFlags;
-extern UCHAR PerflogEnableLevel;
-extern ULONG PerflogModuleLevel;
-extern TRACEHANDLE PerflogTraceHandle;
-extern TRACEHANDLE PerflogRegHandle;
-
-#define PerflogTracingEnabled() (PerflogTraceHandle != 0)
-
-#define PerflogEvent( _x_ ) PerflogTraceEventLevel _x_
-
-VOID
-PerflogTraceEventLevel(
- ULONG Level,
- __in PEVENT_TRACE_HEADER Event
- );
-
-VOID
-PerflogTraceEvent (
- __in PEVENT_TRACE_HEADER Event
- );
diff --git a/dll/src/baseclasses/perfstruct.h b/dll/src/baseclasses/perfstruct.h
deleted file mode 100644
index 9c67b73..0000000
--- a/dll/src/baseclasses/perfstruct.h
+++ /dev/null
@@ -1,194 +0,0 @@
-//------------------------------------------------------------------------------
-// File: PerfStruct.h
-//
-// Desc: Structures for DirectShow performance logging.
-//
-// Copyright (c) 2000-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-#ifndef _PERFSTRUCT_H_
-#define _PERFSTRUCT_H_
-
-#include <wmistr.h>
-#include <evntrace.h>
-
-// {28CF047A-2437-4b24-B653-B9446A419A69}
-DEFINE_GUID(GUID_DSHOW_CTL,
-0x28cf047a, 0x2437, 0x4b24, 0xb6, 0x53, 0xb9, 0x44, 0x6a, 0x41, 0x9a, 0x69);
-
-// {D0DA7AD6-AE80-4de5-AAFC-C126711E7593}
-DEFINE_GUID(GUID_VIDEOREND,
-0xd0da7ad6, 0xae80, 0x4de5, 0xaa, 0xfc, 0xc1, 0x26, 0x71, 0x1e, 0x75, 0x93);
-
-// {DC70AC3E-93E5-48db-88AB-E42064EC276A}
-DEFINE_GUID(GUID_DSOUNDGLITCH,
-0xdc70ac3e, 0x93e5, 0x48db, 0x88, 0xab, 0xe4, 0x20, 0x64, 0xec, 0x27, 0x6a);
-
-// {3d7e7d93-2fc8-4a07-a719-e0922ff2899}
-DEFINE_GUID(GUID_STREAMTRACE,
-0x3d7e7d93, 0x2fc8, 0x4a07, 0xa7, 0x19, 0xe0, 0x92, 0x2f, 0xf2, 0x89, 0x9e);
-
-// AZFIX: the following GUIDs aren't useful right now.
-
-// {3C33F7F5-EE54-493c-BA25-1656539C05AC}
-DEFINE_GUID(GUID_GETTIME,
-0x3c33f7f5, 0xee54, 0x493c, 0xba, 0x25, 0x16, 0x56, 0x53, 0x9c, 0x5, 0xac);
-
-// {CC44B44D-8169-4952-9E4A-A4E13295E492}
-DEFINE_GUID(GUID_AUDIOREND,
-0xcc44b44d, 0x8169, 0x4952, 0x9e, 0x4a, 0xa4, 0xe1, 0x32, 0x95, 0xe4, 0x92);
-
-// {775D19BF-4D8B-4de6-8DC9-66BAC7B310A2}
-DEFINE_GUID(GUID_FRAMEDROP,
-0x775d19bf, 0x4d8b, 0x4de6, 0x8d, 0xc9, 0x66, 0xba, 0xc7, 0xb3, 0x10, 0xa2);
-
-// {56D29065-EFBE-42dc-8C29-E325DC9C27D5}
-DEFINE_GUID(GUID_AUDIOBREAK,
-0x56d29065, 0xefbe, 0x42dc, 0x8c, 0x29, 0xe3, 0x25, 0xdc, 0x9c, 0x27, 0xd5);
-
-// {E1E6EA87-95A8-497e-BFBA-0295AEBCC707}
-DEFINE_GUID(GUID_AUDIORECV,
-0xe1e6ea87, 0x95a8, 0x497e, 0xbf, 0xba, 0x2, 0x95, 0xae, 0xbc, 0xc7, 0x7);
-
-// {10F7768A-B1E7-4242-AD90-A2D44683D9F0}
-DEFINE_GUID(GUID_AUDIOSLAVE,
-0x10f7768a, 0xb1e7, 0x4242, 0xad, 0x90, 0xa2, 0xd4, 0x46, 0x83, 0xd9, 0xf0);
-
-// {8983803D-691A-49bc-8FF6-962A39C0198F}
-DEFINE_GUID(GUID_AUDIOADDBREAK,
-0x8983803d, 0x691a, 0x49bc, 0x8f, 0xf6, 0x96, 0x2a, 0x39, 0xc0, 0x19, 0x8f);
-
-#define GLITCHTYPE_DSOUNDFIRSTGOOD 0
-#define GLITCHTYPE_DSOUNDFIRSTBAD 1
-
-typedef struct PERFINFO_DSHOW_AUDIOGLITCH {
- ULONGLONG cycleCounter;
- DWORD glitchType;
- LONGLONG sampleTime;
- LONGLONG previousTime;
- ULONG_PTR instanceId;
-} PERFINFO_DSHOW_AUDIOGLITCH, *PPERFINFO_DSHOW_AUDIOGLITCH;
-
-typedef struct PERFINFO_WMI_AUDIOGLITCH {
- EVENT_TRACE_HEADER header;
- PERFINFO_DSHOW_AUDIOGLITCH data;
-} PERFINFO_WMI_AUDIO_GLITCH, *PPERFINFO_WMI_AUDIOGLITCH;
-
-typedef struct PERFINFO_DSHOW_GETTIME {
- ULONGLONG cycleCounter;
- ULONGLONG dshowClock;
-} PERFINFO_DSHOW_GETTIME, *PPERFINFO_DSHOW_GETTIME;
-
-typedef struct PERFINFO_WMI_GETTIME {
- EVENT_TRACE_HEADER header;
- PERFINFO_DSHOW_GETTIME data;
-} PERFINFO_WMI_GETTIME, *PPERFINFO_WMI_GETTIME;
-
-typedef struct PERFINFO_DSHOW_AVREND {
- ULONGLONG cycleCounter;
- ULONGLONG dshowClock;
- ULONGLONG sampleTime;
-} PERFINFO_DSHOW_AVREND, *PPERFINFO_DSHOW_AVREND;
-
-typedef struct PERFINFO_WMI_AVREND {
- EVENT_TRACE_HEADER header;
- PERFINFO_DSHOW_AVREND data;
-} PERFINFO_WMI_AVREND, *PPERFINFO_WMI_AVREND;
-
-typedef struct PERFINFO_DSHOW_AUDIOBREAK {
- ULONGLONG cycleCounter;
- ULONGLONG dshowClock;
- ULONGLONG sampleTime;
- ULONGLONG sampleDuration;
-} PERFINFO_DSHOW_AUDIOBREAK, *PPERFINFO_DSHOW_AUDIOBREAK;
-
-typedef struct PERFINFO_WMI_AUDIOBREAK {
- EVENT_TRACE_HEADER header;
- PERFINFO_DSHOW_AUDIOBREAK data;
-} PERFINFO_WMI_AUDIOBREAK, *PPERFINFO_WMI_AUDIOBREAK;
-
-typedef struct PERFINFO_DSHOW_FRAMEDROP {
- ULONGLONG cycleCounter;
- ULONGLONG dshowClock;
- ULONGLONG frameTime;
-} PERFINFO_DSHOW_FRAMEDROP, *PPERFINFO_DSHOW_FRAMEDROP;
-
-typedef struct PERFINFO_WMI_FRAMEDROP {
- EVENT_TRACE_HEADER header;
- PERFINFO_DSHOW_FRAMEDROP data;
-} PERFINFO_WMI_FRAMEDROP, *PPERFINFO_WMI_FRAMEDROP;
-
-#define PERFINFO_STREAMTRACE_MPEG2DEMUX_PTS_TRANSLATION 1
-#define PERFINFO_STREAMTRACE_MPEG2DEMUX_SAMPLE_RECEIVED 2
-#define PERFINFO_STREAMTRACE_VMR_BEGIN_ADVISE 3
-#define PERFINFO_STREAMTRACE_VMR_END_ADVISE 4
-#define PERFINFO_STREAMTRACE_VMR_RECEIVE 5
-#define PERFINFO_STREAMTRACE_VMR_BEGIN_DEINTERLACE 6
-#define PERFINFO_STREAMTRACE_VMR_END_DEINTERLACE 7
-#define PERFINFO_STREAMTRACE_VMR_BEGIN_DECODE 8
-#define PERFINFO_STREAMTRACE_VMR_END_DECODE 9
-#define PERFINFO_STREAMTRACE_VMR_DROPPED_FRAME 10
-#define PERFINFO_STREAMTRACE_ENCDEC_DTFILTERINPUT 11
-#define PERFINFO_STREAMTRACE_ENCDEC_DTFILTEROUTPUT 12
-#define PERFINFO_STREAMTRACE_ENCDEC_ETFILTERINPUT 13
-#define PERFINFO_STREAMTRACE_ENCDEC_ETFILTEROUTPUT 14
-#define PERFINFO_STREAMTRACE_ENCDEC_XDSCODECINPUT 15
-#define PERFINFO_STREAMTRACE_SBE_DVRANALYSISINPUT_RECEIVE 16
-#define PERFINFO_STREAMTRACE_SBE_DVRANALYSISINPUT_DELIVER 17
-#define PERFINFO_STREAMTRACE_SBE_DVRINPUTPIN_RECEIVE 18
-#define PERFINFO_STREAMTRACE_SBE_DVROUTPUTPIN_RECEIVE 19
-#define PERFINFO_STREAMTRACE_VMR_RENDER_TIME 20
-
-typedef struct _PERFINFO_DSHOW_STREAMTRACE {
- ULONG id;
- ULONG reserved;
- ULONGLONG dshowClock;
- ULONGLONG data[ 4 ];
-} PERFINFO_DSHOW_STREAMTRACE, *PPERFINFO_DSHOW_STREAMTRACE;
-
-typedef struct _PERFINFO_WMI_STREAMTRACE {
- EVENT_TRACE_HEADER header;
- PERFINFO_DSHOW_STREAMTRACE data;
-} PERFINFO_WMI_STREAMTRACE, *PPERFINFO_WMI_STREAMTRACE;
-
-
-typedef struct PERFINFO_DSHOW_AUDIORECV {
- LONGLONG streamTime ;
- LONGLONG sampleStart ;
- LONGLONG sampleStop ;
- LONGLONG hwduration ;
- BOOL discontinuity ;
-} PERFINFO_DSHOW_AUDIORECV, *PPERFINFO_DSHOW_AUDIORECV;
-
-typedef struct PERFINFO_WMI_AUDIORECV {
- EVENT_TRACE_HEADER header;
- PERFINFO_DSHOW_AUDIORECV data;
-} PERFINFO_WMI_AUDIORECV, *PPERFINFO_WMI_AUDIORECV;
-
-typedef struct PERFINFO_DSHOW_AUDIOSLAVE {
- LONGLONG masterClock ;
- LONGLONG slaveClock ;
- LONGLONG errorAccum ;
- LONGLONG lastHighErrorSeen ;
- LONGLONG lastLowErrorSeen ;
-} PERFINFO_DSHOW_AUDIOSLAVE, *PPERFINFO_DSHOW_AUDIOSLAVE;
-
-typedef struct PERFINFO_WMI_AUDIOSLAVE {
- EVENT_TRACE_HEADER header;
- PERFINFO_DSHOW_AUDIOSLAVE data;
-} PERFINFO_WMI_AUDIOSLAVE, *PPERFINFO_WMI_AUDIOSLAVE;
-
-typedef struct PERFINFO_DSHOW_AUDIOADDBREAK {
- DWORD iterNextWrite ;
- DWORD offsetNextWrite ;
- DWORD iterWrite ;
- DWORD offsetWrite ;
-} PERFINFO_DSHOW_AUDIOADDBREAK, *PPERFINFO_DSHOW_AUDIOADDBREAK;
-
-typedef struct PERFINFO_WMI_AUDIOADDBREAK {
- EVENT_TRACE_HEADER header;
- PERFINFO_DSHOW_AUDIOADDBREAK data;
-} PERFINFO_WMI_AUDIOADDBREAK, *PPERFINFO_WMI_AUDIOADDBREAK;
-
-#endif // _PREFSTRUCT_H_
diff --git a/dll/src/baseclasses/pstream.cpp b/dll/src/baseclasses/pstream.cpp
deleted file mode 100644
index d20171f..0000000
--- a/dll/src/baseclasses/pstream.cpp
+++ /dev/null
@@ -1,197 +0,0 @@
-//------------------------------------------------------------------------------
-// File: PStream.cpp
-//
-// Desc: DirectShow base classes.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-#include <streams.h>
-#include <strsafe.h>
-
-#ifdef PERF
-#include <measure.h>
-#endif
-// #include "pstream.h" in streams.h
-
-//
-// Constructor
-//
-CPersistStream::CPersistStream(IUnknown *punk, __inout HRESULT *phr)
- : mPS_fDirty(FALSE)
-{
- mPS_dwFileVersion = GetSoftwareVersion();
-}
-
-
-//
-// Destructor
-//
-CPersistStream::~CPersistStream() {
- // Nothing to do
-}
-
-#if 0
-SAMPLE CODE TO COPY - not active at the moment
-
-//
-// NonDelegatingQueryInterface
-//
-// This object supports IPersist & IPersistStream
-STDMETHODIMP CPersistStream::NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv)
-{
- if (riid == IID_IPersist) {
- return GetInterface((IPersist *) this, ppv); // ???
- }
- else if (riid == IID_IPersistStream) {
- return GetInterface((IPersistStream *) this, ppv);
- }
- else {
- return CUnknown::NonDelegatingQueryInterface(riid, ppv);
- }
-}
-#endif
-
-
-//
-// WriteToStream
-//
-// Writes to the stream (default action is to write nothing)
-HRESULT CPersistStream::WriteToStream(IStream *pStream)
-{
- // You can override this to do things like
- // hr = pStream->Write(MyStructure, sizeof(MyStructure), NULL);
-
- return NOERROR;
-}
-
-
-
-HRESULT CPersistStream::ReadFromStream(IStream * pStream)
-{
- // You can override this to do things like
- // hr = pStream->Read(MyStructure, sizeof(MyStructure), NULL);
-
- return NOERROR;
-}
-
-
-//
-// Load
-//
-// Load all the data from the given stream
-STDMETHODIMP CPersistStream::Load(LPSTREAM pStm)
-{
- HRESULT hr;
- // Load the version number then the data
- mPS_dwFileVersion = ReadInt(pStm, hr);
- if (FAILED(hr)) {
- return hr;
- }
-
- return ReadFromStream(pStm);
-} // Load
-
-
-
-//
-// Save
-//
-// Save the contents of this Stream.
-STDMETHODIMP CPersistStream::Save(LPSTREAM pStm, BOOL fClearDirty)
-{
-
- HRESULT hr = WriteInt(pStm, GetSoftwareVersion());
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = WriteToStream(pStm);
- if (FAILED(hr)) {
- return hr;
- }
-
- mPS_fDirty = !fClearDirty;
-
- return hr;
-} // Save
-
-
-// WriteInt
-//
-// Writes an integer to an IStream as 11 UNICODE characters followed by one space.
-// You could use this for shorts or unsigneds or anything (up to 32 bits)
-// where the value isn't actually truncated by squeezing it into 32 bits.
-// Values such as (unsigned) 0x80000000 would come out as -2147483648
-// but would then load as 0x80000000 through ReadInt. Cast as you please.
-
-STDAPI WriteInt(IStream *pIStream, int n)
-{
- WCHAR Buff[13]; // Allows for trailing null that we don't write
- (void)StringCchPrintfW(Buff, NUMELMS(Buff),L"%011d ",n);
- return pIStream->Write(&(Buff[0]), 12*sizeof(WCHAR), NULL);
-} // WriteInt
-
-
-// ReadInt
-//
-// Reads an integer from an IStream.
-// Read as 4 bytes. You could use this for shorts or unsigneds or anything
-// where the value isn't actually truncated by squeezing it into 32 bits
-// Striped down subset of what sscanf can do (without dragging in the C runtime)
-
-STDAPI_(int) ReadInt(IStream *pIStream, __out HRESULT &hr)
-{
-
- int Sign = 1;
- unsigned int n = 0; // result wil be n*Sign
- WCHAR wch;
-
- hr = pIStream->Read( &wch, sizeof(wch), NULL);
- if (FAILED(hr)) {
- return 0;
- }
-
- if (wch==L'-'){
- Sign = -1;
- hr = pIStream->Read( &wch, sizeof(wch), NULL);
- if (FAILED(hr)) {
- return 0;
- }
- }
-
- for( ; ; ) {
- if (wch>=L'0' && wch<=L'9') {
- n = 10*n+(int)(wch-L'0');
- } else if ( wch == L' '
- || wch == L'\t'
- || wch == L'\r'
- || wch == L'\n'
- || wch == L'\0'
- ) {
- break;
- } else {
- hr = VFW_E_INVALID_FILE_FORMAT;
- return 0;
- }
-
- hr = pIStream->Read( &wch, sizeof(wch), NULL);
- if (FAILED(hr)) {
- return 0;
- }
- }
-
- if (n==0x80000000 && Sign==-1) {
- // This is the negative number that has no positive version!
- return (int)n;
- }
- else return (int)n * Sign;
-} // ReadInt
-
-
-// The microsoft C/C++ compile generates level 4 warnings to the effect that
-// a particular inline function (from some base class) was not needed.
-// This line gets rid of hundreds of such unwanted messages and makes
-// -W4 compilation feasible:
-#pragma warning(disable: 4514)
diff --git a/dll/src/baseclasses/pstream.h b/dll/src/baseclasses/pstream.h
deleted file mode 100644
index 04b6af6..0000000
--- a/dll/src/baseclasses/pstream.h
+++ /dev/null
@@ -1,114 +0,0 @@
-//------------------------------------------------------------------------------
-// File: PStream.h
-//
-// Desc: DirectShow base classes - defines a class for persistent properties
-// of filters.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-#ifndef __PSTREAM__
-#define __PSTREAM__
-
-// Base class for persistent properties of filters
-// (i.e. filter properties in saved graphs)
-
-// The simplest way to use this is:
-// 1. Arrange for your filter to inherit this class
-// 2. Implement in your class WriteToStream and ReadFromStream
-// These will override the "do nothing" functions here.
-// 3. Change your NonDelegatingQueryInterface to handle IPersistStream
-// 4. Implement SizeMax to return the number of bytes of data you save.
-// If you save UNICODE data, don't forget a char is 2 bytes.
-// 5. Whenever your data changes, call SetDirty()
-//
-// At some point you may decide to alter, or extend the format of your data.
-// At that point you will wish that you had a version number in all the old
-// saved graphs, so that you can tell, when you read them, whether they
-// represent the old or new form. To assist you in this, this class
-// writes and reads a version number.
-// When it writes, it calls GetSoftwareVersion() to enquire what version
-// of the software we have at the moment. (In effect this is a version number
-// of the data layout in the file). It writes this as the first thing in the data.
-// If you want to change the version, implement (override) GetSoftwareVersion().
-// It reads this from the file into mPS_dwFileVersion before calling ReadFromStream,
-// so in ReadFromStream you can check mPS_dwFileVersion to see if you are reading
-// an old version file.
-// Normally you should accept files whose version is no newer than the software
-// version that's reading them.
-
-
-// CPersistStream
-//
-// Implements IPersistStream.
-// See 'OLE Programmers Reference (Vol 1):Structured Storage Overview' for
-// more implementation information.
-class CPersistStream : public IPersistStream {
- private:
-
- // Internal state:
-
- protected:
- DWORD mPS_dwFileVersion; // version number of file (being read)
- BOOL mPS_fDirty;
-
- public:
-
- // IPersistStream methods
-
- STDMETHODIMP IsDirty()
- {return (mPS_fDirty ? S_OK : S_FALSE);} // note FALSE means clean
- STDMETHODIMP Load(LPSTREAM pStm);
- STDMETHODIMP Save(LPSTREAM pStm, BOOL fClearDirty);
- STDMETHODIMP GetSizeMax(__out ULARGE_INTEGER * pcbSize)
- // Allow 24 bytes for version.
- { pcbSize->QuadPart = 12*sizeof(WCHAR)+SizeMax(); return NOERROR; }
-
- // implementation
-
- CPersistStream(IUnknown *punk, __inout HRESULT *phr);
- ~CPersistStream();
-
- HRESULT SetDirty(BOOL fDirty)
- { mPS_fDirty = fDirty; return NOERROR;}
-
-
- // override to reveal IPersist & IPersistStream
- // STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
-
- // --- IPersist ---
-
- // You must override this to provide your own class id
- STDMETHODIMP GetClassID(__out CLSID *pClsid) PURE;
-
- // overrideable if you want
- // file version number. Override it if you ever change format
- virtual DWORD GetSoftwareVersion(void) { return 0; }
-
-
- //=========================================================================
- // OVERRIDE THESE to read and write your data
- // OVERRIDE THESE to read and write your data
- // OVERRIDE THESE to read and write your data
-
- virtual int SizeMax() {return 0;}
- virtual HRESULT WriteToStream(IStream *pStream);
- virtual HRESULT ReadFromStream(IStream *pStream);
- //=========================================================================
-
- private:
-
-};
-
-
-// --- Useful helpers ---
-
-
-// Writes an int to an IStream as UNICODE.
-STDAPI WriteInt(IStream *pIStream, int n);
-
-// inverse of WriteInt
-STDAPI_(int) ReadInt(IStream *pIStream, __out HRESULT &hr);
-
-#endif // __PSTREAM__
diff --git a/dll/src/baseclasses/pullpin.cpp b/dll/src/baseclasses/pullpin.cpp
deleted file mode 100644
index a197ba5..0000000
--- a/dll/src/baseclasses/pullpin.cpp
+++ /dev/null
@@ -1,588 +0,0 @@
-//------------------------------------------------------------------------------
-// File: PullPin.cpp
-//
-// Desc: DirectShow base classes - implements CPullPin class that pulls data
-// from IAsyncReader.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-#include <streams.h>
-#include "pullpin.h"
-
-#ifdef DXMPERF
-#include "dxmperf.h"
-#endif // DXMPERF
-
-
-CPullPin::CPullPin()
- : m_pReader(NULL),
- m_pAlloc(NULL),
- m_State(TM_Exit)
-{
-#ifdef DXMPERF
- PERFLOG_CTOR( L"CPullPin", this );
-#endif // DXMPERF
-
-}
-
-CPullPin::~CPullPin()
-{
- Disconnect();
-
-#ifdef DXMPERF
- PERFLOG_DTOR( L"CPullPin", this );
-#endif // DXMPERF
-
-}
-
-// returns S_OK if successfully connected to an IAsyncReader interface
-// from this object
-// Optional allocator should be proposed as a preferred allocator if
-// necessary
-HRESULT
-CPullPin::Connect(IUnknown* pUnk, IMemAllocator* pAlloc, BOOL bSync)
-{
- CAutoLock lock(&m_AccessLock);
-
- if (m_pReader) {
- return VFW_E_ALREADY_CONNECTED;
- }
-
- HRESULT hr = pUnk->QueryInterface(IID_IAsyncReader, (void**)&m_pReader);
- if (FAILED(hr)) {
-
-#ifdef DXMPERF
- {
- AM_MEDIA_TYPE * pmt = NULL;
- PERFLOG_CONNECT( this, pUnk, hr, pmt );
- }
-#endif // DXMPERF
-
- return(hr);
- }
-
- hr = DecideAllocator(pAlloc, NULL);
- if (FAILED(hr)) {
- Disconnect();
-
-#ifdef DXMPERF
- {
- AM_MEDIA_TYPE * pmt = NULL;
- PERFLOG_CONNECT( this, pUnk, hr, pmt );
- }
-#endif // DXMPERF
-
- return hr;
- }
-
- LONGLONG llTotal, llAvail;
- hr = m_pReader->Length(&llTotal, &llAvail);
- if (FAILED(hr)) {
- Disconnect();
-
-#ifdef DXMPERF
- {
- AM_MEDIA_TYPE * pmt = NULL;
- PERFLOG_CONNECT( this, pUnk, hr, pmt );
- }
-#endif
-
- return hr;
- }
-
- // convert from file position to reference time
- m_tDuration = llTotal * UNITS;
- m_tStop = m_tDuration;
- m_tStart = 0;
-
- m_bSync = bSync;
-
-#ifdef DXMPERF
- {
- AM_MEDIA_TYPE * pmt = NULL;
- PERFLOG_CONNECT( this, pUnk, S_OK, pmt );
- }
-#endif // DXMPERF
-
-
- return S_OK;
-}
-
-// disconnect any connection made in Connect
-HRESULT
-CPullPin::Disconnect()
-{
- CAutoLock lock(&m_AccessLock);
-
- StopThread();
-
-
-#ifdef DXMPERF
- PERFLOG_DISCONNECT( this, m_pReader, S_OK );
-#endif // DXMPERF
-
-
- if (m_pReader) {
- m_pReader->Release();
- m_pReader = NULL;
- }
-
- if (m_pAlloc) {
- m_pAlloc->Release();
- m_pAlloc = NULL;
- }
-
- return S_OK;
-}
-
-// agree an allocator using RequestAllocator - optional
-// props param specifies your requirements (non-zero fields).
-// returns an error code if fail to match requirements.
-// optional IMemAllocator interface is offered as a preferred allocator
-// but no error occurs if it can't be met.
-HRESULT
-CPullPin::DecideAllocator(
- IMemAllocator * pAlloc,
- __inout_opt ALLOCATOR_PROPERTIES * pProps)
-{
- ALLOCATOR_PROPERTIES *pRequest;
- ALLOCATOR_PROPERTIES Request;
- if (pProps == NULL) {
- Request.cBuffers = 3;
- Request.cbBuffer = 64*1024;
- Request.cbAlign = 0;
- Request.cbPrefix = 0;
- pRequest = &Request;
- } else {
- pRequest = pProps;
- }
- HRESULT hr = m_pReader->RequestAllocator(
- pAlloc,
- pRequest,
- &m_pAlloc);
- return hr;
-}
-
-// start pulling data
-HRESULT
-CPullPin::Active(void)
-{
- ASSERT(!ThreadExists());
- return StartThread();
-}
-
-// stop pulling data
-HRESULT
-CPullPin::Inactive(void)
-{
- StopThread();
-
- return S_OK;
-}
-
-HRESULT
-CPullPin::Seek(REFERENCE_TIME tStart, REFERENCE_TIME tStop)
-{
- CAutoLock lock(&m_AccessLock);
-
- ThreadMsg AtStart = m_State;
-
- if (AtStart == TM_Start) {
- BeginFlush();
- PauseThread();
- EndFlush();
- }
-
- m_tStart = tStart;
- m_tStop = tStop;
-
- HRESULT hr = S_OK;
- if (AtStart == TM_Start) {
- hr = StartThread();
- }
-
- return hr;
-}
-
-HRESULT
-CPullPin::Duration(__out REFERENCE_TIME* ptDuration)
-{
- *ptDuration = m_tDuration;
- return S_OK;
-}
-
-
-HRESULT
-CPullPin::StartThread()
-{
- CAutoLock lock(&m_AccessLock);
-
- if (!m_pAlloc || !m_pReader) {
- return E_UNEXPECTED;
- }
-
- HRESULT hr;
- if (!ThreadExists()) {
-
- // commit allocator
- hr = m_pAlloc->Commit();
- if (FAILED(hr)) {
- return hr;
- }
-
- // start thread
- if (!Create()) {
- return E_FAIL;
- }
- }
-
- m_State = TM_Start;
- hr = (HRESULT) CallWorker(m_State);
- return hr;
-}
-
-HRESULT
-CPullPin::PauseThread()
-{
- CAutoLock lock(&m_AccessLock);
-
- if (!ThreadExists()) {
- return E_UNEXPECTED;
- }
-
- // need to flush to ensure the thread is not blocked
- // in WaitForNext
- HRESULT hr = m_pReader->BeginFlush();
- if (FAILED(hr)) {
- return hr;
- }
-
- m_State = TM_Pause;
- hr = CallWorker(TM_Pause);
-
- m_pReader->EndFlush();
- return hr;
-}
-
-HRESULT
-CPullPin::StopThread()
-{
- CAutoLock lock(&m_AccessLock);
-
- if (!ThreadExists()) {
- return S_FALSE;
- }
-
- // need to flush to ensure the thread is not blocked
- // in WaitForNext
- HRESULT hr = m_pReader->BeginFlush();
- if (FAILED(hr)) {
- return hr;
- }
-
- m_State = TM_Exit;
- hr = CallWorker(TM_Exit);
-
- m_pReader->EndFlush();
-
- // wait for thread to completely exit
- Close();
-
- // decommit allocator
- if (m_pAlloc) {
- m_pAlloc->Decommit();
- }
-
- return S_OK;
-}
-
-
-DWORD
-CPullPin::ThreadProc(void)
-{
- while(1) {
- DWORD cmd = GetRequest();
- switch(cmd) {
- case TM_Exit:
- Reply(S_OK);
- return 0;
-
- case TM_Pause:
- // we are paused already
- Reply(S_OK);
- break;
-
- case TM_Start:
- Reply(S_OK);
- Process();
- break;
- }
-
- // at this point, there should be no outstanding requests on the
- // upstream filter.
- // We should force begin/endflush to ensure that this is true.
- // !!!Note that we may currently be inside a BeginFlush/EndFlush pair
- // on another thread, but the premature EndFlush will do no harm now
- // that we are idle.
- m_pReader->BeginFlush();
- CleanupCancelled();
- m_pReader->EndFlush();
- }
-}
-
-HRESULT
-CPullPin::QueueSample(
- __inout REFERENCE_TIME& tCurrent,
- REFERENCE_TIME tAlignStop,
- BOOL bDiscontinuity
- )
-{
- IMediaSample* pSample;
-
- HRESULT hr = m_pAlloc->GetBuffer(&pSample, NULL, NULL, 0);
- if (FAILED(hr)) {
- return hr;
- }
-
- LONGLONG tStopThis = tCurrent + (pSample->GetSize() * UNITS);
- if (tStopThis > tAlignStop) {
- tStopThis = tAlignStop;
- }
- pSample->SetTime(&tCurrent, &tStopThis);
- tCurrent = tStopThis;
-
- pSample->SetDiscontinuity(bDiscontinuity);
-
- hr = m_pReader->Request(
- pSample,
- 0);
- if (FAILED(hr)) {
- pSample->Release();
-
- CleanupCancelled();
- OnError(hr);
- }
- return hr;
-}
-
-HRESULT
-CPullPin::CollectAndDeliver(
- REFERENCE_TIME tStart,
- REFERENCE_TIME tStop)
-{
- IMediaSample* pSample = NULL; // better be sure pSample is set
- DWORD_PTR dwUnused;
- HRESULT hr = m_pReader->WaitForNext(
- INFINITE,
- &pSample,
- &dwUnused);
- if (FAILED(hr)) {
- if (pSample) {
- pSample->Release();
- }
- } else {
- hr = DeliverSample(pSample, tStart, tStop);
- }
- if (FAILED(hr)) {
- CleanupCancelled();
- OnError(hr);
- }
- return hr;
-
-}
-
-HRESULT
-CPullPin::DeliverSample(
- IMediaSample* pSample,
- REFERENCE_TIME tStart,
- REFERENCE_TIME tStop
- )
-{
- // fix up sample if past actual stop (for sector alignment)
- REFERENCE_TIME t1, t2;
- if (S_OK == pSample->GetTime(&t1, &t2)) {
- if (t2 > tStop) {
- t2 = tStop;
- }
-
- // adjust times to be relative to (aligned) start time
- t1 -= tStart;
- t2 -= tStart;
- HRESULT hr = pSample->SetTime(&t1, &t2);
- if (FAILED(hr)) {
- return hr;
- }
- }
-
-#ifdef DXMPERF
- {
- AM_MEDIA_TYPE * pmt = NULL;
- pSample->GetMediaType( &pmt );
- PERFLOG_RECEIVE( L"CPullPin", m_pReader, this, pSample, pmt );
- }
-#endif
-
- HRESULT hr = Receive(pSample);
- pSample->Release();
- return hr;
-}
-
-void
-CPullPin::Process(void)
-{
- // is there anything to do?
- if (m_tStop <= m_tStart) {
- EndOfStream();
- return;
- }
-
- BOOL bDiscontinuity = TRUE;
-
- // if there is more than one sample at the allocator,
- // then try to queue 2 at once in order to overlap.
- // -- get buffer count and required alignment
- ALLOCATOR_PROPERTIES Actual;
- HRESULT hr = m_pAlloc->GetProperties(&Actual);
-
- // align the start position downwards
- REFERENCE_TIME tStart = AlignDown(m_tStart / UNITS, Actual.cbAlign) * UNITS;
- REFERENCE_TIME tCurrent = tStart;
-
- REFERENCE_TIME tStop = m_tStop;
- if (tStop > m_tDuration) {
- tStop = m_tDuration;
- }
-
- // align the stop position - may be past stop, but that
- // doesn't matter
- REFERENCE_TIME tAlignStop = AlignUp(tStop / UNITS, Actual.cbAlign) * UNITS;
-
-
- DWORD dwRequest;
-
- if (!m_bSync) {
-
- // Break out of the loop either if we get to the end or we're asked
- // to do something else
- while (tCurrent < tAlignStop) {
-
- // Break out without calling EndOfStream if we're asked to
- // do something different
- if (CheckRequest(&dwRequest)) {
- return;
- }
-
- // queue a first sample
- if (Actual.cBuffers > 1) {
-
- hr = QueueSample(tCurrent, tAlignStop, TRUE);
- bDiscontinuity = FALSE;
-
- if (FAILED(hr)) {
- return;
- }
- }
-
-
-
- // loop queueing second and waiting for first..
- while (tCurrent < tAlignStop) {
-
- hr = QueueSample(tCurrent, tAlignStop, bDiscontinuity);
- bDiscontinuity = FALSE;
-
- if (FAILED(hr)) {
- return;
- }
-
- hr = CollectAndDeliver(tStart, tStop);
- if (S_OK != hr) {
-
- // stop if error, or if downstream filter said
- // to stop.
- return;
- }
- }
-
- if (Actual.cBuffers > 1) {
- hr = CollectAndDeliver(tStart, tStop);
- if (FAILED(hr)) {
- return;
- }
- }
- }
- } else {
-
- // sync version of above loop
- while (tCurrent < tAlignStop) {
-
- // Break out without calling EndOfStream if we're asked to
- // do something different
- if (CheckRequest(&dwRequest)) {
- return;
- }
-
- IMediaSample* pSample;
-
- hr = m_pAlloc->GetBuffer(&pSample, NULL, NULL, 0);
- if (FAILED(hr)) {
- OnError(hr);
- return;
- }
-
- LONGLONG tStopThis = tCurrent + (pSample->GetSize() * UNITS);
- if (tStopThis > tAlignStop) {
- tStopThis = tAlignStop;
- }
- pSample->SetTime(&tCurrent, &tStopThis);
- tCurrent = tStopThis;
-
- if (bDiscontinuity) {
- pSample->SetDiscontinuity(TRUE);
- bDiscontinuity = FALSE;
- }
-
- hr = m_pReader->SyncReadAligned(pSample);
-
- if (FAILED(hr)) {
- pSample->Release();
- OnError(hr);
- return;
- }
-
- hr = DeliverSample(pSample, tStart, tStop);
- if (hr != S_OK) {
- if (FAILED(hr)) {
- OnError(hr);
- }
- return;
- }
- }
- }
-
- EndOfStream();
-}
-
-// after a flush, cancelled i/o will be waiting for collection
-// and release
-void
-CPullPin::CleanupCancelled(void)
-{
- while (1) {
- IMediaSample * pSample;
- DWORD_PTR dwUnused;
-
- HRESULT hr = m_pReader->WaitForNext(
- 0, // no wait
- &pSample,
- &dwUnused);
- if(pSample) {
- pSample->Release();
- } else {
- // no more samples
- return;
- }
- }
-}
diff --git a/dll/src/baseclasses/pullpin.h b/dll/src/baseclasses/pullpin.h
deleted file mode 100644
index 03ad40e..0000000
--- a/dll/src/baseclasses/pullpin.h
+++ /dev/null
@@ -1,152 +0,0 @@
-//------------------------------------------------------------------------------
-// File: PullPin.h
-//
-// Desc: DirectShow base classes - defines CPullPin class.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-#ifndef __PULLPIN_H__
-#define __PULLPIN_H__
-
-//
-// CPullPin
-//
-// object supporting pulling data from an IAsyncReader interface.
-// Given a start/stop position, calls a pure Receive method with each
-// IMediaSample received.
-//
-// This is essentially for use in a MemInputPin when it finds itself
-// connected to an IAsyncReader pin instead of a pushing pin.
-//
-
-class CPullPin : public CAMThread
-{
- IAsyncReader* m_pReader;
- REFERENCE_TIME m_tStart;
- REFERENCE_TIME m_tStop;
- REFERENCE_TIME m_tDuration;
- BOOL m_bSync;
-
- enum ThreadMsg {
- TM_Pause, // stop pulling and wait for next message
- TM_Start, // start pulling
- TM_Exit, // stop and exit
- };
-
- ThreadMsg m_State;
-
- // override pure thread proc from CAMThread
- DWORD ThreadProc(void);
-
- // running pull method (check m_bSync)
- void Process(void);
-
- // clean up any cancelled i/o after a flush
- void CleanupCancelled(void);
-
- // suspend thread from pulling, eg during seek
- HRESULT PauseThread();
-
- // start thread pulling - create thread if necy
- HRESULT StartThread();
-
- // stop and close thread
- HRESULT StopThread();
-
- // called from ProcessAsync to queue and collect requests
- HRESULT QueueSample(
- __inout REFERENCE_TIME& tCurrent,
- REFERENCE_TIME tAlignStop,
- BOOL bDiscontinuity);
-
- HRESULT CollectAndDeliver(
- REFERENCE_TIME tStart,
- REFERENCE_TIME tStop);
-
- HRESULT DeliverSample(
- IMediaSample* pSample,
- REFERENCE_TIME tStart,
- REFERENCE_TIME tStop);
-
-protected:
- IMemAllocator * m_pAlloc;
-
-public:
- CPullPin();
- virtual ~CPullPin();
-
- // returns S_OK if successfully connected to an IAsyncReader interface
- // from this object
- // Optional allocator should be proposed as a preferred allocator if
- // necessary
- // bSync is TRUE if we are to use sync reads instead of the
- // async methods.
- HRESULT Connect(IUnknown* pUnk, IMemAllocator* pAlloc, BOOL bSync);
-
- // disconnect any connection made in Connect
- HRESULT Disconnect();
-
- // agree an allocator using RequestAllocator - optional
- // props param specifies your requirements (non-zero fields).
- // returns an error code if fail to match requirements.
- // optional IMemAllocator interface is offered as a preferred allocator
- // but no error occurs if it can't be met.
- virtual HRESULT DecideAllocator(
- IMemAllocator* pAlloc,
- __inout_opt ALLOCATOR_PROPERTIES * pProps);
-
- // set start and stop position. if active, will start immediately at
- // the new position. Default is 0 to duration
- HRESULT Seek(REFERENCE_TIME tStart, REFERENCE_TIME tStop);
-
- // return the total duration
- HRESULT Duration(__out REFERENCE_TIME* ptDuration);
-
- // start pulling data
- HRESULT Active(void);
-
- // stop pulling data
- HRESULT Inactive(void);
-
- // helper functions
- LONGLONG AlignDown(LONGLONG ll, LONG lAlign) {
- // aligning downwards is just truncation
- return ll & ~(lAlign-1);
- };
-
- LONGLONG AlignUp(LONGLONG ll, LONG lAlign) {
- // align up: round up to next boundary
- return (ll + (lAlign -1)) & ~(lAlign -1);
- };
-
- // GetReader returns the (addrefed) IAsyncReader interface
- // for SyncRead etc
- IAsyncReader* GetReader() {
- m_pReader->AddRef();
- return m_pReader;
- };
-
- // -- pure --
-
- // override this to handle data arrival
- // return value other than S_OK will stop data
- virtual HRESULT Receive(IMediaSample*) PURE;
-
- // override this to handle end-of-stream
- virtual HRESULT EndOfStream(void) PURE;
-
- // called on runtime errors that will have caused pulling
- // to stop
- // these errors are all returned from the upstream filter, who
- // will have already reported any errors to the filtergraph.
- virtual void OnError(HRESULT hr) PURE;
-
- // flush this pin and all downstream
- virtual HRESULT BeginFlush() PURE;
- virtual HRESULT EndFlush() PURE;
-
-};
-
-#endif //__PULLPIN_H__
diff --git a/dll/src/baseclasses/refclock.cpp b/dll/src/baseclasses/refclock.cpp
deleted file mode 100644
index 8ae25f4..0000000
--- a/dll/src/baseclasses/refclock.cpp
+++ /dev/null
@@ -1,402 +0,0 @@
-//------------------------------------------------------------------------------
-// File: RefClock.cpp
-//
-// Desc: DirectShow base classes - implements the IReferenceClock interface.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-#include <streams.h>
-#include <limits.h>
-
-#ifdef DXMPERF
-#include "dxmperf.h"
-#endif // DXMPERF
-
-
-// 'this' used in constructor list
-#pragma warning(disable:4355)
-
-
-STDMETHODIMP CBaseReferenceClock::NonDelegatingQueryInterface(
- REFIID riid,
- __deref_out void ** ppv)
-{
- HRESULT hr;
-
- if (riid == IID_IReferenceClock)
- {
- hr = GetInterface((IReferenceClock *) this, ppv);
- }
- else if (riid == IID_IReferenceClockTimerControl)
- {
- hr = GetInterface((IReferenceClockTimerControl *) this, ppv);
- }
- else
- {
- hr = CUnknown::NonDelegatingQueryInterface(riid, ppv);
- }
- return hr;
-}
-
-CBaseReferenceClock::~CBaseReferenceClock()
-{
-#ifdef DXMPERF
- PERFLOG_DTOR( L"CBaseReferenceClock", (IReferenceClock *) this );
-#endif // DXMPERF
-
- if (m_TimerResolution) timeEndPeriod(m_TimerResolution);
-
- if (m_pSchedule)
- {
- m_pSchedule->DumpLinkedList();
- }
-
- if (m_hThread)
- {
- m_bAbort = TRUE;
- TriggerThread();
- WaitForSingleObject( m_hThread, INFINITE );
- EXECUTE_ASSERT( CloseHandle(m_hThread) );
- m_hThread = 0;
- EXECUTE_ASSERT( CloseHandle(m_pSchedule->GetEvent()) );
- delete m_pSchedule;
- }
-}
-
-// A derived class may supply a hThreadEvent if it has its own thread that will take care
-// of calling the schedulers Advise method. (Refere to CBaseReferenceClock::AdviseThread()
-// to see what such a thread has to do.)
-CBaseReferenceClock::CBaseReferenceClock( __in_opt LPCTSTR pName,
- __inout_opt LPUNKNOWN pUnk,
- __inout HRESULT *phr,
- __inout_opt CAMSchedule * pShed )
-: CUnknown( pName, pUnk )
-, m_rtLastGotTime(0)
-, m_TimerResolution(0)
-, m_bAbort( FALSE )
-, m_pSchedule( pShed ? pShed : new CAMSchedule(CreateEvent(NULL, FALSE, FALSE, NULL)) )
-, m_hThread(0)
-{
-
-#ifdef DXMPERF
- PERFLOG_CTOR( pName ? pName : L"CBaseReferenceClock", (IReferenceClock *) this );
-#endif // DXMPERF
-
- ASSERT(m_pSchedule);
- if (!m_pSchedule)
- {
- *phr = E_OUTOFMEMORY;
- }
- else
- {
- // Set up the highest resolution timer we can manage
- TIMECAPS tc;
- m_TimerResolution = (TIMERR_NOERROR == timeGetDevCaps(&tc, sizeof(tc)))
- ? tc.wPeriodMin
- : 1;
-
- timeBeginPeriod(m_TimerResolution);
-
- /* Initialise our system times - the derived clock should set the right values */
- m_dwPrevSystemTime = timeGetTime();
- m_rtPrivateTime = (UNITS / MILLISECONDS) * m_dwPrevSystemTime;
-
- #ifdef PERF
- m_idGetSystemTime = MSR_REGISTER(TEXT("CBaseReferenceClock::GetTime"));
- #endif
-
- if ( !pShed )
- {
- DWORD ThreadID;
- m_hThread = ::CreateThread(NULL, // Security attributes
- (DWORD) 0, // Initial stack size
- AdviseThreadFunction, // Thread start address
- (LPVOID) this, // Thread parameter
- (DWORD) 0, // Creation flags
- &ThreadID); // Thread identifier
-
- if (m_hThread)
- {
- SetThreadPriority( m_hThread, THREAD_PRIORITY_TIME_CRITICAL );
- }
- else
- {
- *phr = E_FAIL;
- EXECUTE_ASSERT( CloseHandle(m_pSchedule->GetEvent()) );
- delete m_pSchedule;
- m_pSchedule = NULL;
- }
- }
- }
-}
-
-void CBaseReferenceClock::Restart (IN REFERENCE_TIME rtMinTime)
-{
- Lock();
- m_rtLastGotTime = rtMinTime ;
- Unlock();
-}
-
-STDMETHODIMP CBaseReferenceClock::GetTime(__out REFERENCE_TIME *pTime)
-{
- HRESULT hr;
- if (pTime)
- {
- REFERENCE_TIME rtNow;
- Lock();
- rtNow = GetPrivateTime();
- if (rtNow > m_rtLastGotTime)
- {
- m_rtLastGotTime = rtNow;
- hr = S_OK;
- }
- else
- {
- hr = S_FALSE;
- }
- *pTime = m_rtLastGotTime;
- Unlock();
- MSR_INTEGER(m_idGetSystemTime, LONG((*pTime) / (UNITS/MILLISECONDS)) );
-
-#ifdef DXMPERF
- PERFLOG_GETTIME( (IReferenceClock *) this, *pTime );
-#endif // DXMPERF
-
- }
- else hr = E_POINTER;
-
- return hr;
-}
-
-/* Ask for an async notification that a time has elapsed */
-
-STDMETHODIMP CBaseReferenceClock::AdviseTime(
- REFERENCE_TIME baseTime, // base reference time
- REFERENCE_TIME streamTime, // stream offset time
- HEVENT hEvent, // advise via this event
- __out DWORD_PTR *pdwAdviseCookie)// where your cookie goes
-{
- CheckPointer(pdwAdviseCookie, E_POINTER);
- *pdwAdviseCookie = 0;
-
- // Check that the event is not already set
- ASSERT(WAIT_TIMEOUT == WaitForSingleObject(HANDLE(hEvent),0));
-
- HRESULT hr;
-
- const REFERENCE_TIME lRefTime = baseTime + streamTime;
- if ( lRefTime <= 0 || lRefTime == MAX_TIME )
- {
- hr = E_INVALIDARG;
- }
- else
- {
- *pdwAdviseCookie = m_pSchedule->AddAdvisePacket( lRefTime, 0, HANDLE(hEvent), FALSE );
- hr = *pdwAdviseCookie ? NOERROR : E_OUTOFMEMORY;
- }
- return hr;
-}
-
-
-/* Ask for an asynchronous periodic notification that a time has elapsed */
-
-STDMETHODIMP CBaseReferenceClock::AdvisePeriodic(
- REFERENCE_TIME StartTime, // starting at this time
- REFERENCE_TIME PeriodTime, // time between notifications
- HSEMAPHORE hSemaphore, // advise via a semaphore
- __out DWORD_PTR *pdwAdviseCookie) // where your cookie goes
-{
- CheckPointer(pdwAdviseCookie, E_POINTER);
- *pdwAdviseCookie = 0;
-
- HRESULT hr;
- if (StartTime > 0 && PeriodTime > 0 && StartTime != MAX_TIME )
- {
- *pdwAdviseCookie = m_pSchedule->AddAdvisePacket( StartTime, PeriodTime, HANDLE(hSemaphore), TRUE );
- hr = *pdwAdviseCookie ? NOERROR : E_OUTOFMEMORY;
- }
- else hr = E_INVALIDARG;
-
- return hr;
-}
-
-
-STDMETHODIMP CBaseReferenceClock::Unadvise(DWORD_PTR dwAdviseCookie)
-{
- return m_pSchedule->Unadvise(dwAdviseCookie);
-}
-
-
-REFERENCE_TIME CBaseReferenceClock::GetPrivateTime()
-{
- CAutoLock cObjectLock(this);
-
-
- /* If the clock has wrapped then the current time will be less than
- * the last time we were notified so add on the extra milliseconds
- *
- * The time period is long enough so that the likelihood of
- * successive calls spanning the clock cycle is not considered.
- */
-
- DWORD dwTime = timeGetTime();
- {
- m_rtPrivateTime += Int32x32To64(UNITS / MILLISECONDS, (DWORD)(dwTime - m_dwPrevSystemTime));
- m_dwPrevSystemTime = dwTime;
- }
-
- return m_rtPrivateTime;
-}
-
-
-/* Adjust the current time by the input value. This allows an
- external time source to work out some of the latency of the clock
- system and adjust the "current" time accordingly. The intent is
- that the time returned to the user is synchronised to a clock
- source and allows drift to be catered for.
-
- For example: if the clock source detects a drift it can pass a delta
- to the current time rather than having to set an explicit time.
-*/
-
-STDMETHODIMP CBaseReferenceClock::SetTimeDelta(const REFERENCE_TIME & TimeDelta)
-{
-#ifdef DEBUG
-
- // Just break if passed an improper time delta value
- LONGLONG llDelta = TimeDelta > 0 ? TimeDelta : -TimeDelta;
- if (llDelta > UNITS * 1000) {
- DbgLog((LOG_TRACE, 0, TEXT("Bad Time Delta")));
- //DebugBreak();
- }
-
- // We're going to calculate a "severity" for the time change. Max -1
- // min 8. We'll then use this as the debug logging level for a
- // debug log message.
- const LONG usDelta = LONG(TimeDelta/10); // Delta in micro-secs
-
- DWORD delta = abs(usDelta); // varying delta
- // Severity == 8 - ceil(log<base 8>(abs( micro-secs delta)))
- int Severity = 8;
- while ( delta > 0 )
- {
- delta >>= 3; // div 8
- Severity--;
- }
-
- // Sev == 0 => > 2 second delta!
- DbgLog((LOG_TIMING, Severity < 0 ? 0 : Severity,
- TEXT("Sev %2i: CSystemClock::SetTimeDelta(%8ld us) %lu -> %lu ms."),
- Severity, usDelta, DWORD(ConvertToMilliseconds(m_rtPrivateTime)),
- DWORD(ConvertToMilliseconds(TimeDelta+m_rtPrivateTime)) ));
-
- // Don't want the DbgBreak to fire when running stress on debug-builds.
- #ifdef BREAK_ON_SEVERE_TIME_DELTA
- if (Severity < 0)
- DbgBreakPoint(TEXT("SetTimeDelta > 16 seconds!"),
- TEXT(__FILE__),__LINE__);
- #endif
-
-#endif
-
- CAutoLock cObjectLock(this);
- m_rtPrivateTime += TimeDelta;
- // If time goes forwards, and we have advises, then we need to
- // trigger the thread so that it can re-evaluate its wait time.
- // Since we don't want the cost of the thread switches if the change
- // is really small, only do it if clock goes forward by more than
- // 0.5 millisecond. If the time goes backwards, the thread will
- // wake up "early" (relativly speaking) and will re-evaluate at
- // that time.
- if ( TimeDelta > 5000 && m_pSchedule->GetAdviseCount() > 0 ) TriggerThread();
- return NOERROR;
-}
-
-// Thread stuff
-
-DWORD __stdcall CBaseReferenceClock::AdviseThreadFunction(__in LPVOID p)
-{
- return DWORD(reinterpret_cast<CBaseReferenceClock*>(p)->AdviseThread());
-}
-
-HRESULT CBaseReferenceClock::AdviseThread()
-{
- DWORD dwWait = INFINITE;
-
- // The first thing we do is wait until something interesting happens
- // (meaning a first advise or shutdown). This prevents us calling
- // GetPrivateTime immediately which is goodness as that is a virtual
- // routine and the derived class may not yet be constructed. (This
- // thread is created in the base class constructor.)
-
- while ( !m_bAbort )
- {
- // Wait for an interesting event to happen
- DbgLog((LOG_TIMING, 3, TEXT("CBaseRefClock::AdviseThread() Delay: %lu ms"), dwWait ));
- WaitForSingleObject(m_pSchedule->GetEvent(), dwWait);
- if (m_bAbort) break;
-
- // There are several reasons why we need to work from the internal
- // time, mainly to do with what happens when time goes backwards.
- // Mainly, it stop us looping madly if an event is just about to
- // expire when the clock goes backward (i.e. GetTime stop for a
- // while).
- const REFERENCE_TIME rtNow = GetPrivateTime();
-
- DbgLog((LOG_TIMING, 3,
- TEXT("CBaseRefClock::AdviseThread() Woke at = %lu ms"),
- ConvertToMilliseconds(rtNow) ));
-
- // We must add in a millisecond, since this is the resolution of our
- // WaitForSingleObject timer. Failure to do so will cause us to loop
- // franticly for (approx) 1 a millisecond.
- m_rtNextAdvise = m_pSchedule->Advise( 10000 + rtNow );
- LONGLONG llWait = m_rtNextAdvise - rtNow;
-
- ASSERT( llWait > 0 );
-
- llWait = ConvertToMilliseconds(llWait);
- // DON'T replace this with a max!! (The type's of these things is VERY important)
- dwWait = (llWait > REFERENCE_TIME(UINT_MAX)) ? UINT_MAX : DWORD(llWait);
- };
- return NOERROR;
-}
-
-HRESULT CBaseReferenceClock::SetDefaultTimerResolution(
- REFERENCE_TIME timerResolution // in 100ns
- )
-{
- CAutoLock cObjectLock(this);
- if( 0 == timerResolution ) {
- if( m_TimerResolution ) {
- timeEndPeriod( m_TimerResolution );
- m_TimerResolution = 0;
- }
- } else {
- TIMECAPS tc;
- DWORD dwMinResolution = (TIMERR_NOERROR == timeGetDevCaps(&tc, sizeof(tc)))
- ? tc.wPeriodMin
- : 1;
- DWORD dwResolution = max( dwMinResolution, DWORD(timerResolution / 10000) );
- if( dwResolution != m_TimerResolution ) {
- timeEndPeriod(m_TimerResolution);
- m_TimerResolution = dwResolution;
- timeBeginPeriod( m_TimerResolution );
- }
- }
- return S_OK;
-}
-
-HRESULT CBaseReferenceClock::GetDefaultTimerResolution(
- __out REFERENCE_TIME* pTimerResolution // in 100ns
- )
-{
- if( !pTimerResolution ) {
- return E_POINTER;
- }
- CAutoLock cObjectLock(this);
- *pTimerResolution = m_TimerResolution * 10000;
- return S_OK;
-}
diff --git a/dll/src/baseclasses/refclock.h b/dll/src/baseclasses/refclock.h
deleted file mode 100644
index d2b0bb1..0000000
--- a/dll/src/baseclasses/refclock.h
+++ /dev/null
@@ -1,184 +0,0 @@
-//------------------------------------------------------------------------------
-// File: RefClock.h
-//
-// Desc: DirectShow base classes - defines the IReferenceClock interface.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-#ifndef __BASEREFCLOCK__
-#define __BASEREFCLOCK__
-
-#include <Schedule.h>
-
-const UINT RESOLUTION = 1; /* High resolution timer */
-const INT ADVISE_CACHE = 4; /* Default cache size */
-const LONGLONG MAX_TIME = 0x7FFFFFFFFFFFFFFF; /* Maximum LONGLONG value */
-
-inline LONGLONG WINAPI ConvertToMilliseconds(const REFERENCE_TIME& RT)
-{
- /* This converts an arbitrary value representing a reference time
- into a MILLISECONDS value for use in subsequent system calls */
-
- return (RT / (UNITS / MILLISECONDS));
-}
-
-/* This class hierarchy will support an IReferenceClock interface so
- that an audio card (or other externally driven clock) can update the
- system wide clock that everyone uses.
-
- The interface will be pretty thin with probably just one update method
- This interface has not yet been defined.
- */
-
-/* This abstract base class implements the IReferenceClock
- * interface. Classes that actually provide clock signals (from
- * whatever source) have to be derived from this class.
- *
- * The abstract class provides implementations for:
- * CUnknown support
- * locking support (CCritSec)
- * client advise code (creates a thread)
- *
- * Question: what can we do about quality? Change the timer
- * resolution to lower the system load? Up the priority of the
- * timer thread to force more responsive signals?
- *
- * During class construction we create a worker thread that is destroyed during
- * destuction. This thread executes a series of WaitForSingleObject calls,
- * waking up when a command is given to the thread or the next wake up point
- * is reached. The wakeup points are determined by clients making Advise
- * calls.
- *
- * Each advise call defines a point in time when they wish to be notified. A
- * periodic advise is a series of these such events. We maintain a list of
- * advise links and calculate when the nearest event notification is due for.
- * We then call WaitForSingleObject with a timeout equal to this time. The
- * handle we wait on is used by the class to signal that something has changed
- * and that we must reschedule the next event. This typically happens when
- * someone comes in and asks for an advise link while we are waiting for an
- * event to timeout.
- *
- * While we are modifying the list of advise requests we
- * are protected from interference through a critical section. Clients are NOT
- * advised through callbacks. One shot clients have an event set, while
- * periodic clients have a semaphore released for each event notification. A
- * semaphore allows a client to be kept up to date with the number of events
- * actually triggered and be assured that they can't miss multiple events being
- * set.
- *
- * Keeping track of advises is taken care of by the CAMSchedule class.
- */
-
-class CBaseReferenceClock
-: public CUnknown, public IReferenceClock, public CCritSec, public IReferenceClockTimerControl
-{
-protected:
- virtual ~CBaseReferenceClock(); // Don't let me be created on the stack!
-public:
- CBaseReferenceClock(__in_opt LPCTSTR pName,
- __inout_opt LPUNKNOWN pUnk,
- __inout HRESULT *phr,
- __inout_opt CAMSchedule * pSched = 0 );
-
- STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void ** ppv);
-
- DECLARE_IUNKNOWN
-
- /* IReferenceClock methods */
- // Derived classes must implement GetPrivateTime(). All our GetTime
- // does is call GetPrivateTime and then check so that time does not
- // go backwards. A return code of S_FALSE implies that the internal
- // clock has gone backwards and GetTime time has halted until internal
- // time has caught up. (Don't know if this will be much use to folk,
- // but it seems odd not to use the return code for something useful.)
- STDMETHODIMP GetTime(__out REFERENCE_TIME *pTime);
- // When this is called, it sets m_rtLastGotTime to the time it returns.
-
- /* Provide standard mechanisms for scheduling events */
-
- /* Ask for an async notification that a time has elapsed */
- STDMETHODIMP AdviseTime(
- REFERENCE_TIME baseTime, // base reference time
- REFERENCE_TIME streamTime, // stream offset time
- HEVENT hEvent, // advise via this event
- __out DWORD_PTR *pdwAdviseCookie// where your cookie goes
- );
-
- /* Ask for an asynchronous periodic notification that a time has elapsed */
- STDMETHODIMP AdvisePeriodic(
- REFERENCE_TIME StartTime, // starting at this time
- REFERENCE_TIME PeriodTime, // time between notifications
- HSEMAPHORE hSemaphore, // advise via a semaphore
- __out DWORD_PTR *pdwAdviseCookie// where your cookie goes
- );
-
- /* Cancel a request for notification(s) - if the notification was
- * a one shot timer then this function doesn't need to be called
- * as the advise is automatically cancelled, however it does no
- * harm to explicitly cancel a one-shot advise. It is REQUIRED that
- * clients call Unadvise to clear a Periodic advise setting.
- */
-
- STDMETHODIMP Unadvise(DWORD_PTR dwAdviseCookie);
-
- /* Methods for the benefit of derived classes or outer objects */
-
- // GetPrivateTime() is the REAL clock. GetTime is just a cover for
- // it. Derived classes will probably override this method but not
- // GetTime() itself.
- // The important point about GetPrivateTime() is it's allowed to go
- // backwards. Our GetTime() will keep returning the LastGotTime
- // until GetPrivateTime() catches up.
- virtual REFERENCE_TIME GetPrivateTime();
-
- /* Provide a method for correcting drift */
- STDMETHODIMP SetTimeDelta( const REFERENCE_TIME& TimeDelta );
-
- CAMSchedule * GetSchedule() const { return m_pSchedule; }
-
- // IReferenceClockTimerControl methods
- //
- // Setting a default of 0 disables the default of 1ms
- STDMETHODIMP SetDefaultTimerResolution(
- REFERENCE_TIME timerResolution // in 100ns
- );
- STDMETHODIMP GetDefaultTimerResolution(
- __out REFERENCE_TIME* pTimerResolution // in 100ns
- );
-
-private:
- REFERENCE_TIME m_rtPrivateTime; // Current best estimate of time
- DWORD m_dwPrevSystemTime; // Last vaule we got from timeGetTime
- REFERENCE_TIME m_rtLastGotTime; // Last time returned by GetTime
- REFERENCE_TIME m_rtNextAdvise; // Time of next advise
- UINT m_TimerResolution;
-
-#ifdef PERF
- int m_idGetSystemTime;
-#endif
-
-// Thread stuff
-public:
- void TriggerThread() // Wakes thread up. Need to do this if
- { // time to next advise needs reevaluating.
- EXECUTE_ASSERT(SetEvent(m_pSchedule->GetEvent()));
- }
-
-
-private:
- BOOL m_bAbort; // Flag used for thread shutdown
- HANDLE m_hThread; // Thread handle
-
- HRESULT AdviseThread(); // Method in which the advise thread runs
- static DWORD __stdcall AdviseThreadFunction(__in LPVOID); // Function used to get there
-
-protected:
- CAMSchedule * m_pSchedule;
-
- void Restart (IN REFERENCE_TIME rtMinTime = 0I64) ;
-};
-
-#endif
-
diff --git a/dll/src/baseclasses/reftime.h b/dll/src/baseclasses/reftime.h
deleted file mode 100644
index 5bc99a6..0000000
--- a/dll/src/baseclasses/reftime.h
+++ /dev/null
@@ -1,116 +0,0 @@
-//------------------------------------------------------------------------------
-// File: RefTime.h
-//
-// Desc: DirectShow base classes - defines CRefTime, a class that manages
-// reference times.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-//
-// CRefTime
-//
-// Manage reference times.
-// Shares same data layout as REFERENCE_TIME, but adds some (nonvirtual)
-// functions providing simple comparison, conversion and arithmetic.
-//
-// A reference time (at the moment) is a unit of seconds represented in
-// 100ns units as is used in the Win32 FILETIME structure. BUT the time
-// a REFERENCE_TIME represents is NOT the time elapsed since 1/1/1601 it
-// will either be stream time or reference time depending upon context
-//
-// This class provides simple arithmetic operations on reference times
-//
-// keep non-virtual otherwise the data layout will not be the same as
-// REFERENCE_TIME
-
-
-// -----
-// note that you are safe to cast a CRefTime* to a REFERENCE_TIME*, but
-// you will need to do so explicitly
-// -----
-
-
-#ifndef __REFTIME__
-#define __REFTIME__
-
-
-const LONGLONG MILLISECONDS = (1000); // 10 ^ 3
-const LONGLONG NANOSECONDS = (1000000000); // 10 ^ 9
-const LONGLONG UNITS = (NANOSECONDS / 100); // 10 ^ 7
-
-/* Unfortunately an inline function here generates a call to __allmul
- - even for constants!
-*/
-#define MILLISECONDS_TO_100NS_UNITS(lMs) \
- Int32x32To64((lMs), (UNITS / MILLISECONDS))
-
-class CRefTime
-{
-public:
-
- // *MUST* be the only data member so that this class is exactly
- // equivalent to a REFERENCE_TIME.
- // Also, must be *no virtual functions*
-
- REFERENCE_TIME m_time;
-
- inline CRefTime()
- {
- // default to 0 time
- m_time = 0;
- };
-
- inline CRefTime(LONG msecs)
- {
- m_time = MILLISECONDS_TO_100NS_UNITS(msecs);
- };
-
- inline CRefTime(REFERENCE_TIME rt)
- {
- m_time = rt;
- };
-
- inline operator REFERENCE_TIME() const
- {
- return m_time;
- };
-
- inline CRefTime& operator=(const CRefTime& rt)
- {
- m_time = rt.m_time;
- return *this;
- };
-
- inline CRefTime& operator=(const LONGLONG ll)
- {
- m_time = ll;
- return *this;
- };
-
- inline CRefTime& operator+=(const CRefTime& rt)
- {
- return (*this = *this + rt);
- };
-
- inline CRefTime& operator-=(const CRefTime& rt)
- {
- return (*this = *this - rt);
- };
-
- inline LONG Millisecs(void)
- {
- return (LONG)(m_time / (UNITS / MILLISECONDS));
- };
-
- inline LONGLONG GetUnits(void)
- {
- return m_time;
- };
-};
-
-const LONGLONG TimeZero = 0;
-
-#endif /* __REFTIME__ */
-
diff --git a/dll/src/baseclasses/renbase.cpp b/dll/src/baseclasses/renbase.cpp
deleted file mode 100644
index c6e1962..0000000
--- a/dll/src/baseclasses/renbase.cpp
+++ /dev/null
@@ -1,2858 +0,0 @@
-//------------------------------------------------------------------------------
-// File: RenBase.cpp
-//
-// Desc: DirectShow base classes.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-#include <streams.h> // DirectShow base class definitions
-#include <mmsystem.h> // Needed for definition of timeGetTime
-#include <limits.h> // Standard data type limit definitions
-#include <measure.h> // Used for time critical log functions
-
-#pragma warning(disable:4355)
-
-// Helper function for clamping time differences
-int inline TimeDiff(REFERENCE_TIME rt)
-{
- if (rt < - (50 * UNITS)) {
- return -(50 * UNITS);
- } else
- if (rt > 50 * UNITS) {
- return 50 * UNITS;
- } else return (int)rt;
-}
-
-// Implements the CBaseRenderer class
-
-CBaseRenderer::CBaseRenderer(REFCLSID RenderClass, // CLSID for this renderer
- __in_opt LPCTSTR pName, // Debug ONLY description
- __inout_opt LPUNKNOWN pUnk, // Aggregated owner object
- __inout HRESULT *phr) : // General OLE return code
-
- CBaseFilter(pName,pUnk,&m_InterfaceLock,RenderClass),
- m_evComplete(TRUE, phr),
- m_RenderEvent(FALSE, phr),
- m_bAbort(FALSE),
- m_pPosition(NULL),
- m_ThreadSignal(TRUE, phr),
- m_bStreaming(FALSE),
- m_bEOS(FALSE),
- m_bEOSDelivered(FALSE),
- m_pMediaSample(NULL),
- m_dwAdvise(0),
- m_pQSink(NULL),
- m_pInputPin(NULL),
- m_bRepaintStatus(TRUE),
- m_SignalTime(0),
- m_bInReceive(FALSE),
- m_EndOfStreamTimer(0)
-{
- if (SUCCEEDED(*phr)) {
- Ready();
-#ifdef PERF
- m_idBaseStamp = MSR_REGISTER(TEXT("BaseRenderer: sample time stamp"));
- m_idBaseRenderTime = MSR_REGISTER(TEXT("BaseRenderer: draw time (msec)"));
- m_idBaseAccuracy = MSR_REGISTER(TEXT("BaseRenderer: Accuracy (msec)"));
-#endif
- }
-}
-
-
-// Delete the dynamically allocated IMediaPosition and IMediaSeeking helper
-// object. The object is created when somebody queries us. These are standard
-// control interfaces for seeking and setting start/stop positions and rates.
-// We will probably also have made an input pin based on CRendererInputPin
-// that has to be deleted, it's created when an enumerator calls our GetPin
-
-CBaseRenderer::~CBaseRenderer()
-{
- ASSERT(m_bStreaming == FALSE);
- ASSERT(m_EndOfStreamTimer == 0);
- StopStreaming();
- ClearPendingSample();
-
- // Delete any IMediaPosition implementation
-
- if (m_pPosition) {
- delete m_pPosition;
- m_pPosition = NULL;
- }
-
- // Delete any input pin created
-
- if (m_pInputPin) {
- delete m_pInputPin;
- m_pInputPin = NULL;
- }
-
- // Release any Quality sink
-
- ASSERT(m_pQSink == NULL);
-}
-
-
-// This returns the IMediaPosition and IMediaSeeking interfaces
-
-HRESULT CBaseRenderer::GetMediaPositionInterface(REFIID riid, __deref_out void **ppv)
-{
- CAutoLock cObjectCreationLock(&m_ObjectCreationLock);
- if (m_pPosition) {
- return m_pPosition->NonDelegatingQueryInterface(riid,ppv);
- }
-
- CBasePin *pPin = GetPin(0);
- if (NULL == pPin) {
- return E_OUTOFMEMORY;
- }
-
- HRESULT hr = NOERROR;
-
- // Create implementation of this dynamically since sometimes we may
- // never try and do a seek. The helper object implements a position
- // control interface (IMediaPosition) which in fact simply takes the
- // calls normally from the filter graph and passes them upstream
-
- m_pPosition = new CRendererPosPassThru(NAME("Renderer CPosPassThru"),
- CBaseFilter::GetOwner(),
- (HRESULT *) &hr,
- pPin);
- if (m_pPosition == NULL) {
- return E_OUTOFMEMORY;
- }
-
- if (FAILED(hr)) {
- delete m_pPosition;
- m_pPosition = NULL;
- return E_NOINTERFACE;
- }
- return GetMediaPositionInterface(riid,ppv);
-}
-
-
-// Overriden to say what interfaces we support and where
-
-STDMETHODIMP CBaseRenderer::NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv)
-{
- // Do we have this interface
-
- if (riid == IID_IMediaPosition || riid == IID_IMediaSeeking) {
- return GetMediaPositionInterface(riid,ppv);
- } else {
- return CBaseFilter::NonDelegatingQueryInterface(riid,ppv);
- }
-}
-
-
-// This is called whenever we change states, we have a manual reset event that
-// is signalled whenever we don't won't the source filter thread to wait in us
-// (such as in a stopped state) and likewise is not signalled whenever it can
-// wait (during paused and running) this function sets or resets the thread
-// event. The event is used to stop source filter threads waiting in Receive
-
-HRESULT CBaseRenderer::SourceThreadCanWait(BOOL bCanWait)
-{
- if (bCanWait == TRUE) {
- m_ThreadSignal.Reset();
- } else {
- m_ThreadSignal.Set();
- }
- return NOERROR;
-}
-
-
-#ifdef DEBUG
-// Dump the current renderer state to the debug terminal. The hardest part of
-// the renderer is the window where we unlock everything to wait for a clock
-// to signal it is time to draw or for the application to cancel everything
-// by stopping the filter. If we get things wrong we can leave the thread in
-// WaitForRenderTime with no way for it to ever get out and we will deadlock
-
-void CBaseRenderer::DisplayRendererState()
-{
- DbgLog((LOG_TIMING, 1, TEXT("\nTimed out in WaitForRenderTime")));
-
- // No way should this be signalled at this point
-
- BOOL bSignalled = m_ThreadSignal.Check();
- DbgLog((LOG_TIMING, 1, TEXT("Signal sanity check %d"),bSignalled));
-
- // Now output the current renderer state variables
-
- DbgLog((LOG_TIMING, 1, TEXT("Filter state %d"),m_State));
-
- DbgLog((LOG_TIMING, 1, TEXT("Abort flag %d"),m_bAbort));
-
- DbgLog((LOG_TIMING, 1, TEXT("Streaming flag %d"),m_bStreaming));
-
- DbgLog((LOG_TIMING, 1, TEXT("Clock advise link %d"),m_dwAdvise));
-
- DbgLog((LOG_TIMING, 1, TEXT("Current media sample %x"),m_pMediaSample));
-
- DbgLog((LOG_TIMING, 1, TEXT("EOS signalled %d"),m_bEOS));
-
- DbgLog((LOG_TIMING, 1, TEXT("EOS delivered %d"),m_bEOSDelivered));
-
- DbgLog((LOG_TIMING, 1, TEXT("Repaint status %d"),m_bRepaintStatus));
-
-
- // Output the delayed end of stream timer information
-
- DbgLog((LOG_TIMING, 1, TEXT("End of stream timer %x"),m_EndOfStreamTimer));
-
- DbgLog((LOG_TIMING, 1, TEXT("Deliver time %s"),CDisp((LONGLONG)m_SignalTime)));
-
-
- // Should never timeout during a flushing state
-
- BOOL bFlushing = m_pInputPin->IsFlushing();
- DbgLog((LOG_TIMING, 1, TEXT("Flushing sanity check %d"),bFlushing));
-
- // Display the time we were told to start at
- DbgLog((LOG_TIMING, 1, TEXT("Last run time %s"),CDisp((LONGLONG)m_tStart.m_time)));
-
- // Have we got a reference clock
- if (m_pClock == NULL) return;
-
- // Get the current time from the wall clock
-
- CRefTime CurrentTime,StartTime,EndTime;
- m_pClock->GetTime((REFERENCE_TIME*) &CurrentTime);
- CRefTime Offset = CurrentTime - m_tStart;
-
- // Display the current time from the clock
-
- DbgLog((LOG_TIMING, 1, TEXT("Clock time %s"),CDisp((LONGLONG)CurrentTime.m_time)));
-
- DbgLog((LOG_TIMING, 1, TEXT("Time difference %dms"),Offset.Millisecs()));
-
-
- // Do we have a sample ready to render
- if (m_pMediaSample == NULL) return;
-
- m_pMediaSample->GetTime((REFERENCE_TIME*)&StartTime, (REFERENCE_TIME*)&EndTime);
- DbgLog((LOG_TIMING, 1, TEXT("Next sample stream times (Start %d End %d ms)"),
- StartTime.Millisecs(),EndTime.Millisecs()));
-
- // Calculate how long it is until it is due for rendering
- CRefTime Wait = (m_tStart + StartTime) - CurrentTime;
- DbgLog((LOG_TIMING, 1, TEXT("Wait required %d ms"),Wait.Millisecs()));
-}
-#endif
-
-
-// Wait until the clock sets the timer event or we're otherwise signalled. We
-// set an arbitrary timeout for this wait and if it fires then we display the
-// current renderer state on the debugger. It will often fire if the filter's
-// left paused in an application however it may also fire during stress tests
-// if the synchronisation with application seeks and state changes is faulty
-
-#define RENDER_TIMEOUT 10000
-
-HRESULT CBaseRenderer::WaitForRenderTime()
-{
- HANDLE WaitObjects[] = { m_ThreadSignal, m_RenderEvent };
- DWORD Result = WAIT_TIMEOUT;
-
- // Wait for either the time to arrive or for us to be stopped
-
- OnWaitStart();
- while (Result == WAIT_TIMEOUT) {
- Result = WaitForMultipleObjects(2,WaitObjects,FALSE,RENDER_TIMEOUT);
-
-#ifdef DEBUG
- if (Result == WAIT_TIMEOUT) DisplayRendererState();
-#endif
-
- }
- OnWaitEnd();
-
- // We may have been awoken without the timer firing
-
- if (Result == WAIT_OBJECT_0) {
- return VFW_E_STATE_CHANGED;
- }
-
- SignalTimerFired();
- return NOERROR;
-}
-
-
-// Poll waiting for Receive to complete. This really matters when
-// Receive may set the palette and cause window messages
-// The problem is that if we don't really wait for a renderer to
-// stop processing we can deadlock waiting for a transform which
-// is calling the renderer's Receive() method because the transform's
-// Stop method doesn't know to process window messages to unblock
-// the renderer's Receive processing
-void CBaseRenderer::WaitForReceiveToComplete()
-{
- for (;;) {
- if (!m_bInReceive) {
- break;
- }
-
- MSG msg;
- // Receive all interthread snedmessages
- PeekMessage(&msg, NULL, WM_NULL, WM_NULL, PM_NOREMOVE);
-
- Sleep(1);
- }
-
- // If the wakebit for QS_POSTMESSAGE is set, the PeekMessage call
- // above just cleared the changebit which will cause some messaging
- // calls to block (waitMessage, MsgWaitFor...) now.
- // Post a dummy message to set the QS_POSTMESSAGE bit again
- if (HIWORD(GetQueueStatus(QS_POSTMESSAGE)) & QS_POSTMESSAGE) {
- // Send dummy message
- PostThreadMessage(GetCurrentThreadId(), WM_NULL, 0, 0);
- }
-}
-
-// A filter can have four discrete states, namely Stopped, Running, Paused,
-// Intermediate. We are in an intermediate state if we are currently trying
-// to pause but haven't yet got the first sample (or if we have been flushed
-// in paused state and therefore still have to wait for a sample to arrive)
-
-// This class contains an event called m_evComplete which is signalled when
-// the current state is completed and is not signalled when we are waiting to
-// complete the last state transition. As mentioned above the only time we
-// use this at the moment is when we wait for a media sample in paused state
-// If while we are waiting we receive an end of stream notification from the
-// source filter then we know no data is imminent so we can reset the event
-// This means that when we transition to paused the source filter must call
-// end of stream on us or send us an image otherwise we'll hang indefinately
-
-
-// Simple internal way of getting the real state
-
-FILTER_STATE CBaseRenderer::GetRealState() {
- return m_State;
-}
-
-
-// The renderer doesn't complete the full transition to paused states until
-// it has got one media sample to render. If you ask it for its state while
-// it's waiting it will return the state along with VFW_S_STATE_INTERMEDIATE
-
-STDMETHODIMP CBaseRenderer::GetState(DWORD dwMSecs,FILTER_STATE *State)
-{
- CheckPointer(State,E_POINTER);
-
- if (WaitDispatchingMessages(m_evComplete, dwMSecs) == WAIT_TIMEOUT) {
- *State = m_State;
- return VFW_S_STATE_INTERMEDIATE;
- }
- *State = m_State;
- return NOERROR;
-}
-
-
-// If we're pausing and we have no samples we don't complete the transition
-// to State_Paused and we return S_FALSE. However if the m_bAbort flag has
-// been set then all samples are rejected so there is no point waiting for
-// one. If we do have a sample then return NOERROR. We will only ever return
-// VFW_S_STATE_INTERMEDIATE from GetState after being paused with no sample
-// (calling GetState after either being stopped or Run will NOT return this)
-
-HRESULT CBaseRenderer::CompleteStateChange(FILTER_STATE OldState)
-{
- // Allow us to be paused when disconnected
-
- if (m_pInputPin->IsConnected() == FALSE) {
- Ready();
- return S_OK;
- }
-
- // Have we run off the end of stream
-
- if (IsEndOfStream() == TRUE) {
- Ready();
- return S_OK;
- }
-
- // Make sure we get fresh data after being stopped
-
- if (HaveCurrentSample() == TRUE) {
- if (OldState != State_Stopped) {
- Ready();
- return S_OK;
- }
- }
- NotReady();
- return S_FALSE;
-}
-
-
-// When we stop the filter the things we do are:-
-
-// Decommit the allocator being used in the connection
-// Release the source filter if it's waiting in Receive
-// Cancel any advise link we set up with the clock
-// Any end of stream signalled is now obsolete so reset
-// Allow us to be stopped when we are not connected
-
-STDMETHODIMP CBaseRenderer::Stop()
-{
- CAutoLock cRendererLock(&m_InterfaceLock);
-
- // Make sure there really is a state change
-
- if (m_State == State_Stopped) {
- return NOERROR;
- }
-
- // Is our input pin connected
-
- if (m_pInputPin->IsConnected() == FALSE) {
- NOTE("Input pin is not connected");
- m_State = State_Stopped;
- return NOERROR;
- }
-
- CBaseFilter::Stop();
-
- // If we are going into a stopped state then we must decommit whatever
- // allocator we are using it so that any source filter waiting in the
- // GetBuffer can be released and unlock themselves for a state change
-
- if (m_pInputPin->Allocator()) {
- m_pInputPin->Allocator()->Decommit();
- }
-
- // Cancel any scheduled rendering
-
- SetRepaintStatus(TRUE);
- StopStreaming();
- SourceThreadCanWait(FALSE);
- ResetEndOfStream();
- CancelNotification();
-
- // There should be no outstanding clock advise
- ASSERT(CancelNotification() == S_FALSE);
- ASSERT(WAIT_TIMEOUT == WaitForSingleObject((HANDLE)m_RenderEvent,0));
- ASSERT(m_EndOfStreamTimer == 0);
-
- Ready();
- WaitForReceiveToComplete();
- m_bAbort = FALSE;
-
- return NOERROR;
-}
-
-
-// When we pause the filter the things we do are:-
-
-// Commit the allocator being used in the connection
-// Allow a source filter thread to wait in Receive
-// Cancel any clock advise link (we may be running)
-// Possibly complete the state change if we have data
-// Allow us to be paused when we are not connected
-
-STDMETHODIMP CBaseRenderer::Pause()
-{
- CAutoLock cRendererLock(&m_InterfaceLock);
- FILTER_STATE OldState = m_State;
- ASSERT(m_pInputPin->IsFlushing() == FALSE);
-
- // Make sure there really is a state change
-
- if (m_State == State_Paused) {
- return CompleteStateChange(State_Paused);
- }
-
- // Has our input pin been connected
-
- if (m_pInputPin->IsConnected() == FALSE) {
- NOTE("Input pin is not connected");
- m_State = State_Paused;
- return CompleteStateChange(State_Paused);
- }
-
- // Pause the base filter class
-
- HRESULT hr = CBaseFilter::Pause();
- if (FAILED(hr)) {
- NOTE("Pause failed");
- return hr;
- }
-
- // Enable EC_REPAINT events again
-
- SetRepaintStatus(TRUE);
- StopStreaming();
- SourceThreadCanWait(TRUE);
- CancelNotification();
- ResetEndOfStreamTimer();
-
- // If we are going into a paused state then we must commit whatever
- // allocator we are using it so that any source filter can call the
- // GetBuffer and expect to get a buffer without returning an error
-
- if (m_pInputPin->Allocator()) {
- m_pInputPin->Allocator()->Commit();
- }
-
- // There should be no outstanding advise
- ASSERT(CancelNotification() == S_FALSE);
- ASSERT(WAIT_TIMEOUT == WaitForSingleObject((HANDLE)m_RenderEvent,0));
- ASSERT(m_EndOfStreamTimer == 0);
- ASSERT(m_pInputPin->IsFlushing() == FALSE);
-
- // When we come out of a stopped state we must clear any image we were
- // holding onto for frame refreshing. Since renderers see state changes
- // first we can reset ourselves ready to accept the source thread data
- // Paused or running after being stopped causes the current position to
- // be reset so we're not interested in passing end of stream signals
-
- if (OldState == State_Stopped) {
- m_bAbort = FALSE;
- ClearPendingSample();
- }
- return CompleteStateChange(OldState);
-}
-
-
-// When we run the filter the things we do are:-
-
-// Commit the allocator being used in the connection
-// Allow a source filter thread to wait in Receive
-// Signal the render event just to get us going
-// Start the base class by calling StartStreaming
-// Allow us to be run when we are not connected
-// Signal EC_COMPLETE if we are not connected
-
-STDMETHODIMP CBaseRenderer::Run(REFERENCE_TIME StartTime)
-{
- CAutoLock cRendererLock(&m_InterfaceLock);
- FILTER_STATE OldState = m_State;
-
- // Make sure there really is a state change
-
- if (m_State == State_Running) {
- return NOERROR;
- }
-
- // Send EC_COMPLETE if we're not connected
-
- if (m_pInputPin->IsConnected() == FALSE) {
- NotifyEvent(EC_COMPLETE,S_OK,(LONG_PTR)(IBaseFilter *)this);
- m_State = State_Running;
- return NOERROR;
- }
-
- Ready();
-
- // Pause the base filter class
-
- HRESULT hr = CBaseFilter::Run(StartTime);
- if (FAILED(hr)) {
- NOTE("Run failed");
- return hr;
- }
-
- // Allow the source thread to wait
- ASSERT(m_pInputPin->IsFlushing() == FALSE);
- SourceThreadCanWait(TRUE);
- SetRepaintStatus(FALSE);
-
- // There should be no outstanding advise
- ASSERT(CancelNotification() == S_FALSE);
- ASSERT(WAIT_TIMEOUT == WaitForSingleObject((HANDLE)m_RenderEvent,0));
- ASSERT(m_EndOfStreamTimer == 0);
- ASSERT(m_pInputPin->IsFlushing() == FALSE);
-
- // If we are going into a running state then we must commit whatever
- // allocator we are using it so that any source filter can call the
- // GetBuffer and expect to get a buffer without returning an error
-
- if (m_pInputPin->Allocator()) {
- m_pInputPin->Allocator()->Commit();
- }
-
- // When we come out of a stopped state we must clear any image we were
- // holding onto for frame refreshing. Since renderers see state changes
- // first we can reset ourselves ready to accept the source thread data
- // Paused or running after being stopped causes the current position to
- // be reset so we're not interested in passing end of stream signals
-
- if (OldState == State_Stopped) {
- m_bAbort = FALSE;
- ClearPendingSample();
- }
- return StartStreaming();
-}
-
-
-// Return the number of input pins we support
-
-int CBaseRenderer::GetPinCount()
-{
- if (m_pInputPin == NULL) {
- // Try to create it
- (void)GetPin(0);
- }
- return m_pInputPin != NULL ? 1 : 0;
-}
-
-
-// We only support one input pin and it is numbered zero
-
-CBasePin *CBaseRenderer::GetPin(int n)
-{
- CAutoLock cObjectCreationLock(&m_ObjectCreationLock);
-
- // Should only ever be called with zero
- ASSERT(n == 0);
-
- if (n != 0) {
- return NULL;
- }
-
- // Create the input pin if not already done so
-
- if (m_pInputPin == NULL) {
-
- // hr must be initialized to NOERROR because
- // CRendererInputPin's constructor only changes
- // hr's value if an error occurs.
- HRESULT hr = NOERROR;
-
- m_pInputPin = new CRendererInputPin(this,&hr,L"In");
- if (NULL == m_pInputPin) {
- return NULL;
- }
-
- if (FAILED(hr)) {
- delete m_pInputPin;
- m_pInputPin = NULL;
- return NULL;
- }
- }
- return m_pInputPin;
-}
-
-
-// If "In" then return the IPin for our input pin, otherwise NULL and error
-
-STDMETHODIMP CBaseRenderer::FindPin(LPCWSTR Id, __deref_out IPin **ppPin)
-{
- CheckPointer(ppPin,E_POINTER);
-
- if (0==lstrcmpW(Id,L"In")) {
- *ppPin = GetPin(0);
- if (*ppPin) {
- (*ppPin)->AddRef();
- } else {
- return E_OUTOFMEMORY;
- }
- } else {
- *ppPin = NULL;
- return VFW_E_NOT_FOUND;
- }
- return NOERROR;
-}
-
-
-// Called when the input pin receives an EndOfStream notification. If we have
-// not got a sample, then notify EC_COMPLETE now. If we have samples, then set
-// m_bEOS and check for this on completing samples. If we're waiting to pause
-// then complete the transition to paused state by setting the state event
-
-HRESULT CBaseRenderer::EndOfStream()
-{
- // Ignore these calls if we are stopped
-
- if (m_State == State_Stopped) {
- return NOERROR;
- }
-
- // If we have a sample then wait for it to be rendered
-
- m_bEOS = TRUE;
- if (m_pMediaSample) {
- return NOERROR;
- }
-
- // If we are waiting for pause then we are now ready since we cannot now
- // carry on waiting for a sample to arrive since we are being told there
- // won't be any. This sets an event that the GetState function picks up
-
- Ready();
-
- // Only signal completion now if we are running otherwise queue it until
- // we do run in StartStreaming. This is used when we seek because a seek
- // causes a pause where early notification of completion is misleading
-
- if (m_bStreaming) {
- SendEndOfStream();
- }
- return NOERROR;
-}
-
-
-// When we are told to flush we should release the source thread
-
-HRESULT CBaseRenderer::BeginFlush()
-{
- // If paused then report state intermediate until we get some data
-
- if (m_State == State_Paused) {
- NotReady();
- }
-
- SourceThreadCanWait(FALSE);
- CancelNotification();
- ClearPendingSample();
- // Wait for Receive to complete
- WaitForReceiveToComplete();
-
- return NOERROR;
-}
-
-
-// After flushing the source thread can wait in Receive again
-
-HRESULT CBaseRenderer::EndFlush()
-{
- // Reset the current sample media time
- if (m_pPosition) m_pPosition->ResetMediaTime();
-
- // There should be no outstanding advise
-
- ASSERT(CancelNotification() == S_FALSE);
- SourceThreadCanWait(TRUE);
- return NOERROR;
-}
-
-
-// We can now send EC_REPAINTs if so required
-
-HRESULT CBaseRenderer::CompleteConnect(IPin *pReceivePin)
-{
- // The caller should always hold the interface lock because
- // the function uses CBaseFilter::m_State.
- ASSERT(CritCheckIn(&m_InterfaceLock));
-
- m_bAbort = FALSE;
-
- if (State_Running == GetRealState()) {
- HRESULT hr = StartStreaming();
- if (FAILED(hr)) {
- return hr;
- }
-
- SetRepaintStatus(FALSE);
- } else {
- SetRepaintStatus(TRUE);
- }
-
- return NOERROR;
-}
-
-
-// Called when we go paused or running
-
-HRESULT CBaseRenderer::Active()
-{
- return NOERROR;
-}
-
-
-// Called when we go into a stopped state
-
-HRESULT CBaseRenderer::Inactive()
-{
- if (m_pPosition) {
- m_pPosition->ResetMediaTime();
- }
- // People who derive from this may want to override this behaviour
- // to keep hold of the sample in some circumstances
- ClearPendingSample();
-
- return NOERROR;
-}
-
-
-// Tell derived classes about the media type agreed
-
-HRESULT CBaseRenderer::SetMediaType(const CMediaType *pmt)
-{
- return NOERROR;
-}
-
-
-// When we break the input pin connection we should reset the EOS flags. When
-// we are asked for either IMediaPosition or IMediaSeeking we will create a
-// CPosPassThru object to handles media time pass through. When we're handed
-// samples we store (by calling CPosPassThru::RegisterMediaTime) their media
-// times so we can then return a real current position of data being rendered
-
-HRESULT CBaseRenderer::BreakConnect()
-{
- // Do we have a quality management sink
-
- if (m_pQSink) {
- m_pQSink->Release();
- m_pQSink = NULL;
- }
-
- // Check we have a valid connection
-
- if (m_pInputPin->IsConnected() == FALSE) {
- return S_FALSE;
- }
-
- // Check we are stopped before disconnecting
- if (m_State != State_Stopped && !m_pInputPin->CanReconnectWhenActive()) {
- return VFW_E_NOT_STOPPED;
- }
-
- SetRepaintStatus(FALSE);
- ResetEndOfStream();
- ClearPendingSample();
- m_bAbort = FALSE;
-
- if (State_Running == m_State) {
- StopStreaming();
- }
-
- return NOERROR;
-}
-
-
-// Retrieves the sample times for this samples (note the sample times are
-// passed in by reference not value). We return S_FALSE to say schedule this
-// sample according to the times on the sample. We also return S_OK in
-// which case the object should simply render the sample data immediately
-
-HRESULT CBaseRenderer::GetSampleTimes(IMediaSample *pMediaSample,
- __out REFERENCE_TIME *pStartTime,
- __out REFERENCE_TIME *pEndTime)
-{
- ASSERT(m_dwAdvise == 0);
- ASSERT(pMediaSample);
-
- // If the stop time for this sample is before or the same as start time,
- // then just ignore it (release it) and schedule the next one in line
- // Source filters should always fill in the start and end times properly!
-
- if (SUCCEEDED(pMediaSample->GetTime(pStartTime, pEndTime))) {
- if (*pEndTime < *pStartTime) {
- return VFW_E_START_TIME_AFTER_END;
- }
- } else {
- // no time set in the sample... draw it now?
- return S_OK;
- }
-
- // Can't synchronise without a clock so we return S_OK which tells the
- // caller that the sample should be rendered immediately without going
- // through the overhead of setting a timer advise link with the clock
-
- if (m_pClock == NULL) {
- return S_OK;
- }
- return ShouldDrawSampleNow(pMediaSample,pStartTime,pEndTime);
-}
-
-
-// By default all samples are drawn according to their time stamps so we
-// return S_FALSE. Returning S_OK means draw immediately, this is used
-// by the derived video renderer class in its quality management.
-
-HRESULT CBaseRenderer::ShouldDrawSampleNow(IMediaSample *pMediaSample,
- __out REFERENCE_TIME *ptrStart,
- __out REFERENCE_TIME *ptrEnd)
-{
- return S_FALSE;
-}
-
-
-// We must always reset the current advise time to zero after a timer fires
-// because there are several possible ways which lead us not to do any more
-// scheduling such as the pending image being cleared after state changes
-
-void CBaseRenderer::SignalTimerFired()
-{
- m_dwAdvise = 0;
-}
-
-
-// Cancel any notification currently scheduled. This is called by the owning
-// window object when it is told to stop streaming. If there is no timer link
-// outstanding then calling this is benign otherwise we go ahead and cancel
-// We must always reset the render event as the quality management code can
-// signal immediate rendering by setting the event without setting an advise
-// link. If we're subsequently stopped and run the first attempt to setup an
-// advise link with the reference clock will find the event still signalled
-
-HRESULT CBaseRenderer::CancelNotification()
-{
- ASSERT(m_dwAdvise == 0 || m_pClock);
- DWORD_PTR dwAdvise = m_dwAdvise;
-
- // Have we a live advise link
-
- if (m_dwAdvise) {
- m_pClock->Unadvise(m_dwAdvise);
- SignalTimerFired();
- ASSERT(m_dwAdvise == 0);
- }
-
- // Clear the event and return our status
-
- m_RenderEvent.Reset();
- return (dwAdvise ? S_OK : S_FALSE);
-}
-
-
-// Responsible for setting up one shot advise links with the clock
-// Return FALSE if the sample is to be dropped (not drawn at all)
-// Return TRUE if the sample is to be drawn and in this case also
-// arrange for m_RenderEvent to be set at the appropriate time
-
-BOOL CBaseRenderer::ScheduleSample(IMediaSample *pMediaSample)
-{
- REFERENCE_TIME StartSample, EndSample;
-
- // Is someone pulling our leg
-
- if (pMediaSample == NULL) {
- return FALSE;
- }
-
- // Get the next sample due up for rendering. If there aren't any ready
- // then GetNextSampleTimes returns an error. If there is one to be done
- // then it succeeds and yields the sample times. If it is due now then
- // it returns S_OK other if it's to be done when due it returns S_FALSE
-
- HRESULT hr = GetSampleTimes(pMediaSample, &StartSample, &EndSample);
- if (FAILED(hr)) {
- return FALSE;
- }
-
- // If we don't have a reference clock then we cannot set up the advise
- // time so we simply set the event indicating an image to render. This
- // will cause us to run flat out without any timing or synchronisation
-
- if (hr == S_OK) {
- EXECUTE_ASSERT(SetEvent((HANDLE) m_RenderEvent));
- return TRUE;
- }
-
- ASSERT(m_dwAdvise == 0);
- ASSERT(m_pClock);
- ASSERT(WAIT_TIMEOUT == WaitForSingleObject((HANDLE)m_RenderEvent,0));
-
- // We do have a valid reference clock interface so we can ask it to
- // set an event when the image comes due for rendering. We pass in
- // the reference time we were told to start at and also the current
- // stream time which is the offset from the start reference time
-
- hr = m_pClock->AdviseTime(
- (REFERENCE_TIME) m_tStart, // Start run time
- StartSample, // Stream time
- (HEVENT)(HANDLE) m_RenderEvent, // Render notification
- &m_dwAdvise); // Advise cookie
-
- if (SUCCEEDED(hr)) {
- return TRUE;
- }
-
- // We could not schedule the next sample for rendering despite the fact
- // we have a valid sample here. This is a fair indication that either
- // the system clock is wrong or the time stamp for the sample is duff
-
- ASSERT(m_dwAdvise == 0);
- return FALSE;
-}
-
-
-// This is called when a sample comes due for rendering. We pass the sample
-// on to the derived class. After rendering we will initialise the timer for
-// the next sample, NOTE signal that the last one fired first, if we don't
-// do this it thinks there is still one outstanding that hasn't completed
-
-HRESULT CBaseRenderer::Render(IMediaSample *pMediaSample)
-{
- // If the media sample is NULL then we will have been notified by the
- // clock that another sample is ready but in the mean time someone has
- // stopped us streaming which causes the next sample to be released
-
- if (pMediaSample == NULL) {
- return S_FALSE;
- }
-
- // If we have stopped streaming then don't render any more samples, the
- // thread that got in and locked us and then reset this flag does not
- // clear the pending sample as we can use it to refresh any output device
-
- if (m_bStreaming == FALSE) {
- return S_FALSE;
- }
-
- // Time how long the rendering takes
-
- OnRenderStart(pMediaSample);
- DoRenderSample(pMediaSample);
- OnRenderEnd(pMediaSample);
-
- return NOERROR;
-}
-
-
-// Checks if there is a sample waiting at the renderer
-
-BOOL CBaseRenderer::HaveCurrentSample()
-{
- CAutoLock cRendererLock(&m_RendererLock);
- return (m_pMediaSample == NULL ? FALSE : TRUE);
-}
-
-
-// Returns the current sample waiting at the video renderer. We AddRef the
-// sample before returning so that should it come due for rendering the
-// person who called this method will hold the remaining reference count
-// that will stop the sample being added back onto the allocator free list
-
-IMediaSample *CBaseRenderer::GetCurrentSample()
-{
- CAutoLock cRendererLock(&m_RendererLock);
- if (m_pMediaSample) {
- m_pMediaSample->AddRef();
- }
- return m_pMediaSample;
-}
-
-
-// Called when the source delivers us a sample. We go through a few checks to
-// make sure the sample can be rendered. If we are running (streaming) then we
-// have the sample scheduled with the reference clock, if we are not streaming
-// then we have received an sample in paused mode so we can complete any state
-// transition. On leaving this function everything will be unlocked so an app
-// thread may get in and change our state to stopped (for example) in which
-// case it will also signal the thread event so that our wait call is stopped
-
-HRESULT CBaseRenderer::PrepareReceive(IMediaSample *pMediaSample)
-{
- CAutoLock cInterfaceLock(&m_InterfaceLock);
- m_bInReceive = TRUE;
-
- // Check our flushing and filter state
-
- // This function must hold the interface lock because it calls
- // CBaseInputPin::Receive() and CBaseInputPin::Receive() uses
- // CBasePin::m_bRunTimeError.
- HRESULT hr = m_pInputPin->CBaseInputPin::Receive(pMediaSample);
-
- if (hr != NOERROR) {
- m_bInReceive = FALSE;
- return E_FAIL;
- }
-
- // Has the type changed on a media sample. We do all rendering
- // synchronously on the source thread, which has a side effect
- // that only one buffer is ever outstanding. Therefore when we
- // have Receive called we can go ahead and change the format
- // Since the format change can cause a SendMessage we just don't
- // lock
- if (m_pInputPin->SampleProps()->pMediaType) {
- hr = m_pInputPin->SetMediaType(
- (CMediaType *)m_pInputPin->SampleProps()->pMediaType);
- if (FAILED(hr)) {
- m_bInReceive = FALSE;
- return hr;
- }
- }
-
-
- CAutoLock cSampleLock(&m_RendererLock);
-
- ASSERT(IsActive() == TRUE);
- ASSERT(m_pInputPin->IsFlushing() == FALSE);
- ASSERT(m_pInputPin->IsConnected() == TRUE);
- ASSERT(m_pMediaSample == NULL);
-
- // Return an error if we already have a sample waiting for rendering
- // source pins must serialise the Receive calls - we also check that
- // no data is being sent after the source signalled an end of stream
-
- if (m_pMediaSample || m_bEOS || m_bAbort) {
- Ready();
- m_bInReceive = FALSE;
- return E_UNEXPECTED;
- }
-
- // Store the media times from this sample
- if (m_pPosition) m_pPosition->RegisterMediaTime(pMediaSample);
-
- // Schedule the next sample if we are streaming
-
- if ((m_bStreaming == TRUE) && (ScheduleSample(pMediaSample) == FALSE)) {
- ASSERT(WAIT_TIMEOUT == WaitForSingleObject((HANDLE)m_RenderEvent,0));
- ASSERT(CancelNotification() == S_FALSE);
- m_bInReceive = FALSE;
- return VFW_E_SAMPLE_REJECTED;
- }
-
- // Store the sample end time for EC_COMPLETE handling
- m_SignalTime = m_pInputPin->SampleProps()->tStop;
-
- // BEWARE we sometimes keep the sample even after returning the thread to
- // the source filter such as when we go into a stopped state (we keep it
- // to refresh the device with) so we must AddRef it to keep it safely. If
- // we start flushing the source thread is released and any sample waiting
- // will be released otherwise GetBuffer may never return (see BeginFlush)
-
- m_pMediaSample = pMediaSample;
- m_pMediaSample->AddRef();
-
- if (m_bStreaming == FALSE) {
- SetRepaintStatus(TRUE);
- }
- return NOERROR;
-}
-
-
-// Called by the source filter when we have a sample to render. Under normal
-// circumstances we set an advise link with the clock, wait for the time to
-// arrive and then render the data using the PURE virtual DoRenderSample that
-// the derived class will have overriden. After rendering the sample we may
-// also signal EOS if it was the last one sent before EndOfStream was called
-
-HRESULT CBaseRenderer::Receive(IMediaSample *pSample)
-{
- ASSERT(pSample);
-
- // It may return VFW_E_SAMPLE_REJECTED code to say don't bother
-
- HRESULT hr = PrepareReceive(pSample);
- ASSERT(m_bInReceive == SUCCEEDED(hr));
- if (FAILED(hr)) {
- if (hr == VFW_E_SAMPLE_REJECTED) {
- return NOERROR;
- }
- return hr;
- }
-
- // We realize the palette in "PrepareRender()" so we have to give away the
- // filter lock here.
- if (m_State == State_Paused) {
- PrepareRender();
- // no need to use InterlockedExchange
- m_bInReceive = FALSE;
- {
- // We must hold both these locks
- CAutoLock cRendererLock(&m_InterfaceLock);
- if (m_State == State_Stopped)
- return NOERROR;
-
- m_bInReceive = TRUE;
- CAutoLock cSampleLock(&m_RendererLock);
- OnReceiveFirstSample(pSample);
- }
- Ready();
- }
- // Having set an advise link with the clock we sit and wait. We may be
- // awoken by the clock firing or by a state change. The rendering call
- // will lock the critical section and check we can still render the data
-
- hr = WaitForRenderTime();
- if (FAILED(hr)) {
- m_bInReceive = FALSE;
- return NOERROR;
- }
-
- PrepareRender();
-
- // Set this here and poll it until we work out the locking correctly
- // It can't be right that the streaming stuff grabs the interface
- // lock - after all we want to be able to wait for this stuff
- // to complete
- m_bInReceive = FALSE;
-
- // We must hold both these locks
- CAutoLock cRendererLock(&m_InterfaceLock);
-
- // since we gave away the filter wide lock, the sate of the filter could
- // have chnaged to Stopped
- if (m_State == State_Stopped)
- return NOERROR;
-
- CAutoLock cSampleLock(&m_RendererLock);
-
- // Deal with this sample
-
- Render(m_pMediaSample);
- ClearPendingSample();
- SendEndOfStream();
- CancelNotification();
- return NOERROR;
-}
-
-
-// This is called when we stop or are inactivated to clear the pending sample
-// We release the media sample interface so that they can be allocated to the
-// source filter again, unless of course we are changing state to inactive in
-// which case GetBuffer will return an error. We must also reset the current
-// media sample to NULL so that we know we do not currently have an image
-
-HRESULT CBaseRenderer::ClearPendingSample()
-{
- CAutoLock cRendererLock(&m_RendererLock);
- if (m_pMediaSample) {
- m_pMediaSample->Release();
- m_pMediaSample = NULL;
- }
- return NOERROR;
-}
-
-
-// Used to signal end of stream according to the sample end time
-
-void CALLBACK EndOfStreamTimer(UINT uID, // Timer identifier
- UINT uMsg, // Not currently used
- DWORD_PTR dwUser,// User information
- DWORD_PTR dw1, // Windows reserved
- DWORD_PTR dw2) // is also reserved
-{
- CBaseRenderer *pRenderer = (CBaseRenderer *) dwUser;
- NOTE1("EndOfStreamTimer called (%d)",uID);
- pRenderer->TimerCallback();
-}
-
-// Do the timer callback work
-void CBaseRenderer::TimerCallback()
-{
- // Lock for synchronization (but don't hold this lock when calling
- // timeKillEvent)
- CAutoLock cRendererLock(&m_RendererLock);
-
- // See if we should signal end of stream now
-
- if (m_EndOfStreamTimer) {
- m_EndOfStreamTimer = 0;
- SendEndOfStream();
- }
-}
-
-
-// If we are at the end of the stream signal the filter graph but do not set
-// the state flag back to FALSE. Once we drop off the end of the stream we
-// leave the flag set (until a subsequent ResetEndOfStream). Each sample we
-// get delivered will update m_SignalTime to be the last sample's end time.
-// We must wait this long before signalling end of stream to the filtergraph
-
-#define TIMEOUT_DELIVERYWAIT 50
-#define TIMEOUT_RESOLUTION 10
-
-HRESULT CBaseRenderer::SendEndOfStream()
-{
- ASSERT(CritCheckIn(&m_RendererLock));
- if (m_bEOS == FALSE || m_bEOSDelivered || m_EndOfStreamTimer) {
- return NOERROR;
- }
-
- // If there is no clock then signal immediately
- if (m_pClock == NULL) {
- return NotifyEndOfStream();
- }
-
- // How long into the future is the delivery time
-
- REFERENCE_TIME Signal = m_tStart + m_SignalTime;
- REFERENCE_TIME CurrentTime;
- m_pClock->GetTime(&CurrentTime);
- LONG Delay = LONG((Signal - CurrentTime) / 10000);
-
- // Dump the timing information to the debugger
-
- NOTE1("Delay until end of stream delivery %d",Delay);
- NOTE1("Current %s",(LPCTSTR)CDisp((LONGLONG)CurrentTime));
- NOTE1("Signal %s",(LPCTSTR)CDisp((LONGLONG)Signal));
-
- // Wait for the delivery time to arrive
-
- if (Delay < TIMEOUT_DELIVERYWAIT) {
- return NotifyEndOfStream();
- }
-
- // Signal a timer callback on another worker thread
-
- m_EndOfStreamTimer = CompatibleTimeSetEvent((UINT) Delay, // Period of timer
- TIMEOUT_RESOLUTION, // Timer resolution
- EndOfStreamTimer, // Callback function
- DWORD_PTR(this), // Used information
- TIME_ONESHOT); // Type of callback
- if (m_EndOfStreamTimer == 0) {
- return NotifyEndOfStream();
- }
- return NOERROR;
-}
-
-
-// Signals EC_COMPLETE to the filtergraph manager
-
-HRESULT CBaseRenderer::NotifyEndOfStream()
-{
- CAutoLock cRendererLock(&m_RendererLock);
- ASSERT(m_bEOSDelivered == FALSE);
- ASSERT(m_EndOfStreamTimer == 0);
-
- // Has the filter changed state
-
- if (m_bStreaming == FALSE) {
- ASSERT(m_EndOfStreamTimer == 0);
- return NOERROR;
- }
-
- // Reset the end of stream timer
- m_EndOfStreamTimer = 0;
-
- // If we've been using the IMediaPosition interface, set it's start
- // and end media "times" to the stop position by hand. This ensures
- // that we actually get to the end, even if the MPEG guestimate has
- // been bad or if the quality management dropped the last few frames
-
- if (m_pPosition) m_pPosition->EOS();
- m_bEOSDelivered = TRUE;
- NOTE("Sending EC_COMPLETE...");
- return NotifyEvent(EC_COMPLETE,S_OK,(LONG_PTR)(IBaseFilter *)this);
-}
-
-
-// Reset the end of stream flag, this is typically called when we transfer to
-// stopped states since that resets the current position back to the start so
-// we will receive more samples or another EndOfStream if there aren't any. We
-// keep two separate flags one to say we have run off the end of the stream
-// (this is the m_bEOS flag) and another to say we have delivered EC_COMPLETE
-// to the filter graph. We need the latter otherwise we can end up sending an
-// EC_COMPLETE every time the source changes state and calls our EndOfStream
-
-HRESULT CBaseRenderer::ResetEndOfStream()
-{
- ResetEndOfStreamTimer();
- CAutoLock cRendererLock(&m_RendererLock);
-
- m_bEOS = FALSE;
- m_bEOSDelivered = FALSE;
- m_SignalTime = 0;
-
- return NOERROR;
-}
-
-
-// Kills any outstanding end of stream timer
-
-void CBaseRenderer::ResetEndOfStreamTimer()
-{
- ASSERT(CritCheckOut(&m_RendererLock));
- if (m_EndOfStreamTimer) {
- timeKillEvent(m_EndOfStreamTimer);
- m_EndOfStreamTimer = 0;
- }
-}
-
-
-// This is called when we start running so that we can schedule any pending
-// image we have with the clock and display any timing information. If we
-// don't have any sample but we have queued an EOS flag then we send it. If
-// we do have a sample then we wait until that has been rendered before we
-// signal the filter graph otherwise we may change state before it's done
-
-HRESULT CBaseRenderer::StartStreaming()
-{
- CAutoLock cRendererLock(&m_RendererLock);
- if (m_bStreaming == TRUE) {
- return NOERROR;
- }
-
- // Reset the streaming times ready for running
-
- m_bStreaming = TRUE;
-
- timeBeginPeriod(1);
- OnStartStreaming();
-
- // There should be no outstanding advise
- ASSERT(WAIT_TIMEOUT == WaitForSingleObject((HANDLE)m_RenderEvent,0));
- ASSERT(CancelNotification() == S_FALSE);
-
- // If we have an EOS and no data then deliver it now
-
- if (m_pMediaSample == NULL) {
- return SendEndOfStream();
- }
-
- // Have the data rendered
-
- ASSERT(m_pMediaSample);
- if (!ScheduleSample(m_pMediaSample))
- m_RenderEvent.Set();
-
- return NOERROR;
-}
-
-
-// This is called when we stop streaming so that we can set our internal flag
-// indicating we are not now to schedule any more samples arriving. The state
-// change methods in the filter implementation take care of cancelling any
-// clock advise link we have set up and clearing any pending sample we have
-
-HRESULT CBaseRenderer::StopStreaming()
-{
- CAutoLock cRendererLock(&m_RendererLock);
- m_bEOSDelivered = FALSE;
-
- if (m_bStreaming == TRUE) {
- m_bStreaming = FALSE;
- OnStopStreaming();
- timeEndPeriod(1);
- }
- return NOERROR;
-}
-
-
-// We have a boolean flag that is reset when we have signalled EC_REPAINT to
-// the filter graph. We set this when we receive an image so that should any
-// conditions arise again we can send another one. By having a flag we ensure
-// we don't flood the filter graph with redundant calls. We do not set the
-// event when we receive an EndOfStream call since there is no point in us
-// sending further EC_REPAINTs. In particular the AutoShowWindow method and
-// the DirectDraw object use this method to control the window repainting
-
-void CBaseRenderer::SetRepaintStatus(BOOL bRepaint)
-{
- CAutoLock cSampleLock(&m_RendererLock);
- m_bRepaintStatus = bRepaint;
-}
-
-
-// Pass the window handle to the upstream filter
-
-void CBaseRenderer::SendNotifyWindow(IPin *pPin,HWND hwnd)
-{
- IMediaEventSink *pSink;
-
- // Does the pin support IMediaEventSink
- HRESULT hr = pPin->QueryInterface(IID_IMediaEventSink,(void **)&pSink);
- if (SUCCEEDED(hr)) {
- pSink->Notify(EC_NOTIFY_WINDOW,LONG_PTR(hwnd),0);
- pSink->Release();
- }
- NotifyEvent(EC_NOTIFY_WINDOW,LONG_PTR(hwnd),0);
-}
-
-
-// Signal an EC_REPAINT to the filter graph. This can be used to have data
-// sent to us. For example when a video window is first displayed it may
-// not have an image to display, at which point it signals EC_REPAINT. The
-// filtergraph will either pause the graph if stopped or if already paused
-// it will call put_CurrentPosition of the current position. Setting the
-// current position to itself has the stream flushed and the image resent
-
-#define RLOG(_x_) DbgLog((LOG_TRACE,1,TEXT(_x_)));
-
-void CBaseRenderer::SendRepaint()
-{
- CAutoLock cSampleLock(&m_RendererLock);
- ASSERT(m_pInputPin);
-
- // We should not send repaint notifications when...
- // - An end of stream has been notified
- // - Our input pin is being flushed
- // - The input pin is not connected
- // - We have aborted a video playback
- // - There is a repaint already sent
-
- if (m_bAbort == FALSE) {
- if (m_pInputPin->IsConnected() == TRUE) {
- if (m_pInputPin->IsFlushing() == FALSE) {
- if (IsEndOfStream() == FALSE) {
- if (m_bRepaintStatus == TRUE) {
- IPin *pPin = (IPin *) m_pInputPin;
- NotifyEvent(EC_REPAINT,(LONG_PTR) pPin,0);
- SetRepaintStatus(FALSE);
- RLOG("Sending repaint");
- }
- }
- }
- }
- }
-}
-
-
-// When a video window detects a display change (WM_DISPLAYCHANGE message) it
-// can send an EC_DISPLAY_CHANGED event code along with the renderer pin. The
-// filtergraph will stop everyone and reconnect our input pin. As we're then
-// reconnected we can accept the media type that matches the new display mode
-// since we may no longer be able to draw the current image type efficiently
-
-BOOL CBaseRenderer::OnDisplayChange()
-{
- // Ignore if we are not connected yet
-
- CAutoLock cSampleLock(&m_RendererLock);
- if (m_pInputPin->IsConnected() == FALSE) {
- return FALSE;
- }
-
- RLOG("Notification of EC_DISPLAY_CHANGE");
-
- // Pass our input pin as parameter on the event
-
- IPin *pPin = (IPin *) m_pInputPin;
- m_pInputPin->AddRef();
- NotifyEvent(EC_DISPLAY_CHANGED,(LONG_PTR) pPin,0);
- SetAbortSignal(TRUE);
- ClearPendingSample();
- m_pInputPin->Release();
-
- return TRUE;
-}
-
-
-// Called just before we start drawing.
-// Store the current time in m_trRenderStart to allow the rendering time to be
-// logged. Log the time stamp of the sample and how late it is (neg is early)
-
-void CBaseRenderer::OnRenderStart(IMediaSample *pMediaSample)
-{
-#ifdef PERF
- REFERENCE_TIME trStart, trEnd;
- pMediaSample->GetTime(&trStart, &trEnd);
-
- MSR_INTEGER(m_idBaseStamp, (int)trStart); // dump low order 32 bits
-
- m_pClock->GetTime(&m_trRenderStart);
- MSR_INTEGER(0, (int)m_trRenderStart);
- REFERENCE_TIME trStream;
- trStream = m_trRenderStart-m_tStart; // convert reftime to stream time
- MSR_INTEGER(0,(int)trStream);
-
- const int trLate = (int)(trStream - trStart);
- MSR_INTEGER(m_idBaseAccuracy, trLate/10000); // dump in mSec
-#endif
-
-} // OnRenderStart
-
-
-// Called directly after drawing an image.
-// calculate the time spent drawing and log it.
-
-void CBaseRenderer::OnRenderEnd(IMediaSample *pMediaSample)
-{
-#ifdef PERF
- REFERENCE_TIME trNow;
- m_pClock->GetTime(&trNow);
- MSR_INTEGER(0,(int)trNow);
- int t = (int)((trNow - m_trRenderStart)/10000); // convert UNITS->msec
- MSR_INTEGER(m_idBaseRenderTime, t);
-#endif
-} // OnRenderEnd
-
-
-
-
-// Constructor must be passed the base renderer object
-
-CRendererInputPin::CRendererInputPin(__inout CBaseRenderer *pRenderer,
- __inout HRESULT *phr,
- __in_opt LPCWSTR pPinName) :
- CBaseInputPin(NAME("Renderer pin"),
- pRenderer,
- &pRenderer->m_InterfaceLock,
- (HRESULT *) phr,
- pPinName)
-{
- m_pRenderer = pRenderer;
- ASSERT(m_pRenderer);
-}
-
-
-// Signals end of data stream on the input pin
-
-STDMETHODIMP CRendererInputPin::EndOfStream()
-{
- CAutoLock cRendererLock(&m_pRenderer->m_InterfaceLock);
- CAutoLock cSampleLock(&m_pRenderer->m_RendererLock);
-
- // Make sure we're streaming ok
-
- HRESULT hr = CheckStreaming();
- if (hr != NOERROR) {
- return hr;
- }
-
- // Pass it onto the renderer
-
- hr = m_pRenderer->EndOfStream();
- if (SUCCEEDED(hr)) {
- hr = CBaseInputPin::EndOfStream();
- }
- return hr;
-}
-
-
-// Signals start of flushing on the input pin - we do the final reset end of
-// stream with the renderer lock unlocked but with the interface lock locked
-// We must do this because we call timeKillEvent, our timer callback method
-// has to take the renderer lock to serialise our state. Therefore holding a
-// renderer lock when calling timeKillEvent could cause a deadlock condition
-
-STDMETHODIMP CRendererInputPin::BeginFlush()
-{
- CAutoLock cRendererLock(&m_pRenderer->m_InterfaceLock);
- {
- CAutoLock cSampleLock(&m_pRenderer->m_RendererLock);
- CBaseInputPin::BeginFlush();
- m_pRenderer->BeginFlush();
- }
- return m_pRenderer->ResetEndOfStream();
-}
-
-
-// Signals end of flushing on the input pin
-
-STDMETHODIMP CRendererInputPin::EndFlush()
-{
- CAutoLock cRendererLock(&m_pRenderer->m_InterfaceLock);
- CAutoLock cSampleLock(&m_pRenderer->m_RendererLock);
-
- HRESULT hr = m_pRenderer->EndFlush();
- if (SUCCEEDED(hr)) {
- hr = CBaseInputPin::EndFlush();
- }
- return hr;
-}
-
-
-// Pass the sample straight through to the renderer object
-
-STDMETHODIMP CRendererInputPin::Receive(IMediaSample *pSample)
-{
- HRESULT hr = m_pRenderer->Receive(pSample);
- if (FAILED(hr)) {
-
- // A deadlock could occur if the caller holds the renderer lock and
- // attempts to acquire the interface lock.
- ASSERT(CritCheckOut(&m_pRenderer->m_RendererLock));
-
- {
- // The interface lock must be held when the filter is calling
- // IsStopped() or IsFlushing(). The interface lock must also
- // be held because the function uses m_bRunTimeError.
- CAutoLock cRendererLock(&m_pRenderer->m_InterfaceLock);
-
- // We do not report errors which occur while the filter is stopping,
- // flushing or if the m_bAbort flag is set . Errors are expected to
- // occur during these operations and the streaming thread correctly
- // handles the errors.
- if (!IsStopped() && !IsFlushing() && !m_pRenderer->m_bAbort && !m_bRunTimeError) {
-
- // EC_ERRORABORT's first parameter is the error which caused
- // the event and its' last parameter is 0. See the Direct
- // Show SDK documentation for more information.
- m_pRenderer->NotifyEvent(EC_ERRORABORT,hr,0);
-
- {
- CAutoLock alRendererLock(&m_pRenderer->m_RendererLock);
- if (m_pRenderer->IsStreaming() && !m_pRenderer->IsEndOfStreamDelivered()) {
- m_pRenderer->NotifyEndOfStream();
- }
- }
-
- m_bRunTimeError = TRUE;
- }
- }
- }
-
- return hr;
-}
-
-
-// Called when the input pin is disconnected
-
-HRESULT CRendererInputPin::BreakConnect()
-{
- HRESULT hr = m_pRenderer->BreakConnect();
- if (FAILED(hr)) {
- return hr;
- }
- return CBaseInputPin::BreakConnect();
-}
-
-
-// Called when the input pin is connected
-
-HRESULT CRendererInputPin::CompleteConnect(IPin *pReceivePin)
-{
- HRESULT hr = m_pRenderer->CompleteConnect(pReceivePin);
- if (FAILED(hr)) {
- return hr;
- }
- return CBaseInputPin::CompleteConnect(pReceivePin);
-}
-
-
-// Give the pin id of our one and only pin
-
-STDMETHODIMP CRendererInputPin::QueryId(__deref_out LPWSTR *Id)
-{
- CheckPointer(Id,E_POINTER);
-
- const WCHAR szIn[] = L"In";
-
- *Id = (LPWSTR)CoTaskMemAlloc(sizeof(szIn));
- if (*Id == NULL) {
- return E_OUTOFMEMORY;
- }
- CopyMemory(*Id, szIn, sizeof(szIn));
- return NOERROR;
-}
-
-
-// Will the filter accept this media type
-
-HRESULT CRendererInputPin::CheckMediaType(const CMediaType *pmt)
-{
- return m_pRenderer->CheckMediaType(pmt);
-}
-
-
-// Called when we go paused or running
-
-HRESULT CRendererInputPin::Active()
-{
- return m_pRenderer->Active();
-}
-
-
-// Called when we go into a stopped state
-
-HRESULT CRendererInputPin::Inactive()
-{
- // The caller must hold the interface lock because
- // this function uses m_bRunTimeError.
- ASSERT(CritCheckIn(&m_pRenderer->m_InterfaceLock));
-
- m_bRunTimeError = FALSE;
-
- return m_pRenderer->Inactive();
-}
-
-
-// Tell derived classes about the media type agreed
-
-HRESULT CRendererInputPin::SetMediaType(const CMediaType *pmt)
-{
- HRESULT hr = CBaseInputPin::SetMediaType(pmt);
- if (FAILED(hr)) {
- return hr;
- }
- return m_pRenderer->SetMediaType(pmt);
-}
-
-
-// We do not keep an event object to use when setting up a timer link with
-// the clock but are given a pointer to one by the owning object through the
-// SetNotificationObject method - this must be initialised before starting
-// We can override the default quality management process to have it always
-// draw late frames, this is currently done by having the following registry
-// key (actually an INI key) called DrawLateFrames set to 1 (default is 0)
-
-const TCHAR AMQUALITY[] = TEXT("ActiveMovie");
-const TCHAR DRAWLATEFRAMES[] = TEXT("DrawLateFrames");
-
-CBaseVideoRenderer::CBaseVideoRenderer(
- REFCLSID RenderClass, // CLSID for this renderer
- __in_opt LPCTSTR pName, // Debug ONLY description
- __inout_opt LPUNKNOWN pUnk, // Aggregated owner object
- __inout HRESULT *phr) : // General OLE return code
-
- CBaseRenderer(RenderClass,pName,pUnk,phr),
- m_cFramesDropped(0),
- m_cFramesDrawn(0),
- m_bSupplierHandlingQuality(FALSE)
-{
- ResetStreamingTimes();
-
-#ifdef PERF
- m_idTimeStamp = MSR_REGISTER(TEXT("Frame time stamp"));
- m_idEarliness = MSR_REGISTER(TEXT("Earliness fudge"));
- m_idTarget = MSR_REGISTER(TEXT("Target (mSec)"));
- m_idSchLateTime = MSR_REGISTER(TEXT("mSec late when scheduled"));
- m_idDecision = MSR_REGISTER(TEXT("Scheduler decision code"));
- m_idQualityRate = MSR_REGISTER(TEXT("Quality rate sent"));
- m_idQualityTime = MSR_REGISTER(TEXT("Quality time sent"));
- m_idWaitReal = MSR_REGISTER(TEXT("Render wait"));
- // m_idWait = MSR_REGISTER(TEXT("wait time recorded (msec)"));
- m_idFrameAccuracy = MSR_REGISTER(TEXT("Frame accuracy (msecs)"));
- m_bDrawLateFrames = GetProfileInt(AMQUALITY, DRAWLATEFRAMES, FALSE);
- //m_idSendQuality = MSR_REGISTER(TEXT("Processing Quality message"));
-
- m_idRenderAvg = MSR_REGISTER(TEXT("Render draw time Avg"));
- m_idFrameAvg = MSR_REGISTER(TEXT("FrameAvg"));
- m_idWaitAvg = MSR_REGISTER(TEXT("WaitAvg"));
- m_idDuration = MSR_REGISTER(TEXT("Duration"));
- m_idThrottle = MSR_REGISTER(TEXT("Audio-video throttle wait"));
- // m_idDebug = MSR_REGISTER(TEXT("Debug stuff"));
-#endif // PERF
-} // Constructor
-
-
-// Destructor is just a placeholder
-
-CBaseVideoRenderer::~CBaseVideoRenderer()
-{
- ASSERT(m_dwAdvise == 0);
-}
-
-
-// The timing functions in this class are called by the window object and by
-// the renderer's allocator.
-// The windows object calls timing functions as it receives media sample
-// images for drawing using GDI.
-// The allocator calls timing functions when it starts passing DCI/DirectDraw
-// surfaces which are not rendered in the same way; The decompressor writes
-// directly to the surface with no separate rendering, so those code paths
-// call direct into us. Since we only ever hand out DCI/DirectDraw surfaces
-// when we have allocated one and only one image we know there cannot be any
-// conflict between the two.
-//
-// We use timeGetTime to return the timing counts we use (since it's relative
-// performance we are interested in rather than absolute compared to a clock)
-// The window object sets the accuracy of the system clock (normally 1ms) by
-// calling timeBeginPeriod/timeEndPeriod when it changes streaming states
-
-
-// Reset all times controlling streaming.
-// Set them so that
-// 1. Frames will not initially be dropped
-// 2. The first frame will definitely be drawn (achieved by saying that there
-// has not ben a frame drawn for a long time).
-
-HRESULT CBaseVideoRenderer::ResetStreamingTimes()
-{
- m_trLastDraw = -1000; // set up as first frame since ages (1 sec) ago
- m_tStreamingStart = timeGetTime();
- m_trRenderAvg = 0;
- m_trFrameAvg = -1; // -1000 fps == "unset"
- m_trDuration = 0; // 0 - strange value
- m_trRenderLast = 0;
- m_trWaitAvg = 0;
- m_tRenderStart = 0;
- m_cFramesDrawn = 0;
- m_cFramesDropped = 0;
- m_iTotAcc = 0;
- m_iSumSqAcc = 0;
- m_iSumSqFrameTime = 0;
- m_trFrame = 0; // hygeine - not really needed
- m_trLate = 0; // hygeine - not really needed
- m_iSumFrameTime = 0;
- m_nNormal = 0;
- m_trEarliness = 0;
- m_trTarget = -300000; // 30mSec early
- m_trThrottle = 0;
- m_trRememberStampForPerf = 0;
-
-#ifdef PERF
- m_trRememberFrameForPerf = 0;
-#endif
-
- return NOERROR;
-} // ResetStreamingTimes
-
-
-// Reset all times controlling streaming. Note that we're now streaming. We
-// don't need to set the rendering event to have the source filter released
-// as it is done during the Run processing. When we are run we immediately
-// release the source filter thread and draw any image waiting (that image
-// may already have been drawn once as a poster frame while we were paused)
-
-HRESULT CBaseVideoRenderer::OnStartStreaming()
-{
- ResetStreamingTimes();
- return NOERROR;
-} // OnStartStreaming
-
-
-// Called at end of streaming. Fixes times for property page report
-
-HRESULT CBaseVideoRenderer::OnStopStreaming()
-{
- m_tStreamingStart = timeGetTime()-m_tStreamingStart;
- return NOERROR;
-} // OnStopStreaming
-
-
-// Called when we start waiting for a rendering event.
-// Used to update times spent waiting and not waiting.
-
-void CBaseVideoRenderer::OnWaitStart()
-{
- MSR_START(m_idWaitReal);
-} // OnWaitStart
-
-
-// Called when we are awoken from the wait in the window OR by our allocator
-// when it is hanging around until the next sample is due for rendering on a
-// DCI/DirectDraw surface. We add the wait time into our rolling average.
-// We grab the interface lock so that we're serialised with the application
-// thread going through the run code - which in due course ends up calling
-// ResetStreaming times - possibly as we run through this section of code
-
-void CBaseVideoRenderer::OnWaitEnd()
-{
-#ifdef PERF
- MSR_STOP(m_idWaitReal);
- // for a perf build we want to know just exactly how late we REALLY are.
- // even if this means that we have to look at the clock again.
-
- REFERENCE_TIME trRealStream; // the real time now expressed as stream time.
-#if 0
- m_pClock->GetTime(&trRealStream); // Calling clock here causes W95 deadlock!
-#else
- // We will be discarding overflows like mad here!
- // This is wrong really because timeGetTime() can wrap but it's
- // only for PERF
- REFERENCE_TIME tr = timeGetTime()*10000;
- trRealStream = tr + m_llTimeOffset;
-#endif
- trRealStream -= m_tStart; // convert to stream time (this is a reftime)
-
- if (m_trRememberStampForPerf==0) {
- // This is probably the poster frame at the start, and it is not scheduled
- // in the usual way at all. Just count it. The rememberstamp gets set
- // in ShouldDrawSampleNow, so this does invalid frame recording until we
- // actually start playing.
- PreparePerformanceData(0, 0);
- } else {
- int trLate = (int)(trRealStream - m_trRememberStampForPerf);
- int trFrame = (int)(tr - m_trRememberFrameForPerf);
- PreparePerformanceData(trLate, trFrame);
- }
- m_trRememberFrameForPerf = tr;
-#endif //PERF
-} // OnWaitEnd
-
-
-// Put data on one side that describes the lateness of the current frame.
-// We don't yet know whether it will actually be drawn. In direct draw mode,
-// this decision is up to the filter upstream, and it could change its mind.
-// The rules say that if it did draw it must call Receive(). One way or
-// another we eventually get into either OnRenderStart or OnDirectRender and
-// these both call RecordFrameLateness to update the statistics.
-
-void CBaseVideoRenderer::PreparePerformanceData(int trLate, int trFrame)
-{
- m_trLate = trLate;
- m_trFrame = trFrame;
-} // PreparePerformanceData
-
-
-// update the statistics:
-// m_iTotAcc, m_iSumSqAcc, m_iSumSqFrameTime, m_iSumFrameTime, m_cFramesDrawn
-// Note that because the properties page reports using these variables,
-// 1. We need to be inside a critical section
-// 2. They must all be updated together. Updating the sums here and the count
-// elsewhere can result in imaginary jitter (i.e. attempts to find square roots
-// of negative numbers) in the property page code.
-
-void CBaseVideoRenderer::RecordFrameLateness(int trLate, int trFrame)
-{
- // Record how timely we are.
- int tLate = trLate/10000;
-
- // Best estimate of moment of appearing on the screen is average of
- // start and end draw times. Here we have only the end time. This may
- // tend to show us as spuriously late by up to 1/2 frame rate achieved.
- // Decoder probably monitors draw time. We don't bother.
- MSR_INTEGER( m_idFrameAccuracy, tLate );
-
- // This is a kludge - we can get frames that are very late
- // especially (at start-up) and they invalidate the statistics.
- // So ignore things that are more than 1 sec off.
- if (tLate>1000 || tLate<-1000) {
- if (m_cFramesDrawn<=1) {
- tLate = 0;
- } else if (tLate>0) {
- tLate = 1000;
- } else {
- tLate = -1000;
- }
- }
- // The very first frame often has a invalid time, so don't
- // count it into the statistics. (???)
- if (m_cFramesDrawn>1) {
- m_iTotAcc += tLate;
- m_iSumSqAcc += (tLate*tLate);
- }
-
- // calculate inter-frame time. Doesn't make sense for first frame
- // second frame suffers from invalid first frame stamp.
- if (m_cFramesDrawn>2) {
- int tFrame = trFrame/10000; // convert to mSec else it overflows
-
- // This is a kludge. It can overflow anyway (a pause can cause
- // a very long inter-frame time) and it overflows at 2**31/10**7
- // or about 215 seconds i.e. 3min 35sec
- if (tFrame>1000||tFrame<0) tFrame = 1000;
- m_iSumSqFrameTime += tFrame*tFrame;
- ASSERT(m_iSumSqFrameTime>=0);
- m_iSumFrameTime += tFrame;
- }
- ++m_cFramesDrawn;
-
-} // RecordFrameLateness
-
-
-void CBaseVideoRenderer::ThrottleWait()
-{
- if (m_trThrottle>0) {
- int iThrottle = m_trThrottle/10000; // convert to mSec
- MSR_INTEGER( m_idThrottle, iThrottle);
- DbgLog((LOG_TRACE, 0, TEXT("Throttle %d ms"), iThrottle));
- Sleep(iThrottle);
- } else {
- Sleep(0);
- }
-} // ThrottleWait
-
-
-// Whenever a frame is rendered it goes though either OnRenderStart
-// or OnDirectRender. Data that are generated during ShouldDrawSample
-// are added to the statistics by calling RecordFrameLateness from both
-// these two places.
-
-// Called in place of OnRenderStart..OnRenderEnd
-// When a DirectDraw image is drawn
-void CBaseVideoRenderer::OnDirectRender(IMediaSample *pMediaSample)
-{
- m_trRenderAvg = 0;
- m_trRenderLast = 5000000; // If we mode switch, we do NOT want this
- // to inhibit the new average getting going!
- // so we set it to half a second
- // MSR_INTEGER(m_idRenderAvg, m_trRenderAvg/10000);
- RecordFrameLateness(m_trLate, m_trFrame);
- ThrottleWait();
-} // OnDirectRender
-
-
-// Called just before we start drawing. All we do is to get the current clock
-// time (from the system) and return. We have to store the start render time
-// in a member variable because it isn't used until we complete the drawing
-// The rest is just performance logging.
-
-void CBaseVideoRenderer::OnRenderStart(IMediaSample *pMediaSample)
-{
- RecordFrameLateness(m_trLate, m_trFrame);
- m_tRenderStart = timeGetTime();
-} // OnRenderStart
-
-
-// Called directly after drawing an image. We calculate the time spent in the
-// drawing code and if this doesn't appear to have any odd looking spikes in
-// it then we add it to the current average draw time. Measurement spikes may
-// occur if the drawing thread is interrupted and switched to somewhere else.
-
-void CBaseVideoRenderer::OnRenderEnd(IMediaSample *pMediaSample)
-{
- // The renderer time can vary erratically if we are interrupted so we do
- // some smoothing to help get more sensible figures out but even that is
- // not enough as figures can go 9,10,9,9,83,9 and we must disregard 83
-
- int tr = (timeGetTime() - m_tRenderStart)*10000; // convert mSec->UNITS
- if (tr < m_trRenderAvg*2 || tr < 2 * m_trRenderLast) {
- // DO_MOVING_AVG(m_trRenderAvg, tr);
- m_trRenderAvg = (tr + (AVGPERIOD-1)*m_trRenderAvg)/AVGPERIOD;
- }
- m_trRenderLast = tr;
- ThrottleWait();
-} // OnRenderEnd
-
-
-STDMETHODIMP CBaseVideoRenderer::SetSink( IQualityControl * piqc)
-{
-
- m_pQSink = piqc;
-
- return NOERROR;
-} // SetSink
-
-
-STDMETHODIMP CBaseVideoRenderer::Notify( IBaseFilter * pSelf, Quality q)
-{
- // NOTE: We are NOT getting any locks here. We could be called
- // asynchronously and possibly even on a time critical thread of
- // someone else's - so we do the minumum. We only set one state
- // variable (an integer) and if that happens to be in the middle
- // of another thread reading it they will just get either the new
- // or the old value. Locking would achieve no more than this.
-
- // It might be nice to check that we are being called from m_pGraph, but
- // it turns out to be a millisecond or so per throw!
-
- // This is heuristics, these numbers are aimed at being "what works"
- // rather than anything based on some theory.
- // We use a hyperbola because it's easy to calculate and it includes
- // a panic button asymptote (which we push off just to the left)
- // The throttling fits the following table (roughly)
- // Proportion Throttle (msec)
- // >=1000 0
- // 900 3
- // 800 7
- // 700 11
- // 600 17
- // 500 25
- // 400 35
- // 300 50
- // 200 72
- // 125 100
- // 100 112
- // 50 146
- // 0 200
-
- // (some evidence that we could go for a sharper kink - e.g. no throttling
- // until below the 750 mark - might give fractionally more frames on a
- // P60-ish machine). The easy way to get these coefficients is to use
- // Renbase.xls follow the instructions therein using excel solver.
-
- if (q.Proportion>=1000) { m_trThrottle = 0; }
- else {
- // The DWORD is to make quite sure I get unsigned arithmetic
- // as the constant is between 2**31 and 2**32
- m_trThrottle = -330000 + (388880000/(q.Proportion+167));
- }
- return NOERROR;
-} // Notify
-
-
-// Send a message to indicate what our supplier should do about quality.
-// Theory:
-// What a supplier wants to know is "is the frame I'm working on NOW
-// going to be late?".
-// F1 is the frame at the supplier (as above)
-// Tf1 is the due time for F1
-// T1 is the time at that point (NOW!)
-// Tr1 is the time that f1 WILL actually be rendered
-// L1 is the latency of the graph for frame F1 = Tr1-T1
-// D1 (for delay) is how late F1 will be beyond its due time i.e.
-// D1 = (Tr1-Tf1) which is what the supplier really wants to know.
-// Unfortunately Tr1 is in the future and is unknown, so is L1
-//
-// We could estimate L1 by its value for a previous frame,
-// L0 = Tr0-T0 and work off
-// D1' = ((T1+L0)-Tf1) = (T1 + (Tr0-T0) -Tf1)
-// Rearranging terms:
-// D1' = (T1-T0) + (Tr0-Tf1)
-// adding (Tf0-Tf0) and rearranging again:
-// = (T1-T0) + (Tr0-Tf0) + (Tf0-Tf1)
-// = (T1-T0) - (Tf1-Tf0) + (Tr0-Tf0)
-// But (Tr0-Tf0) is just D0 - how late frame zero was, and this is the
-// Late field in the quality message that we send.
-// The other two terms just state what correction should be applied before
-// using the lateness of F0 to predict the lateness of F1.
-// (T1-T0) says how much time has actually passed (we have lost this much)
-// (Tf1-Tf0) says how much time should have passed if we were keeping pace
-// (we have gained this much).
-//
-// Suppliers should therefore work off:
-// Quality.Late + (T1-T0) - (Tf1-Tf0)
-// and see if this is "acceptably late" or even early (i.e. negative).
-// They get T1 and T0 by polling the clock, they get Tf1 and Tf0 from
-// the time stamps in the frames. They get Quality.Late from us.
-//
-
-HRESULT CBaseVideoRenderer::SendQuality(REFERENCE_TIME trLate,
- REFERENCE_TIME trRealStream)
-{
- Quality q;
- HRESULT hr;
-
- // If we are the main user of time, then report this as Flood/Dry.
- // If our suppliers are, then report it as Famine/Glut.
- //
- // We need to take action, but avoid hunting. Hunting is caused by
- // 1. Taking too much action too soon and overshooting
- // 2. Taking too long to react (so averaging can CAUSE hunting).
- //
- // The reason why we use trLate as well as Wait is to reduce hunting;
- // if the wait time is coming down and about to go into the red, we do
- // NOT want to rely on some average which is only telling is that it used
- // to be OK once.
-
- q.TimeStamp = (REFERENCE_TIME)trRealStream;
-
- if (m_trFrameAvg<0) {
- q.Type = Famine; // guess
- }
- // Is the greater part of the time taken bltting or something else
- else if (m_trFrameAvg > 2*m_trRenderAvg) {
- q.Type = Famine; // mainly other
- } else {
- q.Type = Flood; // mainly bltting
- }
-
- q.Proportion = 1000; // default
-
- if (m_trFrameAvg<0) {
- // leave it alone - we don't know enough
- }
- else if ( trLate> 0 ) {
- // try to catch up over the next second
- // We could be Really, REALLY late, but rendering all the frames
- // anyway, just because it's so cheap.
-
- q.Proportion = 1000 - (int)((trLate)/(UNITS/1000));
- if (q.Proportion<500) {
- q.Proportion = 500; // don't go daft. (could've been negative!)
- } else {
- }
-
- } else if ( m_trWaitAvg>20000
- && trLate<-20000
- ){
- // Go cautiously faster - aim at 2mSec wait.
- if (m_trWaitAvg>=m_trFrameAvg) {
- // This can happen because of some fudges.
- // The waitAvg is how long we originally planned to wait
- // The frameAvg is more honest.
- // It means that we are spending a LOT of time waiting
- q.Proportion = 2000; // double.
- } else {
- if (m_trFrameAvg+20000 > m_trWaitAvg) {
- q.Proportion
- = 1000 * (m_trFrameAvg / (m_trFrameAvg + 20000 - m_trWaitAvg));
- } else {
- // We're apparently spending more than the whole frame time waiting.
- // Assume that the averages are slightly out of kilter, but that we
- // are indeed doing a lot of waiting. (This leg probably never
- // happens, but the code avoids any potential divide by zero).
- q.Proportion = 2000;
- }
- }
-
- if (q.Proportion>2000) {
- q.Proportion = 2000; // don't go crazy.
- }
- }
-
- // Tell the supplier how late frames are when they get rendered
- // That's how late we are now.
- // If we are in directdraw mode then the guy upstream can see the drawing
- // times and we'll just report on the start time. He can figure out any
- // offset to apply. If we are in DIB Section mode then we will apply an
- // extra offset which is half of our drawing time. This is usually small
- // but can sometimes be the dominant effect. For this we will use the
- // average drawing time rather than the last frame. If the last frame took
- // a long time to draw and made us late, that's already in the lateness
- // figure. We should not add it in again unless we expect the next frame
- // to be the same. We don't, we expect the average to be a better shot.
- // In direct draw mode the RenderAvg will be zero.
-
- q.Late = trLate + m_trRenderAvg/2;
-
- // log what we're doing
- MSR_INTEGER(m_idQualityRate, q.Proportion);
- MSR_INTEGER( m_idQualityTime, (int)q.Late / 10000 );
-
- // A specific sink interface may be set through IPin
-
- if (m_pQSink==NULL) {
- // Get our input pin's peer. We send quality management messages
- // to any nominated receiver of these things (set in the IPin
- // interface), or else to our source filter.
-
- IQualityControl *pQC = NULL;
- IPin *pOutputPin = m_pInputPin->GetConnected();
- ASSERT(pOutputPin != NULL);
-
- // And get an AddRef'd quality control interface
-
- hr = pOutputPin->QueryInterface(IID_IQualityControl,(void**) &pQC);
- if (SUCCEEDED(hr)) {
- m_pQSink = pQC;
- }
- }
- if (m_pQSink) {
- return m_pQSink->Notify(this,q);
- }
-
- return S_FALSE;
-
-} // SendQuality
-
-
-// We are called with a valid IMediaSample image to decide whether this is to
-// be drawn or not. There must be a reference clock in operation.
-// Return S_OK if it is to be drawn Now (as soon as possible)
-// Return S_FALSE if it is to be drawn when it's due
-// Return an error if we want to drop it
-// m_nNormal=-1 indicates that we dropped the previous frame and so this
-// one should be drawn early. Respect it and update it.
-// Use current stream time plus a number of heuristics (detailed below)
-// to make the decision
-
-HRESULT CBaseVideoRenderer::ShouldDrawSampleNow(IMediaSample *pMediaSample,
- __inout REFERENCE_TIME *ptrStart,
- __inout REFERENCE_TIME *ptrEnd)
-{
-
- // Don't call us unless there's a clock interface to synchronise with
- ASSERT(m_pClock);
-
- MSR_INTEGER(m_idTimeStamp, (int)((*ptrStart)>>32)); // high order 32 bits
- MSR_INTEGER(m_idTimeStamp, (int)(*ptrStart)); // low order 32 bits
-
- // We lose a bit of time depending on the monitor type waiting for the next
- // screen refresh. On average this might be about 8mSec - so it will be
- // later than we think when the picture appears. To compensate a bit
- // we bias the media samples by -8mSec i.e. 80000 UNITs.
- // We don't ever make a stream time negative (call it paranoia)
- if (*ptrStart>=80000) {
- *ptrStart -= 80000;
- *ptrEnd -= 80000; // bias stop to to retain valid frame duration
- }
-
- // Cache the time stamp now. We will want to compare what we did with what
- // we started with (after making the monitor allowance).
- m_trRememberStampForPerf = *ptrStart;
-
- // Get reference times (current and late)
- REFERENCE_TIME trRealStream; // the real time now expressed as stream time.
- m_pClock->GetTime(&trRealStream);
-#ifdef PERF
- // While the reference clock is expensive:
- // Remember the offset from timeGetTime and use that.
- // This overflows all over the place, but when we subtract to get
- // differences the overflows all cancel out.
- m_llTimeOffset = trRealStream-timeGetTime()*10000;
-#endif
- trRealStream -= m_tStart; // convert to stream time (this is a reftime)
-
- // We have to wory about two versions of "lateness". The truth, which we
- // try to work out here and the one measured against m_trTarget which
- // includes long term feedback. We report statistics against the truth
- // but for operational decisions we work to the target.
- // We use TimeDiff to make sure we get an integer because we
- // may actually be late (or more likely early if there is a big time
- // gap) by a very long time.
- const int trTrueLate = TimeDiff(trRealStream - *ptrStart);
- const int trLate = trTrueLate;
-
- MSR_INTEGER(m_idSchLateTime, trTrueLate/10000);
-
- // Send quality control messages upstream, measured against target
- HRESULT hr = SendQuality(trLate, trRealStream);
- // Note: the filter upstream is allowed to this FAIL meaning "you do it".
- m_bSupplierHandlingQuality = (hr==S_OK);
-
- // Decision time! Do we drop, draw when ready or draw immediately?
-
- const int trDuration = (int)(*ptrEnd - *ptrStart);
- {
- // We need to see if the frame rate of the file has just changed.
- // This would make comparing our previous frame rate with the current
- // frame rate inefficent. Hang on a moment though. I've seen files
- // where the frames vary between 33 and 34 mSec so as to average
- // 30fps. A minor variation like that won't hurt us.
- int t = m_trDuration/32;
- if ( trDuration > m_trDuration+t
- || trDuration < m_trDuration-t
- ) {
- // There's a major variation. Reset the average frame rate to
- // exactly the current rate to disable decision 9002 for this frame,
- // and remember the new rate.
- m_trFrameAvg = trDuration;
- m_trDuration = trDuration;
- }
- }
-
- MSR_INTEGER(m_idEarliness, m_trEarliness/10000);
- MSR_INTEGER(m_idRenderAvg, m_trRenderAvg/10000);
- MSR_INTEGER(m_idFrameAvg, m_trFrameAvg/10000);
- MSR_INTEGER(m_idWaitAvg, m_trWaitAvg/10000);
- MSR_INTEGER(m_idDuration, trDuration/10000);
-
-#ifdef PERF
- if (S_OK==pMediaSample->IsDiscontinuity()) {
- MSR_INTEGER(m_idDecision, 9000);
- }
-#endif
-
- // Control the graceful slide back from slow to fast machine mode.
- // After a frame drop accept an early frame and set the earliness to here
- // If this frame is already later than the earliness then slide it to here
- // otherwise do the standard slide (reduce by about 12% per frame).
- // Note: earliness is normally NEGATIVE
- BOOL bJustDroppedFrame
- = ( m_bSupplierHandlingQuality
- // Can't use the pin sample properties because we might
- // not be in Receive when we call this
- && (S_OK == pMediaSample->IsDiscontinuity()) // he just dropped one
- )
- || (m_nNormal==-1); // we just dropped one
-
-
- // Set m_trEarliness (slide back from slow to fast machine mode)
- if (trLate>0) {
- m_trEarliness = 0; // we are no longer in fast machine mode at all!
- } else if ( (trLate>=m_trEarliness) || bJustDroppedFrame) {
- m_trEarliness = trLate; // Things have slipped of their own accord
- } else {
- m_trEarliness = m_trEarliness - m_trEarliness/8; // graceful slide
- }
-
- // prepare the new wait average - but don't pollute the old one until
- // we have finished with it.
- int trWaitAvg;
- {
- // We never mix in a negative wait. This causes us to believe in fast machines
- // slightly more.
- int trL = trLate<0 ? -trLate : 0;
- trWaitAvg = (trL + m_trWaitAvg*(AVGPERIOD-1))/AVGPERIOD;
- }
-
-
- int trFrame;
- {
- REFERENCE_TIME tr = trRealStream - m_trLastDraw; // Cd be large - 4 min pause!
- if (tr>10000000) {
- tr = 10000000; // 1 second - arbitrarily.
- }
- trFrame = int(tr);
- }
-
- // We will DRAW this frame IF...
- if (
- // ...the time we are spending drawing is a small fraction of the total
- // observed inter-frame time so that dropping it won't help much.
- (3*m_trRenderAvg <= m_trFrameAvg)
-
- // ...or our supplier is NOT handling things and the next frame would
- // be less timely than this one or our supplier CLAIMS to be handling
- // things, and is now less than a full FOUR frames late.
- || ( m_bSupplierHandlingQuality
- ? (trLate <= trDuration*4)
- : (trLate+trLate < trDuration)
- )
-
- // ...or we are on average waiting for over eight milliseconds then
- // this may be just a glitch. Draw it and we'll hope to catch up.
- || (m_trWaitAvg > 80000)
-
- // ...or we haven't drawn an image for over a second. We will update
- // the display, which stops the video looking hung.
- // Do this regardless of how late this media sample is.
- || ((trRealStream - m_trLastDraw) > UNITS)
-
- ) {
- HRESULT Result;
-
- // We are going to play this frame. We may want to play it early.
- // We will play it early if we think we are in slow machine mode.
- // If we think we are NOT in slow machine mode, we will still play
- // it early by m_trEarliness as this controls the graceful slide back.
- // and in addition we aim at being m_trTarget late rather than "on time".
-
- BOOL bPlayASAP = FALSE;
-
- // we will play it AT ONCE (slow machine mode) if...
-
- // ...we are playing catch-up
- if ( bJustDroppedFrame) {
- bPlayASAP = TRUE;
- MSR_INTEGER(m_idDecision, 9001);
- }
-
- // ...or if we are running below the true frame rate
- // exact comparisons are glitchy, for these measurements,
- // so add an extra 5% or so
- else if ( (m_trFrameAvg > trDuration + trDuration/16)
-
- // It's possible to get into a state where we are losing ground, but
- // are a very long way ahead. To avoid this or recover from it
- // we refuse to play early by more than 10 frames.
- && (trLate > - trDuration*10)
- ){
- bPlayASAP = TRUE;
- MSR_INTEGER(m_idDecision, 9002);
- }
-#if 0
- // ...or if we have been late and are less than one frame early
- else if ( (trLate + trDuration > 0)
- && (m_trWaitAvg<=20000)
- ) {
- bPlayASAP = TRUE;
- MSR_INTEGER(m_idDecision, 9003);
- }
-#endif
- // We will NOT play it at once if we are grossly early. On very slow frame
- // rate movies - e.g. clock.avi - it is not a good idea to leap ahead just
- // because we got starved (for instance by the net) and dropped one frame
- // some time or other. If we are more than 900mSec early, then wait.
- if (trLate<-9000000) {
- bPlayASAP = FALSE;
- }
-
- if (bPlayASAP) {
-
- m_nNormal = 0;
- MSR_INTEGER(m_idDecision, 0);
- // When we are here, we are in slow-machine mode. trLate may well
- // oscillate between negative and positive when the supplier is
- // dropping frames to keep sync. We should not let that mislead
- // us into thinking that we have as much as zero spare time!
- // We just update with a zero wait.
- m_trWaitAvg = (m_trWaitAvg*(AVGPERIOD-1))/AVGPERIOD;
-
- // Assume that we draw it immediately. Update inter-frame stats
- m_trFrameAvg = (trFrame + m_trFrameAvg*(AVGPERIOD-1))/AVGPERIOD;
-#ifndef PERF
- // If this is NOT a perf build, then report what we know so far
- // without looking at the clock any more. This assumes that we
- // actually wait for exactly the time we hope to. It also reports
- // how close we get to the manipulated time stamps that we now have
- // rather than the ones we originally started with. It will
- // therefore be a little optimistic. However it's fast.
- PreparePerformanceData(trTrueLate, trFrame);
-#endif
- m_trLastDraw = trRealStream;
- if (m_trEarliness > trLate) {
- m_trEarliness = trLate; // if we are actually early, this is neg
- }
- Result = S_OK; // Draw it now
-
- } else {
- ++m_nNormal;
- // Set the average frame rate to EXACTLY the ideal rate.
- // If we are exiting slow-machine mode then we will have caught up
- // and be running ahead, so as we slide back to exact timing we will
- // have a longer than usual gap at this point. If we record this
- // real gap then we'll think that we're running slow and go back
- // into slow-machine mode and vever get it straight.
- m_trFrameAvg = trDuration;
- MSR_INTEGER(m_idDecision, 1);
-
- // Play it early by m_trEarliness and by m_trTarget
-
- {
- int trE = m_trEarliness;
- if (trE < -m_trFrameAvg) {
- trE = -m_trFrameAvg;
- }
- *ptrStart += trE; // N.B. earliness is negative
- }
-
- int Delay = -trTrueLate;
- Result = Delay<=0 ? S_OK : S_FALSE; // OK = draw now, FALSE = wait
-
- m_trWaitAvg = trWaitAvg;
-
- // Predict when it will actually be drawn and update frame stats
-
- if (Result==S_FALSE) { // We are going to wait
- trFrame = TimeDiff(*ptrStart-m_trLastDraw);
- m_trLastDraw = *ptrStart;
- } else {
- // trFrame is already = trRealStream-m_trLastDraw;
- m_trLastDraw = trRealStream;
- }
-#ifndef PERF
- int iAccuracy;
- if (Delay>0) {
- // Report lateness based on when we intend to play it
- iAccuracy = TimeDiff(*ptrStart-m_trRememberStampForPerf);
- } else {
- // Report lateness based on playing it *now*.
- iAccuracy = trTrueLate; // trRealStream-RememberStampForPerf;
- }
- PreparePerformanceData(iAccuracy, trFrame);
-#endif
- }
- return Result;
- }
-
- // We are going to drop this frame!
- // Of course in DirectDraw mode the guy upstream may draw it anyway.
-
- // This will probably give a large negative wack to the wait avg.
- m_trWaitAvg = trWaitAvg;
-
-#ifdef PERF
- // Respect registry setting - debug only!
- if (m_bDrawLateFrames) {
- return S_OK; // draw it when it's ready
- } // even though it's late.
-#endif
-
- // We are going to drop this frame so draw the next one early
- // n.b. if the supplier is doing direct draw then he may draw it anyway
- // but he's doing something funny to arrive here in that case.
-
- MSR_INTEGER(m_idDecision, 2);
- m_nNormal = -1;
- return E_FAIL; // drop it
-
-} // ShouldDrawSampleNow
-
-
-// NOTE we're called by both the window thread and the source filter thread
-// so we have to be protected by a critical section (locked before called)
-// Also, when the window thread gets signalled to render an image, it always
-// does so regardless of how late it is. All the degradation is done when we
-// are scheduling the next sample to be drawn. Hence when we start an advise
-// link to draw a sample, that sample's time will always become the last one
-// drawn - unless of course we stop streaming in which case we cancel links
-
-BOOL CBaseVideoRenderer::ScheduleSample(IMediaSample *pMediaSample)
-{
- // We override ShouldDrawSampleNow to add quality management
-
- BOOL bDrawImage = CBaseRenderer::ScheduleSample(pMediaSample);
- if (bDrawImage == FALSE) {
- ++m_cFramesDropped;
- return FALSE;
- }
-
- // m_cFramesDrawn must NOT be updated here. It has to be updated
- // in RecordFrameLateness at the same time as the other statistics.
- return TRUE;
-}
-
-
-// Implementation of IQualProp interface needed to support the property page
-// This is how the property page gets the data out of the scheduler. We are
-// passed into the constructor the owning object in the COM sense, this will
-// either be the video renderer or an external IUnknown if we're aggregated.
-// We initialise our CUnknown base class with this interface pointer. Then
-// all we have to do is to override NonDelegatingQueryInterface to expose
-// our IQualProp interface. The AddRef and Release are handled automatically
-// by the base class and will be passed on to the appropriate outer object
-
-STDMETHODIMP CBaseVideoRenderer::get_FramesDroppedInRenderer(__out int *pcFramesDropped)
-{
- CheckPointer(pcFramesDropped,E_POINTER);
- CAutoLock cVideoLock(&m_InterfaceLock);
- *pcFramesDropped = m_cFramesDropped;
- return NOERROR;
-} // get_FramesDroppedInRenderer
-
-
-// Set *pcFramesDrawn to the number of frames drawn since
-// streaming started.
-
-STDMETHODIMP CBaseVideoRenderer::get_FramesDrawn( int *pcFramesDrawn)
-{
- CheckPointer(pcFramesDrawn,E_POINTER);
- CAutoLock cVideoLock(&m_InterfaceLock);
- *pcFramesDrawn = m_cFramesDrawn;
- return NOERROR;
-} // get_FramesDrawn
-
-
-// Set iAvgFrameRate to the frames per hundred secs since
-// streaming started. 0 otherwise.
-
-STDMETHODIMP CBaseVideoRenderer::get_AvgFrameRate( int *piAvgFrameRate)
-{
- CheckPointer(piAvgFrameRate,E_POINTER);
- CAutoLock cVideoLock(&m_InterfaceLock);
-
- int t;
- if (m_bStreaming) {
- t = timeGetTime()-m_tStreamingStart;
- } else {
- t = m_tStreamingStart;
- }
-
- if (t<=0) {
- *piAvgFrameRate = 0;
- ASSERT(m_cFramesDrawn == 0);
- } else {
- // i is frames per hundred seconds
- *piAvgFrameRate = MulDiv(100000, m_cFramesDrawn, t);
- }
- return NOERROR;
-} // get_AvgFrameRate
-
-
-// Set *piAvg to the average sync offset since streaming started
-// in mSec. The sync offset is the time in mSec between when the frame
-// should have been drawn and when the frame was actually drawn.
-
-STDMETHODIMP CBaseVideoRenderer::get_AvgSyncOffset(__out int *piAvg)
-{
- CheckPointer(piAvg,E_POINTER);
- CAutoLock cVideoLock(&m_InterfaceLock);
-
- if (NULL==m_pClock) {
- *piAvg = 0;
- return NOERROR;
- }
-
- // Note that we didn't gather the stats on the first frame
- // so we use m_cFramesDrawn-1 here
- if (m_cFramesDrawn<=1) {
- *piAvg = 0;
- } else {
- *piAvg = (int)(m_iTotAcc / (m_cFramesDrawn-1));
- }
- return NOERROR;
-} // get_AvgSyncOffset
-
-
-// To avoid dragging in the maths library - a cheap
-// approximate integer square root.
-// We do this by getting a starting guess which is between 1
-// and 2 times too large, followed by THREE iterations of
-// Newton Raphson. (That will give accuracy to the nearest mSec
-// for the range in question - roughly 0..1000)
-//
-// It would be faster to use a linear interpolation and ONE NR, but
-// who cares. If anyone does - the best linear interpolation is
-// to approximates sqrt(x) by
-// y = x * (sqrt(2)-1) + 1 - 1/sqrt(2) + 1/(8*(sqrt(2)-1))
-// 0r y = x*0.41421 + 0.59467
-// This minimises the maximal error in the range in question.
-// (error is about +0.008883 and then one NR will give error .0000something
-// (Of course these are integers, so you can't just multiply by 0.41421
-// you'd have to do some sort of MulDiv).
-// Anyone wanna check my maths? (This is only for a property display!)
-
-int isqrt(int x)
-{
- int s = 1;
- // Make s an initial guess for sqrt(x)
- if (x > 0x40000000) {
- s = 0x8000; // prevent any conceivable closed loop
- } else {
- while (s*s<x) { // loop cannot possible go more than 31 times
- s = 2*s; // normally it goes about 6 times
- }
- // Three NR iterations.
- if (x==0) {
- s= 0; // Wouldn't it be tragic to divide by zero whenever our
- // accuracy was perfect!
- } else {
- s = (s*s+x)/(2*s);
- if (s>=0) s = (s*s+x)/(2*s);
- if (s>=0) s = (s*s+x)/(2*s);
- }
- }
- return s;
-}
-
-//
-// Do estimates for standard deviations for per-frame
-// statistics
-//
-HRESULT CBaseVideoRenderer::GetStdDev(
- int nSamples,
- __out int *piResult,
- LONGLONG llSumSq,
- LONGLONG iTot
-)
-{
- CheckPointer(piResult,E_POINTER);
- CAutoLock cVideoLock(&m_InterfaceLock);
-
- if (NULL==m_pClock) {
- *piResult = 0;
- return NOERROR;
- }
-
- // If S is the Sum of the Squares of observations and
- // T the Total (i.e. sum) of the observations and there were
- // N observations, then an estimate of the standard deviation is
- // sqrt( (S - T**2/N) / (N-1) )
-
- if (nSamples<=1) {
- *piResult = 0;
- } else {
- LONGLONG x;
- // First frames have invalid stamps, so we get no stats for them
- // So we need 2 frames to get 1 datum, so N is cFramesDrawn-1
-
- // so we use m_cFramesDrawn-1 here
- x = llSumSq - llMulDiv(iTot, iTot, nSamples, 0);
- x = x / (nSamples-1);
- ASSERT(x>=0);
- *piResult = isqrt((LONG)x);
- }
- return NOERROR;
-}
-
-// Set *piDev to the standard deviation in mSec of the sync offset
-// of each frame since streaming started.
-
-STDMETHODIMP CBaseVideoRenderer::get_DevSyncOffset(__out int *piDev)
-{
- // First frames have invalid stamps, so we get no stats for them
- // So we need 2 frames to get 1 datum, so N is cFramesDrawn-1
- return GetStdDev(m_cFramesDrawn - 1,
- piDev,
- m_iSumSqAcc,
- m_iTotAcc);
-} // get_DevSyncOffset
-
-
-// Set *piJitter to the standard deviation in mSec of the inter-frame time
-// of frames since streaming started.
-
-STDMETHODIMP CBaseVideoRenderer::get_Jitter(__out int *piJitter)
-{
- // First frames have invalid stamps, so we get no stats for them
- // So second frame gives invalid inter-frame time
- // So we need 3 frames to get 1 datum, so N is cFramesDrawn-2
- return GetStdDev(m_cFramesDrawn - 2,
- piJitter,
- m_iSumSqFrameTime,
- m_iSumFrameTime);
-} // get_Jitter
-
-
-// Overidden to return our IQualProp interface
-
-STDMETHODIMP
-CBaseVideoRenderer::NonDelegatingQueryInterface(REFIID riid,__deref_out VOID **ppv)
-{
- // We return IQualProp and delegate everything else
-
- if (riid == IID_IQualProp) {
- return GetInterface( (IQualProp *)this, ppv);
- } else if (riid == IID_IQualityControl) {
- return GetInterface( (IQualityControl *)this, ppv);
- }
- return CBaseRenderer::NonDelegatingQueryInterface(riid,ppv);
-}
-
-
-// Override JoinFilterGraph so that, just before leaving
-// the graph we can send an EC_WINDOW_DESTROYED event
-
-STDMETHODIMP
-CBaseVideoRenderer::JoinFilterGraph(__inout_opt IFilterGraph *pGraph, __in_opt LPCWSTR pName)
-{
- // Since we send EC_ACTIVATE, we also need to ensure
- // we send EC_WINDOW_DESTROYED or the resource manager may be
- // holding us as a focus object
- if (!pGraph && m_pGraph) {
-
- // We were in a graph and now we're not
- // Do this properly in case we are aggregated
- IBaseFilter* pFilter = this;
- NotifyEvent(EC_WINDOW_DESTROYED, (LPARAM) pFilter, 0);
- }
- return CBaseFilter::JoinFilterGraph(pGraph, pName);
-}
-
-
-// This removes a large number of level 4 warnings from the
-// Microsoft compiler which in this case are not very useful
-#pragma warning(disable: 4514)
-
diff --git a/dll/src/baseclasses/renbase.h b/dll/src/baseclasses/renbase.h
deleted file mode 100644
index c2685bb..0000000
--- a/dll/src/baseclasses/renbase.h
+++ /dev/null
@@ -1,478 +0,0 @@
-//------------------------------------------------------------------------------
-// File: RenBase.h
-//
-// Desc: DirectShow base classes - defines a generic ActiveX base renderer
-// class.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-#ifndef __RENBASE__
-#define __RENBASE__
-
-// Forward class declarations
-
-class CBaseRenderer;
-class CBaseVideoRenderer;
-class CRendererInputPin;
-
-// This is our input pin class that channels calls to the renderer
-
-class CRendererInputPin : public CBaseInputPin
-{
-protected:
-
- CBaseRenderer *m_pRenderer;
-
-public:
-
- CRendererInputPin(__inout CBaseRenderer *pRenderer,
- __inout HRESULT *phr,
- __in_opt LPCWSTR Name);
-
- // Overriden from the base pin classes
-
- HRESULT BreakConnect();
- HRESULT CompleteConnect(IPin *pReceivePin);
- HRESULT SetMediaType(const CMediaType *pmt);
- HRESULT CheckMediaType(const CMediaType *pmt);
- HRESULT Active();
- HRESULT Inactive();
-
- // Add rendering behaviour to interface functions
-
- STDMETHODIMP QueryId(__deref_out LPWSTR *Id);
- STDMETHODIMP EndOfStream();
- STDMETHODIMP BeginFlush();
- STDMETHODIMP EndFlush();
- STDMETHODIMP Receive(IMediaSample *pMediaSample);
-
- // Helper
- IMemAllocator inline *Allocator() const
- {
- return m_pAllocator;
- }
-};
-
-// Main renderer class that handles synchronisation and state changes
-
-class CBaseRenderer : public CBaseFilter
-{
-protected:
-
- friend class CRendererInputPin;
-
- friend void CALLBACK EndOfStreamTimer(UINT uID, // Timer identifier
- UINT uMsg, // Not currently used
- DWORD_PTR dwUser, // User information
- DWORD_PTR dw1, // Windows reserved
- DWORD_PTR dw2); // Is also reserved
-
- CRendererPosPassThru *m_pPosition; // Media seeking pass by object
- CAMEvent m_RenderEvent; // Used to signal timer events
- CAMEvent m_ThreadSignal; // Signalled to release worker thread
- CAMEvent m_evComplete; // Signalled when state complete
- BOOL m_bAbort; // Stop us from rendering more data
- BOOL m_bStreaming; // Are we currently streaming
- DWORD_PTR m_dwAdvise; // Timer advise cookie
- IMediaSample *m_pMediaSample; // Current image media sample
- BOOL m_bEOS; // Any more samples in the stream
- BOOL m_bEOSDelivered; // Have we delivered an EC_COMPLETE
- CRendererInputPin *m_pInputPin; // Our renderer input pin object
- CCritSec m_InterfaceLock; // Critical section for interfaces
- CCritSec m_RendererLock; // Controls access to internals
- IQualityControl * m_pQSink; // QualityControl sink
- BOOL m_bRepaintStatus; // Can we signal an EC_REPAINT
- // Avoid some deadlocks by tracking filter during stop
- volatile BOOL m_bInReceive; // Inside Receive between PrepareReceive
- // And actually processing the sample
- REFERENCE_TIME m_SignalTime; // Time when we signal EC_COMPLETE
- UINT m_EndOfStreamTimer; // Used to signal end of stream
- CCritSec m_ObjectCreationLock; // This lock protects the creation and
- // of m_pPosition and m_pInputPin. It
- // ensures that two threads cannot create
- // either object simultaneously.
-
-public:
-
- CBaseRenderer(REFCLSID RenderClass, // CLSID for this renderer
- __in_opt LPCTSTR pName, // Debug ONLY description
- __inout_opt LPUNKNOWN pUnk, // Aggregated owner object
- __inout HRESULT *phr); // General OLE return code
-
- ~CBaseRenderer();
-
- // Overriden to say what interfaces we support and where
-
- virtual HRESULT GetMediaPositionInterface(REFIID riid, __deref_out void **ppv);
- STDMETHODIMP NonDelegatingQueryInterface(REFIID, __deref_out void **);
-
- virtual HRESULT SourceThreadCanWait(BOOL bCanWait);
-
-#ifdef DEBUG
- // Debug only dump of the renderer state
- void DisplayRendererState();
-#endif
- virtual HRESULT WaitForRenderTime();
- virtual HRESULT CompleteStateChange(FILTER_STATE OldState);
-
- // Return internal information about this filter
-
- BOOL IsEndOfStream() { return m_bEOS; };
- BOOL IsEndOfStreamDelivered() { return m_bEOSDelivered; };
- BOOL IsStreaming() { return m_bStreaming; };
- void SetAbortSignal(BOOL bAbort) { m_bAbort = bAbort; };
- virtual void OnReceiveFirstSample(IMediaSample *pMediaSample) { };
- CAMEvent *GetRenderEvent() { return &m_RenderEvent; };
-
- // Permit access to the transition state
-
- void Ready() { m_evComplete.Set(); };
- void NotReady() { m_evComplete.Reset(); };
- BOOL CheckReady() { return m_evComplete.Check(); };
-
- virtual int GetPinCount();
- virtual CBasePin *GetPin(int n);
- FILTER_STATE GetRealState();
- void SendRepaint();
- void SendNotifyWindow(IPin *pPin,HWND hwnd);
- BOOL OnDisplayChange();
- void SetRepaintStatus(BOOL bRepaint);
-
- // Override the filter and pin interface functions
-
- STDMETHODIMP Stop();
- STDMETHODIMP Pause();
- STDMETHODIMP Run(REFERENCE_TIME StartTime);
- STDMETHODIMP GetState(DWORD dwMSecs, __out FILTER_STATE *State);
- STDMETHODIMP FindPin(LPCWSTR Id, __deref_out IPin **ppPin);
-
- // These are available for a quality management implementation
-
- virtual void OnRenderStart(IMediaSample *pMediaSample);
- virtual void OnRenderEnd(IMediaSample *pMediaSample);
- virtual HRESULT OnStartStreaming() { return NOERROR; };
- virtual HRESULT OnStopStreaming() { return NOERROR; };
- virtual void OnWaitStart() { };
- virtual void OnWaitEnd() { };
- virtual void PrepareRender() { };
-
-#ifdef PERF
- REFERENCE_TIME m_trRenderStart; // Just before we started drawing
- // Set in OnRenderStart, Used in OnRenderEnd
- int m_idBaseStamp; // MSR_id for frame time stamp
- int m_idBaseRenderTime; // MSR_id for true wait time
- int m_idBaseAccuracy; // MSR_id for time frame is late (int)
-#endif
-
- // Quality management implementation for scheduling rendering
-
- virtual BOOL ScheduleSample(IMediaSample *pMediaSample);
- virtual HRESULT GetSampleTimes(IMediaSample *pMediaSample,
- __out REFERENCE_TIME *pStartTime,
- __out REFERENCE_TIME *pEndTime);
-
- virtual HRESULT ShouldDrawSampleNow(IMediaSample *pMediaSample,
- __out REFERENCE_TIME *ptrStart,
- __out REFERENCE_TIME *ptrEnd);
-
- // Lots of end of stream complexities
-
- void TimerCallback();
- void ResetEndOfStreamTimer();
- HRESULT NotifyEndOfStream();
- virtual HRESULT SendEndOfStream();
- virtual HRESULT ResetEndOfStream();
- virtual HRESULT EndOfStream();
-
- // Rendering is based around the clock
-
- void SignalTimerFired();
- virtual HRESULT CancelNotification();
- virtual HRESULT ClearPendingSample();
-
- // Called when the filter changes state
-
- virtual HRESULT Active();
- virtual HRESULT Inactive();
- virtual HRESULT StartStreaming();
- virtual HRESULT StopStreaming();
- virtual HRESULT BeginFlush();
- virtual HRESULT EndFlush();
-
- // Deal with connections and type changes
-
- virtual HRESULT BreakConnect();
- virtual HRESULT SetMediaType(const CMediaType *pmt);
- virtual HRESULT CompleteConnect(IPin *pReceivePin);
-
- // These look after the handling of data samples
-
- virtual HRESULT PrepareReceive(IMediaSample *pMediaSample);
- virtual HRESULT Receive(IMediaSample *pMediaSample);
- virtual BOOL HaveCurrentSample();
- virtual IMediaSample *GetCurrentSample();
- virtual HRESULT Render(IMediaSample *pMediaSample);
-
- // Derived classes MUST override these
- virtual HRESULT DoRenderSample(IMediaSample *pMediaSample) PURE;
- virtual HRESULT CheckMediaType(const CMediaType *) PURE;
-
- // Helper
- void WaitForReceiveToComplete();
-};
-
-
-// CBaseVideoRenderer is a renderer class (see its ancestor class) and
-// it handles scheduling of media samples so that they are drawn at the
-// correct time by the reference clock. It implements a degradation
-// strategy. Possible degradation modes are:
-// Drop frames here (only useful if the drawing takes significant time)
-// Signal supplier (upstream) to drop some frame(s) - i.e. one-off skip.
-// Signal supplier to change the frame rate - i.e. ongoing skipping.
-// Or any combination of the above.
-// In order to determine what's useful to try we need to know what's going
-// on. This is done by timing various operations (including the supplier).
-// This timing is done by using timeGetTime as it is accurate enough and
-// usually cheaper than calling the reference clock. It also tells the
-// truth if there is an audio break and the reference clock stops.
-// We provide a number of public entry points (named OnXxxStart, OnXxxEnd)
-// which the rest of the renderer calls at significant moments. These do
-// the timing.
-
-// the number of frames that the sliding averages are averaged over.
-// the rule is (1024*NewObservation + (AVGPERIOD-1) * PreviousAverage)/AVGPERIOD
-#define AVGPERIOD 4
-#define DO_MOVING_AVG(avg,obs) (avg = (1024*obs + (AVGPERIOD-1)*avg)/AVGPERIOD)
-// Spot the bug in this macro - I can't. but it doesn't work!
-
-class CBaseVideoRenderer : public CBaseRenderer, // Base renderer class
- public IQualProp, // Property page guff
- public IQualityControl // Allow throttling
-{
-protected:
-
- // Hungarian:
- // tFoo is the time Foo in mSec (beware m_tStart from filter.h)
- // trBar is the time Bar by the reference clock
-
- //******************************************************************
- // State variables to control synchronisation
- //******************************************************************
-
- // Control of sending Quality messages. We need to know whether
- // we are in trouble (e.g. frames being dropped) and where the time
- // is being spent.
-
- // When we drop a frame we play the next one early.
- // The frame after that is likely to wait before drawing and counting this
- // wait as spare time is unfair, so we count it as a zero wait.
- // We therefore need to know whether we are playing frames early or not.
-
- int m_nNormal; // The number of consecutive frames
- // drawn at their normal time (not early)
- // -1 means we just dropped a frame.
-
-#ifdef PERF
- BOOL m_bDrawLateFrames; // Don't drop any frames (debug and I'm
- // not keen on people using it!)
-#endif
-
- BOOL m_bSupplierHandlingQuality;// The response to Quality messages says
- // our supplier is handling things.
- // We will allow things to go extra late
- // before dropping frames. We will play
- // very early after he has dropped one.
-
- // Control of scheduling, frame dropping etc.
- // We need to know where the time is being spent so as to tell whether
- // we should be taking action here, signalling supplier or what.
- // The variables are initialised to a mode of NOT dropping frames.
- // They will tell the truth after a few frames.
- // We typically record a start time for an event, later we get the time
- // again and subtract to get the elapsed time, and we average this over
- // a few frames. The average is used to tell what mode we are in.
-
- // Although these are reference times (64 bit) they are all DIFFERENCES
- // between times which are small. An int will go up to 214 secs before
- // overflow. Avoiding 64 bit multiplications and divisions seems
- // worth while.
-
-
-
- // Audio-video throttling. If the user has turned up audio quality
- // very high (in principle it could be any other stream, not just audio)
- // then we can receive cries for help via the graph manager. In this case
- // we put in a wait for some time after rendering each frame.
- int m_trThrottle;
-
- // The time taken to render (i.e. BitBlt) frames controls which component
- // needs to degrade. If the blt is expensive, the renderer degrades.
- // If the blt is cheap it's done anyway and the supplier degrades.
- int m_trRenderAvg; // Time frames are taking to blt
- int m_trRenderLast; // Time for last frame blt
- int m_tRenderStart; // Just before we started drawing (mSec)
- // derived from timeGetTime.
-
- // When frames are dropped we will play the next frame as early as we can.
- // If it was a false alarm and the machine is fast we slide gently back to
- // normal timing. To do this, we record the offset showing just how early
- // we really are. This will normally be negative meaning early or zero.
- int m_trEarliness;
-
- // Target provides slow long-term feedback to try to reduce the
- // average sync offset to zero. Whenever a frame is actually rendered
- // early we add a msec or two, whenever late we take off a few.
- // We add or take off 1/32 of the error time.
- // Eventually we should be hovering around zero. For a really bad case
- // where we were (say) 300mSec off, it might take 100 odd frames to
- // settle down. The rate of change of this is intended to be slower
- // than any other mechanism in Quartz, thereby avoiding hunting.
- int m_trTarget;
-
- // The proportion of time spent waiting for the right moment to blt
- // controls whether we bother to drop a frame or whether we reckon that
- // we're doing well enough that we can stand a one-frame glitch.
- int m_trWaitAvg; // Average of last few wait times
- // (actually we just average how early
- // we were). Negative here means LATE.
-
- // The average inter-frame time.
- // This is used to calculate the proportion of the time used by the
- // three operations (supplying us, waiting, rendering)
- int m_trFrameAvg; // Average inter-frame time
- int m_trDuration; // duration of last frame.
-
-#ifdef PERF
- // Performance logging identifiers
- int m_idTimeStamp; // MSR_id for frame time stamp
- int m_idEarliness; // MSR_id for earliness fudge
- int m_idTarget; // MSR_id for Target fudge
- int m_idWaitReal; // MSR_id for true wait time
- int m_idWait; // MSR_id for wait time recorded
- int m_idFrameAccuracy; // MSR_id for time frame is late (int)
- int m_idRenderAvg; // MSR_id for Render time recorded (int)
- int m_idSchLateTime; // MSR_id for lateness at scheduler
- int m_idQualityRate; // MSR_id for Quality rate requested
- int m_idQualityTime; // MSR_id for Quality time requested
- int m_idDecision; // MSR_id for decision code
- int m_idDuration; // MSR_id for duration of a frame
- int m_idThrottle; // MSR_id for audio-video throttling
- //int m_idDebug; // MSR_id for trace style debugging
- //int m_idSendQuality; // MSR_id for timing the notifications per se
-#endif // PERF
- REFERENCE_TIME m_trRememberStampForPerf; // original time stamp of frame
- // with no earliness fudges etc.
-#ifdef PERF
- REFERENCE_TIME m_trRememberFrameForPerf; // time when previous frame rendered
-
- // debug...
- int m_idFrameAvg;
- int m_idWaitAvg;
-#endif
-
- // PROPERTY PAGE
- // This has edit fields that show the user what's happening
- // These member variables hold these counts.
-
- int m_cFramesDropped; // cumulative frames dropped IN THE RENDERER
- int m_cFramesDrawn; // Frames since streaming started seen BY THE
- // RENDERER (some may be dropped upstream)
-
- // Next two support average sync offset and standard deviation of sync offset.
- LONGLONG m_iTotAcc; // Sum of accuracies in mSec
- LONGLONG m_iSumSqAcc; // Sum of squares of (accuracies in mSec)
-
- // Next two allow jitter calculation. Jitter is std deviation of frame time.
- REFERENCE_TIME m_trLastDraw; // Time of prev frame (for inter-frame times)
- LONGLONG m_iSumSqFrameTime; // Sum of squares of (inter-frame time in mSec)
- LONGLONG m_iSumFrameTime; // Sum of inter-frame times in mSec
-
- // To get performance statistics on frame rate, jitter etc, we need
- // to record the lateness and inter-frame time. What we actually need are the
- // data above (sum, sum of squares and number of entries for each) but the data
- // is generated just ahead of time and only later do we discover whether the
- // frame was actually drawn or not. So we have to hang on to the data
- int m_trLate; // hold onto frame lateness
- int m_trFrame; // hold onto inter-frame time
-
- int m_tStreamingStart; // if streaming then time streaming started
- // else time of last streaming session
- // used for property page statistics
-#ifdef PERF
- LONGLONG m_llTimeOffset; // timeGetTime()*10000+m_llTimeOffset==ref time
-#endif
-
-public:
-
-
- CBaseVideoRenderer(REFCLSID RenderClass, // CLSID for this renderer
- __in_opt LPCTSTR pName, // Debug ONLY description
- __inout_opt LPUNKNOWN pUnk, // Aggregated owner object
- __inout HRESULT *phr); // General OLE return code
-
- ~CBaseVideoRenderer();
-
- // IQualityControl methods - Notify allows audio-video throttling
-
- STDMETHODIMP SetSink( IQualityControl * piqc);
- STDMETHODIMP Notify( IBaseFilter * pSelf, Quality q);
-
- // These provide a full video quality management implementation
-
- void OnRenderStart(IMediaSample *pMediaSample);
- void OnRenderEnd(IMediaSample *pMediaSample);
- void OnWaitStart();
- void OnWaitEnd();
- HRESULT OnStartStreaming();
- HRESULT OnStopStreaming();
- void ThrottleWait();
-
- // Handle the statistics gathering for our quality management
-
- void PreparePerformanceData(int trLate, int trFrame);
- virtual void RecordFrameLateness(int trLate, int trFrame);
- virtual void OnDirectRender(IMediaSample *pMediaSample);
- virtual HRESULT ResetStreamingTimes();
- BOOL ScheduleSample(IMediaSample *pMediaSample);
- HRESULT ShouldDrawSampleNow(IMediaSample *pMediaSample,
- __inout REFERENCE_TIME *ptrStart,
- __inout REFERENCE_TIME *ptrEnd);
-
- virtual HRESULT SendQuality(REFERENCE_TIME trLate, REFERENCE_TIME trRealStream);
- STDMETHODIMP JoinFilterGraph(__inout_opt IFilterGraph * pGraph, __in_opt LPCWSTR pName);
-
- //
- // Do estimates for standard deviations for per-frame
- // statistics
- //
- // *piResult = (llSumSq - iTot * iTot / m_cFramesDrawn - 1) /
- // (m_cFramesDrawn - 2)
- // or 0 if m_cFramesDrawn <= 3
- //
- HRESULT GetStdDev(
- int nSamples,
- __out int *piResult,
- LONGLONG llSumSq,
- LONGLONG iTot
- );
-public:
-
- // IQualProp property page support
-
- STDMETHODIMP get_FramesDroppedInRenderer(__out int *cFramesDropped);
- STDMETHODIMP get_FramesDrawn(__out int *pcFramesDrawn);
- STDMETHODIMP get_AvgFrameRate(__out int *piAvgFrameRate);
- STDMETHODIMP get_Jitter(__out int *piJitter);
- STDMETHODIMP get_AvgSyncOffset(__out int *piAvg);
- STDMETHODIMP get_DevSyncOffset(__out int *piDev);
-
- // Implement an IUnknown interface and expose IQualProp
-
- DECLARE_IUNKNOWN
- STDMETHODIMP NonDelegatingQueryInterface(REFIID riid,__deref_out VOID **ppv);
-};
-
-#endif // __RENBASE__
-
diff --git a/dll/src/baseclasses/schedule.cpp b/dll/src/baseclasses/schedule.cpp
deleted file mode 100644
index 7d79830..0000000
--- a/dll/src/baseclasses/schedule.cpp
+++ /dev/null
@@ -1,284 +0,0 @@
-//------------------------------------------------------------------------------
-// File: Schedule.cpp
-//
-// Desc: DirectShow base classes.
-//
-// Copyright (c) 1996-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-#include <streams.h>
-
-// DbgLog values (all on LOG_TIMING):
-//
-// 2 for schedulting, firing and shunting of events
-// 3 for wait delays and wake-up times of event thread
-// 4 for details of whats on the list when the thread awakes
-
-/* Construct & destructors */
-
-CAMSchedule::CAMSchedule( HANDLE ev )
-: CBaseObject(TEXT("CAMSchedule"))
-, head(&z, 0), z(0, MAX_TIME)
-, m_dwNextCookie(0), m_dwAdviseCount(0)
-, m_pAdviseCache(0), m_dwCacheCount(0)
-, m_ev( ev )
-{
- head.m_dwAdviseCookie = z.m_dwAdviseCookie = 0;
-}
-
-CAMSchedule::~CAMSchedule()
-{
- m_Serialize.Lock();
-
- // Delete cache
- CAdvisePacket * p = m_pAdviseCache;
- while (p)
- {
- CAdvisePacket *const p_next = p->m_next;
- delete p;
- p = p_next;
- }
-
- ASSERT( m_dwAdviseCount == 0 );
- // Better to be safe than sorry
- if ( m_dwAdviseCount > 0 )
- {
- DumpLinkedList();
- while ( !head.m_next->IsZ() )
- {
- head.DeleteNext();
- --m_dwAdviseCount;
- }
- }
-
- // If, in the debug version, we assert twice, it means, not only
- // did we have left over advises, but we have also let m_dwAdviseCount
- // get out of sync. with the number of advises actually on the list.
- ASSERT( m_dwAdviseCount == 0 );
-
- m_Serialize.Unlock();
-}
-
-/* Public methods */
-
-DWORD CAMSchedule::GetAdviseCount()
-{
- // No need to lock, m_dwAdviseCount is 32bits & declared volatile
- return m_dwAdviseCount;
-}
-
-REFERENCE_TIME CAMSchedule::GetNextAdviseTime()
-{
- CAutoLock lck(&m_Serialize); // Need to stop the linked list from changing
- return head.m_next->m_rtEventTime;
-}
-
-DWORD_PTR CAMSchedule::AddAdvisePacket
-( const REFERENCE_TIME & time1
-, const REFERENCE_TIME & time2
-, HANDLE h, BOOL periodic
-)
-{
- // Since we use MAX_TIME as a sentry, we can't afford to
- // schedule a notification at MAX_TIME
- ASSERT( time1 < MAX_TIME );
- DWORD_PTR Result;
- CAdvisePacket * p;
-
- m_Serialize.Lock();
-
- if (m_pAdviseCache)
- {
- p = m_pAdviseCache;
- m_pAdviseCache = p->m_next;
- --m_dwCacheCount;
- }
- else
- {
- p = new CAdvisePacket();
- }
- if (p)
- {
- p->m_rtEventTime = time1; p->m_rtPeriod = time2;
- p->m_hNotify = h; p->m_bPeriodic = periodic;
- Result = AddAdvisePacket( p );
- }
- else Result = 0;
-
- m_Serialize.Unlock();
-
- return Result;
-}
-
-HRESULT CAMSchedule::Unadvise(DWORD_PTR dwAdviseCookie)
-{
- HRESULT hr = S_FALSE;
- CAdvisePacket * p_prev = &head;
- CAdvisePacket * p_n;
- m_Serialize.Lock();
- while ( p_n = p_prev->Next() ) // The Next() method returns NULL when it hits z
- {
- if ( p_n->m_dwAdviseCookie == dwAdviseCookie )
- {
- Delete( p_prev->RemoveNext() );
- --m_dwAdviseCount;
- hr = S_OK;
- // Having found one cookie that matches, there should be no more
- #ifdef DEBUG
- while (p_n = p_prev->Next())
- {
- ASSERT(p_n->m_dwAdviseCookie != dwAdviseCookie);
- p_prev = p_n;
- }
- #endif
- break;
- }
- p_prev = p_n;
- };
- m_Serialize.Unlock();
- return hr;
-}
-
-REFERENCE_TIME CAMSchedule::Advise( const REFERENCE_TIME & rtTime )
-{
- REFERENCE_TIME rtNextTime;
- CAdvisePacket * pAdvise;
-
- DbgLog((LOG_TIMING, 2,
- TEXT("CAMSchedule::Advise( %lu ms )"), ULONG(rtTime / (UNITS / MILLISECONDS))));
-
- CAutoLock lck(&m_Serialize);
-
- #ifdef DEBUG
- if (DbgCheckModuleLevel(LOG_TIMING, 4)) DumpLinkedList();
- #endif
-
- // Note - DON'T cache the difference, it might overflow
- while ( rtTime >= (rtNextTime = (pAdvise=head.m_next)->m_rtEventTime) &&
- !pAdvise->IsZ() )
- {
- ASSERT(pAdvise->m_dwAdviseCookie); // If this is zero, its the head or the tail!!
-
- ASSERT(pAdvise->m_hNotify != INVALID_HANDLE_VALUE);
-
- if (pAdvise->m_bPeriodic == TRUE)
- {
- ReleaseSemaphore(pAdvise->m_hNotify,1,NULL);
- pAdvise->m_rtEventTime += pAdvise->m_rtPeriod;
- ShuntHead();
- }
- else
- {
- ASSERT( pAdvise->m_bPeriodic == FALSE );
- EXECUTE_ASSERT(SetEvent(pAdvise->m_hNotify));
- --m_dwAdviseCount;
- Delete( head.RemoveNext() );
- }
-
- }
-
- DbgLog((LOG_TIMING, 3,
- TEXT("CAMSchedule::Advise() Next time stamp: %lu ms, for advise %lu."),
- DWORD(rtNextTime / (UNITS / MILLISECONDS)), pAdvise->m_dwAdviseCookie ));
-
- return rtNextTime;
-}
-
-/* Private methods */
-
-DWORD_PTR CAMSchedule::AddAdvisePacket( __inout CAdvisePacket * pPacket )
-{
- ASSERT(pPacket->m_rtEventTime >= 0 && pPacket->m_rtEventTime < MAX_TIME);
- ASSERT(CritCheckIn(&m_Serialize));
-
- CAdvisePacket * p_prev = &head;
- CAdvisePacket * p_n;
-
- const DWORD_PTR Result = pPacket->m_dwAdviseCookie = ++m_dwNextCookie;
- // This relies on the fact that z is a sentry with a maximal m_rtEventTime
- for(;;p_prev = p_n)
- {
- p_n = p_prev->m_next;
- if ( p_n->m_rtEventTime >= pPacket->m_rtEventTime ) break;
- }
- p_prev->InsertAfter( pPacket );
- ++m_dwAdviseCount;
-
- DbgLog((LOG_TIMING, 2, TEXT("Added advise %lu, for thread 0x%02X, scheduled at %lu"),
- pPacket->m_dwAdviseCookie, GetCurrentThreadId(), (pPacket->m_rtEventTime / (UNITS / MILLISECONDS)) ));
-
- // If packet added at the head, then clock needs to re-evaluate wait time.
- if ( p_prev == &head ) SetEvent( m_ev );
-
- return Result;
-}
-
-void CAMSchedule::Delete( __inout CAdvisePacket * pPacket )
-{
- if ( m_dwCacheCount >= dwCacheMax ) delete pPacket;
- else
- {
- m_Serialize.Lock();
- pPacket->m_next = m_pAdviseCache;
- m_pAdviseCache = pPacket;
- ++m_dwCacheCount;
- m_Serialize.Unlock();
- }
-}
-
-
-// Takes the head of the list & repositions it
-void CAMSchedule::ShuntHead()
-{
- CAdvisePacket * p_prev = &head;
- CAdvisePacket * p_n;
-
- m_Serialize.Lock();
- CAdvisePacket *const pPacket = head.m_next;
-
- // This will catch both an empty list,
- // and if somehow a MAX_TIME time gets into the list
- // (which would also break this method).
- ASSERT( pPacket->m_rtEventTime < MAX_TIME );
-
- // This relies on the fact that z is a sentry with a maximal m_rtEventTime
- for(;;p_prev = p_n)
- {
- p_n = p_prev->m_next;
- if ( p_n->m_rtEventTime > pPacket->m_rtEventTime ) break;
- }
- // If p_prev == pPacket then we're already in the right place
- if (p_prev != pPacket)
- {
- head.m_next = pPacket->m_next;
- (p_prev->m_next = pPacket)->m_next = p_n;
- }
- #ifdef DEBUG
- DbgLog((LOG_TIMING, 2, TEXT("Periodic advise %lu, shunted to %lu"),
- pPacket->m_dwAdviseCookie, (pPacket->m_rtEventTime / (UNITS / MILLISECONDS)) ));
- #endif
- m_Serialize.Unlock();
-}
-
-
-#ifdef DEBUG
-void CAMSchedule::DumpLinkedList()
-{
- m_Serialize.Lock();
- int i=0;
- DbgLog((LOG_TIMING, 1, TEXT("CAMSchedule::DumpLinkedList() this = 0x%p"), this));
- for ( CAdvisePacket * p = &head
- ; p
- ; p = p->m_next , i++
- )
- {
- DbgLog((LOG_TIMING, 1, TEXT("Advise List # %lu, Cookie %d, RefTime %lu"),
- i,
- p->m_dwAdviseCookie,
- p->m_rtEventTime / (UNITS / MILLISECONDS)
- ));
- }
- m_Serialize.Unlock();
-}
-#endif
diff --git a/dll/src/baseclasses/schedule.h b/dll/src/baseclasses/schedule.h
deleted file mode 100644
index c16700a..0000000
--- a/dll/src/baseclasses/schedule.h
+++ /dev/null
@@ -1,128 +0,0 @@
-//------------------------------------------------------------------------------
-// File: Schedule.h
-//
-// Desc: DirectShow base classes.
-//
-// Copyright (c) 1996-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-#ifndef __CAMSchedule__
-#define __CAMSchedule__
-
-class CAMSchedule : private CBaseObject
-{
-public:
- virtual ~CAMSchedule();
- // ev is the event we should fire if the advise time needs re-evaluating
- CAMSchedule( HANDLE ev );
-
- DWORD GetAdviseCount();
- REFERENCE_TIME GetNextAdviseTime();
-
- // We need a method for derived classes to add advise packets, we return the cookie
- DWORD_PTR AddAdvisePacket( const REFERENCE_TIME & time1, const REFERENCE_TIME & time2, HANDLE h, BOOL periodic );
- // And a way to cancel
- HRESULT Unadvise(DWORD_PTR dwAdviseCookie);
-
- // Tell us the time please, and we'll dispatch the expired events. We return the time of the next event.
- // NB: The time returned will be "useless" if you start adding extra Advises. But that's the problem of
- // whoever is using this helper class (typically a clock).
- REFERENCE_TIME Advise( const REFERENCE_TIME & rtTime );
-
- // Get the event handle which will be set if advise time requires re-evaluation.
- HANDLE GetEvent() const { return m_ev; }
-
-private:
- // We define the nodes that will be used in our singly linked list
- // of advise packets. The list is ordered by time, with the
- // elements that will expire first at the front.
- class CAdvisePacket
- {
- public:
- CAdvisePacket()
- {}
-
- CAdvisePacket * m_next;
- DWORD_PTR m_dwAdviseCookie;
- REFERENCE_TIME m_rtEventTime; // Time at which event should be set
- REFERENCE_TIME m_rtPeriod; // Periodic time
- HANDLE m_hNotify; // Handle to event or semephore
- BOOL m_bPeriodic; // TRUE => Periodic event
-
- CAdvisePacket( __inout_opt CAdvisePacket * next, LONGLONG time ) : m_next(next), m_rtEventTime(time)
- {}
-
- void InsertAfter( __inout CAdvisePacket * p )
- {
- p->m_next = m_next;
- m_next = p;
- }
-
- int IsZ() const // That is, is it the node that represents the end of the list
- { return m_next == 0; }
-
- CAdvisePacket * RemoveNext()
- {
- CAdvisePacket *const next = m_next;
- CAdvisePacket *const new_next = next->m_next;
- m_next = new_next;
- return next;
- }
-
- void DeleteNext()
- {
- delete RemoveNext();
- }
-
- CAdvisePacket * Next() const
- {
- CAdvisePacket * result = m_next;
- if (result->IsZ()) result = 0;
- return result;
- }
-
- DWORD_PTR Cookie() const
- { return m_dwAdviseCookie; }
- };
-
- // Structure is:
- // head -> elmt1 -> elmt2 -> z -> null
- // So an empty list is: head -> z -> null
- // Having head & z as links makes insertaion,
- // deletion and shunting much easier.
- CAdvisePacket head, z; // z is both a tail and a sentry
-
- volatile DWORD_PTR m_dwNextCookie; // Strictly increasing
- volatile DWORD m_dwAdviseCount; // Number of elements on list
-
- CCritSec m_Serialize;
-
- // AddAdvisePacket: adds the packet, returns the cookie (0 if failed)
- DWORD_PTR AddAdvisePacket( __inout CAdvisePacket * pPacket );
- // Event that we should set if the packed added above will be the next to fire.
- const HANDLE m_ev;
-
- // A Shunt is where we have changed the first element in the
- // list and want it re-evaluating (i.e. repositioned) in
- // the list.
- void ShuntHead();
-
- // Rather than delete advise packets, we cache them for future use
- CAdvisePacket * m_pAdviseCache;
- DWORD m_dwCacheCount;
- enum { dwCacheMax = 5 }; // Don't bother caching more than five
-
- void Delete( __inout CAdvisePacket * pLink );// This "Delete" will cache the Link
-
-// Attributes and methods for debugging
-public:
-#ifdef DEBUG
- void DumpLinkedList();
-#else
- void DumpLinkedList() {}
-#endif
-
-};
-
-#endif // __CAMSchedule__
diff --git a/dll/src/baseclasses/seekpt.cpp b/dll/src/baseclasses/seekpt.cpp
deleted file mode 100644
index bb13d6f..0000000
--- a/dll/src/baseclasses/seekpt.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-//------------------------------------------------------------------------------
-// File: SeekPT.cpp
-//
-// Desc: DirectShow base classes.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-#include <streams.h>
-#include "seekpt.h"
-
-//==================================================================
-// CreateInstance
-// This goes in the factory template table to create new instances
-// If there is already a mapper instance - return that, else make one
-// and save it in a static variable so that forever after we can return that.
-//==================================================================
-
-CUnknown * CSeekingPassThru::CreateInstance(__inout_opt LPUNKNOWN pUnk, __inout HRESULT *phr)
-{
- return new CSeekingPassThru(NAME("Seeking PassThru"),pUnk, phr);
-}
-
-
-STDMETHODIMP CSeekingPassThru::NonDelegatingQueryInterface(REFIID riid, __deref_out void ** ppv)
-{
- if (riid == IID_ISeekingPassThru) {
- return GetInterface((ISeekingPassThru *) this, ppv);
- } else {
- if (m_pPosPassThru &&
- (riid == IID_IMediaSeeking ||
- riid == IID_IMediaPosition)) {
- return m_pPosPassThru->NonDelegatingQueryInterface(riid,ppv);
- } else {
- return CUnknown::NonDelegatingQueryInterface(riid, ppv);
- }
- }
-}
-
-
-CSeekingPassThru::CSeekingPassThru( __in_opt LPCTSTR pName, __inout_opt LPUNKNOWN pUnk, __inout HRESULT *phr )
- : CUnknown(pName, pUnk, phr),
- m_pPosPassThru(NULL)
-{
-}
-
-
-CSeekingPassThru::~CSeekingPassThru()
-{
- delete m_pPosPassThru;
-}
-
-STDMETHODIMP CSeekingPassThru::Init(BOOL bRendererSeeking, IPin *pPin)
-{
- HRESULT hr = NOERROR;
- if (m_pPosPassThru) {
- hr = E_FAIL;
- } else {
- m_pPosPassThru =
- bRendererSeeking ?
- new CRendererPosPassThru(
- NAME("Render Seeking COM object"),
- (IUnknown *)this,
- &hr,
- pPin) :
- new CPosPassThru(
- NAME("Render Seeking COM object"),
- (IUnknown *)this,
- &hr,
- pPin);
- if (!m_pPosPassThru) {
- hr = E_OUTOFMEMORY;
- } else {
- if (FAILED(hr)) {
- delete m_pPosPassThru;
- m_pPosPassThru = NULL;
- }
- }
- }
- return hr;
-}
-
diff --git a/dll/src/baseclasses/seekpt.h b/dll/src/baseclasses/seekpt.h
deleted file mode 100644
index 208d418..0000000
--- a/dll/src/baseclasses/seekpt.h
+++ /dev/null
@@ -1,30 +0,0 @@
-//------------------------------------------------------------------------------
-// File: SeekPT.h
-//
-// Desc: DirectShow base classes.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-#ifndef __seekpt_h__
-#define __seekpt_h__
-
-
-class CSeekingPassThru : public ISeekingPassThru, public CUnknown
-{
-public:
- static CUnknown *CreateInstance(__inout_opt LPUNKNOWN pUnk, __inout HRESULT *phr);
- CSeekingPassThru(__in_opt LPCTSTR pName, __inout_opt LPUNKNOWN pUnk, __inout HRESULT *phr);
- ~CSeekingPassThru();
-
- DECLARE_IUNKNOWN;
- STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void ** ppv);
-
- STDMETHODIMP Init(BOOL bSupportRendering, IPin *pPin);
-
-private:
- CPosPassThru *m_pPosPassThru;
-};
-
-#endif
diff --git a/dll/src/baseclasses/source.cpp b/dll/src/baseclasses/source.cpp
deleted file mode 100644
index ef7795c..0000000
--- a/dll/src/baseclasses/source.cpp
+++ /dev/null
@@ -1,522 +0,0 @@
-//------------------------------------------------------------------------------
-// File: Source.cpp
-//
-// Desc: DirectShow base classes - implements CSource, which is a Quartz
-// source filter 'template.'
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-// Locking Strategy.
-//
-// Hold the filter critical section (m_pFilter->pStateLock()) to serialise
-// access to functions. Note that, in general, this lock may be held
-// by a function when the worker thread may want to hold it. Therefore
-// if you wish to access shared state from the worker thread you will
-// need to add another critical section object. The execption is during
-// the threads processing loop, when it is safe to get the filter critical
-// section from within FillBuffer().
-
-#include <streams.h>
-
-
-//
-// CSource::Constructor
-//
-// Initialise the pin count for the filter. The user will create the pins in
-// the derived class.
-CSource::CSource(__in_opt LPCTSTR pName, __inout_opt LPUNKNOWN lpunk, CLSID clsid)
- : CBaseFilter(pName, lpunk, &m_cStateLock, clsid),
- m_iPins(0),
- m_paStreams(NULL)
-{
-}
-
-CSource::CSource(__in_opt LPCTSTR pName, __inout_opt LPUNKNOWN lpunk, CLSID clsid, __inout HRESULT *phr)
- : CBaseFilter(pName, lpunk, &m_cStateLock, clsid),
- m_iPins(0),
- m_paStreams(NULL)
-{
- UNREFERENCED_PARAMETER(phr);
-}
-
-#ifdef UNICODE
-CSource::CSource(__in_opt LPCSTR pName, __inout_opt LPUNKNOWN lpunk, CLSID clsid)
- : CBaseFilter(pName, lpunk, &m_cStateLock, clsid),
- m_iPins(0),
- m_paStreams(NULL)
-{
-}
-
-CSource::CSource(__in_opt LPCSTR pName, __inout_opt LPUNKNOWN lpunk, CLSID clsid, __inout HRESULT *phr)
- : CBaseFilter(pName, lpunk, &m_cStateLock, clsid),
- m_iPins(0),
- m_paStreams(NULL)
-{
- UNREFERENCED_PARAMETER(phr);
-}
-#endif
-
-//
-// CSource::Destructor
-//
-CSource::~CSource()
-{
- /* Free our pins and pin array */
- while (m_iPins != 0) {
- // deleting the pins causes them to be removed from the array...
- delete m_paStreams[m_iPins - 1];
- }
-
- ASSERT(m_paStreams == NULL);
-}
-
-
-//
-// Add a new pin
-//
-HRESULT CSource::AddPin(__in CSourceStream *pStream)
-{
- CAutoLock lock(&m_cStateLock);
-
- /* Allocate space for this pin and the old ones */
- CSourceStream **paStreams = new CSourceStream *[m_iPins + 1];
- if (paStreams == NULL) {
- return E_OUTOFMEMORY;
- }
- if (m_paStreams != NULL) {
- CopyMemory((PVOID)paStreams, (PVOID)m_paStreams,
- m_iPins * sizeof(m_paStreams[0]));
- paStreams[m_iPins] = pStream;
- delete [] m_paStreams;
- }
- m_paStreams = paStreams;
- m_paStreams[m_iPins] = pStream;
- m_iPins++;
- return S_OK;
-}
-
-//
-// Remove a pin - pStream is NOT deleted
-//
-HRESULT CSource::RemovePin(__in CSourceStream *pStream)
-{
- int i;
- for (i = 0; i < m_iPins; i++) {
- if (m_paStreams[i] == pStream) {
- if (m_iPins == 1) {
- delete [] m_paStreams;
- m_paStreams = NULL;
- } else {
- /* no need to reallocate */
- while (++i < m_iPins)
- m_paStreams[i - 1] = m_paStreams[i];
- }
- m_iPins--;
- return S_OK;
- }
- }
- return S_FALSE;
-}
-
-//
-// FindPin
-//
-// Set *ppPin to the IPin* that has the id Id.
-// or to NULL if the Id cannot be matched.
-STDMETHODIMP CSource::FindPin(LPCWSTR Id, __deref_out IPin **ppPin)
-{
- CheckPointer(ppPin,E_POINTER);
- ValidateReadWritePtr(ppPin,sizeof(IPin *));
- // The -1 undoes the +1 in QueryId and ensures that totally invalid
- // strings (for which WstrToInt delivers 0) give a deliver a NULL pin.
- int i = WstrToInt(Id) -1;
- *ppPin = GetPin(i);
- if (*ppPin!=NULL){
- (*ppPin)->AddRef();
- return NOERROR;
- } else {
- return VFW_E_NOT_FOUND;
- }
-}
-
-//
-// FindPinNumber
-//
-// return the number of the pin with this IPin* or -1 if none
-int CSource::FindPinNumber(__in IPin *iPin) {
- int i;
- for (i=0; i<m_iPins; ++i) {
- if ((IPin *)(m_paStreams[i])==iPin) {
- return i;
- }
- }
- return -1;
-}
-
-//
-// GetPinCount
-//
-// Returns the number of pins this filter has
-int CSource::GetPinCount(void) {
-
- CAutoLock lock(&m_cStateLock);
- return m_iPins;
-}
-
-
-//
-// GetPin
-//
-// Return a non-addref'd pointer to pin n
-// needed by CBaseFilter
-CBasePin *CSource::GetPin(int n) {
-
- CAutoLock lock(&m_cStateLock);
-
- // n must be in the range 0..m_iPins-1
- // if m_iPins>n && n>=0 it follows that m_iPins>0
- // which is what used to be checked (i.e. checking that we have a pin)
- if ((n >= 0) && (n < m_iPins)) {
-
- ASSERT(m_paStreams[n]);
- return m_paStreams[n];
- }
- return NULL;
-}
-
-
-//
-
-
-// *
-// * --- CSourceStream ----
-// *
-
-//
-// Set Id to point to a CoTaskMemAlloc'd
-STDMETHODIMP CSourceStream::QueryId(__deref_out LPWSTR *Id) {
- CheckPointer(Id,E_POINTER);
- ValidateReadWritePtr(Id,sizeof(LPWSTR));
-
- // We give the pins id's which are 1,2,...
- // FindPinNumber returns -1 for an invalid pin
- int i = 1+ m_pFilter->FindPinNumber(this);
- if (i<1) return VFW_E_NOT_FOUND;
- *Id = (LPWSTR)CoTaskMemAlloc(sizeof(WCHAR) * 12);
- if (*Id==NULL) {
- return E_OUTOFMEMORY;
- }
- IntToWstr(i, *Id);
- return NOERROR;
-}
-
-
-
-//
-// CSourceStream::Constructor
-//
-// increments the number of pins present on the filter
-CSourceStream::CSourceStream(
- __in_opt LPCTSTR pObjectName,
- __inout HRESULT *phr,
- __inout CSource *ps,
- __in_opt LPCWSTR pPinName)
- : CBaseOutputPin(pObjectName, ps, ps->pStateLock(), phr, pPinName),
- m_pFilter(ps) {
-
- *phr = m_pFilter->AddPin(this);
-}
-
-#ifdef UNICODE
-CSourceStream::CSourceStream(
- __in_opt LPCSTR pObjectName,
- __inout HRESULT *phr,
- __inout CSource *ps,
- __in_opt LPCWSTR pPinName)
- : CBaseOutputPin(pObjectName, ps, ps->pStateLock(), phr, pPinName),
- m_pFilter(ps) {
-
- *phr = m_pFilter->AddPin(this);
-}
-#endif
-//
-// CSourceStream::Destructor
-//
-// Decrements the number of pins on this filter
-CSourceStream::~CSourceStream(void) {
-
- m_pFilter->RemovePin(this);
-}
-
-
-//
-// CheckMediaType
-//
-// Do we support this type? Provides the default support for 1 type.
-HRESULT CSourceStream::CheckMediaType(const CMediaType *pMediaType) {
-
- CAutoLock lock(m_pFilter->pStateLock());
-
- CMediaType mt;
- GetMediaType(&mt);
-
- if (mt == *pMediaType) {
- return NOERROR;
- }
-
- return E_FAIL;
-}
-
-
-//
-// GetMediaType/3
-//
-// By default we support only one type
-// iPosition indexes are 0-n
-HRESULT CSourceStream::GetMediaType(int iPosition, __inout CMediaType *pMediaType) {
-
- CAutoLock lock(m_pFilter->pStateLock());
-
- if (iPosition<0) {
- return E_INVALIDARG;
- }
- if (iPosition>0) {
- return VFW_S_NO_MORE_ITEMS;
- }
- return GetMediaType(pMediaType);
-}
-
-
-//
-// Active
-//
-// The pin is active - start up the worker thread
-HRESULT CSourceStream::Active(void) {
-
- CAutoLock lock(m_pFilter->pStateLock());
-
- HRESULT hr;
-
- if (m_pFilter->IsActive()) {
- return S_FALSE; // succeeded, but did not allocate resources (they already exist...)
- }
-
- // do nothing if not connected - its ok not to connect to
- // all pins of a source filter
- if (!IsConnected()) {
- return NOERROR;
- }
-
- hr = CBaseOutputPin::Active();
- if (FAILED(hr)) {
- return hr;
- }
-
- ASSERT(!ThreadExists());
-
- // start the thread
- if (!Create()) {
- return E_FAIL;
- }
-
- // Tell thread to initialize. If OnThreadCreate Fails, so does this.
- hr = Init();
- if (FAILED(hr))
- return hr;
-
- return Pause();
-}
-
-
-//
-// Inactive
-//
-// Pin is inactive - shut down the worker thread
-// Waits for the worker to exit before returning.
-HRESULT CSourceStream::Inactive(void) {
-
- CAutoLock lock(m_pFilter->pStateLock());
-
- HRESULT hr;
-
- // do nothing if not connected - its ok not to connect to
- // all pins of a source filter
- if (!IsConnected()) {
- return NOERROR;
- }
-
- // !!! need to do this before trying to stop the thread, because
- // we may be stuck waiting for our own allocator!!!
-
- hr = CBaseOutputPin::Inactive(); // call this first to Decommit the allocator
- if (FAILED(hr)) {
- return hr;
- }
-
- if (ThreadExists()) {
- hr = Stop();
-
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = Exit();
- if (FAILED(hr)) {
- return hr;
- }
-
- Close(); // Wait for the thread to exit, then tidy up.
- }
-
- // hr = CBaseOutputPin::Inactive(); // call this first to Decommit the allocator
- //if (FAILED(hr)) {
- // return hr;
- //}
-
- return NOERROR;
-}
-
-
-//
-// ThreadProc
-//
-// When this returns the thread exits
-// Return codes > 0 indicate an error occured
-DWORD CSourceStream::ThreadProc(void) {
-
- HRESULT hr; // the return code from calls
- Command com;
-
- do {
- com = GetRequest();
- if (com != CMD_INIT) {
- DbgLog((LOG_ERROR, 1, TEXT("Thread expected init command")));
- Reply((DWORD) E_UNEXPECTED);
- }
- } while (com != CMD_INIT);
-
- DbgLog((LOG_TRACE, 1, TEXT("CSourceStream worker thread initializing")));
-
- hr = OnThreadCreate(); // perform set up tasks
- if (FAILED(hr)) {
- DbgLog((LOG_ERROR, 1, TEXT("CSourceStream::OnThreadCreate failed. Aborting thread.")));
- OnThreadDestroy();
- Reply(hr); // send failed return code from OnThreadCreate
- return 1;
- }
-
- // Initialisation suceeded
- Reply(NOERROR);
-
- Command cmd;
- do {
- cmd = GetRequest();
-
- switch (cmd) {
-
- case CMD_EXIT:
- Reply(NOERROR);
- break;
-
- case CMD_RUN:
- DbgLog((LOG_ERROR, 1, TEXT("CMD_RUN received before a CMD_PAUSE???")));
- // !!! fall through???
-
- case CMD_PAUSE:
- Reply(NOERROR);
- DoBufferProcessingLoop();
- break;
-
- case CMD_STOP:
- Reply(NOERROR);
- break;
-
- default:
- DbgLog((LOG_ERROR, 1, TEXT("Unknown command %d received!"), cmd));
- Reply((DWORD) E_NOTIMPL);
- break;
- }
- } while (cmd != CMD_EXIT);
-
- hr = OnThreadDestroy(); // tidy up.
- if (FAILED(hr)) {
- DbgLog((LOG_ERROR, 1, TEXT("CSourceStream::OnThreadDestroy failed. Exiting thread.")));
- return 1;
- }
-
- DbgLog((LOG_TRACE, 1, TEXT("CSourceStream worker thread exiting")));
- return 0;
-}
-
-
-//
-// DoBufferProcessingLoop
-//
-// Grabs a buffer and calls the users processing function.
-// Overridable, so that different delivery styles can be catered for.
-HRESULT CSourceStream::DoBufferProcessingLoop(void) {
-
- Command com;
-
- OnThreadStartPlay();
-
- do {
- while (!CheckRequest(&com)) {
-
- IMediaSample *pSample;
-
- HRESULT hr = GetDeliveryBuffer(&pSample,NULL,NULL,0);
- if (FAILED(hr)) {
- Sleep(1);
- continue; // go round again. Perhaps the error will go away
- // or the allocator is decommited & we will be asked to
- // exit soon.
- }
-
- // Virtual function user will override.
- hr = FillBuffer(pSample);
-
- if (hr == S_OK) {
- hr = Deliver(pSample);
- pSample->Release();
-
- // downstream filter returns S_FALSE if it wants us to
- // stop or an error if it's reporting an error.
- if(hr != S_OK)
- {
- DbgLog((LOG_TRACE, 2, TEXT("Deliver() returned %08x; stopping"), hr));
- return S_OK;
- }
-
- } else if (hr == S_FALSE) {
- // derived class wants us to stop pushing data
- pSample->Release();
- DeliverEndOfStream();
- return S_OK;
- } else {
- // derived class encountered an error
- pSample->Release();
- DbgLog((LOG_ERROR, 1, TEXT("Error %08lX from FillBuffer!!!"), hr));
- DeliverEndOfStream();
- m_pFilter->NotifyEvent(EC_ERRORABORT, hr, 0);
- return hr;
- }
-
- // all paths release the sample
- }
-
- // For all commands sent to us there must be a Reply call!
-
- if (com == CMD_RUN || com == CMD_PAUSE) {
- Reply(NOERROR);
- } else if (com != CMD_STOP) {
- Reply((DWORD) E_UNEXPECTED);
- DbgLog((LOG_ERROR, 1, TEXT("Unexpected command!!!")));
- }
- } while (com != CMD_STOP);
-
- return S_FALSE;
-}
-
diff --git a/dll/src/baseclasses/source.h b/dll/src/baseclasses/source.h
deleted file mode 100644
index 528d5bc..0000000
--- a/dll/src/baseclasses/source.h
+++ /dev/null
@@ -1,172 +0,0 @@
-//------------------------------------------------------------------------------
-// File: Source.h
-//
-// Desc: DirectShow base classes - defines classes to simplify creation of
-// ActiveX source filters that support continuous generation of data.
-// No support is provided for IMediaControl or IMediaPosition.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-//
-// Derive your source filter from CSource.
-// During construction either:
-// Create some CSourceStream objects to manage your pins
-// Provide the user with a means of doing so eg, an IPersistFile interface.
-//
-// CSource provides:
-// IBaseFilter interface management
-// IMediaFilter interface management, via CBaseFilter
-// Pin counting for CBaseFilter
-//
-// Derive a class from CSourceStream to manage your output pin types
-// Implement GetMediaType/1 to return the type you support. If you support multiple
-// types then overide GetMediaType/3, CheckMediaType and GetMediaTypeCount.
-// Implement Fillbuffer() to put data into one buffer.
-//
-// CSourceStream provides:
-// IPin management via CBaseOutputPin
-// Worker thread management
-
-#ifndef __CSOURCE__
-#define __CSOURCE__
-
-class CSourceStream; // The class that will handle each pin
-
-
-//
-// CSource
-//
-// Override construction to provide a means of creating
-// CSourceStream derived objects - ie a way of creating pins.
-class CSource : public CBaseFilter {
-public:
-
- CSource(__in_opt LPCTSTR pName, __inout_opt LPUNKNOWN lpunk, CLSID clsid, __inout HRESULT *phr);
- CSource(__in_opt LPCTSTR pName, __inout_opt LPUNKNOWN lpunk, CLSID clsid);
-#ifdef UNICODE
- CSource(__in_opt LPCSTR pName, __inout_opt LPUNKNOWN lpunk, CLSID clsid, __inout HRESULT *phr);
- CSource(__in_opt LPCSTR pName, __inout_opt LPUNKNOWN lpunk, CLSID clsid);
-#endif
- ~CSource();
-
- int GetPinCount(void);
- CBasePin *GetPin(int n);
-
- // -- Utilities --
-
- CCritSec* pStateLock(void) { return &m_cStateLock; } // provide our critical section
-
- HRESULT AddPin(__in CSourceStream *);
- HRESULT RemovePin(__in CSourceStream *);
-
- STDMETHODIMP FindPin(
- LPCWSTR Id,
- __deref_out IPin ** ppPin
- );
-
- int FindPinNumber(__in IPin *iPin);
-
-protected:
-
- int m_iPins; // The number of pins on this filter. Updated by CSourceStream
- // constructors & destructors.
- CSourceStream **m_paStreams; // the pins on this filter.
-
- CCritSec m_cStateLock; // Lock this to serialize function accesses to the filter state
-
-};
-
-
-//
-// CSourceStream
-//
-// Use this class to manage a stream of data that comes from a
-// pin.
-// Uses a worker thread to put data on the pin.
-class CSourceStream : public CAMThread, public CBaseOutputPin {
-public:
-
- CSourceStream(__in_opt LPCTSTR pObjectName,
- __inout HRESULT *phr,
- __inout CSource *pms,
- __in_opt LPCWSTR pName);
-#ifdef UNICODE
- CSourceStream(__in_opt LPCSTR pObjectName,
- __inout HRESULT *phr,
- __inout CSource *pms,
- __in_opt LPCWSTR pName);
-#endif
- virtual ~CSourceStream(void); // virtual destructor ensures derived class destructors are called too.
-
-protected:
-
- CSource *m_pFilter; // The parent of this stream
-
- // *
- // * Data Source
- // *
- // * The following three functions: FillBuffer, OnThreadCreate/Destroy, are
- // * called from within the ThreadProc. They are used in the creation of
- // * the media samples this pin will provide
- // *
-
- // Override this to provide the worker thread a means
- // of processing a buffer
- virtual HRESULT FillBuffer(IMediaSample *pSamp) PURE;
-
- // Called as the thread is created/destroyed - use to perform
- // jobs such as start/stop streaming mode
- // If OnThreadCreate returns an error the thread will exit.
- virtual HRESULT OnThreadCreate(void) {return NOERROR;};
- virtual HRESULT OnThreadDestroy(void) {return NOERROR;};
- virtual HRESULT OnThreadStartPlay(void) {return NOERROR;};
-
- // *
- // * Worker Thread
- // *
-
- HRESULT Active(void); // Starts up the worker thread
- HRESULT Inactive(void); // Exits the worker thread.
-
-public:
- // thread commands
- enum Command {CMD_INIT, CMD_PAUSE, CMD_RUN, CMD_STOP, CMD_EXIT};
- HRESULT Init(void) { return CallWorker(CMD_INIT); }
- HRESULT Exit(void) { return CallWorker(CMD_EXIT); }
- HRESULT Run(void) { return CallWorker(CMD_RUN); }
- HRESULT Pause(void) { return CallWorker(CMD_PAUSE); }
- HRESULT Stop(void) { return CallWorker(CMD_STOP); }
-
-protected:
- Command GetRequest(void) { return (Command) CAMThread::GetRequest(); }
- BOOL CheckRequest(Command *pCom) { return CAMThread::CheckRequest( (DWORD *) pCom); }
-
- // override these if you want to add thread commands
- virtual DWORD ThreadProc(void); // the thread function
-
- virtual HRESULT DoBufferProcessingLoop(void); // the loop executed whilst running
-
-
- // *
- // * AM_MEDIA_TYPE support
- // *
-
- // If you support more than one media type then override these 2 functions
- virtual HRESULT CheckMediaType(const CMediaType *pMediaType);
- virtual HRESULT GetMediaType(int iPosition, __inout CMediaType *pMediaType); // List pos. 0-n
-
- // If you support only one type then override this fn.
- // This will only be called by the default implementations
- // of CheckMediaType and GetMediaType(int, CMediaType*)
- // You must override this fn. or the above 2!
- virtual HRESULT GetMediaType(__inout CMediaType *pMediaType) {return E_UNEXPECTED;}
-
- STDMETHODIMP QueryId(
- __deref_out LPWSTR * Id
- );
-};
-
-#endif // __CSOURCE__
-
diff --git a/dll/src/baseclasses/streams.cpp b/dll/src/baseclasses/streams.cpp
deleted file mode 100644
index c08a6f0..0000000
--- a/dll/src/baseclasses/streams.cpp
+++ /dev/null
@@ -1 +0,0 @@
-#include "streams.h"
diff --git a/dll/src/baseclasses/streams.h b/dll/src/baseclasses/streams.h
deleted file mode 100644
index 56ef0d0..0000000
--- a/dll/src/baseclasses/streams.h
+++ /dev/null
@@ -1,204 +0,0 @@
-//------------------------------------------------------------------------------
-// File: Streams.h
-//
-// Desc: DirectShow base classes - defines overall streams architecture.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-#ifndef __STREAMS__
-#define __STREAMS__
-
-#ifdef _MSC_VER
-// disable some level-4 warnings, use #pragma warning(enable:###) to re-enable
-#pragma warning(disable:4100) // warning C4100: unreferenced formal parameter
-#pragma warning(disable:4201) // warning C4201: nonstandard extension used : nameless struct/union
-#pragma warning(disable:4511) // warning C4511: copy constructor could not be generated
-#pragma warning(disable:4512) // warning C4512: assignment operator could not be generated
-#pragma warning(disable:4514) // warning C4514: "unreferenced inline function has been removed"
-
-#if _MSC_VER>=1100
-#define AM_NOVTABLE __declspec(novtable)
-#else
-#define AM_NOVTABLE
-#endif
-#endif // MSC_VER
-
-
-// Because of differences between Visual C++ and older Microsoft SDKs,
-// you may have defined _DEBUG without defining DEBUG. This logic
-// ensures that both will be set if Visual C++ sets _DEBUG.
-#ifdef _DEBUG
-#ifndef DEBUG
-#define DEBUG
-#endif
-#endif
-
-#pragma comment(lib, "strmiids.lib")
-#pragma comment(lib, "winmm.lib")
-
-#include <windows.h>
-#include <windowsx.h>
-#include <olectl.h>
-#include <ddraw.h>
-#include <mmsystem.h>
-
-
-#ifndef NUMELMS
-#if _WIN32_WINNT < 0x0600
- #define NUMELMS(aa) (sizeof(aa)/sizeof((aa)[0]))
-#else
- #define NUMELMS(aa) ARRAYSIZE(aa)
-#endif
-#endif
-
-///////////////////////////////////////////////////////////////////////////
-// The following definitions come from the Platform SDK and are required if
-// the applicaiton is being compiled with the headers from Visual C++ 6.0.
-/////////////////////////////////////////////////// ////////////////////////
-#ifndef InterlockedExchangePointer
- #define InterlockedExchangePointer(Target, Value) \
- (PVOID)InterlockedExchange((PLONG)(Target), (LONG)(Value))
-#endif
-
-#ifndef _WAVEFORMATEXTENSIBLE_
-#define _WAVEFORMATEXTENSIBLE_
-typedef struct {
- WAVEFORMATEX Format;
- union {
- WORD wValidBitsPerSample; /* bits of precision */
- WORD wSamplesPerBlock; /* valid if wBitsPerSample==0 */
- WORD wReserved; /* If neither applies, set to zero. */
- } Samples;
- DWORD dwChannelMask; /* which channels are */
- /* present in stream */
- GUID SubFormat;
-} WAVEFORMATEXTENSIBLE, *PWAVEFORMATEXTENSIBLE;
-#endif // !_WAVEFORMATEXTENSIBLE_
-
-#if !defined(WAVE_FORMAT_EXTENSIBLE)
-#define WAVE_FORMAT_EXTENSIBLE 0xFFFE
-#endif // !defined(WAVE_FORMAT_EXTENSIBLE)
-
-#ifndef GetWindowLongPtr
- #define GetWindowLongPtrA GetWindowLongA
- #define GetWindowLongPtrW GetWindowLongW
- #ifdef UNICODE
- #define GetWindowLongPtr GetWindowLongPtrW
- #else
- #define GetWindowLongPtr GetWindowLongPtrA
- #endif // !UNICODE
-#endif // !GetWindowLongPtr
-
-#ifndef SetWindowLongPtr
- #define SetWindowLongPtrA SetWindowLongA
- #define SetWindowLongPtrW SetWindowLongW
- #ifdef UNICODE
- #define SetWindowLongPtr SetWindowLongPtrW
- #else
- #define SetWindowLongPtr SetWindowLongPtrA
- #endif // !UNICODE
-#endif // !SetWindowLongPtr
-
-#ifndef GWLP_WNDPROC
- #define GWLP_WNDPROC (-4)
-#endif
-#ifndef GWLP_HINSTANCE
- #define GWLP_HINSTANCE (-6)
-#endif
-#ifndef GWLP_HWNDPARENT
- #define GWLP_HWNDPARENT (-8)
-#endif
-#ifndef GWLP_USERDATA
- #define GWLP_USERDATA (-21)
-#endif
-#ifndef GWLP_ID
- #define GWLP_ID (-12)
-#endif
-#ifndef DWLP_MSGRESULT
- #define DWLP_MSGRESULT 0
-#endif
-#ifndef DWLP_DLGPROC
- #define DWLP_DLGPROC DWLP_MSGRESULT + sizeof(LRESULT)
-#endif
-#ifndef DWLP_USER
- #define DWLP_USER DWLP_DLGPROC + sizeof(DLGPROC)
-#endif
-
-
-#pragma warning(push)
-#pragma warning(disable: 4312 4244)
-// _GetWindowLongPtr
-// Templated version of GetWindowLongPtr, to suppress spurious compiler warning.
-template <class T>
-T _GetWindowLongPtr(HWND hwnd, int nIndex)
-{
- return (T)GetWindowLongPtr(hwnd, nIndex);
-}
-
-// _SetWindowLongPtr
-// Templated version of SetWindowLongPtr, to suppress spurious compiler warning.
-template <class T>
-LONG_PTR _SetWindowLongPtr(HWND hwnd, int nIndex, T p)
-{
- return SetWindowLongPtr(hwnd, nIndex, (LONG_PTR)p);
-}
-#pragma warning(pop)
-
-///////////////////////////////////////////////////////////////////////////
-// End Platform SDK definitions
-///////////////////////////////////////////////////////////////////////////
-
-
-#include <strmif.h> // Generated IDL header file for streams interfaces
-#include <intsafe.h> // required by amvideo.h
-
-#include <reftime.h> // Helper class for REFERENCE_TIME management
-#include <wxdebug.h> // Debug support for logging and ASSERTs
-#include <amvideo.h> // ActiveMovie video interfaces and definitions
-//include amaudio.h explicitly if you need it. it requires the DX SDK.
-//#include <amaudio.h> // ActiveMovie audio interfaces and definitions
-#include <wxutil.h> // General helper classes for threads etc
-#include <combase.h> // Base COM classes to support IUnknown
-#include <dllsetup.h> // Filter registration support functions
-#include <measure.h> // Performance measurement
-#include <comlite.h> // Light weight com function prototypes
-
-#include <cache.h> // Simple cache container class
-#include <wxlist.h> // Non MFC generic list class
-#include <msgthrd.h> // CMsgThread
-#include <mtype.h> // Helper class for managing media types
-#include <fourcc.h> // conversions between FOURCCs and GUIDs
-#include <control.h> // generated from control.odl
-#include <ctlutil.h> // control interface utility classes
-#include <evcode.h> // event code definitions
-#include <amfilter.h> // Main streams architecture class hierachy
-#include <transfrm.h> // Generic transform filter
-#include <transip.h> // Generic transform-in-place filter
-#include <uuids.h> // declaration of type GUIDs and well-known clsids
-#include <source.h> // Generic source filter
-#include <outputq.h> // Output pin queueing
-#include <errors.h> // HRESULT status and error definitions
-#include <renbase.h> // Base class for writing ActiveX renderers
-#include <winutil.h> // Helps with filters that manage windows
-#include <winctrl.h> // Implements the IVideoWindow interface
-#include <videoctl.h> // Specifically video related classes
-#include <refclock.h> // Base clock class
-#include <sysclock.h> // System clock
-#include <pstream.h> // IPersistStream helper class
-#include <vtrans.h> // Video Transform Filter base class
-#include <amextra.h>
-#include <cprop.h> // Base property page class
-#include <strmctl.h> // IAMStreamControl support
-#include <edevdefs.h> // External device control interface defines
-#include <audevcod.h> // audio filter device error event codes
-
-
-
-#else
- #ifdef DEBUG
- #pragma message("STREAMS.H included TWICE")
- #endif
-#endif // __STREAMS__
-
diff --git a/dll/src/baseclasses/strmctl.cpp b/dll/src/baseclasses/strmctl.cpp
deleted file mode 100644
index b7f5952..0000000
--- a/dll/src/baseclasses/strmctl.cpp
+++ /dev/null
@@ -1,402 +0,0 @@
-//------------------------------------------------------------------------------
-// File: StrmCtl.cpp
-//
-// Desc: DirectShow base classes.
-//
-// Copyright (c) 1996-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-#include <streams.h>
-#include <strmctl.h>
-
-CBaseStreamControl::CBaseStreamControl(__inout HRESULT *phr)
-: m_StreamState(STREAM_FLOWING)
-, m_StreamStateOnStop(STREAM_FLOWING) // means no pending stop
-, m_tStartTime(MAX_TIME)
-, m_tStopTime(MAX_TIME)
-, m_StreamEvent(FALSE, phr)
-, m_dwStartCookie(0)
-, m_dwStopCookie(0)
-, m_pRefClock(NULL)
-, m_FilterState(State_Stopped)
-, m_bIsFlushing(FALSE)
-, m_bStopSendExtra(FALSE)
-{}
-
-CBaseStreamControl::~CBaseStreamControl()
-{
- // Make sure we release the clock.
- SetSyncSource(NULL);
- return;
-}
-
-
-STDMETHODIMP CBaseStreamControl::StopAt(const REFERENCE_TIME * ptStop, BOOL bSendExtra, DWORD dwCookie)
-{
- CAutoLock lck(&m_CritSec);
- m_bStopSendExtra = FALSE; // reset
- m_bStopExtraSent = FALSE;
- if (ptStop)
- {
- if (*ptStop == MAX_TIME)
- {
- DbgLog((LOG_TRACE,2,TEXT("StopAt: Cancel stop")));
- CancelStop();
- // If there's now a command to start in the future, we assume
- // they want to be stopped when the graph is first run
- if (m_FilterState == State_Stopped && m_tStartTime < MAX_TIME) {
- m_StreamState = STREAM_DISCARDING;
- DbgLog((LOG_TRACE,2,TEXT("graph will begin by DISCARDING")));
- }
- return NOERROR;
- }
- DbgLog((LOG_TRACE,2,TEXT("StopAt: %dms extra=%d"),
- (int)(*ptStop/10000), bSendExtra));
- // if the first command is to stop in the future, then we assume they
- // want to be started when the graph is first run
- if (m_FilterState == State_Stopped && m_tStartTime > *ptStop) {
- m_StreamState = STREAM_FLOWING;
- DbgLog((LOG_TRACE,2,TEXT("graph will begin by FLOWING")));
- }
- m_bStopSendExtra = bSendExtra;
- m_tStopTime = *ptStop;
- m_dwStopCookie = dwCookie;
- m_StreamStateOnStop = STREAM_DISCARDING;
- }
- else
- {
- DbgLog((LOG_TRACE,2,TEXT("StopAt: now")));
- // sending an extra frame when told to stop now would mess people up
- m_bStopSendExtra = FALSE;
- m_tStopTime = MAX_TIME;
- m_dwStopCookie = 0;
- m_StreamState = STREAM_DISCARDING;
- m_StreamStateOnStop = STREAM_FLOWING; // no pending stop
- }
- // we might change our mind what to do with a sample we're blocking
- m_StreamEvent.Set();
- return NOERROR;
-}
-
-STDMETHODIMP CBaseStreamControl::StartAt
-( const REFERENCE_TIME *ptStart, DWORD dwCookie )
-{
- CAutoLock lck(&m_CritSec);
- if (ptStart)
- {
- if (*ptStart == MAX_TIME)
- {
- DbgLog((LOG_TRACE,2,TEXT("StartAt: Cancel start")));
- CancelStart();
- // If there's now a command to stop in the future, we assume
- // they want to be started when the graph is first run
- if (m_FilterState == State_Stopped && m_tStopTime < MAX_TIME) {
- DbgLog((LOG_TRACE,2,TEXT("graph will begin by FLOWING")));
- m_StreamState = STREAM_FLOWING;
- }
- return NOERROR;
- }
- DbgLog((LOG_TRACE,2,TEXT("StartAt: %dms"), (int)(*ptStart/10000)));
- // if the first command is to start in the future, then we assume they
- // want to be stopped when the graph is first run
- if (m_FilterState == State_Stopped && m_tStopTime >= *ptStart) {
- DbgLog((LOG_TRACE,2,TEXT("graph will begin by DISCARDING")));
- m_StreamState = STREAM_DISCARDING;
- }
- m_tStartTime = *ptStart;
- m_dwStartCookie = dwCookie;
- // if (m_tStopTime == m_tStartTime) CancelStop();
- }
- else
- {
- DbgLog((LOG_TRACE,2,TEXT("StartAt: now")));
- m_tStartTime = MAX_TIME;
- m_dwStartCookie = 0;
- m_StreamState = STREAM_FLOWING;
- }
- // we might change our mind what to do with a sample we're blocking
- m_StreamEvent.Set();
- return NOERROR;
-}
-
-// Retrieve information about current settings
-STDMETHODIMP CBaseStreamControl::GetInfo(__out AM_STREAM_INFO *pInfo)
-{
- if (pInfo == NULL)
- return E_POINTER;
-
- pInfo->tStart = m_tStartTime;
- pInfo->tStop = m_tStopTime;
- pInfo->dwStartCookie = m_dwStartCookie;
- pInfo->dwStopCookie = m_dwStopCookie;
- pInfo->dwFlags = m_bStopSendExtra ? AM_STREAM_INFO_STOP_SEND_EXTRA : 0;
- pInfo->dwFlags |= m_tStartTime == MAX_TIME ? 0 : AM_STREAM_INFO_START_DEFINED;
- pInfo->dwFlags |= m_tStopTime == MAX_TIME ? 0 : AM_STREAM_INFO_STOP_DEFINED;
- switch (m_StreamState) {
- default:
- DbgBreak("Invalid stream state");
- case STREAM_FLOWING:
- break;
- case STREAM_DISCARDING:
- pInfo->dwFlags |= AM_STREAM_INFO_DISCARDING;
- break;
- }
- return S_OK;
-}
-
-
-void CBaseStreamControl::ExecuteStop()
-{
- ASSERT(CritCheckIn(&m_CritSec));
- m_StreamState = m_StreamStateOnStop;
- if (m_dwStopCookie && m_pSink) {
- DbgLog((LOG_TRACE,2,TEXT("*sending EC_STREAM_CONTROL_STOPPED (%d)"),
- m_dwStopCookie));
- m_pSink->Notify(EC_STREAM_CONTROL_STOPPED, (LONG_PTR)this, m_dwStopCookie);
- }
- CancelStop(); // This will do the tidy up
-}
-
-void CBaseStreamControl::ExecuteStart()
-{
- ASSERT(CritCheckIn(&m_CritSec));
- m_StreamState = STREAM_FLOWING;
- if (m_dwStartCookie) {
- DbgLog((LOG_TRACE,2,TEXT("*sending EC_STREAM_CONTROL_STARTED (%d)"),
- m_dwStartCookie));
- m_pSink->Notify(EC_STREAM_CONTROL_STARTED, (LONG_PTR)this, m_dwStartCookie);
- }
- CancelStart(); // This will do the tidy up
-}
-
-void CBaseStreamControl::CancelStop()
-{
- ASSERT(CritCheckIn(&m_CritSec));
- m_tStopTime = MAX_TIME;
- m_dwStopCookie = 0;
- m_StreamStateOnStop = STREAM_FLOWING;
-}
-
-void CBaseStreamControl::CancelStart()
-{
- ASSERT(CritCheckIn(&m_CritSec));
- m_tStartTime = MAX_TIME;
- m_dwStartCookie = 0;
-}
-
-
-// This guy will return one of the three StreamControlState's. Here's what the caller
-// should do for each one:
-//
-// STREAM_FLOWING: Proceed as usual (render or pass the sample on)
-// STREAM_DISCARDING: Calculate the time 'til *pSampleStart and wait that long
-// for the event handle (GetStreamEventHandle()). If the
-// wait expires, throw the sample away. If the event
-// fires, call me back, I've changed my mind.
-// I use pSampleStart (not Stop) so that live sources don't
-// block for the duration of their samples, since the clock
-// will always read approximately pSampleStart when called
-
-
-// All through this code, you'll notice the following rules:
-// - When start and stop time are the same, it's as if start was first
-// - An event is considered inside the sample when it's >= sample start time
-// but < sample stop time
-// - if any part of the sample is supposed to be sent, we'll send the whole
-// thing since we don't break it into smaller pieces
-// - If we skip over a start or stop without doing it, we still signal the event
-// and reset ourselves in case somebody's waiting for the event, and to make
-// sure we notice that the event is past and should be forgotten
-// Here are the 19 cases that have to be handled (x=start o=stop <-->=sample):
-//
-// 1. xo<--> start then stop
-// 2. ox<--> stop then start
-// 3. x<o-> start
-// 4. o<x-> stop then start
-// 5. x<-->o start
-// 6. o<-->x stop
-// 7. <x->o start
-// 8. <o->x no change
-// 9. <xo> start
-// 10. <ox> stop then start
-// 11. <-->xo no change
-// 12. <-->ox no change
-// 13. x<--> start
-// 14. <x-> start
-// 15. <-->x no change
-// 16. o<--> stop
-// 17. <o-> no change
-// 18. <-->o no change
-// 19. <--> no change
-
-
-enum CBaseStreamControl::StreamControlState CBaseStreamControl::CheckSampleTimes
-( __in const REFERENCE_TIME * pSampleStart, __in const REFERENCE_TIME * pSampleStop )
-{
- CAutoLock lck(&m_CritSec);
-
- ASSERT(!m_bIsFlushing);
- ASSERT(pSampleStart && pSampleStop);
-
- // Don't ask me how I came up with the code below to handle all 19 cases
- // - DannyMi
-
- if (m_tStopTime >= *pSampleStart)
- {
- if (m_tStartTime >= *pSampleStop)
- return m_StreamState; // cases 8 11 12 15 17 18 19
- if (m_tStopTime < m_tStartTime)
- ExecuteStop(); // case 10
- ExecuteStart(); // cases 3 5 7 9 13 14
- return m_StreamState;
- }
-
- if (m_tStartTime >= *pSampleStop)
- {
- ExecuteStop(); // cases 6 16
- return m_StreamState;
- }
-
- if (m_tStartTime <= m_tStopTime)
- {
- ExecuteStart();
- ExecuteStop();
- return m_StreamState; // case 1
- }
- else
- {
- ExecuteStop();
- ExecuteStart();
- return m_StreamState; // cases 2 4
- }
-}
-
-
-enum CBaseStreamControl::StreamControlState CBaseStreamControl::CheckStreamState( IMediaSample * pSample )
-{
-
- REFERENCE_TIME rtBufferStart, rtBufferStop;
- const BOOL bNoBufferTimes =
- pSample == NULL ||
- FAILED(pSample->GetTime(&rtBufferStart, &rtBufferStop));
-
- StreamControlState state;
- LONG lWait;
-
- do
- {
- // something has to break out of the blocking
- if (m_bIsFlushing || m_FilterState == State_Stopped)
- return STREAM_DISCARDING;
-
- if (bNoBufferTimes) {
- // Can't do anything until we get a time stamp
- state = m_StreamState;
- break;
- } else {
- state = CheckSampleTimes( &rtBufferStart, &rtBufferStop );
- if (state == STREAM_FLOWING)
- break;
-
- // we aren't supposed to send this, but we've been
- // told to send one more than we were supposed to
- // (and the stop isn't still pending and we're streaming)
- if (m_bStopSendExtra && !m_bStopExtraSent &&
- m_tStopTime == MAX_TIME &&
- m_FilterState != State_Stopped) {
- m_bStopExtraSent = TRUE;
- DbgLog((LOG_TRACE,2,TEXT("%d sending an EXTRA frame"),
- m_dwStopCookie));
- state = STREAM_FLOWING;
- break;
- }
- }
-
- // We're in discarding mode
-
- // If we've no clock, discard as fast as we can
- if (!m_pRefClock) {
- break;
-
- // If we're paused, we can't discard in a timely manner because
- // there's no such thing as stream times. We must block until
- // we run or stop, or we'll end up throwing the whole stream away
- // as quickly as possible
- } else if (m_FilterState == State_Paused) {
- lWait = INFINITE;
-
- } else {
- // wait until it's time for the sample until we say "discard"
- // ("discard in a timely fashion")
- REFERENCE_TIME rtNow;
- EXECUTE_ASSERT(SUCCEEDED(m_pRefClock->GetTime(&rtNow)));
- rtNow -= m_tRunStart; // Into relative ref-time
- lWait = LONG((rtBufferStart - rtNow)/10000); // 100ns -> ms
- if (lWait < 10) break; // Not worth waiting - discard early
- }
-
- } while(WaitForSingleObject(GetStreamEventHandle(), lWait) != WAIT_TIMEOUT);
-
- return state;
-}
-
-
-void CBaseStreamControl::NotifyFilterState( FILTER_STATE new_state, REFERENCE_TIME tStart )
-{
- CAutoLock lck(&m_CritSec);
-
- // or we will get confused
- if (m_FilterState == new_state)
- return;
-
- switch (new_state)
- {
- case State_Stopped:
-
- DbgLog((LOG_TRACE,2,TEXT("Filter is STOPPED")));
-
- // execute any pending starts and stops in the right order,
- // to make sure all notifications get sent, and we end up
- // in the right state to begin next time (??? why not?)
-
- if (m_tStartTime != MAX_TIME && m_tStopTime == MAX_TIME) {
- ExecuteStart();
- } else if (m_tStopTime != MAX_TIME && m_tStartTime == MAX_TIME) {
- ExecuteStop();
- } else if (m_tStopTime != MAX_TIME && m_tStartTime != MAX_TIME) {
- if (m_tStartTime <= m_tStopTime) {
- ExecuteStart();
- ExecuteStop();
- } else {
- ExecuteStop();
- ExecuteStart();
- }
- }
- // always start off flowing when the graph starts streaming
- // unless told otherwise
- m_StreamState = STREAM_FLOWING;
- m_FilterState = new_state;
- break;
-
- case State_Running:
-
- DbgLog((LOG_TRACE,2,TEXT("Filter is RUNNING")));
-
- m_tRunStart = tStart;
- // fall-through
-
- default: // case State_Paused:
- m_FilterState = new_state;
- }
- // unblock!
- m_StreamEvent.Set();
-}
-
-
-void CBaseStreamControl::Flushing(BOOL bInProgress)
-{
- CAutoLock lck(&m_CritSec);
- m_bIsFlushing = bInProgress;
- m_StreamEvent.Set();
-}
diff --git a/dll/src/baseclasses/strmctl.h b/dll/src/baseclasses/strmctl.h
deleted file mode 100644
index cb2adf3..0000000
--- a/dll/src/baseclasses/strmctl.h
+++ /dev/null
@@ -1,157 +0,0 @@
-//------------------------------------------------------------------------------
-// File: StrmCtl.h
-//
-// Desc: DirectShow base classes.
-//
-// Copyright (c) 1996-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-#ifndef __strmctl_h__
-#define __strmctl_h__
-
-class CBaseStreamControl : public IAMStreamControl
-{
-public:
- // Used by the implementation
- enum StreamControlState
- { STREAM_FLOWING = 0x1000,
- STREAM_DISCARDING
- };
-
-private:
- enum StreamControlState m_StreamState; // Current stream state
- enum StreamControlState m_StreamStateOnStop; // State after next stop
- // (i.e.Blocking or Discarding)
-
- REFERENCE_TIME m_tStartTime; // MAX_TIME implies none
- REFERENCE_TIME m_tStopTime; // MAX_TIME implies none
- DWORD m_dwStartCookie; // Cookie for notification to app
- DWORD m_dwStopCookie; // Cookie for notification to app
- volatile BOOL m_bIsFlushing; // No optimization pls!
- volatile BOOL m_bStopSendExtra; // bSendExtra was set
- volatile BOOL m_bStopExtraSent; // the extra one was sent
-
- CCritSec m_CritSec; // CritSec to guard above attributes
-
- // Event to fire when we can come
- // out of blocking, or to come out of waiting
- // to discard if we change our minds.
- //
- CAMEvent m_StreamEvent;
-
- // All of these methods execute immediately. Helpers for others.
- //
- void ExecuteStop();
- void ExecuteStart();
- void CancelStop();
- void CancelStart();
-
- // Some things we need to be told by our owning filter
- // Your pin must also expose IAMStreamControl when QI'd for it!
- //
- IReferenceClock * m_pRefClock; // Need it to set advises
- // Filter must tell us via
- // SetSyncSource
- IMediaEventSink * m_pSink; // Event sink
- // Filter must tell us after it
- // creates it in JoinFilterGraph()
- FILTER_STATE m_FilterState; // Just need it!
- // Filter must tell us via
- // NotifyFilterState
- REFERENCE_TIME m_tRunStart; // Per the Run call to the filter
-
- // This guy will return one of the three StreamControlState's. Here's what
- // the caller should do for each one:
- //
- // STREAM_FLOWING: Proceed as usual (render or pass the sample on)
- // STREAM_DISCARDING: Calculate the time 'til *pSampleStop and wait
- // that long for the event handle
- // (GetStreamEventHandle()). If the wait
- // expires, throw the sample away. If the event
- // fires, call me back - I've changed my mind.
- //
- enum StreamControlState CheckSampleTimes( __in const REFERENCE_TIME * pSampleStart,
- __in const REFERENCE_TIME * pSampleStop );
-
-public:
- // You don't have to tell us much when we're created, but there are other
- // obligations that must be met. See SetSyncSource & NotifyFilterState
- // below.
- //
- CBaseStreamControl(__inout_opt HRESULT *phr = NULL);
- ~CBaseStreamControl();
-
- // If you want this class to work properly, there are thing you need to
- // (keep) telling it. Filters with pins that use this class
- // should ensure that they pass through to this method any calls they
- // receive on their SetSyncSource.
-
- // We need a clock to see what time it is. This is for the
- // "discard in a timely fashion" logic. If we discard everything as
- // quick as possible, a whole 60 minute file could get discarded in the
- // first 10 seconds, and if somebody wants to turn streaming on at 30
- // minutes into the file, and they make the call more than a few seconds
- // after the graph is run, it may be too late!
- // So we hold every sample until it's time has gone, then we discard it.
- // The filter should call this when it gets a SetSyncSource
- //
- void SetSyncSource( IReferenceClock * pRefClock )
- {
- CAutoLock lck(&m_CritSec);
- if (m_pRefClock) m_pRefClock->Release();
- m_pRefClock = pRefClock;
- if (m_pRefClock) m_pRefClock->AddRef();
- }
-
- // Set event sink for notifications
- // The filter should call this in its JoinFilterGraph after it creates the
- // IMediaEventSink
- //
- void SetFilterGraph( IMediaEventSink *pSink ) {
- m_pSink = pSink;
- }
-
- // Since we schedule in stream time, we need the tStart and must track the
- // state of our owning filter.
- // The app should call this ever state change
- //
- void NotifyFilterState( FILTER_STATE new_state, REFERENCE_TIME tStart = 0 );
-
- // Filter should call Flushing(TRUE) in BeginFlush,
- // and Flushing(FALSE) in EndFlush.
- //
- void Flushing( BOOL bInProgress );
-
-
- // The two main methods of IAMStreamControl
-
- // Class adds default values suitable for immediate
- // muting and unmuting of the stream.
-
- STDMETHODIMP StopAt( const REFERENCE_TIME * ptStop = NULL,
- BOOL bSendExtra = FALSE,
- DWORD dwCookie = 0 );
- STDMETHODIMP StartAt( const REFERENCE_TIME * ptStart = NULL,
- DWORD dwCookie = 0 );
- STDMETHODIMP GetInfo( __out AM_STREAM_INFO *pInfo);
-
- // Helper function for pin's receive method. Call this with
- // the sample and we'll tell you what to do with it. We'll do a
- // WaitForSingleObject within this call if one is required. This is
- // a "What should I do with this sample?" kind of call. We'll tell the
- // caller to either flow it or discard it.
- // If pSample is NULL we evaluate based on the current state
- // settings
- enum StreamControlState CheckStreamState( IMediaSample * pSample );
-
-private:
- // These don't require locking, but we are relying on the fact that
- // m_StreamState can be retrieved with integrity, and is a snap shot that
- // may have just been, or may be just about to be, changed.
- HANDLE GetStreamEventHandle() const { return m_StreamEvent; }
- enum StreamControlState GetStreamState() const { return m_StreamState; }
- BOOL IsStreaming() const { return m_StreamState == STREAM_FLOWING; }
-};
-
-#endif
diff --git a/dll/src/baseclasses/sysclock.cpp b/dll/src/baseclasses/sysclock.cpp
deleted file mode 100644
index 0d58291..0000000
--- a/dll/src/baseclasses/sysclock.cpp
+++ /dev/null
@@ -1,74 +0,0 @@
-//------------------------------------------------------------------------------
-// File: SysClock.cpp
-//
-// Desc: DirectShow base classes - implements a system clock based on
-// IReferenceClock.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-#include <streams.h>
-#include <limits.h>
-
-
-#ifdef FILTER_DLL
-
-/* List of class IDs and creator functions for the class factory. This
- provides the link between the OLE entry point in the DLL and an object
- being created. The class factory will call the static CreateInstance
- function when it is asked to create a CLSID_SystemClock object */
-
-CFactoryTemplate g_Templates[1] = {
- {&CLSID_SystemClock, CSystemClock::CreateInstance}
-};
-
-int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
-#endif
-
-/* This goes in the factory template table to create new instances */
-CUnknown * WINAPI CSystemClock::CreateInstance(__inout_opt LPUNKNOWN pUnk, __inout HRESULT *phr)
-{
- return new CSystemClock(NAME("System reference clock"),pUnk, phr);
-}
-
-
-CSystemClock::CSystemClock(__in_opt LPCTSTR pName, __inout_opt LPUNKNOWN pUnk, __inout HRESULT *phr) :
- CBaseReferenceClock(pName, pUnk, phr)
-{
-}
-
-STDMETHODIMP CSystemClock::NonDelegatingQueryInterface(
- REFIID riid,
- __deref_out void ** ppv)
-{
- if (riid == IID_IPersist)
- {
- return GetInterface(static_cast<IPersist *>(this), ppv);
- }
- else if (riid == IID_IAMClockAdjust)
- {
- return GetInterface(static_cast<IAMClockAdjust *>(this), ppv);
- }
- else
- {
- return CBaseReferenceClock::NonDelegatingQueryInterface(riid, ppv);
- }
-}
-
-/* Return the clock's clsid */
-STDMETHODIMP
-CSystemClock::GetClassID(__out CLSID *pClsID)
-{
- CheckPointer(pClsID,E_POINTER);
- ValidateReadWritePtr(pClsID,sizeof(CLSID));
- *pClsID = CLSID_SystemClock;
- return NOERROR;
-}
-
-
-STDMETHODIMP
-CSystemClock::SetClockDelta(REFERENCE_TIME rtDelta)
-{
- return SetTimeDelta(rtDelta);
-}
diff --git a/dll/src/baseclasses/sysclock.h b/dll/src/baseclasses/sysclock.h
deleted file mode 100644
index 3976d34..0000000
--- a/dll/src/baseclasses/sysclock.h
+++ /dev/null
@@ -1,39 +0,0 @@
-//------------------------------------------------------------------------------
-// File: SysClock.h
-//
-// Desc: DirectShow base classes - defines a system clock implementation of
-// IReferenceClock.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-#ifndef __SYSTEMCLOCK__
-#define __SYSTEMCLOCK__
-
-//
-// Base clock. Uses timeGetTime ONLY
-// Uses most of the code in the base reference clock.
-// Provides GetTime
-//
-
-class CSystemClock : public CBaseReferenceClock, public IAMClockAdjust, public IPersist
-{
-public:
- // We must be able to create an instance of ourselves
- static CUnknown * WINAPI CreateInstance(__inout_opt LPUNKNOWN pUnk, __inout HRESULT *phr);
- CSystemClock(__in_opt LPCTSTR pName, __inout_opt LPUNKNOWN pUnk, __inout HRESULT *phr);
-
- DECLARE_IUNKNOWN
-
- STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void ** ppv);
-
- // Yield up our class id so that we can be persisted
- // Implement required Ipersist method
- STDMETHODIMP GetClassID(__out CLSID *pClsID);
-
- // IAMClockAdjust methods
- STDMETHODIMP SetClockDelta(REFERENCE_TIME rtDelta);
-}; //CSystemClock
-
-#endif /* __SYSTEMCLOCK__ */
diff --git a/dll/src/baseclasses/transfrm.cpp b/dll/src/baseclasses/transfrm.cpp
deleted file mode 100644
index 3d17077..0000000
--- a/dll/src/baseclasses/transfrm.cpp
+++ /dev/null
@@ -1,1016 +0,0 @@
-//------------------------------------------------------------------------------
-// File: Transfrm.cpp
-//
-// Desc: DirectShow base classes - implements class for simple transform
-// filters such as video decompressors.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-#include <streams.h>
-#include <measure.h>
-
-
-// =================================================================
-// Implements the CTransformFilter class
-// =================================================================
-
-CTransformFilter::CTransformFilter(__in_opt LPCTSTR pName,
- __inout_opt LPUNKNOWN pUnk,
- REFCLSID clsid) :
- CBaseFilter(pName,pUnk,&m_csFilter, clsid),
- m_pInput(NULL),
- m_pOutput(NULL),
- m_bEOSDelivered(FALSE),
- m_bQualityChanged(FALSE),
- m_bSampleSkipped(FALSE)
-{
-#ifdef PERF
- RegisterPerfId();
-#endif // PERF
-}
-
-#ifdef UNICODE
-CTransformFilter::CTransformFilter(__in_opt LPCSTR pName,
- __inout_opt LPUNKNOWN pUnk,
- REFCLSID clsid) :
- CBaseFilter(pName,pUnk,&m_csFilter, clsid),
- m_pInput(NULL),
- m_pOutput(NULL),
- m_bEOSDelivered(FALSE),
- m_bQualityChanged(FALSE),
- m_bSampleSkipped(FALSE)
-{
-#ifdef PERF
- RegisterPerfId();
-#endif // PERF
-}
-#endif
-
-// destructor
-
-CTransformFilter::~CTransformFilter()
-{
- // Delete the pins
-
- delete m_pInput;
- delete m_pOutput;
-}
-
-
-// Transform place holder - should never be called
-HRESULT CTransformFilter::Transform(IMediaSample * pIn, IMediaSample *pOut)
-{
- UNREFERENCED_PARAMETER(pIn);
- UNREFERENCED_PARAMETER(pOut);
- DbgBreak("CTransformFilter::Transform() should never be called");
- return E_UNEXPECTED;
-}
-
-
-// return the number of pins we provide
-
-int CTransformFilter::GetPinCount()
-{
- return 2;
-}
-
-
-// return a non-addrefed CBasePin * for the user to addref if he holds onto it
-// for longer than his pointer to us. We create the pins dynamically when they
-// are asked for rather than in the constructor. This is because we want to
-// give the derived class an oppportunity to return different pin objects
-
-// We return the objects as and when they are needed. If either of these fails
-// then we return NULL, the assumption being that the caller will realise the
-// whole deal is off and destroy us - which in turn will delete everything.
-
-CBasePin *
-CTransformFilter::GetPin(int n)
-{
- HRESULT hr = S_OK;
-
- // Create an input pin if necessary
-
- if (m_pInput == NULL) {
-
- m_pInput = new CTransformInputPin(NAME("Transform input pin"),
- this, // Owner filter
- &hr, // Result code
- L"XForm In"); // Pin name
-
-
- // Can't fail
- ASSERT(SUCCEEDED(hr));
- if (m_pInput == NULL) {
- return NULL;
- }
- m_pOutput = (CTransformOutputPin *)
- new CTransformOutputPin(NAME("Transform output pin"),
- this, // Owner filter
- &hr, // Result code
- L"XForm Out"); // Pin name
-
-
- // Can't fail
- ASSERT(SUCCEEDED(hr));
- if (m_pOutput == NULL) {
- delete m_pInput;
- m_pInput = NULL;
- }
- }
-
- // Return the appropriate pin
-
- if (n == 0) {
- return m_pInput;
- } else
- if (n == 1) {
- return m_pOutput;
- } else {
- return NULL;
- }
-}
-
-
-//
-// FindPin
-//
-// If Id is In or Out then return the IPin* for that pin
-// creating the pin if need be. Otherwise return NULL with an error.
-
-STDMETHODIMP CTransformFilter::FindPin(LPCWSTR Id, __deref_out IPin **ppPin)
-{
- CheckPointer(ppPin,E_POINTER);
- ValidateReadWritePtr(ppPin,sizeof(IPin *));
-
- if (0==lstrcmpW(Id,L"In")) {
- *ppPin = GetPin(0);
- } else if (0==lstrcmpW(Id,L"Out")) {
- *ppPin = GetPin(1);
- } else {
- *ppPin = NULL;
- return VFW_E_NOT_FOUND;
- }
-
- HRESULT hr = NOERROR;
- // AddRef() returned pointer - but GetPin could fail if memory is low.
- if (*ppPin) {
- (*ppPin)->AddRef();
- } else {
- hr = E_OUTOFMEMORY; // probably. There's no pin anyway.
- }
- return hr;
-}
-
-
-// override these two functions if you want to inform something
-// about entry to or exit from streaming state.
-
-HRESULT
-CTransformFilter::StartStreaming()
-{
- return NOERROR;
-}
-
-
-HRESULT
-CTransformFilter::StopStreaming()
-{
- return NOERROR;
-}
-
-
-// override this to grab extra interfaces on connection
-
-HRESULT
-CTransformFilter::CheckConnect(PIN_DIRECTION dir, IPin *pPin)
-{
- UNREFERENCED_PARAMETER(dir);
- UNREFERENCED_PARAMETER(pPin);
- return NOERROR;
-}
-
-
-// place holder to allow derived classes to release any extra interfaces
-
-HRESULT
-CTransformFilter::BreakConnect(PIN_DIRECTION dir)
-{
- UNREFERENCED_PARAMETER(dir);
- return NOERROR;
-}
-
-
-// Let derived classes know about connection completion
-
-HRESULT
-CTransformFilter::CompleteConnect(PIN_DIRECTION direction,IPin *pReceivePin)
-{
- UNREFERENCED_PARAMETER(direction);
- UNREFERENCED_PARAMETER(pReceivePin);
- return NOERROR;
-}
-
-
-// override this to know when the media type is really set
-
-HRESULT
-CTransformFilter::SetMediaType(PIN_DIRECTION direction,const CMediaType *pmt)
-{
- UNREFERENCED_PARAMETER(direction);
- UNREFERENCED_PARAMETER(pmt);
- return NOERROR;
-}
-
-
-// Set up our output sample
-HRESULT
-CTransformFilter::InitializeOutputSample(IMediaSample *pSample, __deref_out IMediaSample **ppOutSample)
-{
- IMediaSample *pOutSample;
-
- // default - times are the same
-
- AM_SAMPLE2_PROPERTIES * const pProps = m_pInput->SampleProps();
- DWORD dwFlags = m_bSampleSkipped ? AM_GBF_PREVFRAMESKIPPED : 0;
-
- // This will prevent the image renderer from switching us to DirectDraw
- // when we can't do it without skipping frames because we're not on a
- // keyframe. If it really has to switch us, it still will, but then we
- // will have to wait for the next keyframe
- if (!(pProps->dwSampleFlags & AM_SAMPLE_SPLICEPOINT)) {
- dwFlags |= AM_GBF_NOTASYNCPOINT;
- }
-
- ASSERT(m_pOutput->m_pAllocator != NULL);
- HRESULT hr = m_pOutput->m_pAllocator->GetBuffer(
- &pOutSample
- , pProps->dwSampleFlags & AM_SAMPLE_TIMEVALID ?
- &pProps->tStart : NULL
- , pProps->dwSampleFlags & AM_SAMPLE_STOPVALID ?
- &pProps->tStop : NULL
- , dwFlags
- );
- *ppOutSample = pOutSample;
- if (FAILED(hr)) {
- return hr;
- }
-
- ASSERT(pOutSample);
- IMediaSample2 *pOutSample2;
- if (SUCCEEDED(pOutSample->QueryInterface(IID_IMediaSample2,
- (void **)&pOutSample2))) {
- /* Modify it */
- AM_SAMPLE2_PROPERTIES OutProps;
- EXECUTE_ASSERT(SUCCEEDED(pOutSample2->GetProperties(
- FIELD_OFFSET(AM_SAMPLE2_PROPERTIES, tStart), (PBYTE)&OutProps)
- ));
- OutProps.dwTypeSpecificFlags = pProps->dwTypeSpecificFlags;
- OutProps.dwSampleFlags =
- (OutProps.dwSampleFlags & AM_SAMPLE_TYPECHANGED) |
- (pProps->dwSampleFlags & ~AM_SAMPLE_TYPECHANGED);
- OutProps.tStart = pProps->tStart;
- OutProps.tStop = pProps->tStop;
- OutProps.cbData = FIELD_OFFSET(AM_SAMPLE2_PROPERTIES, dwStreamId);
- hr = pOutSample2->SetProperties(
- FIELD_OFFSET(AM_SAMPLE2_PROPERTIES, dwStreamId),
- (PBYTE)&OutProps
- );
- if (pProps->dwSampleFlags & AM_SAMPLE_DATADISCONTINUITY) {
- m_bSampleSkipped = FALSE;
- }
- pOutSample2->Release();
- } else {
- if (pProps->dwSampleFlags & AM_SAMPLE_TIMEVALID) {
- pOutSample->SetTime(&pProps->tStart,
- &pProps->tStop);
- }
- if (pProps->dwSampleFlags & AM_SAMPLE_SPLICEPOINT) {
- pOutSample->SetSyncPoint(TRUE);
- }
- if (pProps->dwSampleFlags & AM_SAMPLE_DATADISCONTINUITY) {
- pOutSample->SetDiscontinuity(TRUE);
- m_bSampleSkipped = FALSE;
- }
- // Copy the media times
-
- LONGLONG MediaStart, MediaEnd;
- if (pSample->GetMediaTime(&MediaStart,&MediaEnd) == NOERROR) {
- pOutSample->SetMediaTime(&MediaStart,&MediaEnd);
- }
- }
- return S_OK;
-}
-
-// override this to customize the transform process
-
-HRESULT
-CTransformFilter::Receive(IMediaSample *pSample)
-{
- /* Check for other streams and pass them on */
- AM_SAMPLE2_PROPERTIES * const pProps = m_pInput->SampleProps();
- if (pProps->dwStreamId != AM_STREAM_MEDIA) {
- return m_pOutput->m_pInputPin->Receive(pSample);
- }
- HRESULT hr;
- ASSERT(pSample);
- IMediaSample * pOutSample;
-
- // If no output to deliver to then no point sending us data
-
- ASSERT (m_pOutput != NULL) ;
-
- // Set up the output sample
- hr = InitializeOutputSample(pSample, &pOutSample);
-
- if (FAILED(hr)) {
- return hr;
- }
-
- // Start timing the transform (if PERF is defined)
- MSR_START(m_idTransform);
-
- // have the derived class transform the data
-
- hr = Transform(pSample, pOutSample);
-
- // Stop the clock and log it (if PERF is defined)
- MSR_STOP(m_idTransform);
-
- if (FAILED(hr)) {
- DbgLog((LOG_TRACE,1,TEXT("Error from transform")));
- } else {
- // the Transform() function can return S_FALSE to indicate that the
- // sample should not be delivered; we only deliver the sample if it's
- // really S_OK (same as NOERROR, of course.)
- if (hr == NOERROR) {
- hr = m_pOutput->m_pInputPin->Receive(pOutSample);
- m_bSampleSkipped = FALSE; // last thing no longer dropped
- } else {
- // S_FALSE returned from Transform is a PRIVATE agreement
- // We should return NOERROR from Receive() in this cause because returning S_FALSE
- // from Receive() means that this is the end of the stream and no more data should
- // be sent.
- if (S_FALSE == hr) {
-
- // Release the sample before calling notify to avoid
- // deadlocks if the sample holds a lock on the system
- // such as DirectDraw buffers do
- pOutSample->Release();
- m_bSampleSkipped = TRUE;
- if (!m_bQualityChanged) {
- NotifyEvent(EC_QUALITY_CHANGE,0,0);
- m_bQualityChanged = TRUE;
- }
- return NOERROR;
- }
- }
- }
-
- // release the output buffer. If the connected pin still needs it,
- // it will have addrefed it itself.
- pOutSample->Release();
-
- return hr;
-}
-
-
-// Return S_FALSE to mean "pass the note on upstream"
-// Return NOERROR (Same as S_OK)
-// to mean "I've done something about it, don't pass it on"
-HRESULT CTransformFilter::AlterQuality(Quality q)
-{
- UNREFERENCED_PARAMETER(q);
- return S_FALSE;
-}
-
-
-// EndOfStream received. Default behaviour is to deliver straight
-// downstream, since we have no queued data. If you overrode Receive
-// and have queue data, then you need to handle this and deliver EOS after
-// all queued data is sent
-HRESULT
-CTransformFilter::EndOfStream(void)
-{
- HRESULT hr = NOERROR;
- if (m_pOutput != NULL) {
- hr = m_pOutput->DeliverEndOfStream();
- }
-
- return hr;
-}
-
-
-// enter flush state. Receives already blocked
-// must override this if you have queued data or a worker thread
-HRESULT
-CTransformFilter::BeginFlush(void)
-{
- HRESULT hr = NOERROR;
- if (m_pOutput != NULL) {
- // block receives -- done by caller (CBaseInputPin::BeginFlush)
-
- // discard queued data -- we have no queued data
-
- // free anyone blocked on receive - not possible in this filter
-
- // call downstream
- hr = m_pOutput->DeliverBeginFlush();
- }
- return hr;
-}
-
-
-// leave flush state. must override this if you have queued data
-// or a worker thread
-HRESULT
-CTransformFilter::EndFlush(void)
-{
- // sync with pushing thread -- we have no worker thread
-
- // ensure no more data to go downstream -- we have no queued data
-
- // call EndFlush on downstream pins
- ASSERT (m_pOutput != NULL);
- return m_pOutput->DeliverEndFlush();
-
- // caller (the input pin's method) will unblock Receives
-}
-
-
-// override these so that the derived filter can catch them
-
-STDMETHODIMP
-CTransformFilter::Stop()
-{
- CAutoLock lck1(&m_csFilter);
- if (m_State == State_Stopped) {
- return NOERROR;
- }
-
- // Succeed the Stop if we are not completely connected
-
- ASSERT(m_pInput == NULL || m_pOutput != NULL);
- if (m_pInput == NULL || m_pInput->IsConnected() == FALSE ||
- m_pOutput->IsConnected() == FALSE) {
- m_State = State_Stopped;
- m_bEOSDelivered = FALSE;
- return NOERROR;
- }
-
- ASSERT(m_pInput);
- ASSERT(m_pOutput);
-
- // decommit the input pin before locking or we can deadlock
- m_pInput->Inactive();
-
- // synchronize with Receive calls
-
- CAutoLock lck2(&m_csReceive);
- m_pOutput->Inactive();
-
- // allow a class derived from CTransformFilter
- // to know about starting and stopping streaming
-
- HRESULT hr = StopStreaming();
- if (SUCCEEDED(hr)) {
- // complete the state transition
- m_State = State_Stopped;
- m_bEOSDelivered = FALSE;
- }
- return hr;
-}
-
-
-STDMETHODIMP
-CTransformFilter::Pause()
-{
- CAutoLock lck(&m_csFilter);
- HRESULT hr = NOERROR;
-
- if (m_State == State_Paused) {
- // (This space left deliberately blank)
- }
-
- // If we have no input pin or it isn't yet connected then when we are
- // asked to pause we deliver an end of stream to the downstream filter.
- // This makes sure that it doesn't sit there forever waiting for
- // samples which we cannot ever deliver without an input connection.
-
- else if (m_pInput == NULL || m_pInput->IsConnected() == FALSE) {
- if (m_pOutput && m_bEOSDelivered == FALSE) {
- m_pOutput->DeliverEndOfStream();
- m_bEOSDelivered = TRUE;
- }
- m_State = State_Paused;
- }
-
- // We may have an input connection but no output connection
- // However, if we have an input pin we do have an output pin
-
- else if (m_pOutput->IsConnected() == FALSE) {
- m_State = State_Paused;
- }
-
- else {
- if (m_State == State_Stopped) {
- // allow a class derived from CTransformFilter
- // to know about starting and stopping streaming
- CAutoLock lck2(&m_csReceive);
- hr = StartStreaming();
- }
- if (SUCCEEDED(hr)) {
- hr = CBaseFilter::Pause();
- }
- }
-
- m_bSampleSkipped = FALSE;
- m_bQualityChanged = FALSE;
- return hr;
-}
-
-HRESULT
-CTransformFilter::NewSegment(
- REFERENCE_TIME tStart,
- REFERENCE_TIME tStop,
- double dRate)
-{
- if (m_pOutput != NULL) {
- return m_pOutput->DeliverNewSegment(tStart, tStop, dRate);
- }
- return S_OK;
-}
-
-// Check streaming status
-HRESULT
-CTransformInputPin::CheckStreaming()
-{
- ASSERT(m_pTransformFilter->m_pOutput != NULL);
- if (!m_pTransformFilter->m_pOutput->IsConnected()) {
- return VFW_E_NOT_CONNECTED;
- } else {
- // Shouldn't be able to get any data if we're not connected!
- ASSERT(IsConnected());
-
- // we're flushing
- if (m_bFlushing) {
- return S_FALSE;
- }
- // Don't process stuff in Stopped state
- if (IsStopped()) {
- return VFW_E_WRONG_STATE;
- }
- if (m_bRunTimeError) {
- return VFW_E_RUNTIME_ERROR;
- }
- return S_OK;
- }
-}
-
-
-// =================================================================
-// Implements the CTransformInputPin class
-// =================================================================
-
-
-// constructor
-
-CTransformInputPin::CTransformInputPin(
- __in_opt LPCTSTR pObjectName,
- __inout CTransformFilter *pTransformFilter,
- __inout HRESULT * phr,
- __in_opt LPCWSTR pName)
- : CBaseInputPin(pObjectName, pTransformFilter, &pTransformFilter->m_csFilter, phr, pName)
-{
- DbgLog((LOG_TRACE,2,TEXT("CTransformInputPin::CTransformInputPin")));
- m_pTransformFilter = pTransformFilter;
-}
-
-#ifdef UNICODE
-CTransformInputPin::CTransformInputPin(
- __in_opt LPCSTR pObjectName,
- __inout CTransformFilter *pTransformFilter,
- __inout HRESULT * phr,
- __in_opt LPCWSTR pName)
- : CBaseInputPin(pObjectName, pTransformFilter, &pTransformFilter->m_csFilter, phr, pName)
-{
- DbgLog((LOG_TRACE,2,TEXT("CTransformInputPin::CTransformInputPin")));
- m_pTransformFilter = pTransformFilter;
-}
-#endif
-
-// provides derived filter a chance to grab extra interfaces
-
-HRESULT
-CTransformInputPin::CheckConnect(IPin *pPin)
-{
- HRESULT hr = m_pTransformFilter->CheckConnect(PINDIR_INPUT,pPin);
- if (FAILED(hr)) {
- return hr;
- }
- return CBaseInputPin::CheckConnect(pPin);
-}
-
-
-// provides derived filter a chance to release it's extra interfaces
-
-HRESULT
-CTransformInputPin::BreakConnect()
-{
- // Can't disconnect unless stopped
- ASSERT(IsStopped());
- m_pTransformFilter->BreakConnect(PINDIR_INPUT);
- return CBaseInputPin::BreakConnect();
-}
-
-
-// Let derived class know when the input pin is connected
-
-HRESULT
-CTransformInputPin::CompleteConnect(IPin *pReceivePin)
-{
- HRESULT hr = m_pTransformFilter->CompleteConnect(PINDIR_INPUT,pReceivePin);
- if (FAILED(hr)) {
- return hr;
- }
- return CBaseInputPin::CompleteConnect(pReceivePin);
-}
-
-
-// check that we can support a given media type
-
-HRESULT
-CTransformInputPin::CheckMediaType(const CMediaType* pmt)
-{
- // Check the input type
-
- HRESULT hr = m_pTransformFilter->CheckInputType(pmt);
- if (S_OK != hr) {
- return hr;
- }
-
- // if the output pin is still connected, then we have
- // to check the transform not just the input format
-
- if ((m_pTransformFilter->m_pOutput != NULL) &&
- (m_pTransformFilter->m_pOutput->IsConnected())) {
- return m_pTransformFilter->CheckTransform(
- pmt,
- &m_pTransformFilter->m_pOutput->CurrentMediaType());
- } else {
- return hr;
- }
-}
-
-
-// set the media type for this connection
-
-HRESULT
-CTransformInputPin::SetMediaType(const CMediaType* mtIn)
-{
- // Set the base class media type (should always succeed)
- HRESULT hr = CBasePin::SetMediaType(mtIn);
- if (FAILED(hr)) {
- return hr;
- }
-
- // check the transform can be done (should always succeed)
- ASSERT(SUCCEEDED(m_pTransformFilter->CheckInputType(mtIn)));
-
- return m_pTransformFilter->SetMediaType(PINDIR_INPUT,mtIn);
-}
-
-
-// =================================================================
-// Implements IMemInputPin interface
-// =================================================================
-
-
-// provide EndOfStream that passes straight downstream
-// (there is no queued data)
-STDMETHODIMP
-CTransformInputPin::EndOfStream(void)
-{
- CAutoLock lck(&m_pTransformFilter->m_csReceive);
- HRESULT hr = CheckStreaming();
- if (S_OK == hr) {
- hr = m_pTransformFilter->EndOfStream();
- }
- return hr;
-}
-
-
-// enter flushing state. Call default handler to block Receives, then
-// pass to overridable method in filter
-STDMETHODIMP
-CTransformInputPin::BeginFlush(void)
-{
- CAutoLock lck(&m_pTransformFilter->m_csFilter);
- // Are we actually doing anything?
- ASSERT(m_pTransformFilter->m_pOutput != NULL);
- if (!IsConnected() ||
- !m_pTransformFilter->m_pOutput->IsConnected()) {
- return VFW_E_NOT_CONNECTED;
- }
- HRESULT hr = CBaseInputPin::BeginFlush();
- if (FAILED(hr)) {
- return hr;
- }
-
- return m_pTransformFilter->BeginFlush();
-}
-
-
-// leave flushing state.
-// Pass to overridable method in filter, then call base class
-// to unblock receives (finally)
-STDMETHODIMP
-CTransformInputPin::EndFlush(void)
-{
- CAutoLock lck(&m_pTransformFilter->m_csFilter);
- // Are we actually doing anything?
- ASSERT(m_pTransformFilter->m_pOutput != NULL);
- if (!IsConnected() ||
- !m_pTransformFilter->m_pOutput->IsConnected()) {
- return VFW_E_NOT_CONNECTED;
- }
-
- HRESULT hr = m_pTransformFilter->EndFlush();
- if (FAILED(hr)) {
- return hr;
- }
-
- return CBaseInputPin::EndFlush();
-}
-
-
-// here's the next block of data from the stream.
-// AddRef it yourself if you need to hold it beyond the end
-// of this call.
-
-HRESULT
-CTransformInputPin::Receive(IMediaSample * pSample)
-{
- HRESULT hr;
- CAutoLock lck(&m_pTransformFilter->m_csReceive);
- ASSERT(pSample);
-
- // check all is well with the base class
- hr = CBaseInputPin::Receive(pSample);
- if (S_OK == hr) {
- hr = m_pTransformFilter->Receive(pSample);
- }
- return hr;
-}
-
-
-
-
-// override to pass downstream
-STDMETHODIMP
-CTransformInputPin::NewSegment(
- REFERENCE_TIME tStart,
- REFERENCE_TIME tStop,
- double dRate)
-{
- // Save the values in the pin
- CBasePin::NewSegment(tStart, tStop, dRate);
- return m_pTransformFilter->NewSegment(tStart, tStop, dRate);
-}
-
-
-
-
-// =================================================================
-// Implements the CTransformOutputPin class
-// =================================================================
-
-
-// constructor
-
-CTransformOutputPin::CTransformOutputPin(
- __in_opt LPCTSTR pObjectName,
- __inout CTransformFilter *pTransformFilter,
- __inout HRESULT * phr,
- __in_opt LPCWSTR pPinName)
- : CBaseOutputPin(pObjectName, pTransformFilter, &pTransformFilter->m_csFilter, phr, pPinName),
- m_pPosition(NULL)
-{
- DbgLog((LOG_TRACE,2,TEXT("CTransformOutputPin::CTransformOutputPin")));
- m_pTransformFilter = pTransformFilter;
-
-}
-
-#ifdef UNICODE
-CTransformOutputPin::CTransformOutputPin(
- __in_opt LPCSTR pObjectName,
- __inout CTransformFilter *pTransformFilter,
- __inout HRESULT * phr,
- __in_opt LPCWSTR pPinName)
- : CBaseOutputPin(pObjectName, pTransformFilter, &pTransformFilter->m_csFilter, phr, pPinName),
- m_pPosition(NULL)
-{
- DbgLog((LOG_TRACE,2,TEXT("CTransformOutputPin::CTransformOutputPin")));
- m_pTransformFilter = pTransformFilter;
-
-}
-#endif
-
-// destructor
-
-CTransformOutputPin::~CTransformOutputPin()
-{
- DbgLog((LOG_TRACE,2,TEXT("CTransformOutputPin::~CTransformOutputPin")));
-
- if (m_pPosition) m_pPosition->Release();
-}
-
-
-// overriden to expose IMediaPosition and IMediaSeeking control interfaces
-
-STDMETHODIMP
-CTransformOutputPin::NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv)
-{
- CheckPointer(ppv,E_POINTER);
- ValidateReadWritePtr(ppv,sizeof(PVOID));
- *ppv = NULL;
-
- if (riid == IID_IMediaPosition || riid == IID_IMediaSeeking) {
-
- // we should have an input pin by now
-
- ASSERT(m_pTransformFilter->m_pInput != NULL);
-
- if (m_pPosition == NULL) {
-
- HRESULT hr = CreatePosPassThru(
- GetOwner(),
- FALSE,
- (IPin *)m_pTransformFilter->m_pInput,
- &m_pPosition);
- if (FAILED(hr)) {
- return hr;
- }
- }
- return m_pPosition->QueryInterface(riid, ppv);
- } else {
- return CBaseOutputPin::NonDelegatingQueryInterface(riid, ppv);
- }
-}
-
-
-// provides derived filter a chance to grab extra interfaces
-
-HRESULT
-CTransformOutputPin::CheckConnect(IPin *pPin)
-{
- // we should have an input connection first
-
- ASSERT(m_pTransformFilter->m_pInput != NULL);
- if ((m_pTransformFilter->m_pInput->IsConnected() == FALSE)) {
- return E_UNEXPECTED;
- }
-
- HRESULT hr = m_pTransformFilter->CheckConnect(PINDIR_OUTPUT,pPin);
- if (FAILED(hr)) {
- return hr;
- }
- return CBaseOutputPin::CheckConnect(pPin);
-}
-
-
-// provides derived filter a chance to release it's extra interfaces
-
-HRESULT
-CTransformOutputPin::BreakConnect()
-{
- // Can't disconnect unless stopped
- ASSERT(IsStopped());
- m_pTransformFilter->BreakConnect(PINDIR_OUTPUT);
- return CBaseOutputPin::BreakConnect();
-}
-
-
-// Let derived class know when the output pin is connected
-
-HRESULT
-CTransformOutputPin::CompleteConnect(IPin *pReceivePin)
-{
- HRESULT hr = m_pTransformFilter->CompleteConnect(PINDIR_OUTPUT,pReceivePin);
- if (FAILED(hr)) {
- return hr;
- }
- return CBaseOutputPin::CompleteConnect(pReceivePin);
-}
-
-
-// check a given transform - must have selected input type first
-
-HRESULT
-CTransformOutputPin::CheckMediaType(const CMediaType* pmtOut)
-{
- // must have selected input first
- ASSERT(m_pTransformFilter->m_pInput != NULL);
- if ((m_pTransformFilter->m_pInput->IsConnected() == FALSE)) {
- return E_INVALIDARG;
- }
-
- return m_pTransformFilter->CheckTransform(
- &m_pTransformFilter->m_pInput->CurrentMediaType(),
- pmtOut);
-}
-
-
-// called after we have agreed a media type to actually set it in which case
-// we run the CheckTransform function to get the output format type again
-
-HRESULT
-CTransformOutputPin::SetMediaType(const CMediaType* pmtOut)
-{
- HRESULT hr = NOERROR;
- ASSERT(m_pTransformFilter->m_pInput != NULL);
-
- ASSERT(m_pTransformFilter->m_pInput->CurrentMediaType().IsValid());
-
- // Set the base class media type (should always succeed)
- hr = CBasePin::SetMediaType(pmtOut);
- if (FAILED(hr)) {
- return hr;
- }
-
-#ifdef DEBUG
- if (FAILED(m_pTransformFilter->CheckTransform(&m_pTransformFilter->
- m_pInput->CurrentMediaType(),pmtOut))) {
- DbgLog((LOG_ERROR,0,TEXT("*** This filter is accepting an output media type")));
- DbgLog((LOG_ERROR,0,TEXT(" that it can't currently transform to. I hope")));
- DbgLog((LOG_ERROR,0,TEXT(" it's smart enough to reconnect its input.")));
- }
-#endif
-
- return m_pTransformFilter->SetMediaType(PINDIR_OUTPUT,pmtOut);
-}
-
-
-// pass the buffer size decision through to the main transform class
-
-HRESULT
-CTransformOutputPin::DecideBufferSize(
- IMemAllocator * pAllocator,
- __inout ALLOCATOR_PROPERTIES* pProp)
-{
- return m_pTransformFilter->DecideBufferSize(pAllocator, pProp);
-}
-
-
-
-// return a specific media type indexed by iPosition
-
-HRESULT
-CTransformOutputPin::GetMediaType(
- int iPosition,
- __inout CMediaType *pMediaType)
-{
- ASSERT(m_pTransformFilter->m_pInput != NULL);
-
- // We don't have any media types if our input is not connected
-
- if (m_pTransformFilter->m_pInput->IsConnected()) {
- return m_pTransformFilter->GetMediaType(iPosition,pMediaType);
- } else {
- return VFW_S_NO_MORE_ITEMS;
- }
-}
-
-
-// Override this if you can do something constructive to act on the
-// quality message. Consider passing it upstream as well
-
-// Pass the quality mesage on upstream.
-
-STDMETHODIMP
-CTransformOutputPin::Notify(IBaseFilter * pSender, Quality q)
-{
- UNREFERENCED_PARAMETER(pSender);
- ValidateReadPtr(pSender,sizeof(IBaseFilter));
-
- // First see if we want to handle this ourselves
- HRESULT hr = m_pTransformFilter->AlterQuality(q);
- if (hr!=S_FALSE) {
- return hr; // either S_OK or a failure
- }
-
- // S_FALSE means we pass the message on.
- // Find the quality sink for our input pin and send it there
-
- ASSERT(m_pTransformFilter->m_pInput != NULL);
-
- return m_pTransformFilter->m_pInput->PassNotify(q);
-
-} // Notify
-
-
-// the following removes a very large number of level 4 warnings from the microsoft
-// compiler output, which are not useful at all in this case.
-#pragma warning(disable:4514)
diff --git a/dll/src/baseclasses/transfrm.h b/dll/src/baseclasses/transfrm.h
deleted file mode 100644
index 9b27647..0000000
--- a/dll/src/baseclasses/transfrm.h
+++ /dev/null
@@ -1,304 +0,0 @@
-//------------------------------------------------------------------------------
-// File: Transfrm.h
-//
-// Desc: DirectShow base classes - defines classes from which simple
-// transform codecs may be derived.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-// It assumes the codec has one input and one output stream, and has no
-// interest in memory management, interface negotiation or anything else.
-//
-// derive your class from this, and supply Transform and the media type/format
-// negotiation functions. Implement that class, compile and link and
-// you're done.
-
-
-#ifndef __TRANSFRM__
-#define __TRANSFRM__
-
-// ======================================================================
-// This is the com object that represents a simple transform filter. It
-// supports IBaseFilter, IMediaFilter and two pins through nested interfaces
-// ======================================================================
-
-class CTransformFilter;
-
-// ==================================================
-// Implements the input pin
-// ==================================================
-
-class CTransformInputPin : public CBaseInputPin
-{
- friend class CTransformFilter;
-
-protected:
- CTransformFilter *m_pTransformFilter;
-
-
-public:
-
- CTransformInputPin(
- __in_opt LPCTSTR pObjectName,
- __inout CTransformFilter *pTransformFilter,
- __inout HRESULT * phr,
- __in_opt LPCWSTR pName);
-#ifdef UNICODE
- CTransformInputPin(
- __in_opt LPCSTR pObjectName,
- __inout CTransformFilter *pTransformFilter,
- __inout HRESULT * phr,
- __in_opt LPCWSTR pName);
-#endif
-
- STDMETHODIMP QueryId(__deref_out LPWSTR * Id)
- {
- return AMGetWideString(L"In", Id);
- }
-
- // Grab and release extra interfaces if required
-
- HRESULT CheckConnect(IPin *pPin);
- HRESULT BreakConnect();
- HRESULT CompleteConnect(IPin *pReceivePin);
-
- // check that we can support this output type
- HRESULT CheckMediaType(const CMediaType* mtIn);
-
- // set the connection media type
- HRESULT SetMediaType(const CMediaType* mt);
-
- // --- IMemInputPin -----
-
- // here's the next block of data from the stream.
- // AddRef it yourself if you need to hold it beyond the end
- // of this call.
- STDMETHODIMP Receive(IMediaSample * pSample);
-
- // provide EndOfStream that passes straight downstream
- // (there is no queued data)
- STDMETHODIMP EndOfStream(void);
-
- // passes it to CTransformFilter::BeginFlush
- STDMETHODIMP BeginFlush(void);
-
- // passes it to CTransformFilter::EndFlush
- STDMETHODIMP EndFlush(void);
-
- STDMETHODIMP NewSegment(
- REFERENCE_TIME tStart,
- REFERENCE_TIME tStop,
- double dRate);
-
- // Check if it's OK to process samples
- virtual HRESULT CheckStreaming();
-
- // Media type
-public:
- CMediaType& CurrentMediaType() { return m_mt; };
-
-};
-
-// ==================================================
-// Implements the output pin
-// ==================================================
-
-class CTransformOutputPin : public CBaseOutputPin
-{
- friend class CTransformFilter;
-
-protected:
- CTransformFilter *m_pTransformFilter;
-
-public:
-
- // implement IMediaPosition by passing upstream
- IUnknown * m_pPosition;
-
- CTransformOutputPin(
- __in_opt LPCTSTR pObjectName,
- __inout CTransformFilter *pTransformFilter,
- __inout HRESULT * phr,
- __in_opt LPCWSTR pName);
-#ifdef UNICODE
- CTransformOutputPin(
- __in_opt LPCSTR pObjectName,
- __inout CTransformFilter *pTransformFilter,
- __inout HRESULT * phr,
- __in_opt LPCWSTR pName);
-#endif
- ~CTransformOutputPin();
-
- // override to expose IMediaPosition
- STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
-
- // --- CBaseOutputPin ------------
-
- STDMETHODIMP QueryId(__deref_out LPWSTR * Id)
- {
- return AMGetWideString(L"Out", Id);
- }
-
- // Grab and release extra interfaces if required
-
- HRESULT CheckConnect(IPin *pPin);
- HRESULT BreakConnect();
- HRESULT CompleteConnect(IPin *pReceivePin);
-
- // check that we can support this output type
- HRESULT CheckMediaType(const CMediaType* mtOut);
-
- // set the connection media type
- HRESULT SetMediaType(const CMediaType *pmt);
-
- // called from CBaseOutputPin during connection to ask for
- // the count and size of buffers we need.
- HRESULT DecideBufferSize(
- IMemAllocator * pAlloc,
- __inout ALLOCATOR_PROPERTIES *pProp);
-
- // returns the preferred formats for a pin
- HRESULT GetMediaType(int iPosition, __inout CMediaType *pMediaType);
-
- // inherited from IQualityControl via CBasePin
- STDMETHODIMP Notify(IBaseFilter * pSender, Quality q);
-
- // Media type
-public:
- CMediaType& CurrentMediaType() { return m_mt; };
-};
-
-
-class AM_NOVTABLE CTransformFilter : public CBaseFilter
-{
-
-public:
-
- // map getpin/getpincount for base enum of pins to owner
- // override this to return more specialised pin objects
-
- virtual int GetPinCount();
- virtual CBasePin * GetPin(int n);
- STDMETHODIMP FindPin(LPCWSTR Id, __deref_out IPin **ppPin);
-
- // override state changes to allow derived transform filter
- // to control streaming start/stop
- STDMETHODIMP Stop();
- STDMETHODIMP Pause();
-
-public:
-
- CTransformFilter(__in_opt LPCTSTR , __inout_opt LPUNKNOWN, REFCLSID clsid);
-#ifdef UNICODE
- CTransformFilter(__in_opt LPCSTR , __inout_opt LPUNKNOWN, REFCLSID clsid);
-#endif
- ~CTransformFilter();
-
- // =================================================================
- // ----- override these bits ---------------------------------------
- // =================================================================
-
- // These must be supplied in a derived class
-
- virtual HRESULT Transform(IMediaSample * pIn, IMediaSample *pOut);
-
- // check if you can support mtIn
- virtual HRESULT CheckInputType(const CMediaType* mtIn) PURE;
-
- // check if you can support the transform from this input to this output
- virtual HRESULT CheckTransform(const CMediaType* mtIn, const CMediaType* mtOut) PURE;
-
- // this goes in the factory template table to create new instances
- // static CCOMObject * CreateInstance(__inout_opt LPUNKNOWN, HRESULT *);
-
- // call the SetProperties function with appropriate arguments
- virtual HRESULT DecideBufferSize(
- IMemAllocator * pAllocator,
- __inout ALLOCATOR_PROPERTIES *pprop) PURE;
-
- // override to suggest OUTPUT pin media types
- virtual HRESULT GetMediaType(int iPosition, __inout CMediaType *pMediaType) PURE;
-
-
-
- // =================================================================
- // ----- Optional Override Methods -----------------------
- // =================================================================
-
- // you can also override these if you want to know about streaming
- virtual HRESULT StartStreaming();
- virtual HRESULT StopStreaming();
-
- // override if you can do anything constructive with quality notifications
- virtual HRESULT AlterQuality(Quality q);
-
- // override this to know when the media type is actually set
- virtual HRESULT SetMediaType(PIN_DIRECTION direction,const CMediaType *pmt);
-
- // chance to grab extra interfaces on connection
- virtual HRESULT CheckConnect(PIN_DIRECTION dir,IPin *pPin);
- virtual HRESULT BreakConnect(PIN_DIRECTION dir);
- virtual HRESULT CompleteConnect(PIN_DIRECTION direction,IPin *pReceivePin);
-
- // chance to customize the transform process
- virtual HRESULT Receive(IMediaSample *pSample);
-
- // Standard setup for output sample
- HRESULT InitializeOutputSample(IMediaSample *pSample, __deref_out IMediaSample **ppOutSample);
-
- // if you override Receive, you may need to override these three too
- virtual HRESULT EndOfStream(void);
- virtual HRESULT BeginFlush(void);
- virtual HRESULT EndFlush(void);
- virtual HRESULT NewSegment(
- REFERENCE_TIME tStart,
- REFERENCE_TIME tStop,
- double dRate);
-
-#ifdef PERF
- // Override to register performance measurement with a less generic string
- // You should do this to avoid confusion with other filters
- virtual void RegisterPerfId()
- {m_idTransform = MSR_REGISTER(TEXT("Transform"));}
-#endif // PERF
-
-
-// implementation details
-
-protected:
-
-#ifdef PERF
- int m_idTransform; // performance measuring id
-#endif
- BOOL m_bEOSDelivered; // have we sent EndOfStream
- BOOL m_bSampleSkipped; // Did we just skip a frame
- BOOL m_bQualityChanged; // Have we degraded?
-
- // critical section protecting filter state.
-
- CCritSec m_csFilter;
-
- // critical section stopping state changes (ie Stop) while we're
- // processing a sample.
- //
- // This critical section is held when processing
- // events that occur on the receive thread - Receive() and EndOfStream().
- //
- // If you want to hold both m_csReceive and m_csFilter then grab
- // m_csFilter FIRST - like CTransformFilter::Stop() does.
-
- CCritSec m_csReceive;
-
- // these hold our input and output pins
-
- friend class CTransformInputPin;
- friend class CTransformOutputPin;
- CTransformInputPin *m_pInput;
- CTransformOutputPin *m_pOutput;
-};
-
-#endif /* __TRANSFRM__ */
-
-
diff --git a/dll/src/baseclasses/transip.cpp b/dll/src/baseclasses/transip.cpp
deleted file mode 100644
index e8e12eb..0000000
--- a/dll/src/baseclasses/transip.cpp
+++ /dev/null
@@ -1,974 +0,0 @@
-//------------------------------------------------------------------------------
-// File: TransIP.cpp
-//
-// Desc: DirectShow base classes - implements class for simple Transform-
-// In-Place filters such as audio.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-// How allocators are decided.
-//
-// An in-place transform tries to do its work in someone else's buffers.
-// It tries to persuade the filters on either side to use the same allocator
-// (and for that matter the same media type). In desperation, if the downstream
-// filter refuses to supply an allocator and the upstream filter offers only
-// a read-only one then it will provide an allocator.
-// if the upstream filter insists on a read-only allocator then the transform
-// filter will (reluctantly) copy the data before transforming it.
-//
-// In order to pass an allocator through it needs to remember the one it got
-// from the first connection to pass it on to the second one.
-//
-// It is good if we can avoid insisting on a particular order of connection
-// (There is a precedent for insisting on the input
-// being connected first. Insisting on the output being connected first is
-// not allowed. That would break RenderFile.)
-//
-// The base pin classes (CBaseOutputPin and CBaseInputPin) both have a
-// m_pAllocator member which is used in places like
-// CBaseOutputPin::GetDeliveryBuffer and CBaseInputPin::Inactive.
-// To avoid lots of extra overriding, we should keep these happy
-// by using these pointers.
-//
-// When each pin is connected, it will set the corresponding m_pAllocator
-// and will have a single ref-count on that allocator.
-//
-// Refcounts are acquired by GetAllocator calls which return AddReffed
-// allocators and are released in one of:
-// CBaseInputPin::Disconnect
-// CBaseOutputPin::BreakConect
-// In each case m_pAllocator is set to NULL after the release, so this
-// is the last chance to ever release it. If there should ever be
-// multiple refcounts associated with the same pointer, this had better
-// be cleared up before that happens. To avoid such problems, we'll
-// stick with one per pointer.
-
-
-
-// RECONNECTING and STATE CHANGES
-//
-// Each pin could be disconnected, connected with a read-only allocator,
-// connected with an upstream read/write allocator, connected with an
-// allocator from downstream or connected with its own allocator.
-// Five states for each pin gives a data space of 25 states.
-//
-// Notation:
-//
-// R/W == read/write
-// R-O == read-only
-//
-// <input pin state> <output pin state> <comments>
-//
-// 00 means an unconnected pin.
-// <- means using a R/W allocator from the upstream filter
-// <= means using a R-O allocator from an upstream filter
-// || means using our own (R/W) allocator.
-// -> means using a R/W allocator from a downstream filter
-// (a R-O allocator from downstream is nonsense, it can't ever work).
-//
-//
-// That makes 25 possible states. Some states are nonsense (two different
-// allocators from the same place). These are just an artifact of the notation.
-// <= <- Nonsense.
-// <- <= Nonsense
-// Some states are illegal (the output pin never accepts a R-O allocator):
-// 00 <= !! Error !!
-// <= <= !! Error !!
-// || <= !! Error !!
-// -> <= !! Error !!
-// Three states appears to be inaccessible:
-// -> || Inaccessible
-// || -> Inaccessible
-// || <- Inaccessible
-// Some states only ever occur as intermediates with a pending reconnect which
-// is guaranteed to finish in another state.
-// -> 00 ?? unstable goes to || 00
-// 00 <- ?? unstable goes to 00 ||
-// -> <- ?? unstable goes to -> ->
-// <- || ?? unstable goes to <- <-
-// <- -> ?? unstable goes to <- <-
-// And that leaves 11 possible resting states:
-// 1 00 00 Nothing connected.
-// 2 <- 00 Input pin connected.
-// 3 <= 00 Input pin connected using R-O allocator.
-// 4 || 00 Needs several state changes to get here.
-// 5 00 || Output pin connected using our allocator
-// 6 00 -> Downstream only connected
-// 7 || || Undesirable but can be forced upon us.
-// 8 <= || Copy forced. <= -> is preferable
-// 9 <= -> OK - forced to copy.
-// 10 <- <- Transform in place (ideal)
-// 11 -> -> Transform in place (ideal)
-//
-// The object of the exercise is to ensure that we finish up in states
-// 10 or 11 whenever possible. State 10 is only possible if the upstream
-// filter has a R/W allocator (the AVI splitter notoriously
-// doesn't) and state 11 is only possible if the downstream filter does
-// offer an allocator.
-//
-// The transition table (entries marked * go via a reconnect)
-//
-// There are 8 possible transitions:
-// A: Connect upstream to filter with R-O allocator that insists on using it.
-// B: Connect upstream to filter with R-O allocator but chooses not to use it.
-// C: Connect upstream to filter with R/W allocator and insists on using it.
-// D: Connect upstream to filter with R/W allocator but chooses not to use it.
-// E: Connect downstream to a filter that offers an allocator
-// F: Connect downstream to a filter that does not offer an allocator
-// G: disconnect upstream
-// H: Disconnect downstream
-//
-// A B C D E F G H
-// ---------------------------------------------------------
-// 00 00 1 | 3 3 2 2 6 5 . . |1 00 00
-// <- 00 2 | . . . . *10/11 10 1 . |2 <- 00
-// <= 00 3 | . . . . *9/11 *7/8 1 . |3 <= 00
-// || 00 4 | . . . . *8 *7 1 . |4 || 00
-// 00 || 5 | 8 7 *10 7 . . . 1 |5 00 ||
-// 00 -> 6 | 9 11 *10 11 . . . 1 |6 00 ->
-// || || 7 | . . . . . . 5 4 |7 || ||
-// <= || 8 | . . . . . . 5 3 |8 <= ||
-// <= -> 9 | . . . . . . 6 3 |9 <= ->
-// <- <- 10| . . . . . . *5/6 2 |10 <- <-
-// -> -> 11| . . . . . . 6 *2/3 |11 -> ->
-// ---------------------------------------------------------
-// A B C D E F G H
-//
-// All these states are accessible without requiring any filter to
-// change its behaviour but not all transitions are accessible, for
-// instance a transition from state 4 to anywhere other than
-// state 8 requires that the upstream filter first offer a R-O allocator
-// and then changes its mind and offer R/W. This is NOT allowable - it
-// leads to things like the output pin getting a R/W allocator from
-// upstream and then the input pin being told it can only have a R-O one.
-// Note that you CAN change (say) the upstream filter for a different one, but
-// only as a disconnect / connect, not as a Reconnect. (Exercise for
-// the reader is to see how you get into state 4).
-//
-// The reconnection stuff goes as follows (some of the cases shown here as
-// "no reconnect" may get one to finalise media type - an old story).
-// If there is a reconnect where it says "no reconnect" here then the
-// reconnection must not change the allocator choice.
-//
-// state 2: <- 00 transition E <- <- case C <- <- (no change)
-// case D -> <- and then to -> ->
-//
-// state 2: <- 00 transition F <- <- (no reconnect)
-//
-// state 3: <= 00 transition E <= -> case A <= -> (no change)
-// case B -> ->
-// transition F <= || case A <= || (no change)
-// case B || ||
-//
-// state 4: || 00 transition E || || case B -> || and then all cases to -> ->
-// F || || case B || || (no change)
-//
-// state 5: 00 || transition A <= || (no reconnect)
-// B || || (no reconnect)
-// C <- || all cases <- <-
-// D || || (unfortunate, but upstream's choice)
-//
-// state 6: 00 -> transition A <= -> (no reconnect)
-// B -> -> (no reconnect)
-// C <- -> all cases <- <-
-// D -> -> (no reconnect)
-//
-// state 10:<- <- transition G 00 <- case E 00 ->
-// case F 00 ||
-//
-// state 11:-> -> transition H -> 00 case A <= 00 (schizo)
-// case B <= 00
-// case C <- 00 (schizo)
-// case D <- 00
-//
-// The Rules:
-// To sort out media types:
-// The input is reconnected
-// if the input pin is connected and the output pin connects
-// The output is reconnected
-// If the output pin is connected
-// and the input pin connects to a different media type
-//
-// To sort out allocators:
-// The input is reconnected
-// if the output disconnects and the input was using a downstream allocator
-// The output pin calls SetAllocator to pass on a new allocator
-// if the output is connected and
-// if the input disconnects and the output was using an upstream allocator
-// if the input acquires an allocator different from the output one
-// and that new allocator is not R-O
-//
-// Data is copied (i.e. call getbuffer and copy the data before transforming it)
-// if the two allocators are different.
-
-
-
-// CHAINS of filters:
-//
-// We sit between two filters (call them A and Z). We should finish up
-// with the same allocator on both of our pins and that should be the
-// same one that A and Z would have agreed on if we hadn't been in the
-// way. Furthermore, it should not matter how many in-place transforms
-// are in the way. Let B, C, D... be in-place transforms ("us").
-// Here's how it goes:
-//
-// 1.
-// A connects to B. They agree on A's allocator.
-// A-a->B
-//
-// 2.
-// B connects to C. Same story. There is no point in a reconnect, but
-// B will request an input reconnect anyway.
-// A-a->B-a->C
-//
-// 3.
-// C connects to Z.
-// C insists on using A's allocator, but compromises by requesting a reconnect.
-// of C's input.
-// A-a->B-?->C-a->Z
-//
-// We now have pending reconnects on both A--->B and B--->C
-//
-// 4.
-// The A--->B link is reconnected.
-// A asks B for an allocator. B sees that it has a downstream connection so
-// asks its downstream input pin i.e. C's input pin for an allocator. C sees
-// that it too has a downstream connection so asks Z for an allocator.
-//
-// Even though Z's input pin is connected, it is being asked for an allocator.
-// It could refuse, in which case the chain is done and will use A's allocator
-// Alternatively, Z may supply one. A chooses either Z's or A's own one.
-// B's input pin gets NotifyAllocator called to tell it the decision and it
-// propagates this downstream by calling ReceiveAllocator on its output pin
-// which calls NotifyAllocator on the next input pin downstream etc.
-// If the choice is Z then it goes:
-// A-z->B-a->C-a->Z
-// A-z->B-z->C-a->Z
-// A-z->B-z->C-z->Z
-//
-// And that's IT!! Any further (essentially spurious) reconnects peter out
-// with no change in the chain.
-
-#include <streams.h>
-#include <measure.h>
-#include <transip.h>
-
-
-// =================================================================
-// Implements the CTransInPlaceFilter class
-// =================================================================
-
-CTransInPlaceFilter::CTransInPlaceFilter
- ( __in_opt LPCTSTR pName,
- __inout_opt LPUNKNOWN pUnk,
- REFCLSID clsid,
- __inout HRESULT *phr,
- bool bModifiesData
- )
- : CTransformFilter(pName, pUnk, clsid),
- m_bModifiesData(bModifiesData)
-{
-#ifdef PERF
- RegisterPerfId();
-#endif // PERF
-
-} // constructor
-
-#ifdef UNICODE
-CTransInPlaceFilter::CTransInPlaceFilter
- ( __in_opt LPCSTR pName,
- __inout_opt LPUNKNOWN pUnk,
- REFCLSID clsid,
- __inout HRESULT *phr,
- bool bModifiesData
- )
- : CTransformFilter(pName, pUnk, clsid),
- m_bModifiesData(bModifiesData)
-{
-#ifdef PERF
- RegisterPerfId();
-#endif // PERF
-
-} // constructor
-#endif
-
-// return a non-addrefed CBasePin * for the user to addref if he holds onto it
-// for longer than his pointer to us. We create the pins dynamically when they
-// are asked for rather than in the constructor. This is because we want to
-// give the derived class an oppportunity to return different pin objects
-
-// As soon as any pin is needed we create both (this is different from the
-// usual transform filter) because enumerators, allocators etc are passed
-// through from one pin to another and it becomes very painful if the other
-// pin isn't there. If we fail to create either pin we ensure we fail both.
-
-CBasePin *
-CTransInPlaceFilter::GetPin(int n)
-{
- HRESULT hr = S_OK;
-
- // Create an input pin if not already done
-
- if (m_pInput == NULL) {
-
- m_pInput = new CTransInPlaceInputPin( NAME("TransInPlace input pin")
- , this // Owner filter
- , &hr // Result code
- , L"Input" // Pin name
- );
-
- // Constructor for CTransInPlaceInputPin can't fail
- ASSERT(SUCCEEDED(hr));
- }
-
- // Create an output pin if not already done
-
- if (m_pInput!=NULL && m_pOutput == NULL) {
-
- m_pOutput = new CTransInPlaceOutputPin( NAME("TransInPlace output pin")
- , this // Owner filter
- , &hr // Result code
- , L"Output" // Pin name
- );
-
- // a failed return code should delete the object
-
- ASSERT(SUCCEEDED(hr));
- if (m_pOutput == NULL) {
- delete m_pInput;
- m_pInput = NULL;
- }
- }
-
- // Return the appropriate pin
-
- ASSERT (n>=0 && n<=1);
- if (n == 0) {
- return m_pInput;
- } else if (n==1) {
- return m_pOutput;
- } else {
- return NULL;
- }
-
-} // GetPin
-
-
-
-// dir is the direction of our pin.
-// pReceivePin is the pin we are connecting to.
-HRESULT CTransInPlaceFilter::CompleteConnect(PIN_DIRECTION dir, IPin *pReceivePin)
-{
- UNREFERENCED_PARAMETER(pReceivePin);
- ASSERT(m_pInput);
- ASSERT(m_pOutput);
-
- // if we are not part of a graph, then don't indirect the pointer
- // this probably prevents use of the filter without a filtergraph
- if (!m_pGraph) {
- return VFW_E_NOT_IN_GRAPH;
- }
-
- // Always reconnect the input to account for buffering changes
- //
- // Because we don't get to suggest a type on ReceiveConnection
- // we need another way of making sure the right type gets used.
- //
- // One way would be to have our EnumMediaTypes return our output
- // connection type first but more deterministic and simple is to
- // call ReconnectEx passing the type we want to reconnect with
- // via the base class ReconeectPin method.
-
- if (dir == PINDIR_OUTPUT) {
- if( m_pInput->IsConnected() ) {
- return ReconnectPin( m_pInput, &m_pOutput->CurrentMediaType() );
- }
- return NOERROR;
- }
-
- ASSERT(dir == PINDIR_INPUT);
-
- // Reconnect output if necessary
-
- if( m_pOutput->IsConnected() ) {
-
- if ( m_pInput->CurrentMediaType()
- != m_pOutput->CurrentMediaType()
- ) {
- return ReconnectPin( m_pOutput, &m_pInput->CurrentMediaType() );
- }
- }
- return NOERROR;
-
-} // ComnpleteConnect
-
-
-//
-// DecideBufferSize
-//
-// Tell the output pin's allocator what size buffers we require.
-// *pAlloc will be the allocator our output pin is using.
-//
-
-HRESULT CTransInPlaceFilter::DecideBufferSize
- ( IMemAllocator *pAlloc
- , __inout ALLOCATOR_PROPERTIES *pProperties
- )
-{
- ALLOCATOR_PROPERTIES Request, Actual;
- HRESULT hr;
-
- // If we are connected upstream, get his views
- if (m_pInput->IsConnected()) {
- // Get the input pin allocator, and get its size and count.
- // we don't care about his alignment and prefix.
-
- hr = InputPin()->PeekAllocator()->GetProperties(&Request);
- if (FAILED(hr)) {
- // Input connected but with a secretive allocator - enough!
- return hr;
- }
- } else {
- // Propose one byte
- // If this isn't enough then when the other pin does get connected
- // we can revise it.
- ZeroMemory(&Request, sizeof(Request));
- Request.cBuffers = 1;
- Request.cbBuffer = 1;
- }
-
-
- DbgLog((LOG_MEMORY,1,TEXT("Setting Allocator Requirements")));
- DbgLog((LOG_MEMORY,1,TEXT("Count %d, Size %d"),
- Request.cBuffers, Request.cbBuffer));
-
- // Pass the allocator requirements to our output side
- // but do a little sanity checking first or we'll just hit
- // asserts in the allocator.
-
- pProperties->cBuffers = Request.cBuffers;
- pProperties->cbBuffer = Request.cbBuffer;
- pProperties->cbAlign = Request.cbAlign;
- if (pProperties->cBuffers<=0) {pProperties->cBuffers = 1; }
- if (pProperties->cbBuffer<=0) {pProperties->cbBuffer = 1; }
- hr = pAlloc->SetProperties(pProperties, &Actual);
-
- if (FAILED(hr)) {
- return hr;
- }
-
- DbgLog((LOG_MEMORY,1,TEXT("Obtained Allocator Requirements")));
- DbgLog((LOG_MEMORY,1,TEXT("Count %d, Size %d, Alignment %d"),
- Actual.cBuffers, Actual.cbBuffer, Actual.cbAlign));
-
- // Make sure we got the right alignment and at least the minimum required
-
- if ( (Request.cBuffers > Actual.cBuffers)
- || (Request.cbBuffer > Actual.cbBuffer)
- || (Request.cbAlign > Actual.cbAlign)
- ) {
- return E_FAIL;
- }
- return NOERROR;
-
-} // DecideBufferSize
-
-//
-// Copy
-//
-// return a pointer to an identical copy of pSample
-__out_opt IMediaSample * CTransInPlaceFilter::Copy(IMediaSample *pSource)
-{
- IMediaSample * pDest;
-
- HRESULT hr;
- REFERENCE_TIME tStart, tStop;
- const BOOL bTime = S_OK == pSource->GetTime( &tStart, &tStop);
-
- // this may block for an indeterminate amount of time
- hr = OutputPin()->PeekAllocator()->GetBuffer(
- &pDest
- , bTime ? &tStart : NULL
- , bTime ? &tStop : NULL
- , m_bSampleSkipped ? AM_GBF_PREVFRAMESKIPPED : 0
- );
-
- if (FAILED(hr)) {
- return NULL;
- }
-
- ASSERT(pDest);
- IMediaSample2 *pSample2;
- if (SUCCEEDED(pDest->QueryInterface(IID_IMediaSample2, (void **)&pSample2))) {
- HRESULT hrProps = pSample2->SetProperties(
- FIELD_OFFSET(AM_SAMPLE2_PROPERTIES, pbBuffer),
- (PBYTE)m_pInput->SampleProps());
- pSample2->Release();
- if (FAILED(hrProps)) {
- pDest->Release();
- return NULL;
- }
- } else {
- if (bTime) {
- pDest->SetTime(&tStart, &tStop);
- }
-
- if (S_OK == pSource->IsSyncPoint()) {
- pDest->SetSyncPoint(TRUE);
- }
- if (S_OK == pSource->IsDiscontinuity() || m_bSampleSkipped) {
- pDest->SetDiscontinuity(TRUE);
- }
- if (S_OK == pSource->IsPreroll()) {
- pDest->SetPreroll(TRUE);
- }
-
- // Copy the media type
- AM_MEDIA_TYPE *pMediaType;
- if (S_OK == pSource->GetMediaType(&pMediaType)) {
- pDest->SetMediaType(pMediaType);
- DeleteMediaType( pMediaType );
- }
-
- }
-
- m_bSampleSkipped = FALSE;
-
- // Copy the sample media times
- REFERENCE_TIME TimeStart, TimeEnd;
- if (pSource->GetMediaTime(&TimeStart,&TimeEnd) == NOERROR) {
- pDest->SetMediaTime(&TimeStart,&TimeEnd);
- }
-
- // Copy the actual data length and the actual data.
- {
- const long lDataLength = pSource->GetActualDataLength();
- if (FAILED(pDest->SetActualDataLength(lDataLength))) {
- pDest->Release();
- return NULL;
- }
-
- // Copy the sample data
- {
- BYTE *pSourceBuffer, *pDestBuffer;
- long lSourceSize = pSource->GetSize();
- long lDestSize = pDest->GetSize();
-
- ASSERT(lDestSize >= lSourceSize && lDestSize >= lDataLength);
-
- if (FAILED(pSource->GetPointer(&pSourceBuffer)) ||
- FAILED(pDest->GetPointer(&pDestBuffer)) ||
- lDestSize < lDataLength ||
- lDataLength < 0) {
- pDest->Release();
- return NULL;
- }
- ASSERT(lDestSize == 0 || pSourceBuffer != NULL && pDestBuffer != NULL);
-
- CopyMemory( (PVOID) pDestBuffer, (PVOID) pSourceBuffer, lDataLength );
- }
- }
-
- return pDest;
-
-} // Copy
-
-
-// override this to customize the transform process
-
-HRESULT
-CTransInPlaceFilter::Receive(IMediaSample *pSample)
-{
- /* Check for other streams and pass them on */
- AM_SAMPLE2_PROPERTIES * const pProps = m_pInput->SampleProps();
- if (pProps->dwStreamId != AM_STREAM_MEDIA) {
- return m_pOutput->Deliver(pSample);
- }
- HRESULT hr;
-
- // Start timing the TransInPlace (if PERF is defined)
- MSR_START(m_idTransInPlace);
-
- if (UsingDifferentAllocators()) {
-
- // We have to copy the data.
-
- pSample = Copy(pSample);
-
- if (pSample==NULL) {
- MSR_STOP(m_idTransInPlace);
- return E_UNEXPECTED;
- }
- }
-
- // have the derived class transform the data
- hr = Transform(pSample);
-
- // Stop the clock and log it (if PERF is defined)
- MSR_STOP(m_idTransInPlace);
-
- if (FAILED(hr)) {
- DbgLog((LOG_TRACE, 1, TEXT("Error from TransInPlace")));
- if (UsingDifferentAllocators()) {
- pSample->Release();
- }
- return hr;
- }
-
- // the Transform() function can return S_FALSE to indicate that the
- // sample should not be delivered; we only deliver the sample if it's
- // really S_OK (same as NOERROR, of course.)
- if (hr == NOERROR) {
- hr = m_pOutput->Deliver(pSample);
- } else {
- // But it would be an error to return this private workaround
- // to the caller ...
- if (S_FALSE == hr) {
- // S_FALSE returned from Transform is a PRIVATE agreement
- // We should return NOERROR from Receive() in this cause because
- // returning S_FALSE from Receive() means that this is the end
- // of the stream and no more data should be sent.
- m_bSampleSkipped = TRUE;
- if (!m_bQualityChanged) {
- NotifyEvent(EC_QUALITY_CHANGE,0,0);
- m_bQualityChanged = TRUE;
- }
- hr = NOERROR;
- }
- }
-
- // release the output buffer. If the connected pin still needs it,
- // it will have addrefed it itself.
- if (UsingDifferentAllocators()) {
- pSample->Release();
- }
-
- return hr;
-
-} // Receive
-
-
-
-// =================================================================
-// Implements the CTransInPlaceInputPin class
-// =================================================================
-
-
-// constructor
-
-CTransInPlaceInputPin::CTransInPlaceInputPin
- ( __in_opt LPCTSTR pObjectName
- , __inout CTransInPlaceFilter *pFilter
- , __inout HRESULT *phr
- , __in_opt LPCWSTR pName
- )
- : CTransformInputPin(pObjectName,
- pFilter,
- phr,
- pName)
- , m_bReadOnly(FALSE)
- , m_pTIPFilter(pFilter)
-{
- DbgLog((LOG_TRACE, 2
- , TEXT("CTransInPlaceInputPin::CTransInPlaceInputPin")));
-
-} // constructor
-
-
-// =================================================================
-// Implements IMemInputPin interface
-// =================================================================
-
-
-// If the downstream filter has one then offer that (even if our own output
-// pin is not using it yet. If the upstream filter chooses it then we will
-// tell our output pin to ReceiveAllocator).
-// Else if our output pin is using an allocator then offer that.
-// ( This could mean offering the upstream filter his own allocator,
-// it could mean offerring our own
-// ) or it could mean offering the one from downstream
-// Else fail to offer any allocator at all.
-
-STDMETHODIMP CTransInPlaceInputPin::GetAllocator(__deref_out IMemAllocator ** ppAllocator)
-{
- CheckPointer(ppAllocator,E_POINTER);
- ValidateReadWritePtr(ppAllocator,sizeof(IMemAllocator *));
- CAutoLock cObjectLock(m_pLock);
-
- HRESULT hr;
-
- if ( m_pTIPFilter->m_pOutput->IsConnected() ) {
- // Store the allocator we got
- hr = m_pTIPFilter->OutputPin()->ConnectedIMemInputPin()
- ->GetAllocator( ppAllocator );
- if (SUCCEEDED(hr)) {
- m_pTIPFilter->OutputPin()->SetAllocator( *ppAllocator );
- }
- }
- else {
- // Help upstream filter (eg TIP filter which is having to do a copy)
- // by providing a temp allocator here - we'll never use
- // this allocator because when our output is connected we'll
- // reconnect this pin
- hr = CTransformInputPin::GetAllocator( ppAllocator );
- }
- return hr;
-
-} // GetAllocator
-
-
-
-/* Get told which allocator the upstream output pin is actually going to use */
-
-
-STDMETHODIMP
-CTransInPlaceInputPin::NotifyAllocator(
- IMemAllocator * pAllocator,
- BOOL bReadOnly)
-{
- HRESULT hr = S_OK;
- CheckPointer(pAllocator,E_POINTER);
- ValidateReadPtr(pAllocator,sizeof(IMemAllocator));
-
- CAutoLock cObjectLock(m_pLock);
-
- m_bReadOnly = bReadOnly;
- // If we modify data then don't accept the allocator if it's
- // the same as the output pin's allocator
-
- // If our output is not connected just accept the allocator
- // We're never going to use this allocator because when our
- // output pin is connected we'll reconnect this pin
- if (!m_pTIPFilter->OutputPin()->IsConnected()) {
- return CTransformInputPin::NotifyAllocator(pAllocator, bReadOnly);
- }
-
- // If the allocator is read-only and we're modifying data
- // and the allocator is the same as the output pin's
- // then reject
- if (bReadOnly && m_pTIPFilter->m_bModifiesData) {
- IMemAllocator *pOutputAllocator =
- m_pTIPFilter->OutputPin()->PeekAllocator();
-
- // Make sure we have an output allocator
- if (pOutputAllocator == NULL) {
- hr = m_pTIPFilter->OutputPin()->ConnectedIMemInputPin()->
- GetAllocator(&pOutputAllocator);
- if(FAILED(hr)) {
- hr = CreateMemoryAllocator(&pOutputAllocator);
- }
- if (SUCCEEDED(hr)) {
- m_pTIPFilter->OutputPin()->SetAllocator(pOutputAllocator);
- pOutputAllocator->Release();
- }
- }
- if (pAllocator == pOutputAllocator) {
- hr = E_FAIL;
- } else if(SUCCEEDED(hr)) {
- // Must copy so set the allocator properties on the output
- ALLOCATOR_PROPERTIES Props, Actual;
- hr = pAllocator->GetProperties(&Props);
- if (SUCCEEDED(hr)) {
- hr = pOutputAllocator->SetProperties(&Props, &Actual);
- }
- if (SUCCEEDED(hr)) {
- if ( (Props.cBuffers > Actual.cBuffers)
- || (Props.cbBuffer > Actual.cbBuffer)
- || (Props.cbAlign > Actual.cbAlign)
- ) {
- hr = E_FAIL;
- }
- }
-
- // Set the allocator on the output pin
- if (SUCCEEDED(hr)) {
- hr = m_pTIPFilter->OutputPin()->ConnectedIMemInputPin()
- ->NotifyAllocator( pOutputAllocator, FALSE );
- }
- }
- } else {
- hr = m_pTIPFilter->OutputPin()->ConnectedIMemInputPin()
- ->NotifyAllocator( pAllocator, bReadOnly );
- if (SUCCEEDED(hr)) {
- m_pTIPFilter->OutputPin()->SetAllocator( pAllocator );
- }
- }
-
- if (SUCCEEDED(hr)) {
-
- // It's possible that the old and the new are the same thing.
- // AddRef before release ensures that we don't unload it.
- pAllocator->AddRef();
-
- if( m_pAllocator != NULL )
- m_pAllocator->Release();
-
- m_pAllocator = pAllocator; // We have an allocator for the input pin
- }
-
- return hr;
-
-} // NotifyAllocator
-
-
-// EnumMediaTypes
-// - pass through to our downstream filter
-STDMETHODIMP CTransInPlaceInputPin::EnumMediaTypes( __deref_out IEnumMediaTypes **ppEnum )
-{
- // Can only pass through if connected
- if( !m_pTIPFilter->m_pOutput->IsConnected() )
- return VFW_E_NOT_CONNECTED;
-
- return m_pTIPFilter->m_pOutput->GetConnected()->EnumMediaTypes( ppEnum );
-
-} // EnumMediaTypes
-
-
-// CheckMediaType
-// - agree to anything if not connected,
-// otherwise pass through to the downstream filter.
-// This assumes that the filter does not change the media type.
-
-HRESULT CTransInPlaceInputPin::CheckMediaType(const CMediaType *pmt )
-{
- HRESULT hr = m_pTIPFilter->CheckInputType(pmt);
- if (hr!=S_OK) return hr;
-
- if( m_pTIPFilter->m_pOutput->IsConnected() )
- return m_pTIPFilter->m_pOutput->GetConnected()->QueryAccept( pmt );
- else
- return S_OK;
-
-} // CheckMediaType
-
-
-// If upstream asks us what our requirements are, we will try to ask downstream
-// if that doesn't work, we'll just take the defaults.
-STDMETHODIMP
-CTransInPlaceInputPin::GetAllocatorRequirements(__out ALLOCATOR_PROPERTIES *pProps)
-{
-
- if( m_pTIPFilter->m_pOutput->IsConnected() )
- return m_pTIPFilter->OutputPin()
- ->ConnectedIMemInputPin()->GetAllocatorRequirements( pProps );
- else
- return E_NOTIMPL;
-
-} // GetAllocatorRequirements
-
-
-// CTransInPlaceInputPin::CompleteConnect() calls CBaseInputPin::CompleteConnect()
-// and then calls CTransInPlaceFilter::CompleteConnect(). It does this because
-// CTransInPlaceFilter::CompleteConnect() can reconnect a pin and we do not
-// want to reconnect a pin if CBaseInputPin::CompleteConnect() fails.
-HRESULT
-CTransInPlaceInputPin::CompleteConnect(IPin *pReceivePin)
-{
- HRESULT hr = CBaseInputPin::CompleteConnect(pReceivePin);
- if (FAILED(hr)) {
- return hr;
- }
-
- return m_pTransformFilter->CompleteConnect(PINDIR_INPUT,pReceivePin);
-} // CompleteConnect
-
-
-// =================================================================
-// Implements the CTransInPlaceOutputPin class
-// =================================================================
-
-
-// constructor
-
-CTransInPlaceOutputPin::CTransInPlaceOutputPin(
- __in_opt LPCTSTR pObjectName,
- __inout CTransInPlaceFilter *pFilter,
- __inout HRESULT * phr,
- __in_opt LPCWSTR pPinName)
- : CTransformOutputPin( pObjectName
- , pFilter
- , phr
- , pPinName),
- m_pTIPFilter(pFilter)
-{
- DbgLog(( LOG_TRACE, 2
- , TEXT("CTransInPlaceOutputPin::CTransInPlaceOutputPin")));
-
-} // constructor
-
-
-// EnumMediaTypes
-// - pass through to our upstream filter
-STDMETHODIMP CTransInPlaceOutputPin::EnumMediaTypes( __deref_out IEnumMediaTypes **ppEnum )
-{
- // Can only pass through if connected.
- if( ! m_pTIPFilter->m_pInput->IsConnected() )
- return VFW_E_NOT_CONNECTED;
-
- return m_pTIPFilter->m_pInput->GetConnected()->EnumMediaTypes( ppEnum );
-
-} // EnumMediaTypes
-
-
-
-// CheckMediaType
-// - agree to anything if not connected,
-// otherwise pass through to the upstream filter.
-
-HRESULT CTransInPlaceOutputPin::CheckMediaType(const CMediaType *pmt )
-{
- // Don't accept any output pin type changes if we're copying
- // between allocators - it's too late to change the input
- // allocator size.
- if (m_pTIPFilter->UsingDifferentAllocators() && !m_pFilter->IsStopped()) {
- if (*pmt == m_mt) {
- return S_OK;
- } else {
- return VFW_E_TYPE_NOT_ACCEPTED;
- }
- }
-
- // Assumes the type does not change. That's why we're calling
- // CheckINPUTType here on the OUTPUT pin.
- HRESULT hr = m_pTIPFilter->CheckInputType(pmt);
- if (hr!=S_OK) return hr;
-
- if( m_pTIPFilter->m_pInput->IsConnected() )
- return m_pTIPFilter->m_pInput->GetConnected()->QueryAccept( pmt );
- else
- return S_OK;
-
-} // CheckMediaType
-
-
-/* Save the allocator pointer in the output pin
-*/
-void
-CTransInPlaceOutputPin::SetAllocator(IMemAllocator * pAllocator)
-{
- pAllocator->AddRef();
- if (m_pAllocator) {
- m_pAllocator->Release();
- }
- m_pAllocator = pAllocator;
-} // SetAllocator
-
-
-// CTransInPlaceOutputPin::CompleteConnect() calls CBaseOutputPin::CompleteConnect()
-// and then calls CTransInPlaceFilter::CompleteConnect(). It does this because
-// CTransInPlaceFilter::CompleteConnect() can reconnect a pin and we do not want to
-// reconnect a pin if CBaseOutputPin::CompleteConnect() fails.
-// CBaseOutputPin::CompleteConnect() often fails when our output pin is being connected
-// to the Video Mixing Renderer.
-HRESULT
-CTransInPlaceOutputPin::CompleteConnect(IPin *pReceivePin)
-{
- HRESULT hr = CBaseOutputPin::CompleteConnect(pReceivePin);
- if (FAILED(hr)) {
- return hr;
- }
-
- return m_pTransformFilter->CompleteConnect(PINDIR_OUTPUT,pReceivePin);
-} // CompleteConnect
diff --git a/dll/src/baseclasses/transip.h b/dll/src/baseclasses/transip.h
deleted file mode 100644
index 3fc335e..0000000
--- a/dll/src/baseclasses/transip.h
+++ /dev/null
@@ -1,250 +0,0 @@
-//------------------------------------------------------------------------------
-// File: TransIP.h
-//
-// Desc: DirectShow base classes - defines classes from which simple
-// Transform-In-Place filters may be derived.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-//
-// The difference between this and Transfrm.h is that Transfrm copies the data.
-//
-// It assumes the filter has one input and one output stream, and has no
-// interest in memory management, interface negotiation or anything else.
-//
-// Derive your class from this, and supply Transform and the media type/format
-// negotiation functions. Implement that class, compile and link and
-// you're done.
-
-
-#ifndef __TRANSIP__
-#define __TRANSIP__
-
-// ======================================================================
-// This is the com object that represents a simple transform filter. It
-// supports IBaseFilter, IMediaFilter and two pins through nested interfaces
-// ======================================================================
-
-class CTransInPlaceFilter;
-
-// Several of the pin functions call filter functions to do the work,
-// so you can often use the pin classes unaltered, just overriding the
-// functions in CTransInPlaceFilter. If that's not enough and you want
-// to derive your own pin class, override GetPin in the filter to supply
-// your own pin classes to the filter.
-
-// ==================================================
-// Implements the input pin
-// ==================================================
-
-class CTransInPlaceInputPin : public CTransformInputPin
-{
-
-protected:
- CTransInPlaceFilter * const m_pTIPFilter; // our filter
- BOOL m_bReadOnly; // incoming stream is read only
-
-public:
-
- CTransInPlaceInputPin(
- __in_opt LPCTSTR pObjectName,
- __inout CTransInPlaceFilter *pFilter,
- __inout HRESULT *phr,
- __in_opt LPCWSTR pName);
-
- // --- IMemInputPin -----
-
- // Provide an enumerator for media types by getting one from downstream
- STDMETHODIMP EnumMediaTypes( __deref_out IEnumMediaTypes **ppEnum );
-
- // Say whether media type is acceptable.
- HRESULT CheckMediaType(const CMediaType* pmt);
-
- // Return our upstream allocator
- STDMETHODIMP GetAllocator(__deref_out IMemAllocator ** ppAllocator);
-
- // get told which allocator the upstream output pin is actually
- // going to use.
- STDMETHODIMP NotifyAllocator(IMemAllocator * pAllocator,
- BOOL bReadOnly);
-
- // Allow the filter to see what allocator we have
- // N.B. This does NOT AddRef
- __out IMemAllocator * PeekAllocator() const
- { return m_pAllocator; }
-
- // Pass this on downstream if it ever gets called.
- STDMETHODIMP GetAllocatorRequirements(__out ALLOCATOR_PROPERTIES *pProps);
-
- HRESULT CompleteConnect(IPin *pReceivePin);
-
- inline const BOOL ReadOnly() { return m_bReadOnly ; }
-
-}; // CTransInPlaceInputPin
-
-// ==================================================
-// Implements the output pin
-// ==================================================
-
-class CTransInPlaceOutputPin : public CTransformOutputPin
-{
-
-protected:
- // m_pFilter points to our CBaseFilter
- CTransInPlaceFilter * const m_pTIPFilter;
-
-public:
-
- CTransInPlaceOutputPin(
- __in_opt LPCTSTR pObjectName,
- __inout CTransInPlaceFilter *pFilter,
- __inout HRESULT *phr,
- __in_opt LPCWSTR pName);
-
-
- // --- CBaseOutputPin ------------
-
- // negotiate the allocator and its buffer size/count
- // Insists on using our own allocator. (Actually the one upstream of us).
- // We don't override this - instead we just agree the default
- // then let the upstream filter decide for itself on reconnect
- // virtual HRESULT DecideAllocator(IMemInputPin * pPin, IMemAllocator ** pAlloc);
-
- // Provide a media type enumerator. Get it from upstream.
- STDMETHODIMP EnumMediaTypes( __deref_out IEnumMediaTypes **ppEnum );
-
- // Say whether media type is acceptable.
- HRESULT CheckMediaType(const CMediaType* pmt);
-
- // This just saves the allocator being used on the output pin
- // Also called by input pin's GetAllocator()
- void SetAllocator(IMemAllocator * pAllocator);
-
- __out_opt IMemInputPin * ConnectedIMemInputPin()
- { return m_pInputPin; }
-
- // Allow the filter to see what allocator we have
- // N.B. This does NOT AddRef
- __out IMemAllocator * PeekAllocator() const
- { return m_pAllocator; }
-
- HRESULT CompleteConnect(IPin *pReceivePin);
-
-}; // CTransInPlaceOutputPin
-
-
-class AM_NOVTABLE CTransInPlaceFilter : public CTransformFilter
-{
-
-public:
-
- // map getpin/getpincount for base enum of pins to owner
- // override this to return more specialised pin objects
-
- virtual CBasePin *GetPin(int n);
-
-public:
-
- // Set bModifiesData == false if your derived filter does
- // not modify the data samples (for instance it's just copying
- // them somewhere else or looking at the timestamps).
-
- CTransInPlaceFilter(__in_opt LPCTSTR, __inout_opt LPUNKNOWN, REFCLSID clsid, __inout HRESULT *,
- bool bModifiesData = true);
-#ifdef UNICODE
- CTransInPlaceFilter(__in_opt LPCSTR, __inout_opt LPUNKNOWN, REFCLSID clsid, __inout HRESULT *,
- bool bModifiesData = true);
-#endif
- // The following are defined to avoid undefined pure virtuals.
- // Even if they are never called, they will give linkage warnings/errors
-
- // We override EnumMediaTypes to bypass the transform class enumerator
- // which would otherwise call this.
- HRESULT GetMediaType(int iPosition, __inout CMediaType *pMediaType)
- { DbgBreak("CTransInPlaceFilter::GetMediaType should never be called");
- return E_UNEXPECTED;
- }
-
- // This is called when we actually have to provide our own allocator.
- HRESULT DecideBufferSize(IMemAllocator*, __inout ALLOCATOR_PROPERTIES *);
-
- // The functions which call this in CTransform are overridden in this
- // class to call CheckInputType with the assumption that the type
- // does not change. In Debug builds some calls will be made and
- // we just ensure that they do not assert.
- HRESULT CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut)
- {
- return S_OK;
- };
-
-
- // =================================================================
- // ----- You may want to override this -----------------------------
- // =================================================================
-
- HRESULT CompleteConnect(PIN_DIRECTION dir,IPin *pReceivePin);
-
- // chance to customize the transform process
- virtual HRESULT Receive(IMediaSample *pSample);
-
- // =================================================================
- // ----- You MUST override these -----------------------------------
- // =================================================================
-
- virtual HRESULT Transform(IMediaSample *pSample) PURE;
-
- // this goes in the factory template table to create new instances
- // static CCOMObject * CreateInstance(LPUNKNOWN, HRESULT *);
-
-
-#ifdef PERF
- // Override to register performance measurement with a less generic string
- // You should do this to avoid confusion with other filters
- virtual void RegisterPerfId()
- {m_idTransInPlace = MSR_REGISTER(TEXT("TransInPlace"));}
-#endif // PERF
-
-
-// implementation details
-
-protected:
-
- __out_opt IMediaSample * CTransInPlaceFilter::Copy(IMediaSample *pSource);
-
-#ifdef PERF
- int m_idTransInPlace; // performance measuring id
-#endif // PERF
- bool m_bModifiesData; // Does this filter change the data?
-
- // these hold our input and output pins
-
- friend class CTransInPlaceInputPin;
- friend class CTransInPlaceOutputPin;
-
- __out CTransInPlaceInputPin *InputPin() const
- {
- return (CTransInPlaceInputPin *)m_pInput;
- };
- __out CTransInPlaceOutputPin *OutputPin() const
- {
- return (CTransInPlaceOutputPin *)m_pOutput;
- };
-
- // Helper to see if the input and output types match
- BOOL TypesMatch()
- {
- return InputPin()->CurrentMediaType() ==
- OutputPin()->CurrentMediaType();
- }
-
- // Are the input and output allocators different?
- BOOL UsingDifferentAllocators() const
- {
- return InputPin()->PeekAllocator() != OutputPin()->PeekAllocator();
- }
-}; // CTransInPlaceFilter
-
-#endif /* __TRANSIP__ */
-
diff --git a/dll/src/baseclasses/videoctl.cpp b/dll/src/baseclasses/videoctl.cpp
deleted file mode 100644
index 2edace9..0000000
--- a/dll/src/baseclasses/videoctl.cpp
+++ /dev/null
@@ -1,734 +0,0 @@
-//------------------------------------------------------------------------------
-// File: VideoCtl.cpp
-//
-// Desc: DirectShow base classes.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-#include <streams.h>
-#include "ddmm.h"
-
-// Load a string from the resource file string table. The buffer must be at
-// least STR_MAX_LENGTH bytes. The easiest way to use this is to declare a
-// buffer in the property page class and use it for all string loading. It
-// cannot be static as multiple property pages may be active simultaneously
-
-LPTSTR WINAPI StringFromResource(__out_ecount(STR_MAX_LENGTH) LPTSTR pBuffer, int iResourceID)
-{
- if (LoadString(g_hInst,iResourceID,pBuffer,STR_MAX_LENGTH) == 0) {
- return TEXT("");
- }
- return pBuffer;
-}
-
-#ifdef UNICODE
-LPSTR WINAPI StringFromResource(__out_ecount(STR_MAX_LENGTH) LPSTR pBuffer, int iResourceID)
-{
- if (LoadStringA(g_hInst,iResourceID,pBuffer,STR_MAX_LENGTH) == 0) {
- return "";
- }
- return pBuffer;
-}
-#endif
-
-
-
-// Property pages typically are called through their OLE interfaces. These
-// use UNICODE strings regardless of how the binary is built. So when we
-// load strings from the resource file we sometimes want to convert them
-// to UNICODE. This method is passed the target UNICODE buffer and does a
-// convert after loading the string (if built UNICODE this is not needed)
-// On WinNT we can explicitly call LoadStringW which saves two conversions
-
-#ifndef UNICODE
-
-LPWSTR WINAPI WideStringFromResource(__out_ecount(STR_MAX_LENGTH) LPWSTR pBuffer, int iResourceID)
-{
- *pBuffer = 0;
- LoadStringW(g_hInst,iResourceID,pBuffer,STR_MAX_LENGTH);
- return pBuffer;
-}
-
-#endif
-
-
-// Helper function to calculate the size of the dialog
-
-BOOL WINAPI GetDialogSize(int iResourceID,
- DLGPROC pDlgProc,
- LPARAM lParam,
- __out SIZE *pResult)
-{
- RECT rc;
- HWND hwnd;
-
- // Create a temporary property page
-
- hwnd = CreateDialogParam(g_hInst,
- MAKEINTRESOURCE(iResourceID),
- GetDesktopWindow(),
- pDlgProc,
- lParam);
- if (hwnd == NULL) {
- return FALSE;
- }
-
- GetWindowRect(hwnd, &rc);
- pResult->cx = rc.right - rc.left;
- pResult->cy = rc.bottom - rc.top;
-
- DestroyWindow(hwnd);
- return TRUE;
-}
-
-
-// Class that aggregates on the IDirectDraw interface. Although DirectDraw
-// has the ability in its interfaces to be aggregated they're not currently
-// implemented. This makes it difficult for various parts of Quartz that want
-// to aggregate these interfaces. In particular the video renderer passes out
-// media samples that expose IDirectDraw and IDirectDrawSurface. The filter
-// graph manager also exposes IDirectDraw as a plug in distributor. For these
-// objects we provide these aggregation classes that republish the interfaces
-
-STDMETHODIMP CAggDirectDraw::NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv)
-{
- ASSERT(m_pDirectDraw);
-
- // Do we have this interface
-
- if (riid == IID_IDirectDraw) {
- return GetInterface((IDirectDraw *)this,ppv);
- } else {
- return CUnknown::NonDelegatingQueryInterface(riid,ppv);
- }
-}
-
-
-STDMETHODIMP CAggDirectDraw::Compact()
-{
- ASSERT(m_pDirectDraw);
- return m_pDirectDraw->Compact();
-}
-
-
-STDMETHODIMP CAggDirectDraw::CreateClipper(DWORD dwFlags, __deref_out LPDIRECTDRAWCLIPPER *lplpDDClipper, __inout_opt IUnknown *pUnkOuter)
-{
- ASSERT(m_pDirectDraw);
- return m_pDirectDraw->CreateClipper(dwFlags,lplpDDClipper,pUnkOuter);
-}
-
-
-STDMETHODIMP CAggDirectDraw::CreatePalette(DWORD dwFlags,
- __in LPPALETTEENTRY lpColorTable,
- __deref_out LPDIRECTDRAWPALETTE *lplpDDPalette,
- __inout_opt IUnknown *pUnkOuter)
-{
- ASSERT(m_pDirectDraw);
- return m_pDirectDraw->CreatePalette(dwFlags,lpColorTable,lplpDDPalette,pUnkOuter);
-}
-
-
-STDMETHODIMP CAggDirectDraw::CreateSurface(__in LPDDSURFACEDESC lpDDSurfaceDesc,
- __deref_out LPDIRECTDRAWSURFACE *lplpDDSurface,
- __inout_opt IUnknown *pUnkOuter)
-{
- ASSERT(m_pDirectDraw);
- return m_pDirectDraw->CreateSurface(lpDDSurfaceDesc,lplpDDSurface,pUnkOuter);
-}
-
-
-STDMETHODIMP CAggDirectDraw::DuplicateSurface(__in LPDIRECTDRAWSURFACE lpDDSurface,
- __deref_out LPDIRECTDRAWSURFACE *lplpDupDDSurface)
-{
- ASSERT(m_pDirectDraw);
- return m_pDirectDraw->DuplicateSurface(lpDDSurface,lplpDupDDSurface);
-}
-
-
-STDMETHODIMP CAggDirectDraw::EnumDisplayModes(DWORD dwSurfaceDescCount,
- __in LPDDSURFACEDESC lplpDDSurfaceDescList,
- __in LPVOID lpContext,
- __in LPDDENUMMODESCALLBACK lpEnumCallback)
-{
- ASSERT(m_pDirectDraw);
- return m_pDirectDraw->EnumDisplayModes(dwSurfaceDescCount,lplpDDSurfaceDescList,lpContext,lpEnumCallback);
-}
-
-
-STDMETHODIMP CAggDirectDraw::EnumSurfaces(DWORD dwFlags,
- __in LPDDSURFACEDESC lpDDSD,
- __in LPVOID lpContext,
- __in LPDDENUMSURFACESCALLBACK lpEnumCallback)
-{
- ASSERT(m_pDirectDraw);
- return m_pDirectDraw->EnumSurfaces(dwFlags,lpDDSD,lpContext,lpEnumCallback);
-}
-
-
-STDMETHODIMP CAggDirectDraw::FlipToGDISurface()
-{
- ASSERT(m_pDirectDraw);
- return m_pDirectDraw->FlipToGDISurface();
-}
-
-
-STDMETHODIMP CAggDirectDraw::GetCaps(__out LPDDCAPS lpDDDriverCaps,__out LPDDCAPS lpDDHELCaps)
-{
- ASSERT(m_pDirectDraw);
- return m_pDirectDraw->GetCaps(lpDDDriverCaps,lpDDHELCaps);
-}
-
-
-STDMETHODIMP CAggDirectDraw::GetDisplayMode(__out LPDDSURFACEDESC lpDDSurfaceDesc)
-{
- ASSERT(m_pDirectDraw);
- return m_pDirectDraw->GetDisplayMode(lpDDSurfaceDesc);
-}
-
-
-STDMETHODIMP CAggDirectDraw::GetFourCCCodes(__inout LPDWORD lpNumCodes,__out_ecount(*lpNumCodes) LPDWORD lpCodes)
-{
- ASSERT(m_pDirectDraw);
- return m_pDirectDraw->GetFourCCCodes(lpNumCodes,lpCodes);
-}
-
-
-STDMETHODIMP CAggDirectDraw::GetGDISurface(__deref_out LPDIRECTDRAWSURFACE *lplpGDIDDSurface)
-{
- ASSERT(m_pDirectDraw);
- return m_pDirectDraw->GetGDISurface(lplpGDIDDSurface);
-}
-
-
-STDMETHODIMP CAggDirectDraw::GetMonitorFrequency(__out LPDWORD lpdwFrequency)
-{
- ASSERT(m_pDirectDraw);
- return m_pDirectDraw->GetMonitorFrequency(lpdwFrequency);
-}
-
-
-STDMETHODIMP CAggDirectDraw::GetScanLine(__out LPDWORD lpdwScanLine)
-{
- ASSERT(m_pDirectDraw);
- return m_pDirectDraw->GetScanLine(lpdwScanLine);
-}
-
-
-STDMETHODIMP CAggDirectDraw::GetVerticalBlankStatus(__out LPBOOL lpblsInVB)
-{
- ASSERT(m_pDirectDraw);
- return m_pDirectDraw->GetVerticalBlankStatus(lpblsInVB);
-}
-
-
-STDMETHODIMP CAggDirectDraw::Initialize(__in GUID *lpGUID)
-{
- ASSERT(m_pDirectDraw);
- return m_pDirectDraw->Initialize(lpGUID);
-}
-
-
-STDMETHODIMP CAggDirectDraw::RestoreDisplayMode()
-{
- ASSERT(m_pDirectDraw);
- return m_pDirectDraw->RestoreDisplayMode();
-}
-
-
-STDMETHODIMP CAggDirectDraw::SetCooperativeLevel(HWND hWnd,DWORD dwFlags)
-{
- ASSERT(m_pDirectDraw);
- return m_pDirectDraw->SetCooperativeLevel(hWnd,dwFlags);
-}
-
-
-STDMETHODIMP CAggDirectDraw::SetDisplayMode(DWORD dwWidth,DWORD dwHeight,DWORD dwBpp)
-{
- ASSERT(m_pDirectDraw);
- return m_pDirectDraw->SetDisplayMode(dwWidth,dwHeight,dwBpp);
-}
-
-
-STDMETHODIMP CAggDirectDraw::WaitForVerticalBlank(DWORD dwFlags,HANDLE hEvent)
-{
- ASSERT(m_pDirectDraw);
- return m_pDirectDraw->WaitForVerticalBlank(dwFlags,hEvent);
-}
-
-
-// Class that aggregates an IDirectDrawSurface interface. Although DirectDraw
-// has the ability in its interfaces to be aggregated they're not currently
-// implemented. This makes it difficult for various parts of Quartz that want
-// to aggregate these interfaces. In particular the video renderer passes out
-// media samples that expose IDirectDraw and IDirectDrawSurface. The filter
-// graph manager also exposes IDirectDraw as a plug in distributor. For these
-// objects we provide these aggregation classes that republish the interfaces
-
-STDMETHODIMP CAggDrawSurface::NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv)
-{
- ASSERT(m_pDirectDrawSurface);
-
- // Do we have this interface
-
- if (riid == IID_IDirectDrawSurface) {
- return GetInterface((IDirectDrawSurface *)this,ppv);
- } else {
- return CUnknown::NonDelegatingQueryInterface(riid,ppv);
- }
-}
-
-
-STDMETHODIMP CAggDrawSurface::AddAttachedSurface(__in LPDIRECTDRAWSURFACE lpDDSAttachedSurface)
-{
- ASSERT(m_pDirectDrawSurface);
- return m_pDirectDrawSurface->AddAttachedSurface(lpDDSAttachedSurface);
-}
-
-
-STDMETHODIMP CAggDrawSurface::AddOverlayDirtyRect(__in LPRECT lpRect)
-{
- ASSERT(m_pDirectDrawSurface);
- return m_pDirectDrawSurface->AddOverlayDirtyRect(lpRect);
-}
-
-
-STDMETHODIMP CAggDrawSurface::Blt(__in LPRECT lpDestRect,
- __in LPDIRECTDRAWSURFACE lpDDSrcSurface,
- __in LPRECT lpSrcRect,
- DWORD dwFlags,
- __in LPDDBLTFX lpDDBltFx)
-{
- ASSERT(m_pDirectDrawSurface);
- return m_pDirectDrawSurface->Blt(lpDestRect,lpDDSrcSurface,lpSrcRect,dwFlags,lpDDBltFx);
-}
-
-
-STDMETHODIMP CAggDrawSurface::BltBatch(__in_ecount(dwCount) LPDDBLTBATCH lpDDBltBatch,DWORD dwCount,DWORD dwFlags)
-{
- ASSERT(m_pDirectDrawSurface);
- return m_pDirectDrawSurface->BltBatch(lpDDBltBatch,dwCount,dwFlags);
-}
-
-
-STDMETHODIMP CAggDrawSurface::BltFast(DWORD dwX,DWORD dwY,
- __in LPDIRECTDRAWSURFACE lpDDSrcSurface,
- __in LPRECT lpSrcRect,
- DWORD dwTrans)
-{
- ASSERT(m_pDirectDrawSurface);
- return m_pDirectDrawSurface->BltFast(dwX,dwY,lpDDSrcSurface,lpSrcRect,dwTrans);
-}
-
-
-STDMETHODIMP CAggDrawSurface::DeleteAttachedSurface(DWORD dwFlags,
- __in LPDIRECTDRAWSURFACE lpDDSAttachedSurface)
-{
- ASSERT(m_pDirectDrawSurface);
- return m_pDirectDrawSurface->DeleteAttachedSurface(dwFlags,lpDDSAttachedSurface);
-}
-
-
-STDMETHODIMP CAggDrawSurface::EnumAttachedSurfaces(__in LPVOID lpContext,
- __in LPDDENUMSURFACESCALLBACK lpEnumSurfacesCallback)
-{
- ASSERT(m_pDirectDrawSurface);
- return m_pDirectDrawSurface->EnumAttachedSurfaces(lpContext,lpEnumSurfacesCallback);
-}
-
-
-STDMETHODIMP CAggDrawSurface::EnumOverlayZOrders(DWORD dwFlags,
- __in LPVOID lpContext,
- __in LPDDENUMSURFACESCALLBACK lpfnCallback)
-{
- ASSERT(m_pDirectDrawSurface);
- return m_pDirectDrawSurface->EnumOverlayZOrders(dwFlags,lpContext,lpfnCallback);
-}
-
-
-STDMETHODIMP CAggDrawSurface::Flip(__in LPDIRECTDRAWSURFACE lpDDSurfaceTargetOverride,DWORD dwFlags)
-{
- ASSERT(m_pDirectDrawSurface);
- return m_pDirectDrawSurface->Flip(lpDDSurfaceTargetOverride,dwFlags);
-}
-
-
-STDMETHODIMP CAggDrawSurface::GetAttachedSurface(__in LPDDSCAPS lpDDSCaps,
- __deref_out LPDIRECTDRAWSURFACE *lplpDDAttachedSurface)
-{
- ASSERT(m_pDirectDrawSurface);
- return m_pDirectDrawSurface->GetAttachedSurface(lpDDSCaps,lplpDDAttachedSurface);
-}
-
-
-STDMETHODIMP CAggDrawSurface::GetBltStatus(DWORD dwFlags)
-{
- ASSERT(m_pDirectDrawSurface);
- return m_pDirectDrawSurface->GetBltStatus(dwFlags);
-}
-
-
-STDMETHODIMP CAggDrawSurface::GetCaps(__out LPDDSCAPS lpDDSCaps)
-{
- ASSERT(m_pDirectDrawSurface);
- return m_pDirectDrawSurface->GetCaps(lpDDSCaps);
-}
-
-
-STDMETHODIMP CAggDrawSurface::GetClipper(__deref_out LPDIRECTDRAWCLIPPER *lplpDDClipper)
-{
- ASSERT(m_pDirectDrawSurface);
- return m_pDirectDrawSurface->GetClipper(lplpDDClipper);
-}
-
-
-STDMETHODIMP CAggDrawSurface::GetColorKey(DWORD dwFlags,__out LPDDCOLORKEY lpDDColorKey)
-{
- ASSERT(m_pDirectDrawSurface);
- return m_pDirectDrawSurface->GetColorKey(dwFlags,lpDDColorKey);
-}
-
-
-STDMETHODIMP CAggDrawSurface::GetDC(__out HDC *lphDC)
-{
- ASSERT(m_pDirectDrawSurface);
- return m_pDirectDrawSurface->GetDC(lphDC);
-}
-
-
-STDMETHODIMP CAggDrawSurface::GetFlipStatus(DWORD dwFlags)
-{
- ASSERT(m_pDirectDrawSurface);
- return m_pDirectDrawSurface->GetFlipStatus(dwFlags);
-}
-
-
-STDMETHODIMP CAggDrawSurface::GetOverlayPosition(__out LPLONG lpdwX,__out LPLONG lpdwY)
-{
- ASSERT(m_pDirectDrawSurface);
- return m_pDirectDrawSurface->GetOverlayPosition(lpdwX,lpdwY);
-}
-
-
-STDMETHODIMP CAggDrawSurface::GetPalette(__deref_out LPDIRECTDRAWPALETTE *lplpDDPalette)
-{
- ASSERT(m_pDirectDrawSurface);
- return m_pDirectDrawSurface->GetPalette(lplpDDPalette);
-}
-
-
-STDMETHODIMP CAggDrawSurface::GetPixelFormat(__out LPDDPIXELFORMAT lpDDPixelFormat)
-{
- ASSERT(m_pDirectDrawSurface);
- return m_pDirectDrawSurface->GetPixelFormat(lpDDPixelFormat);
-}
-
-
-// A bit of a warning here: Our media samples in DirectShow aggregate on
-// IDirectDraw and IDirectDrawSurface (ie are available through IMediaSample
-// by QueryInterface). Unfortunately the underlying DirectDraw code cannot
-// be aggregated so we have to use these classes. The snag is that when we
-// call a different surface and pass in this interface as perhaps the source
-// surface the call will fail because DirectDraw dereferences the pointer to
-// get at its private data structures. Therefore we supply this workaround to give
-// access to the real IDirectDraw surface. A filter can call GetSurfaceDesc
-// and we will fill in the lpSurface pointer with the real underlying surface
-
-STDMETHODIMP CAggDrawSurface::GetSurfaceDesc(__out LPDDSURFACEDESC lpDDSurfaceDesc)
-{
- ASSERT(m_pDirectDrawSurface);
-
- // First call down to the underlying DirectDraw
-
- HRESULT hr = m_pDirectDrawSurface->GetSurfaceDesc(lpDDSurfaceDesc);
- if (FAILED(hr)) {
- return hr;
- }
-
- // Store the real DirectDrawSurface interface
- lpDDSurfaceDesc->lpSurface = m_pDirectDrawSurface;
- return hr;
-}
-
-
-STDMETHODIMP CAggDrawSurface::Initialize(__in LPDIRECTDRAW lpDD,__in LPDDSURFACEDESC lpDDSurfaceDesc)
-{
- ASSERT(m_pDirectDrawSurface);
- return m_pDirectDrawSurface->Initialize(lpDD,lpDDSurfaceDesc);
-}
-
-
-STDMETHODIMP CAggDrawSurface::IsLost()
-{
- ASSERT(m_pDirectDrawSurface);
- return m_pDirectDrawSurface->IsLost();
-}
-
-
-STDMETHODIMP CAggDrawSurface::Lock(__in LPRECT lpDestRect,
- __inout LPDDSURFACEDESC lpDDSurfaceDesc,
- DWORD dwFlags,
- HANDLE hEvent)
-{
- ASSERT(m_pDirectDrawSurface);
- return m_pDirectDrawSurface->Lock(lpDestRect,lpDDSurfaceDesc,dwFlags,hEvent);
-}
-
-
-STDMETHODIMP CAggDrawSurface::ReleaseDC(HDC hDC)
-{
- ASSERT(m_pDirectDrawSurface);
- return m_pDirectDrawSurface->ReleaseDC(hDC);
-}
-
-
-STDMETHODIMP CAggDrawSurface::Restore()
-{
- ASSERT(m_pDirectDrawSurface);
- return m_pDirectDrawSurface->Restore();
-}
-
-
-STDMETHODIMP CAggDrawSurface::SetClipper(__in LPDIRECTDRAWCLIPPER lpDDClipper)
-{
- ASSERT(m_pDirectDrawSurface);
- return m_pDirectDrawSurface->SetClipper(lpDDClipper);
-}
-
-
-STDMETHODIMP CAggDrawSurface::SetColorKey(DWORD dwFlags,__in LPDDCOLORKEY lpDDColorKey)
-{
- ASSERT(m_pDirectDrawSurface);
- return m_pDirectDrawSurface->SetColorKey(dwFlags,lpDDColorKey);
-}
-
-
-STDMETHODIMP CAggDrawSurface::SetOverlayPosition(LONG dwX,LONG dwY)
-{
- ASSERT(m_pDirectDrawSurface);
- return m_pDirectDrawSurface->SetOverlayPosition(dwX,dwY);
-}
-
-
-STDMETHODIMP CAggDrawSurface::SetPalette(__in LPDIRECTDRAWPALETTE lpDDPalette)
-{
- ASSERT(m_pDirectDrawSurface);
- return m_pDirectDrawSurface->SetPalette(lpDDPalette);
-}
-
-
-STDMETHODIMP CAggDrawSurface::Unlock(__in LPVOID lpSurfaceData)
-{
- ASSERT(m_pDirectDrawSurface);
- return m_pDirectDrawSurface->Unlock(lpSurfaceData);
-}
-
-
-STDMETHODIMP CAggDrawSurface::UpdateOverlay(__in LPRECT lpSrcRect,
- __in LPDIRECTDRAWSURFACE lpDDDestSurface,
- __in LPRECT lpDestRect,
- DWORD dwFlags,
- __in LPDDOVERLAYFX lpDDOverlayFX)
-{
- ASSERT(m_pDirectDrawSurface);
- return m_pDirectDrawSurface->UpdateOverlay(lpSrcRect,lpDDDestSurface,lpDestRect,dwFlags,lpDDOverlayFX);
-}
-
-
-STDMETHODIMP CAggDrawSurface::UpdateOverlayDisplay(DWORD dwFlags)
-{
- ASSERT(m_pDirectDrawSurface);
- return m_pDirectDrawSurface->UpdateOverlayDisplay(dwFlags);
-}
-
-
-STDMETHODIMP CAggDrawSurface::UpdateOverlayZOrder(DWORD dwFlags,__in LPDIRECTDRAWSURFACE lpDDSReference)
-{
- ASSERT(m_pDirectDrawSurface);
- return m_pDirectDrawSurface->UpdateOverlayZOrder(dwFlags,lpDDSReference);
-}
-
-
-// DirectShow must work on multiple platforms. In particular, it also runs on
-// Windows NT 3.51 which does not have DirectDraw capabilities. The filters
-// cannot therefore link statically to the DirectDraw library. To make their
-// lives that little bit easier we provide this class that manages loading
-// and unloading the library and creating the initial IDirectDraw interface
-
-CLoadDirectDraw::CLoadDirectDraw() :
- m_pDirectDraw(NULL),
- m_hDirectDraw(NULL)
-{
-}
-
-
-// Destructor forces unload
-
-CLoadDirectDraw::~CLoadDirectDraw()
-{
- ReleaseDirectDraw();
-
- if (m_hDirectDraw) {
- NOTE("Unloading library");
- FreeLibrary(m_hDirectDraw);
- }
-}
-
-
-// We can't be sure that DirectDraw is always available so we can't statically
-// link to the library. Therefore we load the library, get the function entry
-// point addresses and call them to create the driver objects. We return S_OK
-// if we manage to load DirectDraw correctly otherwise we return E_NOINTERFACE
-// We initialise a DirectDraw instance by explicitely loading the library and
-// calling GetProcAddress on the DirectDrawCreate entry point that it exports
-
-// On a multi monitor system, we can get the DirectDraw object for any
-// monitor (device) with the optional szDevice parameter
-
-HRESULT CLoadDirectDraw::LoadDirectDraw(__in LPSTR szDevice)
-{
- PDRAWCREATE pDrawCreate;
- PDRAWENUM pDrawEnum;
- LPDIRECTDRAWENUMERATEEXA pDrawEnumEx;
- HRESULT hr = NOERROR;
-
- NOTE("Entering DoLoadDirectDraw");
-
- // Is DirectDraw already loaded
-
- if (m_pDirectDraw) {
- NOTE("Already loaded");
- ASSERT(m_hDirectDraw);
- return NOERROR;
- }
-
- // Make sure the library is available
-
- if(!m_hDirectDraw)
- {
- UINT ErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX);
- m_hDirectDraw = LoadLibrary(TEXT("DDRAW.DLL"));
- SetErrorMode(ErrorMode);
-
- if (m_hDirectDraw == NULL) {
- DbgLog((LOG_ERROR,1,TEXT("Can't load DDRAW.DLL")));
- NOTE("No library");
- return E_NOINTERFACE;
- }
- }
-
- // Get the DLL address for the creator function
-
- pDrawCreate = (PDRAWCREATE)GetProcAddress(m_hDirectDraw,"DirectDrawCreate");
- // force ANSI, we assume it
- pDrawEnum = (PDRAWENUM)GetProcAddress(m_hDirectDraw,"DirectDrawEnumerateA");
- pDrawEnumEx = (LPDIRECTDRAWENUMERATEEXA)GetProcAddress(m_hDirectDraw,
- "DirectDrawEnumerateExA");
-
- // We don't NEED DirectDrawEnumerateEx, that's just for multimon stuff
- if (pDrawCreate == NULL || pDrawEnum == NULL) {
- DbgLog((LOG_ERROR,1,TEXT("Can't get functions: Create=%x Enum=%x"),
- pDrawCreate, pDrawEnum));
- NOTE("No entry point");
- ReleaseDirectDraw();
- return E_NOINTERFACE;
- }
-
- DbgLog((LOG_TRACE,3,TEXT("Creating DDraw for device %s"),
- szDevice ? szDevice : "<NULL>"));
-
- // Create a DirectDraw display provider for this device, using the fancy
- // multimon-aware version, if it exists
- if (pDrawEnumEx)
- m_pDirectDraw = DirectDrawCreateFromDeviceEx(szDevice, pDrawCreate,
- pDrawEnumEx);
- else
- m_pDirectDraw = DirectDrawCreateFromDevice(szDevice, pDrawCreate,
- pDrawEnum);
-
- if (m_pDirectDraw == NULL) {
- DbgLog((LOG_ERROR,1,TEXT("Can't create DDraw")));
- NOTE("No instance");
- ReleaseDirectDraw();
- return E_NOINTERFACE;
- }
- return NOERROR;
-}
-
-
-// Called to release any DirectDraw provider we previously loaded. We may be
-// called at any time especially when something goes horribly wrong and when
-// we need to clean up before returning so we can't guarantee that all state
-// variables are consistent so free only those really allocated allocated
-// This should only be called once all reference counts have been released
-
-void CLoadDirectDraw::ReleaseDirectDraw()
-{
- NOTE("Releasing DirectDraw driver");
-
- // Release any DirectDraw provider interface
-
- if (m_pDirectDraw) {
- NOTE("Releasing instance");
- m_pDirectDraw->Release();
- m_pDirectDraw = NULL;
- }
-
-}
-
-
-// Return NOERROR (S_OK) if DirectDraw has been loaded by this object
-
-HRESULT CLoadDirectDraw::IsDirectDrawLoaded()
-{
- NOTE("Entering IsDirectDrawLoaded");
-
- if (m_pDirectDraw == NULL) {
- NOTE("DirectDraw not loaded");
- return S_FALSE;
- }
- return NOERROR;
-}
-
-
-// Return the IDirectDraw interface we look after
-
-LPDIRECTDRAW CLoadDirectDraw::GetDirectDraw()
-{
- NOTE("Entering GetDirectDraw");
-
- if (m_pDirectDraw == NULL) {
- NOTE("No DirectDraw");
- return NULL;
- }
-
- NOTE("Returning DirectDraw");
- m_pDirectDraw->AddRef();
- return m_pDirectDraw;
-}
-
-
-// Are we running on Direct Draw version 1? We need to find out as
-// we rely on specific bug fixes in DirectDraw 2 for fullscreen playback. To
-// find out, we simply see if it supports IDirectDraw2. Only version 2 and
-// higher support this.
-
-BOOL CLoadDirectDraw::IsDirectDrawVersion1()
-{
-
- if (m_pDirectDraw == NULL)
- return FALSE;
-
- IDirectDraw2 *p = NULL;
- HRESULT hr = m_pDirectDraw->QueryInterface(IID_IDirectDraw2, (void **)&p);
- if (p)
- p->Release();
- if (hr == NOERROR) {
- DbgLog((LOG_TRACE,3,TEXT("Direct Draw Version 2 or greater")));
- return FALSE;
- } else {
- DbgLog((LOG_TRACE,3,TEXT("Direct Draw Version 1")));
- return TRUE;
- }
-}
diff --git a/dll/src/baseclasses/videoctl.h b/dll/src/baseclasses/videoctl.h
deleted file mode 100644
index 30c3778..0000000
--- a/dll/src/baseclasses/videoctl.h
+++ /dev/null
@@ -1,168 +0,0 @@
-//------------------------------------------------------------------------------
-// File: VideoCtl.h
-//
-// Desc: DirectShow base classes.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-#ifndef __VIDEOCTL__
-#define __VIDEOCTL__
-
-// These help with property page implementations. The first can be used to
-// load any string from a resource file. The buffer to load into is passed
-// as an input parameter. The same buffer is the return value if the string
-// was found otherwise it returns TEXT(""). The GetDialogSize is passed the
-// resource ID of a dialog box and returns the size of it in screen pixels
-
-#define STR_MAX_LENGTH 256
-LPTSTR WINAPI StringFromResource(__out_ecount(STR_MAX_LENGTH) LPTSTR pBuffer, int iResourceID);
-
-#ifdef UNICODE
-#define WideStringFromResource StringFromResource
-LPSTR WINAPI StringFromResource(__out_ecount(STR_MAX_LENGTH) LPSTR pBuffer, int iResourceID);
-#else
-LPWSTR WINAPI WideStringFromResource(__out_ecount(STR_MAX_LENGTH) LPWSTR pBuffer, int iResourceID);
-#endif
-
-
-BOOL WINAPI GetDialogSize(int iResourceID, // Dialog box resource identifier
- DLGPROC pDlgProc, // Pointer to dialog procedure
- LPARAM lParam, // Any user data wanted in pDlgProc
- __out SIZE *pResult);// Returns the size of dialog box
-
-// Class that aggregates an IDirectDraw interface
-
-class CAggDirectDraw : public IDirectDraw, public CUnknown
-{
-protected:
-
- LPDIRECTDRAW m_pDirectDraw;
-
-public:
-
- DECLARE_IUNKNOWN
- STDMETHODIMP NonDelegatingQueryInterface(REFIID riid,__deref_out void **ppv);
-
- // Constructor and destructor
-
- CAggDirectDraw(__in_opt LPCTSTR pName,__inout_opt LPUNKNOWN pUnk) :
- CUnknown(pName,pUnk),
- m_pDirectDraw(NULL) { };
-
- virtual CAggDirectDraw::~CAggDirectDraw() { };
-
- // Set the object we should be aggregating
- void SetDirectDraw(__inout LPDIRECTDRAW pDirectDraw) {
- m_pDirectDraw = pDirectDraw;
- }
-
- // IDirectDraw methods
-
- STDMETHODIMP Compact();
- STDMETHODIMP CreateClipper(DWORD dwFlags,__deref_out LPDIRECTDRAWCLIPPER *lplpDDClipper,__inout_opt IUnknown *pUnkOuter);
- STDMETHODIMP CreatePalette(DWORD dwFlags,__in LPPALETTEENTRY lpColorTable,__deref_out LPDIRECTDRAWPALETTE *lplpDDPalette,__inout_opt IUnknown *pUnkOuter);
- STDMETHODIMP CreateSurface(__in LPDDSURFACEDESC lpDDSurfaceDesc,__deref_out LPDIRECTDRAWSURFACE *lplpDDSurface,__inout_opt IUnknown *pUnkOuter);
- STDMETHODIMP DuplicateSurface(__in LPDIRECTDRAWSURFACE lpDDSurface,__deref_out LPDIRECTDRAWSURFACE *lplpDupDDSurface);
- STDMETHODIMP EnumDisplayModes(DWORD dwSurfaceDescCount,__in LPDDSURFACEDESC lplpDDSurfaceDescList,__in LPVOID lpContext,__in LPDDENUMMODESCALLBACK lpEnumCallback);
- STDMETHODIMP EnumSurfaces(DWORD dwFlags,__in LPDDSURFACEDESC lpDDSD,__in LPVOID lpContext,__in LPDDENUMSURFACESCALLBACK lpEnumCallback);
- STDMETHODIMP FlipToGDISurface();
- STDMETHODIMP GetCaps(__out LPDDCAPS lpDDDriverCaps,__out LPDDCAPS lpDDHELCaps);
- STDMETHODIMP GetDisplayMode(__out LPDDSURFACEDESC lpDDSurfaceDesc);
- STDMETHODIMP GetFourCCCodes(__inout LPDWORD lpNumCodes,__out_ecount(*lpNumCodes) LPDWORD lpCodes);
- STDMETHODIMP GetGDISurface(__deref_out LPDIRECTDRAWSURFACE *lplpGDIDDSurface);
- STDMETHODIMP GetMonitorFrequency(__out LPDWORD lpdwFrequency);
- STDMETHODIMP GetScanLine(__out LPDWORD lpdwScanLine);
- STDMETHODIMP GetVerticalBlankStatus(__out LPBOOL lpblsInVB);
- STDMETHODIMP Initialize(__in GUID *lpGUID);
- STDMETHODIMP RestoreDisplayMode();
- STDMETHODIMP SetCooperativeLevel(HWND hWnd,DWORD dwFlags);
- STDMETHODIMP SetDisplayMode(DWORD dwWidth,DWORD dwHeight,DWORD dwBpp);
- STDMETHODIMP WaitForVerticalBlank(DWORD dwFlags,HANDLE hEvent);
-};
-
-
-// Class that aggregates an IDirectDrawSurface interface
-
-class CAggDrawSurface : public IDirectDrawSurface, public CUnknown
-{
-protected:
-
- LPDIRECTDRAWSURFACE m_pDirectDrawSurface;
-
-public:
-
- DECLARE_IUNKNOWN
- STDMETHODIMP NonDelegatingQueryInterface(REFIID riid,__deref_out void **ppv);
-
- // Constructor and destructor
-
- CAggDrawSurface(__in_opt LPCTSTR pName,__inout_opt LPUNKNOWN pUnk) :
- CUnknown(pName,pUnk),
- m_pDirectDrawSurface(NULL) { };
-
- virtual ~CAggDrawSurface() { };
-
- // Set the object we should be aggregating
- void SetDirectDrawSurface(__inout LPDIRECTDRAWSURFACE pDirectDrawSurface) {
- m_pDirectDrawSurface = pDirectDrawSurface;
- }
-
- // IDirectDrawSurface methods
-
- STDMETHODIMP AddAttachedSurface(__in LPDIRECTDRAWSURFACE lpDDSAttachedSurface);
- STDMETHODIMP AddOverlayDirtyRect(__in LPRECT lpRect);
- STDMETHODIMP Blt(__in LPRECT lpDestRect,__in LPDIRECTDRAWSURFACE lpDDSrcSurface,__in LPRECT lpSrcRect,DWORD dwFlags,__in LPDDBLTFX lpDDBltFx);
- STDMETHODIMP BltBatch(__in_ecount(dwCount) LPDDBLTBATCH lpDDBltBatch,DWORD dwCount,DWORD dwFlags);
- STDMETHODIMP BltFast(DWORD dwX,DWORD dwY,__in LPDIRECTDRAWSURFACE lpDDSrcSurface,__in LPRECT lpSrcRect,DWORD dwTrans);
- STDMETHODIMP DeleteAttachedSurface(DWORD dwFlags,__in LPDIRECTDRAWSURFACE lpDDSAttachedSurface);
- STDMETHODIMP EnumAttachedSurfaces(__in LPVOID lpContext,__in LPDDENUMSURFACESCALLBACK lpEnumSurfacesCallback);
- STDMETHODIMP EnumOverlayZOrders(DWORD dwFlags,__in LPVOID lpContext,__in LPDDENUMSURFACESCALLBACK lpfnCallback);
- STDMETHODIMP Flip(__in LPDIRECTDRAWSURFACE lpDDSurfaceTargetOverride,DWORD dwFlags);
- STDMETHODIMP GetAttachedSurface(__in LPDDSCAPS lpDDSCaps,__deref_out LPDIRECTDRAWSURFACE *lplpDDAttachedSurface);
- STDMETHODIMP GetBltStatus(DWORD dwFlags);
- STDMETHODIMP GetCaps(__out LPDDSCAPS lpDDSCaps);
- STDMETHODIMP GetClipper(__deref_out LPDIRECTDRAWCLIPPER *lplpDDClipper);
- STDMETHODIMP GetColorKey(DWORD dwFlags,__out LPDDCOLORKEY lpDDColorKey);
- STDMETHODIMP GetDC(__out HDC *lphDC);
- STDMETHODIMP GetFlipStatus(DWORD dwFlags);
- STDMETHODIMP GetOverlayPosition(__out LPLONG lpdwX,__out LPLONG lpdwY);
- STDMETHODIMP GetPalette(__deref_out LPDIRECTDRAWPALETTE *lplpDDPalette);
- STDMETHODIMP GetPixelFormat(__out LPDDPIXELFORMAT lpDDPixelFormat);
- STDMETHODIMP GetSurfaceDesc(__out LPDDSURFACEDESC lpDDSurfaceDesc);
- STDMETHODIMP Initialize(__in LPDIRECTDRAW lpDD,__in LPDDSURFACEDESC lpDDSurfaceDesc);
- STDMETHODIMP IsLost();
- STDMETHODIMP Lock(__in LPRECT lpDestRect,__inout LPDDSURFACEDESC lpDDSurfaceDesc,DWORD dwFlags,HANDLE hEvent);
- STDMETHODIMP ReleaseDC(HDC hDC);
- STDMETHODIMP Restore();
- STDMETHODIMP SetClipper(__in LPDIRECTDRAWCLIPPER lpDDClipper);
- STDMETHODIMP SetColorKey(DWORD dwFlags,__in LPDDCOLORKEY lpDDColorKey);
- STDMETHODIMP SetOverlayPosition(LONG dwX,LONG dwY);
- STDMETHODIMP SetPalette(__in LPDIRECTDRAWPALETTE lpDDPalette);
- STDMETHODIMP Unlock(__in LPVOID lpSurfaceData);
- STDMETHODIMP UpdateOverlay(__in LPRECT lpSrcRect,__in LPDIRECTDRAWSURFACE lpDDDestSurface,__in LPRECT lpDestRect,DWORD dwFlags,__in LPDDOVERLAYFX lpDDOverlayFX);
- STDMETHODIMP UpdateOverlayDisplay(DWORD dwFlags);
- STDMETHODIMP UpdateOverlayZOrder(DWORD dwFlags,__in LPDIRECTDRAWSURFACE lpDDSReference);
-};
-
-
-class CLoadDirectDraw
-{
- LPDIRECTDRAW m_pDirectDraw; // The DirectDraw driver instance
- HINSTANCE m_hDirectDraw; // Handle to the loaded library
-
-public:
-
- CLoadDirectDraw();
- ~CLoadDirectDraw();
-
- HRESULT LoadDirectDraw(__in LPSTR szDevice);
- void ReleaseDirectDraw();
- HRESULT IsDirectDrawLoaded();
- LPDIRECTDRAW GetDirectDraw();
- BOOL IsDirectDrawVersion1();
-};
-
-#endif // __VIDEOCTL__
-
diff --git a/dll/src/baseclasses/vtrans.cpp b/dll/src/baseclasses/vtrans.cpp
deleted file mode 100644
index cb4fa99..0000000
--- a/dll/src/baseclasses/vtrans.cpp
+++ /dev/null
@@ -1,468 +0,0 @@
-//------------------------------------------------------------------------------
-// File: Vtrans.cpp
-//
-// Desc: DirectShow base classes.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-#include <streams.h>
-#include <measure.h>
-// #include <vtransfr.h> // now in precomp file streams.h
-
-CVideoTransformFilter::CVideoTransformFilter
- ( __in_opt LPCTSTR pName, __inout_opt LPUNKNOWN pUnk, REFCLSID clsid)
- : CTransformFilter(pName, pUnk, clsid)
- , m_itrLate(0)
- , m_nKeyFramePeriod(0) // No QM until we see at least 2 key frames
- , m_nFramesSinceKeyFrame(0)
- , m_bSkipping(FALSE)
- , m_tDecodeStart(0)
- , m_itrAvgDecode(300000) // 30mSec - probably allows skipping
- , m_bQualityChanged(FALSE)
-{
-#ifdef PERF
- RegisterPerfId();
-#endif // PERF
-}
-
-
-CVideoTransformFilter::~CVideoTransformFilter()
-{
- // nothing to do
-}
-
-
-// Reset our quality management state
-
-HRESULT CVideoTransformFilter::StartStreaming()
-{
- m_itrLate = 0;
- m_nKeyFramePeriod = 0; // No QM until we see at least 2 key frames
- m_nFramesSinceKeyFrame = 0;
- m_bSkipping = FALSE;
- m_tDecodeStart = 0;
- m_itrAvgDecode = 300000; // 30mSec - probably allows skipping
- m_bQualityChanged = FALSE;
- m_bSampleSkipped = FALSE;
- return NOERROR;
-}
-
-
-// Overriden to reset quality management information
-
-HRESULT CVideoTransformFilter::EndFlush()
-{
- {
- // Synchronize
- CAutoLock lck(&m_csReceive);
-
- // Reset our stats
- //
- // Note - we don't want to call derived classes here,
- // we only want to reset our internal variables and this
- // is a convenient way to do it
- CVideoTransformFilter::StartStreaming();
- }
- return CTransformFilter::EndFlush();
-}
-
-
-HRESULT CVideoTransformFilter::AbortPlayback(HRESULT hr)
-{
- NotifyEvent(EC_ERRORABORT, hr, 0);
- m_pOutput->DeliverEndOfStream();
- return hr;
-}
-
-
-// Receive()
-//
-// Accept a sample from upstream, decide whether to process it
-// or drop it. If we process it then get a buffer from the
-// allocator of the downstream connection, transform it into the
-// new buffer and deliver it to the downstream filter.
-// If we decide not to process it then we do not get a buffer.
-
-// Remember that although this code will notice format changes coming into
-// the input pin, it will NOT change its output format if that results
-// in the filter needing to make a corresponding output format change. Your
-// derived filter will have to take care of that. (eg. a palette change if
-// the input and output is an 8 bit format). If the input sample is discarded
-// and nothing is sent out for this Receive, please remember to put the format
-// change on the first output sample that you actually do send.
-// If your filter will produce the same output type even when the input type
-// changes, then this base class code will do everything you need.
-
-HRESULT CVideoTransformFilter::Receive(IMediaSample *pSample)
-{
- // If the next filter downstream is the video renderer, then it may
- // be able to operate in DirectDraw mode which saves copying the data
- // and gives higher performance. In that case the buffer which we
- // get from GetDeliveryBuffer will be a DirectDraw buffer, and
- // drawing into this buffer draws directly onto the display surface.
- // This means that any waiting for the correct time to draw occurs
- // during GetDeliveryBuffer, and that once the buffer is given to us
- // the video renderer will count it in its statistics as a frame drawn.
- // This means that any decision to drop the frame must be taken before
- // calling GetDeliveryBuffer.
-
- ASSERT(CritCheckIn(&m_csReceive));
- AM_MEDIA_TYPE *pmtOut, *pmt;
-#ifdef DEBUG
- FOURCCMap fccOut;
-#endif
- HRESULT hr;
- ASSERT(pSample);
- IMediaSample * pOutSample;
-
- // If no output pin to deliver to then no point sending us data
- ASSERT (m_pOutput != NULL) ;
-
- // The source filter may dynamically ask us to start transforming from a
- // different media type than the one we're using now. If we don't, we'll
- // draw garbage. (typically, this is a palette change in the movie,
- // but could be something more sinister like the compression type changing,
- // or even the video size changing)
-
-#define rcS1 ((VIDEOINFOHEADER *)(pmt->pbFormat))->rcSource
-#define rcT1 ((VIDEOINFOHEADER *)(pmt->pbFormat))->rcTarget
-
- pSample->GetMediaType(&pmt);
- if (pmt != NULL && pmt->pbFormat != NULL) {
-
- // spew some debug output
- ASSERT(!IsEqualGUID(pmt->majortype, GUID_NULL));
-#ifdef DEBUG
- fccOut.SetFOURCC(&pmt->subtype);
- LONG lCompression = HEADER(pmt->pbFormat)->biCompression;
- LONG lBitCount = HEADER(pmt->pbFormat)->biBitCount;
- LONG lStride = (HEADER(pmt->pbFormat)->biWidth * lBitCount + 7) / 8;
- lStride = (lStride + 3) & ~3;
- DbgLog((LOG_TRACE,3,TEXT("*Changing input type on the fly to")));
- DbgLog((LOG_TRACE,3,TEXT("FourCC: %lx Compression: %lx BitCount: %ld"),
- fccOut.GetFOURCC(), lCompression, lBitCount));
- DbgLog((LOG_TRACE,3,TEXT("biHeight: %ld rcDst: (%ld, %ld, %ld, %ld)"),
- HEADER(pmt->pbFormat)->biHeight,
- rcT1.left, rcT1.top, rcT1.right, rcT1.bottom));
- DbgLog((LOG_TRACE,3,TEXT("rcSrc: (%ld, %ld, %ld, %ld) Stride: %ld"),
- rcS1.left, rcS1.top, rcS1.right, rcS1.bottom,
- lStride));
-#endif
-
- // now switch to using the new format. I am assuming that the
- // derived filter will do the right thing when its media type is
- // switched and streaming is restarted.
-
- StopStreaming();
- m_pInput->CurrentMediaType() = *pmt;
- DeleteMediaType(pmt);
- // if this fails, playback will stop, so signal an error
- hr = StartStreaming();
- if (FAILED(hr)) {
- return AbortPlayback(hr);
- }
- }
-
- // Now that we have noticed any format changes on the input sample, it's
- // OK to discard it.
-
- if (ShouldSkipFrame(pSample)) {
- MSR_NOTE(m_idSkip);
- m_bSampleSkipped = TRUE;
- return NOERROR;
- }
-
- // Set up the output sample
- hr = InitializeOutputSample(pSample, &pOutSample);
-
- if (FAILED(hr)) {
- return hr;
- }
-
- m_bSampleSkipped = FALSE;
-
- // The renderer may ask us to on-the-fly to start transforming to a
- // different format. If we don't obey it, we'll draw garbage
-
-#define rcS ((VIDEOINFOHEADER *)(pmtOut->pbFormat))->rcSource
-#define rcT ((VIDEOINFOHEADER *)(pmtOut->pbFormat))->rcTarget
-
- pOutSample->GetMediaType(&pmtOut);
- if (pmtOut != NULL && pmtOut->pbFormat != NULL) {
-
- // spew some debug output
- ASSERT(!IsEqualGUID(pmtOut->majortype, GUID_NULL));
-#ifdef DEBUG
- fccOut.SetFOURCC(&pmtOut->subtype);
- LONG lCompression = HEADER(pmtOut->pbFormat)->biCompression;
- LONG lBitCount = HEADER(pmtOut->pbFormat)->biBitCount;
- LONG lStride = (HEADER(pmtOut->pbFormat)->biWidth * lBitCount + 7) / 8;
- lStride = (lStride + 3) & ~3;
- DbgLog((LOG_TRACE,3,TEXT("*Changing output type on the fly to")));
- DbgLog((LOG_TRACE,3,TEXT("FourCC: %lx Compression: %lx BitCount: %ld"),
- fccOut.GetFOURCC(), lCompression, lBitCount));
- DbgLog((LOG_TRACE,3,TEXT("biHeight: %ld rcDst: (%ld, %ld, %ld, %ld)"),
- HEADER(pmtOut->pbFormat)->biHeight,
- rcT.left, rcT.top, rcT.right, rcT.bottom));
- DbgLog((LOG_TRACE,3,TEXT("rcSrc: (%ld, %ld, %ld, %ld) Stride: %ld"),
- rcS.left, rcS.top, rcS.right, rcS.bottom,
- lStride));
-#endif
-
- // now switch to using the new format. I am assuming that the
- // derived filter will do the right thing when its media type is
- // switched and streaming is restarted.
-
- StopStreaming();
- m_pOutput->CurrentMediaType() = *pmtOut;
- DeleteMediaType(pmtOut);
- hr = StartStreaming();
-
- if (SUCCEEDED(hr)) {
- // a new format, means a new empty buffer, so wait for a keyframe
- // before passing anything on to the renderer.
- // !!! a keyframe may never come, so give up after 30 frames
- DbgLog((LOG_TRACE,3,TEXT("Output format change means we must wait for a keyframe")));
- m_nWaitForKey = 30;
-
- // if this fails, playback will stop, so signal an error
- } else {
-
- // Must release the sample before calling AbortPlayback
- // because we might be holding the win16 lock or
- // ddraw lock
- pOutSample->Release();
- AbortPlayback(hr);
- return hr;
- }
- }
-
- // After a discontinuity, we need to wait for the next key frame
- if (pSample->IsDiscontinuity() == S_OK) {
- DbgLog((LOG_TRACE,3,TEXT("Non-key discontinuity - wait for keyframe")));
- m_nWaitForKey = 30;
- }
-
- // Start timing the transform (and log it if PERF is defined)
-
- if (SUCCEEDED(hr)) {
- m_tDecodeStart = timeGetTime();
- MSR_START(m_idTransform);
-
- // have the derived class transform the data
- hr = Transform(pSample, pOutSample);
-
- // Stop the clock (and log it if PERF is defined)
- MSR_STOP(m_idTransform);
- m_tDecodeStart = timeGetTime()-m_tDecodeStart;
- m_itrAvgDecode = m_tDecodeStart*(10000/16) + 15*(m_itrAvgDecode/16);
-
- // Maybe we're waiting for a keyframe still?
- if (m_nWaitForKey)
- m_nWaitForKey--;
- if (m_nWaitForKey && pSample->IsSyncPoint() == S_OK)
- m_nWaitForKey = FALSE;
-
- // if so, then we don't want to pass this on to the renderer
- if (m_nWaitForKey && hr == NOERROR) {
- DbgLog((LOG_TRACE,3,TEXT("still waiting for a keyframe")));
- hr = S_FALSE;
- }
- }
-
- if (FAILED(hr)) {
- DbgLog((LOG_TRACE,1,TEXT("Error from video transform")));
- } else {
- // the Transform() function can return S_FALSE to indicate that the
- // sample should not be delivered; we only deliver the sample if it's
- // really S_OK (same as NOERROR, of course.)
- // Try not to return S_FALSE to a direct draw buffer (it's wasteful)
- // Try to take the decision earlier - before you get it.
-
- if (hr == NOERROR) {
- hr = m_pOutput->Deliver(pOutSample);
- } else {
- // S_FALSE returned from Transform is a PRIVATE agreement
- // We should return NOERROR from Receive() in this case because returning S_FALSE
- // from Receive() means that this is the end of the stream and no more data should
- // be sent.
- if (S_FALSE == hr) {
-
- // We must Release() the sample before doing anything
- // like calling the filter graph because having the
- // sample means we may have the DirectDraw lock
- // (== win16 lock on some versions)
- pOutSample->Release();
- m_bSampleSkipped = TRUE;
- if (!m_bQualityChanged) {
- m_bQualityChanged = TRUE;
- NotifyEvent(EC_QUALITY_CHANGE,0,0);
- }
- return NOERROR;
- }
- }
- }
-
- // release the output buffer. If the connected pin still needs it,
- // it will have addrefed it itself.
- pOutSample->Release();
- ASSERT(CritCheckIn(&m_csReceive));
-
- return hr;
-}
-
-
-
-BOOL CVideoTransformFilter::ShouldSkipFrame( IMediaSample * pIn)
-{
- REFERENCE_TIME trStart, trStopAt;
- HRESULT hr = pIn->GetTime(&trStart, &trStopAt);
-
- // Don't skip frames with no timestamps
- if (hr != S_OK)
- return FALSE;
-
- int itrFrame = (int)(trStopAt - trStart); // frame duration
-
- if(S_OK==pIn->IsSyncPoint()) {
- MSR_INTEGER(m_idFrameType, 1);
- if ( m_nKeyFramePeriod < m_nFramesSinceKeyFrame ) {
- // record the max
- m_nKeyFramePeriod = m_nFramesSinceKeyFrame;
- }
- m_nFramesSinceKeyFrame = 0;
- m_bSkipping = FALSE;
- } else {
- MSR_INTEGER(m_idFrameType, 2);
- if ( m_nFramesSinceKeyFrame>m_nKeyFramePeriod
- && m_nKeyFramePeriod>0
- ) {
- // We haven't seen the key frame yet, but we were clearly being
- // overoptimistic about how frequent they are.
- m_nKeyFramePeriod = m_nFramesSinceKeyFrame;
- }
- }
-
-
- // Whatever we might otherwise decide,
- // if we are taking only a small fraction of the required frame time to decode
- // then any quality problems are actually coming from somewhere else.
- // Could be a net problem at the source for instance. In this case there's
- // no point in us skipping frames here.
- if (m_itrAvgDecode*4>itrFrame) {
-
- // Don't skip unless we are at least a whole frame late.
- // (We would skip B frames if more than 1/2 frame late, but they're safe).
- if ( m_itrLate > itrFrame ) {
-
- // Don't skip unless the anticipated key frame would be no more than
- // 1 frame early. If the renderer has not been waiting (we *guess*
- // it hasn't because we're late) then it will allow frames to be
- // played early by up to a frame.
-
- // Let T = Stream time from now to anticipated next key frame
- // = (frame duration) * (KeyFramePeriod - FramesSinceKeyFrame)
- // So we skip if T - Late < one frame i.e.
- // (duration) * (freq - FramesSince) - Late < duration
- // or (duration) * (freq - FramesSince - 1) < Late
-
- // We don't dare skip until we have seen some key frames and have
- // some idea how often they occur and they are reasonably frequent.
- if (m_nKeyFramePeriod>0) {
- // It would be crazy - but we could have a stream with key frames
- // a very long way apart - and if they are further than about
- // 3.5 minutes apart then we could get arithmetic overflow in
- // reference time units. Therefore we switch to mSec at this point
- int it = (itrFrame/10000)
- * (m_nKeyFramePeriod-m_nFramesSinceKeyFrame - 1);
- MSR_INTEGER(m_idTimeTillKey, it);
-
- // For debug - might want to see the details - dump them as scratch pad
-#ifdef VTRANSPERF
- MSR_INTEGER(0, itrFrame);
- MSR_INTEGER(0, m_nFramesSinceKeyFrame);
- MSR_INTEGER(0, m_nKeyFramePeriod);
-#endif
- if (m_itrLate/10000 > it) {
- m_bSkipping = TRUE;
- // Now we are committed. Once we start skipping, we
- // cannot stop until we hit a key frame.
- } else {
-#ifdef VTRANSPERF
- MSR_INTEGER(0, 777770); // not near enough to next key
-#endif
- }
- } else {
-#ifdef VTRANSPERF
- MSR_INTEGER(0, 777771); // Next key not predictable
-#endif
- }
- } else {
-#ifdef VTRANSPERF
- MSR_INTEGER(0, 777772); // Less than one frame late
- MSR_INTEGER(0, m_itrLate);
- MSR_INTEGER(0, itrFrame);
-#endif
- }
- } else {
-#ifdef VTRANSPERF
- MSR_INTEGER(0, 777773); // Decode time short - not not worth skipping
- MSR_INTEGER(0, m_itrAvgDecode);
- MSR_INTEGER(0, itrFrame);
-#endif
- }
-
- ++m_nFramesSinceKeyFrame;
-
- if (m_bSkipping) {
- // We will count down the lateness as we skip each frame.
- // We re-assess each frame. The key frame might not arrive when expected.
- // We reset m_itrLate if we get a new Quality message, but actually that's
- // not likely because we're not sending frames on to the Renderer. In
- // fact if we DID get another one it would mean that there's a long
- // pipe between us and the renderer and we might need an altogether
- // better strategy to avoid hunting!
- m_itrLate = m_itrLate - itrFrame;
- }
-
- MSR_INTEGER(m_idLate, (int)m_itrLate/10000 ); // Note how late we think we are
- if (m_bSkipping) {
- if (!m_bQualityChanged) {
- m_bQualityChanged = TRUE;
- NotifyEvent(EC_QUALITY_CHANGE,0,0);
- }
- }
- return m_bSkipping;
-}
-
-
-HRESULT CVideoTransformFilter::AlterQuality(Quality q)
-{
- // to reduce the amount of 64 bit arithmetic, m_itrLate is an int.
- // +, -, >, == etc are not too bad, but * and / are painful.
- if (m_itrLate>300000000) {
- // Avoid overflow and silliness - more than 30 secs late is already silly
- m_itrLate = 300000000;
- } else {
- m_itrLate = (int)q.Late;
- }
- // We ignore the other fields
-
- // We're actually not very good at handling this. In non-direct draw mode
- // most of the time can be spent in the renderer which can skip any frame.
- // In that case we'd rather the renderer handled things.
- // Nevertheless we will keep an eye on it and if we really start getting
- // a very long way behind then we will actually skip - but we'll still tell
- // the renderer (or whoever is downstream) that they should handle quality.
-
- return E_FAIL; // Tell the renderer to do his thing.
-
-}
-
-
-
-// This will avoid several hundred useless warnings if compiled -W4 by MS VC++ v4
-#pragma warning(disable:4514)
-
diff --git a/dll/src/baseclasses/vtrans.h b/dll/src/baseclasses/vtrans.h
deleted file mode 100644
index 49b1509..0000000
--- a/dll/src/baseclasses/vtrans.h
+++ /dev/null
@@ -1,143 +0,0 @@
-//------------------------------------------------------------------------------
-// File: VTrans.h
-//
-// Desc: DirectShow base classes - defines a video transform class.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-// This class is derived from CTransformFilter, but is specialised to handle
-// the requirements of video quality control by frame dropping.
-// This is a non-in-place transform, (i.e. it copies the data) such as a decoder.
-
-class CVideoTransformFilter : public CTransformFilter
-{
- public:
-
- CVideoTransformFilter(__in_opt LPCTSTR, __inout_opt LPUNKNOWN, REFCLSID clsid);
- ~CVideoTransformFilter();
- HRESULT EndFlush();
-
- // =================================================================
- // ----- override these bits ---------------------------------------
- // =================================================================
- // The following methods are in CTransformFilter which is inherited.
- // They are mentioned here for completeness
- //
- // These MUST be supplied in a derived class
- //
- // NOTE:
- // virtual HRESULT Transform(IMediaSample * pIn, IMediaSample *pOut);
- // virtual HRESULT CheckInputType(const CMediaType* mtIn) PURE;
- // virtual HRESULT CheckTransform
- // (const CMediaType* mtIn, const CMediaType* mtOut) PURE;
- // static CCOMObject * CreateInstance(LPUNKNOWN, HRESULT *);
- // virtual HRESULT DecideBufferSize
- // (IMemAllocator * pAllocator, ALLOCATOR_PROPERTIES *pprop) PURE;
- // virtual HRESULT GetMediaType(int iPosition, CMediaType *pMediaType) PURE;
- //
- // These MAY also be overridden
- //
- // virtual HRESULT StopStreaming();
- // virtual HRESULT SetMediaType(PIN_DIRECTION direction,const CMediaType *pmt);
- // virtual HRESULT CheckConnect(PIN_DIRECTION dir,IPin *pPin);
- // virtual HRESULT BreakConnect(PIN_DIRECTION dir);
- // virtual HRESULT CompleteConnect(PIN_DIRECTION direction,IPin *pReceivePin);
- // virtual HRESULT EndOfStream(void);
- // virtual HRESULT BeginFlush(void);
- // virtual HRESULT EndFlush(void);
- // virtual HRESULT NewSegment
- // (REFERENCE_TIME tStart,REFERENCE_TIME tStop,double dRate);
-#ifdef PERF
-
- // If you override this - ensure that you register all these ids
- // as well as any of your own,
- virtual void RegisterPerfId() {
- m_idSkip = MSR_REGISTER(TEXT("Video Transform Skip frame"));
- m_idFrameType = MSR_REGISTER(TEXT("Video transform frame type"));
- m_idLate = MSR_REGISTER(TEXT("Video Transform Lateness"));
- m_idTimeTillKey = MSR_REGISTER(TEXT("Video Transform Estd. time to next key"));
- CTransformFilter::RegisterPerfId();
- }
-#endif
-
- protected:
-
- // =========== QUALITY MANAGEMENT IMPLEMENTATION ========================
- // Frames are assumed to come in three types:
- // Type 1: an AVI key frame or an MPEG I frame.
- // This frame can be decoded with no history.
- // Dropping this frame means that no further frame can be decoded
- // until the next type 1 frame.
- // Type 1 frames are sync points.
- // Type 2: an AVI non-key frame or an MPEG P frame.
- // This frame cannot be decoded unless the previous type 1 frame was
- // decoded and all type 2 frames since have been decoded.
- // Dropping this frame means that no further frame can be decoded
- // until the next type 1 frame.
- // Type 3: An MPEG B frame.
- // This frame cannot be decoded unless the previous type 1 or 2 frame
- // has been decoded AND the subsequent type 1 or 2 frame has also
- // been decoded. (This requires decoding the frames out of sequence).
- // Dropping this frame affects no other frames. This implementation
- // does not allow for these. All non-sync-point frames are treated
- // as being type 2.
- //
- // The spacing of frames of type 1 in a file is not guaranteed. There MUST
- // be a type 1 frame at (well, near) the start of the file in order to start
- // decoding at all. After that there could be one every half second or so,
- // there could be one at the start of each scene (aka "cut", "shot") or
- // there could be no more at all.
- // If there is only a single type 1 frame then NO FRAMES CAN BE DROPPED
- // without losing all the rest of the movie. There is no way to tell whether
- // this is the case, so we find that we are in the gambling business.
- // To try to improve the odds, we record the greatest interval between type 1s
- // that we have seen and we bet on things being no worse than this in the
- // future.
-
- // You can tell if it's a type 1 frame by calling IsSyncPoint().
- // there is no architected way to test for a type 3, so you should override
- // the quality management here if you have B-frames.
-
- int m_nKeyFramePeriod; // the largest observed interval between type 1 frames
- // 1 means every frame is type 1, 2 means every other.
-
- int m_nFramesSinceKeyFrame; // Used to count frames since the last type 1.
- // becomes the new m_nKeyFramePeriod if greater.
-
- BOOL m_bSkipping; // we are skipping to the next type 1 frame
-
-#ifdef PERF
- int m_idFrameType; // MSR id Frame type. 1=Key, 2="non-key"
- int m_idSkip; // MSR id skipping
- int m_idLate; // MSR id lateness
- int m_idTimeTillKey; // MSR id for guessed time till next key frame.
-#endif
-
- virtual HRESULT StartStreaming();
-
- HRESULT AbortPlayback(HRESULT hr); // if something bad happens
-
- HRESULT Receive(IMediaSample *pSample);
-
- HRESULT AlterQuality(Quality q);
-
- BOOL ShouldSkipFrame(IMediaSample * pIn);
-
- int m_itrLate; // lateness from last Quality message
- // (this overflows at 214 secs late).
- int m_tDecodeStart; // timeGetTime when decode started.
- int m_itrAvgDecode; // Average decode time in reference units.
-
- BOOL m_bNoSkip; // debug - no skipping.
-
- // We send an EC_QUALITY_CHANGE notification to the app if we have to degrade.
- // We send one when we start degrading, not one for every frame, this means
- // we track whether we've sent one yet.
- BOOL m_bQualityChanged;
-
- // When non-zero, don't pass anything to renderer until next keyframe
- // If there are few keys, give up and eventually draw something
- int m_nWaitForKey;
-};
diff --git a/dll/src/baseclasses/winctrl.cpp b/dll/src/baseclasses/winctrl.cpp
deleted file mode 100644
index 4d1f52e..0000000
--- a/dll/src/baseclasses/winctrl.cpp
+++ /dev/null
@@ -1,2081 +0,0 @@
-//------------------------------------------------------------------------------
-// File: WinCtrl.cpp
-//
-// Desc: DirectShow base classes - implements video control interface class.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-#include <streams.h>
-#include <intsafe.h>
-#include <checkbmi.h>
-
-// The control interface methods require us to be connected
-
-#define CheckConnected(pin,code) \
-{ \
- if (pin == NULL) { \
- ASSERT(!TEXT("Pin not set")); \
- } else if (pin->IsConnected() == FALSE) { \
- return (code); \
- } \
-}
-
-// This checks to see whether the window has a drain. An application can in
-// most environments set the owner/parent of windows so that they appear in
-// a compound document context (for example). In this case, the application
-// would probably like to be told of any keyboard/mouse messages. Therefore
-// we pass these messages on untranslated, returning TRUE if we're successful
-
-BOOL WINAPI PossiblyEatMessage(HWND hwndDrain, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- if (hwndDrain != NULL && !InSendMessage())
- {
- switch (uMsg)
- {
- case WM_CHAR:
- case WM_DEADCHAR:
- case WM_KEYDOWN:
- case WM_KEYUP:
- case WM_LBUTTONDBLCLK:
- case WM_LBUTTONDOWN:
- case WM_LBUTTONUP:
- case WM_MBUTTONDBLCLK:
- case WM_MBUTTONDOWN:
- case WM_MBUTTONUP:
- case WM_MOUSEACTIVATE:
- case WM_MOUSEMOVE:
- // If we pass this on we don't get any mouse clicks
- //case WM_NCHITTEST:
- case WM_NCLBUTTONDBLCLK:
- case WM_NCLBUTTONDOWN:
- case WM_NCLBUTTONUP:
- case WM_NCMBUTTONDBLCLK:
- case WM_NCMBUTTONDOWN:
- case WM_NCMBUTTONUP:
- case WM_NCMOUSEMOVE:
- case WM_NCRBUTTONDBLCLK:
- case WM_NCRBUTTONDOWN:
- case WM_NCRBUTTONUP:
- case WM_RBUTTONDBLCLK:
- case WM_RBUTTONDOWN:
- case WM_RBUTTONUP:
- case WM_SYSCHAR:
- case WM_SYSDEADCHAR:
- case WM_SYSKEYDOWN:
- case WM_SYSKEYUP:
-
- DbgLog((LOG_TRACE, 2, TEXT("Forwarding %x to drain")));
- PostMessage(hwndDrain, uMsg, wParam, lParam);
-
- return TRUE;
- }
- }
- return FALSE;
-}
-
-
-// This class implements the IVideoWindow control functions (dual interface)
-// we support a large number of properties and methods designed to allow the
-// client (whether it be an automation controller or a C/C++ application) to
-// set and get a number of window related properties such as it's position.
-// We also support some methods that duplicate the properties but provide a
-// more direct and efficient mechanism as many values may be changed in one
-
-CBaseControlWindow::CBaseControlWindow(
- __inout CBaseFilter *pFilter, // Owning filter
- __in CCritSec *pInterfaceLock, // Locking object
- __in_opt LPCTSTR pName, // Object description
- __inout_opt LPUNKNOWN pUnk, // Normal COM ownership
- __inout HRESULT *phr) : // OLE return code
-
- CBaseVideoWindow(pName,pUnk),
- m_pInterfaceLock(pInterfaceLock),
- m_hwndOwner(NULL),
- m_hwndDrain(NULL),
- m_bAutoShow(TRUE),
- m_pFilter(pFilter),
- m_bCursorHidden(FALSE),
- m_pPin(NULL)
-{
- ASSERT(m_pFilter);
- ASSERT(m_pInterfaceLock);
- ASSERT(phr);
- m_BorderColour = VIDEO_COLOUR;
-}
-
-
-// Set the title caption on the base window, we don't do any field checking
-// as we really don't care what title they intend to have. We can always get
-// it back again later with GetWindowText. The only other complication is to
-// do the necessary string conversions between ANSI and OLE Unicode strings
-
-STDMETHODIMP CBaseControlWindow::put_Caption(__in BSTR strCaption)
-{
- CheckPointer((PVOID)strCaption,E_POINTER);
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
-#ifdef UNICODE
- SetWindowText(m_hwnd, strCaption);
-#else
- CHAR Caption[CAPTION];
-
- WideCharToMultiByte(CP_ACP,0,strCaption,-1,Caption,CAPTION,NULL,NULL);
- SetWindowText(m_hwnd, Caption);
-#endif
- return NOERROR;
-}
-
-
-// Get the current base window title caption, once again we do no real field
-// checking. We allocate a string for the window title to be filled in with
-// which ensures the interface doesn't fiddle around with getting memory. A
-// BSTR is a normal C string with the length at position (-1), we use the
-// WriteBSTR helper function to create the caption to try and avoid OLE32
-
-STDMETHODIMP CBaseControlWindow::get_Caption(__out BSTR *pstrCaption)
-{
- CheckPointer(pstrCaption,E_POINTER);
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- WCHAR WideCaption[CAPTION];
-
-#ifdef UNICODE
- GetWindowText(m_hwnd,WideCaption,CAPTION);
-#else
- // Convert the ASCII caption to a UNICODE string
-
- TCHAR Caption[CAPTION];
- GetWindowText(m_hwnd,Caption,CAPTION);
- MultiByteToWideChar(CP_ACP,0,Caption,-1,WideCaption,CAPTION);
-#endif
- return WriteBSTR(pstrCaption,WideCaption);
-}
-
-
-// Set the window style using GWL_EXSTYLE
-
-STDMETHODIMP CBaseControlWindow::put_WindowStyleEx(long WindowStyleEx)
-{
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
-
- // Should we be taking off WS_EX_TOPMOST
-
- if (GetWindowLong(m_hwnd,GWL_EXSTYLE) & WS_EX_TOPMOST) {
- if ((WindowStyleEx & WS_EX_TOPMOST) == 0) {
- SendMessage(m_hwnd,m_ShowStageTop,(WPARAM) FALSE,(LPARAM) 0);
- }
- }
-
- // Likewise should we be adding WS_EX_TOPMOST
-
- if (WindowStyleEx & WS_EX_TOPMOST) {
- SendMessage(m_hwnd,m_ShowStageTop,(WPARAM) TRUE,(LPARAM) 0);
- WindowStyleEx &= (~WS_EX_TOPMOST);
- if (WindowStyleEx == 0) return NOERROR;
- }
- return DoSetWindowStyle(WindowStyleEx,GWL_EXSTYLE);
-}
-
-
-// Gets the current GWL_EXSTYLE base window style
-
-STDMETHODIMP CBaseControlWindow::get_WindowStyleEx(__out long *pWindowStyleEx)
-{
- CheckPointer(pWindowStyleEx,E_POINTER);
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- return DoGetWindowStyle(pWindowStyleEx,GWL_EXSTYLE);
-}
-
-
-// Set the window style using GWL_STYLE
-
-STDMETHODIMP CBaseControlWindow::put_WindowStyle(long WindowStyle)
-{
- // These styles cannot be changed dynamically
-
- if ((WindowStyle & WS_DISABLED) ||
- (WindowStyle & WS_ICONIC) ||
- (WindowStyle & WS_MAXIMIZE) ||
- (WindowStyle & WS_MINIMIZE) ||
- (WindowStyle & WS_HSCROLL) ||
- (WindowStyle & WS_VSCROLL)) {
-
- return E_INVALIDARG;
- }
-
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- return DoSetWindowStyle(WindowStyle,GWL_STYLE);
-}
-
-
-// Get the current GWL_STYLE base window style
-
-STDMETHODIMP CBaseControlWindow::get_WindowStyle(__out long *pWindowStyle)
-{
- CheckPointer(pWindowStyle,E_POINTER);
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- return DoGetWindowStyle(pWindowStyle,GWL_STYLE);
-}
-
-
-// Change the base window style or the extended styles depending on whether
-// WindowLong is GWL_STYLE or GWL_EXSTYLE. We must call SetWindowPos to have
-// the window displayed in it's new style after the change which is a little
-// tricky if the window is not currently visible as we realise it offscreen.
-// In most cases the client will call get_WindowStyle before they call this
-// and then AND and OR in extra bit settings according to the requirements
-
-HRESULT CBaseControlWindow::DoSetWindowStyle(long Style,long WindowLong)
-{
- RECT WindowRect;
-
- // Get the window's visibility before setting the style
- BOOL bVisible = IsWindowVisible(m_hwnd);
- EXECUTE_ASSERT(GetWindowRect(m_hwnd,&WindowRect));
-
- // Set the new style flags for the window
- SetWindowLong(m_hwnd,WindowLong,Style);
- UINT WindowFlags = SWP_SHOWWINDOW | SWP_FRAMECHANGED | SWP_NOACTIVATE;
- WindowFlags |= SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE;
-
- // Show the window again in the current position
-
- if (bVisible == TRUE) {
-
- SetWindowPos(m_hwnd, // Base window handle
- HWND_TOP, // Just a place holder
- 0,0,0,0, // Leave size and position
- WindowFlags); // Just draw it again
-
- return NOERROR;
- }
-
- // Move the window offscreen so the user doesn't see the changes
-
- MoveWindow((HWND) m_hwnd, // Base window handle
- GetSystemMetrics(SM_CXSCREEN), // Current desktop width
- GetSystemMetrics(SM_CYSCREEN), // Likewise it's height
- WIDTH(&WindowRect), // Use the same width
- HEIGHT(&WindowRect), // Keep height same to
- TRUE); // May as well repaint
-
- // Now show the previously hidden window
-
- SetWindowPos(m_hwnd, // Base window handle
- HWND_TOP, // Just a place holder
- 0,0,0,0, // Leave size and position
- WindowFlags); // Just draw it again
-
- ShowWindow(m_hwnd,SW_HIDE);
-
- if (GetParent(m_hwnd)) {
-
- MapWindowPoints(HWND_DESKTOP, GetParent(m_hwnd), (LPPOINT)&WindowRect, 2);
- }
-
- MoveWindow((HWND) m_hwnd, // Base window handle
- WindowRect.left, // Existing x coordinate
- WindowRect.top, // Existing y coordinate
- WIDTH(&WindowRect), // Use the same width
- HEIGHT(&WindowRect), // Keep height same to
- TRUE); // May as well repaint
-
- return NOERROR;
-}
-
-
-// Get the current base window style (either GWL_STYLE or GWL_EXSTYLE)
-
-HRESULT CBaseControlWindow::DoGetWindowStyle(__out long *pStyle,long WindowLong)
-{
- *pStyle = GetWindowLong(m_hwnd,WindowLong);
- return NOERROR;
-}
-
-
-// Change the visibility of the base window, this takes the same parameters
-// as the ShowWindow Win32 API does, so the client can have the window hidden
-// or shown, minimised to an icon, or maximised to play in full screen mode
-// We pass the request on to the base window to actually make the change
-
-STDMETHODIMP CBaseControlWindow::put_WindowState(long WindowState)
-{
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- DoShowWindow(WindowState);
- return NOERROR;
-}
-
-
-// Get the current window state, this function returns a subset of the SW bit
-// settings available in ShowWindow, if the window is visible then SW_SHOW is
-// set, if it is hidden then the SW_HIDDEN is set, if it is either minimised
-// or maximised then the SW_MINIMIZE or SW_MAXIMIZE is set respectively. The
-// other SW bit settings are really set commands not readable output values
-
-STDMETHODIMP CBaseControlWindow::get_WindowState(__out long *pWindowState)
-{
- CheckPointer(pWindowState,E_POINTER);
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- ASSERT(pWindowState);
- *pWindowState = FALSE;
-
- // Is the window visible, a window is termed visible if it is somewhere on
- // the current desktop even if it is completely obscured by other windows
- // so the flag is a style for each window set with the WS_VISIBLE bit
-
- if (IsWindowVisible(m_hwnd) == TRUE) {
-
- // Is the base window iconic
- if (IsIconic(m_hwnd) == TRUE) {
- *pWindowState |= SW_MINIMIZE;
- }
-
- // Has the window been maximised
- else if (IsZoomed(m_hwnd) == TRUE) {
- *pWindowState |= SW_MAXIMIZE;
- }
-
- // Window is normal
- else {
- *pWindowState |= SW_SHOW;
- }
-
- } else {
- *pWindowState |= SW_HIDE;
- }
- return NOERROR;
-}
-
-
-// This makes sure that any palette we realise in the base window (through a
-// media type or through the overlay interface) is done in the background and
-// is therefore mapped to existing device entries rather than taking it over
-// as it will do when we this window gets the keyboard focus. An application
-// uses this to make sure it doesn't have it's palette removed by the window
-
-STDMETHODIMP CBaseControlWindow::put_BackgroundPalette(long BackgroundPalette)
-{
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- CAutoLock cWindowLock(&m_WindowLock);
-
- // Check this is a valid automation boolean type
-
- if (BackgroundPalette != OATRUE) {
- if (BackgroundPalette != OAFALSE) {
- return E_INVALIDARG;
- }
- }
-
- // Make sure the window realises any palette it has again
-
- m_bBackground = (BackgroundPalette == OATRUE ? TRUE : FALSE);
- PostMessage(m_hwnd,m_RealizePalette,0,0);
- PaintWindow(FALSE);
-
- return NOERROR;
-}
-
-
-// This returns the current background realisation setting
-
-STDMETHODIMP
-CBaseControlWindow::get_BackgroundPalette(__out long *pBackgroundPalette)
-{
- CheckPointer(pBackgroundPalette,E_POINTER);
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- CAutoLock cWindowLock(&m_WindowLock);
-
- // Get the current background palette setting
-
- *pBackgroundPalette = (m_bBackground == TRUE ? OATRUE : OAFALSE);
- return NOERROR;
-}
-
-
-// Change the visibility of the base window
-
-STDMETHODIMP CBaseControlWindow::put_Visible(long Visible)
-{
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
-
- // Check this is a valid automation boolean type
-
- if (Visible != OATRUE) {
- if (Visible != OAFALSE) {
- return E_INVALIDARG;
- }
- }
-
- // Convert the boolean visibility into SW_SHOW and SW_HIDE
-
- INT Mode = (Visible == OATRUE ? SW_SHOWNORMAL : SW_HIDE);
- DoShowWindow(Mode);
- return NOERROR;
-}
-
-
-// Return OATRUE if the window is currently visible otherwise OAFALSE
-
-STDMETHODIMP CBaseControlWindow::get_Visible(__out long *pVisible)
-{
- CheckPointer(pVisible,E_POINTER);
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
-
- // See if the base window has a WS_VISIBLE style - this will return TRUE
- // even if the window is completely obscured by other desktop windows, we
- // return FALSE if the window is not showing because of earlier calls
-
- BOOL Mode = IsWindowVisible(m_hwnd);
- *pVisible = (Mode == TRUE ? OATRUE : OAFALSE);
- return NOERROR;
-}
-
-
-// Change the left position of the base window. This keeps the window width
-// and height properties the same so it effectively shunts the window left or
-// right accordingly - there is the Width property to change that dimension
-
-STDMETHODIMP CBaseControlWindow::put_Left(long Left)
-{
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- BOOL bSuccess;
- RECT WindowRect;
-
- // Get the current window position in a RECT
- EXECUTE_ASSERT(GetWindowRect(m_hwnd,&WindowRect));
-
- if (GetParent(m_hwnd)) {
-
- MapWindowPoints(HWND_DESKTOP, GetParent(m_hwnd), (LPPOINT)&WindowRect, 2);
- }
-
- // Adjust the coordinates ready for SetWindowPos, the window rectangle we
- // get back from GetWindowRect is in left,top,right and bottom while the
- // coordinates SetWindowPos wants are left,top,width and height values
-
- WindowRect.bottom = WindowRect.bottom - WindowRect.top;
- WindowRect.right = WindowRect.right - WindowRect.left;
- UINT WindowFlags = SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOACTIVATE;
-
- bSuccess = SetWindowPos(m_hwnd, // Window handle
- HWND_TOP, // Put it at the top
- Left, // New left position
- WindowRect.top, // Leave top alone
- WindowRect.right, // The WIDTH (not right)
- WindowRect.bottom, // The HEIGHT (not bottom)
- WindowFlags); // Show window options
-
- if (bSuccess == FALSE) {
- return E_INVALIDARG;
- }
- return NOERROR;
-}
-
-
-// Return the current base window left position
-
-STDMETHODIMP CBaseControlWindow::get_Left(__out long *pLeft)
-{
- CheckPointer(pLeft,E_POINTER);
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- RECT WindowRect;
-
- EXECUTE_ASSERT(GetWindowRect(m_hwnd,&WindowRect));
- *pLeft = WindowRect.left;
- return NOERROR;
-}
-
-
-// Change the current width of the base window. This property complements the
-// left position property so we must keep the left edge constant and expand or
-// contract to the right, the alternative would be to change the left edge so
-// keeping the right edge constant but this is maybe a little more intuitive
-
-STDMETHODIMP CBaseControlWindow::put_Width(long Width)
-{
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- BOOL bSuccess;
- RECT WindowRect;
-
- // Adjust the coordinates ready for SetWindowPos, the window rectangle we
- // get back from GetWindowRect is in left,top,right and bottom while the
- // coordinates SetWindowPos wants are left,top,width and height values
-
- EXECUTE_ASSERT(GetWindowRect(m_hwnd,&WindowRect));
-
- if (GetParent(m_hwnd)) {
-
- MapWindowPoints(HWND_DESKTOP, GetParent(m_hwnd), (LPPOINT)&WindowRect, 2);
- }
-
- WindowRect.bottom = WindowRect.bottom - WindowRect.top;
- UINT WindowFlags = SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOACTIVATE;
-
- // This seems to have a bug in that calling SetWindowPos on a window with
- // just the width changing causes it to ignore the width that you pass in
- // and sets it to a mimimum value of 110 pixels wide (Windows NT 3.51)
-
- bSuccess = SetWindowPos(m_hwnd, // Window handle
- HWND_TOP, // Put it at the top
- WindowRect.left, // Leave left alone
- WindowRect.top, // Leave top alone
- Width, // New WIDTH dimension
- WindowRect.bottom, // The HEIGHT (not bottom)
- WindowFlags); // Show window options
-
- if (bSuccess == FALSE) {
- return E_INVALIDARG;
- }
- return NOERROR;
-}
-
-
-// Return the current base window width
-
-STDMETHODIMP CBaseControlWindow::get_Width(__out long *pWidth)
-{
- CheckPointer(pWidth,E_POINTER);
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- RECT WindowRect;
-
- EXECUTE_ASSERT(GetWindowRect(m_hwnd,&WindowRect));
- *pWidth = WindowRect.right - WindowRect.left;
- return NOERROR;
-}
-
-
-// This allows the client program to change the top position for the window in
-// the same way that changing the left position does not affect the width of
-// the image so changing the top position does not affect the window height
-
-STDMETHODIMP CBaseControlWindow::put_Top(long Top)
-{
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- BOOL bSuccess;
- RECT WindowRect;
-
- // Get the current window position in a RECT
- EXECUTE_ASSERT(GetWindowRect(m_hwnd,&WindowRect));
-
- if (GetParent(m_hwnd)) {
-
- MapWindowPoints(HWND_DESKTOP, GetParent(m_hwnd), (LPPOINT)&WindowRect, 2);
- }
-
- // Adjust the coordinates ready for SetWindowPos, the window rectangle we
- // get back from GetWindowRect is in left,top,right and bottom while the
- // coordinates SetWindowPos wants are left,top,width and height values
-
- WindowRect.bottom = WindowRect.bottom - WindowRect.top;
- WindowRect.right = WindowRect.right - WindowRect.left;
- UINT WindowFlags = SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOACTIVATE;
-
- bSuccess = SetWindowPos(m_hwnd, // Window handle
- HWND_TOP, // Put it at the top
- WindowRect.left, // Leave left alone
- Top, // New top position
- WindowRect.right, // The WIDTH (not right)
- WindowRect.bottom, // The HEIGHT (not bottom)
- WindowFlags); // Show window flags
-
- if (bSuccess == FALSE) {
- return E_INVALIDARG;
- }
- return NOERROR;
-}
-
-
-// Return the current base window top position
-
-STDMETHODIMP CBaseControlWindow::get_Top(long *pTop)
-{
- CheckPointer(pTop,E_POINTER);
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- RECT WindowRect;
-
- EXECUTE_ASSERT(GetWindowRect(m_hwnd,&WindowRect));
- *pTop = WindowRect.top;
- return NOERROR;
-}
-
-
-// Change the height of the window, this complements the top property so when
-// we change this we must keep the top position for the base window, as said
-// before we could keep the bottom and grow upwards although this is perhaps
-// a little more intuitive since we already have a top position property
-
-STDMETHODIMP CBaseControlWindow::put_Height(long Height)
-{
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- BOOL bSuccess;
- RECT WindowRect;
-
- // Adjust the coordinates ready for SetWindowPos, the window rectangle we
- // get back from GetWindowRect is in left,top,right and bottom while the
- // coordinates SetWindowPos wants are left,top,width and height values
-
- EXECUTE_ASSERT(GetWindowRect(m_hwnd,&WindowRect));
-
- if (GetParent(m_hwnd)) {
-
- MapWindowPoints(HWND_DESKTOP, GetParent(m_hwnd), (LPPOINT)&WindowRect, 2);
- }
-
- WindowRect.right = WindowRect.right - WindowRect.left;
- UINT WindowFlags = SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOACTIVATE;
-
- bSuccess = SetWindowPos(m_hwnd, // Window handle
- HWND_TOP, // Put it at the top
- WindowRect.left, // Leave left alone
- WindowRect.top, // Leave top alone
- WindowRect.right, // The WIDTH (not right)
- Height, // New height dimension
- WindowFlags); // Show window flags
-
- if (bSuccess == FALSE) {
- return E_INVALIDARG;
- }
- return NOERROR;
-}
-
-
-// Return the current base window height
-
-STDMETHODIMP CBaseControlWindow::get_Height(__out long *pHeight)
-{
- CheckPointer(pHeight,E_POINTER);
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- RECT WindowRect;
-
- EXECUTE_ASSERT(GetWindowRect(m_hwnd,&WindowRect));
- *pHeight = WindowRect.bottom - WindowRect.top;
- return NOERROR;
-}
-
-
-// This can be called to change the owning window. Setting the owner is done
-// through this function, however to make the window a true child window the
-// style must also be set to WS_CHILD. After resetting the owner to NULL an
-// application should also set the style to WS_OVERLAPPED | WS_CLIPCHILDREN.
-
-// We cannot lock the object here because the SetParent causes an interthread
-// SendMessage to the owner window. If they are in GetState we will sit here
-// incomplete with the critical section locked therefore blocking out source
-// filter threads from accessing us. Because the source thread can't enter us
-// it can't get buffers or call EndOfStream so the GetState will not complete
-
-STDMETHODIMP CBaseControlWindow::put_Owner(OAHWND Owner)
-{
- // Check we are connected otherwise reject the call
-
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- m_hwndOwner = (HWND) Owner;
- HWND hwndParent = m_hwndOwner;
-
- // Add or remove WS_CHILD as appropriate
-
- LONG Style = GetWindowLong(m_hwnd,GWL_STYLE);
- if (Owner == NULL) {
- Style &= (~WS_CHILD);
- } else {
- Style |= (WS_CHILD);
- }
- SetWindowLong(m_hwnd,GWL_STYLE,Style);
-
- // Don't call this with the filter locked
-
- SetParent(m_hwnd,hwndParent);
-
- PaintWindow(TRUE);
- NOTE1("Changed parent %lx",hwndParent);
-
- return NOERROR;
-}
-
-
-// This complements the put_Owner to get the current owning window property
-// we always return NOERROR although the returned window handle may be NULL
-// to indicate no owning window (the desktop window doesn't qualify as one)
-// If an application sets the owner we call SetParent, however that returns
-// NULL until the WS_CHILD bit is set on, so we store the owner internally
-
-STDMETHODIMP CBaseControlWindow::get_Owner(__out OAHWND *Owner)
-{
- CheckPointer(Owner,E_POINTER);
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- *Owner = (OAHWND) m_hwndOwner;
- return NOERROR;
-}
-
-
-// And renderer supporting IVideoWindow may have an HWND set who will get any
-// keyboard and mouse messages we receive posted on to them. This is separate
-// from setting an owning window. By separating the two, applications may get
-// messages sent on even when they have set no owner (perhaps it's maximised)
-
-STDMETHODIMP CBaseControlWindow::put_MessageDrain(OAHWND Drain)
-{
- // Check we are connected otherwise reject the call
-
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- m_hwndDrain = (HWND) Drain;
- return NOERROR;
-}
-
-
-// Return the current message drain
-
-STDMETHODIMP CBaseControlWindow::get_MessageDrain(__out OAHWND *Drain)
-{
- CheckPointer(Drain,E_POINTER);
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- *Drain = (OAHWND) m_hwndDrain;
- return NOERROR;
-}
-
-
-// This is called by the filter graph to inform us of a message we should know
-// is being sent to our owning window. We have this because as a child window
-// we do not get certain messages that are only sent to top level windows. We
-// must see the palette changed/changing/query messages so that we know if we
-// have the foreground palette or not. We pass the message on to our window
-// using SendMessage - this will cause an interthread send message to occur
-
-STDMETHODIMP
-CBaseControlWindow::NotifyOwnerMessage(OAHWND hwnd, // Window handle
- long uMsg, // Message ID
- LONG_PTR wParam, // Parameters
- LONG_PTR lParam) // for message
-{
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
-
- // Only interested in these Windows messages
-
- switch (uMsg) {
-
- case WM_SYSCOLORCHANGE:
- case WM_PALETTECHANGED:
- case WM_PALETTEISCHANGING:
- case WM_QUERYNEWPALETTE:
- case WM_DEVMODECHANGE:
- case WM_DISPLAYCHANGE:
- case WM_ACTIVATEAPP:
-
- // If we do not have an owner then ignore
-
- if (m_hwndOwner == NULL) {
- return NOERROR;
- }
- SendMessage(m_hwnd,uMsg,(WPARAM)wParam,(LPARAM)lParam);
- break;
-
- // do NOT fwd WM_MOVE. the parameters are the location of the parent
- // window, NOT what the renderer should be looking at. But we need
- // to make sure the overlay is moved with the parent window, so we
- // do this.
- case WM_MOVE:
- PostMessage(m_hwnd,WM_PAINT,0,0);
- break;
- }
- return NOERROR;
-}
-
-
-// Allow an application to have us set the base window in the foreground. We
-// have this because it is difficult for one thread to do do this to a window
-// owned by another thread. We ask the base window class to do the real work
-
-STDMETHODIMP CBaseControlWindow::SetWindowForeground(long Focus)
-{
- // Check this is a valid automation boolean type
-
- if (Focus != OATRUE) {
- if (Focus != OAFALSE) {
- return E_INVALIDARG;
- }
- }
-
- // We shouldn't lock as this sends a message
-
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- BOOL bFocus = (Focus == OATRUE ? TRUE : FALSE);
- DoSetWindowForeground(bFocus);
-
- return NOERROR;
-}
-
-
-// This allows a client to set the complete window size and position in one
-// atomic operation. The same affect can be had by changing each dimension
-// in turn through their individual properties although some flashing will
-// occur as each of them gets updated (they are better set at design time)
-
-STDMETHODIMP
-CBaseControlWindow::SetWindowPosition(long Left,long Top,long Width,long Height)
-{
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- BOOL bSuccess;
-
- // Set the new size and position
- UINT WindowFlags = SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOACTIVATE;
-
- ASSERT(IsWindow(m_hwnd));
- bSuccess = SetWindowPos(m_hwnd, // Window handle
- HWND_TOP, // Put it at the top
- Left, // Left position
- Top, // Top position
- Width, // Window width
- Height, // Window height
- WindowFlags); // Show window flags
- ASSERT(bSuccess);
-#ifdef DEBUG
- DbgLog((LOG_TRACE, 1, TEXT("SWP failed error %d"), GetLastError()));
-#endif
- if (bSuccess == FALSE) {
- return E_INVALIDARG;
- }
- return NOERROR;
-}
-
-
-// This complements the SetWindowPosition to return the current window place
-// in device coordinates. As before the same information can be retrived by
-// calling the property get functions individually but this is atomic and is
-// therefore more suitable to a live environment rather than design time
-
-STDMETHODIMP
-CBaseControlWindow::GetWindowPosition(__out long *pLeft,__out long *pTop,__out long *pWidth,__out long *pHeight)
-{
- // Should check the pointers are not NULL
-
- CheckPointer(pLeft,E_POINTER);
- CheckPointer(pTop,E_POINTER);
- CheckPointer(pWidth,E_POINTER);
- CheckPointer(pHeight,E_POINTER);
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- RECT WindowRect;
-
- // Get the current window coordinates
-
- EXECUTE_ASSERT(GetWindowRect(m_hwnd,&WindowRect));
-
- // Convert the RECT into left,top,width and height values
-
- *pLeft = WindowRect.left;
- *pTop = WindowRect.top;
- *pWidth = WindowRect.right - WindowRect.left;
- *pHeight = WindowRect.bottom - WindowRect.top;
-
- return NOERROR;
-}
-
-
-// When a window is maximised or iconic calling GetWindowPosition will return
-// the current window position (likewise for the properties). However if the
-// restored size (ie the size we'll return to when normally shown) is needed
-// then this should be used. When in a normal position (neither iconic nor
-// maximised) then this returns the same coordinates as GetWindowPosition
-
-STDMETHODIMP
-CBaseControlWindow::GetRestorePosition(__out long *pLeft,__out long *pTop,__out long *pWidth,__out long *pHeight)
-{
- // Should check the pointers are not NULL
-
- CheckPointer(pLeft,E_POINTER);
- CheckPointer(pTop,E_POINTER);
- CheckPointer(pWidth,E_POINTER);
- CheckPointer(pHeight,E_POINTER);
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
-
- // Use GetWindowPlacement to find the restore position
-
- WINDOWPLACEMENT Place;
- Place.length = sizeof(WINDOWPLACEMENT);
- EXECUTE_ASSERT(GetWindowPlacement(m_hwnd,&Place));
-
- RECT WorkArea;
-
- // We must take into account any task bar present
-
- if (SystemParametersInfo(SPI_GETWORKAREA,0,&WorkArea,FALSE) == TRUE) {
- if (GetParent(m_hwnd) == NULL) {
- Place.rcNormalPosition.top += WorkArea.top;
- Place.rcNormalPosition.bottom += WorkArea.top;
- Place.rcNormalPosition.left += WorkArea.left;
- Place.rcNormalPosition.right += WorkArea.left;
- }
- }
-
- // Convert the RECT into left,top,width and height values
-
- *pLeft = Place.rcNormalPosition.left;
- *pTop = Place.rcNormalPosition.top;
- *pWidth = Place.rcNormalPosition.right - Place.rcNormalPosition.left;
- *pHeight = Place.rcNormalPosition.bottom - Place.rcNormalPosition.top;
-
- return NOERROR;
-}
-
-
-// Return the current border colour, if we are playing something to a subset
-// of the base window display there is an outside area exposed. The default
-// action is to paint this colour in the Windows background colour (defined
-// as value COLOR_WINDOW) We reset to this default when we're disconnected
-
-STDMETHODIMP CBaseControlWindow::get_BorderColor(__out long *Color)
-{
- CheckPointer(Color,E_POINTER);
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- *Color = (long) m_BorderColour;
- return NOERROR;
-}
-
-
-// This can be called to set the current border colour
-
-STDMETHODIMP CBaseControlWindow::put_BorderColor(long Color)
-{
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
-
- // Have the window repainted with the new border colour
-
- m_BorderColour = (COLORREF) Color;
- PaintWindow(TRUE);
- return NOERROR;
-}
-
-
-// Delegate fullscreen handling to plug in distributor
-
-STDMETHODIMP CBaseControlWindow::get_FullScreenMode(__out long *FullScreenMode)
-{
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- CheckPointer(FullScreenMode,E_POINTER);
- return E_NOTIMPL;
-}
-
-
-// Delegate fullscreen handling to plug in distributor
-
-STDMETHODIMP CBaseControlWindow::put_FullScreenMode(long FullScreenMode)
-{
- return E_NOTIMPL;
-}
-
-
-// This sets the auto show property, this property causes the base window to
-// be displayed whenever we change state. This allows an application to have
-// to do nothing to have the window appear but still allow them to change the
-// default behaviour if for example they want to keep it hidden for longer
-
-STDMETHODIMP CBaseControlWindow::put_AutoShow(long AutoShow)
-{
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
-
- // Check this is a valid automation boolean type
-
- if (AutoShow != OATRUE) {
- if (AutoShow != OAFALSE) {
- return E_INVALIDARG;
- }
- }
-
- m_bAutoShow = (AutoShow == OATRUE ? TRUE : FALSE);
- return NOERROR;
-}
-
-
-// This can be called to get the current auto show flag. The flag is updated
-// when we connect and disconnect and through this interface all of which are
-// controlled and serialised by means of the main renderer critical section
-
-STDMETHODIMP CBaseControlWindow::get_AutoShow(__out long *AutoShow)
-{
- CheckPointer(AutoShow,E_POINTER);
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- *AutoShow = (m_bAutoShow == TRUE ? OATRUE : OAFALSE);
- return NOERROR;
-}
-
-
-// Return the minimum ideal image size for the current video. This may differ
-// to the actual video dimensions because we may be using DirectDraw hardware
-// that has specific stretching requirements. For example the Cirrus Logic
-// cards have a minimum stretch factor depending on the overlay surface size
-
-STDMETHODIMP
-CBaseControlWindow::GetMinIdealImageSize(__out long *pWidth,__out long *pHeight)
-{
- CheckPointer(pWidth,E_POINTER);
- CheckPointer(pHeight,E_POINTER);
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- FILTER_STATE State;
-
- // Must not be stopped for this to work correctly
-
- m_pFilter->GetState(0,&State);
- if (State == State_Stopped) {
- return VFW_E_WRONG_STATE;
- }
-
- RECT DefaultRect = GetDefaultRect();
- *pWidth = WIDTH(&DefaultRect);
- *pHeight = HEIGHT(&DefaultRect);
- return NOERROR;
-}
-
-
-// Return the maximum ideal image size for the current video. This may differ
-// to the actual video dimensions because we may be using DirectDraw hardware
-// that has specific stretching requirements. For example the Cirrus Logic
-// cards have a maximum stretch factor depending on the overlay surface size
-
-STDMETHODIMP
-CBaseControlWindow::GetMaxIdealImageSize(__out long *pWidth,__out long *pHeight)
-{
- CheckPointer(pWidth,E_POINTER);
- CheckPointer(pHeight,E_POINTER);
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- FILTER_STATE State;
-
- // Must not be stopped for this to work correctly
-
- m_pFilter->GetState(0,&State);
- if (State == State_Stopped) {
- return VFW_E_WRONG_STATE;
- }
-
- RECT DefaultRect = GetDefaultRect();
- *pWidth = WIDTH(&DefaultRect);
- *pHeight = HEIGHT(&DefaultRect);
- return NOERROR;
-}
-
-
-// Allow an application to hide the cursor on our window
-
-STDMETHODIMP
-CBaseControlWindow::HideCursor(long HideCursor)
-{
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
-
- // Check this is a valid automation boolean type
-
- if (HideCursor != OATRUE) {
- if (HideCursor != OAFALSE) {
- return E_INVALIDARG;
- }
- }
-
- m_bCursorHidden = (HideCursor == OATRUE ? TRUE : FALSE);
- return NOERROR;
-}
-
-
-// Returns whether we have the cursor hidden or not
-
-STDMETHODIMP CBaseControlWindow::IsCursorHidden(__out long *CursorHidden)
-{
- CheckPointer(CursorHidden,E_POINTER);
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- *CursorHidden = (m_bCursorHidden == TRUE ? OATRUE : OAFALSE);
- return NOERROR;
-}
-
-
-// This class implements the IBasicVideo control functions (dual interface)
-// we support a large number of properties and methods designed to allow the
-// client (whether it be an automation controller or a C/C++ application) to
-// set and get a number of video related properties such as the native video
-// size. We support some methods that duplicate the properties but provide a
-// more direct and efficient mechanism as many values may be changed in one
-
-CBaseControlVideo::CBaseControlVideo(
- __inout CBaseFilter *pFilter, // Owning filter
- __in CCritSec *pInterfaceLock, // Locking object
- __in_opt LPCTSTR pName, // Object description
- __inout_opt LPUNKNOWN pUnk, // Normal COM ownership
- __inout HRESULT *phr) : // OLE return code
-
- CBaseBasicVideo(pName,pUnk),
- m_pFilter(pFilter),
- m_pInterfaceLock(pInterfaceLock),
- m_pPin(NULL)
-{
- ASSERT(m_pFilter);
- ASSERT(m_pInterfaceLock);
- ASSERT(phr);
-}
-
-// Return an approximate average time per frame
-
-STDMETHODIMP CBaseControlVideo::get_AvgTimePerFrame(__out REFTIME *pAvgTimePerFrame)
-{
- CheckPointer(pAvgTimePerFrame,E_POINTER);
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- CAutoLock cInterfaceLock(m_pInterfaceLock);
-
- VIDEOINFOHEADER *pVideoInfo = GetVideoFormat();
- if (pVideoInfo == NULL)
- return E_OUTOFMEMORY;
- COARefTime AvgTime(pVideoInfo->AvgTimePerFrame);
- *pAvgTimePerFrame = (REFTIME) AvgTime;
-
- return NOERROR;
-}
-
-
-// Return an approximate bit rate for the video
-
-STDMETHODIMP CBaseControlVideo::get_BitRate(__out long *pBitRate)
-{
- CheckPointer(pBitRate,E_POINTER);
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- CAutoLock cInterfaceLock(m_pInterfaceLock);
-
- VIDEOINFOHEADER *pVideoInfo = GetVideoFormat();
- if (pVideoInfo == NULL)
- return E_OUTOFMEMORY;
- *pBitRate = pVideoInfo->dwBitRate;
- return NOERROR;
-}
-
-
-// Return an approximate bit error rate
-
-STDMETHODIMP CBaseControlVideo::get_BitErrorRate(__out long *pBitErrorRate)
-{
- CheckPointer(pBitErrorRate,E_POINTER);
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- CAutoLock cInterfaceLock(m_pInterfaceLock);
-
- VIDEOINFOHEADER *pVideoInfo = GetVideoFormat();
- if (pVideoInfo == NULL)
- return E_OUTOFMEMORY;
- *pBitErrorRate = pVideoInfo->dwBitErrorRate;
- return NOERROR;
-}
-
-
-// This returns the current video width
-
-STDMETHODIMP CBaseControlVideo::get_VideoWidth(__out long *pVideoWidth)
-{
- CheckPointer(pVideoWidth,E_POINTER);
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- CAutoLock cInterfaceLock(m_pInterfaceLock);
-
- VIDEOINFOHEADER *pVideoInfo = GetVideoFormat();
- if (pVideoInfo == NULL)
- return E_OUTOFMEMORY;
- *pVideoWidth = pVideoInfo->bmiHeader.biWidth;
- return NOERROR;
-}
-
-
-// This returns the current video height
-
-STDMETHODIMP CBaseControlVideo::get_VideoHeight(__out long *pVideoHeight)
-{
- CheckPointer(pVideoHeight,E_POINTER);
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- CAutoLock cInterfaceLock(m_pInterfaceLock);
-
- VIDEOINFOHEADER *pVideoInfo = GetVideoFormat();
- if (pVideoInfo == NULL)
- return E_OUTOFMEMORY;
- *pVideoHeight = pVideoInfo->bmiHeader.biHeight;
- return NOERROR;
-}
-
-
-// This returns the current palette the video is using as an array allocated
-// by the user. To remain consistent we use PALETTEENTRY fields to return the
-// colours in rather than RGBQUADs that multimedia decided to use. The memory
-// is allocated by the user so we simple copy each in turn. We check that the
-// number of entries requested and the start position offset are both valid
-// If the number of entries evaluates to zero then we return an S_FALSE code
-
-STDMETHODIMP CBaseControlVideo::GetVideoPaletteEntries(long StartIndex,
- long Entries,
- __out long *pRetrieved,
- __out_ecount_part(Entries, *pRetrieved) long *pPalette)
-{
- CheckPointer(pRetrieved,E_POINTER);
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- CAutoLock cInterfaceLock(m_pInterfaceLock);
- CMediaType MediaType;
-
- // Get the video format from the derived class
-
- VIDEOINFOHEADER *pVideoInfo = GetVideoFormat();
- if (pVideoInfo == NULL)
- return E_OUTOFMEMORY;
- BITMAPINFOHEADER *pHeader = HEADER(pVideoInfo);
-
- // Is the current format palettised
-
- if (PALETTISED(pVideoInfo) == FALSE) {
- *pRetrieved = 0;
- return VFW_E_NO_PALETTE_AVAILABLE;
- }
-
- // Do they just want to know how many are available
-
- if (pPalette == NULL) {
- *pRetrieved = pHeader->biClrUsed;
- return NOERROR;
- }
-
- // Make sure the start position is a valid offset
-
- if (StartIndex >= (LONG) pHeader->biClrUsed || StartIndex < 0) {
- *pRetrieved = 0;
- return E_INVALIDARG;
- }
-
- // Correct the number we can retrieve
-
- LONG Available = (LONG) pHeader->biClrUsed - StartIndex;
- *pRetrieved = max(0,min(Available,Entries));
- if (*pRetrieved == 0) {
- return S_FALSE;
- }
-
- // Copy the palette entries to the output buffer
-
- PALETTEENTRY *pEntries = (PALETTEENTRY *) pPalette;
- RGBQUAD *pColours = COLORS(pVideoInfo) + StartIndex;
-
- for (LONG Count = 0;Count < *pRetrieved;Count++) {
- pEntries[Count].peRed = pColours[Count].rgbRed;
- pEntries[Count].peGreen = pColours[Count].rgbGreen;
- pEntries[Count].peBlue = pColours[Count].rgbBlue;
- pEntries[Count].peFlags = 0;
- }
- return NOERROR;
-}
-
-
-// This returns the current video dimensions as a method rather than a number
-// of individual property get calls. For the same reasons as said before we
-// cannot access the renderer media type directly as the window object thread
-// may be updating it since dynamic format changes may change these values
-
-STDMETHODIMP CBaseControlVideo::GetVideoSize(__out long *pWidth,__out long *pHeight)
-{
- CheckPointer(pWidth,E_POINTER);
- CheckPointer(pHeight,E_POINTER);
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- CAutoLock cInterfaceLock(m_pInterfaceLock);
-
- // Get the video format from the derived class
- VIDEOINFOHEADER *pVideoInfo = GetVideoFormat();
- if (pVideoInfo == NULL)
- return E_OUTOFMEMORY;
- *pWidth = pVideoInfo->bmiHeader.biWidth;
- *pHeight = pVideoInfo->bmiHeader.biHeight;
- return NOERROR;
-}
-
-
-// Set the source video rectangle as left,top,right and bottom coordinates
-// rather than left,top,width and height as per OLE automation interfaces
-// Then pass the rectangle on to the window object to set the source
-
-STDMETHODIMP
-CBaseControlVideo::SetSourcePosition(long Left,long Top,long Width,long Height)
-{
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- CAutoLock cInterfaceLock(m_pInterfaceLock);
- RECT SourceRect;
- SourceRect.left = Left;
- SourceRect.top = Top;
- SourceRect.right = Left + Width;
- SourceRect.bottom = Top + Height;
-
- // Check the source rectangle is valid
-
- HRESULT hr = CheckSourceRect(&SourceRect);
- if (FAILED(hr)) {
- return hr;
- }
-
- // Now set the source rectangle
-
- hr = SetSourceRect(&SourceRect);
- if (FAILED(hr)) {
- return hr;
- }
- return OnUpdateRectangles();
-}
-
-
-// Return the source rectangle in left,top,width and height rather than the
-// left,top,right and bottom values that RECT uses (and which the window
-// object returns through GetSourceRect) which requires a little work
-
-STDMETHODIMP
-CBaseControlVideo::GetSourcePosition(__out long *pLeft,__out long *pTop,__out long *pWidth,__out long *pHeight)
-{
- // Should check the pointers are non NULL
-
- CheckPointer(pLeft,E_POINTER);
- CheckPointer(pTop,E_POINTER);
- CheckPointer(pWidth,E_POINTER);
- CheckPointer(pHeight,E_POINTER);
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- RECT SourceRect;
-
- CAutoLock cInterfaceLock(m_pInterfaceLock);
- GetSourceRect(&SourceRect);
-
- *pLeft = SourceRect.left;
- *pTop = SourceRect.top;
- *pWidth = WIDTH(&SourceRect);
- *pHeight = HEIGHT(&SourceRect);
-
- return NOERROR;
-}
-
-
-// Set the video destination as left,top,right and bottom coordinates rather
-// than the left,top,width and height uses as per OLE automation interfaces
-// Then pass the rectangle on to the window object to set the destination
-
-STDMETHODIMP
-CBaseControlVideo::SetDestinationPosition(long Left,long Top,long Width,long Height)
-{
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- CAutoLock cInterfaceLock(m_pInterfaceLock);
- RECT DestinationRect;
-
- DestinationRect.left = Left;
- DestinationRect.top = Top;
- DestinationRect.right = Left + Width;
- DestinationRect.bottom = Top + Height;
-
- // Check the target rectangle is valid
-
- HRESULT hr = CheckTargetRect(&DestinationRect);
- if (FAILED(hr)) {
- return hr;
- }
-
- // Now set the new target rectangle
-
- hr = SetTargetRect(&DestinationRect);
- if (FAILED(hr)) {
- return hr;
- }
- return OnUpdateRectangles();
-}
-
-
-// Return the destination rectangle in left,top,width and height rather than
-// the left,top,right and bottom values that RECT uses (and which the window
-// object returns through GetDestinationRect) which requires a little work
-
-STDMETHODIMP
-CBaseControlVideo::GetDestinationPosition(__out long *pLeft,__out long *pTop,__out long *pWidth,__out long *pHeight)
-{
- // Should check the pointers are not NULL
-
- CheckPointer(pLeft,E_POINTER);
- CheckPointer(pTop,E_POINTER);
- CheckPointer(pWidth,E_POINTER);
- CheckPointer(pHeight,E_POINTER);
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- RECT DestinationRect;
-
- CAutoLock cInterfaceLock(m_pInterfaceLock);
- GetTargetRect(&DestinationRect);
-
- *pLeft = DestinationRect.left;
- *pTop = DestinationRect.top;
- *pWidth = WIDTH(&DestinationRect);
- *pHeight = HEIGHT(&DestinationRect);
-
- return NOERROR;
-}
-
-
-// Set the source left position, the source rectangle we get back from the
-// window object is a true rectangle in left,top,right and bottom positions
-// so all we have to do is to update the left position and pass it back. We
-// must keep the current width constant when we're updating this property
-
-STDMETHODIMP CBaseControlVideo::put_SourceLeft(long SourceLeft)
-{
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- CAutoLock cInterfaceLock(m_pInterfaceLock);
- RECT SourceRect;
- GetSourceRect(&SourceRect);
- SourceRect.right = SourceLeft + WIDTH(&SourceRect);
- SourceRect.left = SourceLeft;
-
- // Check the source rectangle is valid
-
- HRESULT hr = CheckSourceRect(&SourceRect);
- if (FAILED(hr)) {
- return hr;
- }
-
- // Now set the source rectangle
-
- hr = SetSourceRect(&SourceRect);
- if (FAILED(hr)) {
- return hr;
- }
- return OnUpdateRectangles();
-}
-
-
-// Return the current left source video position
-
-STDMETHODIMP CBaseControlVideo::get_SourceLeft(__out long *pSourceLeft)
-{
- CheckPointer(pSourceLeft,E_POINTER);
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- CAutoLock cInterfaceLock(m_pInterfaceLock);
- RECT SourceRect;
-
- GetSourceRect(&SourceRect);
- *pSourceLeft = SourceRect.left;
- return NOERROR;
-}
-
-
-// Set the source width, we get the current source rectangle and then update
-// the right position to be the left position (thereby keeping it constant)
-// plus the new source width we are passed in (it expands to the right)
-
-STDMETHODIMP CBaseControlVideo::put_SourceWidth(long SourceWidth)
-{
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- CAutoLock cInterfaceLock(m_pInterfaceLock);
- RECT SourceRect;
- GetSourceRect(&SourceRect);
- SourceRect.right = SourceRect.left + SourceWidth;
-
- // Check the source rectangle is valid
-
- HRESULT hr = CheckSourceRect(&SourceRect);
- if (FAILED(hr)) {
- return hr;
- }
-
- // Now set the source rectangle
-
- hr = SetSourceRect(&SourceRect);
- if (FAILED(hr)) {
- return hr;
- }
- return OnUpdateRectangles();
-}
-
-
-// Return the current source width
-
-STDMETHODIMP CBaseControlVideo::get_SourceWidth(__out long *pSourceWidth)
-{
- CheckPointer(pSourceWidth,E_POINTER);
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- CAutoLock cInterfaceLock(m_pInterfaceLock);
- RECT SourceRect;
-
- GetSourceRect(&SourceRect);
- *pSourceWidth = WIDTH(&SourceRect);
- return NOERROR;
-}
-
-
-// Set the source top position - changing this property does not affect the
-// current source height. So changing this shunts the source rectangle up and
-// down appropriately. Changing the height complements this functionality by
-// keeping the top position constant and simply changing the source height
-
-STDMETHODIMP CBaseControlVideo::put_SourceTop(long SourceTop)
-{
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- CAutoLock cInterfaceLock(m_pInterfaceLock);
- RECT SourceRect;
- GetSourceRect(&SourceRect);
- SourceRect.bottom = SourceTop + HEIGHT(&SourceRect);
- SourceRect.top = SourceTop;
-
- // Check the source rectangle is valid
-
- HRESULT hr = CheckSourceRect(&SourceRect);
- if (FAILED(hr)) {
- return hr;
- }
-
- // Now set the source rectangle
-
- hr = SetSourceRect(&SourceRect);
- if (FAILED(hr)) {
- return hr;
- }
- return OnUpdateRectangles();
-}
-
-
-// Return the current top position
-
-STDMETHODIMP CBaseControlVideo::get_SourceTop(__out long *pSourceTop)
-{
- CheckPointer(pSourceTop,E_POINTER);
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- CAutoLock cInterfaceLock(m_pInterfaceLock);
- RECT SourceRect;
-
- GetSourceRect(&SourceRect);
- *pSourceTop = SourceRect.top;
- return NOERROR;
-}
-
-
-// Set the source height
-
-STDMETHODIMP CBaseControlVideo::put_SourceHeight(long SourceHeight)
-{
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- CAutoLock cInterfaceLock(m_pInterfaceLock);
- RECT SourceRect;
- GetSourceRect(&SourceRect);
- SourceRect.bottom = SourceRect.top + SourceHeight;
-
- // Check the source rectangle is valid
-
- HRESULT hr = CheckSourceRect(&SourceRect);
- if (FAILED(hr)) {
- return hr;
- }
-
- // Now set the source rectangle
-
- hr = SetSourceRect(&SourceRect);
- if (FAILED(hr)) {
- return hr;
- }
- return OnUpdateRectangles();
-}
-
-
-// Return the current source height
-
-STDMETHODIMP CBaseControlVideo::get_SourceHeight(__out long *pSourceHeight)
-{
- CheckPointer(pSourceHeight,E_POINTER);
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- CAutoLock cInterfaceLock(m_pInterfaceLock);
- RECT SourceRect;
-
- GetSourceRect(&SourceRect);
- *pSourceHeight = HEIGHT(&SourceRect);
- return NOERROR;
-}
-
-
-// Set the target left position, the target rectangle we get back from the
-// window object is a true rectangle in left,top,right and bottom positions
-// so all we have to do is to update the left position and pass it back. We
-// must keep the current width constant when we're updating this property
-
-STDMETHODIMP CBaseControlVideo::put_DestinationLeft(long DestinationLeft)
-{
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- CAutoLock cInterfaceLock(m_pInterfaceLock);
- RECT DestinationRect;
- GetTargetRect(&DestinationRect);
- DestinationRect.right = DestinationLeft + WIDTH(&DestinationRect);
- DestinationRect.left = DestinationLeft;
-
- // Check the target rectangle is valid
-
- HRESULT hr = CheckTargetRect(&DestinationRect);
- if (FAILED(hr)) {
- return hr;
- }
-
- // Now set the new target rectangle
-
- hr = SetTargetRect(&DestinationRect);
- if (FAILED(hr)) {
- return hr;
- }
- return OnUpdateRectangles();
-}
-
-
-// Return the left position for the destination rectangle
-
-STDMETHODIMP CBaseControlVideo::get_DestinationLeft(__out long *pDestinationLeft)
-{
- CheckPointer(pDestinationLeft,E_POINTER);
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- CAutoLock cInterfaceLock(m_pInterfaceLock);
- RECT DestinationRect;
-
- GetTargetRect(&DestinationRect);
- *pDestinationLeft = DestinationRect.left;
- return NOERROR;
-}
-
-
-// Set the destination width
-
-STDMETHODIMP CBaseControlVideo::put_DestinationWidth(long DestinationWidth)
-{
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- CAutoLock cInterfaceLock(m_pInterfaceLock);
- RECT DestinationRect;
- GetTargetRect(&DestinationRect);
- DestinationRect.right = DestinationRect.left + DestinationWidth;
-
- // Check the target rectangle is valid
-
- HRESULT hr = CheckTargetRect(&DestinationRect);
- if (FAILED(hr)) {
- return hr;
- }
-
- // Now set the new target rectangle
-
- hr = SetTargetRect(&DestinationRect);
- if (FAILED(hr)) {
- return hr;
- }
- return OnUpdateRectangles();
-}
-
-
-// Return the width for the destination rectangle
-
-STDMETHODIMP CBaseControlVideo::get_DestinationWidth(__out long *pDestinationWidth)
-{
- CheckPointer(pDestinationWidth,E_POINTER);
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- CAutoLock cInterfaceLock(m_pInterfaceLock);
- RECT DestinationRect;
-
- GetTargetRect(&DestinationRect);
- *pDestinationWidth = WIDTH(&DestinationRect);
- return NOERROR;
-}
-
-
-// Set the target top position - changing this property does not affect the
-// current target height. So changing this shunts the target rectangle up and
-// down appropriately. Changing the height complements this functionality by
-// keeping the top position constant and simply changing the target height
-
-STDMETHODIMP CBaseControlVideo::put_DestinationTop(long DestinationTop)
-{
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- CAutoLock cInterfaceLock(m_pInterfaceLock);
- RECT DestinationRect;
- GetTargetRect(&DestinationRect);
- DestinationRect.bottom = DestinationTop + HEIGHT(&DestinationRect);
- DestinationRect.top = DestinationTop;
-
- // Check the target rectangle is valid
-
- HRESULT hr = CheckTargetRect(&DestinationRect);
- if (FAILED(hr)) {
- return hr;
- }
-
- // Now set the new target rectangle
-
- hr = SetTargetRect(&DestinationRect);
- if (FAILED(hr)) {
- return hr;
- }
- return OnUpdateRectangles();
-}
-
-
-// Return the top position for the destination rectangle
-
-STDMETHODIMP CBaseControlVideo::get_DestinationTop(__out long *pDestinationTop)
-{
- CheckPointer(pDestinationTop,E_POINTER);
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- CAutoLock cInterfaceLock(m_pInterfaceLock);
- RECT DestinationRect;
-
- GetTargetRect(&DestinationRect);
- *pDestinationTop = DestinationRect.top;
- return NOERROR;
-}
-
-
-// Set the destination height
-
-STDMETHODIMP CBaseControlVideo::put_DestinationHeight(long DestinationHeight)
-{
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- CAutoLock cInterfaceLock(m_pInterfaceLock);
- RECT DestinationRect;
- GetTargetRect(&DestinationRect);
- DestinationRect.bottom = DestinationRect.top + DestinationHeight;
-
- // Check the target rectangle is valid
-
- HRESULT hr = CheckTargetRect(&DestinationRect);
- if (FAILED(hr)) {
- return hr;
- }
-
- // Now set the new target rectangle
-
- hr = SetTargetRect(&DestinationRect);
- if (FAILED(hr)) {
- return hr;
- }
- return OnUpdateRectangles();
-}
-
-
-// Return the height for the destination rectangle
-
-STDMETHODIMP CBaseControlVideo::get_DestinationHeight(__out long *pDestinationHeight)
-{
- CheckPointer(pDestinationHeight,E_POINTER);
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- CAutoLock cInterfaceLock(m_pInterfaceLock);
- RECT DestinationRect;
-
- GetTargetRect(&DestinationRect);
- *pDestinationHeight = HEIGHT(&DestinationRect);
- return NOERROR;
-}
-
-
-// Reset the source rectangle to the full video dimensions
-
-STDMETHODIMP CBaseControlVideo::SetDefaultSourcePosition()
-{
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- CAutoLock cInterfaceLock(m_pInterfaceLock);
- HRESULT hr = SetDefaultSourceRect();
- if (FAILED(hr)) {
- return hr;
- }
- return OnUpdateRectangles();
-}
-
-
-// Return S_OK if we're using the default source otherwise S_FALSE
-
-STDMETHODIMP CBaseControlVideo::IsUsingDefaultSource()
-{
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- CAutoLock cInterfaceLock(m_pInterfaceLock);
- return IsDefaultSourceRect();
-}
-
-
-// Reset the video renderer to use the entire playback area
-
-STDMETHODIMP CBaseControlVideo::SetDefaultDestinationPosition()
-{
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- CAutoLock cInterfaceLock(m_pInterfaceLock);
- HRESULT hr = SetDefaultTargetRect();
- if (FAILED(hr)) {
- return hr;
- }
- return OnUpdateRectangles();
-}
-
-
-// Return S_OK if we're using the default target otherwise S_FALSE
-
-STDMETHODIMP CBaseControlVideo::IsUsingDefaultDestination()
-{
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- CAutoLock cInterfaceLock(m_pInterfaceLock);
- return IsDefaultTargetRect();
-}
-
-
-// Return a copy of the current image in the video renderer
-
-STDMETHODIMP
-CBaseControlVideo::GetCurrentImage(__inout long *pBufferSize,__out_bcount_part(*pBufferSize, *pBufferSize) long *pVideoImage)
-{
- CheckPointer(pBufferSize,E_POINTER);
- CheckConnected(m_pPin,VFW_E_NOT_CONNECTED);
- CAutoLock cInterfaceLock(m_pInterfaceLock);
- FILTER_STATE State;
-
- // Make sure we are in a paused state
-
- if (pVideoImage != NULL) {
- m_pFilter->GetState(0,&State);
- if (State != State_Paused) {
- return VFW_E_NOT_PAUSED;
- }
- return GetStaticImage(pBufferSize,pVideoImage);
- }
-
- // Just return the memory required
-
- VIDEOINFOHEADER *pVideoInfo = GetVideoFormat();
- if (pVideoInfo == NULL)
- return E_OUTOFMEMORY;
- RECT SourceRect;
- GetSourceRect(&SourceRect);
- return GetImageSize(pVideoInfo,pBufferSize,&SourceRect);
-}
-
-
-// An application has two ways of using GetCurrentImage, one is to pass a real
-// buffer which should be filled with the current image. The other is to pass
-// a NULL buffer pointer which is interpreted as asking us to return how much
-// memory is required for the image. The constraints for when the latter can
-// be called are much looser. To calculate the memory required we synthesize
-// a VIDEOINFO that takes into account the source rectangle that's being used
-
-HRESULT CBaseControlVideo::GetImageSize(__in VIDEOINFOHEADER *pVideoInfo,
- __out long *pBufferSize,
- __in RECT *pSourceRect)
-{
- NOTE("Entering GetImageSize");
- ASSERT(pSourceRect);
-
- // Check we have the correct input parameters
-
- if (pSourceRect == NULL ||
- pVideoInfo == NULL ||
- pBufferSize == NULL) {
-
- return E_UNEXPECTED;
- }
-
- // Is the data format compatible
-
- if (pVideoInfo->bmiHeader.biCompression != BI_RGB) {
- if (pVideoInfo->bmiHeader.biCompression != BI_BITFIELDS) {
- return E_INVALIDARG;
- }
- }
-
- ASSERT(IsRectEmpty(pSourceRect) == FALSE);
-
- BITMAPINFOHEADER bih;
- bih.biWidth = WIDTH(pSourceRect);
- bih.biHeight = HEIGHT(pSourceRect);
- bih.biBitCount = pVideoInfo->bmiHeader.biBitCount;
- LONG Size = DIBSIZE(bih);
- Size += GetBitmapFormatSize(HEADER(pVideoInfo)) - SIZE_PREHEADER;
- *pBufferSize = Size;
-
- return NOERROR;
-}
-
-
-// Given an IMediaSample containing a linear buffer with an image and a type
-// describing the bitmap make a rendering of the image into the output buffer
-// This may be called by derived classes who render typical video images to
-// handle the IBasicVideo GetCurrentImage method. The pVideoImage pointer may
-// be NULL when passed to GetCurrentImage in which case GetImageSize will be
-// called instead, which will just do the calculation of the memory required
-
-HRESULT CBaseControlVideo::CopyImage(IMediaSample *pMediaSample,
- __in VIDEOINFOHEADER *pVideoInfo,
- __inout long *pBufferSize,
- __out_bcount_part(*pBufferSize, *pBufferSize) BYTE *pVideoImage,
- __in RECT *pSourceRect)
-{
- NOTE("Entering CopyImage");
- ASSERT(pSourceRect);
- BYTE *pCurrentImage;
-
- // Check we have an image to copy
-
- if (pMediaSample == NULL || pSourceRect == NULL ||
- pVideoInfo == NULL || pVideoImage == NULL ||
- pBufferSize == NULL) {
-
- return E_UNEXPECTED;
- }
-
- // Is the data format compatible
-
- if (pVideoInfo->bmiHeader.biCompression != BI_RGB) {
- if (pVideoInfo->bmiHeader.biCompression != BI_BITFIELDS) {
- return E_INVALIDARG;
- }
- }
-
- if (*pBufferSize < 0) {
- return E_INVALIDARG;
- }
-
- // Arbitrarily large size to prevent integer overflow problems
- if (pVideoInfo->bmiHeader.biSize > 4096)
- {
- return E_INVALIDARG;
- }
-
- ASSERT(IsRectEmpty(pSourceRect) == FALSE);
-
- BITMAPINFOHEADER bih;
- bih.biWidth = WIDTH(pSourceRect);
- bih.biHeight = HEIGHT(pSourceRect);
- bih.biBitCount = pVideoInfo->bmiHeader.biBitCount;
- DWORD Size = GetBitmapFormatSize(HEADER(pVideoInfo)) - SIZE_PREHEADER;
- DWORD Total;
- DWORD dwDibSize;
-
- if( !ValidateBitmapInfoHeader( HEADER(pVideoInfo), Size)) {
- return E_INVALIDARG;
- }
-
- // ValidateBitmapInfoHeader checks this but for some reason code scanning
- // tools aren't picking up the annotation
- __analysis_assume(Size >= sizeof(BITMAPINFOHEADER));
-
- if (FAILED(SAFE_DIBSIZE(&bih, &dwDibSize))) {
- return E_INVALIDARG;
- }
-
- if (FAILED(DWordAdd(Size, dwDibSize, &Total))) {
- return E_INVALIDARG;
- }
-
- // Make sure we have a large enough buffer
-
- if ((DWORD)*pBufferSize < Total) {
- return E_OUTOFMEMORY;
- }
-
- // Copy the BITMAPINFO
-
- CopyMemory((PVOID)pVideoImage, (PVOID)&pVideoInfo->bmiHeader, Size);
- ((BITMAPINFOHEADER *)pVideoImage)->biWidth = WIDTH(pSourceRect);
- ((BITMAPINFOHEADER *)pVideoImage)->biHeight = HEIGHT(pSourceRect);
- ((BITMAPINFOHEADER *)pVideoImage)->biSizeImage = DIBSIZE(bih);
- BYTE *pImageData = pVideoImage + Size;
-
- // Get the pointer to it's image data
-
- HRESULT hr = pMediaSample->GetPointer(&pCurrentImage);
- if (FAILED(hr)) {
- return hr;
- }
-
- // Now we are ready to start copying the source scan lines
-
- LONG ScanLine = (pVideoInfo->bmiHeader.biBitCount / 8) * WIDTH(pSourceRect);
- LONG LinesToSkip = pVideoInfo->bmiHeader.biHeight;
- LinesToSkip -= pSourceRect->top + HEIGHT(pSourceRect);
- pCurrentImage += LinesToSkip * DIBWIDTHBYTES(pVideoInfo->bmiHeader);
- pCurrentImage += pSourceRect->left * (pVideoInfo->bmiHeader.biBitCount / 8);
-
- // Even money on this GP faulting sometime...
-
- for (LONG Line = 0;Line < HEIGHT(pSourceRect);Line++) {
- CopyMemory((PVOID)pImageData, (PVOID)pCurrentImage, ScanLine);
- pImageData += DIBWIDTHBYTES(*(BITMAPINFOHEADER *)pVideoImage);
- pCurrentImage += DIBWIDTHBYTES(pVideoInfo->bmiHeader);
- }
- return NOERROR;
-}
-
-
-// Called when we change media types either during connection or dynamically
-// We inform the filter graph and therefore the application that the video
-// size may have changed, we don't bother looking to see if it really has as
-// we leave that to the application - the dimensions are the event parameters
-
-HRESULT CBaseControlVideo::OnVideoSizeChange()
-{
- // Get the video format from the derived class
-
- VIDEOINFOHEADER *pVideoInfo = GetVideoFormat();
- if (pVideoInfo == NULL)
- return E_OUTOFMEMORY;
- WORD Width = (WORD) pVideoInfo->bmiHeader.biWidth;
- WORD Height = (WORD) pVideoInfo->bmiHeader.biHeight;
-
- return m_pFilter->NotifyEvent(EC_VIDEO_SIZE_CHANGED,
- MAKELPARAM(Width,Height),
- MAKEWPARAM(0,0));
-}
-
-
-// Set the video source rectangle. We must check the source rectangle against
-// the actual video dimensions otherwise when we come to draw the pictures we
-// get access violations as GDI tries to touch data outside of the image data
-// Although we store the rectangle in left, top, right and bottom coordinates
-// instead of left, top, width and height as OLE uses we do take into account
-// that the rectangle is used up to, but not including, the right column and
-// bottom row of pixels, see the Win32 documentation on RECT for more details
-
-HRESULT CBaseControlVideo::CheckSourceRect(__in RECT *pSourceRect)
-{
- CheckPointer(pSourceRect,E_POINTER);
- LONG Width,Height;
- GetVideoSize(&Width,&Height);
-
- // Check the coordinates are greater than zero
- // and that the rectangle is valid (left<right, top<bottom)
-
- if ((pSourceRect->left >= pSourceRect->right) ||
- (pSourceRect->left < 0) ||
- (pSourceRect->top >= pSourceRect->bottom) ||
- (pSourceRect->top < 0)) {
-
- return E_INVALIDARG;
- }
-
- // Check the coordinates are less than the extents
-
- if ((pSourceRect->right > Width) ||
- (pSourceRect->bottom > Height)) {
-
- return E_INVALIDARG;
- }
- return NOERROR;
-}
-
-
-// Check the target rectangle has some valid coordinates, which amounts to
-// little more than checking the destination rectangle isn't empty. Derived
-// classes may call this when they have their SetTargetRect method called to
-// check the rectangle validity, we do not update the rectangles passed in
-// Although we store the rectangle in left, top, right and bottom coordinates
-// instead of left, top, width and height as OLE uses we do take into account
-// that the rectangle is used up to, but not including, the right column and
-// bottom row of pixels, see the Win32 documentation on RECT for more details
-
-HRESULT CBaseControlVideo::CheckTargetRect(__in RECT *pTargetRect)
-{
- // Check the pointer is valid
-
- if (pTargetRect == NULL) {
- return E_POINTER;
- }
-
- // These overflow the WIDTH and HEIGHT checks
-
- if (pTargetRect->left > pTargetRect->right ||
- pTargetRect->top > pTargetRect->bottom) {
- return E_INVALIDARG;
- }
-
- // Check the rectangle has valid coordinates
-
- if (WIDTH(pTargetRect) <= 0 || HEIGHT(pTargetRect) <= 0) {
- return E_INVALIDARG;
- }
-
- ASSERT(IsRectEmpty(pTargetRect) == FALSE);
- return NOERROR;
-}
-
diff --git a/dll/src/baseclasses/winctrl.h b/dll/src/baseclasses/winctrl.h
deleted file mode 100644
index 1080a47..0000000
--- a/dll/src/baseclasses/winctrl.h
+++ /dev/null
@@ -1,224 +0,0 @@
-//------------------------------------------------------------------------------
-// File: WinCtrl.h
-//
-// Desc: DirectShow base classes - defines classes for video control
-// interfaces.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-#ifndef __WINCTRL__
-#define __WINCTRL__
-
-#define ABSOL(x) (x < 0 ? -x : x)
-#define NEGAT(x) (x > 0 ? -x : x)
-
-// Helper
-BOOL WINAPI PossiblyEatMessage(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
-
-class CBaseControlWindow : public CBaseVideoWindow, public CBaseWindow
-{
-protected:
-
- CBaseFilter *m_pFilter; // Pointer to owning media filter
- CBasePin *m_pPin; // Controls media types for connection
- CCritSec *m_pInterfaceLock; // Externally defined critical section
- COLORREF m_BorderColour; // Current window border colour
- BOOL m_bAutoShow; // What happens when the state changes
- HWND m_hwndOwner; // Owner window that we optionally have
- HWND m_hwndDrain; // HWND to post any messages received
- BOOL m_bCursorHidden; // Should we hide the window cursor
-
-public:
-
- // Internal methods for other objects to get information out
-
- HRESULT DoSetWindowStyle(long Style,long WindowLong);
- HRESULT DoGetWindowStyle(__out long *pStyle,long WindowLong);
- BOOL IsAutoShowEnabled() { return m_bAutoShow; };
- COLORREF GetBorderColour() { return m_BorderColour; };
- HWND GetOwnerWindow() { return m_hwndOwner; };
- BOOL IsCursorHidden() { return m_bCursorHidden; };
-
- inline BOOL PossiblyEatMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
- {
- return ::PossiblyEatMessage(m_hwndDrain, uMsg, wParam, lParam);
- }
-
- // Derived classes must call this to set the pin the filter is using
- // We don't have the pin passed in to the constructor (as we do with
- // the CBaseFilter object) because filters typically create the
- // pins dynamically when requested in CBaseFilter::GetPin. This can
- // not be called from our constructor because is is a virtual method
-
- void SetControlWindowPin(CBasePin *pPin) {
- m_pPin = pPin;
- }
-
-public:
-
- CBaseControlWindow(__inout CBaseFilter *pFilter, // Owning media filter
- __in CCritSec *pInterfaceLock, // Locking object
- __in_opt LPCTSTR pName, // Object description
- __inout_opt LPUNKNOWN pUnk, // Normal COM ownership
- __inout HRESULT *phr); // OLE return code
-
- // These are the properties we support
-
- STDMETHODIMP put_Caption(__in BSTR strCaption);
- STDMETHODIMP get_Caption(__out BSTR *pstrCaption);
- STDMETHODIMP put_AutoShow(long AutoShow);
- STDMETHODIMP get_AutoShow(__out long *AutoShow);
- STDMETHODIMP put_WindowStyle(long WindowStyle);
- STDMETHODIMP get_WindowStyle(__out long *pWindowStyle);
- STDMETHODIMP put_WindowStyleEx(long WindowStyleEx);
- STDMETHODIMP get_WindowStyleEx(__out long *pWindowStyleEx);
- STDMETHODIMP put_WindowState(long WindowState);
- STDMETHODIMP get_WindowState(__out long *pWindowState);
- STDMETHODIMP put_BackgroundPalette(long BackgroundPalette);
- STDMETHODIMP get_BackgroundPalette(__out long *pBackgroundPalette);
- STDMETHODIMP put_Visible(long Visible);
- STDMETHODIMP get_Visible(__out long *pVisible);
- STDMETHODIMP put_Left(long Left);
- STDMETHODIMP get_Left(__out long *pLeft);
- STDMETHODIMP put_Width(long Width);
- STDMETHODIMP get_Width(__out long *pWidth);
- STDMETHODIMP put_Top(long Top);
- STDMETHODIMP get_Top(__out long *pTop);
- STDMETHODIMP put_Height(long Height);
- STDMETHODIMP get_Height(__out long *pHeight);
- STDMETHODIMP put_Owner(OAHWND Owner);
- STDMETHODIMP get_Owner(__out OAHWND *Owner);
- STDMETHODIMP put_MessageDrain(OAHWND Drain);
- STDMETHODIMP get_MessageDrain(__out OAHWND *Drain);
- STDMETHODIMP get_BorderColor(__out long *Color);
- STDMETHODIMP put_BorderColor(long Color);
- STDMETHODIMP get_FullScreenMode(__out long *FullScreenMode);
- STDMETHODIMP put_FullScreenMode(long FullScreenMode);
-
- // And these are the methods
-
- STDMETHODIMP SetWindowForeground(long Focus);
- STDMETHODIMP NotifyOwnerMessage(OAHWND hwnd,long uMsg,LONG_PTR wParam,LONG_PTR lParam);
- STDMETHODIMP GetMinIdealImageSize(__out long *pWidth,__out long *pHeight);
- STDMETHODIMP GetMaxIdealImageSize(__out long *pWidth,__out long *pHeight);
- STDMETHODIMP SetWindowPosition(long Left,long Top,long Width,long Height);
- STDMETHODIMP GetWindowPosition(__out long *pLeft,__out long *pTop,__out long *pWidth,__out long *pHeight);
- STDMETHODIMP GetRestorePosition(__out long *pLeft,__out long *pTop,__out long *pWidth,__out long *pHeight);
- STDMETHODIMP HideCursor(long HideCursor);
- STDMETHODIMP IsCursorHidden(__out long *CursorHidden);
-};
-
-// This class implements the IBasicVideo interface
-
-class CBaseControlVideo : public CBaseBasicVideo
-{
-protected:
-
- CBaseFilter *m_pFilter; // Pointer to owning media filter
- CBasePin *m_pPin; // Controls media types for connection
- CCritSec *m_pInterfaceLock; // Externally defined critical section
-
-public:
-
- // Derived classes must provide these for the implementation
-
- virtual HRESULT IsDefaultTargetRect() PURE;
- virtual HRESULT SetDefaultTargetRect() PURE;
- virtual HRESULT SetTargetRect(RECT *pTargetRect) PURE;
- virtual HRESULT GetTargetRect(RECT *pTargetRect) PURE;
- virtual HRESULT IsDefaultSourceRect() PURE;
- virtual HRESULT SetDefaultSourceRect() PURE;
- virtual HRESULT SetSourceRect(RECT *pSourceRect) PURE;
- virtual HRESULT GetSourceRect(RECT *pSourceRect) PURE;
- virtual HRESULT GetStaticImage(__inout long *pBufferSize,__out_bcount_part(*pBufferSize, *pBufferSize) long *pDIBImage) PURE;
-
- // Derived classes must override this to return a VIDEOINFO representing
- // the video format. We cannot call IPin ConnectionMediaType to get this
- // format because various filters dynamically change the type when using
- // DirectDraw such that the format shows the position of the logical
- // bitmap in a frame buffer surface, so the size might be returned as
- // 1024x768 pixels instead of 320x240 which is the real video dimensions
-
- __out virtual VIDEOINFOHEADER *GetVideoFormat() PURE;
-
- // Helper functions for creating memory renderings of a DIB image
-
- HRESULT GetImageSize(__in VIDEOINFOHEADER *pVideoInfo,
- __out LONG *pBufferSize,
- __in RECT *pSourceRect);
-
- HRESULT CopyImage(IMediaSample *pMediaSample,
- __in VIDEOINFOHEADER *pVideoInfo,
- __inout LONG *pBufferSize,
- __out_bcount_part(*pBufferSize, *pBufferSize) BYTE *pVideoImage,
- __in RECT *pSourceRect);
-
- // Override this if you want notifying when the rectangles change
- virtual HRESULT OnUpdateRectangles() { return NOERROR; };
- virtual HRESULT OnVideoSizeChange();
-
- // Derived classes must call this to set the pin the filter is using
- // We don't have the pin passed in to the constructor (as we do with
- // the CBaseFilter object) because filters typically create the
- // pins dynamically when requested in CBaseFilter::GetPin. This can
- // not be called from our constructor because is is a virtual method
-
- void SetControlVideoPin(__inout CBasePin *pPin) {
- m_pPin = pPin;
- }
-
- // Helper methods for checking rectangles
- virtual HRESULT CheckSourceRect(__in RECT *pSourceRect);
- virtual HRESULT CheckTargetRect(__in RECT *pTargetRect);
-
-public:
-
- CBaseControlVideo(__inout CBaseFilter *pFilter, // Owning media filter
- __in CCritSec *pInterfaceLock, // Serialise interface
- __in_opt LPCTSTR pName, // Object description
- __inout_opt LPUNKNOWN pUnk, // Normal COM ownership
- __inout HRESULT *phr); // OLE return code
-
- // These are the properties we support
-
- STDMETHODIMP get_AvgTimePerFrame(__out REFTIME *pAvgTimePerFrame);
- STDMETHODIMP get_BitRate(__out long *pBitRate);
- STDMETHODIMP get_BitErrorRate(__out long *pBitErrorRate);
- STDMETHODIMP get_VideoWidth(__out long *pVideoWidth);
- STDMETHODIMP get_VideoHeight(__out long *pVideoHeight);
- STDMETHODIMP put_SourceLeft(long SourceLeft);
- STDMETHODIMP get_SourceLeft(__out long *pSourceLeft);
- STDMETHODIMP put_SourceWidth(long SourceWidth);
- STDMETHODIMP get_SourceWidth(__out long *pSourceWidth);
- STDMETHODIMP put_SourceTop(long SourceTop);
- STDMETHODIMP get_SourceTop(__out long *pSourceTop);
- STDMETHODIMP put_SourceHeight(long SourceHeight);
- STDMETHODIMP get_SourceHeight(__out long *pSourceHeight);
- STDMETHODIMP put_DestinationLeft(long DestinationLeft);
- STDMETHODIMP get_DestinationLeft(__out long *pDestinationLeft);
- STDMETHODIMP put_DestinationWidth(long DestinationWidth);
- STDMETHODIMP get_DestinationWidth(__out long *pDestinationWidth);
- STDMETHODIMP put_DestinationTop(long DestinationTop);
- STDMETHODIMP get_DestinationTop(__out long *pDestinationTop);
- STDMETHODIMP put_DestinationHeight(long DestinationHeight);
- STDMETHODIMP get_DestinationHeight(__out long *pDestinationHeight);
-
- // And these are the methods
-
- STDMETHODIMP GetVideoSize(__out long *pWidth,__out long *pHeight);
- STDMETHODIMP SetSourcePosition(long Left,long Top,long Width,long Height);
- STDMETHODIMP GetSourcePosition(__out long *pLeft,__out long *pTop,__out long *pWidth,__out long *pHeight);
- STDMETHODIMP GetVideoPaletteEntries(long StartIndex,long Entries,__out long *pRetrieved,__out_ecount_part(Entries, *pRetrieved) long *pPalette);
- STDMETHODIMP SetDefaultSourcePosition();
- STDMETHODIMP IsUsingDefaultSource();
- STDMETHODIMP SetDestinationPosition(long Left,long Top,long Width,long Height);
- STDMETHODIMP GetDestinationPosition(__out long *pLeft,__out long *pTop,__out long *pWidth,__out long *pHeight);
- STDMETHODIMP SetDefaultDestinationPosition();
- STDMETHODIMP IsUsingDefaultDestination();
- STDMETHODIMP GetCurrentImage(__inout long *pBufferSize,__out_bcount_part(*pBufferSize, *pBufferSize) long *pVideoImage);
-};
-
-#endif // __WINCTRL__
-
diff --git a/dll/src/baseclasses/winutil.cpp b/dll/src/baseclasses/winutil.cpp
deleted file mode 100644
index 6653f45..0000000
--- a/dll/src/baseclasses/winutil.cpp
+++ /dev/null
@@ -1,2746 +0,0 @@
-//------------------------------------------------------------------------------
-// File: WinUtil.cpp
-//
-// Desc: DirectShow base classes - implements generic window handler class.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-#include <streams.h>
-#include <limits.h>
-#include <dvdmedia.h>
-#include <strsafe.h>
-#include <checkbmi.h>
-
-static UINT MsgDestroy;
-
-// Constructor
-
-CBaseWindow::CBaseWindow(BOOL bDoGetDC, bool bDoPostToDestroy) :
- m_hInstance(g_hInst),
- m_hwnd(NULL),
- m_hdc(NULL),
- m_bActivated(FALSE),
- m_pClassName(NULL),
- m_ClassStyles(0),
- m_WindowStyles(0),
- m_WindowStylesEx(0),
- m_ShowStageMessage(0),
- m_ShowStageTop(0),
- m_MemoryDC(NULL),
- m_hPalette(NULL),
- m_bBackground(FALSE),
-#ifdef DEBUG
- m_bRealizing(FALSE),
-#endif
- m_bNoRealize(FALSE),
- m_bDoPostToDestroy(bDoPostToDestroy)
-{
- m_bDoGetDC = bDoGetDC;
-}
-
-
-// Prepare a window by spinning off a worker thread to do the creation and
-// also poll the message input queue. We leave this to be called by derived
-// classes because they might want to override methods like MessageLoop and
-// InitialiseWindow, if we do this during construction they'll ALWAYS call
-// this base class methods. We make the worker thread create the window so
-// it owns it rather than the filter graph thread which is constructing us
-
-HRESULT CBaseWindow::PrepareWindow()
-{
- if (m_hwnd) return NOERROR;
- ASSERT(m_hwnd == NULL);
- ASSERT(m_hdc == NULL);
-
- // Get the derived object's window and class styles
-
- m_pClassName = GetClassWindowStyles(&m_ClassStyles,
- &m_WindowStyles,
- &m_WindowStylesEx);
- if (m_pClassName == NULL) {
- return E_FAIL;
- }
-
- // Register our special private messages
- m_ShowStageMessage = RegisterWindowMessage(SHOWSTAGE);
-
- // RegisterWindowMessage() returns 0 if an error occurs.
- if (0 == m_ShowStageMessage) {
- return AmGetLastErrorToHResult();
- }
-
- m_ShowStageTop = RegisterWindowMessage(SHOWSTAGETOP);
- if (0 == m_ShowStageTop) {
- return AmGetLastErrorToHResult();
- }
-
- m_RealizePalette = RegisterWindowMessage(REALIZEPALETTE);
- if (0 == m_RealizePalette) {
- return AmGetLastErrorToHResult();
- }
-
- MsgDestroy = RegisterWindowMessage(TEXT("AM_DESTROY"));
- if (0 == MsgDestroy) {
- return AmGetLastErrorToHResult();
- }
-
- return DoCreateWindow();
-}
-
-
-// Destructor just a placeholder so that we know it becomes virtual
-// Derived classes MUST call DoneWithWindow in their destructors so
-// that no messages arrive after the derived class constructor ends
-
-#ifdef DEBUG
-CBaseWindow::~CBaseWindow()
-{
- ASSERT(m_hwnd == NULL);
- ASSERT(m_hdc == NULL);
-}
-#endif
-
-
-// We use the sync worker event to have the window destroyed. All we do is
-// signal the event and wait on the window thread handle. Trying to send it
-// messages causes too many problems, furthermore to be on the safe side we
-// just wait on the thread handle while it returns WAIT_TIMEOUT or there is
-// a sent message to process on this thread. If the constructor failed to
-// create the thread in the first place then the loop will get terminated
-
-HRESULT CBaseWindow::DoneWithWindow()
-{
- if (!IsWindow(m_hwnd) || (GetWindowThreadProcessId(m_hwnd, NULL) != GetCurrentThreadId())) {
-
- if (IsWindow(m_hwnd)) {
-
- // This code should only be executed if the window exists and if the window's
- // messages are processed on a different thread.
- ASSERT(GetWindowThreadProcessId(m_hwnd, NULL) != GetCurrentThreadId());
-
- if (m_bDoPostToDestroy) {
-
- HRESULT hr = S_OK;
- CAMEvent m_evDone(FALSE, &hr);
- if (FAILED(hr)) {
- return hr;
- }
-
- // We must post a message to destroy the window
- // That way we can't be in the middle of processing a
- // message posted to our window when we do go away
- // Sending a message gives less synchronization.
- PostMessage(m_hwnd, MsgDestroy, (WPARAM)(HANDLE)m_evDone, 0);
- WaitDispatchingMessages(m_evDone, INFINITE);
- } else {
- SendMessage(m_hwnd, MsgDestroy, 0, 0);
- }
- }
-
- //
- // This is not a leak, the window manager automatically free's
- // hdc's that were got via GetDC, which is the case here.
- // We set it to NULL so that we don't get any asserts later.
- //
- m_hdc = NULL;
-
- //
- // We need to free this DC though because USER32 does not know
- // anything about it.
- //
- if (m_MemoryDC)
- {
- EXECUTE_ASSERT(DeleteDC(m_MemoryDC));
- m_MemoryDC = NULL;
- }
-
- // Reset the window variables
- m_hwnd = NULL;
-
- return NOERROR;
- }
- const HWND hwnd = m_hwnd;
- if (hwnd == NULL) {
- return NOERROR;
- }
-
- InactivateWindow();
- NOTE("Inactivated");
-
- // Reset the window styles before destruction
-
- SetWindowLong(hwnd,GWL_STYLE,m_WindowStyles);
- ASSERT(GetParent(hwnd) == NULL);
- NOTE1("Reset window styles %d",m_WindowStyles);
-
- // UnintialiseWindow sets m_hwnd to NULL so save a copy
- UninitialiseWindow();
- DbgLog((LOG_TRACE, 2, TEXT("Destroying 0x%8.8X"), hwnd));
- if (!DestroyWindow(hwnd)) {
- DbgLog((LOG_TRACE, 0, TEXT("DestroyWindow %8.8X failed code %d"),
- hwnd, GetLastError()));
- DbgBreak("");
- }
-
- // Reset our state so we can be prepared again
-
- m_pClassName = NULL;
- m_ClassStyles = 0;
- m_WindowStyles = 0;
- m_WindowStylesEx = 0;
- m_ShowStageMessage = 0;
- m_ShowStageTop = 0;
-
- return NOERROR;
-}
-
-
-// Called at the end to put the window in an inactive state. The pending list
-// will always have been cleared by this time so event if the worker thread
-// gets has been signaled and gets in to render something it will find both
-// the state has been changed and that there are no available sample images
-// Since we wait on the window thread to complete we don't lock the object
-
-HRESULT CBaseWindow::InactivateWindow()
-{
- // Has the window been activated
- if (m_bActivated == FALSE) {
- return S_FALSE;
- }
-
- m_bActivated = FALSE;
- ShowWindow(m_hwnd,SW_HIDE);
- return NOERROR;
-}
-
-
-HRESULT CBaseWindow::CompleteConnect()
-{
- m_bActivated = FALSE;
- return NOERROR;
-}
-
-// This displays a normal window. We ask the base window class for default
-// sizes which unless overriden will return DEFWIDTH and DEFHEIGHT. We go
-// through a couple of extra hoops to get the client area the right size
-// as the object specifies which accounts for the AdjustWindowRectEx calls
-// We also DWORD align the left and top coordinates of the window here to
-// maximise the chance of being able to use DCI/DirectDraw primary surface
-
-HRESULT CBaseWindow::ActivateWindow()
-{
- // Has the window been sized and positioned already
-
- if (m_bActivated == TRUE || GetParent(m_hwnd) != NULL) {
-
- SetWindowPos(m_hwnd, // Our window handle
- HWND_TOP, // Put it at the top
- 0, 0, 0, 0, // Leave in current position
- SWP_NOMOVE | // Don't change it's place
- SWP_NOSIZE); // Change Z-order only
-
- m_bActivated = TRUE;
- return S_FALSE;
- }
-
- // Calculate the desired client rectangle
-
- RECT WindowRect, ClientRect = GetDefaultRect();
- GetWindowRect(m_hwnd,&WindowRect);
- AdjustWindowRectEx(&ClientRect,GetWindowLong(m_hwnd,GWL_STYLE),
- FALSE,GetWindowLong(m_hwnd,GWL_EXSTYLE));
-
- // Align left and top edges on DWORD boundaries
-
- UINT WindowFlags = (SWP_NOACTIVATE | SWP_FRAMECHANGED);
- WindowRect.left -= (WindowRect.left & 3);
- WindowRect.top -= (WindowRect.top & 3);
-
- SetWindowPos(m_hwnd, // Window handle
- HWND_TOP, // Put it at the top
- WindowRect.left, // Align left edge
- WindowRect.top, // And also top place
- WIDTH(&ClientRect), // Horizontal size
- HEIGHT(&ClientRect), // Vertical size
- WindowFlags); // Don't show window
-
- m_bActivated = TRUE;
- return NOERROR;
-}
-
-
-// This can be used to DWORD align the window for maximum performance
-
-HRESULT CBaseWindow::PerformanceAlignWindow()
-{
- RECT ClientRect,WindowRect;
- GetWindowRect(m_hwnd,&WindowRect);
- ASSERT(m_bActivated == TRUE);
-
- // Don't do this if we're owned
-
- if (GetParent(m_hwnd)) {
- return NOERROR;
- }
-
- // Align left and top edges on DWORD boundaries
-
- GetClientRect(m_hwnd, &ClientRect);
- MapWindowPoints(m_hwnd, HWND_DESKTOP, (LPPOINT) &ClientRect, 2);
- WindowRect.left -= (ClientRect.left & 3);
- WindowRect.top -= (ClientRect.top & 3);
- UINT WindowFlags = (SWP_NOACTIVATE | SWP_NOSIZE);
-
- SetWindowPos(m_hwnd, // Window handle
- HWND_TOP, // Put it at the top
- WindowRect.left, // Align left edge
- WindowRect.top, // And also top place
- (int) 0,(int) 0, // Ignore these sizes
- WindowFlags); // Don't show window
-
- return NOERROR;
-}
-
-
-// Install a palette into the base window - we may be called by a different
-// thread to the one that owns the window. We have to be careful how we do
-// the palette realisation as we could be a different thread to the window
-// which would cause an inter thread send message. Therefore we realise the
-// palette by sending it a special message but without the window locked
-
-HRESULT CBaseWindow::SetPalette(HPALETTE hPalette)
-{
- // We must own the window lock during the change
- {
- CAutoLock cWindowLock(&m_WindowLock);
- CAutoLock cPaletteLock(&m_PaletteLock);
- ASSERT(hPalette);
- m_hPalette = hPalette;
- }
- return SetPalette();
-}
-
-
-HRESULT CBaseWindow::SetPalette()
-{
- if (!m_bNoRealize) {
- SendMessage(m_hwnd, m_RealizePalette, 0, 0);
- return S_OK;
- } else {
- // Just select the palette
- ASSERT(m_hdc);
- ASSERT(m_MemoryDC);
-
- CAutoLock cPaletteLock(&m_PaletteLock);
- SelectPalette(m_hdc,m_hPalette,m_bBackground);
- SelectPalette(m_MemoryDC,m_hPalette,m_bBackground);
-
- return S_OK;
- }
-}
-
-
-void CBaseWindow::UnsetPalette()
-{
- CAutoLock cWindowLock(&m_WindowLock);
- CAutoLock cPaletteLock(&m_PaletteLock);
-
- // Get a standard VGA colour palette
-
- HPALETTE hPalette = (HPALETTE) GetStockObject(DEFAULT_PALETTE);
- ASSERT(hPalette);
-
- SelectPalette(GetWindowHDC(), hPalette, TRUE);
- SelectPalette(GetMemoryHDC(), hPalette, TRUE);
-
- m_hPalette = NULL;
-}
-
-
-void CBaseWindow::LockPaletteLock()
-{
- m_PaletteLock.Lock();
-}
-
-
-void CBaseWindow::UnlockPaletteLock()
-{
- m_PaletteLock.Unlock();
-}
-
-
-// Realise our palettes in the window and device contexts
-
-HRESULT CBaseWindow::DoRealisePalette(BOOL bForceBackground)
-{
- {
- CAutoLock cPaletteLock(&m_PaletteLock);
-
- if (m_hPalette == NULL) {
- return NOERROR;
- }
-
- // Realize the palette on the window thread
- ASSERT(m_hdc);
- ASSERT(m_MemoryDC);
-
- SelectPalette(m_hdc,m_hPalette,m_bBackground || bForceBackground);
- SelectPalette(m_MemoryDC,m_hPalette,m_bBackground);
- }
-
- // If we grab a critical section here we can deadlock
- // with the window thread because one of the side effects
- // of RealizePalette is to send a WM_PALETTECHANGED message
- // to every window in the system. In our handling
- // of WM_PALETTECHANGED we used to grab this CS too.
- // The really bad case is when our renderer calls DoRealisePalette()
- // while we're in the middle of processing a palette change
- // for another window.
- // So don't hold the critical section while actually realising
- // the palette. In any case USER is meant to manage palette
- // handling - we shouldn't have to serialize everything as well
- ASSERT(CritCheckOut(&m_WindowLock));
- ASSERT(CritCheckOut(&m_PaletteLock));
-
- EXECUTE_ASSERT(RealizePalette(m_hdc) != GDI_ERROR);
- EXECUTE_ASSERT(RealizePalette(m_MemoryDC) != GDI_ERROR);
-
- return (GdiFlush() == FALSE ? S_FALSE : S_OK);
-}
-
-
-// This is the global window procedure
-
-LRESULT CALLBACK WndProc(HWND hwnd, // Window handle
- UINT uMsg, // Message ID
- WPARAM wParam, // First parameter
- LPARAM lParam) // Other parameter
-{
-
- // Get the window long that holds our window object pointer
- // If it is NULL then we are initialising the window in which
- // case the object pointer has been passed in the window creation
- // structure. IF we get any messages before WM_NCCREATE we will
- // pass them to DefWindowProc.
-
- CBaseWindow *pBaseWindow = _GetWindowLongPtr<CBaseWindow*>(hwnd,0);
-
- if (pBaseWindow == NULL) {
-
- // Get the structure pointer from the create struct.
- // We can only do this for WM_NCCREATE which should be one of
- // the first messages we receive. Anything before this will
- // have to be passed to DefWindowProc (i.e. WM_GETMINMAXINFO)
-
- // If the message is WM_NCCREATE we set our pBaseWindow pointer
- // and will then place it in the window structure
-
- // turn off WS_EX_LAYOUTRTL style for quartz windows
- if (uMsg == WM_NCCREATE) {
- SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) & ~0x400000);
- }
-
- if ((uMsg != WM_NCCREATE)
- || (NULL == (pBaseWindow = *(CBaseWindow**) ((LPCREATESTRUCT)lParam)->lpCreateParams)))
- {
- return(DefWindowProc(hwnd, uMsg, wParam, lParam));
- }
-
- // Set the window LONG to be the object who created us
-#ifdef DEBUG
- SetLastError(0); // because of the way SetWindowLong works
-#endif
-
- LONG_PTR rc = _SetWindowLongPtr(hwnd, (DWORD) 0, pBaseWindow);
-
-
-#ifdef DEBUG
- if (0 == rc) {
- // SetWindowLong MIGHT have failed. (Read the docs which admit
- // that it is awkward to work out if you have had an error.)
- LONG lasterror = GetLastError();
- ASSERT(0 == lasterror);
- // If this is not the case we have not set the pBaseWindow pointer
- // into the window structure and we will blow up.
- }
-#endif
-
- }
- // See if this is the packet of death
- if (uMsg == MsgDestroy && uMsg != 0) {
- pBaseWindow->DoneWithWindow();
- if (pBaseWindow->m_bDoPostToDestroy) {
- EXECUTE_ASSERT(SetEvent((HANDLE)wParam));
- }
- return 0;
- }
- return pBaseWindow->OnReceiveMessage(hwnd,uMsg,wParam,lParam);
-}
-
-
-// When the window size changes we adjust our member variables that
-// contain the dimensions of the client rectangle for our window so
-// that we come to render an image we will know whether to stretch
-
-BOOL CBaseWindow::OnSize(LONG Width, LONG Height)
-{
- m_Width = Width;
- m_Height = Height;
- return TRUE;
-}
-
-
-// This function handles the WM_CLOSE message
-
-BOOL CBaseWindow::OnClose()
-{
- ShowWindow(m_hwnd,SW_HIDE);
- return TRUE;
-}
-
-
-// This is called by the worker window thread when it receives a terminate
-// message from the window object destructor to delete all the resources we
-// allocated during initialisation. By the time the worker thread exits all
-// processing will have been completed as the source filter disconnection
-// flushes the image pending sample, therefore the GdiFlush should succeed
-
-HRESULT CBaseWindow::UninitialiseWindow()
-{
- // Have we already cleaned up
-
- if (m_hwnd == NULL) {
- ASSERT(m_hdc == NULL);
- ASSERT(m_MemoryDC == NULL);
- return NOERROR;
- }
-
- // Release the window resources
-
- EXECUTE_ASSERT(GdiFlush());
-
- if (m_hdc)
- {
- EXECUTE_ASSERT(ReleaseDC(m_hwnd,m_hdc));
- m_hdc = NULL;
- }
-
- if (m_MemoryDC)
- {
- EXECUTE_ASSERT(DeleteDC(m_MemoryDC));
- m_MemoryDC = NULL;
- }
-
- // Reset the window variables
- m_hwnd = NULL;
-
- return NOERROR;
-}
-
-
-// This is called by the worker window thread after it has created the main
-// window and it wants to initialise the rest of the owner objects window
-// variables such as the device contexts. We execute this function with the
-// critical section still locked. Nothing in this function must generate any
-// SendMessage calls to the window because this is executing on the window
-// thread so the message will never be processed and we will deadlock
-
-HRESULT CBaseWindow::InitialiseWindow(HWND hwnd)
-{
- // Initialise the window variables
-
- ASSERT(IsWindow(hwnd));
- m_hwnd = hwnd;
-
- if (m_bDoGetDC)
- {
- EXECUTE_ASSERT(m_hdc = GetDC(hwnd));
- EXECUTE_ASSERT(m_MemoryDC = CreateCompatibleDC(m_hdc));
-
- EXECUTE_ASSERT(SetStretchBltMode(m_hdc,COLORONCOLOR));
- EXECUTE_ASSERT(SetStretchBltMode(m_MemoryDC,COLORONCOLOR));
- }
-
- return NOERROR;
-}
-
-HRESULT CBaseWindow::DoCreateWindow()
-{
- WNDCLASS wndclass; // Used to register classes
- BOOL bRegistered; // Is this class registered
- HWND hwnd; // Handle to our window
-
- bRegistered = GetClassInfo(m_hInstance, // Module instance
- m_pClassName, // Window class
- &wndclass); // Info structure
-
- // if the window is to be used for drawing puposes and we are getting a DC
- // for the entire lifetime of the window then changes the class style to do
- // say so. If we don't set this flag then the DC comes from the cache and is
- // really bad.
- if (m_bDoGetDC)
- {
- m_ClassStyles |= CS_OWNDC;
- }
-
- if (bRegistered == FALSE) {
-
- // Register the renderer window class
-
- wndclass.lpszClassName = m_pClassName;
- wndclass.style = m_ClassStyles;
- wndclass.lpfnWndProc = WndProc;
- wndclass.cbClsExtra = 0;
- wndclass.cbWndExtra = sizeof(CBaseWindow *);
- wndclass.hInstance = m_hInstance;
- wndclass.hIcon = NULL;
- wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
- wndclass.hbrBackground = (HBRUSH) NULL;
- wndclass.lpszMenuName = NULL;
-
- RegisterClass(&wndclass);
- }
-
- // Create the frame window. Pass the pBaseWindow information in the
- // CreateStruct which allows our message handling loop to get hold of
- // the pBaseWindow pointer.
-
- CBaseWindow *pBaseWindow = this; // The owner window object
- hwnd = CreateWindowEx(m_WindowStylesEx, // Extended styles
- m_pClassName, // Registered name
- TEXT("ActiveMovie Window"), // Window title
- m_WindowStyles, // Window styles
- CW_USEDEFAULT, // Start x position
- CW_USEDEFAULT, // Start y position
- DEFWIDTH, // Window width
- DEFHEIGHT, // Window height
- NULL, // Parent handle
- NULL, // Menu handle
- m_hInstance, // Instance handle
- &pBaseWindow); // Creation data
-
- // If we failed signal an error to the object constructor (based on the
- // last Win32 error on this thread) then signal the constructor thread
- // to continue, release the mutex to let others have a go and exit
-
- if (hwnd == NULL) {
- DWORD Error = GetLastError();
- return AmHresultFromWin32(Error);
- }
-
- // Check the window LONG is the object who created us
- ASSERT(GetWindowLongPtr(hwnd, 0) == (LONG_PTR)this);
-
- // Initialise the window and then signal the constructor so that it can
- // continue and then finally unlock the object's critical section. The
- // window class is left registered even after we terminate the thread
- // as we don't know when the last window has been closed. So we allow
- // the operating system to free the class resources as appropriate
-
- InitialiseWindow(hwnd);
-
- DbgLog((LOG_TRACE, 2, TEXT("Created window class (%s) HWND(%8.8X)"),
- m_pClassName, hwnd));
-
- return S_OK;
-}
-
-
-// The base class provides some default handling and calls DefWindowProc
-
-LRESULT CBaseWindow::OnReceiveMessage(HWND hwnd, // Window handle
- UINT uMsg, // Message ID
- WPARAM wParam, // First parameter
- LPARAM lParam) // Other parameter
-{
- ASSERT(IsWindow(hwnd));
-
- if (PossiblyEatMessage(uMsg, wParam, lParam))
- return 0;
-
- // This is sent by the IVideoWindow SetWindowForeground method. If the
- // window is invisible we will show it and make it topmost without the
- // foreground focus. If the window is visible it will also be made the
- // topmost window without the foreground focus. If wParam is TRUE then
- // for both cases the window will be forced into the foreground focus
-
- if (uMsg == m_ShowStageMessage) {
-
- BOOL bVisible = IsWindowVisible(hwnd);
- SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0,
- SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW |
- (bVisible ? SWP_NOACTIVATE : 0));
-
- // Should we bring the window to the foreground
- if (wParam == TRUE) {
- SetForegroundWindow(hwnd);
- }
- return (LRESULT) 1;
- }
-
- // When we go fullscreen we have to add the WS_EX_TOPMOST style to the
- // video window so that it comes out above any task bar (this is more
- // relevant to WindowsNT than Windows95). However the SetWindowPos call
- // must be on the same thread as that which created the window. The
- // wParam parameter can be TRUE or FALSE to set and reset the topmost
-
- if (uMsg == m_ShowStageTop) {
- HWND HwndTop = (wParam == TRUE ? HWND_TOPMOST : HWND_NOTOPMOST);
- BOOL bVisible = IsWindowVisible(hwnd);
- SetWindowPos(hwnd, HwndTop, 0, 0, 0, 0,
- SWP_NOMOVE | SWP_NOSIZE |
- (wParam == TRUE ? SWP_SHOWWINDOW : 0) |
- (bVisible ? SWP_NOACTIVATE : 0));
- return (LRESULT) 1;
- }
-
- // New palette stuff
- if (uMsg == m_RealizePalette) {
- ASSERT(m_hwnd == hwnd);
- return OnPaletteChange(m_hwnd,WM_QUERYNEWPALETTE);
- }
-
- switch (uMsg) {
-
- // Repaint the window if the system colours change
-
- case WM_SYSCOLORCHANGE:
-
- InvalidateRect(hwnd,NULL,FALSE);
- return (LRESULT) 1;
-
- // Somebody has changed the palette
- case WM_PALETTECHANGED:
-
- OnPaletteChange((HWND)wParam,uMsg);
- return (LRESULT) 0;
-
- // We are about to receive the keyboard focus so we ask GDI to realise
- // our logical palette again and hopefully it will be fully installed
- // without any mapping having to be done during any picture rendering
-
- case WM_QUERYNEWPALETTE:
- ASSERT(m_hwnd == hwnd);
- return OnPaletteChange(m_hwnd,uMsg);
-
- // do NOT fwd WM_MOVE. the parameters are the location of the parent
- // window, NOT what the renderer should be looking at. But we need
- // to make sure the overlay is moved with the parent window, so we
- // do this.
- case WM_MOVE:
- if (IsWindowVisible(m_hwnd)) {
- PostMessage(m_hwnd,WM_PAINT,0,0);
- }
- break;
-
- // Store the width and height as useful base class members
-
- case WM_SIZE:
-
- OnSize(LOWORD(lParam), HIWORD(lParam));
- return (LRESULT) 0;
-
- // Intercept the WM_CLOSE messages to hide the window
-
- case WM_CLOSE:
-
- OnClose();
- return (LRESULT) 0;
- }
- return DefWindowProc(hwnd,uMsg,wParam,lParam);
-}
-
-
-// This handles the Windows palette change messages - if we do realise our
-// palette then we return TRUE otherwise we return FALSE. If our window is
-// foreground application then we should get first choice of colours in the
-// system palette entries. We get best performance when our logical palette
-// includes the standard VGA colours (at the beginning and end) otherwise
-// GDI may have to map from our palette to the device palette while drawing
-
-LRESULT CBaseWindow::OnPaletteChange(HWND hwnd,UINT Message)
-{
- // First check we are not changing the palette during closedown
-
- if (m_hwnd == NULL || hwnd == NULL) {
- return (LRESULT) 0;
- }
- ASSERT(!m_bRealizing);
-
- // Should we realise our palette again
-
- if ((Message == WM_QUERYNEWPALETTE || hwnd != m_hwnd)) {
- // It seems that even if we're invisible that we can get asked
- // to realize our palette and this can cause really ugly side-effects
- // Seems like there's another bug but this masks it a least for the
- // shutting down case.
- if (!IsWindowVisible(m_hwnd)) {
- DbgLog((LOG_TRACE, 1, TEXT("Realizing when invisible!")));
- return (LRESULT) 0;
- }
-
- // Avoid recursion with multiple graphs in the same app
-#ifdef DEBUG
- m_bRealizing = TRUE;
-#endif
- DoRealisePalette(Message != WM_QUERYNEWPALETTE);
-#ifdef DEBUG
- m_bRealizing = FALSE;
-#endif
-
- // Should we redraw the window with the new palette
- if (Message == WM_PALETTECHANGED) {
- InvalidateRect(m_hwnd,NULL,FALSE);
- }
- }
-
- return (LRESULT) 1;
-}
-
-
-// Determine if the window exists.
-
-bool CBaseWindow::WindowExists()
-{
- return !!IsWindow(m_hwnd);
-}
-
-
-// Return the default window rectangle
-
-RECT CBaseWindow::GetDefaultRect()
-{
- RECT DefaultRect = {0,0,DEFWIDTH,DEFHEIGHT};
- ASSERT(m_hwnd);
- // ASSERT(m_hdc);
- return DefaultRect;
-}
-
-
-// Return the current window width
-
-LONG CBaseWindow::GetWindowWidth()
-{
- ASSERT(m_hwnd);
- // ASSERT(m_hdc);
- return m_Width;
-}
-
-
-// Return the current window height
-
-LONG CBaseWindow::GetWindowHeight()
-{
- ASSERT(m_hwnd);
- // ASSERT(m_hdc);
- return m_Height;
-}
-
-
-// Return the window handle
-
-HWND CBaseWindow::GetWindowHWND()
-{
- ASSERT(m_hwnd);
- // ASSERT(m_hdc);
- return m_hwnd;
-}
-
-
-// Return the window drawing device context
-
-HDC CBaseWindow::GetWindowHDC()
-{
- ASSERT(m_hwnd);
- ASSERT(m_hdc);
- return m_hdc;
-}
-
-
-// Return the offscreen window drawing device context
-
-HDC CBaseWindow::GetMemoryHDC()
-{
- ASSERT(m_hwnd);
- ASSERT(m_MemoryDC);
- return m_MemoryDC;
-}
-
-
-#ifdef DEBUG
-HPALETTE CBaseWindow::GetPalette()
-{
- // The palette lock should always be held when accessing
- // m_hPalette.
- ASSERT(CritCheckIn(&m_PaletteLock));
- return m_hPalette;
-}
-#endif // DEBUG
-
-
-// This is available to clients who want to change the window visiblity. It's
-// little more than an indirection to the Win32 ShowWindow although these is
-// some benefit in going through here as this function may change sometime
-
-HRESULT CBaseWindow::DoShowWindow(LONG ShowCmd)
-{
- ShowWindow(m_hwnd,ShowCmd);
- return NOERROR;
-}
-
-
-// Generate a WM_PAINT message for the video window
-
-void CBaseWindow::PaintWindow(BOOL bErase)
-{
- InvalidateRect(m_hwnd,NULL,bErase);
-}
-
-
-// Allow an application to have us set the video window in the foreground. We
-// have this because it is difficult for one thread to do do this to a window
-// owned by another thread. Rather than expose the message we use to execute
-// the inter thread send message we provide the interface function. All we do
-// is to SendMessage to the video window renderer thread with a WM_SHOWSTAGE
-
-void CBaseWindow::DoSetWindowForeground(BOOL bFocus)
-{
- SendMessage(m_hwnd,m_ShowStageMessage,(WPARAM) bFocus,(LPARAM) 0);
-}
-
-
-// Constructor initialises the owning object pointer. Since we are a worker
-// class for the main window object we have relatively few state variables to
-// look after. We are given device context handles to use later on as well as
-// the source and destination rectangles (but reset them here just in case)
-
-CDrawImage::CDrawImage(__inout CBaseWindow *pBaseWindow) :
- m_pBaseWindow(pBaseWindow),
- m_hdc(NULL),
- m_MemoryDC(NULL),
- m_bStretch(FALSE),
- m_pMediaType(NULL),
- m_bUsingImageAllocator(FALSE)
-{
- ASSERT(pBaseWindow);
- ResetPaletteVersion();
- SetRectEmpty(&m_TargetRect);
- SetRectEmpty(&m_SourceRect);
-
- m_perfidRenderTime = MSR_REGISTER(TEXT("Single Blt time"));
-}
-
-
-// Overlay the image time stamps on the picture. Access to this method is
-// serialised by the caller. We display the sample start and end times on
-// top of the video using TextOut on the device context we are handed. If
-// there isn't enough room in the window for the times we don't show them
-
-void CDrawImage::DisplaySampleTimes(IMediaSample *pSample)
-{
-#ifdef DEBUG
- //
- // Only allow the "annoying" time messages if the users has turned the
- // logging "way up"
- //
- BOOL bAccept = DbgCheckModuleLevel(LOG_TRACE, 5);
- if (bAccept == FALSE) {
- return;
- }
-#endif
-
- TCHAR szTimes[TIMELENGTH]; // Time stamp strings
- ASSERT(pSample); // Quick sanity check
- RECT ClientRect; // Client window size
- SIZE Size; // Size of text output
-
- // Get the time stamps and window size
-
- pSample->GetTime((REFERENCE_TIME*)&m_StartSample, (REFERENCE_TIME*)&m_EndSample);
- HWND hwnd = m_pBaseWindow->GetWindowHWND();
- EXECUTE_ASSERT(GetClientRect(hwnd,&ClientRect));
-
- // Format the sample time stamps
-
- (void)StringCchPrintf(szTimes,NUMELMS(szTimes),TEXT("%08d : %08d"),
- m_StartSample.Millisecs(),
- m_EndSample.Millisecs());
-
- ASSERT(lstrlen(szTimes) < TIMELENGTH);
-
- // Put the times in the middle at the bottom of the window
-
- GetTextExtentPoint32(m_hdc,szTimes,lstrlen(szTimes),&Size);
- INT XPos = ((ClientRect.right - ClientRect.left) - Size.cx) / 2;
- INT YPos = ((ClientRect.bottom - ClientRect.top) - Size.cy) * 4 / 5;
-
- // Check the window is big enough to have sample times displayed
-
- if ((XPos > 0) && (YPos > 0)) {
- TextOut(m_hdc,XPos,YPos,szTimes,lstrlen(szTimes));
- }
-}
-
-
-// This is called when the drawing code sees that the image has a down level
-// palette cookie. We simply call the SetDIBColorTable Windows API with the
-// palette that is found after the BITMAPINFOHEADER - we return no errors
-
-void CDrawImage::UpdateColourTable(HDC hdc,__in BITMAPINFOHEADER *pbmi)
-{
- ASSERT(pbmi->biClrUsed);
- RGBQUAD *pColourTable = (RGBQUAD *)(pbmi+1);
-
- // Set the new palette in the device context
-
- UINT uiReturn = SetDIBColorTable(hdc,(UINT) 0,
- pbmi->biClrUsed,
- pColourTable);
-
- // Should always succeed but check in debug builds
- ASSERT(uiReturn == pbmi->biClrUsed);
-}
-
-
-// No source rectangle scaling is done by the base class
-
-RECT CDrawImage::ScaleSourceRect(const RECT *pSource)
-{
- ASSERT(pSource);
- return *pSource;
-}
-
-
-// This is called when the funky output pin uses our allocator. The samples we
-// allocate are special because the memory is shared between us and GDI thus
-// removing one copy when we ask for the image to be rendered. The source type
-// information is in the main renderer m_mtIn field which is initialised when
-// the media type is agreed in SetMediaType, the media type may be changed on
-// the fly if, for example, the source filter needs to change the palette
-
-void CDrawImage::FastRender(IMediaSample *pMediaSample)
-{
- BITMAPINFOHEADER *pbmi; // Image format data
- DIBDATA *pDibData; // Stores DIB information
- BYTE *pImage; // Pointer to image data
- HBITMAP hOldBitmap; // Store the old bitmap
- CImageSample *pSample; // Pointer to C++ object
-
- ASSERT(m_pMediaType);
-
- // From the untyped source format block get the VIDEOINFO and subsequently
- // the BITMAPINFOHEADER structure. We can cast the IMediaSample interface
- // to a CImageSample object so we can retrieve it's DIBSECTION details
-
- pbmi = HEADER(m_pMediaType->Format());
- pSample = (CImageSample *) pMediaSample;
- pDibData = pSample->GetDIBData();
- hOldBitmap = (HBITMAP) SelectObject(m_MemoryDC,pDibData->hBitmap);
-
- // Get a pointer to the real image data
-
- HRESULT hr = pMediaSample->GetPointer(&pImage);
- if (FAILED(hr)) {
- return;
- }
-
- // Do we need to update the colour table, we increment our palette cookie
- // each time we get a dynamic format change. The sample palette cookie is
- // stored in the DIBDATA structure so we try to keep the fields in sync
- // By the time we get to draw the images the format change will be done
- // so all we do is ask the renderer for what it's palette version is
-
- if (pDibData->PaletteVersion < GetPaletteVersion()) {
- ASSERT(pbmi->biBitCount <= iPALETTE);
- UpdateColourTable(m_MemoryDC,pbmi);
- pDibData->PaletteVersion = GetPaletteVersion();
- }
-
- // This allows derived classes to change the source rectangle that we do
- // the drawing with. For example a renderer may ask a codec to stretch
- // the video from 320x240 to 640x480, in which case the source we see in
- // here will still be 320x240, although the source we want to draw with
- // should be scaled up to 640x480. The base class implementation of this
- // method does nothing but return the same rectangle as we are passed in
-
- RECT SourceRect = ScaleSourceRect(&m_SourceRect);
-
- // Is the window the same size as the video
-
- if (m_bStretch == FALSE) {
-
- // Put the image straight into the window
-
- BitBlt(
- (HDC) m_hdc, // Target device HDC
- m_TargetRect.left, // X sink position
- m_TargetRect.top, // Y sink position
- m_TargetRect.right - m_TargetRect.left, // Destination width
- m_TargetRect.bottom - m_TargetRect.top, // Destination height
- m_MemoryDC, // Source device context
- SourceRect.left, // X source position
- SourceRect.top, // Y source position
- SRCCOPY); // Simple copy
-
- } else {
-
- // Stretch the image when copying to the window
-
- StretchBlt(
- (HDC) m_hdc, // Target device HDC
- m_TargetRect.left, // X sink position
- m_TargetRect.top, // Y sink position
- m_TargetRect.right - m_TargetRect.left, // Destination width
- m_TargetRect.bottom - m_TargetRect.top, // Destination height
- m_MemoryDC, // Source device HDC
- SourceRect.left, // X source position
- SourceRect.top, // Y source position
- SourceRect.right - SourceRect.left, // Source width
- SourceRect.bottom - SourceRect.top, // Source height
- SRCCOPY); // Simple copy
- }
-
- // This displays the sample times over the top of the image. This used to
- // draw the times into the offscreen device context however that actually
- // writes the text into the image data buffer which may not be writable
-
- #ifdef DEBUG
- DisplaySampleTimes(pMediaSample);
- #endif
-
- // Put the old bitmap back into the device context so we don't leak
- SelectObject(m_MemoryDC,hOldBitmap);
-}
-
-
-// This is called when there is a sample ready to be drawn, unfortunately the
-// output pin was being rotten and didn't choose our super excellent shared
-// memory DIB allocator so we have to do this slow render using boring old GDI
-// SetDIBitsToDevice and StretchDIBits. The down side of using these GDI
-// functions is that the image data has to be copied across from our address
-// space into theirs before going to the screen (although in reality the cost
-// is small because all they do is to map the buffer into their address space)
-
-void CDrawImage::SlowRender(IMediaSample *pMediaSample)
-{
- // Get the BITMAPINFOHEADER for the connection
-
- ASSERT(m_pMediaType);
- BITMAPINFOHEADER *pbmi = HEADER(m_pMediaType->Format());
- BYTE *pImage;
-
- // Get the image data buffer
-
- HRESULT hr = pMediaSample->GetPointer(&pImage);
- if (FAILED(hr)) {
- return;
- }
-
- // This allows derived classes to change the source rectangle that we do
- // the drawing with. For example a renderer may ask a codec to stretch
- // the video from 320x240 to 640x480, in which case the source we see in
- // here will still be 320x240, although the source we want to draw with
- // should be scaled up to 640x480. The base class implementation of this
- // method does nothing but return the same rectangle as we are passed in
-
- RECT SourceRect = ScaleSourceRect(&m_SourceRect);
-
- LONG lAdjustedSourceTop = SourceRect.top;
- // if the origin of bitmap is bottom-left, adjust soruce_rect_top
- // to be the bottom-left corner instead of the top-left.
- if (pbmi->biHeight > 0) {
- lAdjustedSourceTop = pbmi->biHeight - SourceRect.bottom;
- }
- // Is the window the same size as the video
-
- if (m_bStretch == FALSE) {
-
- // Put the image straight into the window
-
- SetDIBitsToDevice(
- (HDC) m_hdc, // Target device HDC
- m_TargetRect.left, // X sink position
- m_TargetRect.top, // Y sink position
- m_TargetRect.right - m_TargetRect.left, // Destination width
- m_TargetRect.bottom - m_TargetRect.top, // Destination height
- SourceRect.left, // X source position
- lAdjustedSourceTop, // Adjusted Y source position
- (UINT) 0, // Start scan line
- pbmi->biHeight, // Scan lines present
- pImage, // Image data
- (BITMAPINFO *) pbmi, // DIB header
- DIB_RGB_COLORS); // Type of palette
-
- } else {
-
- // Stretch the image when copying to the window
-
- StretchDIBits(
- (HDC) m_hdc, // Target device HDC
- m_TargetRect.left, // X sink position
- m_TargetRect.top, // Y sink position
- m_TargetRect.right - m_TargetRect.left, // Destination width
- m_TargetRect.bottom - m_TargetRect.top, // Destination height
- SourceRect.left, // X source position
- lAdjustedSourceTop, // Adjusted Y source position
- SourceRect.right - SourceRect.left, // Source width
- SourceRect.bottom - SourceRect.top, // Source height
- pImage, // Image data
- (BITMAPINFO *) pbmi, // DIB header
- DIB_RGB_COLORS, // Type of palette
- SRCCOPY); // Simple image copy
- }
-
- // This shows the sample reference times over the top of the image which
- // looks a little flickery. I tried using GdiSetBatchLimit and GdiFlush to
- // control the screen updates but it doesn't quite work as expected and
- // only partially reduces the flicker. I also tried using a memory context
- // and combining the two in that before doing a final BitBlt operation to
- // the screen, unfortunately this has considerable performance penalties
- // and also means that this code is not executed when compiled retail
-
- #ifdef DEBUG
- DisplaySampleTimes(pMediaSample);
- #endif
-}
-
-
-// This is called with an IMediaSample interface on the image to be drawn. We
-// decide on the drawing mechanism based on who's allocator we are using. We
-// may be called when the window wants an image painted by WM_PAINT messages
-// We can't realise the palette here because we have the renderer lock, any
-// call to realise may cause an interthread send message to the window thread
-// which may in turn be waiting to get the renderer lock before servicing it
-
-BOOL CDrawImage::DrawImage(IMediaSample *pMediaSample)
-{
- ASSERT(m_hdc);
- ASSERT(m_MemoryDC);
- NotifyStartDraw();
-
- // If the output pin used our allocator then the samples passed are in
- // fact CVideoSample objects that contain CreateDIBSection data that we
- // use to do faster image rendering, they may optionally also contain a
- // DirectDraw surface pointer in which case we do not do the drawing
-
- if (m_bUsingImageAllocator == FALSE) {
- SlowRender(pMediaSample);
- EXECUTE_ASSERT(GdiFlush());
- NotifyEndDraw();
- return TRUE;
- }
-
- // This is a DIBSECTION buffer
-
- FastRender(pMediaSample);
- EXECUTE_ASSERT(GdiFlush());
- NotifyEndDraw();
- return TRUE;
-}
-
-
-BOOL CDrawImage::DrawVideoImageHere(
- HDC hdc,
- IMediaSample *pMediaSample,
- __in LPRECT lprcSrc,
- __in LPRECT lprcDst
- )
-{
- ASSERT(m_pMediaType);
- BITMAPINFOHEADER *pbmi = HEADER(m_pMediaType->Format());
- BYTE *pImage;
-
- // Get the image data buffer
-
- HRESULT hr = pMediaSample->GetPointer(&pImage);
- if (FAILED(hr)) {
- return FALSE;
- }
-
- RECT SourceRect;
- RECT TargetRect;
-
- if (lprcSrc) {
- SourceRect = *lprcSrc;
- }
- else SourceRect = ScaleSourceRect(&m_SourceRect);
-
- if (lprcDst) {
- TargetRect = *lprcDst;
- }
- else TargetRect = m_TargetRect;
-
- LONG lAdjustedSourceTop = SourceRect.top;
- // if the origin of bitmap is bottom-left, adjust soruce_rect_top
- // to be the bottom-left corner instead of the top-left.
- if (pbmi->biHeight > 0) {
- lAdjustedSourceTop = pbmi->biHeight - SourceRect.bottom;
- }
-
-
- // Stretch the image when copying to the DC
-
- BOOL bRet = (0 != StretchDIBits(hdc,
- TargetRect.left,
- TargetRect.top,
- TargetRect.right - TargetRect.left,
- TargetRect.bottom - TargetRect.top,
- SourceRect.left,
- lAdjustedSourceTop,
- SourceRect.right - SourceRect.left,
- SourceRect.bottom - SourceRect.top,
- pImage,
- (BITMAPINFO *)pbmi,
- DIB_RGB_COLORS,
- SRCCOPY));
- return bRet;
-}
-
-
-// This is called by the owning window object after it has created the window
-// and it's drawing contexts. We are constructed with the base window we'll
-// be drawing into so when given the notification we retrive the device HDCs
-// to draw with. We cannot call these in our constructor as they are virtual
-
-void CDrawImage::SetDrawContext()
-{
- m_MemoryDC = m_pBaseWindow->GetMemoryHDC();
- m_hdc = m_pBaseWindow->GetWindowHDC();
-}
-
-
-// This is called to set the target rectangle in the video window, it will be
-// called whenever a WM_SIZE message is retrieved from the message queue. We
-// simply store the rectangle and use it later when we do the drawing calls
-
-void CDrawImage::SetTargetRect(__in RECT *pTargetRect)
-{
- ASSERT(pTargetRect);
- m_TargetRect = *pTargetRect;
- SetStretchMode();
-}
-
-
-// Return the current target rectangle
-
-void CDrawImage::GetTargetRect(__out RECT *pTargetRect)
-{
- ASSERT(pTargetRect);
- *pTargetRect = m_TargetRect;
-}
-
-
-// This is called when we want to change the section of the image to draw. We
-// use this information in the drawing operation calls later on. We must also
-// see if the source and destination rectangles have the same dimensions. If
-// not we must stretch during the drawing rather than a direct pixel copy
-
-void CDrawImage::SetSourceRect(__in RECT *pSourceRect)
-{
- ASSERT(pSourceRect);
- m_SourceRect = *pSourceRect;
- SetStretchMode();
-}
-
-
-// Return the current source rectangle
-
-void CDrawImage::GetSourceRect(__out RECT *pSourceRect)
-{
- ASSERT(pSourceRect);
- *pSourceRect = m_SourceRect;
-}
-
-
-// This is called when either the source or destination rectanges change so we
-// can update the stretch flag. If the rectangles don't match we stretch the
-// video during the drawing otherwise we call the fast pixel copy functions
-// NOTE the source and/or the destination rectangle may be completely empty
-
-void CDrawImage::SetStretchMode()
-{
- // Calculate the overall rectangle dimensions
-
- LONG SourceWidth = m_SourceRect.right - m_SourceRect.left;
- LONG SinkWidth = m_TargetRect.right - m_TargetRect.left;
- LONG SourceHeight = m_SourceRect.bottom - m_SourceRect.top;
- LONG SinkHeight = m_TargetRect.bottom - m_TargetRect.top;
-
- m_bStretch = TRUE;
- if (SourceWidth == SinkWidth) {
- if (SourceHeight == SinkHeight) {
- m_bStretch = FALSE;
- }
- }
-}
-
-
-// Tell us whose allocator we are using. This should be called with TRUE if
-// the filter agrees to use an allocator based around the CImageAllocator
-// SDK base class - whose image buffers are made through CreateDIBSection.
-// Otherwise this should be called with FALSE and we will draw the images
-// using SetDIBitsToDevice and StretchDIBitsToDevice. None of these calls
-// can handle buffers which have non zero strides (like DirectDraw uses)
-
-void CDrawImage::NotifyAllocator(BOOL bUsingImageAllocator)
-{
- m_bUsingImageAllocator = bUsingImageAllocator;
-}
-
-
-// Are we using the image DIBSECTION allocator
-
-BOOL CDrawImage::UsingImageAllocator()
-{
- return m_bUsingImageAllocator;
-}
-
-
-// We need the media type of the connection so that we can get the BITMAPINFO
-// from it. We use that in the calls to draw the image such as StretchDIBits
-// and also when updating the colour table held in shared memory DIBSECTIONs
-
-void CDrawImage::NotifyMediaType(__in CMediaType *pMediaType)
-{
- m_pMediaType = pMediaType;
-}
-
-
-// We store in this object a cookie maintaining the current palette version.
-// Each time a palettised format is changed we increment this value so that
-// when we come to draw the images we look at the colour table value they
-// have and if less than the current we know to update it. This version is
-// only needed and indeed used when working with shared memory DIBSECTIONs
-
-LONG CDrawImage::GetPaletteVersion()
-{
- return m_PaletteVersion;
-}
-
-
-// Resets the current palette version number
-
-void CDrawImage::ResetPaletteVersion()
-{
- m_PaletteVersion = PALETTE_VERSION;
-}
-
-
-// Increment the current palette version
-
-void CDrawImage::IncrementPaletteVersion()
-{
- m_PaletteVersion++;
-}
-
-
-// Constructor must initialise the base allocator. Each sample we create has a
-// palette version cookie on board. When the source filter changes the palette
-// during streaming the window object increments an internal cookie counter it
-// keeps as well. When it comes to render the samples it looks at the cookie
-// values and if they don't match then it knows to update the sample's colour
-// table. However we always create samples with a cookie of PALETTE_VERSION
-// If there have been multiple format changes and we disconnect and reconnect
-// thereby causing the samples to be reallocated we will create them with a
-// cookie much lower than the current version, this isn't a problem since it
-// will be seen by the window object and the versions will then be updated
-
-CImageAllocator::CImageAllocator(__inout CBaseFilter *pFilter,
- __in_opt LPCTSTR pName,
- __inout HRESULT *phr) :
- CBaseAllocator(pName,NULL,phr,TRUE,TRUE),
- m_pFilter(pFilter)
-{
- ASSERT(phr);
- ASSERT(pFilter);
-}
-
-
-// Check our DIB buffers have been released
-
-#ifdef DEBUG
-CImageAllocator::~CImageAllocator()
-{
- ASSERT(m_bCommitted == FALSE);
-}
-#endif
-
-
-// Called from destructor and also from base class to free resources. We work
-// our way through the list of media samples deleting the DIBSECTION created
-// for each. All samples should be back in our list so there is no chance a
-// filter is still using one to write on the display or hold on a pending list
-
-void CImageAllocator::Free()
-{
- ASSERT(m_lAllocated == m_lFree.GetCount());
- EXECUTE_ASSERT(GdiFlush());
- CImageSample *pSample;
- DIBDATA *pDibData;
-
- while (m_lFree.GetCount() != 0) {
- pSample = (CImageSample *) m_lFree.RemoveHead();
- pDibData = pSample->GetDIBData();
- EXECUTE_ASSERT(DeleteObject(pDibData->hBitmap));
- EXECUTE_ASSERT(CloseHandle(pDibData->hMapping));
- delete pSample;
- }
-
- m_lAllocated = 0;
-}
-
-
-// Prepare the allocator by checking all the input parameters
-
-STDMETHODIMP CImageAllocator::CheckSizes(__in ALLOCATOR_PROPERTIES *pRequest)
-{
- // Check we have a valid connection
-
- if (m_pMediaType == NULL) {
- return VFW_E_NOT_CONNECTED;
- }
-
- // NOTE We always create a DIB section with the source format type which
- // may contain a source palette. When we do the BitBlt drawing operation
- // the target display device may contain a different palette (we may not
- // have the focus) in which case GDI will do after the palette mapping
-
- VIDEOINFOHEADER *pVideoInfo = (VIDEOINFOHEADER *) m_pMediaType->Format();
-
- // When we call CreateDIBSection it implicitly maps only enough memory
- // for the image as defined by thee BITMAPINFOHEADER. If the user asks
- // for an image smaller than this then we reject the call, if they ask
- // for an image larger than this then we return what they can have
-
- if ((DWORD) pRequest->cbBuffer < pVideoInfo->bmiHeader.biSizeImage) {
- return E_INVALIDARG;
- }
-
- // Reject buffer prefixes
-
- if (pRequest->cbPrefix > 0) {
- return E_INVALIDARG;
- }
-
- pRequest->cbBuffer = pVideoInfo->bmiHeader.biSizeImage;
- return NOERROR;
-}
-
-
-// Agree the number of media sample buffers and their sizes. The base class
-// this allocator is derived from allows samples to be aligned only on byte
-// boundaries NOTE the buffers are not allocated until the Commit call
-
-STDMETHODIMP CImageAllocator::SetProperties(
- __in ALLOCATOR_PROPERTIES * pRequest,
- __out ALLOCATOR_PROPERTIES * pActual)
-{
- ALLOCATOR_PROPERTIES Adjusted = *pRequest;
-
- // Check the parameters fit with the current connection
-
- HRESULT hr = CheckSizes(&Adjusted);
- if (FAILED(hr)) {
- return hr;
- }
- return CBaseAllocator::SetProperties(&Adjusted, pActual);
-}
-
-
-// Commit the memory by allocating the agreed number of media samples. For
-// each sample we are committed to creating we have a CImageSample object
-// that we use to manage it's resources. This is initialised with a DIBDATA
-// structure that contains amongst other things the GDI DIBSECTION handle
-// We will access the renderer media type during this so we must have locked
-// (to prevent the format changing for example). The class overrides Commit
-// and Decommit to do this locking (base class Commit in turn calls Alloc)
-
-HRESULT CImageAllocator::Alloc(void)
-{
- ASSERT(m_pMediaType);
- CImageSample *pSample;
- DIBDATA DibData;
-
- // Check the base allocator says it's ok to continue
-
- HRESULT hr = CBaseAllocator::Alloc();
- if (FAILED(hr)) {
- return hr;
- }
-
- // We create a new memory mapped object although we don't map it into our
- // address space because GDI does that in CreateDIBSection. It is possible
- // that we run out of resources before creating all the samples in which
- // case the available sample list is left with those already created
-
- ASSERT(m_lAllocated == 0);
- while (m_lAllocated < m_lCount) {
-
- // Create and initialise a shared memory GDI buffer
-
- hr = CreateDIB(m_lSize,DibData);
- if (FAILED(hr)) {
- return hr;
- }
-
- // Create the sample object and pass it the DIBDATA
-
- pSample = CreateImageSample(DibData.pBase,m_lSize);
- if (pSample == NULL) {
- EXECUTE_ASSERT(DeleteObject(DibData.hBitmap));
- EXECUTE_ASSERT(CloseHandle(DibData.hMapping));
- return E_OUTOFMEMORY;
- }
-
- // Add the completed sample to the available list
-
- pSample->SetDIBData(&DibData);
- m_lFree.Add(pSample);
- m_lAllocated++;
- }
- return NOERROR;
-}
-
-
-// We have a virtual method that allocates the samples so that a derived class
-// may override it and allocate more specialised sample objects. So long as it
-// derives its samples from CImageSample then all this code will still work ok
-
-CImageSample *CImageAllocator::CreateImageSample(__in_bcount(Length) LPBYTE pData,LONG Length)
-{
- HRESULT hr = NOERROR;
- CImageSample *pSample;
-
- // Allocate the new sample and check the return codes
-
- pSample = new CImageSample((CBaseAllocator *) this, // Base class
- NAME("Video sample"), // DEBUG name
- (HRESULT *) &hr, // Return code
- (LPBYTE) pData, // DIB address
- (LONG) Length); // Size of DIB
-
- if (pSample == NULL || FAILED(hr)) {
- delete pSample;
- return NULL;
- }
- return pSample;
-}
-
-
-// This function allocates a shared memory block for use by the source filter
-// generating DIBs for us to render. The memory block is created in shared
-// memory so that GDI doesn't have to copy the memory when we do a BitBlt
-
-HRESULT CImageAllocator::CreateDIB(LONG InSize,DIBDATA &DibData)
-{
- BITMAPINFO *pbmi; // Format information for pin
- BYTE *pBase; // Pointer to the actual image
- HANDLE hMapping; // Handle to mapped object
- HBITMAP hBitmap; // DIB section bitmap handle
-
- // Create a file mapping object and map into our address space
-
- hMapping = CreateFileMapping(hMEMORY, // Use system page file
- NULL, // No security attributes
- PAGE_READWRITE, // Full access to memory
- (DWORD) 0, // Less than 4Gb in size
- InSize, // Size of buffer
- NULL); // No name to section
- if (hMapping == NULL) {
- DWORD Error = GetLastError();
- return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, Error);
- }
-
- // NOTE We always create a DIB section with the source format type which
- // may contain a source palette. When we do the BitBlt drawing operation
- // the target display device may contain a different palette (we may not
- // have the focus) in which case GDI will do after the palette mapping
-
- pbmi = (BITMAPINFO *) HEADER(m_pMediaType->Format());
- if (m_pMediaType == NULL) {
- DbgBreak("Invalid media type");
- }
-
- hBitmap = CreateDIBSection((HDC) NULL, // NO device context
- pbmi, // Format information
- DIB_RGB_COLORS, // Use the palette
- (VOID **) &pBase, // Pointer to image data
- hMapping, // Mapped memory handle
- (DWORD) 0); // Offset into memory
-
- if (hBitmap == NULL || pBase == NULL) {
- EXECUTE_ASSERT(CloseHandle(hMapping));
- DWORD Error = GetLastError();
- return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, Error);
- }
-
- // Initialise the DIB information structure
-
- DibData.hBitmap = hBitmap;
- DibData.hMapping = hMapping;
- DibData.pBase = pBase;
- DibData.PaletteVersion = PALETTE_VERSION;
- GetObject(hBitmap,sizeof(DIBSECTION),(VOID *)&DibData.DibSection);
-
- return NOERROR;
-}
-
-
-// We use the media type during the DIBSECTION creation
-
-void CImageAllocator::NotifyMediaType(__in CMediaType *pMediaType)
-{
- m_pMediaType = pMediaType;
-}
-
-
-// Overriden to increment the owning object's reference count
-
-STDMETHODIMP_(ULONG) CImageAllocator::NonDelegatingAddRef()
-{
- return m_pFilter->AddRef();
-}
-
-
-// Overriden to decrement the owning object's reference count
-
-STDMETHODIMP_(ULONG) CImageAllocator::NonDelegatingRelease()
-{
- return m_pFilter->Release();
-}
-
-
-// If you derive a class from CMediaSample that has to transport specialised
-// member variables and entry points then there are three alternate solutions
-// The first is to create a memory buffer larger than actually required by the
-// sample and store your information either at the beginning of it or at the
-// end, the former being moderately safer allowing for misbehaving transform
-// filters. You then adjust the buffer address when you create the base media
-// sample. This has the disadvantage of breaking up the memory allocated to
-// the samples into separate blocks. The second solution is to implement a
-// class derived from CMediaSample and support additional interface(s) that
-// convey your private data. This means defining a custom interface. The final
-// alternative is to create a class that inherits from CMediaSample and adds
-// the private data structures, when you get an IMediaSample in your Receive()
-// call check to see if your allocator is being used, and if it is then cast
-// the IMediaSample into one of your objects. Additional checks can be made
-// to ensure the sample's this pointer is known to be one of your own objects
-
-CImageSample::CImageSample(__inout CBaseAllocator *pAllocator,
- __in_opt LPCTSTR pName,
- __inout HRESULT *phr,
- __in_bcount(length) LPBYTE pBuffer,
- LONG length) :
- CMediaSample(pName,pAllocator,phr,pBuffer,length),
- m_bInit(FALSE)
-{
- ASSERT(pAllocator);
- ASSERT(pBuffer);
-}
-
-
-// Set the shared memory DIB information
-
-void CImageSample::SetDIBData(__in DIBDATA *pDibData)
-{
- ASSERT(pDibData);
- m_DibData = *pDibData;
- m_bInit = TRUE;
-}
-
-
-// Retrieve the shared memory DIB data
-
-__out DIBDATA *CImageSample::GetDIBData()
-{
- ASSERT(m_bInit == TRUE);
- return &m_DibData;
-}
-
-
-// This class handles the creation of a palette. It is fairly specialist and
-// is intended to simplify palette management for video renderer filters. It
-// is for this reason that the constructor requires three other objects with
-// which it interacts, namely a base media filter, a base window and a base
-// drawing object although the base window or the draw object may be NULL to
-// ignore that part of us. We try not to create and install palettes unless
-// absolutely necessary as they typically require WM_PALETTECHANGED messages
-// to be sent to every window thread in the system which is very expensive
-
-CImagePalette::CImagePalette(__inout CBaseFilter *pBaseFilter,
- __inout CBaseWindow *pBaseWindow,
- __inout CDrawImage *pDrawImage) :
- m_pBaseWindow(pBaseWindow),
- m_pFilter(pBaseFilter),
- m_pDrawImage(pDrawImage),
- m_hPalette(NULL)
-{
- ASSERT(m_pFilter);
-}
-
-
-// Destructor
-
-#ifdef DEBUG
-CImagePalette::~CImagePalette()
-{
- ASSERT(m_hPalette == NULL);
-}
-#endif
-
-
-// We allow dynamic format changes of the palette but rather than change the
-// palette every time we call this to work out whether an update is required.
-// If the original type didn't use a palette and the new one does (or vica
-// versa) then we return TRUE. If neither formats use a palette we'll return
-// FALSE. If both formats use a palette we compare their colours and return
-// FALSE if they match. This therefore short circuits palette creation unless
-// absolutely necessary since installing palettes is an expensive operation
-
-BOOL CImagePalette::ShouldUpdate(const VIDEOINFOHEADER *pNewInfo,
- const VIDEOINFOHEADER *pOldInfo)
-{
- // We may not have a current format yet
-
- if (pOldInfo == NULL) {
- return TRUE;
- }
-
- // Do both formats not require a palette
-
- if (ContainsPalette(pNewInfo) == FALSE) {
- if (ContainsPalette(pOldInfo) == FALSE) {
- return FALSE;
- }
- }
-
- // Compare the colours to see if they match
-
- DWORD VideoEntries = pNewInfo->bmiHeader.biClrUsed;
- if (ContainsPalette(pNewInfo) == TRUE)
- if (ContainsPalette(pOldInfo) == TRUE)
- if (pOldInfo->bmiHeader.biClrUsed == VideoEntries)
- if (pOldInfo->bmiHeader.biClrUsed > 0)
- if (memcmp((PVOID) GetBitmapPalette(pNewInfo),
- (PVOID) GetBitmapPalette(pOldInfo),
- VideoEntries * sizeof(RGBQUAD)) == 0) {
-
- return FALSE;
- }
- return TRUE;
-}
-
-
-// This is normally called when the input pin type is set to install a palette
-// We will typically be called from two different places. The first is when we
-// have negotiated a palettised media type after connection, the other is when
-// we receive a new type during processing with an updated palette in which
-// case we must remove and release the resources held by the current palette
-
-// We can be passed an optional device name if we wish to prepare a palette
-// for a specific monitor on a multi monitor system
-
-HRESULT CImagePalette::PreparePalette(const CMediaType *pmtNew,
- const CMediaType *pmtOld,
- __in LPSTR szDevice)
-{
- const VIDEOINFOHEADER *pNewInfo = (VIDEOINFOHEADER *) pmtNew->Format();
- const VIDEOINFOHEADER *pOldInfo = (VIDEOINFOHEADER *) pmtOld->Format();
- ASSERT(pNewInfo);
-
- // This is an performance optimisation, when we get a media type we check
- // to see if the format requires a palette change. If either we need one
- // when previously we didn't or vica versa then this returns TRUE, if we
- // previously needed a palette and we do now it compares their colours
-
- if (ShouldUpdate(pNewInfo,pOldInfo) == FALSE) {
- NOTE("No update needed");
- return S_FALSE;
- }
-
- // We must notify the filter graph that the application may have changed
- // the palette although in practice we don't bother checking to see if it
- // is really different. If it tries to get the palette either the window
- // or renderer lock will ensure it doesn't get in until we are finished
-
- RemovePalette();
- m_pFilter->NotifyEvent(EC_PALETTE_CHANGED,0,0);
-
- // Do we need a palette for the new format
-
- if (ContainsPalette(pNewInfo) == FALSE) {
- NOTE("New has no palette");
- return S_FALSE;
- }
-
- if (m_pBaseWindow) {
- m_pBaseWindow->LockPaletteLock();
- }
-
- // If we're changing the palette on the fly then we increment our palette
- // cookie which is compared against the cookie also stored in all of our
- // DIBSECTION media samples. If they don't match when we come to draw it
- // then we know the sample is out of date and we'll update it's palette
-
- NOTE("Making new colour palette");
- m_hPalette = MakePalette(pNewInfo, szDevice);
- ASSERT(m_hPalette != NULL);
-
- if (m_pBaseWindow) {
- m_pBaseWindow->UnlockPaletteLock();
- }
-
- // The window in which the new palette is to be realised may be a NULL
- // pointer to signal that no window is in use, if so we don't call it
- // Some filters just want to use this object to create/manage palettes
-
- if (m_pBaseWindow) m_pBaseWindow->SetPalette(m_hPalette);
-
- // This is the only time where we need access to the draw object to say
- // to it that a new palette will be arriving on a sample real soon. The
- // constructor may take a NULL pointer in which case we don't call this
-
- if (m_pDrawImage) m_pDrawImage->IncrementPaletteVersion();
- return NOERROR;
-}
-
-
-// Helper function to copy a palette out of any kind of VIDEOINFO (ie it may
-// be YUV or true colour) into a palettised VIDEOINFO. We use this changing
-// palettes on DirectDraw samples as a source filter can attach a palette to
-// any buffer (eg YUV) and hand it back. We make a new palette out of that
-// format and then copy the palette colours into the current connection type
-
-HRESULT CImagePalette::CopyPalette(const CMediaType *pSrc,__out CMediaType *pDest)
-{
- // Reset the destination palette before starting
-
- VIDEOINFOHEADER *pDestInfo = (VIDEOINFOHEADER *) pDest->Format();
- pDestInfo->bmiHeader.biClrUsed = 0;
- pDestInfo->bmiHeader.biClrImportant = 0;
-
- // Does the destination have a palette
-
- if (PALETTISED(pDestInfo) == FALSE) {
- NOTE("No destination palette");
- return S_FALSE;
- }
-
- // Does the source contain a palette
-
- const VIDEOINFOHEADER *pSrcInfo = (VIDEOINFOHEADER *) pSrc->Format();
- if (ContainsPalette(pSrcInfo) == FALSE) {
- NOTE("No source palette");
- return S_FALSE;
- }
-
- // The number of colours may be zero filled
-
- DWORD PaletteEntries = pSrcInfo->bmiHeader.biClrUsed;
- if (PaletteEntries == 0) {
- DWORD Maximum = (1 << pSrcInfo->bmiHeader.biBitCount);
- NOTE1("Setting maximum colours (%d)",Maximum);
- PaletteEntries = Maximum;
- }
-
- // Make sure the destination has enough room for the palette
-
- ASSERT(pSrcInfo->bmiHeader.biClrUsed <= iPALETTE_COLORS);
- ASSERT(pSrcInfo->bmiHeader.biClrImportant <= PaletteEntries);
- ASSERT(COLORS(pDestInfo) == GetBitmapPalette(pDestInfo));
- pDestInfo->bmiHeader.biClrUsed = PaletteEntries;
- pDestInfo->bmiHeader.biClrImportant = pSrcInfo->bmiHeader.biClrImportant;
- ULONG BitmapSize = GetBitmapFormatSize(HEADER(pSrcInfo));
-
- if (pDest->FormatLength() < BitmapSize) {
- NOTE("Reallocating destination");
- pDest->ReallocFormatBuffer(BitmapSize);
- }
-
- // Now copy the palette colours across
-
- CopyMemory((PVOID) COLORS(pDestInfo),
- (PVOID) GetBitmapPalette(pSrcInfo),
- PaletteEntries * sizeof(RGBQUAD));
-
- return NOERROR;
-}
-
-
-// This is normally called when the palette is changed (typically during a
-// dynamic format change) to remove any palette we previously installed. We
-// replace it (if necessary) in the video window with a standard VGA palette
-// that should always be available even if this is a true colour display
-
-HRESULT CImagePalette::RemovePalette()
-{
- if (m_pBaseWindow) {
- m_pBaseWindow->LockPaletteLock();
- }
-
- // Do we have a palette to remove
-
- if (m_hPalette != NULL) {
-
- if (m_pBaseWindow) {
- // Make sure that the window's palette handle matches
- // our palette handle.
- ASSERT(m_hPalette == m_pBaseWindow->GetPalette());
-
- m_pBaseWindow->UnsetPalette();
- }
-
- EXECUTE_ASSERT(DeleteObject(m_hPalette));
- m_hPalette = NULL;
- }
-
- if (m_pBaseWindow) {
- m_pBaseWindow->UnlockPaletteLock();
- }
-
- return NOERROR;
-}
-
-
-// Called to create a palette for the object, the data structure used by GDI
-// to describe a palette is a LOGPALETTE, this includes a variable number of
-// PALETTEENTRY fields which are the colours, we have to convert the RGBQUAD
-// colour fields we are handed in a BITMAPINFO from the media type into these
-// This handles extraction of palettes from true colour and YUV media formats
-
-// We can be passed an optional device name if we wish to prepare a palette
-// for a specific monitor on a multi monitor system
-
-HPALETTE CImagePalette::MakePalette(const VIDEOINFOHEADER *pVideoInfo, __in LPSTR szDevice)
-{
- ASSERT(ContainsPalette(pVideoInfo) == TRUE);
- ASSERT(pVideoInfo->bmiHeader.biClrUsed <= iPALETTE_COLORS);
- BITMAPINFOHEADER *pHeader = HEADER(pVideoInfo);
-
- const RGBQUAD *pColours; // Pointer to the palette
- LOGPALETTE *lp; // Used to create a palette
- HPALETTE hPalette; // Logical palette object
-
- lp = (LOGPALETTE *) new BYTE[sizeof(LOGPALETTE) + SIZE_PALETTE];
- if (lp == NULL) {
- return NULL;
- }
-
- // Unfortunately for some hare brained reason a GDI palette entry (a
- // PALETTEENTRY structure) is different to a palette entry from a DIB
- // format (a RGBQUAD structure) so we have to do the field conversion
- // The VIDEOINFO containing the palette may be a true colour type so
- // we use GetBitmapPalette to skip over any bit fields if they exist
-
- lp->palVersion = PALVERSION;
- lp->palNumEntries = (USHORT) pHeader->biClrUsed;
- if (lp->palNumEntries == 0) lp->palNumEntries = (1 << pHeader->biBitCount);
- pColours = GetBitmapPalette(pVideoInfo);
-
- for (DWORD dwCount = 0;dwCount < lp->palNumEntries;dwCount++) {
- lp->palPalEntry[dwCount].peRed = pColours[dwCount].rgbRed;
- lp->palPalEntry[dwCount].peGreen = pColours[dwCount].rgbGreen;
- lp->palPalEntry[dwCount].peBlue = pColours[dwCount].rgbBlue;
- lp->palPalEntry[dwCount].peFlags = 0;
- }
-
- MakeIdentityPalette(lp->palPalEntry, lp->palNumEntries, szDevice);
-
- // Create a logical palette
-
- hPalette = CreatePalette(lp);
- ASSERT(hPalette != NULL);
- delete[] lp;
- return hPalette;
-}
-
-
-// GDI does a fair job of compressing the palette entries you give it, so for
-// example if you have five entries with an RGB colour (0,0,0) it will remove
-// all but one of them. When you subsequently draw an image it will map from
-// your logical palette to the compressed device palette. This function looks
-// to see if it is trying to be an identity palette and if so sets the flags
-// field in the PALETTEENTRYs so they remain expanded to boost performance
-
-// We can be passed an optional device name if we wish to prepare a palette
-// for a specific monitor on a multi monitor system
-
-HRESULT CImagePalette::MakeIdentityPalette(__inout_ecount_full(iColours) PALETTEENTRY *pEntry,INT iColours, __in LPSTR szDevice)
-{
- PALETTEENTRY SystemEntries[10]; // System palette entries
- BOOL bIdentityPalette = TRUE; // Is an identity palette
- ASSERT(iColours <= iPALETTE_COLORS); // Should have a palette
- const int PalLoCount = 10; // First ten reserved colours
- const int PalHiStart = 246; // Last VGA palette entries
-
- // Does this have the full colour range
-
- if (iColours < 10) {
- return S_FALSE;
- }
-
- // Apparently some displays have odd numbers of system colours
-
- // Get a DC on the right monitor - it's ugly, but this is the way you have
- // to do it
- HDC hdc;
- if (szDevice == NULL || lstrcmpiLocaleIndependentA(szDevice, "DISPLAY") == 0)
- hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
- else
- hdc = CreateDCA(NULL, szDevice, NULL, NULL);
- if (NULL == hdc) {
- return E_OUTOFMEMORY;
- }
- INT Reserved = GetDeviceCaps(hdc,NUMRESERVED);
- if (Reserved != 20) {
- DeleteDC(hdc);
- return S_FALSE;
- }
-
- // Compare our palette against the first ten system entries. The reason I
- // don't do a memory compare between our two arrays of colours is because
- // I am not sure what will be in the flags fields for the system entries
-
- UINT Result = GetSystemPaletteEntries(hdc,0,PalLoCount,SystemEntries);
- for (UINT Count = 0;Count < Result;Count++) {
- if (SystemEntries[Count].peRed != pEntry[Count].peRed ||
- SystemEntries[Count].peGreen != pEntry[Count].peGreen ||
- SystemEntries[Count].peBlue != pEntry[Count].peBlue) {
- bIdentityPalette = FALSE;
- }
- }
-
- // And likewise compare against the last ten entries
-
- Result = GetSystemPaletteEntries(hdc,PalHiStart,PalLoCount,SystemEntries);
- for (UINT Count = 0;Count < Result;Count++) {
- if (INT(Count) + PalHiStart < iColours) {
- if (SystemEntries[Count].peRed != pEntry[PalHiStart + Count].peRed ||
- SystemEntries[Count].peGreen != pEntry[PalHiStart + Count].peGreen ||
- SystemEntries[Count].peBlue != pEntry[PalHiStart + Count].peBlue) {
- bIdentityPalette = FALSE;
- }
- }
- }
-
- // If not an identity palette then return S_FALSE
-
- DeleteDC(hdc);
- if (bIdentityPalette == FALSE) {
- return S_FALSE;
- }
-
- // Set the non VGA entries so that GDI doesn't map them
-
- for (UINT Count = PalLoCount;INT(Count) < min(PalHiStart,iColours);Count++) {
- pEntry[Count].peFlags = PC_NOCOLLAPSE;
- }
- return NOERROR;
-}
-
-
-// Constructor initialises the VIDEOINFO we keep storing the current display
-// format. The format can be changed at any time, to reset the format held
-// by us call the RefreshDisplayType directly (it's a public method). Since
-// more than one thread will typically call us (ie window threads resetting
-// the type and source threads in the type checking methods) we have a lock
-
-CImageDisplay::CImageDisplay()
-{
- RefreshDisplayType(NULL);
-}
-
-
-
-// This initialises the format we hold which contains the display device type
-// We do a conversion on the display device type in here so that when we start
-// type checking input formats we can assume that certain fields have been set
-// correctly, an example is when we make the 16 bit mask fields explicit. This
-// is normally called when we receive WM_DEVMODECHANGED device change messages
-
-// The optional szDeviceName parameter tells us which monitor we are interested
-// in for a multi monitor system
-
-HRESULT CImageDisplay::RefreshDisplayType(__in_opt LPSTR szDeviceName)
-{
- CAutoLock cDisplayLock(this);
-
- // Set the preferred format type
-
- ZeroMemory((PVOID)&m_Display,sizeof(VIDEOINFOHEADER)+sizeof(TRUECOLORINFO));
- m_Display.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- m_Display.bmiHeader.biBitCount = FALSE;
-
- // Get the bit depth of a device compatible bitmap
-
- // get caps of whichever monitor they are interested in (multi monitor)
- HDC hdcDisplay;
- // it's ugly, but this is the way you have to do it
- if (szDeviceName == NULL || lstrcmpiLocaleIndependentA(szDeviceName, "DISPLAY") == 0)
- hdcDisplay = CreateDCA("DISPLAY", NULL, NULL, NULL);
- else
- hdcDisplay = CreateDCA(NULL, szDeviceName, NULL, NULL);
- if (hdcDisplay == NULL) {
- ASSERT(FALSE);
- DbgLog((LOG_ERROR,1,TEXT("ACK! Can't get a DC for %hs"),
- szDeviceName ? szDeviceName : "<NULL>"));
- return E_FAIL;
- } else {
- DbgLog((LOG_TRACE,3,TEXT("Created a DC for %s"),
- szDeviceName ? szDeviceName : "<NULL>"));
- }
- HBITMAP hbm = CreateCompatibleBitmap(hdcDisplay,1,1);
- if ( hbm )
- {
- GetDIBits(hdcDisplay,hbm,0,1,NULL,(BITMAPINFO *)&m_Display.bmiHeader,DIB_RGB_COLORS);
-
- // This call will get the colour table or the proper bitfields
- GetDIBits(hdcDisplay,hbm,0,1,NULL,(BITMAPINFO *)&m_Display.bmiHeader,DIB_RGB_COLORS);
- DeleteObject(hbm);
- }
- DeleteDC(hdcDisplay);
-
- // Complete the display type initialisation
-
- ASSERT(CheckHeaderValidity(&m_Display));
- UpdateFormat(&m_Display);
- DbgLog((LOG_TRACE,3,TEXT("New DISPLAY bit depth =%d"),
- m_Display.bmiHeader.biBitCount));
- return NOERROR;
-}
-
-
-// We assume throughout this code that any bitfields masks are allowed no
-// more than eight bits to store a colour component. This checks that the
-// bit count assumption is enforced and also makes sure that all the bits
-// set are contiguous. We return a boolean TRUE if the field checks out ok
-
-BOOL CImageDisplay::CheckBitFields(const VIDEOINFO *pInput)
-{
- DWORD *pBitFields = (DWORD *) BITMASKS(pInput);
-
- for (INT iColour = iRED;iColour <= iBLUE;iColour++) {
-
- // First of all work out how many bits are set
-
- DWORD SetBits = CountSetBits(pBitFields[iColour]);
- if (SetBits > iMAXBITS || SetBits == 0) {
- NOTE1("Bit fields for component %d invalid",iColour);
- return FALSE;
- }
-
- // Next work out the number of zero bits prefix
- DWORD PrefixBits = CountPrefixBits(pBitFields[iColour]);
-
- // This is going to see if all the bits set are contiguous (as they
- // should be). We know how much to shift them right by from the
- // count of prefix bits. The number of bits set defines a mask, we
- // invert this (ones complement) and AND it with the shifted bit
- // fields. If the result is NON zero then there are bit(s) sticking
- // out the left hand end which means they are not contiguous
-
- DWORD TestField = pBitFields[iColour] >> PrefixBits;
- DWORD Mask = ULONG_MAX << SetBits;
- if (TestField & Mask) {
- NOTE1("Bit fields for component %d not contiguous",iColour);
- return FALSE;
- }
- }
- return TRUE;
-}
-
-
-// This counts the number of bits set in the input field
-
-DWORD CImageDisplay::CountSetBits(DWORD Field)
-{
- // This is a relatively well known bit counting algorithm
-
- DWORD Count = 0;
- DWORD init = Field;
-
- // Until the input is exhausted, count the number of bits
-
- while (init) {
- init = init & (init - 1); // Turn off the bottommost bit
- Count++;
- }
- return Count;
-}
-
-
-// This counts the number of zero bits upto the first one set NOTE the input
-// field should have been previously checked to ensure there is at least one
-// set although if we don't find one set we return the impossible value 32
-
-DWORD CImageDisplay::CountPrefixBits(DWORD Field)
-{
- DWORD Mask = 1;
- DWORD Count = 0;
-
- while (TRUE) {
- if (Field & Mask) {
- return Count;
- }
- Count++;
-
- ASSERT(Mask != 0x80000000);
- if (Mask == 0x80000000) {
- return Count;
- }
- Mask <<= 1;
- }
-}
-
-
-// This is called to check the BITMAPINFOHEADER for the input type. There are
-// many implicit dependancies between the fields in a header structure which
-// if we validate now make for easier manipulation in subsequent handling. We
-// also check that the BITMAPINFOHEADER matches it's specification such that
-// fields likes the number of planes is one, that it's structure size is set
-// correctly and that the bitmap dimensions have not been set as negative
-
-BOOL CImageDisplay::CheckHeaderValidity(const VIDEOINFO *pInput)
-{
- // Check the bitmap width and height are not negative.
-
- if (pInput->bmiHeader.biWidth <= 0 ||
- pInput->bmiHeader.biHeight <= 0) {
- NOTE("Invalid bitmap dimensions");
- return FALSE;
- }
-
- // Check the compression is either BI_RGB or BI_BITFIELDS
-
- if (pInput->bmiHeader.biCompression != BI_RGB) {
- if (pInput->bmiHeader.biCompression != BI_BITFIELDS) {
- NOTE("Invalid compression format");
- return FALSE;
- }
- }
-
- // If BI_BITFIELDS compression format check the colour depth
-
- if (pInput->bmiHeader.biCompression == BI_BITFIELDS) {
- if (pInput->bmiHeader.biBitCount != 16) {
- if (pInput->bmiHeader.biBitCount != 32) {
- NOTE("BI_BITFIELDS not 16/32 bit depth");
- return FALSE;
- }
- }
- }
-
- // Check the assumptions about the layout of the bit fields
-
- if (pInput->bmiHeader.biCompression == BI_BITFIELDS) {
- if (CheckBitFields(pInput) == FALSE) {
- NOTE("Bit fields are not valid");
- return FALSE;
- }
- }
-
- // Are the number of planes equal to one
-
- if (pInput->bmiHeader.biPlanes != 1) {
- NOTE("Number of planes not one");
- return FALSE;
- }
-
- // Check the image size is consistent (it can be zero)
-
- if (pInput->bmiHeader.biSizeImage != GetBitmapSize(&pInput->bmiHeader)) {
- if (pInput->bmiHeader.biSizeImage) {
- NOTE("Image size incorrectly set");
- return FALSE;
- }
- }
-
- // Check the size of the structure
-
- if (pInput->bmiHeader.biSize != sizeof(BITMAPINFOHEADER)) {
- NOTE("Size of BITMAPINFOHEADER wrong");
- return FALSE;
- }
- return CheckPaletteHeader(pInput);
-}
-
-
-// This runs a few simple tests against the palette fields in the input to
-// see if it looks vaguely correct. The tests look at the number of palette
-// colours present, the number considered important and the biCompression
-// field which should always be BI_RGB as no other formats are meaningful
-
-BOOL CImageDisplay::CheckPaletteHeader(const VIDEOINFO *pInput)
-{
- // The checks here are for palettised videos only
-
- if (PALETTISED(pInput) == FALSE) {
- if (pInput->bmiHeader.biClrUsed) {
- NOTE("Invalid palette entries");
- return FALSE;
- }
- return TRUE;
- }
-
- // Compression type of BI_BITFIELDS is meaningless for palette video
-
- if (pInput->bmiHeader.biCompression != BI_RGB) {
- NOTE("Palettised video must be BI_RGB");
- return FALSE;
- }
-
- // Check the number of palette colours is correct
-
- if (pInput->bmiHeader.biClrUsed > PALETTE_ENTRIES(pInput)) {
- NOTE("Too many colours in palette");
- return FALSE;
- }
-
- // The number of important colours shouldn't exceed the number used
-
- if (pInput->bmiHeader.biClrImportant > pInput->bmiHeader.biClrUsed) {
- NOTE("Too many important colours");
- return FALSE;
- }
- return TRUE;
-}
-
-
-// Return the format of the video display
-
-const VIDEOINFO *CImageDisplay::GetDisplayFormat()
-{
- return &m_Display;
-}
-
-
-// Return TRUE if the display uses a palette
-
-BOOL CImageDisplay::IsPalettised()
-{
- return PALETTISED(&m_Display);
-}
-
-
-// Return the bit depth of the current display setting
-
-WORD CImageDisplay::GetDisplayDepth()
-{
- return m_Display.bmiHeader.biBitCount;
-}
-
-
-// Initialise the optional fields in a VIDEOINFO. These are mainly to do with
-// the source and destination rectangles and palette information such as the
-// number of colours present. It simplifies our code just a little if we don't
-// have to keep checking for all the different valid permutations in a header
-// every time we want to do anything with it (an example would be creating a
-// palette). We set the base class media type before calling this function so
-// that the media types between the pins match after a connection is made
-
-HRESULT CImageDisplay::UpdateFormat(__inout VIDEOINFO *pVideoInfo)
-{
- ASSERT(pVideoInfo);
-
- BITMAPINFOHEADER *pbmi = HEADER(pVideoInfo);
- SetRectEmpty(&pVideoInfo->rcSource);
- SetRectEmpty(&pVideoInfo->rcTarget);
-
- // Set the number of colours explicitly
-
- if (PALETTISED(pVideoInfo)) {
- if (pVideoInfo->bmiHeader.biClrUsed == 0) {
- pVideoInfo->bmiHeader.biClrUsed = PALETTE_ENTRIES(pVideoInfo);
- }
- }
-
- // The number of important colours shouldn't exceed the number used, on
- // some displays the number of important colours is not initialised when
- // retrieving the display type so we set the colours used correctly
-
- if (pVideoInfo->bmiHeader.biClrImportant > pVideoInfo->bmiHeader.biClrUsed) {
- pVideoInfo->bmiHeader.biClrImportant = PALETTE_ENTRIES(pVideoInfo);
- }
-
- // Change the image size field to be explicit
-
- if (pVideoInfo->bmiHeader.biSizeImage == 0) {
- pVideoInfo->bmiHeader.biSizeImage = GetBitmapSize(&pVideoInfo->bmiHeader);
- }
- return NOERROR;
-}
-
-
-// Lots of video rendering filters want code to check proposed formats are ok
-// This checks the VIDEOINFO we are passed as a media type. If the media type
-// is a valid media type then we return NOERROR otherwise E_INVALIDARG. Note
-// however we only accept formats that can be easily displayed in the display
-// so if we are on a 16 bit device we will not accept 24 bit images. The one
-// complexity is that most displays draw 8 bit palettised images efficiently
-// Also if the input format is less colour bits per pixel then we also accept
-
-HRESULT CImageDisplay::CheckVideoType(const VIDEOINFO *pInput)
-{
- // First of all check the VIDEOINFOHEADER looks correct
-
- if (CheckHeaderValidity(pInput) == FALSE) {
- return E_INVALIDARG;
- }
-
- // Virtually all devices support palettised images efficiently
-
- if (m_Display.bmiHeader.biBitCount == pInput->bmiHeader.biBitCount) {
- if (PALETTISED(pInput) == TRUE) {
- ASSERT(PALETTISED(&m_Display) == TRUE);
- NOTE("(Video) Type connection ACCEPTED");
- return NOERROR;
- }
- }
-
-
- // Is the display depth greater than the input format
-
- if (m_Display.bmiHeader.biBitCount > pInput->bmiHeader.biBitCount) {
- NOTE("(Video) Mismatch agreed");
- return NOERROR;
- }
-
- // Is the display depth less than the input format
-
- if (m_Display.bmiHeader.biBitCount < pInput->bmiHeader.biBitCount) {
- NOTE("(Video) Format mismatch");
- return E_INVALIDARG;
- }
-
-
- // Both input and display formats are either BI_RGB or BI_BITFIELDS
-
- ASSERT(m_Display.bmiHeader.biBitCount == pInput->bmiHeader.biBitCount);
- ASSERT(PALETTISED(pInput) == FALSE);
- ASSERT(PALETTISED(&m_Display) == FALSE);
-
- // BI_RGB 16 bit representation is implicitly RGB555, and likewise BI_RGB
- // 24 bit representation is RGB888. So we initialise a pointer to the bit
- // fields they really mean and check against the display device format
- // This is only going to be called when both formats are equal bits pixel
-
- const DWORD *pInputMask = GetBitMasks(pInput);
- const DWORD *pDisplayMask = GetBitMasks((VIDEOINFO *)&m_Display);
-
- if (pInputMask[iRED] != pDisplayMask[iRED] ||
- pInputMask[iGREEN] != pDisplayMask[iGREEN] ||
- pInputMask[iBLUE] != pDisplayMask[iBLUE]) {
-
- NOTE("(Video) Bit field mismatch");
- return E_INVALIDARG;
- }
-
- NOTE("(Video) Type connection ACCEPTED");
- return NOERROR;
-}
-
-
-// Return the bit masks for the true colour VIDEOINFO provided
-
-const DWORD *CImageDisplay::GetBitMasks(const VIDEOINFO *pVideoInfo)
-{
- static const DWORD FailMasks[] = {0,0,0};
-
- if (pVideoInfo->bmiHeader.biCompression == BI_BITFIELDS) {
- return BITMASKS(pVideoInfo);
- }
-
- ASSERT(pVideoInfo->bmiHeader.biCompression == BI_RGB);
-
- switch (pVideoInfo->bmiHeader.biBitCount) {
- case 16: return bits555;
- case 24: return bits888;
- case 32: return bits888;
- default: return FailMasks;
- }
-}
-
-
-// Check to see if we can support media type pmtIn as proposed by the output
-// pin - We first check that the major media type is video and also identify
-// the media sub type. Then we thoroughly check the VIDEOINFO type provided
-// As well as the contained VIDEOINFO being correct the major type must be
-// video, the subtype a recognised video format and the type GUID correct
-
-HRESULT CImageDisplay::CheckMediaType(const CMediaType *pmtIn)
-{
- // Does this have a VIDEOINFOHEADER format block
-
- const GUID *pFormatType = pmtIn->FormatType();
- if (*pFormatType != FORMAT_VideoInfo) {
- NOTE("Format GUID not a VIDEOINFOHEADER");
- return E_INVALIDARG;
- }
- ASSERT(pmtIn->Format());
-
- // Check the format looks reasonably ok
-
- ULONG Length = pmtIn->FormatLength();
- if (Length < SIZE_VIDEOHEADER) {
- NOTE("Format smaller than a VIDEOHEADER");
- return E_FAIL;
- }
-
- VIDEOINFO *pInput = (VIDEOINFO *) pmtIn->Format();
-
- // Check the major type is MEDIATYPE_Video
-
- const GUID *pMajorType = pmtIn->Type();
- if (*pMajorType != MEDIATYPE_Video) {
- NOTE("Major type not MEDIATYPE_Video");
- return E_INVALIDARG;
- }
-
- // Check we can identify the media subtype
-
- const GUID *pSubType = pmtIn->Subtype();
- if (GetBitCount(pSubType) == USHRT_MAX) {
- NOTE("Invalid video media subtype");
- return E_INVALIDARG;
- }
- return CheckVideoType(pInput);
-}
-
-
-// Given a video format described by a VIDEOINFO structure we return the mask
-// that is used to obtain the range of acceptable colours for this type, for
-// example, the mask for a 24 bit true colour format is 0xFF in all cases. A
-// 16 bit 5:6:5 display format uses 0xF8, 0xFC and 0xF8, therefore given any
-// RGB triplets we can AND them with these fields to find one that is valid
-
-BOOL CImageDisplay::GetColourMask(__out DWORD *pMaskRed,
- __out DWORD *pMaskGreen,
- __out DWORD *pMaskBlue)
-{
- CAutoLock cDisplayLock(this);
- *pMaskRed = 0xFF;
- *pMaskGreen = 0xFF;
- *pMaskBlue = 0xFF;
-
- // If this format is palettised then it doesn't have bit fields
-
- if (m_Display.bmiHeader.biBitCount < 16) {
- return FALSE;
- }
-
- // If this is a 24 bit true colour display then it can handle all the
- // possible colour component ranges described by a byte. It is never
- // allowed for a 24 bit colour depth image to have BI_BITFIELDS set
-
- if (m_Display.bmiHeader.biBitCount == 24) {
- ASSERT(m_Display.bmiHeader.biCompression == BI_RGB);
- return TRUE;
- }
-
- // Calculate the mask based on the format's bit fields
-
- const DWORD *pBitFields = (DWORD *) GetBitMasks((VIDEOINFO *)&m_Display);
- DWORD *pOutputMask[] = { pMaskRed, pMaskGreen, pMaskBlue };
-
- // We know from earlier testing that there are no more than iMAXBITS
- // bits set in the mask and that they are all contiguous. All that
- // therefore remains is to shift them into the correct position
-
- for (INT iColour = iRED;iColour <= iBLUE;iColour++) {
-
- // This works out how many bits there are and where they live
-
- DWORD PrefixBits = CountPrefixBits(pBitFields[iColour]);
- DWORD SetBits = CountSetBits(pBitFields[iColour]);
-
- // The first shift moves the bit field so that it is right justified
- // in the DWORD, after which we then shift it back left which then
- // puts the leading bit in the bytes most significant bit position
-
- *(pOutputMask[iColour]) = pBitFields[iColour] >> PrefixBits;
- *(pOutputMask[iColour]) <<= (iMAXBITS - SetBits);
- }
- return TRUE;
-}
-
-
-/* Helper to convert to VIDEOINFOHEADER2
-*/
-STDAPI ConvertVideoInfoToVideoInfo2(__inout AM_MEDIA_TYPE *pmt)
-{
- if (pmt->formattype != FORMAT_VideoInfo) {
- return E_INVALIDARG;
- }
- if (NULL == pmt->pbFormat || pmt->cbFormat < sizeof(VIDEOINFOHEADER)) {
- return E_INVALIDARG;
- }
- VIDEOINFO *pVideoInfo = (VIDEOINFO *)pmt->pbFormat;
- DWORD dwNewSize;
- HRESULT hr = DWordAdd(pmt->cbFormat, sizeof(VIDEOINFOHEADER2) - sizeof(VIDEOINFOHEADER), &dwNewSize);
- if (FAILED(hr)) {
- return hr;
- }
- PVOID pvNew = CoTaskMemAlloc(dwNewSize);
- if (pvNew == NULL) {
- return E_OUTOFMEMORY;
- }
- CopyMemory(pvNew, pmt->pbFormat, FIELD_OFFSET(VIDEOINFOHEADER, bmiHeader));
- ZeroMemory((PBYTE)pvNew + FIELD_OFFSET(VIDEOINFOHEADER, bmiHeader),
- sizeof(VIDEOINFOHEADER2) - sizeof(VIDEOINFOHEADER));
- CopyMemory((PBYTE)pvNew + FIELD_OFFSET(VIDEOINFOHEADER2, bmiHeader),
- pmt->pbFormat + FIELD_OFFSET(VIDEOINFOHEADER, bmiHeader),
- pmt->cbFormat - FIELD_OFFSET(VIDEOINFOHEADER, bmiHeader));
- VIDEOINFOHEADER2 *pVideoInfo2 = (VIDEOINFOHEADER2 *)pvNew;
- pVideoInfo2->dwPictAspectRatioX = (DWORD)pVideoInfo2->bmiHeader.biWidth;
- pVideoInfo2->dwPictAspectRatioY = (DWORD)abs(pVideoInfo2->bmiHeader.biHeight);
- pmt->formattype = FORMAT_VideoInfo2;
- CoTaskMemFree(pmt->pbFormat);
- pmt->pbFormat = (PBYTE)pvNew;
- pmt->cbFormat += sizeof(VIDEOINFOHEADER2) - sizeof(VIDEOINFOHEADER);
- return S_OK;
-}
-
-
-// Check a media type containing VIDEOINFOHEADER
-STDAPI CheckVideoInfoType(const AM_MEDIA_TYPE *pmt)
-{
- if (NULL == pmt || NULL == pmt->pbFormat) {
- return E_POINTER;
- }
- if (pmt->majortype != MEDIATYPE_Video ||
- pmt->formattype != FORMAT_VideoInfo ||
- pmt->cbFormat < sizeof(VIDEOINFOHEADER)) {
- return VFW_E_TYPE_NOT_ACCEPTED;
- }
- const VIDEOINFOHEADER *pHeader = (const VIDEOINFOHEADER *)pmt->pbFormat;
- if (!ValidateBitmapInfoHeader(
- &pHeader->bmiHeader,
- pmt->cbFormat - FIELD_OFFSET(VIDEOINFOHEADER, bmiHeader))) {
- return VFW_E_TYPE_NOT_ACCEPTED;
- }
-
- return S_OK;
-}
-
-// Check a media type containing VIDEOINFOHEADER2
-STDAPI CheckVideoInfo2Type(const AM_MEDIA_TYPE *pmt)
-{
- if (NULL == pmt || NULL == pmt->pbFormat) {
- return E_POINTER;
- }
- if (pmt->majortype != MEDIATYPE_Video ||
- pmt->formattype != FORMAT_VideoInfo2 ||
- pmt->cbFormat < sizeof(VIDEOINFOHEADER2)) {
- return VFW_E_TYPE_NOT_ACCEPTED;
- }
- const VIDEOINFOHEADER2 *pHeader = (const VIDEOINFOHEADER2 *)pmt->pbFormat;
- if (!ValidateBitmapInfoHeader(
- &pHeader->bmiHeader,
- pmt->cbFormat - FIELD_OFFSET(VIDEOINFOHEADER2, bmiHeader))) {
- return VFW_E_TYPE_NOT_ACCEPTED;
- }
-
- return S_OK;
-}
diff --git a/dll/src/baseclasses/winutil.h b/dll/src/baseclasses/winutil.h
deleted file mode 100644
index 6bd6235..0000000
--- a/dll/src/baseclasses/winutil.h
+++ /dev/null
@@ -1,419 +0,0 @@
-//------------------------------------------------------------------------------
-// File: WinUtil.h
-//
-// Desc: DirectShow base classes - defines generic handler classes.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-// Make sure that you call PrepareWindow to initialise the window after
-// the object has been constructed. It is a separate method so that
-// derived classes can override useful methods like MessageLoop. Also
-// any derived class must call DoneWithWindow in its destructor. If it
-// doesn't a message may be retrieved and call a derived class member
-// function while a thread is executing the base class destructor code
-
-#ifndef __WINUTIL__
-#define __WINUTIL__
-
-const int DEFWIDTH = 320; // Initial window width
-const int DEFHEIGHT = 240; // Initial window height
-const int CAPTION = 256; // Maximum length of caption
-const int TIMELENGTH = 50; // Maximum length of times
-const int PROFILESTR = 128; // Normal profile string
-const WORD PALVERSION = 0x300; // GDI palette version
-const LONG PALETTE_VERSION = (LONG) 1; // Initial palette version
-const COLORREF VIDEO_COLOUR = 0; // Defaults to black background
-const HANDLE hMEMORY = (HANDLE) (-1); // Says to open as memory file
-
-#define WIDTH(x) ((*(x)).right - (*(x)).left)
-#define HEIGHT(x) ((*(x)).bottom - (*(x)).top)
-#define SHOWSTAGE TEXT("WM_SHOWSTAGE")
-#define SHOWSTAGETOP TEXT("WM_SHOWSTAGETOP")
-#define REALIZEPALETTE TEXT("WM_REALIZEPALETTE")
-
-class AM_NOVTABLE CBaseWindow
-{
-protected:
-
- HINSTANCE m_hInstance; // Global module instance handle
- HWND m_hwnd; // Handle for our window
- HDC m_hdc; // Device context for the window
- LONG m_Width; // Client window width
- LONG m_Height; // Client window height
- BOOL m_bActivated; // Has the window been activated
- LPTSTR m_pClassName; // Static string holding class name
- DWORD m_ClassStyles; // Passed in to our constructor
- DWORD m_WindowStyles; // Likewise the initial window styles
- DWORD m_WindowStylesEx; // And the extended window styles
- UINT m_ShowStageMessage; // Have the window shown with focus
- UINT m_ShowStageTop; // Makes the window WS_EX_TOPMOST
- UINT m_RealizePalette; // Makes us realize our new palette
- HDC m_MemoryDC; // Used for fast BitBlt operations
- HPALETTE m_hPalette; // Handle to any palette we may have
- BYTE m_bNoRealize; // Don't realize palette now
- BYTE m_bBackground; // Should we realise in background
- BYTE m_bRealizing; // already realizing the palette
- CCritSec m_WindowLock; // Serialise window object access
- BOOL m_bDoGetDC; // Should this window get a DC
- bool m_bDoPostToDestroy; // Use PostMessage to destroy
- CCritSec m_PaletteLock; // This lock protects m_hPalette.
- // It should be held anytime the
- // program use the value of m_hPalette.
-
- // Maps windows message procedure into C++ methods
- friend LRESULT CALLBACK WndProc(HWND hwnd, // Window handle
- UINT uMsg, // Message ID
- WPARAM wParam, // First parameter
- LPARAM lParam); // Other parameter
-
- virtual LRESULT OnPaletteChange(HWND hwnd, UINT Message);
-
-public:
-
- CBaseWindow(BOOL bDoGetDC = TRUE, bool bPostToDestroy = false);
-
-#ifdef DEBUG
- virtual ~CBaseWindow();
-#endif
-
- virtual HRESULT DoneWithWindow();
- virtual HRESULT PrepareWindow();
- virtual HRESULT InactivateWindow();
- virtual HRESULT ActivateWindow();
- virtual BOOL OnSize(LONG Width, LONG Height);
- virtual BOOL OnClose();
- virtual RECT GetDefaultRect();
- virtual HRESULT UninitialiseWindow();
- virtual HRESULT InitialiseWindow(HWND hwnd);
-
- HRESULT CompleteConnect();
- HRESULT DoCreateWindow();
-
- HRESULT PerformanceAlignWindow();
- HRESULT DoShowWindow(LONG ShowCmd);
- void PaintWindow(BOOL bErase);
- void DoSetWindowForeground(BOOL bFocus);
- virtual HRESULT SetPalette(HPALETTE hPalette);
- void SetRealize(BOOL bRealize)
- {
- m_bNoRealize = !bRealize;
- }
-
- // Jump over to the window thread to set the current palette
- HRESULT SetPalette();
- void UnsetPalette(void);
- virtual HRESULT DoRealisePalette(BOOL bForceBackground = FALSE);
-
- void LockPaletteLock();
- void UnlockPaletteLock();
-
- virtual BOOL PossiblyEatMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
- { return FALSE; };
-
- // Access our window information
-
- bool WindowExists();
- LONG GetWindowWidth();
- LONG GetWindowHeight();
- HWND GetWindowHWND();
- HDC GetMemoryHDC();
- HDC GetWindowHDC();
-
- #ifdef DEBUG
- HPALETTE GetPalette();
- #endif // DEBUG
-
- // This is the window procedure the derived object should override
-
- virtual LRESULT OnReceiveMessage(HWND hwnd, // Window handle
- UINT uMsg, // Message ID
- WPARAM wParam, // First parameter
- LPARAM lParam); // Other parameter
-
- // Must be overriden to return class and window styles
-
- virtual LPTSTR GetClassWindowStyles(
- __out DWORD *pClassStyles, // Class styles
- __out DWORD *pWindowStyles, // Window styles
- __out DWORD *pWindowStylesEx) PURE; // Extended styles
-};
-
-
-// This helper class is entirely subservient to the owning CBaseWindow object
-// All this object does is to split out the actual drawing operation from the
-// main object (because it was becoming too large). We have a number of entry
-// points to set things like the draw device contexts, to implement the actual
-// drawing and to set the destination rectangle in the client window. We have
-// no critical section locking in this class because we are used exclusively
-// by the owning window object which looks after serialising calls into us
-
-// If you want to use this class make sure you call NotifyAllocator once the
-// allocate has been agreed, also call NotifyMediaType with a pointer to a
-// NON stack based CMediaType once that has been set (we keep a pointer to
-// the original rather than taking a copy). When the palette changes call
-// IncrementPaletteVersion (easiest thing to do is to also call this method
-// in the SetMediaType method most filters implement). Finally before you
-// start rendering anything call SetDrawContext so that we can get the HDCs
-// for drawing from the CBaseWindow object we are given during construction
-
-class CDrawImage
-{
-protected:
-
- CBaseWindow *m_pBaseWindow; // Owning video window object
- CRefTime m_StartSample; // Start time for the current sample
- CRefTime m_EndSample; // And likewise it's end sample time
- HDC m_hdc; // Main window device context
- HDC m_MemoryDC; // Offscreen draw device context
- RECT m_TargetRect; // Target destination rectangle
- RECT m_SourceRect; // Source image rectangle
- BOOL m_bStretch; // Do we have to stretch the images
- BOOL m_bUsingImageAllocator; // Are the samples shared DIBSECTIONs
- CMediaType *m_pMediaType; // Pointer to the current format
- int m_perfidRenderTime; // Time taken to render an image
- LONG m_PaletteVersion; // Current palette version cookie
-
- // Draw the video images in the window
-
- void SlowRender(IMediaSample *pMediaSample);
- void FastRender(IMediaSample *pMediaSample);
- void DisplaySampleTimes(IMediaSample *pSample);
- void UpdateColourTable(HDC hdc,__in BITMAPINFOHEADER *pbmi);
- void SetStretchMode();
-
-public:
-
- // Used to control the image drawing
-
- CDrawImage(__inout CBaseWindow *pBaseWindow);
- BOOL DrawImage(IMediaSample *pMediaSample);
- BOOL DrawVideoImageHere(HDC hdc, IMediaSample *pMediaSample,
- __in LPRECT lprcSrc, __in LPRECT lprcDst);
- void SetDrawContext();
- void SetTargetRect(__in RECT *pTargetRect);
- void SetSourceRect(__in RECT *pSourceRect);
- void GetTargetRect(__out RECT *pTargetRect);
- void GetSourceRect(__out RECT *pSourceRect);
- virtual RECT ScaleSourceRect(const RECT *pSource);
-
- // Handle updating palettes as they change
-
- LONG GetPaletteVersion();
- void ResetPaletteVersion();
- void IncrementPaletteVersion();
-
- // Tell us media types and allocator assignments
-
- void NotifyAllocator(BOOL bUsingImageAllocator);
- void NotifyMediaType(__in CMediaType *pMediaType);
- BOOL UsingImageAllocator();
-
- // Called when we are about to draw an image
-
- void NotifyStartDraw() {
- MSR_START(m_perfidRenderTime);
- };
-
- // Called when we complete an image rendering
-
- void NotifyEndDraw() {
- MSR_STOP(m_perfidRenderTime);
- };
-};
-
-
-// This is the structure used to keep information about each GDI DIB. All the
-// samples we create from our allocator will have a DIBSECTION allocated to
-// them. When we receive the sample we know we can BitBlt straight to an HDC
-
-typedef struct tagDIBDATA {
-
- LONG PaletteVersion; // Current palette version in use
- DIBSECTION DibSection; // Details of DIB section allocated
- HBITMAP hBitmap; // Handle to bitmap for drawing
- HANDLE hMapping; // Handle to shared memory block
- BYTE *pBase; // Pointer to base memory address
-
-} DIBDATA;
-
-
-// This class inherits from CMediaSample and uses all of it's methods but it
-// overrides the constructor to initialise itself with the DIBDATA structure
-// When we come to render an IMediaSample we will know if we are using our own
-// allocator, and if we are, we can cast the IMediaSample to a pointer to one
-// of these are retrieve the DIB section information and hence the HBITMAP
-
-class CImageSample : public CMediaSample
-{
-protected:
-
- DIBDATA m_DibData; // Information about the DIBSECTION
- BOOL m_bInit; // Is the DIB information setup
-
-public:
-
- // Constructor
-
- CImageSample(__inout CBaseAllocator *pAllocator,
- __in_opt LPCTSTR pName,
- __inout HRESULT *phr,
- __in_bcount(length) LPBYTE pBuffer,
- LONG length);
-
- // Maintain the DIB/DirectDraw state
-
- void SetDIBData(__in DIBDATA *pDibData);
- __out DIBDATA *GetDIBData();
-};
-
-
-// This is an allocator based on the abstract CBaseAllocator base class that
-// allocates sample buffers in shared memory. The number and size of these
-// are determined when the output pin calls Prepare on us. The shared memory
-// blocks are used in subsequent calls to GDI CreateDIBSection, once that
-// has been done the output pin can fill the buffers with data which will
-// then be handed to GDI through BitBlt calls and thereby remove one copy
-
-class CImageAllocator : public CBaseAllocator
-{
-protected:
-
- CBaseFilter *m_pFilter; // Delegate reference counts to
- CMediaType *m_pMediaType; // Pointer to the current format
-
- // Used to create and delete samples
-
- HRESULT Alloc();
- void Free();
-
- // Manage the shared DIBSECTION and DCI/DirectDraw buffers
-
- HRESULT CreateDIB(LONG InSize,DIBDATA &DibData);
- STDMETHODIMP CheckSizes(__in ALLOCATOR_PROPERTIES *pRequest);
- virtual CImageSample *CreateImageSample(__in_bcount(Length) LPBYTE pData,LONG Length);
-
-public:
-
- // Constructor and destructor
-
- CImageAllocator(__inout CBaseFilter *pFilter,__in_opt LPCTSTR pName,__inout HRESULT *phr);
-#ifdef DEBUG
- ~CImageAllocator();
-#endif
-
- STDMETHODIMP_(ULONG) NonDelegatingAddRef();
- STDMETHODIMP_(ULONG) NonDelegatingRelease();
- void NotifyMediaType(__in CMediaType *pMediaType);
-
- // Agree the number of buffers to be used and their size
-
- STDMETHODIMP SetProperties(
- __in ALLOCATOR_PROPERTIES *pRequest,
- __out ALLOCATOR_PROPERTIES *pActual);
-};
-
-
-// This class is a fairly specialised helper class for image renderers that
-// have to create and manage palettes. The CBaseWindow class looks after
-// realising palettes once they have been installed. This class can be used
-// to create the palette handles from a media format (which must contain a
-// VIDEOINFO structure in the format block). We try to make the palette an
-// identity palette to maximise performance and also only change palettes
-// if actually required to (we compare palette colours before updating).
-// All the methods are virtual so that they can be overriden if so required
-
-class CImagePalette
-{
-protected:
-
- CBaseWindow *m_pBaseWindow; // Window to realise palette in
- CBaseFilter *m_pFilter; // Media filter to send events
- CDrawImage *m_pDrawImage; // Object who will be drawing
- HPALETTE m_hPalette; // The palette handle we own
-
-public:
-
- CImagePalette(__inout CBaseFilter *pBaseFilter,
- __inout CBaseWindow *pBaseWindow,
- __inout CDrawImage *pDrawImage);
-
-#ifdef DEBUG
- virtual ~CImagePalette();
-#endif
-
- static HPALETTE MakePalette(const VIDEOINFOHEADER *pVideoInfo, __in LPSTR szDevice);
- HRESULT RemovePalette();
- static HRESULT MakeIdentityPalette(__inout_ecount_full(iColours) PALETTEENTRY *pEntry,INT iColours, __in LPSTR szDevice);
- HRESULT CopyPalette(const CMediaType *pSrc,__out CMediaType *pDest);
- BOOL ShouldUpdate(const VIDEOINFOHEADER *pNewInfo,const VIDEOINFOHEADER *pOldInfo);
- HRESULT PreparePalette(const CMediaType *pmtNew,const CMediaType *pmtOld,__in LPSTR szDevice);
-
- BOOL DrawVideoImageHere(HDC hdc, IMediaSample *pMediaSample, __in LPRECT lprcSrc, __in LPRECT lprcDst)
- {
- return m_pDrawImage->DrawVideoImageHere(hdc, pMediaSample, lprcSrc,lprcDst);
- }
-};
-
-
-// Another helper class really for video based renderers. Most such renderers
-// need to know what the display format is to some degree or another. This
-// class initialises itself with the display format. The format can be asked
-// for through GetDisplayFormat and various other accessor functions. If a
-// filter detects a display format change (perhaps it gets a WM_DEVMODECHANGE
-// message then it can call RefreshDisplayType to reset that format). Also
-// many video renderers will want to check formats as they are proposed by
-// source filters. This class provides methods to check formats and only
-// accept those video formats that can be efficiently drawn using GDI calls
-
-class CImageDisplay : public CCritSec
-{
-protected:
-
- // This holds the display format; biSize should not be too big, so we can
- // safely use the VIDEOINFO structure
- VIDEOINFO m_Display;
-
- static DWORD CountSetBits(const DWORD Field);
- static DWORD CountPrefixBits(const DWORD Field);
- static BOOL CheckBitFields(const VIDEOINFO *pInput);
-
-public:
-
- // Constructor and destructor
-
- CImageDisplay();
-
- // Used to manage BITMAPINFOHEADERs and the display format
-
- const VIDEOINFO *GetDisplayFormat();
- HRESULT RefreshDisplayType(__in_opt LPSTR szDeviceName);
- static BOOL CheckHeaderValidity(const VIDEOINFO *pInput);
- static BOOL CheckPaletteHeader(const VIDEOINFO *pInput);
- BOOL IsPalettised();
- WORD GetDisplayDepth();
-
- // Provide simple video format type checking
-
- HRESULT CheckMediaType(const CMediaType *pmtIn);
- HRESULT CheckVideoType(const VIDEOINFO *pInput);
- HRESULT UpdateFormat(__inout VIDEOINFO *pVideoInfo);
- const DWORD *GetBitMasks(const VIDEOINFO *pVideoInfo);
-
- BOOL GetColourMask(__out DWORD *pMaskRed,
- __out DWORD *pMaskGreen,
- __out DWORD *pMaskBlue);
-};
-
-// Convert a FORMAT_VideoInfo to FORMAT_VideoInfo2
-STDAPI ConvertVideoInfoToVideoInfo2(__inout AM_MEDIA_TYPE *pmt);
-
-// Check a media type containing VIDEOINFOHEADER
-STDAPI CheckVideoInfoType(const AM_MEDIA_TYPE *pmt);
-
-// Check a media type containing VIDEOINFOHEADER
-STDAPI CheckVideoInfo2Type(const AM_MEDIA_TYPE *pmt);
-
-#endif // __WINUTIL__
-
diff --git a/dll/src/baseclasses/wxdebug.cpp b/dll/src/baseclasses/wxdebug.cpp
deleted file mode 100644
index 0beec2a..0000000
--- a/dll/src/baseclasses/wxdebug.cpp
+++ /dev/null
@@ -1,1472 +0,0 @@
-//------------------------------------------------------------------------------
-// File: WXDebug.cpp
-//
-// Desc: DirectShow base classes - implements ActiveX system debugging
-// facilities.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-#include <streams.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <dvdmedia.h>
-
-#ifdef DEBUG
-#ifdef UNICODE
-#ifndef _UNICODE
-#define _UNICODE
-#endif // _UNICODE
-#endif // UNICODE
-#endif // DEBUG
-
-#include <tchar.h>
-#include <strsafe.h>
-
-#ifdef DEBUG
-static void DisplayBITMAPINFO(const BITMAPINFOHEADER* pbmi);
-static void DisplayRECT(LPCTSTR szLabel, const RECT& rc);
-
-// The Win32 wsprintf() function writes a maximum of 1024 characters to it's output buffer.
-// See the documentation for wsprintf()'s lpOut parameter for more information.
-const INT iDEBUGINFO = 1024; // Used to format strings
-
-/* For every module and executable we store a debugging level for each of
- the five categories (eg LOG_ERROR and LOG_TIMING). This makes it easy
- to isolate and debug individual modules without seeing everybody elses
- spurious debug output. The keys are stored in the registry under the
- HKEY_LOCAL_MACHINE\SOFTWARE\Debug\<Module Name>\<KeyName> key values
- NOTE these must be in the same order as their enumeration definition */
-
-const LPCTSTR pKeyNames[] = {
- TEXT("TIMING"), // Timing and performance measurements
- TEXT("TRACE"), // General step point call tracing
- TEXT("MEMORY"), // Memory and object allocation/destruction
- TEXT("LOCKING"), // Locking/unlocking of critical sections
- TEXT("ERROR"), // Debug error notification
- TEXT("CUSTOM1"),
- TEXT("CUSTOM2"),
- TEXT("CUSTOM3"),
- TEXT("CUSTOM4"),
- TEXT("CUSTOM5")
- };
-
-const TCHAR CAutoTrace::_szEntering[] = TEXT("->: %s");
-const TCHAR CAutoTrace::_szLeaving[] = TEXT("<-: %s");
-
-const INT iMAXLEVELS = NUMELMS(pKeyNames); // Maximum debug categories
-
-HINSTANCE m_hInst; // Module instance handle
-TCHAR m_ModuleName[iDEBUGINFO]; // Cut down module name
-DWORD m_Levels[iMAXLEVELS]; // Debug level per category
-CRITICAL_SECTION m_CSDebug; // Controls access to list
-DWORD m_dwNextCookie; // Next active object ID
-ObjectDesc *pListHead = NULL; // First active object
-DWORD m_dwObjectCount; // Active object count
-BOOL m_bInit = FALSE; // Have we been initialised
-HANDLE m_hOutput = INVALID_HANDLE_VALUE; // Optional output written here
-DWORD dwWaitTimeout = INFINITE; // Default timeout value
-DWORD dwTimeOffset; // Time of first DbgLog call
-bool g_fUseKASSERT = false; // don't create messagebox
-bool g_fDbgInDllEntryPoint = false;
-bool g_fAutoRefreshLevels = false;
-
-LPCTSTR pBaseKey = TEXT("SOFTWARE\\Microsoft\\DirectShow\\Debug");
-LPCTSTR pGlobalKey = TEXT("GLOBAL");
-static CHAR *pUnknownName = "UNKNOWN";
-
-LPCTSTR TimeoutName = TEXT("TIMEOUT");
-
-/* This sets the instance handle that the debug library uses to find
- the module's file name from the Win32 GetModuleFileName function */
-
-void WINAPI DbgInitialise(HINSTANCE hInst)
-{
- InitializeCriticalSection(&m_CSDebug);
- m_bInit = TRUE;
-
- m_hInst = hInst;
- DbgInitModuleName();
- if (GetProfileInt(m_ModuleName, TEXT("BreakOnLoad"), 0))
- DebugBreak();
- DbgInitModuleSettings(false);
- DbgInitGlobalSettings(true);
- dwTimeOffset = timeGetTime();
-}
-
-
-/* This is called to clear up any resources the debug library uses - at the
- moment we delete our critical section and the object list. The values we
- retrieve from the registry are all done during initialisation but we don't
- go looking for update notifications while we are running, if the values
- are changed then the application has to be restarted to pick them up */
-
-void WINAPI DbgTerminate()
-{
- if (m_hOutput != INVALID_HANDLE_VALUE) {
- EXECUTE_ASSERT(CloseHandle(m_hOutput));
- m_hOutput = INVALID_HANDLE_VALUE;
- }
- DeleteCriticalSection(&m_CSDebug);
- m_bInit = FALSE;
-}
-
-
-/* This is called by DbgInitLogLevels to read the debug settings
- for each logging category for this module from the registry */
-
-void WINAPI DbgInitKeyLevels(HKEY hKey, bool fTakeMax)
-{
- LONG lReturn; // Create key return value
- LONG lKeyPos; // Current key category
- DWORD dwKeySize; // Size of the key value
- DWORD dwKeyType; // Receives it's type
- DWORD dwKeyValue; // This fields value
-
- /* Try and read a value for each key position in turn */
- for (lKeyPos = 0;lKeyPos < iMAXLEVELS;lKeyPos++) {
-
- dwKeySize = sizeof(DWORD);
- lReturn = RegQueryValueEx(
- hKey, // Handle to an open key
- pKeyNames[lKeyPos], // Subkey name derivation
- NULL, // Reserved field
- &dwKeyType, // Returns the field type
- (LPBYTE) &dwKeyValue, // Returns the field's value
- &dwKeySize ); // Number of bytes transferred
-
- /* If either the key was not available or it was not a DWORD value
- then we ensure only the high priority debug logging is output
- but we try and update the field to a zero filled DWORD value */
-
- if (lReturn != ERROR_SUCCESS || dwKeyType != REG_DWORD) {
-
- dwKeyValue = 0;
- lReturn = RegSetValueEx(
- hKey, // Handle of an open key
- pKeyNames[lKeyPos], // Address of subkey name
- (DWORD) 0, // Reserved field
- REG_DWORD, // Type of the key field
- (PBYTE) &dwKeyValue, // Value for the field
- sizeof(DWORD)); // Size of the field buffer
-
- if (lReturn != ERROR_SUCCESS) {
- DbgLog((LOG_ERROR,1,TEXT("Could not create subkey %s"),pKeyNames[lKeyPos]));
- dwKeyValue = 0;
- }
- }
- if(fTakeMax)
- {
- m_Levels[lKeyPos] = max(dwKeyValue,m_Levels[lKeyPos]);
- }
- else
- {
- if((m_Levels[lKeyPos] & LOG_FORCIBLY_SET) == 0) {
- m_Levels[lKeyPos] = dwKeyValue;
- }
- }
- }
-
- /* Read the timeout value for catching hangs */
- dwKeySize = sizeof(DWORD);
- lReturn = RegQueryValueEx(
- hKey, // Handle to an open key
- TimeoutName, // Subkey name derivation
- NULL, // Reserved field
- &dwKeyType, // Returns the field type
- (LPBYTE) &dwWaitTimeout, // Returns the field's value
- &dwKeySize ); // Number of bytes transferred
-
- /* If either the key was not available or it was not a DWORD value
- then we ensure only the high priority debug logging is output
- but we try and update the field to a zero filled DWORD value */
-
- if (lReturn != ERROR_SUCCESS || dwKeyType != REG_DWORD) {
-
- dwWaitTimeout = INFINITE;
- lReturn = RegSetValueEx(
- hKey, // Handle of an open key
- TimeoutName, // Address of subkey name
- (DWORD) 0, // Reserved field
- REG_DWORD, // Type of the key field
- (PBYTE) &dwWaitTimeout, // Value for the field
- sizeof(DWORD)); // Size of the field buffer
-
- if (lReturn != ERROR_SUCCESS) {
- DbgLog((LOG_ERROR,1,TEXT("Could not create subkey %s"),pKeyNames[lKeyPos]));
- dwWaitTimeout = INFINITE;
- }
- }
-}
-
-void WINAPI DbgOutString(LPCTSTR psz)
-{
- if (m_hOutput != INVALID_HANDLE_VALUE) {
- UINT cb = lstrlen(psz);
- DWORD dw;
-#ifdef UNICODE
- CHAR szDest[2048];
- WideCharToMultiByte(CP_ACP, 0, psz, -1, szDest, NUMELMS(szDest), 0, 0);
- WriteFile (m_hOutput, szDest, cb, &dw, NULL);
-#else
- WriteFile (m_hOutput, psz, cb, &dw, NULL);
-#endif
- } else {
- OutputDebugString (psz);
- }
-}
-
-
-
-
-HRESULT DbgUniqueProcessName(LPCTSTR inName, LPTSTR outName)
-{
- HRESULT hr = S_OK;
- const TCHAR *pIn = inName;
- int dotPos = -1;
-
- //scan the input and record the last '.' position
- while (*pIn && (pIn - inName) < MAX_PATH)
- {
- if ( TEXT('.') == *pIn )
- dotPos = (int)(pIn-inName);
- ++pIn;
- }
-
- if (*pIn) //input should be zero-terminated within MAX_PATH
- return E_INVALIDARG;
-
- DWORD dwProcessId = GetCurrentProcessId();
-
- if (dotPos < 0)
- {
- //no extension in the input, appending process id to the input
- hr = StringCchPrintf(outName, MAX_PATH, TEXT("%s_%d"), inName, dwProcessId);
- }
- else
- {
- TCHAR pathAndBasename[MAX_PATH] = {0};
-
- //there's an extension - zero-terminate the path and basename first by copying
- hr = StringCchCopyN(pathAndBasename, MAX_PATH, inName, (size_t)dotPos);
-
- //re-combine path, basename and extension with processId appended to a basename
- if (SUCCEEDED(hr))
- hr = StringCchPrintf(outName, MAX_PATH, TEXT("%s_%d%s"), pathAndBasename, dwProcessId, inName + dotPos);
- }
-
- return hr;
-}
-
-
-/* Called by DbgInitGlobalSettings to setup alternate logging destinations
- */
-
-void WINAPI DbgInitLogTo (
- HKEY hKey)
-{
- LONG lReturn;
- DWORD dwKeyType;
- DWORD dwKeySize;
- TCHAR szFile[MAX_PATH] = {0};
- static const TCHAR cszKey[] = TEXT("LogToFile");
-
- dwKeySize = MAX_PATH;
- lReturn = RegQueryValueEx(
- hKey, // Handle to an open key
- cszKey, // Subkey name derivation
- NULL, // Reserved field
- &dwKeyType, // Returns the field type
- (LPBYTE) szFile, // Returns the field's value
- &dwKeySize); // Number of bytes transferred
-
- // create an empty key if it does not already exist
- //
- if (lReturn != ERROR_SUCCESS || dwKeyType != REG_SZ)
- {
- dwKeySize = sizeof(TCHAR);
- lReturn = RegSetValueEx(
- hKey, // Handle of an open key
- cszKey, // Address of subkey name
- (DWORD) 0, // Reserved field
- REG_SZ, // Type of the key field
- (PBYTE)szFile, // Value for the field
- dwKeySize); // Size of the field buffer
- }
-
- // if an output-to was specified. try to open it.
- //
- if (m_hOutput != INVALID_HANDLE_VALUE) {
- EXECUTE_ASSERT(CloseHandle (m_hOutput));
- m_hOutput = INVALID_HANDLE_VALUE;
- }
- if (szFile[0] != 0)
- {
- if (!lstrcmpi(szFile, TEXT("Console"))) {
- m_hOutput = GetStdHandle (STD_OUTPUT_HANDLE);
- if (m_hOutput == INVALID_HANDLE_VALUE) {
- AllocConsole ();
- m_hOutput = GetStdHandle (STD_OUTPUT_HANDLE);
- }
- SetConsoleTitle (TEXT("ActiveX Debug Output"));
- } else if (szFile[0] &&
- lstrcmpi(szFile, TEXT("Debug")) &&
- lstrcmpi(szFile, TEXT("Debugger")) &&
- lstrcmpi(szFile, TEXT("Deb")))
- {
- m_hOutput = CreateFile(szFile, GENERIC_WRITE,
- FILE_SHARE_READ,
- NULL, OPEN_ALWAYS,
- FILE_ATTRIBUTE_NORMAL,
- NULL);
-
- if (INVALID_HANDLE_VALUE == m_hOutput &&
- GetLastError() == ERROR_SHARING_VIOLATION)
- {
- TCHAR uniqueName[MAX_PATH] = {0};
- if (SUCCEEDED(DbgUniqueProcessName(szFile, uniqueName)))
- {
- m_hOutput = CreateFile(uniqueName, GENERIC_WRITE,
- FILE_SHARE_READ,
- NULL, OPEN_ALWAYS,
- FILE_ATTRIBUTE_NORMAL,
- NULL);
- }
- }
-
- if (INVALID_HANDLE_VALUE != m_hOutput)
- {
- static const TCHAR cszBar[] = TEXT("\r\n\r\n=====DbgInitialize()=====\r\n\r\n");
- SetFilePointer (m_hOutput, 0, NULL, FILE_END);
- DbgOutString (cszBar);
- }
- }
- }
-}
-
-
-
-/* This is called by DbgInitLogLevels to read the global debug settings for
- each logging category for this module from the registry. Normally each
- module has it's own values set for it's different debug categories but
- setting the global SOFTWARE\Debug\Global applies them to ALL modules */
-
-void WINAPI DbgInitGlobalSettings(bool fTakeMax)
-{
- LONG lReturn; // Create key return value
- TCHAR szInfo[iDEBUGINFO]; // Constructs key names
- HKEY hGlobalKey; // Global override key
-
- /* Construct the global base key name */
- (void)StringCchPrintf(szInfo,NUMELMS(szInfo),TEXT("%s\\%s"),pBaseKey,pGlobalKey);
-
- /* Create or open the key for this module */
- lReturn = RegCreateKeyEx(HKEY_LOCAL_MACHINE, // Handle of an open key
- szInfo, // Address of subkey name
- (DWORD) 0, // Reserved value
- NULL, // Address of class name
- (DWORD) 0, // Special options flags
- GENERIC_READ | GENERIC_WRITE, // Desired security access
- NULL, // Key security descriptor
- &hGlobalKey, // Opened handle buffer
- NULL); // What really happened
-
- if (lReturn != ERROR_SUCCESS) {
- lReturn = RegCreateKeyEx(HKEY_LOCAL_MACHINE, // Handle of an open key
- szInfo, // Address of subkey name
- (DWORD) 0, // Reserved value
- NULL, // Address of class name
- (DWORD) 0, // Special options flags
- GENERIC_READ, // Desired security access
- NULL, // Key security descriptor
- &hGlobalKey, // Opened handle buffer
- NULL); // What really happened
- if (lReturn != ERROR_SUCCESS) {
- DbgLog((LOG_ERROR,1,TEXT("Could not access GLOBAL module key")));
- }
- return;
- }
-
- DbgInitKeyLevels(hGlobalKey, fTakeMax);
- RegCloseKey(hGlobalKey);
-}
-
-
-/* This sets the debugging log levels for the different categories. We start
- by opening (or creating if not already available) the SOFTWARE\Debug key
- that all these settings live under. We then look at the global values
- set under SOFTWARE\Debug\Global which apply on top of the individual
- module settings. We then load the individual module registry settings */
-
-void WINAPI DbgInitModuleSettings(bool fTakeMax)
-{
- LONG lReturn; // Create key return value
- TCHAR szInfo[iDEBUGINFO]; // Constructs key names
- HKEY hModuleKey; // Module key handle
-
- /* Construct the base key name */
- (void)StringCchPrintf(szInfo,NUMELMS(szInfo),TEXT("%s\\%s"),pBaseKey,m_ModuleName);
-
- /* Create or open the key for this module */
- lReturn = RegCreateKeyEx(HKEY_LOCAL_MACHINE, // Handle of an open key
- szInfo, // Address of subkey name
- (DWORD) 0, // Reserved value
- NULL, // Address of class name
- (DWORD) 0, // Special options flags
- GENERIC_READ | GENERIC_WRITE, // Desired security access
- NULL, // Key security descriptor
- &hModuleKey, // Opened handle buffer
- NULL); // What really happened
-
- if (lReturn != ERROR_SUCCESS) {
- lReturn = RegCreateKeyEx(HKEY_LOCAL_MACHINE, // Handle of an open key
- szInfo, // Address of subkey name
- (DWORD) 0, // Reserved value
- NULL, // Address of class name
- (DWORD) 0, // Special options flags
- GENERIC_READ, // Desired security access
- NULL, // Key security descriptor
- &hModuleKey, // Opened handle buffer
- NULL); // What really happened
- if (lReturn != ERROR_SUCCESS) {
- DbgLog((LOG_ERROR,1,TEXT("Could not access module key")));
- }
- return;
- }
-
- DbgInitLogTo(hModuleKey);
- DbgInitKeyLevels(hModuleKey, fTakeMax);
- RegCloseKey(hModuleKey);
-}
-
-
-/* Initialise the module file name */
-
-void WINAPI DbgInitModuleName()
-{
- TCHAR FullName[iDEBUGINFO]; // Load the full path and module name
- LPTSTR pName; // Searches from the end for a backslash
-
- GetModuleFileName(m_hInst,FullName,iDEBUGINFO);
- pName = _tcsrchr(FullName,'\\');
- if (pName == NULL) {
- pName = FullName;
- } else {
- pName++;
- }
- (void)StringCchCopy(m_ModuleName,NUMELMS(m_ModuleName), pName);
-}
-
-struct MsgBoxMsg
-{
- HWND hwnd;
- LPCTSTR szTitle;
- LPCTSTR szMessage;
- DWORD dwFlags;
- INT iResult;
-};
-
-//
-// create a thread to call MessageBox(). calling MessageBox() on
-// random threads at bad times can confuse the host (eg IE).
-//
-DWORD WINAPI MsgBoxThread(
- __inout LPVOID lpParameter // thread data
- )
-{
- MsgBoxMsg *pmsg = (MsgBoxMsg *)lpParameter;
- pmsg->iResult = MessageBox(
- pmsg->hwnd,
- pmsg->szTitle,
- pmsg->szMessage,
- pmsg->dwFlags);
-
- return 0;
-}
-
-INT MessageBoxOtherThread(
- HWND hwnd,
- LPCTSTR szTitle,
- LPCTSTR szMessage,
- DWORD dwFlags)
-{
- if(g_fDbgInDllEntryPoint)
- {
- // can't wait on another thread because we have the loader
- // lock held in the dll entry point.
- // This can crash sometimes so just skip it
- // return MessageBox(hwnd, szTitle, szMessage, dwFlags);
- return IDCANCEL;
- }
- else
- {
- MsgBoxMsg msg = {hwnd, szTitle, szMessage, dwFlags, 0};
- DWORD dwid;
- HANDLE hThread = CreateThread(
- 0, // security
- 0, // stack size
- MsgBoxThread,
- (void *)&msg, // arg
- 0, // flags
- &dwid);
- if(hThread)
- {
- WaitForSingleObject(hThread, INFINITE);
- CloseHandle(hThread);
- return msg.iResult;
- }
-
- // break into debugger on failure.
- return IDCANCEL;
- }
-}
-
-/* Displays a message box if the condition evaluated to FALSE */
-
-void WINAPI DbgAssert(LPCTSTR pCondition,LPCTSTR pFileName,INT iLine)
-{
- if(g_fUseKASSERT)
- {
- DbgKernelAssert(pCondition, pFileName, iLine);
- }
- else
- {
-
- TCHAR szInfo[iDEBUGINFO];
-
- (void)StringCchPrintf(szInfo, NUMELMS(szInfo),TEXT("%s \nAt line %d of %s\nContinue? (Cancel to debug)"),
- pCondition, iLine, pFileName);
-
- INT MsgId = MessageBoxOtherThread(NULL,szInfo,TEXT("ASSERT Failed"),
- MB_SYSTEMMODAL |
- MB_ICONHAND |
- MB_YESNOCANCEL |
- MB_SETFOREGROUND);
- switch (MsgId)
- {
- case IDNO: /* Kill the application */
-
- FatalAppExit(FALSE, TEXT("Application terminated"));
- break;
-
- case IDCANCEL: /* Break into the debugger */
-
- DebugBreak();
- break;
-
- case IDYES: /* Ignore assertion continue execution */
- break;
- }
- }
-}
-
-/* Displays a message box at a break point */
-
-void WINAPI DbgBreakPoint(LPCTSTR pCondition,LPCTSTR pFileName,INT iLine)
-{
- if(g_fUseKASSERT)
- {
- DbgKernelAssert(pCondition, pFileName, iLine);
- }
- else
- {
- TCHAR szInfo[iDEBUGINFO];
-
- (void)StringCchPrintf(szInfo, NUMELMS(szInfo),TEXT("%s \nAt line %d of %s\nContinue? (Cancel to debug)"),
- pCondition, iLine, pFileName);
-
- INT MsgId = MessageBoxOtherThread(NULL,szInfo,TEXT("Hard coded break point"),
- MB_SYSTEMMODAL |
- MB_ICONHAND |
- MB_YESNOCANCEL |
- MB_SETFOREGROUND);
- switch (MsgId)
- {
- case IDNO: /* Kill the application */
-
- FatalAppExit(FALSE, TEXT("Application terminated"));
- break;
-
- case IDCANCEL: /* Break into the debugger */
-
- DebugBreak();
- break;
-
- case IDYES: /* Ignore break point continue execution */
- break;
- }
- }
-}
-
-void WINAPI DbgBreakPoint(LPCTSTR pFileName,INT iLine,__format_string LPCTSTR szFormatString,...)
-{
- // A debug break point message can have at most 2000 characters if
- // ANSI or UNICODE characters are being used. A debug break point message
- // can have between 1000 and 2000 double byte characters in it. If a
- // particular message needs more characters, then the value of this constant
- // should be increased.
- const DWORD MAX_BREAK_POINT_MESSAGE_SIZE = 2000;
-
- TCHAR szBreakPointMessage[MAX_BREAK_POINT_MESSAGE_SIZE];
-
- va_list va;
- va_start( va, szFormatString );
-
- HRESULT hr = StringCchVPrintf( szBreakPointMessage, NUMELMS(szBreakPointMessage), szFormatString, va );
-
- va_end(va);
-
- if( FAILED(hr) ) {
- DbgBreak( "ERROR in DbgBreakPoint(). The variable length debug message could not be displayed because StringCchVPrintf() failed." );
- return;
- }
-
- ::DbgBreakPoint( szBreakPointMessage, pFileName, iLine );
-}
-
-
-/* When we initialised the library we stored in the m_Levels array the current
- debug output level for this module for each of the five categories. When
- some debug logging is sent to us it can be sent with a combination of the
- categories (if it is applicable to many for example) in which case we map
- the type's categories into their current debug levels and see if any of
- them can be accepted. The function looks at each bit position in turn from
- the input type field and then compares it's debug level with the modules.
-
- A level of 0 means that output is always sent to the debugger. This is
- due to producing output if the input level is <= m_Levels.
-*/
-
-
-BOOL WINAPI DbgCheckModuleLevel(DWORD Type,DWORD Level)
-{
- if(g_fAutoRefreshLevels)
- {
- // re-read the registry every second. We cannot use RegNotify() to
- // notice registry changes because it's not available on win9x.
- static DWORD g_dwLastRefresh = 0;
- DWORD dwTime = timeGetTime();
- if(dwTime - g_dwLastRefresh > 1000) {
- g_dwLastRefresh = dwTime;
-
- // there's a race condition: multiple threads could update the
- // values. plus read and write not synchronized. no harm
- // though.
- DbgInitModuleSettings(false);
- }
- }
-
-
- DWORD Mask = 0x01;
-
- // If no valid bits are set return FALSE
- if ((Type & ((1<<iMAXLEVELS)-1))) {
-
- // speed up unconditional output.
- if (0==Level)
- return(TRUE);
-
- for (LONG lKeyPos = 0;lKeyPos < iMAXLEVELS;lKeyPos++) {
- if (Type & Mask) {
- if (Level <= (m_Levels[lKeyPos] & ~LOG_FORCIBLY_SET)) {
- return TRUE;
- }
- }
- Mask <<= 1;
- }
- }
- return FALSE;
-}
-
-
-/* Set debug levels to a given value */
-
-void WINAPI DbgSetModuleLevel(DWORD Type, DWORD Level)
-{
- DWORD Mask = 0x01;
-
- for (LONG lKeyPos = 0;lKeyPos < iMAXLEVELS;lKeyPos++) {
- if (Type & Mask) {
- m_Levels[lKeyPos] = Level | LOG_FORCIBLY_SET;
- }
- Mask <<= 1;
- }
-}
-
-/* whether to check registry values periodically. this isn't turned
- automatically because of the potential performance hit. */
-void WINAPI DbgSetAutoRefreshLevels(bool fAuto)
-{
- g_fAutoRefreshLevels = fAuto;
-}
-
-#ifdef UNICODE
-//
-// warning -- this function is implemented twice for ansi applications
-// linking to the unicode library
-//
-void WINAPI DbgLogInfo(DWORD Type,DWORD Level,__format_string LPCSTR pFormat,...)
-{
- /* Check the current level for this type combination */
-
- BOOL bAccept = DbgCheckModuleLevel(Type,Level);
- if (bAccept == FALSE) {
- return;
- }
-
- TCHAR szInfo[2000];
-
- /* Format the variable length parameter list */
-
- va_list va;
- va_start(va, pFormat);
-
- (void)StringCchPrintf(szInfo, NUMELMS(szInfo),
- TEXT("%s(tid %x) %8d : "),
- m_ModuleName,
- GetCurrentThreadId(), timeGetTime() - dwTimeOffset);
-
- CHAR szInfoA[2000];
- WideCharToMultiByte(CP_ACP, 0, szInfo, -1, szInfoA, NUMELMS(szInfoA), 0, 0);
-
- (void)StringCchVPrintfA(szInfoA + lstrlenA(szInfoA), NUMELMS(szInfoA) - lstrlenA(szInfoA), pFormat, va);
- (void)StringCchCatA(szInfoA, NUMELMS(szInfoA), "\r\n");
-
- WCHAR wszOutString[2000];
- MultiByteToWideChar(CP_ACP, 0, szInfoA, -1, wszOutString, NUMELMS(wszOutString));
- DbgOutString(wszOutString);
-
- va_end(va);
-}
-
-void WINAPI DbgAssert(LPCSTR pCondition,LPCSTR pFileName,INT iLine)
-{
- if(g_fUseKASSERT)
- {
- DbgKernelAssert(pCondition, pFileName, iLine);
- }
- else
- {
-
- TCHAR szInfo[iDEBUGINFO];
-
- (void)StringCchPrintf(szInfo, NUMELMS(szInfo), TEXT("%hs \nAt line %d of %hs\nContinue? (Cancel to debug)"),
- pCondition, iLine, pFileName);
-
- INT MsgId = MessageBoxOtherThread(NULL,szInfo,TEXT("ASSERT Failed"),
- MB_SYSTEMMODAL |
- MB_ICONHAND |
- MB_YESNOCANCEL |
- MB_SETFOREGROUND);
- switch (MsgId)
- {
- case IDNO: /* Kill the application */
-
- FatalAppExit(FALSE, TEXT("Application terminated"));
- break;
-
- case IDCANCEL: /* Break into the debugger */
-
- DebugBreak();
- break;
-
- case IDYES: /* Ignore assertion continue execution */
- break;
- }
- }
-}
-
-/* Displays a message box at a break point */
-
-void WINAPI DbgBreakPoint(LPCSTR pCondition,LPCSTR pFileName,INT iLine)
-{
- if(g_fUseKASSERT)
- {
- DbgKernelAssert(pCondition, pFileName, iLine);
- }
- else
- {
- TCHAR szInfo[iDEBUGINFO];
-
- (void)StringCchPrintf(szInfo, NUMELMS(szInfo),TEXT("%hs \nAt line %d of %hs\nContinue? (Cancel to debug)"),
- pCondition, iLine, pFileName);
-
- INT MsgId = MessageBoxOtherThread(NULL,szInfo,TEXT("Hard coded break point"),
- MB_SYSTEMMODAL |
- MB_ICONHAND |
- MB_YESNOCANCEL |
- MB_SETFOREGROUND);
- switch (MsgId)
- {
- case IDNO: /* Kill the application */
-
- FatalAppExit(FALSE, TEXT("Application terminated"));
- break;
-
- case IDCANCEL: /* Break into the debugger */
-
- DebugBreak();
- break;
-
- case IDYES: /* Ignore break point continue execution */
- break;
- }
- }
-}
-
-void WINAPI DbgKernelAssert(LPCSTR pCondition,LPCSTR pFileName,INT iLine)
-{
- DbgLog((LOG_ERROR,0,TEXT("Assertion FAILED (%hs) at line %d in file %hs"),
- pCondition, iLine, pFileName));
- DebugBreak();
-}
-
-#endif
-
-/* Print a formatted string to the debugger prefixed with this module's name
- Because the COMBASE classes are linked statically every module loaded will
- have their own copy of this code. It therefore helps if the module name is
- included on the output so that the offending code can be easily found */
-
-//
-// warning -- this function is implemented twice for ansi applications
-// linking to the unicode library
-//
-void WINAPI DbgLogInfo(DWORD Type,DWORD Level,LPCTSTR pFormat,...)
-{
-
- /* Check the current level for this type combination */
-
- BOOL bAccept = DbgCheckModuleLevel(Type,Level);
- if (bAccept == FALSE) {
- return;
- }
-
- TCHAR szInfo[2000];
-
- /* Format the variable length parameter list */
-
- va_list va;
- va_start(va, pFormat);
-
- (void)StringCchPrintf(szInfo, NUMELMS(szInfo),
- TEXT("%s(tid %x) %8d : "),
- m_ModuleName,
- GetCurrentThreadId(), timeGetTime() - dwTimeOffset);
-
- (void)StringCchVPrintf(szInfo + lstrlen(szInfo), NUMELMS(szInfo) - lstrlen(szInfo), pFormat, va);
- (void)StringCchCat(szInfo, NUMELMS(szInfo), TEXT("\r\n"));
- DbgOutString(szInfo);
-
- va_end(va);
-}
-
-
-/* If we are executing as a pure kernel filter we cannot display message
- boxes to the user, this provides an alternative which puts the error
- condition on the debugger output with a suitable eye catching message */
-
-void WINAPI DbgKernelAssert(LPCTSTR pCondition,LPCTSTR pFileName,INT iLine)
-{
- DbgLog((LOG_ERROR,0,TEXT("Assertion FAILED (%s) at line %d in file %s"),
- pCondition, iLine, pFileName));
- DebugBreak();
-}
-
-
-
-/* Each time we create an object derived from CBaseObject the constructor will
- call us to register the creation of the new object. We are passed a string
- description which we store away. We return a cookie that the constructor
- uses to identify the object when it is destroyed later on. We update the
- total number of active objects in the DLL mainly for debugging purposes */
-
-DWORD WINAPI DbgRegisterObjectCreation(LPCSTR szObjectName,
- LPCWSTR wszObjectName)
-{
- /* If this fires you have a mixed DEBUG/RETAIL build */
-
- ASSERT(!!szObjectName ^ !!wszObjectName);
-
- /* Create a place holder for this object description */
-
- ObjectDesc *pObject = new ObjectDesc;
- ASSERT(pObject);
-
- /* It is valid to pass a NULL object name */
- if (pObject == NULL) {
- return FALSE;
- }
-
- /* Check we have been initialised - we may not be initialised when we are
- being pulled in from an executable which has globally defined objects
- as they are created by the C++ run time before WinMain is called */
-
- if (m_bInit == FALSE) {
- DbgInitialise(GetModuleHandle(NULL));
- }
-
- /* Grab the list critical section */
- EnterCriticalSection(&m_CSDebug);
-
- /* If no name then default to UNKNOWN */
- if (!szObjectName && !wszObjectName) {
- szObjectName = pUnknownName;
- }
-
- /* Put the new description at the head of the list */
-
- pObject->m_szName = szObjectName;
- pObject->m_wszName = wszObjectName;
- pObject->m_dwCookie = ++m_dwNextCookie;
- pObject->m_pNext = pListHead;
-
- pListHead = pObject;
- m_dwObjectCount++;
-
- DWORD ObjectCookie = pObject->m_dwCookie;
- ASSERT(ObjectCookie);
-
- if(wszObjectName) {
- DbgLog((LOG_MEMORY,2,TEXT("Object created %d (%ls) %d Active"),
- pObject->m_dwCookie, wszObjectName, m_dwObjectCount));
- } else {
- DbgLog((LOG_MEMORY,2,TEXT("Object created %d (%hs) %d Active"),
- pObject->m_dwCookie, szObjectName, m_dwObjectCount));
- }
-
- LeaveCriticalSection(&m_CSDebug);
- return ObjectCookie;
-}
-
-
-/* This is called by the CBaseObject destructor when an object is about to be
- destroyed, we are passed the cookie we returned during construction that
- identifies this object. We scan the object list for a matching cookie and
- remove the object if successful. We also update the active object count */
-
-BOOL WINAPI DbgRegisterObjectDestruction(DWORD dwCookie)
-{
- /* Grab the list critical section */
- EnterCriticalSection(&m_CSDebug);
-
- ObjectDesc *pObject = pListHead;
- ObjectDesc *pPrevious = NULL;
-
- /* Scan the object list looking for a cookie match */
-
- while (pObject) {
- if (pObject->m_dwCookie == dwCookie) {
- break;
- }
- pPrevious = pObject;
- pObject = pObject->m_pNext;
- }
-
- if (pObject == NULL) {
- DbgBreak("Apparently destroying a bogus object");
- LeaveCriticalSection(&m_CSDebug);
- return FALSE;
- }
-
- /* Is the object at the head of the list */
-
- if (pPrevious == NULL) {
- pListHead = pObject->m_pNext;
- } else {
- pPrevious->m_pNext = pObject->m_pNext;
- }
-
- /* Delete the object and update the housekeeping information */
-
- m_dwObjectCount--;
-
- if(pObject->m_wszName) {
- DbgLog((LOG_MEMORY,2,TEXT("Object destroyed %d (%ls) %d Active"),
- pObject->m_dwCookie, pObject->m_wszName, m_dwObjectCount));
- } else {
- DbgLog((LOG_MEMORY,2,TEXT("Object destroyed %d (%hs) %d Active"),
- pObject->m_dwCookie, pObject->m_szName, m_dwObjectCount));
- }
-
- delete pObject;
- LeaveCriticalSection(&m_CSDebug);
- return TRUE;
-}
-
-
-/* This runs through the active object list displaying their details */
-
-void WINAPI DbgDumpObjectRegister()
-{
- TCHAR szInfo[iDEBUGINFO];
-
- /* Grab the list critical section */
-
- EnterCriticalSection(&m_CSDebug);
- ObjectDesc *pObject = pListHead;
-
- /* Scan the object list displaying the name and cookie */
-
- DbgLog((LOG_MEMORY,2,TEXT("")));
- DbgLog((LOG_MEMORY,2,TEXT(" ID Object Description")));
- DbgLog((LOG_MEMORY,2,TEXT("")));
-
- while (pObject) {
- if(pObject->m_wszName) {
- (void)StringCchPrintf(szInfo,NUMELMS(szInfo),TEXT("%5d (%p) %30ls"),pObject->m_dwCookie, &pObject, pObject->m_wszName);
- } else {
- (void)StringCchPrintf(szInfo,NUMELMS(szInfo),TEXT("%5d (%p) %30hs"),pObject->m_dwCookie, &pObject, pObject->m_szName);
- }
- DbgLog((LOG_MEMORY,2,szInfo));
- pObject = pObject->m_pNext;
- }
-
- (void)StringCchPrintf(szInfo,NUMELMS(szInfo),TEXT("Total object count %5d"),m_dwObjectCount);
- DbgLog((LOG_MEMORY,2,TEXT("")));
- DbgLog((LOG_MEMORY,1,szInfo));
- LeaveCriticalSection(&m_CSDebug);
-}
-
-/* Debug infinite wait stuff */
-DWORD WINAPI DbgWaitForSingleObject(HANDLE h)
-{
- DWORD dwWaitResult;
- do {
- dwWaitResult = WaitForSingleObject(h, dwWaitTimeout);
- ASSERT(dwWaitResult == WAIT_OBJECT_0);
- } while (dwWaitResult == WAIT_TIMEOUT);
- return dwWaitResult;
-}
-DWORD WINAPI DbgWaitForMultipleObjects(DWORD nCount,
- __in_ecount(nCount) CONST HANDLE *lpHandles,
- BOOL bWaitAll)
-{
- DWORD dwWaitResult;
- do {
- dwWaitResult = WaitForMultipleObjects(nCount,
- lpHandles,
- bWaitAll,
- dwWaitTimeout);
- ASSERT((DWORD)(dwWaitResult - WAIT_OBJECT_0) < MAXIMUM_WAIT_OBJECTS);
- } while (dwWaitResult == WAIT_TIMEOUT);
- return dwWaitResult;
-}
-
-void WINAPI DbgSetWaitTimeout(DWORD dwTimeout)
-{
- dwWaitTimeout = dwTimeout;
-}
-
-#endif /* DEBUG */
-
-#ifdef _OBJBASE_H_
-
- /* Stuff for printing out our GUID names */
-
- GUID_STRING_ENTRY g_GuidNames[] = {
- #define OUR_GUID_ENTRY(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
- { #name, { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } },
- #include <uuids.h>
- };
-
- CGuidNameList GuidNames;
- int g_cGuidNames = sizeof(g_GuidNames) / sizeof(g_GuidNames[0]);
-
- char *CGuidNameList::operator [] (const GUID &guid)
- {
- for (int i = 0; i < g_cGuidNames; i++) {
- if (g_GuidNames[i].guid == guid) {
- return g_GuidNames[i].szName;
- }
- }
- if (guid == GUID_NULL) {
- return "GUID_NULL";
- }
-
- // !!! add something to print FOURCC guids?
-
- // shouldn't this print the hex CLSID?
- return "Unknown GUID Name";
- }
-
-#endif /* _OBJBASE_H_ */
-
-/* CDisp class - display our data types */
-
-// clashes with REFERENCE_TIME
-CDisp::CDisp(LONGLONG ll, int Format)
-{
- // note: this could be combined with CDisp(LONGLONG) by
- // introducing a default format of CDISP_REFTIME
- LARGE_INTEGER li;
- li.QuadPart = ll;
- switch (Format) {
- case CDISP_DEC:
- {
- TCHAR temp[20];
- int pos=20;
- temp[--pos] = 0;
- int digit;
- // always output at least one digit
- do {
- // Get the rightmost digit - we only need the low word
- digit = li.LowPart % 10;
- li.QuadPart /= 10;
- temp[--pos] = (TCHAR) digit+L'0';
- } while (li.QuadPart);
- (void)StringCchCopy(m_String, NUMELMS(m_String), temp+pos);
- break;
- }
- case CDISP_HEX:
- default:
- (void)StringCchPrintf(m_String, NUMELMS(m_String), TEXT("0x%X%8.8X"), li.HighPart, li.LowPart);
- }
-};
-
-CDisp::CDisp(REFCLSID clsid)
-{
-#ifdef UNICODE
- (void)StringFromGUID2(clsid, m_String, NUMELMS(m_String));
-#else
- WCHAR wszTemp[50];
- (void)StringFromGUID2(clsid, wszTemp, NUMELMS(wszTemp));
- (void)StringCchPrintf(m_String, NUMELMS(m_String), TEXT("%S"), wszTemp);
-#endif
-};
-
-#ifdef __STREAMS__
-/* Display stuff */
-CDisp::CDisp(CRefTime llTime)
-{
- LONGLONG llDiv;
- if (llTime < 0) {
- llTime = -llTime;
- (void)StringCchCopy(m_String, NUMELMS(m_String), TEXT("-"));
- }
- llDiv = (LONGLONG)24 * 3600 * 10000000;
- if (llTime >= llDiv) {
- (void)StringCchPrintf(m_String + lstrlen(m_String), NUMELMS(m_String) - lstrlen(m_String), TEXT("%d days "), (LONG)(llTime / llDiv));
- llTime = llTime % llDiv;
- }
- llDiv = (LONGLONG)3600 * 10000000;
- if (llTime >= llDiv) {
- (void)StringCchPrintf(m_String + lstrlen(m_String), NUMELMS(m_String) - lstrlen(m_String), TEXT("%d hrs "), (LONG)(llTime / llDiv));
- llTime = llTime % llDiv;
- }
- llDiv = (LONGLONG)60 * 10000000;
- if (llTime >= llDiv) {
- (void)StringCchPrintf(m_String + lstrlen(m_String), NUMELMS(m_String) - lstrlen(m_String), TEXT("%d mins "), (LONG)(llTime / llDiv));
- llTime = llTime % llDiv;
- }
- (void)StringCchPrintf(m_String + lstrlen(m_String), NUMELMS(m_String) - lstrlen(m_String), TEXT("%d.%3.3d sec"),
- (LONG)llTime / 10000000,
- (LONG)((llTime % 10000000) / 10000));
-};
-
-#endif // __STREAMS__
-
-
-/* Display pin */
-CDisp::CDisp(IPin *pPin)
-{
- PIN_INFO pi;
- TCHAR str[MAX_PIN_NAME];
- CLSID clsid;
-
- if (pPin) {
- pPin->QueryPinInfo(&pi);
- pi.pFilter->GetClassID(&clsid);
- QueryPinInfoReleaseFilter(pi);
- #ifndef UNICODE
- WideCharToMultiByte(GetACP(), 0, pi.achName, lstrlenW(pi.achName) + 1,
- str, MAX_PIN_NAME, NULL, NULL);
- #else
- (void)StringCchCopy(str, NUMELMS(str), pi.achName);
- #endif
- } else {
- (void)StringCchCopy(str, NUMELMS(str), TEXT("NULL IPin"));
- }
-
- m_pString = (PTCHAR) new TCHAR[lstrlen(str)+64];
- if (!m_pString) {
- return;
- }
-
- (void)StringCchPrintf(m_pString, lstrlen(str) + 64, TEXT("%hs(%s)"), GuidNames[clsid], str);
-}
-
-/* Display filter or pin */
-CDisp::CDisp(IUnknown *pUnk)
-{
- IBaseFilter *pf;
- HRESULT hr = pUnk->QueryInterface(IID_IBaseFilter, (void **)&pf);
- if(SUCCEEDED(hr))
- {
- FILTER_INFO fi;
- hr = pf->QueryFilterInfo(&fi);
- if(SUCCEEDED(hr))
- {
- QueryFilterInfoReleaseGraph(fi);
-
- size_t len = lstrlenW(fi.achName) + 1;
-
- m_pString = new TCHAR[len];
- if(m_pString)
- {
-#ifdef UNICODE
- (void)StringCchCopy(m_pString, len, fi.achName);
-#else
- (void)StringCchPrintf(m_pString, len, "%S", fi.achName);
-#endif
- }
- }
-
- pf->Release();
-
- return;
- }
-
- IPin *pp;
- hr = pUnk->QueryInterface(IID_IPin, (void **)&pp);
- if(SUCCEEDED(hr))
- {
- CDisp::CDisp(pp);
- pp->Release();
- return;
- }
-}
-
-
-CDisp::~CDisp()
-{
-}
-
-CDispBasic::~CDispBasic()
-{
- if (m_pString != m_String) {
- delete [] m_pString;
- }
-}
-
-CDisp::CDisp(double d)
-{
- (void)StringCchPrintf(m_String, NUMELMS(m_String), TEXT("%d.%03d"), (int) d, (int) ((d - (int) d) * 1000));
-}
-
-
-/* If built for debug this will display the media type details. We convert the
- major and subtypes into strings and also ask the base classes for a string
- description of the subtype, so MEDIASUBTYPE_RGB565 becomes RGB 565 16 bit
- We also display the fields in the BITMAPINFOHEADER structure, this should
- succeed as we do not accept input types unless the format is big enough */
-
-#ifdef DEBUG
-void WINAPI DisplayType(LPCTSTR label, const AM_MEDIA_TYPE *pmtIn)
-{
-
- /* Dump the GUID types and a short description */
-
- DbgLog((LOG_TRACE,5,TEXT("")));
- DbgLog((LOG_TRACE,2,TEXT("%s M type %hs S type %hs"), label,
- GuidNames[pmtIn->majortype],
- GuidNames[pmtIn->subtype]));
- DbgLog((LOG_TRACE,5,TEXT("Subtype description %s"),GetSubtypeName(&pmtIn->subtype)));
-
- /* Dump the generic media types */
-
- if (pmtIn->bTemporalCompression) {
- DbgLog((LOG_TRACE,5,TEXT("Temporally compressed")));
- } else {
- DbgLog((LOG_TRACE,5,TEXT("Not temporally compressed")));
- }
-
- if (pmtIn->bFixedSizeSamples) {
- DbgLog((LOG_TRACE,5,TEXT("Sample size %d"),pmtIn->lSampleSize));
- } else {
- DbgLog((LOG_TRACE,5,TEXT("Variable size samples")));
- }
-
- if (pmtIn->formattype == FORMAT_VideoInfo) {
-
- VIDEOINFOHEADER *pVideoInfo = (VIDEOINFOHEADER *)pmtIn->pbFormat;
-
- DisplayRECT(TEXT("Source rectangle"),pVideoInfo->rcSource);
- DisplayRECT(TEXT("Target rectangle"),pVideoInfo->rcTarget);
- DisplayBITMAPINFO(HEADER(pmtIn->pbFormat));
-
- } if (pmtIn->formattype == FORMAT_VideoInfo2) {
-
- VIDEOINFOHEADER2 *pVideoInfo2 = (VIDEOINFOHEADER2 *)pmtIn->pbFormat;
-
- DisplayRECT(TEXT("Source rectangle"),pVideoInfo2->rcSource);
- DisplayRECT(TEXT("Target rectangle"),pVideoInfo2->rcTarget);
- DbgLog((LOG_TRACE, 5, TEXT("Aspect Ratio: %d:%d"),
- pVideoInfo2->dwPictAspectRatioX,
- pVideoInfo2->dwPictAspectRatioY));
- DisplayBITMAPINFO(&pVideoInfo2->bmiHeader);
-
- } else if (pmtIn->majortype == MEDIATYPE_Audio) {
- DbgLog((LOG_TRACE,2,TEXT(" Format type %hs"),
- GuidNames[pmtIn->formattype]));
- DbgLog((LOG_TRACE,2,TEXT(" Subtype %hs"),
- GuidNames[pmtIn->subtype]));
-
- if ((pmtIn->subtype != MEDIASUBTYPE_MPEG1Packet)
- && (pmtIn->cbFormat >= sizeof(PCMWAVEFORMAT)))
- {
- /* Dump the contents of the WAVEFORMATEX type-specific format structure */
-
- WAVEFORMATEX *pwfx = (WAVEFORMATEX *) pmtIn->pbFormat;
- DbgLog((LOG_TRACE,2,TEXT("wFormatTag %u"), pwfx->wFormatTag));
- DbgLog((LOG_TRACE,2,TEXT("nChannels %u"), pwfx->nChannels));
- DbgLog((LOG_TRACE,2,TEXT("nSamplesPerSec %lu"), pwfx->nSamplesPerSec));
- DbgLog((LOG_TRACE,2,TEXT("nAvgBytesPerSec %lu"), pwfx->nAvgBytesPerSec));
- DbgLog((LOG_TRACE,2,TEXT("nBlockAlign %u"), pwfx->nBlockAlign));
- DbgLog((LOG_TRACE,2,TEXT("wBitsPerSample %u"), pwfx->wBitsPerSample));
-
- /* PCM uses a WAVEFORMAT and does not have the extra size field */
-
- if (pmtIn->cbFormat >= sizeof(WAVEFORMATEX)) {
- DbgLog((LOG_TRACE,2,TEXT("cbSize %u"), pwfx->cbSize));
- }
- } else {
- }
-
- } else {
- DbgLog((LOG_TRACE,2,TEXT(" Format type %hs"),
- GuidNames[pmtIn->formattype]));
- }
-}
-
-
-void DisplayBITMAPINFO(const BITMAPINFOHEADER* pbmi)
-{
- DbgLog((LOG_TRACE,5,TEXT("Size of BITMAPINFO structure %d"),pbmi->biSize));
- if (pbmi->biCompression < 256) {
- DbgLog((LOG_TRACE,2,TEXT("%dx%dx%d bit (%d)"),
- pbmi->biWidth, pbmi->biHeight,
- pbmi->biBitCount, pbmi->biCompression));
- } else {
- DbgLog((LOG_TRACE,2,TEXT("%dx%dx%d bit '%4.4hs'"),
- pbmi->biWidth, pbmi->biHeight,
- pbmi->biBitCount, &pbmi->biCompression));
- }
-
- DbgLog((LOG_TRACE,2,TEXT("Image size %d"),pbmi->biSizeImage));
- DbgLog((LOG_TRACE,5,TEXT("Planes %d"),pbmi->biPlanes));
- DbgLog((LOG_TRACE,5,TEXT("X Pels per metre %d"),pbmi->biXPelsPerMeter));
- DbgLog((LOG_TRACE,5,TEXT("Y Pels per metre %d"),pbmi->biYPelsPerMeter));
- DbgLog((LOG_TRACE,5,TEXT("Colours used %d"),pbmi->biClrUsed));
-}
-
-
-void DisplayRECT(LPCTSTR szLabel, const RECT& rc)
-{
- DbgLog((LOG_TRACE,5,TEXT("%s (Left %d Top %d Right %d Bottom %d)"),
- szLabel,
- rc.left,
- rc.top,
- rc.right,
- rc.bottom));
-}
-
-
-void WINAPI DumpGraph(IFilterGraph *pGraph, DWORD dwLevel)
-{
- if( !pGraph )
- {
- return;
- }
-
- IEnumFilters *pFilters;
-
- DbgLog((LOG_TRACE,dwLevel,TEXT("DumpGraph [%x]"), pGraph));
-
- if (FAILED(pGraph->EnumFilters(&pFilters))) {
- DbgLog((LOG_TRACE,dwLevel,TEXT("EnumFilters failed!")));
- }
-
- IBaseFilter *pFilter;
- ULONG n;
- while (pFilters->Next(1, &pFilter, &n) == S_OK) {
- FILTER_INFO info;
-
- if (FAILED(pFilter->QueryFilterInfo(&info))) {
- DbgLog((LOG_TRACE,dwLevel,TEXT(" Filter [%p] -- failed QueryFilterInfo"), pFilter));
- } else {
- QueryFilterInfoReleaseGraph(info);
-
- // !!! should QueryVendorInfo here!
-
- DbgLog((LOG_TRACE,dwLevel,TEXT(" Filter [%p] '%ls'"), pFilter, info.achName));
-
- IEnumPins *pins;
-
- if (FAILED(pFilter->EnumPins(&pins))) {
- DbgLog((LOG_TRACE,dwLevel,TEXT("EnumPins failed!")));
- } else {
-
- IPin *pPin;
- while (pins->Next(1, &pPin, &n) == S_OK) {
- PIN_INFO pinInfo;
-
- if (FAILED(pPin->QueryPinInfo(&pinInfo))) {
- DbgLog((LOG_TRACE,dwLevel,TEXT(" Pin [%x] -- failed QueryPinInfo"), pPin));
- } else {
- QueryPinInfoReleaseFilter(pinInfo);
-
- IPin *pPinConnected = NULL;
-
- HRESULT hr = pPin->ConnectedTo(&pPinConnected);
-
- if (pPinConnected) {
- DbgLog((LOG_TRACE,dwLevel,TEXT(" Pin [%p] '%ls' [%sput]")
- TEXT(" Connected to pin [%p]"),
- pPin, pinInfo.achName,
- pinInfo.dir == PINDIR_INPUT ? TEXT("In") : TEXT("Out"),
- pPinConnected));
-
- pPinConnected->Release();
-
- // perhaps we should really dump the type both ways as a sanity
- // check?
- if (pinInfo.dir == PINDIR_OUTPUT) {
- AM_MEDIA_TYPE mt;
-
- hr = pPin->ConnectionMediaType(&mt);
-
- if (SUCCEEDED(hr)) {
- DisplayType(TEXT("Connection type"), &mt);
-
- FreeMediaType(mt);
- }
- }
- } else {
- DbgLog((LOG_TRACE,dwLevel,
- TEXT(" Pin [%x] '%ls' [%sput]"),
- pPin, pinInfo.achName,
- pinInfo.dir == PINDIR_INPUT ? TEXT("In") : TEXT("Out")));
-
- }
- }
-
- pPin->Release();
-
- }
-
- pins->Release();
- }
-
- }
-
- pFilter->Release();
- }
-
- pFilters->Release();
-
-}
-
-#endif
-
diff --git a/dll/src/baseclasses/wxdebug.h b/dll/src/baseclasses/wxdebug.h
deleted file mode 100644
index d4c69db..0000000
--- a/dll/src/baseclasses/wxdebug.h
+++ /dev/null
@@ -1,359 +0,0 @@
-//------------------------------------------------------------------------------
-// File: WXDebug.h
-//
-// Desc: DirectShow base classes - provides debugging facilities.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-#ifndef __WXDEBUG__
-#define __WXDEBUG__
-
-// This library provides fairly straight forward debugging functionality, this
-// is split into two main sections. The first is assertion handling, there are
-// three types of assertions provided here. The most commonly used one is the
-// ASSERT(condition) macro which will pop up a message box including the file
-// and line number if the condition evaluates to FALSE. Then there is the
-// EXECUTE_ASSERT macro which is the same as ASSERT except the condition will
-// still be executed in NON debug builds. The final type of assertion is the
-// KASSERT macro which is more suitable for pure (perhaps kernel) filters as
-// the condition is printed onto the debugger rather than in a message box.
-//
-// The other part of the debug module facilties is general purpose logging.
-// This is accessed by calling DbgLog(). The function takes a type and level
-// field which define the type of informational string you are presenting and
-// it's relative importance. The type field can be a combination (one or more)
-// of LOG_TIMING, LOG_TRACE, LOG_MEMORY, LOG_LOCKING and LOG_ERROR. The level
-// is a DWORD value where zero defines highest important. Use of zero as the
-// debug logging level is to be encouraged ONLY for major errors or events as
-// they will ALWAYS be displayed on the debugger. Other debug output has it's
-// level matched against the current debug output level stored in the registry
-// for this module and if less than the current setting it will be displayed.
-//
-// Each module or executable has it's own debug output level for each of the
-// five types. These are read in when the DbgInitialise function is called
-// for DLLs linking to STRMBASE.LIB this is done automatically when the DLL
-// is loaded, executables must call it explicitely with the module instance
-// handle given to them through the WINMAIN entry point. An executable must
-// also call DbgTerminate when they have finished to clean up the resources
-// the debug library uses, once again this is done automatically for DLLs
-
-// These are the five different categories of logging information
-
-enum { LOG_TIMING = 0x01, // Timing and performance measurements
- LOG_TRACE = 0x02, // General step point call tracing
- LOG_MEMORY = 0x04, // Memory and object allocation/destruction
- LOG_LOCKING = 0x08, // Locking/unlocking of critical sections
- LOG_ERROR = 0x10, // Debug error notification
- LOG_CUSTOM1 = 0x20,
- LOG_CUSTOM2 = 0x40,
- LOG_CUSTOM3 = 0x80,
- LOG_CUSTOM4 = 0x100,
- LOG_CUSTOM5 = 0x200,
-};
-
-#define LOG_FORCIBLY_SET 0x80000000
-
-enum { CDISP_HEX = 0x01,
- CDISP_DEC = 0x02};
-
-// For each object created derived from CBaseObject (in debug builds) we
-// create a descriptor that holds it's name (statically allocated memory)
-// and a cookie we assign it. We keep a list of all the active objects
-// we have registered so that we can dump a list of remaining objects
-
-typedef struct tag_ObjectDesc {
- LPCSTR m_szName;
- LPCWSTR m_wszName;
- DWORD m_dwCookie;
- tag_ObjectDesc *m_pNext;
-} ObjectDesc;
-
-#define DLLIMPORT __declspec(dllimport)
-#define DLLEXPORT __declspec(dllexport)
-
-#ifdef DEBUG
-
- #define NAME(x) TEXT(x)
-
- // These are used internally by the debug library (PRIVATE)
-
- void WINAPI DbgInitKeyLevels(HKEY hKey, bool fTakeMax);
- void WINAPI DbgInitGlobalSettings(bool fTakeMax);
- void WINAPI DbgInitModuleSettings(bool fTakeMax);
- void WINAPI DbgInitModuleName();
- DWORD WINAPI DbgRegisterObjectCreation(
- LPCSTR szObjectName, LPCWSTR wszObjectName);
-
- BOOL WINAPI DbgRegisterObjectDestruction(DWORD dwCookie);
-
- // These are the PUBLIC entry points
-
- BOOL WINAPI DbgCheckModuleLevel(DWORD Type,DWORD Level);
- void WINAPI DbgSetModuleLevel(DWORD Type,DWORD Level);
- void WINAPI DbgSetAutoRefreshLevels(bool fAuto);
-
- // Initialise the library with the module handle
-
- void WINAPI DbgInitialise(HINSTANCE hInst);
- void WINAPI DbgTerminate();
-
- void WINAPI DbgDumpObjectRegister();
-
- // Display error and logging to the user
-
- void WINAPI DbgAssert(LPCTSTR pCondition,LPCTSTR pFileName,INT iLine);
- void WINAPI DbgBreakPoint(LPCTSTR pCondition,LPCTSTR pFileName,INT iLine);
- void WINAPI DbgBreakPoint(LPCTSTR pFileName,INT iLine,__format_string LPCTSTR szFormatString,...);
-
- void WINAPI DbgKernelAssert(LPCTSTR pCondition,LPCTSTR pFileName,INT iLine);
- void WINAPI DbgLogInfo(DWORD Type,DWORD Level,__format_string LPCTSTR pFormat,...);
-#ifdef UNICODE
- void WINAPI DbgLogInfo(DWORD Type,DWORD Level,__format_string LPCSTR pFormat,...);
- void WINAPI DbgAssert(LPCSTR pCondition,LPCSTR pFileName,INT iLine);
- void WINAPI DbgBreakPoint(LPCSTR pCondition,LPCSTR pFileName,INT iLine);
- void WINAPI DbgKernelAssert(LPCSTR pCondition,LPCSTR pFileName,INT iLine);
-#endif
- void WINAPI DbgOutString(LPCTSTR psz);
-
- // Debug infinite wait stuff
- DWORD WINAPI DbgWaitForSingleObject(HANDLE h);
- DWORD WINAPI DbgWaitForMultipleObjects(DWORD nCount,
- __in_ecount(nCount) CONST HANDLE *lpHandles,
- BOOL bWaitAll);
- void WINAPI DbgSetWaitTimeout(DWORD dwTimeout);
-
-#ifdef __strmif_h__
- // Display a media type: Terse at level 2, verbose at level 5
- void WINAPI DisplayType(LPCTSTR label, const AM_MEDIA_TYPE *pmtIn);
-
- // Dump lots of information about a filter graph
- void WINAPI DumpGraph(IFilterGraph *pGraph, DWORD dwLevel);
-#endif
-
- #define KASSERT(_x_) if (!(_x_)) \
- DbgKernelAssert(TEXT(#_x_),TEXT(__FILE__),__LINE__)
-
- // Break on the debugger without putting up a message box
- // message goes to debugger instead
-
- #define KDbgBreak(_x_) \
- DbgKernelAssert(TEXT(#_x_),TEXT(__FILE__),__LINE__)
-
- // We chose a common name for our ASSERT macro, MFC also uses this name
- // So long as the implementation evaluates the condition and handles it
- // then we will be ok. Rather than override the behaviour expected we
- // will leave whatever first defines ASSERT as the handler (i.e. MFC)
- #ifndef ASSERT
- #define ASSERT(_x_) if (!(_x_)) \
- DbgAssert(TEXT(#_x_),TEXT(__FILE__),__LINE__)
- #endif
-
- #define DbgAssertAligned( _ptr_, _alignment_ ) ASSERT( ((DWORD_PTR) (_ptr_)) % (_alignment_) == 0)
-
- // Put up a message box informing the user of a halt
- // condition in the program
-
- #define DbgBreak(_x_) \
- DbgBreakPoint(TEXT(#_x_),TEXT(__FILE__),__LINE__)
-
- #define EXECUTE_ASSERT(_x_) ASSERT(_x_)
- #define DbgLog(_x_) DbgLogInfo _x_
- // MFC style trace macros
-
- #define NOTE(_x_) DbgLog((LOG_TRACE,5,TEXT(_x_)))
- #define NOTE1(_x_,a) DbgLog((LOG_TRACE,5,TEXT(_x_),a))
- #define NOTE2(_x_,a,b) DbgLog((LOG_TRACE,5,TEXT(_x_),a,b))
- #define NOTE3(_x_,a,b,c) DbgLog((LOG_TRACE,5,TEXT(_x_),a,b,c))
- #define NOTE4(_x_,a,b,c,d) DbgLog((LOG_TRACE,5,TEXT(_x_),a,b,c,d))
- #define NOTE5(_x_,a,b,c,d,e) DbgLog((LOG_TRACE,5,TEXT(_x_),a,b,c,d,e))
-
-#else
-
- // Retail builds make public debug functions inert - WARNING the source
- // files do not define or build any of the entry points in debug builds
- // (public entry points compile to nothing) so if you go trying to call
- // any of the private entry points in your source they won't compile
-
- #define NAME(_x_) ((LPTSTR) NULL)
-
- #define DbgInitialise(hInst)
- #define DbgTerminate()
- #define DbgLog(_x_) 0
- #define DbgOutString(psz)
- #define DbgAssertAligned( _ptr_, _alignment_ ) 0
-
- #define DbgRegisterObjectCreation(pObjectName)
- #define DbgRegisterObjectDestruction(dwCookie)
- #define DbgDumpObjectRegister()
-
- #define DbgCheckModuleLevel(Type,Level)
- #define DbgSetModuleLevel(Type,Level)
- #define DbgSetAutoRefreshLevels(fAuto)
-
- #define DbgWaitForSingleObject(h) WaitForSingleObject(h, INFINITE)
- #define DbgWaitForMultipleObjects(nCount, lpHandles, bWaitAll) \
- WaitForMultipleObjects(nCount, lpHandles, bWaitAll, INFINITE)
- #define DbgSetWaitTimeout(dwTimeout)
-
- #define KDbgBreak(_x_)
- #define DbgBreak(_x_)
-
- #define KASSERT(_x_) ((void)0)
- #ifndef ASSERT
- #define ASSERT(_x_) ((void)0)
- #endif
- #define EXECUTE_ASSERT(_x_) ((void)(_x_))
-
- // MFC style trace macros
-
- #define NOTE(_x_) ((void)0)
- #define NOTE1(_x_,a) ((void)0)
- #define NOTE2(_x_,a,b) ((void)0)
- #define NOTE3(_x_,a,b,c) ((void)0)
- #define NOTE4(_x_,a,b,c,d) ((void)0)
- #define NOTE5(_x_,a,b,c,d,e) ((void)0)
-
- #define DisplayType(label, pmtIn) ((void)0)
- #define DumpGraph(pGraph, label) ((void)0)
-#endif
-
-
-// Checks a pointer which should be non NULL - can be used as follows.
-
-#define CheckPointer(p,ret) {if((p)==NULL) return (ret);}
-
-// HRESULT Foo(VOID *pBar)
-// {
-// CheckPointer(pBar,E_INVALIDARG)
-// }
-//
-// Or if the function returns a boolean
-//
-// BOOL Foo(VOID *pBar)
-// {
-// CheckPointer(pBar,FALSE)
-// }
-
-#define ValidateReadPtr(p,cb) 0
-#define ValidateWritePtr(p,cb) 0
-#define ValidateReadWritePtr(p,cb) 0
-#define ValidateStringPtr(p) 0
-#define ValidateStringPtrA(p) 0
-#define ValidateStringPtrW(p) 0
-
-
-#ifdef _OBJBASE_H_
-
- // Outputting GUID names. If you want to include the name
- // associated with a GUID (eg CLSID_...) then
- //
- // GuidNames[yourGUID]
- //
- // Returns the name defined in uuids.h as a string
-
- typedef struct {
- CHAR *szName;
- GUID guid;
- } GUID_STRING_ENTRY;
-
- class CGuidNameList {
- public:
- CHAR *operator [] (const GUID& guid);
- };
-
- extern CGuidNameList GuidNames;
-
-#endif
-
-#ifndef REMIND
- // REMIND macro - generates warning as reminder to complete coding
- // (eg) usage:
- //
- // #pragma message (REMIND("Add automation support"))
-
-
- #define QUOTE(x) #x
- #define QQUOTE(y) QUOTE(y)
- #define REMIND(str) __FILE__ "(" QQUOTE(__LINE__) ") : " str
-#endif
-
-// Method to display objects in a useful format
-//
-// eg If you want to display a LONGLONG ll in a debug string do (eg)
-//
-// DbgLog((LOG_TRACE, n, TEXT("Value is %s"), (LPCTSTR)CDisp(ll, CDISP_HEX)));
-
-
-class CDispBasic
-{
-public:
- CDispBasic() { m_pString = m_String; };
- ~CDispBasic();
-protected:
- PTCHAR m_pString; // normally points to m_String... unless too much data
- TCHAR m_String[50];
-};
-class CDisp : public CDispBasic
-{
-public:
- CDisp(LONGLONG ll, int Format = CDISP_HEX); // Display a LONGLONG in CDISP_HEX or CDISP_DEC form
- CDisp(REFCLSID clsid); // Display a GUID
- CDisp(double d); // Display a floating point number
-#ifdef __strmif_h__
-#ifdef __STREAMS__
- CDisp(CRefTime t); // Display a Reference Time
-#endif
- CDisp(IPin *pPin); // Display a pin as {filter clsid}(pin name)
- CDisp(IUnknown *pUnk); // Display a filter or pin
-#endif // __strmif_h__
- ~CDisp();
-
- // Implement cast to (LPCTSTR) as parameter to logger
- operator LPCTSTR()
- {
- return (LPCTSTR)m_pString;
- };
-};
-
-
-#if defined(DEBUG)
-class CAutoTrace
-{
-private:
- LPCTSTR _szBlkName;
- const int _level;
- static const TCHAR _szEntering[];
- static const TCHAR _szLeaving[];
-public:
- CAutoTrace(LPCTSTR szBlkName, const int level = 15)
- : _szBlkName(szBlkName), _level(level)
- {DbgLog((LOG_TRACE, _level, _szEntering, _szBlkName));}
-
- ~CAutoTrace()
- {DbgLog((LOG_TRACE, _level, _szLeaving, _szBlkName));}
-};
-
-#if defined (__FUNCTION__)
-
-#define AMTRACEFN() CAutoTrace __trace(TEXT(__FUNCTION__))
-#define AMTRACE(_x_) CAutoTrace __trace(TEXT(__FUNCTION__))
-
-#else
-
-#define AMTRACE(_x_) CAutoTrace __trace _x_
-#define AMTRACEFN()
-
-#endif
-
-#else
-
-#define AMTRACE(_x_)
-#define AMTRACEFN()
-
-#endif
-
-#endif // __WXDEBUG__
-
-
diff --git a/dll/src/baseclasses/wxlist.cpp b/dll/src/baseclasses/wxlist.cpp
deleted file mode 100644
index 2ec67a4..0000000
--- a/dll/src/baseclasses/wxlist.cpp
+++ /dev/null
@@ -1,891 +0,0 @@
-//------------------------------------------------------------------------------
-// File: WXList.cpp
-//
-// Desc: DirectShow base classes - implements a non-MFC based generic list
-// template class.
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-/* A generic list of pointers to objects.
- Objectives: avoid using MFC libraries in ndm kernel mode and
- provide a really useful list type.
-
- The class is thread safe in that separate threads may add and
- delete items in the list concurrently although the application
- must ensure that constructor and destructor access is suitably
- synchronised.
-
- The list name must not conflict with MFC classes as an
- application may use both
-
- The nodes form a doubly linked, NULL terminated chain with an anchor
- block (the list object per se) holding pointers to the first and last
- nodes and a count of the nodes.
- There is a node cache to reduce the allocation and freeing overhead.
- It optionally (determined at construction time) has an Event which is
- set whenever the list becomes non-empty and reset whenever it becomes
- empty.
- It optionally (determined at construction time) has a Critical Section
- which is entered during the important part of each operation. (About
- all you can do outside it is some parameter checking).
-
- The node cache is a repository of nodes that are NOT in the list to speed
- up storage allocation. Each list has its own cache to reduce locking and
- serialising. The list accesses are serialised anyway for a given list - a
- common cache would mean that we would have to separately serialise access
- of all lists within the cache. Because the cache only stores nodes that are
- not in the list, releasing the cache does not release any list nodes. This
- means that list nodes can be copied or rechained from one list to another
- without danger of creating a dangling reference if the original cache goes
- away.
-
- Questionable design decisions:
- 1. Retaining the warts for compatibility
- 2. Keeping an element count -i.e. counting whenever we do anything
- instead of only when we want the count.
- 3. Making the chain pointers NULL terminated. If the list object
- itself looks just like a node and the list is kept as a ring then
- it reduces the number of special cases. All inserts look the same.
-*/
-
-
-#include <streams.h>
-
-/* set cursor to the position of each element of list in turn */
-#define INTERNALTRAVERSELIST(list, cursor) \
-for ( cursor = (list).GetHeadPositionI() \
- ; cursor!=NULL \
- ; cursor = (list).Next(cursor) \
- )
-
-
-/* set cursor to the position of each element of list in turn
- in reverse order
-*/
-#define INTERNALREVERSETRAVERSELIST(list, cursor) \
-for ( cursor = (list).GetTailPositionI() \
- ; cursor!=NULL \
- ; cursor = (list).Prev(cursor) \
- )
-
-/* Constructor calls a separate initialisation function that
- creates a node cache, optionally creates a lock object
- and optionally creates a signaling object.
-
- By default we create a locking object, a DEFAULTCACHE sized
- cache but no event object so the list cannot be used in calls
- to WaitForSingleObject
-*/
-CBaseList::CBaseList(__in_opt LPCTSTR pName, // Descriptive list name
- INT iItems) : // Node cache size
-#ifdef DEBUG
- CBaseObject(pName),
-#endif
- m_pFirst(NULL),
- m_pLast(NULL),
- m_Count(0),
- m_Cache(iItems)
-{
-} // constructor
-
-CBaseList::CBaseList(__in_opt LPCTSTR pName) : // Descriptive list name
-#ifdef DEBUG
- CBaseObject(pName),
-#endif
- m_pFirst(NULL),
- m_pLast(NULL),
- m_Count(0),
- m_Cache(DEFAULTCACHE)
-{
-} // constructor
-
-#ifdef UNICODE
-CBaseList::CBaseList(__in_opt LPCSTR pName, // Descriptive list name
- INT iItems) : // Node cache size
-#ifdef DEBUG
- CBaseObject(pName),
-#endif
- m_pFirst(NULL),
- m_pLast(NULL),
- m_Count(0),
- m_Cache(iItems)
-{
-} // constructor
-
-CBaseList::CBaseList(__in_opt LPCSTR pName) : // Descriptive list name
-#ifdef DEBUG
- CBaseObject(pName),
-#endif
- m_pFirst(NULL),
- m_pLast(NULL),
- m_Count(0),
- m_Cache(DEFAULTCACHE)
-{
-} // constructor
-
-#endif
-
-/* The destructor enumerates all the node objects in the list and
- in the cache deleting each in turn. We do not do any processing
- on the objects that the list holds (i.e. points to) so if they
- represent interfaces for example the creator of the list should
- ensure that each of them is released before deleting us
-*/
-CBaseList::~CBaseList()
-{
- /* Delete all our list nodes */
-
- RemoveAll();
-
-} // destructor
-
-/* Remove all the nodes from the list but don't do anything
- with the objects that each node looks after (this is the
- responsibility of the creator).
- Aa a last act we reset the signalling event
- (if available) to indicate to clients that the list
- does not have any entries in it.
-*/
-void CBaseList::RemoveAll()
-{
- /* Free up all the CNode objects NOTE we don't bother putting the
- deleted nodes into the cache as this method is only really called
- in serious times of change such as when we are being deleted at
- which point the cache will be deleted anway */
-
- CNode *pn = m_pFirst;
- while (pn) {
- CNode *op = pn;
- pn = pn->Next();
- delete op;
- }
-
- /* Reset the object count and the list pointers */
-
- m_Count = 0;
- m_pFirst = m_pLast = NULL;
-
-} // RemoveAll
-
-
-
-/* Return a position enumerator for the entire list.
- A position enumerator is a pointer to a node object cast to a
- transparent type so all we do is return the head/tail node
- pointer in the list.
- WARNING because the position is a pointer to a node there is
- an implicit assumption for users a the list class that after
- deleting an object from the list that any other position
- enumerators that you have may be invalid (since the node
- may be gone).
-*/
-__out_opt POSITION CBaseList::GetHeadPositionI() const
-{
- return (POSITION) m_pFirst;
-} // GetHeadPosition
-
-
-
-__out_opt POSITION CBaseList::GetTailPositionI() const
-{
- return (POSITION) m_pLast;
-} // GetTailPosition
-
-
-
-/* Get the number of objects in the list,
- Get the lock before accessing the count.
- Locking may not be entirely necessary but it has the side effect
- of making sure that all operations are complete before we get it.
- So for example if a list is being added to this list then that
- will have completed in full before we continue rather than seeing
- an intermediate albeit valid state
-*/
-int CBaseList::GetCountI() const
-{
- return m_Count;
-} // GetCount
-
-
-
-/* Return the object at rp, update rp to the next object from
- the list or NULL if you have moved over the last object.
- You may still call this function once we return NULL but
- we will continue to return a NULL position value
-*/
-__out void *CBaseList::GetNextI(__inout POSITION& rp) const
-{
- /* have we reached the end of the list */
-
- if (rp == NULL) {
- return NULL;
- }
-
- /* Lock the object before continuing */
-
- void *pObject;
-
- /* Copy the original position then step on */
-
- CNode *pn = (CNode *) rp;
- ASSERT(pn != NULL);
- rp = (POSITION) pn->Next();
-
- /* Get the object at the original position from the list */
-
- pObject = pn->GetData();
- // ASSERT(pObject != NULL); // NULL pointers in the list are allowed.
- return pObject;
-} //GetNext
-
-
-
-/* Return the object at p.
- Asking for the object at NULL ASSERTs then returns NULL
- The object is NOT locked. The list is not being changed
- in any way. If another thread is busy deleting the object
- then locking would only result in a change from one bad
- behaviour to another.
-*/
-__out_opt void *CBaseList::GetI(__in_opt POSITION p) const
-{
- if (p == NULL) {
- return NULL;
- }
-
- CNode * pn = (CNode *) p;
- void *pObject = pn->GetData();
- // ASSERT(pObject != NULL); // NULL pointers in the list are allowed.
- return pObject;
-} //Get
-
-__out void *CBaseList::GetValidI(__in POSITION p) const
-{
- CNode * pn = (CNode *) p;
- void *pObject = pn->GetData();
- // ASSERT(pObject != NULL); // NULL pointers in the list are allowed.
- return pObject;
-} //Get
-
-
-/* Return the first position in the list which holds the given pointer.
- Return NULL if it's not found.
-*/
-__out_opt POSITION CBaseList::FindI( __in void * pObj) const
-{
- POSITION pn;
- INTERNALTRAVERSELIST(*this, pn){
- if (GetI(pn)==pObj) {
- return pn;
- }
- }
- return NULL;
-} // Find
-
-
-
-/* Remove the first node in the list (deletes the pointer to its object
- from the list, does not free the object itself).
- Return the pointer to its object or NULL if empty
-*/
-__out_opt void *CBaseList::RemoveHeadI()
-{
- /* All we do is get the head position and ask for that to be deleted.
- We could special case this since some of the code path checking
- in Remove() is redundant as we know there is no previous
- node for example but it seems to gain little over the
- added complexity
- */
-
- return RemoveI((POSITION)m_pFirst);
-} // RemoveHead
-
-
-
-/* Remove the last node in the list (deletes the pointer to its object
- from the list, does not free the object itself).
- Return the pointer to its object or NULL if empty
-*/
-__out_opt void *CBaseList::RemoveTailI()
-{
- /* All we do is get the tail position and ask for that to be deleted.
- We could special case this since some of the code path checking
- in Remove() is redundant as we know there is no previous
- node for example but it seems to gain little over the
- added complexity
- */
-
- return RemoveI((POSITION)m_pLast);
-} // RemoveTail
-
-
-
-/* Remove the pointer to the object in this position from the list.
- Deal with all the chain pointers
- Return a pointer to the object removed from the list.
- The node object that is freed as a result
- of this operation is added to the node cache where
- it can be used again.
- Remove(NULL) is a harmless no-op - but probably is a wart.
-*/
-__out_opt void *CBaseList::RemoveI(__in_opt POSITION pos)
-{
- /* Lock the critical section before continuing */
-
- // ASSERT (pos!=NULL); // Removing NULL is to be harmless!
- if (pos==NULL) return NULL;
-
-
- CNode *pCurrent = (CNode *) pos;
- ASSERT(pCurrent != NULL);
-
- /* Update the previous node */
-
- CNode *pNode = pCurrent->Prev();
- if (pNode == NULL) {
- m_pFirst = pCurrent->Next();
- } else {
- pNode->SetNext(pCurrent->Next());
- }
-
- /* Update the following node */
-
- pNode = pCurrent->Next();
- if (pNode == NULL) {
- m_pLast = pCurrent->Prev();
- } else {
- pNode->SetPrev(pCurrent->Prev());
- }
-
- /* Get the object this node was looking after */
-
- void *pObject = pCurrent->GetData();
-
- // ASSERT(pObject != NULL); // NULL pointers in the list are allowed.
-
- /* Try and add the node object to the cache -
- a NULL return code from the cache means we ran out of room.
- The cache size is fixed by a constructor argument when the
- list is created and defaults to DEFAULTCACHE.
- This means that the cache will have room for this many
- node objects. So if you have a list of media samples
- and you know there will never be more than five active at
- any given time of them for example then override the default
- constructor
- */
-
- m_Cache.AddToCache(pCurrent);
-
- /* If the list is empty then reset the list event */
-
- --m_Count;
- ASSERT(m_Count >= 0);
- return pObject;
-} // Remove
-
-
-
-/* Add this object to the tail end of our list
- Return the new tail position.
-*/
-
-__out_opt POSITION CBaseList::AddTailI(__in void *pObject)
-{
- /* Lock the critical section before continuing */
-
- CNode *pNode;
- // ASSERT(pObject); // NULL pointers in the list are allowed.
-
- /* If there is a node objects in the cache then use
- that otherwise we will have to create a new one */
-
- pNode = (CNode *) m_Cache.RemoveFromCache();
- if (pNode == NULL) {
- pNode = new CNode;
- }
-
- /* Check we have a valid object */
-
- if (pNode == NULL) {
- return NULL;
- }
-
- /* Initialise all the CNode object
- just in case it came from the cache
- */
-
- pNode->SetData(pObject);
- pNode->SetNext(NULL);
- pNode->SetPrev(m_pLast);
-
- if (m_pLast == NULL) {
- m_pFirst = pNode;
- } else {
- m_pLast->SetNext(pNode);
- }
-
- /* Set the new last node pointer and also increment the number
- of list entries, the critical section is unlocked when we
- exit the function
- */
-
- m_pLast = pNode;
- ++m_Count;
-
- return (POSITION) pNode;
-} // AddTail(object)
-
-
-
-/* Add this object to the head end of our list
- Return the new head position.
-*/
-__out_opt POSITION CBaseList::AddHeadI(__in void *pObject)
-{
- CNode *pNode;
- // ASSERT(pObject); // NULL pointers in the list are allowed.
-
- /* If there is a node objects in the cache then use
- that otherwise we will have to create a new one */
-
- pNode = (CNode *) m_Cache.RemoveFromCache();
- if (pNode == NULL) {
- pNode = new CNode;
- }
-
- /* Check we have a valid object */
-
- if (pNode == NULL) {
- return NULL;
- }
-
- /* Initialise all the CNode object
- just in case it came from the cache
- */
-
- pNode->SetData(pObject);
-
- /* chain it in (set four pointers) */
- pNode->SetPrev(NULL);
- pNode->SetNext(m_pFirst);
-
- if (m_pFirst == NULL) {
- m_pLast = pNode;
- } else {
- m_pFirst->SetPrev(pNode);
- }
- m_pFirst = pNode;
-
- ++m_Count;
-
- return (POSITION) pNode;
-} // AddHead(object)
-
-
-
-/* Add all the elements in *pList to the tail of this list.
- Return TRUE if it all worked, FALSE if it didn't.
- If it fails some elements may have been added.
-*/
-BOOL CBaseList::AddTail(__in CBaseList *pList)
-{
- /* lock the object before starting then enumerate
- each entry in the source list and add them one by one to
- our list (while still holding the object lock)
- Lock the other list too.
- */
- POSITION pos = pList->GetHeadPositionI();
-
- while (pos) {
- if (NULL == AddTailI(pList->GetNextI(pos))) {
- return FALSE;
- }
- }
- return TRUE;
-} // AddTail(list)
-
-
-
-/* Add all the elements in *pList to the head of this list.
- Return TRUE if it all worked, FALSE if it didn't.
- If it fails some elements may have been added.
-*/
-BOOL CBaseList::AddHead(__in CBaseList *pList)
-{
- /* lock the object before starting then enumerate
- each entry in the source list and add them one by one to
- our list (while still holding the object lock)
- Lock the other list too.
-
- To avoid reversing the list, traverse it backwards.
- */
-
- POSITION pos;
-
- INTERNALREVERSETRAVERSELIST(*pList, pos) {
- if (NULL== AddHeadI(pList->GetValidI(pos))){
- return FALSE;
- }
- }
- return TRUE;
-} // AddHead(list)
-
-
-
-/* Add the object after position p
- p is still valid after the operation.
- AddAfter(NULL,x) adds x to the start - same as AddHead
- Return the position of the new object, NULL if it failed
-*/
-__out_opt POSITION CBaseList::AddAfterI(__in_opt POSITION pos, __in void * pObj)
-{
- if (pos==NULL)
- return AddHeadI(pObj);
-
- /* As someone else might be furkling with the list -
- Lock the critical section before continuing
- */
- CNode *pAfter = (CNode *) pos;
- ASSERT(pAfter != NULL);
- if (pAfter==m_pLast)
- return AddTailI(pObj);
-
- /* set pnode to point to a new node, preferably from the cache */
-
- CNode *pNode = (CNode *) m_Cache.RemoveFromCache();
- if (pNode == NULL) {
- pNode = new CNode;
- }
-
- /* Check we have a valid object */
-
- if (pNode == NULL) {
- return NULL;
- }
-
- /* Initialise all the CNode object
- just in case it came from the cache
- */
-
- pNode->SetData(pObj);
-
- /* It is to be added to the middle of the list - there is a before
- and after node. Chain it after pAfter, before pBefore.
- */
- CNode * pBefore = pAfter->Next();
- ASSERT(pBefore != NULL);
-
- /* chain it in (set four pointers) */
- pNode->SetPrev(pAfter);
- pNode->SetNext(pBefore);
- pBefore->SetPrev(pNode);
- pAfter->SetNext(pNode);
-
- ++m_Count;
-
- return (POSITION) pNode;
-
-} // AddAfter(object)
-
-
-
-BOOL CBaseList::AddAfter(__in_opt POSITION p, __in CBaseList *pList)
-{
- POSITION pos;
- INTERNALTRAVERSELIST(*pList, pos) {
- /* p follows along the elements being added */
- p = AddAfterI(p, pList->GetValidI(pos));
- if (p==NULL) return FALSE;
- }
- return TRUE;
-} // AddAfter(list)
-
-
-
-/* Mirror images:
- Add the element or list after position p.
- p is still valid after the operation.
- AddBefore(NULL,x) adds x to the end - same as AddTail
-*/
-__out_opt POSITION CBaseList::AddBeforeI(__in_opt POSITION pos, __in void * pObj)
-{
- if (pos==NULL)
- return AddTailI(pObj);
-
- /* set pnode to point to a new node, preferably from the cache */
-
- CNode *pBefore = (CNode *) pos;
- ASSERT(pBefore != NULL);
- if (pBefore==m_pFirst)
- return AddHeadI(pObj);
-
- CNode * pNode = (CNode *) m_Cache.RemoveFromCache();
- if (pNode == NULL) {
- pNode = new CNode;
- }
-
- /* Check we have a valid object */
-
- if (pNode == NULL) {
- return NULL;
- }
-
- /* Initialise all the CNode object
- just in case it came from the cache
- */
-
- pNode->SetData(pObj);
-
- /* It is to be added to the middle of the list - there is a before
- and after node. Chain it after pAfter, before pBefore.
- */
-
- CNode * pAfter = pBefore->Prev();
- ASSERT(pAfter != NULL);
-
- /* chain it in (set four pointers) */
- pNode->SetPrev(pAfter);
- pNode->SetNext(pBefore);
- pBefore->SetPrev(pNode);
- pAfter->SetNext(pNode);
-
- ++m_Count;
-
- return (POSITION) pNode;
-
-} // Addbefore(object)
-
-
-
-BOOL CBaseList::AddBefore(__in_opt POSITION p, __in CBaseList *pList)
-{
- POSITION pos;
- INTERNALREVERSETRAVERSELIST(*pList, pos) {
- /* p follows along the elements being added */
- p = AddBeforeI(p, pList->GetValidI(pos));
- if (p==NULL) return FALSE;
- }
- return TRUE;
-} // AddBefore(list)
-
-
-
-/* Split *this after position p in *this
- Retain as *this the tail portion of the original *this
- Add the head portion to the tail end of *pList
- Return TRUE if it all worked, FALSE if it didn't.
-
- e.g.
- foo->MoveToTail(foo->GetHeadPosition(), bar);
- moves one element from the head of foo to the tail of bar
- foo->MoveToTail(NULL, bar);
- is a no-op
- foo->MoveToTail(foo->GetTailPosition, bar);
- concatenates foo onto the end of bar and empties foo.
-
- A better, except excessively long name might be
- MoveElementsFromHeadThroughPositionToOtherTail
-*/
-BOOL CBaseList::MoveToTail
- (__in_opt POSITION pos, __in CBaseList *pList)
-{
- /* Algorithm:
- Note that the elements (including their order) in the concatenation
- of *pList to the head of *this is invariant.
- 1. Count elements to be moved
- 2. Join *pList onto the head of this to make one long chain
- 3. Set first/Last pointers in *this and *pList
- 4. Break the chain at the new place
- 5. Adjust counts
- 6. Set/Reset any events
- */
-
- if (pos==NULL) return TRUE; // no-op. Eliminates special cases later.
-
-
- /* Make cMove the number of nodes to move */
- CNode * p = (CNode *)pos;
- int cMove = 0; // number of nodes to move
- while(p!=NULL) {
- p = p->Prev();
- ++cMove;
- }
-
-
- /* Join the two chains together */
- if (pList->m_pLast!=NULL)
- pList->m_pLast->SetNext(m_pFirst);
- if (m_pFirst!=NULL)
- m_pFirst->SetPrev(pList->m_pLast);
-
-
- /* set first and last pointers */
- p = (CNode *)pos;
-
- if (pList->m_pFirst==NULL)
- pList->m_pFirst = m_pFirst;
- m_pFirst = p->Next();
- if (m_pFirst==NULL)
- m_pLast = NULL;
- pList->m_pLast = p;
-
-
- /* Break the chain after p to create the new pieces */
- if (m_pFirst!=NULL)
- m_pFirst->SetPrev(NULL);
- p->SetNext(NULL);
-
-
- /* Adjust the counts */
- m_Count -= cMove;
- pList->m_Count += cMove;
-
- return TRUE;
-
-} // MoveToTail
-
-
-
-/* Mirror image of MoveToTail:
- Split *this before position p in *this.
- Retain in *this the head portion of the original *this
- Add the tail portion to the start (i.e. head) of *pList
- Return TRUE if it all worked, FALSE if it didn't.
-
- e.g.
- foo->MoveToHead(foo->GetTailPosition(), bar);
- moves one element from the tail of foo to the head of bar
- foo->MoveToHead(NULL, bar);
- is a no-op
- foo->MoveToHead(foo->GetHeadPosition, bar);
- concatenates foo onto the start of bar and empties foo.
-*/
-BOOL CBaseList::MoveToHead
- (__in_opt POSITION pos, __in CBaseList *pList)
-{
-
- /* See the comments on the algorithm in MoveToTail */
-
- if (pos==NULL) return TRUE; // no-op. Eliminates special cases later.
-
- /* Make cMove the number of nodes to move */
- CNode * p = (CNode *)pos;
- int cMove = 0; // number of nodes to move
- while(p!=NULL) {
- p = p->Next();
- ++cMove;
- }
-
-
- /* Join the two chains together */
- if (pList->m_pFirst!=NULL)
- pList->m_pFirst->SetPrev(m_pLast);
- if (m_pLast!=NULL)
- m_pLast->SetNext(pList->m_pFirst);
-
-
- /* set first and last pointers */
- p = (CNode *)pos;
-
-
- if (pList->m_pLast==NULL)
- pList->m_pLast = m_pLast;
-
- m_pLast = p->Prev();
- if (m_pLast==NULL)
- m_pFirst = NULL;
- pList->m_pFirst = p;
-
-
- /* Break the chain after p to create the new pieces */
- if (m_pLast!=NULL)
- m_pLast->SetNext(NULL);
- p->SetPrev(NULL);
-
-
- /* Adjust the counts */
- m_Count -= cMove;
- pList->m_Count += cMove;
-
- return TRUE;
-
-} // MoveToHead
-
-
-
-/* Reverse the order of the [pointers to] objects in *this
-*/
-void CBaseList::Reverse()
-{
- /* algorithm:
- The obvious booby trap is that you flip pointers around and lose
- addressability to the node that you are going to process next.
- The easy way to avoid this is do do one chain at a time.
-
- Run along the forward chain,
- For each node, set the reverse pointer to the one ahead of us.
- The reverse chain is now a copy of the old forward chain, including
- the NULL termination.
-
- Run along the reverse chain (i.e. old forward chain again)
- For each node set the forward pointer of the node ahead to point back
- to the one we're standing on.
- The first node needs special treatment,
- it's new forward pointer is NULL.
- Finally set the First/Last pointers
-
- */
- CNode * p;
-
- // Yes we COULD use a traverse, but it would look funny!
- p = m_pFirst;
- while (p!=NULL) {
- CNode * q;
- q = p->Next();
- p->SetNext(p->Prev());
- p->SetPrev(q);
- p = q;
- }
-
- p = m_pFirst;
- m_pFirst = m_pLast;
- m_pLast = p;
-
-
-#if 0 // old version
-
- if (m_pFirst==NULL) return; // empty list
- if (m_pFirst->Next()==NULL) return; // single node list
-
-
- /* run along forward chain */
- for ( p = m_pFirst
- ; p!=NULL
- ; p = p->Next()
- ){
- p->SetPrev(p->Next());
- }
-
-
- /* special case first element */
- m_pFirst->SetNext(NULL); // fix the old first element
-
-
- /* run along new reverse chain i.e. old forward chain again */
- for ( p = m_pFirst // start at the old first element
- ; p->Prev()!=NULL // while there's a node still to be set
- ; p = p->Prev() // work in the same direction as before
- ){
- p->Prev()->SetNext(p);
- }
-
-
- /* fix forward and reverse pointers
- - the triple XOR swap would work but all the casts look hideous */
- p = m_pFirst;
- m_pFirst = m_pLast;
- m_pLast = p;
-#endif
-
-} // Reverse
diff --git a/dll/src/baseclasses/wxlist.h b/dll/src/baseclasses/wxlist.h
deleted file mode 100644
index 47e7123..0000000
--- a/dll/src/baseclasses/wxlist.h
+++ /dev/null
@@ -1,553 +0,0 @@
-//------------------------------------------------------------------------------
-// File: WXList.h
-//
-// Desc: DirectShow base classes - defines a non-MFC generic template list
-// class.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-/* A generic list of pointers to objects.
- No storage management or copying is done on the objects pointed to.
- Objectives: avoid using MFC libraries in ndm kernel mode and
- provide a really useful list type.
-
- The class is thread safe in that separate threads may add and
- delete items in the list concurrently although the application
- must ensure that constructor and destructor access is suitably
- synchronised. An application can cause deadlock with operations
- which use two lists by simultaneously calling
- list1->Operation(list2) and list2->Operation(list1). So don't!
-
- The names must not conflict with MFC classes as an application
- may use both.
- */
-
-#ifndef __WXLIST__
-#define __WXLIST__
-
- /* A POSITION represents (in some fashion that's opaque) a cursor
- on the list that can be set to identify any element. NULL is
- a valid value and several operations regard NULL as the position
- "one step off the end of the list". (In an n element list there
- are n+1 places to insert and NULL is that "n+1-th" value).
- The POSITION of an element in the list is only invalidated if
- that element is deleted. Move operations may mean that what
- was a valid POSITION in one list is now a valid POSITION in
- a different list.
-
- Some operations which at first sight are illegal are allowed as
- harmless no-ops. For instance RemoveHead is legal on an empty
- list and it returns NULL. This allows an atomic way to test if
- there is an element there, and if so, get it. The two operations
- AddTail and RemoveHead thus implement a MONITOR (See Hoare's paper).
-
- Single element operations return POSITIONs, non-NULL means it worked.
- whole list operations return a BOOL. TRUE means it all worked.
-
- This definition is the same as the POSITION type for MFCs, so we must
- avoid defining it twice.
- */
-#ifndef __AFX_H__
-struct __POSITION { int unused; };
-typedef __POSITION* POSITION;
-#endif
-
-const int DEFAULTCACHE = 10; /* Default node object cache size */
-
-/* A class representing one node in a list.
- Each node knows a pointer to it's adjacent nodes and also a pointer
- to the object that it looks after.
- All of these pointers can be retrieved or set through member functions.
-*/
-class CBaseList
-#ifdef DEBUG
- : public CBaseObject
-#endif
-{
- /* Making these classes inherit from CBaseObject does nothing
- functionally but it allows us to check there are no memory
- leaks in debug builds.
- */
-
-public:
-
-#ifdef DEBUG
- class CNode : public CBaseObject {
-#else
- class CNode {
-#endif
-
- CNode *m_pPrev; /* Previous node in the list */
- CNode *m_pNext; /* Next node in the list */
- void *m_pObject; /* Pointer to the object */
-
- public:
-
- /* Constructor - initialise the object's pointers */
- CNode()
-#ifdef DEBUG
- : CBaseObject(NAME("List node"))
-#endif
- {
- };
-
-
- /* Return the previous node before this one */
- __out CNode *Prev() const { return m_pPrev; };
-
-
- /* Return the next node after this one */
- __out CNode *Next() const { return m_pNext; };
-
-
- /* Set the previous node before this one */
- void SetPrev(__in_opt CNode *p) { m_pPrev = p; };
-
-
- /* Set the next node after this one */
- void SetNext(__in_opt CNode *p) { m_pNext = p; };
-
-
- /* Get the pointer to the object for this node */
- __out void *GetData() const { return m_pObject; };
-
-
- /* Set the pointer to the object for this node */
- void SetData(__in void *p) { m_pObject = p; };
- };
-
- class CNodeCache
- {
- public:
- CNodeCache(INT iCacheSize) : m_iCacheSize(iCacheSize),
- m_pHead(NULL),
- m_iUsed(0)
- {};
- ~CNodeCache() {
- CNode *pNode = m_pHead;
- while (pNode) {
- CNode *pCurrent = pNode;
- pNode = pNode->Next();
- delete pCurrent;
- }
- };
- void AddToCache(__inout CNode *pNode)
- {
- if (m_iUsed < m_iCacheSize) {
- pNode->SetNext(m_pHead);
- m_pHead = pNode;
- m_iUsed++;
- } else {
- delete pNode;
- }
- };
- CNode *RemoveFromCache()
- {
- CNode *pNode = m_pHead;
- if (pNode != NULL) {
- m_pHead = pNode->Next();
- m_iUsed--;
- ASSERT(m_iUsed >= 0);
- } else {
- ASSERT(m_iUsed == 0);
- }
- return pNode;
- };
- private:
- INT m_iCacheSize;
- INT m_iUsed;
- CNode *m_pHead;
- };
-
-protected:
-
- CNode* m_pFirst; /* Pointer to first node in the list */
- CNode* m_pLast; /* Pointer to the last node in the list */
- LONG m_Count; /* Number of nodes currently in the list */
-
-private:
-
- CNodeCache m_Cache; /* Cache of unused node pointers */
-
-private:
-
- /* These override the default copy constructor and assignment
- operator for all list classes. They are in the private class
- declaration section so that anybody trying to pass a list
- object by value will generate a compile time error of
- "cannot access the private member function". If these were
- not here then the compiler will create default constructors
- and assignment operators which when executed first take a
- copy of all member variables and then during destruction
- delete them all. This must not be done for any heap
- allocated data.
- */
- CBaseList(const CBaseList &refList);
- CBaseList &operator=(const CBaseList &refList);
-
-public:
-
- CBaseList(__in_opt LPCTSTR pName,
- INT iItems);
-
- CBaseList(__in_opt LPCTSTR pName);
-#ifdef UNICODE
- CBaseList(__in_opt LPCSTR pName,
- INT iItems);
-
- CBaseList(__in_opt LPCSTR pName);
-#endif
- ~CBaseList();
-
- /* Remove all the nodes from *this i.e. make the list empty */
- void RemoveAll();
-
-
- /* Return a cursor which identifies the first element of *this */
- __out_opt POSITION GetHeadPositionI() const;
-
-
- /* Return a cursor which identifies the last element of *this */
- __out_opt POSITION GetTailPositionI() const;
-
-
- /* Return the number of objects in *this */
- int GetCountI() const;
-
-protected:
- /* Return the pointer to the object at rp,
- Update rp to the next node in *this
- but make it NULL if it was at the end of *this.
- This is a wart retained for backwards compatibility.
- GetPrev is not implemented.
- Use Next, Prev and Get separately.
- */
- __out void *GetNextI(__inout POSITION& rp) const;
-
-
- /* Return a pointer to the object at p
- Asking for the object at NULL will return NULL harmlessly.
- */
- __out_opt void *GetI(__in_opt POSITION p) const;
- __out void *GetValidI(__in POSITION p) const;
-
-public:
- /* return the next / prev position in *this
- return NULL when going past the end/start.
- Next(NULL) is same as GetHeadPosition()
- Prev(NULL) is same as GetTailPosition()
- An n element list therefore behaves like a n+1 element
- cycle with NULL at the start/end.
-
- !!WARNING!! - This handling of NULL is DIFFERENT from GetNext.
-
- Some reasons are:
- 1. For a list of n items there are n+1 positions to insert
- These are conveniently encoded as the n POSITIONs and NULL.
- 2. If you are keeping a list sorted (fairly common) and you
- search forward for an element to insert before and don't
- find it you finish up with NULL as the element before which
- to insert. You then want that NULL to be a valid POSITION
- so that you can insert before it and you want that insertion
- point to mean the (n+1)-th one that doesn't have a POSITION.
- (symmetrically if you are working backwards through the list).
- 3. It simplifies the algebra which the methods generate.
- e.g. AddBefore(p,x) is identical to AddAfter(Prev(p),x)
- in ALL cases. All the other arguments probably are reflections
- of the algebraic point.
- */
- __out_opt POSITION Next(__in_opt POSITION pos) const
- {
- if (pos == NULL) {
- return (POSITION) m_pFirst;
- }
- CNode *pn = (CNode *) pos;
- return (POSITION) pn->Next();
- } //Next
-
- // See Next
- __out_opt POSITION Prev(__in_opt POSITION pos) const
- {
- if (pos == NULL) {
- return (POSITION) m_pLast;
- }
- CNode *pn = (CNode *) pos;
- return (POSITION) pn->Prev();
- } //Prev
-
-
- /* Return the first position in *this which holds the given
- pointer. Return NULL if the pointer was not not found.
- */
-protected:
- __out_opt POSITION FindI( __in void * pObj) const;
-
- // ??? Should there be (or even should there be only)
- // ??? POSITION FindNextAfter(void * pObj, POSITION p)
- // ??? And of course FindPrevBefore too.
- // ??? List.Find(&Obj) then becomes List.FindNextAfter(&Obj, NULL)
-
-
- /* Remove the first node in *this (deletes the pointer to its
- object from the list, does not free the object itself).
- Return the pointer to its object.
- If *this was already empty it will harmlessly return NULL.
- */
- __out_opt void *RemoveHeadI();
-
-
- /* Remove the last node in *this (deletes the pointer to its
- object from the list, does not free the object itself).
- Return the pointer to its object.
- If *this was already empty it will harmlessly return NULL.
- */
- __out_opt void *RemoveTailI();
-
-
- /* Remove the node identified by p from the list (deletes the pointer
- to its object from the list, does not free the object itself).
- Asking to Remove the object at NULL will harmlessly return NULL.
- Return the pointer to the object removed.
- */
- __out_opt void *RemoveI(__in_opt POSITION p);
-
- /* Add single object *pObj to become a new last element of the list.
- Return the new tail position, NULL if it fails.
- If you are adding a COM objects, you might want AddRef it first.
- Other existing POSITIONs in *this are still valid
- */
- __out_opt POSITION AddTailI(__in void * pObj);
-public:
-
-
- /* Add all the elements in *pList to the tail of *this.
- This duplicates all the nodes in *pList (i.e. duplicates
- all its pointers to objects). It does not duplicate the objects.
- If you are adding a list of pointers to a COM object into the list
- it's a good idea to AddRef them all it when you AddTail it.
- Return TRUE if it all worked, FALSE if it didn't.
- If it fails some elements may have been added.
- Existing POSITIONs in *this are still valid
-
- If you actually want to MOVE the elements, use MoveToTail instead.
- */
- BOOL AddTail(__in CBaseList *pList);
-
-
- /* Mirror images of AddHead: */
-
- /* Add single object to become a new first element of the list.
- Return the new head position, NULL if it fails.
- Existing POSITIONs in *this are still valid
- */
-protected:
- __out_opt POSITION AddHeadI(__in void * pObj);
-public:
-
- /* Add all the elements in *pList to the head of *this.
- Same warnings apply as for AddTail.
- Return TRUE if it all worked, FALSE if it didn't.
- If it fails some of the objects may have been added.
-
- If you actually want to MOVE the elements, use MoveToHead instead.
- */
- BOOL AddHead(__in CBaseList *pList);
-
-
- /* Add the object *pObj to *this after position p in *this.
- AddAfter(NULL,x) adds x to the start - equivalent to AddHead
- Return the position of the object added, NULL if it failed.
- Existing POSITIONs in *this are undisturbed, including p.
- */
-protected:
- __out_opt POSITION AddAfterI(__in_opt POSITION p, __in void * pObj);
-public:
-
- /* Add the list *pList to *this after position p in *this
- AddAfter(NULL,x) adds x to the start - equivalent to AddHead
- Return TRUE if it all worked, FALSE if it didn't.
- If it fails, some of the objects may be added
- Existing POSITIONs in *this are undisturbed, including p.
- */
- BOOL AddAfter(__in_opt POSITION p, __in CBaseList *pList);
-
-
- /* Mirror images:
- Add the object *pObj to this-List after position p in *this.
- AddBefore(NULL,x) adds x to the end - equivalent to AddTail
- Return the position of the new object, NULL if it fails
- Existing POSITIONs in *this are undisturbed, including p.
- */
- protected:
- __out_opt POSITION AddBeforeI(__in_opt POSITION p, __in void * pObj);
- public:
-
- /* Add the list *pList to *this before position p in *this
- AddAfter(NULL,x) adds x to the start - equivalent to AddHead
- Return TRUE if it all worked, FALSE if it didn't.
- If it fails, some of the objects may be added
- Existing POSITIONs in *this are undisturbed, including p.
- */
- BOOL AddBefore(__in_opt POSITION p, __in CBaseList *pList);
-
-
- /* Note that AddAfter(p,x) is equivalent to AddBefore(Next(p),x)
- even in cases where p is NULL or Next(p) is NULL.
- Similarly for mirror images etc.
- This may make it easier to argue about programs.
- */
-
-
-
- /* The following operations do not copy any elements.
- They move existing blocks of elements around by switching pointers.
- They are fairly efficient for long lists as for short lists.
- (Alas, the Count slows things down).
-
- They split the list into two parts.
- One part remains as the original list, the other part
- is appended to the second list. There are eight possible
- variations:
- Split the list {after/before} a given element
- keep the {head/tail} portion in the original list
- append the rest to the {head/tail} of the new list.
-
- Since After is strictly equivalent to Before Next
- we are not in serious need of the Before/After variants.
- That leaves only four.
-
- If you are processing a list left to right and dumping
- the bits that you have processed into another list as
- you go, the Tail/Tail variant gives the most natural result.
- If you are processing in reverse order, Head/Head is best.
-
- By using NULL positions and empty lists judiciously either
- of the other two can be built up in two operations.
-
- The definition of NULL (see Next/Prev etc) means that
- degenerate cases include
- "move all elements to new list"
- "Split a list into two lists"
- "Concatenate two lists"
- (and quite a few no-ops)
-
- !!WARNING!! The type checking won't buy you much if you get list
- positions muddled up - e.g. use a POSITION that's in a different
- list and see what a mess you get!
- */
-
- /* Split *this after position p in *this
- Retain as *this the tail portion of the original *this
- Add the head portion to the tail end of *pList
- Return TRUE if it all worked, FALSE if it didn't.
-
- e.g.
- foo->MoveToTail(foo->GetHeadPosition(), bar);
- moves one element from the head of foo to the tail of bar
- foo->MoveToTail(NULL, bar);
- is a no-op, returns NULL
- foo->MoveToTail(foo->GetTailPosition, bar);
- concatenates foo onto the end of bar and empties foo.
-
- A better, except excessively long name might be
- MoveElementsFromHeadThroughPositionToOtherTail
- */
- BOOL MoveToTail(__in_opt POSITION pos, __in CBaseList *pList);
-
-
- /* Mirror image:
- Split *this before position p in *this.
- Retain in *this the head portion of the original *this
- Add the tail portion to the start (i.e. head) of *pList
-
- e.g.
- foo->MoveToHead(foo->GetTailPosition(), bar);
- moves one element from the tail of foo to the head of bar
- foo->MoveToHead(NULL, bar);
- is a no-op, returns NULL
- foo->MoveToHead(foo->GetHeadPosition, bar);
- concatenates foo onto the start of bar and empties foo.
- */
- BOOL MoveToHead(__in_opt POSITION pos, __in CBaseList *pList);
-
-
- /* Reverse the order of the [pointers to] objects in *this
- */
- void Reverse();
-
-
- /* set cursor to the position of each element of list in turn */
- #define TRAVERSELIST(list, cursor) \
- for ( cursor = (list).GetHeadPosition() \
- ; cursor!=NULL \
- ; cursor = (list).Next(cursor) \
- )
-
-
- /* set cursor to the position of each element of list in turn
- in reverse order
- */
- #define REVERSETRAVERSELIST(list, cursor) \
- for ( cursor = (list).GetTailPosition() \
- ; cursor!=NULL \
- ; cursor = (list).Prev(cursor) \
- )
-
-}; // end of class declaration
-
-template<class OBJECT> class CGenericList : public CBaseList
-{
-public:
- CGenericList(__in_opt LPCTSTR pName,
- INT iItems,
- BOOL bLock = TRUE,
- BOOL bAlert = FALSE) :
- CBaseList(pName, iItems) {
- UNREFERENCED_PARAMETER(bAlert);
- UNREFERENCED_PARAMETER(bLock);
- };
- CGenericList(__in_opt LPCTSTR pName) :
- CBaseList(pName) {
- };
-
- __out_opt POSITION GetHeadPosition() const { return (POSITION)m_pFirst; }
- __out_opt POSITION GetTailPosition() const { return (POSITION)m_pLast; }
- int GetCount() const { return m_Count; }
-
- __out OBJECT *GetNext(__inout POSITION& rp) const { return (OBJECT *) GetNextI(rp); }
-
- __out_opt OBJECT *Get(__in_opt POSITION p) const { return (OBJECT *) GetI(p); }
- __out OBJECT *GetValid(__in POSITION p) const { return (OBJECT *) GetValidI(p); }
- __out_opt OBJECT *GetHead() const { return Get(GetHeadPosition()); }
-
- __out_opt OBJECT *RemoveHead() { return (OBJECT *) RemoveHeadI(); }
-
- __out_opt OBJECT *RemoveTail() { return (OBJECT *) RemoveTailI(); }
-
- __out_opt OBJECT *Remove(__in_opt POSITION p) { return (OBJECT *) RemoveI(p); }
- __out_opt POSITION AddBefore(__in_opt POSITION p, __in OBJECT * pObj) { return AddBeforeI(p, pObj); }
- __out_opt POSITION AddAfter(__in_opt POSITION p, __in OBJECT * pObj) { return AddAfterI(p, pObj); }
- __out_opt POSITION AddHead(__in OBJECT * pObj) { return AddHeadI(pObj); }
- __out_opt POSITION AddTail(__in OBJECT * pObj) { return AddTailI(pObj); }
- BOOL AddTail(__in CGenericList<OBJECT> *pList)
- { return CBaseList::AddTail((CBaseList *) pList); }
- BOOL AddHead(__in CGenericList<OBJECT> *pList)
- { return CBaseList::AddHead((CBaseList *) pList); }
- BOOL AddAfter(__in_opt POSITION p, __in CGenericList<OBJECT> *pList)
- { return CBaseList::AddAfter(p, (CBaseList *) pList); };
- BOOL AddBefore(__in_opt POSITION p, __in CGenericList<OBJECT> *pList)
- { return CBaseList::AddBefore(p, (CBaseList *) pList); };
- __out_opt POSITION Find( __in OBJECT * pObj) const { return FindI(pObj); }
-}; // end of class declaration
-
-
-
-/* These define the standard list types */
-
-typedef CGenericList<CBaseObject> CBaseObjectList;
-typedef CGenericList<IUnknown> CBaseInterfaceList;
-
-#endif /* __WXLIST__ */
-
diff --git a/dll/src/baseclasses/wxutil.cpp b/dll/src/baseclasses/wxutil.cpp
deleted file mode 100644
index 9fbd497..0000000
--- a/dll/src/baseclasses/wxutil.cpp
+++ /dev/null
@@ -1,755 +0,0 @@
-//------------------------------------------------------------------------------
-// File: WXUtil.cpp
-//
-// Desc: DirectShow base classes - implements helper classes for building
-// multimedia filters.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-#include <streams.h>
-#define STRSAFE_NO_DEPRECATE
-#include <strsafe.h>
-
-#include <VersionHelpers.h>
-
-// --- CAMEvent -----------------------
-CAMEvent::CAMEvent(BOOL fManualReset, __inout_opt HRESULT *phr)
-{
- m_hEvent = CreateEvent(NULL, fManualReset, FALSE, NULL);
- if (NULL == m_hEvent) {
- if (NULL != phr && SUCCEEDED(*phr)) {
- *phr = E_OUTOFMEMORY;
- }
- }
-}
-
-CAMEvent::CAMEvent(__inout_opt HRESULT *phr)
-{
- m_hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
- if (NULL == m_hEvent) {
- if (NULL != phr && SUCCEEDED(*phr)) {
- *phr = E_OUTOFMEMORY;
- }
- }
-}
-
-CAMEvent::~CAMEvent()
-{
- if (m_hEvent) {
- EXECUTE_ASSERT(CloseHandle(m_hEvent));
- }
-}
-
-
-// --- CAMMsgEvent -----------------------
-// One routine. The rest is handled in CAMEvent
-
-CAMMsgEvent::CAMMsgEvent(__inout_opt HRESULT *phr) : CAMEvent(FALSE, phr)
-{
-}
-
-BOOL CAMMsgEvent::WaitMsg(DWORD dwTimeout)
-{
- // wait for the event to be signalled, or for the
- // timeout (in MS) to expire. allow SENT messages
- // to be processed while we wait
- DWORD dwWait;
- DWORD dwStartTime;
-
- // set the waiting period.
- DWORD dwWaitTime = dwTimeout;
-
- // the timeout will eventually run down as we iterate
- // processing messages. grab the start time so that
- // we can calculate elapsed times.
- if (dwWaitTime != INFINITE) {
- dwStartTime = timeGetTime();
- }
-
- do {
- dwWait = MsgWaitForMultipleObjects(1,&m_hEvent,FALSE, dwWaitTime, QS_SENDMESSAGE);
- if (dwWait == WAIT_OBJECT_0 + 1) {
- MSG Message;
- PeekMessage(&Message,NULL,0,0,PM_NOREMOVE);
-
- // If we have an explicit length of time to wait calculate
- // the next wake up point - which might be now.
- // If dwTimeout is INFINITE, it stays INFINITE
- if (dwWaitTime != INFINITE) {
-
- DWORD dwElapsed = timeGetTime()-dwStartTime;
-
- dwWaitTime =
- (dwElapsed >= dwTimeout)
- ? 0 // wake up with WAIT_TIMEOUT
- : dwTimeout-dwElapsed;
- }
- }
- } while (dwWait == WAIT_OBJECT_0 + 1);
-
- // return TRUE if we woke on the event handle,
- // FALSE if we timed out.
- return (dwWait == WAIT_OBJECT_0);
-}
-
-// --- CAMThread ----------------------
-
-
-CAMThread::CAMThread(__inout_opt HRESULT *phr)
- : m_EventSend(TRUE, phr), // must be manual-reset for CheckRequest()
- m_EventComplete(FALSE, phr)
-{
- m_hThread = NULL;
-}
-
-CAMThread::~CAMThread() {
- Close();
-}
-
-
-// when the thread starts, it calls this function. We unwrap the 'this'
-//pointer and call ThreadProc.
-DWORD WINAPI
-CAMThread::InitialThreadProc(__inout LPVOID pv)
-{
- HRESULT hrCoInit = CAMThread::CoInitializeHelper();
- if(FAILED(hrCoInit)) {
- DbgLog((LOG_ERROR, 1, TEXT("CoInitializeEx failed.")));
- }
-
- CAMThread * pThread = (CAMThread *) pv;
-
- HRESULT hr = pThread->ThreadProc();
-
- if(SUCCEEDED(hrCoInit)) {
- CoUninitialize();
- }
-
- return hr;
-}
-
-BOOL
-CAMThread::Create()
-{
- DWORD threadid;
-
- CAutoLock lock(&m_AccessLock);
-
- if (ThreadExists()) {
- return FALSE;
- }
-
- m_hThread = CreateThread(
- NULL,
- 0,
- CAMThread::InitialThreadProc,
- this,
- 0,
- &threadid);
-
- if (!m_hThread) {
- return FALSE;
- }
-
- return TRUE;
-}
-
-DWORD
-CAMThread::CallWorker(DWORD dwParam)
-{
- // lock access to the worker thread for scope of this object
- CAutoLock lock(&m_AccessLock);
-
- if (!ThreadExists()) {
- return (DWORD) E_FAIL;
- }
-
- // set the parameter
- m_dwParam = dwParam;
-
- // signal the worker thread
- m_EventSend.Set();
-
- // wait for the completion to be signalled
- m_EventComplete.Wait();
-
- // done - this is the thread's return value
- return m_dwReturnVal;
-}
-
-// Wait for a request from the client
-DWORD
-CAMThread::GetRequest()
-{
- m_EventSend.Wait();
- return m_dwParam;
-}
-
-// is there a request?
-BOOL
-CAMThread::CheckRequest(__out_opt DWORD * pParam)
-{
- if (!m_EventSend.Check()) {
- return FALSE;
- } else {
- if (pParam) {
- *pParam = m_dwParam;
- }
- return TRUE;
- }
-}
-
-// reply to the request
-void
-CAMThread::Reply(DWORD dw)
-{
- m_dwReturnVal = dw;
-
- // The request is now complete so CheckRequest should fail from
- // now on
- //
- // This event should be reset BEFORE we signal the client or
- // the client may Set it before we reset it and we'll then
- // reset it (!)
-
- m_EventSend.Reset();
-
- // Tell the client we're finished
-
- m_EventComplete.Set();
-}
-
-HRESULT CAMThread::CoInitializeHelper()
-{
- // call CoInitializeEx and tell OLE not to create a window (this
- // thread probably won't dispatch messages and will hang on
- // broadcast msgs o/w).
- //
- // If CoInitEx is not available, threads that don't call CoCreate
- // aren't affected. Threads that do will have to handle the
- // failure. Perhaps we should fall back to CoInitialize and risk
- // hanging?
- //
-
- // older versions of ole32.dll don't have CoInitializeEx
-
- HRESULT hr = E_FAIL;
- HINSTANCE hOle = GetModuleHandle(TEXT("ole32.dll"));
- if(hOle)
- {
- typedef HRESULT (STDAPICALLTYPE *PCoInitializeEx)(
- LPVOID pvReserved, DWORD dwCoInit);
- PCoInitializeEx pCoInitializeEx =
- (PCoInitializeEx)(GetProcAddress(hOle, "CoInitializeEx"));
- if(pCoInitializeEx)
- {
- hr = (*pCoInitializeEx)(0, COINIT_DISABLE_OLE1DDE );
- }
- }
- else
- {
- // caller must load ole32.dll
- DbgBreak("couldn't locate ole32.dll");
- }
-
- return hr;
-}
-
-
-// destructor for CMsgThread - cleans up any messages left in the
-// queue when the thread exited
-CMsgThread::~CMsgThread()
-{
- if (m_hThread != NULL) {
- WaitForSingleObject(m_hThread, INFINITE);
- EXECUTE_ASSERT(CloseHandle(m_hThread));
- }
-
- POSITION pos = m_ThreadQueue.GetHeadPosition();
- while (pos) {
- CMsg * pMsg = m_ThreadQueue.GetNext(pos);
- delete pMsg;
- }
- m_ThreadQueue.RemoveAll();
-
- if (m_hSem != NULL) {
- EXECUTE_ASSERT(CloseHandle(m_hSem));
- }
-}
-
-BOOL
-CMsgThread::CreateThread(
- )
-{
- m_hSem = CreateSemaphore(NULL, 0, 0x7FFFFFFF, NULL);
- if (m_hSem == NULL) {
- return FALSE;
- }
-
- m_hThread = ::CreateThread(NULL, 0, DefaultThreadProc,
- (LPVOID)this, 0, &m_ThreadId);
- return m_hThread != NULL;
-}
-
-
-// This is the threads message pump. Here we get and dispatch messages to
-// clients thread proc until the client refuses to process a message.
-// The client returns a non-zero value to stop the message pump, this
-// value becomes the threads exit code.
-
-DWORD WINAPI
-CMsgThread::DefaultThreadProc(
- __inout LPVOID lpParam
- )
-{
- CMsgThread *lpThis = (CMsgThread *)lpParam;
- CMsg msg;
- LRESULT lResult;
-
- // !!!
- CoInitialize(NULL);
-
- // allow a derived class to handle thread startup
- lpThis->OnThreadInit();
-
- do {
- lpThis->GetThreadMsg(&msg);
- lResult = lpThis->ThreadMessageProc(msg.uMsg,msg.dwFlags,
- msg.lpParam, msg.pEvent);
- } while (lResult == 0L);
-
- // !!!
- CoUninitialize();
-
- return (DWORD)lResult;
-}
-
-
-// Block until the next message is placed on the list m_ThreadQueue.
-// copies the message to the message pointed to by *pmsg
-void
-CMsgThread::GetThreadMsg(__out CMsg *msg)
-{
- CMsg * pmsg = NULL;
-
- // keep trying until a message appears
- while (TRUE) {
- {
- CAutoLock lck(&m_Lock);
- pmsg = m_ThreadQueue.RemoveHead();
- if (pmsg == NULL) {
- m_lWaiting++;
- } else {
- break;
- }
- }
- // the semaphore will be signalled when it is non-empty
- WaitForSingleObject(m_hSem, INFINITE);
- }
- // copy fields to caller's CMsg
- *msg = *pmsg;
-
- // this CMsg was allocated by the 'new' in PutThreadMsg
- delete pmsg;
-
-}
-
-// Helper function - convert int to WSTR
-void WINAPI IntToWstr(int i, __out_ecount(12) LPWSTR wstr)
-{
-#ifdef UNICODE
- if (FAILED(StringCchPrintf(wstr, 12, L"%d", i))) {
- wstr[0] = 0;
- }
-#else
- TCHAR temp[12];
- if (FAILED(StringCchPrintf(temp, NUMELMS(temp), "%d", i))) {
- wstr[0] = 0;
- } else {
- MultiByteToWideChar(CP_ACP, 0, temp, -1, wstr, 12);
- }
-#endif
-} // IntToWstr
-
-
-#define MEMORY_ALIGNMENT 4
-#define MEMORY_ALIGNMENT_LOG2 2
-#define MEMORY_ALIGNMENT_MASK MEMORY_ALIGNMENT - 1
-
-void * __stdcall memmoveInternal(void * dst, const void * src, size_t count)
-{
- void * ret = dst;
-
-#ifdef _X86_
- if (dst <= src || (char *)dst >= ((char *)src + count)) {
-
- /*
- * Non-Overlapping Buffers
- * copy from lower addresses to higher addresses
- */
- _asm {
- mov esi,src
- mov edi,dst
- mov ecx,count
- cld
- mov edx,ecx
- and edx,MEMORY_ALIGNMENT_MASK
- shr ecx,MEMORY_ALIGNMENT_LOG2
- rep movsd
- or ecx,edx
- jz memmove_done
- rep movsb
-memmove_done:
- }
- }
- else {
-
- /*
- * Overlapping Buffers
- * copy from higher addresses to lower addresses
- */
- _asm {
- mov esi,src
- mov edi,dst
- mov ecx,count
- std
- add esi,ecx
- add edi,ecx
- dec esi
- dec edi
- rep movsb
- cld
- }
- }
-#else
- MoveMemory(dst, src, count);
-#endif
-
- return ret;
-}
-
-HRESULT AMSafeMemMoveOffset(
- __in_bcount(dst_size) void * dst,
- __in size_t dst_size,
- __in DWORD cb_dst_offset,
- __in_bcount(src_size) const void * src,
- __in size_t src_size,
- __in DWORD cb_src_offset,
- __in size_t count)
-{
- // prevent read overruns
- if( count + cb_src_offset < count || // prevent integer overflow
- count + cb_src_offset > src_size) // prevent read overrun
- {
- return E_INVALIDARG;
- }
-
- // prevent write overruns
- if( count + cb_dst_offset < count || // prevent integer overflow
- count + cb_dst_offset > dst_size) // prevent write overrun
- {
- return E_INVALIDARG;
- }
-
- memmoveInternal( (BYTE *)dst+cb_dst_offset, (BYTE *)src+cb_src_offset, count);
- return S_OK;
-}
-
-
-#ifdef DEBUG
-/******************************Public*Routine******************************\
-* Debug CCritSec helpers
-*
-* We provide debug versions of the Constructor, destructor, Lock and Unlock
-* routines. The debug code tracks who owns each critical section by
-* maintaining a depth count.
-*
-* History:
-*
-\**************************************************************************/
-
-CCritSec::CCritSec()
-{
- InitializeCriticalSection(&m_CritSec);
- m_currentOwner = m_lockCount = 0;
- m_fTrace = FALSE;
-}
-
-CCritSec::~CCritSec()
-{
- DeleteCriticalSection(&m_CritSec);
-}
-
-void CCritSec::Lock()
-{
- UINT tracelevel=3;
- DWORD us = GetCurrentThreadId();
- DWORD currentOwner = m_currentOwner;
- if (currentOwner && (currentOwner != us)) {
- // already owned, but not by us
- if (m_fTrace) {
- DbgLog((LOG_LOCKING, 2, TEXT("Thread %d about to wait for lock %x owned by %d"),
- GetCurrentThreadId(), &m_CritSec, currentOwner));
- tracelevel=2;
- // if we saw the message about waiting for the critical
- // section we ensure we see the message when we get the
- // critical section
- }
- }
- EnterCriticalSection(&m_CritSec);
- if (0 == m_lockCount++) {
- // we now own it for the first time. Set owner information
- m_currentOwner = us;
-
- if (m_fTrace) {
- DbgLog((LOG_LOCKING, tracelevel, TEXT("Thread %d now owns lock %x"), m_currentOwner, &m_CritSec));
- }
- }
-}
-
-void CCritSec::Unlock() {
- if (0 == --m_lockCount) {
- // about to be unowned
- if (m_fTrace) {
- DbgLog((LOG_LOCKING, 3, TEXT("Thread %d releasing lock %x"), m_currentOwner, &m_CritSec));
- }
-
- m_currentOwner = 0;
- }
- LeaveCriticalSection(&m_CritSec);
-}
-
-void WINAPI DbgLockTrace(CCritSec * pcCrit, BOOL fTrace)
-{
- pcCrit->m_fTrace = fTrace;
-}
-
-BOOL WINAPI CritCheckIn(CCritSec * pcCrit)
-{
- return (GetCurrentThreadId() == pcCrit->m_currentOwner);
-}
-
-BOOL WINAPI CritCheckIn(const CCritSec * pcCrit)
-{
- return (GetCurrentThreadId() == pcCrit->m_currentOwner);
-}
-
-BOOL WINAPI CritCheckOut(CCritSec * pcCrit)
-{
- return (GetCurrentThreadId() != pcCrit->m_currentOwner);
-}
-
-BOOL WINAPI CritCheckOut(const CCritSec * pcCrit)
-{
- return (GetCurrentThreadId() != pcCrit->m_currentOwner);
-}
-#endif
-
-
-STDAPI WriteBSTR(__deref_out BSTR *pstrDest, LPCWSTR szSrc)
-{
- *pstrDest = SysAllocString( szSrc );
- if( !(*pstrDest) ) return E_OUTOFMEMORY;
- return NOERROR;
-}
-
-
-STDAPI FreeBSTR(__deref_in BSTR* pstr)
-{
- if( (PVOID)*pstr == NULL ) return S_FALSE;
- SysFreeString( *pstr );
- return NOERROR;
-}
-
-
-// Return a wide string - allocating memory for it
-// Returns:
-// S_OK - no error
-// E_POINTER - ppszReturn == NULL
-// E_OUTOFMEMORY - can't allocate memory for returned string
-STDAPI AMGetWideString(LPCWSTR psz, __deref_out LPWSTR *ppszReturn)
-{
- CheckPointer(ppszReturn, E_POINTER);
- ValidateReadWritePtr(ppszReturn, sizeof(LPWSTR));
- *ppszReturn = NULL;
- size_t nameLen;
- HRESULT hr = StringCbLengthW(psz, 100000, &nameLen);
- if (FAILED(hr)) {
- return hr;
- }
- *ppszReturn = (LPWSTR)CoTaskMemAlloc(nameLen + sizeof(WCHAR));
- if (*ppszReturn == NULL) {
- return E_OUTOFMEMORY;
- }
- CopyMemory(*ppszReturn, psz, nameLen + sizeof(WCHAR));
- return NOERROR;
-}
-
-// Waits for the HANDLE hObject. While waiting messages sent
-// to windows on our thread by SendMessage will be processed.
-// Using this function to do waits and mutual exclusion
-// avoids some deadlocks in objects with windows.
-// Return codes are the same as for WaitForSingleObject
-DWORD WINAPI WaitDispatchingMessages(
- HANDLE hObject,
- DWORD dwWait,
- HWND hwnd,
- UINT uMsg,
- HANDLE hEvent)
-{
- BOOL bPeeked = FALSE;
- DWORD dwResult;
- DWORD dwStart;
- DWORD dwThreadPriority;
-
- static UINT uMsgId = 0;
-
- HANDLE hObjects[2] = { hObject, hEvent };
- if (dwWait != INFINITE && dwWait != 0) {
- dwStart = GetTickCount();
- }
- for (; ; ) {
- DWORD nCount = NULL != hEvent ? 2 : 1;
-
- // Minimize the chance of actually dispatching any messages
- // by seeing if we can lock immediately.
- dwResult = WaitForMultipleObjects(nCount, hObjects, FALSE, 0);
- if (dwResult < WAIT_OBJECT_0 + nCount) {
- break;
- }
-
- DWORD dwTimeOut = dwWait;
- if (dwTimeOut > 10) {
- dwTimeOut = 10;
- }
- dwResult = MsgWaitForMultipleObjects(
- nCount,
- hObjects,
- FALSE,
- dwTimeOut,
- hwnd == NULL ? QS_SENDMESSAGE :
- QS_SENDMESSAGE + QS_POSTMESSAGE);
- if (dwResult == WAIT_OBJECT_0 + nCount ||
- dwResult == WAIT_TIMEOUT && dwTimeOut != dwWait) {
- MSG msg;
- if (hwnd != NULL) {
- while (PeekMessage(&msg, hwnd, uMsg, uMsg, PM_REMOVE)) {
- DispatchMessage(&msg);
- }
- }
- // Do this anyway - the previous peek doesn't flush out the
- // messages
- PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
-
- if (dwWait != INFINITE && dwWait != 0) {
- DWORD dwNow = GetTickCount();
-
- // Working with differences handles wrap-around
- DWORD dwDiff = dwNow - dwStart;
- if (dwDiff > dwWait) {
- dwWait = 0;
- } else {
- dwWait -= dwDiff;
- }
- dwStart = dwNow;
- }
- if (!bPeeked) {
- // Raise our priority to prevent our message queue
- // building up
- dwThreadPriority = GetThreadPriority(GetCurrentThread());
- if (dwThreadPriority < THREAD_PRIORITY_HIGHEST) {
- SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
- }
- bPeeked = TRUE;
- }
- } else {
- break;
- }
- }
- if (bPeeked) {
- SetThreadPriority(GetCurrentThread(), dwThreadPriority);
- if (HIWORD(GetQueueStatus(QS_POSTMESSAGE)) & QS_POSTMESSAGE) {
- if (uMsgId == 0) {
- uMsgId = RegisterWindowMessage(TEXT("AMUnblock"));
- }
- if (uMsgId != 0) {
- MSG msg;
- // Remove old ones
- while (PeekMessage(&msg, (HWND)-1, uMsgId, uMsgId, PM_REMOVE)) {
- }
- }
- PostThreadMessage(GetCurrentThreadId(), uMsgId, 0, 0);
- }
- }
- return dwResult;
-}
-
-HRESULT AmGetLastErrorToHResult()
-{
- DWORD dwLastError = GetLastError();
- if(dwLastError != 0)
- {
- return HRESULT_FROM_WIN32(dwLastError);
- }
- else
- {
- return E_FAIL;
- }
-}
-
-IUnknown* QzAtlComPtrAssign(__deref_inout_opt IUnknown** pp, __in_opt IUnknown* lp)
-{
- if (lp != NULL)
- lp->AddRef();
- if (*pp)
- (*pp)->Release();
- *pp = lp;
- return lp;
-}
-
-/******************************************************************************
-
-CompatibleTimeSetEvent
-
- CompatibleTimeSetEvent() sets the TIME_KILL_SYNCHRONOUS flag before calling
-timeSetEvent() if the current operating system supports it. TIME_KILL_SYNCHRONOUS
-is supported on Windows XP and later operating systems.
-
-Parameters:
-- The same parameters as timeSetEvent(). See timeSetEvent()'s documentation in
-the Platform SDK for more information.
-
-Return Value:
-- The same return value as timeSetEvent(). See timeSetEvent()'s documentation in
-the Platform SDK for more information.
-
-******************************************************************************/
-MMRESULT CompatibleTimeSetEvent( UINT uDelay, UINT uResolution, __in LPTIMECALLBACK lpTimeProc, DWORD_PTR dwUser, UINT fuEvent )
-{
- #if WINVER >= 0x0501
- {
- static bool fCheckedVersion = false;
- static bool fTimeKillSynchronousFlagAvailable = false;
-
- if( !fCheckedVersion ) {
- fTimeKillSynchronousFlagAvailable = TimeKillSynchronousFlagAvailable();
- fCheckedVersion = true;
- }
-
- if( fTimeKillSynchronousFlagAvailable ) {
- fuEvent = fuEvent | TIME_KILL_SYNCHRONOUS;
- }
- }
- #endif // WINVER >= 0x0501
-
- return timeSetEvent( uDelay, uResolution, lpTimeProc, dwUser, fuEvent );
-}
-
-bool TimeKillSynchronousFlagAvailable( void )
-{
- return IsWindowsXPOrGreater();
-}
-
-
diff --git a/dll/src/baseclasses/wxutil.h b/dll/src/baseclasses/wxutil.h
deleted file mode 100644
index 305974a..0000000
--- a/dll/src/baseclasses/wxutil.h
+++ /dev/null
@@ -1,532 +0,0 @@
-//------------------------------------------------------------------------------
-// File: WXUtil.h
-//
-// Desc: DirectShow base classes - defines helper classes and functions for
-// building multimedia filters.
-//
-// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
-//------------------------------------------------------------------------------
-
-
-#ifndef __WXUTIL__
-#define __WXUTIL__
-
-// eliminate spurious "statement has no effect" warnings.
-#pragma warning(disable: 4705)
-
-// wrapper for whatever critical section we have
-class CCritSec {
-
- // make copy constructor and assignment operator inaccessible
-
- CCritSec(const CCritSec &refCritSec);
- CCritSec &operator=(const CCritSec &refCritSec);
-
- CRITICAL_SECTION m_CritSec;
-
-#ifdef DEBUG
-public:
- DWORD m_currentOwner;
- DWORD m_lockCount;
- BOOL m_fTrace; // Trace this one
-public:
- CCritSec();
- ~CCritSec();
- void Lock();
- void Unlock();
-#else
-
-public:
- CCritSec() {
- InitializeCriticalSection(&m_CritSec);
- };
-
- ~CCritSec() {
- DeleteCriticalSection(&m_CritSec);
- };
-
- void Lock() {
- EnterCriticalSection(&m_CritSec);
- };
-
- void Unlock() {
- LeaveCriticalSection(&m_CritSec);
- };
-#endif
-};
-
-//
-// To make deadlocks easier to track it is useful to insert in the
-// code an assertion that says whether we own a critical section or
-// not. We make the routines that do the checking globals to avoid
-// having different numbers of member functions in the debug and
-// retail class implementations of CCritSec. In addition we provide
-// a routine that allows usage of specific critical sections to be
-// traced. This is NOT on by default - there are far too many.
-//
-
-#ifdef DEBUG
- BOOL WINAPI CritCheckIn(CCritSec * pcCrit);
- BOOL WINAPI CritCheckIn(const CCritSec * pcCrit);
- BOOL WINAPI CritCheckOut(CCritSec * pcCrit);
- BOOL WINAPI CritCheckOut(const CCritSec * pcCrit);
- void WINAPI DbgLockTrace(CCritSec * pcCrit, BOOL fTrace);
-#else
- #define CritCheckIn(x) TRUE
- #define CritCheckOut(x) TRUE
- #define DbgLockTrace(pc, fT)
-#endif
-
-
-// locks a critical section, and unlocks it automatically
-// when the lock goes out of scope
-class CAutoLock {
-
- // make copy constructor and assignment operator inaccessible
-
- CAutoLock(const CAutoLock &refAutoLock);
- CAutoLock &operator=(const CAutoLock &refAutoLock);
-
-protected:
- CCritSec * m_pLock;
-
-public:
- CAutoLock(CCritSec * plock)
- {
- m_pLock = plock;
- m_pLock->Lock();
- };
-
- ~CAutoLock() {
- m_pLock->Unlock();
- };
-};
-
-
-
-// wrapper for event objects
-class CAMEvent
-{
-
- // make copy constructor and assignment operator inaccessible
-
- CAMEvent(const CAMEvent &refEvent);
- CAMEvent &operator=(const CAMEvent &refEvent);
-
-protected:
- HANDLE m_hEvent;
-public:
- CAMEvent(BOOL fManualReset = FALSE, __inout_opt HRESULT *phr = NULL);
- CAMEvent(__inout_opt HRESULT *phr);
- ~CAMEvent();
-
- // Cast to HANDLE - we don't support this as an lvalue
- operator HANDLE () const { return m_hEvent; };
-
- void Set() {EXECUTE_ASSERT(SetEvent(m_hEvent));};
- BOOL Wait(DWORD dwTimeout = INFINITE) {
- return (WaitForSingleObject(m_hEvent, dwTimeout) == WAIT_OBJECT_0);
- };
- void Reset() { ResetEvent(m_hEvent); };
- BOOL Check() { return Wait(0); };
-};
-
-
-// wrapper for event objects that do message processing
-// This adds ONE method to the CAMEvent object to allow sent
-// messages to be processed while waiting
-
-class CAMMsgEvent : public CAMEvent
-{
-
-public:
-
- CAMMsgEvent(__inout_opt HRESULT *phr = NULL);
-
- // Allow SEND messages to be processed while waiting
- BOOL WaitMsg(DWORD dwTimeout = INFINITE);
-};
-
-// old name supported for the time being
-#define CTimeoutEvent CAMEvent
-
-// support for a worker thread
-
-#ifdef AM_NOVTABLE
-// simple thread class supports creation of worker thread, synchronization
-// and communication. Can be derived to simplify parameter passing
-class AM_NOVTABLE CAMThread {
-
- // make copy constructor and assignment operator inaccessible
-
- CAMThread(const CAMThread &refThread);
- CAMThread &operator=(const CAMThread &refThread);
-
- CAMEvent m_EventSend;
- CAMEvent m_EventComplete;
-
- DWORD m_dwParam;
- DWORD m_dwReturnVal;
-
-protected:
- HANDLE m_hThread;
-
- // thread will run this function on startup
- // must be supplied by derived class
- virtual DWORD ThreadProc() = 0;
-
-public:
- CAMThread(__inout_opt HRESULT *phr = NULL);
- virtual ~CAMThread();
-
- CCritSec m_AccessLock; // locks access by client threads
- CCritSec m_WorkerLock; // locks access to shared objects
-
- // thread initially runs this. param is actually 'this'. function
- // just gets this and calls ThreadProc
- static DWORD WINAPI InitialThreadProc(__inout LPVOID pv);
-
- // start thread running - error if already running
- BOOL Create();
-
- // signal the thread, and block for a response
- //
- DWORD CallWorker(DWORD);
-
- // accessor thread calls this when done with thread (having told thread
- // to exit)
- void Close() {
-
- // Disable warning: Conversion from LONG to PVOID of greater size
-#pragma warning(push)
-#pragma warning(disable: 4312)
- HANDLE hThread = (HANDLE)InterlockedExchangePointer(&m_hThread, 0);
-#pragma warning(pop)
-
- if (hThread) {
- WaitForSingleObject(hThread, INFINITE);
- CloseHandle(hThread);
- }
- };
-
- // ThreadExists
- // Return TRUE if the thread exists. FALSE otherwise
- BOOL ThreadExists(void) const
- {
- if (m_hThread == 0) {
- return FALSE;
- } else {
- return TRUE;
- }
- }
-
- // wait for the next request
- DWORD GetRequest();
-
- // is there a request?
- BOOL CheckRequest(__out_opt DWORD * pParam);
-
- // reply to the request
- void Reply(DWORD);
-
- // If you want to do WaitForMultipleObjects you'll need to include
- // this handle in your wait list or you won't be responsive
- HANDLE GetRequestHandle() const { return m_EventSend; };
-
- // Find out what the request was
- DWORD GetRequestParam() const { return m_dwParam; };
-
- // call CoInitializeEx (COINIT_DISABLE_OLE1DDE) if
- // available. S_FALSE means it's not available.
- static HRESULT CoInitializeHelper();
-};
-#endif // AM_NOVTABLE
-
-
-// CQueue
-//
-// Implements a simple Queue ADT. The queue contains a finite number of
-// objects, access to which is controlled by a semaphore. The semaphore
-// is created with an initial count (N). Each time an object is added
-// a call to WaitForSingleObject is made on the semaphore's handle. When
-// this function returns a slot has been reserved in the queue for the new
-// object. If no slots are available the function blocks until one becomes
-// available. Each time an object is removed from the queue ReleaseSemaphore
-// is called on the semaphore's handle, thus freeing a slot in the queue.
-// If no objects are present in the queue the function blocks until an
-// object has been added.
-
-#define DEFAULT_QUEUESIZE 2
-
-template <class T> class CQueue {
-private:
- HANDLE hSemPut; // Semaphore controlling queue "putting"
- HANDLE hSemGet; // Semaphore controlling queue "getting"
- CRITICAL_SECTION CritSect; // Thread seriallization
- int nMax; // Max objects allowed in queue
- int iNextPut; // Array index of next "PutMsg"
- int iNextGet; // Array index of next "GetMsg"
- T *QueueObjects; // Array of objects (ptr's to void)
-
- void Initialize(int n) {
- iNextPut = iNextGet = 0;
- nMax = n;
- InitializeCriticalSection(&CritSect);
- hSemPut = CreateSemaphore(NULL, n, n, NULL);
- hSemGet = CreateSemaphore(NULL, 0, n, NULL);
- QueueObjects = new T[n];
- }
-
-
-public:
- CQueue(int n) {
- Initialize(n);
- }
-
- CQueue() {
- Initialize(DEFAULT_QUEUESIZE);
- }
-
- ~CQueue() {
- delete [] QueueObjects;
- DeleteCriticalSection(&CritSect);
- CloseHandle(hSemPut);
- CloseHandle(hSemGet);
- }
-
- T GetQueueObject() {
- int iSlot;
- T Object;
- LONG lPrevious;
-
- // Wait for someone to put something on our queue, returns straight
- // away is there is already an object on the queue.
- //
- WaitForSingleObject(hSemGet, INFINITE);
-
- EnterCriticalSection(&CritSect);
- iSlot = iNextGet++ % nMax;
- Object = QueueObjects[iSlot];
- LeaveCriticalSection(&CritSect);
-
- // Release anyone waiting to put an object onto our queue as there
- // is now space available in the queue.
- //
- ReleaseSemaphore(hSemPut, 1L, &lPrevious);
- return Object;
- }
-
- void PutQueueObject(T Object) {
- int iSlot;
- LONG lPrevious;
-
- // Wait for someone to get something from our queue, returns straight
- // away is there is already an empty slot on the queue.
- //
- WaitForSingleObject(hSemPut, INFINITE);
-
- EnterCriticalSection(&CritSect);
- iSlot = iNextPut++ % nMax;
- QueueObjects[iSlot] = Object;
- LeaveCriticalSection(&CritSect);
-
- // Release anyone waiting to remove an object from our queue as there
- // is now an object available to be removed.
- //
- ReleaseSemaphore(hSemGet, 1L, &lPrevious);
- }
-};
-
-// Ensures that memory is not read past the length source buffer
-// and that memory is not written past the length of the dst buffer
-// dst - buffer to copy to
-// dst_size - total size of destination buffer
-// cb_dst_offset - offset, first byte copied to dst+cb_dst_offset
-// src - buffer to copy from
-// src_size - total size of source buffer
-// cb_src_offset - offset, first byte copied from src+cb_src_offset
-// count - number of bytes to copy
-//
-// Returns:
-// S_OK - no error
-// E_INVALIDARG - values passed would lead to overrun
-HRESULT AMSafeMemMoveOffset(
- __in_bcount(dst_size) void * dst,
- __in size_t dst_size,
- __in DWORD cb_dst_offset,
- __in_bcount(src_size) const void * src,
- __in size_t src_size,
- __in DWORD cb_src_offset,
- __in size_t count);
-
-extern "C"
-void * __stdcall memmoveInternal(void *, const void *, size_t);
-
-inline void * __cdecl memchrInternal(const void *buf, int chr, size_t cnt)
-{
-#ifdef _X86_
- void *pRet = NULL;
-
- _asm {
- cld // make sure we get the direction right
- mov ecx, cnt // num of bytes to scan
- mov edi, buf // pointer byte stream
- mov eax, chr // byte to scan for
- repne scasb // look for the byte in the byte stream
- jnz exit_memchr // Z flag set if byte found
- dec edi // scasb always increments edi even when it
- // finds the required byte
- mov pRet, edi
-exit_memchr:
- }
- return pRet;
-
-#else
- while ( cnt && (*(unsigned char *)buf != (unsigned char)chr) ) {
- buf = (unsigned char *)buf + 1;
- cnt--;
- }
-
- return(cnt ? (void *)buf : NULL);
-#endif
-}
-
-void WINAPI IntToWstr(int i, __out_ecount(12) LPWSTR wstr);
-
-#define WstrToInt(sz) _wtoi(sz)
-#define atoiW(sz) _wtoi(sz)
-#define atoiA(sz) atoi(sz)
-
-// These are available to help managing bitmap VIDEOINFOHEADER media structures
-
-extern const DWORD bits555[3];
-extern const DWORD bits565[3];
-extern const DWORD bits888[3];
-
-// These help convert between VIDEOINFOHEADER and BITMAPINFO structures
-
-STDAPI_(const GUID) GetTrueColorType(const BITMAPINFOHEADER *pbmiHeader);
-STDAPI_(const GUID) GetBitmapSubtype(const BITMAPINFOHEADER *pbmiHeader);
-STDAPI_(WORD) GetBitCount(const GUID *pSubtype);
-
-// strmbase.lib implements this for compatibility with people who
-// managed to link to this directly. we don't want to advertise it.
-//
-// STDAPI_(/* T */ CHAR *) GetSubtypeName(const GUID *pSubtype);
-
-STDAPI_(CHAR *) GetSubtypeNameA(const GUID *pSubtype);
-STDAPI_(WCHAR *) GetSubtypeNameW(const GUID *pSubtype);
-
-#ifdef UNICODE
-#define GetSubtypeName GetSubtypeNameW
-#else
-#define GetSubtypeName GetSubtypeNameA
-#endif
-
-STDAPI_(LONG) GetBitmapFormatSize(const BITMAPINFOHEADER *pHeader);
-STDAPI_(DWORD) GetBitmapSize(const BITMAPINFOHEADER *pHeader);
-
-#ifdef __AMVIDEO__
-STDAPI_(BOOL) ContainsPalette(const VIDEOINFOHEADER *pVideoInfo);
-STDAPI_(const RGBQUAD *) GetBitmapPalette(const VIDEOINFOHEADER *pVideoInfo);
-#endif // __AMVIDEO__
-
-
-// Compares two interfaces and returns TRUE if they are on the same object
-BOOL WINAPI IsEqualObject(IUnknown *pFirst, IUnknown *pSecond);
-
-// This is for comparing pins
-#define EqualPins(pPin1, pPin2) IsEqualObject(pPin1, pPin2)
-
-
-// Arithmetic helper functions
-
-// Compute (a * b + rnd) / c
-LONGLONG WINAPI llMulDiv(LONGLONG a, LONGLONG b, LONGLONG c, LONGLONG rnd);
-LONGLONG WINAPI Int64x32Div32(LONGLONG a, LONG b, LONG c, LONG rnd);
-
-
-// Avoids us dyna-linking to SysAllocString to copy BSTR strings
-STDAPI WriteBSTR(__deref_out BSTR * pstrDest, LPCWSTR szSrc);
-STDAPI FreeBSTR(__deref_in BSTR* pstr);
-
-// Return a wide string - allocating memory for it
-// Returns:
-// S_OK - no error
-// E_POINTER - ppszReturn == NULL
-// E_OUTOFMEMORY - can't allocate memory for returned string
-STDAPI AMGetWideString(LPCWSTR pszString, __deref_out LPWSTR *ppszReturn);
-
-// Special wait for objects owning windows
-DWORD WINAPI WaitDispatchingMessages(
- HANDLE hObject,
- DWORD dwWait,
- HWND hwnd = NULL,
- UINT uMsg = 0,
- HANDLE hEvent = NULL);
-
-// HRESULT_FROM_WIN32 converts ERROR_SUCCESS to a success code, but in
-// our use of HRESULT_FROM_WIN32, it typically means a function failed
-// to call SetLastError(), and we still want a failure code.
-//
-#define AmHresultFromWin32(x) (MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, x))
-
-// call GetLastError and return an HRESULT value that will fail the
-// SUCCEEDED() macro.
-HRESULT AmGetLastErrorToHResult(void);
-
-// duplicate of ATL's CComPtr to avoid linker conflicts.
-
-IUnknown* QzAtlComPtrAssign(__deref_inout_opt IUnknown** pp, __in_opt IUnknown* lp);
-
-template <class T>
-class QzCComPtr
-{
-public:
- typedef T _PtrClass;
- QzCComPtr() {p=NULL;}
- QzCComPtr(T* lp)
- {
- if ((p = lp) != NULL)
- p->AddRef();
- }
- QzCComPtr(const QzCComPtr<T>& lp)
- {
- if ((p = lp.p) != NULL)
- p->AddRef();
- }
- ~QzCComPtr() {if (p) p->Release();}
- void Release() {if (p) p->Release(); p=NULL;}
- operator T*() {return (T*)p;}
- T& operator*() {ASSERT(p!=NULL); return *p; }
- //The assert on operator& usually indicates a bug. If this is really
- //what is needed, however, take the address of the p member explicitly.
- T** operator&() { ASSERT(p==NULL); return &p; }
- T* operator->() { ASSERT(p!=NULL); return p; }
- T* operator=(T* lp){return (T*)QzAtlComPtrAssign((IUnknown**)&p, lp);}
- T* operator=(const QzCComPtr<T>& lp)
- {
- return (T*)QzAtlComPtrAssign((IUnknown**)&p, lp.p);
- }
-#if _MSC_VER>1020
- bool operator!(){return (p == NULL);}
-#else
- BOOL operator!(){return (p == NULL) ? TRUE : FALSE;}
-#endif
- T* p;
-};
-
-MMRESULT CompatibleTimeSetEvent( UINT uDelay, UINT uResolution, __in LPTIMECALLBACK lpTimeProc, DWORD_PTR dwUser, UINT fuEvent );
-bool TimeKillSynchronousFlagAvailable( void );
-
-// Helper to replace lstrcpmi
-__inline int lstrcmpiLocaleIndependentW(LPCWSTR lpsz1, LPCWSTR lpsz2)
-{
- return CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, lpsz1, -1, lpsz2, -1) - CSTR_EQUAL;
-}
-__inline int lstrcmpiLocaleIndependentA(LPCSTR lpsz1, LPCSTR lpsz2)
-{
- return CompareStringA(LOCALE_INVARIANT, NORM_IGNORECASE, lpsz1, -1, lpsz2, -1) - CSTR_EQUAL;
-}
-
-#endif /* __WXUTIL__ */
diff --git a/dll/src/bs2b.vcxproj b/dll/src/bs2b.vcxproj
deleted file mode 100644
index 283dc11..0000000
--- a/dll/src/bs2b.vcxproj
+++ /dev/null
@@ -1,81 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup Label="ProjectConfigurations">
- <ProjectConfiguration Include="Debug|Win32">
- <Configuration>Debug</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Debug|x64">
- <Configuration>Debug</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|Win32">
- <Configuration>Release</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|x64">
- <Configuration>Release</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- </ItemGroup>
- <PropertyGroup Label="Globals">
- <ProjectGuid>{C59B751C-F10D-4DE0-B580-73CB03B27B6E}</ProjectGuid>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
- <Import Project="..\base.props" />
- <PropertyGroup Label="Configuration">
- <CharacterSet>Unicode</CharacterSet>
- <ConfigurationType>StaticLibrary</ConfigurationType>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
- <UseDebugLibraries>true</UseDebugLibraries>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
- <UseDebugLibraries>false</UseDebugLibraries>
- <WholeProgramOptimization>true</WholeProgramOptimization>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
- <ImportGroup Label="ExtensionSettings">
- </ImportGroup>
- <ImportGroup Label="PropertySheets">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <ItemDefinitionGroup>
- <ClCompile>
- <WarningLevel>Level3</WarningLevel>
- <SDLCheck>true</SDLCheck>
- <MultiProcessorCompilation>true</MultiProcessorCompilation>
- </ClCompile>
- <Link>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- </Link>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
- <ClCompile>
- <Optimization>Disabled</Optimization>
- <MinimalRebuild>false</MinimalRebuild>
- </ClCompile>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
- <ClCompile>
- <Optimization>MaxSpeed</Optimization>
- <FunctionLevelLinking>true</FunctionLevelLinking>
- <IntrinsicFunctions>true</IntrinsicFunctions>
- </ClCompile>
- <Link>
- <EnableCOMDATFolding>true</EnableCOMDATFolding>
- <OptimizeReferences>true</OptimizeReferences>
- </Link>
- </ItemDefinitionGroup>
- <ItemGroup>
- <ClCompile Include="libbs2b\src\bs2b.c" />
- <ClCompile Include="libbs2b\src\bs2bclass.cpp" />
- </ItemGroup>
- <ItemGroup>
- <ClInclude Include="libbs2b\src\bs2b.h" />
- <ClInclude Include="libbs2b\src\bs2bclass.h" />
- </ItemGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
- <ImportGroup Label="ExtensionTargets">
- </ImportGroup>
-</Project> \ No newline at end of file
diff --git a/dll/src/libbs2b b/dll/src/libbs2b
deleted file mode 160000
-Subproject 5ca2d59888df047f1e4b028e3a2fd5be8b5a727
diff --git a/dll/src/sanear-dll.vcxproj b/dll/src/sanear-dll.vcxproj
deleted file mode 100644
index 3e24a91..0000000
--- a/dll/src/sanear-dll.vcxproj
+++ /dev/null
@@ -1,158 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup Label="ProjectConfigurations">
- <ProjectConfiguration Include="Debug|Win32">
- <Configuration>Debug</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Debug|x64">
- <Configuration>Debug</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|Win32">
- <Configuration>Release</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|x64">
- <Configuration>Release</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- </ItemGroup>
- <PropertyGroup Label="Globals">
- <ProjectGuid>{E02FD084-ED17-46C7-B5A6-F0BBB7966BBB}</ProjectGuid>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
- <Import Project="..\base.props" />
- <PropertyGroup Label="Configuration">
- <CharacterSet>Unicode</CharacterSet>
- <ConfigurationType>DynamicLibrary</ConfigurationType>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
- <UseDebugLibraries>true</UseDebugLibraries>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
- <UseDebugLibraries>false</UseDebugLibraries>
- <WholeProgramOptimization>true</WholeProgramOptimization>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
- <ImportGroup Label="ExtensionSettings">
- </ImportGroup>
- <ImportGroup Label="PropertySheets">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <PropertyGroup>
- <OutDir>$(BinDir)</OutDir>
- <TargetExt>.ax</TargetExt>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Platform)'=='Win32'">
- <TargetName>sanear</TargetName>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Platform)'=='x64'">
- <TargetName>sanear64</TargetName>
- </PropertyGroup>
- <ItemDefinitionGroup>
- <ClCompile>
- <WarningLevel>Level3</WarningLevel>
- <SDLCheck>true</SDLCheck>
- <MultiProcessorCompilation>true</MultiProcessorCompilation>
- <PrecompiledHeader>Use</PrecompiledHeader>
- <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
- <AdditionalIncludeDirectories>baseclasses</AdditionalIncludeDirectories>
- </ClCompile>
- <Link>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- <ModuleDefinitionFile>sanear-dll/sanear.def</ModuleDefinitionFile>
- <AdditionalDependencies>Comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
- </Link>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
- <ClCompile>
- <Optimization>Disabled</Optimization>
- <MinimalRebuild>false</MinimalRebuild>
- </ClCompile>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
- <ClCompile>
- <Optimization>MaxSpeed</Optimization>
- <FunctionLevelLinking>true</FunctionLevelLinking>
- <IntrinsicFunctions>true</IntrinsicFunctions>
- </ClCompile>
- <Link>
- <EnableCOMDATFolding>true</EnableCOMDATFolding>
- <OptimizeReferences>true</OptimizeReferences>
- </Link>
- </ItemDefinitionGroup>
- <ItemGroup>
- <ProjectReference Include="..\..\sanear.vcxproj">
- <Project>{bb2b61af-734a-4dad-9326-07f4f9ea088f}</Project>
- </ProjectReference>
- <ProjectReference Include="baseclasses.vcxproj">
- <Project>{b8375339-1932-4cc0-ae5b-257672078e41}</Project>
- <Private>false</Private>
- <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
- <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
- <LinkLibraryDependencies>true</LinkLibraryDependencies>
- <UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
- </ProjectReference>
- <ProjectReference Include="bs2b.vcxproj">
- <Project>{c59b751c-f10d-4de0-b580-73cb03b27b6e}</Project>
- <Private>false</Private>
- <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
- <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
- <LinkLibraryDependencies>true</LinkLibraryDependencies>
- <UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
- </ProjectReference>
- <ProjectReference Include="soundtouch.vcxproj">
- <Project>{3c1b816a-645c-4e1f-a006-5c47263e59c5}</Project>
- <Private>false</Private>
- <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
- <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
- <LinkLibraryDependencies>true</LinkLibraryDependencies>
- <UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
- </ProjectReference>
- <ProjectReference Include="soxr.vcxproj">
- <Project>{2d2a92ff-1fb6-4926-affb-5e00d27939fc}</Project>
- <Private>false</Private>
- <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
- <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
- <LinkLibraryDependencies>true</LinkLibraryDependencies>
- <UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
- </ProjectReference>
- <ProjectReference Include="zita-resampler.vcxproj">
- <Project>{34dc7a3d-b219-4f42-a1e5-8dbb22dec08c}</Project>
- <Private>false</Private>
- <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
- <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
- <LinkLibraryDependencies>true</LinkLibraryDependencies>
- <UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
- </ProjectReference>
- </ItemGroup>
- <ItemGroup>
- <ClCompile Include="sanear-dll\OuterFilter.cpp" />
- <ClCompile Include="sanear-dll\Entry.cpp" />
- <ClCompile Include="sanear-dll\pch.cpp">
- <PrecompiledHeader>Create</PrecompiledHeader>
- </ClCompile>
- <ClCompile Include="sanear-dll\RegistryKey.cpp" />
- <ClCompile Include="sanear-dll\TrayWindow.cpp" />
- </ItemGroup>
- <ItemGroup>
- <ClInclude Include="sanear-dll\OuterFilter.h" />
- <ClInclude Include="sanear-dll\pch.h" />
- <ClInclude Include="sanear-dll\RegistryKey.h" />
- <ClInclude Include="sanear-dll\resource.h" />
- <ClInclude Include="sanear-dll\TrayWindow.h" />
- </ItemGroup>
- <ItemGroup>
- <None Include="sanear-dll\sanear.def" />
- </ItemGroup>
- <ItemGroup>
- <ResourceCompile Include="sanear-dll\sanear.rc" />
- </ItemGroup>
- <ItemGroup>
- <Image Include="sanear-dll\sanear.ico" />
- </ItemGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
- <ImportGroup Label="ExtensionTargets">
- </ImportGroup>
-</Project> \ No newline at end of file
diff --git a/dll/src/sanear-dll/Entry.cpp b/dll/src/sanear-dll/Entry.cpp
deleted file mode 100644
index 84850cf..0000000
--- a/dll/src/sanear-dll/Entry.cpp
+++ /dev/null
@@ -1,127 +0,0 @@
-#include "pch.h"
-
-#include "OuterFilter.h"
-
-namespace
-{
- // {DF557071-C9FD-433A-9627-81E0D3640ED9}
- const GUID filterGuid = {0xdf557071, 0xc9fd, 0x433a, {0x96, 0x27, 0x81, 0xe0, 0xd3, 0x64, 0xe, 0xd9}};
-
- const WCHAR filterName[] = L"sanear";
-
- const AMOVIESETUP_MEDIATYPE pinTypes[] = {
- {&MEDIATYPE_Audio, &CLSID_NULL},
- };
-
- const AMOVIESETUP_PIN setupPin = {
- L"", TRUE, FALSE, FALSE, FALSE, &CLSID_NULL, nullptr, _countof(pinTypes), pinTypes,
- };
-
- const AMOVIESETUP_FILTER setupFilter = {
- &filterGuid, filterName, MERIT_DO_NOT_USE, 1, &setupPin
- };
-}
-
-CUnknown* WINAPI CreateFilterInstance(LPUNKNOWN, HRESULT*);
-
-CFactoryTemplate g_Templates[] = {
- {filterName, &filterGuid, CreateFilterInstance},
-};
-
-int g_cTemplates = _countof(g_Templates);
-
-
-STDAPI RegisterAllServers(LPCWSTR szFileName, BOOL bRegister);
-
-namespace
-{
- struct CoFreeUnusedLibrariesHelper
- {
- ~CoFreeUnusedLibrariesHelper() { CoFreeUnusedLibraries(); };
- };
-
- HRESULT DllRegisterServer(bool reg)
- {
- wchar_t filename[MAX_PATH];
- if (!GetModuleFileName(g_hInst, filename, MAX_PATH))
- return AmGetLastErrorToHResult();
-
- if (reg)
- ReturnIfFailed(RegisterAllServers(filename, TRUE));
-
- {
- SaneAudioRenderer::CoInitializeHelper coInitializeHelper(COINIT_APARTMENTTHREADED);
- CoFreeUnusedLibrariesHelper coFreeUnusedLibrariesHelper;
-
- IFilterMapper2Ptr filterMapper;
- ReturnIfFailed(CoCreateInstance(CLSID_FilterMapper2, nullptr,
- CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&filterMapper)));
- {
- HRESULT result;
-
- result = filterMapper->UnregisterFilter(nullptr, nullptr, *setupFilter.clsID);
-
- if (FAILED(result))
- ReturnIfNotEquals(result, 0x80070002);
-
- result = filterMapper->UnregisterFilter(&CLSID_AudioRendererCategory, nullptr, *setupFilter.clsID);
-
- if (FAILED(result))
- ReturnIfNotEquals(result, 0x80070002);
- }
-
- if (reg)
- {
- const REGFILTER2 rf = {
- 1,
- setupFilter.dwMerit,
- setupFilter.nPins,
- setupFilter.lpPin,
- };
-
- ReturnIfFailed(filterMapper->RegisterFilter(*setupFilter.clsID, setupFilter.strName,
- nullptr, &CLSID_AudioRendererCategory, nullptr, &rf));
-
- ReturnIfFailed(filterMapper->RegisterFilter(*setupFilter.clsID, setupFilter.strName,
- nullptr, nullptr, nullptr, &rf));
- }
- }
-
- if (!reg)
- ReturnIfFailed(RegisterAllServers(filename, FALSE));
-
- return S_OK;
- }
-}
-
-CUnknown* WINAPI CreateFilterInstance(IUnknown* pUnknown, HRESULT* pResult)
-{
- CheckPointer(pResult, nullptr);
-
- auto pFilter = new(std::nothrow) SaneAudioRenderer::OuterFilter(pUnknown, filterGuid);
-
- if (!pFilter)
- *pResult = E_OUTOFMEMORY;
-
- return pFilter;
-}
-
-STDAPI DllRegisterServer()
-{
- if (!IsWindowsVistaOrGreater())
- return E_FAIL;
-
- return DllRegisterServer(true);
-}
-
-STDAPI DllUnregisterServer()
-{
- return DllRegisterServer(false);
-}
-
-extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
-
-BOOL WINAPI DllMain(HINSTANCE hDllHandle, DWORD dwReason, LPVOID pReserved)
-{
- return DllEntryPoint(hDllHandle, dwReason, pReserved);
-}
diff --git a/dll/src/sanear-dll/OuterFilter.cpp b/dll/src/sanear-dll/OuterFilter.cpp
deleted file mode 100644
index 084e869..0000000
--- a/dll/src/sanear-dll/OuterFilter.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-#include "pch.h"
-#include "OuterFilter.h"
-
-#include "../../../src/Factory.h"
-
-namespace SaneAudioRenderer
-{
- namespace
- {
- const auto DeviceId = L"DeviceId";
- const auto DeviceExclusive = L"DeviceExclusive";
- const auto DeviceBufferDuration = L"DeviceBufferDuration";
- const auto AllowBitstreaming = L"AllowBitstreaming";
- const auto CrossfeedEnabled = L"CrossfeedEnabled";
- const auto CrossfeedCutoffFrequency = L"CrossfeedCutoffFrequency";
- const auto CrossfeedLevel = L"CrossfeedLevel";
- }
-
- OuterFilter::OuterFilter(IUnknown* pUnknown, const GUID& guid)
- : CUnknown(L"SaneAudioRenderer::OuterFilter", pUnknown)
- , m_guid(guid)
- {
- }
-
- OuterFilter::~OuterFilter()
- {
- BOOL boolValue;
- WCHAR* stringValue;
- UINT32 uintValue1;
- UINT32 uintValue2;
-
- if (SUCCEEDED(m_settings->GetOuputDevice(&stringValue, &boolValue, &uintValue1)))
- {
- std::unique_ptr<WCHAR, CoTaskMemFreeDeleter> holder(stringValue);
- m_registryKey.SetString(DeviceId, stringValue);
- m_registryKey.SetUint(DeviceExclusive, boolValue);
- m_registryKey.SetUint(DeviceBufferDuration, uintValue1);
- }
-
- m_settings->GetAllowBitstreaming(&boolValue);
- m_registryKey.SetUint(AllowBitstreaming, boolValue);
-
- m_settings->GetCrossfeedEnabled(&boolValue);
- m_registryKey.SetUint(CrossfeedEnabled, boolValue);
-
- m_settings->GetCrossfeedSettings(&uintValue1, &uintValue2);
- m_registryKey.SetUint(CrossfeedCutoffFrequency, uintValue1);
- m_registryKey.SetUint(CrossfeedLevel, uintValue2);
- }
-
- STDMETHODIMP OuterFilter::NonDelegatingQueryInterface(REFIID riid, void** ppv)
- {
- if (!m_initialized)
- ReturnIfFailed(Init());
-
- if (riid == IID_IUnknown)
- return CUnknown::NonDelegatingQueryInterface(riid, ppv);
-
- return m_innerFilter->QueryInterface(riid, ppv);
- }
-
- HRESULT OuterFilter::Init()
- {
- assert(!m_initialized);
-
- ReturnIfFailed(Factory::CreateSettings(&m_settings))
- ReturnIfFailed(Factory::CreateFilterAggregated(GetOwner(), m_guid, m_settings, &m_innerFilter));
- ReturnIfFailed(m_registryKey.Open(HKEY_CURRENT_USER, L"Software\\sanear"));
- ReturnIfFailed(m_trayWindow.Init(m_settings));
-
- m_initialized = true;
-
- std::vector<wchar_t> stringValue;
- uint32_t uintValue1;
- uint32_t uintValue2;
-
- if (m_registryKey.GetString(DeviceId, stringValue) &&
- m_registryKey.GetUint(DeviceExclusive, uintValue1) &&
- m_registryKey.GetUint(DeviceBufferDuration, uintValue2))
- {
- m_settings->SetOuputDevice(stringValue.data(), uintValue1, uintValue2);
- }
-
- if (m_registryKey.GetUint(AllowBitstreaming, uintValue1))
- m_settings->SetAllowBitstreaming(uintValue1);
-
- if (m_registryKey.GetUint(CrossfeedEnabled, uintValue1))
- m_settings->SetCrossfeedEnabled(uintValue1);
-
- if (m_registryKey.GetUint(CrossfeedCutoffFrequency, uintValue1) &&
- m_registryKey.GetUint(CrossfeedLevel, uintValue2))
- {
- m_settings->SetCrossfeedSettings(uintValue1, uintValue2);
- }
-
- return S_OK;
- }
-}
diff --git a/dll/src/sanear-dll/OuterFilter.h b/dll/src/sanear-dll/OuterFilter.h
deleted file mode 100644
index cf4de20..0000000
--- a/dll/src/sanear-dll/OuterFilter.h
+++ /dev/null
@@ -1,35 +0,0 @@
-#pragma once
-
-#include "RegistryKey.h"
-#include "TrayWindow.h"
-
-#include "../../../src/Interfaces.h"
-
-namespace SaneAudioRenderer
-{
- class OuterFilter final
- : public CUnknown
- {
- public:
-
- OuterFilter(IUnknown* pUnknown, const GUID& guid);
- ~OuterFilter();
- OuterFilter(const OuterFilter&) = delete;
- OuterFilter& operator=(const OuterFilter&) = delete;
-
- DECLARE_IUNKNOWN
-
- STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv) override;
-
- private:
-
- HRESULT Init();
-
- const GUID& m_guid;
- bool m_initialized = false;
- RegistryKey m_registryKey;
- ISettingsPtr m_settings;
- IUnknownPtr m_innerFilter;
- TrayWindow m_trayWindow;
- };
-}
diff --git a/dll/src/sanear-dll/RegistryKey.cpp b/dll/src/sanear-dll/RegistryKey.cpp
deleted file mode 100644
index 0e80142..0000000
--- a/dll/src/sanear-dll/RegistryKey.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-#include "pch.h"
-#include "RegistryKey.h"
-
-namespace SaneAudioRenderer
-{
- HRESULT RegistryKey::Open(HKEY key, const wchar_t* subkey)
- {
- Close();
-
- return RegCreateKeyEx(key, subkey, 0, nullptr, REG_OPTION_NON_VOLATILE,
- KEY_READ | KEY_WRITE, nullptr, &m_hKey, nullptr);
- }
-
- void RegistryKey::Close()
- {
- if (m_hKey != NULL)
- {
- RegCloseKey(m_hKey);
- m_hKey = NULL;
- }
- }
-
- RegistryKey::~RegistryKey()
- {
- Close();
- }
-
- bool RegistryKey::SetString(const wchar_t* key, const wchar_t* value)
- {
- const DWORD valueSize = (DWORD)(wcslen(value) + 1) * sizeof(wchar_t);
- return RegSetValueEx(m_hKey, key, 0, REG_SZ, (const BYTE*)value, valueSize) == ERROR_SUCCESS;
- }
-
- bool RegistryKey::GetString(const wchar_t* name, std::vector<wchar_t>& value)
- {
- DWORD valueSize;
- DWORD valuetype;
-
- if (RegQueryValueEx(m_hKey, name, 0, &valuetype, nullptr, &valueSize) != ERROR_SUCCESS)
- return false;
-
- try
- {
- value.resize(valueSize / sizeof(wchar_t));
- }
- catch (std::bad_alloc&)
- {
- return false;
- }
-
- if (RegQueryValueEx(m_hKey, name, 0, &valuetype, (BYTE*)value.data(), &valueSize) != ERROR_SUCCESS ||
- valuetype != REG_SZ)
- {
- return false;
- }
-
- return true;
- }
-
- bool RegistryKey::SetUint(const wchar_t* name, uint32_t value)
- {
- return RegSetValueEx(m_hKey, name, 0, REG_DWORD, (BYTE*)&value, sizeof(uint32_t)) == ERROR_SUCCESS;
- }
-
- bool RegistryKey::GetUint(const wchar_t* name, uint32_t& value)
- {
- DWORD valueSize = sizeof(uint32_t);
- DWORD valuetype;
-
- if (RegQueryValueEx(m_hKey, name, 0, &valuetype, (BYTE*)&value, &valueSize) != ERROR_SUCCESS ||
- valuetype != REG_DWORD)
- {
- return false;
- }
-
- return true;
- }
-}
diff --git a/dll/src/sanear-dll/RegistryKey.h b/dll/src/sanear-dll/RegistryKey.h
deleted file mode 100644
index ba23e40..0000000
--- a/dll/src/sanear-dll/RegistryKey.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#pragma once
-
-namespace SaneAudioRenderer
-{
- class RegistryKey final
- {
- public:
-
- RegistryKey() = default;
- ~RegistryKey();
- RegistryKey(const RegistryKey&) = delete;
- RegistryKey& operator=(const RegistryKey&) = delete;
-
- HRESULT Open(HKEY key, const wchar_t* subkey);
- void Close();
-
- bool SetString(const wchar_t* name, const wchar_t* value);
- bool GetString(const wchar_t* name, std::vector<wchar_t>& value);
-
- bool SetUint(const wchar_t* name, uint32_t value);
- bool RegistryKey::GetUint(const wchar_t* name, uint32_t& value);
-
- private:
-
- HKEY m_hKey = NULL;
- };
-}
diff --git a/dll/src/sanear-dll/TrayWindow.cpp b/dll/src/sanear-dll/TrayWindow.cpp
deleted file mode 100644
index 5f805d4..0000000
--- a/dll/src/sanear-dll/TrayWindow.cpp
+++ /dev/null
@@ -1,390 +0,0 @@
-#include "pch.h"
-#include "TrayWindow.h"
-
-#include "resource.h"
-
-namespace SaneAudioRenderer
-{
- namespace
- {
- const auto WindowClass = L"SaneAudioRenderer::TrayWindow";
- const auto WindowTitle = L"";
-
- enum
- {
- WM_TRAYNOTIFY = WM_USER + 100,
- };
-
- enum Item
- {
- ExclusiveMode = 10,
- AllowBitstreaming,
- EnableCrossfeed,
- CrossfeedCMoy, // used in CheckMenuRadioItem()
- CrossfeedJMeier, // used in CheckMenuRadioItem()
- DefaultDevice, // needs to be last
- };
-
- std::vector<std::pair<std::wstring, std::wstring>> GetDevices()
- {
- std::vector<std::pair<std::wstring, std::wstring>> devices;
-
- IMMDeviceEnumeratorPtr enumerator;
- IMMDeviceCollectionPtr collection;
- UINT count = 0;
-
- if (SUCCEEDED(CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&enumerator))) &&
- SUCCEEDED(enumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE | DEVICE_STATE_UNPLUGGED, &collection)) &&
- SUCCEEDED(collection->GetCount(&count)))
- {
- for (UINT i = 0; i < count; i++)
- {
- IMMDevicePtr device;
- LPWSTR pDeviceId;
- IPropertyStorePtr devicePropertyStore;
- PROPVARIANT friendlyName; // TODO: make wrapper class this, use it also in AudioDeviceManager
- PropVariantInit(&friendlyName);
-
- if (SUCCEEDED(collection->Item(i, &device)) &&
- SUCCEEDED(device->GetId(&pDeviceId)) &&
- SUCCEEDED(device->OpenPropertyStore(STGM_READ, &devicePropertyStore)) &&
- SUCCEEDED(devicePropertyStore->GetValue(PKEY_Device_FriendlyName, &friendlyName)))
- {
- std::unique_ptr<WCHAR, CoTaskMemFreeDeleter> holder(pDeviceId);
- devices.emplace_back(friendlyName.pwszVal, pDeviceId);
- PropVariantClear(&friendlyName);
- }
- }
- }
-
- return devices;
- }
- }
-
- TrayWindow::TrayWindow()
- {
- m_nid = {sizeof(m_nid)};
- }
-
- TrayWindow::~TrayWindow()
- {
- Destroy();
- }
-
- HRESULT TrayWindow::Init(ISettings* pSettings)
- {
- CheckPointer(pSettings, E_POINTER);
-
- assert(m_hThread == NULL);
- Destroy();
-
- ReturnIfFailed(pSettings->QueryInterface(IID_PPV_ARGS(&m_settings)));
-
- m_hThread = (HANDLE)_beginthreadex(nullptr, 0, StaticThreadProc<TrayWindow>, this, 0, nullptr);
-
- if (m_hThread == NULL || !m_windowCreated.get_future().get())
- return E_FAIL;
-
- return S_OK;
- }
-
- DWORD TrayWindow::ThreadProc()
- {
- CoInitializeHelper coInitializeHelper(COINIT_MULTITHREADED);
-
- if (!coInitializeHelper.Initialized())
- {
- m_windowCreated.set_value(false);
- return 0;
- }
-
- WNDCLASSEX windowClass = {
- sizeof(windowClass), 0, StaticWindowProc<TrayWindow>, 0, 0, g_hInst,
- NULL, NULL, NULL, nullptr, WindowClass, NULL
- };
-
- RegisterClassEx(&windowClass);
-
- m_hWindow = CreateWindowEx(0, WindowClass, WindowTitle, 0, 0, 0, 0, 0, 0, NULL, g_hInst, this);
-
- if (m_hWindow == NULL)
- {
- m_windowCreated.set_value(false);
- return 0;
- }
-
- m_windowCreated.set_value(true);
-
- m_taskbarCreatedMessage = RegisterWindowMessage(L"TaskbarCreated");
-
- AddIcon();
-
- RunMessageLoop();
-
- return 0;
- }
-
- LRESULT TrayWindow::WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
- {
- if (msg == m_taskbarCreatedMessage)
- {
- AddIcon();
- return 0;
- }
-
- switch (msg)
- {
- case WM_COMMAND:
- OnCommand(wParam, lParam);
- return 0;
-
- case WM_TRAYNOTIFY:
- OnTrayNotify(wParam, lParam);
- return 0;
-
- case WM_DESTROY:
- RemoveMenu();
- RemoveIcon();
- PostQuitMessage(0);
- return 0;
- }
-
- return DefWindowProc(hWnd, msg, wParam, lParam);
- }
-
- void TrayWindow::Destroy()
- {
- if (m_hThread != NULL)
- {
- PostMessage(m_hWindow, WM_DESTROY, 0, 0);
- WaitForSingleObject(m_hThread, INFINITE);
- CloseHandle(m_hThread);
- m_hThread = NULL;
- }
- }
-
- void TrayWindow::AddIcon()
- {
- m_nid.hWnd = m_hWindow;
- m_nid.uVersion = NOTIFYICON_VERSION_4;
- m_nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP | NIF_SHOWTIP;
- LoadIconMetric(g_hInst, MAKEINTRESOURCE(IDI_ICON1), LIM_SMALL, &m_nid.hIcon);
- m_nid.uCallbackMessage = WM_TRAYNOTIFY;
- lstrcpy(m_nid.szTip, L"sanear");
-
- Shell_NotifyIcon(NIM_ADD, &m_nid);
- Shell_NotifyIcon(NIM_SETVERSION, &m_nid);
- }
-
- void TrayWindow::RemoveIcon()
- {
- Shell_NotifyIcon(NIM_DELETE, &m_nid);
- }
-
- void TrayWindow::AddMenu()
- {
- RemoveMenu();
-
- m_hMenu = CreateMenu();
- HMENU hMenu = CreateMenu();
-
- BOOL allowBitstreaming;
- m_settings->GetAllowBitstreaming(&allowBitstreaming);
-
- BOOL crossfeedEnabled;
- m_settings->GetCrossfeedEnabled(&crossfeedEnabled);
-
- UINT32 crosfeedCutoff;
- UINT32 crosfeedLevel;
- m_settings->GetCrossfeedSettings(&crosfeedCutoff, &crosfeedLevel);
-
- LPWSTR pDeviceId = nullptr;
- BOOL exclusive;
- m_settings->GetOuputDevice(&pDeviceId, &exclusive, nullptr);
- std::unique_ptr<WCHAR, CoTaskMemFreeDeleter> holder(pDeviceId); // TODO: write specialized wrapper for this
-
- try
- {
- m_devices = GetDevices();
- }
- catch (std::bad_alloc&)
- {
- m_devices.clear();
- }
-
- MENUITEMINFO separator = {sizeof(MENUITEMINFO)};
- separator.fMask = MIIM_TYPE;
- separator.fType = MFT_SEPARATOR;
-
- MENUITEMINFO check = {sizeof(MENUITEMINFO)};
- check.fMask = MIIM_STRING | MIIM_ID | MIIM_CHECKMARKS | MIIM_STATE;
-
- MENUITEMINFO submenu = {sizeof(MENUITEMINFO)};
- submenu.fMask = MIIM_SUBMENU;
-
- check.wID = Item::AllowBitstreaming;
- check.dwTypeData = L"Allow bitstreaming (in exclusive WASAPI mode)";
- check.fState = (allowBitstreaming ? MFS_CHECKED : MFS_UNCHECKED) | (exclusive ? MFS_ENABLED : MFS_DISABLED);
- InsertMenuItem(hMenu, 0, TRUE, &check);
-
- check.wID = Item::ExclusiveMode;
- check.dwTypeData = L"Exclusive WASAPI mode";
- check.fState = (exclusive ? MFS_CHECKED : MFS_UNCHECKED);
- InsertMenuItem(hMenu, 0, TRUE, &check);
-
- InsertMenuItem(hMenu, 0, TRUE, &separator);
-
- check.wID = Item::CrossfeedJMeier;
- check.dwTypeData = L"J.Meier-like preset";
- check.fState = (crossfeedEnabled ? MFS_ENABLED : MFS_DISABLED);
- InsertMenuItem(hMenu, 0, TRUE, &check);
-
- check.wID = Item::CrossfeedCMoy;
- check.dwTypeData = L"C.Moy-like preset";
- check.fState = (crossfeedEnabled ? MFS_ENABLED : MFS_DISABLED);
- InsertMenuItem(hMenu, 0, TRUE, &check);
-
- if (crosfeedCutoff == ISettings::CROSSFEED_CUTOFF_FREQ_CMOY &&
- crosfeedLevel == ISettings::CROSSFEED_LEVEL_CMOY)
- {
- CheckMenuRadioItem(hMenu, Item::CrossfeedCMoy, Item::CrossfeedJMeier, Item::CrossfeedCMoy, MF_BYCOMMAND);
- }
- else if (crosfeedCutoff == ISettings::CROSSFEED_CUTOFF_FREQ_JMEIER &&
- crosfeedLevel == ISettings::CROSSFEED_LEVEL_JMEIER)
- {
- CheckMenuRadioItem(hMenu, Item::CrossfeedCMoy, Item::CrossfeedJMeier, Item::CrossfeedJMeier, MF_BYCOMMAND);
- }
-
- check.wID = Item::EnableCrossfeed;
- check.dwTypeData = L"Enable stereo crossfeed (for headphones)";
- check.fState = (crossfeedEnabled ? MFS_CHECKED : MFS_UNCHECKED);
- InsertMenuItem(hMenu, 0, TRUE, &check);
-
- InsertMenuItem(hMenu, 0, TRUE, &separator);
-
- UINT selectedDevice = Item::DefaultDevice;
-
- for (size_t i = 0, n = m_devices.size(); i < n; i++)
- {
- const auto& device = m_devices[n - i - 1];
-
- check.wID = Item::DefaultDevice + (UINT)(n - i);
- check.dwTypeData = (LPWSTR)device.first.c_str();
- check.fState = MFS_ENABLED;
- InsertMenuItem(hMenu, 0, TRUE, &check);
-
- if (pDeviceId && device.second == pDeviceId)
- selectedDevice = check.wID;
- }
-
- check.wID = Item::DefaultDevice;
- check.dwTypeData = L"Default Device";
- check.fState = MFS_ENABLED;
- InsertMenuItem(hMenu, 0, TRUE, &check);
-
- CheckMenuRadioItem(hMenu, Item::DefaultDevice, Item::DefaultDevice + (UINT)m_devices.size(), selectedDevice, MF_BYCOMMAND);
-
- submenu.hSubMenu = hMenu;
- InsertMenuItem(m_hMenu, 0, TRUE, &submenu);
- }
-
- void TrayWindow::RemoveMenu()
- {
- if (m_hMenu)
- {
- EndMenu();
- DestroyMenu(m_hMenu);
- m_hMenu = NULL;
- }
- }
-
- void TrayWindow::OnTrayNotify(WPARAM wParam, LPARAM lParam)
- {
- switch (LOWORD(lParam))
- {
- case NIN_KEYSELECT:
- case NIN_SELECT:
- case WM_CONTEXTMENU:
- AddMenu();
- SetForegroundWindow(m_hWindow);
- TrackPopupMenuEx(GetSubMenu(m_hMenu, 0), TPM_LEFTALIGN | TPM_BOTTOMALIGN, LOWORD(wParam), HIWORD(wParam), m_hWindow, NULL);
- break;
- }
- }
-
- void TrayWindow::OnCommand(WPARAM wParam, LPARAM lParam)
- {
- switch (wParam)
- {
- case Item::ExclusiveMode:
- {
- LPWSTR pDeviceId = nullptr;
- BOOL exclusive;
- UINT32 buffer;
- m_settings->GetOuputDevice(&pDeviceId, &exclusive, &buffer);
- std::unique_ptr<WCHAR, CoTaskMemFreeDeleter> holder(pDeviceId);
- m_settings->SetOuputDevice(pDeviceId, !exclusive, buffer);
- break;
- }
-
- case Item::AllowBitstreaming:
- {
- BOOL value;
- m_settings->GetAllowBitstreaming(&value);
- m_settings->SetAllowBitstreaming(!value);
- break;
- }
-
- case Item::EnableCrossfeed:
- {
- BOOL value;
- m_settings->GetCrossfeedEnabled(&value);
- m_settings->SetCrossfeedEnabled(!value);
- break;
- }
-
- case Item::CrossfeedCMoy:
- {
- m_settings->SetCrossfeedSettings(ISettings::CROSSFEED_CUTOFF_FREQ_CMOY, ISettings::CROSSFEED_LEVEL_CMOY);
- break;
- }
-
- case Item::CrossfeedJMeier:
- {
- m_settings->SetCrossfeedSettings(ISettings::CROSSFEED_CUTOFF_FREQ_JMEIER, ISettings::CROSSFEED_LEVEL_JMEIER);
- break;
- }
-
- case Item::DefaultDevice:
- {
- LPWSTR pDeviceId = nullptr;
- BOOL exclusive;
- UINT32 buffer;
- m_settings->GetOuputDevice(&pDeviceId, &exclusive, &buffer);
- std::unique_ptr<WCHAR, CoTaskMemFreeDeleter> holder(pDeviceId);
-
- if (pDeviceId && *pDeviceId)
- m_settings->SetOuputDevice(nullptr, exclusive, buffer);
-
- break;
- }
-
- default:
- {
- if (wParam <= Item::DefaultDevice || wParam > Item::DefaultDevice + m_devices.size())
- break;
-
- const auto& selection = m_devices[wParam - Item::DefaultDevice - 1].second;
-
- LPWSTR pDeviceId = nullptr;
- BOOL exclusive;
- UINT32 buffer;
- m_settings->GetOuputDevice(&pDeviceId, &exclusive, &buffer);
- std::unique_ptr<WCHAR, CoTaskMemFreeDeleter> holder(pDeviceId);
-
- if (!pDeviceId || selection != pDeviceId)
- m_settings->SetOuputDevice(selection.c_str(), exclusive, buffer);
- }
- }
- }
-}
diff --git a/dll/src/sanear-dll/TrayWindow.h b/dll/src/sanear-dll/TrayWindow.h
deleted file mode 100644
index 99be3d4..0000000
--- a/dll/src/sanear-dll/TrayWindow.h
+++ /dev/null
@@ -1,44 +0,0 @@
-#pragma once
-
-#include "../../../src/Interfaces.h"
-
-namespace SaneAudioRenderer
-{
- class TrayWindow final
- {
- public:
-
- TrayWindow();
- ~TrayWindow();
- TrayWindow(const TrayWindow&) = delete;
- TrayWindow& operator=(const TrayWindow&) = delete;
-
- HRESULT Init(ISettings* pSettings);
-
- DWORD ThreadProc();
- LRESULT WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
-
- private:
-
- void Destroy();
-
- void AddIcon();
- void RemoveIcon();
-
- void AddMenu();
- void RemoveMenu();
-
- void OnTrayNotify(WPARAM wParam, LPARAM lParam);
- void OnCommand(WPARAM wParam, LPARAM lParam);
-
- UINT m_taskbarCreatedMessage = 0;
- NOTIFYICONDATA m_nid;
-
- ISettingsPtr m_settings;
- HANDLE m_hThread = NULL;
- HWND m_hWindow = NULL;
- HMENU m_hMenu = NULL;
- std::promise<bool> m_windowCreated;
- std::vector<std::pair<std::wstring, std::wstring>> m_devices;
- };
-}
diff --git a/dll/src/sanear-dll/pch.cpp b/dll/src/sanear-dll/pch.cpp
deleted file mode 100644
index 9e6b2e0..0000000
--- a/dll/src/sanear-dll/pch.cpp
+++ /dev/null
@@ -1 +0,0 @@
-#include "pch.h"
diff --git a/dll/src/sanear-dll/pch.h b/dll/src/sanear-dll/pch.h
deleted file mode 100644
index d256629..0000000
--- a/dll/src/sanear-dll/pch.h
+++ /dev/null
@@ -1,43 +0,0 @@
-#pragma once
-
-#include "../../../src/pch.h"
-
-#include <Commctrl.h>
-#include <VersionHelpers.h>
-
-namespace SaneAudioRenderer
-{
- template <class T, DWORD(T::*ThreadProc)() = &T::ThreadProc>
- unsigned CALLBACK StaticThreadProc(LPVOID p)
- {
- return (static_cast<T*>(p)->*ThreadProc)();
- }
-
- template <class T, LRESULT(T::*WindowProc)(HWND, UINT, WPARAM, LPARAM) = &T::WindowProc>
- LRESULT CALLBACK StaticWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
- {
- if (LONG_PTR userData = GetWindowLongPtr(hWnd, GWLP_USERDATA))
- return (reinterpret_cast<T*>(userData)->*WindowProc)(hWnd, msg, wParam, lParam);
-
- if (msg == WM_NCCREATE)
- {
- CREATESTRUCT* pCreateStruct = reinterpret_cast<CREATESTRUCT*>(lParam);
- SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pCreateStruct->lpCreateParams));
- return (static_cast<T*>(pCreateStruct->lpCreateParams)->*WindowProc)(hWnd, msg, wParam, lParam);
- }
-
- return DefWindowProc(hWnd, msg, wParam, lParam);
- }
-
- inline void RunMessageLoop()
- {
- MSG msg;
- while (GetMessage(&msg, NULL, 0, 0))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- }
-}
-
-_COM_SMARTPTR_TYPEDEF(IFilterMapper2, __uuidof(IFilterMapper2));
diff --git a/dll/src/sanear-dll/resource.h b/dll/src/sanear-dll/resource.h
deleted file mode 100644
index 6f5a1ff..0000000
--- a/dll/src/sanear-dll/resource.h
+++ /dev/null
@@ -1,16 +0,0 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Used by sanear.rc
-//
-#define IDI_ICON1 101
-
-// Next default values for new objects
-//
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 102
-#define _APS_NEXT_COMMAND_VALUE 40001
-#define _APS_NEXT_CONTROL_VALUE 1001
-#define _APS_NEXT_SYMED_VALUE 101
-#endif
-#endif
diff --git a/dll/src/sanear-dll/sanear.def b/dll/src/sanear-dll/sanear.def
deleted file mode 100644
index 6e3db66..0000000
--- a/dll/src/sanear-dll/sanear.def
+++ /dev/null
@@ -1,5 +0,0 @@
-EXPORTS
- DllGetClassObject PRIVATE
- DllCanUnloadNow PRIVATE
- DllRegisterServer PRIVATE
- DllUnregisterServer PRIVATE
diff --git a/dll/src/sanear-dll/sanear.ico b/dll/src/sanear-dll/sanear.ico
deleted file mode 100644
index 901144e..0000000
--- a/dll/src/sanear-dll/sanear.ico
+++ /dev/null
Binary files differ
diff --git a/dll/src/sanear-dll/sanear.rc b/dll/src/sanear-dll/sanear.rc
deleted file mode 100644
index 6d2fd44..0000000
--- a/dll/src/sanear-dll/sanear.rc
+++ /dev/null
@@ -1,105 +0,0 @@
-// Microsoft Visual C++ generated resource script.
-//
-#include "resource.h"
-
-#define APSTUDIO_READONLY_SYMBOLS
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 2 resource.
-//
-#include "winres.h"
-
-/////////////////////////////////////////////////////////////////////////////
-#undef APSTUDIO_READONLY_SYMBOLS
-
-/////////////////////////////////////////////////////////////////////////////
-// English (United Kingdom) resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
-LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
-#pragma code_page(1252)
-
-#ifdef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// TEXTINCLUDE
-//
-
-1 TEXTINCLUDE
-BEGIN
- "resource.h\0"
-END
-
-2 TEXTINCLUDE
-BEGIN
- "#include ""winres.h""\r\n"
- "\0"
-END
-
-3 TEXTINCLUDE
-BEGIN
- "\r\n"
- "\0"
-END
-
-#endif // APSTUDIO_INVOKED
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Icon
-//
-
-// Icon with lowest ID value placed first to ensure application icon
-// remains consistent on all systems.
-IDI_ICON1 ICON "sanear.ico"
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Version
-//
-
-VS_VERSION_INFO VERSIONINFO
- FILEVERSION 0,1,0,0
- PRODUCTVERSION 0,1,0,0
- FILEFLAGSMASK 0x3fL
-#ifdef _DEBUG
- FILEFLAGS 0x1L
-#else
- FILEFLAGS 0x0L
-#endif
- FILEOS 0x40004L
- FILETYPE 0x2L
- FILESUBTYPE 0x0L
-BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "080904b0"
- BEGIN
- VALUE "FileDescription", "Robust DirectShow audio renderer"
- VALUE "FileVersion", "0.1.0.0"
- VALUE "ProductName", "sanear"
- VALUE "ProductVersion", "0.1.0.0"
- END
- END
- BLOCK "VarFileInfo"
- BEGIN
- VALUE "Translation", 0x809, 1200
- END
-END
-
-#endif // English (United Kingdom) resources
-/////////////////////////////////////////////////////////////////////////////
-
-
-
-#ifndef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 3 resource.
-//
-
-
-/////////////////////////////////////////////////////////////////////////////
-#endif // not APSTUDIO_INVOKED
-
diff --git a/dll/src/sanear-dll/sanear.svg b/dll/src/sanear-dll/sanear.svg
deleted file mode 100644
index 06001ab..0000000
--- a/dll/src/sanear-dll/sanear.svg
+++ /dev/null
@@ -1,79 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="16"
- height="16"
- viewBox="0 0 16 16"
- id="svg4345"
- version="1.1"
- inkscape:version="0.91 r13725"
- sodipodi:docname="sanear.svg">
- <defs
- id="defs4347" />
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="31.678384"
- inkscape:cx="5.562414"
- inkscape:cy="6.5329427"
- inkscape:document-units="px"
- inkscape:current-layer="layer1"
- showgrid="true"
- units="px"
- inkscape:snap-page="false"
- inkscape:snap-bbox="false"
- inkscape:snap-bbox-midpoints="true"
- inkscape:snap-bbox-edge-midpoints="true"
- inkscape:bbox-nodes="true"
- inkscape:bbox-paths="true"
- inkscape:snap-global="true"
- inkscape:object-nodes="false">
- <inkscape:grid
- type="xygrid"
- id="grid4353"
- empspacing="4" />
- </sodipodi:namedview>
- <metadata
- id="metadata4350">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- inkscape:label="Layer 1"
- inkscape:groupmode="layer"
- id="layer1"
- transform="translate(0,-1036.3622)">
- <ellipse
- style="opacity:1;fill:#4a1f8c;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="path4355"
- cx="8"
- cy="1044.3622"
- rx="8"
- ry="8.0000048" />
- <path
- style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ededed;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="m 1,1044.3622 1.3788072,0 1.2209708,-1.4319 1.7158947,3.4951 L 7,1039.1728 l 2.1578363,9.9053 1.8737307,-7.1263 1.621193,3.9685 1.126269,-1.5265 L 15,1044.3622"
- id="path4901"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="cccccccccc" />
- </g>
-</svg>
diff --git a/dll/src/soundtouch b/dll/src/soundtouch
deleted file mode 160000
-Subproject adb60efd61648d9e5068c0ec1fa13c9dbbe728b
diff --git a/dll/src/soundtouch.vcxproj b/dll/src/soundtouch.vcxproj
deleted file mode 100644
index 28c20f4..0000000
--- a/dll/src/soundtouch.vcxproj
+++ /dev/null
@@ -1,105 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup Label="ProjectConfigurations">
- <ProjectConfiguration Include="Debug|Win32">
- <Configuration>Debug</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Debug|x64">
- <Configuration>Debug</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|Win32">
- <Configuration>Release</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|x64">
- <Configuration>Release</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- </ItemGroup>
- <PropertyGroup Label="Globals">
- <ProjectGuid>{3C1B816A-645C-4E1F-A006-5C47263E59C5}</ProjectGuid>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
- <Import Project="..\base.props" />
- <PropertyGroup Label="Configuration">
- <CharacterSet>Unicode</CharacterSet>
- <ConfigurationType>StaticLibrary</ConfigurationType>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
- <UseDebugLibraries>true</UseDebugLibraries>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
- <UseDebugLibraries>false</UseDebugLibraries>
- <WholeProgramOptimization>true</WholeProgramOptimization>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
- <ImportGroup Label="ExtensionSettings">
- </ImportGroup>
- <ImportGroup Label="PropertySheets">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <ItemDefinitionGroup>
- <ClCompile>
- <WarningLevel>Level3</WarningLevel>
- <SDLCheck>true</SDLCheck>
- <MultiProcessorCompilation>true</MultiProcessorCompilation>
- <AdditionalIncludeDirectories>soundtouch\include</AdditionalIncludeDirectories>
- </ClCompile>
- <Link>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- </Link>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
- <ClCompile>
- <Optimization>Disabled</Optimization>
- <MinimalRebuild>false</MinimalRebuild>
- </ClCompile>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
- <ClCompile>
- <Optimization>MaxSpeed</Optimization>
- <FunctionLevelLinking>true</FunctionLevelLinking>
- <IntrinsicFunctions>true</IntrinsicFunctions>
- </ClCompile>
- <Link>
- <EnableCOMDATFolding>true</EnableCOMDATFolding>
- <OptimizeReferences>true</OptimizeReferences>
- </Link>
- </ItemDefinitionGroup>
- <ItemGroup>
- <ClCompile Include="soundtouch\source\SoundTouch\AAFilter.cpp" />
- <ClCompile Include="soundtouch\source\SoundTouch\BPMDetect.cpp" />
- <ClCompile Include="soundtouch\source\SoundTouch\cpu_detect_x86.cpp" />
- <ClCompile Include="soundtouch\source\SoundTouch\FIFOSampleBuffer.cpp" />
- <ClCompile Include="soundtouch\source\SoundTouch\FIRFilter.cpp" />
- <ClCompile Include="soundtouch\source\SoundTouch\InterpolateCubic.cpp" />
- <ClCompile Include="soundtouch\source\SoundTouch\InterpolateLinear.cpp" />
- <ClCompile Include="soundtouch\source\SoundTouch\InterpolateShannon.cpp" />
- <ClCompile Include="soundtouch\source\SoundTouch\PeakFinder.cpp" />
- <ClCompile Include="soundtouch\source\SoundTouch\RateTransposer.cpp" />
- <ClCompile Include="soundtouch\source\SoundTouch\SoundTouch.cpp" />
- <ClCompile Include="soundtouch\source\SoundTouch\sse_optimized.cpp" />
- <ClCompile Include="soundtouch\source\SoundTouch\TDStretch.cpp" />
- </ItemGroup>
- <ItemGroup>
- <ClInclude Include="soundtouch\include\BPMDetect.h" />
- <ClInclude Include="soundtouch\include\FIFOSampleBuffer.h" />
- <ClInclude Include="soundtouch\include\FIFOSamplePipe.h" />
- <ClInclude Include="soundtouch\include\SoundTouch.h" />
- <ClInclude Include="soundtouch\include\STTypes.h" />
- <ClInclude Include="soundtouch\source\SoundTouch\AAFilter.h" />
- <ClInclude Include="soundtouch\source\SoundTouch\cpu_detect.h" />
- <ClInclude Include="soundtouch\source\SoundTouch\FIRFilter.h" />
- <ClInclude Include="soundtouch\source\SoundTouch\InterpolateCubic.h" />
- <ClInclude Include="soundtouch\source\SoundTouch\InterpolateLinear.h" />
- <ClInclude Include="soundtouch\source\SoundTouch\InterpolateShannon.h" />
- <ClInclude Include="soundtouch\source\SoundTouch\PeakFinder.h" />
- <ClInclude Include="soundtouch\source\SoundTouch\RateTransposer.h" />
- <ClInclude Include="soundtouch\source\SoundTouch\TDStretch.h" />
- </ItemGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
- <ImportGroup Label="ExtensionTargets">
- </ImportGroup>
-</Project> \ No newline at end of file
diff --git a/dll/src/soxr b/dll/src/soxr
deleted file mode 160000
-Subproject 988f8303c7f30d0db5db3e15bf973e2bdf5c867
diff --git a/dll/src/soxr-config.h b/dll/src/soxr-config.h
deleted file mode 100644
index 4a6150f..0000000
--- a/dll/src/soxr-config.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#pragma once
-
-#define HAVE_SINGLE_PRECISION 1
-#define HAVE_DOUBLE_PRECISION 1
-#define HAVE_SIMD 1
-#define HAVE_FENV_H 1
-#define HAVE_LRINT 1
-
-#define HAVE_AVFFT 0
-#define WORDS_BIGENDIAN 0
-
-#include <inttypes.h>
-#include <stdbool.h>
diff --git a/dll/src/soxr.vcxproj b/dll/src/soxr.vcxproj
deleted file mode 100644
index ffc1c94..0000000
--- a/dll/src/soxr.vcxproj
+++ /dev/null
@@ -1,93 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup Label="ProjectConfigurations">
- <ProjectConfiguration Include="Debug|Win32">
- <Configuration>Debug</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Debug|x64">
- <Configuration>Debug</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|Win32">
- <Configuration>Release</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|x64">
- <Configuration>Release</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- </ItemGroup>
- <PropertyGroup Label="Globals">
- <ProjectGuid>{2D2A92FF-1FB6-4926-AFFB-5E00D27939FC}</ProjectGuid>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
- <Import Project="..\base.props" />
- <PropertyGroup Label="Configuration">
- <CharacterSet>Unicode</CharacterSet>
- <ConfigurationType>StaticLibrary</ConfigurationType>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
- <UseDebugLibraries>true</UseDebugLibraries>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
- <UseDebugLibraries>false</UseDebugLibraries>
- <WholeProgramOptimization>true</WholeProgramOptimization>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
- <ImportGroup Label="ExtensionSettings">
- </ImportGroup>
- <ImportGroup Label="PropertySheets">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <ItemDefinitionGroup>
- <ClCompile>
- <WarningLevel>TurnOffAllWarnings</WarningLevel>
- <MultiProcessorCompilation>true</MultiProcessorCompilation>
- <AdditionalIncludeDirectories>.</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_USE_MATH_DEFINES;_CRT_SECURE_NO_WARNINGS;SOXR_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- </ClCompile>
- <Link>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- </Link>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
- <ClCompile>
- <Optimization>Disabled</Optimization>
- <MinimalRebuild>false</MinimalRebuild>
- </ClCompile>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
- <ClCompile>
- <Optimization>MaxSpeed</Optimization>
- <FunctionLevelLinking>true</FunctionLevelLinking>
- <IntrinsicFunctions>true</IntrinsicFunctions>
- </ClCompile>
- <Link>
- <EnableCOMDATFolding>true</EnableCOMDATFolding>
- <OptimizeReferences>true</OptimizeReferences>
- </Link>
- </ItemDefinitionGroup>
- <ItemGroup>
- <ClCompile Include="soxr\src\data-io.c" />
- <ClCompile Include="soxr\src\dbesi0.c" />
- <ClCompile Include="soxr\src\fft4g32.c" />
- <ClCompile Include="soxr\src\fft4g64.c" />
- <ClCompile Include="soxr\src\filter.c" />
- <ClCompile Include="soxr\src\lsr.c" />
- <ClCompile Include="soxr\src\pffft32s.c" />
- <ClCompile Include="soxr\src\rate32.c" />
- <ClCompile Include="soxr\src\rate32s.c" />
- <ClCompile Include="soxr\src\rate64.c" />
- <ClCompile Include="soxr\src\simd.c" />
- <ClCompile Include="soxr\src\soxr.c" />
- <ClCompile Include="soxr\src\vr32.c" />
- </ItemGroup>
- <ItemGroup>
- <ClInclude Include="soxr\src\soxr.h" />
- <ClInclude Include="soxr-config.h" />
- </ItemGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
- <ImportGroup Label="ExtensionTargets">
- </ImportGroup>
-</Project> \ No newline at end of file
diff --git a/dll/src/zita-resampler.vcxproj b/dll/src/zita-resampler.vcxproj
deleted file mode 100644
index 9cf66ca..0000000
--- a/dll/src/zita-resampler.vcxproj
+++ /dev/null
@@ -1,85 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup Label="ProjectConfigurations">
- <ProjectConfiguration Include="Debug|Win32">
- <Configuration>Debug</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Debug|x64">
- <Configuration>Debug</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|Win32">
- <Configuration>Release</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|x64">
- <Configuration>Release</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- </ItemGroup>
- <PropertyGroup Label="Globals">
- <ProjectGuid>{34DC7A3D-B219-4F42-A1E5-8DBB22DEC08C}</ProjectGuid>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
- <Import Project="..\base.props" />
- <PropertyGroup Label="Configuration">
- <CharacterSet>Unicode</CharacterSet>
- <ConfigurationType>StaticLibrary</ConfigurationType>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
- <UseDebugLibraries>true</UseDebugLibraries>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
- <UseDebugLibraries>false</UseDebugLibraries>
- <WholeProgramOptimization>true</WholeProgramOptimization>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
- <ImportGroup Label="ExtensionSettings">
- </ImportGroup>
- <ImportGroup Label="PropertySheets">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <ItemDefinitionGroup>
- <ClCompile>
- <WarningLevel>Level3</WarningLevel>
- <SDLCheck>true</SDLCheck>
- <MultiProcessorCompilation>true</MultiProcessorCompilation>
- <AdditionalIncludeDirectories>zita-resampler\libs</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_USE_MATH_DEFINES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- </ClCompile>
- <Link>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- </Link>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
- <ClCompile>
- <Optimization>Disabled</Optimization>
- <MinimalRebuild>false</MinimalRebuild>
- </ClCompile>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
- <ClCompile>
- <Optimization>MaxSpeed</Optimization>
- <FunctionLevelLinking>true</FunctionLevelLinking>
- <IntrinsicFunctions>true</IntrinsicFunctions>
- </ClCompile>
- <Link>
- <EnableCOMDATFolding>true</EnableCOMDATFolding>
- <OptimizeReferences>true</OptimizeReferences>
- </Link>
- </ItemDefinitionGroup>
- <ItemGroup>
- <ClInclude Include="zita-resampler\libs\zita-resampler\resampler-table.h" />
- <ClInclude Include="zita-resampler\libs\zita-resampler\resampler.h" />
- <ClInclude Include="zita-resampler\libs\zita-resampler\vresampler.h" />
- </ItemGroup>
- <ItemGroup>
- <ClCompile Include="zita-resampler\libs\resampler-table.cc" />
- <ClCompile Include="zita-resampler\libs\resampler.cc" />
- <ClCompile Include="zita-resampler\libs\vresampler.cc" />
- </ItemGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
- <ImportGroup Label="ExtensionTargets">
- </ImportGroup>
-</Project> \ No newline at end of file
diff --git a/dll/src/zita-resampler/AUTHORS b/dll/src/zita-resampler/AUTHORS
deleted file mode 100644
index 5443a6e..0000000
--- a/dll/src/zita-resampler/AUTHORS
+++ /dev/null
@@ -1 +0,0 @@
-Fons Adriaensen <fons@linuxaudio.org>
diff --git a/dll/src/zita-resampler/COPYING b/dll/src/zita-resampler/COPYING
deleted file mode 100644
index 818433e..0000000
--- a/dll/src/zita-resampler/COPYING
+++ /dev/null
@@ -1,674 +0,0 @@
- GNU GENERAL PUBLIC LICENSE
- Version 3, 29 June 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The GNU General Public License is a free, copyleft license for
-software and other kinds of works.
-
- The licenses for most software and other practical works are designed
-to take away your freedom to share and change the works. By contrast,
-the GNU General Public License is intended to guarantee your freedom to
-share and change all versions of a program--to make sure it remains free
-software for all its users. We, the Free Software Foundation, use the
-GNU General Public License for most of our software; it applies also to
-any other work released this way by its authors. You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-them if you wish), that you receive source code or can get it if you
-want it, that you can change the software or use pieces of it in new
-free programs, and that you know you can do these things.
-
- To protect your rights, we need to prevent others from denying you
-these rights or asking you to surrender the rights. Therefore, you have
-certain responsibilities if you distribute copies of the software, or if
-you modify it: responsibilities to respect the freedom of others.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must pass on to the recipients the same
-freedoms that you received. You must make sure that they, too, receive
-or can get the source code. And you must show them these terms so they
-know their rights.
-
- Developers that use the GNU GPL protect your rights with two steps:
-(1) assert copyright on the software, and (2) offer you this License
-giving you legal permission to copy, distribute and/or modify it.
-
- For the developers' and authors' protection, the GPL clearly explains
-that there is no warranty for this free software. For both users' and
-authors' sake, the GPL requires that modified versions be marked as
-changed, so that their problems will not be attributed erroneously to
-authors of previous versions.
-
- Some devices are designed to deny users access to install or run
-modified versions of the software inside them, although the manufacturer
-can do so. This is fundamentally incompatible with the aim of
-protecting users' freedom to change the software. The systematic
-pattern of such abuse occurs in the area of products for individuals to
-use, which is precisely where it is most unacceptable. Therefore, we
-have designed this version of the GPL to prohibit the practice for those
-products. If such problems arise substantially in other domains, we
-stand ready to extend this provision to those domains in future versions
-of the GPL, as needed to protect the freedom of users.
-
- Finally, every program is threatened constantly by software patents.
-States should not allow patents to restrict development and use of
-software on general-purpose computers, but in those that do, we wish to
-avoid the special danger that patents applied to a free program could
-make it effectively proprietary. To prevent this, the GPL assures that
-patents cannot be used to render the program non-free.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- TERMS AND CONDITIONS
-
- 0. Definitions.
-
- "This License" refers to version 3 of the GNU General Public License.
-
- "Copyright" also means copyright-like laws that apply to other kinds of
-works, such as semiconductor masks.
-
- "The Program" refers to any copyrightable work licensed under this
-License. Each licensee is addressed as "you". "Licensees" and
-"recipients" may be individuals or organizations.
-
- To "modify" a work means to copy from or adapt all or part of the work
-in a fashion requiring copyright permission, other than the making of an
-exact copy. The resulting work is called a "modified version" of the
-earlier work or a work "based on" the earlier work.
-
- A "covered work" means either the unmodified Program or a work based
-on the Program.
-
- To "propagate" a work means to do anything with it that, without
-permission, would make you directly or secondarily liable for
-infringement under applicable copyright law, except executing it on a
-computer or modifying a private copy. Propagation includes copying,
-distribution (with or without modification), making available to the
-public, and in some countries other activities as well.
-
- To "convey" a work means any kind of propagation that enables other
-parties to make or receive copies. Mere interaction with a user through
-a computer network, with no transfer of a copy, is not conveying.
-
- An interactive user interface displays "Appropriate Legal Notices"
-to the extent that it includes a convenient and prominently visible
-feature that (1) displays an appropriate copyright notice, and (2)
-tells the user that there is no warranty for the work (except to the
-extent that warranties are provided), that licensees may convey the
-work under this License, and how to view a copy of this License. If
-the interface presents a list of user commands or options, such as a
-menu, a prominent item in the list meets this criterion.
-
- 1. Source Code.
-
- The "source code" for a work means the preferred form of the work
-for making modifications to it. "Object code" means any non-source
-form of a work.
-
- A "Standard Interface" means an interface that either is an official
-standard defined by a recognized standards body, or, in the case of
-interfaces specified for a particular programming language, one that
-is widely used among developers working in that language.
-
- The "System Libraries" of an executable work include anything, other
-than the work as a whole, that (a) is included in the normal form of
-packaging a Major Component, but which is not part of that Major
-Component, and (b) serves only to enable use of the work with that
-Major Component, or to implement a Standard Interface for which an
-implementation is available to the public in source code form. A
-"Major Component", in this context, means a major essential component
-(kernel, window system, and so on) of the specific operating system
-(if any) on which the executable work runs, or a compiler used to
-produce the work, or an object code interpreter used to run it.
-
- The "Corresponding Source" for a work in object code form means all
-the source code needed to generate, install, and (for an executable
-work) run the object code and to modify the work, including scripts to
-control those activities. However, it does not include the work's
-System Libraries, or general-purpose tools or generally available free
-programs which are used unmodified in performing those activities but
-which are not part of the work. For example, Corresponding Source
-includes interface definition files associated with source files for
-the work, and the source code for shared libraries and dynamically
-linked subprograms that the work is specifically designed to require,
-such as by intimate data communication or control flow between those
-subprograms and other parts of the work.
-
- The Corresponding Source need not include anything that users
-can regenerate automatically from other parts of the Corresponding
-Source.
-
- The Corresponding Source for a work in source code form is that
-same work.
-
- 2. Basic Permissions.
-
- All rights granted under this License are granted for the term of
-copyright on the Program, and are irrevocable provided the stated
-conditions are met. This License explicitly affirms your unlimited
-permission to run the unmodified Program. The output from running a
-covered work is covered by this License only if the output, given its
-content, constitutes a covered work. This License acknowledges your
-rights of fair use or other equivalent, as provided by copyright law.
-
- You may make, run and propagate covered works that you do not
-convey, without conditions so long as your license otherwise remains
-in force. You may convey covered works to others for the sole purpose
-of having them make modifications exclusively for you, or provide you
-with facilities for running those works, provided that you comply with
-the terms of this License in conveying all material for which you do
-not control copyright. Those thus making or running the covered works
-for you must do so exclusively on your behalf, under your direction
-and control, on terms that prohibit them from making any copies of
-your copyrighted material outside their relationship with you.
-
- Conveying under any other circumstances is permitted solely under
-the conditions stated below. Sublicensing is not allowed; section 10
-makes it unnecessary.
-
- 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
-
- No covered work shall be deemed part of an effective technological
-measure under any applicable law fulfilling obligations under article
-11 of the WIPO copyright treaty adopted on 20 December 1996, or
-similar laws prohibiting or restricting circumvention of such
-measures.
-
- When you convey a covered work, you waive any legal power to forbid
-circumvention of technological measures to the extent such circumvention
-is effected by exercising rights under this License with respect to
-the covered work, and you disclaim any intention to limit operation or
-modification of the work as a means of enforcing, against the work's
-users, your or third parties' legal rights to forbid circumvention of
-technological measures.
-
- 4. Conveying Verbatim Copies.
-
- You may convey verbatim copies of the Program's source code as you
-receive it, in any medium, provided that you conspicuously and
-appropriately publish on each copy an appropriate copyright notice;
-keep intact all notices stating that this License and any
-non-permissive terms added in accord with section 7 apply to the code;
-keep intact all notices of the absence of any warranty; and give all
-recipients a copy of this License along with the Program.
-
- You may charge any price or no price for each copy that you convey,
-and you may offer support or warranty protection for a fee.
-
- 5. Conveying Modified Source Versions.
-
- You may convey a work based on the Program, or the modifications to
-produce it from the Program, in the form of source code under the
-terms of section 4, provided that you also meet all of these conditions:
-
- a) The work must carry prominent notices stating that you modified
- it, and giving a relevant date.
-
- b) The work must carry prominent notices stating that it is
- released under this License and any conditions added under section
- 7. This requirement modifies the requirement in section 4 to
- "keep intact all notices".
-
- c) You must license the entire work, as a whole, under this
- License to anyone who comes into possession of a copy. This
- License will therefore apply, along with any applicable section 7
- additional terms, to the whole of the work, and all its parts,
- regardless of how they are packaged. This License gives no
- permission to license the work in any other way, but it does not
- invalidate such permission if you have separately received it.
-
- d) If the work has interactive user interfaces, each must display
- Appropriate Legal Notices; however, if the Program has interactive
- interfaces that do not display Appropriate Legal Notices, your
- work need not make them do so.
-
- A compilation of a covered work with other separate and independent
-works, which are not by their nature extensions of the covered work,
-and which are not combined with it such as to form a larger program,
-in or on a volume of a storage or distribution medium, is called an
-"aggregate" if the compilation and its resulting copyright are not
-used to limit the access or legal rights of the compilation's users
-beyond what the individual works permit. Inclusion of a covered work
-in an aggregate does not cause this License to apply to the other
-parts of the aggregate.
-
- 6. Conveying Non-Source Forms.
-
- You may convey a covered work in object code form under the terms
-of sections 4 and 5, provided that you also convey the
-machine-readable Corresponding Source under the terms of this License,
-in one of these ways:
-
- a) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by the
- Corresponding Source fixed on a durable physical medium
- customarily used for software interchange.
-
- b) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by a
- written offer, valid for at least three years and valid for as
- long as you offer spare parts or customer support for that product
- model, to give anyone who possesses the object code either (1) a
- copy of the Corresponding Source for all the software in the
- product that is covered by this License, on a durable physical
- medium customarily used for software interchange, for a price no
- more than your reasonable cost of physically performing this
- conveying of source, or (2) access to copy the
- Corresponding Source from a network server at no charge.
-
- c) Convey individual copies of the object code with a copy of the
- written offer to provide the Corresponding Source. This
- alternative is allowed only occasionally and noncommercially, and
- only if you received the object code with such an offer, in accord
- with subsection 6b.
-
- d) Convey the object code by offering access from a designated
- place (gratis or for a charge), and offer equivalent access to the
- Corresponding Source in the same way through the same place at no
- further charge. You need not require recipients to copy the
- Corresponding Source along with the object code. If the place to
- copy the object code is a network server, the Corresponding Source
- may be on a different server (operated by you or a third party)
- that supports equivalent copying facilities, provided you maintain
- clear directions next to the object code saying where to find the
- Corresponding Source. Regardless of what server hosts the
- Corresponding Source, you remain obligated to ensure that it is
- available for as long as needed to satisfy these requirements.
-
- e) Convey the object code using peer-to-peer transmission, provided
- you inform other peers where the object code and Corresponding
- Source of the work are being offered to the general public at no
- charge under subsection 6d.
-
- A separable portion of the object code, whose source code is excluded
-from the Corresponding Source as a System Library, need not be
-included in conveying the object code work.
-
- A "User Product" is either (1) a "consumer product", which means any
-tangible personal property which is normally used for personal, family,
-or household purposes, or (2) anything designed or sold for incorporation
-into a dwelling. In determining whether a product is a consumer product,
-doubtful cases shall be resolved in favor of coverage. For a particular
-product received by a particular user, "normally used" refers to a
-typical or common use of that class of product, regardless of the status
-of the particular user or of the way in which the particular user
-actually uses, or expects or is expected to use, the product. A product
-is a consumer product regardless of whether the product has substantial
-commercial, industrial or non-consumer uses, unless such uses represent
-the only significant mode of use of the product.
-
- "Installation Information" for a User Product means any methods,
-procedures, authorization keys, or other information required to install
-and execute modified versions of a covered work in that User Product from
-a modified version of its Corresponding Source. The information must
-suffice to ensure that the continued functioning of the modified object
-code is in no case prevented or interfered with solely because
-modification has been made.
-
- If you convey an object code work under this section in, or with, or
-specifically for use in, a User Product, and the conveying occurs as
-part of a transaction in which the right of possession and use of the
-User Product is transferred to the recipient in perpetuity or for a
-fixed term (regardless of how the transaction is characterized), the
-Corresponding Source conveyed under this section must be accompanied
-by the Installation Information. But this requirement does not apply
-if neither you nor any third party retains the ability to install
-modified object code on the User Product (for example, the work has
-been installed in ROM).
-
- The requirement to provide Installation Information does not include a
-requirement to continue to provide support service, warranty, or updates
-for a work that has been modified or installed by the recipient, or for
-the User Product in which it has been modified or installed. Access to a
-network may be denied when the modification itself materially and
-adversely affects the operation of the network or violates the rules and
-protocols for communication across the network.
-
- Corresponding Source conveyed, and Installation Information provided,
-in accord with this section must be in a format that is publicly
-documented (and with an implementation available to the public in
-source code form), and must require no special password or key for
-unpacking, reading or copying.
-
- 7. Additional Terms.
-
- "Additional permissions" are terms that supplement the terms of this
-License by making exceptions from one or more of its conditions.
-Additional permissions that are applicable to the entire Program shall
-be treated as though they were included in this License, to the extent
-that they are valid under applicable law. If additional permissions
-apply only to part of the Program, that part may be used separately
-under those permissions, but the entire Program remains governed by
-this License without regard to the additional permissions.
-
- When you convey a copy of a covered work, you may at your option
-remove any additional permissions from that copy, or from any part of
-it. (Additional permissions may be written to require their own
-removal in certain cases when you modify the work.) You may place
-additional permissions on material, added by you to a covered work,
-for which you have or can give appropriate copyright permission.
-
- Notwithstanding any other provision of this License, for material you
-add to a covered work, you may (if authorized by the copyright holders of
-that material) supplement the terms of this License with terms:
-
- a) Disclaiming warranty or limiting liability differently from the
- terms of sections 15 and 16 of this License; or
-
- b) Requiring preservation of specified reasonable legal notices or
- author attributions in that material or in the Appropriate Legal
- Notices displayed by works containing it; or
-
- c) Prohibiting misrepresentation of the origin of that material, or
- requiring that modified versions of such material be marked in
- reasonable ways as different from the original version; or
-
- d) Limiting the use for publicity purposes of names of licensors or
- authors of the material; or
-
- e) Declining to grant rights under trademark law for use of some
- trade names, trademarks, or service marks; or
-
- f) Requiring indemnification of licensors and authors of that
- material by anyone who conveys the material (or modified versions of
- it) with contractual assumptions of liability to the recipient, for
- any liability that these contractual assumptions directly impose on
- those licensors and authors.
-
- All other non-permissive additional terms are considered "further
-restrictions" within the meaning of section 10. If the Program as you
-received it, or any part of it, contains a notice stating that it is
-governed by this License along with a term that is a further
-restriction, you may remove that term. If a license document contains
-a further restriction but permits relicensing or conveying under this
-License, you may add to a covered work material governed by the terms
-of that license document, provided that the further restriction does
-not survive such relicensing or conveying.
-
- If you add terms to a covered work in accord with this section, you
-must place, in the relevant source files, a statement of the
-additional terms that apply to those files, or a notice indicating
-where to find the applicable terms.
-
- Additional terms, permissive or non-permissive, may be stated in the
-form of a separately written license, or stated as exceptions;
-the above requirements apply either way.
-
- 8. Termination.
-
- You may not propagate or modify a covered work except as expressly
-provided under this License. Any attempt otherwise to propagate or
-modify it is void, and will automatically terminate your rights under
-this License (including any patent licenses granted under the third
-paragraph of section 11).
-
- However, if you cease all violation of this License, then your
-license from a particular copyright holder is reinstated (a)
-provisionally, unless and until the copyright holder explicitly and
-finally terminates your license, and (b) permanently, if the copyright
-holder fails to notify you of the violation by some reasonable means
-prior to 60 days after the cessation.
-
- Moreover, your license from a particular copyright holder is
-reinstated permanently if the copyright holder notifies you of the
-violation by some reasonable means, this is the first time you have
-received notice of violation of this License (for any work) from that
-copyright holder, and you cure the violation prior to 30 days after
-your receipt of the notice.
-
- Termination of your rights under this section does not terminate the
-licenses of parties who have received copies or rights from you under
-this License. If your rights have been terminated and not permanently
-reinstated, you do not qualify to receive new licenses for the same
-material under section 10.
-
- 9. Acceptance Not Required for Having Copies.
-
- You are not required to accept this License in order to receive or
-run a copy of the Program. Ancillary propagation of a covered work
-occurring solely as a consequence of using peer-to-peer transmission
-to receive a copy likewise does not require acceptance. However,
-nothing other than this License grants you permission to propagate or
-modify any covered work. These actions infringe copyright if you do
-not accept this License. Therefore, by modifying or propagating a
-covered work, you indicate your acceptance of this License to do so.
-
- 10. Automatic Licensing of Downstream Recipients.
-
- Each time you convey a covered work, the recipient automatically
-receives a license from the original licensors, to run, modify and
-propagate that work, subject to this License. You are not responsible
-for enforcing compliance by third parties with this License.
-
- An "entity transaction" is a transaction transferring control of an
-organization, or substantially all assets of one, or subdividing an
-organization, or merging organizations. If propagation of a covered
-work results from an entity transaction, each party to that
-transaction who receives a copy of the work also receives whatever
-licenses to the work the party's predecessor in interest had or could
-give under the previous paragraph, plus a right to possession of the
-Corresponding Source of the work from the predecessor in interest, if
-the predecessor has it or can get it with reasonable efforts.
-
- You may not impose any further restrictions on the exercise of the
-rights granted or affirmed under this License. For example, you may
-not impose a license fee, royalty, or other charge for exercise of
-rights granted under this License, and you may not initiate litigation
-(including a cross-claim or counterclaim in a lawsuit) alleging that
-any patent claim is infringed by making, using, selling, offering for
-sale, or importing the Program or any portion of it.
-
- 11. Patents.
-
- A "contributor" is a copyright holder who authorizes use under this
-License of the Program or a work on which the Program is based. The
-work thus licensed is called the contributor's "contributor version".
-
- A contributor's "essential patent claims" are all patent claims
-owned or controlled by the contributor, whether already acquired or
-hereafter acquired, that would be infringed by some manner, permitted
-by this License, of making, using, or selling its contributor version,
-but do not include claims that would be infringed only as a
-consequence of further modification of the contributor version. For
-purposes of this definition, "control" includes the right to grant
-patent sublicenses in a manner consistent with the requirements of
-this License.
-
- Each contributor grants you a non-exclusive, worldwide, royalty-free
-patent license under the contributor's essential patent claims, to
-make, use, sell, offer for sale, import and otherwise run, modify and
-propagate the contents of its contributor version.
-
- In the following three paragraphs, a "patent license" is any express
-agreement or commitment, however denominated, not to enforce a patent
-(such as an express permission to practice a patent or covenant not to
-sue for patent infringement). To "grant" such a patent license to a
-party means to make such an agreement or commitment not to enforce a
-patent against the party.
-
- If you convey a covered work, knowingly relying on a patent license,
-and the Corresponding Source of the work is not available for anyone
-to copy, free of charge and under the terms of this License, through a
-publicly available network server or other readily accessible means,
-then you must either (1) cause the Corresponding Source to be so
-available, or (2) arrange to deprive yourself of the benefit of the
-patent license for this particular work, or (3) arrange, in a manner
-consistent with the requirements of this License, to extend the patent
-license to downstream recipients. "Knowingly relying" means you have
-actual knowledge that, but for the patent license, your conveying the
-covered work in a country, or your recipient's use of the covered work
-in a country, would infringe one or more identifiable patents in that
-country that you have reason to believe are valid.
-
- If, pursuant to or in connection with a single transaction or
-arrangement, you convey, or propagate by procuring conveyance of, a
-covered work, and grant a patent license to some of the parties
-receiving the covered work authorizing them to use, propagate, modify
-or convey a specific copy of the covered work, then the patent license
-you grant is automatically extended to all recipients of the covered
-work and works based on it.
-
- A patent license is "discriminatory" if it does not include within
-the scope of its coverage, prohibits the exercise of, or is
-conditioned on the non-exercise of one or more of the rights that are
-specifically granted under this License. You may not convey a covered
-work if you are a party to an arrangement with a third party that is
-in the business of distributing software, under which you make payment
-to the third party based on the extent of your activity of conveying
-the work, and under which the third party grants, to any of the
-parties who would receive the covered work from you, a discriminatory
-patent license (a) in connection with copies of the covered work
-conveyed by you (or copies made from those copies), or (b) primarily
-for and in connection with specific products or compilations that
-contain the covered work, unless you entered into that arrangement,
-or that patent license was granted, prior to 28 March 2007.
-
- Nothing in this License shall be construed as excluding or limiting
-any implied license or other defenses to infringement that may
-otherwise be available to you under applicable patent law.
-
- 12. No Surrender of Others' Freedom.
-
- If conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot convey a
-covered work so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you may
-not convey it at all. For example, if you agree to terms that obligate you
-to collect a royalty for further conveying from those to whom you convey
-the Program, the only way you could satisfy both those terms and this
-License would be to refrain entirely from conveying the Program.
-
- 13. Use with the GNU Affero General Public License.
-
- Notwithstanding any other provision of this License, you have
-permission to link or combine any covered work with a work licensed
-under version 3 of the GNU Affero General Public License into a single
-combined work, and to convey the resulting work. The terms of this
-License will continue to apply to the part which is the covered work,
-but the special requirements of the GNU Affero General Public License,
-section 13, concerning interaction through a network will apply to the
-combination as such.
-
- 14. Revised Versions of this License.
-
- The Free Software Foundation may publish revised and/or new versions of
-the GNU General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
- Each version is given a distinguishing version number. If the
-Program specifies that a certain numbered version of the GNU General
-Public License "or any later version" applies to it, you have the
-option of following the terms and conditions either of that numbered
-version or of any later version published by the Free Software
-Foundation. If the Program does not specify a version number of the
-GNU General Public License, you may choose any version ever published
-by the Free Software Foundation.
-
- If the Program specifies that a proxy can decide which future
-versions of the GNU General Public License can be used, that proxy's
-public statement of acceptance of a version permanently authorizes you
-to choose that version for the Program.
-
- Later license versions may give you additional or different
-permissions. However, no additional obligations are imposed on any
-author or copyright holder as a result of your choosing to follow a
-later version.
-
- 15. Disclaimer of Warranty.
-
- THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
-APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
-HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
-OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
-IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
-ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. Limitation of Liability.
-
- IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
-THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
-GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
-USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
-DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
-PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
-EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGES.
-
- 17. Interpretation of Sections 15 and 16.
-
- If the disclaimer of warranty and limitation of liability provided
-above cannot be given local legal effect according to their terms,
-reviewing courts shall apply local law that most closely approximates
-an absolute waiver of all civil liability in connection with the
-Program, unless a warranty or assumption of liability accompanies a
-copy of the Program in return for a fee.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-state the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- <one line to give the program's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-Also add information on how to contact you by electronic and paper mail.
-
- If the program does terminal interaction, make it output a short
-notice like this when it starts in an interactive mode:
-
- <program> Copyright (C) <year> <name of author>
- This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, your program's commands
-might be different; for a GUI interface, you would use an "about box".
-
- You should also get your employer (if you work as a programmer) or school,
-if any, to sign a "copyright disclaimer" for the program, if necessary.
-For more information on this, and how to apply and follow the GNU GPL, see
-<http://www.gnu.org/licenses/>.
-
- The GNU General Public License does not permit incorporating your program
-into proprietary programs. If your program is a subroutine library, you
-may consider it more useful to permit linking proprietary applications with
-the library. If this is what you want to do, use the GNU Lesser General
-Public License instead of this License. But first, please read
-<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/dll/src/zita-resampler/INSTALL b/dll/src/zita-resampler/INSTALL
deleted file mode 100644
index 9913662..0000000
--- a/dll/src/zita-resampler/INSTALL
+++ /dev/null
@@ -1,31 +0,0 @@
-Dependencies
-------------
-
-The zita-resampler library does not depend on any
-non-standard libraries.
-
-The 'zresample' and 'zretune' application depend on libsndfile
-and the corresponding headers.
-
-Installing the library
-----------------------
-
-To make and install the library, cd to the libs directory,
-make, sudo make install. This will install the lib and
-header file in /usr/lib and /usr/include. To install in
-any other directory, modify the definition of 'PREFIX' in
-the Makefile.
-After the install you can do a 'make clean' to return the
-libs directory to its original state.
-
-
-Installing the application(s)
-----------------------------
-
-To make and install the application(s), you first need to
-make and install the library. Then cd to the apps directory,
-make, sudo make install. This will install the apps in
-/usr/local/bin. To install in other any directory, modify
-the definition of 'PREFIX' in the Makefile.
-After the install you can do a 'make clean' to return the
-apps directory to its original state.
diff --git a/dll/src/zita-resampler/README b/dll/src/zita-resampler/README
deleted file mode 100644
index 3327fae..0000000
--- a/dll/src/zita-resampler/README
+++ /dev/null
@@ -1,45 +0,0 @@
-Zita-resampler is a C++ library for sample rate conversion of
-audio signals. Full documentation is available in HTML format,
-see the 'docs' directory.
-
-
-Release 1.3.0 (26/10/2012)
----------------------------
-
-* Bugfix for 64-bit systems.
-
-
-Release 1.2.0 (25/09/2012)
----------------------------
-
-* Added the zretune application and its manpage.
-
-
-Release 1.1.0 (26/01/2012)
----------------------------
-
-* VResampler class added - provides arbitrary and variable
- resampling ratio, see docs.
-
-* This release is NOT binary compatible with previous ones
- (0.x.x) and requires recompilation of applications using it.
-
-* This release is API compatible with the previous one. But if
- you are using the now deprecated filtlen() function please
- replace this by inpsize() which provides the same information.
-
-* The inpdist() function has been added, see docs.
-
-* The ratio_a() and ratio_b() calls have been removed, if this
- is a problem (I'd be surprised) they can be added again.
-
-* The include files are now in $PREFIX/include/zita-resampler/.
- Please DO remove any old ones manually after installing this
- version. Compiling using the old includes and linking with
- the new library will create havoc.
-
-* #defines and static functions are added for compile time and
- run time version checking, see resampler-table.h.
-
---
-FA
diff --git a/dll/src/zita-resampler/apps/Makefile b/dll/src/zita-resampler/apps/Makefile
deleted file mode 100644
index e5e9395..0000000
--- a/dll/src/zita-resampler/apps/Makefile
+++ /dev/null
@@ -1,73 +0,0 @@
-# ----------------------------------------------------------------------------
-#
-# Copyright (C) 2006-2011 Fons Adriaensen <fons@linuxaudio.org>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http:#www.gnu.org/licenses/>.
-#
-# ----------------------------------------------------------------------------
-
-
-PREFIX = /usr/local
-SUFFIX := $(shell uname -m | sed -e 's/^unknown/$//' -e 's/^i.86/$//' -e 's/^x86_64/$/64/')
-LIBDIR = lib$(SUFFIX)
-DISTDIR = zresample-$(VERSION)
-VERSION = 0.4.0
-MANDIR = /usr/share/man/man1
-LDFLAGS += -L$(PREFIX)/$(LIBDIR)
-CPPFLAGS += -MMD -MP -DVERSION=\"$(VERSION)\"
-CXXFLAGS += -O3 -ffast-math -Wall
-CXXFLAGS += -march=native
-
-
-all: zresample zretune zresample.1.gz zretune.1.gz
-
-
-ZRESAMPLE_O = zresample.o audiofile.o dither.o
-zresample: LDLIBS += -lzita-resampler -lsndfile -lrt
-zresample: $(ZRESAMPLE_O)
- g++ $(LDFLAGS) -o $@ $(ZRESAMPLE_O) $(LDLIBS)
-$(ZRESAMPLE_O):
--include $(ZRESAMPLE_O:%.o=%.d)
-
-
-ZRETUNE_O = zretune.o audiofile.o dither.o
-zretune: LDLIBS += -lzita-resampler -lsndfile -lrt
-zretune: $(ZRETUNE_O)
- g++ $(LDFLAGS) -o $@ $(ZRETUNE_O) $(LDLIBS)
-$(ZRETUNE_O):
--include $(ZRETUNE_O:%.o=%.d)
-
-
-zresample.1.gz: zresample.1
- gzip -c zresample.1 > zresample.1.gz
-
-zretune.1.gz: zretune.1
- gzip -c zretune.1 > zretune.1.gz
-
-
-install: all
- install -Dm 755 zresample $(DESTDIR)$(PREFIX)/bin/zresample
- install -Dm 755 zretune $(DESTDIR)$(PREFIX)/bin/zretune
- install -Dm 644 zresample.1.gz $(DESTDIR)$(MANDIR)/zresample.1.gz
- install -Dm 644 zretune.1.gz $(DESTDIR)$(MANDIR)/zretune.1.gz
-
-uninstall:
- /bin/rm -f $(DESTDIR)$(PREFIX)/bin/zresample
- /bin/rm -f $(DESTDIR)$(PREFIX)/bin/zretune
- /bin/rm -f $(MANDIR)/zresample.1.gz
- /bin/rm -f $(MANDIR)/zretune.1.gz
-
-clean:
- /bin/rm -f *~ *.o *.a *.d *.so *.gz zresample zretune
-
diff --git a/dll/src/zita-resampler/apps/audiofile.cc b/dll/src/zita-resampler/apps/audiofile.cc
deleted file mode 100644
index c097089..0000000
--- a/dll/src/zita-resampler/apps/audiofile.cc
+++ /dev/null
@@ -1,270 +0,0 @@
-// ----------------------------------------------------------------------------
-//
-// Copyright (C) 2006-2011 Fons Adriaensen <fons@linuxaudio.org>
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-//
-// ----------------------------------------------------------------------------
-
-
-#include <stdlib.h>
-#include <string.h>
-#include "audiofile.h"
-
-
-Audiofile::Audiofile (void)
-{
- reset ();
-}
-
-
-Audiofile::~Audiofile (void)
-{
- close ();
-}
-
-
-void Audiofile::reset (void)
-{
- _sndfile = 0;
- _mode = MODE_NONE;
- _type = TYPE_OTHER;
- _form = FORM_OTHER;
- _rate = 0;
- _chan = 0;
- _size = 0;
- _dith_type = 0;
- _dith_proc = 0;
- _dith_buff = 0;
-}
-
-
-int Audiofile::open_read (const char *name)
-{
- SF_INFO I;
-
- if (_mode) return ERR_MODE;
- reset ();
-
- if ((_sndfile = sf_open (name, SFM_READ, &I)) == 0) return ERR_OPEN;
-
- _mode = MODE_READ;
-
- switch (I.format & SF_FORMAT_TYPEMASK)
- {
- case SF_FORMAT_CAF:
- _type = TYPE_CAF;
- break;
- case SF_FORMAT_WAV:
- _type = TYPE_WAV;
- break;
- case SF_FORMAT_WAVEX:
- if (sf_command (_sndfile, SFC_WAVEX_GET_AMBISONIC, 0, 0) == SF_AMBISONIC_B_FORMAT)
- _type = TYPE_AMB;
- else
- _type = TYPE_WAV;
- }
-
- switch (I.format & SF_FORMAT_SUBMASK)
- {
- case SF_FORMAT_PCM_16:
- _form = FORM_16BIT;
- break;
- case SF_FORMAT_PCM_24:
- _form = FORM_24BIT;
- break;
- case SF_FORMAT_PCM_32:
- _form = FORM_32BIT;
- break;
- case SF_FORMAT_FLOAT:
- _form = FORM_FLOAT;
- break;
- }
-
- _rate = I.samplerate;
- _chan = I.channels;
- _size = I.frames;
-
- return 0;
-}
-
-
-int Audiofile::open_write (const char *name, int type, int form, int rate, int chan)
-{
- SF_INFO I;
-
- if (_mode) return ERR_MODE;
- if (!rate || !chan) return ERR_OPEN;
- reset ();
-
- switch (type)
- {
- case TYPE_CAF:
- I.format = SF_FORMAT_CAF;
- break;
- case TYPE_WAV:
- case TYPE_AMB:
- I.format = (chan > 2) ? SF_FORMAT_WAVEX : SF_FORMAT_WAV;
- break;
- default:
- return ERR_TYPE;
- }
-
- switch (form)
- {
- case FORM_16BIT:
- I.format |= SF_FORMAT_PCM_16;
- break;
- case FORM_24BIT:
- I.format |= SF_FORMAT_PCM_24;
- break;
- case FORM_32BIT:
- I.format |= SF_FORMAT_PCM_32;
- break;
- case FORM_FLOAT:
- I.format |= SF_FORMAT_FLOAT;
- break;
- default:
- return ERR_FORM;
- }
-
- I.samplerate = rate;
- I.channels = chan;
- I.sections = 1;
-
- if ((_sndfile = sf_open (name, SFM_WRITE, &I)) == 0) return ERR_OPEN;
-
- if (type == TYPE_AMB)
- {
- sf_command (_sndfile, SFC_WAVEX_SET_AMBISONIC, 0, SF_AMBISONIC_B_FORMAT);
- }
-
- _mode = MODE_WRITE;
- _type = type;
- _form = form;
- _rate = rate;
- _chan = chan;
-
- return 0;
-}
-
-
-int Audiofile::set_dither (int type)
-{
- if (_mode != MODE_WRITE) return ERR_MODE;
- if (_form != FORM_16BIT) return ERR_FORM;
- if (type != DITHER_NONE)
- {
- if (_dith_type == DITHER_NONE)
- {
- _dith_proc = new Dither [_chan];
- _dith_buff = new int16_t [_chan * BUFFSIZE];
- }
- }
- _dith_type = type;
- return 0;
-}
-
-
-int Audiofile::close (void)
-{
- if (_sndfile) sf_close (_sndfile);
- delete[] _dith_proc;
- delete[] _dith_buff;
- reset ();
- return 0;
-}
-
-
-int Audiofile::seek (uint32_t posit)
-{
- if (!_sndfile) return ERR_MODE;
- if (sf_seek (_sndfile, posit, SEEK_SET) != posit) return ERR_SEEK;
- return 0;
-}
-
-
-int Audiofile::read (float *data, uint32_t frames)
-{
- if (_mode != MODE_READ) return ERR_MODE;
- return sf_readf_float (_sndfile, data, frames);
-}
-
-
-int Audiofile::write (float *data, uint32_t frames)
-{
- int i;
- uint32_t k, n, r;
- float *p, v;
- int16_t *q;
- Dither *D;
-
- if (_mode != MODE_WRITE) return ERR_MODE;
- if (_dith_type == DITHER_NONE)
- {
- if (_form != FORM_FLOAT)
- {
- for (i = 0; i < _chan; i++)
- {
- p = data + i;
- for (k = 0; k < frames; k++)
- {
- v = *p;
- if (v > 1.0f) v = 1.0f;
- else if (v < -1.0f) v = -1.0f;
- *p = v;
- p += _chan;
- }
- }
- }
- return sf_writef_float (_sndfile, data, frames);
- }
- else
- {
- n = 0;
- while (frames)
- {
- k = (frames > BUFFSIZE) ? BUFFSIZE : frames;
- p = data;
- q = _dith_buff;
- D = _dith_proc;
- for (i = 0; i < _chan; i++)
- {
- switch (_dith_type)
- {
- case DITHER_RECT:
- D->proc_rectangular (p, q, _chan, k);
- break;
- case DITHER_TRIA:
- D->proc_triangular (p, q, _chan, k);
- break;
- case DITHER_LIPS:
- D->proc_lipschitz (p, q, _chan, k);
- break;
- }
- p++;
- q++;
- D++;
- }
- r = sf_writef_short (_sndfile, _dith_buff, k);
- n += r;
- if (r != k) return n;
- data += k * _chan;
- frames -= k;
- }
- }
- return 0;
-}
-
-
diff --git a/dll/src/zita-resampler/apps/audiofile.h b/dll/src/zita-resampler/apps/audiofile.h
deleted file mode 100644
index 6386a28..0000000
--- a/dll/src/zita-resampler/apps/audiofile.h
+++ /dev/null
@@ -1,119 +0,0 @@
-// ----------------------------------------------------------------------------
-//
-// Copyright (C) 2006-2011 Fons Adriaensen <fons@linuxaudio.org>
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-//
-// ----------------------------------------------------------------------------
-
-
-#ifndef __AUDIOFILE_H
-#define __AUDIOFILE_H
-
-
-#include <stdio.h>
-#include <stdint.h>
-#include <sndfile.h>
-#include "dither.h"
-
-
-class Audiofile
-{
-public:
-
- enum
- {
- MODE_NONE,
- MODE_READ,
- MODE_WRITE
- };
-
- enum
- {
- TYPE_OTHER,
- TYPE_CAF,
- TYPE_WAV,
- TYPE_AMB
- };
-
- enum
- {
- FORM_OTHER,
- FORM_16BIT,
- FORM_24BIT,
- FORM_32BIT,
- FORM_FLOAT,
- };
-
- enum
- {
- DITHER_NONE,
- DITHER_RECT,
- DITHER_TRIA,
- DITHER_LIPS,
- };
-
- enum
- {
- ERR_NONE = 0,
- ERR_MODE = -1,
- ERR_TYPE = -2,
- ERR_FORM = -3,
- ERR_OPEN = -4,
- ERR_SEEK = -5,
- ERR_DATA = -6,
- ERR_READ = -7,
- ERR_WRITE = -8
- };
-
- Audiofile (void);
- ~Audiofile (void);
-
- int mode (void) const { return _mode; }
- int type (void) const { return _type; }
- int form (void) const { return _form; }
- int rate (void) const { return _rate; }
- int chan (void) const { return _chan; }
- uint32_t size (void) const { return _size; }
-
- int open_read (const char *name);
- int open_write (const char *name, int type, int form, int rate, int chan);
- int set_dither (int type);
- int close (void);
-
- int seek (uint32_t posit);
- int read (float *data, uint32_t frames);
- int write (float *data, uint32_t frames);
-
-private:
-
- enum { BUFFSIZE = 1024 };
-
- void reset (void);
-
- SNDFILE *_sndfile;
- int _mode;
- int _type;
- int _form;
- int _rate;
- int _chan;
- uint32_t _size;
- int _dith_type;
- Dither *_dith_proc;
- int16_t *_dith_buff;
-};
-
-
-#endif
-
diff --git a/dll/src/zita-resampler/apps/dither.cc b/dll/src/zita-resampler/apps/dither.cc
deleted file mode 100644
index ef5cd12..0000000
--- a/dll/src/zita-resampler/apps/dither.cc
+++ /dev/null
@@ -1,126 +0,0 @@
-// ----------------------------------------------------------------------------
-//
-// Copyright (C) 2006-2011 Fons Adriaensen <fons@linuxaudio.org>
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-//
-// ----------------------------------------------------------------------------
-
-
-#include <string.h>
-#include <math.h>
-#include "dither.h"
-
-
-float Dither::_div = 0;
-
-#define SCALE 32768.0f
-#define LIMIT 32767
-
-
-
-Dither::Dither (void)
-{
- reset ();
- _div = ldexpf (1.0f, 32);
-}
-
-
-void Dither::reset (void)
-{
- memset (_err, 0, (SIZE + 4) * sizeof(float));
- _ind = SIZE - 1;
- _ran = 1234567;
-}
-
-
-void Dither::proc_rectangular (const float *srce, int16_t *dest, int step, int nsam)
-{
- float v, r;
- int32_t k;
-
- while (nsam--)
- {
- r = genrand () - 0.5f;
- v = *srce * SCALE + r;
- k = lrintf (v);
- if (k < -LIMIT) k = -LIMIT;
- else if (k > LIMIT) k = LIMIT;
- *dest = k;
- srce += step;
- dest += step;
- }
-}
-
-
-void Dither::proc_triangular (const float *srce, int16_t *dest, int step, int nsam)
-{
- float v, r0, r1;
- int32_t k;
-
- r1 = *_err;
- while (nsam--)
- {
- r0 = genrand ();
- v = *srce * SCALE + r0 - r1;
- r1 = r0;
- k = lrintf (v);
- if (k < -LIMIT) k = -LIMIT;
- else if (k > LIMIT) k = LIMIT;
- *dest = k;
- srce += step;
- dest += step;
- }
- *_err = r1;
-}
-
-
-void Dither::proc_lipschitz (const float *srce, int16_t *dest, int step, int nsam)
-{
- float e, u, v, *p;
- int i;
- int32_t k;
-
- i = _ind;
- while (nsam--)
- {
- p = _err + i;
- u = *srce * SCALE
- - 2.033f * p [0]
- + 2.165f * p [1]
- - 1.959f * p [2]
- + 1.590f * p [3]
- - 0.615f * p [4];
- v = u + genrand () - genrand ();
- k = lrintf (v);
- e = k - u;
- if (k < -LIMIT) k = -LIMIT;
- else if (k > LIMIT) k = LIMIT;
- *dest = k;
- if (--i < 0)
- {
- _err [SIZE + 0] = _err [0];
- _err [SIZE + 1] = _err [1];
- _err [SIZE + 2] = _err [2];
- _err [SIZE + 3] = _err [3];
- i += SIZE;
- }
- _err [i] = e;
- srce += step;
- dest += step;
- }
- _ind = i;
-}
-
-
diff --git a/dll/src/zita-resampler/apps/dither.h b/dll/src/zita-resampler/apps/dither.h
deleted file mode 100644
index 1221ac2..0000000
--- a/dll/src/zita-resampler/apps/dither.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// ----------------------------------------------------------------------------
-//
-// Copyright (C) 2006-2011 Fons Adriaensen <fons@linuxaudio.org>
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-//
-// ----------------------------------------------------------------------------
-
-
-#ifndef __DITHER_H
-#define __DITHER_H
-
-
-#include <stdint.h>
-
-
-class Dither
-{
-public:
-
- Dither (void);
- void reset (void);
- void proc_rectangular (const float *srce, int16_t *dest, int step, int nsam);
- void proc_triangular (const float *srce, int16_t *dest, int step, int nsam);
- void proc_lipschitz (const float *srce, int16_t *dest, int step, int nsam);
-
-private:
-
- enum { SIZE = 64 };
-
- float genrand (void)
- {
- _ran *= 1103515245;
- _ran += 12345;
- return _ran / _div;
- }
-
- float _err [SIZE + 4];
- int _ind;
- uint32_t _ran;
-
- static float _div;
-};
-
-
-#endif
-
diff --git a/dll/src/zita-resampler/apps/zresample.1 b/dll/src/zita-resampler/apps/zresample.1
deleted file mode 100644
index fd88416..0000000
--- a/dll/src/zita-resampler/apps/zresample.1
+++ /dev/null
@@ -1,80 +0,0 @@
-.TH zresample 1 "May 2010" "version 0.0.1" "USER COMMANDS"
-.SH NAME
-zresample \- resample and change sample format of audio files
-.SH SYNOPSIS
-.B zresample
-[options] input-file output-file
-.SH DESCRIPTION
-.B zresample
-copies an audio file, changing the sample rate and/or the
-sample format. For 16-bit output it can also dither the
-audio signal. Input can be any audio file readable by the
-libsndfile library. The output file type is either WAV or CAF.
-.SH OPTIONS
-.TP
-.B --help
-Display a short help text.
-.TP
-.B --rate sample-rate
-Set the output sample rate.
-.B Zresample
-uses the zita-resampler library which means that not all
-combinations of input/output sample rate will be accepted.
-The resample ratio must be a reducable to a fraction
-.B a/b
-with both
-.B a
-and
-.B b
-less than or equal to 1000.
-.SS Output file type
-.TP
-.B --wav
-Produce a WAV file, or for more than 2 channels, a WAVEX file.
-This is the default.
-.TP
-.B --amb
-Produce a WAVEX file with the Ambisonic GUID. Such files should
-have the
-.B .amb
-filename extension.
-.TP
-.B --caf
-Produce a Core Audio file.
-.SS Output sample format
-.TP
-.B --16bit
-Output sample format is signed 16-bit. This option also
-enables the use of dithering, described below.
-.TP
-.B --24bit
-Output sample format is 24-bit. This is the default.
-.TP
-.B --float
-Output sample format is 32-bit floating point.
-.SS Dithering
-.TP
-.B --rec
-Add white dithering noise with a rectangular distribution. This
-is the best option if the output data is going to processed again,
-but in that case it would be advisable to use 24-bit or float.
-.TP
-.B --tri
-Add filtered noise with a triangular distribution. Compared to the
-rectangular dither this reduces the noise density in the lower
-frequency range.
-.TP
-.B --lips
-This uses the optimal error feedback filter described by
-Stanley Lipschitz. This is recommended is the output is the
-final distribution format, e.g. for a CD.
-.SS Timing
-.TP
-.B --pad
-Insert zero valued input samples at the start and end so that the output
-includes the full symmetric filter response even for the first and last
-samples.
-.SH EXIT STATUS
-Zero in case there are no errors, non-zero otherwise.
-.SH AUTHOR
-Fons Adriaensen (fons (at) linuxaudio.org)
diff --git a/dll/src/zita-resampler/apps/zresample.cc b/dll/src/zita-resampler/apps/zresample.cc
deleted file mode 100644
index fba0102..0000000
--- a/dll/src/zita-resampler/apps/zresample.cc
+++ /dev/null
@@ -1,272 +0,0 @@
-// ----------------------------------------------------------------------------
-//
-// Copyright (C) 2006-2011 Fons Adriaensen <fons@linuxaudio.org>
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-//
-// ----------------------------------------------------------------------------
-
-
-#include <stdlib.h>
-#include <string.h>
-#include <getopt.h>
-#include <stdio.h>
-#include <math.h>
-#include <zita-resampler/resampler.h>
-#include "audiofile.h"
-
-
-enum { HELP, CAF, WAV, AMB, BIT16, BIT24, FLOAT, RATE, REC, TRI, LIPS, PAD };
-enum { BUFFSIZE = 0x4000, FILTSIZE = 96 };
-
-
-static unsigned int type = Audiofile::TYPE_WAV;
-static unsigned int form = Audiofile::FORM_24BIT;
-static unsigned int rout = 0;
-static unsigned int dith = Audiofile::DITHER_NONE;
-static bool zpad = false;
-
-
-static void help (void)
-{
- fprintf (stderr, "\nzresample %s\n", VERSION);
- fprintf (stderr, "(C) 2007-2012 Fons Adriaensen <fons@linuxaudio.org>\n");
- fprintf (stderr, "Usage: zresample <options> <input file> <output file>.\n");
- fprintf (stderr, "Options:\n");
- fprintf (stderr, " Display this text: --help\n");
- fprintf (stderr, " Output file type: --caf, --wav, --amb\n");
- fprintf (stderr, " Output sample rate: --rate <sample rate>\n");
- fprintf (stderr, " Output sample format: --16bit, --24bit, --float\n");
- fprintf (stderr, " Dither type (16 bit): --rec, --tri, --lips\n");
- fprintf (stderr, " Add zero padding : --pad\n");
- fprintf (stderr, "The default output file format is wav, 24-bit, no dithering.\n");
- fprintf (stderr, "Integer output formats are clipped, float output is not.\n\n");
- exit (1);
-}
-
-
-static struct option options [] =
-{
- { "help", 0, 0, HELP },
- { "caf", 0, 0, CAF },
- { "wav", 0, 0, WAV },
- { "amb", 0, 0, AMB },
- { "16bit", 0, 0, BIT16 },
- { "24bit", 0, 0, BIT24 },
- { "float", 0, 0, FLOAT },
- { "rate", 1, 0, RATE },
- { "rec", 0, 0, REC },
- { "tri", 0, 0, TRI },
- { "lips", 0, 0, LIPS },
- { "pad", 0, 0, PAD },
- { 0, 0, 0, 0 }
-};
-
-
-static void procoptions (int ac, char *av [])
-{
- int k;
-
- while ((k = getopt_long (ac, av, "", options, 0)) != -1)
- {
- switch (k)
- {
- case '?':
- case HELP:
- help ();
- break;
- case CAF:
- type = Audiofile::TYPE_CAF;
- break;
- case WAV:
- type = Audiofile::TYPE_WAV;
- break;
- case AMB:
- type = Audiofile::TYPE_AMB;
- break;
- case BIT16:
- form = Audiofile::FORM_16BIT;
- break;
- case BIT24:
- form = Audiofile::FORM_24BIT;
- break;
- case FLOAT:
- form = Audiofile::FORM_FLOAT;
- break;
- case RATE:
- if (sscanf (optarg, "%d", &rout) != 1)
- {
- fprintf (stderr, "Illegal value for --rate option: '%s'.\n", optarg);
- exit (1);
- }
- break;
- case REC:
- dith = Audiofile::DITHER_RECT;
- break;
- case TRI:
- dith = Audiofile::DITHER_TRIA;
- break;
- case LIPS:
- dith = Audiofile::DITHER_LIPS;
- break;
- case PAD:
- zpad = true;
- break;
- }
- }
-}
-
-
-int main (int ac, char *av [])
-{
- Audiofile Ainp;
- Audiofile Aout;
- Resampler R;
- unsigned int k, chan, rinp, z1, z2;
- float *inpb, *outb;
- bool done;
-
- procoptions (ac, av);
- if (ac - optind < 2)
- {
- fprintf (stderr, "Missing arguments, try --help.\n");
- return 1;
- }
- if (ac - optind > 2 )
- {
- fprintf (stderr, "Too many arguments, try --help.\n");
- return 1;
- }
-
- if (Ainp.open_read (av [optind]))
- {
- fprintf (stderr, "Can't open input file '%s'.\n", av [optind]);
- return 1;
- }
-
- chan = Ainp.chan ();
- rinp = Ainp.rate ();
- if (rout == 0) rout = rinp;
-
- if (rout != rinp)
- {
- if ((rinp < 8000) || (rinp > 192000))
- {
- fprintf (stderr, "Input sample %d rate is out of range.\n", rinp);
- Ainp.close ();
- return 1;
- }
- if ((rout < 8000) || (rout > 192000))
- {
- fprintf (stderr, "Output sample rate %d is out of range.\n", rout);
- Ainp.close ();
- return 1;
- }
- if (R.setup (rinp, rout, chan, FILTSIZE))
- {
- fprintf (stderr, "Sample rate ratio %d/%d is not supported.\n", rout, rinp);
- Ainp.close ();
- return 1;
- }
- }
-
- optind++;
- if (Aout.open_write (av [optind], type, form, rout, chan))
- {
- fprintf (stderr, "Can't open output file '%s'.\n", av [optind]);
- Ainp.close ();
- return 1;
- }
- if (dith != Audiofile::DITHER_NONE)
- {
- Aout.set_dither (dith);
- }
-
- if (zpad)
- {
- z1 = R.inpsize () - 1;
- z2 = R.inpsize () - 1;
- }
- else
- {
- z1 = R.inpsize () / 2 - 1;
- z2 = R.inpsize () / 2;
- }
-
- inpb = new float [chan * BUFFSIZE];
- if (rout != rinp)
- {
- outb = new float [chan * BUFFSIZE];
- // Insert zero samples at start.
- R.inp_count = z1;
- R.inp_data = 0;
- R.out_count = BUFFSIZE;
- R.out_data = outb;
- done = false;
- while (true)
- {
- R.process ();
- if (R.inp_count == 0)
- {
- // Input buffer empty, read more samples, insert
- // zeros at the end, or terminate.
- if (done)
- {
- // We already inserted final zero samples.
- // Write out any remaining output samples and terminate.
- Aout.write (outb, BUFFSIZE - R.out_count);
- break;
- }
- k = Ainp.read (inpb, BUFFSIZE);
- if (k)
- {
- // Process next 'k' input samples.
- R.inp_count = k;
- R.inp_data = inpb;
- }
- else
- {
- // At end of input, insert zero samples.
- R.inp_count = z2;
- R.inp_data = 0;
- done = true;
- }
- }
- if (R.out_count == 0)
- {
- // Output buffer full, write to file.
- Aout.write (outb, BUFFSIZE);
- R.out_count = BUFFSIZE;
- R.out_data = outb;
- }
- }
- delete[] outb;
- }
- else
- {
- // No resampling, just copy.
- while (1)
- {
- k = Ainp.read (inpb, BUFFSIZE);
- if (k) Aout.write (inpb, k);
- else break;
- }
- }
-
- Ainp.close ();
- Aout.close ();
- delete[] inpb;
-
- return 0;
-}
diff --git a/dll/src/zita-resampler/apps/zretune.1 b/dll/src/zita-resampler/apps/zretune.1
deleted file mode 100644
index 3006089..0000000
--- a/dll/src/zita-resampler/apps/zretune.1
+++ /dev/null
@@ -1,73 +0,0 @@
-.TH zretune 1 "Sect 2012" "version 0.0.1" "USER COMMANDS"
-.SH NAME
-zretune \- resample an audio file in order to change its pitch
-.SH SYNOPSIS
-.B zretune
-[options] input-file output-file
-.SH DESCRIPTION
-.B zretune
-resamples an audio file by a the inverse of a ratio expressed in cents,
-without changing the nominal sample rate. The result is to change the
-musical pitch and lenght of the file. Input can be any audio file
-readable by the libsndfile library. The output file type is either
-WAV or CAF.
-.SH OPTIONS
-.TP
-.B --help
-Display a short help text.
-.TP
-.B --cent pitch change in cents
-The number of cents by which the pitch is changed. The accepted
-range is +/- 1200 cents, the useful range in practice will be
-something like +/- 100 cents.
-.SS Output file type
-.TP
-.B --wav
-Produce a WAV file, or for more than 2 channels, a WAVEX file.
-This is the default.
-.TP
-.B --amb
-Produce a WAVEX file with the Ambisonic GUID. Such files should
-have the
-.B .amb
-filename extension.
-.TP
-.B --caf
-Produce a Core Audio file.
-.SS Output sample format
-.TP
-.B --16bit
-Output sample format is signed 16-bit. This option also
-enables the use of dithering, described below.
-.TP
-.B --24bit
-Output sample format is 24-bit. This is the default.
-.TP
-.B --float
-Output sample format is 32-bit floating point.
-.SS Dithering
-.TP
-.B --rec
-Add white dithering noise with a rectangular distribution. This
-is the best option if the output data is going to processed again,
-but in that case it would be advisable to use 24-bit or float.
-.TP
-.B --tri
-Add filtered noise with a triangular distribution. Compared to the
-rectangular dither this reduces the noise density in the lower
-frequency range.
-.TP
-.B --lips
-This uses the optimal error feedback filter described by
-Stanley Lipschitz. This is recommended is the output is the
-final distribution format, e.g. for a CD.
-.SS Timing
-.TP
-.B --pad
-Insert zero valued input samples at the start and end so that the output
-includes the full symmetric filter response even for the first and last
-samples.
-.SH EXIT STATUS
-Zero in case there are no errors, non-zero otherwise.
-.SH AUTHOR
-Fons Adriaensen (fons (at) linuxaudio.org)
diff --git a/dll/src/zita-resampler/apps/zretune.cc b/dll/src/zita-resampler/apps/zretune.cc
deleted file mode 100644
index cb950cb..0000000
--- a/dll/src/zita-resampler/apps/zretune.cc
+++ /dev/null
@@ -1,257 +0,0 @@
-// ----------------------------------------------------------------------------
-//
-// Copyright (C) 2006-2011 Fons Adriaensen <fons@linuxaudio.org>
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-//
-// ----------------------------------------------------------------------------
-
-
-#include <stdlib.h>
-#include <string.h>
-#include <getopt.h>
-#include <stdio.h>
-#include <math.h>
-#include <zita-resampler/vresampler.h>
-#include "audiofile.h"
-
-
-enum { HELP, CAF, WAV, AMB, BIT16, BIT24, FLOAT, CENT, REC, TRI, LIPS, PAD };
-enum { BUFFSIZE = 0x4000, FILTSIZE = 96 };
-
-
-static unsigned int type = Audiofile::TYPE_WAV;
-static unsigned int form = Audiofile::FORM_24BIT;
-static double cent = 0;
-static unsigned int dith = Audiofile::DITHER_NONE;
-static bool zpad = false;
-
-
-static void help (void)
-{
- fprintf (stderr, "\nzretune %s\n", VERSION);
- fprintf (stderr, "(C) 2007-2012 Fons Adriaensen <fons@linuxaudio.org>\n");
- fprintf (stderr, "Usage: zretune <options> <input file> <output file>.\n");
- fprintf (stderr, "Options:\n");
- fprintf (stderr, " Display this text: --help\n");
- fprintf (stderr, " Output file type: --caf, --wav, --amb\n");
- fprintf (stderr, " Resampling ratio: --cent <pitch change>\n");
- fprintf (stderr, " Output sample format: --16bit, --24bit, --float\n");
- fprintf (stderr, " Dither type (16 bit): --rec, --tri, --lips\n");
- fprintf (stderr, " Add zero padding : --pad\n");
- fprintf (stderr, "The default output file format is wav, 24-bit, no dithering.\n");
- fprintf (stderr, "Integer output formats are clipped, float output is not.\n\n");
- exit (1);
-}
-
-
-static struct option options [] =
-{
- { "help", 0, 0, HELP },
- { "caf", 0, 0, CAF },
- { "wav", 0, 0, WAV },
- { "amb", 0, 0, AMB },
- { "16bit", 0, 0, BIT16 },
- { "24bit", 0, 0, BIT24 },
- { "float", 0, 0, FLOAT },
- { "cent", 1, 0, CENT },
- { "rec", 0, 0, REC },
- { "tri", 0, 0, TRI },
- { "lips", 0, 0, LIPS },
- { "pad", 0, 0, PAD },
- { 0, 0, 0, 0 }
-};
-
-
-static void procoptions (int ac, char *av [])
-{
- int k;
-
- while ((k = getopt_long (ac, av, "", options, 0)) != -1)
- {
- switch (k)
- {
- case '?':
- case HELP:
- help ();
- break;
- case CAF:
- type = Audiofile::TYPE_CAF;
- break;
- case WAV:
- type = Audiofile::TYPE_WAV;
- break;
- case AMB:
- type = Audiofile::TYPE_AMB;
- break;
- case BIT16:
- form = Audiofile::FORM_16BIT;
- break;
- case BIT24:
- form = Audiofile::FORM_24BIT;
- break;
- case FLOAT:
- form = Audiofile::FORM_FLOAT;
- break;
- case CENT:
- if (sscanf (optarg, "%lf", &cent) != 1)
- {
- fprintf (stderr, "Illegal value for --rate option: '%s'.\n", optarg);
- exit (1);
- }
- break;
- case REC:
- dith = Audiofile::DITHER_RECT;
- break;
- case TRI:
- dith = Audiofile::DITHER_TRIA;
- break;
- case LIPS:
- dith = Audiofile::DITHER_LIPS;
- break;
- case PAD:
- zpad = true;
- break;
- }
- }
-}
-
-
-int main (int ac, char *av [])
-{
- Audiofile Ainp;
- Audiofile Aout;
- VResampler R;
- unsigned int k, chan, z1, z2;
- float *inpb, *outb;
- bool done;
- double ratio;
-
- procoptions (ac, av);
- if (ac - optind < 2)
- {
- fprintf (stderr, "Missing arguments, try --help.\n");
- return 1;
- }
- if (ac - optind > 2 )
- {
- fprintf (stderr, "Too many arguments, try --help.\n");
- return 1;
- }
-
- if (Ainp.open_read (av [optind]))
- {
- fprintf (stderr, "Can't open input file '%s'.\n", av [optind]);
- return 1;
- }
-
- if ((cent < -1200) || (cent > 1200))
- {
- fprintf (stderr, "Pitch change %3.1lf is out of range.\n", cent);
- Ainp.close ();
- return 1;
- }
- ratio = pow (2.0, -cent / 1200.0);
- R.setup (ratio, Ainp.chan (), FILTSIZE);
-
- optind++;
- if (Aout.open_write (av [optind], type, form, Ainp.rate(), Ainp.chan ()))
- {
- fprintf (stderr, "Can't open output file '%s'.\n", av [optind]);
- Ainp.close ();
- return 1;
- }
- if (dith != Audiofile::DITHER_NONE)
- {
- Aout.set_dither (dith);
- }
-
- if (zpad)
- {
- z1 = R.inpsize () - 1;
- z2 = R.inpsize () - 1;
- }
- else
- {
- z1 = R.inpsize () / 2 - 1;
- z2 = R.inpsize () / 2;
- }
-
- chan = Ainp.chan ();
- inpb = new float [chan * BUFFSIZE];
- if (cent != 0.0)
- {
- outb = new float [chan * BUFFSIZE];
- // Insert zero samples at start.
- R.inp_count = z1;
- R.inp_data = 0;
- R.out_count = BUFFSIZE;
- R.out_data = outb;
- done = false;
- while (true)
- {
- R.process ();
- if (R.inp_count == 0)
- {
- // Input buffer empty, read more samples, insert
- // zeros at the end, or terminate.
- if (done)
- {
- // We already inserted final zero samples.
- // Write out any remaining output samples and terminate.
- Aout.write (outb, BUFFSIZE - R.out_count);
- break;
- }
- k = Ainp.read (inpb, BUFFSIZE);
- if (k)
- {
- // Process next 'k' input samples.
- R.inp_count = k;
- R.inp_data = inpb;
- }
- else
- {
- // At end of input, insert zero samples.
- R.inp_count = z2;
- R.inp_data = 0;
- done = true;
- }
- }
- if (R.out_count == 0)
- {
- // Output buffer full, write to file.
- Aout.write (outb, BUFFSIZE);
- R.out_count = BUFFSIZE;
- R.out_data = outb;
- }
- }
- delete[] outb;
- }
- else
- {
- // No resampling, just copy.
- while (1)
- {
- k = Ainp.read (inpb, BUFFSIZE);
- if (k) Aout.write (inpb, k);
- else break;
- }
- }
-
- Ainp.close ();
- Aout.close ();
- delete[] inpb;
-
- return 0;
-}
diff --git a/dll/src/zita-resampler/docs/filt1.png b/dll/src/zita-resampler/docs/filt1.png
deleted file mode 100644
index 0fdd30c..0000000
--- a/dll/src/zita-resampler/docs/filt1.png
+++ /dev/null
Binary files differ
diff --git a/dll/src/zita-resampler/docs/filt2.png b/dll/src/zita-resampler/docs/filt2.png
deleted file mode 100644
index 4a5bf5b..0000000
--- a/dll/src/zita-resampler/docs/filt2.png
+++ /dev/null
Binary files differ
diff --git a/dll/src/zita-resampler/docs/inpdist.png b/dll/src/zita-resampler/docs/inpdist.png
deleted file mode 100644
index 5a89018..0000000
--- a/dll/src/zita-resampler/docs/inpdist.png
+++ /dev/null
Binary files differ
diff --git a/dll/src/zita-resampler/docs/resampler.html b/dll/src/zita-resampler/docs/resampler.html
deleted file mode 100644
index 67b2d4e..0000000
--- a/dll/src/zita-resampler/docs/resampler.html
+++ /dev/null
@@ -1,574 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<html>
-<head>
- <title>Zita-resampler.</title>
- <meta name="Author" content="Fons Adriaensen (fons@linuxaudio.org)">
- <meta name="Description" content="The zita-resampler library.">
- <meta name="Keywords" content="resampling sound audio dsp linux">
- <link rel=StyleSheet href="zitadocs.css" type="text/css" media="all">
-</head>
-
-<body>
-
-
-<h1>Libzita-resampler</h1>
-<ul>
-<li><a href = "#introduction">Introduction</a>
-<li><a href = "#algorithm">The algorithm</a>
-<li><a href = "#description">API description</a>
-<li><a href = "#reference">API reference</a>
-</ul>
-
-<br>
-<a name = "introduction"></a>
-<h2>Introduction</h2>
-<p>
-Libzita-resampler is a C++ library for resampling audio signals. It is designed
-to be used within a real-time processing context, to be fast, and to provide
-high-quality sample rate conversion.
-</p>
-<p>
-The library operates on signals represented in single-precision floating point
-format. For multichannel operation both the input and output signals are
-assumed to be stored as interleaved samples.
-</p>
-<p>
-The API allows a trade-off between quality and CPU load. For the latter
-a range of approximately 1:6 is available. Even at the highest quality
-setting libzita-resampler will be faster than most similar libraries
-providing the same quality, e.g. libsamplerate.
-</p>
-<p>
-In many real-time resampling applications (e.g. an audio player), processing
-is driven by the ouput sample rate: each processing period requires a fixed
-number of output samples, and the input side has to adapt, providing whatever
-number of samples required. The inverse situation (less common, but possible)
-would be e.g. a recording application that writes an audio file at a rate that
-is different from the hardware sample rate. In that case the number of input
-samples is fixed for each processing period. The API provided by libzita-resampler
-is fully symmetric in this respect - it handles both situations in the exactly the
-same way, using the same application code.
-</p>
-<p>
-Libzita-resampler provides two classes:
-</p>
-<p>
-The <b>Resampler</b> class performs resampling at a fixed ratio <b>F_out / F_in</b>
-which is required to be <b>&ge; 1/16</b> and be reducible to the form <b> b / a</b>
-with <b>a, b</b> integer and <b>b &le; 1000</b>. This includes all the 'standard'
-ratios, e.g. 96000 / 44100 = 320 / 147. These restrictions allow for a more efficient
-implementation.
-</p>
-<p>
-The <b>VResampler</b> class provides an arbitrary ratio <b>r</b> in the range
-<b>1/16 &le; r &le; 64</b> and which can variable within a range of <b>0.95 to
-16.0</b> w.r.t. the originally configured one. The lower limit here is necessary
-because this class still uses a fixed multiphase filter, with only the phase step
-being variable. This class was developed for converting between two nominally fixed
-sample rates with a ratio which is not known exactly and may even drift slowly, e.g.
-when combining sound cards wich do not have a common word clock. This resampler is
-somewhat less efficient than the fixed ratio one since it has to interpolate filter
-coefficients, but the difference is marginal when used on multichannel signals.
-</p>
-<p>
-Both classes provide essentially the same API, with only small differences
-where necessary.
-
-<br>
-<a name = "algorithm"></a>
-<h2>The algorithm</h2>
-<p>
-Libzita-resampler implements <b>constant bandwidth resampling</b>. In contrast
-to e.g. cubic interpolation it does not consider the actual shape of the
-waveform represented by the input samples, but rather operates in the spectral
-domain.
-</p>
-<p>
-Let
-<ul>
-<li><b>F_in, F_out</b>&nbsp &nbsp be the input and output sample rates,</li>
-<li><b>F_min</b>&nbsp &nbsp the lower of the two,</li>
-<li><b>F_lcm</b>&nbsp &nbsp their lowest common multiple,</li>
-<li><b>b = F_lcm / F_in</b>,</li>
-<li><b>a = F_lcm / F_out</b></li>.
-</ul>
-<p>
-Then the calculation performed by zita-resampler is equivalent to:
-</p>
-<ul>
-<li>upsampling to a rate of <b>F_lcm</b> by inserting <b>b - 1</b>
-zero-valued samples after each input sample,</li>
-<li>low-pass filtering of the upsampled signal to remove everything
-above <b>F_min / 2</b>,</li>
-<li>retaining only the first of each series of <b>a</b> filtered
-samples.</li>
-</ul>
-<p>
-This is of course not how things are implemented in the resampler code.
-Only those samples that are actually output are computed, and the inserted
-zeros are never used. In practice this means there is a set of <b>b</b>
-different FIR filters that each output one sample in turn, in round-robin
-fashion. All these filters have the same frequency response, but different
-delays that correspond to the relative position in time of the input and
-output samples.
-</p>
-<p>
-A real-world filter can't be perfect, it is always a compromise between
-complexity (CPU load) and performance. In the context of resampling this
-compromise manifests itself as deviations from the ideally flat frequency
-response, and as aliasing - the same phenomenon that occurs with AD and
-DA conversion. For aliasing, two cases need to be considered:
-</p>
-<p>
-<b>Upsampling.</b> In this case <b>F_min = F_in</b>, and input signals
-below but near to <b>F_in / 2</b> will also appear in the output
-just above this frequency. This is similar to DA conversion.
-</p>
-<p>
-<b>Downsampling.</b> In this case <b>F_min = F_out</b>, and input signals
-above but near to <b>F_out / 2</b> will also appear in the output
-just below this frequency. This is similar to AD conversion.
-</p>
-<p>
-In the design of zita-resampler it was assumed that in most cases
-conversion will be between the 'standard' audio sample rates (44.1,
-48, 88.2, 96, 192 kHz), and that consequently frequency response
-errors and aliasing will occur only above the upper limit of the
-audible frequency range. Given this assumption, some pragmatic
-trade-offs can be made.
-</p>
-<p>
-The filter used by libzita-resampler is dimensioned to reach an
-attenuation of 60dB at the Nyquist frequency. The initialisation
-function takes a parameter named <b>hlen</b> that is in fact half
-the length of the symmetrical FIR filter expressend in samples at
-the rate <b>F_min</b>. The valid range for <b>hlen</b> is 16 to 96.
-The figure below shows the filter responses for <b>hlen</b> = 32,
-48, and 96. The <b>x</b> axis is <b>F / F_min</b>, the <b>y</b> axis
-is in dB. The lower part of the traces is the mirrored continuation
-of the response above the Nyquist frequency, i.e. the aliasing.
-Note that 20 kHz corresponds to x = 0.416 for a sample rate of 48 kHz,
-and to x = 0.454 for a sample rate of 44.1 kHz.
-</p>
-<p>
-<img src="filt1.png">
-</p>
-<p>
-<br>
-The same traces with a reduced vertical range, showing the passband
-response.
-</p>
-<p>
-<img src="filt2.png">
-</p>
-<p>
-From these figures it should be clear that <b>hlen = 32</b> should
-provide very high quality for <b>F_min</b> equal to 48 kHz or higher,
-while <b>hlen = 48</b> should be sufficient for an <b>F_min</b> of
-44.1 kHz. The validity of these assumptions was confirmed by a series
-of listening tests. If fact the conclusion of these test was that even
-at 44.1 kHz the subjects (all audio specialists or musicians) could not
-detect any significant difference between <b>hlen</b> values of 32 and 96.
-</p>
-
-<br>
-<a name = "description"></a>
-<h2>API description</h2>
-<p>
-The constructors of both classes do not initialise the object for a particular
-resampling rate, quality or number of channels - this is done by a separate
-function member which can be used as many times as necessary. This means you
-can allocate <b>(V)Resampler</b> objects before the actual resampling parameters
-are known.
-</p>
-<p>
-The <b>setup ()</b> member initialises a resampler for a combination of input
-sample rate, output sample rate, number of channels, and filter length. This
-function allocates and computes the filter coefficient tables and is definitely
-not RT-safe. The actual tables will be shared with other resampler instances if
-possible - the library maintains a reference-counted collection of them. After
-the initialisation by <b>setup ()</b>, the <b>process ()</b> member can be called
-repeatedly to actually resample audio signals. This function is RT-safe and
-can be used within e.g. a JACK callback. The <b>clear ()</b> member restores
-the object to the initial state it has after construction, and is also called
-from the destructor. You can safely call <b>setup ()</b> again without first
-calling <b>clear ()</b> - doing this avoids recomputation of the filter
-coefficients in some cases.
-</p>
-<p>
-Both classes have four public data members which are used as input and output
-parameters of <b>process ()</b>, in the same way as you would use a C struct
-to pass parameters. These are:
-</p>
-<pre>
- unsigned int inp_count; // number of frames in the input buffer
- unsigned int out_count; // number of frames in the output buffer
- float *inp_data; // pointer to first input frame
- float *out_data; // pointer to first output frame
-</pre>
-<p>
-As <b>process ()</b> does its work, it increments the pointers and decrements the
-counts. The call returns when either of the counts is zero, i.e. when the input
-buffer is empty or the output buffer is full. You should then take appropriate
-action and if necessary call <b>process ()</b> again.
-</p>
-<p>
-When <b>process ()</b> returns, the four parameter values exactly reflect
-those parts of both buffers <b>that have not yet been used</b>.
-One of them will be fully used, with the corresponding count being zero.
-The remaining part of the other, pointed to by the returned pointer, can
-always be replaced before the next call to <b>process ()</b>, but this is
-entirely optional.
-</p>
-<p>
-When for example <b>inp_count</b> is zero, you have to fill the input buffer
-again, or provide a new one, and re-initialise the input count and pointer.
-If at that time <b>out_count</b> is not zero, you can either leave the output
-parameters as they are for the next call to <b>process ()</b>, or you could
-empty the part of the output buffer that has been filled and re-use it from
-the start, or provide a completely different one.
-</p>
-<p>
-The same applies to the input buffer when it is not empty on return of
-<b>process ()</b>: it can be left alone or be replaced. A number of input
-samples is stored internally between <b>process ()</b> calls as part of the
-resampler state, but this never includes samples that have not yet been used.
-So you can 'revise' the input data, starting from the frame pointed to by the
-returned <b>inp_data</b>, up to the last moment.
-</p>
-<p>
-All this means that both classes will interface easily with fixed input and
-output buffers, with dynamically generated input signals, and also with
-lock-free circular buffers.
-</p>
-<p>
-Either of the two pointers can be NULL. When <b>inp_data</b> is zero, the effect
-is to insert zero-valued input samples, as if you had supplied a zero-filled
-buffer of length <b>inp_count</b>. When <b>out_data</b> is zero, input samples
-will be consumed, the internal state of the resampler will advance normally
-and <b>out_count</b> will decrement, but no output samples are written (in
-fact they are not even computed).
-</p>
-<a name = "padding"></a>
-<p>
-Note that libzita-resampler does <b>not</b> automatically insert zero-valued
-input samples at the start and end of the resampling process. The API makes it
-easy to add such padding, and doing this is left entirely up to the user.
-</p>
-<p>
-The <b>inpsize ()</b> member returns the lenght of the FIR filter expressed in
-input samples. At least this number of samples is required to produce an output
-sample. If <b>k</b> is the value returned by this function, then
-</p>
-<ul>
-<li>inserting <b>k / 2 - 1</b> zero-valued samples at the start will align the
-first input and output samples,</li>
-<li>inserting <b>k - 1</b> zero valued samples will ensure that the output
-includes the full filter response for the first input sample.</li>
-</ul>
-<p>
-Similar considerations apply at the end of the input data:
-</p>
-<ul>
-<li>inserting <b>k / 2</b> zero-valued samples at the end will ensure
-that the last output sample produced will correspond to a position as close
-as possible but not past the last real input sample,</li>
-<li>inserting <b>k - 1</b> zero valued samples will ensure that the output
-includes the full filter response for the last real input sample.</li>
-</ul>
-<p>
-<a name = "inpdist"></a>
-The <b>inpdist ()</b> member returns the distance or delay expressed in sample
-periods at the input rate, between the first output sample that will be ouput
-by the next call to <b>process ()</b> and the first input sample that will be
-read (i.e. that is not yet part of the internal state).
-<br><br>
-In the picture below, the red dots represent input samples and the blue ones
-are the output. Solid dots are samples already used or output. After a call
-to process () the resampler object remains in a state ready to produce the next
-output sample, except that it may have to input one or more new samples first.
-The filter is aligned with the next output sample. In this case one more input
-sample is required to compute it, and the input distance is 2.7.
-</p>
-<p>
-<img src="inpdist.png">
-</p>
-<p>
-After a resampler is prefilled with <b>inpsize () / 2 - 1</b> samples as described
-above, <b>inpdist ()</b> will be zero - the first output sample corresponds exactly
-to the first input. Note that without prefilling the distance is negative, which
-means that the first output sample corresponds to some point past the start of the
-input data.
-</p>
-<p>
-The 'resample' application supplied with the library sources provides
-an example of how to use the <b>Resampler</b> class. For an example
-using <b>VResampler</b> you can have a look at zita_a2j and zita_ja2.
-</p>
-
-<br>
-<a name = "reference"></a>
-<h2>API reference</h2>
-<p>
-Public function members of the <b>Resampler</b> and <b>VResampler</b> classes.
-Functions listed without a class prefix are available for both classes.
-</p>
-<ul>
-<li><a href = "#resampler">Resampler ()</a>
-<li><a href = "#resampler">~Resampler ()</a>
-<li><a href = "#vresampler">VResampler ()</a>
-<li><a href = "#vresampler">~VResampler ()</a>
-<li><a href = "#res_setup">Reampler::setup ()</a>
-<li><a href = "#vres_setup">VResampler::setup ()</a>
-<li><a href = "#clear">clear ()</a>
-<li><a href = "#reset">reset ()</a>
-<li><a href = "#process">process ()</a>
-<li><a href = "#nchan">nchan ()</a>
-<li><a href = "#inpsize">inpsize ()</a>
-<li><a href = "#inpdist">inpdist ()</a>
-<li><a href = "#vres_set_rratio">VResampler::set_rratio ()</a>
-<li><a href = "#vres_set_rrfilt">VResampler::set_rrfilt ()</a>
-</ul>
-<p>
-Public data members of the <b>Resampler</b> and <b>VResampler</b> classes.
-</p>
-<ul>
-<li><a href = "#inp_count">inp_count</a>
-<li><a href = "#out_count">out_count</a>
-<li><a href = "#inp_data">inp_data</a>
-<li><a href = "#out_data">out_data</a>
-</ul>
-
-<a name="resampler"></a>
-<br><p class="apihdr">Resampler (void);<br>~Resampler (void);</p>
-<p>
-<b>Description:</b> Constructor and destructor. The constructor just creates an object that takes
-almost no memory but needs to be configured by <a href="#setup"><b>setup ()</b></a> before it
-can be used. The destructor calls <a href="#clear"><b>clear ()</b></a>.
-<br><br>
-<b>RT-safe:</b> No
-</p>
-
-<a name="vresampler"></a>
-<br><p class="apihdr">VResampler (void);<br>~VResampler (void);</p>
-<p>
-<b>Description:</b> Constructor and destructor. The constructor just creates an object that takes
-almost no memory but needs to be configured by <a href="#setup"><b>setup ()</b></a> before it
-can be used. The destructor calls <a href="#clear"><b>clear ()</b></a>.
-<br><br>
-<b>RT-safe:</b> No
-</p>
-
-<a name="res_setup"></a>
-<br><p class="apihdr">int &nbsp Resampler::setup (unsigned int &nbsp fs_inp, unsigned int fs_out, unsigned int nchan, unsigned int hlen);</p>
-<p>
-<b>Description:</b> Configures the object for a combination of input / output sample rates, number
-of channels, and filter lenght.<br>If the parameters are OK, creates the filter coefficient tables
-or re-uses existing ones, allocates some internal resources, and returns via <a href="#reset">
-<b>reset ()</b></a>.
-<br><br>
-<b>Parameters:</b>
-</p>
-<p class="indent">
-<b>fs_inp, fs_out:</b> The input and output sample rates. The ratio <b>fs_out
-/ fs_inp</b> must be <b> &ge; 1/16</b> and reducible to the form <b>b / a</b>
-with <b>a, b</b> integer and <b>b &le; 1000</b>.
-<br><br>
-<b>nchan:</b> Number of channels, must not be zero.
-<br><br>
-<b>hlen:</b> Half the lenght of the filter expressed in samples at the lower of
-input and output rates. This parameter determines the 'quality' as explained
-<a href="#algorithm">here</a>. For any fixed combination of the other parameters,
-cpu load will be roughly proportional to <b>hlen</b>. The valid range is
-<b>16 &le; hlen &le; 96</b>.
-</p>
-<p>
-<b>Returns:</b> Zero on success, non-zero otherwise.
-<br><br>
-<b>Remark:</b> It is perfectly safe to call this function again without
-having called <a href="#clear"><b>clear ()</b></a> first. If only the number
-of channels is changed, doing this will avoid recalculation of the filter tables
-even if they are not shared.
-<br><br>
-<b>RT-safe:</b> No
-</p>
-
-<a name="vres_setup"></a>
-<br><p class="apihdr">int &nbsp VResampler::setup (double ratio, unsigned int nchan, unsigned int hlen);</p>
-<p>
-<b>Description:</b> Configures the object for a combination of resampling ratio, number of channels,
-and filter lenght.<br>If the parameters are OK, creates the filter coefficient tables or re-uses
-existing ones, allocates some internal resources, and returns via <a href="#reset">
-<b>reset ()</b></a>.
-<br><br>
-<b>Parameters:</b>
-</p>
-<p class="indent">
-<b>ratio:</b> The resampling ratio wich must be between <b>1/16</b> and <b>64</b>.
-<br><br>
-<b>nchan:</b> Number of channels, must not be zero.
-<br><br>
-<b>hlen:</b> Half the lenght of the filter expressed in samples at the lower of
-the input and output rates. This parameter determines the 'quality' as explained
-<a href="#algorithm">here</a>. For any fixed combination of the other parameters,
-cpu load will be roughly proportional to <b>hlen</b>. The valid range is
-<b>16 &le; hlen &le; 96</b>.
-</p>
-<p>
-<b>Returns:</b> Zero on success, non-zero otherwise.
-<br><br>
-<b>Remark:</b> It is perfectly safe to call this function again without
-having called <a href="#clear"><b>clear ()</b></a> first. If only the number
-of channels is changed, doing this will avoid recalculation of the filter tables
-even if they are not shared.
-<br><br>
-<b>RT-safe:</b> No
-</p>
-
-<a name="clear"></a>
-<br><p class="apihdr">void &nbsp clear (void);</p>
-<p>
-<b>Description:</b> Deallocates resources (if not shared) and returns the object to
-the unconfigured state as after construction. Also called by the destructor.
-<br><br>
-<b>RT-safe:</b> No
-</p>
-
-<a name="reset"></a>
-<br><p class="apihdr">int &nbsp reset (void);</p>
-<p>
-<b>Description:</b> Resets the internal state of the resampler. Any stored
-input samples are cleared, the filter phase and the four <a href="#inp_count">
-public data members</a> are set to zero. This should be called before starting
-resampling a new stream with the same configuration as the previous one.
-<br><br>
-<b>Returns:</b> Zero if the resampler is configured , non-zero otherwise.
-<br><br>
-<b>RT-safe:</b> Yes.
-</p>
-
-<a name="process"></a>
-<br><p class="apihdr">int &nbsp process (void);</p>
-<p>
-<b>Description:</b> Resamles the input signal until either the input buffer
-is empty or the output buffer is full. Information on the input and output
-buffers is passed to this function using the four <a href="#inp_count"> public
-data members</a> described below. The same four values are updated on return.
-<br><br>
-<b>Returns:</b> Zero if the resampler is configured, non-zero otherwise.
-<br><br>
-<b>RT-safe:</b> Yes.
-</p>
-
-<a name="nchan"></a>
-<br><p class="apihdr">int &nbsp nchan (void);</p>
-<p>
-<b>Description:</b> Accessor.
-<br><br>
-<b>Returns:</b> The number of channels the resampler is configured for,
-or zero if it is unconfigured. Input and output buffers are assumed to contain
-this number of channels in interleaved format.
-<br><br>
-<b>RT-safe:</b> Yes
-</p>
-
-<a name="inpsize"></a>
-<br><p class="apihdr">int &nbsp inpisze (void);</p>
-<p>
-<b>Description:</b> Accessor.
-<br><br>
-<b>Returns:</b> If the resampler is configured, the lenght of the
-finite impulse filter expressed in samples at the input sample rate,
-or zero otherwise. This value may be used to determine the number of
-silence samples to insert at the start and end when resampling e.g.
-an impulse response. See <a href="#padding">here</a> for more about this.
-This function was called 'filtlen ()' in previous releases.
-<br><br>
-<b>RT-safe:</b> Yes
-</p>
-
-<a name="inpdist"></a>
-<br><p class="apihdr">double &nbsp inpdist (void);</p>
-<p>
-<b>Description:</b> Accessor.
-<br><br>
-<b>Returns:</b> If the resampler is configured, the distance between
-the next output sample and the next input sample, expressed in sample
-periods at the input rate, zero otherwise. See <a href="#inpdist">
-here</a> for more about this.
-<br><br>
-<b>RT-safe:</b> Yes
-</p>
-
-<a name="vres_set_rratio"></a>
-<br><p class="apihdr">void &nbsp VResampler::set_rratio (double ratio);</p>
-<p>
-<b>Description:</b> Sets the resampling ratio relative to the one configured
-by <a href="#vres_setup"> setup ()</a>. The valid range is <b>0.95 &le;
-ratio &le; 16</b>.
-<br><br>
-<b>Parameters:</b>
-</p>
-<p class="indent">
-<b>ratio:</b> The relative resampling ratio.
-</p>
-<p>
-<b>RT-safe:</b> Yes
-</p>
-
-<a name="vres_set_rrfilt"></a>
-<br><p class="apihdr">void &nbsp VResampler::set_rrfilt (double time);</p>
-<p>
-<b>Description:</b> Sets the time constant of the first order filter applied
-on values set by <a href="#vres_set_rratio"> set_rratio ()</a>. The time is
-expressed as sample periods at the output rate. The default is zero, which
-means changes are applied instantly.
-<br><br>
-<b>Parameters:</b>
-</p>
-<p class="indent">
-<b>time:</b> The filter time constant.
-</p>
-<p>
-<b>RT-safe:</b> Yes
-</p>
-
-<a name="inp_count"></a>
-<br><p class="apihdr">unsigned int &nbsp inp_count;</p>
-<p>
-<b>Description:</b> Data member, input / output parameter of the <a href="#process">
-process ()</a> function. This value is always equal to the number of frames in the
-input buffer that have not yet been read by the process () function. It should be set
-to the number of available frames before calling process ().
-</p>
-
-<a name="out_count"></a>
-<br><p class="apihdr">unsigned int &nbsp out_count;</p>
-<p>
-<b>Description:</b> Data member, input / output parameter of the <a href="#process">
-process ()</a> function. This value is always equal to the number of frames in the
-output buffer that have not yet been written by the process () function. It should be
-set to the size of the output buffer before calling process ().
-</p>
-
-<a name="inp_data"></a>
-<br><p class="apihdr">float &nbsp *inp_data;</p>
-<p>
-<b>Description:</b> Data member, input / output parameter of the <a href="#process">
-process ()</a> function. If not zero (NULL), this points to the next frame in the
-input buffer that will be read by process (). If set to zero (NULL), the resampler
-will proceed normally but use zero-valued samples as input (still counted by
-<b>inp_count</b>).
-</p>
-
-<a name="out_data"></a>
-<br><p class="apihdr">float &nbsp *out_data;</p>
-<p>
-<b>Description:</b> Data member, input / output parameter of the <a href="#process">
-process ()</a> function. If not zero (NULL), this points to the next frame in the
-output buffer that will be written by process (). If set to zero (NULL), the resampler
-will proceed normally but the output is discarded (but still counted by <b>out_count</b>).
-</p>
-
-</body>
-</html>
diff --git a/dll/src/zita-resampler/docs/src-1kHz.png b/dll/src/zita-resampler/docs/src-1kHz.png
deleted file mode 100644
index 18b450a..0000000
--- a/dll/src/zita-resampler/docs/src-1kHz.png
+++ /dev/null
Binary files differ
diff --git a/dll/src/zita-resampler/docs/zita-1kHz.png b/dll/src/zita-resampler/docs/zita-1kHz.png
deleted file mode 100644
index 4028fa4..0000000
--- a/dll/src/zita-resampler/docs/zita-1kHz.png
+++ /dev/null
Binary files differ
diff --git a/dll/src/zita-resampler/docs/zitadocs.css b/dll/src/zita-resampler/docs/zitadocs.css
deleted file mode 100644
index d75aa68..0000000
--- a/dll/src/zita-resampler/docs/zitadocs.css
+++ /dev/null
@@ -1,18 +0,0 @@
-body { background: white; color: black; font-family: arial, helvetica, sans-serif; }
-center { font-family: arial, helvetica, sans-serif; }
-p { font-family: arial, helvetica, sans-serif; text-align: left; margin-left: 3%; margin-right: 3%; }
-td { font-family: arial, helvetica, sans-serif; background: white; color: black; }
-ul { font-family: arial, helvetica, sans-serif; text-align: left; margin-left: 3%; margin-right: 6%; }
-ol { font-family: arial, helvetica, sans-serif; text-align: left; margin-left: 3%; margin-right: 6%; }
-dl { font-family: arial, helvetica, sans-serif; text-align: left; margin-left: 3%; margin-right: 3%; }
-h1 { font-size: xx-large; background: #8080FF; color: white; text-align: left; padding-left: 20; }
-h2 { font-size: x-large; background: #8080FF; color: white; text-align: left; padding-left: 20; }
-h3 { font-size: large; background: #8080FF; color: white; text-align: left; padding-left: 20; }
-pre { font-family: courier, monospace; font-size: medium; }
-a:link { color: #008000; }
-a:visited { color: #008000; }
-a:active { color: #FF00FF; }
-a:hover { background-color: #80FF80; color: black; }
-.apihdr { background: #E0E0FF; color: black; text-align: left; padding: 5; }
-.indent { font-family: arial, helvetica, sans-serif; text-align: left; margin-left: 50; margin-right: 50; }
-
diff --git a/dll/src/zita-resampler/libs/Makefile b/dll/src/zita-resampler/libs/Makefile
deleted file mode 100644
index 5a95c5f..0000000
--- a/dll/src/zita-resampler/libs/Makefile
+++ /dev/null
@@ -1,68 +0,0 @@
-# ----------------------------------------------------------------------------
-#
-# Copyright (C) 2006-2012 Fons Adriaensen <fons@linuxaudio.org>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-#
-# ----------------------------------------------------------------------------
-
-
-# Modify as required.
-#
-PREFIX = /usr/local
-SUFFIX := $(shell uname -m | sed -e 's/^unknown/$//' -e 's/^i.86/$//' -e 's/^x86_64/$/64/')
-LIBDIR = lib$(SUFFIX)
-
-MAJVERS = 1
-MINVERS = 3.0
-VERSION = $(MAJVERS).$(MINVERS)
-DISTDIR = zita-resampler-$(VERSION)
-
-
-CPPFLAGS += -I. -D_REENTRANT -D_POSIX_PTHREAD_SEMANTICS
-CXXFLAGS += -Wall -fPIC -O2 -ffast-math
-CXXFLAGS += -march=native
-LDFLAGS +=
-LDLIBS +=
-
-
-ZITA-RESAMPLER_SO = libzita-resampler.so
-ZITA-RESAMPLER_MAJ = $(ZITA-RESAMPLER_SO).$(MAJVERS)
-ZITA-RESAMPLER_MIN = $(ZITA-RESAMPLER_MAJ).$(MINVERS)
-ZITA-RESAMPLER_DEP =
-ZITA-RESAMPLER_O = resampler.o vresampler.o resampler-table.o
-ZITA-RESAMPLER_H = zita-resampler/resampler.h zita-resampler/resampler-table.h zita-resampler/vresampler.h
-
-
-$(ZITA-RESAMPLER_MIN): $(ZITA-RESAMPLER_O)
- g++ -shared $(LDFLAGS) -Wl,-soname,$(ZITA-RESAMPLER_MAJ) -o $(ZITA-RESAMPLER_MIN) $(ZITA-RESAMPLER_O) $(ZITA-RESAMPLER_DEP)
-
-$(ZITA-RESAMPLER_O): $(ZITA-RESAMPLER_H)
-
-
-install: $(ZITA-RESAMPLER_MIN)
- install -d $(DESTDIR)$(PREFIX)/include/zita-resampler
- install -d $(DESTDIR)$(PREFIX)/$(LIBDIR)
- install -m 644 $(ZITA-RESAMPLER_H) $(DESTDIR)$(PREFIX)/include/zita-resampler
- install -m 644 $(ZITA-RESAMPLER_MIN) $(DESTDIR)$(PREFIX)/$(LIBDIR)
- ln -sf $(ZITA-RESAMPLER_MIN) $(DESTDIR)$(PREFIX)/$(LIBDIR)/$(ZITA-RESAMPLER_SO)
- ldconfig
-
-uninstall:
- /bin/rm -rf $(DESTDIR)$(PREFIX)/include/zita-resampler
- /bin/rm -rf $(DESTDIR)$(PREFIX)/$(LIBDIR)/libzita-resampler*
-
-clean:
- /bin/rm -rf *~ *.o *.a *.d *.so.* zita-resampler/*~
-
diff --git a/dll/src/zita-resampler/libs/resampler-table.cc b/dll/src/zita-resampler/libs/resampler-table.cc
deleted file mode 100644
index 5fc765f..0000000
--- a/dll/src/zita-resampler/libs/resampler-table.cc
+++ /dev/null
@@ -1,161 +0,0 @@
-// ----------------------------------------------------------------------------
-//
-// Copyright (C) 2006-2012 Fons Adriaensen <fons@linuxaudio.org>
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-//
-// ----------------------------------------------------------------------------
-
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <math.h>
-#include <zita-resampler/resampler-table.h>
-
-
-int zita_resampler_major_version (void)
-{
- return ZITA_RESAMPLER_MAJOR_VERSION;
-}
-
-
-int zita_resampler_minor_version (void)
-{
- return ZITA_RESAMPLER_MINOR_VERSION;
-}
-
-
-static double sinc (double x)
-{
- x = fabs (x);
- if (x < 1e-6) return 1.0;
- x *= M_PI;
- return sin (x) / x;
-}
-
-
-static double wind (double x)
-{
- x = fabs (x);
- if (x >= 1.0) return 0.0f;
- x *= M_PI;
- return 0.384 + 0.500 * cos (x) + 0.116 * cos (2 * x);
-}
-
-
-
-Resampler_table *Resampler_table::_list = 0;
-Resampler_mutex Resampler_table::_mutex;
-
-
-Resampler_table::Resampler_table (double fr, unsigned int hl, unsigned int np) :
- _next (0),
- _refc (0),
- _fr (fr),
- _hl (hl),
- _np (np)
-{
- unsigned int i, j;
- double t;
- float *p;
-
- _ctab = new float [hl * (np + 1)];
- p = _ctab;
- for (j = 0; j <= np; j++)
- {
- t = (double) j / (double) np;
- for (i = 0; i < hl; i++)
- {
- p [hl - i - 1] = (float)(fr * sinc (t * fr) * wind (t / hl));
- t += 1;
- }
- p += hl;
- }
-}
-
-
-Resampler_table::~Resampler_table (void)
-{
- delete[] _ctab;
-}
-
-
-Resampler_table *Resampler_table::create (double fr, unsigned int hl, unsigned int np)
-{
- Resampler_table *P;
-
- _mutex.lock ();
- P = _list;
- while (P)
- {
- if ((fr >= P->_fr * 0.999) && (fr <= P->_fr * 1.001) && (hl == P->_hl) && (np == P->_np))
- {
- P->_refc++;
- _mutex.unlock ();
- return P;
- }
- P = P->_next;
- }
- P = new Resampler_table (fr, hl, np);
- P->_refc = 1;
- P->_next = _list;
- _list = P;
- _mutex.unlock ();
- return P;
-}
-
-
-void Resampler_table::destroy (Resampler_table *T)
-{
- Resampler_table *P, *Q;
-
- _mutex.lock ();
- if (T)
- {
- T->_refc--;
- if (T->_refc == 0)
- {
- P = _list;
- Q = 0;
- while (P)
- {
- if (P == T)
- {
- if (Q) Q->_next = T->_next;
- else _list = T->_next;
- break;
- }
- Q = P;
- P = P->_next;
- }
- delete T;
- }
- }
- _mutex.unlock ();
-}
-
-
-void Resampler_table::print_list (void)
-{
- Resampler_table *P;
-
- printf ("Resampler table\n----\n");
- for (P = _list; P; P = P->_next)
- {
- printf ("refc = %3d fr = %10.6lf hl = %4d np = %4d\n", P->_refc, P->_fr, P->_hl, P->_np);
- }
- printf ("----\n\n");
-}
-
diff --git a/dll/src/zita-resampler/libs/resampler.cc b/dll/src/zita-resampler/libs/resampler.cc
deleted file mode 100644
index 0365f90..0000000
--- a/dll/src/zita-resampler/libs/resampler.cc
+++ /dev/null
@@ -1,263 +0,0 @@
-// ----------------------------------------------------------------------------
-//
-// Copyright (C) 2006-2012 Fons Adriaensen <fons@linuxaudio.org>
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-//
-// ----------------------------------------------------------------------------
-
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <math.h>
-#include <zita-resampler/resampler.h>
-
-
-static unsigned int gcd (unsigned int a, unsigned int b)
-{
- if (a == 0) return b;
- if (b == 0) return a;
- while (1)
- {
- if (a > b)
- {
- a = a % b;
- if (a == 0) return b;
- if (a == 1) return 1;
- }
- else
- {
- b = b % a;
- if (b == 0) return a;
- if (b == 1) return 1;
- }
- }
- return 1;
-}
-
-
-Resampler::Resampler (void) :
- _table (0),
- _nchan (0),
- _buff (0)
-{
- reset ();
-}
-
-
-Resampler::~Resampler (void)
-{
- clear ();
-}
-
-
-int Resampler::setup (unsigned int fs_inp,
- unsigned int fs_out,
- unsigned int nchan,
- unsigned int hlen)
-{
- if ((hlen < 8) || (hlen > 96)) return 1;
- return setup (fs_inp, fs_out, nchan, hlen, 1.0 - 2.6 / hlen);
-}
-
-
-int Resampler::setup (unsigned int fs_inp,
- unsigned int fs_out,
- unsigned int nchan,
- unsigned int hlen,
- double frel)
-{
- unsigned int g, h, k, n, s;
- double r;
- float *B = 0;
- Resampler_table *T = 0;
-
- k = s = 0;
- if (fs_inp && fs_out && nchan)
- {
- r = (double) fs_out / (double) fs_inp;
- g = gcd (fs_out, fs_inp);
- n = fs_out / g;
- s = fs_inp / g;
- if ((16 * r >= 1) && (n <= 1000))
- {
- h = hlen;
- k = 250;
- if (r < 1)
- {
- frel *= r;
- h = (unsigned int)(ceil (h / r));
- k = (unsigned int)(ceil (k / r));
- }
- T = Resampler_table::create (frel, h, n);
- B = new float [nchan * (2 * h - 1 + k)];
- }
- }
- clear ();
- if (T)
- {
- _table = T;
- _buff = B;
- _nchan = nchan;
- _inmax = k;
- _pstep = s;
- return reset ();
- }
- else return 1;
-}
-
-
-void Resampler::clear (void)
-{
- Resampler_table::destroy (_table);
- delete[] _buff;
- _buff = 0;
- _table = 0;
- _nchan = 0;
- _inmax = 0;
- _pstep = 0;
- reset ();
-}
-
-
-double Resampler::inpdist (void) const
-{
- if (!_table) return 0;
- return (int)(_table->_hl + 1 - _nread) - (double)_phase / _table->_np;
-}
-
-
-int Resampler::inpsize (void) const
-{
- if (!_table) return 0;
- return 2 * _table->_hl;
-}
-
-
-int Resampler::reset (void)
-{
- if (!_table) return 1;
-
- inp_count = 0;
- out_count = 0;
- inp_data = 0;
- out_data = 0;
- _index = 0;
- _nread = 0;
- _nzero = 0;
- _phase = 0;
- if (_table)
- {
- _nread = 2 * _table->_hl;
- return 0;
- }
- return 1;
-}
-
-
-int Resampler::process (void)
-{
- unsigned int hl, ph, np, dp, in, nr, nz, i, n, c;
- float *p1, *p2;
-
- if (!_table) return 1;
-
- hl = _table->_hl;
- np = _table->_np;
- dp = _pstep;
- in = _index;
- nr = _nread;
- ph = _phase;
- nz = _nzero;
- n = (2 * hl - nr) * _nchan;
- p1 = _buff + in * _nchan;
- p2 = p1 + n;
-
- while (out_count)
- {
- if (nr)
- {
- if (inp_count == 0) break;
- if (inp_data)
- {
- for (c = 0; c < _nchan; c++) p2 [c] = inp_data [c];
- inp_data += _nchan;
- nz = 0;
- }
- else
- {
- for (c = 0; c < _nchan; c++) p2 [c] = 0;
- if (nz < 2 * hl) nz++;
- }
- nr--;
- p2 += _nchan;
- inp_count--;
- }
- else
- {
- if (out_data)
- {
- if (nz < 2 * hl)
- {
- float *c1 = _table->_ctab + hl * ph;
- float *c2 = _table->_ctab + hl * (np - ph);
- for (c = 0; c < _nchan; c++)
- {
- float *q1 = p1 + c;
- float *q2 = p2 + c;
- float s = 1e-20f;
- for (i = 0; i < hl; i++)
- {
- q2 -= _nchan;
- s += *q1 * c1 [i] + *q2 * c2 [i];
- q1 += _nchan;
- }
- *out_data++ = s - 1e-20f;
- }
- }
- else
- {
- for (c = 0; c < _nchan; c++) *out_data++ = 0;
- }
- }
- out_count--;
-
- ph += dp;
- if (ph >= np)
- {
- nr = ph / np;
- ph -= nr * np;
- in += nr;
- p1 += nr * _nchan;;
- if (in >= _inmax)
- {
- n = (2 * hl - nr) * _nchan;
- memcpy (_buff, p1, n * sizeof (float));
- in = 0;
- p1 = _buff;
- p2 = p1 + n;
- }
- }
- }
- }
- _index = in;
- _nread = nr;
- _phase = ph;
- _nzero = nz;
-
- return 0;
-}
-
-
diff --git a/dll/src/zita-resampler/libs/vresampler.cc b/dll/src/zita-resampler/libs/vresampler.cc
deleted file mode 100644
index 50bf062..0000000
--- a/dll/src/zita-resampler/libs/vresampler.cc
+++ /dev/null
@@ -1,269 +0,0 @@
-// ----------------------------------------------------------------------------
-//
-// Copyright (C) 2006-2012 Fons Adriaensen <fons@linuxaudio.org>
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-//
-// ----------------------------------------------------------------------------
-
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <math.h>
-#include <zita-resampler/vresampler.h>
-
-
-VResampler::VResampler (void) :
- _table (0),
- _nchan (0),
- _buff (0),
- _c1 (0),
- _c2 (0)
-{
- reset ();
-}
-
-
-VResampler::~VResampler (void)
-{
- clear ();
-}
-
-
-int VResampler::setup (double ratio,
- unsigned int nchan,
- unsigned int hlen)
-{
- if ((hlen < 8) || (hlen > 96) || (16 * ratio < 1) || (ratio > 64)) return 1;
- return setup (ratio, nchan, hlen, 1.0 - 2.6 / hlen);
-}
-
-
-int VResampler::setup (double ratio,
- unsigned int nchan,
- unsigned int hlen,
- double frel)
-{
- unsigned int h, k, n;
- double s;
- Resampler_table *T = 0;
-
- if (! nchan) return 1;
- n = NPHASE;
- s = n / ratio;
- h = hlen;
- k = 250;
- if (ratio < 1)
- {
- frel *= ratio;
- h = (unsigned int)(ceil (h / ratio));
- k = (unsigned int)(ceil (k / ratio));
- }
- T = Resampler_table::create (frel, h, n);
- clear ();
- if (T)
- {
- _table = T;
- _buff = new float [nchan * (2 * h - 1 + k)];
- _c1 = new float [2 * h];
- _c2 = new float [2 * h];
- _nchan = nchan;
- _inmax = k;
- _ratio = ratio;
- _pstep = s;
- _qstep = s;
- _wstep = 1;
- return reset ();
- }
- else return 1;
-}
-
-
-void VResampler::clear (void)
-{
- Resampler_table::destroy (_table);
- delete[] _buff;
- delete[] _c1;
- delete[] _c2;
- _buff = 0;
- _c1 = 0;
- _c2 = 0;
- _table = 0;
- _nchan = 0;
- _inmax = 0;
- _pstep = 0;
- _qstep = 0;
- _wstep = 1;
- reset ();
-}
-
-
-void VResampler::set_rrfilt (double t)
-{
- if (!_table) return;
- _wstep = (t < 1) ? 1 : 1 - exp (-1 / t);
-}
-
-
-void VResampler::set_rratio (double r)
-{
- if (!_table) return;
- if (r > 16.0) r = 16.0;
- if (r < 0.95) r = 0.95;
- _qstep = _table->_np / (_ratio * r);
-}
-
-
-double VResampler::inpdist (void) const
-{
- if (!_table) return 0;
- return (int)(_table->_hl + 1 - _nread) - _phase / _table->_np;
-}
-
-
-int VResampler::inpsize (void) const
-{
- if (!_table) return 0;
- return 2 * _table->_hl;
-}
-
-
-int VResampler::reset (void)
-{
- if (!_table) return 1;
-
- inp_count = 0;
- out_count = 0;
- inp_data = 0;
- out_data = 0;
- _index = 0;
- _phase = 0;
- _nread = 0;
- _nzero = 0;
- if (_table)
- {
- _nread = 2 * _table->_hl;
- return 0;
- }
- return 1;
-}
-
-
-int VResampler::process (void)
-{
- unsigned int k, np, in, nr, n, c;
- int i, hl, nz;
- double ph, dp, dd;
- float a, b, *p1, *p2, *q1, *q2;
-
- if (!_table) return 1;
-
- hl = _table->_hl;
- np = _table->_np;
- in = _index;
- nr = _nread;
- nz = _nzero;
- ph = _phase;
- dp = _pstep;
- n = (2 * hl - nr) * _nchan;
- p1 = _buff + in * _nchan;
- p2 = p1 + n;
-
- while (out_count)
- {
- if (nr)
- {
- if (inp_count == 0) break;
- if (inp_data)
- {
- for (c = 0; c < _nchan; c++) p2 [c] = inp_data [c];
- inp_data += _nchan;
- nz = 0;
- }
- else
- {
- for (c = 0; c < _nchan; c++) p2 [c] = 0;
- if (nz < 2 * hl) nz++;
- }
- nr--;
- p2 += _nchan;
- inp_count--;
- }
- else
- {
- if (out_data)
- {
- if (nz < 2 * hl)
- {
- k = (unsigned int) ph;
- b = (float)(ph - k);
- a = 1.0f - b;
- q1 = _table->_ctab + hl * k;
- q2 = _table->_ctab + hl * (np - k);
- for (i = 0; i < hl; i++)
- {
- _c1 [i] = a * q1 [i] + b * q1 [i + hl];
- _c2 [i] = a * q2 [i] + b * q2 [i - hl];
- }
- for (c = 0; c < _nchan; c++)
- {
- q1 = p1 + c;
- q2 = p2 + c;
- a = 1e-25f;
- for (i = 0; i < hl; i++)
- {
- q2 -= _nchan;
- a += *q1 * _c1 [i] + *q2 * _c2 [i];
- q1 += _nchan;
- }
- *out_data++ = a - 1e-25f;
- }
- }
- else
- {
- for (c = 0; c < _nchan; c++) *out_data++ = 0;
- }
- }
- out_count--;
-
- dd = _qstep - dp;
- if (fabs (dd) < 1e-30) dp = _qstep;
- else dp += _wstep * dd;
- ph += dp;
- if (ph >= np)
- {
- nr = (unsigned int) floor( ph / np);
- ph -= nr * np;;
- in += nr;
- p1 += nr * _nchan;;
- if (in >= _inmax)
- {
- n = (2 * hl - nr) * _nchan;
- memcpy (_buff, p1, n * sizeof (float));
- in = 0;
- p1 = _buff;
- p2 = p1 + n;
- }
- }
- }
- }
- _index = in;
- _nread = nr;
- _phase = ph;
- _pstep = dp;
- _nzero = nz;
-
- return 0;
-}
diff --git a/dll/src/zita-resampler/libs/zita-resampler/resampler-table.h b/dll/src/zita-resampler/libs/zita-resampler/resampler-table.h
deleted file mode 100644
index ba42649..0000000
--- a/dll/src/zita-resampler/libs/zita-resampler/resampler-table.h
+++ /dev/null
@@ -1,86 +0,0 @@
-// ----------------------------------------------------------------------------
-//
-// Copyright (C) 2006-2012 Fons Adriaensen <fons@linuxaudio.org>
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-//
-// ----------------------------------------------------------------------------
-
-
-#ifndef __RESAMPLER_TABLE_H
-#define __RESAMPLER_TABLE_H
-
-
-//#include <pthread.h>
-#include <mutex>
-
-
-#define ZITA_RESAMPLER_MAJOR_VERSION 1
-#define ZITA_RESAMPLER_MINOR_VERSION 3
-
-
-extern int zita_resampler_major_version (void);
-extern int zita_resampler_minor_version (void);
-
-
-class Resampler_mutex
-{
-private:
-
- friend class Resampler_table;
-
- //Resampler_mutex (void) { pthread_mutex_init (&_mutex, 0); }
- //~Resampler_mutex (void) { pthread_mutex_destroy (&_mutex); }
- //void lock (void) { pthread_mutex_lock (&_mutex); }
- //void unlock (void) { pthread_mutex_unlock (&_mutex); }
- Resampler_mutex (void) { }
- ~Resampler_mutex (void) { }
- void lock (void) { _mutex.lock(); }
- void unlock (void) { _mutex.unlock(); }
-
- //pthread_mutex_t _mutex;
- std::mutex _mutex;
-};
-
-
-class Resampler_table
-{
-public:
-
- static void print_list (void);
-
-private:
-
- Resampler_table (double fr, unsigned int hl, unsigned int np);
- ~Resampler_table (void);
-
- friend class Resampler;
- friend class VResampler;
-
- Resampler_table *_next;
- unsigned int _refc;
- float *_ctab;
- double _fr;
- unsigned int _hl;
- unsigned int _np;
-
- static Resampler_table *create (double fr, unsigned int hl, unsigned int np);
- static void destroy (Resampler_table *T);
-
- static Resampler_table *_list;
- static Resampler_mutex _mutex;
-};
-
-
-#endif
diff --git a/dll/src/zita-resampler/libs/zita-resampler/resampler.h b/dll/src/zita-resampler/libs/zita-resampler/resampler.h
deleted file mode 100644
index 6e8699c..0000000
--- a/dll/src/zita-resampler/libs/zita-resampler/resampler.h
+++ /dev/null
@@ -1,76 +0,0 @@
-// ----------------------------------------------------------------------------
-//
-// Copyright (C) 2006-2012 Fons Adriaensen <fons@linuxaudio.org>
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-//
-// ----------------------------------------------------------------------------
-
-
-#ifndef __RESAMPLER_H
-#define __RESAMPLER_H
-
-
-#include <zita-resampler/resampler-table.h>
-
-
-class Resampler
-{
-public:
-
- Resampler (void);
- ~Resampler (void);
-
- int setup (unsigned int fs_inp,
- unsigned int fs_out,
- unsigned int nchan,
- unsigned int hlen);
-
- int setup (unsigned int fs_inp,
- unsigned int fs_out,
- unsigned int nchan,
- unsigned int hlen,
- double frel);
-
- void clear (void);
- int reset (void);
- int nchan (void) const { return _nchan; }
- int filtlen (void) const { return inpsize (); } // Deprecated
- int inpsize (void) const;
- double inpdist (void) const;
- int process (void);
-
- unsigned int inp_count;
- unsigned int out_count;
- float *inp_data;
- float *out_data;
- void *inp_list;
- void *out_list;
-
-private:
-
- Resampler_table *_table;
- unsigned int _nchan;
- unsigned int _inmax;
- unsigned int _index;
- unsigned int _nread;
- unsigned int _nzero;
- unsigned int _phase;
- unsigned int _pstep;
- float *_buff;
- void *_dummy [8];
-};
-
-
-#endif
diff --git a/dll/src/zita-resampler/libs/zita-resampler/vresampler.h b/dll/src/zita-resampler/libs/zita-resampler/vresampler.h
deleted file mode 100644
index 9049043..0000000
--- a/dll/src/zita-resampler/libs/zita-resampler/vresampler.h
+++ /dev/null
@@ -1,83 +0,0 @@
-// ----------------------------------------------------------------------------
-//
-// Copyright (C) 2006-2012 Fons Adriaensen <fons@linuxaudio.org>
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-//
-// ----------------------------------------------------------------------------
-
-
-#ifndef __VRESAMPLER_H
-#define __VRESAMPLER_H
-
-
-#include <zita-resampler/resampler-table.h>
-
-
-class VResampler
-{
-public:
-
- VResampler (void);
- ~VResampler (void);
-
- int setup (double ratio,
- unsigned int nchan,
- unsigned int hlen);
-
- int setup (double ratio,
- unsigned int nchan,
- unsigned int hlen,
- double frel);
-
- void clear (void);
- int reset (void);
- int nchan (void) const { return _nchan; }
- int inpsize (void) const;
- double inpdist (void) const;
- int process (void);
-
- void set_rrfilt (double t);
- void set_rratio (double r);
-
- unsigned int inp_count;
- unsigned int out_count;
- float *inp_data;
- float *out_data;
- void *inp_list;
- void *out_list;
-
-private:
-
- enum { NPHASE = 256 };
-
- Resampler_table *_table;
- unsigned int _nchan;
- unsigned int _inmax;
- unsigned int _index;
- unsigned int _nread;
- unsigned int _nzero;
- double _ratio;
- double _phase;
- double _pstep;
- double _qstep;
- double _wstep;
- float *_buff;
- float *_c1;
- float *_c2;
- void *_dummy [8];
-};
-
-
-#endif