diff --git a/build/unix/Makefile.am b/build/unix/Makefile.am index e311ca1..041aa25 100644 --- a/build/unix/Makefile.am +++ b/build/unix/Makefile.am @@ -52,13 +52,7 @@ AM_LDFLAGS = $(PLUGINLDFLAGS) lib_LTLIBRARIES = libfmtconv.la -libfmtconv_la_SOURCES = \ - ../../src/avstp.h \ - ../../src/AvstpWrapper.cpp \ - ../../src/AvstpWrapper.h \ - ../../src/main.cpp \ - ../../src/types.h \ - ../../src/VapourSynth.h \ +commonsrc = \ ../../src/conc/AioAdd.h \ ../../src/conc/AioAdd.hpp \ ../../src/conc/AioMax.h \ @@ -100,31 +94,6 @@ libfmtconv_la_SOURCES = \ ../../src/ffft/FFTReal.hpp \ ../../src/ffft/OscSinCos.h \ ../../src/ffft/OscSinCos.hpp \ - ../../src/fmtc/Bitdepth.cpp \ - ../../src/fmtc/Bitdepth.h \ - ../../src/fmtc/Convert.cpp \ - ../../src/fmtc/Convert.h \ - ../../src/fmtc/ConvStep.cpp \ - ../../src/fmtc/ConvStep.h \ - ../../src/fmtc/fnc.cpp \ - ../../src/fmtc/fnc.h \ - ../../src/fmtc/Matrix2020CL.cpp \ - ../../src/fmtc/Matrix2020CL.h \ - ../../src/fmtc/Matrix.cpp \ - ../../src/fmtc/Matrix.h \ - ../../src/fmtc/NativeToStack16.cpp \ - ../../src/fmtc/NativeToStack16.h \ - ../../src/fmtc/Primaries.cpp \ - ../../src/fmtc/Primaries.h \ - ../../src/fmtc/Resample.cpp \ - ../../src/fmtc/Resample.h \ - ../../src/fmtc/SplFmtUtl.h \ - ../../src/fmtc/SplFmtUtl.hpp \ - ../../src/fmtc/Stack16ToNative.cpp \ - ../../src/fmtc/Stack16ToNative.h \ - ../../src/fmtc/Transfer.cpp \ - ../../src/fmtc/Transfer.h \ - ../../src/fmtc/version.h \ ../../src/fmtcl/ArrayMultiType.cpp \ ../../src/fmtcl/ArrayMultiType.h \ ../../src/fmtcl/ArrayMultiType.hpp \ @@ -167,6 +136,8 @@ libfmtconv_la_SOURCES = \ ../../src/fmtcl/ContFirSpline64.h \ ../../src/fmtcl/ContFirSpline.cpp \ ../../src/fmtcl/ContFirSpline.h \ + ../../src/fmtcl/CpuOptBase.cpp \ + ../../src/fmtcl/CpuOptBase.h \ ../../src/fmtcl/DiscreteFirCustom.cpp \ ../../src/fmtcl/DiscreteFirCustom.h \ ../../src/fmtcl/DiscreteFirInterface.cpp \ @@ -180,7 +151,7 @@ libfmtconv_la_SOURCES = \ ../../src/fmtcl/ErrDifBufFactory.h \ ../../src/fmtcl/FilterResize.cpp \ ../../src/fmtcl/FilterResize.h \ - ../../src/fmtcl/fnc.cpp \ + ../../src/fmtcl/fnc_fmtcl.cpp \ ../../src/fmtcl/fnc.h \ ../../src/fmtcl/InterlacingType.h \ ../../src/fmtcl/KernelData.cpp \ @@ -283,11 +254,42 @@ libfmtconv_la_SOURCES = \ ../../src/fstb/fnc.hpp \ ../../src/fstb/SingleObj.h \ ../../src/fstb/SingleObj.hpp \ - ../../src/vsutl/CpuOpt.cpp \ - ../../src/vsutl/CpuOpt.h \ + ../../src/avstp.h \ + ../../src/AvstpWrapper.cpp \ + ../../src/AvstpWrapper.h + +libfmtconv_la_SOURCES = $(commonsrc) \ + ../../src/main-vs.cpp \ + ../../src/types.h \ + ../../src/VapourSynth.h \ + ../../src/fmtc/Bitdepth.cpp \ + ../../src/fmtc/Bitdepth.h \ + ../../src/fmtc/Convert.cpp \ + ../../src/fmtc/Convert.h \ + ../../src/fmtc/ConvStep.cpp \ + ../../src/fmtc/ConvStep.h \ + ../../src/fmtc/CpuOpt.cpp \ + ../../src/fmtc/CpuOpt.h \ + ../../src/fmtc/fnc_fmtc.cpp \ + ../../src/fmtc/fnc.h \ + ../../src/fmtc/Matrix2020CL.cpp \ + ../../src/fmtc/Matrix2020CL.h \ + ../../src/fmtc/Matrix.cpp \ + ../../src/fmtc/Matrix.h \ + ../../src/fmtc/NativeToStack16.cpp \ + ../../src/fmtc/NativeToStack16.h \ + ../../src/fmtc/Primaries.cpp \ + ../../src/fmtc/Primaries.h \ + ../../src/fmtc/Resample.cpp \ + ../../src/fmtc/Resample.h \ + ../../src/fmtc/Stack16ToNative.cpp \ + ../../src/fmtc/Stack16ToNative.h \ + ../../src/fmtc/Transfer.cpp \ + ../../src/fmtc/Transfer.h \ + ../../src/fmtc/version.h \ ../../src/vsutl/FilterBase.cpp \ ../../src/vsutl/FilterBase.h \ - ../../src/vsutl/fnc.cpp \ + ../../src/vsutl/fnc_vsutl.cpp \ ../../src/vsutl/fnc.h \ ../../src/vsutl/FrameRefSPtr.h \ ../../src/vsutl/FuncRefSPtr.h \ @@ -307,6 +309,7 @@ libfmtconv_la_LIBADD = noinst_LTLIBRARIES = + if X86 libsse2_la_SOURCES = \ @@ -318,20 +321,24 @@ libsse2_la_CXXFLAGS = $(AM_CXXFLAGS) -msse2 libfmtconv_la_LIBADD += libsse2.la noinst_LTLIBRARIES += libsse2.la -libavx_la_SOURCES = \ +commonsrcavx = \ ../../src/fmtcl/MatrixProc_avx.cpp +libavx_la_SOURCES = $(commonsrcavx) + libavx_la_CXXFLAGS = $(AM_CXXFLAGS) -mavx libfmtconv_la_LIBADD += libavx.la noinst_LTLIBRARIES += libavx.la -libavx2_la_SOURCES = \ +commonsrcavx2 = \ ../../src/fmtcl/BitBltConv_avx2.cpp \ ../../src/fmtcl/MatrixProc_avx2.cpp \ ../../src/fmtcl/ProxyRwAvx2.h \ ../../src/fmtcl/ProxyRwAvx2.hpp \ ../../src/fmtcl/Scaler_avx2.cpp \ - ../../src/fmtcl/TransLut_avx2.cpp \ + ../../src/fmtcl/TransLut_avx2.cpp + +libavx2_la_SOURCES = $(commonsrcavx2) \ ../../src/fstb/ToolsAvx2.cpp \ ../../src/fstb/ToolsAvx2.h \ ../../src/fstb/ToolsAvx2.hpp diff --git a/build/win/common/common.vcxproj b/build/win/common/common.vcxproj new file mode 100644 index 0000000..905263e --- /dev/null +++ b/build/win/common/common.vcxproj @@ -0,0 +1,365 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {E3709730-4FD3-4771-844E-719AAC38AA6C} + common + Win32Proj + + + + + + + StaticLibrary + Unicode + + + true + false + + + false + true + + + + + + + + + + true + + + false + + + $(ProjectDir)$(Configuration)$(Platform)\ + $(ProjectDir)$(Configuration)$(Platform)\ + AllRules.ruleset + + + + + + Disabled + ProgramDatabase + _DEBUG;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + true + + + true + + + + + MaxSpeed + AnySuitable + true + Speed + NDEBUG;%(PreprocessorDefinitions) + MultiThreaded + true + + + true + true + true + + + + + StreamingSIMDExtensions2 + true + + + MachineX86 + + + + + X64 + + + MachineX64 + + + + + + + ../../../src;%(AdditionalIncludeDirectories) + WIN32;_LIB;%(PreprocessorDefinitions) + Level4 + 4127 + ProgramDatabase + true + true + true + /Zc:__cplusplus %(AdditionalOptions) + + + $(OutDir)$(ProjectName).lib + + + Ws2_32.lib;%(AdditionalDependencies) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AdvancedVectorExtensions2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AdvancedVectorExtensions + + + AdvancedVectorExtensions2 + + + + + + + + + + + + AdvancedVectorExtensions2 + + + + AdvancedVectorExtensions2 + + + + + + + + + + + + + + + + + + + + AdvancedVectorExtensions2 + + + + + + + + + \ No newline at end of file diff --git a/build/win/common/common.vcxproj.filters b/build/win/common/common.vcxproj.filters new file mode 100644 index 0000000..628de49 --- /dev/null +++ b/build/win/common/common.vcxproj.filters @@ -0,0 +1,662 @@ + + + + + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fstb + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fstb + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fstb + + + fstb + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + + + + + + conc + + + conc + + + conc + + + conc + + + conc + + + conc + + + fstb + + + fstb + + + fstb + + + fstb + + + fmtcl + + + fmtcl + + + conc + + + conc + + + conc + + + conc + + + conc + + + conc + + + conc + + + conc + + + conc + + + conc + + + fmtcl + + + conc + + + conc + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fstb + + + conc + + + ffft + + + fstb + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + ffft + + + ffft + + + fmtcl + + + conc + + + fstb + + + fmtcl + + + conc + + + fstb + + + fmtcl + + + conc + + + conc + + + conc + + + conc + + + conc + + + conc + + + conc + + + conc + + + conc + + + conc + + + conc + + + conc + + + conc + + + ffft + + + ffft + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fstb + + + fstb + + + fstb + + + fstb + + + fstb + + + fstb + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + fmtcl + + + + + {0605c912-f3f0-463c-aa50-470ac213eb24} + + + {96513da9-cd84-4cfd-a5bb-03de0932ccfd} + + + {789213cb-2dfe-4b90-9270-48701d27924b} + + + {aa46c2c1-c035-4927-8d08-e824d5a7daca} + + + \ No newline at end of file diff --git a/build/win/fmtcavs/fmtcavs.vcxproj b/build/win/fmtcavs/fmtcavs.vcxproj new file mode 100644 index 0000000..39c7f28 --- /dev/null +++ b/build/win/fmtcavs/fmtcavs.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {D578C52A-7079-479B-A2AD-17C07E9EE505} + fmtcavs + Win32Proj + + + + + + + DynamicLibrary + Unicode + + + true + false + + + false + true + + + + + + + + + + true + + + false + + + $(ProjectDir)$(Configuration)$(Platform)\ + $(ProjectDir)$(Configuration)$(Platform)\ + AllRules.ruleset + + + + + + Disabled + ProgramDatabase + _DEBUG;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + true + + + true + + + + + MaxSpeed + AnySuitable + true + Speed + NDEBUG;%(PreprocessorDefinitions) + MultiThreaded + true + + + true + true + true + + + + + StreamingSIMDExtensions2 + true + + + MachineX86 + + + + + X64 + + + MachineX64 + + + + + + + ../../../src;%(AdditionalIncludeDirectories) + WIN32;_WINDOWS;_USRDLL;FMTCONV_EXPORTS;%(PreprocessorDefinitions) + Level4 + 4127 + ProgramDatabase + true + true + true + /Zc:__cplusplus %(AdditionalOptions) + + + true + Windows + common.lib;%(AdditionalDependencies) + ..\common\$(Configuration)$(Platform);%(AdditionalLibraryDirectories) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/build/win/fmtcavs/fmtcavs.vcxproj.filters b/build/win/fmtcavs/fmtcavs.vcxproj.filters new file mode 100644 index 0000000..517c6d5 --- /dev/null +++ b/build/win/fmtcavs/fmtcavs.vcxproj.filters @@ -0,0 +1,125 @@ + + + + + {6c93aa52-048b-4d91-804f-deae91f0a7b5} + + + {7a1aeee0-aae6-4fff-ae20-09cb2f01a69f} + + + {ccc042a6-d386-4b51-83db-1ebd9da95b72} + + + + + avs + + + avs + + + avs + + + avs + + + avs + + + avs + + + avs + + + avs + + + avs + + + fmtcavs + + + avsutl + + + avsutl + + + avsutl + + + + avsutl + + + avsutl + + + fmtcavs + + + fmtcavs + + + fmtcavs + + + fmtcavs + + + fmtcavs + + + avsutl + + + fmtcavs + + + avsutl + + + avsutl + + + + + + fmtcavs + + + avsutl + + + avsutl + + + avsutl + + + fmtcavs + + + fmtcavs + + + fmtcavs + + + fmtcavs + + + avsutl + + + fmtcavs + + + avsutl + + + \ No newline at end of file diff --git a/build/win/fmtconv.sln b/build/win/fmtconv.sln index 3bb1fa7..e7dd6b1 100644 --- a/build/win/fmtconv.sln +++ b/build/win/fmtconv.sln @@ -1,9 +1,25 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.31101.0 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29613.14 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fmtconv", "fmtconv.vcxproj", "{82B962E5-3DE3-4933-8B0F-CDA03FAADCB2}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fmtconv", "fmtconv\fmtconv.vcxproj", "{82B962E5-3DE3-4933-8B0F-CDA03FAADCB2}" + ProjectSection(ProjectDependencies) = postProject + {E3709730-4FD3-4771-844E-719AAC38AA6C} = {E3709730-4FD3-4771-844E-719AAC38AA6C} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "common", "common\common.vcxproj", "{E3709730-4FD3-4771-844E-719AAC38AA6C}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8EB6F259-071E-497F-AA1B-8D88A993671A}" + ProjectSection(SolutionItems) = preProject + ..\unix\configure.ac = ..\unix\configure.ac + ..\unix\Makefile.am = ..\unix\Makefile.am + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fmtcavs", "fmtcavs\fmtcavs.vcxproj", "{D578C52A-7079-479B-A2AD-17C07E9EE505}" + ProjectSection(ProjectDependencies) = postProject + {E3709730-4FD3-4771-844E-719AAC38AA6C} = {E3709730-4FD3-4771-844E-719AAC38AA6C} + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -25,8 +41,31 @@ Global {82B962E5-3DE3-4933-8B0F-CDA03FAADCB2}.Release|Win32.Build.0 = Release|Win32 {82B962E5-3DE3-4933-8B0F-CDA03FAADCB2}.Release|x64.ActiveCfg = Release|x64 {82B962E5-3DE3-4933-8B0F-CDA03FAADCB2}.Release|x64.Build.0 = Release|x64 + {E3709730-4FD3-4771-844E-719AAC38AA6C}.Debug|ARM.ActiveCfg = Debug|Win32 + {E3709730-4FD3-4771-844E-719AAC38AA6C}.Debug|Win32.ActiveCfg = Debug|Win32 + {E3709730-4FD3-4771-844E-719AAC38AA6C}.Debug|Win32.Build.0 = Debug|Win32 + {E3709730-4FD3-4771-844E-719AAC38AA6C}.Debug|x64.ActiveCfg = Debug|x64 + {E3709730-4FD3-4771-844E-719AAC38AA6C}.Debug|x64.Build.0 = Debug|x64 + {E3709730-4FD3-4771-844E-719AAC38AA6C}.Release|ARM.ActiveCfg = Release|Win32 + {E3709730-4FD3-4771-844E-719AAC38AA6C}.Release|Win32.ActiveCfg = Release|Win32 + {E3709730-4FD3-4771-844E-719AAC38AA6C}.Release|Win32.Build.0 = Release|Win32 + {E3709730-4FD3-4771-844E-719AAC38AA6C}.Release|x64.ActiveCfg = Release|x64 + {E3709730-4FD3-4771-844E-719AAC38AA6C}.Release|x64.Build.0 = Release|x64 + {D578C52A-7079-479B-A2AD-17C07E9EE505}.Debug|ARM.ActiveCfg = Debug|Win32 + {D578C52A-7079-479B-A2AD-17C07E9EE505}.Debug|Win32.ActiveCfg = Debug|Win32 + {D578C52A-7079-479B-A2AD-17C07E9EE505}.Debug|Win32.Build.0 = Debug|Win32 + {D578C52A-7079-479B-A2AD-17C07E9EE505}.Debug|x64.ActiveCfg = Debug|x64 + {D578C52A-7079-479B-A2AD-17C07E9EE505}.Debug|x64.Build.0 = Debug|x64 + {D578C52A-7079-479B-A2AD-17C07E9EE505}.Release|ARM.ActiveCfg = Release|Win32 + {D578C52A-7079-479B-A2AD-17C07E9EE505}.Release|Win32.ActiveCfg = Release|Win32 + {D578C52A-7079-479B-A2AD-17C07E9EE505}.Release|Win32.Build.0 = Release|Win32 + {D578C52A-7079-479B-A2AD-17C07E9EE505}.Release|x64.ActiveCfg = Release|x64 + {D578C52A-7079-479B-A2AD-17C07E9EE505}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {D79DED9A-5DF1-4F26-AE1E-6A2BB4C64FE2} + EndGlobalSection EndGlobal diff --git a/build/win/fmtconv.vcxproj b/build/win/fmtconv.vcxproj deleted file mode 100644 index c8f1bed..0000000 --- a/build/win/fmtconv.vcxproj +++ /dev/null @@ -1,416 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {82B962E5-3DE3-4933-8B0F-CDA03FAADCB2} - fmtconv - Win32Proj - - - - - - - DynamicLibrary - Unicode - - - true - false - - - false - true - - - - - - - - - - true - - - false - - - $(ProjectDir)$(Configuration)$(Platform)\ - $(ProjectDir)$(Configuration)$(Platform)\ - AllRules.ruleset - - - - - - Disabled - _DEBUG;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebug - true - - - true - - - - - MaxSpeed - AnySuitable - true - Speed - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - true - - - true - true - true - - - - - StreamingSIMDExtensions2 - true - - - MachineX86 - - - - - X64 - - - MachineX64 - - - - - ../../src;%(AdditionalIncludeDirectories) - WIN32;_WINDOWS;_USRDLL;FMTCONV_EXPORTS;%(PreprocessorDefinitions) - - - Level4 - 4127 - ProgramDatabase - true - true - /Zc:__cplusplus %(AdditionalOptions) - - - true - Windows - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - AdvancedVectorExtensions2 - - - - - - - - - - - - - - - - - - - - - - - - - $(IntDir)%(Filename)2.obj - $(IntDir)%(Filename)2.xdc - - - - - - AdvancedVectorExtensions - - - AdvancedVectorExtensions2 - - - - - - - - - - - - AdvancedVectorExtensions2 - - - - AdvancedVectorExtensions2 - - - - - - - - - - - - - - - - - - - - - $(IntDir)%(Filename)3.obj - $(IntDir)%(Filename)3.xdc - - - - - - - - - - - AdvancedVectorExtensions2 - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/build/win/fmtconv.vcxproj.filters b/build/win/fmtconv.vcxproj.filters deleted file mode 100644 index 1bf331d..0000000 --- a/build/win/fmtconv.vcxproj.filters +++ /dev/null @@ -1,797 +0,0 @@ - - - - - {d1d807c2-3439-4dee-ad19-f29504e4be29} - - - {a51f5b8a-dc58-499b-89f1-eaa79698ba55} - - - {e3fd3153-7ca0-4f35-b071-490d7dc8268d} - - - {2d0f371a-a37f-44d9-b69d-be62d7b3a125} - - - {54a5329c-ba35-44c4-b45a-15eab4d0fb39} - - - {9be66ec0-f71c-4686-abdd-33b72e9dfc27} - - - - - fmtc - - - fmtc - - - fmtc - - - fmtc - - - fmtc - - - fmtc - - - vsutl - - - vsutl - - - vsutl - - - vsutl - - - vsutl - - - vsutl - - - vsutl - - - vsutl - - - vsutl - - - vsutl - - - vsutl - - - conc - - - conc - - - conc - - - conc - - - conc - - - conc - - - conc - - - conc - - - conc - - - conc - - - conc - - - conc - - - conc - - - conc - - - conc - - - conc - - - conc - - - conc - - - conc - - - conc - - - conc - - - conc - - - conc - - - conc - - - conc - - - conc - - - conc - - - conc - - - conc - - - conc - - - conc - - - conc - - - conc - - - conc - - - ffft - - - ffft - - - ffft - - - ffft - - - ffft - - - fstb - - - fstb - - - fstb - - - fstb - - - fstb - - - fstb - - - fstb - - - - - - - fmtc - - - fmtc - - - fmtc - - - fmtc - - - fmtc - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fstb - - - fstb - - - fstb - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtc - - - fmtcl - - - vsutl - - - fmtcl - - - fmtcl - - - vsutl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtc - - - fmtcl - - - fstb - - - fstb - - - fmtcl - - - fmtcl - - - fmtcl - - - fstb - - - fstb - - - fmtc - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - - - fmtc - - - fmtc - - - fmtc - - - fmtc - - - fmtc - - - vsutl - - - vsutl - - - vsutl - - - vsutl - - - fstb - - - - - - fmtc - - - fmtc - - - fmtc - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fstb - - - fstb - - - fstb - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtc - - - vsutl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtc - - - fmtcl - - - fmtc - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - fmtcl - - - - - - - \ No newline at end of file diff --git a/build/win/fmtconv/fmtconv.vcxproj b/build/win/fmtconv/fmtconv.vcxproj new file mode 100644 index 0000000..1dc800c --- /dev/null +++ b/build/win/fmtconv/fmtconv.vcxproj @@ -0,0 +1,179 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {82B962E5-3DE3-4933-8B0F-CDA03FAADCB2} + fmtconv + Win32Proj + + + + + + + DynamicLibrary + Unicode + + + true + false + + + false + true + + + + + + + + + + true + + + false + + + $(ProjectDir)$(Configuration)$(Platform)\ + $(ProjectDir)$(Configuration)$(Platform)\ + AllRules.ruleset + + + + + + Disabled + ProgramDatabase + _DEBUG;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + true + + + true + + + + + MaxSpeed + AnySuitable + true + Speed + NDEBUG;%(PreprocessorDefinitions) + MultiThreaded + true + + + true + true + true + + + + + StreamingSIMDExtensions2 + true + + + MachineX86 + + + + + X64 + + + MachineX64 + + + + + + + ../../../src;%(AdditionalIncludeDirectories) + WIN32;_WINDOWS;_USRDLL;FMTCONV_EXPORTS;%(PreprocessorDefinitions) + Level4 + 4127 + ProgramDatabase + true + true + true + /Zc:__cplusplus %(AdditionalOptions) + + + true + Windows + common.lib;%(AdditionalDependencies) + ..\common\$(Configuration)$(Platform);%(AdditionalLibraryDirectories) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/build/win/fmtconv/fmtconv.vcxproj.filters b/build/win/fmtconv/fmtconv.vcxproj.filters new file mode 100644 index 0000000..b0a862b --- /dev/null +++ b/build/win/fmtconv/fmtconv.vcxproj.filters @@ -0,0 +1,140 @@ + + + + + {d1d807c2-3439-4dee-ad19-f29504e4be29} + + + {a51f5b8a-dc58-499b-89f1-eaa79698ba55} + + + + + fmtc + + + fmtc + + + fmtc + + + fmtc + + + fmtc + + + fmtc + + + vsutl + + + vsutl + + + vsutl + + + vsutl + + + vsutl + + + vsutl + + + vsutl + + + vsutl + + + vsutl + + + vsutl + + + vsutl + + + + fmtc + + + fmtc + + + fmtc + + + fmtc + + + vsutl + + + fmtc + + + fmtc + + + fmtc + + + + + fmtc + + + fmtc + + + fmtc + + + fmtc + + + fmtc + + + vsutl + + + vsutl + + + vsutl + + + fmtc + + + fmtc + + + fmtc + + + fmtc + + + fmtc + + + + vsutl + + + fmtc + + + fmtc + + + \ No newline at end of file diff --git a/doc/fmtconv.html b/doc/fmtconv.html index 2a0b9fe..b1159fc 100644 --- a/doc/fmtconv.html +++ b/doc/fmtconv.html @@ -232,68 +232,24 @@

GNU/Linux and other Unix-like systems

You can add some options to the configure command:

-

GCC

- -

Here are the steps needed to compile without the autotools. -From the src directory, compile and link all these files with -g++:

- -
main.cpp
-AvstpWrapper.cpp
-fmtc/*.cpp
-fmtcl/*.cpp
-fstb/*.cpp
-vsutl/*.cpp
- -

Add AvstpFinder.cpp on Windows. -Use the following options (on a single line):

- -
-std=c++14 -shared -fabi-version=6 -msse2 -mcx16 -O3 -DNDEBUG -I.
--Wall -Wextra -Wno-unused-parameter -Wno-unused-result -Wno-missing-field-initializers -Wshadow
--Wno-unused-private-field
- -

You’ll need to replace -msse2 with -mavx2 for all -the *.cpp files containing avx2 in their name. -Same with -mavx and avx files.

- -

Be careful, some files located in different directories have the same name. -To avoid conflicts and missing symbols, keep the source directory structure for -your object files.

- -

People have reported that the -fPIC option was sometimes -needed.

- -

The -mcx16 option is only need for 64-bit builds. -This means that they won’t work on -early AMD64 -CPUs and -allegedly -on a few Intel-based motherboards where the CMPXCHG16B instruction doesn’t work -for some reason.

- -

To compile a debug version, replace -O3 -DNDEBUG with --g.

- -

Link with -latomic -lpthread.

- -

With MinGW, it seems you will need a specific MinGW-64 build supporting -C++14 threading (not tested here yet, please report if you find something -useful).

-

III) Filters description

bitdepth

-
fmtc.bitdepth (
+
+
+
+
+
+
+
VapoursynthAvisynth+
+fmtc.bitdepth (
 	clip       : clip      ;
 	csp        : int  : opt;
 	bits       : int  : opt;
 	flt        : int  : opt;
 	planes     : int[]: opt; (all)
-	fulls      : int  : opt; (depends on the colorspace)
+	fulls      : int  : opt; (depends)
 	fulld      : int  : opt; (fulls)
 	dmode      : int  : opt; (3)
 	ampo       : float: opt; (1)
@@ -305,8 +261,28 @@ 

bitdepth

tpdfo : int : opt; (0) tpdfn : int : opt; (0) corplane : int : opt; (0) -) -
+)
fmtc_bitdepth (
+	clip   c,
+
+	int    bits (-1),
+	bool   flt (undefined),
+	string planes ("all"),
+	bool   fulls (depends),
+	bool   fulld (fulls),
+	int    dmode (3),
+	float  ampo (1),
+	float  ampn (0),
+	bool   dyn (false),
+	bool   staticnoise (false),
+	int    cpuopt (-1),
+	int    patsize (32),
+	bool   tpdfo (false),
+	bool   tpdfn (false),
+	bool   corplane (false)
+)

Bitdepth conversion with optional dithering.

@@ -331,6 +307,10 @@

bitdepth

The internal processing is done in floating point as soon as the input is floating point or a range conversion is detected.

+

The _ColorRange frame property is set if at least one of the +fulls or fulld parameter has been explicitely +defined.

+

Parameters

clip

@@ -343,7 +323,8 @@

Parameters

csp

-

The destination format, as Vapoursynth constant. +

Vapoursynth The destination format, as +a Vapoursynth constant. Can only change the bitdepth and the data type (integer or float). Supported destination colorspaces are the same as for the input clip.

@@ -354,6 +335,8 @@

Parameters

When there is no ambiguity between bitdepth and data type, the data type is automatically selected depending on the bitdepth. For example, specifying 32 bits is enough to switch the output to float.

+

Avisynth+ A negative value means that the +parameter is left undefined.

flt

Set it to 1 to convert to float, and to 0 for integer data. @@ -361,8 +344,19 @@

Parameters

specify the bitdepth for a float conversion.

planes

-

A list of planes to process (0 to 2), in any order. +

A list of planes to process. The content of an unprocessed plane should be considered as garbage.

+

Vapoursynth Planes as index (0 to 2), in any order.

+

Avisynth+ This is a string made of concatenated +substrings for each plane, in any order. +The planes are identified by their index, as well as the following aliases:

+ + + + + + +
"0", "y", "r"Y or red
"1", "u", "g"U or green
"2", "v", "b"V or blue
"3", "a"Alpha channel
"all"All the planes

fulls, fulld

Indicates if the clip is full-range (True) or TV-range (False). @@ -379,6 +373,8 @@

Parameters

They can also be used for range conversions. Pixel values are not clipped during a conversion between two TV-range formats.

+

Avisynth+ Alpha planes are always processed +as full-range.

dmode

Dithering mode, when applicable.

@@ -548,20 +544,38 @@

convert

matrix

-
fmtc.matrix (
+
+
+
+
+
+
fmtc.matrix (
 	clip     : clip        ;
 	mat      : data   : opt;
 	mats     : data   : opt;
 	matd     : data   : opt;
-	fulls    : int    : opt; (depends on the colorspace)
-	fulld    : int    : opt; (fulls)
+	fulls    : int    : opt; (depends)
+	fulld    : int    : opt; (depends)
 	coef     : float[]: opt;
 	csp      : int    : opt;
 	col_fam  : int    : opt;
 	bits     : int    : opt;
 	singleout: int    : opt; (-1)
 	cpuopt   : int    : opt; (-1)
-)
+)
fmtc_matrix (
+	clip   c,
+	string mat (undefined),
+	string mats (undefined),
+	string matd (undefined),
+	bool   fulls (depends),
+	bool   fulld (depends),
+	string coef (undefined),
+	string csp (undefined),
+	string col_fam (undefined),
+	int    bits (undefined),
+	int    singleout (-1),
+	int    cpuopt (-1)
+)

Colorspace conversion or simple cross-plane matrix.

@@ -585,16 +599,31 @@

matrix

For meaningful results, convert to R’G’B’ then to linear RGB and use primaries to perform the intermediary conversion.

+

The _ColorRange frame property is set if the fulld +parameter has been explicitely defined. +If the destination colorspace is a standardized one (as deduced from the +specified matrix), the _Matrix and _ColorSpace +properties are set, otherwise they are deleted from the frame.

+ +

Avisynth+If an alpha channel is present in +both the source and destination colorspaces, it is copied and its bitdepth is +possibly adapted to the destination format. +If there is no alpha channel in the source, full opacity is assumed. +If there is no alpha channel in the destination, the plane is lost.

+

Parameters

clip

The input clip. Mandatory. Supported input formats:

+

Vapoursynth 9-bit integer data is supported too.

+

Avisynth+ Colorspaces with an alpha channel are +supported too.

mat

Predefined matrix for conversions to and from R’G’B’. @@ -730,11 +759,21 @@

Parameters

csp

-

The destination format, as Vapoursynth constant. +

The destination format. It cannot change the data type (integer or float) nor the chroma subsampling. -If the colorspace family is set to GRAY, single-plane processing is enabled. -The output plane is selected with singleout (0 if not specified).

+If the colorspace family is set to GRAY (or Y), single-plane processing is +enabled. +The output plane is selected with singleout (0 if not +specified). +Only planar colorspaces are allowed.

+

Vapoursynth The format is a Vapoursynth +built-in constant.

+

Avisynth+ The format is a string with the +same kind of content as the result from BuildPixelType or the +pixel_type parameter from BlankClip. +For example: "RGBP48", "YV12", +"YUV444PS"

col_fam

Explicit specification of the destination color family, as Vapoursynth @@ -745,9 +784,10 @@

Parameters

bits

Explicit specification of the destination bitdepth. -The only allowed values are 8, 9, 10, 12, 16 and 32. -However you cannot reduce the bitdepth, only keep or increase it. +The only allowed values are 8, 10, 12, 14, 16 and 32. +However you cannot reduce the bitdepth, only keep it constant or increase it. Supersedes the bitdepth from csp.

+

Vapoursynth 9 bits is allowed too.

singleout

Enable single-plane processing. @@ -804,13 +844,18 @@

matrix2020cl

When operating on floating point data, the function uses the 12-bit variant of the scaling coefficients.

+

The _Matrix, _ColorSpace and _Transfer +frame properties are set according to the transformation. +The _ColorRange property is set if the full +parameter has been explicitely defined.

+

Parameters

clip

The input clip. Mandatory. Supported input formats:

@@ -882,6 +927,8 @@

primaries

For more details, see Charles Poynton, A Guided Tour of Color Space, 1997.

+

The _Primaries frame property is set or deleted, depending +on the target gamut.

Parameters

@@ -1047,13 +1094,22 @@

resample

between the sampling points. +

The function handles the following frame properties:

+ + + + + + +
PropertyRead conditionWrite condition
_FieldBasedAutomatic interlacing detectionInterlaced
content
_FieldInterlaced content
_ChromaLocationDepends on cplace parameters
_ColorRangefulld is explicitly set
+

Parameters

clip

Clip to be resized. Mandatory. Supported input formats:

@@ -1413,6 +1469,8 @@

transfer

bitdepth.

The signal is clipped depending on the transfer specification or the domain requirement of the functions.

+

The function sets the _ColorRange and _Transfer +frame properties.

Parameters

@@ -1565,6 +1623,14 @@

V) Changelog

  • bitdepth: added dithering mode 9: quasirandom sequences.
  • bitdepth: added a triangular probability distribution function (TPDF) for the dithering patterns and noises, along with the associated parameters tpdfo and tpdfn.
  • bitdepth: added corplane parameter to prevent colored noise in RGB processing.
  • +
  • bitdepth: fixed crash when trying to change the range (full or TV) without reducing the bitdepth.
  • +
  • matrix: deletes the _Matrix and _ColorSpace properties if a non-standard matrix is used.
  • +
  • matrix2020cl: sets the _Matrix and _Transfer frame properties.
  • +
  • matrix2020cl: fixed hideous colors with slightly out-of-colorspace values when converting from integer Y’Cb’Cr’ to integer linear RGB.
  • +
  • transfer: sYCC curve (similar to sRGB) now supports signed values.
  • +
  • Added information on functions reading and writing frame properties.
  • +
  • Added support for 14-bit data.
  • +
  • Vapoursynth: still uses API v3.6 but can use Python constants from API v4.0.
  • r23, 2021-07-14

    diff --git a/doc/vapourdoc.css b/doc/vapourdoc.css index b604375..b822a68 100644 --- a/doc/vapourdoc.css +++ b/doc/vapourdoc.css @@ -32,6 +32,7 @@ h4 { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 15px; p { margin-left: 2em; margin-right: 0em; text-align: justify; } .var { margin-left: 0.6em; font-style: italic; letter-spacing: 0.0833em; color: #660033; } +.host { font-variant: small-caps; font-weight: bold; color: #505050; display: inline-block; width: 8em; } ul { margin-left: 2em; margin-right: 0em; text-align: justify; list-style-type: square; } .n { margin-left: 2em; margin-right: 0em; text-align: justify; list-style-type: none; } @@ -49,6 +50,7 @@ table { margin-left: 2em; margin-top: 1em; margin-bottom: 1em; .n { margin-left: 0em; margin-top: 0em; margin-bottom: 0em; border: 0em; border-collapse:collapse; } .m { margin-left: 0em; margin-top: 0em; margin-bottom: 0em; border: 0em; border-collapse:collapse; } th { vertical-align:bottom; padding:1em; padding-top:0em; padding-bottom:0.25em; border-bottom: 1px solid #A8B4D8; font-weight: bold; } +.p { vertical-align:bottom; padding:0em; border: 0em; padding-left: 2em; } td { vertical-align:top; padding:1em; padding-top:0.25em; padding-bottom:0.25em; border-top: 1px solid #A8B4D8; border-bottom: 1px solid #A8B4D8; } .n { vertical-align:top; padding:0em; border: 0em; } .m7 { text-align:center; padding:0.25em; border-top: 1px solid #000000; border-left: 1px solid #000000; border-bottom: 0px; } diff --git a/src/VapourSynth.h b/src/VapourSynth.h index b4e7ff0..64d70e6 100644 --- a/src/VapourSynth.h +++ b/src/VapourSynth.h @@ -75,6 +75,12 @@ typedef struct VSAPI VSAPI; typedef struct VSFrameContext VSFrameContext; typedef enum VSColorFamily { + /* New API V4 constants */ + cfUndefined = 0, + cfGray = 1, + cfRGB = 2, + cfYUV = 3, + /* (end of new API V4 constants) */ /* all planar formats */ cmGray = 1000000, cmRGB = 2000000, diff --git a/src/avisynth.h b/src/avisynth.h new file mode 100644 index 0000000..679ac2a --- /dev/null +++ b/src/avisynth.h @@ -0,0 +1,1910 @@ +// Avisynth v2.5. Copyright 2002 Ben Rudiak-Gould et al. +// Avisynth v2.6. Copyright 2006 Klaus Post. +// Avisynth v2.6. Copyright 2009 Ian Brabham. +// Avisynth+ project +// 20160613: new 16 bit planar pixel_type constants go live! +// 20160725: pixel_type constants 10-12-14 bit + planar RGB + BRG48/64 +// 20161005: Fallback of VideoInfo functions to defaults if no function exists +// 20170117: global variables for VfW output OPT_xxxx +// 20170310: new MT mode: MT_SPECIAL_MT +// 20171103: (test with SIZETMOD define: Videoframe offsets to size_t, may affect x64) +// 20171207: C++ Standard Conformance (no change for plugin writers) +// 20180525: AVS_UNUSED define to supress parameter not used warnings +// 2020xxxx: AVS_WINDOWS and AVS_POSIX option see avs/config.h +// 20200305: ScriptEnvironment::VSprintf parameter (void *) changed back to va_list +// 20200330: removed __stdcall from variadic argument functions (Sprintf) +// (remove test SIZETMOD define for clarity) +// Integrate Avisynth Neo structures and interface, PFunction, PDevice +// 20200501: frame property support (NewVideoFrameP and other helpers) to legacy IScriptEnvironment. +// move some former IScriptEnvironment2 functions to IScriptEnvironment: +// GetEnvProperty (system prop), Allocate, Free (buffer pool) +// GetVarTry, GetVarBool/Int/String/Double/Long +// Invoke2, Invoke3, InvokeTry, Invoke2Try, Invoke3Try +// Interface Version to 8 (classic 2.6 = 6) +// 20200527 Add IScriptEnvironment_Avs25, used internally +// 20200607 AVS frame property enums to match existing Avisynth enum style + +// http://www.avisynth.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 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or visit +// http://www.gnu.org/copyleft/gpl.html . +// +// Linking Avisynth statically or dynamically with other modules is making +// a combined work based on Avisynth. Thus, the terms and conditions of +// the GNU General Public License cover the whole combination. +// +// As a special exception, the copyright holders of Avisynth give you +// permission to link Avisynth with independent modules that communicate +// with Avisynth solely through the interfaces defined in avisynth.h, +// regardless of the license terms of these independent modules, and to +// copy and distribute the resulting combined work under terms of your +// choice, provided that every copy of the combined work is accompanied +// by a complete copy of the source code of Avisynth (the version of +// Avisynth used to produce the combined work), being distributed under +// the terms of the GNU General Public License plus this exception. An +// independent module is a module which is not derived from or based on +// Avisynth, such as 3rd-party filters, import and export plugins, or +// graphical user interfaces. + + +#ifndef __AVISYNTH_8_H__ +#define __AVISYNTH_8_H__ + +#include "avs/config.h" +#include "avs/capi.h" +#include "avs/types.h" + +#ifdef AVS_POSIX +# include "avs/posix.h" +#endif + +#if defined(AVS_POSIX) +#if defined(AVS_HAIKU) +#undef __stdcall +#undef __cdecl +#endif +#define __stdcall +#define __cdecl +#endif + +// Important note on AVISYNTH_INTERFACE_VERSION V6->V8 change: +// Note 1: Those few plugins which were using earlier IScriptEnvironment2 despite the big Warning will crash have to be rebuilt. +// Note 2: How to support earlier avisynth interface with an up-to-date avisynth.h: +// Use the new frame property features adaptively after querying that at least v8 is supported +// AviSynth property support can be queried (cpp iface example): +// has_at_least_v8 = true; +// try { env->CheckVersion(8); } catch (const AvisynthError&) { has_at_least_v8 = false; } +// and use it: +// if (has_at_least_v8) dst = env->NewVideoFrameP(vi, &src); else dst = env->NewVideoFrame(vi); + +enum { + AVISYNTH_CLASSIC_INTERFACE_VERSION_25 = 3, + AVISYNTH_CLASSIC_INTERFACE_VERSION_26BETA = 5, + AVISYNTH_CLASSIC_INTERFACE_VERSION = 6, + AVISYNTH_INTERFACE_VERSION = 8 +}; + +/* Compiler-specific crap */ + +// Tell MSVC to stop precompiling here +#if defined(_MSC_VER) && !defined(__clang__) + #pragma hdrstop +#endif + +// Set up debugging macros for MS compilers; for others, step down to the +// standard interface +#ifdef _MSC_VER + #include +#else + #undef _RPT0 + #undef _RPT1 + #undef _RPT2 + #undef _RPT3 + #undef _RPT4 + #undef _RPT5 + #define _RPT0(a,b) ((void)0) + #define _RPT1(a,b,c) ((void)0) + #define _RPT2(a,b,c,d) ((void)0) + #define _RPT3(a,b,c,d,e) ((void)0) + #define _RPT4(a,b,c,d,e,f) ((void)0) + #define _RPT5(a,b,c,d,e,f,g) ((void)0) + + #include + #undef _ASSERTE + #undef _ASSERT + #define _ASSERTE(x) assert(x) + #define _ASSERT(x) assert(x) +#endif + + + +// I had problems with Premiere wanting 1-byte alignment for its structures, +// so I now set the Avisynth struct alignment explicitly here. +#pragma pack(push,8) + +// The VideoInfo struct holds global information about a clip (i.e. +// information that does not depend on the frame number). The GetVideoInfo +// method in IClip returns this struct. + +enum {SAMPLE_INT8 = 1<<0, + SAMPLE_INT16 = 1<<1, + SAMPLE_INT24 = 1<<2, // Int24 is a very stupid thing to code, but it's supported by some hardware. + SAMPLE_INT32 = 1<<3, + SAMPLE_FLOAT = 1<<4}; + +enum { + PLANAR_Y=1<<0, + PLANAR_U=1<<1, + PLANAR_V=1<<2, + PLANAR_ALIGNED=1<<3, + PLANAR_Y_ALIGNED=PLANAR_Y|PLANAR_ALIGNED, + PLANAR_U_ALIGNED=PLANAR_U|PLANAR_ALIGNED, + PLANAR_V_ALIGNED=PLANAR_V|PLANAR_ALIGNED, + PLANAR_A=1<<4, + PLANAR_R=1<<5, + PLANAR_G=1<<6, + PLANAR_B=1<<7, + PLANAR_A_ALIGNED=PLANAR_A|PLANAR_ALIGNED, + PLANAR_R_ALIGNED=PLANAR_R|PLANAR_ALIGNED, + PLANAR_G_ALIGNED=PLANAR_G|PLANAR_ALIGNED, + PLANAR_B_ALIGNED=PLANAR_B|PLANAR_ALIGNED, + }; + +class AvisynthError /* exception */ { +public: + const char* const msg; + AvisynthError(const char* _msg) : msg(_msg) {} + +// Ensure AvisynthError cannot be publicly assigned! +private: + AvisynthError& operator=(const AvisynthError&); +}; // end class AvisynthError + +enum AvsDeviceType { + DEV_TYPE_NONE = 0, + DEV_TYPE_CPU = 1, + DEV_TYPE_CUDA = 2, + DEV_TYPE_ANY = 0xFFFF +}; + +/* Forward references */ +#if defined(MSVC) + #define SINGLE_INHERITANCE __single_inheritance +#else + #define SINGLE_INHERITANCE +#endif +struct SINGLE_INHERITANCE VideoInfo; +class SINGLE_INHERITANCE VideoFrameBuffer; +class SINGLE_INHERITANCE VideoFrame; +class IClip; +class SINGLE_INHERITANCE PClip; +class SINGLE_INHERITANCE PVideoFrame; +class IScriptEnvironment; +class SINGLE_INHERITANCE AVSValue; +class INeoEnv; +class IFunction; +class SINGLE_INHERITANCE PFunction; +class Device; +class SINGLE_INHERITANCE PDevice; +class AVSMap; + + + +/* + * Avisynth C++ plugin API code function pointers. + * + * In order to maintain binary compatibility with + * future version do not change the order of the + * existing function pointers. It will be baked + * into all existing plugins. + * + * Add new function pointers to the end of the + * structure. The linkage macros generate some + * protection code to ensure newer plugin do not + * call non-existing functions in an older host. + */ + +struct AVS_Linkage { + + int Size; + +/**********************************************************************/ + +// struct VideoInfo + bool (VideoInfo::*HasVideo)() const; + bool (VideoInfo::*HasAudio)() const; + bool (VideoInfo::*IsRGB)() const; + bool (VideoInfo::*IsRGB24)() const; + bool (VideoInfo::*IsRGB32)() const; + bool (VideoInfo::*IsYUV)() const; + bool (VideoInfo::*IsYUY2)() const; + bool (VideoInfo::*IsYV24)() const; + bool (VideoInfo::*IsYV16)() const; + bool (VideoInfo::*IsYV12)() const; + bool (VideoInfo::*IsYV411)() const; + bool (VideoInfo::*IsY8)() const; + bool (VideoInfo::*IsColorSpace)(int c_space) const; + bool (VideoInfo::*Is)(int property) const; + bool (VideoInfo::*IsPlanar)() const; + bool (VideoInfo::*IsFieldBased)() const; + bool (VideoInfo::*IsParityKnown)() const; + bool (VideoInfo::*IsBFF)() const; + bool (VideoInfo::*IsTFF)() const; + bool (VideoInfo::*IsVPlaneFirst)() const; + int (VideoInfo::*BytesFromPixels)(int pixels) const; + int (VideoInfo::*RowSize)(int plane) const; + int (VideoInfo::*BMPSize)() const; + int64_t (VideoInfo::*AudioSamplesFromFrames)(int frames) const; + int (VideoInfo::*FramesFromAudioSamples)(int64_t samples) const; + int64_t (VideoInfo::*AudioSamplesFromBytes)(int64_t bytes) const; + int64_t (VideoInfo::*BytesFromAudioSamples)(int64_t samples) const; + int (VideoInfo::*AudioChannels)() const; + int (VideoInfo::*SampleType)() const; + bool (VideoInfo::*IsSampleType)(int testtype) const; + int (VideoInfo::*SamplesPerSecond)() const; + int (VideoInfo::*BytesPerAudioSample)() const; + void (VideoInfo::*SetFieldBased)(bool isfieldbased); + void (VideoInfo::*Set)(int property); + void (VideoInfo::*Clear)(int property); + int (VideoInfo::*GetPlaneWidthSubsampling)(int plane) const; + int (VideoInfo::*GetPlaneHeightSubsampling)(int plane) const; + int (VideoInfo::*BitsPerPixel)() const; + int (VideoInfo::*BytesPerChannelSample)() const; + void (VideoInfo::*SetFPS)(unsigned numerator, unsigned denominator); + void (VideoInfo::*MulDivFPS)(unsigned multiplier, unsigned divisor); + bool (VideoInfo::*IsSameColorspace)(const VideoInfo& vi) const; +// end struct VideoInfo + +/**********************************************************************/ + +// class VideoFrameBuffer + const BYTE* (VideoFrameBuffer::*VFBGetReadPtr)() const; + BYTE* (VideoFrameBuffer::*VFBGetWritePtr)(); + int (VideoFrameBuffer::*GetDataSize)() const; + int (VideoFrameBuffer::*GetSequenceNumber)() const; + int (VideoFrameBuffer::*GetRefcount)() const; +// end class VideoFrameBuffer + +/**********************************************************************/ + +// class VideoFrame + int (VideoFrame::*GetPitch)(int plane) const; + int (VideoFrame::*GetRowSize)(int plane) const; + int (VideoFrame::*GetHeight)(int plane) const; + VideoFrameBuffer* (VideoFrame::*GetFrameBuffer)() const; + int (VideoFrame::*GetOffset)(int plane) const; + const BYTE* (VideoFrame::*VFGetReadPtr)(int plane) const; + bool (VideoFrame::*IsWritable)() const; + BYTE* (VideoFrame::*VFGetWritePtr)(int plane) const; + void (VideoFrame::*VideoFrame_DESTRUCTOR)(); +// end class VideoFrame + +/**********************************************************************/ + +// class IClip + /* nothing */ +// end class IClip + +/**********************************************************************/ + +// class PClip + void (PClip::*PClip_CONSTRUCTOR0)(); + void (PClip::*PClip_CONSTRUCTOR1)(const PClip& x); + void (PClip::*PClip_CONSTRUCTOR2)(IClip* x); + void (PClip::*PClip_OPERATOR_ASSIGN0)(IClip* x); + void (PClip::*PClip_OPERATOR_ASSIGN1)(const PClip& x); + void (PClip::*PClip_DESTRUCTOR)(); +// end class PClip + +/**********************************************************************/ + +// class PVideoFrame + void (PVideoFrame::*PVideoFrame_CONSTRUCTOR0)(); + void (PVideoFrame::*PVideoFrame_CONSTRUCTOR1)(const PVideoFrame& x); + void (PVideoFrame::*PVideoFrame_CONSTRUCTOR2)(VideoFrame* x); + void (PVideoFrame::*PVideoFrame_OPERATOR_ASSIGN0)(VideoFrame* x); + void (PVideoFrame::*PVideoFrame_OPERATOR_ASSIGN1)(const PVideoFrame& x); + void (PVideoFrame::*PVideoFrame_DESTRUCTOR)(); +// end class PVideoFrame + +/**********************************************************************/ + +// class AVSValue + void (AVSValue::*AVSValue_CONSTRUCTOR0)(); + void (AVSValue::*AVSValue_CONSTRUCTOR1)(IClip* c); + void (AVSValue::*AVSValue_CONSTRUCTOR2)(const PClip& c); + void (AVSValue::*AVSValue_CONSTRUCTOR3)(bool b); + void (AVSValue::*AVSValue_CONSTRUCTOR4)(int i); + void (AVSValue::*AVSValue_CONSTRUCTOR5)(float f); + void (AVSValue::*AVSValue_CONSTRUCTOR6)(double f); + void (AVSValue::*AVSValue_CONSTRUCTOR7)(const char* s); + void (AVSValue::*AVSValue_CONSTRUCTOR8)(const AVSValue* a, int size); + void (AVSValue::*AVSValue_CONSTRUCTOR9)(const AVSValue& v); + void (AVSValue::*AVSValue_DESTRUCTOR)(); + AVSValue& (AVSValue::*AVSValue_OPERATOR_ASSIGN)(const AVSValue& v); + const AVSValue& (AVSValue::*AVSValue_OPERATOR_INDEX)(int index) const; + bool (AVSValue::*Defined)() const; + bool (AVSValue::*IsClip)() const; + bool (AVSValue::*IsBool)() const; + bool (AVSValue::*IsInt)() const; + bool (AVSValue::*IsFloat)() const; + bool (AVSValue::*IsString)() const; + bool (AVSValue::*IsArray)() const; + PClip (AVSValue::*AsClip)() const; + bool (AVSValue::*AsBool1)() const; + int (AVSValue::*AsInt1)() const; + const char* (AVSValue::*AsString1)() const; + double (AVSValue::*AsFloat1)() const; + bool (AVSValue::*AsBool2)(bool def) const; + int (AVSValue::*AsInt2)(int def) const; + double (AVSValue::*AsDblDef)(double def) const; + double (AVSValue::*AsFloat2)(float def) const; + const char* (AVSValue::*AsString2)(const char* def) const; + int (AVSValue::*ArraySize)() const; +// end class AVSValue + +/**********************************************************************/ + // Reserve pointer space so that we can keep compatibility with Avs "classic" even if it adds functions on its own + void (VideoInfo::*reserved[32])(); +/**********************************************************************/ + // AviSynth+ additions + int (VideoInfo::*NumComponents)() const; + int (VideoInfo::*ComponentSize)() const; + int (VideoInfo::*BitsPerComponent)() const; + bool (VideoInfo::*Is444)() const; + bool (VideoInfo::*Is422)() const; + bool (VideoInfo::*Is420)() const; + bool (VideoInfo::*IsY)() const; + bool (VideoInfo::*IsRGB48)() const; + bool (VideoInfo::*IsRGB64)() const; + bool (VideoInfo::*IsYUVA)() const; + bool (VideoInfo::*IsPlanarRGB)() const; + bool (VideoInfo::*IsPlanarRGBA)() const; + /**********************************************************************/ + + // frame property access + AVSMap& (VideoFrame::* getProperties)(); + const AVSMap& (VideoFrame::* getConstProperties)(); + void (VideoFrame::* setProperties)(const AVSMap& properties); + + // PFunction + void (AVSValue::* AVSValue_CONSTRUCTOR11)(const PFunction& o); + bool (AVSValue::* IsFunction)() const; + void (PFunction::* PFunction_CONSTRUCTOR0)(); + void (PFunction::* PFunction_CONSTRUCTOR1)(IFunction* p); + void (PFunction::* PFunction_CONSTRUCTOR2)(const PFunction& p); + PFunction& (PFunction::* PFunction_OPERATOR_ASSIGN0)(IFunction* other); + PFunction& (PFunction::* PFunction_OPERATOR_ASSIGN1)(const PFunction& other); + void (PFunction::* PFunction_DESTRUCTOR)(); + // end PFunction + + // extra VideoFrame functions + int (VideoFrame::* VideoFrame_CheckMemory)() const; + PDevice (VideoFrame::* VideoFrame_GetDevice)() const; + + // class PDevice, even if only CPU device + void (PDevice::* PDevice_CONSTRUCTOR0)(); + void (PDevice::* PDevice_CONSTRUCTOR1)(Device* p); + void (PDevice::* PDevice_CONSTRUCTOR2)(const PDevice& p); + PDevice& (PDevice::* PDevice_OPERATOR_ASSIGN0)(Device* other); + PDevice& (PDevice::* PDevice_OPERATOR_ASSIGN1)(const PDevice& other); + void (PDevice::* PDevice_DESTRUCTOR)(); + AvsDeviceType (PDevice::* PDevice_GetType)() const; + int (PDevice::* PDevice_GetId)() const; + int (PDevice::* PDevice_GetIndex)() const; + const char* (PDevice::* PDevice_GetName)() const; + // end class PDevice + + /**********************************************************************/ + // Reserve pointer space for Avisynth+ + void (VideoInfo::* reserved2[64 - 23])(); + /**********************************************************************/ + + // AviSynth Neo additions + INeoEnv* (__stdcall *GetNeoEnv)(IScriptEnvironment* env); + // As of V8 most PDevice, PFunction linkage entries are moved to standard avs+ place. + /**********************************************************************/ + + // this part should be identical with AVS_Linkage entries in interface.cpp +}; + +#if defined(BUILDING_AVSCORE) || defined(AVS_STATIC_LIB) +/* Macro resolution for code inside Avisynth.dll */ +# define AVS_BakedCode(arg) ; +# define AVS_LinkCall(arg) +# define AVS_LinkCallV(arg) +# define AVS_LinkCallOpt(arg, argOpt) AVSLinkCall(arg) +# define AVS_LinkCallOptDefault(arg, argDefaultValue) AVSLinkCall(arg()) +# define CALL_MEMBER_FN(object,ptrToMember) + +#else +/* Macro resolution for code inside user plugin */ +# ifdef AVS_LINKAGE_DLLIMPORT +extern __declspec(dllimport) const AVS_Linkage* const AVS_linkage; +# else +extern const AVS_Linkage* AVS_linkage; +# endif + +# ifndef offsetof +# include +# endif + +# define AVS_BakedCode(arg) { arg ; } +# define AVS_LinkCall(arg) !AVS_linkage || offsetof(AVS_Linkage, arg) >= AVS_linkage->Size ? 0 : (this->*(AVS_linkage->arg)) +# define AVS_LinkCall_Void(arg) !AVS_linkage || offsetof(AVS_Linkage, arg) >= AVS_linkage->Size ? (void)0 : (this->*(AVS_linkage->arg)) +# define AVS_LinkCallV(arg) !AVS_linkage || offsetof(AVS_Linkage, arg) >= AVS_linkage->Size ? *this : (this->*(AVS_linkage->arg)) +// Helper macros for fallback option when a function does not exists +#define CALL_MEMBER_FN(object,ptrToMember) ((object)->*(ptrToMember)) +#define AVS_LinkCallOpt(arg, argOpt) !AVS_linkage ? 0 : \ + ( offsetof(AVS_Linkage, arg) >= AVS_linkage->Size ? \ + (offsetof(AVS_Linkage, argOpt) >= AVS_linkage->Size ? 0 : CALL_MEMBER_FN(this, AVS_linkage->argOpt)() ) : \ + CALL_MEMBER_FN(this, AVS_linkage->arg)() ) +// AVS_LinkCallOptDefault puts automatically () only after arg +# define AVS_LinkCallOptDefault(arg, argDefaultValue) !AVS_linkage || offsetof(AVS_Linkage, arg) >= AVS_linkage->Size ? (argDefaultValue) : ((this->*(AVS_linkage->arg))()) + +#endif + +class PDevice +{ +public: + PDevice() AVS_BakedCode(AVS_LinkCall_Void(PDevice_CONSTRUCTOR0)()) + PDevice(Device* p) AVS_BakedCode(AVS_LinkCall_Void(PDevice_CONSTRUCTOR1)(p)) + PDevice(const PDevice& p) AVS_BakedCode(AVS_LinkCall_Void(PDevice_CONSTRUCTOR2)(p)) + PDevice& operator=(Device* p) AVS_BakedCode(return AVS_LinkCallV(PDevice_OPERATOR_ASSIGN0)(p)) + PDevice& operator=(const PDevice& p) AVS_BakedCode(return AVS_LinkCallV(PDevice_OPERATOR_ASSIGN1)(p)) + ~PDevice() AVS_BakedCode(AVS_LinkCall_Void(PDevice_DESTRUCTOR)()) + + int operator!() const { return !e; } + operator void*() const { return e; } + Device* operator->() const { return e; } + + AvsDeviceType GetType() const AVS_BakedCode(return AVS_LinkCallOptDefault(PDevice_GetType, DEV_TYPE_NONE)) + int GetId() const AVS_BakedCode(return AVS_LinkCall(PDevice_GetId)()) + int GetIndex() const AVS_BakedCode(return AVS_LinkCall(PDevice_GetIndex)()) + const char* GetName() const AVS_BakedCode(return AVS_LinkCall(PDevice_GetName)()) + +private: + Device * e; + +#ifdef BUILDING_AVSCORE +public: + void CONSTRUCTOR0(); /* Damn compiler won't allow taking the address of reserved constructs, make a dummy interlude */ + void CONSTRUCTOR1(Device* p); + void CONSTRUCTOR2(const PDevice& p); + PDevice& OPERATOR_ASSIGN0(Device* p); + PDevice& OPERATOR_ASSIGN1(const PDevice& p); + void DESTRUCTOR(); +#endif +}; +struct VideoInfo { + int width, height; // width=0 means no video + unsigned fps_numerator, fps_denominator; + int num_frames; + // This is more extensible than previous versions. More properties can be added seeminglesly. + + // Colorspace properties. +/* + +Planar match mask 1111.1000.0000.0111.0000.0111.0000.0111 +Planar signature 10xx.1000.0000.00xx.0000.00xx.00xx.00xx ? +Planar signature 10xx.1000.0000.0xxx.0000.00xx.000x.x0xx ? *new +Planar filter mask 1111.1111.1111.1111.1111.1111.1110.0111 (typo from old header fixed) + +pixel_type mapping +================== +pixel_type bit-map PIYB.Z000.0???.0SSS.0000.0???.????.???? + planar YUV CCC HHH.000u.vWWW + planar RGB(A) CCC AR + nonplanar CCC 000.00wx xyAR +Legend +====== +Planar YUV: + Code Bits Remark + W 0-2 Planar Width Subsampling bits + Use (X+1) & 3 for GetPlaneWidthSubsampling + 000 => 1 YV12, YV16, YUV420, YUV422 + 001 => 2 YV411, YUV9 + 010 => reserved + 011 => 0 YV24, YUV444, RGBP + 1xx => reserved + v 3 VPlaneFirst YV12, YV16, YV24, YV411, YUV9 + u 4 UPlaneFirst I420 + H 7-9 Planar Height Subsampling bits + Use ((X>>8)+1) & 3 for GetPlaneHeightSubsampling + 000 => 1 YV12, YUV420 + 001 => 2 YUV9 + 010 => reserved + 011 => 0 YV16, YV24, YV411, YUV422, YUV444, RGBP + 1xx => reserved + +Planar RGB + Code Bits Remark + R 0 BGR, (with SSS bits for 8/16 bit/sample or float) + A 1 BGRA, (with SSS bits for 8/16 bit/sample or float) + + +Not Planar, Interleaved (I flag) +Code Bits Remark + R 0 BGR24, and BGRx in future (with SSS bits for 8/16 bit/sample or float) + A 1 BGR32, and BGRAx in future (with SSS bits for 8/16 bit/sample or float) + y 2 YUY2 + x 3-4 reserved + w 5 Raw32 + +General +Code Bits Remark + S 16-18 Sample resolution bits + 000 => 8 + 001 => 16 + 010 => 32 (float) + 011,100 => reserved + 101 => 10 bits + 110 => 12 bits + 111 => 14 bits +for packed RGB(A): only 8 and 16 bits are valid + +Other YV12 specific (not used?) + C 20-22 Chroma Placement values 0-4 see CS_xxx_CHROMA_PLACEMENT + +Color family and layout + Packed Planar Planar Planar +Code Bits Remark RGB/RGBA YUV YUY2 Y_Grey RGB/RGBA YUVA + R 0 1/0 - 0 - 1/0 - + A 1 0/1 - 0 - 0/1 - + y 2 - - 1 - 0 - + Z 27 YUVA 0 0 0 0 1 1 + B 28 BGR 1 0 0 0 1* 0 + Y 29 YUV 0 1 1 1 0 0 + I 30 Interleaved 1 0 1 1 0 0 + P 31 Planar 0 1 0 1 1 1 +* Planar RGB plane order: G,B,R(,A) + +*/ +enum { + CS_YUVA = 1<<27, + CS_BGR = 1<<28, + CS_YUV = 1<<29, + CS_INTERLEAVED = 1<<30, + CS_PLANAR = 1<<31, + + CS_Shift_Sub_Width = 0, + CS_Shift_Sub_Height = 8, + CS_Shift_Sample_Bits = 16, + + CS_Sub_Width_Mask = 7 << CS_Shift_Sub_Width, + CS_Sub_Width_1 = 3 << CS_Shift_Sub_Width, // YV24 + CS_Sub_Width_2 = 0 << CS_Shift_Sub_Width, // YV12, I420, YV16 + CS_Sub_Width_4 = 1 << CS_Shift_Sub_Width, // YUV9, YV411 + + CS_VPlaneFirst = 1 << 3, // YV12, YV16, YV24, YV411, YUV9 + CS_UPlaneFirst = 1 << 4, // I420 + + CS_Sub_Height_Mask = 7 << CS_Shift_Sub_Height, + CS_Sub_Height_1 = 3 << CS_Shift_Sub_Height, // YV16, YV24, YV411 + CS_Sub_Height_2 = 0 << CS_Shift_Sub_Height, // YV12, I420 + CS_Sub_Height_4 = 1 << CS_Shift_Sub_Height, // YUV9 + + CS_Sample_Bits_Mask = 7 << CS_Shift_Sample_Bits, + CS_Sample_Bits_8 = 0 << CS_Shift_Sample_Bits, + CS_Sample_Bits_10 = 5 << CS_Shift_Sample_Bits, + CS_Sample_Bits_12 = 6 << CS_Shift_Sample_Bits, + CS_Sample_Bits_14 = 7 << CS_Shift_Sample_Bits, + CS_Sample_Bits_16 = 1 << CS_Shift_Sample_Bits, + CS_Sample_Bits_32 = 2 << CS_Shift_Sample_Bits, + + CS_PLANAR_MASK = CS_PLANAR | CS_INTERLEAVED | CS_YUV | CS_BGR | CS_YUVA | CS_Sample_Bits_Mask + | CS_Sub_Height_Mask | CS_Sub_Width_Mask, + CS_PLANAR_FILTER = ~( CS_VPlaneFirst | CS_UPlaneFirst ), + + CS_RGB_TYPE = 1 << 0, + CS_RGBA_TYPE = 1 << 1, + + // Specific colorformats + CS_UNKNOWN = 0, + + CS_BGR24 = CS_RGB_TYPE | CS_BGR | CS_INTERLEAVED, + CS_BGR32 = CS_RGBA_TYPE | CS_BGR | CS_INTERLEAVED, + CS_YUY2 = 1<<2 | CS_YUV | CS_INTERLEAVED, + // CS_YV12 = 1<<3 Reserved + // CS_I420 = 1<<4 Reserved + CS_RAW32 = 1<<5 | CS_INTERLEAVED, + + // YV12 must be 0xA000008 2.5 Baked API will see all new planar as YV12 + // I420 must be 0xA000010 + + CS_GENERIC_YUV420 = CS_PLANAR | CS_YUV | CS_VPlaneFirst | CS_Sub_Height_2 | CS_Sub_Width_2, // 4:2:0 planar + CS_GENERIC_YUV422 = CS_PLANAR | CS_YUV | CS_VPlaneFirst | CS_Sub_Height_1 | CS_Sub_Width_2, // 4:2:2 planar + CS_GENERIC_YUV444 = CS_PLANAR | CS_YUV | CS_VPlaneFirst | CS_Sub_Height_1 | CS_Sub_Width_1, // 4:4:4 planar + CS_GENERIC_Y = CS_PLANAR | CS_INTERLEAVED | CS_YUV, // Y only (4:0:0) + CS_GENERIC_RGBP = CS_PLANAR | CS_BGR | CS_RGB_TYPE, // planar RGB. Though name is RGB but plane order G,B,R + CS_GENERIC_RGBAP = CS_PLANAR | CS_BGR | CS_RGBA_TYPE, // planar RGBA + CS_GENERIC_YUVA420 = CS_PLANAR | CS_YUVA | CS_VPlaneFirst | CS_Sub_Height_2 | CS_Sub_Width_2, // 4:2:0:A planar + CS_GENERIC_YUVA422 = CS_PLANAR | CS_YUVA | CS_VPlaneFirst | CS_Sub_Height_1 | CS_Sub_Width_2, // 4:2:2:A planar + CS_GENERIC_YUVA444 = CS_PLANAR | CS_YUVA | CS_VPlaneFirst | CS_Sub_Height_1 | CS_Sub_Width_1, // 4:4:4:A planar + + CS_YV24 = CS_GENERIC_YUV444 | CS_Sample_Bits_8, // YVU 4:4:4 planar + CS_YV16 = CS_GENERIC_YUV422 | CS_Sample_Bits_8, // YVU 4:2:2 planar + CS_YV12 = CS_GENERIC_YUV420 | CS_Sample_Bits_8, // YVU 4:2:0 planar + CS_I420 = CS_PLANAR | CS_YUV | CS_Sample_Bits_8 | CS_UPlaneFirst | CS_Sub_Height_2 | CS_Sub_Width_2, // YUV 4:2:0 planar + CS_IYUV = CS_I420, + CS_YUV9 = CS_PLANAR | CS_YUV | CS_Sample_Bits_8 | CS_VPlaneFirst | CS_Sub_Height_4 | CS_Sub_Width_4, // YUV 4:1:0 planar + CS_YV411 = CS_PLANAR | CS_YUV | CS_Sample_Bits_8 | CS_VPlaneFirst | CS_Sub_Height_1 | CS_Sub_Width_4, // YUV 4:1:1 planar + + CS_Y8 = CS_GENERIC_Y | CS_Sample_Bits_8, // Y 4:0:0 planar + + //------------------------- + // AVS16: new planar constants go live! Experimental PF 160613 + // 10-12-14 bit + planar RGB + BRG48/64 160725 + + CS_YUV444P10 = CS_GENERIC_YUV444 | CS_Sample_Bits_10, // YUV 4:4:4 10bit samples + CS_YUV422P10 = CS_GENERIC_YUV422 | CS_Sample_Bits_10, // YUV 4:2:2 10bit samples + CS_YUV420P10 = CS_GENERIC_YUV420 | CS_Sample_Bits_10, // YUV 4:2:0 10bit samples + CS_Y10 = CS_GENERIC_Y | CS_Sample_Bits_10, // Y 4:0:0 10bit samples + + CS_YUV444P12 = CS_GENERIC_YUV444 | CS_Sample_Bits_12, // YUV 4:4:4 12bit samples + CS_YUV422P12 = CS_GENERIC_YUV422 | CS_Sample_Bits_12, // YUV 4:2:2 12bit samples + CS_YUV420P12 = CS_GENERIC_YUV420 | CS_Sample_Bits_12, // YUV 4:2:0 12bit samples + CS_Y12 = CS_GENERIC_Y | CS_Sample_Bits_12, // Y 4:0:0 12bit samples + + CS_YUV444P14 = CS_GENERIC_YUV444 | CS_Sample_Bits_14, // YUV 4:4:4 14bit samples + CS_YUV422P14 = CS_GENERIC_YUV422 | CS_Sample_Bits_14, // YUV 4:2:2 14bit samples + CS_YUV420P14 = CS_GENERIC_YUV420 | CS_Sample_Bits_14, // YUV 4:2:0 14bit samples + CS_Y14 = CS_GENERIC_Y | CS_Sample_Bits_14, // Y 4:0:0 14bit samples + + CS_YUV444P16 = CS_GENERIC_YUV444 | CS_Sample_Bits_16, // YUV 4:4:4 16bit samples + CS_YUV422P16 = CS_GENERIC_YUV422 | CS_Sample_Bits_16, // YUV 4:2:2 16bit samples + CS_YUV420P16 = CS_GENERIC_YUV420 | CS_Sample_Bits_16, // YUV 4:2:0 16bit samples + CS_Y16 = CS_GENERIC_Y | CS_Sample_Bits_16, // Y 4:0:0 16bit samples + + // 32 bit samples (float) + CS_YUV444PS = CS_GENERIC_YUV444 | CS_Sample_Bits_32, // YUV 4:4:4 32bit samples + CS_YUV422PS = CS_GENERIC_YUV422 | CS_Sample_Bits_32, // YUV 4:2:2 32bit samples + CS_YUV420PS = CS_GENERIC_YUV420 | CS_Sample_Bits_32, // YUV 4:2:0 32bit samples + CS_Y32 = CS_GENERIC_Y | CS_Sample_Bits_32, // Y 4:0:0 32bit samples + + // RGB packed + CS_BGR48 = CS_RGB_TYPE | CS_BGR | CS_INTERLEAVED | CS_Sample_Bits_16, // BGR 3x16 bit + CS_BGR64 = CS_RGBA_TYPE | CS_BGR | CS_INTERLEAVED | CS_Sample_Bits_16, // BGR 4x16 bit + // no packed 32 bit (float) support for these legacy types + + // RGB planar + CS_RGBP = CS_GENERIC_RGBP | CS_Sample_Bits_8, // Planar RGB 8 bit samples + CS_RGBP8 = CS_GENERIC_RGBP | CS_Sample_Bits_8, // Planar RGB 8 bit samples + CS_RGBP10 = CS_GENERIC_RGBP | CS_Sample_Bits_10, // Planar RGB 10bit samples + CS_RGBP12 = CS_GENERIC_RGBP | CS_Sample_Bits_12, // Planar RGB 12bit samples + CS_RGBP14 = CS_GENERIC_RGBP | CS_Sample_Bits_14, // Planar RGB 14bit samples + CS_RGBP16 = CS_GENERIC_RGBP | CS_Sample_Bits_16, // Planar RGB 16bit samples + CS_RGBPS = CS_GENERIC_RGBP | CS_Sample_Bits_32, // Planar RGB 32bit samples + + // RGBA planar + CS_RGBAP = CS_GENERIC_RGBAP | CS_Sample_Bits_8, // Planar RGBA 8 bit samples + CS_RGBAP8 = CS_GENERIC_RGBAP | CS_Sample_Bits_8, // Planar RGBA 8 bit samples + CS_RGBAP10 = CS_GENERIC_RGBAP | CS_Sample_Bits_10, // Planar RGBA 10bit samples + CS_RGBAP12 = CS_GENERIC_RGBAP | CS_Sample_Bits_12, // Planar RGBA 12bit samples + CS_RGBAP14 = CS_GENERIC_RGBAP | CS_Sample_Bits_14, // Planar RGBA 14bit samples + CS_RGBAP16 = CS_GENERIC_RGBAP | CS_Sample_Bits_16, // Planar RGBA 16bit samples + CS_RGBAPS = CS_GENERIC_RGBAP | CS_Sample_Bits_32, // Planar RGBA 32bit samples + + // Planar YUVA + CS_YUVA444 = CS_GENERIC_YUVA444 | CS_Sample_Bits_8, // YUVA 4:4:4 8bit samples + CS_YUVA422 = CS_GENERIC_YUVA422 | CS_Sample_Bits_8, // YUVA 4:2:2 8bit samples + CS_YUVA420 = CS_GENERIC_YUVA420 | CS_Sample_Bits_8, // YUVA 4:2:0 8bit samples + + CS_YUVA444P10 = CS_GENERIC_YUVA444 | CS_Sample_Bits_10, // YUVA 4:4:4 10bit samples + CS_YUVA422P10 = CS_GENERIC_YUVA422 | CS_Sample_Bits_10, // YUVA 4:2:2 10bit samples + CS_YUVA420P10 = CS_GENERIC_YUVA420 | CS_Sample_Bits_10, // YUVA 4:2:0 10bit samples + + CS_YUVA444P12 = CS_GENERIC_YUVA444 | CS_Sample_Bits_12, // YUVA 4:4:4 12bit samples + CS_YUVA422P12 = CS_GENERIC_YUVA422 | CS_Sample_Bits_12, // YUVA 4:2:2 12bit samples + CS_YUVA420P12 = CS_GENERIC_YUVA420 | CS_Sample_Bits_12, // YUVA 4:2:0 12bit samples + + CS_YUVA444P14 = CS_GENERIC_YUVA444 | CS_Sample_Bits_14, // YUVA 4:4:4 14bit samples + CS_YUVA422P14 = CS_GENERIC_YUVA422 | CS_Sample_Bits_14, // YUVA 4:2:2 14bit samples + CS_YUVA420P14 = CS_GENERIC_YUVA420 | CS_Sample_Bits_14, // YUVA 4:2:0 14bit samples + + CS_YUVA444P16 = CS_GENERIC_YUVA444 | CS_Sample_Bits_16, // YUVA 4:4:4 16bit samples + CS_YUVA422P16 = CS_GENERIC_YUVA422 | CS_Sample_Bits_16, // YUVA 4:2:2 16bit samples + CS_YUVA420P16 = CS_GENERIC_YUVA420 | CS_Sample_Bits_16, // YUVA 4:2:0 16bit samples + + CS_YUVA444PS = CS_GENERIC_YUVA444 | CS_Sample_Bits_32, // YUVA 4:4:4 32bit samples + CS_YUVA422PS = CS_GENERIC_YUVA422 | CS_Sample_Bits_32, // YUVA 4:2:2 32bit samples + CS_YUVA420PS = CS_GENERIC_YUVA420 | CS_Sample_Bits_32, // YUVA 4:2:0 32bit samples + + }; + + int pixel_type; // changed to int as of 2.5 + + + int audio_samples_per_second; // 0 means no audio + int sample_type; // as of 2.5 + int64_t num_audio_samples; // changed as of 2.5 + int nchannels; // as of 2.5 + + // Imagetype properties + + int image_type; + + enum { + IT_BFF = 1<<0, + IT_TFF = 1<<1, + IT_FIELDBASED = 1<<2 + }; + + // Chroma placement bits 20 -> 23 ::FIXME:: Really want a Class to support this + enum { + CS_UNKNOWN_CHROMA_PLACEMENT = 0 << 20, + CS_MPEG1_CHROMA_PLACEMENT = 1 << 20, + CS_MPEG2_CHROMA_PLACEMENT = 2 << 20, + CS_YUY2_CHROMA_PLACEMENT = 3 << 20, + CS_TOPLEFT_CHROMA_PLACEMENT = 4 << 20 + }; + + // useful functions of the above + bool HasVideo() const AVS_BakedCode(return AVS_LinkCall(HasVideo)()) + bool HasAudio() const AVS_BakedCode(return AVS_LinkCall(HasAudio)()) + bool IsRGB() const AVS_BakedCode(return AVS_LinkCall(IsRGB)()) + bool IsRGB24() const AVS_BakedCode(return AVS_LinkCall(IsRGB24)()) + bool IsRGB32() const AVS_BakedCode(return AVS_LinkCall(IsRGB32)()) + bool IsYUV() const AVS_BakedCode(return AVS_LinkCall(IsYUV)()) + bool IsYUY2() const AVS_BakedCode(return AVS_LinkCall(IsYUY2)()) + + bool IsYV24() const AVS_BakedCode(return AVS_LinkCall(IsYV24)()) + bool IsYV16() const AVS_BakedCode(return AVS_LinkCall(IsYV16)()) + bool IsYV12() const AVS_BakedCode(return AVS_LinkCall(IsYV12)()) + bool IsYV411() const AVS_BakedCode(return AVS_LinkCall(IsYV411)()) + //bool IsYUV9() const; + bool IsY8() const AVS_BakedCode(return AVS_LinkCall(IsY8)()) + + bool IsColorSpace(int c_space) const AVS_BakedCode(return AVS_LinkCall(IsColorSpace)(c_space)) + + bool Is(int property) const AVS_BakedCode(return AVS_LinkCall(Is)(property)) + bool IsPlanar() const AVS_BakedCode(return AVS_LinkCall(IsPlanar)()) + bool IsFieldBased() const AVS_BakedCode(return AVS_LinkCall(IsFieldBased)()) + bool IsParityKnown() const AVS_BakedCode(return AVS_LinkCall(IsParityKnown)()) + bool IsBFF() const AVS_BakedCode(return AVS_LinkCall(IsBFF)()) + bool IsTFF() const AVS_BakedCode(return AVS_LinkCall(IsTFF)()) + + bool IsVPlaneFirst() const AVS_BakedCode(return AVS_LinkCall(IsVPlaneFirst)()) // Don't use this + // Will not work on planar images, but will return only luma planes + int BytesFromPixels(int pixels) const AVS_BakedCode(return AVS_LinkCall(BytesFromPixels)(pixels)) + int RowSize(int plane = 0) const AVS_BakedCode(return AVS_LinkCall(RowSize)(plane)) + int BMPSize() const AVS_BakedCode(return AVS_LinkCall(BMPSize)()) + + int64_t AudioSamplesFromFrames(int frames) const AVS_BakedCode(return AVS_LinkCall(AudioSamplesFromFrames)(frames)) + int FramesFromAudioSamples(int64_t samples) const AVS_BakedCode(return AVS_LinkCall(FramesFromAudioSamples)(samples)) + int64_t AudioSamplesFromBytes(int64_t bytes) const AVS_BakedCode(return AVS_LinkCall(AudioSamplesFromBytes)(bytes)) + int64_t BytesFromAudioSamples(int64_t samples) const AVS_BakedCode(return AVS_LinkCall(BytesFromAudioSamples)(samples)) + int AudioChannels() const AVS_BakedCode(return AVS_LinkCall(AudioChannels)()) + int SampleType() const AVS_BakedCode(return AVS_LinkCall(SampleType)()) + bool IsSampleType(int testtype) const AVS_BakedCode(return AVS_LinkCall(IsSampleType)(testtype)) + int SamplesPerSecond() const AVS_BakedCode(return AVS_LinkCall(SamplesPerSecond)()) + int BytesPerAudioSample() const AVS_BakedCode(return AVS_LinkCall(BytesPerAudioSample)()) + void SetFieldBased(bool isfieldbased) AVS_BakedCode(AVS_LinkCall_Void(SetFieldBased)(isfieldbased)) + void Set(int property) AVS_BakedCode(AVS_LinkCall_Void(Set)(property)) + void Clear(int property) AVS_BakedCode(AVS_LinkCall_Void(Clear)(property)) + // Subsampling in bitshifts! + int GetPlaneWidthSubsampling(int plane) const AVS_BakedCode(return AVS_LinkCall(GetPlaneWidthSubsampling)(plane)) + int GetPlaneHeightSubsampling(int plane) const AVS_BakedCode(return AVS_LinkCall(GetPlaneHeightSubsampling)(plane)) + int BitsPerPixel() const AVS_BakedCode(return AVS_LinkCall(BitsPerPixel)()) + + int BytesPerChannelSample() const AVS_BakedCode(return AVS_LinkCall(BytesPerChannelSample)()) + + // useful mutator + void SetFPS(unsigned numerator, unsigned denominator) AVS_BakedCode(AVS_LinkCall_Void(SetFPS)(numerator, denominator)) + + // Range protected multiply-divide of FPS + void MulDivFPS(unsigned multiplier, unsigned divisor) AVS_BakedCode(AVS_LinkCall_Void(MulDivFPS)(multiplier, divisor)) + + // Test for same colorspace + bool IsSameColorspace(const VideoInfo& vi) const AVS_BakedCode(return AVS_LinkCall(IsSameColorspace)(vi)) + + // AVS+ extensions + // 20161005: + // Mapping of AVS+ extensions to classic 2.6 functions. + // In order to use these extended AVS+ functions for plugins that should work + // either with AVS+ or with Classic (8 bit) Avs 2.6 ans earlier AVS+ versions, there is an + // automatic fallback mechanism. + // From AVS+'s point of view these are not "baked" codes, the primary functions should exist. + // Examples: + // Is444() is mapped to IsYV24() for classic AVS2.6 + // ComponentSize() returns constant 1 (1 bytes per pixel component) + // BitsPerComponent() returns constant 8 (Classic AVS2.6 is 8 bit only) + + // Returns the number of color channels or planes in a frame + int NumComponents() const AVS_BakedCode(return AVS_LinkCallOptDefault(NumComponents, (((AVS_LinkCall(IsYUV)()) && !(AVS_LinkCall(IsY8)())) ? 3 : AVS_LinkCall(BytesFromPixels)(1)) ) ) + + // Returns the size in bytes of a single component of a pixel + int ComponentSize() const AVS_BakedCode(return AVS_LinkCallOptDefault(ComponentSize, 1)) + + // Returns the bit depth of a single component of a pixel + int BitsPerComponent() const AVS_BakedCode(return AVS_LinkCallOptDefault(BitsPerComponent, 8)) + + // like IsYV24, but bit-depth independent also for YUVA + bool Is444() const AVS_BakedCode(return AVS_LinkCallOpt(Is444, IsYV24) ) + + // like IsYV16, but bit-depth independent also for YUVA + bool Is422() const AVS_BakedCode(return AVS_LinkCallOpt(Is422, IsYV16) ) + + // like IsYV12, but bit-depth independent also for YUVA + bool Is420() const AVS_BakedCode( return AVS_LinkCallOpt(Is420, IsYV12) ) + + // like IsY8, but bit-depth independent + bool IsY() const AVS_BakedCode( return AVS_LinkCallOpt(IsY, IsY8) ) + + // like IsRGB24 for 16 bit samples + bool IsRGB48() const AVS_BakedCode( return AVS_LinkCallOptDefault(IsRGB48, false) ) + + // like IsRGB32 for 16 bit samples + bool IsRGB64() const AVS_BakedCode( return AVS_LinkCallOptDefault(IsRGB64, false) ) + + // YUVA? + bool IsYUVA() const AVS_BakedCode( return AVS_LinkCallOptDefault(IsYUVA, false) ) + + // Planar RGB? + bool IsPlanarRGB() const AVS_BakedCode( return AVS_LinkCallOptDefault(IsPlanarRGB, false) ) + + // Planar RGBA? + bool IsPlanarRGBA() const AVS_BakedCode( return AVS_LinkCallOptDefault(IsPlanarRGBA, false) ) + +}; // end struct VideoInfo + + + + +// VideoFrameBuffer holds information about a memory block which is used +// for video data. For efficiency, instances of this class are not deleted +// when the refcount reaches zero; instead they're stored in a linked list +// to be reused. The instances are deleted when the corresponding AVS +// file is closed. + +class VideoFrameBuffer { + BYTE* data; + int data_size; + // sequence_number is incremented every time the buffer is changed, so + // that stale views can tell they're no longer valid. + volatile long sequence_number; + + friend class VideoFrame; + friend class Cache; + friend class ScriptEnvironment; + volatile long refcount; + + // AVS+CUDA extension, does not break plugins if appended here + Device* device; + +protected: + VideoFrameBuffer(int size, int margin, Device* device); + VideoFrameBuffer(); + ~VideoFrameBuffer(); + +public: + const BYTE* GetReadPtr() const AVS_BakedCode( return AVS_LinkCall(VFBGetReadPtr)() ) + BYTE* GetWritePtr() AVS_BakedCode( return AVS_LinkCall(VFBGetWritePtr)() ) + int GetDataSize() const AVS_BakedCode( return AVS_LinkCall(GetDataSize)() ) + int GetSequenceNumber() const AVS_BakedCode( return AVS_LinkCall(GetSequenceNumber)() ) + int GetRefcount() const AVS_BakedCode( return AVS_LinkCall(GetRefcount)() ) + +// Ensure VideoFrameBuffer cannot be publicly assigned +private: + VideoFrameBuffer& operator=(const VideoFrameBuffer&); + +}; // end class VideoFrameBuffer + + +// smart pointer to VideoFrame +class PVideoFrame { + + VideoFrame* p; + + void Init(VideoFrame* x); + void Set(VideoFrame* x); + +public: + PVideoFrame() AVS_BakedCode(AVS_LinkCall_Void(PVideoFrame_CONSTRUCTOR0)()) + PVideoFrame(const PVideoFrame& x) AVS_BakedCode(AVS_LinkCall_Void(PVideoFrame_CONSTRUCTOR1)(x)) + PVideoFrame(VideoFrame* x) AVS_BakedCode(AVS_LinkCall_Void(PVideoFrame_CONSTRUCTOR2)(x)) + void operator=(VideoFrame* x) AVS_BakedCode(AVS_LinkCall_Void(PVideoFrame_OPERATOR_ASSIGN0)(x)) + void operator=(const PVideoFrame& x) AVS_BakedCode(AVS_LinkCall_Void(PVideoFrame_OPERATOR_ASSIGN1)(x)) + + VideoFrame* operator->() const { return p; } + + // for conditional expressions + operator void*() const { return p; } + bool operator!() const { return !p; } + + ~PVideoFrame() AVS_BakedCode(AVS_LinkCall_Void(PVideoFrame_DESTRUCTOR)()) +#ifdef BUILDING_AVSCORE +public: + void CONSTRUCTOR0(); /* Damn compiler won't allow taking the address of reserved constructs, make a dummy interlude */ + void CONSTRUCTOR1(const PVideoFrame& x); + void CONSTRUCTOR2(VideoFrame* x); + void OPERATOR_ASSIGN0(VideoFrame* x); + void OPERATOR_ASSIGN1(const PVideoFrame& x); + void DESTRUCTOR(); +#endif +}; // end class PVideoFrame + + +// VideoFrame holds a "window" into a VideoFrameBuffer. Operator new +// is overloaded to recycle class instances. + +class VideoFrame { + volatile long refcount; + VideoFrameBuffer* vfb; + + // Due to technical reasons these members are not const, but should be treated as such. + // That means do not modify them once the class has been constructed. + int offset; + int pitch, row_size, height; + int offsetU, offsetV; // U&V offsets are from top of picture. + int pitchUV, row_sizeUV, heightUV; // for Planar RGB offsetU, offsetV is for the 2nd and 3rd Plane. + // for Planar RGB pitchUV and row_sizeUV = 0, because when no VideoInfo (MakeWriteable) + // the decision on existance of UV is checked by zero pitch + // AVS+ extension, does not break plugins if appended here + int offsetA; + int pitchA, row_sizeA; // 4th alpha plane support, pitch and row_size is 0 is none + + AVSMap *properties; + + friend class PVideoFrame; + void AddRef(); + void Release(); + + friend class ScriptEnvironment; + friend class Cache; + + VideoFrame(VideoFrameBuffer* _vfb, AVSMap* avsmap, int _offset, int _pitch, int _row_size, int _height); + VideoFrame(VideoFrameBuffer* _vfb, AVSMap* avsmap, int _offset, int _pitch, int _row_size, int _height, int _offsetU, int _offsetV, int _pitchUV, int _row_sizeUV, int _heightUV); + // for Alpha + VideoFrame(VideoFrameBuffer* _vfb, AVSMap* avsmap, int _offset, int _pitch, int _row_size, int _height, int _offsetU, int _offsetV, int _pitchUV, int _row_sizeUV, int _heightUV, int _offsetA); + void* operator new(size_t size); +// TESTME: OFFSET U/V may be switched to what could be expected from AVI standard! +public: + int GetPitch(int plane=0) const AVS_BakedCode( return AVS_LinkCall(GetPitch)(plane) ) + int GetRowSize(int plane=0) const AVS_BakedCode( return AVS_LinkCall(GetRowSize)(plane) ) + int GetHeight(int plane=0) const AVS_BakedCode( return AVS_LinkCall(GetHeight)(plane) ) + + // generally you shouldn't use these three + VideoFrameBuffer* GetFrameBuffer() const AVS_BakedCode( return AVS_LinkCall(GetFrameBuffer)() ) + int GetOffset(int plane=0) const AVS_BakedCode( return AVS_LinkCall(GetOffset)(plane) ) + + // in plugins use env->SubFrame() -- because implementation code is only available inside avisynth.dll. Doh! + VideoFrame* Subframe(int rel_offset, int new_pitch, int new_row_size, int new_height) const; + VideoFrame* Subframe(int rel_offset, int new_pitch, int new_row_size, int new_height, int rel_offsetU, int rel_offsetV, int pitchUV) const; + // for Alpha + VideoFrame* Subframe(int rel_offset, int new_pitch, int new_row_size, int new_height, int rel_offsetU, int rel_offsetV, int pitchUV, int rel_offsetA) const; + + const BYTE* GetReadPtr(int plane=0) const AVS_BakedCode( return AVS_LinkCall(VFGetReadPtr)(plane) ) + bool IsWritable() const AVS_BakedCode( return AVS_LinkCall(IsWritable)() ) + BYTE* GetWritePtr(int plane=0) const AVS_BakedCode( return AVS_LinkCall(VFGetWritePtr)(plane) ) + + AVSMap& getProperties() AVS_BakedCode(return AVS_LinkCallOptDefault(getProperties, (AVSMap&)*(AVSMap*)0)) + const AVSMap& getConstProperties() AVS_BakedCode(return AVS_LinkCallOptDefault(getConstProperties, (const AVSMap&)*(const AVSMap*)0)) + void setProperties(const AVSMap & _properties) AVS_BakedCode(AVS_LinkCall_Void(setProperties)(_properties)) + + PDevice GetDevice() const AVS_BakedCode(return AVS_LinkCall(VideoFrame_GetDevice)()) + + // 0: OK, 1: NG, -1: disabled or non CPU frame + int CheckMemory() const AVS_BakedCode(return AVS_LinkCall(VideoFrame_CheckMemory)()) + + ~VideoFrame() AVS_BakedCode( AVS_LinkCall_Void(VideoFrame_DESTRUCTOR)() ) +#ifdef BUILDING_AVSCORE +public: + void DESTRUCTOR(); /* Damn compiler won't allow taking the address of reserved constructs, make a dummy interlude */ +#endif + +// Ensure VideoFrame cannot be publicly assigned +private: + VideoFrame& operator=(const VideoFrame&); + +}; // end class VideoFrame + +enum CachePolicyHint { + // Values 0 to 5 are reserved for old 2.5 plugins + // do not use them in new plugins + + // New 2.6 explicitly defined cache hints. + CACHE_NOTHING=10, // Do not cache video. + CACHE_WINDOW=11, // Hard protect upto X frames within a range of X from the current frame N. + CACHE_GENERIC=12, // LRU cache upto X frames. + CACHE_FORCE_GENERIC=13, // LRU cache upto X frames, override any previous CACHE_WINDOW. + + CACHE_GET_POLICY=30, // Get the current policy. + CACHE_GET_WINDOW=31, // Get the current window h_span. + CACHE_GET_RANGE=32, // Get the current generic frame range. + + CACHE_AUDIO=50, // Explicitly cache audio, X byte cache. + CACHE_AUDIO_NOTHING=51, // Explicitly do not cache audio. + CACHE_AUDIO_NONE=52, // Audio cache off (auto mode), X byte intial cache. + CACHE_AUDIO_AUTO=53, // Audio cache on (auto mode), X byte intial cache. + + CACHE_GET_AUDIO_POLICY=70, // Get the current audio policy. + CACHE_GET_AUDIO_SIZE=71, // Get the current audio cache size. + + CACHE_PREFETCH_FRAME=100, // Queue request to prefetch frame N. + CACHE_PREFETCH_GO=101, // Action video prefetches. + + CACHE_PREFETCH_AUDIO_BEGIN=120, // Begin queue request transaction to prefetch audio (take critical section). + CACHE_PREFETCH_AUDIO_STARTLO=121, // Set low 32 bits of start. + CACHE_PREFETCH_AUDIO_STARTHI=122, // Set high 32 bits of start. + CACHE_PREFETCH_AUDIO_COUNT=123, // Set low 32 bits of length. + CACHE_PREFETCH_AUDIO_COMMIT=124, // Enqueue request transaction to prefetch audio (release critical section). + CACHE_PREFETCH_AUDIO_GO=125, // Action audio prefetches. + + CACHE_GETCHILD_CACHE_MODE=200, // Cache ask Child for desired video cache mode. + CACHE_GETCHILD_CACHE_SIZE=201, // Cache ask Child for desired video cache size. + CACHE_GETCHILD_AUDIO_MODE=202, // Cache ask Child for desired audio cache mode. + CACHE_GETCHILD_AUDIO_SIZE=203, // Cache ask Child for desired audio cache size. + + CACHE_GETCHILD_COST=220, // Cache ask Child for estimated processing cost. + CACHE_COST_ZERO=221, // Child response of zero cost (ptr arithmetic only). + CACHE_COST_UNIT=222, // Child response of unit cost (less than or equal 1 full frame blit). + CACHE_COST_LOW=223, // Child response of light cost. (Fast) + CACHE_COST_MED=224, // Child response of medium cost. (Real time) + CACHE_COST_HI=225, // Child response of heavy cost. (Slow) + + CACHE_GETCHILD_THREAD_MODE=240, // Cache ask Child for thread safetyness. + CACHE_THREAD_UNSAFE=241, // Only 1 thread allowed for all instances. 2.5 filters default! + CACHE_THREAD_CLASS=242, // Only 1 thread allowed for each instance. 2.6 filters default! + CACHE_THREAD_SAFE=243, // Allow all threads in any instance. + CACHE_THREAD_OWN=244, // Safe but limit to 1 thread, internally threaded. + + CACHE_GETCHILD_ACCESS_COST=260, // Cache ask Child for preferred access pattern. + CACHE_ACCESS_RAND=261, // Filter is access order agnostic. + CACHE_ACCESS_SEQ0=262, // Filter prefers sequential access (low cost) + CACHE_ACCESS_SEQ1=263, // Filter needs sequential access (high cost) + + CACHE_AVSPLUS_CONSTANTS = 500, // Smaller values are reserved for classic Avisynth + + CACHE_DONT_CACHE_ME, // Filters that don't need caching (eg. trim, cache etc.) should return 1 to this request + CACHE_SET_MIN_CAPACITY, + CACHE_SET_MAX_CAPACITY, + CACHE_GET_MIN_CAPACITY, + CACHE_GET_MAX_CAPACITY, + CACHE_GET_SIZE, + CACHE_GET_REQUESTED_CAP, + CACHE_GET_CAPACITY, + CACHE_GET_MTMODE, + + CACHE_IS_CACHE_REQ, + CACHE_IS_CACHE_ANS, + CACHE_IS_MTGUARD_REQ, + CACHE_IS_MTGUARD_ANS, + + CACHE_AVSPLUS_CUDA_CONSTANTS = 600, + + CACHE_GET_DEV_TYPE, // Device types a filter can return + CACHE_GET_CHILD_DEV_TYPE, // Device types a fitler can receive + + CACHE_USER_CONSTANTS = 1000 // Smaller values are reserved for the core + +}; + +// Base class for all filters. +class IClip { + friend class PClip; + friend class AVSValue; + volatile long refcnt; + void AddRef(); +#if BUILDING_AVSCORE +public: +#endif + void Release(); +public: + IClip() : refcnt(0) {} + virtual int __stdcall GetVersion() { return AVISYNTH_INTERFACE_VERSION; } + virtual PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env) = 0; + virtual bool __stdcall GetParity(int n) = 0; // return field parity if field_based, else parity of first field in frame + virtual void __stdcall GetAudio(void* buf, int64_t start, int64_t count, IScriptEnvironment* env) = 0; // start and count are in samples + /* Need to check GetVersion first, pre v5 will return random crap from EAX reg. */ + virtual int __stdcall SetCacheHints(int cachehints,int frame_range) = 0 ; // We do not pass cache requests upwards, only to the next filter. + virtual const VideoInfo& __stdcall GetVideoInfo() = 0; + virtual ~IClip() {} +}; // end class IClip + + +// smart pointer to IClip +class PClip { + + IClip* p; + + IClip* GetPointerWithAddRef() const; + friend class AVSValue; + friend class VideoFrame; + + void Init(IClip* x); + void Set(IClip* x); + +public: + PClip() AVS_BakedCode( AVS_LinkCall_Void(PClip_CONSTRUCTOR0)() ) + PClip(const PClip& x) AVS_BakedCode( AVS_LinkCall_Void(PClip_CONSTRUCTOR1)(x) ) + PClip(IClip* x) AVS_BakedCode( AVS_LinkCall_Void(PClip_CONSTRUCTOR2)(x) ) + void operator=(IClip* x) AVS_BakedCode( AVS_LinkCall_Void(PClip_OPERATOR_ASSIGN0)(x) ) + void operator=(const PClip& x) AVS_BakedCode( AVS_LinkCall_Void(PClip_OPERATOR_ASSIGN1)(x) ) + + IClip* operator->() const { return p; } + + // useful in conditional expressions + operator void*() const { return p; } + bool operator!() const { return !p; } + + ~PClip() AVS_BakedCode( AVS_LinkCall_Void(PClip_DESTRUCTOR)() ) +#ifdef BUILDING_AVSCORE +public: + void CONSTRUCTOR0(); /* Damn compiler won't allow taking the address of reserved constructs, make a dummy interlude */ + void CONSTRUCTOR1(const PClip& x); + void CONSTRUCTOR2(IClip* x); + void OPERATOR_ASSIGN0(IClip* x); + void OPERATOR_ASSIGN1(const PClip& x); + void DESTRUCTOR(); +#endif +}; // end class PClip + +// enums for frame property functions +enum AVSPropTypes { + PROPTYPE_UNSET = 'u', // ptUnset + PROPTYPE_INT = 'i', // peType + PROPTYPE_FLOAT = 'f', // ptFloat + PROPTYPE_DATA = 's', // ptData + PROPTYPE_CLIP = 'c', // ptClip + PROPTYPE_FRAME = 'v' // ptFrame + // ptFunction = 'm' +}; + +enum AVSGetPropErrors { + GETPROPERROR_UNSET = 1, // peUnset + GETPROPERROR_TYPE = 2, // peType + GETPROPERROR_INDEX = 4 // peIndex +}; + +enum AVSPropAppendMode { + PROPAPPENDMODE_REPLACE = 0, // paReplace + PROPAPPENDMODE_APPEND = 1, // paAppend + PROPAPPENDMODE_TOUCH = 2 // paTouch +}; + + +class AVSValue { +public: + + AVSValue() AVS_BakedCode( AVS_LinkCall_Void(AVSValue_CONSTRUCTOR0)() ) + AVSValue(IClip* c) AVS_BakedCode( AVS_LinkCall_Void(AVSValue_CONSTRUCTOR1)(c) ) + AVSValue(const PClip& c) AVS_BakedCode( AVS_LinkCall_Void(AVSValue_CONSTRUCTOR2)(c) ) + AVSValue(bool b) AVS_BakedCode( AVS_LinkCall_Void(AVSValue_CONSTRUCTOR3)(b) ) + AVSValue(int i) AVS_BakedCode( AVS_LinkCall_Void(AVSValue_CONSTRUCTOR4)(i) ) +// AVSValue(int64_t l); + AVSValue(float f) AVS_BakedCode( AVS_LinkCall_Void(AVSValue_CONSTRUCTOR5)(f) ) + AVSValue(double f) AVS_BakedCode( AVS_LinkCall_Void(AVSValue_CONSTRUCTOR6)(f) ) + AVSValue(const char* s) AVS_BakedCode( AVS_LinkCall_Void(AVSValue_CONSTRUCTOR7)(s) ) + AVSValue(const AVSValue* a, int size) AVS_BakedCode( AVS_LinkCall_Void(AVSValue_CONSTRUCTOR8)(a, size) ) + AVSValue(const AVSValue& a, int size) AVS_BakedCode( AVS_LinkCall_Void(AVSValue_CONSTRUCTOR8)(&a, size) ) + AVSValue(const AVSValue& v) AVS_BakedCode( AVS_LinkCall_Void(AVSValue_CONSTRUCTOR9)(v) ) + AVSValue(const PFunction& n) AVS_BakedCode(AVS_LinkCall_Void(AVSValue_CONSTRUCTOR11)(n)) + + ~AVSValue() AVS_BakedCode( AVS_LinkCall_Void(AVSValue_DESTRUCTOR)() ) + AVSValue& operator=(const AVSValue& v) AVS_BakedCode( return AVS_LinkCallV(AVSValue_OPERATOR_ASSIGN)(v) ) + + // Note that we transparently allow 'int' to be treated as 'float'. + // There are no int<->bool conversions, though. + + bool Defined() const AVS_BakedCode( return AVS_LinkCall(Defined)() ) + bool IsClip() const AVS_BakedCode( return AVS_LinkCall(IsClip)() ) + bool IsBool() const AVS_BakedCode( return AVS_LinkCall(IsBool)() ) + bool IsInt() const AVS_BakedCode( return AVS_LinkCall(IsInt)() ) +// bool IsLong() const; + bool IsFloat() const AVS_BakedCode( return AVS_LinkCall(IsFloat)() ) + bool IsString() const AVS_BakedCode( return AVS_LinkCall(IsString)() ) + bool IsArray() const AVS_BakedCode(return AVS_LinkCall(IsArray)()) + bool IsFunction() const AVS_BakedCode( return AVS_LinkCall(IsFunction)() ) + + PClip AsClip() const AVS_BakedCode( return AVS_LinkCall(AsClip)() ) + bool AsBool() const AVS_BakedCode( return AVS_LinkCall(AsBool1)() ) + int AsInt() const AVS_BakedCode( return AVS_LinkCall(AsInt1)() ) +// int AsLong() const; + const char* AsString() const AVS_BakedCode( return AVS_LinkCall(AsString1)() ) + double AsFloat() const AVS_BakedCode( return AVS_LinkCall(AsFloat1)() ) + float AsFloatf() const AVS_BakedCode( return float( AVS_LinkCall(AsFloat1)() ) ) + + bool AsBool(bool def) const AVS_BakedCode( return AVS_LinkCall(AsBool2)(def) ) + int AsInt(int def) const AVS_BakedCode( return AVS_LinkCall(AsInt2)(def) ) + double AsDblDef(double def) const AVS_BakedCode( return AVS_LinkCall(AsDblDef)(def) ) // Value is still a float + double AsFloat(float def) const AVS_BakedCode( return AVS_LinkCall(AsFloat2)(def) ) + float AsFloatf(float def) const AVS_BakedCode( return float( AVS_LinkCall(AsFloat2)(def) ) ) + const char* AsString(const char* def) const AVS_BakedCode( return AVS_LinkCall(AsString2)(def) ) + PFunction AsFunction() const; // internal use only + + int ArraySize() const AVS_BakedCode( return AVS_LinkCall(ArraySize)() ) + + const AVSValue& operator[](int index) const AVS_BakedCode( return AVS_LinkCallV(AVSValue_OPERATOR_INDEX)(index) ) + +private: + + short type; // 'a'rray, 'c'lip, 'b'ool, 'i'nt, 'f'loat, 's'tring, 'v'oid, fu'n'ction, or RFU: 'l'ong ('d'ouble) + short array_size; + union { + IClip* clip; + bool boolean; + int integer; + float floating_pt; + const char* string; + const AVSValue* array; + IFunction* function; + #ifdef X86_64 + // if ever, only x64 will support. It breaks struct size on 32 bit + int64_t longlong; // 8 bytes + double double_pt; // 8 bytes + #endif + }; + + void Assign(const AVSValue* src, bool init); +#ifdef BUILDING_AVSCORE +public: + void CONSTRUCTOR0(); /* Damn compiler won't allow taking the address of reserved constructs, make a dummy interlude */ + void CONSTRUCTOR1(IClip* c); + void CONSTRUCTOR2(const PClip& c); + void CONSTRUCTOR3(bool b); + void CONSTRUCTOR4(int i); + void CONSTRUCTOR5(float f); + void CONSTRUCTOR6(double f); + void CONSTRUCTOR7(const char* s); + void CONSTRUCTOR8(const AVSValue* a, int size); + void CONSTRUCTOR9(const AVSValue& v); + void CONSTRUCTOR11(const PFunction& n); + void DESTRUCTOR(); + AVSValue& OPERATOR_ASSIGN(const AVSValue& v); + const AVSValue& OPERATOR_INDEX(int index) const; + + bool AsBool1() const; + int AsInt1() const; + const char* AsString1() const; + double AsFloat1() const; + + bool AsBool2(bool def) const; + int AsInt2(int def) const; + double AsFloat2(float def) const; + const char* AsString2(const char* def) const; + +#ifdef NEW_AVSVALUE + void MarkArrayAsC(); // for C interface, no deep-copy and deep-free + void CONSTRUCTOR10(const AVSValue& v, bool c_arrays); + AVSValue(const AVSValue& v, bool c_arrays); + void Assign2(const AVSValue* src, bool init, bool c_arrays); +#endif + +#endif +}; // end class AVSValue + +#define AVS_UNUSED(x) (void)(x) + +// instantiable null filter +class GenericVideoFilter : public IClip { +protected: + PClip child; + VideoInfo vi; +public: + GenericVideoFilter(PClip _child) : child(_child) { vi = child->GetVideoInfo(); } + PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env) { return child->GetFrame(n, env); } + void __stdcall GetAudio(void* buf, int64_t start, int64_t count, IScriptEnvironment* env) { child->GetAudio(buf, start, count, env); } + const VideoInfo& __stdcall GetVideoInfo() { return vi; } + bool __stdcall GetParity(int n) { return child->GetParity(n); } + int __stdcall SetCacheHints(int cachehints, int frame_range) { AVS_UNUSED(cachehints); AVS_UNUSED(frame_range); return 0; }; // We do not pass cache requests upwards, only to the next filter. +}; + + +class PFunction +{ +public: + PFunction() AVS_BakedCode(AVS_LinkCall_Void(PFunction_CONSTRUCTOR0)()) + PFunction(IFunction* p) AVS_BakedCode(AVS_LinkCall_Void(PFunction_CONSTRUCTOR1)(p)) + PFunction(const PFunction& p) AVS_BakedCode(AVS_LinkCall_Void(PFunction_CONSTRUCTOR2)(p)) + PFunction& operator=(IFunction* p) AVS_BakedCode(return AVS_LinkCallV(PFunction_OPERATOR_ASSIGN0)(p)) + PFunction& operator=(const PFunction& p) AVS_BakedCode(return AVS_LinkCallV(PFunction_OPERATOR_ASSIGN1)(p)) + ~PFunction() AVS_BakedCode(AVS_LinkCall_Void(PFunction_DESTRUCTOR)()) + + int operator!() const { return !e; } + operator void*() const { return e; } + IFunction* operator->() const { return e; } + +private: + IFunction * e; + + friend class AVSValue; + IFunction * GetPointerWithAddRef() const; + void Init(IFunction* p); + void Set(IFunction* p); + +#ifdef BUILDING_AVSCORE +public: + void CONSTRUCTOR0(); /* Damn compiler won't allow taking the address of reserved constructs, make a dummy interlude */ + void CONSTRUCTOR1(IFunction* p); + void CONSTRUCTOR2(const PFunction& p); + PFunction& OPERATOR_ASSIGN0(IFunction* p); + PFunction& OPERATOR_ASSIGN1(const PFunction& p); + void DESTRUCTOR(); +#endif +}; + + +#undef CALL_MEMBER_FN +#undef AVS_LinkCallOptDefault +#undef AVS_LinkCallOpt +#undef AVS_LinkCallV +#undef AVS_LinkCall +#undef AVS_BakedCode + + +#include "avs/cpuid.h" + +// IScriptEnvironment GetEnvProperty +enum AvsEnvProperty +{ + AEP_PHYSICAL_CPUS = 1, + AEP_LOGICAL_CPUS = 2, + AEP_THREADPOOL_THREADS = 3, + AEP_FILTERCHAIN_THREADS = 4, + AEP_THREAD_ID = 5, + AEP_VERSION = 6, + + // Neo additionals + AEP_NUM_DEVICES = 901, + AEP_FRAME_ALIGN = 902, + AEP_PLANE_ALIGN = 903, + + AEP_SUPPRESS_THREAD = 921, + AEP_GETFRAME_RECURSIVE = 922, +}; + +// IScriptEnvironment Allocate +enum AvsAllocType +{ + AVS_NORMAL_ALLOC = 1, + AVS_POOLED_ALLOC = 2 +}; + + +class IScriptEnvironment { +public: + virtual ~IScriptEnvironment() {} + + virtual /*static*/ int __stdcall GetCPUFlags() = 0; + + virtual char* __stdcall SaveString(const char* s, int length = -1) = 0; + virtual char* Sprintf(const char* fmt, ...) = 0; + // note: val is really a va_list; I hope everyone typedefs va_list to a pointer + // 20200305: (void *) changed back to va_list + virtual char* __stdcall VSprintf(const char* fmt, va_list val) = 0; + +#ifdef AVS_WINDOWS + __declspec(noreturn) virtual void ThrowError(const char* fmt, ...) = 0; +#else + virtual void ThrowError(const char* fmt, ...) = 0; +#endif + + class NotFound /*exception*/ {}; // thrown by Invoke and GetVar + + typedef AVSValue (__cdecl *ApplyFunc)(AVSValue args, void* user_data, IScriptEnvironment* env); + + virtual void __stdcall AddFunction(const char* name, const char* params, ApplyFunc apply, void* user_data) = 0; + virtual bool __stdcall FunctionExists(const char* name) = 0; + virtual AVSValue __stdcall Invoke(const char* name, const AVSValue args, const char* const* arg_names=0) = 0; + + virtual AVSValue __stdcall GetVar(const char* name) = 0; + virtual bool __stdcall SetVar(const char* name, const AVSValue& val) = 0; + virtual bool __stdcall SetGlobalVar(const char* name, const AVSValue& val) = 0; + + virtual void __stdcall PushContext(int level=0) = 0; + virtual void __stdcall PopContext() = 0; + + // note v8: deprecated in most cases, use NewVideoFrameP is possible + virtual PVideoFrame __stdcall NewVideoFrame(const VideoInfo& vi, int align=FRAME_ALIGN) = 0; + + virtual bool __stdcall MakeWritable(PVideoFrame* pvf) = 0; + + virtual void __stdcall BitBlt(BYTE* dstp, int dst_pitch, const BYTE* srcp, int src_pitch, int row_size, int height) = 0; + + typedef void (__cdecl *ShutdownFunc)(void* user_data, IScriptEnvironment* env); + virtual void __stdcall AtExit(ShutdownFunc function, void* user_data) = 0; + + virtual void __stdcall CheckVersion(int version = AVISYNTH_INTERFACE_VERSION) = 0; + + virtual PVideoFrame __stdcall Subframe(PVideoFrame src, int rel_offset, int new_pitch, int new_row_size, int new_height) = 0; + + virtual int __stdcall SetMemoryMax(int mem) = 0; + + virtual int __stdcall SetWorkingDir(const char * newdir) = 0; + + virtual void* __stdcall ManageCache(int key, void* data) = 0; + + enum PlanarChromaAlignmentMode { + PlanarChromaAlignmentOff, + PlanarChromaAlignmentOn, + PlanarChromaAlignmentTest }; + + virtual bool __stdcall PlanarChromaAlignment(PlanarChromaAlignmentMode key) = 0; + + virtual PVideoFrame __stdcall SubframePlanar(PVideoFrame src, int rel_offset, int new_pitch, int new_row_size, + int new_height, int rel_offsetU, int rel_offsetV, int new_pitchUV) = 0; + + // **** AVISYNTH_INTERFACE_VERSION 5 **** defined since classic Avisynth 2.6 beta + virtual void __stdcall DeleteScriptEnvironment() = 0; + + virtual void __stdcall ApplyMessage(PVideoFrame* frame, const VideoInfo& vi, const char* message, int size, + int textcolor, int halocolor, int bgcolor) = 0; + + virtual const AVS_Linkage* __stdcall GetAVSLinkage() = 0; + + // **** AVISYNTH_INTERFACE_VERSION 6 **** defined since classic Avisynth 2.6 + // noThrow version of GetVar + virtual AVSValue __stdcall GetVarDef(const char* name, const AVSValue& def = AVSValue()) = 0; + + // **** AVISYNTH_INTERFACE_VERSION 8 **** AviSynth+ 3.6.0- + virtual PVideoFrame __stdcall SubframePlanarA(PVideoFrame src, int rel_offset, int new_pitch, int new_row_size, + int new_height, int rel_offsetU, int rel_offsetV, int new_pitchUV, int rel_offsetA) = 0; + + virtual void __stdcall copyFrameProps(const PVideoFrame& src, PVideoFrame& dst) = 0; + virtual const AVSMap* __stdcall getFramePropsRO(const PVideoFrame& frame) = 0; + virtual AVSMap* __stdcall getFramePropsRW(PVideoFrame& frame) = 0; + + virtual int __stdcall propNumKeys(const AVSMap* map) = 0; + + virtual const char* __stdcall propGetKey(const AVSMap* map, int index) = 0; + virtual int __stdcall propNumElements(const AVSMap* map, const char* key) = 0; + virtual char __stdcall propGetType(const AVSMap* map, const char* key) = 0; + + virtual int64_t __stdcall propGetInt(const AVSMap* map, const char* key, int index, int* error) = 0; + virtual double __stdcall propGetFloat(const AVSMap* map, const char* key, int index, int* error) = 0; + virtual const char* __stdcall propGetData(const AVSMap* map, const char* key, int index, int* error) = 0; + virtual int __stdcall propGetDataSize(const AVSMap* map, const char* key, int index, int* error) = 0; + virtual PClip __stdcall propGetClip(const AVSMap* map, const char* key, int index, int* error) = 0; + virtual const PVideoFrame __stdcall propGetFrame(const AVSMap* map, const char* key, int index, int* error) = 0; + + virtual int __stdcall propDeleteKey(AVSMap* map, const char* key) = 0; + + virtual int __stdcall propSetInt(AVSMap* map, const char* key, int64_t i, int append) = 0; + virtual int __stdcall propSetFloat(AVSMap* map, const char* key, double d, int append) = 0; + virtual int __stdcall propSetData(AVSMap* map, const char* key, const char* d, int length, int append) = 0; + virtual int __stdcall propSetClip(AVSMap* map, const char* key, PClip& clip, int append) = 0; + virtual int __stdcall propSetFrame(AVSMap* map, const char* key, const PVideoFrame& frame, int append) = 0; + + virtual const int64_t* __stdcall propGetIntArray(const AVSMap* map, const char* key, int* error) = 0; + virtual const double* __stdcall propGetFloatArray(const AVSMap* map, const char* key, int* error) = 0; + virtual int __stdcall propSetIntArray(AVSMap* map, const char* key, const int64_t* i, int size) = 0; + virtual int __stdcall propSetFloatArray(AVSMap* map, const char* key, const double* d, int size) = 0; + + virtual AVSMap* __stdcall createMap() = 0; + virtual void __stdcall freeMap(AVSMap* map) = 0; + virtual void __stdcall clearMap(AVSMap* map) = 0; + + // NewVideoFrame with frame property source. + virtual PVideoFrame __stdcall NewVideoFrameP(const VideoInfo& vi, PVideoFrame* propSrc, int align = FRAME_ALIGN) = 0; + + // Note: do not declare existing names like 'NewVideoFrame' again with different parameters since MSVC will reorder it + // in the vtable and group it together with the first NewVideoFrame variant. + // This results in shifting all vtable method pointers after NewVideoFrame and breaks all plugins who expect the old order. + // E.g. ApplyMessage will be called instead of GetAVSLinkage + + // Generic query to ask for various system properties + virtual size_t __stdcall GetEnvProperty(AvsEnvProperty prop) = 0; + + // Support functions + virtual void* __stdcall Allocate(size_t nBytes, size_t alignment, AvsAllocType type) = 0; + virtual void __stdcall Free(void* ptr) = 0; + + // these GetVar versions (renamed differently) were moved from IScriptEnvironment2 + + // Returns TRUE and the requested variable. If the method fails, returns FALSE and does not touch 'val'. + virtual bool __stdcall GetVarTry(const char* name, AVSValue* val) const = 0; // ex virtual bool __stdcall GetVar(const char* name, AVSValue* val) const = 0; + // Return the value of the requested variable. + // If the variable was not found or had the wrong type, + // return the supplied default value. + virtual bool __stdcall GetVarBool(const char* name, bool def) const = 0; + virtual int __stdcall GetVarInt(const char* name, int def) const = 0; + virtual double __stdcall GetVarDouble(const char* name, double def) const = 0; + virtual const char* __stdcall GetVarString(const char* name, const char* def) const = 0; + // brand new in v8 - though no real int64 support yet + virtual int64_t __stdcall GetVarLong(const char* name, int64_t def) const = 0; + + // 'Invoke' functions moved here from internal ScriptEnvironments are renamed in order to keep vtable order + // Invoke functions with 'Try' will return false instead of throwing NotFound(). + // ex-IScriptEnvironment2 + virtual bool __stdcall InvokeTry(AVSValue* result, const char* name, const AVSValue& args, const char* const* arg_names = 0) = 0; + // Since V8 + virtual AVSValue __stdcall Invoke2(const AVSValue& implicit_last, const char* name, const AVSValue args, const char* const* arg_names = 0) = 0; + // Ex-INeo + virtual bool __stdcall Invoke2Try(AVSValue* result, const AVSValue& implicit_last, const char* name, const AVSValue args, const char* const* arg_names = 0) = 0; + virtual AVSValue __stdcall Invoke3(const AVSValue& implicit_last, const PFunction& func, const AVSValue args, const char* const* arg_names = 0) = 0; + virtual bool __stdcall Invoke3Try(AVSValue* result, const AVSValue& implicit_last, const PFunction& func, const AVSValue args, const char* const* arg_names = 0) = 0; + +}; // end class IScriptEnvironment + +// used internally +class IScriptEnvironment_Avs25 { +public: + virtual ~IScriptEnvironment_Avs25() {} + + virtual /*static*/ int __stdcall GetCPUFlags() = 0; + + virtual char* __stdcall SaveString(const char* s, int length = -1) = 0; + virtual char* Sprintf(const char* fmt, ...) = 0; + virtual char* __stdcall VSprintf(const char* fmt, va_list val) = 0; + +#ifdef AVS_WINDOWS + __declspec(noreturn) virtual void ThrowError(const char* fmt, ...) = 0; +#else + virtual void ThrowError(const char* fmt, ...) = 0; +#endif + + class NotFound /*exception*/ {}; // thrown by Invoke and GetVar + + typedef AVSValue(__cdecl* ApplyFunc)(AVSValue args, void* user_data, IScriptEnvironment* env); + + virtual void __stdcall AddFunction25(const char* name, const char* params, ApplyFunc apply, void* user_data) = 0; + virtual bool __stdcall FunctionExists(const char* name) = 0; + virtual AVSValue __stdcall Invoke25(const char* name, const AVSValue args, const char* const* arg_names = 0) = 0; + + virtual AVSValue __stdcall GetVar(const char* name) = 0; + virtual bool __stdcall SetVar(const char* name, const AVSValue& val) = 0; + virtual bool __stdcall SetGlobalVar(const char* name, const AVSValue& val) = 0; + + virtual void __stdcall PushContext(int level = 0) = 0; + virtual void __stdcall PopContext() = 0; + + virtual PVideoFrame __stdcall NewVideoFrame(const VideoInfo& vi, int align = FRAME_ALIGN) = 0; + + virtual bool __stdcall MakeWritable(PVideoFrame* pvf) = 0; + + virtual void __stdcall BitBlt(BYTE* dstp, int dst_pitch, const BYTE* srcp, int src_pitch, int row_size, int height) = 0; + + typedef void(__cdecl* ShutdownFunc)(void* user_data, IScriptEnvironment* env); + virtual void __stdcall AtExit(ShutdownFunc function, void* user_data) = 0; + + virtual void __stdcall CheckVersion(int version = AVISYNTH_CLASSIC_INTERFACE_VERSION_25) = 0; + + virtual PVideoFrame __stdcall Subframe(PVideoFrame src, int rel_offset, int new_pitch, int new_row_size, int new_height) = 0; + + virtual int __stdcall SetMemoryMax(int mem) = 0; + + virtual int __stdcall SetWorkingDir(const char* newdir) = 0; + + // specially returns 1 for key MC_QueryAvs25 to check if called from AVS2.5 interface + virtual void* __stdcall ManageCache25(int key, void* data) = 0; + + enum PlanarChromaAlignmentMode { + PlanarChromaAlignmentOff, + PlanarChromaAlignmentOn, + PlanarChromaAlignmentTest + }; + + virtual bool __stdcall PlanarChromaAlignment(IScriptEnvironment::PlanarChromaAlignmentMode key) = 0; + + virtual PVideoFrame __stdcall SubframePlanar(PVideoFrame src, int rel_offset, int new_pitch, int new_row_size, + int new_height, int rel_offsetU, int rel_offsetV, int new_pitchUV) = 0; + + // Despite the name, we provide entries up to V6 in case someone requests + // a V3 interface and still wants to use V5-V6 functions + + // **** AVISYNTH_INTERFACE_VERSION 5 **** defined since classic Avisynth 2.6 beta + virtual void __stdcall DeleteScriptEnvironment() = 0; + + virtual void __stdcall ApplyMessage(PVideoFrame* frame, const VideoInfo& vi, const char* message, int size, + int textcolor, int halocolor, int bgcolor) = 0; + + virtual const AVS_Linkage* __stdcall GetAVSLinkage() = 0; + + // **** AVISYNTH_INTERFACE_VERSION 6 **** defined since classic Avisynth 2.6 + // noThrow version of GetVar + virtual AVSValue __stdcall GetVarDef(const char* name, const AVSValue& def = AVSValue()) = 0; + +}; // end class IScriptEnvironment_Avs25 + + +enum MtMode +{ + MT_INVALID = 0, + MT_NICE_FILTER = 1, + MT_MULTI_INSTANCE = 2, + MT_SERIALIZED = 3, + MT_SPECIAL_MT = 4, + MT_MODE_COUNT = 5 +}; + +class IJobCompletion +{ +public: + + virtual ~IJobCompletion() {} + virtual void __stdcall Wait() = 0; + virtual AVSValue __stdcall Get(size_t i) = 0; + virtual size_t __stdcall Size() const = 0; + virtual size_t __stdcall Capacity() const = 0; + virtual void __stdcall Reset() = 0; + virtual void __stdcall Destroy() = 0; +}; + +class IScriptEnvironment2; +class Prefetcher; +typedef AVSValue (*ThreadWorkerFuncPtr)(IScriptEnvironment2* env, void* data); + + +/* ----------------------------------------------------------------------------- + Note to plugin authors: The interface in IScriptEnvironment2 is + preliminary / under construction / only for testing / non-final etc.! + As long as you see this note here, IScriptEnvironment2 might still change, + in which case your plugin WILL break. This also means that you are welcome + to test it and give your feedback about any ideas, improvements, or issues + you might have. + ----------------------------------------------------------------------------- */ +class IScriptEnvironment2 : public IScriptEnvironment{ +public: + virtual ~IScriptEnvironment2() {} + + // V8: SubframePlanarA, GetEnvProperty, GetVar versions, Allocate, Free, no-throw Invoke moved to IScriptEnvironment + + // Plugin functions + virtual bool __stdcall LoadPlugin(const char* filePath, bool throwOnError, AVSValue *result) = 0; + virtual void __stdcall AddAutoloadDir(const char* dirPath, bool toFront) = 0; + virtual void __stdcall ClearAutoloadDirs() = 0; + virtual void __stdcall AutoloadPlugins() = 0; + virtual void __stdcall AddFunction(const char* name, const char* params, ApplyFunc apply, void* user_data, const char *exportVar) = 0; + virtual bool __stdcall InternalFunctionExists(const char* name) = 0; + + // Threading + virtual void __stdcall SetFilterMTMode(const char* filter, MtMode mode, bool force) = 0; // If filter is "DEFAULT_MT_MODE", sets the default MT mode + virtual IJobCompletion* __stdcall NewCompletion(size_t capacity) = 0; + virtual void __stdcall ParallelJob(ThreadWorkerFuncPtr jobFunc, void* jobData, IJobCompletion* completion) = 0; + + // These lines are needed so that we can overload the older functions from IScriptEnvironment. + using IScriptEnvironment::Invoke; + using IScriptEnvironment::AddFunction; + +}; // end class IScriptEnvironment2 + + +// To allow Avisynth+ add functions to IScriptEnvironment2, +// Neo defines another new interface, INeoEnv. +// INeoEnv and the legacy interfaces (IScriptEnvironment/IScriptEnvironment2) +// share the same ScriptEnvironment instance. The function with the same signature +// is exactly identical and there is no limitation to switch interfaces. +// You can use any interface you like. +// Note to plugin authors : The interface is not stable, see comments in IScriptEnvironment2 +class INeoEnv { +public: + virtual ~INeoEnv() {} + + typedef IScriptEnvironment::NotFound NotFound; + typedef IScriptEnvironment::ApplyFunc ApplyFunc; + typedef IScriptEnvironment::ShutdownFunc ShutdownFunc; + + virtual void __stdcall DeleteScriptEnvironment() = 0; + + virtual const AVS_Linkage* __stdcall GetAVSLinkage() = 0; + + // Get legacy interface (Avisynth+) + virtual IScriptEnvironment2* __stdcall GetEnv2() = 0; + // Get compatibility interface for AVS CPP 2.5 plugins + virtual IScriptEnvironment_Avs25* __stdcall GetEnv25() = 0; + + // Generic system to ask for various properties + virtual size_t __stdcall GetEnvProperty(AvsEnvProperty prop) = 0; + virtual int __stdcall GetCPUFlags() = 0; + + // Plugin functions + virtual bool __stdcall LoadPlugin(const char* filePath, bool throwOnError, AVSValue *result) = 0; + virtual void __stdcall AddAutoloadDir(const char* dirPath, bool toFront) = 0; + virtual void __stdcall ClearAutoloadDirs() = 0; + virtual void __stdcall AutoloadPlugins() = 0; + + virtual void __stdcall AddFunction( + const char* name, const char* params, ApplyFunc apply, void* user_data) = 0; + virtual void __stdcall AddFunction( + const char* name, const char* params, ApplyFunc apply, void* user_data, const char *exportVar) = 0; + virtual bool __stdcall FunctionExists(const char* name) = 0; + virtual bool __stdcall InternalFunctionExists(const char* name) = 0; + + // Invoke function. Throws NotFound exception when the specified function does not exist. + virtual AVSValue __stdcall Invoke( + const char* name, const AVSValue args, const char* const* arg_names = 0) = 0; + virtual AVSValue __stdcall Invoke2( + const AVSValue& implicit_last, const char* name, const AVSValue args, const char* const* arg_names = 0) = 0; + virtual AVSValue __stdcall Invoke3( + const AVSValue& implicit_last, + const PFunction& func, const AVSValue args, const char* const* arg_names = 0) = 0; + + // These versions of Invoke will return false instead of throwing NotFound(). + virtual bool __stdcall InvokeTry( + AVSValue* result, const char* name, const AVSValue& args, const char* const* arg_names = 0) = 0; + virtual bool __stdcall Invoke2Try( + AVSValue* result, const AVSValue& implicit_last, + const char* name, const AVSValue args, const char* const* arg_names = 0) = 0; + virtual bool __stdcall Invoke3Try( + AVSValue* result, const AVSValue& implicit_last, + const PFunction& func, const AVSValue args, const char* const* arg_names = 0) = 0; + + // Throws exception when the requested variable is not found. + virtual AVSValue __stdcall GetVar(const char* name) = 0; + + // noThrow version of GetVar + virtual AVSValue __stdcall GetVarDef(const char* name, const AVSValue& def = AVSValue()) = 0; + + // Returns TRUE and the requested variable. If the method fails, returns FALSE and does not touch 'val'. + virtual bool __stdcall GetVarTry(const char* name, AVSValue* val) const = 0; + + // Return the value of the requested variable. + // If the variable was not found or had the wrong type, + // return the supplied default value. + virtual bool __stdcall GetVarBool(const char* name, bool def) const = 0; + virtual int __stdcall GetVarInt(const char* name, int def) const = 0; + virtual double __stdcall GetVarDouble(const char* name, double def) const = 0; + virtual const char* __stdcall GetVarString(const char* name, const char* def) const = 0; + virtual int64_t __stdcall GetVarLong(const char* name, int64_t def) const = 0; + + virtual bool __stdcall SetVar(const char* name, const AVSValue& val) = 0; + virtual bool __stdcall SetGlobalVar(const char* name, const AVSValue& val) = 0; + + // Switch local variables + virtual void __stdcall PushContext(int level = 0) = 0; + virtual void __stdcall PopContext() = 0; + + // Global variable frame support + virtual void __stdcall PushContextGlobal() = 0; + virtual void __stdcall PopContextGlobal() = 0; + + // Allocate new video frame + // in PNeoEnv: align parameter is no longer supported + virtual PVideoFrame __stdcall NewVideoFrame(const VideoInfo& vi) = 0; // current device is used + virtual PVideoFrame __stdcall NewVideoFrame(const VideoInfo& vi, const PDevice& device) = 0; + // as above but with property sources + virtual PVideoFrame __stdcall NewVideoFrame(const VideoInfo& vi, PVideoFrame *propSrc) = 0; // current device is used + frame property source + virtual PVideoFrame __stdcall NewVideoFrame(const VideoInfo& vi, const PDevice& device, PVideoFrame* propSrc) = 0; // current device is used + frame property source + + // Frame related operations + virtual bool __stdcall MakeWritable(PVideoFrame* pvf) = 0; + virtual void __stdcall BitBlt(BYTE* dstp, int dst_pitch, const BYTE* srcp, int src_pitch, int row_size, int height) = 0; + + virtual PVideoFrame __stdcall Subframe(PVideoFrame src, int rel_offset, int new_pitch, int new_row_size, int new_height) = 0; + virtual PVideoFrame __stdcall SubframePlanar(PVideoFrame src, int rel_offset, int new_pitch, int new_row_size, + int new_height, int rel_offsetU, int rel_offsetV, int new_pitchUV) = 0; + virtual PVideoFrame __stdcall SubframePlanarA(PVideoFrame src, int rel_offset, int new_pitch, int new_row_size, + int new_height, int rel_offsetU, int rel_offsetV, int new_pitchUV, int rel_offsetA) = 0; + + // frame properties support + virtual void __stdcall copyFrameProps(const PVideoFrame& src, PVideoFrame& dst) = 0; + virtual const AVSMap* __stdcall getFramePropsRO(const PVideoFrame& frame) = 0; + virtual AVSMap* __stdcall getFramePropsRW(PVideoFrame& frame) = 0; + + virtual int __stdcall propNumKeys(const AVSMap* map) = 0; + virtual const char* __stdcall propGetKey(const AVSMap* map, int index) = 0; + virtual int __stdcall propNumElements(const AVSMap* map, const char* key) = 0; + virtual char __stdcall propGetType(const AVSMap* map, const char* key) = 0; + + virtual int64_t __stdcall propGetInt(const AVSMap* map, const char* key, int index, int* error) = 0; + virtual double __stdcall propGetFloat(const AVSMap* map, const char* key, int index, int* error) = 0; + virtual const char* __stdcall propGetData(const AVSMap* map, const char* key, int index, int* error) = 0; + virtual int __stdcall propGetDataSize(const AVSMap* map, const char* key, int index, int* error) = 0; + virtual PClip __stdcall propGetClip(const AVSMap* map, const char* key, int index, int* error) = 0; + virtual const PVideoFrame __stdcall propGetFrame(const AVSMap* map, const char* key, int index, int* error) = 0; + + virtual int __stdcall propDeleteKey(AVSMap* map, const char* key) = 0; + + virtual int __stdcall propSetInt(AVSMap* map, const char* key, int64_t i, int append) = 0; + virtual int __stdcall propSetFloat(AVSMap* map, const char* key, double d, int append) = 0; + virtual int __stdcall propSetData(AVSMap* map, const char* key, const char* d, int length, int append) = 0; + virtual int __stdcall propSetClip(AVSMap* map, const char* key, PClip& clip, int append) = 0; + virtual int __stdcall propSetFrame(AVSMap* map, const char* key, const PVideoFrame& frame, int append) = 0; + + virtual const int64_t *__stdcall propGetIntArray(const AVSMap* map, const char* key, int* error) = 0; + virtual const double *__stdcall propGetFloatArray(const AVSMap* map, const char* key, int* error) = 0; + virtual int __stdcall propSetIntArray(AVSMap* map, const char* key, const int64_t* i, int size) = 0; + virtual int __stdcall propSetFloatArray(AVSMap* map, const char* key, const double* d, int size) = 0; + + virtual AVSMap* __stdcall createMap() = 0; + virtual void __stdcall freeMap(AVSMap* map) = 0; + virtual void __stdcall clearMap(AVSMap* map) = 0; + + // Support functions + virtual void* __stdcall Allocate(size_t nBytes, size_t alignment, AvsAllocType type) = 0; + virtual void __stdcall Free(void* ptr) = 0; + + virtual char* __stdcall SaveString(const char* s, int length = -1) = 0; + virtual char* __stdcall SaveString(const char* s, int length, bool escape) = 0; + virtual char* Sprintf(const char* fmt, ...) = 0; + virtual char* __stdcall VSprintf(const char* fmt, va_list val) = 0; + + __declspec(noreturn) virtual void ThrowError(const char* fmt, ...) = 0; + + virtual void __stdcall ApplyMessage(PVideoFrame* frame, const VideoInfo& vi, const char* message, int size, + int textcolor, int halocolor, int bgcolor) = 0; + + // Setting + virtual int __stdcall SetMemoryMax(int mem) = 0; + virtual int __stdcall SetMemoryMax(AvsDeviceType type, int index, int mem) = 0; + + virtual bool __stdcall PlanarChromaAlignment(IScriptEnvironment::PlanarChromaAlignmentMode key) = 0; + virtual int __stdcall SetWorkingDir(const char * newdir) = 0; + virtual void* __stdcall ManageCache(int key, void* data) = 0; + + virtual void __stdcall AtExit(ShutdownFunc function, void* user_data) = 0; + virtual void __stdcall CheckVersion(int version = AVISYNTH_INTERFACE_VERSION) = 0; + + // Threading + virtual void __stdcall SetFilterMTMode(const char* filter, MtMode mode, bool force) = 0; + virtual IJobCompletion* __stdcall NewCompletion(size_t capacity) = 0; + virtual void __stdcall ParallelJob(ThreadWorkerFuncPtr jobFunc, void* jobData, IJobCompletion* completion) = 0; + + // CUDA Support + virtual PDevice __stdcall GetDevice(AvsDeviceType dev_type, int dev_index) const = 0; + virtual PDevice __stdcall GetDevice() const = 0; // get current device + virtual AvsDeviceType __stdcall GetDeviceType() const = 0; + virtual int __stdcall GetDeviceId() const = 0; + virtual int __stdcall GetDeviceIndex() const = 0; + virtual void* __stdcall GetDeviceStream() const = 0; + virtual void __stdcall DeviceAddCallback(void(*cb)(void*), void* user_data) = 0; + + virtual PVideoFrame __stdcall GetFrame(PClip c, int n, const PDevice& device) = 0; + +}; + +// support interface conversion +struct PNeoEnv { + INeoEnv* p; + PNeoEnv() : p() { } + PNeoEnv(IScriptEnvironment* env) +#if defined(BUILDING_AVSCORE) || defined(AVS_STATIC_LIB) + ; +#else + : p(!AVS_linkage || offsetof(AVS_Linkage, GetNeoEnv) >= AVS_linkage->Size ? 0 : AVS_linkage->GetNeoEnv(env)) { } +#endif + + int operator!() const { return !p; } + operator void*() const { return p; } + INeoEnv* operator->() const { return p; } +#ifdef BUILDING_AVSCORE + inline operator IScriptEnvironment2*(); + inline operator IScriptEnvironment_Avs25* (); +#else + operator IScriptEnvironment2*() { return p->GetEnv2(); } + operator IScriptEnvironment_Avs25* () { return p->GetEnv25(); } +#endif +}; + + +// avisynth.dll exports this; it's a way to use it as a library, without +// writing an AVS script or without going through AVIFile. +AVSC_API(IScriptEnvironment*, CreateScriptEnvironment)(int version = AVISYNTH_INTERFACE_VERSION); + + +// These are some global variables you can set in your script to change AviSynth's behavior. +#define VARNAME_AllowFloatAudio "OPT_AllowFloatAudio" // Allow WAVE_FORMAT_IEEE_FLOAT audio output +#define VARNAME_VDubPlanarHack "OPT_VDubPlanarHack" // Hack YV16 and YV24 chroma plane order for old VDub's +#define VARNAME_AVIPadScanlines "OPT_AVIPadScanlines" // Have scanlines mod4 padded in all pixel formats +#define VARNAME_UseWaveExtensible "OPT_UseWaveExtensible" // Use WAVEFORMATEXTENSIBLE when describing audio to Windows +#define VARNAME_dwChannelMask "OPT_dwChannelMask" // Integer audio channel mask. See description of WAVEFORMATEXTENSIBLE for more info. +#define VARNAME_Enable_V210 "OPT_Enable_V210" // AVS+ use V210 instead of P210 (VfW) +#define VARNAME_Enable_Y3_10_10 "OPT_Enable_Y3_10_10" // AVS+ use Y3[10][10] instead of P210 (VfW) +#define VARNAME_Enable_Y3_10_16 "OPT_Enable_Y3_10_16" // AVS+ use Y3[10][16] instead of P216 (VfW) +#define VARNAME_Enable_b64a "OPT_Enable_b64a" // AVS+ use b64a instead of BRA[64] (VfW) +#define VARNAME_Enable_PlanarToPackedRGB "OPT_Enable_PlanarToPackedRGB" // AVS+ convert Planar RGB to packed RGB (VfW) + +// C exports +#include "avs/capi.h" +AVSC_API(IScriptEnvironment2*, CreateScriptEnvironment2)(int version = AVISYNTH_INTERFACE_VERSION); + +#ifndef BUILDING_AVSCORE +#undef AVS_UNUSED +#endif + +#pragma pack(pop) + +#endif //__AVISYNTH_8_H__ diff --git a/src/avs/alignment.h b/src/avs/alignment.h new file mode 100644 index 0000000..170d9cc --- /dev/null +++ b/src/avs/alignment.h @@ -0,0 +1,134 @@ +// Avisynth C Interface Version 0.20 +// Copyright 2003 Kevin Atkinson + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or visit +// http://www.gnu.org/copyleft/gpl.html . +// +// As a special exception, I give you permission to link to the +// Avisynth C interface with independent modules that communicate with +// the Avisynth C interface solely through the interfaces defined in +// avisynth_c.h, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting combined work +// under terms of your choice, provided that every copy of the +// combined work is accompanied by a complete copy of the source code +// of the Avisynth C interface and Avisynth itself (with the version +// used to produce the combined work), being distributed under the +// terms of the GNU General Public License plus this exception. An +// independent module is a module which is not derived from or based +// on Avisynth C Interface, such as 3rd-party filters, import and +// export plugins, or graphical user interfaces. + +#ifndef AVS_ALIGNMENT_H +#define AVS_ALIGNMENT_H + +// Functions and macros to help work with alignment requirements. + +// Tells if a number is a power of two. +#define IS_POWER2(n) ((n) && !((n) & ((n) - 1))) + +// Tells if the pointer "ptr" is aligned to "align" bytes. +#define IS_PTR_ALIGNED(ptr, align) (((uintptr_t)ptr & ((uintptr_t)(align-1))) == 0) + +// Rounds up the number "n" to the next greater multiple of "align" +#define ALIGN_NUMBER(n, align) (((n) + (align)-1) & (~((align)-1))) + +// Rounds up the pointer address "ptr" to the next greater multiple of "align" +#define ALIGN_POINTER(ptr, align) (((uintptr_t)(ptr) + (align)-1) & (~(uintptr_t)((align)-1))) + +#ifdef __cplusplus + +#include +#include +#include +#include "config.h" + +#if defined(MSVC) && _MSC_VER<1400 + // needed for VS2013, otherwise C++11 'alignas' works + #define avs_alignas(x) __declspec(align(x)) +#else + // assumes C++11 support + #define avs_alignas(x) alignas(x) +#endif + +template +static bool IsPtrAligned(T* ptr, size_t align) +{ + assert(IS_POWER2(align)); + return (bool)IS_PTR_ALIGNED(ptr, align); +} + +template +static T AlignNumber(T n, T align) +{ + assert(IS_POWER2(align)); + return ALIGN_NUMBER(n, align); +} + +template +static T* AlignPointer(T* ptr, size_t align) +{ + assert(IS_POWER2(align)); + return (T*)ALIGN_POINTER(ptr, align); +} + +extern "C" +{ +#else +#include +#endif // __cplusplus + +// Returns a new buffer that is at least the size "nbytes". +// The buffer will be aligned to "align" bytes. +// Returns NULL on error. On successful allocation, +// the returned buffer must be freed using "avs_free". +inline void* avs_malloc(size_t nbytes, size_t align) +{ + if (!IS_POWER2(align)) + return NULL; + + size_t offset = sizeof(void*) + align - 1; + + void *orig = malloc(nbytes + offset); + if (orig == NULL) + return NULL; + + void **aligned = (void**)(((uintptr_t)orig + (uintptr_t)offset) & (~(uintptr_t)(align-1))); + aligned[-1] = orig; + return aligned; +} + +// Buffers allocated using "avs_malloc" must be freed +// using "avs_free" instead of "free". +inline void avs_free(void *ptr) +{ + // Mirroring free()'s semantic requires us to accept NULLs + if (ptr == NULL) + return; + + free(((void**)ptr)[-1]); +} + +#ifdef __cplusplus +} // extern "C" + +// The point of these undef's is to force using the template functions +// if we are in C++ mode. For C, the user can rely only on the macros. +#undef IS_PTR_ALIGNED +#undef ALIGN_NUMBER +#undef ALIGN_POINTER + +#endif // __cplusplus + +#endif //AVS_ALIGNMENT_H diff --git a/src/avs/capi.h b/src/avs/capi.h new file mode 100644 index 0000000..7629296 --- /dev/null +++ b/src/avs/capi.h @@ -0,0 +1,121 @@ +// Avisynth C Interface Version 0.20 +// Copyright 2003 Kevin Atkinson + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or visit +// http://www.gnu.org/copyleft/gpl.html . +// +// As a special exception, I give you permission to link to the +// Avisynth C interface with independent modules that communicate with +// the Avisynth C interface solely through the interfaces defined in +// avisynth_c.h, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting combined work +// under terms of your choice, provided that every copy of the +// combined work is accompanied by a complete copy of the source code +// of the Avisynth C interface and Avisynth itself (with the version +// used to produce the combined work), being distributed under the +// terms of the GNU General Public License plus this exception. An +// independent module is a module which is not derived from or based +// on Avisynth C Interface, such as 3rd-party filters, import and +// export plugins, or graphical user interfaces. + +#ifndef AVS_CAPI_H +#define AVS_CAPI_H + +#include "config.h" + +#ifdef AVS_POSIX +// this is also defined in avs/posix.h +#ifndef AVS_HAIKU +#define __declspec(x) +#endif +#endif + +#ifdef __cplusplus +# define EXTERN_C extern "C" +#else +# define EXTERN_C +#endif + +#ifdef AVS_WINDOWS +#ifdef BUILDING_AVSCORE +# if defined(GCC) && defined(X86_32) +# define AVSC_CC +# else // MSVC builds and 64-bit GCC +# ifndef AVSC_USE_STDCALL +# define AVSC_CC __cdecl +# else +# define AVSC_CC __stdcall +# endif +# endif +#else // needed for programs that talk to AviSynth+ +# ifndef AVSC_WIN32_GCC32 // see comment below +# ifndef AVSC_USE_STDCALL +# define AVSC_CC __cdecl +# else +# define AVSC_CC __stdcall +# endif +# else +# define AVSC_CC +# endif +#endif +# else +# define AVSC_CC +#endif + +// On 64-bit Windows, there's only one calling convention, +// so there is no difference between MSVC and GCC. On 32-bit, +// this isn't true. The convention that GCC needs to use to +// even build AviSynth+ as 32-bit makes anything that uses +// it incompatible with 32-bit MSVC builds of AviSynth+. +// The AVSC_WIN32_GCC32 define is meant to provide a user +// switchable way to make builds of FFmpeg to test 32-bit +// GCC builds of AviSynth+ without having to screw around +// with alternate headers, while still default to the usual +// situation of using 32-bit MSVC builds of AviSynth+. + +// Hopefully, this situation will eventually be resolved +// and a broadly compatible solution will arise so the +// same 32-bit FFmpeg build can handle either MSVC or GCC +// builds of AviSynth+. + +#define AVSC_INLINE static __inline + +#ifdef BUILDING_AVSCORE +#ifdef AVS_WINDOWS +# ifndef AVS_STATIC_LIB +# define AVSC_EXPORT __declspec(dllexport) +# else +# define AVSC_EXPORT +# endif +# define AVSC_API(ret, name) EXTERN_C AVSC_EXPORT ret AVSC_CC name +#else +# define AVSC_EXPORT EXTERN_C +# define AVSC_API(ret, name) EXTERN_C ret AVSC_CC name +#endif +#else +# define AVSC_EXPORT EXTERN_C __declspec(dllexport) +# ifndef AVS_STATIC_LIB +# define AVSC_IMPORT __declspec(dllimport) +# else +# define AVSC_IMPORT +# endif +# ifndef AVSC_NO_DECLSPEC +# define AVSC_API(ret, name) EXTERN_C AVSC_IMPORT ret AVSC_CC name +# else +# define AVSC_API(ret, name) typedef ret (AVSC_CC *name##_func) +# endif +#endif + +#endif //AVS_CAPI_H diff --git a/src/avs/config.h b/src/avs/config.h new file mode 100644 index 0000000..d78ddc4 --- /dev/null +++ b/src/avs/config.h @@ -0,0 +1,159 @@ +// Avisynth C Interface Version 0.20 +// Copyright 2003 Kevin Atkinson + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or visit +// http://www.gnu.org/copyleft/gpl.html . +// +// As a special exception, I give you permission to link to the +// Avisynth C interface with independent modules that communicate with +// the Avisynth C interface solely through the interfaces defined in +// avisynth_c.h, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting combined work +// under terms of your choice, provided that every copy of the +// combined work is accompanied by a complete copy of the source code +// of the Avisynth C interface and Avisynth itself (with the version +// used to produce the combined work), being distributed under the +// terms of the GNU General Public License plus this exception. An +// independent module is a module which is not derived from or based +// on Avisynth C Interface, such as 3rd-party filters, import and +// export plugins, or graphical user interfaces. + +#ifndef AVS_CONFIG_H +#define AVS_CONFIG_H + +// Undefine this to get cdecl calling convention +#define AVSC_USE_STDCALL 1 + +// NOTE TO PLUGIN AUTHORS: +// Because FRAME_ALIGN can be substantially higher than the alignment +// a plugin actually needs, plugins should not use FRAME_ALIGN to check for +// alignment. They should always request the exact alignment value they need. +// This is to make sure that plugins work over the widest range of AviSynth +// builds possible. +#define FRAME_ALIGN 64 + +#if defined(_M_AMD64) || defined(__x86_64) +# define X86_64 +#elif defined(_M_IX86) || defined(__i386__) +# define X86_32 +// VS2017 introduced _M_ARM64 +#elif defined(_M_ARM64) || defined(__aarch64__) +# define ARM64 +#elif defined(_M_ARM) || defined(__arm__) +# define ARM32 +#elif defined(__PPC64__) +# define PPC64 +#elif defined(_M_PPC) || defined(__PPC__) || defined(__POWERPC__) +# define PPC32 +#elif defined(__riscv) +# define RISCV +#elif defined(__sparc_v9__) +# define SPARC +#else +# error Unsupported CPU architecture. +#endif + +// VC++ LLVM-Clang-cl MinGW-Gnu +// MSVC x x +// MSVC_PURE x +// CLANG x +// GCC x + +#if defined(__clang__) +// Check clang first. clang-cl also defines __MSC_VER +// We set MSVC because they are mostly compatible +# define CLANG +#if defined(_MSC_VER) +# define MSVC +# define AVS_FORCEINLINE __attribute__((always_inline)) +#else +# define AVS_FORCEINLINE __attribute__((always_inline)) inline +#endif +#elif defined(_MSC_VER) +# define MSVC +# define MSVC_PURE +# define AVS_FORCEINLINE __forceinline +#elif defined(__GNUC__) +# define GCC +# define AVS_FORCEINLINE __attribute__((always_inline)) inline +#else +# error Unsupported compiler. +# define AVS_FORCEINLINE inline +# undef __forceinline +# define __forceinline inline +#endif + +#if defined(_WIN32) +# define AVS_WINDOWS +#elif defined(__linux__) +# define AVS_LINUX +# define AVS_POSIX +#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) +# define AVS_BSD +# define AVS_POSIX +#elif defined(__APPLE__) +# define AVS_MACOS +# define AVS_POSIX +#elif defined(__HAIKU__) +# define AVS_HAIKU +# define AVS_POSIX +#else +# error Operating system unsupported. +#endif + +// useful warnings disabler macros for supported compilers + +#if defined(_MSC_VER) +#define DISABLE_WARNING_PUSH __pragma(warning( push )) +#define DISABLE_WARNING_POP __pragma(warning( pop )) +#define DISABLE_WARNING(warningNumber) __pragma(warning( disable : warningNumber )) + +#define DISABLE_WARNING_UNREFERENCED_LOCAL_VARIABLE DISABLE_WARNING(4101) +#define DISABLE_WARNING_UNREFERENCED_FUNCTION DISABLE_WARNING(4505) +// other warnings you want to deactivate... + +#elif defined(__GNUC__) || defined(__clang__) +#define DO_PRAGMA(X) _Pragma(#X) +#define DISABLE_WARNING_PUSH DO_PRAGMA(GCC diagnostic push) +#define DISABLE_WARNING_POP DO_PRAGMA(GCC diagnostic pop) +#define DISABLE_WARNING(warningName) DO_PRAGMA(GCC diagnostic ignored #warningName) + +#define DISABLE_WARNING_UNREFERENCED_LOCAL_VARIABLE DISABLE_WARNING(-Wunused-variable) +#define DISABLE_WARNING_UNREFERENCED_FUNCTION DISABLE_WARNING(-Wunused-function) +// other warnings you want to deactivate... + +#else +#define DISABLE_WARNING_PUSH +#define DISABLE_WARNING_POP +#define DISABLE_WARNING_UNREFERENCED_LOCAL_VARIABLE +#define DISABLE_WARNING_UNREFERENCED_FUNCTION +// other warnings you want to deactivate... + +#endif + +#if defined(AVS_POSIX) +#define NEW_AVSVALUE +#else +#define NEW_AVSVALUE +#endif + +#if defined(AVS_WINDOWS) +// Windows XP does not have proper initialization for +// thread local variables. +// Use workaround instead __declspec(thread) +#define XP_TLS +#endif + +#endif //AVS_CONFIG_H diff --git a/src/avs/cpuid.h b/src/avs/cpuid.h new file mode 100644 index 0000000..024e843 --- /dev/null +++ b/src/avs/cpuid.h @@ -0,0 +1,81 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or visit +// http://www.gnu.org/copyleft/gpl.html . +// +// Linking Avisynth statically or dynamically with other modules is making a +// combined work based on Avisynth. Thus, the terms and conditions of the GNU +// General Public License cover the whole combination. +// +// As a special exception, the copyright holders of Avisynth give you +// permission to link Avisynth with independent modules that communicate with +// Avisynth solely through the interfaces defined in avisynth.h, regardless of the license +// terms of these independent modules, and to copy and distribute the +// resulting combined work under terms of your choice, provided that +// every copy of the combined work is accompanied by a complete copy of +// the source code of Avisynth (the version of Avisynth used to produce the +// combined work), being distributed under the terms of the GNU General +// Public License plus this exception. An independent module is a module +// which is not derived from or based on Avisynth, such as 3rd-party filters, +// import and export plugins, or graphical user interfaces. + +#ifndef AVSCORE_CPUID_H +#define AVSCORE_CPUID_H + +// For GetCPUFlags. These are backwards-compatible with those in VirtualDub. +// ending with SSE4_2 +// For emulation see https://software.intel.com/en-us/articles/intel-software-development-emulator +enum { + /* oldest CPU to support extension */ + CPUF_FORCE = 0x01, // N/A + CPUF_FPU = 0x02, // 386/486DX + CPUF_MMX = 0x04, // P55C, K6, PII + CPUF_INTEGER_SSE = 0x08, // PIII, Athlon + CPUF_SSE = 0x10, // PIII, Athlon XP/MP + CPUF_SSE2 = 0x20, // PIV, K8 + CPUF_3DNOW = 0x40, // K6-2 + CPUF_3DNOW_EXT = 0x80, // Athlon + CPUF_X86_64 = 0xA0, // Hammer (note: equiv. to 3DNow + SSE2, which + // only Hammer will have anyway) + CPUF_SSE3 = 0x100, // PIV+, K8 Venice + CPUF_SSSE3 = 0x200, // Core 2 + CPUF_SSE4 = 0x400, + CPUF_SSE4_1 = 0x400, // Penryn, Wolfdale, Yorkfield + CPUF_AVX = 0x800, // Sandy Bridge, Bulldozer + CPUF_SSE4_2 = 0x1000, // Nehalem + // AVS+ + CPUF_AVX2 = 0x2000, // Haswell + CPUF_FMA3 = 0x4000, + CPUF_F16C = 0x8000, + CPUF_MOVBE = 0x10000, // Big Endian move + CPUF_POPCNT = 0x20000, + CPUF_AES = 0x40000, + CPUF_FMA4 = 0x80000, + + CPUF_AVX512F = 0x100000, // AVX-512 Foundation. + CPUF_AVX512DQ = 0x200000, // AVX-512 DQ (Double/Quad granular) Instructions + CPUF_AVX512PF = 0x400000, // AVX-512 Prefetch + CPUF_AVX512ER = 0x800000, // AVX-512 Exponential and Reciprocal + CPUF_AVX512CD = 0x1000000, // AVX-512 Conflict Detection + CPUF_AVX512BW = 0x2000000, // AVX-512 BW (Byte/Word granular) Instructions + CPUF_AVX512VL = 0x4000000, // AVX-512 VL (128/256 Vector Length) Extensions + CPUF_AVX512IFMA = 0x8000000, // AVX-512 IFMA integer 52 bit + CPUF_AVX512VBMI = 0x10000000,// AVX-512 VBMI +}; + +#ifdef BUILDING_AVSCORE +int GetCPUFlags(); +void SetMaxCPU(int new_flags); +#endif + +#endif // AVSCORE_CPUID_H diff --git a/src/avs/filesystem.h b/src/avs/filesystem.h new file mode 100644 index 0000000..8544fd5 --- /dev/null +++ b/src/avs/filesystem.h @@ -0,0 +1,15 @@ +#pragma once + +// Snippet copied from filesystem/README.md + +#if defined(__cplusplus) && __cplusplus >= 201703L && defined(__has_include) +#if __has_include() +#define GHC_USE_STD_FS +#include +namespace fs = std::filesystem; +#endif +#endif +#ifndef GHC_USE_STD_FS +#include +namespace fs = ghc::filesystem; +#endif diff --git a/src/avs/minmax.h b/src/avs/minmax.h new file mode 100644 index 0000000..521ea58 --- /dev/null +++ b/src/avs/minmax.h @@ -0,0 +1,54 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or visit +// http://www.gnu.org/copyleft/gpl.html . +// +// Linking Avisynth statically or dynamically with other modules is making a +// combined work based on Avisynth. Thus, the terms and conditions of the GNU +// General Public License cover the whole combination. +// +// As a special exception, the copyright holders of Avisynth give you +// permission to link Avisynth with independent modules that communicate with +// Avisynth solely through the interfaces defined in avisynth.h, regardless of the license +// terms of these independent modules, and to copy and distribute the +// resulting combined work under terms of your choice, provided that +// every copy of the combined work is accompanied by a complete copy of +// the source code of Avisynth (the version of Avisynth used to produce the +// combined work), being distributed under the terms of the GNU General +// Public License plus this exception. An independent module is a module +// which is not derived from or based on Avisynth, such as 3rd-party filters, +// import and export plugins, or graphical user interfaces. + +#ifndef AVSCORE_MINMAX_H +#define AVSCORE_MINMAX_H + +template +T min(T v1, T v2) +{ + return v1 < v2 ? v1 : v2; +} + +template +T max(T v1, T v2) +{ + return v1 > v2 ? v1 : v2; +} + +template +T clamp(T n, T min, T max) +{ + n = n > max ? max : n; + return n < min ? min : n; +} + +#endif // AVSCORE_MINMAX_H diff --git a/src/avs/posix.h b/src/avs/posix.h new file mode 100644 index 0000000..3f72642 --- /dev/null +++ b/src/avs/posix.h @@ -0,0 +1,129 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or visit +// http://www.gnu.org/copyleft/gpl.html . +// +// Linking Avisynth statically or dynamically with other modules is making a +// combined work based on Avisynth. Thus, the terms and conditions of the GNU +// General Public License cover the whole combination. +// +// As a special exception, the copyright holders of Avisynth give you +// permission to link Avisynth with independent modules that communicate with +// Avisynth solely through the interfaces defined in avisynth.h, regardless of the license +// terms of these independent modules, and to copy and distribute the +// resulting combined work under terms of your choice, provided that +// every copy of the combined work is accompanied by a complete copy of +// the source code of Avisynth (the version of Avisynth used to produce the +// combined work), being distributed under the terms of the GNU General +// Public License plus this exception. An independent module is a module +// which is not derived from or based on Avisynth, such as 3rd-party filters, +// import and export plugins, or graphical user interfaces. + +#ifdef AVS_POSIX +#ifndef AVSCORE_POSIX_H +#define AVSCORE_POSIX_H + +#ifdef __cplusplus +#include +#endif +#include +#include + +// Define these MSVC-extension used in Avisynth +#define __single_inheritance + +// These things don't exist in Linux +#if defined(AVS_HAIKU) +#undef __declspec +#endif +#define __declspec(x) +#define lstrlen strlen +#define lstrcmp strcmp +#define lstrcmpi strcasecmp +#define _stricmp strcasecmp +#define _strnicmp strncasecmp +#define _strdup strdup +#define SetCurrentDirectory(x) chdir(x) +#define SetCurrentDirectoryW(x) chdir(x) +#define GetCurrentDirectoryW(x) getcwd(x) +#define _putenv putenv +#define _alloca alloca + +// Borrowing some compatibility macros from AvxSynth, slightly modified +#define UInt32x32To64(a, b) ((uint64_t)(((uint64_t)((uint32_t)(a))) * ((uint32_t)(b)))) +#define Int64ShrlMod32(a, b) ((uint64_t)((uint64_t)(a) >> (b))) +#define Int32x32To64(a, b) ((int64_t)(((int64_t)((long)(a))) * ((long)(b)))) + +#define InterlockedIncrement(x) __sync_add_and_fetch((x), 1) +#define InterlockedDecrement(x) __sync_sub_and_fetch((x), 1) +#define MulDiv(nNumber, nNumerator, nDenominator) (int32_t) (((int64_t) (nNumber) * (int64_t) (nNumerator) + (int64_t) ((nDenominator)/2)) / (int64_t) (nDenominator)) + +#ifndef TRUE +#define TRUE true +#endif + +#ifndef FALSE +#define FALSE false +#endif + +#define S_FALSE (0x00000001) +#define E_FAIL (0x80004005) +#define FAILED(hr) ((hr) & 0x80000000) +#define SUCCEEDED(hr) (!FAILED(hr)) + +// Statuses copied from comments in exception.cpp +#define STATUS_GUARD_PAGE_VIOLATION 0x80000001 +#define STATUS_DATATYPE_MISALIGNMENT 0x80000002 +#define STATUS_BREAKPOINT 0x80000003 +#define STATUS_SINGLE_STEP 0x80000004 +#define STATUS_ACCESS_VIOLATION 0xc0000005 +#define STATUS_IN_PAGE_ERROR 0xc0000006 +#define STATUS_INVALID_HANDLE 0xc0000008 +#define STATUS_NO_MEMORY 0xc0000017 +#define STATUS_ILLEGAL_INSTRUCTION 0xc000001d +#define STATUS_NONCONTINUABLE_EXCEPTION 0xc0000025 +#define STATUS_INVALID_DISPOSITION 0xc0000026 +#define STATUS_ARRAY_BOUNDS_EXCEEDED 0xc000008c +#define STATUS_FLOAT_DENORMAL_OPERAND 0xc000008d +#define STATUS_FLOAT_DIVIDE_BY_ZERO 0xc000008e +#define STATUS_FLOAT_INEXACT_RESULT 0xc000008f +#define STATUS_FLOAT_INVALID_OPERATION 0xc0000090 +#define STATUS_FLOAT_OVERFLOW 0xc0000091 +#define STATUS_FLOAT_STACK_CHECK 0xc0000092 +#define STATUS_FLOAT_UNDERFLOW 0xc0000093 +#define STATUS_INTEGER_DIVIDE_BY_ZERO 0xc0000094 +#define STATUS_INTEGER_OVERFLOW 0xc0000095 +#define STATUS_PRIVILEGED_INSTRUCTION 0xc0000096 +#define STATUS_STACK_OVERFLOW 0xc00000fd + +// Calling convension +#ifndef AVS_HAIKU +#define __stdcall +#define __cdecl +#endif + +// PowerPC OS X is really niche these days, but this painless equivocation +// of the function/macro names used in posix_get_available_memory() +// is all it takes to let it work. The G5 was 64-bit, and if 10.5 Leopard +// can run in native 64-bit, it probably uses the names in that block as-is. +#ifdef AVS_MACOS +#ifdef PPC32 +#define vm_statistics64_data_t vm_statistics_data_t +#define HOST_VM_INFO64_COUNT HOST_VM_INFO_COUNT +#define HOST_VM_INFO64 HOST_VM_INFO +#define host_statistics64 host_statistics +#endif // PPC32 +#endif // AVS_MACOS + +#endif // AVSCORE_POSIX_H +#endif // AVS_POSIX diff --git a/src/avs/types.h b/src/avs/types.h new file mode 100644 index 0000000..19cc455 --- /dev/null +++ b/src/avs/types.h @@ -0,0 +1,54 @@ +// Avisynth C Interface Version 0.20 +// Copyright 2003 Kevin Atkinson + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or visit +// http://www.gnu.org/copyleft/gpl.html . +// +// As a special exception, I give you permission to link to the +// Avisynth C interface with independent modules that communicate with +// the Avisynth C interface solely through the interfaces defined in +// avisynth_c.h, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting combined work +// under terms of your choice, provided that every copy of the +// combined work is accompanied by a complete copy of the source code +// of the Avisynth C interface and Avisynth itself (with the version +// used to produce the combined work), being distributed under the +// terms of the GNU General Public License plus this exception. An +// independent module is a module which is not derived from or based +// on Avisynth C Interface, such as 3rd-party filters, import and +// export plugins, or graphical user interfaces. + +#ifndef AVS_TYPES_H +#define AVS_TYPES_H + +// Define all types necessary for interfacing with avisynth.dll +#include +#include +#ifdef __cplusplus + #include + #include +#else + #include + #include +#endif + +// Raster types used by VirtualDub & Avisynth +typedef uint32_t Pixel32; +typedef uint8_t BYTE; + +// Audio Sample information +typedef float SFLOAT; + +#endif //AVS_TYPES_H diff --git a/src/avs/win.h b/src/avs/win.h new file mode 100644 index 0000000..6692021 --- /dev/null +++ b/src/avs/win.h @@ -0,0 +1,54 @@ +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or visit +// http://www.gnu.org/copyleft/gpl.html . +// +// Linking Avisynth statically or dynamically with other modules is making a +// combined work based on Avisynth. Thus, the terms and conditions of the GNU +// General Public License cover the whole combination. +// +// As a special exception, the copyright holders of Avisynth give you +// permission to link Avisynth with independent modules that communicate with +// Avisynth solely through the interfaces defined in avisynth.h, regardless of the license +// terms of these independent modules, and to copy and distribute the +// resulting combined work under terms of your choice, provided that +// every copy of the combined work is accompanied by a complete copy of +// the source code of Avisynth (the version of Avisynth used to produce the +// combined work), being distributed under the terms of the GNU General +// Public License plus this exception. An independent module is a module +// which is not derived from or based on Avisynth, such as 3rd-party filters, +// import and export plugins, or graphical user interfaces. + +#ifndef AVSCORE_WIN_H +#define AVSCORE_WIN_H + +// Whenever you need windows headers, start by including this file, then the rest. + +// WWUUT? We require XP now? +#if !defined(NTDDI_VERSION) && !defined(_WIN32_WINNT) + #define NTDDI_VERSION 0x05020000 + #define _WIN32_WINNT 0x0502 +#endif + +#define WIN32_LEAN_AND_MEAN +#define STRICT +#if !defined(NOMINMAX) + #define NOMINMAX +#endif + +#include + +// Provision for UTF-8 max 4 bytes per code point +#define AVS_MAX_PATH MAX_PATH*4 + +#endif // AVSCORE_WIN_H diff --git a/src/avsutl/CsPlane.cpp b/src/avsutl/CsPlane.cpp new file mode 100644 index 0000000..b99bda0 --- /dev/null +++ b/src/avsutl/CsPlane.cpp @@ -0,0 +1,123 @@ +/***************************************************************************** + + CsPlane.cpp + Author: Laurent de Soras, 2021 + +--- Legal stuff --- + +This program is free software. It comes without any warranty, to +the extent permitted by applicable law. You can redistribute it +and/or modify it under the terms of the Do What The Fuck You Want +To Public License, Version 2, as published by Sam Hocevar. See +http://www.wtfpl.net/ for more details. + +*Tab=3***********************************************************************/ + + + +#if defined (_MSC_VER) + #pragma warning (1 : 4130 4223 4705 4706) + #pragma warning (4 : 4355 4786 4800) +#endif + + + +/*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +#include "avsutl/CsPlane.h" +#include "avisynth.h" + +#include + + + +namespace avsutl +{ + + + +/*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + + + +constexpr int CsPlane::_max_nbr_planes; +constexpr int CsPlane::_plane_index_alpha; + + + +CsPlane::CategCs CsPlane::get_cs_categ (const ::VideoInfo &vi) noexcept +{ + return vi.IsRGB () ? CategCs_RGB : CategCs_YUV; +} + + + +const CsPlane::CategInfo & CsPlane::use_categ_info (const ::VideoInfo &vi) noexcept +{ + const CategCs categ = get_cs_categ (vi); + + return _plane_info_list [categ]; +} + + + +const CsPlane::PlaneInfo & CsPlane::use_plane_info (int plane_index, const ::VideoInfo &vi) noexcept +{ + assert (plane_index >= 0); + assert (plane_index < _max_nbr_planes); + assert (plane_index < vi.NumComponents ()); + + const auto & categ_info = use_categ_info (vi); + + return categ_info [plane_index]; +} + + + +int CsPlane::get_plane_id (int plane_index, const ::VideoInfo &vi) noexcept +{ + assert (plane_index >= 0); + assert (plane_index < _max_nbr_planes); + assert (plane_index < vi.NumComponents ()); + + const auto & plane_info = use_plane_info (plane_index, vi); + + return plane_info._id; +} + + + +const std::array < + CsPlane::CategInfo, + CsPlane::CategCs_NBR_ELT +> CsPlane::_plane_info_list = +{{ + {{ + { ::PLANAR_Y, 'y' }, + { ::PLANAR_U, 'u' }, + { ::PLANAR_V, 'v' }, + { ::PLANAR_A, 'a' } + }}, + {{ + { ::PLANAR_R, 'r' }, + { ::PLANAR_G, 'g' }, + { ::PLANAR_B, 'b' }, + { ::PLANAR_A, 'a' } + }} +}}; + + + +/*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + + + +/*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + + + +} // namespace avsutl + + + +/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ diff --git a/src/avsutl/CsPlane.h b/src/avsutl/CsPlane.h new file mode 100644 index 0000000..69d9b8f --- /dev/null +++ b/src/avsutl/CsPlane.h @@ -0,0 +1,116 @@ +/***************************************************************************** + + CsPlane.h + Author: Laurent de Soras, 2021 + +--- Legal stuff --- + +This program is free software. It comes without any warranty, to +the extent permitted by applicable law. You can redistribute it +and/or modify it under the terms of the Do What The Fuck You Want +To Public License, Version 2, as published by Sam Hocevar. See +http://www.wtfpl.net/ for more details. + +*Tab=3***********************************************************************/ + + + +#pragma once +#if ! defined (avsutl_CsPlane_HEADER_INCLUDED) +#define avsutl_CsPlane_HEADER_INCLUDED + + + +/*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +#include + + + +struct VideoInfo; + +namespace avsutl +{ + + + +class CsPlane +{ + +/*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +public: + + static constexpr int _max_nbr_planes = 4; + static constexpr int _plane_index_alpha = 3; + + enum CategCs + { + CategCs_YUV = 0, + CategCs_RGB, + + CategCs_NBR_ELT + }; + + struct PlaneInfo + { + int _id; // PLANAR_? + char _name; // Lower case + }; + + typedef std::array CategInfo; + + static CategCs get_cs_categ (const ::VideoInfo &vi) noexcept; + static const CategInfo & + use_categ_info (const ::VideoInfo &vi) noexcept; + static const PlaneInfo & + use_plane_info (int plane_index, const ::VideoInfo &vi) noexcept; + static int get_plane_id (int plane_index, const ::VideoInfo &vi) noexcept; + + static const std::array + _plane_info_list; + + + +/*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +protected: + + + +/*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +private: + + + + +/*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +private: + + CsPlane () = delete; + CsPlane (const CsPlane &other) = delete; + CsPlane (CsPlane &&other) = delete; + CsPlane & operator = (const CsPlane &other) = delete; + CsPlane & operator = (CsPlane &&other) = delete; + bool operator == (const CsPlane &other) const = delete; + bool operator != (const CsPlane &other) const = delete; + +}; // class CsPlane + + + +} // namespace avsutl + + + +//#include "avsutl/CsPlane.hpp" + + + +#endif // avsutl_CsPlane_HEADER_INCLUDED + + + +/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ diff --git a/src/avsutl/PlaneProcCbInterface.cpp b/src/avsutl/PlaneProcCbInterface.cpp new file mode 100644 index 0000000..7341e44 --- /dev/null +++ b/src/avsutl/PlaneProcCbInterface.cpp @@ -0,0 +1,62 @@ +/***************************************************************************** + + PlaneProcCbInterface.cpp + Author: Laurent de Soras, 2021 + +--- Legal stuff --- + +This program is free software. It comes without any warranty, to +the extent permitted by applicable law. You can redistribute it +and/or modify it under the terms of the Do What The Fuck You Want +To Public License, Version 2, as published by Sam Hocevar. See +http://www.wtfpl.net/ for more details. + +*Tab=3***********************************************************************/ + + + +#if defined (_MSC_VER) + #pragma warning (1 : 4130 4223 4705 4706) + #pragma warning (4 : 4355 4786 4800) +#endif + + + +/*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +#include "avsutl/PlaneProcCbInterface.h" +#include "avisynth.h" + +#include + + + +namespace avsutl +{ + + + +/*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + + + +void PlaneProcCbInterface::process_plane (::PVideoFrame &dst_sptr, int n, ::IScriptEnvironment &env, int plane_index, int plane_id, void *ctx_ptr) +{ + assert (dst_sptr != nullptr); + assert (n >= 0); + assert (plane_index >= 0); + + do_process_plane (dst_sptr, n, env, plane_index, plane_id, ctx_ptr); +} + + + +/*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + + + +} // namespace avsutl + + + +/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ diff --git a/src/avsutl/PlaneProcCbInterface.h b/src/avsutl/PlaneProcCbInterface.h new file mode 100644 index 0000000..514994d --- /dev/null +++ b/src/avsutl/PlaneProcCbInterface.h @@ -0,0 +1,85 @@ +/***************************************************************************** + + PlaneProcCbInterface.h + Author: Laurent de Soras, 2021 + +--- Legal stuff --- + +This program is free software. It comes without any warranty, to +the extent permitted by applicable law. You can redistribute it +and/or modify it under the terms of the Do What The Fuck You Want +To Public License, Version 2, as published by Sam Hocevar. See +http://www.wtfpl.net/ for more details. + +*Tab=3***********************************************************************/ + + + +#pragma once +#if ! defined (avsutl_PlaneProcCbInterface_HEADER_INCLUDED) +#define avsutl_PlaneProcCbInterface_HEADER_INCLUDED + + + +/*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + + + +class IScriptEnvironment; +class PVideoFrame; + +namespace avsutl +{ + + + +class PlaneProcCbInterface +{ + +/*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +public: + + PlaneProcCbInterface () = default; + virtual ~PlaneProcCbInterface () = default; + + void process_plane (::PVideoFrame &dst_sptr, int n, ::IScriptEnvironment &env, int plane_index, int plane_id, void *ctx_ptr); + + + +/*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +protected: + + virtual void do_process_plane (::PVideoFrame &dst_sptr, int n, ::IScriptEnvironment &env, int plane_index, int plane_id, void *ctx_ptr) = 0; + + + +/*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +private: + + PlaneProcCbInterface (const PlaneProcCbInterface &other) = delete; + PlaneProcCbInterface (PlaneProcCbInterface &&other) = delete; + PlaneProcCbInterface & + operator = (const PlaneProcCbInterface &other) = delete; + PlaneProcCbInterface & + operator = (PlaneProcCbInterface &&other) = delete; + +}; // class PlaneProcCbInterface + + + +} // namespace avsutl + + + +//#include "avsutl/PlaneProcCbInterface.hpp" + + + +#endif // avsutl_PlaneProcCbInterface_HEADER_INCLUDED + + + +/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ diff --git a/src/avsutl/PlaneProcMode.h b/src/avsutl/PlaneProcMode.h new file mode 100644 index 0000000..f7da722 --- /dev/null +++ b/src/avsutl/PlaneProcMode.h @@ -0,0 +1,60 @@ +/***************************************************************************** + + PlaneProcMode.h + Author: Laurent de Soras, 2021 + +--- Legal stuff --- + +This program is free software. It comes without any warranty, to +the extent permitted by applicable law. You can redistribute it +and/or modify it under the terms of the Do What The Fuck You Want +To Public License, Version 2, as published by Sam Hocevar. See +http://www.wtfpl.net/ for more details. + +*Tab=3***********************************************************************/ + + + +#pragma once +#if ! defined (avsutl_PlaneProcMode_HEADER_INCLUDED) +#define avsutl_PlaneProcMode_HEADER_INCLUDED + + + +/*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + + + +namespace avsutl +{ + + + +enum PlaneProcMode +{ + PlaneProcMode_FILL = 0, + PlaneProcMode_GARBAGE, + PlaneProcMode_COPY1, + PlaneProcMode_PROCESS, + PlaneProcMode_COPY2, + PlaneProcMode_COPY3, + + PlaneProcMode_NBR_ELT + +}; // enum PlaneProcMode + + + +} // namespace avsutl + + + +//#include "avsutl/PlaneProcMode.hpp" + + + +#endif // avsutl_PlaneProcMode_HEADER_INCLUDED + + + +/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ diff --git a/src/avsutl/PlaneProcessor.cpp b/src/avsutl/PlaneProcessor.cpp new file mode 100644 index 0000000..46a4f47 --- /dev/null +++ b/src/avsutl/PlaneProcessor.cpp @@ -0,0 +1,757 @@ +/***************************************************************************** + + PlaneProcessor.cpp + Author: Laurent de Soras, 2021 + +--- Legal stuff --- + +This program is free software. It comes without any warranty, to +the extent permitted by applicable law. You can redistribute it +and/or modify it under the terms of the Do What The Fuck You Want +To Public License, Version 2, as published by Sam Hocevar. See +http://www.wtfpl.net/ for more details. + +*Tab=3***********************************************************************/ + + + +#if defined (_MSC_VER) + #pragma warning (1 : 4130 4223 4705 4706) + #pragma warning (4 : 4355 4786 4800) +#endif + + + +/*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +#include "avsutl/fnc.h" +#include "avsutl/PlaneProcCbInterface.h" +#include "avsutl/PlaneProcessor.h" +#include "fstb/fnc.h" +#include "avisynth.h" + +#include + +#include +#include + + + +namespace avsutl +{ + + + +/*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + + + +PlaneProcessor::PlaneProcessor (const ::VideoInfo &vi, const ::VideoInfo &vi_src, PlaneProcCbInterface &cb) +: _vi (vi) +, _vi_src (vi_src) +, _cb (cb) +, _nbr_planes (get_nbr_planes (vi)) +{ + // Nothing +} + + + +void PlaneProcessor::set_proc_mode (const std::array &pm_arr) +{ + _proc_mode_arr = pm_arr; +} + + + +// Accepts: +// y, u, v, a +// r, g, b, a +// 0, 1, 2, 3 +void PlaneProcessor::set_proc_mode (std::string pmode) +{ + fstb::conv_to_lower_case (pmode); + + if (pmode == "all") + { + _proc_mode_arr.fill (float (PlaneProcMode_PROCESS)); + } + else + { + _proc_mode_arr.fill (float (PlaneProcMode_GARBAGE)); + + // Plane selection by name + for (const auto &info_categ : CsPlane::_plane_info_list) + { + for (size_t plane_idx = 0; plane_idx < info_categ.size (); ++plane_idx) + { + const auto & plane = info_categ [plane_idx]; + if (pmode.find (plane._name) != std::string::npos) + { + _proc_mode_arr [plane_idx] = PlaneProcMode_PROCESS; + } + } + } + + // Plane selection by numeric index + for (int plane_idx = 0; plane_idx < _max_nbr_planes; ++plane_idx) + { + const auto name = char ('0' + plane_idx); + if (pmode.find (name) != std::string::npos) + { + _proc_mode_arr [plane_idx] = PlaneProcMode_PROCESS; + } + } + } +} + + + +// 0 = destination clip +void PlaneProcessor::set_clip_info (int index, ClipType type) +{ + assert (index >= 0); + assert (index < _max_nbr_clips); + assert (type >= 0); + assert (type < ClipType_NBR_ELT); + + // If the clip is one of the "hack-16" type, make sure it is 8 bits. + assert ( (type == ClipType_NORMAL) + || (index == 0 && _vi.ComponentSize () == 1) + || (index > 0 && _vi_src.ComponentSize () == 1)); + + _clip_type_arr [index] = type; +} + + + +int PlaneProcessor::get_nbr_planes () const +{ + return _nbr_planes; +} + + + +void PlaneProcessor::process_frame (::PVideoFrame &dst_sptr, int n, ::IScriptEnvironment &env, ::PClip *src_1_ptr, ::PClip *src_2_ptr, ::PClip *src_3_ptr, void *ctx_ptr) +{ + assert (dst_sptr != nullptr); + assert (dst_sptr->IsWritable ()); + assert (n >= 0); + + const ClipType type_dst = _clip_type_arr [0]; + const auto & info_categ = CsPlane::use_categ_info (_vi); + + for (int plane_index = 0; plane_index < _nbr_planes; ++plane_index) + { + const int plane_id = info_categ [plane_index]._id; + const float mode = _proc_mode_arr [plane_index]; + + if (mode == float (PlaneProcMode_PROCESS)) + { + _cb.process_plane (dst_sptr, n, env, plane_index, plane_id, ctx_ptr); + } + + else if ( mode >= float (PlaneProcMode_COPY1) + && mode <= float (PlaneProcMode_COPY3)) + { + static const int burp [PlaneProcMode_NBR_ELT] = + { + -1, -1, 1, -1, 2, 3 + }; + const int mode_i = fstb::round_int (mode); + const int src_index = burp [mode_i]; + ::PClip * pouet [4] = { 0, src_1_ptr, src_2_ptr, src_3_ptr }; + ::PClip * src_ptr = pouet [src_index]; + const ClipType type_src = _clip_type_arr [src_index]; + + if (src_ptr != nullptr) + { + copy (dst_sptr, n, plane_id, type_dst, *src_ptr, type_src, env); + } + } + + else if (mode < float (PlaneProcMode_FILL + 1)) + { + fill (dst_sptr, n, plane_id, type_dst, -mode); + } + } +} + + + +int PlaneProcessor::get_plane_id (int plane_index, bool src_flag) +{ + return CsPlane::get_plane_id (plane_index, *(src_flag ? &_vi_src : &_vi)); +} + + + +int PlaneProcessor::get_width (const ::PVideoFrame &frame_sptr, int plane_id, bool src_flag) const +{ + assert (frame_sptr != nullptr); + + const int width_bytes = frame_sptr->GetRowSize (plane_id); + const int bits = + (src_flag) ? _vi_src.BitsPerComponent () : _vi.BitsPerComponent (); + const int width = width_bytes / (bits >> 3); + + return width; +} + + + +int PlaneProcessor::get_height (const ::PVideoFrame &frame_sptr, int plane_id) const +{ + assert (frame_sptr != nullptr); + + const int height = frame_sptr->GetHeight (plane_id); + + return height; +} + + + +int PlaneProcessor::get_height16 (const ::PVideoFrame &frame_sptr, int plane_id) const +{ + return get_height (frame_sptr, plane_id) >> 1; +} + + + +int PlaneProcessor::get_nbr_planes (const ::VideoInfo &vi) +{ + return vi.NumComponents (); +} + + + +int PlaneProcessor::get_bytes_per_component (const ::VideoInfo &vi) +{ + return vi.ComponentSize (); +} + + + +int PlaneProcessor::get_min_w (const ::VideoInfo &vi) +{ + int l = vi.width; + const int nbr_planes = get_nbr_planes (vi); + for (int index = 1; index < nbr_planes; ++index) + { + const int lc = compute_plane_w (vi, index, vi.width); + l = std::min (l, lc); + } + + return l; +} + + + +int PlaneProcessor::get_min_h (const ::VideoInfo &vi, bool stack16_flag) +{ + assert (! stack16_flag || vi.BitsPerComponent () == 8); + + int l = vi.height; + const int nbr_planes = get_nbr_planes (vi); + for (int index = 1; index < nbr_planes; ++index) + { + const int lc = compute_plane_h (vi, index, vi.height); + l = std::min (l, lc); + } + if (stack16_flag) + { + assert ((l & 1) == 0); + l >>= 1; + } + + return l; +} + + + +int PlaneProcessor::compute_plane_w (const ::VideoInfo &vi, int plane_index, int w) +{ + assert (plane_index >= 0); + assert (plane_index < _max_nbr_planes); + assert (w > 0); + + int l = w; + const int plane_id = CsPlane::get_plane_id (plane_index, vi); + const int subspl = vi.GetPlaneWidthSubsampling (plane_id); + l >>= subspl; + + return l; +} + + + +int PlaneProcessor::compute_plane_h (const ::VideoInfo &vi, int plane_index, int h) +{ + assert (plane_index >= 0); + assert (plane_index < _max_nbr_planes); + assert (h > 0); + + int l = h; + const int plane_id = CsPlane::get_plane_id (plane_index, vi); + const int subspl = vi.GetPlaneHeightSubsampling (plane_id); + l >>= subspl; + + return l; +} + + + +void PlaneProcessor::check_same_format (::IScriptEnvironment *env_ptr, const ::VideoInfo &vi, const ::PClip tst_sptr, const char *fnc_name_0, const char *arg_name_0, int flags) +{ + assert (env_ptr != 0); + assert (tst_sptr != 0); + assert (fnc_name_0 != 0); + assert (arg_name_0 != 0); + + const ::VideoInfo & vi_tst = tst_sptr->GetVideoInfo (); + + static char txt_0 [4095+1]; + + if ( vi_tst.height != vi.height + && (flags & FmtChkFlag_H) != 0) + { + fstb::snprintf4all ( + txt_0, sizeof (txt_0), + "%s: clip \"%s\" has a height of %d instead of %d.", + fnc_name_0, arg_name_0, vi_tst.height, vi.height + ); + env_ptr->ThrowError (txt_0); + } + + if ( (flags & FmtChkFlag_W) != 0 + && vi_tst.width != vi.width) + { + fstb::snprintf4all ( + txt_0, sizeof (txt_0), + "%s: clip \"%s\" has a width of %d instead of %d.", + fnc_name_0, arg_name_0, vi_tst.width, vi.width + ); + env_ptr->ThrowError (txt_0); + } + + if ( (flags & FmtChkFlag_NBR_FRAMES) != 0 + && vi_tst.num_frames != vi.num_frames) + { + fstb::snprintf4all ( + txt_0, sizeof (txt_0), + "%s: clip \"%s\" has %d frames instead of %d.", + fnc_name_0, arg_name_0, vi_tst.num_frames, vi.num_frames + ); + env_ptr->ThrowError (txt_0); + } + + // Tests absolute colorspace equality + if ((flags & FmtChkFlag_CS_ALL) == FmtChkFlag_CS_ALL) + { + if (! vi_tst.IsSameColorspace (vi)) + { + fstb::snprintf4all ( + txt_0, sizeof (txt_0), + "%s: clip \"%s\" has not the same colorspace (code %X instead of %X).", + fnc_name_0, arg_name_0, vi_tst.pixel_type, vi.pixel_type + ); + env_ptr->ThrowError (txt_0); + } + } + + // Tests only specific colorspace features + else + { + if ( (flags & FmtChkFlag_CS_TYPE) != 0 + && ( vi_tst.IsRGB () != vi.IsRGB () + || (vi.IsRGB () && vi_tst.IsRGB24 () != vi.IsRGB24 ()))) + { + fstb::snprintf4all ( + txt_0, sizeof (txt_0), + "%s: clip \"%s\" has a wrong pixel type.", + fnc_name_0, arg_name_0 + ); + env_ptr->ThrowError (txt_0); + } + if ( (flags & FmtChkFlag_CS_LAYOUT) != 0 + && vi_tst.IsPlanar () != vi.IsPlanar ()) + { + fstb::snprintf4all ( + txt_0, sizeof (txt_0), + "%s: clip \"%s\" has a wrong planarity.", + fnc_name_0, arg_name_0 + ); + env_ptr->ThrowError (txt_0); + } + // Hahaha! The following test is unreadable. Basically, it makes + // Y compatible with any other YUV colorspace (planar or not). + if ( (flags & FmtChkFlag_CS_SUBSPL) != 0 + && ( (vi_tst.IsYUV () || vi_tst.IsYUVA ()) != (vi.IsYUV () || vi.IsYUVA ()) + || ( ((vi.IsYUV () || vi.IsYUVA ()) && ! vi.IsY () && ! vi_tst.IsY ()) + && ( vi_tst.GetPlaneWidthSubsampling (PLANAR_U) != vi.GetPlaneWidthSubsampling (PLANAR_U) + || vi_tst.GetPlaneHeightSubsampling (PLANAR_U) != vi.GetPlaneHeightSubsampling (PLANAR_U) + ) + ) + ) + ) + { + fstb::snprintf4all ( + txt_0, sizeof (txt_0), + "%s: clip \"%s\" has a wrong chroma subsampling.", + fnc_name_0, arg_name_0 + ); + env_ptr->ThrowError (txt_0); + } + if ( (flags & FmtChkFlag_CS_FORMAT) != 0 + && vi_tst.BitsPerComponent () != vi.BitsPerComponent ()) + { + fstb::snprintf4all ( + txt_0, sizeof (txt_0), + "%s: clip \"%s\" has a wrong data format.", + fnc_name_0, arg_name_0 + ); + env_ptr->ThrowError (txt_0); + } + if ( (flags & FmtChkFlag_CS_NBRCOMP) != 0 + && vi_tst.NumComponents () != vi.NumComponents ()) + { + fstb::snprintf4all ( + txt_0, sizeof (txt_0), + "%s: clip \"%s\" has a wrong number of components.", + fnc_name_0, arg_name_0 + ); + env_ptr->ThrowError (txt_0); + } + } +} + + + +bool PlaneProcessor::check_stack16_width (const ::VideoInfo &vi, int width) +{ + assert (vi.BitsPerComponent () == 8); + + if (width < 0) + { + width = vi.width; + } + + bool ok_flag = true; + + const int nbr_planes = get_nbr_planes (vi); + const auto & info_categ = CsPlane::use_categ_info (vi); + for (int index = 0; index < nbr_planes && ok_flag; ++index) + { + const int plane_id = info_categ [index]._id; + const int subspl = vi.GetPlaneWidthSubsampling (plane_id); + const int mask = (1 << subspl) - 1; + if ((width & mask) != 0) + { + ok_flag = false; + } + } + + return ok_flag; +} + + + +bool PlaneProcessor::check_stack16_height (const ::VideoInfo &vi, int height) +{ + assert (vi.BitsPerComponent () == 8); + + if (height < 0) + { + height = vi.height; + } + + bool ok_flag = ((height & 1) == 0); + + const int nbr_planes = get_nbr_planes (vi); + const auto & info_categ = CsPlane::use_categ_info (vi); + for (int index = 0; index < nbr_planes && ok_flag; ++index) + { + const int plane_id = info_categ [index]._id; + const int subspl = vi.GetPlaneHeightSubsampling (plane_id); + const int mask = (2 << subspl) - 1; + if ((height & mask) != 0) + { + ok_flag = false; + } + } + + return ok_flag; +} + + + +/*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + + + +/*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + + + +void PlaneProcessor::fill (::PVideoFrame &dst_sptr, int n, int plane_id, ClipType type, float val) +{ + assert (dst_sptr != nullptr); + assert (n >= 0); + assert (type >= 0); + + if (type == ClipType_STACKED_16) + { + const int val_int = fstb::round_int (val); + const int val_msb = val_int >> 8; + const int val_lsb = val_int & 255; + fill_frame_part (dst_sptr, n, plane_id, float (val_msb), true, 0); + fill_frame_part (dst_sptr, n, plane_id, float (val_lsb), true, 1); + } + + else if (type == ClipType_INTERLEAVED_16) + { + int val_int = fstb::round_int (val); + val_int >>= (1 - (n & 1)) * 8; + fill_frame_part (dst_sptr, n, plane_id, float (val_int & 255), false, 0); + } + + else + { + fill_frame_part (dst_sptr, n, plane_id, val, false, 0); + } +} + + + +void PlaneProcessor::fill_frame_part (::PVideoFrame &dst_sptr, int n, int plane_id, float val, bool stacked_flag, int part) +{ + fstb::unused (n); + + const int stride = dst_sptr->GetPitch (plane_id); + const int width = get_width (dst_sptr, plane_id, false); + int height = get_height (dst_sptr, plane_id); + + if (_vi.ComponentSize () == 1) + { + uint8_t * data_ptr = dst_sptr->GetWritePtr (plane_id); + + if (stacked_flag && part != 0) + { + height >>= 1; + data_ptr += stride * height; + } + + if (height > 0) + { + const auto val_int = uint8_t (fstb::round_int (val)); + avsutl::fill_block (data_ptr, val_int, stride, width, height); + } + else + { + assert (false); + } + } + + else if (_vi.ComponentSize () == 2) + { + const auto val_int = uint16_t (fstb::round_int (val)); + auto data_ptr = dst_sptr->GetWritePtr (plane_id); + avsutl::fill_block (data_ptr, val_int, stride, width, height); + } + + else + { + assert (_vi.ComponentSize () == 4); + auto data_ptr = dst_sptr->GetWritePtr (plane_id); + avsutl::fill_block (data_ptr, val, stride, width, height); + } +} + + + +void PlaneProcessor::copy (::PVideoFrame &dst_sptr, int n, int plane_id, ClipType type_dst, ::PClip &src_clip, ClipType type_src, ::IScriptEnvironment &env) +{ + assert (dst_sptr != nullptr); + assert (n >= 0); + assert (type_dst >= 0); + assert (type_dst < ClipType_NBR_ELT); + assert (src_clip != nullptr); + assert (type_src >= 0); + assert (type_src < ClipType_NBR_ELT); + + if (src_clip != nullptr) + { + const int nbr_bytes_d = get_bytes_per_component (_vi); + const int nbr_bytes_s = + get_bytes_per_component (src_clip->GetVideoInfo ()); + + if (nbr_bytes_d == 1 && nbr_bytes_s == 1) + { + if (have_same_height (type_dst, type_src)) + { + if ( type_dst == ClipType_INTERLEAVED_16 + && type_src != ClipType_INTERLEAVED_16) + { + n >>= 1; + } + else if ( type_dst != ClipType_INTERLEAVED_16 + && type_src == ClipType_INTERLEAVED_16) + { + n <<= 1; + if (type_dst == ClipType_LSB) + { + ++ n; + } + } + + copy_n_to_n (dst_sptr, src_clip, n, plane_id, env); + } + + else if (is_stacked (type_src) && ! is_stacked (type_dst)) + { + bool lsb_flag = (type_dst == ClipType_LSB); + + if (type_dst == ClipType_INTERLEAVED_16) + { + lsb_flag = ((n & 1) != 0); + n >>= 1; + } + + copy_stack16_to_8 ( + dst_sptr, src_clip, n, plane_id, env, (lsb_flag) ? 1 : 0 + ); + } + + else // ! is_stacked (type_src) && is_stacked (type_dst) + { + if (type_src == ClipType_INTERLEAVED_16) + { + n <<= 1; + copy_8_to_stack16 (dst_sptr, src_clip, n, plane_id, env, 0); + copy_8_to_stack16 (dst_sptr, src_clip, n + 1, plane_id, env, 1); + } + + else + { + copy_8_to_stack16 (dst_sptr, src_clip, n, plane_id, env, 0); + fill_frame_part (dst_sptr, n, plane_id, 0, true, 1); + } + } + } + + else if (nbr_bytes_d == nbr_bytes_s) + { + copy_n_to_n (dst_sptr, src_clip, n, plane_id, env); + } + } +} + + + +void PlaneProcessor::copy_n_to_n (::PVideoFrame &dst_sptr, ::PClip &src_clip, int n, int plane_id, ::IScriptEnvironment &env) +{ + const int dst_stride = dst_sptr->GetPitch (plane_id); + const int dst_width = get_width (dst_sptr, plane_id, false); + const int dst_height = get_height (dst_sptr, plane_id); + uint8_t * dst_data_ptr = dst_sptr->GetWritePtr (plane_id); + + n = std::min (n, src_clip->GetVideoInfo ().num_frames - 1); + + ::PVideoFrame src_sptr = src_clip->GetFrame (n, &env); + const int src_stride = src_sptr->GetPitch (plane_id); + const int src_width = get_width (src_sptr, plane_id, true); + const int src_height = get_height (src_sptr, plane_id); + const uint8_t* src_data_ptr = src_sptr->GetReadPtr (plane_id); + + const int width = std::min (src_width, dst_width); + const int height = std::min (src_height, dst_height); + const int width_bytes = width * _vi.ComponentSize (); + + env.BitBlt ( + dst_data_ptr, dst_stride, + src_data_ptr, src_stride, width_bytes, height + ); +} + + + +void PlaneProcessor::copy_8_to_stack16 (::PVideoFrame &dst_sptr, ::PClip &src_clip, int n, int plane_id, ::IScriptEnvironment &env, int part) +{ + const int dst_stride = dst_sptr->GetPitch (plane_id); + const int dst_width = get_width (dst_sptr, plane_id, false); + const int dst_height = get_height16 (dst_sptr, plane_id); + uint8_t * dst_data_ptr = dst_sptr->GetWritePtr (plane_id); + + n = std::min (n, src_clip->GetVideoInfo ().num_frames - 1); + + ::PVideoFrame src_sptr = src_clip->GetFrame (n, &env); + const int src_stride = src_sptr->GetPitch (plane_id); + const int src_width = get_width (src_sptr, plane_id, true); + const int src_height = get_height (src_sptr, plane_id); + const uint8_t* src_data_ptr = src_sptr->GetReadPtr (plane_id); + + const int width = std::min (src_width, dst_width); + const int height = std::min (src_height, dst_height); + + env.BitBlt ( + dst_data_ptr + part * dst_height * dst_stride, dst_stride, + src_data_ptr, src_stride, width, height + ); +} + + + +void PlaneProcessor::copy_stack16_to_8 (::PVideoFrame &dst_sptr, ::PClip &src_clip, int n, int plane_id, ::IScriptEnvironment &env, int part) +{ + const int dst_stride = dst_sptr->GetPitch (plane_id); + const int dst_width = get_width (dst_sptr, plane_id, false); + const int dst_height = get_height (dst_sptr, plane_id); + uint8_t * dst_data_ptr = dst_sptr->GetWritePtr (plane_id); + + n = std::min (n, src_clip->GetVideoInfo ().num_frames - 1); + + ::PVideoFrame src_sptr = src_clip->GetFrame (n, &env); + const int src_stride = src_sptr->GetPitch (plane_id); + const int src_width = get_width (src_sptr, plane_id, true); + const int src_height = get_height16 (src_sptr, plane_id); + const uint8_t* src_data_ptr = src_sptr->GetReadPtr (plane_id); + + const int width = std::min (src_width, dst_width); + const int height = std::min (src_height, dst_height); + + env.BitBlt ( + dst_data_ptr, dst_stride, + src_data_ptr + part * src_height * src_stride, src_stride, + width, height + ); +} + + + +bool PlaneProcessor::have_same_height (ClipType t1, ClipType t2) +{ + assert (t1 >= 0); + assert (t1 < ClipType_NBR_ELT); + assert (t2 >= 0); + assert (t2 < ClipType_NBR_ELT); + + return (! (is_stacked (t1) ^ is_stacked (t2))); +} + + + +bool PlaneProcessor::is_stacked (ClipType type) +{ + assert (type >= 0); + assert (type < ClipType_NBR_ELT); + + return (type == ClipType_STACKED_16); +} + + + +} // namespace avsutl + + + +/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ diff --git a/src/avsutl/PlaneProcessor.h b/src/avsutl/PlaneProcessor.h new file mode 100644 index 0000000..eeeb554 --- /dev/null +++ b/src/avsutl/PlaneProcessor.h @@ -0,0 +1,181 @@ +/***************************************************************************** + + PlaneProcessor.h + Author: Laurent de Soras, 2021 + +--- Legal stuff --- + +This program is free software. It comes without any warranty, to +the extent permitted by applicable law. You can redistribute it +and/or modify it under the terms of the Do What The Fuck You Want +To Public License, Version 2, as published by Sam Hocevar. See +http://www.wtfpl.net/ for more details. + +*Tab=3***********************************************************************/ + + + +#pragma once +#if ! defined (avsutl_PlaneProcessor_HEADER_INCLUDED) +#define avsutl_PlaneProcessor_HEADER_INCLUDED + + + +/*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +#include "avsutl/CsPlane.h" +#include "avsutl/PlaneProcMode.h" +#include "fstb/fnc.h" + +#include +#include + +#include + + + +class IScriptEnvironment; +class PClip; +class PlaneProcCbInterface; +struct VideoInfo; + +namespace avsutl +{ + + + +class PlaneProcessor +{ + +/*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +public: + + static constexpr int _max_nbr_planes = CsPlane::_max_nbr_planes; + static constexpr int _max_nbr_clips = 1+3; // Index 0 = destination + + enum ClipType + { + ClipType_UNKNOWN = -1, + + ClipType_NORMAL = 0, + ClipType_STACKED_16, + ClipType_INTERLEAVED_16, + ClipType_MSB, + ClipType_LSB, + + ClipType_NBR_ELT + }; + + enum FmtChkFlag + { + FmtChkFlag_CS_TYPE = 1 << 0, // RGB/YUV + FmtChkFlag_CS_LAYOUT = 1 << 1, // Planar/interleaved + FmtChkFlag_CS_SUBSPL = 1 << 2, // Chroma subsampling + FmtChkFlag_CS_FORMAT = 1 << 3, // Data format and bitdepth + FmtChkFlag_CS_NBRCOMP = 1 << 4, // Number of components (planar or not) + + FmtChkFlag_CS_ALL = (1 << 8) - 1, + + FmtChkFlag_W = 1 << 8, + FmtChkFlag_H = 1 << 9, + FmtChkFlag_NBR_FRAMES = 1 << 10, + + FmtChkFlag_ALL = -1 + }; + + explicit PlaneProcessor (const ::VideoInfo &vi, const ::VideoInfo &vi_src, PlaneProcCbInterface &cb); + virtual ~PlaneProcessor () = default; + + void set_proc_mode (const std::array &pm_arr); + void set_proc_mode (std::string pmode); + void set_clip_info (int index, ClipType type); + int get_nbr_planes () const; + + void process_frame (::PVideoFrame &dst_sptr, int n, ::IScriptEnvironment &env, ::PClip *src_1_ptr, ::PClip *src_2_ptr, ::PClip *src_3_ptr, void *ctx_ptr = 0); + int get_plane_id (int plane_index, bool src_flag); + int get_width (const ::PVideoFrame &frame_sptr, int plane_id, bool src_flag = false) const; + int get_height (const ::PVideoFrame &frame_sptr, int plane_id) const; + int get_height16 (const ::PVideoFrame &frame_sptr, int plane_id) const; + + static int get_nbr_planes (const ::VideoInfo &vi); + static int get_bytes_per_component (const ::VideoInfo &vi); + static int get_min_w (const ::VideoInfo &vi); + static int get_min_h (const ::VideoInfo &vi, bool stack16_flag); + static int compute_plane_w (const ::VideoInfo &vi, int plane_index, int w); + static int compute_plane_h (const ::VideoInfo &vi, int plane_index, int h); + static void check_same_format (::IScriptEnvironment *env_ptr, const ::VideoInfo &vi, const ::PClip tst_sptr, const char *fnc_name_0, const char *arg_name_0, int flags = FmtChkFlag_ALL); + static bool check_stack16_width (const ::VideoInfo &vi, int width = -1); + static bool check_stack16_height (const ::VideoInfo &vi, int height = -1); + + + +/*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +protected: + + + +/*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +private: + + void fill (::PVideoFrame &dst_sptr, int n, int plane_id, ClipType type, float val); + void fill_frame_part (::PVideoFrame &dst_sptr, int n, int plane_id, float val, bool stacked_flag, int part); + void copy (::PVideoFrame &dst_sptr, int n, int plane_id, ClipType type_dst, ::PClip &src_clip, ClipType type_src, ::IScriptEnvironment &env); + void copy_n_to_n (::PVideoFrame &dst_sptr, ::PClip &src_clip, int n, int plane_id, ::IScriptEnvironment &env); + void copy_8_to_stack16 (::PVideoFrame &dst_sptr, ::PClip &src_clip, int n, int plane_id, ::IScriptEnvironment &env, int part); + void copy_stack16_to_8 (::PVideoFrame &dst_sptr, ::PClip &src_clip, int n, int plane_id, ::IScriptEnvironment &env, int part); + + static bool have_same_height (ClipType t1, ClipType t2); + static bool is_stacked (ClipType type); + + const ::VideoInfo & + _vi; + const ::VideoInfo & + _vi_src; + PlaneProcCbInterface & + _cb; + int _nbr_planes = 0; + std::array + _proc_mode_arr { fstb::make_array <_max_nbr_planes> ( + float (PlaneProcMode_PROCESS) + ) }; + std::array + _clip_type_arr { fstb::make_array <_max_nbr_clips> ( + ClipType_UNKNOWN + ) }; + + + +/*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +private: + + PlaneProcessor () = delete; + PlaneProcessor (const PlaneProcessor &other) = delete; + PlaneProcessor (PlaneProcessor &&other) = delete; + PlaneProcessor & + operator = (const PlaneProcessor &other) = delete; + PlaneProcessor & + operator = (PlaneProcessor &&other) = delete; + bool operator == (const PlaneProcessor &other) const = delete; + bool operator != (const PlaneProcessor &other) const = delete; + +}; // class PlaneProcessor + + + +} // namespace avsutl + + + +//#include "avsutl/PlaneProcessor.hpp" + + + +#endif // avsutl_PlaneProcessor_HEADER_INCLUDED + + + +/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ diff --git a/src/avsutl/TFlag.h b/src/avsutl/TFlag.h new file mode 100644 index 0000000..77fc41d --- /dev/null +++ b/src/avsutl/TFlag.h @@ -0,0 +1,56 @@ +/***************************************************************************** + + TFlag.h + Author: Laurent de Soras, 2021 + +--- Legal stuff --- + +This program is free software. It comes without any warranty, to +the extent permitted by applicable law. You can redistribute it +and/or modify it under the terms of the Do What The Fuck You Want +To Public License, Version 2, as published by Sam Hocevar. See +http://www.wtfpl.net/ for more details. + +*Tab=3***********************************************************************/ + + + +#pragma once +#if ! defined (avsutl_TFlag_HEADER_INCLUDED) +#define avsutl_TFlag_HEADER_INCLUDED + + + +/*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + + + +namespace avsutl +{ + + + +enum class TFlag +{ + + U = -1, // Undefined + F = 0, // True + T = 1 // False + +}; // enum TFlag + + + +} // namespace avsutl + + + +//#include "avsutl/TFlag.hpp" + + + +#endif // avsutl_TFlag_HEADER_INCLUDED + + + +/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ diff --git a/src/avsutl/VideoFilterBase.cpp b/src/avsutl/VideoFilterBase.cpp new file mode 100644 index 0000000..6a5fb33 --- /dev/null +++ b/src/avsutl/VideoFilterBase.cpp @@ -0,0 +1,91 @@ +/***************************************************************************** + + VideoFilterBase.cpp + Author: Laurent de Soras, 2021 + +--- Legal stuff --- + +This program is free software. It comes without any warranty, to +the extent permitted by applicable law. You can redistribute it +and/or modify it under the terms of the Do What The Fuck You Want +To Public License, Version 2, as published by Sam Hocevar. See +http://www.wtfpl.net/ for more details. + +*Tab=3***********************************************************************/ + + + +#if defined (_MSC_VER) + #pragma warning (1 : 4130 4223 4705 4706) + #pragma warning (4 : 4355 4786 4800) +#endif + + + +/*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +#include "avsutl/VideoFilterBase.h" + +#include + + + +namespace avsutl +{ + + + +/*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + + + +VideoFilterBase::VideoFilterBase (::IScriptEnvironment &env, ::PClip c) +: Inherited (c) +{ + try + { + env.CheckVersion (8); + _prop_flag = true; + } + catch (const ::AvisynthError &) + { + _prop_flag = false; + } +} + + + +bool VideoFilterBase::supports_props () const noexcept +{ + return _prop_flag; +} + + + +::PVideoFrame VideoFilterBase::build_new_frame (::IScriptEnvironment &env, const ::VideoInfo &vi_n, ::PVideoFrame *src_ptr, int align) +{ + if (supports_props ()) + { + return env.NewVideoFrameP (vi_n, src_ptr, align); + } + else + { + return env.NewVideoFrame (vi_n, align); + } +} + + + +/*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + + + +/*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + + + +} // namespace avsutl + + + +/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ diff --git a/src/avsutl/VideoFilterBase.h b/src/avsutl/VideoFilterBase.h new file mode 100644 index 0000000..1efdada --- /dev/null +++ b/src/avsutl/VideoFilterBase.h @@ -0,0 +1,96 @@ +/***************************************************************************** + + VideoFilterBase.h + Author: Laurent de Soras, 2021 + +--- Legal stuff --- + +This program is free software. It comes without any warranty, to +the extent permitted by applicable law. You can redistribute it +and/or modify it under the terms of the Do What The Fuck You Want +To Public License, Version 2, as published by Sam Hocevar. See +http://www.wtfpl.net/ for more details. + +*Tab=3***********************************************************************/ + + + +#pragma once +#if ! defined (avsutl_VideoFilterBase_HEADER_INCLUDED) +#define avsutl_VideoFilterBase_HEADER_INCLUDED + + + +/*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +#include "avisynth.h" + + + +namespace avsutl +{ + + + +class VideoFilterBase +: public ::GenericVideoFilter +{ + +/*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +public: + + explicit VideoFilterBase (::IScriptEnvironment &env, ::PClip c); + + bool supports_props () const noexcept; + ::PVideoFrame build_new_frame (::IScriptEnvironment &env, const ::VideoInfo &vi, ::PVideoFrame *src_ptr, int align = FRAME_ALIGN); + + + +/*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +protected: + + + +/*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +private: + + typedef ::GenericVideoFilter Inherited; + + bool _prop_flag = false; + + + +/*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +private: + + VideoFilterBase () = delete; + VideoFilterBase (const VideoFilterBase &other) = delete; + VideoFilterBase (VideoFilterBase &&other) = delete; + VideoFilterBase & + operator = (const VideoFilterBase &other) = delete; + VideoFilterBase & + operator = (VideoFilterBase &&other) = delete; + bool operator == (const VideoFilterBase &other) const = delete; + bool operator != (const VideoFilterBase &other) const = delete; + +}; // class VideoFilterBase + + + +} // namespace avsutl + + + +//#include "avsutl/VideoFilterBase.hpp" + + + +#endif // avsutl_VideoFilterBase_HEADER_INCLUDED + + + +/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ diff --git a/src/avsutl/fnc.h b/src/avsutl/fnc.h new file mode 100644 index 0000000..c80c9a6 --- /dev/null +++ b/src/avsutl/fnc.h @@ -0,0 +1,59 @@ +/***************************************************************************** + + fnc.h + Author: Laurent de Soras, 2021 + +--- Legal stuff --- + +This program is free software. It comes without any warranty, to +the extent permitted by applicable law. You can redistribute it +and/or modify it under the terms of the Do What The Fuck You Want +To Public License, Version 2, as published by Sam Hocevar. See +http://www.wtfpl.net/ for more details. + +*Tab=3***********************************************************************/ + + + +#pragma once +#if ! defined (avsutl_fnc_HEADER_INCLUDED) +#define avsutl_fnc_HEADER_INCLUDED + + + +/*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +#include "avsutl/TFlag.h" + + + +class AVSValue; +struct VideoInfo; + +namespace avsutl +{ + + + +TFlag set_tristate (const ::AVSValue &val); +bool set_default (TFlag tristate, bool def_flag); +bool is_full_range_default (const ::VideoInfo &vi); + +template +void fill_block (void *ptr, T val, int stride, int w, int h); + + + +} // namespace avsutl + + + +#include "avsutl/fnc.hpp" + + + +#endif // avsutl_fnc_HEADER_INCLUDED + + + +/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ diff --git a/src/avsutl/fnc.hpp b/src/avsutl/fnc.hpp new file mode 100644 index 0000000..f6c8bca --- /dev/null +++ b/src/avsutl/fnc.hpp @@ -0,0 +1,85 @@ +/***************************************************************************** + + fnc.hpp + Author: Laurent de Soras, 2021 + +--- Legal stuff --- + +This program is free software. It comes without any warranty, to +the extent permitted by applicable law. You can redistribute it +and/or modify it under the terms of the Do What The Fuck You Want +To Public License, Version 2, as published by Sam Hocevar. See +http://www.wtfpl.net/ for more details. + +*Tab=3***********************************************************************/ + + + +#if ! defined (avsutl_fnc_CODEHEADER_INCLUDED) +#define avsutl_fnc_CODEHEADER_INCLUDED + + + +/*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +#include + +#include +#include + + + +namespace avsutl +{ + + + +/*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + + + +/*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + + + +// Stride in bytes, w and h in pixels +template +void fill_block (void *ptr, T val, int stride, int w, int h) +{ + assert (ptr != nullptr); + assert (stride > 0); + assert (w > 0); + assert (h > 0); + + constexpr int min_align = 16; + + if (sizeof (val) == 1 && stride >= 0 && stride - w < min_align) + { + auto u8_ptr = static_cast (ptr); + std::fill (u8_ptr, u8_ptr + stride * (h - 1) + w, uint8_t (val)); + } + + else + { + T * data_ptr = reinterpret_cast (ptr); + const int stride_pix = stride / int (sizeof (val)); + assert (stride_pix * int (sizeof (val)) == stride); + for (int y = 0; y < h; ++y) + { + std::fill (data_ptr, data_ptr + w, val); + data_ptr += stride_pix; + } + } +} + + + +} // namespace avsutl + + + +#endif // avsutl_fnc_CODEHEADER_INCLUDED + + + +/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ diff --git a/src/avsutl/fnc_avsutl.cpp b/src/avsutl/fnc_avsutl.cpp new file mode 100644 index 0000000..f2adbc0 --- /dev/null +++ b/src/avsutl/fnc_avsutl.cpp @@ -0,0 +1,82 @@ +/***************************************************************************** + + fnc_avsutl.cpp + Author: Laurent de Soras, 2021 + +--- Legal stuff --- + +This program is free software. It comes without any warranty, to +the extent permitted by applicable law. You can redistribute it +and/or modify it under the terms of the Do What The Fuck You Want +To Public License, Version 2, as published by Sam Hocevar. See +http://www.wtfpl.net/ for more details. + +*Tab=3***********************************************************************/ + + + +#if defined (_MSC_VER) + #pragma warning (1 : 4130 4223 4705 4706) + #pragma warning (4 : 4355 4786 4800) +#endif + + + +/*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +#include "avsutl/fnc.h" +#include "avsutl/TFlag.h" +#include "avisynth.h" + +#include + + + +namespace avsutl +{ + + + +/*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + + + +/*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + + + +TFlag set_tristate (const ::AVSValue &val) +{ + assert (val.IsBool ()); + + return ( + (! val.Defined ()) ? avsutl::TFlag::U + : val.AsBool () ? avsutl::TFlag::T + : avsutl::TFlag::F + ); +} + + + +bool set_default (TFlag tristate, bool def_flag) +{ + return + (tristate == avsutl::TFlag::T) ? 1 + : (tristate == avsutl::TFlag::F) ? 0 + : def_flag; +} + + + +bool is_full_range_default (const ::VideoInfo &vi) +{ + return vi.IsRGB (); +} + + + +} // namespace avsutl + + + +/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ diff --git a/src/fmtc/Bitdepth.cpp b/src/fmtc/Bitdepth.cpp index 2ec282a..da4247f 100644 --- a/src/fmtc/Bitdepth.cpp +++ b/src/fmtc/Bitdepth.cpp @@ -25,11 +25,10 @@ To Public License, Version 2, as published by Sam Hocevar. See /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ #include "fmtc/Bitdepth.h" +#include "fmtc/CpuOpt.h" #include "fmtc/fnc.h" -#include "fmtc/SplFmtUtl.h" #include "fstb/def.h" #include "fstb/fnc.h" -#include "vsutl/CpuOpt.h" #include "vsutl/fnc.h" #include @@ -64,7 +63,7 @@ Bitdepth::Bitdepth (const ::VSMap &in, ::VSMap &out, void *user_data_ptr, ::VSCo { fstb::unused (user_data_ptr); - vsutl::CpuOpt cpu_opt (*this, in, out); + const fmtc::CpuOpt cpu_opt (*this, in, out); const bool sse2_flag = cpu_opt.has_sse2 (); const bool avx2_flag = cpu_opt.has_avx2 (); @@ -96,8 +95,8 @@ Bitdepth::Bitdepth (const ::VSMap &in, ::VSMap &out, void *user_data_ptr, ::VSCo } } - const auto splfmt_src = SplFmtUtl::conv_from_vsformat (fmt_src); - const auto col_fam = conv_colfam_to_fmtcl (fmt_src); + const auto splfmt_src = conv_vsfmt_to_splfmt (fmt_src); + const auto col_fam = conv_vsfmt_to_colfam (fmt_src); // Destination colorspace const ::VSFormat& fmt_dst = get_output_colorspace (in, out, core, fmt_src); @@ -129,7 +128,7 @@ Bitdepth::Bitdepth (const ::VSMap &in, ::VSMap &out, void *user_data_ptr, ::VSCo // Format is validated _vi_out.format = &fmt_dst; - const auto splfmt_dst = SplFmtUtl::conv_from_vsformat (fmt_dst); + const auto splfmt_dst = conv_vsfmt_to_splfmt (fmt_dst); const int w = _vi_in.width; // May be <= 0 diff --git a/src/fmtc/Convert.cpp b/src/fmtc/Convert.cpp index ee43bf1..3fb56c1 100644 --- a/src/fmtc/Convert.cpp +++ b/src/fmtc/Convert.cpp @@ -29,9 +29,11 @@ To Public License, Version 2, as published by Sam Hocevar. See /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ #include "fmtc/Convert.h" +#include "fmtc/fnc.h" #include "fmtc/Matrix.h" #include "fmtc/Resample.h" #include "fmtc/version.h" +#include "fmtcl/MatrixUtil.h" #include "fstb/def.h" #include "vsutl/fnc.h" @@ -94,17 +96,19 @@ Convert::Convert (const ::VSMap &in, ::VSMap &out, void *user_data_ptr, ::VSCore // Matrix presets std::string mat (get_arg_str (in, out, "mat", "")); - std::string mats (( fmt_src.colorFamily == ::cmYUV ) ? mat : ""); - std::string matd (( fmt_dst.colorFamily == ::cmYUV - || fmt_dst.colorFamily == ::cmGray) ? mat : ""); + std::string mats (( vsutl::is_vs_yuv ( fmt_src.colorFamily)) ? mat : ""); + std::string matd (( vsutl::is_vs_yuv ( fmt_dst.colorFamily) + || vsutl::is_vs_gray (fmt_dst.colorFamily)) ? mat : ""); mats = get_arg_str (in, out, "mats", mats); matd = get_arg_str (in, out, "matd", matd); if (! mats.empty () || ! matd.empty ()) { fstb::conv_to_lower_case (mats); fstb::conv_to_lower_case (matd); - Matrix::select_def_mat (mats, fmt_src); - Matrix::select_def_mat (matd, fmt_dst); + const auto col_fam_src = fmtc::conv_vsfmt_to_colfam (fmt_src); + const auto col_fam_dst = fmtc::conv_vsfmt_to_colfam (fmt_dst); + fmtcl::MatrixUtil::select_def_mat (mats, col_fam_src); + fmtcl::MatrixUtil::select_def_mat (matd, col_fam_dst); _mats = Matrix::find_cs_from_mat_str (*this, mats, true); _matd = Matrix::find_cs_from_mat_str (*this, matd, true); } @@ -512,7 +516,7 @@ bool Convert::fill_conv_step_with_curve (ConvStep &step, const ::VSFormat &fmt, { if (mat == fmtcl::ColorSpaceH265_UNSPECIFIED) { - if (fmt.colorFamily == ::cmRGB) + if (vsutl::is_vs_rgb (fmt.colorFamily)) { step._tcurve = fmtcl::TransCurve_SRGB; } diff --git a/src/fmtc/SplFmtUtl.hpp b/src/fmtc/CpuOpt.cpp similarity index 54% rename from src/fmtc/SplFmtUtl.hpp rename to src/fmtc/CpuOpt.cpp index 4726405..8a9b46f 100644 --- a/src/fmtc/SplFmtUtl.hpp +++ b/src/fmtc/CpuOpt.cpp @@ -1,7 +1,7 @@ /***************************************************************************** - SplFmtUtl.hpp - Author: Laurent de Soras, 2012 + CpuOpt.cpp + Author: Laurent de Soras, 2015 --- Legal stuff --- @@ -15,14 +15,19 @@ To Public License, Version 2, as published by Sam Hocevar. See -#if ! defined (fmtc_SplFmtUtl_CODEHEADER_INCLUDED) -#define fmtc_SplFmtUtl_CODEHEADER_INCLUDED +#if defined (_MSC_VER) + #pragma warning (1 : 4130 4223 4705 4706) + #pragma warning (4 : 4355 4786 4800) +#endif /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ -#include "VapourSynth.h" +#include "fmtc/CpuOpt.h" +#include "vsutl/FilterBase.h" + +#include @@ -35,35 +40,12 @@ namespace fmtc -fmtcl::SplFmt SplFmtUtl::conv_from_vsformat (const ::VSFormat &fmt) +CpuOpt::CpuOpt (vsutl::FilterBase &filter, const ::VSMap &in, ::VSMap &out, const char *param_name_0) { - fmtcl::SplFmt type = fmtcl::SplFmt_ILLEGAL; - - if (fmt.sampleType == ::stFloat && fmt.bitsPerSample == 32) - { - type = fmtcl::SplFmt_FLOAT; - } - else - { - if (fmt.bitsPerSample > 8 && fmt.bitsPerSample <= 16) - { - type = fmtcl::SplFmt_INT16; - } - else if (fmt.bitsPerSample <= 8) - { - type = fmtcl::SplFmt_INT8; - } - } - - return (type); -} - - - -void SplFmtUtl::conv_from_vsformat (fmtcl::SplFmt &type, int &bitdepth, const ::VSFormat &fmt) -{ - type = conv_from_vsformat (fmt); - bitdepth = fmt.bitsPerSample; + assert (param_name_0 != 0); + set_level (static_cast (filter.get_arg_int ( + in, out, param_name_0, Level_ANY_AVAILABLE + ) & Level_MASK)); } @@ -80,8 +62,4 @@ void SplFmtUtl::conv_from_vsformat (fmtcl::SplFmt &type, int &bitdepth, const :: -#endif // fmtc_SplFmtUtl_CODEHEADER_INCLUDED - - - /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ diff --git a/src/fmtc/SplFmtUtl.h b/src/fmtc/CpuOpt.h similarity index 54% rename from src/fmtc/SplFmtUtl.h rename to src/fmtc/CpuOpt.h index 228370e..5b934cf 100644 --- a/src/fmtc/SplFmtUtl.h +++ b/src/fmtc/CpuOpt.h @@ -1,7 +1,7 @@ /***************************************************************************** - SplFmtUtl.h - Author: Laurent de Soras, 2012 + CpuOpt.h + Author: Laurent de Soras, 2015 --- Legal stuff --- @@ -15,11 +15,11 @@ To Public License, Version 2, as published by Sam Hocevar. See -#if ! defined (fmtc_SplFmtUtl_HEADER_INCLUDED) -#define fmtc_SplFmtUtl_HEADER_INCLUDED +#pragma once +#if ! defined (fmtc_CpuOpt_HEADER_INCLUDED) +#define fmtc_CpuOpt_HEADER_INCLUDED #if defined (_MSC_VER) - #pragma once #pragma warning (4 : 4250) #endif @@ -27,28 +27,31 @@ To Public License, Version 2, as published by Sam Hocevar. See /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ -#include "fmtcl/SplFmt.h" +#include "fmtcl/CpuOptBase.h" +#include "VapourSynth.h" -struct VSFormat; + +namespace vsutl +{ + class FilterBase; +} namespace fmtc { -class SplFmtUtl +class CpuOpt +: public fmtcl::CpuOptBase { /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ public: - static inline fmtcl::SplFmt - conv_from_vsformat (const ::VSFormat &fmt); - static inline void - conv_from_vsformat (fmtcl::SplFmt &type, int &bitdepth, const ::VSFormat &fmt); + explicit CpuOpt (vsutl::FilterBase &filter, const ::VSMap &in, ::VSMap &out, const char *param_name_0 = "cpuopt"); @@ -68,14 +71,15 @@ class SplFmtUtl private: - SplFmtUtl () = delete; - SplFmtUtl (const SplFmtUtl &other) = delete; - virtual ~SplFmtUtl () = delete; - SplFmtUtl & operator = (const SplFmtUtl &other) = delete; - bool operator == (const SplFmtUtl &other) const = delete; - bool operator != (const SplFmtUtl &other) const = delete; + CpuOpt () = delete; + CpuOpt (const CpuOpt &other) = delete; + CpuOpt (CpuOpt &&other) = delete; + CpuOpt & operator = (const CpuOpt &other) = delete; + CpuOpt & operator = (CpuOpt &&other) = delete; + bool operator == (const CpuOpt &other) const = delete; + bool operator != (const CpuOpt &other) const = delete; -}; // class SplFmtUtl +}; // class CpuOpt @@ -83,11 +87,11 @@ class SplFmtUtl -#include "fmtc/SplFmtUtl.hpp" +//#include "fmtc/CpuOpt.hpp" -#endif // fmtc_SplFmtUtl_HEADER_INCLUDED +#endif // fmtc_CpuOpt_HEADER_INCLUDED diff --git a/src/fmtc/Matrix.cpp b/src/fmtc/Matrix.cpp index b8d93e4..57af2f4 100644 --- a/src/fmtc/Matrix.cpp +++ b/src/fmtc/Matrix.cpp @@ -29,12 +29,12 @@ To Public License, Version 2, as published by Sam Hocevar. See /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ +#include "fmtc/CpuOpt.h" #include "fmtc/Matrix.h" #include "fmtc/fnc.h" #include "fmtcl/MatrixUtil.h" #include "fstb/def.h" #include "fstb/fnc.h" -#include "vsutl/CpuOpt.h" #include "vsutl/fnc.h" #include "vsutl/FrameRefSPtr.h" @@ -71,7 +71,7 @@ Matrix::Matrix (const ::VSMap &in, ::VSMap &out, void * /*user_data_ptr*/, ::VSC , _plane_out (get_arg_int (in, out, "singleout", -1)) , _proc_uptr () { - vsutl::CpuOpt cpu_opt (*this, in, out); + const fmtc::CpuOpt cpu_opt (*this, in, out); _sse_flag = cpu_opt.has_sse (); _sse2_flag = cpu_opt.has_sse2 (); _avx_flag = cpu_opt.has_avx (); @@ -100,6 +100,7 @@ Matrix::Matrix (const ::VSMap &in, ::VSMap &out, void * /*user_data_ptr*/, ::VSC if ( ( fmt_src.sampleType == ::stInteger && ( fmt_src.bitsPerSample < 8 || fmt_src.bitsPerSample > 12) + && fmt_src.bitsPerSample != 14 && fmt_src.bitsPerSample != 16) || ( fmt_src.sampleType == ::stFloat && fmt_src.bitsPerSample != 32)) @@ -120,16 +121,17 @@ Matrix::Matrix (const ::VSMap &in, ::VSMap &out, void * /*user_data_ptr*/, ::VSC in, out, core, fmt_src, _plane_out, force_col_fam_flag ); - if ( fmt_dst_ptr->colorFamily != ::cmGray - && fmt_dst_ptr->colorFamily != ::cmRGB - && fmt_dst_ptr->colorFamily != ::cmYUV - && fmt_dst_ptr->colorFamily != ::cmYCoCg) + if ( ! vsutl::is_vs_gray (fmt_dst_ptr->colorFamily) + && ! vsutl::is_vs_rgb ( fmt_dst_ptr->colorFamily) + && ! vsutl::is_vs_yuv ( fmt_dst_ptr->colorFamily) + && ::cmYCoCg != fmt_dst_ptr->colorFamily) { throw_inval_arg ("unsupported color family for output."); } if ( ( fmt_dst_ptr->sampleType == ::stInteger && ( fmt_dst_ptr->bitsPerSample < 8 || fmt_dst_ptr->bitsPerSample > 12) + && fmt_dst_ptr->bitsPerSample != 14 && fmt_dst_ptr->bitsPerSample != 16) || ( fmt_dst_ptr->sampleType == ::stFloat && fmt_dst_ptr->bitsPerSample != 32)) @@ -146,7 +148,7 @@ Matrix::Matrix (const ::VSMap &in, ::VSMap &out, void * /*user_data_ptr*/, ::VSC ); } - // Preliminary matrix test: deduce the target color family if unspecified + // Preliminary matrix test: deduces the target color family if unspecified if ( ! force_col_fam_flag && fmt_dst_ptr->colorFamily != ::cmGray) { @@ -178,17 +180,19 @@ Matrix::Matrix (const ::VSMap &in, ::VSMap &out, void * /*user_data_ptr*/, ::VSC // Matrix presets std::string mat (get_arg_str (in, out, "mat", "")); - std::string mats (( fmt_src.colorFamily == ::cmYUV ) ? mat : ""); - std::string matd (( fmt_dst.colorFamily == ::cmYUV - || fmt_dst.colorFamily == ::cmGray) ? mat : ""); + std::string mats (( vsutl::is_vs_yuv ( fmt_src.colorFamily)) ? mat : ""); + std::string matd (( vsutl::is_vs_yuv ( fmt_dst.colorFamily) + || vsutl::is_vs_gray (fmt_dst.colorFamily)) ? mat : ""); mats = get_arg_str (in, out, "mats", mats); matd = get_arg_str (in, out, "matd", matd); if (! mats.empty () || ! matd.empty ()) { fstb::conv_to_lower_case (mats); fstb::conv_to_lower_case (matd); - select_def_mat (mats, fmt_src); - select_def_mat (matd, fmt_dst); + const auto col_fam_src = fmtc::conv_vsfmt_to_colfam (fmt_src); + const auto col_fam_dst = fmtc::conv_vsfmt_to_colfam (fmt_dst); + fmtcl::MatrixUtil::select_def_mat (mats, col_fam_src); + fmtcl::MatrixUtil::select_def_mat (matd, col_fam_dst); fmtcl::Mat4 m2s; fmtcl::Mat4 m2d; @@ -374,6 +378,11 @@ const ::VSFrameRef * Matrix::get_frame (int n, int activation_reason, void * &fr _vsapi.propSetInt (&dst_prop, "_Matrix" , int (_csp_out), ::paReplace); _vsapi.propSetInt (&dst_prop, "_ColorSpace", int (_csp_out), ::paReplace); } + else + { + _vsapi.propDeleteKey (&dst_prop, "_Matrix"); + _vsapi.propDeleteKey (&dst_prop, "_ColorSpace"); + } } } @@ -382,33 +391,6 @@ const ::VSFrameRef * Matrix::get_frame (int n, int activation_reason, void * &fr -// Everything should be lower case at this point -void Matrix::select_def_mat (std::string &mat, const ::VSFormat &fmt) -{ - if (mat.empty ()) - { - switch (fmt.colorFamily) - { - case ::cmYUV: - mat = "601"; - break; - - case ::cmYCoCg: - mat = "ycgco"; - break; - - case ::cmGray: // Should not happen actually - case ::cmRGB: - case ::cmCompat: - default: - // Nothing - break; - } - } -} - - - // mat should be already converted to lower case fmtcl::ColorSpaceH265 Matrix::find_cs_from_mat_str (const vsutl::FilterBase &flt, const std::string &mat, bool allow_2020cl_flag) { @@ -478,7 +460,7 @@ const ::VSFormat * Matrix::get_output_colorspace (const ::VSMap &in, ::VSMap &ou { col_fam = ::cmGray; } - else if (col_fam == ::cmGray) + else if (vsutl::is_vs_gray (col_fam)) { plane_out = 0; } @@ -562,7 +544,7 @@ const ::VSFormat * Matrix::find_dst_col_fam (fmtcl::ColorSpaceH265 tmp_csp, cons int bits = fmt_dst_ptr->bitsPerSample; int ssh = fmt_dst_ptr->subSamplingW; int ssv = fmt_dst_ptr->subSamplingH; - if (fmt_src.colorFamily == ::cmRGB) + if (vsutl::is_vs_rgb (fmt_src.colorFamily)) { col_fam = alt_cf; } diff --git a/src/fmtc/Matrix.h b/src/fmtc/Matrix.h index b53aa8e..2357a0f 100644 --- a/src/fmtc/Matrix.h +++ b/src/fmtc/Matrix.h @@ -71,7 +71,6 @@ class Matrix virtual const ::VSFrameRef * get_frame (int n, int activation_reason, void * &frame_data_ptr, ::VSFrameContext &frame_ctx, ::VSCore &core); - static void select_def_mat (std::string &mat, const ::VSFormat &fmt); static fmtcl::ColorSpaceH265 find_cs_from_mat_str (const vsutl::FilterBase &flt, const std::string &mat, bool allow_2020cl_flag); @@ -87,7 +86,7 @@ class Matrix private: - static constexpr int _nbr_planes = 3; + static constexpr int _nbr_planes = fmtcl::MatrixProc::_nbr_planes; enum Dir { diff --git a/src/fmtc/Matrix2020CL.cpp b/src/fmtc/Matrix2020CL.cpp index 9b86e76..e327014 100644 --- a/src/fmtc/Matrix2020CL.cpp +++ b/src/fmtc/Matrix2020CL.cpp @@ -24,12 +24,13 @@ To Public License, Version 2, as published by Sam Hocevar. See /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ -#include "fmtcl/ColorSpaceH265.h" +#include "fmtc/CpuOpt.h" #include "fmtc/fnc.h" #include "fmtc/Matrix2020CL.h" +#include "fmtcl/ColorSpaceH265.h" +#include "fmtcl/TransCurve.h" #include "fstb/def.h" #include "fstb/fnc.h" -#include "vsutl/CpuOpt.h" #include "vsutl/fnc.h" #include "vsutl/FrameRefSPtr.h" @@ -60,7 +61,7 @@ Matrix2020CL::Matrix2020CL (const ::VSMap &in, ::VSMap &out, void *user_data_ptr { fstb::unused (user_data_ptr); - vsutl::CpuOpt cpu_opt (*this, in, out); + const fmtc::CpuOpt cpu_opt (*this, in, out); const bool sse2_flag = cpu_opt.has_sse2 (); const bool avx2_flag = cpu_opt.has_avx2 (); @@ -84,8 +85,8 @@ Matrix2020CL::Matrix2020CL (const ::VSMap &in, ::VSMap &out, void *user_data_ptr { throw_inval_arg ("greyscale format not supported."); } - if ( fmt_src.colorFamily != ::cmRGB - && fmt_src.colorFamily != ::cmYUV) + if ( ! vsutl::is_vs_rgb (fmt_src.colorFamily) + && ! vsutl::is_vs_yuv (fmt_src.colorFamily)) { throw_inval_arg ("Only RGB and YUV color families are supported."); } @@ -99,7 +100,7 @@ Matrix2020CL::Matrix2020CL (const ::VSMap &in, ::VSMap &out, void *user_data_ptr { throw_inval_arg ("pixel bitdepth not supported."); } - if ( fmt_src.colorFamily == ::cmRGB + if ( vsutl::is_vs_rgb (fmt_src.colorFamily) && fmt_src.sampleType == ::stInteger && fmt_src.bitsPerSample != RGB_INT_BITS) { @@ -109,8 +110,8 @@ Matrix2020CL::Matrix2020CL (const ::VSMap &in, ::VSMap &out, void *user_data_ptr // Destination colorspace const ::VSFormat& fmt_dst = get_output_colorspace (in, out, core, fmt_src); - if ( fmt_dst.colorFamily != ::cmRGB - && fmt_dst.colorFamily != ::cmYUV) + if ( ! vsutl::is_vs_rgb (fmt_dst.colorFamily) + && ! vsutl::is_vs_yuv (fmt_dst.colorFamily)) { throw_inval_arg ("unsupported color family for output."); } @@ -124,9 +125,9 @@ Matrix2020CL::Matrix2020CL (const ::VSMap &in, ::VSMap &out, void *user_data_ptr { throw_inval_arg ("output bitdepth not supported."); } - if ( fmt_src.colorFamily == ::cmRGB - && fmt_src.sampleType == ::stInteger - && fmt_src.bitsPerSample != RGB_INT_BITS) + if ( vsutl::is_vs_rgb (fmt_dst.colorFamily) + && fmt_dst.sampleType == ::stInteger + && fmt_dst.bitsPerSample != RGB_INT_BITS) { throw_inval_arg ("output clip: RGB depth cannot be less than 16 bits."); } @@ -141,7 +142,7 @@ Matrix2020CL::Matrix2020CL (const ::VSMap &in, ::VSMap &out, void *user_data_ptr "specified output colorspace is not compatible with the input." ); } - if (fmt_dst.colorFamily == fmt_src.colorFamily) + if (vsutl::is_vs_same_colfam (fmt_dst.colorFamily, fmt_src.colorFamily)) { throw_inval_arg ( "Input and output clips must be of different color families." @@ -150,7 +151,7 @@ Matrix2020CL::Matrix2020CL (const ::VSMap &in, ::VSMap &out, void *user_data_ptr // Output format is validated. _vi_out.format = &fmt_dst; - _to_yuv_flag = (fmt_dst.colorFamily == ::cmYUV); + _to_yuv_flag = vsutl::is_vs_yuv (fmt_dst.colorFamily); // Range const ::VSFormat & fmt_yuv = (_to_yuv_flag) ? fmt_dst : fmt_src; @@ -260,6 +261,13 @@ const ::VSFrameRef * Matrix2020CL::get_frame (int n, int activation_reason, void ? fmtcl::ColorSpaceH265_BT2020CL : fmtcl::ColorSpaceH265_RGB; _vsapi.propSetInt (&dst_prop, "_ColorSpace", cs_out, ::paReplace); + _vsapi.propSetInt (&dst_prop, "_Matrix", cs_out, ::paReplace); + + const auto curve = + (! _to_yuv_flag) ? fmtcl::TransCurve_LINEAR + : (_vi_out.format->bitsPerSample <= 10) ? fmtcl::TransCurve_2020_10 + : fmtcl::TransCurve_2020_12; + _vsapi.propSetInt (&dst_prop, "_Transfer", int (curve), ::paReplace); if (! _to_yuv_flag || _range_set_flag) { @@ -289,7 +297,7 @@ const ::VSFormat & Matrix2020CL::get_output_colorspace (const ::VSMap &in, ::VSM int spl_type = fmt_dst_ptr->sampleType; // Automatic default conversion - if (col_fam == ::cmRGB) + if (vsutl::is_vs_rgb (col_fam)) { col_fam = ::cmYUV; } diff --git a/src/fmtc/Primaries.cpp b/src/fmtc/Primaries.cpp index 11a1724..1754c45 100644 --- a/src/fmtc/Primaries.cpp +++ b/src/fmtc/Primaries.cpp @@ -24,6 +24,7 @@ To Public License, Version 2, as published by Sam Hocevar. See /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ +#include "fmtc/CpuOpt.h" #include "fmtc/fnc.h" #include "fmtc/Primaries.h" #include "fmtcl/fnc.h" @@ -31,7 +32,7 @@ To Public License, Version 2, as published by Sam Hocevar. See #include "fmtcl/PrimUtil.h" #include "fstb/def.h" #include "fstb/fnc.h" -#include "vsutl/CpuOpt.h" +#include "vsutl/fnc.h" #include "vsutl/FrameRefSPtr.h" #include @@ -64,7 +65,7 @@ Primaries::Primaries (const ::VSMap &in, ::VSMap &out, void *user_data_ptr, ::VS { fstb::unused (user_data_ptr, core); - vsutl::CpuOpt cpu_opt (*this, in, out); + const fmtc::CpuOpt cpu_opt (*this, in, out); _sse_flag = cpu_opt.has_sse (); _sse2_flag = cpu_opt.has_sse2 (); _avx_flag = cpu_opt.has_avx (); @@ -234,7 +235,7 @@ void Primaries::check_colorspace (const ::VSFormat &fmt, const char *inout_0) co ); throw_inval_arg (_filter_error_msg_0); } - if (fmt.colorFamily != ::cmRGB) + if (! vsutl::is_vs_rgb (fmt.colorFamily)) { fstb::snprintf4all ( _filter_error_msg_0, diff --git a/src/fmtc/Resample.cpp b/src/fmtc/Resample.cpp index 637c8e2..3d4b913 100644 --- a/src/fmtc/Resample.cpp +++ b/src/fmtc/Resample.cpp @@ -24,12 +24,11 @@ To Public License, Version 2, as published by Sam Hocevar. See /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ +#include "fmtc/CpuOpt.h" #include "fmtc/fnc.h" #include "fmtc/Resample.h" -#include "fmtc/SplFmtUtl.h" #include "fmtcl/ResampleUtil.h" #include "fstb/def.h" -#include "vsutl/CpuOpt.h" #include "vsutl/fnc.h" #include "vsutl/FrameRefSPtr.h" #include "vsutl/PlaneProcMode.h" @@ -102,7 +101,7 @@ Resample::Resample (const ::VSMap &in, ::VSMap &out, void *user_data_ptr, ::VSCo { fstb::unused (user_data_ptr); - vsutl::CpuOpt cpu_opt (*this, in, out); + const fmtc::CpuOpt cpu_opt (*this, in, out); _sse2_flag = cpu_opt.has_sse2 (); _avx2_flag = cpu_opt.has_avx2 (); @@ -122,6 +121,7 @@ Resample::Resample (const ::VSMap &in, ::VSMap &out, void *user_data_ptr, ::VSCo || (st == ::stInteger && bps == 2 && ( res == 9 || res == 10 || res == 12 + || res == 14 || res == 16)) || (st == ::stFloat && bps == 4 && res == 32 ))) { @@ -135,7 +135,7 @@ Resample::Resample (const ::VSMap &in, ::VSMap &out, void *user_data_ptr, ::VSCo _src_width = _vi_in.width; _src_height = _vi_in.height; - SplFmtUtl::conv_from_vsformat (_src_type, _src_res, *_vi_in.format); + conv_vsfmt_to_splfmt (_src_type, _src_res, *_vi_in.format); // Destination colorspace ::VSFormat fmt_def = fmt_src; @@ -173,7 +173,7 @@ Resample::Resample (const ::VSMap &in, ::VSMap &out, void *user_data_ptr, ::VSCo // Done with the format _vi_out.format = &fmt_dst; - SplFmtUtl::conv_from_vsformat (_dst_type, _dst_res, *_vi_out.format); + conv_vsfmt_to_splfmt (_dst_type, _dst_res, *_vi_out.format); if (_interlaced_src < 0 || _interlaced_src >= InterlacingParam_NBR_ELT) { @@ -943,8 +943,8 @@ fmtcl::FilterResize * Resample::create_or_access_plane_filter (int plane_index, void Resample::create_all_plane_specs () { - const fmtcl::ColorFamily src_cf = fmtc::conv_colfam_to_fmtcl (*_vi_in.format); - const fmtcl::ColorFamily dst_cf = fmtc::conv_colfam_to_fmtcl (*_vi_out.format); + const fmtcl::ColorFamily src_cf = fmtc::conv_vsfmt_to_colfam (*_vi_in.format); + const fmtcl::ColorFamily dst_cf = fmtc::conv_vsfmt_to_colfam (*_vi_out.format); const int src_ss_h = _vi_in.format->subSamplingW; const int src_ss_v = _vi_in.format->subSamplingH; const int dst_ss_h = _vi_out.format->subSamplingW; diff --git a/src/fmtc/Transfer.cpp b/src/fmtc/Transfer.cpp index 688f61f..82bafab 100644 --- a/src/fmtc/Transfer.cpp +++ b/src/fmtc/Transfer.cpp @@ -26,11 +26,11 @@ To Public License, Version 2, as published by Sam Hocevar. See #include "fstb/def.h" +#include "fmtc/CpuOpt.h" #include "fmtc/Transfer.h" #include "fmtc/fnc.h" #include "fmtcl/TransUtil.h" #include "fstb/fnc.h" -#include "vsutl/CpuOpt.h" #include "vsutl/fnc.h" #include "vsutl/FrameRefSPtr.h" @@ -81,7 +81,7 @@ Transfer::Transfer (const ::VSMap &in, ::VSMap &out, void * /*user_data_ptr*/, : fstb::conv_to_lower_case (_transs); fstb::conv_to_lower_case (_transd); - vsutl::CpuOpt cpu_opt (*this, in, out); + const fmtc::CpuOpt cpu_opt (*this, in, out); _sse2_flag = cpu_opt.has_sse2 (); _avx2_flag = cpu_opt.has_avx2 (); @@ -93,8 +93,8 @@ Transfer::Transfer (const ::VSMap &in, ::VSMap &out, void * /*user_data_ptr*/, : const ::VSFormat & fmt_src = *_vi_in.format; - if ( fmt_src.colorFamily != ::cmGray - && fmt_src.colorFamily != ::cmRGB) + if ( ! vsutl::is_vs_gray (fmt_src.colorFamily) + && ! vsutl::is_vs_rgb ( fmt_src.colorFamily)) { throw_inval_arg ("unsupported color family."); } diff --git a/src/fmtc/fnc.h b/src/fmtc/fnc.h index fc86889..81053c8 100644 --- a/src/fmtc/fnc.h +++ b/src/fmtc/fnc.h @@ -51,11 +51,11 @@ namespace fmtc -fmtcl::PicFmt conv_vsfmt_to_picfmt (const ::VSFormat &fmt, bool full_flag); -fmtcl::SplFmt conv_vsfmt_to_splfmt (const ::VSFormat &fmt); -fmtcl::ColorFamily - conv_colfam_to_fmtcl (const ::VSFormat &fmt); -void prepare_matrix_coef (const vsutl::FilterBase &filter, fmtcl::MatrixProc &mat_proc, const fmtcl::Mat4 &mat_main, const ::VSFormat &fmt_dst, bool full_range_dst_flag, const ::VSFormat &fmt_src, bool full_range_src_flag, fmtcl::ColorSpaceH265 csp_out = fmtcl::ColorSpaceH265_UNSPECIFIED, int plane_out = -1); +fmtcl::PicFmt conv_vsfmt_to_picfmt (const ::VSFormat &fmt, bool full_flag); +fmtcl::SplFmt conv_vsfmt_to_splfmt (const ::VSFormat &fmt); +void conv_vsfmt_to_splfmt (fmtcl::SplFmt &type, int &bitdepth, const ::VSFormat &fmt); +fmtcl::ColorFamily conv_vsfmt_to_colfam (const ::VSFormat &fmt); +void prepare_matrix_coef (const vsutl::FilterBase &filter, fmtcl::MatrixProc &mat_proc, const fmtcl::Mat4 &mat_main, const ::VSFormat &fmt_dst, bool full_range_dst_flag, const ::VSFormat &fmt_src, bool full_range_src_flag, fmtcl::ColorSpaceH265 csp_out = fmtcl::ColorSpaceH265_UNSPECIFIED, int plane_out = -1); diff --git a/src/fmtc/fnc.cpp b/src/fmtc/fnc_fmtc.cpp similarity index 81% rename from src/fmtc/fnc.cpp rename to src/fmtc/fnc_fmtc.cpp index f590fb3..0c5eff9 100644 --- a/src/fmtc/fnc.cpp +++ b/src/fmtc/fnc_fmtc.cpp @@ -55,7 +55,7 @@ fmtcl::PicFmt conv_vsfmt_to_picfmt (const ::VSFormat &fmt, bool full_flag) fmtcl::PicFmt pic_fmt; pic_fmt._sf = conv_vsfmt_to_splfmt (fmt); pic_fmt._res = fmt.bitsPerSample; - pic_fmt._col_fam = conv_colfam_to_fmtcl (fmt); + pic_fmt._col_fam = conv_vsfmt_to_colfam (fmt); pic_fmt._full_flag = full_flag; return pic_fmt; @@ -67,12 +67,9 @@ fmtcl::SplFmt conv_vsfmt_to_splfmt (const ::VSFormat &fmt) { fmtcl::SplFmt splfmt = fmtcl::SplFmt_ILLEGAL; - if (fmt.sampleType == ::stFloat) + if (fmt.sampleType == ::stFloat && fmt.bitsPerSample == 32) { - if (fmt.bitsPerSample == 32) - { - splfmt = fmtcl::SplFmt_FLOAT; - } + splfmt = fmtcl::SplFmt_FLOAT; } else { @@ -91,17 +88,38 @@ fmtcl::SplFmt conv_vsfmt_to_splfmt (const ::VSFormat &fmt) -fmtcl::ColorFamily conv_colfam_to_fmtcl (const ::VSFormat &fmt) +void conv_vsfmt_to_splfmt (fmtcl::SplFmt &type, int &bitdepth, const ::VSFormat &fmt) +{ + type = conv_vsfmt_to_splfmt (fmt); + bitdepth = fmt.bitsPerSample; +} + + + +fmtcl::ColorFamily conv_vsfmt_to_colfam (const ::VSFormat &fmt) { auto col_fam = fmtcl::ColorFamily_INVALID; switch (fmt.colorFamily) { - case cmGray: col_fam = fmtcl::ColorFamily_GRAY; break; - case cmRGB: col_fam = fmtcl::ColorFamily_RGB; break; - case cmYUV: col_fam = fmtcl::ColorFamily_YUV; break; - case cmYCoCg: col_fam = fmtcl::ColorFamily_YCGCO; break; - default: assert (false); break; + case cfGray: + case cmGray: + col_fam = fmtcl::ColorFamily_GRAY; + break; + case cfRGB: + case cmRGB: + col_fam = fmtcl::ColorFamily_RGB; + break; + case cfYUV: + case cmYUV: + col_fam = fmtcl::ColorFamily_YUV; + break; + case cmYCoCg: + col_fam = fmtcl::ColorFamily_YCGCO; + break; + default: + assert (false); + break; } return col_fam; diff --git a/src/fmtcavs/Bitdepth.cpp b/src/fmtcavs/Bitdepth.cpp new file mode 100644 index 0000000..ae6c0f0 --- /dev/null +++ b/src/fmtcavs/Bitdepth.cpp @@ -0,0 +1,248 @@ +/***************************************************************************** + + Bitdepth.cpp + Author: Laurent de Soras, 2021 + +--- Legal stuff --- + +This program is free software. It comes without any warranty, to +the extent permitted by applicable law. You can redistribute it +and/or modify it under the terms of the Do What The Fuck You Want +To Public License, Version 2, as published by Sam Hocevar. See +http://www.wtfpl.net/ for more details. + +*Tab=3***********************************************************************/ + + + +#if defined (_MSC_VER) + #pragma warning (1 : 4130 4223 4705 4706) + #pragma warning (4 : 4355 4786 4800) +#endif + + + +/*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +#include "avsutl/fnc.h" +#include "fmtcavs/Bitdepth.h" +#include "fmtcavs/CpuOpt.h" +#include "fmtcavs/fnc.h" +#include "fmtcavs/function_names.h" + +#include + + + +namespace fmtcavs +{ + + + +/*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + + + +Bitdepth::Bitdepth (::IScriptEnvironment &env, const ::AVSValue &args) +: Inherited (env, args [Param_CLIP_SRC].AsClip ()) +, _clip_src_sptr (args [Param_CLIP_SRC].AsClip ()) +, _vi_src (vi) +{ + const CpuOpt cpu_opt (args [Param_CPUOPT]); + const bool sse2_flag = cpu_opt.has_sse2 (); + const bool avx2_flag = cpu_opt.has_avx2 (); + + if (! _vi_src.IsPlanar ()) + { + env.ThrowError (fmtcavs_BITDEPTH ": input must be planar."); + } + + // Guess the output format if incomplete + int res = args [Param_BITS].AsInt (-1); + const auto & arg_flt = args [Param_FLT]; + bool flt_flag = arg_flt.AsBool (); + if (arg_flt.Defined ()) + { + if (res < 0 && flt_flag) + { + res = 32; + } + } + else + { + flt_flag = (res == 32); + } + if (res < 0) + { + res = _vi_src.BitsPerComponent (); + } + + // Checks the output format + if (! ( (! flt_flag && ( res == 8 + || res == 10 + || res == 12 + || res == 16)) + || ( flt_flag && res == 32 ))) + { + env.ThrowError ( + fmtcavs_BITDEPTH ": output pixel bitdepth not supported." + ); + } + + // Builds and validates the output format + vi.pixel_type &= ~::VideoInfo::CS_Sample_Bits_Mask; + switch (res) + { + case 8: vi.pixel_type |= ::VideoInfo::CS_Sample_Bits_8; break; + case 10: vi.pixel_type |= ::VideoInfo::CS_Sample_Bits_10; break; + case 12: vi.pixel_type |= ::VideoInfo::CS_Sample_Bits_12; break; + case 16: vi.pixel_type |= ::VideoInfo::CS_Sample_Bits_16; break; + case 32: vi.pixel_type |= ::VideoInfo::CS_Sample_Bits_32; break; + default: assert (false); break; + } + + // Conversion-related things + _fulls_flag = + args [Param_FULLS].AsBool (avsutl::is_full_range_default (_vi_src)); + _fulld_flag = args [Param_FULLD].AsBool (_fulls_flag); + _range_def_flag = + (args [Param_FULLS].Defined () || args [Param_FULLD].Defined ()); + + // Configures the plane processor + _plane_proc_uptr = std::make_unique ( + vi, _vi_src, *this + ); + _plane_proc_uptr->set_proc_mode (args [Param_PLANES].AsString ("all")); + _plane_proc_uptr->set_clip_info (0, avsutl::PlaneProcessor::ClipType_NORMAL); + _plane_proc_uptr->set_clip_info (1, avsutl::PlaneProcessor::ClipType_NORMAL); + + // Dithering parameters + auto dmode = static_cast ( + args [Param_DMODE].AsInt (fmtcl::Dither::DMode_FILTERLITE) + ); + if (dmode == fmtcl::Dither::DMode_ROUND_ALIAS) + { + dmode = fmtcl::Dither::DMode_ROUND; + } + if ( dmode < 0 + || dmode >= fmtcl::Dither::DMode_NBR_ELT) + { + env.ThrowError (fmtcavs_BITDEPTH ": invalid dmode."); + } + + const double ampo = args [Param_AMPO].AsFloat (1.0); + if (ampo < 0) + { + env.ThrowError (fmtcavs_BITDEPTH ": ampo cannot be negative."); + } + + const double ampn = args [Param_AMPN].AsFloat (0.0); + if (ampn < 0) + { + env.ThrowError (fmtcavs_BITDEPTH ": ampn cannot be negative."); + } + + const int pat_size = + args [Param_PATSIZE].AsInt (fmtcl::Dither::_max_pat_width); + if (pat_size < 4 || fmtcl::Dither::_max_pat_width % pat_size != 0) + { + env.ThrowError (fmtcavs_BITDEPTH ": wrong value for patsize."); + } + + const bool dyn_flag = args [Param_DYN ].AsBool (false); + const bool static_noise_flag = args [Param_STATICNOISE].AsBool (false); + const bool tpdfo_flag = args [Param_TPDFO ].AsBool (false); + const bool tpdfn_flag = args [Param_TPDFN ].AsBool (false); + const bool corplane_flag = args [Param_CORPLANE ].AsBool (false); + + // Finally... + const int nbr_planes = vi.NumComponents (); + int res_src; + fmtcl::SplFmt splfmt_src; + conv_vi_to_splfmt (splfmt_src, res_src, _vi_src); + fmtcl::SplFmt splfmt_dst = conv_vi_to_splfmt (vi); + fmtcl::ColorFamily col_fam = conv_vi_to_colfam (vi); + + _engine_uptr = std::make_unique ( + splfmt_src, res_src, _fulls_flag, + splfmt_dst, res , _fulld_flag, + col_fam, nbr_planes, vi.width, + dmode, pat_size, ampo, ampn, + dyn_flag, static_noise_flag, corplane_flag, + tpdfo_flag, tpdfn_flag, + sse2_flag, avx2_flag + ); +} + + + +::PVideoFrame __stdcall Bitdepth::GetFrame (int n, ::IScriptEnvironment *env_ptr) +{ + ::PVideoFrame src_sptr = _clip_src_sptr->GetFrame (n, env_ptr); + ::PVideoFrame dst_sptr = build_new_frame (*env_ptr, vi, &src_sptr); + + _plane_proc_uptr->process_frame ( + dst_sptr, n, *env_ptr, + &_clip_src_sptr, nullptr, nullptr, + nullptr + ); + + return dst_sptr; +} + + + +/*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + + + +void Bitdepth::do_process_plane (::PVideoFrame &dst_sptr, int n, ::IScriptEnvironment &env, int plane_index, int plane_id, void *ctx_ptr) +{ + fstb::unused (ctx_ptr); + + ::PVideoFrame src_sptr = _clip_src_sptr->GetFrame (n, &env); + + uint8_t * data_dst_ptr = dst_sptr->GetWritePtr (plane_id); + const int stride_dst = dst_sptr->GetPitch (plane_id); + const uint8_t* data_src_ptr = src_sptr->GetReadPtr (plane_id); + const int stride_src = src_sptr->GetPitch (plane_id); + const int w = _plane_proc_uptr->get_width (dst_sptr, plane_id); + const int h = _plane_proc_uptr->get_height (dst_sptr, plane_id); + + try + { + _engine_uptr->process_plane ( + data_dst_ptr, stride_dst, + data_src_ptr, stride_src, + w, h, n, plane_index + ); + } + catch (...) + { + assert (false); + } + + // Frame properties + if (supports_props ()) + { + ::AVSMap * props_ptr = env.getFramePropsRW (dst_sptr); + + if (_range_def_flag) + { + const int cr_val = (_fulld_flag) ? 0 : 1; + env.propSetInt (props_ptr, "_ColorRange", cr_val, ::PROPAPPENDMODE_REPLACE); + } + } +} + + + +/*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + + + +} // namespace fmtcavs + + + +/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ diff --git a/src/fmtcavs/Bitdepth.h b/src/fmtcavs/Bitdepth.h new file mode 100644 index 0000000..d998817 --- /dev/null +++ b/src/fmtcavs/Bitdepth.h @@ -0,0 +1,140 @@ +/***************************************************************************** + + Bitdepth.h + Author: Laurent de Soras, 2021 + +--- Legal stuff --- + +This program is free software. It comes without any warranty, to +the extent permitted by applicable law. You can redistribute it +and/or modify it under the terms of the Do What The Fuck You Want +To Public License, Version 2, as published by Sam Hocevar. See +http://www.wtfpl.net/ for more details. + +*Tab=3***********************************************************************/ + + + +#pragma once +#if ! defined (fmtcavs_Bitdepth_HEADER_INCLUDED) +#define fmtcavs_Bitdepth_HEADER_INCLUDED + + + +/*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +#include "fmtcl/Dither.h" +#include "avsutl/PlaneProcCbInterface.h" +#include "avsutl/PlaneProcessor.h" +#include "avsutl/VideoFilterBase.h" + +#include +#include + + + +namespace fmtcavs +{ + + + +class Bitdepth +: public avsutl::VideoFilterBase +, public avsutl::PlaneProcCbInterface +{ + +/*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +public: + + typedef avsutl::VideoFilterBase Inherited; + + enum Param + { + Param_CLIP_SRC = 0, // 0 + Param_BITS, + Param_FLT, + Param_PLANES, + Param_FULLS, + Param_FULLD, + Param_DMODE, + Param_AMPO, + Param_AMPN, + Param_DYN, + Param_STATICNOISE, // 10 + Param_CPUOPT, + Param_PATSIZE, + Param_TPDFO, + Param_TPDFN, + Param_CORPLANE, + + Param_NBR_ELT, + }; + + explicit Bitdepth (::IScriptEnvironment &env, const ::AVSValue &args); + virtual ~Bitdepth () = default; + + // VideoFilterBase + ::PVideoFrame __stdcall + GetFrame (int n, ::IScriptEnvironment *env_ptr) override; + + + +/*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +protected: + + // PlaneProcCbInterface + void do_process_plane (::PVideoFrame &dst_sptr, int n, ::IScriptEnvironment &env, int plane_index, int plane_id, void *ctx_ptr) override; + + + +/*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +private: + + ::PClip _clip_src_sptr; + const ::VideoInfo + _vi_src; + + std::unique_ptr + _plane_proc_uptr; + + std::unique_ptr + _engine_uptr; + + bool _range_def_flag = false; + bool _fulld_flag = false; + bool _fulls_flag = false; + + + +/*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +private: + + Bitdepth () = delete; + Bitdepth (const Bitdepth &other) = delete; + Bitdepth (Bitdepth &&other) = delete; + Bitdepth & operator = (const Bitdepth &other) = delete; + Bitdepth & operator = (Bitdepth &&other) = delete; + bool operator == (const Bitdepth &other) const = delete; + bool operator != (const Bitdepth &other) const = delete; + +}; // class Bitdepth + + + +} // namespace fmtcavs + + + +//#include "fmtcavs/Bitdepth.hpp" + + + +#endif // fmtcavs_Bitdepth_HEADER_INCLUDED + + + +/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ diff --git a/src/fmtcavs/CpuOpt.cpp b/src/fmtcavs/CpuOpt.cpp new file mode 100644 index 0000000..c400bc9 --- /dev/null +++ b/src/fmtcavs/CpuOpt.cpp @@ -0,0 +1,64 @@ +/***************************************************************************** + + CpuOpt.cpp + Author: Laurent de Soras, 2021 + +--- Legal stuff --- + +This program is free software. It comes without any warranty, to +the extent permitted by applicable law. You can redistribute it +and/or modify it under the terms of the Do What The Fuck You Want +To Public License, Version 2, as published by Sam Hocevar. See +http://www.wtfpl.net/ for more details. + +*Tab=3***********************************************************************/ + + + +#if defined (_MSC_VER) + #pragma warning (1 : 4130 4223 4705 4706) + #pragma warning (4 : 4355 4786 4800) +#endif + + + +/*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +#include "fmtcavs/CpuOpt.h" +#include "avisynth.h" + +#include + + + +namespace fmtcavs +{ + + + +/*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + + + +CpuOpt::CpuOpt (const ::AVSValue &arg) +{ + set_level (static_cast ( + arg.AsInt (Level_ANY_AVAILABLE) & Level_MASK + )); +} + + + +/*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + + + +/*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + + + +} // namespace fmtcavs + + + +/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ diff --git a/src/fmtcavs/CpuOpt.h b/src/fmtcavs/CpuOpt.h new file mode 100644 index 0000000..3661940 --- /dev/null +++ b/src/fmtcavs/CpuOpt.h @@ -0,0 +1,89 @@ +/***************************************************************************** + + CpuOpt.h + Author: Laurent de Soras, 2021 + +--- Legal stuff --- + +This program is free software. It comes without any warranty, to +the extent permitted by applicable law. You can redistribute it +and/or modify it under the terms of the Do What The Fuck You Want +To Public License, Version 2, as published by Sam Hocevar. See +http://www.wtfpl.net/ for more details. + +*Tab=3***********************************************************************/ + + + +#pragma once +#if ! defined (fmtcavs_CpuOpt_HEADER_INCLUDED) +#define fmtcavs_CpuOpt_HEADER_INCLUDED + + + +/*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +#include "fmtcl/CpuOptBase.h" + + + +class AVSValue; + +namespace fmtcavs +{ + + + +class CpuOpt +: public fmtcl::CpuOptBase +{ + +/*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +public: + + explicit CpuOpt (const ::AVSValue &arg); + + + +/*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +protected: + + + +/*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +private: + + + +/*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +private: + + CpuOpt () = delete; + CpuOpt (const CpuOpt &other) = delete; + CpuOpt (CpuOpt &&other) = delete; + CpuOpt & operator = (const CpuOpt &other) = delete; + CpuOpt & operator = (CpuOpt &&other) = delete; + bool operator == (const CpuOpt &other) const = delete; + bool operator != (const CpuOpt &other) const = delete; + +}; // class CpuOpt + + + +} // namespace fmtcavs + + + +//#include "fmtcavs/CpuOpt.hpp" + + + +#endif // fmtcavs_CpuOpt_HEADER_INCLUDED + + + +/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ diff --git a/src/fmtcavs/FmtAvs.cpp b/src/fmtcavs/FmtAvs.cpp new file mode 100644 index 0000000..7952e4a --- /dev/null +++ b/src/fmtcavs/FmtAvs.cpp @@ -0,0 +1,596 @@ +/***************************************************************************** + + FmtAvs.cpp + Author: Laurent de Soras, 2021 + +--- Legal stuff --- + +This program is free software. It comes without any warranty, to +the extent permitted by applicable law. You can redistribute it +and/or modify it under the terms of the Do What The Fuck You Want +To Public License, Version 2, as published by Sam Hocevar. See +http://www.wtfpl.net/ for more details. + +*Tab=3***********************************************************************/ + + + +#if defined (_MSC_VER) + #pragma warning (1 : 4130 4223 4705 4706) + #pragma warning (4 : 4355 4786 4800) +#endif + + + +/*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +#include "fstb/fnc.h" +#include "fmtcavs/FmtAvs.h" +#include "avisynth.h" + +#include + +#include +#include + + + +namespace fmtcavs +{ + + + +/*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + + + +FmtAvs::FmtAvs (std::string fmt_str) +{ + if (conv_from_str (fmt_str) != 0) + { + throw std::runtime_error ("Bad video format string"); + } +} + + + +FmtAvs::FmtAvs (const VideoInfo &vi) noexcept +{ + conv_from_vi (vi); +} + + + +void FmtAvs::invalidate () noexcept +{ + _bitdepth = -1; + _col_fam = fmtcl::ColorFamily_INVALID; + _planar_flag = false; + _alpha_flag = false; + _subspl_h = -1; + _subspl_v = -1; +} + + + +// Converts from an Avisynth colorspace +// http://avisynth.nl/index.php/Convert +// Returns 0 if everything is OK. +int FmtAvs::conv_from_str (std::string fmt_str) +{ + invalidate (); + + fmt_str = remove_outer_spaces (fmt_str); + fstb::conv_to_lower_case (fmt_str); + + if (is_eq_leftstr_and_eat (fmt_str, "rgb")) + { + _col_fam = fmtcl::ColorFamily_RGB; + _subspl_h = 0; // Required for consistency + _subspl_v = 0; + if (fmt_str.empty ()) + { + return -1; // Nothing specified after "RGB" + } + + if (fmt_str.front () == 'a') + { + _planar_flag = true; + _alpha_flag = true; + fmt_str.erase (0, 1); + if (fmt_str.empty ()) + { + return -1; // We need the bitdepth + } + } + + // Planar + if (check_planar_bits_and_eat (fmt_str, _bitdepth)) + { + if (_bitdepth < 0) + { + return -1; // Ill-formed string or invalid bitdepth + } + } + + // Interleaved + else + { + if (_planar_flag) + { + return -1; // Interleaved format is always RGBxx, not RGBAxx + } + size_t pos = 0; + const int val_bits = std::stoi (fmt_str, &pos, 10); + if (fmt_str.length () != pos) + { + return -1; // Garbage after RGBxx + } + switch (val_bits) + { + case 24: _bitdepth = 8; _alpha_flag = false; break; + case 32: _bitdepth = 8; _alpha_flag = true; break; + case 48: _bitdepth = 16; _alpha_flag = false; break; + case 64: _bitdepth = 16; _alpha_flag = true; break; + default: return -1; // Invalid bitdepth/alpha combination + } + } + } + + else if (is_eq_leftstr_and_eat (fmt_str, "yuy2")) + { + _col_fam = fmtcl::ColorFamily_YUV; + _bitdepth = 8; + _subspl_h = 1; + _subspl_v = 0; + + if (! fmt_str.empty ()) + { + return -1; // Garbage after YUY2 + } + } + + else if (is_eq_leftstr_and_eat (fmt_str, "yuv")) + { + _col_fam = fmtcl::ColorFamily_YUV; + _planar_flag = true; + + if (fmt_str.front () == 'a') + { + _alpha_flag = true; + fmt_str.erase (0, 1); + if (fmt_str.empty ()) + { + return -1; // We need chroma subsampling + planar bitdepth + } + } + + size_t pos = 0; + const int css = std::stoi (fmt_str, &pos, 10); + fmt_str.erase (0, pos); + switch (css) + { + case 420: _subspl_h = 1; _subspl_v = 1; break; + case 422: _subspl_h = 1; _subspl_v = 0; break; + case 444: _subspl_h = 0; _subspl_v = 0; break; + default: return -1; // Invalid chroma subsampling + } + + if (! check_planar_bits_and_eat (fmt_str, _bitdepth)) + { + return -1; + } + if (_bitdepth < 0) + { + return -1; // Ill-formed string or invalid bitdepth + } + } + + else if (is_eq_leftstr_and_eat (fmt_str, "yv")) + { + _col_fam = fmtcl::ColorFamily_YUV; + _planar_flag = true; + _bitdepth = 8; + size_t pos = 0; + const int val_bits = std::stoi (fmt_str, &pos, 10); + if (fmt_str.length () != pos) + { + return -1; // Garbage after YVxx + } + switch (val_bits) + { + case 12: _subspl_h = 1; _subspl_v = 1; break; + case 16: _subspl_h = 1; _subspl_v = 0; break; + case 24: _subspl_h = 0; _subspl_v = 0; break; + case 411: _subspl_h = 2; _subspl_v = 0; break; + default: return -1; // Invalid chroma subsampling + } + } + + else if (is_eq_leftstr_and_eat (fmt_str, "y")) + { + _col_fam = fmtcl::ColorFamily_GRAY; + _planar_flag = true; + _subspl_h = 0; // Required for consistency + _subspl_v = 0; + _bitdepth = check_bits_and_eat (fmt_str, false); + if (_bitdepth < 0) + { + return -1; // Ill-formed or unsupported bitdepth + } + } + + return 0; +} + + + +// Assumes pixel_type is valid +void FmtAvs::conv_from_vi (const VideoInfo &vi) +{ + invalidate (); + + _bitdepth = vi.BitsPerComponent (); + _planar_flag = vi.IsPlanar (); + + if (vi.IsRGB ()) + { + _col_fam = fmtcl::ColorFamily_RGB; + _subspl_h = 0; // Required for consistency + _subspl_v = 0; + _alpha_flag = (vi.IsRGB32 () || vi.IsRGB64 ()); + } + else if (vi.IsY ()) + { + _col_fam = fmtcl::ColorFamily_GRAY; + _subspl_h = 0; // Required for consistency + _subspl_v = 0; + } + else + { + assert (vi.IsYUV () || vi.IsYUVA ()); + _col_fam = fmtcl::ColorFamily_YUV; + _alpha_flag = vi.IsYUVA (); + _subspl_h = ((vi.pixel_type >> VideoInfo::CS_Shift_Sub_Width ) + 1) & 3; + _subspl_v = ((vi.pixel_type >> VideoInfo::CS_Shift_Sub_Height) + 1) & 3; + } +} + + + +// Returns 0 if conversion is OK. +int FmtAvs::conv_to_vi (VideoInfo &vi) +{ + assert (is_valid ()); + + int pixel_type = 0; + + switch (_bitdepth) + { + case 8: pixel_type |= VideoInfo::CS_Sample_Bits_8; break; + case 10: pixel_type |= VideoInfo::CS_Sample_Bits_10; break; + case 12: pixel_type |= VideoInfo::CS_Sample_Bits_12; break; + case 14: pixel_type |= VideoInfo::CS_Sample_Bits_14; break; + case 16: pixel_type |= VideoInfo::CS_Sample_Bits_16; break; + case 32: pixel_type |= VideoInfo::CS_Sample_Bits_32; break; + default: return -1; // Bitdepth not supported + } + + if (_col_fam == fmtcl::ColorFamily_GRAY) + { + // Chroma subsampling is ignored + if (_alpha_flag) + { + return -1; + } + pixel_type |= VideoInfo::CS_GENERIC_Y; + } + + else if (_col_fam == fmtcl::ColorFamily_RGB) + { + // Chroma subsampling is ignored + pixel_type |= VideoInfo::CS_BGR; + pixel_type |= (_alpha_flag) + ? VideoInfo::CS_RGBA_TYPE + : VideoInfo::CS_RGB_TYPE; + + if (_planar_flag) + { + pixel_type |= VideoInfo::CS_PLANAR; + } + else + { + if (_bitdepth != 8 && _bitdepth != 16) + { + return -1; + } + pixel_type |= VideoInfo::CS_INTERLEAVED; + } + } + + else if (_col_fam == fmtcl::ColorFamily_YUV) + { + if (_planar_flag) + { + pixel_type |= VideoInfo::CS_YUY2; + pixel_type |= VideoInfo::CS_PLANAR; + pixel_type |= VideoInfo::CS_VPlaneFirst; + pixel_type |= (_alpha_flag) ? VideoInfo::CS_YUVA : VideoInfo::CS_YUV; + + switch ((_subspl_v << 4) | _subspl_h) + { + case 0x00: + pixel_type |= VideoInfo::CS_Sub_Height_1 | VideoInfo::CS_Sub_Width_1; + break; + case 0x01: + pixel_type |= VideoInfo::CS_Sub_Height_1 | VideoInfo::CS_Sub_Width_2; + break; + case 0x11: + pixel_type |= VideoInfo::CS_Sub_Height_2 | VideoInfo::CS_Sub_Width_2; + break; + case 0x02: + pixel_type |= VideoInfo::CS_Sub_Height_1 | VideoInfo::CS_Sub_Width_4; + if (_alpha_flag || _bitdepth != 8) + { + return -1; // Only YV411 in 4:1:1 + } + break; + /**** To do: should we allow 4:1:0 (YUV9)? It is in the API but it + seems Avisynth filter don't use it. + http://avisynth.nl/index.php/Avisynthplus_color_formats + ***/ + default: + return -1; // Invalid chroma subsampling + } + } + else + { + // Only YUY2 allowed with interleaved formats + if (_bitdepth != 8 || _alpha_flag || _subspl_h != 1 || _subspl_v != 0) + { + return -1; + } + pixel_type = VideoInfo::CS_YUY2; + } + } + + else + { + return -1; + } + + vi.pixel_type = pixel_type; + + return 0; +} + + + +bool FmtAvs::is_valid () const noexcept +{ + return ( + _bitdepth > 0 && _col_fam >= 0 + && _subspl_h >= 0 && _subspl_v >= 0); +} + + + +void FmtAvs::set_bitdepth (int bitdepth) noexcept +{ + assert (is_bitdepth_valid (bitdepth)); + + _bitdepth = bitdepth; +} + + + +int FmtAvs::get_bitdepth () const noexcept +{ + assert (is_valid ()); + + return _bitdepth; +} + + + +bool FmtAvs::is_float () const noexcept +{ + assert (is_valid ()); + + return (_bitdepth >= 32); +} + + + +void FmtAvs::set_col_fam (fmtcl::ColorFamily col_fam) noexcept +{ + assert (col_fam >= 0); + assert (col_fam < fmtcl::ColorFamily_NBR_ELT); + assert (col_fam != fmtcl::ColorFamily_YCGCO); + + _col_fam = col_fam; +} + + + +fmtcl::ColorFamily FmtAvs::get_col_fam () const noexcept +{ + assert (is_valid ()); + + return _col_fam; +} + + + +bool FmtAvs::is_planar () const noexcept +{ + assert (is_valid ()); + + return _planar_flag; +} + + + +bool FmtAvs::has_alpha () const noexcept +{ + assert (is_valid ()); + + return _alpha_flag; +} + + + +int FmtAvs::get_subspl_h () const noexcept +{ + assert (is_valid ()); + + return _subspl_h; +} + + + +int FmtAvs::get_subspl_v () const noexcept +{ + assert (is_valid ()); + + return _subspl_v; +} + + + +int FmtAvs::get_nbr_comp_non_alpha () const noexcept +{ + assert (is_valid ()); + + return (_col_fam == fmtcl::ColorFamily_GRAY) ? 1 : 3; +} + + + +bool FmtAvs::is_bitdepth_valid (int bitdepth) noexcept +{ + return ( + bitdepth == 8 + || bitdepth == 10 + || bitdepth == 12 + || bitdepth == 14 + || bitdepth == 16 + || bitdepth == 32 + ); +} + + + +/*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + + + +/*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + + + +std::string FmtAvs::remove_outer_spaces (std::string str) +{ + while (! str.empty () && std::isspace (str.back ()) != 0) + { + str.pop_back (); + } + while (! str.empty () && std::isspace (str.front ()) != 0) + { + str.erase (0, 1); + } + + return str; +} + + + +bool FmtAvs::is_eq_leftstr_and_eat (std::string &str, std::string stest) +{ + const auto len = stest.length (); + if (str.substr (0, len) == stest) + { + str.erase (0, len); + return true; + } + + return false; +} + + + +// str must be lower-case +// If the string is ill-formed, returns true and res < 0 +// As the pxx value should be last, the string is considered ill-formed +// if there are characters after the resolution. +bool FmtAvs::check_planar_bits_and_eat (std::string &str, int &res) +{ + if (! str.empty () && str.front () == 'p') + { + str.erase (0, 1); + if (str.empty ()) + { + res = -1; + return true; + } + res = check_bits_and_eat (str, true); + return true; + } + + return false; +} + + + +int FmtAvs::check_bits_and_eat (std::string &str, bool allow_s_flag) +{ + int res = -1; + + if (str.empty ()) + { + return -1; + } + + if (str [0] == 's') + { + if (! allow_s_flag) + { + return -1; + } + res = 32; + str.erase (0, 1); + } + else + { + size_t pos = 0; + res = std::stoi (str, &pos, 10); + switch (res) + { + case 8: + case 10: + case 12: + case 14: + case 16: + case 32: + break; + default: + return -1; + } + str.erase (0, pos); + } + + if (! str.empty ()) + { + return -1; + } + + return res; +} + + + +} // namespace fmtcavs + + + +/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ diff --git a/src/fmtcavs/FmtAvs.h b/src/fmtcavs/FmtAvs.h new file mode 100644 index 0000000..7b53bb5 --- /dev/null +++ b/src/fmtcavs/FmtAvs.h @@ -0,0 +1,128 @@ +/***************************************************************************** + + FmtAvs.h + Author: Laurent de Soras, 2021 + +--- Legal stuff --- + +This program is free software. It comes without any warranty, to +the extent permitted by applicable law. You can redistribute it +and/or modify it under the terms of the Do What The Fuck You Want +To Public License, Version 2, as published by Sam Hocevar. See +http://www.wtfpl.net/ for more details. + +*Tab=3***********************************************************************/ + + + +#pragma once +#if ! defined (fmtcavs_FmtAvs_HEADER_INCLUDED) +#define fmtcavs_FmtAvs_HEADER_INCLUDED + + + +/*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +#include "fmtcl/ColorFamily.h" + +#include + + + +struct VideoInfo; + +namespace fmtcavs +{ + + + +class FmtAvs +{ + +/*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +public: + + explicit FmtAvs (std::string fmt_str); + explicit FmtAvs (const VideoInfo &vi) noexcept; + FmtAvs () = default; + FmtAvs (const FmtAvs &other) = default; + FmtAvs (FmtAvs &&other) = default; + ~FmtAvs () = default; + FmtAvs & operator = (const FmtAvs &other) = default; + FmtAvs & operator = (FmtAvs &&other) = default; + + void invalidate () noexcept; + int conv_from_str (std::string fmt_str); + void conv_from_vi (const VideoInfo &vi); + int conv_to_vi (VideoInfo &vi); + + bool is_valid () const noexcept; + + void set_bitdepth (int bitdepth) noexcept; + int get_bitdepth () const noexcept; + bool is_float () const noexcept; + void set_col_fam (fmtcl::ColorFamily col_fam) noexcept; + fmtcl::ColorFamily + get_col_fam () const noexcept; + bool is_planar () const noexcept; + bool has_alpha () const noexcept; + int get_subspl_h () const noexcept; + int get_subspl_v () const noexcept; + + int get_nbr_comp_non_alpha () const noexcept; + + static bool is_bitdepth_valid (int bitdepth) noexcept; + + + +/*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +protected: + + + +/*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +private: + + static std::string + remove_outer_spaces (std::string str); + static bool is_eq_leftstr_and_eat (std::string &str, std::string stest); + static bool check_planar_bits_and_eat (std::string &str, int &res); + static int check_bits_and_eat (std::string &str, bool allow_s_flag); + + int _bitdepth = -1; + fmtcl::ColorFamily + _col_fam = fmtcl::ColorFamily_INVALID; + bool _planar_flag = false; // Y formats are considered planar + bool _alpha_flag = false; + int _subspl_h = -1; // Bitshift, >= 0. Negative: invalid + int _subspl_v = -1; // Same + + + +/*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +private: + + bool operator == (const FmtAvs &other) const = delete; + bool operator != (const FmtAvs &other) const = delete; + +}; // class FmtAvs + + + +} // namespace fmtcavs + + + +//#include "fmtcavs/FmtAvs.hpp" + + + +#endif // fmtcavs_FmtAvs_HEADER_INCLUDED + + + +/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ diff --git a/src/fmtcavs/Matrix.cpp b/src/fmtcavs/Matrix.cpp new file mode 100644 index 0000000..6730316 --- /dev/null +++ b/src/fmtcavs/Matrix.cpp @@ -0,0 +1,498 @@ +/***************************************************************************** + + Matrix.cpp + Author: Laurent de Soras, 2021 + +--- Legal stuff --- + +This program is free software. It comes without any warranty, to +the extent permitted by applicable law. You can redistribute it +and/or modify it under the terms of the Do What The Fuck You Want +To Public License, Version 2, as published by Sam Hocevar. See +http://www.wtfpl.net/ for more details. + +*Tab=3***********************************************************************/ + + + +#if defined (_MSC_VER) + #pragma warning (1 : 4130 4223 4705 4706) + #pragma warning (4 : 4355 4786 4800) +#endif + + + +/*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +#include "avsutl/CsPlane.h" +#include "fmtcavs/CpuOpt.h" +#include "fmtcavs/fnc.h" +#include "fmtcavs/function_names.h" +#include "fmtcavs/Matrix.h" +#include "fmtcl/fnc.h" +#include "fmtcl/MatrixUtil.h" +#include "fstb/fnc.h" + +#include + + + +namespace fmtcavs +{ + + + +/*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + + + +Matrix::Matrix (::IScriptEnvironment &env, const ::AVSValue &args) +: Inherited (env, args [Param_CLIP_SRC].AsClip ()) +, _clip_src_sptr (args [Param_CLIP_SRC].AsClip ()) +, _vi_src (vi) +, _plane_out (args [Param_SINGLEOUT].AsInt (-1)) +{ + const CpuOpt cpu_opt (args [Param_CPUOPT]); + const bool sse_flag = cpu_opt.has_sse (); + const bool sse2_flag = cpu_opt.has_sse2 (); + const bool avx_flag = cpu_opt.has_avx (); + const bool avx2_flag = cpu_opt.has_avx2 (); + + _proc_uptr = std::make_unique ( + sse_flag, sse2_flag, avx_flag, avx2_flag + ); + + // Checks the input clip + if (! _vi_src.IsPlanar ()) + { + env.ThrowError (fmtcavs_MATRIX ": input must be planar."); + } + + const FmtAvs fmt_src (_vi_src); + if (fmt_src.get_subspl_h () != 0 || fmt_src.get_subspl_v () != 0) + { + env.ThrowError (fmtcavs_MATRIX ": input must be 4:4:4."); + } + const int nbr_planes_src = _vi_src.NumComponents (); + if (nbr_planes_src < _nbr_planes_proc) + { + env.ThrowError ( + fmtcavs_MATRIX ": greyscale format not supported as input." + ); + } + const int bd_src = fmt_src.get_bitdepth (); + if ( ( bd_src < 8 + || bd_src > 12) + && bd_src != 14 + && bd_src != 16 + && bd_src != 32 ) + { + env.ThrowError (fmtcavs_MATRIX ": pixel bitdepth not supported."); + } + + // Plane index for single plane output (0-2), or a negative number if all + // planes are processed. + if (_plane_out >= _nbr_planes_proc) + { + env.ThrowError (fmtcavs_MATRIX + ": singleout is a plane index and must be -1 or ranging from 0 to 3." + ); + } + + // Destination colorspace + bool force_col_fam_flag; + FmtAvs fmt_dst = get_output_colorspace ( + env, args, fmt_src, _plane_out, force_col_fam_flag + ); + + if ( fmt_dst.is_float () != fmt_src.is_float () + || fmt_dst.get_bitdepth () < fmt_src.get_bitdepth () + || fmt_dst.get_subspl_h () != fmt_src.get_subspl_h () + || fmt_dst.get_subspl_v () != fmt_src.get_subspl_v ()) + { + env.ThrowError (fmtcavs_MATRIX + ": specified output colorspace is not compatible with the input." + ); + } + + // Preliminary matrix test: deduces the target color family if unspecified + if ( ! force_col_fam_flag + && fmt_dst.get_col_fam () != fmtcl::ColorFamily_GRAY) + { + int def_count = 0; + def_count += args [Param_MAT ].Defined () ? 1 : 0; + def_count += args [Param_MATS].Defined () ? 1 : 0; + def_count += args [Param_MATD].Defined () ? 1 : 0; + if (def_count == 1) + { + std::string tmp_mat; + tmp_mat = args [Param_MAT ].AsString (tmp_mat.c_str ()); + tmp_mat = args [Param_MATS].AsString (tmp_mat.c_str ()); + tmp_mat = args [Param_MATD].AsString (tmp_mat.c_str ()); + fstb::conv_to_lower_case (tmp_mat); + + const auto tmp_csp = find_cs_from_mat_str (env, tmp_mat, false); + fmt_dst = find_dst_col_fam (tmp_csp, fmt_dst, fmt_src); + } + } + + // Output format is validated + if (fmt_dst.conv_to_vi (vi) != 0) + { + env.ThrowError (fmtcavs_MATRIX ": illegal output colorspace."); + } + + const int nbr_expected_coef = _nbr_planes_proc * (_nbr_planes_proc + 1); + + bool mat_init_flag = false; + fmtcl::Mat4 mat_main; // Main matrix, float input, float output + + // Matrix presets + std::string mat (args [Param_MAT].AsString ("")); + std::string mats (( + fmt_src.get_col_fam () == fmtcl::ColorFamily_YUV ) ? mat : "" + ); + std::string matd ( + ( fmt_dst.get_col_fam () == fmtcl::ColorFamily_YUV + || fmt_dst.get_col_fam () == fmtcl::ColorFamily_GRAY) ? mat : "" + ); + mats = args [Param_MATS].AsString (mats.c_str ()); + matd = args [Param_MATD].AsString (matd.c_str ()); + _csp_out = fmtcl::ColorSpaceH265_UNSPECIFIED; + if (! mats.empty () || ! matd.empty ()) + { + fstb::conv_to_lower_case (mats); + fstb::conv_to_lower_case (matd); + fmtcl::MatrixUtil::select_def_mat (mats, fmt_src.get_col_fam ()); + fmtcl::MatrixUtil::select_def_mat (matd, fmt_dst.get_col_fam ()); + + fmtcl::Mat4 m2s; + fmtcl::Mat4 m2d; + if (fmtcl::MatrixUtil::make_mat_from_str (m2s, mats, true) != 0) + { + env.ThrowError ( + fmtcavs_MATRIX ": unknown source matrix identifier." + ); + } + if (fmtcl::MatrixUtil::make_mat_from_str (m2d, matd, false) != 0) + { + env.ThrowError ( + fmtcavs_MATRIX ": unknown destination matrix identifier." + ); + } + _csp_out = find_cs_from_mat_str (env, matd, false); + + mat_main = m2d * m2s; + mat_init_flag = true; + } + + // Range + _fulls_flag = args [Param_FULLS].AsBool ( + fmtcl::is_full_range_default (fmt_src.get_col_fam ()) + ); + _fulld_flag = args [Param_FULLD].AsBool ( + fmtcl::is_full_range_default (fmt_dst.get_col_fam ()) + ); + _range_def_flag = args [Param_FULLD].Defined (); + + // Alpha plane processing, if any + _proc_alpha_uptr = std::make_unique ( + fmt_dst, fmt_src, _fulld_flag, _fulls_flag, vi.width, vi.height, cpu_opt + ); + + // Custom coefficients + const auto coef_list = + fmtcl::conv_str_to_float_arr (args [Param_COEF].AsString ("")); + const int nbr_coef = int (coef_list.size ()); + const bool custom_mat_flag = (nbr_coef > 0); + const int nbr_proc_planes_src = fmt_src.get_nbr_comp_non_alpha (); + const int nbr_proc_planes_dst = fmt_dst.get_nbr_comp_non_alpha (); + if (custom_mat_flag) + { + if (nbr_coef != nbr_expected_coef) + { + env.ThrowError ( + fmtcavs_MATRIX ": coef has a wrong number of elements." + ); + } + + for (int y = 0; y < _nbr_planes_proc + 1; ++y) + { + for (int x = 0; x < _nbr_planes_proc + 1; ++x) + { + mat_main [y] [x] = (x == y) ? 1 : 0; + + if ( (x < nbr_proc_planes_src || x == _nbr_planes_proc) + && y < nbr_proc_planes_dst) + { + const int index = y * (nbr_proc_planes_src + 1) + x; + mat_main [y] [x] = coef_list [index]; + } + } + } + + mat_init_flag = true; + } + + if (! mat_init_flag) + { + env.ThrowError (fmtcavs_MATRIX + ": you must specify a matrix preset or a custom coefficient list." + ); + } + + // Fixes the output colorspace to a valid H265 colorspace + switch (_csp_out) + { + case fmtcl::ColorSpaceH265_LMS: + _csp_out = fmtcl::ColorSpaceH265_RGB; + break; + case fmtcl::ColorSpaceH265_ICTCP_PQ: + case fmtcl::ColorSpaceH265_ICTCP_HLG: + _csp_out = fmtcl::ColorSpaceH265_ICTCP; + break; + default: + // Nothing to do + break; + } + + prepare_matrix_coef ( + env, *_proc_uptr, mat_main, + fmt_dst, _fulld_flag, + fmt_src, _fulls_flag, + _csp_out, _plane_out + ); +} + + + +// mat should be already converted to lower case +fmtcl::ColorSpaceH265 Matrix::find_cs_from_mat_str (::IScriptEnvironment &env, const std::string &mat, bool allow_2020cl_flag) +{ + const auto cs = + fmtcl::MatrixUtil::find_cs_from_mat_str (mat, allow_2020cl_flag); + if (cs == fmtcl::ColorSpaceH265_UNDEF) + { + env.ThrowError ("Unknown matrix identifier."); + } + + return cs; +} + + + +::PVideoFrame __stdcall Matrix::GetFrame (int n, ::IScriptEnvironment *env_ptr) +{ + ::PVideoFrame src_sptr = _clip_src_sptr->GetFrame (n, env_ptr); + ::PVideoFrame dst_sptr = build_new_frame (*env_ptr, vi, &src_sptr); + + const int p0d = avsutl::CsPlane::get_plane_id (0, vi); + const int p1d = avsutl::CsPlane::get_plane_id (1, vi); + const int p2d = avsutl::CsPlane::get_plane_id (2, vi); + + const int p0s = avsutl::CsPlane::get_plane_id (0, _vi_src); + const int p1s = avsutl::CsPlane::get_plane_id (1, _vi_src); + const int p2s = avsutl::CsPlane::get_plane_id (2, _vi_src); + + const int w = vi.width; + const int h = vi.height; + + uint8_t * const dst_ptr_arr [fmtcl::MatrixProc::_nbr_planes] = + { + dst_sptr->GetWritePtr (p0d), + (_plane_out >= 0) ? nullptr : dst_sptr->GetWritePtr (p1d), + (_plane_out >= 0) ? nullptr : dst_sptr->GetWritePtr (p2d) + }; + const int dst_str_arr [fmtcl::MatrixProc::_nbr_planes] = + { + dst_sptr->GetPitch (p0d), + (_plane_out >= 0) ? 0 : dst_sptr->GetPitch (p1d), + (_plane_out >= 0) ? 0 : dst_sptr->GetPitch (p2d) + }; + + const uint8_t * const + src_ptr_arr [fmtcl::MatrixProc::_nbr_planes] = + { + src_sptr->GetReadPtr (p0s), + src_sptr->GetReadPtr (p1s), + src_sptr->GetReadPtr (p2s) + }; + const int src_str_arr [fmtcl::MatrixProc::_nbr_planes] = + { + src_sptr->GetPitch (p0s), + src_sptr->GetPitch (p1s), + src_sptr->GetPitch (p2s) + }; + + _proc_uptr->process ( + dst_ptr_arr, dst_str_arr, + src_ptr_arr, src_str_arr, + w, h + ); + + // Alpha plane now + _proc_alpha_uptr->process_plane (dst_sptr, src_sptr); + + // Frame properties + if (supports_props ()) + { + ::AVSMap * props_ptr = env_ptr->getFramePropsRW (dst_sptr); + + if (_range_def_flag) + { + const int cr_val = (_fulld_flag) ? 0 : 1; + env_ptr->propSetInt ( + props_ptr, "_ColorRange", cr_val, ::PROPAPPENDMODE_REPLACE + ); + } + + if ( _csp_out != fmtcl::ColorSpaceH265_UNSPECIFIED + && _csp_out <= fmtcl::ColorSpaceH265_ISO_RANGE_LAST) + { + env_ptr->propSetInt ( + props_ptr, "_Matrix" , int (_csp_out), ::PROPAPPENDMODE_REPLACE + ); + env_ptr->propSetInt ( + props_ptr, "_ColorSpace", int (_csp_out), ::PROPAPPENDMODE_REPLACE + ); + } + else + { + env_ptr->propDeleteKey (props_ptr, "_Matrix"); + env_ptr->propDeleteKey (props_ptr, "_ColorSpace"); + } + } + + return dst_sptr; +} + + + +/*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + + + +/*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + + + +constexpr int Matrix::_nbr_planes_proc; + + + +FmtAvs Matrix::get_output_colorspace (::IScriptEnvironment &env, const ::AVSValue &args, const FmtAvs &fmt_src, int &plane_out, bool &force_col_fam_flag) +{ + force_col_fam_flag = false; + + FmtAvs fmt_dst = fmt_src; + + // Full colorspace + if (args [Param_CSP].Defined ()) + { + if (fmt_dst.conv_from_str (args [Param_CSP].AsString ()) != 0) + { + env.ThrowError (fmtcavs_MATRIX ": invalid output colorspace."); + } + else + { + force_col_fam_flag = true; + } + } + + if (! fmt_dst.is_planar ()) + { + env.ThrowError (fmtcavs_MATRIX ": output colorspace must be planar."); + } + + if (args [Param_COL_FAM].Defined ()) + { + force_col_fam_flag = true; + const auto col_fam = + conv_str_to_colfam (args [Param_COL_FAM].AsString ()); + if (col_fam == fmtcl::ColorFamily_INVALID) + { + env.ThrowError (fmtcavs_MATRIX ": invalid col_fam."); + } + fmt_dst.set_col_fam (col_fam); + } + + if (plane_out >= 0) + { + fmt_dst.set_col_fam (fmtcl::ColorFamily_GRAY); + } + else if (fmt_dst.get_col_fam () == fmtcl::ColorFamily_GRAY) + { + plane_out = 0; + } + + const int bitdepth = args [Param_BITS].AsInt (fmt_dst.get_bitdepth ()); + if (! FmtAvs::is_bitdepth_valid (bitdepth)) + { + env.ThrowError (fmtcavs_MATRIX ": invalid bitdepth."); + } + else + { + fmt_dst.set_bitdepth (bitdepth); + } + + return fmt_dst; +} + + + +FmtAvs Matrix::find_dst_col_fam (fmtcl::ColorSpaceH265 tmp_csp, FmtAvs fmt_dst, const FmtAvs &fmt_src) +{ + fmtcl::ColorFamily alt_cf = fmtcl::ColorFamily_INVALID; + + switch (tmp_csp) + { + case fmtcl::ColorSpaceH265_RGB: + case fmtcl::ColorSpaceH265_BT709: + case fmtcl::ColorSpaceH265_FCC: + case fmtcl::ColorSpaceH265_BT470BG: + case fmtcl::ColorSpaceH265_SMPTE170M: + case fmtcl::ColorSpaceH265_SMPTE240M: + case fmtcl::ColorSpaceH265_YCGCO: + case fmtcl::ColorSpaceH265_BT2020NCL: + case fmtcl::ColorSpaceH265_BT2020CL: + case fmtcl::ColorSpaceH265_YDZDX: + case fmtcl::ColorSpaceH265_CHRODERNCL: + case fmtcl::ColorSpaceH265_CHRODERCL: + case fmtcl::ColorSpaceH265_ICTCP: + case fmtcl::ColorSpaceH265_ICTCP_PQ: + case fmtcl::ColorSpaceH265_ICTCP_HLG: + alt_cf = fmtcl::ColorFamily_YUV; + break; + + case fmtcl::ColorSpaceH265_LMS: + alt_cf = fmtcl::ColorFamily_RGB; + break; + + default: + // Nothing + break; + } + + if (alt_cf != fmtcl::ColorFamily_INVALID) + { + const auto col_fam_src = fmt_src.get_col_fam (); + if (col_fam_src == fmtcl::ColorFamily_RGB) + { + fmt_dst.set_col_fam (alt_cf); + } + else if (col_fam_src == alt_cf) + { + fmt_dst.set_col_fam (fmtcl::ColorFamily_RGB); + } + } + + return fmt_dst; +} + + + +} // namespace fmtcavs + + + +/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ diff --git a/src/fmtcavs/Matrix.h b/src/fmtcavs/Matrix.h new file mode 100644 index 0000000..977327f --- /dev/null +++ b/src/fmtcavs/Matrix.h @@ -0,0 +1,143 @@ +/***************************************************************************** + + Matrix.h + Author: Laurent de Soras, 2021 + +--- Legal stuff --- + +This program is free software. It comes without any warranty, to +the extent permitted by applicable law. You can redistribute it +and/or modify it under the terms of the Do What The Fuck You Want +To Public License, Version 2, as published by Sam Hocevar. See +http://www.wtfpl.net/ for more details. + +*Tab=3***********************************************************************/ + + + +#pragma once +#if ! defined (fmtcavs_Matrix_HEADER_INCLUDED) +#define fmtcavs_Matrix_HEADER_INCLUDED + + + +/*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +#include "avsutl/VideoFilterBase.h" +#include "fmtcavs/FmtAvs.h" +#include "fmtcavs/ProcAlpha.h" +#include "fmtcl/ColorSpaceH265.h" +#include "fmtcl/MatrixProc.h" + +#include +#include + + + +namespace fmtcavs +{ + + + +class Matrix +: public avsutl::VideoFilterBase +{ +/*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +public: + + typedef avsutl::VideoFilterBase Inherited; + + enum Param + { + Param_CLIP_SRC = 0, + Param_MAT, + Param_MATS, + Param_MATD, + Param_FULLS, + Param_FULLD, + Param_COEF, + Param_CSP, + Param_COL_FAM, + Param_BITS, + Param_SINGLEOUT, + Param_CPUOPT, + + Param_NBR_ELT + }; + + explicit Matrix (::IScriptEnvironment &env, const ::AVSValue &args); + virtual ~Matrix () = default; + + // VideoFilterBase + ::PVideoFrame __stdcall + GetFrame (int n, ::IScriptEnvironment *env_ptr) override; + + static fmtcl::ColorSpaceH265 + find_cs_from_mat_str (::IScriptEnvironment &env, const std::string &mat, bool allow_2020cl_flag); + + + +/*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +protected: + + + +/*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +private: + + static constexpr int _nbr_planes_proc = fmtcl::MatrixProc::_nbr_planes; + + FmtAvs get_output_colorspace (::IScriptEnvironment &env, const ::AVSValue &args, const FmtAvs &fmt_src, int &plane_out, bool &force_col_fam_flag); + FmtAvs find_dst_col_fam (fmtcl::ColorSpaceH265 tmp_csp, FmtAvs fmt_dst, const FmtAvs &fmt_src); + + ::PClip _clip_src_sptr; + const ::VideoInfo + _vi_src; + + int _plane_out = -1; + std::unique_ptr + _proc_uptr; + + std::unique_ptr + _proc_alpha_uptr; + + bool _range_def_flag = false; + bool _fulls_flag = false; + bool _fulld_flag = false; + fmtcl::ColorSpaceH265 + _csp_out = fmtcl::ColorSpaceH265_UNDEF; + + + +/*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +private: + + Matrix () = delete; + Matrix (const Matrix &other) = delete; + Matrix (Matrix &&other) = delete; + Matrix & operator = (const Matrix &other) = delete; + Matrix & operator = (Matrix &&other) = delete; + bool operator == (const Matrix &other) const = delete; + bool operator != (const Matrix &other) const = delete; + +}; // class Matrix + + + +} // namespace fmtcavs + + + +//#include "fmtcavs/Matrix.hpp" + + + +#endif // fmtcavs_Matrix_HEADER_INCLUDED + + + +/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ diff --git a/src/fmtcavs/ProcAlpha.cpp b/src/fmtcavs/ProcAlpha.cpp new file mode 100644 index 0000000..4d11633 --- /dev/null +++ b/src/fmtcavs/ProcAlpha.cpp @@ -0,0 +1,140 @@ +/***************************************************************************** + + ProcAlpha.cpp + Author: Laurent de Soras, 2021 + +--- Legal stuff --- + +This program is free software. It comes without any warranty, to +the extent permitted by applicable law. You can redistribute it +and/or modify it under the terms of the Do What The Fuck You Want +To Public License, Version 2, as published by Sam Hocevar. See +http://www.wtfpl.net/ for more details. + +*Tab=3***********************************************************************/ + + + +#if defined (_MSC_VER) + #pragma warning (1 : 4130 4223 4705 4706) + #pragma warning (4 : 4355 4786 4800) +#endif + + + +/*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +#include "avsutl/CsPlane.h" +#include "avsutl/fnc.h" +#include "fmtcavs/CpuOpt.h" +#include "fmtcavs/fnc.h" +#include "fmtcavs/ProcAlpha.h" +#include "fmtcl/fnc.h" +#include "avisynth.h" + +#include + + + +namespace fmtcavs +{ + + + +/*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + + + +// w and h in pixels +ProcAlpha::ProcAlpha (FmtAvs fmt_dst, FmtAvs fmt_src, bool fulld_flag, bool fulls_flag, int w, int h, const CpuOpt &cpu_opt) +: _dst_a_flag (fmt_dst.has_alpha ()) +, _src_a_flag (fmt_src.has_alpha ()) +, _dst_res (fmt_dst.get_bitdepth ()) +, _src_res (fmt_dst.get_bitdepth ()) +, _splfmt_dst (conv_bitdepth_to_splfmt (_dst_res)) +, _splfmt_src (conv_bitdepth_to_splfmt (_src_res)) +, _w (w) +, _h (h) +, _scale_info () +, _sse2_flag (cpu_opt.has_sse2 ()) +, _avx2_flag (cpu_opt.has_avx2 ()) +{ + if (_dst_a_flag && _src_a_flag) + { + const auto col_fam_dst = fmt_dst.get_col_fam (); + const auto col_fam_src = fmt_src.get_col_fam (); + fmtcl::compute_fmt_mac_cst ( + _scale_info._gain, + _scale_info._add_cst, + fmtcl::PicFmt { _splfmt_dst, _dst_res, col_fam_dst, fulld_flag }, + fmtcl::PicFmt { _splfmt_src, _src_res, col_fam_src, fulls_flag }, + avsutl::CsPlane::_plane_index_alpha + ); + } +} + + + +void ProcAlpha::process_plane (::PVideoFrame &dst_sptr, ::PVideoFrame &src_sptr) const +{ + if (_dst_a_flag) + { + uint8_t * dst_ptr = dst_sptr->GetWritePtr (::PLANAR_A); + const int dst_stride = dst_sptr->GetPitch (::PLANAR_A); + + // Copy + if (_src_a_flag) + { + const uint8_t* src_ptr = src_sptr->GetReadPtr (::PLANAR_A); + const int src_stride = src_sptr->GetPitch (::PLANAR_A); + + fmtcl::BitBltConv blitter (_sse2_flag, _avx2_flag); + blitter.bitblt ( + _splfmt_dst, _dst_res, dst_ptr, nullptr, dst_stride, + _splfmt_src, _src_res, src_ptr, nullptr, src_stride, + _w, _h, + &_scale_info + ); + } + + // Fill with full opacity + else + { + switch (_splfmt_dst) + { + case fmtcl::SplFmt_FLOAT: + avsutl::fill_block (dst_ptr, 1.f, dst_stride, _w, _h); + break; + case fmtcl::SplFmt_INT16: + { + const auto v = uint16_t ((1 << _dst_res) - 1); + avsutl::fill_block (dst_ptr, v, dst_stride, _w, _h); + } + break; + case fmtcl::SplFmt_INT8: + avsutl::fill_block (dst_ptr, uint8_t (0xFF), dst_stride, _w, _h); + break; + default: + // Other formats not supported + assert (false); + break; + } + } + } +} + + + +/*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + + + +/*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + + + +} // namespace fmtcavs + + + +/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ diff --git a/src/fmtcavs/ProcAlpha.h b/src/fmtcavs/ProcAlpha.h new file mode 100644 index 0000000..59177ad --- /dev/null +++ b/src/fmtcavs/ProcAlpha.h @@ -0,0 +1,107 @@ +/***************************************************************************** + + ProcAlpha.h + Author: Laurent de Soras, 2021 + +--- Legal stuff --- + +This program is free software. It comes without any warranty, to +the extent permitted by applicable law. You can redistribute it +and/or modify it under the terms of the Do What The Fuck You Want +To Public License, Version 2, as published by Sam Hocevar. See +http://www.wtfpl.net/ for more details. + +*Tab=3***********************************************************************/ + + + +#pragma once +#if ! defined (fmtcavs_ProcAlpha_HEADER_INCLUDED) +#define fmtcavs_ProcAlpha_HEADER_INCLUDED + + + +/*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +#include "fmtcavs/FmtAvs.h" +#include "fmtcl/BitBltConv.h" +#include "fmtcl/SplFmt.h" + + + +class PVideoFrame; + +namespace fmtcavs +{ + + + +class CpuOpt; + +class ProcAlpha +{ + +/*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +public: + + explicit ProcAlpha (FmtAvs fmt_dst, FmtAvs fmt_src, bool fulld_flag, bool fulls_flag, int w, int h, const CpuOpt &cpu_opt); + + void process_plane (::PVideoFrame &dst_sptr, ::PVideoFrame &src_sptr) const; + + + +/*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +protected: + + + +/*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +private: + + bool _dst_a_flag = false; + bool _src_a_flag = false; + int _dst_res = -1; + int _src_res = -1; + fmtcl::SplFmt _splfmt_dst = fmtcl::SplFmt_ILLEGAL; + fmtcl::SplFmt _splfmt_src = fmtcl::SplFmt_ILLEGAL; + int _w = 0; + int _h = 0; + fmtcl::BitBltConv::ScaleInfo // Set only when both source and dest have an alpha plane + _scale_info; + bool _sse2_flag = false; + bool _avx2_flag = false; + + + +/*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +private: + + ProcAlpha () = delete; + ProcAlpha (const ProcAlpha &other) = delete; + ProcAlpha (ProcAlpha &&other) = delete; + ProcAlpha & operator = (const ProcAlpha &other) = delete; + ProcAlpha & operator = (ProcAlpha &&other) = delete; + bool operator == (const ProcAlpha &other) const = delete; + bool operator != (const ProcAlpha &other) const = delete; + +}; // class ProcAlpha + + + +} // namespace fmtcavs + + + +//#include "fmtcavs/ProcAlpha.hpp" + + + +#endif // fmtcavs_ProcAlpha_HEADER_INCLUDED + + + +/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ diff --git a/src/fmtcavs/fnc.h b/src/fmtcavs/fnc.h new file mode 100644 index 0000000..62c08b8 --- /dev/null +++ b/src/fmtcavs/fnc.h @@ -0,0 +1,73 @@ +/***************************************************************************** + + fnc.h + Author: Laurent de Soras, 2021 + +--- Legal stuff --- + +This program is free software. It comes without any warranty, to +the extent permitted by applicable law. You can redistribute it +and/or modify it under the terms of the Do What The Fuck You Want +To Public License, Version 2, as published by Sam Hocevar. See +http://www.wtfpl.net/ for more details. + +*Tab=3***********************************************************************/ + + + +#pragma once +#if ! defined (fmtcavs_fnc_HEADER_INCLUDED) +#define fmtcavs_fnc_HEADER_INCLUDED + + + +/*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +#include "fmtcl/ColorFamily.h" +#include "fmtcl/ColorSpaceH265.h" +#include "fmtcl/PicFmt.h" +#include "fmtcl/SplFmt.h" + +#include + + + +class IScriptEnvironment; +struct VideoInfo; + + + +namespace fmtcl +{ + class Mat4; + class MatrixProc; +} + +namespace fmtcavs +{ + +class FmtAvs; + + + +fmtcl::PicFmt conv_fmtavs_to_picfmt (const FmtAvs &fmt, bool full_flag); +fmtcl::SplFmt conv_vi_to_splfmt (const ::VideoInfo &vi); +void conv_vi_to_splfmt (fmtcl::SplFmt &type, int &bitdepth, const ::VideoInfo &vi); +fmtcl::SplFmt conv_bitdepth_to_splfmt (int bitdepth); +fmtcl::ColorFamily conv_vi_to_colfam (const ::VideoInfo &vi); +fmtcl::ColorFamily conv_str_to_colfam (std::string str); +void prepare_matrix_coef (::IScriptEnvironment &env, fmtcl::MatrixProc &mat_proc, const fmtcl::Mat4 &mat_main, const FmtAvs &fmt_dst, bool full_range_dst_flag, const FmtAvs &fmt_src, bool full_range_src_flag, fmtcl::ColorSpaceH265 csp_out, int plane_out); + +} // namespace fmtcavs + + + +//#include "fmtcavs/fnc.hpp" + + + +#endif // fmtcavs_fnc_HEADER_INCLUDED + + + +/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ diff --git a/src/fmtcavs/fnc_fmtcavs.cpp b/src/fmtcavs/fnc_fmtcavs.cpp new file mode 100644 index 0000000..d2f5126 --- /dev/null +++ b/src/fmtcavs/fnc_fmtcavs.cpp @@ -0,0 +1,205 @@ +/***************************************************************************** + + fnc_fmtcavs.cpp + Author: Laurent de Soras, 2021 + +--- Legal stuff --- + +This program is free software. It comes without any warranty, to +the extent permitted by applicable law. You can redistribute it +and/or modify it under the terms of the Do What The Fuck You Want +To Public License, Version 2, as published by Sam Hocevar. See +http://www.wtfpl.net/ for more details. + +*Tab=3***********************************************************************/ + + + +#if defined (_MSC_VER) + #pragma warning (1 : 4130 4223 4705 4706) + #pragma warning (4 : 4355 4786 4800) +#endif + + + +/*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + +#include "fmtcavs/FmtAvs.h" +#include "fmtcavs/fnc.h" +#include "fmtcl/fnc.h" +#include "fmtcl/MatrixProc.h" +#include "fstb/fnc.h" +#include "avisynth.h" + +#include + + + +namespace fmtcavs +{ + + + +/*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + + + +/*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + + + +fmtcl::PicFmt conv_fmtavs_to_picfmt (const FmtAvs &fmt, bool full_flag) +{ + assert (fmt.is_valid ()); + + fmtcl::PicFmt pic_fmt; + pic_fmt._sf = conv_bitdepth_to_splfmt (fmt.get_bitdepth ()); + pic_fmt._res = fmt.get_bitdepth (); + pic_fmt._col_fam = fmt.get_col_fam (); + pic_fmt._full_flag = full_flag; + + return pic_fmt; +} + + + +fmtcl::SplFmt conv_vi_to_splfmt (const ::VideoInfo &vi) +{ + fmtcl::SplFmt type = fmtcl::SplFmt_ILLEGAL; + int bitdepth = 0; + + conv_vi_to_splfmt (type, bitdepth, vi); + assert (type != fmtcl::SplFmt_ILLEGAL); + + return type; +} + + + +void conv_vi_to_splfmt (fmtcl::SplFmt &type, int &bitdepth, const ::VideoInfo &vi) +{ + bitdepth = vi.BitsPerComponent (); + type = conv_bitdepth_to_splfmt (bitdepth); +} + + + +fmtcl::SplFmt conv_bitdepth_to_splfmt (int bitdepth) +{ + fmtcl::SplFmt type = fmtcl::SplFmt_ILLEGAL; + + if (bitdepth == 32) + { + type = fmtcl::SplFmt_FLOAT; + } + else + { + if (bitdepth > 8 && bitdepth <= 16) + { + type = fmtcl::SplFmt_INT16; + } + else if (bitdepth <= 8) + { + type = fmtcl::SplFmt_INT8; + } + } + + return type; +} + + + +fmtcl::ColorFamily conv_vi_to_colfam (const ::VideoInfo &vi) +{ + auto col_fam = fmtcl::ColorFamily_INVALID; + + if (vi.IsY ()) + { + col_fam = fmtcl::ColorFamily_GRAY; + } + else if (vi.IsRGB ()) + { + col_fam = fmtcl::ColorFamily_RGB; + } + else if (vi.IsYUV () || vi.IsYUVA ()) + { + col_fam = fmtcl::ColorFamily_YUV; + } + + return col_fam; +} + + + +fmtcl::ColorFamily conv_str_to_colfam (std::string str) +{ + fstb::conv_to_lower_case (str); + + auto col_fam = fmtcl::ColorFamily_INVALID; + + if (str == "y" || str == "grey" || str == "gray") + { + col_fam = fmtcl::ColorFamily_GRAY; + } + else if (str == "rgb") + { + col_fam = fmtcl::ColorFamily_RGB; + } + else if (str == "yuv") + { + col_fam = fmtcl::ColorFamily_YUV; + } + + return col_fam; +} + + + +void prepare_matrix_coef (::IScriptEnvironment &env, fmtcl::MatrixProc &mat_proc, const fmtcl::Mat4 &mat_main, const FmtAvs &fmt_dst, bool full_range_dst_flag, const FmtAvs &fmt_src, bool full_range_src_flag, fmtcl::ColorSpaceH265 csp_out, int plane_out) +{ + const fmtcl::PicFmt fmt_src_fmtcl = + conv_fmtavs_to_picfmt (fmt_src, full_range_src_flag); + const fmtcl::PicFmt fmt_dst_fmtcl = + conv_fmtavs_to_picfmt (fmt_dst, full_range_dst_flag); + + const int ret_val = fmtcl::prepare_matrix_coef ( + mat_proc, mat_main, fmt_dst_fmtcl, fmt_src_fmtcl, csp_out, plane_out + ); + + if (ret_val != fmtcl::MatrixProc::Err_OK) + { + if (ret_val == fmtcl::MatrixProc::Err_POSSIBLE_OVERFLOW) + { + env.ThrowError ( + "One of the matrix coefficients could cause an overflow." + ); + } + else if (ret_val == fmtcl::MatrixProc::Err_TOO_BIG_COEF) + { + env.ThrowError ( + "Too big matrix coefficient." + ); + } + else if (ret_val == fmtcl::MatrixProc::Err_INVALID_FORMAT_COMBINATION) + { + env.ThrowError ( + "Invalid frame format combination." + ); + } + else + { + assert (false); + env.ThrowError ( + "Unidentified error while building the matrix." + ); + } + } +} + + + +} // namespace fmtcavs + + + +/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ diff --git a/src/fmtcavs/function_names.h b/src/fmtcavs/function_names.h new file mode 100644 index 0000000..5379d8f --- /dev/null +++ b/src/fmtcavs/function_names.h @@ -0,0 +1,54 @@ +/***************************************************************************** + + function_names.h + Author: Laurent de Soras, 2021 + +--- Legal stuff --- + +This program is free software. It comes without any warranty, to +the extent permitted by applicable law. You can redistribute it +and/or modify it under the terms of the Do What The Fuck You Want +To Public License, Version 2, as published by Sam Hocevar. See +http://www.wtfpl.net/ for more details. + +*Tab=3***********************************************************************/ + + + +#pragma once +#if ! defined (fmtcavs_function_names_HEADER_INCLUDED) +#define fmtcavs_function_names_HEADER_INCLUDED + + + +/*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ + + + +namespace fmtcavs +{ + + + +#define fmtcavs_NAMESPACE "fmtc" + +#define fmtcavs_BUILD_NAME(x) fmtcavs_NAMESPACE "_" x + +#define fmtcavs_BITDEPTH fmtcavs_BUILD_NAME ("bitdepth") +#define fmtcavs_MATRIX fmtcavs_BUILD_NAME ("matrix") + + + +} // namespace fmtcavs + + + +//#include "fmtcavs/function_names.hpp" + + + +#endif // fmtcavs_function_names_HEADER_INCLUDED + + + +/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ diff --git a/src/fmtcl/BitBltConv.cpp b/src/fmtcl/BitBltConv.cpp index 6abd934..9f47afd 100644 --- a/src/fmtcl/BitBltConv.cpp +++ b/src/fmtcl/BitBltConv.cpp @@ -214,6 +214,7 @@ void BitBltConv::bitblt_int_to_flt (uint8_t *dst_ptr, int dst_stride, fmtcl::Spl { fmtcl_BitBltConv_CASE (false, false, cpp , Cpp , STACK16, 16, s16) fmtcl_BitBltConv_CASE (false, false, cpp , Cpp , INT16 , 16, i16) + fmtcl_BitBltConv_CASE (false, false, cpp , Cpp , INT16 , 14, i16) fmtcl_BitBltConv_CASE (false, false, cpp , Cpp , INT16 , 12, i16) fmtcl_BitBltConv_CASE (false, false, cpp , Cpp , INT16 , 10, i16) fmtcl_BitBltConv_CASE (false, false, cpp , Cpp , INT16 , 9, i16) @@ -221,6 +222,7 @@ void BitBltConv::bitblt_int_to_flt (uint8_t *dst_ptr, int dst_stride, fmtcl::Spl #if (fstb_ARCHI == fstb_ARCHI_X86) fmtcl_BitBltConv_CASE (false, true , sse2, Sse2, STACK16, 16, s16) fmtcl_BitBltConv_CASE (false, true , sse2, Sse2, INT16 , 16, i16) + fmtcl_BitBltConv_CASE (false, true , sse2, Sse2, INT16 , 14, i16) fmtcl_BitBltConv_CASE (false, true , sse2, Sse2, INT16 , 12, i16) fmtcl_BitBltConv_CASE (false, true , sse2, Sse2, INT16 , 10, i16) fmtcl_BitBltConv_CASE (false, true , sse2, Sse2, INT16 , 9, i16) @@ -228,6 +230,7 @@ void BitBltConv::bitblt_int_to_flt (uint8_t *dst_ptr, int dst_stride, fmtcl::Spl #endif fmtcl_BitBltConv_CASE (true , false, cpp , Cpp , STACK16, 16, s16) fmtcl_BitBltConv_CASE (true , false, cpp , Cpp , INT16 , 16, i16) + fmtcl_BitBltConv_CASE (true , false, cpp , Cpp , INT16 , 14, i16) fmtcl_BitBltConv_CASE (true , false, cpp , Cpp , INT16 , 12, i16) fmtcl_BitBltConv_CASE (true , false, cpp , Cpp , INT16 , 10, i16) fmtcl_BitBltConv_CASE (true , false, cpp , Cpp , INT16 , 9, i16) @@ -235,6 +238,7 @@ void BitBltConv::bitblt_int_to_flt (uint8_t *dst_ptr, int dst_stride, fmtcl::Spl #if (fstb_ARCHI == fstb_ARCHI_X86) fmtcl_BitBltConv_CASE (true , true , sse2, Sse2, STACK16, 16, s16) fmtcl_BitBltConv_CASE (true , true , sse2, Sse2, INT16 , 16, i16) + fmtcl_BitBltConv_CASE (true , true , sse2, Sse2, INT16 , 14, i16) fmtcl_BitBltConv_CASE (true , true , sse2, Sse2, INT16 , 12, i16) fmtcl_BitBltConv_CASE (true , true , sse2, Sse2, INT16 , 10, i16) fmtcl_BitBltConv_CASE (true , true , sse2, Sse2, INT16 , 9, i16) @@ -324,15 +328,21 @@ void BitBltConv::bitblt_int_to_int (fmtcl::SplFmt dst_fmt, int dst_res, uint8_t switch ((_sse2_flag << 24) + (dst_fmt << 20) + (src_fmt << 16) + (dst_res << 8) + src_res) { fmtcl_BitBltConv_CASE (false, cpp , Cpp , STACK16, INT16 , 16, 16, s16, i16) + fmtcl_BitBltConv_CASE (false, cpp , Cpp , STACK16, INT16 , 16, 14, s16, i16) fmtcl_BitBltConv_CASE (false, cpp , Cpp , STACK16, INT16 , 16, 12, s16, i16) fmtcl_BitBltConv_CASE (false, cpp , Cpp , STACK16, INT16 , 16, 10, s16, i16) fmtcl_BitBltConv_CASE (false, cpp , Cpp , STACK16, INT16 , 16, 9, s16, i16) fmtcl_BitBltConv_CASE (false, cpp , Cpp , STACK16, INT8 , 16, 8, s16, i08) fmtcl_BitBltConv_CASE (false, cpp , Cpp , INT16 , STACK16, 16, 16, i16, s16) + fmtcl_BitBltConv_CASE (false, cpp , Cpp , INT16 , INT16 , 16, 14, i16, i16) fmtcl_BitBltConv_CASE (false, cpp , Cpp , INT16 , INT16 , 16, 12, i16, i16) fmtcl_BitBltConv_CASE (false, cpp , Cpp , INT16 , INT16 , 16, 10, i16, i16) fmtcl_BitBltConv_CASE (false, cpp , Cpp , INT16 , INT16 , 16, 9, i16, i16) fmtcl_BitBltConv_CASE (false, cpp , Cpp , INT16 , INT8 , 16, 8, i16, i08) + fmtcl_BitBltConv_CASE (false, cpp , Cpp , INT16 , INT16 , 14, 12, i16, i16) + fmtcl_BitBltConv_CASE (false, cpp , Cpp , INT16 , INT16 , 14, 10, i16, i16) + fmtcl_BitBltConv_CASE (false, cpp , Cpp , INT16 , INT16 , 14, 9, i16, i16) + fmtcl_BitBltConv_CASE (false, cpp , Cpp , INT16 , INT8 , 14, 8, i16, i08) fmtcl_BitBltConv_CASE (false, cpp , Cpp , INT16 , INT16 , 12, 10, i16, i16) fmtcl_BitBltConv_CASE (false, cpp , Cpp , INT16 , INT16 , 12, 9, i16, i16) fmtcl_BitBltConv_CASE (false, cpp , Cpp , INT16 , INT8 , 12, 8, i16, i08) @@ -341,15 +351,21 @@ void BitBltConv::bitblt_int_to_int (fmtcl::SplFmt dst_fmt, int dst_res, uint8_t fmtcl_BitBltConv_CASE (false, cpp , Cpp , INT16 , INT8 , 9, 8, i16, i08) #if (fstb_ARCHI == fstb_ARCHI_X86) fmtcl_BitBltConv_CASE (true , sse2, Sse2, STACK16, INT16 , 16, 16, s16, i16) + fmtcl_BitBltConv_CASE (true , sse2, Sse2, STACK16, INT16 , 16, 14, s16, i16) fmtcl_BitBltConv_CASE (true , sse2, Sse2, STACK16, INT16 , 16, 12, s16, i16) fmtcl_BitBltConv_CASE (true , sse2, Sse2, STACK16, INT16 , 16, 10, s16, i16) fmtcl_BitBltConv_CASE (true , sse2, Sse2, STACK16, INT16 , 16, 9, s16, i16) fmtcl_BitBltConv_CASE (true , sse2, Sse2, STACK16, INT8 , 16, 8, s16, i08) fmtcl_BitBltConv_CASE (true , sse2, Sse2, INT16 , STACK16, 16, 16, i16, s16) + fmtcl_BitBltConv_CASE (true , sse2, Sse2, INT16 , INT16 , 16, 14, i16, i16) fmtcl_BitBltConv_CASE (true , sse2, Sse2, INT16 , INT16 , 16, 12, i16, i16) fmtcl_BitBltConv_CASE (true , sse2, Sse2, INT16 , INT16 , 16, 10, i16, i16) fmtcl_BitBltConv_CASE (true , sse2, Sse2, INT16 , INT16 , 16, 9, i16, i16) fmtcl_BitBltConv_CASE (true , sse2, Sse2, INT16 , INT8 , 16, 8, i16, i08) + fmtcl_BitBltConv_CASE (true , sse2, Sse2, INT16 , INT16 , 14, 12, i16, i16) + fmtcl_BitBltConv_CASE (true , sse2, Sse2, INT16 , INT16 , 14, 10, i16, i16) + fmtcl_BitBltConv_CASE (true , sse2, Sse2, INT16 , INT16 , 14, 9, i16, i16) + fmtcl_BitBltConv_CASE (true , sse2, Sse2, INT16 , INT8 , 14, 8, i16, i08) fmtcl_BitBltConv_CASE (true , sse2, Sse2, INT16 , INT16 , 12, 10, i16, i16) fmtcl_BitBltConv_CASE (true , sse2, Sse2, INT16 , INT16 , 12, 9, i16, i16) fmtcl_BitBltConv_CASE (true , sse2, Sse2, INT16 , INT8 , 12, 8, i16, i08) diff --git a/src/vsutl/CpuOpt.cpp b/src/fmtcl/CpuOptBase.cpp similarity index 64% rename from src/vsutl/CpuOpt.cpp rename to src/fmtcl/CpuOptBase.cpp index 968501c..832320e 100644 --- a/src/vsutl/CpuOpt.cpp +++ b/src/fmtcl/CpuOptBase.cpp @@ -1,7 +1,7 @@ /***************************************************************************** - CpuOpt.cpp - Author: Laurent de Soras, 2015 + CpuOptBase.cpp + Author: Laurent de Soras, 2021 --- Legal stuff --- @@ -9,7 +9,7 @@ This program is free software. It comes without any warranty, to the extent permitted by applicable law. You can redistribute it and/or modify it under the terms of the Do What The Fuck You Want To Public License, Version 2, as published by Sam Hocevar. See -http://sam.zoy.org/wtfpl/COPYING for more details. +http://www.wtfpl.net/ for more details. *Tab=3***********************************************************************/ @@ -24,14 +24,13 @@ To Public License, Version 2, as published by Sam Hocevar. See /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ -#include "vsutl/CpuOpt.h" -#include "vsutl/FilterBase.h" +#include "fmtcl/CpuOptBase.h" #include -namespace vsutl +namespace fmtcl { @@ -40,18 +39,7 @@ namespace vsutl -CpuOpt::CpuOpt (FilterBase &filter, const ::VSMap &in, ::VSMap &out, const char *param_name_0) -: _cpu () -, _level (static_cast (filter.get_arg_int ( - in, out, param_name_0, Level_ANY_AVAILABLE - ) & 0xFFFF)) -{ - assert (param_name_0 != 0); -} - - - -void CpuOpt::set_level (Level level) +void CpuOptBase::set_level (Level level) { assert (level >= 0); assert (level <= Level_ANY_AVAILABLE); @@ -61,121 +49,121 @@ void CpuOpt::set_level (Level level) -bool CpuOpt::has_mmx () const +bool CpuOptBase::has_mmx () const { return (_cpu._mmx_flag && _level >= Level_SSE2); } -bool CpuOpt::has_isse () const +bool CpuOptBase::has_isse () const { return (_cpu._isse_flag && _level >= Level_SSE2); } -bool CpuOpt::has_sse () const +bool CpuOptBase::has_sse () const { return (_cpu._sse_flag && _level >= Level_SSE2); } -bool CpuOpt::has_sse2 () const +bool CpuOptBase::has_sse2 () const { return (_cpu._sse2_flag && _level >= Level_SSE2); } -bool CpuOpt::has_sse3 () const +bool CpuOptBase::has_sse3 () const { return (_cpu._sse3_flag && _level >= Level_SSE3); } -bool CpuOpt::has_ssse3 () const +bool CpuOptBase::has_ssse3 () const { return (_cpu._ssse3_flag && _level >= Level_SSSE3); } -bool CpuOpt::has_sse41 () const +bool CpuOptBase::has_sse41 () const { return (_cpu._sse41_flag && _level >= Level_SSE41); } -bool CpuOpt::has_sse42 () const +bool CpuOptBase::has_sse42 () const { return (_cpu._sse42_flag && _level >= Level_SSE42); } -bool CpuOpt::has_sse4a () const +bool CpuOptBase::has_sse4a () const { return (_cpu._sse4a_flag && _level >= Level_FMA4); } -bool CpuOpt::has_fma3 () const +bool CpuOptBase::has_fma3 () const { return (_cpu._fma3_flag && _level >= Level_FMA3); } -bool CpuOpt::has_fma4 () const +bool CpuOptBase::has_fma4 () const { return (_cpu._fma4_flag && _level >= Level_FMA4); } -bool CpuOpt::has_avx () const +bool CpuOptBase::has_avx () const { return (_cpu._avx_flag && _level >= Level_AVX); } -bool CpuOpt::has_avx2 () const +bool CpuOptBase::has_avx2 () const { return (_cpu._avx2_flag && _level >= Level_AVX2); } -bool CpuOpt::has_avx512f () const +bool CpuOptBase::has_avx512f () const { return (_cpu._avx512f_flag && _level >= Level_AVX512F); } -bool CpuOpt::has_f16c () const +bool CpuOptBase::has_f16c () const { return (_cpu._f16c_flag && _level >= Level_F16C); } -bool CpuOpt::has_cx16 () const +bool CpuOptBase::has_cx16 () const { - return (_cpu._cx16_flag); + return _cpu._cx16_flag; } -const fstb::CpuId & CpuOpt::use_raw_cpuid () const +const fstb::CpuId & CpuOptBase::use_raw_cpuid () const { - return (_cpu); + return _cpu; } @@ -188,7 +176,7 @@ const fstb::CpuId & CpuOpt::use_raw_cpuid () const -} // namespace vsutl +} // namespace fmtcl diff --git a/src/vsutl/CpuOpt.h b/src/fmtcl/CpuOptBase.h similarity index 66% rename from src/vsutl/CpuOpt.h rename to src/fmtcl/CpuOptBase.h index 64ce698..6a9fa59 100644 --- a/src/vsutl/CpuOpt.h +++ b/src/fmtcl/CpuOptBase.h @@ -1,7 +1,7 @@ /***************************************************************************** - CpuOpt.h - Author: Laurent de Soras, 2015 + CpuOptBase.h + Author: Laurent de Soras, 2021 --- Legal stuff --- @@ -9,19 +9,15 @@ This program is free software. It comes without any warranty, to the extent permitted by applicable law. You can redistribute it and/or modify it under the terms of the Do What The Fuck You Want To Public License, Version 2, as published by Sam Hocevar. See -http://sam.zoy.org/wtfpl/COPYING for more details. +http://www.wtfpl.net/ for more details. *Tab=3***********************************************************************/ #pragma once -#if ! defined (vsutl_CpuOpt_HEADER_INCLUDED) -#define vsutl_CpuOpt_HEADER_INCLUDED - -#if defined (_MSC_VER) - #pragma warning (4 : 4250) -#endif +#if ! defined (fmtcl_CpuOptBase_HEADER_INCLUDED) +#define fmtcl_CpuOptBase_HEADER_INCLUDED @@ -29,18 +25,14 @@ To Public License, Version 2, as published by Sam Hocevar. See #include "fstb/CpuId.h" -#include "VapourSynth.h" - -namespace vsutl +namespace fmtcl { -class FilterBase; - -class CpuOpt +class CpuOptBase { /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ @@ -62,11 +54,16 @@ class CpuOpt Level_AVX2, // 10 Level_AVX512F, - Level_ANY_AVAILABLE = 0xFFFF + Level_MASK = 0xFFFF, + Level_ANY_AVAILABLE = Level_MASK }; - explicit CpuOpt (FilterBase &filter, const ::VSMap &in, ::VSMap &out, const char *param_name_0 = "cpuopt"); - virtual ~CpuOpt () {} + CpuOptBase () = default; + virtual ~CpuOptBase () = default; + CpuOptBase (const CpuOptBase &other) = default; + CpuOptBase (CpuOptBase &&other) = default; + CpuOptBase & operator = (const CpuOptBase &other) = default; + CpuOptBase & operator = (CpuOptBase &&other) = default; void set_level (Level level); @@ -103,7 +100,7 @@ class CpuOpt private: fstb::CpuId _cpu; - Level _level; + Level _level = Level_ANY_AVAILABLE; @@ -111,25 +108,22 @@ class CpuOpt private: - CpuOpt () = delete; - CpuOpt (const CpuOpt &other) = delete; - CpuOpt & operator = (const CpuOpt &other) = delete; - bool operator == (const CpuOpt &other) const = delete; - bool operator != (const CpuOpt &other) const = delete; + bool operator == (const CpuOptBase &other) const = delete; + bool operator != (const CpuOptBase &other) const = delete; -}; // class CpuOpt +}; // class CpuOptBase -} // namespace vsutl +} // namespace fmtcl -//#include "vsutl/CpuOpt.hpp" +//#include "fmtcl/CpuOptBase.hpp" -#endif // vsutl_CpuOpt_HEADER_INCLUDED +#endif // fmtcl_CpuOptBase_HEADER_INCLUDED diff --git a/src/fmtcl/Dither.cpp b/src/fmtcl/Dither.cpp index 77a30f5..9e1592b 100644 --- a/src/fmtcl/Dither.cpp +++ b/src/fmtcl/Dither.cpp @@ -425,8 +425,8 @@ void Dither::copy_dither_pat_rotate (PatData &dst, const PatData &src, int angle // All possible combinations #define fmtcl_Dither_SPAN_INT(SETP, NAMP, NAMF, simple_flag, tpdfo_flag, tpdfn_flag, dst_res, dst_fmt, src_res, src_fmt) \ - switch ( ((simple_flag) << 7) \ - + ((tpdfo_flag) << 23) + ((tpdfn_flag) << 22) \ + switch ( (int (simple_flag) << 7) \ + + (int (tpdfo_flag) << 23) + (int (tpdfn_flag) << 22) \ + ((dst_res) << 24) + ((dst_fmt) << 16) \ + ((src_res) << 8) + (src_fmt)) \ { \ @@ -447,12 +447,13 @@ void Dither::copy_dither_pat_rotate (PatData &dst, const PatData &src, int angle SETP (NAMP, NAMF, SplFmt_INT16, uint16_t, 10, SplFmt_INT16, uint16_t, 16) \ SETP (NAMP, NAMF, SplFmt_INT16, uint16_t, 12, SplFmt_INT16, uint16_t, 14) \ SETP (NAMP, NAMF, SplFmt_INT16, uint16_t, 12, SplFmt_INT16, uint16_t, 16) \ + SETP (NAMP, NAMF, SplFmt_INT16, uint16_t, 14, SplFmt_INT16, uint16_t, 16) \ } // All possible combinations using float as intermediary data #define fmtcl_Dither_SPAN_FLT(SETP, NAMP, NAMF, simple_flag, tpdfo_flag, tpdfn_flag, dst_res, dst_fmt, src_res, src_fmt) \ - switch ( ((simple_flag) << 7) \ - + ((tpdfo_flag) << 23) + ((tpdfn_flag) << 22) \ + switch ( (int (simple_flag) << 7) \ + + (int (tpdfo_flag) << 23) + (int (tpdfn_flag) << 22) \ + ((dst_res) << 24) + ((dst_fmt) << 16) \ + ((src_res) << 8) + (src_fmt)) \ { \ @@ -511,7 +512,8 @@ void Dither::copy_dither_pat_rotate (PatData &dst, const PatData &src, int angle FCASE (true , true , true , NAMP, NAMF, DF, DT, DP, SF, ST, SP) #define fmtcl_Dither_SET_FNC_INT_CASE(simple_flag, tpdfo_flag, tpdfn_flag, NAMP, NAMF, DF, DT, DP, SF, ST, SP) \ - case (simple_flag << 7) + (tpdfn_flag << 22) + (tpdfo_flag << 23) \ + case (int (simple_flag) << 7) \ + + (int (tpdfn_flag) << 22) + (int (tpdfo_flag) << 23) \ + (DP << 24) + (DF << 16) + (SP << 8) + SF: \ _process_seg_int_int_ptr = &process_seg_##NAMF##_int_int_cpp < \ simple_flag, tpdfo_flag, tpdfn_flag, DT, DP, ST, SP \ @@ -523,7 +525,8 @@ void Dither::copy_dither_pat_rotate (PatData &dst, const PatData &src, int angle NAMP, NAMF, DF, DT, DP, SF, ST, SP) #define fmtcl_Dither_SET_FNC_FLT_CASE(simple_flag, tpdfo_flag, tpdfn_flag,NAMP, NAMF, DF, DT, DP, SF, ST, SP) \ - case (simple_flag << 7) + (tpdfn_flag << 22) + (tpdfo_flag << 23) \ + case (int (simple_flag) << 7) \ + + (int (tpdfn_flag) << 22) + (int (tpdfo_flag) << 23) \ + (DP << 24) + (DF << 16) + (SP << 8) + SF: \ _process_seg_flt_int_ptr = &process_seg_##NAMF##_flt_int_cpp < \ simple_flag, tpdfo_flag, tpdfn_flag, DT, DP, ST \ @@ -535,7 +538,8 @@ void Dither::copy_dither_pat_rotate (PatData &dst, const PatData &src, int angle NAMP, NAMF, DF, DT, DP, SF, ST, SP) #define fmtcl_Dither_SET_FNC_INT_SSE2_CASE(simple_flag, tpdfo_flag, tpdfn_flag, NAMP, NAMF, DF, DT, DP, SF, ST, SP) \ - case (simple_flag << 7) + (tpdfn_flag << 22) + (tpdfo_flag << 23) \ + case (int (simple_flag) << 7) \ + + (int (tpdfn_flag) << 22) + (int (tpdfo_flag) << 23) \ + (DP << 24) + (DF << 16) + (SP << 8) + SF: \ _process_seg_int_int_ptr = &process_seg_##NAMF##_int_int_sse2 < \ simple_flag, tpdfo_flag, tpdfn_flag, DF, DP, SF, SP \ @@ -547,7 +551,8 @@ void Dither::copy_dither_pat_rotate (PatData &dst, const PatData &src, int angle NAMP, NAMF, DF, DT, DP, SF, ST, SP) #define fmtcl_Dither_SET_FNC_FLT_SSE2_CASE(simple_flag, tpdfo_flag, tpdfn_flag, NAMP, NAMF, DF, DT, DP, SF, ST, SP) \ - case (simple_flag << 7) + (tpdfn_flag << 22) + (tpdfo_flag << 23) \ + case (int (simple_flag) << 7) \ + + (int (tpdfn_flag) << 22) + (int (tpdfo_flag) << 23) \ + (DP << 24) + (DF << 16) + (SP << 8) + SF: \ _process_seg_flt_int_ptr = &process_seg_##NAMF##_flt_int_sse2 < \ simple_flag, tpdfo_flag, tpdfn_flag, DF, DP, SF \ @@ -669,7 +674,7 @@ void Dither::init_fnc_quasirandom () noexcept #define fmtcl_Dither_SET_FNC_ERRDIF_INT_CASE(simple_flag, tpdfn_flag, NAMP, NAMF, DF, DT, DP, SF, ST, SP) \ - case (simple_flag << 7) + (tpdfn_flag << 22) \ + case (int (simple_flag) << 7) + (int (tpdfn_flag) << 22) \ + (DP << 24) + (DF << 16) + (SP << 8) + SF: \ _process_seg_int_int_ptr = &process_seg_errdif_int_int_cpp < \ simple_flag, tpdfn_flag, Diffuse##NAMF \ @@ -683,7 +688,7 @@ void Dither::init_fnc_quasirandom () noexcept fmtcl_Dither_SET_FNC_ERRDIF_INT_CASE (true , true , NAMP, NAMF, DF, DT, DP, SF, ST, SP) #define fmtcl_Dither_SET_FNC_ERRDIF_FLT_CASE(simple_flag, tpdfn_flag, NAMP, NAMF, DF, DT, DP, SF, ST, SP) \ - case (simple_flag << 7) + (tpdfn_flag << 22) \ + case (int (simple_flag) << 7) + (int (tpdfn_flag) << 22) \ + (DP << 24) + (DF << 16) + (SP << 8) + SF: \ _process_seg_flt_int_ptr = &process_seg_errdif_flt_int_cpp < \ simple_flag, tpdfn_flag, Diffuse##NAMF \ @@ -814,10 +819,15 @@ void Dither::dither_plane (uint8_t *dst_ptr, int dst_stride, const uint8_t *src_ } ctx._rnd_state = rnd_state; - const bool sc_flag = - ( _splfmt_src == SplFmt_FLOAT - || ! fstb::is_eq (scale_info._gain * double ((uint64_t (1)) << (_src_res - _dst_res)), 1.0, 1e-6) - || ! fstb::is_null (scale_info._add_cst, 1e-6)); + const bool sc_flag = ( + _splfmt_src == SplFmt_FLOAT + || _src_res == _dst_res + || ! fstb::is_eq ( + scale_info._gain * double ((uint64_t (1)) << (_src_res - _dst_res)), + 1.0, 1e-6 + ) + || ! fstb::is_null (scale_info._add_cst, 1e-6) + ); void (* process_ptr) (uint8_t *dst_ptr, const uint8_t *src_ptr, int w, SegContext &ctx) = (sc_flag) diff --git a/src/fmtcl/Dither.h b/src/fmtcl/Dither.h index edcc32a..afb5246 100644 --- a/src/fmtcl/Dither.h +++ b/src/fmtcl/Dither.h @@ -50,7 +50,7 @@ class Dither public: - static constexpr int _max_nbr_planes = 3; + static constexpr int _max_nbr_planes = 4; static constexpr int _max_pat_width = 32; // Number of pixels for halftone dithering enum DMode diff --git a/src/fmtcl/FilterResize.cpp b/src/fmtcl/FilterResize.cpp index e79dde1..c338665 100644 --- a/src/fmtcl/FilterResize.cpp +++ b/src/fmtcl/FilterResize.cpp @@ -857,7 +857,8 @@ void FilterResize::process_tile_resize (const TaskRsz &tr, const TaskRszGlobal& : (x == 9) ? 1 \ : (x == 10) ? 2 \ : (x == 12) ? 3 \ - : (x == 16) ? 4 : -1) + : (x == 14) ? 4 \ + : (x == 16) ? 5 : -1) #define fmtc_FilterResize_PROC_F(DF, DP, SF, SP) \ case ((SplFmt_##DF << 2) + SplFmt_##SF): \ @@ -891,12 +892,14 @@ void FilterResize::process_tile_resize (const TaskRsz &tr, const TaskRszGlobal& + (dst_fmt_loc << 2) + src_fmt_loc) { fmtc_FilterResize_PROC_I (INT16 , i16, INT16 , i16, 16, i16_i16) + fmtc_FilterResize_PROC_I (INT16 , i16, INT16 , i16, 14, i16_i14) fmtc_FilterResize_PROC_I (INT16 , i16, INT16 , i16, 12, i16_i12) fmtc_FilterResize_PROC_I (INT16 , i16, INT16 , i16, 10, i16_i10) fmtc_FilterResize_PROC_I (INT16 , i16, INT16 , i16, 9, i16_i09) fmtc_FilterResize_PROC_I (INT16 , i16, STACK16, s16, 16, i16_s16) fmtc_FilterResize_PROC_I (INT16 , i16, INT8 , i08, 8, i16_i08) fmtc_FilterResize_PROC_I (STACK16, s16, INT16 , i16, 16, s16_i16) + fmtc_FilterResize_PROC_I (STACK16, s16, INT16 , i16, 14, s16_i14) fmtc_FilterResize_PROC_I (STACK16, s16, INT16 , i16, 12, s16_i12) fmtc_FilterResize_PROC_I (STACK16, s16, INT16 , i16, 10, s16_i10) fmtc_FilterResize_PROC_I (STACK16, s16, INT16 , i16, 9, s16_i09) diff --git a/src/fmtcl/KernelData.cpp b/src/fmtcl/KernelData.cpp index bdeb7da..8418cea 100644 --- a/src/fmtcl/KernelData.cpp +++ b/src/fmtcl/KernelData.cpp @@ -41,6 +41,7 @@ To Public License, Version 2, as published by Sam Hocevar. See #include "fmtcl/ContFirSpline36.h" #include "fmtcl/ContFirSpline64.h" #include "fmtcl/DiscreteFirCustom.h" +#include "fmtcl/fnc.h" #include "fstb/def.h" #include "fstb/fnc.h" @@ -203,7 +204,7 @@ void KernelData::create_kernel_base (std::string kernel_fnc, std::vector &coef_arr, const std::string &str) -{ - coef_arr.clear (); - const char * cur_0 = str.c_str (); - bool cont_flag = true; - do - { - const char * end_0 = cur_0; - const double val = strtod (cur_0, const_cast (&end_0)); - if (end_0 == cur_0) - { - cont_flag = false; - } - else - { - coef_arr.push_back (val); - cur_0 = end_0; - } - } - while (cont_flag); -} - - - template void KernelData::apply_window (std::vector &x, double &norm_sum, int taps, int h_len, int h_len_i, double inv_ovr_s) { diff --git a/src/fmtcl/KernelData.h b/src/fmtcl/KernelData.h index 31c6524..91b71cb 100644 --- a/src/fmtcl/KernelData.h +++ b/src/fmtcl/KernelData.h @@ -105,8 +105,6 @@ class KernelData uint32_t _hash = 0; - static void conv_to_float_arr (std::vector &coef_arr, const std::string &str); - template static void apply_window (std::vector &x, double &norm_sum, int taps, int h_len, int h_len_i, double inv_ovr_s); diff --git a/src/fmtcl/Matrix2020CLProc.cpp b/src/fmtcl/Matrix2020CLProc.cpp index d8b9bfd..b4937ea 100644 --- a/src/fmtcl/Matrix2020CLProc.cpp +++ b/src/fmtcl/Matrix2020CLProc.cpp @@ -626,11 +626,13 @@ void Matrix2020CLProc::conv_ycbcr_2_rgb_cpp_int (uint8_t * const dst_ptr_arr [NB const int bl = _map_gamma_int [bg]; const int rl = _map_gamma_int [rg]; - const int gl = uint16_t ( + const int gl = uint16_t (std::max ( ( rl * _coef_rgby_int [Col_R] + yl * _coef_rgby_int [Col_G] + bl * _coef_rgby_int [Col_B] - + cst_r ) >> SHIFT_INT); + + cst_r ) >> SHIFT_INT, + 0 + )); DST::template write_clip (dst_0_ptr, rl); DST::template write_clip (dst_1_ptr, gl); diff --git a/src/fmtcl/MatrixProc_macro.h b/src/fmtcl/MatrixProc_macro.h index f79665f..88bff47 100644 --- a/src/fmtcl/MatrixProc_macro.h +++ b/src/fmtcl/MatrixProc_macro.h @@ -47,6 +47,13 @@ To Public License, Version 2, as published by Sam Hocevar. See CI (INT16 , 12, INT16 , 11) \ CI (INT16 , 12, INT16 , 12) \ \ + CI (INT16 , 14, INT8 , 8) \ + CI (INT16 , 14, INT16 , 9) \ + CI (INT16 , 14, INT16 , 10) \ + CI (INT16 , 14, INT16 , 11) \ + CI (INT16 , 14, INT16 , 12) \ + CI (INT16 , 14, INT16 , 14) \ + \ CI (INT16 , 16, INT8 , 8) \ CI (INT16 , 16, INT16 , 9) \ CI (INT16 , 16, INT16 , 10) \ diff --git a/src/fmtcl/MatrixUtil.cpp b/src/fmtcl/MatrixUtil.cpp index e76adac..8d82761 100644 --- a/src/fmtcl/MatrixUtil.cpp +++ b/src/fmtcl/MatrixUtil.cpp @@ -42,6 +42,32 @@ namespace fmtcl +// mat should be already converted to lower case +void MatrixUtil::select_def_mat (std::string &mat, ColorFamily col_fam) +{ + if (mat.empty ()) + { + switch (col_fam) + { + case ColorFamily_YUV: + mat = "601"; + break; + + case ColorFamily_YCGCO: + mat = "ycgco"; + break; + + case ColorFamily_GRAY: // Should not happen actually + case ColorFamily_RGB: + default: + // Nothing + break; + } + } +} + + + // mat should be already converted to lower case // Returns ColorSpaceH265_UNDEF if mat is unknown ColorSpaceH265 MatrixUtil::find_cs_from_mat_str (const std::string &mat, bool allow_2020cl_flag) diff --git a/src/fmtcl/MatrixUtil.h b/src/fmtcl/MatrixUtil.h index f94a256..e840f39 100644 --- a/src/fmtcl/MatrixUtil.h +++ b/src/fmtcl/MatrixUtil.h @@ -23,6 +23,7 @@ To Public License, Version 2, as published by Sam Hocevar. See /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ +#include "fmtcl/ColorFamily.h" #include "fmtcl/ColorSpaceH265.h" #include @@ -43,6 +44,7 @@ class MatrixUtil public: + static void select_def_mat (std::string &mat, ColorFamily col_fam); static ColorSpaceH265 find_cs_from_mat_str (const std::string &mat, bool allow_2020cl_flag); diff --git a/src/fmtcl/ResampleUtil.cpp b/src/fmtcl/ResampleUtil.cpp index 2f36a5a..33d3dc9 100644 --- a/src/fmtcl/ResampleUtil.cpp +++ b/src/fmtcl/ResampleUtil.cpp @@ -60,8 +60,10 @@ void ResampleUtil::create_plane_specs (ResamplePlaneData &plane_data, int plane_ spec._dst_height = compute_plane_height (dst_cf, dst_ss_v, dst_h, plane_index); - const double subspl_h = double (1 << src_ss_h); - const double subspl_v = double (1 << src_ss_v); + // We don't use src_ss_* because they are only valid for the chroma planes. + // The formulas belows are valid for any plane. + const double subspl_h = double (src_w / spec._src_width ); + const double subspl_v = double (src_h / spec._src_height); const ResamplePlaneData::Win & s = plane_data._win; spec._win_x = s._x / subspl_h; diff --git a/src/fmtcl/Scaler.h b/src/fmtcl/Scaler.h index b6321df..f8d8a36 100644 --- a/src/fmtcl/Scaler.h +++ b/src/fmtcl/Scaler.h @@ -78,6 +78,9 @@ To Public License, Version 2, as published by Sam Hocevar. See MC (Stack16, Int16 , STACK16, INT16 , 16, 16, s16_i16) \ MC (Int16 , Stack16, INT16 , STACK16, 16, 16, i16_s16) \ MC (Stack16, Stack16, STACK16, STACK16, 16, 16, s16_s16) \ +\ + MC (Int16 , Int16 , INT16 , INT16 , 16, 14, i16_i14) \ + MC (Stack16, Int16 , STACK16, INT16 , 16, 14, s16_i14) \ \ MC (Int16 , Int16 , INT16 , INT16 , 16, 12, i16_i12) \ MC (Stack16, Int16 , STACK16, INT16 , 16, 12, s16_i12) \ diff --git a/src/fmtcl/SplFmt.hpp b/src/fmtcl/SplFmt.hpp index cecea9e..0538586 100644 --- a/src/fmtcl/SplFmt.hpp +++ b/src/fmtcl/SplFmt.hpp @@ -1,6 +1,6 @@ /***************************************************************************** - SplFmtUtl.hpp + SplFmt.hpp Author: Laurent de Soras, 2012 --- Legal stuff --- @@ -15,8 +15,8 @@ To Public License, Version 2, as published by Sam Hocevar. See -#if ! defined (fmtcl_SplFmtUtl_CODEHEADER_INCLUDED) -#define fmtcl_SplFmtUtl_CODEHEADER_INCLUDED +#if ! defined (fmtcl_SplFmt_CODEHEADER_INCLUDED) +#define fmtcl_SplFmt_CODEHEADER_INCLUDED @@ -91,7 +91,7 @@ int SplFmt_get_data_size (SplFmt fmt) -#endif // fmtcl_SplFmtUtl_CODEHEADER_INCLUDED +#endif // fmtcl_SplFmt_CODEHEADER_INCLUDED diff --git a/src/fmtcl/TransCurve.h b/src/fmtcl/TransCurve.h index 2783397..53f21d1 100644 --- a/src/fmtcl/TransCurve.h +++ b/src/fmtcl/TransCurve.h @@ -38,7 +38,9 @@ enum TransCurve { TransCurve_UNDEF = -1, - // ITU-T H.265, High efficiency video coding, 2019-06, p. 409-410 + // ITU-T H.265, High efficiency video coding, 2019-11, p. 422-423 + // Table E.4 - Transfer characteristics interpretation using the + // transfer_characteristics syntax element TransCurve_RESERVED1 = 0, TransCurve_709, // ITU-R BT.709 TransCurve_UNSPECIFIED, diff --git a/src/fmtcl/TransUtil.cpp b/src/fmtcl/TransUtil.cpp index 8da0469..12d7e24 100644 --- a/src/fmtcl/TransUtil.cpp +++ b/src/fmtcl/TransUtil.cpp @@ -367,7 +367,11 @@ TransUtil::OpSPtr TransUtil::conv_curve_to_op (TransCurve c, bool inv_flag, Tran const double phi = (pow (alpha, gamma) * pow (gamma - 1, gamma - 1)) / (pow (alpha - 1, gamma - 1) * pow (gamma, gamma)); - ptr = OpSPtr (new TransOpLinPow (inv_flag, alpha, k0 / phi, 1.0 / gamma, phi)); + const double pwr = 1.0 / gamma; + const double r_neg = (c == TransCurve_SRGB) ? -1.0 : 0.0; + ptr = OpSPtr (new TransOpLinPow ( + inv_flag, alpha, k0 / phi, pwr, phi, r_neg, 1, 1, pwr + )); } #else // Rounded constants used in IEC 61966-2-1 diff --git a/src/fmtcl/fnc.h b/src/fmtcl/fnc.h index 6c908aa..5c0052c 100644 --- a/src/fmtcl/fnc.h +++ b/src/fmtcl/fnc.h @@ -31,6 +31,9 @@ To Public License, Version 2, as published by Sam Hocevar. See #include "fmtcl/ColorSpaceH265.h" #include "fmtcl/SplFmt.h" +#include +#include + namespace fmtcl @@ -51,6 +54,7 @@ double compute_pix_scale (const PicFmt &fmt, int plane_index); double get_pix_min (const PicFmt &fmt, int plane_index); void compute_fmt_mac_cst (double &gain, double &add_cst, const PicFmt &dst_fmt, const PicFmt &src_fmt, int plane_index); int prepare_matrix_coef (MatrixProc &mat_proc, const Mat4 &mat_main, const PicFmt &dst_fmt, const PicFmt &src_fmt, ColorSpaceH265 csp_out, int plane_out); +std::vector conv_str_to_float_arr (const std::string &str); diff --git a/src/fmtcl/fnc.cpp b/src/fmtcl/fnc_fmtcl.cpp similarity index 92% rename from src/fmtcl/fnc.cpp rename to src/fmtcl/fnc_fmtcl.cpp index 5174035..154bed9 100644 --- a/src/fmtcl/fnc.cpp +++ b/src/fmtcl/fnc_fmtcl.cpp @@ -33,6 +33,7 @@ To Public License, Version 2, as published by Sam Hocevar. See #include #include +#include @@ -182,7 +183,7 @@ double compute_pix_scale (const PicFmt &fmt, int plane_index) if (fmt._sf != SplFmt_FLOAT) { const int bps_m8 = fmt._res - 8; - if (fmt._full_flag) + if (fmt._full_flag || plane_index == 3) { scale = double ((uint64_t (1) << fmt._res) - 1); } @@ -223,7 +224,7 @@ double get_pix_min (const PicFmt &fmt, int plane_index) add_val = 0.5; } } - else + else if (plane_index < 3) { add_val = double ((uint64_t (16)) << (fmt._res - 8)); } @@ -297,6 +298,32 @@ int prepare_matrix_coef (MatrixProc &mat_proc, const Mat4 &mat_main, const PicFm +std::vector conv_str_to_float_arr (const std::string &str) +{ + std::vector coef_arr; + const char * cur_0 = str.c_str (); + bool cont_flag = true; + do + { + const char * end_0 = cur_0; + const double val = strtod (cur_0, const_cast (&end_0)); + if (end_0 == cur_0) + { + cont_flag = false; + } + else + { + coef_arr.push_back (val); + cur_0 = end_0; + } + } + while (cont_flag); + + return coef_arr; +} + + + /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ diff --git a/src/main-avs.cpp b/src/main-avs.cpp new file mode 100644 index 0000000..c4e8850 --- /dev/null +++ b/src/main-avs.cpp @@ -0,0 +1,117 @@ + +#define WIN32_LEAN_AND_MEAN +#define NOMINMAX +#define NOGDI + +#include "avsutl/fnc.h" +#include "fmtcavs/Bitdepth.h" +#include "fmtcavs/function_names.h" +#include "fmtcavs/Matrix.h" +#include "fstb/def.h" + +#include +#include "avisynth.h" + +#if defined (_MSC_VER) && ! defined (NDEBUG) && defined (_DEBUG) + #include +#endif + + + +template +::AVSValue __cdecl main_avs_create (::AVSValue args, void *user_data_ptr, ::IScriptEnvironment *env_ptr) +{ + fstb::unused (user_data_ptr); + + return new T (*env_ptr, args); +} + + + +const ::AVS_Linkage * AVS_linkage = nullptr; + +extern "C" __declspec (dllexport) +const char * __stdcall AvisynthPluginInit3 (::IScriptEnvironment *env_ptr, const ::AVS_Linkage * const vectors_ptr) +{ + AVS_linkage = vectors_ptr; + + env_ptr->AddFunction (fmtcavs_BITDEPTH, + "c" "[bits]i" "[flt]b" "[planes]s" // 0 + "[fulls]b" "[fulld]b" "[dmode]i" "[ampo]f" // 4 + "[ampn]f" "[dyn]b" "[staticnoise]b" "[cpuopt]i" // 8 + "[patsize]i" "[tpdfo]b" "[tpdfn]b" "[corplane]b", // 12 + &main_avs_create , nullptr + ); + env_ptr->AddFunction (fmtcavs_MATRIX, + "c" "[mat]s" "[mats]s" "[matd]s" // 0 + "[fulls]b" "[fulld]b" "[coef]s" "[csp]s" // 4 + "[col_fam]s" "[bits]i" "[singleout]i" "[cpuopt]i", // 8 + &main_avs_create , nullptr + ); + + return "fmtconv - video format conversion"; +} + + + +static void main_avs_dll_load (::HINSTANCE hinst) +{ + fstb::unused (hinst); + +#if defined (_MSC_VER) && ! defined (NDEBUG) && defined (_DEBUG) + { + const int mode = (1 * _CRTDBG_MODE_DEBUG) + | (1 * _CRTDBG_MODE_WNDW); + ::_CrtSetReportMode (_CRT_WARN, mode); + ::_CrtSetReportMode (_CRT_ERROR, mode); + ::_CrtSetReportMode (_CRT_ASSERT, mode); + + const int old_flags = ::_CrtSetDbgFlag (_CRTDBG_REPORT_FLAG); + ::_CrtSetDbgFlag ( old_flags + | (1 * _CRTDBG_LEAK_CHECK_DF) + | (0 * _CRTDBG_CHECK_ALWAYS_DF)); + ::_CrtSetBreakAlloc (-1); // Specify here a memory bloc number + } +#endif // _MSC_VER, NDEBUG +} + + + +static void main_avs_dll_unload (::HINSTANCE hinst) +{ + fstb::unused (hinst); + +#if defined (_MSC_VER) && ! defined (NDEBUG) && defined (_DEBUG) + { + const int mode = (1 * _CRTDBG_MODE_DEBUG) + | (0 * _CRTDBG_MODE_WNDW); + ::_CrtSetReportMode (_CRT_WARN, mode); + ::_CrtSetReportMode (_CRT_ERROR, mode); + ::_CrtSetReportMode (_CRT_ASSERT, mode); + + ::_CrtMemState mem_state; + ::_CrtMemCheckpoint (&mem_state); + ::_CrtMemDumpStatistics (&mem_state); + } +#endif // _MSC_VER, NDEBUG +} + + + +BOOL WINAPI DllMain (::HINSTANCE hinst, ::DWORD reason, ::LPVOID reserved_ptr) +{ + fstb::unused (reserved_ptr); + + switch (reason) + { + case DLL_PROCESS_ATTACH: + main_avs_dll_load (hinst); + break; + + case DLL_PROCESS_DETACH: + main_avs_dll_unload (hinst); + break; + } + + return TRUE; +} diff --git a/src/main.cpp b/src/main-vs.cpp similarity index 100% rename from src/main.cpp rename to src/main-vs.cpp diff --git a/src/vsutl/FilterBase.cpp b/src/vsutl/FilterBase.cpp index 5dfcfbb..3e8500b 100644 --- a/src/vsutl/FilterBase.cpp +++ b/src/vsutl/FilterBase.cpp @@ -26,6 +26,7 @@ To Public License, Version 2, as published by Sam Hocevar. See #include "fstb/fnc.h" #include "vsutl/FilterBase.h" +#include "vsutl/fnc.h" #include #include @@ -288,6 +289,14 @@ char FilterBase::_filter_error_msg_0 [_max_error_buf_len] = ""; // are passed to the function. const VSFormat * FilterBase::register_format (int color_family, int sample_type, int bits_per_sample, int sub_sampling_w, int sub_sampling_h, ::VSCore &core) const { + // Maps API V4 colorfamily values to API V3 + switch (color_family) + { + case ::cfGray: color_family = ::cmGray; break; + case ::cfRGB: color_family = ::cmRGB; break; + case ::cfYUV: color_family = ::cmYUV; break; + } + // Copy of the beginning of VSCore::registerFormat() if ( sub_sampling_h < 0 || sub_sampling_w < 0 || sub_sampling_h > 4 || sub_sampling_w > 4) @@ -300,7 +309,7 @@ const VSFormat * FilterBase::register_format (int color_family, int sample_type, throw_rt_err ("Invalid sample type"); } - if (color_family ==:: cmRGB && (sub_sampling_h != 0 || sub_sampling_w != 0)) + if (is_vs_rgb (color_family) && (sub_sampling_h != 0 || sub_sampling_w != 0)) { throw_rt_err ("We do not like subsampled rgb around here"); } diff --git a/src/vsutl/PlaneProcessor.cpp b/src/vsutl/PlaneProcessor.cpp index d8e3f68..d902fca 100644 --- a/src/vsutl/PlaneProcessor.cpp +++ b/src/vsutl/PlaneProcessor.cpp @@ -435,7 +435,7 @@ void PlaneProcessor::copy_plane (::VSFrameRef &dst, const ::VSFrameRef &src, int template void PlaneProcessor::fill_plane (void *ptr, T val, int stride, int w, int h) { - assert (ptr != 0); + assert (ptr != nullptr); assert (stride > 0); assert (w > 0); assert (h > 0); @@ -457,10 +457,7 @@ void PlaneProcessor::fill_plane (void *ptr, T val, int stride, int w, int h) } else { - for (int x = 0; x < w; ++x) - { - data_ptr [x] = val; - } + std::fill (data_ptr, data_ptr + w, val); } data_ptr += stride_pix; diff --git a/src/vsutl/fnc.h b/src/vsutl/fnc.h index d26c440..5952bcc 100644 --- a/src/vsutl/fnc.h +++ b/src/vsutl/fnc.h @@ -27,17 +27,20 @@ To Public License, Version 2, as published by Sam Hocevar. See /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ -#include +#include "VapourSynth.h" +#include -struct VSFormat; -struct VSVideoInfo; namespace vsutl { +bool is_vs_gray (int cf); +bool is_vs_rgb (int cf); +bool is_vs_yuv (int cf); +bool is_vs_same_colfam (int lhs, int rhs); bool is_constant_format (const ::VSVideoInfo &vi); bool has_chroma (const ::VSFormat &fmt); diff --git a/src/vsutl/fnc.cpp b/src/vsutl/fnc_vsutl.cpp similarity index 90% rename from src/vsutl/fnc.cpp rename to src/vsutl/fnc_vsutl.cpp index 30d6fa3..bee3844 100644 --- a/src/vsutl/fnc.cpp +++ b/src/vsutl/fnc_vsutl.cpp @@ -26,7 +26,6 @@ To Public License, Version 2, as published by Sam Hocevar. See #include "fstb/fnc.h" #include "vsutl/fnc.h" -#include "VapourSynth.h" #include #include @@ -38,6 +37,38 @@ namespace vsutl +bool is_vs_gray (int cf) +{ + return (cf == ::cfGray || cf == ::cmGray); +} + + + +bool is_vs_rgb (int cf) +{ + return (cf == ::cfRGB || cf == ::cmRGB); +} + + + +bool is_vs_yuv (int cf) +{ + return (cf == ::cfYUV || cf == ::cmYUV); +} + + + +bool is_vs_same_colfam (int lhs, int rhs) +{ + return ( + is_vs_gray (lhs) == is_vs_gray (rhs) + && is_vs_rgb ( lhs) == is_vs_rgb ( rhs) + && is_vs_yuv ( lhs) == is_vs_yuv ( rhs) + ); +} + + + bool is_constant_format (const ::VSVideoInfo &vi) { return (vi.height > 0 && vi.width > 0 && vi.format != 0); @@ -47,7 +78,7 @@ bool is_constant_format (const ::VSVideoInfo &vi) bool has_chroma (const ::VSFormat &fmt) { - return ( fmt.colorFamily == ::cmYUV + return ( is_vs_yuv (fmt.colorFamily) || fmt.colorFamily == ::cmYCoCg); } @@ -65,7 +96,7 @@ bool is_chroma_plane (const ::VSFormat &fmt, int plane_index) bool is_full_range_default (const ::VSFormat &fmt) { - return ( fmt.colorFamily == ::cmRGB + return ( is_vs_rgb (fmt.colorFamily) || fmt.colorFamily == ::cmYCoCg); } diff --git a/zip-release.bat b/zip-release.bat index 991df48..24ea209 100644 --- a/zip-release.bat +++ b/zip-release.bat @@ -7,32 +7,45 @@ @mkdir "reltmp" @mkdir "reltmp\src" -@mkdir "reltmp\build" -@mkdir "reltmp\build\win" -@mkdir "reltmp\win32" -@mkdir "reltmp\win64" -@xcopy /I "doc" "reltmp\doc" -@xcopy /I "build\unix" "reltmp\build\unix" -@xcopy /I "build\unix\m4" "reltmp\build\unix\m4" -@xcopy /I "src\conc" "reltmp\src\conc" -@xcopy /I "src\ffft" "reltmp\src\ffft" -@xcopy /I "src\fmtc" "reltmp\src\fmtc" -@xcopy /I "src\fmtcl" "reltmp\src\fmtcl" -@xcopy /I "src\fstb" "reltmp\src\fstb" -@xcopy /I "src\vsutl" "reltmp\src\vsutl" -@copy "src\*.cpp" "reltmp\src" -@copy "src\*.h" "reltmp\src" -@copy "src\*.hpp" "reltmp\src" -@copy "build\win\*.sln" "reltmp\build\win" -@copy "build\win\*.vcxproj" "reltmp\build\win" -@copy "build\win\*.vcxproj.filters" "reltmp\build\win" -@copy "build\win\ReleaseWin32\fmtconv.dll" "reltmp\win32" -@copy "build\win\Releasex64\fmtconv.dll" "reltmp\win64" -@copy "*.md" "reltmp" -@copy "COPYING" "reltmp" +@mkdir "reltmp\build\win\common" +@mkdir "reltmp\build\win\fmtcavs" +@mkdir "reltmp\build\win\fmtconv" +@mkdir "reltmp\vapoursynth\win32" +@mkdir "reltmp\vapoursynth\win64" +@xcopy /I "doc" "reltmp\doc" +@xcopy /I "build\unix" "reltmp\build\unix" +@xcopy /I "build\unix\m4" "reltmp\build\unix\m4" +@xcopy /I "src\avs" "reltmp\src\avs" +@xcopy /I "src\avsutl" "reltmp\src\avsutl" +@xcopy /I "src\conc" "reltmp\src\conc" +@xcopy /I "src\ffft" "reltmp\src\ffft" +@xcopy /I "src\fmtc" "reltmp\src\fmtc" +@xcopy /I "src\fmtcavs" "reltmp\src\fmtcavs" +@xcopy /I "src\fmtcl" "reltmp\src\fmtcl" +@xcopy /I "src\fstb" "reltmp\src\fstb" +@xcopy /I "src\vsutl" "reltmp\src\vsutl" +@copy "src\*.cpp" "reltmp\src" +@copy "src\*.h" "reltmp\src" +@copy "src\*.hpp" "reltmp\src" +@copy "build\win\*.sln" "reltmp\build\win" +@copy "build\win\*.vcxproj" "reltmp\build\win" +@copy "build\win\*.vcxproj.filters" "reltmp\build\win" +@copy "build\win\*.props" "reltmp\build\win" +@copy "build\win\common\*.vcxproj" "reltmp\build\win\common" +@copy "build\win\common\*.vcxproj.filters" "reltmp\build\win\common" +@copy "build\win\fmtcavs\*.vcxproj" "reltmp\build\win\fmtcavs" +@copy "build\win\fmtcavs\*.vcxproj.filters" "reltmp\build\win\fmtcavs" +@copy "build\win\fmtconv\*.vcxproj" "reltmp\build\win\fmtconv" +@copy "build\win\fmtconv\*.vcxproj.filters" "reltmp\build\win\fmtconv" +@copy "build\win\fmtcavs\ReleaseWin32\fmtcavs.dll" "reltmp\avisynth+\win32" +@copy "build\win\fmtcavs\Releasex64\fmtcavs.dll" "reltmp\avisynth+\win64" +@copy "build\win\fmtconv\ReleaseWin32\fmtconv.dll" "reltmp\vapoursynth\win32" +@copy "build\win\fmtconv\Releasex64\fmtconv.dll" "reltmp\vapoursynth\win64" +@copy "*.md" "reltmp" +@copy "COPYING" "reltmp" @cd reltmp -@echo fmtconv - Format conversion tools for Vapoursynth. | "C:\Program Files (x86)\Infozip\zip.exe" -r -o -9 -z "..\releases\fmtconv-rnew.zip" "*.*" +@echo fmtconv - Format conversion tools for Vapoursynth and Avisynth+. | "C:\Program Files (x86)\Infozip\zip.exe" -r -o -9 -z "..\releases\fmtconv-rnew.zip" "*.*" @cd .. @rmdir /s /q "reltmp"