<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="http://avisynth.nl/skins/common/feed.css?303"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>http://avisynth.nl/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jmac698</id>
		<title>Avisynth wiki - User contributions [en]</title>
		<link rel="self" type="application/atom+xml" href="http://avisynth.nl/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jmac698"/>
		<link rel="alternate" type="text/html" href="http://avisynth.nl/index.php/Special:Contributions/Jmac698"/>
		<updated>2026-04-07T22:30:04Z</updated>
		<subtitle>User contributions</subtitle>
		<generator>MediaWiki 1.19.24</generator>

	<entry>
		<id>http://avisynth.nl/index.php/Filter_SDK/SimpleSample</id>
		<title>Filter SDK/SimpleSample</title>
		<link rel="alternate" type="text/html" href="http://avisynth.nl/index.php/Filter_SDK/SimpleSample"/>
				<updated>2016-06-11T12:25:50Z</updated>
		
		<summary type="html">&lt;p&gt;Jmac698: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Note: An updated version of this example with source code, documentation, and Avisynth test scripts in available at http://forum.doom9.org/showthread.php?p=1656962#post1656962&lt;br /&gt;
&lt;br /&gt;
I have rewritten SimpleSample for AviSynth 2.6. I changed it into an in place filter (so the source is overwritten). It draws a white square in the center of the clip and it supports all colorformats.&lt;br /&gt;
&lt;br /&gt;
Here's simplesample.cpp:&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;windows.h&amp;gt;&lt;br /&gt;
 #include &amp;quot;avisynth.h&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 class SimpleSample : public GenericVideoFilter {&lt;br /&gt;
    int SquareSize;&lt;br /&gt;
 public:&lt;br /&gt;
    SimpleSample(PClip _child, int _SquareSize, IScriptEnvironment* env);&lt;br /&gt;
    ~SimpleSample();&lt;br /&gt;
    PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env);&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 SimpleSample::SimpleSample(PClip _child, int _SquareSize, IScriptEnvironment* env) :&lt;br /&gt;
    GenericVideoFilter(_child), SquareSize(_SquareSize) {&lt;br /&gt;
    if (vi.width&amp;lt;SquareSize || vi.height&amp;lt;SquareSize) {&lt;br /&gt;
       env-&amp;gt;ThrowError(&amp;quot;SimpleSample: square doesn't fit into the clip!&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 SimpleSample::~SimpleSample() {}&lt;br /&gt;
 &lt;br /&gt;
 PVideoFrame __stdcall SimpleSample::GetFrame(int n, IScriptEnvironment* env) {&lt;br /&gt;
 &lt;br /&gt;
    PVideoFrame src = child-&amp;gt;GetFrame(n, env);&lt;br /&gt;
    env-&amp;gt;MakeWritable(&amp;amp;src);&lt;br /&gt;
 &lt;br /&gt;
    unsigned char* srcp = src-&amp;gt;GetWritePtr();&lt;br /&gt;
    int src_pitch = src-&amp;gt;GetPitch();&lt;br /&gt;
    int src_width = src-&amp;gt;GetRowSize();&lt;br /&gt;
    int src_height = src-&amp;gt;GetHeight();&lt;br /&gt;
 &lt;br /&gt;
    int w, h, woffset;&lt;br /&gt;
 &lt;br /&gt;
    if (vi.IsRGB24()) {&lt;br /&gt;
       srcp = srcp + (src_height/2 - SquareSize/2) * src_pitch;&lt;br /&gt;
 &lt;br /&gt;
       woffset = src_width/2 - 3*SquareSize/2;&lt;br /&gt;
 &lt;br /&gt;
       for (h=0; h&amp;lt;SquareSize; h++) {&lt;br /&gt;
          for (w=0; w&amp;lt;3*SquareSize; w+=3) {&lt;br /&gt;
             *(srcp + woffset + w) = 255;&lt;br /&gt;
             *(srcp + woffset + w + 1) = 255;&lt;br /&gt;
             *(srcp + woffset + w + 2) = 255;&lt;br /&gt;
          }															&lt;br /&gt;
          srcp += src_pitch;&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
    if (vi.IsRGB32()) {&lt;br /&gt;
       srcp = srcp + (src_height/2 - SquareSize/2) * src_pitch;&lt;br /&gt;
 &lt;br /&gt;
       woffset = src_width/2 - 4*SquareSize/2;&lt;br /&gt;
 &lt;br /&gt;
       for (h=0; h&amp;lt;SquareSize; h++) {&lt;br /&gt;
          for (w=0; w&amp;lt;4*SquareSize; w+=4) {&lt;br /&gt;
             *(srcp + woffset + w) = 255;&lt;br /&gt;
             *(srcp + woffset + w + 1) = 255;&lt;br /&gt;
             *(srcp + woffset + w + 2) = 255;&lt;br /&gt;
          }&lt;br /&gt;
          srcp += src_pitch;&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
 /*&lt;br /&gt;
    if (vi.IsRGB32()) { // variant 1 - processing a pixel at once&lt;br /&gt;
       srcp = srcp + (src_height/2 - SquareSize/2) * src_pitch;&lt;br /&gt;
 &lt;br /&gt;
       woffset = src_width/8 - SquareSize/2;&lt;br /&gt;
 &lt;br /&gt;
       for (h=0; h&amp;lt;SquareSize; h++) {&lt;br /&gt;
          for (w=0; w&amp;lt;SquareSize; w++) {&lt;br /&gt;
             *((unsigned int *)srcp + woffset + w) = 0x00FFFFFF;&lt;br /&gt;
          }	&lt;br /&gt;
          srcp += src_pitch;&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
 */&lt;br /&gt;
 /*&lt;br /&gt;
    if (vi.IsRGB32()) { // variant 2 - processing a pixel at once&lt;br /&gt;
       unsigned int* srcp = (unsigned int*)src-&amp;gt;GetWritePtr();&lt;br /&gt;
 	&lt;br /&gt;
       srcp = srcp + (src_height/2 - SquareSize/2) * src_pitch/4;&lt;br /&gt;
 &lt;br /&gt;
       woffset = src_width/8 - SquareSize/2;&lt;br /&gt;
 &lt;br /&gt;
       for (h=0; h&amp;lt;SquareSize; h++) {&lt;br /&gt;
          for (w=0; w&amp;lt;SquareSize; w++) {&lt;br /&gt;
             srcp[woffset + w] = 0x00FFFFFF;&lt;br /&gt;
          }	&lt;br /&gt;
          srcp += src_pitch/4;&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
 */&lt;br /&gt;
    if (vi.IsYUY2()) {&lt;br /&gt;
       srcp = srcp + (src_height/2 - SquareSize/2) * src_pitch;&lt;br /&gt;
 &lt;br /&gt;
       woffset = src_width/8 - SquareSize/4;&lt;br /&gt;
 &lt;br /&gt;
       for (h=0; h&amp;lt;SquareSize; h++) {&lt;br /&gt;
          for (w=0; w&amp;lt;SquareSize/2; w++) {&lt;br /&gt;
             *((unsigned int *)srcp + woffset + w) = 0x80EB80EB;&lt;br /&gt;
          }&lt;br /&gt;
          srcp += src_pitch; &lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
    if (vi.IsPlanar() &amp;amp;&amp;amp; vi.IsYUV()) {&lt;br /&gt;
 &lt;br /&gt;
       int planes[] = {PLANAR_Y, PLANAR_U, PLANAR_V};&lt;br /&gt;
       int square_value[] = {235, 128, 128};&lt;br /&gt;
       int p;&lt;br /&gt;
       int width_sub, height_sub;&lt;br /&gt;
 &lt;br /&gt;
       for (p=0; p&amp;lt;3; p++) {&lt;br /&gt;
          srcp = src-&amp;gt;GetWritePtr(planes[p]);		&lt;br /&gt;
          src_pitch = src-&amp;gt;GetPitch(planes[p]);&lt;br /&gt;
          src_width = src-&amp;gt;GetRowSize(planes[p]);&lt;br /&gt;
          src_height = src-&amp;gt;GetHeight(planes[p]);&lt;br /&gt;
          width_sub = vi.GetPlaneWidthSubsampling(planes[p]);&lt;br /&gt;
          height_sub = vi.GetPlaneHeightSubsampling(planes[p]);&lt;br /&gt;
 &lt;br /&gt;
          srcp = srcp + (src_height/2 - (SquareSize&amp;gt;&amp;gt;height_sub)/2) * src_pitch;&lt;br /&gt;
 &lt;br /&gt;
          woffset = src_width/2 - (SquareSize&amp;gt;&amp;gt;width_sub)/2;&lt;br /&gt;
 &lt;br /&gt;
          for (h=0; h&amp;lt;(SquareSize&amp;gt;&amp;gt;height_sub); h++) {&lt;br /&gt;
             for (w=0; w&amp;lt;(SquareSize&amp;gt;&amp;gt;width_sub); w++) {&lt;br /&gt;
                srcp[woffset + w] = square_value[p];&lt;br /&gt;
             }&lt;br /&gt;
             srcp += src_pitch;&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
    return src;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 AVSValue __cdecl Create_SimpleSample(AVSValue args, void* user_data, IScriptEnvironment* env) {&lt;br /&gt;
    return new SimpleSample(args[0].AsClip(),   &lt;br /&gt;
                            args[1].AsInt(100),&lt;br /&gt;
                            env); &lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 const AVS_Linkage *AVS_linkage = 0;&lt;br /&gt;
 &lt;br /&gt;
 extern &amp;quot;C&amp;quot; __declspec(dllexport) const char* __stdcall AvisynthPluginInit3(IScriptEnvironment* env, const AVS_Linkage* const vectors) {&lt;br /&gt;
    AVS_linkage = vectors;&lt;br /&gt;
    env-&amp;gt;AddFunction(&amp;quot;SimpleSample&amp;quot;, &amp;quot;c[size]i&amp;quot;, Create_SimpleSample, 0);&lt;br /&gt;
    return &amp;quot;SimpleSample plugin&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Compile this file into a DLL named InvertNeg.dll. See [[Filter_SDK/Compiling_instructions|compiling instructions]]. Now create an Avisynth script which looks something like this:&lt;br /&gt;
&lt;br /&gt;
 LoadPlugin(&amp;quot;d:\path\simplesample.dll&amp;quot;)&lt;br /&gt;
 Colorbars().Trim(0,1)&lt;br /&gt;
 ConvertTORGB32()&lt;br /&gt;
 # ConvertTOYV411()&lt;br /&gt;
 SimpleSample(100)&lt;br /&gt;
&lt;br /&gt;
=== Line by line breakdown ===&lt;br /&gt;
&lt;br /&gt;
Here's a line-by-line breakdown of simplesample.cpp. I won't repeat the comments in the previous example InvertNeg.cpp, so read that first if needed. The declaration of the class is as follows&lt;br /&gt;
&lt;br /&gt;
 class SimpleSample : public GenericVideoFilter {&lt;br /&gt;
    int SquareSize;&lt;br /&gt;
 public:&lt;br /&gt;
    SimpleSample(PClip _child,	int _SquareSize, IScriptEnvironment* env);&lt;br /&gt;
    ~SimpleSample();&lt;br /&gt;
    PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env);&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
With respect to our previous example there are two differences. It contains a private data member 'SquareSize' (members are private by default). Note that this is our parameter variable. These have to be declared here.&lt;br /&gt;
&lt;br /&gt;
The member function ~SimpleSample() is the declaration of the destructor. It fulfills the opposite functionality as the constructor. It is automatically called when the filter is destroyed. It is used to release allocated memory when the filter is destroyed. This is needed when there is memory allocated in the constructor. This is not the case in our filter, so we didn't need to declare it.&lt;br /&gt;
&lt;br /&gt;
 SimpleSample::~SimpleSample() {}&lt;br /&gt;
&lt;br /&gt;
This is the actual destructor. You can release allocated memory here using the operator delete.&lt;br /&gt;
&lt;br /&gt;
 SimpleSample::SimpleSample(PClip _child, int _SquareSize, IScriptEnvironment* env) :&lt;br /&gt;
    GenericVideoFilter(_child), SquareSize(_SquareSize) {&lt;br /&gt;
    if (vi.width&amp;lt;SquareSize || vi.height&amp;lt;SquareSize) {&lt;br /&gt;
       env-&amp;gt;ThrowError(&amp;quot;SimpleSample: square doesn't fit into the clip!&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This is the constructor. It initializes the value of SquareSize with the parameter that is passed to it (which is called _SquareSize here). It also checks whether the square which will be drawn fits in the frame, otherwise it will return an error.&lt;br /&gt;
&lt;br /&gt;
    unsigned char* srcp = src-&amp;gt;GetWritePtr();&lt;br /&gt;
    int src_pitch = src-&amp;gt;GetPitch();&lt;br /&gt;
    int src_width = src-&amp;gt;GetRowSize();&lt;br /&gt;
    int src_height = src-&amp;gt;GetHeight();&lt;br /&gt;
&lt;br /&gt;
The default value of plane is PLANAR_Y (= 0) for the functions GetReadPtr, GetWritePtr, GetPitch, GetRowSize and GetHeight. For planar formats this is the luma plane and for interleaved formats this is the whole frame.&lt;br /&gt;
&lt;br /&gt;
    if (vi.IsRGB24()) {&lt;br /&gt;
&lt;br /&gt;
When the clip has color format RGB24 the code path is taken. For RGB24 each pixel is represented by three bytes, blue, green and red (in that order). RGB is up side down, so srcp[0] will be the bottom-left pixel.&lt;br /&gt;
&lt;br /&gt;
       srcp = srcp + (src_height/2 - SquareSize/2) * src_pitch;&lt;br /&gt;
&lt;br /&gt;
The pointer is moved to the lower line of the square that will be drawn. Remember that src_height is the height in pixels.&lt;br /&gt;
 &lt;br /&gt;
       woffset = src_width/2 - 3*SquareSize/2;&lt;br /&gt;
&lt;br /&gt;
The offset is calculated of the left most byte of the square that will be drawn. Remember that src_width is the width in bytes. Since SquareSize is specified in pixels, the corresponding number of bytes is 3*SquareSize.&lt;br /&gt;
&lt;br /&gt;
       for (h=0; h&amp;lt;SquareSize; h++) {         // Loop from bottom line to top line.&lt;br /&gt;
          for (w=0; w&amp;lt;3*SquareSize; w+=3) {   // Loop from left side of the image to the right side 1 pixel (3 bytes) at a time&lt;br /&gt;
             *(srcp + woffset + w) = 255;     // this is the same as srcp[woffset+w]=255;&lt;br /&gt;
             *(srcp + woffset + w + 1) = 255; // this is the same as srcp[woffset+w+1]=255;&lt;br /&gt;
             *(srcp + woffset + w + 2) = 255; // this is the same as srcp[woffset+w+2]=255;&lt;br /&gt;
          }															&lt;br /&gt;
          srcp += src_pitch;&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
Here the white square is drawn. Each color component is set to 255.&lt;br /&gt;
&lt;br /&gt;
For RGB32 the following code path is taken&lt;br /&gt;
&lt;br /&gt;
    if (vi.IsRGB32()) {&lt;br /&gt;
       srcp = srcp + (src_height/2 - SquareSize/2) * src_pitch;&lt;br /&gt;
 &lt;br /&gt;
       woffset = src_width/2 - 4*SquareSize/2;&lt;br /&gt;
 &lt;br /&gt;
       for (h=0; h&amp;lt;SquareSize; h++) {&lt;br /&gt;
          for (w=0; w&amp;lt;4*SquareSize; w+=4) {&lt;br /&gt;
             *(srcp + woffset + w) = 255;&lt;br /&gt;
             *(srcp + woffset + w + 1) = 255;&lt;br /&gt;
             *(srcp + woffset + w + 2) = 255;&lt;br /&gt;
          }&lt;br /&gt;
          srcp += src_pitch;&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
It's the same as for RGB24, except a pixel is represented by four bytes, blue, green, red and alpha (in that order). Since SquareSize is specified in pixels, the corresponding number of bytes is 4*SquareSize. The fourth color component, the alpha channel, *(srcp + woffset + w + 3) is left untouched.&lt;br /&gt;
&lt;br /&gt;
It is possible to speed the code above up a bit since you can deal with whole 32bit variables at a time. This can be done in several ways:&lt;br /&gt;
&lt;br /&gt;
    if (vi.IsRGB32()) { // variant 1 - processing a pixel at once&lt;br /&gt;
       srcp = srcp + (src_height/2 - SquareSize/2) * src_pitch;&lt;br /&gt;
 &lt;br /&gt;
       woffset = src_width/8 - SquareSize/2;   // src_width/2 bytes equals src_width/8 pixels&lt;br /&gt;
 &lt;br /&gt;
       for (h=0; h&amp;lt;SquareSize; h++) {&lt;br /&gt;
          for (w=0; w&amp;lt;SquareSize; w++) {&lt;br /&gt;
             *((unsigned int *)srcp + woffset + w) = 0x00FFFFFF;&lt;br /&gt;
          }	&lt;br /&gt;
          srcp += src_pitch;&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
You need to cast srcp as unsigned int (instead of unsigned char). unsigned int is 4 bytes or 32 bits (it runs from 0 to 2^32-1), which is exactly what we need for one pixel. The casting is done in this line&lt;br /&gt;
&lt;br /&gt;
             *((unsigned int *)srcp + woffset + w) = 0x00FFFFFF;&lt;br /&gt;
&lt;br /&gt;
The value of a white pixel is 0x00FFFFFF (where the alpha pixel is set to black). When writing several bytes at once, you need to write the right one first and the left one last.&lt;br /&gt;
&lt;br /&gt;
It is also possible to declare srcp as unsigned int when defining it, but you have to take it into account in the rest of the code:&lt;br /&gt;
&lt;br /&gt;
    if (vi.IsRGB32()) { // variant 2 - processing a pixel at once&lt;br /&gt;
       unsigned int* srcp = (unsigned int*)src-&amp;gt;GetWritePtr();&lt;br /&gt;
 	&lt;br /&gt;
       srcp = srcp + (src_height/2 - SquareSize/2) * src_pitch/4;&lt;br /&gt;
 &lt;br /&gt;
       woffset = src_width/8 - SquareSize/2;&lt;br /&gt;
 &lt;br /&gt;
       for (h=0; h&amp;lt;SquareSize; h++) {&lt;br /&gt;
          for (w=0; w&amp;lt;SquareSize; w++) {&lt;br /&gt;
             srcp[woffset + w] = 0x00FFFFFF;&lt;br /&gt;
          }	&lt;br /&gt;
          srcp += src_pitch/4;&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
Remember that src_pitch is given in bytes and it is equal to src_pitch/4 pixels.&lt;br /&gt;
&lt;br /&gt;
For YUY2, each 4 byte sequence represents 2 pixels, (Y1, U, Y2 and then V). So we can write two pixels at once by recasting again.&lt;br /&gt;
&lt;br /&gt;
    if (vi.IsYUY2()) {&lt;br /&gt;
       srcp = srcp + (src_height/2 - SquareSize/2) * src_pitch;&lt;br /&gt;
 &lt;br /&gt;
       woffset = src_width/8 - SquareSize/4;&lt;br /&gt;
 &lt;br /&gt;
       for (h=0; h&amp;lt;SquareSize; h++) {&lt;br /&gt;
          for (w=0; w&amp;lt;SquareSize/2; w++) {   // we are writing two pixels at once&lt;br /&gt;
             *((unsigned int *)srcp + woffset + w) = 0x80EB80EB;   // VY2UY1; Y1=Y2=0xEB=235, U=V=0x80=128&lt;br /&gt;
          }&lt;br /&gt;
          srcp += src_pitch; &lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
At last we move on to the YUV planar formats. Since we are processing the color components independently we can loop over the planes.&lt;br /&gt;
&lt;br /&gt;
    if (vi.IsPlanar() &amp;amp;&amp;amp; vi.IsYUV()) {&lt;br /&gt;
&lt;br /&gt;
All planar YUV formats in the 2.6 api are: YV24, YV16, YV12, YV411 and Y8.&lt;br /&gt;
&lt;br /&gt;
       int planes[] = {PLANAR_Y, PLANAR_U, PLANAR_V};&lt;br /&gt;
       int square_value[] = {235, 128, 128};&lt;br /&gt;
       int p;&lt;br /&gt;
       int width_sub, height_sub;&lt;br /&gt;
 &lt;br /&gt;
       for (p=0; p&amp;lt;3; p++) {&lt;br /&gt;
          srcp = src-&amp;gt;GetWritePtr(planes[p]);		&lt;br /&gt;
          src_pitch = src-&amp;gt;GetPitch(planes[p]);&lt;br /&gt;
          src_width = src-&amp;gt;GetRowSize(planes[p]);&lt;br /&gt;
          src_height = src-&amp;gt;GetHeight(planes[p]);&lt;br /&gt;
          width_sub = vi.GetPlaneWidthSubsampling(planes[p]);&lt;br /&gt;
          height_sub = vi.GetPlaneHeightSubsampling(planes[p]);&lt;br /&gt;
&lt;br /&gt;
Since the planes have unequal width (measured in bytes; same for height) we will need their subsampling. The functions [[Filter_SDK/Cplusplus_API/VideoInfo|GetPlaneWidthSubsampling]] and [[Filter_SDK/Cplusplus_API/VideoInfo|GetPlaneHeightSubsampling]] are new in the 2.6 api. They return the horizontal and vertical subsampling of the plane compared to the luma plane. The subsampling of the formats is:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| color format&lt;br /&gt;
| GetPlaneWidthSubsampling(PLANAR_U)&lt;br /&gt;
| GetPlaneHeightSubsampling(PLANAR_U)&lt;br /&gt;
|- &lt;br /&gt;
| YV24&lt;br /&gt;
| 0&lt;br /&gt;
| 0&lt;br /&gt;
|- &lt;br /&gt;
| YV16&lt;br /&gt;
| 1&lt;br /&gt;
| 0&lt;br /&gt;
|- &lt;br /&gt;
| YV12&lt;br /&gt;
| 1&lt;br /&gt;
| 1&lt;br /&gt;
|- &lt;br /&gt;
| YV411&lt;br /&gt;
| 2&lt;br /&gt;
| 1&lt;br /&gt;
|- &lt;br /&gt;
| Y8&lt;br /&gt;
| 0 ?&lt;br /&gt;
| 0 ?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The chroma planes PLANAR_U and PLANAR_V have the same subsampling. Also GetPlaneWidthSubsampling(PLANAR_Y) = GetPlaneHeightSubsampling(PLANAR_Y) = 0 since PLANAR_Y is not subsampled.&lt;br /&gt;
&lt;br /&gt;
          srcp = srcp + (src_height/2 - (SquareSize&amp;gt;&amp;gt;height_sub)/2) * src_pitch;&lt;br /&gt;
&lt;br /&gt;
Note SquareSize is specified in pixels and src_height the height of the samples of plane p. Let's look at YV12 for example. For the luma plane we have SquareSize&amp;gt;&amp;gt;0 = SquareSize since there is no subsampling and for the chroma planes we have SquareSize&amp;gt;&amp;gt;1 = SquareSize/2 since there are twice as many luma samples as chroma samples horizontally.&lt;br /&gt;
&lt;br /&gt;
          woffset = src_width/2 - (SquareSize&amp;gt;&amp;gt;width_sub)/2;&lt;br /&gt;
&lt;br /&gt;
The vertical subsampling is taken into account again.&lt;br /&gt;
&lt;br /&gt;
          for (h=0; h&amp;lt;(SquareSize&amp;gt;&amp;gt;height_sub); h++) {&lt;br /&gt;
             for (w=0; w&amp;lt;(SquareSize&amp;gt;&amp;gt;width_sub); w++) {&lt;br /&gt;
                srcp[woffset + w] = square_value[p];&lt;br /&gt;
             }&lt;br /&gt;
             srcp += src_pitch;&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
Here the white square is drawn. The luma pixels will get the value square_value[PLANAR_Y] = 235, and the chroma pixels will get the value square_value[PLANAR_U] = 128 (idem for PLANAR_V).&lt;br /&gt;
&lt;br /&gt;
 AVSValue __cdecl Create_SimpleSample(AVSValue args, void* user_data, IScriptEnvironment* env) {&lt;br /&gt;
    return new SimpleSample(args[0].AsClip(),&lt;br /&gt;
                            args[1].AsInt(100),&lt;br /&gt;
                            env);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
args[0], args[1], ... are the arguments of the filter. Here there are two arguments. The first one is of type clip and the second one of type int (with default value 100). You can pre-process or post-process your variables (and clips) here too. See DirectShowSource for some examples.&lt;br /&gt;
&lt;br /&gt;
 extern &amp;quot;C&amp;quot; __declspec(dllexport) const char* __stdcall AvisynthPluginInit3(IScriptEnvironment* env, const AVS_Linkage* const vectors) {&lt;br /&gt;
    AVS_linkage = vectors;&lt;br /&gt;
    env-&amp;gt;AddFunction(&amp;quot;SimpleSample&amp;quot;, &amp;quot;c[size]i&amp;quot;, Create_SimpleSample, 0);&lt;br /&gt;
    return &amp;quot;SimpleSample plugin&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The [[Filter_SDK/Cplusplus_API#AddFunction|AddFunction]] has the following parameters:&lt;br /&gt;
&lt;br /&gt;
 AddFunction(Filtername, Arguments, Function to call, 0);&lt;br /&gt;
   &lt;br /&gt;
''Arguments'' is a string that defines the types and optional names of the arguments for your filter. The possible types are:&lt;br /&gt;
&lt;br /&gt;
 # Argument type specifier strings&lt;br /&gt;
  c - clip&lt;br /&gt;
  i - integer&lt;br /&gt;
  f - float&lt;br /&gt;
  s - string&lt;br /&gt;
  b - boolean&lt;br /&gt;
  . - Any type (dot)&lt;br /&gt;
 # Array Specifiers (have a look at StackVertical and SelectEvery for example as to how access such arrays)&lt;br /&gt;
  i* - Integer Array, zero or more&lt;br /&gt;
  i+ - Integer Array, one or more&lt;br /&gt;
  .* - Any type Array, zero or more&lt;br /&gt;
  .+ - Any type Array, one or more&lt;br /&gt;
&lt;br /&gt;
The text inside the [ ] lets you used named parameters in your script. Thus&lt;br /&gt;
&lt;br /&gt;
 clip = ...&lt;br /&gt;
 SimpleSample(clip, size=100)&lt;br /&gt;
&lt;br /&gt;
but&lt;br /&gt;
&lt;br /&gt;
 clip = ...&lt;br /&gt;
 SimpleSample(clip, 100)&lt;br /&gt;
&lt;br /&gt;
works as well. See [[Filter_SDK/InvertNeg|InvertNeg]] for more information.&lt;br /&gt;
&lt;br /&gt;
=== Old versions ===&lt;br /&gt;
&lt;br /&gt;
[[Filter_SDK/Simple_sample|Simple sample]] &amp;lt;need to move the old examples&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:FilterSDK]]&lt;/div&gt;</summary>
		<author><name>Jmac698</name></author>	</entry>

	<entry>
		<id>http://avisynth.nl/index.php/Avisynth_Plugin_Development_in_C</id>
		<title>Avisynth Plugin Development in C</title>
		<link rel="alternate" type="text/html" href="http://avisynth.nl/index.php/Avisynth_Plugin_Development_in_C"/>
				<updated>2016-06-11T11:57:47Z</updated>
		
		<summary type="html">&lt;p&gt;Jmac698: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Note: This guide is in development. Currently, only the section [[Avisynth_Plugin_Development_in_C#Compiling_Your_First_Plugin|Compiling Your First Plugin]] has been tested. The rest contains some errors, so use at your own risk!&lt;br /&gt;
&lt;br /&gt;
Note: for new development, it is recommended to develop in C++ using the Avisynth 2.6 API.  Please refer to the guide, [[Avisynth Plugin Development in CPP]]&lt;br /&gt;
&lt;br /&gt;
Original written by jmac698 with corrections by the Avisynth community.&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
This tutorial takes you step-by-step through the process of creating a new C plugin for AviSynth by modifying an existing example. By the end of this tutorial, you should be able a plugin which returns a normal value or which works on a single frame. The target audience is the beginning level C programmer. &lt;br /&gt;
&lt;br /&gt;
==Why Develop a Plugin in C?==&lt;br /&gt;
Some reasons to use C based plugin development are that,&lt;br /&gt;
&lt;br /&gt;
*Free compilers can be used, such as MingW and online code editors such as https://codeanywhere.com/features/editor; only Microsoft Visual C++ or the free Community Edition may be used to create AviSynth C++ plugins&lt;br /&gt;
*You are only familiar with C&lt;br /&gt;
*It may be simpler to learn for a beginner&lt;br /&gt;
*There is no download (with online code editor) or small download (with mingw)&lt;br /&gt;
*You want to use any .NET language, PureBasic, or Delphi&lt;br /&gt;
&lt;br /&gt;
==Choosing a License==&lt;br /&gt;
Before starting development, be aware of these license requirements:&lt;br /&gt;
&lt;br /&gt;
*The 2.6 C API requires that your plugin uses the GPL license. The GPL license requires that you release the source code.&lt;br /&gt;
*The 2.5 C API can use your own license, but the complete source of AviSynth 2.5 and the C API header must be made available along with your plugin binary&lt;br /&gt;
&lt;br /&gt;
==Plugin Compatibility==&lt;br /&gt;
Plugins programmed in the 2.5 C API can also be used with higher versions of AviSynth, however they can't access any newer features. &lt;br /&gt;
&lt;br /&gt;
==Setting up your Development Environment==&lt;br /&gt;
This tutorial was developed with Code::Blocks, a free development environment. Please follow these steps:&lt;br /&gt;
&lt;br /&gt;
*Download &amp;lt;tt&amp;gt;codeblocks-13.12mingw-setup.exe&amp;lt;/tt&amp;gt; from the [http://www.codeblocks.org/downloads/binaries CodeBlocks homepage] and run it&lt;br /&gt;
*The first screen reads &amp;quot;Welcome to the CodeBlocks Setup Wizard&amp;quot;. Click Next.&lt;br /&gt;
*The GPL license is displayed. Click I Agree.&lt;br /&gt;
*Choose any extra components to install if desired, but the default is sufficient. Click Next.&lt;br /&gt;
*Choose a destination folder. Click Install. Complete the wizard. &lt;br /&gt;
&lt;br /&gt;
==Compiling Your First Plugin==&lt;br /&gt;
Before making our own plugin, first we will learn how to compile an existing plugin. Please follow these steps:&lt;br /&gt;
&lt;br /&gt;
*Ensure that you included the option &amp;quot;Install FilterSDK&amp;quot; when installing AviSynth; otherwise reinstall AviSynth with that option.&lt;br /&gt;
*Create a C Projects folder under My Documents.&lt;br /&gt;
*Obtain the sample plugin Demosaic from [http://www.avisynth.nl/users/warpenterprises/files/demosaic_20071206.zip demosaic_20071206.zip]. Unzip the files to C Projects. There should now be demosaic, avisynth_c and avisynth_c_2_5 folders.&lt;br /&gt;
*Delete the avisynth_c and avisynth_c_2_5 folders.&lt;br /&gt;
*Delete this file from demosaic: makefile&lt;br /&gt;
*Make a new folder, lib under Demosaic.&lt;br /&gt;
*Copy (C:\Program Files\ or other installation directory then:) AviSynth 2.5\Extras\avisynth.lib to demosaic\lib.&lt;br /&gt;
*Copy (C:\Program Files\ or other installation directory then:) AviSynth 2.5\FilterSDK\include\avisynth_c.h to demosaic.&lt;br /&gt;
*Start Code::Blocks. Click Create a new project.&lt;br /&gt;
*Click Projects, then click Dynamic Link Library, then click Go.&lt;br /&gt;
*The wizard page &amp;quot;Dynamic Link Library&amp;quot; appears. Click Next.&lt;br /&gt;
*For Project title, use Demosaic. Choose the My Documents\C Projects folder you created in a previous step. Click Next.&lt;br /&gt;
*Under compiler, choose GNU GCC Compiler. Accept the defaults and click Finish.&lt;br /&gt;
*Right click &amp;quot;Demosaic&amp;quot;, and choose Remove files. A list showing main.cpp and main.h appear. Click OK. Click Yes.&lt;br /&gt;
*Delete these files from demosaic: main.cpp, main.h&lt;br /&gt;
*Right click &amp;quot;Demosaic&amp;quot; and choose Add Files. Add the demosaic.cpp file found in demosaic.&lt;br /&gt;
*A window asks you to choose which targets the file belongs to. Click OK.&lt;br /&gt;
*Right click Demosaic and choose Add Files. Add the avisynth_c.h file found in 'demosaic. Click OK.&lt;br /&gt;
*Select the menu Project-&amp;gt;Build Options.... Select Demosaic in the tree.&lt;br /&gt;
*Select the tab Linker settings. Click Add. Browse for the file Demosaic\lib\avisynth.lib.&lt;br /&gt;
*You are asked &amp;quot;Keep this as a relative path?&amp;quot;. Click Yes. Click OK. Click OK.&lt;br /&gt;
*Select the menu Build-&amp;gt;Select target-&amp;gt;Release.&lt;br /&gt;
*Select the menu Build-&amp;gt;Build.&lt;br /&gt;
*Verify that the file demosaic\bin\Release\Demosaic.dll was made. Copy this file to your (C:\Program Files\ or other installation directory then:) AviSynth 2.5 folder.&lt;br /&gt;
*Test the plugin by writing an AviSynth script: &lt;br /&gt;
&lt;br /&gt;
 Load_Stdcall_Plugin(&amp;quot;Demosaic.dll&amp;quot;)&lt;br /&gt;
 colorbars(pixel_type=&amp;quot;YV12&amp;quot;)&lt;br /&gt;
 Demosaic()&lt;br /&gt;
&lt;br /&gt;
This should display a grey test pattern with some colour fringes.&lt;br /&gt;
&lt;br /&gt;
*Save the project with File-&amp;gt;Save project. &lt;br /&gt;
&lt;br /&gt;
Troubleshooting:&lt;br /&gt;
&lt;br /&gt;
*Note that I found problems using full paths with spaces. The .lib file can only be found when placed in a folder lib and using relative paths.&lt;br /&gt;
*If you have a script error, try using the original demosaic.dll in the Demosaic folder. Note that this file starts with a lower case d, so adjust your script accordingly.&lt;br /&gt;
*The test.avs which comes with the plugin uses &amp;lt;code&amp;gt;LoadCPlugin&amp;lt;/code&amp;gt;. It is better to use &amp;lt;code&amp;gt;Load_Stdcall_Plugin&amp;lt;/code&amp;gt; because the &amp;lt;code&amp;gt;avisynth_c.dll&amp;lt;/code&amp;gt; plugin may be auto-loaded. This is a plugin which overrides the functionality of &amp;lt;code&amp;gt;LoadCPlugin&amp;lt;/code&amp;gt;, such that it won't load &amp;lt;tt&amp;gt;demosaic.dll&amp;lt;/tt&amp;gt; anymore. &lt;br /&gt;
&lt;br /&gt;
==Passing Parameters to your Plugin==&lt;br /&gt;
For this example, again we will start with the C source of Demosaic ([http://www.avisynth.nl/users/warpenterprises/files/demosaic_20071206.zip demosaic_20071206.zip])&lt;br /&gt;
&lt;br /&gt;
The example source defines a function, in AviSynth script terms, as: &lt;br /&gt;
&lt;br /&gt;
 Demosaic(clip clip1, string &amp;quot;mosaic&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
However, for our purposes we want to define a plugin like this:&lt;br /&gt;
&lt;br /&gt;
 Merge(clip clip1, clip clip2, int weight)&lt;br /&gt;
&lt;br /&gt;
Step 1: Define a place to store the parameters&lt;br /&gt;
&lt;br /&gt;
In this step, we will change the existing code:&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;pre&amp;gt;enum Mosaic {&lt;br /&gt;
        BAYER&lt;br /&gt;
 };&lt;br /&gt;
 struct Demosaic {&lt;br /&gt;
        Mosaic  mosaic;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
Into a new version:&lt;br /&gt;
 struct Params&lt;br /&gt;
 {&lt;br /&gt;
        AVS_Clip* clip2;&lt;br /&gt;
         int Weight;&lt;br /&gt;
 };&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Step 2: Tell Avisynth to parse the new parameters&amp;lt;br&amp;gt;&lt;br /&gt;
In this step, we will use a special code to inform the Avisynth parser to look for, and save our parameters. We will change the existing code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;const char* AVSC_CC avisynth_c_plugin_init(AVS_ScriptEnvironment* env)&lt;br /&gt;
 {&lt;br /&gt;
        avs_add_function(env, &amp;quot;Demosaic&amp;quot;, &amp;quot;c[mosaic]s&amp;quot;, create_filter, 0);&lt;br /&gt;
        return &amp;quot;Demosaic plugin&amp;quot;;&lt;br /&gt;
 }&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To the new version:&lt;br /&gt;
 const char* AVSC_CC avisynth_c_plugin_init(AVS_ScriptEnvironment* env)&lt;br /&gt;
 {&lt;br /&gt;
        avs_add_function(env, &amp;quot;Merge&amp;quot;, &amp;quot;cc[weight]i&amp;quot;, create_filter, 0);&lt;br /&gt;
        return &amp;quot;Merge plugin&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The:&lt;br /&gt;
 return &amp;quot;Merge plugin&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
statement returns a value to the LoadCPlugin() command (in AviSynth script) upon loading our plugin. In practice, almost no one checks this return value. The code&lt;br /&gt;
 avs_add_function(env, &amp;quot;Merge&amp;quot;, &amp;quot;c[weight]i&amp;quot;, create_filter, 0);&lt;br /&gt;
&lt;br /&gt;
does a few things; first &amp;quot;Merge&amp;quot; will be the name of our AviSynth script function (i.e., in the same sense that &amp;quot;[[Tweak]]&amp;quot; is a built-in function). Next, we use a special code to define the expected parameters. In this case, &amp;quot;c&amp;quot; refers to a clip while &amp;quot;i&amp;quot; refers to an int. If we had used &amp;quot;ci&amp;quot;, the function would simply expect a clip and an int, like this: &amp;lt;code&amp;gt;Merge(clip1,2)&amp;lt;/code&amp;gt; However, we wanted to use a named parameter, which is an optional parameter in functions which can also be named and placed in any order. For example, we could use this script: &lt;br /&gt;
&lt;br /&gt;
 Merge(clip1,weight=2)&lt;br /&gt;
&lt;br /&gt;
or simply leave it out:&lt;br /&gt;
&lt;br /&gt;
 Merge(clip1)&lt;br /&gt;
To specify the name, we include it in square brackets before the parameter type, which in this example, is &amp;quot;[weight]i&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Reference&lt;br /&gt;
&lt;br /&gt;
The special codes for defining your parameters: 'c' for clip, 'i' for integer, 's' for string, 'b' for boolean, and 'f' for float There are a few more features which are explained at: [http://www.kevina.org/avisynth_c/example.html AviSynth C Interface Illustrated Example] by Kevin Atkinson.&lt;br /&gt;
&lt;br /&gt;
Step 3: Fetching and checking your parameters In this final step, we will actually read the parameters which the AviSynth parser has saved for us. We will change the original code: &lt;br /&gt;
&lt;br /&gt;
        int pnum = 0;&lt;br /&gt;
        ++pnum; mosaic_str = avs_defined(avs_array_elt(args, pnum)) ? avs_as_string(avs_array_elt(args, pnum)) : &amp;quot;Bayer&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
To the following:&lt;br /&gt;
        int pnum = 0;&lt;br /&gt;
        ++pnum; params-&amp;gt;clip2 = avs_defined(avs_array_elt(args, pnum)) ? avs_take_clip(avs_array_elt(args, pnum), env) : 0;&lt;br /&gt;
        ++pnum; params-&amp;gt;weight = avs_defined(avs_array_elt(args, pnum)) ?&lt;br /&gt;
        avs_as_int(avs_array_elt(args, pnum)) : 1; // Default value for weight here&lt;br /&gt;
&lt;br /&gt;
It turns out that avs_array_elt contains our list of arguments in the order they were supplied in the script. We are going to expect the first parameter to be a clip, and the second to be an int. The first element, numbered 0, in the array is the value of last, which is also our first clip. pnum will be a counter to fetch each parameter, starting with number 1 (int pnum=0; ++pnum leaves pnum=1). avs_defined() is a function which checks to see if the parameter exists. So we are seeing if parameter #1 exists, and if so, assign it to params-&amp;gt;clip2 which is the structure we've defined to hold our parameters. If it doesn't exists, we'll just put a 0 there. The function avs_take_clip actually takes our clip.&lt;br /&gt;
&lt;br /&gt;
In the second parameter fetch, we use avs_as_int to fetch our weight. This function doesn't need an &amp;quot;env&amp;quot; argument. Instead of return 0 if the parameter isn't there, we will take the opportunity to also set a default value for weight here.&lt;br /&gt;
&lt;br /&gt;
Next comes checking the parameters. Even though it seems like we've saved the values, we actually don't know what they really are - they're just data at this point, that we've assumed were a clip and an int. Next we have to actually double-check this. Original code:&lt;br /&gt;
 // Check params&lt;br /&gt;
        retval = avs_void;&lt;br /&gt;
        if (stricmp(mosaic_str, &amp;quot;bayer&amp;quot;) == 0)&lt;br /&gt;
                params-&amp;gt;mosaic = BAYER;&lt;br /&gt;
        else&lt;br /&gt;
                retval = avs_new_value_error(&amp;quot;Mosaic mode can be: \&amp;quot;Bayer\&amp;quot;&amp;quot;);&lt;br /&gt;
        if (!avs_defined(retval) &amp;amp;&amp;amp; !avs_is_yuy2(&amp;amp;fi-&amp;gt;vi) &amp;amp;&amp;amp; !avs_is_yv12(&amp;amp;fi-&amp;gt;vi) &amp;amp;&amp;amp; !avs_is_y8(&amp;amp;fi-&amp;gt;vi)) {&lt;br /&gt;
                retval = avs_new_value_error(&amp;quot;Input video format can be: YUY2, YV12, Y8&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
New code:&lt;br /&gt;
  // Check params&lt;br /&gt;
        retval = avs_void;&lt;br /&gt;
  if (!avs_defined(retval) &amp;amp;&amp;amp; !avs_is_yuy2(&amp;amp;fi-&amp;gt;vi)) {&lt;br /&gt;
                retval = avs_new_value_error(&amp;quot;Input video format can be: YUY2&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
  if (!avs_defined(retval) &amp;amp;&amp;amp; !avs_is_int(params-&amp;gt;weight) {&lt;br /&gt;
                retval = avs_new_value_error(&amp;quot;weight must be an int&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
There's a few things to go over here. First of all, in the larger context we are defining what our plugin returns here, and that is what retval is. If you return void, it's the same as returning nothing - you'd see &amp;quot;Not a clip&amp;quot; if you tried to play it. We will cover returning a new clip shortly. !avs_defined(retval) is basically saying, &amp;quot;if retval hasn't been defined yet...&amp;quot;, and this is logic to continue checking parameters. In other words, if one of these checks fails, we will set an error message clip as a retval, then the next check will be skipped because a retval has been set. It's just a way to check each parameter just once and skip all other checks as soon as a problem is found. Now for the actual checking: !avs_is_yuy2(&amp;amp;fi-&amp;gt;vi) checks the colour format of our first clip; there are predefined functions for checking every format. Likewise, !avs_is_int(params-&amp;gt;weight) checks if our weight is really an int. avs_new_value_error() is a function that creates a new video clip with a message in it, similar to messageclip() in script. We use this to inform the user of the error. If all parameters are found to be correct, we finally return the output clip. Original code (unchanged):&lt;br /&gt;
        // If no errors, all is fine, return clip value&lt;br /&gt;
        if (!avs_defined(retval)) {&lt;br /&gt;
                retval = avs_new_value_clip(new_clip);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
Reference There are numerous checks for video type:&lt;br /&gt;
 int avs_is_rgb(const AVS_VideoInfo * p)&lt;br /&gt;
 int avs_is_rgb24(const AVS_VideoInfo * p)&lt;br /&gt;
 int avs_is_rgb32(const AVS_VideoInfo * p)&lt;br /&gt;
 int avs_is_yuy(const AVS_VideoInfo * p)&lt;br /&gt;
 int avs_is_yuy2(const AVS_VideoInfo * p)&lt;br /&gt;
 int avs_is_yv12(const AVS_VideoInfo * p)&lt;br /&gt;
&lt;br /&gt;
There are various checks for other parameters:&lt;br /&gt;
 int avs_defined(AVS_Value v)&lt;br /&gt;
 int avs_is_clip(AVS_Value v)&lt;br /&gt;
 int avs_is_bool(AVS_Value v)&lt;br /&gt;
 int avs_is_int(AVS_Value v)&lt;br /&gt;
 int avs_is_float(AVS_Value v)&lt;br /&gt;
 int avs_is_string(AVS_Value v)&lt;br /&gt;
 int avs_is_array(AVS_Value v)&lt;br /&gt;
 int avs_is_error(AVS_Value v)&lt;br /&gt;
&lt;br /&gt;
And as mentioned, we can return an error clip or a new clip; we can also return int, float, and string values which can be read by the runtime environment:&lt;br /&gt;
 AVS_Value avs_new_value_bool(int v0)&lt;br /&gt;
 AVS_Value avs_new_value_int(int v0)&lt;br /&gt;
 AVS_Value avs_new_value_string(const char * v0)&lt;br /&gt;
 AVS_Value avs_new_value_float(float v0)&lt;br /&gt;
 AVS_Value avs_new_value_error(const char * v0)&lt;br /&gt;
 AVS_Value avs_new_value_clip(AVS_Clip * v0)&lt;br /&gt;
 AVS_Value avs_new_value_array(AVS_Value * v0, int size)&lt;br /&gt;
&lt;br /&gt;
For more information, please review [http://www.kevina.org/avisynth_c/api.html AviSynth C Interface API Reference].&lt;br /&gt;
&lt;br /&gt;
==Writing the actual function==&lt;br /&gt;
After all that work, finally we can write a few simple lines of code to actually merge our videos! However, there's *still* a few more things you need to know. The various video formats are stored in memory in different ways; although we've got a pointer to an area of memory which holds our video, it can be *interpreted* in different ways, even though it's the same size! This is where handling of YUY2 vs YV12 and RGB comes in. We'll start with YUY2 in our example. YUY2 is where every two luma pixels share a color. A color is stored as two values, U and V. We won't go into what U and V means, except to say that if you average two pixels together, everything works out. YUY2 is stored in this format in memory, from the initial pointer to increasing values in memory, a byte at a time: Y1 U Y2 V. If you access the memory 4 bytes at a time (that is, as a 32 bit unsigned int), due to the Intel assembly stored values as Least Significant Byte order, the int would look like this: 0xVVYYUUYY, where each doubled letter represents one HEX value. For example, if our pixels were Y1=35, Y2=40, U=V=128 (which I'll tell you represents no color or grey), we'd have a hex value of 0x80288023. I mention that only as a reminder for the optimizing section. For now we'll simply deal with them as bytes for clarity. New code:&lt;br /&gt;
                 aY1=src_data[x];&lt;br /&gt;
                 bY1=clip2_data[x];&lt;br /&gt;
                 aU=src_data[x+1];&lt;br /&gt;
                 bU=clip2_data[x+1];&lt;br /&gt;
                 aY2=src_data[x+2];&lt;br /&gt;
                 bY2=clip2_data[x+2];&lt;br /&gt;
                 aV=src_data[x+3];&lt;br /&gt;
                 bV=clip2_data[x+3];&lt;br /&gt;
&lt;br /&gt;
Will give us a pair of pixels each from the two input clips in easy to use byte values. Finally, *finally*, we can simply write these 4 lines of code to finish our function:&lt;br /&gt;
           dest_data[x+1] = (aU/weight+bU*weight);&lt;br /&gt;
           dest_data[x+3] = (aV/weight+bV*weight);&lt;br /&gt;
           dest_data[x+0] = (aY1/weight+bY1*weight);&lt;br /&gt;
           dest_data[x+2] = (aY2/weight+bY2*weight);&lt;br /&gt;
&lt;br /&gt;
Just remember, again, that [x] is Y1, [x+1] is U, [x+2] is Y2, and [x+3] is V.&lt;br /&gt;
&lt;br /&gt;
==Putting it all together==&lt;br /&gt;
Download and compile the final sample code from .... Install, then open the Merge.cbp file, the project for Code::Blocks. Simply Build-&amp;gt;Build. You now have a fresh merge.dll in your project directory. In order to test it, I've include some simple windows batch files. Double click the install.bat icon. This will copy the merge.dll to your AviSynth directory. Note: ensure that you have no scripts open using the plugin, or the file will fail to overwrite any existing plugin version in your AviSynth directory. Next, open merge.avs in for example AvsP, then press F5. You should see a semitransparent message overlaid on the background. The weight value will change the degree of transparency, where a higher value makes the message stronger. &lt;br /&gt;
&lt;br /&gt;
==Conclusion==&lt;br /&gt;
In this manual, we've covered the basic steps necessary to convert an existing example to a new filter, with pointers on how to extend the concepts to include any set of parameters, to return a clip or runtime variable, and to access pixels pairs as stored in YUY2 colour format. In the next set of tutorials, it is planned to cover other colour formats, and some notes on optimizing your code for better execution speed. I hope you have found this tutorial useful. If you have any comments or corrections, please see the ongoing discussion at: http://forum.doom9.org/forumdisplay.php?f=69&lt;br /&gt;
&lt;br /&gt;
==External Links==&lt;br /&gt;
*[http://forum.doom9.org/showthread.php?p=1465008#post1465008 Doom9 Forum] - Includes corrections and additional information.&lt;br /&gt;
*[http://forum.doom9.org/showthread.php?p=1688939#post1688939 Doom9 Forum] - Continued discussion.&lt;br /&gt;
&lt;br /&gt;
[[Category:AviSynth_Development]]&lt;br /&gt;
[[Category:FilterSDK]]&lt;/div&gt;</summary>
		<author><name>Jmac698</name></author>	</entry>

	<entry>
		<id>http://avisynth.nl/index.php/Avisynth_Plugin_Development_in_C</id>
		<title>Avisynth Plugin Development in C</title>
		<link rel="alternate" type="text/html" href="http://avisynth.nl/index.php/Avisynth_Plugin_Development_in_C"/>
				<updated>2016-06-11T11:48:12Z</updated>
		
		<summary type="html">&lt;p&gt;Jmac698: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Note: This guide is in development. Currently, only the section [[Avisynth_Plugin_Development_in_C#Compiling_Your_First_Plugin|Compiling Your First Plugin]] has been tested. The rest contains some errors, so use at your own risk!&lt;br /&gt;
&lt;br /&gt;
Original written by jmac698 with corrections by the Avisynth community.&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
This tutorial takes you step-by-step through the process of creating a new C plugin for AviSynth by modifying an existing example. By the end of this tutorial, you should be able a plugin which returns a normal value or which works on a single frame. The target audience is the beginning level C programmer. &lt;br /&gt;
&lt;br /&gt;
==Why Develop a Plugin in C?==&lt;br /&gt;
Some reasons to use C based plugin development are that,&lt;br /&gt;
&lt;br /&gt;
*Free compilers can be used, such as MingW and online code editors such as https://codeanywhere.com/features/editor; only Microsoft Visual C++ or the free Community Edition may be used to create AviSynth C++ plugins&lt;br /&gt;
*You are only familiar with C&lt;br /&gt;
*It may be simpler to learn for a beginner&lt;br /&gt;
*There is no download (with online code editor) or small download (with mingw)&lt;br /&gt;
&lt;br /&gt;
==Choosing a License==&lt;br /&gt;
Before starting development, be aware of these license requirements:&lt;br /&gt;
&lt;br /&gt;
*The 2.6 C API requires that your plugin uses the GPL license. The GPL license requires that you release the source code.&lt;br /&gt;
*The 2.5 C API can use your own license, but the complete source of AviSynth 2.5 and the C API header must be made available along with your plugin binary&lt;br /&gt;
&lt;br /&gt;
==Plugin Compatibility==&lt;br /&gt;
Plugins programmed in the 2.5 C API can also be used with higher versions of AviSynth, however they can't access any newer features. &lt;br /&gt;
&lt;br /&gt;
==Setting up your Development Environment==&lt;br /&gt;
This tutorial was developed with Code::Blocks, a free development environment. Please follow these steps:&lt;br /&gt;
&lt;br /&gt;
*Download &amp;lt;tt&amp;gt;codeblocks-13.12mingw-setup.exe&amp;lt;/tt&amp;gt; from the [http://www.codeblocks.org/downloads/binaries CodeBlocks homepage] and run it&lt;br /&gt;
*The first screen reads &amp;quot;Welcome to the CodeBlocks Setup Wizard&amp;quot;. Click Next.&lt;br /&gt;
*The GPL license is displayed. Click I Agree.&lt;br /&gt;
*Choose any extra components to install if desired, but the default is sufficient. Click Next.&lt;br /&gt;
*Choose a destination folder. Click Install. Complete the wizard. &lt;br /&gt;
&lt;br /&gt;
==Compiling Your First Plugin==&lt;br /&gt;
Before making our own plugin, first we will learn how to compile an existing plugin. Please follow these steps:&lt;br /&gt;
&lt;br /&gt;
*Ensure that you included the option &amp;quot;Install FilterSDK&amp;quot; when installing AviSynth; otherwise reinstall AviSynth with that option.&lt;br /&gt;
*Create a C Projects folder under My Documents.&lt;br /&gt;
*Obtain the sample plugin Demosaic from [http://www.avisynth.nl/users/warpenterprises/files/demosaic_20071206.zip demosaic_20071206.zip]. Unzip the files to C Projects. There should now be demosaic, avisynth_c and avisynth_c_2_5 folders.&lt;br /&gt;
*Delete the avisynth_c and avisynth_c_2_5 folders.&lt;br /&gt;
*Delete this file from demosaic: makefile&lt;br /&gt;
*Make a new folder, lib under Demosaic.&lt;br /&gt;
*Copy (C:\Program Files\ or other installation directory then:) AviSynth 2.5\Extras\avisynth.lib to demosaic\lib.&lt;br /&gt;
*Copy (C:\Program Files\ or other installation directory then:) AviSynth 2.5\FilterSDK\include\avisynth_c.h to demosaic.&lt;br /&gt;
*Start Code::Blocks. Click Create a new project.&lt;br /&gt;
*Click Projects, then click Dynamic Link Library, then click Go.&lt;br /&gt;
*The wizard page &amp;quot;Dynamic Link Library&amp;quot; appears. Click Next.&lt;br /&gt;
*For Project title, use Demosaic. Choose the My Documents\C Projects folder you created in a previous step. Click Next.&lt;br /&gt;
*Under compiler, choose GNU GCC Compiler. Accept the defaults and click Finish.&lt;br /&gt;
*Right click &amp;quot;Demosaic&amp;quot;, and choose Remove files. A list showing main.cpp and main.h appear. Click OK. Click Yes.&lt;br /&gt;
*Delete these files from demosaic: main.cpp, main.h&lt;br /&gt;
*Right click &amp;quot;Demosaic&amp;quot; and choose Add Files. Add the demosaic.cpp file found in demosaic.&lt;br /&gt;
*A window asks you to choose which targets the file belongs to. Click OK.&lt;br /&gt;
*Right click Demosaic and choose Add Files. Add the avisynth_c.h file found in 'demosaic. Click OK.&lt;br /&gt;
*Select the menu Project-&amp;gt;Build Options.... Select Demosaic in the tree.&lt;br /&gt;
*Select the tab Linker settings. Click Add. Browse for the file Demosaic\lib\avisynth.lib.&lt;br /&gt;
*You are asked &amp;quot;Keep this as a relative path?&amp;quot;. Click Yes. Click OK. Click OK.&lt;br /&gt;
*Select the menu Build-&amp;gt;Select target-&amp;gt;Release.&lt;br /&gt;
*Select the menu Build-&amp;gt;Build.&lt;br /&gt;
*Verify that the file demosaic\bin\Release\Demosaic.dll was made. Copy this file to your (C:\Program Files\ or other installation directory then:) AviSynth 2.5 folder.&lt;br /&gt;
*Test the plugin by writing an AviSynth script: &lt;br /&gt;
&lt;br /&gt;
 Load_Stdcall_Plugin(&amp;quot;Demosaic.dll&amp;quot;)&lt;br /&gt;
 colorbars(pixel_type=&amp;quot;YV12&amp;quot;)&lt;br /&gt;
 Demosaic()&lt;br /&gt;
&lt;br /&gt;
This should display a grey test pattern with some colour fringes.&lt;br /&gt;
&lt;br /&gt;
*Save the project with File-&amp;gt;Save project. &lt;br /&gt;
&lt;br /&gt;
Troubleshooting:&lt;br /&gt;
&lt;br /&gt;
*Note that I found problems using full paths with spaces. The .lib file can only be found when placed in a folder lib and using relative paths.&lt;br /&gt;
*If you have a script error, try using the original demosaic.dll in the Demosaic folder. Note that this file starts with a lower case d, so adjust your script accordingly.&lt;br /&gt;
*The test.avs which comes with the plugin uses &amp;lt;code&amp;gt;LoadCPlugin&amp;lt;/code&amp;gt;. It is better to use &amp;lt;code&amp;gt;Load_Stdcall_Plugin&amp;lt;/code&amp;gt; because the &amp;lt;code&amp;gt;avisynth_c.dll&amp;lt;/code&amp;gt; plugin may be auto-loaded. This is a plugin which overrides the functionality of &amp;lt;code&amp;gt;LoadCPlugin&amp;lt;/code&amp;gt;, such that it won't load &amp;lt;tt&amp;gt;demosaic.dll&amp;lt;/tt&amp;gt; anymore. &lt;br /&gt;
&lt;br /&gt;
==Passing Parameters to your Plugin==&lt;br /&gt;
For this example, again we will start with the C source of Demosaic ([http://www.avisynth.nl/users/warpenterprises/files/demosaic_20071206.zip demosaic_20071206.zip])&lt;br /&gt;
&lt;br /&gt;
The example source defines a function, in AviSynth script terms, as: &lt;br /&gt;
&lt;br /&gt;
 Demosaic(clip clip1, string &amp;quot;mosaic&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
However, for our purposes we want to define a plugin like this:&lt;br /&gt;
&lt;br /&gt;
 Merge(clip clip1, clip clip2, int weight)&lt;br /&gt;
&lt;br /&gt;
Step 1: Define a place to store the parameters&lt;br /&gt;
&lt;br /&gt;
In this step, we will change the existing code:&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;pre&amp;gt;enum Mosaic {&lt;br /&gt;
        BAYER&lt;br /&gt;
 };&lt;br /&gt;
 struct Demosaic {&lt;br /&gt;
        Mosaic  mosaic;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
Into a new version:&lt;br /&gt;
 struct Params&lt;br /&gt;
 {&lt;br /&gt;
        AVS_Clip* clip2;&lt;br /&gt;
         int Weight;&lt;br /&gt;
 };&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Step 2: Tell Avisynth to parse the new parameters&amp;lt;br&amp;gt;&lt;br /&gt;
In this step, we will use a special code to inform the Avisynth parser to look for, and save our parameters. We will change the existing code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;const char* AVSC_CC avisynth_c_plugin_init(AVS_ScriptEnvironment* env)&lt;br /&gt;
 {&lt;br /&gt;
        avs_add_function(env, &amp;quot;Demosaic&amp;quot;, &amp;quot;c[mosaic]s&amp;quot;, create_filter, 0);&lt;br /&gt;
        return &amp;quot;Demosaic plugin&amp;quot;;&lt;br /&gt;
 }&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To the new version:&lt;br /&gt;
 const char* AVSC_CC avisynth_c_plugin_init(AVS_ScriptEnvironment* env)&lt;br /&gt;
 {&lt;br /&gt;
        avs_add_function(env, &amp;quot;Merge&amp;quot;, &amp;quot;cc[weight]i&amp;quot;, create_filter, 0);&lt;br /&gt;
        return &amp;quot;Merge plugin&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The:&lt;br /&gt;
 return &amp;quot;Merge plugin&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
statement returns a value to the LoadCPlugin() command (in AviSynth script) upon loading our plugin. In practice, almost no one checks this return value. The code&lt;br /&gt;
 avs_add_function(env, &amp;quot;Merge&amp;quot;, &amp;quot;c[weight]i&amp;quot;, create_filter, 0);&lt;br /&gt;
&lt;br /&gt;
does a few things; first &amp;quot;Merge&amp;quot; will be the name of our AviSynth script function (i.e., in the same sense that &amp;quot;[[Tweak]]&amp;quot; is a built-in function). Next, we use a special code to define the expected parameters. In this case, &amp;quot;c&amp;quot; refers to a clip while &amp;quot;i&amp;quot; refers to an int. If we had used &amp;quot;ci&amp;quot;, the function would simply expect a clip and an int, like this: &amp;lt;code&amp;gt;Merge(clip1,2)&amp;lt;/code&amp;gt; However, we wanted to use a named parameter, which is an optional parameter in functions which can also be named and placed in any order. For example, we could use this script: &lt;br /&gt;
&lt;br /&gt;
 Merge(clip1,weight=2)&lt;br /&gt;
&lt;br /&gt;
or simply leave it out:&lt;br /&gt;
&lt;br /&gt;
 Merge(clip1)&lt;br /&gt;
To specify the name, we include it in square brackets before the parameter type, which in this example, is &amp;quot;[weight]i&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Reference&lt;br /&gt;
&lt;br /&gt;
The special codes for defining your parameters: 'c' for clip, 'i' for integer, 's' for string, 'b' for boolean, and 'f' for float There are a few more features which are explained at: [http://www.kevina.org/avisynth_c/example.html AviSynth C Interface Illustrated Example] by Kevin Atkinson.&lt;br /&gt;
&lt;br /&gt;
Step 3: Fetching and checking your parameters In this final step, we will actually read the parameters which the AviSynth parser has saved for us. We will change the original code: &lt;br /&gt;
&lt;br /&gt;
        int pnum = 0;&lt;br /&gt;
        ++pnum; mosaic_str = avs_defined(avs_array_elt(args, pnum)) ? avs_as_string(avs_array_elt(args, pnum)) : &amp;quot;Bayer&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
To the following:&lt;br /&gt;
        int pnum = 0;&lt;br /&gt;
        ++pnum; params-&amp;gt;clip2 = avs_defined(avs_array_elt(args, pnum)) ? avs_take_clip(avs_array_elt(args, pnum), env) : 0;&lt;br /&gt;
        ++pnum; params-&amp;gt;weight = avs_defined(avs_array_elt(args, pnum)) ?&lt;br /&gt;
        avs_as_int(avs_array_elt(args, pnum)) : 1; // Default value for weight here&lt;br /&gt;
&lt;br /&gt;
It turns out that avs_array_elt contains our list of arguments in the order they were supplied in the script. We are going to expect the first parameter to be a clip, and the second to be an int. The first element, numbered 0, in the array is the value of last, which is also our first clip. pnum will be a counter to fetch each parameter, starting with number 1 (int pnum=0; ++pnum leaves pnum=1). avs_defined() is a function which checks to see if the parameter exists. So we are seeing if parameter #1 exists, and if so, assign it to params-&amp;gt;clip2 which is the structure we've defined to hold our parameters. If it doesn't exists, we'll just put a 0 there. The function avs_take_clip actually takes our clip.&lt;br /&gt;
&lt;br /&gt;
In the second parameter fetch, we use avs_as_int to fetch our weight. This function doesn't need an &amp;quot;env&amp;quot; argument. Instead of return 0 if the parameter isn't there, we will take the opportunity to also set a default value for weight here.&lt;br /&gt;
&lt;br /&gt;
Next comes checking the parameters. Even though it seems like we've saved the values, we actually don't know what they really are - they're just data at this point, that we've assumed were a clip and an int. Next we have to actually double-check this. Original code:&lt;br /&gt;
 // Check params&lt;br /&gt;
        retval = avs_void;&lt;br /&gt;
        if (stricmp(mosaic_str, &amp;quot;bayer&amp;quot;) == 0)&lt;br /&gt;
                params-&amp;gt;mosaic = BAYER;&lt;br /&gt;
        else&lt;br /&gt;
                retval = avs_new_value_error(&amp;quot;Mosaic mode can be: \&amp;quot;Bayer\&amp;quot;&amp;quot;);&lt;br /&gt;
        if (!avs_defined(retval) &amp;amp;&amp;amp; !avs_is_yuy2(&amp;amp;fi-&amp;gt;vi) &amp;amp;&amp;amp; !avs_is_yv12(&amp;amp;fi-&amp;gt;vi) &amp;amp;&amp;amp; !avs_is_y8(&amp;amp;fi-&amp;gt;vi)) {&lt;br /&gt;
                retval = avs_new_value_error(&amp;quot;Input video format can be: YUY2, YV12, Y8&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
New code:&lt;br /&gt;
  // Check params&lt;br /&gt;
        retval = avs_void;&lt;br /&gt;
  if (!avs_defined(retval) &amp;amp;&amp;amp; !avs_is_yuy2(&amp;amp;fi-&amp;gt;vi)) {&lt;br /&gt;
                retval = avs_new_value_error(&amp;quot;Input video format can be: YUY2&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
  if (!avs_defined(retval) &amp;amp;&amp;amp; !avs_is_int(params-&amp;gt;weight) {&lt;br /&gt;
                retval = avs_new_value_error(&amp;quot;weight must be an int&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
There's a few things to go over here. First of all, in the larger context we are defining what our plugin returns here, and that is what retval is. If you return void, it's the same as returning nothing - you'd see &amp;quot;Not a clip&amp;quot; if you tried to play it. We will cover returning a new clip shortly. !avs_defined(retval) is basically saying, &amp;quot;if retval hasn't been defined yet...&amp;quot;, and this is logic to continue checking parameters. In other words, if one of these checks fails, we will set an error message clip as a retval, then the next check will be skipped because a retval has been set. It's just a way to check each parameter just once and skip all other checks as soon as a problem is found. Now for the actual checking: !avs_is_yuy2(&amp;amp;fi-&amp;gt;vi) checks the colour format of our first clip; there are predefined functions for checking every format. Likewise, !avs_is_int(params-&amp;gt;weight) checks if our weight is really an int. avs_new_value_error() is a function that creates a new video clip with a message in it, similar to messageclip() in script. We use this to inform the user of the error. If all parameters are found to be correct, we finally return the output clip. Original code (unchanged):&lt;br /&gt;
        // If no errors, all is fine, return clip value&lt;br /&gt;
        if (!avs_defined(retval)) {&lt;br /&gt;
                retval = avs_new_value_clip(new_clip);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
Reference There are numerous checks for video type:&lt;br /&gt;
 int avs_is_rgb(const AVS_VideoInfo * p)&lt;br /&gt;
 int avs_is_rgb24(const AVS_VideoInfo * p)&lt;br /&gt;
 int avs_is_rgb32(const AVS_VideoInfo * p)&lt;br /&gt;
 int avs_is_yuy(const AVS_VideoInfo * p)&lt;br /&gt;
 int avs_is_yuy2(const AVS_VideoInfo * p)&lt;br /&gt;
 int avs_is_yv12(const AVS_VideoInfo * p)&lt;br /&gt;
&lt;br /&gt;
There are various checks for other parameters:&lt;br /&gt;
 int avs_defined(AVS_Value v)&lt;br /&gt;
 int avs_is_clip(AVS_Value v)&lt;br /&gt;
 int avs_is_bool(AVS_Value v)&lt;br /&gt;
 int avs_is_int(AVS_Value v)&lt;br /&gt;
 int avs_is_float(AVS_Value v)&lt;br /&gt;
 int avs_is_string(AVS_Value v)&lt;br /&gt;
 int avs_is_array(AVS_Value v)&lt;br /&gt;
 int avs_is_error(AVS_Value v)&lt;br /&gt;
&lt;br /&gt;
And as mentioned, we can return an error clip or a new clip; we can also return int, float, and string values which can be read by the runtime environment:&lt;br /&gt;
 AVS_Value avs_new_value_bool(int v0)&lt;br /&gt;
 AVS_Value avs_new_value_int(int v0)&lt;br /&gt;
 AVS_Value avs_new_value_string(const char * v0)&lt;br /&gt;
 AVS_Value avs_new_value_float(float v0)&lt;br /&gt;
 AVS_Value avs_new_value_error(const char * v0)&lt;br /&gt;
 AVS_Value avs_new_value_clip(AVS_Clip * v0)&lt;br /&gt;
 AVS_Value avs_new_value_array(AVS_Value * v0, int size)&lt;br /&gt;
&lt;br /&gt;
For more information, please review [http://www.kevina.org/avisynth_c/api.html AviSynth C Interface API Reference].&lt;br /&gt;
&lt;br /&gt;
==Writing the actual function==&lt;br /&gt;
After all that work, finally we can write a few simple lines of code to actually merge our videos! However, there's *still* a few more things you need to know. The various video formats are stored in memory in different ways; although we've got a pointer to an area of memory which holds our video, it can be *interpreted* in different ways, even though it's the same size! This is where handling of YUY2 vs YV12 and RGB comes in. We'll start with YUY2 in our example. YUY2 is where every two luma pixels share a color. A color is stored as two values, U and V. We won't go into what U and V means, except to say that if you average two pixels together, everything works out. YUY2 is stored in this format in memory, from the initial pointer to increasing values in memory, a byte at a time: Y1 U Y2 V. If you access the memory 4 bytes at a time (that is, as a 32 bit unsigned int), due to the Intel assembly stored values as Least Significant Byte order, the int would look like this: 0xVVYYUUYY, where each doubled letter represents one HEX value. For example, if our pixels were Y1=35, Y2=40, U=V=128 (which I'll tell you represents no color or grey), we'd have a hex value of 0x80288023. I mention that only as a reminder for the optimizing section. For now we'll simply deal with them as bytes for clarity. New code:&lt;br /&gt;
                 aY1=src_data[x];&lt;br /&gt;
                 bY1=clip2_data[x];&lt;br /&gt;
                 aU=src_data[x+1];&lt;br /&gt;
                 bU=clip2_data[x+1];&lt;br /&gt;
                 aY2=src_data[x+2];&lt;br /&gt;
                 bY2=clip2_data[x+2];&lt;br /&gt;
                 aV=src_data[x+3];&lt;br /&gt;
                 bV=clip2_data[x+3];&lt;br /&gt;
&lt;br /&gt;
Will give us a pair of pixels each from the two input clips in easy to use byte values. Finally, *finally*, we can simply write these 4 lines of code to finish our function:&lt;br /&gt;
           dest_data[x+1] = (aU/weight+bU*weight);&lt;br /&gt;
           dest_data[x+3] = (aV/weight+bV*weight);&lt;br /&gt;
           dest_data[x+0] = (aY1/weight+bY1*weight);&lt;br /&gt;
           dest_data[x+2] = (aY2/weight+bY2*weight);&lt;br /&gt;
&lt;br /&gt;
Just remember, again, that [x] is Y1, [x+1] is U, [x+2] is Y2, and [x+3] is V.&lt;br /&gt;
&lt;br /&gt;
==Putting it all together==&lt;br /&gt;
Download and compile the final sample code from .... Install, then open the Merge.cbp file, the project for Code::Blocks. Simply Build-&amp;gt;Build. You now have a fresh merge.dll in your project directory. In order to test it, I've include some simple windows batch files. Double click the install.bat icon. This will copy the merge.dll to your AviSynth directory. Note: ensure that you have no scripts open using the plugin, or the file will fail to overwrite any existing plugin version in your AviSynth directory. Next, open merge.avs in for example AvsP, then press F5. You should see a semitransparent message overlaid on the background. The weight value will change the degree of transparency, where a higher value makes the message stronger. &lt;br /&gt;
&lt;br /&gt;
==Conclusion==&lt;br /&gt;
In this manual, we've covered the basic steps necessary to convert an existing example to a new filter, with pointers on how to extend the concepts to include any set of parameters, to return a clip or runtime variable, and to access pixels pairs as stored in YUY2 colour format. In the next set of tutorials, it is planned to cover other colour formats, and some notes on optimizing your code for better execution speed. I hope you have found this tutorial useful. If you have any comments or corrections, please see the ongoing discussion at: http://forum.doom9.org/forumdisplay.php?f=69&lt;br /&gt;
&lt;br /&gt;
==External Links==&lt;br /&gt;
*[http://forum.doom9.org/showthread.php?p=1465008#post1465008 Doom9 Forum] - Includes corrections and additional information.&lt;br /&gt;
*[http://forum.doom9.org/showthread.php?p=1688939#post1688939 Doom9 Forum] - Continued discussion.&lt;br /&gt;
&lt;br /&gt;
[[Category:AviSynth_Development]]&lt;br /&gt;
[[Category:FilterSDK]]&lt;/div&gt;</summary>
		<author><name>Jmac698</name></author>	</entry>

	<entry>
		<id>http://avisynth.nl/index.php/Avisynth_Plugin_Development_in_C</id>
		<title>Avisynth Plugin Development in C</title>
		<link rel="alternate" type="text/html" href="http://avisynth.nl/index.php/Avisynth_Plugin_Development_in_C"/>
				<updated>2016-06-11T11:43:54Z</updated>
		
		<summary type="html">&lt;p&gt;Jmac698: /* Choosing a License */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Note: This guide is in development. Currently, only the section [[Avisynth_Plugin_Development_in_C#Compiling_Your_First_Plugin|Compiling Your First Plugin]] has been tested. The rest contains some errors, so use at your own risk! &lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
This tutorial takes you step-by-step through the process of creating a new C plugin for AviSynth by modifying an existing example. By the end of this tutorial, you should be able a plugin which returns a normal value or which works on a single frame. The target audience is the beginning level C programmer. &lt;br /&gt;
&lt;br /&gt;
==Why Develop a Plugin in C?==&lt;br /&gt;
Some reasons to use C based plugin development are that,&lt;br /&gt;
&lt;br /&gt;
*Free compilers can be used, such as MingW and online code editors such as https://codeanywhere.com/features/editor; only Microsoft Visual C++ or the free Community Edition may be used to create AviSynth C++ plugins&lt;br /&gt;
*You are only familiar with C&lt;br /&gt;
*It may be simpler to learn for a beginner&lt;br /&gt;
*There is no download (with online code editor) or small download (with mingw)&lt;br /&gt;
&lt;br /&gt;
==Choosing a License==&lt;br /&gt;
Before starting development, be aware of these license requirements:&lt;br /&gt;
&lt;br /&gt;
*The 2.6 C API requires that your plugin uses the GPL license. The GPL license requires that you release the source code.&lt;br /&gt;
*The 2.5 C API can use your own license, but the complete source of AviSynth 2.5 and the C API header must be made available along with your plugin binary&lt;br /&gt;
&lt;br /&gt;
==Plugin Compatibility==&lt;br /&gt;
Plugins programmed in the 2.5 C API can also be used with higher versions of AviSynth, however they can't access any newer features. &lt;br /&gt;
&lt;br /&gt;
==Setting up your Development Environment==&lt;br /&gt;
This tutorial was developed with Code::Blocks, a free development environment. Please follow these steps:&lt;br /&gt;
&lt;br /&gt;
*Download &amp;lt;tt&amp;gt;codeblocks-13.12mingw-setup.exe&amp;lt;/tt&amp;gt; from the [http://www.codeblocks.org/downloads/binaries CodeBlocks homepage] and run it&lt;br /&gt;
*The first screen reads &amp;quot;Welcome to the CodeBlocks Setup Wizard&amp;quot;. Click Next.&lt;br /&gt;
*The GPL license is displayed. Click I Agree.&lt;br /&gt;
*Choose any extra components to install if desired, but the default is sufficient. Click Next.&lt;br /&gt;
*Choose a destination folder. Click Install. Complete the wizard. &lt;br /&gt;
&lt;br /&gt;
==Compiling Your First Plugin==&lt;br /&gt;
Before making our own plugin, first we will learn how to compile an existing plugin. Please follow these steps:&lt;br /&gt;
&lt;br /&gt;
*Ensure that you included the option &amp;quot;Install FilterSDK&amp;quot; when installing AviSynth; otherwise reinstall AviSynth with that option.&lt;br /&gt;
*Create a C Projects folder under My Documents.&lt;br /&gt;
*Obtain the sample plugin Demosaic from [http://www.avisynth.nl/users/warpenterprises/files/demosaic_20071206.zip demosaic_20071206.zip]. Unzip the files to C Projects. There should now be demosaic, avisynth_c and avisynth_c_2_5 folders.&lt;br /&gt;
*Delete the avisynth_c and avisynth_c_2_5 folders.&lt;br /&gt;
*Delete this file from demosaic: makefile&lt;br /&gt;
*Make a new folder, lib under Demosaic.&lt;br /&gt;
*Copy (C:\Program Files\ or other installation directory then:) AviSynth 2.5\Extras\avisynth.lib to demosaic\lib.&lt;br /&gt;
*Copy (C:\Program Files\ or other installation directory then:) AviSynth 2.5\FilterSDK\include\avisynth_c.h to demosaic.&lt;br /&gt;
*Start Code::Blocks. Click Create a new project.&lt;br /&gt;
*Click Projects, then click Dynamic Link Library, then click Go.&lt;br /&gt;
*The wizard page &amp;quot;Dynamic Link Library&amp;quot; appears. Click Next.&lt;br /&gt;
*For Project title, use Demosaic. Choose the My Documents\C Projects folder you created in a previous step. Click Next.&lt;br /&gt;
*Under compiler, choose GNU GCC Compiler. Accept the defaults and click Finish.&lt;br /&gt;
*Right click &amp;quot;Demosaic&amp;quot;, and choose Remove files. A list showing main.cpp and main.h appear. Click OK. Click Yes.&lt;br /&gt;
*Delete these files from demosaic: main.cpp, main.h&lt;br /&gt;
*Right click &amp;quot;Demosaic&amp;quot; and choose Add Files. Add the demosaic.cpp file found in demosaic.&lt;br /&gt;
*A window asks you to choose which targets the file belongs to. Click OK.&lt;br /&gt;
*Right click Demosaic and choose Add Files. Add the avisynth_c.h file found in 'demosaic. Click OK.&lt;br /&gt;
*Select the menu Project-&amp;gt;Build Options.... Select Demosaic in the tree.&lt;br /&gt;
*Select the tab Linker settings. Click Add. Browse for the file Demosaic\lib\avisynth.lib.&lt;br /&gt;
*You are asked &amp;quot;Keep this as a relative path?&amp;quot;. Click Yes. Click OK. Click OK.&lt;br /&gt;
*Select the menu Build-&amp;gt;Select target-&amp;gt;Release.&lt;br /&gt;
*Select the menu Build-&amp;gt;Build.&lt;br /&gt;
*Verify that the file demosaic\bin\Release\Demosaic.dll was made. Copy this file to your (C:\Program Files\ or other installation directory then:) AviSynth 2.5 folder.&lt;br /&gt;
*Test the plugin by writing an AviSynth script: &lt;br /&gt;
&lt;br /&gt;
 Load_Stdcall_Plugin(&amp;quot;Demosaic.dll&amp;quot;)&lt;br /&gt;
 colorbars(pixel_type=&amp;quot;YV12&amp;quot;)&lt;br /&gt;
 Demosaic()&lt;br /&gt;
&lt;br /&gt;
This should display a grey test pattern with some colour fringes.&lt;br /&gt;
&lt;br /&gt;
*Save the project with File-&amp;gt;Save project. &lt;br /&gt;
&lt;br /&gt;
Troubleshooting:&lt;br /&gt;
&lt;br /&gt;
*Note that I found problems using full paths with spaces. The .lib file can only be found when placed in a folder lib and using relative paths.&lt;br /&gt;
*If you have a script error, try using the original demosaic.dll in the Demosaic folder. Note that this file starts with a lower case d, so adjust your script accordingly.&lt;br /&gt;
*The test.avs which comes with the plugin uses &amp;lt;code&amp;gt;LoadCPlugin&amp;lt;/code&amp;gt;. It is better to use &amp;lt;code&amp;gt;Load_Stdcall_Plugin&amp;lt;/code&amp;gt; because the &amp;lt;code&amp;gt;avisynth_c.dll&amp;lt;/code&amp;gt; plugin may be auto-loaded. This is a plugin which overrides the functionality of &amp;lt;code&amp;gt;LoadCPlugin&amp;lt;/code&amp;gt;, such that it won't load &amp;lt;tt&amp;gt;demosaic.dll&amp;lt;/tt&amp;gt; anymore. &lt;br /&gt;
&lt;br /&gt;
==Passing Parameters to your Plugin==&lt;br /&gt;
For this example, again we will start with the C source of Demosaic ([http://www.avisynth.nl/users/warpenterprises/files/demosaic_20071206.zip demosaic_20071206.zip])&lt;br /&gt;
&lt;br /&gt;
The example source defines a function, in AviSynth script terms, as: &lt;br /&gt;
&lt;br /&gt;
 Demosaic(clip clip1, string &amp;quot;mosaic&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
However, for our purposes we want to define a plugin like this:&lt;br /&gt;
&lt;br /&gt;
 Merge(clip clip1, clip clip2, int weight)&lt;br /&gt;
&lt;br /&gt;
Step 1: Define a place to store the parameters&lt;br /&gt;
&lt;br /&gt;
In this step, we will change the existing code:&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;pre&amp;gt;enum Mosaic {&lt;br /&gt;
        BAYER&lt;br /&gt;
 };&lt;br /&gt;
 struct Demosaic {&lt;br /&gt;
        Mosaic  mosaic;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
Into a new version:&lt;br /&gt;
 struct Params&lt;br /&gt;
 {&lt;br /&gt;
        AVS_Clip* clip2;&lt;br /&gt;
         int Weight;&lt;br /&gt;
 };&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Step 2: Tell Avisynth to parse the new parameters&amp;lt;br&amp;gt;&lt;br /&gt;
In this step, we will use a special code to inform the Avisynth parser to look for, and save our parameters. We will change the existing code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;const char* AVSC_CC avisynth_c_plugin_init(AVS_ScriptEnvironment* env)&lt;br /&gt;
 {&lt;br /&gt;
        avs_add_function(env, &amp;quot;Demosaic&amp;quot;, &amp;quot;c[mosaic]s&amp;quot;, create_filter, 0);&lt;br /&gt;
        return &amp;quot;Demosaic plugin&amp;quot;;&lt;br /&gt;
 }&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To the new version:&lt;br /&gt;
 const char* AVSC_CC avisynth_c_plugin_init(AVS_ScriptEnvironment* env)&lt;br /&gt;
 {&lt;br /&gt;
        avs_add_function(env, &amp;quot;Merge&amp;quot;, &amp;quot;cc[weight]i&amp;quot;, create_filter, 0);&lt;br /&gt;
        return &amp;quot;Merge plugin&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The:&lt;br /&gt;
 return &amp;quot;Merge plugin&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
statement returns a value to the LoadCPlugin() command (in AviSynth script) upon loading our plugin. In practice, almost no one checks this return value. The code&lt;br /&gt;
 avs_add_function(env, &amp;quot;Merge&amp;quot;, &amp;quot;c[weight]i&amp;quot;, create_filter, 0);&lt;br /&gt;
&lt;br /&gt;
does a few things; first &amp;quot;Merge&amp;quot; will be the name of our AviSynth script function (i.e., in the same sense that &amp;quot;[[Tweak]]&amp;quot; is a built-in function). Next, we use a special code to define the expected parameters. In this case, &amp;quot;c&amp;quot; refers to a clip while &amp;quot;i&amp;quot; refers to an int. If we had used &amp;quot;ci&amp;quot;, the function would simply expect a clip and an int, like this: &amp;lt;code&amp;gt;Merge(clip1,2)&amp;lt;/code&amp;gt; However, we wanted to use a named parameter, which is an optional parameter in functions which can also be named and placed in any order. For example, we could use this script: &lt;br /&gt;
&lt;br /&gt;
 Merge(clip1,weight=2)&lt;br /&gt;
&lt;br /&gt;
or simply leave it out:&lt;br /&gt;
&lt;br /&gt;
 Merge(clip1)&lt;br /&gt;
To specify the name, we include it in square brackets before the parameter type, which in this example, is &amp;quot;[weight]i&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Reference&lt;br /&gt;
&lt;br /&gt;
The special codes for defining your parameters: 'c' for clip, 'i' for integer, 's' for string, 'b' for boolean, and 'f' for float There are a few more features which are explained at: [http://www.kevina.org/avisynth_c/example.html AviSynth C Interface Illustrated Example] by Kevin Atkinson.&lt;br /&gt;
&lt;br /&gt;
Step 3: Fetching and checking your parameters In this final step, we will actually read the parameters which the AviSynth parser has saved for us. We will change the original code: &lt;br /&gt;
&lt;br /&gt;
        int pnum = 0;&lt;br /&gt;
        ++pnum; mosaic_str = avs_defined(avs_array_elt(args, pnum)) ? avs_as_string(avs_array_elt(args, pnum)) : &amp;quot;Bayer&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
To the following:&lt;br /&gt;
        int pnum = 0;&lt;br /&gt;
        ++pnum; params-&amp;gt;clip2 = avs_defined(avs_array_elt(args, pnum)) ? avs_take_clip(avs_array_elt(args, pnum), env) : 0;&lt;br /&gt;
        ++pnum; params-&amp;gt;weight = avs_defined(avs_array_elt(args, pnum)) ?&lt;br /&gt;
        avs_as_int(avs_array_elt(args, pnum)) : 1; // Default value for weight here&lt;br /&gt;
&lt;br /&gt;
It turns out that avs_array_elt contains our list of arguments in the order they were supplied in the script. We are going to expect the first parameter to be a clip, and the second to be an int. The first element, numbered 0, in the array is the value of last, which is also our first clip. pnum will be a counter to fetch each parameter, starting with number 1 (int pnum=0; ++pnum leaves pnum=1). avs_defined() is a function which checks to see if the parameter exists. So we are seeing if parameter #1 exists, and if so, assign it to params-&amp;gt;clip2 which is the structure we've defined to hold our parameters. If it doesn't exists, we'll just put a 0 there. The function avs_take_clip actually takes our clip.&lt;br /&gt;
&lt;br /&gt;
In the second parameter fetch, we use avs_as_int to fetch our weight. This function doesn't need an &amp;quot;env&amp;quot; argument. Instead of return 0 if the parameter isn't there, we will take the opportunity to also set a default value for weight here.&lt;br /&gt;
&lt;br /&gt;
Next comes checking the parameters. Even though it seems like we've saved the values, we actually don't know what they really are - they're just data at this point, that we've assumed were a clip and an int. Next we have to actually double-check this. Original code:&lt;br /&gt;
 // Check params&lt;br /&gt;
        retval = avs_void;&lt;br /&gt;
        if (stricmp(mosaic_str, &amp;quot;bayer&amp;quot;) == 0)&lt;br /&gt;
                params-&amp;gt;mosaic = BAYER;&lt;br /&gt;
        else&lt;br /&gt;
                retval = avs_new_value_error(&amp;quot;Mosaic mode can be: \&amp;quot;Bayer\&amp;quot;&amp;quot;);&lt;br /&gt;
        if (!avs_defined(retval) &amp;amp;&amp;amp; !avs_is_yuy2(&amp;amp;fi-&amp;gt;vi) &amp;amp;&amp;amp; !avs_is_yv12(&amp;amp;fi-&amp;gt;vi) &amp;amp;&amp;amp; !avs_is_y8(&amp;amp;fi-&amp;gt;vi)) {&lt;br /&gt;
                retval = avs_new_value_error(&amp;quot;Input video format can be: YUY2, YV12, Y8&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
New code:&lt;br /&gt;
  // Check params&lt;br /&gt;
        retval = avs_void;&lt;br /&gt;
  if (!avs_defined(retval) &amp;amp;&amp;amp; !avs_is_yuy2(&amp;amp;fi-&amp;gt;vi)) {&lt;br /&gt;
                retval = avs_new_value_error(&amp;quot;Input video format can be: YUY2&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
  if (!avs_defined(retval) &amp;amp;&amp;amp; !avs_is_int(params-&amp;gt;weight) {&lt;br /&gt;
                retval = avs_new_value_error(&amp;quot;weight must be an int&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
There's a few things to go over here. First of all, in the larger context we are defining what our plugin returns here, and that is what retval is. If you return void, it's the same as returning nothing - you'd see &amp;quot;Not a clip&amp;quot; if you tried to play it. We will cover returning a new clip shortly. !avs_defined(retval) is basically saying, &amp;quot;if retval hasn't been defined yet...&amp;quot;, and this is logic to continue checking parameters. In other words, if one of these checks fails, we will set an error message clip as a retval, then the next check will be skipped because a retval has been set. It's just a way to check each parameter just once and skip all other checks as soon as a problem is found. Now for the actual checking: !avs_is_yuy2(&amp;amp;fi-&amp;gt;vi) checks the colour format of our first clip; there are predefined functions for checking every format. Likewise, !avs_is_int(params-&amp;gt;weight) checks if our weight is really an int. avs_new_value_error() is a function that creates a new video clip with a message in it, similar to messageclip() in script. We use this to inform the user of the error. If all parameters are found to be correct, we finally return the output clip. Original code (unchanged):&lt;br /&gt;
        // If no errors, all is fine, return clip value&lt;br /&gt;
        if (!avs_defined(retval)) {&lt;br /&gt;
                retval = avs_new_value_clip(new_clip);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
Reference There are numerous checks for video type:&lt;br /&gt;
 int avs_is_rgb(const AVS_VideoInfo * p)&lt;br /&gt;
 int avs_is_rgb24(const AVS_VideoInfo * p)&lt;br /&gt;
 int avs_is_rgb32(const AVS_VideoInfo * p)&lt;br /&gt;
 int avs_is_yuy(const AVS_VideoInfo * p)&lt;br /&gt;
 int avs_is_yuy2(const AVS_VideoInfo * p)&lt;br /&gt;
 int avs_is_yv12(const AVS_VideoInfo * p)&lt;br /&gt;
&lt;br /&gt;
There are various checks for other parameters:&lt;br /&gt;
 int avs_defined(AVS_Value v)&lt;br /&gt;
 int avs_is_clip(AVS_Value v)&lt;br /&gt;
 int avs_is_bool(AVS_Value v)&lt;br /&gt;
 int avs_is_int(AVS_Value v)&lt;br /&gt;
 int avs_is_float(AVS_Value v)&lt;br /&gt;
 int avs_is_string(AVS_Value v)&lt;br /&gt;
 int avs_is_array(AVS_Value v)&lt;br /&gt;
 int avs_is_error(AVS_Value v)&lt;br /&gt;
&lt;br /&gt;
And as mentioned, we can return an error clip or a new clip; we can also return int, float, and string values which can be read by the runtime environment:&lt;br /&gt;
 AVS_Value avs_new_value_bool(int v0)&lt;br /&gt;
 AVS_Value avs_new_value_int(int v0)&lt;br /&gt;
 AVS_Value avs_new_value_string(const char * v0)&lt;br /&gt;
 AVS_Value avs_new_value_float(float v0)&lt;br /&gt;
 AVS_Value avs_new_value_error(const char * v0)&lt;br /&gt;
 AVS_Value avs_new_value_clip(AVS_Clip * v0)&lt;br /&gt;
 AVS_Value avs_new_value_array(AVS_Value * v0, int size)&lt;br /&gt;
&lt;br /&gt;
For more information, please review [http://www.kevina.org/avisynth_c/api.html AviSynth C Interface API Reference].&lt;br /&gt;
&lt;br /&gt;
==Writing the actual function==&lt;br /&gt;
After all that work, finally we can write a few simple lines of code to actually merge our videos! However, there's *still* a few more things you need to know. The various video formats are stored in memory in different ways; although we've got a pointer to an area of memory which holds our video, it can be *interpreted* in different ways, even though it's the same size! This is where handling of YUY2 vs YV12 and RGB comes in. We'll start with YUY2 in our example. YUY2 is where every two luma pixels share a color. A color is stored as two values, U and V. We won't go into what U and V means, except to say that if you average two pixels together, everything works out. YUY2 is stored in this format in memory, from the initial pointer to increasing values in memory, a byte at a time: Y1 U Y2 V. If you access the memory 4 bytes at a time (that is, as a 32 bit unsigned int), due to the Intel assembly stored values as Least Significant Byte order, the int would look like this: 0xVVYYUUYY, where each doubled letter represents one HEX value. For example, if our pixels were Y1=35, Y2=40, U=V=128 (which I'll tell you represents no color or grey), we'd have a hex value of 0x80288023. I mention that only as a reminder for the optimizing section. For now we'll simply deal with them as bytes for clarity. New code:&lt;br /&gt;
                 aY1=src_data[x];&lt;br /&gt;
                 bY1=clip2_data[x];&lt;br /&gt;
                 aU=src_data[x+1];&lt;br /&gt;
                 bU=clip2_data[x+1];&lt;br /&gt;
                 aY2=src_data[x+2];&lt;br /&gt;
                 bY2=clip2_data[x+2];&lt;br /&gt;
                 aV=src_data[x+3];&lt;br /&gt;
                 bV=clip2_data[x+3];&lt;br /&gt;
&lt;br /&gt;
Will give us a pair of pixels each from the two input clips in easy to use byte values. Finally, *finally*, we can simply write these 4 lines of code to finish our function:&lt;br /&gt;
           dest_data[x+1] = (aU/weight+bU*weight);&lt;br /&gt;
           dest_data[x+3] = (aV/weight+bV*weight);&lt;br /&gt;
           dest_data[x+0] = (aY1/weight+bY1*weight);&lt;br /&gt;
           dest_data[x+2] = (aY2/weight+bY2*weight);&lt;br /&gt;
&lt;br /&gt;
Just remember, again, that [x] is Y1, [x+1] is U, [x+2] is Y2, and [x+3] is V.&lt;br /&gt;
&lt;br /&gt;
==Putting it all together==&lt;br /&gt;
Download and compile the final sample code from .... Install, then open the Merge.cbp file, the project for Code::Blocks. Simply Build-&amp;gt;Build. You now have a fresh merge.dll in your project directory. In order to test it, I've include some simple windows batch files. Double click the install.bat icon. This will copy the merge.dll to your AviSynth directory. Note: ensure that you have no scripts open using the plugin, or the file will fail to overwrite any existing plugin version in your AviSynth directory. Next, open merge.avs in for example AvsP, then press F5. You should see a semitransparent message overlaid on the background. The weight value will change the degree of transparency, where a higher value makes the message stronger. &lt;br /&gt;
&lt;br /&gt;
==Conclusion==&lt;br /&gt;
In this manual, we've covered the basic steps necessary to convert an existing example to a new filter, with pointers on how to extend the concepts to include any set of parameters, to return a clip or runtime variable, and to access pixels pairs as stored in YUY2 colour format. In the next set of tutorials, it is planned to cover other colour formats, and some notes on optimizing your code for better execution speed. I hope you have found this tutorial useful. If you have any comments or corrections, please see the ongoing discussion at: http://forum.doom9.org/forumdisplay.php?f=69&lt;br /&gt;
&lt;br /&gt;
==External Links==&lt;br /&gt;
*[http://forum.doom9.org/showthread.php?p=1465008#post1465008 Doom9 Forum] - Includes corrections and additional information.&lt;br /&gt;
*[http://forum.doom9.org/showthread.php?p=1688939#post1688939 Doom9 Forum] - Continued discussion.&lt;br /&gt;
&lt;br /&gt;
[[Category:AviSynth_Development]]&lt;br /&gt;
[[Category:FilterSDK]]&lt;/div&gt;</summary>
		<author><name>Jmac698</name></author>	</entry>

	<entry>
		<id>http://avisynth.nl/index.php/Avisynth_Plugin_Development_in_C</id>
		<title>Avisynth Plugin Development in C</title>
		<link rel="alternate" type="text/html" href="http://avisynth.nl/index.php/Avisynth_Plugin_Development_in_C"/>
				<updated>2016-06-11T11:42:49Z</updated>
		
		<summary type="html">&lt;p&gt;Jmac698: /* Why Develop a Plugin in C? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Note: This guide is in development. Currently, only the section [[Avisynth_Plugin_Development_in_C#Compiling_Your_First_Plugin|Compiling Your First Plugin]] has been tested. The rest contains some errors, so use at your own risk! &lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
This tutorial takes you step-by-step through the process of creating a new C plugin for AviSynth by modifying an existing example. By the end of this tutorial, you should be able a plugin which returns a normal value or which works on a single frame. The target audience is the beginning level C programmer. &lt;br /&gt;
&lt;br /&gt;
==Why Develop a Plugin in C?==&lt;br /&gt;
Some reasons to use C based plugin development are that,&lt;br /&gt;
&lt;br /&gt;
*Free compilers can be used, such as MingW and online code editors such as https://codeanywhere.com/features/editor; only Microsoft Visual C++ or the free Community Edition may be used to create AviSynth C++ plugins&lt;br /&gt;
*You are only familiar with C&lt;br /&gt;
*It may be simpler to learn for a beginner&lt;br /&gt;
*There is no download (with online code editor) or small download (with mingw)&lt;br /&gt;
&lt;br /&gt;
==Choosing a License==&lt;br /&gt;
Before starting development, be aware of these license requirements:&lt;br /&gt;
&lt;br /&gt;
*The 2.6a5 C API requires that your plugin uses the GPL license. The GPL license requires that you release the source code.&lt;br /&gt;
*The 2.5 C API can use your own license, but the complete source of AviSynth 2.5 and the C API header must be made available along with your plugin binary&lt;br /&gt;
&lt;br /&gt;
==Plugin Compatibility==&lt;br /&gt;
Plugins programmed in the 2.5 C API can also be used with higher versions of AviSynth, however they can't access any newer features. &lt;br /&gt;
&lt;br /&gt;
==Setting up your Development Environment==&lt;br /&gt;
This tutorial was developed with Code::Blocks, a free development environment. Please follow these steps:&lt;br /&gt;
&lt;br /&gt;
*Download &amp;lt;tt&amp;gt;codeblocks-13.12mingw-setup.exe&amp;lt;/tt&amp;gt; from the [http://www.codeblocks.org/downloads/binaries CodeBlocks homepage] and run it&lt;br /&gt;
*The first screen reads &amp;quot;Welcome to the CodeBlocks Setup Wizard&amp;quot;. Click Next.&lt;br /&gt;
*The GPL license is displayed. Click I Agree.&lt;br /&gt;
*Choose any extra components to install if desired, but the default is sufficient. Click Next.&lt;br /&gt;
*Choose a destination folder. Click Install. Complete the wizard. &lt;br /&gt;
&lt;br /&gt;
==Compiling Your First Plugin==&lt;br /&gt;
Before making our own plugin, first we will learn how to compile an existing plugin. Please follow these steps:&lt;br /&gt;
&lt;br /&gt;
*Ensure that you included the option &amp;quot;Install FilterSDK&amp;quot; when installing AviSynth; otherwise reinstall AviSynth with that option.&lt;br /&gt;
*Create a C Projects folder under My Documents.&lt;br /&gt;
*Obtain the sample plugin Demosaic from [http://www.avisynth.nl/users/warpenterprises/files/demosaic_20071206.zip demosaic_20071206.zip]. Unzip the files to C Projects. There should now be demosaic, avisynth_c and avisynth_c_2_5 folders.&lt;br /&gt;
*Delete the avisynth_c and avisynth_c_2_5 folders.&lt;br /&gt;
*Delete this file from demosaic: makefile&lt;br /&gt;
*Make a new folder, lib under Demosaic.&lt;br /&gt;
*Copy (C:\Program Files\ or other installation directory then:) AviSynth 2.5\Extras\avisynth.lib to demosaic\lib.&lt;br /&gt;
*Copy (C:\Program Files\ or other installation directory then:) AviSynth 2.5\FilterSDK\include\avisynth_c.h to demosaic.&lt;br /&gt;
*Start Code::Blocks. Click Create a new project.&lt;br /&gt;
*Click Projects, then click Dynamic Link Library, then click Go.&lt;br /&gt;
*The wizard page &amp;quot;Dynamic Link Library&amp;quot; appears. Click Next.&lt;br /&gt;
*For Project title, use Demosaic. Choose the My Documents\C Projects folder you created in a previous step. Click Next.&lt;br /&gt;
*Under compiler, choose GNU GCC Compiler. Accept the defaults and click Finish.&lt;br /&gt;
*Right click &amp;quot;Demosaic&amp;quot;, and choose Remove files. A list showing main.cpp and main.h appear. Click OK. Click Yes.&lt;br /&gt;
*Delete these files from demosaic: main.cpp, main.h&lt;br /&gt;
*Right click &amp;quot;Demosaic&amp;quot; and choose Add Files. Add the demosaic.cpp file found in demosaic.&lt;br /&gt;
*A window asks you to choose which targets the file belongs to. Click OK.&lt;br /&gt;
*Right click Demosaic and choose Add Files. Add the avisynth_c.h file found in 'demosaic. Click OK.&lt;br /&gt;
*Select the menu Project-&amp;gt;Build Options.... Select Demosaic in the tree.&lt;br /&gt;
*Select the tab Linker settings. Click Add. Browse for the file Demosaic\lib\avisynth.lib.&lt;br /&gt;
*You are asked &amp;quot;Keep this as a relative path?&amp;quot;. Click Yes. Click OK. Click OK.&lt;br /&gt;
*Select the menu Build-&amp;gt;Select target-&amp;gt;Release.&lt;br /&gt;
*Select the menu Build-&amp;gt;Build.&lt;br /&gt;
*Verify that the file demosaic\bin\Release\Demosaic.dll was made. Copy this file to your (C:\Program Files\ or other installation directory then:) AviSynth 2.5 folder.&lt;br /&gt;
*Test the plugin by writing an AviSynth script: &lt;br /&gt;
&lt;br /&gt;
 Load_Stdcall_Plugin(&amp;quot;Demosaic.dll&amp;quot;)&lt;br /&gt;
 colorbars(pixel_type=&amp;quot;YV12&amp;quot;)&lt;br /&gt;
 Demosaic()&lt;br /&gt;
&lt;br /&gt;
This should display a grey test pattern with some colour fringes.&lt;br /&gt;
&lt;br /&gt;
*Save the project with File-&amp;gt;Save project. &lt;br /&gt;
&lt;br /&gt;
Troubleshooting:&lt;br /&gt;
&lt;br /&gt;
*Note that I found problems using full paths with spaces. The .lib file can only be found when placed in a folder lib and using relative paths.&lt;br /&gt;
*If you have a script error, try using the original demosaic.dll in the Demosaic folder. Note that this file starts with a lower case d, so adjust your script accordingly.&lt;br /&gt;
*The test.avs which comes with the plugin uses &amp;lt;code&amp;gt;LoadCPlugin&amp;lt;/code&amp;gt;. It is better to use &amp;lt;code&amp;gt;Load_Stdcall_Plugin&amp;lt;/code&amp;gt; because the &amp;lt;code&amp;gt;avisynth_c.dll&amp;lt;/code&amp;gt; plugin may be auto-loaded. This is a plugin which overrides the functionality of &amp;lt;code&amp;gt;LoadCPlugin&amp;lt;/code&amp;gt;, such that it won't load &amp;lt;tt&amp;gt;demosaic.dll&amp;lt;/tt&amp;gt; anymore. &lt;br /&gt;
&lt;br /&gt;
==Passing Parameters to your Plugin==&lt;br /&gt;
For this example, again we will start with the C source of Demosaic ([http://www.avisynth.nl/users/warpenterprises/files/demosaic_20071206.zip demosaic_20071206.zip])&lt;br /&gt;
&lt;br /&gt;
The example source defines a function, in AviSynth script terms, as: &lt;br /&gt;
&lt;br /&gt;
 Demosaic(clip clip1, string &amp;quot;mosaic&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
However, for our purposes we want to define a plugin like this:&lt;br /&gt;
&lt;br /&gt;
 Merge(clip clip1, clip clip2, int weight)&lt;br /&gt;
&lt;br /&gt;
Step 1: Define a place to store the parameters&lt;br /&gt;
&lt;br /&gt;
In this step, we will change the existing code:&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;pre&amp;gt;enum Mosaic {&lt;br /&gt;
        BAYER&lt;br /&gt;
 };&lt;br /&gt;
 struct Demosaic {&lt;br /&gt;
        Mosaic  mosaic;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
Into a new version:&lt;br /&gt;
 struct Params&lt;br /&gt;
 {&lt;br /&gt;
        AVS_Clip* clip2;&lt;br /&gt;
         int Weight;&lt;br /&gt;
 };&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Step 2: Tell Avisynth to parse the new parameters&amp;lt;br&amp;gt;&lt;br /&gt;
In this step, we will use a special code to inform the Avisynth parser to look for, and save our parameters. We will change the existing code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;const char* AVSC_CC avisynth_c_plugin_init(AVS_ScriptEnvironment* env)&lt;br /&gt;
 {&lt;br /&gt;
        avs_add_function(env, &amp;quot;Demosaic&amp;quot;, &amp;quot;c[mosaic]s&amp;quot;, create_filter, 0);&lt;br /&gt;
        return &amp;quot;Demosaic plugin&amp;quot;;&lt;br /&gt;
 }&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To the new version:&lt;br /&gt;
 const char* AVSC_CC avisynth_c_plugin_init(AVS_ScriptEnvironment* env)&lt;br /&gt;
 {&lt;br /&gt;
        avs_add_function(env, &amp;quot;Merge&amp;quot;, &amp;quot;cc[weight]i&amp;quot;, create_filter, 0);&lt;br /&gt;
        return &amp;quot;Merge plugin&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The:&lt;br /&gt;
 return &amp;quot;Merge plugin&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
statement returns a value to the LoadCPlugin() command (in AviSynth script) upon loading our plugin. In practice, almost no one checks this return value. The code&lt;br /&gt;
 avs_add_function(env, &amp;quot;Merge&amp;quot;, &amp;quot;c[weight]i&amp;quot;, create_filter, 0);&lt;br /&gt;
&lt;br /&gt;
does a few things; first &amp;quot;Merge&amp;quot; will be the name of our AviSynth script function (i.e., in the same sense that &amp;quot;[[Tweak]]&amp;quot; is a built-in function). Next, we use a special code to define the expected parameters. In this case, &amp;quot;c&amp;quot; refers to a clip while &amp;quot;i&amp;quot; refers to an int. If we had used &amp;quot;ci&amp;quot;, the function would simply expect a clip and an int, like this: &amp;lt;code&amp;gt;Merge(clip1,2)&amp;lt;/code&amp;gt; However, we wanted to use a named parameter, which is an optional parameter in functions which can also be named and placed in any order. For example, we could use this script: &lt;br /&gt;
&lt;br /&gt;
 Merge(clip1,weight=2)&lt;br /&gt;
&lt;br /&gt;
or simply leave it out:&lt;br /&gt;
&lt;br /&gt;
 Merge(clip1)&lt;br /&gt;
To specify the name, we include it in square brackets before the parameter type, which in this example, is &amp;quot;[weight]i&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Reference&lt;br /&gt;
&lt;br /&gt;
The special codes for defining your parameters: 'c' for clip, 'i' for integer, 's' for string, 'b' for boolean, and 'f' for float There are a few more features which are explained at: [http://www.kevina.org/avisynth_c/example.html AviSynth C Interface Illustrated Example] by Kevin Atkinson.&lt;br /&gt;
&lt;br /&gt;
Step 3: Fetching and checking your parameters In this final step, we will actually read the parameters which the AviSynth parser has saved for us. We will change the original code: &lt;br /&gt;
&lt;br /&gt;
        int pnum = 0;&lt;br /&gt;
        ++pnum; mosaic_str = avs_defined(avs_array_elt(args, pnum)) ? avs_as_string(avs_array_elt(args, pnum)) : &amp;quot;Bayer&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
To the following:&lt;br /&gt;
        int pnum = 0;&lt;br /&gt;
        ++pnum; params-&amp;gt;clip2 = avs_defined(avs_array_elt(args, pnum)) ? avs_take_clip(avs_array_elt(args, pnum), env) : 0;&lt;br /&gt;
        ++pnum; params-&amp;gt;weight = avs_defined(avs_array_elt(args, pnum)) ?&lt;br /&gt;
        avs_as_int(avs_array_elt(args, pnum)) : 1; // Default value for weight here&lt;br /&gt;
&lt;br /&gt;
It turns out that avs_array_elt contains our list of arguments in the order they were supplied in the script. We are going to expect the first parameter to be a clip, and the second to be an int. The first element, numbered 0, in the array is the value of last, which is also our first clip. pnum will be a counter to fetch each parameter, starting with number 1 (int pnum=0; ++pnum leaves pnum=1). avs_defined() is a function which checks to see if the parameter exists. So we are seeing if parameter #1 exists, and if so, assign it to params-&amp;gt;clip2 which is the structure we've defined to hold our parameters. If it doesn't exists, we'll just put a 0 there. The function avs_take_clip actually takes our clip.&lt;br /&gt;
&lt;br /&gt;
In the second parameter fetch, we use avs_as_int to fetch our weight. This function doesn't need an &amp;quot;env&amp;quot; argument. Instead of return 0 if the parameter isn't there, we will take the opportunity to also set a default value for weight here.&lt;br /&gt;
&lt;br /&gt;
Next comes checking the parameters. Even though it seems like we've saved the values, we actually don't know what they really are - they're just data at this point, that we've assumed were a clip and an int. Next we have to actually double-check this. Original code:&lt;br /&gt;
 // Check params&lt;br /&gt;
        retval = avs_void;&lt;br /&gt;
        if (stricmp(mosaic_str, &amp;quot;bayer&amp;quot;) == 0)&lt;br /&gt;
                params-&amp;gt;mosaic = BAYER;&lt;br /&gt;
        else&lt;br /&gt;
                retval = avs_new_value_error(&amp;quot;Mosaic mode can be: \&amp;quot;Bayer\&amp;quot;&amp;quot;);&lt;br /&gt;
        if (!avs_defined(retval) &amp;amp;&amp;amp; !avs_is_yuy2(&amp;amp;fi-&amp;gt;vi) &amp;amp;&amp;amp; !avs_is_yv12(&amp;amp;fi-&amp;gt;vi) &amp;amp;&amp;amp; !avs_is_y8(&amp;amp;fi-&amp;gt;vi)) {&lt;br /&gt;
                retval = avs_new_value_error(&amp;quot;Input video format can be: YUY2, YV12, Y8&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
New code:&lt;br /&gt;
  // Check params&lt;br /&gt;
        retval = avs_void;&lt;br /&gt;
  if (!avs_defined(retval) &amp;amp;&amp;amp; !avs_is_yuy2(&amp;amp;fi-&amp;gt;vi)) {&lt;br /&gt;
                retval = avs_new_value_error(&amp;quot;Input video format can be: YUY2&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
  if (!avs_defined(retval) &amp;amp;&amp;amp; !avs_is_int(params-&amp;gt;weight) {&lt;br /&gt;
                retval = avs_new_value_error(&amp;quot;weight must be an int&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
There's a few things to go over here. First of all, in the larger context we are defining what our plugin returns here, and that is what retval is. If you return void, it's the same as returning nothing - you'd see &amp;quot;Not a clip&amp;quot; if you tried to play it. We will cover returning a new clip shortly. !avs_defined(retval) is basically saying, &amp;quot;if retval hasn't been defined yet...&amp;quot;, and this is logic to continue checking parameters. In other words, if one of these checks fails, we will set an error message clip as a retval, then the next check will be skipped because a retval has been set. It's just a way to check each parameter just once and skip all other checks as soon as a problem is found. Now for the actual checking: !avs_is_yuy2(&amp;amp;fi-&amp;gt;vi) checks the colour format of our first clip; there are predefined functions for checking every format. Likewise, !avs_is_int(params-&amp;gt;weight) checks if our weight is really an int. avs_new_value_error() is a function that creates a new video clip with a message in it, similar to messageclip() in script. We use this to inform the user of the error. If all parameters are found to be correct, we finally return the output clip. Original code (unchanged):&lt;br /&gt;
        // If no errors, all is fine, return clip value&lt;br /&gt;
        if (!avs_defined(retval)) {&lt;br /&gt;
                retval = avs_new_value_clip(new_clip);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
Reference There are numerous checks for video type:&lt;br /&gt;
 int avs_is_rgb(const AVS_VideoInfo * p)&lt;br /&gt;
 int avs_is_rgb24(const AVS_VideoInfo * p)&lt;br /&gt;
 int avs_is_rgb32(const AVS_VideoInfo * p)&lt;br /&gt;
 int avs_is_yuy(const AVS_VideoInfo * p)&lt;br /&gt;
 int avs_is_yuy2(const AVS_VideoInfo * p)&lt;br /&gt;
 int avs_is_yv12(const AVS_VideoInfo * p)&lt;br /&gt;
&lt;br /&gt;
There are various checks for other parameters:&lt;br /&gt;
 int avs_defined(AVS_Value v)&lt;br /&gt;
 int avs_is_clip(AVS_Value v)&lt;br /&gt;
 int avs_is_bool(AVS_Value v)&lt;br /&gt;
 int avs_is_int(AVS_Value v)&lt;br /&gt;
 int avs_is_float(AVS_Value v)&lt;br /&gt;
 int avs_is_string(AVS_Value v)&lt;br /&gt;
 int avs_is_array(AVS_Value v)&lt;br /&gt;
 int avs_is_error(AVS_Value v)&lt;br /&gt;
&lt;br /&gt;
And as mentioned, we can return an error clip or a new clip; we can also return int, float, and string values which can be read by the runtime environment:&lt;br /&gt;
 AVS_Value avs_new_value_bool(int v0)&lt;br /&gt;
 AVS_Value avs_new_value_int(int v0)&lt;br /&gt;
 AVS_Value avs_new_value_string(const char * v0)&lt;br /&gt;
 AVS_Value avs_new_value_float(float v0)&lt;br /&gt;
 AVS_Value avs_new_value_error(const char * v0)&lt;br /&gt;
 AVS_Value avs_new_value_clip(AVS_Clip * v0)&lt;br /&gt;
 AVS_Value avs_new_value_array(AVS_Value * v0, int size)&lt;br /&gt;
&lt;br /&gt;
For more information, please review [http://www.kevina.org/avisynth_c/api.html AviSynth C Interface API Reference].&lt;br /&gt;
&lt;br /&gt;
==Writing the actual function==&lt;br /&gt;
After all that work, finally we can write a few simple lines of code to actually merge our videos! However, there's *still* a few more things you need to know. The various video formats are stored in memory in different ways; although we've got a pointer to an area of memory which holds our video, it can be *interpreted* in different ways, even though it's the same size! This is where handling of YUY2 vs YV12 and RGB comes in. We'll start with YUY2 in our example. YUY2 is where every two luma pixels share a color. A color is stored as two values, U and V. We won't go into what U and V means, except to say that if you average two pixels together, everything works out. YUY2 is stored in this format in memory, from the initial pointer to increasing values in memory, a byte at a time: Y1 U Y2 V. If you access the memory 4 bytes at a time (that is, as a 32 bit unsigned int), due to the Intel assembly stored values as Least Significant Byte order, the int would look like this: 0xVVYYUUYY, where each doubled letter represents one HEX value. For example, if our pixels were Y1=35, Y2=40, U=V=128 (which I'll tell you represents no color or grey), we'd have a hex value of 0x80288023. I mention that only as a reminder for the optimizing section. For now we'll simply deal with them as bytes for clarity. New code:&lt;br /&gt;
                 aY1=src_data[x];&lt;br /&gt;
                 bY1=clip2_data[x];&lt;br /&gt;
                 aU=src_data[x+1];&lt;br /&gt;
                 bU=clip2_data[x+1];&lt;br /&gt;
                 aY2=src_data[x+2];&lt;br /&gt;
                 bY2=clip2_data[x+2];&lt;br /&gt;
                 aV=src_data[x+3];&lt;br /&gt;
                 bV=clip2_data[x+3];&lt;br /&gt;
&lt;br /&gt;
Will give us a pair of pixels each from the two input clips in easy to use byte values. Finally, *finally*, we can simply write these 4 lines of code to finish our function:&lt;br /&gt;
           dest_data[x+1] = (aU/weight+bU*weight);&lt;br /&gt;
           dest_data[x+3] = (aV/weight+bV*weight);&lt;br /&gt;
           dest_data[x+0] = (aY1/weight+bY1*weight);&lt;br /&gt;
           dest_data[x+2] = (aY2/weight+bY2*weight);&lt;br /&gt;
&lt;br /&gt;
Just remember, again, that [x] is Y1, [x+1] is U, [x+2] is Y2, and [x+3] is V.&lt;br /&gt;
&lt;br /&gt;
==Putting it all together==&lt;br /&gt;
Download and compile the final sample code from .... Install, then open the Merge.cbp file, the project for Code::Blocks. Simply Build-&amp;gt;Build. You now have a fresh merge.dll in your project directory. In order to test it, I've include some simple windows batch files. Double click the install.bat icon. This will copy the merge.dll to your AviSynth directory. Note: ensure that you have no scripts open using the plugin, or the file will fail to overwrite any existing plugin version in your AviSynth directory. Next, open merge.avs in for example AvsP, then press F5. You should see a semitransparent message overlaid on the background. The weight value will change the degree of transparency, where a higher value makes the message stronger. &lt;br /&gt;
&lt;br /&gt;
==Conclusion==&lt;br /&gt;
In this manual, we've covered the basic steps necessary to convert an existing example to a new filter, with pointers on how to extend the concepts to include any set of parameters, to return a clip or runtime variable, and to access pixels pairs as stored in YUY2 colour format. In the next set of tutorials, it is planned to cover other colour formats, and some notes on optimizing your code for better execution speed. I hope you have found this tutorial useful. If you have any comments or corrections, please see the ongoing discussion at: http://forum.doom9.org/forumdisplay.php?f=69&lt;br /&gt;
&lt;br /&gt;
==External Links==&lt;br /&gt;
*[http://forum.doom9.org/showthread.php?p=1465008#post1465008 Doom9 Forum] - Includes corrections and additional information.&lt;br /&gt;
*[http://forum.doom9.org/showthread.php?p=1688939#post1688939 Doom9 Forum] - Continued discussion.&lt;br /&gt;
&lt;br /&gt;
[[Category:AviSynth_Development]]&lt;br /&gt;
[[Category:FilterSDK]]&lt;/div&gt;</summary>
		<author><name>Jmac698</name></author>	</entry>

	<entry>
		<id>http://avisynth.nl/index.php/Avisynth_Plugin_Development_in_C</id>
		<title>Avisynth Plugin Development in C</title>
		<link rel="alternate" type="text/html" href="http://avisynth.nl/index.php/Avisynth_Plugin_Development_in_C"/>
				<updated>2016-06-11T11:39:42Z</updated>
		
		<summary type="html">&lt;p&gt;Jmac698: /* Writing the actual function */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Note: This guide is in development. Currently, only the section [[Avisynth_Plugin_Development_in_C#Compiling_Your_First_Plugin|Compiling Your First Plugin]] has been tested. The rest contains some errors, so use at your own risk! &lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
This tutorial takes you step-by-step through the process of creating a new C plugin for AviSynth by modifying an existing example. By the end of this tutorial, you should be able a plugin which returns a normal value or which works on a single frame. The target audience is the beginning level C programmer. &lt;br /&gt;
&lt;br /&gt;
==Why Develop a Plugin in C?==&lt;br /&gt;
Some reasons to use C based plugin development are that,&lt;br /&gt;
&lt;br /&gt;
*Free compilers can be used, such as MingW; only Microsoft Visual C++ may be used to create AviSynth C++ plugins&lt;br /&gt;
*You are only familiar with C&lt;br /&gt;
*It may be simpler to learn for a beginner &lt;br /&gt;
&lt;br /&gt;
==Choosing a License==&lt;br /&gt;
Before starting development, be aware of these license requirements:&lt;br /&gt;
&lt;br /&gt;
*The 2.6a5 C API requires that your plugin uses the GPL license. The GPL license requires that you release the source code.&lt;br /&gt;
*The 2.5 C API can use your own license, but the complete source of AviSynth 2.5 and the C API header must be made available along with your plugin binary&lt;br /&gt;
&lt;br /&gt;
==Plugin Compatibility==&lt;br /&gt;
Plugins programmed in the 2.5 C API can also be used with higher versions of AviSynth, however they can't access any newer features. &lt;br /&gt;
&lt;br /&gt;
==Setting up your Development Environment==&lt;br /&gt;
This tutorial was developed with Code::Blocks, a free development environment. Please follow these steps:&lt;br /&gt;
&lt;br /&gt;
*Download &amp;lt;tt&amp;gt;codeblocks-13.12mingw-setup.exe&amp;lt;/tt&amp;gt; from the [http://www.codeblocks.org/downloads/binaries CodeBlocks homepage] and run it&lt;br /&gt;
*The first screen reads &amp;quot;Welcome to the CodeBlocks Setup Wizard&amp;quot;. Click Next.&lt;br /&gt;
*The GPL license is displayed. Click I Agree.&lt;br /&gt;
*Choose any extra components to install if desired, but the default is sufficient. Click Next.&lt;br /&gt;
*Choose a destination folder. Click Install. Complete the wizard. &lt;br /&gt;
&lt;br /&gt;
==Compiling Your First Plugin==&lt;br /&gt;
Before making our own plugin, first we will learn how to compile an existing plugin. Please follow these steps:&lt;br /&gt;
&lt;br /&gt;
*Ensure that you included the option &amp;quot;Install FilterSDK&amp;quot; when installing AviSynth; otherwise reinstall AviSynth with that option.&lt;br /&gt;
*Create a C Projects folder under My Documents.&lt;br /&gt;
*Obtain the sample plugin Demosaic from [http://www.avisynth.nl/users/warpenterprises/files/demosaic_20071206.zip demosaic_20071206.zip]. Unzip the files to C Projects. There should now be demosaic, avisynth_c and avisynth_c_2_5 folders.&lt;br /&gt;
*Delete the avisynth_c and avisynth_c_2_5 folders.&lt;br /&gt;
*Delete this file from demosaic: makefile&lt;br /&gt;
*Make a new folder, lib under Demosaic.&lt;br /&gt;
*Copy (C:\Program Files\ or other installation directory then:) AviSynth 2.5\Extras\avisynth.lib to demosaic\lib.&lt;br /&gt;
*Copy (C:\Program Files\ or other installation directory then:) AviSynth 2.5\FilterSDK\include\avisynth_c.h to demosaic.&lt;br /&gt;
*Start Code::Blocks. Click Create a new project.&lt;br /&gt;
*Click Projects, then click Dynamic Link Library, then click Go.&lt;br /&gt;
*The wizard page &amp;quot;Dynamic Link Library&amp;quot; appears. Click Next.&lt;br /&gt;
*For Project title, use Demosaic. Choose the My Documents\C Projects folder you created in a previous step. Click Next.&lt;br /&gt;
*Under compiler, choose GNU GCC Compiler. Accept the defaults and click Finish.&lt;br /&gt;
*Right click &amp;quot;Demosaic&amp;quot;, and choose Remove files. A list showing main.cpp and main.h appear. Click OK. Click Yes.&lt;br /&gt;
*Delete these files from demosaic: main.cpp, main.h&lt;br /&gt;
*Right click &amp;quot;Demosaic&amp;quot; and choose Add Files. Add the demosaic.cpp file found in demosaic.&lt;br /&gt;
*A window asks you to choose which targets the file belongs to. Click OK.&lt;br /&gt;
*Right click Demosaic and choose Add Files. Add the avisynth_c.h file found in 'demosaic. Click OK.&lt;br /&gt;
*Select the menu Project-&amp;gt;Build Options.... Select Demosaic in the tree.&lt;br /&gt;
*Select the tab Linker settings. Click Add. Browse for the file Demosaic\lib\avisynth.lib.&lt;br /&gt;
*You are asked &amp;quot;Keep this as a relative path?&amp;quot;. Click Yes. Click OK. Click OK.&lt;br /&gt;
*Select the menu Build-&amp;gt;Select target-&amp;gt;Release.&lt;br /&gt;
*Select the menu Build-&amp;gt;Build.&lt;br /&gt;
*Verify that the file demosaic\bin\Release\Demosaic.dll was made. Copy this file to your (C:\Program Files\ or other installation directory then:) AviSynth 2.5 folder.&lt;br /&gt;
*Test the plugin by writing an AviSynth script: &lt;br /&gt;
&lt;br /&gt;
 Load_Stdcall_Plugin(&amp;quot;Demosaic.dll&amp;quot;)&lt;br /&gt;
 colorbars(pixel_type=&amp;quot;YV12&amp;quot;)&lt;br /&gt;
 Demosaic()&lt;br /&gt;
&lt;br /&gt;
This should display a grey test pattern with some colour fringes.&lt;br /&gt;
&lt;br /&gt;
*Save the project with File-&amp;gt;Save project. &lt;br /&gt;
&lt;br /&gt;
Troubleshooting:&lt;br /&gt;
&lt;br /&gt;
*Note that I found problems using full paths with spaces. The .lib file can only be found when placed in a folder lib and using relative paths.&lt;br /&gt;
*If you have a script error, try using the original demosaic.dll in the Demosaic folder. Note that this file starts with a lower case d, so adjust your script accordingly.&lt;br /&gt;
*The test.avs which comes with the plugin uses &amp;lt;code&amp;gt;LoadCPlugin&amp;lt;/code&amp;gt;. It is better to use &amp;lt;code&amp;gt;Load_Stdcall_Plugin&amp;lt;/code&amp;gt; because the &amp;lt;code&amp;gt;avisynth_c.dll&amp;lt;/code&amp;gt; plugin may be auto-loaded. This is a plugin which overrides the functionality of &amp;lt;code&amp;gt;LoadCPlugin&amp;lt;/code&amp;gt;, such that it won't load &amp;lt;tt&amp;gt;demosaic.dll&amp;lt;/tt&amp;gt; anymore. &lt;br /&gt;
&lt;br /&gt;
==Passing Parameters to your Plugin==&lt;br /&gt;
For this example, again we will start with the C source of Demosaic ([http://www.avisynth.nl/users/warpenterprises/files/demosaic_20071206.zip demosaic_20071206.zip])&lt;br /&gt;
&lt;br /&gt;
The example source defines a function, in AviSynth script terms, as: &lt;br /&gt;
&lt;br /&gt;
 Demosaic(clip clip1, string &amp;quot;mosaic&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
However, for our purposes we want to define a plugin like this:&lt;br /&gt;
&lt;br /&gt;
 Merge(clip clip1, clip clip2, int weight)&lt;br /&gt;
&lt;br /&gt;
Step 1: Define a place to store the parameters&lt;br /&gt;
&lt;br /&gt;
In this step, we will change the existing code:&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;pre&amp;gt;enum Mosaic {&lt;br /&gt;
        BAYER&lt;br /&gt;
 };&lt;br /&gt;
 struct Demosaic {&lt;br /&gt;
        Mosaic  mosaic;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
Into a new version:&lt;br /&gt;
 struct Params&lt;br /&gt;
 {&lt;br /&gt;
        AVS_Clip* clip2;&lt;br /&gt;
         int Weight;&lt;br /&gt;
 };&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Step 2: Tell Avisynth to parse the new parameters&amp;lt;br&amp;gt;&lt;br /&gt;
In this step, we will use a special code to inform the Avisynth parser to look for, and save our parameters. We will change the existing code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;const char* AVSC_CC avisynth_c_plugin_init(AVS_ScriptEnvironment* env)&lt;br /&gt;
 {&lt;br /&gt;
        avs_add_function(env, &amp;quot;Demosaic&amp;quot;, &amp;quot;c[mosaic]s&amp;quot;, create_filter, 0);&lt;br /&gt;
        return &amp;quot;Demosaic plugin&amp;quot;;&lt;br /&gt;
 }&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To the new version:&lt;br /&gt;
 const char* AVSC_CC avisynth_c_plugin_init(AVS_ScriptEnvironment* env)&lt;br /&gt;
 {&lt;br /&gt;
        avs_add_function(env, &amp;quot;Merge&amp;quot;, &amp;quot;cc[weight]i&amp;quot;, create_filter, 0);&lt;br /&gt;
        return &amp;quot;Merge plugin&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The:&lt;br /&gt;
 return &amp;quot;Merge plugin&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
statement returns a value to the LoadCPlugin() command (in AviSynth script) upon loading our plugin. In practice, almost no one checks this return value. The code&lt;br /&gt;
 avs_add_function(env, &amp;quot;Merge&amp;quot;, &amp;quot;c[weight]i&amp;quot;, create_filter, 0);&lt;br /&gt;
&lt;br /&gt;
does a few things; first &amp;quot;Merge&amp;quot; will be the name of our AviSynth script function (i.e., in the same sense that &amp;quot;[[Tweak]]&amp;quot; is a built-in function). Next, we use a special code to define the expected parameters. In this case, &amp;quot;c&amp;quot; refers to a clip while &amp;quot;i&amp;quot; refers to an int. If we had used &amp;quot;ci&amp;quot;, the function would simply expect a clip and an int, like this: &amp;lt;code&amp;gt;Merge(clip1,2)&amp;lt;/code&amp;gt; However, we wanted to use a named parameter, which is an optional parameter in functions which can also be named and placed in any order. For example, we could use this script: &lt;br /&gt;
&lt;br /&gt;
 Merge(clip1,weight=2)&lt;br /&gt;
&lt;br /&gt;
or simply leave it out:&lt;br /&gt;
&lt;br /&gt;
 Merge(clip1)&lt;br /&gt;
To specify the name, we include it in square brackets before the parameter type, which in this example, is &amp;quot;[weight]i&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Reference&lt;br /&gt;
&lt;br /&gt;
The special codes for defining your parameters: 'c' for clip, 'i' for integer, 's' for string, 'b' for boolean, and 'f' for float There are a few more features which are explained at: [http://www.kevina.org/avisynth_c/example.html AviSynth C Interface Illustrated Example] by Kevin Atkinson.&lt;br /&gt;
&lt;br /&gt;
Step 3: Fetching and checking your parameters In this final step, we will actually read the parameters which the AviSynth parser has saved for us. We will change the original code: &lt;br /&gt;
&lt;br /&gt;
        int pnum = 0;&lt;br /&gt;
        ++pnum; mosaic_str = avs_defined(avs_array_elt(args, pnum)) ? avs_as_string(avs_array_elt(args, pnum)) : &amp;quot;Bayer&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
To the following:&lt;br /&gt;
        int pnum = 0;&lt;br /&gt;
        ++pnum; params-&amp;gt;clip2 = avs_defined(avs_array_elt(args, pnum)) ? avs_take_clip(avs_array_elt(args, pnum), env) : 0;&lt;br /&gt;
        ++pnum; params-&amp;gt;weight = avs_defined(avs_array_elt(args, pnum)) ?&lt;br /&gt;
        avs_as_int(avs_array_elt(args, pnum)) : 1; // Default value for weight here&lt;br /&gt;
&lt;br /&gt;
It turns out that avs_array_elt contains our list of arguments in the order they were supplied in the script. We are going to expect the first parameter to be a clip, and the second to be an int. The first element, numbered 0, in the array is the value of last, which is also our first clip. pnum will be a counter to fetch each parameter, starting with number 1 (int pnum=0; ++pnum leaves pnum=1). avs_defined() is a function which checks to see if the parameter exists. So we are seeing if parameter #1 exists, and if so, assign it to params-&amp;gt;clip2 which is the structure we've defined to hold our parameters. If it doesn't exists, we'll just put a 0 there. The function avs_take_clip actually takes our clip.&lt;br /&gt;
&lt;br /&gt;
In the second parameter fetch, we use avs_as_int to fetch our weight. This function doesn't need an &amp;quot;env&amp;quot; argument. Instead of return 0 if the parameter isn't there, we will take the opportunity to also set a default value for weight here.&lt;br /&gt;
&lt;br /&gt;
Next comes checking the parameters. Even though it seems like we've saved the values, we actually don't know what they really are - they're just data at this point, that we've assumed were a clip and an int. Next we have to actually double-check this. Original code:&lt;br /&gt;
 // Check params&lt;br /&gt;
        retval = avs_void;&lt;br /&gt;
        if (stricmp(mosaic_str, &amp;quot;bayer&amp;quot;) == 0)&lt;br /&gt;
                params-&amp;gt;mosaic = BAYER;&lt;br /&gt;
        else&lt;br /&gt;
                retval = avs_new_value_error(&amp;quot;Mosaic mode can be: \&amp;quot;Bayer\&amp;quot;&amp;quot;);&lt;br /&gt;
        if (!avs_defined(retval) &amp;amp;&amp;amp; !avs_is_yuy2(&amp;amp;fi-&amp;gt;vi) &amp;amp;&amp;amp; !avs_is_yv12(&amp;amp;fi-&amp;gt;vi) &amp;amp;&amp;amp; !avs_is_y8(&amp;amp;fi-&amp;gt;vi)) {&lt;br /&gt;
                retval = avs_new_value_error(&amp;quot;Input video format can be: YUY2, YV12, Y8&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
New code:&lt;br /&gt;
  // Check params&lt;br /&gt;
        retval = avs_void;&lt;br /&gt;
  if (!avs_defined(retval) &amp;amp;&amp;amp; !avs_is_yuy2(&amp;amp;fi-&amp;gt;vi)) {&lt;br /&gt;
                retval = avs_new_value_error(&amp;quot;Input video format can be: YUY2&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
  if (!avs_defined(retval) &amp;amp;&amp;amp; !avs_is_int(params-&amp;gt;weight) {&lt;br /&gt;
                retval = avs_new_value_error(&amp;quot;weight must be an int&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
There's a few things to go over here. First of all, in the larger context we are defining what our plugin returns here, and that is what retval is. If you return void, it's the same as returning nothing - you'd see &amp;quot;Not a clip&amp;quot; if you tried to play it. We will cover returning a new clip shortly. !avs_defined(retval) is basically saying, &amp;quot;if retval hasn't been defined yet...&amp;quot;, and this is logic to continue checking parameters. In other words, if one of these checks fails, we will set an error message clip as a retval, then the next check will be skipped because a retval has been set. It's just a way to check each parameter just once and skip all other checks as soon as a problem is found. Now for the actual checking: !avs_is_yuy2(&amp;amp;fi-&amp;gt;vi) checks the colour format of our first clip; there are predefined functions for checking every format. Likewise, !avs_is_int(params-&amp;gt;weight) checks if our weight is really an int. avs_new_value_error() is a function that creates a new video clip with a message in it, similar to messageclip() in script. We use this to inform the user of the error. If all parameters are found to be correct, we finally return the output clip. Original code (unchanged):&lt;br /&gt;
        // If no errors, all is fine, return clip value&lt;br /&gt;
        if (!avs_defined(retval)) {&lt;br /&gt;
                retval = avs_new_value_clip(new_clip);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
Reference There are numerous checks for video type:&lt;br /&gt;
 int avs_is_rgb(const AVS_VideoInfo * p)&lt;br /&gt;
 int avs_is_rgb24(const AVS_VideoInfo * p)&lt;br /&gt;
 int avs_is_rgb32(const AVS_VideoInfo * p)&lt;br /&gt;
 int avs_is_yuy(const AVS_VideoInfo * p)&lt;br /&gt;
 int avs_is_yuy2(const AVS_VideoInfo * p)&lt;br /&gt;
 int avs_is_yv12(const AVS_VideoInfo * p)&lt;br /&gt;
&lt;br /&gt;
There are various checks for other parameters:&lt;br /&gt;
 int avs_defined(AVS_Value v)&lt;br /&gt;
 int avs_is_clip(AVS_Value v)&lt;br /&gt;
 int avs_is_bool(AVS_Value v)&lt;br /&gt;
 int avs_is_int(AVS_Value v)&lt;br /&gt;
 int avs_is_float(AVS_Value v)&lt;br /&gt;
 int avs_is_string(AVS_Value v)&lt;br /&gt;
 int avs_is_array(AVS_Value v)&lt;br /&gt;
 int avs_is_error(AVS_Value v)&lt;br /&gt;
&lt;br /&gt;
And as mentioned, we can return an error clip or a new clip; we can also return int, float, and string values which can be read by the runtime environment:&lt;br /&gt;
 AVS_Value avs_new_value_bool(int v0)&lt;br /&gt;
 AVS_Value avs_new_value_int(int v0)&lt;br /&gt;
 AVS_Value avs_new_value_string(const char * v0)&lt;br /&gt;
 AVS_Value avs_new_value_float(float v0)&lt;br /&gt;
 AVS_Value avs_new_value_error(const char * v0)&lt;br /&gt;
 AVS_Value avs_new_value_clip(AVS_Clip * v0)&lt;br /&gt;
 AVS_Value avs_new_value_array(AVS_Value * v0, int size)&lt;br /&gt;
&lt;br /&gt;
For more information, please review [http://www.kevina.org/avisynth_c/api.html AviSynth C Interface API Reference].&lt;br /&gt;
&lt;br /&gt;
==Writing the actual function==&lt;br /&gt;
After all that work, finally we can write a few simple lines of code to actually merge our videos! However, there's *still* a few more things you need to know. The various video formats are stored in memory in different ways; although we've got a pointer to an area of memory which holds our video, it can be *interpreted* in different ways, even though it's the same size! This is where handling of YUY2 vs YV12 and RGB comes in. We'll start with YUY2 in our example. YUY2 is where every two luma pixels share a color. A color is stored as two values, U and V. We won't go into what U and V means, except to say that if you average two pixels together, everything works out. YUY2 is stored in this format in memory, from the initial pointer to increasing values in memory, a byte at a time: Y1 U Y2 V. If you access the memory 4 bytes at a time (that is, as a 32 bit unsigned int), due to the Intel assembly stored values as Least Significant Byte order, the int would look like this: 0xVVYYUUYY, where each doubled letter represents one HEX value. For example, if our pixels were Y1=35, Y2=40, U=V=128 (which I'll tell you represents no color or grey), we'd have a hex value of 0x80288023. I mention that only as a reminder for the optimizing section. For now we'll simply deal with them as bytes for clarity. New code:&lt;br /&gt;
                 aY1=src_data[x];&lt;br /&gt;
                 bY1=clip2_data[x];&lt;br /&gt;
                 aU=src_data[x+1];&lt;br /&gt;
                 bU=clip2_data[x+1];&lt;br /&gt;
                 aY2=src_data[x+2];&lt;br /&gt;
                 bY2=clip2_data[x+2];&lt;br /&gt;
                 aV=src_data[x+3];&lt;br /&gt;
                 bV=clip2_data[x+3];&lt;br /&gt;
&lt;br /&gt;
Will give us a pair of pixels each from the two input clips in easy to use byte values. Finally, *finally*, we can simply write these 4 lines of code to finish our function:&lt;br /&gt;
           dest_data[x+1] = (aU/weight+bU*weight);&lt;br /&gt;
           dest_data[x+3] = (aV/weight+bV*weight);&lt;br /&gt;
           dest_data[x+0] = (aY1/weight+bY1*weight);&lt;br /&gt;
           dest_data[x+2] = (aY2/weight+bY2*weight);&lt;br /&gt;
&lt;br /&gt;
Just remember, again, that [x] is Y1, [x+1] is U, [x+2] is Y2, and [x+3] is V.&lt;br /&gt;
&lt;br /&gt;
==Putting it all together==&lt;br /&gt;
Download and compile the final sample code from .... Install, then open the Merge.cbp file, the project for Code::Blocks. Simply Build-&amp;gt;Build. You now have a fresh merge.dll in your project directory. In order to test it, I've include some simple windows batch files. Double click the install.bat icon. This will copy the merge.dll to your AviSynth directory. Note: ensure that you have no scripts open using the plugin, or the file will fail to overwrite any existing plugin version in your AviSynth directory. Next, open merge.avs in for example AvsP, then press F5. You should see a semitransparent message overlaid on the background. The weight value will change the degree of transparency, where a higher value makes the message stronger. &lt;br /&gt;
&lt;br /&gt;
==Conclusion==&lt;br /&gt;
In this manual, we've covered the basic steps necessary to convert an existing example to a new filter, with pointers on how to extend the concepts to include any set of parameters, to return a clip or runtime variable, and to access pixels pairs as stored in YUY2 colour format. In the next set of tutorials, it is planned to cover other colour formats, and some notes on optimizing your code for better execution speed. I hope you have found this tutorial useful. If you have any comments or corrections, please see the ongoing discussion at: http://forum.doom9.org/forumdisplay.php?f=69&lt;br /&gt;
&lt;br /&gt;
==External Links==&lt;br /&gt;
*[http://forum.doom9.org/showthread.php?p=1465008#post1465008 Doom9 Forum] - Includes corrections and additional information.&lt;br /&gt;
*[http://forum.doom9.org/showthread.php?p=1688939#post1688939 Doom9 Forum] - Continued discussion.&lt;br /&gt;
&lt;br /&gt;
[[Category:AviSynth_Development]]&lt;br /&gt;
[[Category:FilterSDK]]&lt;/div&gt;</summary>
		<author><name>Jmac698</name></author>	</entry>

	<entry>
		<id>http://avisynth.nl/index.php/High_bit-depth_Support_with_Avisynth</id>
		<title>High bit-depth Support with Avisynth</title>
		<link rel="alternate" type="text/html" href="http://avisynth.nl/index.php/High_bit-depth_Support_with_Avisynth"/>
				<updated>2015-11-10T02:34:55Z</updated>
		
		<summary type="html">&lt;p&gt;Jmac698: /* Image Magick */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Currently, Avisynth only supports 8-bit video.  Nevertheless, through various utilities, plugins, and scripts, Avisynth can be used to import, process, and export high bit-depth video.  There has been some effort to update Avisynth itself to support high bit-depth, but there has been no progress as of 2012 (http://forum.doom9.org/showthread.php?t=162436).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== What is Deep Color? ==&lt;br /&gt;
&lt;br /&gt;
Deepcolor refers to using more than 8 bits of data to represent each color channel.  It is also referred to as high bit-depth color.  Basically, deepcolor/high bit-depth allows finer graduations of color, allowing smoother gradients and more detail.  Please refer to this short, easy to understand article:  [http://www.pcworld.com/article/171223/what_is_10bit_color.html PCWorld: What is 10-bit Color?]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Why Use Deep Color? ==&lt;br /&gt;
&lt;br /&gt;
*Higher internal precision, using high-bit depth color, when processing an image in a filter, gives a higher quality (8-bit) output.&lt;br /&gt;
*If a video filter uses linear gamma internally, there can be noticeable differences in the image.  A linear gamma representation is best supported with a high bit-depth. See the illustration for [http://int64.org/projects/resamplehq/ ResampleHQ].&lt;br /&gt;
*If you encode high-bit depth video, you can get better compression (reportedly up to 30%) and less banding.  &lt;br /&gt;
*Banding is one of the most serious liabilities of 8-bit depth.  Refer to the following references for an explanation of why 10-bit encodes compress better:&lt;br /&gt;
**[http://x264.nl/x264/10bit_02-ateme-why_does_10bit_save_bandwidth.pdf Why does 10-bit save bandwidth (even when content is 8-bit)?.pdf]&lt;br /&gt;
**[http://x264.nl/x264/10bit_01-ateme_pierre_larbier_422_10-bit.pdf Using 10-bit AVC/H.264 Encoding with 4:2:2 for Broadcast Contribution.pdf]&lt;br /&gt;
**[http://x264.nl/x264/10bit_03-422_10_bit_pristine_video_quality.pdf Keeping Video Quality Pristine throughout the Production Process: 4:2:2 10-bit AVC/H.264 encoding.pdf]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Importing High Bit-depth Video into AviSynth ==&lt;br /&gt;
For importing high bit depth video [http://sourceforge.net/projects/avisynth2/ AviSynth 2.6.0] or greater is strongly recommended. AviSynth 2.6 adds the additional [[planar]] color spaces ([[Y8]],[[YV16]],[[YV24]], [[YV411]]) which makes it that much more compatible with all of the existing formats. &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== [[FFmpegSource|FFMS2]] ===&lt;br /&gt;
'''Patched FFMS2''' - import DNxHD, ProRes, and other 10-bit videos in their native format (4:2:2 and 4:4:4 are also supported), output greater than 8-bits will always be in the [[Stack16]] format.&lt;br /&gt;
&lt;br /&gt;
*Source code: [http://github.com/SAPikachu/ffms2_hacks GitHub repository]&lt;br /&gt;
*Discussion: [http://forum.doom9.org/showthread.php?t=164841 Doom9 thread] - Importing DNxHD to Avisynth (some of the links may be outdated; see downloads below or [http://forum.doom9.org/member.php?u=135430 SAPikachu's signature] for latest versions)&lt;br /&gt;
&lt;br /&gt;
==== Download ====&lt;br /&gt;
Updated binaries: March 15, 2015 | [http://www.mediafire.com/folder/2izh9abzep52o/Video_works older versions]&lt;br /&gt;
* &amp;lt;code&amp;gt;[http://www.nmm-hd.org/upload/get~t6gq8DWihBs/ffms2-6e0d654+a9fe004-ffmbc-FFmbc-0.7.1.7z ffms2-6e0d654+a9fe004-ffmbc-FFmbc-0.7.1.7z]&amp;lt;/code&amp;gt; | [http://web.archive.org/web/20150321005059/https://www.nmm-hd.org/upload/get~t6gq8DWihBs/ffms2-6e0d654+a9fe004-ffmbc-FFmbc-0.7.1.7z mirror] - This version uses [http://code.google.com/p/ffmbc/ FFmbc] as a decoder; may have better support for professional video formats like ProRes, DNxHD, etc.&lt;br /&gt;
* &amp;lt;code&amp;gt;[http://www.nmm-hd.org/upload/get~BLsLZwgj5ps/ffms2-6e0d654+a9fe004-ffmpeg-1e4d049.7z ffms2-6e0d654+a9fe004-ffmpeg-1e4d049.7z]&amp;lt;/code&amp;gt; | [http://web.archive.org/web/20150321005255/https://www.nmm-hd.org/upload/get~BLsLZwgj5ps/ffms2-6e0d654+a9fe004-ffmpeg-1e4d049.7z mirror] - This version uses [http://en.wikipedia.org/wiki/FFmpeg FFmpeg] as a decoder; may be better for general (more common) formats.&lt;br /&gt;
* &amp;lt;code&amp;gt;[http://www.nmm-hd.org/upload/get~Q4mZfV9y0Og/ffms2-6e0d654+a9fe004-libav-9a60b1f.7z ffms2-6e0d654+a9fe004-libav-9a60b1f.7z]&amp;lt;/code&amp;gt; | [http://web.archive.org/web/20150321005339/https://www.nmm-hd.org/upload/get~Q4mZfV9y0Og/ffms2-6e0d654+a9fe004-libav-9a60b1f.7z mirror] - This version uses [http://en.wikipedia.org/wiki/Libav Libav] as a decoder; may be better for general (more common) formats.&lt;br /&gt;
These versions work just like the official [[FFmpegSource|FFMS2]], but includes the additional {{FuncDef3|enable10bithack}} parameter and support for the additional [[planar]] colorspaces available is AviSynth 2.6. &amp;lt;br/&amp;gt;By default {{FuncDef3|enable10bithack}} is set to false so it will work just like the official FFMS2; to import high bit depth video set {{FuncDef3|enable10bithack}}&amp;lt;tt&amp;gt;=true&amp;lt;/tt&amp;gt;, output will be in the [[Stack16]] format.&amp;lt;br/&amp;gt;&lt;br /&gt;
See [http://github.com/mpv-player/mpv/wiki/FFmpeg-versus-Libav FFmpeg versus Libav] for information on pros and cons and differences between the FFmpeg and Libav.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;!--===== Archived Downloads =====&lt;br /&gt;
* &amp;lt;code&amp;gt;[http://www.nmm-hd.org/upload/get~PbKYgPe2oKY/ffms2-9417b9c-ffmbc-FFmbc-0.7-rc8.7z ffms2-9417b9c-ffmbc-FFmbc-0.7-rc8.7z]&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;[http://www.nmm-hd.org/upload/get~fmbjO7t9dEg/ffms2-9417b9c-ffmpeg-8728360.7z ffms2-9417b9c-ffmpeg-8728360.7z]&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;[http://www.nmm-hd.org/upload/get~3O9tHZ9TJIM/ffms2-9417b9c-libav-aca2510.7z ffms2-9417b9c-libav-aca2510.7z]&amp;lt;/code&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[LSMASHSource]] ===&lt;br /&gt;
Another source filter to import regular 8-bit and high bit depth video. LSMASHSource includes these 2 fuctions to import video:&lt;br /&gt;
*[[LSMASHSource/LSMASHVideoSource|LSMASHVideoSource]] - This function uses [http://en.wikipedia.org/wiki/Libavcodec#Implemented_video_codecs libavcodec] as a video decoder and [http://github.com/l-smash/l-smash L-SMASH] as a demuxer. Recommended for MP4, MOV, [http://en.wikipedia.org/wiki/ISO_base_media_file_format ISO Base Media] and its derived file formats.&amp;lt;br/&amp;gt;&lt;br /&gt;
*[[LSMASHSource/LWLibavVideoSource|LWLibavVideoSource]] - This function uses [http://en.wikipedia.org/wiki/Libavcodec#Implemented_video_codecs libavcodec] as a video decoder and [http://www.ffmpeg.org/libavformat.html libavformat] as a demuxer.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== [[VapourSource]] ===&lt;br /&gt;
Can be used to import [http://www.vapoursynth.com/ VapourSynth] scripts into AviSynth. Video can be 8-bit or greater.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Image Magick]] ===&lt;br /&gt;
You can also import video or still via 16-bit PNG format pictures with the following Image Magick command lines (examples shown for Windows, requires the 16-bit version of Image Magick found at http://www.imagemagick.org/script/bi...es.php#windows, the file ImageMagick-x.y.z-a-Q16-x64)&lt;br /&gt;
&lt;br /&gt;
Convert 16-bit to stacked (high/low or stack16 format):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
convert 16bit.png -depth 16 ( +clone -evaluate and 255 -evaluate multiply 256 ) -append stacked.png&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
convert stacked (high/low) to 16bit:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
convert stacked.png -depth 16 -crop 100%x50% ( +clone -evaluate divide 256 ) -delete 1 -compose Add -composite -define png:bit-depth=16 16bit1.png&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For further explanation of these command lines, please see the thread http://forum.doom9.org/showthread.php?t=172846&lt;br /&gt;
&lt;br /&gt;
=== Obsolete === &lt;br /&gt;
'''The following methods are obsolete! If you must, only use as a verification or as workaround:'''&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*[http://forum.doom9.org/showthread.php?p=1526131#post1526131 Readv210mod] - Can read uncompressed v210 in .mov container as color.  Needs a manual setting skip the file header.  &lt;br /&gt;
&lt;br /&gt;
*[http://sites.google.com/site/ourenthusiasmsasham/soft Sashimi] - Sashimi 0.85 has different bit-depth support.  Please see OtherFormats/Read_v210.avs included in the package.&lt;br /&gt;
&lt;br /&gt;
*[http://forum.doom9.org/showthread.php?t=158985 ReadV210] - Can read uncompressed v210 in .mov container as greyscale.  &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alternative builds and methods of importing '''(also obsolete)''':&lt;br /&gt;
&lt;br /&gt;
*[http://forum.doom9.org/showthread.php?p=1528494 ffms2mod] - Can return most 10bit video in the Avisynth high bit-depth convention.&lt;br /&gt;
&lt;br /&gt;
*[http://forum.doom9.org/showthread.php?t=162598&amp;amp;page=2 RawSource with ffmpeg]  - shows an example of using ffmpeg to convert to a 16bit format which can be read by RawSource in Avisynth 2.6.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Processing High Bit-depth Video with AviSynth ==&lt;br /&gt;
&lt;br /&gt;
Some plugins support processing internally in a higher bit-depth for better quality and return an 8-bit video.  Others support full high-bit processing and can retun a special format 16 bit video.&lt;br /&gt;
&lt;br /&gt;
Most developers have adopted a vertically stacked format known as [[Stack16]], where the high bits (MSB) are stored in the upper half of a video, and the lower bits (LSB) in the lower half of the video.&amp;lt;br&amp;gt;&lt;br /&gt;
This special format must be processed only with high-bit aware scripts and plugins.&amp;lt;br&amp;gt;&lt;br /&gt;
* Multipurpose&lt;br /&gt;
**'''[[Dither_tools|Dither]]''' - A set of scripts, original and modified plugins to process 16-bit clips. Some of the functions include 16-bit color space conversion, debanding, denoising, resizing, and dithering 16-bit to lower bit depths.&lt;br /&gt;
**'''[http://github.com/tp7/CLExpr/releases CLExpr]''' - OpenCl plugin for runtime calculation of expressions on 8 and 16-bit depths clips. Makes mt_lutxy and mt_lutxyz possible on 16-bit. More information [http://forum.doom9.org/showpost.php?p=1672638 here].&lt;br /&gt;
**'''[http://forum.doom9.org/showthread.php?t=154971 SmoothAdjust]''' - High quality YUV color adjustment plugin. SmoothAdjust can input and output 16-bits; all calculations are internally done in 32-bit float to avoid rounding errors and artifacts.&lt;br /&gt;
&lt;br /&gt;
* Antialiasing&lt;br /&gt;
**'''[[Xaa]]''' - anti-aliasing and resizing script.&lt;br /&gt;
&lt;br /&gt;
* Debanding&lt;br /&gt;
**'''[http://forum.doom9.org/showthread.php?t=161411 flash3kyuu_deband]''' - Debanding filter with 8/16 bit input/output. In addition flash3kyuu_deband can be used to dither 16-bit to lower bit depths. &lt;br /&gt;
&lt;br /&gt;
* Degraining&lt;br /&gt;
**'''[[SMDegrain]]''' - mvtools+mdegrain denoising with 16-bit input and output.&lt;br /&gt;
&lt;br /&gt;
* Denoising&lt;br /&gt;
**'''[http://forum.doom9.org/showthread.php?t=162342 DenoiseMD]''' - 8/16-bit denoise.&lt;br /&gt;
**'''[[Dfttest]]''' - 8/16-bit 2D/3D frequency domain denoiser.&lt;br /&gt;
**'''[http://forum.doom9.org/showthread.php?t=171379 KNLMeansCL]''' - OpenCL based Non Local Means denoising with support for 16-bit input and output.&lt;br /&gt;
**'''[http://forum.doom9.org/showthread.php?t=163018 RedAverage]''' - 16-bit capable average with masking. Download latest version [http://chaosking.de/wp-content/uploads/avsfilters/Unclassified/RedAverage___(1.4.3_-_2011-12-02).7z here]&lt;br /&gt;
**'''[http://forum.videohelp.com/threads/369142-Simple-MDegrain-Mod-v2-2d-A-Quality-Denoising-Solution SMDegrainMod]''' - 8/16 bit denoising with additional features like sharpening. [http://web.archive.org/web/20131210170708/http://doom10.org/index.php?topic=2178.0 Original Doom10 archived page.]&lt;br /&gt;
**'''[http://forum.doom9.org/showthread.php?t=167032 TempLinearApproximate]''' - 8/16 bit filter for temporal linear approximation between pixels . Meant mainly for denoising aid in motion compensated clips.&lt;br /&gt;
&lt;br /&gt;
* Deringing&lt;br /&gt;
**[[HQDering_mod|'''HQDeringMod''']] - Deringing script with 16-bit input and output.&lt;br /&gt;
&lt;br /&gt;
* Effects&lt;br /&gt;
**'''[[f3kgrain]]''' - Luma adaptive grain generator with 8/16-bit input and output.&lt;br /&gt;
&lt;br /&gt;
* Frame Averaging&lt;br /&gt;
**'''[http://forum.doom9.org/showpost.php?p=1579509 AvgAll_16]''' - Average all frames in a clip with 16-bit accuracy.&lt;br /&gt;
**'''[http://forum.doom9.org/showthread.php?t=168048 ClipBlend16]''' - Blend an specified amount of frames into a single frame with 16-bit accuracy. &lt;br /&gt;
	&lt;br /&gt;
* Resizing&lt;br /&gt;
**'''[[Debicubic]]''' - This filter is designed to reverse the effects of bicubic upsampling. 8/16-bit input and output.&lt;br /&gt;
**'''[[Debilinear]]''' - This filter is designed to reverse the effects of bilinear upsampling. 8/16-bit input and output.    &lt;br /&gt;
**'''[[nnedi3_resize16]]''' - An advanced script for high quality image resizing and colorspace conversion. It supports 16-bit input and output.&lt;br /&gt;
**'''[http://svn.int64.org/viewvc/int64/resamplehq/doc/index.html ResampleHQ]''' - Provides gamma-aware resizing and color space conversion.  Uses 32-bit linear color internally but input and output is limited to 8-bit.&lt;br /&gt;
**'''[http://forum.videohelp.com/threads/369143-ResizersPack-MasksPack-PlaygroundPack-SmoothContrast-Logo-mod-functions?p=2364056 Resizers Functions Pack]''' - Includes LinearResize(), a function to resize in linear space. 8/16-bit input/output. [http://web.archive.org/web/20141105135234/http://doom10.org/index.php?topic=2182.0 Original Doom10 archived page.]&lt;br /&gt;
&lt;br /&gt;
* Deprecated&lt;br /&gt;
**'''[http://forum.doom9.org/showthread.php?p=1467907#post1467907 Deep Color Tools]''' - This Script provides basic functions to import 10bit video, do color adjustments, and export to 8bit. (NOT RECOMMENDED, THERE ARE BETTER ALTERNATIVES)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You can also check the [[External_filters#Deepcolor_Filters|External Filters: DeepColor]] section, and the [[:Category:Deep_color_tools|Deep Color Tools]] category for possibly more listings.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Codecs which support high bit-depth ==&lt;br /&gt;
&lt;br /&gt;
*[http://en.wikipedia.org/wiki/Animation_codec Apple Animation]&lt;br /&gt;
&lt;br /&gt;
*[http://en.wikipedia.org/wiki/DNxHD DNxHD] also supported by [http://code.google.com/p/ffmbc/ ffmbc]&lt;br /&gt;
&lt;br /&gt;
*[http://en.wikipedia.org/wiki/H.264 H.264] - 10-bit YUV 4:2:0/4:2:2/4:4:4 available via x264 (lossy/lossless compression supported).&lt;br /&gt;
&lt;br /&gt;
*[http://en.wikipedia.org/wiki/High_Efficiency_Video_Coding HEVC] - 10-bit YUV 4:2:0/4:2:2/4:4:4 available via x265 (lossy/lossless compression supported).&lt;br /&gt;
&lt;br /&gt;
*[http://en.wikipedia.org/wiki/ProRes ProRes 422]&lt;br /&gt;
&lt;br /&gt;
*[http://www.videohelp.com/tools/Ut-Video-Codec-Suite Ut Video Codec Suite] - YUV 4:2:2 10bit (lossless compression).&lt;br /&gt;
&lt;br /&gt;
*[http://en.wikipedia.org/wiki/VP9 VP9] - support for YUV 4:2:0/4:2:2/4:4:4 10-12bit encoding via [http://en.wikipedia.org/wiki/VP9#Profiles profiles 2 and 3.] &lt;br /&gt;
&lt;br /&gt;
*[http://azfcpug.org/wp-content/uploads/2011/02/Digital%20Video%20Acquisition%20Codecs.pdf Digital Video Acquisition Codecs.pdf] [http://web.archive.org/web/20141021023458/http://azfcpug.org/wp-content/uploads/2011/02/Digital%20Video%20Acquisition%20Codecs.pdf mirror]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Exporting High Bit-depth Video ==&lt;br /&gt;
&lt;br /&gt;
You can encode out of AviSynth to 10bit x264 via&lt;br /&gt;
&lt;br /&gt;
*[http://tmod.nmm-hd.org/x264/ x264-tMod] - A modification to the x264 encoder to enable various enhancements, especially for the use of high-bit depth input.  Supports the AviSynth high bit-depth convention, quality enhancements, bit-depth conversion, filters such as denoising and deinterlacing.&amp;lt;br&amp;gt;10bit x264 command-line example:&amp;lt;br/&amp;gt;&amp;lt;pre&amp;gt;avs2yuv -raw &amp;quot;script.avs&amp;quot; -o - | x264-10bit --demuxer raw --input-depth 10 --input-res 1280x720 --fps 24 --output &amp;quot;out.mp4&amp;quot; -&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*[[Avs2YUV]]&lt;br /&gt;
&lt;br /&gt;
*[[avs2pipemod]]&lt;br /&gt;
&lt;br /&gt;
*[[avs4x264mod]] - This command-line tool will directly convert from a high bit-depth convention Avisynth script to H.264 with x264, including the 10bit profile.  Please check the [http://astrataro.wordpress.com/category/encode/x264/avs4x26x/ blog] for updated versions.&amp;lt;br&amp;gt;Example:&amp;lt;br/&amp;gt;&amp;lt;pre&amp;gt;avs4x264mod.exe --x264-binary “C:\x264_64-abc.exe” -o out.264 in.avs&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Some tutorials on exporting high bit depth image sequences:&lt;br /&gt;
*[http://web.archive.org/web/20130914191039/http://blendervse.wordpress.com/2011/09/16/8bit-video-to-16bit-scene-referred-linear-exrs/ 8-bit video to 16-bit Scene Referred Linear .EXR’s]&lt;br /&gt;
*[http://web.archive.org/web/20131112191047/http://blendervse.wordpress.com/2013/03/23/pipe-to-rgb-quick-how-to/ Pipe To RGB – Quick How To]&lt;br /&gt;
*[http://web.archive.org/web/20131009105710/http://blendervse.wordpress.com/2013/03/12/pipe-to-rgb-avspmod-to-imagemagick/ Pipe To RGB – AvsPmod To ImageMagick]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Playback of High Bit-depth Videos ==&lt;br /&gt;
*Most of the time you will only get to see dithered 8-bit video, as equipment to truly display high bit-depths is not as common at the consumer level in 2014 ([http://4ktvblog.com/10-bit-monitor list of 10-bit monitors]).&lt;br /&gt;
&lt;br /&gt;
*The Blu-ray standard does not support high bit-depth video nor [http://en.wikipedia.org/wiki/XvYCC xvYCC] color space (full-range 8 bit video). On September 2014 it was announced that the up-and-coming [http://en.wikipedia.org/wiki/Blu-ray_Disc#4K_Blu-ray_Disc 4k Blu-ray] standard will support 10-bit video and a greater color gamut by using the [http://en.wikipedia.org/wiki/Rec._2020 Rec. 2020] color space.&lt;br /&gt;
&lt;br /&gt;
*Digital theaters project up to 12-bit video; for more information read the wiki article: [http://en.wikipedia.org/wiki/Digital_Cinema_Initiatives#Image_and_audio_capability_overview Digital Cinema Initiatives]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Playback Software'''&lt;br /&gt;
&lt;br /&gt;
*[http://forum.doom9.org/showthread.php?t=146228 MadVR]&lt;br /&gt;
&lt;br /&gt;
*[http://mpc-hc.org/ MPC-HC]&lt;br /&gt;
&lt;br /&gt;
*[http://forum.doom9.org/showthread.php?t=171120 MPDN]&lt;br /&gt;
&lt;br /&gt;
*[http://www.videolan.org VLC]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Other Software and Information'''&lt;br /&gt;
&lt;br /&gt;
*[http://forum.doom9.org/showthread.php?t=161548 Further information on high-bit playback]&lt;br /&gt;
&lt;br /&gt;
*[http://haruhichan.com/wpblog/?p=205 An excellent guide on 10-bit playback]&lt;br /&gt;
&lt;br /&gt;
*[http://forum.doom9.org/showthread.php?t=161915 FFdshow builds with 10-bit support] (deprecated)&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Sample High Bit-Depth Videos ==&lt;br /&gt;
&lt;br /&gt;
See this thread for links to examples.  There are also deepcolor versions of standard test clips (used in image processing research).  http://forum.doom9.org/showthread.php?t=158836&amp;amp;highlight=v210&lt;br /&gt;
&lt;br /&gt;
todo add: piping RGB48 data from avs2yuv and export 16bit image sequences in either .tif or .exr preferably using ImageMagick: http://www.imagemagick.org/discourse-server/viewtopic.php?f=1&amp;amp;t=18943 or .jp2 image sequences http://www.imagemagick.org/discourse-server/viewtopic.php?f=3&amp;amp;t=24718&lt;br /&gt;
&lt;br /&gt;
[[Category:Advanced topics]]&lt;/div&gt;</summary>
		<author><name>Jmac698</name></author>	</entry>

	<entry>
		<id>http://avisynth.nl/index.php/High_bit-depth_Support_with_Avisynth</id>
		<title>High bit-depth Support with Avisynth</title>
		<link rel="alternate" type="text/html" href="http://avisynth.nl/index.php/High_bit-depth_Support_with_Avisynth"/>
				<updated>2015-11-10T02:32:51Z</updated>
		
		<summary type="html">&lt;p&gt;Jmac698: /* VapourSource */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
Currently, Avisynth only supports 8-bit video.  Nevertheless, through various utilities, plugins, and scripts, Avisynth can be used to import, process, and export high bit-depth video.  There has been some effort to update Avisynth itself to support high bit-depth, but there has been no progress as of 2012 (http://forum.doom9.org/showthread.php?t=162436).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== What is Deep Color? ==&lt;br /&gt;
&lt;br /&gt;
Deepcolor refers to using more than 8 bits of data to represent each color channel.  It is also referred to as high bit-depth color.  Basically, deepcolor/high bit-depth allows finer graduations of color, allowing smoother gradients and more detail.  Please refer to this short, easy to understand article:  [http://www.pcworld.com/article/171223/what_is_10bit_color.html PCWorld: What is 10-bit Color?]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Why Use Deep Color? ==&lt;br /&gt;
&lt;br /&gt;
*Higher internal precision, using high-bit depth color, when processing an image in a filter, gives a higher quality (8-bit) output.&lt;br /&gt;
*If a video filter uses linear gamma internally, there can be noticeable differences in the image.  A linear gamma representation is best supported with a high bit-depth. See the illustration for [http://int64.org/projects/resamplehq/ ResampleHQ].&lt;br /&gt;
*If you encode high-bit depth video, you can get better compression (reportedly up to 30%) and less banding.  &lt;br /&gt;
*Banding is one of the most serious liabilities of 8-bit depth.  Refer to the following references for an explanation of why 10-bit encodes compress better:&lt;br /&gt;
**[http://x264.nl/x264/10bit_02-ateme-why_does_10bit_save_bandwidth.pdf Why does 10-bit save bandwidth (even when content is 8-bit)?.pdf]&lt;br /&gt;
**[http://x264.nl/x264/10bit_01-ateme_pierre_larbier_422_10-bit.pdf Using 10-bit AVC/H.264 Encoding with 4:2:2 for Broadcast Contribution.pdf]&lt;br /&gt;
**[http://x264.nl/x264/10bit_03-422_10_bit_pristine_video_quality.pdf Keeping Video Quality Pristine throughout the Production Process: 4:2:2 10-bit AVC/H.264 encoding.pdf]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Importing High Bit-depth Video into AviSynth ==&lt;br /&gt;
For importing high bit depth video [http://sourceforge.net/projects/avisynth2/ AviSynth 2.6.0] or greater is strongly recommended. AviSynth 2.6 adds the additional [[planar]] color spaces ([[Y8]],[[YV16]],[[YV24]], [[YV411]]) which makes it that much more compatible with all of the existing formats. &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== [[FFmpegSource|FFMS2]] ===&lt;br /&gt;
'''Patched FFMS2''' - import DNxHD, ProRes, and other 10-bit videos in their native format (4:2:2 and 4:4:4 are also supported), output greater than 8-bits will always be in the [[Stack16]] format.&lt;br /&gt;
&lt;br /&gt;
*Source code: [http://github.com/SAPikachu/ffms2_hacks GitHub repository]&lt;br /&gt;
*Discussion: [http://forum.doom9.org/showthread.php?t=164841 Doom9 thread] - Importing DNxHD to Avisynth (some of the links may be outdated; see downloads below or [http://forum.doom9.org/member.php?u=135430 SAPikachu's signature] for latest versions)&lt;br /&gt;
&lt;br /&gt;
==== Download ====&lt;br /&gt;
Updated binaries: March 15, 2015 | [http://www.mediafire.com/folder/2izh9abzep52o/Video_works older versions]&lt;br /&gt;
* &amp;lt;code&amp;gt;[http://www.nmm-hd.org/upload/get~t6gq8DWihBs/ffms2-6e0d654+a9fe004-ffmbc-FFmbc-0.7.1.7z ffms2-6e0d654+a9fe004-ffmbc-FFmbc-0.7.1.7z]&amp;lt;/code&amp;gt; | [http://web.archive.org/web/20150321005059/https://www.nmm-hd.org/upload/get~t6gq8DWihBs/ffms2-6e0d654+a9fe004-ffmbc-FFmbc-0.7.1.7z mirror] - This version uses [http://code.google.com/p/ffmbc/ FFmbc] as a decoder; may have better support for professional video formats like ProRes, DNxHD, etc.&lt;br /&gt;
* &amp;lt;code&amp;gt;[http://www.nmm-hd.org/upload/get~BLsLZwgj5ps/ffms2-6e0d654+a9fe004-ffmpeg-1e4d049.7z ffms2-6e0d654+a9fe004-ffmpeg-1e4d049.7z]&amp;lt;/code&amp;gt; | [http://web.archive.org/web/20150321005255/https://www.nmm-hd.org/upload/get~BLsLZwgj5ps/ffms2-6e0d654+a9fe004-ffmpeg-1e4d049.7z mirror] - This version uses [http://en.wikipedia.org/wiki/FFmpeg FFmpeg] as a decoder; may be better for general (more common) formats.&lt;br /&gt;
* &amp;lt;code&amp;gt;[http://www.nmm-hd.org/upload/get~Q4mZfV9y0Og/ffms2-6e0d654+a9fe004-libav-9a60b1f.7z ffms2-6e0d654+a9fe004-libav-9a60b1f.7z]&amp;lt;/code&amp;gt; | [http://web.archive.org/web/20150321005339/https://www.nmm-hd.org/upload/get~Q4mZfV9y0Og/ffms2-6e0d654+a9fe004-libav-9a60b1f.7z mirror] - This version uses [http://en.wikipedia.org/wiki/Libav Libav] as a decoder; may be better for general (more common) formats.&lt;br /&gt;
These versions work just like the official [[FFmpegSource|FFMS2]], but includes the additional {{FuncDef3|enable10bithack}} parameter and support for the additional [[planar]] colorspaces available is AviSynth 2.6. &amp;lt;br/&amp;gt;By default {{FuncDef3|enable10bithack}} is set to false so it will work just like the official FFMS2; to import high bit depth video set {{FuncDef3|enable10bithack}}&amp;lt;tt&amp;gt;=true&amp;lt;/tt&amp;gt;, output will be in the [[Stack16]] format.&amp;lt;br/&amp;gt;&lt;br /&gt;
See [http://github.com/mpv-player/mpv/wiki/FFmpeg-versus-Libav FFmpeg versus Libav] for information on pros and cons and differences between the FFmpeg and Libav.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;!--===== Archived Downloads =====&lt;br /&gt;
* &amp;lt;code&amp;gt;[http://www.nmm-hd.org/upload/get~PbKYgPe2oKY/ffms2-9417b9c-ffmbc-FFmbc-0.7-rc8.7z ffms2-9417b9c-ffmbc-FFmbc-0.7-rc8.7z]&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;[http://www.nmm-hd.org/upload/get~fmbjO7t9dEg/ffms2-9417b9c-ffmpeg-8728360.7z ffms2-9417b9c-ffmpeg-8728360.7z]&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;[http://www.nmm-hd.org/upload/get~3O9tHZ9TJIM/ffms2-9417b9c-libav-aca2510.7z ffms2-9417b9c-libav-aca2510.7z]&amp;lt;/code&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[LSMASHSource]] ===&lt;br /&gt;
Another source filter to import regular 8-bit and high bit depth video. LSMASHSource includes these 2 fuctions to import video:&lt;br /&gt;
*[[LSMASHSource/LSMASHVideoSource|LSMASHVideoSource]] - This function uses [http://en.wikipedia.org/wiki/Libavcodec#Implemented_video_codecs libavcodec] as a video decoder and [http://github.com/l-smash/l-smash L-SMASH] as a demuxer. Recommended for MP4, MOV, [http://en.wikipedia.org/wiki/ISO_base_media_file_format ISO Base Media] and its derived file formats.&amp;lt;br/&amp;gt;&lt;br /&gt;
*[[LSMASHSource/LWLibavVideoSource|LWLibavVideoSource]] - This function uses [http://en.wikipedia.org/wiki/Libavcodec#Implemented_video_codecs libavcodec] as a video decoder and [http://www.ffmpeg.org/libavformat.html libavformat] as a demuxer.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== [[VapourSource]] ===&lt;br /&gt;
Can be used to import [http://www.vapoursynth.com/ VapourSynth] scripts into AviSynth. Video can be 8-bit or greater.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Image Magick]] ===&lt;br /&gt;
You can also import video or still via 16-bit PNG format pictures with the following Image Magick command lines (examples shown for Windows, requires the 16-bit version of Image Magick found at http://www.imagemagick.org/script/bi...es.php#windows, the file ImageMagick-x.y.z-a-Q16-x64)&lt;br /&gt;
&lt;br /&gt;
Convert 16-bit to stacked (high/low or stack16 format):&lt;br /&gt;
[code]&lt;br /&gt;
convert 16bit.png -depth 16 ( +clone -evaluate and 255 -evaluate multiply 256 ) -append stacked.png&lt;br /&gt;
[/code]&lt;br /&gt;
&lt;br /&gt;
convert stacked (high/low) to 16bit:&lt;br /&gt;
[code]&lt;br /&gt;
convert stacked.png -depth 16 -crop 100%x50% ( +clone -evaluate divide 256 ) -delete 1 -compose Add -composite -define png:bit-depth=16 16bit1.png&lt;br /&gt;
[/code]&lt;br /&gt;
&lt;br /&gt;
For further explanation of these command lines, please see the thread http://forum.doom9.org/showthread.php?t=172846&lt;br /&gt;
&lt;br /&gt;
=== Obsolete === &lt;br /&gt;
'''The following methods are obsolete! If you must, only use as a verification or as workaround:'''&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*[http://forum.doom9.org/showthread.php?p=1526131#post1526131 Readv210mod] - Can read uncompressed v210 in .mov container as color.  Needs a manual setting skip the file header.  &lt;br /&gt;
&lt;br /&gt;
*[http://sites.google.com/site/ourenthusiasmsasham/soft Sashimi] - Sashimi 0.85 has different bit-depth support.  Please see OtherFormats/Read_v210.avs included in the package.&lt;br /&gt;
&lt;br /&gt;
*[http://forum.doom9.org/showthread.php?t=158985 ReadV210] - Can read uncompressed v210 in .mov container as greyscale.  &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alternative builds and methods of importing '''(also obsolete)''':&lt;br /&gt;
&lt;br /&gt;
*[http://forum.doom9.org/showthread.php?p=1528494 ffms2mod] - Can return most 10bit video in the Avisynth high bit-depth convention.&lt;br /&gt;
&lt;br /&gt;
*[http://forum.doom9.org/showthread.php?t=162598&amp;amp;page=2 RawSource with ffmpeg]  - shows an example of using ffmpeg to convert to a 16bit format which can be read by RawSource in Avisynth 2.6.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Processing High Bit-depth Video with AviSynth ==&lt;br /&gt;
&lt;br /&gt;
Some plugins support processing internally in a higher bit-depth for better quality and return an 8-bit video.  Others support full high-bit processing and can retun a special format 16 bit video.&lt;br /&gt;
&lt;br /&gt;
Most developers have adopted a vertically stacked format known as [[Stack16]], where the high bits (MSB) are stored in the upper half of a video, and the lower bits (LSB) in the lower half of the video.&amp;lt;br&amp;gt;&lt;br /&gt;
This special format must be processed only with high-bit aware scripts and plugins.&amp;lt;br&amp;gt;&lt;br /&gt;
* Multipurpose&lt;br /&gt;
**'''[[Dither_tools|Dither]]''' - A set of scripts, original and modified plugins to process 16-bit clips. Some of the functions include 16-bit color space conversion, debanding, denoising, resizing, and dithering 16-bit to lower bit depths.&lt;br /&gt;
**'''[http://github.com/tp7/CLExpr/releases CLExpr]''' - OpenCl plugin for runtime calculation of expressions on 8 and 16-bit depths clips. Makes mt_lutxy and mt_lutxyz possible on 16-bit. More information [http://forum.doom9.org/showpost.php?p=1672638 here].&lt;br /&gt;
**'''[http://forum.doom9.org/showthread.php?t=154971 SmoothAdjust]''' - High quality YUV color adjustment plugin. SmoothAdjust can input and output 16-bits; all calculations are internally done in 32-bit float to avoid rounding errors and artifacts.&lt;br /&gt;
&lt;br /&gt;
* Antialiasing&lt;br /&gt;
**'''[[Xaa]]''' - anti-aliasing and resizing script.&lt;br /&gt;
&lt;br /&gt;
* Debanding&lt;br /&gt;
**'''[http://forum.doom9.org/showthread.php?t=161411 flash3kyuu_deband]''' - Debanding filter with 8/16 bit input/output. In addition flash3kyuu_deband can be used to dither 16-bit to lower bit depths. &lt;br /&gt;
&lt;br /&gt;
* Degraining&lt;br /&gt;
**'''[[SMDegrain]]''' - mvtools+mdegrain denoising with 16-bit input and output.&lt;br /&gt;
&lt;br /&gt;
* Denoising&lt;br /&gt;
**'''[http://forum.doom9.org/showthread.php?t=162342 DenoiseMD]''' - 8/16-bit denoise.&lt;br /&gt;
**'''[[Dfttest]]''' - 8/16-bit 2D/3D frequency domain denoiser.&lt;br /&gt;
**'''[http://forum.doom9.org/showthread.php?t=171379 KNLMeansCL]''' - OpenCL based Non Local Means denoising with support for 16-bit input and output.&lt;br /&gt;
**'''[http://forum.doom9.org/showthread.php?t=163018 RedAverage]''' - 16-bit capable average with masking. Download latest version [http://chaosking.de/wp-content/uploads/avsfilters/Unclassified/RedAverage___(1.4.3_-_2011-12-02).7z here]&lt;br /&gt;
**'''[http://forum.videohelp.com/threads/369142-Simple-MDegrain-Mod-v2-2d-A-Quality-Denoising-Solution SMDegrainMod]''' - 8/16 bit denoising with additional features like sharpening. [http://web.archive.org/web/20131210170708/http://doom10.org/index.php?topic=2178.0 Original Doom10 archived page.]&lt;br /&gt;
**'''[http://forum.doom9.org/showthread.php?t=167032 TempLinearApproximate]''' - 8/16 bit filter for temporal linear approximation between pixels . Meant mainly for denoising aid in motion compensated clips.&lt;br /&gt;
&lt;br /&gt;
* Deringing&lt;br /&gt;
**[[HQDering_mod|'''HQDeringMod''']] - Deringing script with 16-bit input and output.&lt;br /&gt;
&lt;br /&gt;
* Effects&lt;br /&gt;
**'''[[f3kgrain]]''' - Luma adaptive grain generator with 8/16-bit input and output.&lt;br /&gt;
&lt;br /&gt;
* Frame Averaging&lt;br /&gt;
**'''[http://forum.doom9.org/showpost.php?p=1579509 AvgAll_16]''' - Average all frames in a clip with 16-bit accuracy.&lt;br /&gt;
**'''[http://forum.doom9.org/showthread.php?t=168048 ClipBlend16]''' - Blend an specified amount of frames into a single frame with 16-bit accuracy. &lt;br /&gt;
	&lt;br /&gt;
* Resizing&lt;br /&gt;
**'''[[Debicubic]]''' - This filter is designed to reverse the effects of bicubic upsampling. 8/16-bit input and output.&lt;br /&gt;
**'''[[Debilinear]]''' - This filter is designed to reverse the effects of bilinear upsampling. 8/16-bit input and output.    &lt;br /&gt;
**'''[[nnedi3_resize16]]''' - An advanced script for high quality image resizing and colorspace conversion. It supports 16-bit input and output.&lt;br /&gt;
**'''[http://svn.int64.org/viewvc/int64/resamplehq/doc/index.html ResampleHQ]''' - Provides gamma-aware resizing and color space conversion.  Uses 32-bit linear color internally but input and output is limited to 8-bit.&lt;br /&gt;
**'''[http://forum.videohelp.com/threads/369143-ResizersPack-MasksPack-PlaygroundPack-SmoothContrast-Logo-mod-functions?p=2364056 Resizers Functions Pack]''' - Includes LinearResize(), a function to resize in linear space. 8/16-bit input/output. [http://web.archive.org/web/20141105135234/http://doom10.org/index.php?topic=2182.0 Original Doom10 archived page.]&lt;br /&gt;
&lt;br /&gt;
* Deprecated&lt;br /&gt;
**'''[http://forum.doom9.org/showthread.php?p=1467907#post1467907 Deep Color Tools]''' - This Script provides basic functions to import 10bit video, do color adjustments, and export to 8bit. (NOT RECOMMENDED, THERE ARE BETTER ALTERNATIVES)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You can also check the [[External_filters#Deepcolor_Filters|External Filters: DeepColor]] section, and the [[:Category:Deep_color_tools|Deep Color Tools]] category for possibly more listings.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Codecs which support high bit-depth ==&lt;br /&gt;
&lt;br /&gt;
*[http://en.wikipedia.org/wiki/Animation_codec Apple Animation]&lt;br /&gt;
&lt;br /&gt;
*[http://en.wikipedia.org/wiki/DNxHD DNxHD] also supported by [http://code.google.com/p/ffmbc/ ffmbc]&lt;br /&gt;
&lt;br /&gt;
*[http://en.wikipedia.org/wiki/H.264 H.264] - 10-bit YUV 4:2:0/4:2:2/4:4:4 available via x264 (lossy/lossless compression supported).&lt;br /&gt;
&lt;br /&gt;
*[http://en.wikipedia.org/wiki/High_Efficiency_Video_Coding HEVC] - 10-bit YUV 4:2:0/4:2:2/4:4:4 available via x265 (lossy/lossless compression supported).&lt;br /&gt;
&lt;br /&gt;
*[http://en.wikipedia.org/wiki/ProRes ProRes 422]&lt;br /&gt;
&lt;br /&gt;
*[http://www.videohelp.com/tools/Ut-Video-Codec-Suite Ut Video Codec Suite] - YUV 4:2:2 10bit (lossless compression).&lt;br /&gt;
&lt;br /&gt;
*[http://en.wikipedia.org/wiki/VP9 VP9] - support for YUV 4:2:0/4:2:2/4:4:4 10-12bit encoding via [http://en.wikipedia.org/wiki/VP9#Profiles profiles 2 and 3.] &lt;br /&gt;
&lt;br /&gt;
*[http://azfcpug.org/wp-content/uploads/2011/02/Digital%20Video%20Acquisition%20Codecs.pdf Digital Video Acquisition Codecs.pdf] [http://web.archive.org/web/20141021023458/http://azfcpug.org/wp-content/uploads/2011/02/Digital%20Video%20Acquisition%20Codecs.pdf mirror]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Exporting High Bit-depth Video ==&lt;br /&gt;
&lt;br /&gt;
You can encode out of AviSynth to 10bit x264 via&lt;br /&gt;
&lt;br /&gt;
*[http://tmod.nmm-hd.org/x264/ x264-tMod] - A modification to the x264 encoder to enable various enhancements, especially for the use of high-bit depth input.  Supports the AviSynth high bit-depth convention, quality enhancements, bit-depth conversion, filters such as denoising and deinterlacing.&amp;lt;br&amp;gt;10bit x264 command-line example:&amp;lt;br/&amp;gt;&amp;lt;pre&amp;gt;avs2yuv -raw &amp;quot;script.avs&amp;quot; -o - | x264-10bit --demuxer raw --input-depth 10 --input-res 1280x720 --fps 24 --output &amp;quot;out.mp4&amp;quot; -&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*[[Avs2YUV]]&lt;br /&gt;
&lt;br /&gt;
*[[avs2pipemod]]&lt;br /&gt;
&lt;br /&gt;
*[[avs4x264mod]] - This command-line tool will directly convert from a high bit-depth convention Avisynth script to H.264 with x264, including the 10bit profile.  Please check the [http://astrataro.wordpress.com/category/encode/x264/avs4x26x/ blog] for updated versions.&amp;lt;br&amp;gt;Example:&amp;lt;br/&amp;gt;&amp;lt;pre&amp;gt;avs4x264mod.exe --x264-binary “C:\x264_64-abc.exe” -o out.264 in.avs&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Some tutorials on exporting high bit depth image sequences:&lt;br /&gt;
*[http://web.archive.org/web/20130914191039/http://blendervse.wordpress.com/2011/09/16/8bit-video-to-16bit-scene-referred-linear-exrs/ 8-bit video to 16-bit Scene Referred Linear .EXR’s]&lt;br /&gt;
*[http://web.archive.org/web/20131112191047/http://blendervse.wordpress.com/2013/03/23/pipe-to-rgb-quick-how-to/ Pipe To RGB – Quick How To]&lt;br /&gt;
*[http://web.archive.org/web/20131009105710/http://blendervse.wordpress.com/2013/03/12/pipe-to-rgb-avspmod-to-imagemagick/ Pipe To RGB – AvsPmod To ImageMagick]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Playback of High Bit-depth Videos ==&lt;br /&gt;
*Most of the time you will only get to see dithered 8-bit video, as equipment to truly display high bit-depths is not as common at the consumer level in 2014 ([http://4ktvblog.com/10-bit-monitor list of 10-bit monitors]).&lt;br /&gt;
&lt;br /&gt;
*The Blu-ray standard does not support high bit-depth video nor [http://en.wikipedia.org/wiki/XvYCC xvYCC] color space (full-range 8 bit video). On September 2014 it was announced that the up-and-coming [http://en.wikipedia.org/wiki/Blu-ray_Disc#4K_Blu-ray_Disc 4k Blu-ray] standard will support 10-bit video and a greater color gamut by using the [http://en.wikipedia.org/wiki/Rec._2020 Rec. 2020] color space.&lt;br /&gt;
&lt;br /&gt;
*Digital theaters project up to 12-bit video; for more information read the wiki article: [http://en.wikipedia.org/wiki/Digital_Cinema_Initiatives#Image_and_audio_capability_overview Digital Cinema Initiatives]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Playback Software'''&lt;br /&gt;
&lt;br /&gt;
*[http://forum.doom9.org/showthread.php?t=146228 MadVR]&lt;br /&gt;
&lt;br /&gt;
*[http://mpc-hc.org/ MPC-HC]&lt;br /&gt;
&lt;br /&gt;
*[http://forum.doom9.org/showthread.php?t=171120 MPDN]&lt;br /&gt;
&lt;br /&gt;
*[http://www.videolan.org VLC]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Other Software and Information'''&lt;br /&gt;
&lt;br /&gt;
*[http://forum.doom9.org/showthread.php?t=161548 Further information on high-bit playback]&lt;br /&gt;
&lt;br /&gt;
*[http://haruhichan.com/wpblog/?p=205 An excellent guide on 10-bit playback]&lt;br /&gt;
&lt;br /&gt;
*[http://forum.doom9.org/showthread.php?t=161915 FFdshow builds with 10-bit support] (deprecated)&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Sample High Bit-Depth Videos ==&lt;br /&gt;
&lt;br /&gt;
See this thread for links to examples.  There are also deepcolor versions of standard test clips (used in image processing research).  http://forum.doom9.org/showthread.php?t=158836&amp;amp;highlight=v210&lt;br /&gt;
&lt;br /&gt;
todo add: piping RGB48 data from avs2yuv and export 16bit image sequences in either .tif or .exr preferably using ImageMagick: http://www.imagemagick.org/discourse-server/viewtopic.php?f=1&amp;amp;t=18943 or .jp2 image sequences http://www.imagemagick.org/discourse-server/viewtopic.php?f=3&amp;amp;t=24718&lt;br /&gt;
&lt;br /&gt;
[[Category:Advanced topics]]&lt;/div&gt;</summary>
		<author><name>Jmac698</name></author>	</entry>

	</feed>