Log in

View Full Version : pitch alignment


kassandro
24th February 2005, 11:01
If I generate a new frame with NewVideoFrame on a P4, then the frame pointer address is a multiple of 16. That's fine. However, GetPitch returns a number, which may not be a multiple of 16 even if the frame was created with alignment=16. This unexpected behavior was the reason for some hard to track SSE2/SSE3 crashes and should be corrected. Pitch and frame pointer should have the same alignment, otherwise the alignment is hardly usable.
Also there should be an SSE3 flag for GetCPUFlags, but this is less important.

Edit: The unaligned pitch seems only to occure on the chroma planes, but to make optimal use of SSE2/SSE3 the pitch of these planes should also be a multiple of 16.

Leak
24th February 2005, 13:12
Originally posted by kassandro
Pitch and frame pointer should have the same alignment, otherwise the alignment is hardly usable.

While we're on the topic - the same thing already happens if you use Crop without "align=true"; maybe "align=true" should be made the default?

Edit: even worse, frames returned from Crop might not even be aligned at all, of course...

np: Mr. Lif - Jugular Vein (Emergency Rations)

ARDA
24th February 2005, 15:42
NewVideoFrame(vi,64)
or
NewVideoFrame(vi,32)

By that way you can be sure you have your new frame with every plane with at minimun 16b aligned.
But you can't be sure about your source clip, so you'll have to test; if not you have a problem and should open branches of your algo.
I guess you are trying to get better perfomance in removegrain.
Movdqu will kill most of your efforts and you can't do pmaxub or pminub over memory because there will be an exception.
Good luck
I hope this can be usefull
ARDA

kassandro
24th February 2005, 16:48
Originally posted by ARDA
NewVideoFrame(vi,64)
or
NewVideoFrame(vi,32)

Many thanks for the information. That should do it for my filter, but it can't resolve Leak's problem with crop. I hope that in version 2.5.6 all planes are 16b aligned with NewVideoFrame(vi,16). Currently the chroma planes seems to have half the alignment of the y plane.


I guess you are trying to get better perfomance in removegrain.

No, currently I am experimenting a little bit with motion compensated cleaning. Doing it at the pixel level did give poor results. Hence, to do it on half pixel level I needed filters magnifyby2 and shrinkby2, which are as fast as possible and which have the additonal property that shrinkby2.magnifyby2 leaves the clip unchanged. Here I wanted to do an aligned 16b write to a newly created frame and was stunned to get cpu exceptions.


Movdqu will kill most of your efforts and you can't do pmaxub or pminub over memory because there will be an exception.

Yes movdqu seems to be slower than two times movq, but with SSE3 you have the lddqu instruction, which is almost as fast as aligned reading if reading is done along a sequential pattern. That boosts RemoveGrain performance by about 70-80% with respect to the SSE version, though I have yet to confirm this with more thorough benchmarks.
The unaligned pmaxub etc. with the key mistake, why my first SSE2 version didn't work.

@Leak:
Of course with frames from other filters I was more cautious. I always checked whether the address was aligned. But now I know that I have alos to check the pitch, which I thought that it should be always aligned. But hopefully this will become true in the future.

IanB
26th March 2005, 09:52
Yes, the default alignment is 16 for the luma plane, 8 for the chroma planes (always gunna be half luma). I have on my personal todo list to test bumping the default alignment to 32 (16 for chroma). A few trickey places deliberatly force non-alignment so these need tracking and ratifying. Just need some time.

Crop(align=True) will inherit any new default alignment. Setting align=True makes a crop cost a set of blits, by default it is zero per frame cost. I don't want to make slow the default, only a few special plugins need alignment.

IanB

kassandro
27th March 2005, 00:17
Originally posted by IanB
Yes, the default alignment is 16 for the luma plane, 8 for the chroma planes (always gunna be half luma). I have on my personal todo list to test bumping the default alignment to 32 (16 for chroma).
I would rather prefer to have the same alignment for all planes. Why do we want alignment? Answer: because we want fasted processing without vasting too much memory. If this answer is correct, an alignment of 8 doesn't make sense for a P4. Actually, if you use SSE2 instructions with addresses not a multiple of 16 you get an address violation.

If we always demand that the alignment of the chroma planes is half that of the luma plane, then we should also demand that the yv12 chroma pitch is always half the luma pitch.

Bidoche
27th March 2005, 11:02
Originally posted by kassandro
I would rather prefer to have the same alignment for all planes. Why do we want alignment? Answer: because we want fasted processing without vasting too much memory. I think it's the way because VFW pass YV12 with luma 4-aligned and chroma 2-aligned, and the same scheme was reproduced.

I was aware of the pb as well, so 3.0 use 16 bytes alignment for all memory blocks, and pitchs are 16 aligned too. (ie all scanlines are 16-aligned)

IanB
27th March 2005, 14:55
Originally posted by kassandro
I would rather prefer to have the same alignment for all planes. Why do we want alignment? Answer: because we want fasted processing without vasting too much memory. If this answer is correct, an alignment of 8 doesn't make sense for a P4. Actually, if you use SSE2 instructions with addresses not a multiple of 16 you get an address violation.And this is why I will be trying to give a minimum 16 alignment on the chroma planes where possible.

Remember nothing on earth can guarantee the output alignment of some arbitary upstream plugin. Where possible internal Avisynth routines attempt to provide best attempt alignment.

Unfortunatly VFW delivers and expects YV12 data as a single block in a particular layout, this layout in not alignment optimal.

On balance the per frame cost of doing a set of blits just to correct alignment can always be better absorbed into the filter in question.(Unaligned Read + Aligned Write) + Aligned Read > Unaligned Read
however
(Unaligned Read + Aligned Write) + Aligned Read*N < Unaligned Read*N for N > 2 or 3
BUT! A clever implementation would be simply
Unaligned Read + Aligned Write + Aligned Read*(N-1)If the planes are unaligned then something always has to take the hit.

If we always demand that the alignment of the chroma planes is half that of the luma plane, then we should also demand that the yv12 chroma pitch is always half the luma pitch.
Although AviSynth currently works this way good programing shouldn't assume relative plane alignment.

You should always retrieve the attributes for luma and chroma planes separatly. With 3.0 and support for other planer formats even the conformant chroma plane assumption may become invalid.

IanB

Bidoche
27th March 2005, 15:25
Originally posted by IanB
You should always retrieve the attributes for luma and chroma planes separatly. With 3.0 and support for other planer formats even the conformant chroma plane assumption may become invalid.3.0 doesn't even let you the opportunity to (wrongly) assume anything about that.
It always gives you ptr, pitch, width and height at the same time (in a struct)

kassandro
27th March 2005, 17:30
Originally posted by IanB

Unfortunatly VFW delivers and expects YV12 data as a single block in a particular layout, this layout in not alignment optimal.

Ok, that's the answer. Now I understand also Bidoche's earlier explanation. When Avisynth delievers a yv12 frame to an encoder, it must convert the frame to this particular layout. Hence it is very reasonable that Avisynth by default creates frames, which are VfW compliant. On the other hand, I thought that the alignment of a frame created by NewVideoFrame is processor dependent. This would contradict the philosophy of VfW compliant default frames.

Bidoche
27th March 2005, 21:51
Originally posted by kassandro
When Avisynth delievers a yv12 frame to an encoder, it must convert the frame to this particular layout. It's the other way around. When exporting, doing one or 3 blits does not matter, you will have to blit anyway.
It's when you get frame from a VFW decoder that if you can directly use the layout as is, that you save blits.

3.0 tries as well to save the blits on YV12 input but it only works with width multiple of 32 (still a relatively common case).

kassandro
28th March 2005, 09:52
Originally posted by Bidoche
It's the other way around. When exporting, doing one or 3 blits does not matter, you will have to blit anyway.
It's when you get frame from a VFW decoder that if you can directly use the layout as is, that you save blits.

I see. This sounds very reasonable. But then Avisource and DirectshowFilter should have a variable align - just like crop, which ensures that everything is optimally aligned. If it is not so from the get go, then these filter have to do a bitblt, if align=true - just like crop(align=true). The default should, of course, be align=false - just like crop. On the other hand, if a frame is created with NewVideoFrame, it should get the optimal alignment by default, whence Mpeg2Source will automaticly generate optimally aligned frames.

IanB
29th March 2005, 08:23
Adding Align=True randomly to various filters is not a very graceful solution. Having Filters optimally use the input frame as best they can gives far greater gain. And doing so means a filter always works.

If you really need to force plane realignment use Crop(0,0,0,0,True).

Although the code is currently not quite right, I will fix it to work correctly. Note to others:- Alignment cannot be determined in the constructor, alignment is a per frame attribute. (Think about C=A+B or C=Interleave(A, B) etc)

Many cases requiring realignment need just the chroma planes aligned, but the sledge hammer approach touted here always required 3 blits to correct the alignment. Maybe in 3.0 plane buffers could be decoupled so a single plane can be manipulated independantly of it's peers.

IanB

Bidoche
29th March 2005, 09:48
Originally posted by IanB
Maybe in 3.0 plane buffers could be decoupled so a single plane can be manipulated independantly of it's peers. That's exactly how it is done.
I have an object (frame buffer) to hold video (ot not) data.
And YV12 simply use 3 of them

IanB
8th May 2005, 05:25
kassandro,

You have your wish, the May 6th release does priority alignment of the chroma planes for YV12.

NewVideoFrame(vi, 16) for YV12 gives 16 alignment for chroma planes (and 32 for the luma) for interleaved formats the alignment is vanilla 16 as before.

IanB

kassandro
8th May 2005, 08:15
Originally posted by IanB

You have your wish, the May 6th release does priority alignment of the chroma planes for YV12.

NewVideoFrame(vi, 16) for YV12 gives 16 alignment for chroma planes (and 32 for the luma) for interleaved formats the alignment is vanilla 16 as before.

Hmmm, following ARDA I currently use NewVideoFrame(vi, 32), which seems to be identical to the new NewVideoFrame(vi, 16). This certainly avoids alignment crashes. However, for better speed I also would like to receive well aligned frames from other filters and this can be achieved if NewVideoFrame(vi) = NewVideoFrame(vi, 16) (the new one with 16 byte chroma alignment) on a P4 or an Athlon64. Then also old filters would automaticly creat aligned frames and I can use the routines for aligned access, which are substantially faster than the unaligned ones, if SSE2 is used.

IanB
8th May 2005, 09:25
kassandro,

... NewVideoFrame(vi) = NewVideoFrame(vi, 16) ...

And I forgot to mention the default alignment is 16, so unless filters go out of there way to screw with alignment you should get 16 aligned input chroma planes when using the latest 2.5.6

Of course to be backwards compatible you need to still request 32 aligned to avoid alignment traps on older versions. Can't have everything.:rolleyes:

IanB

kassandro
8th May 2005, 12:29
IanB,
it was the best you could do. For a transition tinme, say, until 2006, I have to use NewVideoFrame(vi, 32) and waste a little bit of memory, but I immediately get better aligned frames, if version 2.5.6 is installed.
Thanks.

CyberGuy
11th May 2005, 21:06
The following script causes the output to have a video pitch of 736 instead of 720. The souce is 720x576. I'm using a patched version of DGDECODE.DLL that does not cause this aligment problem. If I comment out the LanczosResize operation, then the video pitch is 720. If resizing to 704x304, then the video pitch is 704, so this appears to happen when width is not changed.

LoadPlugin("DGDECODE.DLL")
Source = Mpeg2Source("VIDEO.D2V", iDCT=4, CPU=0)
Source = Trim(Source, 70, 3145)
Source = Crop(Source, 0, 76, -0, -76)
Source = LanczosResize(Source, 720, 304, Taps=8)
Return(Source)

Leak
11th May 2005, 21:35
Originally posted by CyberGuy
The following script causes the output to have a video pitch of 736 instead of 720. The souce is 720x576. I'm using a patched version of DGDECODE.DLL that does not cause this aligment problem. If I comment out the LanczosResize operation, then the video pitch is 720. If resizing to 704x304, then the video pitch is 704, so this appears to happen when width is not changed.

Well, after some changes the luma plane will be mod 32-aligned in the current AviSynth betas, and since 720/32 gives 22.5 the 720 is rounded up to 736 which is evenly divisible by 32 - so I would call that expected behaviour and not a bug.

The pitch must always be large enough that the next line starts beyond the end of the current one, but for alignment purposes it can be larger than neccessary - for example, if you do a SeparateFields the pitch of the returned frames will be twice the size it was before, even though the line width didn't change...

np: Autechre - Part 5 (XLTronic Radio 25.01.05)

CyberGuy
11th May 2005, 22:52
Originally posted by Leak
Well, after some changes the luma plane will be mod 32-aligned in the current AviSynth betas, and since 720/32 gives 22.5 the 720 is rounded up to 736 which is evenly divisible by 32 - so I would call that expected behaviour and not a bug.

The pitch must always be large enough that the next line starts beyond the end of the current one, but for alignment purposes it can be larger than neccessary - for example, if you do a SeparateFields the pitch of the returned frames will be twice the size it was before, even though the line width didn't change...

np: Autechre - Part 5 (XLTronic Radio 25.01.05)
Sorry, I had read mod 16 in other posts. I was able to get around the problem by using the following:

LoadPlugin("DGDECODE.DLL")
Source = Mpeg2Source("VIDEO.D2V", iDCT=4, CPU=0)
Source = Trim(Source, 70, 3145)
Source = Crop(Source, 0, 76, -0, -76)
Source = AddBorders(Source, 16, 0, 0, 0, $000000)
Source = LanczosResize(Source, 736, 304, Taps=8)
Return(Source)

MENCODER.EXE VIDEO.AVS -nosound -ovc raw -vf crop=720:304:17:0,format=i420 -of rawvideo -o VIDEO.YUV