Skip to content

Instantly share code, notes, and snippets.

@Patman86
Created March 20, 2022 13:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Patman86/71a7db5cb65169f607d8da692ca271f5 to your computer and use it in GitHub Desktop.
Save Patman86/71a7db5cb65169f607d8da692ca271f5 to your computer and use it in GitHub Desktop.
Modifikation to Support VapourSynth R57
#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;
}
#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