jmac698
9th November 2011, 21:38
Hi all,
Many have suggested to me that the things I'm trying to accomplish in script would be easier as a plugin. I agree. What remains for me to be productive is only that I can learn to make a plugin. I've tried to do so, the result is my article,
http://avisynthnew.wikinet.org/wiki/Avisynth_Plugin_Development_in_C#Passing_Parameters_to_your_Plugin
I was not able to complete the article, as the steps included will not work. A lot of the errors came up when I changed the file extension to .C, which seemed to indicate to my IDE to engage pure C mode, which then lead to a number of errors. I was able to fix some of these.
Edit: the code below compiles, but I doubt it's correct. Suggestions?
// Merge plugin, written by jmac698, modified from Demosaic plugin
//
// Originally written by Written by Balazs OROSZI
// Copyleft 2007.11.
//
// You may use this plugin however you wish,
// and distribute it under the terms of the GNU GPL
//
// Plugin parameters:
// ------------------
// Merge(clip clip1, clip clip2, int weight)
//
// clip clip: input clip, can be YUY2, YV12 or Y8
// weight to merge clip1*weight+(1-weight)*clip2
//
// output: YUV color image
#include "avisynth_c.h"
#include <stdlib.h>
#include <string.h>
// ---------- avisynth_c interface extension - begin ----------
// The following is missing from avisynth_c interface version 0.20 and is needed by this plugin.
// It can safely be removed, as soon as it is implemented.
enum {
AVS_CS_Y8 = 1<<8 | AVS_CS_YUV | AVS_CS_PLANAR, // Y 4:0:0 planar
};
AVSC_INLINE int avs_is_y8(const AVS_VideoInfo * p)
{ return (p->pixel_type & AVS_CS_Y8) == AVS_CS_Y8; }
// ---------- avisynth_c interface extension - end ----------
typedef struct Parms
{
AVS_Clip* clip1;
AVS_Clip* clip2;
int weight;
} Parms;
AVS_VideoFrame* AVSC_CC get_frame(AVS_FilterInfo* fi, int n)
{
// parameters
// don't know what the old line was for
// destination
AVS_VideoFrame* dest_frame;
BYTE* dest_data;
unsigned int dest_pitch, dest_height;
dest_frame = avs_new_video_frame(fi->env, &fi->vi);
dest_data = avs_get_write_ptr(dest_frame);
dest_pitch = avs_get_pitch(dest_frame);
dest_height = avs_get_height(dest_frame);
// source
AVS_VideoFrame* src_frame = avs_get_frame(fi->child, n);
const BYTE* src_data;
unsigned int src_pitch;
unsigned int src_row_size; // in bytes!
unsigned int src_height;
unsigned int src_inc; // next pixel in row
// YV12
if (avs_is_yv12(avs_get_video_info(fi->child))) { // Important: fi->child!
src_data = avs_get_read_ptr_p(src_frame, AVS_PLANAR_Y);
src_pitch = avs_get_pitch_p(src_frame, AVS_PLANAR_Y);
src_row_size = avs_get_row_size_p(src_frame, AVS_PLANAR_Y); // in bytes!
src_height = avs_get_height_p(src_frame, AVS_PLANAR_Y);
src_inc = 1;
}
// YUY2
else if (avs_is_yuy2(avs_get_video_info(fi->child))) {
src_data = avs_get_read_ptr(src_frame);
src_pitch = avs_get_pitch(src_frame);
src_row_size = avs_get_row_size(src_frame); // in bytes!
src_height = avs_get_height(src_frame);
src_inc = 2;
}
// Y8
else if (avs_is_y8(avs_get_video_info(fi->child))) {
src_data = avs_get_read_ptr(src_frame);
src_pitch = avs_get_pitch(src_frame);
src_row_size = avs_get_row_size(src_frame); // in bytes!
src_height = avs_get_height(src_frame);
src_inc = 1;
}
// somethings very wrong
else {
avs_release_frame(src_frame); // only when writing to new clip
return dest_frame;
}
// RGB is upside down
dest_data += (dest_height - 1) * dest_pitch;
src_data += 2 * src_pitch;
unsigned int y;
unsigned int sx;
unsigned int dx;
for (y = 2; y < src_height; y += 2) {
for (sx = 2 * src_inc, dx = 0; sx < src_row_size; sx += 2 * src_inc, dx += 2 * 4) {
// c<row><col>
const unsigned int c11 = (src_data - 2 * src_pitch)[sx - 2 * src_inc];
const unsigned int c12 = (src_data - 2 * src_pitch)[sx - 1 * src_inc];
const unsigned int c13 = (src_data - 2 * src_pitch)[sx - 0 * src_inc];
const unsigned int c21 = (src_data - 1 * src_pitch)[sx - 2 * src_inc];
const unsigned int c22 = (src_data - 1 * src_pitch)[sx - 1 * src_inc];
const unsigned int c23 = (src_data - 1 * src_pitch)[sx - 0 * src_inc];
const unsigned int c31 = (src_data - 0 * src_pitch)[sx - 2 * src_inc];
const unsigned int c32 = (src_data - 0 * src_pitch)[sx - 1 * src_inc];
const unsigned int c33 = (src_data - 0 * src_pitch)[sx - 0 * src_inc];
dest_data[dx + 0] = c21; // B
dest_data[dx + 1] = (c22 + c11) / 2; // G
dest_data[dx + 2] = c12; // R
dest_data[dx + 4 + 0] = c23; // B
dest_data[dx + 4 + 1] = (c22 + c13) / 2; // G
dest_data[dx + 4 + 2] = c12; // R
(dest_data - dest_pitch)[dx + 0] = c21; // B
(dest_data - dest_pitch)[dx + 1] = (c22 + c31) / 2; // G
(dest_data - dest_pitch)[dx + 2] = c32; // R
(dest_data - dest_pitch)[dx + 4 + 0] = c23; // B
(dest_data - dest_pitch)[dx + 4 + 1] = (c22 + c33) / 2; // G
(dest_data - dest_pitch)[dx + 4 + 2] = c32; // R
}
src_data += 2 * src_pitch;
dest_data -= 2 * dest_pitch;
}
avs_release_frame(src_frame); // only when writing to new clip
return dest_frame;
}
void AVSC_CC free_filter(AVS_FilterInfo* fi)
{
Parms *params = (Parms *)malloc(sizeof(Parms));
free(params);
}
AVS_Value AVSC_CC create_filter(AVS_ScriptEnvironment* env, AVS_Value args, void* param)
{
AVS_Value retval;
AVS_FilterInfo* fi;
AVS_Clip* new_clip = avs_new_c_filter(env, &fi, avs_array_elt(args, 0), 1);
// Instance data
//Demosaic* params = new Demosaic();
Parms *params = (Parms *)malloc(sizeof(Parms));
// Parameters
//Parms params;
int pnum = 0;
++pnum; params->clip2 = avs_defined(avs_array_elt(args, pnum)) ? avs_take_clip(avs_array_elt(args, pnum), env) : 0;
++pnum; params->weight = avs_defined(avs_array_elt(args, pnum)) ?
avs_as_int(avs_array_elt(args, pnum)) : 1; // Default value for weight here
// Check params
retval = avs_void;
if (!avs_defined(retval) && !avs_is_yuy2(&fi->vi)) {
retval = avs_new_value_error("Input video format can be: YUY2");
}
if (!avs_defined(retval) && !avs_is_int(avs_array_elt(args, 2))) {
retval = avs_new_value_error("weight must be an int");
}
// If no errors, all is fine, return clip value
if (!avs_defined(retval)) {
retval = avs_new_value_clip(new_clip);
}
// Set up FilterInfo
fi->user_data = (void*) params;
fi->get_frame = get_frame;
// Set up VideoInfo
fi->vi.pixel_type = AVS_CS_BGR32;
avs_release_clip(new_clip);
return retval;
}
const char* AVSC_CC avisynth_c_plugin_init(AVS_ScriptEnvironment* env)
{
avs_add_function(env, "Merge", "cc[weight]i", create_filter, 0);
return "Merge plugin";
}
Many have suggested to me that the things I'm trying to accomplish in script would be easier as a plugin. I agree. What remains for me to be productive is only that I can learn to make a plugin. I've tried to do so, the result is my article,
http://avisynthnew.wikinet.org/wiki/Avisynth_Plugin_Development_in_C#Passing_Parameters_to_your_Plugin
I was not able to complete the article, as the steps included will not work. A lot of the errors came up when I changed the file extension to .C, which seemed to indicate to my IDE to engage pure C mode, which then lead to a number of errors. I was able to fix some of these.
Edit: the code below compiles, but I doubt it's correct. Suggestions?
// Merge plugin, written by jmac698, modified from Demosaic plugin
//
// Originally written by Written by Balazs OROSZI
// Copyleft 2007.11.
//
// You may use this plugin however you wish,
// and distribute it under the terms of the GNU GPL
//
// Plugin parameters:
// ------------------
// Merge(clip clip1, clip clip2, int weight)
//
// clip clip: input clip, can be YUY2, YV12 or Y8
// weight to merge clip1*weight+(1-weight)*clip2
//
// output: YUV color image
#include "avisynth_c.h"
#include <stdlib.h>
#include <string.h>
// ---------- avisynth_c interface extension - begin ----------
// The following is missing from avisynth_c interface version 0.20 and is needed by this plugin.
// It can safely be removed, as soon as it is implemented.
enum {
AVS_CS_Y8 = 1<<8 | AVS_CS_YUV | AVS_CS_PLANAR, // Y 4:0:0 planar
};
AVSC_INLINE int avs_is_y8(const AVS_VideoInfo * p)
{ return (p->pixel_type & AVS_CS_Y8) == AVS_CS_Y8; }
// ---------- avisynth_c interface extension - end ----------
typedef struct Parms
{
AVS_Clip* clip1;
AVS_Clip* clip2;
int weight;
} Parms;
AVS_VideoFrame* AVSC_CC get_frame(AVS_FilterInfo* fi, int n)
{
// parameters
// don't know what the old line was for
// destination
AVS_VideoFrame* dest_frame;
BYTE* dest_data;
unsigned int dest_pitch, dest_height;
dest_frame = avs_new_video_frame(fi->env, &fi->vi);
dest_data = avs_get_write_ptr(dest_frame);
dest_pitch = avs_get_pitch(dest_frame);
dest_height = avs_get_height(dest_frame);
// source
AVS_VideoFrame* src_frame = avs_get_frame(fi->child, n);
const BYTE* src_data;
unsigned int src_pitch;
unsigned int src_row_size; // in bytes!
unsigned int src_height;
unsigned int src_inc; // next pixel in row
// YV12
if (avs_is_yv12(avs_get_video_info(fi->child))) { // Important: fi->child!
src_data = avs_get_read_ptr_p(src_frame, AVS_PLANAR_Y);
src_pitch = avs_get_pitch_p(src_frame, AVS_PLANAR_Y);
src_row_size = avs_get_row_size_p(src_frame, AVS_PLANAR_Y); // in bytes!
src_height = avs_get_height_p(src_frame, AVS_PLANAR_Y);
src_inc = 1;
}
// YUY2
else if (avs_is_yuy2(avs_get_video_info(fi->child))) {
src_data = avs_get_read_ptr(src_frame);
src_pitch = avs_get_pitch(src_frame);
src_row_size = avs_get_row_size(src_frame); // in bytes!
src_height = avs_get_height(src_frame);
src_inc = 2;
}
// Y8
else if (avs_is_y8(avs_get_video_info(fi->child))) {
src_data = avs_get_read_ptr(src_frame);
src_pitch = avs_get_pitch(src_frame);
src_row_size = avs_get_row_size(src_frame); // in bytes!
src_height = avs_get_height(src_frame);
src_inc = 1;
}
// somethings very wrong
else {
avs_release_frame(src_frame); // only when writing to new clip
return dest_frame;
}
// RGB is upside down
dest_data += (dest_height - 1) * dest_pitch;
src_data += 2 * src_pitch;
unsigned int y;
unsigned int sx;
unsigned int dx;
for (y = 2; y < src_height; y += 2) {
for (sx = 2 * src_inc, dx = 0; sx < src_row_size; sx += 2 * src_inc, dx += 2 * 4) {
// c<row><col>
const unsigned int c11 = (src_data - 2 * src_pitch)[sx - 2 * src_inc];
const unsigned int c12 = (src_data - 2 * src_pitch)[sx - 1 * src_inc];
const unsigned int c13 = (src_data - 2 * src_pitch)[sx - 0 * src_inc];
const unsigned int c21 = (src_data - 1 * src_pitch)[sx - 2 * src_inc];
const unsigned int c22 = (src_data - 1 * src_pitch)[sx - 1 * src_inc];
const unsigned int c23 = (src_data - 1 * src_pitch)[sx - 0 * src_inc];
const unsigned int c31 = (src_data - 0 * src_pitch)[sx - 2 * src_inc];
const unsigned int c32 = (src_data - 0 * src_pitch)[sx - 1 * src_inc];
const unsigned int c33 = (src_data - 0 * src_pitch)[sx - 0 * src_inc];
dest_data[dx + 0] = c21; // B
dest_data[dx + 1] = (c22 + c11) / 2; // G
dest_data[dx + 2] = c12; // R
dest_data[dx + 4 + 0] = c23; // B
dest_data[dx + 4 + 1] = (c22 + c13) / 2; // G
dest_data[dx + 4 + 2] = c12; // R
(dest_data - dest_pitch)[dx + 0] = c21; // B
(dest_data - dest_pitch)[dx + 1] = (c22 + c31) / 2; // G
(dest_data - dest_pitch)[dx + 2] = c32; // R
(dest_data - dest_pitch)[dx + 4 + 0] = c23; // B
(dest_data - dest_pitch)[dx + 4 + 1] = (c22 + c33) / 2; // G
(dest_data - dest_pitch)[dx + 4 + 2] = c32; // R
}
src_data += 2 * src_pitch;
dest_data -= 2 * dest_pitch;
}
avs_release_frame(src_frame); // only when writing to new clip
return dest_frame;
}
void AVSC_CC free_filter(AVS_FilterInfo* fi)
{
Parms *params = (Parms *)malloc(sizeof(Parms));
free(params);
}
AVS_Value AVSC_CC create_filter(AVS_ScriptEnvironment* env, AVS_Value args, void* param)
{
AVS_Value retval;
AVS_FilterInfo* fi;
AVS_Clip* new_clip = avs_new_c_filter(env, &fi, avs_array_elt(args, 0), 1);
// Instance data
//Demosaic* params = new Demosaic();
Parms *params = (Parms *)malloc(sizeof(Parms));
// Parameters
//Parms params;
int pnum = 0;
++pnum; params->clip2 = avs_defined(avs_array_elt(args, pnum)) ? avs_take_clip(avs_array_elt(args, pnum), env) : 0;
++pnum; params->weight = avs_defined(avs_array_elt(args, pnum)) ?
avs_as_int(avs_array_elt(args, pnum)) : 1; // Default value for weight here
// Check params
retval = avs_void;
if (!avs_defined(retval) && !avs_is_yuy2(&fi->vi)) {
retval = avs_new_value_error("Input video format can be: YUY2");
}
if (!avs_defined(retval) && !avs_is_int(avs_array_elt(args, 2))) {
retval = avs_new_value_error("weight must be an int");
}
// If no errors, all is fine, return clip value
if (!avs_defined(retval)) {
retval = avs_new_value_clip(new_clip);
}
// Set up FilterInfo
fi->user_data = (void*) params;
fi->get_frame = get_frame;
// Set up VideoInfo
fi->vi.pixel_type = AVS_CS_BGR32;
avs_release_clip(new_clip);
return retval;
}
const char* AVSC_CC avisynth_c_plugin_init(AVS_ScriptEnvironment* env)
{
avs_add_function(env, "Merge", "cc[weight]i", create_filter, 0);
return "Merge plugin";
}