├── InputPipeMain ├── InputPipeMain.h ├── small.ico ├── MainDlg.cpp ├── InputPipeMain.rc ├── InputPipeMain.ico ├── targetver.h ├── framework.h ├── cpp.hint ├── Resource.h ├── MainDlg.h ├── InputPipeMain.vcxproj.filters ├── InputPipeMain.vcxproj └── InputPipeMain.cpp ├── Share ├── IPC.cpp ├── IPC.h ├── Common.h ├── Common.cpp ├── Logger.cpp ├── PluginWrapper.cpp ├── PluginWrapper.h ├── CodeConvert.h ├── Logger.h ├── CodeConvert.cpp └── ptreeWrapper.h ├── InputPipePlugin ├── input.def ├── input.h ├── pch.cpp ├── framework.h ├── pch.h ├── dllmain.cpp ├── InputPipePlugin.vcxproj.filters ├── InputPipePlugin.vcxproj └── input.cpp ├── .gitignore ├── InputPipePlugin.sln ├── LICENSE └── Readme.md /InputPipeMain/InputPipeMain.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "resource.h" 4 | -------------------------------------------------------------------------------- /Share/IPC.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amate/InputPipePlugin/HEAD/Share/IPC.cpp -------------------------------------------------------------------------------- /Share/IPC.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amate/InputPipePlugin/HEAD/Share/IPC.h -------------------------------------------------------------------------------- /Share/Common.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amate/InputPipePlugin/HEAD/Share/Common.h -------------------------------------------------------------------------------- /Share/Common.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amate/InputPipePlugin/HEAD/Share/Common.cpp -------------------------------------------------------------------------------- /Share/Logger.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amate/InputPipePlugin/HEAD/Share/Logger.cpp -------------------------------------------------------------------------------- /InputPipeMain/small.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amate/InputPipePlugin/HEAD/InputPipeMain/small.ico -------------------------------------------------------------------------------- /InputPipePlugin/input.def: -------------------------------------------------------------------------------- 1 | LIBRARY InputPipePlugin 2 | 3 | EXPORTS 4 | GetInputPluginTable @1 5 | 6 | -------------------------------------------------------------------------------- /InputPipePlugin/input.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amate/InputPipePlugin/HEAD/InputPipePlugin/input.h -------------------------------------------------------------------------------- /Share/PluginWrapper.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amate/InputPipePlugin/HEAD/Share/PluginWrapper.cpp -------------------------------------------------------------------------------- /Share/PluginWrapper.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amate/InputPipePlugin/HEAD/Share/PluginWrapper.h -------------------------------------------------------------------------------- /InputPipeMain/MainDlg.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amate/InputPipePlugin/HEAD/InputPipeMain/MainDlg.cpp -------------------------------------------------------------------------------- /InputPipeMain/InputPipeMain.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amate/InputPipePlugin/HEAD/InputPipeMain/InputPipeMain.rc -------------------------------------------------------------------------------- /InputPipeMain/InputPipeMain.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amate/InputPipePlugin/HEAD/InputPipeMain/InputPipeMain.ico -------------------------------------------------------------------------------- /InputPipePlugin/pch.cpp: -------------------------------------------------------------------------------- 1 | // pch.cpp: プリコンパイル済みヘッダーに対応するソース ファイル 2 | 3 | #include "pch.h" 4 | 5 | // プリコンパイル済みヘッダーを使用している場合、コンパイルを成功させるにはこのソース ファイルが必要です。 6 | -------------------------------------------------------------------------------- /InputPipePlugin/framework.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define WIN32_LEAN_AND_MEAN // Windows ヘッダーからほとんど使用されていない部分を除外する 4 | // Windows ヘッダー ファイル 5 | #include 6 | -------------------------------------------------------------------------------- /Share/CodeConvert.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #include 5 | 6 | namespace CodeConvert 7 | { 8 | std::string ShiftJISfromUTF16(const std::wstring& utf16); 9 | std::wstring UTF16fromShiftJIS(const std::string& sjis); 10 | 11 | } // namespace 12 | -------------------------------------------------------------------------------- /InputPipeMain/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // // SDKDDKVer.h をインクルードすると、利用できる最も高いレベルの Windows プラットフォームが定義されます。 4 | // 以前の Windows プラットフォーム用にアプリケーションをビルドする場合は、WinSDKVer.h をインクルードし、 5 | // サポートしたいプラットフォームに _WIN32_WINNT マクロを設定してから SDKDDKVer.h をインクルードします。 6 | #include 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | *.user 3 | *.aps 4 | *.pch 5 | *.vspscc 6 | *_i.c 7 | *_p.c 8 | *.ncb 9 | *.suo 10 | *.bak 11 | *.cache 12 | *.ilk 13 | *.log 14 | [Bb]in 15 | [Dd]ebug*/ 16 | *.sbr 17 | obj/ 18 | [Rr]elease*/ 19 | _ReSharper*/ 20 | 21 | /.vs/ 22 | /aviutl100/ 23 | /PipeList/ 24 | -------------------------------------------------------------------------------- /InputPipeMain/framework.h: -------------------------------------------------------------------------------- 1 | // header.h : 標準のシステム インクルード ファイルのインクルード ファイル、 2 | // またはプロジェクト専用のインクルード ファイル 3 | // 4 | 5 | #pragma once 6 | 7 | #include "targetver.h" 8 | #define WIN32_LEAN_AND_MEAN // Windows ヘッダーからほとんど使用されていない部分を除外する 9 | // Windows ヘッダー ファイル 10 | #include 11 | // C ランタイム ヘッダー ファイル 12 | #include 13 | #include 14 | #include 15 | #include 16 | -------------------------------------------------------------------------------- /InputPipePlugin/pch.h: -------------------------------------------------------------------------------- 1 | // pch.h: プリコンパイル済みヘッダー ファイルです。 2 | // 次のファイルは、その後のビルドのビルド パフォーマンスを向上させるため 1 回だけコンパイルされます。 3 | // コード補完や多くのコード参照機能などの IntelliSense パフォーマンスにも影響します。 4 | // ただし、ここに一覧表示されているファイルは、ビルド間でいずれかが更新されると、すべてが再コンパイルされます。 5 | // 頻繁に更新するファイルをここに追加しないでください。追加すると、パフォーマンス上の利点がなくなります。 6 | 7 | #ifndef PCH_H 8 | #define PCH_H 9 | 10 | // プリコンパイルするヘッダーをここに追加します 11 | #include "framework.h" 12 | 13 | #endif //PCH_H 14 | -------------------------------------------------------------------------------- /InputPipePlugin/dllmain.cpp: -------------------------------------------------------------------------------- 1 | // dllmain.cpp : DLL アプリケーションのエントリ ポイントを定義します。 2 | #include "pch.h" 3 | 4 | HMODULE g_hModule = NULL; 5 | 6 | BOOL APIENTRY DllMain( HMODULE hModule, 7 | DWORD ul_reason_for_call, 8 | LPVOID lpReserved 9 | ) 10 | { 11 | switch (ul_reason_for_call) 12 | { 13 | case DLL_PROCESS_ATTACH: 14 | g_hModule = hModule; 15 | case DLL_THREAD_ATTACH: 16 | case DLL_THREAD_DETACH: 17 | case DLL_PROCESS_DETACH: 18 | break; 19 | } 20 | return TRUE; 21 | } 22 | 23 | -------------------------------------------------------------------------------- /InputPipeMain/cpp.hint: -------------------------------------------------------------------------------- 1 | // ヒント ファイルは、Visual Studio IDE が Visual C++ 識別子を解釈するのに役立ちます 2 | // 関数およびマクロの名前などです。 3 | // 詳細については次を参照してください https://go.microsoft.com/fwlink/?linkid=865984 4 | #define BEGIN_MSG_MAP_EX(theClass) @< 5 | #define END_MSG_MAP() @> 6 | #define BEGIN_DDX_MAP(theClass) @< 7 | #define END_DDX_MAP() @> 8 | #define DECLARE_WND_CLASS_EX(WndClassName, style, bkgnd) static ATL::CWndClassInfo& GetWndClassInfo() { static ATL::CWndClassInfo wc = { { sizeof(WNDCLASSEX), style, StartWindowProc, 0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName, NULL }, NULL, NULL, IDC_ARROW, TRUE, 0, _T("") }; return wc; } 9 | -------------------------------------------------------------------------------- /Share/Logger.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | 5 | #pragma once 6 | 7 | //#define BOOST_USE_WINAPI_VERSION 0x0501 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #define INFO_LOG BOOST_LOG_SEV(my_logger::get(), boost::log::trivial::info) 16 | #define WARN_LOG BOOST_LOG_SEV(my_logger::get(), boost::log::trivial::warning) 17 | #define ERROR_LOG BOOST_LOG_SEV(my_logger::get(), boost::log::trivial::error) 18 | 19 | //#define SYS_LOGFILE "info.log" 20 | std::string LogFileName(); 21 | 22 | //Narrow-char thread-safe logger. 23 | typedef boost::log::sources::wseverity_logger_mt logger_t; 24 | 25 | //declares a global logger with a custom initialization 26 | BOOST_LOG_GLOBAL_LOGGER(my_logger, logger_t) 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /Share/CodeConvert.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include "CodeConvert.h" 4 | #include 5 | 6 | namespace CodeConvert 7 | { 8 | 9 | std::string ShiftJISfromUTF16(const std::wstring & utf16) 10 | { 11 | int requireBytes = ::WideCharToMultiByte(CP_ACP, 0, utf16.c_str(), utf16.length(), nullptr, 0, NULL, NULL); 12 | if (requireBytes > 0) { 13 | std::string sjis; 14 | sjis.resize(requireBytes); 15 | int ret = ::WideCharToMultiByte(CP_ACP, 0, utf16.c_str(), utf16.length(), (LPSTR)sjis.data(), requireBytes, NULL, NULL); 16 | if (ret > 0) { 17 | return sjis; 18 | } 19 | } 20 | return std::string(); 21 | } 22 | 23 | std::wstring UTF16fromShiftJIS(const std::string& sjis) 24 | { 25 | int requireChars = ::MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, sjis.c_str(), sjis.length(), nullptr, 0); 26 | if (requireChars > 0) { 27 | std::wstring utf16; 28 | utf16.resize(requireChars); 29 | int ret = ::MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, sjis.c_str(), sjis.length(), (LPWSTR)utf16.data(), requireChars); 30 | if (ret > 0) { 31 | return utf16; 32 | } 33 | } 34 | return std::wstring(); 35 | } 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | } // namespace CodeConvert -------------------------------------------------------------------------------- /InputPipeMain/Resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ で生成されたインクルード ファイル。 3 | // InputPipeMain.rc で使用 4 | // 5 | #define IDC_MYICON 2 6 | #define IDOK2 3 7 | #define IDD_INPUTPIPEMAIN_DIALOG 102 8 | #define IDS_APP_TITLE 103 9 | #define IDD_ABOUTBOX 103 10 | #define IDM_ABOUT 104 11 | #define IDM_EXIT 105 12 | #define IDI_INPUTPIPEMAIN 107 13 | #define IDI_SMALL 108 14 | #define IDC_INPUTPIPEMAIN 109 15 | #define IDR_MAINFRAME 128 16 | #define IDD_MAINDLG 129 17 | #define IDC_CHECK_ENABLE_HANDLECACHE 1000 18 | #define IDC_CHECK_ENABLE_IPC 1001 19 | #define IDC_RADIO_NAMEDPIPE 1002 20 | #define IDC_RADIO2 1003 21 | #define IDC_RADIO_SHAREDMEMORY 1003 22 | #define IDC_STATIC -1 23 | 24 | // Next default values for new objects 25 | // 26 | #ifdef APSTUDIO_INVOKED 27 | #ifndef APSTUDIO_READONLY_SYMBOLS 28 | #define _APS_NO_MFC 1 29 | #define _APS_NEXT_RESOURCE_VALUE 130 30 | #define _APS_NEXT_COMMAND_VALUE 32771 31 | #define _APS_NEXT_CONTROL_VALUE 1004 32 | #define _APS_NEXT_SYMED_VALUE 110 33 | #endif 34 | #endif 35 | -------------------------------------------------------------------------------- /Share/ptreeWrapper.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file ptreeWrapper.h 3 | */ 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | namespace fs = boost::filesystem; 16 | fs::path GetExeDirectory(); 17 | 18 | 19 | class ptreeWrapper 20 | { 21 | public: 22 | using wptree = boost::property_tree::wptree; 23 | 24 | static wptree LoadIniPtree(const std::string& fileName) 25 | { 26 | wptree pt; 27 | 28 | fs::path filterPath = GetExeDirectory() / fileName; 29 | std::wifstream fs(filterPath.wstring()); 30 | if (!fs) { 31 | return pt; 32 | } 33 | fs.imbue(std::locale(std::locale(), new std::codecvt_utf8_utf16)); 34 | 35 | try { 36 | boost::property_tree::read_ini(fs, pt); 37 | } 38 | catch (...) { 39 | } 40 | return pt; 41 | } 42 | 43 | static bool SaveIniPtree(const std::string& fileName, const wptree& pt) 44 | { 45 | fs::path filterPath = GetExeDirectory() / fileName; 46 | std::wofstream fs(filterPath.wstring()); 47 | if (!fs) 48 | return false; 49 | fs.imbue(std::locale(std::locale(), new std::codecvt_utf8_utf16)); 50 | 51 | try { 52 | boost::property_tree::write_ini(fs, pt); 53 | } 54 | catch (...) { 55 | return false; 56 | } 57 | return true; 58 | } 59 | 60 | 61 | static wptree BuildPtreeFromText(const std::wstring& text) 62 | { 63 | std::wstringstream ss(text); 64 | wptree pt; 65 | try { 66 | boost::property_tree::read_xml(ss, pt); 67 | } 68 | catch (...) { 69 | 70 | } 71 | return pt; 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 | -------------------------------------------------------------------------------- /InputPipePlugin.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29102.190 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "InputPipePlugin", "InputPipePlugin\InputPipePlugin.vcxproj", "{B752F6B8-D93A-4F10-BFAB-B08C7114D3BF}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "InputPipeMain", "InputPipeMain\InputPipeMain.vcxproj", "{291F3EAA-62CA-43F5-A096-009B7EFABF04}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|x64 = Debug|x64 13 | Debug|x86 = Debug|x86 14 | Release|x64 = Release|x64 15 | Release|x86 = Release|x86 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {B752F6B8-D93A-4F10-BFAB-B08C7114D3BF}.Debug|x64.ActiveCfg = Debug|x64 19 | {B752F6B8-D93A-4F10-BFAB-B08C7114D3BF}.Debug|x64.Build.0 = Debug|x64 20 | {B752F6B8-D93A-4F10-BFAB-B08C7114D3BF}.Debug|x86.ActiveCfg = Debug|Win32 21 | {B752F6B8-D93A-4F10-BFAB-B08C7114D3BF}.Debug|x86.Build.0 = Debug|Win32 22 | {B752F6B8-D93A-4F10-BFAB-B08C7114D3BF}.Release|x64.ActiveCfg = Release|x64 23 | {B752F6B8-D93A-4F10-BFAB-B08C7114D3BF}.Release|x64.Build.0 = Release|x64 24 | {B752F6B8-D93A-4F10-BFAB-B08C7114D3BF}.Release|x86.ActiveCfg = Release|Win32 25 | {B752F6B8-D93A-4F10-BFAB-B08C7114D3BF}.Release|x86.Build.0 = Release|Win32 26 | {291F3EAA-62CA-43F5-A096-009B7EFABF04}.Debug|x64.ActiveCfg = Debug|x64 27 | {291F3EAA-62CA-43F5-A096-009B7EFABF04}.Debug|x64.Build.0 = Debug|x64 28 | {291F3EAA-62CA-43F5-A096-009B7EFABF04}.Debug|x86.ActiveCfg = Debug|Win32 29 | {291F3EAA-62CA-43F5-A096-009B7EFABF04}.Debug|x86.Build.0 = Debug|Win32 30 | {291F3EAA-62CA-43F5-A096-009B7EFABF04}.Release|x64.ActiveCfg = Release|x64 31 | {291F3EAA-62CA-43F5-A096-009B7EFABF04}.Release|x64.Build.0 = Release|x64 32 | {291F3EAA-62CA-43F5-A096-009B7EFABF04}.Release|x86.ActiveCfg = Release|Win32 33 | {291F3EAA-62CA-43F5-A096-009B7EFABF04}.Release|x86.Build.0 = Release|Win32 34 | EndGlobalSection 35 | GlobalSection(SolutionProperties) = preSolution 36 | HideSolutionNode = FALSE 37 | EndGlobalSection 38 | GlobalSection(ExtensibilityGlobals) = postSolution 39 | SolutionGuid = {86DF73F2-5F9C-4CAD-86FA-9588EFF6A323} 40 | EndGlobalSection 41 | EndGlobal 42 | -------------------------------------------------------------------------------- /InputPipeMain/MainDlg.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "resource.h" 4 | 5 | #include 6 | #include 7 | 8 | extern CAppModule _Module; 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | #define _ATL_USE_DDX_FLOAT 17 | #include 18 | #include 19 | 20 | #include "..\Share\Common.h" 21 | 22 | 23 | class CMainDlg : 24 | public CDialogImpl, 25 | public CMessageFilter, 26 | public CIdleHandler, 27 | public CWinDataExchange 28 | { 29 | public: 30 | enum { IDD = IDD_MAINDLG }; 31 | 32 | virtual BOOL PreTranslateMessage(MSG* pMsg) 33 | { 34 | return CWindow::IsDialogMessage(pMsg); 35 | } 36 | 37 | virtual BOOL OnIdle() 38 | { 39 | return FALSE; 40 | } 41 | 42 | BEGIN_DDX_MAP(CMainDlg) 43 | DDX_CHECK(IDC_CHECK_ENABLE_HANDLECACHE, m_config.bEnableHandleCache) 44 | DDX_CHECK(IDC_CHECK_ENABLE_IPC, m_config.bEnableIPC) 45 | DDX_RADIO(IDC_RADIO_NAMEDPIPE, m_radioNamedPipeOrSharedMemory); 46 | END_DDX_MAP() 47 | 48 | BEGIN_MSG_MAP_EX(CMainDlg) 49 | MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) 50 | MESSAGE_HANDLER(WM_DESTROY, OnDestroy) 51 | COMMAND_ID_HANDLER(IDOK, OnOK) 52 | COMMAND_ID_HANDLER(IDCANCEL, OnCancel) 53 | END_MSG_MAP() 54 | 55 | // Handler prototypes (uncomment arguments if needed): 56 | // LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) 57 | // LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) 58 | // LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/) 59 | 60 | LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 61 | LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 62 | 63 | LRESULT OnOK(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 64 | LRESULT OnCancel(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 65 | 66 | void CloseDialog(int nVal); 67 | 68 | private: 69 | Config m_config; 70 | int m_radioNamedPipeOrSharedMemory; 71 | }; 72 | 73 | 74 | #ifdef _UNICODE 75 | #if defined _M_IX86 76 | #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"") 77 | #elif defined _M_X64 78 | #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"") 79 | #else 80 | #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") 81 | #endif 82 | #endif 83 | 84 | -------------------------------------------------------------------------------- /InputPipePlugin/InputPipePlugin.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;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {ce2e929b-cb4f-44f4-9d1c-f90c9a304d46} 18 | 19 | 20 | 21 | 22 | ヘッダー ファイル 23 | 24 | 25 | ヘッダー ファイル 26 | 27 | 28 | ソース ファイル 29 | 30 | 31 | ソース ファイル\Share 32 | 33 | 34 | ソース ファイル\Share 35 | 36 | 37 | ソース ファイル\Share 38 | 39 | 40 | ソース ファイル\Share 41 | 42 | 43 | ソース ファイル\Share 44 | 45 | 46 | 47 | 48 | ソース ファイル 49 | 50 | 51 | ソース ファイル 52 | 53 | 54 | ソース ファイル 55 | 56 | 57 | ソース ファイル\Share 58 | 59 | 60 | ソース ファイル\Share 61 | 62 | 63 | ソース ファイル\Share 64 | 65 | 66 | ソース ファイル\Share 67 | 68 | 69 | ソース ファイル\Share 70 | 71 | 72 | 73 | 74 | リソース ファイル 75 | 76 | 77 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Copyright (C) 2019 amate 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 9 | 10 | ----------------------------------------------------------------------------- 11 | 12 | Copyright (C) 2011-2015 L-SMASH Works project 13 | 14 | Permission to use, copy, modify, and/or distribute this software for any 15 | purpose with or without fee is hereby granted, provided that the above 16 | copyright notice and this permission notice appear in all copies. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 19 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 20 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 21 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 22 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 23 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 24 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 25 | 26 | ----------------------------------------------------------------------------- 27 | 28 | Copyright (C) 2011-2015 L-SMASH Works project 29 | Copyright (C) 1999-2012 Kenkun 30 | 31 | Permission is hereby granted, free of charge, to any person obtaining a copy 32 | of this software and associated documentation files (the "Software"), to deal 33 | in the Software without restriction, including without limitation the rights 34 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 35 | copies of the Software, and to permit persons to whom the Software is 36 | furnished to do so, subject to the following conditions: 37 | 38 | The above copyright notice and this permission notice shall be included in 39 | all copies or substantial portions of the Software. 40 | 41 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 42 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 43 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 44 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 45 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 46 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 47 | THE SOFTWARE. 48 | -------------------------------------------------------------------------------- /InputPipeMain/InputPipeMain.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;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {88e11b15-d252-4910-b42e-ffa9faecb439} 18 | 19 | 20 | 21 | 22 | ヘッダー ファイル 23 | 24 | 25 | ヘッダー ファイル 26 | 27 | 28 | ヘッダー ファイル 29 | 30 | 31 | ヘッダー ファイル 32 | 33 | 34 | ソース ファイル\Share 35 | 36 | 37 | ソース ファイル\Share 38 | 39 | 40 | ソース ファイル\Share 41 | 42 | 43 | ソース ファイル\Share 44 | 45 | 46 | ソース ファイル 47 | 48 | 49 | ソース ファイル\Share 50 | 51 | 52 | ソース ファイル\Share 53 | 54 | 55 | 56 | 57 | ソース ファイル 58 | 59 | 60 | ソース ファイル\Share 61 | 62 | 63 | ソース ファイル\Share 64 | 65 | 66 | ソース ファイル 67 | 68 | 69 | ソース ファイル\Share 70 | 71 | 72 | ソース ファイル\Share 73 | 74 | 75 | ソース ファイル\Share 76 | 77 | 78 | 79 | 80 | リソース ファイル 81 | 82 | 83 | 84 | 85 | リソース ファイル 86 | 87 | 88 | リソース ファイル 89 | 90 | 91 | 92 | 93 | ソース ファイル 94 | 95 | 96 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # InputPipePlugin             2 | 3 | ## ■はじめに 4 | このソフトは、L-SMASH_Works File Reader(lwinput.aui)を別プロセスで実行してあげることによって 5 | aviutlのメモリ使用量削減を目論む、aviutlの入力プラグインです 6 | 7 | ダウンロードはこちらから 8 | https://github.com/amate/InputPipePlugin/releases/latest 9 | 10 | ## ■動作環境 11 | ・Windows 10 home 64bit バージョン 2004 12 | ・AviUtl 1.00 or 1.10 13 | ・拡張編集 0.92 14 | ※ 拡張編集 0.93rc1 はシーン周りに不具合があるので推奨しません 15 | ・L-SMASH Works r935 release2 16 | ・L-SMASH-Works_rev1096_Mr-Ojii_Mr-Ojii_AviUtl 17 | 上記の環境で動作を確認しています 18 | XPではたぶん動きません(コンパイラが対応していないため) 19 | 20 | ## ■導入方法 21 | 22 | https://github.com/amate/InputPipePlugin/releases/latest 23 | 上記リンクから"InputPipePlugin_1.x.zip"をダウンロードして、適当なフォルダに展開します 24 | 25 | lwinput.aui が置いてあるフォルダ(aviutl.exeがあるフォルダ、もしくは "aviutl.exeがあるフォルダ\plugins\"に存在するはず)に、 26 | InputPipePlugin.aui と InputPipeMain.exe をコピーするだけです 27 | 28 | その後、aviutlのメインメニューから、[ファイル]->[環境設定]->[入力プラグイン優先度の設定]を選択し、 29 | "InputPipePlugin"を"L-SMASH Works File Reader"より上にドラッグして移動してあげれば完了です 30 | 31 | ## ■導入の確認 32 | 拡張編集のウィンドウに適当に動画ファイルを放り込んで、"InputPipeMain.exe"のプロセスが立ち上がっていれば成功です 33 | 34 | - 導入が確認できない 35 | 入力プラグイン優先度で、"DirectShow File Reader"がInputPipePluginより上に存在すると動作しないので、InputPipePluginをそれより上に移動させてください 36 | 37 | - aviutlが落ちる 38 | "InputPipePlugin.aui"と"InputPipeMain.exe"が"lwinput.aui"と同じフォルダに存在するか確認してください 39 | "InputPipeMain.exe"を起動してみて、"lwinput.aui が同じフォルダに存在しています!"と表示されれば大丈夫です 40 | もしくは、[InputPipePluginの設定]から[プロセス間通信を有効にする]のチェックを外してください 41 | 42 | ## ■InputPipeMain64.exe について 43 | 44 | 64bit版 L-SMASH_Works File Reader(lwinput64.aui)が InputPipePlugin.aui と同じフォルダ内に存在するとき、そちらを利用するようになります 45 | リリース時に 64bit版L-SMASH_Works File Readerが存在しないので正常に動作するかは不明です 46 | 47 | - 想定している内部仕様について 48 | 49 | 32bitと64bitでは INPUT_INFO や INPUT_HANDLE のサイズが異なりますが、InputPipeMain64.exeが内部で変換してからInputPipePlugin.auiへ伝えるので、lwinput64.aui側で特に何かする必要はありません 50 | 51 | 52 | ## ■設定 53 | [ファイル]->[環境設定]->[入力プラグインの設定]->[InputPipePluginの設定]で 54 | プラグインの設定ができます 55 | 56 | - ハンドルキャッシュを有効 57 | 動画では説明しませんでしたが、編集で同じ動画ファイルのカットを多用するなどの場合、 58 | 拡張編集プラグインが同じ動画に対して毎回ファイルオープンのリクエストを送ってくるので、 59 | いちいちL-SMASH Worksプラグインへ ファイルオープンのリクエストを送らずに、 60 | 一度開いたファイルのハンドルを使いまわすようにする設定です 61 | 62 | ぶっちゃけ外部プロセスなんて使わずに、これにチェック入れるだけでいいんじゃないかなって 63 | 実装した後に気づきました 64 | でも、無駄にはなってないはずです… 65 | 66 | ※ハンドルキャッシュ有効時に、同一ファイル名の動画または音声ファイルが、同じフレームの違うレイヤーで使われている時に問題が発生する 67 | 68 | 別のレイヤーに同じファイルを配置した場合、1フレーム再生する毎に動画や音声のシークが起きて負荷の重い処理が走り、再生や出力がおかしくなる場合がある 69 | 上記の問題を回避するために、"Altキーを押しながら拡張編集のタイムラインウィンドウにメディアファイルをドラッグドロップする"操作によって、ハンドルキャッシュを有効にしていても、ドロップされたファイルのハンドルをキャッシュから使いまわさずに、新しいファイルとしてオープンするようにします 70 | ファイル名の末尾に".[alt_XXXXXXXX]"などが付けば、それは別のファイルとして開かれたことを示します 71 | この機能を使った場合、ドロップされたファイルがあるフォルダに、"ファイル名.[alt_XXXXXXXX].\#junk"というゴミファイルができますが、AviUtl再起動時に、タイムラインに配置したオブジェクトが消えないようにするための処理です 72 | 動画が完成したら申し訳ありませんが、手動で消してください・・・ 73 | 74 | - プロセス間通信を有効にする 75 | デフォルトではオンになってます 76 | 外部プロセスを立ち上げて、その中でlwinput.auiを実行するようにします 77 | 78 | 外部プロセスとの通信はコストがかかるので、重いと感じたらチェック外してください 79 | 80 | - 内部のデータ交換方式 81 | * 名前付きパイプ 82 | v1.4以前の方式です 83 | 84 | * 共有メモリ 85 | v1.5から実装された方式です 86 | 予めデータ用のメモリを確保しておくので、こちらの方が少し高速です 87 | 88 | 設定の保存に失敗するので、AviUtlのフォルダを [C:\Program Files]や[C:\Program Files (x86)]フォルダ内に置かないでください 89 | 90 | ## ■プラグインを入れて不安定になった場合 91 | - 拡張編集の環境設定から、動画ファイルのハンドル数を8から16程度に増やしてみてください 92 | - InputPipePluginの設定から[プロセス間通信を有効にする]のチェックを外してみてください 93 | - 入力プラグインの優先度設定で、"Wave File Reader"を"InputPipePlugin"より上に移動させてみてください 94 | - 動画ファイルがmp4の場合、コンテナをmkvに変更してみるとか(※実験的なもので効果は出ないかも…) 95 | 96 | ## ■アンインストールの方法 97 | AviUtlのフォルダにコピーした 98 | InputPipePlugin.aui と 99 | InputPipeMain.exe と 100 | InputPipePluginConfig.ini を削除してください 101 | 102 | ## ■免責 103 | 作者(原著者&改変者)は、このソフトによって生じた如何なる損害にも、 104 | 修正や更新も、責任を負わないこととします。 105 | 使用にあたっては、自己責任でお願いします。 106 | 107 | 何かあれば下記のURLにあるメールフォームにお願いします。 108 | https://ws.formzu.net/fgen/S37403840/ 109 | 110 | ## ■著作権表示 111 | Copyright (C) 2019-2023 amate 112 | 113 | 私が書いた部分のソースコードは、MIT License とします。 114 | 115 | ## ■謝辞 116 | aviutlの作者様、L-SMASH Worksの作者様 117 | あなた方の活躍のおかげで、素晴らしい動画がたくさん生まれていることに感謝いたします 118 | ありがとう! 119 | 120 | ## ■... 121 | よろしければ、\[ [sm35585310](https://www.nicovideo.jp/watch/sm35585310) \] を親作品登録してくれると色々助かります 122 | 123 | ## ■誰かの役に立つかもしれない情報 124 | 125 | - GeForce Experience(ShadowPlay)で録画したファイルを編集しようとしたら音ズレしてる! 126 | 動画プレイヤーで再生したときは音ズレしていないのに、aviutlで編集しようとしたらなぜか音ズレしてしまっている場合、 127 | →Avidemuxを使ってコンテナをmkvに変更する 128 | AvidemuxのVideo OutputとAudio OutputをCopyに、Output FormatをMkv Muxerに変更して 129 | ファイルを読み込んだ後、Saveで出力する 130 | 出来上がったmkvファイルを読み込むとなぜか音ズレしていない 131 | 132 | - OBS Studioで録画したファイルのシークが死ぬほど遅い! 133 | →Avidemuxを使ってコンテナをmkvに変更する 134 | 上記の手順を実行 135 | なぜかシークが軽くなっている 136 | 137 | - Detected CTS duplication at frame XXX ってダイアログが出る! 138 | →Avidemuxを使ってコンテナをmkvに変更する 139 | 以下略 140 | 141 | コンテナを変更するだけでなぜ直るのかは謎 142 | 143 | ## ■ビルドについて 144 | Visual Studio 2022 が必要です 145 | ビルドには boost(1.70~)とWTL(10_9163) が必要なのでそれぞれ用意してください。 146 | 147 | Boost::Logを使用しているので、事前にライブラリのビルドが必要になります 148 | 149 | Boostライブラリのビルド方法 150 | https://boostjp.github.io/howtobuild.html 151 | //コマンドライン 152 | b2.exe install -j 16 --prefix=lib toolset=msvc-14.2 runtime-link=static --with-log --with-filesystem 153 | 154 | ◆boost 155 | http://www.boost.org/ 156 | 157 | ◆WTL 158 | http://sourceforge.net/projects/wtl/ 159 | 160 | 161 | ## ■更新履歴 162 |
163 | 
164 | v2.0
165 | ・[add] InputPipeMain64.exeを追加 (64bit版 L-SMASH_Works File Reader(lwinput64.aui)が存在するときはそちらを利用するようにした)
166 | 
167 | v1.10
168 | ・[fix] 動画ファイルの幅、高さが4の倍数でないときに強制終了するバグを修正 #5
169 | 
170 | v1.9
171 | ・[update] 開発環境を Visual Studio 2022 に更新
172 | ・[fix] lwinput.auiに func_init、func_exitが実装されていれば、それぞれ呼ぶようにした (オリジナルはnullptrだったので呼んでいなかった)
173 | ・[change] 内部データ交換方式は、"共有メモリ"をデフォルトにした
174 | ・[fix] InputPipePlugin.aui から InputPipeMain.exe 実行時に、カレントディレクトリを設定するようにした (lsmash.iniを読み込めるようになったはず)
175 | 
176 | v1.8
177 | ・[add] 同一フレーム同一ファイル問題に対処、Altを押しながらのファイルドロップで、新規ファイルとして開く処理を追加
178 | 
179 | v1.7
180 | ・[fix] IPC有効時、プラグインの終了時にInputPipeMain.exeをまともに終了させるようにした
181 | ・[change] lwinput.auiの各種関数呼び出しにラッパーを噛ませた (例外も握り潰すようにしたので多少落ちなくなったはず)
182 | ・[add] 設定の保存に失敗した場合、メッセージボックスを表示するようにした (AviUtlフォルダを [Program Files]や[Program Files (x86)]フォルダ内に置かないでください)
183 | ・[fix] IPC有効時、名前付きパイプの準備やInputPipeMain.exeの起動に失敗した場合、IPCを無効化して動作させるようにした
184 | ・[fix] ConnectNamedPipeの呼び出しが、タイミングによって失敗することがあるのを修正 
185 | ・[fix] 音声が存在しない動画ファイル読み込み時、iip->audio_formatが無効なアドレスを指していたのを修正
186 | ・[misc] 使用していないソースコードの削除や INPUT_INFO周りの処理を共通化
187 | ・[change] 名前付きパイプのバッファサイズを増加させた (512->4096)
188 | 
189 | v1.6
190 | ・[change]設定で内部データの交換方式を選択できるようにした(デフォルトを名前付きパイプへ変更)
191 | 共有メモリだと落ちる場合があるらしいが、再現しないのでエラーが起こりそうな場所にメッセージボックスを埋め込んどいた
192 | ・[fix]InputPipeMain.exeがboost::logに依存しないようにした
193 | アンチウィルスがうるさいらしいのでその対策
194 | 
195 | v1.5
196 | ・[fix] aviutl起動時に、InputPipePlugin.auiと同じフォルダに lwinput.aui が存在しない場合プロセスが強制終了するのを修正
197 | ・[add] aviutl起動時に、InputPipePlugin.auiと同じフォルダに lwinput.aui が存在しない場合メッセージボックスを表示するようにした
198 | ・[change] プロセス間通信有効時、画像と音声の転送に共有メモリを使用するようにした (6割ほど高速化した)
199 | ・[change] boostを1.72.0へ更新
200 | ・[chagen] std::filesystemからboost::filesystemへ使用ライブラリを変更
201 | 
202 | v1.4
203 | ・[change]プロセス間通信有効、func_read_videoで画像の取得に失敗した場合の処理をInputPipePlugin.auiではなく、InputPipeMain.exeで実行するようにした
204 | ・[add]プロセス間通信無効時でも、func_info_getでキャッシュ情報を返すようにした
205 | 
206 | v1.3
207 | ・[fix] func_read_videoで画像の取得に失敗した場合、一度前のフレームを取得してから目的のフレームを取得するようにした [緑の画面が出る対策](ワークアラウンドっぽいがとりあえず動く)
208 | 
209 | v1.2
210 | ・[fix] CreateNamedPipeでPIPE_TYPE_MESSAGEのままだったのを修正
211 | ・[add] NamedPipe::Read failed 時に、GetLastErrorの内容を書き込むようにした(上の修正でもう書き込まれないはず…)
212 | 
213 | v1.1
214 | ・[fix] IPC有効時、外部プロセスとの通信にコケるのを修正(マルチスレッドで各種関数が実行されることがあるようなので、排他制御を入れた)
215 | ・[change] 名前付きパイプの設定を、バイトストリームモードへ変更(上のバグのせいで変なことしてた)
216 | ・[fix] 外部プロセスにて、func_info_getが失敗することを考慮に入れてなかったのを修正
217 | ・[change] 名前付きパイプの名前をランダムに変更するようにした
218 | 
219 | v1.0
220 | ・完成
221 | 
-------------------------------------------------------------------------------- /InputPipeMain/InputPipeMain.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | {291F3EAA-62CA-43F5-A096-009B7EFABF04} 24 | Win32Proj 25 | InputPipeMain 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v143 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v143 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v143 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v143 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | $(SolutionDir)$(Configuration)\plugins\ 76 | C:\Programing\#lib\boost_1_73_0\lib\include\boost-1_73;C:\Programing\#lib\WTL10_10320_Release\Include;$(IncludePath) 77 | C:\Programing\#lib\boost_1_73_0\lib\lib;$(LibraryPath) 78 | 79 | 80 | true 81 | C:\Programing\#lib\boost_1_73_0\lib\include\boost-1_73;C:\Programing\#lib\WTL10_10320_Release\Include;$(VC_IncludePath);$(WindowsSDK_IncludePath); 82 | C:\Programing\#lib\boost_1_73_0\lib\lib;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64) 83 | $(ProjectName)64 84 | 85 | 86 | false 87 | $(SolutionDir)$(Configuration)\ 88 | C:\Programing\#lib\boost_1_73_0\lib\include\boost-1_73;C:\Programing\#lib\WTL10_10320_Release\Include;$(IncludePath) 89 | C:\Programing\#lib\boost_1_73_0\lib\lib;$(LibraryPath) 90 | 91 | 92 | false 93 | C:\Programing\#lib\boost_1_73_0\lib\include\boost-1_73;C:\Programing\#lib\WTL10_10320_Release\Include;$(VC_IncludePath);$(WindowsSDK_IncludePath); 94 | C:\Programing\#lib\boost_1_73_0\lib\lib;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64) 95 | $(ProjectName)64 96 | 97 | 98 | 99 | 100 | 101 | Level3 102 | Disabled 103 | true 104 | WIN32;INPUT_PIPE_MAIN;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) 105 | true 106 | MultiThreadedDebug 107 | 108 | 109 | Windows 110 | true 111 | true 112 | 113 | 114 | 115 | 116 | 117 | 118 | Level3 119 | Disabled 120 | true 121 | INPUT_PIPE_MAIN;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) 122 | true 123 | MultiThreadedDebug 124 | 125 | 126 | Windows 127 | true 128 | 129 | 130 | 131 | 132 | 133 | 134 | Level3 135 | true 136 | true 137 | true 138 | WIN32;INPUT_PIPE_MAIN;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 139 | true 140 | Speed 141 | MultiThreaded 142 | 143 | 144 | Windows 145 | true 146 | false 147 | true 148 | true 149 | 150 | 151 | 152 | 153 | 154 | 155 | Level3 156 | MaxSpeed 157 | true 158 | true 159 | true 160 | INPUT_PIPE_MAIN;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 161 | true 162 | MultiThreaded 163 | 164 | 165 | Windows 166 | true 167 | true 168 | true 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | true 190 | true 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | -------------------------------------------------------------------------------- /InputPipePlugin/InputPipePlugin.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | {B752F6B8-D93A-4F10-BFAB-B08C7114D3BF} 24 | Win32Proj 25 | InputPipePlugin 26 | 10.0 27 | 28 | 29 | 30 | DynamicLibrary 31 | true 32 | Unicode 33 | v143 34 | 35 | 36 | DynamicLibrary 37 | false 38 | v143 39 | true 40 | Unicode 41 | 42 | 43 | DynamicLibrary 44 | true 45 | v143 46 | Unicode 47 | 48 | 49 | DynamicLibrary 50 | false 51 | v143 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | .aui 76 | $(SolutionDir)$(Configuration)\plugins\ 77 | C:\Programing\#lib\boost_1_73_0\lib\include\boost-1_73;C:\Programing\#lib\WTL10_10320_Release\Include;$(IncludePath) 78 | C:\Programing\#lib\boost_1_73_0\lib\lib;$(LibraryPath) 79 | 80 | 81 | true 82 | 83 | 84 | false 85 | .aui 86 | C:\Programing\#lib\boost_1_73_0\lib\include\boost-1_73;C:\Programing\#lib\WTL10_10320_Release\Include;$(IncludePath) 87 | C:\Programing\#lib\boost_1_73_0\lib\lib;$(LibraryPath) 88 | 89 | 90 | false 91 | 92 | 93 | 94 | Use 95 | Level3 96 | Disabled 97 | true 98 | WIN32;_DEBUG;INPUTPIPEPLUGIN_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 99 | true 100 | pch.h 101 | MultiThreadedDebug 102 | 103 | 104 | Windows 105 | true 106 | false 107 | input.def 108 | 109 | 110 | 111 | 112 | Use 113 | Level3 114 | Disabled 115 | true 116 | _DEBUG;INPUTPIPEPLUGIN_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 117 | true 118 | pch.h 119 | 120 | 121 | Windows 122 | true 123 | false 124 | 125 | 126 | 127 | 128 | Use 129 | Level3 130 | true 131 | true 132 | true 133 | WIN32;NDEBUG;INPUTPIPEPLUGIN_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 134 | true 135 | pch.h 136 | MultiThreaded 137 | 138 | 139 | Windows 140 | true 141 | true 142 | true 143 | false 144 | input.def 145 | 146 | 147 | 148 | 149 | Use 150 | Level3 151 | MaxSpeed 152 | true 153 | true 154 | true 155 | NDEBUG;INPUTPIPEPLUGIN_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 156 | true 157 | pch.h 158 | 159 | 160 | Windows 161 | true 162 | true 163 | true 164 | false 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | NotUsing 180 | NotUsing 181 | 182 | 183 | NotUsing 184 | NotUsing 185 | 186 | 187 | NotUsing 188 | NotUsing 189 | 190 | 191 | NotUsing 192 | NotUsing 193 | 194 | 195 | NotUsing 196 | NotUsing 197 | 198 | 199 | 200 | 201 | Create 202 | Create 203 | Create 204 | Create 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | {291f3eaa-62ca-43f5-a096-009b7efabf04} 213 | 214 | 215 | 216 | 217 | 218 | -------------------------------------------------------------------------------- /InputPipeMain/InputPipeMain.cpp: -------------------------------------------------------------------------------- 1 | // InputPipeMain.cpp : アプリケーションのエントリ ポイントを定義します。 2 | // 3 | 4 | #include "framework.h" 5 | #include "InputPipeMain.h" 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "..\Share\IPC.h" 11 | //#include "..\Share\Logger.h" 12 | #include "..\Share\Common.h" 13 | #include "..\Share\PluginWrapper.h" 14 | #include "..\InputPipePlugin\input.h" 15 | #include "MainDlg.h" 16 | 17 | // グローバル変数: 18 | CAppModule _Module; 19 | HMODULE g_hModule; 20 | 21 | HMODULE g_hWinputDll = NULL; 22 | INPUT_PLUGIN_TABLE* g_winputPluginTable = nullptr; 23 | 24 | std::vector g_readVideoBuffer; 25 | std::vector g_readAudioBuffer; 26 | 27 | #ifdef _WIN64 28 | #define LWINNPUT_NAME L"lwinput64.aui" 29 | #else 30 | #define LWINNPUT_NAME L"lwinput.aui" 31 | #endif 32 | 33 | // for Logger 34 | std::string LogFileName() 35 | { 36 | return (GetExeDirectory() / L"InputPipeMain.log").string(); 37 | } 38 | 39 | int Run() 40 | { 41 | HRESULT hRes = ::CoInitialize(NULL); 42 | // If you are running on NT 4.0 or higher you can use the following call instead to 43 | // make the EXE free threaded. This means that calls come in on a random RPC thread. 44 | // HRESULT hRes = ::CoInitializeEx(NULL, COINIT_MULTITHREADED); 45 | ATLASSERT(SUCCEEDED(hRes)); 46 | 47 | // this resolves ATL window thunking problem when Microsoft Layer for Unicode (MSLU) is used 48 | ::DefWindowProc(NULL, 0, 0, 0L); 49 | 50 | AtlInitCommonControls(ICC_BAR_CLASSES); // add flags to support other controls 51 | 52 | hRes = _Module.Init(NULL, g_hModule); 53 | ATLASSERT(SUCCEEDED(hRes)); 54 | 55 | int nRet = 0; 56 | { 57 | CMessageLoop theLoop; 58 | _Module.AddMessageLoop(&theLoop); 59 | 60 | CMainDlg dlgMain; 61 | 62 | if (dlgMain.Create(NULL) == NULL) 63 | { 64 | ATLTRACE(_T("Main dialog creation failed!\n")); 65 | return 0; 66 | } 67 | 68 | dlgMain.ShowWindow(SW_SHOWNORMAL); 69 | 70 | nRet = theLoop.Run(); 71 | 72 | _Module.RemoveMessageLoop(); 73 | } 74 | 75 | _Module.Term(); 76 | ::CoUninitialize(); 77 | return nRet; 78 | } 79 | 80 | /////////////////////////////////////////////////////////////// 81 | 82 | int APIENTRY wWinMain(_In_ HINSTANCE hInstance, 83 | _In_opt_ HINSTANCE hPrevInstance, 84 | _In_ LPWSTR lpCmdLine, 85 | _In_ int nCmdShow) 86 | { 87 | UNREFERENCED_PARAMETER(hPrevInstance); 88 | UNREFERENCED_PARAMETER(lpCmdLine); 89 | 90 | #ifdef _DEBUG 91 | ATLTRACE(L"INPUT_INFO size: %d\n", sizeof(INPUT_INFO)); 92 | ATLTRACE(L"INPUT_INFO32 size: %d\n", sizeof(INPUT_INFO32)); 93 | ATLTRACE(L"INPUT_PLUGIN_TABLE size: %d\n", sizeof(INPUT_PLUGIN_TABLE)); 94 | 95 | #endif 96 | 97 | g_hModule = hInstance; 98 | #if 1 99 | std::wstring cmdLine = lpCmdLine;//::GetCommandLine(); 100 | // INFO_LOG << L"CommandLine: " << cmdLine; 101 | if (cmdLine.empty()) { 102 | bool pluginExists = fs::exists((GetExeDirectory() / LWINNPUT_NAME)); 103 | MessageBox(NULL, pluginExists ? LWINNPUT_NAME L" が同じフォルダに存在しています!" 104 | : LWINNPUT_NAME L" が同じフォルダに存在しません...", L"InputPipeMain", MB_OK); 105 | return 0; 106 | } else if (cmdLine == L"-config") { 107 | int ret = Run(); 108 | return ret; 109 | } 110 | 111 | auto llhandle = std::stoll(cmdLine); 112 | HANDLE hEvent = (HANDLE)llhandle; 113 | 114 | size_t spacePos = cmdLine.find(L' '); 115 | // INFO_LOG << L"spacePos: " << spacePos; 116 | assert(spacePos != std::wstring::npos); 117 | std::wstring pipeName = cmdLine.substr(spacePos + 1); 118 | size_t tailSpacePos = pipeName.find(L' '); 119 | if (tailSpacePos != std::wstring::npos) { 120 | pipeName.resize(tailSpacePos); 121 | } 122 | 123 | std::wstring kJobName = L"InputPipePlugin_Job" + std::to_wstring((uint64_t)hEvent); 124 | HANDLE hJob = ::OpenJobObject(JOB_OBJECT_ASSIGN_PROCESS, FALSE, kJobName.c_str()); 125 | //assert(hJob); 126 | if (hJob == NULL) { 127 | return 0; 128 | } 129 | ::AssignProcessToJobObject(hJob, GetCurrentProcess()); 130 | ::CloseHandle(hJob); 131 | 132 | { 133 | g_hWinputDll = ::LoadLibrary((GetExeDirectory() / LWINNPUT_NAME).c_str()); 134 | assert(g_hWinputDll); 135 | if (g_hWinputDll == NULL) { 136 | //WARN_LOG << L"LoadLibrary failed (lwinput.aui)"; 137 | return 0; 138 | } 139 | 140 | using GetInputPluginTableFunc = INPUT_PLUGIN_TABLE * (__stdcall*)(void); 141 | GetInputPluginTableFunc funcGetTable = (GetInputPluginTableFunc)::GetProcAddress(g_hWinputDll, "GetInputPluginTable"); 142 | ATLASSERT(funcGetTable); 143 | g_winputPluginTable = funcGetTable(); 144 | } 145 | 146 | #endif 147 | 148 | std::wstring randomString; 149 | SharedMemory videoSharedMemory; 150 | SharedMemory audioSharedMemory; 151 | std::pair videoSharedBuffer = { nullptr, 0 }; 152 | std::pair audioSharedBuffer = { nullptr, 0 }; 153 | bool bUseSharedMemory = false; 154 | if (cmdLine.find(L"-sharedMemory") != std::wstring::npos) { 155 | bUseSharedMemory = true; 156 | 157 | auto randPos = cmdLine.find(L'_'); 158 | assert(randPos != std::wstring::npos); 159 | auto randPosEnd = cmdLine.find(L'_', randPos + 1); 160 | assert(randPosEnd != std::wstring::npos); 161 | randomString = cmdLine.substr(randPos, randPosEnd - randPos + 1); 162 | } 163 | 164 | 165 | // TODO: ここにコードを挿入してください。 166 | //InitHook(); 167 | NamedPipe namedPipe; 168 | bool success = namedPipe.OpenNamedPipe(pipeName); 169 | if (!success) { 170 | ATLASSERT(FALSE); 171 | return 0; 172 | } 173 | 174 | BOOL b = Plugin_func_init(); 175 | 176 | // for Debug 177 | CallFunc lastCallFunc; 178 | bool activeLoop = true; 179 | while (activeLoop) { 180 | std::vector readData = namedPipe.Read(kToWindDataHeaderSize); 181 | if (readData.size() == 0) { 182 | assert(false); 183 | break; 184 | } 185 | ToWinputData* toData = (ToWinputData*)readData.data(); 186 | lastCallFunc = toData->header.callFunc; 187 | 188 | std::vector dataBody = namedPipe.Read(toData->header.paramSize); 189 | switch (toData->header.callFunc) { 190 | case CallFunc::kOpen: 191 | { 192 | LPSTR file = (LPSTR)dataBody.data(); 193 | #ifdef INPUT_PIPE_MAIN64 194 | INPUT_HANDLE32 ih = Plugin_func_open(file); 195 | #else 196 | INPUT_HANDLE ih = Plugin_func_open(file); 197 | #endif 198 | //INFO_LOG << L"kOpen: " << ih; 199 | 200 | auto fromData = GenerateFromInputData(CallFunc::kOpen, ih, 0); 201 | namedPipe.Write((const BYTE*)fromData.get(), FromWinputDataTotalSize(*fromData)); 202 | //INFO_LOG << L"Write: " << FromWinputDataTotalSize(*fromData) << L" bytes"; 203 | } 204 | break; 205 | 206 | case CallFunc::kClose: 207 | { 208 | StandardParamPack* spp = (StandardParamPack*)dataBody.data(); 209 | BOOL b = Plugin_func_close(spp->ih); 210 | //INFO_LOG << L"kClose: " << spp->ih; 211 | 212 | auto fromData = GenerateFromInputData(CallFunc::kClose, b, 0); 213 | namedPipe.Write((const BYTE*)fromData.get(), FromWinputDataTotalSize(*fromData)); 214 | //INFO_LOG << L"Write: " << FromWinputDataTotalSize(*fromData) << L" bytes"; 215 | } 216 | break; 217 | 218 | case CallFunc::kInfoGet: 219 | { 220 | 221 | StandardParamPack* spp = (StandardParamPack*)dataBody.data(); 222 | INPUT_INFO inputInfo = {}; 223 | BOOL b = Plugin_func_info_get(spp->ih, &inputInfo); 224 | assert(b); 225 | //INFO_LOG << L"kInfoGet: " << spp->ih; 226 | if (b) { 227 | const int totalInputInfoSize = CalcTotalInputInfoSize(&inputInfo); 228 | auto infoGetData = SerializeInputInfo(&inputInfo); 229 | 230 | auto fromData = GenerateFromInputData(CallFunc::kInfoGet, b, infoGetData.get(), totalInputInfoSize); 231 | namedPipe.Write((const BYTE*)fromData.get(), FromWinputDataTotalSize(*fromData)); 232 | //INFO_LOG << L"Write: " << FromWinputDataTotalSize(*fromData) << L" bytes"; 233 | 234 | } else { 235 | auto fromData = GenerateFromInputData(CallFunc::kInfoGet, b, 0); 236 | namedPipe.Write((const BYTE*)fromData.get(), FromWinputDataTotalSize(*fromData)); 237 | //INFO_LOG << L"Write: " << FromWinputDataTotalSize(*fromData) << L" bytes"; 238 | } 239 | } 240 | break; 241 | 242 | case CallFunc::kReadVideo: 243 | { 244 | StandardParamPack* spp = (StandardParamPack*)dataBody.data(); 245 | void* buf; 246 | bool sharedMemoryReopen = false; 247 | if (bUseSharedMemory) { 248 | if (videoSharedBuffer.second < spp->perBufferSize) { 249 | videoSharedMemory.CloseHandle(); 250 | std::wstring sharedMemoryName = kVideoSharedMemoryPrefix + randomString + std::to_wstring(spp->perBufferSize); 251 | videoSharedBuffer.first = videoSharedMemory.CreateSharedMemory(sharedMemoryName.c_str(), spp->perBufferSize); 252 | if (!videoSharedBuffer.first) { 253 | DWORD error = ::GetLastError(); 254 | std::wstring errorMsg = L"videoSharedMemory.CreateSharedMemoryに失敗\nsharedMemoryName: " + sharedMemoryName + L"\nGetLastError: " + std::to_wstring(error); 255 | MessageBox(NULL, errorMsg.c_str(), L"InputPipeMainエラー", MB_ICONERROR);; 256 | } 257 | videoSharedBuffer.second = spp->perBufferSize; 258 | sharedMemoryReopen = true; 259 | } 260 | buf = videoSharedBuffer.first; 261 | } else { 262 | if (static_cast(g_readVideoBuffer.size()) < spp->perBufferSize) { 263 | g_readVideoBuffer.resize(spp->perBufferSize); 264 | } 265 | buf = g_readVideoBuffer.data(); 266 | } 267 | const int frame = spp->param1; 268 | int readBytes = Plugin_func_read_video(spp->ih, spp->param1, buf); 269 | //INFO_LOG << L"kReadVideo: " << spp->ih; 270 | 271 | namedPipe.Write((const BYTE*)&toData->header.callFunc, sizeof(toData->header.callFunc)); 272 | std::int32_t totalSize = sizeof(int) + readBytes; 273 | namedPipe.Write((const BYTE*)&totalSize, sizeof(totalSize)); 274 | namedPipe.Write((const BYTE*)&readBytes, sizeof(readBytes)); 275 | if (bUseSharedMemory) { 276 | namedPipe.Write((const BYTE*)&sharedMemoryReopen, sizeof(sharedMemoryReopen)); 277 | } else { 278 | namedPipe.Write((const BYTE*)g_readVideoBuffer.data(), readBytes); 279 | } 280 | //auto fromData = GenerateFromInputData(toData->header.callFunc, readBytes, g_readVideoBuffer.data(), readBytes); 281 | //namedPipe.Write((const BYTE*)fromData.get(), FromWinputDataTotalSize(*fromData)); 282 | //INFO_LOG << L"Write: " << FromWinputDataTotalSize(*fromData) << L" bytes"; 283 | } 284 | break; 285 | 286 | case CallFunc::kReadAudio: 287 | { 288 | StandardParamPack* spp = (StandardParamPack*)dataBody.data(); 289 | const int PerAudioSampleBufferSize = spp->perBufferSize; 290 | const int requestReadBytes = PerAudioSampleBufferSize * spp->param2; 291 | void* buf; 292 | bool sharedMemoryReopen = false; 293 | if (bUseSharedMemory) { 294 | if (audioSharedBuffer.second < requestReadBytes) { 295 | audioSharedMemory.CloseHandle(); 296 | std::wstring sharedMemoryName = kAudioSharedMemoryPrefix + randomString + std::to_wstring(requestReadBytes); 297 | audioSharedBuffer.first = audioSharedMemory.CreateSharedMemory(sharedMemoryName.c_str(), requestReadBytes); 298 | if (!audioSharedBuffer.first) { 299 | DWORD error = ::GetLastError(); 300 | std::wstring errorMsg = L"audioSharedMemory.CreateSharedMemoryに失敗\nsharedMemoryName: " + sharedMemoryName + L"\nGetLastError: " + std::to_wstring(error); 301 | MessageBox(NULL, errorMsg.c_str(), L"InputPipeMainエラー", MB_ICONERROR);; 302 | } 303 | audioSharedBuffer.second = requestReadBytes; 304 | sharedMemoryReopen = true; 305 | } 306 | buf = audioSharedBuffer.first; 307 | } else { 308 | if (static_cast(g_readAudioBuffer.size()) < requestReadBytes) { 309 | g_readAudioBuffer.resize(requestReadBytes); 310 | } 311 | buf = g_readAudioBuffer.data(); 312 | } 313 | 314 | int readSample = Plugin_func_read_audio(spp->ih, spp->param1, spp->param2, buf); 315 | //assert(readSample > 0); 316 | //INFO_LOG << L"kReadAudio: " << spp->ih << L" readSample: " << readSample; 317 | const int readBufferSize = PerAudioSampleBufferSize * readSample; 318 | 319 | namedPipe.Write((const BYTE*)& toData->header.callFunc, sizeof(toData->header.callFunc)); 320 | std::int32_t totalSize = sizeof(int) + readBufferSize; 321 | namedPipe.Write((const BYTE*)&totalSize, sizeof(totalSize)); 322 | namedPipe.Write((const BYTE*)&readSample, sizeof(readSample)); 323 | if (bUseSharedMemory) { 324 | namedPipe.Write((const BYTE*)&sharedMemoryReopen, sizeof(sharedMemoryReopen)); 325 | } else { 326 | namedPipe.Write((const BYTE*)g_readAudioBuffer.data(), readBufferSize); 327 | } 328 | //auto fromData = GenerateFromInputData(toData->header.callFunc, readSample, g_readAudioBuffer.data(), readBufferSize); 329 | //namedPipe.Write((const BYTE*)fromData.get(), FromWinputDataTotalSize(*fromData)); 330 | //INFO_LOG << L"Write: " << FromWinputDataTotalSize(*fromData) << L" bytes"; 331 | } 332 | break; 333 | 334 | case CallFunc::kIsKeyframe: 335 | { 336 | //INFO_LOG << L"kIsKeyframe"; 337 | 338 | #ifdef INPUT_PIPE_MAIN64 339 | BOOL b = FALSE; 340 | #else 341 | StandardParamPack* spp = (StandardParamPack*)dataBody.data(); 342 | BOOL b = g_winputPluginTable->func_is_keyframe(spp->ih, spp->param1); 343 | #endif 344 | auto fromData = GenerateFromInputData(CallFunc::kIsKeyframe, b, 0); 345 | namedPipe.Write((const BYTE*)fromData.get(), FromWinputDataTotalSize(*fromData)); 346 | } 347 | break; 348 | 349 | case CallFunc::kExit: 350 | { 351 | //INFO_LOG << L"kExit"; 352 | namedPipe.Disconnect(); 353 | activeLoop = false; 354 | } 355 | break; 356 | 357 | default: 358 | assert(false); 359 | break; 360 | } 361 | 362 | }; 363 | 364 | b = Plugin_func_exit(); 365 | 366 | ::FreeLibrary(g_hWinputDll); 367 | g_hWinputDll = NULL; 368 | 369 | #if 0 370 | int result = 0; 371 | DWORD ret = ::WaitForSingleObject(hEvent, INFINITE); 372 | if (ret == WAIT_OBJECT_0) { 373 | result = 1; 374 | } else if (ret == WAIT_TIMEOUT) { 375 | result = 2; 376 | } else { 377 | DWORD err = ::GetLastError(); 378 | result = 3; 379 | } 380 | #endif 381 | return 0; 382 | } 383 | 384 | -------------------------------------------------------------------------------- /InputPipePlugin/input.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------------------------- 2 | // サンプルAVI(vfw経由)入力プラグイン for AviUtl ver0.98以降 3 | //---------------------------------------------------------------------------------- 4 | #include "pch.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | //#include 16 | //#pragma comment(lib, "Vfw32.lib") 17 | 18 | #include 19 | #pragma comment(lib, "Shell32.lib") 20 | 21 | #include "input.h" 22 | 23 | #include "..\Share\Logger.h" 24 | #include "..\Share\IPC.h" 25 | #include "..\Share\Common.h" 26 | #include "..\Share\CodeConvert.h" 27 | #include "..\Share\PluginWrapper.h" 28 | 29 | extern HMODULE g_hModule; 30 | HMODULE g_hWinputDll = NULL; 31 | INPUT_PLUGIN_TABLE* g_winputPluginTable = nullptr; 32 | 33 | BindProcess g_bindProcess; 34 | LPCWSTR kPipeName = LR"(\\.\pipe\InputPipePlugin)"; 35 | NamedPipe g_namedPipe; 36 | 37 | //std::vector g_lastInfoGetData; 38 | 39 | Config m_config; 40 | 41 | struct FrameAudioVideoBufferSize 42 | { 43 | int OneFrameBufferSize; 44 | int PerAudioSampleBufferSize; 45 | }; 46 | 47 | std::unordered_map g_mapFrameBufferSize; 48 | 49 | std::unordered_map> g_mapInputHandleInfoGetData; 50 | 51 | using HandleCache = std::tuple; 52 | std::vector g_vecHandleCache; 53 | 54 | std::mutex g_mtxIPC; 55 | 56 | std::wstring g_randamString; 57 | SharedMemory g_videoSharedMemory; 58 | SharedMemory g_audioSharedMemory; 59 | 60 | // for Logger 61 | std::string LogFileName() 62 | { 63 | return (GetExeDirectory() / L"InputPipePlugin.log").string(); 64 | } 65 | 66 | 67 | //#define DEBUG_PROCESSINGTIME 68 | 69 | void DisconnectPipeAndStopProcess() 70 | { 71 | StandardParamPack spp = {}; 72 | auto toData = GenerateToInputData(CallFunc::kExit, spp); 73 | g_namedPipe.Write((const BYTE*)toData.get(), ToWinputDataTotalSize(*toData)); 74 | 75 | g_namedPipe.Disconnect(); 76 | g_bindProcess.StopProcess(); 77 | } 78 | 79 | //--------------------------------------------------------------------- 80 | // 入力プラグイン構造体定義 81 | //--------------------------------------------------------------------- 82 | INPUT_PLUGIN_TABLE input_plugin_table = { 83 | INPUT_PLUGIN_FLAG_VIDEO|INPUT_PLUGIN_FLAG_AUDIO, // フラグ 84 | // INPUT_PLUGIN_FLAG_VIDEO : 画像をサポートする 85 | // INPUT_PLUGIN_FLAG_AUDIO : 音声をサポートする 86 | "InputPipePlugin", // プラグインの名前 87 | "any files (*.*)\0*.*\0", // 入力ファイルフィルタ 88 | "Plugin to bypass lwinput.aui By amate version " PLUGIN_VERSION, // プラグインの情報 89 | func_init, // DLL開始時に呼ばれる関数へのポインタ (NULLなら呼ばれません) 90 | func_exit, // DLL終了時に呼ばれる関数へのポインタ (NULLなら呼ばれません) 91 | func_open, // 入力ファイルをオープンする関数へのポインタ 92 | func_close, // 入力ファイルをクローズする関数へのポインタ 93 | func_info_get, // 入力ファイルの情報を取得する関数へのポインタ 94 | func_read_video, // 画像データを読み込む関数へのポインタ 95 | func_read_audio, // 音声データを読み込む関数へのポインタ 96 | func_is_keyframe, // キーフレームか調べる関数へのポインタ (NULLなら全てキーフレーム) 97 | func_config, // 入力設定のダイアログを要求された時に呼ばれる関数へのポインタ (NULLなら呼ばれません) 98 | }; 99 | 100 | 101 | //--------------------------------------------------------------------- 102 | // 入力プラグイン構造体のポインタを渡す関数 103 | //--------------------------------------------------------------------- 104 | EXTERN_C INPUT_PLUGIN_TABLE __declspec(dllexport) * __stdcall GetInputPluginTable( void ) 105 | { 106 | g_hWinputDll = ::LoadLibrary((GetExeDirectory() / L"lwinput.aui").c_str()); 107 | assert(g_hWinputDll); 108 | if (g_hWinputDll == NULL) { 109 | WARN_LOG << L"lwinput.aui not found"; 110 | MessageBox(NULL, L"同じフォルダ内に lwinput.aui が存在しません\nlwinput.aui が存在するフォルダに InputPipePlugin.aui と InputPipeMain.exe をコピーしてください", L"InputPipePluginエラー", MB_ICONERROR); 111 | return &input_plugin_table; 112 | } 113 | 114 | using GetInputPluginTableFunc = INPUT_PLUGIN_TABLE * (__stdcall*)(void); 115 | GetInputPluginTableFunc funcGetTable = (GetInputPluginTableFunc)::GetProcAddress(g_hWinputDll, "GetInputPluginTable"); 116 | g_winputPluginTable = funcGetTable(); 117 | 118 | //::FreeLibrary(g_hWinputDll); 119 | //g_hWinputDll = NULL; 120 | 121 | return &input_plugin_table; 122 | } 123 | 124 | 125 | #if 0 126 | //--------------------------------------------------------------------- 127 | // ファイルハンドル構造体 128 | //--------------------------------------------------------------------- 129 | typedef struct { 130 | int flag; 131 | PAVIFILE pfile; 132 | PAVISTREAM pvideo,paudio; 133 | AVIFILEINFO fileinfo; 134 | AVISTREAMINFO videoinfo,audioinfo; 135 | void *videoformat; 136 | LONG videoformatsize; 137 | void *audioformat; 138 | LONG audioformatsize; 139 | } FILE_HANDLE; 140 | #define FILE_HANDLE_FLAG_VIDEO 1 141 | #define FILE_HANDLE_FLAG_AUDIO 2 142 | #endif 143 | 144 | //--------------------------------------------------------------------- 145 | // 初期化 146 | //--------------------------------------------------------------------- 147 | BOOL func_init( void ) 148 | { 149 | INFO_LOG << L"func_init"; 150 | 151 | if (g_hWinputDll == NULL) { 152 | return FALSE; 153 | } 154 | 155 | m_config.LoadConfig(); 156 | //m_config.bUseSharedMemory = true; 157 | 158 | if (m_config.bEnableIPC) { 159 | INFO_LOG << "EnableIPC"; 160 | 161 | enum { kRandamStrLength = 32 }; 162 | std::random_device randdev; 163 | WCHAR tempstr[] = L"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; 164 | std::uniform_int_distribution dist(0, std::size(tempstr) - 2); 165 | std::wstring randamString = L"_"; 166 | for (int i = 0; i < kRandamStrLength; ++i) { 167 | randamString += tempstr[dist(randdev)]; 168 | } 169 | randamString += L"_"; 170 | std::wstring pipeName = std::wstring(kPipeName) + randamString; 171 | bool ret = g_namedPipe.CreateNamedPipe(pipeName); 172 | INFO_LOG << L"CreateNamedPipe: " << pipeName << L" ret: " << ret; 173 | if (!ret) { 174 | ERROR_LOG << L"CreateNamedPipe failed - GetLastError: " << GetLastErrorString(); 175 | WARN_LOG << L"エラーが発生したのでIPCを無効化します"; 176 | m_config.bEnableIPC = false; 177 | return TRUE; 178 | } 179 | 180 | auto InputPipeMainPath = GetExeDirectory() / L"InputPipeMain.exe"; 181 | auto lwinput64Path = GetExeDirectory() / L"lwinput64.aui"; 182 | if (fs::exists(lwinput64Path)) { 183 | InputPipeMainPath = GetExeDirectory() / L"InputPipeMain64.exe"; 184 | } 185 | 186 | std::wstring commandLine = pipeName; 187 | if (m_config.bUseSharedMemory) { 188 | g_randamString = randamString; 189 | commandLine += L" -sharedMemory"; 190 | } 191 | bool startRet = g_bindProcess.StartProcess(InputPipeMainPath.native(), commandLine); 192 | // INFO_LOG << L"StartProcess: " << L" ret: " << startRet; 193 | if (!startRet) { 194 | ERROR_LOG << L"g_bindProcess.StartProcess(InputPipeMainPath failed - GetLastError: " << GetLastErrorString(); 195 | WARN_LOG << L"エラーが発生したのでIPCを無効化します"; 196 | DisconnectPipeAndStopProcess(); 197 | m_config.bEnableIPC = false; 198 | return TRUE; 199 | } 200 | 201 | if (!g_namedPipe.ConnectNamedPipe()) { 202 | ERROR_LOG << L"ConnectNamedPipe failed - GetLastError: " << GetLastErrorString(); 203 | WARN_LOG << L"エラーが発生したのでIPCを無効化します"; 204 | DisconnectPipeAndStopProcess(); 205 | m_config.bEnableIPC = false; 206 | return TRUE; 207 | } 208 | return TRUE; 209 | 210 | } else { 211 | BOOL b = Plugin_func_init(); 212 | return b; 213 | } 214 | } 215 | 216 | 217 | //--------------------------------------------------------------------- 218 | // 終了 219 | //--------------------------------------------------------------------- 220 | BOOL func_exit( void ) 221 | { 222 | INFO_LOG << L"func_exit"; 223 | 224 | if (g_hWinputDll == NULL) { 225 | return FALSE; 226 | } 227 | 228 | if (m_config.bEnableIPC) { 229 | g_videoSharedMemory.CloseHandle(); 230 | g_audioSharedMemory.CloseHandle(); 231 | 232 | DisconnectPipeAndStopProcess(); 233 | 234 | return TRUE; 235 | } else { 236 | BOOL b = Plugin_func_exit(); 237 | return b; 238 | } 239 | } 240 | 241 | bool IsAlternativeFileName(const std::string& filePath) 242 | { 243 | return filePath.rfind(".[alt_") != std::string::npos; 244 | } 245 | 246 | std::string ConvertOriginalFileNameFromAlt(const std::string& filePath) 247 | { 248 | auto pos = filePath.rfind(".[alt_"); 249 | return filePath.substr(0, pos); 250 | } 251 | 252 | 253 | //--------------------------------------------------------------------- 254 | // ファイルオープン 255 | //--------------------------------------------------------------------- 256 | INPUT_HANDLE func_open( LPSTR file ) 257 | { 258 | INFO_LOG << L"func_open: " << CodeConvert::UTF16fromShiftJIS(file); 259 | 260 | if (g_hWinputDll == NULL) { 261 | return nullptr; 262 | } 263 | 264 | std::lock_guard lock(g_mtxIPC); 265 | 266 | const bool bAltKeyPress = ::GetAsyncKeyState(VK_MENU) < 0; 267 | const bool bAlternativeFileName = IsAlternativeFileName(file); 268 | 269 | if (m_config.bEnableHandleCache && (!bAltKeyPress || bAlternativeFileName)) { 270 | std::string fileName = file; 271 | auto itfound = std::find_if(g_vecHandleCache.begin(), g_vecHandleCache.end(), 272 | [fileName](const HandleCache& handleCache) { 273 | return std::get(handleCache) == fileName; 274 | }); 275 | if (itfound != g_vecHandleCache.end()) { 276 | int& refCount = std::get(*itfound); 277 | INFO_LOG << L" Cache found : " << refCount << L" -> " << (refCount + 1); 278 | ++refCount; 279 | return std::get(*itfound); 280 | } 281 | } 282 | 283 | INPUT_HANDLE ih = NULL; 284 | std::string filePath = file; 285 | if (bAlternativeFileName) { 286 | filePath = ConvertOriginalFileNameFromAlt(filePath); 287 | INFO_LOG << L" ConvertOriginalFileNameFromAlt"; 288 | } 289 | 290 | /* func_open */ 291 | if (m_config.bEnableIPC) { 292 | size_t paramSize = filePath.length() + 1; 293 | std::shared_ptr toData((ToWinputData*)new BYTE[kToWindDataHeaderSize + paramSize], 294 | [](ToWinputData* p) { 295 | delete[](BYTE*)p; 296 | }); 297 | toData->header.callFunc = CallFunc::kOpen; 298 | toData->header.paramSize = paramSize; 299 | memcpy_s(toData->paramData, paramSize, filePath.c_str(), paramSize); 300 | g_namedPipe.Write((const BYTE*)toData.get(), ToWinputDataTotalSize(*toData)); 301 | 302 | std::vector headerData = g_namedPipe.Read(kFromWinputDataHeaderSize); 303 | FromWinputData* fromData = (FromWinputData*)headerData.data(); 304 | //INFO_LOG << L"Read: " << fromData->returnSize << L" bytes"; 305 | assert(fromData->callFunc == CallFunc::kOpen); 306 | std::vector readBody = g_namedPipe.Read(fromData->returnSize); 307 | ih = *(INPUT_HANDLE*)readBody.data(); 308 | 309 | } else { 310 | ih = Plugin_func_open(const_cast(filePath.data())); 311 | } 312 | INFO_LOG << ih; 313 | 314 | if (m_config.bEnableHandleCache) { 315 | if (bAlternativeFileName) { 316 | filePath = file; // ファイル名をAlternativeFileNameへ戻す 317 | } else if (bAltKeyPress) { 318 | filePath += ".[alt_" + std::to_string(reinterpret_cast(ih)) + "].#junk"; 319 | ::strcpy_s(file, MAX_PATH, filePath.c_str()); // 元のファイル名を変更する 320 | INFO_LOG << L" Add Alt"; 321 | std::ofstream tempfs(file); // 一時ファイル作成 322 | } 323 | g_vecHandleCache.emplace_back(filePath, ih, 1); 324 | } 325 | 326 | return ih; 327 | } 328 | 329 | 330 | //--------------------------------------------------------------------- 331 | // ファイルクローズ 332 | //--------------------------------------------------------------------- 333 | BOOL func_close( INPUT_HANDLE ih ) 334 | { 335 | INFO_LOG << L"func_close: " << ih; 336 | std::lock_guard lock(g_mtxIPC); 337 | 338 | if (m_config.bEnableHandleCache) { 339 | auto itfound = std::find_if(g_vecHandleCache.begin(), g_vecHandleCache.end(), 340 | [ih](const HandleCache& handleCache) { 341 | return std::get(handleCache) == ih; 342 | }); 343 | assert(itfound != g_vecHandleCache.end()); 344 | if (itfound == g_vecHandleCache.end()) { 345 | ERROR_LOG << L" func_close g_vecFileInputHandle.erase failed: " << ih; 346 | } else { 347 | int& refCount = std::get(*itfound); 348 | INFO_LOG << L" Cache refCount : " << refCount << L" -> " << (refCount - 1); 349 | --refCount; 350 | if (refCount > 0) { 351 | return TRUE; // まだ消さない! 352 | 353 | } else { 354 | INFO_LOG << L" Cache delete: " << ih; 355 | g_vecHandleCache.erase(itfound); 356 | } 357 | } 358 | } 359 | 360 | auto itfound = g_mapInputHandleInfoGetData.find(ih); 361 | if (itfound != g_mapInputHandleInfoGetData.end()) { 362 | g_mapInputHandleInfoGetData.erase(itfound); 363 | } 364 | if (m_config.bEnableIPC) { 365 | StandardParamPack spp = { ih }; 366 | auto toData = GenerateToInputData(CallFunc::kClose, spp); 367 | g_namedPipe.Write((const BYTE*)toData.get(), ToWinputDataTotalSize(*toData)); 368 | 369 | std::vector headerData = g_namedPipe.Read(kFromWinputDataHeaderSize); 370 | FromWinputData* fromData = (FromWinputData*)headerData.data(); 371 | //INFO_LOG << L"Read: " << fromData->returnSize << L" bytes"; 372 | assert(fromData->callFunc == CallFunc::kClose); 373 | std::vector readBody = g_namedPipe.Read(fromData->returnSize); 374 | auto retData = ParseFromInputData(readBody); 375 | 376 | g_mapFrameBufferSize.erase(ih); 377 | return retData.first; 378 | } else { 379 | BOOL b = Plugin_func_close(ih); 380 | return b; 381 | } 382 | } 383 | 384 | 385 | //--------------------------------------------------------------------- 386 | // ファイルの情報 387 | //--------------------------------------------------------------------- 388 | BOOL func_info_get( INPUT_HANDLE ih,INPUT_INFO *iip ) 389 | { 390 | INFO_LOG << L"func_info_get"; 391 | std::lock_guard lock(g_mtxIPC); 392 | 393 | auto itfound = g_mapInputHandleInfoGetData.find(ih); 394 | if (itfound != g_mapInputHandleInfoGetData.end()) { 395 | INFO_LOG << L" InfoGetData cache found!"; 396 | *iip = *reinterpret_cast(itfound->second.get()); 397 | return TRUE; 398 | } 399 | if (m_config.bEnableIPC) { 400 | StandardParamPack spp = { ih }; 401 | auto toData = GenerateToInputData(CallFunc::kInfoGet, spp); 402 | g_namedPipe.Write((const BYTE*)toData.get(), ToWinputDataTotalSize(*toData)); 403 | 404 | std::vector headerData = g_namedPipe.Read(kFromWinputDataHeaderSize); 405 | FromWinputData* fromData = (FromWinputData*)headerData.data(); 406 | //INFO_LOG << L"Read: " << fromData->returnSize << L" bytes"; 407 | assert(fromData->callFunc == CallFunc::kInfoGet); 408 | std::vector readBody = g_namedPipe.Read(fromData->returnSize); 409 | auto retData = ParseFromInputData(readBody); 410 | if (retData.first) { 411 | auto infoGetData = DeserializeInputInfo(retData.second, iip); 412 | g_mapInputHandleInfoGetData.emplace(ih, std::move(infoGetData)); 413 | 414 | int OneFrameBufferSize = 0; 415 | if (iip->format_size > 0) { 416 | int paddingWidth = iip->format->biWidth; 417 | if (iip->format->biWidth % 4) { 418 | paddingWidth += 4 - (iip->format->biWidth % 4); // padding 分追加 419 | } 420 | int paddingHeight = iip->format->biHeight; 421 | if (iip->format->biHeight % 4) { 422 | paddingHeight += 4 - (iip->format->biHeight % 4); // padding 分追加 423 | } 424 | OneFrameBufferSize = paddingWidth * paddingHeight * (iip->format->biBitCount / 8); 425 | } 426 | int PerAudioSampleBufferSize = 0; 427 | if (iip->audio_format_size > 0) { 428 | PerAudioSampleBufferSize = iip->audio_format->nChannels * (iip->audio_format->wBitsPerSample / 8); 429 | } 430 | g_mapFrameBufferSize.emplace(ih, FrameAudioVideoBufferSize{ OneFrameBufferSize , PerAudioSampleBufferSize }); 431 | 432 | INFO_LOG << L" OneFrameBufferSize: " << OneFrameBufferSize << L" PerAudioSampleBufferSize: " << PerAudioSampleBufferSize; 433 | } else { 434 | ERROR_LOG << L" func_info_get failed, ih: " << ih; 435 | } 436 | return retData.first; 437 | 438 | } else { 439 | BOOL b = Plugin_func_info_get(ih, iip); 440 | if (b) { 441 | auto infoGetData = SerializeInputInfo(iip); 442 | g_mapInputHandleInfoGetData.emplace(ih, std::move(infoGetData)); 443 | } 444 | 445 | return b; 446 | } 447 | } 448 | 449 | //--------------------------------------------------------------------- 450 | // 画像読み込み 451 | //--------------------------------------------------------------------- 452 | int func_read_video( INPUT_HANDLE ih,int frame,void *buf ) 453 | { 454 | //INFO_LOG << L"func_read_video" << L" frame: " << frame; 455 | std::lock_guard lock(g_mtxIPC); 456 | 457 | #ifdef DEBUG_PROCESSINGTIME 458 | auto startTime = std::chrono::high_resolution_clock::now(); 459 | #endif 460 | 461 | if (m_config.bEnableIPC) { 462 | const int OneFrameBufferSize = g_mapFrameBufferSize[ih].OneFrameBufferSize; 463 | 464 | StandardParamPack spp = { ih, frame }; 465 | spp.perBufferSize = OneFrameBufferSize; 466 | auto toData = GenerateToInputData(CallFunc::kReadVideo, spp); 467 | g_namedPipe.Write((const BYTE*)toData.get(), ToWinputDataTotalSize(*toData)); 468 | 469 | std::vector headerData = g_namedPipe.Read(kFromWinputDataHeaderSize); 470 | FromWinputData* fromData = (FromWinputData*)headerData.data(); 471 | //INFO_LOG << L"Read: " << fromData->returnSize << L" bytes"; 472 | assert(fromData->callFunc == CallFunc::kReadVideo); 473 | int readBytes = 0; 474 | int nRet = g_namedPipe.Read((BYTE*)& readBytes, sizeof(readBytes)); 475 | assert(nRet == sizeof(readBytes)); 476 | assert((readBytes + sizeof(int)) == fromData->returnSize); 477 | if (m_config.bUseSharedMemory) { 478 | void* sharedBufferView; 479 | bool sharedMemoryReopen = false; 480 | g_namedPipe.Read((BYTE*)&sharedMemoryReopen, sizeof(sharedMemoryReopen)); 481 | if (sharedMemoryReopen) { 482 | g_videoSharedMemory.CloseHandle(); 483 | std::wstring sharedMemoryName = kVideoSharedMemoryPrefix + g_randamString + std::to_wstring(spp.perBufferSize); 484 | sharedBufferView = g_videoSharedMemory.OpenSharedMemory(sharedMemoryName.c_str(), true); 485 | assert(sharedBufferView); 486 | if (!sharedBufferView) { 487 | DWORD error = ::GetLastError(); 488 | std::wstring errorMsg = L"g_videoSharedMemory.OpenSharedMemoryに失敗\nsharedMemoryName: " + sharedMemoryName + L"\nGetLastError: " + std::to_wstring(error); 489 | MessageBox(NULL, errorMsg.c_str(), L"InputPipePluginエラー", MB_ICONERROR); 490 | return 0; 491 | } 492 | } else { 493 | sharedBufferView = g_videoSharedMemory.GetPointer(); 494 | } 495 | memcpy_s(buf, readBytes, sharedBufferView, readBytes); 496 | } else { 497 | nRet = g_namedPipe.Read((BYTE*)buf, readBytes); 498 | assert(nRet == readBytes); 499 | } 500 | 501 | #ifdef DEBUG_PROCESSINGTIME // 処理時間計測 502 | auto processingTime = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - startTime).count(); 503 | static bool firstSkip = true; 504 | 505 | static std::vector processingTimes; 506 | enum { kMaxTime = 100 }; 507 | if (!firstSkip) { 508 | processingTimes.emplace_back(processingTime); 509 | if (processingTimes.size() == kMaxTime) { 510 | long long avgTime = 0; 511 | for (auto time : processingTimes) { 512 | avgTime += time; 513 | } 514 | avgTime /= 100; 515 | WARN_LOG << L"processingTime : " << processingTime << L"µs avg: " << avgTime << L"µs"; 516 | processingTimes.clear(); 517 | } 518 | } else { 519 | firstSkip = false; 520 | processingTimes.reserve(kMaxTime); 521 | } 522 | #endif 523 | return readBytes; 524 | 525 | } else { 526 | 527 | int readBytes = Plugin_func_read_video(ih, frame, buf); 528 | 529 | #ifdef DEBUG_PROCESSINGTIME // 処理時間計測 530 | auto processingTime = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - startTime).count(); 531 | static bool firstSkip = true; 532 | 533 | static std::vector processingTimes; 534 | enum { kMaxTime = 100 }; 535 | if (!firstSkip) { 536 | processingTimes.emplace_back(processingTime); 537 | if (processingTimes.size() == kMaxTime) { 538 | long long avgTime = 0; 539 | for (auto time : processingTimes) { 540 | avgTime += time; 541 | } 542 | avgTime /= 100; 543 | WARN_LOG << L"processingTime : " << processingTime << L"µs avg: " << avgTime << L"µs"; 544 | processingTimes.clear(); 545 | } 546 | } else { 547 | firstSkip = false; 548 | processingTimes.reserve(kMaxTime); 549 | } 550 | #endif 551 | return readBytes; 552 | } 553 | 554 | } 555 | 556 | #undef DEBUG_PROCESSINGTIME 557 | 558 | //--------------------------------------------------------------------- 559 | // 音声読み込み 560 | //--------------------------------------------------------------------- 561 | int func_read_audio(INPUT_HANDLE ih, int start, int length, void* buf) 562 | { 563 | //INFO_LOG << L"func_read_audio: " << ih << L" start: " << start << L" length: " << length; 564 | std::lock_guard lock(g_mtxIPC); 565 | 566 | #ifdef DEBUG_PROCESSINGTIME 567 | auto startTime = std::chrono::high_resolution_clock::now(); 568 | #endif 569 | 570 | if (m_config.bEnableIPC) { 571 | const int PerAudioSampleBufferSize = g_mapFrameBufferSize[ih].PerAudioSampleBufferSize; 572 | 573 | StandardParamPack spp = { ih, start, length, PerAudioSampleBufferSize }; 574 | auto toData = GenerateToInputData(CallFunc::kReadAudio, spp); 575 | g_namedPipe.Write((const BYTE*)toData.get(), ToWinputDataTotalSize(*toData)); 576 | 577 | std::vector headerData = g_namedPipe.Read(kFromWinputDataHeaderSize); 578 | FromWinputData* fromData = (FromWinputData*)headerData.data(); 579 | //INFO_LOG << L"Read: " << fromData->returnSize << L" bytes"; 580 | assert(fromData->callFunc == CallFunc::kReadAudio); 581 | int readSample = 0; 582 | int nRet = g_namedPipe.Read((BYTE*)& readSample, sizeof(readSample)); 583 | assert(nRet == sizeof(readSample)); 584 | const int audioBufferSize = fromData->returnSize - sizeof(int); 585 | assert(audioBufferSize >= 0); 586 | if (m_config.bUseSharedMemory) { 587 | void* sharedBufferView; 588 | bool sharedMemoryReopen = false; 589 | g_namedPipe.Read((BYTE*)&sharedMemoryReopen, sizeof(sharedMemoryReopen)); 590 | if (sharedMemoryReopen) { 591 | g_audioSharedMemory.CloseHandle(); 592 | std::wstring sharedMemoryName = kAudioSharedMemoryPrefix + g_randamString + std::to_wstring(audioBufferSize); 593 | sharedBufferView = g_audioSharedMemory.OpenSharedMemory(sharedMemoryName.c_str(), true); 594 | if (!sharedBufferView) { 595 | DWORD error = ::GetLastError(); 596 | std::wstring errorMsg = L"g_audioSharedMemory.OpenSharedMemoryに失敗\nsharedMemoryName: " + sharedMemoryName + L"\nGetLastError: " + std::to_wstring(error); 597 | MessageBox(NULL, errorMsg.c_str(), L"InputPipePluginエラー", MB_ICONERROR); 598 | return 0; 599 | } 600 | assert(sharedBufferView); 601 | } else { 602 | sharedBufferView = g_audioSharedMemory.GetPointer(); 603 | } 604 | memcpy_s(buf, audioBufferSize, sharedBufferView, audioBufferSize); 605 | } else { 606 | nRet = g_namedPipe.Read((BYTE*)buf, audioBufferSize); 607 | assert(nRet == audioBufferSize); 608 | } 609 | 610 | #ifdef DEBUG_PROCESSINGTIME // 処理時間計測 611 | auto processingTime = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - startTime).count(); 612 | static bool firstSkip = true; 613 | 614 | static std::vector processingTimes; 615 | enum { kMaxTime = 100 }; 616 | if (!firstSkip) { 617 | processingTimes.emplace_back(processingTime); 618 | if (processingTimes.size() == kMaxTime) { 619 | long long avgTime = 0; 620 | for (auto time : processingTimes) { 621 | avgTime += time; 622 | } 623 | avgTime /= 100; 624 | WARN_LOG << L"processingTime : " << processingTime << L"µs avg: " << avgTime << L"µs"; 625 | processingTimes.clear(); 626 | } 627 | } else { 628 | firstSkip = false; 629 | processingTimes.reserve(kMaxTime); 630 | } 631 | #endif 632 | return readSample; 633 | } else { 634 | int n = Plugin_func_read_audio(ih, start, length, buf); 635 | #ifdef DEBUG_PROCESSINGTIME // 処理時間計測 636 | auto processingTime = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - startTime).count(); 637 | static bool firstSkip = true; 638 | 639 | static std::vector processingTimes; 640 | enum { kMaxTime = 100 }; 641 | if (!firstSkip) { 642 | processingTimes.emplace_back(processingTime); 643 | if (processingTimes.size() == kMaxTime) { 644 | long long avgTime = 0; 645 | for (auto time : processingTimes) { 646 | avgTime += time; 647 | } 648 | avgTime /= 100; 649 | WARN_LOG << L"processingTime : " << processingTime << L"µs avg: " << avgTime << L"µs"; 650 | processingTimes.clear(); 651 | } 652 | } else { 653 | firstSkip = false; 654 | processingTimes.reserve(kMaxTime); 655 | } 656 | #endif 657 | return n; 658 | } 659 | } 660 | 661 | 662 | //--------------------------------------------------------------------- 663 | // キーフレーム情報 664 | //--------------------------------------------------------------------- 665 | BOOL func_is_keyframe(INPUT_HANDLE ih, int frame) 666 | { 667 | // INFO_LOG << L"func_is_keyframe" << L" frame:" << frame; 668 | std::lock_guard lock(g_mtxIPC); 669 | 670 | if (m_config.bEnableIPC) { 671 | StandardParamPack spp = { ih, frame }; 672 | auto toData = GenerateToInputData(CallFunc::kIsKeyframe, spp); 673 | g_namedPipe.Write((const BYTE*)toData.get(), ToWinputDataTotalSize(*toData)); 674 | 675 | std::vector headerData = g_namedPipe.Read(kFromWinputDataHeaderSize); 676 | FromWinputData* fromData = (FromWinputData*)headerData.data(); 677 | assert(fromData->callFunc == CallFunc::kIsKeyframe); 678 | std::vector readBody = g_namedPipe.Read(fromData->returnSize); 679 | auto retData = ParseFromInputData(readBody); 680 | return retData.first; 681 | } else { 682 | BOOL b = g_winputPluginTable->func_is_keyframe(ih, frame); 683 | return b; 684 | } 685 | } 686 | 687 | 688 | //--------------------------------------------------------------------- 689 | // 設定ダイアログ 690 | //--------------------------------------------------------------------- 691 | BOOL func_config( HWND hwnd, HINSTANCE dll_hinst ) 692 | { 693 | // INFO_LOG << L"func_config"; 694 | #ifndef NO_REMOTE 695 | auto InputPipeMainPath = GetExeDirectory() / L"InputPipeMain.exe"; 696 | ::ShellExecute(NULL, NULL, InputPipeMainPath.c_str(), L" -config", NULL, SW_SHOWNORMAL); 697 | return TRUE; 698 | 699 | #else 700 | BOOL b = g_winputPluginTable->func_config(hwnd, dll_hinst); 701 | return b; 702 | #endif 703 | } 704 | 705 | 706 | --------------------------------------------------------------------------------