/***************************************************************************** * 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 #include "avisynth.h" #include #include 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; }