Log in

View Full Version : One frame in -- Two frames out | How?


525/60
28th March 2007, 06:54
Taking the simplest example I can think of, how would one modify the Invert filter sample so that it copies each frame and inverts each frame and sends them both out -- two frames for each frame in. Kind of like SimpleSample and Invert in one.

The reason I ask is because I am trying to understand how SeparateFields works. I am writing a filter called BobInPlace that only modifies the bottom field. What it does does not make sense unless it is followed immediately by SeparateFields. Rather than relying on the user to understand that, I'd rather the filter just separate the fields itself. Studying field.cpp isn't helping me.

Stephen

Leak
28th March 2007, 08:11
Taking the simplest example I can think of, how would one modify the Invert filter sample so that it copies each frame and inverts each frame and sends them both out -- two frames for each frame in. Kind of like SimpleSample and Invert in one.
While I haven't written an AviSynth filter in ages, it works something like this:

You take the number of frames in the input clip fed to your filter, double it and return it as the number of frames in the clip you return from your filter.

In GetFrame, you just take the lowest bit of the frame number n that's passed in (modulo 2 or binary-and 1) and select which field to return based on that. Then you halve n (or shift it right one bit) and request that frame from your input clip to work on.

Essentially, you give each frame you produce a new number (and adjust the length of the clip you produce accordingly) that can be used to calculate the input frame number to use. That way, you still only ever return one frame per GetFrame call, but GetFrame will simply be called more often by the next filter.

525/60
28th March 2007, 15:29
@Leak

If I combine what you are saying with the avisynth code for SeparateFields, I might begin to understand it:
PVideoFrame frame = child->GetFrame(n>>1, env);
Perhaps that corresponds to this:
Then you halve n (or shift it right one bit) and request that frame from your input clip to work on.
and then this way of determining whether we have the topfield:
const bool topfield = (child->GetParity(n)+n)&1;
corresponds to this:
In GetFrame, you just take the lowest bit of the frame number n that's passed in (modulo 2 or binary-and 1) and select which field to return based on that.Only here it was done in reverse order, 1) shifting n to the right one bit within GetFrame and 2) determining which field we have.

I know how to adjust the length of the clip. I am not sure how to return the frames. SeparateFields uses the source frame as the destination frame because it does not change any pixels. Whereas I am alternately passing through a line and then filtering a line of pixels:
for (int x = 0; x < row_sizeY; x++) dstpY[x] = srcpY[x];
srcpY += src_pitchY;
dstpY += dst_pitchY;

for (int x = 0; x < row_sizeY; x++) dstpY[x] = (srcpY[x]+srcpY[x-2*src_pitchY])>>1;
srcpY += src_pitchY;
dstpY += dst_pitchY;
Perhaps I am going about it wrong, because what I really need to do is read in one field at a time and alternate what I do with that field based on whether it is the top field or the bottom field?

Or if I went back to my original question regarding a Simple-InvertFrameFilter, how would I distinguish between my source frame number and the two frame numbers I am sending out?

Guest
28th March 2007, 18:09
Are you aware that you can use env->Invoke to internally run the SeparateFields filter so that it is transparent to the user? Your filter could receive the separated clip internally and then work on that.

525/60
28th March 2007, 19:50
@neuron2
No, I did not know that.

This is as far as I can get trying to merge the code:

7014

Stephen

Guest
28th March 2007, 20:13
I have to head out on a business trip for a few days. If noone's got you going by the time I come back I'll have a look at it and get you going.

Fizick
29th March 2007, 18:53
525/60,
I do not quite nderstand what do you want, but :

n is frame number of output clip.
n>>1 is frame number of source clip,

probably, you may use:

bool topfield = (child->GetParity(n>>1)+n)&1;

IanB
30th March 2007, 00:10
I assume you are trying to write a filter to do this...
TFF=GetParity()
SeparateFields()
E=SelectEven() # 0, 2, 4, ...
E=TFF?E:E.Invert()
O=SelectOdd() # 1, 3, 5, ...
O=TFF?O.Invert():O
Interleave(E, O)And you are confusing yourself by thinking Push model instead of Pull model.

Your filter gets asked for frame n. You calculate that you want source frame n/2. You need to GetParity(n/2) to see if Odd n or Even n is the bottom field. You are currently doing GetParity(n) which is wrong!const bool topfield = (child->GetParity(n/2) ^ (n & 1));
If you calculate that input n is asking for a Top field just use SubFrame to extract that field from the input frame, you don't want to do a NewVideoFrame() here! This path will be a "zero cost filter".

If you calculate that n is asking for a Bottom field then you do your stuff. i.e. Get a NewVideoFrame, transcribe and invert the bottom field, then return dst.

As a performance boost you could check if the Src frame IsWriteable and use SubFrame to extract the bottom field at zero cost and then do a faster in place algorithm i.e. Srcp[x] ^= 255; If it is not writeable then you do the slower transcription algorithm. :search: for recent posts by Arda in this thread.