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 12th May 2013, 20:51   #1  |  Link
jordanh
Registered User
 
Join Date: Apr 2013
Location: Vienna, Austria
Posts: 48
about GetPitch() and non "multiple of 8" resolutions

It seems that a lot or most, or even all filters have problems when it comes to picture resolution widths that are not multiples of 8. I am not sure about this, thats why i made a topic out of it.

As i am currently developing a Source Filter that of course targets to be compatible to virtually "all" other AVisynth filters, i got to this problem:
720x576 = OK, 1920x1080 = OK, 852x480=FAIL

I needed to experiment more than i liked in order to find out, that all my problems are about about the Pitch. I always assumed that

Code:
width*height*bytesperpixel = buffersize //incorrect
but thats WRONG. The correct formula can only be done using the pich:

Code:
Height*Pitch = buffersize //correct
Which means for source plugins, they need to find out the pitch dynamically for each resolution and send avisynth the bytes it needs.

What i dont understand is, why video engines like AVISynth and also Carboncoder actually have something like a pitch. (in carbon they call it "stride") What is it good for? - i know that encoders need it that way, or maybe decoders decode it that way.. but is it really neccessary within a framework?
Everything seems to come down to either a multiple of 8 or a multiple of 16. AVISynth seems to keep a stride of multiple of 8.

When i do env->NewVideoFrame(InputVideoInfo), and then GetPitch() on this frame, it will return the next bigger value than the width that a multiple of 8.
e.g. 852 will have a stride of 856*2 (=1712) for yuy2 colorspace (2 bytes per pixel)
and one cannot change that.

Here is some picture visualizing the pitch (its the green bar on the right)

input video 852x480 from carbon where pitch is a multiple of 16, so the pitch is a 864x480 frame



...a frame dump of avisynth would have a smaller green bar because the pitch needs to be only 8 bytes less.

The question at this time is, if it can be that i am right and nearly all plugins have troubles with sources thats width isnt a multiple of 8. By now i only tested directshowsource and the Convertto functions. All had problems.
Can i write my source filter in a way that i provide a source that 852 in the "right way" so that the user does not need to do the resize in the avs script?

Harry

Some additional information:
___________________________________________________________________________________________________________________________________________________

Here is how i copy the frames: (unit->stride is actually the pitch)

Code:
	for (int i=0; i<unit->height;i++){
		unsigned char* _in = (unsigned char*) (in_ptr + (i * m_carboncode_inputpitch));//source
		unsigned char* _out = (unsigned char*)(out_ptr + (i * m_avisynth_inputpitch));//target
		memcpy(_out,_in,unit->width*2);//*2 = hardcodec aligned yuv422 support (2 bytes per pixel)
	}



While i am developing my source filter, of course i always prove where things go wrong. I think i proved that the ConvertTo...() functions and the monitor filter have the problems, and i cannot really help them besides resizing the picture to an easy "by 8" resolution

1) "Hello World" just returns the same clip than the Source Plugin:


Uploaded with ImageShack.us

2) When we use some filterint, the picture lines are shifted


Uploaded with ImageShack.us

3) We can workaround this by resizing the picture before doing other filtering


Uploaded with ImageShack.us

4) Just for fun, we test if tht monitor plugin is able to process the original resolution while Carboncoder on the right side shows the finally returned clip


Uploaded with ImageShack.us

5) When we use the monitor after the resize, it works as expected


Uploaded with ImageShack.us
jordanh is offline   Reply With Quote
Old 12th May 2013, 21:10   #2  |  Link
Reel.Deel
Registered User
 
Join Date: Mar 2012
Location: Texas
Posts: 1,084
Hello jordanh, I don't know much about programming but I had a similar situation when I was testing out a plugin.
Addional link. Hope it helps.
Reel.Deel is offline   Reply With Quote
Old 12th May 2013, 22:30   #3  |  Link
jordanh
Registered User
 
Join Date: Apr 2013
Location: Vienna, Austria
Posts: 48
Hmm... thanks, that reminds me of the correct word for "multiple of 8": mod 8...

Thanks reel.deel, it seems like your thread just hardens the assumption that most filters have a bug here.

Any other experiences to this?

cheers,
Harry
jordanh is offline   Reply With Quote
Old 12th May 2013, 22:57   #4  |  Link
Youka
Registered User
 
Youka's Avatar
 
Join Date: Mar 2011
Location: Germany
Posts: 64
Image processing is expensive, so SIMD instructions are often used to speed tasks up.
SSE uses 128 bit = 16 byte registers, so 8 yuv2 pixels can be processed the same time.
AVX uses 256 bit = 32 byte registers, so 16 yuv2 pixels can be processed the same time.
I guess it have to do something with this.
Youka is offline   Reply With Quote
Old 13th May 2013, 04:42   #5  |  Link
IanB
Avisynth Developer
 
Join Date: Jan 2003
Location: Melbourne, Australia
Posts: 3,168
The current default memory alignment for Avisynth video structures is 16 bytes. This to provide SSE friendly memory addresses. This was 8 in earlier versions and may become 32 in future versions.

By default the address in memory of the 1st byte of each picture line will satisfy (int)Address & 15 == 0. This allows the use of fast MOVDQA instructions.

The Pitch or Stride is the distance from the start of one picture line to the start of the next and by default will be mod 16 in order to satisfy the condition above.

Various operations can effect this default behaviour, e.g a Crop() operation with a non mod 16 left value. The Crop() function has an optional Align=True argument that will blit unaligned picture contents into a new aligned picture structure. Of course doing this costs the memory copy time, but if a filter fails or runs slowly with unaligned memory it is necessary.

Also one must not assume any relationship between rowsize and pitch or that the pitch of different frames within a clip is consistent.

The optional align argument of the env-NewVideoFrame(vi, align); method allows overriding and increasing the default pitch. e.g you might specify 64 to be processor cache line aligned or 32 to be AVX instruction aligned. If you specify a negative align value you can force arbitrary pitch alignment, this option should be used with extreme caution, not all plugin authors correctly test input pointer alignment. The AVISource() filter use align=-4 to create a DIB compatible buffer to pass into the VFW API calls and avoid an extra input memory blit.

Filter code should always check input memory pointer alignment complies with the requirements of the code and fall back to an alternative unaligned code path. The unaligned code path must be functionally equivalent but need not be speed optimised. Bliting an unaligned input frame to an aligned copy is an option.


The IScriptEnvironment method :-

virtual void __stdcall BitBlt(BYTE* dstp, int dst_pitch, const BYTE* srcp, int src_pitch, int row_size, int height);

provides an ISSE optimised routine for copying rectangular blocks of memory (blitting).

Last edited by IanB; 13th May 2013 at 13:42. Reason: should -> must!
IanB is offline   Reply With Quote
Old 13th May 2013, 04:43   #6  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 5,791
Width & height can be changed in-situ by crop so using pitch is a must, also, pitch can change frame by frame in same clip (interleave might do this).

Oops, just beaten to it.
__________________
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 ???
StainlessS is online now   Reply With Quote
Old 13th May 2013, 12:59   #7  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,380
Quote:
Originally Posted by jordanh View Post
It seems that a lot or most, or even all filters have problems when it comes to picture resolution widths that are not multiples of 8.
...
I think i proved that the ConvertTo...() functions and the monitor filter have the problems
Quote:
Originally Posted by IanB View Post
Filter code should always check input memory pointer alignment complies with the requirements of the code and fall back to an alternative unaligned code path.
Ian, are you saying that ConvertToXXX() is deficient in this respect, or is something wrong with the frames generated by jordanh's source filter (which appears to take the pitch into account)?
__________________
GScript and GRunT - complex Avisynth scripting made easier
Gavino is offline   Reply With Quote
Old 13th May 2013, 14:00   #8  |  Link
IanB
Avisynth Developer
 
Join Date: Jan 2003
Location: Melbourne, Australia
Posts: 3,168
The YV12 path of ConvertToYUY2() outputs mod 32 pitch so it can do 16 pixels per loop. Line 132 of convert/convert_yuy2.cpp
Quote:
Originally Posted by IanB View Post
Also one must not assume any relationship between rowsize and pitch or that the pitch of different frames within a clip is consistent.
And must not assume any relationship between pitch of the luma planes and chroma planes for the planar formats.

You must use the GetPitch() method on each and every PVideoFrame you get.

Pitch torture test for filters.
Code:
...
A=SelectEvery(4, 0)
B=SelectEvery(4, 1).AddBorders(0,0,8,0).Crop(0,0,-8,0)
C=SelectEvery(4, 2).AddBorders(0,0,16,0).Crop(0,0,-16,0)
D=SelectEvery(4, 3).AddBorders(2,0,22,0).Crop(2,0,-22,0)
Interleave(A,B,C,D)
FilterUnderPitchStressTest(...)
...
IanB is offline   Reply With Quote
Old 30th May 2013, 18:51   #9  |  Link
jordanh
Registered User
 
Join Date: Apr 2013
Location: Vienna, Austria
Posts: 48
IanB is of course completely right. Thanks very much for explaining it so deeply.
My problem was that at initialisation of the transcode process, in the application that creates the avisynth env, i did this after initializing the avs script:

Code:
PVideoFrame analyseframe=env->NewVideoFrame(avisynthOutputVideoInfo);
m_outputstride = analyseframe->GetPitch();
Then i used this pitch also for frames that i pulled from the returned clip of the script.

I added this information to the cplusplus wiki.

Last question on this topic:

The following expression generates a frame with settings of the returned clip from a avs script:

Code:
*Video = env->Invoke("Import",AVSValue(args_userscript,1)).AsClip();
avisynthOutputVideoInfo = (*Video)->GetVideoInfo();
so why does this PVideoFrame have another pitch than a real frame thats created using

Code:
(*Video)->getFrame();
...

Also still there is the question why DirectshowSource and MonitorFilter also have problems with that resultion? (i only tested one file type, its hard to get something compatible to directshowsource)
jordanh is offline   Reply With Quote
Old 30th May 2013, 19:21   #10  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,380
Quote:
Originally Posted by jordanh View Post
The following expression generates a frame with settings of the returned clip from a avs script:
Code:
*Video = env->Invoke("Import",AVSValue(args_userscript,1)).AsClip();
avisynthOutputVideoInfo = (*Video)->GetVideoInfo();
so why does this PVideoFrame have another pitch than a real frame thats created using
Code:
(*Video)->getFrame();
env->NewVideoFrame(avisynthOutputVideoInfo) will create a frame with the default pitch appropriate to the frame width.

(*Video)->getFrame() will deliver a frame that in general depends on the filters used in the script (and may be different for each frame). For example, Crop() may have been used to create a subframe of a wider frame - this will still have the same pitch as the wider source frame.
__________________
GScript and GRunT - complex Avisynth scripting made easier
Gavino is offline   Reply With Quote
Reply

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 13:20.


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