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. |
25th November 2012, 00:58 | #1 | Link |
HeartlessS Usurer
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"; } (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 |
25th November 2012, 03:34 | #2 | Link |
HeartlessS Usurer
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. |
25th November 2012, 22:34 | #3 | Link | |
Avisynth Developer
Join Date: Jan 2003
Location: Melbourne, Australia
Posts: 3,167
|
Quote:
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. |
|
26th November 2012, 00:47 | #4 | Link | |
Registered User
Join Date: Nov 2004
Location: Poland
Posts: 2,843
|
Quote:
|
|
26th November 2012, 06:13 | #5 | Link |
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. |
26th November 2012, 07:00 | #6 | Link |
HeartlessS Usurer
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. |
11th January 2013, 05:50 | #7 | Link |
HeartlessS Usurer
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"; } 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. |
11th January 2013, 21:54 | #8 | Link |
HeartlessS Usurer
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. |
29th October 2015, 01:28 | #9 | Link |
HeartlessS Usurer
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). 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. |
Tags |
source filter |
Thread Tools | Search this Thread |
Display Modes | |
|
|