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. |
|
|
Thread Tools | Search this Thread | Display Modes |
23rd July 2005, 22:44 | #1 | Link |
I'm trying... Honest!
Join Date: Jul 2005
Location: California, USA
Posts: 8
|
UPD: PlaneMinMax: Frame Based YV12 Plane Min/Max Functions Without ConditionalFilter
See Post #10 For Updated Information
First things first... As this is the first post I've done here, I'd like to take a moment to thank all of those who are responsible for such a fantastic tool as AviSynth. I stand in awe of the skills that have been exhibited in it's construction and use. Also, as I'm not an experienced programmer in C++, the code here might be in terrible shape, so please let me know how badly I've botched it. Learning is something that I've always attempted to do through projects and this plugin is no exception. In that light, I most humbly request that any of the experienced developers take a moment, if you have the spare time, to look over the source code and provide feedback. It would help immensly in my learning about C++ programming and AviSynth specifically. Now... On with the show... USAGE These filters will process YV12 planar frames to retrieve the minimum or maximum value of the specified planes. These functions would normally be done using the AviSynth native functions FrameEvaluate() or ScriptClip(), in conjunction with *PlaneMin() and *PlaneMax(), but the price of processing the frames using FrameEvaluate() or ScriptClip() is quite high, perhaps significantly so with some tasks. Like the built-in ConditionalFilter functions, this filter returns values for each frame processed. Code:
last = PlaneMinMax(last, 1, 1, "YMin") Code:
last = PlaneMinMax(last, 3, 2, "VMax") Code:
last = PlaneMinMax(plane1=1, mode1=1, gvar1="YMin", plane2=1, mode2=2, \ gvar2="YMax", plane3=2, mode3=1, gvar3="UMin", plane4=2, \ mode4=2, gvar4="UMax", plane5=3, mode5=1, gvar5="VMin", \ plane6=3, mode6=2, gvar6="VMax") Code:
last = PlaneUMinMax(gumin="UMin", gumax="UMax") Code:
last = PlaneYUVMax("YMax", "UMax", "VMax") FUNCTION DEFINITIONS Code:
clip PlaneMinMax( [clip last,] int plane1, int mode1, string gvar1 [, int plane2, int mode2, string gvar2] [, int plane3, int mode3, string gvar3] [, int plane4, int mode4, string gvar4] [, int plane5, int mode5, string gvar5] [, int plane6, int mode6, string gvar6] ) int plane1 - First plane to process. 1 = Y, 2 = U, and 3 = V. int mode1 - First mode to process. 1 = min, 2 = max. string gvar1 - First global variable name to receive the result. int plane2-6 (optional) - Additional planes (2nd thru 6th) to process. 0 = Y, 1 = U, and 2 = V. int mode2-6 (optional) - Additional modes (2nd thru 6th) to process. 0 = min, 1 = max. string gvar2-6 (optional) - Additional global variable (2nd thru 6th) names to receive the results. Code:
clip PlaneYMinMax( [clip last,] string gymin, string gymax ) string gymin - First global variable name to receive Y plane minimum result. string gymax - First global variable name to receive Y plane maximum result. Code:
clip PlaneUMinMax( [clip last,] string gumin, string gumax ) string gumin - First global variable name to receive U plane minimum result. string gumax - First global variable name to receive U plane maximum result. Code:
clip PlaneVMinMax( [clip last,] string gvmin, string gvmax ) string gvmin - First global variable name to receive V plane minimum result. string gvmax - First global variable name to receive V plane maximum result. Code:
clip PlaneYUVMin( [clip last,] string gymin, string gumin, string gvmin ) string gymin - First global variable name to receive Y plane minimum result. string gumin - First global variable name to receive U plane minimum result. string gvmin - First global variable name to receive V plane minimum result. Code:
clip PlaneYUVMax( [clip last,] string gymax, string gumax, string gvmax ) string gymax - First global variable name to receive Y plane maximum result. string gumax - First global variable name to receive U plane maximum result. string gvmax - First global variable name to receive V plane maximum result. COMPATABILITY This plugin was compiled and tested with a current CVS build of AviSynth 2.5, and is known to properly function in that environment, but should work pproperly with any 2.5 build of Avisynth. The source was compiled in Release mode using MSVC71 (VS .NET 2003) for distribution. The TestRegimen.avs script and includes are provided to ease testing and evaluation of the plugin. CHANGE LOG 0.1 - 07/14/2005 Creation - Many thanks to Si (Simon Walters) and sh0dan for a good working example to start from. Whoever was responsible for the internal c code for doing the calculations also receives my gratitude. I would not have thought to calculate the values in this way. 0.2 - 07/17/2005 Extended to support returning multiple values with one invocation, as well as specific invocations for the (what I believe) are the most likely combinations of values. 0.2 - 07/23/2005 First Beta release in the forums. DOWNLOAD PlaneMinMax_20050723_v0_2_0_17.zip
__________________
Yes... My name really is Bart S*, but not *impson! :) Last edited by barts(impson...Not!); 28th July 2005 at 03:51. Reason: Note about updates, updated title |
24th July 2005, 04:20 | #3 | Link |
Registered User
Join Date: Feb 2002
Posts: 1,195
|
i suppose it could be used to update (in order to speedup) the current script like QMF who apply a dynamic filtering by detecting the different motions in the movie.
__________________
AutoDub v1.8 : Divx3/4/5 & Xvid Video codec and .OGG/.MP3/.AC3/.WMA audio codec. AutoRV10 v1.0 : Use RealVideo 10 Codec and support 2 Audio Streams and Subtitles. |
24th July 2005, 04:27 | #4 | Link |
I'm trying... Honest!
Join Date: Jul 2005
Location: California, USA
Posts: 8
|
Mostly I would submit that typical applications would be where data is being collected from the video for output using WriteFile(). Of course, you could use the values for other purposes.
When I assembled the plugin, I was pretty tired of watching my low end data collection scripts running at only 20fps, and high end scripts (that build maps for image content matching) running at 2fps on a P4/3.0. Taking the opportunity at this moment, I stood on the shoulders of giants (so to speak) to get the basis for the functionality and twisted it a little to do things in a way that made sense to me. I've been given the task of building a database of library clips that's searchable by luma and chroma similarity/difference. So.. I guess that perhaps this might be more of a specialized plugin based on my needs at present. As in keeping with opensource projects, it felt right and proper to give something back, so I've attempted to do such. If anybody else out there finds that what I concocted is useful to them then all the better... Hence my tag line. It also gave me an excuse to try to write something productive in C++, a language I don't normally write in at all, and am on the verge of being able to use instead of just reading and understanding the source code. btw: Doh! is quite appropriate for where my head is sometimes. hehe
__________________
Yes... My name really is Bart S*, but not *impson! :) |
24th July 2005, 07:46 | #5 | Link |
Registered User
Join Date: May 2005
Location: Germany
Posts: 495
|
Hi Bart S,
very interesting work. Maybe I can use it in some of my functions. Why you doesn´t create such a function like ydifference(clip1,clip2) or something like this and then use the internal condition function (? : ) to get the same effect (or do I understand something wrong with PlaneYUVMax(), I never used it before, but in some tasks it could be useful). Maybe you get what I try. The simple yuvdifference functions would be just more useful for me and shouldn´t be hard to create for you. But of course, if this has no use for you I won´t bother anymore. Thank you, very useful work Last edited by MOmonster; 24th July 2005 at 07:48. |
25th July 2005, 04:07 | #6 | Link | ||
I'm trying... Honest!
Join Date: Jul 2005
Location: California, USA
Posts: 8
|
@MOmonster:
Quote:
Quote:
Code:
Global MaxY = 0 Global MaxU = 0 Global MaxV = 0 last = PlaneYUVMax(last, "MaxY", "MaxU", "MaxV") Code:
Global MaxY = 0 Global MaxU = 0 Global MaxV = 0 last = PlaneMinMax(last, 1, 2, "MaxY", 2, 2, "MaxU", 3, 2, "MaxV") @all: Perhaps what I've done in some way breaks the general paradigm for AviSynth scripts? It just seemed to me when I put this animal together that having to instantiate a complete IScriptEnvironment with dynamic compilation each frame was wasteful at best...
__________________
Yes... My name really is Bart S*, but not *impson! :) |
||
25th July 2005, 09:22 | #7 | Link | ||
Registered User
Join Date: May 2005
Location: Germany
Posts: 495
|
Quote:
Quote:
Maybe you could explain me what is meant with this value (does it change for every frame or only if it is higher or less? for what stand this value?) By the way, why you created your plugin with so many functions, through PlaneMinMax has the possibilities of all the other functions? Do the other functions run a little bit faster or more stable because of the limits or is it just for a easier use? Last edited by MOmonster; 25th July 2005 at 11:26. |
||
26th July 2005, 04:43 | #8 | Link | |||
I'm trying... Honest!
Join Date: Jul 2005
Location: California, USA
Posts: 8
|
Quote:
Quote:
Code:
tmp = FrameEvaluate(dst, "iMinY = YPlaneMin(dst)", after_frame = True) tmp = FrameEvaluate(tmp, "iMinY = YPlaneMax(dst)", after_frame = True) Code:
tmp = FrameEvaluate(dst, "iMinY = YPlaneMin(dst)" + Chr(13) + \ "iMaxY = YPlaneMax(dst)", after_frame = True) Code:
tmp = PlaneMinMax(dst, 1, 1, "iMinY") tmp = PlaneMinMax(tmp, 1, 2, "iMaxY") Code:
tmp = PlaneMinMax(dst, 1, 1, "iMinY", 1, 2, "iMaxY") Code:
tmp = PlaneYMinMax(dst, "iMinY", "iMaxY") Quote:
__________________
Yes... My name really is Bart S*, but not *impson! :) |
|||
26th July 2005, 09:46 | #9 | Link |
Registered User
Join Date: May 2005
Location: Germany
Posts: 495
|
Thank you for your short explanation. I took a closer look to the output values of your function and now I get what it does.
Ok we can use this function for example to tweak the motion estimation or something similar, but standalone it isn´t that useful for tasks. I think combining with the conditional enviroment (because of yuvdifference and so on) isn´t that advisable I think. Just because the stability and only a less speedgain (because if we already use the enviroment, we can also use the functions inside). But if you would create in near future some more of this internal functions we could totally avoid the use of conditional filters. This would be great. But ofcourse it is absolutly your decission to build the plugins you need and want. Keep it up, the good work, Bart S. |
28th July 2005, 03:49 | #10 | Link |
I'm trying... Honest!
Join Date: Jul 2005
Location: California, USA
Posts: 8
|
Updated Version 0.3.0.19
USAGE
Code:
last = PlaneMinMax(last, 1, 1, "YMin") Code:
last = PlaneMinMax(last, 3, 2, "VMax") Code:
last = PlaneMinMax(last, 2, 3, "UAvg") Code:
last = PlaneMinMax(plane1=1, mode1=1, gvar1="YMin", plane2=1, mode2=2, \ gvar2="YMax", plane3=1, mode3=3, gvar3="YAvg", plane4=2, \ mode4=1, gvar4="UMin", plane5=2, mode5=2, gvar5="UMax", \ plane6=2, mode6=3, gvar6="UAvg", plane7=3, mode7=1, \ gvar7="VMin", plane8=3, mode8=2, gvar8="VMax", plane9=3, \ mode9=3, gvar9="VAvg") Code:
last = PlaneUMinMax(gumin="UMin", gumax="UMax") Code:
last = PlaneYUVMax("YMax", "UMax", "VMax") Code:
last = PlaneYUVMax("YAvg", "UAvg", "VAvg") FUNCTION DEFINITIONS Code:
clip PlaneMinMax( [clip last,] int plane1, int mode1, string gvar1 [, int plane2, int mode2, string gvar2] [, int plane3, int mode3, string gvar3] [, int plane4, int mode4, string gvar4] [, int plane5, int mode5, string gvar5] [, int plane6, int mode6, string gvar6] [, int plane7, int mode7, string gvar7] [, int plane8, int mode8, string gvar8] [, int plane9, int mode9, string gvar9] ) int plane1 - First plane to process. 1 = Y, 2 = U, and 3 = V. int mode1 - First mode to process. 1 = min, 2 = max, 3 = average. string gvar1 - First global variable name to receive the result. int plane2-9 (optional) - Additional planes (2nd thru 6th) to process. 1 = Y, 2 = U, and 3 = V. int mode2-9 (optional) - Additional modes (2nd thru 6th) to process. 1 = min, 2 = max, and 3 = average. string gvar2-9 (optional) - Additional global variable (2nd thru 6th) names to receive the results. Code:
clip PlaneYMinMax( [clip last,] string gymin, string gymax ) string gymin - Global variable name to receive Y plane minimum result. string gymax - Global variable name to receive Y plane maximum result. Code:
clip PlaneUMinMax( [clip last,] string gumin, string gumax ) string gumin - Global variable name to receive U plane minimum result. string gumax - Global variable name to receive U plane maximum result. Code:
clip PlaneVMinMax( [clip last,] string gvmin, string gvmax ) string gvmin - Global variable name to receive V plane minimum result. string gvmax - Global variable name to receive V plane maximum result. Code:
clip PlaneYUVMin( [clip last,] string gymin, string gumin, string gvmin ) string gymin - Global variable name to receive Y plane minimum result. string gumin - Global variable name to receive U plane minimum result. string gvmin - Global variable name to receive V plane minimum result. Code:
clip PlaneYUVMax( [clip last,] string gymax, string gumax, string gvmax ) string gymax - Global variable name to receive Y plane maximum result. string gumax - Global variable name to receive U plane maximum result. string gvmax - Global variable name to receive V plane maximum result. Code:
clip PlaneYAvg( [clip last,] string gyavg ) string gyavg - Global variable name to receive Y plane average result. Code:
clip PlaneUAvg( [clip last,] string guavg ) string guavg - Global variable name to receive U plane average result. Code:
clip PlaneVAvg( [clip last,] string gvavg ) string gvavg - Global variable name to receive V plane average result. Code:
clip PlaneYUAvg( [clip last,] string gyavg, string guavg ) string gyavg - Global variable name to receive Y plane average result. string guavg - Global variable name to receive U plane average result. Code:
clip PlaneYVAvg( [clip last,] string gyavg, string gvavg ) string gyavg - Global variable name to receive Y plane average result. string gvavg - Global variable name to receive V plane average result. Code:
clip PlaneUVAvg( [clip last,] string guavg, string gvavg ) string guavg - Global variable name to receive U plane average result. string gvavg - Global variable name to receive V plane average result. Code:
clip PlaneYUVAvg( [clip last,] string gyavg, string guavg, string gvavg ) string gyavg - Global variable name to receive Y plane average result. string guavg - Global variable name to receive U plane average result. string gvavg - Global variable name to receive V plane average result. COMPATABILITY This plugin was compiled and tested with a current CVS build of AviSynth 2.5, and is known to properly function in that environment, but should work pproperly with any 2.5 build of Avisynth. The source was compiled in Release mode using MSVC71 (VS .NET 2003) for distribution. The TestRegimen.avs script and includes are provided to ease testing and evaluation of the plugin. CHANGE LOG Version Date/Activity 0.1 07/14/2005 Creation - Many thanks to Si (Simon Walters) and sh0dan for a good working example to start from. Whoever was responsible for the internal c code for doing the calculations also receives my gratitude. I would not have thought to calculate the values in this way. 0.2 07/17/2005 Extended to support returning multiple values with one invocation, as well as specific invocations for the (what I believe) are the most likely combinations of values. 0.2.0.17 07/23/2005 First Beta release in the forums. 0.3 07/26/2005 Extended to support returning average value using mode 3, as well as specific invocations for the (what I believe) are the most likely combinations of values. Although the average feature is not optimized as isse code, it doesn't have the downfall of only producing results on 16px boundry clips. 0.3.0.19 07/27/2005 Second Beta release in the forums. DOWNLOAD PlaneMinMax_20050727_v0_3_0_19.zip
__________________
Yes... My name really is Bart S*, but not *impson! :) |
30th July 2005, 06:13 | #12 | Link |
I'm trying... Honest!
Join Date: Jul 2005
Location: California, USA
Posts: 8
|
The most recent version has the average value functions added. I'm in process on making the plugin provide the other internal functions. As for a frame evaluated version of ConditionalFunction()... I'm undecided as to it's inclusion in this plugin, or if it should be split into another plugin.
More over I'm considering if min/max/avg should be one plugin, functions that handle differences in clips/frames of a clip in another, and selection/ternary functions in another. This in my mind would ease the complexity of the plugins such that they could be more easily optimized to assembler code. Personally, I'm not up to the task of doing such optimization, but if it turns out to be valuable enough I'm sure there many members who would be able to assist in such a task.
__________________
Yes... My name really is Bart S*, but not *impson! :) |
30th July 2005, 07:16 | #13 | Link | |
Registered User
Join Date: May 2005
Location: Germany
Posts: 495
|
Many thanks for the work on this, Bart S
I looked in your sourcecode (I´m no coder, that´s why I don´t understand it in detail) and just the code used on the frames (not to create so many function, set variables and so on), don´t looks so complex that it should be hard to optimize this code. Maybe your plugin should only have planeminmax() to make the code a little bit smaller. I don´t think that the handling get worse because of this. So or so, that more functions or plugins you use internal in avisynth, clear that more the script slows down. It should be faster to realize all the functions you need in one filter than calling many different filters. But of course, if it make sense to build in such functions like averageluma or lumadifference? The functions are too different and aren´t used so often together. But also for this function, it would be nice to have one function for the similar internals, I mean making something like yuv(plane)difference and yuv(plane)average. Is your new avg option similar to averageluma or is it (min+max)/2? Quote:
I see the most advantage of your function that it creates the variables outside of any special enviroment. So we can use the variables inside of a function and create our own evaluation process without the need of any conditional filters. The simple "? :" should be just enough |
|
30th July 2005, 10:37 | #14 | Link | |
Registered User
Join Date: Apr 2002
Location: Germany
Posts: 5,389
|
Quote:
It doesn't help if a variable in fact is recalculated for every frame, if you use the variable in a "normal" function, or whatever. The conditions for "? :" are evaluated only one single time by Avisynth's script parser: at script loading time, to build up the internal process chain. Later on, when serving frame after frame, those conditions are no more evaluated, since the chain is already build and fixed. Same goes for any parameters that are given as variables - the parameters will stay fixed at those values that the variable has had at frame 0, no matter if the variable is per-frame recalculated by a filter later on. That's why the conditional functions are there at all: to achieve a more variable processing chain.
__________________
- We´re at the beginning of the end of mankind´s childhood - My little flickr gallery. (Yes indeed, I do have hobbies other than digital video!) Last edited by Didée; 30th July 2005 at 10:39. |
|
30th July 2005, 11:14 | #15 | Link |
I'm trying... Honest!
Join Date: Jul 2005
Location: California, USA
Posts: 8
|
As for the ConditionalFunction() thing... That was an error on my part. I meant ConditionalFilter(). Sorry for any confusion.
You're correct on the complexity issue. The only code that would really need optimization would be the actual pixel processing loops in PlaneMinMax::GetFrame(). My downfall in doing that piece in assembly code is that the last such work I did was over 10 years ago, and at that mostly on Motorola 68000 family chips. For all of the other exported functions in the plugin, they're only called when the plugin is loaded (autoload or through LoadPlugin,) or when the script is loaded (the execution plan for the script is being constructed.) When the frames are actually being processed, only GetFrame() and things which it uses are actually executed. The thing that slows down ConditionalFilter(), FrameEvaluate(), and ScriptClip() is that the script code being used is actually parsed in the same way as when a script is loaded, but it happens each frame AFAIK. Note to the developers: If I've misunderstood how the conditional functions/plugin loading/script loading mechanisms work, please correct me. I think I understand the situation, but I would much rather know how it really works. The new average functions are more akin to AverageLuma. All of the min/max/avg functions make sense being implemented in the same code loop, as they all have to walk each pixel of the plane and retrieve the values. How they actually determine the value to return is where they differ. The min value for the plane is the lowest pixel value found, the max value is the highest pixel value found, and the average (median) is the sum of all the pixel values divided by the total number of pixels. I agree that the simple ternary function ( ? : ) should be sufficient for handling the results, but during my testing of ternarys inline with the PlaneMinMax() don't get evaluated at each frame. I'll have to check if that is also that case if you wrap the ternary inside a user function, or if you've already tried it, please let me know your findings. Also, I've been remiss in thanking you for your help and ideas about my small animal. I really appreciate your help.
__________________
Yes... My name really is Bart S*, but not *impson! :) |
30th July 2005, 11:18 | #16 | Link | |
I'm trying... Honest!
Join Date: Jul 2005
Location: California, USA
Posts: 8
|
Quote:
So, basically, either we would need to continue to use internal conditional functions, or I would need to implement a frame evaluated version of the ternary operator.
__________________
Yes... My name really is Bart S*, but not *impson! :) Last edited by barts(impson...Not!); 30th July 2005 at 11:34. |
|
Thread Tools | Search this Thread |
Display Modes | |
|
|