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. |
12th May 2013, 20:51 | #1 | Link |
Registered User
Join Date: Apr 2013
Location: Vienna, Austria
Posts: 55
|
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 Code:
Height*Pitch = buffersize //correct 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 |
12th May 2013, 21:10 | #2 | Link |
Registered User
Join Date: Mar 2012
Location: Texas
Posts: 1,664
|
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. |
12th May 2013, 22:30 | #3 | Link |
Registered User
Join Date: Apr 2013
Location: Vienna, Austria
Posts: 55
|
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 |
12th May 2013, 22:57 | #4 | Link |
Registered User
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. |
13th May 2013, 04:42 | #5 | Link |
Avisynth Developer
Join Date: Jan 2003
Location: Melbourne, Australia
Posts: 3,167
|
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! |
13th May 2013, 04:43 | #6 | Link |
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
|
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 ??? |
13th May 2013, 12:59 | #7 | Link | |
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,431
|
Quote:
|
|
13th May 2013, 14:00 | #8 | Link | |
Avisynth Developer
Join Date: Jan 2003
Location: Melbourne, Australia
Posts: 3,167
|
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:
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(...) ... |
|
30th May 2013, 18:51 | #9 | Link |
Registered User
Join Date: Apr 2013
Location: Vienna, Austria
Posts: 55
|
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(); 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(); 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) |
30th May 2013, 19:21 | #10 | Link | |
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,431
|
Quote:
(*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. |
|
Thread Tools | Search this Thread |
Display Modes | |
|
|