Log in

View Full Version : Vapoursynth


Pages : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 [84] 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100

StainlessS
17th January 2021, 18:59
I'm sure that its lovely Feisty, Myrsloik and VideoH are just being, well themselves really :)

feisty2
17th January 2021, 19:34
Imagine having a bug in your filter and having to go to feisty2 for support. :rolleyes:
that is simply not true. the source code is publicly available and extremely easy to understand. anyone reasonably familiar with the C++ language should be able to manipulate the wrapper (adding more functionality, fixing bugs, etc.) however he or she wants with zero difficulty.

videoh
17th January 2021, 19:53
Where is the documentation for the wrapper?

Visual Studio solution files for building the examples?

feisty2
17th January 2021, 20:15
I'm sure it's wonderful and great for noobs.

also not true. the wrapper covers all functions provided by the C API, so anything you can do with the low level API, you can do the same with the C++ wrapper, plus the much cleaner and more concise syntax while also being less error prone. there is no performance cost (as long as you choose not to enable some dynamic features like automatic padding which are meant for fast prototyping), everything is built upon zero cost abstraction. even experienced developers should enjoy some benefits like RAII and expect less memory errors.

someone must be a masochist to prefer

auto std = vsapi->getPluginByNs("std", core);
auto args = vsapi->createMap();
vsapi->propSetNode(args, "clip", node, paAppend);
vsapi->freeNode(node);
auto ret = vsapi->invoke(std, "Transpose", args);
vsapi->freeMap(args);
node = vsapi->propGetNode(ret, "clip", 0, nullptr);
vsapi->freeMap(ret);


over


auto TransposedClip = Core["std"]["Transpose"]("clip", InputClip);

feisty2
17th January 2021, 20:54
Where is the documentation for the wrapper?

Visual Studio solution files for building the examples?

I haven't started working on documentation and I'll get started once all interface design is finalized. I have covered all functions in the C API but the filter backbone is still subject to change.

for now, you can find various examples here: https://github.com/IFeelBloated/vsFilterScript/tree/master/Examples

GaussBlur - simple 3x3 convolutional filter

TemporalMedian - a temporal filter

Rec601ToRGB - an example showing how to write filters that manipulate frame properties, and output a video clip of a different format than its input

Crop - an example showing how to write filters that deal with various bitdepths, and output a video clip with a different image size

ModifyFrame - an example showing how to write filters that interact with Python scripts.

Palette - an example showing how to write filters with multiple outputs

SeparableConvolution - an example showing how to write filters that invoke external filters and itself

GaussBlurFast - an example showing how to write filters without automatic padding.

msvc is not currently supported, because it lacks many core language features of C++20 (mainly concepts). you need at least GCC 10.2 to compile the examples

videoh
17th January 2021, 21:47
It's undocumented and I can't build with it or debug it in my development environment. I'm such a masochist for not using it. :rolleyes:

sl1pkn07
20th January 2021, 00:21
@videoh. is a joke?

> I can't build with it or debug it in my development environment.

maybe is your problem(?)

videoh
20th January 2021, 03:05
Because Visual Studio on Windows has such a tiny usage. I'm the only one that would be stupid enough to have such an environment.

Hey, he called me a masochist for not using his stuff. How about you mind your own business? Or how about you ask him to create some documentation, for God's sake?

The only joke here is the never-DG guys continually twisting themselves into pretzels. Pitiful.

feisty2
20th January 2021, 07:48
it's nobody's problem, msvc is well known to be slow on supporting new C++ features (it's also not the worst tho, apple clang is far worse than msvc in terms of C++20 support (https://en.cppreference.com/w/cpp/compiler_support/20)). things will get there eventually. the main problem with msvc currently is that it does not provide complete support for concepts, a major C++20 feature that the wrapper relies on heavily.

and the masochist thing is not personal, using the low level API not only requires more work to do the same thing, it is also very error prone in certain cases, especially when dealing with reference counted objects. you won't believe how easy and how likely it is to forget calling that "free" function marked in red in the following code block

auto std = vsapi->getPluginByNs("std", core);
auto args = vsapi->createMap();
vsapi->propSetNode(args, "clip", node, paAppend);
vsapi->freeNode(node); // manually releasing resource acquired in a foreign scope, highly error prone.
auto ret = vsapi->invoke(std, "Transpose", args);
vsapi->freeMap(args);
node = vsapi->propGetNode(ret, "clip", 0, nullptr);
vsapi->freeMap(ret);

and bang! there you have a memory leak. and that's what I meant by "masochist", to rely on the not always so consciously stable human willpower to deal with all that when you have the option to let a language facility do it automatically for you.

videoh
20th January 2021, 12:45
when you have the option to let a language facility do it automatically for you I don't have that option, and I can't wait for eventually.

And do yourself a favor and write some documentation. Examples are not enough.

foxyshadis
22nd January 2021, 06:28
it's nobody's problem, msvc is well known to be slow on supporting new C++ features (it's also not the worst tho, apple clang is far worse than msvc in terms of C++20 support (https://en.cppreference.com/w/cpp/compiler_support/20)). things will get there eventually. the main problem with msvc currently is that it does not provide complete support for concepts, a major C++20 feature that the wrapper relies on heavily.

You have to be kidding me, right? This is a bleeding edge GCC 10 feature. You need an Ubuntu line less than six months old to be able to use that, no 20.04 or LTS for you. There's still no RHEL/CentOS that has gcc10. You literally have to reinstall your entire OS to be able to build this, or have a dev environment just for it.

You're intentionally cutting your userbase off in order to experiment with bleeding edge features, which is fine in the abstract, but marks the project as unsuitable for anyone else.

feisty2
22nd January 2021, 11:22
the latest version of all 3 mainstream compilers (GCC, Clang, MSVC) have supported many C++20 features, both GCC and Clang have implemented full support for concepts, and MSVC has partial support for it. I can imagine that MSVC should be able to catch up in the following months and my project should work with all mainstream compilers by the time I finish writing the documentation. CentOS is dead so not supporting it is no big deal, regardless of that, GCC is capable of bootstrapping, just download the source code of the latest version and build it with whatever version you already have, you certainly don't need to reinstall your OS to run the latest version of GCC. what's the point really to use Linux if you can't even compile GCC from scratch...

concepts is a must-have in order to design a flexible interface in C++, it is by far the only facility to express type-level equivariance in C++, take the following polymorphic function f() for example:

auto f(auto&& x) {
if constexpr (requires { { x.g() }->Iterable; })
if constexpr (requires { { *x.g().begin() }->SubtypeOf<VideoInfo>; })
return std::vector<VideoNode>{};
else if constexpr (requires { { *x.g().begin() }->SubtypeOf<AudioInfo>; })
return std::vector<AudioNode>{};
else
static_assert(AlwaysFalse<decltype(x)>, "Type Error!");
else if constexpr (requires { { x.g() }->SubtypeOf<VideoInfo>; })
return VideoNode{};
else if constexpr (requires { { x.g() }->SubtypeOf<AudioInfo>; })
return AudioNode{};
else
static_assert(AlwaysFalse<decltype(x)>, "Type Error!");
}

the "if constexpr (requires { ... })" construct defines an equivariant map from the return type of x.g() to the return type of f(), and therefore extends polymorphism to the type level for f(). As a result, the user defined function x.g() no longer needs to be constrained by an invariant interface. the user is allowed to define g() however he/she likes at the type level, whatever works the best for his/her particular use case, and the framework function f() always self-adapts to whatever the user wants.

you simply cannot write such f() without concepts. you can try mimicking it using SFINAE in older versions of C++ and I guarantee that your code will be an unreadable and unmaintainable mess in no time. therefore concepts is absolutely essential if you agree that the user's freewill matters.

edit: simple proof that shows f() is indeed equivariant at the type level for types that it can handle.
let F() denote f() at the type level, [] denote a type operator that transforms any type T to std::vector<T>.

we have that:
F([VideoInfo]) = [VideoNode]
[F(VideoInfo)] = [VideoNode]
F([AudioInfo]) = [AudioNode]
[F(AudioInfo)] = [AudioNode]

therefore F() satisfies F(G∙T) = G∙F(T), where G = [], T = VideoInfo, AudioInfo.

_Al_
22nd January 2021, 20:09
Not that is important, but tried to subclass videonode, if for example could use custom attributes like clip.rgb, clip.isError etc:
class My_videonode(vs.VideoNode):
def __init__(self, clip, *args, **kwargs):
super(My_videonode, self).__init__(*args,**kwargs)

my_videonode = My_videonode(clip1)
got error, vapoursynth.Error: Class cannot be instantiated directly,
from here:
https://github.com/vapoursynth/vapoursynth/blob/master/src/cython/vapoursynth.pyx#L954

is it possible, or is it stupid idea, it could be done differently sure, or forget it?

feisty2
22nd January 2021, 20:13
use VaporMagik (https://github.com/IFeelBloated/VaporMagik), it allows you to do dangerous things to native extensions, not just VideoNode, you can even modify the behavior of built-in types like list or int

_Al_
22nd January 2021, 21:41
thank you,
I think I saw it before, really advanced script for me, thinking what it would be good for :-) . I tried to butcher it a bit and came up with this, which works. So I might use it. Interesting. I realized also I could also use collections.namedtuple lib, not sure how I would implement it yet. But your VaporMagik seams to be fun:

import ctypes
import builtins

class PyObject(ctypes.Structure):
pass

PyObject._fields_ = [
('ob_refcnt', ctypes.c_ssize_t),
('ob_type', ctypes.POINTER(PyObject)),
]

class NativeMappingProxy(PyObject):
_fields_ = [('UnderlyingDictionary', ctypes.POINTER(PyObject))]

def Dereference(Pointer):
ObjectHolder = []
ctypes.pythonapi.PyList_Append(ctypes.py_object(ObjectHolder), Pointer)
return ObjectHolder[0]

def ExposeAttributeDictionary(Type):
AttributeMaps = Type.__dict__
TransparentAttributeMaps = NativeMappingProxy.from_address(id(AttributeMaps))
return Dereference(TransparentAttributeMaps.UnderlyingDictionary)

def SetTypeAttribute(Type, Name, Attribute):
AttributeDictionary = ExposeAttributeDictionary(Type)
AttributeDictionary[Name] = Attribute
ctypes.pythonapi.PyType_Modified(ctypes.py_object(Type))

@property
def rgb(self):
return self.resize.Bicubic(format=vs.RGB24)

SetTypeAttribute(vs.VideoNode, 'rgb', rgb)


clip = core.avisource.AVISource(file.avi)
print(clip)
print(clip.rgb)

_Al_
22nd January 2021, 22:15
is it possible using VaporMagik to do get things out of tuple to atribute:
@property
def rgb(self):
#action of converting
return rgb_clip, isError, log #returned is vs.VideoNode, bool and string

#something:
SetTypeAttribute(vs.VideoNode, 'rgb', rgb)

clip = core.avisource.AVISource(file.avi)
print(clip)
print(clip.rgb)
print(clip.isError)
print(clip.log)
#or maybe better
print(clip.rgb)
print(clip.rgb.isError)
print(clip.rgb.log)
#or
print(clip.rgb[0], clip.rgb[1], clip.rgb[2])

feisty2
23rd January 2021, 07:20
I don't see why you'd think that you cannot do that, although what you're trying to do doesn't seem elegant to me.

_Al_
23rd January 2021, 09:00
ok, I got that, thanks, but then I could not figure out how to have array/list of clips done by that, that code is too much for me, I settled with something like this at the end:
import vapoursynth as vs
from vapoursynth import core
import collections

class Clips(list):
def __init__(self, inputs):
list.__init__(self,[])

self.Clip_data = collections.namedtuple('Clip_data', ['clip','rgb','isError','log','output_index'])

if isinstance(inputs, type(vs.get_outputs())):
inputs = [ (clip, output_index) for output_index, clip in inputs.items()]

elif isinstance(inputs, list):
inputs = [ (clip, None) for clip in inputs]
else:
raise ValueError('wrong input')
for clip, output_index in inputs:
self.append(self.set(clip, output_index))

def set(self, clip, output_index=None):
rgb, isError, log = self.toRGB(clip)
#other work
return self.Clip_data(clip=clip, rgb=rgb, isError=isError, log=log, output_index=output_index)

def replace(self, index, clip, output_index=None):
self[index] = self.set(clip, output_index)

def appending(self, clip, output_index=None):
self.append(self.set(clip, output_index))

def toRGB(self, c):
#conversion to rgb, mocking a return for show
return core.resize.Bicubic(c, matrix_in_s='170m',format=vs.RGB24), False, 'this is a conversion log'

vs.clear_outputs()
clip = core.std.BlankClip(format=vs.YUV420P8)
clip.set_output(0)

bright = clip.std.Expr(['x 40 +','',''])
bright.set_output(1)

clips = Clips([clip, bright])
##clips = Clips(vs.get_outputs())

print(clips[0].clip)
print(clips[0].rgb)
print(clips[0].log)
print(clips[1].clip)
#...

#replacing clip on index 1
brightest = clip.std.Expr(['x 100 +','',''])
clips.replace(1, brightest)

#apending clip
clip = core.std.BlankClip(color=(255,0,0)).resize.Point(matrix_s='170m',format=vs.YUV420P8)
clips.appending(clip)

feisty2
23rd January 2021, 12:39
but then I could not figure out how to have array/list of clips done by that

obviously, you need to inject your custom attributes into the built-in list type. use the @Inject decorator provided by VaporMagik


@Inject
def f(self: list):
for x in self:
print(x)

[1, 2, 3, 4].f() # prints "1 2 3 4"

_Al_
25th January 2021, 23:20
ok thanks, I used dataclass at the end, same syntax as namedtuple, I understand it, and it can assign and change attributes directly (namedtuple has awkward syntax). Not saying that VaporMagik cannot do that, most likely yes.

feisty2
27th January 2021, 07:12
@Myrsloik
could you explain how getFrame() is invoked with different activation reasons, particularly the case involving arAllFramesReady && !*frameData? it seems getFrame() might be invoked twice with the same activation reason, what happens after getFrame() exits from the arAllFramesReady && !*frameData branch and before it gets invoked again? if several frames (either from the same node or from several nodes) are requested in the arAllFramesReady && !*frameData branch, is it guaranteed that all requested frames are ready before the next call to getFrame()?

there seems to be 4 types of filters with different getFrame() skeletons:

standard filters
arInitial -> RequestReferenceFrames()
arAllFramesReady -> DrawFrame()

source filters
arInitial -> DrawFrame()

special filters (e.g. std.FrameEval)
arInitial -> RequestReferenceFrames()
arAllFramesReady && !*frameData -> RequestSpecialResources()
arAllFramesReady -> DrawFrame()

special(or weird?) source filters
arInitial && !*frameData -> RequestSpecialResources()
arInitial -> DrawFrame()

any other possibilities? also is it possible to get a concrete error message if the arError branch is activated?

Myrsloik
27th January 2021, 11:09
@Myrsloik
could you explain how getFrame() is invoked with different activation reasons, particularly the case involving arAllFramesReady && !*frameData? it seems getFrame() might be invoked twice with the same activation reason, what happens after getFrame() exits from the arAllFramesReady && !*frameData branch and before it gets invoked again? if several frames (either from the same node or from several nodes) are requested in the arAllFramesReady && !*frameData branch, is it guaranteed that all requested frames are ready before the next call to getFrame()?

there seems to be 4 types of filters with different getFrame() skeletons:

standard filters
arInitial -> RequestReferenceFrames()
arAllFramesReady -> DrawFrame()

source filters
arInitial -> DrawFrame()

special filters (e.g. std.FrameEval)
arInitial -> RequestReferenceFrames()
arAllFramesReady && !*frameData -> RequestSpecialResources()
arAllFramesReady -> DrawFrame()

special(or weird?) source filters
arInitial && !*frameData -> RequestSpecialResources()
arInitial -> DrawFrame()

any other possibilities? also is it possible to get a concrete error message if the arError branch is activated?

That's more or less the existing cases. Rule is very simple (ignore arFrameReady since it's effectively deprecated):

At the end of each invocation either an output frame must be returned OR there must be outstanding frame requests (requestFrameFilter).

First call is always arInitial to make things clear.
Once all requested frames are available arAllFramesReady is called.
You're allowed to request additional frames in arAllFramesReady which will then result in getting called with arAllFramesReady again and you can repeat this as many times as you like.
Errors may be propagated from other filters at any time after the arInitial call and then it's not the filter's job to handle it, only to clean up any allocated resources and return nothing. The error message is always propagated to the original requester to display. (As in whoever called getFrame/getFrameAsync)

Your last weird example is obviously invalid since it'll have outstanding frame requests when returning an output frame.

feisty2
27th January 2021, 12:51
Your last weird example is obviously invalid since it'll have outstanding frame requests when returning an output frame.


that's good to know. then apparently the last weird case and the standard case could be unified by generalizing RequestReferenceFrames() to RequestResources()


if (activationReason == arInitial)
if constexpr (requires { { filter->RequestResources() }->AnyBut<void>; })
*frameData = new auto{ filter->RequestResources() };
else if constexpr (requires { filter->RequestResources(); }) // fails to satisfy AnyBut<void>, therefore returns void, equivalent to RequestReferenceFrames()
filter->RequestResources();
else if constexpr (requires { { filter->DrawFrame() }->SubtypeOf<FrameReference>; }) // source filter
return filter->DrawFrame().Leak();
else
static_assert(AlwaysFalse<decltype(filter)>, "missing attribute!");

feisty2
28th January 2021, 07:49
what happens if there's no frame requested or generated in the arInitial branch (empty branch)? it might happen in rare cases like the following

if (activationReason == arInitial)
for (auto& node : inputs) // inputs might be an empty container depending on the user input
node.RequestFrame(n, FrameContext);

will getFrame() still be invoked with arAllFramesReady later on?

Myrsloik
28th January 2021, 09:59
what happens if there's no frame requested or generated in the arInitial branch (empty branch)? it might happen in rare cases like the following

if (activationReason == arInitial)
for (auto& node : inputs) // inputs might be an empty container depending on the user input
node.RequestFrame(n, FrameContext);

will getFrame() still be invoked with arAllFramesReady later on?

That's a fatal error since you either must have outstanding requests or return a frame.

lansing
1st February 2021, 04:39
How does the api getCoreInfo2() function works? It asks for the core and VSCoreInfo as parameters. But the only way to get the VSCoreInfo from the document is by using api->getCoreInfo(), but it also said that this function was deprecated.

feisty2
1st February 2021, 06:15
How does the api getCoreInfo2() function works? It asks for the core and VSCoreInfo as parameters. But the only way to get the VSCoreInfo from the document is by using api->getCoreInfo(), but it also said that this function was deprecated.

https://github.com/IFeelBloated/vsFilterScript/blob/master/include/Core.vxx#L9

lansing
1st February 2021, 06:43
https://github.com/IFeelBloated/vsFilterScript/blob/master/include/Core.vxx#L9

Thanks I got it working. The naming is confusing, this is more like setCoreInfo rather than getCoreInfo

feisty2
1st February 2021, 08:09
it's a common practice in C to return something via side effects (by manipulating global variables or modifying something from a foreign scope via pointers)

lansing
2nd February 2021, 01:46
Can I retrieve the paths for the vs plugin folder and script folder through the api?

feisty2
2nd February 2021, 05:27
plugin path: https://github.com/IFeelBloated/vsFilterScript/blob/master/include/Plugin.vxx#L59
script path: https://github.com/IFeelBloated/VaporMagik/blob/master/VaporMagik.py#L71

Myrsloik
2nd February 2021, 11:52
Can I retrieve the paths for the vs plugin folder and script folder through the api?

The script "folder" isn't a single folder but simply all the normal python import paths. You can see vsrepo.py to see how it's determined by default I guess.

The "vs plugin folder" is also harder to determine. Basically you have 3 locations:
1. The core plugins
2. The global plugins
3. User plugins

The location of 2 is written to the registry and 3 is always in the same appdata location. Why do you even need to find out where things are?

lansing
2nd February 2021, 12:09
The script "folder" isn't a single folder but simply all the normal python import paths. You can see vsrepo.py to see how it's determined by default I guess.

The "vs plugin folder" is also harder to determine. Basically you have 3 locations:
1. The core plugins
2. The global plugins
3. User plugins

The location of 2 is written to the registry and 3 is always in the same appdata location. Why do you even need to find out where things are?
I want to create links in vseditor to open them in one click. Right now I’m relying on vsrepogui, but when vsrepogui didn’t work, it’ll be a pain to look for them manually.

ChaosKing
2nd February 2021, 12:28
For plugins http://www.vapoursynth.com/doc/plugins.html#windows
vsrepogui just uses the paths provided by vsrepo.

But registry can be tricky if the user has installed 32bit vapoursynth or it is a "per user installation".

I need to check 4 locations in vsrepogui to cover all cases.

var regl32 = new VsRegistry().GetRegistry(localKey32, @"SOFTWARE\VapourSynth-32");
var regl64 = new VsRegistry().GetRegistry(localKey64, @"SOFTWARE\VapourSynth");

var regu32 = new VsRegistry().GetRegistry(userKey32, @"SOFTWARE\VapourSynth-32");
var regu64 = new VsRegistry().GetRegistry(userKey64, @"SOFTWARE\VapourSynth");

localKey* => RegistryHive.LocalMachine
userKey* => RegistryHive.CurrentUser


EDIT
vsrepo code for scripts

https://github.com/vapoursynth/vsrepo/blob/efda91e3a4a57a400d403ee878e3489540886880/vsrepo.py#L186
import site
site_package_dir = site.getusersitepackages()

Which returns C:\Users\USER\AppData\Roaming\Python\Python38\site-packages

lansing
2nd February 2021, 13:21
User plugin should be all I need. I think I’ll just call vsrepo to open them.

Jukus
3rd February 2021, 19:57
How should such a video be indexed?
Format : AVI
Format/Info : Audio Video Interleave
Commercial name : DV
Format profile : OpenDML
Overall bit rate mode : Constant
Overall bit rate : 30 Mb/s

Video
ID : 0
Format : DV
Codec ID : dvsd
Codec ID/Hint : Sony
Bit rate mode : Constant
Width : 720 pixels
Height : 480 pixels
Display aspect ratio : 16:9
Frame rate mode : Constant
Frame rate : 29.970 (30000/1001) FPS
Original frame rate : 29.970 (29970/1000) FPS
Standard : NTSC
Color space : YUV
Chroma subsampling : 4:1:1
Bit depth : 8 bits
Scan type : Interlaced
Scan order : Bottom Field First
Compression mode : Lossy

stax76
3rd February 2021, 20:04
You can open that with ffms2 or L-Smash-Source.

LigH
3rd February 2021, 21:39
Disadvantage: Because it is a "keyframe only" video format, the index will be huge and indexing will take a lot of time.

poisondeathray
3rd February 2021, 21:47
If you're on windows, you can open it up with core.avisource.AVISource without indexing. Disadvantage - requires system installed DV codec and none that I know of return the original NTSC 4:1:1 .

feisty2
4th February 2021, 13:40
does anyone actually need half precision (fp16) facilities and does any plugin actually provide support for it? I don't really wanna have it in my project and I have very good reasons:

1) there's no native support for fp16 in standard C/C++ and most CPUs provide very little or no support for it, meaning you will have to create your homegrown software-emulated fp16 type. it's not portable and it's very likely that it will be way slower than fp32 which comes with native hardware support.

2) unlike fp32 and fp64 which are universally well defined (literally every implementation out there adopts the representation defined by IEEE 754), the representation of fp16 varies on different platforms. there's the IEEE fp16, and BFloat16 (Google TPU), and who knows what else! applying arithmetic operations defined for one fp16 representation on another fp16 representation leads to garbage result. The user (or maybe even the developer) usually has absolutely no clue which fp16 representation is being used and all sorts of weird shit can happen. It might be better to avoid all this by simply not supporting fp16.

Myrsloik
4th February 2021, 13:44
does anyone actually need half precision (fp16) facilities and does any plugin actually provide support for it? I don't really wanna have it in my project and I have very good reasons:

1) there's no native support for fp16 in standard C/C++ and most CPUs provide very little or no support for it, meaning you will have to create your homegrown software-emulated fp16 type. it's not portable and it's very likely that it will be way slower than fp32 which comes with native hardware support.

2) unlike fp32 and fp64 which are universally well defined (literally every implementation out there adopts the representation defined by IEEE 754), the representation of fp16 varies on different platforms. there's the IEEE fp16, and BFloat16 (Google TPU), and who knows what else! applying arithmetic operations defined for one fp16 representation on another fp16 representation leads to garbage result. The user (or maybe even the developer) usually has absolutely no clue which fp16 representation is being used and all sorts of weird shit can happen. It might be better to avoid all this by simply not supporting fp16.

1. That's not how you do it. You use the unpack/pack instructions for fp16 for load and store and then feed that to the normal fp32 path. It's the only way to make it perform well.

2. Obviously it's whatever the cpu native fp16 format is, just like with other floats. So IEEE all the way on x86 (and just about all sane cpus).

Support is mostly pointless.

Jukus
4th February 2021, 17:46
Disadvantage: Because it is a "keyframe only" video format, the index will be huge and indexing will take a lot of time.
The file weighs over 30 gb
Duration over 02:30:00
The size of the ffms index is 50+ kb

lansing
5th February 2021, 11:16
What function do I use to retrieve warning message from the api? If I run a script with clip = core.get_core() in PyCharm it'll give me a nice deprecated warning, but in vseditor I couldn't find a function that can do that. the getError() only return on fatal error like frame failed to load.

feisty2
5th February 2021, 11:26
https://github.com/vapoursynth/vapoursynth/blob/doodle1/src/cython/vapoursynth.pyx#L2337
it has nothing to do with VS per se. you just have to find a way to utilize python's warnings module in your application.

LigH
5th February 2021, 23:12
@Jukus: OK, maybe it's worse with uncompressed audio. My memories may be not completely correct in this case.

lansing
6th February 2021, 01:36
https://github.com/vapoursynth/vapoursynth/blob/doodle1/src/cython/vapoursynth.pyx#L2337
it has nothing to do with VS per se. you just have to find a way to utilize python's warnings module in your application.

I don't really know what to do. Maybe like embedding Python into my vseditor project and then have it evaluate the script so I can catch the warning?

feisty2
6th February 2021, 08:20
you can use vaporsynth's FFI facilities to execute arbitrary python code in your C++ programs. you need to:
1) define a python function that does what you want, in this case, the function should collect all warning messages from warnings and return them as a list of strings.
2) pass the function to a special filter and execute it, in this case, you can instantly execute the acquired function in your filter's constructor, then call Core.Alert() to send all warning messages to console.

lansing
6th February 2021, 17:18
you can use vaporsynth's FFI facilities to execute arbitrary python code in your C++ programs. you need to:
1) define a python function that does what you want, in this case, the function should collect all warning messages from warnings and return them as a list of strings.
2) pass the function to a special filter and execute it, in this case, you can instantly execute the acquired function in your filter's constructor, then call Core.Alert() to send all warning messages to console.

What is vaporsynth's FFI facilities?

feisty2
6th February 2021, 17:40
What is vaporsynth's FFI facilities?

https://github.com/IFeelBloated/vsFilterScript/blob/master/include/Function.vxx

and use it to run python code thru a special filter

struct PythonEval {
static constexpr auto Name = "PythonEval";
static constexpr auto Signature = "code:func;";

PythonEval(auto Arguments, auto Core) {
for (auto PythonCode = static_cast<Function>(Arguments["code"]); auto&& WarningMessage : PythonCode())
Core.Alert(static_cast<std::string>(WarningMessage));
}
};

lansing
7th February 2021, 07:51
This is what I found to catch the warnings:


import warnings

with warnings.catch_warnings(record=True) as warning_list:
core = vs.get_core()
clip = core.dgdecodenv.DGSource(r'hello.dgi')
clip.set_output()

for warning in warning_list:
print(warning.message)


But I need to wrap the whole script inside this warnings.catch_warnings in order to catch them.