mirror of https://github.com/odrling/Aegisub
156 lines
4.6 KiB
C++
156 lines
4.6 KiB
C++
|
/*****************************************************************************
|
||
|
* asa: portable digital subtitle renderer
|
||
|
*****************************************************************************
|
||
|
* Copyright (C) 2006 David Lamparter
|
||
|
*
|
||
|
* This program is free software; you can redistribute it and/or modify
|
||
|
* it under the terms of the GNU General Public License as published by
|
||
|
* the Free Software Foundation; either version 2 of the License, or
|
||
|
* (at your option) any later version.
|
||
|
*
|
||
|
* This program is distributed in the hope that it will be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
* GNU General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU General Public License
|
||
|
* along with this program; if not, write to the Free Software
|
||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||
|
****************************************************************************/
|
||
|
|
||
|
#include <windows.h>
|
||
|
#include "avisynth.h"
|
||
|
#include <stdio.h>
|
||
|
|
||
|
#include <csri/csri.h>
|
||
|
|
||
|
class CSRIAviSynth : public GenericVideoFilter {
|
||
|
csri_inst *inst;
|
||
|
double spf;
|
||
|
|
||
|
public:
|
||
|
CSRIAviSynth(PClip _child, IScriptEnvironment *env, const char *file,
|
||
|
const char *rendname, const char *rendver);
|
||
|
~CSRIAviSynth();
|
||
|
|
||
|
enum csri_pixfmt GetPixfmt();
|
||
|
|
||
|
PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment *env);
|
||
|
|
||
|
static AVSValue __cdecl Create(AVSValue args, void* user_data,
|
||
|
IScriptEnvironment* env);
|
||
|
};
|
||
|
|
||
|
CSRIAviSynth::CSRIAviSynth(PClip _child, IScriptEnvironment *env,
|
||
|
const char *file, const char *rendname, const char *rendver)
|
||
|
: GenericVideoFilter(_child)
|
||
|
{
|
||
|
csri_rend *r = csri_renderer_byname(rendname, rendver);
|
||
|
if (!r) {
|
||
|
if (rendver)
|
||
|
env->ThrowError("Failed to load renderer \"%s\""
|
||
|
" version \"%s\"", rendname, rendver);
|
||
|
else if (rendname)
|
||
|
env->ThrowError("Failed to load renderer \"%s\"",
|
||
|
rendname);
|
||
|
else
|
||
|
env->ThrowError("Failed to load default renderer");
|
||
|
}
|
||
|
|
||
|
struct csri_fmt fmt;
|
||
|
fmt.pixfmt = GetPixfmt();
|
||
|
if (fmt.pixfmt == -1)
|
||
|
env->ThrowError("Pixel format not supported by "
|
||
|
"AviSynth interface");
|
||
|
|
||
|
inst = csri_open_file(r, file, NULL);
|
||
|
if (!inst)
|
||
|
env->ThrowError("Failed to load \"%s\"", file);
|
||
|
|
||
|
fmt.width = vi.width;
|
||
|
fmt.height = vi.height;
|
||
|
if (csri_request_fmt(inst, &fmt)) {
|
||
|
csri_close(inst);
|
||
|
env->ThrowError("Selected pixel format or size not supported "
|
||
|
"by selected subtitle renderer", file);
|
||
|
}
|
||
|
spf = (double)vi.fps_denominator / (double)vi.fps_numerator;
|
||
|
}
|
||
|
|
||
|
CSRIAviSynth::~CSRIAviSynth()
|
||
|
{
|
||
|
csri_close(inst);
|
||
|
}
|
||
|
|
||
|
enum csri_pixfmt CSRIAviSynth::GetPixfmt()
|
||
|
{
|
||
|
switch (vi.pixel_type) {
|
||
|
case VideoInfo::CS_BGR24: return CSRI_F_BGR;
|
||
|
case VideoInfo::CS_BGR32: return CSRI_F_BGR_;
|
||
|
case VideoInfo::CS_YUY2: return CSRI_F_YUY2;
|
||
|
case VideoInfo::CS_YV12: return CSRI_F_YV12;
|
||
|
}
|
||
|
return (enum csri_pixfmt)-1;
|
||
|
}
|
||
|
|
||
|
PVideoFrame __stdcall CSRIAviSynth::GetFrame(int n, IScriptEnvironment *env)
|
||
|
{
|
||
|
PVideoFrame avsframe = child->GetFrame(n, env);
|
||
|
struct csri_frame frame;
|
||
|
|
||
|
env->MakeWritable(&avsframe);
|
||
|
|
||
|
frame.pixfmt = GetPixfmt();
|
||
|
frame.planes[0] = avsframe->GetWritePtr();
|
||
|
frame.strides[0] = avsframe->GetPitch();
|
||
|
if (csri_is_yuv_planar(frame.pixfmt)) {
|
||
|
frame.planes[1] = avsframe->GetWritePtr(PLANAR_U);
|
||
|
frame.strides[1] = avsframe->GetPitch(PLANAR_U);
|
||
|
frame.planes[2] = avsframe->GetWritePtr(PLANAR_V);
|
||
|
frame.strides[2] = avsframe->GetPitch(PLANAR_V);
|
||
|
}
|
||
|
if (csri_is_rgb(frame.pixfmt)) {
|
||
|
frame.planes[0] += (vi.height - 1) * frame.strides[0];
|
||
|
frame.strides[0] = -frame.strides[0];
|
||
|
}
|
||
|
|
||
|
csri_render(inst, &frame, n * spf);
|
||
|
return avsframe;
|
||
|
}
|
||
|
|
||
|
AVSValue __cdecl CSRIAviSynth::Create(AVSValue args, void* user_data,
|
||
|
IScriptEnvironment* env)
|
||
|
{
|
||
|
const char *rname = args.ArraySize() >= 2 ? args[2].AsString() : NULL,
|
||
|
*rver = args.ArraySize() >= 3 ? args[3].AsString() : NULL;
|
||
|
return new CSRIAviSynth(args[0].AsClip(), env, args[1].AsString(),
|
||
|
rname, rver);
|
||
|
}
|
||
|
|
||
|
extern "C" __declspec(dllexport) const char* __stdcall AvisynthPluginInit2(
|
||
|
IScriptEnvironment* env)
|
||
|
{
|
||
|
static char avs_name_f[2048];
|
||
|
const char *avs_cmdname = (const char *)csri_query_ext(NULL,
|
||
|
"csri.avisynth25.command_name");
|
||
|
const char *avs_name = (const char *)csri_query_ext(NULL,
|
||
|
"csri.avisynth25.name");
|
||
|
|
||
|
if (!csri_renderer_default())
|
||
|
return NULL;
|
||
|
|
||
|
if (!avs_cmdname)
|
||
|
avs_cmdname = "CSRI";
|
||
|
if (!avs_name)
|
||
|
avs_name = "Common Subtitle Renderer Interface";
|
||
|
|
||
|
env->AddFunction(avs_cmdname, "cs", CSRIAviSynth::Create, 0);
|
||
|
env->AddFunction(avs_cmdname, "css", CSRIAviSynth::Create, 0);
|
||
|
env->AddFunction(avs_cmdname, "csss", CSRIAviSynth::Create, 0);
|
||
|
|
||
|
snprintf(avs_name_f, sizeof(avs_name_f),
|
||
|
"%s [AviSynth 2.5 front-end]", avs_name);
|
||
|
return avs_name_f;
|
||
|
}
|
||
|
|