├── .gitignore
├── .gitmodules
├── Include
├── FilterInterfaces.h
├── FilterInterfacesImpl.h
├── VSScript4.h
├── VapourSynth4.h
├── Version.h
├── avisynth.h
└── avs
│ ├── capi.h
│ ├── config.h
│ ├── cpuid.h
│ └── types.h
├── LICENSE.txt
├── MpcScriptSource.sln
├── Readme.md
├── Source
├── AviSynthStream.cpp
├── AviSynthStream.h
├── Helper.cpp
├── Helper.h
├── IScriptSource.h
├── MpcScriptSource.def
├── MpcScriptSource.rc
├── MpcScriptSource.vcxproj
├── MpcScriptSource.vcxproj.filters
├── PropPage.cpp
├── PropPage.h
├── ScriptSource.cpp
├── ScriptSource.h
├── Utils
│ ├── StringUtil.cpp
│ ├── StringUtil.h
│ ├── Util.cpp
│ └── Util.h
├── VUIOptions.cpp
├── VUIOptions.h
├── VapourSynthStream.cpp
├── VapourSynthStream.h
├── dllmain.cpp
├── res
│ └── MpcScriptSource.rc2
├── resource.h
├── stdafx.cpp
└── stdafx.h
├── build_scriptsource.cmd
├── common.props
├── distrib
├── Install_MpcScriptSource_32.cmd
├── Install_MpcScriptSource_64.cmd
├── Reset_Settings.cmd
├── Uninstall_MpcScriptSource_32.cmd
└── Uninstall_MpcScriptSource_64.cmd
├── external
├── BaseClasses.vcxproj
└── BaseClasses.vcxproj.filters
├── history.txt
├── platform.props
├── sign.cmd
└── update_revision.cmd
/.gitignore:
--------------------------------------------------------------------------------
1 | *.user
2 | *.aps
3 | /.vs
4 | /_bin
5 | /revision.h
6 | /signinfo.txt
7 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "external/BaseClasses"]
2 | path = external/BaseClasses
3 | url = https://github.com/v0lt/BaseClasses.git
4 |
--------------------------------------------------------------------------------
/Include/FilterInterfaces.h:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) 2017-2024 see Authors.txt
3 | *
4 | * This file is part of MPC-BE.
5 | *
6 | * MPC-BE is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * MPC-BE is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | *
19 | */
20 |
21 | #pragma once
22 |
23 | interface __declspec(uuid("3F56FEBC-633C-4C76-8455-0787FC62C8F8")) IExFilterInfo : public IUnknown
24 | {
25 | // The memory for strings and binary data is allocated by the callee
26 | // by using LocalAlloc. It is the caller's responsibility to release the
27 | // memory by calling LocalFree.
28 | STDMETHOD(GetPropertyInt )(LPCSTR field, int *value) PURE;
29 | STDMETHOD(GetPropertyString)(LPCSTR field, LPWSTR *value, unsigned *chars) PURE;
30 | STDMETHOD(GetPropertyBin )(LPCSTR field, LPVOID *value, unsigned *size ) PURE;
31 | };
32 | // return values:
33 | // E_NOTIMPL - method not implemented, any parameters will be ignored.
34 | // E_POINTER - invalid pointer
35 | // E_INVALIDARG - wrong name or type of field
36 | // E_ABORT - field is correct, but the value is undefined
37 | // S_OK - operation successful
38 | //
39 | // available info fields:
40 | // name type filter valid values
41 | // VIDEO_PROFILE int MatroskaSplitter
42 | // VIDEO_PIXEL_FORMAT int MatroskaSplitter
43 | // VIDEO_INTERLACED int MatroskaSplitter,MP4Splitter,RawVideoSplitter 0-progressive, 1-tff, 2-bff
44 | // VIDEO_FLAG_ONLY_DTS int MatroskaSplitter,MP4Splitter 0-no, 1-yes
45 | // VIDEO_DELAY int MP4Splitter
46 | // PALETTE bin MP4Splitter
47 | // VIDEO_COLOR_SPACE bin MatroskaSplitter
48 | // HDR_MASTERING_METADATA bin MatroskaSplitter
49 | // HDR_CONTENT_LIGHT_LEVEL bin MatroskaSplitter
50 |
51 | interface __declspec(uuid("37CBDF10-D65E-4E5A-8F37-40E0C8EA1695")) IExFilterConfig : public IUnknown
52 | {
53 | // The memory for strings and binary data is allocated by the callee
54 | // by using LocalAlloc. It is the caller's responsibility to release the
55 | // memory by calling LocalFree.
56 | STDMETHOD(Flt_GetBool )(LPCSTR field, bool *value) PURE;
57 | STDMETHOD(Flt_GetInt )(LPCSTR field, int *value) PURE;
58 | STDMETHOD(Flt_GetInt64 )(LPCSTR field, __int64 *value) PURE;
59 | STDMETHOD(Flt_GetDouble)(LPCSTR field, double *value) PURE;
60 | STDMETHOD(Flt_GetString)(LPCSTR field, LPWSTR *value, unsigned *chars) PURE;
61 | STDMETHOD(Flt_GetBin )(LPCSTR field, LPVOID *value, unsigned *size ) PURE;
62 |
63 | STDMETHOD(Flt_SetBool )(LPCSTR field, bool value) PURE;
64 | STDMETHOD(Flt_SetInt )(LPCSTR field, int value) PURE;
65 | STDMETHOD(Flt_SetInt64 )(LPCSTR field, __int64 value) PURE;
66 | STDMETHOD(Flt_SetDouble)(LPCSTR field, double value) PURE;
67 | STDMETHOD(Flt_SetString)(LPCSTR field, LPWSTR value, int chars) PURE;
68 | STDMETHOD(Flt_SetBin )(LPCSTR field, LPVOID value, int size ) PURE;
69 | };
70 | // available settings:
71 | // name type filter mode valid values
72 | // stereodownmix bool MpaDecFilter set true/false
73 | // queueDuration int BaseSplitter set/get 100...15000 milliseconds
74 | // networkTimeout int BaseSplitter set/get 2000...20000 milliseconds (reserved)
75 | // version int64 MpcVideoRenderer get 0.3.3.886 or newer
76 | // statsEnable bool MpcVideoRenderer set/get true/false
77 | // cmd_redraw bool MpcVideoRenderer set true
78 | // playbackState int MpcVideoRenderer get 0-State_Stopped, 1-State_Paused, 2-State_Running
79 | // rotation int MpcVideoRenderer get 0, 90, 180, 270 (reserved)
80 |
--------------------------------------------------------------------------------
/Include/FilterInterfacesImpl.h:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) 2017-2024 see Authors.txt
3 | *
4 | * This file is part of MPC-BE.
5 | *
6 | * MPC-BE is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * MPC-BE is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | *
19 | */
20 |
21 | #pragma once
22 |
23 | #include "FilterInterfaces.h"
24 |
25 | class CExFilterInfoImpl : public IExFilterInfo
26 | {
27 | STDMETHODIMP GetPropertyInt (LPCSTR field, int *value) { return E_NOTIMPL; };
28 | STDMETHODIMP GetPropertyString(LPCSTR field, LPWSTR *value, unsigned *chars) { return E_NOTIMPL; };
29 | STDMETHODIMP GetPropertyBin (LPCSTR field, LPVOID *value, unsigned *size ) { return E_NOTIMPL; };
30 | };
31 |
32 | class CExFilterConfigImpl : public IExFilterConfig
33 | {
34 | STDMETHODIMP Flt_GetBool (LPCSTR field, bool *value) { return E_NOTIMPL; };
35 | STDMETHODIMP Flt_GetInt (LPCSTR field, int *value) { return E_NOTIMPL; };
36 | STDMETHODIMP Flt_GetInt64 (LPCSTR field, __int64 *value) { return E_NOTIMPL; };
37 | STDMETHODIMP Flt_GetDouble(LPCSTR field, double *value) { return E_NOTIMPL; };
38 | STDMETHODIMP Flt_GetString(LPCSTR field, LPWSTR *value, unsigned *chars) { return E_NOTIMPL; };
39 | STDMETHODIMP Flt_GetBin (LPCSTR field, LPVOID *value, unsigned *size ) { return E_NOTIMPL; };
40 |
41 | STDMETHODIMP Flt_SetBool (LPCSTR field, bool value) { return E_NOTIMPL; };
42 | STDMETHODIMP Flt_SetInt (LPCSTR field, int value) { return E_NOTIMPL; };
43 | STDMETHODIMP Flt_SetInt64 (LPCSTR field, __int64 value) { return E_NOTIMPL; };
44 | STDMETHODIMP Flt_SetDouble(LPCSTR field, double value) { return E_NOTIMPL; };
45 | STDMETHODIMP Flt_SetString(LPCSTR field, LPWSTR value, int chars) { return E_NOTIMPL; };
46 | STDMETHODIMP Flt_SetBin (LPCSTR field, LPVOID value, int size ) { return E_NOTIMPL; };
47 | };
48 |
--------------------------------------------------------------------------------
/Include/VSScript4.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2020 Fredrik Mellbin
3 | *
4 | * This file is part of VapourSynth.
5 | *
6 | * VapourSynth is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * VapourSynth is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with VapourSynth; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | #ifndef VSSCRIPT4_H
22 | #define VSSCRIPT4_H
23 |
24 | #include "VapourSynth4.h"
25 |
26 | #define VSSCRIPT_API_MAJOR 4
27 | #define VSSCRIPT_API_MINOR 1
28 | #define VSSCRIPT_API_VERSION VS_MAKE_VERSION(VSSCRIPT_API_MAJOR, VSSCRIPT_API_MINOR)
29 |
30 | typedef struct VSScript VSScript;
31 | typedef struct VSSCRIPTAPI VSSCRIPTAPI;
32 |
33 | struct VSSCRIPTAPI {
34 | /* Returns the highest supported VSSCRIPT_API_VERSION */
35 | int (VS_CC *getAPIVersion)(void) VS_NOEXCEPT;
36 |
37 | /* Convenience function for retrieving a VSAPI pointer without having to use the VapourSynth library. Always pass VAPOURSYNTH_API_VERSION */
38 | const VSAPI *(VS_CC *getVSAPI)(int version) VS_NOEXCEPT;
39 |
40 | /*
41 | * Providing a pre-created core is useful for setting core creation flags, log callbacks, preload specific plugins and many other things.
42 | * You must create a VSScript object before evaluating a script. Always takes ownership of the core even on failure. Returns NULL on failure.
43 | * Pass NULL to have a core automatically created with the default options.
44 | */
45 | VSScript *(VS_CC *createScript)(VSCore *core) VS_NOEXCEPT;
46 |
47 | /* The core is valid as long as the environment exists, return NULL on error */
48 | VSCore *(VS_CC *getCore)(VSScript *handle) VS_NOEXCEPT;
49 |
50 | /*
51 | * Evaluates a script passed in the buffer argument. The scriptFilename is only used for display purposes. in Python
52 | * it means that the main module won't be unnamed in error messages.
53 | *
54 | * Returns 0 on success.
55 | *
56 | * Note that calling any function other than getError() and freeScript() on a VSScript object in the error state
57 | * will result in undefined behavior.
58 | */
59 | int (VS_CC *evaluateBuffer)(VSScript *handle, const char *buffer, const char *scriptFilename) VS_NOEXCEPT;
60 |
61 | /* Convenience version of the above function that loads the script from scriptFilename and passes as the buffer to evaluateBuffer */
62 | int (VS_CC *evaluateFile)(VSScript *handle, const char *scriptFilename) VS_NOEXCEPT;
63 |
64 | /* Returns NULL on success, otherwise an error message */
65 | const char *(VS_CC *getError)(VSScript *handle) VS_NOEXCEPT;
66 |
67 | /* Returns the script's reported exit code */
68 | int (VS_CC *getExitCode)(VSScript *handle) VS_NOEXCEPT;
69 |
70 | /* Fetches a variable of any VSMap storable type set in a script. It is stored in the key with the same name in dst. Returns 0 on success. */
71 | int (VS_CC *getVariable)(VSScript *handle, const char *name, VSMap *dst) VS_NOEXCEPT;
72 |
73 | /* Sets all keys in the provided VSMap as variables in the script. Returns 0 on success. */
74 | int (VS_CC *setVariables)(VSScript *handle, const VSMap *vars) VS_NOEXCEPT;
75 |
76 | /*
77 | * The returned nodes must be freed using freeNode() before calling freeScript() since they may depend on data in the VSScript
78 | * environment. Returns NULL if no node was set as output in the script. Index 0 is used by default in scripts and other
79 | * values are rarely used.
80 | */
81 | VSNode *(VS_CC *getOutputNode)(VSScript *handle, int index) VS_NOEXCEPT;
82 | VSNode *(VS_CC *getOutputAlphaNode)(VSScript *handle, int index) VS_NOEXCEPT;
83 | int (VS_CC *getAltOutputMode)(VSScript *handle, int index) VS_NOEXCEPT;
84 |
85 | void (VS_CC *freeScript)(VSScript *handle) VS_NOEXCEPT;
86 |
87 | /*
88 | * Set whether or not the working directory is temporarily changed to the same
89 | * location as the script file when evaluateFile is called. Off by default.
90 | */
91 | void (VS_CC *evalSetWorkingDir)(VSScript *handle, int setCWD) VS_NOEXCEPT;
92 |
93 | };
94 |
95 | VS_API(const VSSCRIPTAPI *) getVSScriptAPI(int version) VS_NOEXCEPT;
96 |
97 | #endif /* VSSCRIPT4_H */
98 |
--------------------------------------------------------------------------------
/Include/Version.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "../revision.h"
4 |
5 | #ifndef REV_DATE
6 | #define REV_DATE 0
7 | #endif
8 |
9 | #ifndef REV_HASH
10 | #define REV_HASH 0
11 | #endif
12 |
13 | #ifndef REV_NUM
14 | #define REV_NUM 0
15 | #endif
16 |
17 | #define DO_MAKE_STR(x) #x
18 | #define MAKE_STR(x) DO_MAKE_STR(x)
19 |
20 | #define VER_RELEASE 1
21 |
22 | #define VER_MAJOR 0
23 | #define VER_MINOR 2
24 | #define VER_BUILD 7
25 |
26 | #define VERSION_NUM VER_MAJOR,VER_MINOR,VER_BUILD,REV_NUM
27 | #define VERSION_STR MAKE_STR(VER_MAJOR) "." MAKE_STR(VER_MINOR) "." MAKE_STR(VER_BUILD) "." MAKE_STR(REV_NUM)
28 |
--------------------------------------------------------------------------------
/Include/avs/capi.h:
--------------------------------------------------------------------------------
1 | // Avisynth C Interface Version 0.20
2 | // Copyright 2003 Kevin Atkinson
3 |
4 | // This program is free software; you can redistribute it and/or modify
5 | // it under the terms of the GNU General Public License as published by
6 | // the Free Software Foundation; either version 2 of the License, or
7 | // (at your option) any later version.
8 | //
9 | // This program is distributed in the hope that it will be useful,
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | // GNU General Public License for more details.
13 | //
14 | // You should have received a copy of the GNU General Public License
15 | // along with this program; if not, write to the Free Software
16 | // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or visit
17 | // http://www.gnu.org/copyleft/gpl.html .
18 | //
19 | // As a special exception, I give you permission to link to the
20 | // Avisynth C interface with independent modules that communicate with
21 | // the Avisynth C interface solely through the interfaces defined in
22 | // avisynth_c.h, regardless of the license terms of these independent
23 | // modules, and to copy and distribute the resulting combined work
24 | // under terms of your choice, provided that every copy of the
25 | // combined work is accompanied by a complete copy of the source code
26 | // of the Avisynth C interface and Avisynth itself (with the version
27 | // used to produce the combined work), being distributed under the
28 | // terms of the GNU General Public License plus this exception. An
29 | // independent module is a module which is not derived from or based
30 | // on Avisynth C Interface, such as 3rd-party filters, import and
31 | // export plugins, or graphical user interfaces.
32 |
33 | #ifndef AVS_CAPI_H
34 | #define AVS_CAPI_H
35 |
36 | #include "config.h"
37 |
38 | #ifdef AVS_POSIX
39 | // this is also defined in avs/posix.h
40 | #ifndef AVS_HAIKU
41 | #define __declspec(x)
42 | #endif
43 | #endif
44 |
45 | #ifdef __cplusplus
46 | # define EXTERN_C extern "C"
47 | #else
48 | # define EXTERN_C
49 | #endif
50 |
51 | #ifdef AVS_WINDOWS
52 | #ifdef BUILDING_AVSCORE
53 | # if defined(GCC) && defined(X86_32)
54 | # define AVSC_CC
55 | # else // MSVC builds and 64-bit GCC
56 | # ifndef AVSC_USE_STDCALL
57 | # define AVSC_CC __cdecl
58 | # else
59 | # define AVSC_CC __stdcall
60 | # endif
61 | # endif
62 | #else // needed for programs that talk to AviSynth+
63 | # ifndef AVSC_WIN32_GCC32 // see comment below
64 | # ifndef AVSC_USE_STDCALL
65 | # define AVSC_CC __cdecl
66 | # else
67 | # define AVSC_CC __stdcall
68 | # endif
69 | # else
70 | # define AVSC_CC
71 | # endif
72 | #endif
73 | # else
74 | # define AVSC_CC
75 | #endif
76 |
77 | // On 64-bit Windows, there's only one calling convention,
78 | // so there is no difference between MSVC and GCC. On 32-bit,
79 | // this isn't true. The convention that GCC needs to use to
80 | // even build AviSynth+ as 32-bit makes anything that uses
81 | // it incompatible with 32-bit MSVC builds of AviSynth+.
82 | // The AVSC_WIN32_GCC32 define is meant to provide a user
83 | // switchable way to make builds of FFmpeg to test 32-bit
84 | // GCC builds of AviSynth+ without having to screw around
85 | // with alternate headers, while still default to the usual
86 | // situation of using 32-bit MSVC builds of AviSynth+.
87 |
88 | // Hopefully, this situation will eventually be resolved
89 | // and a broadly compatible solution will arise so the
90 | // same 32-bit FFmpeg build can handle either MSVC or GCC
91 | // builds of AviSynth+.
92 |
93 | #define AVSC_INLINE static __inline
94 |
95 | #ifdef BUILDING_AVSCORE
96 | #ifdef AVS_WINDOWS
97 | # ifndef AVS_STATIC_LIB
98 | # define AVSC_EXPORT __declspec(dllexport)
99 | # else
100 | # define AVSC_EXPORT
101 | # endif
102 | # define AVSC_API(ret, name) EXTERN_C AVSC_EXPORT ret AVSC_CC name
103 | #else
104 | # define AVSC_EXPORT EXTERN_C
105 | # define AVSC_API(ret, name) EXTERN_C ret AVSC_CC name
106 | #endif
107 | #else
108 | # define AVSC_EXPORT EXTERN_C __declspec(dllexport)
109 | # ifndef AVS_STATIC_LIB
110 | # define AVSC_IMPORT __declspec(dllimport)
111 | # else
112 | # define AVSC_IMPORT
113 | # endif
114 | # ifndef AVSC_NO_DECLSPEC
115 | # define AVSC_API(ret, name) EXTERN_C AVSC_IMPORT ret AVSC_CC name
116 | # else
117 | # define AVSC_API(ret, name) typedef ret (AVSC_CC *name##_func)
118 | # endif
119 | #endif
120 |
121 | #endif //AVS_CAPI_H
122 |
--------------------------------------------------------------------------------
/Include/avs/config.h:
--------------------------------------------------------------------------------
1 | // Avisynth C Interface Version 0.20
2 | // Copyright 2003 Kevin Atkinson
3 |
4 | // This program is free software; you can redistribute it and/or modify
5 | // it under the terms of the GNU General Public License as published by
6 | // the Free Software Foundation; either version 2 of the License, or
7 | // (at your option) any later version.
8 | //
9 | // This program is distributed in the hope that it will be useful,
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | // GNU General Public License for more details.
13 | //
14 | // You should have received a copy of the GNU General Public License
15 | // along with this program; if not, write to the Free Software
16 | // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or visit
17 | // http://www.gnu.org/copyleft/gpl.html .
18 | //
19 | // As a special exception, I give you permission to link to the
20 | // Avisynth C interface with independent modules that communicate with
21 | // the Avisynth C interface solely through the interfaces defined in
22 | // avisynth_c.h, regardless of the license terms of these independent
23 | // modules, and to copy and distribute the resulting combined work
24 | // under terms of your choice, provided that every copy of the
25 | // combined work is accompanied by a complete copy of the source code
26 | // of the Avisynth C interface and Avisynth itself (with the version
27 | // used to produce the combined work), being distributed under the
28 | // terms of the GNU General Public License plus this exception. An
29 | // independent module is a module which is not derived from or based
30 | // on Avisynth C Interface, such as 3rd-party filters, import and
31 | // export plugins, or graphical user interfaces.
32 |
33 | #ifndef AVS_CONFIG_H
34 | #define AVS_CONFIG_H
35 |
36 | // Undefine this to get cdecl calling convention
37 | #define AVSC_USE_STDCALL 1
38 |
39 | // NOTE TO PLUGIN AUTHORS:
40 | // Because FRAME_ALIGN can be substantially higher than the alignment
41 | // a plugin actually needs, plugins should not use FRAME_ALIGN to check for
42 | // alignment. They should always request the exact alignment value they need.
43 | // This is to make sure that plugins work over the widest range of AviSynth
44 | // builds possible.
45 | #define FRAME_ALIGN 64
46 |
47 | #if defined(_M_AMD64) || defined(__x86_64)
48 | # define X86_64
49 | #elif defined(_M_IX86) || defined(__i386__)
50 | # define X86_32
51 | // VS2017 introduced _M_ARM64
52 | #elif defined(_M_ARM64) || defined(__aarch64__)
53 | # define ARM64
54 | #elif defined(_M_ARM) || defined(__arm__)
55 | # define ARM32
56 | #elif defined(__PPC64__)
57 | # define PPC64
58 | #elif defined(_M_PPC) || defined(__PPC__) || defined(__POWERPC__)
59 | # define PPC32
60 | #elif defined(__riscv)
61 | # define RISCV
62 | #elif defined(__sparc_v9__)
63 | # define SPARC
64 | #elif defined(__mips__)
65 | # define MIPS
66 | #else
67 | # error Unsupported CPU architecture.
68 | #endif
69 |
70 | // VC++ LLVM-Clang-cl MinGW-Gnu
71 | // MSVC x x
72 | // MSVC_PURE x
73 | // CLANG x
74 | // GCC x
75 |
76 | #if defined(__clang__)
77 | // Check clang first. clang-cl also defines __MSC_VER
78 | // We set MSVC because they are mostly compatible
79 | # define CLANG
80 | #if defined(_MSC_VER)
81 | # define MSVC
82 | # define AVS_FORCEINLINE __attribute__((always_inline))
83 | #else
84 | # define AVS_FORCEINLINE __attribute__((always_inline)) inline
85 | #endif
86 | #elif defined(_MSC_VER)
87 | # define MSVC
88 | # define MSVC_PURE
89 | # define AVS_FORCEINLINE __forceinline
90 | #elif defined(__GNUC__)
91 | # define GCC
92 | # define AVS_FORCEINLINE __attribute__((always_inline)) inline
93 | #elif defined(__INTEL_COMPILER) || defined(__INTEL_LLVM_COMPILER)
94 | // Intel C++ Compilers with MSVC command line interface will not appear here rather at _MSC_VER
95 | # define AVS_FORCEINLINE inline
96 | # undef __forceinline
97 | # define __forceinline inline
98 | #else
99 | # error Unsupported compiler.
100 | # define AVS_FORCEINLINE inline
101 | # undef __forceinline
102 | # define __forceinline inline
103 | #endif
104 |
105 | #if defined(_WIN32)
106 | # define AVS_WINDOWS
107 | #elif defined(__linux__)
108 | # define AVS_LINUX
109 | # define AVS_POSIX
110 | #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
111 | # define AVS_BSD
112 | # define AVS_POSIX
113 | #elif defined(__APPLE__)
114 | # define AVS_MACOS
115 | # define AVS_POSIX
116 | #elif defined(__HAIKU__)
117 | # define AVS_HAIKU
118 | # define AVS_POSIX
119 | #else
120 | # error Operating system unsupported.
121 | #endif
122 |
123 | // useful warnings disabler macros for supported compilers
124 |
125 | #if defined(_MSC_VER)
126 | #define DISABLE_WARNING_PUSH __pragma(warning( push ))
127 | #define DISABLE_WARNING_POP __pragma(warning( pop ))
128 | #define DISABLE_WARNING(warningNumber) __pragma(warning( disable : warningNumber ))
129 |
130 | #define DISABLE_WARNING_UNREFERENCED_LOCAL_VARIABLE DISABLE_WARNING(4101)
131 | #define DISABLE_WARNING_UNREFERENCED_FUNCTION DISABLE_WARNING(4505)
132 | // other warnings you want to deactivate...
133 |
134 | #elif defined(__GNUC__) || defined(__clang__)
135 | #define DO_PRAGMA(X) _Pragma(#X)
136 | #define DISABLE_WARNING_PUSH DO_PRAGMA(GCC diagnostic push)
137 | #define DISABLE_WARNING_POP DO_PRAGMA(GCC diagnostic pop)
138 | #define DISABLE_WARNING(warningName) DO_PRAGMA(GCC diagnostic ignored #warningName)
139 |
140 | #define DISABLE_WARNING_UNREFERENCED_LOCAL_VARIABLE DISABLE_WARNING(-Wunused-variable)
141 | #define DISABLE_WARNING_UNREFERENCED_FUNCTION DISABLE_WARNING(-Wunused-function)
142 | // other warnings you want to deactivate...
143 |
144 | #else
145 | #define DISABLE_WARNING_PUSH
146 | #define DISABLE_WARNING_POP
147 | #define DISABLE_WARNING_UNREFERENCED_LOCAL_VARIABLE
148 | #define DISABLE_WARNING_UNREFERENCED_FUNCTION
149 | // other warnings you want to deactivate...
150 |
151 | #endif
152 |
153 | #if defined(AVS_WINDOWS) && defined(_USING_V110_SDK71_)
154 | // Windows XP does not have proper initialization for
155 | // thread local variables.
156 | // Use workaround instead __declspec(thread)
157 | #define XP_TLS
158 | #endif
159 |
160 | #ifndef MSVC
161 | // GCC and Clang can be used on big endian systems, MSVC can't.
162 | # if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
163 | # define AVS_ENDIANNESS "little"
164 | # elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
165 | # define AVS_ENDIANNESS "big"
166 | # else
167 | # define AVS_ENDIANNESS "middle"
168 | # endif
169 | #else
170 | #define AVS_ENDIANNESS "little"
171 | #endif
172 |
173 | #endif //AVS_CONFIG_H
174 |
--------------------------------------------------------------------------------
/Include/avs/cpuid.h:
--------------------------------------------------------------------------------
1 | // This program is free software; you can redistribute it and/or modify
2 | // it under the terms of the GNU General Public License as published by
3 | // the Free Software Foundation; either version 2 of the License, or
4 | // (at your option) any later version.
5 | //
6 | // This program is distributed in the hope that it will be useful,
7 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
8 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 | // GNU General Public License for more details.
10 | //
11 | // You should have received a copy of the GNU General Public License
12 | // along with this program; if not, write to the Free Software
13 | // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or visit
14 | // http://www.gnu.org/copyleft/gpl.html .
15 | //
16 | // Linking Avisynth statically or dynamically with other modules is making a
17 | // combined work based on Avisynth. Thus, the terms and conditions of the GNU
18 | // General Public License cover the whole combination.
19 | //
20 | // As a special exception, the copyright holders of Avisynth give you
21 | // permission to link Avisynth with independent modules that communicate with
22 | // Avisynth solely through the interfaces defined in avisynth.h, regardless of the license
23 | // terms of these independent modules, and to copy and distribute the
24 | // resulting combined work under terms of your choice, provided that
25 | // every copy of the combined work is accompanied by a complete copy of
26 | // the source code of Avisynth (the version of Avisynth used to produce the
27 | // combined work), being distributed under the terms of the GNU General
28 | // Public License plus this exception. An independent module is a module
29 | // which is not derived from or based on Avisynth, such as 3rd-party filters,
30 | // import and export plugins, or graphical user interfaces.
31 |
32 | #ifndef AVSCORE_CPUID_H
33 | #define AVSCORE_CPUID_H
34 |
35 | // For GetCPUFlags. These are backwards-compatible with those in VirtualDub.
36 | // ending with SSE4_2
37 | // For emulation see https://software.intel.com/en-us/articles/intel-software-development-emulator
38 | enum {
39 | /* oldest CPU to support extension */
40 | CPUF_FORCE = 0x01, // N/A
41 | CPUF_FPU = 0x02, // 386/486DX
42 | CPUF_MMX = 0x04, // P55C, K6, PII
43 | CPUF_INTEGER_SSE = 0x08, // PIII, Athlon
44 | CPUF_SSE = 0x10, // PIII, Athlon XP/MP
45 | CPUF_SSE2 = 0x20, // PIV, K8
46 | CPUF_3DNOW = 0x40, // K6-2
47 | CPUF_3DNOW_EXT = 0x80, // Athlon
48 | CPUF_X86_64 = 0xA0, // Hammer (note: equiv. to 3DNow + SSE2, which
49 | // only Hammer will have anyway)
50 | CPUF_SSE3 = 0x100, // PIV+, K8 Venice
51 | CPUF_SSSE3 = 0x200, // Core 2
52 | CPUF_SSE4 = 0x400,
53 | CPUF_SSE4_1 = 0x400, // Penryn, Wolfdale, Yorkfield
54 | CPUF_AVX = 0x800, // Sandy Bridge, Bulldozer
55 | CPUF_SSE4_2 = 0x1000, // Nehalem
56 | // AVS+
57 | CPUF_AVX2 = 0x2000, // Haswell
58 | CPUF_FMA3 = 0x4000,
59 | CPUF_F16C = 0x8000,
60 | CPUF_MOVBE = 0x10000, // Big Endian move
61 | CPUF_POPCNT = 0x20000,
62 | CPUF_AES = 0x40000,
63 | CPUF_FMA4 = 0x80000,
64 |
65 | CPUF_AVX512F = 0x100000, // AVX-512 Foundation.
66 | CPUF_AVX512DQ = 0x200000, // AVX-512 DQ (Double/Quad granular) Instructions
67 | CPUF_AVX512PF = 0x400000, // AVX-512 Prefetch
68 | CPUF_AVX512ER = 0x800000, // AVX-512 Exponential and Reciprocal
69 | CPUF_AVX512CD = 0x1000000, // AVX-512 Conflict Detection
70 | CPUF_AVX512BW = 0x2000000, // AVX-512 BW (Byte/Word granular) Instructions
71 | CPUF_AVX512VL = 0x4000000, // AVX-512 VL (128/256 Vector Length) Extensions
72 | CPUF_AVX512IFMA = 0x8000000, // AVX-512 IFMA integer 52 bit
73 | CPUF_AVX512VBMI = 0x10000000,// AVX-512 VBMI
74 | };
75 |
76 | #ifdef BUILDING_AVSCORE
77 | int GetCPUFlags();
78 | void SetMaxCPU(int new_flags);
79 | #endif
80 |
81 | #endif // AVSCORE_CPUID_H
82 |
--------------------------------------------------------------------------------
/Include/avs/types.h:
--------------------------------------------------------------------------------
1 | // Avisynth C Interface Version 0.20
2 | // Copyright 2003 Kevin Atkinson
3 |
4 | // This program is free software; you can redistribute it and/or modify
5 | // it under the terms of the GNU General Public License as published by
6 | // the Free Software Foundation; either version 2 of the License, or
7 | // (at your option) any later version.
8 | //
9 | // This program is distributed in the hope that it will be useful,
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | // GNU General Public License for more details.
13 | //
14 | // You should have received a copy of the GNU General Public License
15 | // along with this program; if not, write to the Free Software
16 | // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or visit
17 | // http://www.gnu.org/copyleft/gpl.html .
18 | //
19 | // As a special exception, I give you permission to link to the
20 | // Avisynth C interface with independent modules that communicate with
21 | // the Avisynth C interface solely through the interfaces defined in
22 | // avisynth_c.h, regardless of the license terms of these independent
23 | // modules, and to copy and distribute the resulting combined work
24 | // under terms of your choice, provided that every copy of the
25 | // combined work is accompanied by a complete copy of the source code
26 | // of the Avisynth C interface and Avisynth itself (with the version
27 | // used to produce the combined work), being distributed under the
28 | // terms of the GNU General Public License plus this exception. An
29 | // independent module is a module which is not derived from or based
30 | // on Avisynth C Interface, such as 3rd-party filters, import and
31 | // export plugins, or graphical user interfaces.
32 |
33 | #ifndef AVS_TYPES_H
34 | #define AVS_TYPES_H
35 |
36 | // Define all types necessary for interfacing with avisynth.dll
37 | #include
38 | #include
39 | #ifdef __cplusplus
40 | #include
41 | #include
42 | #else
43 | #include
44 | #include
45 | #endif
46 |
47 | // Raster types used by VirtualDub & Avisynth
48 | typedef uint32_t Pixel32;
49 | typedef uint8_t BYTE;
50 |
51 | // Audio Sample information
52 | typedef float SFLOAT;
53 |
54 | #endif //AVS_TYPES_H
55 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 2.1, February 1999
3 |
4 | Copyright (C) 1991, 1999 Free Software Foundation, Inc.
5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, but changing it is not allowed.
8 |
9 | [This is the first released version of the Lesser GPL. It also counts
10 | as the successor of the GNU Library Public License, version 2, hence
11 | the version number 2.1.]
12 |
13 | Preamble
14 |
15 | The licenses for most software are designed to take away your
16 | freedom to share and change it. By contrast, the GNU General Public
17 | Licenses are intended to guarantee your freedom to share and change
18 | free software--to make sure the software is free for all its users.
19 |
20 | This license, the Lesser General Public License, applies to some
21 | specially designated software packages--typically libraries--of the
22 | Free Software Foundation and other authors who decide to use it. You
23 | can use it too, but we suggest you first think carefully about whether
24 | this license or the ordinary General Public License is the better
25 | strategy to use in any particular case, based on the explanations below.
26 |
27 | When we speak of free software, we are referring to freedom of use,
28 | not price. Our General Public Licenses are designed to make sure that
29 | you have the freedom to distribute copies of free software (and charge
30 | for this service if you wish); that you receive source code or can get
31 | it if you want it; that you can change the software and use pieces of
32 | it in new free programs; and that you are informed that you can do
33 | these things.
34 |
35 | To protect your rights, we need to make restrictions that forbid
36 | distributors to deny you these rights or to ask you to surrender these
37 | rights. These restrictions translate to certain responsibilities for
38 | you if you distribute copies of the library or if you modify it.
39 |
40 | For example, if you distribute copies of the library, whether gratis
41 | or for a fee, you must give the recipients all the rights that we gave
42 | you. You must make sure that they, too, receive or can get the source
43 | code. If you link other code with the library, you must provide
44 | complete object files to the recipients, so that they can relink them
45 | with the library after making changes to the library and recompiling
46 | it. And you must show them these terms so they know their rights.
47 |
48 | We protect your rights with a two-step method: (1) we copyright the
49 | library, and (2) we offer you this license, which gives you legal
50 | permission to copy, distribute and/or modify the library.
51 |
52 | To protect each distributor, we want to make it very clear that
53 | there is no warranty for the free library. Also, if the library is
54 | modified by someone else and passed on, the recipients should know
55 | that what they have is not the original version, so that the original
56 | author's reputation will not be affected by problems that might be
57 | introduced by others.
58 |
59 | Finally, software patents pose a constant threat to the existence of
60 | any free program. We wish to make sure that a company cannot
61 | effectively restrict the users of a free program by obtaining a
62 | restrictive license from a patent holder. Therefore, we insist that
63 | any patent license obtained for a version of the library must be
64 | consistent with the full freedom of use specified in this license.
65 |
66 | Most GNU software, including some libraries, is covered by the
67 | ordinary GNU General Public License. This license, the GNU Lesser
68 | General Public License, applies to certain designated libraries, and
69 | is quite different from the ordinary General Public License. We use
70 | this license for certain libraries in order to permit linking those
71 | libraries into non-free programs.
72 |
73 | When a program is linked with a library, whether statically or using
74 | a shared library, the combination of the two is legally speaking a
75 | combined work, a derivative of the original library. The ordinary
76 | General Public License therefore permits such linking only if the
77 | entire combination fits its criteria of freedom. The Lesser General
78 | Public License permits more lax criteria for linking other code with
79 | the library.
80 |
81 | We call this license the "Lesser" General Public License because it
82 | does Less to protect the user's freedom than the ordinary General
83 | Public License. It also provides other free software developers Less
84 | of an advantage over competing non-free programs. These disadvantages
85 | are the reason we use the ordinary General Public License for many
86 | libraries. However, the Lesser license provides advantages in certain
87 | special circumstances.
88 |
89 | For example, on rare occasions, there may be a special need to
90 | encourage the widest possible use of a certain library, so that it becomes
91 | a de-facto standard. To achieve this, non-free programs must be
92 | allowed to use the library. A more frequent case is that a free
93 | library does the same job as widely used non-free libraries. In this
94 | case, there is little to gain by limiting the free library to free
95 | software only, so we use the Lesser General Public License.
96 |
97 | In other cases, permission to use a particular library in non-free
98 | programs enables a greater number of people to use a large body of
99 | free software. For example, permission to use the GNU C Library in
100 | non-free programs enables many more people to use the whole GNU
101 | operating system, as well as its variant, the GNU/Linux operating
102 | system.
103 |
104 | Although the Lesser General Public License is Less protective of the
105 | users' freedom, it does ensure that the user of a program that is
106 | linked with the Library has the freedom and the wherewithal to run
107 | that program using a modified version of the Library.
108 |
109 | The precise terms and conditions for copying, distribution and
110 | modification follow. Pay close attention to the difference between a
111 | "work based on the library" and a "work that uses the library". The
112 | former contains code derived from the library, whereas the latter must
113 | be combined with the library in order to run.
114 |
115 | GNU LESSER GENERAL PUBLIC LICENSE
116 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
117 |
118 | 0. This License Agreement applies to any software library or other
119 | program which contains a notice placed by the copyright holder or
120 | other authorized party saying it may be distributed under the terms of
121 | this Lesser General Public License (also called "this License").
122 | Each licensee is addressed as "you".
123 |
124 | A "library" means a collection of software functions and/or data
125 | prepared so as to be conveniently linked with application programs
126 | (which use some of those functions and data) to form executables.
127 |
128 | The "Library", below, refers to any such software library or work
129 | which has been distributed under these terms. A "work based on the
130 | Library" means either the Library or any derivative work under
131 | copyright law: that is to say, a work containing the Library or a
132 | portion of it, either verbatim or with modifications and/or translated
133 | straightforwardly into another language. (Hereinafter, translation is
134 | included without limitation in the term "modification".)
135 |
136 | "Source code" for a work means the preferred form of the work for
137 | making modifications to it. For a library, complete source code means
138 | all the source code for all modules it contains, plus any associated
139 | interface definition files, plus the scripts used to control compilation
140 | and installation of the library.
141 |
142 | Activities other than copying, distribution and modification are not
143 | covered by this License; they are outside its scope. The act of
144 | running a program using the Library is not restricted, and output from
145 | such a program is covered only if its contents constitute a work based
146 | on the Library (independent of the use of the Library in a tool for
147 | writing it). Whether that is true depends on what the Library does
148 | and what the program that uses the Library does.
149 |
150 | 1. You may copy and distribute verbatim copies of the Library's
151 | complete source code as you receive it, in any medium, provided that
152 | you conspicuously and appropriately publish on each copy an
153 | appropriate copyright notice and disclaimer of warranty; keep intact
154 | all the notices that refer to this License and to the absence of any
155 | warranty; and distribute a copy of this License along with the
156 | Library.
157 |
158 | You may charge a fee for the physical act of transferring a copy,
159 | and you may at your option offer warranty protection in exchange for a
160 | fee.
161 |
162 | 2. You may modify your copy or copies of the Library or any portion
163 | of it, thus forming a work based on the Library, and copy and
164 | distribute such modifications or work under the terms of Section 1
165 | above, provided that you also meet all of these conditions:
166 |
167 | a) The modified work must itself be a software library.
168 |
169 | b) You must cause the files modified to carry prominent notices
170 | stating that you changed the files and the date of any change.
171 |
172 | c) You must cause the whole of the work to be licensed at no
173 | charge to all third parties under the terms of this License.
174 |
175 | d) If a facility in the modified Library refers to a function or a
176 | table of data to be supplied by an application program that uses
177 | the facility, other than as an argument passed when the facility
178 | is invoked, then you must make a good faith effort to ensure that,
179 | in the event an application does not supply such function or
180 | table, the facility still operates, and performs whatever part of
181 | its purpose remains meaningful.
182 |
183 | (For example, a function in a library to compute square roots has
184 | a purpose that is entirely well-defined independent of the
185 | application. Therefore, Subsection 2d requires that any
186 | application-supplied function or table used by this function must
187 | be optional: if the application does not supply it, the square
188 | root function must still compute square roots.)
189 |
190 | These requirements apply to the modified work as a whole. If
191 | identifiable sections of that work are not derived from the Library,
192 | and can be reasonably considered independent and separate works in
193 | themselves, then this License, and its terms, do not apply to those
194 | sections when you distribute them as separate works. But when you
195 | distribute the same sections as part of a whole which is a work based
196 | on the Library, the distribution of the whole must be on the terms of
197 | this License, whose permissions for other licensees extend to the
198 | entire whole, and thus to each and every part regardless of who wrote
199 | it.
200 |
201 | Thus, it is not the intent of this section to claim rights or contest
202 | your rights to work written entirely by you; rather, the intent is to
203 | exercise the right to control the distribution of derivative or
204 | collective works based on the Library.
205 |
206 | In addition, mere aggregation of another work not based on the Library
207 | with the Library (or with a work based on the Library) on a volume of
208 | a storage or distribution medium does not bring the other work under
209 | the scope of this License.
210 |
211 | 3. You may opt to apply the terms of the ordinary GNU General Public
212 | License instead of this License to a given copy of the Library. To do
213 | this, you must alter all the notices that refer to this License, so
214 | that they refer to the ordinary GNU General Public License, version 2,
215 | instead of to this License. (If a newer version than version 2 of the
216 | ordinary GNU General Public License has appeared, then you can specify
217 | that version instead if you wish.) Do not make any other change in
218 | these notices.
219 |
220 | Once this change is made in a given copy, it is irreversible for
221 | that copy, so the ordinary GNU General Public License applies to all
222 | subsequent copies and derivative works made from that copy.
223 |
224 | This option is useful when you wish to copy part of the code of
225 | the Library into a program that is not a library.
226 |
227 | 4. You may copy and distribute the Library (or a portion or
228 | derivative of it, under Section 2) in object code or executable form
229 | under the terms of Sections 1 and 2 above provided that you accompany
230 | it with the complete corresponding machine-readable source code, which
231 | must be distributed under the terms of Sections 1 and 2 above on a
232 | medium customarily used for software interchange.
233 |
234 | If distribution of object code is made by offering access to copy
235 | from a designated place, then offering equivalent access to copy the
236 | source code from the same place satisfies the requirement to
237 | distribute the source code, even though third parties are not
238 | compelled to copy the source along with the object code.
239 |
240 | 5. A program that contains no derivative of any portion of the
241 | Library, but is designed to work with the Library by being compiled or
242 | linked with it, is called a "work that uses the Library". Such a
243 | work, in isolation, is not a derivative work of the Library, and
244 | therefore falls outside the scope of this License.
245 |
246 | However, linking a "work that uses the Library" with the Library
247 | creates an executable that is a derivative of the Library (because it
248 | contains portions of the Library), rather than a "work that uses the
249 | library". The executable is therefore covered by this License.
250 | Section 6 states terms for distribution of such executables.
251 |
252 | When a "work that uses the Library" uses material from a header file
253 | that is part of the Library, the object code for the work may be a
254 | derivative work of the Library even though the source code is not.
255 | Whether this is true is especially significant if the work can be
256 | linked without the Library, or if the work is itself a library. The
257 | threshold for this to be true is not precisely defined by law.
258 |
259 | If such an object file uses only numerical parameters, data
260 | structure layouts and accessors, and small macros and small inline
261 | functions (ten lines or less in length), then the use of the object
262 | file is unrestricted, regardless of whether it is legally a derivative
263 | work. (Executables containing this object code plus portions of the
264 | Library will still fall under Section 6.)
265 |
266 | Otherwise, if the work is a derivative of the Library, you may
267 | distribute the object code for the work under the terms of Section 6.
268 | Any executables containing that work also fall under Section 6,
269 | whether or not they are linked directly with the Library itself.
270 |
271 | 6. As an exception to the Sections above, you may also combine or
272 | link a "work that uses the Library" with the Library to produce a
273 | work containing portions of the Library, and distribute that work
274 | under terms of your choice, provided that the terms permit
275 | modification of the work for the customer's own use and reverse
276 | engineering for debugging such modifications.
277 |
278 | You must give prominent notice with each copy of the work that the
279 | Library is used in it and that the Library and its use are covered by
280 | this License. You must supply a copy of this License. If the work
281 | during execution displays copyright notices, you must include the
282 | copyright notice for the Library among them, as well as a reference
283 | directing the user to the copy of this License. Also, you must do one
284 | of these things:
285 |
286 | a) Accompany the work with the complete corresponding
287 | machine-readable source code for the Library including whatever
288 | changes were used in the work (which must be distributed under
289 | Sections 1 and 2 above); and, if the work is an executable linked
290 | with the Library, with the complete machine-readable "work that
291 | uses the Library", as object code and/or source code, so that the
292 | user can modify the Library and then relink to produce a modified
293 | executable containing the modified Library. (It is understood
294 | that the user who changes the contents of definitions files in the
295 | Library will not necessarily be able to recompile the application
296 | to use the modified definitions.)
297 |
298 | b) Use a suitable shared library mechanism for linking with the
299 | Library. A suitable mechanism is one that (1) uses at run time a
300 | copy of the library already present on the user's computer system,
301 | rather than copying library functions into the executable, and (2)
302 | will operate properly with a modified version of the library, if
303 | the user installs one, as long as the modified version is
304 | interface-compatible with the version that the work was made with.
305 |
306 | c) Accompany the work with a written offer, valid for at
307 | least three years, to give the same user the materials
308 | specified in Subsection 6a, above, for a charge no more
309 | than the cost of performing this distribution.
310 |
311 | d) If distribution of the work is made by offering access to copy
312 | from a designated place, offer equivalent access to copy the above
313 | specified materials from the same place.
314 |
315 | e) Verify that the user has already received a copy of these
316 | materials or that you have already sent this user a copy.
317 |
318 | For an executable, the required form of the "work that uses the
319 | Library" must include any data and utility programs needed for
320 | reproducing the executable from it. However, as a special exception,
321 | the materials to be distributed need not include anything that is
322 | normally distributed (in either source or binary form) with the major
323 | components (compiler, kernel, and so on) of the operating system on
324 | which the executable runs, unless that component itself accompanies
325 | the executable.
326 |
327 | It may happen that this requirement contradicts the license
328 | restrictions of other proprietary libraries that do not normally
329 | accompany the operating system. Such a contradiction means you cannot
330 | use both them and the Library together in an executable that you
331 | distribute.
332 |
333 | 7. You may place library facilities that are a work based on the
334 | Library side-by-side in a single library together with other library
335 | facilities not covered by this License, and distribute such a combined
336 | library, provided that the separate distribution of the work based on
337 | the Library and of the other library facilities is otherwise
338 | permitted, and provided that you do these two things:
339 |
340 | a) Accompany the combined library with a copy of the same work
341 | based on the Library, uncombined with any other library
342 | facilities. This must be distributed under the terms of the
343 | Sections above.
344 |
345 | b) Give prominent notice with the combined library of the fact
346 | that part of it is a work based on the Library, and explaining
347 | where to find the accompanying uncombined form of the same work.
348 |
349 | 8. You may not copy, modify, sublicense, link with, or distribute
350 | the Library except as expressly provided under this License. Any
351 | attempt otherwise to copy, modify, sublicense, link with, or
352 | distribute the Library is void, and will automatically terminate your
353 | rights under this License. However, parties who have received copies,
354 | or rights, from you under this License will not have their licenses
355 | terminated so long as such parties remain in full compliance.
356 |
357 | 9. You are not required to accept this License, since you have not
358 | signed it. However, nothing else grants you permission to modify or
359 | distribute the Library or its derivative works. These actions are
360 | prohibited by law if you do not accept this License. Therefore, by
361 | modifying or distributing the Library (or any work based on the
362 | Library), you indicate your acceptance of this License to do so, and
363 | all its terms and conditions for copying, distributing or modifying
364 | the Library or works based on it.
365 |
366 | 10. Each time you redistribute the Library (or any work based on the
367 | Library), the recipient automatically receives a license from the
368 | original licensor to copy, distribute, link with or modify the Library
369 | subject to these terms and conditions. You may not impose any further
370 | restrictions on the recipients' exercise of the rights granted herein.
371 | You are not responsible for enforcing compliance by third parties with
372 | this License.
373 |
374 | 11. If, as a consequence of a court judgment or allegation of patent
375 | infringement or for any other reason (not limited to patent issues),
376 | conditions are imposed on you (whether by court order, agreement or
377 | otherwise) that contradict the conditions of this License, they do not
378 | excuse you from the conditions of this License. If you cannot
379 | distribute so as to satisfy simultaneously your obligations under this
380 | License and any other pertinent obligations, then as a consequence you
381 | may not distribute the Library at all. For example, if a patent
382 | license would not permit royalty-free redistribution of the Library by
383 | all those who receive copies directly or indirectly through you, then
384 | the only way you could satisfy both it and this License would be to
385 | refrain entirely from distribution of the Library.
386 |
387 | If any portion of this section is held invalid or unenforceable under any
388 | particular circumstance, the balance of the section is intended to apply,
389 | and the section as a whole is intended to apply in other circumstances.
390 |
391 | It is not the purpose of this section to induce you to infringe any
392 | patents or other property right claims or to contest validity of any
393 | such claims; this section has the sole purpose of protecting the
394 | integrity of the free software distribution system which is
395 | implemented by public license practices. Many people have made
396 | generous contributions to the wide range of software distributed
397 | through that system in reliance on consistent application of that
398 | system; it is up to the author/donor to decide if he or she is willing
399 | to distribute software through any other system and a licensee cannot
400 | impose that choice.
401 |
402 | This section is intended to make thoroughly clear what is believed to
403 | be a consequence of the rest of this License.
404 |
405 | 12. If the distribution and/or use of the Library is restricted in
406 | certain countries either by patents or by copyrighted interfaces, the
407 | original copyright holder who places the Library under this License may add
408 | an explicit geographical distribution limitation excluding those countries,
409 | so that distribution is permitted only in or among countries not thus
410 | excluded. In such case, this License incorporates the limitation as if
411 | written in the body of this License.
412 |
413 | 13. The Free Software Foundation may publish revised and/or new
414 | versions of the Lesser General Public License from time to time.
415 | Such new versions will be similar in spirit to the present version,
416 | but may differ in detail to address new problems or concerns.
417 |
418 | Each version is given a distinguishing version number. If the Library
419 | specifies a version number of this License which applies to it and
420 | "any later version", you have the option of following the terms and
421 | conditions either of that version or of any later version published by
422 | the Free Software Foundation. If the Library does not specify a
423 | license version number, you may choose any version ever published by
424 | the Free Software Foundation.
425 |
426 | 14. If you wish to incorporate parts of the Library into other free
427 | programs whose distribution conditions are incompatible with these,
428 | write to the author to ask for permission. For software which is
429 | copyrighted by the Free Software Foundation, write to the Free
430 | Software Foundation; we sometimes make exceptions for this. Our
431 | decision will be guided by the two goals of preserving the free status
432 | of all derivatives of our free software and of promoting the sharing
433 | and reuse of software generally.
434 |
435 | NO WARRANTY
436 |
437 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
438 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
439 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
440 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
441 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
442 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
443 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
444 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
445 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
446 |
447 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
448 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
449 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
450 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
451 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
452 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
453 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
454 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
455 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
456 | DAMAGES.
457 |
458 | END OF TERMS AND CONDITIONS
459 |
460 | How to Apply These Terms to Your New Libraries
461 |
462 | If you develop a new library, and you want it to be of the greatest
463 | possible use to the public, we recommend making it free software that
464 | everyone can redistribute and change. You can do so by permitting
465 | redistribution under these terms (or, alternatively, under the terms of the
466 | ordinary General Public License).
467 |
468 | To apply these terms, attach the following notices to the library. It is
469 | safest to attach them to the start of each source file to most effectively
470 | convey the exclusion of warranty; and each file should have at least the
471 | "copyright" line and a pointer to where the full notice is found.
472 |
473 |
474 | Copyright (C)
475 |
476 | This library is free software; you can redistribute it and/or
477 | modify it under the terms of the GNU Lesser General Public
478 | License as published by the Free Software Foundation; either
479 | version 2.1 of the License, or (at your option) any later version.
480 |
481 | This library is distributed in the hope that it will be useful,
482 | but WITHOUT ANY WARRANTY; without even the implied warranty of
483 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
484 | Lesser General Public License for more details.
485 |
486 | You should have received a copy of the GNU Lesser General Public
487 | License along with this library; if not, write to the Free Software
488 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
489 | USA
490 |
491 | Also add information on how to contact you by electronic and paper mail.
492 |
493 | You should also get your employer (if you work as a programmer) or your
494 | school, if any, to sign a "copyright disclaimer" for the library, if
495 | necessary. Here is a sample; alter the names:
496 |
497 | Yoyodyne, Inc., hereby disclaims all copyright interest in the
498 | library `Frob' (a library for tweaking knobs) written by James Random
499 | Hacker.
500 |
501 | , 1 April 1990
502 | Ty Coon, President of Vice
503 |
504 | That's all there is to it!
505 |
--------------------------------------------------------------------------------
/MpcScriptSource.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.10.35122.118
5 | MinimumVisualStudioVersion = 15.0.27130.2036
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MpcScriptSource", "Source\MpcScriptSource.vcxproj", "{DAF59106-BC83-478F-95D9-4516C2A52970}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Include", "Include", "{C7CAE27C-03BC-45F2-BF8E-DEE05DBF37B8}"
9 | ProjectSection(SolutionItems) = preProject
10 | Include\avisynth.h = Include\avisynth.h
11 | Include\FilterInterfaces.h = Include\FilterInterfaces.h
12 | Include\FilterInterfacesImpl.h = Include\FilterInterfacesImpl.h
13 | Include\VapourSynth4.h = Include\VapourSynth4.h
14 | Include\Version.h = Include\Version.h
15 | Include\VSScript4.h = Include\VSScript4.h
16 | EndProjectSection
17 | EndProject
18 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "avs", "avs", "{5FDFFC8B-BC55-4214-BE2B-19331F617146}"
19 | ProjectSection(SolutionItems) = preProject
20 | Include\avs\capi.h = Include\avs\capi.h
21 | Include\avs\config.h = Include\avs\config.h
22 | Include\avs\cpuid.h = Include\avs\cpuid.h
23 | Include\avs\types.h = Include\avs\types.h
24 | EndProjectSection
25 | EndProject
26 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BaseClasses", "external\BaseClasses.vcxproj", "{E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}"
27 | EndProject
28 | Global
29 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
30 | Debug|x64 = Debug|x64
31 | Debug|x86 = Debug|x86
32 | Release|x64 = Release|x64
33 | Release|x86 = Release|x86
34 | EndGlobalSection
35 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
36 | {DAF59106-BC83-478F-95D9-4516C2A52970}.Debug|x64.ActiveCfg = Debug|x64
37 | {DAF59106-BC83-478F-95D9-4516C2A52970}.Debug|x64.Build.0 = Debug|x64
38 | {DAF59106-BC83-478F-95D9-4516C2A52970}.Debug|x86.ActiveCfg = Debug|Win32
39 | {DAF59106-BC83-478F-95D9-4516C2A52970}.Debug|x86.Build.0 = Debug|Win32
40 | {DAF59106-BC83-478F-95D9-4516C2A52970}.Release|x64.ActiveCfg = Release|x64
41 | {DAF59106-BC83-478F-95D9-4516C2A52970}.Release|x64.Build.0 = Release|x64
42 | {DAF59106-BC83-478F-95D9-4516C2A52970}.Release|x86.ActiveCfg = Release|Win32
43 | {DAF59106-BC83-478F-95D9-4516C2A52970}.Release|x86.Build.0 = Release|Win32
44 | {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug|x64.ActiveCfg = Debug|x64
45 | {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug|x64.Build.0 = Debug|x64
46 | {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug|x86.ActiveCfg = Debug|Win32
47 | {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug|x86.Build.0 = Debug|Win32
48 | {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release|x64.ActiveCfg = Release|x64
49 | {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release|x64.Build.0 = Release|x64
50 | {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release|x86.ActiveCfg = Release|Win32
51 | {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release|x86.Build.0 = Release|Win32
52 | EndGlobalSection
53 | GlobalSection(SolutionProperties) = preSolution
54 | HideSolutionNode = FALSE
55 | EndGlobalSection
56 | GlobalSection(NestedProjects) = preSolution
57 | {5FDFFC8B-BC55-4214-BE2B-19331F617146} = {C7CAE27C-03BC-45F2-BF8E-DEE05DBF37B8}
58 | EndGlobalSection
59 | GlobalSection(ExtensibilityGlobals) = postSolution
60 | SolutionGuid = {5D7781ED-53B1-4197-9C68-D2EDD94EC59B}
61 | EndGlobalSection
62 | EndGlobal
63 |
--------------------------------------------------------------------------------
/Readme.md:
--------------------------------------------------------------------------------
1 | # MPC Script Source
2 |
3 | MPC Script Source is a free and open-source DirectShow filter. The filter allows to open AviSynth+ and VapourSynth script files in video players.
4 |
5 | ## Minimum system requirements
6 |
7 | * An SSE2-capable CPU
8 | * Windows 7 or newer
9 |
10 | ## License
11 |
12 | MPC Script Source's code is licensed under [LGPL v2.1].
13 |
14 | ## Links
15 |
16 | Topic in MPC-BE forum (Russian) -
17 |
18 | MPC-BE video player -
19 |
20 | ## Donate
21 |
22 | ЮMoney - https://yoomoney.ru/to/4100115126389817
23 |
--------------------------------------------------------------------------------
/Source/AviSynthStream.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020-2024 v0lt
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-only
5 | */
6 |
7 | #include "stdafx.h"
8 | #include "VUIOptions.h"
9 | #include "ScriptSource.h"
10 |
11 | #include "AviSynthStream.h"
12 |
13 | #include
14 |
15 | const AVS_Linkage* AVS_linkage = NULL;
16 |
17 | //
18 | // CAviSynthFile
19 | //
20 |
21 | CAviSynthFile::CAviSynthFile(const WCHAR* name, CSource* pParent, HRESULT* phr)
22 | {
23 | try {
24 | m_hAviSynthDll = LoadLibraryW(L"Avisynth.dll");
25 | if (!m_hAviSynthDll) {
26 | throw std::exception("Failed to load AviSynth+");
27 | }
28 |
29 | IScriptEnvironment* (WINAPI* CreateScriptEnvironment)(int version) =
30 | (IScriptEnvironment * (WINAPI*)(int)) GetProcAddress(m_hAviSynthDll, "CreateScriptEnvironment");
31 |
32 | if (!CreateScriptEnvironment) {
33 | throw std::exception("Cannot resolve AviSynth+ CreateScriptEnvironment function");
34 | }
35 |
36 | m_ScriptEnvironment = CreateScriptEnvironment(6);
37 | if (!m_ScriptEnvironment) {
38 | throw std::exception("A newer AviSynth+ version is required");
39 | }
40 |
41 | AVS_linkage = m_Linkage = m_ScriptEnvironment->GetAVSLinkage();
42 | }
43 | catch ([[maybe_unused]] const std::exception& e) {
44 | DLog(A2WStr(e.what()));
45 | *phr = E_FAIL;
46 | return;
47 | }
48 |
49 | HRESULT hr;
50 | std::wstring error;
51 |
52 | try {
53 | std::string utf8file = ConvertWideToUtf8(name);
54 | AVSValue args[2] = { utf8file.c_str(), true };
55 | const char* const arg_names[2] = { 0, "utf8" };
56 | try {
57 | m_AVSValue = m_ScriptEnvironment->Invoke("Import", AVSValue(args, 2), arg_names);
58 | }
59 | catch (const AvisynthError& e) {
60 | error = ConvertUtf8ToWide(e.msg);
61 | throw std::exception("Failure to open Avisynth script file.");
62 | }
63 |
64 | if (!m_AVSValue.IsClip()) {
65 | throw std::exception("AviSynth+ script does not return a video clip");
66 | }
67 |
68 | auto Clip = m_AVSValue.AsClip();
69 | auto VInfo = Clip->GetVideoInfo();
70 |
71 | if (VInfo.HasVideo()) {
72 | auto& Format = GetFormatParamsAviSynth(VInfo.pixel_type);
73 | if (Format.fourcc == DWORD(-1)) {
74 | throw std::exception(std::format("Unsuported pixel_type {:#010x} ({})", (uint32_t)VInfo.pixel_type, VInfo.pixel_type).c_str());
75 | }
76 |
77 | auto pVideoStream = new CAviSynthVideoStream(this, pParent, &hr);
78 | if (FAILED(hr)) {
79 | pParent->RemovePin(pVideoStream);
80 | delete pVideoStream;
81 | throw std::exception("AviSynth+ script returned unsupported video");
82 | }
83 | else {
84 | m_FileInfo.append(pVideoStream->GetInfo());
85 | m_FileInfo += (L'\n');
86 | }
87 | }
88 |
89 | if (VInfo.HasAudio()) {
90 | auto pAudioStream = new CAviSynthAudioStream(this, pParent, &hr);
91 | if (FAILED(hr)) {
92 | DLog(L"AviSynth+ script returned unsupported audio");
93 | }
94 | else {
95 | m_FileInfo.append(pAudioStream->GetInfo());
96 | m_FileInfo += (L'\n');
97 | }
98 | }
99 |
100 | hr = S_OK;
101 | }
102 | catch ([[maybe_unused]] const std::exception& e) {
103 | DLog(L"{}\n{}", A2WStr(e.what()), error);
104 |
105 | new CAviSynthVideoStream(error, pParent, &hr);
106 | if (SUCCEEDED(hr)) {
107 | hr = S_FALSE;
108 | } else {
109 | hr = E_FAIL;
110 | }
111 | }
112 |
113 | *phr = hr;
114 | }
115 |
116 | CAviSynthFile::~CAviSynthFile()
117 | {
118 | AVS_linkage = m_Linkage;
119 |
120 | m_AVSValue = 0;
121 |
122 | if (m_ScriptEnvironment) {
123 | m_ScriptEnvironment->DeleteScriptEnvironment();
124 | m_ScriptEnvironment = nullptr;
125 | }
126 |
127 | AVS_linkage = nullptr;
128 | m_Linkage = nullptr;
129 |
130 | if (m_hAviSynthDll) {
131 | FreeLibrary(m_hAviSynthDll);
132 | }
133 | }
134 |
135 | //
136 | // CAviSynthVideoStream
137 | //
138 |
139 | CAviSynthVideoStream::CAviSynthVideoStream(CAviSynthFile* pAviSynthFile, CSource* pParent, HRESULT* phr)
140 | : CSourceStream(L"Video", phr, pParent, L"Video")
141 | , CSourceSeeking(L"Video", (IPin*)this, phr, &m_cSharedState)
142 | , m_pAviSynthFile(pAviSynthFile)
143 | {
144 | CAutoLock cAutoLock(&m_cSharedState);
145 |
146 | HRESULT hr;
147 | std::wstring error;
148 |
149 | try {
150 | auto Clip = m_pAviSynthFile->m_AVSValue.AsClip();
151 | auto VInfo = Clip->GetVideoInfo();
152 |
153 | m_Format = GetFormatParamsAviSynth(VInfo.pixel_type);
154 | if (m_Format.fourcc == DWORD(-1)) {
155 | throw std::exception(std::format("Unsuported pixel_type {:#010x} ({})", (uint32_t)VInfo.pixel_type, VInfo.pixel_type).c_str());
156 | }
157 |
158 | UINT bitdepth = VInfo.BitsPerPixel();
159 |
160 | auto VFrame = Clip->GetFrame(0, m_pAviSynthFile->m_ScriptEnvironment);
161 | m_Pitch = VFrame->GetPitch();
162 |
163 | m_Width = VInfo.width;
164 | m_Height = VInfo.height;
165 | m_PitchBuff = m_Pitch;
166 | m_BufferSize = m_PitchBuff * m_Height * m_Format.buffCoeff / 2;
167 |
168 | m_fpsNum = VInfo.fps_numerator;
169 | m_fpsDen = VInfo.fps_denominator;
170 | m_NumFrames = VInfo.num_frames;
171 | m_AvgTimePerFrame = UNITS * m_fpsDen / m_fpsNum; // no need any MulDiv here
172 | m_rtDuration = m_rtStop = llMulDiv(UNITS * m_NumFrames, m_fpsDen, m_fpsNum, 0);
173 |
174 | if (VInfo.IsPlanar()) {
175 | if (VInfo.IsYUV() || VInfo.IsYUVA()) {
176 | m_Planes[0] = PLANAR_Y;
177 | if (VInfo.IsYV12() || VInfo.IsYV16() || VInfo.IsYV24()) {
178 | m_Planes[1] = PLANAR_V;
179 | m_Planes[2] = PLANAR_U;
180 | } else {
181 | m_Planes[1] = PLANAR_U;
182 | m_Planes[2] = PLANAR_V;
183 | }
184 | }
185 | else if (VInfo.IsRGB()) {
186 | m_Planes[0] = PLANAR_G;
187 | m_Planes[1] = PLANAR_B;
188 | m_Planes[2] = PLANAR_R;
189 | }
190 | m_Planes[3] = PLANAR_A;
191 | }
192 |
193 | UINT color_info = 0;
194 |
195 | m_StreamInfo = std::format(
196 | L"Script type : AviSynth\n"
197 | L"Video stream: {} {}x{} {:.3f} fps",
198 | m_Format.str, m_Width, m_Height, (double)m_fpsNum/m_fpsDen
199 | );
200 |
201 | bool has_at_least_v9 = true;
202 | try {
203 | m_pAviSynthFile->m_ScriptEnvironment->CheckVersion(9);
204 | }
205 | catch (const AvisynthError&) {
206 | has_at_least_v9 = false;
207 | }
208 |
209 | if (has_at_least_v9) {
210 | auto& avsMap = VFrame->getConstProperties();
211 | int numKeys = m_pAviSynthFile->m_ScriptEnvironment->propNumKeys(&avsMap);
212 | if (numKeys > 0) {
213 | m_StreamInfo += std::format(L"\nProperties [{}]:", numKeys);
214 | }
215 |
216 | for (int i = 0; i < numKeys; i++) {
217 | const char* keyName = m_pAviSynthFile->m_ScriptEnvironment->propGetKey(&avsMap, i);
218 | if (keyName) {
219 | int64_t val_Int = 0;
220 | double val_Float = 0;
221 | const char* val_Data = 0;
222 | int err = 0;
223 | const char keyType = m_pAviSynthFile->m_ScriptEnvironment->propGetType(&avsMap, keyName);
224 |
225 | m_StreamInfo += std::format(L"\n{:>2}: <{}> '{}'", i, keyType, A2WStr(keyName));
226 |
227 | switch (keyType) {
228 | case PROPTYPE_INT:
229 | val_Int = m_pAviSynthFile->m_ScriptEnvironment->propGetInt(&avsMap, keyName, 0, &err);
230 | if (!err) {
231 | m_StreamInfo += std::format(L" = {}", val_Int);
232 | if (strcmp(keyName, "_SARNum") == 0) {
233 | m_Sar.num = val_Int;
234 | }
235 | else if (strcmp(keyName, "_SARDen") == 0) {
236 | m_Sar.den = val_Int;
237 | }
238 | else {
239 | SetColorInfoFromFrameFrops(color_info, keyName, val_Int);
240 | }
241 | }
242 | break;
243 | case PROPTYPE_FLOAT:
244 | val_Float = m_pAviSynthFile->m_ScriptEnvironment->propGetFloat(&avsMap, keyName, 0, &err);
245 | if (!err) {
246 | m_StreamInfo += std::format(L" = {:.3f}", val_Float);
247 | }
248 | break;
249 | case PROPTYPE_DATA:
250 | val_Data = m_pAviSynthFile->m_ScriptEnvironment->propGetData(&avsMap, keyName, 0, &err);
251 | if (!err) {
252 | const int dataSize = m_pAviSynthFile->m_ScriptEnvironment->propGetDataSize(&avsMap, keyName, 0, &err);
253 | if (!err) {
254 | if (dataSize == 1 && strcmp(keyName, "_PictType") == 0) {
255 | m_StreamInfo += std::format(L" = {}", val_Data[0]);
256 | } else {
257 | m_StreamInfo += std::format(L", {} bytes", dataSize);
258 | }
259 | }
260 | }
261 | break;
262 | }
263 | }
264 | }
265 | }
266 |
267 | if (color_info) {
268 | m_ColorInfo = color_info | (AMCONTROL_USED | AMCONTROL_COLORINFO_PRESENT);
269 | }
270 |
271 | InitVideoMediaType();
272 |
273 | DLog(m_StreamInfo);
274 |
275 | hr = S_OK;
276 | }
277 | catch ([[maybe_unused]] const std::exception& e) {
278 | DLog(L"{}\n{}", A2WStr(e.what()), error);
279 |
280 | hr = E_FAIL;
281 | }
282 |
283 | *phr = hr;
284 | }
285 |
286 | CAviSynthVideoStream::CAviSynthVideoStream(std::wstring_view error_str, CSource* pParent, HRESULT* phr)
287 | : CSourceStream(L"Video", phr, pParent, L"Video")
288 | , CSourceSeeking(L"Video", (IPin*)this, phr, &m_cSharedState)
289 | , m_pAviSynthFile(nullptr)
290 | {
291 | m_Format = GetFormatParamsAviSynth(VideoInfo::CS_BGR32);
292 |
293 | m_Width = 640;
294 | m_Height = 360;
295 | m_Pitch = m_Width * 4;
296 | m_PitchBuff = m_Pitch;
297 | m_BufferSize = m_PitchBuff * m_Height * m_Format.buffCoeff / 2;
298 | m_Sar = {};
299 |
300 | m_fpsNum = 1;
301 | m_fpsDen = 1;
302 | m_NumFrames = 10;
303 | m_AvgTimePerFrame = UNITS;
304 | m_rtDuration = m_rtStop = UNITS * m_NumFrames;
305 |
306 | std::wstring str(error_str);
307 | m_BitmapError = GetBitmapWithText(str, m_Width, m_Height);
308 |
309 | if (m_BitmapError) {
310 | *phr = S_FALSE;
311 | InitVideoMediaType();
312 | } else {
313 | *phr = E_FAIL;
314 | }
315 | }
316 |
317 | CAviSynthVideoStream::~CAviSynthVideoStream()
318 | {
319 | }
320 |
321 | STDMETHODIMP CAviSynthVideoStream::NonDelegatingQueryInterface(REFIID riid, void** ppv)
322 | {
323 | CheckPointer(ppv, E_POINTER);
324 |
325 | return (riid == IID_IMediaSeeking) ? CSourceSeeking::NonDelegatingQueryInterface(riid, ppv)
326 | : CSourceStream::NonDelegatingQueryInterface(riid, ppv);
327 | }
328 |
329 | HRESULT CAviSynthVideoStream::OnThreadCreate()
330 | {
331 | CAutoLock cAutoLockShared(&m_cSharedState);
332 |
333 | m_FrameCounter = 0;
334 | m_CurrentFrame = (int)llMulDiv(m_rtStart, m_fpsNum, m_fpsDen * UNITS, 0); // round down
335 |
336 | return CSourceStream::OnThreadCreate();
337 | }
338 |
339 | HRESULT CAviSynthVideoStream::OnThreadStartPlay()
340 | {
341 | m_bDiscontinuity = TRUE;
342 | return DeliverNewSegment(m_rtStart, m_rtStop, m_dRateSeeking);
343 | }
344 |
345 | void CAviSynthVideoStream::UpdateFromSeek()
346 | {
347 | if (ThreadExists()) {
348 | // next time around the loop, the worker thread will
349 | // pick up the position change.
350 | // We need to flush all the existing data - we must do that here
351 | // as our thread will probably be blocked in GetBuffer otherwise
352 |
353 | m_bFlushing = TRUE;
354 |
355 | DeliverBeginFlush();
356 | // make sure we have stopped pushing
357 | Stop();
358 | // complete the flush
359 | DeliverEndFlush();
360 |
361 | m_bFlushing = FALSE;
362 |
363 | // restart
364 | Run();
365 | }
366 | }
367 |
368 | HRESULT CAviSynthVideoStream::SetRate(double dRate)
369 | {
370 | if (dRate <= 0) {
371 | return E_INVALIDARG;
372 | }
373 |
374 | {
375 | CAutoLock lock(CSourceSeeking::m_pLock);
376 | m_dRateSeeking = dRate;
377 | }
378 |
379 | UpdateFromSeek();
380 |
381 | return S_OK;
382 | }
383 |
384 | HRESULT CAviSynthVideoStream::ChangeStart()
385 | {
386 | {
387 | CAutoLock lock(CSourceSeeking::m_pLock);
388 | m_FrameCounter = 0;
389 | m_CurrentFrame = (int)llMulDiv(m_rtStart, m_fpsNum, m_fpsDen * UNITS, 0); // round down
390 | }
391 |
392 | UpdateFromSeek();
393 |
394 | return S_OK;
395 | }
396 |
397 | HRESULT CAviSynthVideoStream::ChangeStop()
398 | {
399 | {
400 | CAutoLock lock(CSourceSeeking::m_pLock);
401 | if (m_CurrentFrame < m_NumFrames) {
402 | return S_OK;
403 | }
404 | }
405 |
406 | // We're already past the new stop time -- better flush the graph.
407 | UpdateFromSeek();
408 |
409 | return S_OK;
410 | }
411 |
412 | void CAviSynthVideoStream::InitVideoMediaType()
413 | {
414 | m_mt.InitMediaType();
415 | m_mt.SetType(&MEDIATYPE_Video);
416 | m_mt.SetSubtype(&m_Format.subtype);
417 | m_mt.SetFormatType(&FORMAT_VideoInfo2);
418 | m_mt.SetTemporalCompression(FALSE);
419 | m_mt.SetSampleSize(m_BufferSize);
420 |
421 | VIDEOINFOHEADER2* vih2 = (VIDEOINFOHEADER2*)m_mt.AllocFormatBuffer(sizeof(VIDEOINFOHEADER2));
422 | ZeroMemory(vih2, sizeof(VIDEOINFOHEADER2));
423 | vih2->rcSource = { 0, 0, (long)m_Width, (long)m_Height };
424 | vih2->rcTarget = vih2->rcSource;
425 | vih2->AvgTimePerFrame = m_AvgTimePerFrame;
426 | vih2->bmiHeader.biSize = sizeof(vih2->bmiHeader);
427 | vih2->bmiHeader.biWidth = m_PitchBuff / m_Format.Packsize;
428 | vih2->bmiHeader.biHeight = (m_Format.fourcc == BI_RGB) ? -(long)m_Height : m_Height;
429 | vih2->bmiHeader.biPlanes = 1;
430 | vih2->bmiHeader.biBitCount = m_Format.bitCount;
431 | vih2->bmiHeader.biCompression = m_Format.fourcc;
432 | vih2->bmiHeader.biSizeImage = m_BufferSize;
433 |
434 | vih2->dwControlFlags = m_ColorInfo;
435 |
436 | if (m_Sar.num > 0 && m_Sar.den > 0 && m_Sar.num < INT16_MAX && m_Sar.den < INT16_MAX) {
437 | auto parX = m_Sar.num * m_Width;
438 | auto parY = m_Sar.den * m_Height;
439 | const auto gcd = std::gcd(parX, parY);
440 | parX /= gcd;
441 | parY /= gcd;
442 | vih2->dwPictAspectRatioX = parX;
443 | vih2->dwPictAspectRatioY = parY;
444 | }
445 | }
446 |
447 | HRESULT CAviSynthVideoStream::DecideBufferSize(IMemAllocator* pAlloc, ALLOCATOR_PROPERTIES* pProperties)
448 | {
449 | //CAutoLock cAutoLock(m_pFilter->pStateLock());
450 |
451 | ASSERT(pAlloc);
452 | ASSERT(pProperties);
453 |
454 | HRESULT hr = NOERROR;
455 |
456 | pProperties->cBuffers = 1;
457 | pProperties->cbBuffer = m_BufferSize;
458 |
459 | ALLOCATOR_PROPERTIES Actual;
460 | if (FAILED(hr = pAlloc->SetProperties(pProperties, &Actual))) {
461 | return hr;
462 | }
463 |
464 | if (Actual.cbBuffer < pProperties->cbBuffer) {
465 | return E_FAIL;
466 | }
467 | ASSERT(Actual.cBuffers == pProperties->cBuffers);
468 |
469 | return NOERROR;
470 | }
471 |
472 | HRESULT CAviSynthVideoStream::FillBuffer(IMediaSample* pSample)
473 | {
474 | {
475 | CAutoLock cAutoLockShared(&m_cSharedState);
476 |
477 | if (m_CurrentFrame >= m_NumFrames) {
478 | return S_FALSE;
479 | }
480 |
481 | AM_MEDIA_TYPE* pmt;
482 | if (SUCCEEDED(pSample->GetMediaType(&pmt)) && pmt) {
483 | CMediaType mt(*pmt);
484 | SetMediaType(&mt);
485 | DeleteMediaType(pmt);
486 | }
487 |
488 | if (m_mt.formattype != FORMAT_VideoInfo2) {
489 | return S_FALSE;
490 | }
491 |
492 | BYTE* dst_data = nullptr;
493 | HRESULT hr = pSample->GetPointer(&dst_data);
494 | if (FAILED(hr) || !dst_data) {
495 | return S_FALSE;
496 | }
497 |
498 | long buffSize = pSample->GetSize();
499 | if (buffSize < (long)m_BufferSize) {
500 | return S_FALSE;
501 | }
502 |
503 | UINT DataLength = 0;
504 |
505 | if (m_BitmapError) {
506 | DataLength = m_PitchBuff * m_Height;
507 |
508 | const BYTE* src_data = m_BitmapError.get();
509 | if (m_Pitch == m_PitchBuff) {
510 | memcpy(dst_data, src_data, DataLength);
511 | }
512 | else {
513 | UINT linesize = std::min(m_Pitch, m_PitchBuff);
514 | for (UINT y = 0; y < m_Height; y++) {
515 | memcpy(dst_data, src_data, linesize);
516 | src_data += m_Pitch;
517 | dst_data += m_PitchBuff;
518 | }
519 | }
520 | }
521 | else {
522 | auto Clip = m_pAviSynthFile->m_AVSValue.AsClip();
523 | auto VFrame = Clip->GetFrame(m_CurrentFrame, m_pAviSynthFile->m_ScriptEnvironment);
524 |
525 | const int num_planes = m_Format.planes;
526 | for (int i = 0; i < num_planes; i++) {
527 | const int plane = m_Planes[i];
528 | const BYTE* src_data = VFrame->GetReadPtr(plane);
529 | int src_pitch = VFrame->GetPitch(plane);
530 | const UINT height = VFrame->GetHeight(plane);
531 | UINT dst_pitch = m_PitchBuff;
532 | if (i > 0 && (m_Format.ASformat&VideoInfo::CS_Sub_Width_Mask) == VideoInfo::CS_Sub_Width_2) {
533 | dst_pitch /= 2;
534 | }
535 |
536 | if (m_Format.fourcc == BI_RGB) {
537 | src_data += src_pitch * (height - 1);
538 | src_pitch = -src_pitch;
539 | }
540 |
541 | if (src_pitch == dst_pitch) {
542 | memcpy(dst_data, src_data, dst_pitch * height);
543 | dst_data += dst_pitch * height;
544 | }
545 | else {
546 | UINT linesize = std::min((UINT)abs(src_pitch), dst_pitch);
547 | for (UINT y = 0; y < height; y++) {
548 | memcpy(dst_data, src_data, linesize);
549 | src_data += src_pitch;
550 | dst_data += dst_pitch;
551 | }
552 | }
553 | DataLength += dst_pitch * height;
554 | }
555 | }
556 |
557 | pSample->SetActualDataLength(DataLength);
558 |
559 | // Sample time
560 | REFERENCE_TIME rtStart = llMulDiv(UNITS * m_FrameCounter, m_fpsDen, m_fpsNum, 0);
561 | REFERENCE_TIME rtStop = llMulDiv(UNITS * (m_FrameCounter+1), m_fpsDen, m_fpsNum, 0);
562 | // The sample times are modified by the current rate.
563 | if (m_dRateSeeking != 1.0) {
564 | rtStart = static_cast(rtStart / m_dRateSeeking);
565 | rtStop = static_cast(rtStop / m_dRateSeeking);
566 | }
567 | pSample->SetTime(&rtStart, &rtStop);
568 |
569 | m_FrameCounter++;
570 | m_CurrentFrame++;
571 | }
572 |
573 | pSample->SetSyncPoint(TRUE);
574 |
575 | if (m_bDiscontinuity) {
576 | pSample->SetDiscontinuity(TRUE);
577 | m_bDiscontinuity = FALSE;
578 | }
579 |
580 | return S_OK;
581 | }
582 |
583 | HRESULT CAviSynthVideoStream::CheckMediaType(const CMediaType* pmt)
584 | {
585 | if (pmt->majortype == MEDIATYPE_Video
586 | && pmt->subtype == m_Format.subtype
587 | && pmt->formattype == FORMAT_VideoInfo2) {
588 |
589 | VIDEOINFOHEADER2* vih2 = (VIDEOINFOHEADER2*)pmt->Format();
590 | if (vih2->bmiHeader.biWidth >= (long)m_Width && abs(vih2->bmiHeader.biHeight) == (long)m_Height) {
591 | return S_OK;
592 | }
593 | }
594 |
595 | return E_INVALIDARG;
596 | }
597 |
598 | HRESULT CAviSynthVideoStream::SetMediaType(const CMediaType* pMediaType)
599 | {
600 | HRESULT hr = __super::SetMediaType(pMediaType);
601 |
602 | if (SUCCEEDED(hr)) {
603 | VIDEOINFOHEADER2* vih2 = (VIDEOINFOHEADER2*)pMediaType->Format();
604 | m_PitchBuff = m_Format.Packsize * vih2->bmiHeader.biWidth;
605 | ASSERT(m_PitchBuff >= m_Pitch);
606 | m_BufferSize = m_PitchBuff * abs(vih2->bmiHeader.biHeight) * m_Format.buffCoeff / 2;
607 |
608 | DLog(L"SetMediaType with subtype {}", GUIDtoWString(m_mt.subtype));
609 | }
610 |
611 | return hr;
612 | }
613 |
614 | HRESULT CAviSynthVideoStream::GetMediaType(int iPosition, CMediaType* pmt)
615 | {
616 | CAutoLock cAutoLock(m_pFilter->pStateLock());
617 |
618 | if (iPosition < 0) {
619 | return E_INVALIDARG;
620 | }
621 | if (iPosition >= 1) {
622 | return VFW_S_NO_MORE_ITEMS;
623 | }
624 |
625 | *pmt = m_mt;
626 |
627 | return S_OK;
628 | }
629 |
630 | //
631 | // CAviSynthAudioStream
632 | //
633 |
634 | CAviSynthAudioStream::CAviSynthAudioStream(CAviSynthFile* pAviSynthFile, CSource* pParent, HRESULT* phr)
635 | : CSourceStream(L"Audio", phr, pParent, L"Audio")
636 | , CSourceSeeking(L"Audio", (IPin*)this, phr, &m_cSharedState)
637 | , m_pAviSynthFile(pAviSynthFile)
638 | {
639 | CAutoLock cAutoLock(&m_cSharedState);
640 |
641 | HRESULT hr;
642 | std::wstring error;
643 |
644 | try {
645 | auto Clip = m_pAviSynthFile->m_AVSValue.AsClip();
646 | auto VInfo = Clip->GetVideoInfo();
647 |
648 | if (VInfo.HasAudio()) {
649 | m_Channels = VInfo.AudioChannels();
650 | m_SampleRate = VInfo.SamplesPerSecond();
651 | m_BytesPerSample = VInfo.BytesPerAudioSample();
652 | m_BitDepth = m_BytesPerSample * 8 / m_Channels;
653 | m_SampleType = (AvsSampleType)VInfo.SampleType();
654 | m_NumSamples = VInfo.num_audio_samples;
655 |
656 | WORD wFormatTag;
657 | if (m_SampleType == SAMPLE_FLOAT) {
658 | wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
659 | m_Subtype = MEDIASUBTYPE_IEEE_FLOAT;
660 | } else {
661 | wFormatTag = WAVE_FORMAT_PCM;
662 | m_Subtype = MEDIASUBTYPE_PCM;
663 | }
664 |
665 | m_BufferSamples = m_SampleRate / 5; // 5 for 200 ms; 20 for 50 ms
666 |
667 | m_rtDuration = m_rtStop = llMulDiv(m_NumSamples, UNITS, m_SampleRate, 0);
668 |
669 | m_mt.InitMediaType();
670 | m_mt.SetType(&MEDIATYPE_Audio);
671 | m_mt.SetSubtype(&m_Subtype);
672 | m_mt.SetFormatType(&FORMAT_WaveFormatEx);
673 | m_mt.SetTemporalCompression(FALSE);
674 | m_mt.SetSampleSize(m_BytesPerSample);
675 |
676 | bool has_at_least_v10 = true;
677 | try {
678 | m_pAviSynthFile->m_ScriptEnvironment->CheckVersion(10);
679 | }
680 | catch (const AvisynthError&) {
681 | has_at_least_v10 = false;
682 | }
683 |
684 | UINT channelLayout = has_at_least_v10 ? VInfo.GetChannelMask() : 0;
685 |
686 | if (channelLayout) {
687 | WAVEFORMATEXTENSIBLE* wfex = (WAVEFORMATEXTENSIBLE*)m_mt.AllocFormatBuffer(sizeof(WAVEFORMATEXTENSIBLE));
688 | wfex->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
689 | wfex->Format.nChannels = m_Channels;
690 | wfex->Format.nSamplesPerSec = m_SampleRate;
691 | wfex->Format.nAvgBytesPerSec = m_BytesPerSample * m_SampleRate;
692 | wfex->Format.nBlockAlign = m_BytesPerSample;
693 | wfex->Format.wBitsPerSample = m_BitDepth;
694 | wfex->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX); // 22
695 | wfex->Samples.wValidBitsPerSample = m_BitDepth;
696 | wfex->dwChannelMask = channelLayout;
697 | wfex->SubFormat = m_Subtype;
698 | }
699 | else {
700 | WAVEFORMATEX* wfe = (WAVEFORMATEX*)m_mt.AllocFormatBuffer(sizeof(WAVEFORMATEX));
701 | wfe->wFormatTag = wFormatTag;
702 | wfe->nChannels = m_Channels;
703 | wfe->nSamplesPerSec = m_SampleRate;
704 | wfe->nAvgBytesPerSec = m_BytesPerSample * m_SampleRate;
705 | wfe->nBlockAlign = m_BytesPerSample;
706 | wfe->wBitsPerSample = m_BitDepth;
707 | wfe->cbSize = 0;
708 | }
709 |
710 | m_StreamInfo = std::format(L"Audio stream: {} channels, {} Hz, ", m_Channels, m_SampleRate);
711 | switch (m_SampleType) {
712 | case SAMPLE_INT8: m_StreamInfo.append(L"int8"); break;
713 | case SAMPLE_INT16: m_StreamInfo.append(L"int16"); break;
714 | case SAMPLE_INT24: m_StreamInfo.append(L"int24"); break;
715 | case SAMPLE_INT32: m_StreamInfo.append(L"int32"); break;
716 | case SAMPLE_FLOAT: m_StreamInfo.append(L"float32"); break;
717 | }
718 | DLog(m_StreamInfo);
719 |
720 | hr = S_OK;
721 | }
722 | }
723 | catch ([[maybe_unused]] const std::exception& e) {
724 | DLog(L"{}\n{}", A2WStr(e.what()), error);
725 |
726 | hr = E_FAIL;
727 | }
728 |
729 | *phr = hr;
730 | }
731 |
732 | CAviSynthAudioStream::~CAviSynthAudioStream()
733 | {
734 | }
735 |
736 | STDMETHODIMP CAviSynthAudioStream::NonDelegatingQueryInterface(REFIID riid, void** ppv)
737 | {
738 | CheckPointer(ppv, E_POINTER);
739 |
740 | return (riid == IID_IMediaSeeking) ? CSourceSeeking::NonDelegatingQueryInterface(riid, ppv)
741 | : CSourceStream::NonDelegatingQueryInterface(riid, ppv);
742 | }
743 |
744 | HRESULT CAviSynthAudioStream::OnThreadCreate()
745 | {
746 | CAutoLock cAutoLockShared(&m_cSharedState);
747 |
748 | m_SampleCounter = 0;
749 | m_CurrentSample = (int)llMulDiv(m_rtStart, m_SampleRate, UNITS, 0); // round down
750 |
751 | return CSourceStream::OnThreadCreate();
752 | }
753 |
754 | HRESULT CAviSynthAudioStream::OnThreadStartPlay()
755 | {
756 | m_bDiscontinuity = TRUE;
757 | return DeliverNewSegment(m_rtStart, m_rtStop, m_dRateSeeking);
758 | }
759 |
760 | void CAviSynthAudioStream::UpdateFromSeek()
761 | {
762 | if (ThreadExists()) {
763 | // next time around the loop, the worker thread will
764 | // pick up the position change.
765 | // We need to flush all the existing data - we must do that here
766 | // as our thread will probably be blocked in GetBuffer otherwise
767 |
768 | m_bFlushing = TRUE;
769 |
770 | DeliverBeginFlush();
771 | // make sure we have stopped pushing
772 | Stop();
773 | // complete the flush
774 | DeliverEndFlush();
775 |
776 | m_bFlushing = FALSE;
777 |
778 | // restart
779 | Run();
780 | }
781 | }
782 |
783 | HRESULT CAviSynthAudioStream::SetRate(double dRate)
784 | {
785 | if (dRate <= 0) {
786 | return E_INVALIDARG;
787 | }
788 |
789 | {
790 | CAutoLock lock(CSourceSeeking::m_pLock);
791 | m_dRateSeeking = dRate;
792 | }
793 |
794 | UpdateFromSeek();
795 |
796 | return S_OK;
797 | }
798 |
799 | HRESULT CAviSynthAudioStream::ChangeStart()
800 | {
801 | {
802 | CAutoLock lock(CSourceSeeking::m_pLock);
803 | m_SampleCounter = 0;
804 | m_CurrentSample = (int)llMulDiv(m_rtStart, m_SampleRate, UNITS, 0); // round down
805 | }
806 |
807 | UpdateFromSeek();
808 |
809 | return S_OK;
810 | }
811 |
812 | HRESULT CAviSynthAudioStream::ChangeStop()
813 | {
814 | {
815 | CAutoLock lock(CSourceSeeking::m_pLock);
816 | if (m_CurrentSample < m_NumSamples) {
817 | return S_OK;
818 | }
819 | }
820 |
821 | // We're already past the new stop time -- better flush the graph.
822 | UpdateFromSeek();
823 |
824 | return S_OK;
825 | }
826 |
827 | HRESULT CAviSynthAudioStream::DecideBufferSize(IMemAllocator* pAlloc, ALLOCATOR_PROPERTIES* pProperties)
828 | {
829 | //CAutoLock cAutoLock(m_pFilter->pStateLock());
830 |
831 | ASSERT(pAlloc);
832 | ASSERT(pProperties);
833 |
834 | HRESULT hr = NOERROR;
835 |
836 | pProperties->cBuffers = 1;
837 | pProperties->cbBuffer = m_BufferSamples * m_BytesPerSample;
838 |
839 | ALLOCATOR_PROPERTIES Actual;
840 | if (FAILED(hr = pAlloc->SetProperties(pProperties, &Actual))) {
841 | return hr;
842 | }
843 |
844 | if (Actual.cbBuffer < pProperties->cbBuffer) {
845 | return E_FAIL;
846 | }
847 | ASSERT(Actual.cBuffers == pProperties->cBuffers);
848 |
849 | return NOERROR;
850 | }
851 |
852 | HRESULT CAviSynthAudioStream::FillBuffer(IMediaSample* pSample)
853 | {
854 | {
855 | CAutoLock cAutoLockShared(&m_cSharedState);
856 |
857 | if (m_CurrentSample >= m_NumSamples) {
858 | return S_FALSE;
859 | }
860 |
861 | AM_MEDIA_TYPE* pmt;
862 | if (SUCCEEDED(pSample->GetMediaType(&pmt)) && pmt) {
863 | CMediaType mt(*pmt);
864 | SetMediaType(&mt);
865 | DeleteMediaType(pmt);
866 | }
867 |
868 | if (m_mt.formattype != FORMAT_WaveFormatEx) {
869 | return S_FALSE;
870 | }
871 |
872 | BYTE* dst_data = nullptr;
873 | HRESULT hr = pSample->GetPointer(&dst_data);
874 | if (FAILED(hr) || !dst_data) {
875 | return S_FALSE;
876 | }
877 |
878 | long buffSize = pSample->GetSize();
879 | if (buffSize < (long)(m_BufferSamples * m_BytesPerSample)) {
880 | return S_FALSE;
881 | }
882 |
883 | auto Clip = m_pAviSynthFile->m_AVSValue.AsClip();
884 | int64_t count = std::min(m_BufferSamples, m_NumSamples - m_CurrentSample);
885 | Clip->GetAudio(dst_data, m_CurrentSample, count, m_pAviSynthFile->m_ScriptEnvironment);
886 |
887 | pSample->SetActualDataLength(count * m_BytesPerSample);
888 |
889 | // Sample time
890 | REFERENCE_TIME rtStart = llMulDiv(m_SampleCounter, UNITS, m_SampleRate, 0);
891 | REFERENCE_TIME rtStop = llMulDiv(m_SampleCounter + count, UNITS, m_SampleRate, 0);
892 | // The sample times are modified by the current rate.
893 | if (m_dRateSeeking != 1.0) {
894 | rtStart = static_cast(rtStart / m_dRateSeeking);
895 | rtStop = static_cast(rtStop / m_dRateSeeking);
896 | }
897 | pSample->SetTime(&rtStart, &rtStop);
898 |
899 | m_SampleCounter += count;
900 | m_CurrentSample += count;
901 | }
902 |
903 | pSample->SetSyncPoint(TRUE);
904 |
905 | if (m_bDiscontinuity) {
906 | pSample->SetDiscontinuity(TRUE);
907 | m_bDiscontinuity = FALSE;
908 | }
909 |
910 | return S_OK;
911 | }
912 |
913 | HRESULT CAviSynthAudioStream::CheckMediaType(const CMediaType* pmt)
914 | {
915 | if (pmt->majortype == MEDIATYPE_Audio
916 | && pmt->subtype == m_Subtype
917 | && pmt->formattype == FORMAT_WaveFormatEx) {
918 |
919 | WAVEFORMATEX* wfe = (WAVEFORMATEX*)pmt->Format();
920 | if ((int)wfe->nChannels >= m_Channels
921 | && (int)wfe->nSamplesPerSec == m_SampleRate
922 | && (int)wfe->nBlockAlign == m_BytesPerSample
923 | && (int)wfe->wBitsPerSample == m_BitDepth) {
924 | return S_OK;
925 | }
926 | }
927 |
928 | return E_INVALIDARG;
929 | }
930 |
931 | HRESULT CAviSynthAudioStream::SetMediaType(const CMediaType* pMediaType)
932 | {
933 | HRESULT hr = __super::SetMediaType(pMediaType);
934 |
935 | if (SUCCEEDED(hr)) {
936 | DLog(L"SetMediaType with subtype {}", GUIDtoWString(m_mt.subtype));
937 | }
938 |
939 | return hr;
940 | }
941 |
942 | HRESULT CAviSynthAudioStream::GetMediaType(int iPosition, CMediaType* pmt)
943 | {
944 | CAutoLock cAutoLock(m_pFilter->pStateLock());
945 |
946 | if (iPosition < 0) {
947 | return E_INVALIDARG;
948 | }
949 | if (iPosition >= 1) {
950 | return VFW_S_NO_MORE_ITEMS;
951 | }
952 |
953 | *pmt = m_mt;
954 |
955 | return S_OK;
956 | }
957 |
--------------------------------------------------------------------------------
/Source/AviSynthStream.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020-2024 v0lt
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-only
5 | */
6 |
7 | #pragma once
8 |
9 | #ifndef __AVISYNTH_7_H__
10 | #include "../Include/avisynth.h"
11 | #endif
12 | #include "Helper.h"
13 |
14 | //
15 | // CAviSynthFile
16 | //
17 |
18 | class CAviSynthFile
19 | {
20 | friend class CAviSynthVideoStream;
21 | friend class CAviSynthAudioStream;
22 |
23 | HMODULE m_hAviSynthDll = nullptr;
24 |
25 | IScriptEnvironment* m_ScriptEnvironment = nullptr;
26 | AVSValue m_AVSValue;
27 | const AVS_Linkage* m_Linkage = nullptr;
28 |
29 | std::wstring m_FileInfo;
30 |
31 | public:
32 | CAviSynthFile(const WCHAR* filepath, CSource* pParent, HRESULT* phr);
33 | ~CAviSynthFile();
34 |
35 | std::wstring_view GetInfo() { return m_FileInfo; }
36 | };
37 |
38 | //
39 | // CAviSynthVideoStream
40 | //
41 |
42 | class CAviSynthVideoStream
43 | : public CSourceStream
44 | , public CSourceSeeking
45 | {
46 | private:
47 | CCritSec m_cSharedState;
48 |
49 | const CAviSynthFile* m_pAviSynthFile;
50 |
51 | BOOL m_bDiscontinuity = FALSE;
52 | BOOL m_bFlushing = FALSE;
53 |
54 | PVideoFrame m_Frame;
55 | int m_Planes[4] = {};
56 |
57 | std::unique_ptr m_BitmapError;
58 |
59 | REFERENCE_TIME m_AvgTimePerFrame = 0;
60 | int m_FrameCounter = 0;
61 | int m_CurrentFrame = 0;
62 |
63 | FmtParams_t m_Format = {};
64 | UINT m_Width = 0;
65 | UINT m_Height = 0;
66 | UINT m_Pitch = 0;
67 | UINT m_PitchBuff = 0;
68 | UINT m_BufferSize = 0;
69 |
70 | UINT m_ColorInfo = 0;
71 | struct {
72 | int64_t num = 0;
73 | int64_t den = 0;
74 | } m_Sar;
75 |
76 | int m_NumFrames = 0;
77 | unsigned m_fpsNum = 1;
78 | unsigned m_fpsDen = 1;
79 |
80 | std::wstring m_StreamInfo;
81 |
82 | public:
83 | CAviSynthVideoStream(CAviSynthFile* pAviSynthFile, CSource* pParent, HRESULT* phr);
84 | CAviSynthVideoStream(std::wstring_view error_str, CSource* pParent, HRESULT* phr);
85 | virtual ~CAviSynthVideoStream();
86 |
87 | STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv) override;
88 |
89 | std::wstring_view GetInfo() { return m_StreamInfo; }
90 |
91 | private:
92 | HRESULT OnThreadCreate() override;
93 | HRESULT OnThreadStartPlay() override;
94 |
95 | void UpdateFromSeek();
96 |
97 | // IMediaSeeking
98 | STDMETHODIMP SetRate(double dRate) override;
99 |
100 | HRESULT ChangeStart() override;
101 | HRESULT ChangeStop() override;
102 | HRESULT ChangeRate() override { return S_OK; }
103 |
104 | void InitVideoMediaType();
105 |
106 | public:
107 | HRESULT DecideBufferSize(IMemAllocator* pIMemAlloc, ALLOCATOR_PROPERTIES* pProperties) override;
108 | HRESULT FillBuffer(IMediaSample* pSample) override;
109 | HRESULT CheckMediaType(const CMediaType* pMediaType) override;
110 | HRESULT SetMediaType(const CMediaType* pMediaType) override;
111 | HRESULT GetMediaType(int iPosition, CMediaType* pmt) override;
112 |
113 | // IQualityControl
114 | STDMETHODIMP Notify(IBaseFilter* pSender, Quality q) override { return E_NOTIMPL; }
115 | };
116 |
117 | //
118 | // CAviSynthAudioStream
119 | //
120 |
121 | class CAviSynthAudioStream
122 | : public CSourceStream
123 | , public CSourceSeeking
124 | {
125 | private:
126 | CCritSec m_cSharedState;
127 |
128 | const CAviSynthFile* m_pAviSynthFile;
129 |
130 | BOOL m_bDiscontinuity = FALSE;
131 | BOOL m_bFlushing = FALSE;
132 |
133 | GUID m_Subtype = {};
134 | int m_Channels = 0;
135 | int m_SampleRate = 0;
136 | int m_BytesPerSample = 0; // for all audio channels
137 | int m_BitDepth = 0;
138 | AvsSampleType m_SampleType = (AvsSampleType)0;
139 |
140 | int m_BufferSamples = 0;
141 |
142 | int64_t m_SampleCounter = 0;
143 | int64_t m_CurrentSample = 0;
144 | int64_t m_NumSamples = 0;
145 |
146 | std::wstring m_StreamInfo;
147 |
148 | public:
149 | CAviSynthAudioStream(CAviSynthFile* pAviSynthFile, CSource* pParent, HRESULT* phr);
150 | virtual ~CAviSynthAudioStream();
151 |
152 | STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv) override;
153 |
154 | std::wstring_view GetInfo() { return m_StreamInfo; }
155 |
156 | private:
157 | HRESULT OnThreadCreate() override;
158 | HRESULT OnThreadStartPlay() override;
159 | void UpdateFromSeek();
160 |
161 | // IMediaSeeking
162 | STDMETHODIMP SetRate(double dRate) override;
163 |
164 | HRESULT ChangeStart() override;
165 | HRESULT ChangeStop() override;
166 | HRESULT ChangeRate() override { return S_OK; }
167 |
168 | public:
169 | HRESULT DecideBufferSize(IMemAllocator* pIMemAlloc, ALLOCATOR_PROPERTIES* pProperties) override;
170 | HRESULT FillBuffer(IMediaSample* pSample) override;
171 | HRESULT CheckMediaType(const CMediaType* pMediaType) override;
172 | HRESULT SetMediaType(const CMediaType* pMediaType) override;
173 | HRESULT GetMediaType(int iPosition, CMediaType* pmt) override;
174 |
175 | // IQualityControl
176 | STDMETHODIMP Notify(IBaseFilter* pSender, Quality q) override { return E_NOTIMPL; }
177 | };
178 |
--------------------------------------------------------------------------------
/Source/Helper.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020-2024 v0lt
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-only
5 | */
6 |
7 | #include "stdafx.h"
8 | #include "../Include/Version.h"
9 |
10 | #ifndef __AVISYNTH_7_H__
11 | #include "../Include/avisynth.h"
12 | #endif
13 |
14 | #ifndef VSSCRIPT_H
15 | #include "../Include/VSScript4.h"
16 | #endif
17 |
18 | #include "Helper.h"
19 |
20 |
21 | std::wstring GetVersionStr()
22 | {
23 | std::wstring version = _CRT_WIDE(VERSION_STR);
24 | #if VER_RELEASE != 1
25 | version += std::format(L" (git-{}-{})",
26 | _CRT_WIDE(_CRT_STRINGIZE(REV_DATE)),
27 | _CRT_WIDE(_CRT_STRINGIZE(REV_HASH))
28 | );
29 | #endif
30 | #ifdef _WIN64
31 | version.append(L" x64");
32 | #endif
33 | #ifdef _DEBUG
34 | version.append(L" DEBUG");
35 | #endif
36 | return version;
37 | }
38 |
39 | LPCWSTR GetNameAndVersion()
40 | {
41 | static std::wstring version = L"MPC Script Source " + GetVersionStr();
42 |
43 | return version.c_str();
44 | }
45 |
46 | static const FmtParams_t s_FormatTable[] = {
47 | // fourcc | subtype | ASformat | VSformat | str |Packsize|buffCoeff|CDepth|planes|bitCount
48 | {DWORD(-1), GUID_NULL, 0, 0, nullptr, 0, 0, 0, 0, 0},
49 | // YUV packed
50 | {FCC('YUY2'), MEDIASUBTYPE_YUY2, VideoInfo::CS_YUY2, 0, L"YUY2", 2, 2, 8, 1, 16},
51 | // YUV planar
52 | {FCC('YV12'), MEDIASUBTYPE_YV12, VideoInfo::CS_I420, 0, L"I420", 1, 3, 8, 3, 12},
53 | {FCC('YV12'), MEDIASUBTYPE_YV12, VideoInfo::CS_YV12, pfYUV420P8, L"YV12", 1, 3, 8, 3, 12},
54 | {MAKEFOURCC('Y','3',11,10), MEDIASUBTYPE_LAV_RAWVIDEO, VideoInfo::CS_YUV420P10, pfYUV420P10, L"YUV420P10", 2, 3, 10, 3, 24},
55 | {MAKEFOURCC('Y','3',11,12), MEDIASUBTYPE_LAV_RAWVIDEO, VideoInfo::CS_YUV420P12, pfYUV420P12, L"YUV420P12", 2, 3, 12, 3, 24},
56 | {MAKEFOURCC('Y','3',11,14), MEDIASUBTYPE_LAV_RAWVIDEO, VideoInfo::CS_YUV420P14, pfYUV420P14, L"YUV420P14", 2, 3, 14, 3, 24},
57 | {MAKEFOURCC('Y','3',11,16), MEDIASUBTYPE_LAV_RAWVIDEO, VideoInfo::CS_YUV420P16, pfYUV420P16, L"YUV420P16", 2, 3, 16, 3, 24},
58 | {FCC('YV16'), MEDIASUBTYPE_YV16, VideoInfo::CS_YV16, pfYUV422P8, L"YV16", 1, 4, 8, 3, 16},
59 | {MAKEFOURCC('Y','3',10,10), MEDIASUBTYPE_LAV_RAWVIDEO, VideoInfo::CS_YUV422P10, pfYUV422P10, L"YUV422P10", 2, 4, 10, 3, 32},
60 | {MAKEFOURCC('Y','3',10,12), MEDIASUBTYPE_LAV_RAWVIDEO, VideoInfo::CS_YUV422P12, pfYUV422P12, L"YUV422P12", 2, 4, 12, 3, 32},
61 | {MAKEFOURCC('Y','3',10,14), MEDIASUBTYPE_LAV_RAWVIDEO, VideoInfo::CS_YUV422P14, pfYUV422P14, L"YUV422P14", 2, 4, 14, 3, 32},
62 | {MAKEFOURCC('Y','3',10,16), MEDIASUBTYPE_LAV_RAWVIDEO, VideoInfo::CS_YUV422P16, pfYUV422P16, L"YUV422P16", 2, 4, 16, 3, 32},
63 | {FCC('YV24'), MEDIASUBTYPE_YV24, VideoInfo::CS_YV24, pfYUV444P8, L"YV24", 1, 6, 8, 3, 24},
64 | {MAKEFOURCC('Y','3',0,10), MEDIASUBTYPE_LAV_RAWVIDEO, VideoInfo::CS_YUV444P10, pfYUV444P10, L"YUV444P10", 2, 6, 10, 3, 48},
65 | {MAKEFOURCC('Y','3',0,12), MEDIASUBTYPE_LAV_RAWVIDEO, VideoInfo::CS_YUV444P12, pfYUV444P12, L"YUV444P12", 2, 6, 12, 3, 48},
66 | {MAKEFOURCC('Y','3',0,14), MEDIASUBTYPE_LAV_RAWVIDEO, VideoInfo::CS_YUV444P14, pfYUV444P14, L"YUV444P14", 2, 6, 14, 3, 48},
67 | {MAKEFOURCC('Y','3',0,16), MEDIASUBTYPE_LAV_RAWVIDEO, VideoInfo::CS_YUV444P16, pfYUV444P16, L"YUV444P16", 2, 6, 16, 3, 48},
68 | // YUV planar whith alpha
69 | {MAKEFOURCC('Y','4',0,8), MEDIASUBTYPE_LAV_RAWVIDEO, VideoInfo::CS_YUVA444, 0, L"YUVA444P8", 1, 8, 8, 4, 32},
70 | {MAKEFOURCC('Y','4',0,10), MEDIASUBTYPE_LAV_RAWVIDEO, VideoInfo::CS_YUVA444P10, 0, L"YUVA444P10", 2, 8, 10, 4, 64},
71 | {MAKEFOURCC('Y','4',0,16), MEDIASUBTYPE_LAV_RAWVIDEO, VideoInfo::CS_YUVA444P16, 0, L"YUVA444P16", 2, 8, 16, 4, 64},
72 | // RGB packed
73 | {BI_RGB, MEDIASUBTYPE_RGB24, VideoInfo::CS_BGR24, 0, L"RGB24", 3, 2, 8, 1, 24},
74 | {BI_RGB, MEDIASUBTYPE_RGB32, 0, 0, L"RGB32", 4, 2, 8, 1, 32},
75 | {BI_RGB, MEDIASUBTYPE_ARGB32, VideoInfo::CS_BGR32, 0, L"ARGB32", 4, 2, 8, 1, 32},
76 | {MAKEFOURCC('B','G','R',48), MEDIASUBTYPE_BGR48, VideoInfo::CS_BGR48, 0, L"BGR48", 6, 2, 16, 1, 48},
77 | {MAKEFOURCC('B','R','A',64), MEDIASUBTYPE_BGRA64, VideoInfo::CS_BGR64, 0, L"BGRA64", 8, 2, 16, 1, 64},
78 | // RGB planar
79 | {MAKEFOURCC('G','3',0,8), MEDIASUBTYPE_LAV_RAWVIDEO, VideoInfo::CS_RGBP, pfRGB24, L"RGBP8", 1, 6, 8, 3, 24},
80 | {MAKEFOURCC('G','3',0,10), MEDIASUBTYPE_LAV_RAWVIDEO, VideoInfo::CS_RGBP10, pfRGB30, L"RGBP10", 2, 6, 10, 3, 48},
81 | {MAKEFOURCC('G','3',0,16), MEDIASUBTYPE_LAV_RAWVIDEO, VideoInfo::CS_RGBP16, pfRGB48, L"RGBP16", 2, 6, 16, 3, 48},
82 | // RGB planar whith alpha
83 | {MAKEFOURCC('G','4',0,8), MEDIASUBTYPE_LAV_RAWVIDEO, VideoInfo::CS_RGBAP, 0, L"RGBAP8", 1, 8, 8, 4, 32},
84 | {MAKEFOURCC('G','4',0,10), MEDIASUBTYPE_LAV_RAWVIDEO, VideoInfo::CS_RGBAP10, 0, L"RGBAP10", 2, 8, 10, 4, 64},
85 | {MAKEFOURCC('G','4',0,16), MEDIASUBTYPE_LAV_RAWVIDEO, VideoInfo::CS_RGBAP16, 0, L"RGBAP16", 2, 8, 16, 4, 64},
86 | // grayscale
87 | {FCC('Y800'), MEDIASUBTYPE_Y800, VideoInfo::CS_Y8, pfGray8, L"Y8", 1, 2, 8, 1, 8},
88 | {MAKEFOURCC('Y','1',0,10), MEDIASUBTYPE_LAV_RAWVIDEO, VideoInfo::CS_Y10, pfGray10, L"Y10", 2, 2, 10, 1, 16},
89 | {MAKEFOURCC('Y','1',0,16), MEDIASUBTYPE_Y16, VideoInfo::CS_Y16, pfGray16, L"Y16", 2, 2, 16, 1, 16},
90 | };
91 |
92 | const FmtParams_t& GetFormatParamsAviSynth(const int asFormat)
93 | {
94 | for (const auto& f : s_FormatTable) {
95 | if (f.ASformat == asFormat) {
96 | return f;
97 | }
98 | }
99 | return s_FormatTable[0];
100 | }
101 |
102 | const FmtParams_t& GetFormatParamsVapourSynth(const int vsVideoFormat)
103 | {
104 | for (const auto& f : s_FormatTable) {
105 | if (f.VSformat == vsVideoFormat) {
106 | return f;
107 | }
108 | }
109 | return s_FormatTable[0];
110 | }
111 |
112 | std::unique_ptr GetBitmapWithText(const std::wstring& text, const long width, const long height)
113 | {
114 | HFONT hFont = CreateFontW(-14, 0, 0, 0, FW_NORMAL, FALSE,
115 | FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
116 | CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY,
117 | FIXED_PITCH, L"Consolas");
118 | if (!hFont) {
119 | return nullptr;
120 | }
121 |
122 | BOOL ret = 0;
123 | HDC hDC = CreateCompatibleDC(nullptr);
124 | SetMapMode(hDC, MM_TEXT);
125 |
126 | HFONT hFontOld = (HFONT)SelectObject(hDC, hFont);
127 |
128 | SIZE size;
129 | ret = GetTextExtentPoint32W(hDC, L"_", 1, &size);
130 |
131 | // Prepare to create a bitmap
132 | BITMAPINFO bmi = {};
133 | bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
134 | bmi.bmiHeader.biWidth = width;
135 | bmi.bmiHeader.biHeight = -height;
136 | bmi.bmiHeader.biPlanes = 1;
137 | bmi.bmiHeader.biCompression = BI_RGB;
138 | bmi.bmiHeader.biBitCount = 32;
139 |
140 | HGDIOBJ hBitmapOld = nullptr;
141 | void* pBitmapBits = nullptr;
142 | HBITMAP hBitmap = CreateDIBSection(hDC, &bmi, DIB_RGB_COLORS, &pBitmapBits, nullptr, 0);
143 | if (pBitmapBits) {
144 | HGDIOBJ hBitmapOld = SelectObject(hDC, hBitmap);
145 |
146 | SetTextColor(hDC, RGB(255, 255, 255));
147 | SetBkColor(hDC, RGB(64, 64, 64));
148 | RECT rect = {0, 0, width, height};
149 | HBRUSH hBrush = CreateSolidBrush(RGB(64, 64, 64));
150 | FillRect(hDC, &rect, hBrush);
151 | DrawTextW(hDC, text.c_str(), text.size(), &rect, DT_LEFT|DT_WORDBREAK);
152 |
153 | GdiFlush();
154 | DeleteObject(hBrush);
155 |
156 | const long len = width * height * 4;
157 | std::unique_ptr bitmapData(new(std::nothrow) BYTE[len]);
158 |
159 | if (bitmapData) {
160 | memcpy(bitmapData.get(), pBitmapBits, len);
161 | }
162 |
163 | SelectObject(hDC, hBitmapOld);
164 | DeleteObject(hBitmap);
165 |
166 | SelectObject(hDC, hFontOld);
167 | DeleteObject(hFont);
168 | DeleteDC(hDC);
169 |
170 | return bitmapData;
171 | }
172 |
173 | SelectObject(hDC, hFontOld);
174 | DeleteObject(hFont);
175 | DeleteDC(hDC);
176 |
177 | return nullptr;
178 | }
179 |
--------------------------------------------------------------------------------
/Source/Helper.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020-2024 v0lt
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-only
5 | */
6 |
7 | #pragma once
8 |
9 | #include "Utils/Util.h"
10 | #include "Utils/StringUtil.h"
11 |
12 | LPCWSTR GetNameAndVersion();
13 |
14 | struct FmtParams_t {
15 | DWORD fourcc;
16 | GUID subtype;
17 | int ASformat;
18 | int VSformat;
19 | const wchar_t* str;
20 | int Packsize;
21 | int buffCoeff;
22 | int CDepth;
23 | int planes;
24 | int bitCount;
25 | };
26 |
27 | const FmtParams_t& GetFormatParamsAviSynth(const int asFormat);
28 | const FmtParams_t& GetFormatParamsVapourSynth(const int vsVideoFormat);
29 |
30 | std::unique_ptr GetBitmapWithText(const std::wstring& text, const long width, const long height);
31 |
--------------------------------------------------------------------------------
/Source/IScriptSource.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020-2024 v0lt
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-only
5 | */
6 |
7 | #pragma once
8 |
9 | interface __declspec(uuid("1B3DA9DF-63CA-46ED-8572-1615AA187662"))
10 | IScriptSource : public IUnknown {
11 | STDMETHOD_(bool, GetActive()) PURE;
12 | STDMETHOD(GetScriptInfo) (std::wstring& str) PURE;
13 | };
14 |
--------------------------------------------------------------------------------
/Source/MpcScriptSource.def:
--------------------------------------------------------------------------------
1 | EXPORTS
2 | DllCanUnloadNow PRIVATE
3 | DllGetClassObject PRIVATE
4 | DllRegisterServer PRIVATE
5 | DllUnregisterServer PRIVATE
6 |
--------------------------------------------------------------------------------
/Source/MpcScriptSource.rc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/v0lt/ScriptSourceFilter/37546f0cfd188d08fb1dc888dbaf0c7e2b7e379f/Source/MpcScriptSource.rc
--------------------------------------------------------------------------------
/Source/MpcScriptSource.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Debug
10 | x64
11 |
12 |
13 | Release
14 | Win32
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | {DAF59106-BC83-478F-95D9-4516C2A52970}
23 | MpcScriptSource
24 | Win32Proj
25 | MpcScriptSource
26 |
27 |
28 |
29 |
30 | DynamicLibrary
31 | Unicode
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | .ax
43 |
44 |
45 | $(ProjectName)64
46 |
47 |
48 |
49 | MpcScriptSource.def
50 | false
51 |
52 |
53 | ..\update_revision.cmd
54 |
55 |
56 | $(ProjectDir)
57 | Use
58 | stdafx.h
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 | Create
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 | {e8a3f6fa-ae1c-4c8e-a0b6-9c8480324eaa}
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
--------------------------------------------------------------------------------
/Source/MpcScriptSource.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {9788c006-0809-4532-aa20-b51ed992525a}
6 | cpp;c;cxx;def;odl;idl;hpj;bat;asm
7 |
8 |
9 | {4d561854-929b-492e-9fba-c2cebb7cc3d4}
10 | h;hpp;hxx;hm;inl;inc
11 |
12 |
13 | {addff0d6-0d94-4e4c-b5ea-b7d5b330fd45}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe
15 |
16 |
17 | {a01ce4a8-f1ae-4465-8aea-4c4d569b5f63}
18 |
19 |
20 |
21 |
22 | Source Files
23 |
24 |
25 | Source Files
26 |
27 |
28 | Source Files
29 |
30 |
31 | Source Files
32 |
33 |
34 | Source Files
35 |
36 |
37 | Source Files
38 |
39 |
40 | Source Files
41 |
42 |
43 | Source Files
44 |
45 |
46 | Utils
47 |
48 |
49 | Utils
50 |
51 |
52 |
53 |
54 | Header Files
55 |
56 |
57 | Header Files
58 |
59 |
60 | Resource Files
61 |
62 |
63 | Header Files
64 |
65 |
66 | Header Files
67 |
68 |
69 | Header Files
70 |
71 |
72 | Header Files
73 |
74 |
75 | Header Files
76 |
77 |
78 | Header Files
79 |
80 |
81 | Utils
82 |
83 |
84 | Utils
85 |
86 |
87 |
88 |
89 | Resource Files
90 |
91 |
92 |
93 |
94 | Resource Files
95 |
96 |
97 |
--------------------------------------------------------------------------------
/Source/PropPage.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020-2024 v0lt
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-only
5 | */
6 |
7 | #include "stdafx.h"
8 | #include "resource.h"
9 | #include "Helper.h"
10 | #include "PropPage.h"
11 |
12 | void SetCursor(HWND hWnd, LPCWSTR lpCursorName)
13 | {
14 | SetClassLongPtrW(hWnd, GCLP_HCURSOR, (LONG_PTR)::LoadCursorW(nullptr, lpCursorName));
15 | }
16 |
17 | void SetCursor(HWND hWnd, UINT nID, LPCWSTR lpCursorName)
18 | {
19 | SetCursor(::GetDlgItem(hWnd, nID), lpCursorName);
20 | }
21 |
22 | inline void ComboBox_AddStringData(HWND hWnd, int nIDComboBox, LPCWSTR str, LONG_PTR data)
23 | {
24 | LRESULT lValue = SendDlgItemMessageW(hWnd, nIDComboBox, CB_ADDSTRING, 0, (LPARAM)str);
25 | if (lValue != CB_ERR) {
26 | SendDlgItemMessageW(hWnd, nIDComboBox, CB_SETITEMDATA, lValue, data);
27 | }
28 | }
29 |
30 | inline LONG_PTR ComboBox_GetCurItemData(HWND hWnd, int nIDComboBox)
31 | {
32 | LRESULT lValue = SendDlgItemMessageW(hWnd, nIDComboBox, CB_GETCURSEL, 0, 0);
33 | if (lValue != CB_ERR) {
34 | lValue = SendDlgItemMessageW(hWnd, nIDComboBox, CB_GETITEMDATA, lValue, 0);
35 | }
36 | return lValue;
37 | }
38 |
39 | void ComboBox_SelectByItemData(HWND hWnd, int nIDComboBox, LONG_PTR data)
40 | {
41 | LRESULT lCount = SendDlgItemMessageW(hWnd, nIDComboBox, CB_GETCOUNT, 0, 0);
42 | if (lCount != CB_ERR) {
43 | for (LRESULT idx = 0; idx < lCount; idx++) {
44 | const LRESULT lValue = SendDlgItemMessageW(hWnd, nIDComboBox, CB_GETITEMDATA, idx, 0);
45 | if (data == lValue) {
46 | SendDlgItemMessageW(hWnd, nIDComboBox, CB_SETCURSEL, idx, 0);
47 | break;
48 | }
49 | }
50 | }
51 | }
52 |
53 |
54 | // CSSInfoPPage
55 |
56 | // https://msdn.microsoft.com/ru-ru/library/windows/desktop/dd375010(v=vs.85).aspx
57 |
58 | CSSInfoPPage::CSSInfoPPage(LPUNKNOWN lpunk, HRESULT* phr) :
59 | CBasePropertyPage(L"InfoProp", lpunk, IDD_INFOPROPPAGE, IDS_INFOPROPPAGE_TITLE)
60 | {
61 | DLog(L"CSSInfoPPage()");
62 | }
63 |
64 | CSSInfoPPage::~CSSInfoPPage()
65 | {
66 | DLog(L"~CSSInfoPPage()");
67 |
68 | if (m_hMonoFont) {
69 | DeleteObject(m_hMonoFont);
70 | m_hMonoFont = 0;
71 | }
72 | }
73 |
74 | void CSSInfoPPage::SetControls()
75 | {
76 | std::wstring strInfo;
77 | m_pScriptSource->GetScriptInfo(strInfo);
78 | str_replace(strInfo, L"\n", L"\r\n");
79 | SetDlgItemTextW(IDC_EDIT1, strInfo.c_str());
80 | }
81 |
82 | HRESULT CSSInfoPPage::OnConnect(IUnknown *pUnk)
83 | {
84 | if (pUnk == nullptr) return E_POINTER;
85 |
86 | m_pScriptSource = pUnk;
87 | if (!m_pScriptSource) {
88 | return E_NOINTERFACE;
89 | }
90 |
91 | return S_OK;
92 | }
93 |
94 | HRESULT CSSInfoPPage::OnDisconnect()
95 | {
96 | if (m_pScriptSource == nullptr) {
97 | return E_UNEXPECTED;
98 | }
99 |
100 | m_pScriptSource.Release();
101 |
102 | return S_OK;
103 | }
104 |
105 | HRESULT CSSInfoPPage::OnActivate()
106 | {
107 | // set m_hWnd for CWindow
108 | m_hWnd = m_hwnd;
109 |
110 | // init monospace font
111 | LOGFONTW lf = {};
112 | HDC hdc = GetWindowDC();
113 | lf.lfHeight = -MulDiv(9, GetDeviceCaps(hdc, LOGPIXELSY), 72);
114 | ReleaseDC(hdc);
115 | lf.lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
116 | wcscpy_s(lf.lfFaceName, L"Consolas");
117 | m_hMonoFont = CreateFontIndirectW(&lf);
118 |
119 | GetDlgItem(IDC_EDIT1).SetFont(m_hMonoFont);
120 |
121 | SetControls();
122 |
123 | SetDlgItemTextW(IDC_EDIT3, GetNameAndVersion());
124 |
125 | SetCursor(m_hWnd, IDC_ARROW);
126 |
127 | return S_OK;
128 | }
129 |
130 | INT_PTR CSSInfoPPage::OnReceiveMessage(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
131 | {
132 | if (uMsg == WM_CLOSE) {
133 | // fixed Esc handling when EDITTEXT control has ES_MULTILINE property and is in focus
134 | return (LRESULT)1;
135 | }
136 |
137 | // Let the parent class handle the message.
138 | return CBasePropertyPage::OnReceiveMessage(hwnd, uMsg, wParam, lParam);
139 | }
140 |
141 | HRESULT CSSInfoPPage::OnApplyChanges()
142 | {
143 | return S_OK;
144 | }
145 |
--------------------------------------------------------------------------------
/Source/PropPage.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020-2024 v0lt
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-only
5 | */
6 |
7 | #pragma once
8 |
9 | #include "IScriptSource.h"
10 |
11 | // CSSInfoPPage
12 |
13 | class __declspec(uuid("D36E542D-8645-4F2C-A758-55C6FDF67E50"))
14 | CSSInfoPPage : public CBasePropertyPage, public CWindow
15 | {
16 | HFONT m_hMonoFont = nullptr;
17 | CComQIPtr m_pScriptSource;
18 |
19 | public:
20 | CSSInfoPPage(LPUNKNOWN lpunk, HRESULT* phr);
21 | ~CSSInfoPPage();
22 |
23 | private:
24 | void SetControls();
25 |
26 | HRESULT OnConnect(IUnknown* pUnknown) override;
27 | HRESULT OnDisconnect() override;
28 | HRESULT OnActivate() override;
29 | void SetDirty()
30 | {
31 | m_bDirty = TRUE;
32 | if (m_pPageSite) {
33 | m_pPageSite->OnStatusChange(PROPPAGESTATUS_DIRTY);
34 | }
35 | }
36 | INT_PTR OnReceiveMessage(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) override;
37 | HRESULT OnApplyChanges() override;
38 | };
39 |
--------------------------------------------------------------------------------
/Source/ScriptSource.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020-2024 v0lt
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-only
5 | */
6 |
7 | #include "stdafx.h"
8 |
9 | #include "../Include/Version.h"
10 | #include "PropPage.h"
11 |
12 | #include "ScriptSource.h"
13 |
14 | #define OPT_REGKEY_ScriptSource L"Software\\MPC-BE Filters\\MPC Script Source"
15 |
16 | //
17 | // CScriptSource
18 | //
19 |
20 | CScriptSource::CScriptSource(LPUNKNOWN lpunk, HRESULT* phr)
21 | : CSource(L"MPC Script Source", lpunk, __uuidof(this))
22 | {
23 | #ifdef _DEBUG
24 | DbgSetModuleLevel(LOG_TRACE, DWORD_MAX);
25 | DbgSetModuleLevel(LOG_ERROR, DWORD_MAX);
26 | #endif
27 |
28 | DLog(L"Windows {}", GetWindowsVersion());
29 | DLog(GetNameAndVersion());
30 |
31 | HRESULT hr = S_OK;
32 |
33 | if (phr) {
34 | *phr = hr;
35 | }
36 |
37 | return;
38 | }
39 |
40 | CScriptSource::~CScriptSource()
41 | {
42 | DLog(L"~CScriptSource()");
43 | }
44 |
45 | STDMETHODIMP CScriptSource::NonDelegatingQueryInterface(REFIID riid, void** ppv)
46 | {
47 | CheckPointer(ppv, E_POINTER);
48 |
49 | return
50 | QI(IFileSourceFilter)
51 | QI(IAMFilterMiscFlags)
52 | QI(ISpecifyPropertyPages)
53 | QI(IScriptSource)
54 | QI(IExFilterConfig)
55 | __super::NonDelegatingQueryInterface(riid, ppv);
56 | }
57 |
58 | // IFileSourceFilter
59 |
60 | STDMETHODIMP CScriptSource::Load(LPCOLESTR pszFileName, const AM_MEDIA_TYPE* pmt)
61 | {
62 | // TODO: destroy any already existing pins and create new, now we are just going die nicely instead of doing it :)
63 | if (GetPinCount() > 0) {
64 | return VFW_E_ALREADY_CONNECTED;
65 | }
66 |
67 | std::wstring fn = pszFileName;
68 | std::wstring ext = fn.substr(fn.find_last_of('.'));
69 | str_tolower(ext);
70 |
71 | HRESULT hr = S_OK;
72 | if (ext == L".avs") {
73 | m_pAviSynthFile.reset(new(std::nothrow) CAviSynthFile(pszFileName, this, &hr));
74 | }
75 | else if (ext == L".vpy") {
76 | m_pVapourSynthFile.reset(new(std::nothrow) CVapourSynthFile(pszFileName, this, &hr));
77 | }
78 | else {
79 | return E_INVALIDARG;
80 | }
81 |
82 | if (FAILED(hr)) {
83 | return hr;
84 | }
85 |
86 | m_fn = std::move(fn);
87 |
88 | return S_OK;
89 | }
90 |
91 | STDMETHODIMP CScriptSource::GetCurFile(LPOLESTR* ppszFileName, AM_MEDIA_TYPE* pmt)
92 | {
93 | CheckPointer(ppszFileName, E_POINTER);
94 |
95 | size_t nCount = m_fn.size() + 1;
96 | *ppszFileName = (LPOLESTR)CoTaskMemAlloc(nCount * sizeof(WCHAR));
97 | if (!(*ppszFileName)) {
98 | return E_OUTOFMEMORY;
99 | }
100 |
101 | wcscpy_s(*ppszFileName, nCount, m_fn.c_str());
102 |
103 | return S_OK;
104 | }
105 |
106 | // IAMFilterMiscFlags
107 |
108 | STDMETHODIMP_(ULONG) CScriptSource::GetMiscFlags()
109 | {
110 | return AM_FILTER_MISC_FLAGS_IS_SOURCE;
111 | }
112 |
113 | // ISpecifyPropertyPages
114 | STDMETHODIMP CScriptSource::GetPages(CAUUID* pPages)
115 | {
116 | CheckPointer(pPages, E_POINTER);
117 |
118 | pPages->cElems = 1;
119 | pPages->pElems = reinterpret_cast(CoTaskMemAlloc(sizeof(GUID) * pPages->cElems));
120 | if (pPages->pElems == nullptr) {
121 | return E_OUTOFMEMORY;
122 | }
123 |
124 | pPages->pElems[0] = __uuidof(CSSInfoPPage);
125 |
126 | return S_OK;
127 | }
128 |
129 | // IScriptSource
130 |
131 | STDMETHODIMP_(bool) CScriptSource::GetActive()
132 | {
133 | return (GetPinCount() > 0);
134 | }
135 |
136 | STDMETHODIMP CScriptSource::GetScriptInfo(std::wstring& str)
137 | {
138 | if (GetActive()) {
139 | if (m_pAviSynthFile) {
140 | str.assign(m_pAviSynthFile->GetInfo());
141 | }
142 | else if (m_pVapourSynthFile) {
143 | str.assign(m_pVapourSynthFile->GetInfo());
144 | }
145 | return S_OK;
146 | } else {
147 | str.assign(L"filter is not active");
148 | return S_FALSE;
149 | }
150 | }
151 |
152 | // IExFilterConfig
153 |
154 | STDMETHODIMP CScriptSource::Flt_GetInt64(LPCSTR field, __int64 *value)
155 | {
156 | CheckPointer(value, E_POINTER);
157 |
158 | if (!strcmp(field, "version")) {
159 | *value = ((uint64_t)VER_MAJOR << 48)
160 | | ((uint64_t)VER_MINOR << 32)
161 | | ((uint64_t)VER_BUILD << 16)
162 | | ((uint64_t)REV_NUM);
163 | return S_OK;
164 | }
165 |
166 | return E_INVALIDARG;
167 | }
168 |
--------------------------------------------------------------------------------
/Source/ScriptSource.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020-2024 v0lt
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-only
5 | */
6 |
7 | #pragma once
8 |
9 | #include
10 | #include
11 | #include "Helper.h"
12 | #include "IScriptSource.h"
13 | #include "../Include/FilterInterfacesImpl.h"
14 |
15 | #include "AviSynthStream.h"
16 | #include "VapourSynthStream.h"
17 |
18 | #define STR_CLSID_ScriptSource "{7D3BBD5A-880D-4A30-A2D1-7B8C2741AFEF}"
19 |
20 | class __declspec(uuid(STR_CLSID_ScriptSource))
21 | CScriptSource
22 | : public CSource
23 | , public IFileSourceFilter
24 | , public IAMFilterMiscFlags
25 | , public ISpecifyPropertyPages
26 | , public IScriptSource
27 | , public CExFilterConfigImpl
28 | {
29 | private:
30 | friend class CAviSynthStream;
31 | friend class CVapourSynthStream;
32 |
33 | std::wstring m_fn;
34 |
35 | std::unique_ptr m_pAviSynthFile;
36 | std::unique_ptr m_pVapourSynthFile;
37 |
38 | public:
39 | CScriptSource(LPUNKNOWN lpunk, HRESULT* phr);
40 | ~CScriptSource();
41 |
42 | DECLARE_IUNKNOWN
43 | STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv);
44 |
45 | // IFileSourceFilter
46 | STDMETHODIMP Load(LPCOLESTR pszFileName, const AM_MEDIA_TYPE* pmt);
47 | STDMETHODIMP GetCurFile(LPOLESTR* ppszFileName, AM_MEDIA_TYPE* pmt);
48 |
49 | // IAMFilterMiscFlags
50 | STDMETHODIMP_(ULONG) GetMiscFlags();
51 |
52 | // ISpecifyPropertyPages
53 | STDMETHODIMP GetPages(CAUUID* pPages);
54 |
55 | // IScriptSource
56 | STDMETHODIMP_(bool) GetActive();
57 | STDMETHODIMP GetScriptInfo(std::wstring& str);
58 |
59 | // IExFilterConfig
60 | STDMETHODIMP Flt_GetInt64(LPCSTR field, __int64* value) override;
61 | };
62 |
--------------------------------------------------------------------------------
/Source/Utils/StringUtil.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2020-2024 v0lt, Aleksoid
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #include "stdafx.h"
22 | #include
23 | #include "StringUtil.h"
24 |
25 | void str_split(const std::string& str, std::vector& tokens, char delim)
26 | {
27 | std::istringstream iss(str);
28 | std::string tmp;
29 | while (std::getline(iss, tmp, delim)) {
30 | if (tmp.size()) {
31 | tokens.push_back(tmp);
32 | }
33 | }
34 | }
35 |
36 | void str_split(const std::wstring& wstr, std::vector& tokens, wchar_t delim)
37 | {
38 | std::wistringstream iss(wstr);
39 | std::wstring tmp;
40 | while (std::getline(iss, tmp, delim)) {
41 | if (tmp.size()) {
42 | tokens.push_back(tmp);
43 | }
44 | }
45 | }
46 |
47 | void str_replace(std::string& s, const std::string_view from, const std::string_view to)
48 | {
49 | std::string str;
50 | size_t pos = 0;
51 | size_t pf = 0;
52 | while ((pf = s.find(from, pos)) < s.size()) {
53 | str.append(s, pos, pf - pos);
54 | str.append(to);
55 | pos = pf + from.size();
56 | }
57 | if (str.size()) {
58 | str.append(s, pos);
59 | s = str;
60 | }
61 | }
62 |
63 | void str_replace(std::wstring& s, const std::wstring_view from, const std::wstring_view to)
64 | {
65 | std::wstring str;
66 | size_t pos = 0;
67 | size_t pf = 0;
68 | while ((pf = s.find(from, pos)) < s.size()) {
69 | str.append(s, pos, pf - pos);
70 | str.append(to);
71 | pos = pf + from.size();
72 | }
73 | if (str.size()) {
74 | str.append(s, pos);
75 | s = str;
76 | }
77 | }
78 |
79 | //
80 | // converting strings of different formats
81 | //
82 |
83 | std::wstring ConvertAnsiToWide(const std::string_view sv)
84 | {
85 | int count = MultiByteToWideChar(CP_ACP, 0, sv.data(), (int)sv.length(), nullptr, 0);
86 | std::wstring wstr(count, 0);
87 | MultiByteToWideChar(CP_ACP, 0, sv.data(), (int)sv.length(), &wstr[0], count);
88 | return wstr;
89 | }
90 |
91 | std::wstring ConvertUtf8ToWide(const std::string_view sv)
92 | {
93 | int count = MultiByteToWideChar(CP_UTF8, 0, sv.data(), (int)sv.length(), nullptr, 0);
94 | std::wstring wstr(count, 0);
95 | MultiByteToWideChar(CP_UTF8, 0, sv.data(), (int)sv.length(), &wstr[0], count);
96 | return wstr;
97 | }
98 |
99 | std::string ConvertWideToANSI(const std::wstring_view wsv)
100 | {
101 | int count = WideCharToMultiByte(CP_ACP, 0, wsv.data(), (int)wsv.length(), nullptr, 0, nullptr, nullptr);
102 | std::string str(count, 0);
103 | WideCharToMultiByte(CP_ACP, 0, wsv.data(), -1, &str[0], count, nullptr, nullptr);
104 | return str;
105 | }
106 |
107 | std::string ConvertWideToUtf8(const std::wstring_view wsv)
108 | {
109 | int count = WideCharToMultiByte(CP_UTF8, 0, wsv.data(), (int)wsv.length(), nullptr, 0, nullptr, nullptr);
110 | std::string str(count, 0);
111 | WideCharToMultiByte(CP_UTF8, 0, wsv.data(), -1, &str[0], count, nullptr, nullptr);
112 | return str;
113 | }
114 |
--------------------------------------------------------------------------------
/Source/Utils/StringUtil.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2020-2024 v0lt, Aleksoid
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #pragma once
22 |
23 | #include
24 | #include
25 |
26 | //
27 | // convert string to lower or upper case
28 | //
29 |
30 | inline void str_tolower(std::string& s)
31 | {
32 | std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c){ return std::tolower(c); } );
33 | // char for std::tolower should be converted to unsigned char
34 | }
35 |
36 | inline void str_toupper(std::string& s)
37 | {
38 | std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c){ return std::toupper(c); } );
39 | // char for std::toupper should be converted to unsigned char
40 | }
41 |
42 | inline void str_tolower(std::wstring& s)
43 | {
44 | std::transform(s.begin(), s.end(), s.begin(), ::tolower);
45 | }
46 |
47 | inline void str_toupper(std::wstring& s)
48 | {
49 | std::transform(s.begin(), s.end(), s.begin(), ::toupper);
50 | }
51 |
52 | inline void str_tolower_all(std::wstring& s)
53 | {
54 | const std::ctype& f = std::use_facet>(std::locale());
55 | std::ignore = f.tolower(&s[0], &s[0] + s.size());
56 | }
57 |
58 | inline void str_toupper_all(std::wstring& s)
59 | {
60 | const std::ctype& f = std::use_facet>(std::locale());
61 | std::ignore = f.toupper(&s[0], &s[0] + s.size());
62 | }
63 |
64 | //
65 | // split a string using char delimiter
66 | //
67 |
68 | void str_split(const std::string& str, std::vector& tokens, char delim);
69 |
70 | void str_split(const std::wstring& wstr, std::vector& tokens, wchar_t delim);
71 |
72 | //
73 | // trimming whitespace
74 | //
75 |
76 | inline std::string str_trim(const std::string_view sv)
77 | {
78 | auto sfront = std::find_if_not(sv.begin(), sv.end(), [](int c) {return isspace(c); });
79 | auto sback = std::find_if_not(sv.rbegin(), sv.rend(), [](int c) {return isspace(c); }).base();
80 | return (sback <= sfront ? std::string() : std::string(sfront, sback));
81 | }
82 |
83 | inline std::wstring str_trim(const std::wstring_view sv)
84 | {
85 | auto sfront = std::find_if_not(sv.begin(), sv.end(), [](int c) {return iswspace(c); });
86 | auto sback = std::find_if_not(sv.rbegin(), sv.rend(), [](int c) {return iswspace(c); }).base();
87 | return (sback <= sfront ? std::wstring() : std::wstring(sfront, sback));
88 | }
89 |
90 | //
91 | // trimming a character at the end
92 | //
93 |
94 | inline void str_trim_end(std::string& s, const char ch)
95 | {
96 | s.erase(s.find_last_not_of(ch) + 1);
97 | }
98 |
99 | inline void str_trim_end(std::wstring& s, const wchar_t ch)
100 | {
101 | s.erase(s.find_last_not_of(ch) + 1);
102 | }
103 |
104 | //
105 | // truncate after a null character
106 | //
107 |
108 | inline void str_truncate_after_null(std::string& s)
109 | {
110 | s.erase(std::find(s.begin(), s.end(), '\0'), s.end());
111 | }
112 |
113 | inline void str_truncate_after_null(std::wstring& s)
114 | {
115 | s.erase(std::find(s.begin(), s.end(), '\0'), s.end());
116 | }
117 |
118 | //
119 | // replace substring
120 | //
121 |
122 | void str_replace(std::string& s, const std::string_view from, const std::string_view to);
123 | void str_replace(std::wstring& s, const std::wstring_view from, const std::wstring_view to);
124 |
125 | //
126 | // simple convert ANSI string to wide character string
127 | //
128 |
129 | inline std::wstring A2WStr(const std::string_view sv)
130 | {
131 | return std::wstring(sv.begin(), sv.end());
132 | }
133 |
134 | //
135 | // converting strings of different formats
136 | //
137 |
138 | std::wstring ConvertAnsiToWide(const std::string_view sv);
139 |
140 | std::wstring ConvertUtf8ToWide(const std::string_view sv);
141 |
142 | std::string ConvertWideToANSI(const std::wstring_view wsv);
143 |
144 | std::string ConvertWideToUtf8(const std::wstring_view wsv);
145 |
--------------------------------------------------------------------------------
/Source/Utils/Util.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2020-2024 v0lt, Aleksoid
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #include "stdafx.h"
22 | #include "Util.h"
23 |
24 | static bool IsWindows11OrGreater(DWORD dwBuildNumber)
25 | {
26 | OSVERSIONINFOEXW osvi = {
27 | .dwOSVersionInfoSize = sizeof(osvi),
28 | .dwMajorVersion = HIBYTE(_WIN32_WINNT_WIN10),
29 | .dwMinorVersion = LOBYTE(_WIN32_WINNT_WIN10),
30 | .dwBuildNumber = dwBuildNumber, };
31 | DWORDLONG const dwlConditionMask = VerSetConditionMask(
32 | VerSetConditionMask(
33 | VerSetConditionMask(
34 | 0, VER_MAJORVERSION, VER_GREATER_EQUAL),
35 | VER_MINORVERSION, VER_GREATER_EQUAL),
36 | VER_BUILDNUMBER, VER_GREATER_EQUAL);
37 |
38 | return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER, dwlConditionMask) != FALSE;
39 | }
40 |
41 | static LPCWSTR GetWinVer()
42 | {
43 | // https://learn.microsoft.com/en-us/windows/release-health/release-information#windows-10-release-history
44 | // https://learn.microsoft.com/en-us/windows/release-health/windows11-release-information#windows-11-release-history
45 | const struct {
46 | const DWORD buildNumber;
47 | LPCWSTR version;
48 | }
49 | win10versions[] = {
50 | { 26100, L"11 24H2" },
51 | { 22631, L"11 23H2" },
52 | { 22621, L"11 22H2" },
53 | { 22000, L"11 21H2" },
54 | { 19045, L"10 22H2" },
55 | { 19044, L"10 21H2" },
56 | { 19043, L"10 21H1" },
57 | { 19042, L"10 20H2" },
58 | { 19041, L"10 2004" },
59 | { 18363, L"10 1909" },
60 | { 18362, L"10 1903" },
61 | { 17763, L"10 1809" },
62 | { 17134, L"10 1803" },
63 | { 16299, L"10 1709" },
64 | { 15063, L"10 1703" },
65 | { 14393, L"10 1607" },
66 | { 10586, L"10 1511" },
67 | { 10240, L"10 1507" },
68 | };
69 |
70 | OSVERSIONINFOEXW osvi = {
71 | .dwOSVersionInfoSize = sizeof(osvi),
72 | .dwMajorVersion = HIBYTE(_WIN32_WINNT_WIN10),
73 | .dwMinorVersion = LOBYTE(_WIN32_WINNT_WIN10), };
74 | DWORDLONG const dwlConditionMask = VerSetConditionMask(
75 | VerSetConditionMask(
76 | VerSetConditionMask(
77 | 0, VER_MAJORVERSION, VER_GREATER_EQUAL),
78 | VER_MINORVERSION, VER_GREATER_EQUAL),
79 | VER_BUILDNUMBER, VER_GREATER_EQUAL);
80 |
81 | for (const auto& win10ver : win10versions) {
82 | osvi.dwBuildNumber = win10ver.buildNumber;
83 | if (VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER, dwlConditionMask) != FALSE) {
84 | return win10ver.version;
85 | }
86 | }
87 |
88 | if (IsWindows8Point1OrGreater()) {
89 | return L"8.1";
90 | }
91 | if (IsWindows8OrGreater()) {
92 | return L"8";
93 | }
94 | if (IsWindows7SP1OrGreater()) {
95 | return L"7 SP1";
96 | }
97 | if (IsWindows7OrGreater()) {
98 | return L"7";
99 | }
100 | return L"Vista or older";
101 | }
102 |
103 | bool IsWindows11_24H2OrGreater()
104 | {
105 | static auto ret = IsWindows11OrGreater(26100);
106 | return ret;
107 | }
108 |
109 | LPCWSTR GetWindowsVersion()
110 | {
111 | static LPCWSTR winver = GetWinVer();
112 | return winver;
113 | }
114 |
115 | std::wstring HR2Str(const HRESULT hr)
116 | {
117 | std::wstring str;
118 | #define UNPACK_VALUE(VALUE) case VALUE: str = L#VALUE; break;
119 | #define UNPACK_HR_WIN32(VALUE) case (((VALUE) & 0x0000FFFF) | (FACILITY_WIN32 << 16) | 0x80000000): str = L#VALUE; break;
120 | switch (hr) {
121 | // Common HRESULT Values https://learn.microsoft.com/en-us/windows/win32/seccrypto/common-hresult-values
122 | UNPACK_VALUE(S_OK);
123 | #ifdef _WINERROR_
124 | UNPACK_VALUE(S_FALSE);
125 | UNPACK_VALUE(E_NOTIMPL);
126 | UNPACK_VALUE(E_NOINTERFACE);
127 | UNPACK_VALUE(E_POINTER);
128 | UNPACK_VALUE(E_ABORT);
129 | UNPACK_VALUE(E_FAIL);
130 | UNPACK_VALUE(E_UNEXPECTED);
131 | UNPACK_VALUE(E_ACCESSDENIED);
132 | UNPACK_VALUE(E_HANDLE);
133 | UNPACK_VALUE(E_OUTOFMEMORY);
134 | UNPACK_VALUE(E_INVALIDARG);
135 | // some COM Error Codes (Generic) https://learn.microsoft.com/en-us/windows/win32/com/com-error-codes-1
136 | UNPACK_VALUE(REGDB_E_CLASSNOTREG);
137 | // some COM Error Codes (UI, Audio, DirectX, Codec) https://learn.microsoft.com/en-us/windows/win32/com/com-error-codes-10
138 | UNPACK_VALUE(DXGI_STATUS_OCCLUDED);
139 | UNPACK_VALUE(DXGI_STATUS_MODE_CHANGED);
140 | UNPACK_VALUE(DXGI_ERROR_INVALID_CALL);
141 | UNPACK_VALUE(DXGI_ERROR_DEVICE_REMOVED);
142 | UNPACK_VALUE(DXGI_ERROR_DEVICE_RESET);
143 | UNPACK_VALUE(DXGI_ERROR_SDK_COMPONENT_MISSING);
144 | UNPACK_VALUE(WINCODEC_ERR_COMPONENTNOTFOUND);
145 | UNPACK_VALUE(WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT);
146 | UNPACK_VALUE(WINCODEC_ERR_PROPERTYUNEXPECTEDTYPE);
147 | // some System Error Codes https://learn.microsoft.com/en-us/windows/win32/debug/system-error-codes
148 | UNPACK_HR_WIN32(ERROR_GEN_FAILURE);
149 | UNPACK_HR_WIN32(ERROR_NOT_SUPPORTED);
150 | UNPACK_HR_WIN32(ERROR_INSUFFICIENT_BUFFER);
151 | UNPACK_HR_WIN32(ERROR_MOD_NOT_FOUND);
152 | UNPACK_HR_WIN32(ERROR_INVALID_WINDOW_HANDLE);
153 | UNPACK_HR_WIN32(ERROR_CLASS_ALREADY_EXISTS);
154 | #endif
155 | #ifdef _MFERROR_H
156 | UNPACK_VALUE(MF_E_INVALIDMEDIATYPE);
157 | UNPACK_VALUE(MF_E_INVALID_FORMAT);
158 | #endif
159 | #ifdef _D3D9_H_
160 | // some D3DERR values https://learn.microsoft.com/en-us/windows/win32/direct3d9/d3derr
161 | UNPACK_VALUE(S_PRESENT_OCCLUDED);
162 | UNPACK_VALUE(S_PRESENT_MODE_CHANGED);
163 | UNPACK_VALUE(D3DERR_DEVICEHUNG);
164 | UNPACK_VALUE(D3DERR_DEVICELOST);
165 | UNPACK_VALUE(D3DERR_DEVICENOTRESET);
166 | UNPACK_VALUE(D3DERR_DEVICEREMOVED);
167 | UNPACK_VALUE(D3DERR_DRIVERINTERNALERROR);
168 | UNPACK_VALUE(D3DERR_INVALIDCALL);
169 | UNPACK_VALUE(D3DERR_OUTOFVIDEOMEMORY);
170 | UNPACK_VALUE(D3DERR_WASSTILLDRAWING);
171 | UNPACK_VALUE(D3DERR_NOTAVAILABLE);
172 | #endif
173 | default:
174 | str = std::format(L"{:#010x}", (uint32_t)hr);
175 | };
176 | #undef UNPACK_VALUE
177 | #undef UNPACK_HR_WIN32
178 | return str;
179 | }
180 |
181 | HRESULT GetDataFromResource(LPVOID& data, DWORD& size, UINT resid)
182 | {
183 | static const HMODULE hModule = (HMODULE)&__ImageBase;
184 |
185 | HRSRC hrsrc = FindResourceW(hModule, MAKEINTRESOURCEW(resid), L"FILE");
186 | if (!hrsrc) {
187 | return E_INVALIDARG;
188 | }
189 | HGLOBAL hGlobal = LoadResource(hModule, hrsrc);
190 | if (!hGlobal) {
191 | return E_FAIL;
192 | }
193 | size = SizeofResource(hModule, hrsrc);
194 | if (!size) {
195 | return E_FAIL;
196 | }
197 | data = LockResource(hGlobal);
198 | if (!data) {
199 | return E_FAIL;
200 | }
201 |
202 | return S_OK;
203 | }
204 |
205 | // https://learn.microsoft.com/en-us/visualstudio/debugger/how-to-set-a-thread-name-in-native-code
206 | //
207 | // Usage: SetThreadName ((DWORD)-1, "MainThread");
208 | //
209 | const DWORD MS_VC_EXCEPTION = 0x406D1388;
210 | #pragma pack(push,8)
211 | typedef struct tagTHREADNAME_INFO
212 | {
213 | DWORD dwType; // Must be 0x1000.
214 | LPCSTR szName; // Pointer to name (in user addr space).
215 | DWORD dwThreadID; // Thread ID (-1=caller thread).
216 | DWORD dwFlags; // Reserved for future use, must be zero.
217 | } THREADNAME_INFO;
218 | #pragma pack(pop)
219 | void SetThreadName(DWORD dwThreadID, const char* threadName) {
220 | THREADNAME_INFO info;
221 | info.dwType = 0x1000;
222 | info.szName = threadName;
223 | info.dwThreadID = dwThreadID;
224 | info.dwFlags = 0;
225 | #pragma warning(push)
226 | #pragma warning(disable: 6320 6322)
227 | __try {
228 | RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info);
229 | }
230 | __except (EXCEPTION_EXECUTE_HANDLER) {
231 | }
232 | #pragma warning(pop)
233 | }
234 |
--------------------------------------------------------------------------------
/Source/Utils/Util.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2020-2024 v0lt, Aleksoid
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #pragma once
22 |
23 | #ifndef FCC
24 | #define FCC(ch4) ((((DWORD)(ch4) & 0xFF) << 24) | \
25 | (((DWORD)(ch4) & 0xFF00) << 8) | \
26 | (((DWORD)(ch4) & 0xFF0000) >> 8) | \
27 | (((DWORD)(ch4) & 0xFF000000) >> 24))
28 | #endif
29 |
30 | #ifndef DEFINE_MEDIATYPE_GUID
31 | #define DEFINE_MEDIATYPE_GUID(name, format) \
32 | DEFINE_GUID(name, \
33 | format, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
34 | #endif
35 |
36 | template
37 | inline void DebugLogFmt(std::wstring_view format, Args&& ...args)
38 | {
39 | DbgLogInfo(LOG_TRACE, 3, std::vformat(format, std::make_wformat_args(args...)).c_str());
40 | }
41 |
42 | #ifdef _DEBUG
43 | #define DLog(...) DebugLogFmt(__VA_ARGS__)
44 | #define DLogIf(f,...) {if (f) DebugLogFmt(__VA_ARGS__);}
45 | #else
46 | #define DLog(...) __noop
47 | #define DLogIf(f,...) __noop
48 | #endif
49 |
50 | #define SAFE_RELEASE(p) { if (p) { (p)->Release(); (p) = nullptr; } }
51 | #define SAFE_CLOSE_HANDLE(p) { if (p) { if ((p) != INVALID_HANDLE_VALUE) ASSERT(CloseHandle(p)); (p) = nullptr; } }
52 | #define SAFE_DELETE(p) { if (p) { delete (p); (p) = nullptr; } }
53 |
54 | #define QI(i) (riid == __uuidof(i)) ? GetInterface((i*)this, ppv) :
55 | #define IFQIRETURN(i) if (riid == __uuidof(i)) { return GetInterface((i*)this, ppv); }
56 |
57 | #define ALIGN(x, a) __ALIGN_MASK(x,(decltype(x))(a)-1)
58 | #define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask))
59 |
60 | // Media subtypes
61 | DEFINE_MEDIATYPE_GUID(MEDIASUBTYPE_Y8, 0x20203859);
62 | DEFINE_MEDIATYPE_GUID(MEDIASUBTYPE_Y800, 0x30303859);
63 | DEFINE_MEDIATYPE_GUID(MEDIASUBTYPE_Y16, 0x10003159); // Y1[0][16]
64 | DEFINE_MEDIATYPE_GUID(MEDIASUBTYPE_YV16, 0x36315659);
65 | DEFINE_MEDIATYPE_GUID(MEDIASUBTYPE_YV24, 0x34325659);
66 | DEFINE_MEDIATYPE_GUID(MEDIASUBTYPE_I420, 0x30323449); // from "wmcodecdsp.h"
67 | DEFINE_MEDIATYPE_GUID(MEDIASUBTYPE_Y42B, 0x42323459);
68 | DEFINE_MEDIATYPE_GUID(MEDIASUBTYPE_444P, 0x50343434);
69 | DEFINE_MEDIATYPE_GUID(MEDIASUBTYPE_Y210, 0x30313259);
70 | DEFINE_MEDIATYPE_GUID(MEDIASUBTYPE_Y216, 0x36313259);
71 | DEFINE_MEDIATYPE_GUID(MEDIASUBTYPE_Y410, 0x30313459);
72 | DEFINE_MEDIATYPE_GUID(MEDIASUBTYPE_Y416, 0x36313459);
73 | DEFINE_MEDIATYPE_GUID(MEDIASUBTYPE_YUV444P16, 0x10003359); // Y3[0][16]
74 | DEFINE_MEDIATYPE_GUID(MEDIASUBTYPE_RGB48, 0x30424752); // RGB[48] (RGB0)
75 | DEFINE_MEDIATYPE_GUID(MEDIASUBTYPE_BGR48, 0x30524742); // BGR[48] (BGR0)
76 | DEFINE_MEDIATYPE_GUID(MEDIASUBTYPE_BGRA64, 0x40415242); // BRA[64] (BRA@)
77 | DEFINE_MEDIATYPE_GUID(MEDIASUBTYPE_b48r, 0x72383462);
78 | DEFINE_MEDIATYPE_GUID(MEDIASUBTYPE_b64a, 0x61343662);
79 | DEFINE_MEDIATYPE_GUID(MEDIASUBTYPE_r210, 0x30313272);
80 | DEFINE_GUID(MEDIASUBTYPE_LAV_RAWVIDEO, 0xd80fa03c, 0x35c1, 0x4fa1, 0x8c, 0x8e, 0x37, 0x5c, 0x86, 0x67, 0x16, 0x6e);
81 |
82 | // non-standard values for Transfer Matrix
83 | #define VIDEOTRANSFERMATRIX_FCC 6
84 | #define VIDEOTRANSFERMATRIX_YCgCo 7
85 |
86 | template
87 | // If the specified value is out of range, set to default values.
88 | inline T discard(T const& val, T const& def, T const& lo, T const& hi)
89 | {
90 | return (val > hi || val < lo) ? def : val;
91 | }
92 |
93 | template
94 | inline T round_pow2(T number, T pow2)
95 | {
96 | ASSERT(pow2 > 0);
97 | ASSERT(!(pow2 & (pow2 - 1)));
98 | --pow2;
99 | if (number < 0) {
100 | return (number - pow2) & ~pow2;
101 | } else {
102 | return (number + pow2) & ~pow2;
103 | }
104 | }
105 |
106 | [[nodiscard]] bool IsWindows11_24H2OrGreater();
107 | LPCWSTR GetWindowsVersion();
108 |
109 | inline std::wstring GUIDtoWString(const GUID& guid)
110 | {
111 | std::wstring str(39, 0);
112 | int ret = StringFromGUID2(guid, &str[0], 39);
113 | if (ret) {
114 | str.resize(ret - 1);
115 | } else {
116 | str.clear();
117 | }
118 | return str;
119 | }
120 |
121 | std::wstring HR2Str(const HRESULT hr);
122 |
123 | HRESULT GetDataFromResource(LPVOID& data, DWORD& size, UINT resid);
124 |
125 | // Usage: SetThreadName ((DWORD)-1, "MainThread");
126 | void SetThreadName(DWORD dwThreadID, const char* threadName);
127 |
--------------------------------------------------------------------------------
/Source/VUIOptions.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020-2024 v0lt
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-only
5 | */
6 |
7 | #include "stdafx.h"
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include "Helper.h"
13 | #include "VUIOptions.h"
14 |
15 | // Rec. ITU-T H.264
16 | // https://www.itu.int/itu-t/recommendations/rec.aspx?rec=14659
17 |
18 | bool SetColorInfoFromFrameFrops(UINT& extFmtValue, const char* keyName, int64_t value)
19 | {
20 | DXVA2_ExtendedFormat exFmt;
21 | exFmt.value = extFmtValue;
22 |
23 | if (strcmp(keyName, "_ChromaLocation") == 0) {
24 | // 0=left, 1=center, 2=topleft, 3=top, 4=bottomleft, 5=bottom.
25 | switch (value) {
26 | case 0: exFmt.VideoChromaSubsampling = DXVA2_VideoChromaSubsampling_MPEG2; break;
27 | case 1: exFmt.VideoChromaSubsampling = DXVA2_VideoChromaSubsampling_MPEG1; break;
28 | case 2: exFmt.VideoChromaSubsampling = DXVA2_VideoChromaSubsampling_Cosited; break;
29 | }
30 | }
31 | else if (strcmp(keyName, "_ColorRange") == 0) {
32 | // 0=full range, 1=limited range
33 | switch (value) {
34 | case 0: exFmt.NominalRange = DXVA2_NominalRange_0_255; break;
35 | case 1: exFmt.NominalRange = DXVA2_NominalRange_16_235; break;
36 | }
37 | }
38 | else if (strcmp(keyName, "_Primaries") == 0) {
39 | switch (value) {
40 | case 1: exFmt.VideoPrimaries = DXVA2_VideoPrimaries_BT709; break;
41 | case 4: exFmt.VideoPrimaries = DXVA2_VideoPrimaries_BT470_2_SysM; break;
42 | case 5: exFmt.VideoPrimaries = DXVA2_VideoPrimaries_BT470_2_SysBG; break;
43 | case 6: exFmt.VideoPrimaries = DXVA2_VideoPrimaries_SMPTE170M; break;
44 | case 7: exFmt.VideoPrimaries = DXVA2_VideoPrimaries_SMPTE240M; break;
45 | case 9: exFmt.VideoPrimaries = MFVideoPrimaries_BT2020; break;
46 | case 10: exFmt.VideoPrimaries = MFVideoPrimaries_XYZ; break;
47 | case 11: exFmt.VideoPrimaries = MFVideoPrimaries_DCI_P3; break;
48 | }
49 | }
50 | else if (strcmp(keyName, "_Matrix") == 0) {
51 | switch (value) {
52 | case 1: exFmt.VideoTransferMatrix = DXVA2_VideoTransferMatrix_BT709; break;
53 | case 4: exFmt.VideoTransferMatrix = VIDEOTRANSFERMATRIX_FCC; break;
54 | case 5:
55 | case 6: exFmt.VideoTransferMatrix = DXVA2_VideoTransferMatrix_BT601; break;
56 | case 7: exFmt.VideoTransferMatrix = DXVA2_VideoTransferMatrix_SMPTE240M; break;
57 | case 8: exFmt.VideoTransferMatrix = VIDEOTRANSFERMATRIX_YCgCo; break;
58 | case 10:
59 | case 11: exFmt.VideoTransferMatrix = MFVideoTransferMatrix_BT2020_10; break;
60 | }
61 | }
62 | else if (strcmp(keyName, "_Transfer") == 0) {
63 | switch (value) {
64 | case 1:
65 | case 6:
66 | case 14:
67 | case 15: exFmt.VideoTransferFunction = DXVA2_VideoTransFunc_709; break;
68 | case 4: exFmt.VideoTransferFunction = DXVA2_VideoTransFunc_22; break;
69 | case 5: exFmt.VideoTransferFunction = DXVA2_VideoTransFunc_28; break;
70 | case 7: exFmt.VideoTransferFunction = DXVA2_VideoTransFunc_240M; break;
71 | case 8: exFmt.VideoTransferFunction = DXVA2_VideoTransFunc_10; break;
72 | case 9: exFmt.VideoTransferFunction = MFVideoTransFunc_Log_100; break;
73 | case 10: exFmt.VideoTransferFunction = MFVideoTransFunc_Log_316; break;
74 | case 16: exFmt.VideoTransferFunction = MFVideoTransFunc_2084; break;
75 | case 18: exFmt.VideoTransferFunction = MFVideoTransFunc_HLG; break;
76 | }
77 | }
78 |
79 | if (exFmt.value != extFmtValue) {
80 | extFmtValue = exFmt.value;
81 | return true;
82 | }
83 | else {
84 | return false;
85 | }
86 | }
87 |
88 | /*
89 | "Video Usability Info" https://code.videolan.org/videolan/x264/-/blob/master/x264.c
90 |
91 | --range Specify color range
92 | auto, tv, pc
93 |
94 | --colorprim Specify color primaries
95 | undef, bt709, bt470m, bt470bg, smpte170m,
96 | smpte240m, film, bt2020, smpte428,
97 | smpte431, smpte432
98 |
99 | --transfer Specify transfer characteristics
100 | undef, bt709, bt470m, bt470bg, smpte170m,
101 | smpte240m, linear, log100, log316,
102 | iec61966-2-4, bt1361e, iec61966-2-1,
103 | bt2020-10, bt2020-12, smpte2084, smpte428,
104 | arib-std-b67
105 |
106 | --colormatrix Specify color matrix setting
107 | undef, bt709, fcc, bt470bg, smpte170m,
108 | smpte240m, GBR, YCgCo, bt2020nc, bt2020c,
109 | smpte2085, chroma-derived-nc,
110 | chroma-derived-c, ICtCp
111 |
112 | --chromaloc Specify chroma sample location (0 to 5)
113 | 0 - Left(MPEG-2)
114 | 1 - Center(MPEG-1)
115 | 2 - TopLeft(Co-sited)
116 | */
117 |
118 | struct str_value {
119 | LPCSTR str;
120 | UINT value;
121 | };
122 |
123 | static const str_value vui_range[] {
124 | { "tv", DXVA2_NominalRange_16_235 },
125 | { "pc", DXVA2_NominalRange_0_255 },
126 | };
127 |
128 | static const str_value vui_colorprim[] {
129 | { "bt709", DXVA2_VideoPrimaries_BT709 },
130 | { "bt470m", DXVA2_VideoPrimaries_BT470_2_SysM },
131 | { "bt470bg", DXVA2_VideoPrimaries_BT470_2_SysBG },
132 | { "smpte170m", DXVA2_VideoPrimaries_SMPTE170M },
133 | { "smpte240m", DXVA2_VideoPrimaries_SMPTE240M },
134 | { "bt2020", MFVideoPrimaries_BT2020 },
135 | };
136 |
137 | static const str_value vui_transfer[] {
138 | { "bt709", DXVA2_VideoTransFunc_709 },
139 | { "bt470m", DXVA2_VideoTransFunc_22 },
140 | { "bt470bg", DXVA2_VideoTransFunc_28 },
141 | { "smpte170m", DXVA2_VideoTransFunc_709 },
142 | { "smpte240m", DXVA2_VideoTransFunc_240M },
143 | { "linear", DXVA2_VideoTransFunc_10 },
144 | { "log100", MFVideoTransFunc_Log_100 },
145 | { "log316", MFVideoTransFunc_Log_316 },
146 | { "smpte2084", MFVideoTransFunc_2084 },
147 | { "arib-std-b67", MFVideoTransFunc_HLG },
148 | };
149 |
150 | static const str_value vui_colormatrix[] {
151 | { "bt709", DXVA2_VideoTransferMatrix_BT709 },
152 | { "fcc", VIDEOTRANSFERMATRIX_FCC },
153 | { "bt470bg", DXVA2_VideoTransferMatrix_BT601 },
154 | { "smpte240m", DXVA2_VideoTransferMatrix_SMPTE240M },
155 | { "YCgCo", VIDEOTRANSFERMATRIX_YCgCo },
156 | { "bt2020nc", MFVideoTransferMatrix_BT2020_10 },
157 | { "bt2020c", MFVideoTransferMatrix_BT2020_10 },
158 | };
159 |
160 | static const str_value vui_chromaloc[] {
161 | { "0", DXVA2_VideoChromaSubsampling_MPEG2 },
162 | { "1", DXVA2_VideoChromaSubsampling_MPEG1 },
163 | { "2", DXVA2_VideoChromaSubsampling_Cosited },
164 | };
165 |
166 | bool SetColorInfoFromVUIOptions(UINT& extFmtValue, LPCWSTR scriptfile)
167 | {
168 | DXVA2_ExtendedFormat exFmt;
169 | exFmt.value = extFmtValue;
170 |
171 | std::string vui_options;
172 | std::ifstream scrypt(scriptfile);
173 |
174 | if (scrypt.is_open()) {
175 | const std::string vui_prefix("# $VUI:");
176 | std::string line;
177 | while (std::getline(scrypt, line)) {
178 | // looking for the last line of VUI options
179 | if (line.compare(0, vui_prefix.size(), vui_prefix) == 0) {
180 | vui_options = line.substr(vui_prefix.size());
181 | }
182 | }
183 | scrypt.close();
184 | }
185 |
186 | std::vector tokens;
187 | str_split(vui_options, tokens, ' ');
188 |
189 | if (tokens.size() >= 2) {
190 | unsigned i = 0;
191 | while (i+1 < tokens.size()) {
192 | const auto& param = tokens[i];
193 | const auto& value = tokens[i+1];
194 | if (param == "--range") {
195 | for (const auto& item : vui_range) {
196 | if (value == item.str) {
197 | exFmt.NominalRange = item.value;
198 | i++;
199 | break;
200 | }
201 | }
202 | }
203 | else if (param == "--colorprim") {
204 | for (const auto& item : vui_colorprim) {
205 | if (value == item.str) {
206 | exFmt.VideoPrimaries = item.value;
207 | i++;
208 | break;
209 | }
210 | }
211 | }
212 | else if (param == "--transfer") {
213 | for (const auto& item : vui_transfer) {
214 | if (value == item.str) {
215 | exFmt.VideoTransferFunction = item.value;
216 | i++;
217 | break;
218 | }
219 | }
220 | }
221 | else if (param == "--colormatrix") {
222 | for (const auto& item : vui_colormatrix) {
223 | if (value == item.str) {
224 | exFmt.VideoTransferMatrix = item.value;
225 | i++;
226 | break;
227 | }
228 | }
229 | }
230 | else if (param == "--chromaloc") {
231 | for (const auto& item : vui_chromaloc) {
232 | if (value == item.str) {
233 | exFmt.VideoChromaSubsampling = item.value;
234 | i++;
235 | break;
236 | }
237 | }
238 | }
239 | i++;
240 | }
241 | }
242 |
243 | if (exFmt.value != extFmtValue) {
244 | extFmtValue = exFmt.value;
245 | return true;
246 | }
247 | else {
248 | return false;
249 | }
250 | }
251 |
--------------------------------------------------------------------------------
/Source/VUIOptions.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020-2024 v0lt
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-only
5 | */
6 |
7 | #pragma once
8 |
9 | bool SetColorInfoFromFrameFrops(UINT& extFmtValue, const char* keyName, int64_t value);
10 |
11 | bool SetColorInfoFromVUIOptions(UINT& extFmtValue, LPCWSTR scriptfile);
12 |
--------------------------------------------------------------------------------
/Source/VapourSynthStream.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020-2024 v0lt
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-only
5 | */
6 |
7 | #pragma once
8 |
9 | #ifndef VSSCRIPT_H
10 | #include "../Include/VSScript4.h"
11 | #endif
12 | #include "Helper.h"
13 |
14 | //
15 | // CVapourSynthFile
16 | //
17 |
18 | class CVapourSynthFile
19 | {
20 | friend class CVapourSynthVideoStream;
21 | friend class CVapourSynthAudioStream;
22 |
23 | HMODULE m_hVSScriptDll = nullptr;
24 |
25 | const VSAPI* m_vsAPI = nullptr;
26 | const VSSCRIPTAPI* m_vsScriptAPI = nullptr;
27 | VSScript* m_vsScript = nullptr;
28 | VSNode* m_vsNodeVideo = nullptr;
29 | VSNode* m_vsNodeAudio = nullptr;
30 |
31 | std::wstring m_FileInfo;
32 |
33 | void SetVSNodes();
34 |
35 | public:
36 | CVapourSynthFile(const WCHAR* filepath, CSource* pParent, HRESULT* phr);
37 | ~CVapourSynthFile();
38 |
39 | std::wstring_view GetInfo() { return m_FileInfo; }
40 | };
41 |
42 | //
43 | // CVapourSynthVideoStream
44 | //
45 |
46 | class CVapourSynthVideoStream
47 | : public CSourceStream
48 | , public CSourceSeeking
49 | {
50 | private:
51 | CCritSec m_cSharedState;
52 |
53 | const CVapourSynthFile* m_pVapourSynthFile;
54 |
55 | const VSVideoInfo* m_vsVideoInfo = nullptr;
56 | int m_Planes[4] = { 0, 1, 2, 3 };
57 |
58 | std::unique_ptr m_BitmapError;
59 |
60 | REFERENCE_TIME m_AvgTimePerFrame = 0;
61 | int m_FrameCounter = 0;
62 | int m_CurrentFrame = 0;
63 |
64 | BOOL m_bDiscontinuity = FALSE;
65 | BOOL m_bFlushing = FALSE;
66 |
67 | FmtParams_t m_Format = {};
68 | UINT m_Width = 0;
69 | UINT m_Height = 0;
70 | UINT m_Pitch = 0;
71 | UINT m_PitchBuff = 0;
72 | UINT m_BufferSize = 0;
73 |
74 | UINT m_ColorInfo = 0;
75 | struct {
76 | int64_t num = 0;
77 | int64_t den = 0;
78 | } m_Sar;
79 |
80 | int m_NumFrames = 0;
81 | int64_t m_fpsNum = 1;
82 | int64_t m_fpsDen = 1;
83 |
84 | char m_vsErrorMessage[1024] = {};
85 | std::wstring m_StreamInfo;
86 |
87 | public:
88 | CVapourSynthVideoStream(CVapourSynthFile* pVapourSynthFile, CSource* pParent, HRESULT* phr);
89 | virtual ~CVapourSynthVideoStream();
90 |
91 | STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv) override;
92 |
93 | std::wstring_view GetInfo() { return m_StreamInfo; }
94 |
95 | private:
96 | HRESULT OnThreadCreate() override;
97 | HRESULT OnThreadStartPlay() override;
98 |
99 | void UpdateFromSeek();
100 |
101 | // IMediaSeeking
102 | STDMETHODIMP SetRate(double dRate) override;
103 |
104 | HRESULT ChangeStart() override;
105 | HRESULT ChangeStop() override;
106 | HRESULT ChangeRate() override { return S_OK; }
107 |
108 | void InitVideoMediaType();
109 |
110 | public:
111 | HRESULT DecideBufferSize(IMemAllocator* pIMemAlloc, ALLOCATOR_PROPERTIES* pProperties) override;
112 | HRESULT FillBuffer(IMediaSample* pSample) override;
113 | HRESULT CheckMediaType(const CMediaType* pMediaType) override;
114 | HRESULT SetMediaType(const CMediaType* pMediaType) override;
115 | HRESULT GetMediaType(int iPosition, CMediaType* pmt) override;
116 |
117 | // IQualityControl
118 | STDMETHODIMP Notify(IBaseFilter* pSender, Quality q) override { return E_NOTIMPL; }
119 | };
120 |
121 | //
122 | // CVapourSynthAudioStream
123 | //
124 |
125 | class CVapourSynthAudioStream
126 | : public CSourceStream
127 | , public CSourceSeeking
128 | {
129 | private:
130 | CCritSec m_cSharedState;
131 |
132 | const CVapourSynthFile* m_pVapourSynthFile;
133 |
134 | const VSAudioInfo* m_vsAudioInfo = nullptr;
135 |
136 | BOOL m_bDiscontinuity = FALSE;
137 | BOOL m_bFlushing = FALSE;
138 |
139 | GUID m_Subtype = {};
140 | int m_Channels = 0;
141 | int m_SampleRate = 0;
142 | int m_BytesPerSample = 0; // for all audio channels
143 | int m_BitDepth = 0;
144 | VSSampleType m_SampleType = {};
145 |
146 | int m_FrameSamples = 0;
147 | int m_NumFrames = 0;
148 | int64_t m_NumSamples = 0;
149 |
150 | int m_FrameCounter = 0;
151 | int m_CurrentFrame = 0;
152 |
153 | char m_vsErrorMessage[1024] = {};
154 | std::wstring m_StreamInfo;
155 |
156 | public:
157 | CVapourSynthAudioStream(CVapourSynthFile* pVapourSynthFile, CSource* pParent, HRESULT* phr);
158 | virtual ~CVapourSynthAudioStream();
159 |
160 | STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv) override;
161 |
162 | std::wstring_view GetInfo() { return m_StreamInfo; }
163 |
164 | private:
165 | HRESULT OnThreadCreate() override;
166 | HRESULT OnThreadStartPlay() override;
167 | void UpdateFromSeek();
168 |
169 | // IMediaSeeking
170 | STDMETHODIMP SetRate(double dRate) override;
171 |
172 | HRESULT ChangeStart() override;
173 | HRESULT ChangeStop() override;
174 | HRESULT ChangeRate() override { return S_OK; }
175 |
176 | public:
177 | HRESULT DecideBufferSize(IMemAllocator* pIMemAlloc, ALLOCATOR_PROPERTIES* pProperties) override;
178 | HRESULT FillBuffer(IMediaSample* pSample) override;
179 | HRESULT CheckMediaType(const CMediaType* pMediaType) override;
180 | HRESULT SetMediaType(const CMediaType* pMediaType) override;
181 | HRESULT GetMediaType(int iPosition, CMediaType* pmt) override;
182 |
183 | // IQualityControl
184 | STDMETHODIMP Notify(IBaseFilter* pSender, Quality q) override { return E_NOTIMPL; }
185 | };
186 |
--------------------------------------------------------------------------------
/Source/dllmain.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020-2024 v0lt
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-only
5 | */
6 |
7 | #include "stdafx.h"
8 | #include
9 | #include "ScriptSource.h"
10 | #include "PropPage.h"
11 |
12 | template
13 | static CUnknown* WINAPI CreateInstance(LPUNKNOWN lpunk, HRESULT* phr)
14 | {
15 | *phr = S_OK;
16 | CUnknown* punk = new(std::nothrow) T(lpunk, phr);
17 | if (punk == nullptr) {
18 | *phr = E_OUTOFMEMORY;
19 | }
20 | return punk;
21 | }
22 |
23 | const AMOVIESETUP_PIN sudpPins[] = {
24 | {(LPWSTR)L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, nullptr, 0, nullptr},
25 | };
26 |
27 | const AMOVIESETUP_FILTER sudFilter[] = {
28 | {&__uuidof(CScriptSource), L"MPC Script Source", MERIT_NORMAL, (UINT)std::size(sudpPins), sudpPins, CLSID_LegacyAmFilterCategory},
29 | };
30 |
31 | CFactoryTemplate g_Templates[] = {
32 | {sudFilter[0].strName, sudFilter[0].clsID, CreateInstance, nullptr, &sudFilter[0]},
33 | {L"InfoProp", &__uuidof(CSSInfoPPage), CreateInstance, nullptr, nullptr},
34 | };
35 |
36 | int g_cTemplates = (int)std::size(g_Templates);
37 |
38 | STDAPI DllRegisterServer()
39 | {
40 | return AMovieDllRegisterServer2(TRUE);
41 | }
42 |
43 | STDAPI DllUnregisterServer()
44 | {
45 | LPCWSTR strGuid = _CRT_WIDE(STR_CLSID_ScriptSource);
46 | DWORD type;
47 | WCHAR data[40];
48 | DWORD cbData;
49 |
50 | HKEY hKey;
51 | LONG ec = ::RegOpenKeyExW(HKEY_CLASSES_ROOT, L"Media Type\\Extensions\\.avs", 0, KEY_ALL_ACCESS, &hKey);
52 | if (ec == ERROR_SUCCESS) {
53 | ec = RegQueryValueExW(hKey, L"Source Filter", nullptr, &type, (LPBYTE)data, &cbData);
54 | if (ec == ERROR_SUCCESS && type == REG_SZ && _wcsicmp(strGuid, data) == 0) {
55 | RegDeleteValueW(hKey, L"Source Filter");
56 | }
57 | ::RegCloseKey(hKey);
58 | }
59 |
60 | ec = ::RegOpenKeyExW(HKEY_CLASSES_ROOT, L"Media Type\\Extensions\\.vpy", 0, KEY_ALL_ACCESS, &hKey);
61 | if (ec == ERROR_SUCCESS) {
62 | ec = RegQueryValueExW(hKey, L"Source Filter", nullptr, &type, (LPBYTE)data, &cbData);
63 | if (ec == ERROR_SUCCESS && type == REG_SZ && _wcsicmp(strGuid, data) == 0) {
64 | RegDeleteValueW(hKey, L"Source Filter");
65 | }
66 | ::RegCloseKey(hKey);
67 | }
68 |
69 | return AMovieDllRegisterServer2(FALSE);
70 | }
71 |
72 | extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
73 |
74 | BOOL WINAPI DllMain(HINSTANCE hDllHandle, DWORD dwReason, LPVOID pReserved)
75 | {
76 | return DllEntryPoint(hDllHandle, dwReason, pReserved);
77 | }
78 |
--------------------------------------------------------------------------------
/Source/res/MpcScriptSource.rc2:
--------------------------------------------------------------------------------
1 | //
2 | // MpcScriptSource.rc2 - resources Microsoft Visual C++ does not edit directly
3 | //
4 |
5 | #ifdef APSTUDIO_INVOKED
6 | #error this file is not editable by Microsoft Visual C++
7 | #endif //APSTUDIO_INVOKED
8 |
9 |
10 | /////////////////////////////////////////////////////////////////////////////
11 | // Add manually edited resources here...
12 |
13 | /////////////////////////////////////////////////////////////////////////////
14 |
15 | #include "../../Include/Version.h"
16 |
17 |
18 | /////////////////////////////////////////////////////////////////////////////
19 | //
20 | // FILE
21 | //
22 |
23 |
24 | /////////////////////////////////////////////////////////////////////////////
25 | //
26 | // Version
27 | //
28 |
29 | VS_VERSION_INFO VERSIONINFO
30 | FILEVERSION VERSION_NUM
31 | PRODUCTVERSION VERSION_NUM
32 | FILEFLAGSMASK 0x17L
33 | #ifdef _DEBUG
34 | FILEFLAGS 0x1L
35 | #else
36 | FILEFLAGS 0x0L
37 | #endif
38 | FILEOS 0x4L
39 | FILETYPE 0x2L
40 | FILESUBTYPE 0x0L
41 | BEGIN
42 | BLOCK "StringFileInfo"
43 | BEGIN
44 | BLOCK "040904b0"
45 | BEGIN
46 | VALUE "CompanyName", "MPC-BE Team"
47 | VALUE "FileDescription", "MPC Script Source"
48 | VALUE "FileVersion", VERSION_STR
49 | VALUE "InternalName", "ScriptSource"
50 | VALUE "LegalCopyright", "Copyright 2020-2024"
51 | #ifdef _WIN64
52 |
53 | VALUE "OriginalFilename", "MpcScriptSource64.ax"
54 | #else
55 | VALUE "OriginalFilename", "MpcScriptSource.ax"
56 | #endif
57 | VALUE "ProductName", "MPC Script Source"
58 | VALUE "ProductVersion", VERSION_STR
59 | END
60 | END
61 | BLOCK "VarFileInfo"
62 | BEGIN
63 | VALUE "Translation", 0x409, 1200
64 | END
65 | END
66 |
--------------------------------------------------------------------------------
/Source/resource.h:
--------------------------------------------------------------------------------
1 | //{{NO_DEPENDENCIES}}
2 | // Microsoft Visual C++ generated include file.
3 | // Used by MpcScriptSource.rc
4 | //
5 | #define IDD_MAINPROPPAGE 102
6 | #define IDD_INFOPROPPAGE 103
7 | #define IDS_MAINPROPPAGE_TITLE 104
8 | #define IDS_INFOPROPPAGE_TITLE 105
9 | #define IDC_STATIC1 1001
10 | #define IDC_STATIC2 1002
11 | #define IDC_STATIC3 1003
12 | #define IDC_CHECK1 1004
13 | #define IDC_CHECK2 1005
14 | #define IDC_CHECK3 1006
15 | #define IDC_CHECK4 1007
16 | #define IDC_CHECK5 1008
17 | #define IDC_CHECK6 1009
18 | #define IDC_CHECK7 1010
19 | #define IDC_CHECK8 1011
20 | #define IDC_CHECK9 1012
21 | #define IDC_CHECK10 1013
22 | #define IDC_CHECK11 1014
23 | #define IDC_CHECK12 1015
24 | #define IDC_COMBO1 1016
25 | #define IDC_COMBO2 1017
26 | #define IDC_COMBO3 1018
27 | #define IDC_COMBO4 1019
28 | #define IDC_COMBO5 1020
29 | #define IDC_EDIT1 1021
30 | #define IDC_EDIT2 1022
31 | #define IDC_EDIT3 1023
32 | #define IDC_BUTTON1 1024
33 | #define IDC_SLIDER1 1025
34 | #define IDC_SLIDER2 1026
35 |
36 | // Next default values for new objects
37 | //
38 | #ifdef APSTUDIO_INVOKED
39 | #ifndef APSTUDIO_READONLY_SYMBOLS
40 | #define _APS_NEXT_RESOURCE_VALUE 104
41 | #define _APS_NEXT_COMMAND_VALUE 40001
42 | #define _APS_NEXT_CONTROL_VALUE 1026
43 | #define _APS_NEXT_SYMED_VALUE 101
44 | #endif
45 | #endif
46 |
--------------------------------------------------------------------------------
/Source/stdafx.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020-2024 v0lt
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-only
5 | */
6 |
7 | #include "stdafx.h"
8 |
9 | #pragma comment(lib, "winmm.lib")
10 |
--------------------------------------------------------------------------------
/Source/stdafx.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020-2024 v0lt
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-only
5 | */
6 |
7 | #pragma once
8 |
9 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
10 | #define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
11 |
12 | #include
13 | #include
14 |
15 | #include
16 | #include
17 | #include
18 |
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 |
26 | #include "../external/BaseClasses/streams.h"
27 |
--------------------------------------------------------------------------------
/build_scriptsource.cmd:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 | REM Copyright (C) 2020-2024 v0lt
3 | REM
4 | REM SPDX-License-Identifier: LGPL-2.1-only
5 |
6 | SETLOCAL ENABLEDELAYEDEXPANSION
7 | CD /D %~dp0
8 |
9 | SET "TITLE=MPC Script Source"
10 | SET "PROJECT=MpcScriptSource"
11 |
12 | SET "MSBUILD_SWITCHES=/nologo /consoleloggerparameters:Verbosity=minimal /maxcpucount /nodeReuse:true"
13 | SET "BUILDTYPE=Build"
14 | SET "BUILDCFG=Release"
15 | SET "SUFFIX="
16 | SET "SIGN=False"
17 |
18 | FOR %%A IN (%*) DO (
19 | IF /I "%%A" == "Debug" (
20 | SET "BUILDCFG=Debug"
21 | SET "SUFFIX=_Debug"
22 | )
23 | IF /I "%%A" == "Sign" (
24 | SET "SIGN=True"
25 | )
26 | IF /I "%%A" == "VS2019" (
27 | SET "COMPILER=VS2019"
28 | )
29 | IF /I "%%A" == "VS2022" (
30 | SET "COMPILER=VS2022"
31 | )
32 | )
33 |
34 | IF /I "%SIGN%" == "True" (
35 | IF NOT EXIST "%~dp0signinfo.txt" (
36 | CALL :SubMsg "WARNING" "signinfo.txt not found."
37 | SET "SIGN=False"
38 | )
39 | )
40 |
41 | CALL :SubVSPath
42 | SET "TOOLSET=%VS_PATH%\Common7\Tools\vsdevcmd"
43 |
44 | SET "LOG_DIR=_bin\logs"
45 | IF NOT EXIST "%LOG_DIR%" MD "%LOG_DIR%"
46 |
47 | CALL "%TOOLSET%" -arch=x86
48 | REM again set the source directory (fix possible bug in VS2017)
49 | CD /D %~dp0
50 | CALL :SubCompiling x86
51 |
52 | CALL "%TOOLSET%" -arch=amd64
53 | REM again set the source directory (fix possible bug in VS2017)
54 | CD /D %~dp0
55 | CALL :SubCompiling x64
56 |
57 | IF /I "%SIGN%" == "True" (
58 | SET FILES="%~dp0_bin\Filter_x86%SUFFIX%\%PROJECT%.ax" "%~dp0_bin\Filter_x64%SUFFIX%\%PROJECT%64.ax"
59 | CALL "%~dp0\sign.cmd" %%FILES%%
60 | IF %ERRORLEVEL% NEQ 0 (
61 | CALL :SubMsg "ERROR" "Problem signing files."
62 | ) ELSE (
63 | CALL :SubMsg "INFO" "Files signed successfully."
64 | )
65 | )
66 |
67 | FOR /F "tokens=3,4 delims= " %%A IN (
68 | 'FINDSTR /I /L /C:"define VER_MAJOR" "Include\Version.h"') DO (SET "VERMAJOR=%%A")
69 | FOR /F "tokens=3,4 delims= " %%A IN (
70 | 'FINDSTR /I /L /C:"define VER_MINOR" "Include\Version.h"') DO (SET "VERMINOR=%%A")
71 | FOR /F "tokens=3,4 delims= " %%A IN (
72 | 'FINDSTR /I /L /C:"define VER_BUILD" "Include\Version.h"') DO (SET "VERBUILD=%%A")
73 | FOR /F "tokens=3,4 delims= " %%A IN (
74 | 'FINDSTR /I /L /C:"define VER_RELEASE" "Include\Version.h"') DO (SET "VERRELEASE=%%A")
75 | FOR /F "tokens=3,4 delims= " %%A IN (
76 | 'FINDSTR /I /L /C:"define REV_DATE" "revision.h"') DO (SET "REVDATE=%%A")
77 | FOR /F "tokens=3,4 delims= " %%A IN (
78 | 'FINDSTR /I /L /C:"define REV_HASH" "revision.h"') DO (SET "REVHASH=%%A")
79 | FOR /F "tokens=3,4 delims= " %%A IN (
80 | 'FINDSTR /I /L /C:"define REV_NUM" "revision.h"') DO (SET "REVNUM=%%A")
81 | FOR /F "tokens=3,4 delims= " %%A IN (
82 | 'FINDSTR /I /L /C:"define REV_BRANCH" "revision.h"') DO (SET "REVBRANCH=%%A")
83 |
84 | IF /I "%VERRELEASE%" == "1" (
85 | SET "PCKG_NAME=%PROJECT%-%VERMAJOR%.%VERMINOR%.%VERBUILD%.%REVNUM%%SUFFIX%"
86 | ) ELSE (
87 | IF /I "%REVBRANCH%" == "master" (
88 | SET "PCKG_NAME=%PROJECT%-%VERMAJOR%.%VERMINOR%.%VERBUILD%.%REVNUM%_git%REVDATE%-%REVHASH%%SUFFIX%"
89 | ) ELSE (
90 | SET "PCKG_NAME=%PROJECT%-%VERMAJOR%.%VERMINOR%.%VERBUILD%.%REVNUM%.%REVBRANCH%_git%REVDATE%-%REVHASH%%SUFFIX%"
91 | )
92 | )
93 |
94 | CALL :SubDetectSevenzipPath
95 | IF DEFINED SEVENZIP (
96 | IF EXIST "_bin\%PCKG_NAME%.zip" DEL "_bin\%PCKG_NAME%.zip"
97 |
98 | TITLE Creating archive %PCKG_NAME%.zip...
99 | START "7z" /B /WAIT "%SEVENZIP%" a -tzip -mx9 "_bin\%PCKG_NAME%.zip" ^
100 | .\_bin\Filter_x86%SUFFIX%\%PROJECT%.ax ^
101 | .\_bin\Filter_x64%SUFFIX%\%PROJECT%64.ax ^
102 | .\distrib\Install_MpcScriptSource_32.cmd ^
103 | .\distrib\Install_MpcScriptSource_64.cmd ^
104 | .\distrib\Uninstall_MpcScriptSource_32.cmd ^
105 | .\distrib\Uninstall_MpcScriptSource_64.cmd ^
106 | .\distrib\Reset_Settings.cmd ^
107 | .\Readme.md ^
108 | .\history.txt ^
109 | .\LICENSE.txt
110 | IF %ERRORLEVEL% NEQ 0 CALL :SubMsg "ERROR" "Unable to create %PCKG_NAME%.zip!"
111 | CALL :SubMsg "INFO" "%PCKG_NAME%.zip successfully created"
112 | )
113 |
114 | TITLE Compiling %TITLE% [FINISHED]
115 | TIMEOUT /T 3
116 | ENDLOCAL
117 | EXIT
118 |
119 | :SubVSPath
120 | SET "PARAMS=-property installationPath -requires Microsoft.Component.MSBuild"
121 | IF /I "%COMPILER%" == "VS2019" (
122 | SET "PARAMS=%PARAMS% -version [16.0,17.0)"
123 | ) ELSE IF /I "%COMPILER%" == "VS2022" (
124 | SET "PARAMS=%PARAMS% -version [17.0,18.0)"
125 | ) ELSE (
126 | SET "PARAMS=%PARAMS% -latest"
127 | )
128 | SET "VSWHERE="%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" %PARAMS%"
129 | FOR /f "delims=" %%A IN ('!VSWHERE!') DO SET VS_PATH=%%A
130 | EXIT /B
131 |
132 | :SubDetectSevenzipPath
133 | FOR %%G IN (7z.exe) DO (SET "SEVENZIP_PATH=%%~$PATH:G")
134 | IF EXIST "%SEVENZIP_PATH%" (SET "SEVENZIP=%SEVENZIP_PATH%" & EXIT /B)
135 |
136 | FOR %%G IN (7za.exe) DO (SET "SEVENZIP_PATH=%%~$PATH:G")
137 | IF EXIST "%SEVENZIP_PATH%" (SET "SEVENZIP=%SEVENZIP_PATH%" & EXIT /B)
138 |
139 | FOR /F "tokens=2*" %%A IN (
140 | 'REG QUERY "HKLM\SOFTWARE\7-Zip" /v "Path" 2^>NUL ^| FIND "REG_SZ" ^|^|
141 | REG QUERY "HKLM\SOFTWARE\Wow6432Node\7-Zip" /v "Path" 2^>NUL ^| FIND "REG_SZ"') DO SET "SEVENZIP=%%B\7z.exe"
142 | EXIT /B
143 |
144 | :SubCompiling
145 | TITLE Compiling %TITLE% - %BUILDCFG%^|%1...
146 | MSBuild.exe %PROJECT%.sln %MSBUILD_SWITCHES%^
147 | /target:%BUILDTYPE% /p:Configuration="%BUILDCFG%" /p:Platform=%1^
148 | /flp1:LogFile=%LOG_DIR%\errors_%BUILDCFG%_%1.log;errorsonly;Verbosity=diagnostic^
149 | /flp2:LogFile=%LOG_DIR%\warnings_%BUILDCFG%_%1.log;warningsonly;Verbosity=diagnostic
150 | IF %ERRORLEVEL% NEQ 0 (
151 | CALL :SubMsg "ERROR" "%PROJECT%.sln %BUILDCFG% %1 - Compilation failed!"
152 | ) ELSE (
153 | CALL :SubMsg "INFO" "%PROJECT%.sln %BUILDCFG% %1 compiled successfully"
154 | )
155 | EXIT /B
156 |
157 | :SubMsg
158 | ECHO. & ECHO ------------------------------
159 | IF /I "%~1" == "ERROR" (
160 | CALL :SubColorText "0C" "[%~1]" & ECHO %~2
161 | ) ELSE IF /I "%~1" == "INFO" (
162 | CALL :SubColorText "0A" "[%~1]" & ECHO %~2
163 | ) ELSE IF /I "%~1" == "WARNING" (
164 | CALL :SubColorText "0E" "[%~1]" & ECHO %~2
165 | )
166 | ECHO ------------------------------ & ECHO.
167 | IF /I "%~1" == "ERROR" (
168 | ECHO Press any key to close this window...
169 | PAUSE >NUL
170 | ENDLOCAL
171 | EXIT
172 | ) ELSE (
173 | EXIT /B
174 | )
175 |
176 | :SubColorText
177 | FOR /F "tokens=1,2 delims=#" %%A IN (
178 | '"PROMPT #$H#$E# & ECHO ON & FOR %%B IN (1) DO REM"') DO (
179 | SET "DEL=%%A")
180 | "%~2"
181 | FINDSTR /v /a:%1 /R ".18" "%~2" NUL
182 | DEL "%~2" > NUL 2>&1
183 | EXIT /B
--------------------------------------------------------------------------------
/common.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $(SolutionDir)_bin\obj\$(Configuration)_$(PlatformShortName)\$(ProjectName)\
5 | $(SolutionDir)_bin\lib\$(Configuration)_$(PlatformShortName)\
6 | $(SolutionDir)_bin\Filter_$(PlatformShortName)_Debug\
7 | $(SolutionDir)_bin\Filter_$(PlatformShortName)\
8 | true
9 | false
10 |
11 |
12 |
13 | /Zo /Zc:throwingNew /Zc:rvalueCast %(AdditionalOptions)
14 | true
15 | 4244; 4838; 26451
16 | 4267;%(DisableSpecificWarnings)
17 | Sync
18 | true
19 | stdcpp20
20 | true
21 | NOMINMAX;_WINDOWS;WINDOWS;WINVER=0x0601;_WIN32_WINNT=0x0601;_USRDLL;__STDC_CONSTANT_MACROS;%(PreprocessorDefinitions)
22 | WIN32;%(PreprocessorDefinitions)
23 | _WIN64;WIN64;%(PreprocessorDefinitions)
24 | Level3
25 |
26 |
27 | MachineX86
28 | MachineX64
29 |
30 |
31 | true
32 | Debug
33 | true
34 | Windows
35 | MachineX86
36 | MachineX64
37 |
38 |
39 | 0x0409
40 | WIN32;%(PreprocessorDefinitions)
41 | _WIN64;%(PreprocessorDefinitions)
42 |
43 |
44 |
45 |
46 | EnableFastChecks
47 | EditAndContinue
48 | ProgramDatabase
49 | Disabled
50 | MultiThreadedDebug
51 |
52 |
53 | _DEBUG;%(PreprocessorDefinitions)
54 |
55 |
56 | false
57 | DebugFastLink
58 |
59 |
60 |
61 |
62 | /Zc:inline %(AdditionalOptions)
63 | ProgramDatabase
64 | AnySuitable
65 | true
66 | Speed
67 | false
68 | MaxSpeed
69 | _CRT_SECURE_NO_WARNINGS;NDEBUG;%(PreprocessorDefinitions)
70 | MultiThreaded
71 | true
72 | true
73 |
74 |
75 | true
76 |
77 |
78 | true
79 | true
80 | UseFastLinkTimeCodeGeneration
81 | .rdata=.text
82 | true
83 | true
84 |
85 |
86 | NDEBUG;%(PreprocessorDefinitions)
87 |
88 |
89 |
--------------------------------------------------------------------------------
/distrib/Install_MpcScriptSource_32.cmd:
--------------------------------------------------------------------------------
1 | @cd /d "%~dp0"
2 | @regsvr32.exe MpcScriptSource.ax /s
3 | @if %errorlevel% NEQ 0 goto error
4 | :success
5 | @echo.
6 | @echo.
7 | @echo Installation succeeded.
8 | @echo.
9 | @echo Please do not delete the MpcScriptSource.ax file.
10 | @echo The installer has not copied the files anywhere.
11 | @echo.
12 | @goto done
13 | :error
14 | @echo.
15 | @echo.
16 | @echo Installation failed.
17 | @echo.
18 | @echo You need to right click "Install_MPCScriptSource_32.cmd" and choose "run as admin".
19 | @echo.
20 | :done
21 | @pause >NUL
22 |
--------------------------------------------------------------------------------
/distrib/Install_MpcScriptSource_64.cmd:
--------------------------------------------------------------------------------
1 | @cd /d "%~dp0"
2 | @regsvr32.exe MpcScriptSource64.ax /s
3 | @if %errorlevel% NEQ 0 goto error
4 | :success
5 | @echo.
6 | @echo.
7 | @echo Installation succeeded.
8 | @echo.
9 | @echo Please do not delete the MpcScriptSource64.ax file.
10 | @echo The installer has not copied the files anywhere.
11 | @echo.
12 | @goto done
13 | :error
14 | @echo.
15 | @echo.
16 | @echo Installation failed.
17 | @echo.
18 | @echo You need to right click "Install_MpcScriptSource_64.cmd" and choose "run as admin".
19 | @echo.
20 | :done
21 | @pause >NUL
22 |
--------------------------------------------------------------------------------
/distrib/Reset_Settings.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 | echo.
3 | echo.
4 | title Restore MPC Script Source default settings...
5 | start /min reg delete "HKEY_CURRENT_USER\Software\MPC-BE Filters\MPC Script Source" /f
6 | echo settings were reset to default
7 | echo.
8 | pause >NUL
9 |
--------------------------------------------------------------------------------
/distrib/Uninstall_MpcScriptSource_32.cmd:
--------------------------------------------------------------------------------
1 | @cd /d "%~dp0"
2 | @regsvr32.exe MpcScriptSource.ax /u /s
3 | @if %errorlevel% NEQ 0 goto error
4 | :success
5 | @echo.
6 | @echo.
7 | @echo Uninstallation succeeded.
8 | @echo.
9 | @goto done
10 | :error
11 | @echo.
12 | @echo.
13 | @echo Uninstallation failed.
14 | @echo.
15 | @echo You need to right click "Uninstall_MpcScriptSource_32.cmd" and choose "run as admin".
16 | @echo.
17 | :done
18 | @pause >NUL
19 |
--------------------------------------------------------------------------------
/distrib/Uninstall_MpcScriptSource_64.cmd:
--------------------------------------------------------------------------------
1 | @cd /d "%~dp0"
2 | @regsvr32.exe MpcScriptSource64.ax /u /s
3 | @if %errorlevel% NEQ 0 goto error
4 | :success
5 | @echo.
6 | @echo.
7 | @echo Uninstallation succeeded.
8 | @echo.
9 | @goto done
10 | :error
11 | @echo.
12 | @echo.
13 | @echo Uninstallation failed.
14 | @echo.
15 | @echo You need to right click "Uninstall_MpcScriptSource_64.cmd" and choose "run as admin".
16 | @echo.
17 | :done
18 | @pause >NUL
19 |
--------------------------------------------------------------------------------
/external/BaseClasses.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Debug
10 | x64
11 |
12 |
13 | Release
14 | Win32
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}
23 | BaseClasses
24 | Win32Proj
25 | BaseClasses
26 |
27 |
28 |
29 |
30 | StaticLibrary
31 | Unicode
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | _LIB;%(PreprocessorDefinitions)
43 | Use
44 | streams.h
45 |
46 |
47 | strmiids.lib
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 | Create
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
--------------------------------------------------------------------------------
/external/BaseClasses.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hpp;hxx;hm;inl;inc;xsd
11 |
12 |
13 |
14 |
15 | Header Files
16 |
17 |
18 | Header Files
19 |
20 |
21 | Header Files
22 |
23 |
24 | Header Files
25 |
26 |
27 | Header Files
28 |
29 |
30 | Header Files
31 |
32 |
33 | Header Files
34 |
35 |
36 | Header Files
37 |
38 |
39 | Header Files
40 |
41 |
42 | Header Files
43 |
44 |
45 | Header Files
46 |
47 |
48 | Header Files
49 |
50 |
51 | Header Files
52 |
53 |
54 | Header Files
55 |
56 |
57 | Header Files
58 |
59 |
60 | Header Files
61 |
62 |
63 | Header Files
64 |
65 |
66 | Header Files
67 |
68 |
69 | Header Files
70 |
71 |
72 | Header Files
73 |
74 |
75 | Header Files
76 |
77 |
78 | Header Files
79 |
80 |
81 | Header Files
82 |
83 |
84 | Header Files
85 |
86 |
87 | Header Files
88 |
89 |
90 | Header Files
91 |
92 |
93 | Header Files
94 |
95 |
96 | Header Files
97 |
98 |
99 | Header Files
100 |
101 |
102 | Header Files
103 |
104 |
105 | Header Files
106 |
107 |
108 | Header Files
109 |
110 |
111 | Header Files
112 |
113 |
114 | Header Files
115 |
116 |
117 | Header Files
118 |
119 |
120 | Header Files
121 |
122 |
123 | Header Files
124 |
125 |
126 | Header Files
127 |
128 |
129 |
130 |
131 | Source Files
132 |
133 |
134 | Source Files
135 |
136 |
137 | Source Files
138 |
139 |
140 | Source Files
141 |
142 |
143 | Source Files
144 |
145 |
146 | Source Files
147 |
148 |
149 | Source Files
150 |
151 |
152 | Source Files
153 |
154 |
155 | Source Files
156 |
157 |
158 | Source Files
159 |
160 |
161 | Source Files
162 |
163 |
164 | Source Files
165 |
166 |
167 | Source Files
168 |
169 |
170 | Source Files
171 |
172 |
173 | Source Files
174 |
175 |
176 | Source Files
177 |
178 |
179 | Source Files
180 |
181 |
182 | Source Files
183 |
184 |
185 | Source Files
186 |
187 |
188 | Source Files
189 |
190 |
191 | Source Files
192 |
193 |
194 | Source Files
195 |
196 |
197 | Source Files
198 |
199 |
200 | Source Files
201 |
202 |
203 | Source Files
204 |
205 |
206 | Source Files
207 |
208 |
209 | Source Files
210 |
211 |
212 | Source Files
213 |
214 |
215 | Source Files
216 |
217 |
218 | Source Files
219 |
220 |
221 | Source Files
222 |
223 |
224 | Source Files
225 |
226 |
227 | Source Files
228 |
229 |
230 |
--------------------------------------------------------------------------------
/history.txt:
--------------------------------------------------------------------------------
1 | 0.2.7.192 - 2024-04-03
2 | -----------------------
3 | Fixed registration of a filter from a folder with Unicode characters.
4 |
5 | 0.2.5.183 - 2024-12-13
6 | -----------------------
7 | Fixed support for YV12, YV16, YV24 formats for AviSynth+.
8 |
9 | 0.2.3.174 - 2024-11-05
10 | -----------------------
11 | Fixed display of video frame with error in AviSynth script.
12 | Fixed opening VapourSynth scripts without sound.
13 | Added support for Y10 (Gray10) format.
14 |
15 | 0.2.1.165 - 2024-08-18
16 | -----------------------
17 | The license has been changed to LGPL-2.1.
18 | Added audio support for AviSynth+ and VapourSynth scripts.
19 | ScriptSourceFilter will not show a video with an error if it cannot connect to AviSynth+ or VapourSynth. This will allow the player to try other filters.
20 | Now uses VapourSynth API 4.
21 | Recommended versions are AviSynth+ 3.7.3 or later, VapourSynth R63 or later.
22 |
23 | 0.1.4.128 - 2022-09-21
24 | -----------------------
25 | Added Frame Properties support for AviSynth+ and VapourSynth R59.
26 | Recommended versions are AviSynth+ 3.7.2 or later, VapourSynth R59 or later.
27 |
28 | 0.1.2.106 - 2022-01-05
29 | -----------------------
30 | Removed filter registration for .avs and .vpy extensions. This preserves the ability to open scripts using the "AVI/WAV File Source" system filter. Better solution is to add ScriptSourceFilter as an external filter in MPC-BE, MPC-HC and other players, set the priority as preferred and enable the filter when needed.
31 |
32 | 0.1.0.76 - 2020-06-16
33 | ----------------------
34 | The first official release.
--------------------------------------------------------------------------------
/platform.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 10.0.17763.0
5 | v141
6 |
7 |
8 | 10.0
9 | v142
10 |
11 |
12 | 10.0
13 | v143
14 |
15 |
--------------------------------------------------------------------------------
/sign.cmd:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 | REM (C) 2015-2019 see Authors.txt
3 | REM
4 | REM This file is part of MPC-BE.
5 | REM
6 | REM MPC-BE is free software; you can redistribute it and/or modify
7 | REM it under the terms of the GNU General Public License as published by
8 | REM the Free Software Foundation; either version 3 of the License, or
9 | REM (at your option) any later version.
10 | REM
11 | REM MPC-BE is distributed in the hope that it will be useful,
12 | REM but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | REM MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | REM GNU General Public License for more details.
15 | REM
16 | REM You should have received a copy of the GNU General Public License
17 | REM along with this program. If not, see .
18 |
19 | SETLOCAL
20 |
21 | IF "%~1" == "" (
22 | ECHO %~nx0: No input file specified!
23 | GOTO END
24 | )
25 |
26 | IF NOT EXIST "%~dp0signinfo.txt" (
27 | ECHO %~nx0: %~dp0signinfo.txt is not present!
28 | GOTO END
29 | )
30 |
31 | IF NOT DEFINED VCVARS (
32 | FOR /f "delims=" %%A IN ('"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -property installationPath -requires Microsoft.Component.MSBuild Microsoft.VisualStudio.Component.VC.ATLMFC Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -latest') DO SET "VCVARS=%%A\Common7\Tools\vsdevcmd.bat"
33 | )
34 |
35 | IF NOT EXIST "%VCVARS%" (
36 | ECHO ERROR: "Visual Studio environment variable(s) is missing - possible it's not installed on your PC"
37 | GOTO END
38 | )
39 |
40 | CALL "%VCVARS%" -no_logo -arch=x86
41 |
42 | TITLE Signing "%*"...
43 | ECHO. & ECHO Signing "%*"...
44 |
45 | FOR /F "delims=" %%A IN (%~dp0signinfo.txt) DO (SET "SIGN_CMD=%%A" && CALL :SIGN %*)
46 |
47 | :END
48 | ENDLOCAL
49 | EXIT /B %ERRORLEVEL%
50 |
51 | :SIGN
52 | FOR /L %%i IN (1,1,5) DO (
53 | IF %%i GTR 1 ECHO %%i attempt
54 | signtool.exe sign %SIGN_CMD% %*
55 | IF %ERRORLEVEL% EQU 0 EXIT /B %ERRORLEVEL%
56 | )
57 |
--------------------------------------------------------------------------------
/update_revision.cmd:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 | SETLOCAL
3 | CD /D %~dp0
4 |
5 | ECHO #pragma once > revision.h
6 |
7 | SET gitexe="git.exe"
8 | %gitexe% --version
9 | IF /I %ERRORLEVEL%==0 GOTO :GitOK
10 |
11 | SET gitexe="c:\Program Files\Git\cmd\git.exe"
12 | IF NOT EXIST %gitexe% set gitexe="c:\Program Files\Git\bin\git.exe"
13 | IF NOT EXIST %gitexe% GOTO :END
14 |
15 | :GitOK
16 |
17 | %gitexe% log -1 --date=format:%%Y.%%m.%%d --pretty=format:"#define REV_DATE %%ad%%n" >> revision.h
18 | %gitexe% log -1 --pretty=format:"#define REV_HASH %%h%%n" >> revision.h
19 |
20 | > revision.h
21 | %gitexe% symbolic-ref --short HEAD >> revision.h
22 | IF %ERRORLEVEL% NEQ 0 (
23 | ECHO LOCAL >> revision.h
24 | )
25 |
26 | > revision.h
27 | %gitexe% rev-list --count HEAD >> revision.h
28 | IF %ERRORLEVEL% NEQ 0 (
29 | ECHO 0 >> revision.h
30 | )
31 |
32 | :END
33 | ENDLOCAL
34 | EXIT /B
35 |
--------------------------------------------------------------------------------