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 25th November 2012, 00:58   #1  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
Simple Source Filter. (RandomSource)

Code:
#include "windows.h"
#include "avisynth.h"

class RandomSource : public IClip {
private:
    const VideoInfo vi;
    bool  parity;
public:
    RandomSource(const VideoInfo& _vi,bool _parity) : vi(_vi), parity(_parity) {}
    ~RandomSource(){}
    void __stdcall GetAudio(void* buf, __int64 start, __int64 count, IScriptEnvironment* env) {}
    const VideoInfo& __stdcall GetVideoInfo() { return vi; }
    bool __stdcall GetParity(int n) { return (vi.IsFieldBased() ? (n&1) : false) ^ parity; }
    void __stdcall SetCacheHints(int cachehints,int frame_range) {};
    PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env);
};

PVideoFrame __stdcall RandomSource::GetFrame(int n, IScriptEnvironment* env) {
    PVideoFrame frame = env->NewVideoFrame(vi);
    BYTE* p = frame->GetWritePtr();
    int size = frame->GetPitch() * frame->GetHeight();
    for (int i=0; i<size; i+=4) {
        *(p+i+0) = rand() & 0xFF;   // B
        *(p+i+1) = rand() & 0xFF;   // G
        *(p+i+2) = rand() & 0xFF;   // R
        *(p+i+3) = 0;               // Alpha
    }
    return frame;
}

static AVSValue __cdecl Create_RandomSource(AVSValue args, void*, IScriptEnvironment* env) {
    VideoInfo vi;
    memset(&vi, 0, sizeof(VideoInfo));
    vi.width                    =640;
    vi.height                   =480;
    vi.fps_numerator            =24;
    vi.fps_denominator          =1;
    vi.num_frames               =10000;
    vi.pixel_type               =VideoInfo::CS_BGR32;
    vi.audio_samples_per_second =0;     // 0 means no audio
    vi.sample_type              =0;     // as of 2.5
    vi.num_audio_samples        =0;     // changed as of 2.5
    vi.nchannels                =0;     // as of 2.5
    vi.SetFieldBased(false);
    bool parity=false;
    return new RandomSource(vi, parity);
}

extern "C" __declspec(dllexport) const char* __stdcall AvisynthPluginInit2(IScriptEnvironment* env) {
    env->AddFunction("RandomSource","",Create_RandomSource, 0);
    return "`RandomSource' RandomSource plugin";
}
Memory usage constantly creeps upwards (in AvsMeter), am I doing wrong or is that normal.
(EDIT: Memory usage does max out so looks not to be buggy.)
If normal, is there a way of limiting memory usage within plugin, eg
SetCacheHints(CACHE_NOTHING, 0) or whatever, but as we are a source plugin, is it us that need to
do something for the SetCacheHints call ?

EDIT:
I would be quite happy with a single non-cached re-writeable frame.
Also, perhaps an int 'last' variable implemented in class, to track previously generated frame,
to avoid regeneration when called by another filter on the same frame number.
Want to use this as test clip generator to verify similar results when modding a filter
(in the immediate case for a ShowChannels update).

See Mediafire in sig below for dll + source.
__________________
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; 20th January 2018 at 19:52. Reason: name change
StainlessS is offline   Reply With Quote
Old 25th November 2012, 03:34   #2  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
This seems to implement the "remember previous frame generated" in 'last' variable but as caching insists on butting in, is untested.

Code:
#include "windows.h"
#include "avisynth.h"

class RandomSource : public IClip {
private:
    const   VideoInfo vi;
    bool    parity;
    int     last;           // remember last frame generated
    PVideoFrame frame;
public:
    RandomSource(const VideoInfo& _vi,PVideoFrame _frame, bool _parity) : vi(_vi), frame(_frame),parity(_parity), last(-1) {}
    ~RandomSource(){}
    void __stdcall GetAudio(void* buf, __int64 start, __int64 count, IScriptEnvironment* env) {}
    const VideoInfo& __stdcall GetVideoInfo() { return vi; }
    bool __stdcall GetParity(int n) { return (vi.IsFieldBased() ? (n&1) : false) ^ parity; }
    void __stdcall SetCacheHints(int cachehints,int frame_range) {}
    PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env);
};

PVideoFrame __stdcall RandomSource::GetFrame(int n, IScriptEnvironment* env) {
    n = (n < 0) ? 0 : (n >= vi.num_frames) ? vi.num_frames - 1 : n;     // Range limit
    if(n != last) {
        frame = env->NewVideoFrame(vi);                                 // create new frame
        BYTE* p = frame->GetWritePtr();
        int size = frame->GetPitch() * frame->GetHeight();
        for (int i=0; i<size; i+=4) {
            *(p+i+0) = rand() & 0xFF;   // B
            *(p+i+1) = rand() & 0xFF;   // G
            *(p+i+2) = rand() & 0xFF;   // R
            *(p+i+3) = 0;               // Alpha
        }
        last = n;                                                        // Remember last generated frame number
    }
    return frame;
}

static AVSValue __cdecl Create_RandomSource(AVSValue args, void*, IScriptEnvironment* env) {
    VideoInfo vi;
    memset(&vi, 0, sizeof(VideoInfo));
    vi.width                    =640;
    vi.height                   =480;
    vi.fps_numerator            =24;
    vi.fps_denominator          =1;
    vi.num_frames               =1000000;
    vi.pixel_type               =VideoInfo::CS_BGR32;
    vi.SetFieldBased(false);
    bool parity=false;
    PVideoFrame frame = env->NewVideoFrame(vi);         // Create initial frame
    return new RandomSource(vi,frame, parity);
}

extern "C" __declspec(dllexport) const char* __stdcall AvisynthPluginInit2(IScriptEnvironment* env) {
    env->AddFunction("RandomSource","",Create_RandomSource, 0);
    return "`RandomSource' RandomSource plugin";
}
__________________
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; 26th November 2012 at 17:41.
StainlessS is offline   Reply With Quote
Old 25th November 2012, 22:34   #3  |  Link
IanB
Avisynth Developer
 
Join Date: Jan 2003
Location: Melbourne, Australia
Posts: 3,167
Quote:
Originally Posted by StainlessS View Post
Memory usage constantly creeps upwards (in AvsMeter), am I doing wrong or is that normal.
(EDIT: Memory usage does max out so looks not to be buggy.)
If normal, is there a way of limiting memory usage within plugin, eg
SetCacheHints(CACHE_NOTHING, 0) or whatever, but as we are a source plugin, is it us that need to
do something for the SetCacheHints call ?

EDIT:
I would be quite happy with a single non-cached re-writeable frame.
Also, perhaps an int 'last' variable implemented in class, to track previously generated frame,
to avoid regeneration when called by another filter on the same frame number.
Want to use this as test clip generator to verify similar results when modding a filter
(in the immediate case for a ShowChannels update).
As a source filter you don't have a cache as you don't have a child.

The parent filter(s) above you will have a cache. With some trickery you could explicitly add a cache after your source filter then configure it, however there is no guarantee that the parent filter won't reconfigure it for their needs.

Under normal circumstances env->NewVideoFrame(vi); will deliver a freshly malloc'd chunk of memory until the pool for frame buffers reaches the SetMemoryMax size, then it will deliver the ""oldest"" unused chunk of memory. The pool is global to the whole script not just local to your source filter. And fiddling with the cache doesn't effect that behaviour.

As the primary owner of PVideoFrame frame; you could reuse it for each call as long as no parent filter has a reference to an instance of the frame, GetWritePtr returns zero when there are multiple references to signal the fail. And GetWritePtr increments the frame's sequence number each time it is successfully called.

Code:
...
    if(n != last) {
        BYTE* p = frame->GetWritePtr();               // try to reuse old frame
        if (!p) {
          frame = env->NewVideoFrame(vi);                 // ditch old frame and create a new frame
          p = frame->GetWritePtr();
        }
        int size = frame->GetPitch() * frame->GetHeight();
...


As a sample test filter it probably doesn't matter much, but the expectation for all Avisynth filters is that they return identical frame contents for a given frame number every time they are called. The above filter returns the same frame for subsequent call of a constant frame number but different random contents for return visits. AddGrain had a similar problem in the past, iirc it now remembers the rand seed for each frame it returns so it can regenerate the identical sequence next time it is needed.
IanB is offline   Reply With Quote
Old 26th November 2012, 00:47   #4  |  Link
kolak
Registered User
 
Join Date: Nov 2004
Location: Poland
Posts: 2,843
Quote:
Originally Posted by IanB View Post
As a sample test filter it probably doesn't matter much, but the expectation for all Avisynth filters is that they return identical frame contents for a given frame number every time they are called. The above filter returns the same frame for subsequent call of a constant frame number but different random contents for return visits. AddGrain had a similar problem in the past, iirc it now remembers the rand seed for each frame it returns so it can regenerate the identical sequence next time it is needed.
I had such an issue with ditheirng based on random noise It was used with encoder, which does store source information during 1st pass and than reports source change during 2nd pass. Good thing that this can be turned off- otherwise it would not encode 2nd pass
kolak is offline   Reply With Quote
Old 26th November 2012, 06:13   #5  |  Link
IanB
Avisynth Developer
 
Join Date: Jan 2003
Location: Melbourne, Australia
Posts: 3,167
@kolak,

Good point, although Avisynth only expects repeatability from filters within the current session, it is advantageous for many users to have the output repeatable across sessions as well.
IanB is offline   Reply With Quote
Old 26th November 2012, 07:00   #6  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
Thank you both very much for the input.
I shall implement the frame->GetWritePtr() mod and also give seed as an option, repeatable across sessions
(EDIT: Had intended to do that anyway, so that a test can be repeated).

Was in a hurry to get this working ok, as I need to test across multiple colorspaces/croppings and
also because of coordinates being variable down to a single pixel x/y/w/h, its a lot of testing needed.
(got a GScript/RT_Stats script to auto test at a range of coordinates to compare with a previous version).
Also very tricky coping with mod 1 coords in ALL colorspaces including 2.6 ones (although will not be testable
unless compiled for such [EDIT: Except Y8]).
Got to ensure that its all working ok, before I start adding the interlaced planar arg which will make it even
more tricky to deal with 2.6 colorspaces and mod 1 coords.

Shall post here any update to above simple source filter as I dont think I've seen anything similar, at least not in full.

Again, thanks.
__________________
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; 26th November 2012 at 07:41.
StainlessS is offline   Reply With Quote
Old 11th January 2013, 05:50   #7  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
This seems to work ok:

Code:
#include <windows.h>
#include <stdio.h>
#include <time.h>
#include "avisynth.h"

#define OUTBUG

#ifdef OUTBUG
    int dprintf(char* fmt, ...) {
    char printString[2048];
        char *p=printString;
        va_list argp;
        va_start(argp, fmt);
        vsprintf(p, fmt, argp);
        va_end(argp);
        for(;*p++;);
        --p;                                                            // @ null term
        if(printString == p || p[-1] != '\n') {
            p[0]='\n';                                                  // append n/l if not there already
            p[1]='\0';
            OutputDebugString(printString);
            p[0]='\0';                                                  // remove appended n/l
        } else {
            OutputDebugString(printString);
        }
        return p-printString;                                           // strlen printString
    }
#endif


class RandomSource : public IClip {
private:
    const   VideoInfo vi;
    bool    parity;
    int     last;                                                       // remember last frame generated
    PVideoFrame frame;
    //
    //
    const unsigned int UserSeed;                                        // User supplied or random (time(0))
    unsigned __int64 SetupSeed;                                         // Used to setup WELLRNG512 random bits
    //
    unsigned int state[16];                                             // need initialize state to random bits
    unsigned int index;                                                 // init should also reset this to 0
    //
    unsigned int GetSetupRand(void);
    void InitWELLRNG512(unsigned int n);    
    unsigned int WELLRNG512(void);  
    //
public:
    RandomSource(const VideoInfo& _vi,PVideoFrame _frame, bool _parity,unsigned int _userseed)
        : vi(_vi), frame(_frame),parity(_parity),UserSeed(_userseed), last(-1) {}
    ~RandomSource(){}
    void __stdcall GetAudio(void* buf, __int64 start, __int64 count, IScriptEnvironment* env) {}
    const VideoInfo& __stdcall GetVideoInfo() { return vi; }
    bool __stdcall GetParity(int n) { return (vi.IsFieldBased() ? (n&1) : false) ^ parity; }
    void __stdcall SetCacheHints(int cachehints,int frame_range) {}
    PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env);
};

PVideoFrame __stdcall RandomSource::GetFrame(int n, IScriptEnvironment* env) {
    n = (n < 0) ? 0 : (n >= vi.num_frames) ? vi.num_frames - 1 : n;     // Range limit
    if(n != last) {
        BYTE* p = frame->GetWritePtr();                                 // Try to reuse old frame
        if  (!p) {
            frame = env->NewVideoFrame(vi);                             // Ditch old frame and create a new frame
            p = frame->GetWritePtr();
        }
        InitWELLRNG512(n);                                              // init
        int i,size = frame->GetPitch() * frame->GetHeight();
        for (i=0; i<size; i+=4) {
            unsigned int rgb = WELLRNG512() & 0x00FFFFFF;
            *((unsigned int*)(p+i)) = rgb;
        }
        last = n;                                                       // Remember last generated frame number
    }
    return frame;
}


unsigned int RandomSource::GetSetupRand(void) {
//  http://en.wikipedia.org/wiki/Linear_congruential_generator
//  Numbers by Donald Knuth, MMIX.
//
//  X_n+1 equiv ( a * X_n + c ) % m
//
    unsigned __int64 a = 6364136223846793005;
    unsigned __int64 c = 1442695040888963407;
    // m = 2 ^ 64
    SetupSeed = (a * SetupSeed + c);                        // % m (2 ^ 64)
    return (unsigned int)(SetupSeed >> 32);                 // Hi 32 bits, (most randomized bits)
}


void RandomSource::InitWELLRNG512(unsigned int n) {
    SetupSeed = (n + 1) * 4562693 + UserSeed;               // init the setup seed (4562693 prime picked out of the hat)
    int i;
    for(i=0;i<13;++i)                                       // Kick it through a few iterations
        GetSetupRand();
    for(i=0;i<16;++i) {
        state[i]= GetSetupRand();                           // Initialise WELLRNG512
    }
    index = 0;                                              // All systems GO!
    for(i=0;i<7;++i)                                        // Kick main rand generator through a few iterations Too
        WELLRNG512();
}


unsigned int RandomSource::WELLRNG512(void) {               // return 32 bit random number
// Public Domain, Chriss Lomont @ http://www.lomont.org : Feb 8 2008.
    unsigned long a, b, c, d;
    a = state[index];
    c = state[(index+13) & 15];
    b = a^c^(a<<16)^(c<<15);
    c = state[(index+9) & 15];
    c ^= (c>>11);
    a = state[index] = b^c;
    d = a^((a<<5) & 0xDA442D24UL);
    index = (index + 15) & 15;
    a = state[index];
    state[index] = a^b^d^(a<<2)^(b<<18)^(c<<28);
    return state[index];
}


static AVSValue __cdecl Create_RandomSource(AVSValue args, void*, IScriptEnvironment* env) {
    int userseed = args[0].AsInt(0);                        // userseed defaults to 0 (ALWAYS SAME)
    if(userseed == -1)
        userseed = (int)(time(NULL));
#ifdef OUTBUG
    dprintf("RandomSource: Seed = %d (0x%08X)\n",userseed,userseed);
#endif
    VideoInfo vi;
    memset(&vi, 0, sizeof(VideoInfo));
    vi.width                    =640;
    vi.height                   =480;
    vi.fps_numerator            =24;
    vi.fps_denominator          =1;
    vi.num_frames               =24*60*60;
    vi.pixel_type               =VideoInfo::CS_BGR32;
    vi.SetFieldBased(false);
    bool parity=false;
    PVideoFrame frame = env->NewVideoFrame(vi);         // Create initial frame
    return new RandomSource(vi,frame, parity,(unsigned int)userseed);
}

extern "C" __declspec(dllexport) const char* __stdcall AvisynthPluginInit2(IScriptEnvironment* env) {
    env->AddFunction("RandomSource","[seed]i",Create_RandomSource, 0);
    return "`RandomSource' RandomSource plugin";
}
RandomSource(int "seed"=0)

Random seed if 'seed' == -1, [time(NULL)].
Uses fixed seed if not supplied (0).
Otherwise uses user supplied seed.

Random seed (-1), frames repeatable within current session,
Supplied seed (or default 0) , repeatable across sessions.

Creates 640x480@24FPS RGB32, 1 hour (86400 frames, 24*60*60).
__________________
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; 11th January 2013 at 21:48.
StainlessS is offline   Reply With Quote
Old 11th January 2013, 21:54   #8  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
Changed defaults, default seed now 0, so that user need NOT supply a seed to get repeatable frames across sessions.
Seed -1, now sets the randomized seed [time(0)].
Other supplied seeds set that value seed.

We also now, kick the main rand genny through a few iterations in init routine.

See updated previous post.

EDIT: Can anyone else see vertical lines in the random frames, or is it my imagination ?

EDIT: Closed VDubMod (100% zoom), opened in current VD, no vertical lines. Re-opened in VDMod again, lines gone. Go figure.
__________________
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; 11th January 2013 at 22:26.
StainlessS is offline   Reply With Quote
Old 29th October 2015, 01:28   #9  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
I dont seem to have provided this as a plugin, only source, so here is usable dll, See Mediafire in sig (32KB, Incl source)

Code:
RandomSource(clip c,Int "seed"=0)

RandomSource creates 640x480 24FPS RGB32 @ 24*60*60 frames (1 hour).

Seed, Default 0 ( = always same). -1, Random Seed, other supplied seeds set that value seed (again, same every time).
EDIT: No audio.

See Mediafire in sig below for dll + source.

EDIT: Now posted in Usage forum, with additional args for Length, width and Height:- https://forum.doom9.org/showthread.p...44#post1862844
__________________
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; 14th January 2019 at 19:15.
StainlessS is offline   Reply With Quote
Reply

Tags
source filter

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 10:50.


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