Log in

View Full Version : Humbly requested: Filter SDK / Easy filter sample


Pages : 1 [2] 3 4 5

Bidoche
19th March 2003, 00:18
@sh0dan

From the videoframe client perspective, is it a difference between starting at top left with positive pitch and starting at bottom left with a negative pitch ?

If current code can feed from that, RGB don't to have to be really flipped (just appear it is)

sh0dan
19th March 2003, 13:01
Negative pitch is a no-no internally in AviSynth - at least - much assembler would have to be rewritten. Let's just keep RGB bottom-up, with positive pitch - there is no need to make things more complicated than that.

Bidoche
20th March 2003, 22:40
@sh0dan

As expected, it's not possible... :'(

@siwalters

Here is the OOP version I promised...
... in 3.0 style, but besides it allowed me to skip the copy part, it don't change much.


class SimpleSampleParent : public GenericVideoFilter {
public:
SimpleSampleParent(PClip _child, int _SquareSize) : GenericVideoFilter(_child), SquareSize(_SquareSize) { }

virtual CPVideoFrame _stdcall GetFrame(int n)
//in 3.0 there is a distinction from CPVideoFrame and PVideoFrame
//C stands for const, those cannot be modified
{
PVideoFrame frame = chid->GetFrame(n);
//conversion a CPVideoFrame to a PVideoFrame
//does what is needed to allow modifications
//(I can develop if you want)

Process(frame); //call the filling method

return frame; //implicit cast from PVideoFrame to CPVideoFrame
}

protected:
// define the parameter variable
const int SquareSize;

virtual void _stdcall Process(PVideoFrame frame) = 0;

void _stdcall ByteSquareFill(BYTE * dstp, int pitch, int width, int height, BYTE fillPattern)
//method to fill a rect with a BYTE value
//used in RGB and YV12
{
for(int h = height; h --> 0; dstp += pitch)
for(int w = width; w --> 0; )
*(dstp + w) = fillPattern;
}

BYTE * _stdcall FindSquareLeftCorner(PVideoFrame frame, Plane plane, int BpP, int scaleFactor = 1)
{
Byte * result = frame->GetWritePtr(plane);
result += (frame->GetHeight(plane)>>1 - SquareSize>>1/scaleFactor) * frame->GetPitch(plane);
result += frame->GetRowSize(plane)>>1 - SquareSize>>1/scaleFactor * BpP;
return result;
}
};


class SimpleSampleRGB : public SimpleSampleParent {
//no distinction between RGB24 and RGB32
//I fill alpha with 255 too
//if that is unwanted make a special version for RGB32

public:
SimpleSampleRGB(PClip _child, int _SquareSize) : SimpleSampleParent(_child, _SquareSize) { }

protected:
virtual void _stdcall Process(PVideoFrame frame)
{
int BpP = vi.IsRGB32()? 4 : 3;
ByteSquareFill(FindSquareLeftCorner(frame, NOT_PLANAR, BpP), frame->GetPitch(), BpP*SquareSize, SquareSize, 255));
}
};


class SimpleSampleYUY2 : public SimpleSampleParent {
public:
SimpleSampleYUY2(PClip _child, int _SquareSize) : SimpleSampleInterleaved(_child, _SquareSize) { }

protected:
virtual void _stdcall Process(PVideoFrame frame)
{
BYTE * dstp = FindSquareLeftCorner(frame, NOT_PLANAR, 2);
int pitch = frame->GetPitch(NOT_PLANAR);
for(int h = SquareSize; h --> 0; dstp += pitch)
for(int w = SquareSize>>1; w --> 0; )
*((unsigned int *)dstp + w) = 0x80EB80EB;
}
};

class SimpleSampleYV12 : SimpleSampleParent {
public:
SimpleSampleYV12(PClip _child, int _SquareSize) : SimpleSampleParent(_child, _SquareSize) { }

protected:
virtual void _stdcall Process(PVideoFrame frame)
{
static const BYTE fillPatterns[] = { 235, 128, 128 };
static const int scaleFactor[] = { 1, 2, 2 };

for(int i = 3; i --> 0; )
Plane p = VideoFrame::IndexToPlane(i);
int s = scaleFactor[i];
ByteSquareFill(FindSquareLeftCorner(frame, p, 1, s), frame->GetPitch(), SquareSize/s, SquareSize/s, fillPatterns[i]);
}
}
};


AVSValue __cdecl Create_SimpleSample(const vector<AVSValue>& args) {

PClip clip = args[0]; //implicit conversions
int sq = args[1];
switch(clip->GetVideoInfo().GetColorSpace().id)
{
case I_RGB24:
case I_RGB32:
return new SimpleSampleRGB(clip, sq);
case I_YUY2:
return new SimpleSampleYUY2(clip, sq);
case I_YV12:
return new SimpleSampleYV12(clip, sq);
}
}

Si
21st March 2003, 18:55
Very interesting - if only I understood it :o

I had a go at trying to hack it to work in 2.5 but didn't get any where - is it possible to do it?

I mean can it be done at all? (or do you need the 3.0 enviroment to make SimpleSample OOP friendly?)

regards
Simon

Bidoche
22nd March 2003, 01:20
@siwalters

It is possible to do it with 2.5, but the code is longer and I am not as used to it.
And I didn't not wanted to copy the frames by myself (in fact I could have blitted them :p), 3.0 does it automatically (and I like automatic things (if you don't, you should)).

Please point to what you don't understand and I will try to provide explanations (please don't say everything, it won't get us anywhere :p)

Edit:

It occured to me that we can use BitBlit to fill the squares provided we fill a BYTE raw somewhere with the good pattern (and a 0 pitch).
This way RGB and YUY2 can even be more merged together.

Will see it tomorrow, it's getting kinda late here :p

@sh0dan

Please don't tell me 0 pitch is forbidden.

Si
22nd March 2003, 11:42
I won't say everything :o .

I didn't mean to distract you from 3.0 - please just ignore my request.

regards
Simon

Bidoche
22nd March 2003, 12:17
I can do it, no problem.
And besides sometimes I can use the distraction. :)

Bidoche
24th March 2003, 17:05
Well let's do some comments... :)

In the above code, I made two kind of transformations:
- one is the transformation of the original class into a parent class and some subclasses (ie using OOP legacy/polymorphism)
- the other is just a factorisation of the code, with the functions ByteSquareFill and FindSquareLeftCorner(which I am not so happy about it :/).

To perform the first, used the natural colorspace hierarchy :General --- Interleaved --- RGB --- RGB24
\ \ \-- RGB32
\- YV12 \- YUY2I guess everyone will agree that how colorspace are naturally grouped
(sometimes YV12 and YUY2 are better seen siblings but not often)

Looking at your code, you search for similitude :
- RGB24 and RGB32 both fill a memory rectangle with 255, then the fill code can be shared and each just need its own rectangle coordinates calculation .

- YUY2 and RGB (24 & 32) both fill a memory rectangle with a specified pattern (FFFFFFFF for RGB, I forgot for YUY2).
Then if I make sych a method it can be shared (and called by the RGB 255 fill method)

- YV12 fills memory blocks like RGB so I can reuse its method (factorisation)

so you have (in pseudo-code)
class parent {
void patternFill(some memory coordinates, pattern); //a factorisation
pattern bytePattern(int patternlength, byte ToMakeThePatternWith) //same thing
};

class interleaved {
virtual pattern makePattern(int length) = 0;
};

class interleaved {
virtual PVideoFrame GetFrame()... //getFrame imple
//relies on BitPerPixels(colorspace) to get memory coordinates right
//and call patternFill(makePattern)
};

class yuy2, rgb24, rgb32 {
virtual pattern makePattern(int length) //implementation
//if we set rgb32 alpha to 255 we merge rgb32 and rgb24 (I did this)
//use of the factorised bytePattern in rgb24 (and maybe 32)
};

class yv12 {
virtual PVideoFrame GetFrame...
//planes coordinates calcul
//call PatternFill(..., bytePattern) on each plane)
};

Is that better ?

Si
25th March 2003, 19:54
Cough Cough:)
Obviously a moderator and a 3.0 developer can do what they want :) but have you thought about putting this in a separate thread?

says Simon who then runs away to hide from a thunderbolt from above :)

sh0dan
25th March 2003, 21:53
@siwalters: Being moderator makes it possible to fix these things. :)

For discussions related to frametypes in Avs 3.0 - see this thread (http://forum.doom9.org/showthread.php?s=&threadid=49555).

Leuf
12th April 2003, 05:04
SimpleSample::SimpleSample(PClip _child, int _SquareSize, IScriptEnvironment* env) :
GenericVideoFilter(_child), SquareSize(_SquareSize) {


Could someone explain this to a poor C programmer who hasn't learned inheritance? I know enough to know it's inheritance, but the SquareSize(_SquareSize) has me stumped. I just need to understand well enough to add some more arguments, one of which is a string, the rest are all ints.

Si
12th April 2003, 11:09
class SimpleSample : public GenericVideoFilter {
int SquareSize;
string parameter2;

public:

SimpleSample(PClip _child, int _SquareSize, string _parameter2, IScriptEnvironment* env);

SimpleSample::SimpleSample(PClip _child, int _SquareSize, IScriptEnvironment* env) :
GenericVideoFilter(_child), SquareSize(_SquareSize), parameter2(_parameter2) {
...

AVSValue __cdecl Create_SimpleSample(AVSValue args, void* user_data, IScriptEnvironment* env) {
return new SimpleSample(args[0].AsClip(),
args[1].AsInt(0),
args[2].AsString(""),
env);
}


extern "C" __declspec(dllexport) const char* __stdcall AvisynthPluginInit2(IScriptEnvironment* env) {
env->AddFunction("SimpleSample", "c[SIZE]i[PARAM2]s", Create_SimpleSample, 0);

return "`SimpleSample' SimpleSample plugin";



Should show how to introduce a 2nd parameter.

AFAIK the SquareSize(_SquareSize) is just one of the ways to intialise variables and isn't anything clever or complicated (or how else would I be able to use it :) )

regards
Simon

Leuf
13th April 2003, 11:01
Yep, I figured it out. I just moved the initializing into the constructor, since I have about 15 arguments the line was pretty ungodly.

I think the next logical step for the sample filter would be to modify the existing pixels rather than just overwrite them with a color. Something simple like add 10 to green, iirc the vdub sdk does something like that.

Si
13th April 2003, 13:24
I think the next logical step for the sample filter would be to modify the existing pixels rather than just overwrite them with a color. Something simple like add 10 to green, iirc the vdub sdk does something like that.


...

if (vi.IsRGB24()) {

...

//Now enhance the greeness of a square in the middle of the frame

dstp = dst->GetWritePtr();
dstp = dstp + (dst_height/2 - SquareSize/2)*dst_pitch;

for (h=0; h < SquareSize;h++) {
for (w = dst_width/2 - SquareSize*3/2; w < dst_width/2 + SquareSize*3/2; w+=3) {

*(dstp + w + 1) = max(255,*(dstp + w + 1) + 10); // Increase Green value by 10 limiting it to 255 (assumes src already copied to dst)
}
dstp = dstp + dst_pitch;
srcp = srcp+ src_pitch;
}
}


(untested)

regards
Simon

Bidoche
18th April 2003, 00:22
@Leuf

In the initialiser list (ie the list between : and { ) you must initialise superclasses (if there are any) and you can initialise members too.
If you don't initialise members there, they are default initialised.
For int and other primitives types, the default init is a no op so it's cost nothing more, but with classes it's generally better to use initialisers.
And sometimes, you have to use them : when the variable is not assignable (ie cannot use = ) like const objects and some objects where copy has no meaning.

Sigmatador
1st May 2003, 20:29
is there a way to add text (debug information) on a PVideoFrame ?

sh0dan
1st May 2003, 21:42
The easiest way is to invoke the Subtitle filter.

IIRC the syntax is something like:

PClip result = env->Invoke(child, "Subtitle", AVSValue(text));
return result.GetFrame(n,env);

For more advanced output, have a look at Donalds fast and nice algorithm in Dup and Decomb.

Sigmatador
2nd May 2003, 14:20
oki thx ^^ i'll try this.

another (stupid) question:
if i need some operation on 2D-matrix (FFT/iFFT,DCT/iDCT,sum,product)
is there in avisynth some functions for this or do i need to include library (do you know a good one ?)

Bidoche
2nd May 2003, 14:45
There are no such things in avisynth.

You can use boost/uBlas to provide matrix. Only sum and product I fear, you would have to make FFT and DCT yourself.
I don't know of any library who provide those as well.

trbarry
2nd May 2003, 14:51
if i need some operation on 2D-matrix (FFT/iFFT,DCT/iDCT,sum,product)
is there in avisynth some functions for this or do i need to include library (do you know a good one ?)

My DctFilter() works by doing an 8x8 DCT, modding the values, and then using iDCT, using functions pilfered from Xvid. So you might use the source as a basis for a new filter. See:

www.trbarry.com/DctFilter.zip (src & dll)

- Tom

Sigmatador
2nd May 2003, 15:41
@Bidoche
I wrote the FFT function. it works fine but too sloooowwwww !! (so i didn't start to code the iFFT).
i heard that fftw (http://www.fftw.org) is a higly optimized FFT library, but i don't undestand how to use it (i started c++ 2days ago... noob inside ^^)

@trbarry
thanks a million ^^

edit1: oops an error:
identifier "_aligned_malloc" is undefined
pWorkArea = (short * const) _aligned_malloc(8*8*2, 128);
edit1b: _aligned_malloc isn't defined in my malloc.h (VCPP6.0 SP5)
:confused::confused::confused::confused:
edit1c: replaced by malloc(8*8*2) and everythingrules ^^

edit2: oohhh your code is clean, nice to read ^^
edit3: i suppose sse2 optimization is disabled for the same reason than xvid.

Sigmatador
3rd May 2003, 15:08
@siwalters
your simplescript is a great educationnal tool ^^. Very easy to learn every colorspaces and spatial filtering.
What about a TemporalSimpleScript ? ^^ (i started to read sansgrip code)

trbarry
3rd May 2003, 15:27
edit1: oops an error:
identifier "_aligned_malloc" is undefined
pWorkArea = (short * const) _aligned_malloc(8*8*2, 128);
edit1b: _aligned_malloc isn't defined in my malloc.h (VCPP6.0 SP5)

I just had that same error when installing VS6 sp5 under on a new XP system. I think it was fixed by also installing the asm processor pack, PP5. It got fixed somehow. ?? Aligned malloc is needed if you do SSE2 specific code which gives errors when things are not 16 byte aligned.

- Tom

sh0dan
29th May 2003, 10:29
Have a look at audio.cpp (http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/avisynth2/avisynth/audio.cpp?rev=1.16&only_with_tag=MAIN&sortby=date&content-type=text/vnd.viewcvs-markup) instead.

To make an audio filter, remove the GetFrame part and put in a
void __stdcall YourClass::GetAudio(void* buf, __int64 start, __int64 count, IScriptEnvironment* env) function.

Guest
31st May 2003, 03:26
_aligned_malloc() is part of the platform SDK.

snowmoon
15th July 2003, 04:22
Geocities appears to be hating me... I can't download the sample .zip file. * GOT IT - You might want to link it off your site since geocities won't allow direct inking from this site *


Thanks

Si
16th July 2003, 18:29
@Sigmatador (Sorry didn't realise thread had changed :( )
I was hoping someone else would do this :)

@wer
All the main source code is also available via Avisynth.org (http://www.avisynth.org/index.php?page=FilterSDK)


regards
Simon

cudmore
9th August 2003, 22:04
All the sample code is very helpful but I would like to write a filter that operates on more than one clip. Something like:

Dissolve(clip clip1, clip clip2 [,...], int overlap)

Does anyone have a pointer to sample code for writing a filter to operate on multiple clips?

I can't seem to be able to figure out how to access more than one clip in the GetFrame() method. All I can find are examples that operate on:

PVideoFrame src = child->GetFrame(n, env);

Where are the other clips when the filter takes multiple clips?

Thanks

Bob Cudmore

Si
29th August 2003, 00:43
@cudmore
I've given it a go and it seems I can get it to work.

So SimpleSample1.7 is available here (http://www.geocities.com/siwalters_uk/simplesample17.zip) (need to right-click and download as usual)

I've only modded the YUY2 code (cause 1 - I'm too lazy to do the YV12 :o and Avisynth doesn't work anymore in RGB on my computer :( )

regards
Simon

bkam
18th November 2003, 18:55
I have been looking at this thread, and I am also interested in writing filters. I have very little coding knowledge, however, so little that I don't know how one would even go about compiling / what program to use etc. From what I gather this is C (that's right, I don't even know C, but I am determined). So if someone could tell the tools needed to get started with this (since this is a beginners sticky), it would be really cool, like what programs you are using to compile etc. I hope it doesn't seem pointless to explain if I have never coded anything really, but everyone starts somewhere right? And I have coded assembly language for TI calculators for fun a few years ago, this code looks much nicer than that :D. But still I am a coding n00b, so any help is appreciated! Thanks!

Si
19th November 2003, 00:15
I use Microsoft Visual C++ to compile filters.

You probably can compile them with some flavour of MS .net but I've no experience with this (Hopefully someone else can comment)

You can't use any known free compiler, so unfortunately you'll have to fork out some money to start.:(



regards
Simon

MrTibs
26th January 2004, 17:03
I'm having trouble with this sample code. The code compiles fine but I can't load the finished DLL. So far, it seems to be caused by the avisynth.h file. I'm testing with Avisynth 2.5.0, is that the reason?
I'm using MSVC 5.0.

P.S. Thanks for the excellent example, it has been VERY helpful.

Si
26th January 2004, 21:55
AFAIK you need MSVC 6 or later to make Avisynth filters

regards
Simon

MrTibs
5th February 2004, 04:43
First I would like to thank everyone who have worked on the SimpleSample. It is helping a lot. However, considering that I don't own MASC 6, would it be possible to have a SimpleSample with the C interface using the YV12 color space?

morsa
15th February 2004, 07:30
Hello everyone,
Iīm trying to make my first avisynth filter and I have a big stupid problem.I just canīt figure out how to define a destination frame with 2x the original width and height.I've been looking into many filter sources but, no way I can't understand how the new dimensions are set.
Anybody could help me?
Take note I'm really dumb about coding C++ and using Avisynth code.
Thanks.

Si
15th February 2004, 15:58
See if the stuff in this thread helps - if not - come back :)

http://forum.doom9.org/showthread.php?s=&postid=392435#post392435

regards
Simon

morsa
18th February 2004, 03:53
It seems that vi.width = vi.width*2; vi.height = vi.height*2; isnīt working for me.I canīt get a double size.
In fact I used simplesample as framework and changed silly things but nothing happens.

tempetai
18th February 2004, 07:15
I believed they are read only properties. Why don't you use

Simpleresize(vi.width*2,vi.height*2)

morsa
18th February 2004, 08:46
Weīre not talking about scripting but coding in C++.
By this time I'm trying to make an Scale2x implementation for Avisynth for testing purposes (I'm thinking about coupling it with some kind of pre-prosesing filter or a mixture of algos) but I'm really stuck with this problem.I know it may sound trivial for most people here, but the lack of documentation and full examples is driving me nuts!
Thank you.



P.S: BTW whatīs the use of Subframe??

vcmohan
19th February 2004, 04:08
I had used Siwalters simple Sample to develop my transition plugins and am greatful to him. However the example of a square box removes all complexities involved in coding a YV12 frame. I am trying to resize such a frame and find in a hopeless situation as it is becoming more and more approx. Can the YV12 be more lucidly demonstrated

Si
20th February 2004, 07:04
@vcmohan
What sort of operation do you want an example of ?

regards
Simon

sh0dan
20th February 2004, 12:52
Originally posted by vcmohan
I am trying to resize such a frame and find in a hopeless situation as it is becoming more and more approx.

There is a thread about the topic. YV12 is no different than other colorspaces in regard to resizing.

Can the YV12 be more lucidly demonstrated
There is a bunch of stuff about ColorSpaces (http://www.avisynth.org/index.php?page=ColorSpaces) , Working with images (http://www.avisynth.org/index.php?page=WorkingWithImages), Data Storage in AviSynth (http://www.avisynth.org/index.php?page=DataStorageInAviSynth) and Planar Image formats (http://www.avisynth.org/index.php?page=PlanarImageFormat) at avisynth.org. There is also a wide variety of filters available with source - not to speak of all the internal filters. If you provided a clearer description of your problems it might be easier for us to help you.

vcmohan
21st February 2004, 03:26
Originally posted by siwalters
What sort of operation do you want an example of ?
Simon [/B]

I do reductions and rotatios. While reducing in x or y axis the adjacent pixels may be from different positions of original, the u and v values which as I understand are one value for two pixels entails re computing the original RGB values and re composing as Y U and V values. This I find as cumbersome, and a tedium of coding. May be I understood wrongly the format.

Si
21st February 2004, 20:26
This I find as cumbersome, and a tedium of coding

YV12 (and YUY2) aren't as simple and neat as RGB32 for simple pixel manipulation.

The advantage of working in YV12 or YUY2 comes when you just want to manipulate Y values and therefore you don't have to translate from RGB to Y and back again.

If your source is YV12 (e.g MPEG-2) or analog YUY2 capture then your filter can run a lot faster beacuse there are less bytes to process.

Once you start doing manipulation like your's maybe the speed gains are totally offset by the complexity involved.

regards
Simon

morsa
24th February 2004, 07:23
..

vcmohan
25th February 2004, 02:38
Originally posted by morsa
..
Is something missing? There was no text here

morsa
25th February 2004, 12:38
Could someone show me what's the way to copy YUY2 U and V planes from a source to a 2X destination frame.I lack the experience, can't find an example that works for my dead brain and I'm going nuts........................HeLp:D

Si
25th February 2004, 20:26
You could have a look at my ShowPixelValues filter (which is basically a type of point resize filter)

the code where I translate YUY2 to YUV is here
// Separate Y1 and Y2 values into their own 32bit "pixels"
// i.e double 16 130 18 131 becomes 16 130 16 131 18 130 18 131
for (h=0;h < (src_height);h++) {
for (w = ((src_width>>6)<<2)-4;w>=0;w-=4) {

*(dstp + (w*2) + 7 + (h * dst_pitch)) = *(dstp +w + 3 + (h * dst_pitch));
*(dstp + (w*2) + 6 + (h * dst_pitch)) = *(dstp +(w+2) + (h * dst_pitch));
*(dstp + (w*2) + 5 + (h * dst_pitch)) = *(dstp +w + 1 + (h * dst_pitch));
*(dstp + (w*2) + 4 + (h * dst_pitch)) = *(dstp +(w+2) + (h * dst_pitch));
*(dstp + (w*2) + 3 + (h * dst_pitch)) = *(dstp +w + 3 + (h * dst_pitch));
*(dstp + (w*2) + 2 + (h * dst_pitch)) = *(dstp +w + (h * dst_pitch));
*(dstp + (w*2) + 1 + (h * dst_pitch)) = *(dstp +w + 1 + (h * dst_pitch));
*(dstp + (w*2) + (h * dst_pitch)) = *(dstp + w + (h * dst_pitch));


}
}


regards
Simon

morsa
26th February 2004, 00:00
Thanks Simon, really!!!!
Another question, what is >>6 and <<2??

Si
26th February 2004, 08:49
>> is the binary shift right operator and << the left one.
So x<<1 == x=x*2 and x>>1 == x=x div 2.
and x<<2 == x=x*4 and x>>2 == x=x div 4 etc.
therefore x>>6 == x=x div 64.


regards
Simon