mirror of
https://github.com/staxrip/staxrip.git
synced 2026-10-18 22:50:34 +08:00
197 lines
4.1 KiB
C++
197 lines
4.1 KiB
C++
|
|
#include "AviSynthServer.h"
|
|
|
|
|
|
///////// IUnknown
|
|
|
|
HRESULT __stdcall AviSynthServer::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 AviSynthServer::AddRef()
|
|
{
|
|
return ++m_References;
|
|
}
|
|
|
|
|
|
ULONG __stdcall AviSynthServer::Release() {
|
|
int refs = --m_References;
|
|
|
|
if (!refs)
|
|
delete this;
|
|
|
|
return refs;
|
|
}
|
|
|
|
|
|
////////// IFrameServer
|
|
|
|
HRESULT __stdcall AviSynthServer::OpenFile(WCHAR* file)
|
|
{
|
|
try
|
|
{
|
|
memset(&m_Clip, 0, sizeof(PClip));
|
|
memset(&m_Frame, 0, sizeof(PVideoFrame));
|
|
|
|
WCHAR* dllPath = _wgetenv(L"AviSynthDLL");
|
|
HMODULE dll;
|
|
|
|
if (FileExists(dllPath))
|
|
dll = LoadLibrary(dllPath);
|
|
else
|
|
dll = LoadLibrary(L"AviSynth.dll");
|
|
|
|
if (!dll)
|
|
{
|
|
std::string msg = GetWinErrorMessage(GetLastError());
|
|
throw std::runtime_error("Failed to load AviSynth+: \r\n\r\n" + msg);
|
|
}
|
|
|
|
typedef IScriptEnvironment* (__stdcall* cse_t)(int);
|
|
cse_t create_env = reinterpret_cast<cse_t>(GetProcAddress(dll, "CreateScriptEnvironment"));
|
|
|
|
if (!create_env)
|
|
throw std::exception("Failed to get CreateScriptEnvironment");
|
|
|
|
m_ScriptEnvironment = create_env(6 /*AVS_INTERFACE_VERSION*/);
|
|
|
|
if (!m_ScriptEnvironment)
|
|
throw std::exception("A newer AviSynth version is required");
|
|
|
|
AVS_linkage = m_Linkage = m_ScriptEnvironment->GetAVSLinkage();
|
|
|
|
std::string ansiFile = ConvertWideToANSI(file);
|
|
AVSValue arg(ansiFile.c_str());
|
|
m_AVSValue = m_ScriptEnvironment->Invoke("Import", AVSValue(&arg, 1));
|
|
|
|
if (!m_AVSValue.IsClip())
|
|
throw std::exception("AviSynth+ script does not return a video clip");
|
|
|
|
m_Clip = m_AVSValue.AsClip();
|
|
|
|
VideoInfo vi = m_Clip->GetVideoInfo();
|
|
|
|
m_Info.Width = vi.width;
|
|
m_Info.Height = vi.height;
|
|
m_Info.FrameCount = vi.num_frames;
|
|
m_Info.FrameRateNum = vi.fps_numerator;
|
|
m_Info.FrameRateDen = vi.fps_denominator;
|
|
m_Info.ColorSpace = vi.pixel_type;
|
|
m_Info.BitsPerPixel = vi.BitsPerPixel();
|
|
|
|
return S_OK;
|
|
}
|
|
catch (AvisynthError& e)
|
|
{
|
|
m_Error = ConvertAnsiToWide(e.msg);
|
|
}
|
|
catch (std::exception& e)
|
|
{
|
|
m_Error = ConvertAnsiToWide(e.what());
|
|
}
|
|
catch (...)
|
|
{
|
|
m_Error = L"Exception: AviSynthServer::OpenFile";
|
|
}
|
|
|
|
Free();
|
|
return E_FAIL;
|
|
}
|
|
|
|
|
|
HRESULT __stdcall AviSynthServer::GetFrame(int position, void** data, int& pitch)
|
|
{
|
|
try
|
|
{
|
|
if (m_Info.FrameCount == 0)
|
|
return E_FAIL;
|
|
|
|
AVS_linkage = m_Linkage;
|
|
m_Frame = m_Clip->GetFrame(position, m_ScriptEnvironment);
|
|
*data = (void*)m_Frame->GetReadPtr();
|
|
|
|
if (!(*data))
|
|
throw std::exception("AviSynth+ pixel data pointer is null");
|
|
|
|
pitch = m_Frame->GetPitch();
|
|
return S_OK;
|
|
}
|
|
catch (AvisynthError& e)
|
|
{
|
|
m_Error = ConvertAnsiToWide(e.msg);
|
|
}
|
|
catch (std::exception& e)
|
|
{
|
|
m_Error = ConvertAnsiToWide(e.what());
|
|
}
|
|
catch (...)
|
|
{
|
|
m_Error = L"Exception: AviSynthServer::GetFrame";
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
ServerInfo* __stdcall AviSynthServer::GetInfo()
|
|
{
|
|
return &m_Info;
|
|
}
|
|
|
|
|
|
WCHAR* __stdcall AviSynthServer::GetError()
|
|
{
|
|
return (WCHAR*)m_Error.c_str();
|
|
}
|
|
|
|
|
|
/////////// local
|
|
|
|
AviSynthServer::~AviSynthServer()
|
|
{
|
|
Free();
|
|
}
|
|
|
|
|
|
void AviSynthServer::Free()
|
|
{
|
|
AVS_linkage = m_Linkage;
|
|
|
|
m_Frame = NULL;
|
|
m_Clip = NULL;
|
|
m_AVSValue = NULL;
|
|
|
|
if (m_ScriptEnvironment)
|
|
{
|
|
m_ScriptEnvironment->DeleteScriptEnvironment();
|
|
m_ScriptEnvironment = NULL;
|
|
}
|
|
|
|
AVS_linkage = NULL;
|
|
m_Linkage = NULL;
|
|
}
|
|
|
|
|
|
///////// extern
|
|
|
|
extern "C" __declspec(dllexport) AviSynthServer* __stdcall
|
|
CreateAviSynthServer()
|
|
{
|
|
AviSynthServer* server = new AviSynthServer();
|
|
server->AddRef();
|
|
return server;
|
|
}
|