Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion.

Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules.

 

Go Back   Doom9's Forum > Capturing and Editing Video > Avisynth Development

Reply
 
Thread Tools Search this Thread Display Modes
Old 13th November 2011, 22:08   #1  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,984
Avisynth CPP Interface for C Programmers. - 31 Mar 2015

v0.3 - 30 Jan 2012
Added 'bool "show"' [default true]. Shows text on-screen.
Added Bouncing walls demo when 'int bounce' non zero.
int "bounce", default -1, 0 == Off, -1 == Auto, <= -2 == Variable, 1 -> 64 == Fixed bounce step size (limited to max 64).
v0.5, 31 March 2015. Added Compiler.h. Added v2.6 dll. Added Avsynth Version 6 Header for v2.6 dll.
Slight mods and fixes. Compiled dll's via VS 2008 Express.


There Follows five pages of what will I hope become a useful guide for C programmers on the intricacies
of the Avisynth C Plus Plus interface. It is not intended to be any kind of course in programming in either
C or C++, just a crash (and burn) course for C programmers.

I will undoubtably have made many mistakes, & it is for you fellows to gratuitously point them out
as cruelly as you can, but that's OK, as I am after all, a HeartlessS Userer.


Page 1, The Intro:-

Page 2, The Class Definition:-

Page 3, Class Member Functions Part_1:-

Page 4, Class Member Functions Part_2:-

Page 5, Avisynth registration and Filter Creation:-

-----------------------------------------------

Page 1, The Intro:-

Code:
/*
  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/

/*
  Example() Plugin for Avisynth v2.5 & v2.6

  Compiling for both Avisynth v2.58 & v2.6 Example under VS6, where Example is the base name of the plugin.
   Create an additional project Example26 and copy the
   project files into Example folder. Add headers and source files to v2.6 project.
   You should have "avisynth25.h" in the Example Header Files and
   "avisynth26.h" in the Example26 Header Files.
   For the v2.58 project, add preprocessor definition to :-
   Menu/Project/Settings/All Configuration/C/C++, AVISYNTH_PLUGIN_25
*/

/*

  http://forum.doom9.org/showthread.php?p=1538557#post1538557

  v0.0 - 10 Nov 2011, StainlessS. Feel free to correct and update.
  v0.1 - 13 Nov 2011, Fixed Aborting message.
  v0.2 - 19 Nov 2011, InfoF.h moved to active Example() source.
    Formatted print member fn DrawFStr() added with FULL string & screen/layout formatting.
    (the above function implemented for the first time for this Example() but the
    demo-ing screen/layout output string was partially robbed from DDigitTest() plugin).
  v0.3 - 30 Jan 2012
    Added 'bool "show"' [default true]. Shows text on-screen.
    Added Bouncing walls demo when 'int bounce' non zero.
    int "bounce", default -1, 0 == Off, -1 == Auto, <= -2 == Variable, 1 -> 64 == Fixed bounce step size (limited to max 64).
  v0.5, 31 March 2015. Added Compiler.h. Added v2.6 dll. Added Avsynth Version 6 Header for v2.6 dll.
    Slight mods and fixes. Compiled dll's via VS 2008 Express.

  This is not intended to give any kind of detailed information on the C++
  language, for that, it would take considerable time to both write and read,
  there are many tombs that are quite competent in that field already.
  Intention here, is to give simple explanation as to what all of the fluffy CPP stuff
  does in a filter class declaration and the Avisynth filter registration and
  creation code. Intended for those that speak C but for whom CPP is a mystery.
  This is to the best of my understanding, what it means / how it works but
  should perhaps not be taken as absolute gospel. I'm just a beginner too, it
  is based on memories of about a decade and a half ago (then a beginner also).
  It is not a very useful nor exciting plugin, you may not even bother to compile
  it (I wouldn't), just take what info you may find in it and jump in and have a
  go yourself. The example plugin is made deliberately boring & non functional
  so as not to obscure the supposed information content.
  This text is not intended to show how to manipulate frames in any way,
  it is only to try to clarify the fluff, for frame manipulation see the
  SimpleSample sources. (v0.3, added bouncing walls demo to GetFrame() so it is not
  quite as boring as it was).
   In addition to the fluff, I thought it might be worthwhile to also show how
  textual information may be displayed on-screen either on the video frame
  or in a DebugView window (Google). Both of these output methods could be of
  use in getting to grips with plug development, and in v0.2, I have added a header
  which allows screen/layout formatted print to a video frame and added a member function to
  use the InfoF.h for fully formatted print (string & screen/layout).
  If InfoF.h header is not supplied with this file, it can be obtained from the
  DDigitTest() plugin which supplies source for "DDigit text renderer for Plugin
  writers" (as can Info.h), see here:-

  http://forum.doom9.org/showthread.php?t=156888

  Dont get too caught up in the fluffy stuff, if it is not explained, then just
  copy what you see, you can look into the un-explained fragments in other sources,
  in some cases, you may not find those parts being used at all by anybody.

  usage: Example(clip,intarg=42,version=true,show=true,bounce=-1) # defaults given.


# -------------------------------------------------------
# Test AVS file.
ColorBars()
#ConvertToYV12()
#ConvertToYUY2()
#ConvertToRGB32()
#ConvertToRGB24()
#ConvertToY8()

Example()                                             # Default Example(intarg=42,version=true,show=true,bounce=-1)
#Example(intarg=27,version=false,show=true,bounce=32) # Fixed bounce at 32
#Example(intarg=76,version=true,show=true,bounce=-1)  # Fixed bounce Auto assigned
#Example(intarg=33,version=false,show=true,bounce=-2) # Variable bounce
#Example(intarg=64,version=true,show=true,bounce=0)   # Bounce Off
#Example(version=false,show=false,bounce=-1)          # Bounce Auto, text OFF

#ConvertToRGB32()                                     # If Y8
#
# This should work with Text Off in v2.6, or should work with Text On if compiled for v2.6.
#ConvertToYV24().Example(version=false,show=false,bounce=-1).ConvertToRGB32()
return last
# -------------------------------------------------------


  The filter class definition will follow shortly near the beginning of this file,
  whereas the code that registers the filter with Avisynth and to create an instance
  of the filter class is at the end of this file (usual practice in most sources).


  You may also like to see the "AviSynth 2.5/FilterSDK/BensAviSynthDocs.htm" file
  installed with 2.58/2.6 when Filter SDK is selected during install, or can find it
  online here:-

  http://www.neuron2.net/www.math.berkeley.edu/benrg/avisynth-extensions.html

  DebugView from SysInternals (Microsoft) can be found here:
  http://technet.microsoft.com/en-gb/sysinternals/bb545027

  To filter out the rubbish in DebugView, set the filter to 'Example:'.
*/


A Zip of the entire file, Example.dll and Example26.dll can be downloaded here:-
(the zip may be slightly out of date because of amendments due to suggestions posted here).

v0.5 - 31 Mar 2015 - See MediaFire in sig below, DEVELOPER FOLDER
Supplied with project files for VS 2008 Express for simple build.

EDIT: Small (29 page) intro of C++ for C programmers:- (AQuickIntroductiontoCPP.PDF)
See MediaFire in sig below, DEVELOPER FOLDER
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 31st March 2015 at 22:49. Reason: update
StainlessS is online now   Reply With Quote
Old 13th November 2011, 22:09   #2  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,984
Page 2, The Class definition:-

Code:
// ------------------------------------------------------------
// ------------------------------------------------------------
// ------------        And So It Begins      ------------------
// ------------------------------------------------------------
// ------------------------------------------------------------

#define DEMOVERSION   "v0.5 - 31 March 2015"

#include "Compiler.h"   // v0.5, Added. Fix a few problems in eg VS 2008

//  Just any old names here to set name of filter to use in AVS file & source.
//  The below is just for this explanation, you may wish to hard code
//  the names, most people do. A simple search / replace and then
//  removal of the below #define's might be a quick way to knock up
//  your template with hardcoded names.

#define AVISYNTHNAME  "Example" // Name (string) used for the filter in AVS script.
#define INTERNALNAME  ClassNAME // Name used internally for the class, could use same.(without quotes ie Example)


#include <windows.h>
#include <stdio.h>  // OutputDebugString(), Needs DebugView utility, http://technet.microsoft.com/en-gb/sysinternals/bb545027

#ifdef AVISYNTH_PLUGIN_25
  #include "Avisynth25.h"   // Version 3 for Avisynth 2.58
#else
  #include "Avisynth26.h"   // Version 6 for Avisynth 2.60
#endif

#include "Info.h"
// Plugin text rendering header from Avisynth v2.6, (Use Version of 17 April 2011, or later, bugs fixed, OK for v2.5+)
// Provides white only horizontal print at pixel coordinates, no formatting of any kind.
// Obtainable here (look for 'Info.h'):-
//    http://avisynth2.cvs.sourceforge.net/viewvc/avisynth2/avisynth/src/core/

#include "InfoF.h"  // New in v0.2
// A companion to Info.h, provides screen/layout formatted printing via embedded control codes.
// Also provides stubs for character coord printing as well as pixel coordinates.
//   Formatting control codes:-
//   '\n', Newline, positioning cursor 1 line down and at left edge of screen.
//   '\r', Newline Special, moves 1 line down and positions cursor at on-entry X position.
//   '\b', Backspace, obvious, not sure how useful this will be.
//   '\f', Forward Space, again obvious, re-uses formfeed code for this. Again, maybe not so useful.
//   '\t', Tab, @ character positions, every 4 characters.(relative screen LHS).
//
// DDigit() from which this header originates, provides horizontal & vertical print at both pixel
// and character coords, 16 color printing and screen/layout formatting (eg '\n') control codes together
// with color control codes. Control codes, vertical print and colorspace code are all controlled
// via compiler directives and so can be excluded from the binary if not required.
//

#define GETFRAME(g, fp) \
{ \
  int GETFRAMEf; \
  GETFRAMEf = (g); \
  if (GETFRAMEf < 0) GETFRAMEf = 0; \
  if (GETFRAMEf > num_frames_hi - 1) GETFRAMEf = num_frames_hi - 1; \
  (fp) = child->GetFrame(GETFRAMEf, env); \
}
// A pretty standard macro used in plugins, gets frame n with valid range check.


// ------------------------------

/****************************
 * The following are the header declarations/definitions
 * For larger projects, move this into a .h file
 * that can be included.
 ****************************/

// The Class definition.
// Really, this is just a structure  for a class together with declared variables and
// function prototypes of member functions belonging to the class.
// Class member functions being called on an instance of a class can call member functions of the same class
// without any extended specifiers.
// Class member functions being called on an instance of a class can access the class variables belonging to the very same
// instance of the class without any extended specifiers. For the most part, (without special specifiers), the class
// variables can be considered as local variables, local to a particular instance of a class (filter).
//
// A Class can inherit properties (variables) and member functions from another class and those properties can
// be added to and the member functions extended by the inheriting class, ie the inheriting class could do something
// a little bit different to what the inherited class does but using the exact same function names and calling
// conventions.
// 
// Here for the class, it is termed a definition rather than declaration, for even though storage is not allocated,
// the class is fully defined (if member functions are only declared ie fn prototypes, they are function pointers,
// and if fully defined, they are 'inlined').
// I guess therefore that all the contents of a class definition are also definitions rather than declarations.

//
// THIS IS THE BEGINNING OF THE CLASS STRUCTURE definition.
class INTERNALNAME : public GenericVideoFilter {   
  // INTERNALNAME defines the name of the filter class, this name is only used internally in the source, and does not affect
  // the name of your filter in scripts, it is however, usual for the internal and external names to be the same.
  //
  // The GenericVideoFilter, is a filter which incorporates basic functionality, our filter class inherits capabilities from
  // GenericVideoFilter, and extends them.
  // The GenericVideoFilter has both 'child' PClip and 'vi' VideoInfo variables which are initialized during our class's
  // construction and can be accessed by our member functions just by using their names directly eg 'child'.


private:
  // A Class will by default, be private access, but is here explicitly specified (I always forget the default)
  // using the 'private:' private access specifier.
  // The private section is where properties (variables) and member functions can only be accessed by other member functions
  // of the same class, and cannot be accessed by member functions of other classes (or non-class functions), even using
  // extended specifiers. 
  //
  // Variables and member functions in the 'private:' section cannot be accessed/called by Avisynth (or any other non member).
  //


int   intarg;
const bool version; // The const specifier will be explained in the implementation of the constructor.
const bool show;
int   bounce;


int num_frames_hi;
  // num_frames_hi is just a fairly standard usage variable that is used by the GETFRAME Macro and is very handy to
  // have around. I always set this and so do many others.

int *LifeLong;  // Just a demo of buffer creation.

  // accessable only to member functions of the class.
  enum{
    MSG_BUFSZ = 256,        // message buffer size
    FMT_BUFSZ = 2048        // Biggish Buffer size for v0.2 implemented DrawFStr().
  };

char errbf[MSG_BUFSZ];            // To print a text message

char formatted_buf[FMT_BUFSZ];    // enough for whatever, hopefully

  // The below three examples are user defined member function prototypes to show metrics type stuff
  // They take as a first arg, a reference to a frame, a sort of pointer that does not use
  // dereferencing to access what it points to, ie not *r just r.
    // eg:
    //  int a  = 2; // This is an initialization rather than an assignment
    //  int &r = a; // Reference MUST be initiallized to refer to a variable.
    //  r+=1;       // Changes 'a' to 3
  // The above 'int&' ; says it is a reference to type int.
  //
  // Example of the reference operator (from MS docs, VS6 online manual I think)
  //  void AddIt(int& x)
  //  {
  //    x += 2;
  //  }
  //  int x;        // Un-initialized variable
  //  x = 3;        // This is an assignment
  //  AddIt(x);     // Creates a temp reference to 'x' and calls the function with it (implicit type conversion).
  //  printf("%d", x) ;  // The value of x is now 5
  //
  // The above examples of initialization/assignment are true only for basic types (int/char, etc), for
  // User Defined Types (UDT's, class's etc), the above is not so clear. (TODO). 

  void __stdcall DrawStr(PVideoFrame &dst,int x,int y, const char *s);
  void __stdcall DrawFStr(PVideoFrame &dst,int x,int y,const char *format, ...);  // New v0.2
  void __stdcall DrawShow(PVideoFrame &dst, int n, IScriptEnvironment* env);
  // The above prototypes are both declarations and definitions.
  // They are declarations, of the functions which must be defined elsewhere, but, they 
  // are definitions in that they define function pointers to the as yet only declared functions.

  // The below function is 'inlined' (defined/implemented within the class definition) and does
  // not require implementation elsewhere.
  // Daft example only. Inline only used for short functions, if long, compiler will NOT inline,
  // ie, if inline then will expand code wherever fn call occurs in the source, if compiler
  // does NOT inline (because too long) then will create a function and call that
  // function instead of expanding code inline. Probably more than about 3 or 4 lines of code will
  // result in the 'inline' being ignored and a real function created instead.
  int   __stdcall timestwo(int n) {
    return n * 2;
  }

public:
  // A Class can have a 'public:' section where properties (variables) and member functions can be accessed by member
  // functions of other classes (or non-class functions). For class member functions to be available to Avisynth (
  // or other non class functions), there MUST be a public: access section and the accessible member functions
  // must be declared/defined in it.
  //
  // 'struct's too can have member functions (as can 'union',s) and the only difference I am aware of is that in a 'struct',
  // the default access specifier is 'public:' rather than 'private:'. There is also a 'protected:' access specifier
  // which will we will not go into here.
  // 
  // GenericVideoFilter is inherited into the 'public:' section and so is visible to Avisynth. (see head of class structure).
  // GenericVideoFilter would be the 'parent class' to 'INTERNALNAME'.
  // Below is the basic functionality of GenericVideoFilter which may be extended in your filter classes.
  // Most would solely re-define eg the GetFrame() function, whereas only those extending audio capabilities would re-define
  // the GetAudio() member function. If eg GetAudio() is not re-defined, then the default behaviour of the GenericVideoFilter
  // will be used to handle the audio (the audio will just be passed through untouched).
  //
  //    PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env);
  //    bool __stdcall GetParity(int n);
  //    void __stdcall GetAudio(void* buf, __int64 start, __int64 count, IScriptEnvironment* env);
  //    void __stdcall SetCacheHints(int cachehints,int frame_range);
  //
  // When re-defining the standard Avisynth filter functions, they must be present in the 'public:' section
  // so that Avisynth can call them. It may be best to have only the 'constructor', the 'destructor',
  // and the standard Avisynth functions that you will re-define in the 'public:' section of the class.
  //  
  // ------------------------------------------
  //  There are 3 member functions that SHOULD/MUST be declared or defined here so that external
  //  classes or functions can call them, ie to create a filter (instance of a filter), destroy a
  //  a filter or get a frame and return it to Avisynth.
  // --------
  //  1) the constructor, which creates an instance of the class. (the filter)
  //    A constructor has the same name as the class itself, in this case 'INTERNALNAME'.
  INTERNALNAME(PClip _child,int _intarg,const bool _version,bool _show, int _bounce, IScriptEnvironment* env);
  // This is the constructor. It does not return any value, and is always used when an instance of the class is created.
  // Since there is no code in this, this is the declaration and the body of the function has to be defined 
  // outside of the class.
  // 
  //  For Avisynth, the first arg is usually of type PClip usually named _child,
  //  Subsequent, clip args would use type PClip with names of eg _child2,
  //  The Last arg is usually type IScriptEnvironment*  named env.
  //  Strictly speaking, only the types are required, the names will be ignored
  //  here, it is only a declaration (prototype) rather than the implementation/definition.
  //  The code in the avisynth registration & filter creation functions (at the end of
  //  this file) need to be amended to match the constructor. (or vice versa)
  //    In C++ there can be more than one constructor, all with the same name and are differentiated by the
  //    compiler based upon the function arguments. This is called 'function overloading' (not just constructors).
  //    If eg fn(int) and fn(short) were defined and called as fn(char), the compiler would complain about
  //    ambiguity due to it not knowing which to convert the char argument to and would require an explicit
  //    cast to the required type. fn(int,int) etc could also be defined and differentiated correctly as the compiler,
  //  distinguishes by both number and type of arguments.
  //    Most plugin writers are happy to stick to one constructor only.
  //

  // --------
  //  2) the Destructor. The destructor takes the name of the class BUT preceded by a
  //     '~' symbol ie '~INTERNALNAME'.
  //  This is a declaration only and so has to be also defined outside of the class.
  //  A Destructor is not strictly necessary if it does nothing but it is good practice
  //  to ALWAYS do a destructor. (If you omit the destructor, the compiler will create
  //  one that does, almost nothing). A destructor takes no arguments.
  //
  ~INTERNALNAME();  // This is the destructor declaration. This is called when the filter is destroyed.
  //
  //  --------
  //  3) GetFrame, always same Standard GetFrame declaration.
  PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env);
  // This is the function that AviSynth calls to get a given frame.
  // So when this function gets called, the filter is supposed to return frame n.
  // 
  //  'env' is supplied so that you can call avisynth to use some built in feature of avisynth, eg 'env->MakeWritable()'.
  // ------------------------------------------
};
// THIS IS THE END OF THE CLASS STRUCTURE
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 31st March 2015 at 19:23. Reason: Update
StainlessS is online now   Reply With Quote
Old 13th November 2011, 22:10   #3  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,984
Page 3, Class Member Functions Part_1:-

Code:

/***************************
 * The following are the implementation / definition
 * of the declared class member functions.
 ***************************/


// This is the destructor definition. This is called when the filter is destroyed.
// Where declared or defined within the class, it uses the name eg '~INTERNALNAME', the class name preceded by tilde (~). 
// The destructor in this case, uses this form 'INTERNALNAME::~INTERNALNAME', where 'INTERNALNAME::' gives the name of
// the class it belongs to using the scope operator '::'.
// As with all class member functions, when defined outside of the class, the scope operator (::)  is used and specifies
// the class to which the member being defined belongs. Thus granting exactly the same scope properties as if this
// function definition was directly included within the class definition. This allows you to use a name of eg a class 
// member function or variable within the body of a function without any additional specifiers.

INTERNALNAME::~INTERNALNAME()
{
  // Clean up and Kill 'lifelong' arrays in here
  if(LifeLong != NULL) {
    OutputDebugString(AVISYNTHNAME ": Destructor delete[] LifeLong\n");
    delete [] LifeLong;                         // free(LifeLong)
    LifeLong=NULL;  // Not necessary, personal preference. On exit entire class instance including LifeLong gone.
  }
  OutputDebugString(AVISYNTHNAME ": Destructor now complete & exiting.\n");
  // The 'delete []' above will first call the destructor on each element of LifeLong before freeing the array.
  // As it happens, the built-in types (int, short, char etc) dont have destructors, they dont need any
  // special handling for destruction, and so there are no destructor calls in this case for LifeLong.
  //
  // The destructor does NOT return any type, not even void.
}




// This is the implementation of the constructor.
// As with all class members defined outside of the class, it is preceded by the class name and scope operator. 

INTERNALNAME::INTERNALNAME(
    PClip _child,int _intarg,const bool _version, bool _show, int _bounce, IScriptEnvironment* env) \
    :  \
    GenericVideoFilter(_child),version(_version),show(_show), LifeLong(NULL)     // initialization list
{
  //  Note above, the 1st line (after the name) contains the function arguments and closing
  //  parenthesis matching the prototype in the class structure.
  //  The following  ':' introduces an initialization list which initializes 'const' members.
  //  It will be necessary for the initialization of 'GenericVideoFilter' in this case and also 'version' & 'show'.
  //  In the above format, 'GenericVideoFilter(_child)' means initialize 'GenericVideoFilter' with the
  //  variable held in the _child fn argument. Same type of thing for 'version' & 'show' class variables. 
  //  Note that we did not initialize the intarg class variable with the _intarg fn argument, we will do
  //  that later. However, as the type of the 'version' class variable is 'const bool version' we have to 
  //  initialize it here. C++ differentiates between assignment and initialization, you can only initialize
  //  a const, you cannot assign to one, and that is what all that above weird stuff is.
  //  Quite often, coders just use the initializer versions if it results in an empty constructor.
  //  We also initialized 'LifeLong' above, even though it was not a function argument, nor a const (for
  //. no particular reason, just to show that you can).
  //
    // The child clip (source clip) is inherited by the GenericVideoFilter,
    //  where the following variables get defined:
    //   PClip child;   // Contains the source clip.
    //   VideoInfo vi;  // Contains video info on the source clip.
  //
  //
  // What the above is saying is that GenericVideoFilter has a child variable which is intialized
  // by the above GenericVideoFilter(_child). As the INTERNALNAME class inherits from GenericVideoFilter
  // ("class INTERNALNAME : public GenericVideoFilter {" at the very start of the class definition)
  // so we can in class member functions refer to child and actually access the 'child' PClip in the
  // GenericVideoFilter. The _child constructor argument is replicated to the GenericVideoFilter 'child',
  // and that is inherited by the INTERNALNAME class instance.
  //   Dont worry too much about that, you can access the child source clip and that is all
  // you really need to know. Also VideoInfo vi for the source clip, is likewise available without extra
  // specifiers

  intarg = _intarg; // We did not initialize intarg in the initialization list above so we assign to it here.

//  version = true;   // This would produce a compile time error as it is 'const', we used the initialization list instead.

//  show = true;      // This would produce a compile time error as it is 'const', we used the initialization list instead.


  bounce = (_bounce <= 64) ? _bounce : 64; // assign limited bounce with maximum of 64 (allow -ve bounce though)

//  LifeLong=NULL;    // Set to invalid - Commented Out, we used the above constructor initializer list instead.


  num_frames_hi = vi.num_frames;
  // We get the number of frames in clip, used by GETFRAME() macro (NOTE direct use of vi in GenericVideoFilter).

  errbf[0]=0;       // Clear error message

  int err = 0;      // So far, so good.

  OutputDebugString(AVISYNTHNAME ": Constructor now testing ColorSpace\n");
  // Above strings are concatenated (AVISYNTHNAME is a string)

  if (!vi.IsPlanar() && !vi.IsYUY2() && !vi.IsRGB32() && !vi.IsRGB24()) {
    strcpy(errbf,AVISYNTHNAME ": Input must be Planar, YUY2, RGB32 or RGB24\n");
    err=1;
  } else {  
    #ifdef AVISYNTH_PLUGIN_25
    // Plugin v2.5 and Avisynth v2.6
    AVSValue args[1];         // 1 undefined arg
    AVSValue res=env->Invoke("VersionNumber", AVSValue(args, 0)); 
    double ver=res.AsFloat();     // v2.6 comes out as 2.599999
    if(ver > 2.58 && vi.IsPlanar()) {
      if( vi.pixel_type!=0xA0000008 &&  // YV12
        vi.pixel_type!=0xE0000000   // Y8
      ) {
        strcpy(errbf,AVISYNTHNAME " ColorSpace unsupported in v2.5 plugin\n");
        err=1;
      }
    }
    # endif
  }
  if(err==0) {
    OutputDebugString(AVISYNTHNAME ": Constructor now trying 'LifeLong = new int[256]'\n");
    LifeLong = new int[256];                // (int *) malloc(256 * sizeof(LifeLong[0]));
  // Above new would call constructor on each element of LifeLong if it pointed to user defined type array,
  // but as basic types eg int do not have constructors, there are no constructor calls in this instance.
    if (LifeLong == NULL) {
      strcpy(errbf,AVISYNTHNAME ": Cannot allocate LifeLong\n");
      err=1;
    } else {
      OutputDebugString(AVISYNTHNAME ": Setting LifeLong dummy data\n");
      for(int i=0;i<256;++i)
        LifeLong[i]=i;            // Give it some dummy data
    }
  }
  
  if(err) {                       // Goodness me!
    OutputDebugString(AVISYNTHNAME ": Error Aborting\n");
    // Constructor not completing, destructor will NOT be called. (must free any allocated resources before exit)
    if(LifeLong!=NULL) {
      OutputDebugString(AVISYNTHNAME ": delete[] LifeLong\n");
      delete [] LifeLong;                       // equiv 'free(LifeLong);'
      LifeLong=NULL;              
    }

    if(errbf[0] == '\0') {
      char *p=errbf,*s=AVISYNTHNAME ": ERROR, *UKNOWN* Error, Dial 911 and ask for the Coastguard.\n";
      while(*p++=*s++);                 // strcpy()
    }

    OutputDebugString(errbf);           // Output the actual error message to DebugView Window
    env->ThrowError(errbf);             // Kiss me Hardy aaarh... (Last words of Stan Laurel).
    // Exit reporting avisynth error (will present message in Avisynth little red error box).
  }
  OutputDebugString(AVISYNTHNAME ": Constructor now complete & exiting OK.\n");
  // Constructors DONT return anything
}
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 31st March 2015 at 19:25. Reason: Update
StainlessS is online now   Reply With Quote
Old 13th November 2011, 22:11   #4  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,984
Page 4, Class Member Functions Part_2:-

Code:
// GetFrame() Called by Avisynth to get frame n. Via eg: YourFilter->GetFrame(n, env);
// As with all class members defined outside of the class, it is preceded by the class name and scope operator. 

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

  PVideoFrame dst; // Safe pointer to Video Frame

  #if 0
    if(n<0) n=0;
    else if(n>=num_frames_hi) n=num_frames_hi-1;
    // Range limit n to valid frames
  
    dst=child->GetFrame(n, env);  // get read only source frame n
  #else
    GETFRAME(n,dst);              // get read only source frame n (range limited by macro)
  #endif

  // The above range limiting, is not really much use here as Avisynth would usually
  // have given a valid n in it's call here (unless a following filter was in error when requesting frame n).
  // Where this is necessary is when you perhaps request frames on either side of 'n' for some
  // kind of temporal processing. eg child->GetFrame(n-1, env), could cause a problem when n==0
  // if not range limited.
  // The above is intended just to show how you would use the GETFRAME macro and what it does.
  //
  // The above "child->GetFrame(n, env);" is actually calling the version of GetFrame() that
  // was provided in the creation of the instance of the filter via Create_INTERNALNAME(),
  // (which is described later), it is passed as an argument to the constructor as _child and
  // is replicated during the initialzation of GenericVideoFilter into the child variable.
  // When calling child->GetFrame(n,env) you are fetching a frame from the previous filter
  // in the chain or whatever class it was that provided the source clip. (Perhaps a source class
  // eg AviSource, or ColorBars).
  // Our filter's GetFrame() [the function we are in right now] will modify the clip producing another.
  // clip (one frame at a time) which will be passed on to whatever filter follows in the chain.
  //
  //
  
  if(show || version) {
    DrawShow(dst,n,env);            // Do something simple to modify the frame with text.
  }

  if (bounce) { // bounce added in v0.3
    // We apply bounce AFTER rendering any text on-screen.
    env->MakeWritable(&dst);    // We are calling Avisynth here via env.
    // DrawShow() may have already made dst writable (if called), but we do it again. No effect if already writable.

    // We do something frivolous here to alter the frame, see SimpleSample source for better examples.

  int fps = (int)((double)vi.fps_numerator/(double)vi.fps_denominator + 0.5);
    const int width   = vi.width;                  // In pixels, (why not exposed via PVideoFrame eg dst->GetWidth() ?)
  if (fps * 4 > width)
    fps = width / 4;  // Avoid Divide by Zero if High Framerate or small clip.
  int Secs72 = 72 * fps;
  int Secs8  = 8  * fps;
  int Secs4  = 4  * fps;

    int nn = (n % Secs72); // cycle 72 seconds
    if((nn-=Secs8) >= 0) { // 8 Secs rest, 64 secs active (start x/y==0).

      // Get colorspace common vars (We only are only going to alter Y in YUV colorspaces).
      // Should work OK in Avisynth v2.6 colorspaces as we only touch Y in YUV (although any
      // planar RGB colorspace would fail). The Example() plugin as a whole will not work properley in Avisynth
      // v2.6 extended colorspaces as Info.h text renderer alters the chroma and as the Avisynth
      // v2.5 header returns the wrong values for chroma width/height, the chroma will be wrong (ghosted miniture
      // colored text). Plugin should work just fine as it in Y8 colorspace as Y8 has no chroma.
      // If recompiled for Avisynth v2.6, plugin should work OK in all colorspaces (with exception of any Planar RGB).

      const int height  = dst->GetHeight(PLANAR_Y);
      const int rowsize = dst->GetRowSize(PLANAR_Y); // In bytes (eg, About pixel width * 3 in RGB24 [mod whatever])
      const int pitch   = dst->GetPitch(PLANAR_Y);
      // eg GetPitch() and GetPitch(PLANAR_Y) are equivalent for non-planar eg YUY2, RGB24 or RGB32.
      // (PLANAR_Y equates to 0) EDIT: WRONG, Equates to 1 << 0
      // NOTE, if doing any kind of temporal processing, each frame should have it's own 'pitch' variable as
      // 'pitch' can vary within the same clip (perhaps by eg interleaving clips with different croppings).

      const int bounce_step=(bounce>0)?bounce:(bounce<=-2)?((nn/100+1)*2):(width/Secs4);
      // Bouncing walls movement step (both x & y).
      // Speed of moving walls per frame, a bit slow to move 1 pixel per frame.
      // ie if 1 then would take eg 720 frames to cross 720 width clip (might be smoother, but very tedious).

      const int xm = (nn %  (vi.width / bounce_step)) * bounce_step;
      const int ym = (nn %  (vi.height/ bounce_step)) * bounce_step;
      // Cursor positions relative, xLft, xRgt, yTop, yBot to qualify for invert.

      int x,y,w;

      if(vi.IsPlanar() || vi.IsYUY2()) {
        // Planar or YUY2

        unsigned char *dp = dst->GetWritePtr(PLANAR_Y);
        // We are only going to alter Y, we do not touch chroma.

        const int wstep   = (vi.IsPlanar()) ? 1 : 2;  // 2 for YUY2 or 1 for any Planar.

        for (y=0; y < height; ++y) {

          bool invert_y = (y <= ym) ^ ((height-1-y) >= ym);
          // invert due to vertical scanning walls ?

          for (x = w = 0; w < rowsize; w += wstep, ++x) {

            bool invert_x = ((x <= xm) ^ ((width-1-x) >= xm));
            // invert due to horizontal scanning walls ?
            
            // we tracked all four walls so as to avoid up to 4 inverts
            // An even number of inverts is the same as no invert, but we used '^' (XOR) instead of add.
            if(invert_y ^ invert_x) { // combined invert flags
              dp[w] ^= 0xFF;      // XOR 0xFF, ie invert
            }
          }
          dp += pitch;          // Add the pitch of one line (in bytes) to the dest.
        }

      } else if(vi.IsRGB()){
        // RGB24 or RGB32

        // RGB is Weird. starts at bottom Left Hand Side instead of Top Left Hand Side (vertically flipped).
        // Ie, GetWritePtr(), is the left side of bottom raster line, not the top.
        unsigned char *dp = dst->GetWritePtr() + (height-1) * pitch;
        // Top left hand side, ie normal, although we have to Subtract rather than add to
        // go to the next raster line.
        // We could have started at the bottom and by adding pitch, scan upwards but just
        // so that both YUV and RGB work in the same fashion, we add (height-1) * pitch
        // to start at the top.

        const int wstep = (vi.IsRGB24()) ? 3 : 4; // 3 bytes for RGB24, & 4 for RGB32.

        for (y=0; y < height; ++y) {

          bool invert_y = (y <= ym) ^ ((height-1-y) >= ym);
          
          for (x = w = 0; w < rowsize; w += wstep, ++x) {

            bool invert_x = ((x <= xm) ^ ((width-1-x) >= xm));
            
            if(invert_y ^ invert_x) { // combined invert flags      
              dp[w]   ^= 0xFF;    // B, XOR 0xFF, ie invert
              dp[w+1] ^= 0xFF;    // G
              dp[w+2] ^= 0xFF;    // R
            }
          }
          dp -= pitch;  // Subtract the pitch of one line (in bytes, Daft RGB), one raster line down.
        }
      }
    }
  }
  return dst;
}



// DrawStr() Draw a string of text at character position, a user defined member function.
// As with all class members defined outside of the class, it is preceded by the class name and scope operator. 

void __stdcall INTERNALNAME::DrawStr(PVideoFrame &dst,int x,int y,const char *s) {
  x *= 10;  y *= 20;  // conv char to pixel coords  (this assumes knowledge of the internals of Info.h)

  // The DrawStringXXX fn's are implemented in the Info.h file.
  // Draw some plain text with NO formatting at all. (Info.h converts ALL control codes to SPACE).
  if(vi.IsPlanar())     DrawStringPlanar(dst,x,y,s);
  else if(vi.IsYUY2())  DrawStringYUY2(dst,x,y,s);
  else if(vi.IsRGB32()) DrawStringRGB32(dst,x,y,s);
  else if(vi.IsRGB24()) DrawStringRGB24(dst,x,y,s);
  // This is a member function so it has access to vi for input source clip
  // as initialized in the GenericVideoFilter by the constructor
  // NOTE, dst is a reference so the frame can be updated without returning anything.
}

// DrawFStr() Draw a Formatted string of text at character position, a user defined member function.
// As with all class members defined outside of the class, it is preceded by the class name and scope operator. 

void __stdcall INTERNALNAME::DrawFStr(PVideoFrame &dst,int x,int y,const char *format, ...)
{
  // This member function added in v0.2, adds BOTH string and screen/layout formatting, 
  // eg '%f' for string and '\n' for screen/layout.

  // Firstly, string formatting, into the buffer implemented in the class instance, formatted_buf[FMT_BUFSZ].
  va_list args;
  va_start(args, format);
  _vsnprintf(formatted_buf,FMT_BUFSZ-1, format, args);
  va_end(args);
  // The above allows you to use this member function in the same way as eg printf("test=%d",i) ie DrawFStr(dst,x,y,"test=%d",i)

  // The DrawFStrXXX fn's are implemented in the InfoF.h file and provide screen/layout formatting, eg '\'n and '\t'.
  // As string formatting has already been done above (eg floats etc turned to character strings), and the below
  // DrawFStrXXX functions provide screen/layout formatting, so full formatting is achieved on the video frame.
  //
  //   Formatting control codes (as provided by InfoF.h):-
  //   '\n', Newline, positioning cursor 1 line down and at left edge of screen.
  //   '\r', Newline Special, moves 1 line down and positions cursor at on-entry X position.
  //   '\b', Backspace, obvious, not sure how useful this will be.
  //   '\f', Forward Space, again obvious, re-uses formfeed code for this. Again, maybe not so useful.
  //   '\t', Tab, @ character positions, every 4 characters.(relative screen LHS).
  //  
  if(vi.IsPlanar())     DrawFStrPlanar(dst,x,y,formatted_buf);
  else if(vi.IsYUY2())  DrawFStrYUY2(dst,x,y,formatted_buf);
  else if(vi.IsRGB32()) DrawFStrRGB32(dst,x,y,formatted_buf);
  else if(vi.IsRGB24()) DrawFStrRGB24(dst,x,y,formatted_buf);
}

// DrawShow() show some text type stuff
// As with all class members defined outside of the class, it is preceded by the class name and scope operator. 

void INTERNALNAME::DrawShow(PVideoFrame &dst, int n,IScriptEnvironment* env)
{
char buf[256];

  env->MakeWritable(&dst);    // We are calling Avisynth here via env.
  // Make sure we can write to it.
  // If dst is read only (original source frame usually) we need to create
  // another writable frame, which is a copy of the original, dst will hold a writable copy.
  // If frame is already read/write, then will not do anything.

  int voff = 0;   // vertical print offset

  if(version) {
    // draw some text with neither string nor screen formatting, directly from concatenated string literals.
    DrawStr(dst,0,voff,"Just a daft " AVISYNTHNAME "() demo " DEMOVERSION);
    voff+=2;
  }

  if(show) {
    sprintf(buf,"Frame = %i",n);  // draw some text with string formatting only.
    DrawStr(dst,0,voff,buf);      // Info.h converts ALL control characters to SPACE, eg '\n' prints SPACE.
    voff+=2;

    DrawStr(dst,0,voff++,"Args:-");   // no formatting, string literal

    // string formatting only
    sprintf(buf,"1 intarg  = %i",intarg);
    DrawStr(dst,2,voff++,buf);
    sprintf(buf,"2 version = %s",(version)?"true":"false");
    DrawStr(dst,2,voff++,buf);
    sprintf(buf,"3 show    = %s",(show)?"true":"false");
    DrawStr(dst,2,voff++,buf);
    sprintf(buf,"4 bounce  = %i %s",bounce,(bounce==-1)?"(Auto)":(bounce<-1)?"(Variable)":(bounce==0)?"(Off)":"(Fixed)");
    DrawStr(dst,2,voff++,buf);
    voff++;

    sprintf(buf,"timestwo(frame+intarg)=%i",timestwo(n+intarg));
    DrawStr(dst,0,voff,buf);
    voff+=2;

    // FULL string + screen/layout formatting example.

    DrawFStr(dst,1,voff + 0,    // NOTE, DIFFERENT CALL ie DrawFStr()
    "EVERYTHING HERE/BELOW is one single printed string.\r"
    "Combines both string (eg %%f) and layout (eg '\\n') formatting.\r\r"
    "Frame: %-7u( Red    / Green  /  Blue  )\r"
    "     Fred:    (%7.2f /%7.2f /%7.2f )\r"
    "      Ted:    (%7.2f /%7.2f /%7.2f )\r"
    "     Bill:    ( %3d    / %3d    / %3d    )\r"
    "      Ben:    ( %3d    / %3d    / %3d    )\r"
    "     Jack:    ( %3d    / %3d    / %3d    )\r"
    "     Jill:    ( %3d    / %3d    / %3d    )\r"
    "\t\t\t\tDATA is RANDOM ONLY"
    ,n,
    rand()*255.0/RAND_MAX,rand()*255.0/RAND_MAX,rand()*255.0/RAND_MAX,
    rand()*255.0/RAND_MAX,rand()*255.0/RAND_MAX,rand()*255.0/RAND_MAX,
    rand()&255,rand()&255,rand()&255,rand()&255,rand()&255,rand()&255,
    rand()&255,rand()&255,rand()&255,rand()&255,rand()&255,rand()&255
    );
  }
  // Exit with dst frame read/write and updated
}
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 23rd October 2017 at 22:20. Reason: Update
StainlessS is online now   Reply With Quote
Old 13th November 2011, 22:12   #5  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,984
Page 5, Avisynth registration and Filter Creation:-

Code:
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// The stuff below is to connect and make available the plugin to Avisynth.
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------


// This is the function that creates an instance of the filter class when the filter is used in Avisynth.
// In this case, the function is called 'Create_INTERNALNAME', but it could have been called anything,
// the Avisynth Plugin registration Function 'AvisynthPluginInit2()' (below) told Avisynth which
// function to call to create an instance of the filter. You will only be wanting to edit the name of this
// function, the arguments and calling convention should remain fixed.
//  This function can be used for simple parameter checking, so it is possible to create different filters,
// based on the arguments received, for further, see filter sources.

AVSValue __cdecl Create_INTERNALNAME(AVSValue args, void* user_data, IScriptEnvironment* env) {
  // Calls the filter class constructor with the arguments provided.
  // The arguments to 'new' MUST match those in the class declaration for the constructor.
  // BEWARE the 'n' in args[n] must also be set correctly. (incremental from zero)
  // Can use types eg, AsClip(), AsInt(), AsFloat(), AsString(), AsBool() and can supply a default argument. 

  int default_intarg = 42;          // could set this default, from eg a settings file.

  OutputDebugString(AVISYNTHNAME ": Creating Filter instance - Calling Constructor\n");

  return new INTERNALNAME(            // Arguments to the Filter class Constructor of INTERNALNAME class.
      args[0].AsClip(),               // _child,  (Not optional no default specified)
      args[1].AsInt(default_intarg),  // _intarg, with default set to 'default_intarg'.
      args[2].AsBool(true),           // _version, with default to true if not supplied.
      args[3].AsBool(true),           // _show, with default to true if not supplied.
      args[4].AsInt(-1),              // _bounce, with default -1 (auto select bounce step)
      env  // Supplies constructor with environment, env is often used for raising an error in the constructor.
      );
  // The above 'new' is sort of like a malloc to get a block of memory for the
  // class structure, followed by calling the constructor for the class on that memory block,
  // which creates an instance of the filter class and returns it to Avisynth as an AVSValue.
  // AVSValue, a type of variant holding a value of any type. The args function argument above is an
  // AVSValue which happens to be an array of AVSValues, and eg args[0].AsClip() was used to get
  // the first argument as a Clip without a default value.
  // An optional clip would eg use a default of 'NULL' (zero) which should be detected as invalid/not-used
  // by a filter class constructor, and obviously should not be accessed as a clip, as an alternative, you might call
  // a different constructor for the filter which does not take the optional clip arg. (a class can have multiple
  // constructors).
} 



// ------------------------------------------
// The standard Avisynth Plugin registration Function
// The following function is the function that actually registers the filter in AviSynth
// It is called automatically, when the plugin is loaded to see which functions this filter contains.
// It does not actually create an instance of the filter, but it does tell Avisynth which function to call
// to do that, if the filter is used within a script.
// The name, the argument, and calling convention is fixed. 

#ifdef AVISYNTH_PLUGIN_25
  extern "C" __declspec(dllexport) const char* __stdcall AvisynthPluginInit2(IScriptEnvironment* env){
    OutputDebugString(AVISYNTHNAME ": AvisynthPluginInit2 Calling env->AddFunction\n");
#else
  /* New 2.6 requirement!!! */
  // Declare and initialise server pointers static storage.
  const AVS_Linkage *AVS_linkage = 0;

  /* New 2.6 requirement!!! */
  // DLL entry point called from LoadPlugin() to setup a user plugin.
  extern "C" __declspec(dllexport) const char* __stdcall
      AvisynthPluginInit3(IScriptEnvironment* env, const AVS_Linkage* const vectors) {

      /* New 2.6 requirment!!! */
      // Save the server pointers.
      AVS_linkage = vectors;
      OutputDebugString(AVISYNTHNAME ": AvisynthPluginInit3 Calling env->AddFunction\n");
#endif

  // The code below, registers the plugin with avisynth and tells it how to construct/create
  // the filter, the argument types it accepts and whether they are optional/named arguments.
  // AddFunction has the following paramters:
  // AddFunction(FilterName , Arguments, Function-to-call,0);


    env->AddFunction(
      AVISYNTHNAME,                               // The name of the filter in Avisynth (as a string).
      "c[intarg]i[version]b[show]b[bounce]i",  // Arguments, THIS MUST BE EDITED TO SUIT THE FILTER ARGUMENTS.
      Create_INTERNALNAME,                        // The function Avisynth will call to create an instance of the filter.
      0                                           // Zero. (possibly 'user_data' arg in Create_INTERNALNAME, never seen used).
    );
  // This particular registration, says:
  // The name of the filter in Avisynth is AVISYNTHNAME().
  // First filter arg 'c' is an un-named compulsory clip ('[name]' means 'name' is optional), 
  // Second filter arg '[intarg]i' is an optional arg of type int.
  // Third filter arg '[version]b' is an optional arg of type bool.
  // Forth filter arg '[show]b' is an optional arg of type bool.
  // Fifth filter arg '[bounce]i' is an optional arg of type int.
  // In this case the filter is similar to an Avisynth script definition of 
  // AVISYNTHNAME(clip,int "intarg",bool "version",bool "show", int "bounce").
  // Of course, this must match what it uses in the above Avisynth Filter Creation function,
  // and is almost always what the class constructor accepts.

  // Arguments is a string that defines the types and optional names of the arguments for your filter.
  // The names of optional arguments are enclosed in '[]' as in [name] and followed by the type string specifier.
  // An argument list of eg "cc" would indicate a filter requiring two compulsory un-named clips.
  // An arg list of eg "c[]c" would indicate a filter accepting a compulsory un-named clip and an
  // optional un-named clip, without the '[]' in the arg list string, Avisynth would NOT allow you to call
  // the filter without both clips even if you gave a default value in the 'Create_INTERNALNAME' filter creator
  // (previous function above).

  // Argument type specifier strings.
  // c - Video Clip
  // i - Integer number
  // f - Float number
  // s - String
  // b - boolean
  // . - Any type (dot)
  //      Array Specifiers
  // i* - Integer Array, zero or more
  // i+ - Integer Array, one or more
  // .* - Any type Array, zero or more
  // .+ - Any type Array, one or more
  //      Etc

  #ifdef AVISYNTH_PLUGIN_25
    OutputDebugString(AVISYNTHNAME ": AvisynthPluginInit2 returning to Avisynth\n");
  #else
    OutputDebugString(AVISYNTHNAME ": AvisynthPluginInit3 returning to Avisynth\n");
  #endif

  //  return "'Example' Example plugin";
  return ("'" AVISYNTHNAME "' " AVISYNTHNAME " plugin");
  // A freeform name of the plugin. Dont think this returned string is actually used for anything in Avisynth.
}
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 31st March 2015 at 19:26. Reason: Update
StainlessS is online now   Reply With Quote
Old 14th November 2011, 00:50   #6  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,380
Nice work, StainlessS.
A couple of things I spotted on a quick browse through:
Quote:
Originally Posted by StainlessS View Post
Page 3, Class Member Functions:-
Code:
...
  // The above "child->GetFrame(n, env);" is actually calling the GenericVideoFilter implemented
  // version of GetFrame() which provides the basic functionality of getting the un-edited source
  // frame, and our filters GetFrame() [the function we are in right now] will provide new
  // functionality by modifying it.
No, child->GetFrame is calling the GetFrame() of whatever class the child clip is - this will usually be another filter, whatever was used in the script to produce the input to your plugin.
Perhaps you meant 'replicating' rather than 'calling' here?

Quote:
Originally Posted by StainlessS View Post
Page 4, Avisynth registration and Filter Creation:-
Code:
...
  return new INTERNALNAME(          // Arguments to the Filter class Constructor of INTERNALNAME class.
      args[0].AsClip(),         // child,  (Not optional no default specified)
      args[1].AsInt(default_intarg),    // intarg, with default set to 'default_intarg'.
      args[2].AsBool(true),       // version, with default to true if not supplied.
      env                 // Supplies your constructor with environment, rarely used in constructors.
env is often used for raising an error in the constructor args (as indeed you do in this example).
__________________
GScript and GRunT - complex Avisynth scripting made easier
Gavino is offline   Reply With Quote
Old 14th November 2011, 01:27   #7  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,984
Quote:
Originally Posted by Gavino View Post
No, child->GetFrame is calling the GetFrame() of whatever class the child clip is -
this will usually be another filter, whatever was used in the script to produce the input to your plugin.
Perhaps you meant 'replicating' rather than 'calling' here?
Dont really know what I meant there, I was just bluffing.


Quote:
Originally Posted by Gavino View Post
env is often used for raising an error in the constructor args (as indeed you do in this example).
Yes indeed (kicks oneself).
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???
StainlessS is online now   Reply With Quote
Old 19th November 2011, 20:39   #8  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,984
Update:

v0.2 - 19 Nov 2011, InfoF.h moved to active Example() source.
Formatted print member fn DrawFStr() added with FULL string & screen formatting.
(the above function implemented for the first time for this Example() but the
demo-ing screen output string was partially robbed from DDigitTest() plugin).


MAIN CHANGES to previous version noted here:

Page 2, The Class definition:-

Code:
#include "Info.h"
// Plugin text rendering header from Avisynth v2.6, (Use Version of 17 April 2011, or later, bugs fixed, OK for v2.5+)
// Provides white only horizontal print at pixel coordinates, no formatting of any kind.
// Obtainable here (look for 'Info.h'):-
//    http://avisynth2.cvs.sourceforge.net/viewvc/avisynth2/avisynth/src/core/

#include "InfoF.h"  // New in v0.2
// A companion to Info.h, provides screen formatted printing via embedded control codes.
// Also provides stubs for character coord printing as well as pixel coordinates.
//   Formatting control codes:-
//   '\n', Newline, positioning cursor 1 line down and at left edge of screen.
//   '\r', Newline Special, moves 1 line down and positions cursor at on-entry X position.
//   '\b', Backspace, obvious, not sure how useful this will be.
//   '\f', Forward Space, again obvious, re-uses formfeed code for this. Again, maybe not so useful.
//   '\t', Tab, @ character positions, every 4 characters.(relative screen LHS).
//
// DDigit() from which this header originates, provides horizontal & vertical print at both pixel
// and character coords, 16 color printing and screen formatting (eg '\n') control codes together
// with color control codes. Control codes, vertical print and colorspace code are all controlled
// via compiler directives and so can be excluded from the binary if not required.
//
Page 3, Class Member Functions:-

Code:
// DrawFStr() Draw a Formatted string of text at character position, a user defined member function.
// As with all class members defined outside of the class, it is preceded by the class name and scope operator. 

void __stdcall INTERNALNAME::DrawFStr(PVideoFrame &dst,int x,int y,const char *format, ...)
{
  // This member function added in v0.2, adds BOTH string and screen formatting, eg '%f' for string and '\n' for screen.

  // Firstly, string formatting, into the buffer implemented in the class instance, formatted_buf[FMT_BUFSZ].
  va_list args;
  va_start(args, format);
  _vsnprintf(formatted_buf,FMT_BUFSZ-1, format, args);
  va_end(args);

  // The DrawFStrXXX fn's are implemented in the InfoF.h file and provide screen formatting, eg '\'n and '\t'.
  // As string formatting has already been done above (eg floats etc turned to character strings), and the below
  // DrawFStrXXX functions provide screen formatting, so full formatting is achieved on the video frame.
  //
  //   Formatting control codes (as provided by InfoF.h):-
  //   '\n', Newline, positioning cursor 1 line down and at left edge of screen.
  //   '\r', Newline Special, moves 1 line down and positions cursor at on-entry X position.
  //   '\b', Backspace, obvious, not sure how useful this will be.
  //   '\f', Forward Space, again obvious, re-uses formfeed code for this. Again, maybe not so useful.
  //   '\t', Tab, @ character positions, every 4 characters.(relative screen LHS).
  //  
  if(vi.IsPlanar())     DrawFStrPlanar(dst,x,y,formatted_buf);
  else if(vi.IsYUY2())  DrawFStrYUY2(dst,x,y,formatted_buf);
  else if(vi.IsRGB32()) DrawFStrRGB32(dst,x,y,formatted_buf);
  else if(vi.IsRGB24()) DrawFStrRGB24(dst,x,y,formatted_buf);
}

// DrawShow() show some text type stuff
// As with all class members defined outside of the class, it is preceded by the class name and scope operator. 

void INTERNALNAME::DrawShow(PVideoFrame &dst, int n,IScriptEnvironment* env)
{
char buf[256];

  env->MakeWritable(&dst);    // We are calling Avisynth here via env.
  // Make sure we can write to it.
  // If dst is read only (original source frame usually) we need to create
  // another writable frame, which is a copy of the original, dst will hold a writable copy.
  // If frame is already read/write, then will not do anything.

  int voff = 0;   // vertical print offset

  if(version) {
    // draw some text with neither string nor screen formatting, directly from concatenated string literal.
    DrawStr(dst,0,voff,"Just a daft " AVISYNTHNAME "() demo " DEMOVERSION);
    voff+=2;
  }

  sprintf(buf,"Frame = %i",n);  // draw some text with string formatting only.
  DrawStr(dst,0,voff,buf);      // Info.h converts ALL control characters to SPACE, eg '\n' prints SPACE.
  voff+=2;

  DrawStr(dst,0,voff++,"Args:-");   // no formatting, string literal

  sprintf(buf,"1 intarg  = %i)",intarg);
  DrawStr(dst,2,voff++,buf);        // draw some text with string formatting only.

  // string formatting only
  sprintf(buf,"2 version = %s)",(version)?"true":"false");
  DrawStr(dst,2,voff,buf);
  voff+=2;
  sprintf(buf,"timestwo(frame+intarg)=%i",timestwo(n+intarg));
  DrawStr(dst,0,voff,buf);
  voff+=2;

  // FULL string + Screen formatting example.

  DrawFStr(dst,2,voff+2,    // NOTE, DIFFERENT CALL ie DrawFStr()
   "EVERYTHING BELOW (incl this) is 1 single printed string.\r"
  "Combines both string (eg %%f) and screen (eg '\\n') formatting.\r\r"
  "Frame: %-7u( Red    / Green  /  Blue  )\r"
  "     Fred:    (%7.2f /%7.2f /%7.2f )\r"
  "      Ted:    (%7.2f /%7.2f /%7.2f )\r"
  "     Bill:    ( %3d    / %3d    / %3d    )\r"
  "      Ben:    ( %3d    / %3d    / %3d    )\r"
  "     Jack:    ( %3d    / %3d    / %3d    )\r"
  "     Jill:    ( %3d    / %3d    / %3d    )\r"
  "\t\t\t\tDATA is RANDOM ONLY\n\n"
  ,n,
  rand()*255.0/RAND_MAX,rand()*255.0/RAND_MAX,rand()*255.0/RAND_MAX,
  rand()*255.0/RAND_MAX,rand()*255.0/RAND_MAX,rand()*255.0/RAND_MAX,
  rand()&255,rand()&255,rand()&255,rand()&255,rand()&255,rand()&255,
  rand()&255,rand()&255,rand()&255,rand()&255,rand()&255,rand()&255
  );
  // Exit with dst frame read/write and updated
}
Example() Output showing DrawShow calling DrawFStr().



EDIT: Oh dear, we seem to have a surplus of parenthesis in the args printout.
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 10th May 2018 at 11:25.
StainlessS is online now   Reply With Quote
Old 30th January 2012, 04:19   #9  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,984
Update: See 1st post.

Code:
  v0.3 - 30 Jan 2012
    Added 'bool "show"' [default true]. Shows text on-screen.
    Added Bouncing walls demo when 'int bounce' non zero.
    int "bounce", default -1, 0 == Off, -1 == Auto, <= -2 == Variable, 1 -> 64 == Fixed bounce step size (limited to max 64).
As 'Page 3 Member Functions,' Overflowed 20Kb (Doom9 post limit), have had to split that page in two and put 1st
page in the opening post.


MAIN CHANGES to previous version noted here:

Page 1, The Intro:-

Code:
# Test AVS file.
ColorBars()
#ConvertToYV12()
#ConvertToYUY2()
#ConvertToRGB32()
#ConvertToRGB24()
#ConvertToY8()

Example()  	                                      # Default Example(intarg=42,version=true,show=true,bounce=-1)
#Example(intarg=27,version=false,show=true,bounce=32) # Fixed bounce at 32
#Example(intarg=76,version=true,show=true,bounce=-1)  # Fixed bounce Auto assigned
#Example(intarg=33,version=false,show=true,bounce=-2) # Variable bounce
#Example(intarg=64,version=true,show=true,bounce=0)   # Bounce Off
#Example(version=false,show=false,bounce=-1)          # Bounce Auto, text OFF

#ConvertToRGB32()                                     # If Y8
#
# This should work with Text Off in v2.6, or should work with Text On if compiled for v2.6.
#ConvertToYV24().Example(version=false,show=false,bounce=-1).ConvertToRGB32()
return last
Page 4, Class Member Functions Part_2:-

Code:
// GetFrame() Called by Avisynth to get frame n. Via eg: YourFilter->GetFrame(n, env);
// As with all class members defined outside of the class, it is preceded by the class name and scope operator. 

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

  PVideoFrame dst; // Safe pointer to Video Frame

  #if 0
    if(n<0) n=0;
    else if(n>=num_frames_hi) n=num_frames_hi-1;
    // Range limit n to valid frames
  
    dst=child->GetFrame(n, env);  // get read only source frame n
  #else
    GETFRAME(n,dst);              // get read only source frame n (range limited by macro)
  #endif

  // The above range limiting, is not really much use here as Avisynth would usually
  // have given a valid n in it's call here (unless a following filter was in error when requesting frame n).
  // Where this is necessary is when you perhaps request frames on either side of 'n' for some
  // kind of temporal processing. eg child->GetFrame(n-1, env), could cause a problem when n==0
  // if not range limited.
  // The above is intended just to show how you would use the GETFRAME macro and what it does.
  //
  // The above "child->GetFrame(n, env);" is actually calling the version of GetFrame() that
  // was provided in the creation of the instance of the filter via Create_INTERNALNAME(),
  // (which is described later), it is passed as an argument to the constructor as _child and
  // is replicated during the initialzation of GenericVideoFilter into the child variable.
  // When calling child->GetFrame(n,env) you are fetching a frame from the previous filter
  // in the chain or whatever class it was that provided the source clip. (Perhaps a source class
  // eg AviSource, or ColorBars).
  // Our filter's GetFrame() [the function we are in right now] will modify the clip producing another.
  // clip (one frame at a time) which will be passed on to whatever filter follows in the chain.
  //
  //
  
  if(show || version) {
    DrawShow(dst,n,env);            // Do something simple to modify the frame with text.
  }

  if (bounce) { // bounce added in v0.3
    // We apply bounce AFTER rendering any text on-screen.
    env->MakeWritable(&dst);    // We are calling Avisynth here via env.
    // DrawShow() may have already made dst writable (if called), but we do it again. No effect if already writable.

    // We do something frivolous here to alter the frame, see SimpleSample source for better examples.


    int fps = (int)((double)vi.fps_numerator/(double)vi.fps_denominator + 0.5);
    const int width   = vi.width;                  // In pixels, (why not exposed via PVideoFrame eg dst->GetWidth() ?)
    if (fps * 4 > width)
      fps = width / 4;                   // Avoid Divide by Zero if High Framerate or small clip.
    int Secs72 = 72 * fps;
    int Secs8  = 8  * fps;
    int Secs4  = 4  * fps;

    int nn = (n % Secs72); // cycle 72 seconds
    if((nn-=Secs8) >= 0) { // 8 Secs rest, 64 secs active (start x/y==0).
      // Get colorspace common vars (We only are only going to alter Y in YUV colorspaces).
      // Should work OK in Avisynth v2.6 colorspaces as we only touch Y in YUV (although any
      // planar RGB colorspace would fail). The Example() plugin as a whole will not work properley in Avisynth
      // v2.6 extended colorspaces as Info.h text renderer alters the chroma and as the Avisynth
      // v2.5 header returns the wrong values for chroma width/height, the chroma will be wrong (ghosted miniture
      // colored text). Plugin should work just fine as it in Y8 colorspace as Y8 has no chroma.
      // If recompiled for Avisynth v2.6, plugin should work OK in all colorspaces (with exception of any Planar RGB).

      const int height  = dst->GetHeight(PLANAR_Y);
      const int rowsize = dst->GetRowSize(PLANAR_Y); // In bytes (eg, About pixel width * 3 in RGB24 [mod whatever])
      const int pitch   = dst->GetPitch(PLANAR_Y);
      // eg GetPitch() and GetPitch(PLANAR_Y) are equivalent for non-planar eg YUY2, RGB24 or RGB32.
      // (PLANAR_Y equates to 0) # EDIT: WRONG, it equates to 1<<0 ie 1
      // NOTE, if doing any kind of temporal processing, each frame should have it's own 'pitch' variable as
      // 'pitch' can vary within the same clip (perhaps by eg interleaving clips with different croppings).

       const int bounce_step=(bounce>0)?bounce:(bounce<=-2)?((nn/100+1)*2):(width/Secs4);
      // Bouncing walls movement step (both x & y).
      // Speed of moving walls per frame, a bit slow to move 1 pixel per frame.
      // ie if 1 then would take eg 720 frames to cross 720 width clip (might be smoother, but very tedious).

      const int xm = (nn %  (vi.width / bounce_step)) * bounce_step;
      const int ym = (nn %  (vi.height/ bounce_step)) * bounce_step;
      // Cursor positions relative, xLft, xRgt, yTop, yBot to qualify for invert.

      int x,y,w;

      if(vi.IsPlanar() || vi.IsYUY2()) {
        // Planar or YUY2

        unsigned char *dp = dst->GetWritePtr(PLANAR_Y);
        // We are only going to alter Y, we do not touch chroma.

        const int wstep   = (vi.IsPlanar()) ? 1 : 2;  // 2 for YUY2 or 1 for any Planar.

        for (y=0; y < height; ++y) {

          bool invert_y = (y <= ym) ^ ((height-1-y) >= ym);
          // invert due to vertical scanning walls ?

          for (x = w = 0; w < rowsize; w += wstep, ++x) {

            bool invert_x = ((x <= xm) ^ ((width-1-x) >= xm));
            // invert due to horizontal scanning walls ?
            
            // we tracked all four walls so as to avoid up to 4 inverts
            // An even number of inverts is the same as no invert, but we used '^' (XOR) instead of add.
            if(invert_y ^ invert_x) { // combined invert flags
              dp[w] ^= 0xFF;      // XOR 0xFF, ie invert
            }
          }
          dp += pitch;          // Add the pitch of one line (in bytes) to the dest.
        }

      } else if(vi.IsRGB()){
        // RGB24 or RGB32

        // RGB is Weird. starts at bottom Left Hand Side instead of Top Left Hand Side.
        // Ie, GetWritePtr(), is the left side of bottom raster line, not the top.
        unsigned char *dp = dst->GetWritePtr() + (height-1) * pitch;
        // Top left hand side, ie normal, although we have to Subtract rather than add to
        // go to the next raster line.
        // We could have started at the bottom and by adding pitch, scan upwards but just
        // so that both YUV and RGB work in the same fashion, we add (height-1) * pitch
        // to start at the top.

        const wstep = (vi.IsRGB24()) ? 3 : 4; // 3 bytes for RGB24, & 4 for RGB32.

        for (y=0; y < height; ++y) {

          bool invert_y = (y <= ym) ^ ((height-1-y) >= ym);
          // invert due to vertical scanning walls ?
          
          for (x = w = 0; w < rowsize; w += wstep, ++x) {

            bool invert_x = ((x <= xm) ^ ((width-1-x) >= xm));
            // invert due to horizontal scanning walls ?
            
            // we tracked all four walls so as to avoid up to 4 inverts
            // An even number of inverts is the same as no invert, but we used '^' (XOR) instead of add.
            if(invert_y ^ invert_x) { // combined invert flags      
              dp[w]   ^= 0xFF;    // B, XOR 0xFF, ie invert
              dp[w+1] ^= 0xFF;    // G
              dp[w+2] ^= 0xFF;    // R
            }
          }
          dp -= pitch;  // Subtract the pitch of one line (in bytes, Daft RGB), one raster line down.
        }
      }
    }
  }
  return dst;
}

The new Bouncing walls demo implements bidirectional sweeping inversion both horizonally and vertically.
Implemented on RGB or only the Y channel on YUV frames.
EDIT: Inversion meaning eg Black<-->White.
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 8th December 2016 at 12:34.
StainlessS is online now   Reply With Quote
Old 1st February 2012, 21:50   #10  |  Link
jmac698
Registered User
 
Join Date: Jan 2006
Posts: 1,862
Guess what, I found my visual studio installation - yes I can actually try this stuff now (it's a big joke around here, that I would never install vs)
jmac698 is offline   Reply With Quote
Old 2nd February 2012, 13:25   #11  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,984
Glad to hear it, if you find any of the above unclear, let me know.
You should find CPP interface requires a lot less messing about.

EDIT: I hear that you are a malware menace.
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???
StainlessS is online now   Reply With Quote
Old 4th February 2012, 18:17   #12  |  Link
jmac698
Registered User
 
Join Date: Jan 2006
Posts: 1,862
No,
I think someone clicked the wrong download link at sendspace. Though it's a joke to us, rumours should be stopped in case anyone else reads.
Easy solution, don't use Sendspace. At least I'm glad I didn't use megaupload

infecting your brain with my thoughts...
jmac698 is offline   Reply With Quote
Old 7th July 2012, 11:00   #13  |  Link
jmac698
Registered User
 
Join Date: Jan 2006
Posts: 1,862
Hey S,
So I finally got around to playing with this (only took 8 months!), and it won't compile.
I'm using vs08. I made a new, empty win32 console, added all your headers and source, msgs:
Code:
example.cpp(377) : error C2664: 'OutputDebugStringW' : cannot convert parameter 1 from 'const char [39]' to 'LPCWSTR'
1>        Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
example.cpp(610) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
Do I need to see the wizard?

Fix the 2nd with
Code:
const int wstep = (vi.IsRGB24()) ? 3 : 4; // 3 bytes for RGB24, & 4 for RGB32.
The first needs some kind of conversion to a unicode string.
Code:
#define AVISYNTHNAME  L"Example"
didn't work

Last edited by jmac698; 7th July 2012 at 11:14.
jmac698 is offline   Reply With Quote
Old 7th July 2012, 11:22   #14  |  Link
Groucho2004
 
Groucho2004's Avatar
 
Join Date: Mar 2006
Posts: 3,896
Quote:
Originally Posted by jmac698 View Post
I made a new, empty win32 console,
???
The source is for a plugin, therefore you have to create a DLL. Also, VS2008 creates Unicode builds by default, you'll want a MBCS project.
Groucho2004 is offline   Reply With Quote
Old 7th July 2012, 11:25   #15  |  Link
jmac698
Registered User
 
Join Date: Jan 2006
Posts: 1,862
I followed the instructions at http://avisynth.org/mediawiki/Filter..._VC.2B.2B_2005
Code:
Menu: fiIe -> Create new project.
Select Win32 console appication.
Enter name of your new project and press OK.
You will in Win32 Appcilation Wizard. Press Application Settings (left panel).
Select Application Type as DLL (but it may be console too).
At Additional options select "Empty project"
Copy files to project folder with Explorer.
Actually the wizard crashes halfway through, maybe I need to update IE

Project, Properties, Configuration Properties, General,
Configuration type=dll
MFC yes
ATL no
Char Set Unicode

Last edited by jmac698; 7th July 2012 at 11:29.
jmac698 is offline   Reply With Quote
Old 7th July 2012, 13:10   #16  |  Link
jmac698
Registered User
 
Join Date: Jan 2006
Posts: 1,862
Ok, if I change Unicode to MCBS in there it will work, but I get a lot of warnings about printf being unsafe.
jmac698 is offline   Reply With Quote
Old 7th July 2012, 14:03   #17  |  Link
Groucho2004
 
Groucho2004's Avatar
 
Join Date: Mar 2006
Posts: 3,896
Quote:
Originally Posted by jmac698 View Post
Ok, if I change Unicode to MCBS in there it will work, but I get a lot of warnings about printf being unsafe.
All "printf()" are commented out, are you by any chance talking about "sprintf()"?
Either way, you can ignore it (or disable that warning).

Apparently M$ thinks that developers have become more stupid over time and don't know any more that they have to allocate a buffer for the string.
Groucho2004 is offline   Reply With Quote
Old 7th July 2012, 15:34   #18  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,984
@Jmac

Ah, finally bit the bullet.

@Grouchy

Thanx for taking care of shop.
Dang, so that's the reason MS recons it's deprecated. Had wondered about that.
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???
StainlessS is online now   Reply With Quote
Old 7th July 2012, 16:19   #19  |  Link
kemuri-_9
Compiling Encoder
 
kemuri-_9's Avatar
 
Join Date: Jan 2007
Posts: 1,348
Quote:
Originally Posted by Groucho2004 View Post
Apparently M$ thinks that developers have become more stupid over time and don't know any more that they have to allocate a buffer for the string.
they really want you to use the _s version which also specifies the size of the buffer to avoid the potential of a buffer overwrite that'll corrupt memory. it's more so a security issue rather than they think you're stupid (though, stupidity is probably a factor)
__________________
custom x264 builds & patches | F@H | My Specs
kemuri-_9 is offline   Reply With Quote
Old 7th July 2012, 18:00   #20  |  Link
SEt
Registered User
 
Join Date: Aug 2007
Posts: 374
What they really want is to bind you to MS compiler since most _s functions are non-standard MS extensions. The only exception I can think of is gets_s that replaces gets in C11.
So, don't worry – it's one of the warnings you should permanently suppress in all your projects if you care about portability.
SEt is offline   Reply With Quote
Reply

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 00:23.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2018, vBulletin Solutions Inc.