AviSynth / AviSynthPlus

AviSynth with improvements
http://avs-plus.net
930 stars 74 forks source link

[Feature request] Apply frame properties by dictionary ruleset file #393

Open qyot27 opened 2 months ago

qyot27 commented 2 months ago

Something of a companion issue to #391.

A function name like propSetRules / propSetDict / propTrace / propDict or something similar.

Obviously, not all plugins support frame properties, and there are many old plugins that still work with new versions of AviSynth+ but won't ever support frameprops because they were closed source and/or development on them stopped years ago (for the FOSS ones with zero devs left, with the added point that no-one else is otherwise motivated enough to fork it just to patch it up for frameprops).

The proposed function would allow users to load a file with custom rulesets for plugins (or functions generally) to respect or change frameprops appropriately. Loading the file and the inheritance would be similar to SetMemoryMax, in that it would be intended to only be used once at the top of the script, and the entire set of rules gets added and handled by the core so that if it knows the script is using one of the functions tagged in the rules file, the core itself handles the frameprop change. Maybe provide a function to set rules for a single plugin/function in the script itself (like SetFilterMTMode), but that would get unwieldy if the plugin/function can do multiple types of changes (and due to the nature of how the functions actually work, it's not like there would be disagreement over what changes should be made given what the function is supposed to be doing to the content).

The idea of the core using the dict file to apply the changes when detected in the script is where the proposed propTrace name came from, in addition to being distinct from the existing propSet/Get functions, because the function itself would be pretty distinct from what the rest of the prop setting functions do, even though it would be invoking those functions under the hood.

The actual syntax of such a ruleset file is something that would need careful consideration, of course. Things that adjust multiple properties in different ways would need some way of declaring all those cases, although since it would presumably be tied to the parameters passed to the function itself, it could essentially be dumb logic that ties to the parameters, but not only that; for example, ConvertToYCgCo exists, and with things like Dolby Vision support in FFmpeg, there are patches to add new entries into the Transfer/Matrix/Primaries for those formats, which - if the AviSynth demuxer in libavformat can be extended to pass through the DoVi-related frameprops, would need to add those into its switch cases as well (it might very well gain those entries before any support for the DoVi frameprops materializes, but still...).

pinterf commented 2 months ago

Do you mean, like SetFilterMTMode which sets/overrides the MT mode filter property, this propSetRules (or whatever name) would


- Able to add specific frame properties and their values based on a ruleset.
  e.g. `_ColorRange = 0`

?
qyot27 commented 2 months ago

On the inheritance part, yes, that's exactly what I'm thinking it would do.

The ruleset for say, Convert (obviously not long-term, but for the sake of argument), would need to be able to account for the fact that it can do multiple types of changes with different combinations of parameters. So the ruleset would be set up basically with switch cases so that if the parser checks the function used in the script, sees matrix="Rec709" in the Convert call, it would - based on the ruleset - then automatically propSet("_Matrix","709") afterward. Same with any other things like Transfer, Primaries, Chroma Placement, etc.

The part where it needs to be able to know how to cope with all the different values a parameter might set is why I said that a filter that could do it in-script would get unwieldy, and why it's more suited to something like a ruleset file where all of the values and what the core should do in that scenario can be expressed once. A ruleset file with what amounts to switch cases is simply more human-readable than like MTModes.avsi using SetFilterMTMode on each line for each iteration of each parameter in the target functions:

filtername: [optional keys, like 'passthrough']
    parameter(param name) = propname
        value = [array of possible aliases for a value], value to pass to propSet
deen: passthrough

Convert:
    parameter(matrix) = _Matrix
        value = ["rgb", "0", "AVS_MATRIX_RGB"], AVS_MATRIX_RGB
        value = ["709", "1", "AVS_MATRIX_BT709"], AVS_MATRIX_BT709
    parameter(primaries) = _Primaries (yes, I know Convert lacks a 'primaries' option; it's just an example)
        value = [...]
    [some way of defining special cases where multiple parameters interact in some way
     distinct from using them by themselves, might be necessary for other kinds of plugins/functions]

TFM:
[...]

is easier to read for an end-user to create new rulesets for other plugins than something like:

propSetDict(function="Convert",parameter="matrix",value="709",set="_Matrix:AVS_MATRIX_BT709")
propSetDict(function="Convert",parameter="matrix",value="2020ncl",set="_Matrix:9")

and so on, repeated for each various combination it can do.

Example 2 mainly just has the value of being absolutely explicit about what you're doing, but it's probably limited in some way that isn't immediately obvious to me at the moment. Given that something like that could be thrown into an .avsi first, the difference would mainly be in whether there's an appreciable resource cost calling potentially dozens/hundreds/thousands of individual propSetDict() calls in an .avsi vs. loading all the rules at once into the parser through a ruleset like example 1.