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

Closed Thread
 
Thread Tools Search this Thread Display Modes
Old 1st November 2013, 00:58   #201  |  Link
ultim
AVS+ Dev
 
ultim's Avatar
 
Join Date: Aug 2013
Posts: 359
Quote:
Originally Posted by ajp_anton View Post
If there's room for feature requests, can we skip some arguments when calling functions like this:
some_function(a,b,,d,e)
if I don't want to change the default value for the third argument, and don't want to explicitly use the names of the 4th and 5th arguments.
Sure, there is always room for feature requests! So please post everything on your mind here on the forums, or as a GitHub issue. It allows us to discuss your ideas. In this particular case, I agree with Gavino, that the syntax you demonstrated would let many typos go undiscovered, but Gavino proposed a nice way to get what you'd like without its dangers. Cheers to both of you.
ultim is offline  
Old 1st November 2013, 13:50   #202  |  Link
raffriff42
Retried Guesser
 
raffriff42's Avatar
 
Join Date: Jun 2012
Posts: 1,373
Quote:
Originally Posted by ultim View Post
Sure, there is always room for feature requests!
How about this syntax change...for better self-documenting function declarations:

(EDIT or would this be out because it breaks compatibility?)
Code:
## function declare examples, current syntax:

function SAA(clip C, int "ss", bool "cp", int "aa")

function FunkyDeblock(clip c, int "quant", int "th", 
\        int "radius", bool "deblock", bool "depump")

function Detwinkle(clip C, float "grainmask", 
\        int "grainmode", int "tstren",  
\        float "hicont", float "hisharp", 
\        float "unblur", float "mosens", 
\        int "hismooth", String "show") 

## add syntax support for DEFAULT VALUE:

## * defaults are optional of course
## * compiler assigns default values automatically if specified
## * string literals only - no variables or Eval statements!
## * strings are not quoted (certain chars can't be supported - unless escaped?)
## * empty String defaults accepted, meaning empty string, as opposed to Undefined.
## * other empty defaults are syntax errors
## * specify explicit undefined defaults with "Undefined", "Nop" or "null"

function SAA(clip C, int "ss=2", bool "cp=true", int "aa=48")

function FunkyDeblock(clip c, int "quant=4", int "th=3", 
\        int "radius=4", bool "deblock=true", bool "depump=true")

function Detwinkle(clip C, float "grainmask=1.3", 
\        int "grainmode=2", int "tstren=25",  
\        float "hicont=1.3", float "hisharp=0", 
\        float "unblur=3", float "mosens=3", 
\        int "hismooth=2", String "show=") 


## add syntax support for DEFAULT VALUE and VALID INPUTS:

## * compiler assigns default values and enforces valid inputs
## * space optional before start of "[...]" range specifier
## * ranges ".." delimited? Dunno.
## * valid alternate values "|" delimited
## * valid ranges: "[min..max]" "[min..]" "[..max]"  or "[alt1|alt2|alt3]"
## * consider enforcing range specifier if default is used

function SAA(clip C, int "ss=2 [1..8]", bool "cp=true", int "aa=48 [4..256]")

function FunkyDeblock(clip c, int "quant=4 [0..51]", int "th=3 [0..128]", 
\        int "radius=4 [1..60]", bool "deblock=true", bool "depump=true")

function Detwinkle[clip C, float "grainmask=1.3 [0.7..18]", 
\      int "grainmode=2 [0..18]", int "tstren=25 [1..255]",  
\      float "hicont=1.3 [0.1..10]", float "hisharp=0 [-1..1]", 
\      float "unblur=3 [0..99]", float "mosens=3 [0.1..5]", 
\      int "hismooth=2 [1..5]", String "show= [blur|mask|luma|cyan|]")

Last edited by raffriff42; 1st November 2013 at 13:57.
raffriff42 is offline  
Old 1st November 2013, 19:27   #203  |  Link
ultim
AVS+ Dev
 
ultim's Avatar
 
Join Date: Aug 2013
Posts: 359
Quote:
Originally Posted by raffriff42 View Post
(EDIT or would this be out because it breaks compatibility?)
That's not a problem. As long as old Avisynth scripts can continue to run on Avs+, it is fine. I personally don't require that Avs+ scripts must also run on Avisynth, because otherwise a lot of improvements wouldn't be possible.

As for the feature at hand, I like the ideas, though I'd rather have some syntax details different. For example, the specification of the default values as per you wouldn't let the complier know the value's type. Only putting quotes around the var's name solves this, or in case a default values is supplied, not putting any quotes at all, because parameters that have a default are optional by definition.
ultim is offline  
Old 1st November 2013, 22:28   #204  |  Link
ultim
AVS+ Dev
 
ultim's Avatar
 
Join Date: Aug 2013
Posts: 359
Finally, some time to write down things on my mind. Well, not all the things, but it's a start

Everybody hates MT-modes, me included. They shouldn't be required, but unfortunately we cannot dispose of them, because there are a lot of old plugins out there that were written without any consideration for multithreading. Not supporting MT modes would mean throwing out a lot of great plugins, keeping only those that perfectly adhere to the points in my previous "Plugin Writing Tips" post. So I've been wondering, what MT-modes should be supported? We know Avisynth-MT supports at least 5, but which of those are really usefull? I have recently recognized that the Avisynth-MT OP post has been updated, and now it only lists modes 1-3 as "usefull". I've set out to compile my own list, while in the process answering questions such as "When exactly do we need those modes?", "What modes are needed if no plugins are fixed?", "What modes are needed if all plugins are fixed (as per my plugin writing tips)?" and also "Which plugins cannot be used with the recommended set of MT-modes (1-3) of Avisynth-MT"?

I started to think analytically, and compiled a set of three tables found here to summarize my findings. I might have overlooked some things or made a mistake or two, so let me know if you find anything. Each table lists four negative plugin properties as their columns, basically violations against multithreading support. The last column contains the protection that Avisynth+ would need to implement to keep that kind of plugin working correctly despite its violations.

Table 1. has all the different combinations of properties, irrespective of if that combination is even realistic at all or not. For example, there can be no plugin such as its 9. row, because a plugin can only possibly require ordered frame retrieval if it stores at least some kind of internal state. There are also cases of inherently broken plugins that cannot be guarded against in Avisynth, because they'd require limiting the plugin simultaneously to both single AND to multiple instances. So, let's see, how many MT-modes do we need? Six MT-modes, ouch. More precisely, six MT-modes if we do want to support all possible kinds of "broken" plugins, without fixing any of them. This is where I've said "no way I'm gonna implement all those MT-modes"! So what can we do? Fix the plugins of course!

One of the easiest plugin fixes is getting rid of storing the environment pointer in classes or globals. Fixing these violations has some nice advantages: First of all, this is a trivial fix in any plugin, so as long as we have the sources, this kind of fixing will go fast and easy. Also, quite importantly, getting rid of this single violation in every plugin will effectively ensure that there is at least a way to use all plugins in multithreaded modes (as long as the required protections are implemented in the core). So, never store the env.ptr. in classes and globals, and we are down to only 7 cases and 4 MT-modes (3 protections). Welcome to table 2. The protections in table 2. are what we'd need to have if we could perform only a trivial fix in the few plugins that need it.

Getting to table 3. from here is actually quite simple, only two simple facts have been used for this transformation. One is to get rid of using global variables. This is also a simple fix, as basically all that needs to be done, is to make class variables out of global variables. This will not effect plugin behavior at all, but it will remove the need to serialize these plugins, which is practically the same as letting them run fully parallel. Believe me, this fix is almost just copy-paste work for many plugins (not for those whose algorithm requires it, but those can be fixed too in every case, except that more work needs to be done). The main obstacle will (again) be having the sources to the offending plugins. OK, so far so good. But to get to table 3., I've also done something else: I've assumed that there are no plugins that must serially access all frames up to frame n, to calculate frame n. Why? Because such a plugin would hardly be usable in Avisynth (as it would make it impossible to seek inside or trim the video), and thus I actually doubt that one like that exists at all. (EDIT: I've been let to know that there are such plugins in existence. But all Avs+ could do to protect them is to play back all frames of the video internally until the requested frame is reached, which is performance-wise not practical at all - think of having to wait for multiple hours just to seek into the middle of the video clip).

So, we're at table 3., and IMHO have don't need any complex plugin fixes. Table 3. summarizes the MT modes that we need to implement if we assume we can fix all plugins until at least none of them uses global vars. Is that realistic? Yes, as long as we have the sources. Surprisingly to me, the conclusion in this table is that we either need no protection at all, or a single protection for unfixed plugins that store state across frames, but that still allows for full performance/parallelization, only with memory overhead (fully fixed plugins never require any protection from Avisynth). A second protection (3rd mode) is added to optimize source filters further, and while tbh I don't think it is strictly needed for correct source filters, it should still help their performance by reducing disk seeks. Another (important but sad) advantage of having this special mode for source filters, is that the same protection also lets us use unfixed plugins that use global or static variables. Note that while this special mode allows you to use such plugins, you should not rely on this mode (except for source filters), because it will cripple your multicore performance and flush it down the toilet, instead it is better to work on the plugin to not require a single serialized instance.

Avisynth+ will likely implement the modes listed in table 3., and I will take time to try and fix/modify as many plugins as possible, as well as motivate others to do so. In contrast to Avisynth-MT though, Avisynth+ will also allow plugins to register themself for the correct MT-mode they need, so users won't have to know by heart for all plugins if they have been fixed, or if they are unfixed, which mode they need.


Congrats for reading this rant of mine. What's to take home ?
- Fix plugins that store and reuse the env. ptr. It is often neglected but very important.
- Fix plugins that use global or static variables. We can guard against them to ensure they will work correctly, but they cannot be executed in parallel, and will seriously limit the multithreaded performance for your whole filterchain (even for correct plugins, due to frame dependencies).
- You can violate multiple rules for multithreading, and not all are equally important. Most importantly, ensure that the env.ptr. is never stored and reused. If you still have energy left after that, fix the plugin further so that no global/static state is used. Then if you still have energy left, try to turn all class members into read-only.
- The three MT-modes listed as "usefull" for Avisynth-MT really are the three most usefull MT-modes.
- The MT-modes of Avisynth-MT are not enough to use every single plugin when MT-mode is enabled. You might get crashes or corrupted frames if you use an unsupported plugin in an MT-mode, but don't blame Avisynth-MT, it is really not his fault. Blame the author of the offending plugin.
- Always fix plugins instead of relying on MT-protections. Most fixes are very easy and you will get much better performance than using a built-in protection.
- If you have the sources to a plugin, please don't keep it to yourself.

Last edited by ultim; 1st November 2013 at 23:15.
ultim is offline  
Old 2nd November 2013, 01:30   #205  |  Link
TurboPascal7
Registered User
 
TurboPascal7's Avatar
 
Join Date: Jan 2010
Posts: 270
Okay, here are my thoughts on the issue. Everything runs on the assumption that most filters will get updated. There are just too many things to add and I want to hope that with the help of VSynth team we will be able to make the most used plugins less bad quite fast.

Common things:
  • In any case the core should include a static thread pool with number of threads configured on script initialization. Additional function like SetThreads(4) should be provided with all calls other than the first one ignored. This is exactly how Avstp works.
  • Nothing should be threaded by default. If the core does not have any information on the filter it will run singlethreaded. Always.
The question is: how does the core get the required info if the filter does not register itself?

1. Single-line SetMtMode
First option is to make the user put this info in his script but unlike the original SetMtMode apply threading only to the filter inside the call. The result script would look like:
Code:
SetThreads(4)
Source(...)
SomeRegisteredFilter()          # registers itself as threaded, runs with 4 threads
SomeBrokenFilter()          # does not register itself, singlethreaded
ForceThreading(SomeFilter(), 2)        # SomeFilter runs in mode 2, forced threading
This assumes that avisynth evaluator would allow making SomeFilter() threaded and you don't have to use like SetMtMode(2).SomeFilter().SetMtMode(0) which is quite ugly.
Compared to original mt-mode solutions, this makes immediately obvious where and which mt-mode is used. Of course it runs on assumption that most filers will get updated, otherwise you'll end up writing ForceThreading call on every line or separating all your stuff into functions just to thread said function in one call.

However, just like the vanilla SetMtMode solution, this has some serious disadvantages.
First of all, it requires users to know implementation details of every plugin and script they're using, in other words - making the user learn a lot of stuff he doesn't care about.
Second, it makes your script less readable by simply adding garbage calls to it.
Third, imagine you're using some dither.avsi function with 50 calls to perfectly threadable masktools and a single call to hopelessly broken removegrain. You'll end up using the slowest mt mode of all (if any) unless you're willing to modify this script. No one will do that.

So I think we should face it: SetMtMode solution is terrible. I'd rather continue running scripts singlethreaded than spending hours and hours understanding what I can and cannot thread just to later end up with a broken encode because I used a wrong mt mode.

2. Embed this information into the core
Do pretty much the same thing VSynth is doing: embed all the required info into the core. Here is how it'd work:
  1. The core has predefined dictionary of mt modes for every plugin known. {"mt_lut": 0, "removegrain": 2} and so on. User has no ways of providing this info. No SetMtMode function exists.
  2. When a threaded plugin is loaded, its registration info overrides the default dictionary values. This is important because we'll never be able to keep the list up to date.
  3. All filters that do not register themselves and don't have an entry in the core dictionary run singlethreaded.
  4. When a filter gets updated, we simply remove its entry from the core. This makes it singlethreaded for users that updated the core but didn't update the filter. Can't be helped.
Yes, this solution is harder for the devs since one would need to gather the info required to embed it in the core. Yes, this solution is not optimal from performance point of view - even if the filter can be easily threaded, unless it registers itself or has an entry in the core dictionary - it won't.
But it does not require the user to know anything about filters he's using. Plus it doesn't add anything to your scripts. Plus you automatically get threading even inside complicated scripts that no one will ever modify. User updates avisynth.dll and it just works. Then when plugins get updated, he replaced the files in his plugins folder and it just works.

I definitely think this is the way to go. MAXIMUM PERFORMANCE is cool and everything, but I really want things to just work without me doing anything. In the end, 20 minutes of my time is much more important for me than those four additional hours my PC will spend on filtering running some more stuff singlethreaded.
__________________
Me on GitHub | AviSynth+ - the (dead) future of AviSynth

Last edited by TurboPascal7; 2nd November 2013 at 03:02.
TurboPascal7 is offline  
Old 2nd November 2013, 14:28   #206  |  Link
ajp_anton
Registered User
 
ajp_anton's Avatar
 
Join Date: Aug 2006
Location: Stockholm/Helsinki
Posts: 805
Bug?
subtitle doesn't accept an argument named "text". The text has to be the first unnamed argument for it to work. I was trying to re-organize the arguments when calling subtitle for easier readability.

Feature request: allow comments on split lines, like this:
filter(argument 1 #comment
\, argument 2)
ajp_anton is offline  
Old 2nd November 2013, 15:30   #207  |  Link
ultim
AVS+ Dev
 
ultim's Avatar
 
Join Date: Aug 2013
Posts: 359
Quote:
Originally Posted by ajp_anton View Post
Bug?
subtitle doesn't accept an argument named "text". The text has to be the first unnamed argument for it to work. I was trying to re-organize the arguments when calling subtitle for easier readability.
No, not a bug. The "text" argument is mandatory, meaning it is not a named argument. Because it is not a named argument, you cannot reorder it and refer to it by name.

Quote:
Originally Posted by ajp_anton View Post
Feature request: allow comments on split lines, like this:
filter(argument 1 #comment
\, argument 2)
Noted. Thx.
ultim is offline  
Old 2nd November 2013, 16:25   #208  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,431
Quote:
Originally Posted by ajp_anton View Post
Feature request: allow comments on split lines, like this:
filter(argument 1 #comment
\, argument 2)
You can use the /* ... */ style of comment to do this (in both Avisynth and Avisynth+)
Code:
filter(argument 1 /* comment */
\, argument 2)
__________________
GScript and GRunT - complex Avisynth scripting made easier
Gavino is offline  
Old 4th November 2013, 19:44   #209  |  Link
LaTo
LaTo INV.
 
LaTo's Avatar
 
Join Date: Jun 2007
Location: France
Posts: 701
Quote:
Originally Posted by ultim View Post
Surprisingly to me, the conclusion in this table is that we either need no protection at all, or a single protection for unfixed plugins that store state across frames, but that still allows for full performance/parallelization, only with memory overhead (fully fixed plugins never require any protection from Avisynth).
If we really need some writable class member, what is a good method?

(I was thinking about a wrapper which dispatch data between threads using a hashmap of thread id)

Last edited by Guest; 4th November 2013 at 19:58. Reason: rule 12: don't ask what's best
LaTo is offline  
Old 4th November 2013, 21:30   #210  |  Link
TurboPascal7
Registered User
 
TurboPascal7's Avatar
 
Join Date: Jan 2010
Posts: 270
Quote:
Originally Posted by LaTo View Post
If we really need some writable class member, what is a good method?

(I was thinking about a wrapper which dispatch data between threads using a hashmap of thread id)
There is also an option of letting the core create a few instances of your filter class. This way you won't have to implement any kind of synchronization or complicate your plugin.

Using a hashmap in this case is quite hard. You will either have to implement a thread-safe hashmap or know all possible filter ids during hashmap creation in filter constructor. First way will complicate your implementation a lot, the other one will bind your plugin to avs+, plus it is somewhat a bad api design.
__________________
Me on GitHub | AviSynth+ - the (dead) future of AviSynth

Last edited by TurboPascal7; 4th November 2013 at 21:47.
TurboPascal7 is offline  
Old 4th November 2013, 23:33   #211  |  Link
ultim
AVS+ Dev
 
ultim's Avatar
 
Join Date: Aug 2013
Posts: 359
Quote:
Originally Posted by LaTo View Post
If we really need some writable class member, what is a good method?

(I was thinking about a wrapper which dispatch data between threads using a hashmap of thread id)
You don't need to do that kind of dispatching on your own.

The "best" (ahm) way depends on how you'll use the class member. If you don't mind missing out some frames here and there, the easiest way for you as a filter author is to not implement any synchronization, and let Avisynth create multiple instances of your filter. This will of course come with some overhead, mostly some memory, but it's the quick'n dirty method, because from your filter's point of view there will always be just one thread.

On the other hand, if you'd want to share your state between all your instances (and you don't want to miss out on any of the frames), then you'll want to implement your own synchronization, and ask for the 1st MT mode where Avisynth does not provide any "workaround"/protection. In this case Avs+ will create just a single instance of your filter (which will be the same one called from every thread), and you'll need to synchronize access to the state yourself. Note though that from your point of view, the frames might (probably) still not be accessed in sequential order.

So to sum up, the first method is useful if you only need to store some temporal state, but you don't mind if your filter's instance will not see some frames. Otherwise, use the second method. Jugding by the fact that you wanted to dispatch data based on the thread ID, you probably want to use the solution involving multiple instances.

(And for future reference, if you really do want to dispatch data yourself, you don't need to use a hashmap. Avs+ will sequentially number the threads for you, so you'll be able to use a simple array lookup. You'll tie your plugin to Avs+ by that though.)
ultim is offline  
Old 5th November 2013, 19:31   #212  |  Link
SEt
Registered User
 
Join Date: Aug 2007
Posts: 374
Don't bother with MT modes if you want future-proof solution. It's a ok hack for doing work right now, but it's not scalable. I have much better idea how efficient threading should be done, but never got to implement it (mostly because I'm not pressed since MT modes do work for now).

That have been said, I'm busy with other areas atm. (And you will likely see something useful for Avisynth in several days. )
SEt is offline  
Old 5th November 2013, 21:33   #213  |  Link
TurboPascal7
Registered User
 
TurboPascal7's Avatar
 
Join Date: Jan 2010
Posts: 270
Quote:
Originally Posted by SEt View Post
I have much better idea how efficient threading should be done
You could tell us about this idea of yours instead of just saying you have it, you know.
__________________
Me on GitHub | AviSynth+ - the (dead) future of AviSynth
TurboPascal7 is offline  
Old 6th November 2013, 00:48   #214  |  Link
TurboPascal7
Registered User
 
TurboPascal7's Avatar
 
Join Date: Jan 2010
Posts: 270
Okay, this projects needs some user input again.

A new issue got created on github but unfortunately we couldn't decide whether it should be implemented or not. This is not a critical issue of any sort but it is quite annoying.

How to reproduce
The minimal example as posted on github is:
Code:
blankclip(1000,720,480, "yv12",color_yuv=$808080)
anotherfilter = blankclip(1000,720,480, "yv12",color_yuv=$FF8080)
StackHorizontal(last, anotherfilter)
It works fine. Now if you remove the last line, making the script
Code:
blankclip(1000,720,480, "yv12",color_yuv=$808080)
anotherfilter = blankclip(1000,720,480, "yv12",color_yuv=$FF8080)
you will get a "Not a clip" error.

Why
Assignment operator returns uninitialized avisynth value, basically nothing. This "nothing" does not override the last variable so you still can request that one simply putting last on the next line.

Proposed solution
Instead of returning nothing, return the last clip value if it exists. Same effect could be achieved right now by adding last to the line after every assignment in your script.

Drawbacks
I don't see how this could break any existing script. It might reduce performance of script initialization a bit since it requires looking up the last variable on every assignment, but you won't notice this. Of course I might be missing something.

Why bother
You write a script and then you decide to try it without a few lines at the end, so you comment them out and BAM - "not a clip". This could be solved by always adding "last" to the last line of your scripts but it's kinda hacky.

What's needed
Your input. Basically, something like "oh I had this problem before, would be nice to get this fixed" or "nah, this will break my scripts because I found a way to rely on this behavior", or even "omg no, this will reduce initialization performance by 0.00000001%, can't have that" would work.
IanB's opinion if we could fix this in the vanilla avisynth would be really appreciated.

Thanks in advance.
__________________
Me on GitHub | AviSynth+ - the (dead) future of AviSynth

Last edited by TurboPascal7; 6th November 2013 at 00:57.
TurboPascal7 is offline  
Old 6th November 2013, 00:53   #215  |  Link
wOxxOm
Oz of the zOo
 
Join Date: May 2005
Posts: 208
Quote:
Originally Posted by TurboPascal7 View Post
It might reduce performance of script initialization
There won't be any perceivable penalty at all in case avisynth+ would implicitly add 'last' only to the end of a scope (function/eval snippet/entire script).
wOxxOm is offline  
Old 6th November 2013, 01:48   #216  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,431
If I understand correctly, the proposal is that a script that ends with an assignment should return 'last', instead of a 'void' value as currently. I assume the same would apply to functions ending with an assignment (and also to Eval() contents).

I don't expect any currently working scripts (or functions) would break as a result.
However, a script that ends with an assignment is probably wrong. Why assign to a variable that will never be used?
Who knows what the user intended in such a case?
Perhaps he meant to return the value being assigned, rather than a 'last' that may have been set many lines earlier.
So I think it is better to keep the existing scheme, which forces the user to make the intention clear.

Quote:
Originally Posted by wOxxOm View Post
There won't be any perceivable penalty at all in case avisynth+ would implicitly add 'last' only to the end of a scope (function/eval snippet/entire script).
However, it must only do this for assignments. With the existing data structures, at the time the end of the scope is being evaluated, you no longer know whether you had an assignment - and when evaluating an assignment, you don't know whether it's the last thing in its scope. So the simplest implementation, if going ahead with this, would be for all assignments to return 'last' as their value.
__________________
GScript and GRunT - complex Avisynth scripting made easier
Gavino is offline  
Old 6th November 2013, 01:58   #217  |  Link
innocenat
Registered User
 
innocenat's Avatar
 
Join Date: Dec 2011
Posts: 77
I think implicitly return last variable on every script is a good idea. Sure, it might not seems resonable at first, but if you need temporary storage in your script you probably aren't beginner and should know what you are doing and what last variable refer to anyway.

As for multithreading, I dont think creating multiple instances of filter is a good idea. I think avs interfacd should provide filter thread local storage and thread-safe global storage. On filter that require linear frame access, filter should be registered as such, but avs interface should provide a way for filter to tell the core that the process that require linear access has done and the core is allowed to request next frame while this frame is still processing.

I know this is not a light work and may break compatibility, but it's how I imagine it right now.
innocenat is offline  
Old 6th November 2013, 02:10   #218  |  Link
TurboPascal7
Registered User
 
TurboPascal7's Avatar
 
Join Date: Jan 2010
Posts: 270
Quote:
Originally Posted by Gavino View Post
However, a script that ends with an assignment is probably wrong. Why assign to a variable that will never be used?
Who knows what the user intended in such a case?
Perhaps he meant to return the value being assigned, rather than a 'last' that may have been set many lines earlier.
So I think it is better to keep the existing scheme, which forces the user to make the intention clear.
This is a job for an analysis tool and not for the core itself, imho. I don't see how assignment on the last line is wrong while having any number of unused variables in other parts of the script is okay.

Quote:
Originally Posted by innocenat View Post
As for multithreading, I dont think creating multiple instances of filter is a good idea. I think avs interfacd should provide filter thread local storage and thread-safe global storage.
There is a "small" problem with this solution - it ties the plugin to avs+. Maybe it would be okay if we were starting from scratch, but with o9k avisynth forks around I think it would be reasonable to avoid coupling the plugins to avs+ interface as much as possible. Not to mention that the core will need to implement the multiple class instances solution anyway just to thread some existing plugins without modifications.
__________________
Me on GitHub | AviSynth+ - the (dead) future of AviSynth

Last edited by TurboPascal7; 6th November 2013 at 02:14.
TurboPascal7 is offline  
Old 6th November 2013, 02:14   #219  |  Link
cwk
Registered User
 
Join Date: Jan 2004
Location: earth, barely
Posts: 96
Can we assume this only attempts to solve the case where the last variable received a valid video clip, just fails to return it?

Consider the case where a script is calling functions that are under construction.

Code:
mySource = avisource("blah")
a = mySource.SomeCompletelyAwesomeFunction()
return a
Here 'not a clip' is useful, because it tells me my function is not returning a valid clip.

Another approach would be to make the existing 'not a clip' message more informative. It could tell the user what the current return value is, or point out the line providing the return.
cwk is offline  
Old 6th November 2013, 02:19   #220  |  Link
TurboPascal7
Registered User
 
TurboPascal7's Avatar
 
Join Date: Jan 2010
Posts: 270
Quote:
Originally Posted by cwk View Post
Can we assume this only attempts to solve the case where the last variable received a valid video clip, just fails to return it?
This proposal would change exactly nothing in your example if this is what you're asking about.
__________________
Me on GitHub | AviSynth+ - the (dead) future of AviSynth
TurboPascal7 is offline  
Closed Thread

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 12:45.


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