View Full Version : Avisynth+
MysteryX
25th April 2017, 02:01
We just have to call "AverageLuma(last, n, 10)" as the 2nd try IF current_frame is set on the parser (called within a conditional function) AND function_name is in the list of conditional filters.
This should do it.
expression.cpp, line 538, invert the 2 blocks of code.
// first try without implicit "last"
try
{ // Invoke can always throw by calling a constructor of a filter that throws
if (env2->Invoke(&result, name, AVSValue(args.data()+2, arg_expr_count), arg_expr_names+2))
return result;
} catch(const IScriptEnvironment::NotFound&){}
// if that fails, try with implicit "last" (except when OOP notation was used)
if (!oop_notation && env2->GetVar("last", &args[1]))
{
try
{
if (env2->Invoke(&result, name, AVSValue(args.data()+1, arg_expr_count+1), arg_expr_names+1))
return result;
} catch(const IScriptEnvironment::NotFound&){}
// for per-frame expressions, try with implicit "last" and "frame_number"
if (frame_number >= 0)
{
args[0] = args[1]; // "last"
args[1] = AVSValue(frame_number);
try
{
if (env2->Invoke(&result, name, AVSValue(args.data(), arg_expr_count+2), arg_expr_names))
return result;
}
catch (const IScriptEnvironment::NotFound&) {}
}
}
At "frame_number > 0", also check if "name" is in the list of conditional_filters.
TODO for Pinterf:
- Fix the deadlock
- Implement the change mentioned here
- Normalize values for high-bit-depth clips
MysteryX
25th April 2017, 03:14
Another issue: LumaDifference takes 2 clips. The function definition is "cic". We can't call "LumaDifference(clip1, clip2)".
The solution may be to make frame_number as the first parameter, so the definition becomes "icc".
Function evaluation then goes in this order for "LumaDifference(clip1, clip2)"
- LumaDifference(clip1, clip2) # not found
- LumaDifference(frame_number, clip1, clip2) # this version will be taken
- LumaDifference(frame_number, last, clip1, clip2)
- LumaDifference(last, clip1, clip2)
This means all functions in conditional_functions.cpp need params to start with "ic" instead of "ci", and all other functions in that page to reflect the parameter change. Then the code in expression.cpp can easily be adapted for that change. This should work perfect then.
Also to take into consideration... with this model, anyone could write custom per-frame functions as long as they respect the parameters order. If they do that, however, we can't check against a hard-coded list of per-frame functions. If frame_number is before the clip in the parameters order, it should avoid confusion between frame_number vs offset being passed as parameter -- are there still cases where it would cause problem?
pinterf
25th April 2017, 07:50
TODO for Pinterf:
- Fix the deadlock
Thanks. I have made already (nonpublished because they were dead end) fixes twice during the past months that had been seemed to be a good idea but were causing deadlocks sometimes (the nasty thing is when the tests are run with increasing Prefetch threads and the error appears over Prefetch(7) - timing? frame order dependencies?), so this solution just propagates the error into a deadlock.
Anyway, I will check the code whether the deadlock is of different origin than my ones and will ask if I have questions or requests.
Until then please test further, find other heavy scripts from doom9, I'm sure StainlessS has some - that are using conditional functions (with or without extra parameters).
pinterf
25th April 2017, 07:57
Another issue: LumaDifference takes 2 clips. The function definition is "cic". We can't call "LumaDifference(clip1, clip2)".
The solution may be to make frame_number as the first parameter, so the definition becomes "icc".
In OOP syntax the last clip result will turn implicitely into the first parameter of the filter. That's why clip is always at the first place.
Gavino
25th April 2017, 10:36
with this model, anyone could write custom per-frame functions as long as they respect the parameters order. If they do that, however, we can't check against a hard-coded list of per-frame functions.
It was always possible to write your own run-time functions, even in classic Avisynth, just by reading the value of the variable 'current_frame'.
In any case, having a list of 'special' function names hard-coded into the parser is ugly.
However, not knowing whether a function being called really wants to be supplied with the current frame number gives rise to the other problem you identified:
There is also the risk that some other standard function gets passed "frame_number" as its int argument when it shouldn't.
A better scheme would be to use a new argument type identifier (eg 'n') in the function template string to mark arguments that expect to be given the current frame number.
That way, the argument can be in any position and you avoid the complications (and performance overhead) of trying different parameter combinations using 'implicit current_frame' with or without 'implicit last'.
StainlessS
25th April 2017, 10:51
Here, my way of getting user supplied n, and delta (as in v2.6 AverageLuma Offset).
// Snippet, originally from Gavino
AVSValue __cdecl GetVar(IScriptEnvironment* env, const char* name) {
try {return env->GetVar(name);} catch (IScriptEnvironment::NotFound) {} return AVSValue();}
AVSValue __cdecl RT_YDifference(AVSValue args, void* user_data, IScriptEnvironment* env) {
char * myName="RT_YDifference: ";
if(!args[0].IsClip())
env->ThrowError("%sMust have a clip",myName);
PClip child = args[0].AsClip(); // Clip
int n,n2;
if(args[1].IsInt()) {n = args[1].AsInt(); } // Frame n
else {
AVSValue cn = GetVar(env,"current_frame");
if (!cn.IsInt()) env->ThrowError("%s'current_frame' only available in runtime scripts",myName);
n = cn.AsInt(); // current_frame
}
n2 = args[2].AsInt(1); // Delta: default 1 as YDifferenceFromNext
n2 += n; // n2 relative n --> frame number
const VideoInfo &vi = child->GetVideoInfo();
n = (n<0) ? 0 : (n>=vi.num_frames) ?vi.num_frames-1:n; // Range limit frame n
n2 = (n2<0) ? 0 : (n2>=vi.num_frames)?vi.num_frames-1:n2; // Range limit frame n2
if(!vi.IsPlanar() && !vi.IsYUY2() && !vi.IsRGB24() && !vi.IsRGB32()) {
env->ThrowError("%sPlanar, YUY2, RGB24 and RGB32 Only",myName);
}
if(vi.width==0 || vi.num_frames==0) env->ThrowError("%sclip must have video",myName);
int xx=args[3].AsInt(0);
int yy=args[4].AsInt(0);
int ww=args[5].AsInt(0);
int hh=args[6].AsInt(0);
int xx2=args[7].AsInt(xx);
int yy2=args[8].AsInt(yy);
bool altscan=args[9].AsBool(false);
const int matrix = args[10].AsInt(vi.width>1100 || vi.height>600?3:2); // Matrix: REC601 : 1=REC709 : 2 = PC601 : 3 = PC709
if(ww <= 0) ww += vi.width - xx;
if(hh <= 0) hh += vi.height - yy;
if(altscan && ((hh & 0x01) == 0)) --hh; // If altscan then ensure ODD number of lines, last line other field does not count.
altscan=(altscan && hh!=1);
if(xx < 0 || xx >=vi.width) env->ThrowError("%sInvalid X coord",myName);
if(yy < 0 || yy >=vi.height) env->ThrowError("%sInvalid Y coord",myName);
if(ww <= 0 || xx + ww > vi.width) env->ThrowError("%sInvalid W coord for X",myName);
if(hh <= 0 || yy + hh > vi.height) env->ThrowError("%sInvalid H coord for Y",myName);
if(xx2 < 0 || xx2 >=vi.width) env->ThrowError("%sInvalid X2 coord",myName);
if(yy2 < 0 || yy2 >=vi.height) env->ThrowError("%sInvalid Y2 coord",myName);
if(xx2 + ww >vi.width) env->ThrowError("%sInvalid W coord for X2",myName);
if(yy2 + hh >vi.height) env->ThrowError("%sInvalid H coord for Y2",myName);
PVideoFrame src;
PVideoFrame src2;
// fetch frames in lo->hi order
if(n <= n2) {src = child->GetFrame(n,env); src2 = child->GetFrame(n2,env);
} else {src2 = child->GetFrame(n2,env); src = child->GetFrame(n,env);}
double result = 0.0;
if(vi.IsYUY2()) {
result = PVF_LumaDifference_YUY2(src,src2,xx,yy,ww,hh,xx2,yy2,altscan);
} else if(vi.IsPlanar()) {
result = PVF_LumaDifference_Planar(src,src2,xx,yy,ww,hh,xx2,yy2,altscan);
} else if(vi.IsRGB()) {
if(matrix<0 || matrix > 3) env->ThrowError("%Matrix 0 -> 3",myName);
result = PVF_LumaDifference_RGB(src,src2,xx,yy,ww,hh,xx2,yy2,altscan,matrix,vi.IsRGB32());
}
return result;
}
MysteryX
25th April 2017, 17:55
This could be another solution -- and less hacky: adding a named argument called "current_frame" at the end.
Argument "n" runs the risk of creating conflicts with other plugins, and doesn't say what it is.
Function evaluation then goes in this order for "LumaDifference(clip1, clip2)"
- LumaDifference(clip1, clip2, current_frame) # this version will be taken
- LumaDifference(last, clip1, clip2, current_frame)
- LumaDifference(clip1, clip2)
- LumaDifference(last, clip1, clip2)
This could work.
That, or
- LumaDifference(n, clip1, clip2) # if (args[0].IsClip())
- LumaDifference(n, last, clip1, clip2)
- LumaDifference(clip1, clip2)
- LumaDifference(last, clip1, clip2)
This also would work if the 1st is being tried only if args[0] is a clip. Because of OOP syntax, clip is always being placed first, thus there are no functions starting with "int,clip" so trying functions starting with "int,clip" can only succeed on per-frame functions. Personally I like this option better because it imposes no restriction on variable names, and it is cleaner (IMO).
ScriptClip(last, "Subtitle(String(AverageLuma(10)))")
This will call AverageLuma(n, last, 10)
Subtitle(String(AverageLuma(10)))
Subtitle(String(last.AverageLuma(10)))
These two will fail -- but were never meant to work.
Subtitle(String(AverageLuma(50, last, 10)))
This will display the AverageLuma of the 50th frame with offset=10 on every frame
If we instead use a named parameter
Subtitle(String(AverageLuma(10, current_frame=50)))
Subtitle(String(last.AverageLuma(10, current_frame=50)))
These two would work.
Which solution is best? Personally I'd go for "ic" as the first args.
pinterf
25th April 2017, 17:58
I was just inspecting the same, that LumaDifference will be broken.
MysteryX
25th April 2017, 19:03
I'm updating the code and will re-push.
MysteryX
25th April 2017, 20:15
Code updated and submitted. (https://github.com/pinterf/AviSynthPlus/pull/10)
I tried all samples from the ConditionalFilter wiki page and it worked -- except samples about writing current_frame to the screen.
To write a per-frame filter, its definition must start with "ic" for "frame_number|last".
MysteryX
26th April 2017, 00:16
For "current_frame", I could create a function "current_frame(n,c)" that returns n. This should make it work.
MysteryX
26th April 2017, 04:08
Function "current_frame" added. (https://github.com/pinterf/AviSynthPlus/pull/10/commits/56682b902d60bbc5088472073ddacc6e90316367) Now all samples work :D
vcmohan
26th April 2017, 07:03
I am experimenting with a new code for a plugin Balloon. I found that the call BitBlt is causing access violation if used in multi thread mode. I am using vdub to monitor output. If I step frame by frame it works out OK, but if I press the run button the access violation occurs. After checking I found that the BitBlt call is the culprit.i am on r2420_MT 64 bit version.
My simple code to check problem in Get Frame method is
PVideoFrame __stdcall EffectBalloon::GetFrame(int in, IScriptEnvironment* env)
{
// This is the implementation of the constructor.
PVideoFrame Frame = child->GetFrame(in, env);
if(in<StartFrame || in>EndFrame)
return Frame;
int n=in-StartFrame;
int nframes= EndFrame-StartFrame+1;
PVideoFrame dst = env->NewVideoFrame(vi);
const unsigned char *fp= Frame->GetWritePtr();
const int fpitch = Frame->GetPitch();
const int bwd = vi.width;
const int bht = dst->GetHeight();
int dpitch = dst->GetPitch();
unsigned char* dp= dst->GetWritePtr();
const int kb = vi.BytesFromPixels(1) ;
// copy input frame on to output dst. For RGB, YUY2 and Y of Planar formats
env->BitBlt(dp, dpitch, fp, fpitch, Frame->GetRowSize(), bht);// commenting this out runs ok.
return Frame;// return dst;returning dst or frame have same problem ;
If I comment out the BitBlt call it runs OK.
The script used to test is
[code]
loadplugin (---------balloon.dll)
SetFilterMTMode("Balloon", MT_NICE_FILTER)
colorbars()
trim(1,100)
converttoRGB24()
Balloon()
return(last)
prefetch(6)
[\code]
The other problem I posted on 14th and 15th April seems to habeen lost.
pinterf
26th April 2017, 10:39
I am experimenting with a new code for a plugin Balloon. I found that the call BitBlt is causing access violation if used in multi thread mode. I am using vdub to monitor output. If I step frame by frame it works out OK, but if I press the run button the access violation occurs. After checking I found that the BitBlt call is the culprit.i am on r2420_MT 64 bit version.
My simple code to check problem in Get Frame method is
PVideoFrame __stdcall EffectBalloon::GetFrame(int in, IScriptEnvironment* env)
{
// This is the implementation of the constructor.
PVideoFrame Frame = child->GetFrame(in, env);
if(in<StartFrame || in>EndFrame)
return Frame;
int n=in-StartFrame;
int nframes= EndFrame-StartFrame+1;
PVideoFrame dst = env->NewVideoFrame(vi);
const unsigned char *fp= Frame->GetWritePtr();
const int fpitch = Frame->GetPitch();
const int bwd = vi.width;
const int bht = dst->GetHeight();
int dpitch = dst->GetPitch();
unsigned char* dp= dst->GetWritePtr();
const int kb = vi.BytesFromPixels(1) ;
// copy input frame on to output dst. For RGB, YUY2 and Y of Planar formats
env->BitBlt(dp, dpitch, fp, fpitch, Frame->GetRowSize(), bht);// commenting this out runs ok.
return Frame;// return dst;returning dst or frame have same problem ;
If I comment out the BitBlt call it runs OK.
Could you check the value of Frame->GetRowsize()? And that the dimensions and format of the source/destination is matching? Does it fail on both debug and release version (filling unused variables may be optimized out).
pinterf
26th April 2017, 11:00
@MisteryX: Unfortunately not only "current_frame", but variable "last" is also affected in the MT scope change (I have posted the TLS Invoke code previously).
Usually "last" exists in the main thread (whose variables are visible when the filter is instantiated) so it won't give you instant error.
It is just possible that the filter is working with the wrong "last" value.
We have to solve the whole ScriptClip problem, that is how can an instance use the thread local last and current_frame.
I was experimenting a bit and when it seemed to be working in Prefetch(8), Prefetch(120) failed.
I recommend tests with multiple lines of the same simple "torture" line.
A clip with white-grey-black-white... should result in a given sequence in LumaDifference that we can check.
Then use two or more active clips e.g. YV12/YUV444P16, first with level sequence 16-128-235, the other one 50-128-200 and get the LumaDifference for both, and put the results into a common clip.
The values should follow in the proper order in repeating sequence.
Do it with large Prefetch values, timing and frame request sequence problems may appear under extreme threading conditions but it should be correct anyhow.
StainlessS
26th April 2017, 12:24
VideoFrame __stdcall EffectBalloon::GetFrame(int in, IScriptEnvironment* env)
{
// This is the implementation of the constructor.
PVideoFrame Frame = child->GetFrame(in, env);
if(in<StartFrame || in>EndFrame)
return Frame;
// int n=in-StartFrame; // Unused
// int nframes= EndFrame-StartFrame+1; // Unused
PVideoFrame dst = env->NewVideoFrame(vi);
const unsigned char *fp= Frame->GetWritePtr(); // src fp, const unsigned char * to WRITEPTR
const int fpitch = Frame->GetPitch();
// const int bwd = vi.width; // Unused
const int bht = dst->GetHeight();
int dpitch = dst->GetPitch();
unsigned char* dp= dst->GetWritePtr();
// const int kb = vi.BytesFromPixels(1) ; // Unused
// copy input frame on to output dst. For RGB, YUY2 and Y of Planar formats
env->BitBlt(dp, dpitch, fp, fpitch, Frame->GetRowSize(), bht);// commenting this out runs ok.
return Frame;// return dst;returning dst or frame have same problem ;
Just pointing out a few things.
EDIT: What is effect of taking writeptr on non writable src frame ?
vcmohan
26th April 2017, 12:37
Could you check the value of Frame->GetRowsize()? And that the dimensions and format of the source/destination is matching? Does it fail on both debug and release version (filling unused variables may be optimized out).
The Frame dimensions and row size are ok. Width 640, rowsize 1920, bytes per pixel 3 (as RGB24).
When I tried compiling in debug mode I ran into problems. (using vs 13 community version update 4). First it complained about not finding avisynth.h file which was placed in include folder, inspite Path of this folder being in the additional include folders. After placing copy of this along with avs folder in my project itself, it started complaining not able to open the files in the avs folder.(#include <avs/config.h>
#include <avs/capi.h>
#include <avs/types.h>) may be <> to be replaced by " in the header file? I gave up trying.
I noted another spooky thing. When I commented out the BitBlt and stepping in vdub I noticed that each frame was getting the previous frame output as dst. So I could see by end all previous frame outputs one over other. (my Balloon traverses a parabolic path and I see it at all stages in the last frame). However if I press run button I see occassionally colorbars frames also.Is this normal behaviour. I thought that the output will not be recycled so soon.
pinterf
26th April 2017, 14:18
EDIT: What is effect of taking writeptr on non writable src frame ?
When the reference count for the frame and its framebuffer is not 1 then it returns NULL.
pinterf
26th April 2017, 14:46
I noted another spooky thing. When I commented out the BitBlt and stepping in vdub I noticed that each frame was getting the previous frame output as dst. So I could see by end all previous frame outputs one over other. (my Balloon traverses a parabolic path and I see it at all stages in the last frame). However if I press run button I see occassionally colorbars frames also.Is this normal behaviour. I thought that the output will not be recycled so soon.
It's normal :) When I was starting working on masktools I went crazy when remnants from previous random frames appeared in the output until I realized that no U and V processing was done (no copy or fill or whatever, the documentation properly mentioned that the content in such case can be anything for not in-place filters)
MysteryX
26th April 2017, 16:08
@MisteryX: Unfortunately not only "current_frame", but variable "last" is also affected in the MT scope change
I was worried about that, but then hadn't seen any issue in my tests. It is very possible it will fail under extreme circumstances, yes.
Any suggestion?
It's not making a difference with the ScriptClip expression -- rather it is to reset "last" after the expression is evaluated. Doesn't Eval have the same issue?
pinterf
26th April 2017, 16:19
I think that only runtime is affected. I'd like to see an "elegant" way to solve it, but either this way does not exist (unless we are breaking and rewriting the whole MT internal concepts - which I'm not willing to do :) ) or have to learn on and do more reverse engineering and experimenting.
MysteryX
26th April 2017, 16:28
Eval doesn't do this, but EvalOop does the exact same "last" reset as ScriptClip.
It leaves room for bugs -- but has anyone encountered a problem with Clip.Eval ?
Which specific circumstance will be affected by that?
qyot27
26th April 2017, 17:01
After placing copy of this along with avs folder in my project itself, it started complaining not able to open the files in the avs folder.(#include <avs/config.h>
#include <avs/capi.h>
#include <avs/types.h>) may be <> to be replaced by " in the header file? I gave up trying.
This has been brought up before. The idea was that the directory avs/ resides in should be added to the project path so it's treated as a system directory like the <> denotes. Of course, it's still a problem because it was generally accepted that the proper install path for the headers would be include/avisynth/ when being installed system-wide.
I've long been in favor of changing the references in avisynth[_c].h to the avs/ subdir from <> to "" - it's not like plugins are going to need to rely on stuff in avs/ without also pulling in avisynth[_c].h as well. Or you know, at all, since avisynth[_c].h should be the single point of contact between the AviSynth+ API and the plugin.
MysteryX
26th April 2017, 17:17
I've long been in favor of changing the references in avisynth[_c].h to the avs/ subdir from <> to ""
I'm not familiar with the background of this issue, but that's what I've been doing.
MysteryX
27th April 2017, 05:14
FrameRateConverter (https://forum.doom9.org/showthread.php?p=1805171#post1805171) plays weird in Avisynth+, even without MT. It plays a bunch of frames, pauses, then plays another bunch of frames, then pauses again, etc.
With MT, it stalls at low CPU usage, but first it would be good to debug the issue without MT.
vcmohan
27th April 2017, 07:46
[CODE]
Just pointing out a few things.
EDIT: What is effect of taking writeptr on non writable src frame ?
Thanks for pointing out. But those variables are used in my subsequent code which I deleted just for checking.
The main culprit is the Frame->GetWritePtr().
I forgot to change this to GetReadPtr after I deleted make writeable which I used earlier. Now it works OK. But wonder how it was working when I was just stepping frame by frame without crashing?
Also problem of compiling under debug and script I pointed out on 14th and 15th April is unresolved.
pinterf
27th April 2017, 09:58
Also problem of compiling under debug and script I pointed out on 14th and 15th April is unresolved.
This problem, right? https://forum.doom9.org/showthread.php?p=1803688#post1803688
Could not reproduce. With and without imagesource.
I'd need to have the same conditiones.
So you are on 2420 x64 MT
- Can it be reproduced w/o ImageSource on your machine (just a BlankClip with similar dimensions and format?)
- Processor architecture (though no AVX2 code is used here)
- Does it happen when encoding to e.g. x264 or when viewing from VirtualDub or AvsPMod?
- Clip is of a single image or multiple frames? (e.g. ImageSource(...).Loop(20))
MysteryX
27th April 2017, 16:49
new req Grunt, but that should be built-in to Avisynth, along with GScript (GScript is builtin in AVS+, already).
I said the same. GRunT should be built-in to Avisynth.
To put in the TODO list.
pinterf
27th April 2017, 16:55
I have mentioned it already, and most of it is done. Except setting current_frame into global variable. But until the basic ScriptClip suffers in MT, I won't put it up in git and release.
MysteryX
27th April 2017, 18:34
ScriptClip should be working now.
We just have to see whether "last" causes issues, not only with ScriptClip but with Eval and any other run-time expression evaluation.
Is there any other issue with global variables?
mariush
27th April 2017, 21:59
Not sure if something like this is already implemented or not in AviSynth+ but just saying it anyway.
Would there be any interest in adding "native" support for reading and writing PNG files? Seems like a good idea: they support up to 16 bit per channel, so it could store 8 bit, 10bit, 12bit .. all the way up to 16 bit and also supports grayscale. Yeah, it's only RGB but as far as I know, so is BMP and eBMP right?
If speed is a concern (for ImageWriter) you can simply default to compression = 0 or 1 (just copy or ultra fast zlib compression) and the only added cpu cost would be the calculation of a 32bit checksum.
It would be also possible to use a bunch of custom tags (the png format allows for that) like let's say xACy, xACb , xACr for example for planar formats and YCbCr or whatever Rec.2020 uses if it's different (too lazy to search now) .... and maybe store a default generic small image maybe with some text saying "this is a custom png file which stores the image information in custom chunks readable by Avisynth+ ) and the png format also allows and has text chunks where Avisynth+ could store some encoded data required to understand what it actually stored in the png file ( planar or interleaved, color space, full range/limited range etc)
Could be a good replacement for that non-standard ebmp
ps. Just checking the ImageWriter (avisynth.nl/index.php/ImageWriter) wiki page ... also noticed something... seems the function defaults to "c:" if the path is not specified. Windows would most likely block writing directly to C:\ by default (to protect itself and file system, perhaps it would be a good idea to use C:\AviSynth or %AviSynth_Install_Folder\Images instead
Don't know how anyone thought the root of a drive to be a good default setting.
raffriff42
28th April 2017, 05:24
RGBAdjust (http://avisynth.nl/index.php/RGBAdjust) - gain arguments autoscale (https://forum.doom9.org/showthread.php?p=1805251#post1805251), but bias does not. Levels - no arguments autoscale. Just noting it in passing.
vcmohan
28th April 2017, 06:06
This problem, right? https://forum.doom9.org/showthread.php?p=1803688#post1803688
Could not reproduce. With and without imagesource.
I'd need to have the same conditiones.
So you are on 2420 x64 MT
- Can it be reproduced w/o ImageSource on your machine (just a BlankClip with similar dimensions and format?)
- Processor architecture (though no AVX2 code is used here)
- Does it happen when encoding to e.g. x264 or when viewing from VirtualDub or AvsPMod?
- Clip is of a single image or multiple frames? (e.g. ImageSource(...).Loop(20))
I checked with following script
#imagesource("c:\images\source1_z.jpg",end = 500)
imagereader("c:\images\stamil.jpg",end = 100)
#imagesource("C:\avi_plugins\DeNoise\grainnoise.png", end = 30).converttoYv12()
#imagereader("C:\avi_plugins\varianslim\theoin.jpg", end = 1000)
#colorbars()
converttoYUY2()
stackhorizontal(last,last)
stackvertical(last,last)
reduceby2()
return(last)
I found that it works ok excepting for that particular imagereader (or if replaced by imagesource) uncommented line. Appears that particular jpg is creating the problem. When I step through I get some green screens. File information looks OK.
Still I can not understand what the problem is, for if I comment out reduceby2() it runs ok with the same input. The particular stamil.jpg image is 602 x 566. I use vdub to monitor output. My Samsung laptop runs with windows 10 home edition. Processor intel i7-4500U1.80Ghz 2.4Ghz, 8GB memory.
pinterf
28th April 2017, 10:09
The particular stamil.jpg image is 602 x 566.
Thanks, the size the key.
Replaced ImageSource with ColorBars
colorbars().Spline64Resize(610,566)
600 ok, 602 fail, 604 ok, 606 fail, 608 ok, 610 fail
EDIT: fixed (YUY2 HorizontalReduceBy2 did nothing if target width is not mod4)
The constructor of HorizontalReduceBy2 is checking YUY2 clip if the width of source is mod4 (valid YUY2 target width should be mod2). Then it sets output vi.width, divides by 2.
In GetFrame, it checks width again mod4, but the width here is already divided by 2.
It was doing the reduce operation only if width is mod4, which is wrong, here the width is mod2 already (The whole checking is not needed, because it was pre-checked in constructor). Or else it did nothing, frame is undefined content.
pinterf
28th April 2017, 11:49
RGBAdjust (http://avisynth.nl/index.php/RGBAdjust) - gain arguments autoscale (https://forum.doom9.org/showthread.php?p=1805251#post1805251), but bias does not. Levels - no arguments autoscale. Just noting it in passing.
Thanks, this is inconsistent, and we can call it bug, that was at the very beginning of the project. For a brand new project I'd choose nothing to scale, but keeping scripts easy to maintain is another aspect. Still I'd like to have an option for expert users providing parameters as-is, by something like "paramscale" in masktools.
raffriff42
28th April 2017, 14:06
After thinking about it, I have no preference for or against autoscaling. One the one hand, it is convenient now, while adapting one's thinking in terms of 0-255 to deep color. On the other hand, it sets the current way of thinking into stone, forever.
In a few years people may instead think in terms of normalized (0-1) range, as strange as that may seem to us now. Maybe they will prefer 0-1023, 0-65535, or something else.
Scaling a non-autoscaled argument is easily done by the user. Re-scaling an 0-255 autoscaled argument to a different source range is also easily done. So I don't care which it is.
Here's an example of Levels (not currently autoscaling) with user-side scaling; changes in blue:##################################
### scale 0-255 Levels arguments to clip 'C' bit depth (AVS+)
function ScaledLevels(clip C,
\ int input_low, float gamma, int input_high,
\ int output_low, int output_high,
\ bool "coring", bool "dither")
{
return C.Levels(
\ C.sb8x(input_low),
\ gamma,
\ C.sb8x(input_high),
\ C.sb8x(output_low),
\ C.sb8x(output_high),
\ coring, dither)
}
You see how easy it is. Supporting code is below. (suggested filename 'argscale.avsi')
### manual scaling of arguments from one bit depth to another
## version 28-Apr-2017, raffriff42
#######################################
### scale a value from one bit depth to another
##
## @ bits_in - the bit depth being converted from
## @ bits_out - the bit depth being converted to
## @ cx - clamp output (cf. sbx below)
## @ returns float if not clamped;
## else returns int for int formats, float for float
##
function sbf(int bits_in, int bits_out, float f, bool "cx")
{
clamp = Default(cx, false)
fsi = getFullscale(bits_in)
fso = getFullscale(bits_out)
fsi1 = Float( (bits_in==32) ? 256.0/255.0 : fsi+1 )
fso1 = Float( (bits_out==32) ? 256.0/255.0 : fso+1 )
fr = (bits_in==bits_out) ? f : f * fso1 / fsi1 ## unclamped result
fr = (clamp==false) ? fr : Min(Max(0.0, fr), fso)
fr = (clamp==false) ? fr : (bits_out==32) ? fr : Round(fr)
return fr
}
#######################################
### scale a value from one bit depth to another; clamp output
##
## @ bits_in - the bit depth being converted from
## @ bits_out - the bit depth being converted to
## @ returns int for int formats, float for float
##
function sbx(int bits_in, int bits_out, float f)
{
return sbf(bits_in, bits_out, f, true)
}
#######################################
### scale an 8-bit value for target clip 'T'; clamp output
##
## @ T - clip with target bit depth
## @ returns int for int formats, float for float
##
function sb8x(clip T, float f)
{
return sbf(8, T.BitsPerComponent, f, true)
}
#######################################
### scale a 'normalized' (0 to 1) value for target clip 'T'; clamp output
##
## @ T - clip with target bit depth
## @ returns int for int formats, float for float
##
function sbnx(clip T, float f)
{
return sbf(32, T.BitsPerComponent, f, true)
}
#######################################
### scale a value from one bit depth to another; string result
##
## @ bits_in - the bit depth being converted from
## @ bits_out - the bit depth being converted to
## @ returns String, unclamped
##
function sbs(int bits_in, int bits_out, float f, int "decimals")
{
decimals = Min(Max(0, Default(decimals, 4)), 8)
return String(sbf(bits_in, bits_out, f), "%0."+String(decimals)+"f")
}
#######################################
### scale an 8-bit value for target clip 'T'; string result
## @ T - clip with target bit depth (assume bits_in = 8)
## @ returns String, unclamped
##
function sb8s(clip T, float f, int "decimals")
{
return sbs(8, T.BitsPerComponent, f, decimals)
}
#######################################
### scale a 'normalized' (0 to 1) value for target clip 'T'; string result
## @ T - clip with target bit depth (assume bits_in = 8)
## @ returns String, unclamped
##
function sbns(clip T, float f, int "decimals")
{
return sbs(32, T.BitsPerComponent, f, decimals)
}
#######################################
### return integer fullscale value for given bit depth (mostly for internal use)
function getFullscale(int bits)
{
return (bits==8) ? 255
\ : (bits==10) ? 1023
\ : (bits==12) ? 4095
\ : (bits==14) ? 16383
\ : (bits==16) ? 65535
\ : (bits==32) ? 1
\ : Assert(false,
\ "getFullscale: 'bits' not one of (8|10|12|14|16|32)")
}
## end
nhope
28th April 2017, 19:50
Apologies for this but where's the user-friendly document that explains the AviSynth+ MT stuff like SetFilterMTMode() and Prefetch(), and the changes required in scripts? Can't find it anywhere. Google doesn't know. I seem to remember it was on a wiki.
LigH
28th April 2017, 20:56
AviSynth Wiki (http://avisynth.nl/index.php/Main_Page)
Multi-Threading (http://avisynth.nl/index.php/MT) (old MT() and v2.x-MT SetMTMode())
AviSynth+ (http://avisynth.nl/index.php/AviSynth%2B) — MT Notes (http://avisynth.nl/index.php/AviSynth%2B#MT_Notes) (SetFilterMTMode() and Prefetch())
raffriff42
28th April 2017, 20:58
where's the user-friendly document that explains the AviSynth+ MT stuff like SetFilterMTMode() and Prefetch()Some of it was 'hidden' on the AVS+ developers' page (http://avisynth.nl/index.php/Avisynthplus/Developers) in the wiki; I've moved it to the AVS+ main page (http://avisynth.nl/index.php/AviSynth%2B) as a stopgap until the MT docs can be expanded.
nhope
29th April 2017, 04:01
Thank you both. It was http://avisynth.nl/index.php/AviSynth%2B#MT_Notes that I was looking for.
MysteryX
29th April 2017, 18:10
I was thinking about the issue with "last" and global vars.
"last" isn't used within script functions so script libraries won't be affected by any issue here. If there are problems, it's going to happen at the main script level. If it works within script functions (without implicit "last"), then it's a huge improvement already. Once that is working, we can give it some more thoughts about how to handle variables like "last", as well as produce bogus scripts for testing. I think we're better to leave that one for later. If we're going to change it, we'll have to do it right, and for now we have no right solution.
Still, that doesn't prevent conditional functions from being supported.
raffriff42
29th April 2017, 19:14
"last" isn't used within script functions so script libraries won't be affected by any issue here.What what what!!!
MysteryX
29th April 2017, 20:03
What what what!!!
Fct1() # uses implicit last -- possible issue with dynamic evaluation of expressions like Eval which reset "last"
Fct2()
function Fct1(clip c) {
c = c.Fct2() # here we need to define the clip explicitely
return Fct3(c)
}
raffriff42
29th April 2017, 20:22
I once told a guy -- can't find the link right now -- about the easy way to create a function from a bunch of script lines. Something like:function foo(clip C)
{
C ## Last==C
Filter1
Filter2
Filter3
return Last
}...and some of my user functions look just like that example. All I'm saying is, don't even think about breaking my preciousss Last.
EDIT - I always use explicit Last with BlankClip and ScriptClip; maybe Eval should get special treatment (from the user) also.
LigH
29th April 2017, 20:29
Or so:
function Fct1(clip c) {
c # means explicitly: last = c
Fct2()
return Fct3()
}
Of course, the scope in the function does not use the last clip from the main level inside. It creates an own last variable.
Fortunately, last is not "super-global". At least I hope so.
MysteryX
29th April 2017, 21:10
Right -- sorry my mistake.
We're not changing anything to "last". We're just worried it might have some of the same issues as "current_frame" with MT -- although we're not clear on how such problem manifests. We haven't seen any issue so far.
StainlessS
29th April 2017, 21:18
function Fct1(clip c) {
c # means explicitly: last = c
Fct2()
x=sin(.5)
sin(.5) # EDIT: added
return Last # return result of Fct2() # Assuming it was a clip
}
Last (so far as I understand it) stores the previous (clip only) return variable that was not assigned to anything else.
LigH
29th April 2017, 23:09
That's an interesting question. I really wonder if "return" returns a clip or a number. In my current mental state, I would bet on ... number. I should try it.
pinterf
30th April 2017, 08:22
That deadlock thing is hard to catch. I was working on the problem during December, now I have returned to it.
In my test code the variables last and current_frame were passed to the invoke with guards of mutex. That specific TLS (Thread Local Storage) Invoke - I had linked earlier which was doing context switch and made "current_frame" and "last" out of scope - was modified a bit to re-set those variables in the scope of the core. But this was only the first small step which only allowed the script not to fail in YDifferenceFromPrevious's constructor (which so far was complaining "current_frame" does not exists)
ScriptClip MT test script, which I'm using to ensure that last is always right.
Frames should follow each other displaying 16-32-48-96-16-32-48-96 sequence if frame order is OK.
There is a second ScriptClip line, because it makes our life shorter and increases the stress level a bit. We have another parallel work in runtime evaluation.
Case #1 happyness
When the second ScriptClip line is independent from the first ScriptClip(commented out c1=, c2= lines in code below), then there is no problem, I'm doing Prefetch(300) and nothing fails.
Case#2 deadlock
But when the second ScriptClip is using the output of the first ScriptClip, sometimes deadlock occurs.
Depending on the clip size, additional filters at the end, they all modify internal timings, order of cache hits, this "sometimes" can be never or 10 or 100 frames. I have experimented with a few hundred variants. Deadlock can be eliminated when ScriptClip is defined as "DONT_CACHE_ME", but this is no-go of course.
Sometimes Prefetch(80) is OK, but Prefetch(90) deadlocks. In other timing conditions the limit is Prefetch(8), etc.
len=1
w=64
h=48
c1=BlankClip(width=w,height=h,length=len,pixel_type="YV24",color_yuv=$008080)
c2=BlankClip(width=w,height=h,length=len,pixel_type="YV24",color_yuv=$108080) # diff 16
c3=BlankClip(width=w,height=h,length=len,pixel_type="YV24",color_yuv=$308080) # diff 32
c4=BlankClip(width=w,height=h,length=len,pixel_type="YV24",color_yuv=$608080) # diff 48 -> diff (-)96
c=c1+c2+c3+c4
c.Loop(100)
# this will deadlock sooner or later or never, more Prefetch makes deadlock to appear, even more -> deadlock sooner
ScriptClip(last, "Subtitle(String(YDifferenceFromPrevious()))")
ScriptClip(last, "Subtitle(String(YDifferenceFromPrevious()),X=0,Y=30)")
/* This works for any Prefetch, no dependancy between them
c1=ScriptClip(last, "Subtitle(String(YDifferenceFromPrevious()))")
c2=ScriptClip(last, "Subtitle(String(YDifferenceFromPrevious()),X=0,Y=30)")
Stackvertical(c1,c2)
*/
ConvertToRGB32() #additional filters modify timing thus, frame evaluation order/cache hit order in MT
ConvertToRGB24()
ConvertToRGB32()
ConvertToRGB24()
Prefetch(60)
MysteryX
30th April 2017, 15:30
I tried doing a bit of multi-threading in C++ until I realized how much of a pain it was. I was reading many articles saying how MT was only for experts, and I then understood why.
My recommendation: write the thread management in .NET (no "undefined" state!!) :) but that's not really an option -- if rewriting was an option, it's VapourSynth all the way
so... Good luck :D
vBulletin® v3.8.11, Copyright ©2000-2025, vBulletin Solutions Inc.