Created
March 20, 2022 13:00
-
-
Save Patman86/71a7db5cb65169f607d8da692ca271f5 to your computer and use it in GitHub Desktop.
Modifikation to Support VapourSynth R57
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "VapourSynthServer.h" | |
// IUnknown | |
HRESULT __stdcall VapourSynthServer::QueryInterface(const IID& iid, void** ppv) | |
{ | |
if (!ppv) | |
return E_POINTER; | |
if (iid == IID_IUnknown || iid == IID_IFrameServer) | |
{ | |
*ppv = this; | |
AddRef(); | |
return S_OK; | |
} | |
*ppv = NULL; | |
return E_NOINTERFACE; | |
} | |
ULONG __stdcall VapourSynthServer::AddRef() | |
{ | |
return ++m_References; | |
} | |
ULONG __stdcall VapourSynthServer::Release() { | |
int refs = --m_References; | |
if (!refs) | |
delete this; | |
return refs; | |
} | |
// IFrameServer | |
HRESULT __stdcall VapourSynthServer::OpenFile(WCHAR* file) | |
{ | |
try | |
{ | |
static bool wasResolved = false; | |
if (!wasResolved) | |
{ | |
HMODULE dll = LoadLibrary(L"VSScript"); | |
if (!dll) | |
{ | |
std::string msg = GetWinErrorMessage(GetLastError()); | |
throw std::runtime_error("Failed to load VSScript:\r\n\r\n" + msg); | |
} | |
bool x64 = sizeof(void*) == 8; | |
getVSScriptAPI = reinterpret_cast<vss_api>(GetProcAddress(dll, "getVSScriptAPI")); | |
if (!getVSScriptAPI) | |
{ | |
throw std::exception("Failed to resolve VapourSynth vsscript functions"); | |
} | |
} | |
wasResolved = true; | |
m_vssapi = getVSScriptAPI(VSSCRIPT_API_VERSION); | |
if (!m_vssapi) | |
{ | |
throw std::exception("Failed to initialize VSScript"); | |
} | |
m_vsAPI = m_vssapi->getVSAPI(VAPOURSYNTH_API_VERSION); | |
if (!m_vsAPI) | |
{ | |
throw std::exception("Failed to get VapourSynth API pointer"); | |
} | |
std::string utf8file = ConvertWideToUtf8(file); | |
m_core = m_vsAPI->createCore(0); | |
m_vsScript = m_vssapi->createScript(m_core); | |
m_vssapi->evalSetWorkingDir(m_vsScript, 1); | |
m_vssapi->evaluateFile(m_vsScript, utf8file.c_str()); | |
if (m_vssapi->getError(m_vsScript)) | |
{ | |
m_Error = ConvertUtf8ToWide(m_vssapi->getError(m_vsScript)); | |
Free(); | |
return E_FAIL; | |
} | |
m_vsNode = m_vssapi->getOutputNode(m_vsScript, 0); | |
if (!m_vsNode || m_vsAPI->getNodeType(m_vsNode) != mtVideo) | |
throw std::exception("Failed to get VapourSynth output"); | |
VSCoreInfo core_info; | |
m_vsAPI->getCoreInfo(m_vssapi->getCore(m_vsScript), &core_info); | |
m_vsInfo = m_vsAPI->getVideoInfo(m_vsNode); | |
if (!m_vsInfo) | |
throw std::exception("Failed to get VapourSynth info"); | |
m_Info.Width = m_vsInfo->width; | |
m_Info.Height = m_vsInfo->height; | |
m_Info.FrameCount = m_vsInfo->numFrames; | |
m_Info.FrameRateNum = m_vsInfo->fpsNum; | |
m_Info.FrameRateDen = m_vsInfo->fpsDen; | |
uint32_t id = m_vsAPI->queryVideoFormatID(m_vsInfo->format.colorFamily, m_vsInfo->format.sampleType, m_vsInfo->format.bitsPerSample, m_vsInfo->format.subSamplingW, m_vsInfo->format.subSamplingH, m_core); | |
if (id == pfYUV444P8) m_Info.ColorSpace = VideoInfo::CS_YV24; | |
else if (id == pfYUV422P8) m_Info.ColorSpace = VideoInfo::CS_YV16; | |
else if (id == pfYUV420P8) m_Info.ColorSpace = VideoInfo::CS_YV12; | |
else if (id == pfYUV410P8) m_Info.ColorSpace = VideoInfo::CS_YUV9; | |
else if (id == pfYUV411P8) m_Info.ColorSpace = VideoInfo::CS_YV411; | |
else if (id == pfGray8) m_Info.ColorSpace = VideoInfo::CS_Y8; | |
else if (id == pfYUV444P10) m_Info.ColorSpace = VideoInfo::CS_YUV444P10; | |
else if (id == pfYUV422P10) m_Info.ColorSpace = VideoInfo::CS_YUV422P10; | |
else if (id == pfYUV420P10) m_Info.ColorSpace = VideoInfo::CS_YUV420P10; | |
else if (id == pfYUV444P12) m_Info.ColorSpace = VideoInfo::CS_YUV444P12; | |
else if (id == pfYUV422P12) m_Info.ColorSpace = VideoInfo::CS_YUV422P12; | |
else if (id == pfYUV420P12) m_Info.ColorSpace = VideoInfo::CS_YUV420P12; | |
else if (id == pfYUV444P14) m_Info.ColorSpace = VideoInfo::CS_YUV444P14; | |
else if (id == pfYUV422P14) m_Info.ColorSpace = VideoInfo::CS_YUV422P14; | |
else if (id == pfYUV420P14) m_Info.ColorSpace = VideoInfo::CS_YUV420P14; | |
else if (id == pfYUV444P16) m_Info.ColorSpace = VideoInfo::CS_YUV444P16; | |
else if (id == pfYUV422P16) m_Info.ColorSpace = VideoInfo::CS_YUV422P16; | |
else if (id == pfYUV420P16) m_Info.ColorSpace = VideoInfo::CS_YUV420P16; | |
else if (id == pfGray16) m_Info.ColorSpace = VideoInfo::CS_Y16; | |
else if (id == pfYUV444PS) m_Info.ColorSpace = VideoInfo::CS_YUV444PS; | |
else if (id == pfGrayS) m_Info.ColorSpace = VideoInfo::CS_Y32; | |
else if (id == pfRGB24) m_Info.ColorSpace = VideoInfo::CS_RGBP; | |
else if (id == pfRGB30) m_Info.ColorSpace = VideoInfo::CS_RGBP10; | |
else if (id == pfRGB48) m_Info.ColorSpace = VideoInfo::CS_RGBP16; | |
else if (id == pfGrayS) m_Info.ColorSpace = VideoInfo::CS_Y32; | |
else if (m_vsInfo->format.bitsPerSample == 12 && m_vsInfo->format.colorFamily == cfRGB) | |
m_Info.ColorSpace = VideoInfo::CS_RGBP12; | |
else if (m_vsInfo->format.bitsPerSample == 14 && m_vsInfo->format.colorFamily == cfRGB) | |
m_Info.ColorSpace = VideoInfo::CS_RGBP14; | |
else if (m_vsInfo->format.bitsPerSample == 32 && m_vsInfo->format.colorFamily == cfYUV && m_vsInfo->format.sampleType == stFloat && m_vsInfo->format.subSamplingH == 0 && m_vsInfo->format.subSamplingW == 1) | |
m_Info.ColorSpace = VideoInfo::CS_YUV422PS; | |
else if (m_vsInfo->format.bitsPerSample == 32 && m_vsInfo->format.colorFamily == cfYUV && m_vsInfo->format.sampleType == stFloat && m_vsInfo->format.subSamplingH == 1 && m_vsInfo->format.subSamplingW == 1) | |
m_Info.ColorSpace = VideoInfo::CS_YUV420PS; | |
else if (m_vsInfo->format.bitsPerSample == 12 && m_vsInfo->format.colorFamily == cfGray && m_vsInfo->format.sampleType == stInteger) | |
m_Info.ColorSpace = VideoInfo::CS_Y12; | |
else if (m_vsInfo->format.bitsPerSample == 10 && m_vsInfo->format.colorFamily == cfGray && m_vsInfo->format.sampleType == stInteger) | |
m_Info.ColorSpace = VideoInfo::CS_Y10; | |
else if (m_vsInfo->format.bitsPerSample == 14 && m_vsInfo->format.colorFamily == cfGray && m_vsInfo->format.sampleType == stInteger) | |
m_Info.ColorSpace = VideoInfo::CS_Y14; | |
return S_OK; | |
} | |
catch (std::exception& e) | |
{ | |
m_Error = ConvertAnsiToWide(e.what()); | |
} | |
Free(); | |
return E_FAIL; | |
} | |
HRESULT __stdcall VapourSynthServer::GetFrame(int position, void** data, int& pitch) | |
{ | |
if (!data) | |
return E_POINTER; | |
if (!m_vsAPI || !m_vsNode) | |
return E_FAIL; | |
const VSFrame* frame = m_vsAPI->getFrame(position, m_vsNode, m_vsErrorMessage, sizeof(m_vsErrorMessage)); | |
if (!frame) | |
{ | |
m_Error = ConvertUtf8ToWide(m_vsErrorMessage); | |
return E_FAIL; | |
} | |
*data = (void*)m_vsAPI->getReadPtr(frame, 0); | |
if (!(*data)) | |
{ | |
m_Error = L"VapourSynthServer m_vsAPI->getReadPtr returned NULL"; | |
return E_FAIL; | |
} | |
pitch = m_vsAPI->getStride(frame, 0); | |
if (m_vsFrame) | |
m_vsAPI->freeFrame(m_vsFrame); | |
m_vsFrame = frame; | |
return S_OK; | |
} | |
ServerInfo* __stdcall VapourSynthServer::GetInfo() | |
{ | |
return &m_Info; | |
} | |
WCHAR* __stdcall VapourSynthServer::GetError() | |
{ | |
return (WCHAR*)m_Error.c_str(); | |
} | |
/////////// local | |
VapourSynthServer::~VapourSynthServer() | |
{ | |
Free(); | |
} | |
void VapourSynthServer::Free() | |
{ | |
if (m_vsAPI) | |
{ | |
if (m_vsFrame) | |
{ | |
m_vsAPI->freeFrame(m_vsFrame); | |
m_vsFrame = NULL; | |
} | |
if (m_vsNode) | |
{ | |
m_vsAPI->freeNode(m_vsNode); | |
m_vsNode = NULL; | |
} | |
} | |
if (m_vsScript) | |
{ | |
m_vssapi->freeScript(m_vsScript); | |
m_vsScript = NULL; | |
} | |
} | |
// Extern | |
extern "C" __declspec(dllexport) VapourSynthServer* __stdcall | |
CreateVapourSynthServer() | |
{ | |
VapourSynthServer* server = new VapourSynthServer(); | |
server->AddRef(); | |
return server; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#define WIN32_LEAN_AND_MEAN | |
#include "Common.h" | |
#include "FrameServer.h" | |
#include "avisynth.h" | |
#include "VSScript4.h" | |
#include "VSHelper4.h" | |
#include "Windows.h" | |
#include <atomic> | |
#include <array> | |
using vss_api = const VSSCRIPTAPI* (VS_CC*)(int version); | |
class VapourSynthServer : IFrameServer | |
{ | |
private: | |
std::atomic<int> m_References = 0; | |
std::wstring m_Error; | |
ServerInfo m_Info = {}; | |
vss_api getVSScriptAPI; | |
const VSAPI* m_vsAPI = NULL; | |
const VSSCRIPTAPI* m_vssapi = NULL; | |
VSScript* m_vsScript = NULL; | |
VSNode* m_vsNode = NULL; | |
VSCore* m_core = NULL; | |
const VSFrame* m_vsFrame = NULL; | |
const VSVideoInfo* m_vsInfo = NULL; | |
char m_vsErrorMessage[1024]; | |
void Free(); | |
public: | |
~VapourSynthServer(); | |
// IUnknown | |
HRESULT __stdcall QueryInterface(const IID& iid, void** ppv); | |
ULONG __stdcall AddRef(); | |
ULONG __stdcall Release(); | |
// IFrameServer | |
HRESULT __stdcall OpenFile(WCHAR* file); | |
HRESULT __stdcall GetFrame(int position, void** data, int& pitch); | |
ServerInfo* __stdcall GetInfo(); | |
WCHAR* __stdcall GetError(); | |
}; | |
extern "C" __declspec(dllexport) VapourSynthServer* __stdcall CreateVapourSynthServer(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment