Filter SDK/DualPlugins

From Avisynth wiki
(Difference between revisions)
Jump to: navigation, search
(Brute force solution two)

Revision as of 17:22, 1 September 2013

There are three ways to make 2.6 plugins (that is plugins compiled with plugin api v5 or higher) work with AviSynth 2.5, provided that you use the 2.5 feature set. They are described here below.

Brute force solution one

This solution doubles all the code. You need to rename avisynth.h (v3) to avisynth25.h and avisynth.h (v5) to avisynth26.h and add them both to your project. You also need to add the following two source files to your project:

InvertNeg25.cpp

#include <windows.h>
#include "avisynth25.h"

class InvertNeg25 : public GenericVideoFilter {
public:
   InvertNeg25(PClip _child, IScriptEnvironment* env);
   PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env);
};

InvertNeg25::InvertNeg25(PClip _child, IScriptEnvironment* env) :
   GenericVideoFilter(_child) {
   if (!vi.IsPlanar() || !vi.IsYUV()) {
      env->ThrowError("InvertNeg: planar YUV data only!");
   }
}

PVideoFrame __stdcall InvertNeg25::GetFrame(int n, IScriptEnvironment* env) {

   PVideoFrame src = child->GetFrame(n, env);
   PVideoFrame dst = env->NewVideoFrame(vi);

   const unsigned char* srcp;
   unsigned char* dstp;
   int src_pitch, dst_pitch, row_size, height;
   int p, x, y;

   int planes[] = {PLANAR_Y, PLANAR_V, PLANAR_U};
	
   for (p=0; p<3; p++) {
      srcp = src->GetReadPtr(planes[p]);
      dstp = dst->GetWritePtr(planes[p]);

      src_pitch = src->GetPitch(planes[p]);
      dst_pitch = dst->GetPitch(planes[p]);
      row_size = dst->GetRowSize(planes[p]);
      height = dst->GetHeight(planes[p]);

      for (y = 0; y < height; y++) {
         for (x = 0; x < row_size; x++) {
            dstp[x] = srcp[x] ^ 255;
         }
         srcp += src_pitch;
         dstp += dst_pitch;
      }
   }
   return dst;
}

AVSValue __cdecl Create_InvertNeg25(AVSValue args, void* user_data, IScriptEnvironment* env) {
   return new InvertNeg25(args[0].AsClip(), env);
}

extern "C" __declspec(dllexport) const char* __stdcall AvisynthPluginInit2(IScriptEnvironment* env) {
   env->AddFunction("InvertNeg", "c", Create_InvertNeg25, 0);
   return "InvertNeg sample plugin";
}


InvertNeg26.cpp

#include <windows.h>
#include "avisynth26.h"

class InvertNeg26 : public GenericVideoFilter {
public:
   InvertNeg26(PClip _child, IScriptEnvironment* env);
   PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env);
};

InvertNeg26::InvertNeg26(PClip _child, IScriptEnvironment* env) :
   GenericVideoFilter(_child) {
   if (!vi.IsPlanar() || !vi.IsYUV()) {
      env->ThrowError("InvertNeg: planar YUV data only!");
   }
}

PVideoFrame __stdcall InvertNeg26::GetFrame(int n, IScriptEnvironment* env) {

   PVideoFrame src = child->GetFrame(n, env);
   PVideoFrame dst = env->NewVideoFrame(vi);

   const unsigned char* srcp;
   unsigned char* dstp;
   int src_pitch, dst_pitch, row_size, height;
   int p, x, y;

   int planes[] = {PLANAR_Y, PLANAR_V, PLANAR_U};
	
   for (p=0; p<3; p++) {
      srcp = src->GetReadPtr(planes[p]);
      dstp = dst->GetWritePtr(planes[p]);

      src_pitch = src->GetPitch(planes[p]);
      dst_pitch = dst->GetPitch(planes[p]);
      row_size = dst->GetRowSize(planes[p]);
      height = dst->GetHeight(planes[p]);

      for (y = 0; y < height; y++) {
         for (x = 0; x < row_size; x++) {
            dstp[x] = srcp[x] ^ 255;
         }
         srcp += src_pitch;
         dstp += dst_pitch;
      }
   }
   return dst;
}

AVSValue __cdecl Create_InvertNeg26(AVSValue args, void* user_data, IScriptEnvironment* env) {
   return new InvertNeg26(args[0].AsClip(), env);
}

const AVS_Linkage *AVS_linkage = 0;

extern "C" __declspec(dllexport) const char* __stdcall AvisynthPluginInit3(IScriptEnvironment* env, const AVS_Linkage* const vectors) {
   AVS_linkage = vectors;
   env->AddFunction("InvertNeg", "c", Create_InvertNeg26, 0);
   return "InvertNeg sample plugin";
}

Note that both functions Create_InvertNeg25 and Create_InvertNeg26 are added in the function table (by AddFunction) as InvertNeg. Which one is called by your script will be decided by the AvisynthPluginInit2 and AvisynthPluginInit3 entry points (and thus your AviSynth version).

Compile both files into a DLL named InvertNeg.dll. See compiling instructions. Now create an Avisynth script which looks something like this:

LoadPlugin("d:\path\InvertNeg.dll")
clip = BlankClip().ConvertToYV12()
return clip.InvertNeg()

It should work both for AviSynth 2.5 and 2.6.

Brute force solution two

To stop having to double your source code you could use the namespace trick the 2.0 import wrapper uses.

Place all the filter generic code into a separate file, "InvertNeg.hpp", and #include it twice. Technically you have two copies of everything binary, but only a single source code. Note: outside the namespace you uniquely access object names as avs25::name or avs26::name.

/* InverNeg.cpp */

include <windows.h>

namespace avs25 {
   #include "avisynth25.h"
   #include "InvertNeg.hpp"
}

namespace avs26 {
   #include "avs26/avisynth.h"
   const AVS_Linkage *AVS_linkage = 0;
   #include "InvertNeg.hpp"
}

extern "C" __declspec(dllexport) const char* __stdcall AvisynthPluginInit3(IScriptEnvironment* env, const avs26::AVS_Linkage* const vectors) {
   avs26::AVS_linkage = vectors;
   env->AddFunction("InvertNeg", "c", avs26::Create_InvertNeg, 0);
   return "InvertNeg sample plugin";
}

extern "C" __declspec(dllexport) const char* __stdcall AvisynthPluginInit2(IScriptEnvironment* env) {
   env->AddFunction("InvertNeg", "c", avs25::Create_InvertNeg, 0);
   return "InvertNeg sample plugin";
}


/* InverNeg.hpp */

class InvertNeg : public GenericVideoFilter {
public:
   InvertNeg(PClip _child, IScriptEnvironment* env);
   PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env);
};

InvertNeg::InvertNeg(PClip _child, IScriptEnvironment* env) :
   GenericVideoFilter(_child) {
   if (!vi.IsPlanar() || !vi.IsYUV()) {
      env->ThrowError("InvertNeg: planar YUV data only!");
   }
}

PVideoFrame __stdcall InvertNeg::GetFrame(int n, IScriptEnvironment* env) {

   PVideoFrame src = child->GetFrame(n, env);
   PVideoFrame dst = env->NewVideoFrame(vi);

   const unsigned char* srcp;
   unsigned char* dstp;
   int src_pitch, dst_pitch, row_size, height;
   int p, x, y;

   int planes[] = {PLANAR_Y, PLANAR_V, PLANAR_U};
	
   for (p=0; p<3; p++) {
      srcp = src->GetReadPtr(planes[p]);
      dstp = dst->GetWritePtr(planes[p]);

      src_pitch = src->GetPitch(planes[p]);
      dst_pitch = dst->GetPitch(planes[p]);
      row_size = dst->GetRowSize(planes[p]);
      height = dst->GetHeight(planes[p]);

      for (y = 0; y < height; y++) {
         for (x = 0; x < row_size; x++) {
            dstp[x] = srcp[x] ^ 255;
         }
         srcp += src_pitch;
         dstp += dst_pitch;
      }
   }
   return dst;
}

AVSValue __cdecl Create_InvertNeg(AVSValue args, void* user_data, IScriptEnvironment* env) {
   return new InvertNeg(args[0].AsClip(), env);
}

Compile this file into a DLL named InvertNeg.dll. See compiling instructions. Now create an Avisynth script which looks something like this:

LoadPlugin("d:\path\InvertNeg.dll")
clip = BlankClip().ConvertToYV12()
return clip.InvertNeg()

TODO: try it out!!!

http://forum.doom9.org/showthread.php?p=1641372#post1641372

xxx

http://forum.doom9.org/showthread.php?p=1641346#post1641346 and subsequent posts ....

Personal tools